swc_css_codegen/
lib.rs

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