1#![deny(clippy::all)]
2#![allow(clippy::needless_update)]
3#![allow(non_local_definitions)]
4
5pub use std::fmt::Result;
6use std::{borrow::Cow, str, str::from_utf8};
7
8use serde::{Deserialize, Serialize};
9use swc_atoms::atom;
10use swc_common::{BytePos, Span, Spanned, DUMMY_SP};
11use swc_css_ast::*;
12use swc_css_codegen_macros::emitter;
13use swc_css_utils::serialize_ident;
14use writer::CssWriter;
15
16pub use self::emit::*;
17use self::{ctx::Ctx, list::ListFormat};
18
19#[macro_use]
20mod macros;
21mod ctx;
22mod emit;
23mod list;
24pub mod writer;
25
26#[derive(Debug, Default, Clone, Copy, Serialize, Deserialize)]
27#[serde(rename_all = "camelCase")]
28pub struct CodegenConfig {
29 #[serde(default)]
30 pub minify: bool,
31}
32
33#[derive(Debug)]
34pub struct CodeGenerator<W>
35where
36 W: CssWriter,
37{
38 wr: W,
39 config: CodegenConfig,
40 ctx: Ctx,
41}
42
43impl<W> CodeGenerator<W>
44where
45 W: CssWriter,
46{
47 pub fn new(wr: W, config: CodegenConfig) -> Self {
48 CodeGenerator {
49 wr,
50 config,
51 ctx: Default::default(),
52 }
53 }
54
55 #[emitter]
56 fn emit_stylesheet(&mut self, n: &Stylesheet) -> Result {
57 self.emit_list(
58 &n.rules,
59 if self.config.minify {
60 ListFormat::NotDelimited
61 } else {
62 ListFormat::NotDelimited | ListFormat::MultiLine
63 },
64 )?;
65 }
66
67 #[emitter]
68 fn emit_rule(&mut self, n: &Rule) -> Result {
69 match n {
70 Rule::QualifiedRule(n) => emit!(self, n),
71 Rule::AtRule(n) => emit!(self, n),
72 Rule::ListOfComponentValues(n) => {
73 emit!(
74 &mut *self.with_ctx(Ctx {
75 in_list_of_component_values: true,
76 ..self.ctx
77 }),
78 n
79 )
80 }
81 }
82 }
83
84 #[emitter]
85 fn emit_qualified_rule(&mut self, n: &QualifiedRule) -> Result {
86 emit!(self, n.prelude);
87 emit!(self, n.block);
88 }
89
90 #[emitter]
91 fn emit_qualified_rule_prelude(&mut self, n: &QualifiedRulePrelude) -> Result {
92 match n {
93 QualifiedRulePrelude::SelectorList(n) => {
94 emit!(self, n);
95 formatting_space!(self);
96 }
97 QualifiedRulePrelude::RelativeSelectorList(n) => {
98 emit!(self, n);
99 formatting_space!(self);
100 }
101 QualifiedRulePrelude::ListOfComponentValues(n) => {
102 emit!(
103 &mut *self.with_ctx(Ctx {
104 in_list_of_component_values: true,
105 ..self.ctx
106 }),
107 n
108 )
109 }
110 }
111 }
112
113 #[emitter]
114 fn emit_at_rule(&mut self, n: &AtRule) -> Result {
115 write_raw!(self, lo_span_offset!(n.span, 1), "@");
116 emit!(
117 &mut *self.with_ctx(Ctx {
118 allow_to_lowercase: true,
119 ..self.ctx
120 }),
121 n.name
122 );
123
124 if let Some(prelude) = &n.prelude {
125 emit!(
126 &mut *self.with_ctx(Ctx {
127 in_single_line_selectors: true,
128 ..self.ctx
129 }),
130 prelude
131 );
132 }
133
134 if n.block.is_some() {
135 match n.prelude.as_deref() {
136 Some(AtRulePrelude::ListOfComponentValues(_)) | None => {}
137 _ => {
138 formatting_space!(self);
139 }
140 }
141
142 emit!(self, n.block)
143 } else {
144 semi!(self);
145 }
146 }
147
148 #[emitter]
149 fn emit_at_rule_name(&mut self, n: &AtRuleName) -> Result {
150 match n {
151 AtRuleName::Ident(n) => emit!(self, n),
152 AtRuleName::DashedIdent(n) => emit!(self, n),
153 }
154 }
155
156 #[emitter]
157 fn emit_at_rule_prelude(&mut self, n: &AtRulePrelude) -> Result {
158 match n {
159 AtRulePrelude::CharsetPrelude(n) => {
160 space!(self);
161 emit!(self, n);
162 }
163 AtRulePrelude::PropertyPrelude(n) => {
164 space!(self);
165 emit!(self, n);
166 }
167 AtRulePrelude::CounterStylePrelude(n) => {
168 space!(self);
169 emit!(self, n);
170 }
171 AtRulePrelude::ColorProfilePrelude(n) => {
172 space!(self);
173 emit!(self, n);
174 }
175 AtRulePrelude::DocumentPrelude(n) => {
176 space!(self);
177 emit!(self, n);
178 }
179 AtRulePrelude::FontPaletteValuesPrelude(n) => {
180 space!(self);
181 emit!(self, n);
182 }
183 AtRulePrelude::FontFeatureValuesPrelude(n) => {
184 let need_space = !matches!(n.font_family.first(), Some(FamilyName::Str(_)));
185
186 if need_space {
187 space!(self);
188 } else {
189 formatting_space!(self);
190 }
191
192 emit!(self, n);
193 }
194 AtRulePrelude::NestPrelude(n) => {
195 space!(self);
196 emit!(self, n);
197 }
198 AtRulePrelude::KeyframesPrelude(n) => {
199 match n {
200 KeyframesName::Str(_) => {
201 formatting_space!(self);
202 }
203 KeyframesName::CustomIdent(_)
204 | KeyframesName::PseudoPrefix(_)
205 | KeyframesName::PseudoFunction(_) => {
206 space!(self);
207 }
208 }
209
210 emit!(self, n);
211 }
212 AtRulePrelude::ImportPrelude(n) => {
213 match &*n.href {
214 ImportHref::Url(_) => {
215 space!(self);
216 }
217 ImportHref::Str(_) => {
218 formatting_space!(self);
219 }
220 }
221
222 emit!(self, n);
223 }
224 AtRulePrelude::NamespacePrelude(n) => emit!(self, n),
225 AtRulePrelude::MediaPrelude(n) => {
226 let need_space = match n.queries.first() {
227 Some(media_query)
228 if media_query.modifier.is_none() && media_query.media_type.is_none() =>
229 {
230 match media_query.condition.as_deref() {
231 Some(MediaConditionType::All(media_condition)) => !matches!(
232 media_condition.conditions.first(),
233 Some(MediaConditionAllType::MediaInParens(
234 MediaInParens::MediaCondition(_)
235 )) | Some(MediaConditionAllType::MediaInParens(
236 MediaInParens::Feature(_)
237 )) | Some(MediaConditionAllType::MediaInParens(
238 MediaInParens::GeneralEnclosed(GeneralEnclosed::SimpleBlock(_))
239 ))
240 ),
241 _ => true,
242 }
243 }
244 _ => true,
245 };
246
247 if need_space {
248 space!(self);
249 } else {
250 formatting_space!(self);
251 }
252
253 emit!(self, n);
254 }
255 AtRulePrelude::SupportsPrelude(n) => {
256 let need_space = !matches!(
257 n.conditions.first(),
258 Some(SupportsConditionType::SupportsInParens(
259 SupportsInParens::SupportsCondition(_)
260 )) | Some(SupportsConditionType::SupportsInParens(
261 SupportsInParens::Feature(SupportsFeature::Declaration(_))
262 )) | Some(SupportsConditionType::SupportsInParens(
263 SupportsInParens::GeneralEnclosed(GeneralEnclosed::SimpleBlock(_)),
264 ))
265 );
266
267 if need_space {
268 space!(self);
269 } else {
270 formatting_space!(self);
271 }
272
273 emit!(self, n);
274 }
275 AtRulePrelude::PagePrelude(n) => {
276 match n.selectors.first() {
277 Some(page_selector) if page_selector.page_type.is_none() => {
278 formatting_space!(self);
279 }
280 _ => {
281 space!(self);
282 }
283 }
284
285 emit!(self, n);
286 }
287 AtRulePrelude::LayerPrelude(n) => {
288 space!(self);
289 emit!(self, n);
290 }
291 AtRulePrelude::ContainerPrelude(n) => {
292 let need_space = match n.name {
293 Some(_) => true,
294 _ => !matches!(
295 n.query.queries.first(),
296 Some(ContainerQueryType::QueryInParens(
297 QueryInParens::ContainerQuery(_,)
298 )) | Some(ContainerQueryType::QueryInParens(
299 QueryInParens::SizeFeature(_)
300 )) | Some(ContainerQueryType::QueryInParens(
301 QueryInParens::GeneralEnclosed(GeneralEnclosed::SimpleBlock(_)),
302 ))
303 ),
304 };
305
306 if need_space {
307 space!(self);
308 } else {
309 formatting_space!(self);
310 }
311
312 emit!(self, n);
313 }
314 AtRulePrelude::CustomMediaPrelude(n) => {
315 space!(self);
316 emit!(self, n);
317 }
318 AtRulePrelude::ListOfComponentValues(n) => {
319 emit!(
320 &mut *self.with_ctx(Ctx {
321 in_list_of_component_values: true,
322 ..self.ctx
323 }),
324 n
325 )
326 }
327 AtRulePrelude::ScopePrelude(n) => {
328 emit!(self, n);
329 }
330 }
331 }
332
333 #[emitter]
334 fn emit_list_of_component_values(&mut self, n: &ListOfComponentValues) -> Result {
335 self.emit_list_of_component_values_inner(
336 &n.children,
337 ListFormat::SpaceDelimited | ListFormat::SingleLine,
338 )?;
339 }
340
341 #[emitter]
342 fn emit_import_prelude(&mut self, n: &ImportPrelude) -> Result {
343 emit!(self, n.href);
344
345 if n.layer_name.is_some() || n.import_conditions.is_some() {
346 formatting_space!(self);
347 }
348
349 if let Some(layer_name) = &n.layer_name {
350 emit!(self, layer_name);
351
352 if n.import_conditions.is_some() {
353 if let ImportLayerName::Ident(_) = &**layer_name {
354 space!(self);
355 } else {
356 formatting_space!(self);
357 }
358 }
359 }
360
361 emit!(self, n.import_conditions);
362 }
363
364 #[emitter]
365 fn emit_import_prelude_href(&mut self, n: &ImportHref) -> Result {
366 match n {
367 ImportHref::Url(n) => emit!(self, n),
368 ImportHref::Str(n) => emit!(self, n),
369 }
370 }
371
372 #[emitter]
373 fn emit_import_layer_name(&mut self, n: &ImportLayerName) -> Result {
374 match n {
375 ImportLayerName::Ident(n) => emit!(self, n),
376 ImportLayerName::Function(n) if n.value.is_empty() => {
377 emit!(
379 self,
380 AtRuleName::Ident(swc_css_ast::Ident {
381 span: n.span,
382 value: atom!("layer"),
383 raw: None
384 })
385 )
386 }
387 ImportLayerName::Function(n) => {
388 emit!(self, n)
389 }
390 }
391 }
392
393 #[emitter]
394 fn emit_import_conditions(&mut self, n: &ImportConditions) -> Result {
395 if let Some(supports) = &n.supports {
396 emit!(self, supports);
397
398 if n.media.is_some() {
399 formatting_space!(self);
400 }
401 }
402
403 if let Some(media) = &n.media {
404 emit!(self, media);
405 }
406 }
407
408 #[emitter]
409 fn emit_keyframes_name(&mut self, n: &KeyframesName) -> Result {
410 match n {
411 KeyframesName::CustomIdent(n) => emit!(self, n),
412 KeyframesName::Str(n) => emit!(self, n),
413 KeyframesName::PseudoFunction(n) => emit!(self, n),
414 KeyframesName::PseudoPrefix(n) => emit!(self, n),
415 }
416 }
417
418 #[emitter]
419 fn emit_keyframes_pseudo_function(&mut self, n: &KeyframesPseudoFunction) -> Result {
420 write_raw!(self, ":");
421 emit!(self, n.pseudo);
422 write_raw!(self, "(");
423 emit!(self, n.name);
424 write_raw!(self, ")");
425 }
426
427 #[emitter]
428 fn emit_keyframes_pseudo_prefix(&mut self, n: &KeyframesPseudoPrefix) -> Result {
429 write_raw!(self, ":");
430 emit!(self, n.pseudo);
431 space!(self);
432 emit!(self, n.name);
433 }
434
435 #[emitter]
436 fn emit_keyframe_block(&mut self, n: &KeyframeBlock) -> Result {
437 self.emit_list(&n.prelude, ListFormat::CommaDelimited)?;
438
439 formatting_space!(self);
440
441 emit!(self, n.block);
442 }
443
444 #[emitter]
445 fn emit_keyframe_selector(&mut self, n: &KeyframeSelector) -> Result {
446 match n {
447 KeyframeSelector::Ident(n) => emit!(
448 &mut *self.with_ctx(Ctx {
449 allow_to_lowercase: true,
450 ..self.ctx
451 }),
452 n
453 ),
454 KeyframeSelector::Percentage(n) => emit!(self, n),
455 }
456 }
457
458 #[emitter]
459 fn emit_font_feature_values_prelude(&mut self, n: &FontFeatureValuesPrelude) -> Result {
460 self.emit_list(&n.font_family, ListFormat::CommaDelimited)?;
461 }
462
463 #[emitter]
464 fn emit_layer_name(&mut self, n: &LayerName) -> Result {
465 self.emit_list(&n.name, ListFormat::DotDelimited)?;
466 }
467
468 #[emitter]
469 fn emit_layer_name_list(&mut self, n: &LayerNameList) -> Result {
470 self.emit_list(&n.name_list, ListFormat::CommaDelimited)?;
471 }
472
473 #[emitter]
474 fn emit_layer_prelude(&mut self, n: &LayerPrelude) -> Result {
475 match n {
476 LayerPrelude::Name(n) => emit!(self, n),
477 LayerPrelude::NameList(n) => emit!(self, n),
478 }
479 }
480
481 #[emitter]
482 fn emit_media_query_list(&mut self, n: &MediaQueryList) -> Result {
483 self.emit_list(&n.queries, ListFormat::CommaDelimited)?;
484 }
485
486 #[emitter]
487 fn emit_media_query(&mut self, n: &MediaQuery) -> Result {
488 if n.modifier.is_some() {
489 emit!(
490 &mut *self.with_ctx(Ctx {
491 allow_to_lowercase: true,
492 ..self.ctx
493 }),
494 n.modifier
495 );
496 space!(self);
497 }
498
499 if n.media_type.is_some() {
500 emit!(
501 &mut *self.with_ctx(Ctx {
502 allow_to_lowercase: true,
503 ..self.ctx
504 }),
505 n.media_type
506 );
507
508 if n.condition.is_some() {
509 space!(self);
510 write_raw!(self, "and");
511 space!(self);
512 }
513 }
514
515 if n.condition.is_some() {
516 emit!(self, n.condition);
517 }
518 }
519
520 #[emitter]
521 fn emit_media_type(&mut self, n: &MediaType) -> Result {
522 match n {
523 MediaType::Ident(n) => emit!(self, n),
524 }
525 }
526
527 #[emitter]
528 fn emit_media_condition_type(&mut self, n: &MediaConditionType) -> Result {
529 match n {
530 MediaConditionType::All(n) => emit!(self, n),
531 MediaConditionType::WithoutOr(n) => emit!(self, n),
532 }
533 }
534
535 #[emitter]
536 fn emit_media_condition(&mut self, n: &MediaCondition) -> Result {
537 self.emit_list(
538 &n.conditions,
539 if self.config.minify {
540 ListFormat::NotDelimited
541 } else {
542 ListFormat::SpaceDelimited
543 },
544 )?;
545 }
546
547 #[emitter]
548 fn emit_media_condition_without_or(&mut self, n: &MediaConditionWithoutOr) -> Result {
549 self.emit_list(
550 &n.conditions,
551 if self.config.minify {
552 ListFormat::NotDelimited
553 } else {
554 ListFormat::SpaceDelimited
555 },
556 )?;
557 }
558
559 #[emitter]
560 fn emit_media_condition_all_type(&mut self, n: &MediaConditionAllType) -> Result {
561 match n {
562 MediaConditionAllType::Not(n) => emit!(self, n),
563 MediaConditionAllType::And(n) => emit!(self, n),
564 MediaConditionAllType::Or(n) => emit!(self, n),
565 MediaConditionAllType::MediaInParens(n) => emit!(self, n),
566 }
567 }
568
569 #[emitter]
570 fn emit_media_condition_without_or_type(&mut self, n: &MediaConditionWithoutOrType) -> Result {
571 match n {
572 MediaConditionWithoutOrType::Not(n) => emit!(self, n),
573 MediaConditionWithoutOrType::And(n) => emit!(self, n),
574 MediaConditionWithoutOrType::MediaInParens(n) => emit!(self, n),
575 }
576 }
577
578 #[emitter]
579 fn emit_media_not(&mut self, n: &MediaNot) -> Result {
580 write_raw!(self, "not");
581 space!(self);
582 emit!(self, n.condition);
583 }
584
585 #[emitter]
586 fn emit_media_and(&mut self, n: &MediaAnd) -> Result {
587 write_raw!(self, "and");
588 space!(self);
589 emit!(self, n.condition);
590 }
591
592 #[emitter]
593 fn emit_media_or(&mut self, n: &MediaOr) -> Result {
594 write_raw!(self, "or");
595 space!(self);
596 emit!(self, n.condition);
597 }
598
599 #[emitter]
600 fn emit_media_in_parens(&mut self, n: &MediaInParens) -> Result {
601 match n {
602 MediaInParens::MediaCondition(n) => {
603 write_raw!(self, lo_span_offset!(n.span, 1), "(");
604 emit!(self, n);
605 write_raw!(self, hi_span_offset!(n.span, 1), ")");
606 }
607 MediaInParens::Feature(n) => emit!(self, n),
608 MediaInParens::GeneralEnclosed(n) => emit!(self, n),
609 }
610 }
611
612 #[emitter]
613 fn emit_media_feature(&mut self, n: &MediaFeature) -> Result {
614 let span = match n {
615 MediaFeature::Plain(n) => n.span,
616 MediaFeature::Boolean(n) => n.span,
617 MediaFeature::Range(n) => n.span,
618 MediaFeature::RangeInterval(n) => n.span,
619 };
620
621 write_raw!(self, lo_span_offset!(span, 1), "(");
622
623 match n {
624 MediaFeature::Plain(n) => emit!(self, n),
625 MediaFeature::Boolean(n) => emit!(self, n),
626 MediaFeature::Range(n) => emit!(self, n),
627 MediaFeature::RangeInterval(n) => emit!(self, n),
628 }
629
630 write_raw!(self, hi_span_offset!(span, 1), ")");
631 }
632
633 #[emitter]
634 fn emit_media_feature_name(&mut self, n: &MediaFeatureName) -> Result {
635 match n {
636 MediaFeatureName::Ident(n) => emit!(self, n),
637 MediaFeatureName::ExtensionName(n) => emit!(self, n),
638 }
639 }
640
641 #[emitter]
642 fn emit_media_feature_value(&mut self, n: &MediaFeatureValue) -> Result {
643 match n {
644 MediaFeatureValue::Number(n) => emit!(self, n),
645 MediaFeatureValue::Dimension(n) => emit!(self, n),
646 MediaFeatureValue::Ident(n) => emit!(self, n),
647 MediaFeatureValue::Ratio(n) => emit!(self, n),
648 MediaFeatureValue::Function(n) => emit!(self, n),
649 }
650 }
651
652 #[emitter]
653 fn emit_media_feature_plain(&mut self, n: &MediaFeaturePlain) -> Result {
654 emit!(self, n.name);
655 write_raw!(self, ":");
656 formatting_space!(self);
657 emit!(self, n.value);
658 }
659
660 #[emitter]
661 fn emit_media_feature_boolean(&mut self, n: &MediaFeatureBoolean) -> Result {
662 emit!(self, n.name);
663 }
664
665 #[emitter]
666 fn emit_media_feature_range(&mut self, n: &MediaFeatureRange) -> Result {
667 emit!(self, n.left);
668 formatting_space!(self);
669 write_raw!(self, n.span, n.comparison.as_str());
670 formatting_space!(self);
671 emit!(self, n.right);
672 }
673
674 #[emitter]
675 fn emit_media_feature_range_interval(&mut self, n: &MediaFeatureRangeInterval) -> Result {
676 emit!(self, n.left);
677 formatting_space!(self);
678 write_raw!(self, n.span, n.left_comparison.as_str());
679 formatting_space!(self);
680 emit!(self, n.name);
681 formatting_space!(self);
682 write_raw!(self, n.span, n.right_comparison.as_str());
683 formatting_space!(self);
684 emit!(self, n.right);
685 }
686
687 #[emitter]
688 fn emit_supports_condition(&mut self, n: &SupportsCondition) -> Result {
689 self.emit_list(
690 &n.conditions,
691 if self.config.minify {
692 ListFormat::NotDelimited
693 } else {
694 ListFormat::SpaceDelimited
695 },
696 )?;
697 }
698
699 #[emitter]
700 fn emit_supports_condition_type(&mut self, n: &SupportsConditionType) -> Result {
701 match n {
702 SupportsConditionType::Not(n) => emit!(self, n),
703 SupportsConditionType::And(n) => emit!(self, n),
704 SupportsConditionType::Or(n) => emit!(self, n),
705 SupportsConditionType::SupportsInParens(n) => emit!(self, n),
706 }
707 }
708
709 #[emitter]
710 fn emit_supports_not(&mut self, n: &SupportsNot) -> Result {
711 write_raw!(self, "not");
712 space!(self);
713 emit!(self, n.condition);
714 }
715
716 #[emitter]
717 fn emit_supports_and(&mut self, n: &SupportsAnd) -> Result {
718 write_raw!(self, "and");
719 space!(self);
720 emit!(self, n.condition);
721 }
722
723 #[emitter]
724 fn emit_support_or(&mut self, n: &SupportsOr) -> Result {
725 write_raw!(self, "or");
726 space!(self);
727 emit!(self, n.condition);
728 }
729
730 #[emitter]
731 fn emit_supports_in_parens(&mut self, n: &SupportsInParens) -> Result {
732 match n {
733 SupportsInParens::SupportsCondition(n) => {
734 write_raw!(self, lo_span_offset!(n.span, 1), "(");
735 emit!(self, n);
736 write_raw!(self, hi_span_offset!(n.span, 1), ")");
737 }
738 SupportsInParens::Feature(n) => emit!(self, n),
739 SupportsInParens::GeneralEnclosed(n) => emit!(self, n),
740 }
741 }
742
743 #[emitter]
744 fn emit_supports_feature(&mut self, n: &SupportsFeature) -> Result {
745 match n {
746 SupportsFeature::Declaration(n) => {
747 write_raw!(self, lo_span_offset!(n.span, 1), "(");
748 emit!(self, n);
749 write_raw!(self, hi_span_offset!(n.span, 1), ")");
750 }
751 SupportsFeature::Function(n) => emit!(self, n),
752 }
753 }
754
755 #[emitter]
756 fn emit_general_enclosed(&mut self, n: &GeneralEnclosed) -> Result {
757 match n {
758 GeneralEnclosed::Function(n) => emit!(self, n),
759 GeneralEnclosed::SimpleBlock(n) => emit!(self, n),
760 }
761 }
762
763 #[emitter]
764 fn emit_page_selector_list(&mut self, n: &PageSelectorList) -> Result {
765 self.emit_list(&n.selectors, ListFormat::CommaDelimited)?;
766 }
767
768 #[emitter]
769 fn emit_page_selector(&mut self, n: &PageSelector) -> Result {
770 if let Some(page_type) = &n.page_type {
771 emit!(self, page_type);
772 }
773
774 if let Some(pseudos) = &n.pseudos {
775 self.emit_list(pseudos, ListFormat::NotDelimited)?;
776 }
777 }
778
779 #[emitter]
780 fn emit_page_selector_type(&mut self, n: &PageSelectorType) -> Result {
781 emit!(self, n.value);
782 }
783
784 #[emitter]
785 fn emit_page_selector_pseudo(&mut self, n: &PageSelectorPseudo) -> Result {
786 write_raw!(self, ":");
787 emit!(
788 &mut *self.with_ctx(Ctx {
789 allow_to_lowercase: true,
790 ..self.ctx
791 }),
792 n.value
793 );
794 }
795
796 #[emitter]
797 fn emit_namespace_prelude(&mut self, n: &NamespacePrelude) -> Result {
798 let has_prefix = n.prefix.is_some();
799 let is_uri_url = match &*n.uri {
800 NamespacePreludeUri::Url(_) => true,
801 NamespacePreludeUri::Str(_) => false,
802 };
803
804 if has_prefix || is_uri_url {
805 space!(self);
806 } else {
807 formatting_space!(self);
808 }
809
810 if has_prefix {
811 emit!(self, n.prefix);
812
813 if is_uri_url {
814 space!(self);
815 } else {
816 formatting_space!(self);
817 }
818 }
819
820 emit!(self, n.uri);
821 }
822
823 #[emitter]
824 fn emit_namespace_prelude_uri(&mut self, n: &NamespacePreludeUri) -> Result {
825 match n {
826 NamespacePreludeUri::Url(n) => emit!(self, n),
827 NamespacePreludeUri::Str(n) => emit!(self, n),
828 }
829 }
830
831 #[emitter]
832 fn emit_document_prelude(&mut self, n: &DocumentPrelude) -> Result {
833 self.emit_list(&n.matching_functions, ListFormat::CommaDelimited)?;
834 }
835
836 #[emitter]
837 fn emit_document_prelude_matching_function(
838 &mut self,
839 n: &DocumentPreludeMatchingFunction,
840 ) -> Result {
841 match n {
842 DocumentPreludeMatchingFunction::Url(n) => emit!(self, n),
843 DocumentPreludeMatchingFunction::Function(n) => emit!(self, n),
844 }
845 }
846
847 #[emitter]
848 fn emit_container_condition(&mut self, n: &ContainerCondition) -> Result {
849 if let Some(name) = &n.name {
850 emit!(self, name);
851 space!(self);
852 }
853
854 emit!(self, n.query);
855 }
856
857 #[emitter]
858 fn emit_container_name(&mut self, n: &ContainerName) -> Result {
859 match n {
860 ContainerName::CustomIdent(n) => emit!(self, n),
861 }
862 }
863
864 #[emitter]
865 fn emit_container_query(&mut self, n: &ContainerQuery) -> Result {
866 self.emit_list(
867 &n.queries,
868 if self.config.minify {
869 ListFormat::NotDelimited
870 } else {
871 ListFormat::SpaceDelimited
872 },
873 )?;
874 }
875
876 #[emitter]
877 fn emit_container_query_type(&mut self, n: &ContainerQueryType) -> Result {
878 match n {
879 ContainerQueryType::Not(n) => emit!(self, n),
880 ContainerQueryType::And(n) => emit!(self, n),
881 ContainerQueryType::Or(n) => emit!(self, n),
882 ContainerQueryType::QueryInParens(n) => emit!(self, n),
883 }
884 }
885
886 #[emitter]
887 fn emit_container_query_not(&mut self, n: &ContainerQueryNot) -> Result {
888 write_raw!(self, "not");
889 space!(self);
890 emit!(self, n.query);
891 }
892
893 #[emitter]
894 fn emit_container_query_and(&mut self, n: &ContainerQueryAnd) -> Result {
895 write_raw!(self, "and");
896 space!(self);
897 emit!(self, n.query);
898 }
899
900 #[emitter]
901 fn emit_container_query_or(&mut self, n: &ContainerQueryOr) -> Result {
902 write_raw!(self, "or");
903 space!(self);
904 emit!(self, n.query);
905 }
906
907 #[emitter]
908 fn emit_query_in_parens(&mut self, n: &QueryInParens) -> Result {
909 match n {
910 QueryInParens::ContainerQuery(n) => {
911 write_raw!(self, lo_span_offset!(n.span, 1), "(");
912 emit!(self, n);
913 write_raw!(self, hi_span_offset!(n.span, 1), ")");
914 }
915 QueryInParens::SizeFeature(n) => emit!(self, n),
916 QueryInParens::GeneralEnclosed(n) => emit!(self, n),
917 }
918 }
919
920 #[emitter]
921 fn emit_size_feature(&mut self, n: &SizeFeature) -> Result {
922 let span = match n {
923 SizeFeature::Plain(n) => n.span,
924 SizeFeature::Boolean(n) => n.span,
925 SizeFeature::Range(n) => n.span,
926 SizeFeature::RangeInterval(n) => n.span,
927 };
928
929 write_raw!(self, lo_span_offset!(span, 1), "(");
930
931 match n {
932 SizeFeature::Plain(n) => emit!(self, n),
933 SizeFeature::Boolean(n) => emit!(self, n),
934 SizeFeature::Range(n) => emit!(self, n),
935 SizeFeature::RangeInterval(n) => emit!(self, n),
936 }
937
938 write_raw!(self, hi_span_offset!(span, 1), ")");
939 }
940
941 #[emitter]
942 fn emit_size_feature_name(&mut self, n: &SizeFeatureName) -> Result {
943 match n {
944 SizeFeatureName::Ident(n) => emit!(self, n),
945 }
946 }
947
948 #[emitter]
949 fn emit_size_feature_value(&mut self, n: &SizeFeatureValue) -> Result {
950 match n {
951 SizeFeatureValue::Number(n) => emit!(self, n),
952 SizeFeatureValue::Dimension(n) => emit!(self, n),
953 SizeFeatureValue::Ident(n) => emit!(self, n),
954 SizeFeatureValue::Ratio(n) => emit!(self, n),
955 SizeFeatureValue::Function(n) => emit!(self, n),
956 }
957 }
958
959 #[emitter]
960 fn emit_size_feature_plain(&mut self, n: &SizeFeaturePlain) -> Result {
961 emit!(
962 &mut *self.with_ctx(Ctx {
963 allow_to_lowercase: true,
964 ..self.ctx
965 }),
966 n.name
967 );
968 write_raw!(self, ":");
969 formatting_space!(self);
970 emit!(self, n.value);
971 }
972
973 #[emitter]
974 fn emit_size_feature_boolean(&mut self, n: &SizeFeatureBoolean) -> Result {
975 emit!(
976 &mut *self.with_ctx(Ctx {
977 allow_to_lowercase: true,
978 ..self.ctx
979 }),
980 n.name
981 );
982 }
983
984 #[emitter]
985 fn emit_size_feature_range(&mut self, n: &SizeFeatureRange) -> Result {
986 emit!(self, n.left);
987 formatting_space!(self);
988 write_raw!(self, n.span, n.comparison.as_str());
989 formatting_space!(self);
990 emit!(self, n.right);
991 }
992
993 #[emitter]
994 fn emit_size_feature_range_interval(&mut self, n: &SizeFeatureRangeInterval) -> Result {
995 emit!(self, n.left);
996 formatting_space!(self);
997 write_raw!(self, n.span, n.left_comparison.as_str());
998 formatting_space!(self);
999 emit!(
1000 &mut *self.with_ctx(Ctx {
1001 allow_to_lowercase: true,
1002 ..self.ctx
1003 }),
1004 n.name
1005 );
1006 formatting_space!(self);
1007 write_raw!(self, n.span, n.right_comparison.as_str());
1008 formatting_space!(self);
1009 emit!(self, n.right);
1010 }
1011
1012 #[emitter]
1013 fn emit_custom_media_query(&mut self, n: &CustomMediaQuery) -> Result {
1014 emit!(self, n.name);
1015 space!(self);
1016 emit!(self, n.media);
1017 }
1018
1019 #[emitter]
1020 fn emit_custom_media_query_media_type(&mut self, n: &CustomMediaQueryMediaType) -> Result {
1021 match n {
1022 CustomMediaQueryMediaType::MediaQueryList(n) => emit!(self, n),
1023 CustomMediaQueryMediaType::Ident(n) => emit!(self, n),
1024 }
1025 }
1026
1027 fn emit_list_of_component_values_inner(
1028 &mut self,
1029 nodes: &[ComponentValue],
1030 format: ListFormat,
1031 ) -> Result {
1032 let iter = nodes.iter();
1033 let len = nodes.len();
1034
1035 for (idx, node) in iter.enumerate() {
1036 emit!(self, node);
1037
1038 if self.ctx.in_list_of_component_values {
1039 continue;
1040 }
1041
1042 let is_current_preserved_token = matches!(node, ComponentValue::PreservedToken(_));
1043 let next = nodes.get(idx + 1);
1044 let is_next_preserved_token = matches!(next, Some(ComponentValue::PreservedToken(_)));
1045
1046 if idx != len - 1 && !is_current_preserved_token && !is_next_preserved_token {
1047 let need_delim = match node {
1048 ComponentValue::SimpleBlock(_)
1049 | ComponentValue::Function(_)
1050 | ComponentValue::Delimiter(_)
1051 | ComponentValue::Str(_)
1052 | ComponentValue::Url(_)
1053 | ComponentValue::Percentage(_)
1054 | ComponentValue::LengthPercentage(_)
1055 | ComponentValue::FrequencyPercentage(_)
1056 | ComponentValue::AnglePercentage(_)
1057 | ComponentValue::TimePercentage(_) => match next {
1058 Some(ComponentValue::Delimiter(delimiter))
1059 if matches!(
1060 **delimiter,
1061 Delimiter {
1062 value: DelimiterValue::Comma,
1063 ..
1064 }
1065 ) =>
1066 {
1067 false
1068 }
1069 _ => !self.config.minify,
1070 },
1071 ComponentValue::Color(color)
1072 if matches!(
1073 **color,
1074 Color::AbsoluteColorBase(AbsoluteColorBase::Function(_))
1075 | Color::Function(_)
1076 ) =>
1077 {
1078 match next {
1079 Some(ComponentValue::Delimiter(delimiter))
1080 if matches!(
1081 **delimiter,
1082 Delimiter {
1083 value: DelimiterValue::Comma,
1084 ..
1085 }
1086 ) =>
1087 {
1088 false
1089 }
1090 _ => !self.config.minify,
1091 }
1092 }
1093 ComponentValue::Ident(_) | ComponentValue::DashedIdent(_) => match next {
1094 Some(ComponentValue::SimpleBlock(simple_block)) => {
1095 if simple_block.name.token == Token::LParen {
1096 true
1097 } else {
1098 !self.config.minify
1099 }
1100 }
1101 Some(ComponentValue::Color(color))
1102 if matches!(
1103 **color,
1104 Color::AbsoluteColorBase(AbsoluteColorBase::HexColor(_),)
1105 ) =>
1106 {
1107 !self.config.minify
1108 }
1109 Some(ComponentValue::Str(_)) => !self.config.minify,
1110 Some(ComponentValue::Delimiter(_)) => false,
1111 Some(ComponentValue::Number(n)) if self.config.minify => {
1112 let minified = minify_numeric(n.value);
1113
1114 !minified.starts_with('.')
1115 }
1116 Some(ComponentValue::Number(_)) => true,
1117 Some(ComponentValue::Dimension(dimension)) if self.config.minify => {
1118 let value = match &**dimension {
1119 Dimension::Length(i) => i.value.value,
1120 Dimension::Angle(i) => i.value.value,
1121 Dimension::Time(i) => i.value.value,
1122 Dimension::Frequency(i) => i.value.value,
1123 Dimension::Resolution(i) => i.value.value,
1124 Dimension::Flex(i) => i.value.value,
1125 Dimension::UnknownDimension(i) => i.value.value,
1126 };
1127
1128 let minified = minify_numeric(value);
1129
1130 !minified.starts_with('.')
1131 }
1132 Some(ComponentValue::Dimension(_)) => true,
1133 Some(component_value) if self.config.minify => {
1134 if let Some(minified) = match component_value {
1135 ComponentValue::LengthPercentage(p) => {
1136 p.as_length().map(|l| l.value.value)
1137 }
1138 ComponentValue::FrequencyPercentage(p) => {
1139 p.as_frequency().map(|f| f.value.value)
1140 }
1141 ComponentValue::AnglePercentage(p) => {
1142 p.as_angle().map(|a| a.value.value)
1143 }
1144 ComponentValue::TimePercentage(p) => {
1145 p.as_time().map(|t| t.value.value)
1146 }
1147 _ => None,
1148 }
1149 .map(minify_numeric)
1150 {
1151 !minified.starts_with('.')
1152 } else {
1153 true
1154 }
1155 }
1156 _ => true,
1157 },
1158 _ => match next {
1159 Some(ComponentValue::SimpleBlock(_)) => !self.config.minify,
1160 Some(ComponentValue::Color(color))
1161 if matches!(
1162 &**color,
1163 Color::AbsoluteColorBase(AbsoluteColorBase::HexColor(_))
1164 ) =>
1165 {
1166 !self.config.minify
1167 }
1168 Some(ComponentValue::Delimiter(_)) => false,
1169 _ => true,
1170 },
1171 };
1172
1173 if need_delim {
1174 self.write_delim(format)?;
1175 }
1176 }
1177 }
1178
1179 Ok(())
1180 }
1181
1182 #[emitter]
1183 fn emit_function(&mut self, n: &Function) -> Result {
1184 emit!(
1185 &mut *self.with_ctx(Ctx {
1186 allow_to_lowercase: true,
1187 ..self.ctx
1188 }),
1189 n.name
1190 );
1191 write_raw!(self, "(");
1192 self.emit_list_of_component_values_inner(
1193 &n.value,
1194 ListFormat::SpaceDelimited | ListFormat::SingleLine,
1195 )?;
1196 write_raw!(self, ")");
1197 }
1198
1199 #[emitter]
1200 fn emit_function_name(&mut self, n: &FunctionName) -> Result {
1201 match n {
1202 FunctionName::Ident(n) => emit!(self, n),
1203 FunctionName::DashedIdent(n) => emit!(self, n),
1204 }
1205 }
1206
1207 #[emitter]
1208 fn emit_color_profile_name(&mut self, n: &ColorProfileName) -> Result {
1209 match n {
1210 ColorProfileName::Ident(n) => emit!(self, n),
1211 ColorProfileName::DashedIdent(n) => emit!(self, n),
1212 }
1213 }
1214
1215 #[emitter]
1216 fn emit_str(&mut self, n: &Str) -> Result {
1217 if self.config.minify {
1218 let minified = minify_string(&n.value);
1219
1220 write_str!(self, n.span, &minified);
1221 } else if let Some(raw) = &n.raw {
1222 write_str!(self, n.span, raw);
1223 } else {
1224 let value = serialize_string(&n.value);
1225
1226 write_str!(self, n.span, &value);
1227 }
1228 }
1229
1230 #[emitter]
1231 fn emit_simple_block(&mut self, n: &SimpleBlock) -> Result {
1232 let (starting, ending) = match n.name.token {
1233 Token::LBracket => ("[", "]"),
1234 Token::LParen => ("(", ")"),
1235 Token::LBrace => ("{", "}"),
1236 _ => {
1237 unreachable!();
1238 }
1239 };
1240
1241 write_raw!(self, lo_span_offset!(n.span, 1), starting);
1242
1243 let len = n.value.len();
1244
1245 for (idx, node) in n.value.iter().enumerate() {
1246 match node {
1247 ComponentValue::ListOfComponentValues(_) | ComponentValue::Declaration(_) => {
1248 if idx == 0 {
1249 formatting_newline!(self);
1250 }
1251
1252 increase_indent!(self);
1253 }
1254 ComponentValue::AtRule(_)
1255 | ComponentValue::QualifiedRule(_)
1256 | ComponentValue::KeyframeBlock(_) => {
1257 formatting_newline!(self);
1258 increase_indent!(self);
1259 }
1260
1261 _ => {}
1262 }
1263
1264 match node {
1265 ComponentValue::ListOfComponentValues(node) => {
1266 emit!(
1267 &mut *self.with_ctx(Ctx {
1268 in_list_of_component_values: true,
1269 ..self.ctx
1270 }),
1271 node
1272 );
1273 }
1274 _ => {
1275 emit!(self, node);
1276 }
1277 }
1278
1279 match node {
1280 ComponentValue::AtRule(_) | ComponentValue::QualifiedRule(_) => {
1281 formatting_newline!(self);
1282 decrease_indent!(self);
1283 }
1284 ComponentValue::Declaration(_) => {
1285 if idx != len - 1 {
1286 semi!(self);
1287 } else {
1288 formatting_semi!(self);
1289 }
1290
1291 formatting_newline!(self);
1292 decrease_indent!(self);
1293 }
1294 ComponentValue::ListOfComponentValues(_) => {
1295 decrease_indent!(self);
1296 }
1297
1298 ComponentValue::KeyframeBlock(_) => {
1299 if idx == len - 1 {
1300 formatting_newline!(self);
1301 }
1302
1303 decrease_indent!(self);
1304 }
1305
1306 _ => {
1307 if !self.ctx.in_list_of_component_values && ending == "]" && idx != len - 1 {
1308 space!(self);
1309 }
1310 }
1311 }
1312 }
1313
1314 write_raw!(self, hi_span_offset!(n.span, 1), ending);
1315 }
1316
1317 #[emitter]
1318 fn emit_component_value(&mut self, n: &ComponentValue) -> Result {
1319 match n {
1320 ComponentValue::PreservedToken(n) => emit!(self, n),
1321 ComponentValue::Function(n) => emit!(self, n),
1322 ComponentValue::SimpleBlock(n) => emit!(self, n),
1323
1324 ComponentValue::ListOfComponentValues(n) => emit!(self, n),
1325 ComponentValue::QualifiedRule(n) => emit!(self, n),
1326 ComponentValue::AtRule(n) => emit!(self, n),
1327 ComponentValue::KeyframeBlock(n) => emit!(self, n),
1328
1329 ComponentValue::Ident(n) => emit!(self, n),
1330 ComponentValue::DashedIdent(n) => emit!(self, n),
1331 ComponentValue::Str(n) => emit!(self, n),
1332 ComponentValue::Url(n) => emit!(self, n),
1333 ComponentValue::Integer(n) => emit!(self, n),
1334 ComponentValue::Number(n) => emit!(self, n),
1335 ComponentValue::Percentage(n) => emit!(self, n),
1336 ComponentValue::Dimension(n) => emit!(self, n),
1337 ComponentValue::LengthPercentage(n) => emit!(self, n),
1338 ComponentValue::FrequencyPercentage(n) => emit!(self, n),
1339 ComponentValue::AnglePercentage(n) => emit!(self, n),
1340 ComponentValue::TimePercentage(n) => emit!(self, n),
1341 ComponentValue::Ratio(n) => emit!(self, n),
1342 ComponentValue::UnicodeRange(n) => emit!(self, n),
1343 ComponentValue::Color(n) => emit!(self, n),
1344 ComponentValue::AlphaValue(n) => emit!(self, n),
1345 ComponentValue::Hue(n) => emit!(self, n),
1346 ComponentValue::CmykComponent(n) => emit!(self, n),
1347 ComponentValue::Delimiter(n) => emit!(self, n),
1348
1349 ComponentValue::CalcSum(n) => emit!(self, n),
1350 ComponentValue::ComplexSelector(n) => emit!(self, n),
1351 ComponentValue::LayerName(n) => emit!(self, n),
1352 ComponentValue::Declaration(n) => emit!(self, n),
1353 ComponentValue::SupportsCondition(n) => emit!(self, n),
1354 ComponentValue::IdSelector(n) => emit!(self, n),
1355 }
1356 }
1357
1358 #[emitter]
1359 fn emit_style_block(&mut self, n: &StyleBlock) -> Result {
1360 match n {
1361 StyleBlock::ListOfComponentValues(n) => {
1362 emit!(
1363 &mut *self.with_ctx(Ctx {
1364 in_list_of_component_values: true,
1365 ..self.ctx
1366 }),
1367 n
1368 )
1369 }
1370 StyleBlock::AtRule(n) => emit!(self, n),
1371 StyleBlock::Declaration(n) => emit!(self, n),
1372 StyleBlock::QualifiedRule(n) => emit!(self, n),
1373 }
1374 }
1375
1376 #[emitter]
1377 fn emit_declaration_block_item(&mut self, n: &DeclarationOrAtRule) -> Result {
1378 match n {
1379 DeclarationOrAtRule::Declaration(n) => emit!(self, n),
1380 DeclarationOrAtRule::AtRule(n) => emit!(self, n),
1381 DeclarationOrAtRule::ListOfComponentValues(n) => {
1382 emit!(
1383 &mut *self.with_ctx(Ctx {
1384 in_list_of_component_values: true,
1385 ..self.ctx
1386 }),
1387 n
1388 )
1389 }
1390 }
1391 }
1392
1393 #[emitter]
1394 fn emit_declaration(&mut self, n: &Declaration) -> Result {
1395 emit!(
1396 &mut *self.with_ctx(Ctx {
1397 allow_to_lowercase: true,
1398 ..self.ctx
1399 }),
1400 n.name
1401 );
1402 write_raw!(self, ":");
1403
1404 let is_custom_property = match n.name {
1405 DeclarationName::DashedIdent(_) => true,
1406 DeclarationName::Ident(_) => false,
1407 };
1408
1409 if is_custom_property {
1413 match n.value.first() {
1414 None => {
1415 space!(self);
1416 }
1417 _ => {
1418 formatting_space!(self);
1419 }
1420 };
1421 } else {
1422 formatting_space!(self);
1423 }
1424
1425 if is_custom_property {
1426 self.with_ctx(Ctx {
1427 in_list_of_component_values: true,
1428 ..self.ctx
1429 })
1430 .emit_list(&n.value, ListFormat::NotDelimited)?;
1431 } else {
1432 self.emit_list_of_component_values_inner(
1433 &n.value,
1434 ListFormat::SpaceDelimited | ListFormat::SingleLine,
1435 )?;
1436 }
1437
1438 if n.important.is_some() {
1439 if !is_custom_property {
1440 formatting_space!(self);
1441 }
1442
1443 emit!(self, n.important);
1444 }
1445 }
1446
1447 #[emitter]
1448 fn emit_declaration_name(&mut self, n: &DeclarationName) -> Result {
1449 match n {
1450 DeclarationName::Ident(n) => emit!(self, n),
1451 DeclarationName::DashedIdent(n) => emit!(self, n),
1452 }
1453 }
1454
1455 #[emitter]
1456 fn emit_important_flag(&mut self, n: &ImportantFlag) -> Result {
1457 write_raw!(self, lo_span_offset!(n.span, 1), "!");
1458
1459 if self.config.minify {
1460 emit!(
1461 &mut *self.with_ctx(Ctx {
1462 allow_to_lowercase: true,
1463 ..self.ctx
1464 }),
1465 n.value
1466 );
1467 } else {
1468 emit!(self, n.value);
1469 }
1470 }
1471
1472 #[emitter]
1473 fn emit_ident(&mut self, n: &Ident) -> Result {
1474 let value = if self.ctx.allow_to_lowercase && self.config.minify {
1475 Cow::Owned(n.value.to_ascii_lowercase())
1476 } else {
1477 Cow::Borrowed(&n.value)
1478 };
1479
1480 let serialized = serialize_ident(&value, self.config.minify);
1481
1482 if self.ctx.is_dimension_unit {
1486 write_raw!(self, n.span, &serialize_dimension_unit(&serialized));
1487 } else {
1488 write_raw!(self, n.span, &serialized);
1489 }
1490 }
1491
1492 #[emitter]
1493 fn emit_custom_ident(&mut self, n: &CustomIdent) -> Result {
1494 let serialized = serialize_ident(&n.value, self.config.minify);
1495
1496 write_raw!(self, n.span, &serialized);
1497 }
1498
1499 #[emitter]
1500 fn emit_dashed_ident(&mut self, n: &DashedIdent) -> Result {
1501 write_raw!(self, lo_span_offset!(n.span, 2), "--");
1502
1503 let serialized = serialize_ident(&n.value, self.config.minify);
1504
1505 write_raw!(self, n.span, &serialized);
1506 }
1507
1508 #[emitter]
1509 fn emit_extension_name(&mut self, n: &ExtensionName) -> Result {
1510 let serialized = serialize_ident(&n.value, self.config.minify);
1511
1512 write_raw!(self, n.span, &serialized);
1513 }
1514
1515 #[emitter]
1516 fn emit_custom_highlight_name(&mut self, n: &CustomHighlightName) -> Result {
1517 let serialized = serialize_ident(&n.value, self.config.minify);
1518
1519 write_raw!(self, n.span, &serialized);
1520 }
1521
1522 #[emitter]
1523 fn emit_custom_property_name(&mut self, n: &CustomPropertyName) -> Result {
1524 write_raw!(self, n.span, &n.value);
1525 }
1526
1527 #[emitter]
1528 fn emit_percentage(&mut self, n: &Percentage) -> Result {
1529 emit!(self, n.value);
1530 write_raw!(self, hi_span_offset!(n.span, 1), "%");
1531 }
1532
1533 #[emitter]
1534 fn emit_length_percentage(&mut self, n: &LengthPercentage) -> Result {
1535 match n {
1536 LengthPercentage::Length(n) => emit!(self, n),
1537 LengthPercentage::Percentage(n) => emit!(self, n),
1538 }
1539 }
1540
1541 #[emitter]
1542 fn emit_frequency_percentage(&mut self, n: &FrequencyPercentage) -> Result {
1543 match n {
1544 FrequencyPercentage::Frequency(n) => emit!(self, n),
1545 FrequencyPercentage::Percentage(n) => emit!(self, n),
1546 }
1547 }
1548
1549 #[emitter]
1550 fn emit_angle_percentage(&mut self, n: &AnglePercentage) -> Result {
1551 match n {
1552 AnglePercentage::Angle(n) => emit!(self, n),
1553 AnglePercentage::Percentage(n) => emit!(self, n),
1554 }
1555 }
1556
1557 #[emitter]
1558 fn emit_time_percentage(&mut self, n: &TimePercentage) -> Result {
1559 match n {
1560 TimePercentage::Time(n) => emit!(self, n),
1561 TimePercentage::Percentage(n) => emit!(self, n),
1562 }
1563 }
1564
1565 #[emitter]
1566 fn emit_dimension(&mut self, n: &Dimension) -> Result {
1567 match n {
1568 Dimension::Length(n) => emit!(self, n),
1569 Dimension::Angle(n) => emit!(self, n),
1570 Dimension::Time(n) => emit!(self, n),
1571 Dimension::Frequency(n) => emit!(self, n),
1572 Dimension::Resolution(n) => emit!(self, n),
1573 Dimension::Flex(n) => emit!(self, n),
1574 Dimension::UnknownDimension(n) => emit!(self, n),
1575 }
1576 }
1577
1578 #[emitter]
1579 fn emit_length(&mut self, n: &Length) -> Result {
1580 emit!(self, n.value);
1581 emit!(
1582 &mut *self.with_ctx(Ctx {
1583 is_dimension_unit: true,
1584 allow_to_lowercase: true,
1585 ..self.ctx
1586 }),
1587 n.unit
1588 );
1589 }
1590
1591 #[emitter]
1592 fn emit_angle(&mut self, n: &Angle) -> Result {
1593 emit!(self, n.value);
1594 emit!(
1595 &mut *self.with_ctx(Ctx {
1596 is_dimension_unit: true,
1597 allow_to_lowercase: true,
1598 ..self.ctx
1599 }),
1600 n.unit
1601 );
1602 }
1603
1604 #[emitter]
1605 fn emit_time(&mut self, n: &Time) -> Result {
1606 emit!(self, n.value);
1607 emit!(
1608 &mut *self.with_ctx(Ctx {
1609 is_dimension_unit: true,
1610 allow_to_lowercase: true,
1611 ..self.ctx
1612 }),
1613 n.unit
1614 );
1615 }
1616
1617 #[emitter]
1618 fn emit_frequency(&mut self, n: &Frequency) -> Result {
1619 emit!(self, n.value);
1620 emit!(
1621 &mut *self.with_ctx(Ctx {
1622 is_dimension_unit: true,
1623 allow_to_lowercase: true,
1624 ..self.ctx
1625 }),
1626 n.unit
1627 );
1628 }
1629
1630 #[emitter]
1631 fn emit_resolution(&mut self, n: &Resolution) -> Result {
1632 emit!(self, n.value);
1633 emit!(
1634 &mut *self.with_ctx(Ctx {
1635 is_dimension_unit: true,
1636 allow_to_lowercase: true,
1637 ..self.ctx
1638 }),
1639 n.unit
1640 );
1641 }
1642
1643 #[emitter]
1644 fn emit_flex(&mut self, n: &Flex) -> Result {
1645 emit!(self, n.value);
1646 emit!(
1647 &mut *self.with_ctx(Ctx {
1648 is_dimension_unit: true,
1649 allow_to_lowercase: true,
1650 ..self.ctx
1651 }),
1652 n.unit
1653 );
1654 }
1655
1656 #[emitter]
1657 fn emit_unknown_dimension(&mut self, n: &UnknownDimension) -> Result {
1658 emit!(self, n.value);
1659 emit!(
1660 &mut *self.with_ctx(Ctx {
1661 is_dimension_unit: true,
1662 allow_to_lowercase: true,
1663 ..self.ctx
1664 }),
1665 n.unit
1666 );
1667 }
1668
1669 #[emitter]
1670 fn emit_integer(&mut self, n: &Integer) -> Result {
1671 write_raw!(self, n.span, &n.value.to_string());
1672 }
1673
1674 #[emitter]
1675 fn emit_number(&mut self, n: &Number) -> Result {
1676 if self.config.minify {
1677 let minified = minify_numeric(n.value);
1678
1679 write_raw!(self, n.span, &minified);
1680 } else if let Some(raw) = &n.raw {
1681 write_raw!(self, n.span, raw);
1682 } else {
1683 write_raw!(self, n.span, &n.value.to_string());
1684 }
1685 }
1686
1687 #[emitter]
1688 fn emit_ration(&mut self, n: &Ratio) -> Result {
1689 emit!(self, n.left);
1690
1691 if let Some(right) = &n.right {
1692 write_raw!(self, "/");
1693 emit!(self, right);
1694 }
1695 }
1696
1697 #[emitter]
1698 fn emit_color(&mut self, n: &Color) -> Result {
1699 match n {
1700 Color::AbsoluteColorBase(n) => emit!(self, n),
1701 Color::CurrentColorOrSystemColor(n) => emit!(self, n),
1702 Color::Function(n) => emit!(self, n),
1703 }
1704 }
1705
1706 #[emitter]
1707 fn emit_absolute_color_base(&mut self, n: &AbsoluteColorBase) -> Result {
1708 match n {
1709 AbsoluteColorBase::HexColor(n) => emit!(self, n),
1710 AbsoluteColorBase::NamedColorOrTransparent(n) => emit!(self, n),
1711 AbsoluteColorBase::Function(n) => emit!(self, n),
1712 }
1713 }
1714
1715 #[emitter]
1716 fn emit_hex_color(&mut self, n: &HexColor) -> Result {
1717 let mut hex_color = String::with_capacity(9);
1718
1719 hex_color.push('#');
1720
1721 if self.config.minify {
1722 let minified = minify_hex_color(&n.value);
1723
1724 hex_color.push_str(&minified);
1725 } else {
1726 hex_color.push_str(&n.value);
1727 }
1728
1729 write_raw!(self, n.span, &hex_color);
1730 }
1731
1732 #[emitter]
1733 fn emit_alpha_value(&mut self, n: &AlphaValue) -> Result {
1734 match n {
1735 AlphaValue::Number(n) => emit!(self, n),
1736 AlphaValue::Percentage(n) => emit!(self, n),
1737 }
1738 }
1739
1740 #[emitter]
1741 fn emit_hue(&mut self, n: &Hue) -> Result {
1742 match n {
1743 Hue::Number(n) => emit!(self, n),
1744 Hue::Angle(n) => emit!(self, n),
1745 }
1746 }
1747
1748 #[emitter]
1749 fn emit_cmyk_component(&mut self, n: &CmykComponent) -> Result {
1750 match n {
1751 CmykComponent::Number(n) => emit!(self, n),
1752 CmykComponent::Percentage(n) => emit!(self, n),
1753 CmykComponent::Function(n) => emit!(self, n),
1754 }
1755 }
1756
1757 #[emitter]
1758 fn emit_delimiter(&mut self, n: &Delimiter) -> Result {
1759 write_raw!(self, n.span, n.value.as_str());
1760 }
1761
1762 #[emitter]
1763 fn emit_calc_sum(&mut self, n: &CalcSum) -> Result {
1764 self.emit_list(&n.expressions, ListFormat::NotDelimited)?;
1765 }
1766
1767 #[emitter]
1768 fn emit_calc_product_or_operator(&mut self, n: &CalcProductOrOperator) -> Result {
1769 match n {
1770 CalcProductOrOperator::Product(n) => emit!(self, n),
1771 CalcProductOrOperator::Operator(n) => emit!(self, n),
1772 }
1773 }
1774
1775 #[emitter]
1776 fn emit_calc_operator(&mut self, n: &CalcOperator) -> Result {
1777 let need_space = matches!(n.value, CalcOperatorType::Add | CalcOperatorType::Sub);
1778
1779 if need_space {
1780 space!(self);
1781 } else {
1782 formatting_space!(self);
1783 }
1784
1785 write_raw!(self, n.span, n.value.as_str());
1786
1787 if need_space {
1788 space!(self);
1789 } else {
1790 formatting_space!(self);
1791 }
1792 }
1793
1794 #[emitter]
1795 fn emit_calc_product(&mut self, n: &CalcProduct) -> Result {
1796 self.emit_list(&n.expressions, ListFormat::None)?;
1797 }
1798
1799 #[emitter]
1800 fn emit_calc_value_or_operator(&mut self, n: &CalcValueOrOperator) -> Result {
1801 match n {
1802 CalcValueOrOperator::Value(n) => emit!(self, n),
1803 CalcValueOrOperator::Operator(n) => emit!(self, n),
1804 }
1805 }
1806
1807 #[emitter]
1808 fn emit_calc_value(&mut self, n: &CalcValue) -> Result {
1809 match n {
1810 CalcValue::Number(n) => emit!(self, n),
1811 CalcValue::Dimension(n) => emit!(self, n),
1812 CalcValue::Percentage(n) => emit!(self, n),
1813 CalcValue::Constant(n) => emit!(self, n),
1814 CalcValue::Sum(n) => {
1815 write_raw!(self, lo_span_offset!(n.span, 1), "(");
1816 emit!(self, n);
1817 write_raw!(self, hi_span_offset!(n.span, 1), ")");
1818 }
1819 CalcValue::Function(n) => emit!(self, n),
1820 }
1821 }
1822
1823 #[emitter]
1824 fn emit_token_and_span(&mut self, n: &TokenAndSpan) -> Result {
1825 let span = n.span;
1826
1827 match &n.token {
1828 Token::AtKeyword { raw, .. } => {
1829 let mut at_keyword = String::with_capacity(1 + raw.len());
1830
1831 at_keyword.push('@');
1832 at_keyword.push_str(raw);
1833
1834 write_raw!(self, span, &at_keyword);
1835 }
1836 Token::Delim { value } => {
1837 write_raw!(self, span, &value.to_string());
1838 }
1839 Token::LParen => {
1840 write_raw!(self, span, "(");
1841 }
1842 Token::RParen => {
1843 write_raw!(self, span, ")");
1844 }
1845 Token::LBracket => {
1846 write_raw!(self, span, "[");
1847 }
1848 Token::RBracket => {
1849 write_raw!(self, span, "]");
1850 }
1851 Token::Number { raw, .. } => {
1852 write_raw!(self, span, raw);
1853 }
1854 Token::Percentage { raw, .. } => {
1855 let mut percentage = String::with_capacity(raw.len() + 1);
1856
1857 percentage.push_str(raw);
1858 percentage.push('%');
1859
1860 write_raw!(self, span, &percentage);
1861 }
1862 Token::Dimension { dimension: token } => {
1863 let mut dimension =
1864 String::with_capacity(token.raw_value.len() + token.raw_unit.len());
1865
1866 dimension.push_str(&token.raw_value);
1867 dimension.push_str(&token.raw_unit);
1868
1869 write_raw!(self, span, &dimension);
1870 }
1871 Token::Ident { raw, .. } => {
1872 write_raw!(self, span, raw);
1873 }
1874 Token::Function { raw, .. } => {
1875 let mut function = String::with_capacity(raw.len() + 1);
1876
1877 function.push_str(raw);
1878 function.push('(');
1879
1880 write_raw!(self, span, &function);
1881 }
1882 Token::BadString { raw } => {
1883 write_str!(self, span, raw);
1884 }
1885 Token::String { raw, .. } => {
1886 write_str!(self, span, raw);
1887 }
1888 Token::Url { raw, .. } => {
1889 let mut url = String::with_capacity(raw.0.len() + raw.1.len() + 2);
1890
1891 url.push_str(&raw.0);
1892 url.push('(');
1893 url.push_str(&raw.1);
1894 url.push(')');
1895
1896 write_str!(self, span, &url);
1897 }
1898 Token::BadUrl { raw, .. } => {
1899 write_str!(self, span, raw);
1900 }
1901 Token::Comma => {
1902 write_raw!(self, span, ",");
1903 }
1904 Token::Semi => {
1905 write_raw!(self, span, ";");
1906 }
1907 Token::LBrace => {
1908 write_raw!(self, span, "{");
1909 }
1910 Token::RBrace => {
1911 write_raw!(self, span, "}");
1912 }
1913 Token::Colon => {
1914 write_raw!(self, span, ":");
1915 }
1916 Token::Hash { raw, .. } => {
1917 let mut hash = String::with_capacity(raw.len() + 1);
1918
1919 hash.push('#');
1920 hash.push_str(raw);
1921
1922 write_raw!(self, span, &hash);
1923 }
1924 Token::WhiteSpace { value } => {
1925 write_str!(self, span, value);
1926 }
1927 Token::CDC => {
1928 write_raw!(self, span, "-->");
1929 }
1930 Token::CDO => {
1931 write_raw!(self, span, "<!--");
1932 }
1933 }
1934 }
1935
1936 #[emitter]
1937 fn emit_url(&mut self, n: &Url) -> Result {
1938 emit!(
1939 &mut *self.with_ctx(Ctx {
1940 allow_to_lowercase: true,
1941 ..self.ctx
1942 }),
1943 n.name
1944 );
1945 write_raw!(self, "(");
1946
1947 if let Some(value) = &n.value {
1948 emit!(self, value);
1949 }
1950
1951 if let Some(modifiers) = &n.modifiers {
1952 if !modifiers.is_empty() {
1953 if n.value.is_some() {
1954 formatting_space!(self);
1955 }
1956
1957 self.emit_list(modifiers, ListFormat::SpaceDelimited)?;
1958 }
1959 }
1960
1961 write_raw!(self, ")");
1962 }
1963
1964 #[emitter]
1965 fn emit_url_value(&mut self, n: &UrlValue) -> Result {
1966 match n {
1967 UrlValue::Raw(n) => emit!(self, n),
1968 UrlValue::Str(n) => emit!(self, n),
1969 }
1970 }
1971
1972 #[emitter]
1973 fn emit_url_value_raw(&mut self, n: &UrlValueRaw) -> Result {
1974 write_str!(self, n.span, &serialize_url(&n.value));
1975 }
1976
1977 #[emitter]
1978 fn emit_url_modifier(&mut self, n: &UrlModifier) -> Result {
1979 match n {
1980 UrlModifier::Ident(n) => emit!(self, n),
1981 UrlModifier::Function(n) => emit!(self, n),
1982 }
1983 }
1984
1985 #[emitter]
1986 fn emit_unicode_range(&mut self, n: &UnicodeRange) -> Result {
1987 let mut value = String::with_capacity(
1988 n.start.len()
1989 + if let Some(end) = &n.end {
1990 end.len() + 1
1991 } else {
1992 0
1993 }
1994 + 2,
1995 );
1996
1997 value.push_str("u+");
1998 value.push_str(&n.start);
1999
2000 if let Some(end) = &n.end {
2001 value.push('-');
2002 value.push_str(end);
2003 }
2004
2005 write_raw!(self, n.span, &value);
2006 }
2007
2008 #[emitter]
2009 fn emit_family_name(&mut self, n: &FamilyName) -> Result {
2010 match n {
2011 FamilyName::Str(n) => emit!(self, n),
2012 FamilyName::SequenceOfCustomIdents(n) => emit!(self, n),
2013 }
2014 }
2015
2016 #[emitter]
2017 fn emit_sequence_of_custom_idents(&mut self, n: &SequenceOfCustomIdents) -> Result {
2018 self.emit_list(&n.value, ListFormat::SpaceDelimited)?;
2019 }
2020
2021 #[emitter]
2022 fn emit_selector_list(&mut self, n: &SelectorList) -> Result {
2023 self.emit_list(
2024 &n.children,
2025 if self.config.minify || self.ctx.in_single_line_selectors {
2026 ListFormat::CommaDelimited
2027 } else {
2028 ListFormat::CommaDelimited | ListFormat::MultiLine
2029 },
2030 )?;
2031 }
2032
2033 #[emitter]
2034 fn emit_forgiving_selector_list(&mut self, n: &ForgivingSelectorList) -> Result {
2035 for (idx, node) in n.children.iter().enumerate() {
2036 if idx != 0 {
2037 write_raw!(self, ",");
2038
2039 let need_space = matches!(node, ForgivingComplexSelector::ComplexSelector(_));
2040
2041 if need_space {
2042 formatting_space!(self);
2043 }
2044 }
2045
2046 emit!(self, node)
2047 }
2048 }
2049
2050 #[emitter]
2051 fn emit_forgiving_complex_list(&mut self, n: &ForgivingComplexSelector) -> Result {
2052 match n {
2053 ForgivingComplexSelector::ComplexSelector(n) => emit!(self, n),
2054 ForgivingComplexSelector::ListOfComponentValues(n) => {
2055 emit!(
2056 &mut *self.with_ctx(Ctx {
2057 in_list_of_component_values: true,
2058 ..self.ctx
2059 }),
2060 n
2061 )
2062 }
2063 }
2064 }
2065
2066 #[emitter]
2067 fn emit_compound_selector_list(&mut self, n: &CompoundSelectorList) -> Result {
2068 self.emit_list(&n.children, ListFormat::CommaDelimited)?;
2069 }
2070
2071 #[emitter]
2072 fn emit_relative_selector_list(&mut self, n: &RelativeSelectorList) -> Result {
2073 self.emit_list(&n.children, ListFormat::CommaDelimited)?;
2074 }
2075
2076 #[emitter]
2077 fn emit_forgiving_relative_selector_list(
2078 &mut self,
2079 n: &ForgivingRelativeSelectorList,
2080 ) -> Result {
2081 for (idx, node) in n.children.iter().enumerate() {
2082 if idx != 0 {
2083 write_raw!(self, ",");
2084
2085 let need_space = matches!(node, ForgivingRelativeSelector::RelativeSelector(_));
2086
2087 if need_space {
2088 formatting_space!(self);
2089 }
2090 }
2091
2092 emit!(self, node)
2093 }
2094 }
2095
2096 #[emitter]
2097 fn emit_forgiving_relative_selector(&mut self, n: &ForgivingRelativeSelector) -> Result {
2098 match n {
2099 ForgivingRelativeSelector::RelativeSelector(n) => emit!(self, n),
2100 ForgivingRelativeSelector::ListOfComponentValues(n) => {
2101 emit!(
2102 &mut *self.with_ctx(Ctx {
2103 in_list_of_component_values: true,
2104 ..self.ctx
2105 }),
2106 n
2107 )
2108 }
2109 }
2110 }
2111
2112 #[emitter]
2113 fn emit_complex_selector(&mut self, n: &ComplexSelector) -> Result {
2114 for (idx, node) in n.children.iter().enumerate() {
2115 emit!(self, node);
2116
2117 match node {
2118 ComplexSelectorChildren::Combinator(Combinator {
2119 value: CombinatorValue::Descendant,
2120 ..
2121 }) => {}
2122 _ => match n.children.get(idx + 1) {
2123 Some(ComplexSelectorChildren::Combinator(Combinator {
2124 value: CombinatorValue::Descendant,
2125 ..
2126 })) => {}
2127 Some(_) => {
2128 formatting_space!(self);
2129 }
2130 _ => {}
2131 },
2132 }
2133 }
2134 }
2135
2136 #[emitter]
2137 fn emit_relative_selector(&mut self, n: &RelativeSelector) -> Result {
2138 if let Some(combinator) = &n.combinator {
2139 emit!(self, combinator);
2140
2141 formatting_space!(self);
2142 }
2143
2144 emit!(self, n.selector);
2145 }
2146
2147 #[emitter]
2148 fn emit_complex_selector_children(&mut self, n: &ComplexSelectorChildren) -> Result {
2149 match n {
2150 ComplexSelectorChildren::CompoundSelector(n) => emit!(self, n),
2151 ComplexSelectorChildren::Combinator(n) => emit!(self, n),
2152 }
2153 }
2154
2155 #[emitter]
2156 fn emit_compound_selector(&mut self, n: &CompoundSelector) -> Result {
2157 emit!(self, n.nesting_selector);
2158 emit!(self, n.type_selector);
2159
2160 self.emit_list(&n.subclass_selectors, ListFormat::NotDelimited)?;
2161 }
2162
2163 #[emitter]
2164 fn emit_combinator(&mut self, n: &Combinator) -> Result {
2165 write_raw!(self, n.span, n.value.as_str());
2166 }
2167
2168 #[emitter]
2169 fn emit_nesting_selector(&mut self, n: &NestingSelector) -> Result {
2170 write_raw!(self, n.span, "&");
2171 }
2172
2173 #[emitter]
2174 fn emit_subclass_selector(&mut self, n: &SubclassSelector) -> Result {
2175 match n {
2176 SubclassSelector::Id(n) => emit!(self, n),
2177 SubclassSelector::Class(n) => emit!(self, n),
2178 SubclassSelector::Attribute(n) => emit!(self, n),
2179 SubclassSelector::PseudoClass(n) => emit!(self, n),
2180 SubclassSelector::PseudoElement(n) => emit!(self, n),
2181 }
2182 }
2183
2184 #[emitter]
2185 fn emit_type_selector(&mut self, n: &TypeSelector) -> Result {
2186 match n {
2187 TypeSelector::TagName(n) => emit!(self, n),
2188 TypeSelector::Universal(n) => emit!(self, n),
2189 }
2190 }
2191
2192 #[emitter]
2193 fn emit_tag_name_selector(&mut self, n: &TagNameSelector) -> Result {
2194 emit!(
2195 &mut *self.with_ctx(Ctx {
2196 allow_to_lowercase: true,
2197 ..self.ctx
2198 }),
2199 n.name
2200 );
2201 }
2202
2203 #[emitter]
2204 fn emit_universal_selector(&mut self, n: &UniversalSelector) -> Result {
2205 if let Some(prefix) = &n.prefix {
2206 emit!(self, prefix);
2207 }
2208
2209 write_raw!(self, hi_span_offset!(n.span, 1), "*");
2210 }
2211
2212 #[emitter]
2213 fn emit_namespace_prefix(&mut self, n: &NamespacePrefix) -> Result {
2214 if let Some(namespace) = &n.namespace {
2215 emit!(self, namespace);
2216 }
2217
2218 write_raw!(self, hi_span_offset!(n.span, 1), "|");
2219 }
2220
2221 #[emitter]
2222 fn emit_namespace(&mut self, n: &Namespace) -> Result {
2223 match n {
2224 Namespace::Named(n) => emit!(self, n),
2225 Namespace::Any(n) => emit!(self, n),
2226 }
2227 }
2228
2229 #[emitter]
2230 fn emit_named_namespace(&mut self, n: &NamedNamespace) -> Result {
2231 emit!(self, n.name);
2232 }
2233
2234 #[emitter]
2235 fn emit_any_namespace(&mut self, n: &AnyNamespace) -> Result {
2236 write_raw!(self, n.span, "*");
2237 }
2238
2239 #[emitter]
2240 fn emit_wq_name(&mut self, n: &WqName) -> Result {
2241 if n.prefix.is_some() {
2242 emit!(self, n.prefix);
2243 }
2244
2245 emit!(self, n.value);
2246 }
2247
2248 #[emitter]
2249 fn emit_id_selector(&mut self, n: &IdSelector) -> Result {
2250 write_raw!(self, lo_span_offset!(n.span, 1), "#");
2251 emit!(self, n.text);
2252 }
2253
2254 #[emitter]
2255 fn emit_class_selector(&mut self, n: &ClassSelector) -> Result {
2256 write_raw!(self, lo_span_offset!(n.span, 1), ".");
2257 emit!(self, n.text);
2258 }
2259
2260 #[emitter]
2261 fn emit_attribute_selector(&mut self, n: &AttributeSelector) -> Result {
2262 write_raw!(self, lo_span_offset!(n.span, 1), "[");
2263 emit!(self, n.name);
2264
2265 if n.matcher.is_some() {
2266 emit!(self, n.matcher);
2267 emit!(self, n.value);
2268
2269 if n.modifier.is_some() {
2270 match n.value {
2271 Some(AttributeSelectorValue::Str(_)) => {
2272 formatting_space!(self);
2273 }
2274 Some(AttributeSelectorValue::Ident(_)) => {
2275 space!(self);
2276 }
2277 _ => {}
2278 }
2279
2280 emit!(self, n.modifier);
2281 }
2282 }
2283
2284 write_raw!(self, hi_span_offset!(n.span, 1), "]");
2285 }
2286
2287 #[emitter]
2288 fn emit_attribute_selector_matcher(&mut self, n: &AttributeSelectorMatcher) -> Result {
2289 write_raw!(self, n.span, n.value.as_str());
2290 }
2291
2292 #[emitter]
2293 fn emit_attribute_selector_value(&mut self, n: &AttributeSelectorValue) -> Result {
2294 match n {
2295 AttributeSelectorValue::Str(n) => emit!(self, n),
2296 AttributeSelectorValue::Ident(n) => emit!(self, n),
2297 }
2298 }
2299
2300 #[emitter]
2301 fn emit_attribute_selector_modifier(&mut self, n: &AttributeSelectorModifier) -> Result {
2302 emit!(
2303 &mut *self.with_ctx(Ctx {
2304 allow_to_lowercase: true,
2305 ..self.ctx
2306 }),
2307 n.value
2308 );
2309 }
2310
2311 #[emitter]
2312 fn emit_an_plus_b(&mut self, n: &AnPlusB) -> Result {
2313 match n {
2314 AnPlusB::Ident(n) => emit!(self, n),
2315 AnPlusB::AnPlusBNotation(n) => emit!(self, n),
2316 }
2317 }
2318
2319 #[emitter]
2320 fn emit_an_plus_b_notation(&mut self, n: &AnPlusBNotation) -> Result {
2321 let mut an_plus_b = String::with_capacity(4);
2322
2323 if let Some(a) = &n.a {
2324 if *a == -1 {
2325 an_plus_b.push('-');
2326 } else if *a != 1 {
2327 an_plus_b.push_str(&a.to_string());
2328 }
2329
2330 an_plus_b.push('n');
2331 }
2332
2333 if let Some(b) = &n.b {
2334 if *b >= 0 && n.a.is_some() {
2335 an_plus_b.push('+');
2336 }
2337
2338 an_plus_b.push_str(&b.to_string());
2339 }
2340
2341 write_raw!(self, n.span, &an_plus_b);
2342 }
2343
2344 #[emitter]
2345 fn emit_pseudo_class_selector(&mut self, n: &PseudoClassSelector) -> Result {
2346 write_raw!(self, lo_span_offset!(n.span, 1), ":");
2347 emit!(
2348 &mut *self.with_ctx(Ctx {
2349 allow_to_lowercase: true,
2350 ..self.ctx
2351 }),
2352 n.name
2353 );
2354
2355 if let Some(children) = &n.children {
2356 write_raw!(self, "(");
2357 self.emit_list_pseudo_class_selector_children(children)?;
2358 write_raw!(self, ")");
2359 }
2360 }
2361
2362 #[emitter]
2363 fn emit_pseudo_class_selector_children(&mut self, n: &PseudoClassSelectorChildren) -> Result {
2364 match n {
2365 PseudoClassSelectorChildren::PreservedToken(n) => emit!(self, n),
2366 PseudoClassSelectorChildren::AnPlusB(n) => emit!(self, n),
2367 PseudoClassSelectorChildren::Ident(n) => emit!(self, n),
2368 PseudoClassSelectorChildren::Str(n) => emit!(self, n),
2369 PseudoClassSelectorChildren::Delimiter(n) => emit!(self, n),
2370 PseudoClassSelectorChildren::ComplexSelector(n) => emit!(self, n),
2371 PseudoClassSelectorChildren::SelectorList(n) => emit!(
2372 &mut *self.with_ctx(Ctx {
2373 in_single_line_selectors: true,
2374 ..self.ctx
2375 }),
2376 n
2377 ),
2378 PseudoClassSelectorChildren::ForgivingSelectorList(n) => emit!(
2379 &mut *self.with_ctx(Ctx {
2380 in_single_line_selectors: true,
2381 ..self.ctx
2382 }),
2383 n
2384 ),
2385 PseudoClassSelectorChildren::CompoundSelectorList(n) => emit!(self, n),
2386 PseudoClassSelectorChildren::RelativeSelectorList(n) => emit!(self, n),
2387 PseudoClassSelectorChildren::ForgivingRelativeSelectorList(n) => emit!(self, n),
2388 PseudoClassSelectorChildren::CompoundSelector(n) => emit!(self, n),
2389 }
2390 }
2391
2392 fn emit_list_pseudo_class_selector_children(
2393 &mut self,
2394 nodes: &[PseudoClassSelectorChildren],
2395 ) -> Result {
2396 let len = nodes.len();
2397
2398 for (idx, node) in nodes.iter().enumerate() {
2399 emit!(self, node);
2400
2401 if idx != len - 1 {
2402 match node {
2403 PseudoClassSelectorChildren::PreservedToken(_) => {}
2404 PseudoClassSelectorChildren::Delimiter(_) => {
2405 formatting_space!(self);
2406 }
2407 _ => {
2408 let next = nodes.get(idx + 1);
2409
2410 match next {
2411 Some(PseudoClassSelectorChildren::Delimiter(Delimiter {
2412 value: DelimiterValue::Comma,
2413 ..
2414 })) => {}
2415 _ => {
2416 space!(self)
2417 }
2418 }
2419 }
2420 }
2421 }
2422 }
2423
2424 Ok(())
2425 }
2426
2427 #[emitter]
2428 fn emit_pseudo_element_selector(&mut self, n: &PseudoElementSelector) -> Result {
2429 write_raw!(self, lo_span_offset!(n.span, 1), ":");
2430 write_raw!(self, lo_span_offset!(n.span, 2), ":");
2431 emit!(
2432 &mut *self.with_ctx(Ctx {
2433 allow_to_lowercase: true,
2434 ..self.ctx
2435 }),
2436 n.name
2437 );
2438
2439 if let Some(children) = &n.children {
2440 write_raw!(self, "(");
2441 self.emit_list_pseudo_element_selector_children(children)?;
2442 write_raw!(self, ")");
2443 }
2444 }
2445
2446 #[emitter]
2447 fn emit_pseudo_element_selector_children(
2448 &mut self,
2449 n: &PseudoElementSelectorChildren,
2450 ) -> Result {
2451 match n {
2452 PseudoElementSelectorChildren::PreservedToken(n) => emit!(self, n),
2453 PseudoElementSelectorChildren::Ident(n) => emit!(self, n),
2454 PseudoElementSelectorChildren::CompoundSelector(n) => emit!(self, n),
2455 PseudoElementSelectorChildren::CustomHighlightName(n) => emit!(self, n),
2456 }
2457 }
2458
2459 #[emitter]
2460 fn emit_scope_range(&mut self, n: &ScopeRange) -> Result {
2461 if let Some(start) = &n.scope_start {
2462 formatting_space!(self);
2463 write_raw!(self, "(");
2464 emit!(self, start);
2465 write_raw!(self, ")");
2466 }
2467 if let Some(end) = &n.scope_end {
2468 write_raw!(self, " to");
2469 space!(self);
2470 write_raw!(self, "(");
2471 emit!(self, end);
2472 write_raw!(self, ")");
2473 }
2474 }
2475
2476 fn emit_list_pseudo_element_selector_children(
2477 &mut self,
2478 nodes: &[PseudoElementSelectorChildren],
2479 ) -> Result {
2480 let len = nodes.len();
2481
2482 for (idx, node) in nodes.iter().enumerate() {
2483 emit!(self, node);
2484
2485 if idx != len - 1 {
2486 match node {
2487 PseudoElementSelectorChildren::PreservedToken(_) => {}
2488 _ => {
2489 space!(self)
2490 }
2491 }
2492 }
2493 }
2494
2495 Ok(())
2496 }
2497
2498 fn emit_list<N>(&mut self, nodes: &[N], format: ListFormat) -> Result
2499 where
2500 Self: Emit<N>,
2501 N: Spanned,
2502 {
2503 for (idx, node) in nodes.iter().enumerate() {
2504 if idx != 0 {
2505 self.write_delim(format)?;
2506
2507 if format & ListFormat::LinesMask == ListFormat::MultiLine {
2508 formatting_newline!(self);
2509 }
2510 }
2511
2512 emit!(self, node)
2513 }
2514
2515 Ok(())
2516 }
2517
2518 fn write_delim(&mut self, f: ListFormat) -> Result {
2519 match f & ListFormat::DelimitersMask {
2520 ListFormat::None => {}
2521 ListFormat::CommaDelimited => {
2522 write_raw!(self, ",");
2523 formatting_space!(self);
2524 }
2525 ListFormat::SpaceDelimited => {
2526 space!(self)
2527 }
2528 ListFormat::SemiDelimited => {
2529 write_raw!(self, ";")
2530 }
2531 ListFormat::DotDelimited => {
2532 write_raw!(self, ".");
2533 }
2534 _ => unreachable!(),
2535 }
2536
2537 Ok(())
2538 }
2539}
2540
2541fn minify_numeric(value: f64) -> String {
2542 if value.is_sign_negative() && value == 0.0 {
2543 return "-0".to_owned();
2544 }
2545 let mut minified = value.to_string();
2546
2547 if minified.starts_with("0.") {
2548 minified.replace_range(0..1, "");
2549 } else if minified.starts_with("-0.") {
2550 minified.replace_range(1..2, "");
2551 }
2552
2553 if minified.starts_with(".000") {
2554 let mut cnt = 3;
2555
2556 for &v in minified.as_bytes().iter().skip(4) {
2557 if v == b'0' {
2558 cnt += 1;
2559 } else {
2560 break;
2561 }
2562 }
2563
2564 minified.replace_range(0..cnt + 1, "");
2565
2566 let remain_len = minified.len();
2567
2568 minified.push_str("e-");
2569 minified.push_str(&(remain_len + cnt).to_string());
2570 } else if minified.ends_with("000") {
2571 let mut cnt = 3;
2572
2573 for &v in minified.as_bytes().iter().rev().skip(3) {
2574 if v == b'0' {
2575 cnt += 1;
2576 } else {
2577 break;
2578 }
2579 }
2580
2581 minified.truncate(minified.len() - cnt);
2582 minified.push('e');
2583 minified.push_str(&cnt.to_string());
2584 }
2585
2586 minified
2587}
2588
2589fn minify_hex_color(value: &str) -> String {
2590 let length = value.len();
2591
2592 if length == 6 || length == 8 {
2593 let chars = value.as_bytes();
2594
2595 if chars[0] == chars[1] && chars[2] == chars[3] && chars[4] == chars[5] {
2596 if length == 6 || chars[6] == b'f' && chars[7] == b'f' {
2598 let mut minified = String::with_capacity(3);
2599
2600 minified.push(chars[0] as char);
2601 minified.push(chars[2] as char);
2602 minified.push(chars[4] as char);
2603
2604 return minified;
2605 }
2606 else if length == 8 && chars[6] == chars[7] {
2608 let mut minified = String::with_capacity(4);
2609
2610 minified.push(chars[0] as char);
2611 minified.push(chars[2] as char);
2612 minified.push(chars[4] as char);
2613 minified.push(chars[6] as char);
2614
2615 return minified;
2616 }
2617 }
2618 }
2619
2620 value.to_string()
2621}
2622
2623fn serialize_string(value: &str) -> String {
2624 let mut minified = String::with_capacity(value.len());
2625
2626 for c in value.chars() {
2627 match c {
2628 '\0' => {
2630 minified.push('\u{FFFD}');
2631 }
2632 '\x01'..='\x1F' | '\x7F' => {
2635 static HEX_DIGITS: &[u8; 16] = b"0123456789abcdef";
2636
2637 let b3;
2638 let b4;
2639 let char_as_u8 = c as u8;
2640
2641 let bytes = if char_as_u8 > 0x0f {
2642 let high = (char_as_u8 >> 4) as usize;
2643 let low = (char_as_u8 & 0x0f) as usize;
2644
2645 b4 = [b'\\', HEX_DIGITS[high], HEX_DIGITS[low], b' '];
2646
2647 &b4[..]
2648 } else {
2649 b3 = [b'\\', HEX_DIGITS[c as usize], b' '];
2650
2651 &b3[..]
2652 };
2653
2654 minified.push_str(from_utf8(bytes).unwrap());
2655 }
2656 '\\' => {
2658 minified.push_str("\\\\");
2659 }
2660 '"' => {
2661 minified.push('\"');
2662 }
2663 _ => {
2665 minified.push(c);
2666 }
2667 };
2668 }
2669
2670 format!("\"{}\"", minified.replace('"', "\\\""))
2671}
2672
2673fn serialize_url(value: &str) -> String {
2674 let mut new_value = String::with_capacity(value.len());
2675
2676 for c in value.chars() {
2677 match c {
2678 '\x01'..='\x1F' | '\x7F' => {
2679 static HEX_DIGITS: &[u8; 16] = b"0123456789abcdef";
2680
2681 let b3;
2682 let b4;
2683 let char_as_u8 = c as u8;
2684
2685 let bytes = if char_as_u8 > 0x0f {
2686 let high = (char_as_u8 >> 4) as usize;
2687 let low = (char_as_u8 & 0x0f) as usize;
2688
2689 b4 = [b'\\', HEX_DIGITS[high], HEX_DIGITS[low], b' '];
2690
2691 &b4[..]
2692 } else {
2693 b3 = [b'\\', HEX_DIGITS[c as usize], b' '];
2694
2695 &b3[..]
2696 };
2697
2698 new_value.push_str(from_utf8(bytes).unwrap());
2699 }
2700 '(' | ')' | '"' | '\'' => {
2701 new_value.push('\\');
2702 new_value.push(c)
2703 }
2704 '\\' => {
2705 new_value.push_str("\\\\");
2706 }
2707 _ if c.is_whitespace() => {
2708 new_value.push('\\');
2709 new_value.push(c)
2710 }
2711 _ => {
2712 new_value.push(c);
2713 }
2714 };
2715 }
2716
2717 new_value
2718}
2719
2720fn minify_string(value: &str) -> String {
2721 let mut minified = String::with_capacity(value.len());
2722
2723 let mut dq = 0;
2724 let mut sq = 0;
2725
2726 for c in value.chars() {
2727 match c {
2728 '\0' => {
2730 minified.push('\u{FFFD}');
2731 }
2732 '\x01'..='\x1F' | '\x7F' => {
2735 static HEX_DIGITS: &[u8; 16] = b"0123456789abcdef";
2736
2737 let b3;
2738 let b4;
2739 let char_as_u8 = c as u8;
2740
2741 let bytes = if char_as_u8 > 0x0f {
2742 let high = (char_as_u8 >> 4) as usize;
2743 let low = (char_as_u8 & 0x0f) as usize;
2744
2745 b4 = [b'\\', HEX_DIGITS[high], HEX_DIGITS[low], b' '];
2746
2747 &b4[..]
2748 } else {
2749 b3 = [b'\\', HEX_DIGITS[c as usize], b' '];
2750
2751 &b3[..]
2752 };
2753
2754 minified.push_str(from_utf8(bytes).unwrap());
2755 }
2756 '\\' => {
2760 minified.push_str("\\\\");
2761 }
2762 '"' => {
2763 dq += 1;
2764
2765 minified.push(c);
2766 }
2767 '\'' => {
2768 sq += 1;
2769
2770 minified.push(c);
2771 }
2772 _ => {
2774 minified.push(c);
2775 }
2776 };
2777 }
2778
2779 if dq > sq {
2780 format!("'{}'", minified.replace('\'', "\\'"))
2781 } else {
2782 format!("\"{}\"", minified.replace('"', "\\\""))
2783 }
2784}
2785
2786fn serialize_dimension_unit(value: &str) -> Cow<'_, str> {
2787 let need_escape =
2789 (value.len() >= 2 && value.as_bytes()[0] == b'e' && value.as_bytes()[1].is_ascii_digit())
2790 || value.contains(char::REPLACEMENT_CHARACTER);
2791
2792 if !need_escape {
2793 return Cow::Borrowed(value);
2794 }
2795
2796 let mut result = String::with_capacity(value.len());
2797 let mut chars = value.chars().enumerate().peekable();
2798
2799 while let Some((i, c)) = chars.next() {
2800 match c {
2801 char::REPLACEMENT_CHARACTER => {
2803 result.push_str("\\0");
2804 }
2805 'e' if i == 0 => {
2808 if matches!(chars.peek(), Some((_, '0'..='9'))) {
2809 result.push(c);
2810 result.push_str("\\3");
2811 } else {
2812 result.push(c);
2813 }
2814 }
2815 _ => {
2816 result.push(c);
2817 }
2818 }
2819 }
2820
2821 Cow::Owned(result)
2822}