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