1use swc_atoms::atom;
2use swc_common::{util::take::Take, Span, DUMMY_SP};
3use swc_css_ast::*;
4
5use super::Compressor;
6
7impl Compressor {
8 pub(super) fn compress_declaration(&self, declaration: &mut Declaration) {
9 if let DeclarationName::Ident(Ident { value: name, .. }) = &mut declaration.name {
10 *name = name.to_ascii_lowercase();
11
12 match &**name {
13 "display" if declaration.value.len() > 1 => {
14 let mut outside = None;
15 let mut inside = None;
16 let mut list_item = None;
17
18 for value in declaration.value.iter() {
19 match value {
20 outside_node @ ComponentValue::Ident(ident)
21 if matches_eq_ignore_ascii_case!(
22 ident.value,
23 "block",
24 "inline",
25 "run-in"
26 ) =>
27 {
28 outside = Some(outside_node);
29 }
30 inside_node @ ComponentValue::Ident(ident)
31 if matches_eq_ignore_ascii_case!(
32 ident.value,
33 "flow",
34 "flow-root",
35 "table",
36 "flex",
37 "grid",
38 "ruby"
39 ) =>
40 {
41 inside = Some(inside_node);
42 }
43 list_item_node @ ComponentValue::Ident(ident)
44 if ident.value.eq_ignore_ascii_case("list-item") =>
45 {
46 if let Some(ComponentValue::Ident(ident)) = inside {
47 if !matches_eq_ignore_ascii_case!(
48 ident.value,
49 "flow",
50 "flow-root"
51 ) {
52 continue;
53 }
54 }
55
56 list_item = Some(list_item_node)
57 }
58 _ => {}
59 }
60 }
61
62 match (outside, inside, list_item) {
63 (Some(outside), Some(ComponentValue::Ident(inside_ident)), None)
67 if inside_ident.value.eq_ignore_ascii_case("flow") =>
68 {
69 declaration.value = vec![outside.clone()];
70 }
71 (
73 Some(ComponentValue::Ident(outside_ident)),
74 Some(inside @ ComponentValue::Ident(inside_ident)),
75 None,
76 ) if outside_ident.value.eq_ignore_ascii_case("block")
77 && inside_ident.value.eq_ignore_ascii_case("flow-root") =>
78 {
79 declaration.value = vec![inside.clone()];
80 }
81 (
83 Some(ComponentValue::Ident(outside_ident)),
84 Some(ComponentValue::Ident(inside_ident)),
85 None,
86 ) if outside_ident.value.eq_ignore_ascii_case("inline")
87 && inside_ident.value.eq_ignore_ascii_case("flow-root") =>
88 {
89 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
90 span: outside_ident.span,
91 value: atom!("inline-block"),
92 raw: None,
93 }))];
94 }
95 (
97 Some(ComponentValue::Ident(outside_ident)),
98 Some(ComponentValue::Ident(inside_ident)),
99 Some(list_item),
100 ) if outside_ident.value.eq_ignore_ascii_case("block")
101 && inside_ident.value.eq_ignore_ascii_case("flow") =>
102 {
103 declaration.value = vec![list_item.clone()];
104 }
105 (Some(ComponentValue::Ident(outside_ident)), None, Some(list_item))
107 if outside_ident.value.eq_ignore_ascii_case("block") =>
108 {
109 declaration.value = vec![list_item.clone()];
110 }
111 (None, Some(ComponentValue::Ident(inside_ident)), Some(list_item))
113 if inside_ident.value.eq_ignore_ascii_case("flow") =>
114 {
115 declaration.value = vec![list_item.clone()];
116 }
117 (
119 Some(outside @ ComponentValue::Ident(outside_ident)),
120 Some(ComponentValue::Ident(inside_ident)),
121 Some(list_item),
122 ) if outside_ident.value.eq_ignore_ascii_case("inline")
123 && inside_ident.value.eq_ignore_ascii_case("flow") =>
124 {
125 declaration.value = vec![outside.clone(), list_item.clone()];
126 }
127 (
131 Some(ComponentValue::Ident(outside_ident)),
132 Some(inside @ ComponentValue::Ident(inside_ident)),
133 None,
134 ) if outside_ident.value.eq_ignore_ascii_case("block")
135 && matches_eq_ignore_ascii_case!(
136 inside_ident.value,
137 "flex",
138 "grid",
139 "table"
140 ) =>
141 {
142 declaration.value = vec![inside.clone()];
143 }
144 (
146 Some(ComponentValue::Ident(outside_ident)),
147 Some(inside @ ComponentValue::Ident(inside_ident)),
148 None,
149 ) if outside_ident.value.eq_ignore_ascii_case("inline")
150 && inside_ident.value.eq_ignore_ascii_case("ruby") =>
151 {
152 declaration.value = vec![inside.clone()];
153 }
154 _ => {}
155 }
156 }
157 "padding"
160 | "margin"
161 | "border-width"
162 | "inset"
163 | "scroll-margin"
164 | "scroll-padding"
165 | "mask-border-outset"
166 | "border-image-width"
167 | "border-image-outset"
168 | "border-image-slice"
169 if declaration.value.len() > 1 =>
170 {
171 let top = declaration.value.first();
172 let right = declaration
173 .value
174 .get(1)
175 .or_else(|| declaration.value.first());
176 let bottom = declaration
177 .value
178 .get(2)
179 .or_else(|| declaration.value.first());
180 let left = declaration
181 .value
182 .get(3)
183 .or_else(|| declaration.value.get(1))
184 .or_else(|| declaration.value.first());
185
186 if self.is_same_length_percentage_nodes(left, right) {
187 if self.is_same_length_percentage_nodes(bottom, top) {
188 if self.is_same_length_percentage_nodes(right, top) {
189 declaration.value = vec![top.unwrap().clone()];
190 } else {
191 declaration.value =
192 vec![top.unwrap().clone(), right.unwrap().clone()];
193 }
194 } else {
195 declaration.value = vec![
196 top.unwrap().clone(),
197 right.unwrap().clone(),
198 bottom.unwrap().clone(),
199 ];
200 }
201 }
202 }
203 "padding-inline"
204 | "padding-block"
205 | "margin-inline"
206 | "margin-block"
207 | "margin-inline"
208 | "inset-inline"
209 | "inset-block"
210 | "border-inline-width"
211 | "border-block-width"
212 | "scroll-padding-inline"
213 | "scroll-padding-block"
214 | "scroll-margin-inline"
215 | "scroll-margin-block"
216 | "border-top-left-radius"
217 | "border-top-right-radius"
218 | "border-bottom-right-radius"
219 | "border-bottom-left-radius"
220 | "border-start-start-radius"
221 | "border-start-end-radius"
222 | "border-end-start-radius"
223 | "border-end-end-radius"
224 if declaration.value.len() == 2 =>
225 {
226 let first = declaration.value.first();
227 let second = declaration.value.get(1);
228
229 if self.is_same_length_percentage_nodes(first, second)
230 || self.is_same_ident(first, second)
231 {
232 declaration.value.remove(1);
233 }
234 }
235 "border-style" if declaration.value.len() > 1 => {
236 let top = declaration.value.first();
237 let right = declaration
238 .value
239 .get(1)
240 .or_else(|| declaration.value.first());
241 let bottom = declaration
242 .value
243 .get(2)
244 .or_else(|| declaration.value.first());
245 let left = declaration
246 .value
247 .get(3)
248 .or_else(|| declaration.value.get(1))
249 .or_else(|| declaration.value.first());
250
251 if self.is_same_ident(left, right) {
252 if self.is_same_ident(bottom, top) {
253 if self.is_same_ident(right, top) {
254 declaration.value = vec![top.unwrap().clone()];
255 } else {
256 declaration.value =
257 vec![top.unwrap().clone(), right.unwrap().clone()];
258 }
259 } else {
260 declaration.value = vec![
261 top.unwrap().clone(),
262 right.unwrap().clone(),
263 bottom.unwrap().clone(),
264 ];
265 }
266 }
267 }
268 "border-spacing" | "border-image-repeat" if declaration.value.len() == 2 => {
269 let first = declaration.value.first();
270 let second = declaration.value.get(1);
271
272 if self.is_same_length_nodes(first, second) {
273 declaration.value.remove(1);
274 }
275 }
276 "font-weight" => {
277 declaration.value = declaration
278 .value
279 .take()
280 .into_iter()
281 .map(|node| match node {
282 ComponentValue::Ident(ident)
283 if ident.value.eq_ignore_ascii_case("normal") =>
284 {
285 ComponentValue::Integer(Box::new(Integer {
286 span: ident.span,
287 value: 400,
288 raw: None,
289 }))
290 }
291 ComponentValue::Ident(ident)
292 if ident.value.eq_ignore_ascii_case("bold") =>
293 {
294 ComponentValue::Integer(Box::new(Integer {
295 span: ident.span,
296 value: 700,
297 raw: None,
298 }))
299 }
300 _ => node,
301 })
302 .collect();
303 }
304 "background-repeat" | "mask-repeat" | "-webkit-mask-repeat"
305 if declaration.value.len() == 2 =>
306 {
307 let first = declaration.value.first();
308 let second = declaration.value.get(1);
309
310 if let (
311 Some(ComponentValue::Ident(first_ident)),
312 Some(ComponentValue::Ident(second_ident)),
313 ) = (first, second)
314 {
315 match (
316 &*first_ident.value.to_ascii_lowercase(),
317 &*second_ident.value.to_ascii_lowercase(),
318 ) {
319 ("repeat", "no-repeat") => {
320 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
321 span: first_ident.span,
322 value: atom!("repeat-x"),
323 raw: None,
324 }))];
325 }
326 ("no-repeat", "repeat") => {
327 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
328 span: first_ident.span,
329 value: atom!("repeat-y"),
330 raw: None,
331 }))];
332 }
333 ("repeat", "repeat")
334 | ("space", "space")
335 | ("round", "round")
336 | ("no-repeat", "no-repeat") => {
337 declaration.value.remove(1);
338 }
339 _ => {}
340 }
341 }
342 }
343 "border-image-repeat"
344 | "mask-border-repeat"
345 | "-webkit-mask-box-image-repeat"
346 | "overscroll-behavior"
347 | "scroll-snap-align"
348 | "overflow"
349 | "place-self"
350 | "place-items"
351 | "place-content"
352 if declaration.value.len() == 2 =>
353 {
354 let first = declaration.value.first();
355 let second = declaration.value.get(1);
356
357 if self.is_same_ident(first, second) {
358 declaration.value.remove(1);
359 }
360 }
361 "animation" if !declaration.value.is_empty() => {
362 let first = declaration.value.first().cloned();
363 if let Some(ComponentValue::Str(ident)) = first {
364 declaration.value.remove(0);
365 match &*ident.value.to_ascii_lowercase() {
366 _ if crate::is_css_wide_keyword(&ident.value)
367 || ident.value.eq_ignore_ascii_case("none") =>
368 {
369 declaration.value.insert(0, ComponentValue::Str(ident));
370 }
371 to_be_identify => {
372 declaration.value.insert(
373 0,
374 if self.is_ident_shorter_than_str(to_be_identify) {
375 ComponentValue::Ident(Box::new(Ident {
376 span: ident.span,
377 value: to_be_identify.into(),
378 raw: None,
379 }))
380 } else {
381 ComponentValue::Str(Box::new(Str {
382 span: ident.span,
383 value: to_be_identify.into(),
384 raw: None,
385 }))
386 },
387 );
388 }
389 }
390 }
391 }
392 "animation-name" => {
393 declaration.value = declaration
394 .value
395 .take()
396 .into_iter()
397 .map(|node| match node {
398 ComponentValue::Str(ref ident) => {
399 let value = ident.value.to_ascii_lowercase();
400 match &*value {
401 _ if crate::is_css_wide_keyword(&ident.value)
402 || ident.value.eq_ignore_ascii_case("none") =>
403 {
404 node
405 }
406 to_be_identify => {
407 if self.is_ident_shorter_than_str(to_be_identify) {
408 ComponentValue::Ident(Box::new(Ident {
409 span: ident.span,
410 value: to_be_identify.into(),
411 raw: None,
412 }))
413 } else {
414 ComponentValue::Str(Box::new(Str {
415 span: ident.span,
416 value: to_be_identify.into(),
417 raw: None,
418 }))
419 }
420 }
421 }
422 }
423 _ => node,
424 })
425 .collect();
426 }
427 _ => {}
428 }
429
430 let is_initial = if let Some(ComponentValue::Ident(ident)) = declaration.value.first() {
431 if ident.value.eq_ignore_ascii_case("initial") {
432 Some(ident.span)
433 } else {
434 None
435 }
436 } else {
437 None
438 };
439
440 if let Some(span) = is_initial {
441 self.compress_from_initial(declaration, span);
442 }
443 }
448 }
449
450 fn is_same_length_nodes(
451 &self,
452 node_1: Option<&ComponentValue>,
453 node_2: Option<&ComponentValue>,
454 ) -> bool {
455 let Some(node_1) = node_1 else { return false };
456 let Some(node_2) = node_2 else { return false };
457
458 match (node_1, node_2) {
459 (ComponentValue::Dimension(dimension_1), ComponentValue::Dimension(dimension_2)) => {
460 let result_1 = dimension_1
461 .as_length()
462 .map(|length| (&length.value.value, &length.unit.value));
463
464 let result_2 = dimension_2
465 .as_length()
466 .map(|length| (&length.value.value, &length.unit.value));
467
468 result_1.is_some() && result_1 == result_2
469 }
470 (ComponentValue::Integer(integer_1), ComponentValue::Integer(integer_2)) => {
471 integer_1.value == 0 && integer_2.value == 0
472 }
473 (ComponentValue::Number(number_1), ComponentValue::Number(number_2)) => {
474 number_1.value == number_2.value
475 }
476 _ => false,
477 }
478 }
479
480 fn is_same_length_percentage_nodes(
481 &self,
482 node_1: Option<&ComponentValue>,
483 node_2: Option<&ComponentValue>,
484 ) -> bool {
485 let Some(node_1) = node_1 else { return false };
486 let Some(node_2) = node_2 else { return false };
487
488 match (node_1, node_2) {
489 (ComponentValue::Dimension(dimension_1), ComponentValue::Dimension(dimension_2)) => {
490 let Some(result_1) = dimension_1.as_length() else {
491 return false;
492 };
493
494 let Some(result_2) = dimension_2.as_length() else {
495 return false;
496 };
497
498 result_1.value.value == result_2.value.value
499 && result_1
500 .unit
501 .value
502 .eq_ignore_ascii_case(&result_2.unit.value)
503 }
504 (
505 ComponentValue::Percentage(percentage_1),
506 ComponentValue::Percentage(percentage_2),
507 ) => percentage_1.value.value == percentage_2.value.value,
508 (ComponentValue::Integer(integer_1), ComponentValue::Integer(integer_2)) => {
509 integer_1.value == 0 && integer_2.value == 0
510 }
511 (ComponentValue::Number(number_1), ComponentValue::Number(number_2)) => {
512 number_1.value == number_2.value
513 }
514 _ => false,
515 }
516 }
517
518 fn is_same_ident(
519 &self,
520 node_1: Option<&ComponentValue>,
521 node_2: Option<&ComponentValue>,
522 ) -> bool {
523 let Some(node_1) = node_1 else { return false };
524 let Some(node_2) = node_2 else { return false };
525
526 let Some(value_1) = node_1.as_ident().map(|ident| &ident.value) else {
527 return false;
528 };
529 let Some(value_2) = node_2.as_ident().map(|ident| &ident.value) else {
530 return false;
531 };
532
533 value_1.eq_ignore_ascii_case(value_2)
534 }
535
536 fn compress_from_initial(&self, declaration: &mut Declaration, span: Span) {
537 let name = if let DeclarationName::Ident(Ident { value, .. }) = &declaration.name {
538 value
539 } else {
540 return;
541 };
542
543 match &**name {
544 "accent-color"
545 | "align-self"
546 | "animation-timeline"
547 | "aspect-ratio"
548 | "block-size"
549 | "bottom"
550 | "break-after"
551 | "break-before"
552 | "break-inside"
553 | "caret-color"
554 | "caret-shape"
555 | "clip"
556 | "column-count"
557 | "column-width"
558 | "cursor"
559 | "flex-basis"
560 | "font-kerning"
561 | "font-optical-sizing"
562 | "forced-color-adjust"
563 | "grid-auto-columns"
564 | "grid-auto-rows"
565 | "grid-column-end"
566 | "grid-column-start"
567 | "grid-row-end"
568 | "grid-row-start"
569 | "height"
570 | "hyphenate-character"
571 | "image-rendering"
572 | "ime-mode"
573 | "initial-letter-align"
574 | "inline-size"
575 | "input-security"
576 | "inset"
577 | "inset-block"
578 | "inset-block-end"
579 | "inset-block-start"
580 | "inset-inline"
581 | "inset-inline-end"
582 | "inset-inline-start"
583 | "isolation"
584 | "justify-self"
585 | "left"
586 | "line-break"
587 | "mask-border-width"
588 | "mask-size"
589 | "min-height"
590 | "min-width"
591 | "offset-anchor"
592 | "offset-position"
593 | "offset-rotate"
594 | "overflow-anchor"
595 | "overflow-block"
596 | "overflow-inline"
597 | "overscroll-behavior"
598 | "overscroll-behavior-block"
599 | "overscroll-behavior-inline"
600 | "overscroll-behavior-x"
601 | "overscroll-behavior-y"
602 | "page-break-after"
603 | "page-break-before"
604 | "page-break-inside"
605 | "pointer-events"
606 | "right"
607 | "scrollbar-color"
608 | "scrollbar-gutter"
609 | "scrollbar-width"
610 | "scroll-behavior"
611 | "scroll-padding"
612 | "scroll-padding-block"
613 | "scroll-padding-block-start"
614 | "scroll-padding-block-end"
615 | "scroll-padding-bottom"
616 | "scroll-padding-inline"
617 | "scroll-padding-inline-start"
618 | "scroll-padding-inline-end"
619 | "scroll-padding-left"
620 | "scroll-padding-right"
621 | "scroll-padding-top"
622 | "table-layout"
623 | "text-align-last"
624 | "text-decoration-skip-ink"
625 | "text-decoration-thickness"
626 | "text-justify"
627 | "text-rendering"
628 | "text-underline-offset"
629 | "text-underline-position"
630 | "top"
631 | "touch-action"
632 | "user-select"
633 | "width"
634 | "will-change"
635 | "z-index" => {
636 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
637 span,
638 value: atom!("auto"),
639 raw: None,
640 }))];
641 }
642 "-webkit-line-clamp"
643 | "animation-fill-mode"
644 | "animation-name"
645 | "appearance"
646 | "backdrop-filter"
647 | "background-image"
648 | "border-block-style"
649 | "border-block-end-style"
650 | "border-block-start-style"
651 | "border-bottom-style"
652 | "border-image-source"
653 | "border-inline-style"
654 | "border-inline-end-style"
655 | "border-inline-start-style"
656 | "border-left-style"
657 | "border-right-style"
658 | "border-top-style"
659 | "box-shadow"
660 | "clear"
661 | "clip-path"
662 | "column-rule-style"
663 | "column-span"
664 | "contain"
665 | "contain-intrinsic-block-size"
666 | "contain-intrinsic-height"
667 | "contain-intrinsic-inline-size"
668 | "contain-intrinsic-width"
669 | "counter-increment"
670 | "counter-reset"
671 | "counter-set"
672 | "filter"
673 | "float"
674 | "font-size-adjust"
675 | "grid-template-areas"
676 | "grid-template-columns"
677 | "grid-template-rows"
678 | "hanging-punctuation"
679 | "line-clamp"
680 | "list-style-image"
681 | "margin-trim"
682 | "mask-border-source"
683 | "mask-image"
684 | "max-block-size"
685 | "max-height"
686 | "max-inline-size"
687 | "max-lines"
688 | "max-width"
689 | "offset-path"
690 | "outline-style"
691 | "perspective"
692 | "resize"
693 | "rotate"
694 | "scale"
695 | "scroll-snap-align"
696 | "scroll-snap-coordinate"
697 | "scroll-snap-points-x"
698 | "scroll-snap-points-y"
699 | "scroll-snap-type"
700 | "scroll-snap-type-x"
701 | "scroll-snap-type-y"
702 | "scroll-timeline-name"
703 | "shape-outside"
704 | "text-combine-upright"
705 | "text-decoration-line"
706 | "text-emphasis-style"
707 | "text-shadow"
708 | "text-transform"
709 | "transform"
710 | "translate" => {
711 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
712 span,
713 value: atom!("none"),
714 raw: None,
715 }))];
716 }
717 "align-content"
718 | "align-items"
719 | "align-tracks"
720 | "animation-direction"
721 | "background-blend-mode"
722 | "color-scheme"
723 | "column-gap"
724 | "content"
725 | "font-feature-settings"
726 | "font-language-override"
727 | "font-variation-settings"
728 | "font-stretch"
729 | "font-style"
730 | "font-variant"
731 | "font-variant-alternates"
732 | "font-variant-caps"
733 | "font-variant-east-asian"
734 | "font-variant-ligatures"
735 | "font-variant-numeric"
736 | "font-variant-position"
737 | "font-weight"
738 | "initial-letter"
739 | "justify-content"
740 | "justify-tracks"
741 | "letter-spacing"
742 | "line-height"
743 | "math-shift"
744 | "math-style"
745 | "mix-blend-mode"
746 | "overflow-wrap"
747 | "paint-order"
748 | "place-content"
749 | "row-gap"
750 | "scroll-snap-stop"
751 | "unicode-bidi"
752 | "white-space"
753 | "word-break"
754 | "word-spacing"
755 | "word-wrap"
756 | "grid-row-gap"
757 | "grid-column-gap" => {
758 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
759 span,
760 value: atom!("normal"),
761 raw: None,
762 }))];
763 }
764 "animation-delay"
765 | "animation-duration"
766 | "transition-delay"
767 | "transition-duration" => {
768 declaration.value =
769 vec![ComponentValue::Dimension(Box::new(Dimension::Time(Time {
770 span,
771 value: Number {
772 span: DUMMY_SP,
773 value: 0.0,
774 raw: None,
775 },
776 unit: Ident {
777 span: DUMMY_SP,
778 value: atom!("s"),
779 raw: None,
780 },
781 })))];
782 }
783 "shape-image-threshold" | "opacity" => {
784 declaration.value = vec![ComponentValue::AlphaValue(Box::new(AlphaValue::Number(
785 Number {
786 span,
787 value: 0.0,
788 raw: None,
789 },
790 )))];
791 }
792 "animation-iteration-count" => {
793 declaration.value = vec![ComponentValue::Number(Box::new(Number {
794 span,
795 value: 1.0,
796 raw: None,
797 }))];
798 }
799 "animation-timing-function" | "transition-timing-function" => {
800 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
801 span,
802 value: atom!("ease"),
803 raw: None,
804 }))];
805 }
806 "azimuth" | "mask-position" => {
807 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
808 span,
809 value: atom!("center"),
810 raw: None,
811 }))];
812 }
813 "background-attachment" => {
814 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
815 span,
816 value: atom!("scroll"),
817 raw: None,
818 }))];
819 }
820 "background-position" => {
821 declaration.value = vec![
822 ComponentValue::Percentage(Box::new(Percentage {
823 span,
824 value: Number {
825 span: DUMMY_SP,
826 value: 0.0,
827 raw: None,
828 },
829 })),
830 ComponentValue::Percentage(Box::new(Percentage {
831 span,
832 value: Number {
833 span: DUMMY_SP,
834 value: 0.0,
835 raw: None,
836 },
837 })),
838 ];
839 }
840 "background-position-x" | "background-position-y" => {
841 declaration.value = vec![ComponentValue::Percentage(Box::new(Percentage {
842 span,
843 value: Number {
844 span: DUMMY_SP,
845 value: 0.0,
846 raw: None,
847 },
848 }))];
849 }
850 "background-repeat" | "mask-repeat" => {
851 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
852 span,
853 value: atom!("repeat"),
854 raw: None,
855 }))];
856 }
857 "block-overflow" => {
858 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
859 span,
860 value: atom!("clip"),
861 raw: None,
862 }))];
863 }
864 "border-block-width"
865 | "border-block-end-width"
866 | "border-block-start-width"
867 | "border-bottom-width"
868 | "border-inline-width"
869 | "border-inline-end-width"
870 | "border-inline-start-width"
871 | "border-left-width"
872 | "border-right-width"
873 | "border-top-width"
874 | "column-rule-width"
875 | "font-size"
876 | "outline-width" => {
877 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
878 span,
879 value: atom!("medium"),
880 raw: None,
881 }))];
882 }
883 "border-top-left-radius"
884 | "border-top-right-radius"
885 | "border-start-end-radius"
886 | "border-start-start-radius"
887 | "border-bottom-left-radius"
888 | "border-bottom-right-radius"
889 | "border-end-end-radius"
890 | "border-end-start-radius"
891 | "shape-margin"
892 | "offset-distance" => {
893 declaration.value = vec![ComponentValue::LengthPercentage(Box::new(
894 LengthPercentage::Length(Length {
895 span,
896 value: Number {
897 span: DUMMY_SP,
898 value: 0.0,
899 raw: None,
900 },
901 unit: Ident {
902 span: DUMMY_SP,
903 value: atom!("px"),
904 raw: None,
905 },
906 }),
907 ))];
908 }
909 "padding-block"
910 | "padding-block-end"
911 | "padding-block-start"
912 | "padding-bottom"
913 | "padding-inline"
914 | "padding-inline-end"
915 | "padding-inline-start"
916 | "padding-left"
917 | "padding-right"
918 | "padding-top"
919 | "padding"
920 | "margin-block"
921 | "margin-block-end"
922 | "margin-block-start"
923 | "margin-bottom"
924 | "margin-inline"
925 | "margin-inline-end"
926 | "margin-inline-start"
927 | "margin-left"
928 | "margin-right"
929 | "margin-top"
930 | "margin"
931 | "scroll-margin"
932 | "scroll-margin-block"
933 | "scroll-margin-block-start"
934 | "scroll-margin-block-end"
935 | "scroll-margin-bottom"
936 | "scroll-margin-inline"
937 | "scroll-margin-inline-start"
938 | "scroll-margin-inline-end"
939 | "scroll-margin-left"
940 | "scroll-margin-right"
941 | "scroll-margin-top"
942 | "min-inline-size"
943 | "min-block-size"
944 | "border-image-outset"
945 | "text-indent"
946 | "outline-offset"
947 | "line-height-step"
948 | "border-spacing" => {
949 declaration.value = vec![ComponentValue::Dimension(Box::new(Dimension::Length(
950 Length {
951 span,
952 value: Number {
953 span: DUMMY_SP,
954 value: 0.0,
955 raw: None,
956 },
957 unit: Ident {
958 span: DUMMY_SP,
959 value: atom!("px"),
960 raw: None,
961 },
962 },
963 )))];
964 }
965 "flex-direction" | "grid-auto-flow" => {
966 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
967 span,
968 value: atom!("row"),
969 raw: None,
970 }))];
971 }
972 "mask-border-slice" | "mask-border-outset" => {
973 declaration.value = vec![ComponentValue::Number(Box::new(Number {
974 span,
975 value: 0.0,
976 raw: None,
977 }))];
978 }
979 "border-image-slice" => {
980 declaration.value = vec![ComponentValue::Percentage(Box::new(Percentage {
981 span,
982 value: Number {
983 span: DUMMY_SP,
984 value: 100.0,
985 raw: None,
986 },
987 }))];
988 }
989 "border-image-width" => {
990 declaration.value = vec![ComponentValue::Number(Box::new(Number {
991 span,
992 value: 1.0,
993 raw: None,
994 }))];
995 }
996 "box-decoration-break" => {
997 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
998 span,
999 value: atom!("slice"),
1000 raw: None,
1001 }))];
1002 }
1003 "caption-side" => {
1004 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
1005 span,
1006 value: atom!("top"),
1007 raw: None,
1008 }))];
1009 }
1010 "direction" => {
1011 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
1012 span,
1013 value: atom!("ltr"),
1014 raw: None,
1015 }))];
1016 }
1017 "empty-cells" => {
1018 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
1019 span,
1020 value: atom!("show"),
1021 raw: None,
1022 }))];
1023 }
1024 "flex-grow" => {
1025 declaration.value = vec![ComponentValue::Number(Box::new(Number {
1026 span,
1027 value: 0.0,
1028 raw: None,
1029 }))];
1030 }
1031 "flex-shrink" => {
1032 declaration.value = vec![ComponentValue::Number(Box::new(Number {
1033 span,
1034 value: 1.0,
1035 raw: None,
1036 }))];
1037 }
1038 "flex-wrap" => {
1039 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
1040 span,
1041 value: atom!("nowrap"),
1042 raw: None,
1043 }))];
1044 }
1045 "hyphens" => {
1046 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
1047 span,
1048 value: atom!("manual"),
1049 raw: None,
1050 }))];
1051 }
1052 "image-resolution" => {
1053 declaration.value = vec![ComponentValue::Dimension(Box::new(
1054 Dimension::Resolution(Resolution {
1055 span,
1056 value: Number {
1057 span: DUMMY_SP,
1058 value: 1.0,
1059 raw: None,
1060 },
1061 unit: Ident {
1062 span: DUMMY_SP,
1063 value: atom!("dppx"),
1064 raw: None,
1065 },
1066 }),
1067 ))];
1068 }
1069 "justify-items" => {
1070 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
1071 span,
1072 value: atom!("legacy"),
1073 raw: None,
1074 }))];
1075 }
1076 "list-style-type" => {
1077 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
1078 span,
1079 value: atom!("disk"),
1080 raw: None,
1081 }))];
1082 }
1083 "mask-border-mode" => {
1084 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
1085 span,
1086 value: atom!("alpha"),
1087 raw: None,
1088 }))];
1089 }
1090 "mask-composite" => {
1091 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
1092 span,
1093 value: atom!("add"),
1094 raw: None,
1095 }))];
1096 }
1097 "masonry-auto-flow" => {
1098 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
1099 span,
1100 value: atom!("pack"),
1101 raw: None,
1102 }))];
1103 }
1104 "math-depth" | "order" => {
1105 declaration.value = vec![ComponentValue::Integer(Box::new(Integer {
1106 span,
1107 value: 0,
1108 raw: None,
1109 }))];
1110 }
1111 "object-fit" => {
1112 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
1113 span,
1114 value: atom!("fill"),
1115 raw: None,
1116 }))];
1117 }
1118 "overflow-clip-margin" => {
1119 declaration.value = vec![ComponentValue::Dimension(Box::new(Dimension::Length(
1120 Length {
1121 span,
1122 value: Number {
1123 span: DUMMY_SP,
1124 value: 0.0,
1125 raw: None,
1126 },
1127 unit: Ident {
1128 span: DUMMY_SP,
1129 value: atom!("px"),
1130 raw: None,
1131 },
1132 },
1133 )))];
1134 }
1135 "position" => {
1136 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
1137 span,
1138 value: atom!("static"),
1139 raw: None,
1140 }))];
1141 }
1142 "scroll-timeline-axis" => {
1143 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
1144 span,
1145 value: atom!("block"),
1146 raw: None,
1147 }))];
1148 }
1149 "tab-size" => {
1150 declaration.value = vec![ComponentValue::Number(Box::new(Number {
1151 span: DUMMY_SP,
1152 value: 8.0,
1153 raw: None,
1154 }))];
1155 }
1156 "text-decoration-style" => {
1157 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
1158 span,
1159 value: atom!("solid"),
1160 raw: None,
1161 }))];
1162 }
1163 "text-orientation" => {
1164 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
1165 span,
1166 value: atom!("mixed"),
1167 raw: None,
1168 }))];
1169 }
1170 "text-overflow" => {
1171 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
1172 span,
1173 value: atom!("clip"),
1174 raw: None,
1175 }))];
1176 }
1177 "transform-style" => {
1178 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
1179 span,
1180 value: atom!("flat"),
1181 raw: None,
1182 }))];
1183 }
1184 "transition-property" => {
1185 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
1186 span,
1187 value: atom!("all"),
1188 raw: None,
1189 }))];
1190 }
1191 "orphans" | "widows" => {
1192 declaration.value = vec![ComponentValue::Integer(Box::new(Integer {
1193 span,
1194 value: 2,
1195 raw: None,
1196 }))];
1197 }
1198 _ => {}
1199 }
1200 }
1201
1202 fn _compress_to_initial(&self, declaration: &mut Declaration) {
1203 let name = if let DeclarationName::Ident(Ident { value, .. }) = &declaration.name {
1204 value
1205 } else {
1206 return;
1207 };
1208
1209 match &**name {
1210 "background-clip" | "mask-clip" | "mask-origin" => {
1211 if let Some(ComponentValue::Ident(ident)) = declaration.value.first() {
1212 if ident.value.eq_ignore_ascii_case("border-box") {
1213 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
1214 span: ident.span,
1215 value: atom!("initial"),
1216 raw: None,
1217 }))];
1218 }
1219 }
1220 }
1221 "background-color" => {
1222 if let Some(ComponentValue::Ident(ident)) = declaration.value.first() {
1223 if ident.value.eq_ignore_ascii_case("transparent") {
1224 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
1225 span: ident.span,
1226 value: atom!("initial"),
1227 raw: None,
1228 }))];
1229 }
1230 }
1231 }
1232 "background-origin" => {
1233 if let Some(ComponentValue::Ident(ident)) = declaration.value.first() {
1234 if ident.value.eq_ignore_ascii_case("padding-box") {
1235 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
1236 span: ident.span,
1237 value: atom!("initial"),
1238 raw: None,
1239 }))];
1240 }
1241 }
1242 }
1243 "background-size" => {
1244 if let (Some(ComponentValue::Ident(first)), Some(ComponentValue::Ident(second))) =
1245 (declaration.value.first(), declaration.value.get(1))
1246 {
1247 if first.value.eq_ignore_ascii_case("auto")
1248 && second.value.eq_ignore_ascii_case("auto")
1249 && declaration.value.len() == 2
1250 {
1251 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
1252 span: first.span,
1253 value: atom!("initial"),
1254 raw: None,
1255 }))];
1256 }
1257 }
1258 }
1259 "border-block-color"
1260 | "border-block-start-color"
1261 | "border-block-end-color"
1262 | "border-inline-color"
1263 | "border-inline-start-color"
1264 | "border-inline-end-color"
1265 | "border-bottom-color"
1266 | "border-left-color"
1267 | "border-right-color"
1268 | "border-top-color"
1269 | "column-rule-color"
1270 | "text-emphasis-color"
1271 | "text-decoration-color" => {
1272 if let Some(ComponentValue::Ident(ident)) = declaration.value.first() {
1273 if ident.value.eq_ignore_ascii_case("currentcolor") {
1274 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
1275 span: ident.span,
1276 value: atom!("initial"),
1277 raw: None,
1278 }))];
1279 }
1280 }
1281 }
1282 "border-collapse" => {
1283 if let Some(ComponentValue::Ident(ident)) = declaration.value.first() {
1284 if ident.value.eq_ignore_ascii_case("separate") {
1285 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
1286 span: ident.span,
1287 value: atom!("initial"),
1288 raw: None,
1289 }))];
1290 }
1291 }
1292 }
1293 "box-sizing" => {
1294 if let Some(ComponentValue::Ident(ident)) = declaration.value.first() {
1295 if ident.value.eq_ignore_ascii_case("content-box") {
1296 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
1297 span: ident.span,
1298 value: atom!("initial"),
1299 raw: None,
1300 }))];
1301 }
1302 }
1303 }
1304 "color" => {
1305 if let Some(ComponentValue::Ident(ident)) = declaration.value.first() {
1306 if ident.value.eq_ignore_ascii_case("canvastext") {
1307 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
1308 span: ident.span,
1309 value: atom!("initial"),
1310 raw: None,
1311 }))];
1312 }
1313 }
1314 }
1315 "font-synthesis" => {
1316 if let (Some(ComponentValue::Ident(first)), Some(ComponentValue::Ident(second))) =
1317 (declaration.value.first(), declaration.value.get(1))
1318 {
1319 if first.value.eq_ignore_ascii_case("weight")
1320 && second.value.eq_ignore_ascii_case("style")
1321 && declaration.value.len() == 2
1322 {
1323 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
1324 span: first.span,
1325 value: atom!("initial"),
1326 raw: None,
1327 }))];
1328 }
1329 }
1330 }
1331 "image-orientation" => {
1332 if let Some(ComponentValue::Ident(ident)) = declaration.value.first() {
1333 if ident.value.eq_ignore_ascii_case("from-image") {
1334 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
1335 span: ident.span,
1336 value: atom!("initial"),
1337 raw: None,
1338 }))];
1339 }
1340 }
1341 }
1342 "mask-mode" => {
1343 if let Some(ComponentValue::Ident(ident)) = declaration.value.first() {
1344 if ident.value.eq_ignore_ascii_case("match-source")
1345 && declaration.value.len() == 1
1346 {
1347 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
1348 span: ident.span,
1349 value: atom!("initial"),
1350 raw: None,
1351 }))];
1352 }
1353 }
1354 }
1355 "mask-type" => {
1356 if let Some(ComponentValue::Ident(ident)) = declaration.value.first() {
1357 if ident.value.eq_ignore_ascii_case("luminance") {
1358 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
1359 span: ident.span,
1360 value: atom!("initial"),
1361 raw: None,
1362 }))];
1363 }
1364 }
1365 }
1366 "ruby-align" => {
1367 if let Some(ComponentValue::Ident(ident)) = declaration.value.first() {
1368 if ident.value.eq_ignore_ascii_case("space-around") {
1369 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
1370 span: ident.span,
1371 value: atom!("initial"),
1372 raw: None,
1373 }))];
1374 }
1375 }
1376 }
1377 "ruby-merge" => {
1378 if let Some(ComponentValue::Ident(ident)) = declaration.value.first() {
1379 if ident.value.eq_ignore_ascii_case("separate") {
1380 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
1381 span: ident.span,
1382 value: atom!("initial"),
1383 raw: None,
1384 }))];
1385 }
1386 }
1387 }
1388 "ruby-position" => {
1389 if let Some(ComponentValue::Ident(ident)) = declaration.value.first() {
1390 if ident.value.eq_ignore_ascii_case("alternate") {
1391 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
1392 span: ident.span,
1393 value: atom!("initial"),
1394 raw: None,
1395 }))];
1396 }
1397 }
1398 }
1399 "text-emphasis-position" => {
1400 if let (Some(ComponentValue::Ident(first)), Some(ComponentValue::Ident(second))) =
1401 (declaration.value.first(), declaration.value.get(1))
1402 {
1403 if first.value.eq_ignore_ascii_case("over")
1404 && second.value.eq_ignore_ascii_case("right")
1405 {
1406 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
1407 span: first.span,
1408 value: atom!("initial"),
1409 raw: None,
1410 }))];
1411 }
1412 }
1413 }
1414 "transform-box" => {
1415 if let Some(ComponentValue::Ident(ident)) = declaration.value.first() {
1416 if ident.value.eq_ignore_ascii_case("view-box") {
1417 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
1418 span: ident.span,
1419 value: atom!("initial"),
1420 raw: None,
1421 }))];
1422 }
1423 }
1424 }
1425 "transform-origin" => {
1426 if let (
1427 Some(Percentage {
1428 value: Number { value: first, .. },
1429 span,
1430 ..
1431 }),
1432 Some(Percentage {
1433 value: Number { value: second, .. },
1434 ..
1435 }),
1436 Some(Integer { value: third, .. }),
1437 ) = (
1438 declaration
1439 .value
1440 .first()
1441 .and_then(|x| x.as_percentage())
1442 .map(|x| x.as_ref()),
1443 declaration
1444 .value
1445 .get(1)
1446 .and_then(|x| x.as_percentage())
1447 .map(|x| x.as_ref()),
1448 declaration
1449 .value
1450 .get(2)
1451 .and_then(|x| x.as_integer())
1452 .map(|x| x.as_ref()),
1453 ) {
1454 if *first == 50.0
1455 && *second == 50.0
1456 && *third == 0
1457 && declaration.value.len() == 3
1458 {
1459 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
1460 span: *span,
1461 value: atom!("initial"),
1462 raw: None,
1463 }))];
1464 }
1465 }
1466 }
1467 "vertical-align" => {
1468 if let Some(ComponentValue::Ident(ident)) = declaration.value.first() {
1469 if ident.value.eq_ignore_ascii_case("baseline") {
1470 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
1471 span: ident.span,
1472 value: atom!("initial"),
1473 raw: None,
1474 }))];
1475 }
1476 }
1477 }
1478 "writing-mode" => {
1479 if let Some(ComponentValue::Ident(ident)) = declaration.value.first() {
1480 if ident.value.eq_ignore_ascii_case("horizontal-tb") {
1481 declaration.value = vec![ComponentValue::Ident(Box::new(Ident {
1482 span: ident.span,
1483 value: atom!("initial"),
1484 raw: None,
1485 }))];
1486 }
1487 }
1488 }
1489 _ => {}
1490 }
1491 }
1492}