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