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