Skip to main content

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)) if self.config.minify => {
1112                            let minified = minify_numeric(n.value);
1113
1114                            !minified.starts_with('.')
1115                        }
1116                        Some(ComponentValue::Number(_)) => true,
1117                        Some(ComponentValue::Dimension(dimension)) if self.config.minify => {
1118                            let value = match &**dimension {
1119                                Dimension::Length(i) => i.value.value,
1120                                Dimension::Angle(i) => i.value.value,
1121                                Dimension::Time(i) => i.value.value,
1122                                Dimension::Frequency(i) => i.value.value,
1123                                Dimension::Resolution(i) => i.value.value,
1124                                Dimension::Flex(i) => i.value.value,
1125                                Dimension::UnknownDimension(i) => i.value.value,
1126                            };
1127
1128                            let minified = minify_numeric(value);
1129
1130                            !minified.starts_with('.')
1131                        }
1132                        Some(ComponentValue::Dimension(_)) => true,
1133                        Some(component_value) if self.config.minify => {
1134                            if let Some(minified) = match component_value {
1135                                ComponentValue::LengthPercentage(p) => {
1136                                    p.as_length().map(|l| l.value.value)
1137                                }
1138                                ComponentValue::FrequencyPercentage(p) => {
1139                                    p.as_frequency().map(|f| f.value.value)
1140                                }
1141                                ComponentValue::AnglePercentage(p) => {
1142                                    p.as_angle().map(|a| a.value.value)
1143                                }
1144                                ComponentValue::TimePercentage(p) => {
1145                                    p.as_time().map(|t| t.value.value)
1146                                }
1147                                _ => None,
1148                            }
1149                            .map(minify_numeric)
1150                            {
1151                                !minified.starts_with('.')
1152                            } else {
1153                                true
1154                            }
1155                        }
1156                        _ => true,
1157                    },
1158                    _ => match next {
1159                        Some(ComponentValue::SimpleBlock(_)) => !self.config.minify,
1160                        Some(ComponentValue::Color(color))
1161                            if matches!(
1162                                &**color,
1163                                Color::AbsoluteColorBase(AbsoluteColorBase::HexColor(_))
1164                            ) =>
1165                        {
1166                            !self.config.minify
1167                        }
1168                        Some(ComponentValue::Delimiter(_)) => false,
1169                        _ => true,
1170                    },
1171                };
1172
1173                if need_delim {
1174                    self.write_delim(format)?;
1175                }
1176            }
1177        }
1178
1179        Ok(())
1180    }
1181
1182    #[emitter]
1183    fn emit_function(&mut self, n: &Function) -> Result {
1184        emit!(
1185            &mut *self.with_ctx(Ctx {
1186                allow_to_lowercase: true,
1187                ..self.ctx
1188            }),
1189            n.name
1190        );
1191        write_raw!(self, "(");
1192        self.emit_list_of_component_values_inner(
1193            &n.value,
1194            ListFormat::SpaceDelimited | ListFormat::SingleLine,
1195        )?;
1196        write_raw!(self, ")");
1197    }
1198
1199    #[emitter]
1200    fn emit_function_name(&mut self, n: &FunctionName) -> Result {
1201        match n {
1202            FunctionName::Ident(n) => emit!(self, n),
1203            FunctionName::DashedIdent(n) => emit!(self, n),
1204        }
1205    }
1206
1207    #[emitter]
1208    fn emit_color_profile_name(&mut self, n: &ColorProfileName) -> Result {
1209        match n {
1210            ColorProfileName::Ident(n) => emit!(self, n),
1211            ColorProfileName::DashedIdent(n) => emit!(self, n),
1212        }
1213    }
1214
1215    #[emitter]
1216    fn emit_str(&mut self, n: &Str) -> Result {
1217        if self.config.minify {
1218            let minified = minify_string(&n.value);
1219
1220            write_str!(self, n.span, &minified);
1221        } else if let Some(raw) = &n.raw {
1222            write_str!(self, n.span, raw);
1223        } else {
1224            let value = serialize_string(&n.value);
1225
1226            write_str!(self, n.span, &value);
1227        }
1228    }
1229
1230    #[emitter]
1231    fn emit_simple_block(&mut self, n: &SimpleBlock) -> Result {
1232        let (starting, ending) = match n.name.token {
1233            Token::LBracket => ("[", "]"),
1234            Token::LParen => ("(", ")"),
1235            Token::LBrace => ("{", "}"),
1236            _ => {
1237                unreachable!();
1238            }
1239        };
1240
1241        write_raw!(self, lo_span_offset!(n.span, 1), starting);
1242
1243        let len = n.value.len();
1244
1245        for (idx, node) in n.value.iter().enumerate() {
1246            match node {
1247                ComponentValue::ListOfComponentValues(_) | ComponentValue::Declaration(_) => {
1248                    if idx == 0 {
1249                        formatting_newline!(self);
1250                    }
1251
1252                    increase_indent!(self);
1253                }
1254                ComponentValue::AtRule(_)
1255                | ComponentValue::QualifiedRule(_)
1256                | ComponentValue::KeyframeBlock(_) => {
1257                    formatting_newline!(self);
1258                    increase_indent!(self);
1259                }
1260
1261                _ => {}
1262            }
1263
1264            match node {
1265                ComponentValue::ListOfComponentValues(node) => {
1266                    emit!(
1267                        &mut *self.with_ctx(Ctx {
1268                            in_list_of_component_values: true,
1269                            ..self.ctx
1270                        }),
1271                        node
1272                    );
1273                }
1274                _ => {
1275                    emit!(self, node);
1276                }
1277            }
1278
1279            match node {
1280                ComponentValue::AtRule(_) | ComponentValue::QualifiedRule(_) => {
1281                    formatting_newline!(self);
1282                    decrease_indent!(self);
1283                }
1284                ComponentValue::Declaration(_) => {
1285                    if idx != len - 1 {
1286                        semi!(self);
1287                    } else {
1288                        formatting_semi!(self);
1289                    }
1290
1291                    formatting_newline!(self);
1292                    decrease_indent!(self);
1293                }
1294                ComponentValue::ListOfComponentValues(_) => {
1295                    decrease_indent!(self);
1296                }
1297
1298                ComponentValue::KeyframeBlock(_) => {
1299                    if idx == len - 1 {
1300                        formatting_newline!(self);
1301                    }
1302
1303                    decrease_indent!(self);
1304                }
1305
1306                _ => {
1307                    if !self.ctx.in_list_of_component_values && ending == "]" && idx != len - 1 {
1308                        space!(self);
1309                    }
1310                }
1311            }
1312        }
1313
1314        write_raw!(self, hi_span_offset!(n.span, 1), ending);
1315    }
1316
1317    #[emitter]
1318    fn emit_component_value(&mut self, n: &ComponentValue) -> Result {
1319        match n {
1320            ComponentValue::PreservedToken(n) => emit!(self, n),
1321            ComponentValue::Function(n) => emit!(self, n),
1322            ComponentValue::SimpleBlock(n) => emit!(self, n),
1323
1324            ComponentValue::ListOfComponentValues(n) => emit!(self, n),
1325            ComponentValue::QualifiedRule(n) => emit!(self, n),
1326            ComponentValue::AtRule(n) => emit!(self, n),
1327            ComponentValue::KeyframeBlock(n) => emit!(self, n),
1328
1329            ComponentValue::Ident(n) => emit!(self, n),
1330            ComponentValue::DashedIdent(n) => emit!(self, n),
1331            ComponentValue::Str(n) => emit!(self, n),
1332            ComponentValue::Url(n) => emit!(self, n),
1333            ComponentValue::Integer(n) => emit!(self, n),
1334            ComponentValue::Number(n) => emit!(self, n),
1335            ComponentValue::Percentage(n) => emit!(self, n),
1336            ComponentValue::Dimension(n) => emit!(self, n),
1337            ComponentValue::LengthPercentage(n) => emit!(self, n),
1338            ComponentValue::FrequencyPercentage(n) => emit!(self, n),
1339            ComponentValue::AnglePercentage(n) => emit!(self, n),
1340            ComponentValue::TimePercentage(n) => emit!(self, n),
1341            ComponentValue::Ratio(n) => emit!(self, n),
1342            ComponentValue::UnicodeRange(n) => emit!(self, n),
1343            ComponentValue::Color(n) => emit!(self, n),
1344            ComponentValue::AlphaValue(n) => emit!(self, n),
1345            ComponentValue::Hue(n) => emit!(self, n),
1346            ComponentValue::CmykComponent(n) => emit!(self, n),
1347            ComponentValue::Delimiter(n) => emit!(self, n),
1348
1349            ComponentValue::CalcSum(n) => emit!(self, n),
1350            ComponentValue::ComplexSelector(n) => emit!(self, n),
1351            ComponentValue::LayerName(n) => emit!(self, n),
1352            ComponentValue::Declaration(n) => emit!(self, n),
1353            ComponentValue::SupportsCondition(n) => emit!(self, n),
1354            ComponentValue::IdSelector(n) => emit!(self, n),
1355        }
1356    }
1357
1358    #[emitter]
1359    fn emit_style_block(&mut self, n: &StyleBlock) -> Result {
1360        match n {
1361            StyleBlock::ListOfComponentValues(n) => {
1362                emit!(
1363                    &mut *self.with_ctx(Ctx {
1364                        in_list_of_component_values: true,
1365                        ..self.ctx
1366                    }),
1367                    n
1368                )
1369            }
1370            StyleBlock::AtRule(n) => emit!(self, n),
1371            StyleBlock::Declaration(n) => emit!(self, n),
1372            StyleBlock::QualifiedRule(n) => emit!(self, n),
1373        }
1374    }
1375
1376    #[emitter]
1377    fn emit_declaration_block_item(&mut self, n: &DeclarationOrAtRule) -> Result {
1378        match n {
1379            DeclarationOrAtRule::Declaration(n) => emit!(self, n),
1380            DeclarationOrAtRule::AtRule(n) => emit!(self, n),
1381            DeclarationOrAtRule::ListOfComponentValues(n) => {
1382                emit!(
1383                    &mut *self.with_ctx(Ctx {
1384                        in_list_of_component_values: true,
1385                        ..self.ctx
1386                    }),
1387                    n
1388                )
1389            }
1390        }
1391    }
1392
1393    #[emitter]
1394    fn emit_declaration(&mut self, n: &Declaration) -> Result {
1395        emit!(
1396            &mut *self.with_ctx(Ctx {
1397                allow_to_lowercase: true,
1398                ..self.ctx
1399            }),
1400            n.name
1401        );
1402        write_raw!(self, ":");
1403
1404        let is_custom_property = match n.name {
1405            DeclarationName::DashedIdent(_) => true,
1406            DeclarationName::Ident(_) => false,
1407        };
1408
1409        // https://github.com/w3c/csswg-drafts/issues/774
1410        // `--foo: ;` and `--foo:;` is valid, but not all browsers support it, currently
1411        // we print " " (whitespace) always
1412        if is_custom_property {
1413            match n.value.first() {
1414                None => {
1415                    space!(self);
1416                }
1417                _ => {
1418                    formatting_space!(self);
1419                }
1420            };
1421        } else {
1422            formatting_space!(self);
1423        }
1424
1425        if is_custom_property {
1426            self.with_ctx(Ctx {
1427                in_list_of_component_values: true,
1428                ..self.ctx
1429            })
1430            .emit_list(&n.value, ListFormat::NotDelimited)?;
1431        } else {
1432            self.emit_list_of_component_values_inner(
1433                &n.value,
1434                ListFormat::SpaceDelimited | ListFormat::SingleLine,
1435            )?;
1436        }
1437
1438        if n.important.is_some() {
1439            if !is_custom_property {
1440                formatting_space!(self);
1441            }
1442
1443            emit!(self, n.important);
1444        }
1445    }
1446
1447    #[emitter]
1448    fn emit_declaration_name(&mut self, n: &DeclarationName) -> Result {
1449        match n {
1450            DeclarationName::Ident(n) => emit!(self, n),
1451            DeclarationName::DashedIdent(n) => emit!(self, n),
1452        }
1453    }
1454
1455    #[emitter]
1456    fn emit_important_flag(&mut self, n: &ImportantFlag) -> Result {
1457        write_raw!(self, lo_span_offset!(n.span, 1), "!");
1458
1459        if self.config.minify {
1460            emit!(
1461                &mut *self.with_ctx(Ctx {
1462                    allow_to_lowercase: true,
1463                    ..self.ctx
1464                }),
1465                n.value
1466            );
1467        } else {
1468            emit!(self, n.value);
1469        }
1470    }
1471
1472    #[emitter]
1473    fn emit_ident(&mut self, n: &Ident) -> Result {
1474        let value = if self.ctx.allow_to_lowercase && self.config.minify {
1475            Cow::Owned(n.value.to_ascii_lowercase())
1476        } else {
1477            Cow::Borrowed(&n.value)
1478        };
1479
1480        let serialized = serialize_ident(&value, self.config.minify);
1481
1482        // The unit of a <dimension-token> may need escaping to disambiguate with
1483        // scientific notation.
1484        // Old browser hacks with `\0` and other - IE
1485        if self.ctx.is_dimension_unit {
1486            write_raw!(self, n.span, &serialize_dimension_unit(&serialized));
1487        } else {
1488            write_raw!(self, n.span, &serialized);
1489        }
1490    }
1491
1492    #[emitter]
1493    fn emit_custom_ident(&mut self, n: &CustomIdent) -> Result {
1494        let serialized = serialize_ident(&n.value, self.config.minify);
1495
1496        write_raw!(self, n.span, &serialized);
1497    }
1498
1499    #[emitter]
1500    fn emit_dashed_ident(&mut self, n: &DashedIdent) -> Result {
1501        write_raw!(self, lo_span_offset!(n.span, 2), "--");
1502
1503        let serialized = serialize_ident(&n.value, self.config.minify);
1504
1505        write_raw!(self, n.span, &serialized);
1506    }
1507
1508    #[emitter]
1509    fn emit_extension_name(&mut self, n: &ExtensionName) -> Result {
1510        let serialized = serialize_ident(&n.value, self.config.minify);
1511
1512        write_raw!(self, n.span, &serialized);
1513    }
1514
1515    #[emitter]
1516    fn emit_custom_highlight_name(&mut self, n: &CustomHighlightName) -> Result {
1517        let serialized = serialize_ident(&n.value, self.config.minify);
1518
1519        write_raw!(self, n.span, &serialized);
1520    }
1521
1522    #[emitter]
1523    fn emit_custom_property_name(&mut self, n: &CustomPropertyName) -> Result {
1524        write_raw!(self, n.span, &n.value);
1525    }
1526
1527    #[emitter]
1528    fn emit_percentage(&mut self, n: &Percentage) -> Result {
1529        emit!(self, n.value);
1530        write_raw!(self, hi_span_offset!(n.span, 1), "%");
1531    }
1532
1533    #[emitter]
1534    fn emit_length_percentage(&mut self, n: &LengthPercentage) -> Result {
1535        match n {
1536            LengthPercentage::Length(n) => emit!(self, n),
1537            LengthPercentage::Percentage(n) => emit!(self, n),
1538        }
1539    }
1540
1541    #[emitter]
1542    fn emit_frequency_percentage(&mut self, n: &FrequencyPercentage) -> Result {
1543        match n {
1544            FrequencyPercentage::Frequency(n) => emit!(self, n),
1545            FrequencyPercentage::Percentage(n) => emit!(self, n),
1546        }
1547    }
1548
1549    #[emitter]
1550    fn emit_angle_percentage(&mut self, n: &AnglePercentage) -> Result {
1551        match n {
1552            AnglePercentage::Angle(n) => emit!(self, n),
1553            AnglePercentage::Percentage(n) => emit!(self, n),
1554        }
1555    }
1556
1557    #[emitter]
1558    fn emit_time_percentage(&mut self, n: &TimePercentage) -> Result {
1559        match n {
1560            TimePercentage::Time(n) => emit!(self, n),
1561            TimePercentage::Percentage(n) => emit!(self, n),
1562        }
1563    }
1564
1565    #[emitter]
1566    fn emit_dimension(&mut self, n: &Dimension) -> Result {
1567        match n {
1568            Dimension::Length(n) => emit!(self, n),
1569            Dimension::Angle(n) => emit!(self, n),
1570            Dimension::Time(n) => emit!(self, n),
1571            Dimension::Frequency(n) => emit!(self, n),
1572            Dimension::Resolution(n) => emit!(self, n),
1573            Dimension::Flex(n) => emit!(self, n),
1574            Dimension::UnknownDimension(n) => emit!(self, n),
1575        }
1576    }
1577
1578    #[emitter]
1579    fn emit_length(&mut self, n: &Length) -> Result {
1580        emit!(self, n.value);
1581        emit!(
1582            &mut *self.with_ctx(Ctx {
1583                is_dimension_unit: true,
1584                allow_to_lowercase: true,
1585                ..self.ctx
1586            }),
1587            n.unit
1588        );
1589    }
1590
1591    #[emitter]
1592    fn emit_angle(&mut self, n: &Angle) -> Result {
1593        emit!(self, n.value);
1594        emit!(
1595            &mut *self.with_ctx(Ctx {
1596                is_dimension_unit: true,
1597                allow_to_lowercase: true,
1598                ..self.ctx
1599            }),
1600            n.unit
1601        );
1602    }
1603
1604    #[emitter]
1605    fn emit_time(&mut self, n: &Time) -> Result {
1606        emit!(self, n.value);
1607        emit!(
1608            &mut *self.with_ctx(Ctx {
1609                is_dimension_unit: true,
1610                allow_to_lowercase: true,
1611                ..self.ctx
1612            }),
1613            n.unit
1614        );
1615    }
1616
1617    #[emitter]
1618    fn emit_frequency(&mut self, n: &Frequency) -> Result {
1619        emit!(self, n.value);
1620        emit!(
1621            &mut *self.with_ctx(Ctx {
1622                is_dimension_unit: true,
1623                allow_to_lowercase: true,
1624                ..self.ctx
1625            }),
1626            n.unit
1627        );
1628    }
1629
1630    #[emitter]
1631    fn emit_resolution(&mut self, n: &Resolution) -> Result {
1632        emit!(self, n.value);
1633        emit!(
1634            &mut *self.with_ctx(Ctx {
1635                is_dimension_unit: true,
1636                allow_to_lowercase: true,
1637                ..self.ctx
1638            }),
1639            n.unit
1640        );
1641    }
1642
1643    #[emitter]
1644    fn emit_flex(&mut self, n: &Flex) -> Result {
1645        emit!(self, n.value);
1646        emit!(
1647            &mut *self.with_ctx(Ctx {
1648                is_dimension_unit: true,
1649                allow_to_lowercase: true,
1650                ..self.ctx
1651            }),
1652            n.unit
1653        );
1654    }
1655
1656    #[emitter]
1657    fn emit_unknown_dimension(&mut self, n: &UnknownDimension) -> Result {
1658        emit!(self, n.value);
1659        emit!(
1660            &mut *self.with_ctx(Ctx {
1661                is_dimension_unit: true,
1662                allow_to_lowercase: true,
1663                ..self.ctx
1664            }),
1665            n.unit
1666        );
1667    }
1668
1669    #[emitter]
1670    fn emit_integer(&mut self, n: &Integer) -> Result {
1671        write_raw!(self, n.span, &n.value.to_string());
1672    }
1673
1674    #[emitter]
1675    fn emit_number(&mut self, n: &Number) -> Result {
1676        if self.config.minify {
1677            let minified = minify_numeric(n.value);
1678
1679            write_raw!(self, n.span, &minified);
1680        } else if let Some(raw) = &n.raw {
1681            write_raw!(self, n.span, raw);
1682        } else {
1683            write_raw!(self, n.span, &n.value.to_string());
1684        }
1685    }
1686
1687    #[emitter]
1688    fn emit_ration(&mut self, n: &Ratio) -> Result {
1689        emit!(self, n.left);
1690
1691        if let Some(right) = &n.right {
1692            write_raw!(self, "/");
1693            emit!(self, right);
1694        }
1695    }
1696
1697    #[emitter]
1698    fn emit_color(&mut self, n: &Color) -> Result {
1699        match n {
1700            Color::AbsoluteColorBase(n) => emit!(self, n),
1701            Color::CurrentColorOrSystemColor(n) => emit!(self, n),
1702            Color::Function(n) => emit!(self, n),
1703        }
1704    }
1705
1706    #[emitter]
1707    fn emit_absolute_color_base(&mut self, n: &AbsoluteColorBase) -> Result {
1708        match n {
1709            AbsoluteColorBase::HexColor(n) => emit!(self, n),
1710            AbsoluteColorBase::NamedColorOrTransparent(n) => emit!(self, n),
1711            AbsoluteColorBase::Function(n) => emit!(self, n),
1712        }
1713    }
1714
1715    #[emitter]
1716    fn emit_hex_color(&mut self, n: &HexColor) -> Result {
1717        let mut hex_color = String::with_capacity(9);
1718
1719        hex_color.push('#');
1720
1721        if self.config.minify {
1722            let minified = minify_hex_color(&n.value);
1723
1724            hex_color.push_str(&minified);
1725        } else {
1726            hex_color.push_str(&n.value);
1727        }
1728
1729        write_raw!(self, n.span, &hex_color);
1730    }
1731
1732    #[emitter]
1733    fn emit_alpha_value(&mut self, n: &AlphaValue) -> Result {
1734        match n {
1735            AlphaValue::Number(n) => emit!(self, n),
1736            AlphaValue::Percentage(n) => emit!(self, n),
1737        }
1738    }
1739
1740    #[emitter]
1741    fn emit_hue(&mut self, n: &Hue) -> Result {
1742        match n {
1743            Hue::Number(n) => emit!(self, n),
1744            Hue::Angle(n) => emit!(self, n),
1745        }
1746    }
1747
1748    #[emitter]
1749    fn emit_cmyk_component(&mut self, n: &CmykComponent) -> Result {
1750        match n {
1751            CmykComponent::Number(n) => emit!(self, n),
1752            CmykComponent::Percentage(n) => emit!(self, n),
1753            CmykComponent::Function(n) => emit!(self, n),
1754        }
1755    }
1756
1757    #[emitter]
1758    fn emit_delimiter(&mut self, n: &Delimiter) -> Result {
1759        write_raw!(self, n.span, n.value.as_str());
1760    }
1761
1762    #[emitter]
1763    fn emit_calc_sum(&mut self, n: &CalcSum) -> Result {
1764        self.emit_list(&n.expressions, ListFormat::NotDelimited)?;
1765    }
1766
1767    #[emitter]
1768    fn emit_calc_product_or_operator(&mut self, n: &CalcProductOrOperator) -> Result {
1769        match n {
1770            CalcProductOrOperator::Product(n) => emit!(self, n),
1771            CalcProductOrOperator::Operator(n) => emit!(self, n),
1772        }
1773    }
1774
1775    #[emitter]
1776    fn emit_calc_operator(&mut self, n: &CalcOperator) -> Result {
1777        let need_space = matches!(n.value, CalcOperatorType::Add | CalcOperatorType::Sub);
1778
1779        if need_space {
1780            space!(self);
1781        } else {
1782            formatting_space!(self);
1783        }
1784
1785        write_raw!(self, n.span, n.value.as_str());
1786
1787        if need_space {
1788            space!(self);
1789        } else {
1790            formatting_space!(self);
1791        }
1792    }
1793
1794    #[emitter]
1795    fn emit_calc_product(&mut self, n: &CalcProduct) -> Result {
1796        self.emit_list(&n.expressions, ListFormat::None)?;
1797    }
1798
1799    #[emitter]
1800    fn emit_calc_value_or_operator(&mut self, n: &CalcValueOrOperator) -> Result {
1801        match n {
1802            CalcValueOrOperator::Value(n) => emit!(self, n),
1803            CalcValueOrOperator::Operator(n) => emit!(self, n),
1804        }
1805    }
1806
1807    #[emitter]
1808    fn emit_calc_value(&mut self, n: &CalcValue) -> Result {
1809        match n {
1810            CalcValue::Number(n) => emit!(self, n),
1811            CalcValue::Dimension(n) => emit!(self, n),
1812            CalcValue::Percentage(n) => emit!(self, n),
1813            CalcValue::Constant(n) => emit!(self, n),
1814            CalcValue::Sum(n) => {
1815                write_raw!(self, lo_span_offset!(n.span, 1), "(");
1816                emit!(self, n);
1817                write_raw!(self, hi_span_offset!(n.span, 1), ")");
1818            }
1819            CalcValue::Function(n) => emit!(self, n),
1820        }
1821    }
1822
1823    #[emitter]
1824    fn emit_token_and_span(&mut self, n: &TokenAndSpan) -> Result {
1825        let span = n.span;
1826
1827        match &n.token {
1828            Token::AtKeyword { raw, .. } => {
1829                let mut at_keyword = String::with_capacity(1 + raw.len());
1830
1831                at_keyword.push('@');
1832                at_keyword.push_str(raw);
1833
1834                write_raw!(self, span, &at_keyword);
1835            }
1836            Token::Delim { value } => {
1837                write_raw!(self, span, &value.to_string());
1838            }
1839            Token::LParen => {
1840                write_raw!(self, span, "(");
1841            }
1842            Token::RParen => {
1843                write_raw!(self, span, ")");
1844            }
1845            Token::LBracket => {
1846                write_raw!(self, span, "[");
1847            }
1848            Token::RBracket => {
1849                write_raw!(self, span, "]");
1850            }
1851            Token::Number { raw, .. } => {
1852                write_raw!(self, span, raw);
1853            }
1854            Token::Percentage { raw, .. } => {
1855                let mut percentage = String::with_capacity(raw.len() + 1);
1856
1857                percentage.push_str(raw);
1858                percentage.push('%');
1859
1860                write_raw!(self, span, &percentage);
1861            }
1862            Token::Dimension { dimension: token } => {
1863                let mut dimension =
1864                    String::with_capacity(token.raw_value.len() + token.raw_unit.len());
1865
1866                dimension.push_str(&token.raw_value);
1867                dimension.push_str(&token.raw_unit);
1868
1869                write_raw!(self, span, &dimension);
1870            }
1871            Token::Ident { raw, .. } => {
1872                write_raw!(self, span, raw);
1873            }
1874            Token::Function { raw, .. } => {
1875                let mut function = String::with_capacity(raw.len() + 1);
1876
1877                function.push_str(raw);
1878                function.push('(');
1879
1880                write_raw!(self, span, &function);
1881            }
1882            Token::BadString { raw } => {
1883                write_str!(self, span, raw);
1884            }
1885            Token::String { raw, .. } => {
1886                write_str!(self, span, raw);
1887            }
1888            Token::Url { raw, .. } => {
1889                let mut url = String::with_capacity(raw.0.len() + raw.1.len() + 2);
1890
1891                url.push_str(&raw.0);
1892                url.push('(');
1893                url.push_str(&raw.1);
1894                url.push(')');
1895
1896                write_str!(self, span, &url);
1897            }
1898            Token::BadUrl { raw, .. } => {
1899                write_str!(self, span, raw);
1900            }
1901            Token::Comma => {
1902                write_raw!(self, span, ",");
1903            }
1904            Token::Semi => {
1905                write_raw!(self, span, ";");
1906            }
1907            Token::LBrace => {
1908                write_raw!(self, span, "{");
1909            }
1910            Token::RBrace => {
1911                write_raw!(self, span, "}");
1912            }
1913            Token::Colon => {
1914                write_raw!(self, span, ":");
1915            }
1916            Token::Hash { raw, .. } => {
1917                let mut hash = String::with_capacity(raw.len() + 1);
1918
1919                hash.push('#');
1920                hash.push_str(raw);
1921
1922                write_raw!(self, span, &hash);
1923            }
1924            Token::WhiteSpace { value } => {
1925                write_str!(self, span, value);
1926            }
1927            Token::CDC => {
1928                write_raw!(self, span, "-->");
1929            }
1930            Token::CDO => {
1931                write_raw!(self, span, "<!--");
1932            }
1933        }
1934    }
1935
1936    #[emitter]
1937    fn emit_url(&mut self, n: &Url) -> Result {
1938        emit!(
1939            &mut *self.with_ctx(Ctx {
1940                allow_to_lowercase: true,
1941                ..self.ctx
1942            }),
1943            n.name
1944        );
1945        write_raw!(self, "(");
1946
1947        if let Some(value) = &n.value {
1948            emit!(self, value);
1949        }
1950
1951        if let Some(modifiers) = &n.modifiers {
1952            if !modifiers.is_empty() {
1953                if n.value.is_some() {
1954                    formatting_space!(self);
1955                }
1956
1957                self.emit_list(modifiers, ListFormat::SpaceDelimited)?;
1958            }
1959        }
1960
1961        write_raw!(self, ")");
1962    }
1963
1964    #[emitter]
1965    fn emit_url_value(&mut self, n: &UrlValue) -> Result {
1966        match n {
1967            UrlValue::Raw(n) => emit!(self, n),
1968            UrlValue::Str(n) => emit!(self, n),
1969        }
1970    }
1971
1972    #[emitter]
1973    fn emit_url_value_raw(&mut self, n: &UrlValueRaw) -> Result {
1974        write_str!(self, n.span, &serialize_url(&n.value));
1975    }
1976
1977    #[emitter]
1978    fn emit_url_modifier(&mut self, n: &UrlModifier) -> Result {
1979        match n {
1980            UrlModifier::Ident(n) => emit!(self, n),
1981            UrlModifier::Function(n) => emit!(self, n),
1982        }
1983    }
1984
1985    #[emitter]
1986    fn emit_unicode_range(&mut self, n: &UnicodeRange) -> Result {
1987        let mut value = String::with_capacity(
1988            n.start.len()
1989                + if let Some(end) = &n.end {
1990                    end.len() + 1
1991                } else {
1992                    0
1993                }
1994                + 2,
1995        );
1996
1997        value.push_str("u+");
1998        value.push_str(&n.start);
1999
2000        if let Some(end) = &n.end {
2001            value.push('-');
2002            value.push_str(end);
2003        }
2004
2005        write_raw!(self, n.span, &value);
2006    }
2007
2008    #[emitter]
2009    fn emit_family_name(&mut self, n: &FamilyName) -> Result {
2010        match n {
2011            FamilyName::Str(n) => emit!(self, n),
2012            FamilyName::SequenceOfCustomIdents(n) => emit!(self, n),
2013        }
2014    }
2015
2016    #[emitter]
2017    fn emit_sequence_of_custom_idents(&mut self, n: &SequenceOfCustomIdents) -> Result {
2018        self.emit_list(&n.value, ListFormat::SpaceDelimited)?;
2019    }
2020
2021    #[emitter]
2022    fn emit_selector_list(&mut self, n: &SelectorList) -> Result {
2023        self.emit_list(
2024            &n.children,
2025            if self.config.minify || self.ctx.in_single_line_selectors {
2026                ListFormat::CommaDelimited
2027            } else {
2028                ListFormat::CommaDelimited | ListFormat::MultiLine
2029            },
2030        )?;
2031    }
2032
2033    #[emitter]
2034    fn emit_forgiving_selector_list(&mut self, n: &ForgivingSelectorList) -> Result {
2035        for (idx, node) in n.children.iter().enumerate() {
2036            if idx != 0 {
2037                write_raw!(self, ",");
2038
2039                let need_space = matches!(node, ForgivingComplexSelector::ComplexSelector(_));
2040
2041                if need_space {
2042                    formatting_space!(self);
2043                }
2044            }
2045
2046            emit!(self, node)
2047        }
2048    }
2049
2050    #[emitter]
2051    fn emit_forgiving_complex_list(&mut self, n: &ForgivingComplexSelector) -> Result {
2052        match n {
2053            ForgivingComplexSelector::ComplexSelector(n) => emit!(self, n),
2054            ForgivingComplexSelector::ListOfComponentValues(n) => {
2055                emit!(
2056                    &mut *self.with_ctx(Ctx {
2057                        in_list_of_component_values: true,
2058                        ..self.ctx
2059                    }),
2060                    n
2061                )
2062            }
2063        }
2064    }
2065
2066    #[emitter]
2067    fn emit_compound_selector_list(&mut self, n: &CompoundSelectorList) -> Result {
2068        self.emit_list(&n.children, ListFormat::CommaDelimited)?;
2069    }
2070
2071    #[emitter]
2072    fn emit_relative_selector_list(&mut self, n: &RelativeSelectorList) -> Result {
2073        self.emit_list(&n.children, ListFormat::CommaDelimited)?;
2074    }
2075
2076    #[emitter]
2077    fn emit_forgiving_relative_selector_list(
2078        &mut self,
2079        n: &ForgivingRelativeSelectorList,
2080    ) -> Result {
2081        for (idx, node) in n.children.iter().enumerate() {
2082            if idx != 0 {
2083                write_raw!(self, ",");
2084
2085                let need_space = matches!(node, ForgivingRelativeSelector::RelativeSelector(_));
2086
2087                if need_space {
2088                    formatting_space!(self);
2089                }
2090            }
2091
2092            emit!(self, node)
2093        }
2094    }
2095
2096    #[emitter]
2097    fn emit_forgiving_relative_selector(&mut self, n: &ForgivingRelativeSelector) -> Result {
2098        match n {
2099            ForgivingRelativeSelector::RelativeSelector(n) => emit!(self, n),
2100            ForgivingRelativeSelector::ListOfComponentValues(n) => {
2101                emit!(
2102                    &mut *self.with_ctx(Ctx {
2103                        in_list_of_component_values: true,
2104                        ..self.ctx
2105                    }),
2106                    n
2107                )
2108            }
2109        }
2110    }
2111
2112    #[emitter]
2113    fn emit_complex_selector(&mut self, n: &ComplexSelector) -> Result {
2114        for (idx, node) in n.children.iter().enumerate() {
2115            emit!(self, node);
2116
2117            match node {
2118                ComplexSelectorChildren::Combinator(Combinator {
2119                    value: CombinatorValue::Descendant,
2120                    ..
2121                }) => {}
2122                _ => match n.children.get(idx + 1) {
2123                    Some(ComplexSelectorChildren::Combinator(Combinator {
2124                        value: CombinatorValue::Descendant,
2125                        ..
2126                    })) => {}
2127                    Some(_) => {
2128                        formatting_space!(self);
2129                    }
2130                    _ => {}
2131                },
2132            }
2133        }
2134    }
2135
2136    #[emitter]
2137    fn emit_relative_selector(&mut self, n: &RelativeSelector) -> Result {
2138        if let Some(combinator) = &n.combinator {
2139            emit!(self, combinator);
2140
2141            formatting_space!(self);
2142        }
2143
2144        emit!(self, n.selector);
2145    }
2146
2147    #[emitter]
2148    fn emit_complex_selector_children(&mut self, n: &ComplexSelectorChildren) -> Result {
2149        match n {
2150            ComplexSelectorChildren::CompoundSelector(n) => emit!(self, n),
2151            ComplexSelectorChildren::Combinator(n) => emit!(self, n),
2152        }
2153    }
2154
2155    #[emitter]
2156    fn emit_compound_selector(&mut self, n: &CompoundSelector) -> Result {
2157        emit!(self, n.nesting_selector);
2158        emit!(self, n.type_selector);
2159
2160        self.emit_list(&n.subclass_selectors, ListFormat::NotDelimited)?;
2161    }
2162
2163    #[emitter]
2164    fn emit_combinator(&mut self, n: &Combinator) -> Result {
2165        write_raw!(self, n.span, n.value.as_str());
2166    }
2167
2168    #[emitter]
2169    fn emit_nesting_selector(&mut self, n: &NestingSelector) -> Result {
2170        write_raw!(self, n.span, "&");
2171    }
2172
2173    #[emitter]
2174    fn emit_subclass_selector(&mut self, n: &SubclassSelector) -> Result {
2175        match n {
2176            SubclassSelector::Id(n) => emit!(self, n),
2177            SubclassSelector::Class(n) => emit!(self, n),
2178            SubclassSelector::Attribute(n) => emit!(self, n),
2179            SubclassSelector::PseudoClass(n) => emit!(self, n),
2180            SubclassSelector::PseudoElement(n) => emit!(self, n),
2181        }
2182    }
2183
2184    #[emitter]
2185    fn emit_type_selector(&mut self, n: &TypeSelector) -> Result {
2186        match n {
2187            TypeSelector::TagName(n) => emit!(self, n),
2188            TypeSelector::Universal(n) => emit!(self, n),
2189        }
2190    }
2191
2192    #[emitter]
2193    fn emit_tag_name_selector(&mut self, n: &TagNameSelector) -> Result {
2194        emit!(
2195            &mut *self.with_ctx(Ctx {
2196                allow_to_lowercase: true,
2197                ..self.ctx
2198            }),
2199            n.name
2200        );
2201    }
2202
2203    #[emitter]
2204    fn emit_universal_selector(&mut self, n: &UniversalSelector) -> Result {
2205        if let Some(prefix) = &n.prefix {
2206            emit!(self, prefix);
2207        }
2208
2209        write_raw!(self, hi_span_offset!(n.span, 1), "*");
2210    }
2211
2212    #[emitter]
2213    fn emit_namespace_prefix(&mut self, n: &NamespacePrefix) -> Result {
2214        if let Some(namespace) = &n.namespace {
2215            emit!(self, namespace);
2216        }
2217
2218        write_raw!(self, hi_span_offset!(n.span, 1), "|");
2219    }
2220
2221    #[emitter]
2222    fn emit_namespace(&mut self, n: &Namespace) -> Result {
2223        match n {
2224            Namespace::Named(n) => emit!(self, n),
2225            Namespace::Any(n) => emit!(self, n),
2226        }
2227    }
2228
2229    #[emitter]
2230    fn emit_named_namespace(&mut self, n: &NamedNamespace) -> Result {
2231        emit!(self, n.name);
2232    }
2233
2234    #[emitter]
2235    fn emit_any_namespace(&mut self, n: &AnyNamespace) -> Result {
2236        write_raw!(self, n.span, "*");
2237    }
2238
2239    #[emitter]
2240    fn emit_wq_name(&mut self, n: &WqName) -> Result {
2241        if n.prefix.is_some() {
2242            emit!(self, n.prefix);
2243        }
2244
2245        emit!(self, n.value);
2246    }
2247
2248    #[emitter]
2249    fn emit_id_selector(&mut self, n: &IdSelector) -> Result {
2250        write_raw!(self, lo_span_offset!(n.span, 1), "#");
2251        emit!(self, n.text);
2252    }
2253
2254    #[emitter]
2255    fn emit_class_selector(&mut self, n: &ClassSelector) -> Result {
2256        write_raw!(self, lo_span_offset!(n.span, 1), ".");
2257        emit!(self, n.text);
2258    }
2259
2260    #[emitter]
2261    fn emit_attribute_selector(&mut self, n: &AttributeSelector) -> Result {
2262        write_raw!(self, lo_span_offset!(n.span, 1), "[");
2263        emit!(self, n.name);
2264
2265        if n.matcher.is_some() {
2266            emit!(self, n.matcher);
2267            emit!(self, n.value);
2268
2269            if n.modifier.is_some() {
2270                match n.value {
2271                    Some(AttributeSelectorValue::Str(_)) => {
2272                        formatting_space!(self);
2273                    }
2274                    Some(AttributeSelectorValue::Ident(_)) => {
2275                        space!(self);
2276                    }
2277                    _ => {}
2278                }
2279
2280                emit!(self, n.modifier);
2281            }
2282        }
2283
2284        write_raw!(self, hi_span_offset!(n.span, 1), "]");
2285    }
2286
2287    #[emitter]
2288    fn emit_attribute_selector_matcher(&mut self, n: &AttributeSelectorMatcher) -> Result {
2289        write_raw!(self, n.span, n.value.as_str());
2290    }
2291
2292    #[emitter]
2293    fn emit_attribute_selector_value(&mut self, n: &AttributeSelectorValue) -> Result {
2294        match n {
2295            AttributeSelectorValue::Str(n) => emit!(self, n),
2296            AttributeSelectorValue::Ident(n) => emit!(self, n),
2297        }
2298    }
2299
2300    #[emitter]
2301    fn emit_attribute_selector_modifier(&mut self, n: &AttributeSelectorModifier) -> Result {
2302        emit!(
2303            &mut *self.with_ctx(Ctx {
2304                allow_to_lowercase: true,
2305                ..self.ctx
2306            }),
2307            n.value
2308        );
2309    }
2310
2311    #[emitter]
2312    fn emit_an_plus_b(&mut self, n: &AnPlusB) -> Result {
2313        match n {
2314            AnPlusB::Ident(n) => emit!(self, n),
2315            AnPlusB::AnPlusBNotation(n) => emit!(self, n),
2316        }
2317    }
2318
2319    #[emitter]
2320    fn emit_an_plus_b_notation(&mut self, n: &AnPlusBNotation) -> Result {
2321        let mut an_plus_b = String::with_capacity(4);
2322
2323        if let Some(a) = &n.a {
2324            if *a == -1 {
2325                an_plus_b.push('-');
2326            } else if *a != 1 {
2327                an_plus_b.push_str(&a.to_string());
2328            }
2329
2330            an_plus_b.push('n');
2331        }
2332
2333        if let Some(b) = &n.b {
2334            if *b >= 0 && n.a.is_some() {
2335                an_plus_b.push('+');
2336            }
2337
2338            an_plus_b.push_str(&b.to_string());
2339        }
2340
2341        write_raw!(self, n.span, &an_plus_b);
2342    }
2343
2344    #[emitter]
2345    fn emit_pseudo_class_selector(&mut self, n: &PseudoClassSelector) -> Result {
2346        write_raw!(self, lo_span_offset!(n.span, 1), ":");
2347        emit!(
2348            &mut *self.with_ctx(Ctx {
2349                allow_to_lowercase: true,
2350                ..self.ctx
2351            }),
2352            n.name
2353        );
2354
2355        if let Some(children) = &n.children {
2356            write_raw!(self, "(");
2357            self.emit_list_pseudo_class_selector_children(children)?;
2358            write_raw!(self, ")");
2359        }
2360    }
2361
2362    #[emitter]
2363    fn emit_pseudo_class_selector_children(&mut self, n: &PseudoClassSelectorChildren) -> Result {
2364        match n {
2365            PseudoClassSelectorChildren::PreservedToken(n) => emit!(self, n),
2366            PseudoClassSelectorChildren::AnPlusB(n) => emit!(self, n),
2367            PseudoClassSelectorChildren::Ident(n) => emit!(self, n),
2368            PseudoClassSelectorChildren::Str(n) => emit!(self, n),
2369            PseudoClassSelectorChildren::Delimiter(n) => emit!(self, n),
2370            PseudoClassSelectorChildren::ComplexSelector(n) => emit!(self, n),
2371            PseudoClassSelectorChildren::SelectorList(n) => emit!(
2372                &mut *self.with_ctx(Ctx {
2373                    in_single_line_selectors: true,
2374                    ..self.ctx
2375                }),
2376                n
2377            ),
2378            PseudoClassSelectorChildren::ForgivingSelectorList(n) => emit!(
2379                &mut *self.with_ctx(Ctx {
2380                    in_single_line_selectors: true,
2381                    ..self.ctx
2382                }),
2383                n
2384            ),
2385            PseudoClassSelectorChildren::CompoundSelectorList(n) => emit!(self, n),
2386            PseudoClassSelectorChildren::RelativeSelectorList(n) => emit!(self, n),
2387            PseudoClassSelectorChildren::ForgivingRelativeSelectorList(n) => emit!(self, n),
2388            PseudoClassSelectorChildren::CompoundSelector(n) => emit!(self, n),
2389        }
2390    }
2391
2392    fn emit_list_pseudo_class_selector_children(
2393        &mut self,
2394        nodes: &[PseudoClassSelectorChildren],
2395    ) -> Result {
2396        let len = nodes.len();
2397
2398        for (idx, node) in nodes.iter().enumerate() {
2399            emit!(self, node);
2400
2401            if idx != len - 1 {
2402                match node {
2403                    PseudoClassSelectorChildren::PreservedToken(_) => {}
2404                    PseudoClassSelectorChildren::Delimiter(_) => {
2405                        formatting_space!(self);
2406                    }
2407                    _ => {
2408                        let next = nodes.get(idx + 1);
2409
2410                        match next {
2411                            Some(PseudoClassSelectorChildren::Delimiter(Delimiter {
2412                                value: DelimiterValue::Comma,
2413                                ..
2414                            })) => {}
2415                            _ => {
2416                                space!(self)
2417                            }
2418                        }
2419                    }
2420                }
2421            }
2422        }
2423
2424        Ok(())
2425    }
2426
2427    #[emitter]
2428    fn emit_pseudo_element_selector(&mut self, n: &PseudoElementSelector) -> Result {
2429        write_raw!(self, lo_span_offset!(n.span, 1), ":");
2430        write_raw!(self, lo_span_offset!(n.span, 2), ":");
2431        emit!(
2432            &mut *self.with_ctx(Ctx {
2433                allow_to_lowercase: true,
2434                ..self.ctx
2435            }),
2436            n.name
2437        );
2438
2439        if let Some(children) = &n.children {
2440            write_raw!(self, "(");
2441            self.emit_list_pseudo_element_selector_children(children)?;
2442            write_raw!(self, ")");
2443        }
2444    }
2445
2446    #[emitter]
2447    fn emit_pseudo_element_selector_children(
2448        &mut self,
2449        n: &PseudoElementSelectorChildren,
2450    ) -> Result {
2451        match n {
2452            PseudoElementSelectorChildren::PreservedToken(n) => emit!(self, n),
2453            PseudoElementSelectorChildren::Ident(n) => emit!(self, n),
2454            PseudoElementSelectorChildren::CompoundSelector(n) => emit!(self, n),
2455            PseudoElementSelectorChildren::CustomHighlightName(n) => emit!(self, n),
2456        }
2457    }
2458
2459    #[emitter]
2460    fn emit_scope_range(&mut self, n: &ScopeRange) -> Result {
2461        if let Some(start) = &n.scope_start {
2462            formatting_space!(self);
2463            write_raw!(self, "(");
2464            emit!(self, start);
2465            write_raw!(self, ")");
2466        }
2467        if let Some(end) = &n.scope_end {
2468            write_raw!(self, " to");
2469            space!(self);
2470            write_raw!(self, "(");
2471            emit!(self, end);
2472            write_raw!(self, ")");
2473        }
2474    }
2475
2476    fn emit_list_pseudo_element_selector_children(
2477        &mut self,
2478        nodes: &[PseudoElementSelectorChildren],
2479    ) -> Result {
2480        let len = nodes.len();
2481
2482        for (idx, node) in nodes.iter().enumerate() {
2483            emit!(self, node);
2484
2485            if idx != len - 1 {
2486                match node {
2487                    PseudoElementSelectorChildren::PreservedToken(_) => {}
2488                    _ => {
2489                        space!(self)
2490                    }
2491                }
2492            }
2493        }
2494
2495        Ok(())
2496    }
2497
2498    fn emit_list<N>(&mut self, nodes: &[N], format: ListFormat) -> Result
2499    where
2500        Self: Emit<N>,
2501        N: Spanned,
2502    {
2503        for (idx, node) in nodes.iter().enumerate() {
2504            if idx != 0 {
2505                self.write_delim(format)?;
2506
2507                if format & ListFormat::LinesMask == ListFormat::MultiLine {
2508                    formatting_newline!(self);
2509                }
2510            }
2511
2512            emit!(self, node)
2513        }
2514
2515        Ok(())
2516    }
2517
2518    fn write_delim(&mut self, f: ListFormat) -> Result {
2519        match f & ListFormat::DelimitersMask {
2520            ListFormat::None => {}
2521            ListFormat::CommaDelimited => {
2522                write_raw!(self, ",");
2523                formatting_space!(self);
2524            }
2525            ListFormat::SpaceDelimited => {
2526                space!(self)
2527            }
2528            ListFormat::SemiDelimited => {
2529                write_raw!(self, ";")
2530            }
2531            ListFormat::DotDelimited => {
2532                write_raw!(self, ".");
2533            }
2534            _ => unreachable!(),
2535        }
2536
2537        Ok(())
2538    }
2539}
2540
2541fn minify_numeric(value: f64) -> String {
2542    if value.is_sign_negative() && value == 0.0 {
2543        return "-0".to_owned();
2544    }
2545    let mut minified = value.to_string();
2546
2547    if minified.starts_with("0.") {
2548        minified.replace_range(0..1, "");
2549    } else if minified.starts_with("-0.") {
2550        minified.replace_range(1..2, "");
2551    }
2552
2553    if minified.starts_with(".000") {
2554        let mut cnt = 3;
2555
2556        for &v in minified.as_bytes().iter().skip(4) {
2557            if v == b'0' {
2558                cnt += 1;
2559            } else {
2560                break;
2561            }
2562        }
2563
2564        minified.replace_range(0..cnt + 1, "");
2565
2566        let remain_len = minified.len();
2567
2568        minified.push_str("e-");
2569        minified.push_str(&(remain_len + cnt).to_string());
2570    } else if minified.ends_with("000") {
2571        let mut cnt = 3;
2572
2573        for &v in minified.as_bytes().iter().rev().skip(3) {
2574            if v == b'0' {
2575                cnt += 1;
2576            } else {
2577                break;
2578            }
2579        }
2580
2581        minified.truncate(minified.len() - cnt);
2582        minified.push('e');
2583        minified.push_str(&cnt.to_string());
2584    }
2585
2586    minified
2587}
2588
2589fn minify_hex_color(value: &str) -> String {
2590    let length = value.len();
2591
2592    if length == 6 || length == 8 {
2593        let chars = value.as_bytes();
2594
2595        if chars[0] == chars[1] && chars[2] == chars[3] && chars[4] == chars[5] {
2596            // 6 -> 3 or 8 -> 3
2597            if length == 6 || chars[6] == b'f' && chars[7] == b'f' {
2598                let mut minified = String::with_capacity(3);
2599
2600                minified.push(chars[0] as char);
2601                minified.push(chars[2] as char);
2602                minified.push(chars[4] as char);
2603
2604                return minified;
2605            }
2606            // 8 -> 4
2607            else if length == 8 && chars[6] == chars[7] {
2608                let mut minified = String::with_capacity(4);
2609
2610                minified.push(chars[0] as char);
2611                minified.push(chars[2] as char);
2612                minified.push(chars[4] as char);
2613                minified.push(chars[6] as char);
2614
2615                return minified;
2616            }
2617        }
2618    }
2619
2620    value.to_string()
2621}
2622
2623fn serialize_string(value: &str) -> String {
2624    let mut minified = String::with_capacity(value.len());
2625
2626    for c in value.chars() {
2627        match c {
2628            // If the character is NULL (U+0000), then the REPLACEMENT CHARACTER (U+FFFD).
2629            '\0' => {
2630                minified.push('\u{FFFD}');
2631            }
2632            // If the character is in the range [\1-\1f] (U+0001 to U+001F) or is U+007F, the
2633            // character escaped as code point.
2634            '\x01'..='\x1F' | '\x7F' => {
2635                static HEX_DIGITS: &[u8; 16] = b"0123456789abcdef";
2636
2637                let b3;
2638                let b4;
2639                let char_as_u8 = c as u8;
2640
2641                let bytes = if char_as_u8 > 0x0f {
2642                    let high = (char_as_u8 >> 4) as usize;
2643                    let low = (char_as_u8 & 0x0f) as usize;
2644
2645                    b4 = [b'\\', HEX_DIGITS[high], HEX_DIGITS[low], b' '];
2646
2647                    &b4[..]
2648                } else {
2649                    b3 = [b'\\', HEX_DIGITS[c as usize], b' '];
2650
2651                    &b3[..]
2652                };
2653
2654                minified.push_str(from_utf8(bytes).unwrap());
2655            }
2656            // If the character is '"' (U+0022) or "\" (U+005C), the escaped character.
2657            '\\' => {
2658                minified.push_str("\\\\");
2659            }
2660            '"' => {
2661                minified.push('\"');
2662            }
2663            // Otherwise, the character itself.
2664            _ => {
2665                minified.push(c);
2666            }
2667        };
2668    }
2669
2670    format!("\"{}\"", minified.replace('"', "\\\""))
2671}
2672
2673fn serialize_url(value: &str) -> String {
2674    let mut new_value = String::with_capacity(value.len());
2675
2676    for c in value.chars() {
2677        match c {
2678            '\x01'..='\x1F' | '\x7F' => {
2679                static HEX_DIGITS: &[u8; 16] = b"0123456789abcdef";
2680
2681                let b3;
2682                let b4;
2683                let char_as_u8 = c as u8;
2684
2685                let bytes = if char_as_u8 > 0x0f {
2686                    let high = (char_as_u8 >> 4) as usize;
2687                    let low = (char_as_u8 & 0x0f) as usize;
2688
2689                    b4 = [b'\\', HEX_DIGITS[high], HEX_DIGITS[low], b' '];
2690
2691                    &b4[..]
2692                } else {
2693                    b3 = [b'\\', HEX_DIGITS[c as usize], b' '];
2694
2695                    &b3[..]
2696                };
2697
2698                new_value.push_str(from_utf8(bytes).unwrap());
2699            }
2700            '(' | ')' | '"' | '\'' => {
2701                new_value.push('\\');
2702                new_value.push(c)
2703            }
2704            '\\' => {
2705                new_value.push_str("\\\\");
2706            }
2707            _ if c.is_whitespace() => {
2708                new_value.push('\\');
2709                new_value.push(c)
2710            }
2711            _ => {
2712                new_value.push(c);
2713            }
2714        };
2715    }
2716
2717    new_value
2718}
2719
2720fn minify_string(value: &str) -> String {
2721    let mut minified = String::with_capacity(value.len());
2722
2723    let mut dq = 0;
2724    let mut sq = 0;
2725
2726    for c in value.chars() {
2727        match c {
2728            // If the character is NULL (U+0000), then the REPLACEMENT CHARACTER (U+FFFD).
2729            '\0' => {
2730                minified.push('\u{FFFD}');
2731            }
2732            // If the character is in the range [\1-\1f] (U+0001 to U+001F) or is U+007F, the
2733            // character escaped as code point.
2734            '\x01'..='\x1F' | '\x7F' => {
2735                static HEX_DIGITS: &[u8; 16] = b"0123456789abcdef";
2736
2737                let b3;
2738                let b4;
2739                let char_as_u8 = c as u8;
2740
2741                let bytes = if char_as_u8 > 0x0f {
2742                    let high = (char_as_u8 >> 4) as usize;
2743                    let low = (char_as_u8 & 0x0f) as usize;
2744
2745                    b4 = [b'\\', HEX_DIGITS[high], HEX_DIGITS[low], b' '];
2746
2747                    &b4[..]
2748                } else {
2749                    b3 = [b'\\', HEX_DIGITS[c as usize], b' '];
2750
2751                    &b3[..]
2752                };
2753
2754                minified.push_str(from_utf8(bytes).unwrap());
2755            }
2756            // If the character is '"' (U+0022) or "\" (U+005C), the escaped character.
2757            // We avoid escaping `"` to better string compression - we count the quantity of
2758            // quotes to choose the best default quotes
2759            '\\' => {
2760                minified.push_str("\\\\");
2761            }
2762            '"' => {
2763                dq += 1;
2764
2765                minified.push(c);
2766            }
2767            '\'' => {
2768                sq += 1;
2769
2770                minified.push(c);
2771            }
2772            // Otherwise, the character itself.
2773            _ => {
2774                minified.push(c);
2775            }
2776        };
2777    }
2778
2779    if dq > sq {
2780        format!("'{}'", minified.replace('\'', "\\'"))
2781    } else {
2782        format!("\"{}\"", minified.replace('"', "\\\""))
2783    }
2784}
2785
2786fn serialize_dimension_unit(value: &str) -> Cow<'_, str> {
2787    // Fast-path
2788    let need_escape =
2789        (value.len() >= 2 && value.as_bytes()[0] == b'e' && value.as_bytes()[1].is_ascii_digit())
2790            || value.contains(char::REPLACEMENT_CHARACTER);
2791
2792    if !need_escape {
2793        return Cow::Borrowed(value);
2794    }
2795
2796    let mut result = String::with_capacity(value.len());
2797    let mut chars = value.chars().enumerate().peekable();
2798
2799    while let Some((i, c)) = chars.next() {
2800        match c {
2801            // Old browser hacks with `\0` and other - IE
2802            char::REPLACEMENT_CHARACTER => {
2803                result.push_str("\\0");
2804            }
2805            // The unit of a <dimension-token> may need escaping to disambiguate with scientific
2806            // notation.
2807            'e' if i == 0 => {
2808                if matches!(chars.peek(), Some((_, '0'..='9'))) {
2809                    result.push(c);
2810                    result.push_str("\\3");
2811                } else {
2812                    result.push(c);
2813                }
2814            }
2815            _ => {
2816                result.push(c);
2817            }
2818        }
2819    }
2820
2821    Cow::Owned(result)
2822}