lightningcss/
lib.rs

1//! Lightning CSS is a CSS parser, transformer, and minifier based on the
2//! [cssparser](https://github.com/servo/rust-cssparser) crate used in Firefox.
3//! It supports fully parsing all CSS rules, properties, and values into normalized
4//! structures exactly how a browser would. Once parsed, the CSS can be transformed
5//! to add or remove vendor prefixes, or lower syntax for older browsers as appropriate.
6//! The style sheet can also be minified to merge longhand properties into shorthands,
7//! merge adjacent rules, reduce `calc()` expressions, and more. Finally, the style sheet
8//! can be printed back to CSS syntax, either minified to remove whitespace and compress
9//! the output as much as possible, or pretty printed.
10//!
11//! The [StyleSheet](stylesheet::StyleSheet) struct is the main entrypoint for Lightning CSS,
12//! and supports parsing and transforming entire CSS files. You can also parse and manipulate
13//! individual CSS [rules](rules), [properties](properties), or [values](values). The [bundler](bundler)
14//! module also can be used to combine a CSS file and all of its dependencies together into a single
15//! style sheet. See the individual module documentation for more details and examples.
16
17#![deny(missing_docs)]
18#![cfg_attr(docsrs, feature(doc_cfg))]
19
20#[cfg(feature = "bundler")]
21#[cfg_attr(docsrs, doc(cfg(feature = "bundler")))]
22pub mod bundler;
23mod compat;
24mod context;
25pub mod css_modules;
26pub mod declaration;
27pub mod dependencies;
28pub mod error;
29mod logical;
30mod macros;
31pub mod media_query;
32mod parser;
33mod prefixes;
34pub mod printer;
35pub mod properties;
36pub mod rules;
37pub mod selector;
38pub mod stylesheet;
39pub mod targets;
40pub mod traits;
41pub mod values;
42pub mod vendor_prefix;
43#[cfg(feature = "visitor")]
44#[cfg_attr(docsrs, doc(cfg(feature = "visitor")))]
45pub mod visitor;
46
47#[cfg(feature = "serde")]
48mod serialization;
49
50#[cfg(test)]
51mod tests {
52  use crate::css_modules::{CssModuleExport, CssModuleExports, CssModuleReference, CssModuleReferences};
53  use crate::dependencies::Dependency;
54  use crate::error::{Error, ErrorLocation, MinifyErrorKind, ParserError, PrinterErrorKind, SelectorError};
55  use crate::parser::ParserFlags;
56  use crate::properties::custom::Token;
57  use crate::properties::Property;
58  use crate::rules::CssRule;
59  use crate::rules::Location;
60  use crate::stylesheet::*;
61  use crate::targets::{Browsers, Features, Targets};
62  use crate::traits::{Parse, ToCss};
63  use crate::values::color::CssColor;
64  use crate::vendor_prefix::VendorPrefix;
65  use cssparser::SourceLocation;
66  use indoc::indoc;
67  use pretty_assertions::assert_eq;
68  use std::collections::HashMap;
69  use std::sync::{Arc, RwLock};
70
71  fn test(source: &str, expected: &str) {
72    test_with_options(source, expected, ParserOptions::default())
73  }
74
75  fn test_with_options<'i, 'o>(source: &'i str, expected: &'i str, options: ParserOptions<'o, 'i>) {
76    let mut stylesheet = StyleSheet::parse(&source, options).unwrap();
77    stylesheet.minify(MinifyOptions::default()).unwrap();
78    let res = stylesheet.to_css(PrinterOptions::default()).unwrap();
79    assert_eq!(res.code, expected);
80  }
81
82  fn minify_test(source: &str, expected: &str) {
83    minify_test_with_options(source, expected, ParserOptions::default())
84  }
85
86  #[track_caller]
87  fn minify_test_with_options<'i, 'o>(source: &'i str, expected: &'i str, options: ParserOptions<'o, 'i>) {
88    let mut stylesheet = StyleSheet::parse(&source, options.clone()).unwrap();
89    stylesheet.minify(MinifyOptions::default()).unwrap();
90    let res = stylesheet
91      .to_css(PrinterOptions {
92        minify: true,
93        ..PrinterOptions::default()
94      })
95      .unwrap();
96    assert_eq!(res.code, expected);
97  }
98
99  fn minify_error_test_with_options<'i, 'o>(
100    source: &'i str,
101    error: MinifyErrorKind,
102    options: ParserOptions<'o, 'i>,
103  ) {
104    let mut stylesheet = StyleSheet::parse(&source, options.clone()).unwrap();
105    match stylesheet.minify(MinifyOptions::default()) {
106      Err(e) => assert_eq!(e.kind, error),
107      _ => unreachable!(),
108    }
109  }
110
111  fn prefix_test(source: &str, expected: &str, targets: Browsers) {
112    let mut stylesheet = StyleSheet::parse(&source, ParserOptions::default()).unwrap();
113    stylesheet
114      .minify(MinifyOptions {
115        targets: targets.into(),
116        ..MinifyOptions::default()
117      })
118      .unwrap();
119    let res = stylesheet
120      .to_css(PrinterOptions {
121        targets: targets.into(),
122        ..PrinterOptions::default()
123      })
124      .unwrap();
125    assert_eq!(res.code, expected);
126  }
127
128  fn attr_test(source: &str, expected: &str, minify: bool, targets: Option<Browsers>) {
129    let mut attr = StyleAttribute::parse(source, ParserOptions::default()).unwrap();
130    attr.minify(MinifyOptions {
131      targets: targets.into(),
132      ..MinifyOptions::default()
133    });
134    let res = attr
135      .to_css(PrinterOptions {
136        targets: targets.into(),
137        minify,
138        ..PrinterOptions::default()
139      })
140      .unwrap();
141    assert_eq!(res.code, expected);
142  }
143
144  fn nesting_test(source: &str, expected: &str) {
145    nesting_test_with_targets(
146      source,
147      expected,
148      Browsers {
149        chrome: Some(95 << 16),
150        ..Browsers::default()
151      }
152      .into(),
153    );
154  }
155
156  fn nesting_test_with_targets(source: &str, expected: &str, targets: Targets) {
157    let mut stylesheet = StyleSheet::parse(&source, ParserOptions::default()).unwrap();
158    stylesheet
159      .minify(MinifyOptions {
160        targets,
161        ..MinifyOptions::default()
162      })
163      .unwrap();
164    let res = stylesheet
165      .to_css(PrinterOptions {
166        targets,
167        ..PrinterOptions::default()
168      })
169      .unwrap();
170    assert_eq!(res.code, expected);
171  }
172
173  fn nesting_test_no_targets(source: &str, expected: &str) {
174    let mut stylesheet = StyleSheet::parse(&source, ParserOptions::default()).unwrap();
175    stylesheet.minify(MinifyOptions::default()).unwrap();
176    let res = stylesheet.to_css(PrinterOptions::default()).unwrap();
177    assert_eq!(res.code, expected);
178  }
179
180  fn css_modules_test<'i>(
181    source: &'i str,
182    expected: &str,
183    expected_exports: CssModuleExports,
184    expected_references: CssModuleReferences,
185    config: crate::css_modules::Config<'i>,
186    minify: bool,
187  ) {
188    let mut stylesheet = StyleSheet::parse(
189      &source,
190      ParserOptions {
191        filename: "test.css".into(),
192        css_modules: Some(config),
193        ..ParserOptions::default()
194      },
195    )
196    .unwrap();
197    stylesheet.minify(MinifyOptions::default()).unwrap();
198    let res = stylesheet
199      .to_css(PrinterOptions {
200        minify,
201        ..Default::default()
202      })
203      .unwrap();
204    assert_eq!(res.code, expected);
205    assert_eq!(res.exports.unwrap(), expected_exports);
206    assert_eq!(res.references.unwrap(), expected_references);
207  }
208
209  fn custom_media_test(source: &str, expected: &str) {
210    let mut stylesheet = StyleSheet::parse(
211      &source,
212      ParserOptions {
213        flags: ParserFlags::CUSTOM_MEDIA,
214        ..ParserOptions::default()
215      },
216    )
217    .unwrap();
218    stylesheet
219      .minify(MinifyOptions {
220        targets: Browsers {
221          chrome: Some(95 << 16),
222          ..Browsers::default()
223        }
224        .into(),
225        ..MinifyOptions::default()
226      })
227      .unwrap();
228    let res = stylesheet.to_css(PrinterOptions::default()).unwrap();
229    assert_eq!(res.code, expected);
230  }
231
232  fn error_test(source: &str, error: ParserError) {
233    let res = StyleSheet::parse(&source, ParserOptions::default());
234    match res {
235      Ok(_) => unreachable!(),
236      Err(e) => assert_eq!(e.kind, error),
237    }
238  }
239
240  fn error_recovery_test(source: &str) {
241    let warnings = Arc::new(RwLock::default());
242    let res = StyleSheet::parse(
243      &source,
244      ParserOptions {
245        error_recovery: true,
246        warnings: Some(warnings.clone()),
247        ..Default::default()
248      },
249    );
250    match res {
251      Ok(..) => {}
252      Err(e) => unreachable!("parser error should be recovered, but got {e:?}"),
253    }
254  }
255
256  fn css_modules_error_test(source: &str, error: ParserError) {
257    let res = StyleSheet::parse(
258      &source,
259      ParserOptions {
260        css_modules: Some(Default::default()),
261        ..Default::default()
262      },
263    );
264    match res {
265      Ok(_) => unreachable!(),
266      Err(e) => assert_eq!(e.kind, error),
267    }
268  }
269
270  macro_rules! map(
271    { $($key:expr => $name:literal $(referenced: $referenced: literal)? $($value:literal $(global: $global: literal)? $(from $from:literal)?)*),* } => {
272      {
273        #[allow(unused_mut)]
274        let mut m = HashMap::new();
275        $(
276          #[allow(unused_mut)]
277          let mut v = Vec::new();
278          #[allow(unused_macros)]
279          macro_rules! insert {
280            ($local:literal from $specifier:literal) => {
281              v.push(CssModuleReference::Dependency {
282                name: $local.into(),
283                specifier: $specifier.into()
284              });
285            };
286            ($local:literal global: $is_global: literal) => {
287              v.push(CssModuleReference::Global {
288                name: $local.into()
289              });
290            };
291            ($local:literal) => {
292              v.push(CssModuleReference::Local {
293                name: $local.into()
294              });
295            };
296          }
297          $(
298            insert!($value $(global: $global)? $(from $from)?);
299          )*
300
301          macro_rules! is_referenced {
302            ($ref: literal) => {
303              $ref
304            };
305            () => {
306              false
307            };
308          }
309
310          m.insert($key.into(), CssModuleExport {
311            name: $name.into(),
312            composes: v,
313            is_referenced: is_referenced!($($referenced)?)
314          });
315        )*
316        m
317      }
318    };
319  );
320
321  #[test]
322  pub fn test_border_spacing() {
323    minify_test(
324      r#"
325      .foo {
326        border-spacing: 0px;
327      }
328    "#,
329      indoc! {".foo{border-spacing:0}"
330      },
331    );
332    minify_test(
333      r#"
334      .foo {
335        border-spacing: 0px 0px;
336      }
337    "#,
338      indoc! {".foo{border-spacing:0}"
339      },
340    );
341
342    minify_test(
343      r#"
344      .foo {
345        border-spacing: 12px   0px;
346      }
347    "#,
348      indoc! {".foo{border-spacing:12px 0}"
349      },
350    );
351
352    minify_test(
353      r#"
354      .foo {
355        border-spacing: calc(3px * 2) calc(5px * 0);
356      }
357    "#,
358      indoc! {".foo{border-spacing:6px 0}"
359      },
360    );
361
362    minify_test(
363      r#"
364      .foo {
365        border-spacing: calc(3px * 2) max(0px, 8px);
366      }
367    "#,
368      indoc! {".foo{border-spacing:6px 8px}"
369      },
370    );
371
372    // TODO: The `<length>` in border-spacing cannot have a negative value,
373    // we may need to implement NonNegativeLength like Servo does.
374    // Servo Code: https://github.com/servo/servo/blob/08bc2d53579c9ab85415d4363888881b91df073b/components/style/values/specified/length.rs#L875
375    // CSSWG issue: https://lists.w3.org/Archives/Public/www-style/2008Sep/0161.html
376    // `border-spacing = <length> <length>?`
377    minify_test(
378      r#"
379      .foo {
380        border-spacing: -20px;
381      }
382    "#,
383      indoc! {".foo{border-spacing:-20px}"
384      },
385    );
386  }
387
388  #[test]
389  pub fn test_border() {
390    test(
391      r#"
392      .foo {
393        border-left: 2px solid red;
394        border-right: 2px solid red;
395        border-bottom: 2px solid red;
396        border-top: 2px solid red;
397      }
398    "#,
399      indoc! {r#"
400      .foo {
401        border: 2px solid red;
402      }
403    "#
404      },
405    );
406
407    test(
408      r#"
409      .foo {
410        border-left-color: red;
411        border-right-color: red;
412        border-bottom-color: red;
413        border-top-color: red;
414      }
415    "#,
416      indoc! {r#"
417      .foo {
418        border-color: red;
419      }
420    "#
421      },
422    );
423
424    test(
425      r#"
426      .foo {
427        border-left-width: thin;
428        border-right-width: thin;
429        border-bottom-width: thin;
430        border-top-width: thin;
431      }
432    "#,
433      indoc! {r#"
434      .foo {
435        border-width: thin;
436      }
437    "#
438      },
439    );
440
441    test(
442      r#"
443      .foo {
444        border-left-style: dotted;
445        border-right-style: dotted;
446        border-bottom-style: dotted;
447        border-top-style: dotted;
448      }
449    "#,
450      indoc! {r#"
451      .foo {
452        border-style: dotted;
453      }
454    "#
455      },
456    );
457
458    test(
459      r#"
460      .foo {
461        border-left-width: thin;
462        border-left-style: dotted;
463        border-left-color: red;
464      }
465    "#,
466      indoc! {r#"
467      .foo {
468        border-left: thin dotted red;
469      }
470    "#
471      },
472    );
473
474    test(
475      r#"
476      .foo {
477        border-left-width: thick;
478        border-left: thin dotted red;
479      }
480    "#,
481      indoc! {r#"
482      .foo {
483        border-left: thin dotted red;
484      }
485    "#
486      },
487    );
488
489    test(
490      r#"
491      .foo {
492        border-left-width: thick;
493        border: thin dotted red;
494      }
495    "#,
496      indoc! {r#"
497      .foo {
498        border: thin dotted red;
499      }
500    "#
501      },
502    );
503
504    test(
505      r#"
506      .foo {
507        border: thin dotted red;
508        border-right-width: thick;
509      }
510    "#,
511      indoc! {r#"
512      .foo {
513        border: thin dotted red;
514        border-right-width: thick;
515      }
516    "#
517      },
518    );
519
520    test(
521      r#"
522      .foo {
523        border: thin dotted red;
524        border-right: thick dotted red;
525      }
526    "#,
527      indoc! {r#"
528      .foo {
529        border: thin dotted red;
530        border-right-width: thick;
531      }
532    "#
533      },
534    );
535
536    test(
537      r#"
538      .foo {
539        border: thin dotted red;
540        border-right-width: thick;
541        border-right-style: solid;
542      }
543    "#,
544      indoc! {r#"
545      .foo {
546        border: thin dotted red;
547        border-right: thick solid red;
548      }
549    "#
550      },
551    );
552
553    test(
554      r#"
555      .foo {
556        border-top: thin dotted red;
557        border-block-start: thick solid green;
558      }
559    "#,
560      indoc! {r#"
561      .foo {
562        border-top: thin dotted red;
563        border-block-start: thick solid green;
564      }
565    "#
566      },
567    );
568
569    test(
570      r#"
571      .foo {
572        border: thin dotted red;
573        border-block-start-width: thick;
574        border-left-width: medium;
575      }
576    "#,
577      indoc! {r#"
578      .foo {
579        border: thin dotted red;
580        border-block-start-width: thick;
581        border-left-width: medium;
582      }
583    "#
584      },
585    );
586
587    test(
588      r#"
589      .foo {
590        border-block-start: thin dotted red;
591        border-inline-end: thin dotted red;
592      }
593    "#,
594      indoc! {r#"
595      .foo {
596        border-block-start: thin dotted red;
597        border-inline-end: thin dotted red;
598      }
599    "#
600      },
601    );
602
603    test(
604      r#"
605      .foo {
606        border-block-start-width: thin;
607        border-block-start-style: dotted;
608        border-block-start-color: red;
609        border-inline-end: thin dotted red;
610      }
611    "#,
612      indoc! {r#"
613      .foo {
614        border-block-start: thin dotted red;
615        border-inline-end: thin dotted red;
616      }
617    "#
618      },
619    );
620
621    test(
622      r#"
623      .foo {
624        border-block-start: thin dotted red;
625        border-block-end: thin dotted red;
626      }
627    "#,
628      indoc! {r#"
629      .foo {
630        border-block: thin dotted red;
631      }
632    "#
633      },
634    );
635
636    minify_test(
637      r#"
638      .foo {
639        border: none;
640      }
641    "#,
642      indoc! {".foo{border:none}"
643      },
644    );
645
646    minify_test(".foo { border-width: 0 0 1px; }", ".foo{border-width:0 0 1px}");
647    test(
648      r#"
649      .foo {
650        border-block-width: 1px;
651        border-inline-width: 1px;
652      }
653    "#,
654      indoc! {r#"
655      .foo {
656        border-width: 1px;
657      }
658    "#
659      },
660    );
661    test(
662      r#"
663      .foo {
664        border-block-start-width: 1px;
665        border-block-end-width: 1px;
666        border-inline-start-width: 1px;
667        border-inline-end-width: 1px;
668      }
669    "#,
670      indoc! {r#"
671      .foo {
672        border-width: 1px;
673      }
674    "#
675      },
676    );
677    test(
678      r#"
679      .foo {
680        border-block-start-width: 1px;
681        border-block-end-width: 1px;
682        border-inline-start-width: 2px;
683        border-inline-end-width: 2px;
684      }
685    "#,
686      indoc! {r#"
687      .foo {
688        border-block-width: 1px;
689        border-inline-width: 2px;
690      }
691    "#
692      },
693    );
694    test(
695      r#"
696      .foo {
697        border-block-start-width: 1px;
698        border-block-end-width: 1px;
699        border-inline-start-width: 2px;
700        border-inline-end-width: 3px;
701      }
702    "#,
703      indoc! {r#"
704      .foo {
705        border-block-width: 1px;
706        border-inline-width: 2px 3px;
707      }
708    "#
709      },
710    );
711
712    minify_test(
713      ".foo { border-bottom: 1px solid var(--spectrum-global-color-gray-200)}",
714      ".foo{border-bottom:1px solid var(--spectrum-global-color-gray-200)}",
715    );
716    test(
717      r#"
718      .foo {
719        border-width: 0;
720        border-bottom: var(--test, 1px) solid;
721      }
722    "#,
723      indoc! {r#"
724      .foo {
725        border-width: 0;
726        border-bottom: var(--test, 1px) solid;
727      }
728    "#
729      },
730    );
731
732    test(
733      r#"
734      .foo {
735        border: 1px solid black;
736        border-width: 1px 1px 0 0;
737      }
738    "#,
739      indoc! {r#"
740      .foo {
741        border: 1px solid #000;
742        border-width: 1px 1px 0 0;
743      }
744    "#},
745    );
746
747    test(
748      r#"
749      .foo {
750        border-top: 1px solid black;
751        border-bottom: 1px solid black;
752        border-left: 2px solid black;
753        border-right: 2px solid black;
754      }
755    "#,
756      indoc! {r#"
757      .foo {
758        border: 1px solid #000;
759        border-width: 1px 2px;
760      }
761    "#},
762    );
763
764    test(
765      r#"
766      .foo {
767        border-top: 1px solid black;
768        border-bottom: 1px solid black;
769        border-left: 2px solid black;
770        border-right: 1px solid black;
771      }
772    "#,
773      indoc! {r#"
774      .foo {
775        border: 1px solid #000;
776        border-left-width: 2px;
777      }
778    "#},
779    );
780
781    test(
782      r#"
783      .foo {
784        border-top: 1px solid black;
785        border-bottom: 1px solid black;
786        border-left: 1px solid red;
787        border-right: 1px solid red;
788      }
789    "#,
790      indoc! {r#"
791      .foo {
792        border: 1px solid #000;
793        border-color: #000 red;
794      }
795    "#},
796    );
797
798    test(
799      r#"
800      .foo {
801        border-block-start: 1px solid black;
802        border-block-end: 1px solid black;
803        border-inline-start: 1px solid red;
804        border-inline-end: 1px solid red;
805      }
806    "#,
807      indoc! {r#"
808      .foo {
809        border: 1px solid #000;
810        border-inline-color: red;
811      }
812    "#},
813    );
814
815    test(
816      r#"
817      .foo {
818        border-block-start: 1px solid black;
819        border-block-end: 1px solid black;
820        border-inline-start: 2px solid black;
821        border-inline-end: 2px solid black;
822      }
823    "#,
824      indoc! {r#"
825      .foo {
826        border: 1px solid #000;
827        border-inline-width: 2px;
828      }
829    "#},
830    );
831
832    test(
833      r#"
834      .foo {
835        border-block-start: 1px solid black;
836        border-block-end: 1px solid black;
837        border-inline-start: 2px solid red;
838        border-inline-end: 2px solid red;
839      }
840    "#,
841      indoc! {r#"
842      .foo {
843        border: 1px solid #000;
844        border-inline: 2px solid red;
845      }
846    "#},
847    );
848
849    test(
850      r#"
851      .foo {
852        border-block-start: 1px solid black;
853        border-block-end: 1px solid black;
854        border-inline-start: 2px solid red;
855        border-inline-end: 3px solid red;
856      }
857    "#,
858      indoc! {r#"
859      .foo {
860        border: 1px solid #000;
861        border-inline-start: 2px solid red;
862        border-inline-end: 3px solid red;
863      }
864    "#},
865    );
866
867    test(
868      r#"
869      .foo {
870        border-block-start: 2px solid black;
871        border-block-end: 1px solid black;
872        border-inline-start: 2px solid red;
873        border-inline-end: 2px solid red;
874      }
875    "#,
876      indoc! {r#"
877      .foo {
878        border: 2px solid red;
879        border-block-start-color: #000;
880        border-block-end: 1px solid #000;
881      }
882    "#},
883    );
884
885    test(
886      r#"
887      .foo {
888        border-block-start: 2px solid red;
889        border-block-end: 1px solid red;
890        border-inline-start: 2px solid red;
891        border-inline-end: 2px solid red;
892      }
893    "#,
894      indoc! {r#"
895      .foo {
896        border: 2px solid red;
897        border-block-end-width: 1px;
898      }
899    "#},
900    );
901
902    test(
903      r#"
904      .foo {
905        border-block-start: 2px solid red;
906        border-block-end: 2px solid red;
907        border-inline-start: 2px solid red;
908        border-inline-end: 1px solid red;
909      }
910    "#,
911      indoc! {r#"
912      .foo {
913        border: 2px solid red;
914        border-inline-end-width: 1px;
915      }
916    "#},
917    );
918
919    test(
920      r#"
921      .foo {
922        border: 1px solid currentColor;
923      }
924    "#,
925      indoc! {r#"
926      .foo {
927        border: 1px solid;
928      }
929    "#
930      },
931    );
932
933    minify_test(
934      r#"
935      .foo {
936        border: 1px solid currentColor;
937      }
938    "#,
939      ".foo{border:1px solid}",
940    );
941
942    prefix_test(
943      r#"
944      .foo {
945        border-block: 2px solid red;
946      }
947    "#,
948      indoc! {r#"
949      .foo {
950        border-top: 2px solid red;
951        border-bottom: 2px solid red;
952      }
953    "#
954      },
955      Browsers {
956        safari: Some(8 << 16),
957        ..Browsers::default()
958      },
959    );
960
961    prefix_test(
962      r#"
963      .foo {
964        border-block-start: 2px solid red;
965      }
966    "#,
967      indoc! {r#"
968      .foo {
969        border-top: 2px solid red;
970      }
971    "#
972      },
973      Browsers {
974        safari: Some(8 << 16),
975        ..Browsers::default()
976      },
977    );
978
979    prefix_test(
980      r#"
981      .foo {
982        border-block-end: 2px solid red;
983      }
984    "#,
985      indoc! {r#"
986      .foo {
987        border-bottom: 2px solid red;
988      }
989    "#
990      },
991      Browsers {
992        safari: Some(8 << 16),
993        ..Browsers::default()
994      },
995    );
996
997    prefix_test(
998      r#"
999      .foo {
1000        border-inline: 2px solid red;
1001      }
1002    "#,
1003      indoc! {r#"
1004      .foo {
1005        border-left: 2px solid red;
1006        border-right: 2px solid red;
1007      }
1008    "#
1009      },
1010      Browsers {
1011        safari: Some(8 << 16),
1012        ..Browsers::default()
1013      },
1014    );
1015
1016    prefix_test(
1017      r#"
1018      .foo {
1019        border-block-width: 2px;
1020      }
1021    "#,
1022      indoc! {r#"
1023      .foo {
1024        border-block-start-width: 2px;
1025        border-block-end-width: 2px;
1026      }
1027    "#
1028      },
1029      Browsers {
1030        safari: Some(13 << 16),
1031        ..Browsers::default()
1032      },
1033    );
1034
1035    prefix_test(
1036      r#"
1037      .foo {
1038        border-block-width: 2px;
1039      }
1040    "#,
1041      indoc! {r#"
1042      .foo {
1043        border-block-width: 2px;
1044      }
1045    "#
1046      },
1047      Browsers {
1048        safari: Some(15 << 16),
1049        ..Browsers::default()
1050      },
1051    );
1052
1053    prefix_test(
1054      r#"
1055      .foo {
1056        border-inline-start: 2px solid red;
1057      }
1058    "#,
1059      indoc! {r#"
1060      .foo:not(:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
1061        border-left: 2px solid red;
1062      }
1063
1064      .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
1065        border-left: 2px solid red;
1066      }
1067
1068      .foo:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
1069        border-right: 2px solid red;
1070      }
1071
1072      .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
1073        border-right: 2px solid red;
1074      }
1075    "#
1076      },
1077      Browsers {
1078        safari: Some(8 << 16),
1079        ..Browsers::default()
1080      },
1081    );
1082
1083    prefix_test(
1084      r#"
1085      .foo {
1086        border-inline-start-width: 2px;
1087      }
1088    "#,
1089      indoc! {r#"
1090      .foo:not(:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
1091        border-left-width: 2px;
1092      }
1093
1094      .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
1095        border-left-width: 2px;
1096      }
1097
1098      .foo:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
1099        border-right-width: 2px;
1100      }
1101
1102      .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
1103        border-right-width: 2px;
1104      }
1105    "#
1106      },
1107      Browsers {
1108        safari: Some(8 << 16),
1109        ..Browsers::default()
1110      },
1111    );
1112
1113    prefix_test(
1114      r#"
1115      .foo {
1116        border-inline-end: 2px solid red;
1117      }
1118    "#,
1119      indoc! {r#"
1120      .foo:not(:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
1121        border-right: 2px solid red;
1122      }
1123
1124      .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
1125        border-right: 2px solid red;
1126      }
1127
1128      .foo:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
1129        border-left: 2px solid red;
1130      }
1131
1132      .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
1133        border-left: 2px solid red;
1134      }
1135    "#
1136      },
1137      Browsers {
1138        safari: Some(8 << 16),
1139        ..Browsers::default()
1140      },
1141    );
1142
1143    prefix_test(
1144      r#"
1145      .foo {
1146        border-inline-start: 2px solid red;
1147        border-inline-end: 5px solid green;
1148      }
1149    "#,
1150      indoc! {r#"
1151      .foo:not(:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
1152        border-left: 2px solid red;
1153        border-right: 5px solid green;
1154      }
1155
1156      .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
1157        border-left: 2px solid red;
1158        border-right: 5px solid green;
1159      }
1160
1161      .foo:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
1162        border-left: 5px solid green;
1163        border-right: 2px solid red;
1164      }
1165
1166      .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
1167        border-left: 5px solid green;
1168        border-right: 2px solid red;
1169      }
1170    "#
1171      },
1172      Browsers {
1173        safari: Some(8 << 16),
1174        ..Browsers::default()
1175      },
1176    );
1177
1178    prefix_test(
1179      r#"
1180      .foo {
1181        border-inline-start: 2px solid red;
1182        border-inline-end: 5px solid green;
1183      }
1184
1185      .bar {
1186        border-inline-start: 1px dotted gray;
1187        border-inline-end: 1px solid black;
1188      }
1189    "#,
1190      indoc! {r#"
1191      .foo:not(:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
1192        border-left: 2px solid red;
1193        border-right: 5px solid green;
1194      }
1195
1196      .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
1197        border-left: 2px solid red;
1198        border-right: 5px solid green;
1199      }
1200
1201      .foo:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
1202        border-left: 5px solid green;
1203        border-right: 2px solid red;
1204      }
1205
1206      .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
1207        border-left: 5px solid green;
1208        border-right: 2px solid red;
1209      }
1210
1211      .bar:not(:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
1212        border-left: 1px dotted gray;
1213        border-right: 1px solid #000;
1214      }
1215
1216      .bar:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
1217        border-left: 1px dotted gray;
1218        border-right: 1px solid #000;
1219      }
1220
1221      .bar:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
1222        border-left: 1px solid #000;
1223        border-right: 1px dotted gray;
1224      }
1225
1226      .bar:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
1227        border-left: 1px solid #000;
1228        border-right: 1px dotted gray;
1229      }
1230    "#
1231      },
1232      Browsers {
1233        safari: Some(8 << 16),
1234        ..Browsers::default()
1235      },
1236    );
1237
1238    prefix_test(
1239      r#"
1240      .foo {
1241        border-inline-width: 2px;
1242      }
1243    "#,
1244      indoc! {r#"
1245      .foo {
1246        border-left-width: 2px;
1247        border-right-width: 2px;
1248      }
1249    "#
1250      },
1251      Browsers {
1252        safari: Some(8 << 16),
1253        ..Browsers::default()
1254      },
1255    );
1256
1257    prefix_test(
1258      r#"
1259      .foo {
1260        border-inline-width: 2px;
1261      }
1262    "#,
1263      indoc! {r#"
1264      .foo {
1265        border-left-width: 2px;
1266        border-right-width: 2px;
1267      }
1268    "#
1269      },
1270      Browsers {
1271        safari: Some(8 << 16),
1272        ..Browsers::default()
1273      },
1274    );
1275
1276    prefix_test(
1277      r#"
1278      .foo {
1279        border-inline-style: solid;
1280      }
1281    "#,
1282      indoc! {r#"
1283      .foo {
1284        border-left-style: solid;
1285        border-right-style: solid;
1286      }
1287    "#
1288      },
1289      Browsers {
1290        safari: Some(8 << 16),
1291        ..Browsers::default()
1292      },
1293    );
1294
1295    prefix_test(
1296      r#"
1297      .foo {
1298        border-inline-color: red;
1299      }
1300    "#,
1301      indoc! {r#"
1302      .foo {
1303        border-left-color: red;
1304        border-right-color: red;
1305      }
1306    "#
1307      },
1308      Browsers {
1309        safari: Some(8 << 16),
1310        ..Browsers::default()
1311      },
1312    );
1313
1314    prefix_test(
1315      r#"
1316      .foo {
1317        border-inline-end: var(--test);
1318      }
1319    "#,
1320      indoc! {r#"
1321      .foo:not(:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
1322        border-right: var(--test);
1323      }
1324
1325      .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
1326        border-right: var(--test);
1327      }
1328
1329      .foo:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
1330        border-left: var(--test);
1331      }
1332
1333      .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
1334        border-left: var(--test);
1335      }
1336    "#
1337      },
1338      Browsers {
1339        safari: Some(8 << 16),
1340        ..Browsers::default()
1341      },
1342    );
1343
1344    prefix_test(
1345      r#"
1346      .foo {
1347        border-inline-start: var(--start);
1348        border-inline-end: var(--end);
1349      }
1350    "#,
1351      indoc! {r#"
1352      .foo:not(:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
1353        border-left: var(--start);
1354        border-right: var(--end);
1355      }
1356
1357      .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
1358        border-left: var(--start);
1359        border-right: var(--end);
1360      }
1361
1362      .foo:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
1363        border-right: var(--start);
1364        border-left: var(--end);
1365      }
1366
1367      .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
1368        border-right: var(--start);
1369        border-left: var(--end);
1370      }
1371    "#
1372      },
1373      Browsers {
1374        safari: Some(8 << 16),
1375        ..Browsers::default()
1376      },
1377    );
1378
1379    for prop in &[
1380      "border-inline-start-color",
1381      "border-inline-end-color",
1382      "border-block-start-color",
1383      "border-block-end-color",
1384      "border-top-color",
1385      "border-bottom-color",
1386      "border-left-color",
1387      "border-right-color",
1388      "border-color",
1389      "border-block-color",
1390      "border-inline-color",
1391    ] {
1392      prefix_test(
1393        &format!(
1394          r#"
1395        .foo {{
1396          {}: lab(40% 56.6 39);
1397        }}
1398      "#,
1399          prop
1400        ),
1401        &format!(
1402          indoc! {r#"
1403        .foo {{
1404          {}: #b32323;
1405          {}: lab(40% 56.6 39);
1406        }}
1407      "#},
1408          prop, prop
1409        ),
1410        Browsers {
1411          chrome: Some(90 << 16),
1412          ..Browsers::default()
1413        },
1414      );
1415    }
1416
1417    for prop in &[
1418      "border",
1419      "border-inline",
1420      "border-block",
1421      "border-left",
1422      "border-right",
1423      "border-top",
1424      "border-bottom",
1425      "border-block-start",
1426      "border-block-end",
1427      "border-inline-start",
1428      "border-inline-end",
1429    ] {
1430      prefix_test(
1431        &format!(
1432          r#"
1433        .foo {{
1434          {}: 2px solid lab(40% 56.6 39);
1435        }}
1436      "#,
1437          prop
1438        ),
1439        &format!(
1440          indoc! {r#"
1441        .foo {{
1442          {}: 2px solid #b32323;
1443          {}: 2px solid lab(40% 56.6 39);
1444        }}
1445      "#},
1446          prop, prop
1447        ),
1448        Browsers {
1449          chrome: Some(90 << 16),
1450          ..Browsers::default()
1451        },
1452      );
1453    }
1454
1455    for prop in &[
1456      "border",
1457      "border-inline",
1458      "border-block",
1459      "border-left",
1460      "border-right",
1461      "border-top",
1462      "border-bottom",
1463      "border-block-start",
1464      "border-block-end",
1465      "border-inline-start",
1466      "border-inline-end",
1467    ] {
1468      prefix_test(
1469        &format!(
1470          r#"
1471        .foo {{
1472          {}: var(--border-width) solid lab(40% 56.6 39);
1473        }}
1474      "#,
1475          prop
1476        ),
1477        &format!(
1478          indoc! {r#"
1479        .foo {{
1480          {}: var(--border-width) solid #b32323;
1481        }}
1482
1483        @supports (color: lab(0% 0 0)) {{
1484          .foo {{
1485            {}: var(--border-width) solid lab(40% 56.6 39);
1486          }}
1487        }}
1488      "#},
1489          prop, prop
1490        ),
1491        Browsers {
1492          chrome: Some(90 << 16),
1493          ..Browsers::default()
1494        },
1495      );
1496
1497      prefix_test(
1498        &format!(
1499          r#"
1500        @supports (color: lab(0% 0 0)) {{
1501          .foo {{
1502            {}: var(--border-width) solid lab(40% 56.6 39);
1503          }}
1504        }}
1505      "#,
1506          prop
1507        ),
1508        &format!(
1509          indoc! {r#"
1510        @supports (color: lab(0% 0 0)) {{
1511          .foo {{
1512            {}: var(--border-width) solid lab(40% 56.6 39);
1513          }}
1514        }}
1515      "#},
1516          prop,
1517        ),
1518        Browsers {
1519          chrome: Some(90 << 16),
1520          ..Browsers::default()
1521        },
1522      );
1523    }
1524
1525    prefix_test(
1526      r#"
1527      .foo {
1528        border-inline-start-color: lab(40% 56.6 39);
1529      }
1530    "#,
1531      indoc! {r#"
1532      .foo:not(:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
1533        border-left-color: #b32323;
1534        border-left-color: lab(40% 56.6 39);
1535      }
1536
1537      .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
1538        border-left-color: #b32323;
1539        border-left-color: lab(40% 56.6 39);
1540      }
1541
1542      .foo:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
1543        border-right-color: #b32323;
1544        border-right-color: lab(40% 56.6 39);
1545      }
1546
1547      .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
1548        border-right-color: #b32323;
1549        border-right-color: lab(40% 56.6 39);
1550      }
1551    "#},
1552      Browsers {
1553        safari: Some(8 << 16),
1554        ..Browsers::default()
1555      },
1556    );
1557
1558    prefix_test(
1559      r#"
1560      .foo {
1561        border-inline-end-color: lab(40% 56.6 39);
1562      }
1563    "#,
1564      indoc! {r#"
1565      .foo:not(:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
1566        border-right-color: #b32323;
1567        border-right-color: lab(40% 56.6 39);
1568      }
1569
1570      .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
1571        border-right-color: #b32323;
1572        border-right-color: lab(40% 56.6 39);
1573      }
1574
1575      .foo:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
1576        border-left-color: #b32323;
1577        border-left-color: lab(40% 56.6 39);
1578      }
1579
1580      .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
1581        border-left-color: #b32323;
1582        border-left-color: lab(40% 56.6 39);
1583      }
1584    "#},
1585      Browsers {
1586        safari: Some(8 << 16),
1587        ..Browsers::default()
1588      },
1589    );
1590
1591    prefix_test(
1592      r#"
1593      .foo {
1594        border-inline-start-color: lab(40% 56.6 39);
1595        border-inline-end-color: lch(50.998% 135.363 338);
1596      }
1597    "#,
1598      indoc! {r#"
1599      .foo:not(:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
1600        border-left-color: #b32323;
1601        border-left-color: lab(40% 56.6 39);
1602        border-right-color: #ee00be;
1603        border-right-color: lch(50.998% 135.363 338);
1604      }
1605
1606      .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
1607        border-left-color: #b32323;
1608        border-left-color: lab(40% 56.6 39);
1609        border-right-color: #ee00be;
1610        border-right-color: lch(50.998% 135.363 338);
1611      }
1612
1613      .foo:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
1614        border-left-color: #ee00be;
1615        border-left-color: lch(50.998% 135.363 338);
1616        border-right-color: #b32323;
1617        border-right-color: lab(40% 56.6 39);
1618      }
1619
1620      .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
1621        border-left-color: #ee00be;
1622        border-left-color: lch(50.998% 135.363 338);
1623        border-right-color: #b32323;
1624        border-right-color: lab(40% 56.6 39);
1625      }
1626    "#},
1627      Browsers {
1628        safari: Some(8 << 16),
1629        ..Browsers::default()
1630      },
1631    );
1632
1633    prefix_test(
1634      r#"
1635      .foo {
1636        border-inline-start-color: lab(40% 56.6 39);
1637        border-inline-end-color: lch(50.998% 135.363 338);
1638      }
1639    "#,
1640      indoc! {r#"
1641      .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
1642        border-left-color: #b32323;
1643        border-left-color: color(display-p3 .643308 .192455 .167712);
1644        border-left-color: lab(40% 56.6 39);
1645        border-right-color: #ee00be;
1646        border-right-color: color(display-p3 .972962 -.362078 .804206);
1647        border-right-color: lch(50.998% 135.363 338);
1648      }
1649
1650      .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
1651        border-left-color: #ee00be;
1652        border-left-color: color(display-p3 .972962 -.362078 .804206);
1653        border-left-color: lch(50.998% 135.363 338);
1654        border-right-color: #b32323;
1655        border-right-color: color(display-p3 .643308 .192455 .167712);
1656        border-right-color: lab(40% 56.6 39);
1657      }
1658    "#},
1659      Browsers {
1660        chrome: Some(8 << 16),
1661        safari: Some(14 << 16),
1662        ..Browsers::default()
1663      },
1664    );
1665
1666    prefix_test(
1667      r#"
1668      .foo {
1669        border-inline-start: 2px solid lab(40% 56.6 39);
1670      }
1671    "#,
1672      indoc! {r#"
1673      .foo:not(:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
1674        border-left: 2px solid #b32323;
1675        border-left: 2px solid lab(40% 56.6 39);
1676      }
1677
1678      .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
1679        border-left: 2px solid #b32323;
1680        border-left: 2px solid lab(40% 56.6 39);
1681      }
1682
1683      .foo:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
1684        border-right: 2px solid #b32323;
1685        border-right: 2px solid lab(40% 56.6 39);
1686      }
1687
1688      .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
1689        border-right: 2px solid #b32323;
1690        border-right: 2px solid lab(40% 56.6 39);
1691      }
1692    "#},
1693      Browsers {
1694        safari: Some(8 << 16),
1695        ..Browsers::default()
1696      },
1697    );
1698
1699    prefix_test(
1700      r#"
1701      .foo {
1702        border-inline-end: 2px solid lab(40% 56.6 39);
1703      }
1704    "#,
1705      indoc! {r#"
1706      .foo:not(:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
1707        border-right: 2px solid #b32323;
1708        border-right: 2px solid lab(40% 56.6 39);
1709      }
1710
1711      .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
1712        border-right: 2px solid #b32323;
1713        border-right: 2px solid lab(40% 56.6 39);
1714      }
1715
1716      .foo:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
1717        border-left: 2px solid #b32323;
1718        border-left: 2px solid lab(40% 56.6 39);
1719      }
1720
1721      .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
1722        border-left: 2px solid #b32323;
1723        border-left: 2px solid lab(40% 56.6 39);
1724      }
1725    "#},
1726      Browsers {
1727        safari: Some(8 << 16),
1728        ..Browsers::default()
1729      },
1730    );
1731
1732    prefix_test(
1733      r#"
1734      .foo {
1735        border-inline-end: var(--border-width) solid lab(40% 56.6 39);
1736      }
1737    "#,
1738      indoc! {r#"
1739      .foo:not(:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
1740        border-right: var(--border-width) solid #b32323;
1741      }
1742
1743      .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
1744        border-right: var(--border-width) solid #b32323;
1745      }
1746
1747      @supports (color: lab(0% 0 0)) {
1748        .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
1749          border-right: var(--border-width) solid lab(40% 56.6 39);
1750        }
1751      }
1752
1753      .foo:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
1754        border-left: var(--border-width) solid #b32323;
1755      }
1756
1757      .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
1758        border-left: var(--border-width) solid #b32323;
1759      }
1760
1761      @supports (color: lab(0% 0 0)) {
1762        .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
1763          border-left: var(--border-width) solid lab(40% 56.6 39);
1764        }
1765      }
1766    "#},
1767      Browsers {
1768        safari: Some(8 << 16),
1769        ..Browsers::default()
1770      },
1771    );
1772
1773    prefix_test(
1774      r#"
1775      .foo {
1776        border-inline-start: 2px solid red;
1777        border-inline-end: 2px solid red;
1778      }
1779    "#,
1780      indoc! {r#"
1781      .foo {
1782        border-inline-start: 2px solid red;
1783        border-inline-end: 2px solid red;
1784      }
1785    "#
1786      },
1787      Browsers {
1788        safari: Some(13 << 16),
1789        ..Browsers::default()
1790      },
1791    );
1792
1793    prefix_test(
1794      r#"
1795      .foo {
1796        border-inline-start: 2px solid red;
1797        border-inline-end: 2px solid red;
1798      }
1799    "#,
1800      indoc! {r#"
1801      .foo {
1802        border-inline: 2px solid red;
1803      }
1804    "#
1805      },
1806      Browsers {
1807        safari: Some(15 << 16),
1808        ..Browsers::default()
1809      },
1810    );
1811
1812    prefix_test(
1813      r#"
1814      .foo {
1815        border-width: 22px;
1816        border-width: max(2cqw, 22px);
1817      }
1818    "#,
1819      indoc! {r#"
1820      .foo {
1821        border-width: 22px;
1822        border-width: max(2cqw, 22px);
1823      }
1824    "#
1825      },
1826      Browsers {
1827        safari: Some(14 << 16),
1828        ..Browsers::default()
1829      },
1830    );
1831    prefix_test(
1832      r#"
1833      .foo {
1834        border-width: 22px;
1835        border-width: max(2cqw, 22px);
1836      }
1837    "#,
1838      indoc! {r#"
1839      .foo {
1840        border-width: max(2cqw, 22px);
1841      }
1842    "#
1843      },
1844      Browsers {
1845        safari: Some(16 << 16),
1846        ..Browsers::default()
1847      },
1848    );
1849    prefix_test(
1850      r#"
1851      .foo {
1852        border-color: #4263eb;
1853        border-color: color(display-p3 0 .5 1);
1854      }
1855    "#,
1856      indoc! {r#"
1857      .foo {
1858        border-color: #4263eb;
1859        border-color: color(display-p3 0 .5 1);
1860      }
1861    "#
1862      },
1863      Browsers {
1864        chrome: Some(99 << 16),
1865        ..Browsers::default()
1866      },
1867    );
1868    prefix_test(
1869      r#"
1870      .foo {
1871        border-color: #4263eb;
1872        border-color: color(display-p3 0 .5 1);
1873      }
1874    "#,
1875      indoc! {r#"
1876      .foo {
1877        border-color: color(display-p3 0 .5 1);
1878      }
1879    "#
1880      },
1881      Browsers {
1882        safari: Some(16 << 16),
1883        ..Browsers::default()
1884      },
1885    );
1886    prefix_test(
1887      r#"
1888      .foo {
1889        border: 1px solid #4263eb;
1890        border-color: color(display-p3 0 .5 1);
1891      }
1892    "#,
1893      indoc! {r#"
1894      .foo {
1895        border: 1px solid #4263eb;
1896        border-color: color(display-p3 0 .5 1);
1897      }
1898    "#
1899      },
1900      Browsers {
1901        chrome: Some(99 << 16),
1902        ..Browsers::default()
1903      },
1904    );
1905    prefix_test(
1906      r#"
1907      .foo {
1908        border: 1px solid #4263eb;
1909        border-color: color(display-p3 0 .5 1);
1910      }
1911    "#,
1912      indoc! {r#"
1913      .foo {
1914        border: 1px solid color(display-p3 0 .5 1);
1915      }
1916    "#
1917      },
1918      Browsers {
1919        safari: Some(16 << 16),
1920        ..Browsers::default()
1921      },
1922    );
1923    prefix_test(
1924      r#"
1925      .foo {
1926        border-color: var(--fallback);
1927        border-color: color(display-p3 0 .5 1);
1928      }
1929    "#,
1930      indoc! {r#"
1931      .foo {
1932        border-color: var(--fallback);
1933        border-color: color(display-p3 0 .5 1);
1934      }
1935    "#
1936      },
1937      Browsers {
1938        chrome: Some(99 << 16),
1939        ..Browsers::default()
1940      },
1941    );
1942  }
1943
1944  #[test]
1945  pub fn test_border_image() {
1946    test(
1947      r#"
1948      .foo {
1949        border-image: url(test.png) 60;
1950      }
1951    "#,
1952      indoc! {r#"
1953      .foo {
1954        border-image: url("test.png") 60;
1955      }
1956    "#
1957      },
1958    );
1959
1960    test(
1961      r#"
1962      .foo {
1963        border-image: url(test.png) 60;
1964        border-image-source: url(foo.png);
1965      }
1966    "#,
1967      indoc! {r#"
1968      .foo {
1969        border-image: url("foo.png") 60;
1970      }
1971    "#
1972      },
1973    );
1974
1975    test(
1976      r#"
1977      .foo {
1978        border-image-source: url(foo.png);
1979        border-image-slice: 10 40 10 40 fill;
1980        border-image-width: 10px;
1981        border-image-outset: 0;
1982        border-image-repeat: round round;
1983      }
1984    "#,
1985      indoc! {r#"
1986      .foo {
1987        border-image: url("foo.png") 10 40 fill / 10px round;
1988      }
1989    "#
1990      },
1991    );
1992
1993    test(
1994      r#"
1995      .foo {
1996        border-image: url(foo.png) 60;
1997        border-image-source: var(--test);
1998      }
1999    "#,
2000      indoc! {r#"
2001      .foo {
2002        border-image: url("foo.png") 60;
2003        border-image-source: var(--test);
2004      }
2005    "#
2006      },
2007    );
2008
2009    test(
2010      r#"
2011      .foo {
2012        -webkit-border-image: url("test.png") 60;
2013      }
2014    "#,
2015      indoc! {r#"
2016      .foo {
2017        -webkit-border-image: url("test.png") 60;
2018      }
2019    "#
2020      },
2021    );
2022
2023    test(
2024      r#"
2025      .foo {
2026        -webkit-border-image: url("test.png") 60;
2027        border-image: url("test.png") 60;
2028      }
2029    "#,
2030      indoc! {r#"
2031      .foo {
2032        -webkit-border-image: url("test.png") 60;
2033        border-image: url("test.png") 60;
2034      }
2035    "#
2036      },
2037    );
2038
2039    test(
2040      r#"
2041      .foo {
2042        -webkit-border-image: url("test.png") 60;
2043        border-image-source: url(foo.png);
2044      }
2045    "#,
2046      indoc! {r#"
2047      .foo {
2048        -webkit-border-image: url("test.png") 60;
2049        border-image-source: url("foo.png");
2050      }
2051    "#
2052      },
2053    );
2054
2055    test(
2056      r#"
2057      .foo {
2058        border: 1px solid red;
2059        border-image: url(test.png) 60;
2060      }
2061    "#,
2062      indoc! {r#"
2063      .foo {
2064        border: 1px solid red;
2065        border-image: url("test.png") 60;
2066      }
2067    "#
2068      },
2069    );
2070
2071    test(
2072      r#"
2073      .foo {
2074        border-image: url(test.png) 60;
2075        border: 1px solid red;
2076      }
2077    "#,
2078      indoc! {r#"
2079      .foo {
2080        border: 1px solid red;
2081      }
2082    "#
2083      },
2084    );
2085
2086    test(
2087      r#"
2088      .foo {
2089        border: 1px solid red;
2090        border-image: var(--border-image);
2091      }
2092    "#,
2093      indoc! {r#"
2094      .foo {
2095        border: 1px solid red;
2096        border-image: var(--border-image);
2097      }
2098    "#
2099      },
2100    );
2101
2102    prefix_test(
2103      r#"
2104      .foo {
2105        border-image: url("test.png") 60;
2106      }
2107    "#,
2108      indoc! {r#"
2109      .foo {
2110        -webkit-border-image: url("test.png") 60;
2111        -moz-border-image: url("test.png") 60;
2112        -o-border-image: url("test.png") 60;
2113        border-image: url("test.png") 60;
2114      }
2115    "#
2116      },
2117      Browsers {
2118        safari: Some(4 << 16),
2119        firefox: Some(4 << 16),
2120        opera: Some(12 << 16),
2121        ..Browsers::default()
2122      },
2123    );
2124
2125    prefix_test(
2126      r#"
2127      .foo {
2128        border-image: url(foo.png) 10 40 fill / 10px round;
2129      }
2130    "#,
2131      indoc! {r#"
2132      .foo {
2133        border-image: url("foo.png") 10 40 fill / 10px round;
2134      }
2135    "#
2136      },
2137      Browsers {
2138        safari: Some(4 << 16),
2139        firefox: Some(4 << 16),
2140        opera: Some(12 << 16),
2141        ..Browsers::default()
2142      },
2143    );
2144
2145    prefix_test(
2146      r#"
2147      .foo {
2148        border-image: var(--test) 60;
2149      }
2150    "#,
2151      indoc! {r#"
2152      .foo {
2153        -webkit-border-image: var(--test) 60;
2154        -moz-border-image: var(--test) 60;
2155        -o-border-image: var(--test) 60;
2156        border-image: var(--test) 60;
2157      }
2158    "#
2159      },
2160      Browsers {
2161        safari: Some(4 << 16),
2162        firefox: Some(4 << 16),
2163        opera: Some(12 << 16),
2164        ..Browsers::default()
2165      },
2166    );
2167
2168    prefix_test(
2169      r#"
2170      .foo {
2171        -webkit-border-image: url(foo.png) 60;
2172        -moz-border-image: url(foo.png) 60;
2173        -o-border-image: url(foo.png) 60;
2174        border-image: url(foo.png) 60;
2175      }
2176    "#,
2177      indoc! {r#"
2178      .foo {
2179        border-image: url("foo.png") 60;
2180      }
2181    "#
2182      },
2183      Browsers {
2184        chrome: Some(15 << 16),
2185        ..Browsers::default()
2186      },
2187    );
2188
2189    prefix_test(
2190      r#"
2191      .foo {
2192        border-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 60;
2193      }
2194    "#,
2195      indoc! {r#"
2196      .foo {
2197        -webkit-border-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ff0f0e), to(#7773ff)) 60;
2198        -webkit-border-image: -webkit-linear-gradient(top, #ff0f0e, #7773ff) 60;
2199        border-image: linear-gradient(#ff0f0e, #7773ff) 60;
2200        border-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 60;
2201      }
2202    "#
2203      },
2204      Browsers {
2205        chrome: Some(8 << 16),
2206        ..Browsers::default()
2207      },
2208    );
2209
2210    prefix_test(
2211      r#"
2212      .foo {
2213        border-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 60;
2214      }
2215    "#,
2216      indoc! {r#"
2217      .foo {
2218        -webkit-border-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ff0f0e), to(#7773ff)) 60;
2219        -webkit-border-image: -webkit-linear-gradient(top, #ff0f0e, #7773ff) 60;
2220        -moz-border-image: -moz-linear-gradient(top, #ff0f0e, #7773ff) 60;
2221        border-image: linear-gradient(#ff0f0e, #7773ff) 60;
2222        border-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 60;
2223      }
2224    "#
2225      },
2226      Browsers {
2227        chrome: Some(8 << 16),
2228        firefox: Some(4 << 16),
2229        ..Browsers::default()
2230      },
2231    );
2232
2233    prefix_test(
2234      r#"
2235      .foo {
2236        border-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 60;
2237      }
2238    "#,
2239      indoc! {r#"
2240      .foo {
2241        border-image: -webkit-linear-gradient(top, #ff0f0e, #7773ff) 60;
2242        border-image: -moz-linear-gradient(top, #ff0f0e, #7773ff) 60;
2243        border-image: linear-gradient(#ff0f0e, #7773ff) 60;
2244        border-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 60;
2245      }
2246    "#
2247      },
2248      Browsers {
2249        chrome: Some(15 << 16),
2250        firefox: Some(15 << 16),
2251        ..Browsers::default()
2252      },
2253    );
2254
2255    prefix_test(
2256      r#"
2257      .foo {
2258        border-image-source: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
2259      }
2260    "#,
2261      indoc! {r#"
2262      .foo {
2263        border-image-source: -webkit-linear-gradient(top, #ff0f0e, #7773ff);
2264        border-image-source: linear-gradient(#ff0f0e, #7773ff);
2265        border-image-source: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
2266      }
2267    "#
2268      },
2269      Browsers {
2270        chrome: Some(15 << 16),
2271        ..Browsers::default()
2272      },
2273    );
2274
2275    prefix_test(
2276      r#"
2277      .foo {
2278        border-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) var(--foo);
2279      }
2280    "#,
2281      indoc! {r#"
2282      .foo {
2283        border-image: linear-gradient(#ff0f0e, #7773ff) var(--foo);
2284      }
2285
2286      @supports (color: lab(0% 0 0)) {
2287        .foo {
2288          border-image: linear-gradient(lab(56.208% 94.4644 98.8928), lab(51% 70.4544 -115.586)) var(--foo);
2289        }
2290      }
2291    "#
2292      },
2293      Browsers {
2294        chrome: Some(90 << 16),
2295        ..Browsers::default()
2296      },
2297    );
2298
2299    prefix_test(
2300      r#"
2301      .foo {
2302        border-image-source: linear-gradient(red, green);
2303        border-image-source: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
2304      }
2305    "#,
2306      indoc! {r#"
2307      .foo {
2308        border-image-source: linear-gradient(red, green);
2309        border-image-source: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
2310      }
2311    "#
2312      },
2313      Browsers {
2314        chrome: Some(95 << 16),
2315        ..Browsers::default()
2316      },
2317    );
2318
2319    prefix_test(
2320      r#"
2321      .foo {
2322        border-image-source: linear-gradient(red, green);
2323        border-image-source: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
2324      }
2325    "#,
2326      indoc! {r#"
2327      .foo {
2328        border-image-source: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
2329      }
2330    "#
2331      },
2332      Browsers {
2333        chrome: Some(112 << 16),
2334        ..Browsers::default()
2335      },
2336    );
2337
2338    prefix_test(
2339      r#"
2340      .foo {
2341        border-image: linear-gradient(red, green);
2342        border-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
2343      }
2344    "#,
2345      indoc! {r#"
2346      .foo {
2347        border-image: linear-gradient(red, green);
2348        border-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
2349      }
2350    "#
2351      },
2352      Browsers {
2353        chrome: Some(95 << 16),
2354        ..Browsers::default()
2355      },
2356    );
2357
2358    prefix_test(
2359      r#"
2360      .foo {
2361        border-image: var(--fallback);
2362        border-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
2363      }
2364    "#,
2365      indoc! {r#"
2366      .foo {
2367        border-image: var(--fallback);
2368        border-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
2369      }
2370    "#
2371      },
2372      Browsers {
2373        chrome: Some(95 << 16),
2374        ..Browsers::default()
2375      },
2376    );
2377
2378    prefix_test(
2379      r#"
2380      .foo {
2381        border-image: url("fallback.png") 10 40 fill / 10px;
2382        border-image: url("main.png") 10 40 fill / 10px space;
2383      }
2384    "#,
2385      indoc! {r#"
2386      .foo {
2387        border-image: url("fallback.png") 10 40 fill / 10px;
2388        border-image: url("main.png") 10 40 fill / 10px space;
2389      }
2390    "#
2391      },
2392      Browsers {
2393        chrome: Some(50 << 16),
2394        ..Browsers::default()
2395      },
2396    );
2397
2398    prefix_test(
2399      r#"
2400      .foo {
2401        border-image: url("fallback.png") 10 40 fill / 10px;
2402        border-image: url("main.png") 10 40 fill / 10px space;
2403      }
2404    "#,
2405      indoc! {r#"
2406      .foo {
2407        border-image: url("main.png") 10 40 fill / 10px space;
2408      }
2409    "#
2410      },
2411      Browsers {
2412        chrome: Some(56 << 16),
2413        ..Browsers::default()
2414      },
2415    );
2416
2417    minify_test(".foo { border: none green }", ".foo{border:green}");
2418  }
2419
2420  #[test]
2421  pub fn test_border_radius() {
2422    test(
2423      r#"
2424      .foo {
2425        border-radius: 10px 100px 10px 100px;
2426      }
2427    "#,
2428      indoc! {r#"
2429      .foo {
2430        border-radius: 10px 100px;
2431      }
2432    "#
2433      },
2434    );
2435
2436    test(
2437      r#"
2438      .foo {
2439        border-radius: 10px 100px 10px 100px / 120px 120px;
2440      }
2441    "#,
2442      indoc! {r#"
2443      .foo {
2444        border-radius: 10px 100px / 120px;
2445      }
2446    "#
2447      },
2448    );
2449
2450    test(
2451      r#"
2452      .foo {
2453        border-top-left-radius: 10px 120px;
2454        border-top-right-radius: 100px 120px;
2455        border-bottom-right-radius: 100px 120px;
2456        border-bottom-left-radius: 10px 120px;
2457      }
2458    "#,
2459      indoc! {r#"
2460      .foo {
2461        border-radius: 10px 100px 100px 10px / 120px;
2462      }
2463    "#
2464      },
2465    );
2466
2467    test(
2468      r#"
2469      .foo {
2470        border-top-left-radius: 4px 2px;
2471        border-top-right-radius: 3px 4px;
2472        border-bottom-right-radius: 6px 2px;
2473        border-bottom-left-radius: 3px 4px;
2474      }
2475    "#,
2476      indoc! {r#"
2477      .foo {
2478        border-radius: 4px 3px 6px / 2px 4px;
2479      }
2480    "#
2481      },
2482    );
2483
2484    test(
2485      r#"
2486      .foo {
2487        border-top-left-radius: 1% 2%;
2488        border-top-right-radius: 3% 4%;
2489        border-bottom-right-radius: 5% 6%;
2490        border-bottom-left-radius: 7% 8%;
2491      }
2492    "#,
2493      indoc! {r#"
2494      .foo {
2495        border-radius: 1% 3% 5% 7% / 2% 4% 6% 8%;
2496      }
2497    "#
2498      },
2499    );
2500
2501    test(
2502      r#"
2503      .foo {
2504        border-radius: 10px 100px 10px 100px / 120px 120px;
2505        border-start-start-radius: 10px;
2506      }
2507    "#,
2508      indoc! {r#"
2509      .foo {
2510        border-radius: 10px 100px / 120px;
2511        border-start-start-radius: 10px;
2512      }
2513    "#
2514      },
2515    );
2516
2517    test(
2518      r#"
2519      .foo {
2520        border-start-start-radius: 10px;
2521        border-radius: 10px 100px 10px 100px / 120px 120px;
2522      }
2523    "#,
2524      indoc! {r#"
2525      .foo {
2526        border-radius: 10px 100px / 120px;
2527      }
2528    "#
2529      },
2530    );
2531
2532    test(
2533      r#"
2534      .foo {
2535        border-top-left-radius: 10px 120px;
2536        border-top-right-radius: 100px 120px;
2537        border-start-start-radius: 10px;
2538        border-bottom-right-radius: 100px 120px;
2539        border-bottom-left-radius: 10px 120px;
2540      }
2541    "#,
2542      indoc! {r#"
2543      .foo {
2544        border-top-left-radius: 10px 120px;
2545        border-top-right-radius: 100px 120px;
2546        border-start-start-radius: 10px;
2547        border-bottom-right-radius: 100px 120px;
2548        border-bottom-left-radius: 10px 120px;
2549      }
2550    "#
2551      },
2552    );
2553
2554    test(
2555      r#"
2556      .foo {
2557        border-radius: 10px;
2558        border-top-left-radius: 20px;
2559      }
2560    "#,
2561      indoc! {r#"
2562      .foo {
2563        border-radius: 20px 10px 10px;
2564      }
2565    "#
2566      },
2567    );
2568
2569    test(
2570      r#"
2571      .foo {
2572        border-radius: 10px;
2573        border-top-left-radius: var(--test);
2574      }
2575    "#,
2576      indoc! {r#"
2577      .foo {
2578        border-radius: 10px;
2579        border-top-left-radius: var(--test);
2580      }
2581    "#
2582      },
2583    );
2584
2585    test(
2586      r#"
2587      .foo {
2588        -webkit-border-radius: 10px 100px 10px 100px;
2589        -moz-border-radius: 10px 100px 10px 100px;
2590        border-radius: 10px 100px 10px 100px;
2591      }
2592    "#,
2593      indoc! {r#"
2594      .foo {
2595        -webkit-border-radius: 10px 100px;
2596        -moz-border-radius: 10px 100px;
2597        border-radius: 10px 100px;
2598      }
2599    "#
2600      },
2601    );
2602
2603    test(
2604      r#"
2605      .foo {
2606        -webkit-border-radius: 10px 100px 10px 100px;
2607        -moz-border-radius: 20px;
2608        border-radius: 30px;
2609      }
2610    "#,
2611      indoc! {r#"
2612      .foo {
2613        -webkit-border-radius: 10px 100px;
2614        -moz-border-radius: 20px;
2615        border-radius: 30px;
2616      }
2617    "#
2618      },
2619    );
2620
2621    test(
2622      r#"
2623      .foo {
2624        -webkit-border-top-left-radius: 10px;
2625        -moz-border-top-left-radius: 10px;
2626        border-top-left-radius: 10px;
2627      }
2628    "#,
2629      indoc! {r#"
2630      .foo {
2631        -webkit-border-top-left-radius: 10px;
2632        -moz-border-top-left-radius: 10px;
2633        border-top-left-radius: 10px;
2634      }
2635    "#
2636      },
2637    );
2638
2639    prefix_test(
2640      r#"
2641      .foo {
2642        border-radius: 30px;
2643      }
2644    "#,
2645      indoc! {r#"
2646      .foo {
2647        -webkit-border-radius: 30px;
2648        -moz-border-radius: 30px;
2649        border-radius: 30px;
2650      }
2651    "#
2652      },
2653      Browsers {
2654        safari: Some(4 << 16),
2655        firefox: Some(3 << 16),
2656        ..Browsers::default()
2657      },
2658    );
2659
2660    prefix_test(
2661      r#"
2662      .foo {
2663        border-top-left-radius: 30px;
2664      }
2665    "#,
2666      indoc! {r#"
2667      .foo {
2668        -webkit-border-top-left-radius: 30px;
2669        -moz-border-top-left-radius: 30px;
2670        border-top-left-radius: 30px;
2671      }
2672    "#
2673      },
2674      Browsers {
2675        safari: Some(4 << 16),
2676        firefox: Some(3 << 16),
2677        ..Browsers::default()
2678      },
2679    );
2680
2681    prefix_test(
2682      r#"
2683      .foo {
2684        -webkit-border-radius: 30px;
2685        -moz-border-radius: 30px;
2686        border-radius: 30px;
2687      }
2688    "#,
2689      indoc! {r#"
2690      .foo {
2691        border-radius: 30px;
2692      }
2693    "#
2694      },
2695      Browsers {
2696        safari: Some(14 << 16),
2697        firefox: Some(46 << 16),
2698        ..Browsers::default()
2699      },
2700    );
2701
2702    prefix_test(
2703      r#"
2704      .foo {
2705        -webkit-border-top-left-radius: 30px;
2706        -moz-border-top-left-radius: 30px;
2707        border-top-left-radius: 30px;
2708      }
2709    "#,
2710      indoc! {r#"
2711      .foo {
2712        border-top-left-radius: 30px;
2713      }
2714    "#
2715      },
2716      Browsers {
2717        safari: Some(14 << 16),
2718        firefox: Some(46 << 16),
2719        ..Browsers::default()
2720      },
2721    );
2722
2723    prefix_test(
2724      r#"
2725      .foo {
2726        -webkit-border-radius: 30px;
2727        -moz-border-radius: 30px;
2728      }
2729    "#,
2730      indoc! {r#"
2731      .foo {
2732        -webkit-border-radius: 30px;
2733        -moz-border-radius: 30px;
2734      }
2735    "#
2736      },
2737      Browsers {
2738        safari: Some(14 << 16),
2739        firefox: Some(46 << 16),
2740        ..Browsers::default()
2741      },
2742    );
2743
2744    prefix_test(
2745      r#"
2746      .foo {
2747        -webkit-border-top-left-radius: 30px;
2748        -moz-border-top-right-radius: 30px;
2749        border-bottom-right-radius: 30px;
2750        border-bottom-left-radius: 30px;
2751      }
2752    "#,
2753      indoc! {r#"
2754      .foo {
2755        -webkit-border-top-left-radius: 30px;
2756        -moz-border-top-right-radius: 30px;
2757        border-bottom-right-radius: 30px;
2758        border-bottom-left-radius: 30px;
2759      }
2760    "#
2761      },
2762      Browsers {
2763        safari: Some(14 << 16),
2764        firefox: Some(46 << 16),
2765        ..Browsers::default()
2766      },
2767    );
2768
2769    prefix_test(
2770      r#"
2771      .foo {
2772        border-radius: var(--test);
2773      }
2774    "#,
2775      indoc! {r#"
2776      .foo {
2777        -webkit-border-radius: var(--test);
2778        -moz-border-radius: var(--test);
2779        border-radius: var(--test);
2780      }
2781    "#
2782      },
2783      Browsers {
2784        safari: Some(4 << 16),
2785        firefox: Some(3 << 16),
2786        ..Browsers::default()
2787      },
2788    );
2789
2790    prefix_test(
2791      r#"
2792      .foo {
2793        border-start-start-radius: 5px;
2794      }
2795    "#,
2796      indoc! {r#"
2797      .foo:not(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
2798        border-top-left-radius: 5px;
2799      }
2800
2801      .foo:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) {
2802        border-top-right-radius: 5px;
2803      }
2804    "#
2805      },
2806      Browsers {
2807        safari: Some(12 << 16),
2808        ..Browsers::default()
2809      },
2810    );
2811
2812    prefix_test(
2813      r#"
2814      .foo {
2815        border-start-start-radius: 5px;
2816        border-start-end-radius: 10px;
2817      }
2818    "#,
2819      indoc! {r#"
2820      .foo:not(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
2821        border-top-left-radius: 5px;
2822        border-top-right-radius: 10px;
2823      }
2824
2825      .foo:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) {
2826        border-top-left-radius: 10px;
2827        border-top-right-radius: 5px;
2828      }
2829    "#
2830      },
2831      Browsers {
2832        safari: Some(12 << 16),
2833        ..Browsers::default()
2834      },
2835    );
2836
2837    prefix_test(
2838      r#"
2839      .foo {
2840        border-end-end-radius: 10px;
2841        border-end-start-radius: 5px;
2842      }
2843    "#,
2844      indoc! {r#"
2845      .foo:not(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
2846        border-bottom-right-radius: 10px;
2847        border-bottom-left-radius: 5px;
2848      }
2849
2850      .foo:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) {
2851        border-bottom-right-radius: 5px;
2852        border-bottom-left-radius: 10px;
2853      }
2854    "#
2855      },
2856      Browsers {
2857        safari: Some(12 << 16),
2858        ..Browsers::default()
2859      },
2860    );
2861
2862    prefix_test(
2863      r#"
2864      .foo {
2865        border-start-start-radius: var(--radius);
2866      }
2867    "#,
2868      indoc! {r#"
2869      .foo:not(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
2870        border-top-left-radius: var(--radius);
2871      }
2872
2873      .foo:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) {
2874        border-top-right-radius: var(--radius);
2875      }
2876    "#
2877      },
2878      Browsers {
2879        safari: Some(12 << 16),
2880        ..Browsers::default()
2881      },
2882    );
2883
2884    prefix_test(
2885      r#"
2886      .foo {
2887        border-start-start-radius: var(--start);
2888        border-start-end-radius: var(--end);
2889      }
2890    "#,
2891      indoc! {r#"
2892      .foo:not(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
2893        border-top-left-radius: var(--start);
2894        border-top-right-radius: var(--end);
2895      }
2896
2897      .foo:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) {
2898        border-top-right-radius: var(--start);
2899        border-top-left-radius: var(--end);
2900      }
2901    "#
2902      },
2903      Browsers {
2904        safari: Some(12 << 16),
2905        ..Browsers::default()
2906      },
2907    );
2908  }
2909
2910  #[test]
2911  pub fn test_outline() {
2912    test(
2913      r#"
2914      .foo {
2915        outline-width: 2px;
2916        outline-style: solid;
2917        outline-color: blue;
2918      }
2919    "#,
2920      indoc! {r#"
2921      .foo {
2922        outline: 2px solid #00f;
2923      }
2924    "#
2925      },
2926    );
2927
2928    test(
2929      r#"
2930      .foo {
2931        outline: 2px solid blue;
2932      }
2933    "#,
2934      indoc! {r#"
2935      .foo {
2936        outline: 2px solid #00f;
2937      }
2938    "#
2939      },
2940    );
2941
2942    test(
2943      r#"
2944      .foo {
2945        outline: 2px solid red;
2946        outline-color: blue;
2947      }
2948    "#,
2949      indoc! {r#"
2950      .foo {
2951        outline: 2px solid #00f;
2952      }
2953    "#
2954      },
2955    );
2956
2957    test(
2958      r#"
2959      .foo {
2960        outline: 2px solid yellow;
2961        outline-color: var(--color);
2962      }
2963    "#,
2964      indoc! {r#"
2965      .foo {
2966        outline: 2px solid #ff0;
2967        outline-color: var(--color);
2968      }
2969    "#
2970      },
2971    );
2972
2973    prefix_test(
2974      ".foo { outline-color: lab(40% 56.6 39) }",
2975      indoc! { r#"
2976        .foo {
2977          outline-color: #b32323;
2978          outline-color: lab(40% 56.6 39);
2979        }
2980      "#},
2981      Browsers {
2982        chrome: Some(90 << 16),
2983        ..Browsers::default()
2984      },
2985    );
2986
2987    prefix_test(
2988      ".foo { outline: 2px solid lab(40% 56.6 39) }",
2989      indoc! { r#"
2990        .foo {
2991          outline: 2px solid #b32323;
2992          outline: 2px solid lab(40% 56.6 39);
2993        }
2994      "#},
2995      Browsers {
2996        chrome: Some(90 << 16),
2997        ..Browsers::default()
2998      },
2999    );
3000
3001    prefix_test(
3002      ".foo { outline: var(--width) solid lab(40% 56.6 39) }",
3003      indoc! { r#"
3004        .foo {
3005          outline: var(--width) solid #b32323;
3006        }
3007
3008        @supports (color: lab(0% 0 0)) {
3009          .foo {
3010            outline: var(--width) solid lab(40% 56.6 39);
3011          }
3012        }
3013      "#},
3014      Browsers {
3015        chrome: Some(90 << 16),
3016        ..Browsers::default()
3017      },
3018    );
3019  }
3020
3021  #[test]
3022  pub fn test_margin() {
3023    test(
3024      r#"
3025      .foo {
3026        margin-left: 10px;
3027        margin-right: 10px;
3028        margin-top: 20px;
3029        margin-bottom: 20px;
3030      }
3031    "#,
3032      indoc! {r#"
3033      .foo {
3034        margin: 20px 10px;
3035      }
3036    "#
3037      },
3038    );
3039
3040    test(
3041      r#"
3042      .foo {
3043        margin-block-start: 15px;
3044        margin-block-end: 15px;
3045      }
3046    "#,
3047      indoc! {r#"
3048      .foo {
3049        margin-block: 15px;
3050      }
3051    "#
3052      },
3053    );
3054
3055    test(
3056      r#"
3057      .foo {
3058        margin-left: 10px;
3059        margin-right: 10px;
3060        margin-inline-start: 15px;
3061        margin-inline-end: 15px;
3062        margin-top: 20px;
3063        margin-bottom: 20px;
3064
3065      }
3066    "#,
3067      indoc! {r#"
3068      .foo {
3069        margin-left: 10px;
3070        margin-right: 10px;
3071        margin-inline: 15px;
3072        margin-top: 20px;
3073        margin-bottom: 20px;
3074      }
3075    "#
3076      },
3077    );
3078
3079    test(
3080      r#"
3081      .foo {
3082        margin: 10px;
3083        margin-top: 20px;
3084      }
3085    "#,
3086      indoc! {r#"
3087      .foo {
3088        margin: 20px 10px 10px;
3089      }
3090    "#
3091      },
3092    );
3093
3094    test(
3095      r#"
3096      .foo {
3097        margin: 10px;
3098        margin-top: var(--top);
3099      }
3100    "#,
3101      indoc! {r#"
3102      .foo {
3103        margin: 10px;
3104        margin-top: var(--top);
3105      }
3106    "#
3107      },
3108    );
3109
3110    prefix_test(
3111      r#"
3112      .foo {
3113        margin-inline-start: 2px;
3114      }
3115    "#,
3116      indoc! {r#"
3117      .foo:not(:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
3118        margin-left: 2px;
3119      }
3120
3121      .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
3122        margin-left: 2px;
3123      }
3124
3125      .foo:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
3126        margin-right: 2px;
3127      }
3128
3129      .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
3130        margin-right: 2px;
3131      }
3132    "#
3133      },
3134      Browsers {
3135        safari: Some(8 << 16),
3136        ..Browsers::default()
3137      },
3138    );
3139
3140    prefix_test(
3141      r#"
3142      .foo {
3143        margin-inline-start: 2px;
3144        margin-inline-end: 4px;
3145      }
3146    "#,
3147      indoc! {r#"
3148      .foo:not(:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
3149        margin-left: 2px;
3150        margin-right: 4px;
3151      }
3152
3153      .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
3154        margin-left: 2px;
3155        margin-right: 4px;
3156      }
3157
3158      .foo:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
3159        margin-left: 4px;
3160        margin-right: 2px;
3161      }
3162
3163      .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
3164        margin-left: 4px;
3165        margin-right: 2px;
3166      }
3167    "#
3168      },
3169      Browsers {
3170        safari: Some(8 << 16),
3171        ..Browsers::default()
3172      },
3173    );
3174
3175    prefix_test(
3176      r#"
3177      .foo {
3178        margin-inline: 2px;
3179      }
3180    "#,
3181      indoc! {r#"
3182      .foo {
3183        margin-left: 2px;
3184        margin-right: 2px;
3185      }
3186    "#
3187      },
3188      Browsers {
3189        safari: Some(8 << 16),
3190        ..Browsers::default()
3191      },
3192    );
3193
3194    prefix_test(
3195      r#"
3196      .foo {
3197        margin-block-start: 2px;
3198      }
3199    "#,
3200      indoc! {r#"
3201      .foo {
3202        margin-top: 2px;
3203      }
3204    "#
3205      },
3206      Browsers {
3207        safari: Some(8 << 16),
3208        ..Browsers::default()
3209      },
3210    );
3211
3212    prefix_test(
3213      r#"
3214      .foo {
3215        margin-block-end: 2px;
3216      }
3217    "#,
3218      indoc! {r#"
3219      .foo {
3220        margin-bottom: 2px;
3221      }
3222    "#
3223      },
3224      Browsers {
3225        safari: Some(8 << 16),
3226        ..Browsers::default()
3227      },
3228    );
3229
3230    prefix_test(
3231      r#"
3232      .foo {
3233        margin-inline-start: 2px;
3234        margin-inline-end: 2px;
3235      }
3236    "#,
3237      indoc! {r#"
3238      .foo {
3239        margin-inline-start: 2px;
3240        margin-inline-end: 2px;
3241      }
3242    "#
3243      },
3244      Browsers {
3245        safari: Some(13 << 16),
3246        ..Browsers::default()
3247      },
3248    );
3249
3250    prefix_test(
3251      r#"
3252      .foo {
3253        margin-inline: 2px;
3254      }
3255    "#,
3256      indoc! {r#"
3257      .foo {
3258        margin-inline-start: 2px;
3259        margin-inline-end: 2px;
3260      }
3261    "#
3262      },
3263      Browsers {
3264        safari: Some(13 << 16),
3265        ..Browsers::default()
3266      },
3267    );
3268
3269    prefix_test(
3270      r#"
3271      .foo {
3272        margin-inline-start: 2px;
3273        margin-inline-end: 2px;
3274      }
3275    "#,
3276      indoc! {r#"
3277      .foo {
3278        margin-inline: 2px;
3279      }
3280    "#
3281      },
3282      Browsers {
3283        safari: Some(15 << 16),
3284        ..Browsers::default()
3285      },
3286    );
3287
3288    prefix_test(
3289      r#"
3290      .foo {
3291        margin-inline: 2px;
3292      }
3293    "#,
3294      indoc! {r#"
3295      .foo {
3296        margin-inline: 2px;
3297      }
3298    "#
3299      },
3300      Browsers {
3301        safari: Some(15 << 16),
3302        ..Browsers::default()
3303      },
3304    );
3305  }
3306
3307  #[test]
3308  fn test_length() {
3309    for prop in &[
3310      "margin-right",
3311      "margin",
3312      "padding-right",
3313      "padding",
3314      "width",
3315      "height",
3316      "min-height",
3317      "max-height",
3318      "line-height",
3319      "border-radius",
3320    ] {
3321      prefix_test(
3322        &format!(
3323          r#"
3324        .foo {{
3325          {}: 22px;
3326          {}: max(4%, 22px);
3327        }}
3328      "#,
3329          prop, prop
3330        ),
3331        &format!(
3332          indoc! {r#"
3333        .foo {{
3334          {}: 22px;
3335          {}: max(4%, 22px);
3336        }}
3337      "#
3338          },
3339          prop, prop
3340        ),
3341        Browsers {
3342          safari: Some(10 << 16),
3343          ..Browsers::default()
3344        },
3345      );
3346
3347      prefix_test(
3348        &format!(
3349          r#"
3350        .foo {{
3351          {}: 22px;
3352          {}: max(4%, 22px);
3353        }}
3354      "#,
3355          prop, prop
3356        ),
3357        &format!(
3358          indoc! {r#"
3359        .foo {{
3360          {}: max(4%, 22px);
3361        }}
3362      "#
3363          },
3364          prop
3365        ),
3366        Browsers {
3367          safari: Some(14 << 16),
3368          ..Browsers::default()
3369        },
3370      );
3371
3372      prefix_test(
3373        &format!(
3374          r#"
3375        .foo {{
3376          {}: 22px;
3377          {}: max(2cqw, 22px);
3378        }}
3379      "#,
3380          prop, prop
3381        ),
3382        &format!(
3383          indoc! {r#"
3384        .foo {{
3385          {}: 22px;
3386          {}: max(2cqw, 22px);
3387        }}
3388      "#
3389          },
3390          prop, prop
3391        ),
3392        Browsers {
3393          safari: Some(14 << 16),
3394          ..Browsers::default()
3395        },
3396      );
3397      prefix_test(
3398        &format!(
3399          r#"
3400        .foo {{
3401          {}: 22px;
3402          {}: max(2cqw, 22px);
3403        }}
3404      "#,
3405          prop, prop
3406        ),
3407        &format!(
3408          indoc! {r#"
3409        .foo {{
3410          {}: max(2cqw, 22px);
3411        }}
3412      "#
3413          },
3414          prop
3415        ),
3416        Browsers {
3417          safari: Some(16 << 16),
3418          ..Browsers::default()
3419        },
3420      );
3421    }
3422  }
3423
3424  #[test]
3425  pub fn test_padding() {
3426    test(
3427      r#"
3428      .foo {
3429        padding-left: 10px;
3430        padding-right: 10px;
3431        padding-top: 20px;
3432        padding-bottom: 20px;
3433      }
3434    "#,
3435      indoc! {r#"
3436      .foo {
3437        padding: 20px 10px;
3438      }
3439    "#
3440      },
3441    );
3442
3443    test(
3444      r#"
3445      .foo {
3446        padding-block-start: 15px;
3447        padding-block-end: 15px;
3448      }
3449    "#,
3450      indoc! {r#"
3451      .foo {
3452        padding-block: 15px;
3453      }
3454    "#
3455      },
3456    );
3457
3458    test(
3459      r#"
3460      .foo {
3461        padding-left: 10px;
3462        padding-right: 10px;
3463        padding-inline-start: 15px;
3464        padding-inline-end: 15px;
3465        padding-top: 20px;
3466        padding-bottom: 20px;
3467
3468      }
3469    "#,
3470      indoc! {r#"
3471      .foo {
3472        padding-left: 10px;
3473        padding-right: 10px;
3474        padding-inline: 15px;
3475        padding-top: 20px;
3476        padding-bottom: 20px;
3477      }
3478    "#
3479      },
3480    );
3481
3482    prefix_test(
3483      r#"
3484      .foo {
3485        padding-inline-start: 2px;
3486      }
3487    "#,
3488      indoc! {r#"
3489      .foo:not(:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
3490        padding-left: 2px;
3491      }
3492
3493      .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
3494        padding-left: 2px;
3495      }
3496
3497      .foo:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
3498        padding-right: 2px;
3499      }
3500
3501      .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
3502        padding-right: 2px;
3503      }
3504    "#
3505      },
3506      Browsers {
3507        safari: Some(8 << 16),
3508        ..Browsers::default()
3509      },
3510    );
3511
3512    prefix_test(
3513      r#"
3514      .foo {
3515        padding-inline-start: 2px;
3516        padding-inline-end: 4px;
3517      }
3518    "#,
3519      indoc! {r#"
3520      .foo:not(:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
3521        padding-left: 2px;
3522        padding-right: 4px;
3523      }
3524
3525      .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
3526        padding-left: 2px;
3527        padding-right: 4px;
3528      }
3529
3530      .foo:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
3531        padding-left: 4px;
3532        padding-right: 2px;
3533      }
3534
3535      .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
3536        padding-left: 4px;
3537        padding-right: 2px;
3538      }
3539    "#
3540      },
3541      Browsers {
3542        safari: Some(8 << 16),
3543        ..Browsers::default()
3544      },
3545    );
3546
3547    prefix_test(
3548      r#"
3549      .foo {
3550        padding-inline-start: var(--padding);
3551      }
3552    "#,
3553      indoc! {r#"
3554      .foo:not(:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
3555        padding-left: var(--padding);
3556      }
3557
3558      .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
3559        padding-left: var(--padding);
3560      }
3561
3562      .foo:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
3563        padding-right: var(--padding);
3564      }
3565
3566      .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
3567        padding-right: var(--padding);
3568      }
3569    "#
3570      },
3571      Browsers {
3572        safari: Some(8 << 16),
3573        ..Browsers::default()
3574      },
3575    );
3576
3577    prefix_test(
3578      r#"
3579      .foo {
3580        padding-inline: 2px;
3581      }
3582    "#,
3583      indoc! {r#"
3584      .foo {
3585        padding-left: 2px;
3586        padding-right: 2px;
3587      }
3588    "#
3589      },
3590      Browsers {
3591        safari: Some(8 << 16),
3592        ..Browsers::default()
3593      },
3594    );
3595
3596    prefix_test(
3597      r#"
3598      .foo {
3599        padding-block-start: 2px;
3600      }
3601    "#,
3602      indoc! {r#"
3603      .foo {
3604        padding-top: 2px;
3605      }
3606    "#
3607      },
3608      Browsers {
3609        safari: Some(8 << 16),
3610        ..Browsers::default()
3611      },
3612    );
3613
3614    prefix_test(
3615      r#"
3616      .foo {
3617        padding-block-end: 2px;
3618      }
3619    "#,
3620      indoc! {r#"
3621      .foo {
3622        padding-bottom: 2px;
3623      }
3624    "#
3625      },
3626      Browsers {
3627        safari: Some(8 << 16),
3628        ..Browsers::default()
3629      },
3630    );
3631
3632    prefix_test(
3633      r#"
3634      .foo {
3635        padding-top: 1px;
3636        padding-left: 2px;
3637        padding-bottom: 3px;
3638        padding-right: 4px;
3639      }
3640    "#,
3641      indoc! {r#"
3642      .foo {
3643        padding: 1px 4px 3px 2px;
3644      }
3645    "#},
3646      Browsers {
3647        safari: Some(8 << 16),
3648        ..Browsers::default()
3649      },
3650    );
3651
3652    prefix_test(
3653      r#"
3654      .foo {
3655        padding-inline-start: 2px;
3656        padding-inline-end: 2px;
3657      }
3658    "#,
3659      indoc! {r#"
3660      .foo {
3661        padding-inline-start: 2px;
3662        padding-inline-end: 2px;
3663      }
3664    "#
3665      },
3666      Browsers {
3667        safari: Some(13 << 16),
3668        ..Browsers::default()
3669      },
3670    );
3671
3672    prefix_test(
3673      r#"
3674      .foo {
3675        padding-inline-start: 2px;
3676        padding-inline-end: 2px;
3677      }
3678    "#,
3679      indoc! {r#"
3680      .foo {
3681        padding-inline: 2px;
3682      }
3683    "#
3684      },
3685      Browsers {
3686        safari: Some(15 << 16),
3687        ..Browsers::default()
3688      },
3689    );
3690  }
3691
3692  #[test]
3693  fn test_scroll_padding() {
3694    prefix_test(
3695      r#"
3696      .foo {
3697        scroll-padding-inline: 2px;
3698      }
3699    "#,
3700      indoc! {r#"
3701      .foo {
3702        scroll-padding-inline: 2px;
3703      }
3704    "#
3705      },
3706      Browsers {
3707        safari: Some(8 << 16),
3708        ..Browsers::default()
3709      },
3710    );
3711  }
3712
3713  #[test]
3714  fn test_size() {
3715    prefix_test(
3716      r#"
3717      .foo {
3718        block-size: 25px;
3719        inline-size: 25px;
3720        min-block-size: 25px;
3721        min-inline-size: 25px;
3722      }
3723    "#,
3724      indoc! {r#"
3725      .foo {
3726        height: 25px;
3727        min-height: 25px;
3728        width: 25px;
3729        min-width: 25px;
3730      }
3731    "#},
3732      Browsers {
3733        safari: Some(8 << 16),
3734        ..Browsers::default()
3735      },
3736    );
3737
3738    prefix_test(
3739      r#"
3740      .foo {
3741        block-size: 25px;
3742        min-block-size: 25px;
3743        inline-size: 25px;
3744        min-inline-size: 25px;
3745      }
3746    "#,
3747      indoc! {r#"
3748      .foo {
3749        block-size: 25px;
3750        min-block-size: 25px;
3751        inline-size: 25px;
3752        min-inline-size: 25px;
3753      }
3754    "#},
3755      Browsers {
3756        safari: Some(14 << 16),
3757        ..Browsers::default()
3758      },
3759    );
3760
3761    prefix_test(
3762      r#"
3763      .foo {
3764        block-size: var(--size);
3765        min-block-size: var(--size);
3766        inline-size: var(--size);
3767        min-inline-size: var(--size);
3768      }
3769    "#,
3770      indoc! {r#"
3771      .foo {
3772        height: var(--size);
3773        min-height: var(--size);
3774        width: var(--size);
3775        min-width: var(--size);
3776      }
3777    "#},
3778      Browsers {
3779        safari: Some(8 << 16),
3780        ..Browsers::default()
3781      },
3782    );
3783
3784    for (in_prop, out_prop) in [
3785      ("width", "width"),
3786      ("height", "height"),
3787      ("block-size", "height"),
3788      ("inline-size", "width"),
3789      ("min-width", "min-width"),
3790      ("min-height", "min-height"),
3791      ("min-block-size", "min-height"),
3792      ("min-inline-size", "min-width"),
3793      ("max-width", "max-width"),
3794      ("max-height", "max-height"),
3795      ("max-block-size", "max-height"),
3796      ("max-inline-size", "max-width"),
3797    ] {
3798      prefix_test(
3799        &format!(
3800          r#"
3801        .foo {{
3802          {}: stretch;
3803        }}
3804      "#,
3805          in_prop
3806        ),
3807        &format!(
3808          indoc! {r#"
3809        .foo {{
3810          {}: -webkit-fill-available;
3811          {}: -moz-available;
3812          {}: stretch;
3813        }}
3814      "#},
3815          out_prop, out_prop, out_prop
3816        ),
3817        Browsers {
3818          safari: Some(8 << 16),
3819          firefox: Some(4 << 16),
3820          ..Browsers::default()
3821        },
3822      );
3823
3824      prefix_test(
3825        &format!(
3826          r#"
3827        .foo {{
3828          {}: -webkit-fill-available;
3829        }}
3830      "#,
3831          in_prop
3832        ),
3833        &format!(
3834          indoc! {r#"
3835        .foo {{
3836          {}: -webkit-fill-available;
3837        }}
3838      "#},
3839          out_prop
3840        ),
3841        Browsers {
3842          safari: Some(8 << 16),
3843          firefox: Some(4 << 16),
3844          ..Browsers::default()
3845        },
3846      );
3847
3848      prefix_test(
3849        &format!(
3850          r#"
3851        .foo {{
3852          {}: 100vw;
3853          {}: -webkit-fill-available;
3854        }}
3855      "#,
3856          in_prop, in_prop
3857        ),
3858        &format!(
3859          indoc! {r#"
3860        .foo {{
3861          {}: 100vw;
3862          {}: -webkit-fill-available;
3863        }}
3864      "#},
3865          out_prop, out_prop
3866        ),
3867        Browsers {
3868          safari: Some(8 << 16),
3869          firefox: Some(4 << 16),
3870          ..Browsers::default()
3871        },
3872      );
3873
3874      prefix_test(
3875        &format!(
3876          r#"
3877        .foo {{
3878          {}: fit-content;
3879        }}
3880      "#,
3881          in_prop
3882        ),
3883        &format!(
3884          indoc! {r#"
3885        .foo {{
3886          {}: -webkit-fit-content;
3887          {}: -moz-fit-content;
3888          {}: fit-content;
3889        }}
3890      "#},
3891          out_prop, out_prop, out_prop
3892        ),
3893        Browsers {
3894          safari: Some(8 << 16),
3895          firefox: Some(4 << 16),
3896          ..Browsers::default()
3897        },
3898      );
3899
3900      prefix_test(
3901        &format!(
3902          r#"
3903        .foo {{
3904          {}: fit-content(50%);
3905        }}
3906      "#,
3907          in_prop
3908        ),
3909        &format!(
3910          indoc! {r#"
3911        .foo {{
3912          {}: fit-content(50%);
3913        }}
3914      "#},
3915          out_prop
3916        ),
3917        Browsers {
3918          safari: Some(8 << 16),
3919          firefox: Some(4 << 16),
3920          ..Browsers::default()
3921        },
3922      );
3923
3924      prefix_test(
3925        &format!(
3926          r#"
3927        .foo {{
3928          {}: min-content;
3929        }}
3930      "#,
3931          in_prop
3932        ),
3933        &format!(
3934          indoc! {r#"
3935        .foo {{
3936          {}: -webkit-min-content;
3937          {}: -moz-min-content;
3938          {}: min-content;
3939        }}
3940      "#},
3941          out_prop, out_prop, out_prop
3942        ),
3943        Browsers {
3944          safari: Some(8 << 16),
3945          firefox: Some(4 << 16),
3946          ..Browsers::default()
3947        },
3948      );
3949
3950      prefix_test(
3951        &format!(
3952          r#"
3953        .foo {{
3954          {}: max-content;
3955        }}
3956      "#,
3957          in_prop
3958        ),
3959        &format!(
3960          indoc! {r#"
3961        .foo {{
3962          {}: -webkit-max-content;
3963          {}: -moz-max-content;
3964          {}: max-content;
3965        }}
3966      "#},
3967          out_prop, out_prop, out_prop
3968        ),
3969        Browsers {
3970          safari: Some(8 << 16),
3971          firefox: Some(4 << 16),
3972          ..Browsers::default()
3973        },
3974      );
3975
3976      prefix_test(
3977        &format!(
3978          r#"
3979        .foo {{
3980          {}: 100%;
3981          {}: max-content;
3982        }}
3983      "#,
3984          in_prop, in_prop
3985        ),
3986        &format!(
3987          indoc! {r#"
3988        .foo {{
3989          {}: 100%;
3990          {}: max-content;
3991        }}
3992      "#},
3993          out_prop, out_prop
3994        ),
3995        Browsers {
3996          safari: Some(8 << 16),
3997          firefox: Some(4 << 16),
3998          ..Browsers::default()
3999        },
4000      );
4001
4002      prefix_test(
4003        &format!(
4004          r#"
4005        .foo {{
4006          {}: var(--fallback);
4007          {}: max-content;
4008        }}
4009      "#,
4010          in_prop, in_prop
4011        ),
4012        &format!(
4013          indoc! {r#"
4014        .foo {{
4015          {}: var(--fallback);
4016          {}: max-content;
4017        }}
4018      "#},
4019          out_prop, out_prop
4020        ),
4021        Browsers {
4022          safari: Some(8 << 16),
4023          firefox: Some(4 << 16),
4024          ..Browsers::default()
4025        },
4026      );
4027    }
4028
4029    minify_test(".foo { aspect-ratio: auto }", ".foo{aspect-ratio:auto}");
4030    minify_test(".foo { aspect-ratio: 2 / 3 }", ".foo{aspect-ratio:2/3}");
4031    minify_test(".foo { aspect-ratio: auto 2 / 3 }", ".foo{aspect-ratio:auto 2/3}");
4032    minify_test(".foo { aspect-ratio: 2 / 3 auto }", ".foo{aspect-ratio:auto 2/3}");
4033
4034    minify_test(
4035      ".foo { width: 200px; width: var(--foo); }",
4036      ".foo{width:200px;width:var(--foo)}",
4037    );
4038    minify_test(
4039      ".foo { width: var(--foo); width: 200px; }",
4040      ".foo{width:var(--foo);width:200px}",
4041    );
4042  }
4043
4044  #[test]
4045  pub fn test_background() {
4046    test(
4047      r#"
4048      .foo {
4049        background: url(img.png);
4050        background-position-x: 20px;
4051        background-position-y: 10px;
4052        background-size: 50px 100px;
4053        background-repeat: repeat no-repeat;
4054      }
4055    "#,
4056      indoc! {r#"
4057      .foo {
4058        background: url("img.png") 20px 10px / 50px 100px repeat-x;
4059      }
4060    "#
4061      },
4062    );
4063
4064    test(
4065      r#"
4066      .foo {
4067        background-color: red;
4068        background-position: 0% 0%;
4069        background-size: auto;
4070        background-repeat: repeat;
4071        background-clip: border-box;
4072        background-origin: padding-box;
4073        background-attachment: scroll;
4074        background-image: none
4075      }
4076    "#,
4077      indoc! {r#"
4078      .foo {
4079        background: red;
4080      }
4081    "#
4082      },
4083    );
4084
4085    test(
4086      r#"
4087      .foo {
4088        background-color: gray;
4089        background-position: 40% 50%;
4090        background-size: 10em auto;
4091        background-repeat: round;
4092        background-clip: border-box;
4093        background-origin: border-box;
4094        background-attachment: fixed;
4095        background-image: url('chess.png');
4096      }
4097    "#,
4098      indoc! {r#"
4099      .foo {
4100        background: gray url("chess.png") 40% / 10em round fixed border-box;
4101      }
4102    "#
4103      },
4104    );
4105
4106    test(
4107      r#"
4108      .foo {
4109        background: url(img.png), url(test.jpg) gray;
4110        background-position-x: right 20px, 10px;
4111        background-position-y: top 20px, 15px;
4112        background-size: 50px 50px, auto;
4113        background-repeat: repeat no-repeat, no-repeat;
4114      }
4115    "#,
4116      indoc! {r#"
4117      .foo {
4118        background: url("img.png") right 20px top 20px / 50px 50px repeat-x, gray url("test.jpg") 10px 15px no-repeat;
4119      }
4120    "#
4121      },
4122    );
4123
4124    minify_test(
4125      r#"
4126      .foo {
4127        background-position: center center;
4128      }
4129    "#,
4130      indoc! {".foo{background-position:50%}"
4131      },
4132    );
4133
4134    test(
4135      r#"
4136      .foo {
4137        background: url(img.png) gray;
4138        background-clip: content-box;
4139        -webkit-background-clip: text;
4140      }
4141    "#,
4142      indoc! {r#"
4143      .foo {
4144        background: gray url("img.png") padding-box content-box;
4145        -webkit-background-clip: text;
4146      }
4147    "#
4148      },
4149    );
4150
4151    test(
4152      r#"
4153      .foo {
4154        background: url(img.png) gray;
4155        -webkit-background-clip: text;
4156        background-clip: content-box;
4157      }
4158    "#,
4159      indoc! {r#"
4160      .foo {
4161        background: gray url("img.png");
4162        -webkit-background-clip: text;
4163        background-clip: content-box;
4164      }
4165    "#
4166      },
4167    );
4168
4169    test(
4170      r#"
4171      .foo {
4172        background: url(img.png) gray;
4173        background-position: var(--pos);
4174      }
4175    "#,
4176      indoc! {r#"
4177      .foo {
4178        background: gray url("img.png");
4179        background-position: var(--pos);
4180      }
4181    "#
4182      },
4183    );
4184
4185    minify_test(
4186      ".foo { background-position: bottom left }",
4187      ".foo{background-position:0 100%}",
4188    );
4189    minify_test(
4190      ".foo { background-position: left 10px center }",
4191      ".foo{background-position:10px 50%}",
4192    );
4193    minify_test(
4194      ".foo { background-position: right 10px center }",
4195      ".foo{background-position:right 10px center}",
4196    );
4197    minify_test(
4198      ".foo { background-position: right 10px top 20px }",
4199      ".foo{background-position:right 10px top 20px}",
4200    );
4201    minify_test(
4202      ".foo { background-position: left 10px top 20px }",
4203      ".foo{background-position:10px 20px}",
4204    );
4205    minify_test(
4206      ".foo { background-position: left 10px bottom 20px }",
4207      ".foo{background-position:left 10px bottom 20px}",
4208    );
4209    minify_test(
4210      ".foo { background-position: left 10px top }",
4211      ".foo{background-position:10px 0}",
4212    );
4213    minify_test(
4214      ".foo { background-position: bottom right }",
4215      ".foo{background-position:100% 100%}",
4216    );
4217
4218    minify_test(
4219      ".foo { background: url('img-sprite.png') no-repeat bottom right }",
4220      ".foo{background:url(img-sprite.png) 100% 100% no-repeat}",
4221    );
4222    minify_test(".foo { background: transparent }", ".foo{background:0 0}");
4223
4224    minify_test(".foo { background: url(\"data:image/svg+xml,%3Csvg width='168' height='24' xmlns='http://www.w3.org/2000/svg'%3E%3C/svg%3E\") }", ".foo{background:url(\"data:image/svg+xml,%3Csvg width='168' height='24' xmlns='http://www.w3.org/2000/svg'%3E%3C/svg%3E\")}");
4225
4226    test(
4227      r#"
4228      .foo {
4229        background: url(img.png);
4230        background-clip: text;
4231      }
4232    "#,
4233      indoc! {r#"
4234      .foo {
4235        background: url("img.png") text;
4236      }
4237    "#
4238      },
4239    );
4240
4241    prefix_test(
4242      r#"
4243      .foo {
4244        background: url(img.png);
4245        background-clip: text;
4246      }
4247    "#,
4248      indoc! {r#"
4249      .foo {
4250        background: url("img.png");
4251        -webkit-background-clip: text;
4252        background-clip: text;
4253      }
4254    "#
4255      },
4256      Browsers {
4257        safari: Some(8 << 16),
4258        ..Browsers::default()
4259      },
4260    );
4261
4262    prefix_test(
4263      r#"
4264      .foo {
4265        background: url(img.png);
4266        background-clip: text;
4267      }
4268    "#,
4269      indoc! {r#"
4270      .foo {
4271        background: url("img.png") text;
4272      }
4273    "#
4274      },
4275      Browsers {
4276        safari: Some(14 << 16),
4277        ..Browsers::default()
4278      },
4279    );
4280
4281    prefix_test(
4282      r#"
4283      .foo {
4284        background: url(img.png) text;
4285      }
4286    "#,
4287      indoc! {r#"
4288      .foo {
4289        background: url("img.png");
4290        -webkit-background-clip: text;
4291        background-clip: text;
4292      }
4293    "#
4294      },
4295      Browsers {
4296        chrome: Some(45 << 16),
4297        ..Browsers::default()
4298      },
4299    );
4300
4301    prefix_test(
4302      r#"
4303      .foo {
4304        background: url(img.png);
4305        -webkit-background-clip: text;
4306      }
4307    "#,
4308      indoc! {r#"
4309      .foo {
4310        background: url("img.png");
4311        -webkit-background-clip: text;
4312      }
4313    "#
4314      },
4315      Browsers {
4316        chrome: Some(45 << 16),
4317        ..Browsers::default()
4318      },
4319    );
4320
4321    prefix_test(
4322      r#"
4323      .foo {
4324        background: url(img.png);
4325        background-clip: text;
4326      }
4327    "#,
4328      indoc! {r#"
4329      .foo {
4330        background: url("img.png");
4331        -webkit-background-clip: text;
4332        background-clip: text;
4333      }
4334    "#
4335      },
4336      Browsers {
4337        safari: Some(14 << 16),
4338        chrome: Some(95 << 16),
4339        ..Browsers::default()
4340      },
4341    );
4342
4343    prefix_test(
4344      r#"
4345      .foo {
4346        background-image: url(img.png);
4347        background-clip: text;
4348      }
4349    "#,
4350      indoc! {r#"
4351      .foo {
4352        background-image: url("img.png");
4353        -webkit-background-clip: text;
4354        background-clip: text;
4355      }
4356    "#
4357      },
4358      Browsers {
4359        safari: Some(8 << 16),
4360        ..Browsers::default()
4361      },
4362    );
4363
4364    prefix_test(
4365      r#"
4366      .foo {
4367        -webkit-background-clip: text;
4368        background-clip: text;
4369      }
4370    "#,
4371      indoc! {r#"
4372      .foo {
4373        -webkit-background-clip: text;
4374        background-clip: text;
4375      }
4376    "#
4377      },
4378      Browsers {
4379        chrome: Some(45 << 16),
4380        ..Browsers::default()
4381      },
4382    );
4383
4384    prefix_test(
4385      r#"
4386      .foo {
4387        background-image: url(img.png);
4388        background-clip: text;
4389      }
4390    "#,
4391      indoc! {r#"
4392      .foo {
4393        background-image: url("img.png");
4394        background-clip: text;
4395      }
4396    "#
4397      },
4398      Browsers {
4399        safari: Some(14 << 16),
4400        ..Browsers::default()
4401      },
4402    );
4403
4404    minify_test(".foo { background: none center }", ".foo{background:50%}");
4405    minify_test(".foo { background: none }", ".foo{background:0 0}");
4406
4407    prefix_test(
4408      r#"
4409      .foo {
4410        background: lab(51.5117% 43.3777 -29.0443);
4411      }
4412    "#,
4413      indoc! {r#"
4414      .foo {
4415        background: #af5cae;
4416        background: lab(51.5117% 43.3777 -29.0443);
4417      }
4418    "#
4419      },
4420      Browsers {
4421        chrome: Some(95 << 16),
4422        safari: Some(15 << 16),
4423        ..Browsers::default()
4424      },
4425    );
4426
4427    prefix_test(
4428      r#"
4429      .foo {
4430        background: lab(51.5117% 43.3777 -29.0443) url(foo.png);
4431      }
4432    "#,
4433      indoc! {r#"
4434      .foo {
4435        background: #af5cae url("foo.png");
4436        background: lab(51.5117% 43.3777 -29.0443) url("foo.png");
4437      }
4438    "#
4439      },
4440      Browsers {
4441        chrome: Some(95 << 16),
4442        safari: Some(15 << 16),
4443        ..Browsers::default()
4444      },
4445    );
4446
4447    prefix_test(
4448      r#"
4449      .foo {
4450        background: lab(51.5117% 43.3777 -29.0443) linear-gradient(lab(52.2319% 40.1449 59.9171), lab(47.7776% -34.2947 -7.65904));
4451      }
4452    "#,
4453      indoc! {r#"
4454      .foo {
4455        background: #af5cae linear-gradient(#c65d07, #00807c);
4456        background: lab(51.5117% 43.3777 -29.0443) linear-gradient(lab(52.2319% 40.1449 59.9171), lab(47.7776% -34.2947 -7.65904));
4457      }
4458    "#
4459      },
4460      Browsers {
4461        chrome: Some(95 << 16),
4462        safari: Some(15 << 16),
4463        ..Browsers::default()
4464      },
4465    );
4466
4467    test(
4468      ".foo { background: calc(var(--v) / 0.3)",
4469      indoc! {r#"
4470      .foo {
4471        background: calc(var(--v) / .3);
4472      }
4473    "#},
4474    );
4475
4476    prefix_test(
4477      r#"
4478      .foo {
4479        background-color: #4263eb;
4480        background-color: color(display-p3 0 .5 1);
4481      }
4482    "#,
4483      indoc! {r#"
4484      .foo {
4485        background-color: #4263eb;
4486        background-color: color(display-p3 0 .5 1);
4487      }
4488    "#
4489      },
4490      Browsers {
4491        chrome: Some(99 << 16),
4492        ..Browsers::default()
4493      },
4494    );
4495    prefix_test(
4496      r#"
4497      .foo {
4498        background-color: #4263eb;
4499        background-color: color(display-p3 0 .5 1);
4500      }
4501    "#,
4502      indoc! {r#"
4503      .foo {
4504        background-color: color(display-p3 0 .5 1);
4505      }
4506    "#
4507      },
4508      Browsers {
4509        safari: Some(16 << 16),
4510        ..Browsers::default()
4511      },
4512    );
4513    prefix_test(
4514      r#"
4515      .foo {
4516        background-image: linear-gradient(red, green);
4517        background-image: linear-gradient(lch(50% 132 50), lch(50% 130 150));
4518      }
4519    "#,
4520      indoc! {r#"
4521      .foo {
4522        background-image: linear-gradient(red, green);
4523        background-image: linear-gradient(lch(50% 132 50), lch(50% 130 150));
4524      }
4525    "#
4526      },
4527      Browsers {
4528        chrome: Some(99 << 16),
4529        ..Browsers::default()
4530      },
4531    );
4532    prefix_test(
4533      r#"
4534      .foo {
4535        background-image: linear-gradient(red, green);
4536        background-image: linear-gradient(lch(50% 132 50), lch(50% 130 150));
4537      }
4538    "#,
4539      indoc! {r#"
4540      .foo {
4541        background-image: linear-gradient(lch(50% 132 50), lch(50% 130 150));
4542      }
4543    "#
4544      },
4545      Browsers {
4546        safari: Some(16 << 16),
4547        ..Browsers::default()
4548      },
4549    );
4550    prefix_test(
4551      r#"
4552      .foo {
4553        background: #4263eb;
4554        background: color(display-p3 0 .5 1);
4555      }
4556    "#,
4557      indoc! {r#"
4558      .foo {
4559        background: #4263eb;
4560        background: color(display-p3 0 .5 1);
4561      }
4562    "#
4563      },
4564      Browsers {
4565        chrome: Some(99 << 16),
4566        ..Browsers::default()
4567      },
4568    );
4569    prefix_test(
4570      r#"
4571      .foo {
4572        background: #4263eb;
4573        background: color(display-p3 0 .5 1);
4574      }
4575    "#,
4576      indoc! {r#"
4577      .foo {
4578        background: color(display-p3 0 .5 1);
4579      }
4580    "#
4581      },
4582      Browsers {
4583        safari: Some(16 << 16),
4584        ..Browsers::default()
4585      },
4586    );
4587    prefix_test(
4588      r#"
4589      .foo {
4590        background: linear-gradient(red, green);
4591        background: linear-gradient(lch(50% 132 50), lch(50% 130 150));
4592      }
4593    "#,
4594      indoc! {r#"
4595      .foo {
4596        background: linear-gradient(red, green);
4597        background: linear-gradient(lch(50% 132 50), lch(50% 130 150));
4598      }
4599    "#
4600      },
4601      Browsers {
4602        chrome: Some(99 << 16),
4603        ..Browsers::default()
4604      },
4605    );
4606    prefix_test(
4607      r#"
4608      .foo {
4609        background: red;
4610        background: linear-gradient(lch(50% 132 50), lch(50% 130 150));
4611      }
4612    "#,
4613      indoc! {r#"
4614      .foo {
4615        background: red;
4616        background: linear-gradient(lch(50% 132 50), lch(50% 130 150));
4617      }
4618    "#
4619      },
4620      Browsers {
4621        chrome: Some(99 << 16),
4622        ..Browsers::default()
4623      },
4624    );
4625    prefix_test(
4626      r#"
4627      .foo {
4628        background: linear-gradient(red, green);
4629        background: linear-gradient(lch(50% 132 50), lch(50% 130 150));
4630      }
4631    "#,
4632      indoc! {r#"
4633      .foo {
4634        background: linear-gradient(lch(50% 132 50), lch(50% 130 150));
4635      }
4636    "#
4637      },
4638      Browsers {
4639        safari: Some(16 << 16),
4640        ..Browsers::default()
4641      },
4642    );
4643    prefix_test(
4644      r#"
4645      .foo {
4646        background: var(--fallback);
4647        background: linear-gradient(lch(50% 132 50), lch(50% 130 150));
4648      }
4649    "#,
4650      indoc! {r#"
4651      .foo {
4652        background: var(--fallback);
4653        background: linear-gradient(lch(50% 132 50), lch(50% 130 150));
4654      }
4655    "#
4656      },
4657      Browsers {
4658        chrome: Some(99 << 16),
4659        ..Browsers::default()
4660      },
4661    );
4662    prefix_test(
4663      r#"
4664      .foo {
4665        background: red url(foo.png);
4666        background: lch(50% 132 50) url(foo.png);
4667      }
4668    "#,
4669      indoc! {r#"
4670      .foo {
4671        background: red url("foo.png");
4672        background: lch(50% 132 50) url("foo.png");
4673      }
4674    "#
4675      },
4676      Browsers {
4677        chrome: Some(99 << 16),
4678        ..Browsers::default()
4679      },
4680    );
4681  }
4682
4683  #[test]
4684  pub fn test_flex() {
4685    test(
4686      r#"
4687      .foo {
4688        flex-direction: column;
4689        flex-wrap: wrap;
4690      }
4691    "#,
4692      indoc! {r#"
4693      .foo {
4694        flex-flow: column wrap;
4695      }
4696    "#
4697      },
4698    );
4699
4700    test(
4701      r#"
4702      .foo {
4703        flex-direction: row;
4704        flex-wrap: wrap;
4705      }
4706    "#,
4707      indoc! {r#"
4708      .foo {
4709        flex-flow: wrap;
4710      }
4711    "#
4712      },
4713    );
4714
4715    test(
4716      r#"
4717      .foo {
4718        flex-direction: row;
4719        flex-wrap: nowrap;
4720      }
4721    "#,
4722      indoc! {r#"
4723      .foo {
4724        flex-flow: row;
4725      }
4726    "#
4727      },
4728    );
4729
4730    test(
4731      r#"
4732      .foo {
4733        flex-direction: column;
4734        flex-wrap: nowrap;
4735      }
4736    "#,
4737      indoc! {r#"
4738      .foo {
4739        flex-flow: column;
4740      }
4741    "#
4742      },
4743    );
4744
4745    test(
4746      r#"
4747      .foo {
4748        flex-grow: 1;
4749        flex-shrink: 1;
4750        flex-basis: 0%;
4751      }
4752    "#,
4753      indoc! {r#"
4754      .foo {
4755        flex: 1;
4756      }
4757    "#
4758      },
4759    );
4760
4761    test(
4762      r#"
4763      .foo {
4764        flex-grow: 1;
4765        flex-shrink: 1;
4766        flex-basis: 0;
4767      }
4768    "#,
4769      indoc! {r#"
4770      .foo {
4771        flex: 1 1 0;
4772      }
4773    "#
4774      },
4775    );
4776
4777    test(
4778      r#"
4779      .foo {
4780        flex-grow: 1;
4781        flex-shrink: 1;
4782        flex-basis: 0px;
4783      }
4784    "#,
4785      indoc! {r#"
4786      .foo {
4787        flex: 1 1 0;
4788      }
4789    "#
4790      },
4791    );
4792
4793    test(
4794      r#"
4795      .foo {
4796        flex-grow: 1;
4797        flex-shrink: 2;
4798        flex-basis: 0%;
4799      }
4800    "#,
4801      indoc! {r#"
4802      .foo {
4803        flex: 1 2;
4804      }
4805    "#
4806      },
4807    );
4808
4809    test(
4810      r#"
4811      .foo {
4812        flex-grow: 2;
4813        flex-shrink: 1;
4814        flex-basis: 0%;
4815      }
4816    "#,
4817      indoc! {r#"
4818      .foo {
4819        flex: 2;
4820      }
4821    "#
4822      },
4823    );
4824
4825    test(
4826      r#"
4827      .foo {
4828        flex-grow: 2;
4829        flex-shrink: 2;
4830        flex-basis: 0%;
4831      }
4832    "#,
4833      indoc! {r#"
4834      .foo {
4835        flex: 2 2;
4836      }
4837    "#
4838      },
4839    );
4840
4841    test(
4842      r#"
4843      .foo {
4844        flex-grow: 1;
4845        flex-shrink: 1;
4846        flex-basis: 10px;
4847      }
4848    "#,
4849      indoc! {r#"
4850      .foo {
4851        flex: 10px;
4852      }
4853    "#
4854      },
4855    );
4856
4857    test(
4858      r#"
4859      .foo {
4860        flex-grow: 2;
4861        flex-shrink: 1;
4862        flex-basis: 10px;
4863      }
4864    "#,
4865      indoc! {r#"
4866      .foo {
4867        flex: 2 10px;
4868      }
4869    "#
4870      },
4871    );
4872
4873    test(
4874      r#"
4875      .foo {
4876        flex-grow: 1;
4877        flex-shrink: 0;
4878        flex-basis: 0%;
4879      }
4880    "#,
4881      indoc! {r#"
4882      .foo {
4883        flex: 1 0;
4884      }
4885    "#
4886      },
4887    );
4888
4889    test(
4890      r#"
4891      .foo {
4892        flex-grow: 1;
4893        flex-shrink: 0;
4894        flex-basis: auto;
4895      }
4896    "#,
4897      indoc! {r#"
4898      .foo {
4899        flex: 1 0 auto;
4900      }
4901    "#
4902      },
4903    );
4904
4905    test(
4906      r#"
4907      .foo {
4908        flex-grow: 1;
4909        flex-shrink: 1;
4910        flex-basis: auto;
4911      }
4912    "#,
4913      indoc! {r#"
4914      .foo {
4915        flex: auto;
4916      }
4917    "#
4918      },
4919    );
4920
4921    test(
4922      r#"
4923      .foo {
4924        flex: 0 0;
4925        flex-grow: 1;
4926      }
4927    "#,
4928      indoc! {r#"
4929      .foo {
4930        flex: 1 0;
4931      }
4932    "#
4933      },
4934    );
4935
4936    test(
4937      r#"
4938      .foo {
4939        flex: 0 0;
4940        flex-grow: var(--grow);
4941      }
4942    "#,
4943      indoc! {r#"
4944      .foo {
4945        flex: 0 0;
4946        flex-grow: var(--grow);
4947      }
4948    "#
4949      },
4950    );
4951
4952    test(
4953      r#"
4954      .foo {
4955        align-content: center;
4956        justify-content: center;
4957      }
4958    "#,
4959      indoc! {r#"
4960      .foo {
4961        place-content: center;
4962      }
4963    "#
4964      },
4965    );
4966
4967    test(
4968      r#"
4969      .foo {
4970        align-content: first baseline;
4971        justify-content: safe right;
4972      }
4973    "#,
4974      indoc! {r#"
4975      .foo {
4976        place-content: baseline safe right;
4977      }
4978    "#
4979      },
4980    );
4981
4982    test(
4983      r#"
4984      .foo {
4985        place-content: first baseline unsafe left;
4986      }
4987    "#,
4988      indoc! {r#"
4989      .foo {
4990        place-content: baseline unsafe left;
4991      }
4992    "#
4993      },
4994    );
4995
4996    test(
4997      r#"
4998      .foo {
4999        place-content: center center;
5000      }
5001    "#,
5002      indoc! {r#"
5003      .foo {
5004        place-content: center;
5005      }
5006    "#
5007      },
5008    );
5009
5010    test(
5011      r#"
5012      .foo {
5013        align-self: center;
5014        justify-self: center;
5015      }
5016    "#,
5017      indoc! {r#"
5018      .foo {
5019        place-self: center;
5020      }
5021    "#
5022      },
5023    );
5024
5025    test(
5026      r#"
5027      .foo {
5028        align-self: center;
5029        justify-self: unsafe left;
5030      }
5031    "#,
5032      indoc! {r#"
5033      .foo {
5034        place-self: center unsafe left;
5035      }
5036    "#
5037      },
5038    );
5039
5040    test(
5041      r#"
5042      .foo {
5043        align-items: center;
5044        justify-items: center;
5045      }
5046    "#,
5047      indoc! {r#"
5048      .foo {
5049        place-items: center;
5050      }
5051    "#
5052      },
5053    );
5054
5055    test(
5056      r#"
5057      .foo {
5058        align-items: center;
5059        justify-items: legacy left;
5060      }
5061    "#,
5062      indoc! {r#"
5063      .foo {
5064        place-items: center legacy left;
5065      }
5066    "#
5067      },
5068    );
5069
5070    test(
5071      r#"
5072      .foo {
5073        place-items: center;
5074        justify-items: var(--justify);
5075      }
5076    "#,
5077      indoc! {r#"
5078      .foo {
5079        place-items: center;
5080        justify-items: var(--justify);
5081      }
5082    "#
5083      },
5084    );
5085
5086    test(
5087      r#"
5088      .foo {
5089        row-gap: 10px;
5090        column-gap: 20px;
5091      }
5092    "#,
5093      indoc! {r#"
5094      .foo {
5095        gap: 10px 20px;
5096      }
5097    "#
5098      },
5099    );
5100
5101    test(
5102      r#"
5103      .foo {
5104        row-gap: 10px;
5105        column-gap: 10px;
5106      }
5107    "#,
5108      indoc! {r#"
5109      .foo {
5110        gap: 10px;
5111      }
5112    "#
5113      },
5114    );
5115
5116    test(
5117      r#"
5118      .foo {
5119        gap: 10px;
5120        column-gap: 20px;
5121      }
5122    "#,
5123      indoc! {r#"
5124      .foo {
5125        gap: 10px 20px;
5126      }
5127    "#
5128      },
5129    );
5130
5131    test(
5132      r#"
5133      .foo {
5134        column-gap: 20px;
5135        gap: 10px;
5136      }
5137    "#,
5138      indoc! {r#"
5139      .foo {
5140        gap: 10px;
5141      }
5142    "#
5143      },
5144    );
5145
5146    test(
5147      r#"
5148      .foo {
5149        row-gap: normal;
5150        column-gap: 20px;
5151      }
5152    "#,
5153      indoc! {r#"
5154      .foo {
5155        gap: normal 20px;
5156      }
5157    "#
5158      },
5159    );
5160
5161    test(
5162      r#"
5163      .foo {
5164        -webkit-flex-grow: 1;
5165        -webkit-flex-shrink: 1;
5166        -webkit-flex-basis: auto;
5167      }
5168    "#,
5169      indoc! {r#"
5170      .foo {
5171        -webkit-flex: auto;
5172      }
5173    "#
5174      },
5175    );
5176    test(
5177      r#"
5178      .foo {
5179        -webkit-flex-grow: 1;
5180        -webkit-flex-shrink: 1;
5181        -webkit-flex-basis: auto;
5182        flex-grow: 1;
5183        flex-shrink: 1;
5184        flex-basis: auto;
5185      }
5186    "#,
5187      indoc! {r#"
5188      .foo {
5189        -webkit-flex: auto;
5190        flex: auto;
5191      }
5192    "#
5193      },
5194    );
5195    prefix_test(
5196      r#"
5197      .foo {
5198        -webkit-box-orient: horizontal;
5199        -webkit-box-direction: normal;
5200        flex-direction: row;
5201      }
5202    "#,
5203      indoc! {r#"
5204      .foo {
5205        -webkit-box-orient: horizontal;
5206        -webkit-box-direction: normal;
5207        -webkit-flex-direction: row;
5208        flex-direction: row;
5209      }
5210    "#},
5211      Browsers {
5212        safari: Some(4 << 16),
5213        ..Browsers::default()
5214      },
5215    );
5216    prefix_test(
5217      r#"
5218      .foo {
5219        flex-direction: row;
5220      }
5221    "#,
5222      indoc! {r#"
5223      .foo {
5224        -webkit-box-orient: horizontal;
5225        -moz-box-orient: horizontal;
5226        -webkit-box-direction: normal;
5227        -moz-box-direction: normal;
5228        -webkit-flex-direction: row;
5229        -ms-flex-direction: row;
5230        flex-direction: row;
5231      }
5232    "#},
5233      Browsers {
5234        safari: Some(4 << 16),
5235        firefox: Some(4 << 16),
5236        ie: Some(10 << 16),
5237        ..Browsers::default()
5238      },
5239    );
5240    prefix_test(
5241      r#"
5242      .foo {
5243        -webkit-box-orient: horizontal;
5244        -webkit-box-direction: normal;
5245        -moz-box-orient: horizontal;
5246        -moz-box-direction: normal;
5247        -webkit-flex-direction: row;
5248        -ms-flex-direction: row;
5249        flex-direction: row;
5250      }
5251    "#,
5252      indoc! {r#"
5253      .foo {
5254        flex-direction: row;
5255      }
5256    "#},
5257      Browsers {
5258        safari: Some(14 << 16),
5259        ..Browsers::default()
5260      },
5261    );
5262    prefix_test(
5263      r#"
5264      .foo {
5265        flex-wrap: wrap;
5266      }
5267    "#,
5268      indoc! {r#"
5269      .foo {
5270        -webkit-box-lines: multiple;
5271        -moz-box-lines: multiple;
5272        -webkit-flex-wrap: wrap;
5273        -ms-flex-wrap: wrap;
5274        flex-wrap: wrap;
5275      }
5276    "#},
5277      Browsers {
5278        safari: Some(4 << 16),
5279        firefox: Some(4 << 16),
5280        ie: Some(10 << 16),
5281        ..Browsers::default()
5282      },
5283    );
5284    prefix_test(
5285      r#"
5286      .foo {
5287        -webkit-box-lines: multiple;
5288        -moz-box-lines: multiple;
5289        -webkit-flex-wrap: wrap;
5290        -ms-flex-wrap: wrap;
5291        flex-wrap: wrap;
5292      }
5293    "#,
5294      indoc! {r#"
5295      .foo {
5296        flex-wrap: wrap;
5297      }
5298    "#},
5299      Browsers {
5300        safari: Some(11 << 16),
5301        ..Browsers::default()
5302      },
5303    );
5304    prefix_test(
5305      r#"
5306      .foo {
5307        flex-flow: row wrap;
5308      }
5309    "#,
5310      indoc! {r#"
5311      .foo {
5312        -webkit-box-orient: horizontal;
5313        -moz-box-orient: horizontal;
5314        -webkit-box-direction: normal;
5315        -moz-box-direction: normal;
5316        -webkit-flex-flow: wrap;
5317        -ms-flex-flow: wrap;
5318        flex-flow: wrap;
5319      }
5320    "#},
5321      Browsers {
5322        safari: Some(4 << 16),
5323        firefox: Some(4 << 16),
5324        ie: Some(10 << 16),
5325        ..Browsers::default()
5326      },
5327    );
5328    prefix_test(
5329      r#"
5330      .foo {
5331        -webkit-box-orient: horizontal;
5332        -moz-box-orient: horizontal;
5333        -webkit-box-direction: normal;
5334        -moz-box-direction: normal;
5335        -webkit-flex-flow: wrap;
5336        -ms-flex-flow: wrap;
5337        flex-flow: wrap;
5338      }
5339    "#,
5340      indoc! {r#"
5341      .foo {
5342        flex-flow: wrap;
5343      }
5344    "#},
5345      Browsers {
5346        safari: Some(11 << 16),
5347        ..Browsers::default()
5348      },
5349    );
5350    prefix_test(
5351      r#"
5352      .foo {
5353        flex-grow: 1;
5354      }
5355    "#,
5356      indoc! {r#"
5357      .foo {
5358        -webkit-box-flex: 1;
5359        -moz-box-flex: 1;
5360        -ms-flex-positive: 1;
5361        -webkit-flex-grow: 1;
5362        flex-grow: 1;
5363      }
5364    "#},
5365      Browsers {
5366        safari: Some(4 << 16),
5367        firefox: Some(4 << 16),
5368        ie: Some(10 << 16),
5369        ..Browsers::default()
5370      },
5371    );
5372    prefix_test(
5373      r#"
5374      .foo {
5375        -webkit-box-flex: 1;
5376        -moz-box-flex: 1;
5377        -ms-flex-positive: 1;
5378        -webkit-flex-grow: 1;
5379        flex-grow: 1;
5380      }
5381    "#,
5382      indoc! {r#"
5383      .foo {
5384        flex-grow: 1;
5385      }
5386    "#},
5387      Browsers {
5388        safari: Some(11 << 16),
5389        ..Browsers::default()
5390      },
5391    );
5392    prefix_test(
5393      r#"
5394      .foo {
5395        flex-shrink: 1;
5396      }
5397    "#,
5398      indoc! {r#"
5399      .foo {
5400        -ms-flex-negative: 1;
5401        -webkit-flex-shrink: 1;
5402        flex-shrink: 1;
5403      }
5404    "#},
5405      Browsers {
5406        safari: Some(4 << 16),
5407        firefox: Some(4 << 16),
5408        ie: Some(10 << 16),
5409        ..Browsers::default()
5410      },
5411    );
5412    prefix_test(
5413      r#"
5414      .foo {
5415        -ms-flex-negative: 1;
5416        -webkit-flex-shrink: 1;
5417        flex-shrink: 1;
5418      }
5419    "#,
5420      indoc! {r#"
5421      .foo {
5422        flex-shrink: 1;
5423      }
5424    "#},
5425      Browsers {
5426        safari: Some(11 << 16),
5427        ..Browsers::default()
5428      },
5429    );
5430    prefix_test(
5431      r#"
5432      .foo {
5433        flex-basis: 1px;
5434      }
5435    "#,
5436      indoc! {r#"
5437      .foo {
5438        -ms-flex-preferred-size: 1px;
5439        -webkit-flex-basis: 1px;
5440        flex-basis: 1px;
5441      }
5442    "#},
5443      Browsers {
5444        safari: Some(4 << 16),
5445        firefox: Some(4 << 16),
5446        ie: Some(10 << 16),
5447        ..Browsers::default()
5448      },
5449    );
5450    prefix_test(
5451      r#"
5452      .foo {
5453        -ms-flex-preferred-size: 1px;
5454        -webkit-flex-basis: 1px;
5455        flex-basis: 1px;
5456      }
5457    "#,
5458      indoc! {r#"
5459      .foo {
5460        flex-basis: 1px;
5461      }
5462    "#},
5463      Browsers {
5464        safari: Some(11 << 16),
5465        ..Browsers::default()
5466      },
5467    );
5468    prefix_test(
5469      r#"
5470      .foo {
5471        flex: 1;
5472      }
5473    "#,
5474      indoc! {r#"
5475      .foo {
5476        -webkit-box-flex: 1;
5477        -moz-box-flex: 1;
5478        -webkit-flex: 1;
5479        -ms-flex: 1;
5480        flex: 1;
5481      }
5482    "#},
5483      Browsers {
5484        safari: Some(4 << 16),
5485        firefox: Some(4 << 16),
5486        ie: Some(10 << 16),
5487        ..Browsers::default()
5488      },
5489    );
5490    prefix_test(
5491      r#"
5492      .foo {
5493        -webkit-box-flex: 1;
5494        -moz-box-flex: 1;
5495        -webkit-flex: 1;
5496        -ms-flex: 1;
5497        flex: 1;
5498      }
5499    "#,
5500      indoc! {r#"
5501      .foo {
5502        flex: 1;
5503      }
5504    "#},
5505      Browsers {
5506        safari: Some(11 << 16),
5507        ..Browsers::default()
5508      },
5509    );
5510    prefix_test(
5511      r#"
5512      .foo {
5513        align-content: space-between;
5514      }
5515    "#,
5516      indoc! {r#"
5517      .foo {
5518        -ms-flex-line-pack: justify;
5519        -webkit-align-content: space-between;
5520        align-content: space-between;
5521      }
5522    "#},
5523      Browsers {
5524        safari: Some(4 << 16),
5525        firefox: Some(4 << 16),
5526        ie: Some(10 << 16),
5527        ..Browsers::default()
5528      },
5529    );
5530    prefix_test(
5531      r#"
5532      .foo {
5533        -ms-flex-line-pack: justify;
5534        -webkit-align-content: space-between;
5535        align-content: space-between;
5536      }
5537    "#,
5538      indoc! {r#"
5539      .foo {
5540        align-content: space-between;
5541      }
5542    "#},
5543      Browsers {
5544        safari: Some(11 << 16),
5545        ..Browsers::default()
5546      },
5547    );
5548    prefix_test(
5549      r#"
5550      .foo {
5551        justify-content: space-between;
5552      }
5553    "#,
5554      indoc! {r#"
5555      .foo {
5556        -webkit-box-pack: justify;
5557        -moz-box-pack: justify;
5558        -ms-flex-pack: justify;
5559        -webkit-justify-content: space-between;
5560        justify-content: space-between;
5561      }
5562    "#},
5563      Browsers {
5564        safari: Some(4 << 16),
5565        firefox: Some(4 << 16),
5566        ie: Some(10 << 16),
5567        ..Browsers::default()
5568      },
5569    );
5570    prefix_test(
5571      r#"
5572      .foo {
5573        -webkit-box-pack: justify;
5574        -moz-box-pack: justify;
5575        -ms-flex-pack: justify;
5576        -webkit-justify-content: space-between;
5577        justify-content: space-between;
5578      }
5579    "#,
5580      indoc! {r#"
5581      .foo {
5582        justify-content: space-between;
5583      }
5584    "#},
5585      Browsers {
5586        safari: Some(11 << 16),
5587        ..Browsers::default()
5588      },
5589    );
5590    prefix_test(
5591      r#"
5592      .foo {
5593        place-content: space-between flex-end;
5594      }
5595    "#,
5596      indoc! {r#"
5597      .foo {
5598        -ms-flex-line-pack: justify;
5599        -webkit-box-pack: end;
5600        -moz-box-pack: end;
5601        -ms-flex-pack: end;
5602        -webkit-align-content: space-between;
5603        align-content: space-between;
5604        -webkit-justify-content: flex-end;
5605        justify-content: flex-end;
5606      }
5607    "#},
5608      Browsers {
5609        safari: Some(4 << 16),
5610        firefox: Some(4 << 16),
5611        ie: Some(10 << 16),
5612        ..Browsers::default()
5613      },
5614    );
5615    prefix_test(
5616      r#"
5617      .foo {
5618        -ms-flex-line-pack: justify;
5619        -webkit-box-pack: end;
5620        -moz-box-pack: end;
5621        -ms-flex-pack: end;
5622        -webkit-align-content: space-between;
5623        -webkit-justify-content: flex-end;
5624        place-content: space-between flex-end;
5625      }
5626    "#,
5627      indoc! {r#"
5628      .foo {
5629        place-content: space-between flex-end;
5630      }
5631    "#},
5632      Browsers {
5633        safari: Some(11 << 16),
5634        ..Browsers::default()
5635      },
5636    );
5637    prefix_test(
5638      r#"
5639      .foo {
5640        place-content: space-between flex-end;
5641      }
5642    "#,
5643      indoc! {r#"
5644      .foo {
5645        align-content: space-between;
5646        justify-content: flex-end;
5647      }
5648    "#},
5649      Browsers {
5650        chrome: Some(30 << 16),
5651        ..Browsers::default()
5652      },
5653    );
5654    prefix_test(
5655      r#"
5656      .foo {
5657        place-content: space-between flex-end;
5658      }
5659    "#,
5660      indoc! {r#"
5661      .foo {
5662        place-content: space-between flex-end;
5663      }
5664    "#},
5665      Browsers {
5666        chrome: Some(60 << 16),
5667        ..Browsers::default()
5668      },
5669    );
5670    prefix_test(
5671      r#"
5672      .foo {
5673        align-self: flex-end;
5674      }
5675    "#,
5676      indoc! {r#"
5677      .foo {
5678        -ms-flex-item-align: end;
5679        -webkit-align-self: flex-end;
5680        align-self: flex-end;
5681      }
5682    "#},
5683      Browsers {
5684        safari: Some(4 << 16),
5685        firefox: Some(4 << 16),
5686        ie: Some(10 << 16),
5687        ..Browsers::default()
5688      },
5689    );
5690    prefix_test(
5691      r#"
5692      .foo {
5693        -ms-flex-item-align: end;
5694        -webkit-align-self: flex-end;
5695        align-self: flex-end;
5696      }
5697    "#,
5698      indoc! {r#"
5699      .foo {
5700        align-self: flex-end;
5701      }
5702    "#},
5703      Browsers {
5704        safari: Some(11 << 16),
5705        ..Browsers::default()
5706      },
5707    );
5708    prefix_test(
5709      r#"
5710      .foo {
5711        place-self: center flex-end;
5712      }
5713    "#,
5714      indoc! {r#"
5715      .foo {
5716        -ms-flex-item-align: center;
5717        -webkit-align-self: center;
5718        align-self: center;
5719        justify-self: flex-end;
5720      }
5721    "#},
5722      Browsers {
5723        safari: Some(4 << 16),
5724        firefox: Some(4 << 16),
5725        ie: Some(10 << 16),
5726        ..Browsers::default()
5727      },
5728    );
5729    prefix_test(
5730      r#"
5731      .foo {
5732        -ms-flex-item-align: center;
5733        -webkit-align-self: center;
5734        place-self: center flex-end;
5735      }
5736    "#,
5737      indoc! {r#"
5738      .foo {
5739        place-self: center flex-end;
5740      }
5741    "#},
5742      Browsers {
5743        safari: Some(11 << 16),
5744        ..Browsers::default()
5745      },
5746    );
5747    prefix_test(
5748      r#"
5749      .foo {
5750        place-self: center flex-end;
5751      }
5752    "#,
5753      indoc! {r#"
5754      .foo {
5755        align-self: center;
5756        justify-self: flex-end;
5757      }
5758    "#},
5759      Browsers {
5760        chrome: Some(57 << 16),
5761        ..Browsers::default()
5762      },
5763    );
5764    prefix_test(
5765      r#"
5766      .foo {
5767        place-self: center flex-end;
5768      }
5769    "#,
5770      indoc! {r#"
5771      .foo {
5772        place-self: center flex-end;
5773      }
5774    "#},
5775      Browsers {
5776        chrome: Some(59 << 16),
5777        ..Browsers::default()
5778      },
5779    );
5780    prefix_test(
5781      r#"
5782      .foo {
5783        align-items: flex-end;
5784      }
5785    "#,
5786      indoc! {r#"
5787      .foo {
5788        -webkit-box-align: end;
5789        -moz-box-align: end;
5790        -ms-flex-align: end;
5791        -webkit-align-items: flex-end;
5792        align-items: flex-end;
5793      }
5794    "#},
5795      Browsers {
5796        safari: Some(4 << 16),
5797        firefox: Some(4 << 16),
5798        ie: Some(10 << 16),
5799        ..Browsers::default()
5800      },
5801    );
5802    prefix_test(
5803      r#"
5804      .foo {
5805        -webkit-box-align: end;
5806        -moz-box-align: end;
5807        -ms-flex-align: end;
5808        -webkit-align-items: flex-end;
5809        align-items: flex-end;
5810      }
5811    "#,
5812      indoc! {r#"
5813      .foo {
5814        align-items: flex-end;
5815      }
5816    "#},
5817      Browsers {
5818        safari: Some(11 << 16),
5819        ..Browsers::default()
5820      },
5821    );
5822    prefix_test(
5823      r#"
5824      .foo {
5825        place-items: flex-end center;
5826      }
5827    "#,
5828      indoc! {r#"
5829      .foo {
5830        -webkit-box-align: end;
5831        -moz-box-align: end;
5832        -ms-flex-align: end;
5833        -webkit-align-items: flex-end;
5834        align-items: flex-end;
5835        justify-items: center;
5836      }
5837    "#},
5838      Browsers {
5839        safari: Some(4 << 16),
5840        firefox: Some(4 << 16),
5841        ie: Some(10 << 16),
5842        ..Browsers::default()
5843      },
5844    );
5845    prefix_test(
5846      r#"
5847      .foo {
5848        -webkit-box-align: end;
5849        -moz-box-align: end;
5850        -ms-flex-align: end;
5851        -webkit-align-items: flex-end;
5852        place-items: flex-end center;
5853      }
5854    "#,
5855      indoc! {r#"
5856      .foo {
5857        place-items: flex-end center;
5858      }
5859    "#},
5860      Browsers {
5861        safari: Some(11 << 16),
5862        ..Browsers::default()
5863      },
5864    );
5865    prefix_test(
5866      r#"
5867      .foo {
5868        place-items: flex-end center;
5869      }
5870    "#,
5871      indoc! {r#"
5872      .foo {
5873        align-items: flex-end;
5874        justify-items: center;
5875      }
5876    "#},
5877      Browsers {
5878        safari: Some(10 << 16),
5879        ..Browsers::default()
5880      },
5881    );
5882    prefix_test(
5883      r#"
5884      .foo {
5885        order: 1;
5886      }
5887    "#,
5888      indoc! {r#"
5889      .foo {
5890        -webkit-box-ordinal-group: 1;
5891        -moz-box-ordinal-group: 1;
5892        -ms-flex-order: 1;
5893        -webkit-order: 1;
5894        order: 1;
5895      }
5896    "#},
5897      Browsers {
5898        safari: Some(4 << 16),
5899        firefox: Some(4 << 16),
5900        ie: Some(10 << 16),
5901        ..Browsers::default()
5902      },
5903    );
5904    prefix_test(
5905      r#"
5906      .foo {
5907        -webkit-box-ordinal-group: 1;
5908        -moz-box-ordinal-group: 1;
5909        -ms-flex-order: 1;
5910        -webkit-order: 1;
5911        order: 1;
5912      }
5913    "#,
5914      indoc! {r#"
5915      .foo {
5916        order: 1;
5917      }
5918    "#},
5919      Browsers {
5920        safari: Some(11 << 16),
5921        ..Browsers::default()
5922      },
5923    );
5924    prefix_test(
5925      r#"
5926      .foo {
5927        -ms-flex: 0 0 8%;
5928        flex: 0 0 5%;
5929      }
5930    "#,
5931      indoc! {r#"
5932      .foo {
5933        -ms-flex: 0 0 8%;
5934        flex: 0 0 5%;
5935      }
5936    "#},
5937      Browsers {
5938        safari: Some(11 << 16),
5939        ..Browsers::default()
5940      },
5941    );
5942  }
5943
5944  #[test]
5945  fn test_font() {
5946    test(
5947      r#"
5948      .foo {
5949        font-family: "Helvetica", "Times New Roman", sans-serif;
5950        font-size: 12px;
5951        font-weight: bold;
5952        font-style: italic;
5953        font-stretch: expanded;
5954        font-variant-caps: small-caps;
5955        line-height: 1.2em;
5956      }
5957    "#,
5958      indoc! {r#"
5959      .foo {
5960        font: italic small-caps bold expanded 12px / 1.2em Helvetica, Times New Roman, sans-serif;
5961      }
5962    "#
5963      },
5964    );
5965
5966    minify_test(
5967      r#"
5968      .foo {
5969        font-family: "Helvetica", "Times New Roman", sans-serif;
5970        font-size: 12px;
5971        font-weight: bold;
5972        font-style: italic;
5973        font-stretch: expanded;
5974        font-variant-caps: small-caps;
5975        line-height: 1.2em;
5976      }
5977    "#,
5978      indoc! {".foo{font:italic small-caps 700 125% 12px/1.2em Helvetica,Times New Roman,sans-serif}"
5979      },
5980    );
5981
5982    test(
5983      r#"
5984      .foo {
5985        font: 12px "Helvetica", "Times New Roman", sans-serif;
5986        line-height: 1.2em;
5987      }
5988    "#,
5989      indoc! {r#"
5990      .foo {
5991        font: 12px / 1.2em Helvetica, Times New Roman, sans-serif;
5992      }
5993    "#
5994      },
5995    );
5996
5997    test(
5998      r#"
5999      .foo {
6000        font: 12px "Helvetica", "Times New Roman", sans-serif;
6001        line-height: var(--lh);
6002      }
6003    "#,
6004      indoc! {r#"
6005      .foo {
6006        font: 12px Helvetica, Times New Roman, sans-serif;
6007        line-height: var(--lh);
6008      }
6009    "#
6010      },
6011    );
6012
6013    minify_test(
6014      r#"
6015      .foo {
6016        font-family: "Helvetica", "Times New Roman", sans-serif;
6017        font-size: 12px;
6018        font-stretch: expanded;
6019      }
6020    "#,
6021      indoc! {".foo{font-family:Helvetica,Times New Roman,sans-serif;font-size:12px;font-stretch:125%}"
6022      },
6023    );
6024
6025    test(
6026      r#"
6027      .foo {
6028        font-family: "Helvetica", "Times New Roman", sans-serif;
6029        font-size: 12px;
6030        font-weight: bold;
6031        font-style: italic;
6032        font-stretch: expanded;
6033        font-variant-caps: all-small-caps;
6034        line-height: 1.2em;
6035      }
6036    "#,
6037      indoc! {r#"
6038      .foo {
6039        font: italic bold expanded 12px / 1.2em Helvetica, Times New Roman, sans-serif;
6040        font-variant-caps: all-small-caps;
6041      }
6042    "#
6043      },
6044    );
6045
6046    minify_test(
6047      ".foo { font: normal normal 600 9px/normal Charcoal; }",
6048      ".foo{font:600 9px Charcoal}",
6049    );
6050    minify_test(
6051      ".foo { font: normal normal 500 medium/normal Charcoal; }",
6052      ".foo{font:500 medium Charcoal}",
6053    );
6054    minify_test(
6055      ".foo { font: normal normal 400 medium Charcoal; }",
6056      ".foo{font:400 medium Charcoal}",
6057    );
6058    minify_test(
6059      ".foo { font: normal normal 500 medium/10px Charcoal; }",
6060      ".foo{font:500 medium/10px Charcoal}",
6061    );
6062    minify_test(
6063      ".foo { font-family: 'sans-serif'; }",
6064      ".foo{font-family:\"sans-serif\"}",
6065    );
6066    minify_test(".foo { font-family: sans-serif; }", ".foo{font-family:sans-serif}");
6067    minify_test(".foo { font-family: 'default'; }", ".foo{font-family:\"default\"}");
6068    minify_test(".foo { font-family: default; }", ".foo{font-family:default}");
6069    minify_test(".foo { font-family: 'inherit'; }", ".foo{font-family:\"inherit\"}");
6070    minify_test(".foo { font-family: inherit; }", ".foo{font-family:inherit}");
6071    minify_test(".foo { font-family: inherit test; }", ".foo{font-family:inherit test}");
6072    minify_test(
6073      ".foo { font-family: 'inherit test'; }",
6074      ".foo{font-family:inherit test}",
6075    );
6076    minify_test(".foo { font-family: revert; }", ".foo{font-family:revert}");
6077    minify_test(".foo { font-family: 'revert'; }", ".foo{font-family:\"revert\"}");
6078    minify_test(".foo { font-family: revert-layer; }", ".foo{font-family:revert-layer}");
6079    minify_test(
6080      ".foo { font-family: revert-layer, serif; }",
6081      ".foo{font-family:revert-layer,serif}",
6082    );
6083    minify_test(
6084      ".foo { font-family: 'revert', sans-serif; }",
6085      ".foo{font-family:\"revert\",sans-serif}",
6086    );
6087    minify_test(
6088      ".foo { font-family: 'revert', foo, sans-serif; }",
6089      ".foo{font-family:\"revert\",foo,sans-serif}",
6090    );
6091    minify_test(".foo { font-family: ''; }", ".foo{font-family:\"\"}");
6092
6093    // font-family in @font-face
6094    minify_test(
6095      "@font-face { font-family: 'revert'; }",
6096      "@font-face{font-family:\"revert\"}",
6097    );
6098    minify_test(
6099      "@font-face { font-family: 'revert-layer'; }",
6100      "@font-face{font-family:\"revert-layer\"}",
6101    );
6102
6103    prefix_test(
6104      r#"
6105      .foo {
6106        font-family: Helvetica, system-ui, sans-serif;
6107      }
6108    "#,
6109      indoc! {r#"
6110      .foo {
6111        font-family: Helvetica, system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Noto Sans, Ubuntu, Cantarell, Helvetica Neue, sans-serif;
6112      }
6113    "#
6114      },
6115      Browsers {
6116        safari: Some(8 << 16),
6117        ..Browsers::default()
6118      },
6119    );
6120
6121    prefix_test(
6122      r#"
6123      .foo {
6124        font: 100%/1.5 Helvetica, system-ui, sans-serif;
6125      }
6126    "#,
6127      indoc! {r#"
6128      .foo {
6129        font: 100% / 1.5 Helvetica, system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Noto Sans, Ubuntu, Cantarell, Helvetica Neue, sans-serif;
6130      }
6131    "#
6132      },
6133      Browsers {
6134        safari: Some(8 << 16),
6135        ..Browsers::default()
6136      },
6137    );
6138
6139    prefix_test(
6140      r#"
6141      .foo {
6142        font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
6143      }
6144    "#,
6145      indoc! {r#"
6146      .foo {
6147        font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Noto Sans, Ubuntu, Cantarell, Helvetica Neue, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;
6148      }
6149    "#
6150      },
6151      Browsers {
6152        firefox: Some(91 << 16),
6153        ..Browsers::default()
6154      },
6155    );
6156
6157    prefix_test(
6158      r#"
6159      .foo {
6160        font-size: 22px;
6161        font-size: max(2cqw, 22px);
6162      }
6163    "#,
6164      indoc! {r#"
6165      .foo {
6166        font-size: 22px;
6167        font-size: max(2cqw, 22px);
6168      }
6169    "#
6170      },
6171      Browsers {
6172        safari: Some(14 << 16),
6173        ..Browsers::default()
6174      },
6175    );
6176    prefix_test(
6177      r#"
6178      .foo {
6179        font-size: 22px;
6180        font-size: max(2cqw, 22px);
6181      }
6182    "#,
6183      indoc! {r#"
6184      .foo {
6185        font-size: max(2cqw, 22px);
6186      }
6187    "#
6188      },
6189      Browsers {
6190        safari: Some(16 << 16),
6191        ..Browsers::default()
6192      },
6193    );
6194
6195    prefix_test(
6196      r#"
6197      .foo {
6198        font-size: 22px;
6199        font-size: xxx-large;
6200      }
6201    "#,
6202      indoc! {r#"
6203      .foo {
6204        font-size: 22px;
6205        font-size: xxx-large;
6206      }
6207    "#
6208      },
6209      Browsers {
6210        chrome: Some(70 << 16),
6211        ..Browsers::default()
6212      },
6213    );
6214    prefix_test(
6215      r#"
6216      .foo {
6217        font-size: 22px;
6218        font-size: xxx-large;
6219      }
6220    "#,
6221      indoc! {r#"
6222      .foo {
6223        font-size: xxx-large;
6224      }
6225    "#
6226      },
6227      Browsers {
6228        chrome: Some(80 << 16),
6229        ..Browsers::default()
6230      },
6231    );
6232
6233    prefix_test(
6234      r#"
6235      .foo {
6236        font-weight: 700;
6237        font-weight: 789;
6238      }
6239    "#,
6240      indoc! {r#"
6241      .foo {
6242        font-weight: 700;
6243        font-weight: 789;
6244      }
6245    "#
6246      },
6247      Browsers {
6248        chrome: Some(60 << 16),
6249        ..Browsers::default()
6250      },
6251    );
6252    prefix_test(
6253      r#"
6254      .foo {
6255        font-weight: 700;
6256        font-weight: 789;
6257      }
6258    "#,
6259      indoc! {r#"
6260      .foo {
6261        font-weight: 789;
6262      }
6263    "#
6264      },
6265      Browsers {
6266        chrome: Some(80 << 16),
6267        ..Browsers::default()
6268      },
6269    );
6270
6271    prefix_test(
6272      r#"
6273      .foo {
6274        font-family: Helvetica;
6275        font-family: system-ui;
6276      }
6277    "#,
6278      indoc! {r#"
6279      .foo {
6280        font-family: Helvetica;
6281        font-family: system-ui;
6282      }
6283    "#
6284      },
6285      Browsers {
6286        chrome: Some(50 << 16),
6287        ..Browsers::default()
6288      },
6289    );
6290    prefix_test(
6291      r#"
6292      .foo {
6293        font-family: Helvetica;
6294        font-family: system-ui;
6295      }
6296    "#,
6297      indoc! {r#"
6298      .foo {
6299        font-family: system-ui;
6300      }
6301    "#
6302      },
6303      Browsers {
6304        chrome: Some(80 << 16),
6305        ..Browsers::default()
6306      },
6307    );
6308
6309    prefix_test(
6310      r#"
6311      .foo {
6312        font-style: oblique;
6313        font-style: oblique 40deg;
6314      }
6315    "#,
6316      indoc! {r#"
6317      .foo {
6318        font-style: oblique;
6319        font-style: oblique 40deg;
6320      }
6321    "#
6322      },
6323      Browsers {
6324        firefox: Some(50 << 16),
6325        ..Browsers::default()
6326      },
6327    );
6328    prefix_test(
6329      r#"
6330      .foo {
6331        font-style: oblique;
6332        font-style: oblique 40deg;
6333      }
6334    "#,
6335      indoc! {r#"
6336      .foo {
6337        font-style: oblique 40deg;
6338      }
6339    "#
6340      },
6341      Browsers {
6342        firefox: Some(80 << 16),
6343        ..Browsers::default()
6344      },
6345    );
6346
6347    prefix_test(
6348      r#"
6349      .foo {
6350        font: 22px Helvetica;
6351        font: xxx-large system-ui;
6352      }
6353    "#,
6354      indoc! {r#"
6355      .foo {
6356        font: 22px Helvetica;
6357        font: xxx-large system-ui;
6358      }
6359    "#
6360      },
6361      Browsers {
6362        chrome: Some(70 << 16),
6363        ..Browsers::default()
6364      },
6365    );
6366    prefix_test(
6367      r#"
6368      .foo {
6369        font: 22px Helvetica;
6370        font: xxx-large system-ui;
6371      }
6372    "#,
6373      indoc! {r#"
6374      .foo {
6375        font: xxx-large system-ui;
6376      }
6377    "#
6378      },
6379      Browsers {
6380        chrome: Some(80 << 16),
6381        ..Browsers::default()
6382      },
6383    );
6384
6385    prefix_test(
6386      r#"
6387      .foo {
6388        font: var(--fallback);
6389        font: xxx-large system-ui;
6390      }
6391    "#,
6392      indoc! {r#"
6393      .foo {
6394        font: var(--fallback);
6395        font: xxx-large system-ui;
6396      }
6397    "#
6398      },
6399      Browsers {
6400        chrome: Some(50 << 16),
6401        ..Browsers::default()
6402      },
6403    );
6404  }
6405
6406  #[test]
6407  fn test_vertical_align() {
6408    minify_test(".foo { vertical-align: middle }", ".foo{vertical-align:middle}");
6409    minify_test(".foo { vertical-align: 0.3em }", ".foo{vertical-align:.3em}");
6410  }
6411
6412  #[test]
6413  fn test_selectors() {
6414    minify_test(":nth-col(2n) {width: 20px}", ":nth-col(2n){width:20px}");
6415    minify_test(":nth-col(10n-1) {width: 20px}", ":nth-col(10n-1){width:20px}");
6416    minify_test(":nth-col(-n+2) {width: 20px}", ":nth-col(-n+2){width:20px}");
6417    minify_test(":nth-col(even) {width: 20px}", ":nth-col(2n){width:20px}");
6418    minify_test(":nth-col(odd) {width: 20px}", ":nth-col(odd){width:20px}");
6419    minify_test(":nth-last-col(2n) {width: 20px}", ":nth-last-col(2n){width:20px}");
6420    minify_test(":nth-last-col(10n-1) {width: 20px}", ":nth-last-col(10n-1){width:20px}");
6421    minify_test(":nth-last-col(-n+2) {width: 20px}", ":nth-last-col(-n+2){width:20px}");
6422    minify_test(":nth-last-col(even) {width: 20px}", ":nth-last-col(2n){width:20px}");
6423    minify_test(":nth-last-col(odd) {width: 20px}", ":nth-last-col(odd){width:20px}");
6424    minify_test(":nth-child(odd) {width: 20px}", ":nth-child(odd){width:20px}");
6425    minify_test(":nth-child(2n) {width: 20px}", ":nth-child(2n){width:20px}");
6426    minify_test(":nth-child(2n+1) {width: 20px}", ":nth-child(odd){width:20px}");
6427    minify_test(":first-child {width: 20px}", ":first-child{width:20px}");
6428    minify_test(":nth-child(1) {width: 20px}", ":first-child{width:20px}");
6429    minify_test(":nth-last-child(1) {width: 20px}", ":last-child{width:20px}");
6430    minify_test(":nth-of-type(1) {width: 20px}", ":first-of-type{width:20px}");
6431    minify_test(":nth-last-of-type(1) {width: 20px}", ":last-of-type{width:20px}");
6432    minify_test(
6433      ":nth-child(even of li.important) {width: 20px}",
6434      ":nth-child(2n of li.important){width:20px}",
6435    );
6436    minify_test(
6437      ":nth-child(1 of li.important) {width: 20px}",
6438      ":nth-child(1 of li.important){width:20px}",
6439    );
6440    minify_test(
6441      ":nth-last-child(even of li.important) {width: 20px}",
6442      ":nth-last-child(2n of li.important){width:20px}",
6443    );
6444    minify_test(
6445      ":nth-last-child(1 of li.important) {width: 20px}",
6446      ":nth-last-child(1 of li.important){width:20px}",
6447    );
6448    minify_test(
6449      ":nth-last-child(1 of.important) {width: 20px}",
6450      ":nth-last-child(1 of .important){width:20px}",
6451    );
6452
6453    minify_test("[foo=\"baz\"] {color:red}", "[foo=baz]{color:red}");
6454    minify_test("[foo=\"foo bar\"] {color:red}", "[foo=foo\\ bar]{color:red}");
6455    minify_test("[foo=\"foo bar baz\"] {color:red}", "[foo=\"foo bar baz\"]{color:red}");
6456    minify_test("[foo=\"\"] {color:red}", "[foo=\"\"]{color:red}");
6457    minify_test(
6458      ".test:not([foo=\"bar\"]) {color:red}",
6459      ".test:not([foo=bar]){color:red}",
6460    );
6461    minify_test(".test + .foo {color:red}", ".test+.foo{color:red}");
6462    minify_test(".test ~ .foo {color:red}", ".test~.foo{color:red}");
6463    minify_test(".test .foo {color:red}", ".test .foo{color:red}");
6464    minify_test(
6465      ".custom-range::-webkit-slider-thumb:active {color:red}",
6466      ".custom-range::-webkit-slider-thumb:active{color:red}",
6467    );
6468    minify_test(".test:not(.foo, .bar) {color:red}", ".test:not(.foo,.bar){color:red}");
6469    minify_test(".test:is(.foo, .bar) {color:red}", ".test:is(.foo,.bar){color:red}");
6470    minify_test(
6471      ".test:where(.foo, .bar) {color:red}",
6472      ".test:where(.foo,.bar){color:red}",
6473    );
6474    minify_test(
6475      ".test:where(.foo, .bar) {color:red}",
6476      ".test:where(.foo,.bar){color:red}",
6477    );
6478    minify_test(":host {color:red}", ":host{color:red}");
6479    minify_test(":host(.foo) {color:red}", ":host(.foo){color:red}");
6480    minify_test("::slotted(span) {color:red", "::slotted(span){color:red}");
6481    minify_test(
6482      "custom-element::part(foo) {color:red}",
6483      "custom-element::part(foo){color:red}",
6484    );
6485    minify_test(".sm\\:text-5xl { font-size: 3rem }", ".sm\\:text-5xl{font-size:3rem}");
6486    minify_test("a:has(> img) {color:red}", "a:has(>img){color:red}");
6487    minify_test("dt:has(+ dt) {color:red}", "dt:has(+dt){color:red}");
6488    minify_test(
6489      "section:not(:has(h1, h2, h3, h4, h5, h6)) {color:red}",
6490      "section:not(:has(h1,h2,h3,h4,h5,h6)){color:red}",
6491    );
6492    minify_test(
6493      ":has(.sibling ~ .target) {color:red}",
6494      ":has(.sibling~.target){color:red}",
6495    );
6496    minify_test(".x:has(> .a > .b) {color:red}", ".x:has(>.a>.b){color:red}");
6497    minify_test(".x:has(.bar, #foo) {color:red}", ".x:has(.bar,#foo){color:red}");
6498    minify_test(".x:has(span + span) {color:red}", ".x:has(span+span){color:red}");
6499    minify_test("a:has(:visited) {color:red}", "a:has(:visited){color:red}");
6500    for element in [
6501      "-webkit-scrollbar",
6502      "-webkit-scrollbar-button",
6503      "-webkit-scrollbar-track",
6504      "-webkit-scrollbar-track-piece",
6505      "-webkit-scrollbar-thumb",
6506      "-webkit-scrollbar-corner",
6507      "-webkit-resizer",
6508    ] {
6509      for class in [
6510        "enabled",
6511        "disabled",
6512        "hover",
6513        "active",
6514        "horizontal",
6515        "vertical",
6516        "decrement",
6517        "increment",
6518        "start",
6519        "end",
6520        "double-button",
6521        "single-button",
6522        "no-button",
6523        "corner-present",
6524        "window-inactive",
6525      ] {
6526        minify_test(
6527          &format!("::{}:{} {{color:red}}", element, class),
6528          &format!("::{}:{}{{color:red}}", element, class),
6529        );
6530      }
6531    }
6532    for class in [
6533      "horizontal",
6534      "vertical",
6535      "decrement",
6536      "increment",
6537      "start",
6538      "end",
6539      "double-button",
6540      "single-button",
6541      "no-button",
6542      "corner-present",
6543      "window-inactive",
6544    ] {
6545      error_test(
6546        &format!(":{} {{color:red}}", class),
6547        ParserError::SelectorError(SelectorError::InvalidPseudoClassBeforeWebKitScrollbar),
6548      );
6549    }
6550    for element in [
6551      "-webkit-scrollbar",
6552      "-webkit-scrollbar-button",
6553      "-webkit-scrollbar-track",
6554      "-webkit-scrollbar-track-piece",
6555      "-webkit-scrollbar-thumb",
6556      "-webkit-scrollbar-corner",
6557      "-webkit-resizer",
6558    ] {
6559      error_test(
6560        &format!("::{}:focus {{color:red}}", element),
6561        ParserError::SelectorError(SelectorError::InvalidPseudoClassAfterWebKitScrollbar),
6562      );
6563    }
6564
6565    error_test(
6566      "a::first-letter:last-child {color:red}",
6567      ParserError::SelectorError(SelectorError::InvalidPseudoClassAfterPseudoElement),
6568    );
6569    minify_test(
6570      "a:last-child::first-letter {color:red}",
6571      "a:last-child:first-letter{color:red}",
6572    );
6573
6574    prefix_test(
6575      ".test:not(.foo, .bar) {color:red}",
6576      indoc! {r#"
6577      .test:not(:-webkit-any(.foo, .bar)) {
6578        color: red;
6579      }
6580
6581      .test:not(:is(.foo, .bar)) {
6582        color: red;
6583      }
6584      "#},
6585      Browsers {
6586        safari: Some(8 << 16),
6587        ..Browsers::default()
6588      },
6589    );
6590    prefix_test(
6591      ".test:not(.foo, .bar) {color:red}",
6592      indoc! {r#"
6593      .test:not(.foo, .bar) {
6594        color: red;
6595      }
6596      "#},
6597      Browsers {
6598        safari: Some(11 << 16),
6599        ..Browsers::default()
6600      },
6601    );
6602
6603    minify_test("a:lang(en) {color:red}", "a:lang(en){color:red}");
6604    minify_test("a:lang(en, fr) {color:red}", "a:lang(en,fr){color:red}");
6605    minify_test("a:lang('en') {color:red}", "a:lang(en){color:red}");
6606    minify_test(
6607      "a:-webkit-any(.foo, .bar) {color:red}",
6608      "a:-webkit-any(.foo,.bar){color:red}",
6609    );
6610    minify_test("a:-moz-any(.foo, .bar) {color:red}", "a:-moz-any(.foo,.bar){color:red}");
6611
6612    prefix_test(
6613      "a:is(.foo, .bar) {color:red}",
6614      indoc! {r#"
6615      a:-webkit-any(.foo, .bar) {
6616        color: red;
6617      }
6618
6619      a:-moz-any(.foo, .bar) {
6620        color: red;
6621      }
6622
6623      a:is(.foo, .bar) {
6624        color: red;
6625      }
6626      "#},
6627      Browsers {
6628        safari: Some(11 << 16),
6629        firefox: Some(50 << 16),
6630        ..Browsers::default()
6631      },
6632    );
6633
6634    prefix_test(
6635      "a:is(.foo > .bar) {color:red}",
6636      indoc! {r#"
6637      a:is(.foo > .bar) {
6638        color: red;
6639      }
6640      "#},
6641      Browsers {
6642        safari: Some(11 << 16),
6643        firefox: Some(50 << 16),
6644        ..Browsers::default()
6645      },
6646    );
6647
6648    prefix_test(
6649      "a:lang(en, fr) {color:red}",
6650      indoc! {r#"
6651      a:-webkit-any(:lang(en), :lang(fr)) {
6652        color: red;
6653      }
6654
6655      a:-moz-any(:lang(en), :lang(fr)) {
6656        color: red;
6657      }
6658
6659      a:is(:lang(en), :lang(fr)) {
6660        color: red;
6661      }
6662      "#},
6663      Browsers {
6664        safari: Some(11 << 16),
6665        firefox: Some(50 << 16),
6666        ..Browsers::default()
6667      },
6668    );
6669
6670    prefix_test(
6671      "a:lang(en, fr) {color:red}",
6672      indoc! {r#"
6673      a:is(:lang(en), :lang(fr)) {
6674        color: red;
6675      }
6676      "#},
6677      Browsers {
6678        safari: Some(14 << 16),
6679        firefox: Some(88 << 16),
6680        ..Browsers::default()
6681      },
6682    );
6683
6684    prefix_test(
6685      "a:lang(en, fr) {color:red}",
6686      indoc! {r#"
6687      a:lang(en, fr) {
6688        color: red;
6689      }
6690      "#},
6691      Browsers {
6692        safari: Some(14 << 16),
6693        ..Browsers::default()
6694      },
6695    );
6696
6697    prefix_test(
6698      "a:dir(rtl) {color:red}",
6699      indoc! {r#"
6700      a:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
6701        color: red;
6702      }
6703
6704      a:-moz-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
6705        color: red;
6706      }
6707
6708      a:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
6709        color: red;
6710      }
6711      "#},
6712      Browsers {
6713        safari: Some(11 << 16),
6714        firefox: Some(50 << 16),
6715        ..Browsers::default()
6716      },
6717    );
6718
6719    prefix_test(
6720      "a:dir(ltr) {color:red}",
6721      indoc! {r#"
6722      a:not(:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
6723        color: red;
6724      }
6725
6726      a:not(:-moz-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
6727        color: red;
6728      }
6729
6730      a:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
6731        color: red;
6732      }
6733      "#},
6734      Browsers {
6735        safari: Some(11 << 16),
6736        firefox: Some(50 << 16),
6737        ..Browsers::default()
6738      },
6739    );
6740
6741    prefix_test(
6742      "a:dir(rtl) {color:red}",
6743      indoc! {r#"
6744      a:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
6745        color: red;
6746      }
6747      "#},
6748      Browsers {
6749        safari: Some(14 << 16),
6750        firefox: Some(88 << 16),
6751        ..Browsers::default()
6752      },
6753    );
6754
6755    prefix_test(
6756      "a:dir(ltr) {color:red}",
6757      indoc! {r#"
6758      a:not(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
6759        color: red;
6760      }
6761      "#},
6762      Browsers {
6763        safari: Some(14 << 16),
6764        firefox: Some(88 << 16),
6765        ..Browsers::default()
6766      },
6767    );
6768
6769    prefix_test(
6770      "a:dir(rtl) {color:red}",
6771      indoc! {r#"
6772      a:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) {
6773        color: red;
6774      }
6775      "#},
6776      Browsers {
6777        safari: Some(14 << 16),
6778        ..Browsers::default()
6779      },
6780    );
6781
6782    prefix_test(
6783      "a:dir(ltr) {color:red}",
6784      indoc! {r#"
6785      a:not(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
6786        color: red;
6787      }
6788      "#},
6789      Browsers {
6790        safari: Some(14 << 16),
6791        ..Browsers::default()
6792      },
6793    );
6794
6795    prefix_test(
6796      "a:is(:dir(rtl)) {color:red}",
6797      indoc! {r#"
6798      a:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) {
6799        color: red;
6800      }
6801      "#},
6802      Browsers {
6803        safari: Some(14 << 16),
6804        ..Browsers::default()
6805      },
6806    );
6807
6808    prefix_test(
6809      "a:where(:dir(rtl)) {color:red}",
6810      indoc! {r#"
6811      a:where(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
6812        color: red;
6813      }
6814      "#},
6815      Browsers {
6816        safari: Some(14 << 16),
6817        ..Browsers::default()
6818      },
6819    );
6820
6821    prefix_test(
6822      "a:has(:dir(rtl)) {color:red}",
6823      indoc! {r#"
6824      a:has(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
6825        color: red;
6826      }
6827      "#},
6828      Browsers {
6829        safari: Some(14 << 16),
6830        ..Browsers::default()
6831      },
6832    );
6833
6834    prefix_test(
6835      "a:not(:dir(rtl)) {color:red}",
6836      indoc! {r#"
6837      a:not(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
6838        color: red;
6839      }
6840      "#},
6841      Browsers {
6842        safari: Some(14 << 16),
6843        ..Browsers::default()
6844      },
6845    );
6846
6847    prefix_test(
6848      "a:dir(rtl)::after {color:red}",
6849      indoc! {r#"
6850      a:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi):after {
6851        color: red;
6852      }
6853      "#},
6854      Browsers {
6855        safari: Some(14 << 16),
6856        ..Browsers::default()
6857      },
6858    );
6859
6860    prefix_test(
6861      "a:dir(rtl) div {color:red}",
6862      indoc! {r#"
6863      a:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) div {
6864        color: red;
6865      }
6866      "#},
6867      Browsers {
6868        safari: Some(14 << 16),
6869        ..Browsers::default()
6870      },
6871    );
6872
6873    minify_test(".foo::cue {color: red}", ".foo::cue{color:red}");
6874    minify_test(".foo::cue-region {color: red}", ".foo::cue-region{color:red}");
6875    minify_test(".foo::cue(b) {color: red}", ".foo::cue(b){color:red}");
6876    minify_test(".foo::cue-region(b) {color: red}", ".foo::cue-region(b){color:red}");
6877    minify_test(
6878      "::cue(v[voice='active']) {color: yellow;}",
6879      "::cue(v[voice=active]){color:#ff0}",
6880    );
6881    minify_test(":foo(bar) { color: yellow }", ":foo(bar){color:#ff0}");
6882    minify_test("::foo(bar) { color: yellow }", "::foo(bar){color:#ff0}");
6883    minify_test("::foo(*) { color: yellow }", "::foo(*){color:#ff0}");
6884
6885    minify_test(":is(.foo) { color: yellow }", ".foo{color:#ff0}");
6886    minify_test(":is(#foo) { color: yellow }", "#foo{color:#ff0}");
6887    minify_test("a:is(.foo) { color: yellow }", "a.foo{color:#ff0}");
6888    minify_test("a:is([data-test]) { color: yellow }", "a[data-test]{color:#ff0}");
6889    minify_test(".foo:is(a) { color: yellow }", ".foo:is(a){color:#ff0}");
6890    minify_test(".foo:is(*|a) { color: yellow }", ".foo:is(*|a){color:#ff0}");
6891    minify_test(".foo:is(*) { color: yellow }", ".foo:is(*){color:#ff0}");
6892    minify_test(
6893      "@namespace svg url(http://www.w3.org/2000/svg); .foo:is(svg|a) { color: yellow }",
6894      "@namespace svg \"http://www.w3.org/2000/svg\";.foo:is(svg|a){color:#ff0}",
6895    );
6896    minify_test("a:is(.foo .bar) { color: yellow }", "a:is(.foo .bar){color:#ff0}");
6897    minify_test(":is(.foo, .bar) { color: yellow }", ":is(.foo,.bar){color:#ff0}");
6898    minify_test("a:is(:not(.foo)) { color: yellow }", "a:not(.foo){color:#ff0}");
6899    minify_test("a:is(:first-child) { color: yellow }", "a:first-child{color:#ff0}");
6900    minify_test("a:is(:has(.foo)) { color: yellow }", "a:has(.foo){color:#ff0}");
6901    minify_test("a:is(:is(.foo)) { color: yellow }", "a.foo{color:#ff0}");
6902    minify_test(":host(:hover) {color: red}", ":host(:hover){color:red}");
6903    minify_test("::slotted(:hover) {color: red}", "::slotted(:hover){color:red}");
6904
6905    minify_test(
6906      ":root::view-transition {position: fixed}",
6907      ":root::view-transition{position:fixed}",
6908    );
6909    minify_test(
6910      ":root:active-view-transition {position: fixed}",
6911      ":root:active-view-transition{position:fixed}",
6912    );
6913    minify_test(
6914      ":root:active-view-transition-type(slide-in) {position: fixed}",
6915      ":root:active-view-transition-type(slide-in){position:fixed}",
6916    );
6917    minify_test(
6918      ":root:active-view-transition-type(slide-in, reverse) {position: fixed}",
6919      ":root:active-view-transition-type(slide-in,reverse){position:fixed}",
6920    );
6921
6922    for name in &[
6923      "view-transition-group",
6924      "view-transition-image-pair",
6925      "view-transition-new",
6926      "view-transition-old",
6927    ] {
6928      minify_test(
6929        &format!(":root::{}(*) {{position: fixed}}", name),
6930        &format!(":root::{}(*){{position:fixed}}", name),
6931      );
6932      minify_test(
6933        &format!(":root::{}(*.class) {{position: fixed}}", name),
6934        &format!(":root::{}(*.class){{position:fixed}}", name),
6935      );
6936      minify_test(
6937        &format!(":root::{}(*.class.class) {{position: fixed}}", name),
6938        &format!(":root::{}(*.class.class){{position:fixed}}", name),
6939      );
6940      minify_test(
6941        &format!(":root::{}(foo) {{position: fixed}}", name),
6942        &format!(":root::{}(foo){{position:fixed}}", name),
6943      );
6944      minify_test(
6945        &format!(":root::{}(foo.class) {{position: fixed}}", name),
6946        &format!(":root::{}(foo.class){{position:fixed}}", name),
6947      );
6948      minify_test(
6949        &format!(":root::{}(foo.bar.baz) {{position: fixed}}", name),
6950        &format!(":root::{}(foo.bar.baz){{position:fixed}}", name),
6951      );
6952      minify_test(
6953        &format!(":root::{}(foo):only-child {{position: fixed}}", name),
6954        &format!(":root::{}(foo):only-child{{position:fixed}}", name),
6955      );
6956      minify_test(
6957        &format!(":root::{}(foo.bar.baz):only-child {{position: fixed}}", name),
6958        &format!(":root::{}(foo.bar.baz):only-child{{position:fixed}}", name),
6959      );
6960      minify_test(
6961        &format!(":root::{}(.foo) {{position: fixed}}", name),
6962        &format!(":root::{}(.foo){{position:fixed}}", name),
6963      );
6964      minify_test(
6965        &format!(":root::{}(.foo.bar) {{position: fixed}}", name),
6966        &format!(":root::{}(.foo.bar){{position:fixed}}", name),
6967      );
6968      error_test(
6969        &format!(":root::{}(foo):first-child {{position: fixed}}", name),
6970        ParserError::SelectorError(SelectorError::InvalidPseudoClassAfterPseudoElement),
6971      );
6972      error_test(
6973        &format!(":root::{}(foo)::before {{position: fixed}}", name),
6974        ParserError::SelectorError(SelectorError::InvalidState),
6975      );
6976      error_test(
6977        &format!(":root::{}(*.*) {{position: fixed}}", name),
6978        ParserError::SelectorError(SelectorError::InvalidState),
6979      );
6980      error_test(
6981        &format!(":root::{}(*. cls) {{position: fixed}}", name),
6982        ParserError::SelectorError(SelectorError::InvalidState),
6983      );
6984      error_test(
6985        &format!(":root::{}(foo .bar) {{position: fixed}}", name),
6986        ParserError::SelectorError(SelectorError::InvalidState),
6987      );
6988      error_test(
6989        &format!(":root::{}(*.cls. c) {{position: fixed}}", name),
6990        ParserError::SelectorError(SelectorError::InvalidState),
6991      );
6992      error_test(
6993        &format!(":root::{}(*.cls>cls) {{position: fixed}}", name),
6994        ParserError::SelectorError(SelectorError::InvalidState),
6995      );
6996      error_test(
6997        &format!(":root::{}(*.cls.foo.*) {{position: fixed}}", name),
6998        ParserError::SelectorError(SelectorError::InvalidState),
6999      );
7000    }
7001
7002    minify_test(".foo ::deep .bar {width: 20px}", ".foo ::deep .bar{width:20px}");
7003    minify_test(".foo::deep .bar {width: 20px}", ".foo::deep .bar{width:20px}");
7004    minify_test(".foo ::deep.bar {width: 20px}", ".foo ::deep.bar{width:20px}");
7005    minify_test(".foo ::unknown .bar {width: 20px}", ".foo ::unknown .bar{width:20px}");
7006    minify_test(
7007      ".foo ::unknown(foo) .bar {width: 20px}",
7008      ".foo ::unknown(foo) .bar{width:20px}",
7009    );
7010    minify_test(
7011      ".foo ::unknown:only-child {width: 20px}",
7012      ".foo ::unknown:only-child{width:20px}",
7013    );
7014    minify_test(
7015      ".foo ::unknown(.foo) .bar {width: 20px}",
7016      ".foo ::unknown(.foo) .bar{width:20px}",
7017    );
7018    minify_test(
7019      ".foo ::unknown(.foo .bar / .baz) .bar {width: 20px}",
7020      ".foo ::unknown(.foo .bar / .baz) .bar{width:20px}",
7021    );
7022    minify_test(
7023      ".foo ::unknown(something(foo)) .bar {width: 20px}",
7024      ".foo ::unknown(something(foo)) .bar{width:20px}",
7025    );
7026    minify_test(
7027      ".foo ::unknown([abc]) .bar {width: 20px}",
7028      ".foo ::unknown([abc]) .bar{width:20px}",
7029    );
7030
7031    let deep_options = ParserOptions {
7032      flags: ParserFlags::DEEP_SELECTOR_COMBINATOR,
7033      ..ParserOptions::default()
7034    };
7035
7036    error_test(
7037      ".foo >>> .bar {width: 20px}",
7038      ParserError::SelectorError(SelectorError::DanglingCombinator),
7039    );
7040    error_test(
7041      ".foo /deep/ .bar {width: 20px}",
7042      ParserError::SelectorError(SelectorError::DanglingCombinator),
7043    );
7044    minify_test_with_options(
7045      ".foo >>> .bar {width: 20px}",
7046      ".foo>>>.bar{width:20px}",
7047      deep_options.clone(),
7048    );
7049    minify_test_with_options(
7050      ".foo /deep/ .bar {width: 20px}",
7051      ".foo /deep/ .bar{width:20px}",
7052      deep_options.clone(),
7053    );
7054
7055    let pure_css_module_options = ParserOptions {
7056      css_modules: Some(crate::css_modules::Config {
7057        pure: true,
7058        ..Default::default()
7059      }),
7060      ..ParserOptions::default()
7061    };
7062
7063    minify_error_test_with_options(
7064      "div {width: 20px}",
7065      MinifyErrorKind::ImpureCSSModuleSelector,
7066      pure_css_module_options.clone(),
7067    );
7068    minify_error_test_with_options(
7069      ":global(.foo) {width: 20px}",
7070      MinifyErrorKind::ImpureCSSModuleSelector,
7071      pure_css_module_options.clone(),
7072    );
7073    minify_error_test_with_options(
7074      "[foo=bar] {width: 20px}",
7075      MinifyErrorKind::ImpureCSSModuleSelector,
7076      pure_css_module_options.clone(),
7077    );
7078    minify_error_test_with_options(
7079      "div, .foo {width: 20px}",
7080      MinifyErrorKind::ImpureCSSModuleSelector,
7081      pure_css_module_options.clone(),
7082    );
7083    minify_test_with_options(
7084      ":local(.foo) {width: 20px}",
7085      "._8Z4fiW_foo{width:20px}",
7086      pure_css_module_options.clone(),
7087    );
7088    minify_test_with_options(
7089      "div.my-class {color: red;}",
7090      "div._8Z4fiW_my-class{color:red}",
7091      pure_css_module_options.clone(),
7092    );
7093    minify_test_with_options(
7094      "#id {color: red;}",
7095      "#_8Z4fiW_id{color:red}",
7096      pure_css_module_options.clone(),
7097    );
7098    minify_test_with_options(
7099      "a .my-class{color: red;}",
7100      "a ._8Z4fiW_my-class{color:red}",
7101      pure_css_module_options.clone(),
7102    );
7103    minify_test_with_options(
7104      ".my-class a {color: red;}",
7105      "._8Z4fiW_my-class a{color:red}",
7106      pure_css_module_options.clone(),
7107    );
7108    minify_test_with_options(
7109      ".my-class:is(a) {color: red;}",
7110      "._8Z4fiW_my-class:is(a){color:red}",
7111      pure_css_module_options.clone(),
7112    );
7113    minify_test_with_options(
7114      "div:has(.my-class) {color: red;}",
7115      "div:has(._8Z4fiW_my-class){color:red}",
7116      pure_css_module_options.clone(),
7117    );
7118    minify_test_with_options(
7119      ".foo { html &:hover { a_value: some-value; } }",
7120      "._8Z4fiW_foo{html &:hover{a_value:some-value}}",
7121      pure_css_module_options.clone(),
7122    );
7123    minify_test_with_options(
7124      ".foo { span { color: red; } }",
7125      "._8Z4fiW_foo{& span{color:red}}",
7126      pure_css_module_options.clone(),
7127    );
7128    minify_error_test_with_options(
7129      "html { .foo { span { color: red; } } }",
7130      MinifyErrorKind::ImpureCSSModuleSelector,
7131      pure_css_module_options.clone(),
7132    );
7133    minify_test_with_options(
7134      ".foo { div { span { color: red; } } }",
7135      "._8Z4fiW_foo{& div{& span{color:red}}}",
7136      pure_css_module_options.clone(),
7137    );
7138    minify_error_test_with_options(
7139      "@scope (div) { .foo { color: red } }",
7140      MinifyErrorKind::ImpureCSSModuleSelector,
7141      pure_css_module_options.clone(),
7142    );
7143    minify_error_test_with_options(
7144      "@scope (.a) to (div) { .foo { color: red } }",
7145      MinifyErrorKind::ImpureCSSModuleSelector,
7146      pure_css_module_options.clone(),
7147    );
7148    minify_error_test_with_options(
7149      "@scope (.a) to (.b) { div { color: red } }",
7150      MinifyErrorKind::ImpureCSSModuleSelector,
7151      pure_css_module_options.clone(),
7152    );
7153    minify_test_with_options(
7154      "@scope (.a) to (.b) { .foo { color: red } }",
7155      "@scope(._8Z4fiW_a) to (._8Z4fiW_b){._8Z4fiW_foo{color:red}}",
7156      pure_css_module_options.clone(),
7157    );
7158    minify_test_with_options(
7159      "/* cssmodules-pure-no-check */ :global(.foo) { color: red }",
7160      ".foo{color:red}",
7161      pure_css_module_options.clone(),
7162    );
7163    minify_test_with_options(
7164      "/*! some license */ /* cssmodules-pure-no-check */ :global(.foo) { color: red }",
7165      "/*! some license */\n.foo{color:red}",
7166      pure_css_module_options.clone(),
7167    );
7168
7169    error_test(
7170      "input.defaultCheckbox::before h1 {width: 20px}",
7171      ParserError::SelectorError(SelectorError::UnexpectedSelectorAfterPseudoElement(Token::Ident(
7172        "h1".into(),
7173      ))),
7174    );
7175    error_test(
7176      "input.defaultCheckbox::before .my-class {width: 20px}",
7177      ParserError::SelectorError(SelectorError::UnexpectedSelectorAfterPseudoElement(Token::Delim('.'))),
7178    );
7179    error_test(
7180      "input.defaultCheckbox::before.my-class {width: 20px}",
7181      ParserError::SelectorError(SelectorError::UnexpectedSelectorAfterPseudoElement(Token::Delim('.'))),
7182    );
7183    error_test(
7184      "input.defaultCheckbox::before #id {width: 20px}",
7185      ParserError::SelectorError(SelectorError::UnexpectedSelectorAfterPseudoElement(Token::IDHash(
7186        "id".into(),
7187      ))),
7188    );
7189    error_test(
7190      "input.defaultCheckbox::before#id {width: 20px}",
7191      ParserError::SelectorError(SelectorError::UnexpectedSelectorAfterPseudoElement(Token::IDHash(
7192        "id".into(),
7193      ))),
7194    );
7195    error_test(
7196      "input.defaultCheckbox::before [attr] {width: 20px}",
7197      ParserError::SelectorError(SelectorError::UnexpectedSelectorAfterPseudoElement(
7198        Token::SquareBracketBlock,
7199      )),
7200    );
7201    error_test(
7202      "input.defaultCheckbox::before[attr] {width: 20px}",
7203      ParserError::SelectorError(SelectorError::UnexpectedSelectorAfterPseudoElement(
7204        Token::SquareBracketBlock,
7205      )),
7206    );
7207  }
7208
7209  #[test]
7210  fn test_keyframes() {
7211    minify_test(
7212      r#"
7213      @keyframes "test" {
7214        100% {
7215          background: blue
7216        }
7217      }
7218    "#,
7219      "@keyframes test{to{background:#00f}}",
7220    );
7221    minify_test(
7222      r#"
7223      @keyframes test {
7224        100% {
7225          background: blue
7226        }
7227      }
7228    "#,
7229      "@keyframes test{to{background:#00f}}",
7230    );
7231
7232    // named animation range percentages
7233    minify_test(
7234      r#"
7235      @keyframes test {
7236        entry 0% {
7237          background: blue
7238        }
7239        exit 100% {
7240          background: green
7241        }
7242      }
7243    "#,
7244      "@keyframes test{entry 0%{background:#00f}exit 100%{background:green}}",
7245    );
7246
7247    // CSS-wide keywords and `none` cannot remove quotes.
7248    minify_test(
7249      r#"
7250      @keyframes "revert" {
7251        from {
7252          background: green;
7253        }
7254      }
7255    "#,
7256      "@keyframes \"revert\"{0%{background:green}}",
7257    );
7258
7259    minify_test(
7260      r#"
7261      @keyframes "none" {
7262        from {
7263          background: green;
7264        }
7265      }
7266    "#,
7267      "@keyframes \"none\"{0%{background:green}}",
7268    );
7269
7270    // named animation ranges cannot be used with to or from
7271    minify_test(
7272      r#"
7273      @keyframes test {
7274        entry to {
7275          background: blue
7276        }
7277      }
7278    "#,
7279      "@keyframes test{}",
7280    );
7281
7282    // CSS-wide keywords without quotes throws an error.
7283    error_test(
7284      r#"
7285      @keyframes revert {}
7286    "#,
7287      ParserError::UnexpectedToken(Token::Ident("revert".into())),
7288    );
7289
7290    error_test(
7291      r#"
7292      @keyframes revert-layer {}
7293    "#,
7294      ParserError::UnexpectedToken(Token::Ident("revert-layer".into())),
7295    );
7296
7297    error_test(
7298      r#"
7299      @keyframes none {}
7300    "#,
7301      ParserError::UnexpectedToken(Token::Ident("none".into())),
7302    );
7303
7304    error_test(
7305      r#"
7306      @keyframes NONE {}
7307    "#,
7308      ParserError::UnexpectedToken(Token::Ident("NONE".into())),
7309    );
7310
7311    minify_test(
7312      r#"
7313      @-webkit-keyframes test {
7314        from {
7315          background: green;
7316          background-color: red;
7317        }
7318
7319        100% {
7320          background: blue
7321        }
7322      }
7323    "#,
7324      "@-webkit-keyframes test{0%{background:red}to{background:#00f}}",
7325    );
7326    minify_test(
7327      r#"
7328      @-moz-keyframes test {
7329        from {
7330          background: green;
7331          background-color: red;
7332        }
7333
7334        100% {
7335          background: blue
7336        }
7337      }
7338    "#,
7339      "@-moz-keyframes test{0%{background:red}to{background:#00f}}",
7340    );
7341    minify_test(r#"
7342      @-webkit-keyframes test {
7343        from {
7344          background: green;
7345          background-color: red;
7346        }
7347
7348        100% {
7349          background: blue
7350        }
7351      }
7352      @-moz-keyframes test {
7353        from {
7354          background: green;
7355          background-color: red;
7356        }
7357
7358        100% {
7359          background: blue
7360        }
7361      }
7362    "#, "@-webkit-keyframes test{0%{background:red}to{background:#00f}}@-moz-keyframes test{0%{background:red}to{background:#00f}}");
7363
7364    prefix_test(
7365      r#"
7366      @keyframes test {
7367        from {
7368          background: green;
7369        }
7370        to {
7371          background: blue
7372        }
7373      }
7374    "#,
7375      indoc! { r#"
7376      @-webkit-keyframes test {
7377        from {
7378          background: green;
7379        }
7380
7381        to {
7382          background: #00f;
7383        }
7384      }
7385
7386      @-moz-keyframes test {
7387        from {
7388          background: green;
7389        }
7390
7391        to {
7392          background: #00f;
7393        }
7394      }
7395
7396      @keyframes test {
7397        from {
7398          background: green;
7399        }
7400
7401        to {
7402          background: #00f;
7403        }
7404      }
7405    "#},
7406      Browsers {
7407        safari: Some(5 << 16),
7408        firefox: Some(6 << 16),
7409        ..Browsers::default()
7410      },
7411    );
7412    prefix_test(
7413      r#"
7414      @-webkit-keyframes test {
7415        from {
7416          background: green;
7417        }
7418
7419        to {
7420          background: blue;
7421        }
7422      }
7423      @-moz-keyframes test {
7424        from {
7425          background: green;
7426        }
7427
7428        to {
7429          background: blue;
7430        }
7431      }
7432      @keyframes test {
7433        from {
7434          background: green;
7435        }
7436        to {
7437          background: blue
7438        }
7439      }
7440    "#,
7441      indoc! { r#"
7442      @keyframes test {
7443        from {
7444          background: green;
7445        }
7446
7447        to {
7448          background: #00f;
7449        }
7450      }
7451    "#},
7452      Browsers {
7453        safari: Some(10 << 16),
7454        firefox: Some(17 << 16),
7455        ..Browsers::default()
7456      },
7457    );
7458    prefix_test(
7459      r#"
7460      @-webkit-keyframes test1 {
7461        from {
7462          background: green;
7463        }
7464
7465        to {
7466          background: blue;
7467        }
7468      }
7469
7470      @-moz-keyframes test2 {
7471        from {
7472          background: green;
7473        }
7474
7475        to {
7476          background: blue;
7477        }
7478      }
7479
7480      @keyframes test3 {
7481        from {
7482          background: green;
7483        }
7484        to {
7485          background: blue
7486        }
7487      }
7488    "#,
7489      indoc! { r#"
7490      @-webkit-keyframes test1 {
7491        from {
7492          background: green;
7493        }
7494
7495        to {
7496          background: #00f;
7497        }
7498      }
7499
7500      @-moz-keyframes test2 {
7501        from {
7502          background: green;
7503        }
7504
7505        to {
7506          background: #00f;
7507        }
7508      }
7509
7510      @keyframes test3 {
7511        from {
7512          background: green;
7513        }
7514
7515        to {
7516          background: #00f;
7517        }
7518      }
7519    "#},
7520      Browsers {
7521        safari: Some(10 << 16),
7522        firefox: Some(17 << 16),
7523        ..Browsers::default()
7524      },
7525    );
7526    prefix_test(
7527      r#"
7528      @-webkit-keyframes test {
7529        from {
7530          background: green;
7531        }
7532
7533        to {
7534          background: red;
7535        }
7536      }
7537      @-moz-keyframes test {
7538        from {
7539          background: green;
7540        }
7541
7542        to {
7543          background: pink;
7544        }
7545      }
7546      @keyframes test {
7547        from {
7548          background: green;
7549        }
7550        to {
7551          background: blue
7552        }
7553      }
7554    "#,
7555      indoc! { r#"
7556      @-webkit-keyframes test {
7557        from {
7558          background: green;
7559        }
7560
7561        to {
7562          background: red;
7563        }
7564      }
7565
7566      @-moz-keyframes test {
7567        from {
7568          background: green;
7569        }
7570
7571        to {
7572          background: pink;
7573        }
7574      }
7575
7576      @keyframes test {
7577        from {
7578          background: green;
7579        }
7580
7581        to {
7582          background: #00f;
7583        }
7584      }
7585    "#},
7586      Browsers {
7587        safari: Some(10 << 16),
7588        firefox: Some(17 << 16),
7589        ..Browsers::default()
7590      },
7591    );
7592
7593    minify_test(
7594      r#"
7595      @keyframes test {
7596        100% {
7597          background: blue
7598        }
7599      }
7600
7601      @keyframes test {
7602        100% {
7603          background: red
7604        }
7605      }
7606    "#,
7607      "@keyframes test{to{background:red}}",
7608    );
7609    minify_test(
7610      r#"
7611      @keyframes test {
7612        100% {
7613          background: blue
7614        }
7615      }
7616
7617      @-webkit-keyframes test {
7618        100% {
7619          background: red
7620        }
7621      }
7622    "#,
7623      "@keyframes test{to{background:#00f}}@-webkit-keyframes test{to{background:red}}",
7624    );
7625  }
7626
7627  #[test]
7628  fn test_important() {
7629    test(
7630      r#"
7631      .foo {
7632        align-items: center;
7633        justify-items: center !important;
7634      }
7635    "#,
7636      indoc! {r#"
7637      .foo {
7638        align-items: center;
7639        justify-items: center !important;
7640      }
7641    "#},
7642    );
7643
7644    test(
7645      r#"
7646      .foo {
7647        justify-items: center !important;
7648        align-items: center;
7649      }
7650    "#,
7651      indoc! {r#"
7652      .foo {
7653        align-items: center;
7654        justify-items: center !important;
7655      }
7656    "#},
7657    );
7658
7659    minify_test(
7660      r#"
7661      .foo {
7662        font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace !important;
7663      }
7664    "#,
7665      ".foo{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace!important}",
7666    );
7667  }
7668
7669  #[test]
7670  fn test_calc() {
7671    minify_test(".foo { width: calc(20px * 2) }", ".foo{width:40px}");
7672    minify_test(".foo { font-size: calc(100vw / 35) }", ".foo{font-size:2.85714vw}");
7673    minify_test(".foo { width: calc(20px * 2 * 3) }", ".foo{width:120px}");
7674    minify_test(".foo { width: calc(20px + 30px) }", ".foo{width:50px}");
7675    minify_test(".foo { width: calc(20px + 30px + 40px) }", ".foo{width:90px}");
7676    minify_test(".foo { width: calc(100% - 30px) }", ".foo{width:calc(100% - 30px)}");
7677    minify_test(
7678      ".foo { width: calc(100% - 30px + 20px) }",
7679      ".foo{width:calc(100% - 10px)}",
7680    );
7681    minify_test(
7682      ".foo { width: calc(20px + 100% - 30px) }",
7683      ".foo{width:calc(100% - 10px)}",
7684    );
7685    minify_test(
7686      ".foo { width: calc(20px + 100% + 10vw - 30px) }",
7687      ".foo{width:calc(100% - 10px + 10vw)}",
7688    );
7689    minify_test(
7690      ".foo { width: calc(20px + 100% - 30px) }",
7691      ".foo{width:calc(100% - 10px)}",
7692    );
7693    minify_test(
7694      ".foo { width: calc(2 * (100% - 20px)) }",
7695      ".foo{width:calc(200% - 40px)}",
7696    );
7697    minify_test(
7698      ".foo { width: calc((100% - 20px) * 2) }",
7699      ".foo{width:calc(200% - 40px)}",
7700    );
7701    minify_test(".foo { width: calc(100% - 20px * 2) }", ".foo{width:calc(100% - 40px)}");
7702    minify_test(".foo { width: calc(1px + 1px) }", ".foo{width:2px}");
7703    minify_test(".foo { width: calc(100vw / 2) }", ".foo{width:50vw}");
7704    minify_test(".foo { width: calc(50px - (20px - 30px)) }", ".foo{width:60px}");
7705    minify_test(".foo { width: calc(100px - (100px - 100%)) }", ".foo{width:100%}");
7706    minify_test(
7707      ".foo { width: calc(100px + (100px - 100%)) }",
7708      ".foo{width:calc(200px - 100%)}",
7709    );
7710    minify_test(
7711      ".foo { width: calc(1px - (2em + 3%)) }",
7712      ".foo{width:calc(1px + -2em - 3%)}",
7713    ); // TODO: fix sign
7714    minify_test(
7715      ".foo { width: calc((100vw - 50em) / 2) }",
7716      ".foo{width:calc(50vw - 25em)}",
7717    );
7718    minify_test(
7719      ".foo { width: calc(1px - (2em + 4vh + 3%)) }",
7720      ".foo{width:calc(1px + -2em - 4vh - 3%)}",
7721    ); // TODO
7722    minify_test(
7723      ".foo { width: calc(1px + (2em + (3vh + 4px))) }",
7724      ".foo{width:calc(2em + 3vh + 5px)}",
7725    );
7726    minify_test(
7727      ".foo { width: calc(1px - (2em + 4px - 6vh) / 2) }",
7728      ".foo{width:calc(-1em - 1px + 3vh)}",
7729    );
7730    minify_test(
7731      ".foo { width: calc(100% - calc(50% + 25px)) }",
7732      ".foo{width:calc(50% - 25px)}",
7733    );
7734    minify_test(".foo { width: calc(1px/100) }", ".foo{width:.01px}");
7735    minify_test(
7736      ".foo { width: calc(100vw / 2 - 6px + 0px) }",
7737      ".foo{width:calc(50vw - 6px)}",
7738    );
7739    minify_test(".foo { width: calc(1px + 1) }", ".foo{width:calc(1px + 1)}");
7740    minify_test(
7741      ".foo { width: calc( (1em - calc( 10px + 1em)) / 2) }",
7742      ".foo{width:-5px}",
7743    );
7744    minify_test(
7745      ".foo { width: calc((100px - 1em) + (-50px + 1em)) }",
7746      ".foo{width:50px}",
7747    );
7748    minify_test(
7749      ".foo { width: calc(100% + (2 * 100px) - ((75.37% - 63.5px) - 900px)) }",
7750      ".foo{width:calc(24.63% + 1163.5px)}",
7751    );
7752    minify_test(
7753      ".foo { width: calc(((((100% + (2 * 30px) + 63.5px) / 0.7537) - (100vw - 60px)) / 2) + 30px) }",
7754      ".foo{width:calc(66.3394% + 141.929px - 50vw)}",
7755    );
7756    minify_test(
7757      ".foo { width: calc(((75.37% - 63.5px) - 900px) + (2 * 100px)) }",
7758      ".foo{width:calc(75.37% - 763.5px)}",
7759    );
7760    minify_test(
7761      ".foo { width: calc((900px - (10% - 63.5px)) + (2 * 100px)) }",
7762      ".foo{width:calc(1163.5px - 10%)}",
7763    );
7764    minify_test(".foo { width: calc(500px/0) }", ".foo{width:calc(500px/0)}");
7765    minify_test(".foo { width: calc(500px/2px) }", ".foo{width:calc(500px/2px)}");
7766    minify_test(".foo { width: calc(100% / 3 * 3) }", ".foo{width:100%}");
7767    minify_test(".foo { width: calc(+100px + +100px) }", ".foo{width:200px}");
7768    minify_test(".foo { width: calc(+100px - +100px) }", ".foo{width:0}");
7769    minify_test(".foo { width: calc(200px * +1) }", ".foo{width:200px}");
7770    minify_test(".foo { width: calc(200px / +1) }", ".foo{width:200px}");
7771    minify_test(".foo { width: calc(1.1e+1px + 1.1e+1px) }", ".foo{width:22px}");
7772    minify_test(".foo { border-width: calc(1px + 2px) }", ".foo{border-width:3px}");
7773    minify_test(
7774      ".foo { border-width: calc(1em + 2px + 2em + 3px) }",
7775      ".foo{border-width:calc(3em + 5px)}",
7776    );
7777
7778    minify_test(
7779      ".foo { border-width: min(1em, 2px) }",
7780      ".foo{border-width:min(1em,2px)}",
7781    );
7782    minify_test(
7783      ".foo { border-width: min(1em + 2em, 2px + 2px) }",
7784      ".foo{border-width:min(3em,4px)}",
7785    );
7786    minify_test(
7787      ".foo { border-width: min(1em + 2px, 2px + 1em) }",
7788      ".foo{border-width:min(1em + 2px,2px + 1em)}",
7789    );
7790    minify_test(
7791      ".foo { border-width: min(1em + 2px + 2px, 2px + 1em + 1px) }",
7792      ".foo{border-width:min(1em + 4px,3px + 1em)}",
7793    );
7794    minify_test(
7795      ".foo { border-width: min(2px + 1px, 3px + 4px) }",
7796      ".foo{border-width:3px}",
7797    );
7798    minify_test(
7799      ".foo { border-width: min(1px, 1em, 2px, 3in) }",
7800      ".foo{border-width:min(1px,1em)}",
7801    );
7802
7803    minify_test(
7804      ".foo { border-width: max(1em, 2px) }",
7805      ".foo{border-width:max(1em,2px)}",
7806    );
7807    minify_test(
7808      ".foo { border-width: max(1em + 2em, 2px + 2px) }",
7809      ".foo{border-width:max(3em,4px)}",
7810    );
7811    minify_test(
7812      ".foo { border-width: max(1em + 2px, 2px + 1em) }",
7813      ".foo{border-width:max(1em + 2px,2px + 1em)}",
7814    );
7815    minify_test(
7816      ".foo { border-width: max(1em + 2px + 2px, 2px + 1em + 1px) }",
7817      ".foo{border-width:max(1em + 4px,3px + 1em)}",
7818    );
7819    minify_test(
7820      ".foo { border-width: max(2px + 1px, 3px + 4px) }",
7821      ".foo{border-width:7px}",
7822    );
7823    minify_test(
7824      ".foo { border-width: max(1px, 1em, 2px, 3in) }",
7825      ".foo{border-width:max(3in,1em)}",
7826    );
7827
7828    minify_test(".foo { border-width: clamp(1px, 2px, 3px) }", ".foo{border-width:2px}");
7829    minify_test(".foo { border-width: clamp(1px, 10px, 3px) }", ".foo{border-width:3px}");
7830    minify_test(".foo { border-width: clamp(5px, 2px, 10px) }", ".foo{border-width:5px}");
7831    minify_test(
7832      ".foo { border-width: clamp(100px, 2px, 10px) }",
7833      ".foo{border-width:100px}",
7834    );
7835    minify_test(
7836      ".foo { border-width: clamp(5px + 5px, 5px + 7px, 10px + 20px) }",
7837      ".foo{border-width:12px}",
7838    );
7839
7840    minify_test(
7841      ".foo { border-width: clamp(1em, 2px, 4vh) }",
7842      ".foo{border-width:clamp(1em,2px,4vh)}",
7843    );
7844    minify_test(
7845      ".foo { border-width: clamp(1em, 2em, 4vh) }",
7846      ".foo{border-width:clamp(1em,2em,4vh)}",
7847    );
7848    minify_test(
7849      ".foo { border-width: clamp(1em, 2vh, 4vh) }",
7850      ".foo{border-width:max(1em,2vh)}",
7851    );
7852    minify_test(
7853      ".foo { border-width: clamp(1px, 1px + 2em, 4px) }",
7854      ".foo{border-width:clamp(1px,1px + 2em,4px)}",
7855    );
7856    minify_test(".foo { border-width: clamp(1px, 2pt, 1in) }", ".foo{border-width:2pt}");
7857    minify_test(
7858      ".foo { width: clamp(-100px, 0px, 50% - 50vw); }",
7859      ".foo{width:clamp(-100px,0px,50% - 50vw)}",
7860    );
7861
7862    minify_test(
7863      ".foo { top: calc(-1 * clamp(1.75rem, 8vw, 4rem)) }",
7864      ".foo{top:calc(-1*clamp(1.75rem,8vw,4rem))}",
7865    );
7866    minify_test(
7867      ".foo { top: calc(-1 * min(1.75rem, 8vw, 4rem)) }",
7868      ".foo{top:calc(-1*min(1.75rem,8vw))}",
7869    );
7870    minify_test(
7871      ".foo { top: calc(-1 * max(1.75rem, 8vw, 4rem)) }",
7872      ".foo{top:calc(-1*max(4rem,8vw))}",
7873    );
7874    minify_test(
7875      ".foo { top: calc(clamp(1.75rem, 8vw, 4rem) * -1) }",
7876      ".foo{top:calc(-1*clamp(1.75rem,8vw,4rem))}",
7877    );
7878    minify_test(
7879      ".foo { top: calc(min(1.75rem, 8vw, 4rem) * -1) }",
7880      ".foo{top:calc(-1*min(1.75rem,8vw))}",
7881    );
7882    minify_test(
7883      ".foo { top: calc(max(1.75rem, 8vw, 4rem) * -1) }",
7884      ".foo{top:calc(-1*max(4rem,8vw))}",
7885    );
7886    minify_test(
7887      ".foo { top: calc(clamp(1.75rem, 8vw, 4rem) / 2) }",
7888      ".foo{top:calc(clamp(1.75rem,8vw,4rem)/2)}",
7889    );
7890    minify_test(
7891      ".foo { top: calc(min(1.75rem, 8vw, 4rem) / 2) }",
7892      ".foo{top:calc(min(1.75rem,8vw)/2)}",
7893    );
7894    minify_test(
7895      ".foo { top: calc(max(1.75rem, 8vw, 4rem) / 2) }",
7896      ".foo{top:calc(max(4rem,8vw)/2)}",
7897    );
7898    minify_test(
7899      ".foo { top: calc(0.5 * clamp(1.75rem, 8vw, 4rem)) }",
7900      ".foo{top:calc(clamp(1.75rem,8vw,4rem)/2)}",
7901    );
7902    minify_test(
7903      ".foo { top: calc(1 * clamp(1.75rem, 8vw, 4rem)) }",
7904      ".foo{top:calc(clamp(1.75rem,8vw,4rem))}",
7905    );
7906    minify_test(
7907      ".foo { top: calc(2 * clamp(1.75rem, 8vw, 4rem) / 2) }",
7908      ".foo{top:calc(clamp(1.75rem,8vw,4rem))}",
7909    );
7910
7911    minify_test(".foo { width: max(0px, 1vw) }", ".foo{width:max(0px,1vw)}");
7912
7913    prefix_test(
7914      ".foo { border-width: clamp(1em, 2px, 4vh) }",
7915      indoc! { r#"
7916        .foo {
7917          border-width: max(1em, min(2px, 4vh));
7918        }
7919      "#},
7920      Browsers {
7921        safari: Some(12 << 16),
7922        ..Browsers::default()
7923      },
7924    );
7925
7926    prefix_test(
7927      ".foo { border-width: clamp(1em, 2px, 4vh) }",
7928      indoc! { r#"
7929        .foo {
7930          border-width: clamp(1em, 2px, 4vh);
7931        }
7932      "#},
7933      Browsers {
7934        safari: Some(14 << 16),
7935        ..Browsers::default()
7936      },
7937    );
7938
7939    minify_test(".foo { width: calc(1vh + 2vh) }", ".foo{width:3vh}");
7940    minify_test(".foo { width: calc(1dvh + 2dvh) }", ".foo{width:3dvh}");
7941    minify_test(".foo { width: calc(1lvh + 2lvh) }", ".foo{width:3lvh}");
7942    minify_test(".foo { width: calc(1svh + 2svh) }", ".foo{width:3svh}");
7943    minify_test(".foo { width: calc(1sVmin + 2Svmin) }", ".foo{width:3svmin}");
7944    minify_test(".foo { width: calc(1ic + 2ic) }", ".foo{width:3ic}");
7945    minify_test(".foo { width: calc(1ric + 2ric) }", ".foo{width:3ric}");
7946    minify_test(".foo { width: calc(1cap + 2cap) }", ".foo{width:3cap}");
7947    minify_test(".foo { width: calc(1lh + 2lh) }", ".foo{width:3lh}");
7948    minify_test(".foo { width: calc(1x + 2x) }", ".foo{width:calc(1x + 2x)}");
7949    minify_test(
7950      ".foo { left: calc(50% - 100px + clamp(0px, calc(50vw - 50px), 100px)) }",
7951      ".foo{left:calc(50% - 100px + clamp(0px,50vw - 50px,100px))}",
7952    );
7953    minify_test(
7954      ".foo { left: calc(10px + min(10px, 1rem) + max(2px, 1vw)) }",
7955      ".foo{left:calc(10px + min(10px,1rem) + max(2px,1vw))}",
7956    );
7957    minify_test(".foo { width: round(22px, 5px) }", ".foo{width:20px}");
7958    minify_test(".foo { width: round(nearest, 22px, 5px) }", ".foo{width:20px}");
7959    minify_test(".foo { width: round(down, 22px, 5px) }", ".foo{width:20px}");
7960    minify_test(".foo { width: round(to-zero, 22px, 5px) }", ".foo{width:20px}");
7961    minify_test(".foo { width: round(up, 22px, 5px) }", ".foo{width:25px}");
7962    minify_test(".foo { width: round(23px, 5px) }", ".foo{width:25px}");
7963    minify_test(".foo { width: round(nearest, 23px, 5px) }", ".foo{width:25px}");
7964    minify_test(".foo { width: round(down, 23px, 5px) }", ".foo{width:20px}");
7965    minify_test(".foo { width: round(to-zero, 23px, 5px) }", ".foo{width:20px}");
7966    minify_test(".foo { width: round(up, 23px, 5px) }", ".foo{width:25px}");
7967    minify_test(".foo { width: round(22px, 5vw) }", ".foo{width:round(22px,5vw)}");
7968    minify_test(".foo { rotate: round(22deg, 5deg) }", ".foo{rotate:20deg}");
7969    minify_test(".foo { rotate: round(22deg, 5deg) }", ".foo{rotate:20deg}");
7970    minify_test(
7971      ".foo { transition-duration: round(22ms, 5ms) }",
7972      ".foo{transition-duration:20ms}",
7973    );
7974    minify_test(".foo { margin: round(to-zero, -23px, 5px) }", ".foo{margin:-20px}");
7975    minify_test(".foo { margin: round(nearest, -23px, 5px) }", ".foo{margin:-25px}");
7976    minify_test(".foo { margin: calc(10px * round(22, 5)) }", ".foo{margin:200px}");
7977    minify_test(".foo { width: rem(18px, 5px) }", ".foo{width:3px}");
7978    minify_test(".foo { width: rem(-18px, 5px) }", ".foo{width:-3px}");
7979    minify_test(".foo { width: rem(18px, 5vw) }", ".foo{width:rem(18px,5vw)}");
7980    minify_test(".foo { rotate: rem(-140deg, -90deg) }", ".foo{rotate:-50deg}");
7981    minify_test(".foo { rotate: rem(140deg, -90deg) }", ".foo{rotate:50deg}");
7982    minify_test(".foo { width: calc(10px * rem(18, 5)) }", ".foo{width:30px}");
7983    minify_test(".foo { width: mod(18px, 5px) }", ".foo{width:3px}");
7984    minify_test(".foo { width: mod(-18px, 5px) }", ".foo{width:2px}");
7985    minify_test(".foo { rotate: mod(-140deg, -90deg) }", ".foo{rotate:-50deg}");
7986    minify_test(".foo { rotate: mod(140deg, -90deg) }", ".foo{rotate:-40deg}");
7987    minify_test(".foo { width: mod(18px, 5vw) }", ".foo{width:mod(18px,5vw)}");
7988    minify_test(
7989      ".foo { transform: rotateX(mod(140deg, -90deg)) rotateY(rem(140deg, -90deg)) }",
7990      ".foo{transform:rotateX(-40deg)rotateY(50deg)}",
7991    );
7992    minify_test(".foo { width: calc(10px * mod(18, 5)) }", ".foo{width:30px}");
7993
7994    minify_test(
7995      ".foo { width: calc(100% - 30px - 0) }",
7996      ".foo{width:calc(100% - 30px - 0)}",
7997    );
7998    minify_test(
7999      ".foo { width: calc(100% - 30px - 1 - 2) }",
8000      ".foo{width:calc(100% - 30px - 3)}",
8001    );
8002    minify_test(
8003      ".foo { width: calc(1 - 2 - 100% - 30px) }",
8004      ".foo{width:calc(-1 - 100% - 30px)}",
8005    );
8006    minify_test(
8007      ".foo { width: calc(2 * min(1px, 1vmin) - min(1px, 1vmin)); }",
8008      ".foo{width:calc(2*min(1px,1vmin) - min(1px,1vmin))}",
8009    );
8010    minify_test(
8011      ".foo { width: calc(100% - clamp(1.125rem, 1.25vw, 1.2375rem) - clamp(1.125rem, 1.25vw, 1.2375rem)); }",
8012      ".foo{width:calc(100% - clamp(1.125rem,1.25vw,1.2375rem) - clamp(1.125rem,1.25vw,1.2375rem))}",
8013    );
8014    minify_test(
8015      ".foo { width: calc(100% - 2 (2 * var(--card-margin))); }",
8016      ".foo{width:calc(100% - 2 (2*var(--card-margin)))}",
8017    );
8018  }
8019
8020  #[test]
8021  fn test_trig() {
8022    minify_test(".foo { width: calc(2px * pi); }", ".foo{width:6.28319px}");
8023    minify_test(".foo { width: calc(2px / pi); }", ".foo{width:.63662px}");
8024    // minify_test(
8025    //   ".foo { width: calc(2px * infinity); }",
8026    //   ".foo{width:calc(2px*infinity)}",
8027    // );
8028    // minify_test(
8029    //   ".foo { width: calc(2px * -infinity); }",
8030    //   ".foo{width:calc(2px*-infinity)}",
8031    // );
8032    minify_test(".foo { width: calc(100px * sin(45deg))", ".foo{width:70.7107px}");
8033    minify_test(".foo { width: calc(100px * sin(.125turn))", ".foo{width:70.7107px}");
8034    minify_test(
8035      ".foo { width: calc(100px * sin(3.14159265 / 4))",
8036      ".foo{width:70.7107px}",
8037    );
8038    minify_test(".foo { width: calc(100px * sin(pi / 4))", ".foo{width:70.7107px}");
8039    minify_test(
8040      ".foo { width: calc(100px * sin(22deg + 23deg))",
8041      ".foo{width:70.7107px}",
8042    );
8043
8044    minify_test(".foo { width: calc(2px * cos(45deg))", ".foo{width:1.41421px}");
8045    minify_test(".foo { width: calc(2px * tan(45deg))", ".foo{width:2px}");
8046
8047    minify_test(".foo { rotate: asin(sin(45deg))", ".foo{rotate:45deg}");
8048    minify_test(".foo { rotate: asin(1)", ".foo{rotate:90deg}");
8049    minify_test(".foo { rotate: asin(-1)", ".foo{rotate:-90deg}");
8050    minify_test(".foo { rotate: asin(0.5)", ".foo{rotate:30deg}");
8051    minify_test(".foo { rotate: asin(45deg)", ".foo{rotate:asin(45deg)}"); // invalid
8052    minify_test(".foo { rotate: asin(-20)", ".foo{rotate:asin(-20)}"); // evaluates to NaN
8053    minify_test(".foo { width: asin(sin(45deg))", ".foo{width:asin(sin(45deg))}"); // invalid
8054
8055    minify_test(".foo { rotate: acos(cos(45deg))", ".foo{rotate:45deg}");
8056    minify_test(".foo { rotate: acos(-1)", ".foo{rotate:180deg}");
8057    minify_test(".foo { rotate: acos(0)", ".foo{rotate:90deg}");
8058    minify_test(".foo { rotate: acos(1)", ".foo{rotate:none}");
8059    minify_test(".foo { rotate: acos(45deg)", ".foo{rotate:acos(45deg)}"); // invalid
8060    minify_test(".foo { rotate: acos(-20)", ".foo{rotate:acos(-20)}"); // evaluates to NaN
8061
8062    minify_test(".foo { rotate: atan(tan(45deg))", ".foo{rotate:45deg}");
8063    minify_test(".foo { rotate: atan(1)", ".foo{rotate:45deg}");
8064    minify_test(".foo { rotate: atan(0)", ".foo{rotate:none}");
8065    minify_test(".foo { rotate: atan(45deg)", ".foo{rotate:atan(45deg)}"); // invalid
8066
8067    minify_test(".foo { rotate: atan2(1px, -1px)", ".foo{rotate:135deg}");
8068    minify_test(".foo { rotate: atan2(1vw, -1vw)", ".foo{rotate:135deg}");
8069    minify_test(".foo { rotate: atan2(1, -1)", ".foo{rotate:135deg}");
8070    minify_test(".foo { rotate: atan2(1ms, -1ms)", ".foo{rotate:135deg}");
8071    minify_test(".foo { rotate: atan2(1%, -1%)", ".foo{rotate:135deg}");
8072    minify_test(".foo { rotate: atan2(1deg, -1deg)", ".foo{rotate:135deg}");
8073    minify_test(".foo { rotate: atan2(1cm, 1mm)", ".foo{rotate:84.2894deg}");
8074    minify_test(".foo { rotate: atan2(0, -1)", ".foo{rotate:180deg}");
8075    minify_test(".foo { rotate: atan2(-1, 1)", ".foo{rotate:-45deg}");
8076    // incompatible units
8077    minify_test(".foo { rotate: atan2(1px, -1vw)", ".foo{rotate:atan2(1px,-1vw)}");
8078  }
8079
8080  #[test]
8081  fn test_exp() {
8082    minify_test(".foo { width: hypot()", ".foo{width:hypot()}");
8083    minify_test(".foo { width: hypot(1px)", ".foo{width:1px}");
8084    minify_test(".foo { width: hypot(1px, 2px)", ".foo{width:2.23607px}");
8085    minify_test(".foo { width: hypot(1px, 2px, 3px)", ".foo{width:3.74166px}");
8086    minify_test(".foo { width: hypot(1px, 2vw)", ".foo{width:hypot(1px,2vw)}");
8087    minify_test(".foo { width: hypot(1px, 2px, 3vw)", ".foo{width:hypot(1px,2px,3vw)}");
8088    minify_test(".foo { width: calc(100px * hypot(3, 4))", ".foo{width:500px}");
8089    minify_test(".foo { width: calc(1px * pow(2, sqrt(100))", ".foo{width:1024px}");
8090    minify_test(".foo { width: calc(100px * pow(2, pow(2, 2)", ".foo{width:1600px}");
8091    minify_test(".foo { width: calc(1px * log(1))", ".foo{width:0}");
8092    minify_test(".foo { width: calc(1px * log(10, 10))", ".foo{width:1px}");
8093    minify_test(".foo { width: calc(1px * exp(0))", ".foo{width:1px}");
8094    minify_test(".foo { width: calc(1px * log(e))", ".foo{width:1px}");
8095    minify_test(".foo { width: calc(1px * (e - exp(1)))", ".foo{width:0}");
8096    minify_test(
8097      ".foo { width: calc(1px * (exp(log(1) + exp(0)*2))",
8098      ".foo{width:7.38906px}",
8099    );
8100  }
8101
8102  #[test]
8103  fn test_sign() {
8104    minify_test(".foo { width: abs(1px)", ".foo{width:1px}");
8105    minify_test(".foo { width: abs(-1px)", ".foo{width:1px}");
8106    minify_test(".foo { width: abs(1%)", ".foo{width:abs(1%)}"); // spec says percentages must be against resolved value
8107
8108    minify_test(".foo { width: calc(10px * sign(-1vw)", ".foo{width:-10px}");
8109    minify_test(".foo { width: calc(10px * sign(1%)", ".foo{width:calc(10px*sign(1%))}");
8110  }
8111
8112  #[test]
8113  fn test_box_shadow() {
8114    minify_test(
8115      ".foo { box-shadow: 64px 64px 12px 40px rgba(0,0,0,0.4) }",
8116      ".foo{box-shadow:64px 64px 12px 40px #0006}",
8117    );
8118    minify_test(
8119      ".foo { box-shadow: 12px 12px 0px 8px rgba(0,0,0,0.4) inset }",
8120      ".foo{box-shadow:inset 12px 12px 0 8px #0006}",
8121    );
8122    minify_test(
8123      ".foo { box-shadow: inset 12px 12px 0px 8px rgba(0,0,0,0.4) }",
8124      ".foo{box-shadow:inset 12px 12px 0 8px #0006}",
8125    );
8126    minify_test(
8127      ".foo { box-shadow: 12px 12px 8px 0px rgba(0,0,0,0.4) }",
8128      ".foo{box-shadow:12px 12px 8px #0006}",
8129    );
8130    minify_test(
8131      ".foo { box-shadow: 12px 12px 0px 0px rgba(0,0,0,0.4) }",
8132      ".foo{box-shadow:12px 12px #0006}",
8133    );
8134    minify_test(
8135      ".foo { box-shadow: 64px 64px 12px 40px rgba(0,0,0,0.4), 12px 12px 0px 8px rgba(0,0,0,0.4) inset }",
8136      ".foo{box-shadow:64px 64px 12px 40px #0006,inset 12px 12px 0 8px #0006}",
8137    );
8138
8139    prefix_test(
8140      ".foo { box-shadow: 12px 12px lab(40% 56.6 39) }",
8141      indoc! { r#"
8142        .foo {
8143          box-shadow: 12px 12px #b32323;
8144          box-shadow: 12px 12px lab(40% 56.6 39);
8145        }
8146      "#},
8147      Browsers {
8148        chrome: Some(90 << 16),
8149        ..Browsers::default()
8150      },
8151    );
8152
8153    prefix_test(
8154      ".foo { box-shadow: 12px 12px lab(40% 56.6 39) }",
8155      indoc! { r#"
8156        .foo {
8157          -webkit-box-shadow: 12px 12px #b32323;
8158          box-shadow: 12px 12px #b32323;
8159          box-shadow: 12px 12px lab(40% 56.6 39);
8160        }
8161      "#},
8162      Browsers {
8163        chrome: Some(4 << 16),
8164        ..Browsers::default()
8165      },
8166    );
8167
8168    prefix_test(
8169      ".foo { box-shadow: 12px 12px lab(40% 56.6 39), 12px 12px yellow }",
8170      indoc! { r#"
8171        .foo {
8172          -webkit-box-shadow: 12px 12px #b32323, 12px 12px #ff0;
8173          box-shadow: 12px 12px #b32323, 12px 12px #ff0;
8174          box-shadow: 12px 12px lab(40% 56.6 39), 12px 12px #ff0;
8175        }
8176      "#},
8177      Browsers {
8178        chrome: Some(4 << 16),
8179        ..Browsers::default()
8180      },
8181    );
8182
8183    prefix_test(
8184      ".foo { -webkit-box-shadow: 12px 12px #0006 }",
8185      indoc! { r#"
8186        .foo {
8187          -webkit-box-shadow: 12px 12px rgba(0, 0, 0, .4);
8188        }
8189      "#},
8190      Browsers {
8191        chrome: Some(4 << 16),
8192        ..Browsers::default()
8193      },
8194    );
8195
8196    prefix_test(
8197      ".foo {
8198        -webkit-box-shadow: 12px 12px #0006;
8199        -moz-box-shadow: 12px 12px #0009;
8200      }",
8201      indoc! { r#"
8202        .foo {
8203          -webkit-box-shadow: 12px 12px rgba(0, 0, 0, .4);
8204          -moz-box-shadow: 12px 12px rgba(0, 0, 0, .6);
8205        }
8206      "#},
8207      Browsers {
8208        chrome: Some(4 << 16),
8209        ..Browsers::default()
8210      },
8211    );
8212
8213    prefix_test(
8214      ".foo {
8215        -webkit-box-shadow: 12px 12px #0006;
8216        -moz-box-shadow: 12px 12px #0006;
8217        box-shadow: 12px 12px #0006;
8218      }",
8219      indoc! { r#"
8220        .foo {
8221          box-shadow: 12px 12px #0006;
8222        }
8223      "#},
8224      Browsers {
8225        chrome: Some(95 << 16),
8226        ..Browsers::default()
8227      },
8228    );
8229
8230    prefix_test(
8231      ".foo { box-shadow: var(--foo) 12px lab(40% 56.6 39) }",
8232      indoc! { r#"
8233        .foo {
8234          box-shadow: var(--foo) 12px #b32323;
8235        }
8236
8237        @supports (color: lab(0% 0 0)) {
8238          .foo {
8239            box-shadow: var(--foo) 12px lab(40% 56.6 39);
8240          }
8241        }
8242      "#},
8243      Browsers {
8244        chrome: Some(90 << 16),
8245        ..Browsers::default()
8246      },
8247    );
8248
8249    prefix_test(
8250      r#"
8251      .foo {
8252        box-shadow: 0px 0px 22px red;
8253        box-shadow: 0px 0px max(2cqw, 22px) red;
8254      }
8255    "#,
8256      indoc! {r#"
8257      .foo {
8258        box-shadow: 0 0 22px red;
8259        box-shadow: 0 0 max(2cqw, 22px) red;
8260      }
8261    "#
8262      },
8263      Browsers {
8264        safari: Some(14 << 16),
8265        ..Browsers::default()
8266      },
8267    );
8268    prefix_test(
8269      r#"
8270      .foo {
8271        box-shadow: 0px 0px 22px red;
8272        box-shadow: 0px 0px max(2cqw, 22px) red;
8273      }
8274    "#,
8275      indoc! {r#"
8276      .foo {
8277        box-shadow: 0 0 max(2cqw, 22px) red;
8278      }
8279    "#
8280      },
8281      Browsers {
8282        safari: Some(16 << 16),
8283        ..Browsers::default()
8284      },
8285    );
8286
8287    prefix_test(
8288      r#"
8289      .foo {
8290        box-shadow: 0px 0px 22px red;
8291        box-shadow: 0px 0px 22px lab(40% 56.6 39);
8292      }
8293    "#,
8294      indoc! {r#"
8295      .foo {
8296        box-shadow: 0 0 22px red;
8297        box-shadow: 0 0 22px lab(40% 56.6 39);
8298      }
8299    "#
8300      },
8301      Browsers {
8302        safari: Some(14 << 16),
8303        ..Browsers::default()
8304      },
8305    );
8306    prefix_test(
8307      r#"
8308      .foo {
8309        box-shadow: 0px 0px 22px red;
8310        box-shadow: 0px 0px 22px lab(40% 56.6 39);
8311      }
8312    "#,
8313      indoc! {r#"
8314      .foo {
8315        box-shadow: 0 0 22px lab(40% 56.6 39);
8316      }
8317    "#
8318      },
8319      Browsers {
8320        safari: Some(16 << 16),
8321        ..Browsers::default()
8322      },
8323    );
8324
8325    prefix_test(
8326      r#"
8327      .foo {
8328        box-shadow: var(--fallback);
8329        box-shadow: 0px 0px 22px lab(40% 56.6 39);
8330      }
8331    "#,
8332      indoc! {r#"
8333      .foo {
8334        box-shadow: var(--fallback);
8335        box-shadow: 0 0 22px lab(40% 56.6 39);
8336      }
8337    "#
8338      },
8339      Browsers {
8340        safari: Some(16 << 16),
8341        ..Browsers::default()
8342      },
8343    );
8344  }
8345
8346  #[test]
8347  fn test_media() {
8348    minify_test(
8349      "@media (min-width: 240px) { .foo { color: chartreuse }}",
8350      "@media (width>=240px){.foo{color:#7fff00}}",
8351    );
8352    minify_test(
8353      "@media (width < 240px) { .foo { color: chartreuse }}",
8354      "@media (width<240px){.foo{color:#7fff00}}",
8355    );
8356    minify_test(
8357      "@media (width <= 240px) { .foo { color: chartreuse }}",
8358      "@media (width<=240px){.foo{color:#7fff00}}",
8359    );
8360    minify_test(
8361      "@media (width > 240px) { .foo { color: chartreuse }}",
8362      "@media (width>240px){.foo{color:#7fff00}}",
8363    );
8364    minify_test(
8365      "@media (width >= 240px) { .foo { color: chartreuse }}",
8366      "@media (width>=240px){.foo{color:#7fff00}}",
8367    );
8368    minify_test(
8369      "@media (240px < width) { .foo { color: chartreuse }}",
8370      "@media (width>240px){.foo{color:#7fff00}}",
8371    );
8372    minify_test(
8373      "@media (240px <= width) { .foo { color: chartreuse }}",
8374      "@media (width>=240px){.foo{color:#7fff00}}",
8375    );
8376    minify_test(
8377      "@media (240px > width) { .foo { color: chartreuse }}",
8378      "@media (width<240px){.foo{color:#7fff00}}",
8379    );
8380    minify_test(
8381      "@media (240px >= width) { .foo { color: chartreuse }}",
8382      "@media (width<=240px){.foo{color:#7fff00}}",
8383    );
8384    minify_test(
8385      "@media (100px < width < 200px) { .foo { color: chartreuse }}",
8386      "@media (100px<width<200px){.foo{color:#7fff00}}",
8387    );
8388    minify_test(
8389      "@media (100px <= width <= 200px) { .foo { color: chartreuse }}",
8390      "@media (100px<=width<=200px){.foo{color:#7fff00}}",
8391    );
8392    minify_test(
8393      "@media (min-width: 30em) and (max-width: 50em) { .foo { color: chartreuse }}",
8394      "@media (width>=30em) and (width<=50em){.foo{color:#7fff00}}",
8395    );
8396    minify_test(
8397      "@media screen, print { .foo { color: chartreuse }}",
8398      "@media screen,print{.foo{color:#7fff00}}",
8399    );
8400    minify_test(
8401      "@media (hover: hover) { .foo { color: chartreuse }}",
8402      "@media (hover:hover){.foo{color:#7fff00}}",
8403    );
8404    minify_test(
8405      "@media (hover) { .foo { color: chartreuse }}",
8406      "@media (hover){.foo{color:#7fff00}}",
8407    );
8408    minify_test(
8409      "@media (aspect-ratio: 11/5) { .foo { color: chartreuse }}",
8410      "@media (aspect-ratio:11/5){.foo{color:#7fff00}}",
8411    );
8412    minify_test(
8413      "@media (aspect-ratio: 2/1) { .foo { color: chartreuse }}",
8414      "@media (aspect-ratio:2){.foo{color:#7fff00}}",
8415    );
8416    minify_test(
8417      "@media (aspect-ratio: 2) { .foo { color: chartreuse }}",
8418      "@media (aspect-ratio:2){.foo{color:#7fff00}}",
8419    );
8420    minify_test(
8421      "@media not screen and (color) { .foo { color: chartreuse }}",
8422      "@media not screen and (color){.foo{color:#7fff00}}",
8423    );
8424    minify_test(
8425      "@media only screen and (color) { .foo { color: chartreuse }}",
8426      "@media only screen and (color){.foo{color:#7fff00}}",
8427    );
8428    minify_test(
8429      "@media (update: slow) or (hover: none) { .foo { color: chartreuse }}",
8430      "@media (update:slow) or (hover:none){.foo{color:#7fff00}}",
8431    );
8432    minify_test(
8433      "@media (width < 600px) and (height < 600px) { .foo { color: chartreuse }}",
8434      "@media (width<600px) and (height<600px){.foo{color:#7fff00}}",
8435    );
8436    minify_test(
8437      "@media (not (color)) or (hover) { .foo { color: chartreuse }}",
8438      "@media (not (color)) or (hover){.foo{color:#7fff00}}",
8439    );
8440    error_test(
8441      "@media (example, all,), speech { .foo { color: chartreuse }}",
8442      ParserError::UnexpectedToken(Token::Comma),
8443    );
8444    error_test(
8445      "@media &test, speech { .foo { color: chartreuse }}",
8446      ParserError::UnexpectedToken(Token::Delim('&')),
8447    );
8448    error_test(
8449      "@media &test { .foo { color: chartreuse }}",
8450      ParserError::UnexpectedToken(Token::Delim('&')),
8451    );
8452    minify_test(
8453      "@media (min-width: calc(200px + 40px)) { .foo { color: chartreuse }}",
8454      "@media (width>=240px){.foo{color:#7fff00}}",
8455    );
8456    minify_test(
8457      "@media (min-width: calc(1em + 5px)) { .foo { color: chartreuse }}",
8458      "@media (width>=calc(1em + 5px)){.foo{color:#7fff00}}",
8459    );
8460    minify_test("@media { .foo { color: chartreuse }}", ".foo{color:#7fff00}");
8461    minify_test("@media all { .foo { color: chartreuse }}", ".foo{color:#7fff00}");
8462    minify_test(
8463      "@media not (((color) or (hover))) { .foo { color: chartreuse }}",
8464      "@media not ((color) or (hover)){.foo{color:#7fff00}}",
8465    );
8466    minify_test(
8467      "@media (hover) and ((color) and (test)) { .foo { color: chartreuse }}",
8468      "@media (hover) and (color) and (test){.foo{color:#7fff00}}",
8469    );
8470    minify_test(
8471      "@media (grid: 1) { .foo { color: chartreuse }}",
8472      "@media (grid:1){.foo{color:#7fff00}}",
8473    );
8474    minify_test(
8475      "@media (width >= calc(2px + 4px)) { .foo { color: chartreuse }}",
8476      "@media (width>=6px){.foo{color:#7fff00}}",
8477    );
8478
8479    prefix_test(
8480      r#"
8481        @media (width >= 240px) {
8482          .foo {
8483            color: chartreuse;
8484          }
8485        }
8486      "#,
8487      indoc! { r#"
8488        @media (min-width: 240px) {
8489          .foo {
8490            color: #7fff00;
8491          }
8492        }
8493      "#},
8494      Browsers {
8495        firefox: Some(60 << 16),
8496        ..Browsers::default()
8497      },
8498    );
8499
8500    prefix_test(
8501      r#"
8502        @media (width >= 240px) {
8503          .foo {
8504            color: chartreuse;
8505          }
8506        }
8507      "#,
8508      indoc! { r#"
8509        @media (width >= 240px) {
8510          .foo {
8511            color: #7fff00;
8512          }
8513        }
8514      "#},
8515      Browsers {
8516        firefox: Some(64 << 16),
8517        ..Browsers::default()
8518      },
8519    );
8520
8521    prefix_test(
8522      r#"
8523        @media (color > 2) {
8524          .foo {
8525            color: chartreuse;
8526          }
8527        }
8528      "#,
8529      indoc! { r#"
8530        @media not (max-color: 2) {
8531          .foo {
8532            color: #7fff00;
8533          }
8534        }
8535      "#},
8536      Browsers {
8537        firefox: Some(60 << 16),
8538        ..Browsers::default()
8539      },
8540    );
8541
8542    prefix_test(
8543      r#"
8544        @media (color < 2) {
8545          .foo {
8546            color: chartreuse;
8547          }
8548        }
8549      "#,
8550      indoc! { r#"
8551        @media not (min-color: 2) {
8552          .foo {
8553            color: #7fff00;
8554          }
8555        }
8556      "#},
8557      Browsers {
8558        firefox: Some(60 << 16),
8559        ..Browsers::default()
8560      },
8561    );
8562
8563    prefix_test(
8564      r#"
8565        @media (width > 240px) {
8566          .foo {
8567            color: chartreuse;
8568          }
8569        }
8570      "#,
8571      indoc! { r#"
8572        @media not (max-width: 240px) {
8573          .foo {
8574            color: #7fff00;
8575          }
8576        }
8577      "#},
8578      Browsers {
8579        firefox: Some(60 << 16),
8580        ..Browsers::default()
8581      },
8582    );
8583
8584    prefix_test(
8585      r#"
8586        @media (width <= 240px) {
8587          .foo {
8588            color: chartreuse;
8589          }
8590        }
8591      "#,
8592      indoc! { r#"
8593        @media (max-width: 240px) {
8594          .foo {
8595            color: #7fff00;
8596          }
8597        }
8598      "#},
8599      Browsers {
8600        firefox: Some(60 << 16),
8601        ..Browsers::default()
8602      },
8603    );
8604
8605    prefix_test(
8606      r#"
8607        @media (width <= 240px) {
8608          .foo {
8609            color: chartreuse;
8610          }
8611        }
8612      "#,
8613      indoc! { r#"
8614        @media (width <= 240px) {
8615          .foo {
8616            color: #7fff00;
8617          }
8618        }
8619      "#},
8620      Browsers {
8621        firefox: Some(64 << 16),
8622        ..Browsers::default()
8623      },
8624    );
8625
8626    prefix_test(
8627      r#"
8628        @media (width < 240px) {
8629          .foo {
8630            color: chartreuse;
8631          }
8632        }
8633      "#,
8634      indoc! { r#"
8635        @media not (min-width: 240px) {
8636          .foo {
8637            color: #7fff00;
8638          }
8639        }
8640      "#},
8641      Browsers {
8642        firefox: Some(60 << 16),
8643        ..Browsers::default()
8644      },
8645    );
8646
8647    prefix_test(
8648      r#"
8649        @media not (width < 240px) {
8650          .foo {
8651            color: chartreuse;
8652          }
8653        }
8654      "#,
8655      indoc! { r#"
8656        @media (min-width: 240px) {
8657          .foo {
8658            color: #7fff00;
8659          }
8660        }
8661      "#},
8662      Browsers {
8663        firefox: Some(60 << 16),
8664        ..Browsers::default()
8665      },
8666    );
8667
8668    test(
8669      r#"
8670        @media not (width < 240px) {
8671          .foo {
8672            color: chartreuse;
8673          }
8674        }
8675      "#,
8676      indoc! { r#"
8677        @media (width >= 240px) {
8678          .foo {
8679            color: #7fff00;
8680          }
8681        }
8682      "#},
8683    );
8684
8685    prefix_test(
8686      r#"
8687        @media (width < 240px) and (hover) {
8688          .foo {
8689            color: chartreuse;
8690          }
8691        }
8692      "#,
8693      indoc! { r#"
8694        @media (not (min-width: 240px)) and (hover) {
8695          .foo {
8696            color: #7fff00;
8697          }
8698        }
8699      "#},
8700      Browsers {
8701        firefox: Some(60 << 16),
8702        ..Browsers::default()
8703      },
8704    );
8705
8706    prefix_test(
8707      r#"
8708        @media (100px <= width <= 200px) {
8709          .foo {
8710            color: chartreuse;
8711          }
8712        }
8713      "#,
8714      indoc! { r#"
8715        @media (min-width: 100px) and (max-width: 200px) {
8716          .foo {
8717            color: #7fff00;
8718          }
8719        }
8720      "#},
8721      Browsers {
8722        firefox: Some(85 << 16),
8723        ..Browsers::default()
8724      },
8725    );
8726
8727    prefix_test(
8728      r#"
8729        @media not (100px <= width <= 200px) {
8730          .foo {
8731            color: chartreuse;
8732          }
8733        }
8734      "#,
8735      indoc! { r#"
8736        @media not ((min-width: 100px) and (max-width: 200px)) {
8737          .foo {
8738            color: #7fff00;
8739          }
8740        }
8741      "#},
8742      Browsers {
8743        firefox: Some(85 << 16),
8744        ..Browsers::default()
8745      },
8746    );
8747
8748    prefix_test(
8749      r#"
8750        @media (hover) and (100px <= width <= 200px) {
8751          .foo {
8752            color: chartreuse;
8753          }
8754        }
8755      "#,
8756      indoc! { r#"
8757        @media (hover) and (min-width: 100px) and (max-width: 200px) {
8758          .foo {
8759            color: #7fff00;
8760          }
8761        }
8762      "#},
8763      Browsers {
8764        firefox: Some(85 << 16),
8765        ..Browsers::default()
8766      },
8767    );
8768
8769    prefix_test(
8770      r#"
8771        @media (hover) or (100px <= width <= 200px) {
8772          .foo {
8773            color: chartreuse;
8774          }
8775        }
8776      "#,
8777      indoc! { r#"
8778        @media (hover) or ((min-width: 100px) and (max-width: 200px)) {
8779          .foo {
8780            color: #7fff00;
8781          }
8782        }
8783      "#},
8784      Browsers {
8785        firefox: Some(85 << 16),
8786        ..Browsers::default()
8787      },
8788    );
8789
8790    prefix_test(
8791      r#"
8792        @media (100px < width < 200px) {
8793          .foo {
8794            color: chartreuse;
8795          }
8796        }
8797      "#,
8798      indoc! { r#"
8799        @media (not (max-width: 100px)) and (not (min-width: 200px)) {
8800          .foo {
8801            color: #7fff00;
8802          }
8803        }
8804      "#},
8805      Browsers {
8806        firefox: Some(85 << 16),
8807        ..Browsers::default()
8808      },
8809    );
8810
8811    prefix_test(
8812      r#"
8813        @media not (100px < width < 200px) {
8814          .foo {
8815            color: chartreuse;
8816          }
8817        }
8818      "#,
8819      indoc! { r#"
8820        @media not ((not (max-width: 100px)) and (not (min-width: 200px))) {
8821          .foo {
8822            color: #7fff00;
8823          }
8824        }
8825      "#},
8826      Browsers {
8827        firefox: Some(85 << 16),
8828        ..Browsers::default()
8829      },
8830    );
8831
8832    prefix_test(
8833      r#"
8834        @media (200px >= width >= 100px) {
8835          .foo {
8836            color: chartreuse;
8837          }
8838        }
8839      "#,
8840      indoc! { r#"
8841        @media (max-width: 200px) and (min-width: 100px) {
8842          .foo {
8843            color: #7fff00;
8844          }
8845        }
8846      "#},
8847      Browsers {
8848        firefox: Some(85 << 16),
8849        ..Browsers::default()
8850      },
8851    );
8852
8853    test(
8854      r#"
8855      @media not all {
8856        .a {
8857          color: green;
8858        }
8859      }
8860      "#,
8861      "\n",
8862    );
8863
8864    prefix_test(
8865      r#"
8866      @media (width > calc(1px + 1rem)) {
8867        .foo { color: yellow; }
8868      }
8869      "#,
8870      indoc! { r#"
8871        @media not (max-width: calc(1px + 1rem)) {
8872          .foo {
8873            color: #ff0;
8874          }
8875        }
8876      "#},
8877      Browsers {
8878        chrome: Some(85 << 16),
8879        ..Browsers::default()
8880      },
8881    );
8882    prefix_test(
8883      r#"
8884      @media (width > max(10px, 1rem)) {
8885        .foo { color: yellow; }
8886      }
8887      "#,
8888      indoc! { r#"
8889        @media not (max-width: max(10px, 1rem)) {
8890          .foo {
8891            color: #ff0;
8892          }
8893        }
8894      "#},
8895      Browsers {
8896        chrome: Some(85 << 16),
8897        ..Browsers::default()
8898      },
8899    );
8900    prefix_test(
8901      r#"
8902      @media (width > 0) {
8903        .foo { color: yellow; }
8904      }
8905      "#,
8906      indoc! { r#"
8907        @media not (max-width: 0) {
8908          .foo {
8909            color: #ff0;
8910          }
8911        }
8912      "#},
8913      Browsers {
8914        chrome: Some(85 << 16),
8915        ..Browsers::default()
8916      },
8917    );
8918    prefix_test(
8919      r#"
8920      @media (min-resolution: 2dppx) {
8921        .foo { color: yellow; }
8922      }
8923      "#,
8924      indoc! { r#"
8925        @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 2dppx) {
8926          .foo {
8927            color: #ff0;
8928          }
8929        }
8930      "#},
8931      Browsers {
8932        safari: Some(15 << 16),
8933        ..Browsers::default()
8934      },
8935    );
8936    prefix_test(
8937      r#"
8938      @media (min-resolution: 2dppx) {
8939        .foo { color: yellow; }
8940      }
8941      "#,
8942      indoc! { r#"
8943        @media (min--moz-device-pixel-ratio: 2), (min-resolution: 2dppx) {
8944          .foo {
8945            color: #ff0;
8946          }
8947        }
8948      "#},
8949      Browsers {
8950        firefox: Some(10 << 16),
8951        ..Browsers::default()
8952      },
8953    );
8954    prefix_test(
8955      r#"
8956      @media (resolution > 2dppx) {
8957        .foo { color: yellow; }
8958      }
8959      "#,
8960      indoc! { r#"
8961        @media not (-webkit-max-device-pixel-ratio: 2), not (max-resolution: 2dppx) {
8962          .foo {
8963            color: #ff0;
8964          }
8965        }
8966      "#},
8967      Browsers {
8968        safari: Some(15 << 16),
8969        ..Browsers::default()
8970      },
8971    );
8972    prefix_test(
8973      r#"
8974      @media (resolution >= 300dpi) {
8975        .foo { color: yellow; }
8976      }
8977      "#,
8978      indoc! { r#"
8979        @media (-webkit-min-device-pixel-ratio: 3.125), (min-resolution: 300dpi) {
8980          .foo {
8981            color: #ff0;
8982          }
8983        }
8984      "#},
8985      Browsers {
8986        safari: Some(15 << 16),
8987        ..Browsers::default()
8988      },
8989    );
8990    prefix_test(
8991      r#"
8992      @media (min-resolution: 113.38dpcm) {
8993        .foo { color: yellow; }
8994      }
8995      "#,
8996      indoc! { r#"
8997        @media (-webkit-min-device-pixel-ratio: 2.99985), (min--moz-device-pixel-ratio: 2.99985), (min-resolution: 113.38dpcm) {
8998          .foo {
8999            color: #ff0;
9000          }
9001        }
9002      "#},
9003      Browsers {
9004        safari: Some(15 << 16),
9005        firefox: Some(10 << 16),
9006        ..Browsers::default()
9007      },
9008    );
9009    prefix_test(
9010      r#"
9011      @media (color) and (min-resolution: 2dppx) {
9012        .foo { color: yellow; }
9013      }
9014      "#,
9015      indoc! { r#"
9016        @media (color) and (-webkit-min-device-pixel-ratio: 2), (color) and (min-resolution: 2dppx) {
9017          .foo {
9018            color: #ff0;
9019          }
9020        }
9021      "#},
9022      Browsers {
9023        safari: Some(15 << 16),
9024        ..Browsers::default()
9025      },
9026    );
9027    prefix_test(
9028      r#"
9029      @media (min-resolution: 2dppx),
9030             (min-resolution: 192dpi) {
9031        .foo { color: yellow; }
9032      }
9033      "#,
9034      indoc! { r#"
9035        @media (-webkit-min-device-pixel-ratio: 2), (min--moz-device-pixel-ratio: 2), (min-resolution: 2dppx), (min-resolution: 192dpi) {
9036          .foo {
9037            color: #ff0;
9038          }
9039        }
9040      "#},
9041      Browsers {
9042        safari: Some(15 << 16),
9043        firefox: Some(10 << 16),
9044        ..Browsers::default()
9045      },
9046    );
9047    prefix_test(
9048      r#"
9049      @media only screen and (min-resolution: 124.8dpi) {
9050        .foo { color: yellow; }
9051      }
9052      "#,
9053      indoc! { r#"
9054        @media only screen and (-webkit-min-device-pixel-ratio: 1.3), only screen and (min--moz-device-pixel-ratio: 1.3), only screen and (min-resolution: 124.8dpi) {
9055          .foo {
9056            color: #ff0;
9057          }
9058        }
9059      "#},
9060      Browsers {
9061        safari: Some(15 << 16),
9062        firefox: Some(10 << 16),
9063        ..Browsers::default()
9064      },
9065    );
9066
9067    error_test(
9068      "@media (min-width: hi) { .foo { color: chartreuse }}",
9069      ParserError::InvalidMediaQuery,
9070    );
9071    error_test(
9072      "@media (width >= hi) { .foo { color: chartreuse }}",
9073      ParserError::InvalidMediaQuery,
9074    );
9075    error_test(
9076      "@media (width >= 2/1) { .foo { color: chartreuse }}",
9077      ParserError::UnexpectedToken(Token::Delim('/')),
9078    );
9079    error_test(
9080      "@media (600px <= min-height) { .foo { color: chartreuse }}",
9081      ParserError::InvalidMediaQuery,
9082    );
9083    error_test(
9084      "@media (scan >= 1) { .foo { color: chartreuse }}",
9085      ParserError::InvalidMediaQuery,
9086    );
9087    error_test(
9088      "@media (min-scan: interlace) { .foo { color: chartreuse }}",
9089      ParserError::InvalidMediaQuery,
9090    );
9091    error_test(
9092      "@media (1px <= width <= bar) { .foo { color: chartreuse }}",
9093      ParserError::InvalidMediaQuery,
9094    );
9095    error_test(
9096      "@media (1px <= min-width <= 2px) { .foo { color: chartreuse }}",
9097      ParserError::InvalidMediaQuery,
9098    );
9099    error_test(
9100      "@media (1px <= scan <= 2px) { .foo { color: chartreuse }}",
9101      ParserError::InvalidMediaQuery,
9102    );
9103    error_test(
9104      "@media (grid: 10) { .foo { color: chartreuse }}",
9105      ParserError::InvalidMediaQuery,
9106    );
9107    error_test(
9108      "@media (prefers-color-scheme = dark) { .foo { color: chartreuse }}",
9109      ParserError::InvalidMediaQuery,
9110    );
9111  }
9112
9113  #[test]
9114  fn test_merge_layers() {
9115    test(
9116      r#"
9117      @layer foo {
9118        .foo {
9119          color: red;
9120        }
9121      }
9122      @layer foo {
9123        .foo {
9124          background: #fff;
9125        }
9126
9127        .baz {
9128          color: #fff;
9129        }
9130      }
9131      "#,
9132      indoc! {r#"
9133      @layer foo {
9134        .foo {
9135          color: red;
9136          background: #fff;
9137        }
9138
9139        .baz {
9140          color: #fff;
9141        }
9142      }
9143    "#},
9144    );
9145    test(
9146      r#"
9147      @layer a {}
9148      @layer b {}
9149
9150      @layer b {
9151        foo {
9152          color: red;
9153        }
9154      }
9155
9156      @layer a {
9157        bar {
9158          color: yellow;
9159        }
9160      }
9161      "#,
9162      indoc! {r#"
9163      @layer a {
9164        bar {
9165          color: #ff0;
9166        }
9167      }
9168
9169      @layer b {
9170        foo {
9171          color: red;
9172        }
9173      }
9174    "#},
9175    );
9176
9177    test(
9178      r#"
9179      @layer a {}
9180      @layer b {}
9181
9182      @layer b {
9183        foo {
9184          color: red;
9185        }
9186      }
9187      "#,
9188      indoc! {r#"
9189      @layer a;
9190
9191      @layer b {
9192        foo {
9193          color: red;
9194        }
9195      }
9196    "#},
9197    );
9198
9199    test(
9200      r#"
9201      @layer a;
9202      @layer b;
9203      @layer c;
9204      "#,
9205      indoc! {r#"
9206      @layer a, b, c;
9207    "#},
9208    );
9209
9210    test(
9211      r#"
9212      @layer a {}
9213      @layer b {}
9214      @layer c {}
9215      "#,
9216      indoc! {r#"
9217      @layer a, b, c;
9218    "#},
9219    );
9220
9221    test(
9222      r#"
9223      @layer a;
9224      @layer b {
9225        .foo {
9226          color: red;
9227        }
9228      }
9229      @layer c {}
9230      "#,
9231      indoc! {r#"
9232      @layer a;
9233
9234      @layer b {
9235        .foo {
9236          color: red;
9237        }
9238      }
9239
9240      @layer c;
9241    "#},
9242    );
9243
9244    test(
9245      r#"
9246      @layer a, b;
9247      @layer c {}
9248
9249      @layer d {
9250        foo {
9251          color: red;
9252        }
9253      }
9254      "#,
9255      indoc! {r#"
9256      @layer a, b, c;
9257
9258      @layer d {
9259        foo {
9260          color: red;
9261        }
9262      }
9263    "#},
9264    );
9265
9266    test(
9267      r#"
9268      @layer a;
9269      @layer b;
9270      @import "a.css" layer(x);
9271      @layer c;
9272
9273      @layer d {
9274        foo {
9275          color: red;
9276        }
9277      }
9278      "#,
9279      indoc! {r#"
9280      @layer a, b;
9281      @import "a.css" layer(x);
9282      @layer c;
9283
9284      @layer d {
9285        foo {
9286          color: red;
9287        }
9288      }
9289    "#},
9290    );
9291
9292    test(
9293      r#"
9294      @layer a, b, c;
9295
9296      @layer a {
9297        foo {
9298          color: red;
9299        }
9300      }
9301      "#,
9302      indoc! {r#"
9303      @layer a {
9304        foo {
9305          color: red;
9306        }
9307      }
9308
9309      @layer b, c;
9310    "#},
9311    );
9312
9313    test(
9314      r#"
9315      @layer a;
9316      @import "foo.css";
9317
9318      @layer a {
9319        foo {
9320          color: red;
9321        }
9322      }
9323      "#,
9324      indoc! {r#"
9325      @layer a;
9326      @import "foo.css";
9327
9328      @layer a {
9329        foo {
9330          color: red;
9331        }
9332      }
9333    "#},
9334    );
9335  }
9336
9337  #[test]
9338  fn test_merge_rules() {
9339    test(
9340      r#"
9341      .foo {
9342        color: red;
9343      }
9344      .bar {
9345        color: red;
9346      }
9347    "#,
9348      indoc! {r#"
9349      .foo, .bar {
9350        color: red;
9351      }
9352    "#},
9353    );
9354    test(
9355      r#"
9356      .foo {
9357        color: red;
9358      }
9359      .foo {
9360        background: green;
9361      }
9362    "#,
9363      indoc! {r#"
9364      .foo {
9365        color: red;
9366        background: green;
9367      }
9368    "#},
9369    );
9370    test(
9371      r#"
9372      .foo {
9373        color: red;
9374      }
9375      .foo {
9376        background: green !important;
9377      }
9378    "#,
9379      indoc! {r#"
9380      .foo {
9381        color: red;
9382        background: green !important;
9383      }
9384    "#},
9385    );
9386    test(
9387      r#"
9388      .foo {
9389        background: red;
9390      }
9391      .foo {
9392        background: green;
9393      }
9394    "#,
9395      indoc! {r#"
9396      .foo {
9397        background: green;
9398      }
9399    "#},
9400    );
9401    test(
9402      r#"
9403      .foo {
9404        --foo: red;
9405        --foo: purple;
9406      }
9407      .foo {
9408        --foo: green;
9409      }
9410    "#,
9411      indoc! {r#"
9412      .foo {
9413        --foo: green;
9414      }
9415    "#},
9416    );
9417    test(
9418      r#"
9419      .foo {
9420        color: red;
9421      }
9422
9423      .bar {
9424        background: green;
9425      }
9426    "#,
9427      indoc! {r#"
9428      .foo {
9429        color: red;
9430      }
9431
9432      .bar {
9433        background: green;
9434      }
9435    "#},
9436    );
9437    test(
9438      r#"
9439      .foo {
9440        color: red;
9441      }
9442
9443      .baz {
9444        color: blue;
9445      }
9446
9447      .bar {
9448        color: red;
9449      }
9450    "#,
9451      indoc! {r#"
9452      .foo {
9453        color: red;
9454      }
9455
9456      .baz {
9457        color: #00f;
9458      }
9459
9460      .bar {
9461        color: red;
9462      }
9463    "#},
9464    );
9465    test(
9466      r#"
9467      .foo {
9468        background: red;
9469      }
9470      .bar {
9471        background: red;
9472      }
9473      .foo {
9474        color: green;
9475      }
9476      .bar {
9477        color: green;
9478      }
9479    "#,
9480      indoc! {r#"
9481      .foo, .bar {
9482        color: green;
9483        background: red;
9484      }
9485    "#},
9486    );
9487    test(
9488      r#"
9489      .foo, .bar {
9490        background: red;
9491      }
9492      .foo {
9493        color: green;
9494      }
9495      .bar {
9496        color: green;
9497      }
9498    "#,
9499      indoc! {r#"
9500      .foo, .bar {
9501        color: green;
9502        background: red;
9503      }
9504    "#},
9505    );
9506    test(
9507      r#"
9508      .foo {
9509        background: red;
9510      }
9511      .foo {
9512        color: green;
9513      }
9514      .bar {
9515        background: red;
9516      }
9517      .bar {
9518        color: green;
9519      }
9520    "#,
9521      indoc! {r#"
9522      .foo, .bar {
9523        color: green;
9524        background: red;
9525      }
9526    "#},
9527    );
9528    test(
9529      r#"
9530      [foo="bar"] {
9531        color: red;
9532      }
9533      .bar {
9534        color: red;
9535      }
9536    "#,
9537      indoc! {r#"
9538      [foo="bar"], .bar {
9539        color: red;
9540      }
9541    "#},
9542    );
9543    test(
9544      r#"
9545      .a {
9546        color: red;
9547      }
9548      .b {
9549        color: green;
9550      }
9551      .a {
9552        color: red;
9553      }
9554    "#,
9555      indoc! {r#"
9556      .b {
9557        color: green;
9558      }
9559
9560      .a {
9561        color: red;
9562      }
9563    "#},
9564    );
9565    test(
9566      r#"
9567      .a {
9568        color: red;
9569      }
9570      .b {
9571        color: green;
9572      }
9573      .a {
9574        color: pink;
9575      }
9576    "#,
9577      indoc! {r#"
9578      .b {
9579        color: green;
9580      }
9581
9582      .a {
9583        color: pink;
9584      }
9585    "#},
9586    );
9587    test(
9588      r#"
9589      .a:foo(#000) {
9590        color: red;
9591      }
9592      .b {
9593        color: green;
9594      }
9595      .a:foo(#ff0) {
9596        color: pink;
9597      }
9598    "#,
9599      indoc! {r#"
9600      .a:foo(#000) {
9601        color: red;
9602      }
9603
9604      .b {
9605        color: green;
9606      }
9607
9608      .a:foo(#ff0) {
9609        color: pink;
9610      }
9611    "#},
9612    );
9613    test(
9614      r#"
9615      .a {
9616        border-radius: 10px;
9617      }
9618      .b {
9619        color: green;
9620      }
9621      .a {
9622        border-radius: 10px;
9623      }
9624    "#,
9625      indoc! {r#"
9626      .b {
9627        color: green;
9628      }
9629
9630      .a {
9631        border-radius: 10px;
9632      }
9633    "#},
9634    );
9635    test(
9636      r#"
9637      .a {
9638        border-radius: 10px;
9639      }
9640      .b {
9641        color: green;
9642      }
9643      .a {
9644        -webkit-border-radius: 10px;
9645      }
9646    "#,
9647      indoc! {r#"
9648      .a {
9649        border-radius: 10px;
9650      }
9651
9652      .b {
9653        color: green;
9654      }
9655
9656      .a {
9657        -webkit-border-radius: 10px;
9658      }
9659    "#},
9660    );
9661    test(
9662      r#"
9663      .a {
9664        border-radius: 10px;
9665      }
9666      .b {
9667        color: green;
9668      }
9669      .a {
9670        border-radius: var(--foo);
9671      }
9672    "#,
9673      indoc! {r#"
9674      .b {
9675        color: green;
9676      }
9677
9678      .a {
9679        border-radius: var(--foo);
9680      }
9681    "#},
9682    );
9683    test(
9684      r#"
9685      .a {
9686        border-radius: 10px;
9687      }
9688      .b {
9689        color: green;
9690      }
9691      .c {
9692        border-radius: 20px;
9693      }
9694    "#,
9695      indoc! {r#"
9696      .a {
9697        border-radius: 10px;
9698      }
9699
9700      .b {
9701        color: green;
9702      }
9703
9704      .c {
9705        border-radius: 20px;
9706      }
9707    "#},
9708    );
9709    test(
9710      r#"
9711      @media print {
9712        .a {
9713          color: red;
9714        }
9715        .b {
9716          color: green;
9717        }
9718        .a {
9719          color: red;
9720        }
9721      }
9722    "#,
9723      indoc! {r#"
9724      @media print {
9725        .b {
9726          color: green;
9727        }
9728
9729        .a {
9730          color: red;
9731        }
9732      }
9733    "#},
9734    );
9735    test(
9736      r#"
9737      .a {
9738        border-radius: 10px;
9739      }
9740      .b {
9741        color: green;
9742      }
9743      .a {
9744        border-radius: 20px;
9745        color: pink;
9746      }
9747    "#,
9748      indoc! {r#"
9749      .a {
9750        border-radius: 10px;
9751      }
9752
9753      .b {
9754        color: green;
9755      }
9756
9757      .a {
9758        color: pink;
9759        border-radius: 20px;
9760      }
9761    "#},
9762    );
9763    test(
9764      r#"
9765      .a {
9766        color: red;
9767      }
9768      .b {
9769        color: green;
9770      }
9771      .a {
9772        color: red;
9773      }
9774      .b {
9775        color: green;
9776      }
9777    "#,
9778      indoc! {r#"
9779      .a {
9780        color: red;
9781      }
9782
9783      .b {
9784        color: green;
9785      }
9786    "#},
9787    );
9788
9789    prefix_test(
9790      r#"
9791      [foo="bar"] {
9792        color: red;
9793      }
9794      .bar {
9795        color: red;
9796      }
9797    "#,
9798      indoc! {r#"
9799      [foo="bar"] {
9800        color: red;
9801      }
9802
9803      .bar {
9804        color: red;
9805      }
9806    "#},
9807      Browsers {
9808        ie: Some(6 << 16),
9809        ..Browsers::default()
9810      },
9811    );
9812
9813    prefix_test(
9814      r#"
9815      [foo="bar"] {
9816        color: red;
9817      }
9818      .bar {
9819        color: red;
9820      }
9821    "#,
9822      indoc! {r#"
9823      [foo="bar"], .bar {
9824        color: red;
9825      }
9826    "#},
9827      Browsers {
9828        ie: Some(10 << 16),
9829        ..Browsers::default()
9830      },
9831    );
9832
9833    test(
9834      r#"
9835      .foo:-moz-read-only {
9836        color: red;
9837      }
9838    "#,
9839      indoc! {r#"
9840      .foo:-moz-read-only {
9841        color: red;
9842      }
9843    "#},
9844    );
9845
9846    test(
9847      r#"
9848      .foo:-moz-read-only {
9849        color: red;
9850      }
9851
9852      .foo:read-only {
9853        color: red;
9854      }
9855    "#,
9856      indoc! {r#"
9857      .foo:-moz-read-only {
9858        color: red;
9859      }
9860
9861      .foo:read-only {
9862        color: red;
9863      }
9864    "#},
9865    );
9866
9867    prefix_test(
9868      r#"
9869      .foo:-moz-read-only {
9870        color: red;
9871      }
9872
9873      .foo:read-only {
9874        color: red;
9875      }
9876    "#,
9877      indoc! {r#"
9878      .foo:read-only {
9879        color: red;
9880      }
9881    "#},
9882      Browsers {
9883        firefox: Some(85 << 16),
9884        ..Browsers::default()
9885      },
9886    );
9887
9888    prefix_test(
9889      r#"
9890      .foo:-moz-read-only {
9891        color: red;
9892      }
9893
9894      .bar {
9895        color: yellow;
9896      }
9897
9898      .foo:read-only {
9899        color: red;
9900      }
9901    "#,
9902      indoc! {r#"
9903      .foo:-moz-read-only {
9904        color: red;
9905      }
9906
9907      .bar {
9908        color: #ff0;
9909      }
9910
9911      .foo:read-only {
9912        color: red;
9913      }
9914    "#},
9915      Browsers {
9916        firefox: Some(85 << 16),
9917        ..Browsers::default()
9918      },
9919    );
9920
9921    prefix_test(
9922      r#"
9923      .foo:-moz-read-only {
9924        color: red;
9925      }
9926
9927      .foo:read-only {
9928        color: red;
9929      }
9930    "#,
9931      indoc! {r#"
9932      .foo:-moz-read-only {
9933        color: red;
9934      }
9935
9936      .foo:read-only {
9937        color: red;
9938      }
9939    "#},
9940      Browsers {
9941        firefox: Some(36 << 16),
9942        ..Browsers::default()
9943      },
9944    );
9945
9946    prefix_test(
9947      r#"
9948      .foo:read-only {
9949        color: red;
9950      }
9951    "#,
9952      indoc! {r#"
9953      .foo:-moz-read-only {
9954        color: red;
9955      }
9956
9957      .foo:read-only {
9958        color: red;
9959      }
9960    "#},
9961      Browsers {
9962        firefox: Some(36 << 16),
9963        ..Browsers::default()
9964      },
9965    );
9966
9967    prefix_test(
9968      r#"
9969      .foo:-webkit-full-screen {
9970        color: red;
9971      }
9972      .foo:-moz-full-screen {
9973        color: red;
9974      }
9975      .foo:-ms-fullscreen {
9976        color: red;
9977      }
9978      .foo:fullscreen {
9979        color: red;
9980      }
9981    "#,
9982      indoc! {r#"
9983      .foo:fullscreen {
9984        color: red;
9985      }
9986    "#},
9987      Browsers {
9988        chrome: Some(96 << 16),
9989        ..Browsers::default()
9990      },
9991    );
9992
9993    prefix_test(
9994      r#"
9995      .foo:fullscreen {
9996        color: red;
9997      }
9998    "#,
9999      indoc! {r#"
10000      .foo:-webkit-full-screen {
10001        color: red;
10002      }
10003
10004      .foo:-moz-full-screen {
10005        color: red;
10006      }
10007
10008      .foo:-ms-fullscreen {
10009        color: red;
10010      }
10011
10012      .foo:fullscreen {
10013        color: red;
10014      }
10015    "#},
10016      Browsers {
10017        chrome: Some(45 << 16),
10018        firefox: Some(45 << 16),
10019        ie: Some(11 << 16),
10020        ..Browsers::default()
10021      },
10022    );
10023
10024    prefix_test(
10025      r#"
10026      .foo::placeholder {
10027        color: red;
10028      }
10029    "#,
10030      indoc! {r#"
10031      .foo::-webkit-input-placeholder {
10032        color: red;
10033      }
10034
10035      .foo::-moz-placeholder {
10036        color: red;
10037      }
10038
10039      .foo::-ms-input-placeholder {
10040        color: red;
10041      }
10042
10043      .foo::placeholder {
10044        color: red;
10045      }
10046    "#},
10047      Browsers {
10048        chrome: Some(45 << 16),
10049        firefox: Some(45 << 16),
10050        ie: Some(11 << 16),
10051        ..Browsers::default()
10052      },
10053    );
10054
10055    prefix_test(
10056      r#"
10057      .foo::file-selector-button {
10058        color: red;
10059      }
10060    "#,
10061      indoc! {r#"
10062      .foo::-webkit-file-upload-button {
10063        color: red;
10064      }
10065
10066      .foo::-ms-browse {
10067        color: red;
10068      }
10069
10070      .foo::file-selector-button {
10071        color: red;
10072      }
10073    "#},
10074      Browsers {
10075        chrome: Some(84 << 16),
10076        ie: Some(10 << 16),
10077        ..Browsers::default()
10078      },
10079    );
10080
10081    prefix_test(
10082      r#"
10083      .foo::file-selector-button {
10084        margin-inline-start: 2px;
10085      }
10086    "#,
10087      indoc! {r#"
10088      .foo:not(:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)))::-webkit-file-upload-button {
10089        margin-left: 2px;
10090      }
10091
10092      .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)))::-ms-browse {
10093        margin-left: 2px;
10094      }
10095
10096      .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)))::file-selector-button {
10097        margin-left: 2px;
10098      }
10099
10100      .foo:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))::-webkit-file-upload-button {
10101        margin-right: 2px;
10102      }
10103
10104      .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))::-ms-browse {
10105        margin-right: 2px;
10106      }
10107
10108      .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))::file-selector-button {
10109        margin-right: 2px;
10110      }
10111    "#},
10112      Browsers {
10113        chrome: Some(84 << 16),
10114        ie: Some(10 << 16),
10115        ..Browsers::default()
10116      },
10117    );
10118
10119    prefix_test(
10120      r#"
10121      .foo:placeholder-shown .bar { color: red; }
10122      .foo:autofill .baz { color: red; }
10123      "#,
10124      indoc! {r#"
10125      .foo:placeholder-shown .bar {
10126        color: red;
10127      }
10128
10129      .foo:-webkit-autofill .baz {
10130        color: red;
10131      }
10132
10133      .foo:autofill .baz {
10134        color: red;
10135      }
10136      "#},
10137      Browsers {
10138        chrome: Some(103 << 16),
10139        ..Browsers::default()
10140      },
10141    );
10142
10143    prefix_test(
10144      r#"
10145      .foo:placeholder-shown .bar,.foo:autofill .baz{color:red}
10146      "#,
10147      indoc! {r#"
10148      :-webkit-any(.foo:placeholder-shown .bar, .foo:-webkit-autofill .baz) {
10149        color: red;
10150      }
10151
10152      :is(.foo:placeholder-shown .bar, .foo:autofill .baz) {
10153        color: red;
10154      }
10155      "#},
10156      Browsers {
10157        chrome: Some(103 << 16),
10158        ..Browsers::default()
10159      },
10160    );
10161
10162    prefix_test(
10163      r#"
10164      .foo:placeholder-shown .bar, .foo:-webkit-autofill .baz {
10165        color: red;
10166      }
10167
10168      .foo:placeholder-shown .bar, .foo:autofill .baz {
10169        color: red;
10170      }
10171      "#,
10172      indoc! {r#"
10173      :-webkit-any(.foo:placeholder-shown .bar, .foo:-webkit-autofill .baz) {
10174        color: red;
10175      }
10176
10177      :is(.foo:placeholder-shown .bar, .foo:autofill .baz) {
10178        color: red;
10179      }
10180      "#},
10181      Browsers {
10182        chrome: Some(103 << 16),
10183        ..Browsers::default()
10184      },
10185    );
10186
10187    test(
10188      r#"
10189      .foo:placeholder-shown .bar, .foo:-webkit-autofill .baz {
10190        color: red;
10191      }
10192
10193      .foo:placeholder-shown .bar, .foo:autofill .baz {
10194        color: red;
10195      }
10196      "#,
10197      indoc! {r#"
10198      .foo:placeholder-shown .bar, .foo:-webkit-autofill .baz {
10199        color: red;
10200      }
10201
10202      .foo:placeholder-shown .bar, .foo:autofill .baz {
10203        color: red;
10204      }
10205      "#},
10206    );
10207
10208    prefix_test(
10209      r#"
10210      :hover, :focus-visible {
10211        color: red;
10212      }
10213      "#,
10214      indoc! {r#"
10215      :hover {
10216        color: red;
10217      }
10218
10219      :focus-visible {
10220        color: red;
10221      }
10222      "#},
10223      Browsers {
10224        safari: Some(13 << 16),
10225        ..Browsers::default()
10226      },
10227    );
10228
10229    prefix_test(
10230      r#"
10231      .foo {
10232        color: red;
10233      }
10234
10235      :hover, :focus-visible {
10236        color: red;
10237      }
10238      "#,
10239      indoc! {r#"
10240      .foo, :hover {
10241        color: red;
10242      }
10243
10244      :focus-visible {
10245        color: red;
10246      }
10247      "#},
10248      Browsers {
10249        safari: Some(13 << 16),
10250        ..Browsers::default()
10251      },
10252    );
10253
10254    prefix_test(
10255      r#"
10256      :hover, :focus-visible {
10257        margin-inline-start: 24px;
10258      }
10259      "#,
10260      indoc! {r#"
10261      :hover:not(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
10262        margin-left: 24px;
10263      }
10264
10265      :hover:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) {
10266        margin-right: 24px;
10267      }
10268
10269      :focus-visible:not(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
10270        margin-left: 24px;
10271      }
10272
10273      :focus-visible:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) {
10274        margin-right: 24px;
10275      }
10276      "#},
10277      Browsers {
10278        safari: Some(11 << 16),
10279        ..Browsers::default()
10280      },
10281    );
10282
10283    prefix_test(
10284      r#"
10285      :focus-within, :focus-visible {
10286        color: red;
10287      }
10288      "#,
10289      indoc! {r#"
10290      :focus-within {
10291        color: red;
10292      }
10293
10294      :focus-visible {
10295        color: red;
10296      }
10297      "#},
10298      Browsers {
10299        safari: Some(9 << 16),
10300        ..Browsers::default()
10301      },
10302    );
10303
10304    prefix_test(
10305      r#"
10306      :hover, :focus-visible {
10307        color: red;
10308      }
10309      "#,
10310      indoc! {r#"
10311      :is(:hover, :focus-visible) {
10312        color: red;
10313      }
10314      "#},
10315      Browsers {
10316        safari: Some(14 << 16),
10317        ..Browsers::default()
10318      },
10319    );
10320
10321    prefix_test(
10322      r#"
10323      a::after:hover, a::after:focus-visible {
10324        color: red;
10325      }
10326      "#,
10327      indoc! {r#"
10328      a:after:hover {
10329        color: red;
10330      }
10331
10332      a:after:focus-visible {
10333        color: red;
10334      }
10335      "#},
10336      Browsers {
10337        safari: Some(14 << 16),
10338        ..Browsers::default()
10339      },
10340    );
10341
10342    prefix_test(
10343      r#"
10344      a:not(:hover), a:not(:focus-visible) {
10345        color: red;
10346      }
10347      "#,
10348      indoc! {r#"
10349      :is(a:not(:hover), a:not(:focus-visible)) {
10350        color: red;
10351      }
10352      "#},
10353      Browsers {
10354        safari: Some(14 << 16),
10355        ..Browsers::default()
10356      },
10357    );
10358
10359    prefix_test(
10360      r#"
10361      a:has(:hover), a:has(:focus-visible) {
10362        color: red;
10363      }
10364      "#,
10365      indoc! {r#"
10366      :is(a:has(:hover), a:has(:focus-visible)) {
10367        color: red;
10368      }
10369      "#},
10370      Browsers {
10371        safari: Some(14 << 16),
10372        ..Browsers::default()
10373      },
10374    );
10375
10376    prefix_test(
10377      r#"
10378      .foo.foo:hover, .bar:focus-visible {
10379        color: red;
10380      }
10381      "#,
10382      indoc! {r#"
10383      .foo.foo:hover {
10384        color: red;
10385      }
10386
10387      .bar:focus-visible {
10388        color: red;
10389      }
10390      "#},
10391      Browsers {
10392        safari: Some(14 << 16),
10393        ..Browsers::default()
10394      },
10395    );
10396
10397    prefix_test(
10398      r#"
10399      a::unknown-a, a::unknown-b {
10400        color: red;
10401      }
10402      "#,
10403      indoc! {r#"
10404      a::unknown-a {
10405        color: red;
10406      }
10407
10408      a::unknown-b {
10409        color: red;
10410      }
10411      "#},
10412      Browsers {
10413        safari: Some(14 << 16),
10414        ..Browsers::default()
10415      },
10416    );
10417
10418    nesting_test_with_targets(
10419      r#"
10420      .foo {
10421        padding-inline-start: 3px;
10422
10423        .bar {
10424          padding-inline-start: 5px;
10425        }
10426      }
10427      "#,
10428      indoc! {r#"
10429      .foo:not(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
10430        padding-left: 3px;
10431      }
10432
10433      .foo:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) {
10434        padding-right: 3px;
10435      }
10436
10437      .foo .bar:not(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
10438        padding-left: 5px;
10439      }
10440
10441      .foo .bar:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) {
10442        padding-right: 5px;
10443      }
10444      "#},
10445      Browsers {
10446        safari: Some(12 << 16),
10447        ..Browsers::default()
10448      }
10449      .into(),
10450    );
10451
10452    prefix_test(
10453      r#"
10454      .foo::part(header), .foo::part(body) {
10455        display: none
10456      }
10457      "#,
10458      indoc! {r#"
10459      .foo::part(header), .foo::part(body) {
10460        display: none;
10461      }
10462      "#},
10463      Browsers {
10464        safari: Some(14 << 16),
10465        ..Browsers::default()
10466      },
10467    );
10468
10469    prefix_test(
10470      r#"
10471      .foo :is(.bar) {
10472        color: red;
10473      }
10474      "#,
10475      indoc! {r#"
10476        .foo .bar {
10477          color: red;
10478        }
10479      "#},
10480      Browsers {
10481        chrome: Some(87 << 16),
10482        ..Browsers::default()
10483      },
10484    );
10485
10486    prefix_test(
10487      r#"
10488      .foo :is(.bar), .bar :is(.baz) {
10489        color: red;
10490      }
10491      "#,
10492      indoc! {r#"
10493        .foo .bar, .bar .baz {
10494          color: red;
10495        }
10496      "#},
10497      Browsers {
10498        chrome: Some(87 << 16),
10499        ..Browsers::default()
10500      },
10501    );
10502
10503    prefix_test(
10504      r#"
10505      .foo :is(.bar:focus-visible), .bar :is(.baz:hover) {
10506        color: red;
10507      }
10508      "#,
10509      indoc! {r#"
10510        .bar .baz:hover {
10511          color: red;
10512        }
10513
10514        .foo .bar:focus-visible {
10515          color: red;
10516        }
10517      "#},
10518      Browsers {
10519        chrome: Some(85 << 16),
10520        ..Browsers::default()
10521      },
10522    );
10523
10524    prefix_test(
10525      r#"
10526      *,
10527      ::before,
10528      ::after,
10529      ::backdrop {
10530        padding: 5px;
10531      }
10532      "#,
10533      indoc! {r#"
10534        *, :before, :after {
10535          padding: 5px;
10536        }
10537
10538        ::-webkit-backdrop {
10539          padding: 5px;
10540        }
10541
10542        ::backdrop {
10543          padding: 5px;
10544        }
10545      "#},
10546      Browsers {
10547        chrome: Some(33 << 16),
10548        ..Browsers::default()
10549      },
10550    );
10551
10552    test(
10553      r#"
10554      .foo:-webkit-any(.bar, .baz):after {
10555        color: red;
10556      }
10557
10558      .foo:is(.bar, .baz):after {
10559        color: red;
10560      }
10561      "#,
10562      indoc! {r#"
10563        .foo:-webkit-any(.bar, .baz):after {
10564          color: red;
10565        }
10566
10567        .foo:is(.bar, .baz):after {
10568          color: red;
10569        }
10570      "#},
10571    );
10572
10573    prefix_test(
10574      r#"
10575      .foo:-webkit-any(.bar, .baz):after {
10576        color: red;
10577      }
10578
10579      .foo:is(.bar, .baz):after {
10580        color: red;
10581      }
10582      "#,
10583      indoc! {r#"
10584        .foo:is(.bar, .baz):after {
10585          color: red;
10586        }
10587      "#},
10588      Browsers {
10589        safari: Some(16 << 16),
10590        ..Browsers::default()
10591      },
10592    );
10593
10594    prefix_test(
10595      r#"
10596      .foo:-webkit-any(.bar):after {
10597        color: red;
10598      }
10599
10600      .foo:is(.bar, .baz):after {
10601        color: red;
10602      }
10603      "#,
10604      indoc! {r#"
10605        .foo:-webkit-any(.bar):after {
10606          color: red;
10607        }
10608
10609        .foo:is(.bar, .baz):after {
10610          color: red;
10611        }
10612      "#},
10613      Browsers {
10614        safari: Some(16 << 16),
10615        ..Browsers::default()
10616      },
10617    );
10618
10619    prefix_test(
10620      r#"
10621      .foo:-webkit-any(.bar, .baz):after {
10622        color: red;
10623      }
10624
10625      .foo:is(.bar, .baz):after {
10626        color: red;
10627      }
10628      "#,
10629      indoc! {r#"
10630        .foo:-webkit-any(.bar, .baz):after {
10631          color: red;
10632        }
10633
10634        .foo:is(.bar, .baz):after {
10635          color: red;
10636        }
10637      "#},
10638      Browsers {
10639        safari: Some(12 << 16),
10640        ..Browsers::default()
10641      },
10642    );
10643
10644    prefix_test(
10645      r#"
10646      .foo:-webkit-any(.bar, .baz):after {
10647        color: red;
10648      }
10649
10650      .foo:-moz-any(.bar, .baz):after {
10651        color: red;
10652      }
10653      "#,
10654      indoc! {r#"
10655        .foo:-webkit-any(.bar, .baz):after {
10656          color: red;
10657        }
10658
10659        .foo:-moz-any(.bar, .baz):after {
10660          color: red;
10661        }
10662      "#},
10663      Browsers {
10664        safari: Some(12 << 16),
10665        firefox: Some(67 << 16),
10666        ..Browsers::default()
10667      },
10668    );
10669
10670    prefix_test(
10671      r#"
10672      .a {
10673        padding-inline: var(--foo);
10674      }
10675
10676      .a:-webkit-any(.b, .c) {
10677        padding-inline: var(--foo);
10678      }
10679      "#,
10680      indoc! {r#"
10681        .a {
10682          padding-inline: var(--foo);
10683        }
10684
10685        .a:-webkit-any(.b, .c) {
10686          padding-inline: var(--foo);
10687        }
10688      "#},
10689      Browsers {
10690        safari: Some(12 << 16),
10691        ..Browsers::default()
10692      },
10693    );
10694  }
10695
10696  #[test]
10697  fn test_merge_media_rules() {
10698    test(
10699      r#"
10700      @media (hover) {
10701        .foo {
10702          color: red;
10703        }
10704      }
10705      @media (hover) {
10706        .foo {
10707          background: #fff;
10708        }
10709
10710        .baz {
10711          color: #fff;
10712        }
10713      }
10714      "#,
10715      indoc! {r#"
10716      @media (hover) {
10717        .foo {
10718          color: red;
10719          background: #fff;
10720        }
10721
10722        .baz {
10723          color: #fff;
10724        }
10725      }
10726    "#},
10727    );
10728
10729    test(
10730      r#"
10731      @media (hover) {
10732        .foo {
10733          color: red;
10734        }
10735      }
10736      @media (min-width: 250px) {
10737        .foo {
10738          background: #fff;
10739        }
10740
10741        .baz {
10742          color: #fff;
10743        }
10744      }
10745      "#,
10746      indoc! {r#"
10747      @media (hover) {
10748        .foo {
10749          color: red;
10750        }
10751      }
10752
10753      @media (width >= 250px) {
10754        .foo {
10755          background: #fff;
10756        }
10757
10758        .baz {
10759          color: #fff;
10760        }
10761      }
10762    "#},
10763    );
10764  }
10765
10766  #[test]
10767  fn test_merge_supports() {
10768    test(
10769      r#"
10770      @supports (flex: 1) {
10771        .foo {
10772          color: red;
10773        }
10774      }
10775      @supports (flex: 1) {
10776        .foo {
10777          background: #fff;
10778        }
10779
10780        .baz {
10781          color: #fff;
10782        }
10783      }
10784      "#,
10785      indoc! {r#"
10786      @supports (flex: 1) {
10787        .foo {
10788          color: red;
10789          background: #fff;
10790        }
10791
10792        .baz {
10793          color: #fff;
10794        }
10795      }
10796    "#},
10797    );
10798
10799    test(
10800      r#"
10801      @supports (flex: 1) {
10802        .foo {
10803          color: red;
10804        }
10805      }
10806      @supports (display: grid) {
10807        .foo {
10808          background: #fff;
10809        }
10810
10811        .baz {
10812          color: #fff;
10813        }
10814      }
10815      "#,
10816      indoc! {r#"
10817      @supports (flex: 1) {
10818        .foo {
10819          color: red;
10820        }
10821      }
10822
10823      @supports (display: grid) {
10824        .foo {
10825          background: #fff;
10826        }
10827
10828        .baz {
10829          color: #fff;
10830        }
10831      }
10832    "#},
10833    );
10834  }
10835
10836  #[test]
10837  fn test_opacity() {
10838    minify_test(".foo { opacity: 0 }", ".foo{opacity:0}");
10839    minify_test(".foo { opacity: 0% }", ".foo{opacity:0}");
10840    minify_test(".foo { opacity: 0.5 }", ".foo{opacity:.5}");
10841    minify_test(".foo { opacity: 50% }", ".foo{opacity:.5}");
10842    minify_test(".foo { opacity: 1 }", ".foo{opacity:1}");
10843    minify_test(".foo { opacity: 100% }", ".foo{opacity:1}");
10844  }
10845
10846  #[test]
10847  fn test_transitions() {
10848    minify_test(".foo { transition-duration: 500ms }", ".foo{transition-duration:.5s}");
10849    minify_test(".foo { transition-duration: .5s }", ".foo{transition-duration:.5s}");
10850    minify_test(".foo { transition-duration: 99ms }", ".foo{transition-duration:99ms}");
10851    minify_test(".foo { transition-duration: .099s }", ".foo{transition-duration:99ms}");
10852    minify_test(".foo { transition-duration: 2000ms }", ".foo{transition-duration:2s}");
10853    minify_test(".foo { transition-duration: 2s }", ".foo{transition-duration:2s}");
10854    minify_test(
10855      ".foo { transition-duration: calc(1s - 50ms) }",
10856      ".foo{transition-duration:.95s}",
10857    );
10858    minify_test(
10859      ".foo { transition-duration: calc(1s - 50ms + 2s) }",
10860      ".foo{transition-duration:2.95s}",
10861    );
10862    minify_test(
10863      ".foo { transition-duration: calc((1s - 50ms) * 2) }",
10864      ".foo{transition-duration:1.9s}",
10865    );
10866    minify_test(
10867      ".foo { transition-duration: calc(2 * (1s - 50ms)) }",
10868      ".foo{transition-duration:1.9s}",
10869    );
10870    minify_test(
10871      ".foo { transition-duration: calc((2s + 50ms) - (1s - 50ms)) }",
10872      ".foo{transition-duration:1.1s}",
10873    );
10874    minify_test(
10875      ".foo { transition-duration: 500ms, 50ms }",
10876      ".foo{transition-duration:.5s,50ms}",
10877    );
10878    minify_test(".foo { transition-delay: 500ms }", ".foo{transition-delay:.5s}");
10879    minify_test(
10880      ".foo { transition-property: background }",
10881      ".foo{transition-property:background}",
10882    );
10883    minify_test(
10884      ".foo { transition-property: background, opacity }",
10885      ".foo{transition-property:background,opacity}",
10886    );
10887    minify_test(
10888      ".foo { transition-timing-function: linear }",
10889      ".foo{transition-timing-function:linear}",
10890    );
10891    minify_test(
10892      ".foo { transition-timing-function: ease }",
10893      ".foo{transition-timing-function:ease}",
10894    );
10895    minify_test(
10896      ".foo { transition-timing-function: ease-in }",
10897      ".foo{transition-timing-function:ease-in}",
10898    );
10899    minify_test(
10900      ".foo { transition-timing-function: ease-out }",
10901      ".foo{transition-timing-function:ease-out}",
10902    );
10903    minify_test(
10904      ".foo { transition-timing-function: ease-in-out }",
10905      ".foo{transition-timing-function:ease-in-out}",
10906    );
10907    minify_test(
10908      ".foo { transition-timing-function: cubic-bezier(0.25, 0.1, 0.25, 1) }",
10909      ".foo{transition-timing-function:ease}",
10910    );
10911    minify_test(
10912      ".foo { transition-timing-function: cubic-bezier(0.42, 0, 1, 1) }",
10913      ".foo{transition-timing-function:ease-in}",
10914    );
10915    minify_test(
10916      ".foo { transition-timing-function: cubic-bezier(0, 0, 0.58, 1) }",
10917      ".foo{transition-timing-function:ease-out}",
10918    );
10919    minify_test(
10920      ".foo { transition-timing-function: cubic-bezier(0.42, 0, 0.58, 1) }",
10921      ".foo{transition-timing-function:ease-in-out}",
10922    );
10923    minify_test(
10924      ".foo { transition-timing-function: cubic-bezier(0.58, 0.2, 0.11, 1.2) }",
10925      ".foo{transition-timing-function:cubic-bezier(.58,.2,.11,1.2)}",
10926    );
10927    minify_test(
10928      ".foo { transition-timing-function: step-start }",
10929      ".foo{transition-timing-function:step-start}",
10930    );
10931    minify_test(
10932      ".foo { transition-timing-function: step-end }",
10933      ".foo{transition-timing-function:step-end}",
10934    );
10935    minify_test(
10936      ".foo { transition-timing-function: steps(1, start) }",
10937      ".foo{transition-timing-function:step-start}",
10938    );
10939    minify_test(
10940      ".foo { transition-timing-function: steps(1, jump-start) }",
10941      ".foo{transition-timing-function:step-start}",
10942    );
10943    minify_test(
10944      ".foo { transition-timing-function: steps(1, end) }",
10945      ".foo{transition-timing-function:step-end}",
10946    );
10947    minify_test(
10948      ".foo { transition-timing-function: steps(1, jump-end) }",
10949      ".foo{transition-timing-function:step-end}",
10950    );
10951    minify_test(
10952      ".foo { transition-timing-function: steps(5, jump-start) }",
10953      ".foo{transition-timing-function:steps(5,start)}",
10954    );
10955    minify_test(
10956      ".foo { transition-timing-function: steps(5, jump-end) }",
10957      ".foo{transition-timing-function:steps(5,end)}",
10958    );
10959    minify_test(
10960      ".foo { transition-timing-function: steps(5, jump-both) }",
10961      ".foo{transition-timing-function:steps(5,jump-both)}",
10962    );
10963    minify_test(
10964      ".foo { transition-timing-function: ease-in-out, cubic-bezier(0.42, 0, 1, 1) }",
10965      ".foo{transition-timing-function:ease-in-out,ease-in}",
10966    );
10967    minify_test(
10968      ".foo { transition-timing-function: cubic-bezier(0.42, 0, 1, 1), cubic-bezier(0.58, 0.2, 0.11, 1.2) }",
10969      ".foo{transition-timing-function:ease-in,cubic-bezier(.58,.2,.11,1.2)}",
10970    );
10971    minify_test(
10972      ".foo { transition-timing-function: step-start, steps(5, jump-start) }",
10973      ".foo{transition-timing-function:step-start,steps(5,start)}",
10974    );
10975    minify_test(".foo { transition: width 2s ease }", ".foo{transition:width 2s}");
10976    minify_test(
10977      ".foo { transition: width 2s ease, height 1000ms cubic-bezier(0.25, 0.1, 0.25, 1) }",
10978      ".foo{transition:width 2s,height 1s}",
10979    );
10980    minify_test(".foo { transition: width 2s 1s }", ".foo{transition:width 2s 1s}");
10981    minify_test(".foo { transition: width 2s ease 1s }", ".foo{transition:width 2s 1s}");
10982    minify_test(
10983      ".foo { transition: ease-in 1s width 4s }",
10984      ".foo{transition:width 1s ease-in 4s}",
10985    );
10986    minify_test(".foo { transition: opacity 0s .6s }", ".foo{transition:opacity 0s .6s}");
10987    test(
10988      r#"
10989      .foo {
10990        transition-property: opacity;
10991        transition-duration: 0.09s;
10992        transition-timing-function: ease-in-out;
10993        transition-delay: 500ms;
10994      }
10995    "#,
10996      indoc! {r#"
10997      .foo {
10998        transition: opacity 90ms ease-in-out .5s;
10999      }
11000    "#},
11001    );
11002    test(
11003      r#"
11004      .foo {
11005        transition: opacity 2s;
11006        transition-timing-function: ease;
11007        transition-delay: 500ms;
11008      }
11009    "#,
11010      indoc! {r#"
11011      .foo {
11012        transition: opacity 2s .5s;
11013      }
11014    "#},
11015    );
11016    test(
11017      r#"
11018      .foo {
11019        transition: opacity 500ms;
11020        transition-timing-function: var(--ease);
11021      }
11022    "#,
11023      indoc! {r#"
11024      .foo {
11025        transition: opacity .5s;
11026        transition-timing-function: var(--ease);
11027      }
11028    "#},
11029    );
11030    test(
11031      r#"
11032      .foo {
11033        transition-property: opacity;
11034        transition-duration: 0.09s;
11035        transition-timing-function: ease-in-out;
11036        transition-delay: 500ms;
11037        transition: color 2s;
11038      }
11039    "#,
11040      indoc! {r#"
11041      .foo {
11042        transition: color 2s;
11043      }
11044    "#},
11045    );
11046    test(
11047      r#"
11048      .foo {
11049        transition-property: opacity, color;
11050        transition-duration: 2s, 4s;
11051        transition-timing-function: ease-in-out, ease-in;
11052        transition-delay: 500ms, 0s;
11053      }
11054    "#,
11055      indoc! {r#"
11056      .foo {
11057        transition: opacity 2s ease-in-out .5s, color 4s ease-in;
11058      }
11059    "#},
11060    );
11061    test(
11062      r#"
11063      .foo {
11064        transition-property: opacity, color;
11065        transition-duration: 2s;
11066        transition-timing-function: ease-in-out;
11067        transition-delay: 500ms;
11068      }
11069    "#,
11070      indoc! {r#"
11071      .foo {
11072        transition: opacity 2s ease-in-out .5s, color 2s ease-in-out .5s;
11073      }
11074    "#},
11075    );
11076    test(
11077      r#"
11078      .foo {
11079        transition-property: opacity, color, width, height;
11080        transition-duration: 2s, 4s;
11081        transition-timing-function: ease;
11082        transition-delay: 0s;
11083      }
11084    "#,
11085      indoc! {r#"
11086      .foo {
11087        transition: opacity 2s, color 4s, width 2s, height 4s;
11088      }
11089    "#},
11090    );
11091
11092    test(
11093      r#"
11094      .foo {
11095        -webkit-transition-property: opacity, color;
11096        -webkit-transition-duration: 2s, 4s;
11097        -webkit-transition-timing-function: ease-in-out, ease-in;
11098        -webkit-transition-delay: 500ms, 0s;
11099      }
11100    "#,
11101      indoc! {r#"
11102      .foo {
11103        -webkit-transition: opacity 2s ease-in-out .5s, color 4s ease-in;
11104      }
11105    "#},
11106    );
11107
11108    test(
11109      r#"
11110      .foo {
11111        -webkit-transition-property: opacity, color;
11112        -webkit-transition-duration: 2s, 4s;
11113        -webkit-transition-timing-function: ease-in-out, ease-in;
11114        -webkit-transition-delay: 500ms, 0s;
11115        -moz-transition-property: opacity, color;
11116        -moz-transition-duration: 2s, 4s;
11117        -moz-transition-timing-function: ease-in-out, ease-in;
11118        -moz-transition-delay: 500ms, 0s;
11119        transition-property: opacity, color;
11120        transition-duration: 2s, 4s;
11121        transition-timing-function: ease-in-out, ease-in;
11122        transition-delay: 500ms, 0s;
11123      }
11124    "#,
11125      indoc! {r#"
11126      .foo {
11127        -webkit-transition: opacity 2s ease-in-out .5s, color 4s ease-in;
11128        -moz-transition: opacity 2s ease-in-out .5s, color 4s ease-in;
11129        transition: opacity 2s ease-in-out .5s, color 4s ease-in;
11130      }
11131    "#},
11132    );
11133
11134    test(
11135      r#"
11136      .foo {
11137        -webkit-transition-property: opacity, color;
11138        -moz-transition-property: opacity, color;
11139        transition-property: opacity, color;
11140        -webkit-transition-duration: 2s, 4s;
11141        -moz-transition-duration: 2s, 4s;
11142        transition-duration: 2s, 4s;
11143        -webkit-transition-timing-function: ease-in-out, ease-in;
11144        transition-timing-function: ease-in-out, ease-in;
11145        -moz-transition-timing-function: ease-in-out, ease-in;
11146        -webkit-transition-delay: 500ms, 0s;
11147        -moz-transition-delay: 500ms, 0s;
11148        transition-delay: 500ms, 0s;
11149      }
11150    "#,
11151      indoc! {r#"
11152      .foo {
11153        -webkit-transition: opacity 2s ease-in-out .5s, color 4s ease-in;
11154        -moz-transition: opacity 2s ease-in-out .5s, color 4s ease-in;
11155        transition: opacity 2s ease-in-out .5s, color 4s ease-in;
11156      }
11157    "#},
11158    );
11159
11160    test(
11161      r#"
11162      .foo {
11163        -webkit-transition-property: opacity;
11164        -moz-transition-property: color;
11165        transition-property: opacity, color;
11166        -webkit-transition-duration: 2s;
11167        -moz-transition-duration: 4s;
11168        transition-duration: 2s, 4s;
11169        -webkit-transition-timing-function: ease-in-out;
11170        -moz-transition-timing-function: ease-in-out;
11171        transition-timing-function: ease-in-out, ease-in;
11172        -webkit-transition-delay: 500ms;
11173        -moz-transition-delay: 0s;
11174        transition-delay: 500ms, 0s;
11175      }
11176    "#,
11177      indoc! {r#"
11178      .foo {
11179        -webkit-transition-property: opacity;
11180        -moz-transition-property: color;
11181        transition-property: opacity, color;
11182        -webkit-transition-duration: 2s;
11183        -moz-transition-duration: 4s;
11184        transition-duration: 2s, 4s;
11185        -webkit-transition-timing-function: ease-in-out;
11186        -moz-transition-timing-function: ease-in-out;
11187        -webkit-transition-delay: .5s;
11188        transition-timing-function: ease-in-out, ease-in;
11189        -moz-transition-delay: 0s;
11190        transition-delay: .5s, 0s;
11191      }
11192    "#},
11193    );
11194
11195    test(
11196      r#"
11197      .foo {
11198        -webkit-transition-property: opacity;
11199        transition-property: opacity, color;
11200        -moz-transition-property: color;
11201        -webkit-transition-duration: 2s;
11202        transition-duration: 2s, 4s;
11203        -moz-transition-duration: 4s;
11204        -webkit-transition-timing-function: ease-in-out;
11205        transition-timing-function: ease-in-out, ease-in;
11206        -moz-transition-timing-function: ease-in-out;
11207        -webkit-transition-delay: 500ms;
11208        transition-delay: 500ms, 0s;
11209        -moz-transition-delay: 0s;
11210      }
11211    "#,
11212      indoc! {r#"
11213      .foo {
11214        -webkit-transition-property: opacity;
11215        transition-property: opacity, color;
11216        -moz-transition-property: color;
11217        -webkit-transition-duration: 2s;
11218        transition-duration: 2s, 4s;
11219        -moz-transition-duration: 4s;
11220        -webkit-transition-timing-function: ease-in-out;
11221        transition-timing-function: ease-in-out, ease-in;
11222        -webkit-transition-delay: .5s;
11223        -moz-transition-timing-function: ease-in-out;
11224        transition-delay: .5s, 0s;
11225        -moz-transition-delay: 0s;
11226      }
11227    "#},
11228    );
11229
11230    test(
11231      r#"
11232      .foo {
11233        transition: opacity 2s;
11234        -webkit-transition-duration: 2s;
11235      }
11236    "#,
11237      indoc! {r#"
11238      .foo {
11239        transition: opacity 2s;
11240        -webkit-transition-duration: 2s;
11241      }
11242    "#},
11243    );
11244
11245    prefix_test(
11246      r#"
11247      .foo {
11248        transition-property: margin-inline-start;
11249      }
11250    "#,
11251      indoc! {r#"
11252      .foo:not(:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
11253        transition-property: margin-left;
11254      }
11255
11256      .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
11257        transition-property: margin-left;
11258      }
11259
11260      .foo:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
11261        transition-property: margin-right;
11262      }
11263
11264      .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
11265        transition-property: margin-right;
11266      }
11267    "#
11268      },
11269      Browsers {
11270        safari: Some(8 << 16),
11271        ..Browsers::default()
11272      },
11273    );
11274
11275    prefix_test(
11276      r#"
11277      .foo {
11278        transition-property: margin-inline-start, padding-inline-start;
11279      }
11280    "#,
11281      indoc! {r#"
11282      .foo:not(:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
11283        transition-property: margin-left, padding-left;
11284      }
11285
11286      .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
11287        transition-property: margin-left, padding-left;
11288      }
11289
11290      .foo:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
11291        transition-property: margin-right, padding-right;
11292      }
11293
11294      .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
11295        transition-property: margin-right, padding-right;
11296      }
11297    "#
11298      },
11299      Browsers {
11300        safari: Some(8 << 16),
11301        ..Browsers::default()
11302      },
11303    );
11304
11305    prefix_test(
11306      r#"
11307      .foo {
11308        transition-property: margin-inline-start, opacity, padding-inline-start, color;
11309      }
11310    "#,
11311      indoc! {r#"
11312      .foo:not(:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
11313        transition-property: margin-left, opacity, padding-left, color;
11314      }
11315
11316      .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
11317        transition-property: margin-left, opacity, padding-left, color;
11318      }
11319
11320      .foo:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
11321        transition-property: margin-right, opacity, padding-right, color;
11322      }
11323
11324      .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
11325        transition-property: margin-right, opacity, padding-right, color;
11326      }
11327    "#
11328      },
11329      Browsers {
11330        safari: Some(8 << 16),
11331        ..Browsers::default()
11332      },
11333    );
11334
11335    prefix_test(
11336      r#"
11337      .foo {
11338        transition-property: margin-block;
11339      }
11340    "#,
11341      indoc! {r#"
11342      .foo {
11343        transition-property: margin-top, margin-bottom;
11344      }
11345    "#
11346      },
11347      Browsers {
11348        safari: Some(8 << 16),
11349        ..Browsers::default()
11350      },
11351    );
11352
11353    prefix_test(
11354      r#"
11355      .foo {
11356        transition: margin-inline-start 2s;
11357      }
11358    "#,
11359      indoc! {r#"
11360      .foo:not(:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
11361        transition: margin-left 2s;
11362      }
11363
11364      .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
11365        transition: margin-left 2s;
11366      }
11367
11368      .foo:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
11369        transition: margin-right 2s;
11370      }
11371
11372      .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
11373        transition: margin-right 2s;
11374      }
11375    "#
11376      },
11377      Browsers {
11378        safari: Some(8 << 16),
11379        ..Browsers::default()
11380      },
11381    );
11382
11383    prefix_test(
11384      r#"
11385      .foo {
11386        transition: margin-inline-start 2s, padding-inline-start 2s;
11387      }
11388    "#,
11389      indoc! {r#"
11390      .foo:not(:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
11391        transition: margin-left 2s, padding-left 2s;
11392      }
11393
11394      .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
11395        transition: margin-left 2s, padding-left 2s;
11396      }
11397
11398      .foo:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
11399        transition: margin-right 2s, padding-right 2s;
11400      }
11401
11402      .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
11403        transition: margin-right 2s, padding-right 2s;
11404      }
11405    "#
11406      },
11407      Browsers {
11408        safari: Some(8 << 16),
11409        ..Browsers::default()
11410      },
11411    );
11412
11413    prefix_test(
11414      r#"
11415      .foo {
11416        transition: margin-block-start 2s;
11417      }
11418    "#,
11419      indoc! {r#"
11420      .foo {
11421        transition: margin-top 2s;
11422      }
11423    "#
11424      },
11425      Browsers {
11426        safari: Some(8 << 16),
11427        ..Browsers::default()
11428      },
11429    );
11430
11431    prefix_test(
11432      r#"
11433      .foo {
11434        transition: transform;
11435      }
11436    "#,
11437      indoc! {r#"
11438      .foo {
11439        -webkit-transition: -webkit-transform, transform;
11440        transition: -webkit-transform, transform;
11441      }
11442    "#
11443      },
11444      Browsers {
11445        safari: Some(6 << 16),
11446        ..Browsers::default()
11447      },
11448    );
11449
11450    prefix_test(
11451      r#"
11452      .foo {
11453        transition: border-start-start-radius;
11454      }
11455    "#,
11456      indoc! {r#"
11457      .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
11458        -webkit-transition: -webkit-border-top-left-radius, border-top-left-radius;
11459        transition: -webkit-border-top-left-radius, border-top-left-radius;
11460      }
11461
11462      .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
11463        -webkit-transition: -webkit-border-top-right-radius, border-top-right-radius;
11464        transition: -webkit-border-top-right-radius, border-top-right-radius;
11465      }
11466    "#
11467      },
11468      Browsers {
11469        safari: Some(4 << 16),
11470        ..Browsers::default()
11471      },
11472    );
11473
11474    prefix_test(
11475      r#"
11476      .foo {
11477        transition: border-start-start-radius;
11478      }
11479    "#,
11480      indoc! {r#"
11481      .foo:not(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
11482        transition: border-top-left-radius;
11483      }
11484
11485      .foo:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) {
11486        transition: border-top-right-radius;
11487      }
11488    "#
11489      },
11490      Browsers {
11491        safari: Some(12 << 16),
11492        ..Browsers::default()
11493      },
11494    );
11495
11496    test(
11497      r#"
11498      .foo {
11499        -webkit-transition: background 200ms;
11500        -moz-transition: background 200ms;
11501        transition: background 230ms;
11502      }
11503    "#,
11504      indoc! {r#"
11505      .foo {
11506        -webkit-transition: background .2s;
11507        -moz-transition: background .2s;
11508        transition: background .23s;
11509      }
11510    "#},
11511    );
11512
11513    prefix_test(
11514      r#"
11515      .foo {
11516        -webkit-transition: background 200ms;
11517        -moz-transition: background 200ms;
11518        transition: background 230ms;
11519      }
11520    "#,
11521      indoc! {r#"
11522      .foo {
11523        -webkit-transition: background .2s;
11524        -moz-transition: background .2s;
11525        transition: background .23s;
11526      }
11527    "#},
11528      Browsers {
11529        chrome: Some(95 << 16),
11530        ..Browsers::default()
11531      },
11532    );
11533    prefix_test(
11534      r#"
11535       .foo {
11536         transition-property: -webkit-backdrop-filter, backdrop-filter;
11537       }
11538       .bar {
11539         transition-property: backdrop-filter;
11540       }
11541       .baz {
11542         transition-property: -webkit-backdrop-filter;
11543       }
11544     "#,
11545      indoc! {r#"
11546       .foo, .bar {
11547         transition-property: -webkit-backdrop-filter, backdrop-filter;
11548       }
11549
11550       .baz {
11551         transition-property: -webkit-backdrop-filter;
11552       }
11553     "#
11554      },
11555      Browsers {
11556        safari: Some(15 << 16),
11557        ..Browsers::default()
11558      },
11559    );
11560    prefix_test(
11561      r#"
11562       .foo {
11563         transition-property: -webkit-border-radius, -webkit-border-radius, -moz-border-radius;
11564       }
11565     "#,
11566      indoc! {r#"
11567       .foo {
11568         transition-property: -webkit-border-radius, -moz-border-radius;
11569       }
11570     "#
11571      },
11572      Browsers {
11573        safari: Some(15 << 16),
11574        ..Browsers::default()
11575      },
11576    );
11577    prefix_test(
11578      r#"
11579       .foo {
11580         transition: -webkit-backdrop-filter, backdrop-filter;
11581       }
11582       .bar {
11583         transition: backdrop-filter;
11584       }
11585       .baz {
11586         transition: -webkit-backdrop-filter;
11587       }
11588     "#,
11589      indoc! {r#"
11590       .foo, .bar {
11591         transition: -webkit-backdrop-filter, backdrop-filter;
11592       }
11593
11594       .baz {
11595         transition: -webkit-backdrop-filter;
11596       }
11597     "#
11598      },
11599      Browsers {
11600        safari: Some(15 << 16),
11601        ..Browsers::default()
11602      },
11603    );
11604  }
11605
11606  #[test]
11607  fn test_animation() {
11608    minify_test(".foo { animation-name: test }", ".foo{animation-name:test}");
11609    minify_test(".foo { animation-name: \"test\" }", ".foo{animation-name:test}");
11610    minify_test(".foo { animation-name: foo, bar }", ".foo{animation-name:foo,bar}");
11611    minify_test(".foo { animation-name: \"none\" }", ".foo{animation-name:\"none\"}");
11612    minify_test(
11613      ".foo { animation-name: \"none\", foo }",
11614      ".foo{animation-name:\"none\",foo}",
11615    );
11616    let name = crate::properties::animation::AnimationName::parse_string("default");
11617    assert!(matches!(name, Err(..)));
11618
11619    minify_test(".foo { animation-name: none }", ".foo{animation-name:none}");
11620    minify_test(".foo { animation-name: none, none }", ".foo{animation-name:none,none}");
11621
11622    // Test CSS-wide keywords
11623    minify_test(".foo { animation-name: unset }", ".foo{animation-name:unset}");
11624    minify_test(".foo { animation-name: \"unset\" }", ".foo{animation-name:\"unset\"}");
11625    minify_test(".foo { animation-name: \"revert\" }", ".foo{animation-name:\"revert\"}");
11626    minify_test(
11627      ".foo { animation-name: \"unset\", \"revert\"}",
11628      ".foo{animation-name:\"unset\",\"revert\"}",
11629    );
11630    minify_test(
11631      ".foo { animation-name: foo, \"revert\"}",
11632      ".foo{animation-name:foo,\"revert\"}",
11633    );
11634    minify_test(
11635      ".foo { animation-name: \"string\", \"revert\"}",
11636      ".foo{animation-name:string,\"revert\"}",
11637    );
11638    minify_test(
11639      ".foo { animation-name: \"string\", foo, \"revert\"}",
11640      ".foo{animation-name:string,foo,\"revert\"}",
11641    );
11642    minify_test(
11643      ".foo { animation-name: \"default\" }",
11644      ".foo{animation-name:\"default\"}",
11645    );
11646    minify_test(".foo { animation-duration: 100ms }", ".foo{animation-duration:.1s}");
11647    minify_test(
11648      ".foo { animation-duration: 100ms, 2000ms }",
11649      ".foo{animation-duration:.1s,2s}",
11650    );
11651    minify_test(
11652      ".foo { animation-timing-function: ease }",
11653      ".foo{animation-timing-function:ease}",
11654    );
11655    minify_test(
11656      ".foo { animation-timing-function: cubic-bezier(0.42, 0, 1, 1) }",
11657      ".foo{animation-timing-function:ease-in}",
11658    );
11659    minify_test(
11660      ".foo { animation-timing-function: ease, cubic-bezier(0.42, 0, 1, 1) }",
11661      ".foo{animation-timing-function:ease,ease-in}",
11662    );
11663    minify_test(
11664      ".foo { animation-iteration-count: 5 }",
11665      ".foo{animation-iteration-count:5}",
11666    );
11667    minify_test(
11668      ".foo { animation-iteration-count: 2.5 }",
11669      ".foo{animation-iteration-count:2.5}",
11670    );
11671    minify_test(
11672      ".foo { animation-iteration-count: 2.0 }",
11673      ".foo{animation-iteration-count:2}",
11674    );
11675    minify_test(
11676      ".foo { animation-iteration-count: infinite }",
11677      ".foo{animation-iteration-count:infinite}",
11678    );
11679    minify_test(
11680      ".foo { animation-iteration-count: 1, infinite }",
11681      ".foo{animation-iteration-count:1,infinite}",
11682    );
11683    minify_test(
11684      ".foo { animation-direction: reverse }",
11685      ".foo{animation-direction:reverse}",
11686    );
11687    minify_test(
11688      ".foo { animation-direction: alternate, reverse }",
11689      ".foo{animation-direction:alternate,reverse}",
11690    );
11691    minify_test(
11692      ".foo { animation-play-state: paused }",
11693      ".foo{animation-play-state:paused}",
11694    );
11695    minify_test(
11696      ".foo { animation-play-state: running, paused }",
11697      ".foo{animation-play-state:running,paused}",
11698    );
11699    minify_test(".foo { animation-delay: 100ms }", ".foo{animation-delay:.1s}");
11700    minify_test(
11701      ".foo { animation-delay: 100ms, 2000ms }",
11702      ".foo{animation-delay:.1s,2s}",
11703    );
11704    minify_test(
11705      ".foo { animation-fill-mode: forwards }",
11706      ".foo{animation-fill-mode:forwards}",
11707    );
11708    minify_test(
11709      ".foo { animation-fill-mode: Backwards,forwards }",
11710      ".foo{animation-fill-mode:backwards,forwards}",
11711    );
11712    minify_test(".foo { animation: none }", ".foo{animation:none}");
11713    minify_test(".foo { animation: \"none\" }", ".foo{animation:\"none\"}");
11714    minify_test(".foo { animation: \"None\" }", ".foo{animation:\"None\"}");
11715    minify_test(".foo { animation: \"none\", none }", ".foo{animation:\"none\",none}");
11716    minify_test(".foo { animation: none, none }", ".foo{animation:none,none}");
11717    minify_test(".foo { animation: \"none\" none }", ".foo{animation:\"none\"}");
11718    minify_test(".foo { animation: none none }", ".foo{animation:none}");
11719
11720    // Test animation-name + animation-fill-mode
11721    minify_test(
11722      ".foo { animation: 2s both \"none\"}",
11723      ".foo{animation:2s both \"none\"}",
11724    );
11725    minify_test(
11726      ".foo { animation: both \"none\" 2s}",
11727      ".foo{animation:2s both \"none\"}",
11728    );
11729    minify_test(".foo { animation: \"none\" 2s none}", ".foo{animation:2s \"none\"}");
11730    minify_test(".foo { animation: none \"none\" 2s}", ".foo{animation:2s \"none\"}");
11731    minify_test(
11732      ".foo { animation: none, \"none\" 2s forwards}",
11733      ".foo{animation:none,2s forwards \"none\"}",
11734    );
11735
11736    minify_test(".foo { animation: \"unset\" }", ".foo{animation:\"unset\"}");
11737    minify_test(".foo { animation: \"string\" .5s }", ".foo{animation:.5s string}");
11738    minify_test(".foo { animation: \"unset\" .5s }", ".foo{animation:.5s \"unset\"}");
11739    minify_test(
11740      ".foo { animation: none, \"unset\" .5s}",
11741      ".foo{animation:none,.5s \"unset\"}",
11742    );
11743    minify_test(
11744      ".foo { animation: \"unset\" 0s 3s infinite, none }",
11745      ".foo{animation:0s 3s infinite \"unset\",none}",
11746    );
11747
11748    minify_test(".foo { animation: \"infinite\" 2s 1 }", ".foo{animation:2s 1 infinite}");
11749    minify_test(".foo { animation: \"paused\" 2s }", ".foo{animation:2s running paused}");
11750    minify_test(
11751      ".foo { animation: \"forwards\" 2s }",
11752      ".foo{animation:2s none forwards}",
11753    );
11754    minify_test(
11755      ".foo { animation: \"reverse\" 2s }",
11756      ".foo{animation:2s normal reverse}",
11757    );
11758    minify_test(
11759      ".foo { animation: \"reverse\" 2s alternate }",
11760      ".foo{animation:2s alternate reverse}",
11761    );
11762
11763    minify_test(
11764      ".foo { animation: 3s ease-in 1s infinite reverse both running slidein }",
11765      ".foo{animation:3s ease-in 1s infinite reverse both slidein}",
11766    );
11767    minify_test(
11768      ".foo { animation: 3s slidein paused ease 1s 1 reverse both }",
11769      ".foo{animation:3s 1s reverse both paused slidein}",
11770    );
11771    minify_test(".foo { animation: 3s ease ease }", ".foo{animation:3s ease ease}");
11772    minify_test(
11773      ".foo { animation: 3s cubic-bezier(0.25, 0.1, 0.25, 1) foo }",
11774      ".foo{animation:3s foo}",
11775    );
11776    minify_test(
11777      ".foo { animation: foo 0s 3s infinite }",
11778      ".foo{animation:0s 3s infinite foo}",
11779    );
11780    minify_test(".foo { animation: foo 3s --test }", ".foo{animation:3s foo --test}");
11781    minify_test(".foo { animation: foo 3s scroll() }", ".foo{animation:3s foo scroll()}");
11782    minify_test(
11783      ".foo { animation: foo 3s scroll(block) }",
11784      ".foo{animation:3s foo scroll()}",
11785    );
11786    minify_test(
11787      ".foo { animation: foo 3s scroll(root inline) }",
11788      ".foo{animation:3s foo scroll(root inline)}",
11789    );
11790    minify_test(
11791      ".foo { animation: foo 3s scroll(inline root) }",
11792      ".foo{animation:3s foo scroll(root inline)}",
11793    );
11794    minify_test(
11795      ".foo { animation: foo 3s scroll(inline nearest) }",
11796      ".foo{animation:3s foo scroll(inline)}",
11797    );
11798    minify_test(
11799      ".foo { animation: foo 3s view(block) }",
11800      ".foo{animation:3s foo view()}",
11801    );
11802    minify_test(
11803      ".foo { animation: foo 3s view(inline) }",
11804      ".foo{animation:3s foo view(inline)}",
11805    );
11806    minify_test(
11807      ".foo { animation: foo 3s view(inline 10px 10px) }",
11808      ".foo{animation:3s foo view(inline 10px)}",
11809    );
11810    minify_test(
11811      ".foo { animation: foo 3s view(inline 10px 12px) }",
11812      ".foo{animation:3s foo view(inline 10px 12px)}",
11813    );
11814    minify_test(
11815      ".foo { animation: foo 3s view(inline auto auto) }",
11816      ".foo{animation:3s foo view(inline)}",
11817    );
11818    minify_test(".foo { animation: foo 3s auto }", ".foo{animation:3s foo}");
11819    minify_test(".foo { animation-composition: add }", ".foo{animation-composition:add}");
11820    test(
11821      r#"
11822      .foo {
11823        animation-name: foo;
11824        animation-duration: 0.09s;
11825        animation-timing-function: ease-in-out;
11826        animation-iteration-count: 2;
11827        animation-direction: alternate;
11828        animation-play-state: running;
11829        animation-delay: 100ms;
11830        animation-fill-mode: forwards;
11831        animation-timeline: auto;
11832      }
11833    "#,
11834      indoc! {r#"
11835      .foo {
11836        animation: 90ms ease-in-out .1s 2 alternate forwards foo;
11837      }
11838    "#},
11839    );
11840    test(
11841      r#"
11842      .foo {
11843        animation-name: foo, bar;
11844        animation-duration: 0.09s, 200ms;
11845        animation-timing-function: ease-in-out, ease;
11846        animation-iteration-count: 2, 1;
11847        animation-direction: alternate, normal;
11848        animation-play-state: running, paused;
11849        animation-delay: 100ms, 0s;
11850        animation-fill-mode: forwards, none;
11851        animation-timeline: auto, auto;
11852      }
11853    "#,
11854      indoc! {r#"
11855      .foo {
11856        animation: 90ms ease-in-out .1s 2 alternate forwards foo, .2s paused bar;
11857      }
11858    "#},
11859    );
11860    test(
11861      r#"
11862      .foo {
11863        animation: bar 200ms;
11864        animation-timing-function: ease-in-out;
11865      }
11866    "#,
11867      indoc! {r#"
11868      .foo {
11869        animation: .2s ease-in-out bar;
11870      }
11871    "#},
11872    );
11873    test(
11874      r#"
11875      .foo {
11876        animation: bar 200ms;
11877        animation-timing-function: var(--ease);
11878      }
11879    "#,
11880      indoc! {r#"
11881      .foo {
11882        animation: .2s bar;
11883        animation-timing-function: var(--ease);
11884      }
11885    "#},
11886    );
11887    test(
11888      r#"
11889      .foo {
11890        animation-name: foo, bar;
11891        animation-duration: 0.09s;
11892        animation-timing-function: ease-in-out;
11893        animation-iteration-count: 2;
11894        animation-direction: alternate;
11895        animation-play-state: running;
11896        animation-delay: 100ms;
11897        animation-fill-mode: forwards;
11898        animation-timeline: auto;
11899      }
11900    "#,
11901      indoc! {r#"
11902      .foo {
11903        animation-name: foo, bar;
11904        animation-duration: 90ms;
11905        animation-timing-function: ease-in-out;
11906        animation-iteration-count: 2;
11907        animation-direction: alternate;
11908        animation-play-state: running;
11909        animation-delay: .1s;
11910        animation-fill-mode: forwards;
11911        animation-timeline: auto;
11912      }
11913    "#},
11914    );
11915    test(
11916      r#"
11917      .foo {
11918        animation-name: foo;
11919        animation-duration: 0.09s;
11920        animation-timing-function: ease-in-out;
11921        animation-iteration-count: 2;
11922        animation-direction: alternate;
11923        animation-play-state: running;
11924        animation-delay: 100ms;
11925        animation-fill-mode: forwards;
11926        animation-timeline: scroll();
11927      }
11928    "#,
11929      indoc! {r#"
11930      .foo {
11931        animation: 90ms ease-in-out .1s 2 alternate forwards foo scroll();
11932      }
11933    "#},
11934    );
11935    test(
11936      r#"
11937      .foo {
11938        animation-name: foo;
11939        animation-duration: 0.09s;
11940        animation-timing-function: ease-in-out;
11941        animation-iteration-count: 2;
11942        animation-direction: alternate;
11943        animation-play-state: running;
11944        animation-delay: 100ms;
11945        animation-fill-mode: forwards;
11946        animation-timeline: scroll(), view();
11947      }
11948    "#,
11949      indoc! {r#"
11950      .foo {
11951        animation-name: foo;
11952        animation-duration: 90ms;
11953        animation-timing-function: ease-in-out;
11954        animation-iteration-count: 2;
11955        animation-direction: alternate;
11956        animation-play-state: running;
11957        animation-delay: .1s;
11958        animation-fill-mode: forwards;
11959        animation-timeline: scroll(), view();
11960      }
11961    "#},
11962    );
11963    test(
11964      r#"
11965      .foo {
11966        -webkit-animation-name: foo;
11967        -webkit-animation-duration: 0.09s;
11968        -webkit-animation-timing-function: ease-in-out;
11969        -webkit-animation-iteration-count: 2;
11970        -webkit-animation-direction: alternate;
11971        -webkit-animation-play-state: running;
11972        -webkit-animation-delay: 100ms;
11973        -webkit-animation-fill-mode: forwards;
11974      }
11975    "#,
11976      indoc! {r#"
11977      .foo {
11978        -webkit-animation: 90ms ease-in-out .1s 2 alternate forwards foo;
11979      }
11980    "#},
11981    );
11982    test(
11983      r#"
11984      .foo {
11985        -moz-animation: bar 200ms;
11986        -moz-animation-timing-function: ease-in-out;
11987      }
11988    "#,
11989      indoc! {r#"
11990      .foo {
11991        -moz-animation: .2s ease-in-out bar;
11992      }
11993    "#},
11994    );
11995    test(
11996      r#"
11997      .foo {
11998        -webkit-animation: bar 200ms;
11999        -webkit-animation-timing-function: ease-in-out;
12000        -moz-animation: bar 200ms;
12001        -moz-animation-timing-function: ease-in-out;
12002      }
12003    "#,
12004      indoc! {r#"
12005      .foo {
12006        -webkit-animation: .2s ease-in-out bar;
12007        -moz-animation: .2s ease-in-out bar;
12008      }
12009    "#},
12010    );
12011
12012    prefix_test(
12013      r#"
12014      .foo {
12015        animation: .2s ease-in-out bar;
12016      }
12017    "#,
12018      indoc! {r#"
12019      .foo {
12020        -webkit-animation: .2s ease-in-out bar;
12021        -moz-animation: .2s ease-in-out bar;
12022        animation: .2s ease-in-out bar;
12023      }
12024    "#},
12025      Browsers {
12026        firefox: Some(6 << 16),
12027        safari: Some(6 << 16),
12028        ..Browsers::default()
12029      },
12030    );
12031
12032    prefix_test(
12033      r#"
12034      .foo {
12035        -webkit-animation: .2s ease-in-out bar;
12036        -moz-animation: .2s ease-in-out bar;
12037        animation: .2s ease-in-out bar;
12038      }
12039    "#,
12040      indoc! {r#"
12041      .foo {
12042        animation: .2s ease-in-out bar;
12043      }
12044    "#},
12045      Browsers {
12046        firefox: Some(20 << 16),
12047        safari: Some(14 << 16),
12048        ..Browsers::default()
12049      },
12050    );
12051    prefix_test(
12052      r#"
12053      .foo {
12054        animation: 200ms var(--ease) bar;
12055      }
12056    "#,
12057      indoc! {r#"
12058      .foo {
12059        -webkit-animation: .2s var(--ease) bar;
12060        -moz-animation: .2s var(--ease) bar;
12061        animation: .2s var(--ease) bar;
12062      }
12063    "#},
12064      Browsers {
12065        firefox: Some(6 << 16),
12066        safari: Some(6 << 16),
12067        ..Browsers::default()
12068      },
12069    );
12070
12071    prefix_test(
12072      r#"
12073      .foo {
12074        animation: .2s ease-in-out bar scroll();
12075      }
12076    "#,
12077      indoc! {r#"
12078      .foo {
12079        animation: .2s ease-in-out bar;
12080        animation-timeline: scroll();
12081      }
12082    "#},
12083      Browsers {
12084        safari: Some(16 << 16),
12085        ..Browsers::default()
12086      },
12087    );
12088    prefix_test(
12089      r#"
12090      .foo {
12091        animation: .2s ease-in-out bar scroll();
12092      }
12093    "#,
12094      indoc! {r#"
12095      .foo {
12096        animation: .2s ease-in-out bar scroll();
12097      }
12098    "#},
12099      Browsers {
12100        chrome: Some(120 << 16),
12101        ..Browsers::default()
12102      },
12103    );
12104    prefix_test(
12105      r#"
12106      .foo {
12107        animation: .2s ease-in-out bar scroll();
12108      }
12109    "#,
12110      indoc! {r#"
12111      .foo {
12112        -webkit-animation: .2s ease-in-out bar;
12113        animation: .2s ease-in-out bar;
12114        animation-timeline: scroll();
12115      }
12116    "#},
12117      Browsers {
12118        safari: Some(6 << 16),
12119        ..Browsers::default()
12120      },
12121    );
12122
12123    minify_test(
12124      ".foo { animation-range-start: entry 10% }",
12125      ".foo{animation-range-start:entry 10%}",
12126    );
12127    minify_test(
12128      ".foo { animation-range-start: entry 0% }",
12129      ".foo{animation-range-start:entry}",
12130    );
12131    minify_test(
12132      ".foo { animation-range-start: entry }",
12133      ".foo{animation-range-start:entry}",
12134    );
12135    minify_test(".foo { animation-range-start: 50% }", ".foo{animation-range-start:50%}");
12136    minify_test(
12137      ".foo { animation-range-end: exit 10% }",
12138      ".foo{animation-range-end:exit 10%}",
12139    );
12140    minify_test(
12141      ".foo { animation-range-end: exit 100% }",
12142      ".foo{animation-range-end:exit}",
12143    );
12144    minify_test(".foo { animation-range-end: exit }", ".foo{animation-range-end:exit}");
12145    minify_test(".foo { animation-range-end: 50% }", ".foo{animation-range-end:50%}");
12146    minify_test(
12147      ".foo { animation-range: entry 10% exit 90% }",
12148      ".foo{animation-range:entry 10% exit 90%}",
12149    );
12150    minify_test(
12151      ".foo { animation-range: entry 0% exit 100% }",
12152      ".foo{animation-range:entry exit}",
12153    );
12154    minify_test(".foo { animation-range: entry }", ".foo{animation-range:entry}");
12155    minify_test(
12156      ".foo { animation-range: entry 0% entry 100% }",
12157      ".foo{animation-range:entry}",
12158    );
12159    minify_test(".foo { animation-range: 50% normal }", ".foo{animation-range:50%}");
12160    minify_test(
12161      ".foo { animation-range: normal normal }",
12162      ".foo{animation-range:normal}",
12163    );
12164    test(
12165      r#"
12166      .foo {
12167        animation-range-start: entry 10%;
12168        animation-range-end: exit 90%;
12169      }
12170      "#,
12171      indoc! {r#"
12172      .foo {
12173        animation-range: entry 10% exit 90%;
12174      }
12175      "#},
12176    );
12177    test(
12178      r#"
12179      .foo {
12180        animation-range-start: entry 0%;
12181        animation-range-end: entry 100%;
12182      }
12183      "#,
12184      indoc! {r#"
12185      .foo {
12186        animation-range: entry;
12187      }
12188      "#},
12189    );
12190    test(
12191      r#"
12192      .foo {
12193        animation-range-start: entry 0%;
12194        animation-range-end: exit 100%;
12195      }
12196      "#,
12197      indoc! {r#"
12198      .foo {
12199        animation-range: entry exit;
12200      }
12201      "#},
12202    );
12203    test(
12204      r#"
12205      .foo {
12206        animation-range-start: 10%;
12207        animation-range-end: normal;
12208      }
12209      "#,
12210      indoc! {r#"
12211      .foo {
12212        animation-range: 10%;
12213      }
12214      "#},
12215    );
12216    test(
12217      r#"
12218      .foo {
12219        animation-range-start: 10%;
12220        animation-range-end: 90%;
12221      }
12222      "#,
12223      indoc! {r#"
12224      .foo {
12225        animation-range: 10% 90%;
12226      }
12227      "#},
12228    );
12229    test(
12230      r#"
12231      .foo {
12232        animation-range-start: entry 10%;
12233        animation-range-end: exit 100%;
12234      }
12235      "#,
12236      indoc! {r#"
12237      .foo {
12238        animation-range: entry 10% exit;
12239      }
12240      "#},
12241    );
12242    test(
12243      r#"
12244      .foo {
12245        animation-range-start: 10%;
12246        animation-range-end: exit 90%;
12247      }
12248      "#,
12249      indoc! {r#"
12250      .foo {
12251        animation-range: 10% exit 90%;
12252      }
12253      "#},
12254    );
12255    test(
12256      r#"
12257      .foo {
12258        animation-range-start: entry 10%;
12259        animation-range-end: 90%;
12260      }
12261      "#,
12262      indoc! {r#"
12263      .foo {
12264        animation-range: entry 10% 90%;
12265      }
12266      "#},
12267    );
12268    test(
12269      r#"
12270      .foo {
12271        animation-range: entry;
12272        animation-range-end: 90%;
12273      }
12274      "#,
12275      indoc! {r#"
12276      .foo {
12277        animation-range: entry 90%;
12278      }
12279      "#},
12280    );
12281    test(
12282      r#"
12283      .foo {
12284        animation-range: entry;
12285        animation-range-end: var(--end);
12286      }
12287      "#,
12288      indoc! {r#"
12289      .foo {
12290        animation-range: entry;
12291        animation-range-end: var(--end);
12292      }
12293      "#},
12294    );
12295    test(
12296      r#"
12297      .foo {
12298        animation-range-start: entry 10%, entry 50%;
12299        animation-range-end: exit 90%;
12300      }
12301      "#,
12302      indoc! {r#"
12303      .foo {
12304        animation-range-start: entry 10%, entry 50%;
12305        animation-range-end: exit 90%;
12306      }
12307      "#},
12308    );
12309    test(
12310      r#"
12311      .foo {
12312        animation-range-start: entry 10%, entry 50%;
12313        animation-range-end: exit 90%, exit 100%;
12314      }
12315      "#,
12316      indoc! {r#"
12317      .foo {
12318        animation-range: entry 10% exit 90%, entry 50% exit;
12319      }
12320      "#},
12321    );
12322    test(
12323      r#"
12324      .foo {
12325        animation-range: entry;
12326        animation-range-end: 90%;
12327        animation: spin 100ms;
12328      }
12329      "#,
12330      indoc! {r#"
12331      .foo {
12332        animation: .1s spin;
12333      }
12334      "#},
12335    );
12336    test(
12337      r#"
12338      .foo {
12339        animation: spin 100ms;
12340        animation-range: entry;
12341        animation-range-end: 90%;
12342      }
12343      "#,
12344      indoc! {r#"
12345      .foo {
12346        animation: .1s spin;
12347        animation-range: entry 90%;
12348      }
12349      "#},
12350    );
12351    test(
12352      r#"
12353      .foo {
12354        animation-range: entry;
12355        animation-range-end: 90%;
12356        animation: var(--animation) 100ms;
12357      }
12358      "#,
12359      indoc! {r#"
12360      .foo {
12361        animation: var(--animation) .1s;
12362      }
12363      "#},
12364    );
12365  }
12366
12367  #[test]
12368  fn test_transform() {
12369    minify_test(
12370      ".foo { transform: translate(2px, 3px)",
12371      ".foo{transform:translate(2px,3px)}",
12372    );
12373    minify_test(
12374      ".foo { transform: translate(2px, 0px)",
12375      ".foo{transform:translate(2px)}",
12376    );
12377    minify_test(
12378      ".foo { transform: translate(0px, 2px)",
12379      ".foo{transform:translateY(2px)}",
12380    );
12381    minify_test(".foo { transform: translateX(2px)", ".foo{transform:translate(2px)}");
12382    minify_test(".foo { transform: translateY(2px)", ".foo{transform:translateY(2px)}");
12383    minify_test(".foo { transform: translateZ(2px)", ".foo{transform:translateZ(2px)}");
12384    minify_test(
12385      ".foo { transform: translate3d(2px, 3px, 4px)",
12386      ".foo{transform:translate3d(2px,3px,4px)}",
12387    );
12388    minify_test(
12389      ".foo { transform: translate3d(10%, 20%, 4px)",
12390      ".foo{transform:translate3d(10%,20%,4px)}",
12391    );
12392    minify_test(
12393      ".foo { transform: translate3d(2px, 0px, 0px)",
12394      ".foo{transform:translate(2px)}",
12395    );
12396    minify_test(
12397      ".foo { transform: translate3d(0px, 2px, 0px)",
12398      ".foo{transform:translateY(2px)}",
12399    );
12400    minify_test(
12401      ".foo { transform: translate3d(0px, 0px, 2px)",
12402      ".foo{transform:translateZ(2px)}",
12403    );
12404    minify_test(
12405      ".foo { transform: translate3d(2px, 3px, 0px)",
12406      ".foo{transform:translate(2px,3px)}",
12407    );
12408    minify_test(".foo { transform: scale(2, 3)", ".foo{transform:scale(2,3)}");
12409    minify_test(".foo { transform: scale(10%, 20%)", ".foo{transform:scale(.1,.2)}");
12410    minify_test(".foo { transform: scale(2, 2)", ".foo{transform:scale(2)}");
12411    minify_test(".foo { transform: scale(2, 1)", ".foo{transform:scaleX(2)}");
12412    minify_test(".foo { transform: scale(1, 2)", ".foo{transform:scaleY(2)}");
12413    minify_test(".foo { transform: scaleX(2)", ".foo{transform:scaleX(2)}");
12414    minify_test(".foo { transform: scaleY(2)", ".foo{transform:scaleY(2)}");
12415    minify_test(".foo { transform: scaleZ(2)", ".foo{transform:scaleZ(2)}");
12416    minify_test(".foo { transform: scale3d(2, 3, 4)", ".foo{transform:scale3d(2,3,4)}");
12417    minify_test(".foo { transform: scale3d(2, 1, 1)", ".foo{transform:scaleX(2)}");
12418    minify_test(".foo { transform: scale3d(1, 2, 1)", ".foo{transform:scaleY(2)}");
12419    minify_test(".foo { transform: scale3d(1, 1, 2)", ".foo{transform:scaleZ(2)}");
12420    minify_test(".foo { transform: scale3d(2, 2, 1)", ".foo{transform:scale(2)}");
12421    minify_test(".foo { transform: rotate(20deg)", ".foo{transform:rotate(20deg)}");
12422    minify_test(".foo { transform: rotateX(20deg)", ".foo{transform:rotateX(20deg)}");
12423    minify_test(".foo { transform: rotateY(20deg)", ".foo{transform:rotateY(20deg)}");
12424    minify_test(".foo { transform: rotateZ(20deg)", ".foo{transform:rotate(20deg)}");
12425    minify_test(".foo { transform: rotate(360deg)", ".foo{transform:rotate(360deg)}");
12426    minify_test(
12427      ".foo { transform: rotate3d(2, 3, 4, 20deg)",
12428      ".foo{transform:rotate3d(2,3,4,20deg)}",
12429    );
12430    minify_test(
12431      ".foo { transform: rotate3d(1, 0, 0, 20deg)",
12432      ".foo{transform:rotateX(20deg)}",
12433    );
12434    minify_test(
12435      ".foo { transform: rotate3d(0, 1, 0, 20deg)",
12436      ".foo{transform:rotateY(20deg)}",
12437    );
12438    minify_test(
12439      ".foo { transform: rotate3d(0, 0, 1, 20deg)",
12440      ".foo{transform:rotate(20deg)}",
12441    );
12442    minify_test(".foo { transform: rotate(405deg)}", ".foo{transform:rotate(405deg)}");
12443    minify_test(".foo { transform: rotateX(405deg)}", ".foo{transform:rotateX(405deg)}");
12444    minify_test(".foo { transform: rotateY(405deg)}", ".foo{transform:rotateY(405deg)}");
12445    minify_test(".foo { transform: rotate(-200deg)}", ".foo{transform:rotate(-200deg)}");
12446    minify_test(".foo { transform: rotate(0)", ".foo{transform:rotate(0)}");
12447    minify_test(".foo { transform: rotate(0deg)", ".foo{transform:rotate(0)}");
12448    minify_test(
12449      ".foo { transform: rotateX(-200deg)}",
12450      ".foo{transform:rotateX(-200deg)}",
12451    );
12452    minify_test(
12453      ".foo { transform: rotateY(-200deg)}",
12454      ".foo{transform:rotateY(-200deg)}",
12455    );
12456    minify_test(
12457      ".foo { transform: rotate3d(1, 1, 0, -200deg)",
12458      ".foo{transform:rotate3d(1,1,0,-200deg)}",
12459    );
12460    minify_test(".foo { transform: skew(20deg)", ".foo{transform:skew(20deg)}");
12461    minify_test(".foo { transform: skew(20deg, 0deg)", ".foo{transform:skew(20deg)}");
12462    minify_test(".foo { transform: skew(0deg, 20deg)", ".foo{transform:skewY(20deg)}");
12463    minify_test(".foo { transform: skewX(20deg)", ".foo{transform:skew(20deg)}");
12464    minify_test(".foo { transform: skewY(20deg)", ".foo{transform:skewY(20deg)}");
12465    minify_test(
12466      ".foo { transform: perspective(10px)",
12467      ".foo{transform:perspective(10px)}",
12468    );
12469    minify_test(
12470      ".foo { transform: matrix(1, 2, -1, 1, 80, 80)",
12471      ".foo{transform:matrix(1,2,-1,1,80,80)}",
12472    );
12473    minify_test(
12474      ".foo { transform: matrix3d(1, 0, 0, 0, 0, 1, 6, 0, 0, 0, 1, 0, 50, 100, 0, 1.1)",
12475      ".foo{transform:matrix3d(1,0,0,0,0,1,6,0,0,0,1,0,50,100,0,1.1)}",
12476    );
12477    // TODO: Re-enable with a better solution
12478    //       See: https://github.com/parcel-bundler/lightningcss/issues/288
12479    // minify_test(
12480    //   ".foo{transform:translate(100px,200px) rotate(45deg) skew(10deg) scale(2)}",
12481    //   ".foo{transform:matrix(1.41421,1.41421,-1.16485,1.66358,100,200)}",
12482    // );
12483    // minify_test(
12484    //   ".foo{transform:translate(200px,300px) translate(100px,200px) scale(2)}",
12485    //   ".foo{transform:matrix(2,0,0,2,300,500)}",
12486    // );
12487    minify_test(
12488      ".foo{transform:translate(100px,200px) rotate(45deg)}",
12489      ".foo{transform:translate(100px,200px)rotate(45deg)}",
12490    );
12491    minify_test(
12492      ".foo{transform:rotate3d(1, 1, 1, 45deg) translate3d(100px, 100px, 10px)}",
12493      ".foo{transform:rotate3d(1,1,1,45deg)translate3d(100px,100px,10px)}",
12494    );
12495    // TODO: Re-enable with a better solution
12496    //       See: https://github.com/parcel-bundler/lightningcss/issues/288
12497    // minify_test(
12498    //   ".foo{transform:translate3d(100px, 100px, 10px) skew(10deg) scale3d(2, 3, 4)}",
12499    //   ".foo{transform:matrix3d(2,0,0,0,.528981,3,0,0,0,0,4,0,100,100,10,1)}",
12500    // );
12501    // minify_test(
12502    //   ".foo{transform:matrix3d(0.804737854124365, 0.5058793634016805, -0.31061721752604554, 0, -0.31061721752604554, 0.804737854124365, 0.5058793634016805, 0, 0.5058793634016805, -0.31061721752604554, 0.804737854124365, 0, 100, 100, 10, 1)}",
12503    //   ".foo{transform:translate3d(100px,100px,10px)rotate3d(1,1,1,45deg)}"
12504    // );
12505    // minify_test(
12506    //   ".foo{transform:matrix3d(1, 0, 0, 0, 0, 0.7071067811865476, 0.7071067811865475, 0, 0, -0.7071067811865475, 0.7071067811865476, 0, 100, 100, 10, 1)}",
12507    //   ".foo{transform:translate3d(100px,100px,10px)rotateX(45deg)}"
12508    // );
12509    // minify_test(
12510    //   ".foo{transform:translate3d(100px, 200px, 10px) translate(100px, 100px)}",
12511    //   ".foo{transform:translate3d(200px,300px,10px)}",
12512    // );
12513    // minify_test(
12514    //   ".foo{transform:rotate(45deg) rotate(45deg)}",
12515    //   ".foo{transform:rotate(90deg)}",
12516    // );
12517    // minify_test(
12518    //   ".foo{transform:matrix(0.7071067811865476, 0.7071067811865475, -0.7071067811865475, 0.7071067811865476, 100, 100)}",
12519    //   ".foo{transform:translate(100px,100px)rotate(45deg)}"
12520    // );
12521    // minify_test(
12522    //   ".foo{transform:translateX(2in) translateX(50px)}",
12523    //   ".foo{transform:translate(242px)}",
12524    // );
12525    minify_test(
12526      ".foo{transform:translateX(calc(2in + 50px))}",
12527      ".foo{transform:translate(242px)}",
12528    );
12529    minify_test(".foo{transform:translateX(50%)}", ".foo{transform:translate(50%)}");
12530    minify_test(
12531      ".foo{transform:translateX(calc(50% - 100px + 20px))}",
12532      ".foo{transform:translate(calc(50% - 80px))}",
12533    );
12534    minify_test(
12535      ".foo{transform:rotate(calc(10deg + 20deg))}",
12536      ".foo{transform:rotate(30deg)}",
12537    );
12538    minify_test(
12539      ".foo{transform:rotate(calc(10deg + 0.349066rad))}",
12540      ".foo{transform:rotate(30deg)}",
12541    );
12542    minify_test(
12543      ".foo{transform:rotate(calc(10deg + 1.5turn))}",
12544      ".foo{transform:rotate(550deg)}",
12545    );
12546    minify_test(
12547      ".foo{transform:rotate(calc(10deg * 2))}",
12548      ".foo{transform:rotate(20deg)}",
12549    );
12550    minify_test(
12551      ".foo{transform:rotate(calc(-10deg * 2))}",
12552      ".foo{transform:rotate(-20deg)}",
12553    );
12554    minify_test(
12555      ".foo{transform:rotate(calc(10deg + var(--test)))}",
12556      ".foo{transform:rotate(calc(10deg + var(--test)))}",
12557    );
12558    minify_test(".foo { transform: scale(calc(10% + 20%))", ".foo{transform:scale(.3)}");
12559    minify_test(".foo { transform: scale(calc(.1 + .2))", ".foo{transform:scale(.3)}");
12560
12561    minify_test(
12562      ".foo { -webkit-transform: scale(calc(10% + 20%))",
12563      ".foo{-webkit-transform:scale(.3)}",
12564    );
12565
12566    minify_test(".foo { translate: 1px 2px 3px }", ".foo{translate:1px 2px 3px}");
12567    minify_test(".foo { translate: 1px 0px 0px }", ".foo{translate:1px}");
12568    minify_test(".foo { translate: 1px 2px 0px }", ".foo{translate:1px 2px}");
12569    minify_test(".foo { translate: 1px 0px 2px }", ".foo{translate:1px 0 2px}");
12570    minify_test(".foo { translate: none }", ".foo{translate:none}");
12571    minify_test(".foo { rotate: 10deg }", ".foo{rotate:10deg}");
12572    minify_test(".foo { rotate: z 10deg }", ".foo{rotate:10deg}");
12573    minify_test(".foo { rotate: 0 0 1 10deg }", ".foo{rotate:10deg}");
12574    minify_test(".foo { rotate: x 10deg }", ".foo{rotate:x 10deg}");
12575    minify_test(".foo { rotate: 1 0 0 10deg }", ".foo{rotate:x 10deg}");
12576    minify_test(".foo { rotate: y 10deg }", ".foo{rotate:y 10deg}");
12577    minify_test(".foo { rotate: 0 1 0 10deg }", ".foo{rotate:y 10deg}");
12578    minify_test(".foo { rotate: 1 1 1 10deg }", ".foo{rotate:1 1 1 10deg}");
12579    minify_test(".foo { rotate: 0 0 1 0deg }", ".foo{rotate:none}");
12580    minify_test(".foo { rotate: none }", ".foo{rotate:none}");
12581    minify_test(".foo { scale: 1 }", ".foo{scale:1}");
12582    minify_test(".foo { scale: 1 1 }", ".foo{scale:1}");
12583    minify_test(".foo { scale: 1 1 1 }", ".foo{scale:1}");
12584    minify_test(".foo { scale: none }", ".foo{scale:none}");
12585    minify_test(".foo { scale: 1 0 }", ".foo{scale:1 0}");
12586    minify_test(".foo { scale: 1 0 1 }", ".foo{scale:1 0}");
12587    minify_test(".foo { scale: 1 0 0 }", ".foo{scale:1 0 0}");
12588
12589    // TODO: Re-enable with a better solution
12590    //       See: https://github.com/parcel-bundler/lightningcss/issues/288
12591    // minify_test(".foo { transform: scale(3); scale: 0.5 }", ".foo{transform:scale(1.5)}");
12592    minify_test(".foo { scale: 0.5; transform: scale(3); }", ".foo{transform:scale(3)}");
12593
12594    prefix_test(
12595      r#"
12596      .foo {
12597        transform: scale(0.5);
12598      }
12599    "#,
12600      indoc! {r#"
12601      .foo {
12602        -webkit-transform: scale(.5);
12603        -moz-transform: scale(.5);
12604        transform: scale(.5);
12605      }
12606    "#},
12607      Browsers {
12608        firefox: Some(6 << 16),
12609        safari: Some(6 << 16),
12610        ..Browsers::default()
12611      },
12612    );
12613
12614    prefix_test(
12615      r#"
12616      .foo {
12617        transform: var(--transform);
12618      }
12619    "#,
12620      indoc! {r#"
12621      .foo {
12622        -webkit-transform: var(--transform);
12623        -moz-transform: var(--transform);
12624        transform: var(--transform);
12625      }
12626    "#},
12627      Browsers {
12628        firefox: Some(6 << 16),
12629        safari: Some(6 << 16),
12630        ..Browsers::default()
12631      },
12632    );
12633
12634    test(
12635      r#"
12636      .foo {
12637        transform: translateX(-50%);
12638        transform: translateX(20px);
12639      }
12640      "#,
12641      indoc! {r#"
12642      .foo {
12643        transform: translateX(20px);
12644      }
12645      "#},
12646    );
12647  }
12648
12649  #[test]
12650  pub fn test_gradients() {
12651    minify_test(
12652      ".foo { background: linear-gradient(yellow, blue) }",
12653      ".foo{background:linear-gradient(#ff0,#00f)}",
12654    );
12655    minify_test(
12656      ".foo { background: linear-gradient(to bottom, yellow, blue); }",
12657      ".foo{background:linear-gradient(#ff0,#00f)}",
12658    );
12659    minify_test(
12660      ".foo { background: linear-gradient(180deg, yellow, blue); }",
12661      ".foo{background:linear-gradient(#ff0,#00f)}",
12662    );
12663    minify_test(
12664      ".foo { background: linear-gradient(0.5turn, yellow, blue); }",
12665      ".foo{background:linear-gradient(#ff0,#00f)}",
12666    );
12667    minify_test(
12668      ".foo { background: linear-gradient(yellow 10%, blue 20%) }",
12669      ".foo{background:linear-gradient(#ff0 10%,#00f 20%)}",
12670    );
12671    minify_test(
12672      ".foo { background: linear-gradient(to top, blue, yellow); }",
12673      ".foo{background:linear-gradient(#ff0,#00f)}",
12674    );
12675    minify_test(
12676      ".foo { background: linear-gradient(to top, blue 10%, yellow 20%); }",
12677      ".foo{background:linear-gradient(#ff0 80%,#00f 90%)}",
12678    );
12679    minify_test(
12680      ".foo { background: linear-gradient(to top, blue 10px, yellow 20px); }",
12681      ".foo{background:linear-gradient(0deg,#00f 10px,#ff0 20px)}",
12682    );
12683    minify_test(
12684      ".foo { background: linear-gradient(135deg, yellow, blue); }",
12685      ".foo{background:linear-gradient(135deg,#ff0,#00f)}",
12686    );
12687    minify_test(
12688      ".foo { background: linear-gradient(yellow, blue 20%, #0f0); }",
12689      ".foo{background:linear-gradient(#ff0,#00f 20%,#0f0)}",
12690    );
12691    minify_test(
12692      ".foo { background: linear-gradient(to top right, red, white, blue) }",
12693      ".foo{background:linear-gradient(to top right,red,#fff,#00f)}",
12694    );
12695    minify_test(
12696      ".foo { background: linear-gradient(yellow, blue calc(10% * 2), #0f0); }",
12697      ".foo{background:linear-gradient(#ff0,#00f 20%,#0f0)}",
12698    );
12699    minify_test(
12700      ".foo { background: linear-gradient(yellow, 20%, blue); }",
12701      ".foo{background:linear-gradient(#ff0,20%,#00f)}",
12702    );
12703    minify_test(
12704      ".foo { background: linear-gradient(yellow, 50%, blue); }",
12705      ".foo{background:linear-gradient(#ff0,#00f)}",
12706    );
12707    minify_test(
12708      ".foo { background: linear-gradient(yellow, 20px, blue); }",
12709      ".foo{background:linear-gradient(#ff0,20px,#00f)}",
12710    );
12711    minify_test(
12712      ".foo { background: linear-gradient(yellow, 50px, blue); }",
12713      ".foo{background:linear-gradient(#ff0,50px,#00f)}",
12714    );
12715    minify_test(
12716      ".foo { background: linear-gradient(yellow, 50px, blue); }",
12717      ".foo{background:linear-gradient(#ff0,50px,#00f)}",
12718    );
12719    minify_test(
12720      ".foo { background: linear-gradient(yellow, red 30% 40%, blue); }",
12721      ".foo{background:linear-gradient(#ff0,red 30% 40%,#00f)}",
12722    );
12723    minify_test(
12724      ".foo { background: linear-gradient(yellow, red 30%, red 40%, blue); }",
12725      ".foo{background:linear-gradient(#ff0,red 30% 40%,#00f)}",
12726    );
12727    minify_test(
12728      ".foo { background: linear-gradient(0, yellow, blue); }",
12729      ".foo{background:linear-gradient(#00f,#ff0)}",
12730    );
12731    minify_test(
12732      ".foo { background: -webkit-linear-gradient(yellow, blue) }",
12733      ".foo{background:-webkit-linear-gradient(#ff0,#00f)}",
12734    );
12735    minify_test(
12736      ".foo { background: -webkit-linear-gradient(bottom, yellow, blue); }",
12737      ".foo{background:-webkit-linear-gradient(#ff0,#00f)}",
12738    );
12739    minify_test(
12740      ".foo { background: -webkit-linear-gradient(top right, red, white, blue) }",
12741      ".foo{background:-webkit-linear-gradient(top right,red,#fff,#00f)}",
12742    );
12743    minify_test(
12744      ".foo { background: -moz-linear-gradient(yellow, blue) }",
12745      ".foo{background:-moz-linear-gradient(#ff0,#00f)}",
12746    );
12747    minify_test(
12748      ".foo { background: -moz-linear-gradient(bottom, yellow, blue); }",
12749      ".foo{background:-moz-linear-gradient(#ff0,#00f)}",
12750    );
12751    minify_test(
12752      ".foo { background: -moz-linear-gradient(top right, red, white, blue) }",
12753      ".foo{background:-moz-linear-gradient(top right,red,#fff,#00f)}",
12754    );
12755    minify_test(
12756      ".foo { background: -o-linear-gradient(yellow, blue) }",
12757      ".foo{background:-o-linear-gradient(#ff0,#00f)}",
12758    );
12759    minify_test(
12760      ".foo { background: -o-linear-gradient(bottom, yellow, blue); }",
12761      ".foo{background:-o-linear-gradient(#ff0,#00f)}",
12762    );
12763    minify_test(
12764      ".foo { background: -o-linear-gradient(top right, red, white, blue) }",
12765      ".foo{background:-o-linear-gradient(top right,red,#fff,#00f)}",
12766    );
12767    minify_test(
12768      ".foo { background: -webkit-gradient(linear, left top, left bottom, from(blue), to(yellow)) }",
12769      ".foo{background:-webkit-gradient(linear,0 0,0 100%,from(#00f),to(#ff0))}",
12770    );
12771    minify_test(
12772      ".foo { background: -webkit-gradient(linear, left top, left bottom, from(blue), color-stop(50%, red), to(yellow)) }",
12773      ".foo{background:-webkit-gradient(linear,0 0,0 100%,from(#00f),color-stop(.5,red),to(#ff0))}"
12774    );
12775    minify_test(
12776      ".foo { background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, blue), color-stop(50%, red), color-stop(100%, yellow)) }",
12777      ".foo{background:-webkit-gradient(linear,0 0,0 100%,from(#00f),color-stop(.5,red),to(#ff0))}"
12778    );
12779    minify_test(
12780      ".foo { background: repeating-linear-gradient(yellow 10px, blue 50px) }",
12781      ".foo{background:repeating-linear-gradient(#ff0 10px,#00f 50px)}",
12782    );
12783    minify_test(
12784      ".foo { background: -webkit-repeating-linear-gradient(yellow 10px, blue 50px) }",
12785      ".foo{background:-webkit-repeating-linear-gradient(#ff0 10px,#00f 50px)}",
12786    );
12787    minify_test(
12788      ".foo { background: -moz-repeating-linear-gradient(yellow 10px, blue 50px) }",
12789      ".foo{background:-moz-repeating-linear-gradient(#ff0 10px,#00f 50px)}",
12790    );
12791    minify_test(
12792      ".foo { background: -o-repeating-linear-gradient(yellow 10px, blue 50px) }",
12793      ".foo{background:-o-repeating-linear-gradient(#ff0 10px,#00f 50px)}",
12794    );
12795    minify_test(
12796      ".foo { background: radial-gradient(yellow, blue) }",
12797      ".foo{background:radial-gradient(#ff0,#00f)}",
12798    );
12799    minify_test(
12800      ".foo { background: radial-gradient(at top left, yellow, blue) }",
12801      ".foo{background:radial-gradient(at 0 0,#ff0,#00f)}",
12802    );
12803    minify_test(
12804      ".foo { background: radial-gradient(5em circle at top left, yellow, blue) }",
12805      ".foo{background:radial-gradient(5em at 0 0,#ff0,#00f)}",
12806    );
12807    minify_test(
12808      ".foo { background: radial-gradient(circle at 100%, #333, #333 50%, #eee 75%, #333 75%) }",
12809      ".foo{background:radial-gradient(circle at 100%,#333,#333 50%,#eee 75%,#333 75%)}",
12810    );
12811    minify_test(
12812      ".foo { background: radial-gradient(farthest-corner circle at 100% 50%, #333, #333 50%, #eee 75%, #333 75%) }",
12813      ".foo{background:radial-gradient(circle at 100%,#333,#333 50%,#eee 75%,#333 75%)}"
12814    );
12815    minify_test(
12816      ".foo { background: radial-gradient(farthest-corner circle at 50% 50%, #333, #333 50%, #eee 75%, #333 75%) }",
12817      ".foo{background:radial-gradient(circle,#333,#333 50%,#eee 75%,#333 75%)}"
12818    );
12819    minify_test(
12820      ".foo { background: radial-gradient(ellipse at top, #e66465, transparent) }",
12821      ".foo{background:radial-gradient(at top,#e66465,#0000)}",
12822    );
12823    minify_test(
12824      ".foo { background: radial-gradient(20px, yellow, blue) }",
12825      ".foo{background:radial-gradient(20px,#ff0,#00f)}",
12826    );
12827    minify_test(
12828      ".foo { background: radial-gradient(circle 20px, yellow, blue) }",
12829      ".foo{background:radial-gradient(20px,#ff0,#00f)}",
12830    );
12831    minify_test(
12832      ".foo { background: radial-gradient(20px 40px, yellow, blue) }",
12833      ".foo{background:radial-gradient(20px 40px,#ff0,#00f)}",
12834    );
12835    minify_test(
12836      ".foo { background: radial-gradient(ellipse 20px 40px, yellow, blue) }",
12837      ".foo{background:radial-gradient(20px 40px,#ff0,#00f)}",
12838    );
12839    minify_test(
12840      ".foo { background: radial-gradient(ellipse calc(20px + 10px) 40px, yellow, blue) }",
12841      ".foo{background:radial-gradient(30px 40px,#ff0,#00f)}",
12842    );
12843    minify_test(
12844      ".foo { background: radial-gradient(circle farthest-side, yellow, blue) }",
12845      ".foo{background:radial-gradient(circle farthest-side,#ff0,#00f)}",
12846    );
12847    minify_test(
12848      ".foo { background: radial-gradient(farthest-side circle, yellow, blue) }",
12849      ".foo{background:radial-gradient(circle farthest-side,#ff0,#00f)}",
12850    );
12851    minify_test(
12852      ".foo { background: radial-gradient(ellipse farthest-side, yellow, blue) }",
12853      ".foo{background:radial-gradient(farthest-side,#ff0,#00f)}",
12854    );
12855    minify_test(
12856      ".foo { background: radial-gradient(farthest-side ellipse, yellow, blue) }",
12857      ".foo{background:radial-gradient(farthest-side,#ff0,#00f)}",
12858    );
12859    minify_test(
12860      ".foo { background: -webkit-radial-gradient(yellow, blue) }",
12861      ".foo{background:-webkit-radial-gradient(#ff0,#00f)}",
12862    );
12863    minify_test(
12864      ".foo { background: -moz-radial-gradient(yellow, blue) }",
12865      ".foo{background:-moz-radial-gradient(#ff0,#00f)}",
12866    );
12867    minify_test(
12868      ".foo { background: -o-radial-gradient(yellow, blue) }",
12869      ".foo{background:-o-radial-gradient(#ff0,#00f)}",
12870    );
12871    minify_test(
12872      ".foo { background: repeating-radial-gradient(circle 20px, yellow, blue) }",
12873      ".foo{background:repeating-radial-gradient(20px,#ff0,#00f)}",
12874    );
12875    minify_test(
12876      ".foo { background: -webkit-repeating-radial-gradient(circle 20px, yellow, blue) }",
12877      ".foo{background:-webkit-repeating-radial-gradient(20px,#ff0,#00f)}",
12878    );
12879    minify_test(
12880      ".foo { background: -moz-repeating-radial-gradient(circle 20px, yellow, blue) }",
12881      ".foo{background:-moz-repeating-radial-gradient(20px,#ff0,#00f)}",
12882    );
12883    minify_test(
12884      ".foo { background: -o-repeating-radial-gradient(circle 20px, yellow, blue) }",
12885      ".foo{background:-o-repeating-radial-gradient(20px,#ff0,#00f)}",
12886    );
12887    minify_test(
12888      ".foo { background: -webkit-gradient(radial, center center, 0, center center, 100, from(blue), to(yellow)) }",
12889      ".foo{background:-webkit-gradient(radial,50% 50%,0,50% 50%,100,from(#00f),to(#ff0))}"
12890    );
12891    minify_test(
12892      ".foo { background: conic-gradient(#f06, gold) }",
12893      ".foo{background:conic-gradient(#f06,gold)}",
12894    );
12895    minify_test(
12896      ".foo { background: conic-gradient(at 50% 50%, #f06, gold) }",
12897      ".foo{background:conic-gradient(#f06,gold)}",
12898    );
12899    minify_test(
12900      ".foo { background: conic-gradient(from 0deg, #f06, gold) }",
12901      ".foo{background:conic-gradient(#f06,gold)}",
12902    );
12903    minify_test(
12904      ".foo { background: conic-gradient(from 0, #f06, gold) }",
12905      ".foo{background:conic-gradient(#f06,gold)}",
12906    );
12907    minify_test(
12908      ".foo { background: conic-gradient(from 0deg at center, #f06, gold) }",
12909      ".foo{background:conic-gradient(#f06,gold)}",
12910    );
12911    minify_test(
12912      ".foo { background: conic-gradient(white -50%, black 150%) }",
12913      ".foo{background:conic-gradient(#fff -50%,#000 150%)}",
12914    );
12915    minify_test(
12916      ".foo { background: conic-gradient(white -180deg, black 540deg) }",
12917      ".foo{background:conic-gradient(#fff -180deg,#000 540deg)}",
12918    );
12919    minify_test(
12920      ".foo { background: conic-gradient(from 45deg, white, black, white) }",
12921      ".foo{background:conic-gradient(from 45deg,#fff,#000,#fff)}",
12922    );
12923    minify_test(
12924      ".foo { background: repeating-conic-gradient(from 45deg, white, black, white) }",
12925      ".foo{background:repeating-conic-gradient(from 45deg,#fff,#000,#fff)}",
12926    );
12927    minify_test(
12928      ".foo { background: repeating-conic-gradient(black 0deg 25%, white 0deg 50%) }",
12929      ".foo{background:repeating-conic-gradient(#000 0deg 25%,#fff 0deg 50%)}",
12930    );
12931
12932    test(
12933      r#"
12934        .foo {
12935          background: -webkit-gradient(linear, left top, left bottom, from(red), to(blue));
12936          background: -webkit-linear-gradient(red, blue);
12937          background: -moz-linear-gradient(red, blue);
12938          background: -o-linear-gradient(red, blue);
12939          background: linear-gradient(red, blue);
12940        }
12941      "#,
12942      indoc! {r#"
12943        .foo {
12944          background: -webkit-gradient(linear, left top, left bottom, from(red), to(#00f));
12945          background: -webkit-linear-gradient(red, #00f);
12946          background: -moz-linear-gradient(red, #00f);
12947          background: -o-linear-gradient(red, #00f);
12948          background: linear-gradient(red, #00f);
12949        }
12950      "#},
12951    );
12952
12953    prefix_test(
12954      r#"
12955      .foo {
12956        background: -webkit-gradient(linear, left top, left bottom, from(red), to(blue));
12957        background: -webkit-linear-gradient(red, blue);
12958        background: -moz-linear-gradient(red, blue);
12959        background: -o-linear-gradient(red, blue);
12960        background: linear-gradient(red, blue);
12961      }
12962      "#,
12963      indoc! {r#"
12964      .foo {
12965        background: linear-gradient(red, #00f);
12966      }
12967      "#},
12968      Browsers {
12969        chrome: Some(95 << 16),
12970        ..Browsers::default()
12971      },
12972    );
12973    prefix_test(
12974      r#"
12975      .foo {
12976        background: -webkit-gradient(linear, left top, left bottom, from(red), to(blue));
12977        background: -webkit-linear-gradient(red, blue);
12978        background: -moz-linear-gradient(red, blue);
12979        background: -o-linear-gradient(red, blue);
12980      }
12981      "#,
12982      indoc! {r#"
12983      .foo {
12984        background: -webkit-gradient(linear, left top, left bottom, from(red), to(#00f));
12985        background: -webkit-linear-gradient(red, #00f);
12986        background: -moz-linear-gradient(red, #00f);
12987        background: -o-linear-gradient(red, #00f);
12988      }
12989      "#},
12990      Browsers {
12991        chrome: Some(95 << 16),
12992        ..Browsers::default()
12993      },
12994    );
12995    prefix_test(
12996      r#"
12997      .foo {
12998        background-image: linear-gradient(red, blue);
12999      }
13000      "#,
13001      indoc! {r#"
13002      .foo {
13003        background-image: -webkit-gradient(linear, 0 0, 0 100%, from(red), to(#00f));
13004        background-image: -webkit-linear-gradient(top, red, #00f);
13005        background-image: linear-gradient(red, #00f);
13006      }
13007      "#},
13008      Browsers {
13009        chrome: Some(8 << 16),
13010        ..Browsers::default()
13011      },
13012    );
13013    prefix_test(
13014      r#"
13015      .foo {
13016        background-image: linear-gradient(to right, red, blue);
13017      }
13018      "#,
13019      indoc! {r#"
13020      .foo {
13021        background-image: -webkit-gradient(linear, 0 0, 100% 0, from(red), to(#00f));
13022        background-image: -webkit-linear-gradient(left, red, #00f);
13023        background-image: linear-gradient(to right, red, #00f);
13024      }
13025      "#},
13026      Browsers {
13027        chrome: Some(8 << 16),
13028        ..Browsers::default()
13029      },
13030    );
13031    prefix_test(
13032      r#"
13033      .foo {
13034        background-image: linear-gradient(to top, red, blue);
13035      }
13036      "#,
13037      indoc! {r#"
13038      .foo {
13039        background-image: -webkit-gradient(linear, 0 100%, 0 0, from(red), to(#00f));
13040        background-image: -webkit-linear-gradient(red, #00f);
13041        background-image: linear-gradient(to top, red, #00f);
13042      }
13043      "#},
13044      Browsers {
13045        chrome: Some(8 << 16),
13046        ..Browsers::default()
13047      },
13048    );
13049    prefix_test(
13050      r#"
13051      .foo {
13052        background-image: linear-gradient(to left, red, blue);
13053      }
13054      "#,
13055      indoc! {r#"
13056      .foo {
13057        background-image: -webkit-gradient(linear, 100% 0, 0 0, from(red), to(#00f));
13058        background-image: -webkit-linear-gradient(right, red, #00f);
13059        background-image: linear-gradient(to left, red, #00f);
13060      }
13061      "#},
13062      Browsers {
13063        chrome: Some(8 << 16),
13064        ..Browsers::default()
13065      },
13066    );
13067    prefix_test(
13068      r#"
13069      .foo {
13070        background-image: linear-gradient(to left bottom, red, blue);
13071      }
13072      "#,
13073      indoc! {r#"
13074      .foo {
13075        background-image: -webkit-gradient(linear, 100% 0, 0 100%, from(red), to(#00f));
13076        background-image: -webkit-linear-gradient(top right, red, #00f);
13077        background-image: linear-gradient(to bottom left, red, #00f);
13078      }
13079      "#},
13080      Browsers {
13081        chrome: Some(8 << 16),
13082        ..Browsers::default()
13083      },
13084    );
13085    prefix_test(
13086      r#"
13087      .foo {
13088        background-image: linear-gradient(to top right, red, blue);
13089      }
13090      "#,
13091      indoc! {r#"
13092      .foo {
13093        background-image: -webkit-gradient(linear, 0 100%, 100% 0, from(red), to(#00f));
13094        background-image: -webkit-linear-gradient(bottom left, red, #00f);
13095        background-image: linear-gradient(to top right, red, #00f);
13096      }
13097      "#},
13098      Browsers {
13099        chrome: Some(8 << 16),
13100        ..Browsers::default()
13101      },
13102    );
13103    prefix_test(
13104      r#"
13105      .foo {
13106        background-image: linear-gradient(90deg, red, blue);
13107      }
13108      "#,
13109      indoc! {r#"
13110      .foo {
13111        background-image: -webkit-gradient(linear, 0 0, 100% 0, from(red), to(#00f));
13112        background-image: -webkit-linear-gradient(0deg, red, #00f);
13113        background-image: linear-gradient(90deg, red, #00f);
13114      }
13115      "#},
13116      Browsers {
13117        chrome: Some(8 << 16),
13118        ..Browsers::default()
13119      },
13120    );
13121    prefix_test(
13122      r#"
13123      .foo {
13124        background-image: linear-gradient(45deg, red, blue);
13125      }
13126      "#,
13127      indoc! {r#"
13128      .foo {
13129        background-image: -webkit-linear-gradient(45deg, red, #00f);
13130        background-image: linear-gradient(45deg, red, #00f);
13131      }
13132      "#},
13133      Browsers {
13134        chrome: Some(8 << 16),
13135        ..Browsers::default()
13136      },
13137    );
13138    prefix_test(
13139      r#"
13140      .foo {
13141        background-image: linear-gradient(red, blue);
13142      }
13143      "#,
13144      indoc! {r#"
13145      .foo {
13146        background-image: -webkit-linear-gradient(top, red, #00f);
13147        background-image: linear-gradient(red, #00f);
13148      }
13149      "#},
13150      Browsers {
13151        chrome: Some(10 << 16),
13152        ..Browsers::default()
13153      },
13154    );
13155    prefix_test(
13156      r#"
13157      .foo {
13158        background-image: radial-gradient(20px, red, blue);
13159      }
13160      "#,
13161      indoc! {r#"
13162      .foo {
13163        background-image: -webkit-gradient(radial, center center, 0, center center, 20, from(red), to(#00f));
13164        background-image: -webkit-radial-gradient(20px, red, #00f);
13165        background-image: radial-gradient(20px, red, #00f);
13166      }
13167      "#},
13168      Browsers {
13169        chrome: Some(8 << 16),
13170        ..Browsers::default()
13171      },
13172    );
13173    prefix_test(
13174      r#"
13175      .foo {
13176        background-image: radial-gradient(20px at top left, red, blue);
13177      }
13178      "#,
13179      indoc! {r#"
13180      .foo {
13181        background-image: -webkit-gradient(radial, left top, 0, left top, 20, from(red), to(#00f));
13182        background-image: -webkit-radial-gradient(20px at 0 0, red, #00f);
13183        background-image: radial-gradient(20px at 0 0, red, #00f);
13184      }
13185      "#},
13186      Browsers {
13187        chrome: Some(8 << 16),
13188        ..Browsers::default()
13189      },
13190    );
13191    prefix_test(
13192      r#"
13193      .foo {
13194        background-image: radial-gradient(red, blue);
13195      }
13196      "#,
13197      indoc! {r#"
13198      .foo {
13199        background-image: -webkit-radial-gradient(red, #00f);
13200        background-image: radial-gradient(red, #00f);
13201      }
13202      "#},
13203      Browsers {
13204        chrome: Some(8 << 16),
13205        ..Browsers::default()
13206      },
13207    );
13208    prefix_test(
13209      r#"
13210      .foo {
13211        background-image: -webkit-gradient(radial, left top, 0, left top, 20, from(red), to(#00f));
13212        background-image: -webkit-radial-gradient(20px at 0% 0%, red, #00f);
13213        background-image: radial-gradient(20px at 0% 0%, red, #00f);
13214      }
13215      "#,
13216      indoc! {r#"
13217      .foo {
13218        background-image: radial-gradient(20px at 0 0, red, #00f);
13219      }
13220      "#},
13221      Browsers {
13222        chrome: Some(30 << 16),
13223        ..Browsers::default()
13224      },
13225    );
13226    prefix_test(
13227      r#"
13228      .foo {
13229        background: -webkit-gradient(radial, left top, 0, left top, 20, from(red), to(#00f));
13230        background: -webkit-radial-gradient(20px at 0% 0%, red, #00f);
13231        background: radial-gradient(20px at 0% 0%, red, #00f);
13232      }
13233      "#,
13234      indoc! {r#"
13235      .foo {
13236        background: radial-gradient(20px at 0 0, red, #00f);
13237      }
13238      "#},
13239      Browsers {
13240        chrome: Some(30 << 16),
13241        ..Browsers::default()
13242      },
13243    );
13244    prefix_test(
13245      r#"
13246      .foo {
13247        background: radial-gradient(red, blue);
13248      }
13249      "#,
13250      indoc! {r#"
13251      .foo {
13252        background: -webkit-radial-gradient(red, #00f);
13253        background: radial-gradient(red, #00f);
13254      }
13255      "#},
13256      Browsers {
13257        chrome: Some(8 << 16),
13258        ..Browsers::default()
13259      },
13260    );
13261    prefix_test(
13262      r#"
13263      .foo {
13264        background: radial-gradient(red, blue), linear-gradient(yellow, red), url(bg.jpg);
13265      }
13266      "#,
13267      indoc! {r#"
13268      .foo {
13269        background: -webkit-gradient(linear, 0 0, 0 100%, from(#ff0), to(red)), url("bg.jpg");
13270        background: -webkit-radial-gradient(red, #00f), -webkit-linear-gradient(top, #ff0, red), url("bg.jpg");
13271        background: -moz-radial-gradient(red, #00f), -moz-linear-gradient(top, #ff0, red), url("bg.jpg");
13272        background: -o-radial-gradient(red, #00f), -o-linear-gradient(top, #ff0, red), url("bg.jpg");
13273        background: radial-gradient(red, #00f), linear-gradient(#ff0, red), url("bg.jpg");
13274      }
13275      "#},
13276      Browsers {
13277        chrome: Some(8 << 16),
13278        firefox: Some(4 << 16),
13279        opera: Some(11 << 16 | 5 << 8),
13280        ..Browsers::default()
13281      },
13282    );
13283
13284    prefix_test(
13285      r#"
13286      .foo {
13287        background: linear-gradient(yellow, red 30% 40%, blue);
13288      }
13289      "#,
13290      indoc! {r#"
13291      .foo {
13292        background: linear-gradient(#ff0, red 30%, red 40%, #00f);
13293      }
13294      "#},
13295      Browsers {
13296        chrome: Some(70 << 16),
13297        ..Browsers::default()
13298      },
13299    );
13300
13301    prefix_test(
13302      r#"
13303      .foo {
13304        background: linear-gradient(yellow, red 30% 40%, blue);
13305      }
13306      "#,
13307      indoc! {r#"
13308      .foo {
13309        background: linear-gradient(#ff0, red 30% 40%, #00f);
13310      }
13311      "#},
13312      Browsers {
13313        chrome: Some(71 << 16),
13314        ..Browsers::default()
13315      },
13316    );
13317
13318    prefix_test(
13319      ".foo { background: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
13320      indoc! { r#"
13321        .foo {
13322          background: linear-gradient(#ff0f0e, #7773ff);
13323          background: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
13324        }
13325      "#},
13326      Browsers {
13327        chrome: Some(90 << 16),
13328        ..Browsers::default()
13329      },
13330    );
13331
13332    prefix_test(
13333      ".foo { background: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
13334      indoc! { r#"
13335        .foo {
13336          background: linear-gradient(#ff0f0e, #7773ff);
13337          background: linear-gradient(color(display-p3 1 .0000153435 -.00000303562), color(display-p3 .440289 .28452 1.23485));
13338          background: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
13339        }
13340      "#},
13341      Browsers {
13342        chrome: Some(90 << 16),
13343        safari: Some(14 << 16),
13344        ..Browsers::default()
13345      },
13346    );
13347
13348    prefix_test(
13349      ".foo { background: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
13350      indoc! { r#"
13351        .foo {
13352          background: -webkit-linear-gradient(top, #ff0f0e, #7773ff);
13353          background: linear-gradient(#ff0f0e, #7773ff);
13354          background: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
13355        }
13356      "#},
13357      Browsers {
13358        chrome: Some(20 << 16),
13359        ..Browsers::default()
13360      },
13361    );
13362
13363    prefix_test(
13364      ".foo { background: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
13365      indoc! { r#"
13366        .foo {
13367          background: -webkit-gradient(linear, 0 0, 0 100%, from(#ff0f0e), to(#7773ff));
13368          background: -webkit-linear-gradient(top, #ff0f0e, #7773ff);
13369          background: linear-gradient(#ff0f0e, #7773ff);
13370          background: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
13371        }
13372      "#},
13373      Browsers {
13374        chrome: Some(8 << 16),
13375        ..Browsers::default()
13376      },
13377    );
13378
13379    prefix_test(
13380      ".foo { background: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
13381      indoc! { r#"
13382        .foo {
13383          background: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
13384        }
13385      "#},
13386      Browsers {
13387        safari: Some(15 << 16),
13388        ..Browsers::default()
13389      },
13390    );
13391
13392    prefix_test(
13393      ".foo { background-image: linear-gradient(oklab(59.686% 0.1009 0.1192), oklab(54.0% -0.10 -0.02)); }",
13394      indoc! { r#"
13395        .foo {
13396          background-image: linear-gradient(lab(52.2319% 40.1449 59.9171), lab(47.7776% -34.2947 -7.65904));
13397        }
13398      "#},
13399      Browsers {
13400        safari: Some(15 << 16),
13401        ..Browsers::default()
13402      },
13403    );
13404
13405    prefix_test(
13406      ".foo { background-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
13407      indoc! { r#"
13408        .foo {
13409          background-image: linear-gradient(#ff0f0e, #7773ff);
13410          background-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
13411        }
13412      "#},
13413      Browsers {
13414        chrome: Some(90 << 16),
13415        ..Browsers::default()
13416      },
13417    );
13418
13419    prefix_test(
13420      ".foo { background-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
13421      indoc! { r#"
13422        .foo {
13423          background-image: linear-gradient(#ff0f0e, #7773ff);
13424          background-image: linear-gradient(color(display-p3 1 .0000153435 -.00000303562), color(display-p3 .440289 .28452 1.23485));
13425          background-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
13426        }
13427      "#},
13428      Browsers {
13429        chrome: Some(90 << 16),
13430        safari: Some(14 << 16),
13431        ..Browsers::default()
13432      },
13433    );
13434
13435    prefix_test(
13436      ".foo { background-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
13437      indoc! { r#"
13438        .foo {
13439          background-image: -webkit-linear-gradient(top, #ff0f0e, #7773ff);
13440          background-image: linear-gradient(#ff0f0e, #7773ff);
13441          background-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
13442        }
13443      "#},
13444      Browsers {
13445        chrome: Some(20 << 16),
13446        ..Browsers::default()
13447      },
13448    );
13449
13450    prefix_test(
13451      ".foo { background-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
13452      indoc! { r#"
13453        .foo {
13454          background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ff0f0e), to(#7773ff));
13455          background-image: -webkit-linear-gradient(top, #ff0f0e, #7773ff);
13456          background-image: linear-gradient(#ff0f0e, #7773ff);
13457          background-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
13458        }
13459      "#},
13460      Browsers {
13461        chrome: Some(8 << 16),
13462        ..Browsers::default()
13463      },
13464    );
13465
13466    prefix_test(
13467      ".foo { background-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
13468      indoc! { r#"
13469        .foo {
13470          background-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
13471        }
13472      "#},
13473      Browsers {
13474        safari: Some(15 << 16),
13475        ..Browsers::default()
13476      },
13477    );
13478
13479    prefix_test(
13480      ".foo { background-image: linear-gradient(oklab(59.686% 0.1009 0.1192), oklab(54.0% -0.10 -0.02)); }",
13481      indoc! { r#"
13482        .foo {
13483          background-image: linear-gradient(lab(52.2319% 40.1449 59.9171), lab(47.7776% -34.2947 -7.65904));
13484        }
13485      "#},
13486      Browsers {
13487        safari: Some(15 << 16),
13488        ..Browsers::default()
13489      },
13490    );
13491
13492    // Test cases from https://github.com/postcss/autoprefixer/blob/541295c0e6dd348db2d3f52772b59cd403c59d29/test/cases/gradient.css
13493    prefix_test(
13494      r#"
13495        a {
13496          background: linear-gradient(350.5deg, white, black), linear-gradient(-130deg, black, white), linear-gradient(45deg, black, white);
13497        }
13498        b {
13499          background-image: linear-gradient(rgba(0,0,0,1), white), linear-gradient(white, black);
13500        }
13501        strong {
13502          background: linear-gradient(to top, transparent, rgba(0, 0, 0, 0.8) 20px, #000 30px, #000) no-repeat;
13503        }
13504        div {
13505          background-image: radial-gradient(to left, white, black), repeating-linear-gradient(to bottom right, black, white), repeating-radial-gradient(to top, aqua, red);
13506        }
13507        .old-radial {
13508          background: radial-gradient(0 50%, ellipse farthest-corner, black, white);
13509        }
13510        .simple1 {
13511          background: linear-gradient(black, white);
13512        }
13513        .simple2 {
13514          background: linear-gradient(to left, black 0%, rgba(0, 0, 0, 0.5)50%, white 100%);
13515        }
13516        .simple3 {
13517          background: linear-gradient(to left, black 50%, white 100%);
13518        }
13519        .simple4 {
13520          background: linear-gradient(to right top, black, white);
13521        }
13522        .direction {
13523          background: linear-gradient(top left, black, rgba(0, 0, 0, 0.5), white);
13524        }
13525        .silent {
13526          background: -webkit-linear-gradient(top left, black, white);
13527        }
13528        .radial {
13529          background: radial-gradient(farthest-side at 0 50%, white, black);
13530        }
13531        .second {
13532          background: red linear-gradient(red, blue);
13533          background: url('logo.png'), linear-gradient(#fff, #000);
13534        }
13535        .px {
13536          background: linear-gradient(black 0, white 100px);
13537        }
13538        .list {
13539          list-style-image: linear-gradient(white, black);
13540        }
13541        .mask {
13542          mask: linear-gradient(white, black);
13543        }
13544        .newline {
13545          background-image:
13546              linear-gradient( white, black ),
13547              linear-gradient( black, white );
13548        }
13549        .convert {
13550          background: linear-gradient(0deg, white, black);
13551          background: linear-gradient(90deg, white, black);
13552          background: linear-gradient(180deg, white, black);
13553          background: linear-gradient(270deg, white, black);
13554        }
13555        .grad {
13556          background: linear-gradient(1grad, white, black);
13557        }
13558        .rad {
13559          background: linear-gradient(1rad, white, black);
13560        }
13561        .turn {
13562          background: linear-gradient(0.3turn, white, black);
13563        }
13564        .norm {
13565          background: linear-gradient(-90deg, white, black);
13566        }
13567        .mask {
13568          mask-image: radial-gradient(circle at 86% 86%, transparent 8px, black 8px);
13569        }
13570        .cover {
13571          background: radial-gradient(ellipse cover at center, white, black);
13572        }
13573        .contain {
13574          background: radial-gradient(contain at center, white, black);
13575        }
13576        .no-div {
13577          background: linear-gradient(black);
13578        }
13579        .background-shorthand {
13580          background: radial-gradient(#FFF, transparent) 0 0 / cover no-repeat #F0F;
13581        }
13582        .background-advanced {
13583          background: radial-gradient(ellipse farthest-corner at 5px 15px, rgba(214, 168, 18, 0.7) 0%, rgba(255, 21, 177, 0.7) 50%, rgba(210, 7, 148, 0.7) 95%),
13584                      radial-gradient(#FFF, transparent),
13585                      url(path/to/image.jpg) 50%/cover;
13586        }
13587        .multiradial {
13588          mask-image: radial-gradient(circle closest-corner at 100% 50%, #000, transparent);
13589        }
13590        .broken {
13591          mask-image: radial-gradient(white, black);
13592        }
13593        .loop {
13594          background-image: url("https://test.com/lol(test.png"), radial-gradient(yellow, black, yellow);
13595        }
13596        .unitless-zero {
13597          background-image: linear-gradient(0, green, blue);
13598          background: repeating-linear-gradient(0, blue, red 33.3%)
13599        }
13600        .zero-grad {
13601          background: linear-gradient(0grad, green, blue);
13602          background-image: repeating-linear-gradient(0grad, blue, red 33.3%)
13603        }
13604        .zero-rad {
13605          background: linear-gradient(0rad, green, blue);
13606        }
13607        .zero-turn {
13608          background: linear-gradient(0turn, green, blue);
13609        }
13610      "#,
13611      indoc! { r#"
13612        a {
13613          background: -webkit-linear-gradient(99.5deg, #fff, #000), -webkit-linear-gradient(220deg, #000, #fff), -webkit-linear-gradient(45deg, #000, #fff);
13614          background: -o-linear-gradient(99.5deg, #fff, #000), -o-linear-gradient(220deg, #000, #fff), -o-linear-gradient(45deg, #000, #fff);
13615          background: linear-gradient(350.5deg, #fff, #000), linear-gradient(-130deg, #000, #fff), linear-gradient(45deg, #000, #fff);
13616        }
13617
13618        b {
13619          background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#000), to(#fff)), -webkit-gradient(linear, 0 0, 0 100%, from(#fff), to(#000));
13620          background-image: -webkit-linear-gradient(top, #000, #fff), -webkit-linear-gradient(top, #fff, #000);
13621          background-image: -o-linear-gradient(top, #000, #fff), -o-linear-gradient(top, #fff, #000);
13622          background-image: linear-gradient(#000, #fff), linear-gradient(#fff, #000);
13623        }
13624
13625        strong {
13626          background: -webkit-linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, .8) 20px, #000 30px, #000) no-repeat;
13627          background: -o-linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, .8) 20px, #000 30px, #000) no-repeat;
13628          background: linear-gradient(to top, rgba(0, 0, 0, 0), rgba(0, 0, 0, .8) 20px, #000 30px, #000) no-repeat;
13629        }
13630
13631        div {
13632          background-image: radial-gradient(to left, white, black), repeating-linear-gradient(to bottom right, black, white), repeating-radial-gradient(to top, aqua, red);
13633        }
13634
13635        .old-radial {
13636          background: radial-gradient(0 50%, ellipse farthest-corner, black, white);
13637        }
13638
13639        .simple1 {
13640          background: -webkit-gradient(linear, 0 0, 0 100%, from(#000), to(#fff));
13641          background: -webkit-linear-gradient(top, #000, #fff);
13642          background: -o-linear-gradient(top, #000, #fff);
13643          background: linear-gradient(#000, #fff);
13644        }
13645
13646        .simple2 {
13647          background: -webkit-gradient(linear, 100% 0, 0 0, from(#000), color-stop(.5, rgba(0, 0, 0, .5)), to(#fff));
13648          background: -webkit-linear-gradient(right, #000 0%, rgba(0, 0, 0, .5) 50%, #fff 100%);
13649          background: -o-linear-gradient(right, #000 0%, rgba(0, 0, 0, .5) 50%, #fff 100%);
13650          background: linear-gradient(to left, #000 0%, rgba(0, 0, 0, .5) 50%, #fff 100%);
13651        }
13652
13653        .simple3 {
13654          background: -webkit-gradient(linear, 100% 0, 0 0, color-stop(.5, #000), to(#fff));
13655          background: -webkit-linear-gradient(right, #000 50%, #fff 100%);
13656          background: -o-linear-gradient(right, #000 50%, #fff 100%);
13657          background: linear-gradient(to left, #000 50%, #fff 100%);
13658        }
13659
13660        .simple4 {
13661          background: -webkit-gradient(linear, 0 100%, 100% 0, from(#000), to(#fff));
13662          background: -webkit-linear-gradient(bottom left, #000, #fff);
13663          background: -o-linear-gradient(bottom left, #000, #fff);
13664          background: linear-gradient(to top right, #000, #fff);
13665        }
13666
13667        .direction {
13668          background: linear-gradient(top left, black, rgba(0, 0, 0, .5), white);
13669        }
13670
13671        .silent {
13672          background: -webkit-gradient(linear, 100% 100%, 0 0, from(#000), to(#fff));
13673          background: -webkit-linear-gradient(top left, #000, #fff);
13674        }
13675
13676        .radial {
13677          background: -webkit-radial-gradient(farthest-side at 0, #fff, #000);
13678          background: -o-radial-gradient(farthest-side at 0, #fff, #000);
13679          background: radial-gradient(farthest-side at 0, #fff, #000);
13680        }
13681
13682        .second {
13683          background: red -webkit-gradient(linear, 0 0, 0 100%, from(red), to(#00f));
13684          background: red -webkit-linear-gradient(top, red, #00f);
13685          background: red -o-linear-gradient(top, red, #00f);
13686          background: red linear-gradient(red, #00f);
13687          background: url("logo.png"), linear-gradient(#fff, #000);
13688        }
13689
13690        .px {
13691          background: -webkit-linear-gradient(top, #000 0, #fff 100px);
13692          background: -o-linear-gradient(top, #000 0, #fff 100px);
13693          background: linear-gradient(#000 0, #fff 100px);
13694        }
13695
13696        .list {
13697          list-style-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fff), to(#000));
13698          list-style-image: -webkit-linear-gradient(top, #fff, #000);
13699          list-style-image: -o-linear-gradient(top, #fff, #000);
13700          list-style-image: linear-gradient(#fff, #000);
13701        }
13702
13703        .mask {
13704          -webkit-mask: -webkit-gradient(linear, 0 0, 0 100%, from(#fff), to(#000));
13705          -webkit-mask: -webkit-linear-gradient(top, #fff, #000);
13706          -webkit-mask: -o-linear-gradient(top, #fff, #000);
13707          mask: -o-linear-gradient(top, #fff, #000);
13708          -webkit-mask: linear-gradient(#fff, #000);
13709          mask: linear-gradient(#fff, #000);
13710        }
13711
13712        .newline {
13713          background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fff), to(#000)), -webkit-gradient(linear, 0 0, 0 100%, from(#000), to(#fff));
13714          background-image: -webkit-linear-gradient(top, #fff, #000), -webkit-linear-gradient(top, #000, #fff);
13715          background-image: -o-linear-gradient(top, #fff, #000), -o-linear-gradient(top, #000, #fff);
13716          background-image: linear-gradient(#fff, #000), linear-gradient(#000, #fff);
13717        }
13718
13719        .convert {
13720          background: -webkit-gradient(linear, 0 100%, 0 0, from(#fff), to(#000));
13721          background: -webkit-linear-gradient(90deg, #fff, #000);
13722          background: -o-linear-gradient(90deg, #fff, #000);
13723          background: linear-gradient(0deg, #fff, #000);
13724          background: linear-gradient(90deg, #fff, #000);
13725          background: linear-gradient(#fff, #000);
13726          background: linear-gradient(270deg, #fff, #000);
13727        }
13728
13729        .grad {
13730          background: -webkit-linear-gradient(89.1deg, #fff, #000);
13731          background: -o-linear-gradient(89.1deg, #fff, #000);
13732          background: linear-gradient(1grad, #fff, #000);
13733        }
13734
13735        .rad {
13736          background: -webkit-linear-gradient(32.704deg, #fff, #000);
13737          background: -o-linear-gradient(32.704deg, #fff, #000);
13738          background: linear-gradient(57.2958deg, #fff, #000);
13739        }
13740
13741        .turn {
13742          background: -webkit-linear-gradient(342deg, #fff, #000);
13743          background: -o-linear-gradient(342deg, #fff, #000);
13744          background: linear-gradient(.3turn, #fff, #000);
13745        }
13746
13747        .norm {
13748          background: -webkit-linear-gradient(#fff, #000);
13749          background: -o-linear-gradient(#fff, #000);
13750          background: linear-gradient(-90deg, #fff, #000);
13751        }
13752
13753        .mask {
13754          -webkit-mask-image: -webkit-radial-gradient(circle at 86% 86%, rgba(0, 0, 0, 0) 8px, #000 8px);
13755          -webkit-mask-image: -o-radial-gradient(circle at 86% 86%, rgba(0, 0, 0, 0) 8px, #000 8px);
13756          mask-image: -o-radial-gradient(circle at 86% 86%, rgba(0, 0, 0, 0) 8px, #000 8px);
13757          -webkit-mask-image: radial-gradient(circle at 86% 86%, rgba(0, 0, 0, 0) 8px, #000 8px);
13758          mask-image: radial-gradient(circle at 86% 86%, rgba(0, 0, 0, 0) 8px, #000 8px);
13759        }
13760
13761        .cover {
13762          background: radial-gradient(ellipse cover at center, white, black);
13763        }
13764
13765        .contain {
13766          background: radial-gradient(contain at center, white, black);
13767        }
13768
13769        .no-div {
13770          background: -webkit-gradient(linear, 0 0, 0 100%, from(#000));
13771          background: -webkit-linear-gradient(top, #000);
13772          background: -o-linear-gradient(top, #000);
13773          background: linear-gradient(#000);
13774        }
13775
13776        .background-shorthand {
13777          background: #f0f -webkit-radial-gradient(#fff, rgba(0, 0, 0, 0)) 0 0 / cover no-repeat;
13778          background: #f0f -o-radial-gradient(#fff, rgba(0, 0, 0, 0)) 0 0 / cover no-repeat;
13779          background: #f0f radial-gradient(#fff, rgba(0, 0, 0, 0)) 0 0 / cover no-repeat;
13780        }
13781
13782        .background-advanced {
13783          background: url("path/to/image.jpg") 50% / cover;
13784          background: -webkit-radial-gradient(at 5px 15px, rgba(214, 168, 18, .7) 0%, rgba(255, 21, 177, .7) 50%, rgba(210, 7, 148, .7) 95%), -webkit-radial-gradient(#fff, rgba(0, 0, 0, 0)), url("path/to/image.jpg") 50% / cover;
13785          background: -o-radial-gradient(at 5px 15px, rgba(214, 168, 18, .7) 0%, rgba(255, 21, 177, .7) 50%, rgba(210, 7, 148, .7) 95%), -o-radial-gradient(#fff, rgba(0, 0, 0, 0)), url("path/to/image.jpg") 50% / cover;
13786          background: radial-gradient(at 5px 15px, rgba(214, 168, 18, .7) 0%, rgba(255, 21, 177, .7) 50%, rgba(210, 7, 148, .7) 95%), radial-gradient(#fff, rgba(0, 0, 0, 0)), url("path/to/image.jpg") 50% / cover;
13787        }
13788
13789        .multiradial {
13790          -webkit-mask-image: -webkit-radial-gradient(circle closest-corner at 100%, #000, rgba(0, 0, 0, 0));
13791          -webkit-mask-image: -o-radial-gradient(circle closest-corner at 100%, #000, rgba(0, 0, 0, 0));
13792          mask-image: -o-radial-gradient(circle closest-corner at 100%, #000, rgba(0, 0, 0, 0));
13793          -webkit-mask-image: radial-gradient(circle closest-corner at 100%, #000, rgba(0, 0, 0, 0));
13794          mask-image: radial-gradient(circle closest-corner at 100%, #000, rgba(0, 0, 0, 0));
13795        }
13796
13797        .broken {
13798          -webkit-mask-image: -webkit-radial-gradient(#fff, #000);
13799          -webkit-mask-image: -o-radial-gradient(#fff, #000);
13800          mask-image: -o-radial-gradient(#fff, #000);
13801          -webkit-mask-image: radial-gradient(#fff, #000);
13802          mask-image: radial-gradient(#fff, #000);
13803        }
13804
13805        .loop {
13806          background-image: url("https://test.com/lol(test.png");
13807          background-image: url("https://test.com/lol(test.png"), -webkit-radial-gradient(#ff0, #000, #ff0);
13808          background-image: url("https://test.com/lol(test.png"), -o-radial-gradient(#ff0, #000, #ff0);
13809          background-image: url("https://test.com/lol(test.png"), radial-gradient(#ff0, #000, #ff0);
13810        }
13811
13812        .unitless-zero {
13813          background-image: -webkit-gradient(linear, 0 100%, 0 0, from(green), to(#00f));
13814          background-image: -webkit-linear-gradient(90deg, green, #00f);
13815          background-image: -o-linear-gradient(90deg, green, #00f);
13816          background-image: linear-gradient(0deg, green, #00f);
13817          background: repeating-linear-gradient(0deg, #00f, red 33.3%);
13818        }
13819
13820        .zero-grad {
13821          background: -webkit-gradient(linear, 0 100%, 0 0, from(green), to(#00f));
13822          background: -webkit-linear-gradient(90deg, green, #00f);
13823          background: -o-linear-gradient(90deg, green, #00f);
13824          background: linear-gradient(0grad, green, #00f);
13825          background-image: repeating-linear-gradient(0grad, #00f, red 33.3%);
13826        }
13827
13828        .zero-rad, .zero-turn {
13829          background: -webkit-gradient(linear, 0 100%, 0 0, from(green), to(#00f));
13830          background: -webkit-linear-gradient(90deg, green, #00f);
13831          background: -o-linear-gradient(90deg, green, #00f);
13832          background: linear-gradient(0deg, green, #00f);
13833        }
13834      "#},
13835      Browsers {
13836        chrome: Some(25 << 16),
13837        opera: Some(12 << 16),
13838        android: Some(2 << 16 | 3 << 8),
13839        ..Browsers::default()
13840      },
13841    );
13842  }
13843
13844  #[test]
13845  fn test_font_face() {
13846    minify_test(
13847      r#"@font-face {
13848      src: url("test.woff");
13849      font-family: "Helvetica";
13850      font-weight: bold;
13851      font-style: italic;
13852    }"#,
13853      "@font-face{src:url(test.woff);font-family:Helvetica;font-weight:700;font-style:italic}",
13854    );
13855    minify_test("@font-face {src: url(test.woff);}", "@font-face{src:url(test.woff)}");
13856    minify_test("@font-face {src: local(\"Test\");}", "@font-face{src:local(Test)}");
13857    minify_test(
13858      "@font-face {src: local(\"Foo Bar\");}",
13859      "@font-face{src:local(Foo Bar)}",
13860    );
13861    minify_test("@font-face {src: local(Test);}", "@font-face{src:local(Test)}");
13862    minify_test("@font-face {src: local(Foo Bar);}", "@font-face{src:local(Foo Bar)}");
13863
13864    minify_test(
13865      "@font-face {src: url(\"test.woff\") format(woff);}",
13866      "@font-face{src:url(test.woff)format(\"woff\")}",
13867    );
13868    minify_test(
13869      "@font-face {src: url(\"test.ttc\") format(collection), url(test.ttf) format(truetype);}",
13870      "@font-face{src:url(test.ttc)format(\"collection\"),url(test.ttf)format(\"truetype\")}",
13871    );
13872    minify_test(
13873      "@font-face {src: url(\"test.otf\") format(opentype) tech(features-aat);}",
13874      "@font-face{src:url(test.otf)format(\"opentype\")tech(features-aat)}",
13875    );
13876    minify_test(
13877      "@font-face {src: url(\"test.woff\") format(woff) tech(color-colrv1);}",
13878      "@font-face{src:url(test.woff)format(\"woff\")tech(color-colrv1)}",
13879    );
13880    minify_test(
13881      "@font-face {src: url(\"test.woff2\") format(woff2) tech(variations);}",
13882      "@font-face{src:url(test.woff2)format(\"woff2\")tech(variations)}",
13883    );
13884    minify_test(
13885      "@font-face {src: url(\"test.woff\") format(woff) tech(palettes);}",
13886      "@font-face{src:url(test.woff)format(\"woff\")tech(palettes)}",
13887    );
13888    // multiple tech
13889    minify_test(
13890      "@font-face {src: url(\"test.woff\") format(woff) tech(features-opentype, color-sbix);}",
13891      "@font-face{src:url(test.woff)format(\"woff\")tech(features-opentype,color-sbix)}",
13892    );
13893    minify_test(
13894      "@font-face {src: url(\"test.woff\")   format(woff)    tech(incremental, color-svg, features-graphite, features-aat);}",
13895      "@font-face{src:url(test.woff)format(\"woff\")tech(incremental,color-svg,features-graphite,features-aat)}",
13896    );
13897    // format() function must precede tech() if both are present
13898    minify_test(
13899      "@font-face {src: url(\"foo.ttf\") format(opentype) tech(color-colrv1);}",
13900      "@font-face{src:url(foo.ttf)format(\"opentype\")tech(color-colrv1)}",
13901    );
13902    // only have tech is valid
13903    minify_test(
13904      "@font-face {src: url(\"foo.ttf\") tech(color-SVG);}",
13905      "@font-face{src:url(foo.ttf)tech(color-svg)}",
13906    );
13907    // CGQAQ: if tech and format both presence, order is matter, tech before format is invalid
13908    // but now just return raw token, we don't have strict mode yet.
13909    // ref: https://github.com/parcel-bundler/lightningcss/pull/255#issuecomment-1219049998
13910    minify_test(
13911      "@font-face {src: url(\"foo.ttf\") tech(palettes  color-colrv0  variations) format(opentype);}",
13912      "@font-face{src:url(foo.ttf) tech(palettes color-colrv0 variations)format(opentype)}",
13913    );
13914    // TODO(CGQAQ): make this test pass when we have strict mode
13915    // ref: https://github.com/web-platform-tests/wpt/blob/9f8a6ccc41aa725e8f51f4f096f686313bb88d8d/css/css-fonts/parsing/font-face-src-tech.html#L45
13916    // error_test(
13917    //   "@font-face {src: url(\"foo.ttf\") tech(features-opentype) format(opentype);}",
13918    //   ParserError::AtRuleBodyInvalid,
13919    // );
13920    // error_test(
13921    //   "@font-face {src: url(\"foo.ttf\") tech();}",
13922    //   ParserError::AtRuleBodyInvalid,
13923    // );
13924    // error_test(
13925    //   "@font-face {src: url(\"foo.ttf\") tech(\"features-opentype\");}",
13926    //   ParserError::AtRuleBodyInvalid,
13927    // );
13928    // error_test(
13929    //   "@font-face {src: url(\"foo.ttf\") tech(\"color-colrv0\");}",
13930    //   ParserError::AtRuleBodyInvalid,
13931    // );
13932    minify_test(
13933      "@font-face {src: local(\"\") url(\"test.woff\");}",
13934      "@font-face{src:local(\"\")url(test.woff)}",
13935    );
13936    minify_test("@font-face {font-weight: 200 400}", "@font-face{font-weight:200 400}");
13937    minify_test("@font-face {font-weight: 400 400}", "@font-face{font-weight:400}");
13938    minify_test(
13939      "@font-face {font-stretch: 50% 200%}",
13940      "@font-face{font-stretch:50% 200%}",
13941    );
13942    minify_test("@font-face {font-stretch: 50% 50%}", "@font-face{font-stretch:50%}");
13943    minify_test("@font-face {unicode-range: U+26;}", "@font-face{unicode-range:U+26}");
13944    minify_test("@font-face {unicode-range: u+26;}", "@font-face{unicode-range:U+26}");
13945    minify_test(
13946      "@font-face {unicode-range: U+0-7F;}",
13947      "@font-face{unicode-range:U+0-7F}",
13948    );
13949    minify_test(
13950      "@font-face {unicode-range: U+0025-00FF;}",
13951      "@font-face{unicode-range:U+25-FF}",
13952    );
13953    minify_test("@font-face {unicode-range: U+4??;}", "@font-face{unicode-range:U+4??}");
13954    minify_test(
13955      "@font-face {unicode-range: U+400-4FF;}",
13956      "@font-face{unicode-range:U+4??}",
13957    );
13958    minify_test(
13959      "@font-face {unicode-range: U+0025-00FF, U+4??;}",
13960      "@font-face{unicode-range:U+25-FF,U+4??}",
13961    );
13962    minify_test(
13963      "@font-face {unicode-range: U+A5, U+4E00-9FFF, U+30??, U+FF00-FF9F;}",
13964      "@font-face{unicode-range:U+A5,U+4E00-9FFF,U+30??,U+FF00-FF9F}",
13965    );
13966    minify_test(
13967      "@font-face {unicode-range: U+????;}",
13968      "@font-face{unicode-range:U+????}",
13969    );
13970    minify_test(
13971      "@font-face {unicode-range: U+0000-FFFF;}",
13972      "@font-face{unicode-range:U+????}",
13973    );
13974    minify_test(
13975      "@font-face {unicode-range: U+10????;}",
13976      "@font-face{unicode-range:U+10????}",
13977    );
13978    minify_test(
13979      "@font-face {unicode-range: U+100000-10FFFF;}",
13980      "@font-face{unicode-range:U+10????}",
13981    );
13982    minify_test(
13983      "@font-face {unicode-range: U+1e1e?;}",
13984      "@font-face{unicode-range:U+1E1E?}",
13985    );
13986    minify_test(
13987      "@font-face {unicode-range: u+????, U+1????, U+10????;}",
13988      "@font-face{unicode-range:U+????,U+1????,U+10????}",
13989    );
13990    minify_test(r#"
13991      @font-face {
13992        font-family: Inter;
13993        font-style: oblique 0deg 10deg;
13994        font-weight: 100 900;
13995        src: url("../fonts/Inter.var.woff2?v=3.19") format("woff2");
13996        font-display: swap;
13997      }
13998    "#, "@font-face{font-family:Inter;font-style:oblique 0deg 10deg;font-weight:100 900;src:url(../fonts/Inter.var.woff2?v=3.19)format(\"woff2\");font-display:swap}");
13999    minify_test(r#"
14000    @font-face {
14001      font-family: Inter;
14002      font-style: oblique 14deg 14deg;
14003      font-weight: 100 900;
14004      src: url("../fonts/Inter.var.woff2?v=3.19") format("woff2");
14005      font-display: swap;
14006    }
14007  "#, "@font-face{font-family:Inter;font-style:oblique;font-weight:100 900;src:url(../fonts/Inter.var.woff2?v=3.19)format(\"woff2\");font-display:swap}");
14008  }
14009
14010  #[test]
14011  fn test_font_palette_values() {
14012    minify_test(
14013      r#"@font-palette-values --Cooler {
14014      font-family: Bixa;
14015      base-palette: 1;
14016      override-colors: 1 #7EB7E4;
14017    }"#,
14018      "@font-palette-values --Cooler{font-family:Bixa;base-palette:1;override-colors:1 #7eb7e4}",
14019    );
14020    minify_test(
14021      r#"@font-palette-values --Cooler {
14022      font-family: Handover Sans;
14023      base-palette: 3;
14024      override-colors: 1 rgb(43, 12, 9), 3 lime;
14025    }"#,
14026      "@font-palette-values --Cooler{font-family:Handover Sans;base-palette:3;override-colors:1 #2b0c09,3 #0f0}",
14027    );
14028    minify_test(r#"@font-palette-values --Cooler {
14029      font-family: Handover Sans;
14030      base-palette: 3;
14031      override-colors: 1 rgb(43, 12, 9), 3 var(--highlight);
14032    }"#, "@font-palette-values --Cooler{font-family:Handover Sans;base-palette:3;override-colors:1 #2b0c09,3 var(--highlight)}");
14033    prefix_test(
14034      r#"@font-palette-values --Cooler {
14035      font-family: Handover Sans;
14036      base-palette: 3;
14037      override-colors: 1 rgb(43, 12, 9), 3 lch(50.998% 135.363 338);
14038    }"#,
14039      indoc! {r#"@font-palette-values --Cooler {
14040      font-family: Handover Sans;
14041      base-palette: 3;
14042      override-colors: 1 #2b0c09, 3 #ee00be;
14043      override-colors: 1 #2b0c09, 3 lch(50.998% 135.363 338);
14044    }
14045    "#},
14046      Browsers {
14047        chrome: Some(90 << 16),
14048        ..Browsers::default()
14049      },
14050    );
14051    prefix_test(
14052      r#"@font-palette-values --Cooler {
14053      font-family: Handover Sans;
14054      base-palette: 3;
14055      override-colors: 1 var(--foo), 3 lch(50.998% 135.363 338);
14056    }"#,
14057      indoc! {r#"@font-palette-values --Cooler {
14058      font-family: Handover Sans;
14059      base-palette: 3;
14060      override-colors: 1 var(--foo), 3 #ee00be;
14061    }
14062
14063    @supports (color: lab(0% 0 0)) {
14064      @font-palette-values --Cooler {
14065        font-family: Handover Sans;
14066        base-palette: 3;
14067        override-colors: 1 var(--foo), 3 lab(50.998% 125.506 -50.7078);
14068      }
14069    }
14070    "#},
14071      Browsers {
14072        chrome: Some(90 << 16),
14073        ..Browsers::default()
14074      },
14075    );
14076    prefix_test(
14077      r#"@supports (color: lab(0% 0 0)) {
14078      @font-palette-values --Cooler {
14079        font-family: Handover Sans;
14080        base-palette: 3;
14081        override-colors: 1 var(--foo), 3 lab(50.998% 125.506 -50.7078);
14082      }
14083    }"#,
14084      indoc! {r#"@supports (color: lab(0% 0 0)) {
14085      @font-palette-values --Cooler {
14086        font-family: Handover Sans;
14087        base-palette: 3;
14088        override-colors: 1 var(--foo), 3 lab(50.998% 125.506 -50.7078);
14089      }
14090    }
14091    "#},
14092      Browsers {
14093        chrome: Some(90 << 16),
14094        ..Browsers::default()
14095      },
14096    );
14097    minify_test(".foo { font-palette: --Custom; }", ".foo{font-palette:--Custom}");
14098  }
14099
14100  #[test]
14101  fn test_font_feature_values() {
14102    // https://github.com/clagnut/TODS/blob/e693d52ad411507b960cf01a9734265e3efab102/tods.css#L116-L142
14103    minify_test(
14104      r#"
14105@font-feature-values "Fancy Font Name" {
14106  @styleset { cursive: 1; swoopy: 7 16; }
14107  @character-variant { ampersand: 1; capital-q: 2; }
14108  @stylistic { two-story-g: 1; straight-y: 2; }
14109  @swash { swishy: 1; flowing: 2; }
14110  @ornaments { clover: 1; fleuron: 2; }
14111  @annotation { circled: 1; boxed: 2; }
14112}
14113    "#,
14114      r#"@font-feature-values Fancy Font Name{@styleset{cursive:1;swoopy:7 16}@character-variant{ampersand:1;capital-q:2}@stylistic{two-story-g:1;straight-y:2}@swash{swishy:1;flowing:2}@ornaments{clover:1;fleuron:2}@annotation{circled:1;boxed:2}}"#,
14115    );
14116
14117    // https://github.com/Sorixelle/srxl.me/blob/4eb4f4a15cb2d21356df24c096d6a819cfdc1a99/public/fonts/inter/inter.css#L201-L222
14118    minify_test(
14119      r#"
14120@font-feature-values "Inter", "Inter var", "Inter var experimental" {
14121  @styleset {
14122    open-digits: 1;
14123    disambiguation: 2;
14124    curved-r: 3;
14125    disambiguation-without-zero: 4;
14126  }
14127
14128  @character-variant {
14129    alt-one: 1;
14130    open-four: 2;
14131    open-six: 3;
14132    open-nine: 4;
14133    lower-l-with-tail: 5;
14134    curved-lower-r: 6;
14135    german-double-s: 7;
14136    upper-i-with-serif: 8;
14137    flat-top-three: 9;
14138    upper-g-with-spur: 10;
14139    single-storey-a: 11;
14140  }
14141}
14142      "#,
14143      r#"@font-feature-values Inter,Inter var,Inter var experimental{@styleset{open-digits:1;disambiguation:2;curved-r:3;disambiguation-without-zero:4}@character-variant{alt-one:1;open-four:2;open-six:3;open-nine:4;lower-l-with-tail:5;curved-lower-r:6;german-double-s:7;upper-i-with-serif:8;flat-top-three:9;upper-g-with-spur:10;single-storey-a:11}}"#,
14144    );
14145
14146    // https://github.com/MihailJP/Inconsolata-LGC/blob/7c53cf455787096c93d82d9a51018f12ec39a6e9/Inconsolata-LGC.css#L65-L91
14147    minify_test(
14148      r#"
14149@font-feature-values "Inconsolata LGC" {
14150	@styleset {
14151		alternative-umlaut: 1;
14152	}
14153	@character-variant {
14154		zero-plain: 1 1;
14155		zero-dotted: 1 2;
14156		zero-longslash: 1 3;
14157		r-with-serif: 2 1;
14158		eng-descender: 3 1;
14159		eng-uppercase: 3 2;
14160		dollar-open: 4 1;
14161		dollar-oldstyle: 4 2;
14162		dollar-cifrao: 4 2;
14163		ezh-no-descender: 5 1;
14164		ezh-reversed-sigma: 5 2;
14165		triangle-text-form: 6 1;
14166		el-with-hook-old: 7 1;
14167		qa-enlarged-lowercase: 8 1;
14168		qa-reversed-p: 8 2;
14169		che-with-hook: 9 1;
14170		che-with-hook-alt: 9 2;
14171		ge-with-hook: 10 1;
14172		ge-with-hook-alt: 10 2;
14173		ge-with-stroke-and-descender: 11 1;
14174	}
14175}
14176    "#,
14177      r#"@font-feature-values Inconsolata LGC{@styleset{alternative-umlaut:1}@character-variant{zero-plain:1 1;zero-dotted:1 2;zero-longslash:1 3;r-with-serif:2 1;eng-descender:3 1;eng-uppercase:3 2;dollar-open:4 1;dollar-oldstyle:4 2;dollar-cifrao:4 2;ezh-no-descender:5 1;ezh-reversed-sigma:5 2;triangle-text-form:6 1;el-with-hook-old:7 1;qa-enlarged-lowercase:8 1;qa-reversed-p:8 2;che-with-hook:9 1;che-with-hook-alt:9 2;ge-with-hook:10 1;ge-with-hook-alt:10 2;ge-with-stroke-and-descender:11 1}}"#,
14178    );
14179
14180    minify_test(
14181      r#"
14182      @font-feature-values "Fancy Font Name" {
14183        @styleset { cursive: 1; swoopy: 7 16; }
14184        @character-variant { ampersand: 1; capital-q: 2; }
14185      }
14186      "#,
14187      r#"@font-feature-values Fancy Font Name{@styleset{cursive:1;swoopy:7 16}@character-variant{ampersand:1;capital-q:2}}"#,
14188    );
14189    minify_test(
14190      r#"
14191      @font-feature-values foo {
14192          @swash { pretty: 0; pretty: 1; cool: 2; }
14193      }
14194      "#,
14195      "@font-feature-values foo{@swash{pretty:1;cool:2}}",
14196    );
14197    minify_test(
14198      r#"
14199      @font-feature-values foo {
14200          @swash { pretty: 1; }
14201          @swash { cool: 2; }
14202      }
14203      "#,
14204      "@font-feature-values foo{@swash{pretty:1;cool:2}}",
14205    );
14206    minify_test(
14207      r#"
14208      @font-feature-values foo {
14209          @swash { pretty: 1; }
14210      }
14211      @font-feature-values foo {
14212          @swash { cool: 2; }
14213      }
14214      "#,
14215      "@font-feature-values foo{@swash{pretty:1;cool:2}}",
14216    );
14217  }
14218
14219  #[test]
14220  fn test_page_rule() {
14221    minify_test("@page {margin: 0.5cm}", "@page{margin:.5cm}");
14222    minify_test("@page :left {margin: 0.5cm}", "@page:left{margin:.5cm}");
14223    minify_test("@page :right {margin: 0.5cm}", "@page:right{margin:.5cm}");
14224    minify_test(
14225      "@page LandscapeTable {margin: 0.5cm}",
14226      "@page LandscapeTable{margin:.5cm}",
14227    );
14228    minify_test(
14229      "@page CompanyLetterHead:first {margin: 0.5cm}",
14230      "@page CompanyLetterHead:first{margin:.5cm}",
14231    );
14232    minify_test("@page:first {margin: 0.5cm}", "@page:first{margin:.5cm}");
14233    minify_test("@page :blank:first {margin: 0.5cm}", "@page:blank:first{margin:.5cm}");
14234    minify_test("@page toc, index {margin: 0.5cm}", "@page toc,index{margin:.5cm}");
14235    minify_test(
14236      r#"
14237    @page :right {
14238      @bottom-left {
14239        margin: 10pt;
14240      }
14241    }
14242    "#,
14243      "@page:right{@bottom-left{margin:10pt}}",
14244    );
14245    minify_test(
14246      r#"
14247    @page :right {
14248      margin: 1in;
14249
14250      @bottom-left {
14251        margin: 10pt;
14252      }
14253    }
14254    "#,
14255      "@page:right{margin:1in;@bottom-left{margin:10pt}}",
14256    );
14257
14258    test(
14259      r#"
14260    @page :right {
14261      @bottom-left {
14262        margin: 10pt;
14263      }
14264    }
14265    "#,
14266      indoc! {r#"
14267      @page :right {
14268        @bottom-left {
14269          margin: 10pt;
14270        }
14271      }
14272      "#},
14273    );
14274
14275    test(
14276      r#"
14277    @page :right {
14278      margin: 1in;
14279
14280      @bottom-left-corner { content: "Foo"; }
14281      @bottom-right-corner { content: "Bar"; }
14282    }
14283    "#,
14284      indoc! {r#"
14285      @page :right {
14286        margin: 1in;
14287
14288        @bottom-left-corner {
14289          content: "Foo";
14290        }
14291
14292        @bottom-right-corner {
14293          content: "Bar";
14294        }
14295      }
14296      "#},
14297    );
14298
14299    error_test(
14300      r#"
14301      @page {
14302        @foo {
14303          margin: 1in;
14304        }
14305      }
14306      "#,
14307      ParserError::AtRuleInvalid("foo".into()),
14308    );
14309
14310    error_test(
14311      r#"
14312      @page {
14313        @top-left-corner {
14314          @bottom-left {
14315            margin: 1in;
14316          }
14317        }
14318      }
14319      "#,
14320      ParserError::AtRuleInvalid("bottom-left".into()),
14321    );
14322  }
14323
14324  #[test]
14325  fn test_supports_rule() {
14326    test(
14327      r#"
14328      @supports (foo: bar) {
14329        .test {
14330          foo: bar;
14331        }
14332      }
14333    "#,
14334      indoc! { r#"
14335      @supports (foo: bar) {
14336        .test {
14337          foo: bar;
14338        }
14339      }
14340    "#},
14341    );
14342    test(
14343      r#"
14344      @supports not (foo: bar) {
14345        .test {
14346          foo: bar;
14347        }
14348      }
14349    "#,
14350      indoc! { r#"
14351      @supports not (foo: bar) {
14352        .test {
14353          foo: bar;
14354        }
14355      }
14356    "#},
14357    );
14358    test(
14359      r#"
14360      @supports (foo: bar) or (bar: baz) {
14361        .test {
14362          foo: bar;
14363        }
14364      }
14365    "#,
14366      indoc! { r#"
14367      @supports (foo: bar) or (bar: baz) {
14368        .test {
14369          foo: bar;
14370        }
14371      }
14372    "#},
14373    );
14374    test(
14375      r#"
14376      @supports (((foo: bar) or (bar: baz))) {
14377        .test {
14378          foo: bar;
14379        }
14380      }
14381    "#,
14382      indoc! { r#"
14383      @supports (foo: bar) or (bar: baz) {
14384        .test {
14385          foo: bar;
14386        }
14387      }
14388    "#},
14389    );
14390    test(
14391      r#"
14392      @supports (foo: bar) and (bar: baz) {
14393        .test {
14394          foo: bar;
14395        }
14396      }
14397    "#,
14398      indoc! { r#"
14399      @supports (foo: bar) and (bar: baz) {
14400        .test {
14401          foo: bar;
14402        }
14403      }
14404    "#},
14405    );
14406    test(
14407      r#"
14408      @supports (((foo: bar) and (bar: baz))) {
14409        .test {
14410          foo: bar;
14411        }
14412      }
14413    "#,
14414      indoc! { r#"
14415      @supports (foo: bar) and (bar: baz) {
14416        .test {
14417          foo: bar;
14418        }
14419      }
14420    "#},
14421    );
14422    test(
14423      r#"
14424      @supports (foo: bar) and (((bar: baz) or (test: foo))) {
14425        .test {
14426          foo: bar;
14427        }
14428      }
14429    "#,
14430      indoc! { r#"
14431      @supports (foo: bar) and ((bar: baz) or (test: foo)) {
14432        .test {
14433          foo: bar;
14434        }
14435      }
14436    "#},
14437    );
14438    test(
14439      r#"
14440      @supports not (((foo: bar) and (bar: baz))) {
14441        .test {
14442          foo: bar;
14443        }
14444      }
14445    "#,
14446      indoc! { r#"
14447      @supports not ((foo: bar) and (bar: baz)) {
14448        .test {
14449          foo: bar;
14450        }
14451      }
14452    "#},
14453    );
14454    test(
14455      r#"
14456      @supports selector(a > b) {
14457        .test {
14458          foo: bar;
14459        }
14460      }
14461    "#,
14462      indoc! { r#"
14463      @supports selector(a > b) {
14464        .test {
14465          foo: bar;
14466        }
14467      }
14468    "#},
14469    );
14470    test(
14471      r#"
14472      @supports unknown(test) {
14473        .test {
14474          foo: bar;
14475        }
14476      }
14477    "#,
14478      indoc! { r#"
14479      @supports unknown(test) {
14480        .test {
14481          foo: bar;
14482        }
14483      }
14484    "#},
14485    );
14486    test(
14487      r#"
14488      @supports (unknown) {
14489        .test {
14490          foo: bar;
14491        }
14492      }
14493    "#,
14494      indoc! { r#"
14495      @supports (unknown) {
14496        .test {
14497          foo: bar;
14498        }
14499      }
14500    "#},
14501    );
14502    test(
14503      r#"
14504      @supports (display: grid) and (not (display: inline-grid)) {
14505        .test {
14506          foo: bar;
14507        }
14508      }
14509    "#,
14510      indoc! { r#"
14511      @supports (display: grid) and (not (display: inline-grid)) {
14512        .test {
14513          foo: bar;
14514        }
14515      }
14516    "#},
14517    );
14518    prefix_test(
14519      r#"
14520      @supports (backdrop-filter: blur(10px)) {
14521        div {
14522          backdrop-filter: blur(10px);
14523        }
14524      }
14525    "#,
14526      indoc! { r#"
14527      @supports ((-webkit-backdrop-filter: blur(10px)) or (backdrop-filter: blur(10px))) {
14528        div {
14529          -webkit-backdrop-filter: blur(10px);
14530          backdrop-filter: blur(10px);
14531        }
14532      }
14533    "#},
14534      Browsers {
14535        safari: Some(14 << 16),
14536        ..Default::default()
14537      },
14538    );
14539    prefix_test(
14540      r#"
14541      @supports ((-webkit-backdrop-filter: blur(10px)) or (backdrop-filter: blur(10px))) {
14542        div {
14543          backdrop-filter: blur(10px);
14544        }
14545      }
14546    "#,
14547      indoc! { r#"
14548      @supports ((-webkit-backdrop-filter: blur(10px)) or (backdrop-filter: blur(10px))) {
14549        div {
14550          -webkit-backdrop-filter: blur(10px);
14551          backdrop-filter: blur(10px);
14552        }
14553      }
14554    "#},
14555      Browsers {
14556        safari: Some(14 << 16),
14557        ..Default::default()
14558      },
14559    );
14560    prefix_test(
14561      r#"
14562      @supports ((-webkit-backdrop-filter: blur(20px)) or (backdrop-filter: blur(10px))) {
14563        div {
14564          backdrop-filter: blur(10px);
14565        }
14566      }
14567    "#,
14568      indoc! { r#"
14569      @supports ((-webkit-backdrop-filter: blur(20px))) or ((-webkit-backdrop-filter: blur(10px)) or (backdrop-filter: blur(10px))) {
14570        div {
14571          -webkit-backdrop-filter: blur(10px);
14572          backdrop-filter: blur(10px);
14573        }
14574      }
14575    "#},
14576      Browsers {
14577        safari: Some(14 << 16),
14578        ..Default::default()
14579      },
14580    );
14581    prefix_test(
14582      r#"
14583      @supports ((-webkit-backdrop-filter: blur(10px)) or (backdrop-filter: blur(10px))) {
14584        div {
14585          backdrop-filter: blur(10px);
14586        }
14587      }
14588    "#,
14589      indoc! { r#"
14590      @supports (backdrop-filter: blur(10px)) {
14591        div {
14592          backdrop-filter: blur(10px);
14593        }
14594      }
14595    "#},
14596      Browsers {
14597        chrome: Some(80 << 16),
14598        ..Default::default()
14599      },
14600    );
14601    minify_test(
14602      r#"
14603      @supports (width: calc(10px * 2)) {
14604        .test {
14605          width: calc(10px * 2);
14606        }
14607      }
14608    "#,
14609      "@supports (width:calc(10px * 2)){.test{width:20px}}",
14610    );
14611    minify_test(
14612      r#"
14613      @supports (color: hsl(0deg, 0%, 0%)) {
14614        .test {
14615          color: hsl(0deg, 0%, 0%);
14616        }
14617      }
14618    "#,
14619      "@supports (color:hsl(0deg, 0%, 0%)){.test{color:#000}}",
14620    );
14621  }
14622
14623  #[test]
14624  fn test_counter_style() {
14625    test(
14626      r#"
14627      @counter-style circled-alpha {
14628        system: fixed;
14629        symbols: Ⓐ Ⓑ Ⓒ;
14630        suffix: " ";
14631      }
14632    "#,
14633      indoc! { r#"
14634      @counter-style circled-alpha {
14635        system: fixed;
14636        symbols: Ⓐ Ⓑ Ⓒ;
14637        suffix: " ";
14638      }
14639    "#},
14640    );
14641  }
14642
14643  #[test]
14644  fn test_namespace() {
14645    minify_test(
14646      "@namespace url(http://toto.example.org);",
14647      "@namespace \"http://toto.example.org\";",
14648    );
14649    minify_test(
14650      "@namespace \"http://toto.example.org\";",
14651      "@namespace \"http://toto.example.org\";",
14652    );
14653    minify_test(
14654      "@namespace toto \"http://toto.example.org\";",
14655      "@namespace toto \"http://toto.example.org\";",
14656    );
14657    minify_test(
14658      "@namespace toto url(http://toto.example.org);",
14659      "@namespace toto \"http://toto.example.org\";",
14660    );
14661
14662    test(
14663      r#"
14664      @namespace "http://example.com/foo";
14665
14666      x {
14667        color: red;
14668      }
14669    "#,
14670      indoc! {r#"
14671      @namespace "http://example.com/foo";
14672
14673      x {
14674        color: red;
14675      }
14676    "#},
14677    );
14678
14679    test(
14680      r#"
14681      @namespace toto "http://toto.example.org";
14682
14683      toto|x {
14684        color: red;
14685      }
14686
14687      [toto|att=val] {
14688        color: blue
14689      }
14690    "#,
14691      indoc! {r#"
14692      @namespace toto "http://toto.example.org";
14693
14694      toto|x {
14695        color: red;
14696      }
14697
14698      [toto|att="val"] {
14699        color: #00f;
14700      }
14701    "#},
14702    );
14703
14704    test(
14705      r#"
14706      @namespace "http://example.com/foo";
14707
14708      |x {
14709        color: red;
14710      }
14711
14712      [|att=val] {
14713        color: blue
14714      }
14715    "#,
14716      indoc! {r#"
14717      @namespace "http://example.com/foo";
14718
14719      |x {
14720        color: red;
14721      }
14722
14723      [att="val"] {
14724        color: #00f;
14725      }
14726    "#},
14727    );
14728
14729    test(
14730      r#"
14731      @namespace "http://example.com/foo";
14732
14733      *|x {
14734        color: red;
14735      }
14736
14737      [*|att=val] {
14738        color: blue
14739      }
14740    "#,
14741      indoc! {r#"
14742      @namespace "http://example.com/foo";
14743
14744      *|x {
14745        color: red;
14746      }
14747
14748      [*|att="val"] {
14749        color: #00f;
14750      }
14751    "#},
14752    );
14753
14754    error_test(
14755      ".foo { color: red } @namespace \"http://example.com/foo\";",
14756      ParserError::UnexpectedNamespaceRule,
14757    );
14758  }
14759
14760  #[test]
14761  fn test_import() {
14762    minify_test("@import url(foo.css);", "@import \"foo.css\";");
14763    minify_test("@import \"foo.css\";", "@import \"foo.css\";");
14764    minify_test("@import url(foo.css) print;", "@import \"foo.css\" print;");
14765    minify_test("@import \"foo.css\" print;", "@import \"foo.css\" print;");
14766    minify_test(
14767      "@import \"foo.css\" screen and (orientation: landscape);",
14768      "@import \"foo.css\" screen and (orientation:landscape);",
14769    );
14770    minify_test(
14771      "@import url(foo.css) supports(display: flex);",
14772      "@import \"foo.css\" supports(display:flex);",
14773    );
14774    minify_test(
14775      "@import url(foo.css) supports(display: flex) print;",
14776      "@import \"foo.css\" supports(display:flex) print;",
14777    );
14778    minify_test(
14779      "@import url(foo.css) supports(not (display: flex));",
14780      "@import \"foo.css\" supports(not (display:flex));",
14781    );
14782    minify_test(
14783      "@import url(foo.css) supports((display: flex));",
14784      "@import \"foo.css\" supports(display:flex);",
14785    );
14786    minify_test("@charset \"UTF-8\"; @import url(foo.css);", "@import \"foo.css\";");
14787    minify_test("@layer foo; @import url(foo.css);", "@layer foo;@import \"foo.css\";");
14788    error_test(
14789      ".foo { color: red } @import url(bar.css);",
14790      ParserError::UnexpectedImportRule,
14791    );
14792    error_test(
14793      "@namespace \"http://example.com/foo\"; @import url(bar.css);",
14794      ParserError::UnexpectedImportRule,
14795    );
14796    error_test(
14797      "@media print { .foo { color: red }} @import url(bar.css);",
14798      ParserError::UnexpectedImportRule,
14799    );
14800    error_test(
14801      "@layer foo; @import url(foo.css); @layer bar; @import url(bar.css)",
14802      ParserError::UnexpectedImportRule,
14803    );
14804  }
14805
14806  #[test]
14807  fn test_prefixes() {
14808    prefix_test(
14809      r#"
14810      .foo {
14811        -webkit-transition: opacity 200ms;
14812        -moz-transition: opacity 200ms;
14813        transition: opacity 200ms;
14814      }
14815      "#,
14816      indoc! {r#"
14817      .foo {
14818        transition: opacity .2s;
14819      }
14820      "#},
14821      Browsers {
14822        chrome: Some(95 << 16),
14823        ..Browsers::default()
14824      },
14825    );
14826
14827    prefix_test(
14828      ".foo{transition:opacity 200ms}",
14829      indoc! {r#"
14830      .foo {
14831        -webkit-transition: opacity .2s;
14832        -moz-transition: opacity .2s;
14833        transition: opacity .2s;
14834      }
14835      "#},
14836      Browsers {
14837        safari: Some(5 << 16),
14838        firefox: Some(14 << 16),
14839        ..Browsers::default()
14840      },
14841    );
14842  }
14843
14844  #[test]
14845  fn test_display() {
14846    minify_test(".foo { display: block }", ".foo{display:block}");
14847    minify_test(".foo { display: block flow }", ".foo{display:block}");
14848    minify_test(".foo { display: flow-root }", ".foo{display:flow-root}");
14849    minify_test(".foo { display: block flow-root }", ".foo{display:flow-root}");
14850    minify_test(".foo { display: inline }", ".foo{display:inline}");
14851    minify_test(".foo { display: inline flow }", ".foo{display:inline}");
14852    minify_test(".foo { display: inline-block }", ".foo{display:inline-block}");
14853    minify_test(".foo { display: inline flow-root }", ".foo{display:inline-block}");
14854    minify_test(".foo { display: run-in }", ".foo{display:run-in}");
14855    minify_test(".foo { display: run-in flow }", ".foo{display:run-in}");
14856    minify_test(".foo { display: list-item }", ".foo{display:list-item}");
14857    minify_test(".foo { display: block flow list-item }", ".foo{display:list-item}");
14858    minify_test(".foo { display: inline list-item }", ".foo{display:inline list-item}");
14859    minify_test(
14860      ".foo { display: inline flow list-item }",
14861      ".foo{display:inline list-item}",
14862    );
14863    minify_test(".foo { display: flex }", ".foo{display:flex}");
14864    minify_test(".foo { display: block flex }", ".foo{display:flex}");
14865    minify_test(".foo { display: inline-flex }", ".foo{display:inline-flex}");
14866    minify_test(".foo { display: inline flex }", ".foo{display:inline-flex}");
14867    minify_test(".foo { display: grid }", ".foo{display:grid}");
14868    minify_test(".foo { display: block grid }", ".foo{display:grid}");
14869    minify_test(".foo { display: inline-grid }", ".foo{display:inline-grid}");
14870    minify_test(".foo { display: inline grid }", ".foo{display:inline-grid}");
14871    minify_test(".foo { display: ruby }", ".foo{display:ruby}");
14872    minify_test(".foo { display: inline ruby }", ".foo{display:ruby}");
14873    minify_test(".foo { display: block ruby }", ".foo{display:block ruby}");
14874    minify_test(".foo { display: table }", ".foo{display:table}");
14875    minify_test(".foo { display: block table }", ".foo{display:table}");
14876    minify_test(".foo { display: inline-table }", ".foo{display:inline-table}");
14877    minify_test(".foo { display: inline table }", ".foo{display:inline-table}");
14878    minify_test(".foo { display: table-row-group }", ".foo{display:table-row-group}");
14879    minify_test(".foo { display: contents }", ".foo{display:contents}");
14880    minify_test(".foo { display: none }", ".foo{display:none}");
14881    minify_test(".foo { display: -webkit-flex }", ".foo{display:-webkit-flex}");
14882    minify_test(".foo { display: -ms-flexbox }", ".foo{display:-ms-flexbox}");
14883    minify_test(".foo { display: -webkit-box }", ".foo{display:-webkit-box}");
14884    minify_test(".foo { display: -moz-box }", ".foo{display:-moz-box}");
14885    minify_test(
14886      ".foo { display: -webkit-flex; display: -moz-box; display: flex }",
14887      ".foo{display:-webkit-flex;display:-moz-box;display:flex}",
14888    );
14889    minify_test(
14890      ".foo { display: -webkit-flex; display: flex; display: -moz-box }",
14891      ".foo{display:-webkit-flex;display:flex;display:-moz-box}",
14892    );
14893    minify_test(".foo { display: flex; display: grid }", ".foo{display:grid}");
14894    minify_test(
14895      ".foo { display: -webkit-inline-flex; display: -moz-inline-box; display: inline-flex }",
14896      ".foo{display:-webkit-inline-flex;display:-moz-inline-box;display:inline-flex}",
14897    );
14898    minify_test(
14899      ".foo { display: flex; display: var(--grid); }",
14900      ".foo{display:flex;display:var(--grid)}",
14901    );
14902    prefix_test(
14903      ".foo{ display: flex }",
14904      indoc! {r#"
14905      .foo {
14906        display: -webkit-box;
14907        display: -moz-box;
14908        display: -webkit-flex;
14909        display: -ms-flexbox;
14910        display: flex;
14911      }
14912      "#},
14913      Browsers {
14914        safari: Some(4 << 16),
14915        firefox: Some(14 << 16),
14916        ie: Some(10 << 16),
14917        ..Browsers::default()
14918      },
14919    );
14920    prefix_test(
14921      ".foo{ display: flex; display: -webkit-box; }",
14922      indoc! {r#"
14923      .foo {
14924        display: -webkit-box;
14925      }
14926      "#},
14927      Browsers {
14928        safari: Some(4 << 16),
14929        firefox: Some(14 << 16),
14930        ie: Some(10 << 16),
14931        ..Browsers::default()
14932      },
14933    );
14934    prefix_test(
14935      ".foo{ display: -webkit-box; display: flex; }",
14936      indoc! {r#"
14937      .foo {
14938        display: -webkit-box;
14939        display: -moz-box;
14940        display: -webkit-flex;
14941        display: -ms-flexbox;
14942        display: flex;
14943      }
14944      "#},
14945      Browsers {
14946        safari: Some(4 << 16),
14947        firefox: Some(14 << 16),
14948        ie: Some(10 << 16),
14949        ..Browsers::default()
14950      },
14951    );
14952    prefix_test(
14953      r#"
14954      .foo {
14955        display: -webkit-box;
14956        display: -moz-box;
14957        display: -webkit-flex;
14958        display: -ms-flexbox;
14959        display: flex;
14960      }
14961      "#,
14962      indoc! {r#"
14963      .foo {
14964        display: flex;
14965      }
14966      "#},
14967      Browsers {
14968        safari: Some(14 << 16),
14969        ..Browsers::default()
14970      },
14971    );
14972    prefix_test(
14973      r#"
14974      .foo {
14975        display: -webkit-box;
14976        display: flex;
14977        display: -moz-box;
14978        display: -webkit-flex;
14979        display: -ms-flexbox;
14980      }
14981      "#,
14982      indoc! {r#"
14983      .foo {
14984        display: -moz-box;
14985        display: -webkit-flex;
14986        display: -ms-flexbox;
14987      }
14988      "#},
14989      Browsers {
14990        safari: Some(14 << 16),
14991        ..Browsers::default()
14992      },
14993    );
14994    prefix_test(
14995      ".foo{ display: inline-flex }",
14996      indoc! {r#"
14997      .foo {
14998        display: -webkit-inline-box;
14999        display: -moz-inline-box;
15000        display: -webkit-inline-flex;
15001        display: -ms-inline-flexbox;
15002        display: inline-flex;
15003      }
15004      "#},
15005      Browsers {
15006        safari: Some(4 << 16),
15007        firefox: Some(14 << 16),
15008        ie: Some(10 << 16),
15009        ..Browsers::default()
15010      },
15011    );
15012    prefix_test(
15013      r#"
15014      .foo {
15015        display: -webkit-inline-box;
15016        display: -moz-inline-box;
15017        display: -webkit-inline-flex;
15018        display: -ms-inline-flexbox;
15019        display: inline-flex;
15020      }
15021      "#,
15022      indoc! {r#"
15023      .foo {
15024        display: inline-flex;
15025      }
15026      "#},
15027      Browsers {
15028        safari: Some(14 << 16),
15029        ..Browsers::default()
15030      },
15031    );
15032  }
15033
15034  #[test]
15035  fn test_visibility() {
15036    minify_test(".foo { visibility: visible }", ".foo{visibility:visible}");
15037    minify_test(".foo { visibility: hidden }", ".foo{visibility:hidden}");
15038    minify_test(".foo { visibility: collapse }", ".foo{visibility:collapse}");
15039    minify_test(".foo { visibility: Visible }", ".foo{visibility:visible}");
15040  }
15041
15042  #[test]
15043  fn test_text_transform() {
15044    minify_test(".foo { text-transform: uppercase }", ".foo{text-transform:uppercase}");
15045    minify_test(".foo { text-transform: lowercase }", ".foo{text-transform:lowercase}");
15046    minify_test(".foo { text-transform: capitalize }", ".foo{text-transform:capitalize}");
15047    minify_test(".foo { text-transform: none }", ".foo{text-transform:none}");
15048    minify_test(".foo { text-transform: full-width }", ".foo{text-transform:full-width}");
15049    minify_test(
15050      ".foo { text-transform: full-size-kana }",
15051      ".foo{text-transform:full-size-kana}",
15052    );
15053    minify_test(
15054      ".foo { text-transform: uppercase full-width }",
15055      ".foo{text-transform:uppercase full-width}",
15056    );
15057    minify_test(
15058      ".foo { text-transform: full-width uppercase }",
15059      ".foo{text-transform:uppercase full-width}",
15060    );
15061    minify_test(
15062      ".foo { text-transform: uppercase full-width full-size-kana }",
15063      ".foo{text-transform:uppercase full-width full-size-kana}",
15064    );
15065    minify_test(
15066      ".foo { text-transform: full-width uppercase full-size-kana }",
15067      ".foo{text-transform:uppercase full-width full-size-kana}",
15068    );
15069  }
15070
15071  #[test]
15072  fn test_whitespace() {
15073    minify_test(".foo { white-space: normal }", ".foo{white-space:normal}");
15074    minify_test(".foo { white-space: pre }", ".foo{white-space:pre}");
15075    minify_test(".foo { white-space: nowrap }", ".foo{white-space:nowrap}");
15076    minify_test(".foo { white-space: pre-wrap }", ".foo{white-space:pre-wrap}");
15077    minify_test(".foo { white-space: break-spaces }", ".foo{white-space:break-spaces}");
15078    minify_test(".foo { white-space: pre-line }", ".foo{white-space:pre-line}");
15079    minify_test(".foo { white-space: NoWrAp }", ".foo{white-space:nowrap}");
15080  }
15081
15082  #[test]
15083  fn test_tab_size() {
15084    minify_test(".foo { tab-size: 8 }", ".foo{tab-size:8}");
15085    minify_test(".foo { tab-size: 4px }", ".foo{tab-size:4px}");
15086    minify_test(".foo { -moz-tab-size: 4px }", ".foo{-moz-tab-size:4px}");
15087    minify_test(".foo { -o-tab-size: 4px }", ".foo{-o-tab-size:4px}");
15088    prefix_test(
15089      ".foo{ tab-size: 4 }",
15090      indoc! {r#"
15091      .foo {
15092        -moz-tab-size: 4;
15093        -o-tab-size: 4;
15094        tab-size: 4;
15095      }
15096      "#},
15097      Browsers {
15098        safari: Some(8 << 16),
15099        firefox: Some(50 << 16),
15100        opera: Some(12 << 16),
15101        ..Browsers::default()
15102      },
15103    );
15104    prefix_test(
15105      r#"
15106      .foo {
15107        -moz-tab-size: 4;
15108        -o-tab-size: 4;
15109        tab-size: 4;
15110      }
15111      "#,
15112      indoc! {r#"
15113      .foo {
15114        tab-size: 4;
15115      }
15116      "#},
15117      Browsers {
15118        safari: Some(8 << 16),
15119        firefox: Some(94 << 16),
15120        opera: Some(30 << 16),
15121        ..Browsers::default()
15122      },
15123    );
15124  }
15125
15126  #[test]
15127  fn test_word_break() {
15128    minify_test(".foo { word-break: normal }", ".foo{word-break:normal}");
15129    minify_test(".foo { word-break: keep-all }", ".foo{word-break:keep-all}");
15130    minify_test(".foo { word-break: break-all }", ".foo{word-break:break-all}");
15131    minify_test(".foo { word-break: break-word }", ".foo{word-break:break-word}");
15132  }
15133
15134  #[test]
15135  fn test_line_break() {
15136    minify_test(".foo { line-break: auto }", ".foo{line-break:auto}");
15137    minify_test(".foo { line-break: Loose }", ".foo{line-break:loose}");
15138    minify_test(".foo { line-break: anywhere }", ".foo{line-break:anywhere}");
15139  }
15140
15141  #[test]
15142  fn test_wrap() {
15143    minify_test(".foo { overflow-wrap: nOrmal }", ".foo{overflow-wrap:normal}");
15144    minify_test(".foo { overflow-wrap: break-Word }", ".foo{overflow-wrap:break-word}");
15145    minify_test(".foo { overflow-wrap: Anywhere }", ".foo{overflow-wrap:anywhere}");
15146    minify_test(".foo { word-wrap: Normal }", ".foo{word-wrap:normal}");
15147    minify_test(".foo { word-wrap: Break-wOrd }", ".foo{word-wrap:break-word}");
15148    minify_test(".foo { word-wrap: Anywhere }", ".foo{word-wrap:anywhere}");
15149  }
15150
15151  #[test]
15152  fn test_hyphens() {
15153    minify_test(".foo { hyphens: manual }", ".foo{hyphens:manual}");
15154    minify_test(".foo { hyphens: auto }", ".foo{hyphens:auto}");
15155    minify_test(".foo { hyphens: none }", ".foo{hyphens:none}");
15156    minify_test(".foo { -webkit-hyphens: manual }", ".foo{-webkit-hyphens:manual}");
15157    minify_test(".foo { -moz-hyphens: manual }", ".foo{-moz-hyphens:manual}");
15158    minify_test(".foo { -ms-hyphens: manual }", ".foo{-ms-hyphens:manual}");
15159    prefix_test(
15160      ".foo{ hyphens: manual }",
15161      indoc! {r#"
15162      .foo {
15163        -webkit-hyphens: manual;
15164        -moz-hyphens: manual;
15165        -ms-hyphens: manual;
15166        hyphens: manual;
15167      }
15168      "#},
15169      Browsers {
15170        safari: Some(14 << 16),
15171        firefox: Some(40 << 16),
15172        ie: Some(10 << 16),
15173        ..Browsers::default()
15174      },
15175    );
15176    prefix_test(
15177      r#"
15178      .foo {
15179        -webkit-hyphens: manual;
15180        -moz-hyphens: manual;
15181        -ms-hyphens: manual;
15182        hyphens: manual;
15183      }
15184      "#,
15185      indoc! {r#"
15186      .foo {
15187        -webkit-hyphens: manual;
15188        hyphens: manual;
15189      }
15190      "#},
15191      Browsers {
15192        safari: Some(14 << 16),
15193        chrome: Some(88 << 16),
15194        firefox: Some(88 << 16),
15195        edge: Some(79 << 16),
15196        ..Browsers::default()
15197      },
15198    );
15199    prefix_test(
15200      r#"
15201      .foo {
15202        -webkit-hyphens: manual;
15203        -moz-hyphens: manual;
15204        -ms-hyphens: manual;
15205        hyphens: manual;
15206      }
15207      "#,
15208      indoc! {r#"
15209      .foo {
15210        hyphens: manual;
15211      }
15212      "#},
15213      Browsers {
15214        chrome: Some(88 << 16),
15215        firefox: Some(88 << 16),
15216        edge: Some(79 << 16),
15217        ..Browsers::default()
15218      },
15219    );
15220  }
15221
15222  #[test]
15223  fn test_text_align() {
15224    minify_test(".foo { text-align: left }", ".foo{text-align:left}");
15225    minify_test(".foo { text-align: Left }", ".foo{text-align:left}");
15226    minify_test(".foo { text-align: END }", ".foo{text-align:end}");
15227    minify_test(".foo { text-align: left }", ".foo{text-align:left}");
15228
15229    prefix_test(
15230      r#"
15231      .foo {
15232        text-align: start;
15233      }
15234    "#,
15235      indoc! {r#"
15236      .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
15237        text-align: left;
15238      }
15239
15240      .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
15241        text-align: right;
15242      }
15243    "#
15244      },
15245      Browsers {
15246        safari: Some(2 << 16),
15247        ..Browsers::default()
15248      },
15249    );
15250
15251    prefix_test(
15252      r#"
15253      .foo {
15254        text-align: end;
15255      }
15256    "#,
15257      indoc! {r#"
15258      .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
15259        text-align: right;
15260      }
15261
15262      .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
15263        text-align: left;
15264      }
15265    "#
15266      },
15267      Browsers {
15268        safari: Some(2 << 16),
15269        ..Browsers::default()
15270      },
15271    );
15272
15273    prefix_test(
15274      r#"
15275      .foo {
15276        text-align: start;
15277      }
15278    "#,
15279      indoc! {r#"
15280      .foo {
15281        text-align: start;
15282      }
15283    "#
15284      },
15285      Browsers {
15286        safari: Some(14 << 16),
15287        ..Browsers::default()
15288      },
15289    );
15290
15291    prefix_test(
15292      r#"
15293      .foo > .bar {
15294        text-align: start;
15295      }
15296    "#,
15297      indoc! {r#"
15298      .foo > .bar:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
15299        text-align: left;
15300      }
15301
15302      .foo > .bar:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
15303        text-align: right;
15304      }
15305    "#
15306      },
15307      Browsers {
15308        safari: Some(2 << 16),
15309        ..Browsers::default()
15310      },
15311    );
15312
15313    prefix_test(
15314      r#"
15315      .foo:after {
15316        text-align: start;
15317      }
15318    "#,
15319      indoc! {r#"
15320      .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))):after {
15321        text-align: left;
15322      }
15323
15324      .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)):after {
15325        text-align: right;
15326      }
15327    "#
15328      },
15329      Browsers {
15330        safari: Some(2 << 16),
15331        ..Browsers::default()
15332      },
15333    );
15334
15335    prefix_test(
15336      r#"
15337      .foo:hover {
15338        text-align: start;
15339      }
15340    "#,
15341      indoc! {r#"
15342      .foo:hover:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
15343        text-align: left;
15344      }
15345
15346      .foo:hover:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
15347        text-align: right;
15348      }
15349    "#
15350      },
15351      Browsers {
15352        safari: Some(2 << 16),
15353        ..Browsers::default()
15354      },
15355    );
15356  }
15357
15358  #[test]
15359  fn test_text_align_last() {
15360    minify_test(".foo { text-align-last: left }", ".foo{text-align-last:left}");
15361    minify_test(".foo { text-align-last: justify }", ".foo{text-align-last:justify}");
15362    prefix_test(
15363      ".foo{ text-align-last: left }",
15364      indoc! {r#"
15365      .foo {
15366        -moz-text-align-last: left;
15367        text-align-last: left;
15368      }
15369      "#},
15370      Browsers {
15371        firefox: Some(40 << 16),
15372        ..Browsers::default()
15373      },
15374    );
15375    prefix_test(
15376      r#"
15377      .foo {
15378        -moz-text-align-last: left;
15379        text-align-last: left;
15380      }
15381      "#,
15382      indoc! {r#"
15383      .foo {
15384        text-align-last: left;
15385      }
15386      "#},
15387      Browsers {
15388        firefox: Some(88 << 16),
15389        ..Browsers::default()
15390      },
15391    );
15392  }
15393
15394  #[test]
15395  fn test_text_justify() {
15396    minify_test(".foo { text-justify: auto }", ".foo{text-justify:auto}");
15397    minify_test(".foo { text-justify: inter-word }", ".foo{text-justify:inter-word}");
15398  }
15399
15400  #[test]
15401  fn test_word_spacing() {
15402    minify_test(".foo { word-spacing: normal }", ".foo{word-spacing:normal}");
15403    minify_test(".foo { word-spacing: 3px }", ".foo{word-spacing:3px}");
15404  }
15405
15406  #[test]
15407  fn test_letter_spacing() {
15408    minify_test(".foo { letter-spacing: normal }", ".foo{letter-spacing:normal}");
15409    minify_test(".foo { letter-spacing: 3px }", ".foo{letter-spacing:3px}");
15410  }
15411
15412  #[test]
15413  fn test_text_indent() {
15414    minify_test(".foo { text-indent: 20px }", ".foo{text-indent:20px}");
15415    minify_test(".foo { text-indent: 10% }", ".foo{text-indent:10%}");
15416    minify_test(".foo { text-indent: 3em hanging }", ".foo{text-indent:3em hanging}");
15417    minify_test(".foo { text-indent: 3em each-line }", ".foo{text-indent:3em each-line}");
15418    minify_test(
15419      ".foo { text-indent: 3em hanging each-line }",
15420      ".foo{text-indent:3em hanging each-line}",
15421    );
15422    minify_test(
15423      ".foo { text-indent: 3em each-line hanging }",
15424      ".foo{text-indent:3em hanging each-line}",
15425    );
15426    minify_test(
15427      ".foo { text-indent: each-line 3em hanging }",
15428      ".foo{text-indent:3em hanging each-line}",
15429    );
15430    minify_test(
15431      ".foo { text-indent: each-line hanging 3em }",
15432      ".foo{text-indent:3em hanging each-line}",
15433    );
15434  }
15435
15436  #[test]
15437  fn test_text_size_adjust() {
15438    minify_test(".foo { text-size-adjust: none }", ".foo{text-size-adjust:none}");
15439    minify_test(".foo { text-size-adjust: auto }", ".foo{text-size-adjust:auto}");
15440    minify_test(".foo { text-size-adjust: 80% }", ".foo{text-size-adjust:80%}");
15441    prefix_test(
15442      r#"
15443      .foo {
15444        text-size-adjust: none;
15445      }
15446    "#,
15447      indoc! {r#"
15448      .foo {
15449        -webkit-text-size-adjust: none;
15450        -moz-text-size-adjust: none;
15451        -ms-text-size-adjust: none;
15452        text-size-adjust: none;
15453      }
15454    "#},
15455      Browsers {
15456        ios_saf: Some(16 << 16),
15457        edge: Some(15 << 16),
15458        firefox: Some(20 << 16),
15459        ..Browsers::default()
15460      },
15461    );
15462    prefix_test(
15463      r#"
15464      .foo {
15465        -webkit-text-size-adjust: none;
15466        -moz-text-size-adjust: none;
15467        -ms-text-size-adjust: none;
15468        text-size-adjust: none;
15469      }
15470    "#,
15471      indoc! {r#"
15472      .foo {
15473        text-size-adjust: none;
15474      }
15475    "#},
15476      Browsers {
15477        chrome: Some(110 << 16),
15478        ..Browsers::default()
15479      },
15480    );
15481  }
15482
15483  #[test]
15484  fn test_text_decoration() {
15485    minify_test(".foo { text-decoration-line: none }", ".foo{text-decoration-line:none}");
15486    minify_test(
15487      ".foo { text-decoration-line: underline }",
15488      ".foo{text-decoration-line:underline}",
15489    );
15490    minify_test(
15491      ".foo { text-decoration-line: overline }",
15492      ".foo{text-decoration-line:overline}",
15493    );
15494    minify_test(
15495      ".foo { text-decoration-line: line-through }",
15496      ".foo{text-decoration-line:line-through}",
15497    );
15498    minify_test(
15499      ".foo { text-decoration-line: blink }",
15500      ".foo{text-decoration-line:blink}",
15501    );
15502    minify_test(
15503      ".foo { text-decoration-line: underline overline }",
15504      ".foo{text-decoration-line:underline overline}",
15505    );
15506    minify_test(
15507      ".foo { text-decoration-line: overline underline }",
15508      ".foo{text-decoration-line:underline overline}",
15509    );
15510    minify_test(
15511      ".foo { text-decoration-line: overline line-through underline }",
15512      ".foo{text-decoration-line:underline overline line-through}",
15513    );
15514    minify_test(
15515      ".foo { text-decoration-line: spelling-error }",
15516      ".foo{text-decoration-line:spelling-error}",
15517    );
15518    minify_test(
15519      ".foo { text-decoration-line: grammar-error }",
15520      ".foo{text-decoration-line:grammar-error}",
15521    );
15522    minify_test(
15523      ".foo { -webkit-text-decoration-line: overline underline }",
15524      ".foo{-webkit-text-decoration-line:underline overline}",
15525    );
15526    minify_test(
15527      ".foo { -moz-text-decoration-line: overline underline }",
15528      ".foo{-moz-text-decoration-line:underline overline}",
15529    );
15530
15531    minify_test(
15532      ".foo { text-decoration-style: solid }",
15533      ".foo{text-decoration-style:solid}",
15534    );
15535    minify_test(
15536      ".foo { text-decoration-style: dotted }",
15537      ".foo{text-decoration-style:dotted}",
15538    );
15539    minify_test(
15540      ".foo { -webkit-text-decoration-style: solid }",
15541      ".foo{-webkit-text-decoration-style:solid}",
15542    );
15543
15544    minify_test(
15545      ".foo { text-decoration-color: yellow }",
15546      ".foo{text-decoration-color:#ff0}",
15547    );
15548    minify_test(
15549      ".foo { -webkit-text-decoration-color: yellow }",
15550      ".foo{-webkit-text-decoration-color:#ff0}",
15551    );
15552
15553    minify_test(".foo { text-decoration: none }", ".foo{text-decoration:none}");
15554    minify_test(
15555      ".foo { text-decoration: underline dotted }",
15556      ".foo{text-decoration:underline dotted}",
15557    );
15558    minify_test(
15559      ".foo { text-decoration: underline dotted yellow }",
15560      ".foo{text-decoration:underline dotted #ff0}",
15561    );
15562    minify_test(
15563      ".foo { text-decoration: yellow dotted underline }",
15564      ".foo{text-decoration:underline dotted #ff0}",
15565    );
15566    minify_test(
15567      ".foo { text-decoration: underline overline dotted yellow }",
15568      ".foo{text-decoration:underline overline dotted #ff0}",
15569    );
15570    minify_test(
15571      ".foo { -webkit-text-decoration: yellow dotted underline }",
15572      ".foo{-webkit-text-decoration:underline dotted #ff0}",
15573    );
15574    minify_test(
15575      ".foo { -moz-text-decoration: yellow dotted underline }",
15576      ".foo{-moz-text-decoration:underline dotted #ff0}",
15577    );
15578
15579    test(
15580      r#"
15581      .foo {
15582        text-decoration-line: underline;
15583        text-decoration-style: dotted;
15584        text-decoration-color: yellow;
15585        text-decoration-thickness: 2px;
15586      }
15587    "#,
15588      indoc! {r#"
15589      .foo {
15590        text-decoration: underline 2px dotted #ff0;
15591      }
15592    "#},
15593    );
15594
15595    test(
15596      r#"
15597      .foo {
15598        text-decoration: underline;
15599        text-decoration-style: dotted;
15600      }
15601    "#,
15602      indoc! {r#"
15603      .foo {
15604        text-decoration: underline dotted;
15605      }
15606    "#},
15607    );
15608
15609    test(
15610      r#"
15611      .foo {
15612        text-decoration: underline;
15613        text-decoration-style: var(--style);
15614      }
15615    "#,
15616      indoc! {r#"
15617      .foo {
15618        text-decoration: underline;
15619        text-decoration-style: var(--style);
15620      }
15621    "#},
15622    );
15623
15624    test(
15625      r#"
15626      .foo {
15627        -webkit-text-decoration: underline;
15628        -webkit-text-decoration-style: dotted;
15629      }
15630    "#,
15631      indoc! {r#"
15632      .foo {
15633        -webkit-text-decoration: underline dotted;
15634      }
15635    "#},
15636    );
15637
15638    prefix_test(
15639      r#"
15640      .foo {
15641        text-decoration: underline dotted;
15642      }
15643    "#,
15644      indoc! {r#"
15645      .foo {
15646        -webkit-text-decoration: underline dotted;
15647        text-decoration: underline dotted;
15648      }
15649    "#},
15650      Browsers {
15651        safari: Some(8 << 16),
15652        firefox: Some(30 << 16),
15653        ..Browsers::default()
15654      },
15655    );
15656
15657    prefix_test(
15658      r#"
15659      .foo {
15660        text-decoration-line: underline;
15661      }
15662    "#,
15663      indoc! {r#"
15664      .foo {
15665        -webkit-text-decoration-line: underline;
15666        -moz-text-decoration-line: underline;
15667        text-decoration-line: underline;
15668      }
15669    "#},
15670      Browsers {
15671        safari: Some(8 << 16),
15672        firefox: Some(30 << 16),
15673        ..Browsers::default()
15674      },
15675    );
15676
15677    prefix_test(
15678      r#"
15679      .foo {
15680        text-decoration-style: dotted;
15681      }
15682    "#,
15683      indoc! {r#"
15684      .foo {
15685        -webkit-text-decoration-style: dotted;
15686        -moz-text-decoration-style: dotted;
15687        text-decoration-style: dotted;
15688      }
15689    "#},
15690      Browsers {
15691        safari: Some(8 << 16),
15692        firefox: Some(30 << 16),
15693        ..Browsers::default()
15694      },
15695    );
15696
15697    prefix_test(
15698      r#"
15699      .foo {
15700        text-decoration-color: yellow;
15701      }
15702    "#,
15703      indoc! {r#"
15704      .foo {
15705        -webkit-text-decoration-color: #ff0;
15706        -moz-text-decoration-color: #ff0;
15707        text-decoration-color: #ff0;
15708      }
15709    "#},
15710      Browsers {
15711        safari: Some(8 << 16),
15712        firefox: Some(30 << 16),
15713        ..Browsers::default()
15714      },
15715    );
15716
15717    prefix_test(
15718      r#"
15719      .foo {
15720        text-decoration: underline;
15721      }
15722    "#,
15723      indoc! {r#"
15724      .foo {
15725        text-decoration: underline;
15726      }
15727    "#},
15728      Browsers {
15729        safari: Some(8 << 16),
15730        firefox: Some(30 << 16),
15731        ..Browsers::default()
15732      },
15733    );
15734
15735    prefix_test(
15736      r#"
15737      .foo {
15738        -webkit-text-decoration: underline dotted;
15739        text-decoration: underline dotted;
15740      }
15741    "#,
15742      indoc! {r#"
15743      .foo {
15744        -webkit-text-decoration: underline dotted;
15745        text-decoration: underline dotted;
15746      }
15747    "#},
15748      Browsers {
15749        safari: Some(14 << 16),
15750        firefox: Some(45 << 16),
15751        ..Browsers::default()
15752      },
15753    );
15754
15755    prefix_test(
15756      r#"
15757      .foo {
15758        text-decoration: double underline;
15759      }
15760    "#,
15761      indoc! {r#"
15762      .foo {
15763        -webkit-text-decoration: underline double;
15764        text-decoration: underline double;
15765      }
15766    "#},
15767      Browsers {
15768        safari: Some(16 << 16),
15769        ..Browsers::default()
15770      },
15771    );
15772
15773    prefix_test(
15774      r#"
15775      .foo {
15776        text-decoration: underline;
15777        text-decoration-style: double;
15778      }
15779    "#,
15780      indoc! {r#"
15781      .foo {
15782        -webkit-text-decoration: underline double;
15783        text-decoration: underline double;
15784      }
15785    "#},
15786      Browsers {
15787        safari: Some(16 << 16),
15788        ..Browsers::default()
15789      },
15790    );
15791
15792    prefix_test(
15793      r#"
15794      .foo {
15795        text-decoration: underline;
15796        text-decoration-color: red;
15797      }
15798    "#,
15799      indoc! {r#"
15800      .foo {
15801        -webkit-text-decoration: underline red;
15802        text-decoration: underline red;
15803      }
15804    "#},
15805      Browsers {
15806        safari: Some(16 << 16),
15807        ..Browsers::default()
15808      },
15809    );
15810
15811    prefix_test(
15812      r#"
15813      .foo {
15814        text-decoration: var(--test);
15815      }
15816    "#,
15817      indoc! {r#"
15818      .foo {
15819        -webkit-text-decoration: var(--test);
15820        text-decoration: var(--test);
15821      }
15822    "#},
15823      Browsers {
15824        safari: Some(8 << 16),
15825        firefox: Some(30 << 16),
15826        ..Browsers::default()
15827      },
15828    );
15829
15830    minify_test(
15831      ".foo { text-decoration-skip-ink: all }",
15832      ".foo{text-decoration-skip-ink:all}",
15833    );
15834    minify_test(
15835      ".foo { -webkit-text-decoration-skip-ink: all }",
15836      ".foo{-webkit-text-decoration-skip-ink:all}",
15837    );
15838
15839    prefix_test(
15840      r#"
15841      .foo {
15842        text-decoration: lch(50.998% 135.363 338) underline;
15843      }
15844    "#,
15845      indoc! {r#"
15846      .foo {
15847        -webkit-text-decoration: underline #ee00be;
15848        text-decoration: underline #ee00be;
15849        -webkit-text-decoration: underline lch(50.998% 135.363 338);
15850        text-decoration: underline lch(50.998% 135.363 338);
15851      }
15852    "#},
15853      Browsers {
15854        safari: Some(8 << 16),
15855        firefox: Some(30 << 16),
15856        ..Browsers::default()
15857      },
15858    );
15859
15860    prefix_test(
15861      r#"
15862      .foo {
15863        text-decoration-color: lch(50.998% 135.363 338);
15864      }
15865    "#,
15866      indoc! {r#"
15867      .foo {
15868        -webkit-text-decoration-color: #ee00be;
15869        -moz-text-decoration-color: #ee00be;
15870        text-decoration-color: #ee00be;
15871        -webkit-text-decoration-color: lch(50.998% 135.363 338);
15872        -moz-text-decoration-color: lch(50.998% 135.363 338);
15873        text-decoration-color: lch(50.998% 135.363 338);
15874      }
15875    "#},
15876      Browsers {
15877        safari: Some(8 << 16),
15878        firefox: Some(30 << 16),
15879        ..Browsers::default()
15880      },
15881    );
15882
15883    prefix_test(
15884      r#"
15885      .foo {
15886        text-decoration: lch(50.998% 135.363 338) var(--style);
15887      }
15888    "#,
15889      indoc! {r#"
15890      .foo {
15891        text-decoration: #ee00be var(--style);
15892      }
15893
15894      @supports (color: lab(0% 0 0)) {
15895        .foo {
15896          text-decoration: lab(50.998% 125.506 -50.7078) var(--style);
15897        }
15898      }
15899    "#},
15900      Browsers {
15901        chrome: Some(90 << 16),
15902        ..Browsers::default()
15903      },
15904    );
15905
15906    prefix_test(
15907      r#"
15908      @supports (color: lab(0% 0 0)) {
15909        .foo {
15910          text-decoration: lab(50.998% 125.506 -50.7078) var(--style);
15911        }
15912      }
15913    "#,
15914      indoc! {r#"
15915      @supports (color: lab(0% 0 0)) {
15916        .foo {
15917          text-decoration: lab(50.998% 125.506 -50.7078) var(--style);
15918        }
15919      }
15920    "#},
15921      Browsers {
15922        chrome: Some(90 << 16),
15923        ..Browsers::default()
15924      },
15925    );
15926
15927    prefix_test(
15928      r#"
15929      .foo {
15930        text-decoration: underline 10px;
15931      }
15932    "#,
15933      indoc! {r#"
15934      .foo {
15935        text-decoration: underline;
15936        text-decoration-thickness: 10px;
15937      }
15938    "#},
15939      Browsers {
15940        safari: Some(15 << 16),
15941        ..Browsers::default()
15942      },
15943    );
15944
15945    prefix_test(
15946      r#"
15947      .foo {
15948        text-decoration: underline 10px;
15949      }
15950    "#,
15951      indoc! {r#"
15952      .foo {
15953        text-decoration: underline 10px;
15954      }
15955    "#},
15956      Browsers {
15957        chrome: Some(90 << 16),
15958        ..Browsers::default()
15959      },
15960    );
15961
15962    prefix_test(
15963      r#"
15964      .foo {
15965        text-decoration: underline 10%;
15966      }
15967    "#,
15968      indoc! {r#"
15969      .foo {
15970        text-decoration: underline;
15971        text-decoration-thickness: calc(1em / 10);
15972      }
15973    "#},
15974      Browsers {
15975        safari: Some(12 << 16),
15976        ..Browsers::default()
15977      },
15978    );
15979
15980    prefix_test(
15981      r#"
15982      .foo {
15983        text-decoration: underline 10%;
15984      }
15985    "#,
15986      indoc! {r#"
15987      .foo {
15988        text-decoration: underline 10%;
15989      }
15990    "#},
15991      Browsers {
15992        firefox: Some(89 << 16),
15993        ..Browsers::default()
15994      },
15995    );
15996
15997    prefix_test(
15998      r#"
15999      .foo {
16000        text-decoration-thickness: 10%;
16001      }
16002    "#,
16003      indoc! {r#"
16004      .foo {
16005        text-decoration-thickness: calc(1em / 10);
16006      }
16007    "#},
16008      Browsers {
16009        safari: Some(12 << 16),
16010        ..Browsers::default()
16011      },
16012    );
16013
16014    prefix_test(
16015      r#"
16016      .foo {
16017        text-decoration-thickness: 10%;
16018      }
16019    "#,
16020      indoc! {r#"
16021      .foo {
16022        text-decoration-thickness: 10%;
16023      }
16024    "#},
16025      Browsers {
16026        firefox: Some(89 << 16),
16027        ..Browsers::default()
16028      },
16029    );
16030  }
16031
16032  #[test]
16033  fn test_text_emphasis() {
16034    minify_test(".foo { text-emphasis-style: none }", ".foo{text-emphasis-style:none}");
16035    minify_test(
16036      ".foo { text-emphasis-style: filled }",
16037      ".foo{text-emphasis-style:filled}",
16038    );
16039    minify_test(".foo { text-emphasis-style: open }", ".foo{text-emphasis-style:open}");
16040    minify_test(".foo { text-emphasis-style: dot }", ".foo{text-emphasis-style:dot}");
16041    minify_test(
16042      ".foo { text-emphasis-style: filled dot }",
16043      ".foo{text-emphasis-style:dot}",
16044    );
16045    minify_test(
16046      ".foo { text-emphasis-style: dot filled }",
16047      ".foo{text-emphasis-style:dot}",
16048    );
16049    minify_test(
16050      ".foo { text-emphasis-style: open dot }",
16051      ".foo{text-emphasis-style:open dot}",
16052    );
16053    minify_test(
16054      ".foo { text-emphasis-style: dot open }",
16055      ".foo{text-emphasis-style:open dot}",
16056    );
16057    minify_test(".foo { text-emphasis-style: \"x\" }", ".foo{text-emphasis-style:\"x\"}");
16058
16059    minify_test(".foo { text-emphasis-color: yellow }", ".foo{text-emphasis-color:#ff0}");
16060
16061    minify_test(".foo { text-emphasis: none }", ".foo{text-emphasis:none}");
16062    minify_test(".foo { text-emphasis: filled }", ".foo{text-emphasis:filled}");
16063    minify_test(
16064      ".foo { text-emphasis: filled yellow }",
16065      ".foo{text-emphasis:filled #ff0}",
16066    );
16067    minify_test(
16068      ".foo { text-emphasis: dot filled yellow }",
16069      ".foo{text-emphasis:dot #ff0}",
16070    );
16071
16072    test(
16073      r#"
16074      .foo {
16075        text-emphasis-style: filled;
16076        text-emphasis-color: yellow;
16077      }
16078    "#,
16079      indoc! {r#"
16080      .foo {
16081        text-emphasis: filled #ff0;
16082      }
16083    "#},
16084    );
16085
16086    test(
16087      r#"
16088      .foo {
16089        text-emphasis: filled red;
16090        text-emphasis-color: yellow;
16091      }
16092    "#,
16093      indoc! {r#"
16094      .foo {
16095        text-emphasis: filled #ff0;
16096      }
16097    "#},
16098    );
16099
16100    test(
16101      r#"
16102      .foo {
16103        text-emphasis: filled yellow;
16104        text-emphasis-color: var(--color);
16105      }
16106    "#,
16107      indoc! {r#"
16108      .foo {
16109        text-emphasis: filled #ff0;
16110        text-emphasis-color: var(--color);
16111      }
16112    "#},
16113    );
16114
16115    prefix_test(
16116      r#"
16117      .foo {
16118        text-emphasis-style: filled;
16119      }
16120    "#,
16121      indoc! {r#"
16122      .foo {
16123        -webkit-text-emphasis-style: filled;
16124        text-emphasis-style: filled;
16125      }
16126    "#},
16127      Browsers {
16128        safari: Some(10 << 16),
16129        chrome: Some(30 << 16),
16130        firefox: Some(45 << 16),
16131        ..Browsers::default()
16132      },
16133    );
16134
16135    prefix_test(
16136      r#"
16137      .foo {
16138        -webkit-text-emphasis-style: filled;
16139        text-emphasis-style: filled;
16140      }
16141    "#,
16142      indoc! {r#"
16143      .foo {
16144        text-emphasis-style: filled;
16145      }
16146    "#},
16147      Browsers {
16148        safari: Some(10 << 16),
16149        firefox: Some(45 << 16),
16150        ..Browsers::default()
16151      },
16152    );
16153
16154    minify_test(
16155      ".foo { text-emphasis-position: over }",
16156      ".foo{text-emphasis-position:over}",
16157    );
16158    minify_test(
16159      ".foo { text-emphasis-position: under }",
16160      ".foo{text-emphasis-position:under}",
16161    );
16162    minify_test(
16163      ".foo { text-emphasis-position: over right }",
16164      ".foo{text-emphasis-position:over}",
16165    );
16166    minify_test(
16167      ".foo { text-emphasis-position: over left }",
16168      ".foo{text-emphasis-position:over left}",
16169    );
16170
16171    prefix_test(
16172      r#"
16173      .foo {
16174        text-emphasis-position: over;
16175      }
16176    "#,
16177      indoc! {r#"
16178      .foo {
16179        -webkit-text-emphasis-position: over;
16180        text-emphasis-position: over;
16181      }
16182    "#},
16183      Browsers {
16184        safari: Some(10 << 16),
16185        chrome: Some(30 << 16),
16186        firefox: Some(45 << 16),
16187        ..Browsers::default()
16188      },
16189    );
16190
16191    prefix_test(
16192      r#"
16193      .foo {
16194        text-emphasis-position: over left;
16195      }
16196    "#,
16197      indoc! {r#"
16198      .foo {
16199        text-emphasis-position: over left;
16200      }
16201    "#},
16202      Browsers {
16203        safari: Some(10 << 16),
16204        chrome: Some(30 << 16),
16205        firefox: Some(45 << 16),
16206        ..Browsers::default()
16207      },
16208    );
16209
16210    prefix_test(
16211      r#"
16212      .foo {
16213        text-emphasis-position: var(--test);
16214      }
16215    "#,
16216      indoc! {r#"
16217      .foo {
16218        -webkit-text-emphasis-position: var(--test);
16219        text-emphasis-position: var(--test);
16220      }
16221    "#},
16222      Browsers {
16223        safari: Some(10 << 16),
16224        chrome: Some(30 << 16),
16225        firefox: Some(45 << 16),
16226        ..Browsers::default()
16227      },
16228    );
16229
16230    prefix_test(
16231      r#"
16232      .foo {
16233        text-emphasis: filled lch(50.998% 135.363 338);
16234      }
16235    "#,
16236      indoc! {r#"
16237      .foo {
16238        -webkit-text-emphasis: filled #ee00be;
16239        text-emphasis: filled #ee00be;
16240        -webkit-text-emphasis: filled lch(50.998% 135.363 338);
16241        text-emphasis: filled lch(50.998% 135.363 338);
16242      }
16243    "#},
16244      Browsers {
16245        chrome: Some(25 << 16),
16246        firefox: Some(48 << 16),
16247        ..Browsers::default()
16248      },
16249    );
16250
16251    prefix_test(
16252      r#"
16253      .foo {
16254        text-emphasis-color: lch(50.998% 135.363 338);
16255      }
16256    "#,
16257      indoc! {r#"
16258      .foo {
16259        -webkit-text-emphasis-color: #ee00be;
16260        text-emphasis-color: #ee00be;
16261        -webkit-text-emphasis-color: lch(50.998% 135.363 338);
16262        text-emphasis-color: lch(50.998% 135.363 338);
16263      }
16264    "#},
16265      Browsers {
16266        chrome: Some(25 << 16),
16267        firefox: Some(48 << 16),
16268        ..Browsers::default()
16269      },
16270    );
16271
16272    prefix_test(
16273      r#"
16274      .foo {
16275        text-emphasis: lch(50.998% 135.363 338) var(--style);
16276      }
16277    "#,
16278      indoc! {r#"
16279      .foo {
16280        text-emphasis: #ee00be var(--style);
16281      }
16282
16283      @supports (color: lab(0% 0 0)) {
16284        .foo {
16285          text-emphasis: lab(50.998% 125.506 -50.7078) var(--style);
16286        }
16287      }
16288    "#},
16289      Browsers {
16290        safari: Some(8 << 16),
16291        ..Browsers::default()
16292      },
16293    );
16294
16295    prefix_test(
16296      r#"
16297      @supports (color: lab(0% 0 0)) {
16298        .foo {
16299          text-emphasis: lab(50.998% 125.506 -50.7078) var(--style);
16300        }
16301      }
16302    "#,
16303      indoc! {r#"
16304      @supports (color: lab(0% 0 0)) {
16305        .foo {
16306          text-emphasis: lab(50.998% 125.506 -50.7078) var(--style);
16307        }
16308      }
16309    "#},
16310      Browsers {
16311        safari: Some(8 << 16),
16312        ..Browsers::default()
16313      },
16314    );
16315  }
16316
16317  #[test]
16318  fn test_text_shadow() {
16319    minify_test(
16320      ".foo { text-shadow: 1px 1px 2px yellow; }",
16321      ".foo{text-shadow:1px 1px 2px #ff0}",
16322    );
16323    minify_test(
16324      ".foo { text-shadow: 1px 1px 2px 3px yellow; }",
16325      ".foo{text-shadow:1px 1px 2px 3px #ff0}",
16326    );
16327    minify_test(
16328      ".foo { text-shadow: 1px 1px 0 yellow; }",
16329      ".foo{text-shadow:1px 1px #ff0}",
16330    );
16331    minify_test(
16332      ".foo { text-shadow: 1px 1px yellow; }",
16333      ".foo{text-shadow:1px 1px #ff0}",
16334    );
16335    minify_test(
16336      ".foo { text-shadow: 1px 1px yellow, 2px 3px red; }",
16337      ".foo{text-shadow:1px 1px #ff0,2px 3px red}",
16338    );
16339
16340    prefix_test(
16341      ".foo { text-shadow: 12px 12px lab(40% 56.6 39) }",
16342      indoc! { r#"
16343        .foo {
16344          text-shadow: 12px 12px #b32323;
16345          text-shadow: 12px 12px lab(40% 56.6 39);
16346        }
16347      "#},
16348      Browsers {
16349        chrome: Some(4 << 16),
16350        ..Browsers::default()
16351      },
16352    );
16353
16354    prefix_test(
16355      ".foo { text-shadow: 12px 12px lab(40% 56.6 39) }",
16356      indoc! { r#"
16357        .foo {
16358          text-shadow: 12px 12px #b32323;
16359          text-shadow: 12px 12px color(display-p3 .643308 .192455 .167712);
16360          text-shadow: 12px 12px lab(40% 56.6 39);
16361        }
16362      "#},
16363      Browsers {
16364        chrome: Some(90 << 16),
16365        safari: Some(14 << 16),
16366        ..Browsers::default()
16367      },
16368    );
16369
16370    prefix_test(
16371      ".foo { text-shadow: 12px 12px lab(40% 56.6 39), 12px 12px yellow }",
16372      indoc! { r#"
16373        .foo {
16374          text-shadow: 12px 12px #b32323, 12px 12px #ff0;
16375          text-shadow: 12px 12px lab(40% 56.6 39), 12px 12px #ff0;
16376        }
16377      "#},
16378      Browsers {
16379        chrome: Some(4 << 16),
16380        ..Browsers::default()
16381      },
16382    );
16383
16384    prefix_test(
16385      ".foo { text-shadow: var(--foo) 12px lab(40% 56.6 39) }",
16386      indoc! { r#"
16387        .foo {
16388          text-shadow: var(--foo) 12px #b32323;
16389        }
16390
16391        @supports (color: lab(0% 0 0)) {
16392          .foo {
16393            text-shadow: var(--foo) 12px lab(40% 56.6 39);
16394          }
16395        }
16396      "#},
16397      Browsers {
16398        chrome: Some(4 << 16),
16399        ..Browsers::default()
16400      },
16401    );
16402
16403    prefix_test(
16404      r#"
16405        @supports (color: lab(0% 0 0)) {
16406          .foo {
16407            text-shadow: var(--foo) 12px lab(40% 56.6 39);
16408          }
16409        }
16410      "#,
16411      indoc! { r#"
16412        @supports (color: lab(0% 0 0)) {
16413          .foo {
16414            text-shadow: var(--foo) 12px lab(40% 56.6 39);
16415          }
16416        }
16417      "#},
16418      Browsers {
16419        chrome: Some(4 << 16),
16420        ..Browsers::default()
16421      },
16422    );
16423  }
16424
16425  #[test]
16426  fn test_break() {
16427    prefix_test(
16428      r#"
16429      .foo {
16430        box-decoration-break: clone;
16431      }
16432    "#,
16433      indoc! {r#"
16434      .foo {
16435        -webkit-box-decoration-break: clone;
16436        box-decoration-break: clone;
16437      }
16438    "#},
16439      Browsers {
16440        safari: Some(15 << 16),
16441        ..Browsers::default()
16442      },
16443    );
16444
16445    prefix_test(
16446      r#"
16447      .foo {
16448        box-decoration-break: clone;
16449      }
16450    "#,
16451      indoc! {r#"
16452      .foo {
16453        box-decoration-break: clone;
16454      }
16455    "#},
16456      Browsers {
16457        firefox: Some(95 << 16),
16458        ..Browsers::default()
16459      },
16460    );
16461  }
16462
16463  #[test]
16464  fn test_position() {
16465    test(
16466      r#"
16467      .foo {
16468        position: relative;
16469        position: absolute;
16470      }
16471    "#,
16472      indoc! {r#"
16473      .foo {
16474        position: absolute;
16475      }
16476    "#},
16477    );
16478
16479    test(
16480      r#"
16481      .foo {
16482        position: -webkit-sticky;
16483        position: sticky;
16484      }
16485    "#,
16486      indoc! {r#"
16487      .foo {
16488        position: -webkit-sticky;
16489        position: sticky;
16490      }
16491    "#},
16492    );
16493
16494    prefix_test(
16495      r#"
16496      .foo {
16497        position: sticky;
16498      }
16499    "#,
16500      indoc! {r#"
16501      .foo {
16502        position: -webkit-sticky;
16503        position: sticky;
16504      }
16505    "#},
16506      Browsers {
16507        safari: Some(8 << 16),
16508        ..Browsers::default()
16509      },
16510    );
16511
16512    prefix_test(
16513      r#"
16514      .foo {
16515        position: -webkit-sticky;
16516        position: sticky;
16517      }
16518    "#,
16519      indoc! {r#"
16520      .foo {
16521        position: sticky;
16522      }
16523    "#},
16524      Browsers {
16525        safari: Some(13 << 16),
16526        ..Browsers::default()
16527      },
16528    );
16529
16530    test(
16531      r#"
16532      .foo {
16533        top: 0;
16534        left: 0;
16535        bottom: 0;
16536        right: 0;
16537      }
16538    "#,
16539      indoc! {r#"
16540      .foo {
16541        inset: 0;
16542      }
16543    "#},
16544    );
16545
16546    test(
16547      r#"
16548      .foo {
16549        top: 2px;
16550        left: 4px;
16551        bottom: 2px;
16552        right: 4px;
16553      }
16554    "#,
16555      indoc! {r#"
16556      .foo {
16557        inset: 2px 4px;
16558      }
16559    "#},
16560    );
16561
16562    test(
16563      r#"
16564      .foo {
16565        top: 1px;
16566        left: 2px;
16567        bottom: 3px;
16568        right: 4px;
16569      }
16570    "#,
16571      indoc! {r#"
16572      .foo {
16573        inset: 1px 4px 3px 2px;
16574      }
16575    "#},
16576    );
16577
16578    test(
16579      r#"
16580      .foo {
16581        inset-block-start: 2px;
16582        inset-block-end: 2px;
16583        inset-inline-start: 4px;
16584        inset-inline-end: 4px;
16585      }
16586    "#,
16587      indoc! {r#"
16588      .foo {
16589        inset-block: 2px;
16590        inset-inline: 4px;
16591      }
16592    "#},
16593    );
16594
16595    test(
16596      r#"
16597      .foo {
16598        inset-block-start: 2px;
16599        inset-block-end: 3px;
16600        inset-inline-start: 4px;
16601        inset-inline-end: 5px;
16602      }
16603    "#,
16604      indoc! {r#"
16605      .foo {
16606        inset-block: 2px 3px;
16607        inset-inline: 4px 5px;
16608      }
16609    "#},
16610    );
16611
16612    test(
16613      r#"
16614      .foo {
16615        inset-block-start: 2px;
16616        inset-block-end: 3px;
16617        inset: 4px;
16618        inset-inline-start: 4px;
16619        inset-inline-end: 5px;
16620      }
16621    "#,
16622      indoc! {r#"
16623      .foo {
16624        inset: 4px;
16625        inset-inline: 4px 5px;
16626      }
16627    "#},
16628    );
16629
16630    prefix_test(
16631      r#"
16632      .foo {
16633        inset-inline-start: 2px;
16634      }
16635    "#,
16636      indoc! {r#"
16637      .foo:not(:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
16638        left: 2px;
16639      }
16640
16641      .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
16642        left: 2px;
16643      }
16644
16645      .foo:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
16646        right: 2px;
16647      }
16648
16649      .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
16650        right: 2px;
16651      }
16652    "#
16653      },
16654      Browsers {
16655        safari: Some(8 << 16),
16656        ..Browsers::default()
16657      },
16658    );
16659
16660    prefix_test(
16661      r#"
16662      .foo {
16663        inset-inline-start: 2px;
16664        inset-inline-end: 4px;
16665      }
16666    "#,
16667      indoc! {r#"
16668      .foo:not(:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
16669        left: 2px;
16670        right: 4px;
16671      }
16672
16673      .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
16674        left: 2px;
16675        right: 4px;
16676      }
16677
16678      .foo:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
16679        left: 4px;
16680        right: 2px;
16681      }
16682
16683      .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
16684        left: 4px;
16685        right: 2px;
16686      }
16687    "#
16688      },
16689      Browsers {
16690        safari: Some(8 << 16),
16691        ..Browsers::default()
16692      },
16693    );
16694
16695    prefix_test(
16696      r#"
16697      .foo {
16698        inset-inline: 2px;
16699      }
16700    "#,
16701      indoc! {r#"
16702      .foo {
16703        left: 2px;
16704        right: 2px;
16705      }
16706    "#
16707      },
16708      Browsers {
16709        safari: Some(8 << 16),
16710        ..Browsers::default()
16711      },
16712    );
16713
16714    prefix_test(
16715      r#"
16716      .foo {
16717        inset-block-start: 2px;
16718      }
16719    "#,
16720      indoc! {r#"
16721      .foo {
16722        top: 2px;
16723      }
16724    "#
16725      },
16726      Browsers {
16727        safari: Some(8 << 16),
16728        ..Browsers::default()
16729      },
16730    );
16731
16732    prefix_test(
16733      r#"
16734      .foo {
16735        inset-block-end: 2px;
16736      }
16737    "#,
16738      indoc! {r#"
16739      .foo {
16740        bottom: 2px;
16741      }
16742    "#
16743      },
16744      Browsers {
16745        safari: Some(8 << 16),
16746        ..Browsers::default()
16747      },
16748    );
16749
16750    prefix_test(
16751      r#"
16752      .foo {
16753        top: 1px;
16754        left: 2px;
16755        bottom: 3px;
16756        right: 4px;
16757      }
16758    "#,
16759      indoc! {r#"
16760      .foo {
16761        top: 1px;
16762        bottom: 3px;
16763        left: 2px;
16764        right: 4px;
16765      }
16766    "#},
16767      Browsers {
16768        safari: Some(8 << 16),
16769        ..Browsers::default()
16770      },
16771    );
16772  }
16773
16774  #[test]
16775  fn test_overflow() {
16776    minify_test(".foo { overflow: hidden }", ".foo{overflow:hidden}");
16777    minify_test(".foo { overflow: hidden hidden }", ".foo{overflow:hidden}");
16778    minify_test(".foo { overflow: hidden auto }", ".foo{overflow:hidden auto}");
16779
16780    test(
16781      r#"
16782      .foo {
16783        overflow-x: hidden;
16784        overflow-y: auto;
16785      }
16786    "#,
16787      indoc! {r#"
16788      .foo {
16789        overflow: hidden auto;
16790      }
16791    "#},
16792    );
16793
16794    test(
16795      r#"
16796      .foo {
16797        overflow: hidden;
16798        overflow-y: auto;
16799      }
16800    "#,
16801      indoc! {r#"
16802      .foo {
16803        overflow: hidden auto;
16804      }
16805    "#},
16806    );
16807    test(
16808      r#"
16809      .foo {
16810        overflow: hidden;
16811        overflow-y: var(--y);
16812      }
16813    "#,
16814      indoc! {r#"
16815      .foo {
16816        overflow: hidden;
16817        overflow-y: var(--y);
16818      }
16819    "#},
16820    );
16821    prefix_test(
16822      r#"
16823      .foo {
16824        overflow: hidden auto;
16825      }
16826    "#,
16827      indoc! {r#"
16828      .foo {
16829        overflow-x: hidden;
16830        overflow-y: auto;
16831      }
16832    "#},
16833      Browsers {
16834        chrome: Some(67 << 16),
16835        ..Browsers::default()
16836      },
16837    );
16838    prefix_test(
16839      r#"
16840      .foo {
16841        overflow: hidden hidden;
16842      }
16843    "#,
16844      indoc! {r#"
16845      .foo {
16846        overflow: hidden;
16847      }
16848    "#},
16849      Browsers {
16850        chrome: Some(67 << 16),
16851        ..Browsers::default()
16852      },
16853    );
16854    prefix_test(
16855      r#"
16856      .foo {
16857        overflow: hidden auto;
16858      }
16859    "#,
16860      indoc! {r#"
16861      .foo {
16862        overflow: hidden auto;
16863      }
16864    "#},
16865      Browsers {
16866        chrome: Some(68 << 16),
16867        ..Browsers::default()
16868      },
16869    );
16870
16871    minify_test(".foo { text-overflow: ellipsis }", ".foo{text-overflow:ellipsis}");
16872    prefix_test(
16873      r#"
16874      .foo {
16875        text-overflow: ellipsis;
16876      }
16877    "#,
16878      indoc! {r#"
16879      .foo {
16880        -o-text-overflow: ellipsis;
16881        text-overflow: ellipsis;
16882      }
16883    "#},
16884      Browsers {
16885        safari: Some(4 << 16),
16886        opera: Some(10 << 16),
16887        ..Browsers::default()
16888      },
16889    );
16890
16891    prefix_test(
16892      r#"
16893      .foo {
16894        -o-text-overflow: ellipsis;
16895        text-overflow: ellipsis;
16896      }
16897    "#,
16898      indoc! {r#"
16899      .foo {
16900        text-overflow: ellipsis;
16901      }
16902    "#},
16903      Browsers {
16904        safari: Some(4 << 16),
16905        opera: Some(14 << 16),
16906        ..Browsers::default()
16907      },
16908    );
16909  }
16910
16911  #[test]
16912  fn test_ui() {
16913    minify_test(".foo { resize: both }", ".foo{resize:both}");
16914    minify_test(".foo { resize: Horizontal }", ".foo{resize:horizontal}");
16915    minify_test(".foo { cursor: ew-resize }", ".foo{cursor:ew-resize}");
16916    minify_test(
16917      ".foo { cursor: url(\"test.cur\"), ew-resize }",
16918      ".foo{cursor:url(test.cur),ew-resize}",
16919    );
16920    minify_test(
16921      ".foo { cursor: url(\"test.cur\"), url(\"foo.cur\"), ew-resize }",
16922      ".foo{cursor:url(test.cur),url(foo.cur),ew-resize}",
16923    );
16924    minify_test(".foo { caret-color: auto }", ".foo{caret-color:auto}");
16925    minify_test(".foo { caret-color: yellow }", ".foo{caret-color:#ff0}");
16926    minify_test(".foo { caret-shape: block }", ".foo{caret-shape:block}");
16927    minify_test(".foo { caret: yellow block }", ".foo{caret:#ff0 block}");
16928    minify_test(".foo { caret: block yellow }", ".foo{caret:#ff0 block}");
16929    minify_test(".foo { caret: block }", ".foo{caret:block}");
16930    minify_test(".foo { caret: yellow }", ".foo{caret:#ff0}");
16931    minify_test(".foo { caret: auto auto }", ".foo{caret:auto}");
16932    minify_test(".foo { caret: auto }", ".foo{caret:auto}");
16933    minify_test(".foo { caret: yellow auto }", ".foo{caret:#ff0}");
16934    minify_test(".foo { caret: auto block }", ".foo{caret:block}");
16935    minify_test(".foo { user-select: none }", ".foo{user-select:none}");
16936    minify_test(".foo { -webkit-user-select: none }", ".foo{-webkit-user-select:none}");
16937    minify_test(".foo { accent-color: auto }", ".foo{accent-color:auto}");
16938    minify_test(".foo { accent-color: yellow }", ".foo{accent-color:#ff0}");
16939    minify_test(".foo { appearance: None }", ".foo{appearance:none}");
16940    minify_test(
16941      ".foo { -webkit-appearance: textfield }",
16942      ".foo{-webkit-appearance:textfield}",
16943    );
16944
16945    prefix_test(
16946      r#"
16947      .foo {
16948        user-select: none;
16949      }
16950    "#,
16951      indoc! {r#"
16952      .foo {
16953        -webkit-user-select: none;
16954        -moz-user-select: none;
16955        -ms-user-select: none;
16956        user-select: none;
16957      }
16958    "#},
16959      Browsers {
16960        safari: Some(8 << 16),
16961        opera: Some(5 << 16),
16962        firefox: Some(10 << 16),
16963        ie: Some(10 << 16),
16964        ..Browsers::default()
16965      },
16966    );
16967
16968    prefix_test(
16969      r#"
16970      .foo {
16971        -webkit-user-select: none;
16972        -moz-user-select: none;
16973        -ms-user-select: none;
16974        user-select: none;
16975      }
16976    "#,
16977      indoc! {r#"
16978      .foo {
16979        -webkit-user-select: none;
16980        user-select: none;
16981      }
16982    "#},
16983      Browsers {
16984        safari: Some(8 << 16),
16985        opera: Some(80 << 16),
16986        firefox: Some(80 << 16),
16987        edge: Some(80 << 16),
16988        ..Browsers::default()
16989      },
16990    );
16991
16992    prefix_test(
16993      r#"
16994      .foo {
16995        -webkit-user-select: none;
16996        -moz-user-select: none;
16997        -ms-user-select: none;
16998        user-select: none;
16999      }
17000    "#,
17001      indoc! {r#"
17002      .foo {
17003        user-select: none;
17004      }
17005    "#},
17006      Browsers {
17007        opera: Some(80 << 16),
17008        firefox: Some(80 << 16),
17009        edge: Some(80 << 16),
17010        ..Browsers::default()
17011      },
17012    );
17013
17014    prefix_test(
17015      r#"
17016      .foo {
17017        appearance: none;
17018      }
17019    "#,
17020      indoc! {r#"
17021      .foo {
17022        -webkit-appearance: none;
17023        -moz-appearance: none;
17024        -ms-appearance: none;
17025        appearance: none;
17026      }
17027    "#},
17028      Browsers {
17029        safari: Some(8 << 16),
17030        chrome: Some(80 << 16),
17031        firefox: Some(10 << 16),
17032        ie: Some(11 << 16),
17033        ..Browsers::default()
17034      },
17035    );
17036
17037    prefix_test(
17038      r#"
17039      .foo {
17040        -webkit-appearance: none;
17041        -moz-appearance: none;
17042        -ms-appearance: none;
17043        appearance: none;
17044      }
17045    "#,
17046      indoc! {r#"
17047      .foo {
17048        -webkit-appearance: none;
17049        appearance: none;
17050      }
17051    "#},
17052      Browsers {
17053        safari: Some(15 << 16),
17054        chrome: Some(85 << 16),
17055        firefox: Some(80 << 16),
17056        edge: Some(85 << 16),
17057        ..Browsers::default()
17058      },
17059    );
17060
17061    prefix_test(
17062      r#"
17063      .foo {
17064        -webkit-appearance: none;
17065        -moz-appearance: none;
17066        -ms-appearance: none;
17067        appearance: none;
17068      }
17069    "#,
17070      indoc! {r#"
17071      .foo {
17072        appearance: none;
17073      }
17074    "#},
17075      Browsers {
17076        chrome: Some(85 << 16),
17077        firefox: Some(80 << 16),
17078        edge: Some(85 << 16),
17079        ..Browsers::default()
17080      },
17081    );
17082
17083    prefix_test(
17084      ".foo { caret-color: lch(50.998% 135.363 338) }",
17085      indoc! { r#"
17086        .foo {
17087          caret-color: #ee00be;
17088          caret-color: color(display-p3 .972962 -.362078 .804206);
17089          caret-color: lch(50.998% 135.363 338);
17090        }
17091      "#},
17092      Browsers {
17093        chrome: Some(90 << 16),
17094        safari: Some(14 << 16),
17095        ..Browsers::default()
17096      },
17097    );
17098
17099    prefix_test(
17100      ".foo { caret: lch(50.998% 135.363 338) block }",
17101      indoc! { r#"
17102        .foo {
17103          caret: #ee00be block;
17104          caret: color(display-p3 .972962 -.362078 .804206) block;
17105          caret: lch(50.998% 135.363 338) block;
17106        }
17107      "#},
17108      Browsers {
17109        chrome: Some(90 << 16),
17110        safari: Some(14 << 16),
17111        ..Browsers::default()
17112      },
17113    );
17114
17115    prefix_test(
17116      ".foo { caret: lch(50.998% 135.363 338) var(--foo) }",
17117      indoc! { r#"
17118        .foo {
17119          caret: #ee00be var(--foo);
17120        }
17121
17122        @supports (color: lab(0% 0 0)) {
17123          .foo {
17124            caret: lab(50.998% 125.506 -50.7078) var(--foo);
17125          }
17126        }
17127      "#},
17128      Browsers {
17129        chrome: Some(90 << 16),
17130        ..Browsers::default()
17131      },
17132    );
17133
17134    prefix_test(
17135      r#"
17136        @supports (color: lab(0% 0 0)) {
17137          .foo {
17138            caret: lab(50.998% 125.506 -50.7078) var(--foo);
17139          }
17140        }
17141      "#,
17142      indoc! { r#"
17143        @supports (color: lab(0% 0 0)) {
17144          .foo {
17145            caret: lab(50.998% 125.506 -50.7078) var(--foo);
17146          }
17147        }
17148      "#},
17149      Browsers {
17150        chrome: Some(90 << 16),
17151        ..Browsers::default()
17152      },
17153    );
17154  }
17155
17156  #[test]
17157  fn test_list() {
17158    minify_test(".foo { list-style-type: disc; }", ".foo{list-style-type:disc}");
17159    minify_test(".foo { list-style-type: \"★\"; }", ".foo{list-style-type:\"★\"}");
17160    minify_test(
17161      ".foo { list-style-type: symbols(cyclic '○' '●'); }",
17162      ".foo{list-style-type:symbols(cyclic \"○\" \"●\")}",
17163    );
17164    minify_test(
17165      ".foo { list-style-type: symbols('○' '●'); }",
17166      ".foo{list-style-type:symbols(\"○\" \"●\")}",
17167    );
17168    minify_test(
17169      ".foo { list-style-type: symbols(symbolic '○' '●'); }",
17170      ".foo{list-style-type:symbols(\"○\" \"●\")}",
17171    );
17172    minify_test(
17173      ".foo { list-style-type: symbols(symbolic url('ellipse.png')); }",
17174      ".foo{list-style-type:symbols(url(ellipse.png))}",
17175    );
17176    minify_test(
17177      ".foo { list-style-image: url('ellipse.png'); }",
17178      ".foo{list-style-image:url(ellipse.png)}",
17179    );
17180    minify_test(
17181      ".foo { list-style-position: outside; }",
17182      ".foo{list-style-position:outside}",
17183    );
17184    minify_test(
17185      ".foo { list-style: \"★\" url(ellipse.png) outside; }",
17186      ".foo{list-style:url(ellipse.png) \"★\"}",
17187    );
17188    minify_test(".foo { list-style: none; }", ".foo{list-style:none}");
17189    minify_test(".foo { list-style: none none outside; }", ".foo{list-style:none}");
17190    minify_test(".foo { list-style: none none inside; }", ".foo{list-style:inside none}");
17191    minify_test(".foo { list-style: none inside; }", ".foo{list-style:inside none}");
17192    minify_test(".foo { list-style: none disc; }", ".foo{list-style:outside}");
17193    minify_test(".foo { list-style: none inside disc; }", ".foo{list-style:inside}");
17194    minify_test(".foo { list-style: none \"★\"; }", ".foo{list-style:\"★\"}");
17195    minify_test(
17196      ".foo { list-style: none url(foo.png); }",
17197      ".foo{list-style:url(foo.png) none}",
17198    );
17199
17200    test(
17201      r#"
17202      .foo {
17203        list-style-type: disc;
17204        list-style-image: url(ellipse.png);
17205        list-style-position: outside;
17206      }
17207    "#,
17208      indoc! {r#"
17209      .foo {
17210        list-style: url("ellipse.png");
17211      }
17212    "#},
17213    );
17214
17215    test(
17216      r#"
17217      .foo {
17218        list-style: \"★\" url(ellipse.png) outside;
17219        list-style-image: none;
17220      }
17221    "#,
17222      indoc! {r#"
17223      .foo {
17224        list-style: \"★\";
17225      }
17226    "#},
17227    );
17228
17229    test(
17230      r#"
17231      .foo {
17232        list-style: \"★\" url(ellipse.png) outside;
17233        list-style-image: var(--img);
17234      }
17235    "#,
17236      indoc! {r#"
17237      .foo {
17238        list-style: url("ellipse.png") \"★\";
17239        list-style-image: var(--img);
17240      }
17241    "#},
17242    );
17243
17244    prefix_test(
17245      ".foo { list-style-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
17246      indoc! { r#"
17247        .foo {
17248          list-style-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ff0f0e), to(#7773ff));
17249          list-style-image: -webkit-linear-gradient(top, #ff0f0e, #7773ff);
17250          list-style-image: linear-gradient(#ff0f0e, #7773ff);
17251          list-style-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
17252        }
17253      "#},
17254      Browsers {
17255        chrome: Some(8 << 16),
17256        ..Browsers::default()
17257      },
17258    );
17259
17260    prefix_test(
17261      ".foo { list-style: \"★\" linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
17262      indoc! { r#"
17263        .foo {
17264          list-style: linear-gradient(#ff0f0e, #7773ff) "★";
17265          list-style: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) "★";
17266        }
17267      "#},
17268      Browsers {
17269        chrome: Some(90 << 16),
17270        ..Browsers::default()
17271      },
17272    );
17273
17274    prefix_test(
17275      ".foo { list-style: var(--foo) linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
17276      indoc! { r#"
17277        .foo {
17278          list-style: var(--foo) linear-gradient(#ff0f0e, #7773ff);
17279        }
17280
17281        @supports (color: lab(0% 0 0)) {
17282          .foo {
17283            list-style: var(--foo) linear-gradient(lab(56.208% 94.4644 98.8928), lab(51% 70.4544 -115.586));
17284          }
17285        }
17286      "#},
17287      Browsers {
17288        chrome: Some(90 << 16),
17289        ..Browsers::default()
17290      },
17291    );
17292
17293    prefix_test(
17294      r#"
17295        @supports (color: lab(0% 0 0)) {
17296          .foo {
17297            list-style: var(--foo) linear-gradient(lab(56.208% 94.4644 98.8928), lab(51% 70.4544 -115.586));
17298          }
17299        }
17300      "#,
17301      indoc! { r#"
17302        @supports (color: lab(0% 0 0)) {
17303          .foo {
17304            list-style: var(--foo) linear-gradient(lab(56.208% 94.4644 98.8928), lab(51% 70.4544 -115.586));
17305          }
17306        }
17307      "#},
17308      Browsers {
17309        chrome: Some(90 << 16),
17310        ..Browsers::default()
17311      },
17312    );
17313
17314    test(
17315      r#"
17316      .foo {
17317        list-style: inside;
17318        list-style-type: disc;
17319      }
17320    "#,
17321      indoc! {r#"
17322      .foo {
17323        list-style: inside;
17324      }
17325    "#},
17326    );
17327    test(
17328      r#"
17329      .foo {
17330        list-style: inside;
17331        list-style-type: decimal;
17332      }
17333    "#,
17334      indoc! {r#"
17335      .foo {
17336        list-style: inside decimal;
17337      }
17338    "#},
17339    );
17340  }
17341
17342  #[test]
17343  fn test_image_set() {
17344    // Spec: https://drafts.csswg.org/css-images-4/#image-set-notation
17345    // WPT: https://github.com/web-platform-tests/wpt/blob/master/css/css-images/image-set/image-set-parsing.html
17346    // test image-set(<string>)
17347    minify_test(
17348      ".foo { background: image-set(\"foo.png\" 2x, url(bar.png) 1x) }",
17349      ".foo{background:image-set(\"foo.png\" 2x,\"bar.png\" 1x)}",
17350    );
17351
17352    // test image-set(type(<string>))
17353    minify_test(
17354      ".foo { background: image-set('foo.webp' type('webp'), url(foo.jpg)) }",
17355      ".foo{background:image-set(\"foo.webp\" 1x type(\"webp\"),\"foo.jpg\" 1x)}",
17356    );
17357    minify_test(
17358      ".foo { background: image-set('foo.avif' 2x type('image/avif'), url(foo.png)) }",
17359      ".foo{background:image-set(\"foo.avif\" 2x type(\"image/avif\"),\"foo.png\" 1x)}",
17360    );
17361    minify_test(
17362      ".foo { background: image-set(url('example.png') 3x type('image/png')) }",
17363      ".foo{background:image-set(\"example.png\" 3x type(\"image/png\"))}",
17364    );
17365
17366    minify_test(
17367      ".foo { background: image-set(url(example.png) type('image/png') 1x) }",
17368      ".foo{background:image-set(\"example.png\" 1x type(\"image/png\"))}",
17369    );
17370
17371    minify_test(
17372      ".foo { background: -webkit-image-set(url(\"foo.png\") 2x, url(bar.png) 1x) }",
17373      ".foo{background:-webkit-image-set(url(foo.png) 2x,url(bar.png) 1x)}",
17374    );
17375
17376    test(
17377      r#"
17378      .foo {
17379        background: -webkit-image-set(url("foo.png") 2x, url(bar.png) 1x);
17380        background: image-set(url("foo.png") 2x, url(bar.png) 1x);
17381      }
17382    "#,
17383      indoc! {r#"
17384      .foo {
17385        background: -webkit-image-set(url("foo.png") 2x, url("bar.png") 1x);
17386        background: image-set("foo.png" 2x, "bar.png" 1x);
17387      }
17388    "#},
17389    );
17390
17391    // test image-set(<gradient>)
17392    test(
17393      r#"
17394      .foo {
17395        background: image-set(linear-gradient(cornflowerblue, white) 1x, url("detailed-gradient.png") 3x);
17396      }
17397    "#,
17398      indoc! {r#"
17399      .foo {
17400        background: image-set(linear-gradient(#6495ed, #fff) 1x, "detailed-gradient.png" 3x);
17401      }
17402    "#},
17403    );
17404
17405    prefix_test(
17406      r#"
17407      .foo {
17408        background: image-set(url("foo.png") 2x, url(bar.png) 1x);
17409      }
17410    "#,
17411      indoc! {r#"
17412      .foo {
17413        background: -webkit-image-set(url("foo.png") 2x, url("bar.png") 1x);
17414        background: image-set("foo.png" 2x, "bar.png" 1x);
17415      }
17416    "#},
17417      Browsers {
17418        chrome: Some(85 << 16),
17419        firefox: Some(80 << 16),
17420        ..Browsers::default()
17421      },
17422    );
17423
17424    prefix_test(
17425      r#"
17426      .foo {
17427        background: -webkit-image-set(url("foo.png") 2x, url(bar.png) 1x);
17428        background: image-set(url("foo.png") 2x, url(bar.png) 1x);
17429      }
17430    "#,
17431      indoc! {r#"
17432      .foo {
17433        background: -webkit-image-set(url("foo.png") 2x, url("bar.png") 1x);
17434        background: image-set("foo.png" 2x, "bar.png" 1x);
17435      }
17436    "#},
17437      Browsers {
17438        firefox: Some(80 << 16),
17439        ..Browsers::default()
17440      },
17441    );
17442
17443    prefix_test(
17444      r#"
17445      .foo {
17446        background: -webkit-image-set(url("foo.png") 2x, url(bar.png) 1x);
17447      }
17448    "#,
17449      indoc! {r#"
17450      .foo {
17451        background: -webkit-image-set(url("foo.png") 2x, url("bar.png") 1x);
17452      }
17453    "#},
17454      Browsers {
17455        chrome: Some(95 << 16),
17456        ..Browsers::default()
17457      },
17458    );
17459
17460    for property in &[
17461      "background",
17462      "background-image",
17463      "border-image-source",
17464      "border-image",
17465      "border-image-source",
17466      "-webkit-mask-image",
17467      "-webkit-mask",
17468      "list-style-image",
17469      "list-style",
17470    ] {
17471      prefix_test(
17472        &format!(
17473          r#"
17474        .foo {{
17475          {}: url(foo.png);
17476          {}: image-set(url("foo.png") 2x, url(bar.png) 1x);
17477        }}
17478      "#,
17479          property, property
17480        ),
17481        &format!(
17482          indoc! {r#"
17483        .foo {{
17484          {}: url("foo.png");
17485          {}: image-set("foo.png" 2x, "bar.png" 1x);
17486        }}
17487      "#},
17488          property, property
17489        ),
17490        Browsers {
17491          ie: Some(11 << 16),
17492          chrome: Some(95 << 16),
17493          ..Browsers::default()
17494        },
17495      );
17496
17497      prefix_test(
17498        &format!(
17499          r#"
17500        .foo {{
17501          {}: url(foo.png);
17502          {}: image-set(url("foo.png") 2x, url(bar.png) 1x);
17503        }}
17504      "#,
17505          property, property
17506        ),
17507        &format!(
17508          indoc! {r#"
17509        .foo {{
17510          {}: -webkit-image-set(url("foo.png") 2x, url("bar.png") 1x);
17511          {}: image-set("foo.png" 2x, "bar.png" 1x);
17512        }}
17513      "#},
17514          property, property
17515        ),
17516        Browsers {
17517          chrome: Some(95 << 16),
17518          ..Browsers::default()
17519        },
17520      );
17521    }
17522  }
17523
17524  #[test]
17525  fn test_color() {
17526    minify_test(".foo { color: yellow }", ".foo{color:#ff0}");
17527    minify_test(".foo { color: rgb(255, 255, 0) }", ".foo{color:#ff0}");
17528    minify_test(".foo { color: rgba(255, 255, 0, 1) }", ".foo{color:#ff0}");
17529    minify_test(".foo { color: rgba(255, 255, 0, 0.8) }", ".foo{color:#ff0c}");
17530    minify_test(".foo { color: rgb(128, 128, 128) }", ".foo{color:gray}");
17531    minify_test(".foo { color: rgb(123, 255, 255) }", ".foo{color:#7bffff}");
17532    minify_test(".foo { color: rgba(123, 255, 255, 0.5) }", ".foo{color:#7bffff80}");
17533    minify_test(".foo { color: rgb(123 255 255) }", ".foo{color:#7bffff}");
17534    minify_test(".foo { color: rgb(123 255 255 / .5) }", ".foo{color:#7bffff80}");
17535    minify_test(".foo { color: rgb(123 255 255 / 50%) }", ".foo{color:#7bffff80}");
17536    minify_test(".foo { color: rgb(48% 100% 100% / 50%) }", ".foo{color:#7affff80}");
17537    minify_test(".foo { color: hsl(100deg, 100%, 50%) }", ".foo{color:#5f0}");
17538    minify_test(".foo { color: hsl(100, 100%, 50%) }", ".foo{color:#5f0}");
17539    minify_test(".foo { color: hsl(100 100% 50%) }", ".foo{color:#5f0}");
17540    minify_test(".foo { color: hsl(100 100 50) }", ".foo{color:#5f0}");
17541    minify_test(".foo { color: hsl(100, 100%, 50%, .8) }", ".foo{color:#5f0c}");
17542    minify_test(".foo { color: hsl(100 100% 50% / .8) }", ".foo{color:#5f0c}");
17543    minify_test(".foo { color: hsla(100, 100%, 50%, .8) }", ".foo{color:#5f0c}");
17544    minify_test(".foo { color: hsla(100 100% 50% / .8) }", ".foo{color:#5f0c}");
17545    minify_test(".foo { color: transparent }", ".foo{color:#0000}");
17546    minify_test(".foo { color: currentColor }", ".foo{color:currentColor}");
17547    minify_test(".foo { color: ButtonBorder }", ".foo{color:buttonborder}");
17548    minify_test(".foo { color: hwb(194 0% 0%) }", ".foo{color:#00c4ff}");
17549    minify_test(".foo { color: hwb(194 0% 0% / 50%) }", ".foo{color:#00c4ff80}");
17550    minify_test(".foo { color: hwb(194 0% 50%) }", ".foo{color:#006280}");
17551    minify_test(".foo { color: hwb(194 50% 0%) }", ".foo{color:#80e1ff}");
17552    minify_test(".foo { color: hwb(194 50 0) }", ".foo{color:#80e1ff}");
17553    minify_test(".foo { color: hwb(194 50% 50%) }", ".foo{color:gray}");
17554    // minify_test(".foo { color: ActiveText }", ".foo{color:ActiveTet}");
17555    minify_test(
17556      ".foo { color: lab(29.2345% 39.3825 20.0664); }",
17557      ".foo{color:lab(29.2345% 39.3825 20.0664)}",
17558    );
17559    minify_test(
17560      ".foo { color: lab(29.2345 39.3825 20.0664); }",
17561      ".foo{color:lab(29.2345% 39.3825 20.0664)}",
17562    );
17563    minify_test(
17564      ".foo { color: lab(29.2345% 39.3825% 20.0664%); }",
17565      ".foo{color:lab(29.2345% 49.2281 25.083)}",
17566    );
17567    minify_test(
17568      ".foo { color: lab(29.2345% 39.3825 20.0664 / 100%); }",
17569      ".foo{color:lab(29.2345% 39.3825 20.0664)}",
17570    );
17571    minify_test(
17572      ".foo { color: lab(29.2345% 39.3825 20.0664 / 50%); }",
17573      ".foo{color:lab(29.2345% 39.3825 20.0664/.5)}",
17574    );
17575    minify_test(
17576      ".foo { color: lch(29.2345% 44.2 27); }",
17577      ".foo{color:lch(29.2345% 44.2 27)}",
17578    );
17579    minify_test(
17580      ".foo { color: lch(29.2345 44.2 27); }",
17581      ".foo{color:lch(29.2345% 44.2 27)}",
17582    );
17583    minify_test(
17584      ".foo { color: lch(29.2345% 44.2% 27deg); }",
17585      ".foo{color:lch(29.2345% 66.3 27)}",
17586    );
17587    minify_test(
17588      ".foo { color: lch(29.2345% 44.2 45deg); }",
17589      ".foo{color:lch(29.2345% 44.2 45)}",
17590    );
17591    minify_test(
17592      ".foo { color: lch(29.2345% 44.2 .5turn); }",
17593      ".foo{color:lch(29.2345% 44.2 180)}",
17594    );
17595    minify_test(
17596      ".foo { color: lch(29.2345% 44.2 27 / 100%); }",
17597      ".foo{color:lch(29.2345% 44.2 27)}",
17598    );
17599    minify_test(
17600      ".foo { color: lch(29.2345% 44.2 27 / 50%); }",
17601      ".foo{color:lch(29.2345% 44.2 27/.5)}",
17602    );
17603    minify_test(
17604      ".foo { color: oklab(40.101% 0.1147 0.0453); }",
17605      ".foo{color:oklab(40.101% .1147 .0453)}",
17606    );
17607    minify_test(
17608      ".foo { color: oklab(.40101 0.1147 0.0453); }",
17609      ".foo{color:oklab(40.101% .1147 .0453)}",
17610    );
17611    minify_test(
17612      ".foo { color: oklab(40.101% 0.1147% 0.0453%); }",
17613      ".foo{color:oklab(40.101% .0004588 .0001812)}",
17614    );
17615    minify_test(
17616      ".foo { color: oklch(40.101% 0.12332 21.555); }",
17617      ".foo{color:oklch(40.101% .12332 21.555)}",
17618    );
17619    minify_test(
17620      ".foo { color: oklch(.40101 0.12332 21.555); }",
17621      ".foo{color:oklch(40.101% .12332 21.555)}",
17622    );
17623    minify_test(
17624      ".foo { color: oklch(40.101% 0.12332% 21.555); }",
17625      ".foo{color:oklch(40.101% .00049328 21.555)}",
17626    );
17627    minify_test(
17628      ".foo { color: oklch(40.101% 0.12332 .5turn); }",
17629      ".foo{color:oklch(40.101% .12332 180)}",
17630    );
17631    minify_test(
17632      ".foo { color: color(display-p3 1 0.5 0); }",
17633      ".foo{color:color(display-p3 1 .5 0)}",
17634    );
17635    minify_test(
17636      ".foo { color: color(display-p3 100% 50% 0%); }",
17637      ".foo{color:color(display-p3 1 .5 0)}",
17638    );
17639    minify_test(
17640      ".foo { color: color(xyz-d50 0.2005 0.14089 0.4472); }",
17641      ".foo{color:color(xyz-d50 .2005 .14089 .4472)}",
17642    );
17643    minify_test(
17644      ".foo { color: color(xyz-d50 20.05% 14.089% 44.72%); }",
17645      ".foo{color:color(xyz-d50 .2005 .14089 .4472)}",
17646    );
17647    minify_test(
17648      ".foo { color: color(xyz-d65 0.2005 0.14089 0.4472); }",
17649      ".foo{color:color(xyz .2005 .14089 .4472)}",
17650    );
17651    minify_test(
17652      ".foo { color: color(xyz-d65 20.05% 14.089% 44.72%); }",
17653      ".foo{color:color(xyz .2005 .14089 .4472)}",
17654    );
17655    minify_test(
17656      ".foo { color: color(xyz 0.2005 0.14089 0.4472); }",
17657      ".foo{color:color(xyz .2005 .14089 .4472)}",
17658    );
17659    minify_test(
17660      ".foo { color: color(xyz 20.05% 14.089% 44.72%); }",
17661      ".foo{color:color(xyz .2005 .14089 .4472)}",
17662    );
17663    minify_test(
17664      ".foo { color: color(xyz 0.2005 0 0); }",
17665      ".foo{color:color(xyz .2005 0 0)}",
17666    );
17667    minify_test(".foo { color: color(xyz 0 0 0); }", ".foo{color:color(xyz 0 0 0)}");
17668    minify_test(".foo { color: color(xyz 0 1 0); }", ".foo{color:color(xyz 0 1 0)}");
17669    minify_test(
17670      ".foo { color: color(xyz 0 1 0 / 20%); }",
17671      ".foo{color:color(xyz 0 1 0/.2)}",
17672    );
17673    minify_test(
17674      ".foo { color: color(xyz 0 0 0 / 20%); }",
17675      ".foo{color:color(xyz 0 0 0/.2)}",
17676    );
17677    minify_test(
17678      ".foo { color: color(display-p3 100% 50% 0 / 20%); }",
17679      ".foo{color:color(display-p3 1 .5 0/.2)}",
17680    );
17681    minify_test(
17682      ".foo { color: color(display-p3 100% 0 0 / 20%); }",
17683      ".foo{color:color(display-p3 1 0 0/.2)}",
17684    );
17685    minify_test(".foo { color: hsl(none none none) }", ".foo{color:#000}");
17686    minify_test(".foo { color: hwb(none none none) }", ".foo{color:red}");
17687    minify_test(".foo { color: rgb(none none none) }", ".foo{color:#000}");
17688
17689    // If the browser doesn't support `#rrggbbaa` color syntax, it is converted to `transparent`.
17690    attr_test(
17691      "color: rgba(0, 0, 0, 0)",
17692      "color:transparent",
17693      true,
17694      Some(Browsers {
17695        chrome: Some(61 << 16), // Chrome >= 62 supports `#rrggbbaa` color.
17696        ..Browsers::default()
17697      }),
17698    );
17699
17700    attr_test(
17701      "color: #0000",
17702      "color:transparent",
17703      true,
17704      Some(Browsers {
17705        chrome: Some(61 << 16), // Chrome >= 62 supports `#rrggbbaa` color.
17706        ..Browsers::default()
17707      }),
17708    );
17709
17710    attr_test(
17711      "color: transparent",
17712      "color:transparent",
17713      true,
17714      Some(Browsers {
17715        chrome: Some(61 << 16),
17716        ..Browsers::default()
17717      }),
17718    );
17719
17720    attr_test(
17721      "color: rgba(0, 0, 0, 0)",
17722      "color: rgba(0, 0, 0, 0)",
17723      false,
17724      Some(Browsers {
17725        chrome: Some(61 << 16),
17726        ..Browsers::default()
17727      }),
17728    );
17729
17730    attr_test(
17731      "color: rgba(255, 0, 0, 0)",
17732      "color:rgba(255,0,0,0)",
17733      true,
17734      Some(Browsers {
17735        chrome: Some(61 << 16),
17736        ..Browsers::default()
17737      }),
17738    );
17739
17740    attr_test(
17741      "color: rgba(255, 0, 0, 0)",
17742      "color:#f000",
17743      true,
17744      Some(Browsers {
17745        chrome: Some(62 << 16),
17746        ..Browsers::default()
17747      }),
17748    );
17749
17750    prefix_test(
17751      ".foo { color: rgba(123, 456, 789, 0.5) }",
17752      indoc! { r#"
17753        .foo {
17754          color: #7bffff80;
17755        }
17756      "#},
17757      Browsers {
17758        chrome: Some(95 << 16),
17759        ..Browsers::default()
17760      },
17761    );
17762
17763    prefix_test(
17764      ".foo { color: rgba(123, 255, 255, 0.5) }",
17765      indoc! { r#"
17766        .foo {
17767          color: rgba(123, 255, 255, .5);
17768        }
17769      "#},
17770      Browsers {
17771        ie: Some(11 << 16),
17772        ..Browsers::default()
17773      },
17774    );
17775
17776    prefix_test(
17777      ".foo { color: #7bffff80 }",
17778      indoc! { r#"
17779        .foo {
17780          color: rgba(123, 255, 255, .5);
17781        }
17782      "#},
17783      Browsers {
17784        ie: Some(11 << 16),
17785        ..Browsers::default()
17786      },
17787    );
17788
17789    prefix_test(
17790      ".foo { color: rgba(123, 456, 789, 0.5) }",
17791      indoc! { r#"
17792        .foo {
17793          color: rgba(123, 255, 255, .5);
17794        }
17795      "#},
17796      Browsers {
17797        firefox: Some(48 << 16),
17798        safari: Some(10 << 16),
17799        ios_saf: Some(9 << 16),
17800        ..Browsers::default()
17801      },
17802    );
17803
17804    prefix_test(
17805      ".foo { color: rgba(123, 456, 789, 0.5) }",
17806      indoc! { r#"
17807        .foo {
17808          color: #7bffff80;
17809        }
17810      "#},
17811      Browsers {
17812        firefox: Some(49 << 16),
17813        safari: Some(10 << 16),
17814        ios_saf: Some(10 << 16),
17815        ..Browsers::default()
17816      },
17817    );
17818
17819    prefix_test(
17820      ".foo { background-color: lab(40% 56.6 39) }",
17821      indoc! { r#"
17822        .foo {
17823          background-color: #b32323;
17824          background-color: lab(40% 56.6 39);
17825        }
17826      "#},
17827      Browsers {
17828        chrome: Some(90 << 16),
17829        ..Browsers::default()
17830      },
17831    );
17832
17833    prefix_test(
17834      ".foo { background-color: lch(40% 68.735435 34.568626) }",
17835      indoc! { r#"
17836        .foo {
17837          background-color: #b32323;
17838          background-color: lch(40% 68.7354 34.5686);
17839        }
17840      "#},
17841      Browsers {
17842        chrome: Some(90 << 16),
17843        ..Browsers::default()
17844      },
17845    );
17846
17847    prefix_test(
17848      ".foo { background-color: oklab(59.686% 0.1009 0.1192); }",
17849      indoc! { r#"
17850        .foo {
17851          background-color: #c65d07;
17852          background-color: lab(52.2319% 40.1449 59.9171);
17853        }
17854      "#},
17855      Browsers {
17856        chrome: Some(90 << 16),
17857        ..Browsers::default()
17858      },
17859    );
17860
17861    prefix_test(
17862      ".foo { background-color: oklch(40% 0.1268735435 34.568626) }",
17863      indoc! { r#"
17864        .foo {
17865          background-color: #7e250f;
17866          background-color: lab(29.2661% 38.2437 35.3889);
17867        }
17868      "#},
17869      Browsers {
17870        chrome: Some(90 << 16),
17871        ..Browsers::default()
17872      },
17873    );
17874
17875    prefix_test(
17876      ".foo { background-color: lab(40% 56.6 39) }",
17877      indoc! { r#"
17878        .foo {
17879          background-color: lab(40% 56.6 39);
17880        }
17881      "#},
17882      Browsers {
17883        safari: Some(15 << 16),
17884        ..Browsers::default()
17885      },
17886    );
17887
17888    prefix_test(
17889      ".foo { background-color: oklab(59.686% 0.1009 0.1192); }",
17890      indoc! { r#"
17891        .foo {
17892          background-color: #c65d07;
17893          background-color: lab(52.2319% 40.1449 59.9171);
17894        }
17895      "#},
17896      Browsers {
17897        chrome: Some(90 << 16),
17898        safari: Some(15 << 16),
17899        ..Browsers::default()
17900      },
17901    );
17902
17903    prefix_test(
17904      ".foo { background-color: oklab(59.686% 0.1009 0.1192); }",
17905      indoc! { r#"
17906        .foo {
17907          background-color: #c65d07;
17908          background-color: color(display-p3 .724144 .386777 .148795);
17909          background-color: lab(52.2319% 40.1449 59.9171);
17910        }
17911      "#},
17912      Browsers {
17913        chrome: Some(90 << 16),
17914        safari: Some(14 << 16),
17915        ..Browsers::default()
17916      },
17917    );
17918
17919    prefix_test(
17920      ".foo { background-color: lab(40% 56.6 39) }",
17921      indoc! { r#"
17922        .foo {
17923          background-color: #b32323;
17924          background-color: color(display-p3 .643308 .192455 .167712);
17925          background-color: lab(40% 56.6 39);
17926        }
17927      "#},
17928      Browsers {
17929        chrome: Some(90 << 16),
17930        safari: Some(14 << 16),
17931        ..Browsers::default()
17932      },
17933    );
17934
17935    prefix_test(
17936      ".foo { background-color: oklch(59.686% 0.15619 49.7694); }",
17937      indoc! { r#"
17938        .foo {
17939          background-color: #c65d06;
17940          background-color: lab(52.2321% 40.1417 59.9527);
17941        }
17942      "#},
17943      Browsers {
17944        chrome: Some(90 << 16),
17945        safari: Some(15 << 16),
17946        ..Browsers::default()
17947      },
17948    );
17949
17950    prefix_test(
17951      ".foo { background-color: color(sRGB 0.41587 0.503670 0.36664); }",
17952      indoc! { r#"
17953        .foo {
17954          background-color: #6a805d;
17955          background-color: color(srgb .41587 .50367 .36664);
17956        }
17957      "#},
17958      Browsers {
17959        chrome: Some(90 << 16),
17960        ..Browsers::default()
17961      },
17962    );
17963
17964    prefix_test(
17965      ".foo { background-color: color(display-p3 0.43313 0.50108 0.37950); }",
17966      indoc! { r#"
17967        .foo {
17968          background-color: #6a805d;
17969          background-color: color(display-p3 .43313 .50108 .3795);
17970        }
17971      "#},
17972      Browsers {
17973        chrome: Some(90 << 16),
17974        ..Browsers::default()
17975      },
17976    );
17977
17978    prefix_test(
17979      ".foo { background-color: color(display-p3 0.43313 0.50108 0.37950); }",
17980      indoc! { r#"
17981        .foo {
17982          background-color: #6a805d;
17983          background-color: color(display-p3 .43313 .50108 .3795);
17984        }
17985      "#},
17986      Browsers {
17987        chrome: Some(90 << 16),
17988        safari: Some(14 << 16),
17989        ..Browsers::default()
17990      },
17991    );
17992
17993    prefix_test(
17994      ".foo { background-color: color(display-p3 0.43313 0.50108 0.37950); }",
17995      indoc! { r#"
17996        .foo {
17997          background-color: color(display-p3 .43313 .50108 .3795);
17998        }
17999      "#},
18000      Browsers {
18001        safari: Some(14 << 16),
18002        ..Browsers::default()
18003      },
18004    );
18005
18006    prefix_test(
18007      ".foo { background-color: color(display-p3 0.43313 0.50108 0.37950); }",
18008      indoc! { r#"
18009        .foo {
18010          background-color: #6a805d;
18011          background-color: color(display-p3 .43313 .50108 .3795);
18012        }
18013      "#},
18014      Browsers {
18015        chrome: Some(90 << 16),
18016        safari: Some(15 << 16),
18017        ..Browsers::default()
18018      },
18019    );
18020
18021    prefix_test(
18022      ".foo { background-color: color(display-p3 0.43313 0.50108 0.37950); }",
18023      indoc! { r#"
18024        .foo {
18025          background-color: #6a805d;
18026          background-color: color(display-p3 .43313 .50108 .3795);
18027        }
18028      "#},
18029      Browsers {
18030        chrome: Some(90 << 16),
18031        ..Browsers::default()
18032      },
18033    );
18034
18035    prefix_test(
18036      ".foo { background-color: color(a98-rgb 0.44091 0.49971 0.37408); }",
18037      indoc! { r#"
18038        .foo {
18039          background-color: #6a805d;
18040          background-color: color(a98-rgb .44091 .49971 .37408);
18041        }
18042      "#},
18043      Browsers {
18044        chrome: Some(90 << 16),
18045        ..Browsers::default()
18046      },
18047    );
18048
18049    prefix_test(
18050      ".foo { background-color: color(a98-rgb 0.44091 0.49971 0.37408); }",
18051      indoc! { r#"
18052        .foo {
18053          background-color: color(a98-rgb .44091 .49971 .37408);
18054        }
18055      "#},
18056      Browsers {
18057        safari: Some(15 << 16),
18058        ..Browsers::default()
18059      },
18060    );
18061
18062    prefix_test(
18063      ".foo { background-color: color(prophoto-rgb 0.36589 0.41717 0.31333); }",
18064      indoc! { r#"
18065        .foo {
18066          background-color: #6a805d;
18067          background-color: color(prophoto-rgb .36589 .41717 .31333);
18068        }
18069      "#},
18070      Browsers {
18071        chrome: Some(90 << 16),
18072        ..Browsers::default()
18073      },
18074    );
18075
18076    prefix_test(
18077      ".foo { background-color: color(rec2020 0.42210 0.47580 0.35605); }",
18078      indoc! { r#"
18079        .foo {
18080          background-color: #728765;
18081          background-color: color(rec2020 .4221 .4758 .35605);
18082        }
18083      "#},
18084      Browsers {
18085        chrome: Some(90 << 16),
18086        ..Browsers::default()
18087      },
18088    );
18089
18090    prefix_test(
18091      ".foo { background-color: color(xyz-d50 0.2005 0.14089 0.4472); }",
18092      indoc! { r#"
18093        .foo {
18094          background-color: #7654cd;
18095          background-color: color(xyz-d50 .2005 .14089 .4472);
18096        }
18097      "#},
18098      Browsers {
18099        chrome: Some(90 << 16),
18100        ..Browsers::default()
18101      },
18102    );
18103
18104    prefix_test(
18105      ".foo { background-color: color(xyz-d65 0.21661 0.14602 0.59452); }",
18106      indoc! { r#"
18107        .foo {
18108          background-color: #7654cd;
18109          background-color: color(xyz .21661 .14602 .59452);
18110        }
18111      "#},
18112      Browsers {
18113        chrome: Some(90 << 16),
18114        ..Browsers::default()
18115      },
18116    );
18117
18118    prefix_test(
18119      ".foo { background-color: lch(50.998% 135.363 338) }",
18120      indoc! { r#"
18121        .foo {
18122          background-color: #ee00be;
18123          background-color: color(display-p3 .972962 -.362078 .804206);
18124          background-color: lch(50.998% 135.363 338);
18125        }
18126      "#},
18127      Browsers {
18128        chrome: Some(90 << 16),
18129        safari: Some(14 << 16),
18130        ..Browsers::default()
18131      },
18132    );
18133
18134    prefix_test(
18135      ".foo { color: lch(50.998% 135.363 338) }",
18136      indoc! { r#"
18137        .foo {
18138          color: #ee00be;
18139          color: color(display-p3 .972962 -.362078 .804206);
18140          color: lch(50.998% 135.363 338);
18141        }
18142      "#},
18143      Browsers {
18144        chrome: Some(90 << 16),
18145        safari: Some(14 << 16),
18146        ..Browsers::default()
18147      },
18148    );
18149
18150    prefix_test(
18151      ".foo { background: var(--image) lch(40% 68.735435 34.568626) }",
18152      indoc! { r#"
18153        .foo {
18154          background: var(--image) #b32323;
18155        }
18156
18157        @supports (color: lab(0% 0 0)) {
18158          .foo {
18159            background: var(--image) lab(40% 56.6 39);
18160          }
18161        }
18162      "#},
18163      Browsers {
18164        chrome: Some(90 << 16),
18165        ..Browsers::default()
18166      },
18167    );
18168
18169    prefix_test(
18170      r#"
18171        @supports (color: lab(0% 0 0)) {
18172          .foo {
18173            background: var(--image) lab(40% 56.6 39);
18174          }
18175        }
18176      "#,
18177      indoc! { r#"
18178        @supports (color: lab(0% 0 0)) {
18179          .foo {
18180            background: var(--image) lab(40% 56.6 39);
18181          }
18182        }
18183      "#},
18184      Browsers {
18185        chrome: Some(90 << 16),
18186        ..Browsers::default()
18187      },
18188    );
18189
18190    prefix_test(
18191      r#"
18192      .foo {
18193        color: red;
18194        color: lab(40% 56.6 39);
18195      }
18196    "#,
18197      indoc! {r#"
18198      .foo {
18199        color: red;
18200        color: lab(40% 56.6 39);
18201      }
18202    "#
18203      },
18204      Browsers {
18205        safari: Some(14 << 16),
18206        ..Browsers::default()
18207      },
18208    );
18209    prefix_test(
18210      r#"
18211      .foo {
18212        color: red;
18213        color: lab(40% 56.6 39);
18214      }
18215    "#,
18216      indoc! {r#"
18217      .foo {
18218        color: lab(40% 56.6 39);
18219      }
18220    "#
18221      },
18222      Browsers {
18223        safari: Some(16 << 16),
18224        ..Browsers::default()
18225      },
18226    );
18227
18228    prefix_test(
18229      r#"
18230      .foo {
18231        color: var(--fallback);
18232        color: lab(40% 56.6 39);
18233      }
18234    "#,
18235      indoc! {r#"
18236      .foo {
18237        color: var(--fallback);
18238        color: lab(40% 56.6 39);
18239      }
18240    "#
18241      },
18242      Browsers {
18243        safari: Some(14 << 16),
18244        ..Browsers::default()
18245      },
18246    );
18247
18248    prefix_test(
18249      r#"
18250      .foo {
18251        color: var(--fallback);
18252        color: lab(40% 56.6 39);
18253      }
18254    "#,
18255      indoc! {r#"
18256      .foo {
18257        color: lab(40% 56.6 39);
18258      }
18259    "#
18260      },
18261      Browsers {
18262        safari: Some(16 << 16),
18263        ..Browsers::default()
18264      },
18265    );
18266
18267    prefix_test(
18268      r#"
18269      .foo {
18270        color: red;
18271        color: var(--foo, lab(40% 56.6 39));
18272      }
18273    "#,
18274      indoc! {r#"
18275      .foo {
18276        color: var(--foo, color(display-p3 .643308 .192455 .167712));
18277      }
18278
18279      @supports (color: lab(0% 0 0)) {
18280        .foo {
18281          color: var(--foo, lab(40% 56.6 39));
18282        }
18283      }
18284    "#
18285      },
18286      Browsers {
18287        safari: Some(14 << 16),
18288        ..Browsers::default()
18289      },
18290    );
18291
18292    prefix_test(
18293      r#"
18294      @supports (color: lab(0% 0 0)) {
18295        .foo {
18296          color: var(--foo, lab(40% 56.6 39));
18297        }
18298      }
18299    "#,
18300      indoc! {r#"
18301      @supports (color: lab(0% 0 0)) {
18302        .foo {
18303          color: var(--foo, lab(40% 56.6 39));
18304        }
18305      }
18306    "#
18307      },
18308      Browsers {
18309        safari: Some(14 << 16),
18310        ..Browsers::default()
18311      },
18312    );
18313
18314    prefix_test(
18315      r#"
18316      .foo {
18317        --a: rgb(0 0 0 / var(--alpha));
18318        --b: rgb(50% 50% 50% / var(--alpha));
18319        --c: rgb(var(--x) 0 0);
18320        --d: rgb(0 var(--x) 0);
18321        --e: rgb(0 0 var(--x));
18322        --f: rgb(var(--x) 0 0 / var(--alpha));
18323        --g: rgb(0 var(--x) 0 / var(--alpha));
18324        --h: rgb(0 0 var(--x) / var(--alpha));
18325        --i: rgb(none 0 0 / var(--alpha));
18326        --j: rgb(from yellow r g b / var(--alpha));
18327      }
18328      "#,
18329      indoc! { r#"
18330        .foo {
18331          --a: rgba(0, 0, 0, var(--alpha));
18332          --b: rgba(128, 128, 128, var(--alpha));
18333          --c: rgb(var(--x) 0 0);
18334          --d: rgb(0 var(--x) 0);
18335          --e: rgb(0 0 var(--x));
18336          --f: rgb(var(--x) 0 0 / var(--alpha));
18337          --g: rgb(0 var(--x) 0 / var(--alpha));
18338          --h: rgb(0 0 var(--x) / var(--alpha));
18339          --i: rgb(none 0 0 / var(--alpha));
18340          --j: rgba(255, 255, 0, var(--alpha));
18341        }
18342      "#},
18343      Browsers {
18344        safari: Some(11 << 16),
18345        ..Browsers::default()
18346      },
18347    );
18348
18349    prefix_test(
18350      r#"
18351      .foo {
18352        --a: rgb(0 0 0 / var(--alpha));
18353        --b: rgb(50% 50% 50% / var(--alpha));
18354        --c: rgb(var(--x) 0 0);
18355        --d: rgb(0 var(--x) 0);
18356        --e: rgb(0 0 var(--x));
18357        --f: rgb(var(--x) 0 0 / var(--alpha));
18358        --g: rgb(0 var(--x) 0 / var(--alpha));
18359        --h: rgb(0 0 var(--x) / var(--alpha));
18360        --i: rgb(none 0 0 / var(--alpha));
18361        --j: rgb(from yellow r g b / var(--alpha));
18362      }
18363      "#,
18364      indoc! { r#"
18365        .foo {
18366          --a: rgb(0 0 0 / var(--alpha));
18367          --b: rgb(128 128 128 / var(--alpha));
18368          --c: rgb(var(--x) 0 0);
18369          --d: rgb(0 var(--x) 0);
18370          --e: rgb(0 0 var(--x));
18371          --f: rgb(var(--x) 0 0 / var(--alpha));
18372          --g: rgb(0 var(--x) 0 / var(--alpha));
18373          --h: rgb(0 0 var(--x) / var(--alpha));
18374          --i: rgb(none 0 0 / var(--alpha));
18375          --j: rgb(255 255 0 / var(--alpha));
18376        }
18377      "#},
18378      Browsers {
18379        safari: Some(13 << 16),
18380        ..Browsers::default()
18381      },
18382    );
18383
18384    prefix_test(
18385      r#"
18386      .foo {
18387        --a: hsl(270 100% 50% / var(--alpha));
18388        --b: hsl(var(--x) 0 0);
18389        --c: hsl(0 var(--x) 0);
18390        --d: hsl(0 0 var(--x));
18391        --e: hsl(var(--x) 0 0 / var(--alpha));
18392        --f: hsl(0 var(--x) 0 / var(--alpha));
18393        --g: hsl(0 0 var(--x) / var(--alpha));
18394        --h: hsl(270 100% 50% / calc(var(--alpha) / 2));
18395        --i: hsl(none 100% 50% / var(--alpha));
18396        --j: hsl(from yellow h s l / var(--alpha));
18397      }
18398      "#,
18399      indoc! { r#"
18400        .foo {
18401          --a: hsla(270, 100%, 50%, var(--alpha));
18402          --b: hsl(var(--x) 0 0);
18403          --c: hsl(0 var(--x) 0);
18404          --d: hsl(0 0 var(--x));
18405          --e: hsl(var(--x) 0 0 / var(--alpha));
18406          --f: hsl(0 var(--x) 0 / var(--alpha));
18407          --g: hsl(0 0 var(--x) / var(--alpha));
18408          --h: hsla(270, 100%, 50%, calc(var(--alpha) / 2));
18409          --i: hsl(none 100% 50% / var(--alpha));
18410          --j: hsla(60, 100%, 50%, var(--alpha));
18411        }
18412      "#},
18413      Browsers {
18414        safari: Some(11 << 16),
18415        ..Browsers::default()
18416      },
18417    );
18418
18419    prefix_test(
18420      r#"
18421      .foo {
18422        --a: hsl(270 100% 50% / var(--alpha));
18423        --b: hsl(var(--x) 0 0);
18424        --c: hsl(0 var(--x) 0);
18425        --d: hsl(0 0 var(--x));
18426        --e: hsl(var(--x) 0 0 / var(--alpha));
18427        --f: hsl(0 var(--x) 0 / var(--alpha));
18428        --g: hsl(0 0 var(--x) / var(--alpha));
18429        --h: hsl(270 100% 50% / calc(var(--alpha) / 2));
18430        --i: hsl(none 100% 50% / var(--alpha));
18431      }
18432      "#,
18433      indoc! { r#"
18434        .foo {
18435          --a: hsl(270 100% 50% / var(--alpha));
18436          --b: hsl(var(--x) 0 0);
18437          --c: hsl(0 var(--x) 0);
18438          --d: hsl(0 0 var(--x));
18439          --e: hsl(var(--x) 0 0 / var(--alpha));
18440          --f: hsl(0 var(--x) 0 / var(--alpha));
18441          --g: hsl(0 0 var(--x) / var(--alpha));
18442          --h: hsl(270 100% 50% / calc(var(--alpha) / 2));
18443          --i: hsl(none 100% 50% / var(--alpha));
18444        }
18445      "#},
18446      Browsers {
18447        safari: Some(13 << 16),
18448        ..Browsers::default()
18449      },
18450    );
18451
18452    test(
18453      r#"
18454      .foo {
18455        --a: rgb(50% 50% 50% / calc(100% / 2));
18456        --b: hsl(calc(360deg / 2) 50% 50%);
18457        --c: oklab(40.101% calc(0.1 + 0.2) 0.0453);
18458        --d: color(display-p3 0.43313 0.50108 calc(0.1 + 0.2));
18459        --e: rgb(calc(255 / 2), calc(255 / 2), calc(255 / 2));
18460      }
18461      "#,
18462      indoc! { r#"
18463        .foo {
18464          --a: #80808080;
18465          --b: #40bfbf;
18466          --c: oklab(40.101% .3 .0453);
18467          --d: color(display-p3 .43313 .50108 .3);
18468          --e: gray;
18469        }
18470      "#},
18471    );
18472  }
18473
18474  #[test]
18475  fn test_relative_color() {
18476    fn test(input: &str, output: &str) {
18477      let output = CssColor::parse_string(output)
18478        .unwrap()
18479        .to_css_string(PrinterOptions {
18480          minify: true,
18481          ..PrinterOptions::default()
18482        })
18483        .unwrap();
18484      minify_test(
18485        &format!(".foo {{ color: {} }}", input),
18486        &format!(".foo{{color:{}}}", output),
18487      );
18488    }
18489
18490    test("lab(from indianred calc(l * .8) a b)", "lab(43.1402% 45.7516 23.1557)");
18491    test("lch(from indianred calc(l + 10) c h)", "lch(63.9252% 51.2776 26.8448)");
18492    test("lch(from indianred l calc(c - 50) h)", "lch(53.9252% 1.27763 26.8448)");
18493    test(
18494      "lch(from indianred l c calc(h + 180deg))",
18495      "lch(53.9252% 51.2776 206.845)",
18496    );
18497    test("lch(from orchid l 30 h)", "lch(62.7526% 30 326.969)");
18498    test("lch(from orchid l 30 h)", "lch(62.7526% 30 326.969)");
18499    test("lch(from peru calc(l * 0.8) c h)", "lch(49.8022% 54.0117 63.6804)");
18500    test("rgb(from indianred 255 g b)", "rgb(255, 92, 92)");
18501    test("rgb(from indianred r g b / .5)", "rgba(205, 92, 92, .5)");
18502    test(
18503      "rgb(from rgba(205, 92, 92, .5) r g b / calc(alpha + .2))",
18504      "rgba(205, 92, 92, .7)",
18505    );
18506    test(
18507      "rgb(from rgba(205, 92, 92, .5) r g b / calc(alpha + .2))",
18508      "rgba(205, 92, 92, .7)",
18509    );
18510    test("lch(from indianred l sin(c) h)", "lch(53.9252% .84797 26.8448)");
18511    test("lch(from indianred l sqrt(c) h)", "lch(53.9252% 7.16084 26.8448)");
18512    test("lch(from indianred l c sin(h))", "lch(53.9252% 51.2776 .451575)");
18513    test("lch(from indianred calc(10% + 20%) c h)", "lch(30% 51.2776 26.8448)");
18514    test("lch(from indianred calc(10 + 20) c h)", "lch(30% 51.2776 26.8448)");
18515    test("lch(from indianred l c calc(10 + 20))", "lch(53.9252% 51.2776 30)");
18516    test(
18517      "lch(from indianred l c calc(10deg + 20deg))",
18518      "lch(53.9252% 51.2776 30)",
18519    );
18520    test(
18521      "lch(from indianred l c calc(10deg + 0.35rad))",
18522      "lch(53.9252% 51.2776 30.0535)",
18523    );
18524    minify_test(
18525      ".foo{color:lch(from currentColor l c sin(h))}",
18526      ".foo{color:lch(from currentColor l c sin(h))}",
18527    );
18528
18529    // The following tests were converted from WPT: https://github.com/web-platform-tests/wpt/blob/master/css/css-color/parsing/relative-color-valid.html
18530    // Find: test_valid_value\(`color`, `(.*?)`,\s*`(.*?)`\)
18531    // Replace: test("$1", "$2")
18532
18533    // Testing no modifications.
18534    test("rgb(from rebeccapurple r g b)", "#639");
18535    test("rgb(from rebeccapurple r g b / alpha)", "#639");
18536    test("rgb(from rgb(20%, 40%, 60%, 80%) r g b / alpha)", "#369c");
18537    test("rgb(from hsl(120deg 20% 50% / .5) r g b / alpha)", "#66996680");
18538
18539    // Test nesting relative colors.
18540    test("rgb(from rgb(from rebeccapurple r g b) r g b)", "#639");
18541
18542    // Testing non-sRGB origin colors to see gamut mapping.
18543    test("rgb(from color(display-p3 0 1 0) r g b / alpha)", "#00f942"); // Naive clip based mapping would give rgb(0, 255, 0).
18544    test("rgb(from lab(100% 104.3 -50.9) r g b)", "#fff"); // Naive clip based mapping would give rgb(255, 150, 255).
18545    test("rgb(from lab(0% 104.3 -50.9) r g b)", "#2a0022"); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black.
18546    test("rgb(from lch(100% 116 334) r g b)", "#fff"); // Naive clip based mapping would give rgb(255, 150, 255).
18547    test("rgb(from lch(0% 116 334) r g b)", "#2a0022"); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black.
18548    test("rgb(from oklab(100% 0.365 -0.16) r g b)", "#fff"); // Naive clip based mapping would give rgb(255, 92, 255).
18549    test("rgb(from oklab(0% 0.365 -0.16) r g b)", "#000"); // Naive clip based mapping would give rgb(19, 0, 24).
18550    test("rgb(from oklch(100% 0.399 336.3) r g b)", "#fff"); // Naive clip based mapping would give rgb(255, 91, 255).
18551    test("rgb(from oklch(0% 0.399 336.3) r g b)", "#000"); // Naive clip based mapping would give rgb(20, 0, 24).
18552
18553    // Testing replacement with 0.
18554    test("rgb(from rebeccapurple 0 0 0)", "rgb(0, 0, 0)");
18555    test("rgb(from rebeccapurple 0 0 0 / 0)", "rgba(0, 0, 0, 0)");
18556    test("rgb(from rebeccapurple 0 g b / alpha)", "rgb(0, 51, 153)");
18557    test("rgb(from rebeccapurple r 0 b / alpha)", "rgb(102, 0, 153)");
18558    test("rgb(from rebeccapurple r g 0 / alpha)", "rgb(102, 51, 0)");
18559    test("rgb(from rebeccapurple r g b / 0)", "rgba(102, 51, 153, 0)");
18560    test(
18561      "rgb(from rgb(20%, 40%, 60%, 80%) 0 g b / alpha)",
18562      "rgba(0, 102, 153, 0.8)",
18563    );
18564    test(
18565      "rgb(from rgb(20%, 40%, 60%, 80%) r 0 b / alpha)",
18566      "rgba(51, 0, 153, 0.8)",
18567    );
18568    test(
18569      "rgb(from rgb(20%, 40%, 60%, 80%) r g 0 / alpha)",
18570      "rgba(51, 102, 0, 0.8)",
18571    );
18572    test("rgb(from rgb(20%, 40%, 60%, 80%) r g b / 0)", "rgba(51, 102, 153, 0)");
18573
18574    // Testing replacement with a number.
18575    test("rgb(from rebeccapurple 25 g b / alpha)", "rgb(25, 51, 153)");
18576    test("rgb(from rebeccapurple r 25 b / alpha)", "rgb(102, 25, 153)");
18577    test("rgb(from rebeccapurple r g 25 / alpha)", "rgb(102, 51, 25)");
18578    test("rgb(from rebeccapurple r g b / .25)", "rgba(102, 51, 153, 0.25)");
18579    test(
18580      "rgb(from rgb(20%, 40%, 60%, 80%) 25 g b / alpha)",
18581      "rgba(25, 102, 153, 0.8)",
18582    );
18583    test(
18584      "rgb(from rgb(20%, 40%, 60%, 80%) r 25 b / alpha)",
18585      "rgba(51, 25, 153, 0.8)",
18586    );
18587    test(
18588      "rgb(from rgb(20%, 40%, 60%, 80%) r g 25 / alpha)",
18589      "rgba(51, 102, 25, 0.8)",
18590    );
18591    test(
18592      "rgb(from rgb(20%, 40%, 60%, 80%) r g b / .20)",
18593      "rgba(51, 102, 153, 0.2)",
18594    );
18595
18596    // Testing replacement with a percentage.
18597    test("rgb(from rebeccapurple 20% g b / alpha)", "rgb(51, 51, 153)");
18598    test("rgb(from rebeccapurple r 20% b / alpha)", "rgb(102, 51, 153)");
18599    test("rgb(from rebeccapurple r g 20% / alpha)", "rgb(102, 51, 51)");
18600    test("rgb(from rebeccapurple r g b / 20%)", "rgba(102, 51, 153, 0.2)");
18601    test(
18602      "rgb(from rgb(20%, 40%, 60%, 80%) 20% g b / alpha)",
18603      "rgba(51, 102, 153, 0.8)",
18604    );
18605    test(
18606      "rgb(from rgb(20%, 40%, 60%, 80%) r 20% b / alpha)",
18607      "rgba(51, 51, 153, 0.8)",
18608    );
18609    test(
18610      "rgb(from rgb(20%, 40%, 60%, 80%) r g 20% / alpha)",
18611      "rgba(51, 102, 51, 0.8)",
18612    );
18613    test(
18614      "rgb(from rgb(20%, 40%, 60%, 80%) r g b / 20%)",
18615      "rgba(51, 102, 153, 0.2)",
18616    );
18617
18618    // Testing replacement with a number for r, g, b but percent for alpha.
18619    test("rgb(from rebeccapurple 25 g b / 25%)", "rgba(25, 51, 153, 0.25)");
18620    test("rgb(from rebeccapurple r 25 b / 25%)", "rgba(102, 25, 153, 0.25)");
18621    test("rgb(from rebeccapurple r g 25 / 25%)", "rgba(102, 51, 25, 0.25)");
18622    test(
18623      "rgb(from rgb(20%, 40%, 60%, 80%) 25 g b / 25%)",
18624      "rgba(25, 102, 153, 0.25)",
18625    );
18626    test(
18627      "rgb(from rgb(20%, 40%, 60%, 80%) r 25 b / 25%)",
18628      "rgba(51, 25, 153, 0.25)",
18629    );
18630    test(
18631      "rgb(from rgb(20%, 40%, 60%, 80%) r g 25 / 25%)",
18632      "rgba(51, 102, 25, 0.25)",
18633    );
18634
18635    // Testing permutation.
18636    test("rgb(from rebeccapurple g b r)", "rgb(51, 153, 102)");
18637    test("rgb(from rebeccapurple b alpha r / g)", "rgba(153, 1, 102, 1)");
18638    test("rgb(from rebeccapurple r r r / r)", "rgba(102, 102, 102, 1)");
18639    test("rgb(from rebeccapurple alpha alpha alpha / alpha)", "rgb(1, 1, 1)");
18640    test("rgb(from rgb(20%, 40%, 60%, 80%) g b r)", "rgb(102, 153, 51)");
18641    test("rgb(from rgb(20%, 40%, 60%, 80%) b alpha r / g)", "rgba(153, 1, 51, 1)");
18642    test("rgb(from rgb(20%, 40%, 60%, 80%) r r r / r)", "rgba(51, 51, 51, 1)");
18643    test(
18644      "rgb(from rgb(20%, 40%, 60%, 80%) alpha alpha alpha / alpha)",
18645      "rgba(1, 1, 1, 0.8)",
18646    );
18647
18648    // Testing mixes of number and percentage. (These would not be allowed in the non-relative syntax).
18649    test("rgb(from rebeccapurple r 20% 10)", "rgb(102, 51, 10)");
18650    test("rgb(from rebeccapurple r 10 20%)", "rgb(102, 10, 51)");
18651    test("rgb(from rebeccapurple 0% 10 10)", "rgb(0, 10, 10)");
18652    test("rgb(from rgb(20%, 40%, 60%, 80%) r 20% 10)", "rgb(51, 51, 10)");
18653    test("rgb(from rgb(20%, 40%, 60%, 80%) r 10 20%)", "rgb(51, 10, 51)");
18654    test("rgb(from rgb(20%, 40%, 60%, 80%) 0% 10 10)", "rgb(0, 10, 10)");
18655
18656    // Testing with calc().
18657    test("rgb(from rebeccapurple calc(r) calc(g) calc(b))", "rgb(102, 51, 153)");
18658    test("rgb(from rebeccapurple r calc(g * 2) 10)", "rgb(102, 102, 10)");
18659    test("rgb(from rebeccapurple b calc(r * .5) 10)", "rgb(153, 51, 10)");
18660    test("rgb(from rebeccapurple r calc(g * .5 + g * .5) 10)", "rgb(102, 51, 10)");
18661    test("rgb(from rebeccapurple r calc(b * .5 - g * .5) 10)", "rgb(102, 51, 10)");
18662    test(
18663      "rgb(from rgb(20%, 40%, 60%, 80%) calc(r) calc(g) calc(b) / calc(alpha))",
18664      "rgba(51, 102, 153, 0.8)",
18665    );
18666
18667    // Testing with 'none'.
18668    test("rgb(from rebeccapurple none none none)", "rgb(0, 0, 0)");
18669    test("rgb(from rebeccapurple none none none / none)", "rgba(0, 0, 0, 0)");
18670    test("rgb(from rebeccapurple r g none)", "rgb(102, 51, 0)");
18671    test("rgb(from rebeccapurple r g none / alpha)", "rgb(102, 51, 0)");
18672    test("rgb(from rebeccapurple r g b / none)", "rgba(102, 51, 153, 0)");
18673    test(
18674      "rgb(from rgb(20% 40% 60% / 80%) r g none / alpha)",
18675      "rgba(51, 102, 0, 0.8)",
18676    );
18677    test("rgb(from rgb(20% 40% 60% / 80%) r g b / none)", "rgba(51, 102, 153, 0)");
18678    // FIXME: Clarify with spec editors if 'none' should pass through to the constants.
18679    test("rgb(from rgb(none none none) r g b)", "rgb(0, 0, 0)");
18680    test("rgb(from rgb(none none none / none) r g b / alpha)", "rgba(0, 0, 0, 0)");
18681    test("rgb(from rgb(20% none 60%) r g b)", "rgb(51, 0, 153)");
18682    test(
18683      "rgb(from rgb(20% 40% 60% / none) r g b / alpha)",
18684      "rgba(51, 102, 153, 0)",
18685    );
18686
18687    // hsl(from ...)
18688
18689    // Testing no modifications.
18690    test("hsl(from rebeccapurple h s l)", "rgb(102, 51, 153)");
18691    test("hsl(from rebeccapurple h s l / alpha)", "rgb(102, 51, 153)");
18692    test(
18693      "hsl(from rgb(20%, 40%, 60%, 80%) h s l / alpha)",
18694      "rgba(51, 102, 153, 0.8)",
18695    );
18696    test(
18697      "hsl(from hsl(120deg 20% 50% / .5) h s l / alpha)",
18698      "rgba(102, 153, 102, 0.5)",
18699    );
18700
18701    // Test nesting relative colors.
18702    test("hsl(from hsl(from rebeccapurple h s l) h s l)", "rgb(102, 51, 153)");
18703
18704    // Testing non-sRGB origin colors to see gamut mapping.
18705    test("hsl(from color(display-p3 0 1 0) h s l / alpha)", "rgb(0, 249, 66)"); // Naive clip based mapping would give rgb(0, 255, 0).
18706    test("hsl(from lab(100% 104.3 -50.9) h s l)", "rgb(255, 255, 255)"); // Naive clip based mapping would give rgb(255, 150, 255).
18707    test("hsl(from lab(0% 104.3 -50.9) h s l)", "rgb(42, 0, 34)"); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
18708    test("hsl(from lch(100% 116 334) h s l)", "rgb(255, 255, 255)"); // Naive clip based mapping would give rgb(255, 150, 255).
18709    test("hsl(from lch(0% 116 334) h s l)", "rgb(42, 0, 34)"); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
18710    test("hsl(from oklab(100% 0.365 -0.16) h s l)", "rgb(255, 255, 255)"); // Naive clip based mapping would give rgb(255, 92, 255).
18711    test("hsl(from oklab(0% 0.365 -0.16) h s l)", "rgb(0, 0, 0)"); // Naive clip based mapping would give rgb(19, 0, 24).
18712    test("hsl(from oklch(100% 0.399 336.3) h s l)", "rgb(255, 255, 255)"); // Naive clip based mapping would give rgb(255, 91, 255).
18713    test("hsl(from oklch(0% 0.399 336.3) h s l)", "rgb(0, 0, 0)"); // Naive clip based mapping would give rgb(20, 0, 24).
18714
18715    // Testing replacement with 0.
18716    test("hsl(from rebeccapurple 0 0% 0%)", "rgb(0, 0, 0)");
18717    test("hsl(from rebeccapurple 0deg 0% 0%)", "rgb(0, 0, 0)");
18718    test("hsl(from rebeccapurple 0 0% 0% / 0)", "rgba(0, 0, 0, 0)");
18719    test("hsl(from rebeccapurple 0deg 0% 0% / 0)", "rgba(0, 0, 0, 0)");
18720    test("hsl(from rebeccapurple 0 s l / alpha)", "rgb(153, 51, 51)");
18721    test("hsl(from rebeccapurple 0deg s l / alpha)", "rgb(153, 51, 51)");
18722    test("hsl(from rebeccapurple h 0% l / alpha)", "rgb(102, 102, 102)");
18723    test("hsl(from rebeccapurple h s 0% / alpha)", "rgb(0, 0, 0)");
18724    test("hsl(from rebeccapurple h s l / 0)", "rgba(102, 51, 153, 0)");
18725    test(
18726      "hsl(from rgb(20%, 40%, 60%, 80%) 0 s l / alpha)",
18727      "rgba(153, 51, 51, 0.8)",
18728    );
18729    test(
18730      "hsl(from rgb(20%, 40%, 60%, 80%) 0deg s l / alpha)",
18731      "rgba(153, 51, 51, 0.8)",
18732    );
18733    test(
18734      "hsl(from rgb(20%, 40%, 60%, 80%) h 0% l / alpha)",
18735      "rgba(102, 102, 102, 0.8)",
18736    );
18737    test("hsl(from rgb(20%, 40%, 60%, 80%) h s 0% / alpha)", "rgba(0, 0, 0, 0.8)");
18738    test("hsl(from rgb(20%, 40%, 60%, 80%) h s l / 0)", "rgba(51, 102, 153, 0)");
18739
18740    // Testing replacement with a constant.
18741    test("hsl(from rebeccapurple 25 s l / alpha)", "rgb(153, 94, 51)");
18742    test("hsl(from rebeccapurple 25deg s l / alpha)", "rgb(153, 94, 51)");
18743    test("hsl(from rebeccapurple h 20% l / alpha)", "rgb(102, 82, 122)");
18744    test("hsl(from rebeccapurple h s 20% / alpha)", "rgb(51, 25, 77)");
18745    test("hsl(from rebeccapurple h s l / .25)", "rgba(102, 51, 153, 0.25)");
18746    test(
18747      "hsl(from rgb(20%, 40%, 60%, 80%) 25 s l / alpha)",
18748      "rgba(153, 94, 51, 0.8)",
18749    );
18750    test(
18751      "hsl(from rgb(20%, 40%, 60%, 80%) 25deg s l / alpha)",
18752      "rgba(153, 94, 51, 0.8)",
18753    );
18754    test(
18755      "hsl(from rgb(20%, 40%, 60%, 80%) h 20% l / alpha)",
18756      "rgba(82, 102, 122, 0.8)",
18757    );
18758    test(
18759      "hsl(from rgb(20%, 40%, 60%, 80%) h s 20% / alpha)",
18760      "rgba(25, 51, 77, 0.8)",
18761    );
18762    test(
18763      "hsl(from rgb(20%, 40%, 60%, 80%) h s l / .2)",
18764      "rgba(51, 102, 153, 0.2)",
18765    );
18766
18767    // Testing valid permutation (types match).
18768    test("hsl(from rebeccapurple h l s)", "rgb(128, 77, 179)");
18769    test(
18770      "hsl(from rebeccapurple h calc(alpha * 100) l / calc(s / 100))",
18771      "rgba(102, 0, 204, 0.5)",
18772    );
18773    test(
18774      "hsl(from rebeccapurple h l l / calc(l / 100))",
18775      "rgba(102, 61, 143, 0.4)",
18776    );
18777    test(
18778      "hsl(from rebeccapurple h calc(alpha * 100) calc(alpha * 100) / calc(alpha * 100))",
18779      "rgb(255, 255, 255)",
18780    );
18781    test("hsl(from rgb(20%, 40%, 60%, 80%) h l s)", "rgb(77, 128, 179)");
18782    test(
18783      "hsl(from rgb(20%, 40%, 60%, 80%) h calc(alpha * 100) l / calc(s / 100))",
18784      "rgba(20, 102, 184, 0.5)",
18785    );
18786    test(
18787      "hsl(from rgb(20%, 40%, 60%, 80%) h l l / calc(l / 100))",
18788      "rgba(61, 102, 143, 0.4)",
18789    );
18790    test(
18791      "hsl(from rgb(20%, 40%, 60%, 80%) h calc(alpha * 100) calc(alpha * 100) / alpha)",
18792      "rgba(163, 204, 245, 0.8)",
18793    );
18794
18795    // Testing with calc().
18796    test("hsl(from rebeccapurple calc(h) calc(s) calc(l))", "rgb(102, 51, 153)");
18797    test(
18798      "hsl(from rgb(20%, 40%, 60%, 80%) calc(h) calc(s) calc(l) / calc(alpha))",
18799      "rgba(51, 102, 153, 0.8)",
18800    );
18801
18802    // Testing with 'none'.
18803    test("hsl(from rebeccapurple none none none)", "rgb(0, 0, 0)");
18804    test("hsl(from rebeccapurple none none none / none)", "rgba(0, 0, 0, 0)");
18805    test("hsl(from rebeccapurple h s none)", "rgb(0, 0, 0)");
18806    test("hsl(from rebeccapurple h s none / alpha)", "rgb(0, 0, 0)");
18807    test("hsl(from rebeccapurple h s l / none)", "rgba(102, 51, 153, 0)");
18808    test("hsl(from rebeccapurple none s l / alpha)", "rgb(153, 51, 51)");
18809    test(
18810      "hsl(from hsl(120deg 20% 50% / .5) h s none / alpha)",
18811      "rgba(0, 0, 0, 0.5)",
18812    );
18813    test(
18814      "hsl(from hsl(120deg 20% 50% / .5) h s l / none)",
18815      "rgba(102, 153, 102, 0)",
18816    );
18817    test(
18818      "hsl(from hsl(120deg 20% 50% / .5) none s l / alpha)",
18819      "rgba(153, 102, 102, 0.5)",
18820    );
18821    // FIXME: Clarify with spec editors if 'none' should pass through to the constants.
18822    test("hsl(from hsl(none none none) h s l)", "rgb(0, 0, 0)");
18823    test("hsl(from hsl(none none none / none) h s l / alpha)", "rgba(0, 0, 0, 0)");
18824    test("hsl(from hsl(120deg none 50% / .5) h s l)", "rgb(128, 128, 128)");
18825    test(
18826      "hsl(from hsl(120deg 20% 50% / none) h s l / alpha)",
18827      "rgba(102, 153, 102, 0)",
18828    );
18829    test(
18830      "hsl(from hsl(none 20% 50% / .5) h s l / alpha)",
18831      "rgba(153, 102, 102, 0.5)",
18832    );
18833
18834    // hwb(from ...)
18835
18836    // Testing no modifications.
18837    test("hwb(from rebeccapurple h w b)", "rgb(102, 51, 153)");
18838    test("hwb(from rebeccapurple h w b / alpha)", "rgb(102, 51, 153)");
18839    test(
18840      "hwb(from rgb(20%, 40%, 60%, 80%) h w b / alpha)",
18841      "rgba(51, 102, 153, 0.8)",
18842    );
18843    test(
18844      "hwb(from hsl(120deg 20% 50% / .5) h w b / alpha)",
18845      "rgba(102, 153, 102, 0.5)",
18846    );
18847
18848    // Test nesting relative colors.
18849    test("hwb(from hwb(from rebeccapurple h w b) h w b)", "rgb(102, 51, 153)");
18850
18851    // Testing non-sRGB origin colors to see gamut mapping.
18852    test("hwb(from color(display-p3 0 1 0) h w b / alpha)", "rgb(0, 249, 66)"); // Naive clip based mapping would give rgb(0, 255, 0).
18853    test("hwb(from lab(100% 104.3 -50.9) h w b)", "rgb(255, 255, 255)"); // Naive clip based mapping would give rgb(255, 150, 255).
18854    test("hwb(from lab(0% 104.3 -50.9) h w b)", "rgb(42, 0, 34)"); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
18855    test("hwb(from lch(100% 116 334) h w b)", "rgb(255, 255, 255)"); // Naive clip based mapping would give rgb(255, 150, 255).
18856    test("hwb(from lch(0% 116 334) h w b)", "rgb(42, 0, 34)"); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
18857    test("hwb(from oklab(100% 0.365 -0.16) h w b)", "rgb(255, 255, 255)"); // Naive clip based mapping would give rgb(255, 92, 255).
18858    test("hwb(from oklab(0% 0.365 -0.16) h w b)", "rgb(0, 0, 0)"); // Naive clip based mapping would give rgb(19, 0, 24).
18859    test("hwb(from oklch(100% 0.399 336.3) h w b)", "rgb(255, 255, 255)"); // Naive clip based mapping would give rgb(255, 91, 255).
18860    test("hwb(from oklch(0% 0.399 336.3) h w b)", "rgb(0, 0, 0)"); // Naive clip based mapping would give rgb(20, 0, 24).
18861
18862    // Testing replacement with 0.
18863    test("hwb(from rebeccapurple 0 0% 0%)", "rgb(255, 0, 0)");
18864    test("hwb(from rebeccapurple 0deg 0% 0%)", "rgb(255, 0, 0)");
18865    test("hwb(from rebeccapurple 0 0% 0% / 0)", "rgba(255, 0, 0, 0)");
18866    test("hwb(from rebeccapurple 0deg 0% 0% / 0)", "rgba(255, 0, 0, 0)");
18867    test("hwb(from rebeccapurple 0 w b / alpha)", "rgb(153, 51, 51)");
18868    test("hwb(from rebeccapurple 0deg w b / alpha)", "rgb(153, 51, 51)");
18869    test("hwb(from rebeccapurple h 0% b / alpha)", "rgb(77, 0, 153)");
18870    test("hwb(from rebeccapurple h w 0% / alpha)", "rgb(153, 51, 255)");
18871    test("hwb(from rebeccapurple h w b / 0)", "rgba(102, 51, 153, 0)");
18872    test(
18873      "hwb(from rgb(20%, 40%, 60%, 80%) 0 w b / alpha)",
18874      "rgba(153, 51, 51, 0.8)",
18875    );
18876    test(
18877      "hwb(from rgb(20%, 40%, 60%, 80%) 0deg w b / alpha)",
18878      "rgba(153, 51, 51, 0.8)",
18879    );
18880    test(
18881      "hwb(from rgb(20%, 40%, 60%, 80%) h 0% b / alpha)",
18882      "rgba(0, 77, 153, 0.8)",
18883    );
18884    test(
18885      "hwb(from rgb(20%, 40%, 60%, 80%) h w 0% / alpha)",
18886      "rgba(51, 153, 255, 0.8)",
18887    );
18888    test("hwb(from rgb(20%, 40%, 60%, 80%) h w b / 0)", "rgba(51, 102, 153, 0)");
18889
18890    // Testing replacement with a constant.
18891    test("hwb(from rebeccapurple 25 w b / alpha)", "rgb(153, 94, 51)");
18892    test("hwb(from rebeccapurple 25deg w b / alpha)", "rgb(153, 94, 51)");
18893    test("hwb(from rebeccapurple h 20% b / alpha)", "rgb(102, 51, 153)");
18894    test("hwb(from rebeccapurple h w 20% / alpha)", "rgb(128, 51, 204)");
18895    test("hwb(from rebeccapurple h w b / .2)", "rgba(102, 51, 153, 0.2)");
18896    test(
18897      "hwb(from rgb(20%, 40%, 60%, 80%) 25 w b / alpha)",
18898      "rgba(153, 94, 51, 0.8)",
18899    );
18900    test(
18901      "hwb(from rgb(20%, 40%, 60%, 80%) 25deg w b / alpha)",
18902      "rgba(153, 94, 51, 0.8)",
18903    );
18904    test(
18905      "hwb(from rgb(20%, 40%, 60%, 80%) h 20% b / alpha)",
18906      "rgba(51, 102, 153, 0.8)",
18907    );
18908    test(
18909      "hwb(from rgb(20%, 40%, 60%, 80%) h w 20% / alpha)",
18910      "rgba(51, 128, 204, 0.8)",
18911    );
18912    test(
18913      "hwb(from rgb(20%, 40%, 60%, 80%) h w b / .2)",
18914      "rgba(51, 102, 153, 0.2)",
18915    );
18916
18917    // Testing valid permutation (types match).
18918    test("hwb(from rebeccapurple h b w)", "rgb(153, 102, 204)");
18919    test(
18920      "hwb(from rebeccapurple h calc(alpha * 100) w / calc(b / 100))",
18921      "rgba(213, 213, 213, 0.4)",
18922    );
18923    test(
18924      "hwb(from rebeccapurple h w w / calc(w / 100))",
18925      "rgba(128, 51, 204, 0.2)",
18926    );
18927    test(
18928      "hwb(from rebeccapurple h calc(alpha * 100) calc(alpha * 100) / alpha)",
18929      "rgb(128, 128, 128)",
18930    );
18931    test("hwb(from rgb(20%, 40%, 60%, 80%) h b w)", "rgb(102, 153, 204)");
18932    test(
18933      "hwb(from rgb(20%, 40%, 60%, 80%) h calc(alpha * 100) w / calc(b / 100))",
18934      "rgba(204, 204, 204, 0.4)",
18935    );
18936    test(
18937      "hwb(from rgb(20%, 40%, 60%, 80%) h w w / calc(w / 100))",
18938      "rgba(51, 128, 204, 0.2)",
18939    );
18940    test(
18941      "hwb(from rgb(20%, 40%, 60%, 80%) h calc(alpha * 100) calc(alpha * 100) / alpha)",
18942      "rgba(128, 128, 128, 0.8)",
18943    );
18944
18945    // Testing with calc().
18946    test("hwb(from rebeccapurple calc(h) calc(w) calc(b))", "rgb(102, 51, 153)");
18947    test(
18948      "hwb(from rgb(20%, 40%, 60%, 80%) calc(h) calc(w) calc(b) / calc(alpha))",
18949      "rgba(51, 102, 153, 0.8)",
18950    );
18951
18952    // Testing with 'none'.
18953    test("hwb(from rebeccapurple none none none)", "rgb(255, 0, 0)");
18954    test("hwb(from rebeccapurple none none none / none)", "rgba(255, 0, 0, 0)");
18955    test("hwb(from rebeccapurple h w none)", "rgb(153, 51, 255)");
18956    test("hwb(from rebeccapurple h w none / alpha)", "rgb(153, 51, 255)");
18957    test("hwb(from rebeccapurple h w b / none)", "rgba(102, 51, 153, 0)");
18958    test("hwb(from rebeccapurple none w b / alpha)", "rgb(153, 51, 51)");
18959    test(
18960      "hwb(from hwb(120deg 20% 50% / .5) h w none / alpha)",
18961      "rgba(51, 255, 51, 0.5)",
18962    );
18963    test(
18964      "hwb(from hwb(120deg 20% 50% / .5) h w b / none)",
18965      "rgba(51, 128, 51, 0)",
18966    );
18967    test(
18968      "hwb(from hwb(120deg 20% 50% / .5) none w b / alpha)",
18969      "rgba(128, 51, 51, 0.5)",
18970    );
18971    // FIXME: Clarify with spec editors if 'none' should pass through to the constants.
18972    test("hwb(from hwb(none none none) h w b)", "rgb(255, 0, 0)");
18973    test(
18974      "hwb(from hwb(none none none / none) h w b / alpha)",
18975      "rgba(255, 0, 0, 0)",
18976    );
18977    test("hwb(from hwb(120deg none 50% / .5) h w b)", "rgb(0, 128, 0)");
18978    test(
18979      "hwb(from hwb(120deg 20% 50% / none) h w b / alpha)",
18980      "rgba(51, 128, 51, 0)",
18981    );
18982    test(
18983      "hwb(from hwb(none 20% 50% / .5) h w b / alpha)",
18984      "rgba(128, 51, 51, 0.5)",
18985    );
18986
18987    for color_space in &["lab", "oklab"] {
18988      // Testing no modifications.
18989      test(
18990        &format!("{}(from {}(25% 20 50) l a b)", color_space, color_space),
18991        &format!("{}(25% 20 50)", color_space),
18992      );
18993      test(
18994        &format!("{}(from {}(25% 20 50) l a b / alpha)", color_space, color_space),
18995        &format!("{}(25% 20 50)", color_space),
18996      );
18997      test(
18998        &format!("{}(from {}(25% 20 50 / 40%) l a b / alpha)", color_space, color_space),
18999        &format!("{}(25% 20 50 / 0.4)", color_space),
19000      );
19001      test(
19002        &format!(
19003          "{}(from {}(200% 300 400 / 500%) l a b / alpha)",
19004          color_space, color_space
19005        ),
19006        &format!("{}(200% 300 400)", color_space),
19007      );
19008      test(
19009        &format!(
19010          "{}(from {}(-200% -300 -400 / -500%) l a b / alpha)",
19011          color_space, color_space
19012        ),
19013        &format!("{}(0% -300 -400 / 0)", color_space),
19014      );
19015
19016      // Test nesting relative colors.
19017      test(
19018        &format!(
19019          "{}(from {}(from {}(25% 20 50) l a b) l a b)",
19020          color_space, color_space, color_space
19021        ),
19022        &format!("{}(25% 20 50)", color_space),
19023      );
19024
19025      // Testing non-${colorSpace} origin to see conversion.
19026      test(
19027        &format!("{}(from color(display-p3 0 0 0) l a b / alpha)", color_space),
19028        &format!("{}(0% 0 0)", color_space),
19029      );
19030
19031      // Testing replacement with 0.
19032      test(
19033        &format!("{}(from {}(25% 20 50) 0% 0 0)", color_space, color_space),
19034        &format!("{}(0% 0 0)", color_space),
19035      );
19036      test(
19037        &format!("{}(from {}(25% 20 50) 0% 0 0 / 0)", color_space, color_space),
19038        &format!("{}(0% 0 0 / 0)", color_space),
19039      );
19040      test(
19041        &format!("{}(from {}(25% 20 50) 0% a b / alpha)", color_space, color_space),
19042        &format!("{}(0% 20 50)", color_space),
19043      );
19044      test(
19045        &format!("{}(from {}(25% 20 50) l 0 b / alpha)", color_space, color_space),
19046        &format!("{}(25% 0 50)", color_space),
19047      );
19048      test(
19049        &format!("{}(from {}(25% 20 50) l a 0 / alpha)", color_space, color_space),
19050        &format!("{}(25% 20 0)", color_space),
19051      );
19052      test(
19053        &format!("{}(from {}(25% 20 50) l a b / 0)", color_space, color_space),
19054        &format!("{}(25% 20 50 / 0)", color_space),
19055      );
19056      test(
19057        &format!("{}(from {}(25% 20 50 / 40%) 0% a b / alpha)", color_space, color_space),
19058        &format!("{}(0% 20 50 / 0.4)", color_space),
19059      );
19060      test(
19061        &format!("{}(from {}(25% 20 50 / 40%) l 0 b / alpha)", color_space, color_space),
19062        &format!("{}(25% 0 50 / 0.4)", color_space),
19063      );
19064      test(
19065        &format!("{}(from {}(25% 20 50 / 40%) l a 0 / alpha)", color_space, color_space),
19066        &format!("{}(25% 20 0 / 0.4)", color_space),
19067      );
19068      test(
19069        &format!("{}(from {}(25% 20 50 / 40%) l a b / 0)", color_space, color_space),
19070        &format!("{}(25% 20 50 / 0)", color_space),
19071      );
19072
19073      // Testing replacement with a constant.
19074      test(
19075        &format!("{}(from {}(25% 20 50) 35% a b / alpha)", color_space, color_space),
19076        &format!("{}(35% 20 50)", color_space),
19077      );
19078      test(
19079        &format!("{}(from {}(25% 20 50) l 35 b / alpha)", color_space, color_space),
19080        &format!("{}(25% 35 50)", color_space),
19081      );
19082      test(
19083        &format!("{}(from {}(25% 20 50) l a 35 / alpha)", color_space, color_space),
19084        &format!("{}(25% 20 35)", color_space),
19085      );
19086      test(
19087        &format!("{}(from {}(25% 20 50) l a b / .35)", color_space, color_space),
19088        &format!("{}(25% 20 50 / 0.35)", color_space),
19089      );
19090      test(
19091        &format!("{}(from {}(25% 20 50 / 40%) 35% a b / alpha)", color_space, color_space),
19092        &format!("{}(35% 20 50 / 0.4)", color_space),
19093      );
19094      test(
19095        &format!("{}(from {}(25% 20 50 / 40%) l 35 b / alpha)", color_space, color_space),
19096        &format!("{}(25% 35 50 / 0.4)", color_space),
19097      );
19098      test(
19099        &format!("{}(from {}(25% 20 50 / 40%) l a 35 / alpha)", color_space, color_space),
19100        &format!("{}(25% 20 35 / 0.4)", color_space),
19101      );
19102      test(
19103        &format!("{}(from {}(25% 20 50 / 40%) l a b / .35)", color_space, color_space),
19104        &format!("{}(25% 20 50 / 0.35)", color_space),
19105      );
19106      test(
19107        &format!(
19108          "{}(from {}(70% 45 30 / 40%) 200% 300 400 / 500)",
19109          color_space, color_space
19110        ),
19111        &format!("{}(200% 300 400)", color_space),
19112      );
19113      test(
19114        &format!(
19115          "{}(from {}(70% 45 30 / 40%) -200% -300 -400 / -500)",
19116          color_space, color_space
19117        ),
19118        &format!("{}(0% -300 -400 / 0)", color_space),
19119      );
19120
19121      // Testing valid permutation (types match).
19122      test(
19123        &format!("{}(from {}(25% 20 50) l b a)", color_space, color_space),
19124        &format!("{}(25% 50 20)", color_space),
19125      );
19126      test(
19127        &format!("{}(from {}(25% 20 50) l a a / a)", color_space, color_space),
19128        &format!("{}(25% 20 20)", color_space),
19129      );
19130      test(
19131        &format!("{}(from {}(25% 20 50 / 40%) l b a)", color_space, color_space),
19132        &format!("{}(25% 50 20)", color_space),
19133      );
19134      test(
19135        &format!("{}(from {}(25% 20 50 / 40%) l a a / a)", color_space, color_space),
19136        &format!("{}(25% 20 20)", color_space),
19137      );
19138
19139      // Testing with calc().
19140      test(
19141        &format!(
19142          "{}(from {}(25% 20 50) calc(l) calc(a) calc(b))",
19143          color_space, color_space
19144        ),
19145        &format!("{}(25% 20 50)", color_space),
19146      );
19147      test(
19148        &format!(
19149          "{}(from {}(25% 20 50 / 40%) calc(l) calc(a) calc(b) / calc(alpha))",
19150          color_space, color_space
19151        ),
19152        &format!("{}(25% 20 50 / 0.4)", color_space),
19153      );
19154
19155      // Testing with 'none'.
19156      test(
19157        &format!("{}(from {}(25% 20 50) none none none)", color_space, color_space),
19158        &format!("{}(none none none)", color_space),
19159      );
19160      test(
19161        &format!("{}(from {}(25% 20 50) none none none / none)", color_space, color_space),
19162        &format!("{}(none none none / none)", color_space),
19163      );
19164      test(
19165        &format!("{}(from {}(25% 20 50) l a none)", color_space, color_space),
19166        &format!("{}(25% 20 none)", color_space),
19167      );
19168      test(
19169        &format!("{}(from {}(25% 20 50) l a none / alpha)", color_space, color_space),
19170        &format!("{}(25% 20 none)", color_space),
19171      );
19172      test(
19173        &format!("{}(from {}(25% 20 50) l a b / none)", color_space, color_space),
19174        &format!("{}(25% 20 50 / none)", color_space),
19175      );
19176      test(
19177        &format!(
19178          "{}(from {}(25% 20 50 / 40%) l a none / alpha)",
19179          color_space, color_space
19180        ),
19181        &format!("{}(25% 20 none / 0.4)", color_space),
19182      );
19183      test(
19184        &format!("{}(from {}(25% 20 50 / 40%) l a b / none)", color_space, color_space),
19185        &format!("{}(25% 20 50 / none)", color_space),
19186      );
19187      // FIXME: Clarify with spec editors if 'none' should pass through to the constants.
19188      test(
19189        &format!("{}(from {}(none none none) l a b)", color_space, color_space),
19190        &format!("{}(0% 0 0)", color_space),
19191      );
19192      test(
19193        &format!(
19194          "{}(from {}(none none none / none) l a b / alpha)",
19195          color_space, color_space
19196        ),
19197        &format!("{}(0% 0 0 / 0)", color_space),
19198      );
19199      test(
19200        &format!("{}(from {}(25% none 50) l a b)", color_space, color_space),
19201        &format!("{}(25% 0 50)", color_space),
19202      );
19203      test(
19204        &format!("{}(from {}(25% 20 50 / none) l a b / alpha)", color_space, color_space),
19205        &format!("{}(25% 20 50 / 0)", color_space),
19206      );
19207    }
19208
19209    // test_valid_value\(`color`, `\$\{colorSpace\}\(from \$\{colorSpace\}\((.*?)`,\s*`\$\{colorSpace\}(.*?)`\)
19210    // test(&format!("{}(from {}($1", color_space, color_space), &format!("{}$2", color_space))
19211
19212    for color_space in &["lch", "oklch"] {
19213      // Testing no modifications.
19214      test(
19215        &format!("{}(from {}(70% 45 30) l c h)", color_space, color_space),
19216        &format!("{}(70% 45 30)", color_space),
19217      );
19218      test(
19219        &format!("{}(from {}(70% 45 30) l c h / alpha)", color_space, color_space),
19220        &format!("{}(70% 45 30)", color_space),
19221      );
19222      test(
19223        &format!("{}(from {}(70% 45 30 / 40%) l c h / alpha)", color_space, color_space),
19224        &format!("{}(70% 45 30 / 0.4)", color_space),
19225      );
19226      test(
19227        &format!(
19228          "{}(from {}(200% 300 400 / 500%) l c h / alpha)",
19229          color_space, color_space
19230        ),
19231        &format!("{}(200% 300 40)", color_space),
19232      );
19233      test(
19234        &format!(
19235          "{}(from {}(-200% -300 -400 / -500%) l c h / alpha)",
19236          color_space, color_space
19237        ),
19238        &format!("{}(0% 0 320 / 0)", color_space),
19239      );
19240
19241      // Test nesting relative colors.
19242      test(
19243        &format!(
19244          "{}(from {}(from {}(70% 45 30) l c h) l c h)",
19245          color_space, color_space, color_space
19246        ),
19247        &format!("{}(70% 45 30)", color_space),
19248      );
19249
19250      // Testing non-sRGB origin colors (no gamut mapping will happen since the destination is not a bounded RGB color space).
19251      test(
19252        &format!("{}(from color(display-p3 0 0 0) l c h / alpha)", color_space),
19253        &format!("{}(0% 0 0)", color_space),
19254      );
19255
19256      // Testing replacement with 0.
19257      test(
19258        &format!("{}(from {}(70% 45 30) 0% 0 0)", color_space, color_space),
19259        &format!("{}(0% 0 0)", color_space),
19260      );
19261      test(
19262        &format!("{}(from {}(70% 45 30) 0% 0 0deg)", color_space, color_space),
19263        &format!("{}(0% 0 0)", color_space),
19264      );
19265      test(
19266        &format!("{}(from {}(70% 45 30) 0% 0 0 / 0)", color_space, color_space),
19267        &format!("{}(0% 0 0 / 0)", color_space),
19268      );
19269      test(
19270        &format!("{}(from {}(70% 45 30) 0% 0 0deg / 0)", color_space, color_space),
19271        &format!("{}(0% 0 0 / 0)", color_space),
19272      );
19273      test(
19274        &format!("{}(from {}(70% 45 30) 0% c h / alpha)", color_space, color_space),
19275        &format!("{}(0% 45 30)", color_space),
19276      );
19277      test(
19278        &format!("{}(from {}(70% 45 30) l 0 h / alpha)", color_space, color_space),
19279        &format!("{}(70% 0 30)", color_space),
19280      );
19281      test(
19282        &format!("{}(from {}(70% 45 30) l c 0 / alpha)", color_space, color_space),
19283        &format!("{}(70% 45 0)", color_space),
19284      );
19285      test(
19286        &format!("{}(from {}(70% 45 30) l c 0deg / alpha)", color_space, color_space),
19287        &format!("{}(70% 45 0)", color_space),
19288      );
19289      test(
19290        &format!("{}(from {}(70% 45 30) l c h / 0)", color_space, color_space),
19291        &format!("{}(70% 45 30 / 0)", color_space),
19292      );
19293      test(
19294        &format!("{}(from {}(70% 45 30 / 40%) 0% c h / alpha)", color_space, color_space),
19295        &format!("{}(0% 45 30 / 0.4)", color_space),
19296      );
19297      test(
19298        &format!("{}(from {}(70% 45 30 / 40%) l 0 h / alpha)", color_space, color_space),
19299        &format!("{}(70% 0 30 / 0.4)", color_space),
19300      );
19301      test(
19302        &format!("{}(from {}(70% 45 30 / 40%) l c 0 / alpha)", color_space, color_space),
19303        &format!("{}(70% 45 0 / 0.4)", color_space),
19304      );
19305      test(
19306        &format!(
19307          "{}(from {}(70% 45 30 / 40%) l c 0deg / alpha)",
19308          color_space, color_space
19309        ),
19310        &format!("{}(70% 45 0 / 0.4)", color_space),
19311      );
19312      test(
19313        &format!("{}(from {}(70% 45 30 / 40%) l c h / 0)", color_space, color_space),
19314        &format!("{}(70% 45 30 / 0)", color_space),
19315      );
19316
19317      // Testing replacement with a constant.
19318      test(
19319        &format!("{}(from {}(70% 45 30) 25% c h / alpha)", color_space, color_space),
19320        &format!("{}(25% 45 30)", color_space),
19321      );
19322      test(
19323        &format!("{}(from {}(70% 45 30) l 25 h / alpha)", color_space, color_space),
19324        &format!("{}(70% 25 30)", color_space),
19325      );
19326      test(
19327        &format!("{}(from {}(70% 45 30) l c 25 / alpha)", color_space, color_space),
19328        &format!("{}(70% 45 25)", color_space),
19329      );
19330      test(
19331        &format!("{}(from {}(70% 45 30) l c 25deg / alpha)", color_space, color_space),
19332        &format!("{}(70% 45 25)", color_space),
19333      );
19334      test(
19335        &format!("{}(from {}(70% 45 30) l c h / .25)", color_space, color_space),
19336        &format!("{}(70% 45 30 / 0.25)", color_space),
19337      );
19338      test(
19339        &format!("{}(from {}(70% 45 30 / 40%) 25% c h / alpha)", color_space, color_space),
19340        &format!("{}(25% 45 30 / 0.4)", color_space),
19341      );
19342      test(
19343        &format!("{}(from {}(70% 45 30 / 40%) l 25 h / alpha)", color_space, color_space),
19344        &format!("{}(70% 25 30 / 0.4)", color_space),
19345      );
19346      test(
19347        &format!("{}(from {}(70% 45 30 / 40%) l c 25 / alpha)", color_space, color_space),
19348        &format!("{}(70% 45 25 / 0.4)", color_space),
19349      );
19350      test(
19351        &format!(
19352          "{}(from {}(70% 45 30 / 40%) l c 25deg / alpha)",
19353          color_space, color_space
19354        ),
19355        &format!("{}(70% 45 25 / 0.4)", color_space),
19356      );
19357      test(
19358        &format!("{}(from {}(70% 45 30 / 40%) l c h / .25)", color_space, color_space),
19359        &format!("{}(70% 45 30 / 0.25)", color_space),
19360      );
19361      test(
19362        &format!(
19363          "{}(from {}(70% 45 30 / 40%) 200% 300 400 / 500)",
19364          color_space, color_space
19365        ),
19366        &format!("{}(200% 300 400)", color_space),
19367      );
19368      test(
19369        &format!(
19370          "{}(from {}(70% 45 30 / 40%) -200% -300 -400 / -500)",
19371          color_space, color_space
19372        ),
19373        &format!("{}(0% 0 -400 / 0)", color_space),
19374      );
19375      test(
19376        &format!(
19377          "{}(from {}(70% 45 30 / 40%) 50% 120 400deg / 500)",
19378          color_space, color_space
19379        ),
19380        &format!("{}(50% 120 400)", color_space),
19381      );
19382      test(
19383        &format!(
19384          "{}(from {}(70% 45 30 / 40%) 50% 120 -400deg / -500)",
19385          color_space, color_space
19386        ),
19387        &format!("{}(50% 120 -400 / 0)", color_space),
19388      );
19389
19390      // Testing valid permutation (types match).
19391      // NOTE: 'c' is a valid hue, as hue is <angle>|<number>.
19392      test(
19393        &format!("{}(from {}(70% 45 30) alpha c h / l)", color_space, color_space),
19394        &format!(
19395          "{}(1 45 30 / {})",
19396          color_space,
19397          if *color_space == "lch" { "1" } else { ".7" }
19398        ),
19399      );
19400      test(
19401        &format!("{}(from {}(70% 45 30) l c c / alpha)", color_space, color_space),
19402        &format!("{}(70% 45 45)", color_space),
19403      );
19404      test(
19405        &format!("{}(from {}(70% 45 30) alpha c h / alpha)", color_space, color_space),
19406        &format!("{}(1 45 30)", color_space),
19407      );
19408      test(
19409        &format!("{}(from {}(70% 45 30) alpha c c / alpha)", color_space, color_space),
19410        &format!("{}(1 45 45)", color_space),
19411      );
19412      test(
19413        &format!("{}(from {}(70% 45 30 / 40%) alpha c h / l)", color_space, color_space),
19414        &format!(
19415          "{}(.4 45 30 / {})",
19416          color_space,
19417          if *color_space == "lch" { "1" } else { ".7" }
19418        ),
19419      );
19420      test(
19421        &format!("{}(from {}(70% 45 30 / 40%) l c c / alpha)", color_space, color_space),
19422        &format!("{}(70% 45 45 / 0.4)", color_space),
19423      );
19424      test(
19425        &format!(
19426          "{}(from {}(70% 45 30 / 40%) alpha c h / alpha)",
19427          color_space, color_space
19428        ),
19429        &format!("{}(.4 45 30 / 0.4)", color_space),
19430      );
19431      test(
19432        &format!(
19433          "{}(from {}(70% 45 30 / 40%) alpha c c / alpha)",
19434          color_space, color_space
19435        ),
19436        &format!("{}(.4 45 45 / 0.4)", color_space),
19437      );
19438
19439      // Testing with calc().
19440      test(
19441        &format!(
19442          "{}(from {}(70% 45 30) calc(l) calc(c) calc(h))",
19443          color_space, color_space
19444        ),
19445        &format!("{}(70% 45 30)", color_space),
19446      );
19447      test(
19448        &format!(
19449          "{}(from {}(70% 45 30 / 40%) calc(l) calc(c) calc(h) / calc(alpha))",
19450          color_space, color_space
19451        ),
19452        &format!("{}(70% 45 30 / 0.4)", color_space),
19453      );
19454
19455      // Testing with 'none'.
19456      test(
19457        &format!("{}(from {}(70% 45 30) none none none)", color_space, color_space),
19458        &format!("{}(none none none)", color_space),
19459      );
19460      test(
19461        &format!("{}(from {}(70% 45 30) none none none / none)", color_space, color_space),
19462        &format!("{}(none none none / none)", color_space),
19463      );
19464      test(
19465        &format!("{}(from {}(70% 45 30) l c none)", color_space, color_space),
19466        &format!("{}(70% 45 none)", color_space),
19467      );
19468      test(
19469        &format!("{}(from {}(70% 45 30) l c none / alpha)", color_space, color_space),
19470        &format!("{}(70% 45 none)", color_space),
19471      );
19472      test(
19473        &format!("{}(from {}(70% 45 30) l c h / none)", color_space, color_space),
19474        &format!("{}(70% 45 30 / none)", color_space),
19475      );
19476      test(
19477        &format!(
19478          "{}(from {}(70% 45 30 / 40%) l c none / alpha)",
19479          color_space, color_space
19480        ),
19481        &format!("{}(70% 45 none / 0.4)", color_space),
19482      );
19483      test(
19484        &format!("{}(from {}(70% 45 30 / 40%) l c h / none)", color_space, color_space),
19485        &format!("{}(70% 45 30 / none)", color_space),
19486      );
19487      // FIXME: Clarify with spec editors if 'none' should pass through to the constants.
19488      test(
19489        &format!("{}(from {}(none none none) l c h)", color_space, color_space),
19490        &format!("{}(0% 0 0)", color_space),
19491      );
19492      test(
19493        &format!(
19494          "{}(from {}(none none none / none) l c h / alpha)",
19495          color_space, color_space
19496        ),
19497        &format!("{}(0% 0 0 / 0)", color_space),
19498      );
19499      test(
19500        &format!("{}(from {}(70% none 30) l c h)", color_space, color_space),
19501        &format!("{}(70% 0 30)", color_space),
19502      );
19503      test(
19504        &format!("{}(from {}(70% 45 30 / none) l c h / alpha)", color_space, color_space),
19505        &format!("{}(70% 45 30 / 0)", color_space),
19506      );
19507    }
19508
19509    // test_valid_value\(`color`, `color\(from color\(\$\{colorSpace\}(.*?) \$\{colorSpace\}(.*?)`,\s*`color\(\$\{colorSpace\}(.*?)`\)
19510    // test(&format!("color(from color({}$1 {}$2", color_space, color_space), &format!("color({}$3", color_space))
19511
19512    for color_space in &["srgb", "srgb-linear", "a98-rgb", "rec2020", "prophoto-rgb"] {
19513      // Testing no modifications.
19514      test(
19515        &format!("color(from color({} 0.7 0.5 0.3) {} r g b)", color_space, color_space),
19516        &format!("color({} 0.7 0.5 0.3)", color_space),
19517      );
19518      test(
19519        &format!(
19520          "color(from color({} 0.7 0.5 0.3) {} r g b / alpha)",
19521          color_space, color_space
19522        ),
19523        &format!("color({} 0.7 0.5 0.3)", color_space),
19524      );
19525      test(
19526        &format!(
19527          "color(from color({} 0.7 0.5 0.3 / 40%) {} r g b)",
19528          color_space, color_space
19529        ),
19530        &format!("color({} 0.7 0.5 0.3)", color_space),
19531      );
19532      test(
19533        &format!(
19534          "color(from color({} 0.7 0.5 0.3 / 40%) {} r g b / alpha)",
19535          color_space, color_space
19536        ),
19537        &format!("color({} 0.7 0.5 0.3 / 0.4)", color_space),
19538      );
19539
19540      // Test nesting relative colors.
19541      test(
19542        &format!(
19543          "color(from color(from color({} 0.7 0.5 0.3) {} r g b) {} r g b)",
19544          color_space, color_space, color_space
19545        ),
19546        &format!("color({} 0.7 0.5 0.3)", color_space),
19547      );
19548
19549      // Testing replacement with 0.
19550      test(
19551        &format!("color(from color({} 0.7 0.5 0.3) {} 0 0 0)", color_space, color_space),
19552        &format!("color({} 0 0 0)", color_space),
19553      );
19554      test(
19555        &format!(
19556          "color(from color({} 0.7 0.5 0.3) {} 0 0 0 / 0)",
19557          color_space, color_space
19558        ),
19559        &format!("color({} 0 0 0 / 0)", color_space),
19560      );
19561      test(
19562        &format!(
19563          "color(from color({} 0.7 0.5 0.3) {} 0 g b / alpha)",
19564          color_space, color_space
19565        ),
19566        &format!("color({} 0 0.5 0.3)", color_space),
19567      );
19568      test(
19569        &format!(
19570          "color(from color({} 0.7 0.5 0.3) {} r 0 b / alpha)",
19571          color_space, color_space
19572        ),
19573        &format!("color({} 0.7 0 0.3)", color_space),
19574      );
19575      test(
19576        &format!(
19577          "color(from color({} 0.7 0.5 0.3) {} r g 0 / alpha)",
19578          color_space, color_space
19579        ),
19580        &format!("color({} 0.7 0.5 0)", color_space),
19581      );
19582      test(
19583        &format!(
19584          "color(from color({} 0.7 0.5 0.3) {} r g b / 0)",
19585          color_space, color_space
19586        ),
19587        &format!("color({} 0.7 0.5 0.3 / 0)", color_space),
19588      );
19589      test(
19590        &format!(
19591          "color(from color({} 0.7 0.5 0.3 / 40%) {} 0 g b / alpha)",
19592          color_space, color_space
19593        ),
19594        &format!("color({} 0 0.5 0.3 / 0.4)", color_space),
19595      );
19596      test(
19597        &format!(
19598          "color(from color({} 0.7 0.5 0.3 / 40%) {} r 0 b / alpha)",
19599          color_space, color_space
19600        ),
19601        &format!("color({} 0.7 0 0.3 / 0.4)", color_space),
19602      );
19603      test(
19604        &format!(
19605          "color(from color({} 0.7 0.5 0.3 / 40%) {} r g 0 / alpha)",
19606          color_space, color_space
19607        ),
19608        &format!("color({} 0.7 0.5 0 / 0.4)", color_space),
19609      );
19610      test(
19611        &format!(
19612          "color(from color({} 0.7 0.5 0.3 / 40%) {} r g b / 0)",
19613          color_space, color_space
19614        ),
19615        &format!("color({} 0.7 0.5 0.3 / 0)", color_space),
19616      );
19617
19618      // Testing replacement with a constant.
19619      test(
19620        &format!(
19621          "color(from color({} 0.7 0.5 0.3) {} 0.2 g b / alpha)",
19622          color_space, color_space
19623        ),
19624        &format!("color({} 0.2 0.5 0.3)", color_space),
19625      );
19626      test(
19627        &format!(
19628          "color(from color({} 0.7 0.5 0.3) {} 20% g b / alpha)",
19629          color_space, color_space
19630        ),
19631        &format!("color({} 0.2 0.5 0.3)", color_space),
19632      );
19633      test(
19634        &format!(
19635          "color(from color({} 0.7 0.5 0.3) {} r 0.2 b / alpha)",
19636          color_space, color_space
19637        ),
19638        &format!("color({} 0.7 0.2 0.3)", color_space),
19639      );
19640      test(
19641        &format!(
19642          "color(from color({} 0.7 0.5 0.3) {} r 20% b / alpha)",
19643          color_space, color_space
19644        ),
19645        &format!("color({} 0.7 0.2 0.3)", color_space),
19646      );
19647      test(
19648        &format!(
19649          "color(from color({} 0.7 0.5 0.3) {} r g 0.2 / alpha)",
19650          color_space, color_space
19651        ),
19652        &format!("color({} 0.7 0.5 0.2)", color_space),
19653      );
19654      test(
19655        &format!(
19656          "color(from color({} 0.7 0.5 0.3) {} r g 20% / alpha)",
19657          color_space, color_space
19658        ),
19659        &format!("color({} 0.7 0.5 0.2)", color_space),
19660      );
19661      test(
19662        &format!(
19663          "color(from color({} 0.7 0.5 0.3) {} r g b / 0.2)",
19664          color_space, color_space
19665        ),
19666        &format!("color({} 0.7 0.5 0.3 / 0.2)", color_space),
19667      );
19668      test(
19669        &format!(
19670          "color(from color({} 0.7 0.5 0.3) {} r g b / 20%)",
19671          color_space, color_space
19672        ),
19673        &format!("color({} 0.7 0.5 0.3 / 0.2)", color_space),
19674      );
19675      test(
19676        &format!(
19677          "color(from color({} 0.7 0.5 0.3 / 40%) {} 0.2 g b / alpha)",
19678          color_space, color_space
19679        ),
19680        &format!("color({} 0.2 0.5 0.3 / 0.4)", color_space),
19681      );
19682      test(
19683        &format!(
19684          "color(from color({} 0.7 0.5 0.3 / 40%) {} 20% g b / alpha)",
19685          color_space, color_space
19686        ),
19687        &format!("color({} 0.2 0.5 0.3 / 0.4)", color_space),
19688      );
19689      test(
19690        &format!(
19691          "color(from color({} 0.7 0.5 0.3 / 40%) {} r 0.2 b / alpha)",
19692          color_space, color_space
19693        ),
19694        &format!("color({} 0.7 0.2 0.3 / 0.4)", color_space),
19695      );
19696      test(
19697        &format!(
19698          "color(from color({} 0.7 0.5 0.3 / 40%) {} r 20% b / alpha)",
19699          color_space, color_space
19700        ),
19701        &format!("color({} 0.7 0.2 0.3 / 0.4)", color_space),
19702      );
19703      test(
19704        &format!(
19705          "color(from color({} 0.7 0.5 0.3 / 40%) {} r g 0.2 / alpha)",
19706          color_space, color_space
19707        ),
19708        &format!("color({} 0.7 0.5 0.2 / 0.4)", color_space),
19709      );
19710      test(
19711        &format!(
19712          "color(from color({} 0.7 0.5 0.3 / 40%) {} r g 20% / alpha)",
19713          color_space, color_space
19714        ),
19715        &format!("color({} 0.7 0.5 0.2 / 0.4)", color_space),
19716      );
19717      test(
19718        &format!(
19719          "color(from color({} 0.7 0.5 0.3 / 40%) {} r g b / 0.2)",
19720          color_space, color_space
19721        ),
19722        &format!("color({} 0.7 0.5 0.3 / 0.2)", color_space),
19723      );
19724      test(
19725        &format!(
19726          "color(from color({} 0.7 0.5 0.3 / 40%) {} r g b / 20%)",
19727          color_space, color_space
19728        ),
19729        &format!("color({} 0.7 0.5 0.3 / 0.2)", color_space),
19730      );
19731      test(
19732        &format!("color(from color({} 0.7 0.5 0.3) {} 2 3 4)", color_space, color_space),
19733        &format!("color({} 2 3 4)", color_space),
19734      );
19735      test(
19736        &format!(
19737          "color(from color({} 0.7 0.5 0.3) {} 2 3 4 / 5)",
19738          color_space, color_space
19739        ),
19740        &format!("color({} 2 3 4)", color_space),
19741      );
19742      test(
19743        &format!(
19744          "color(from color({} 0.7 0.5 0.3) {} -2 -3 -4)",
19745          color_space, color_space
19746        ),
19747        &format!("color({} -2 -3 -4)", color_space),
19748      );
19749      test(
19750        &format!(
19751          "color(from color({} 0.7 0.5 0.3) {} -2 -3 -4 / -5)",
19752          color_space, color_space
19753        ),
19754        &format!("color({} -2 -3 -4 / 0)", color_space),
19755      );
19756      test(
19757        &format!(
19758          "color(from color({} 0.7 0.5 0.3) {} 200% 300% 400%)",
19759          color_space, color_space
19760        ),
19761        &format!("color({} 2 3 4)", color_space),
19762      );
19763      test(
19764        &format!(
19765          "color(from color({} 0.7 0.5 0.3) {} 200% 300% 400% / 500%)",
19766          color_space, color_space
19767        ),
19768        &format!("color({} 2 3 4)", color_space),
19769      );
19770      test(
19771        &format!(
19772          "color(from color({} 0.7 0.5 0.3) {} -200% -300% -400%)",
19773          color_space, color_space
19774        ),
19775        &format!("color({} -2 -3 -4)", color_space),
19776      );
19777      test(
19778        &format!(
19779          "color(from color({} 0.7 0.5 0.3) {} -200% -300% -400% / -500%)",
19780          color_space, color_space
19781        ),
19782        &format!("color({} -2 -3 -4 / 0)", color_space),
19783      );
19784
19785      // Testing valid permutation (types match).
19786      test(
19787        &format!("color(from color({} 0.7 0.5 0.3) {} g b r)", color_space, color_space),
19788        &format!("color({} 0.5 0.3 0.7)", color_space),
19789      );
19790      test(
19791        &format!(
19792          "color(from color({} 0.7 0.5 0.3) {} b alpha r / g)",
19793          color_space, color_space
19794        ),
19795        &format!("color({} 0.3 1 0.7 / 0.5)", color_space),
19796      );
19797      test(
19798        &format!(
19799          "color(from color({} 0.7 0.5 0.3) {} r r r / r)",
19800          color_space, color_space
19801        ),
19802        &format!("color({} 0.7 0.7 0.7 / 0.7)", color_space),
19803      );
19804      test(
19805        &format!(
19806          "color(from color({} 0.7 0.5 0.3) {} alpha alpha alpha / alpha)",
19807          color_space, color_space
19808        ),
19809        &format!("color({} 1 1 1)", color_space),
19810      );
19811      test(
19812        &format!(
19813          "color(from color({} 0.7 0.5 0.3 / 40%) {} g b r)",
19814          color_space, color_space
19815        ),
19816        &format!("color({} 0.5 0.3 0.7)", color_space),
19817      );
19818      test(
19819        &format!(
19820          "color(from color({} 0.7 0.5 0.3 / 40%) {} b alpha r / g)",
19821          color_space, color_space
19822        ),
19823        &format!("color({} 0.3 0.4 0.7 / 0.5)", color_space),
19824      );
19825      test(
19826        &format!(
19827          "color(from color({} 0.7 0.5 0.3 / 40%) {} r r r / r)",
19828          color_space, color_space
19829        ),
19830        &format!("color({} 0.7 0.7 0.7 / 0.7)", color_space),
19831      );
19832      test(
19833        &format!(
19834          "color(from color({} 0.7 0.5 0.3 / 40%) {} alpha alpha alpha / alpha)",
19835          color_space, color_space
19836        ),
19837        &format!("color({} 0.4 0.4 0.4 / 0.4)", color_space),
19838      );
19839
19840      // Testing out of gamut components.
19841      test(
19842        &format!("color(from color({} 1.7 1.5 1.3) {} r g b)", color_space, color_space),
19843        &format!("color({} 1.7 1.5 1.3)", color_space),
19844      );
19845      test(
19846        &format!(
19847          "color(from color({} 1.7 1.5 1.3) {} r g b / alpha)",
19848          color_space, color_space
19849        ),
19850        &format!("color({} 1.7 1.5 1.3)", color_space),
19851      );
19852      test(
19853        &format!(
19854          "color(from color({} 1.7 1.5 1.3 / 140%) {} r g b)",
19855          color_space, color_space
19856        ),
19857        &format!("color({} 1.7 1.5 1.3)", color_space),
19858      );
19859      test(
19860        &format!(
19861          "color(from color({} 1.7 1.5 1.3 / 140%) {} r g b / alpha)",
19862          color_space, color_space
19863        ),
19864        &format!("color({} 1.7 1.5 1.3)", color_space),
19865      );
19866      test(
19867        &format!(
19868          "color(from color({} -0.7 -0.5 -0.3) {} r g b)",
19869          color_space, color_space
19870        ),
19871        &format!("color({} -0.7 -0.5 -0.3)", color_space),
19872      );
19873      test(
19874        &format!(
19875          "color(from color({} -0.7 -0.5 -0.3) {} r g b / alpha)",
19876          color_space, color_space
19877        ),
19878        &format!("color({} -0.7 -0.5 -0.3)", color_space),
19879      );
19880      test(
19881        &format!(
19882          "color(from color({} -0.7 -0.5 -0.3 / -40%) {} r g b)",
19883          color_space, color_space
19884        ),
19885        &format!("color({} -0.7 -0.5 -0.3)", color_space),
19886      );
19887      test(
19888        &format!(
19889          "color(from color({} -0.7 -0.5 -0.3 / -40%) {} r g b / alpha)",
19890          color_space, color_space
19891        ),
19892        &format!("color({} -0.7 -0.5 -0.3 / 0)", color_space),
19893      );
19894
19895      // Testing with calc().
19896      test(
19897        &format!(
19898          "color(from color({} 0.7 0.5 0.3) {} calc(r) calc(g) calc(b))",
19899          color_space, color_space
19900        ),
19901        &format!("color({} 0.7 0.5 0.3)", color_space),
19902      );
19903      test(
19904        &format!(
19905          "color(from color({} 0.7 0.5 0.3 / 40%) {} calc(r) calc(g) calc(b) / calc(alpha))",
19906          color_space, color_space
19907        ),
19908        &format!("color({} 0.7 0.5 0.3 / 0.4)", color_space),
19909      );
19910
19911      // Testing with 'none'.
19912      test(
19913        &format!(
19914          "color(from color({} 0.7 0.5 0.3) {} none none none)",
19915          color_space, color_space
19916        ),
19917        &format!("color({} none none none)", color_space),
19918      );
19919      test(
19920        &format!(
19921          "color(from color({} 0.7 0.5 0.3) {} none none none / none)",
19922          color_space, color_space
19923        ),
19924        &format!("color({} none none none / none)", color_space),
19925      );
19926      test(
19927        &format!(
19928          "color(from color({} 0.7 0.5 0.3) {} r g none)",
19929          color_space, color_space
19930        ),
19931        &format!("color({} 0.7 0.5 none)", color_space),
19932      );
19933      test(
19934        &format!(
19935          "color(from color({} 0.7 0.5 0.3) {} r g none / alpha)",
19936          color_space, color_space
19937        ),
19938        &format!("color({} 0.7 0.5 none)", color_space),
19939      );
19940      test(
19941        &format!(
19942          "color(from color({} 0.7 0.5 0.3) {} r g b / none)",
19943          color_space, color_space
19944        ),
19945        &format!("color({} 0.7 0.5 0.3 / none)", color_space),
19946      );
19947      test(
19948        &format!(
19949          "color(from color({} 0.7 0.5 0.3 / 40%) {} r g none / alpha)",
19950          color_space, color_space
19951        ),
19952        &format!("color({} 0.7 0.5 none / 0.4)", color_space),
19953      );
19954      test(
19955        &format!(
19956          "color(from color({} 0.7 0.5 0.3 / 40%) {} r g b / none)",
19957          color_space, color_space
19958        ),
19959        &format!("color({} 0.7 0.5 0.3 / none)", color_space),
19960      );
19961      // FIXME: Clarify with spec editors if 'none' should pass through to the constants.
19962      test(
19963        &format!(
19964          "color(from color({} none none none) {} r g b)",
19965          color_space, color_space
19966        ),
19967        &format!("color({} 0 0 0)", color_space),
19968      );
19969      test(
19970        &format!(
19971          "color(from color({} none none none / none) {} r g b / alpha)",
19972          color_space, color_space
19973        ),
19974        &format!("color({} 0 0 0 / 0)", color_space),
19975      );
19976      test(
19977        &format!("color(from color({} 0.7 none 0.3) {} r g b)", color_space, color_space),
19978        &format!("color({} 0.7 0 0.3)", color_space),
19979      );
19980      test(
19981        &format!(
19982          "color(from color({} 0.7 0.5 0.3 / none) {} r g b / alpha)",
19983          color_space, color_space
19984        ),
19985        &format!("color({} 0.7 0.5 0.3 / 0)", color_space),
19986      );
19987    }
19988
19989    // test_valid_value\(`color`, `color\(from color\(\$\{colorSpace\}(.*?) \$\{colorSpace\}(.*?)`,\s*`color\(\$\{resultColorSpace\}(.*?)`\)
19990    // test(&format!("color(from color({}$1 {}$2", color_space, color_space), &format!("color({}$3", result_color_space))
19991
19992    for color_space in &["xyz", "xyz-d50", "xyz-d65"] {
19993      let result_color_space = if *color_space == "xyz" { "xyz-d65" } else { color_space };
19994
19995      // Testing no modifications.
19996      test(
19997        &format!("color(from color({} 7 -20.5 100) {} x y z)", color_space, color_space),
19998        &format!("color({} 7 -20.5 100)", result_color_space),
19999      );
20000      test(
20001        &format!(
20002          "color(from color({} 7 -20.5 100) {} x y z / alpha)",
20003          color_space, color_space
20004        ),
20005        &format!("color({} 7 -20.5 100)", result_color_space),
20006      );
20007      test(
20008        &format!(
20009          "color(from color({} 7 -20.5 100 / 40%) {} x y z)",
20010          color_space, color_space
20011        ),
20012        &format!("color({} 7 -20.5 100)", result_color_space),
20013      );
20014      test(
20015        &format!(
20016          "color(from color({} 7 -20.5 100 / 40%) {} x y z / alpha)",
20017          color_space, color_space
20018        ),
20019        &format!("color({} 7 -20.5 100 / 0.4)", result_color_space),
20020      );
20021
20022      // Test nesting relative colors.
20023      test(
20024        &format!(
20025          "color(from color(from color({} 7 -20.5 100) {} x y z) {} x y z)",
20026          color_space, color_space, color_space
20027        ),
20028        &format!("color({} 7 -20.5 100)", result_color_space),
20029      );
20030
20031      // Testing replacement with 0.
20032      test(
20033        &format!("color(from color({} 7 -20.5 100) {} 0 0 0)", color_space, color_space),
20034        &format!("color({} 0 0 0)", result_color_space),
20035      );
20036      test(
20037        &format!(
20038          "color(from color({} 7 -20.5 100) {} 0 0 0 / 0)",
20039          color_space, color_space
20040        ),
20041        &format!("color({} 0 0 0 / 0)", result_color_space),
20042      );
20043      test(
20044        &format!(
20045          "color(from color({} 7 -20.5 100) {} 0 y z / alpha)",
20046          color_space, color_space
20047        ),
20048        &format!("color({} 0 -20.5 100)", result_color_space),
20049      );
20050      test(
20051        &format!(
20052          "color(from color({} 7 -20.5 100) {} x 0 z / alpha)",
20053          color_space, color_space
20054        ),
20055        &format!("color({} 7 0 100)", result_color_space),
20056      );
20057      test(
20058        &format!(
20059          "color(from color({} 7 -20.5 100) {} x y 0 / alpha)",
20060          color_space, color_space
20061        ),
20062        &format!("color({} 7 -20.5 0)", result_color_space),
20063      );
20064      test(
20065        &format!(
20066          "color(from color({} 7 -20.5 100) {} x y z / 0)",
20067          color_space, color_space
20068        ),
20069        &format!("color({} 7 -20.5 100 / 0)", result_color_space),
20070      );
20071      test(
20072        &format!(
20073          "color(from color({} 7 -20.5 100 / 40%) {} 0 y z / alpha)",
20074          color_space, color_space
20075        ),
20076        &format!("color({} 0 -20.5 100 / 0.4)", result_color_space),
20077      );
20078      test(
20079        &format!(
20080          "color(from color({} 7 -20.5 100 / 40%) {} x 0 z / alpha)",
20081          color_space, color_space
20082        ),
20083        &format!("color({} 7 0 100 / 0.4)", result_color_space),
20084      );
20085      test(
20086        &format!(
20087          "color(from color({} 7 -20.5 100 / 40%) {} x y 0 / alpha)",
20088          color_space, color_space
20089        ),
20090        &format!("color({} 7 -20.5 0 / 0.4)", result_color_space),
20091      );
20092      test(
20093        &format!(
20094          "color(from color({} 7 -20.5 100 / 40%) {} x y z / 0)",
20095          color_space, color_space
20096        ),
20097        &format!("color({} 7 -20.5 100 / 0)", result_color_space),
20098      );
20099
20100      // Testing replacement with a constant.
20101      test(
20102        &format!(
20103          "color(from color({} 7 -20.5 100) {} 0.2 y z / alpha)",
20104          color_space, color_space
20105        ),
20106        &format!("color({} 0.2 -20.5 100)", result_color_space),
20107      );
20108      test(
20109        &format!(
20110          "color(from color({} 7 -20.5 100) {} x 0.2 z / alpha)",
20111          color_space, color_space
20112        ),
20113        &format!("color({} 7 0.2 100)", result_color_space),
20114      );
20115      test(
20116        &format!(
20117          "color(from color({} 7 -20.5 100) {} x y 0.2 / alpha)",
20118          color_space, color_space
20119        ),
20120        &format!("color({} 7 -20.5 0.2)", result_color_space),
20121      );
20122      test(
20123        &format!(
20124          "color(from color({} 7 -20.5 100) {} x y z / 0.2)",
20125          color_space, color_space
20126        ),
20127        &format!("color({} 7 -20.5 100 / 0.2)", result_color_space),
20128      );
20129      test(
20130        &format!(
20131          "color(from color({} 7 -20.5 100) {} x y z / 20%)",
20132          color_space, color_space
20133        ),
20134        &format!("color({} 7 -20.5 100 / 0.2)", result_color_space),
20135      );
20136      test(
20137        &format!(
20138          "color(from color({} 7 -20.5 100 / 40%) {} 0.2 y z / alpha)",
20139          color_space, color_space
20140        ),
20141        &format!("color({} 0.2 -20.5 100 / 0.4)", result_color_space),
20142      );
20143      test(
20144        &format!(
20145          "color(from color({} 7 -20.5 100 / 40%) {} x 0.2 z / alpha)",
20146          color_space, color_space
20147        ),
20148        &format!("color({} 7 0.2 100 / 0.4)", result_color_space),
20149      );
20150      test(
20151        &format!(
20152          "color(from color({} 7 -20.5 100 / 40%) {} x y 0.2 / alpha)",
20153          color_space, color_space
20154        ),
20155        &format!("color({} 7 -20.5 0.2 / 0.4)", result_color_space),
20156      );
20157      test(
20158        &format!(
20159          "color(from color({} 7 -20.5 100 / 40%) {} x y z / 0.2)",
20160          color_space, color_space
20161        ),
20162        &format!("color({} 7 -20.5 100 / 0.2)", result_color_space),
20163      );
20164
20165      // Testing valid permutation (types match).
20166      test(
20167        &format!("color(from color({} 7 -20.5 100) {} y z x)", color_space, color_space),
20168        &format!("color({} -20.5 100 7)", result_color_space),
20169      );
20170      test(
20171        &format!(
20172          "color(from color({} 7 -20.5 100) {} x x x / x)",
20173          color_space, color_space
20174        ),
20175        &format!("color({} 7 7 7)", result_color_space),
20176      );
20177      test(
20178        &format!(
20179          "color(from color({} 7 -20.5 100 / 40%) {} y z x)",
20180          color_space, color_space
20181        ),
20182        &format!("color({} -20.5 100 7)", result_color_space),
20183      );
20184      test(
20185        &format!(
20186          "color(from color({} 7 -20.5 100 / 40%) {} x x x / x)",
20187          color_space, color_space
20188        ),
20189        &format!("color({} 7 7 7)", result_color_space),
20190      );
20191
20192      // Testing with calc().
20193      test(
20194        &format!(
20195          "color(from color({} 7 -20.5 100) {} calc(x) calc(y) calc(z))",
20196          color_space, color_space
20197        ),
20198        &format!("color({} 7 -20.5 100)", result_color_space),
20199      );
20200      test(
20201        &format!(
20202          "color(from color({} 7 -20.5 100 / 40%) {} calc(x) calc(y) calc(z) / calc(alpha))",
20203          color_space, color_space
20204        ),
20205        &format!("color({} 7 -20.5 100 / 0.4)", result_color_space),
20206      );
20207
20208      // Testing with 'none'.
20209      test(
20210        &format!(
20211          "color(from color({} 7 -20.5 100) {} none none none)",
20212          color_space, color_space
20213        ),
20214        &format!("color({} none none none)", result_color_space),
20215      );
20216      test(
20217        &format!(
20218          "color(from color({} 7 -20.5 100) {} none none none / none)",
20219          color_space, color_space
20220        ),
20221        &format!("color({} none none none / none)", result_color_space),
20222      );
20223      test(
20224        &format!(
20225          "color(from color({} 7 -20.5 100) {} x y none)",
20226          color_space, color_space
20227        ),
20228        &format!("color({} 7 -20.5 none)", result_color_space),
20229      );
20230      test(
20231        &format!(
20232          "color(from color({} 7 -20.5 100) {} x y none / alpha)",
20233          color_space, color_space
20234        ),
20235        &format!("color({} 7 -20.5 none)", result_color_space),
20236      );
20237      test(
20238        &format!(
20239          "color(from color({} 7 -20.5 100) {} x y z / none)",
20240          color_space, color_space
20241        ),
20242        &format!("color({} 7 -20.5 100 / none)", result_color_space),
20243      );
20244      test(
20245        &format!(
20246          "color(from color({} 7 -20.5 100 / 40%) {} x y none / alpha)",
20247          color_space, color_space
20248        ),
20249        &format!("color({} 7 -20.5 none / 0.4)", result_color_space),
20250      );
20251      test(
20252        &format!(
20253          "color(from color({} 7 -20.5 100 / 40%) {} x y z / none)",
20254          color_space, color_space
20255        ),
20256        &format!("color({} 7 -20.5 100 / none)", result_color_space),
20257      );
20258      // FIXME: Clarify with spec editors if 'none' should pass through to the constants.
20259      test(
20260        &format!(
20261          "color(from color({} none none none) {} x y z)",
20262          color_space, color_space
20263        ),
20264        &format!("color({} 0 0 0)", result_color_space),
20265      );
20266      test(
20267        &format!(
20268          "color(from color({} none none none / none) {} x y z / alpha)",
20269          color_space, color_space
20270        ),
20271        &format!("color({} 0 0 0 / 0)", result_color_space),
20272      );
20273      test(
20274        &format!("color(from color({} 7 none 100) {} x y z)", color_space, color_space),
20275        &format!("color({} 7 0 100)", result_color_space),
20276      );
20277      test(
20278        &format!(
20279          "color(from color({} 7 -20.5 100 / none) {} x y z / alpha)",
20280          color_space, color_space
20281        ),
20282        &format!("color({} 7 -20.5 100 / 0)", result_color_space),
20283      );
20284
20285      // https://github.com/web-platform-tests/wpt/blob/master/css/css-color/parsing/relative-color-invalid.html
20286      minify_test(
20287        ".foo{color:rgb(from rebeccapurple r 10deg 10)}",
20288        ".foo{color:rgb(from rebeccapurple r 10deg 10)}",
20289      );
20290      minify_test(
20291        ".foo{color:rgb(from rebeccapurple l g b)}",
20292        ".foo{color:rgb(from rebeccapurple l g b)}",
20293      );
20294      minify_test(
20295        ".foo{color:hsl(from rebeccapurple s h l)}",
20296        ".foo{color:hsl(from rebeccapurple s h l)}",
20297      );
20298      minify_test(".foo{color:hsl(from rebeccapurple s s s / s)}", ".foo{color:#bfaa40}");
20299      minify_test(
20300        ".foo{color:hsl(from rebeccapurple calc(alpha * 100) calc(alpha * 100) calc(alpha * 100) / alpha)}",
20301        ".foo{color:#fff}",
20302      );
20303    }
20304  }
20305
20306  #[test]
20307  fn test_color_mix() {
20308    minify_test(
20309      ".foo { color: color-mix(in lab, purple 50%, plum 50%); }",
20310      ".foo{color:lab(51.5117% 43.3777 -29.0443)}",
20311    );
20312    minify_test(
20313      ".foo { color: color-mix(in lch, peru 40%, palegoldenrod); }",
20314      ".foo{color:lch(79.7255% 40.4542 84.7634)}",
20315    );
20316    minify_test(
20317      ".foo { color: color-mix(in lch, teal 65%, olive); }",
20318      ".foo{color:lch(49.4431% 40.4806 162.546)}",
20319    );
20320    minify_test(
20321      ".foo { color: color-mix(in lch, white, black); }",
20322      ".foo{color:lch(50% 0 none)}",
20323    );
20324    minify_test(
20325      ".foo { color: color-mix(in xyz, rgb(82.02% 30.21% 35.02%) 75.23%, rgb(5.64% 55.94% 85.31%)); }",
20326      ".foo{color:color(xyz .287458 .208776 .260566)}",
20327    );
20328    minify_test(
20329      ".foo { color: color-mix(in lch, white, blue); }",
20330      ".foo{color:lch(64.7842% 65.6007 301.364)}",
20331    );
20332    minify_test(
20333      ".foo { color: color-mix(in oklch, white, blue); }",
20334      ".foo{color:oklch(72.6007% .156607 264.052)}",
20335    );
20336    minify_test(
20337      ".foo { color: color-mix(in srgb, white, blue); }",
20338      ".foo{color:#8080ff}",
20339    );
20340    minify_test(
20341      ".foo { color: color-mix(in lch, blue, white); }",
20342      ".foo{color:lch(64.7842% 65.6007 301.364)}",
20343    );
20344    minify_test(
20345      ".foo { color: color-mix(in oklch, blue, white); }",
20346      ".foo{color:oklch(72.6007% .156607 264.052)}",
20347    );
20348    minify_test(
20349      ".foo { color: color-mix(in srgb, blue, white); }",
20350      ".foo{color:#8080ff}",
20351    );
20352    // minify_test(".foo { color: color-mix(in hsl, color(display-p3 0 1 0) 80%, yellow); }", ".foo{color:hsl(108 100% 49.9184%) }");
20353    minify_test(
20354      ".foo { color: color-mix(in hsl, hsl(120 100% 49.898%) 80%, yellow); }",
20355      ".foo{color:#33fe00}",
20356    );
20357    minify_test(
20358      ".foo { color: color-mix(in srgb, rgb(100% 0% 0% / 0.7) 25%, rgb(0% 100% 0% / 0.2)); }",
20359      ".foo{color:#89760053}",
20360    );
20361    minify_test(
20362      ".foo { color: color-mix(in srgb, rgb(100% 0% 0% / 0.7) 20%, rgb(0% 100% 0% / 0.2) 60%); }",
20363      ".foo{color:#89760042}",
20364    );
20365    minify_test(
20366      ".foo { color: color-mix(in lch, color(display-p3 0 1 none), color(display-p3 0 0 1)); }",
20367      ".foo{color:lch(58.8143% 141.732 218.684)}",
20368    );
20369    minify_test(
20370      ".foo { color: color-mix(in srgb, rgb(128 128 none), rgb(none none 128)); }",
20371      ".foo{color:gray}",
20372    );
20373    minify_test(
20374      ".foo { color: color-mix(in srgb, rgb(50% 50% none), rgb(none none 50%)); }",
20375      ".foo{color:gray}",
20376    );
20377    minify_test(
20378      ".foo { color: color-mix(in srgb, rgb(none 50% none), rgb(50% none 50%)); }",
20379      ".foo{color:gray}",
20380    );
20381    minify_test(
20382      ".foo { --color: color-mix(in lch, teal 65%, olive); }",
20383      ".foo{--color:lch(49.4431% 40.4806 162.546)}",
20384    );
20385    minify_test(
20386      ".foo { color: color-mix(in xyz, transparent, green 65%); }",
20387      ".foo{color:color(xyz .0771883 .154377 .0257295/.65)}",
20388    );
20389    prefix_test(
20390      ".foo { color: color-mix(in xyz, transparent, green 65%); }",
20391      indoc! { r#"
20392      .foo {
20393        color: #008000a6;
20394        color: color(xyz .0771883 .154377 .0257295 / .65);
20395      }
20396      "# },
20397      Browsers {
20398        chrome: Some(95 << 16),
20399        ..Default::default()
20400      },
20401    );
20402    minify_test(
20403      ".foo { color: color-mix(in srgb, currentColor, blue); }",
20404      ".foo{color:color-mix(in srgb,currentColor,blue)}",
20405    );
20406    minify_test(
20407      ".foo { color: color-mix(in srgb, blue, currentColor); }",
20408      ".foo{color:color-mix(in srgb,blue,currentColor)}",
20409    );
20410    minify_test(
20411      ".foo { color: color-mix(in srgb, accentcolor, blue); }",
20412      ".foo{color:color-mix(in srgb,accentcolor,blue)}",
20413    );
20414    minify_test(
20415      ".foo { color: color-mix(in srgb, blue, accentcolor); }",
20416      ".foo{color:color-mix(in srgb,blue,accentcolor)}",
20417    );
20418
20419    // regex for converting web platform tests:
20420    // test_computed_value\(.*?, `(.*?)`, `(.*?)`\);
20421    // minify_test(".foo { color: $1 }", ".foo{color:$2}");
20422
20423    // https://github.com/web-platform-tests/wpt/blob/f8c76b11cff66a7adc87264a18e39353cb5a60c9/css/css-color/parsing/color-mix-computed.html
20424    minify_test(
20425      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%)) }",
20426      ".foo{color:#545c3d}",
20427    );
20428    minify_test(
20429      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40%)) }",
20430      ".foo{color:#706a43}",
20431    );
20432    minify_test(
20433      ".foo { color: color-mix(in hsl, 25% hsl(120deg 10% 20%), hsl(30deg 30% 40%)) }",
20434      ".foo{color:#706a43}",
20435    );
20436    minify_test(
20437      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20%), 25% hsl(30deg 30% 40%)) }",
20438      ".foo{color:#3d4936}",
20439    );
20440    minify_test(
20441      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%) 25%) }",
20442      ".foo{color:#3d4936}",
20443    );
20444    minify_test(
20445      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40%) 75%) }",
20446      ".foo{color:#706a43}",
20447    );
20448    minify_test(
20449      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20%) 30%, hsl(30deg 30% 40%) 90%) }",
20450      ".foo{color:#706a43}",
20451    ); // Scale down > 100% sum.
20452    minify_test(
20453      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20%) 12.5%, hsl(30deg 30% 40%) 37.5%) }",
20454      ".foo{color:#706a4380}",
20455    ); // Scale up < 100% sum, causes alpha multiplication.
20456    minify_test(
20457      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20%) 0%, hsl(30deg 30% 40%)) }",
20458      ".foo{color:#856647}",
20459    );
20460
20461    minify_test(
20462      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20% / .4), hsl(30deg 30% 40% / .8)) }",
20463      ".foo{color:#5f694199}",
20464    );
20465    minify_test(
20466      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40% / .8)) }",
20467      ".foo{color:#6c6742d9}",
20468    );
20469    minify_test(
20470      ".foo { color: color-mix(in hsl, 25% hsl(120deg 10% 20% / .4), hsl(30deg 30% 40% / .8)) }",
20471      ".foo{color:#797245b3}",
20472    );
20473    minify_test(
20474      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20% / .4), 25% hsl(30deg 30% 40% / .8)) }",
20475      ".foo{color:#44543b80}",
20476    );
20477    minify_test(
20478      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20% / .4), hsl(30deg 30% 40% / .8) 25%) }",
20479      ".foo{color:#44543b80}",
20480    );
20481    minify_test(
20482      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20% / .4) 25%, hsl(30deg 30% 40% / .8) 75%) }",
20483      ".foo{color:#797245b3}",
20484    );
20485    minify_test(
20486      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20% / .4) 30%, hsl(30deg 30% 40% / .8) 90%) }",
20487      ".foo{color:#797245b3}",
20488    ); // Scale down > 100% sum.
20489    minify_test(
20490      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20% / .4) 12.5%, hsl(30deg 30% 40% / .8) 37.5%) }",
20491      ".foo{color:#79724559}",
20492    ); // Scale up < 100% sum, causes alpha multiplication.
20493    minify_test(
20494      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20% / .4) 0%, hsl(30deg 30% 40% / .8)) }",
20495      ".foo{color:#856647cc}",
20496    );
20497
20498    fn canonicalize(s: &str) -> String {
20499      use crate::traits::{Parse, ToCss};
20500      use crate::values::color::CssColor;
20501      use cssparser::{Parser, ParserInput};
20502
20503      let mut input = ParserInput::new(s);
20504      let mut parser = Parser::new(&mut input);
20505      let v = CssColor::parse(&mut parser).unwrap().to_rgb().unwrap();
20506      format!(".foo{{color:{}}}", v.to_css_string(PrinterOptions::default()).unwrap())
20507    }
20508
20509    // regex for converting web platform tests:
20510    // test_computed_value\(.*?, `(.*?)`, canonicalize\(`(.*?)`\)\);
20511    // minify_test(".foo { color: $1 }", &canonicalize("$2"));
20512
20513    minify_test(
20514      ".foo { color: color-mix(in hsl, hsl(40deg 50% 50%), hsl(60deg 50% 50%)) }",
20515      &canonicalize("hsl(50deg 50% 50%)"),
20516    );
20517    minify_test(
20518      ".foo { color: color-mix(in hsl, hsl(60deg 50% 50%), hsl(40deg 50% 50%)) }",
20519      &canonicalize("hsl(50deg 50% 50%)"),
20520    );
20521    minify_test(
20522      ".foo { color: color-mix(in hsl, hsl(50deg 50% 50%), hsl(330deg 50% 50%)) }",
20523      &canonicalize("hsl(10deg 50% 50%)"),
20524    );
20525    minify_test(
20526      ".foo { color: color-mix(in hsl, hsl(330deg 50% 50%), hsl(50deg 50% 50%)) }",
20527      &canonicalize("hsl(10deg 50% 50%)"),
20528    );
20529    minify_test(
20530      ".foo { color: color-mix(in hsl, hsl(20deg 50% 50%), hsl(320deg 50% 50%)) }",
20531      &canonicalize("hsl(350deg 50% 50%)"),
20532    );
20533    minify_test(
20534      ".foo { color: color-mix(in hsl, hsl(320deg 50% 50%), hsl(20deg 50% 50%)) }",
20535      &canonicalize("hsl(350deg 50% 50%)"),
20536    );
20537
20538    minify_test(
20539      ".foo { color: color-mix(in hsl shorter hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%)) }",
20540      &canonicalize("hsl(50deg 50% 50%)"),
20541    );
20542    minify_test(
20543      ".foo { color: color-mix(in hsl shorter hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%)) }",
20544      &canonicalize("hsl(50deg 50% 50%)"),
20545    );
20546    minify_test(
20547      ".foo { color: color-mix(in hsl shorter hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%)) }",
20548      &canonicalize("hsl(10deg 50% 50%)"),
20549    );
20550    minify_test(
20551      ".foo { color: color-mix(in hsl shorter hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%)) }",
20552      &canonicalize("hsl(10deg 50% 50%)"),
20553    );
20554    minify_test(
20555      ".foo { color: color-mix(in hsl shorter hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%)) }",
20556      &canonicalize("hsl(350deg 50% 50%)"),
20557    );
20558    minify_test(
20559      ".foo { color: color-mix(in hsl shorter hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%)) }",
20560      &canonicalize("hsl(350deg 50% 50%)"),
20561    );
20562
20563    minify_test(
20564      ".foo { color: color-mix(in hsl longer hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%)) }",
20565      &canonicalize("hsl(230deg 50% 50%)"),
20566    );
20567    minify_test(
20568      ".foo { color: color-mix(in hsl longer hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%)) }",
20569      &canonicalize("hsl(230deg 50% 50%)"),
20570    );
20571    minify_test(
20572      ".foo { color: color-mix(in hsl longer hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%)) }",
20573      &canonicalize("hsl(190deg 50% 50%)"),
20574    );
20575    minify_test(
20576      ".foo { color: color-mix(in hsl longer hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%)) }",
20577      &canonicalize("hsl(190deg 50% 50%)"),
20578    );
20579    // minify_test(".foo { color: color-mix(in hsl longer hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%)) }", &canonicalize("hsl(170deg 50% 50%)"));
20580    // minify_test(".foo { color: color-mix(in hsl longer hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%)) }", &canonicalize("hsl(170deg 50% 50%)"));
20581
20582    minify_test(
20583      ".foo { color: color-mix(in hsl increasing hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%)) }",
20584      &canonicalize("hsl(50deg 50% 50%)"),
20585    );
20586    minify_test(
20587      ".foo { color: color-mix(in hsl increasing hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%)) }",
20588      &canonicalize("hsl(230deg 50% 50%)"),
20589    );
20590    minify_test(
20591      ".foo { color: color-mix(in hsl increasing hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%)) }",
20592      &canonicalize("hsl(190deg 50% 50%)"),
20593    );
20594    minify_test(
20595      ".foo { color: color-mix(in hsl increasing hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%)) }",
20596      &canonicalize("hsl(10deg 50% 50%)"),
20597    );
20598    // minify_test(".foo { color: color-mix(in hsl increasing hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%)) }", &canonicalize("hsl(170deg 50% 50%)"));
20599    // minify_test(".foo { color: color-mix(in hsl increasing hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%)) }", &canonicalize("hsl(350deg 50% 50%)"));
20600
20601    minify_test(
20602      ".foo { color: color-mix(in hsl decreasing hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%)) }",
20603      &canonicalize("hsl(230deg 50% 50%)"),
20604    );
20605    minify_test(
20606      ".foo { color: color-mix(in hsl decreasing hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%)) }",
20607      &canonicalize("hsl(50deg 50% 50%)"),
20608    );
20609    minify_test(
20610      ".foo { color: color-mix(in hsl decreasing hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%)) }",
20611      &canonicalize("hsl(10deg 50% 50%)"),
20612    );
20613    minify_test(
20614      ".foo { color: color-mix(in hsl decreasing hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%)) }",
20615      &canonicalize("hsl(190deg 50% 50%)"),
20616    );
20617    minify_test(
20618      ".foo { color: color-mix(in hsl decreasing hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%)) }",
20619      &canonicalize("hsl(350deg 50% 50%)"),
20620    );
20621    // minify_test(".foo { color: color-mix(in hsl decreasing hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%)) }", &canonicalize("hsl(170deg 50% 50%)"));
20622
20623    minify_test(
20624      ".foo { color: color-mix(in hsl specified hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%)) }",
20625      &canonicalize("hsl(50deg 50% 50%)"),
20626    );
20627    minify_test(
20628      ".foo { color: color-mix(in hsl specified hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%)) }",
20629      &canonicalize("hsl(50deg 50% 50%)"),
20630    );
20631    minify_test(
20632      ".foo { color: color-mix(in hsl specified hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%)) }",
20633      &canonicalize("hsl(190deg 50% 50%)"),
20634    );
20635    minify_test(
20636      ".foo { color: color-mix(in hsl specified hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%)) }",
20637      &canonicalize("hsl(190deg 50% 50%)"),
20638    );
20639    // minify_test(".foo { color: color-mix(in hsl specified hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%)) }", &canonicalize("hsl(170deg 50% 50%)"));
20640    // minify_test(".foo { color: color-mix(in hsl specified hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%)) }", &canonicalize("hsl(170deg 50% 50%)"));
20641
20642    minify_test(
20643      ".foo { color: color-mix(in hsl, hsl(none none none), hsl(none none none)) }",
20644      &canonicalize("hsl(none none none)"),
20645    );
20646    minify_test(
20647      ".foo { color: color-mix(in hsl, hsl(none none none), hsl(30deg 40% 80%)) }",
20648      &canonicalize("hsl(30deg 40% 80%)"),
20649    );
20650    minify_test(
20651      ".foo { color: color-mix(in hsl, hsl(120deg 20% 40%), hsl(none none none)) }",
20652      &canonicalize("hsl(120deg 20% 40%)"),
20653    );
20654    minify_test(
20655      ".foo { color: color-mix(in hsl, hsl(120deg 20% none), hsl(30deg 40% 60%)) }",
20656      &canonicalize("hsl(75deg 30% 60%)"),
20657    );
20658    minify_test(
20659      ".foo { color: color-mix(in hsl, hsl(120deg 20% 40%), hsl(30deg 20% none)) }",
20660      &canonicalize("hsl(75deg 20% 40%)"),
20661    );
20662    minify_test(
20663      ".foo { color: color-mix(in hsl, hsl(none 20% 40%), hsl(30deg none 80%)) }",
20664      &canonicalize("hsl(30deg 20% 60%)"),
20665    );
20666
20667    minify_test(
20668      ".foo { color: color-mix(in hsl, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%) }",
20669      &canonicalize("rgb(0, 249, 66)"),
20670    ); // Naive clip based mapping would give rgb(0, 255, 0).
20671    minify_test(
20672      ".foo { color: color-mix(in hsl, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%) }",
20673      &canonicalize("rgb(255, 255, 255)"),
20674    ); // Naive clip based mapping would give rgb(255, 150, 255).
20675    minify_test(
20676      ".foo { color: color-mix(in hsl, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%) }",
20677      &canonicalize("rgb(42, 0, 34)"),
20678    ); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
20679    minify_test(
20680      ".foo { color: color-mix(in hsl, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%) }",
20681      &canonicalize("rgb(255, 255, 255)"),
20682    ); // Naive clip based mapping would give rgb(255, 150, 255).
20683    minify_test(
20684      ".foo { color: color-mix(in hsl, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%) }",
20685      &canonicalize("rgb(42, 0, 34)"),
20686    ); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
20687    minify_test(
20688      ".foo { color: color-mix(in hsl, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%) }",
20689      &canonicalize("rgb(255, 255, 255)"),
20690    ); // Naive clip based mapping would give rgb(255, 92, 255).
20691    minify_test(
20692      ".foo { color: color-mix(in hsl, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%) }",
20693      &canonicalize("rgb(0, 0, 0)"),
20694    ); // Naive clip based mapping would give rgb(19, 0, 24).
20695    minify_test(
20696      ".foo { color: color-mix(in hsl, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%) }",
20697      &canonicalize("rgb(255, 255, 255)"),
20698    ); // Naive clip based mapping would give rgb(255, 91, 255).
20699    minify_test(
20700      ".foo { color: color-mix(in hsl, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%) }",
20701      &canonicalize("rgb(0, 0, 0)"),
20702    ); // Naive clip based mapping would give rgb(20, 0, 24).
20703
20704    minify_test(
20705      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%)) }",
20706      &canonicalize("rgb(147, 179, 52)"),
20707    );
20708    minify_test(
20709      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%)) }",
20710      &canonicalize("rgb(166, 153, 64)"),
20711    );
20712    minify_test(
20713      ".foo { color: color-mix(in hwb, 25% hwb(120deg 10% 20%), hwb(30deg 30% 40%)) }",
20714      &canonicalize("rgb(166, 153, 64)"),
20715    );
20716    minify_test(
20717      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20%), 25% hwb(30deg 30% 40%)) }",
20718      &canonicalize("rgb(96, 191, 39)"),
20719    );
20720    minify_test(
20721      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%) 25%) }",
20722      &canonicalize("rgb(96, 191, 39)"),
20723    );
20724    minify_test(
20725      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%) 75%) }",
20726      &canonicalize("rgb(166, 153, 64)"),
20727    );
20728    minify_test(
20729      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20%) 30%, hwb(30deg 30% 40%) 90%) }",
20730      &canonicalize("rgb(166, 153, 64)"),
20731    ); // Scale down > 100% sum.
20732    minify_test(
20733      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20%) 12.5%, hwb(30deg 30% 40%) 37.5%) }",
20734      &canonicalize("rgba(166, 153, 64, 0.5)"),
20735    ); // Scale up < 100% sum, causes alpha multiplication.
20736    minify_test(
20737      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20%) 0%, hwb(30deg 30% 40%)) }",
20738      &canonicalize("rgb(153, 115, 77)"),
20739    );
20740
20741    minify_test(
20742      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20% / .4), hwb(30deg 30% 40% / .8)) }",
20743      &canonicalize("rgba(143, 170, 60, 0.6)"),
20744    );
20745    minify_test(
20746      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20% / .4) 25%, hwb(30deg 30% 40% / .8)) }",
20747      &canonicalize("rgba(160, 149, 70, 0.7)"),
20748    );
20749    minify_test(
20750      ".foo { color: color-mix(in hwb, 25% hwb(120deg 10% 20% / .4), hwb(30deg 30% 40% / .8)) }",
20751      &canonicalize("rgba(160, 149, 70, 0.7)"),
20752    );
20753    minify_test(
20754      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20%), 25% hwb(30deg 30% 40% / .8)) }",
20755      &canonicalize("rgba(95, 193, 37, 0.95)"),
20756    );
20757    minify_test(
20758      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20% / .4), hwb(30deg 30% 40% / .8) 25%) }",
20759      &canonicalize("rgba(98, 184, 46, 0.5)"),
20760    );
20761    minify_test(
20762      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20% / .4) 25%, hwb(30deg 30% 40% / .8) 75%) }",
20763      &canonicalize("rgba(160, 149, 70, 0.7)"),
20764    );
20765    minify_test(
20766      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20% / .4) 30%, hwb(30deg 30% 40% / .8) 90%) }",
20767      &canonicalize("rgba(160, 149, 70, 0.7)"),
20768    ); // Scale down > 100% sum.
20769    minify_test(
20770      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20% / .4) 12.5%, hwb(30deg 30% 40% / .8) 37.5%) }",
20771      &canonicalize("rgba(160, 149, 70, 0.35)"),
20772    ); // Scale up < 100% sum, causes alpha multiplication.
20773    minify_test(
20774      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20% / .4) 0%, hwb(30deg 30% 40% / .8)) }",
20775      &canonicalize("rgba(153, 115, 77, 0.8)"),
20776    );
20777
20778    //  minify_test(".foo { color: color-mix(in hwb, hwb(40deg 30% 40%), hwb(60deg 30% 40%)) }", &canonicalize("hwb(50deg 30% 40%)"));
20779    //  minify_test(".foo { color: color-mix(in hwb, hwb(60deg 30% 40%), hwb(40deg 30% 40%)) }", &canonicalize("hwb(50deg 30% 40%)"));
20780    minify_test(
20781      ".foo { color: color-mix(in hwb, hwb(50deg 30% 40%), hwb(330deg 30% 40%)) }",
20782      &canonicalize("hwb(10deg 30% 40%)"),
20783    );
20784    minify_test(
20785      ".foo { color: color-mix(in hwb, hwb(330deg 30% 40%), hwb(50deg 30% 40%)) }",
20786      &canonicalize("hwb(10deg 30% 40%)"),
20787    );
20788    minify_test(
20789      ".foo { color: color-mix(in hwb, hwb(20deg 30% 40%), hwb(320deg 30% 40%)) }",
20790      &canonicalize("hwb(350deg 30% 40%)"),
20791    );
20792    minify_test(
20793      ".foo { color: color-mix(in hwb, hwb(320deg 30% 40%), hwb(20deg 30% 40%)) }",
20794      &canonicalize("hwb(350deg 30% 40%)"),
20795    );
20796
20797    //  minify_test(".foo { color: color-mix(in hwb shorter hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%)) }", &canonicalize("hwb(50deg 30% 40%)"));
20798    //  minify_test(".foo { color: color-mix(in hwb shorter hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%)) }", &canonicalize("hwb(50deg 30% 40%)"));
20799    minify_test(
20800      ".foo { color: color-mix(in hwb shorter hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%)) }",
20801      &canonicalize("hwb(10deg 30% 40%)"),
20802    );
20803    minify_test(
20804      ".foo { color: color-mix(in hwb shorter hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%)) }",
20805      &canonicalize("hwb(10deg 30% 40%)"),
20806    );
20807    minify_test(
20808      ".foo { color: color-mix(in hwb shorter hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%)) }",
20809      &canonicalize("hwb(350deg 30% 40%)"),
20810    );
20811    minify_test(
20812      ".foo { color: color-mix(in hwb shorter hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%)) }",
20813      &canonicalize("hwb(350deg 30% 40%)"),
20814    );
20815
20816    minify_test(
20817      ".foo { color: color-mix(in hwb longer hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%)) }",
20818      &canonicalize("hwb(230deg 30% 40%)"),
20819    );
20820    minify_test(
20821      ".foo { color: color-mix(in hwb longer hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%)) }",
20822      &canonicalize("hwb(230deg 30% 40%)"),
20823    );
20824    //  minify_test(".foo { color: color-mix(in hwb longer hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%)) }", &canonicalize("hwb(190deg 30% 40%)"));
20825    //  minify_test(".foo { color: color-mix(in hwb longer hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%)) }", &canonicalize("hwb(190deg 30% 40%)"));
20826    //  minify_test(".foo { color: color-mix(in hwb longer hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%)) }", &canonicalize("hwb(170deg 30% 40%)"));
20827    //  minify_test(".foo { color: color-mix(in hwb longer hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%)) }", &canonicalize("hwb(170deg 30% 40%)"));
20828
20829    // minify_test(".foo { color: color-mix(in hwb increasing hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%)) }", &canonicalize("hwb(50deg 30% 40%)"));
20830    minify_test(
20831      ".foo { color: color-mix(in hwb increasing hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%)) }",
20832      &canonicalize("hwb(230deg 30% 40%)"),
20833    );
20834    // minify_test(".foo { color: color-mix(in hwb increasing hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%)) }", &canonicalize("hwb(190deg 30% 40%)"));
20835    minify_test(
20836      ".foo { color: color-mix(in hwb increasing hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%)) }",
20837      &canonicalize("hwb(10deg 30% 40%)"),
20838    );
20839    // minify_test(".foo { color: color-mix(in hwb increasing hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%)) }", &canonicalize("hwb(170deg 30% 40%)"));
20840    minify_test(
20841      ".foo { color: color-mix(in hwb increasing hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%)) }",
20842      &canonicalize("hwb(350deg 30% 40%)"),
20843    );
20844
20845    minify_test(
20846      ".foo { color: color-mix(in hwb decreasing hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%)) }",
20847      &canonicalize("hwb(230deg 30% 40%)"),
20848    );
20849    // minify_test(".foo { color: color-mix(in hwb decreasing hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%)) }", &canonicalize("hwb(50deg 30% 40%)"));
20850    minify_test(
20851      ".foo { color: color-mix(in hwb decreasing hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%)) }",
20852      &canonicalize("hwb(10deg 30% 40%)"),
20853    );
20854    // minify_test(".foo { color: color-mix(in hwb decreasing hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%)) }", &canonicalize("hwb(190deg 30% 40%)"));
20855    minify_test(
20856      ".foo { color: color-mix(in hwb decreasing hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%)) }",
20857      &canonicalize("hwb(350deg 30% 40%)"),
20858    );
20859    // minify_test(".foo { color: color-mix(in hwb decreasing hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%)) }", &canonicalize("hwb(170deg 30% 40%)"));
20860
20861    // minify_test(".foo { color: color-mix(in hwb specified hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%)) }", &canonicalize("hwb(50deg 30% 40%)"));
20862    // minify_test(".foo { color: color-mix(in hwb specified hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%)) }", &canonicalize("hwb(50deg 30% 40%)"));
20863    // minify_test(".foo { color: color-mix(in hwb specified hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%)) }", &canonicalize("hwb(190deg 30% 40%)"));
20864    // minify_test(".foo { color: color-mix(in hwb specified hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%)) }", &canonicalize("hwb(190deg 30% 40%)"));
20865    // minify_test(".foo { color: color-mix(in hwb specified hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%)) }", &canonicalize("hwb(170deg 30% 40%)"));
20866    // minify_test(".foo { color: color-mix(in hwb specified hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%)) }", &canonicalize("hwb(170deg 30% 40%)"));
20867
20868    minify_test(
20869      ".foo { color: color-mix(in hwb, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%) }",
20870      &canonicalize("rgb(0, 249, 66)"),
20871    ); // Naive clip based mapping would give rgb(0, 255, 0).
20872    minify_test(
20873      ".foo { color: color-mix(in hwb, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%) }",
20874      &canonicalize("rgb(255, 255, 255)"),
20875    ); // Naive clip based mapping would give rgb(255, 150, 255).
20876    minify_test(
20877      ".foo { color: color-mix(in hwb, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%) }",
20878      &canonicalize("rgb(42, 0, 34)"),
20879    ); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
20880    minify_test(
20881      ".foo { color: color-mix(in hwb, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%) }",
20882      &canonicalize("rgb(255, 255, 255)"),
20883    ); // Naive clip based mapping would give rgb(255, 150, 255).
20884    minify_test(
20885      ".foo { color: color-mix(in hwb, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%) }",
20886      &canonicalize("rgb(42, 0, 34)"),
20887    ); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
20888    minify_test(
20889      ".foo { color: color-mix(in hwb, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%) }",
20890      &canonicalize("rgb(255, 255, 255)"),
20891    ); // Naive clip based mapping would give rgb(255, 92, 255).
20892    minify_test(
20893      ".foo { color: color-mix(in hwb, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%) }",
20894      &canonicalize("rgb(0, 0, 0)"),
20895    ); // Naive clip based mapping would give rgb(19, 0, 24).
20896    minify_test(
20897      ".foo { color: color-mix(in hwb, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%) }",
20898      &canonicalize("rgb(255, 255, 255)"),
20899    ); // Naive clip based mapping would give rgb(255, 91, 255).
20900    minify_test(
20901      ".foo { color: color-mix(in hwb, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%) }",
20902      &canonicalize("rgb(0, 0, 0)"),
20903    ); // Naive clip based mapping would give rgb(20, 0, 24).
20904
20905    for color_space in &["lch", "oklch"] {
20906      // regex for converting web platform tests:
20907      // test_computed_value\(.*?, `color-mix\(in \$\{colorSpace\}(.*?), (.*?)\$\{colorSpace\}(.*?) \$\{colorSpace\}(.*?)`, `\$\{colorSpace\}(.*?)`\);
20908      // minify_test(&format!(".foo {{ color: color-mix(in {0}$1, $2{0}$3 {0}$4 }}", color_space), &format!(".foo{{color:{}$5}}", color_space));
20909
20910      minify_test(
20911        &format!(
20912          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg), {0}(50% 60 70deg)) }}",
20913          color_space
20914        ),
20915        &format!(".foo{{color:{}(30% 40 50)}}", color_space),
20916      );
20917      minify_test(
20918        &format!(
20919          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg) 25%, {0}(50% 60 70deg)) }}",
20920          color_space
20921        ),
20922        &format!(".foo{{color:{}(40% 50 60)}}", color_space),
20923      );
20924      minify_test(
20925        &format!(
20926          ".foo {{ color: color-mix(in {0}, 25% {0}(10% 20 30deg), {0}(50% 60 70deg)) }}",
20927          color_space
20928        ),
20929        &format!(".foo{{color:{}(40% 50 60)}}", color_space),
20930      );
20931      minify_test(
20932        &format!(
20933          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg), 25% {0}(50% 60 70deg)) }}",
20934          color_space
20935        ),
20936        &format!(".foo{{color:{}(20% 30 40)}}", color_space),
20937      );
20938      minify_test(
20939        &format!(
20940          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg), {0}(50% 60 70deg) 25%) }}",
20941          color_space
20942        ),
20943        &format!(".foo{{color:{}(20% 30 40)}}", color_space),
20944      );
20945      minify_test(
20946        &format!(
20947          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg) 25%, {0}(50% 60 70deg) 75%) }}",
20948          color_space
20949        ),
20950        &format!(".foo{{color:{}(40% 50 60)}}", color_space),
20951      );
20952      minify_test(
20953        &format!(
20954          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg) 30%, {0}(50% 60 70deg) 90%) }}",
20955          color_space
20956        ),
20957        &format!(".foo{{color:{}(40% 50 60)}}", color_space),
20958      ); // Scale down > 100% sum.
20959      minify_test(
20960        &format!(
20961          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg) 12.5%, {0}(50% 60 70deg) 37.5%) }}",
20962          color_space
20963        ),
20964        &format!(".foo{{color:{}(40% 50 60/.5)}}", color_space),
20965      ); // Scale up < 100% sum, causes alpha multiplication.
20966      minify_test(
20967        &format!(
20968          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg) 0%, {0}(50% 60 70deg)) }}",
20969          color_space
20970        ),
20971        &format!(".foo{{color:{}(50% 60 70)}}", color_space),
20972      );
20973
20974      minify_test(
20975        &format!(
20976          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg / .4), {0}(50% 60 70deg / .8)) }}",
20977          color_space
20978        ),
20979        &format!(".foo{{color:{}(36.6667% 46.6667 50/.6)}}", color_space),
20980      );
20981      minify_test(
20982        &format!(
20983          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg / .4) 25%, {0}(50% 60 70deg / .8)) }}",
20984          color_space
20985        ),
20986        &format!(".foo{{color:{}(44.2857% 54.2857 60/.7)}}", color_space),
20987      );
20988      minify_test(
20989        &format!(
20990          ".foo {{ color: color-mix(in {0}, 25% {0}(10% 20 30deg / .4), {0}(50% 60 70deg / .8)) }}",
20991          color_space
20992        ),
20993        &format!(".foo{{color:{}(44.2857% 54.2857 60/.7)}}", color_space),
20994      );
20995      minify_test(
20996        &format!(
20997          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg / .4), 25% {0}(50% 60 70deg / .8)) }}",
20998          color_space
20999        ),
21000        &format!(".foo{{color:{}(26% 36 40/.5)}}", color_space),
21001      );
21002      minify_test(
21003        &format!(
21004          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg / .4), {0}(50% 60 70deg / .8) 25%) }}",
21005          color_space
21006        ),
21007        &format!(".foo{{color:{}(26% 36 40/.5)}}", color_space),
21008      );
21009      minify_test(
21010        &format!(
21011          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg / .4) 25%, {0}(50% 60 70deg / .8) 75%) }}",
21012          color_space
21013        ),
21014        &format!(".foo{{color:{}(44.2857% 54.2857 60/.7)}}", color_space),
21015      );
21016      minify_test(
21017        &format!(
21018          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg / .4) 30%, {0}(50% 60 70deg / .8) 90%) }}",
21019          color_space
21020        ),
21021        &format!(".foo{{color:{}(44.2857% 54.2857 60/.7)}}", color_space),
21022      ); // Scale down > 100% sum.
21023      minify_test(
21024        &format!(
21025          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg / .4) 12.5%, {0}(50% 60 70deg / .8) 37.5%) }}",
21026          color_space
21027        ),
21028        &format!(".foo{{color:{}(44.2857% 54.2857 60/.35)}}", color_space),
21029      ); // Scale up < 100% sum, causes alpha multiplication.
21030      minify_test(
21031        &format!(
21032          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg / .4) 0%, {0}(50% 60 70deg / .8)) }}",
21033          color_space
21034        ),
21035        &format!(".foo{{color:{}(50% 60 70/.8)}}", color_space),
21036      );
21037
21038      minify_test(
21039        &format!(
21040          ".foo {{ color: color-mix(in {0}, {0}(100% 0 40deg), {0}(100% 0 60deg)) }}",
21041          color_space
21042        ),
21043        &format!(".foo{{color:{}(100% 0 50)}}", color_space),
21044      );
21045      minify_test(
21046        &format!(
21047          ".foo {{ color: color-mix(in {0}, {0}(100% 0 60deg), {0}(100% 0 40deg)) }}",
21048          color_space
21049        ),
21050        &format!(".foo{{color:{}(100% 0 50)}}", color_space),
21051      );
21052      minify_test(
21053        &format!(
21054          ".foo {{ color: color-mix(in {0}, {0}(100% 0 50deg), {0}(100% 0 330deg)) }}",
21055          color_space
21056        ),
21057        &format!(".foo{{color:{}(100% 0 10)}}", color_space),
21058      );
21059      minify_test(
21060        &format!(
21061          ".foo {{ color: color-mix(in {0}, {0}(100% 0 330deg), {0}(100% 0 50deg)) }}",
21062          color_space
21063        ),
21064        &format!(".foo{{color:{}(100% 0 10)}}", color_space),
21065      );
21066      minify_test(
21067        &format!(
21068          ".foo {{ color: color-mix(in {0}, {0}(100% 0 20deg), {0}(100% 0 320deg)) }}",
21069          color_space
21070        ),
21071        &format!(".foo{{color:{}(100% 0 350)}}", color_space),
21072      );
21073      minify_test(
21074        &format!(
21075          ".foo {{ color: color-mix(in {0}, {0}(100% 0 320deg), {0}(100% 0 20deg)) }}",
21076          color_space
21077        ),
21078        &format!(".foo{{color:{}(100% 0 350)}}", color_space),
21079      );
21080
21081      minify_test(
21082        &format!(
21083          ".foo {{ color: color-mix(in {0} shorter hue, {0}(100% 0 40deg), {0}(100% 0 60deg)) }}",
21084          color_space
21085        ),
21086        &format!(".foo{{color:{}(100% 0 50)}}", color_space),
21087      );
21088      minify_test(
21089        &format!(
21090          ".foo {{ color: color-mix(in {0} shorter hue, {0}(100% 0 60deg), {0}(100% 0 40deg)) }}",
21091          color_space
21092        ),
21093        &format!(".foo{{color:{}(100% 0 50)}}", color_space),
21094      );
21095      minify_test(
21096        &format!(
21097          ".foo {{ color: color-mix(in {0} shorter hue, {0}(100% 0 50deg), {0}(100% 0 330deg)) }}",
21098          color_space
21099        ),
21100        &format!(".foo{{color:{}(100% 0 10)}}", color_space),
21101      );
21102      minify_test(
21103        &format!(
21104          ".foo {{ color: color-mix(in {0} shorter hue, {0}(100% 0 330deg), {0}(100% 0 50deg)) }}",
21105          color_space
21106        ),
21107        &format!(".foo{{color:{}(100% 0 10)}}", color_space),
21108      );
21109      minify_test(
21110        &format!(
21111          ".foo {{ color: color-mix(in {0} shorter hue, {0}(100% 0 20deg), {0}(100% 0 320deg)) }}",
21112          color_space
21113        ),
21114        &format!(".foo{{color:{}(100% 0 350)}}", color_space),
21115      );
21116      minify_test(
21117        &format!(
21118          ".foo {{ color: color-mix(in {0} shorter hue, {0}(100% 0 320deg), {0}(100% 0 20deg)) }}",
21119          color_space
21120        ),
21121        &format!(".foo{{color:{}(100% 0 350)}}", color_space),
21122      );
21123
21124      minify_test(
21125        &format!(
21126          ".foo {{ color: color-mix(in {0} longer hue, {0}(100% 0 40deg), {0}(100% 0 60deg)) }}",
21127          color_space
21128        ),
21129        &format!(".foo{{color:{}(100% 0 230)}}", color_space),
21130      );
21131      minify_test(
21132        &format!(
21133          ".foo {{ color: color-mix(in {0} longer hue, {0}(100% 0 60deg), {0}(100% 0 40deg)) }}",
21134          color_space
21135        ),
21136        &format!(".foo{{color:{}(100% 0 230)}}", color_space),
21137      );
21138      minify_test(
21139        &format!(
21140          ".foo {{ color: color-mix(in {0} longer hue, {0}(100% 0 50deg), {0}(100% 0 330deg)) }}",
21141          color_space
21142        ),
21143        &format!(".foo{{color:{}(100% 0 190)}}", color_space),
21144      );
21145      minify_test(
21146        &format!(
21147          ".foo {{ color: color-mix(in {0} longer hue, {0}(100% 0 330deg), {0}(100% 0 50deg)) }}",
21148          color_space
21149        ),
21150        &format!(".foo{{color:{}(100% 0 190)}}", color_space),
21151      );
21152      minify_test(
21153        &format!(
21154          ".foo {{ color: color-mix(in {0} longer hue, {0}(100% 0 20deg), {0}(100% 0 320deg)) }}",
21155          color_space
21156        ),
21157        &format!(".foo{{color:{}(100% 0 170)}}", color_space),
21158      );
21159      minify_test(
21160        &format!(
21161          ".foo {{ color: color-mix(in {0} longer hue, {0}(100% 0 320deg), {0}(100% 0 20deg)) }}",
21162          color_space
21163        ),
21164        &format!(".foo{{color:{}(100% 0 170)}}", color_space),
21165      );
21166
21167      minify_test(
21168        &format!(
21169          ".foo {{ color: color-mix(in {0} increasing hue, {0}(100% 0 40deg), {0}(100% 0 60deg)) }}",
21170          color_space
21171        ),
21172        &format!(".foo{{color:{}(100% 0 50)}}", color_space),
21173      );
21174      minify_test(
21175        &format!(
21176          ".foo {{ color: color-mix(in {0} increasing hue, {0}(100% 0 60deg), {0}(100% 0 40deg)) }}",
21177          color_space
21178        ),
21179        &format!(".foo{{color:{}(100% 0 230)}}", color_space),
21180      );
21181      minify_test(
21182        &format!(
21183          ".foo {{ color: color-mix(in {0} increasing hue, {0}(100% 0 50deg), {0}(100% 0 330deg)) }}",
21184          color_space
21185        ),
21186        &format!(".foo{{color:{}(100% 0 190)}}", color_space),
21187      );
21188      minify_test(
21189        &format!(
21190          ".foo {{ color: color-mix(in {0} increasing hue, {0}(100% 0 330deg), {0}(100% 0 50deg)) }}",
21191          color_space
21192        ),
21193        &format!(".foo{{color:{}(100% 0 10)}}", color_space),
21194      );
21195      minify_test(
21196        &format!(
21197          ".foo {{ color: color-mix(in {0} increasing hue, {0}(100% 0 20deg), {0}(100% 0 320deg)) }}",
21198          color_space
21199        ),
21200        &format!(".foo{{color:{}(100% 0 170)}}", color_space),
21201      );
21202      minify_test(
21203        &format!(
21204          ".foo {{ color: color-mix(in {0} increasing hue, {0}(100% 0 320deg), {0}(100% 0 20deg)) }}",
21205          color_space
21206        ),
21207        &format!(".foo{{color:{}(100% 0 350)}}", color_space),
21208      );
21209
21210      minify_test(
21211        &format!(
21212          ".foo {{ color: color-mix(in {0} decreasing hue, {0}(100% 0 40deg), {0}(100% 0 60deg)) }}",
21213          color_space
21214        ),
21215        &format!(".foo{{color:{}(100% 0 230)}}", color_space),
21216      );
21217      minify_test(
21218        &format!(
21219          ".foo {{ color: color-mix(in {0} decreasing hue, {0}(100% 0 60deg), {0}(100% 0 40deg)) }}",
21220          color_space
21221        ),
21222        &format!(".foo{{color:{}(100% 0 50)}}", color_space),
21223      );
21224      minify_test(
21225        &format!(
21226          ".foo {{ color: color-mix(in {0} decreasing hue, {0}(100% 0 50deg), {0}(100% 0 330deg)) }}",
21227          color_space
21228        ),
21229        &format!(".foo{{color:{}(100% 0 10)}}", color_space),
21230      );
21231      minify_test(
21232        &format!(
21233          ".foo {{ color: color-mix(in {0} decreasing hue, {0}(100% 0 330deg), {0}(100% 0 50deg)) }}",
21234          color_space
21235        ),
21236        &format!(".foo{{color:{}(100% 0 190)}}", color_space),
21237      );
21238      minify_test(
21239        &format!(
21240          ".foo {{ color: color-mix(in {0} decreasing hue, {0}(100% 0 20deg), {0}(100% 0 320deg)) }}",
21241          color_space
21242        ),
21243        &format!(".foo{{color:{}(100% 0 350)}}", color_space),
21244      );
21245      minify_test(
21246        &format!(
21247          ".foo {{ color: color-mix(in {0} decreasing hue, {0}(100% 0 320deg), {0}(100% 0 20deg)) }}",
21248          color_space
21249        ),
21250        &format!(".foo{{color:{}(100% 0 170)}}", color_space),
21251      );
21252
21253      minify_test(
21254        &format!(
21255          ".foo {{ color: color-mix(in {0} specified hue, {0}(100% 0 40deg), {0}(100% 0 60deg)) }}",
21256          color_space
21257        ),
21258        &format!(".foo{{color:{}(100% 0 50)}}", color_space),
21259      );
21260      minify_test(
21261        &format!(
21262          ".foo {{ color: color-mix(in {0} specified hue, {0}(100% 0 60deg), {0}(100% 0 40deg)) }}",
21263          color_space
21264        ),
21265        &format!(".foo{{color:{}(100% 0 50)}}", color_space),
21266      );
21267      minify_test(
21268        &format!(
21269          ".foo {{ color: color-mix(in {0} specified hue, {0}(100% 0 50deg), {0}(100% 0 330deg)) }}",
21270          color_space
21271        ),
21272        &format!(".foo{{color:{}(100% 0 190)}}", color_space),
21273      );
21274      minify_test(
21275        &format!(
21276          ".foo {{ color: color-mix(in {0} specified hue, {0}(100% 0 330deg), {0}(100% 0 50deg)) }}",
21277          color_space
21278        ),
21279        &format!(".foo{{color:{}(100% 0 190)}}", color_space),
21280      );
21281      minify_test(
21282        &format!(
21283          ".foo {{ color: color-mix(in {0} specified hue, {0}(100% 0 20deg), {0}(100% 0 320deg)) }}",
21284          color_space
21285        ),
21286        &format!(".foo{{color:{}(100% 0 170)}}", color_space),
21287      );
21288      minify_test(
21289        &format!(
21290          ".foo {{ color: color-mix(in {0} specified hue, {0}(100% 0 320deg), {0}(100% 0 20deg)) }}",
21291          color_space
21292        ),
21293        &format!(".foo{{color:{}(100% 0 170)}}", color_space),
21294      );
21295
21296      minify_test(
21297        &format!(
21298          ".foo {{ color: color-mix(in {0}, {0}(none none none), {0}(none none none)) }}",
21299          color_space
21300        ),
21301        &format!(".foo{{color:{}(none none none)}}", color_space),
21302      );
21303      minify_test(
21304        &format!(
21305          ".foo {{ color: color-mix(in {0}, {0}(none none none), {0}(50% 60 70deg)) }}",
21306          color_space
21307        ),
21308        &format!(".foo{{color:{}(50% 60 70)}}", color_space),
21309      );
21310      minify_test(
21311        &format!(
21312          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg), {0}(none none none)) }}",
21313          color_space
21314        ),
21315        &format!(".foo{{color:{}(10% 20 30)}}", color_space),
21316      );
21317      minify_test(
21318        &format!(
21319          ".foo {{ color: color-mix(in {0}, {0}(10% 20 none), {0}(50% 60 70deg)) }}",
21320          color_space
21321        ),
21322        &format!(".foo{{color:{}(30% 40 70)}}", color_space),
21323      );
21324      minify_test(
21325        &format!(
21326          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg), {0}(50% 60 none)) }}",
21327          color_space
21328        ),
21329        &format!(".foo{{color:{}(30% 40 30)}}", color_space),
21330      );
21331      minify_test(
21332        &format!(
21333          ".foo {{ color: color-mix(in {0}, {0}(none 20 30deg), {0}(50% none 70deg)) }}",
21334          color_space
21335        ),
21336        &format!(".foo{{color:{}(50% 20 50)}}", color_space),
21337      );
21338      minify_test(
21339        &format!(
21340          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg / none), {0}(50% 60 70deg)) }}",
21341          color_space
21342        ),
21343        &format!(".foo{{color:{}(30% 40 50)}}", color_space),
21344      );
21345      minify_test(
21346        &format!(
21347          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg / none), {0}(50% 60 70deg / 0.5)) }}",
21348          color_space
21349        ),
21350        &format!(".foo{{color:{}(30% 40 50/.5)}}", color_space),
21351      );
21352      minify_test(
21353        &format!(
21354          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg / none), {0}(50% 60 70deg / none)) }}",
21355          color_space
21356        ),
21357        &format!(".foo{{color:{}(30% 40 50/none)}}", color_space),
21358      );
21359    }
21360
21361    for color_space in ["lab", "oklab"] {
21362      minify_test(
21363        &format!(
21364          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30), {0}(50% 60 70)) }}",
21365          color_space
21366        ),
21367        &format!(".foo{{color:{}(30% 40 50)}}", color_space),
21368      );
21369      minify_test(
21370        &format!(
21371          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30) 25%, {0}(50% 60 70)) }}",
21372          color_space
21373        ),
21374        &format!(".foo{{color:{}(40% 50 60)}}", color_space),
21375      );
21376      minify_test(
21377        &format!(
21378          ".foo {{ color: color-mix(in {0}, 25% {0}(10% 20 30), {0}(50% 60 70)) }}",
21379          color_space
21380        ),
21381        &format!(".foo{{color:{}(40% 50 60)}}", color_space),
21382      );
21383      minify_test(
21384        &format!(
21385          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30), 25% {0}(50% 60 70)) }}",
21386          color_space
21387        ),
21388        &format!(".foo{{color:{}(20% 30 40)}}", color_space),
21389      );
21390      minify_test(
21391        &format!(
21392          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30), {0}(50% 60 70) 25%) }}",
21393          color_space
21394        ),
21395        &format!(".foo{{color:{}(20% 30 40)}}", color_space),
21396      );
21397      minify_test(
21398        &format!(
21399          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30) 25%, {0}(50% 60 70) 75%) }}",
21400          color_space
21401        ),
21402        &format!(".foo{{color:{}(40% 50 60)}}", color_space),
21403      );
21404      minify_test(
21405        &format!(
21406          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30) 30%, {0}(50% 60 70) 90%) }}",
21407          color_space
21408        ),
21409        &format!(".foo{{color:{}(40% 50 60)}}", color_space),
21410      ); // Scale down > 100% sum.
21411      minify_test(
21412        &format!(
21413          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30) 12.5%, {0}(50% 60 70) 37.5%) }}",
21414          color_space
21415        ),
21416        &format!(".foo{{color:{}(40% 50 60/.5)}}", color_space),
21417      ); // Scale up < 100% sum, causes alpha multiplication.
21418      minify_test(
21419        &format!(
21420          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30) 0%, {0}(50% 60 70)) }}",
21421          color_space
21422        ),
21423        &format!(".foo{{color:{}(50% 60 70)}}", color_space),
21424      );
21425
21426      minify_test(
21427        &format!(
21428          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30 / .4), {0}(50% 60 70 / .8)) }}",
21429          color_space
21430        ),
21431        &format!(".foo{{color:{}(36.6667% 46.6667 56.6667/.6)}}", color_space),
21432      );
21433      minify_test(
21434        &format!(
21435          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30 / .4) 25%, {0}(50% 60 70 / .8)) }}",
21436          color_space
21437        ),
21438        &format!(".foo{{color:{}(44.2857% 54.2857 64.2857/.7)}}", color_space),
21439      );
21440      minify_test(
21441        &format!(
21442          ".foo {{ color: color-mix(in {0}, 25% {0}(10% 20 30 / .4), {0}(50% 60 70 / .8)) }}",
21443          color_space
21444        ),
21445        &format!(".foo{{color:{}(44.2857% 54.2857 64.2857/.7)}}", color_space),
21446      );
21447      minify_test(
21448        &format!(
21449          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30 / .4), 25% {0}(50% 60 70 / .8)) }}",
21450          color_space
21451        ),
21452        &format!(".foo{{color:{}(26% 36 46/.5)}}", color_space),
21453      );
21454      minify_test(
21455        &format!(
21456          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30 / .4), {0}(50% 60 70 / .8) 25%) }}",
21457          color_space
21458        ),
21459        &format!(".foo{{color:{}(26% 36 46/.5)}}", color_space),
21460      );
21461      minify_test(
21462        &format!(
21463          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30 / .4) 25%, {0}(50% 60 70 / .8) 75%) }}",
21464          color_space
21465        ),
21466        &format!(".foo{{color:{}(44.2857% 54.2857 64.2857/.7)}}", color_space),
21467      );
21468      minify_test(
21469        &format!(
21470          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30 / .4) 30%, {0}(50% 60 70 / .8) 90%) }}",
21471          color_space
21472        ),
21473        &format!(".foo{{color:{}(44.2857% 54.2857 64.2857/.7)}}", color_space),
21474      ); // Scale down > 100% sum.
21475      minify_test(
21476        &format!(
21477          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30 / .4) 12.5%, {0}(50% 60 70 / .8) 37.5%) }}",
21478          color_space
21479        ),
21480        &format!(".foo{{color:{}(44.2857% 54.2857 64.2857/.35)}}", color_space),
21481      ); // Scale up < 100% sum, causes alpha multiplication.
21482      minify_test(
21483        &format!(
21484          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30 / .4) 0%, {0}(50% 60 70 / .8)) }}",
21485          color_space
21486        ),
21487        &format!(".foo{{color:{}(50% 60 70/.8)}}", color_space),
21488      );
21489
21490      minify_test(
21491        &format!(
21492          ".foo {{ color: color-mix(in {0}, {0}(none none none), {0}(none none none)) }}",
21493          color_space
21494        ),
21495        &format!(".foo{{color:{}(none none none)}}", color_space),
21496      );
21497      minify_test(
21498        &format!(
21499          ".foo {{ color: color-mix(in {0}, {0}(none none none), {0}(50% 60 70)) }}",
21500          color_space
21501        ),
21502        &format!(".foo{{color:{}(50% 60 70)}}", color_space),
21503      );
21504      minify_test(
21505        &format!(
21506          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30), {0}(none none none)) }}",
21507          color_space
21508        ),
21509        &format!(".foo{{color:{}(10% 20 30)}}", color_space),
21510      );
21511      minify_test(
21512        &format!(
21513          ".foo {{ color: color-mix(in {0}, {0}(10% 20 none), {0}(50% 60 70)) }}",
21514          color_space
21515        ),
21516        &format!(".foo{{color:{}(30% 40 70)}}", color_space),
21517      );
21518      minify_test(
21519        &format!(
21520          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30), {0}(50% 60 none)) }}",
21521          color_space
21522        ),
21523        &format!(".foo{{color:{}(30% 40 30)}}", color_space),
21524      );
21525      minify_test(
21526        &format!(
21527          ".foo {{ color: color-mix(in {0}, {0}(none 20 30), {0}(50% none 70)) }}",
21528          color_space
21529        ),
21530        &format!(".foo{{color:{}(50% 20 50)}}", color_space),
21531      );
21532      minify_test(
21533        &format!(
21534          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30 / none), {0}(50% 60 70)) }}",
21535          color_space
21536        ),
21537        &format!(".foo{{color:{}(30% 40 50)}}", color_space),
21538      );
21539      minify_test(
21540        &format!(
21541          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30 / none), {0}(50% 60 70 / 0.5)) }}",
21542          color_space
21543        ),
21544        &format!(".foo{{color:{}(30% 40 50/.5)}}", color_space),
21545      );
21546      minify_test(
21547        &format!(
21548          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30 / none), {0}(50% 60 70 / none)) }}",
21549          color_space
21550        ),
21551        &format!(".foo{{color:{}(30% 40 50/none)}}", color_space),
21552      );
21553    }
21554
21555    for color_space in [/*"srgb", */ "srgb-linear", "xyz", "xyz-d50", "xyz-d65"] {
21556      // regex for converting web platform tests:
21557      // test_computed_value\(.*?, `color-mix\(in \$\{colorSpace\}(.*?), (.*?)color\(\$\{colorSpace\}(.*?) color\(\$\{colorSpace\}(.*?)`, `color\(\$\{resultColorSpace\}(.*?)`\);
21558      // minify_test(&format!(".foo {{ color: color-mix(in {0}$1, $2color({0}$3 color({0}$4 }}", color_space), &format!(".foo{{color:color({}$5}}", result_color_space));
21559
21560      let result_color_space = if color_space == "xyz-d65" { "xyz" } else { color_space };
21561
21562      minify_test(
21563        &format!(
21564          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3), color({0} .5 .6 .7)) }}",
21565          color_space
21566        ),
21567        &format!(".foo{{color:color({} .3 .4 .5)}}", result_color_space),
21568      );
21569      minify_test(
21570        &format!(
21571          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3) 25%, color({0} .5 .6 .7)) }}",
21572          color_space
21573        ),
21574        &format!(".foo{{color:color({} .4 .5 .6)}}", result_color_space),
21575      );
21576      minify_test(
21577        &format!(
21578          ".foo {{ color: color-mix(in {0}, 25% color({0} .1 .2 .3), color({0} .5 .6 .7)) }}",
21579          color_space
21580        ),
21581        &format!(".foo{{color:color({} .4 .5 .6)}}", result_color_space),
21582      );
21583      minify_test(
21584        &format!(
21585          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3), color({0} .5 .6 .7) 25%) }}",
21586          color_space
21587        ),
21588        &format!(".foo{{color:color({} .2 .3 .4)}}", result_color_space),
21589      );
21590      minify_test(
21591        &format!(
21592          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3), 25% color({0} .5 .6 .7)) }}",
21593          color_space
21594        ),
21595        &format!(".foo{{color:color({} .2 .3 .4)}}", result_color_space),
21596      );
21597      minify_test(
21598        &format!(
21599          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3) 25%, color({0} .5 .6 .7) 75%) }}",
21600          color_space
21601        ),
21602        &format!(".foo{{color:color({} .4 .5 .6)}}", result_color_space),
21603      );
21604      minify_test(
21605        &format!(
21606          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3) 30%, color({0} .5 .6 .7) 90%) }}",
21607          color_space
21608        ),
21609        &format!(".foo{{color:color({} .4 .5 .6)}}", result_color_space),
21610      ); // Scale down > 100% sum.
21611      minify_test(
21612        &format!(
21613          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3) 12.5%, color({0} .5 .6 .7) 37.5%) }}",
21614          color_space
21615        ),
21616        &format!(".foo{{color:color({} .4 .5 .6/.5)}}", result_color_space),
21617      ); // Scale up < 100% sum, causes alpha multiplication.
21618      minify_test(
21619        &format!(
21620          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3) 0%, color({0} .5 .6 .7)) }}",
21621          color_space
21622        ),
21623        &format!(".foo{{color:color({} .5 .6 .7)}}", result_color_space),
21624      );
21625
21626      minify_test(
21627        &format!(
21628          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3 / .5), color({0} .5 .6 .7 / .8)) }}",
21629          color_space
21630        ),
21631        &format!(
21632          ".foo{{color:color({} .346154 .446154 .546154/.65)}}",
21633          result_color_space
21634        ),
21635      );
21636      minify_test(
21637        &format!(
21638          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3 / .4) 25%, color({0} .5 .6 .7 / .8)) }}",
21639          color_space
21640        ),
21641        &format!(".foo{{color:color({} .442857 .542857 .642857/.7)}}", result_color_space),
21642      );
21643      minify_test(
21644        &format!(
21645          ".foo {{ color: color-mix(in {0}, 25% color({0} .1 .2 .3 / .4), color({0} .5 .6 .7 / .8)) }}",
21646          color_space
21647        ),
21648        &format!(".foo{{color:color({} .442857 .542857 .642857/.7)}}", result_color_space),
21649      );
21650      minify_test(
21651        &format!(
21652          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3 / .4), color({0} .5 .6 .7 / .8) 25%) }}",
21653          color_space
21654        ),
21655        &format!(".foo{{color:color({} .26 .36 .46/.5)}}", result_color_space),
21656      );
21657      minify_test(
21658        &format!(
21659          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3 / .4), 25% color({0} .5 .6 .7 / .8)) }}",
21660          color_space
21661        ),
21662        &format!(".foo{{color:color({} .26 .36 .46/.5)}}", result_color_space),
21663      );
21664      minify_test(
21665        &format!(
21666          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3 / .4) 25%, color({0} .5 .6 .7 / .8) 75%) }}",
21667          color_space
21668        ),
21669        &format!(".foo{{color:color({} .442857 .542857 .642857/.7)}}", result_color_space),
21670      );
21671      minify_test(
21672        &format!(
21673          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3 / .4) 30%, color({0} .5 .6 .7 / .8) 90%) }}",
21674          color_space
21675        ),
21676        &format!(".foo{{color:color({} .442857 .542857 .642857/.7)}}", result_color_space),
21677      ); // Scale down > 100% sum.
21678      minify_test(
21679        &format!(
21680          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3 / .4) 12.5%, color({0} .5 .6 .7 / .8) 37.5%) }}",
21681          color_space
21682        ),
21683        &format!(
21684          ".foo{{color:color({} .442857 .542857 .642857/.35)}}",
21685          result_color_space
21686        ),
21687      ); // Scale up < 100% sum, causes alpha multiplication.
21688      minify_test(
21689        &format!(
21690          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3 / .4) 0%, color({0} .5 .6 .7 / .8)) }}",
21691          color_space
21692        ),
21693        &format!(".foo{{color:color({} .5 .6 .7/.8)}}", result_color_space),
21694      );
21695
21696      minify_test(
21697        &format!(
21698          ".foo {{ color: color-mix(in {0}, color({0} 2 3 4 / 5), color({0} 4 6 8 / 10)) }}",
21699          color_space
21700        ),
21701        &format!(".foo{{color:color({} 3 4.5 6)}}", result_color_space),
21702      );
21703      minify_test(
21704        &format!(
21705          ".foo {{ color: color-mix(in {0}, color({0} -2 -3 -4), color({0} -4 -6 -8)) }}",
21706          color_space
21707        ),
21708        &format!(".foo{{color:color({} -3 -4.5 -6)}}", result_color_space),
21709      );
21710      minify_test(
21711        &format!(
21712          ".foo {{ color: color-mix(in {0}, color({0} -2 -3 -4 / -5), color({0} -4 -6 -8 / -10)) }}",
21713          color_space
21714        ),
21715        &format!(".foo{{color:color({} 0 0 0/0)}}", result_color_space),
21716      );
21717
21718      minify_test(
21719        &format!(
21720          ".foo {{ color: color-mix(in {0}, color({0} none none none), color({0} none none none)) }}",
21721          color_space
21722        ),
21723        &format!(".foo{{color:color({} none none none)}}", result_color_space),
21724      );
21725      minify_test(
21726        &format!(
21727          ".foo {{ color: color-mix(in {0}, color({0} none none none), color({0} .5 .6 .7)) }}",
21728          color_space
21729        ),
21730        &format!(".foo{{color:color({} .5 .6 .7)}}", result_color_space),
21731      );
21732      minify_test(
21733        &format!(
21734          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3), color({0} none none none)) }}",
21735          color_space
21736        ),
21737        &format!(".foo{{color:color({} .1 .2 .3)}}", result_color_space),
21738      );
21739      minify_test(
21740        &format!(
21741          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 none), color({0} .5 .6 .7)) }}",
21742          color_space
21743        ),
21744        &format!(".foo{{color:color({} .3 .4 .7)}}", result_color_space),
21745      );
21746      minify_test(
21747        &format!(
21748          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3), color({0} .5 .6 none)) }}",
21749          color_space
21750        ),
21751        &format!(".foo{{color:color({} .3 .4 .3)}}", result_color_space),
21752      );
21753      minify_test(
21754        &format!(
21755          ".foo {{ color: color-mix(in {0}, color({0} none .2 .3), color({0} .5 none .7)) }}",
21756          color_space
21757        ),
21758        &format!(".foo{{color:color({} .5 .2 .5)}}", result_color_space),
21759      );
21760      minify_test(
21761        &format!(
21762          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3 / none), color({0} .5 .6 .7)) }}",
21763          color_space
21764        ),
21765        &format!(".foo{{color:color({} .3 .4 .5)}}", result_color_space),
21766      );
21767      minify_test(
21768        &format!(
21769          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3 / none), color({0} .5 .6 .7 / 0.5)) }}",
21770          color_space
21771        ),
21772        &format!(".foo{{color:color({} .3 .4 .5/.5)}}", result_color_space),
21773      );
21774      minify_test(
21775        &format!(
21776          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3 / none), color({0} .5 .6 .7 / none)) }}",
21777          color_space
21778        ),
21779        &format!(".foo{{color:color({} .3 .4 .5/none)}}", result_color_space),
21780      );
21781    }
21782  }
21783
21784  #[test]
21785  fn test_grid() {
21786    minify_test(
21787      ".foo { grid-template-columns: [first nav-start]  150px [main-start] 1fr [last]; }",
21788      ".foo{grid-template-columns:[first nav-start]150px[main-start]1fr[last]}",
21789    );
21790    minify_test(
21791      ".foo { grid-template-columns: 150px 1fr; }",
21792      ".foo{grid-template-columns:150px 1fr}",
21793    );
21794    minify_test(
21795      ".foo { grid-template-columns: repeat(4, 1fr); }",
21796      ".foo{grid-template-columns:repeat(4,1fr)}",
21797    );
21798    minify_test(
21799      ".foo { grid-template-columns: repeat(2, [e] 40px); }",
21800      ".foo{grid-template-columns:repeat(2,[e]40px)}",
21801    );
21802    minify_test(
21803      ".foo { grid-template-columns: repeat(4, [col-start] 250px [col-end]); }",
21804      ".foo{grid-template-columns:repeat(4,[col-start]250px[col-end])}",
21805    );
21806    minify_test(
21807      ".foo { grid-template-columns: repeat(4, [col-start] 60% [col-end]); }",
21808      ".foo{grid-template-columns:repeat(4,[col-start]60%[col-end])}",
21809    );
21810    minify_test(
21811      ".foo { grid-template-columns: repeat(4, [col-start] 1fr [col-end]); }",
21812      ".foo{grid-template-columns:repeat(4,[col-start]1fr[col-end])}",
21813    );
21814    minify_test(
21815      ".foo { grid-template-columns: repeat(4, [col-start] min-content [col-end]); }",
21816      ".foo{grid-template-columns:repeat(4,[col-start]min-content[col-end])}",
21817    );
21818    minify_test(
21819      ".foo { grid-template-columns: repeat(4, [col-start] max-content [col-end]); }",
21820      ".foo{grid-template-columns:repeat(4,[col-start]max-content[col-end])}",
21821    );
21822    minify_test(
21823      ".foo { grid-template-columns: repeat(4, [col-start] auto [col-end]); }",
21824      ".foo{grid-template-columns:repeat(4,[col-start]auto[col-end])}",
21825    );
21826    minify_test(
21827      ".foo { grid-template-columns: repeat(4, [col-start] minmax(100px, 1fr) [col-end]); }",
21828      ".foo{grid-template-columns:repeat(4,[col-start]minmax(100px,1fr)[col-end])}",
21829    );
21830    minify_test(
21831      ".foo { grid-template-columns: repeat(4, [col-start] fit-content(200px) [col-end]); }",
21832      ".foo{grid-template-columns:repeat(4,[col-start]fit-content(200px)[col-end])}",
21833    );
21834    minify_test(
21835      ".foo { grid-template-columns: repeat(4, 10px [col-start] 30% [col-middle] auto [col-end]); }",
21836      ".foo{grid-template-columns:repeat(4,10px[col-start]30%[col-middle]auto[col-end])}",
21837    );
21838    minify_test(
21839      ".foo { grid-template-columns: repeat(5, auto); }",
21840      ".foo{grid-template-columns:repeat(5,auto)}",
21841    );
21842    minify_test(
21843      ".foo { grid-template-columns: repeat(auto-fill, 250px); }",
21844      ".foo{grid-template-columns:repeat(auto-fill,250px)}",
21845    );
21846    minify_test(
21847      ".foo { grid-template-columns: repeat(auto-fit, 250px); }",
21848      ".foo{grid-template-columns:repeat(auto-fit,250px)}",
21849    );
21850    minify_test(
21851      ".foo { grid-template-columns: repeat(auto-fill, [col-start] 250px [col-end]); }",
21852      ".foo{grid-template-columns:repeat(auto-fill,[col-start]250px[col-end])}",
21853    );
21854    minify_test(
21855      ".foo { grid-template-columns: repeat(auto-fill, [col-start] minmax(100px, 1fr) [col-end]); }",
21856      ".foo{grid-template-columns:repeat(auto-fill,[col-start]minmax(100px,1fr)[col-end])}",
21857    );
21858    minify_test(
21859      ".foo { grid-template-columns: minmax(min-content, 1fr); }",
21860      ".foo{grid-template-columns:minmax(min-content,1fr)}",
21861    );
21862    minify_test(
21863      ".foo { grid-template-columns: 200px repeat(auto-fill, 100px) 300px; }",
21864      ".foo{grid-template-columns:200px repeat(auto-fill,100px) 300px}",
21865    );
21866    minify_test(".foo { grid-template-columns: [linename1 linename2] 100px repeat(auto-fit, [linename1] 300px) [linename3]; }", ".foo{grid-template-columns:[linename1 linename2]100px repeat(auto-fit,[linename1]300px)[linename3]}");
21867    minify_test(
21868      ".foo { grid-template-rows: [linename1 linename2] 100px repeat(auto-fit, [linename1] 300px) [linename3]; }",
21869      ".foo{grid-template-rows:[linename1 linename2]100px repeat(auto-fit,[linename1]300px)[linename3]}",
21870    );
21871
21872    minify_test(".foo { grid-auto-rows: auto; }", ".foo{grid-auto-rows:auto}");
21873    minify_test(".foo { grid-auto-rows: 1fr; }", ".foo{grid-auto-rows:1fr}");
21874    minify_test(".foo { grid-auto-rows: 100px; }", ".foo{grid-auto-rows:100px}");
21875    minify_test(
21876      ".foo { grid-auto-rows: min-content; }",
21877      ".foo{grid-auto-rows:min-content}",
21878    );
21879    minify_test(
21880      ".foo { grid-auto-rows: max-content; }",
21881      ".foo{grid-auto-rows:max-content}",
21882    );
21883    minify_test(
21884      ".foo { grid-auto-rows: minmax(100px,auto); }",
21885      ".foo{grid-auto-rows:minmax(100px,auto)}",
21886    );
21887    minify_test(
21888      ".foo { grid-auto-rows: fit-content(20%); }",
21889      ".foo{grid-auto-rows:fit-content(20%)}",
21890    );
21891    minify_test(
21892      ".foo { grid-auto-rows: 100px minmax(100px, auto) 10% 0.5fr fit-content(400px); }",
21893      ".foo{grid-auto-rows:100px minmax(100px,auto) 10% .5fr fit-content(400px)}",
21894    );
21895    minify_test(
21896      ".foo { grid-auto-columns: 100px minmax(100px, auto) 10% 0.5fr fit-content(400px); }",
21897      ".foo{grid-auto-columns:100px minmax(100px,auto) 10% .5fr fit-content(400px)}",
21898    );
21899
21900    minify_test(
21901      r#"
21902      .foo {
21903        grid-template-areas: "head head"
21904                             "nav  main"
21905                             "foot ....";
21906      }
21907    "#,
21908      ".foo{grid-template-areas:\"head head\"\"nav main\"\"foot.\"}",
21909    );
21910    minify_test(
21911      r#"
21912      .foo {
21913        grid-template-areas: "head head"
21914                             "nav  main"
21915                             ".... foot";
21916      }
21917    "#,
21918      ".foo{grid-template-areas:\"head head\"\"nav main\"\".foot\"}",
21919    );
21920    minify_test(
21921      r#"
21922      .foo {
21923        grid-template-areas: "head head"
21924                             "nav  main"
21925                             ".... ....";
21926      }
21927    "#,
21928      ".foo{grid-template-areas:\"head head\"\"nav main\"\". .\"}",
21929    );
21930
21931    test(
21932      r#"
21933      .foo {
21934        grid-template-areas: "head head" "nav  main" "foot ....";
21935      }
21936    "#,
21937      indoc! { r#"
21938      .foo {
21939        grid-template-areas: "head head"
21940                             "nav main"
21941                             "foot .";
21942      }
21943    "#},
21944    );
21945
21946    minify_test(
21947      r#"
21948      .foo {
21949        grid-template: [header-top] "a   a   a"     [header-bottom]
21950                       [main-top] "b   b   b" 1fr [main-bottom];
21951      }
21952    "#,
21953      ".foo{grid-template:[header-top]\"a a a\"[header-bottom main-top]\"b b b\"1fr[main-bottom]}",
21954    );
21955    minify_test(
21956      r#"
21957      .foo {
21958        grid-template: "head head"
21959                       "nav  main" 1fr
21960                       "foot ....";
21961      }
21962    "#,
21963      ".foo{grid-template:\"head head\"\"nav main\"1fr\"foot.\"}",
21964    );
21965    minify_test(
21966      r#"
21967      .foo {
21968        grid-template: [header-top] "a   a   a"     [header-bottom]
21969                         [main-top] "b   b   b" 1fr [main-bottom]
21970                                  / auto 1fr auto;
21971      }
21972    "#,
21973      ".foo{grid-template:[header-top]\"a a a\"[header-bottom main-top]\"b b b\"1fr[main-bottom]/auto 1fr auto}",
21974    );
21975
21976    minify_test(
21977      ".foo { grid-template: auto 1fr / auto 1fr auto; }",
21978      ".foo{grid-template:auto 1fr/auto 1fr auto}",
21979    );
21980    minify_test(
21981      ".foo { grid-template: [linename1 linename2] 100px repeat(auto-fit, [linename1] 300px) [linename3] / [linename1 linename2] 100px repeat(auto-fit, [linename1] 300px) [linename3]; }",
21982      ".foo{grid-template:[linename1 linename2]100px repeat(auto-fit,[linename1]300px)[linename3]/[linename1 linename2]100px repeat(auto-fit,[linename1]300px)[linename3]}"
21983    );
21984
21985    test(
21986      ".foo{grid-template:[header-top]\"a a a\"[header-bottom main-top]\"b b b\"1fr[main-bottom]/auto 1fr auto}",
21987      indoc! {r#"
21988        .foo {
21989          grid-template: [header-top] "a a a" [header-bottom]
21990                         [main-top] "b b b" 1fr [main-bottom]
21991                         / auto 1fr auto;
21992        }
21993      "#},
21994    );
21995    test(
21996      ".foo{grid-template:[header-top]\"a a a\"[main-top]\"b b b\"1fr/auto 1fr auto}",
21997      indoc! {r#"
21998        .foo {
21999          grid-template: [header-top] "a a a"
22000                         [main-top] "b b b" 1fr
22001                         / auto 1fr auto;
22002        }
22003      "#},
22004    );
22005
22006    minify_test(".foo { grid-auto-flow: row }", ".foo{grid-auto-flow:row}");
22007    minify_test(".foo { grid-auto-flow: column }", ".foo{grid-auto-flow:column}");
22008    minify_test(".foo { grid-auto-flow: row dense }", ".foo{grid-auto-flow:dense}");
22009    minify_test(".foo { grid-auto-flow: dense row }", ".foo{grid-auto-flow:dense}");
22010    minify_test(
22011      ".foo { grid-auto-flow: column dense }",
22012      ".foo{grid-auto-flow:column dense}",
22013    );
22014    minify_test(
22015      ".foo { grid-auto-flow: dense column }",
22016      ".foo{grid-auto-flow:column dense}",
22017    );
22018
22019    minify_test(".foo { grid: none }", ".foo{grid:none}");
22020    minify_test(".foo { grid: \"a\" 100px \"b\" 1fr }", ".foo{grid:\"a\"100px\"b\"1fr}");
22021    minify_test(
22022      ".foo { grid: [linename1] \"a\" 100px [linename2] }",
22023      ".foo{grid:[linename1]\"a\"100px[linename2]}",
22024    );
22025    minify_test(
22026      ".foo { grid: \"a\" 200px \"b\" min-content }",
22027      ".foo{grid:\"a\"200px\"b\"min-content}",
22028    );
22029    minify_test(
22030      ".foo { grid: \"a\" minmax(100px, max-content) \"b\" 20% }",
22031      ".foo{grid:\"a\"minmax(100px,max-content)\"b\"20%}",
22032    );
22033    minify_test(".foo { grid: 100px / 200px }", ".foo{grid:100px/200px}");
22034    minify_test(
22035      ".foo { grid: minmax(400px, min-content) / repeat(auto-fill, 50px) }",
22036      ".foo{grid:minmax(400px,min-content)/repeat(auto-fill,50px)}",
22037    );
22038
22039    minify_test(".foo { grid: 200px / auto-flow }", ".foo{grid:200px/auto-flow}");
22040    minify_test(".foo { grid: 30% / auto-flow dense }", ".foo{grid:30%/auto-flow dense}");
22041    minify_test(".foo { grid: 30% / dense auto-flow }", ".foo{grid:30%/auto-flow dense}");
22042    minify_test(
22043      ".foo { grid: repeat(3, [line1 line2 line3] 200px) / auto-flow 300px }",
22044      ".foo{grid:repeat(3,[line1 line2 line3]200px)/auto-flow 300px}",
22045    );
22046    minify_test(
22047      ".foo { grid: [line1] minmax(20em, max-content) / auto-flow dense 40% }",
22048      ".foo{grid:[line1]minmax(20em,max-content)/auto-flow dense 40%}",
22049    );
22050    minify_test(".foo { grid: none / auto-flow 1fr }", ".foo{grid:none/auto-flow 1fr}");
22051
22052    minify_test(".foo { grid: auto-flow / 200px }", ".foo{grid:none/200px}");
22053    minify_test(".foo { grid: auto-flow dense / 30% }", ".foo{grid:auto-flow dense/30%}");
22054    minify_test(".foo { grid: dense auto-flow / 30% }", ".foo{grid:auto-flow dense/30%}");
22055    minify_test(
22056      ".foo { grid: auto-flow 300px / repeat(3, [line1 line2 line3] 200px) }",
22057      ".foo{grid:auto-flow 300px/repeat(3,[line1 line2 line3]200px)}",
22058    );
22059    minify_test(
22060      ".foo { grid: auto-flow dense 40% / [line1] minmax(20em, max-content) }",
22061      ".foo{grid:auto-flow dense 40%/[line1]minmax(20em,max-content)}",
22062    );
22063
22064    minify_test(".foo { grid-row-start: auto }", ".foo{grid-row-start:auto}");
22065    minify_test(".foo { grid-row-start: some-area }", ".foo{grid-row-start:some-area}");
22066    minify_test(".foo { grid-row-start: 2 }", ".foo{grid-row-start:2}");
22067    minify_test(
22068      ".foo { grid-row-start: 2 some-line }",
22069      ".foo{grid-row-start:2 some-line}",
22070    );
22071    minify_test(
22072      ".foo { grid-row-start: some-line 2 }",
22073      ".foo{grid-row-start:2 some-line}",
22074    );
22075    minify_test(".foo { grid-row-start: span 3 }", ".foo{grid-row-start:span 3}");
22076    minify_test(
22077      ".foo { grid-row-start: span some-line }",
22078      ".foo{grid-row-start:span some-line}",
22079    );
22080    minify_test(
22081      ".foo { grid-row-start: span some-line 1 }",
22082      ".foo{grid-row-start:span some-line}",
22083    );
22084    minify_test(
22085      ".foo { grid-row-start: span 1 some-line }",
22086      ".foo{grid-row-start:span some-line}",
22087    );
22088    minify_test(
22089      ".foo { grid-row-start: span 5 some-line }",
22090      ".foo{grid-row-start:span 5 some-line}",
22091    );
22092    minify_test(
22093      ".foo { grid-row-start: span some-line 5 }",
22094      ".foo{grid-row-start:span 5 some-line}",
22095    );
22096
22097    minify_test(
22098      ".foo { grid-row-end: span 1 some-line }",
22099      ".foo{grid-row-end:span some-line}",
22100    );
22101    minify_test(
22102      ".foo { grid-column-start: span 1 some-line }",
22103      ".foo{grid-column-start:span some-line}",
22104    );
22105    minify_test(
22106      ".foo { grid-column-end: span 1 some-line }",
22107      ".foo{grid-column-end:span some-line}",
22108    );
22109
22110    minify_test(".foo { grid-row: 1 }", ".foo{grid-row:1}");
22111    minify_test(".foo { grid-row: 1 / auto }", ".foo{grid-row:1}");
22112    minify_test(".foo { grid-row: 1 / 1 }", ".foo{grid-row:1/1}");
22113    minify_test(".foo { grid-row: 1 / 3 }", ".foo{grid-row:1/3}");
22114    minify_test(".foo { grid-row: 1 / span 2 }", ".foo{grid-row:1/span 2}");
22115    minify_test(".foo { grid-row: main-start }", ".foo{grid-row:main-start}");
22116    minify_test(
22117      ".foo { grid-row: main-start / main-end }",
22118      ".foo{grid-row:main-start/main-end}",
22119    );
22120    minify_test(
22121      ".foo { grid-row: main-start / main-start }",
22122      ".foo{grid-row:main-start}",
22123    );
22124    minify_test(".foo { grid-column: 1 / auto }", ".foo{grid-column:1}");
22125
22126    minify_test(".foo { grid-area: a }", ".foo{grid-area:a}");
22127    minify_test(".foo { grid-area: a / a / a / a }", ".foo{grid-area:a}");
22128    minify_test(".foo { grid-area: a / b / a / b }", ".foo{grid-area:a/b}");
22129    minify_test(".foo { grid-area: a / b / c / b }", ".foo{grid-area:a/b/c}");
22130    minify_test(".foo { grid-area: a / b / c / d }", ".foo{grid-area:a/b/c/d}");
22131
22132    minify_test(".foo { grid-area: auto / auto / auto / auto }", ".foo{grid-area:auto}");
22133    minify_test(".foo { grid-area: 1 / auto }", ".foo{grid-area:1}");
22134    minify_test(".foo { grid-area: 1 / 2 / 3 / 4 }", ".foo{grid-area:1/2/3/4}");
22135    minify_test(".foo { grid-area: 1 / 1 / 1 / 1 }", ".foo{grid-area:1/1/1/1}");
22136
22137    test(
22138      r#"
22139        .foo{
22140          grid-template-rows: auto 1fr;
22141          grid-template-columns: auto 1fr auto;
22142          grid-template-areas: none;
22143        }
22144      "#,
22145      indoc! {r#"
22146        .foo {
22147          grid-template: auto 1fr / auto 1fr auto;
22148        }
22149      "#},
22150    );
22151
22152    test(
22153      r#"
22154        .foo{
22155          grid-template-areas: "a a a"
22156                               "b b b";
22157          grid-template-rows: [header-top] auto [header-bottom main-top] 1fr [main-bottom];
22158          grid-template-columns: auto 1fr auto;
22159        }
22160      "#,
22161      indoc! {r#"
22162        .foo {
22163          grid-template: [header-top] "a a a" [header-bottom]
22164                         [main-top] "b b b" 1fr [main-bottom]
22165                         / auto 1fr auto;
22166        }
22167      "#},
22168    );
22169
22170    test(
22171      r#"
22172        .foo{
22173          grid-template-areas: "a a a"
22174                               "b b b";
22175          grid-template-columns: repeat(3, 1fr);
22176          grid-template-rows: auto 1fr;
22177        }
22178      "#,
22179      indoc! {r#"
22180        .foo {
22181          grid-template-rows: auto 1fr;
22182          grid-template-columns: repeat(3, 1fr);
22183          grid-template-areas: "a a a"
22184                               "b b b";
22185        }
22186      "#},
22187    );
22188
22189    test(
22190      r#"
22191        .foo{
22192          grid-template-areas: "a a a"
22193                               "b b b";
22194          grid-template-columns: auto 1fr auto;
22195          grid-template-rows: repeat(2, 1fr);
22196        }
22197      "#,
22198      indoc! {r#"
22199        .foo {
22200          grid-template-rows: repeat(2, 1fr);
22201          grid-template-columns: auto 1fr auto;
22202          grid-template-areas: "a a a"
22203                               "b b b";
22204        }
22205      "#},
22206    );
22207
22208    test(
22209      r#"
22210        .foo{
22211          grid-template-areas: ". a a ."
22212                               ". b b .";
22213          grid-template-rows: auto 1fr;
22214          grid-template-columns: 10px 1fr 1fr 10px;
22215        }
22216      "#,
22217      indoc! {r#"
22218        .foo {
22219          grid-template: ". a a ."
22220                         ". b b ." 1fr
22221                         / 10px 1fr 1fr 10px;
22222        }
22223      "#},
22224    );
22225
22226    test(
22227      r#"
22228        .foo{
22229          grid-template-areas: none;
22230          grid-template-columns: auto 1fr auto;
22231          grid-template-rows: repeat(2, 1fr);
22232        }
22233      "#,
22234      indoc! {r#"
22235        .foo {
22236          grid-template: repeat(2, 1fr) / auto 1fr auto;
22237        }
22238      "#},
22239    );
22240
22241    test(
22242      r#"
22243        .foo{
22244          grid-template-areas: none;
22245          grid-template-columns: none;
22246          grid-template-rows: none;
22247        }
22248      "#,
22249      indoc! {r#"
22250        .foo {
22251          grid-template: none;
22252        }
22253      "#},
22254    );
22255
22256    test(
22257      r#"
22258        .foo{
22259          grid-template-areas: "a a a"
22260                               "b b b";
22261          grid-template-rows: [header-top] auto [header-bottom main-top] 1fr [main-bottom];
22262          grid-template-columns: auto 1fr auto;
22263          grid-auto-flow: row;
22264          grid-auto-rows: auto;
22265          grid-auto-columns: auto;
22266        }
22267      "#,
22268      indoc! {r#"
22269        .foo {
22270          grid: [header-top] "a a a" [header-bottom]
22271                [main-top] "b b b" 1fr [main-bottom]
22272                / auto 1fr auto;
22273        }
22274      "#},
22275    );
22276
22277    test(
22278      r#"
22279        .foo{
22280          grid-template-areas: none;
22281          grid-template-columns: auto 1fr auto;
22282          grid-template-rows: repeat(2, 1fr);
22283          grid-auto-flow: row;
22284          grid-auto-rows: auto;
22285          grid-auto-columns: auto;
22286        }
22287      "#,
22288      indoc! {r#"
22289        .foo {
22290          grid: repeat(2, 1fr) / auto 1fr auto;
22291        }
22292      "#},
22293    );
22294
22295    test(
22296      r#"
22297        .foo{
22298          grid-template-areas: none;
22299          grid-template-columns: none;
22300          grid-template-rows: none;
22301          grid-auto-flow: row;
22302          grid-auto-rows: auto;
22303          grid-auto-columns: auto;
22304        }
22305      "#,
22306      indoc! {r#"
22307        .foo {
22308          grid: none;
22309        }
22310      "#},
22311    );
22312
22313    test(
22314      r#"
22315        .foo{
22316          grid-template-areas: "a a a"
22317                               "b b b";
22318          grid-template-rows: [header-top] auto [header-bottom main-top] 1fr [main-bottom];
22319          grid-template-columns: auto 1fr auto;
22320          grid-auto-flow: column;
22321          grid-auto-rows: 1fr;
22322          grid-auto-columns: 1fr;
22323        }
22324      "#,
22325      indoc! {r#"
22326        .foo {
22327          grid-template: [header-top] "a a a" [header-bottom]
22328                         [main-top] "b b b" 1fr [main-bottom]
22329                         / auto 1fr auto;
22330          grid-auto-rows: 1fr;
22331          grid-auto-columns: 1fr;
22332          grid-auto-flow: column;
22333        }
22334      "#},
22335    );
22336
22337    test(
22338      r#"
22339        .foo{
22340          grid-template-rows: auto 1fr;
22341          grid-template-columns: auto 1fr auto;
22342          grid-template-areas: none;
22343          grid-auto-flow: row;
22344          grid-auto-rows: auto;
22345          grid-auto-columns: auto;
22346        }
22347      "#,
22348      indoc! {r#"
22349        .foo {
22350          grid: auto 1fr / auto 1fr auto;
22351        }
22352      "#},
22353    );
22354
22355    test(
22356      r#"
22357        .foo{
22358          grid-template-rows: auto 1fr;
22359          grid-template-columns: auto 1fr auto;
22360          grid-template-areas: none;
22361          grid-auto-flow: column;
22362          grid-auto-rows: 1fr;
22363          grid-auto-columns: 1fr;
22364        }
22365      "#,
22366      indoc! {r#"
22367        .foo {
22368          grid-template: auto 1fr / auto 1fr auto;
22369          grid-auto-rows: 1fr;
22370          grid-auto-columns: 1fr;
22371          grid-auto-flow: column;
22372        }
22373      "#},
22374    );
22375
22376    test(
22377      r#"
22378        .foo{
22379          grid-template-rows: none;
22380          grid-template-columns: auto 1fr auto;
22381          grid-template-areas: none;
22382          grid-auto-flow: column;
22383          grid-auto-rows: 1fr;
22384          grid-auto-columns: 1fr;
22385        }
22386      "#,
22387      indoc! {r#"
22388        .foo {
22389          grid-template: none / auto 1fr auto;
22390          grid-auto-rows: 1fr;
22391          grid-auto-columns: 1fr;
22392          grid-auto-flow: column;
22393        }
22394      "#},
22395    );
22396
22397    test(
22398      r#"
22399        .foo{
22400          grid-template-rows: none;
22401          grid-template-columns: auto 1fr auto;
22402          grid-template-areas: none;
22403          grid-auto-flow: row;
22404          grid-auto-rows: 1fr;
22405          grid-auto-columns: auto;
22406        }
22407      "#,
22408      indoc! {r#"
22409        .foo {
22410          grid: auto-flow 1fr / auto 1fr auto;
22411        }
22412      "#},
22413    );
22414
22415    test(
22416      r#"
22417        .foo{
22418          grid-template-rows: none;
22419          grid-template-columns: auto 1fr auto;
22420          grid-template-areas: none;
22421          grid-auto-flow: row dense;
22422          grid-auto-rows: 1fr;
22423          grid-auto-columns: auto;
22424        }
22425      "#,
22426      indoc! {r#"
22427        .foo {
22428          grid: auto-flow dense 1fr / auto 1fr auto;
22429        }
22430      "#},
22431    );
22432
22433    test(
22434      r#"
22435        .foo{
22436          grid-template-rows: auto 1fr auto;
22437          grid-template-columns: none;
22438          grid-template-areas: none;
22439          grid-auto-flow: column;
22440          grid-auto-rows: auto;
22441          grid-auto-columns: 1fr;
22442        }
22443      "#,
22444      indoc! {r#"
22445        .foo {
22446          grid: auto 1fr auto / auto-flow 1fr;
22447        }
22448      "#},
22449    );
22450
22451    test(
22452      r#"
22453        .foo{
22454          grid-template-rows: auto 1fr auto;
22455          grid-template-columns: none;
22456          grid-template-areas: none;
22457          grid-auto-flow: column dense;
22458          grid-auto-rows: auto;
22459          grid-auto-columns: 1fr;
22460        }
22461      "#,
22462      indoc! {r#"
22463        .foo {
22464          grid: auto 1fr auto / auto-flow dense 1fr;
22465        }
22466      "#},
22467    );
22468
22469    test(
22470      r#"
22471        .foo{
22472          grid-template-rows: auto 1fr auto;
22473          grid-template-columns: none;
22474          grid-template-areas: none;
22475          grid-auto-flow: var(--auto-flow);
22476          grid-auto-rows: auto;
22477          grid-auto-columns: 1fr;
22478        }
22479      "#,
22480      indoc! {r#"
22481        .foo {
22482          grid-template: auto 1fr auto / none;
22483          grid-auto-flow: var(--auto-flow);
22484          grid-auto-rows: auto;
22485          grid-auto-columns: 1fr;
22486        }
22487      "#},
22488    );
22489
22490    test(
22491      r#"
22492        .foo{
22493          grid: auto 1fr auto / auto-flow dense 1fr;
22494          grid-template-rows: 1fr 1fr 1fr;
22495        }
22496      "#,
22497      indoc! {r#"
22498        .foo {
22499          grid: 1fr 1fr 1fr / auto-flow dense 1fr;
22500        }
22501      "#},
22502    );
22503
22504    test(
22505      r#"
22506        .foo{
22507          grid-row-start: a;
22508          grid-row-end: a;
22509          grid-column-start: a;
22510          grid-column-end: a;
22511        }
22512      "#,
22513      indoc! {r#"
22514        .foo {
22515          grid-area: a;
22516        }
22517      "#},
22518    );
22519
22520    test(
22521      r#"
22522        .foo{
22523          grid-row-start: 1;
22524          grid-row-end: 2;
22525          grid-column-start: 3;
22526          grid-column-end: 4;
22527        }
22528      "#,
22529      indoc! {r#"
22530        .foo {
22531          grid-area: 1 / 3 / 2 / 4;
22532        }
22533      "#},
22534    );
22535
22536    test(
22537      r#"
22538        .foo{
22539          grid-row-start: a;
22540          grid-row-end: a;
22541        }
22542      "#,
22543      indoc! {r#"
22544        .foo {
22545          grid-row: a;
22546        }
22547      "#},
22548    );
22549
22550    test(
22551      r#"
22552        .foo{
22553          grid-column-start: a;
22554          grid-column-end: a;
22555        }
22556      "#,
22557      indoc! {r#"
22558        .foo {
22559          grid-column: a;
22560        }
22561      "#},
22562    );
22563  }
22564
22565  #[test]
22566  fn test_moz_document() {
22567    minify_test(
22568      r#"
22569      @-moz-document url-prefix() {
22570        h1 {
22571          color: yellow;
22572        }
22573      }
22574    "#,
22575      "@-moz-document url-prefix(){h1{color:#ff0}}",
22576    );
22577    minify_test(
22578      r#"
22579      @-moz-document url-prefix("") {
22580        h1 {
22581          color: yellow;
22582        }
22583      }
22584    "#,
22585      "@-moz-document url-prefix(){h1{color:#ff0}}",
22586    );
22587    error_test(
22588      "@-moz-document url-prefix(foo) {}",
22589      ParserError::UnexpectedToken(crate::properties::custom::Token::Ident("foo".into())),
22590    );
22591    error_test(
22592      "@-moz-document url-prefix(\"foo\") {}",
22593      ParserError::UnexpectedToken(crate::properties::custom::Token::String("foo".into())),
22594    );
22595  }
22596
22597  #[test]
22598  fn test_custom_properties() {
22599    minify_test(".foo { --test: ; }", ".foo{--test: }");
22600    minify_test(".foo { --test:  ; }", ".foo{--test: }");
22601    minify_test(".foo { --test: foo; }", ".foo{--test:foo}");
22602    minify_test(".foo { --test:  foo; }", ".foo{--test:foo}");
22603    minify_test(".foo { --test: foo ; }", ".foo{--test:foo}");
22604    minify_test(".foo { --test: foo  ; }", ".foo{--test:foo}");
22605    minify_test(".foo { --test:foo; }", ".foo{--test:foo}");
22606    minify_test(".foo { --test:foo ; }", ".foo{--test:foo}");
22607    minify_test(".foo { --test: var(--foo, 20px); }", ".foo{--test:var(--foo,20px)}");
22608    minify_test(
22609      ".foo { transition: var(--foo, 20px),\nvar(--bar, 40px); }",
22610      ".foo{transition:var(--foo,20px),var(--bar,40px)}",
22611    );
22612    minify_test(
22613      ".foo { background: var(--color) var(--image); }",
22614      ".foo{background:var(--color)var(--image)}",
22615    );
22616    minify_test(
22617      ".foo { height: calc(var(--spectrum-global-dimension-size-300) / 2);",
22618      ".foo{height:calc(var(--spectrum-global-dimension-size-300)/2)}",
22619    );
22620    minify_test(
22621      ".foo { color: var(--color, rgb(255, 255, 0)); }",
22622      ".foo{color:var(--color,#ff0)}",
22623    );
22624    minify_test(
22625      ".foo { color: var(--color, #ffff00); }",
22626      ".foo{color:var(--color,#ff0)}",
22627    );
22628    minify_test(
22629      ".foo { color: var(--color, rgb(var(--red), var(--green), 0)); }",
22630      ".foo{color:var(--color,rgb(var(--red),var(--green),0))}",
22631    );
22632    minify_test(".foo { --test: .5s; }", ".foo{--test:.5s}");
22633    minify_test(".foo { --theme-sizes-1\\/12: 2 }", ".foo{--theme-sizes-1\\/12:2}");
22634    minify_test(".foo { --test: 0px; }", ".foo{--test:0px}");
22635
22636    prefix_test(
22637      r#"
22638      .foo {
22639        --custom: lab(40% 56.6 39);
22640      }
22641    "#,
22642      indoc! {r#"
22643      .foo {
22644        --custom: #b32323;
22645      }
22646
22647      @supports (color: lab(0% 0 0)) {
22648        .foo {
22649          --custom: lab(40% 56.6 39);
22650        }
22651      }
22652    "#},
22653      Browsers {
22654        chrome: Some(90 << 16),
22655        ..Browsers::default()
22656      },
22657    );
22658
22659    prefix_test(
22660      r#"
22661      @supports (color: lab(0% 0 0)) {
22662        .foo {
22663          --custom: lab(40% 56.6 39);
22664        }
22665      }
22666    "#,
22667      indoc! {r#"
22668      @supports (color: lab(0% 0 0)) {
22669        .foo {
22670          --custom: lab(40% 56.6 39);
22671        }
22672      }
22673    "#},
22674      Browsers {
22675        chrome: Some(90 << 16),
22676        ..Browsers::default()
22677      },
22678    );
22679
22680    prefix_test(
22681      r#"
22682      .foo {
22683        --custom: lab(40% 56.6 39) !important;
22684      }
22685    "#,
22686      indoc! {r#"
22687      .foo {
22688        --custom: #b32323 !important;
22689      }
22690
22691      @supports (color: lab(0% 0 0)) {
22692        .foo {
22693          --custom: lab(40% 56.6 39) !important;
22694        }
22695      }
22696    "#},
22697      Browsers {
22698        chrome: Some(90 << 16),
22699        ..Browsers::default()
22700      },
22701    );
22702
22703    prefix_test(
22704      r#"
22705      @supports (color: lab(0% 0 0)) {
22706        .foo {
22707          --custom: lab(40% 56.6 39) !important;
22708        }
22709      }
22710    "#,
22711      indoc! {r#"
22712      @supports (color: lab(0% 0 0)) {
22713        .foo {
22714          --custom: lab(40% 56.6 39) !important;
22715        }
22716      }
22717    "#},
22718      Browsers {
22719        chrome: Some(90 << 16),
22720        ..Browsers::default()
22721      },
22722    );
22723
22724    prefix_test(
22725      r#"
22726      .foo {
22727        --custom: lab(40% 56.6 39);
22728      }
22729    "#,
22730      indoc! {r#"
22731      .foo {
22732        --custom: #b32323;
22733      }
22734
22735      @supports (color: color(display-p3 0 0 0)) {
22736        .foo {
22737          --custom: color(display-p3 .643308 .192455 .167712);
22738        }
22739      }
22740
22741      @supports (color: lab(0% 0 0)) {
22742        .foo {
22743          --custom: lab(40% 56.6 39);
22744        }
22745      }
22746    "#},
22747      Browsers {
22748        chrome: Some(90 << 16),
22749        safari: Some(14 << 16),
22750        ..Browsers::default()
22751      },
22752    );
22753
22754    prefix_test(
22755      r#"
22756      @supports (color: color(display-p3 0 0 0)) {
22757        .foo {
22758          --custom: color(display-p3 .643308 .192455 .167712);
22759        }
22760      }
22761
22762      @supports (color: lab(0% 0 0)) {
22763        .foo {
22764          --custom: lab(40% 56.6 39);
22765        }
22766      }
22767    "#,
22768      indoc! {r#"
22769      @supports (color: color(display-p3 0 0 0)) {
22770        .foo {
22771          --custom: color(display-p3 .643308 .192455 .167712);
22772        }
22773      }
22774
22775      @supports (color: lab(0% 0 0)) {
22776        .foo {
22777          --custom: lab(40% 56.6 39);
22778        }
22779      }
22780    "#},
22781      Browsers {
22782        chrome: Some(90 << 16),
22783        safari: Some(14 << 16),
22784        ..Browsers::default()
22785      },
22786    );
22787
22788    prefix_test(
22789      r#"
22790      .foo {
22791        --custom: lab(40% 56.6 39);
22792      }
22793    "#,
22794      indoc! {r#"
22795      .foo {
22796        --custom: color(display-p3 .643308 .192455 .167712);
22797      }
22798
22799      @supports (color: lab(0% 0 0)) {
22800        .foo {
22801          --custom: lab(40% 56.6 39);
22802        }
22803      }
22804    "#},
22805      Browsers {
22806        safari: Some(14 << 16),
22807        ..Browsers::default()
22808      },
22809    );
22810
22811    prefix_test(
22812      r#"
22813      .foo {
22814        --custom: lab(40% 56.6 39);
22815      }
22816    "#,
22817      indoc! {r#"
22818      .foo {
22819        --custom: lab(40% 56.6 39);
22820      }
22821    "#},
22822      Browsers {
22823        safari: Some(15 << 16),
22824        ..Browsers::default()
22825      },
22826    );
22827
22828    prefix_test(
22829      r#"
22830      .foo {
22831        --custom: oklab(59.686% 0.1009 0.1192);
22832      }
22833    "#,
22834      indoc! {r#"
22835      .foo {
22836        --custom: lab(52.2319% 40.1449 59.9171);
22837      }
22838    "#},
22839      Browsers {
22840        safari: Some(15 << 16),
22841        ..Browsers::default()
22842      },
22843    );
22844
22845    prefix_test(
22846      r#"
22847      .foo {
22848        --custom: oklab(59.686% 0.1009 0.1192);
22849      }
22850    "#,
22851      indoc! {r#"
22852      .foo {
22853        --custom: color(display-p3 .724144 .386777 .148795);
22854      }
22855
22856      @supports (color: lab(0% 0 0)) {
22857        .foo {
22858          --custom: lab(52.2319% 40.1449 59.9171);
22859        }
22860      }
22861    "#},
22862      Browsers {
22863        safari: Some(14 << 16),
22864        ..Browsers::default()
22865      },
22866    );
22867
22868    prefix_test(
22869      r#"
22870      .foo {
22871        --custom: oklab(59.686% 0.1009 0.1192);
22872      }
22873    "#,
22874      indoc! {r#"
22875      .foo {
22876        --custom: #c65d07;
22877      }
22878
22879      @supports (color: color(display-p3 0 0 0)) {
22880        .foo {
22881          --custom: color(display-p3 .724144 .386777 .148795);
22882        }
22883      }
22884
22885      @supports (color: lab(0% 0 0)) {
22886        .foo {
22887          --custom: lab(52.2319% 40.1449 59.9171);
22888        }
22889      }
22890    "#},
22891      Browsers {
22892        safari: Some(14 << 16),
22893        chrome: Some(90 << 16),
22894        ..Browsers::default()
22895      },
22896    );
22897
22898    prefix_test(
22899      r#"
22900      .foo {
22901        --foo: oklab(59.686% 0.1009 0.1192);
22902        --bar: lab(40% 56.6 39);
22903      }
22904    "#,
22905      indoc! {r#"
22906      .foo {
22907        --foo: #c65d07;
22908        --bar: #b32323;
22909      }
22910
22911      @supports (color: color(display-p3 0 0 0)) {
22912        .foo {
22913          --foo: color(display-p3 .724144 .386777 .148795);
22914          --bar: color(display-p3 .643308 .192455 .167712);
22915        }
22916      }
22917
22918      @supports (color: lab(0% 0 0)) {
22919        .foo {
22920          --foo: lab(52.2319% 40.1449 59.9171);
22921          --bar: lab(40% 56.6 39);
22922        }
22923      }
22924    "#},
22925      Browsers {
22926        safari: Some(14 << 16),
22927        chrome: Some(90 << 16),
22928        ..Browsers::default()
22929      },
22930    );
22931
22932    prefix_test(
22933      r#"
22934      .foo {
22935        --foo: color(display-p3 0 1 0);
22936      }
22937    "#,
22938      indoc! {r#"
22939      .foo {
22940        --foo: #00f942;
22941      }
22942
22943      @supports (color: color(display-p3 0 0 0)) {
22944        .foo {
22945          --foo: color(display-p3 0 1 0);
22946        }
22947      }
22948    "#},
22949      Browsers {
22950        safari: Some(14 << 16),
22951        chrome: Some(90 << 16),
22952        ..Browsers::default()
22953      },
22954    );
22955
22956    prefix_test(
22957      r#"
22958      @supports (color: color(display-p3 0 0 0)) {
22959        .foo {
22960          --foo: color(display-p3 0 1 0);
22961        }
22962      }
22963    "#,
22964      indoc! {r#"
22965      @supports (color: color(display-p3 0 0 0)) {
22966        .foo {
22967          --foo: color(display-p3 0 1 0);
22968        }
22969      }
22970    "#},
22971      Browsers {
22972        safari: Some(14 << 16),
22973        chrome: Some(90 << 16),
22974        ..Browsers::default()
22975      },
22976    );
22977
22978    prefix_test(
22979      r#"
22980      .foo {
22981        --foo: color(display-p3 0 1 0);
22982      }
22983    "#,
22984      indoc! {r#"
22985      .foo {
22986        --foo: color(display-p3 0 1 0);
22987      }
22988    "#},
22989      Browsers {
22990        safari: Some(14 << 16),
22991        ..Browsers::default()
22992      },
22993    );
22994
22995    prefix_test(
22996      r#"
22997      .foo {
22998        --foo: color(display-p3 0 1 0);
22999      }
23000    "#,
23001      indoc! {r#"
23002      .foo {
23003        --foo: #00f942;
23004      }
23005
23006      @supports (color: color(display-p3 0 0 0)) {
23007        .foo {
23008          --foo: color(display-p3 0 1 0);
23009        }
23010      }
23011    "#},
23012      Browsers {
23013        safari: Some(15 << 16),
23014        chrome: Some(90 << 16),
23015        ..Browsers::default()
23016      },
23017    );
23018
23019    prefix_test(
23020      r#"
23021      .foo {
23022        --foo: color(display-p3 0 1 0);
23023      }
23024    "#,
23025      indoc! {r#"
23026      .foo {
23027        --foo: #00f942;
23028      }
23029
23030      @supports (color: color(display-p3 0 0 0)) {
23031        .foo {
23032          --foo: color(display-p3 0 1 0);
23033        }
23034      }
23035    "#},
23036      Browsers {
23037        chrome: Some(90 << 16),
23038        ..Browsers::default()
23039      },
23040    );
23041
23042    prefix_test(
23043      r#"
23044      .foo {
23045        text-decoration: underline;
23046      }
23047
23048      .foo {
23049        --custom: lab(40% 56.6 39);
23050      }
23051    "#,
23052      indoc! {r#"
23053      .foo {
23054        --custom: #b32323;
23055        text-decoration: underline;
23056      }
23057
23058      @supports (color: lab(0% 0 0)) {
23059        .foo {
23060          --custom: lab(40% 56.6 39);
23061        }
23062      }
23063    "#},
23064      Browsers {
23065        chrome: Some(90 << 16),
23066        ..Browsers::default()
23067      },
23068    );
23069
23070    prefix_test(
23071      r#"
23072      .foo {
23073        --custom: lab(40% 56.6 39);
23074      }
23075
23076      .foo {
23077        text-decoration: underline;
23078      }
23079    "#,
23080      indoc! {r#"
23081      .foo {
23082        --custom: #b32323;
23083      }
23084
23085      @supports (color: lab(0% 0 0)) {
23086        .foo {
23087          --custom: lab(40% 56.6 39);
23088        }
23089      }
23090
23091      .foo {
23092        text-decoration: underline;
23093      }
23094    "#},
23095      Browsers {
23096        chrome: Some(90 << 16),
23097        ..Browsers::default()
23098      },
23099    );
23100
23101    prefix_test(
23102      r#"
23103      @keyframes foo {
23104        from {
23105          --custom: lab(40% 56.6 39);
23106        }
23107
23108        to {
23109          --custom: lch(50.998% 135.363 338);
23110        }
23111      }
23112    "#,
23113      indoc! {r#"
23114      @keyframes foo {
23115        from {
23116          --custom: #b32323;
23117        }
23118
23119        to {
23120          --custom: #ee00be;
23121        }
23122      }
23123
23124      @supports (color: lab(0% 0 0)) {
23125        @keyframes foo {
23126          from {
23127            --custom: lab(40% 56.6 39);
23128          }
23129
23130          to {
23131            --custom: lab(50.998% 125.506 -50.7078);
23132          }
23133        }
23134      }
23135    "#},
23136      Browsers {
23137        chrome: Some(90 << 16),
23138        ..Browsers::default()
23139      },
23140    );
23141
23142    prefix_test(
23143      r#"
23144      @supports (color: lab(0% 0 0)) {
23145        @keyframes foo {
23146          from {
23147            --custom: lab(40% 56.6 39);
23148          }
23149
23150          to {
23151            --custom: lab(50.998% 125.506 -50.7078);
23152          }
23153        }
23154      }
23155    "#,
23156      indoc! {r#"
23157      @supports (color: lab(0% 0 0)) {
23158        @keyframes foo {
23159          from {
23160            --custom: lab(40% 56.6 39);
23161          }
23162
23163          to {
23164            --custom: lab(50.998% 125.506 -50.7078);
23165          }
23166        }
23167      }
23168    "#},
23169      Browsers {
23170        chrome: Some(90 << 16),
23171        ..Browsers::default()
23172      },
23173    );
23174
23175    prefix_test(
23176      r#"
23177      @keyframes foo {
23178        from {
23179          --custom: lab(40% 56.6 39);
23180        }
23181
23182        to {
23183          --custom: lch(50.998% 135.363 338);
23184        }
23185      }
23186    "#,
23187      indoc! {r#"
23188      @keyframes foo {
23189        from {
23190          --custom: #b32323;
23191        }
23192
23193        to {
23194          --custom: #ee00be;
23195        }
23196      }
23197
23198      @supports (color: color(display-p3 0 0 0)) {
23199        @keyframes foo {
23200          from {
23201            --custom: color(display-p3 .643308 .192455 .167712);
23202          }
23203
23204          to {
23205            --custom: color(display-p3 .972962 -.362078 .804206);
23206          }
23207        }
23208      }
23209
23210      @supports (color: lab(0% 0 0)) {
23211        @keyframes foo {
23212          from {
23213            --custom: lab(40% 56.6 39);
23214          }
23215
23216          to {
23217            --custom: lab(50.998% 125.506 -50.7078);
23218          }
23219        }
23220      }
23221    "#},
23222      Browsers {
23223        chrome: Some(90 << 16),
23224        safari: Some(14 << 16),
23225        ..Browsers::default()
23226      },
23227    );
23228
23229    prefix_test(
23230      r#"
23231      @supports (color: color(display-p3 0 0 0)) {
23232        @keyframes foo {
23233          from {
23234            --custom: color(display-p3 .643308 .192455 .167712);
23235          }
23236
23237          to {
23238            --custom: color(display-p3 .972962 -.362078 .804206);
23239          }
23240        }
23241      }
23242
23243      @supports (color: lab(0% 0 0)) {
23244        @keyframes foo {
23245          from {
23246            --custom: lab(40% 56.6 39);
23247          }
23248
23249          to {
23250            --custom: lab(50.998% 125.506 -50.7078);
23251          }
23252        }
23253      }
23254    "#,
23255      indoc! {r#"
23256      @supports (color: color(display-p3 0 0 0)) {
23257        @keyframes foo {
23258          from {
23259            --custom: color(display-p3 .643308 .192455 .167712);
23260          }
23261
23262          to {
23263            --custom: color(display-p3 .972962 -.362078 .804206);
23264          }
23265        }
23266      }
23267
23268      @supports (color: lab(0% 0 0)) {
23269        @keyframes foo {
23270          from {
23271            --custom: lab(40% 56.6 39);
23272          }
23273
23274          to {
23275            --custom: lab(50.998% 125.506 -50.7078);
23276          }
23277        }
23278      }
23279    "#},
23280      Browsers {
23281        chrome: Some(90 << 16),
23282        safari: Some(14 << 16),
23283        ..Browsers::default()
23284      },
23285    );
23286
23287    prefix_test(
23288      r#"
23289      @keyframes foo {
23290        from {
23291          --custom: #ff0;
23292          opacity: 0;
23293        }
23294
23295        to {
23296          --custom: lch(50.998% 135.363 338);
23297          opacity: 1;
23298        }
23299      }
23300    "#,
23301      indoc! {r#"
23302      @keyframes foo {
23303        from {
23304          --custom: #ff0;
23305          opacity: 0;
23306        }
23307
23308        to {
23309          --custom: #ee00be;
23310          opacity: 1;
23311        }
23312      }
23313
23314      @supports (color: lab(0% 0 0)) {
23315        @keyframes foo {
23316          from {
23317            --custom: #ff0;
23318            opacity: 0;
23319          }
23320
23321          to {
23322            --custom: lab(50.998% 125.506 -50.7078);
23323            opacity: 1;
23324          }
23325        }
23326      }
23327    "#},
23328      Browsers {
23329        chrome: Some(90 << 16),
23330        ..Browsers::default()
23331      },
23332    );
23333
23334    prefix_test(
23335      r#"
23336      @keyframes foo {
23337        from {
23338          text-decoration: var(--foo) lab(29.2345% 39.3825 20.0664);
23339        }
23340      }
23341    "#,
23342      indoc! {r#"
23343      @keyframes foo {
23344        from {
23345          text-decoration: var(--foo) #7d2329;
23346        }
23347      }
23348
23349      @supports (color: lab(0% 0 0)) {
23350        @keyframes foo {
23351          from {
23352            text-decoration: var(--foo) lab(29.2345% 39.3825 20.0664);
23353          }
23354        }
23355      }
23356    "#},
23357      Browsers {
23358        chrome: Some(90 << 16),
23359        ..Browsers::default()
23360      },
23361    );
23362  }
23363
23364  #[test]
23365  fn test_charset() {
23366    test(
23367      r#"
23368      @charset "UTF-8";
23369
23370      .foo {
23371        color: red;
23372      }
23373
23374      @charset "UTF-8";
23375
23376      .bar {
23377        color: yellow;
23378      }
23379    "#,
23380      indoc! { r#"
23381      .foo {
23382        color: red;
23383      }
23384
23385      .bar {
23386        color: #ff0;
23387      }
23388    "#},
23389    )
23390  }
23391
23392  #[test]
23393  fn test_style_attr() {
23394    attr_test("color: yellow; flex: 1 1 auto", "color: #ff0; flex: auto", false, None);
23395    attr_test("color: yellow; flex: 1 1 auto", "color:#ff0;flex:auto", true, None);
23396    attr_test(
23397      "border-inline-start: 2px solid red",
23398      "border-inline-start: 2px solid red",
23399      false,
23400      Some(Browsers {
23401        safari: Some(12 << 16),
23402        ..Browsers::default()
23403      }),
23404    );
23405    attr_test(
23406      "color: lab(40% 56.6 39);",
23407      "color:#b32323;color:lab(40% 56.6 39)",
23408      true,
23409      Some(Browsers {
23410        safari: Some(8 << 16),
23411        ..Browsers::default()
23412      }),
23413    );
23414    attr_test(
23415      "--foo: lab(40% 56.6 39);",
23416      "--foo:#b32323",
23417      true,
23418      Some(Browsers {
23419        safari: Some(8 << 16),
23420        ..Browsers::default()
23421      }),
23422    );
23423    attr_test(
23424      "text-decoration: var(--foo) lab(40% 56.6 39);",
23425      "text-decoration:var(--foo)#b32323",
23426      true,
23427      Some(Browsers {
23428        chrome: Some(90 << 16),
23429        ..Browsers::default()
23430      }),
23431    );
23432  }
23433
23434  #[test]
23435  fn test_nesting() {
23436    nesting_test(
23437      r#"
23438        .foo {
23439          color: blue;
23440          & > .bar { color: red; }
23441        }
23442      "#,
23443      indoc! {r#"
23444        .foo {
23445          color: #00f;
23446        }
23447
23448        .foo > .bar {
23449          color: red;
23450        }
23451      "#},
23452    );
23453
23454    nesting_test(
23455      r#"
23456        .foo {
23457          color: blue;
23458          &.bar { color: red; }
23459        }
23460      "#,
23461      indoc! {r#"
23462        .foo {
23463          color: #00f;
23464        }
23465
23466        .foo.bar {
23467          color: red;
23468        }
23469      "#},
23470    );
23471
23472    nesting_test(
23473      r#"
23474        .foo, .bar {
23475          color: blue;
23476          & + .baz, &.qux { color: red; }
23477        }
23478      "#,
23479      indoc! {r#"
23480        .foo, .bar {
23481          color: #00f;
23482        }
23483
23484        :is(.foo, .bar) + .baz, :is(.foo, .bar).qux {
23485          color: red;
23486        }
23487      "#},
23488    );
23489
23490    nesting_test(
23491      r#"
23492        .foo {
23493          color: blue;
23494          & .bar & .baz & .qux { color: red; }
23495        }
23496      "#,
23497      indoc! {r#"
23498        .foo {
23499          color: #00f;
23500        }
23501
23502        .foo .bar .foo .baz .foo .qux {
23503          color: red;
23504        }
23505      "#},
23506    );
23507
23508    nesting_test(
23509      r#"
23510        .foo {
23511          color: blue;
23512          & { padding: 2ch; }
23513        }
23514      "#,
23515      indoc! {r#"
23516        .foo {
23517          color: #00f;
23518        }
23519
23520        .foo {
23521          padding: 2ch;
23522        }
23523      "#},
23524    );
23525
23526    nesting_test(
23527      r#"
23528        .foo {
23529          color: blue;
23530          && { padding: 2ch; }
23531        }
23532      "#,
23533      indoc! {r#"
23534        .foo {
23535          color: #00f;
23536        }
23537
23538        .foo.foo {
23539          padding: 2ch;
23540        }
23541      "#},
23542    );
23543
23544    nesting_test(
23545      r#"
23546        .error, .invalid {
23547          &:hover > .baz { color: red; }
23548        }
23549      "#,
23550      indoc! {r#"
23551        :is(.error, .invalid):hover > .baz {
23552          color: red;
23553        }
23554      "#},
23555    );
23556
23557    nesting_test(
23558      r#"
23559        .foo {
23560          &:is(.bar, &.baz) { color: red; }
23561        }
23562      "#,
23563      indoc! {r#"
23564        .foo:is(.bar, .foo.baz) {
23565          color: red;
23566        }
23567      "#},
23568    );
23569
23570    nesting_test(
23571      r#"
23572        figure {
23573          margin: 0;
23574
23575          & > figcaption {
23576            background: hsl(0 0% 0% / 50%);
23577
23578            & > p {
23579              font-size: .9rem;
23580            }
23581          }
23582        }
23583      "#,
23584      indoc! {r#"
23585        figure {
23586          margin: 0;
23587        }
23588
23589        figure > figcaption {
23590          background: #00000080;
23591        }
23592
23593        figure > figcaption > p {
23594          font-size: .9rem;
23595        }
23596      "#},
23597    );
23598
23599    nesting_test(
23600      r#"
23601        .foo {
23602          display: grid;
23603
23604          @media (orientation: landscape) {
23605            grid-auto-flow: column;
23606          }
23607        }
23608      "#,
23609      indoc! {r#"
23610        .foo {
23611          display: grid;
23612        }
23613
23614        @media (orientation: landscape) {
23615          .foo {
23616            grid-auto-flow: column;
23617          }
23618        }
23619      "#},
23620    );
23621
23622    nesting_test(
23623      r#"
23624        .foo {
23625          display: grid;
23626
23627          @media (orientation: landscape) {
23628            grid-auto-flow: column;
23629
23630            @media (width > 1024px) {
23631              max-inline-size: 1024px;
23632            }
23633          }
23634        }
23635      "#,
23636      indoc! {r#"
23637        .foo {
23638          display: grid;
23639        }
23640
23641        @media (orientation: landscape) {
23642          .foo {
23643            grid-auto-flow: column;
23644          }
23645
23646          @media not (max-width: 1024px) {
23647            .foo {
23648              max-inline-size: 1024px;
23649            }
23650          }
23651        }
23652      "#},
23653    );
23654
23655    nesting_test(
23656      r#"
23657        .foo {
23658          @media (min-width: 640px) {
23659            color: red !important;
23660          }
23661        }
23662      "#,
23663      indoc! {r#"
23664        @media (min-width: 640px) {
23665          .foo {
23666            color: red !important;
23667          }
23668        }
23669      "#},
23670    );
23671
23672    nesting_test(
23673      r#"
23674        .foo {
23675          display: grid;
23676
23677          @supports (foo: bar) {
23678            grid-auto-flow: column;
23679          }
23680        }
23681      "#,
23682      indoc! {r#"
23683        .foo {
23684          display: grid;
23685        }
23686
23687        @supports (foo: bar) {
23688          .foo {
23689            grid-auto-flow: column;
23690          }
23691        }
23692      "#},
23693    );
23694
23695    nesting_test(
23696      r#"
23697        .foo {
23698          display: grid;
23699
23700          @container (min-width: 100px) {
23701            grid-auto-flow: column;
23702          }
23703        }
23704      "#,
23705      indoc! {r#"
23706        .foo {
23707          display: grid;
23708        }
23709
23710        @container (width >= 100px) {
23711          .foo {
23712            grid-auto-flow: column;
23713          }
23714        }
23715      "#},
23716    );
23717
23718    nesting_test(
23719      r#"
23720        .foo {
23721          display: grid;
23722
23723          @layer test {
23724            grid-auto-flow: column;
23725          }
23726        }
23727      "#,
23728      indoc! {r#"
23729        .foo {
23730          display: grid;
23731        }
23732
23733        @layer test {
23734          .foo {
23735            grid-auto-flow: column;
23736          }
23737        }
23738      "#},
23739    );
23740
23741    nesting_test(
23742      r#"
23743        .foo {
23744          display: grid;
23745
23746          @layer {
23747            grid-auto-flow: column;
23748          }
23749        }
23750      "#,
23751      indoc! {r#"
23752        .foo {
23753          display: grid;
23754        }
23755
23756        @layer {
23757          .foo {
23758            grid-auto-flow: column;
23759          }
23760        }
23761      "#},
23762    );
23763
23764    nesting_test(
23765      r#"
23766        @namespace "http://example.com/foo";
23767        @namespace toto "http://toto.example.org";
23768
23769        .foo {
23770          &div {
23771            color: red;
23772          }
23773
23774          &* {
23775            color: green;
23776          }
23777
23778          &|x {
23779            color: red;
23780          }
23781
23782          &*|x {
23783            color: green;
23784          }
23785
23786          &toto|x {
23787            color: red;
23788          }
23789        }
23790      "#,
23791      indoc! {r#"
23792        @namespace "http://example.com/foo";
23793        @namespace toto "http://toto.example.org";
23794
23795        div.foo {
23796          color: red;
23797        }
23798
23799        *.foo {
23800          color: green;
23801        }
23802
23803        |x.foo {
23804          color: red;
23805        }
23806
23807        *|x.foo {
23808          color: green;
23809        }
23810
23811        toto|x.foo {
23812          color: red;
23813        }
23814      "#},
23815    );
23816
23817    nesting_test(
23818      r#"
23819        .foo {
23820          &article > figure {
23821            color: red;
23822          }
23823        }
23824      "#,
23825      indoc! {r#"
23826        article.foo > figure {
23827          color: red;
23828        }
23829      "#},
23830    );
23831
23832    nesting_test(
23833      r#"
23834        div {
23835          &.bar {
23836            background: green;
23837          }
23838        }
23839      "#,
23840      indoc! {r#"
23841        div.bar {
23842          background: green;
23843        }
23844      "#},
23845    );
23846
23847    nesting_test(
23848      r#"
23849        div > .foo {
23850          &span {
23851            background: green;
23852          }
23853        }
23854      "#,
23855      indoc! {r#"
23856        span:is(div > .foo) {
23857          background: green;
23858        }
23859      "#},
23860    );
23861
23862    nesting_test(
23863      r#"
23864        .foo {
23865          & h1 {
23866            background: green;
23867          }
23868        }
23869      "#,
23870      indoc! {r#"
23871        .foo h1 {
23872          background: green;
23873        }
23874      "#},
23875    );
23876
23877    nesting_test(
23878      r#"
23879        .foo .bar {
23880          &h1 {
23881            background: green;
23882          }
23883        }
23884      "#,
23885      indoc! {r#"
23886        h1:is(.foo .bar) {
23887          background: green;
23888        }
23889      "#},
23890    );
23891
23892    nesting_test(
23893      r#"
23894        .foo.bar {
23895          &h1 {
23896            background: green;
23897          }
23898        }
23899      "#,
23900      indoc! {r#"
23901        h1.foo.bar {
23902          background: green;
23903        }
23904      "#},
23905    );
23906
23907    nesting_test(
23908      r#"
23909        .foo .bar {
23910          &h1 .baz {
23911            background: green;
23912          }
23913        }
23914      "#,
23915      indoc! {r#"
23916        h1:is(.foo .bar) .baz {
23917          background: green;
23918        }
23919      "#},
23920    );
23921
23922    nesting_test(
23923      r#"
23924        .foo .bar {
23925          &.baz {
23926            background: green;
23927          }
23928        }
23929      "#,
23930      indoc! {r#"
23931        .foo .bar.baz {
23932          background: green;
23933        }
23934      "#},
23935    );
23936
23937    nesting_test(
23938      r#"
23939        .foo {
23940          color: red;
23941          @nest .parent & {
23942            color: blue;
23943          }
23944        }
23945      "#,
23946      indoc! {r#"
23947        .foo {
23948          color: red;
23949        }
23950
23951        .parent .foo {
23952          color: #00f;
23953        }
23954      "#},
23955    );
23956
23957    nesting_test(
23958      r#"
23959        .foo {
23960          color: red;
23961          @nest :not(&) {
23962            color: blue;
23963          }
23964        }
23965      "#,
23966      indoc! {r#"
23967        .foo {
23968          color: red;
23969        }
23970
23971        :not(.foo) {
23972          color: #00f;
23973        }
23974      "#},
23975    );
23976
23977    nesting_test(
23978      r#"
23979        .foo {
23980          color: blue;
23981          @nest .bar & {
23982            color: red;
23983            &.baz {
23984              color: green;
23985            }
23986          }
23987        }
23988      "#,
23989      indoc! {r#"
23990        .foo {
23991          color: #00f;
23992        }
23993
23994        .bar .foo {
23995          color: red;
23996        }
23997
23998        .bar .foo.baz {
23999          color: green;
24000        }
24001      "#},
24002    );
24003
24004    nesting_test(
24005      r#"
24006        .foo {
24007          @nest :not(&) {
24008            color: red;
24009          }
24010
24011          & h1 {
24012            background: green;
24013          }
24014        }
24015      "#,
24016      indoc! {r#"
24017        :not(.foo) {
24018          color: red;
24019        }
24020
24021        .foo h1 {
24022          background: green;
24023        }
24024      "#},
24025    );
24026
24027    nesting_test(
24028      r#"
24029        .foo {
24030          & h1 {
24031            background: green;
24032          }
24033
24034          @nest :not(&) {
24035            color: red;
24036          }
24037        }
24038      "#,
24039      indoc! {r#"
24040        .foo h1 {
24041          background: green;
24042        }
24043
24044        :not(.foo) {
24045          color: red;
24046        }
24047      "#},
24048    );
24049
24050    nesting_test(
24051      r#"
24052        .foo .bar {
24053          @nest h1& {
24054            background: green;
24055          }
24056        }
24057      "#,
24058      indoc! {r#"
24059        h1:is(.foo .bar) {
24060          background: green;
24061        }
24062      "#},
24063    );
24064
24065    nesting_test(
24066      r#"
24067        @namespace "http://example.com/foo";
24068        @namespace toto "http://toto.example.org";
24069
24070        div {
24071          @nest .foo& {
24072            color: red;
24073          }
24074        }
24075
24076        * {
24077          @nest .foo& {
24078            color: red;
24079          }
24080        }
24081
24082        |x {
24083          @nest .foo& {
24084            color: red;
24085          }
24086        }
24087
24088        *|x {
24089          @nest .foo& {
24090            color: red;
24091          }
24092        }
24093
24094        toto|x {
24095          @nest .foo& {
24096            color: red;
24097          }
24098        }
24099      "#,
24100      indoc! {r#"
24101        @namespace "http://example.com/foo";
24102        @namespace toto "http://toto.example.org";
24103
24104        .foo:is(div) {
24105          color: red;
24106        }
24107
24108        .foo:is(*) {
24109          color: red;
24110        }
24111
24112        .foo:is(|x) {
24113          color: red;
24114        }
24115
24116        .foo:is(*|x) {
24117          color: red;
24118        }
24119
24120        .foo:is(toto|x) {
24121          color: red;
24122        }
24123      "#},
24124    );
24125
24126    nesting_test(
24127      r#"
24128        .foo .bar {
24129          @nest h1 .baz& {
24130            background: green;
24131          }
24132        }
24133      "#,
24134      indoc! {r#"
24135        h1 .baz:is(.foo .bar) {
24136          background: green;
24137        }
24138      "#},
24139    );
24140
24141    nesting_test(
24142      r#"
24143        .foo .bar {
24144          @nest .baz& {
24145            background: green;
24146          }
24147        }
24148      "#,
24149      indoc! {r#"
24150        .baz:is(.foo .bar) {
24151          background: green;
24152        }
24153      "#},
24154    );
24155
24156    nesting_test(
24157      r#"
24158        .foo .bar {
24159          @nest .baz & {
24160            background: green;
24161          }
24162        }
24163      "#,
24164      indoc! {r#"
24165        .baz :is(.foo .bar) {
24166          background: green;
24167        }
24168      "#},
24169    );
24170
24171    nesting_test(
24172      r#"
24173        .foo {
24174          color: red;
24175          @nest & > .bar {
24176            color: blue;
24177          }
24178        }
24179      "#,
24180      indoc! {r#"
24181        .foo {
24182          color: red;
24183        }
24184
24185        .foo > .bar {
24186          color: #00f;
24187        }
24188      "#},
24189    );
24190
24191    nesting_test(
24192      r#"
24193      .foo {
24194        color: red;
24195        .bar {
24196          color: blue;
24197        }
24198      }
24199      "#,
24200      indoc! {r#"
24201      .foo {
24202        color: red;
24203      }
24204
24205      .foo .bar {
24206        color: #00f;
24207      }
24208      "#},
24209    );
24210
24211    nesting_test(
24212      r#"
24213      .foo {
24214        color: red;
24215        .bar & {
24216          color: blue;
24217        }
24218      }
24219      "#,
24220      indoc! {r#"
24221      .foo {
24222        color: red;
24223      }
24224
24225      .bar .foo {
24226        color: #00f;
24227      }
24228      "#},
24229    );
24230
24231    nesting_test(
24232      r#"
24233      .foo {
24234        color: red;
24235        + .bar + & { color: blue; }
24236      }
24237      "#,
24238      indoc! {r#"
24239      .foo {
24240        color: red;
24241      }
24242
24243      .foo + .bar + .foo {
24244        color: #00f;
24245      }
24246      "#},
24247    );
24248
24249    nesting_test(
24250      r#"
24251      .foo {
24252        color: red;
24253        .bar & {
24254          color: blue;
24255        }
24256      }
24257      "#,
24258      indoc! {r#"
24259      .foo {
24260        color: red;
24261      }
24262
24263      .bar .foo {
24264        color: #00f;
24265      }
24266      "#},
24267    );
24268
24269    nesting_test(
24270      r#"
24271        .foo {
24272          color: red;
24273          .parent & {
24274            color: blue;
24275          }
24276        }
24277      "#,
24278      indoc! {r#"
24279        .foo {
24280          color: red;
24281        }
24282
24283        .parent .foo {
24284          color: #00f;
24285        }
24286      "#},
24287    );
24288
24289    nesting_test(
24290      r#"
24291        .foo {
24292          color: red;
24293          :not(&) {
24294            color: blue;
24295          }
24296        }
24297      "#,
24298      indoc! {r#"
24299        .foo {
24300          color: red;
24301        }
24302
24303        :not(.foo) {
24304          color: #00f;
24305        }
24306      "#},
24307    );
24308
24309    nesting_test(
24310      r#"
24311        .foo {
24312          color: blue;
24313          .bar & {
24314            color: red;
24315            &.baz {
24316              color: green;
24317            }
24318          }
24319        }
24320      "#,
24321      indoc! {r#"
24322        .foo {
24323          color: #00f;
24324        }
24325
24326        .bar .foo {
24327          color: red;
24328        }
24329
24330        .bar .foo.baz {
24331          color: green;
24332        }
24333      "#},
24334    );
24335
24336    nesting_test(
24337      r#"
24338        .foo {
24339          :not(&) {
24340            color: red;
24341          }
24342
24343          & h1 {
24344            background: green;
24345          }
24346        }
24347      "#,
24348      indoc! {r#"
24349        :not(.foo) {
24350          color: red;
24351        }
24352
24353        .foo h1 {
24354          background: green;
24355        }
24356      "#},
24357    );
24358
24359    nesting_test(
24360      r#"
24361        .foo {
24362          & h1 {
24363            background: green;
24364          }
24365
24366          :not(&) {
24367            color: red;
24368          }
24369        }
24370      "#,
24371      indoc! {r#"
24372        .foo h1 {
24373          background: green;
24374        }
24375
24376        :not(.foo) {
24377          color: red;
24378        }
24379      "#},
24380    );
24381
24382    nesting_test(
24383      r#"
24384        .foo .bar {
24385          :is(h1)& {
24386            background: green;
24387          }
24388        }
24389      "#,
24390      indoc! {r#"
24391        :is(h1):is(.foo .bar) {
24392          background: green;
24393        }
24394      "#},
24395    );
24396
24397    nesting_test(
24398      r#"
24399        @namespace "http://example.com/foo";
24400        @namespace toto "http://toto.example.org";
24401
24402        div {
24403          .foo& {
24404            color: red;
24405          }
24406        }
24407
24408        * {
24409          .foo& {
24410            color: red;
24411          }
24412        }
24413
24414        |x {
24415          .foo& {
24416            color: red;
24417          }
24418        }
24419
24420        *|x {
24421          .foo& {
24422            color: red;
24423          }
24424        }
24425
24426        toto|x {
24427          .foo& {
24428            color: red;
24429          }
24430        }
24431      "#,
24432      indoc! {r#"
24433        @namespace "http://example.com/foo";
24434        @namespace toto "http://toto.example.org";
24435
24436        .foo:is(div) {
24437          color: red;
24438        }
24439
24440        .foo:is(*) {
24441          color: red;
24442        }
24443
24444        .foo:is(|x) {
24445          color: red;
24446        }
24447
24448        .foo:is(*|x) {
24449          color: red;
24450        }
24451
24452        .foo:is(toto|x) {
24453          color: red;
24454        }
24455      "#},
24456    );
24457
24458    nesting_test(
24459      r#"
24460        .foo .bar {
24461          :is(h1) .baz& {
24462            background: green;
24463          }
24464        }
24465      "#,
24466      indoc! {r#"
24467        :is(h1) .baz:is(.foo .bar) {
24468          background: green;
24469        }
24470      "#},
24471    );
24472
24473    nesting_test(
24474      r#"
24475        .foo .bar {
24476          .baz& {
24477            background: green;
24478          }
24479        }
24480      "#,
24481      indoc! {r#"
24482        .baz:is(.foo .bar) {
24483          background: green;
24484        }
24485      "#},
24486    );
24487
24488    nesting_test(
24489      r#"
24490        .foo .bar {
24491          .baz & {
24492            background: green;
24493          }
24494        }
24495      "#,
24496      indoc! {r#"
24497        .baz :is(.foo .bar) {
24498          background: green;
24499        }
24500      "#},
24501    );
24502
24503    nesting_test(
24504      r#"
24505        .foo {
24506          .bar {
24507            color: blue;
24508          }
24509          color: red;
24510        }
24511      "#,
24512      indoc! {r#"
24513        .foo .bar {
24514          color: #00f;
24515        }
24516
24517        .foo {
24518          color: red;
24519        }
24520      "#},
24521    );
24522
24523    nesting_test(
24524      r#"
24525        article {
24526          color: green;
24527          & { color: blue; }
24528          color: red;
24529        }
24530      "#,
24531      indoc! {r#"
24532        article {
24533          color: green;
24534        }
24535
24536        article {
24537          color: #00f;
24538        }
24539
24540        article {
24541          color: red;
24542        }
24543      "#},
24544    );
24545
24546    nesting_test(
24547      r#"
24548        & .foo {
24549          color: red;
24550        }
24551      "#,
24552      indoc! {r#"
24553        :scope .foo {
24554          color: red;
24555        }
24556      "#},
24557    );
24558
24559    nesting_test(
24560      r#"
24561        &.foo {
24562          color: red;
24563        }
24564      "#,
24565      indoc! {r#"
24566        :scope.foo {
24567          color: red;
24568        }
24569      "#},
24570    );
24571
24572    nesting_test(
24573      r#"
24574        .foo& {
24575          color: red;
24576        }
24577      "#,
24578      indoc! {r#"
24579        .foo:scope {
24580          color: red;
24581        }
24582      "#},
24583    );
24584
24585    nesting_test(
24586      r#"
24587        &html {
24588          color: red;
24589        }
24590      "#,
24591      indoc! {r#"
24592        html:scope {
24593          color: red;
24594        }
24595      "#},
24596    );
24597
24598    nesting_test(
24599      r#"
24600        .foo {
24601          color: blue;
24602          div {
24603            color: red;
24604          }
24605        }
24606      "#,
24607      indoc! {r#"
24608        .foo {
24609          color: #00f;
24610        }
24611
24612        .foo div {
24613          color: red;
24614        }
24615      "#},
24616    );
24617
24618    nesting_test(
24619      r#"
24620        div {
24621          color: blue;
24622
24623          button:focus {
24624            color: red;
24625          }
24626        }
24627      "#,
24628      indoc! {r#"
24629        div {
24630          color: #00f;
24631        }
24632
24633        div button:focus {
24634          color: red;
24635        }
24636      "#},
24637    );
24638    nesting_test(
24639      r#"
24640        div {
24641          color: blue;
24642
24643          --button:focus {
24644            color: red;
24645          }
24646        }
24647      "#,
24648      indoc! {r#"
24649        div {
24650          color: #00f;
24651          --button: focus { color: red; };
24652        }
24653      "#},
24654    );
24655    nesting_test(
24656      r#"
24657      .foo {
24658        &::before, &::after {
24659          background: blue;
24660          @media screen {
24661            background: orange;
24662          }
24663        }
24664      }
24665      "#,
24666      indoc! {r#"
24667      .foo:before, .foo:after {
24668        background: #00f;
24669      }
24670
24671      @media screen {
24672        .foo:before, .foo:after {
24673          background: orange;
24674        }
24675      }
24676      "#},
24677    );
24678
24679    nesting_test_no_targets(
24680      r#"
24681        .foo {
24682          color: blue;
24683          @nest .bar & {
24684            color: red;
24685            &.baz {
24686              color: green;
24687            }
24688          }
24689        }
24690      "#,
24691      indoc! {r#"
24692        .foo {
24693          color: #00f;
24694
24695          @nest .bar & {
24696            color: red;
24697
24698            &.baz {
24699              color: green;
24700            }
24701          }
24702        }
24703      "#},
24704    );
24705
24706    nesting_test_no_targets(
24707      r#"
24708        .foo {
24709          color: blue;
24710          &div {
24711            color: red;
24712          }
24713
24714          &span {
24715            color: purple;
24716          }
24717        }
24718      "#,
24719      indoc! {r#"
24720        .foo {
24721          color: #00f;
24722
24723          &div {
24724            color: red;
24725          }
24726
24727          &span {
24728            color: purple;
24729          }
24730        }
24731      "#},
24732    );
24733
24734    nesting_test_no_targets(
24735      r#"
24736        .error, .invalid {
24737          &:hover > .baz { color: red; }
24738        }
24739      "#,
24740      indoc! {r#"
24741        .error, .invalid {
24742          &:hover > .baz {
24743            color: red;
24744          }
24745        }
24746      "#},
24747    );
24748
24749    nesting_test_with_targets(
24750      r#"
24751        .foo {
24752          color: blue;
24753          & > .bar { color: red; }
24754        }
24755      "#,
24756      indoc! {r#"
24757        .foo {
24758          color: #00f;
24759        }
24760
24761        .foo > .bar {
24762          color: red;
24763        }
24764      "#},
24765      Targets {
24766        browsers: Some(Browsers {
24767          chrome: Some(112 << 16),
24768          ..Browsers::default()
24769        }),
24770        include: Features::Nesting,
24771        exclude: Features::empty(),
24772      },
24773    );
24774    nesting_test_with_targets(
24775      r#"
24776        .foo {
24777          color: blue;
24778          & > .bar { color: red; }
24779        }
24780      "#,
24781      indoc! {r#"
24782        .foo {
24783          color: #00f;
24784
24785          & > .bar {
24786            color: red;
24787          }
24788        }
24789      "#},
24790      Targets {
24791        browsers: Some(Browsers {
24792          chrome: Some(50 << 16),
24793          ..Browsers::default()
24794        }),
24795        include: Features::empty(),
24796        exclude: Features::Nesting,
24797      },
24798    );
24799
24800    let mut stylesheet = StyleSheet::parse(
24801      r#"
24802      .foo {
24803        color: blue;
24804        .bar {
24805          color: red;
24806        }
24807      }
24808      "#,
24809      ParserOptions::default(),
24810    )
24811    .unwrap();
24812    stylesheet.minify(MinifyOptions::default()).unwrap();
24813    let res = stylesheet
24814      .to_css(PrinterOptions {
24815        minify: true,
24816        ..PrinterOptions::default()
24817      })
24818      .unwrap();
24819    assert_eq!(res.code, ".foo{color:#00f;& .bar{color:red}}");
24820
24821    nesting_test_with_targets(
24822      r#"
24823        .a {
24824          &.b,
24825          &.c {
24826            &.d {
24827              color: red;
24828            }
24829          }
24830        }
24831      "#,
24832      indoc! {r#"
24833        .a.b.d {
24834          color: red;
24835        }
24836
24837        .a.c.d {
24838          color: red;
24839        }
24840      "#},
24841      Targets {
24842        browsers: Some(Browsers {
24843          safari: Some(13 << 16),
24844          ..Browsers::default()
24845        }),
24846        include: Features::Nesting,
24847        exclude: Features::empty(),
24848      },
24849    );
24850  }
24851
24852  #[test]
24853  fn test_nesting_error_recovery() {
24854    error_recovery_test(
24855      "
24856    .container {
24857      padding: 3rem;
24858      @media (max-width: --styled-jsx-placeholder-0__) {
24859        .responsive {
24860          color: purple;
24861        }
24862      }
24863    }
24864    ",
24865    );
24866  }
24867
24868  #[test]
24869  fn test_css_variable_error_recovery() {
24870    error_recovery_test("
24871    .container {
24872      --local-var: --styled-jsx-placeholder-0__;
24873      color: var(--text-color);
24874      background: linear-gradient(to right, --styled-jsx-placeholder-1__, --styled-jsx-placeholder-2__);
24875
24876      .item {
24877        transform: translate(calc(var(--x) + --styled-jsx-placeholder-3__px), calc(var(--y) + --styled-jsx-placeholder-4__px));
24878      }
24879
24880      div {
24881        margin: calc(10px + --styled-jsx-placeholder-5__px);
24882      }
24883    }
24884  ");
24885  }
24886
24887  #[test]
24888  fn test_css_modules() {
24889    css_modules_test(
24890      r#"
24891      .foo {
24892        color: red;
24893      }
24894
24895      #id {
24896        animation: 2s test;
24897      }
24898
24899      @keyframes test {
24900        from { color: red }
24901        to { color: yellow }
24902      }
24903
24904      @counter-style circles {
24905        symbols: Ⓐ Ⓑ Ⓒ;
24906      }
24907
24908      ul {
24909        list-style: circles;
24910      }
24911
24912      ol {
24913        list-style-type: none;
24914      }
24915
24916      li {
24917        list-style-type: disc;
24918      }
24919
24920      @keyframes fade {
24921        from { opacity: 0 }
24922        to { opacity: 1 }
24923      }
24924    "#,
24925      indoc! {r#"
24926      .EgL3uq_foo {
24927        color: red;
24928      }
24929
24930      #EgL3uq_id {
24931        animation: 2s EgL3uq_test;
24932      }
24933
24934      @keyframes EgL3uq_test {
24935        from {
24936          color: red;
24937        }
24938
24939        to {
24940          color: #ff0;
24941        }
24942      }
24943
24944      @counter-style EgL3uq_circles {
24945        symbols: Ⓐ Ⓑ Ⓒ;
24946      }
24947
24948      ul {
24949        list-style: EgL3uq_circles;
24950      }
24951
24952      ol {
24953        list-style-type: none;
24954      }
24955
24956      li {
24957        list-style-type: disc;
24958      }
24959
24960      @keyframes EgL3uq_fade {
24961        from {
24962          opacity: 0;
24963        }
24964
24965        to {
24966          opacity: 1;
24967        }
24968      }
24969    "#},
24970      map! {
24971        "foo" => "EgL3uq_foo",
24972        "id" => "EgL3uq_id",
24973        "test" => "EgL3uq_test" referenced: true,
24974        "circles" => "EgL3uq_circles" referenced: true,
24975        "fade" => "EgL3uq_fade"
24976      },
24977      HashMap::new(),
24978      Default::default(),
24979      false,
24980    );
24981
24982    css_modules_test(
24983      r#"
24984      .foo {
24985        color: red;
24986      }
24987
24988      #id {
24989        animation: 2s test;
24990      }
24991
24992      @keyframes test {
24993        from { color: red }
24994        to { color: yellow }
24995      }
24996    "#,
24997      indoc! {r#"
24998      .EgL3uq_foo {
24999        color: red;
25000      }
25001
25002      #EgL3uq_id {
25003        animation: 2s test;
25004      }
25005
25006      @keyframes test {
25007        from {
25008          color: red;
25009        }
25010
25011        to {
25012          color: #ff0;
25013        }
25014      }
25015    "#},
25016      map! {
25017        "foo" => "EgL3uq_foo",
25018        "id" => "EgL3uq_id"
25019      },
25020      HashMap::new(),
25021      crate::css_modules::Config {
25022        animation: false,
25023        // custom_idents: false,
25024        ..Default::default()
25025      },
25026      false,
25027    );
25028
25029    css_modules_test(
25030      r#"
25031      @counter-style circles {
25032        symbols: Ⓐ Ⓑ Ⓒ;
25033      }
25034
25035      ul {
25036        list-style: circles;
25037      }
25038
25039      ol {
25040        list-style-type: none;
25041      }
25042
25043      li {
25044        list-style-type: disc;
25045      }
25046    "#,
25047      indoc! {r#"
25048      @counter-style circles {
25049        symbols: Ⓐ Ⓑ Ⓒ;
25050      }
25051
25052      ul {
25053        list-style: circles;
25054      }
25055
25056      ol {
25057        list-style-type: none;
25058      }
25059
25060      li {
25061        list-style-type: disc;
25062      }
25063    "#},
25064      map! {
25065        "circles" => "EgL3uq_circles" referenced: true
25066      },
25067      HashMap::new(),
25068      crate::css_modules::Config {
25069        custom_idents: false,
25070        ..Default::default()
25071      },
25072      false,
25073    );
25074
25075    css_modules_test(
25076      r#"
25077      body {
25078        grid: [header-top] "a a a" [header-bottom]
25079              [main-top] "b b b" 1fr [main-bottom]
25080              / auto 1fr auto;
25081      }
25082
25083      header {
25084        grid-area: a;
25085      }
25086
25087      main {
25088        grid-row: main-top / main-bottom;
25089      }
25090    "#,
25091      indoc! {r#"
25092      body {
25093        grid: [EgL3uq_header-top] "EgL3uq_a EgL3uq_a EgL3uq_a" [EgL3uq_header-bottom]
25094              [EgL3uq_main-top] "EgL3uq_b EgL3uq_b EgL3uq_b" 1fr [EgL3uq_main-bottom]
25095              / auto 1fr auto;
25096      }
25097
25098      header {
25099        grid-area: EgL3uq_a;
25100      }
25101
25102      main {
25103        grid-row: EgL3uq_main-top / EgL3uq_main-bottom;
25104      }
25105    "#},
25106      map! {
25107        "header-top" => "EgL3uq_header-top",
25108        "header-bottom" => "EgL3uq_header-bottom",
25109        "main-top" => "EgL3uq_main-top",
25110        "main-bottom" => "EgL3uq_main-bottom",
25111        "a" => "EgL3uq_a",
25112        "b" => "EgL3uq_b"
25113      },
25114      HashMap::new(),
25115      Default::default(),
25116      false,
25117    );
25118
25119    css_modules_test(
25120      r#"
25121        .grid {
25122          grid-template-areas: "foo";
25123        }
25124
25125        .foo {
25126          grid-area: foo;
25127        }
25128
25129        .bar {
25130          grid-column-start: foo-start;
25131        }
25132      "#,
25133      indoc! {r#"
25134        .EgL3uq_grid {
25135          grid-template-areas: "EgL3uq_foo";
25136        }
25137
25138        .EgL3uq_foo {
25139          grid-area: EgL3uq_foo;
25140        }
25141
25142        .EgL3uq_bar {
25143          grid-column-start: EgL3uq_foo-start;
25144        }
25145      "#},
25146      map! {
25147        "foo" => "EgL3uq_foo",
25148        "foo-start" => "EgL3uq_foo-start",
25149        "grid" => "EgL3uq_grid",
25150        "bar" => "EgL3uq_bar"
25151      },
25152      HashMap::new(),
25153      Default::default(),
25154      false,
25155    );
25156
25157    css_modules_test(
25158      r#"
25159        .grid {
25160          grid-template-areas: "foo";
25161        }
25162
25163        .foo {
25164          grid-area: foo;
25165        }
25166
25167        .bar {
25168          grid-column-start: foo-start;
25169        }
25170      "#,
25171      indoc! {r#"
25172        .EgL3uq_grid {
25173          grid-template-areas: "foo";
25174        }
25175
25176        .EgL3uq_foo {
25177          grid-area: foo;
25178        }
25179
25180        .EgL3uq_bar {
25181          grid-column-start: foo-start;
25182        }
25183      "#},
25184      map! {
25185        "foo" => "EgL3uq_foo",
25186        "grid" => "EgL3uq_grid",
25187        "bar" => "EgL3uq_bar"
25188      },
25189      HashMap::new(),
25190      crate::css_modules::Config {
25191        grid: false,
25192        ..Default::default()
25193      },
25194      false,
25195    );
25196
25197    css_modules_test(
25198      r#"
25199      test {
25200        transition-property: opacity;
25201      }
25202    "#,
25203      indoc! {r#"
25204      test {
25205        transition-property: opacity;
25206      }
25207    "#},
25208      map! {},
25209      HashMap::new(),
25210      Default::default(),
25211      false,
25212    );
25213
25214    css_modules_test(
25215      r#"
25216      :global(.foo) {
25217        color: red;
25218      }
25219
25220      :local(.bar) {
25221        color: yellow;
25222      }
25223
25224      .bar :global(.baz) {
25225        color: purple;
25226      }
25227    "#,
25228      indoc! {r#"
25229      .foo {
25230        color: red;
25231      }
25232
25233      .EgL3uq_bar {
25234        color: #ff0;
25235      }
25236
25237      .EgL3uq_bar .baz {
25238        color: purple;
25239      }
25240    "#},
25241      map! {
25242        "bar" => "EgL3uq_bar"
25243      },
25244      HashMap::new(),
25245      Default::default(),
25246      false,
25247    );
25248
25249    // :global(:local(.hi)) {
25250    //   color: green;
25251    // }
25252
25253    css_modules_test(
25254      r#"
25255      .test {
25256        composes: foo;
25257        background: white;
25258      }
25259
25260      .foo {
25261        color: red;
25262      }
25263    "#,
25264      indoc! {r#"
25265      .EgL3uq_test {
25266        background: #fff;
25267      }
25268
25269      .EgL3uq_foo {
25270        color: red;
25271      }
25272    "#},
25273      map! {
25274        "test" => "EgL3uq_test" "EgL3uq_foo",
25275        "foo" => "EgL3uq_foo"
25276      },
25277      HashMap::new(),
25278      Default::default(),
25279      false,
25280    );
25281
25282    css_modules_test(
25283      r#"
25284      .a, .b {
25285        composes: foo;
25286        background: white;
25287      }
25288
25289      .foo {
25290        color: red;
25291      }
25292    "#,
25293      indoc! {r#"
25294      .EgL3uq_a, .EgL3uq_b {
25295        background: #fff;
25296      }
25297
25298      .EgL3uq_foo {
25299        color: red;
25300      }
25301    "#},
25302      map! {
25303        "a" => "EgL3uq_a" "EgL3uq_foo",
25304        "b" => "EgL3uq_b" "EgL3uq_foo",
25305        "foo" => "EgL3uq_foo"
25306      },
25307      HashMap::new(),
25308      Default::default(),
25309      false,
25310    );
25311
25312    css_modules_test(
25313      r#"
25314      .test {
25315        composes: foo bar;
25316        background: white;
25317      }
25318
25319      .foo {
25320        color: red;
25321      }
25322
25323      .bar {
25324        color: yellow;
25325      }
25326    "#,
25327      indoc! {r#"
25328      .EgL3uq_test {
25329        background: #fff;
25330      }
25331
25332      .EgL3uq_foo {
25333        color: red;
25334      }
25335
25336      .EgL3uq_bar {
25337        color: #ff0;
25338      }
25339    "#},
25340      map! {
25341        "test" => "EgL3uq_test" "EgL3uq_foo" "EgL3uq_bar",
25342        "foo" => "EgL3uq_foo",
25343        "bar" => "EgL3uq_bar"
25344      },
25345      HashMap::new(),
25346      Default::default(),
25347      false,
25348    );
25349
25350    css_modules_test(
25351      r#"
25352      .test {
25353        composes: foo from global;
25354        background: white;
25355      }
25356    "#,
25357      indoc! {r#"
25358      .EgL3uq_test {
25359        background: #fff;
25360      }
25361    "#},
25362      map! {
25363        "test" => "EgL3uq_test" "foo" global: true
25364      },
25365      HashMap::new(),
25366      Default::default(),
25367      false,
25368    );
25369
25370    css_modules_test(
25371      r#"
25372      .test {
25373        composes: foo bar from global;
25374        background: white;
25375      }
25376    "#,
25377      indoc! {r#"
25378      .EgL3uq_test {
25379        background: #fff;
25380      }
25381    "#},
25382      map! {
25383        "test" => "EgL3uq_test" "foo" global: true "bar" global: true
25384      },
25385      HashMap::new(),
25386      Default::default(),
25387      false,
25388    );
25389
25390    css_modules_test(
25391      r#"
25392      .test {
25393        composes: foo from "foo.css";
25394        background: white;
25395      }
25396    "#,
25397      indoc! {r#"
25398      .EgL3uq_test {
25399        background: #fff;
25400      }
25401    "#},
25402      map! {
25403        "test" => "EgL3uq_test" "foo" from "foo.css"
25404      },
25405      HashMap::new(),
25406      Default::default(),
25407      false,
25408    );
25409
25410    css_modules_test(
25411      r#"
25412      .test {
25413        composes: foo bar from "foo.css";
25414        background: white;
25415      }
25416    "#,
25417      indoc! {r#"
25418      .EgL3uq_test {
25419        background: #fff;
25420      }
25421    "#},
25422      map! {
25423        "test" => "EgL3uq_test" "foo" from "foo.css" "bar" from "foo.css"
25424      },
25425      HashMap::new(),
25426      Default::default(),
25427      false,
25428    );
25429
25430    css_modules_test(
25431      r#"
25432      .test {
25433        composes: foo;
25434        composes: foo from "foo.css";
25435        composes: bar from "bar.css";
25436        background: white;
25437      }
25438
25439      .foo {
25440        color: red;
25441      }
25442    "#,
25443      indoc! {r#"
25444      .EgL3uq_test {
25445        background: #fff;
25446      }
25447
25448      .EgL3uq_foo {
25449        color: red;
25450      }
25451    "#},
25452      map! {
25453        "test" => "EgL3uq_test" "EgL3uq_foo" "foo" from "foo.css" "bar" from "bar.css",
25454        "foo" => "EgL3uq_foo"
25455      },
25456      HashMap::new(),
25457      Default::default(),
25458      false,
25459    );
25460
25461    css_modules_test(
25462      r#"
25463      .foo {
25464        color: red;
25465      }
25466    "#,
25467      indoc! {r#"
25468      .test-EgL3uq-foo {
25469        color: red;
25470      }
25471    "#},
25472      map! {
25473        "foo" => "test-EgL3uq-foo"
25474      },
25475      HashMap::new(),
25476      crate::css_modules::Config {
25477        pattern: crate::css_modules::Pattern::parse("test-[hash]-[local]").unwrap(),
25478        ..Default::default()
25479      },
25480      false,
25481    );
25482
25483    let stylesheet = StyleSheet::parse(
25484      r#"
25485        .grid {
25486          grid-template-areas: "foo";
25487        }
25488
25489        .foo {
25490          grid-area: foo;
25491        }
25492
25493        .bar {
25494          grid-column-start: foo-start;
25495        }
25496      "#,
25497      ParserOptions {
25498        css_modules: Some(crate::css_modules::Config {
25499          pattern: crate::css_modules::Pattern::parse("test-[local]-[hash]").unwrap(),
25500          ..Default::default()
25501        }),
25502        ..ParserOptions::default()
25503      },
25504    )
25505    .unwrap();
25506    if let Err(err) = stylesheet.to_css(PrinterOptions::default()) {
25507      assert_eq!(err.kind, PrinterErrorKind::InvalidCssModulesPatternInGrid);
25508    } else {
25509      unreachable!()
25510    }
25511
25512    css_modules_test(
25513      r#"
25514      @property --foo {
25515        syntax: '<color>';
25516        inherits: false;
25517        initial-value: yellow;
25518      }
25519
25520      .foo {
25521        --foo: red;
25522        color: var(--foo);
25523      }
25524    "#,
25525      indoc! {r#"
25526      @property --foo {
25527        syntax: "<color>";
25528        inherits: false;
25529        initial-value: #ff0;
25530      }
25531
25532      .EgL3uq_foo {
25533        --foo: red;
25534        color: var(--foo);
25535      }
25536    "#},
25537      map! {
25538        "foo" => "EgL3uq_foo"
25539      },
25540      HashMap::new(),
25541      Default::default(),
25542      false,
25543    );
25544
25545    css_modules_test(
25546      r#"
25547      @property --foo {
25548        syntax: '<color>';
25549        inherits: false;
25550        initial-value: yellow;
25551      }
25552
25553      @font-palette-values --Cooler {
25554        font-family: Bixa;
25555        base-palette: 1;
25556        override-colors: 1 #7EB7E4;
25557      }
25558
25559      .foo {
25560        --foo: red;
25561        --bar: green;
25562        color: var(--foo);
25563        font-palette: --Cooler;
25564      }
25565
25566      .bar {
25567        color: var(--color from "./b.css");
25568      }
25569    "#,
25570      indoc! {r#"
25571      @property --EgL3uq_foo {
25572        syntax: "<color>";
25573        inherits: false;
25574        initial-value: #ff0;
25575      }
25576
25577      @font-palette-values --EgL3uq_Cooler {
25578        font-family: Bixa;
25579        base-palette: 1;
25580        override-colors: 1 #7eb7e4;
25581      }
25582
25583      .EgL3uq_foo {
25584        --EgL3uq_foo: red;
25585        --EgL3uq_bar: green;
25586        color: var(--EgL3uq_foo);
25587        font-palette: --EgL3uq_Cooler;
25588      }
25589
25590      .EgL3uq_bar {
25591        color: var(--ma1CsG);
25592      }
25593    "#},
25594      map! {
25595        "foo" => "EgL3uq_foo",
25596        "--foo" => "--EgL3uq_foo" referenced: true,
25597        "--bar" => "--EgL3uq_bar",
25598        "bar" => "EgL3uq_bar",
25599        "--Cooler" => "--EgL3uq_Cooler" referenced: true
25600      },
25601      HashMap::from([(
25602        "--ma1CsG".into(),
25603        CssModuleReference::Dependency {
25604          name: "--color".into(),
25605          specifier: "./b.css".into(),
25606        },
25607      )]),
25608      crate::css_modules::Config {
25609        dashed_idents: true,
25610        ..Default::default()
25611      },
25612      false,
25613    );
25614
25615    css_modules_test(
25616      r#"
25617      .test {
25618        animation: rotate var(--duration) linear infinite;
25619      }
25620    "#,
25621      indoc! {r#"
25622      .EgL3uq_test {
25623        animation: EgL3uq_rotate var(--duration) linear infinite;
25624      }
25625    "#},
25626      map! {
25627        "test" => "EgL3uq_test",
25628        "rotate" => "EgL3uq_rotate" referenced: true
25629      },
25630      HashMap::new(),
25631      Default::default(),
25632      false,
25633    );
25634    css_modules_test(
25635      r#"
25636      .test {
25637        animation: none var(--duration);
25638      }
25639    "#,
25640      indoc! {r#"
25641      .EgL3uq_test {
25642        animation: none var(--duration);
25643      }
25644    "#},
25645      map! {
25646        "test" => "EgL3uq_test"
25647      },
25648      HashMap::new(),
25649      Default::default(),
25650      false,
25651    );
25652    css_modules_test(
25653      r#"
25654      .test {
25655        animation: var(--animation);
25656      }
25657    "#,
25658      indoc! {r#"
25659      .EgL3uq_test {
25660        animation: var(--animation);
25661      }
25662    "#},
25663      map! {
25664        "test" => "EgL3uq_test"
25665      },
25666      HashMap::new(),
25667      Default::default(),
25668      false,
25669    );
25670    css_modules_test(
25671      r#"
25672      .test {
25673        animation: rotate var(--duration);
25674      }
25675    "#,
25676      indoc! {r#"
25677      .EgL3uq_test {
25678        animation: rotate var(--duration);
25679      }
25680    "#},
25681      map! {
25682        "test" => "EgL3uq_test"
25683      },
25684      HashMap::new(),
25685      crate::css_modules::Config {
25686        animation: false,
25687        ..Default::default()
25688      },
25689      false,
25690    );
25691    css_modules_test(
25692      r#"
25693      .test {
25694        animation: "rotate" var(--duration);
25695      }
25696    "#,
25697      indoc! {r#"
25698      .EgL3uq_test {
25699        animation: EgL3uq_rotate var(--duration);
25700      }
25701    "#},
25702      map! {
25703        "test" => "EgL3uq_test",
25704        "rotate" => "EgL3uq_rotate" referenced: true
25705      },
25706      HashMap::new(),
25707      crate::css_modules::Config { ..Default::default() },
25708      false,
25709    );
25710
25711    css_modules_test(
25712      r#"
25713      .test {
25714        composes: foo bar from "foo.css";
25715        background: white;
25716      }
25717    "#,
25718      indoc! {r#"
25719      ._5h2kwG-test {
25720        background: #fff;
25721      }
25722    "#},
25723      map! {
25724        "test" => "_5h2kwG-test" "foo" from "foo.css" "bar" from "foo.css"
25725      },
25726      HashMap::new(),
25727      crate::css_modules::Config {
25728        pattern: crate::css_modules::Pattern::parse("[content-hash]-[local]").unwrap(),
25729        ..Default::default()
25730      },
25731      false,
25732    );
25733
25734    css_modules_test(
25735      r#"
25736      .box2 {
25737        @container main (width >= 0) {
25738          background-color: #90ee90;
25739        }
25740      }
25741    "#,
25742      indoc! {r#"
25743      .EgL3uq_box2 {
25744        @container EgL3uq_main (width >= 0) {
25745          background-color: #90ee90;
25746        }
25747      }
25748    "#},
25749      map! {
25750        "main" => "EgL3uq_main",
25751        "box2" => "EgL3uq_box2"
25752      },
25753      HashMap::new(),
25754      crate::css_modules::Config { ..Default::default() },
25755      false,
25756    );
25757
25758    css_modules_test(
25759      r#"
25760      .box2 {
25761        @container main (width >= 0) {
25762          background-color: #90ee90;
25763        }
25764      }
25765    "#,
25766      indoc! {r#"
25767      .EgL3uq_box2 {
25768        @container main (width >= 0) {
25769          background-color: #90ee90;
25770        }
25771      }
25772    "#},
25773      map! {
25774        "box2" => "EgL3uq_box2"
25775      },
25776      HashMap::new(),
25777      crate::css_modules::Config {
25778        container: false,
25779        ..Default::default()
25780      },
25781      false,
25782    );
25783
25784    css_modules_test(
25785      ".foo { view-transition-name: bar }",
25786      ".EgL3uq_foo{view-transition-name:EgL3uq_bar}",
25787      map! {
25788        "foo" => "EgL3uq_foo",
25789        "bar" => "EgL3uq_bar"
25790      },
25791      HashMap::new(),
25792      Default::default(),
25793      true,
25794    );
25795    css_modules_test(
25796      ".foo { view-transition-name: none }",
25797      ".EgL3uq_foo{view-transition-name:none}",
25798      map! {
25799        "foo" => "EgL3uq_foo"
25800      },
25801      HashMap::new(),
25802      Default::default(),
25803      true,
25804    );
25805    css_modules_test(
25806      ".foo { view-transition-name: auto }",
25807      ".EgL3uq_foo{view-transition-name:auto}",
25808      map! {
25809        "foo" => "EgL3uq_foo"
25810      },
25811      HashMap::new(),
25812      Default::default(),
25813      true,
25814    );
25815
25816    css_modules_test(
25817      ".foo { view-transition-class: bar baz qux }",
25818      ".EgL3uq_foo{view-transition-class:EgL3uq_bar EgL3uq_baz EgL3uq_qux}",
25819      map! {
25820        "foo" => "EgL3uq_foo",
25821        "bar" => "EgL3uq_bar",
25822        "baz" => "EgL3uq_baz",
25823        "qux" => "EgL3uq_qux"
25824      },
25825      HashMap::new(),
25826      Default::default(),
25827      true,
25828    );
25829
25830    css_modules_test(
25831      ".foo { view-transition-group: contain }",
25832      ".EgL3uq_foo{view-transition-group:contain}",
25833      map! {
25834        "foo" => "EgL3uq_foo"
25835      },
25836      HashMap::new(),
25837      Default::default(),
25838      true,
25839    );
25840    css_modules_test(
25841      ".foo { view-transition-group: bar }",
25842      ".EgL3uq_foo{view-transition-group:EgL3uq_bar}",
25843      map! {
25844        "foo" => "EgL3uq_foo",
25845        "bar" => "EgL3uq_bar"
25846      },
25847      HashMap::new(),
25848      Default::default(),
25849      true,
25850    );
25851
25852    css_modules_test(
25853      "@view-transition { types: foo bar baz }",
25854      "@view-transition{types:EgL3uq_foo EgL3uq_bar EgL3uq_baz}",
25855      map! {
25856        "foo" => "EgL3uq_foo",
25857        "bar" => "EgL3uq_bar",
25858        "baz" => "EgL3uq_baz"
25859      },
25860      HashMap::new(),
25861      Default::default(),
25862      true,
25863    );
25864
25865    css_modules_test(
25866      ":root:active-view-transition-type(foo, bar) { color: red }",
25867      ":root:active-view-transition-type(EgL3uq_foo,EgL3uq_bar){color:red}",
25868      map! {
25869        "foo" => "EgL3uq_foo",
25870        "bar" => "EgL3uq_bar"
25871      },
25872      HashMap::new(),
25873      Default::default(),
25874      true,
25875    );
25876
25877    for name in &[
25878      "view-transition-group",
25879      "view-transition-image-pair",
25880      "view-transition-new",
25881      "view-transition-old",
25882    ] {
25883      css_modules_test(
25884        &format!(":root::{}(foo) {{position: fixed}}", name),
25885        &format!(":root::{}(EgL3uq_foo){{position:fixed}}", name),
25886        map! {
25887          "foo" => "EgL3uq_foo"
25888        },
25889        HashMap::new(),
25890        Default::default(),
25891        true,
25892      );
25893      css_modules_test(
25894        &format!(":root::{}(.bar) {{position: fixed}}", name),
25895        &format!(":root::{}(.EgL3uq_bar){{position:fixed}}", name),
25896        map! {
25897          "bar" => "EgL3uq_bar"
25898        },
25899        HashMap::new(),
25900        Default::default(),
25901        true,
25902      );
25903      css_modules_test(
25904        &format!(":root::{}(foo.bar.baz) {{position: fixed}}", name),
25905        &format!(":root::{}(EgL3uq_foo.EgL3uq_bar.EgL3uq_baz){{position:fixed}}", name),
25906        map! {
25907          "foo" => "EgL3uq_foo",
25908          "bar" => "EgL3uq_bar",
25909          "baz" => "EgL3uq_baz"
25910        },
25911        HashMap::new(),
25912        Default::default(),
25913        true,
25914      );
25915
25916      css_modules_test(
25917        ":nth-child(1 of .foo) {width: 20px}",
25918        ":nth-child(1 of .EgL3uq_foo){width:20px}",
25919        map! {
25920          "foo" => "EgL3uq_foo"
25921        },
25922        HashMap::new(),
25923        Default::default(),
25924        true,
25925      );
25926      css_modules_test(
25927        ":nth-last-child(1 of .foo) {width: 20px}",
25928        ":nth-last-child(1 of .EgL3uq_foo){width:20px}",
25929        map! {
25930          "foo" => "EgL3uq_foo"
25931        },
25932        HashMap::new(),
25933        Default::default(),
25934        true,
25935      );
25936    }
25937
25938    // Stable hashes between project roots.
25939    fn test_project_root(project_root: &str, filename: &str, hash: &str) {
25940      let stylesheet = StyleSheet::parse(
25941        r#"
25942        .foo {
25943          background: red;
25944        }
25945        "#,
25946        ParserOptions {
25947          filename: filename.into(),
25948          css_modules: Some(Default::default()),
25949          ..ParserOptions::default()
25950        },
25951      )
25952      .unwrap();
25953      let res = stylesheet
25954        .to_css(PrinterOptions {
25955          project_root: Some(project_root),
25956          ..PrinterOptions::default()
25957        })
25958        .unwrap();
25959      assert_eq!(
25960        res.code,
25961        format!(
25962          indoc! {r#"
25963      .{}_foo {{
25964        background: red;
25965      }}
25966      "#},
25967          hash
25968        )
25969      );
25970    }
25971
25972    test_project_root("/foo/bar", "/foo/bar/test.css", "EgL3uq");
25973    test_project_root("/foo", "/foo/test.css", "EgL3uq");
25974    test_project_root("/foo/bar", "/foo/bar/baz/test.css", "xLEkNW");
25975    test_project_root("/foo", "/foo/baz/test.css", "xLEkNW");
25976
25977    let mut stylesheet = StyleSheet::parse(
25978      r#"
25979      .foo {
25980        color: red;
25981        .bar {
25982          color: green;
25983        }
25984        composes: test from "foo.css";
25985      }
25986      "#,
25987      ParserOptions {
25988        filename: "test.css".into(),
25989        css_modules: Some(Default::default()),
25990        ..ParserOptions::default()
25991      },
25992    )
25993    .unwrap();
25994    stylesheet.minify(MinifyOptions::default()).unwrap();
25995    let res = stylesheet
25996      .to_css(PrinterOptions {
25997        targets: Browsers {
25998          chrome: Some(95 << 16),
25999          ..Browsers::default()
26000        }
26001        .into(),
26002        ..Default::default()
26003      })
26004      .unwrap();
26005    assert_eq!(
26006      res.code,
26007      indoc! {r#"
26008    .EgL3uq_foo {
26009      color: red;
26010    }
26011
26012    .EgL3uq_foo .EgL3uq_bar {
26013      color: green;
26014    }
26015
26016
26017    "#}
26018    );
26019    assert_eq!(
26020      res.exports.unwrap(),
26021      map! {
26022        "foo" => "EgL3uq_foo" "test" from "foo.css",
26023        "bar" => "EgL3uq_bar"
26024      }
26025    );
26026  }
26027
26028  #[test]
26029  fn test_pseudo_replacement() {
26030    let source = r#"
26031      .foo:hover {
26032        color: red;
26033      }
26034
26035      .foo:active {
26036        color: yellow;
26037      }
26038
26039      .foo:focus-visible {
26040        color: purple;
26041      }
26042    "#;
26043
26044    let expected = indoc! { r#"
26045      .foo.is-hovered {
26046        color: red;
26047      }
26048
26049      .foo.is-active {
26050        color: #ff0;
26051      }
26052
26053      .foo.focus-visible {
26054        color: purple;
26055      }
26056    "#};
26057
26058    let stylesheet = StyleSheet::parse(&source, ParserOptions::default()).unwrap();
26059    let res = stylesheet
26060      .to_css(PrinterOptions {
26061        pseudo_classes: Some(PseudoClasses {
26062          hover: Some("is-hovered"),
26063          active: Some("is-active"),
26064          focus_visible: Some("focus-visible"),
26065          ..PseudoClasses::default()
26066        }),
26067        ..PrinterOptions::default()
26068      })
26069      .unwrap();
26070    assert_eq!(res.code, expected);
26071
26072    let source = r#"
26073      .foo:hover {
26074        color: red;
26075      }
26076    "#;
26077
26078    let expected = indoc! { r#"
26079      .EgL3uq_foo.EgL3uq_is-hovered {
26080        color: red;
26081      }
26082    "#};
26083
26084    let stylesheet = StyleSheet::parse(
26085      &source,
26086      ParserOptions {
26087        filename: "test.css".into(),
26088        css_modules: Some(Default::default()),
26089        ..ParserOptions::default()
26090      },
26091    )
26092    .unwrap();
26093    let res = stylesheet
26094      .to_css(PrinterOptions {
26095        pseudo_classes: Some(PseudoClasses {
26096          hover: Some("is-hovered"),
26097          ..PseudoClasses::default()
26098        }),
26099        ..PrinterOptions::default()
26100      })
26101      .unwrap();
26102    assert_eq!(res.code, expected);
26103  }
26104
26105  #[test]
26106  fn test_unused_symbols() {
26107    let source = r#"
26108      .foo {
26109        color: red;
26110      }
26111
26112      .bar {
26113        color: green;
26114      }
26115
26116      .bar:hover {
26117        color: purple;
26118      }
26119
26120      .bar .baz {
26121        background: red;
26122      }
26123
26124      .baz:is(.bar) {
26125        background: green;
26126      }
26127
26128      #id {
26129        animation: 2s test;
26130      }
26131
26132      #other_id {
26133        color: red;
26134      }
26135
26136      @keyframes test {
26137        from { color: red }
26138        to { color: yellow }
26139      }
26140
26141      @counter-style circles {
26142        symbols: Ⓐ Ⓑ Ⓒ;
26143      }
26144
26145      @keyframes fade {
26146        from { opacity: 0 }
26147        to { opacity: 1 }
26148      }
26149    "#;
26150
26151    let expected = indoc! {r#"
26152      .foo {
26153        color: red;
26154      }
26155
26156      #id {
26157        animation: 2s test;
26158      }
26159
26160      @keyframes test {
26161        from {
26162          color: red;
26163        }
26164
26165        to {
26166          color: #ff0;
26167        }
26168      }
26169    "#};
26170
26171    let mut stylesheet = StyleSheet::parse(&source, ParserOptions::default()).unwrap();
26172    stylesheet
26173      .minify(MinifyOptions {
26174        unused_symbols: vec!["bar", "other_id", "fade", "circles"]
26175          .iter()
26176          .map(|s| String::from(*s))
26177          .collect(),
26178        ..MinifyOptions::default()
26179      })
26180      .unwrap();
26181    let res = stylesheet.to_css(PrinterOptions::default()).unwrap();
26182    assert_eq!(res.code, expected);
26183
26184    let source = r#"
26185      .foo {
26186        color: red;
26187
26188        &.bar {
26189          color: green;
26190        }
26191      }
26192    "#;
26193
26194    let expected = indoc! {r#"
26195      .foo {
26196        color: red;
26197      }
26198    "#};
26199
26200    let mut stylesheet = StyleSheet::parse(&source, ParserOptions::default()).unwrap();
26201    stylesheet
26202      .minify(MinifyOptions {
26203        unused_symbols: vec!["bar"].iter().map(|s| String::from(*s)).collect(),
26204        ..MinifyOptions::default()
26205      })
26206      .unwrap();
26207    let res = stylesheet.to_css(PrinterOptions::default()).unwrap();
26208    assert_eq!(res.code, expected);
26209
26210    let source = r#"
26211      .foo {
26212        color: red;
26213
26214        &.bar {
26215          color: purple;
26216        }
26217
26218        @nest &.bar {
26219          color: orange;
26220        }
26221
26222        @nest :not(&) {
26223          color: green;
26224        }
26225
26226        @media (orientation: portrait) {
26227          color: brown;
26228        }
26229      }
26230
26231      .x {
26232        color: purple;
26233
26234        &.y {
26235          color: green;
26236        }
26237      }
26238    "#;
26239
26240    let expected = indoc! {r#"
26241      :not(.foo) {
26242        color: green;
26243      }
26244    "#};
26245
26246    let mut stylesheet = StyleSheet::parse(&source, ParserOptions::default()).unwrap();
26247    stylesheet
26248      .minify(MinifyOptions {
26249        unused_symbols: vec!["foo", "x"].iter().map(|s| String::from(*s)).collect(),
26250        ..MinifyOptions::default()
26251      })
26252      .unwrap();
26253    let res = stylesheet
26254      .to_css(PrinterOptions {
26255        targets: Browsers {
26256          chrome: Some(95 << 16),
26257          ..Browsers::default()
26258        }
26259        .into(),
26260        ..PrinterOptions::default()
26261      })
26262      .unwrap();
26263    assert_eq!(res.code, expected);
26264
26265    let source = r#"
26266      @property --EgL3uq_foo {
26267        syntax: "<color>";
26268        inherits: false;
26269        initial-value: #ff0;
26270      }
26271
26272      @font-palette-values --EgL3uq_Cooler {
26273        font-family: Bixa;
26274        base-palette: 1;
26275        override-colors: 1 #7EB7E4;
26276      }
26277
26278      .EgL3uq_foo {
26279        --EgL3uq_foo: red;
26280      }
26281
26282      .EgL3uq_bar {
26283        color: green;
26284      }
26285    "#;
26286
26287    let expected = indoc! {r#"
26288      .EgL3uq_bar {
26289        color: green;
26290      }
26291    "#};
26292
26293    let mut stylesheet = StyleSheet::parse(&source, ParserOptions::default()).unwrap();
26294    stylesheet
26295      .minify(MinifyOptions {
26296        unused_symbols: vec!["--EgL3uq_foo", "--EgL3uq_Cooler"]
26297          .iter()
26298          .map(|s| String::from(*s))
26299          .collect(),
26300        ..MinifyOptions::default()
26301      })
26302      .unwrap();
26303    let res = stylesheet.to_css(PrinterOptions::default()).unwrap();
26304    assert_eq!(res.code, expected);
26305  }
26306
26307  #[test]
26308  fn test_svg() {
26309    minify_test(".foo { fill: yellow; }", ".foo{fill:#ff0}");
26310    minify_test(".foo { fill: url(#foo); }", ".foo{fill:url(#foo)}");
26311    minify_test(".foo { fill: url(#foo) none; }", ".foo{fill:url(#foo) none}");
26312    minify_test(".foo { fill: url(#foo) yellow; }", ".foo{fill:url(#foo) #ff0}");
26313    minify_test(".foo { fill: none; }", ".foo{fill:none}");
26314    minify_test(".foo { fill: context-fill; }", ".foo{fill:context-fill}");
26315    minify_test(".foo { fill: context-stroke; }", ".foo{fill:context-stroke}");
26316
26317    minify_test(".foo { stroke: yellow; }", ".foo{stroke:#ff0}");
26318    minify_test(".foo { stroke: url(#foo); }", ".foo{stroke:url(#foo)}");
26319    minify_test(".foo { stroke: url(#foo) none; }", ".foo{stroke:url(#foo) none}");
26320    minify_test(".foo { stroke: url(#foo) yellow; }", ".foo{stroke:url(#foo) #ff0}");
26321    minify_test(".foo { stroke: none; }", ".foo{stroke:none}");
26322    minify_test(".foo { stroke: context-fill; }", ".foo{stroke:context-fill}");
26323    minify_test(".foo { stroke: context-stroke; }", ".foo{stroke:context-stroke}");
26324
26325    minify_test(".foo { marker-start: url(#foo); }", ".foo{marker-start:url(#foo)}");
26326
26327    minify_test(".foo { stroke-dasharray: 4 1 2; }", ".foo{stroke-dasharray:4 1 2}");
26328    minify_test(".foo { stroke-dasharray: 4,1,2; }", ".foo{stroke-dasharray:4 1 2}");
26329    minify_test(".foo { stroke-dasharray: 4, 1, 2; }", ".foo{stroke-dasharray:4 1 2}");
26330    minify_test(
26331      ".foo { stroke-dasharray: 4px, 1px, 2px; }",
26332      ".foo{stroke-dasharray:4 1 2}",
26333    );
26334
26335    minify_test(".foo { mask: url('foo.svg'); }", ".foo{mask:url(foo.svg)}");
26336    minify_test(
26337      ".foo { mask: url(masks.svg#star) luminance }",
26338      ".foo{mask:url(masks.svg#star) luminance}",
26339    );
26340    minify_test(
26341      ".foo { mask: url(masks.svg#star) 40px 20px }",
26342      ".foo{mask:url(masks.svg#star) 40px 20px}",
26343    );
26344    minify_test(
26345      ".foo { mask: url(masks.svg#star) 0 0 / 50px 50px }",
26346      ".foo{mask:url(masks.svg#star) 0 0/50px 50px}",
26347    );
26348    minify_test(
26349      ".foo { mask: url(masks.svg#star) repeat-x }",
26350      ".foo{mask:url(masks.svg#star) repeat-x}",
26351    );
26352    minify_test(
26353      ".foo { mask: url(masks.svg#star) stroke-box }",
26354      ".foo{mask:url(masks.svg#star) stroke-box}",
26355    );
26356    minify_test(
26357      ".foo { mask: url(masks.svg#star) stroke-box stroke-box }",
26358      ".foo{mask:url(masks.svg#star) stroke-box}",
26359    );
26360    minify_test(
26361      ".foo { mask: url(masks.svg#star) border-box }",
26362      ".foo{mask:url(masks.svg#star)}",
26363    );
26364    minify_test(
26365      ".foo { mask: url(masks.svg#star) left / 16px repeat-y, url(masks.svg#circle) right / 16px repeat-y }",
26366      ".foo{mask:url(masks.svg#star) 0/16px repeat-y,url(masks.svg#circle) 100%/16px repeat-y}",
26367    );
26368
26369    minify_test(
26370      ".foo { mask-border: url('border-mask.png') 25; }",
26371      ".foo{mask-border:url(border-mask.png) 25}",
26372    );
26373    minify_test(
26374      ".foo { mask-border: url('border-mask.png') 25 / 35px / 12px space alpha; }",
26375      ".foo{mask-border:url(border-mask.png) 25/35px/12px space}",
26376    );
26377    minify_test(
26378      ".foo { mask-border: url('border-mask.png') 25 / 35px / 12px space luminance; }",
26379      ".foo{mask-border:url(border-mask.png) 25/35px/12px space luminance}",
26380    );
26381    minify_test(
26382      ".foo { mask-border: url('border-mask.png') luminance 25 / 35px / 12px space; }",
26383      ".foo{mask-border:url(border-mask.png) 25/35px/12px space luminance}",
26384    );
26385
26386    minify_test(
26387      ".foo { clip-path: url('clip.svg#star'); }",
26388      ".foo{clip-path:url(clip.svg#star)}",
26389    );
26390    minify_test(".foo { clip-path: margin-box; }", ".foo{clip-path:margin-box}");
26391    minify_test(
26392      ".foo { clip-path: inset(100px 50px); }",
26393      ".foo{clip-path:inset(100px 50px)}",
26394    );
26395    minify_test(
26396      ".foo { clip-path: inset(100px 50px round 5px); }",
26397      ".foo{clip-path:inset(100px 50px round 5px)}",
26398    );
26399    minify_test(
26400      ".foo { clip-path: inset(100px 50px round 5px 5px 5px 5px); }",
26401      ".foo{clip-path:inset(100px 50px round 5px)}",
26402    );
26403    minify_test(".foo { clip-path: circle(50px); }", ".foo{clip-path:circle(50px)}");
26404    minify_test(
26405      ".foo { clip-path: circle(50px at center center); }",
26406      ".foo{clip-path:circle(50px)}",
26407    );
26408    minify_test(
26409      ".foo { clip-path: circle(50px at 50% 50%); }",
26410      ".foo{clip-path:circle(50px)}",
26411    );
26412    minify_test(
26413      ".foo { clip-path: circle(50px at 0 100px); }",
26414      ".foo{clip-path:circle(50px at 0 100px)}",
26415    );
26416    minify_test(
26417      ".foo { clip-path: circle(closest-side at 0 100px); }",
26418      ".foo{clip-path:circle(at 0 100px)}",
26419    );
26420    minify_test(
26421      ".foo { clip-path: circle(farthest-side at 0 100px); }",
26422      ".foo{clip-path:circle(farthest-side at 0 100px)}",
26423    );
26424    minify_test(
26425      ".foo { clip-path: circle(closest-side at 50% 50%); }",
26426      ".foo{clip-path:circle()}",
26427    );
26428    minify_test(
26429      ".foo { clip-path: ellipse(50px 60px at 0 10% 20%); }",
26430      ".foo{clip-path:ellipse(50px 60px at 0 10% 20%)}",
26431    );
26432    minify_test(
26433      ".foo { clip-path: ellipse(50px 60px at center center); }",
26434      ".foo{clip-path:ellipse(50px 60px)}",
26435    );
26436    minify_test(
26437      ".foo { clip-path: ellipse(closest-side closest-side at 50% 50%); }",
26438      ".foo{clip-path:ellipse()}",
26439    );
26440    minify_test(
26441      ".foo { clip-path: ellipse(closest-side closest-side at 10% 20%); }",
26442      ".foo{clip-path:ellipse(at 10% 20%)}",
26443    );
26444    minify_test(
26445      ".foo { clip-path: ellipse(farthest-side closest-side at 10% 20%); }",
26446      ".foo{clip-path:ellipse(farthest-side closest-side at 10% 20%)}",
26447    );
26448    minify_test(
26449      ".foo { clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%); }",
26450      ".foo{clip-path:polygon(50% 0%,100% 50%,50% 100%,0% 50%)}",
26451    );
26452    minify_test(
26453      ".foo { clip-path: polygon(nonzero, 50% 0%, 100% 50%, 50% 100%, 0% 50%); }",
26454      ".foo{clip-path:polygon(50% 0%,100% 50%,50% 100%,0% 50%)}",
26455    );
26456    minify_test(
26457      ".foo { clip-path: polygon(evenodd, 50% 0%, 100% 50%, 50% 100%, 0% 50%); }",
26458      ".foo{clip-path:polygon(evenodd,50% 0%,100% 50%,50% 100%,0% 50%)}",
26459    );
26460    minify_test(
26461      ".foo { clip-path: padding-box circle(50px at 0 100px); }",
26462      ".foo{clip-path:circle(50px at 0 100px) padding-box}",
26463    );
26464    minify_test(
26465      ".foo { clip-path: circle(50px at 0 100px) padding-box; }",
26466      ".foo{clip-path:circle(50px at 0 100px) padding-box}",
26467    );
26468    minify_test(
26469      ".foo { clip-path: circle(50px at 0 100px) border-box; }",
26470      ".foo{clip-path:circle(50px at 0 100px)}",
26471    );
26472
26473    prefix_test(
26474      ".foo { clip-path: circle(50px); }",
26475      indoc! { r#"
26476        .foo {
26477          -webkit-clip-path: circle(50px);
26478          clip-path: circle(50px);
26479        }
26480      "#},
26481      Browsers {
26482        chrome: Some(30 << 16),
26483        ..Browsers::default()
26484      },
26485    );
26486
26487    prefix_test(
26488      ".foo { clip-path: circle(50px); }",
26489      indoc! { r#"
26490        .foo {
26491          clip-path: circle(50px);
26492        }
26493      "#},
26494      Browsers {
26495        chrome: Some(80 << 16),
26496        ..Browsers::default()
26497      },
26498    );
26499
26500    prefix_test(
26501      ".foo { clip-path: circle(50px); }",
26502      indoc! { r#"
26503        .foo {
26504          -webkit-clip-path: circle(50px);
26505          clip-path: circle(50px);
26506        }
26507      "#},
26508      Browsers {
26509        safari: Some(8 << 16),
26510        ..Browsers::default()
26511      },
26512    );
26513
26514    prefix_test(
26515      ".foo { clip-path: circle(50px); }",
26516      indoc! { r#"
26517        .foo {
26518          clip-path: circle(50px);
26519        }
26520      "#},
26521      Browsers {
26522        safari: Some(14 << 16),
26523        ..Browsers::default()
26524      },
26525    );
26526
26527    prefix_test(
26528      ".foo { fill: lch(50.998% 135.363 338) }",
26529      indoc! { r#"
26530        .foo {
26531          fill: #ee00be;
26532          fill: color(display-p3 .972962 -.362078 .804206);
26533          fill: lch(50.998% 135.363 338);
26534        }
26535      "#},
26536      Browsers {
26537        chrome: Some(90 << 16),
26538        safari: Some(14 << 16),
26539        ..Browsers::default()
26540      },
26541    );
26542
26543    prefix_test(
26544      ".foo { stroke: lch(50.998% 135.363 338) }",
26545      indoc! { r#"
26546        .foo {
26547          stroke: #ee00be;
26548          stroke: color(display-p3 .972962 -.362078 .804206);
26549          stroke: lch(50.998% 135.363 338);
26550        }
26551      "#},
26552      Browsers {
26553        chrome: Some(90 << 16),
26554        safari: Some(14 << 16),
26555        ..Browsers::default()
26556      },
26557    );
26558
26559    prefix_test(
26560      ".foo { fill: url(#foo) lch(50.998% 135.363 338) }",
26561      indoc! { r##"
26562        .foo {
26563          fill: url("#foo") #ee00be;
26564          fill: url("#foo") color(display-p3 .972962 -.362078 .804206);
26565          fill: url("#foo") lch(50.998% 135.363 338);
26566        }
26567      "##},
26568      Browsers {
26569        chrome: Some(90 << 16),
26570        safari: Some(14 << 16),
26571        ..Browsers::default()
26572      },
26573    );
26574
26575    prefix_test(
26576      ".foo { fill: var(--url) lch(50.998% 135.363 338) }",
26577      indoc! { r#"
26578        .foo {
26579          fill: var(--url) #ee00be;
26580        }
26581
26582        @supports (color: lab(0% 0 0)) {
26583          .foo {
26584            fill: var(--url) lab(50.998% 125.506 -50.7078);
26585          }
26586        }
26587      "#},
26588      Browsers {
26589        chrome: Some(90 << 16),
26590        ..Browsers::default()
26591      },
26592    );
26593
26594    prefix_test(
26595      r#"
26596        @supports (color: lab(0% 0 0)) {
26597          .foo {
26598            fill: var(--url) lab(50.998% 125.506 -50.7078);
26599          }
26600        }
26601      "#,
26602      indoc! { r#"
26603        @supports (color: lab(0% 0 0)) {
26604          .foo {
26605            fill: var(--url) lab(50.998% 125.506 -50.7078);
26606          }
26607        }
26608      "#},
26609      Browsers {
26610        chrome: Some(90 << 16),
26611        ..Browsers::default()
26612      },
26613    );
26614
26615    prefix_test(
26616      ".foo { mask-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
26617      indoc! { r#"
26618        .foo {
26619          -webkit-mask-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ff0f0e), to(#7773ff));
26620          -webkit-mask-image: -webkit-linear-gradient(top, #ff0f0e, #7773ff);
26621          -webkit-mask-image: linear-gradient(#ff0f0e, #7773ff);
26622          mask-image: linear-gradient(#ff0f0e, #7773ff);
26623          -webkit-mask-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
26624          mask-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
26625        }
26626      "#},
26627      Browsers {
26628        chrome: Some(8 << 16),
26629        ..Browsers::default()
26630      },
26631    );
26632
26633    prefix_test(
26634      ".foo { mask-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
26635      indoc! { r#"
26636        .foo {
26637          -webkit-mask-image: linear-gradient(#ff0f0e, #7773ff);
26638          mask-image: linear-gradient(#ff0f0e, #7773ff);
26639          -webkit-mask-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
26640          mask-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
26641        }
26642      "#},
26643      Browsers {
26644        chrome: Some(95 << 16),
26645        ..Browsers::default()
26646      },
26647    );
26648
26649    prefix_test(
26650      ".foo { mask-image: linear-gradient(red, green) }",
26651      indoc! { r#"
26652        .foo {
26653          -webkit-mask-image: linear-gradient(red, green);
26654          mask-image: linear-gradient(red, green);
26655        }
26656      "#},
26657      Browsers {
26658        chrome: Some(95 << 16),
26659        ..Browsers::default()
26660      },
26661    );
26662
26663    prefix_test(
26664      ".foo { -webkit-mask-image: url(x.svg); mask-image: url(x.svg); }",
26665      indoc! { r#"
26666        .foo {
26667          -webkit-mask-image: url("x.svg");
26668          mask-image: url("x.svg");
26669        }
26670      "#},
26671      Browsers {
26672        chrome: Some(95 << 16),
26673        ..Browsers::default()
26674      },
26675    );
26676
26677    prefix_test(
26678      ".foo { mask: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 40px 20px }",
26679      indoc! { r#"
26680        .foo {
26681          -webkit-mask: -webkit-gradient(linear, 0 0, 0 100%, from(#ff0f0e), to(#7773ff)) 40px 20px;
26682          -webkit-mask: -webkit-linear-gradient(top, #ff0f0e, #7773ff) 40px 20px;
26683          -webkit-mask: linear-gradient(#ff0f0e, #7773ff) 40px 20px;
26684          mask: linear-gradient(#ff0f0e, #7773ff) 40px 20px;
26685          -webkit-mask: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 40px 20px;
26686          mask: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 40px 20px;
26687        }
26688      "#},
26689      Browsers {
26690        chrome: Some(8 << 16),
26691        ..Browsers::default()
26692      },
26693    );
26694
26695    prefix_test(
26696      ".foo { mask: -webkit-linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 40px 20px }",
26697      indoc! { r#"
26698        .foo {
26699          -webkit-mask: -webkit-gradient(linear, 0 0, 0 100%, from(#ff0f0e), to(#7773ff)) 40px 20px;
26700          -webkit-mask: -webkit-linear-gradient(#ff0f0e, #7773ff) 40px 20px;
26701        }
26702      "#},
26703      Browsers {
26704        chrome: Some(8 << 16),
26705        ..Browsers::default()
26706      },
26707    );
26708
26709    prefix_test(
26710      ".foo { mask: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 40px var(--foo) }",
26711      indoc! { r#"
26712        .foo {
26713          -webkit-mask: linear-gradient(#ff0f0e, #7773ff) 40px var(--foo);
26714          mask: linear-gradient(#ff0f0e, #7773ff) 40px var(--foo);
26715        }
26716
26717        @supports (color: lab(0% 0 0)) {
26718          .foo {
26719            -webkit-mask: linear-gradient(lab(56.208% 94.4644 98.8928), lab(51% 70.4544 -115.586)) 40px var(--foo);
26720            mask: linear-gradient(lab(56.208% 94.4644 98.8928), lab(51% 70.4544 -115.586)) 40px var(--foo);
26721          }
26722        }
26723      "#},
26724      Browsers {
26725        chrome: Some(90 << 16),
26726        ..Browsers::default()
26727      },
26728    );
26729
26730    prefix_test(
26731      r#"
26732        @supports (color: lab(0% 0 0)) {
26733          .foo {
26734            mask: linear-gradient(lab(56.208% 94.4644 98.8928), lab(51% 70.4544 -115.586)) 40px var(--foo);
26735          }
26736        }
26737      "#,
26738      indoc! { r#"
26739        @supports (color: lab(0% 0 0)) {
26740          .foo {
26741            -webkit-mask: linear-gradient(lab(56.208% 94.4644 98.8928), lab(51% 70.4544 -115.586)) 40px var(--foo);
26742            mask: linear-gradient(lab(56.208% 94.4644 98.8928), lab(51% 70.4544 -115.586)) 40px var(--foo);
26743          }
26744        }
26745      "#},
26746      Browsers {
26747        chrome: Some(90 << 16),
26748        ..Browsers::default()
26749      },
26750    );
26751
26752    prefix_test(
26753      ".foo { mask: url(masks.svg#star) luminance }",
26754      indoc! { r#"
26755        .foo {
26756          -webkit-mask: url("masks.svg#star");
26757          -webkit-mask-source-type: luminance;
26758          mask: url("masks.svg#star") luminance;
26759        }
26760    "#},
26761      Browsers {
26762        chrome: Some(90 << 16),
26763        ..Browsers::default()
26764      },
26765    );
26766
26767    prefix_test(
26768      ".foo { mask-image: url(masks.svg#star) }",
26769      indoc! { r#"
26770        .foo {
26771          -webkit-mask-image: url("masks.svg#star");
26772          mask-image: url("masks.svg#star");
26773        }
26774    "#},
26775      Browsers {
26776        chrome: Some(90 << 16),
26777        ..Browsers::default()
26778      },
26779    );
26780
26781    prefix_test(
26782      r#"
26783        .foo {
26784          mask-image: url(masks.svg#star);
26785          mask-position: 25% 75%;
26786          mask-size: cover;
26787          mask-repeat: no-repeat;
26788          mask-clip: padding-box;
26789          mask-origin: content-box;
26790          mask-composite: subtract;
26791          mask-mode: luminance;
26792        }
26793      "#,
26794      indoc! { r#"
26795        .foo {
26796          -webkit-mask: url("masks.svg#star") 25% 75% / cover no-repeat content-box padding-box;
26797          -webkit-mask-composite: source-out;
26798          -webkit-mask-source-type: luminance;
26799          mask: url("masks.svg#star") 25% 75% / cover no-repeat content-box padding-box subtract luminance;
26800        }
26801    "#},
26802      Browsers {
26803        chrome: Some(90 << 16),
26804        ..Browsers::default()
26805      },
26806    );
26807
26808    prefix_test(
26809      r#"
26810        .foo {
26811          mask-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
26812          mask-position: 25% 75%;
26813          mask-size: cover;
26814          mask-repeat: no-repeat;
26815          mask-clip: padding-box;
26816          mask-origin: content-box;
26817          mask-composite: subtract;
26818          mask-mode: luminance;
26819        }
26820      "#,
26821      indoc! { r#"
26822        .foo {
26823          -webkit-mask: linear-gradient(#ff0f0e, #7773ff) 25% 75% / cover no-repeat content-box padding-box;
26824          -webkit-mask-composite: source-out;
26825          -webkit-mask-source-type: luminance;
26826          mask: linear-gradient(#ff0f0e, #7773ff) 25% 75% / cover no-repeat content-box padding-box subtract luminance;
26827          -webkit-mask: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 25% 75% / cover no-repeat content-box padding-box;
26828          -webkit-mask-composite: source-out;
26829          -webkit-mask-source-type: luminance;
26830          mask: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 25% 75% / cover no-repeat content-box padding-box subtract luminance;
26831        }
26832    "#},
26833      Browsers {
26834        chrome: Some(90 << 16),
26835        ..Browsers::default()
26836      },
26837    );
26838
26839    test(
26840      r#"
26841        .foo {
26842          mask: none center / 100% no-repeat;
26843          mask-image: var(--svg);
26844        }
26845      "#,
26846      indoc! { r#"
26847        .foo {
26848          mask: none center / 100% no-repeat;
26849          mask-image: var(--svg);
26850        }
26851      "#},
26852    );
26853
26854    prefix_test(
26855      r#"
26856        .foo {
26857          mask-composite: subtract;
26858        }
26859      "#,
26860      indoc! { r#"
26861        .foo {
26862          -webkit-mask-composite: source-out;
26863          mask-composite: subtract;
26864        }
26865    "#},
26866      Browsers {
26867        chrome: Some(90 << 16),
26868        ..Browsers::default()
26869      },
26870    );
26871
26872    prefix_test(
26873      r#"
26874        .foo {
26875          mask-mode: luminance;
26876        }
26877      "#,
26878      indoc! { r#"
26879        .foo {
26880          -webkit-mask-source-type: luminance;
26881          mask-mode: luminance;
26882        }
26883    "#},
26884      Browsers {
26885        chrome: Some(90 << 16),
26886        ..Browsers::default()
26887      },
26888    );
26889
26890    prefix_test(
26891      r#"
26892        .foo {
26893          mask-border: url('border-mask.png') 25 / 35px / 12px space luminance;
26894        }
26895      "#,
26896      indoc! { r#"
26897        .foo {
26898          -webkit-mask-box-image: url("border-mask.png") 25 / 35px / 12px space;
26899          mask-border: url("border-mask.png") 25 / 35px / 12px space luminance;
26900        }
26901    "#},
26902      Browsers {
26903        chrome: Some(90 << 16),
26904        ..Browsers::default()
26905      },
26906    );
26907
26908    prefix_test(
26909      r#"
26910        .foo {
26911          mask-border: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 25 / 35px / 12px space luminance;
26912        }
26913      "#,
26914      indoc! { r#"
26915        .foo {
26916          -webkit-mask-box-image: linear-gradient(#ff0f0e, #7773ff) 25 / 35px / 12px space;
26917          mask-border: linear-gradient(#ff0f0e, #7773ff) 25 / 35px / 12px space luminance;
26918          -webkit-mask-box-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 25 / 35px / 12px space;
26919          mask-border: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 25 / 35px / 12px space luminance;
26920        }
26921    "#},
26922      Browsers {
26923        chrome: Some(90 << 16),
26924        ..Browsers::default()
26925      },
26926    );
26927
26928    prefix_test(
26929      r#"
26930        .foo {
26931          mask-border-source: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
26932        }
26933      "#,
26934      indoc! { r#"
26935        .foo {
26936          -webkit-mask-box-image-source: linear-gradient(#ff0f0e, #7773ff);
26937          mask-border-source: linear-gradient(#ff0f0e, #7773ff);
26938          -webkit-mask-box-image-source: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
26939          mask-border-source: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
26940        }
26941    "#},
26942      Browsers {
26943        chrome: Some(90 << 16),
26944        ..Browsers::default()
26945      },
26946    );
26947
26948    prefix_test(
26949      r#"
26950        .foo {
26951          mask-border-source: url(foo.png);
26952          mask-border-slice: 10 40 10 40;
26953          mask-border-width: 10px;
26954          mask-border-outset: 0;
26955          mask-border-repeat: round round;
26956          mask-border-mode: luminance;
26957        }
26958      "#,
26959      indoc! { r#"
26960        .foo {
26961          -webkit-mask-box-image: url("foo.png") 10 40 / 10px round;
26962          mask-border: url("foo.png") 10 40 / 10px round luminance;
26963        }
26964    "#},
26965      Browsers {
26966        chrome: Some(90 << 16),
26967        ..Browsers::default()
26968      },
26969    );
26970
26971    prefix_test(
26972      r#"
26973        .foo {
26974          -webkit-mask-box-image-source: url(foo.png);
26975          -webkit-mask-box-image-slice: 10 40 10 40;
26976          -webkit-mask-box-image-width: 10px;
26977          -webkit-mask-box-image-outset: 0;
26978          -webkit-mask-box-image-repeat: round round;
26979        }
26980      "#,
26981      indoc! { r#"
26982        .foo {
26983          -webkit-mask-box-image: url("foo.png") 10 40 / 10px round;
26984        }
26985    "#},
26986      Browsers {
26987        chrome: Some(90 << 16),
26988        ..Browsers::default()
26989      },
26990    );
26991
26992    prefix_test(
26993      r#"
26994        .foo {
26995          mask-border-slice: 10 40 10 40;
26996        }
26997      "#,
26998      indoc! { r#"
26999        .foo {
27000          -webkit-mask-box-image-slice: 10 40;
27001          mask-border-slice: 10 40;
27002        }
27003    "#},
27004      Browsers {
27005        chrome: Some(90 << 16),
27006        ..Browsers::default()
27007      },
27008    );
27009
27010    prefix_test(
27011      r#"
27012        .foo {
27013          mask-border-slice: var(--foo);
27014        }
27015      "#,
27016      indoc! { r#"
27017        .foo {
27018          -webkit-mask-box-image-slice: var(--foo);
27019          mask-border-slice: var(--foo);
27020        }
27021    "#},
27022      Browsers {
27023        chrome: Some(90 << 16),
27024        ..Browsers::default()
27025      },
27026    );
27027
27028    prefix_test(
27029      r#"
27030        .foo {
27031          mask-border: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) var(--foo);
27032        }
27033      "#,
27034      indoc! { r#"
27035        .foo {
27036          -webkit-mask-box-image: linear-gradient(#ff0f0e, #7773ff) var(--foo);
27037          mask-border: linear-gradient(#ff0f0e, #7773ff) var(--foo);
27038        }
27039
27040        @supports (color: lab(0% 0 0)) {
27041          .foo {
27042            -webkit-mask-box-image: linear-gradient(lab(56.208% 94.4644 98.8928), lab(51% 70.4544 -115.586)) var(--foo);
27043            mask-border: linear-gradient(lab(56.208% 94.4644 98.8928), lab(51% 70.4544 -115.586)) var(--foo);
27044          }
27045        }
27046    "#},
27047      Browsers {
27048        chrome: Some(90 << 16),
27049        ..Browsers::default()
27050      },
27051    );
27052
27053    prefix_test(
27054      r#"
27055        .foo {
27056          transition: mask 200ms;
27057        }
27058      "#,
27059      indoc! { r#"
27060        .foo {
27061          transition: -webkit-mask .2s, mask .2s;
27062        }
27063    "#},
27064      Browsers {
27065        chrome: Some(90 << 16),
27066        ..Browsers::default()
27067      },
27068    );
27069
27070    prefix_test(
27071      r#"
27072        .foo {
27073          transition: mask-border 200ms;
27074        }
27075      "#,
27076      indoc! { r#"
27077        .foo {
27078          transition: -webkit-mask-box-image .2s, mask-border .2s;
27079        }
27080    "#},
27081      Browsers {
27082        chrome: Some(90 << 16),
27083        ..Browsers::default()
27084      },
27085    );
27086
27087    prefix_test(
27088      r#"
27089        .foo {
27090          transition-property: mask;
27091        }
27092      "#,
27093      indoc! { r#"
27094        .foo {
27095          transition-property: -webkit-mask, mask;
27096        }
27097    "#},
27098      Browsers {
27099        chrome: Some(90 << 16),
27100        ..Browsers::default()
27101      },
27102    );
27103
27104    prefix_test(
27105      r#"
27106        .foo {
27107          transition-property: mask-border;
27108        }
27109      "#,
27110      indoc! { r#"
27111        .foo {
27112          transition-property: -webkit-mask-box-image, mask-border;
27113        }
27114    "#},
27115      Browsers {
27116        chrome: Some(90 << 16),
27117        ..Browsers::default()
27118      },
27119    );
27120
27121    prefix_test(
27122      r#"
27123        .foo {
27124          transition-property: mask-composite, mask-mode;
27125        }
27126      "#,
27127      indoc! { r#"
27128        .foo {
27129          transition-property: -webkit-mask-composite, mask-composite, -webkit-mask-source-type, mask-mode;
27130        }
27131    "#},
27132      Browsers {
27133        chrome: Some(90 << 16),
27134        ..Browsers::default()
27135      },
27136    );
27137  }
27138
27139  #[test]
27140  fn test_filter() {
27141    minify_test(
27142      ".foo { filter: url('filters.svg#filter-id'); }",
27143      ".foo{filter:url(filters.svg#filter-id)}",
27144    );
27145    minify_test(".foo { filter: blur(5px); }", ".foo{filter:blur(5px)}");
27146    minify_test(".foo { filter: blur(0px); }", ".foo{filter:blur()}");
27147    minify_test(".foo { filter: brightness(10%); }", ".foo{filter:brightness(10%)}");
27148    minify_test(".foo { filter: brightness(100%); }", ".foo{filter:brightness()}");
27149    minify_test(
27150      ".foo { filter: drop-shadow(16px 16px 20px yellow); }",
27151      ".foo{filter:drop-shadow(16px 16px 20px #ff0)}",
27152    );
27153    minify_test(
27154      ".foo { filter: contrast(175%) brightness(3%); }",
27155      ".foo{filter:contrast(175%)brightness(3%)}",
27156    );
27157    minify_test(".foo { filter: hue-rotate(0) }", ".foo{filter:hue-rotate()}");
27158
27159    prefix_test(
27160      ".foo { filter: blur(5px) }",
27161      indoc! { r#"
27162        .foo {
27163          -webkit-filter: blur(5px);
27164          filter: blur(5px);
27165        }
27166      "#},
27167      Browsers {
27168        chrome: Some(20 << 16),
27169        ..Browsers::default()
27170      },
27171    );
27172
27173    prefix_test(
27174      ".foo { filter: blur(5px) }",
27175      indoc! { r#"
27176        .foo {
27177          filter: blur(5px);
27178        }
27179      "#},
27180      Browsers {
27181        chrome: Some(80 << 16),
27182        ..Browsers::default()
27183      },
27184    );
27185
27186    prefix_test(
27187      ".foo { backdrop-filter: blur(5px) }",
27188      indoc! { r#"
27189        .foo {
27190          backdrop-filter: blur(5px);
27191        }
27192      "#},
27193      Browsers {
27194        chrome: Some(80 << 16),
27195        ..Browsers::default()
27196      },
27197    );
27198
27199    prefix_test(
27200      ".foo { backdrop-filter: blur(5px) }",
27201      indoc! { r#"
27202        .foo {
27203          -webkit-backdrop-filter: blur(5px);
27204          backdrop-filter: blur(5px);
27205        }
27206      "#},
27207      Browsers {
27208        safari: Some(15 << 16),
27209        ..Browsers::default()
27210      },
27211    );
27212    prefix_test(
27213      r#"
27214      .foo {
27215        -webkit-backdrop-filter: blur(8px);
27216        backdrop-filter: blur(8px);
27217      }
27218      "#,
27219      indoc! {r#"
27220      .foo {
27221        -webkit-backdrop-filter: blur(8px);
27222        backdrop-filter: blur(8px);
27223      }
27224      "#},
27225      Browsers {
27226        safari: Some(16 << 16),
27227        ..Browsers::default()
27228      },
27229    );
27230
27231    prefix_test(
27232      ".foo { filter: var(--foo) }",
27233      indoc! { r#"
27234        .foo {
27235          -webkit-filter: var(--foo);
27236          filter: var(--foo);
27237        }
27238      "#},
27239      Browsers {
27240        chrome: Some(20 << 16),
27241        ..Browsers::default()
27242      },
27243    );
27244
27245    prefix_test(
27246      ".foo { filter: drop-shadow(16px 16px 20px lab(40% 56.6 39)) }",
27247      indoc! { r#"
27248        .foo {
27249          -webkit-filter: drop-shadow(16px 16px 20px #b32323);
27250          filter: drop-shadow(16px 16px 20px #b32323);
27251          filter: drop-shadow(16px 16px 20px lab(40% 56.6 39));
27252        }
27253      "#},
27254      Browsers {
27255        chrome: Some(20 << 16),
27256        ..Browsers::default()
27257      },
27258    );
27259
27260    prefix_test(
27261      ".foo { filter: contrast(175%) drop-shadow(16px 16px 20px lab(40% 56.6 39)) }",
27262      indoc! { r#"
27263        .foo {
27264          filter: contrast(175%) drop-shadow(16px 16px 20px #b32323);
27265          filter: contrast(175%) drop-shadow(16px 16px 20px lab(40% 56.6 39));
27266        }
27267      "#},
27268      Browsers {
27269        chrome: Some(4 << 16),
27270        ..Browsers::default()
27271      },
27272    );
27273
27274    prefix_test(
27275      ".foo { filter: drop-shadow(16px 16px 20px lab(40% 56.6 39)) drop-shadow(16px 16px 20px yellow) }",
27276      indoc! { r#"
27277        .foo {
27278          filter: drop-shadow(16px 16px 20px #b32323) drop-shadow(16px 16px 20px #ff0);
27279          filter: drop-shadow(16px 16px 20px lab(40% 56.6 39)) drop-shadow(16px 16px 20px #ff0);
27280        }
27281      "#},
27282      Browsers {
27283        chrome: Some(4 << 16),
27284        ..Browsers::default()
27285      },
27286    );
27287
27288    prefix_test(
27289      ".foo { filter: var(--foo) drop-shadow(16px 16px 20px lab(40% 56.6 39)) }",
27290      indoc! { r#"
27291        .foo {
27292          filter: var(--foo) drop-shadow(16px 16px 20px #b32323);
27293        }
27294
27295        @supports (color: lab(0% 0 0)) {
27296          .foo {
27297            filter: var(--foo) drop-shadow(16px 16px 20px lab(40% 56.6 39));
27298          }
27299        }
27300      "#},
27301      Browsers {
27302        chrome: Some(4 << 16),
27303        ..Browsers::default()
27304      },
27305    );
27306  }
27307
27308  #[test]
27309  fn test_viewport() {
27310    minify_test(
27311      r#"
27312    @viewport {
27313      width: 100vw;
27314    }"#,
27315      "@viewport{width:100vw}",
27316    );
27317    minify_test(
27318      r#"
27319    @-ms-viewport {
27320      width: device-width;
27321    }"#,
27322      "@-ms-viewport{width:device-width}",
27323    );
27324  }
27325
27326  #[test]
27327  fn test_at_scope() {
27328    minify_test(
27329      r#"
27330      @scope {
27331        .foo {
27332          display: flex;
27333        }
27334      }
27335      "#,
27336      "@scope{.foo{display:flex}}",
27337    );
27338    minify_test(
27339      r#"
27340      @scope {
27341        :scope {
27342          display: flex;
27343          color: lightblue;
27344        }
27345      }"#,
27346      "@scope{:scope{color:#add8e6;display:flex}}",
27347    );
27348    minify_test(
27349      r#"
27350      @scope (.light-scheme) {
27351        a { color: yellow; }
27352      }
27353      "#,
27354      "@scope(.light-scheme){a{color:#ff0}}",
27355    );
27356    minify_test(
27357      r#"
27358      @scope (.media-object) to (.content > *) {
27359        a { color: yellow; }
27360      }
27361      "#,
27362      "@scope(.media-object) to (.content>*){a{color:#ff0}}",
27363    );
27364    minify_test(
27365      r#"
27366      @scope to (.content > *) {
27367        a { color: yellow; }
27368      }
27369      "#,
27370      "@scope to (.content>*){a{color:#ff0}}",
27371    );
27372    minify_test(
27373      r#"
27374      @scope (#my-component) {
27375        & { color: yellow; }
27376      }
27377      "#,
27378      "@scope(#my-component){&{color:#ff0}}",
27379    );
27380    minify_test(
27381      r#"
27382      @scope (.parent-scope) {
27383        @scope (:scope > .child-scope) to (:scope .limit) {
27384          .content { color: yellow; }
27385        }
27386      }
27387      "#,
27388      "@scope(.parent-scope){@scope(:scope>.child-scope) to (:scope .limit){.content{color:#ff0}}}",
27389    );
27390    minify_test(
27391      r#"
27392      .foo {
27393        @scope (.bar) {
27394          color: yellow;
27395        }
27396      }
27397      "#,
27398      ".foo{@scope(.bar){color:#ff0}}",
27399    );
27400    nesting_test(
27401      r#"
27402      .foo {
27403        @scope (.bar) {
27404          color: yellow;
27405        }
27406      }
27407      "#,
27408      indoc! {r#"
27409        @scope (.bar) {
27410          color: #ff0;
27411        }
27412      "#},
27413    );
27414    nesting_test(
27415      r#"
27416      .parent {
27417        color: blue;
27418
27419        @scope (& > .scope) to (& .limit) {
27420          & .content {
27421            color: yellow;
27422          }
27423        }
27424      }
27425      "#,
27426      indoc! {r#"
27427        .parent {
27428          color: #00f;
27429        }
27430
27431        @scope (.parent > .scope) to (.parent > .scope .limit) {
27432          :scope .content {
27433            color: #ff0;
27434          }
27435        }
27436      "#},
27437    );
27438  }
27439
27440  #[test]
27441  fn test_custom_media() {
27442    custom_media_test(
27443      r#"
27444      @custom-media --modern (color), (hover);
27445
27446      @media (--modern) and (width > 1024px) {
27447        .a {
27448          color: green;
27449        }
27450      }
27451      "#,
27452      indoc! {r#"
27453      @media ((color) or (hover)) and (width > 1024px) {
27454        .a {
27455          color: green;
27456        }
27457      }
27458      "#},
27459    );
27460
27461    custom_media_test(
27462      r#"
27463      @custom-media --color (color);
27464
27465      @media (--color) and (width > 1024px) {
27466        .a {
27467          color: green;
27468        }
27469      }
27470      "#,
27471      indoc! {r#"
27472      @media (color) and (width > 1024px) {
27473        .a {
27474          color: green;
27475        }
27476      }
27477      "#},
27478    );
27479
27480    custom_media_test(
27481      r#"
27482      @custom-media --a (color);
27483      @custom-media --b (--a);
27484
27485      @media (--b) and (width > 1024px) {
27486        .a {
27487          color: green;
27488        }
27489      }
27490      "#,
27491      indoc! {r#"
27492      @media (color) and (width > 1024px) {
27493        .a {
27494          color: green;
27495        }
27496      }
27497      "#},
27498    );
27499
27500    custom_media_test(
27501      r#"
27502      @custom-media --not-color not (color);
27503
27504      @media not (--not-color) {
27505        .a {
27506          color: green;
27507        }
27508      }
27509      "#,
27510      indoc! {r#"
27511      @media (color) {
27512        .a {
27513          color: green;
27514        }
27515      }
27516      "#},
27517    );
27518
27519    custom_media_test(
27520      r#"
27521      @custom-media --color-print print and (color);
27522
27523      @media (--color-print) {
27524        .a {
27525          color: green;
27526        }
27527      }
27528      "#,
27529      indoc! {r#"
27530      @media print and (color) {
27531        .a {
27532          color: green;
27533        }
27534      }
27535      "#},
27536    );
27537
27538    custom_media_test(
27539      r#"
27540      @custom-media --color-print print and (color);
27541
27542      @media print and (--color-print) {
27543        .a {
27544          color: green;
27545        }
27546      }
27547      "#,
27548      indoc! {r#"
27549      @media print and (color) {
27550        .a {
27551          color: green;
27552        }
27553      }
27554      "#},
27555    );
27556
27557    custom_media_test(
27558      r#"
27559      @custom-media --not-color-print not print and (color);
27560
27561      @media not print and (--not-color-print) {
27562        .a {
27563          color: green;
27564        }
27565      }
27566      "#,
27567      indoc! {r#"
27568      @media not print and (color) {
27569        .a {
27570          color: green;
27571        }
27572      }
27573      "#},
27574    );
27575
27576    custom_media_test(
27577      r#"
27578      @custom-media --print print;
27579
27580      @media (--print) {
27581        .a {
27582          color: green;
27583        }
27584      }
27585      "#,
27586      indoc! {r#"
27587      @media print {
27588        .a {
27589          color: green;
27590        }
27591      }
27592      "#},
27593    );
27594
27595    custom_media_test(
27596      r#"
27597      @custom-media --print print;
27598
27599      @media not (--print) {
27600        .a {
27601          color: green;
27602        }
27603      }
27604      "#,
27605      indoc! {r#"
27606      @media not print {
27607        .a {
27608          color: green;
27609        }
27610      }
27611      "#},
27612    );
27613
27614    custom_media_test(
27615      r#"
27616      @custom-media --print not print;
27617
27618      @media not (--print) {
27619        .a {
27620          color: green;
27621        }
27622      }
27623      "#,
27624      indoc! {r#"
27625      @media print {
27626        .a {
27627          color: green;
27628        }
27629      }
27630      "#},
27631    );
27632
27633    custom_media_test(
27634      r#"
27635      @custom-media --print print;
27636
27637      @media ((--print)) {
27638        .a {
27639          color: green;
27640        }
27641      }
27642      "#,
27643      indoc! {r#"
27644      @media print {
27645        .a {
27646          color: green;
27647        }
27648      }
27649      "#},
27650    );
27651
27652    custom_media_test(
27653      r#"
27654      @custom-media --color (color);
27655      @custom-media --print print;
27656
27657      @media (--print) and (--color) {
27658        .a {
27659          color: green;
27660        }
27661      }
27662      "#,
27663      indoc! {r#"
27664      @media print and (color) {
27665        .a {
27666          color: green;
27667        }
27668      }
27669      "#},
27670    );
27671
27672    custom_media_test(
27673      r#"
27674      @custom-media --color (color);
27675      @custom-media --not-print not print;
27676
27677      @media (--not-print) and (--color) {
27678        .a {
27679          color: green;
27680        }
27681      }
27682      "#,
27683      indoc! {r#"
27684      @media not print and (color) {
27685        .a {
27686          color: green;
27687        }
27688      }
27689      "#},
27690    );
27691
27692    custom_media_test(
27693      r#"
27694      @custom-media --color (color);
27695      @custom-media --screen screen;
27696      @custom-media --print print;
27697
27698      @media (--print) and (--color), (--screen) and (--color) {
27699        .a {
27700          color: green;
27701        }
27702      }
27703      "#,
27704      indoc! {r#"
27705      @media print and (color), screen and (color) {
27706        .a {
27707          color: green;
27708        }
27709      }
27710      "#},
27711    );
27712
27713    custom_media_test(
27714      r#"
27715      @custom-media --color print and (color), print and (script);
27716
27717      @media (--color) {
27718        .a {
27719          color: green;
27720        }
27721      }
27722      "#,
27723      indoc! {r#"
27724      @media print and ((color) or (script)) {
27725        .a {
27726          color: green;
27727        }
27728      }
27729      "#},
27730    );
27731
27732    custom_media_test(
27733      r#"
27734      @custom-media --color (color);
27735      @custom-media --not-color not all and (--color);
27736
27737      @media (--not-color) {
27738        .a {
27739          color: green;
27740        }
27741      }
27742      "#,
27743      indoc! {r#"
27744        @media not all and (color) {
27745          .a {
27746            color: green;
27747          }
27748        }
27749      "#},
27750    );
27751
27752    custom_media_test(
27753      r#"
27754      @custom-media --color (color);
27755
27756      @media not all and (--color) {
27757        .a {
27758          color: green;
27759        }
27760      }
27761      "#,
27762      indoc! {r#"
27763        @media not all and (color) {
27764          .a {
27765            color: green;
27766          }
27767        }
27768      "#},
27769    );
27770
27771    custom_media_test(
27772      r#"
27773      @media (--print) {
27774        .a {
27775          color: green;
27776        }
27777      }
27778
27779      @custom-media --print print;
27780      "#,
27781      indoc! {r#"
27782      @media print {
27783        .a {
27784          color: green;
27785        }
27786      }
27787      "#},
27788    );
27789
27790    custom_media_test(
27791      r#"
27792      @custom-media --not-width not (min-width: 300px);
27793      @media screen and ((prefers-color-scheme: dark) or (--not-width)) {
27794        .foo {
27795          order: 6;
27796        }
27797      }
27798      "#,
27799      indoc! {r#"
27800      @media screen and ((prefers-color-scheme: dark) or ((width < 300px))) {
27801        .foo {
27802          order: 6;
27803        }
27804      }
27805      "#},
27806    );
27807
27808    fn custom_media_error_test(source: &str, err: Error<MinifyErrorKind>) {
27809      let mut stylesheet = StyleSheet::parse(
27810        &source,
27811        ParserOptions {
27812          filename: "test.css".into(),
27813          flags: ParserFlags::CUSTOM_MEDIA,
27814          ..ParserOptions::default()
27815        },
27816      )
27817      .unwrap();
27818      let res = stylesheet.minify(MinifyOptions {
27819        targets: Browsers {
27820          chrome: Some(95 << 16),
27821          ..Browsers::default()
27822        }
27823        .into(),
27824        ..MinifyOptions::default()
27825      });
27826      assert_eq!(res, Err(err))
27827    }
27828
27829    custom_media_error_test(
27830      r#"
27831      @custom-media --color-print print and (color);
27832
27833      @media screen and (--color-print) {
27834        .a {
27835          color: green;
27836        }
27837      }
27838      "#,
27839      Error {
27840        kind: MinifyErrorKind::UnsupportedCustomMediaBooleanLogic {
27841          custom_media_loc: Location {
27842            source_index: 0,
27843            line: 1,
27844            column: 7,
27845          },
27846        },
27847        loc: Some(ErrorLocation {
27848          filename: "test.css".into(),
27849          line: 3,
27850          column: 7,
27851        }),
27852      },
27853    );
27854
27855    custom_media_error_test(
27856      r#"
27857      @custom-media --color-print print and (color);
27858
27859      @media not print and (--color-print) {
27860        .a {
27861          color: green;
27862        }
27863      }
27864      "#,
27865      Error {
27866        kind: MinifyErrorKind::UnsupportedCustomMediaBooleanLogic {
27867          custom_media_loc: Location {
27868            source_index: 0,
27869            line: 1,
27870            column: 7,
27871          },
27872        },
27873        loc: Some(ErrorLocation {
27874          filename: "test.css".into(),
27875          line: 3,
27876          column: 7,
27877        }),
27878      },
27879    );
27880
27881    custom_media_error_test(
27882      r#"
27883      @custom-media --color-print print and (color);
27884      @custom-media --color-screen screen and (color);
27885
27886      @media (--color-print) or (--color-screen) {}
27887      "#,
27888      Error {
27889        kind: MinifyErrorKind::UnsupportedCustomMediaBooleanLogic {
27890          custom_media_loc: Location {
27891            source_index: 0,
27892            line: 2,
27893            column: 7,
27894          },
27895        },
27896        loc: Some(ErrorLocation {
27897          filename: "test.css".into(),
27898          line: 4,
27899          column: 7,
27900        }),
27901      },
27902    );
27903
27904    custom_media_error_test(
27905      r#"
27906      @custom-media --color-print print and (color);
27907      @custom-media --color-screen screen and (color);
27908
27909      @media (--color-print) and (--color-screen) {}
27910      "#,
27911      Error {
27912        kind: MinifyErrorKind::UnsupportedCustomMediaBooleanLogic {
27913          custom_media_loc: Location {
27914            source_index: 0,
27915            line: 2,
27916            column: 7,
27917          },
27918        },
27919        loc: Some(ErrorLocation {
27920          filename: "test.css".into(),
27921          line: 4,
27922          column: 7,
27923        }),
27924      },
27925    );
27926
27927    custom_media_error_test(
27928      r#"
27929      @custom-media --screen screen;
27930      @custom-media --print print;
27931
27932      @media (--print) and (--screen) {}
27933      "#,
27934      Error {
27935        kind: MinifyErrorKind::UnsupportedCustomMediaBooleanLogic {
27936          custom_media_loc: Location {
27937            source_index: 0,
27938            line: 1,
27939            column: 7,
27940          },
27941        },
27942        loc: Some(ErrorLocation {
27943          filename: "test.css".into(),
27944          line: 4,
27945          column: 7,
27946        }),
27947      },
27948    );
27949
27950    custom_media_error_test(
27951      r#"
27952      @custom-media --not-print not print and (color);
27953      @custom-media --not-screen not screen and (color);
27954
27955      @media ((script) or ((--not-print) and (--not-screen))) {
27956        .a {
27957          color: green;
27958        }
27959      }
27960      "#,
27961      Error {
27962        kind: MinifyErrorKind::UnsupportedCustomMediaBooleanLogic {
27963          custom_media_loc: Location {
27964            source_index: 0,
27965            line: 2,
27966            column: 7,
27967          },
27968        },
27969        loc: Some(ErrorLocation {
27970          filename: "test.css".into(),
27971          line: 4,
27972          column: 7,
27973        }),
27974      },
27975    );
27976
27977    custom_media_error_test(
27978      r#"
27979      @custom-media --color screen and (color), print and (color);
27980
27981      @media (--color) {
27982        .a {
27983          color: green;
27984        }
27985      }
27986      "#,
27987      Error {
27988        kind: MinifyErrorKind::UnsupportedCustomMediaBooleanLogic {
27989          custom_media_loc: Location {
27990            source_index: 0,
27991            line: 1,
27992            column: 7,
27993          },
27994        },
27995        loc: Some(ErrorLocation {
27996          filename: "test.css".into(),
27997          line: 3,
27998          column: 7,
27999        }),
28000      },
28001    );
28002
28003    custom_media_error_test(
28004      r#"
28005      @media (--not-defined) {
28006        .a {
28007          color: green;
28008        }
28009      }
28010      "#,
28011      Error {
28012        kind: MinifyErrorKind::CustomMediaNotDefined {
28013          name: "--not-defined".into(),
28014        },
28015        loc: Some(ErrorLocation {
28016          filename: "test.css".into(),
28017          line: 1,
28018          column: 7,
28019        }),
28020      },
28021    );
28022
28023    custom_media_error_test(
28024      r#"
28025      @custom-media --circular-mq-a (--circular-mq-b);
28026      @custom-media --circular-mq-b (--circular-mq-a);
28027
28028      @media (--circular-mq-a) {
28029        body {
28030          order: 3;
28031        }
28032      }
28033      "#,
28034      Error {
28035        kind: MinifyErrorKind::CircularCustomMedia {
28036          name: "--circular-mq-a".into(),
28037        },
28038        loc: Some(ErrorLocation {
28039          filename: "test.css".into(),
28040          line: 4,
28041          column: 7,
28042        }),
28043      },
28044    );
28045  }
28046
28047  #[test]
28048  fn test_dependencies() {
28049    fn dep_test(source: &str, expected: &str, deps: Vec<(&str, &str)>) {
28050      let mut stylesheet = StyleSheet::parse(
28051        &source,
28052        ParserOptions {
28053          filename: "test.css".into(),
28054          ..ParserOptions::default()
28055        },
28056      )
28057      .unwrap();
28058      stylesheet.minify(MinifyOptions::default()).unwrap();
28059      let res = stylesheet
28060        .to_css(PrinterOptions {
28061          analyze_dependencies: Some(Default::default()),
28062          minify: true,
28063          ..PrinterOptions::default()
28064        })
28065        .unwrap();
28066      assert_eq!(res.code, expected);
28067      let dependencies = res.dependencies.unwrap();
28068      assert_eq!(dependencies.len(), deps.len());
28069      for (i, (url, placeholder)) in deps.into_iter().enumerate() {
28070        match &dependencies[i] {
28071          Dependency::Url(dep) => {
28072            assert_eq!(dep.url, url);
28073            assert_eq!(dep.placeholder, placeholder);
28074          }
28075          Dependency::Import(dep) => {
28076            assert_eq!(dep.url, url);
28077            assert_eq!(dep.placeholder, placeholder);
28078          }
28079        }
28080      }
28081    }
28082
28083    fn dep_error_test(source: &str, error: PrinterErrorKind) {
28084      let stylesheet = StyleSheet::parse(&source, ParserOptions::default()).unwrap();
28085      let res = stylesheet.to_css(PrinterOptions {
28086        analyze_dependencies: Some(Default::default()),
28087        ..PrinterOptions::default()
28088      });
28089      match res {
28090        Err(e) => assert_eq!(e.kind, error),
28091        _ => unreachable!(),
28092      }
28093    }
28094
28095    dep_test(
28096      ".foo { background: image-set('./img12x.png', './img21x.png' 2x)}",
28097      ".foo{background:image-set(\"hXFI8W\" 1x,\"5TkpBa\" 2x)}",
28098      vec![("./img12x.png", "hXFI8W"), ("./img21x.png", "5TkpBa")],
28099    );
28100
28101    dep_test(
28102      ".foo { background: image-set(url(./img12x.png), url('./img21x.png') 2x)}",
28103      ".foo{background:image-set(\"hXFI8W\" 1x,\"5TkpBa\" 2x)}",
28104      vec![("./img12x.png", "hXFI8W"), ("./img21x.png", "5TkpBa")],
28105    );
28106
28107    dep_test(
28108      ".foo { --test: url(/foo.png) }",
28109      ".foo{--test:url(\"lDnnrG\")}",
28110      vec![("/foo.png", "lDnnrG")],
28111    );
28112
28113    dep_test(
28114      ".foo { --test: url(\"/foo.png\") }",
28115      ".foo{--test:url(\"lDnnrG\")}",
28116      vec![("/foo.png", "lDnnrG")],
28117    );
28118
28119    dep_test(
28120      ".foo { --test: url(\"http://example.com/foo.png\") }",
28121      ".foo{--test:url(\"3X1zSW\")}",
28122      vec![("http://example.com/foo.png", "3X1zSW")],
28123    );
28124
28125    dep_test(
28126      ".foo { --test: url(\"data:image/svg+xml;utf8,<svg></svg>\") }",
28127      ".foo{--test:url(\"-vl-rG\")}",
28128      vec![("data:image/svg+xml;utf8,<svg></svg>", "-vl-rG")],
28129    );
28130
28131    dep_test(
28132      ".foo { background: url(\"foo.png\") var(--test) }",
28133      ".foo{background:url(\"Vwkwkq\") var(--test)}",
28134      vec![("foo.png", "Vwkwkq")],
28135    );
28136
28137    dep_error_test(
28138      ".foo { --test: url(\"foo.png\") }",
28139      PrinterErrorKind::AmbiguousUrlInCustomProperty { url: "foo.png".into() },
28140    );
28141
28142    dep_error_test(
28143      ".foo { --test: url(foo.png) }",
28144      PrinterErrorKind::AmbiguousUrlInCustomProperty { url: "foo.png".into() },
28145    );
28146
28147    dep_error_test(
28148      ".foo { --test: url(./foo.png) }",
28149      PrinterErrorKind::AmbiguousUrlInCustomProperty {
28150        url: "./foo.png".into(),
28151      },
28152    );
28153
28154    dep_test(
28155      ".foo { behavior: url(#foo) }",
28156      ".foo{behavior:url(\"Zn9-2q\")}",
28157      vec![("#foo", "Zn9-2q")],
28158    );
28159
28160    dep_test(
28161      ".foo { --foo: url(#foo) }",
28162      ".foo{--foo:url(\"Zn9-2q\")}",
28163      vec![("#foo", "Zn9-2q")],
28164    );
28165
28166    dep_test(
28167      "@import \"test.css\"; .foo { color: red }",
28168      "@import \"hHsogW\";.foo{color:red}",
28169      vec![("test.css", "hHsogW")],
28170    );
28171  }
28172
28173  #[test]
28174  fn test_api() {
28175    let stylesheet = StyleSheet::parse(".foo:hover { color: red }", ParserOptions::default()).unwrap();
28176    match &stylesheet.rules.0[0] {
28177      CssRule::Style(s) => {
28178        assert_eq!(&s.selectors.to_string(), ".foo:hover");
28179      }
28180      _ => unreachable!(),
28181    }
28182
28183    let color = CssColor::parse_string("#f0f").unwrap();
28184    assert_eq!(color.to_css_string(PrinterOptions::default()).unwrap(), "#f0f");
28185
28186    let rule = CssRule::parse_string(".foo { color: red }", ParserOptions::default()).unwrap();
28187    assert_eq!(
28188      rule.to_css_string(PrinterOptions::default()).unwrap(),
28189      indoc! {r#"
28190    .foo {
28191      color: red;
28192    }"#}
28193    );
28194
28195    let property = Property::parse_string("color".into(), "#f0f", ParserOptions::default()).unwrap();
28196    assert_eq!(
28197      property.to_css_string(false, PrinterOptions::default()).unwrap(),
28198      "color: #f0f"
28199    );
28200    assert_eq!(
28201      property.to_css_string(true, PrinterOptions::default()).unwrap(),
28202      "color: #f0f !important"
28203    );
28204
28205    let code = indoc! { r#"
28206      .foo {
28207        color: green;
28208      }
28209
28210      .bar {
28211        color: red;
28212        background: pink;
28213      }
28214
28215      @media print {
28216        .baz {
28217          color: green;
28218        }
28219      }
28220    "#};
28221    let stylesheet = StyleSheet::parse(code, ParserOptions::default()).unwrap();
28222    if let CssRule::Style(style) = &stylesheet.rules.0[1] {
28223      let (key, val) = style.property_location(code, 0).unwrap();
28224      assert_eq!(
28225        key,
28226        SourceLocation { line: 5, column: 3 }..SourceLocation { line: 5, column: 8 }
28227      );
28228      assert_eq!(
28229        val,
28230        SourceLocation { line: 5, column: 10 }..SourceLocation { line: 5, column: 13 }
28231      );
28232    }
28233
28234    if let CssRule::Style(style) = &stylesheet.rules.0[1] {
28235      let (key, val) = style.property_location(code, 1).unwrap();
28236      assert_eq!(
28237        key,
28238        SourceLocation { line: 6, column: 3 }..SourceLocation { line: 6, column: 13 }
28239      );
28240      assert_eq!(
28241        val,
28242        SourceLocation { line: 6, column: 15 }..SourceLocation { line: 6, column: 19 }
28243      );
28244    }
28245    if let CssRule::Media(media) = &stylesheet.rules.0[2] {
28246      if let CssRule::Style(style) = &media.rules.0[0] {
28247        let (key, val) = style.property_location(code, 0).unwrap();
28248        assert_eq!(
28249          key,
28250          SourceLocation { line: 11, column: 5 }..SourceLocation { line: 11, column: 10 }
28251        );
28252        assert_eq!(
28253          val,
28254          SourceLocation { line: 11, column: 12 }..SourceLocation { line: 11, column: 17 }
28255        );
28256      }
28257    }
28258
28259    let mut property = Property::Transform(Default::default(), VendorPrefix::WebKit);
28260    property.set_prefix(VendorPrefix::None);
28261    assert_eq!(property, Property::Transform(Default::default(), VendorPrefix::None));
28262    property.set_prefix(VendorPrefix::Moz);
28263    assert_eq!(property, Property::Transform(Default::default(), VendorPrefix::Moz));
28264    property.set_prefix(VendorPrefix::WebKit | VendorPrefix::Moz);
28265    assert_eq!(
28266      property,
28267      Property::Transform(Default::default(), VendorPrefix::WebKit | VendorPrefix::Moz)
28268    );
28269
28270    let mut property = Property::TextDecorationLine(Default::default(), VendorPrefix::None);
28271    property.set_prefix(VendorPrefix::Ms);
28272    assert_eq!(
28273      property,
28274      Property::TextDecorationLine(Default::default(), VendorPrefix::None)
28275    );
28276    property.set_prefix(VendorPrefix::WebKit | VendorPrefix::Moz | VendorPrefix::Ms);
28277    assert_eq!(
28278      property,
28279      Property::TextDecorationLine(Default::default(), VendorPrefix::WebKit | VendorPrefix::Moz)
28280    );
28281
28282    let mut property = Property::AccentColor(Default::default());
28283    property.set_prefix(VendorPrefix::WebKit);
28284    assert_eq!(property, Property::AccentColor(Default::default()));
28285  }
28286
28287  #[cfg(feature = "substitute_variables")]
28288  #[test]
28289  fn test_substitute_vars() {
28290    use crate::properties::custom::TokenList;
28291    use crate::traits::ParseWithOptions;
28292
28293    fn test(property: Property, vars: HashMap<&str, &str>, expected: &str) {
28294      if let Property::Unparsed(unparsed) = property {
28295        let vars = vars
28296          .into_iter()
28297          .map(|(k, v)| {
28298            (
28299              k,
28300              TokenList::parse_string_with_options(v, ParserOptions::default()).unwrap(),
28301            )
28302          })
28303          .collect();
28304        let substituted = unparsed.substitute_variables(&vars).unwrap();
28305        assert_eq!(
28306          substituted.to_css_string(false, PrinterOptions::default()).unwrap(),
28307          expected
28308        );
28309      } else {
28310        panic!("Not an unparsed property");
28311      }
28312    }
28313
28314    let property = Property::parse_string("color".into(), "var(--test)", ParserOptions::default()).unwrap();
28315    test(property, HashMap::from([("--test", "yellow")]), "color: #ff0");
28316
28317    let property =
28318      Property::parse_string("color".into(), "var(--test, var(--foo))", ParserOptions::default()).unwrap();
28319    test(property, HashMap::from([("--foo", "yellow")]), "color: #ff0");
28320    let property = Property::parse_string(
28321      "color".into(),
28322      "var(--test, var(--foo, yellow))",
28323      ParserOptions::default(),
28324    )
28325    .unwrap();
28326    test(property, HashMap::new(), "color: #ff0");
28327
28328    let property =
28329      Property::parse_string("width".into(), "calc(var(--a) + var(--b))", ParserOptions::default()).unwrap();
28330    test(property, HashMap::from([("--a", "2px"), ("--b", "4px")]), "width: 6px");
28331
28332    let property = Property::parse_string("color".into(), "var(--a)", ParserOptions::default()).unwrap();
28333    test(
28334      property,
28335      HashMap::from([("--a", "var(--b)"), ("--b", "yellow")]),
28336      "color: #ff0",
28337    );
28338
28339    let property = Property::parse_string("color".into(), "var(--a)", ParserOptions::default()).unwrap();
28340    test(
28341      property,
28342      HashMap::from([("--a", "var(--b)"), ("--b", "var(--c)"), ("--c", "var(--a)")]),
28343      "color: var(--a)",
28344    );
28345  }
28346
28347  #[test]
28348  fn test_layer() {
28349    minify_test("@layer foo;", "@layer foo;");
28350    minify_test("@layer foo, bar;", "@layer foo,bar;");
28351    minify_test("@layer foo.bar;", "@layer foo.bar;");
28352    minify_test("@layer foo.bar, baz;", "@layer foo.bar,baz;");
28353
28354    minify_test(
28355      r#"
28356      @layer foo {
28357        .bar {
28358          color: red;
28359        }
28360      }
28361    "#,
28362      "@layer foo{.bar{color:red}}",
28363    );
28364    minify_test(
28365      r#"
28366      @layer foo.bar {
28367        .bar {
28368          color: red;
28369        }
28370      }
28371    "#,
28372      "@layer foo.bar{.bar{color:red}}",
28373    );
28374    minify_test(r#"
28375      @layer base {
28376        p { max-width: 70ch; }
28377      }
28378
28379      @layer framework {
28380        @layer base {
28381          p { margin-block: 0.75em; }
28382        }
28383
28384        @layer theme {
28385          p { color: #222; }
28386        }
28387      }
28388    "#, "@layer base{p{max-width:70ch}}@layer framework{@layer base{p{margin-block:.75em}}@layer theme{p{color:#222}}}");
28389    minify_test(
28390      r#"
28391      @layer {
28392        .bar {
28393          color: red;
28394        }
28395      }
28396    "#,
28397      "@layer{.bar{color:red}}",
28398    );
28399    minify_test(
28400      r#"
28401      @layer foo\20 bar, baz;
28402    "#,
28403      "@layer foo\\ bar,baz;",
28404    );
28405    minify_test(
28406      r#"
28407      @layer one.two\20 three\#four\.five {
28408        .bar {
28409          color: red;
28410        }
28411      }
28412    "#,
28413      "@layer one.two\\ three\\#four\\.five{.bar{color:red}}",
28414    );
28415
28416    error_test("@layer;", ParserError::UnexpectedToken(Token::Semicolon));
28417    error_test("@layer foo, bar {};", ParserError::AtRuleBodyInvalid);
28418    minify_test("@import 'test.css' layer;", "@import \"test.css\" layer;");
28419    minify_test("@import 'test.css' layer(foo);", "@import \"test.css\" layer(foo);");
28420    minify_test(
28421      "@import 'test.css' layer(foo.bar);",
28422      "@import \"test.css\" layer(foo.bar);",
28423    );
28424    minify_test(
28425      "@import 'test.css' layer(foo\\20 bar);",
28426      "@import \"test.css\" layer(foo\\ bar);",
28427    );
28428    error_test(
28429      "@import 'test.css' layer(foo, bar) {};",
28430      ParserError::UnexpectedToken(Token::Comma),
28431    );
28432    minify_test(
28433      r#"
28434      @layer one {
28435        body {
28436          background: red;
28437        }
28438      }
28439
28440      body {
28441        background: red;
28442      }
28443
28444      @layer two {
28445        body {
28446          background: green;
28447        }
28448      }
28449
28450      @layer one {
28451        body {
28452          background: yellow;
28453        }
28454      }
28455      "#,
28456      "@layer one{body{background:#ff0}}body{background:red}@layer two{body{background:green}}",
28457    );
28458  }
28459
28460  #[test]
28461  fn test_property() {
28462    minify_test(
28463      r#"
28464      @property --property-name {
28465        syntax: '<color>';
28466        inherits: false;
28467        initial-value: yellow;
28468      }
28469    "#,
28470      "@property --property-name{syntax:\"<color>\";inherits:false;initial-value:#ff0}",
28471    );
28472
28473    test(
28474      r#"
28475      @property --property-name {
28476        syntax: '*';
28477        inherits: false;
28478        initial-value: ;
28479      }
28480    "#,
28481      indoc! {r#"
28482      @property --property-name {
28483        syntax: "*";
28484        inherits: false;
28485        initial-value: ;
28486      }
28487    "#},
28488    );
28489
28490    minify_test(
28491      r#"
28492      @property --property-name {
28493        syntax: '*';
28494        inherits: false;
28495        initial-value: ;
28496      }
28497    "#,
28498      "@property --property-name{syntax:\"*\";inherits:false;initial-value:}",
28499    );
28500
28501    test(
28502      r#"
28503      @property --property-name {
28504        syntax: '*';
28505        inherits: false;
28506        initial-value:;
28507      }
28508    "#,
28509      indoc! {r#"
28510      @property --property-name {
28511        syntax: "*";
28512        inherits: false;
28513        initial-value: ;
28514      }
28515    "#},
28516    );
28517
28518    minify_test(
28519      r#"
28520      @property --property-name {
28521        syntax: '*';
28522        inherits: false;
28523        initial-value:;
28524      }
28525    "#,
28526      "@property --property-name{syntax:\"*\";inherits:false;initial-value:}",
28527    );
28528    minify_test(
28529      r#"
28530      @property --property-name {
28531        syntax: '*';
28532        inherits: false;
28533        initial-value: foo bar;
28534      }
28535    "#,
28536      "@property --property-name{syntax:\"*\";inherits:false;initial-value:foo bar}",
28537    );
28538
28539    minify_test(
28540      r#"
28541      @property --property-name {
28542        syntax: '<length>';
28543        inherits: true;
28544        initial-value: 25px;
28545      }
28546    "#,
28547      "@property --property-name{syntax:\"<length>\";inherits:true;initial-value:25px}",
28548    );
28549
28550    error_test(
28551      r#"
28552      @property --property-name {
28553        syntax: '<color>';
28554        inherits: false;
28555        initial-value: 25px;
28556      }
28557    "#,
28558      ParserError::UnexpectedToken(crate::properties::custom::Token::Dimension {
28559        has_sign: false,
28560        value: 25.0,
28561        int_value: Some(25),
28562        unit: "px".into(),
28563      }),
28564    );
28565
28566    error_test(
28567      r#"
28568      @property --property-name {
28569        syntax: '<length>';
28570        inherits: false;
28571        initial-value: var(--some-value);
28572      }
28573    "#,
28574      ParserError::UnexpectedToken(crate::properties::custom::Token::Function("var".into())),
28575    );
28576
28577    error_test(
28578      r#"
28579      @property --property-name {
28580        syntax: '<color>';
28581        inherits: false;
28582      }
28583    "#,
28584      ParserError::AtRuleBodyInvalid,
28585    );
28586
28587    minify_test(
28588      r#"
28589      @property --property-name {
28590        syntax: '*';
28591        inherits: false;
28592      }
28593    "#,
28594      "@property --property-name{syntax:\"*\";inherits:false}",
28595    );
28596
28597    error_test(
28598      r#"
28599      @property --property-name {
28600        syntax: '*';
28601      }
28602    "#,
28603      ParserError::AtRuleBodyInvalid,
28604    );
28605
28606    error_test(
28607      r#"
28608      @property --property-name {
28609        inherits: false;
28610      }
28611    "#,
28612      ParserError::AtRuleBodyInvalid,
28613    );
28614
28615    error_test(
28616      r#"
28617      @property property-name {
28618        syntax: '*';
28619        inherits: false;
28620      }
28621    "#,
28622      ParserError::UnexpectedToken(crate::properties::custom::Token::Ident("property-name".into())),
28623    );
28624
28625    minify_test(
28626      r#"
28627      @property --property-name {
28628        syntax: 'custom | <color>';
28629        inherits: false;
28630        initial-value: yellow;
28631      }
28632    "#,
28633      "@property --property-name{syntax:\"custom|<color>\";inherits:false;initial-value:#ff0}",
28634    );
28635
28636    // TODO: Re-enable with a better solution
28637    //       See: https://github.com/parcel-bundler/lightningcss/issues/288
28638    // minify_test(r#"
28639    //   @property --property-name {
28640    //     syntax: '<transform-list>';
28641    //     inherits: false;
28642    //     initial-value: translate(200px,300px) translate(100px,200px) scale(2);
28643    //   }
28644    // "#, "@property --property-name{syntax:\"<transform-list>\";inherits:false;initial-value:matrix(2,0,0,2,300,500)}");
28645
28646    minify_test(
28647      r#"
28648      @property --property-name {
28649        syntax: '<time>';
28650        inherits: false;
28651        initial-value: 1000ms;
28652      }
28653    "#,
28654      "@property --property-name{syntax:\"<time>\";inherits:false;initial-value:1s}",
28655    );
28656
28657    minify_test(
28658      r#"
28659      @property --property-name {
28660        syntax: '<url>';
28661        inherits: false;
28662        initial-value: url("foo.png");
28663      }
28664    "#,
28665      "@property --property-name{syntax:\"<url>\";inherits:false;initial-value:url(foo.png)}",
28666    );
28667
28668    minify_test(
28669      r#"
28670      @property --property-name {
28671        syntax: '<image>';
28672        inherits: false;
28673        initial-value: linear-gradient(yellow, blue);
28674      }
28675    "#,
28676      "@property --property-name{syntax:\"<image>\";inherits:false;initial-value:linear-gradient(#ff0,#00f)}",
28677    );
28678
28679    minify_test(
28680      r#"
28681      @property --property-name {
28682        initial-value: linear-gradient(yellow, blue);
28683        inherits: false;
28684        syntax: '<image>';
28685      }
28686    "#,
28687      "@property --property-name{syntax:\"<image>\";inherits:false;initial-value:linear-gradient(#ff0,#00f)}",
28688    );
28689
28690    test(
28691      r#"
28692      @property --property-name {
28693        syntax: '<length>|none';
28694        inherits: false;
28695        initial-value: none;
28696      }
28697    "#,
28698      indoc! {r#"
28699      @property --property-name {
28700        syntax: "<length> | none";
28701        inherits: false;
28702        initial-value: none;
28703      }
28704    "#},
28705    );
28706
28707    minify_test(
28708      r#"
28709      @property --property-name {
28710        syntax: '<color>#';
28711        inherits: false;
28712        initial-value: yellow, blue;
28713      }
28714    "#,
28715      "@property --property-name{syntax:\"<color>#\";inherits:false;initial-value:#ff0,#00f}",
28716    );
28717    minify_test(
28718      r#"
28719      @property --property-name {
28720        syntax: '<color>+';
28721        inherits: false;
28722        initial-value: yellow blue;
28723      }
28724    "#,
28725      "@property --property-name{syntax:\"<color>+\";inherits:false;initial-value:#ff0 #00f}",
28726    );
28727    minify_test(
28728      r#"
28729      @property --property-name {
28730        syntax: '<color>';
28731        inherits: false;
28732        initial-value: yellow;
28733      }
28734      .foo {
28735        color: var(--property-name)
28736      }
28737      @property --property-name {
28738        syntax: '<color>';
28739        inherits: true;
28740        initial-value: blue;
28741      }
28742    "#,
28743      "@property --property-name{syntax:\"<color>\";inherits:true;initial-value:#00f}.foo{color:var(--property-name)}",
28744    );
28745  }
28746
28747  #[test]
28748  fn test_quoting_unquoting_urls() {
28749    // Quotes remain double quotes when not minifying
28750    test(
28751      r#".foo {
28752      background-image: url("0123abcd");
28753    }"#,
28754      r#".foo {
28755  background-image: url("0123abcd");
28756}
28757"#,
28758    );
28759
28760    // Quotes removed when minifying
28761    minify_test(
28762      r#".foo {
28763      background-image: url("0123abcd");
28764    }"#,
28765      r#".foo{background-image:url(0123abcd)}"#,
28766    );
28767
28768    // Doubles quotes added if not present when not minifying
28769    test(
28770      r#".foo {
28771      background-image: url(0123abcd);
28772    }"#,
28773      r#".foo {
28774  background-image: url("0123abcd");
28775}
28776"#,
28777    );
28778
28779    // No quotes changed if not present when not minifying
28780    minify_test(
28781      r#".foo {
28782      background-image: url(0123abcd);
28783    }"#,
28784      r#".foo{background-image:url(0123abcd)}"#,
28785    );
28786  }
28787
28788  #[test]
28789  fn test_zindex() {
28790    minify_test(".foo { z-index: 2 }", ".foo{z-index:2}");
28791    minify_test(".foo { z-index: -2 }", ".foo{z-index:-2}");
28792    minify_test(".foo { z-index: 999999 }", ".foo{z-index:999999}");
28793    minify_test(".foo { z-index: 9999999 }", ".foo{z-index:9999999}");
28794    minify_test(".foo { z-index: -9999999 }", ".foo{z-index:-9999999}");
28795  }
28796
28797  #[test]
28798  #[cfg(feature = "sourcemap")]
28799  fn test_input_source_map() {
28800    let source = r#".imported {
28801      content: "yay, file support!";
28802    }
28803
28804    .selector {
28805      margin: 1em;
28806      background-color: #f60;
28807    }
28808
28809    .selector .nested {
28810      margin: 0.5em;
28811    }
28812
28813    /*# sourceMappingURL=data:application/json;base64,ewoJInZlcnNpb24iOiAzLAoJInNvdXJjZVJvb3QiOiAicm9vdCIsCgkiZmlsZSI6ICJzdGRvdXQiLAoJInNvdXJjZXMiOiBbCgkJInN0ZGluIiwKCQkic2Fzcy9fdmFyaWFibGVzLnNjc3MiLAoJCSJzYXNzL19kZW1vLnNjc3MiCgldLAoJInNvdXJjZXNDb250ZW50IjogWwoJCSJAaW1wb3J0IFwiX3ZhcmlhYmxlc1wiO1xuQGltcG9ydCBcIl9kZW1vXCI7XG5cbi5zZWxlY3RvciB7XG4gIG1hcmdpbjogJHNpemU7XG4gIGJhY2tncm91bmQtY29sb3I6ICRicmFuZENvbG9yO1xuXG4gIC5uZXN0ZWQge1xuICAgIG1hcmdpbjogJHNpemUgLyAyO1xuICB9XG59IiwKCQkiJGJyYW5kQ29sb3I6ICNmNjA7XG4kc2l6ZTogMWVtOyIsCgkJIi5pbXBvcnRlZCB7XG4gIGNvbnRlbnQ6IFwieWF5LCBmaWxlIHN1cHBvcnQhXCI7XG59IgoJXSwKCSJtYXBwaW5ncyI6ICJBRUFBLFNBQVMsQ0FBQztFQUNSLE9BQU8sRUFBRSxvQkFBcUI7Q0FDL0I7O0FGQ0QsU0FBUyxDQUFDO0VBQ1IsTUFBTSxFQ0hELEdBQUc7RURJUixnQkFBZ0IsRUNMTCxJQUFJO0NEVWhCOztBQVBELFNBQVMsQ0FJUCxPQUFPLENBQUM7RUFDTixNQUFNLEVDUEgsS0FBRztDRFFQIiwKCSJuYW1lcyI6IFtdCn0= */"#;
28814
28815    let mut stylesheet = StyleSheet::parse(&source, ParserOptions::default()).unwrap();
28816    stylesheet.minify(MinifyOptions::default()).unwrap();
28817    let mut sm = parcel_sourcemap::SourceMap::new("/");
28818    stylesheet
28819      .to_css(PrinterOptions {
28820        source_map: Some(&mut sm),
28821        minify: true,
28822        ..PrinterOptions::default()
28823      })
28824      .unwrap();
28825    let map = sm.to_json(None).unwrap();
28826    assert_eq!(
28827      map,
28828      r#"{"version":3,"sourceRoot":null,"mappings":"AAAA,uCCGA,2CAAA","sources":["sass/_demo.scss","stdin"],"sourcesContent":[".imported {\n  content: \"yay, file support!\";\n}","@import \"_variables\";\n@import \"_demo\";\n\n.selector {\n  margin: $size;\n  background-color: $brandColor;\n\n  .nested {\n    margin: $size / 2;\n  }\n}"],"names":[]}"#
28829    );
28830  }
28831
28832  #[test]
28833  #[cfg(feature = "sourcemap")]
28834  fn test_source_maps_with_license_comments() {
28835    let source = r#"/*! a single line comment */
28836    /*!
28837      a comment
28838      containing
28839      multiple
28840      lines
28841    */
28842    .a {
28843      display: flex;
28844    }
28845
28846    .b {
28847      display: hidden;
28848    }
28849    "#;
28850
28851    let mut sm = parcel_sourcemap::SourceMap::new("/");
28852    let source_index = sm.add_source("input.css");
28853    sm.set_source_content(source_index as usize, source).unwrap();
28854
28855    let mut stylesheet = StyleSheet::parse(
28856      &source,
28857      ParserOptions {
28858        source_index,
28859        ..Default::default()
28860      },
28861    )
28862    .unwrap();
28863    stylesheet.minify(MinifyOptions::default()).unwrap();
28864    stylesheet
28865      .to_css(PrinterOptions {
28866        source_map: Some(&mut sm),
28867        minify: true,
28868        ..PrinterOptions::default()
28869      })
28870      .unwrap();
28871    let map = sm.to_json(None).unwrap();
28872    assert_eq!(
28873      map,
28874      r#"{"version":3,"sourceRoot":null,"mappings":";;;;;;;AAOI,gBAIA","sources":["input.css"],"sourcesContent":["/*! a single line comment */\n    /*!\n      a comment\n      containing\n      multiple\n      lines\n    */\n    .a {\n      display: flex;\n    }\n\n    .b {\n      display: hidden;\n    }\n    "],"names":[]}"#
28875    );
28876  }
28877
28878  #[test]
28879  fn test_error_recovery() {
28880    use std::sync::{Arc, RwLock};
28881    let warnings = Some(Arc::new(RwLock::new(Vec::new())));
28882    test_with_options(
28883      r#"
28884      h1(>h1) {
28885        color: red;
28886      }
28887
28888      .foo {
28889        color: red;
28890      }
28891
28892      .clearfix {
28893        *zoom: 1;
28894        background: red;
28895      }
28896
28897      @media (hover) {
28898        h1(>h1) {
28899          color: red;
28900        }
28901
28902        .bar {
28903          color: red;
28904        }
28905      }
28906
28907      input:placeholder {
28908        color: red;
28909      }
28910
28911      input::hover {
28912        color: red;
28913      }
28914    "#,
28915      indoc! { r#"
28916      .foo {
28917        color: red;
28918      }
28919
28920      .clearfix {
28921        background: red;
28922      }
28923
28924      @media (hover) {
28925        .bar {
28926          color: red;
28927        }
28928      }
28929
28930      input:placeholder {
28931        color: red;
28932      }
28933
28934      input::hover {
28935        color: red;
28936      }
28937    "#},
28938      ParserOptions {
28939        filename: "test.css".into(),
28940        error_recovery: true,
28941        warnings: warnings.clone(),
28942        ..ParserOptions::default()
28943      },
28944    );
28945    let w = warnings.unwrap();
28946    let warnings = w.read().unwrap();
28947    assert_eq!(
28948      *warnings,
28949      vec![
28950        Error {
28951          kind: ParserError::SelectorError(SelectorError::EmptySelector),
28952          loc: Some(ErrorLocation {
28953            filename: "test.css".into(),
28954            line: 1,
28955            column: 7
28956          })
28957        },
28958        Error {
28959          kind: ParserError::UnexpectedToken(Token::Semicolon),
28960          loc: Some(ErrorLocation {
28961            filename: "test.css".into(),
28962            line: 10,
28963            column: 17
28964          })
28965        },
28966        Error {
28967          kind: ParserError::SelectorError(SelectorError::EmptySelector),
28968          loc: Some(ErrorLocation {
28969            filename: "test.css".into(),
28970            line: 15,
28971            column: 9
28972          })
28973        },
28974        Error {
28975          kind: ParserError::SelectorError(SelectorError::UnsupportedPseudoClass("placeholder".into())),
28976          loc: Some(ErrorLocation {
28977            filename: "test.css".into(),
28978            line: 24,
28979            column: 13,
28980          }),
28981        },
28982        Error {
28983          kind: ParserError::SelectorError(SelectorError::UnsupportedPseudoElement("hover".into())),
28984          loc: Some(ErrorLocation {
28985            filename: "test.css".into(),
28986            line: 28,
28987            column: 13,
28988          }),
28989        },
28990      ]
28991    )
28992  }
28993
28994  #[test]
28995  fn test_invalid() {
28996    error_test(
28997      ".a{color: hsla(120, 62.32%;}",
28998      ParserError::UnexpectedToken(Token::CloseCurlyBracket),
28999    );
29000    error_test(
29001      ".a{--foo: url(foo\\) b\\)ar)}",
29002      ParserError::UnexpectedToken(Token::BadUrl("foo\\) b\\)ar".into())),
29003    );
29004  }
29005
29006  #[test]
29007  fn test_container_queries() {
29008    // with name
29009    minify_test(
29010      r#"
29011      @container my-layout (inline-size > 45em) {
29012        .foo {
29013          color: red;
29014        }
29015      }
29016    "#,
29017      "@container my-layout (inline-size>45em){.foo{color:red}}",
29018    );
29019
29020    minify_test(
29021      r#"
29022      @container my-layout ( not (width > 500px) ) {
29023        .foo {
29024          color: red;
29025        }
29026      }
29027    "#,
29028      "@container my-layout not (width>500px){.foo{color:red}}",
29029    );
29030
29031    minify_test(
29032      r#"
29033      @container my-layout not (width > 500px) {
29034        .foo {
29035          color: red;
29036        }
29037      }
29038    "#,
29039      "@container my-layout not (width>500px){.foo{color:red}}",
29040    );
29041
29042    minify_test(
29043      r#"
29044      @container not (width > 500px) {
29045        .foo {
29046          color: red;
29047        }
29048      }
29049    "#,
29050      "@container not (width>500px){.foo{color:red}}",
29051    );
29052
29053    minify_test(
29054      r#"
29055      @container my-layout ((width: 100px) and (not (height: 100px))) {
29056        .foo {
29057          color: red;
29058        }
29059      }
29060    "#,
29061      "@container my-layout (width:100px) and (not (height:100px)){.foo{color:red}}",
29062    );
29063
29064    minify_test(
29065      r#"
29066      @container my-layout (width = max(10px, 10em)) {
29067        .foo {
29068          color: red;
29069        }
29070      }
29071    "#,
29072      "@container my-layout (width=max(10px,10em)){.foo{color:red}}",
29073    );
29074
29075    // without name
29076    minify_test(
29077      r#"
29078      @container (inline-size > 45em) {
29079        .foo {
29080          color: red;
29081        }
29082      }
29083    "#,
29084      "@container (inline-size>45em){.foo{color:red}}",
29085    );
29086
29087    minify_test(
29088      r#"
29089      @container (inline-size > 45em) and (inline-size < 100em) {
29090        .foo {
29091          color: red;
29092        }
29093      }
29094    "#,
29095      "@container (inline-size>45em) and (inline-size<100em){.foo{color:red}}",
29096    );
29097
29098    // calc()
29099    minify_test(
29100      r#"
29101      @container (width > calc(100vw - 50px)) {
29102        .foo {
29103          color: red;
29104        }
29105      }
29106    "#,
29107      "@container (width>calc(100vw - 50px)){.foo{color:red}}",
29108    );
29109
29110    minify_test(
29111      r#"
29112      @container (calc(100vh - 50px) <= height ) {
29113        .foo {
29114          color: red;
29115        }
29116      }
29117    "#,
29118      "@container (height>=calc(100vh - 50px)){.foo{color:red}}",
29119    );
29120
29121    // merge adjacent
29122    minify_test(
29123      r#"
29124      @container my-layout (inline-size > 45em) {
29125        .foo {
29126          color: red;
29127        }
29128      }
29129
29130      @container my-layout (inline-size > 45em) {
29131        .foo {
29132          background: yellow;
29133        }
29134
29135        .bar {
29136          color: white;
29137        }
29138      }
29139    "#,
29140      "@container my-layout (inline-size>45em){.foo{color:red;background:#ff0}.bar{color:#fff}}",
29141    );
29142
29143    minify_test(
29144      r#"
29145    .foo {
29146      container-name: foo bar;
29147      container-type: size;
29148    }
29149    "#,
29150      ".foo{container:foo bar/size}",
29151    );
29152    minify_test(
29153      r#"
29154    .foo {
29155      container-name: foo bar;
29156      container-type: normal;
29157    }
29158    "#,
29159      ".foo{container:foo bar}",
29160    );
29161    minify_test(
29162      ".foo{ container-type: inline-size }",
29163      ".foo{container-type:inline-size}",
29164    );
29165    minify_test(".foo{ container-name: none; }", ".foo{container-name:none}");
29166    minify_test(".foo{ container-name: foo; }", ".foo{container-name:foo}");
29167    minify_test(".foo{ container: foo / normal; }", ".foo{container:foo}");
29168    minify_test(
29169      ".foo{ container: foo / inline-size; }",
29170      ".foo{container:foo/inline-size}",
29171    );
29172    minify_test(".foo { width: calc(1cqw + 2cqw) }", ".foo{width:3cqw}");
29173    minify_test(".foo { width: calc(1cqh + 2cqh) }", ".foo{width:3cqh}");
29174    minify_test(".foo { width: calc(1cqi + 2cqi) }", ".foo{width:3cqi}");
29175    minify_test(".foo { width: calc(1cqb + 2cqb) }", ".foo{width:3cqb}");
29176    minify_test(".foo { width: calc(1cqmin + 2cqmin) }", ".foo{width:3cqmin}");
29177    minify_test(".foo { width: calc(1cqmax + 2cqmax) }", ".foo{width:3cqmax}");
29178
29179    // Unlike in @media, there is no need to convert the range syntax in @container,
29180    // because browsers all support this syntax.
29181    prefix_test(
29182      r#"
29183      @container (width > 100px) {
29184        .foo { padding: 5px; }
29185      }
29186      "#,
29187      indoc! { r#"
29188        @container (width > 100px) {
29189          .foo {
29190            padding: 5px;
29191          }
29192        }
29193      "#},
29194      Browsers {
29195        chrome: Some(105 << 16),
29196        ..Browsers::default()
29197      },
29198    );
29199    prefix_test(
29200      r#"
29201      @container (min-width: 100px) {
29202        .foo { padding: 5px; }
29203      }
29204      "#,
29205      indoc! { r#"
29206        @container (width >= 100px) {
29207          .foo {
29208            padding: 5px;
29209          }
29210        }
29211      "#},
29212      Browsers {
29213        chrome: Some(105 << 16),
29214        ..Browsers::default()
29215      },
29216    );
29217
29218    minify_test(
29219      r#"
29220      @container style(--responsive: true) {
29221        .foo {
29222          color: red;
29223        }
29224      }
29225    "#,
29226      "@container style(--responsive:true){.foo{color:red}}",
29227    );
29228    minify_test(
29229      r#"
29230      @container style(--responsive: true) and style(color: yellow) {
29231        .foo {
29232          color: red;
29233        }
29234      }
29235    "#,
29236      "@container style(--responsive:true) and style(color:#ff0){.foo{color:red}}",
29237    );
29238    minify_test(
29239      r#"
29240      @container not style(--responsive: true) {
29241        .foo {
29242          color: red;
29243        }
29244      }
29245    "#,
29246      "@container not style(--responsive:true){.foo{color:red}}",
29247    );
29248    minify_test(
29249      r#"
29250      @container (inline-size > 45em) and style(--responsive: true) {
29251        .foo {
29252          color: red;
29253        }
29254      }
29255    "#,
29256      "@container (inline-size>45em) and style(--responsive:true){.foo{color:red}}",
29257    );
29258    minify_test(
29259      r#"
29260      @container style((accent-color: yellow) or (--bar: 10px)) {
29261        .foo {
29262          color: red;
29263        }
29264      }
29265    "#,
29266      "@container style((accent-color:#ff0) or (--bar:10px)){.foo{color:red}}",
29267    );
29268    minify_test(
29269      r#"
29270      @container style(not ((width: calc(10px + 20px)) and ((--bar: url(x))))) {
29271        .foo {
29272          color: red;
29273        }
29274      }
29275    "#,
29276      "@container style(not ((width:30px) and (--bar:url(x)))){.foo{color:red}}",
29277    );
29278    minify_test(
29279      r#"
29280      @container style(color: yellow !important) {
29281        .foo {
29282          color: red;
29283        }
29284      }
29285    "#,
29286      "@container style(color:yellow){.foo{color:red}}",
29287    );
29288    minify_test(
29289      r#"
29290      @container style(--foo:) {
29291        .foo {
29292          color: red;
29293        }
29294      }
29295    "#,
29296      "@container style(--foo:){.foo{color:red}}",
29297    );
29298    minify_test(
29299      r#"
29300      @container style(--foo: ) {
29301        .foo {
29302          color: red;
29303        }
29304      }
29305    "#,
29306      "@container style(--foo:){.foo{color:red}}",
29307    );
29308    minify_test(
29309      r#"
29310      @container style(--my-prop: foo - bar ()) {
29311        .foo {
29312          color: red;
29313        }
29314      }
29315    "#,
29316      "@container style(--my-prop:foo - bar ()){.foo{color:red}}",
29317    );
29318    minify_test(
29319      r#"
29320      @container style(--test) {
29321        .foo {
29322          color: red;
29323        }
29324      }
29325    "#,
29326      "@container style(--test){.foo{color:red}}",
29327    );
29328    minify_test(
29329      r#"
29330      @container style(width) {
29331        .foo {
29332          color: red;
29333        }
29334      }
29335    "#,
29336      "@container style(width){.foo{color:red}}",
29337    );
29338
29339    // Disallow 'none', 'not', 'and', 'or' as a `<container-name>`
29340    // https://github.com/w3c/csswg-drafts/issues/7203#issuecomment-1144257312
29341    // https://chromium-review.googlesource.com/c/chromium/src/+/3698402
29342    error_test(
29343      "@container none (width < 100vw) {}",
29344      ParserError::UnexpectedToken(crate::properties::custom::Token::Ident("none".into())),
29345    );
29346
29347    error_test(
29348      "@container and (width < 100vw) {}",
29349      ParserError::UnexpectedToken(crate::properties::custom::Token::Ident("and".into())),
29350    );
29351
29352    error_test(
29353      "@container or (width < 100vw) {}",
29354      ParserError::UnexpectedToken(crate::properties::custom::Token::Ident("or".into())),
29355    );
29356
29357    // Disallow CSS wide keywords as a `<container-name>`
29358    error_test(
29359      "@container revert-layer (width < 100vw) {}",
29360      ParserError::UnexpectedToken(crate::properties::custom::Token::Ident("revert-layer".into())),
29361    );
29362
29363    error_test(
29364      "@container initial (width < 100vw) {}",
29365      ParserError::UnexpectedToken(crate::properties::custom::Token::Ident("initial".into())),
29366    );
29367
29368    // <ident> contains spaces
29369    // https://github.com/web-platform-tests/wpt/blob/39f0da08fbbe33d0582a35749b6dbf8bd067a52d/css/css-contain/container-queries/at-container-parsing.html#L160-L178
29370    error_test(
29371      "@container foo bar (width < 100vw) {}",
29372      ParserError::UnexpectedToken(crate::properties::custom::Token::Ident("bar".into())),
29373    );
29374
29375    error_test("@container (inline-size <= foo) {}", ParserError::InvalidMediaQuery);
29376    error_test("@container (orientation <= 10px) {}", ParserError::InvalidMediaQuery);
29377
29378    error_test(
29379      "@container style(style(--foo: bar)) {}",
29380      ParserError::UnexpectedToken(crate::properties::custom::Token::Function("style".into())),
29381    );
29382  }
29383
29384  #[test]
29385  fn test_css_modules_value_rule() {
29386    css_modules_error_test(
29387      "@value compact: (max-width: 37.4375em);",
29388      ParserError::DeprecatedCssModulesValueRule,
29389    );
29390  }
29391
29392  #[test]
29393  fn test_unknown_at_rules() {
29394    minify_test("@foo;", "@foo;");
29395    minify_test("@foo bar;", "@foo bar;");
29396    minify_test("@foo (bar: baz);", "@foo (bar: baz);");
29397    test(
29398      r#"@foo test {
29399      div {
29400        color: red;
29401      }
29402    }"#,
29403      indoc! {r#"
29404      @foo test {
29405        div { color: red; }
29406      }
29407      "#},
29408    );
29409    minify_test(
29410      r#"@foo test {
29411      div {
29412        color: red;
29413      }
29414    }"#,
29415      "@foo test{div { color: red; }}",
29416    );
29417    minify_test(
29418      r#"@foo test {
29419        foo: bar;
29420      }"#,
29421      "@foo test{foo: bar;}",
29422    );
29423    test(
29424      r#"@foo {
29425        foo: bar;
29426      }"#,
29427      indoc! {r#"
29428      @foo {
29429        foo: bar;
29430      }
29431      "#},
29432    );
29433    minify_test(
29434      r#"@foo {
29435        foo: bar;
29436      }"#,
29437      "@foo{foo: bar;}",
29438    );
29439  }
29440
29441  #[test]
29442  fn test_resolution() {
29443    prefix_test(
29444      r#"
29445      @media (resolution: 1dppx) {
29446        body {
29447          background: red;
29448        }
29449      }
29450      "#,
29451      indoc! { r#"
29452      @media (resolution: 1dppx) {
29453        body {
29454          background: red;
29455        }
29456      }
29457      "#},
29458      Browsers {
29459        chrome: Some(50 << 16),
29460        ..Browsers::default()
29461      },
29462    );
29463
29464    prefix_test(
29465      r#"
29466      @media (resolution: 1dppx) {
29467        body {
29468          background: red;
29469        }
29470      }
29471      "#,
29472      indoc! { r#"
29473      @media (resolution: 1x) {
29474        body {
29475          background: red;
29476        }
29477      }
29478      "#},
29479      Browsers {
29480        chrome: Some(95 << 16),
29481        ..Browsers::default()
29482      },
29483    );
29484  }
29485
29486  #[test]
29487  fn test_environment() {
29488    minify_test(
29489      r#"
29490      @media (max-width: env(--branding-small)) {
29491        body {
29492          padding: env(--branding-padding);
29493        }
29494      }
29495    "#,
29496      "@media (width<=env(--branding-small)){body{padding:env(--branding-padding)}}",
29497    );
29498
29499    minify_test(
29500      r#"
29501      @media (max-width: env(--branding-small 1)) {
29502        body {
29503          padding: env(--branding-padding 2);
29504        }
29505      }
29506    "#,
29507      "@media (width<=env(--branding-small 1)){body{padding:env(--branding-padding 2)}}",
29508    );
29509
29510    minify_test(
29511      r#"
29512      @media (max-width: env(--branding-small 1, 20px)) {
29513        body {
29514          padding: env(--branding-padding 2, 20px);
29515        }
29516      }
29517    "#,
29518      "@media (width<=env(--branding-small 1,20px)){body{padding:env(--branding-padding 2,20px)}}",
29519    );
29520
29521    minify_test(
29522      r#"
29523      @media (max-width: env(safe-area-inset-top)) {
29524        body {
29525          padding: env(safe-area-inset-top);
29526        }
29527      }
29528    "#,
29529      "@media (width<=env(safe-area-inset-top)){body{padding:env(safe-area-inset-top)}}",
29530    );
29531
29532    minify_test(
29533      r#"
29534      @media (max-width: env(unknown)) {
29535        body {
29536          padding: env(unknown);
29537        }
29538      }
29539    "#,
29540      "@media (width<=env(unknown)){body{padding:env(unknown)}}",
29541    );
29542
29543    prefix_test(
29544      r#"
29545      .foo {
29546        color: env(--brand-color, color(display-p3 0 1 0));
29547      }
29548    "#,
29549      indoc! {r#"
29550      .foo {
29551        color: env(--brand-color, #00f942);
29552      }
29553
29554      @supports (color: color(display-p3 0 0 0)) {
29555        .foo {
29556          color: env(--brand-color, color(display-p3 0 1 0));
29557        }
29558      }
29559    "#},
29560      Browsers {
29561        safari: Some(15 << 16),
29562        chrome: Some(90 << 16),
29563        ..Browsers::default()
29564      },
29565    );
29566
29567    prefix_test(
29568      r#"
29569      @supports (color: color(display-p3 0 0 0)) {
29570        .foo {
29571          color: env(--brand-color, color(display-p3 0 1 0));
29572        }
29573      }
29574    "#,
29575      indoc! {r#"
29576      @supports (color: color(display-p3 0 0 0)) {
29577        .foo {
29578          color: env(--brand-color, color(display-p3 0 1 0));
29579        }
29580      }
29581    "#},
29582      Browsers {
29583        safari: Some(15 << 16),
29584        chrome: Some(90 << 16),
29585        ..Browsers::default()
29586      },
29587    );
29588
29589    css_modules_test(
29590      r#"
29591      @media (max-width: env(--branding-small)) {
29592        .foo {
29593          color: env(--brand-color);
29594        }
29595      }
29596    "#,
29597      indoc! {r#"
29598      @media (width <= env(--EgL3uq_branding-small)) {
29599        .EgL3uq_foo {
29600          color: env(--EgL3uq_brand-color);
29601        }
29602      }
29603    "#},
29604      map! {
29605        "foo" => "EgL3uq_foo",
29606        "--brand-color" => "--EgL3uq_brand-color" referenced: true,
29607        "--branding-small" => "--EgL3uq_branding-small" referenced: true
29608      },
29609      HashMap::new(),
29610      crate::css_modules::Config {
29611        dashed_idents: true,
29612        ..Default::default()
29613      },
29614      false,
29615    );
29616  }
29617
29618  #[test]
29619  fn test_license_comments() {
29620    minify_test(
29621      r#"
29622      /*! Copyright 2023 Someone awesome */
29623      /* Some other comment */
29624      .foo {
29625        color: red;
29626      }
29627    "#,
29628      indoc! {r#"
29629      /*! Copyright 2023 Someone awesome */
29630      .foo{color:red}"#},
29631    );
29632
29633    minify_test(
29634      r#"
29635      /*! Copyright 2023 Someone awesome */
29636      /*! Copyright 2023 Someone else */
29637      .foo {
29638        color: red;
29639      }
29640    "#,
29641      indoc! {r#"
29642      /*! Copyright 2023 Someone awesome */
29643      /*! Copyright 2023 Someone else */
29644      .foo{color:red}"#},
29645    );
29646  }
29647
29648  #[test]
29649  fn test_starting_style() {
29650    minify_test(
29651      r#"
29652      @starting-style {
29653        h1 {
29654          background: yellow;
29655        }
29656      }
29657      "#,
29658      "@starting-style{h1{background:#ff0}}",
29659    );
29660    minify_test("@starting-style {}", "");
29661
29662    nesting_test(
29663      r#"
29664      h1 {
29665        background: red;
29666        @starting-style {
29667          background: yellow;
29668        }
29669      }
29670      "#,
29671      indoc! {r#"
29672      h1 {
29673        background: red;
29674      }
29675
29676      @starting-style {
29677        h1 {
29678          background: #ff0;
29679        }
29680      }
29681      "#},
29682    );
29683  }
29684
29685  #[test]
29686  fn test_color_scheme() {
29687    minify_test(".foo { color-scheme: normal; }", ".foo{color-scheme:normal}");
29688    minify_test(".foo { color-scheme: light; }", ".foo{color-scheme:light}");
29689    minify_test(".foo { color-scheme: dark; }", ".foo{color-scheme:dark}");
29690    minify_test(".foo { color-scheme: light dark; }", ".foo{color-scheme:light dark}");
29691    minify_test(".foo { color-scheme: dark light; }", ".foo{color-scheme:light dark}");
29692    minify_test(".foo { color-scheme: only light; }", ".foo{color-scheme:light only}");
29693    minify_test(".foo { color-scheme: only dark; }", ".foo{color-scheme:dark only}");
29694    minify_test(
29695      ".foo { color-scheme: dark light only; }",
29696      ".foo{color-scheme:light dark only}",
29697    );
29698    minify_test(".foo { color-scheme: foo bar light; }", ".foo{color-scheme:light}");
29699    minify_test(
29700      ".foo { color-scheme: only foo dark bar; }",
29701      ".foo{color-scheme:dark only}",
29702    );
29703    prefix_test(
29704      ".foo { color-scheme: dark; }",
29705      indoc! { r#"
29706      .foo {
29707        --lightningcss-light: ;
29708        --lightningcss-dark: initial;
29709        color-scheme: dark;
29710      }
29711      "#},
29712      Browsers {
29713        chrome: Some(90 << 16),
29714        ..Browsers::default()
29715      },
29716    );
29717    prefix_test(
29718      ".foo { color-scheme: light; }",
29719      indoc! { r#"
29720      .foo {
29721        --lightningcss-light: initial;
29722        --lightningcss-dark: ;
29723        color-scheme: light;
29724      }
29725      "#},
29726      Browsers {
29727        chrome: Some(90 << 16),
29728        ..Browsers::default()
29729      },
29730    );
29731    prefix_test(
29732      ".foo { color-scheme: light dark; }",
29733      indoc! { r#"
29734      .foo {
29735        --lightningcss-light: initial;
29736        --lightningcss-dark: ;
29737        color-scheme: light dark;
29738      }
29739
29740      @media (prefers-color-scheme: dark) {
29741        .foo {
29742          --lightningcss-light: ;
29743          --lightningcss-dark: initial;
29744        }
29745      }
29746      "#},
29747      Browsers {
29748        chrome: Some(90 << 16),
29749        ..Browsers::default()
29750      },
29751    );
29752    prefix_test(
29753      ".foo { color-scheme: light dark; }",
29754      indoc! { r#"
29755      .foo {
29756        color-scheme: light dark;
29757      }
29758      "#},
29759      Browsers {
29760        firefox: Some(120 << 16),
29761        ..Browsers::default()
29762      },
29763    );
29764
29765    minify_test(
29766      ".foo { color: light-dark(yellow, red); }",
29767      ".foo{color:light-dark(#ff0,red)}",
29768    );
29769    minify_test(
29770      ".foo { color: light-dark(light-dark(yellow, red), light-dark(yellow, red)); }",
29771      ".foo{color:light-dark(#ff0,red)}",
29772    );
29773    minify_test(
29774      ".foo { color: light-dark(rgb(0, 0, 255), hsl(120deg, 50%, 50%)); }",
29775      ".foo{color:light-dark(#00f,#40bf40)}",
29776    );
29777    prefix_test(
29778      ".foo { color: light-dark(oklch(40% 0.1268735435 34.568626), oklab(59.686% 0.1009 0.1192)); }",
29779      indoc! { r#"
29780      .foo {
29781        color: var(--lightningcss-light, #7e250f) var(--lightningcss-dark, #c65d07);
29782        color: var(--lightningcss-light, lab(29.2661% 38.2437 35.3889)) var(--lightningcss-dark, lab(52.2319% 40.1449 59.9171));
29783      }
29784      "#},
29785      Browsers {
29786        chrome: Some(90 << 16),
29787        ..Browsers::default()
29788      },
29789    );
29790    prefix_test(
29791      ".foo { color: light-dark(oklch(40% 0.1268735435 34.568626), oklab(59.686% 0.1009 0.1192)); }",
29792      indoc! { r#"
29793      .foo {
29794        color: light-dark(oklch(40% .126874 34.5686), oklab(59.686% .1009 .1192));
29795      }
29796      "#},
29797      Browsers {
29798        firefox: Some(120 << 16),
29799        ..Browsers::default()
29800      },
29801    );
29802    prefix_test(
29803      r#"
29804      .foo {
29805        box-shadow:
29806            oklch(100% 0 0deg / 50%) 0 0.63rem 0.94rem -0.19rem,
29807            currentColor 0 0.44rem 0.8rem -0.58rem;
29808      }
29809    "#,
29810      indoc! { r#"
29811      .foo {
29812        box-shadow: 0 .63rem .94rem -.19rem #ffffff80, 0 .44rem .8rem -.58rem;
29813        box-shadow: 0 .63rem .94rem -.19rem lab(100% 0 0 / .5), 0 .44rem .8rem -.58rem;
29814      }
29815      "#},
29816      Browsers {
29817        chrome: Some(95 << 16),
29818        ..Browsers::default()
29819      },
29820    );
29821    prefix_test(
29822      r#"
29823      .foo {
29824        box-shadow:
29825            oklch(100% 0 0deg / 50%) 0 0.63rem 0.94rem -0.19rem,
29826            currentColor 0 0.44rem 0.8rem -0.58rem;
29827      }
29828    "#,
29829      indoc! { r#"
29830      .foo {
29831        box-shadow: 0 .63rem .94rem -.19rem color(display-p3 1 1 1 / .5), 0 .44rem .8rem -.58rem;
29832        box-shadow: 0 .63rem .94rem -.19rem lab(100% 0 0 / .5), 0 .44rem .8rem -.58rem;
29833      }
29834      "#},
29835      Browsers {
29836        safari: Some(14 << 16),
29837        ..Browsers::default()
29838      },
29839    );
29840
29841    prefix_test(
29842      ".foo { color: light-dark(var(--light), var(--dark)); }",
29843      indoc! { r#"
29844      .foo {
29845        color: var(--lightningcss-light, var(--light)) var(--lightningcss-dark, var(--dark));
29846      }
29847      "#},
29848      Browsers {
29849        chrome: Some(90 << 16),
29850        ..Browsers::default()
29851      },
29852    );
29853    prefix_test(
29854      ".foo { color: rgb(from light-dark(yellow, red) r g b / 10%); }",
29855      indoc! { r#"
29856      .foo {
29857        color: var(--lightningcss-light, #ffff001a) var(--lightningcss-dark, #ff00001a);
29858      }
29859      "#},
29860      Browsers {
29861        chrome: Some(90 << 16),
29862        ..Browsers::default()
29863      },
29864    );
29865    prefix_test(
29866      ".foo { color: rgb(from light-dark(yellow, red) r g b / var(--alpha)); }",
29867      indoc! { r#"
29868      .foo {
29869        color: var(--lightningcss-light, rgb(255 255 0 / var(--alpha))) var(--lightningcss-dark, rgb(255 0 0 / var(--alpha)));
29870      }
29871      "#},
29872      Browsers {
29873        chrome: Some(90 << 16),
29874        ..Browsers::default()
29875      },
29876    );
29877    prefix_test(
29878      ".foo { color: color(from light-dark(yellow, red) srgb r g b / 10%); }",
29879      indoc! { r#"
29880      .foo {
29881        color: var(--lightningcss-light, #ffff001a) var(--lightningcss-dark, #ff00001a);
29882        color: var(--lightningcss-light, color(srgb 1 1 0 / .1)) var(--lightningcss-dark, color(srgb 1 0 0 / .1));
29883      }
29884      "#},
29885      Browsers {
29886        chrome: Some(90 << 16),
29887        ..Browsers::default()
29888      },
29889    );
29890    prefix_test(
29891      ".foo { color: color-mix(in srgb, light-dark(yellow, red), light-dark(red, pink)); }",
29892      indoc! { r#"
29893      .foo {
29894        color: var(--lightningcss-light, #ff8000) var(--lightningcss-dark, #ff6066);
29895      }
29896      "#},
29897      Browsers {
29898        chrome: Some(90 << 16),
29899        ..Browsers::default()
29900      },
29901    );
29902    nesting_test_with_targets(
29903      r#"
29904        .foo { color-scheme: light; }
29905        .bar { color: light-dark(red, green); }
29906      "#,
29907      indoc! {r#"
29908        .foo {
29909          color-scheme: light;
29910        }
29911
29912        .bar {
29913          color: light-dark(red, green);
29914        }
29915      "#},
29916      Targets {
29917        browsers: Some(Browsers {
29918          safari: Some(13 << 16),
29919          ..Browsers::default()
29920        }),
29921        include: Features::empty(),
29922        exclude: Features::LightDark,
29923      },
29924    );
29925  }
29926
29927  #[test]
29928  fn test_all() {
29929    minify_test(".foo { all: initial; all: initial }", ".foo{all:initial}");
29930    minify_test(".foo { all: initial; all: revert }", ".foo{all:revert}");
29931    minify_test(".foo { background: red; all: revert-layer }", ".foo{all:revert-layer}");
29932    minify_test(
29933      ".foo { background: red; all: revert-layer; background: green }",
29934      ".foo{all:revert-layer;background:green}",
29935    );
29936    minify_test(
29937      ".foo { --test: red; all: revert-layer }",
29938      ".foo{--test:red;all:revert-layer}",
29939    );
29940    minify_test(
29941      ".foo { unicode-bidi: embed; all: revert-layer }",
29942      ".foo{all:revert-layer;unicode-bidi:embed}",
29943    );
29944    minify_test(
29945      ".foo { direction: rtl; all: revert-layer }",
29946      ".foo{all:revert-layer;direction:rtl}",
29947    );
29948    minify_test(
29949      ".foo { direction: rtl; all: revert-layer; direction: ltr }",
29950      ".foo{all:revert-layer;direction:ltr}",
29951    );
29952    minify_test(".foo { background: var(--foo); all: unset; }", ".foo{all:unset}");
29953    minify_test(
29954      ".foo { all: unset; background: var(--foo); }",
29955      ".foo{all:unset;background:var(--foo)}",
29956    );
29957    minify_test(
29958      ".foo {--bar:currentcolor; --foo:1.1em; all:unset}",
29959      ".foo{--bar:currentcolor;--foo:1.1em;all:unset}",
29960    );
29961  }
29962
29963  #[test]
29964  fn test_view_transition() {
29965    minify_test(
29966      "@view-transition { navigation: auto }",
29967      "@view-transition{navigation:auto}",
29968    );
29969    minify_test(
29970      "@view-transition { navigation: auto; types: none; }",
29971      "@view-transition{navigation:auto;types:none}",
29972    );
29973    minify_test(
29974      "@view-transition { navigation: auto; types: foo bar; }",
29975      "@view-transition{navigation:auto;types:foo bar}",
29976    );
29977    minify_test(
29978      "@layer { @view-transition { navigation: auto; types: foo bar; } }",
29979      "@layer{@view-transition{navigation:auto;types:foo bar}}",
29980    );
29981  }
29982
29983  #[test]
29984  fn test_skip_generating_unnecessary_fallbacks() {
29985    prefix_test(
29986      r#"
29987      @supports (color: lab(0% 0 0)) and (color: color(display-p3 0 0 0)) {
29988        .foo {
29989          color: lab(40% 56.6 39);
29990        }
29991
29992        .bar {
29993          color: color(display-p3 .643308 .192455 .167712);
29994        }
29995      }
29996      "#,
29997      indoc! {r#"
29998      @supports (color: lab(0% 0 0)) and (color: color(display-p3 0 0 0)) {
29999        .foo {
30000          color: lab(40% 56.6 39);
30001        }
30002
30003        .bar {
30004          color: color(display-p3 .643308 .192455 .167712);
30005        }
30006      }
30007      "#},
30008      Browsers {
30009        chrome: Some(4 << 16),
30010        ..Browsers::default()
30011      },
30012    );
30013
30014    prefix_test(
30015      r#"
30016      @supports (color: lab(40% 56.6 39)) {
30017        .foo {
30018          color: lab(40% 56.6 39);
30019        }
30020      }
30021      "#,
30022      indoc! {r#"
30023      @supports (color: lab(40% 56.6 39)) {
30024        .foo {
30025          color: lab(40% 56.6 39);
30026        }
30027      }
30028      "#},
30029      Browsers {
30030        chrome: Some(4 << 16),
30031        ..Browsers::default()
30032      },
30033    );
30034
30035    prefix_test(
30036      r#"
30037      @supports (background-color: lab(40% 56.6 39)) {
30038        .foo {
30039          background-color: lab(40% 56.6 39);
30040        }
30041      }
30042      "#,
30043      indoc! {r#"
30044      @supports (background-color: lab(40% 56.6 39)) {
30045        .foo {
30046          background-color: lab(40% 56.6 39);
30047        }
30048      }
30049      "#},
30050      Browsers {
30051        chrome: Some(4 << 16),
30052        ..Browsers::default()
30053      },
30054    );
30055
30056    prefix_test(
30057      r#"
30058      @supports (color: light-dark(#f00, #00f)) {
30059        .foo {
30060          color: light-dark(#ff0, #0ff);
30061        }
30062      }
30063      "#,
30064      indoc! {r#"
30065      @supports (color: light-dark(#f00, #00f)) {
30066        .foo {
30067          color: light-dark(#ff0, #0ff);
30068        }
30069      }
30070      "#},
30071      Browsers {
30072        chrome: Some(4 << 16),
30073        ..Browsers::default()
30074      },
30075    );
30076
30077    // NOTE: fallback for lab is not necessary
30078    prefix_test(
30079      r#"
30080      @supports (color: lab(0% 0 0)) and (not (color: color(display-p3 0 0 0))) {
30081        .foo {
30082          color: lab(40% 56.6 39);
30083        }
30084
30085        .bar {
30086          color: color(display-p3 .643308 .192455 .167712);
30087        }
30088      }
30089      "#,
30090      indoc! {r#"
30091      @supports (color: lab(0% 0 0)) and (not (color: color(display-p3 0 0 0))) {
30092        .foo {
30093          color: #b32323;
30094          color: lab(40% 56.6 39);
30095        }
30096
30097        .bar {
30098          color: #b32323;
30099          color: color(display-p3 .643308 .192455 .167712);
30100        }
30101      }
30102      "#},
30103      Browsers {
30104        chrome: Some(4 << 16),
30105        ..Browsers::default()
30106      },
30107    );
30108
30109    prefix_test(
30110      r#"
30111      @supports (color: lab(0% 0 0)) or (color: color(display-p3 0 0 0)) {
30112        .foo {
30113          color: lab(40% 56.6 39);
30114        }
30115
30116        .bar {
30117          color: color(display-p3 .643308 .192455 .167712);
30118        }
30119      }
30120      "#,
30121      indoc! {r#"
30122      @supports (color: lab(0% 0 0)) or (color: color(display-p3 0 0 0)) {
30123        .foo {
30124          color: #b32323;
30125          color: lab(40% 56.6 39);
30126        }
30127
30128        .bar {
30129          color: #b32323;
30130          color: color(display-p3 .643308 .192455 .167712);
30131        }
30132      }
30133      "#},
30134      Browsers {
30135        chrome: Some(4 << 16),
30136        ..Browsers::default()
30137      },
30138    );
30139  }
30140}