Skip to main content

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// This third-party fork retains upstream implementation style. Workspace
18// membership is for distribution and regression tests, not Vize style rules.
19#![allow(clippy::all, clippy::wildcard_imports)]
20#![deny(missing_docs)]
21#![cfg_attr(docsrs, feature(doc_cfg))]
22
23#[cfg(feature = "bundler")]
24#[cfg_attr(docsrs, doc(cfg(feature = "bundler")))]
25pub mod bundler;
26mod compat;
27mod context;
28pub mod css_modules;
29pub mod declaration;
30pub mod dependencies;
31pub mod error;
32mod logical;
33mod macros;
34pub mod media_query;
35mod parser;
36mod prefixes;
37pub mod printer;
38pub mod properties;
39pub mod rules;
40pub mod selector;
41pub mod stylesheet;
42pub mod targets;
43pub mod traits;
44pub mod values;
45pub mod vendor_prefix;
46#[cfg(feature = "visitor")]
47#[cfg_attr(docsrs, doc(cfg(feature = "visitor")))]
48pub mod visitor;
49
50#[cfg(feature = "serde")]
51mod serialization;
52
53#[cfg(test)]
54mod test_helpers;
55
56#[cfg(test)]
57mod tests {
58  use crate::css_modules::{CssModuleExport, CssModuleExports, CssModuleReference, CssModuleReferences};
59  use crate::dependencies::Dependency;
60  use crate::error::{Error, ErrorLocation, MinifyErrorKind, ParserError, PrinterErrorKind, SelectorError};
61  use crate::parser::ParserFlags;
62  use crate::properties::custom::Token;
63  use crate::properties::Property;
64  use crate::rules::CssRule;
65  use crate::rules::Location;
66  use crate::stylesheet::*;
67  use crate::targets::{Browsers, Features, Targets};
68  use crate::test_helpers::panic_with_test_error;
69  use crate::traits::{Parse, ToCss};
70  use crate::values::color::CssColor;
71  use crate::vendor_prefix::VendorPrefix;
72  use cssparser::SourceLocation;
73  use indoc::indoc;
74  use pretty_assertions::assert_eq;
75  use std::collections::HashMap;
76  use std::sync::{Arc, RwLock};
77
78  #[track_caller]
79  fn test(source: &str, expected: &str) {
80    test_with_options(source, expected, ParserOptions::default())
81  }
82
83  #[track_caller]
84  fn test_with_options<'i>(source: &'i str, expected: &'i str, options: ParserOptions<'i>) {
85    let mut stylesheet = match StyleSheet::parse(&source, options) {
86      Ok(stylesheet) => stylesheet,
87      Err(e) => panic_with_test_error("test_with_options", "parse", source, e),
88    };
89    if let Err(e) = stylesheet.minify(MinifyOptions::default()) {
90      panic_with_test_error("test_with_options", "minify", source, e);
91    }
92    let res = match stylesheet.to_css(PrinterOptions::default()) {
93      Ok(res) => res,
94      Err(e) => panic_with_test_error("test_with_options", "print", source, e),
95    };
96    assert_eq!(res.code, expected);
97  }
98
99  #[track_caller]
100  fn test_with_printer_options<'i>(source: &'i str, expected: &'i str, options: PrinterOptions<'i>) {
101    let mut stylesheet = match StyleSheet::parse(&source, ParserOptions::default()) {
102      Ok(stylesheet) => stylesheet,
103      Err(e) => panic_with_test_error("test_with_printer_options", "parse", source, e),
104    };
105    if let Err(e) = stylesheet.minify(MinifyOptions::default()) {
106      panic_with_test_error("test_with_printer_options", "minify", source, e);
107    }
108    let res = match stylesheet.to_css(options) {
109      Ok(res) => res,
110      Err(e) => panic_with_test_error("test_with_printer_options", "print", source, e),
111    };
112    assert_eq!(res.code, expected);
113  }
114
115  #[track_caller]
116  fn minify_test(source: &str, expected: &str) {
117    minify_test_with_options(source, expected, ParserOptions::default())
118  }
119
120  #[track_caller]
121  fn minify_test_with_options<'i>(source: &'i str, expected: &'i str, options: ParserOptions<'i>) {
122    minify_test_with_options_and_browsers(source, expected, options, None)
123  }
124
125  #[track_caller]
126  fn minify_test_with_options_and_browsers<'i>(
127    source: &'i str,
128    expected: &'i str,
129    options: ParserOptions<'i>,
130    browsers: Option<Browsers>,
131  ) {
132    let targets = browsers.into();
133    let mut stylesheet = match StyleSheet::parse(&source, options) {
134      Ok(stylesheet) => stylesheet,
135      Err(e) => panic_with_test_error("minify_test_with_options", "parse", source, e),
136    };
137    if let Err(e) = stylesheet.minify(MinifyOptions {
138      targets,
139      ..MinifyOptions::default()
140    }) {
141      panic_with_test_error("minify_test_with_options", "minify", source, e);
142    }
143    let res = match stylesheet.to_css(PrinterOptions {
144      minify: true,
145      targets,
146      ..PrinterOptions::default()
147    }) {
148      Ok(res) => res,
149      Err(e) => panic_with_test_error("minify_test_with_options", "print", source, e),
150    };
151    assert_eq!(res.code, expected);
152  }
153
154  #[track_caller]
155  fn minify_error_test_with_options<'i>(source: &'i str, error: MinifyErrorKind, options: ParserOptions<'i>) {
156    let mut stylesheet = match StyleSheet::parse(&source, options) {
157      Ok(stylesheet) => stylesheet,
158      Err(e) => panic_with_test_error("minify_error_test_with_options", "parse", source, e),
159    };
160    match stylesheet.minify(MinifyOptions::default()) {
161      Err(e) => assert_eq!(e.kind, error),
162      Ok(()) => panic!(
163        "minify_error_test_with_options: expected minify error {:?}, but minification succeeded.\nsource:\n{source}",
164        error
165      ),
166    }
167  }
168
169  #[track_caller]
170  fn prefix_test(source: &str, expected: &str, targets: Browsers) {
171    let mut stylesheet = match StyleSheet::parse(&source, ParserOptions::default()) {
172      Ok(stylesheet) => stylesheet,
173      Err(e) => panic_with_test_error("prefix_test", "parse", source, e),
174    };
175    if let Err(e) = stylesheet.minify(MinifyOptions {
176      targets: targets.into(),
177      ..MinifyOptions::default()
178    }) {
179      panic_with_test_error("prefix_test", "minify", source, e);
180    }
181    let res = match stylesheet.to_css(PrinterOptions {
182      targets: targets.into(),
183      ..PrinterOptions::default()
184    }) {
185      Ok(res) => res,
186      Err(e) => panic_with_test_error("prefix_test", "print", source, e),
187    };
188    assert_eq!(res.code, expected);
189  }
190
191  #[track_caller]
192  fn attr_test(source: &str, expected: &str, minify: bool, targets: Option<Browsers>) {
193    let mut attr = match StyleAttribute::parse(source, ParserOptions::default()) {
194      Ok(attr) => attr,
195      Err(e) => panic_with_test_error("attr_test", "parse", source, e),
196    };
197    attr.minify(MinifyOptions {
198      targets: targets.into(),
199      ..MinifyOptions::default()
200    });
201    let res = match attr.to_css(PrinterOptions {
202      targets: targets.into(),
203      minify,
204      ..PrinterOptions::default()
205    }) {
206      Ok(res) => res,
207      Err(e) => panic_with_test_error("attr_test", "print", source, e),
208    };
209    assert_eq!(res.code, expected);
210  }
211
212  #[track_caller]
213  fn nesting_test(source: &str, expected: &str) {
214    nesting_test_with_targets(
215      source,
216      expected,
217      Browsers {
218        chrome: Some(95 << 16),
219        ..Browsers::default()
220      }
221      .into(),
222    );
223  }
224
225  #[track_caller]
226  fn nesting_test_with_targets(source: &str, expected: &str, targets: Targets) {
227    let mut stylesheet = match StyleSheet::parse(&source, ParserOptions::default()) {
228      Ok(stylesheet) => stylesheet,
229      Err(e) => panic_with_test_error("nesting_test_with_targets", "parse", source, e),
230    };
231    if let Err(e) = stylesheet.minify(MinifyOptions {
232      targets,
233      ..MinifyOptions::default()
234    }) {
235      panic_with_test_error("nesting_test_with_targets", "minify", source, e);
236    }
237    let res = match stylesheet.to_css(PrinterOptions {
238      targets,
239      ..PrinterOptions::default()
240    }) {
241      Ok(res) => res,
242      Err(e) => panic_with_test_error("nesting_test_with_targets", "print", source, e),
243    };
244    assert_eq!(res.code, expected);
245  }
246
247  #[track_caller]
248  fn nesting_test_no_targets(source: &str, expected: &str) {
249    let mut stylesheet = match StyleSheet::parse(&source, ParserOptions::default()) {
250      Ok(stylesheet) => stylesheet,
251      Err(e) => panic_with_test_error("nesting_test_no_targets", "parse", source, e),
252    };
253    if let Err(e) = stylesheet.minify(MinifyOptions::default()) {
254      panic_with_test_error("nesting_test_no_targets", "minify", source, e);
255    }
256    let res = match stylesheet.to_css(PrinterOptions::default()) {
257      Ok(res) => res,
258      Err(e) => panic_with_test_error("nesting_test_no_targets", "print", source, e),
259    };
260    assert_eq!(res.code, expected);
261  }
262
263  #[track_caller]
264  fn css_modules_test<'i>(
265    source: &'i str,
266    expected: &str,
267    expected_exports: CssModuleExports,
268    expected_references: CssModuleReferences,
269    config: crate::css_modules::Config,
270    minify: bool,
271  ) {
272    let mut stylesheet = match StyleSheet::parse(
273      &source,
274      ParserOptions {
275        filename: "test.css".into(),
276        css_modules: Some(config),
277        ..ParserOptions::default()
278      },
279    ) {
280      Ok(stylesheet) => stylesheet,
281      Err(e) => panic_with_test_error("css_modules_test", "parse", source, e),
282    };
283    if let Err(e) = stylesheet.minify(MinifyOptions::default()) {
284      panic_with_test_error("css_modules_test", "minify", source, e);
285    }
286    let res = match stylesheet.to_css(PrinterOptions {
287      minify,
288      ..Default::default()
289    }) {
290      Ok(res) => res,
291      Err(e) => panic_with_test_error("css_modules_test", "print", source, e),
292    };
293    assert_eq!(res.code, expected);
294    match res.exports {
295      Some(exports) => assert_eq!(exports, expected_exports),
296      None => panic!("css_modules_test: expected CSS module exports, but got None.\nsource:\n{source}"),
297    }
298    match res.references {
299      Some(references) => assert_eq!(references, expected_references),
300      None => panic!("css_modules_test: expected CSS module references, but got None.\nsource:\n{source}"),
301    }
302  }
303
304  #[track_caller]
305  fn custom_media_test(source: &str, expected: &str) {
306    let mut stylesheet = match StyleSheet::parse(
307      &source,
308      ParserOptions {
309        flags: ParserFlags::CUSTOM_MEDIA,
310        ..ParserOptions::default()
311      },
312    ) {
313      Ok(stylesheet) => stylesheet,
314      Err(e) => panic_with_test_error("custom_media_test", "parse", source, e),
315    };
316    if let Err(e) = stylesheet.minify(MinifyOptions {
317      targets: Browsers {
318        chrome: Some(95 << 16),
319        ..Browsers::default()
320      }
321      .into(),
322      ..MinifyOptions::default()
323    }) {
324      panic_with_test_error("custom_media_test", "minify", source, e);
325    }
326    let res = match stylesheet.to_css(PrinterOptions::default()) {
327      Ok(res) => res,
328      Err(e) => panic_with_test_error("custom_media_test", "print", source, e),
329    };
330    assert_eq!(res.code, expected);
331  }
332
333  fn error_test(source: &str, error: ParserError) {
334    let res = StyleSheet::parse(&source, ParserOptions::default());
335    match res {
336      Ok(_) => unreachable!(),
337      Err(e) => assert_eq!(e.kind, error),
338    }
339  }
340
341  fn error_test_with_options<'i>(source: &'i str, error: ParserError<'i>, options: ParserOptions<'i>) {
342    let res = StyleSheet::parse(&source, options);
343    match res {
344      Ok(_) => unreachable!(),
345      Err(e) => assert_eq!(e.kind, error),
346    }
347  }
348
349  fn error_recovery_test(source: &str) -> Vec<Error<ParserError<'_>>> {
350    let warnings = Arc::new(RwLock::default());
351    {
352      let res = StyleSheet::parse(
353        &source,
354        ParserOptions {
355          error_recovery: true,
356          warnings: Some(warnings.clone()),
357          ..Default::default()
358        },
359      );
360      match res {
361        Ok(..) => {}
362        Err(e) => unreachable!("parser error should be recovered, but got {e:?}"),
363      }
364    }
365    let warnings = match Arc::into_inner(warnings) {
366      Some(warnings) => warnings,
367      None => panic!("error_recovery_test: expected a single Arc owner for warnings"),
368    };
369    match warnings.into_inner() {
370      Ok(warnings) => warnings,
371      Err(e) => panic!("error_recovery_test: warnings lock is poisoned: {e}"),
372    }
373  }
374
375  fn css_modules_error_test(source: &str, error: ParserError) {
376    let res = StyleSheet::parse(
377      &source,
378      ParserOptions {
379        css_modules: Some(Default::default()),
380        ..Default::default()
381      },
382    );
383    match res {
384      Ok(_) => unreachable!(),
385      Err(e) => assert_eq!(e.kind, error),
386    }
387  }
388
389  macro_rules! map(
390    { $($key:expr => $name:literal $(referenced: $referenced: literal)? $($value:literal $(global: $global: literal)? $(from $from:literal)?)*),* } => {
391      {
392        #[allow(unused_mut)]
393        let mut m = HashMap::new();
394        $(
395          #[allow(unused_mut)]
396          let mut v = Vec::new();
397          #[allow(unused_macros)]
398          macro_rules! insert {
399            ($local:literal from $specifier:literal) => {
400              v.push(CssModuleReference::Dependency {
401                name: $local.into(),
402                specifier: $specifier.into()
403              });
404            };
405            ($local:literal global: $is_global: literal) => {
406              v.push(CssModuleReference::Global {
407                name: $local.into()
408              });
409            };
410            ($local:literal) => {
411              v.push(CssModuleReference::Local {
412                name: $local.into()
413              });
414            };
415          }
416          $(
417            insert!($value $(global: $global)? $(from $from)?);
418          )*
419
420          macro_rules! is_referenced {
421            ($ref: literal) => {
422              $ref
423            };
424            () => {
425              false
426            };
427          }
428
429          m.insert($key.into(), CssModuleExport {
430            name: $name.into(),
431            composes: v,
432            is_referenced: is_referenced!($($referenced)?)
433          });
434        )*
435        m
436      }
437    };
438  );
439
440  #[test]
441  pub fn test_border_spacing() {
442    minify_test(
443      r#"
444      .foo {
445        border-spacing: 0px;
446      }
447    "#,
448      indoc! {".foo{border-spacing:0}"
449      },
450    );
451    minify_test(
452      r#"
453      .foo {
454        border-spacing: 0px 0px;
455      }
456    "#,
457      indoc! {".foo{border-spacing:0}"
458      },
459    );
460
461    minify_test(
462      r#"
463      .foo {
464        border-spacing: 12px   0px;
465      }
466    "#,
467      indoc! {".foo{border-spacing:12px 0}"
468      },
469    );
470
471    minify_test(
472      r#"
473      .foo {
474        border-spacing: calc(3px * 2) calc(5px * 0);
475      }
476    "#,
477      indoc! {".foo{border-spacing:6px 0}"
478      },
479    );
480
481    minify_test(
482      r#"
483      .foo {
484        border-spacing: calc(3px * 2) max(0px, 8px);
485      }
486    "#,
487      indoc! {".foo{border-spacing:6px 8px}"
488      },
489    );
490
491    // TODO: The `<length>` in border-spacing cannot have a negative value,
492    // we may need to implement NonNegativeLength like Servo does.
493    // Servo Code: https://github.com/servo/servo/blob/08bc2d53579c9ab85415d4363888881b91df073b/components/style/values/specified/length.rs#L875
494    // CSSWG issue: https://lists.w3.org/Archives/Public/www-style/2008Sep/0161.html
495    // `border-spacing = <length> <length>?`
496    minify_test(
497      r#"
498      .foo {
499        border-spacing: -20px;
500      }
501    "#,
502      indoc! {".foo{border-spacing:-20px}"
503      },
504    );
505  }
506
507  #[test]
508  pub fn test_math_fn() {
509    // max()
510    minify_test(
511      r#"
512      .foo {
513        color: rgb(max(255, 100), 0, 0);
514      }
515    "#,
516      indoc! {".foo{color:red}"
517      },
518    );
519    // min()
520    minify_test(
521      r#"
522      .foo {
523        color: rgb(min(255, 500), 0, 0);
524      }
525    "#,
526      indoc! {".foo{color:red}"
527      },
528    );
529    // abs()
530    minify_test(
531      r#"
532      .foo {
533        color: rgb(abs(-255), 0, 0);
534      }
535    "#,
536      indoc! {".foo{color:red}"
537      },
538    );
539    // clamp()
540    minify_test(
541      r#"
542      .foo {
543        flex: clamp(1, 5.20, 20);
544        color: rgb(clamp(0, 255, 300), 0, 0);
545      }
546    "#,
547      indoc! {".foo{color:red;flex:5.2}"
548      },
549    );
550    // round()
551    minify_test(
552      r#"
553      .round-color {
554        color: rgb(round(down, 255.6, 1), 0, 0);
555      }
556    "#,
557      indoc! {".round-color{color:red}"
558      },
559    );
560    // hypot()
561    minify_test(
562      r#"
563      .hypot-color {
564        color: rgb(hypot(255, 0), 0, 0);
565      }
566    "#,
567      indoc! {".hypot-color{color:red}"
568      },
569    );
570    // sign(), sign(50) = 1
571    minify_test(
572      r#"
573      .sign-color {
574        color: rgb(sign(50), 0, 0);
575      }
576    "#,
577      indoc! {".sign-color{color:#010000}"
578      },
579    );
580    // rem(), rem(21, 2) = 1
581    minify_test(
582      r#"
583      .rem-color {
584        color: rgb(rem(21, 2), 0, 0);
585      }
586    "#,
587      indoc! {".rem-color{color:#010000}"
588      },
589    );
590    // max() in width
591    minify_test(
592      r#"
593      .foo {
594        width: max(200px,   5px);
595      }
596    "#,
597      indoc! {".foo{width:200px}"
598      },
599    );
600    // max() in opacity
601    minify_test(
602      r#"
603      .foo {
604        opacity: max(1, 0.2);
605        filter: invert(min(1, 0.5));
606      }
607    "#,
608      indoc! {".foo{opacity:1;filter:invert(.5)}"
609      },
610    );
611    // TODO: support calc in Integer
612    // minify_test(
613    //   r#"
614    //   .foo {
615    //     z-index: max(100,    20);
616    //   }
617    // "#,
618    //   indoc! {".foo{z-index:100}"
619    //   },
620    // );
621  }
622
623  #[test]
624  pub fn test_border() {
625    test(
626      r#"
627      .foo {
628        border-left: 2px solid red;
629        border-right: 2px solid red;
630        border-bottom: 2px solid red;
631        border-top: 2px solid red;
632      }
633    "#,
634      indoc! {r#"
635      .foo {
636        border: 2px solid red;
637      }
638    "#
639      },
640    );
641
642    test(
643      r#"
644      .foo {
645        border-left-color: red;
646        border-right-color: red;
647        border-bottom-color: red;
648        border-top-color: red;
649      }
650    "#,
651      indoc! {r#"
652      .foo {
653        border-color: red;
654      }
655    "#
656      },
657    );
658
659    test(
660      r#"
661      .foo {
662        border-left-width: thin;
663        border-right-width: thin;
664        border-bottom-width: thin;
665        border-top-width: thin;
666      }
667    "#,
668      indoc! {r#"
669      .foo {
670        border-width: thin;
671      }
672    "#
673      },
674    );
675
676    test(
677      r#"
678      .foo {
679        border-left-style: dotted;
680        border-right-style: dotted;
681        border-bottom-style: dotted;
682        border-top-style: dotted;
683      }
684    "#,
685      indoc! {r#"
686      .foo {
687        border-style: dotted;
688      }
689    "#
690      },
691    );
692
693    test(
694      r#"
695      .foo {
696        border-left-width: thin;
697        border-left-style: dotted;
698        border-left-color: red;
699      }
700    "#,
701      indoc! {r#"
702      .foo {
703        border-left: thin dotted red;
704      }
705    "#
706      },
707    );
708
709    test(
710      r#"
711      .foo {
712        border-left-width: thick;
713        border-left: thin dotted red;
714      }
715    "#,
716      indoc! {r#"
717      .foo {
718        border-left: thin dotted red;
719      }
720    "#
721      },
722    );
723
724    test(
725      r#"
726      .foo {
727        border-left-width: thick;
728        border: thin dotted red;
729      }
730    "#,
731      indoc! {r#"
732      .foo {
733        border: thin dotted red;
734      }
735    "#
736      },
737    );
738
739    test(
740      r#"
741      .foo {
742        border: thin dotted red;
743        border-right-width: thick;
744      }
745    "#,
746      indoc! {r#"
747      .foo {
748        border: thin dotted red;
749        border-right-width: thick;
750      }
751    "#
752      },
753    );
754
755    test(
756      r#"
757      .foo {
758        border: thin dotted red;
759        border-right: thick dotted red;
760      }
761    "#,
762      indoc! {r#"
763      .foo {
764        border: thin dotted red;
765        border-right-width: thick;
766      }
767    "#
768      },
769    );
770
771    test(
772      r#"
773      .foo {
774        border: thin dotted red;
775        border-right-width: thick;
776        border-right-style: solid;
777      }
778    "#,
779      indoc! {r#"
780      .foo {
781        border: thin dotted red;
782        border-right: thick solid red;
783      }
784    "#
785      },
786    );
787
788    test(
789      r#"
790      .foo {
791        border-top: thin dotted red;
792        border-block-start: thick solid green;
793      }
794    "#,
795      indoc! {r#"
796      .foo {
797        border-top: thin dotted red;
798        border-block-start: thick solid green;
799      }
800    "#
801      },
802    );
803
804    test(
805      r#"
806      .foo {
807        border: thin dotted red;
808        border-block-start-width: thick;
809        border-left-width: medium;
810      }
811    "#,
812      indoc! {r#"
813      .foo {
814        border: thin dotted red;
815        border-block-start-width: thick;
816        border-left-width: medium;
817      }
818    "#
819      },
820    );
821
822    test(
823      r#"
824      .foo {
825        border-block-start: thin dotted red;
826        border-inline-end: thin dotted red;
827      }
828    "#,
829      indoc! {r#"
830      .foo {
831        border-block-start: thin dotted red;
832        border-inline-end: thin dotted red;
833      }
834    "#
835      },
836    );
837
838    test(
839      r#"
840      .foo {
841        border-block-start-width: thin;
842        border-block-start-style: dotted;
843        border-block-start-color: red;
844        border-inline-end: thin dotted red;
845      }
846    "#,
847      indoc! {r#"
848      .foo {
849        border-block-start: thin dotted red;
850        border-inline-end: thin dotted red;
851      }
852    "#
853      },
854    );
855
856    test(
857      r#"
858      .foo {
859        border-block-start: thin dotted red;
860        border-block-end: thin dotted red;
861      }
862    "#,
863      indoc! {r#"
864      .foo {
865        border-block: thin dotted red;
866      }
867    "#
868      },
869    );
870
871    minify_test(
872      r#"
873      .foo {
874        border: none;
875      }
876    "#,
877      indoc! {".foo{border:none}"
878      },
879    );
880
881    minify_test(".foo { border-width: 0 0 1px; }", ".foo{border-width:0 0 1px}");
882    test(
883      r#"
884      .foo {
885        border-block-width: 1px;
886        border-inline-width: 1px;
887      }
888    "#,
889      indoc! {r#"
890      .foo {
891        border-width: 1px;
892      }
893    "#
894      },
895    );
896    test(
897      r#"
898      .foo {
899        border-block-start-width: 1px;
900        border-block-end-width: 1px;
901        border-inline-start-width: 1px;
902        border-inline-end-width: 1px;
903      }
904    "#,
905      indoc! {r#"
906      .foo {
907        border-width: 1px;
908      }
909    "#
910      },
911    );
912    test(
913      r#"
914      .foo {
915        border-block-start-width: 1px;
916        border-block-end-width: 1px;
917        border-inline-start-width: 2px;
918        border-inline-end-width: 2px;
919      }
920    "#,
921      indoc! {r#"
922      .foo {
923        border-block-width: 1px;
924        border-inline-width: 2px;
925      }
926    "#
927      },
928    );
929    test(
930      r#"
931      .foo {
932        border-block-start-width: 1px;
933        border-block-end-width: 1px;
934        border-inline-start-width: 2px;
935        border-inline-end-width: 3px;
936      }
937    "#,
938      indoc! {r#"
939      .foo {
940        border-block-width: 1px;
941        border-inline-width: 2px 3px;
942      }
943    "#
944      },
945    );
946
947    minify_test(
948      ".foo { border-bottom: 1px solid var(--spectrum-global-color-gray-200)}",
949      ".foo{border-bottom:1px solid var(--spectrum-global-color-gray-200)}",
950    );
951    test(
952      r#"
953      .foo {
954        border-width: 0;
955        border-bottom: var(--test, 1px) solid;
956      }
957    "#,
958      indoc! {r#"
959      .foo {
960        border-width: 0;
961        border-bottom: var(--test, 1px) solid;
962      }
963    "#
964      },
965    );
966
967    test(
968      r#"
969      .foo {
970        border: 1px solid black;
971        border-width: 1px 1px 0 0;
972      }
973    "#,
974      indoc! {r#"
975      .foo {
976        border: 1px solid #000;
977        border-width: 1px 1px 0 0;
978      }
979    "#},
980    );
981
982    test(
983      r#"
984      .foo {
985        border-top: 1px solid black;
986        border-bottom: 1px solid black;
987        border-left: 2px solid black;
988        border-right: 2px solid black;
989      }
990    "#,
991      indoc! {r#"
992      .foo {
993        border: 1px solid #000;
994        border-width: 1px 2px;
995      }
996    "#},
997    );
998
999    test(
1000      r#"
1001      .foo {
1002        border-top: 1px solid black;
1003        border-bottom: 1px solid black;
1004        border-left: 2px solid black;
1005        border-right: 1px solid black;
1006      }
1007    "#,
1008      indoc! {r#"
1009      .foo {
1010        border: 1px solid #000;
1011        border-left-width: 2px;
1012      }
1013    "#},
1014    );
1015
1016    test(
1017      r#"
1018      .foo {
1019        border-top: 1px solid black;
1020        border-bottom: 1px solid black;
1021        border-left: 1px solid red;
1022        border-right: 1px solid red;
1023      }
1024    "#,
1025      indoc! {r#"
1026      .foo {
1027        border: 1px solid #000;
1028        border-color: #000 red;
1029      }
1030    "#},
1031    );
1032
1033    test(
1034      r#"
1035      .foo {
1036        border-block-start: 1px solid black;
1037        border-block-end: 1px solid black;
1038        border-inline-start: 1px solid red;
1039        border-inline-end: 1px solid red;
1040      }
1041    "#,
1042      indoc! {r#"
1043      .foo {
1044        border: 1px solid #000;
1045        border-inline-color: red;
1046      }
1047    "#},
1048    );
1049
1050    test(
1051      r#"
1052      .foo {
1053        border-block-start: 1px solid black;
1054        border-block-end: 1px solid black;
1055        border-inline-start: 2px solid black;
1056        border-inline-end: 2px solid black;
1057      }
1058    "#,
1059      indoc! {r#"
1060      .foo {
1061        border: 1px solid #000;
1062        border-inline-width: 2px;
1063      }
1064    "#},
1065    );
1066
1067    test(
1068      r#"
1069      .foo {
1070        border-block-start: 1px solid black;
1071        border-block-end: 1px solid black;
1072        border-inline-start: 2px solid red;
1073        border-inline-end: 2px solid red;
1074      }
1075    "#,
1076      indoc! {r#"
1077      .foo {
1078        border: 1px solid #000;
1079        border-inline: 2px solid red;
1080      }
1081    "#},
1082    );
1083
1084    test(
1085      r#"
1086      .foo {
1087        border-block-start: 1px solid black;
1088        border-block-end: 1px solid black;
1089        border-inline-start: 2px solid red;
1090        border-inline-end: 3px solid red;
1091      }
1092    "#,
1093      indoc! {r#"
1094      .foo {
1095        border: 1px solid #000;
1096        border-inline-start: 2px solid red;
1097        border-inline-end: 3px solid red;
1098      }
1099    "#},
1100    );
1101
1102    test(
1103      r#"
1104      .foo {
1105        border-block-start: 2px solid black;
1106        border-block-end: 1px solid black;
1107        border-inline-start: 2px solid red;
1108        border-inline-end: 2px solid red;
1109      }
1110    "#,
1111      indoc! {r#"
1112      .foo {
1113        border: 2px solid red;
1114        border-block-start-color: #000;
1115        border-block-end: 1px solid #000;
1116      }
1117    "#},
1118    );
1119
1120    test(
1121      r#"
1122      .foo {
1123        border-block-start: 2px solid red;
1124        border-block-end: 1px solid red;
1125        border-inline-start: 2px solid red;
1126        border-inline-end: 2px solid red;
1127      }
1128    "#,
1129      indoc! {r#"
1130      .foo {
1131        border: 2px solid red;
1132        border-block-end-width: 1px;
1133      }
1134    "#},
1135    );
1136
1137    test(
1138      r#"
1139      .foo {
1140        border-block-start: 2px solid red;
1141        border-block-end: 2px solid red;
1142        border-inline-start: 2px solid red;
1143        border-inline-end: 1px solid red;
1144      }
1145    "#,
1146      indoc! {r#"
1147      .foo {
1148        border: 2px solid red;
1149        border-inline-end-width: 1px;
1150      }
1151    "#},
1152    );
1153
1154    test(
1155      r#"
1156      .foo {
1157        border: 1px solid currentColor;
1158      }
1159    "#,
1160      indoc! {r#"
1161      .foo {
1162        border: 1px solid;
1163      }
1164    "#
1165      },
1166    );
1167
1168    minify_test(
1169      r#"
1170      .foo {
1171        border: 1px solid currentColor;
1172      }
1173    "#,
1174      ".foo{border:1px solid}",
1175    );
1176
1177    prefix_test(
1178      r#"
1179      .foo {
1180        border-block: 2px solid red;
1181      }
1182    "#,
1183      indoc! {r#"
1184      .foo {
1185        border-top: 2px solid red;
1186        border-bottom: 2px solid red;
1187      }
1188    "#
1189      },
1190      Browsers {
1191        safari: Some(8 << 16),
1192        ..Browsers::default()
1193      },
1194    );
1195
1196    prefix_test(
1197      r#"
1198      .foo {
1199        border-block-start: 2px solid red;
1200      }
1201    "#,
1202      indoc! {r#"
1203      .foo {
1204        border-top: 2px solid red;
1205      }
1206    "#
1207      },
1208      Browsers {
1209        safari: Some(8 << 16),
1210        ..Browsers::default()
1211      },
1212    );
1213
1214    prefix_test(
1215      r#"
1216      .foo {
1217        border-block-end: 2px solid red;
1218      }
1219    "#,
1220      indoc! {r#"
1221      .foo {
1222        border-bottom: 2px solid red;
1223      }
1224    "#
1225      },
1226      Browsers {
1227        safari: Some(8 << 16),
1228        ..Browsers::default()
1229      },
1230    );
1231
1232    prefix_test(
1233      r#"
1234      .foo {
1235        border-inline: 2px solid red;
1236      }
1237    "#,
1238      indoc! {r#"
1239      .foo {
1240        border-left: 2px solid red;
1241        border-right: 2px solid red;
1242      }
1243    "#
1244      },
1245      Browsers {
1246        safari: Some(8 << 16),
1247        ..Browsers::default()
1248      },
1249    );
1250
1251    prefix_test(
1252      r#"
1253      .foo {
1254        border-block-width: 2px;
1255      }
1256    "#,
1257      indoc! {r#"
1258      .foo {
1259        border-block-start-width: 2px;
1260        border-block-end-width: 2px;
1261      }
1262    "#
1263      },
1264      Browsers {
1265        safari: Some(13 << 16),
1266        ..Browsers::default()
1267      },
1268    );
1269
1270    prefix_test(
1271      r#"
1272      .foo {
1273        border-block-width: 2px;
1274      }
1275    "#,
1276      indoc! {r#"
1277      .foo {
1278        border-block-width: 2px;
1279      }
1280    "#
1281      },
1282      Browsers {
1283        safari: Some(15 << 16),
1284        ..Browsers::default()
1285      },
1286    );
1287
1288    prefix_test(
1289      r#"
1290      .foo {
1291        border-inline-start: 2px solid red;
1292      }
1293    "#,
1294      indoc! {r#"
1295      .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))) {
1296        border-left: 2px solid red;
1297      }
1298
1299      .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))) {
1300        border-left: 2px solid red;
1301      }
1302
1303      .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)) {
1304        border-right: 2px solid red;
1305      }
1306
1307      .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)) {
1308        border-right: 2px solid red;
1309      }
1310    "#
1311      },
1312      Browsers {
1313        safari: Some(8 << 16),
1314        ..Browsers::default()
1315      },
1316    );
1317
1318    prefix_test(
1319      r#"
1320      .foo {
1321        border-inline-start-width: 2px;
1322      }
1323    "#,
1324      indoc! {r#"
1325      .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))) {
1326        border-left-width: 2px;
1327      }
1328
1329      .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))) {
1330        border-left-width: 2px;
1331      }
1332
1333      .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)) {
1334        border-right-width: 2px;
1335      }
1336
1337      .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)) {
1338        border-right-width: 2px;
1339      }
1340    "#
1341      },
1342      Browsers {
1343        safari: Some(8 << 16),
1344        ..Browsers::default()
1345      },
1346    );
1347
1348    prefix_test(
1349      r#"
1350      .foo {
1351        border-inline-end: 2px solid red;
1352      }
1353    "#,
1354      indoc! {r#"
1355      .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))) {
1356        border-right: 2px solid red;
1357      }
1358
1359      .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))) {
1360        border-right: 2px solid red;
1361      }
1362
1363      .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)) {
1364        border-left: 2px solid red;
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-left: 2px solid red;
1369      }
1370    "#
1371      },
1372      Browsers {
1373        safari: Some(8 << 16),
1374        ..Browsers::default()
1375      },
1376    );
1377
1378    prefix_test(
1379      r#"
1380      .foo {
1381        border-inline-start: 2px solid red;
1382        border-inline-end: 5px solid green;
1383      }
1384    "#,
1385      indoc! {r#"
1386      .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))) {
1387        border-left: 2px solid red;
1388        border-right: 5px solid green;
1389      }
1390
1391      .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))) {
1392        border-left: 2px solid red;
1393        border-right: 5px solid green;
1394      }
1395
1396      .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)) {
1397        border-left: 5px solid green;
1398        border-right: 2px solid red;
1399      }
1400
1401      .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)) {
1402        border-left: 5px solid green;
1403        border-right: 2px solid red;
1404      }
1405    "#
1406      },
1407      Browsers {
1408        safari: Some(8 << 16),
1409        ..Browsers::default()
1410      },
1411    );
1412
1413    prefix_test(
1414      r#"
1415      .foo {
1416        border-inline-start: 2px solid red;
1417        border-inline-end: 5px solid green;
1418      }
1419
1420      .bar {
1421        border-inline-start: 1px dotted gray;
1422        border-inline-end: 1px solid black;
1423      }
1424    "#,
1425      indoc! {r#"
1426      .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))) {
1427        border-left: 2px solid red;
1428        border-right: 5px solid green;
1429      }
1430
1431      .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))) {
1432        border-left: 2px solid red;
1433        border-right: 5px solid green;
1434      }
1435
1436      .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)) {
1437        border-left: 5px solid green;
1438        border-right: 2px solid red;
1439      }
1440
1441      .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)) {
1442        border-left: 5px solid green;
1443        border-right: 2px solid red;
1444      }
1445
1446      .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))) {
1447        border-left: 1px dotted gray;
1448        border-right: 1px solid #000;
1449      }
1450
1451      .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))) {
1452        border-left: 1px dotted gray;
1453        border-right: 1px solid #000;
1454      }
1455
1456      .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)) {
1457        border-left: 1px solid #000;
1458        border-right: 1px dotted gray;
1459      }
1460
1461      .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)) {
1462        border-left: 1px solid #000;
1463        border-right: 1px dotted gray;
1464      }
1465    "#
1466      },
1467      Browsers {
1468        safari: Some(8 << 16),
1469        ..Browsers::default()
1470      },
1471    );
1472
1473    prefix_test(
1474      r#"
1475      .foo {
1476        border-inline-width: 2px;
1477      }
1478    "#,
1479      indoc! {r#"
1480      .foo {
1481        border-left-width: 2px;
1482        border-right-width: 2px;
1483      }
1484    "#
1485      },
1486      Browsers {
1487        safari: Some(8 << 16),
1488        ..Browsers::default()
1489      },
1490    );
1491
1492    prefix_test(
1493      r#"
1494      .foo {
1495        border-inline-width: 2px;
1496      }
1497    "#,
1498      indoc! {r#"
1499      .foo {
1500        border-left-width: 2px;
1501        border-right-width: 2px;
1502      }
1503    "#
1504      },
1505      Browsers {
1506        safari: Some(8 << 16),
1507        ..Browsers::default()
1508      },
1509    );
1510
1511    prefix_test(
1512      r#"
1513      .foo {
1514        border-inline-style: solid;
1515      }
1516    "#,
1517      indoc! {r#"
1518      .foo {
1519        border-left-style: solid;
1520        border-right-style: solid;
1521      }
1522    "#
1523      },
1524      Browsers {
1525        safari: Some(8 << 16),
1526        ..Browsers::default()
1527      },
1528    );
1529
1530    prefix_test(
1531      r#"
1532      .foo {
1533        border-inline-color: red;
1534      }
1535    "#,
1536      indoc! {r#"
1537      .foo {
1538        border-left-color: red;
1539        border-right-color: red;
1540      }
1541    "#
1542      },
1543      Browsers {
1544        safari: Some(8 << 16),
1545        ..Browsers::default()
1546      },
1547    );
1548
1549    prefix_test(
1550      r#"
1551      .foo {
1552        border-inline-end: var(--test);
1553      }
1554    "#,
1555      indoc! {r#"
1556      .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))) {
1557        border-right: var(--test);
1558      }
1559
1560      .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))) {
1561        border-right: var(--test);
1562      }
1563
1564      .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)) {
1565        border-left: var(--test);
1566      }
1567
1568      .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)) {
1569        border-left: var(--test);
1570      }
1571    "#
1572      },
1573      Browsers {
1574        safari: Some(8 << 16),
1575        ..Browsers::default()
1576      },
1577    );
1578
1579    prefix_test(
1580      r#"
1581      .foo {
1582        border-inline-start: var(--start);
1583        border-inline-end: var(--end);
1584      }
1585    "#,
1586      indoc! {r#"
1587      .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))) {
1588        border-left: var(--start);
1589        border-right: var(--end);
1590      }
1591
1592      .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))) {
1593        border-left: var(--start);
1594        border-right: var(--end);
1595      }
1596
1597      .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)) {
1598        border-right: var(--start);
1599        border-left: var(--end);
1600      }
1601
1602      .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)) {
1603        border-right: var(--start);
1604        border-left: var(--end);
1605      }
1606    "#
1607      },
1608      Browsers {
1609        safari: Some(8 << 16),
1610        ..Browsers::default()
1611      },
1612    );
1613
1614    for prop in &[
1615      "border-inline-start-color",
1616      "border-inline-end-color",
1617      "border-block-start-color",
1618      "border-block-end-color",
1619      "border-top-color",
1620      "border-bottom-color",
1621      "border-left-color",
1622      "border-right-color",
1623      "border-color",
1624      "border-block-color",
1625      "border-inline-color",
1626    ] {
1627      prefix_test(
1628        &format!(
1629          r#"
1630        .foo {{
1631          {}: lab(40% 56.6 39);
1632        }}
1633      "#,
1634          prop
1635        ),
1636        &format!(
1637          indoc! {r#"
1638        .foo {{
1639          {}: #b32323;
1640          {}: lab(40% 56.6 39);
1641        }}
1642      "#},
1643          prop, prop
1644        ),
1645        Browsers {
1646          chrome: Some(90 << 16),
1647          ..Browsers::default()
1648        },
1649      );
1650    }
1651
1652    for prop in &[
1653      "border",
1654      "border-inline",
1655      "border-block",
1656      "border-left",
1657      "border-right",
1658      "border-top",
1659      "border-bottom",
1660      "border-block-start",
1661      "border-block-end",
1662      "border-inline-start",
1663      "border-inline-end",
1664    ] {
1665      prefix_test(
1666        &format!(
1667          r#"
1668        .foo {{
1669          {}: 2px solid lab(40% 56.6 39);
1670        }}
1671      "#,
1672          prop
1673        ),
1674        &format!(
1675          indoc! {r#"
1676        .foo {{
1677          {}: 2px solid #b32323;
1678          {}: 2px solid lab(40% 56.6 39);
1679        }}
1680      "#},
1681          prop, prop
1682        ),
1683        Browsers {
1684          chrome: Some(90 << 16),
1685          ..Browsers::default()
1686        },
1687      );
1688    }
1689
1690    for prop in &[
1691      "border",
1692      "border-inline",
1693      "border-block",
1694      "border-left",
1695      "border-right",
1696      "border-top",
1697      "border-bottom",
1698      "border-block-start",
1699      "border-block-end",
1700      "border-inline-start",
1701      "border-inline-end",
1702    ] {
1703      prefix_test(
1704        &format!(
1705          r#"
1706        .foo {{
1707          {}: var(--border-width) solid lab(40% 56.6 39);
1708        }}
1709      "#,
1710          prop
1711        ),
1712        &format!(
1713          indoc! {r#"
1714        .foo {{
1715          {}: var(--border-width) solid #b32323;
1716        }}
1717
1718        @supports (color: lab(0% 0 0)) {{
1719          .foo {{
1720            {}: var(--border-width) solid lab(40% 56.6 39);
1721          }}
1722        }}
1723      "#},
1724          prop, prop
1725        ),
1726        Browsers {
1727          chrome: Some(90 << 16),
1728          ..Browsers::default()
1729        },
1730      );
1731
1732      prefix_test(
1733        &format!(
1734          r#"
1735        @supports (color: lab(0% 0 0)) {{
1736          .foo {{
1737            {}: var(--border-width) solid lab(40% 56.6 39);
1738          }}
1739        }}
1740      "#,
1741          prop
1742        ),
1743        &format!(
1744          indoc! {r#"
1745        @supports (color: lab(0% 0 0)) {{
1746          .foo {{
1747            {}: var(--border-width) solid lab(40% 56.6 39);
1748          }}
1749        }}
1750      "#},
1751          prop,
1752        ),
1753        Browsers {
1754          chrome: Some(90 << 16),
1755          ..Browsers::default()
1756        },
1757      );
1758    }
1759
1760    prefix_test(
1761      r#"
1762      .foo {
1763        border-inline-start-color: lab(40% 56.6 39);
1764      }
1765    "#,
1766      indoc! {r#"
1767      .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))) {
1768        border-left-color: #b32323;
1769        border-left-color: lab(40% 56.6 39);
1770      }
1771
1772      .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))) {
1773        border-left-color: #b32323;
1774        border-left-color: lab(40% 56.6 39);
1775      }
1776
1777      .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)) {
1778        border-right-color: #b32323;
1779        border-right-color: lab(40% 56.6 39);
1780      }
1781
1782      .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)) {
1783        border-right-color: #b32323;
1784        border-right-color: lab(40% 56.6 39);
1785      }
1786    "#},
1787      Browsers {
1788        safari: Some(8 << 16),
1789        ..Browsers::default()
1790      },
1791    );
1792
1793    prefix_test(
1794      r#"
1795      .foo {
1796        border-inline-end-color: lab(40% 56.6 39);
1797      }
1798    "#,
1799      indoc! {r#"
1800      .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))) {
1801        border-right-color: #b32323;
1802        border-right-color: lab(40% 56.6 39);
1803      }
1804
1805      .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))) {
1806        border-right-color: #b32323;
1807        border-right-color: lab(40% 56.6 39);
1808      }
1809
1810      .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)) {
1811        border-left-color: #b32323;
1812        border-left-color: lab(40% 56.6 39);
1813      }
1814
1815      .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)) {
1816        border-left-color: #b32323;
1817        border-left-color: lab(40% 56.6 39);
1818      }
1819    "#},
1820      Browsers {
1821        safari: Some(8 << 16),
1822        ..Browsers::default()
1823      },
1824    );
1825
1826    prefix_test(
1827      r#"
1828      .foo {
1829        border-inline-start-color: lab(40% 56.6 39);
1830        border-inline-end-color: lch(50.998% 135.363 338);
1831      }
1832    "#,
1833      indoc! {r#"
1834      .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))) {
1835        border-left-color: #b32323;
1836        border-left-color: lab(40% 56.6 39);
1837        border-right-color: #ee00be;
1838        border-right-color: lch(50.998% 135.363 338);
1839      }
1840
1841      .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))) {
1842        border-left-color: #b32323;
1843        border-left-color: lab(40% 56.6 39);
1844        border-right-color: #ee00be;
1845        border-right-color: lch(50.998% 135.363 338);
1846      }
1847
1848      .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)) {
1849        border-left-color: #ee00be;
1850        border-left-color: lch(50.998% 135.363 338);
1851        border-right-color: #b32323;
1852        border-right-color: lab(40% 56.6 39);
1853      }
1854
1855      .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)) {
1856        border-left-color: #ee00be;
1857        border-left-color: lch(50.998% 135.363 338);
1858        border-right-color: #b32323;
1859        border-right-color: lab(40% 56.6 39);
1860      }
1861    "#},
1862      Browsers {
1863        safari: Some(8 << 16),
1864        ..Browsers::default()
1865      },
1866    );
1867
1868    prefix_test(
1869      r#"
1870      .foo {
1871        border-inline-start-color: lab(40% 56.6 39);
1872        border-inline-end-color: lch(50.998% 135.363 338);
1873      }
1874    "#,
1875      indoc! {r#"
1876      .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))) {
1877        border-left-color: #b32323;
1878        border-left-color: color(display-p3 .643308 .192455 .167712);
1879        border-left-color: lab(40% 56.6 39);
1880        border-right-color: #ee00be;
1881        border-right-color: color(display-p3 .972962 -.362078 .804206);
1882        border-right-color: lch(50.998% 135.363 338);
1883      }
1884
1885      .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)) {
1886        border-left-color: #ee00be;
1887        border-left-color: color(display-p3 .972962 -.362078 .804206);
1888        border-left-color: lch(50.998% 135.363 338);
1889        border-right-color: #b32323;
1890        border-right-color: color(display-p3 .643308 .192455 .167712);
1891        border-right-color: lab(40% 56.6 39);
1892      }
1893    "#},
1894      Browsers {
1895        chrome: Some(8 << 16),
1896        safari: Some(14 << 16),
1897        ..Browsers::default()
1898      },
1899    );
1900
1901    prefix_test(
1902      r#"
1903      .foo {
1904        border-inline-start: 2px solid lab(40% 56.6 39);
1905      }
1906    "#,
1907      indoc! {r#"
1908      .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))) {
1909        border-left: 2px solid #b32323;
1910        border-left: 2px solid lab(40% 56.6 39);
1911      }
1912
1913      .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))) {
1914        border-left: 2px solid #b32323;
1915        border-left: 2px solid lab(40% 56.6 39);
1916      }
1917
1918      .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)) {
1919        border-right: 2px solid #b32323;
1920        border-right: 2px solid lab(40% 56.6 39);
1921      }
1922
1923      .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)) {
1924        border-right: 2px solid #b32323;
1925        border-right: 2px solid lab(40% 56.6 39);
1926      }
1927    "#},
1928      Browsers {
1929        safari: Some(8 << 16),
1930        ..Browsers::default()
1931      },
1932    );
1933
1934    prefix_test(
1935      r#"
1936      .foo {
1937        border-inline-end: 2px solid lab(40% 56.6 39);
1938      }
1939    "#,
1940      indoc! {r#"
1941      .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))) {
1942        border-right: 2px solid #b32323;
1943        border-right: 2px solid lab(40% 56.6 39);
1944      }
1945
1946      .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))) {
1947        border-right: 2px solid #b32323;
1948        border-right: 2px solid lab(40% 56.6 39);
1949      }
1950
1951      .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)) {
1952        border-left: 2px solid #b32323;
1953        border-left: 2px solid lab(40% 56.6 39);
1954      }
1955
1956      .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)) {
1957        border-left: 2px solid #b32323;
1958        border-left: 2px solid lab(40% 56.6 39);
1959      }
1960    "#},
1961      Browsers {
1962        safari: Some(8 << 16),
1963        ..Browsers::default()
1964      },
1965    );
1966
1967    prefix_test(
1968      r#"
1969      .foo {
1970        border-inline-end: var(--border-width) solid lab(40% 56.6 39);
1971      }
1972    "#,
1973      indoc! {r#"
1974      .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))) {
1975        border-right: var(--border-width) solid #b32323;
1976      }
1977
1978      .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))) {
1979        border-right: var(--border-width) solid #b32323;
1980      }
1981
1982      @supports (color: lab(0% 0 0)) {
1983        .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))) {
1984          border-right: var(--border-width) solid lab(40% 56.6 39);
1985        }
1986      }
1987
1988      .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)) {
1989        border-left: var(--border-width) solid #b32323;
1990      }
1991
1992      .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)) {
1993        border-left: var(--border-width) solid #b32323;
1994      }
1995
1996      @supports (color: lab(0% 0 0)) {
1997        .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)) {
1998          border-left: var(--border-width) solid lab(40% 56.6 39);
1999        }
2000      }
2001    "#},
2002      Browsers {
2003        safari: Some(8 << 16),
2004        ..Browsers::default()
2005      },
2006    );
2007
2008    prefix_test(
2009      r#"
2010      .foo {
2011        border-inline-start: 2px solid red;
2012        border-inline-end: 2px solid red;
2013      }
2014    "#,
2015      indoc! {r#"
2016      .foo {
2017        border-inline-start: 2px solid red;
2018        border-inline-end: 2px solid red;
2019      }
2020    "#
2021      },
2022      Browsers {
2023        safari: Some(13 << 16),
2024        ..Browsers::default()
2025      },
2026    );
2027
2028    prefix_test(
2029      r#"
2030      .foo {
2031        border-inline-start: 2px solid red;
2032        border-inline-end: 2px solid red;
2033      }
2034    "#,
2035      indoc! {r#"
2036      .foo {
2037        border-inline: 2px solid red;
2038      }
2039    "#
2040      },
2041      Browsers {
2042        safari: Some(15 << 16),
2043        ..Browsers::default()
2044      },
2045    );
2046
2047    prefix_test(
2048      r#"
2049      .foo {
2050        border-width: 22px;
2051        border-width: max(2cqw, 22px);
2052      }
2053    "#,
2054      indoc! {r#"
2055      .foo {
2056        border-width: 22px;
2057        border-width: max(2cqw, 22px);
2058      }
2059    "#
2060      },
2061      Browsers {
2062        safari: Some(14 << 16),
2063        ..Browsers::default()
2064      },
2065    );
2066    prefix_test(
2067      r#"
2068      .foo {
2069        border-width: 22px;
2070        border-width: max(2cqw, 22px);
2071      }
2072    "#,
2073      indoc! {r#"
2074      .foo {
2075        border-width: max(2cqw, 22px);
2076      }
2077    "#
2078      },
2079      Browsers {
2080        safari: Some(16 << 16),
2081        ..Browsers::default()
2082      },
2083    );
2084    prefix_test(
2085      r#"
2086      .foo {
2087        border-color: #4263eb;
2088        border-color: color(display-p3 0 .5 1);
2089      }
2090    "#,
2091      indoc! {r#"
2092      .foo {
2093        border-color: #4263eb;
2094        border-color: color(display-p3 0 .5 1);
2095      }
2096    "#
2097      },
2098      Browsers {
2099        chrome: Some(99 << 16),
2100        ..Browsers::default()
2101      },
2102    );
2103    prefix_test(
2104      r#"
2105      .foo {
2106        border-color: #4263eb;
2107        border-color: color(display-p3 0 .5 1);
2108      }
2109    "#,
2110      indoc! {r#"
2111      .foo {
2112        border-color: color(display-p3 0 .5 1);
2113      }
2114    "#
2115      },
2116      Browsers {
2117        safari: Some(16 << 16),
2118        ..Browsers::default()
2119      },
2120    );
2121    prefix_test(
2122      r#"
2123      .foo {
2124        border: 1px solid #4263eb;
2125        border-color: color(display-p3 0 .5 1);
2126      }
2127    "#,
2128      indoc! {r#"
2129      .foo {
2130        border: 1px solid #4263eb;
2131        border-color: color(display-p3 0 .5 1);
2132      }
2133    "#
2134      },
2135      Browsers {
2136        chrome: Some(99 << 16),
2137        ..Browsers::default()
2138      },
2139    );
2140    prefix_test(
2141      r#"
2142      .foo {
2143        border: 1px solid #4263eb;
2144        border-color: color(display-p3 0 .5 1);
2145      }
2146    "#,
2147      indoc! {r#"
2148      .foo {
2149        border: 1px solid color(display-p3 0 .5 1);
2150      }
2151    "#
2152      },
2153      Browsers {
2154        safari: Some(16 << 16),
2155        ..Browsers::default()
2156      },
2157    );
2158    prefix_test(
2159      r#"
2160      .foo {
2161        border-color: var(--fallback);
2162        border-color: color(display-p3 0 .5 1);
2163      }
2164    "#,
2165      indoc! {r#"
2166      .foo {
2167        border-color: var(--fallback);
2168        border-color: color(display-p3 0 .5 1);
2169      }
2170    "#
2171      },
2172      Browsers {
2173        chrome: Some(99 << 16),
2174        ..Browsers::default()
2175      },
2176    );
2177  }
2178
2179  #[test]
2180  pub fn test_border_image() {
2181    test(
2182      r#"
2183      .foo {
2184        border-image: url(test.png) 60;
2185      }
2186    "#,
2187      indoc! {r#"
2188      .foo {
2189        border-image: url("test.png") 60;
2190      }
2191    "#
2192      },
2193    );
2194
2195    test(
2196      r#"
2197      .foo {
2198        border-image: url(test.png) 60;
2199        border-image-source: url(foo.png);
2200      }
2201    "#,
2202      indoc! {r#"
2203      .foo {
2204        border-image: url("foo.png") 60;
2205      }
2206    "#
2207      },
2208    );
2209
2210    test(
2211      r#"
2212      .foo {
2213        border-image-source: url(foo.png);
2214        border-image-slice: 10 40 10 40 fill;
2215        border-image-width: 10px;
2216        border-image-outset: 0;
2217        border-image-repeat: round round;
2218      }
2219    "#,
2220      indoc! {r#"
2221      .foo {
2222        border-image: url("foo.png") 10 40 fill / 10px round;
2223      }
2224    "#
2225      },
2226    );
2227
2228    test(
2229      r#"
2230      .foo {
2231        border-image: url(foo.png) 60;
2232        border-image-source: var(--test);
2233      }
2234    "#,
2235      indoc! {r#"
2236      .foo {
2237        border-image: url("foo.png") 60;
2238        border-image-source: var(--test);
2239      }
2240    "#
2241      },
2242    );
2243
2244    test(
2245      r#"
2246      .foo {
2247        -webkit-border-image: url("test.png") 60;
2248      }
2249    "#,
2250      indoc! {r#"
2251      .foo {
2252        -webkit-border-image: url("test.png") 60;
2253      }
2254    "#
2255      },
2256    );
2257
2258    test(
2259      r#"
2260      .foo {
2261        -webkit-border-image: url("test.png") 60;
2262        border-image: url("test.png") 60;
2263      }
2264    "#,
2265      indoc! {r#"
2266      .foo {
2267        -webkit-border-image: url("test.png") 60;
2268        border-image: url("test.png") 60;
2269      }
2270    "#
2271      },
2272    );
2273
2274    test(
2275      r#"
2276      .foo {
2277        -webkit-border-image: url("test.png") 60;
2278        border-image-source: url(foo.png);
2279      }
2280    "#,
2281      indoc! {r#"
2282      .foo {
2283        -webkit-border-image: url("test.png") 60;
2284        border-image-source: url("foo.png");
2285      }
2286    "#
2287      },
2288    );
2289
2290    test(
2291      r#"
2292      .foo {
2293        border: 1px solid red;
2294        border-image: url(test.png) 60;
2295      }
2296    "#,
2297      indoc! {r#"
2298      .foo {
2299        border: 1px solid red;
2300        border-image: url("test.png") 60;
2301      }
2302    "#
2303      },
2304    );
2305
2306    test(
2307      r#"
2308      .foo {
2309        border-image: url(test.png) 60;
2310        border: 1px solid red;
2311      }
2312    "#,
2313      indoc! {r#"
2314      .foo {
2315        border: 1px solid red;
2316      }
2317    "#
2318      },
2319    );
2320
2321    test(
2322      r#"
2323      .foo {
2324        border: 1px solid red;
2325        border-image: var(--border-image);
2326      }
2327    "#,
2328      indoc! {r#"
2329      .foo {
2330        border: 1px solid red;
2331        border-image: var(--border-image);
2332      }
2333    "#
2334      },
2335    );
2336
2337    prefix_test(
2338      r#"
2339      .foo {
2340        border-image: url("test.png") 60;
2341      }
2342    "#,
2343      indoc! {r#"
2344      .foo {
2345        -webkit-border-image: url("test.png") 60;
2346        -moz-border-image: url("test.png") 60;
2347        -o-border-image: url("test.png") 60;
2348        border-image: url("test.png") 60;
2349      }
2350    "#
2351      },
2352      Browsers {
2353        safari: Some(4 << 16),
2354        firefox: Some(4 << 16),
2355        opera: Some(12 << 16),
2356        ..Browsers::default()
2357      },
2358    );
2359
2360    prefix_test(
2361      r#"
2362      .foo {
2363        border-image: url(foo.png) 10 40 fill / 10px round;
2364      }
2365    "#,
2366      indoc! {r#"
2367      .foo {
2368        border-image: url("foo.png") 10 40 fill / 10px round;
2369      }
2370    "#
2371      },
2372      Browsers {
2373        safari: Some(4 << 16),
2374        firefox: Some(4 << 16),
2375        opera: Some(12 << 16),
2376        ..Browsers::default()
2377      },
2378    );
2379
2380    prefix_test(
2381      r#"
2382      .foo {
2383        border-image: var(--test) 60;
2384      }
2385    "#,
2386      indoc! {r#"
2387      .foo {
2388        -webkit-border-image: var(--test) 60;
2389        -moz-border-image: var(--test) 60;
2390        -o-border-image: var(--test) 60;
2391        border-image: var(--test) 60;
2392      }
2393    "#
2394      },
2395      Browsers {
2396        safari: Some(4 << 16),
2397        firefox: Some(4 << 16),
2398        opera: Some(12 << 16),
2399        ..Browsers::default()
2400      },
2401    );
2402
2403    prefix_test(
2404      r#"
2405      .foo {
2406        -webkit-border-image: url(foo.png) 60;
2407        -moz-border-image: url(foo.png) 60;
2408        -o-border-image: url(foo.png) 60;
2409        border-image: url(foo.png) 60;
2410      }
2411    "#,
2412      indoc! {r#"
2413      .foo {
2414        border-image: url("foo.png") 60;
2415      }
2416    "#
2417      },
2418      Browsers {
2419        chrome: Some(15 << 16),
2420        ..Browsers::default()
2421      },
2422    );
2423
2424    prefix_test(
2425      r#"
2426      .foo {
2427        border-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 60;
2428      }
2429    "#,
2430      indoc! {r#"
2431      .foo {
2432        -webkit-border-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ff0f0e), to(#7773ff)) 60;
2433        -webkit-border-image: -webkit-linear-gradient(top, #ff0f0e, #7773ff) 60;
2434        border-image: linear-gradient(#ff0f0e, #7773ff) 60;
2435        border-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 60;
2436      }
2437    "#
2438      },
2439      Browsers {
2440        chrome: Some(8 << 16),
2441        ..Browsers::default()
2442      },
2443    );
2444
2445    prefix_test(
2446      r#"
2447      .foo {
2448        border-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 60;
2449      }
2450    "#,
2451      indoc! {r#"
2452      .foo {
2453        -webkit-border-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ff0f0e), to(#7773ff)) 60;
2454        -webkit-border-image: -webkit-linear-gradient(top, #ff0f0e, #7773ff) 60;
2455        -moz-border-image: -moz-linear-gradient(top, #ff0f0e, #7773ff) 60;
2456        border-image: linear-gradient(#ff0f0e, #7773ff) 60;
2457        border-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 60;
2458      }
2459    "#
2460      },
2461      Browsers {
2462        chrome: Some(8 << 16),
2463        firefox: Some(4 << 16),
2464        ..Browsers::default()
2465      },
2466    );
2467
2468    prefix_test(
2469      r#"
2470      .foo {
2471        border-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 60;
2472      }
2473    "#,
2474      indoc! {r#"
2475      .foo {
2476        border-image: -webkit-linear-gradient(top, #ff0f0e, #7773ff) 60;
2477        border-image: -moz-linear-gradient(top, #ff0f0e, #7773ff) 60;
2478        border-image: linear-gradient(#ff0f0e, #7773ff) 60;
2479        border-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 60;
2480      }
2481    "#
2482      },
2483      Browsers {
2484        chrome: Some(15 << 16),
2485        firefox: Some(15 << 16),
2486        ..Browsers::default()
2487      },
2488    );
2489
2490    prefix_test(
2491      r#"
2492      .foo {
2493        border-image-source: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
2494      }
2495    "#,
2496      indoc! {r#"
2497      .foo {
2498        border-image-source: -webkit-linear-gradient(top, #ff0f0e, #7773ff);
2499        border-image-source: linear-gradient(#ff0f0e, #7773ff);
2500        border-image-source: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
2501      }
2502    "#
2503      },
2504      Browsers {
2505        chrome: Some(15 << 16),
2506        ..Browsers::default()
2507      },
2508    );
2509
2510    prefix_test(
2511      r#"
2512      .foo {
2513        border-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) var(--foo);
2514      }
2515    "#,
2516      indoc! {r#"
2517      .foo {
2518        border-image: linear-gradient(#ff0f0e, #7773ff) var(--foo);
2519      }
2520
2521      @supports (color: lab(0% 0 0)) {
2522        .foo {
2523          border-image: linear-gradient(lab(56.208% 94.4644 98.8928), lab(51% 70.4544 -115.586)) var(--foo);
2524        }
2525      }
2526    "#
2527      },
2528      Browsers {
2529        chrome: Some(90 << 16),
2530        ..Browsers::default()
2531      },
2532    );
2533
2534    prefix_test(
2535      r#"
2536      .foo {
2537        border-image-source: linear-gradient(red, green);
2538        border-image-source: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
2539      }
2540    "#,
2541      indoc! {r#"
2542      .foo {
2543        border-image-source: linear-gradient(red, green);
2544        border-image-source: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
2545      }
2546    "#
2547      },
2548      Browsers {
2549        chrome: Some(95 << 16),
2550        ..Browsers::default()
2551      },
2552    );
2553
2554    prefix_test(
2555      r#"
2556      .foo {
2557        border-image-source: linear-gradient(red, green);
2558        border-image-source: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
2559      }
2560    "#,
2561      indoc! {r#"
2562      .foo {
2563        border-image-source: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
2564      }
2565    "#
2566      },
2567      Browsers {
2568        chrome: Some(112 << 16),
2569        ..Browsers::default()
2570      },
2571    );
2572
2573    prefix_test(
2574      r#"
2575      .foo {
2576        border-image: linear-gradient(red, green);
2577        border-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
2578      }
2579    "#,
2580      indoc! {r#"
2581      .foo {
2582        border-image: linear-gradient(red, green);
2583        border-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
2584      }
2585    "#
2586      },
2587      Browsers {
2588        chrome: Some(95 << 16),
2589        ..Browsers::default()
2590      },
2591    );
2592
2593    prefix_test(
2594      r#"
2595      .foo {
2596        border-image: var(--fallback);
2597        border-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
2598      }
2599    "#,
2600      indoc! {r#"
2601      .foo {
2602        border-image: var(--fallback);
2603        border-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
2604      }
2605    "#
2606      },
2607      Browsers {
2608        chrome: Some(95 << 16),
2609        ..Browsers::default()
2610      },
2611    );
2612
2613    prefix_test(
2614      r#"
2615      .foo {
2616        border-image: url("fallback.png") 10 40 fill / 10px;
2617        border-image: url("main.png") 10 40 fill / 10px space;
2618      }
2619    "#,
2620      indoc! {r#"
2621      .foo {
2622        border-image: url("fallback.png") 10 40 fill / 10px;
2623        border-image: url("main.png") 10 40 fill / 10px space;
2624      }
2625    "#
2626      },
2627      Browsers {
2628        chrome: Some(50 << 16),
2629        ..Browsers::default()
2630      },
2631    );
2632
2633    prefix_test(
2634      r#"
2635      .foo {
2636        border-image: url("fallback.png") 10 40 fill / 10px;
2637        border-image: url("main.png") 10 40 fill / 10px space;
2638      }
2639    "#,
2640      indoc! {r#"
2641      .foo {
2642        border-image: url("main.png") 10 40 fill / 10px space;
2643      }
2644    "#
2645      },
2646      Browsers {
2647        chrome: Some(56 << 16),
2648        ..Browsers::default()
2649      },
2650    );
2651
2652    minify_test(".foo { border: none green }", ".foo{border:green}");
2653  }
2654
2655  #[test]
2656  pub fn test_border_radius() {
2657    test(
2658      r#"
2659      .foo {
2660        border-radius: 10px 100px 10px 100px;
2661      }
2662    "#,
2663      indoc! {r#"
2664      .foo {
2665        border-radius: 10px 100px;
2666      }
2667    "#
2668      },
2669    );
2670
2671    test(
2672      r#"
2673      .foo {
2674        border-radius: 10px 100px 10px 100px / 120px 120px;
2675      }
2676    "#,
2677      indoc! {r#"
2678      .foo {
2679        border-radius: 10px 100px / 120px;
2680      }
2681    "#
2682      },
2683    );
2684
2685    test(
2686      r#"
2687      .foo {
2688        border-top-left-radius: 10px 120px;
2689        border-top-right-radius: 100px 120px;
2690        border-bottom-right-radius: 100px 120px;
2691        border-bottom-left-radius: 10px 120px;
2692      }
2693    "#,
2694      indoc! {r#"
2695      .foo {
2696        border-radius: 10px 100px 100px 10px / 120px;
2697      }
2698    "#
2699      },
2700    );
2701
2702    test(
2703      r#"
2704      .foo {
2705        border-top-left-radius: 4px 2px;
2706        border-top-right-radius: 3px 4px;
2707        border-bottom-right-radius: 6px 2px;
2708        border-bottom-left-radius: 3px 4px;
2709      }
2710    "#,
2711      indoc! {r#"
2712      .foo {
2713        border-radius: 4px 3px 6px / 2px 4px;
2714      }
2715    "#
2716      },
2717    );
2718
2719    test(
2720      r#"
2721      .foo {
2722        border-top-left-radius: 1% 2%;
2723        border-top-right-radius: 3% 4%;
2724        border-bottom-right-radius: 5% 6%;
2725        border-bottom-left-radius: 7% 8%;
2726      }
2727    "#,
2728      indoc! {r#"
2729      .foo {
2730        border-radius: 1% 3% 5% 7% / 2% 4% 6% 8%;
2731      }
2732    "#
2733      },
2734    );
2735
2736    test(
2737      r#"
2738      .foo {
2739        border-radius: 10px 100px 10px 100px / 120px 120px;
2740        border-start-start-radius: 10px;
2741      }
2742    "#,
2743      indoc! {r#"
2744      .foo {
2745        border-radius: 10px 100px / 120px;
2746        border-start-start-radius: 10px;
2747      }
2748    "#
2749      },
2750    );
2751
2752    test(
2753      r#"
2754      .foo {
2755        border-start-start-radius: 10px;
2756        border-radius: 10px 100px 10px 100px / 120px 120px;
2757      }
2758    "#,
2759      indoc! {r#"
2760      .foo {
2761        border-radius: 10px 100px / 120px;
2762      }
2763    "#
2764      },
2765    );
2766
2767    test(
2768      r#"
2769      .foo {
2770        border-top-left-radius: 10px 120px;
2771        border-top-right-radius: 100px 120px;
2772        border-start-start-radius: 10px;
2773        border-bottom-right-radius: 100px 120px;
2774        border-bottom-left-radius: 10px 120px;
2775      }
2776    "#,
2777      indoc! {r#"
2778      .foo {
2779        border-top-left-radius: 10px 120px;
2780        border-top-right-radius: 100px 120px;
2781        border-start-start-radius: 10px;
2782        border-bottom-right-radius: 100px 120px;
2783        border-bottom-left-radius: 10px 120px;
2784      }
2785    "#
2786      },
2787    );
2788
2789    test(
2790      r#"
2791      .foo {
2792        border-radius: 10px;
2793        border-top-left-radius: 20px;
2794      }
2795    "#,
2796      indoc! {r#"
2797      .foo {
2798        border-radius: 20px 10px 10px;
2799      }
2800    "#
2801      },
2802    );
2803
2804    test(
2805      r#"
2806      .foo {
2807        border-radius: 10px;
2808        border-top-left-radius: var(--test);
2809      }
2810    "#,
2811      indoc! {r#"
2812      .foo {
2813        border-radius: 10px;
2814        border-top-left-radius: var(--test);
2815      }
2816    "#
2817      },
2818    );
2819
2820    test(
2821      r#"
2822      .foo {
2823        -webkit-border-radius: 10px 100px 10px 100px;
2824        -moz-border-radius: 10px 100px 10px 100px;
2825        border-radius: 10px 100px 10px 100px;
2826      }
2827    "#,
2828      indoc! {r#"
2829      .foo {
2830        -webkit-border-radius: 10px 100px;
2831        -moz-border-radius: 10px 100px;
2832        border-radius: 10px 100px;
2833      }
2834    "#
2835      },
2836    );
2837
2838    test(
2839      r#"
2840      .foo {
2841        -webkit-border-radius: 10px 100px 10px 100px;
2842        -moz-border-radius: 20px;
2843        border-radius: 30px;
2844      }
2845    "#,
2846      indoc! {r#"
2847      .foo {
2848        -webkit-border-radius: 10px 100px;
2849        -moz-border-radius: 20px;
2850        border-radius: 30px;
2851      }
2852    "#
2853      },
2854    );
2855
2856    test(
2857      r#"
2858      .foo {
2859        -webkit-border-top-left-radius: 10px;
2860        -moz-border-top-left-radius: 10px;
2861        border-top-left-radius: 10px;
2862      }
2863    "#,
2864      indoc! {r#"
2865      .foo {
2866        -webkit-border-top-left-radius: 10px;
2867        -moz-border-top-left-radius: 10px;
2868        border-top-left-radius: 10px;
2869      }
2870    "#
2871      },
2872    );
2873
2874    prefix_test(
2875      r#"
2876      .foo {
2877        border-radius: 30px;
2878      }
2879    "#,
2880      indoc! {r#"
2881      .foo {
2882        -webkit-border-radius: 30px;
2883        -moz-border-radius: 30px;
2884        border-radius: 30px;
2885      }
2886    "#
2887      },
2888      Browsers {
2889        safari: Some(4 << 16),
2890        firefox: Some(3 << 16),
2891        ..Browsers::default()
2892      },
2893    );
2894
2895    prefix_test(
2896      r#"
2897      .foo {
2898        border-top-left-radius: 30px;
2899      }
2900    "#,
2901      indoc! {r#"
2902      .foo {
2903        -webkit-border-top-left-radius: 30px;
2904        -moz-border-top-left-radius: 30px;
2905        border-top-left-radius: 30px;
2906      }
2907    "#
2908      },
2909      Browsers {
2910        safari: Some(4 << 16),
2911        firefox: Some(3 << 16),
2912        ..Browsers::default()
2913      },
2914    );
2915
2916    prefix_test(
2917      r#"
2918      .foo {
2919        -webkit-border-radius: 30px;
2920        -moz-border-radius: 30px;
2921        border-radius: 30px;
2922      }
2923    "#,
2924      indoc! {r#"
2925      .foo {
2926        border-radius: 30px;
2927      }
2928    "#
2929      },
2930      Browsers {
2931        safari: Some(14 << 16),
2932        firefox: Some(46 << 16),
2933        ..Browsers::default()
2934      },
2935    );
2936
2937    prefix_test(
2938      r#"
2939      .foo {
2940        -webkit-border-top-left-radius: 30px;
2941        -moz-border-top-left-radius: 30px;
2942        border-top-left-radius: 30px;
2943      }
2944    "#,
2945      indoc! {r#"
2946      .foo {
2947        border-top-left-radius: 30px;
2948      }
2949    "#
2950      },
2951      Browsers {
2952        safari: Some(14 << 16),
2953        firefox: Some(46 << 16),
2954        ..Browsers::default()
2955      },
2956    );
2957
2958    prefix_test(
2959      r#"
2960      .foo {
2961        -webkit-border-radius: 30px;
2962        -moz-border-radius: 30px;
2963      }
2964    "#,
2965      indoc! {r#"
2966      .foo {
2967        -webkit-border-radius: 30px;
2968        -moz-border-radius: 30px;
2969      }
2970    "#
2971      },
2972      Browsers {
2973        safari: Some(14 << 16),
2974        firefox: Some(46 << 16),
2975        ..Browsers::default()
2976      },
2977    );
2978
2979    prefix_test(
2980      r#"
2981      .foo {
2982        -webkit-border-top-left-radius: 30px;
2983        -moz-border-top-right-radius: 30px;
2984        border-bottom-right-radius: 30px;
2985        border-bottom-left-radius: 30px;
2986      }
2987    "#,
2988      indoc! {r#"
2989      .foo {
2990        -webkit-border-top-left-radius: 30px;
2991        -moz-border-top-right-radius: 30px;
2992        border-bottom-right-radius: 30px;
2993        border-bottom-left-radius: 30px;
2994      }
2995    "#
2996      },
2997      Browsers {
2998        safari: Some(14 << 16),
2999        firefox: Some(46 << 16),
3000        ..Browsers::default()
3001      },
3002    );
3003
3004    prefix_test(
3005      r#"
3006      .foo {
3007        border-radius: var(--test);
3008      }
3009    "#,
3010      indoc! {r#"
3011      .foo {
3012        -webkit-border-radius: var(--test);
3013        -moz-border-radius: var(--test);
3014        border-radius: var(--test);
3015      }
3016    "#
3017      },
3018      Browsers {
3019        safari: Some(4 << 16),
3020        firefox: Some(3 << 16),
3021        ..Browsers::default()
3022      },
3023    );
3024
3025    prefix_test(
3026      r#"
3027      .foo {
3028        border-start-start-radius: 5px;
3029      }
3030    "#,
3031      indoc! {r#"
3032      .foo:not(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
3033        border-top-left-radius: 5px;
3034      }
3035
3036      .foo:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) {
3037        border-top-right-radius: 5px;
3038      }
3039    "#
3040      },
3041      Browsers {
3042        safari: Some(12 << 16),
3043        ..Browsers::default()
3044      },
3045    );
3046
3047    prefix_test(
3048      r#"
3049      .foo {
3050        border-start-start-radius: 5px;
3051        border-start-end-radius: 10px;
3052      }
3053    "#,
3054      indoc! {r#"
3055      .foo:not(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
3056        border-top-left-radius: 5px;
3057        border-top-right-radius: 10px;
3058      }
3059
3060      .foo:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) {
3061        border-top-left-radius: 10px;
3062        border-top-right-radius: 5px;
3063      }
3064    "#
3065      },
3066      Browsers {
3067        safari: Some(12 << 16),
3068        ..Browsers::default()
3069      },
3070    );
3071
3072    prefix_test(
3073      r#"
3074      .foo {
3075        border-end-end-radius: 10px;
3076        border-end-start-radius: 5px;
3077      }
3078    "#,
3079      indoc! {r#"
3080      .foo:not(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
3081        border-bottom-right-radius: 10px;
3082        border-bottom-left-radius: 5px;
3083      }
3084
3085      .foo:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) {
3086        border-bottom-right-radius: 5px;
3087        border-bottom-left-radius: 10px;
3088      }
3089    "#
3090      },
3091      Browsers {
3092        safari: Some(12 << 16),
3093        ..Browsers::default()
3094      },
3095    );
3096
3097    prefix_test(
3098      r#"
3099      .foo {
3100        border-start-start-radius: var(--radius);
3101      }
3102    "#,
3103      indoc! {r#"
3104      .foo:not(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
3105        border-top-left-radius: var(--radius);
3106      }
3107
3108      .foo:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) {
3109        border-top-right-radius: var(--radius);
3110      }
3111    "#
3112      },
3113      Browsers {
3114        safari: Some(12 << 16),
3115        ..Browsers::default()
3116      },
3117    );
3118
3119    prefix_test(
3120      r#"
3121      .foo {
3122        border-start-start-radius: var(--start);
3123        border-start-end-radius: var(--end);
3124      }
3125    "#,
3126      indoc! {r#"
3127      .foo:not(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
3128        border-top-left-radius: var(--start);
3129        border-top-right-radius: var(--end);
3130      }
3131
3132      .foo:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) {
3133        border-top-right-radius: var(--start);
3134        border-top-left-radius: var(--end);
3135      }
3136    "#
3137      },
3138      Browsers {
3139        safari: Some(12 << 16),
3140        ..Browsers::default()
3141      },
3142    );
3143  }
3144
3145  #[test]
3146  pub fn test_outline() {
3147    test(
3148      r#"
3149      .foo {
3150        outline-width: 2px;
3151        outline-style: solid;
3152        outline-color: blue;
3153      }
3154    "#,
3155      indoc! {r#"
3156      .foo {
3157        outline: 2px solid #00f;
3158      }
3159    "#
3160      },
3161    );
3162
3163    test(
3164      r#"
3165      .foo {
3166        outline: 2px solid blue;
3167      }
3168    "#,
3169      indoc! {r#"
3170      .foo {
3171        outline: 2px solid #00f;
3172      }
3173    "#
3174      },
3175    );
3176
3177    test(
3178      r#"
3179      .foo {
3180        outline: 2px solid red;
3181        outline-color: blue;
3182      }
3183    "#,
3184      indoc! {r#"
3185      .foo {
3186        outline: 2px solid #00f;
3187      }
3188    "#
3189      },
3190    );
3191
3192    test(
3193      r#"
3194      .foo {
3195        outline: 2px solid yellow;
3196        outline-color: var(--color);
3197      }
3198    "#,
3199      indoc! {r#"
3200      .foo {
3201        outline: 2px solid #ff0;
3202        outline-color: var(--color);
3203      }
3204    "#
3205      },
3206    );
3207
3208    prefix_test(
3209      ".foo { outline-color: lab(40% 56.6 39) }",
3210      indoc! { r#"
3211        .foo {
3212          outline-color: #b32323;
3213          outline-color: lab(40% 56.6 39);
3214        }
3215      "#},
3216      Browsers {
3217        chrome: Some(90 << 16),
3218        ..Browsers::default()
3219      },
3220    );
3221
3222    prefix_test(
3223      ".foo { outline: 2px solid lab(40% 56.6 39) }",
3224      indoc! { r#"
3225        .foo {
3226          outline: 2px solid #b32323;
3227          outline: 2px solid lab(40% 56.6 39);
3228        }
3229      "#},
3230      Browsers {
3231        chrome: Some(90 << 16),
3232        ..Browsers::default()
3233      },
3234    );
3235
3236    prefix_test(
3237      ".foo { outline: var(--width) solid lab(40% 56.6 39) }",
3238      indoc! { r#"
3239        .foo {
3240          outline: var(--width) solid #b32323;
3241        }
3242
3243        @supports (color: lab(0% 0 0)) {
3244          .foo {
3245            outline: var(--width) solid lab(40% 56.6 39);
3246          }
3247        }
3248      "#},
3249      Browsers {
3250        chrome: Some(90 << 16),
3251        ..Browsers::default()
3252      },
3253    );
3254  }
3255
3256  #[test]
3257  pub fn test_margin() {
3258    test(
3259      r#"
3260      .foo {
3261        margin-left: 10px;
3262        margin-right: 10px;
3263        margin-top: 20px;
3264        margin-bottom: 20px;
3265      }
3266    "#,
3267      indoc! {r#"
3268      .foo {
3269        margin: 20px 10px;
3270      }
3271    "#
3272      },
3273    );
3274
3275    test(
3276      r#"
3277      .foo {
3278        margin-block-start: 15px;
3279        margin-block-end: 15px;
3280      }
3281    "#,
3282      indoc! {r#"
3283      .foo {
3284        margin-block: 15px;
3285      }
3286    "#
3287      },
3288    );
3289
3290    test(
3291      r#"
3292      .foo {
3293        margin-left: 10px;
3294        margin-right: 10px;
3295        margin-inline-start: 15px;
3296        margin-inline-end: 15px;
3297        margin-top: 20px;
3298        margin-bottom: 20px;
3299
3300      }
3301    "#,
3302      indoc! {r#"
3303      .foo {
3304        margin-left: 10px;
3305        margin-right: 10px;
3306        margin-inline: 15px;
3307        margin-top: 20px;
3308        margin-bottom: 20px;
3309      }
3310    "#
3311      },
3312    );
3313
3314    test(
3315      r#"
3316      .foo {
3317        margin: 10px;
3318        margin-top: 20px;
3319      }
3320    "#,
3321      indoc! {r#"
3322      .foo {
3323        margin: 20px 10px 10px;
3324      }
3325    "#
3326      },
3327    );
3328
3329    test(
3330      r#"
3331      .foo {
3332        margin: 10px;
3333        margin-top: var(--top);
3334      }
3335    "#,
3336      indoc! {r#"
3337      .foo {
3338        margin: 10px;
3339        margin-top: var(--top);
3340      }
3341    "#
3342      },
3343    );
3344
3345    prefix_test(
3346      r#"
3347      .foo {
3348        margin-inline-start: 2px;
3349      }
3350    "#,
3351      indoc! {r#"
3352      .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))) {
3353        margin-left: 2px;
3354      }
3355
3356      .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))) {
3357        margin-left: 2px;
3358      }
3359
3360      .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)) {
3361        margin-right: 2px;
3362      }
3363
3364      .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)) {
3365        margin-right: 2px;
3366      }
3367    "#
3368      },
3369      Browsers {
3370        safari: Some(8 << 16),
3371        ..Browsers::default()
3372      },
3373    );
3374
3375    prefix_test(
3376      r#"
3377      .foo {
3378        margin-inline-start: 2px;
3379        margin-inline-end: 4px;
3380      }
3381    "#,
3382      indoc! {r#"
3383      .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))) {
3384        margin-left: 2px;
3385        margin-right: 4px;
3386      }
3387
3388      .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))) {
3389        margin-left: 2px;
3390        margin-right: 4px;
3391      }
3392
3393      .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)) {
3394        margin-left: 4px;
3395        margin-right: 2px;
3396      }
3397
3398      .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)) {
3399        margin-left: 4px;
3400        margin-right: 2px;
3401      }
3402    "#
3403      },
3404      Browsers {
3405        safari: Some(8 << 16),
3406        ..Browsers::default()
3407      },
3408    );
3409
3410    prefix_test(
3411      r#"
3412      .foo {
3413        margin-inline: 2px;
3414      }
3415    "#,
3416      indoc! {r#"
3417      .foo {
3418        margin-left: 2px;
3419        margin-right: 2px;
3420      }
3421    "#
3422      },
3423      Browsers {
3424        safari: Some(8 << 16),
3425        ..Browsers::default()
3426      },
3427    );
3428
3429    prefix_test(
3430      r#"
3431      .foo {
3432        margin-block-start: 2px;
3433      }
3434    "#,
3435      indoc! {r#"
3436      .foo {
3437        margin-top: 2px;
3438      }
3439    "#
3440      },
3441      Browsers {
3442        safari: Some(8 << 16),
3443        ..Browsers::default()
3444      },
3445    );
3446
3447    prefix_test(
3448      r#"
3449      .foo {
3450        margin-block-end: 2px;
3451      }
3452    "#,
3453      indoc! {r#"
3454      .foo {
3455        margin-bottom: 2px;
3456      }
3457    "#
3458      },
3459      Browsers {
3460        safari: Some(8 << 16),
3461        ..Browsers::default()
3462      },
3463    );
3464
3465    prefix_test(
3466      r#"
3467      .foo {
3468        margin-inline-start: 2px;
3469        margin-inline-end: 2px;
3470      }
3471    "#,
3472      indoc! {r#"
3473      .foo {
3474        margin-inline-start: 2px;
3475        margin-inline-end: 2px;
3476      }
3477    "#
3478      },
3479      Browsers {
3480        safari: Some(13 << 16),
3481        ..Browsers::default()
3482      },
3483    );
3484
3485    prefix_test(
3486      r#"
3487      .foo {
3488        margin-inline: 2px;
3489      }
3490    "#,
3491      indoc! {r#"
3492      .foo {
3493        margin-inline-start: 2px;
3494        margin-inline-end: 2px;
3495      }
3496    "#
3497      },
3498      Browsers {
3499        safari: Some(13 << 16),
3500        ..Browsers::default()
3501      },
3502    );
3503
3504    prefix_test(
3505      r#"
3506      .foo {
3507        margin-inline-start: 2px;
3508        margin-inline-end: 2px;
3509      }
3510    "#,
3511      indoc! {r#"
3512      .foo {
3513        margin-inline: 2px;
3514      }
3515    "#
3516      },
3517      Browsers {
3518        safari: Some(15 << 16),
3519        ..Browsers::default()
3520      },
3521    );
3522
3523    prefix_test(
3524      r#"
3525      .foo {
3526        margin-inline: 2px;
3527      }
3528    "#,
3529      indoc! {r#"
3530      .foo {
3531        margin-inline: 2px;
3532      }
3533    "#
3534      },
3535      Browsers {
3536        safari: Some(15 << 16),
3537        ..Browsers::default()
3538      },
3539    );
3540  }
3541
3542  #[test]
3543  fn test_length() {
3544    for prop in &[
3545      "margin-right",
3546      "margin",
3547      "padding-right",
3548      "padding",
3549      "width",
3550      "height",
3551      "min-height",
3552      "max-height",
3553      "line-height",
3554      "border-radius",
3555    ] {
3556      prefix_test(
3557        &format!(
3558          r#"
3559        .foo {{
3560          {}: 22px;
3561          {}: max(4%, 22px);
3562        }}
3563      "#,
3564          prop, prop
3565        ),
3566        &format!(
3567          indoc! {r#"
3568        .foo {{
3569          {}: 22px;
3570          {}: max(4%, 22px);
3571        }}
3572      "#
3573          },
3574          prop, prop
3575        ),
3576        Browsers {
3577          safari: Some(10 << 16),
3578          ..Browsers::default()
3579        },
3580      );
3581
3582      prefix_test(
3583        &format!(
3584          r#"
3585        .foo {{
3586          {}: 22px;
3587          {}: max(4%, 22px);
3588        }}
3589      "#,
3590          prop, prop
3591        ),
3592        &format!(
3593          indoc! {r#"
3594        .foo {{
3595          {}: max(4%, 22px);
3596        }}
3597      "#
3598          },
3599          prop
3600        ),
3601        Browsers {
3602          safari: Some(14 << 16),
3603          ..Browsers::default()
3604        },
3605      );
3606
3607      prefix_test(
3608        &format!(
3609          r#"
3610        .foo {{
3611          {}: 22px;
3612          {}: max(2cqw, 22px);
3613        }}
3614      "#,
3615          prop, prop
3616        ),
3617        &format!(
3618          indoc! {r#"
3619        .foo {{
3620          {}: 22px;
3621          {}: max(2cqw, 22px);
3622        }}
3623      "#
3624          },
3625          prop, prop
3626        ),
3627        Browsers {
3628          safari: Some(14 << 16),
3629          ..Browsers::default()
3630        },
3631      );
3632      prefix_test(
3633        &format!(
3634          r#"
3635        .foo {{
3636          {}: 22px;
3637          {}: max(2cqw, 22px);
3638        }}
3639      "#,
3640          prop, prop
3641        ),
3642        &format!(
3643          indoc! {r#"
3644        .foo {{
3645          {}: max(2cqw, 22px);
3646        }}
3647      "#
3648          },
3649          prop
3650        ),
3651        Browsers {
3652          safari: Some(16 << 16),
3653          ..Browsers::default()
3654        },
3655      );
3656    }
3657  }
3658
3659  #[test]
3660  pub fn test_padding() {
3661    test(
3662      r#"
3663      .foo {
3664        padding-left: 10px;
3665        padding-right: 10px;
3666        padding-top: 20px;
3667        padding-bottom: 20px;
3668      }
3669    "#,
3670      indoc! {r#"
3671      .foo {
3672        padding: 20px 10px;
3673      }
3674    "#
3675      },
3676    );
3677
3678    test(
3679      r#"
3680      .foo {
3681        padding-block-start: 15px;
3682        padding-block-end: 15px;
3683      }
3684    "#,
3685      indoc! {r#"
3686      .foo {
3687        padding-block: 15px;
3688      }
3689    "#
3690      },
3691    );
3692
3693    test(
3694      r#"
3695      .foo {
3696        padding-left: 10px;
3697        padding-right: 10px;
3698        padding-inline-start: 15px;
3699        padding-inline-end: 15px;
3700        padding-top: 20px;
3701        padding-bottom: 20px;
3702
3703      }
3704    "#,
3705      indoc! {r#"
3706      .foo {
3707        padding-left: 10px;
3708        padding-right: 10px;
3709        padding-inline: 15px;
3710        padding-top: 20px;
3711        padding-bottom: 20px;
3712      }
3713    "#
3714      },
3715    );
3716
3717    prefix_test(
3718      r#"
3719      .foo {
3720        padding-inline-start: 2px;
3721      }
3722    "#,
3723      indoc! {r#"
3724      .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))) {
3725        padding-left: 2px;
3726      }
3727
3728      .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))) {
3729        padding-left: 2px;
3730      }
3731
3732      .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)) {
3733        padding-right: 2px;
3734      }
3735
3736      .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)) {
3737        padding-right: 2px;
3738      }
3739    "#
3740      },
3741      Browsers {
3742        safari: Some(8 << 16),
3743        ..Browsers::default()
3744      },
3745    );
3746
3747    prefix_test(
3748      r#"
3749      .foo {
3750        padding-inline-start: 2px;
3751        padding-inline-end: 4px;
3752      }
3753    "#,
3754      indoc! {r#"
3755      .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))) {
3756        padding-left: 2px;
3757        padding-right: 4px;
3758      }
3759
3760      .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))) {
3761        padding-left: 2px;
3762        padding-right: 4px;
3763      }
3764
3765      .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)) {
3766        padding-left: 4px;
3767        padding-right: 2px;
3768      }
3769
3770      .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)) {
3771        padding-left: 4px;
3772        padding-right: 2px;
3773      }
3774    "#
3775      },
3776      Browsers {
3777        safari: Some(8 << 16),
3778        ..Browsers::default()
3779      },
3780    );
3781
3782    prefix_test(
3783      r#"
3784      .foo {
3785        padding-inline-start: var(--padding);
3786      }
3787    "#,
3788      indoc! {r#"
3789      .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))) {
3790        padding-left: var(--padding);
3791      }
3792
3793      .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))) {
3794        padding-left: var(--padding);
3795      }
3796
3797      .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)) {
3798        padding-right: var(--padding);
3799      }
3800
3801      .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)) {
3802        padding-right: var(--padding);
3803      }
3804    "#
3805      },
3806      Browsers {
3807        safari: Some(8 << 16),
3808        ..Browsers::default()
3809      },
3810    );
3811
3812    prefix_test(
3813      r#"
3814      .foo {
3815        padding-inline: 2px;
3816      }
3817    "#,
3818      indoc! {r#"
3819      .foo {
3820        padding-left: 2px;
3821        padding-right: 2px;
3822      }
3823    "#
3824      },
3825      Browsers {
3826        safari: Some(8 << 16),
3827        ..Browsers::default()
3828      },
3829    );
3830
3831    prefix_test(
3832      r#"
3833      .foo {
3834        padding-block-start: 2px;
3835      }
3836    "#,
3837      indoc! {r#"
3838      .foo {
3839        padding-top: 2px;
3840      }
3841    "#
3842      },
3843      Browsers {
3844        safari: Some(8 << 16),
3845        ..Browsers::default()
3846      },
3847    );
3848
3849    prefix_test(
3850      r#"
3851      .foo {
3852        padding-block-end: 2px;
3853      }
3854    "#,
3855      indoc! {r#"
3856      .foo {
3857        padding-bottom: 2px;
3858      }
3859    "#
3860      },
3861      Browsers {
3862        safari: Some(8 << 16),
3863        ..Browsers::default()
3864      },
3865    );
3866
3867    prefix_test(
3868      r#"
3869      .foo {
3870        padding-top: 1px;
3871        padding-left: 2px;
3872        padding-bottom: 3px;
3873        padding-right: 4px;
3874      }
3875    "#,
3876      indoc! {r#"
3877      .foo {
3878        padding: 1px 4px 3px 2px;
3879      }
3880    "#},
3881      Browsers {
3882        safari: Some(8 << 16),
3883        ..Browsers::default()
3884      },
3885    );
3886
3887    prefix_test(
3888      r#"
3889      .foo {
3890        padding-inline-start: 2px;
3891        padding-inline-end: 2px;
3892      }
3893    "#,
3894      indoc! {r#"
3895      .foo {
3896        padding-inline-start: 2px;
3897        padding-inline-end: 2px;
3898      }
3899    "#
3900      },
3901      Browsers {
3902        safari: Some(13 << 16),
3903        ..Browsers::default()
3904      },
3905    );
3906
3907    prefix_test(
3908      r#"
3909      .foo {
3910        padding-inline-start: 2px;
3911        padding-inline-end: 2px;
3912      }
3913    "#,
3914      indoc! {r#"
3915      .foo {
3916        padding-inline: 2px;
3917      }
3918    "#
3919      },
3920      Browsers {
3921        safari: Some(15 << 16),
3922        ..Browsers::default()
3923      },
3924    );
3925  }
3926
3927  #[test]
3928  fn test_scroll_padding() {
3929    prefix_test(
3930      r#"
3931      .foo {
3932        scroll-padding-inline: 2px;
3933      }
3934    "#,
3935      indoc! {r#"
3936      .foo {
3937        scroll-padding-inline: 2px;
3938      }
3939    "#
3940      },
3941      Browsers {
3942        safari: Some(8 << 16),
3943        ..Browsers::default()
3944      },
3945    );
3946  }
3947
3948  #[test]
3949  fn test_size() {
3950    prefix_test(
3951      r#"
3952      .foo {
3953        block-size: 25px;
3954        inline-size: 25px;
3955        min-block-size: 25px;
3956        min-inline-size: 25px;
3957      }
3958    "#,
3959      indoc! {r#"
3960      .foo {
3961        height: 25px;
3962        min-height: 25px;
3963        width: 25px;
3964        min-width: 25px;
3965      }
3966    "#},
3967      Browsers {
3968        safari: Some(8 << 16),
3969        ..Browsers::default()
3970      },
3971    );
3972
3973    prefix_test(
3974      r#"
3975      .foo {
3976        block-size: 25px;
3977        min-block-size: 25px;
3978        inline-size: 25px;
3979        min-inline-size: 25px;
3980      }
3981    "#,
3982      indoc! {r#"
3983      .foo {
3984        block-size: 25px;
3985        min-block-size: 25px;
3986        inline-size: 25px;
3987        min-inline-size: 25px;
3988      }
3989    "#},
3990      Browsers {
3991        safari: Some(14 << 16),
3992        ..Browsers::default()
3993      },
3994    );
3995
3996    prefix_test(
3997      r#"
3998      .foo {
3999        block-size: var(--size);
4000        min-block-size: var(--size);
4001        inline-size: var(--size);
4002        min-inline-size: var(--size);
4003      }
4004    "#,
4005      indoc! {r#"
4006      .foo {
4007        height: var(--size);
4008        min-height: var(--size);
4009        width: var(--size);
4010        min-width: var(--size);
4011      }
4012    "#},
4013      Browsers {
4014        safari: Some(8 << 16),
4015        ..Browsers::default()
4016      },
4017    );
4018
4019    for (in_prop, out_prop) in [
4020      ("width", "width"),
4021      ("height", "height"),
4022      ("block-size", "height"),
4023      ("inline-size", "width"),
4024      ("min-width", "min-width"),
4025      ("min-height", "min-height"),
4026      ("min-block-size", "min-height"),
4027      ("min-inline-size", "min-width"),
4028      ("max-width", "max-width"),
4029      ("max-height", "max-height"),
4030      ("max-block-size", "max-height"),
4031      ("max-inline-size", "max-width"),
4032    ] {
4033      prefix_test(
4034        &format!(
4035          r#"
4036        .foo {{
4037          {}: stretch;
4038        }}
4039      "#,
4040          in_prop
4041        ),
4042        &format!(
4043          indoc! {r#"
4044        .foo {{
4045          {}: -webkit-fill-available;
4046          {}: -moz-available;
4047          {}: stretch;
4048        }}
4049      "#},
4050          out_prop, out_prop, out_prop
4051        ),
4052        Browsers {
4053          safari: Some(8 << 16),
4054          firefox: Some(4 << 16),
4055          ..Browsers::default()
4056        },
4057      );
4058
4059      prefix_test(
4060        &format!(
4061          r#"
4062        .foo {{
4063          {}: -webkit-fill-available;
4064        }}
4065      "#,
4066          in_prop
4067        ),
4068        &format!(
4069          indoc! {r#"
4070        .foo {{
4071          {}: -webkit-fill-available;
4072        }}
4073      "#},
4074          out_prop
4075        ),
4076        Browsers {
4077          safari: Some(8 << 16),
4078          firefox: Some(4 << 16),
4079          ..Browsers::default()
4080        },
4081      );
4082
4083      prefix_test(
4084        &format!(
4085          r#"
4086        .foo {{
4087          {}: 100vw;
4088          {}: -webkit-fill-available;
4089        }}
4090      "#,
4091          in_prop, in_prop
4092        ),
4093        &format!(
4094          indoc! {r#"
4095        .foo {{
4096          {}: 100vw;
4097          {}: -webkit-fill-available;
4098        }}
4099      "#},
4100          out_prop, out_prop
4101        ),
4102        Browsers {
4103          safari: Some(8 << 16),
4104          firefox: Some(4 << 16),
4105          ..Browsers::default()
4106        },
4107      );
4108
4109      prefix_test(
4110        &format!(
4111          r#"
4112        .foo {{
4113          {}: fit-content;
4114        }}
4115      "#,
4116          in_prop
4117        ),
4118        &format!(
4119          indoc! {r#"
4120        .foo {{
4121          {}: -webkit-fit-content;
4122          {}: -moz-fit-content;
4123          {}: fit-content;
4124        }}
4125      "#},
4126          out_prop, out_prop, out_prop
4127        ),
4128        Browsers {
4129          safari: Some(8 << 16),
4130          firefox: Some(4 << 16),
4131          ..Browsers::default()
4132        },
4133      );
4134
4135      prefix_test(
4136        &format!(
4137          r#"
4138        .foo {{
4139          {}: fit-content(50%);
4140        }}
4141      "#,
4142          in_prop
4143        ),
4144        &format!(
4145          indoc! {r#"
4146        .foo {{
4147          {}: fit-content(50%);
4148        }}
4149      "#},
4150          out_prop
4151        ),
4152        Browsers {
4153          safari: Some(8 << 16),
4154          firefox: Some(4 << 16),
4155          ..Browsers::default()
4156        },
4157      );
4158
4159      prefix_test(
4160        &format!(
4161          r#"
4162        .foo {{
4163          {}: min-content;
4164        }}
4165      "#,
4166          in_prop
4167        ),
4168        &format!(
4169          indoc! {r#"
4170        .foo {{
4171          {}: -webkit-min-content;
4172          {}: -moz-min-content;
4173          {}: min-content;
4174        }}
4175      "#},
4176          out_prop, out_prop, out_prop
4177        ),
4178        Browsers {
4179          safari: Some(8 << 16),
4180          firefox: Some(4 << 16),
4181          ..Browsers::default()
4182        },
4183      );
4184
4185      prefix_test(
4186        &format!(
4187          r#"
4188        .foo {{
4189          {}: max-content;
4190        }}
4191      "#,
4192          in_prop
4193        ),
4194        &format!(
4195          indoc! {r#"
4196        .foo {{
4197          {}: -webkit-max-content;
4198          {}: -moz-max-content;
4199          {}: max-content;
4200        }}
4201      "#},
4202          out_prop, out_prop, out_prop
4203        ),
4204        Browsers {
4205          safari: Some(8 << 16),
4206          firefox: Some(4 << 16),
4207          ..Browsers::default()
4208        },
4209      );
4210
4211      prefix_test(
4212        &format!(
4213          r#"
4214        .foo {{
4215          {}: 100%;
4216          {}: max-content;
4217        }}
4218      "#,
4219          in_prop, in_prop
4220        ),
4221        &format!(
4222          indoc! {r#"
4223        .foo {{
4224          {}: 100%;
4225          {}: max-content;
4226        }}
4227      "#},
4228          out_prop, out_prop
4229        ),
4230        Browsers {
4231          safari: Some(8 << 16),
4232          firefox: Some(4 << 16),
4233          ..Browsers::default()
4234        },
4235      );
4236
4237      prefix_test(
4238        &format!(
4239          r#"
4240        .foo {{
4241          {}: var(--fallback);
4242          {}: max-content;
4243        }}
4244      "#,
4245          in_prop, in_prop
4246        ),
4247        &format!(
4248          indoc! {r#"
4249        .foo {{
4250          {}: var(--fallback);
4251          {}: max-content;
4252        }}
4253      "#},
4254          out_prop, out_prop
4255        ),
4256        Browsers {
4257          safari: Some(8 << 16),
4258          firefox: Some(4 << 16),
4259          ..Browsers::default()
4260        },
4261      );
4262    }
4263
4264    minify_test(".foo { aspect-ratio: auto }", ".foo{aspect-ratio:auto}");
4265    minify_test(".foo { aspect-ratio: 2 / 3 }", ".foo{aspect-ratio:2/3}");
4266    minify_test(".foo { aspect-ratio: auto 2 / 3 }", ".foo{aspect-ratio:auto 2/3}");
4267    minify_test(".foo { aspect-ratio: 2 / 3 auto }", ".foo{aspect-ratio:auto 2/3}");
4268
4269    minify_test(
4270      ".foo { width: 200px; width: var(--foo); }",
4271      ".foo{width:200px;width:var(--foo)}",
4272    );
4273    minify_test(
4274      ".foo { width: var(--foo); width: 200px; }",
4275      ".foo{width:var(--foo);width:200px}",
4276    );
4277  }
4278
4279  #[test]
4280  pub fn test_background() {
4281    test(
4282      r#"
4283      .foo {
4284        background: url(img.png);
4285        background-position-x: 20px;
4286        background-position-y: 10px;
4287        background-size: 50px 100px;
4288        background-repeat: repeat no-repeat;
4289      }
4290    "#,
4291      indoc! {r#"
4292      .foo {
4293        background: url("img.png") 20px 10px / 50px 100px repeat-x;
4294      }
4295    "#
4296      },
4297    );
4298
4299    test(
4300      r#"
4301      .foo {
4302        background-color: red;
4303        background-position: 0% 0%;
4304        background-size: auto;
4305        background-repeat: repeat;
4306        background-clip: border-box;
4307        background-origin: padding-box;
4308        background-attachment: scroll;
4309        background-image: none
4310      }
4311    "#,
4312      indoc! {r#"
4313      .foo {
4314        background: red;
4315      }
4316    "#
4317      },
4318    );
4319
4320    test(
4321      r#"
4322      .foo {
4323        background-color: gray;
4324        background-position: 40% 50%;
4325        background-size: 10em auto;
4326        background-repeat: round;
4327        background-clip: border-box;
4328        background-origin: border-box;
4329        background-attachment: fixed;
4330        background-image: url('chess.png');
4331      }
4332    "#,
4333      indoc! {r#"
4334      .foo {
4335        background: gray url("chess.png") 40% / 10em round fixed border-box;
4336      }
4337    "#
4338      },
4339    );
4340
4341    test(
4342      r#"
4343      .foo {
4344        background: url(img.png), url(test.jpg) gray;
4345        background-position-x: right 20px, 10px;
4346        background-position-y: top 20px, 15px;
4347        background-size: 50px 50px, auto;
4348        background-repeat: repeat no-repeat, no-repeat;
4349      }
4350    "#,
4351      indoc! {r#"
4352      .foo {
4353        background: url("img.png") right 20px top 20px / 50px 50px repeat-x, gray url("test.jpg") 10px 15px no-repeat;
4354      }
4355    "#
4356      },
4357    );
4358
4359    minify_test(
4360      r#"
4361      .foo {
4362        background-position: center center;
4363      }
4364    "#,
4365      indoc! {".foo{background-position:50%}"
4366      },
4367    );
4368
4369    test(
4370      r#"
4371      .foo {
4372        background: url(img.png) gray;
4373        background-clip: content-box;
4374        -webkit-background-clip: text;
4375      }
4376    "#,
4377      indoc! {r#"
4378      .foo {
4379        background: gray url("img.png") padding-box content-box;
4380        -webkit-background-clip: text;
4381      }
4382    "#
4383      },
4384    );
4385
4386    test(
4387      r#"
4388      .foo {
4389        background: url(img.png) gray;
4390        -webkit-background-clip: text;
4391        background-clip: content-box;
4392      }
4393    "#,
4394      indoc! {r#"
4395      .foo {
4396        background: gray url("img.png");
4397        -webkit-background-clip: text;
4398        background-clip: content-box;
4399      }
4400    "#
4401      },
4402    );
4403
4404    test(
4405      r#"
4406      .foo {
4407        background: url(img.png) gray;
4408        background-position: var(--pos);
4409      }
4410    "#,
4411      indoc! {r#"
4412      .foo {
4413        background: gray url("img.png");
4414        background-position: var(--pos);
4415      }
4416    "#
4417      },
4418    );
4419
4420    minify_test(
4421      ".foo { background-position: bottom left }",
4422      ".foo{background-position:0 100%}",
4423    );
4424    minify_test(
4425      ".foo { background-position: left 10px center }",
4426      ".foo{background-position:10px}",
4427    );
4428    minify_test(
4429      ".foo { background-position: right 10px center }",
4430      ".foo{background-position:right 10px center}",
4431    );
4432    minify_test(
4433      ".foo { background-position: center top 10px }",
4434      ".foo{background-position:50% 10px}",
4435    );
4436    minify_test(
4437      ".foo { background-position: center bottom 10px }",
4438      ".foo{background-position:center bottom 10px}",
4439    );
4440    minify_test(
4441      ".foo { background-position: center 10px }",
4442      ".foo{background-position:50% 10px}",
4443    );
4444    minify_test(
4445      ".foo { background-position: right 10px top 20px }",
4446      ".foo{background-position:right 10px top 20px}",
4447    );
4448    minify_test(
4449      ".foo { background-position: left 10px top 20px }",
4450      ".foo{background-position:10px 20px}",
4451    );
4452    minify_test(
4453      ".foo { background-position: left 10px bottom 20px }",
4454      ".foo{background-position:left 10px bottom 20px}",
4455    );
4456    minify_test(
4457      ".foo { background-position: left 10px top }",
4458      ".foo{background-position:10px 0}",
4459    );
4460    minify_test(
4461      ".foo { background-position: bottom right }",
4462      ".foo{background-position:100% 100%}",
4463    );
4464    minify_test(
4465      ".foo { background-position: center top }",
4466      ".foo{background-position:top}",
4467    );
4468    minify_test(
4469      ".foo { background-position: center bottom }",
4470      ".foo{background-position:bottom}",
4471    );
4472    minify_test(
4473      ".foo { background-position: left center }",
4474      ".foo{background-position:0}",
4475    );
4476    minify_test(
4477      ".foo { background-position: right center }",
4478      ".foo{background-position:100%}",
4479    );
4480    minify_test(
4481      ".foo { background-position: 20px center }",
4482      ".foo{background-position:20px}",
4483    );
4484
4485    minify_test(
4486      ".foo { background: url('img-sprite.png') no-repeat bottom right }",
4487      ".foo{background:url(img-sprite.png) 100% 100% no-repeat}",
4488    );
4489    minify_test(".foo { background: transparent }", ".foo{background:0 0}");
4490
4491    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\")}");
4492
4493    test(
4494      r#"
4495      .foo {
4496        background: url(img.png);
4497        background-clip: text;
4498      }
4499    "#,
4500      indoc! {r#"
4501      .foo {
4502        background: url("img.png") text;
4503      }
4504    "#
4505      },
4506    );
4507
4508    prefix_test(
4509      r#"
4510      .foo {
4511        background: url(img.png);
4512        background-clip: text;
4513      }
4514    "#,
4515      indoc! {r#"
4516      .foo {
4517        background: url("img.png");
4518        -webkit-background-clip: text;
4519        background-clip: text;
4520      }
4521    "#
4522      },
4523      Browsers {
4524        safari: Some(8 << 16),
4525        ..Browsers::default()
4526      },
4527    );
4528
4529    prefix_test(
4530      r#"
4531      .foo {
4532        background: url(img.png);
4533        background-clip: text;
4534      }
4535    "#,
4536      indoc! {r#"
4537      .foo {
4538        background: url("img.png") text;
4539      }
4540    "#
4541      },
4542      Browsers {
4543        safari: Some(14 << 16),
4544        ..Browsers::default()
4545      },
4546    );
4547
4548    prefix_test(
4549      r#"
4550      .foo {
4551        background: url(img.png) text;
4552      }
4553    "#,
4554      indoc! {r#"
4555      .foo {
4556        background: url("img.png");
4557        -webkit-background-clip: text;
4558        background-clip: text;
4559      }
4560    "#
4561      },
4562      Browsers {
4563        chrome: Some(45 << 16),
4564        ..Browsers::default()
4565      },
4566    );
4567
4568    prefix_test(
4569      r#"
4570      .foo {
4571        background: url(img.png);
4572        -webkit-background-clip: text;
4573      }
4574    "#,
4575      indoc! {r#"
4576      .foo {
4577        background: url("img.png");
4578        -webkit-background-clip: text;
4579      }
4580    "#
4581      },
4582      Browsers {
4583        chrome: Some(45 << 16),
4584        ..Browsers::default()
4585      },
4586    );
4587
4588    prefix_test(
4589      r#"
4590      .foo {
4591        background: url(img.png);
4592        background-clip: text;
4593      }
4594    "#,
4595      indoc! {r#"
4596      .foo {
4597        background: url("img.png");
4598        -webkit-background-clip: text;
4599        background-clip: text;
4600      }
4601    "#
4602      },
4603      Browsers {
4604        safari: Some(14 << 16),
4605        chrome: Some(95 << 16),
4606        ..Browsers::default()
4607      },
4608    );
4609
4610    prefix_test(
4611      r#"
4612      .foo {
4613        background-image: url(img.png);
4614        background-clip: text;
4615      }
4616    "#,
4617      indoc! {r#"
4618      .foo {
4619        background-image: url("img.png");
4620        -webkit-background-clip: text;
4621        background-clip: text;
4622      }
4623    "#
4624      },
4625      Browsers {
4626        safari: Some(8 << 16),
4627        ..Browsers::default()
4628      },
4629    );
4630
4631    prefix_test(
4632      r#"
4633      .foo {
4634        -webkit-background-clip: text;
4635        background-clip: text;
4636      }
4637    "#,
4638      indoc! {r#"
4639      .foo {
4640        -webkit-background-clip: text;
4641        background-clip: text;
4642      }
4643    "#
4644      },
4645      Browsers {
4646        chrome: Some(45 << 16),
4647        ..Browsers::default()
4648      },
4649    );
4650
4651    prefix_test(
4652      r#"
4653      .foo {
4654        background-image: url(img.png);
4655        background-clip: text;
4656      }
4657    "#,
4658      indoc! {r#"
4659      .foo {
4660        background-image: url("img.png");
4661        background-clip: text;
4662      }
4663    "#
4664      },
4665      Browsers {
4666        safari: Some(14 << 16),
4667        ..Browsers::default()
4668      },
4669    );
4670
4671    minify_test(".foo { background: none center }", ".foo{background:50%}");
4672    minify_test(".foo { background: none }", ".foo{background:0 0}");
4673
4674    prefix_test(
4675      r#"
4676      .foo {
4677        background: lab(51.5117% 43.3777 -29.0443);
4678      }
4679    "#,
4680      indoc! {r#"
4681      .foo {
4682        background: #af5cae;
4683        background: lab(51.5117% 43.3777 -29.0443);
4684      }
4685    "#
4686      },
4687      Browsers {
4688        chrome: Some(95 << 16),
4689        safari: Some(15 << 16),
4690        ..Browsers::default()
4691      },
4692    );
4693
4694    prefix_test(
4695      r#"
4696      .foo {
4697        background: lab(51.5117% 43.3777 -29.0443) url(foo.png);
4698      }
4699    "#,
4700      indoc! {r#"
4701      .foo {
4702        background: #af5cae url("foo.png");
4703        background: lab(51.5117% 43.3777 -29.0443) url("foo.png");
4704      }
4705    "#
4706      },
4707      Browsers {
4708        chrome: Some(95 << 16),
4709        safari: Some(15 << 16),
4710        ..Browsers::default()
4711      },
4712    );
4713
4714    prefix_test(
4715      r#"
4716      .foo {
4717        background: lab(51.5117% 43.3777 -29.0443) linear-gradient(lab(52.2319% 40.1449 59.9171), lab(47.7776% -34.2947 -7.65904));
4718      }
4719    "#,
4720      indoc! {r#"
4721      .foo {
4722        background: #af5cae linear-gradient(#c65d07, #00807c);
4723        background: lab(51.5117% 43.3777 -29.0443) linear-gradient(lab(52.2319% 40.1449 59.9171), lab(47.7776% -34.2947 -7.65904));
4724      }
4725    "#
4726      },
4727      Browsers {
4728        chrome: Some(95 << 16),
4729        safari: Some(15 << 16),
4730        ..Browsers::default()
4731      },
4732    );
4733
4734    test(
4735      ".foo { background: calc(var(--v) / 0.3)",
4736      indoc! {r#"
4737      .foo {
4738        background: calc(var(--v) / .3);
4739      }
4740    "#},
4741    );
4742
4743    prefix_test(
4744      r#"
4745      .foo {
4746        background-color: #4263eb;
4747        background-color: color(display-p3 0 .5 1);
4748      }
4749    "#,
4750      indoc! {r#"
4751      .foo {
4752        background-color: #4263eb;
4753        background-color: color(display-p3 0 .5 1);
4754      }
4755    "#
4756      },
4757      Browsers {
4758        chrome: Some(99 << 16),
4759        ..Browsers::default()
4760      },
4761    );
4762    prefix_test(
4763      r#"
4764      .foo {
4765        background-color: #4263eb;
4766        background-color: color(display-p3 0 .5 1);
4767      }
4768    "#,
4769      indoc! {r#"
4770      .foo {
4771        background-color: color(display-p3 0 .5 1);
4772      }
4773    "#
4774      },
4775      Browsers {
4776        safari: Some(16 << 16),
4777        ..Browsers::default()
4778      },
4779    );
4780    prefix_test(
4781      r#"
4782      .foo {
4783        background-image: linear-gradient(red, green);
4784        background-image: linear-gradient(lch(50% 132 50), lch(50% 130 150));
4785      }
4786    "#,
4787      indoc! {r#"
4788      .foo {
4789        background-image: linear-gradient(red, green);
4790        background-image: linear-gradient(lch(50% 132 50), lch(50% 130 150));
4791      }
4792    "#
4793      },
4794      Browsers {
4795        chrome: Some(99 << 16),
4796        ..Browsers::default()
4797      },
4798    );
4799    prefix_test(
4800      r#"
4801      .foo {
4802        background-image: linear-gradient(red, green);
4803        background-image: linear-gradient(lch(50% 132 50), lch(50% 130 150));
4804      }
4805    "#,
4806      indoc! {r#"
4807      .foo {
4808        background-image: linear-gradient(lch(50% 132 50), lch(50% 130 150));
4809      }
4810    "#
4811      },
4812      Browsers {
4813        safari: Some(16 << 16),
4814        ..Browsers::default()
4815      },
4816    );
4817    prefix_test(
4818      r#"
4819      .foo {
4820        background: #4263eb;
4821        background: color(display-p3 0 .5 1);
4822      }
4823    "#,
4824      indoc! {r#"
4825      .foo {
4826        background: #4263eb;
4827        background: color(display-p3 0 .5 1);
4828      }
4829    "#
4830      },
4831      Browsers {
4832        chrome: Some(99 << 16),
4833        ..Browsers::default()
4834      },
4835    );
4836    prefix_test(
4837      r#"
4838      .foo {
4839        background: #4263eb;
4840        background: color(display-p3 0 .5 1);
4841      }
4842    "#,
4843      indoc! {r#"
4844      .foo {
4845        background: color(display-p3 0 .5 1);
4846      }
4847    "#
4848      },
4849      Browsers {
4850        safari: Some(16 << 16),
4851        ..Browsers::default()
4852      },
4853    );
4854    prefix_test(
4855      r#"
4856      .foo {
4857        background: linear-gradient(red, green);
4858        background: linear-gradient(lch(50% 132 50), lch(50% 130 150));
4859      }
4860    "#,
4861      indoc! {r#"
4862      .foo {
4863        background: linear-gradient(red, green);
4864        background: linear-gradient(lch(50% 132 50), lch(50% 130 150));
4865      }
4866    "#
4867      },
4868      Browsers {
4869        chrome: Some(99 << 16),
4870        ..Browsers::default()
4871      },
4872    );
4873    prefix_test(
4874      r#"
4875      .foo {
4876        background: red;
4877        background: linear-gradient(lch(50% 132 50), lch(50% 130 150));
4878      }
4879    "#,
4880      indoc! {r#"
4881      .foo {
4882        background: red;
4883        background: linear-gradient(lch(50% 132 50), lch(50% 130 150));
4884      }
4885    "#
4886      },
4887      Browsers {
4888        chrome: Some(99 << 16),
4889        ..Browsers::default()
4890      },
4891    );
4892    prefix_test(
4893      r#"
4894      .foo {
4895        background: linear-gradient(red, green);
4896        background: linear-gradient(lch(50% 132 50), lch(50% 130 150));
4897      }
4898    "#,
4899      indoc! {r#"
4900      .foo {
4901        background: linear-gradient(lch(50% 132 50), lch(50% 130 150));
4902      }
4903    "#
4904      },
4905      Browsers {
4906        safari: Some(16 << 16),
4907        ..Browsers::default()
4908      },
4909    );
4910    prefix_test(
4911      r#"
4912      .foo {
4913        background: var(--fallback);
4914        background: linear-gradient(lch(50% 132 50), lch(50% 130 150));
4915      }
4916    "#,
4917      indoc! {r#"
4918      .foo {
4919        background: var(--fallback);
4920        background: linear-gradient(lch(50% 132 50), lch(50% 130 150));
4921      }
4922    "#
4923      },
4924      Browsers {
4925        chrome: Some(99 << 16),
4926        ..Browsers::default()
4927      },
4928    );
4929    prefix_test(
4930      r#"
4931      .foo {
4932        background: red url(foo.png);
4933        background: lch(50% 132 50) url(foo.png);
4934      }
4935    "#,
4936      indoc! {r#"
4937      .foo {
4938        background: red url("foo.png");
4939        background: lch(50% 132 50) url("foo.png");
4940      }
4941    "#
4942      },
4943      Browsers {
4944        chrome: Some(99 << 16),
4945        ..Browsers::default()
4946      },
4947    );
4948  }
4949
4950  #[test]
4951  pub fn test_flex() {
4952    test(
4953      r#"
4954      .foo {
4955        flex-direction: column;
4956        flex-wrap: wrap;
4957      }
4958    "#,
4959      indoc! {r#"
4960      .foo {
4961        flex-flow: column wrap;
4962      }
4963    "#
4964      },
4965    );
4966
4967    test(
4968      r#"
4969      .foo {
4970        flex-direction: row;
4971        flex-wrap: wrap;
4972      }
4973    "#,
4974      indoc! {r#"
4975      .foo {
4976        flex-flow: wrap;
4977      }
4978    "#
4979      },
4980    );
4981
4982    test(
4983      r#"
4984      .foo {
4985        flex-direction: row;
4986        flex-wrap: nowrap;
4987      }
4988    "#,
4989      indoc! {r#"
4990      .foo {
4991        flex-flow: row;
4992      }
4993    "#
4994      },
4995    );
4996
4997    test(
4998      r#"
4999      .foo {
5000        flex-direction: column;
5001        flex-wrap: nowrap;
5002      }
5003    "#,
5004      indoc! {r#"
5005      .foo {
5006        flex-flow: column;
5007      }
5008    "#
5009      },
5010    );
5011
5012    test(
5013      r#"
5014      .foo {
5015        flex-grow: 1;
5016        flex-shrink: 1;
5017        flex-basis: 0%;
5018      }
5019    "#,
5020      indoc! {r#"
5021      .foo {
5022        flex: 1;
5023      }
5024    "#
5025      },
5026    );
5027
5028    test(
5029      r#"
5030      .foo {
5031        flex-grow: 1;
5032        flex-shrink: 1;
5033        flex-basis: 0;
5034      }
5035    "#,
5036      indoc! {r#"
5037      .foo {
5038        flex: 1 1 0;
5039      }
5040    "#
5041      },
5042    );
5043
5044    test(
5045      r#"
5046      .foo {
5047        flex-grow: 1;
5048        flex-shrink: 1;
5049        flex-basis: 0px;
5050      }
5051    "#,
5052      indoc! {r#"
5053      .foo {
5054        flex: 1 1 0;
5055      }
5056    "#
5057      },
5058    );
5059
5060    test(
5061      r#"
5062      .foo {
5063        flex-grow: 1;
5064        flex-shrink: 2;
5065        flex-basis: 0%;
5066      }
5067    "#,
5068      indoc! {r#"
5069      .foo {
5070        flex: 1 2;
5071      }
5072    "#
5073      },
5074    );
5075
5076    test(
5077      r#"
5078      .foo {
5079        flex-grow: 2;
5080        flex-shrink: 1;
5081        flex-basis: 0%;
5082      }
5083    "#,
5084      indoc! {r#"
5085      .foo {
5086        flex: 2;
5087      }
5088    "#
5089      },
5090    );
5091
5092    test(
5093      r#"
5094      .foo {
5095        flex-grow: 2;
5096        flex-shrink: 2;
5097        flex-basis: 0%;
5098      }
5099    "#,
5100      indoc! {r#"
5101      .foo {
5102        flex: 2 2;
5103      }
5104    "#
5105      },
5106    );
5107
5108    test(
5109      r#"
5110      .foo {
5111        flex-grow: 1;
5112        flex-shrink: 1;
5113        flex-basis: 10px;
5114      }
5115    "#,
5116      indoc! {r#"
5117      .foo {
5118        flex: 10px;
5119      }
5120    "#
5121      },
5122    );
5123
5124    test(
5125      r#"
5126      .foo {
5127        flex-grow: 2;
5128        flex-shrink: 1;
5129        flex-basis: 10px;
5130      }
5131    "#,
5132      indoc! {r#"
5133      .foo {
5134        flex: 2 10px;
5135      }
5136    "#
5137      },
5138    );
5139
5140    test(
5141      r#"
5142      .foo {
5143        flex-grow: 1;
5144        flex-shrink: 0;
5145        flex-basis: 0%;
5146      }
5147    "#,
5148      indoc! {r#"
5149      .foo {
5150        flex: 1 0;
5151      }
5152    "#
5153      },
5154    );
5155
5156    test(
5157      r#"
5158      .foo {
5159        flex-grow: 1;
5160        flex-shrink: 0;
5161        flex-basis: auto;
5162      }
5163    "#,
5164      indoc! {r#"
5165      .foo {
5166        flex: 1 0 auto;
5167      }
5168    "#
5169      },
5170    );
5171
5172    test(
5173      r#"
5174      .foo {
5175        flex-grow: 1;
5176        flex-shrink: 1;
5177        flex-basis: auto;
5178      }
5179    "#,
5180      indoc! {r#"
5181      .foo {
5182        flex: auto;
5183      }
5184    "#
5185      },
5186    );
5187
5188    test(
5189      r#"
5190      .foo {
5191        flex: 0 0;
5192        flex-grow: 1;
5193      }
5194    "#,
5195      indoc! {r#"
5196      .foo {
5197        flex: 1 0;
5198      }
5199    "#
5200      },
5201    );
5202
5203    test(
5204      r#"
5205      .foo {
5206        flex: 0 0;
5207        flex-grow: var(--grow);
5208      }
5209    "#,
5210      indoc! {r#"
5211      .foo {
5212        flex: 0 0;
5213        flex-grow: var(--grow);
5214      }
5215    "#
5216      },
5217    );
5218
5219    test(
5220      r#"
5221      .foo {
5222        align-content: center;
5223        justify-content: center;
5224      }
5225    "#,
5226      indoc! {r#"
5227      .foo {
5228        place-content: center;
5229      }
5230    "#
5231      },
5232    );
5233
5234    test(
5235      r#"
5236      .foo {
5237        align-content: first baseline;
5238        justify-content: safe right;
5239      }
5240    "#,
5241      indoc! {r#"
5242      .foo {
5243        place-content: baseline safe right;
5244      }
5245    "#
5246      },
5247    );
5248
5249    test(
5250      r#"
5251      .foo {
5252        place-content: first baseline unsafe left;
5253      }
5254    "#,
5255      indoc! {r#"
5256      .foo {
5257        place-content: baseline unsafe left;
5258      }
5259    "#
5260      },
5261    );
5262
5263    test(
5264      r#"
5265      .foo {
5266        place-content: center center;
5267      }
5268    "#,
5269      indoc! {r#"
5270      .foo {
5271        place-content: center;
5272      }
5273    "#
5274      },
5275    );
5276
5277    test(
5278      r#"
5279      .foo {
5280        align-self: center;
5281        justify-self: center;
5282      }
5283    "#,
5284      indoc! {r#"
5285      .foo {
5286        place-self: center;
5287      }
5288    "#
5289      },
5290    );
5291
5292    test(
5293      r#"
5294      .foo {
5295        align-self: center;
5296        justify-self: unsafe left;
5297      }
5298    "#,
5299      indoc! {r#"
5300      .foo {
5301        place-self: center unsafe left;
5302      }
5303    "#
5304      },
5305    );
5306
5307    test(
5308      r#"
5309      .foo {
5310        align-items: center;
5311        justify-items: center;
5312      }
5313    "#,
5314      indoc! {r#"
5315      .foo {
5316        place-items: center;
5317      }
5318    "#
5319      },
5320    );
5321
5322    test(
5323      r#"
5324      .foo {
5325        align-items: center;
5326        justify-items: legacy left;
5327      }
5328    "#,
5329      indoc! {r#"
5330      .foo {
5331        place-items: center legacy left;
5332      }
5333    "#
5334      },
5335    );
5336
5337    test(
5338      r#"
5339      .foo {
5340        place-items: center;
5341        justify-items: var(--justify);
5342      }
5343    "#,
5344      indoc! {r#"
5345      .foo {
5346        place-items: center;
5347        justify-items: var(--justify);
5348      }
5349    "#
5350      },
5351    );
5352
5353    test(
5354      r#"
5355      .foo {
5356        row-gap: 10px;
5357        column-gap: 20px;
5358      }
5359    "#,
5360      indoc! {r#"
5361      .foo {
5362        gap: 10px 20px;
5363      }
5364    "#
5365      },
5366    );
5367
5368    test(
5369      r#"
5370      .foo {
5371        row-gap: 10px;
5372        column-gap: 10px;
5373      }
5374    "#,
5375      indoc! {r#"
5376      .foo {
5377        gap: 10px;
5378      }
5379    "#
5380      },
5381    );
5382
5383    test(
5384      r#"
5385      .foo {
5386        gap: 10px;
5387        column-gap: 20px;
5388      }
5389    "#,
5390      indoc! {r#"
5391      .foo {
5392        gap: 10px 20px;
5393      }
5394    "#
5395      },
5396    );
5397
5398    test(
5399      r#"
5400      .foo {
5401        column-gap: 20px;
5402        gap: 10px;
5403      }
5404    "#,
5405      indoc! {r#"
5406      .foo {
5407        gap: 10px;
5408      }
5409    "#
5410      },
5411    );
5412
5413    test(
5414      r#"
5415      .foo {
5416        row-gap: normal;
5417        column-gap: 20px;
5418      }
5419    "#,
5420      indoc! {r#"
5421      .foo {
5422        gap: normal 20px;
5423      }
5424    "#
5425      },
5426    );
5427
5428    test(
5429      r#"
5430      .foo {
5431        -webkit-flex-grow: 1;
5432        -webkit-flex-shrink: 1;
5433        -webkit-flex-basis: auto;
5434      }
5435    "#,
5436      indoc! {r#"
5437      .foo {
5438        -webkit-flex: auto;
5439      }
5440    "#
5441      },
5442    );
5443    test(
5444      r#"
5445      .foo {
5446        -webkit-flex-grow: 1;
5447        -webkit-flex-shrink: 1;
5448        -webkit-flex-basis: auto;
5449        flex-grow: 1;
5450        flex-shrink: 1;
5451        flex-basis: auto;
5452      }
5453    "#,
5454      indoc! {r#"
5455      .foo {
5456        -webkit-flex: auto;
5457        flex: auto;
5458      }
5459    "#
5460      },
5461    );
5462    prefix_test(
5463      r#"
5464      .foo {
5465        -webkit-box-orient: horizontal;
5466        -webkit-box-direction: normal;
5467        flex-direction: row;
5468      }
5469    "#,
5470      indoc! {r#"
5471      .foo {
5472        -webkit-box-orient: horizontal;
5473        -webkit-box-direction: normal;
5474        -webkit-flex-direction: row;
5475        flex-direction: row;
5476      }
5477    "#},
5478      Browsers {
5479        safari: Some(4 << 16),
5480        ..Browsers::default()
5481      },
5482    );
5483    prefix_test(
5484      r#"
5485      .foo {
5486        flex-direction: row;
5487      }
5488    "#,
5489      indoc! {r#"
5490      .foo {
5491        -webkit-box-orient: horizontal;
5492        -moz-box-orient: horizontal;
5493        -webkit-box-direction: normal;
5494        -moz-box-direction: normal;
5495        -webkit-flex-direction: row;
5496        -ms-flex-direction: row;
5497        flex-direction: row;
5498      }
5499    "#},
5500      Browsers {
5501        safari: Some(4 << 16),
5502        firefox: Some(4 << 16),
5503        ie: Some(10 << 16),
5504        ..Browsers::default()
5505      },
5506    );
5507    prefix_test(
5508      r#"
5509      .foo {
5510        -webkit-box-orient: horizontal;
5511        -webkit-box-direction: normal;
5512        -moz-box-orient: horizontal;
5513        -moz-box-direction: normal;
5514        -webkit-flex-direction: row;
5515        -ms-flex-direction: row;
5516        flex-direction: row;
5517      }
5518    "#,
5519      indoc! {r#"
5520      .foo {
5521        flex-direction: row;
5522      }
5523    "#},
5524      Browsers {
5525        safari: Some(14 << 16),
5526        ..Browsers::default()
5527      },
5528    );
5529    prefix_test(
5530      r#"
5531      .foo {
5532        flex-wrap: wrap;
5533      }
5534    "#,
5535      indoc! {r#"
5536      .foo {
5537        -webkit-box-lines: multiple;
5538        -moz-box-lines: multiple;
5539        -webkit-flex-wrap: wrap;
5540        -ms-flex-wrap: wrap;
5541        flex-wrap: wrap;
5542      }
5543    "#},
5544      Browsers {
5545        safari: Some(4 << 16),
5546        firefox: Some(4 << 16),
5547        ie: Some(10 << 16),
5548        ..Browsers::default()
5549      },
5550    );
5551    prefix_test(
5552      r#"
5553      .foo {
5554        -webkit-box-lines: multiple;
5555        -moz-box-lines: multiple;
5556        -webkit-flex-wrap: wrap;
5557        -ms-flex-wrap: wrap;
5558        flex-wrap: wrap;
5559      }
5560    "#,
5561      indoc! {r#"
5562      .foo {
5563        flex-wrap: wrap;
5564      }
5565    "#},
5566      Browsers {
5567        safari: Some(11 << 16),
5568        ..Browsers::default()
5569      },
5570    );
5571    prefix_test(
5572      r#"
5573      .foo {
5574        flex-flow: row wrap;
5575      }
5576    "#,
5577      indoc! {r#"
5578      .foo {
5579        -webkit-box-orient: horizontal;
5580        -moz-box-orient: horizontal;
5581        -webkit-box-direction: normal;
5582        -moz-box-direction: normal;
5583        -webkit-flex-flow: wrap;
5584        -ms-flex-flow: wrap;
5585        flex-flow: wrap;
5586      }
5587    "#},
5588      Browsers {
5589        safari: Some(4 << 16),
5590        firefox: Some(4 << 16),
5591        ie: Some(10 << 16),
5592        ..Browsers::default()
5593      },
5594    );
5595    prefix_test(
5596      r#"
5597      .foo {
5598        -webkit-box-orient: horizontal;
5599        -moz-box-orient: horizontal;
5600        -webkit-box-direction: normal;
5601        -moz-box-direction: normal;
5602        -webkit-flex-flow: wrap;
5603        -ms-flex-flow: wrap;
5604        flex-flow: wrap;
5605      }
5606    "#,
5607      indoc! {r#"
5608      .foo {
5609        flex-flow: wrap;
5610      }
5611    "#},
5612      Browsers {
5613        safari: Some(11 << 16),
5614        ..Browsers::default()
5615      },
5616    );
5617    prefix_test(
5618      r#"
5619      .foo {
5620        flex-grow: 1;
5621      }
5622    "#,
5623      indoc! {r#"
5624      .foo {
5625        -webkit-box-flex: 1;
5626        -moz-box-flex: 1;
5627        -ms-flex-positive: 1;
5628        -webkit-flex-grow: 1;
5629        flex-grow: 1;
5630      }
5631    "#},
5632      Browsers {
5633        safari: Some(4 << 16),
5634        firefox: Some(4 << 16),
5635        ie: Some(10 << 16),
5636        ..Browsers::default()
5637      },
5638    );
5639    prefix_test(
5640      r#"
5641      .foo {
5642        -webkit-box-flex: 1;
5643        -moz-box-flex: 1;
5644        -ms-flex-positive: 1;
5645        -webkit-flex-grow: 1;
5646        flex-grow: 1;
5647      }
5648    "#,
5649      indoc! {r#"
5650      .foo {
5651        flex-grow: 1;
5652      }
5653    "#},
5654      Browsers {
5655        safari: Some(11 << 16),
5656        ..Browsers::default()
5657      },
5658    );
5659    prefix_test(
5660      r#"
5661      .foo {
5662        flex-shrink: 1;
5663      }
5664    "#,
5665      indoc! {r#"
5666      .foo {
5667        -ms-flex-negative: 1;
5668        -webkit-flex-shrink: 1;
5669        flex-shrink: 1;
5670      }
5671    "#},
5672      Browsers {
5673        safari: Some(4 << 16),
5674        firefox: Some(4 << 16),
5675        ie: Some(10 << 16),
5676        ..Browsers::default()
5677      },
5678    );
5679    prefix_test(
5680      r#"
5681      .foo {
5682        -ms-flex-negative: 1;
5683        -webkit-flex-shrink: 1;
5684        flex-shrink: 1;
5685      }
5686    "#,
5687      indoc! {r#"
5688      .foo {
5689        flex-shrink: 1;
5690      }
5691    "#},
5692      Browsers {
5693        safari: Some(11 << 16),
5694        ..Browsers::default()
5695      },
5696    );
5697    prefix_test(
5698      r#"
5699      .foo {
5700        flex-basis: 1px;
5701      }
5702    "#,
5703      indoc! {r#"
5704      .foo {
5705        -ms-flex-preferred-size: 1px;
5706        -webkit-flex-basis: 1px;
5707        flex-basis: 1px;
5708      }
5709    "#},
5710      Browsers {
5711        safari: Some(4 << 16),
5712        firefox: Some(4 << 16),
5713        ie: Some(10 << 16),
5714        ..Browsers::default()
5715      },
5716    );
5717    prefix_test(
5718      r#"
5719      .foo {
5720        -ms-flex-preferred-size: 1px;
5721        -webkit-flex-basis: 1px;
5722        flex-basis: 1px;
5723      }
5724    "#,
5725      indoc! {r#"
5726      .foo {
5727        flex-basis: 1px;
5728      }
5729    "#},
5730      Browsers {
5731        safari: Some(11 << 16),
5732        ..Browsers::default()
5733      },
5734    );
5735    prefix_test(
5736      r#"
5737      .foo {
5738        flex: 1;
5739      }
5740    "#,
5741      indoc! {r#"
5742      .foo {
5743        -webkit-box-flex: 1;
5744        -moz-box-flex: 1;
5745        -webkit-flex: 1;
5746        -ms-flex: 1;
5747        flex: 1;
5748      }
5749    "#},
5750      Browsers {
5751        safari: Some(4 << 16),
5752        firefox: Some(4 << 16),
5753        ie: Some(10 << 16),
5754        ..Browsers::default()
5755      },
5756    );
5757    prefix_test(
5758      r#"
5759      .foo {
5760        -webkit-box-flex: 1;
5761        -moz-box-flex: 1;
5762        -webkit-flex: 1;
5763        -ms-flex: 1;
5764        flex: 1;
5765      }
5766    "#,
5767      indoc! {r#"
5768      .foo {
5769        flex: 1;
5770      }
5771    "#},
5772      Browsers {
5773        safari: Some(11 << 16),
5774        ..Browsers::default()
5775      },
5776    );
5777    prefix_test(
5778      r#"
5779      .foo {
5780        align-content: space-between;
5781      }
5782    "#,
5783      indoc! {r#"
5784      .foo {
5785        -ms-flex-line-pack: justify;
5786        -webkit-align-content: space-between;
5787        align-content: space-between;
5788      }
5789    "#},
5790      Browsers {
5791        safari: Some(4 << 16),
5792        firefox: Some(4 << 16),
5793        ie: Some(10 << 16),
5794        ..Browsers::default()
5795      },
5796    );
5797    prefix_test(
5798      r#"
5799      .foo {
5800        -ms-flex-line-pack: justify;
5801        -webkit-align-content: space-between;
5802        align-content: space-between;
5803      }
5804    "#,
5805      indoc! {r#"
5806      .foo {
5807        align-content: space-between;
5808      }
5809    "#},
5810      Browsers {
5811        safari: Some(11 << 16),
5812        ..Browsers::default()
5813      },
5814    );
5815    prefix_test(
5816      r#"
5817      .foo {
5818        justify-content: space-between;
5819      }
5820    "#,
5821      indoc! {r#"
5822      .foo {
5823        -webkit-box-pack: justify;
5824        -moz-box-pack: justify;
5825        -ms-flex-pack: justify;
5826        -webkit-justify-content: space-between;
5827        justify-content: space-between;
5828      }
5829    "#},
5830      Browsers {
5831        safari: Some(4 << 16),
5832        firefox: Some(4 << 16),
5833        ie: Some(10 << 16),
5834        ..Browsers::default()
5835      },
5836    );
5837    prefix_test(
5838      r#"
5839      .foo {
5840        -webkit-box-pack: justify;
5841        -moz-box-pack: justify;
5842        -ms-flex-pack: justify;
5843        -webkit-justify-content: space-between;
5844        justify-content: space-between;
5845      }
5846    "#,
5847      indoc! {r#"
5848      .foo {
5849        justify-content: space-between;
5850      }
5851    "#},
5852      Browsers {
5853        safari: Some(11 << 16),
5854        ..Browsers::default()
5855      },
5856    );
5857    prefix_test(
5858      r#"
5859      .foo {
5860        place-content: space-between flex-end;
5861      }
5862    "#,
5863      indoc! {r#"
5864      .foo {
5865        -ms-flex-line-pack: justify;
5866        -webkit-box-pack: end;
5867        -moz-box-pack: end;
5868        -ms-flex-pack: end;
5869        -webkit-align-content: space-between;
5870        align-content: space-between;
5871        -webkit-justify-content: flex-end;
5872        justify-content: flex-end;
5873      }
5874    "#},
5875      Browsers {
5876        safari: Some(4 << 16),
5877        firefox: Some(4 << 16),
5878        ie: Some(10 << 16),
5879        ..Browsers::default()
5880      },
5881    );
5882    prefix_test(
5883      r#"
5884      .foo {
5885        -ms-flex-line-pack: justify;
5886        -webkit-box-pack: end;
5887        -moz-box-pack: end;
5888        -ms-flex-pack: end;
5889        -webkit-align-content: space-between;
5890        -webkit-justify-content: flex-end;
5891        place-content: space-between flex-end;
5892      }
5893    "#,
5894      indoc! {r#"
5895      .foo {
5896        place-content: space-between flex-end;
5897      }
5898    "#},
5899      Browsers {
5900        safari: Some(11 << 16),
5901        ..Browsers::default()
5902      },
5903    );
5904    prefix_test(
5905      r#"
5906      .foo {
5907        place-content: space-between flex-end;
5908      }
5909    "#,
5910      indoc! {r#"
5911      .foo {
5912        align-content: space-between;
5913        justify-content: flex-end;
5914      }
5915    "#},
5916      Browsers {
5917        chrome: Some(30 << 16),
5918        ..Browsers::default()
5919      },
5920    );
5921    prefix_test(
5922      r#"
5923      .foo {
5924        place-content: space-between flex-end;
5925      }
5926    "#,
5927      indoc! {r#"
5928      .foo {
5929        place-content: space-between flex-end;
5930      }
5931    "#},
5932      Browsers {
5933        chrome: Some(60 << 16),
5934        ..Browsers::default()
5935      },
5936    );
5937    prefix_test(
5938      r#"
5939      .foo {
5940        align-self: flex-end;
5941      }
5942    "#,
5943      indoc! {r#"
5944      .foo {
5945        -ms-flex-item-align: end;
5946        -webkit-align-self: flex-end;
5947        align-self: flex-end;
5948      }
5949    "#},
5950      Browsers {
5951        safari: Some(4 << 16),
5952        firefox: Some(4 << 16),
5953        ie: Some(10 << 16),
5954        ..Browsers::default()
5955      },
5956    );
5957    prefix_test(
5958      r#"
5959      .foo {
5960        -ms-flex-item-align: end;
5961        -webkit-align-self: flex-end;
5962        align-self: flex-end;
5963      }
5964    "#,
5965      indoc! {r#"
5966      .foo {
5967        align-self: flex-end;
5968      }
5969    "#},
5970      Browsers {
5971        safari: Some(11 << 16),
5972        ..Browsers::default()
5973      },
5974    );
5975    prefix_test(
5976      r#"
5977      .foo {
5978        place-self: center flex-end;
5979      }
5980    "#,
5981      indoc! {r#"
5982      .foo {
5983        -ms-flex-item-align: center;
5984        -webkit-align-self: center;
5985        align-self: center;
5986        justify-self: flex-end;
5987      }
5988    "#},
5989      Browsers {
5990        safari: Some(4 << 16),
5991        firefox: Some(4 << 16),
5992        ie: Some(10 << 16),
5993        ..Browsers::default()
5994      },
5995    );
5996    prefix_test(
5997      r#"
5998      .foo {
5999        -ms-flex-item-align: center;
6000        -webkit-align-self: center;
6001        place-self: center flex-end;
6002      }
6003    "#,
6004      indoc! {r#"
6005      .foo {
6006        place-self: center flex-end;
6007      }
6008    "#},
6009      Browsers {
6010        safari: Some(11 << 16),
6011        ..Browsers::default()
6012      },
6013    );
6014    prefix_test(
6015      r#"
6016      .foo {
6017        place-self: center flex-end;
6018      }
6019    "#,
6020      indoc! {r#"
6021      .foo {
6022        align-self: center;
6023        justify-self: flex-end;
6024      }
6025    "#},
6026      Browsers {
6027        chrome: Some(57 << 16),
6028        ..Browsers::default()
6029      },
6030    );
6031    prefix_test(
6032      r#"
6033      .foo {
6034        place-self: center flex-end;
6035      }
6036    "#,
6037      indoc! {r#"
6038      .foo {
6039        place-self: center flex-end;
6040      }
6041    "#},
6042      Browsers {
6043        chrome: Some(59 << 16),
6044        ..Browsers::default()
6045      },
6046    );
6047    prefix_test(
6048      r#"
6049      .foo {
6050        align-items: flex-end;
6051      }
6052    "#,
6053      indoc! {r#"
6054      .foo {
6055        -webkit-box-align: end;
6056        -moz-box-align: end;
6057        -ms-flex-align: end;
6058        -webkit-align-items: flex-end;
6059        align-items: flex-end;
6060      }
6061    "#},
6062      Browsers {
6063        safari: Some(4 << 16),
6064        firefox: Some(4 << 16),
6065        ie: Some(10 << 16),
6066        ..Browsers::default()
6067      },
6068    );
6069    prefix_test(
6070      r#"
6071      .foo {
6072        -webkit-box-align: end;
6073        -moz-box-align: end;
6074        -ms-flex-align: end;
6075        -webkit-align-items: flex-end;
6076        align-items: flex-end;
6077      }
6078    "#,
6079      indoc! {r#"
6080      .foo {
6081        align-items: flex-end;
6082      }
6083    "#},
6084      Browsers {
6085        safari: Some(11 << 16),
6086        ..Browsers::default()
6087      },
6088    );
6089    prefix_test(
6090      r#"
6091      .foo {
6092        place-items: flex-end center;
6093      }
6094    "#,
6095      indoc! {r#"
6096      .foo {
6097        -webkit-box-align: end;
6098        -moz-box-align: end;
6099        -ms-flex-align: end;
6100        -webkit-align-items: flex-end;
6101        align-items: flex-end;
6102        justify-items: center;
6103      }
6104    "#},
6105      Browsers {
6106        safari: Some(4 << 16),
6107        firefox: Some(4 << 16),
6108        ie: Some(10 << 16),
6109        ..Browsers::default()
6110      },
6111    );
6112    prefix_test(
6113      r#"
6114      .foo {
6115        -webkit-box-align: end;
6116        -moz-box-align: end;
6117        -ms-flex-align: end;
6118        -webkit-align-items: flex-end;
6119        place-items: flex-end center;
6120      }
6121    "#,
6122      indoc! {r#"
6123      .foo {
6124        place-items: flex-end center;
6125      }
6126    "#},
6127      Browsers {
6128        safari: Some(11 << 16),
6129        ..Browsers::default()
6130      },
6131    );
6132    prefix_test(
6133      r#"
6134      .foo {
6135        place-items: flex-end center;
6136      }
6137    "#,
6138      indoc! {r#"
6139      .foo {
6140        align-items: flex-end;
6141        justify-items: center;
6142      }
6143    "#},
6144      Browsers {
6145        safari: Some(10 << 16),
6146        ..Browsers::default()
6147      },
6148    );
6149    prefix_test(
6150      r#"
6151      .foo {
6152        order: 1;
6153      }
6154    "#,
6155      indoc! {r#"
6156      .foo {
6157        -webkit-box-ordinal-group: 1;
6158        -moz-box-ordinal-group: 1;
6159        -ms-flex-order: 1;
6160        -webkit-order: 1;
6161        order: 1;
6162      }
6163    "#},
6164      Browsers {
6165        safari: Some(4 << 16),
6166        firefox: Some(4 << 16),
6167        ie: Some(10 << 16),
6168        ..Browsers::default()
6169      },
6170    );
6171    prefix_test(
6172      r#"
6173      .foo {
6174        -webkit-box-ordinal-group: 1;
6175        -moz-box-ordinal-group: 1;
6176        -ms-flex-order: 1;
6177        -webkit-order: 1;
6178        order: 1;
6179      }
6180    "#,
6181      indoc! {r#"
6182      .foo {
6183        order: 1;
6184      }
6185    "#},
6186      Browsers {
6187        safari: Some(11 << 16),
6188        ..Browsers::default()
6189      },
6190    );
6191    prefix_test(
6192      r#"
6193      .foo {
6194        -ms-flex: 0 0 8%;
6195        flex: 0 0 5%;
6196      }
6197    "#,
6198      indoc! {r#"
6199      .foo {
6200        -ms-flex: 0 0 8%;
6201        flex: 0 0 5%;
6202      }
6203    "#},
6204      Browsers {
6205        safari: Some(11 << 16),
6206        ..Browsers::default()
6207      },
6208    );
6209  }
6210
6211  #[test]
6212  fn test_font() {
6213    test(
6214      r#"
6215      .foo {
6216        font-family: "Helvetica", "Times New Roman", sans-serif;
6217        font-size: 12px;
6218        font-weight: bold;
6219        font-style: italic;
6220        font-stretch: expanded;
6221        font-variant-caps: small-caps;
6222        line-height: 1.2em;
6223      }
6224    "#,
6225      indoc! {r#"
6226      .foo {
6227        font: italic small-caps bold expanded 12px / 1.2em Helvetica, Times New Roman, sans-serif;
6228      }
6229    "#
6230      },
6231    );
6232
6233    minify_test(
6234      r#"
6235      .foo {
6236        font-family: "Helvetica", "Times New Roman", sans-serif;
6237        font-size: 12px;
6238        font-weight: bold;
6239        font-style: italic;
6240        font-stretch: expanded;
6241        font-variant-caps: small-caps;
6242        line-height: 1.2em;
6243      }
6244    "#,
6245      indoc! {".foo{font:italic small-caps 700 125% 12px/1.2em Helvetica,Times New Roman,sans-serif}"
6246      },
6247    );
6248
6249    test(
6250      r#"
6251      .foo {
6252        font: 12px "Helvetica", "Times New Roman", sans-serif;
6253        line-height: 1.2em;
6254      }
6255    "#,
6256      indoc! {r#"
6257      .foo {
6258        font: 12px / 1.2em Helvetica, Times New Roman, sans-serif;
6259      }
6260    "#
6261      },
6262    );
6263
6264    test(
6265      r#"
6266      .foo {
6267        font: 12px "Helvetica", "Times New Roman", sans-serif;
6268        line-height: var(--lh);
6269      }
6270    "#,
6271      indoc! {r#"
6272      .foo {
6273        font: 12px Helvetica, Times New Roman, sans-serif;
6274        line-height: var(--lh);
6275      }
6276    "#
6277      },
6278    );
6279
6280    minify_test(
6281      r#"
6282      .foo {
6283        font-family: "Helvetica", "Times New Roman", sans-serif;
6284        font-size: 12px;
6285        font-stretch: expanded;
6286      }
6287    "#,
6288      indoc! {".foo{font-family:Helvetica,Times New Roman,sans-serif;font-size:12px;font-stretch:125%}"
6289      },
6290    );
6291
6292    test(
6293      r#"
6294      .foo {
6295        font-family: "Helvetica", "Times New Roman", sans-serif;
6296        font-size: 12px;
6297        font-weight: bold;
6298        font-style: italic;
6299        font-stretch: expanded;
6300        font-variant-caps: all-small-caps;
6301        line-height: 1.2em;
6302      }
6303    "#,
6304      indoc! {r#"
6305      .foo {
6306        font: italic bold expanded 12px / 1.2em Helvetica, Times New Roman, sans-serif;
6307        font-variant-caps: all-small-caps;
6308      }
6309    "#
6310      },
6311    );
6312
6313    minify_test(
6314      ".foo { font: normal normal 600 9px/normal Charcoal; }",
6315      ".foo{font:600 9px Charcoal}",
6316    );
6317    minify_test(
6318      ".foo { font: normal normal 500 medium/normal Charcoal; }",
6319      ".foo{font:500 medium Charcoal}",
6320    );
6321    minify_test(
6322      ".foo { font: normal normal 400 medium Charcoal; }",
6323      ".foo{font:400 medium Charcoal}",
6324    );
6325    minify_test(
6326      ".foo { font: normal normal 500 medium/10px Charcoal; }",
6327      ".foo{font:500 medium/10px Charcoal}",
6328    );
6329    minify_test(
6330      ".foo { font-family: 'sans-serif'; }",
6331      ".foo{font-family:\"sans-serif\"}",
6332    );
6333    minify_test(".foo { font-family: sans-serif; }", ".foo{font-family:sans-serif}");
6334    minify_test(".foo { font-family: 'default'; }", ".foo{font-family:\"default\"}");
6335    minify_test(".foo { font-family: default; }", ".foo{font-family:default}");
6336    minify_test(".foo { font-family: 'inherit'; }", ".foo{font-family:\"inherit\"}");
6337    minify_test(".foo { font-family: inherit; }", ".foo{font-family:inherit}");
6338    minify_test(".foo { font-family: inherit test; }", ".foo{font-family:inherit test}");
6339    minify_test(
6340      ".foo { font-family: 'inherit test'; }",
6341      ".foo{font-family:inherit test}",
6342    );
6343    minify_test(".foo { font-family: revert; }", ".foo{font-family:revert}");
6344    minify_test(".foo { font-family: 'revert'; }", ".foo{font-family:\"revert\"}");
6345    minify_test(".foo { font-family: revert-layer; }", ".foo{font-family:revert-layer}");
6346    minify_test(
6347      ".foo { font-family: revert-layer, serif; }",
6348      ".foo{font-family:revert-layer,serif}",
6349    );
6350    minify_test(
6351      ".foo { font-family: 'revert', sans-serif; }",
6352      ".foo{font-family:\"revert\",sans-serif}",
6353    );
6354    minify_test(
6355      ".foo { font-family: 'revert', foo, sans-serif; }",
6356      ".foo{font-family:\"revert\",foo,sans-serif}",
6357    );
6358    minify_test(".foo { font-family: ''; }", ".foo{font-family:\"\"}");
6359
6360    // font-family in @font-face
6361    minify_test(
6362      "@font-face { font-family: 'revert'; }",
6363      "@font-face{font-family:\"revert\"}",
6364    );
6365    minify_test(
6366      "@font-face { font-family: 'revert-layer'; }",
6367      "@font-face{font-family:\"revert-layer\"}",
6368    );
6369
6370    prefix_test(
6371      r#"
6372      .foo {
6373        font-family: Helvetica, system-ui, sans-serif;
6374      }
6375    "#,
6376      indoc! {r#"
6377      .foo {
6378        font-family: Helvetica, system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Noto Sans, Ubuntu, Cantarell, Helvetica Neue, sans-serif;
6379      }
6380    "#
6381      },
6382      Browsers {
6383        safari: Some(8 << 16),
6384        ..Browsers::default()
6385      },
6386    );
6387
6388    prefix_test(
6389      r#"
6390      .foo {
6391        font: 100%/1.5 Helvetica, system-ui, sans-serif;
6392      }
6393    "#,
6394      indoc! {r#"
6395      .foo {
6396        font: 100% / 1.5 Helvetica, system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Noto Sans, Ubuntu, Cantarell, Helvetica Neue, sans-serif;
6397      }
6398    "#
6399      },
6400      Browsers {
6401        safari: Some(8 << 16),
6402        ..Browsers::default()
6403      },
6404    );
6405
6406    prefix_test(
6407      r#"
6408      .foo {
6409        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";
6410      }
6411    "#,
6412      indoc! {r#"
6413      .foo {
6414        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;
6415      }
6416    "#
6417      },
6418      Browsers {
6419        firefox: Some(91 << 16),
6420        ..Browsers::default()
6421      },
6422    );
6423
6424    prefix_test(
6425      r#"
6426      .foo {
6427        font-size: 22px;
6428        font-size: max(2cqw, 22px);
6429      }
6430    "#,
6431      indoc! {r#"
6432      .foo {
6433        font-size: 22px;
6434        font-size: max(2cqw, 22px);
6435      }
6436    "#
6437      },
6438      Browsers {
6439        safari: Some(14 << 16),
6440        ..Browsers::default()
6441      },
6442    );
6443    prefix_test(
6444      r#"
6445      .foo {
6446        font-size: 22px;
6447        font-size: max(2cqw, 22px);
6448      }
6449    "#,
6450      indoc! {r#"
6451      .foo {
6452        font-size: max(2cqw, 22px);
6453      }
6454    "#
6455      },
6456      Browsers {
6457        safari: Some(16 << 16),
6458        ..Browsers::default()
6459      },
6460    );
6461
6462    prefix_test(
6463      r#"
6464      .foo {
6465        font-size: 22px;
6466        font-size: xxx-large;
6467      }
6468    "#,
6469      indoc! {r#"
6470      .foo {
6471        font-size: 22px;
6472        font-size: xxx-large;
6473      }
6474    "#
6475      },
6476      Browsers {
6477        chrome: Some(70 << 16),
6478        ..Browsers::default()
6479      },
6480    );
6481    prefix_test(
6482      r#"
6483      .foo {
6484        font-size: 22px;
6485        font-size: xxx-large;
6486      }
6487    "#,
6488      indoc! {r#"
6489      .foo {
6490        font-size: xxx-large;
6491      }
6492    "#
6493      },
6494      Browsers {
6495        chrome: Some(80 << 16),
6496        ..Browsers::default()
6497      },
6498    );
6499
6500    prefix_test(
6501      r#"
6502      .foo {
6503        font-weight: 700;
6504        font-weight: 789;
6505      }
6506    "#,
6507      indoc! {r#"
6508      .foo {
6509        font-weight: 700;
6510        font-weight: 789;
6511      }
6512    "#
6513      },
6514      Browsers {
6515        chrome: Some(60 << 16),
6516        ..Browsers::default()
6517      },
6518    );
6519    prefix_test(
6520      r#"
6521      .foo {
6522        font-weight: 700;
6523        font-weight: 789;
6524      }
6525    "#,
6526      indoc! {r#"
6527      .foo {
6528        font-weight: 789;
6529      }
6530    "#
6531      },
6532      Browsers {
6533        chrome: Some(80 << 16),
6534        ..Browsers::default()
6535      },
6536    );
6537
6538    prefix_test(
6539      r#"
6540      .foo {
6541        font-family: Helvetica;
6542        font-family: system-ui;
6543      }
6544    "#,
6545      indoc! {r#"
6546      .foo {
6547        font-family: Helvetica;
6548        font-family: system-ui;
6549      }
6550    "#
6551      },
6552      Browsers {
6553        chrome: Some(50 << 16),
6554        ..Browsers::default()
6555      },
6556    );
6557    prefix_test(
6558      r#"
6559      .foo {
6560        font-family: Helvetica;
6561        font-family: system-ui;
6562      }
6563    "#,
6564      indoc! {r#"
6565      .foo {
6566        font-family: system-ui;
6567      }
6568    "#
6569      },
6570      Browsers {
6571        chrome: Some(80 << 16),
6572        ..Browsers::default()
6573      },
6574    );
6575
6576    prefix_test(
6577      r#"
6578      .foo {
6579        font-style: oblique;
6580        font-style: oblique 40deg;
6581      }
6582    "#,
6583      indoc! {r#"
6584      .foo {
6585        font-style: oblique;
6586        font-style: oblique 40deg;
6587      }
6588    "#
6589      },
6590      Browsers {
6591        firefox: Some(50 << 16),
6592        ..Browsers::default()
6593      },
6594    );
6595    prefix_test(
6596      r#"
6597      .foo {
6598        font-style: oblique;
6599        font-style: oblique 40deg;
6600      }
6601    "#,
6602      indoc! {r#"
6603      .foo {
6604        font-style: oblique 40deg;
6605      }
6606    "#
6607      },
6608      Browsers {
6609        firefox: Some(80 << 16),
6610        ..Browsers::default()
6611      },
6612    );
6613
6614    prefix_test(
6615      r#"
6616      .foo {
6617        font: 22px Helvetica;
6618        font: xxx-large system-ui;
6619      }
6620    "#,
6621      indoc! {r#"
6622      .foo {
6623        font: 22px Helvetica;
6624        font: xxx-large system-ui;
6625      }
6626    "#
6627      },
6628      Browsers {
6629        chrome: Some(70 << 16),
6630        ..Browsers::default()
6631      },
6632    );
6633    prefix_test(
6634      r#"
6635      .foo {
6636        font: 22px Helvetica;
6637        font: xxx-large system-ui;
6638      }
6639    "#,
6640      indoc! {r#"
6641      .foo {
6642        font: xxx-large system-ui;
6643      }
6644    "#
6645      },
6646      Browsers {
6647        chrome: Some(80 << 16),
6648        ..Browsers::default()
6649      },
6650    );
6651
6652    prefix_test(
6653      r#"
6654      .foo {
6655        font: var(--fallback);
6656        font: xxx-large system-ui;
6657      }
6658    "#,
6659      indoc! {r#"
6660      .foo {
6661        font: var(--fallback);
6662        font: xxx-large system-ui;
6663      }
6664    "#
6665      },
6666      Browsers {
6667        chrome: Some(50 << 16),
6668        ..Browsers::default()
6669      },
6670    );
6671  }
6672
6673  #[test]
6674  fn test_vertical_align() {
6675    minify_test(".foo { vertical-align: middle }", ".foo{vertical-align:middle}");
6676    minify_test(".foo { vertical-align: 0.3em }", ".foo{vertical-align:.3em}");
6677  }
6678
6679  #[test]
6680  fn test_selectors() {
6681    minify_test(":nth-col(2n) {width: 20px}", ":nth-col(2n){width:20px}");
6682    minify_test(":nth-col(10n-1) {width: 20px}", ":nth-col(10n-1){width:20px}");
6683    minify_test(":nth-col(-n+2) {width: 20px}", ":nth-col(-n+2){width:20px}");
6684    minify_test(":nth-col(even) {width: 20px}", ":nth-col(2n){width:20px}");
6685    minify_test(":nth-col(odd) {width: 20px}", ":nth-col(odd){width:20px}");
6686    minify_test(":nth-last-col(2n) {width: 20px}", ":nth-last-col(2n){width:20px}");
6687    minify_test(":nth-last-col(10n-1) {width: 20px}", ":nth-last-col(10n-1){width:20px}");
6688    minify_test(":nth-last-col(-n+2) {width: 20px}", ":nth-last-col(-n+2){width:20px}");
6689    minify_test(":nth-last-col(even) {width: 20px}", ":nth-last-col(2n){width:20px}");
6690    minify_test(":nth-last-col(odd) {width: 20px}", ":nth-last-col(odd){width:20px}");
6691    minify_test(":nth-child(odd) {width: 20px}", ":nth-child(odd){width:20px}");
6692    minify_test(":nth-child(2n) {width: 20px}", ":nth-child(2n){width:20px}");
6693    minify_test(":nth-child(2n+1) {width: 20px}", ":nth-child(odd){width:20px}");
6694    minify_test(":first-child {width: 20px}", ":first-child{width:20px}");
6695    minify_test(":nth-child(1) {width: 20px}", ":first-child{width:20px}");
6696    minify_test(":nth-last-child(1) {width: 20px}", ":last-child{width:20px}");
6697    minify_test(":nth-of-type(1) {width: 20px}", ":first-of-type{width:20px}");
6698    minify_test(":nth-last-of-type(1) {width: 20px}", ":last-of-type{width:20px}");
6699    minify_test(
6700      ":nth-child(even of li.important) {width: 20px}",
6701      ":nth-child(2n of li.important){width:20px}",
6702    );
6703    minify_test(
6704      ":nth-child(1 of li.important) {width: 20px}",
6705      ":nth-child(1 of li.important){width:20px}",
6706    );
6707    minify_test(
6708      ":nth-last-child(even of li.important) {width: 20px}",
6709      ":nth-last-child(2n of li.important){width:20px}",
6710    );
6711    minify_test(
6712      ":nth-last-child(1 of li.important) {width: 20px}",
6713      ":nth-last-child(1 of li.important){width:20px}",
6714    );
6715    minify_test(
6716      ":nth-last-child(1 of.important) {width: 20px}",
6717      ":nth-last-child(1 of .important){width:20px}",
6718    );
6719
6720    minify_test("[foo=\"baz\"] {color:red}", "[foo=baz]{color:red}");
6721    minify_test("[foo=\"foo bar\"] {color:red}", "[foo=foo\\ bar]{color:red}");
6722    minify_test("[foo=\"foo bar baz\"] {color:red}", "[foo=\"foo bar baz\"]{color:red}");
6723    minify_test("[foo=\"\"] {color:red}", "[foo=\"\"]{color:red}");
6724    minify_test(
6725      ".test:not([foo=\"bar\"]) {color:red}",
6726      ".test:not([foo=bar]){color:red}",
6727    );
6728    minify_test(".test + .foo {color:red}", ".test+.foo{color:red}");
6729    minify_test(".test ~ .foo {color:red}", ".test~.foo{color:red}");
6730    minify_test(".test .foo {color:red}", ".test .foo{color:red}");
6731    minify_test(
6732      ".custom-range::-webkit-slider-thumb:active {color:red}",
6733      ".custom-range::-webkit-slider-thumb:active{color:red}",
6734    );
6735    minify_test(".test:not(.foo, .bar) {color:red}", ".test:not(.foo,.bar){color:red}");
6736    minify_test(".test:is(.foo, .bar) {color:red}", ".test:is(.foo,.bar){color:red}");
6737    minify_test(
6738      ".test:where(.foo, .bar) {color:red}",
6739      ".test:where(.foo,.bar){color:red}",
6740    );
6741    minify_test(
6742      ".test:where(.foo, .bar) {color:red}",
6743      ".test:where(.foo,.bar){color:red}",
6744    );
6745
6746    // Test scroll navigation controls pseudo-classes
6747    let scroll_navigation_controls_options = ParserOptions {
6748      flags: ParserFlags::SCROLL_NAVIGATION_CONTROLS,
6749      ..ParserOptions::default()
6750    };
6751    minify_test_with_options(
6752      "a:target-current { color: green }",
6753      "a:target-current{color:green}",
6754      scroll_navigation_controls_options.clone(),
6755    );
6756    minify_test_with_options(
6757      "a:target-before { color: green }",
6758      "a:target-before{color:green}",
6759      scroll_navigation_controls_options.clone(),
6760    );
6761    minify_test_with_options(
6762      "a:target-after { color: green }",
6763      "a:target-after{color:green}",
6764      scroll_navigation_controls_options.clone(),
6765    );
6766    minify_test_with_options(
6767      ":is(a:target-before, a:target-after) { color: green }",
6768      ":is(a:target-before,a:target-after){color:green}",
6769      scroll_navigation_controls_options.clone(),
6770    );
6771    minify_test_with_options(
6772      "a:where(:target-before, :target-after) { color: green }",
6773      "a:where(:target-before,:target-after){color:green}",
6774      scroll_navigation_controls_options.clone(),
6775    );
6776    // If the browser does not support it, it will output the `:is()` selector.
6777    minify_test_with_options_and_browsers(
6778      "a:target-before, a:target-after { color: green }",
6779      ":is(a:target-before,a:target-after){color:green}",
6780      scroll_navigation_controls_options.clone(),
6781      Some(Browsers {
6782        chrome: Some(130 << 16),
6783        ..Browsers::default()
6784      }),
6785    );
6786    minify_test_with_options_and_browsers(
6787      "a:target-before, a:target-after { color: green }",
6788      "a:target-before,a:target-after{color:green}",
6789      scroll_navigation_controls_options.clone(),
6790      Some(Browsers {
6791        chrome: Some(150 << 16),
6792        ..Browsers::default()
6793      }),
6794    );
6795
6796    error_test_with_options(
6797      "a::before:target-current { color: green }",
6798      ParserError::SelectorError(SelectorError::InvalidPseudoClassAfterPseudoElement),
6799      ParserOptions {
6800        flags: ParserFlags::SCROLL_NAVIGATION_CONTROLS,
6801        ..ParserOptions::default()
6802      },
6803    );
6804
6805    let warnings = Some(Arc::new(RwLock::new(Vec::new())));
6806    let _ = StyleSheet::parse(
6807      "a:target-current { color: green }",
6808      ParserOptions {
6809        warnings: warnings.clone(),
6810        ..ParserOptions::default()
6811      },
6812    )
6813    .unwrap();
6814    let warnings = Arc::try_unwrap(warnings.unwrap()).unwrap().into_inner().unwrap();
6815    assert_eq!(warnings.len(), 1);
6816    assert_eq!(
6817      warnings[0].kind,
6818      ParserError::SelectorError(SelectorError::UnsupportedPseudoClass("target-current".into()))
6819    );
6820
6821    minify_test(":host {color:red}", ":host{color:red}");
6822    minify_test(":host(.foo) {color:red}", ":host(.foo){color:red}");
6823    minify_test("::slotted(span) {color:red", "::slotted(span){color:red}");
6824    minify_test(
6825      "custom-element::part(foo) {color:red}",
6826      "custom-element::part(foo){color:red}",
6827    );
6828    minify_test(".sm\\:text-5xl { font-size: 3rem }", ".sm\\:text-5xl{font-size:3rem}");
6829    minify_test("a:has(> img) {color:red}", "a:has(>img){color:red}");
6830    minify_test("dt:has(+ dt) {color:red}", "dt:has(+dt){color:red}");
6831    minify_test(
6832      "section:not(:has(h1, h2, h3, h4, h5, h6)) {color:red}",
6833      "section:not(:has(h1,h2,h3,h4,h5,h6)){color:red}",
6834    );
6835    minify_test(
6836      ":has(.sibling ~ .target) {color:red}",
6837      ":has(.sibling~.target){color:red}",
6838    );
6839    minify_test(".x:has(> .a > .b) {color:red}", ".x:has(>.a>.b){color:red}");
6840    minify_test(".x:has(.bar, #foo) {color:red}", ".x:has(.bar,#foo){color:red}");
6841    minify_test(".x:has(span + span) {color:red}", ".x:has(span+span){color:red}");
6842    minify_test("a:has(:visited) {color:red}", "a:has(:visited){color:red}");
6843    for element in [
6844      "-webkit-scrollbar",
6845      "-webkit-scrollbar-button",
6846      "-webkit-scrollbar-track",
6847      "-webkit-scrollbar-track-piece",
6848      "-webkit-scrollbar-thumb",
6849      "-webkit-scrollbar-corner",
6850      "-webkit-resizer",
6851    ] {
6852      for class in [
6853        "enabled",
6854        "disabled",
6855        "hover",
6856        "active",
6857        "horizontal",
6858        "vertical",
6859        "decrement",
6860        "increment",
6861        "start",
6862        "end",
6863        "double-button",
6864        "single-button",
6865        "no-button",
6866        "corner-present",
6867        "window-inactive",
6868      ] {
6869        minify_test(
6870          &format!("::{}:{} {{color:red}}", element, class),
6871          &format!("::{}:{}{{color:red}}", element, class),
6872        );
6873      }
6874    }
6875    for class in [
6876      "horizontal",
6877      "vertical",
6878      "decrement",
6879      "increment",
6880      "start",
6881      "end",
6882      "double-button",
6883      "single-button",
6884      "no-button",
6885      "corner-present",
6886      "window-inactive",
6887    ] {
6888      error_test(
6889        &format!(":{} {{color:red}}", class),
6890        ParserError::SelectorError(SelectorError::InvalidPseudoClassBeforeWebKitScrollbar),
6891      );
6892    }
6893    for element in [
6894      "-webkit-scrollbar",
6895      "-webkit-scrollbar-button",
6896      "-webkit-scrollbar-track",
6897      "-webkit-scrollbar-track-piece",
6898      "-webkit-scrollbar-thumb",
6899      "-webkit-scrollbar-corner",
6900      "-webkit-resizer",
6901    ] {
6902      error_test(
6903        &format!("::{}:focus {{color:red}}", element),
6904        ParserError::SelectorError(SelectorError::InvalidPseudoClassAfterWebKitScrollbar),
6905      );
6906    }
6907
6908    error_test(
6909      "a::first-letter:last-child {color:red}",
6910      ParserError::SelectorError(SelectorError::InvalidPseudoClassAfterPseudoElement),
6911    );
6912    minify_test(
6913      "a:last-child::first-letter {color:red}",
6914      "a:last-child:first-letter{color:red}",
6915    );
6916
6917    prefix_test(
6918      ".test:not(.foo, .bar) {color:red}",
6919      indoc! {r#"
6920      .test:not(:-webkit-any(.foo, .bar)) {
6921        color: red;
6922      }
6923
6924      .test:not(:is(.foo, .bar)) {
6925        color: red;
6926      }
6927      "#},
6928      Browsers {
6929        safari: Some(8 << 16),
6930        ..Browsers::default()
6931      },
6932    );
6933    prefix_test(
6934      ".test:not(.foo, .bar) {color:red}",
6935      indoc! {r#"
6936      .test:not(.foo, .bar) {
6937        color: red;
6938      }
6939      "#},
6940      Browsers {
6941        safari: Some(11 << 16),
6942        ..Browsers::default()
6943      },
6944    );
6945
6946    minify_test("a:lang(en) {color:red}", "a:lang(en){color:red}");
6947    minify_test("a:lang(en, fr) {color:red}", "a:lang(en,fr){color:red}");
6948    minify_test("a:lang('en') {color:red}", "a:lang(en){color:red}");
6949    minify_test(
6950      "a:-webkit-any(.foo, .bar) {color:red}",
6951      "a:-webkit-any(.foo,.bar){color:red}",
6952    );
6953    minify_test("a:-moz-any(.foo, .bar) {color:red}", "a:-moz-any(.foo,.bar){color:red}");
6954
6955    prefix_test(
6956      "a:is(.foo, .bar) {color:red}",
6957      indoc! {r#"
6958      a:-webkit-any(.foo, .bar) {
6959        color: red;
6960      }
6961
6962      a:-moz-any(.foo, .bar) {
6963        color: red;
6964      }
6965
6966      a:is(.foo, .bar) {
6967        color: red;
6968      }
6969      "#},
6970      Browsers {
6971        safari: Some(11 << 16),
6972        firefox: Some(50 << 16),
6973        ..Browsers::default()
6974      },
6975    );
6976
6977    prefix_test(
6978      "a:is(.foo > .bar) {color:red}",
6979      indoc! {r#"
6980      a:is(.foo > .bar) {
6981        color: red;
6982      }
6983      "#},
6984      Browsers {
6985        safari: Some(11 << 16),
6986        firefox: Some(50 << 16),
6987        ..Browsers::default()
6988      },
6989    );
6990
6991    prefix_test(
6992      "a:lang(en, fr) {color:red}",
6993      indoc! {r#"
6994      a:-webkit-any(:lang(en), :lang(fr)) {
6995        color: red;
6996      }
6997
6998      a:-moz-any(:lang(en), :lang(fr)) {
6999        color: red;
7000      }
7001
7002      a:is(:lang(en), :lang(fr)) {
7003        color: red;
7004      }
7005      "#},
7006      Browsers {
7007        safari: Some(11 << 16),
7008        firefox: Some(50 << 16),
7009        ..Browsers::default()
7010      },
7011    );
7012
7013    prefix_test(
7014      "a:lang(en, fr) {color:red}",
7015      indoc! {r#"
7016      a:is(:lang(en), :lang(fr)) {
7017        color: red;
7018      }
7019      "#},
7020      Browsers {
7021        safari: Some(14 << 16),
7022        firefox: Some(88 << 16),
7023        ..Browsers::default()
7024      },
7025    );
7026
7027    prefix_test(
7028      "a:lang(en, fr) {color:red}",
7029      indoc! {r#"
7030      a:lang(en, fr) {
7031        color: red;
7032      }
7033      "#},
7034      Browsers {
7035        safari: Some(14 << 16),
7036        ..Browsers::default()
7037      },
7038    );
7039
7040    prefix_test(
7041      "a:dir(rtl) {color:red}",
7042      indoc! {r#"
7043      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)) {
7044        color: red;
7045      }
7046
7047      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)) {
7048        color: red;
7049      }
7050
7051      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)) {
7052        color: red;
7053      }
7054      "#},
7055      Browsers {
7056        safari: Some(11 << 16),
7057        firefox: Some(50 << 16),
7058        ..Browsers::default()
7059      },
7060    );
7061
7062    prefix_test(
7063      "a:dir(ltr) {color:red}",
7064      indoc! {r#"
7065      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))) {
7066        color: red;
7067      }
7068
7069      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))) {
7070        color: red;
7071      }
7072
7073      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))) {
7074        color: red;
7075      }
7076      "#},
7077      Browsers {
7078        safari: Some(11 << 16),
7079        firefox: Some(50 << 16),
7080        ..Browsers::default()
7081      },
7082    );
7083
7084    prefix_test(
7085      "a:dir(rtl) {color:red}",
7086      indoc! {r#"
7087      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)) {
7088        color: red;
7089      }
7090      "#},
7091      Browsers {
7092        safari: Some(14 << 16),
7093        firefox: Some(88 << 16),
7094        ..Browsers::default()
7095      },
7096    );
7097
7098    prefix_test(
7099      "a:dir(ltr) {color:red}",
7100      indoc! {r#"
7101      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)) {
7102        color: red;
7103      }
7104      "#},
7105      Browsers {
7106        safari: Some(14 << 16),
7107        firefox: Some(88 << 16),
7108        ..Browsers::default()
7109      },
7110    );
7111
7112    prefix_test(
7113      "a:dir(rtl) {color:red}",
7114      indoc! {r#"
7115      a:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) {
7116        color: red;
7117      }
7118      "#},
7119      Browsers {
7120        safari: Some(14 << 16),
7121        ..Browsers::default()
7122      },
7123    );
7124
7125    prefix_test(
7126      "a:dir(ltr) {color:red}",
7127      indoc! {r#"
7128      a:not(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
7129        color: red;
7130      }
7131      "#},
7132      Browsers {
7133        safari: Some(14 << 16),
7134        ..Browsers::default()
7135      },
7136    );
7137
7138    prefix_test(
7139      "a:is(:dir(rtl)) {color:red}",
7140      indoc! {r#"
7141      a:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) {
7142        color: red;
7143      }
7144      "#},
7145      Browsers {
7146        safari: Some(14 << 16),
7147        ..Browsers::default()
7148      },
7149    );
7150
7151    prefix_test(
7152      "a:where(:dir(rtl)) {color:red}",
7153      indoc! {r#"
7154      a:where(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
7155        color: red;
7156      }
7157      "#},
7158      Browsers {
7159        safari: Some(14 << 16),
7160        ..Browsers::default()
7161      },
7162    );
7163
7164    prefix_test(
7165      "a:has(:dir(rtl)) {color:red}",
7166      indoc! {r#"
7167      a:has(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
7168        color: red;
7169      }
7170      "#},
7171      Browsers {
7172        safari: Some(14 << 16),
7173        ..Browsers::default()
7174      },
7175    );
7176
7177    prefix_test(
7178      "a:not(:dir(rtl)) {color:red}",
7179      indoc! {r#"
7180      a:not(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
7181        color: red;
7182      }
7183      "#},
7184      Browsers {
7185        safari: Some(14 << 16),
7186        ..Browsers::default()
7187      },
7188    );
7189
7190    prefix_test(
7191      "a:dir(rtl)::after {color:red}",
7192      indoc! {r#"
7193      a:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi):after {
7194        color: red;
7195      }
7196      "#},
7197      Browsers {
7198        safari: Some(14 << 16),
7199        ..Browsers::default()
7200      },
7201    );
7202
7203    prefix_test(
7204      "a:dir(rtl) div {color:red}",
7205      indoc! {r#"
7206      a:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) div {
7207        color: red;
7208      }
7209      "#},
7210      Browsers {
7211        safari: Some(14 << 16),
7212        ..Browsers::default()
7213      },
7214    );
7215
7216    minify_test(".foo::cue {color: red}", ".foo::cue{color:red}");
7217    minify_test(".foo::cue-region {color: red}", ".foo::cue-region{color:red}");
7218    minify_test(".foo::cue(b) {color: red}", ".foo::cue(b){color:red}");
7219    minify_test(".foo::cue-region(b) {color: red}", ".foo::cue-region(b){color:red}");
7220    minify_test(
7221      "::cue(v[voice='active']) {color: yellow;}",
7222      "::cue(v[voice=active]){color:#ff0}",
7223    );
7224    minify_test(":foo(bar) { color: yellow }", ":foo(bar){color:#ff0}");
7225    minify_test("::foo(bar) { color: yellow }", "::foo(bar){color:#ff0}");
7226    minify_test("::foo(*) { color: yellow }", "::foo(*){color:#ff0}");
7227
7228    minify_test(":is(.foo) { color: yellow }", ".foo{color:#ff0}");
7229    minify_test(":is(#foo) { color: yellow }", "#foo{color:#ff0}");
7230    minify_test("a:is(.foo) { color: yellow }", "a.foo{color:#ff0}");
7231    minify_test("a:is([data-test]) { color: yellow }", "a[data-test]{color:#ff0}");
7232    minify_test(".foo:is(a) { color: yellow }", ".foo:is(a){color:#ff0}");
7233    minify_test(".foo:is(*|a) { color: yellow }", ".foo:is(*|a){color:#ff0}");
7234    minify_test(".foo:is(*) { color: yellow }", ".foo:is(*){color:#ff0}");
7235    minify_test(
7236      "@namespace svg url(http://www.w3.org/2000/svg); .foo:is(svg|a) { color: yellow }",
7237      "@namespace svg \"http://www.w3.org/2000/svg\";.foo:is(svg|a){color:#ff0}",
7238    );
7239    minify_test("a:is(.foo .bar) { color: yellow }", "a:is(.foo .bar){color:#ff0}");
7240    minify_test(":is(.foo, .bar) { color: yellow }", ":is(.foo,.bar){color:#ff0}");
7241    minify_test("a:is(:not(.foo)) { color: yellow }", "a:not(.foo){color:#ff0}");
7242    minify_test("a:is(:first-child) { color: yellow }", "a:first-child{color:#ff0}");
7243    minify_test("a:is(:has(.foo)) { color: yellow }", "a:has(.foo){color:#ff0}");
7244    minify_test("a:is(:is(.foo)) { color: yellow }", "a.foo{color:#ff0}");
7245    minify_test(":host(:hover) {color: red}", ":host(:hover){color:red}");
7246    minify_test("::slotted(:hover) {color: red}", "::slotted(:hover){color:red}");
7247
7248    minify_test(
7249      ":root::view-transition {position: fixed}",
7250      ":root::view-transition{position:fixed}",
7251    );
7252    minify_test(
7253      ":root:active-view-transition {position: fixed}",
7254      ":root:active-view-transition{position:fixed}",
7255    );
7256    minify_test(
7257      ":root:active-view-transition-type(slide-in) {position: fixed}",
7258      ":root:active-view-transition-type(slide-in){position:fixed}",
7259    );
7260    minify_test(
7261      ":root:active-view-transition-type(slide-in, reverse) {position: fixed}",
7262      ":root:active-view-transition-type(slide-in,reverse){position:fixed}",
7263    );
7264
7265    for name in &[
7266      "view-transition-group",
7267      "view-transition-image-pair",
7268      "view-transition-new",
7269      "view-transition-old",
7270    ] {
7271      minify_test(
7272        &format!(":root::{}(*) {{position: fixed}}", name),
7273        &format!(":root::{}(*){{position:fixed}}", name),
7274      );
7275      minify_test(
7276        &format!(":root::{}(*.class) {{position: fixed}}", name),
7277        &format!(":root::{}(*.class){{position:fixed}}", name),
7278      );
7279      minify_test(
7280        &format!(":root::{}(*.class.class) {{position: fixed}}", name),
7281        &format!(":root::{}(*.class.class){{position:fixed}}", name),
7282      );
7283      minify_test(
7284        &format!(":root::{}(foo) {{position: fixed}}", name),
7285        &format!(":root::{}(foo){{position:fixed}}", name),
7286      );
7287      minify_test(
7288        &format!(":root::{}(foo.class) {{position: fixed}}", name),
7289        &format!(":root::{}(foo.class){{position:fixed}}", name),
7290      );
7291      minify_test(
7292        &format!(":root::{}(foo.bar.baz) {{position: fixed}}", name),
7293        &format!(":root::{}(foo.bar.baz){{position:fixed}}", name),
7294      );
7295      minify_test(
7296        &format!(":root::{}(foo):only-child {{position: fixed}}", name),
7297        &format!(":root::{}(foo):only-child{{position:fixed}}", name),
7298      );
7299      minify_test(
7300        &format!(":root::{}(foo.bar.baz):only-child {{position: fixed}}", name),
7301        &format!(":root::{}(foo.bar.baz):only-child{{position:fixed}}", name),
7302      );
7303      minify_test(
7304        &format!(":root::{}(.foo) {{position: fixed}}", name),
7305        &format!(":root::{}(.foo){{position:fixed}}", name),
7306      );
7307      minify_test(
7308        &format!(":root::{}(.foo.bar) {{position: fixed}}", name),
7309        &format!(":root::{}(.foo.bar){{position:fixed}}", name),
7310      );
7311      minify_test(
7312        &format!(":root::{}(  .foo.bar  ) {{position: fixed}}", name),
7313        &format!(":root::{}(.foo.bar){{position:fixed}}", name),
7314      );
7315      error_test(
7316        &format!(":root::{}(foo):first-child {{position: fixed}}", name),
7317        ParserError::SelectorError(SelectorError::InvalidPseudoClassAfterPseudoElement),
7318      );
7319      error_test(
7320        &format!(":root::{}(foo)::before {{position: fixed}}", name),
7321        ParserError::SelectorError(SelectorError::InvalidState),
7322      );
7323      error_test(
7324        &format!(":root::{}(*.*) {{position: fixed}}", name),
7325        ParserError::SelectorError(SelectorError::InvalidState),
7326      );
7327      error_test(
7328        &format!(":root::{}(*. cls) {{position: fixed}}", name),
7329        ParserError::SelectorError(SelectorError::InvalidState),
7330      );
7331      error_test(
7332        &format!(":root::{}(foo .bar) {{position: fixed}}", name),
7333        ParserError::SelectorError(SelectorError::InvalidState),
7334      );
7335      error_test(
7336        &format!(":root::{}(*.cls. c) {{position: fixed}}", name),
7337        ParserError::SelectorError(SelectorError::InvalidState),
7338      );
7339      error_test(
7340        &format!(":root::{}(*.cls>cls) {{position: fixed}}", name),
7341        ParserError::SelectorError(SelectorError::InvalidState),
7342      );
7343      error_test(
7344        &format!(":root::{}(*.cls.foo.*) {{position: fixed}}", name),
7345        ParserError::SelectorError(SelectorError::InvalidState),
7346      );
7347    }
7348    minify_test(
7349      "wa-checkbox:state(disabled) {color:red}",
7350      "wa-checkbox:state(disabled){color:red}",
7351    );
7352    minify_test(
7353      "button:state(checked) {background:blue}",
7354      "button:state(checked){background:#00f}",
7355    );
7356    minify_test(
7357      "input:state(custom-state) {border:1px solid}",
7358      "input:state(custom-state){border:1px solid}",
7359    );
7360    minify_test(
7361      "button:active:not(:state(disabled))::part(control) {border:1px solid}",
7362      "button:active:not(:state(disabled))::part(control){border:1px solid}",
7363    );
7364    // Test nested CSS with :state() selector
7365    nesting_test(
7366      r#"
7367        custom-element {
7368          color: blue;
7369          &:state(loading) {
7370            opacity: 0.5;
7371            & .spinner {
7372              display: block;
7373            }
7374          }
7375          &:state(error) {
7376            border: 2px solid red;
7377          }
7378        }
7379      "#,
7380      indoc! {r#"
7381        custom-element {
7382          color: #00f;
7383        }
7384
7385        custom-element:state(loading) {
7386          opacity: .5;
7387        }
7388
7389        custom-element:state(loading) .spinner {
7390          display: block;
7391        }
7392
7393        custom-element:state(error) {
7394          border: 2px solid red;
7395        }
7396      "#},
7397    );
7398    minify_test(".foo ::deep .bar {width: 20px}", ".foo ::deep .bar{width:20px}");
7399    minify_test(".foo::deep .bar {width: 20px}", ".foo::deep .bar{width:20px}");
7400    minify_test(".foo ::deep.bar {width: 20px}", ".foo ::deep.bar{width:20px}");
7401    minify_test(".foo ::unknown .bar {width: 20px}", ".foo ::unknown .bar{width:20px}");
7402    minify_test(
7403      ".foo ::unknown(foo) .bar {width: 20px}",
7404      ".foo ::unknown(foo) .bar{width:20px}",
7405    );
7406    minify_test(
7407      ".foo ::unknown:only-child {width: 20px}",
7408      ".foo ::unknown:only-child{width:20px}",
7409    );
7410    minify_test(
7411      ".foo ::unknown(.foo) .bar {width: 20px}",
7412      ".foo ::unknown(.foo) .bar{width:20px}",
7413    );
7414    minify_test(
7415      ".foo ::unknown(.foo .bar / .baz) .bar {width: 20px}",
7416      ".foo ::unknown(.foo .bar / .baz) .bar{width:20px}",
7417    );
7418    minify_test(
7419      ".foo ::unknown(something(foo)) .bar {width: 20px}",
7420      ".foo ::unknown(something(foo)) .bar{width:20px}",
7421    );
7422    minify_test(
7423      ".foo ::unknown([abc]) .bar {width: 20px}",
7424      ".foo ::unknown([abc]) .bar{width:20px}",
7425    );
7426
7427    let deep_options = ParserOptions {
7428      flags: ParserFlags::DEEP_SELECTOR_COMBINATOR,
7429      ..ParserOptions::default()
7430    };
7431
7432    error_test(
7433      ".foo >>> .bar {width: 20px}",
7434      ParserError::SelectorError(SelectorError::DanglingCombinator),
7435    );
7436    error_test(
7437      ".foo /deep/ .bar {width: 20px}",
7438      ParserError::SelectorError(SelectorError::DanglingCombinator),
7439    );
7440    minify_test_with_options(
7441      ".foo >>> .bar {width: 20px}",
7442      ".foo>>>.bar{width:20px}",
7443      deep_options.clone(),
7444    );
7445    minify_test_with_options(
7446      ".foo /deep/ .bar {width: 20px}",
7447      ".foo /deep/ .bar{width:20px}",
7448      deep_options.clone(),
7449    );
7450
7451    let pure_css_module_options = ParserOptions {
7452      css_modules: Some(crate::css_modules::Config {
7453        pure: true,
7454        ..Default::default()
7455      }),
7456      ..ParserOptions::default()
7457    };
7458
7459    minify_error_test_with_options(
7460      "div {width: 20px}",
7461      MinifyErrorKind::ImpureCSSModuleSelector,
7462      pure_css_module_options.clone(),
7463    );
7464    minify_error_test_with_options(
7465      ":global(.foo) {width: 20px}",
7466      MinifyErrorKind::ImpureCSSModuleSelector,
7467      pure_css_module_options.clone(),
7468    );
7469    minify_error_test_with_options(
7470      "[foo=bar] {width: 20px}",
7471      MinifyErrorKind::ImpureCSSModuleSelector,
7472      pure_css_module_options.clone(),
7473    );
7474    minify_error_test_with_options(
7475      "div, .foo {width: 20px}",
7476      MinifyErrorKind::ImpureCSSModuleSelector,
7477      pure_css_module_options.clone(),
7478    );
7479    minify_test_with_options(
7480      ":local(.foo) {width: 20px}",
7481      "._8Z4fiW_foo{width:20px}",
7482      pure_css_module_options.clone(),
7483    );
7484    minify_test_with_options(
7485      "div.my-class {color: red;}",
7486      "div._8Z4fiW_my-class{color:red}",
7487      pure_css_module_options.clone(),
7488    );
7489    minify_test_with_options(
7490      "#id {color: red;}",
7491      "#_8Z4fiW_id{color:red}",
7492      pure_css_module_options.clone(),
7493    );
7494    minify_test_with_options(
7495      "a .my-class{color: red;}",
7496      "a ._8Z4fiW_my-class{color:red}",
7497      pure_css_module_options.clone(),
7498    );
7499    minify_test_with_options(
7500      ".my-class a {color: red;}",
7501      "._8Z4fiW_my-class a{color:red}",
7502      pure_css_module_options.clone(),
7503    );
7504    minify_test_with_options(
7505      ".my-class:is(a) {color: red;}",
7506      "._8Z4fiW_my-class:is(a){color:red}",
7507      pure_css_module_options.clone(),
7508    );
7509    minify_test_with_options(
7510      "div:has(.my-class) {color: red;}",
7511      "div:has(._8Z4fiW_my-class){color:red}",
7512      pure_css_module_options.clone(),
7513    );
7514    minify_test_with_options(
7515      ".foo { html &:hover { a_value: some-value; } }",
7516      "._8Z4fiW_foo{html &:hover{a_value:some-value}}",
7517      pure_css_module_options.clone(),
7518    );
7519    minify_test_with_options(
7520      ".foo { span { color: red; } }",
7521      "._8Z4fiW_foo{& span{color:red}}",
7522      pure_css_module_options.clone(),
7523    );
7524    minify_error_test_with_options(
7525      "html { .foo { span { color: red; } } }",
7526      MinifyErrorKind::ImpureCSSModuleSelector,
7527      pure_css_module_options.clone(),
7528    );
7529    minify_test_with_options(
7530      ".foo { div { span { color: red; } } }",
7531      "._8Z4fiW_foo{& div{& span{color:red}}}",
7532      pure_css_module_options.clone(),
7533    );
7534    minify_error_test_with_options(
7535      "@scope (div) { .foo { color: red } }",
7536      MinifyErrorKind::ImpureCSSModuleSelector,
7537      pure_css_module_options.clone(),
7538    );
7539    minify_error_test_with_options(
7540      "@scope (.a) to (div) { .foo { color: red } }",
7541      MinifyErrorKind::ImpureCSSModuleSelector,
7542      pure_css_module_options.clone(),
7543    );
7544    minify_error_test_with_options(
7545      "@scope (.a) to (.b) { div { color: red } }",
7546      MinifyErrorKind::ImpureCSSModuleSelector,
7547      pure_css_module_options.clone(),
7548    );
7549    minify_test_with_options(
7550      "@scope (.a) to (.b) { .foo { color: red } }",
7551      "@scope(._8Z4fiW_a) to (._8Z4fiW_b){._8Z4fiW_foo{color:red}}",
7552      pure_css_module_options.clone(),
7553    );
7554    minify_test_with_options(
7555      "/* cssmodules-pure-no-check */ :global(.foo) { color: red }",
7556      ".foo{color:red}",
7557      pure_css_module_options.clone(),
7558    );
7559    minify_test_with_options(
7560      "/*! some license */ /* cssmodules-pure-no-check */ :global(.foo) { color: red }",
7561      "/*! some license */\n.foo{color:red}",
7562      pure_css_module_options.clone(),
7563    );
7564
7565    error_test(
7566      "input.defaultCheckbox::before h1 {width: 20px}",
7567      ParserError::SelectorError(SelectorError::UnexpectedSelectorAfterPseudoElement(Token::Ident(
7568        "h1".into(),
7569      ))),
7570    );
7571    error_test(
7572      "input.defaultCheckbox::before .my-class {width: 20px}",
7573      ParserError::SelectorError(SelectorError::UnexpectedSelectorAfterPseudoElement(Token::Delim('.'))),
7574    );
7575    error_test(
7576      "input.defaultCheckbox::before.my-class {width: 20px}",
7577      ParserError::SelectorError(SelectorError::UnexpectedSelectorAfterPseudoElement(Token::Delim('.'))),
7578    );
7579    error_test(
7580      "input.defaultCheckbox::before #id {width: 20px}",
7581      ParserError::SelectorError(SelectorError::UnexpectedSelectorAfterPseudoElement(Token::IDHash(
7582        "id".into(),
7583      ))),
7584    );
7585    error_test(
7586      "input.defaultCheckbox::before#id {width: 20px}",
7587      ParserError::SelectorError(SelectorError::UnexpectedSelectorAfterPseudoElement(Token::IDHash(
7588        "id".into(),
7589      ))),
7590    );
7591    error_test(
7592      "input.defaultCheckbox::before [attr] {width: 20px}",
7593      ParserError::SelectorError(SelectorError::UnexpectedSelectorAfterPseudoElement(
7594        Token::SquareBracketBlock,
7595      )),
7596    );
7597    error_test(
7598      "input.defaultCheckbox::before[attr] {width: 20px}",
7599      ParserError::SelectorError(SelectorError::UnexpectedSelectorAfterPseudoElement(
7600        Token::SquareBracketBlock,
7601      )),
7602    );
7603  }
7604
7605  #[test]
7606  fn test_keyframes() {
7607    minify_test(
7608      r#"
7609      @keyframes "test" {
7610        100% {
7611          background: blue
7612        }
7613      }
7614    "#,
7615      "@keyframes test{to{background:#00f}}",
7616    );
7617    minify_test(
7618      r#"
7619      @keyframes test {
7620        100% {
7621          background: blue
7622        }
7623      }
7624    "#,
7625      "@keyframes test{to{background:#00f}}",
7626    );
7627
7628    // named animation range percentages
7629    minify_test(
7630      r#"
7631      @keyframes test {
7632        entry 0% {
7633          background: blue
7634        }
7635        exit 100% {
7636          background: green
7637        }
7638      }
7639    "#,
7640      "@keyframes test{entry 0%{background:#00f}exit 100%{background:green}}",
7641    );
7642
7643    // CSS-wide keywords and `none` cannot remove quotes.
7644    minify_test(
7645      r#"
7646      @keyframes "revert" {
7647        from {
7648          background: green;
7649        }
7650      }
7651    "#,
7652      "@keyframes \"revert\"{0%{background:green}}",
7653    );
7654
7655    minify_test(
7656      r#"
7657      @keyframes "none" {
7658        from {
7659          background: green;
7660        }
7661      }
7662    "#,
7663      "@keyframes \"none\"{0%{background:green}}",
7664    );
7665
7666    // named animation ranges cannot be used with to or from
7667    minify_test(
7668      r#"
7669      @keyframes test {
7670        entry to {
7671          background: blue
7672        }
7673      }
7674    "#,
7675      "@keyframes test{}",
7676    );
7677
7678    // CSS-wide keywords without quotes throws an error.
7679    error_test(
7680      r#"
7681      @keyframes revert {}
7682    "#,
7683      ParserError::UnexpectedToken(Token::Ident("revert".into())),
7684    );
7685
7686    error_test(
7687      r#"
7688      @keyframes revert-layer {}
7689    "#,
7690      ParserError::UnexpectedToken(Token::Ident("revert-layer".into())),
7691    );
7692
7693    error_test(
7694      r#"
7695      @keyframes none {}
7696    "#,
7697      ParserError::UnexpectedToken(Token::Ident("none".into())),
7698    );
7699
7700    error_test(
7701      r#"
7702      @keyframes NONE {}
7703    "#,
7704      ParserError::UnexpectedToken(Token::Ident("NONE".into())),
7705    );
7706
7707    minify_test(
7708      r#"
7709      @-webkit-keyframes test {
7710        from {
7711          background: green;
7712          background-color: red;
7713        }
7714
7715        100% {
7716          background: blue
7717        }
7718      }
7719    "#,
7720      "@-webkit-keyframes test{0%{background:red}to{background:#00f}}",
7721    );
7722    minify_test(
7723      r#"
7724      @-moz-keyframes test {
7725        from {
7726          background: green;
7727          background-color: red;
7728        }
7729
7730        100% {
7731          background: blue
7732        }
7733      }
7734    "#,
7735      "@-moz-keyframes test{0%{background:red}to{background:#00f}}",
7736    );
7737    minify_test(r#"
7738      @-webkit-keyframes test {
7739        from {
7740          background: green;
7741          background-color: red;
7742        }
7743
7744        100% {
7745          background: blue
7746        }
7747      }
7748      @-moz-keyframes test {
7749        from {
7750          background: green;
7751          background-color: red;
7752        }
7753
7754        100% {
7755          background: blue
7756        }
7757      }
7758    "#, "@-webkit-keyframes test{0%{background:red}to{background:#00f}}@-moz-keyframes test{0%{background:red}to{background:#00f}}");
7759
7760    prefix_test(
7761      r#"
7762      @keyframes test {
7763        from {
7764          background: green;
7765        }
7766        to {
7767          background: blue
7768        }
7769      }
7770    "#,
7771      indoc! { r#"
7772      @-webkit-keyframes test {
7773        from {
7774          background: green;
7775        }
7776
7777        to {
7778          background: #00f;
7779        }
7780      }
7781
7782      @-moz-keyframes test {
7783        from {
7784          background: green;
7785        }
7786
7787        to {
7788          background: #00f;
7789        }
7790      }
7791
7792      @keyframes test {
7793        from {
7794          background: green;
7795        }
7796
7797        to {
7798          background: #00f;
7799        }
7800      }
7801    "#},
7802      Browsers {
7803        safari: Some(5 << 16),
7804        firefox: Some(6 << 16),
7805        ..Browsers::default()
7806      },
7807    );
7808    prefix_test(
7809      r#"
7810      @-webkit-keyframes test {
7811        from {
7812          background: green;
7813        }
7814
7815        to {
7816          background: blue;
7817        }
7818      }
7819      @-moz-keyframes test {
7820        from {
7821          background: green;
7822        }
7823
7824        to {
7825          background: blue;
7826        }
7827      }
7828      @keyframes test {
7829        from {
7830          background: green;
7831        }
7832        to {
7833          background: blue
7834        }
7835      }
7836    "#,
7837      indoc! { r#"
7838      @keyframes test {
7839        from {
7840          background: green;
7841        }
7842
7843        to {
7844          background: #00f;
7845        }
7846      }
7847    "#},
7848      Browsers {
7849        safari: Some(10 << 16),
7850        firefox: Some(17 << 16),
7851        ..Browsers::default()
7852      },
7853    );
7854    prefix_test(
7855      r#"
7856      @-webkit-keyframes test1 {
7857        from {
7858          background: green;
7859        }
7860
7861        to {
7862          background: blue;
7863        }
7864      }
7865
7866      @-moz-keyframes test2 {
7867        from {
7868          background: green;
7869        }
7870
7871        to {
7872          background: blue;
7873        }
7874      }
7875
7876      @keyframes test3 {
7877        from {
7878          background: green;
7879        }
7880        to {
7881          background: blue
7882        }
7883      }
7884    "#,
7885      indoc! { r#"
7886      @-webkit-keyframes test1 {
7887        from {
7888          background: green;
7889        }
7890
7891        to {
7892          background: #00f;
7893        }
7894      }
7895
7896      @-moz-keyframes test2 {
7897        from {
7898          background: green;
7899        }
7900
7901        to {
7902          background: #00f;
7903        }
7904      }
7905
7906      @keyframes test3 {
7907        from {
7908          background: green;
7909        }
7910
7911        to {
7912          background: #00f;
7913        }
7914      }
7915    "#},
7916      Browsers {
7917        safari: Some(10 << 16),
7918        firefox: Some(17 << 16),
7919        ..Browsers::default()
7920      },
7921    );
7922    prefix_test(
7923      r#"
7924      @-webkit-keyframes test {
7925        from {
7926          background: green;
7927        }
7928
7929        to {
7930          background: red;
7931        }
7932      }
7933      @-moz-keyframes test {
7934        from {
7935          background: green;
7936        }
7937
7938        to {
7939          background: pink;
7940        }
7941      }
7942      @keyframes test {
7943        from {
7944          background: green;
7945        }
7946        to {
7947          background: blue
7948        }
7949      }
7950    "#,
7951      indoc! { r#"
7952      @-webkit-keyframes test {
7953        from {
7954          background: green;
7955        }
7956
7957        to {
7958          background: red;
7959        }
7960      }
7961
7962      @-moz-keyframes test {
7963        from {
7964          background: green;
7965        }
7966
7967        to {
7968          background: pink;
7969        }
7970      }
7971
7972      @keyframes test {
7973        from {
7974          background: green;
7975        }
7976
7977        to {
7978          background: #00f;
7979        }
7980      }
7981    "#},
7982      Browsers {
7983        safari: Some(10 << 16),
7984        firefox: Some(17 << 16),
7985        ..Browsers::default()
7986      },
7987    );
7988
7989    minify_test(
7990      r#"
7991      @keyframes test {
7992        100% {
7993          background: blue
7994        }
7995      }
7996
7997      @keyframes test {
7998        100% {
7999          background: red
8000        }
8001      }
8002    "#,
8003      "@keyframes test{to{background:red}}",
8004    );
8005    minify_test(
8006      r#"
8007      @keyframes test {
8008        100% {
8009          background: blue
8010        }
8011      }
8012
8013      @-webkit-keyframes test {
8014        100% {
8015          background: red
8016        }
8017      }
8018    "#,
8019      "@keyframes test{to{background:#00f}}@-webkit-keyframes test{to{background:red}}",
8020    );
8021  }
8022
8023  #[test]
8024  fn test_important() {
8025    test(
8026      r#"
8027      .foo {
8028        align-items: center;
8029        justify-items: center !important;
8030      }
8031    "#,
8032      indoc! {r#"
8033      .foo {
8034        align-items: center;
8035        justify-items: center !important;
8036      }
8037    "#},
8038    );
8039
8040    test(
8041      r#"
8042      .foo {
8043        justify-items: center !important;
8044        align-items: center;
8045      }
8046    "#,
8047      indoc! {r#"
8048      .foo {
8049        align-items: center;
8050        justify-items: center !important;
8051      }
8052    "#},
8053    );
8054
8055    minify_test(
8056      r#"
8057      .foo {
8058        font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace !important;
8059      }
8060    "#,
8061      ".foo{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace!important}",
8062    );
8063  }
8064
8065  #[test]
8066  fn test_calc() {
8067    minify_test(".foo { width: calc(20px * 2) }", ".foo{width:40px}");
8068    minify_test(".foo { font-size: calc(100vw / 35) }", ".foo{font-size:2.85714vw}");
8069    minify_test(".foo { width: calc(20px * 2 * 3) }", ".foo{width:120px}");
8070    minify_test(".foo { width: calc(20px + 30px) }", ".foo{width:50px}");
8071    minify_test(".foo { width: calc(20px + 30px + 40px) }", ".foo{width:90px}");
8072    minify_test(".foo { width: calc(100% - 30px) }", ".foo{width:calc(100% - 30px)}");
8073    minify_test(
8074      ".foo { width: calc(100% - 30px + 20px) }",
8075      ".foo{width:calc(100% - 10px)}",
8076    );
8077    minify_test(
8078      ".foo { width: calc(20px + 100% - 30px) }",
8079      ".foo{width:calc(100% - 10px)}",
8080    );
8081    minify_test(
8082      ".foo { width: calc(20px + 100% + 10vw - 30px) }",
8083      ".foo{width:calc(100% - 10px + 10vw)}",
8084    );
8085    minify_test(
8086      ".foo { width: calc(20px + 100% - 30px) }",
8087      ".foo{width:calc(100% - 10px)}",
8088    );
8089    minify_test(
8090      ".foo { width: calc(2 * (100% - 20px)) }",
8091      ".foo{width:calc(200% - 40px)}",
8092    );
8093    minify_test(
8094      ".foo { width: calc((100% - 20px) * 2) }",
8095      ".foo{width:calc(200% - 40px)}",
8096    );
8097    minify_test(".foo { width: calc(100% - 20px * 2) }", ".foo{width:calc(100% - 40px)}");
8098    minify_test(".foo { width: calc(1px + 1px) }", ".foo{width:2px}");
8099    minify_test(".foo { width: calc(100vw / 2) }", ".foo{width:50vw}");
8100    minify_test(".foo { width: calc(50px - (20px - 30px)) }", ".foo{width:60px}");
8101    minify_test(".foo { width: calc(100px - (100px - 100%)) }", ".foo{width:100%}");
8102    minify_test(
8103      ".foo { width: calc(100px + (100px - 100%)) }",
8104      ".foo{width:calc(200px - 100%)}",
8105    );
8106    minify_test(
8107      ".foo { width: calc(1px - (2em + 3%)) }",
8108      ".foo{width:calc(1px + -2em - 3%)}",
8109    ); // TODO: fix sign
8110    minify_test(
8111      ".foo { width: calc((100vw - 50em) / 2) }",
8112      ".foo{width:calc(50vw - 25em)}",
8113    );
8114    minify_test(
8115      ".foo { width: calc(1px - (2em + 4vh + 3%)) }",
8116      ".foo{width:calc(1px + -2em - 4vh - 3%)}",
8117    ); // TODO
8118    minify_test(
8119      ".foo { width: calc(1px + (2em + (3vh + 4px))) }",
8120      ".foo{width:calc(2em + 3vh + 5px)}",
8121    );
8122    minify_test(
8123      ".foo { width: calc(1px - (2em + 4px - 6vh) / 2) }",
8124      ".foo{width:calc(-1em - 1px + 3vh)}",
8125    );
8126    minify_test(
8127      ".foo { width: calc(100% - calc(50% + 25px)) }",
8128      ".foo{width:calc(50% - 25px)}",
8129    );
8130    minify_test(".foo { width: calc(1px/100) }", ".foo{width:.01px}");
8131    minify_test(
8132      ".foo { width: calc(100vw / 2 - 6px + 0px) }",
8133      ".foo{width:calc(50vw - 6px)}",
8134    );
8135    minify_test(".foo { width: calc(1px + 1) }", ".foo{width:calc(1px + 1)}");
8136    minify_test(
8137      ".foo { width: calc( (1em - calc( 10px + 1em)) / 2) }",
8138      ".foo{width:-5px}",
8139    );
8140    minify_test(
8141      ".foo { width: calc((100px - 1em) + (-50px + 1em)) }",
8142      ".foo{width:50px}",
8143    );
8144    minify_test(
8145      ".foo { width: calc(100% + (2 * 100px) - ((75.37% - 63.5px) - 900px)) }",
8146      ".foo{width:calc(24.63% + 1163.5px)}",
8147    );
8148    minify_test(
8149      ".foo { width: calc(((((100% + (2 * 30px) + 63.5px) / 0.7537) - (100vw - 60px)) / 2) + 30px) }",
8150      ".foo{width:calc(66.3394% + 141.929px - 50vw)}",
8151    );
8152    minify_test(
8153      ".foo { width: calc(((75.37% - 63.5px) - 900px) + (2 * 100px)) }",
8154      ".foo{width:calc(75.37% - 763.5px)}",
8155    );
8156    minify_test(
8157      ".foo { width: calc((900px - (10% - 63.5px)) + (2 * 100px)) }",
8158      ".foo{width:calc(1163.5px - 10%)}",
8159    );
8160    minify_test(".foo { width: calc(500px/0) }", ".foo{width:calc(500px/0)}");
8161    minify_test(".foo { width: calc(500px/2px) }", ".foo{width:calc(500px/2px)}");
8162    minify_test(".foo { width: calc(100% / 3 * 3) }", ".foo{width:100%}");
8163    minify_test(".foo { width: calc(+100px + +100px) }", ".foo{width:200px}");
8164    minify_test(".foo { width: calc(+100px - +100px) }", ".foo{width:0}");
8165    minify_test(".foo { width: calc(200px * +1) }", ".foo{width:200px}");
8166    minify_test(".foo { width: calc(200px / +1) }", ".foo{width:200px}");
8167    minify_test(".foo { width: calc(1.1e+1px + 1.1e+1px) }", ".foo{width:22px}");
8168    minify_test(".foo { border-width: calc(1px + 2px) }", ".foo{border-width:3px}");
8169    minify_test(
8170      ".foo { border-width: calc(1em + 2px + 2em + 3px) }",
8171      ".foo{border-width:calc(3em + 5px)}",
8172    );
8173
8174    minify_test(
8175      ".foo { border-width: min(1em, 2px) }",
8176      ".foo{border-width:min(1em,2px)}",
8177    );
8178    minify_test(
8179      ".foo { border-width: min(1em + 2em, 2px + 2px) }",
8180      ".foo{border-width:min(3em,4px)}",
8181    );
8182    minify_test(
8183      ".foo { border-width: min(1em + 2px, 2px + 1em) }",
8184      ".foo{border-width:min(1em + 2px,2px + 1em)}",
8185    );
8186    minify_test(
8187      ".foo { border-width: min(1em + 2px + 2px, 2px + 1em + 1px) }",
8188      ".foo{border-width:min(1em + 4px,3px + 1em)}",
8189    );
8190    minify_test(
8191      ".foo { border-width: min(2px + 1px, 3px + 4px) }",
8192      ".foo{border-width:3px}",
8193    );
8194    minify_test(
8195      ".foo { border-width: min(1px, 1em, 2px, 3in) }",
8196      ".foo{border-width:min(1px,1em)}",
8197    );
8198
8199    minify_test(
8200      ".foo { border-width: max(1em, 2px) }",
8201      ".foo{border-width:max(1em,2px)}",
8202    );
8203    minify_test(
8204      ".foo { border-width: max(1em + 2em, 2px + 2px) }",
8205      ".foo{border-width:max(3em,4px)}",
8206    );
8207    minify_test(
8208      ".foo { border-width: max(1em + 2px, 2px + 1em) }",
8209      ".foo{border-width:max(1em + 2px,2px + 1em)}",
8210    );
8211    minify_test(
8212      ".foo { border-width: max(1em + 2px + 2px, 2px + 1em + 1px) }",
8213      ".foo{border-width:max(1em + 4px,3px + 1em)}",
8214    );
8215    minify_test(
8216      ".foo { border-width: max(2px + 1px, 3px + 4px) }",
8217      ".foo{border-width:7px}",
8218    );
8219    minify_test(
8220      ".foo { border-width: max(1px, 1em, 2px, 3in) }",
8221      ".foo{border-width:max(3in,1em)}",
8222    );
8223
8224    minify_test(".foo { border-width: clamp(1px, 2px, 3px) }", ".foo{border-width:2px}");
8225    minify_test(".foo { border-width: clamp(1px, 10px, 3px) }", ".foo{border-width:3px}");
8226    minify_test(".foo { border-width: clamp(5px, 2px, 10px) }", ".foo{border-width:5px}");
8227    minify_test(
8228      ".foo { border-width: clamp(100px, 2px, 10px) }",
8229      ".foo{border-width:100px}",
8230    );
8231    minify_test(
8232      ".foo { border-width: clamp(5px + 5px, 5px + 7px, 10px + 20px) }",
8233      ".foo{border-width:12px}",
8234    );
8235
8236    minify_test(
8237      ".foo { border-width: clamp(1em, 2px, 4vh) }",
8238      ".foo{border-width:clamp(1em,2px,4vh)}",
8239    );
8240    minify_test(
8241      ".foo { border-width: clamp(1em, 2em, 4vh) }",
8242      ".foo{border-width:clamp(1em,2em,4vh)}",
8243    );
8244    minify_test(
8245      ".foo { border-width: clamp(1em, 2vh, 4vh) }",
8246      ".foo{border-width:max(1em,2vh)}",
8247    );
8248    minify_test(
8249      ".foo { border-width: clamp(1px, 1px + 2em, 4px) }",
8250      ".foo{border-width:clamp(1px,1px + 2em,4px)}",
8251    );
8252    minify_test(".foo { border-width: clamp(1px, 2pt, 1in) }", ".foo{border-width:2pt}");
8253    minify_test(
8254      ".foo { width: clamp(-100px, 0px, 50% - 50vw); }",
8255      ".foo{width:clamp(-100px,0px,50% - 50vw)}",
8256    );
8257
8258    minify_test(
8259      ".foo { top: calc(-1 * clamp(1.75rem, 8vw, 4rem)) }",
8260      ".foo{top:calc(-1*clamp(1.75rem,8vw,4rem))}",
8261    );
8262    minify_test(
8263      ".foo { top: calc(-1 * min(1.75rem, 8vw, 4rem)) }",
8264      ".foo{top:calc(-1*min(1.75rem,8vw))}",
8265    );
8266    minify_test(
8267      ".foo { top: calc(-1 * max(1.75rem, 8vw, 4rem)) }",
8268      ".foo{top:calc(-1*max(4rem,8vw))}",
8269    );
8270    minify_test(
8271      ".foo { top: calc(clamp(1.75rem, 8vw, 4rem) * -1) }",
8272      ".foo{top:calc(-1*clamp(1.75rem,8vw,4rem))}",
8273    );
8274    minify_test(
8275      ".foo { top: calc(min(1.75rem, 8vw, 4rem) * -1) }",
8276      ".foo{top:calc(-1*min(1.75rem,8vw))}",
8277    );
8278    minify_test(
8279      ".foo { top: calc(max(1.75rem, 8vw, 4rem) * -1) }",
8280      ".foo{top:calc(-1*max(4rem,8vw))}",
8281    );
8282    minify_test(
8283      ".foo { top: calc(clamp(1.75rem, 8vw, 4rem) / 2) }",
8284      ".foo{top:calc(clamp(1.75rem,8vw,4rem)/2)}",
8285    );
8286    minify_test(
8287      ".foo { top: calc(min(1.75rem, 8vw, 4rem) / 2) }",
8288      ".foo{top:calc(min(1.75rem,8vw)/2)}",
8289    );
8290    minify_test(
8291      ".foo { top: calc(max(1.75rem, 8vw, 4rem) / 2) }",
8292      ".foo{top:calc(max(4rem,8vw)/2)}",
8293    );
8294    minify_test(
8295      ".foo { top: calc(0.5 * clamp(1.75rem, 8vw, 4rem)) }",
8296      ".foo{top:calc(clamp(1.75rem,8vw,4rem)/2)}",
8297    );
8298    minify_test(
8299      ".foo { top: calc(1 * clamp(1.75rem, 8vw, 4rem)) }",
8300      ".foo{top:calc(clamp(1.75rem,8vw,4rem))}",
8301    );
8302    minify_test(
8303      ".foo { top: calc(2 * clamp(1.75rem, 8vw, 4rem) / 2) }",
8304      ".foo{top:calc(clamp(1.75rem,8vw,4rem))}",
8305    );
8306
8307    minify_test(".foo { width: max(0px, 1vw) }", ".foo{width:max(0px,1vw)}");
8308
8309    prefix_test(
8310      ".foo { border-width: clamp(1em, 2px, 4vh) }",
8311      indoc! { r#"
8312        .foo {
8313          border-width: max(1em, min(2px, 4vh));
8314        }
8315      "#},
8316      Browsers {
8317        safari: Some(12 << 16),
8318        ..Browsers::default()
8319      },
8320    );
8321
8322    prefix_test(
8323      ".foo { border-width: clamp(1em, 2px, 4vh) }",
8324      indoc! { r#"
8325        .foo {
8326          border-width: clamp(1em, 2px, 4vh);
8327        }
8328      "#},
8329      Browsers {
8330        safari: Some(14 << 16),
8331        ..Browsers::default()
8332      },
8333    );
8334
8335    minify_test(".foo { width: calc(1vh + 2vh) }", ".foo{width:3vh}");
8336    minify_test(".foo { width: calc(1dvh + 2dvh) }", ".foo{width:3dvh}");
8337    minify_test(".foo { width: calc(1lvh + 2lvh) }", ".foo{width:3lvh}");
8338    minify_test(".foo { width: calc(1svh + 2svh) }", ".foo{width:3svh}");
8339    minify_test(".foo { width: calc(1sVmin + 2Svmin) }", ".foo{width:3svmin}");
8340    minify_test(".foo { width: calc(1ic + 2ic) }", ".foo{width:3ic}");
8341    minify_test(".foo { width: calc(1ric + 2ric) }", ".foo{width:3ric}");
8342    minify_test(".foo { width: calc(1cap + 2cap) }", ".foo{width:3cap}");
8343    minify_test(".foo { width: calc(1lh + 2lh) }", ".foo{width:3lh}");
8344    minify_test(".foo { width: calc(1x + 2x) }", ".foo{width:calc(1x + 2x)}");
8345    minify_test(
8346      ".foo { left: calc(50% - 100px + clamp(0px, calc(50vw - 50px), 100px)) }",
8347      ".foo{left:calc(50% - 100px + clamp(0px,50vw - 50px,100px))}",
8348    );
8349    minify_test(
8350      ".foo { left: calc(10px + min(10px, 1rem) + max(2px, 1vw)) }",
8351      ".foo{left:calc(10px + min(10px,1rem) + max(2px,1vw))}",
8352    );
8353    minify_test(".foo { width: round(22px, 5px) }", ".foo{width:20px}");
8354    minify_test(".foo { width: round(nearest, 22px, 5px) }", ".foo{width:20px}");
8355    minify_test(".foo { width: round(down, 22px, 5px) }", ".foo{width:20px}");
8356    minify_test(".foo { width: round(to-zero, 22px, 5px) }", ".foo{width:20px}");
8357    minify_test(".foo { width: round(up, 22px, 5px) }", ".foo{width:25px}");
8358    minify_test(".foo { width: round(23px, 5px) }", ".foo{width:25px}");
8359    minify_test(".foo { width: round(nearest, 23px, 5px) }", ".foo{width:25px}");
8360    minify_test(".foo { width: round(down, 23px, 5px) }", ".foo{width:20px}");
8361    minify_test(".foo { width: round(to-zero, 23px, 5px) }", ".foo{width:20px}");
8362    minify_test(".foo { width: round(up, 23px, 5px) }", ".foo{width:25px}");
8363    minify_test(".foo { width: round(22px, 5vw) }", ".foo{width:round(22px,5vw)}");
8364    minify_test(".foo { rotate: round(22deg, 5deg) }", ".foo{rotate:20deg}");
8365    minify_test(".foo { rotate: round(22deg, 5deg) }", ".foo{rotate:20deg}");
8366    minify_test(
8367      ".foo { transition-duration: round(22ms, 5ms) }",
8368      ".foo{transition-duration:20ms}",
8369    );
8370    minify_test(".foo { margin: round(to-zero, -23px, 5px) }", ".foo{margin:-20px}");
8371    minify_test(".foo { margin: round(nearest, -23px, 5px) }", ".foo{margin:-25px}");
8372    minify_test(".foo { margin: calc(10px * round(22, 5)) }", ".foo{margin:200px}");
8373    minify_test(".foo { width: rem(18px, 5px) }", ".foo{width:3px}");
8374    minify_test(".foo { width: rem(-18px, 5px) }", ".foo{width:-3px}");
8375    minify_test(".foo { width: rem(18px, 5vw) }", ".foo{width:rem(18px,5vw)}");
8376    minify_test(".foo { rotate: rem(-140deg, -90deg) }", ".foo{rotate:-50deg}");
8377    minify_test(".foo { rotate: rem(140deg, -90deg) }", ".foo{rotate:50deg}");
8378    minify_test(".foo { width: calc(10px * rem(18, 5)) }", ".foo{width:30px}");
8379    minify_test(".foo { width: mod(18px, 5px) }", ".foo{width:3px}");
8380    minify_test(".foo { width: mod(-18px, 5px) }", ".foo{width:2px}");
8381    minify_test(".foo { rotate: mod(-140deg, -90deg) }", ".foo{rotate:-50deg}");
8382    minify_test(".foo { rotate: mod(140deg, -90deg) }", ".foo{rotate:-40deg}");
8383    minify_test(".foo { width: mod(18px, 5vw) }", ".foo{width:mod(18px,5vw)}");
8384    minify_test(
8385      ".foo { transform: rotateX(mod(140deg, -90deg)) rotateY(rem(140deg, -90deg)) }",
8386      ".foo{transform:rotateX(-40deg)rotateY(50deg)}",
8387    );
8388    minify_test(".foo { width: calc(10px * mod(18, 5)) }", ".foo{width:30px}");
8389
8390    minify_test(
8391      ".foo { width: calc(100% - 30px - 0) }",
8392      ".foo{width:calc(100% - 30px - 0)}",
8393    );
8394    minify_test(
8395      ".foo { width: calc(100% - 30px - 1 - 2) }",
8396      ".foo{width:calc(100% - 30px - 3)}",
8397    );
8398    minify_test(
8399      ".foo { width: calc(1 - 2 - 100% - 30px) }",
8400      ".foo{width:calc(-1 - 100% - 30px)}",
8401    );
8402    minify_test(
8403      ".foo { width: calc(2 * min(1px, 1vmin) - min(1px, 1vmin)); }",
8404      ".foo{width:calc(2*min(1px,1vmin) - min(1px,1vmin))}",
8405    );
8406    minify_test(
8407      ".foo { width: calc(100% - clamp(1.125rem, 1.25vw, 1.2375rem) - clamp(1.125rem, 1.25vw, 1.2375rem)); }",
8408      ".foo{width:calc(100% - clamp(1.125rem,1.25vw,1.2375rem) - clamp(1.125rem,1.25vw,1.2375rem))}",
8409    );
8410    minify_test(
8411      ".foo { width: calc(100% - 2 (2 * var(--card-margin))); }",
8412      ".foo{width:calc(100% - 2 (2 * var(--card-margin)))}",
8413    );
8414
8415    test(
8416      indoc! {r#"
8417    .test {
8418      width: calc(var(--test) + 2px);
8419      width: calc(var(--test) - 2px);
8420    }
8421    "#},
8422      indoc! {r#"
8423    .test {
8424      width: calc(var(--test) + 2px);
8425      width: calc(var(--test) - 2px);
8426    }
8427    "#},
8428    );
8429  }
8430
8431  #[test]
8432  fn test_trig() {
8433    minify_test(".foo { width: calc(2px * pi); }", ".foo{width:6.28319px}");
8434    minify_test(".foo { width: calc(2px / pi); }", ".foo{width:.63662px}");
8435    // minify_test(
8436    //   ".foo { width: calc(2px * infinity); }",
8437    //   ".foo{width:calc(2px*infinity)}",
8438    // );
8439    // minify_test(
8440    //   ".foo { width: calc(2px * -infinity); }",
8441    //   ".foo{width:calc(2px*-infinity)}",
8442    // );
8443    minify_test(".foo { width: calc(100px * sin(45deg))", ".foo{width:70.7107px}");
8444    minify_test(".foo { width: calc(100px * sin(.125turn))", ".foo{width:70.7107px}");
8445    minify_test(
8446      ".foo { width: calc(100px * sin(3.14159265 / 4))",
8447      ".foo{width:70.7107px}",
8448    );
8449    minify_test(".foo { width: calc(100px * sin(pi / 4))", ".foo{width:70.7107px}");
8450    minify_test(
8451      ".foo { width: calc(100px * sin(22deg + 23deg))",
8452      ".foo{width:70.7107px}",
8453    );
8454
8455    minify_test(".foo { width: calc(2px * cos(45deg))", ".foo{width:1.41421px}");
8456    minify_test(".foo { width: calc(2px * tan(45deg))", ".foo{width:2px}");
8457
8458    minify_test(".foo { rotate: asin(sin(45deg))", ".foo{rotate:45deg}");
8459    minify_test(".foo { rotate: asin(1)", ".foo{rotate:90deg}");
8460    minify_test(".foo { rotate: asin(-1)", ".foo{rotate:-90deg}");
8461    minify_test(".foo { rotate: asin(0.5)", ".foo{rotate:30deg}");
8462    minify_test(".foo { rotate: asin(45deg)", ".foo{rotate:asin(45deg)}"); // invalid
8463    minify_test(".foo { rotate: asin(-20)", ".foo{rotate:asin(-20)}"); // evaluates to NaN
8464    minify_test(".foo { width: asin(sin(45deg))", ".foo{width:asin(sin(45deg))}"); // invalid
8465
8466    minify_test(".foo { rotate: acos(cos(45deg))", ".foo{rotate:45deg}");
8467    minify_test(".foo { rotate: acos(-1)", ".foo{rotate:180deg}");
8468    minify_test(".foo { rotate: acos(0)", ".foo{rotate:90deg}");
8469    minify_test(".foo { rotate: acos(1)", ".foo{rotate:0deg}");
8470    minify_test(".foo { rotate: acos(45deg)", ".foo{rotate:acos(45deg)}"); // invalid
8471    minify_test(".foo { rotate: acos(-20)", ".foo{rotate:acos(-20)}"); // evaluates to NaN
8472
8473    minify_test(".foo { rotate: atan(tan(45deg))", ".foo{rotate:45deg}");
8474    minify_test(".foo { rotate: atan(1)", ".foo{rotate:45deg}");
8475    minify_test(".foo { rotate: atan(0)", ".foo{rotate:0deg}");
8476    minify_test(".foo { rotate: atan(45deg)", ".foo{rotate:atan(45deg)}"); // invalid
8477
8478    minify_test(".foo { rotate: atan2(1px, -1px)", ".foo{rotate:135deg}");
8479    minify_test(".foo { rotate: atan2(1vw, -1vw)", ".foo{rotate:135deg}");
8480    minify_test(".foo { rotate: atan2(1, -1)", ".foo{rotate:135deg}");
8481    minify_test(".foo { rotate: atan2(1ms, -1ms)", ".foo{rotate:135deg}");
8482    minify_test(".foo { rotate: atan2(1%, -1%)", ".foo{rotate:135deg}");
8483    minify_test(".foo { rotate: atan2(1deg, -1deg)", ".foo{rotate:135deg}");
8484    minify_test(".foo { rotate: atan2(1cm, 1mm)", ".foo{rotate:84.2894deg}");
8485    minify_test(".foo { rotate: atan2(0, -1)", ".foo{rotate:180deg}");
8486    minify_test(".foo { rotate: atan2(-1, 1)", ".foo{rotate:-45deg}");
8487    // incompatible units
8488    minify_test(".foo { rotate: atan2(1px, -1vw)", ".foo{rotate:atan2(1px, -1vw)}");
8489
8490    minify_test(".foo { transform: rotate(acos(1)) }", ".foo{transform:rotate(0)}");
8491    minify_test(".foo { transform: rotate(atan(0)) }", ".foo{transform:rotate(0)}");
8492  }
8493
8494  #[test]
8495  fn test_exp() {
8496    minify_test(".foo { width: hypot()", ".foo{width:hypot()}");
8497    minify_test(".foo { width: hypot(1px)", ".foo{width:1px}");
8498    minify_test(".foo { width: hypot(1px, 2px)", ".foo{width:2.23607px}");
8499    minify_test(".foo { width: hypot(1px, 2px, 3px)", ".foo{width:3.74166px}");
8500    minify_test(".foo { width: hypot(1px, 2vw)", ".foo{width:hypot(1px,2vw)}");
8501    minify_test(".foo { width: hypot(1px, 2px, 3vw)", ".foo{width:hypot(1px,2px,3vw)}");
8502    minify_test(".foo { width: calc(100px * hypot(3, 4))", ".foo{width:500px}");
8503    minify_test(".foo { width: calc(1px * pow(2, sqrt(100))", ".foo{width:1024px}");
8504    minify_test(".foo { width: calc(100px * pow(2, pow(2, 2)", ".foo{width:1600px}");
8505    minify_test(".foo { width: calc(1px * log(1))", ".foo{width:0}");
8506    minify_test(".foo { width: calc(1px * log(10, 10))", ".foo{width:1px}");
8507    minify_test(".foo { width: calc(1px * exp(0))", ".foo{width:1px}");
8508    minify_test(".foo { width: calc(1px * log(e))", ".foo{width:1px}");
8509    minify_test(".foo { width: calc(1px * (e - exp(1)))", ".foo{width:0}");
8510    minify_test(
8511      ".foo { width: calc(1px * (exp(log(1) + exp(0)*2))",
8512      ".foo{width:7.38906px}",
8513    );
8514  }
8515
8516  #[test]
8517  fn test_sign() {
8518    minify_test(".foo { width: abs(1px)", ".foo{width:1px}");
8519    minify_test(".foo { width: abs(-1px)", ".foo{width:1px}");
8520    minify_test(".foo { width: abs(1%)", ".foo{width:abs(1%)}"); // spec says percentages must be against resolved value
8521
8522    minify_test(".foo { width: calc(10px * sign(-1vw)", ".foo{width:-10px}");
8523    minify_test(
8524      ".foo { width: calc(10px * sign(1%)",
8525      ".foo{width:calc(10px * sign(1%))}",
8526    );
8527  }
8528
8529  #[test]
8530  fn test_box_shadow() {
8531    minify_test(
8532      ".foo { box-shadow: 64px 64px 12px 40px rgba(0,0,0,0.4) }",
8533      ".foo{box-shadow:64px 64px 12px 40px #0006}",
8534    );
8535    minify_test(
8536      ".foo { box-shadow: 12px 12px 0px 8px rgba(0,0,0,0.4) inset }",
8537      ".foo{box-shadow:inset 12px 12px 0 8px #0006}",
8538    );
8539    minify_test(
8540      ".foo { box-shadow: inset 12px 12px 0px 8px rgba(0,0,0,0.4) }",
8541      ".foo{box-shadow:inset 12px 12px 0 8px #0006}",
8542    );
8543    minify_test(
8544      ".foo { box-shadow: 12px 12px 8px 0px rgba(0,0,0,0.4) }",
8545      ".foo{box-shadow:12px 12px 8px #0006}",
8546    );
8547    minify_test(
8548      ".foo { box-shadow: 12px 12px 0px 0px rgba(0,0,0,0.4) }",
8549      ".foo{box-shadow:12px 12px #0006}",
8550    );
8551    minify_test(
8552      ".foo { box-shadow: 64px 64px 12px 40px rgba(0,0,0,0.4), 12px 12px 0px 8px rgba(0,0,0,0.4) inset }",
8553      ".foo{box-shadow:64px 64px 12px 40px #0006,inset 12px 12px 0 8px #0006}",
8554    );
8555
8556    prefix_test(
8557      ".foo { box-shadow: 12px 12px lab(40% 56.6 39) }",
8558      indoc! { r#"
8559        .foo {
8560          box-shadow: 12px 12px #b32323;
8561          box-shadow: 12px 12px lab(40% 56.6 39);
8562        }
8563      "#},
8564      Browsers {
8565        chrome: Some(90 << 16),
8566        ..Browsers::default()
8567      },
8568    );
8569
8570    prefix_test(
8571      ".foo { box-shadow: 12px 12px lab(40% 56.6 39) }",
8572      indoc! { r#"
8573        .foo {
8574          -webkit-box-shadow: 12px 12px #b32323;
8575          box-shadow: 12px 12px #b32323;
8576          box-shadow: 12px 12px lab(40% 56.6 39);
8577        }
8578      "#},
8579      Browsers {
8580        chrome: Some(4 << 16),
8581        ..Browsers::default()
8582      },
8583    );
8584
8585    prefix_test(
8586      ".foo { box-shadow: 12px 12px lab(40% 56.6 39), 12px 12px yellow }",
8587      indoc! { r#"
8588        .foo {
8589          -webkit-box-shadow: 12px 12px #b32323, 12px 12px #ff0;
8590          box-shadow: 12px 12px #b32323, 12px 12px #ff0;
8591          box-shadow: 12px 12px lab(40% 56.6 39), 12px 12px #ff0;
8592        }
8593      "#},
8594      Browsers {
8595        chrome: Some(4 << 16),
8596        ..Browsers::default()
8597      },
8598    );
8599
8600    prefix_test(
8601      ".foo { -webkit-box-shadow: 12px 12px #0006 }",
8602      indoc! { r#"
8603        .foo {
8604          -webkit-box-shadow: 12px 12px rgba(0, 0, 0, .4);
8605        }
8606      "#},
8607      Browsers {
8608        chrome: Some(4 << 16),
8609        ..Browsers::default()
8610      },
8611    );
8612
8613    prefix_test(
8614      ".foo {
8615        -webkit-box-shadow: 12px 12px #0006;
8616        -moz-box-shadow: 12px 12px #0009;
8617      }",
8618      indoc! { r#"
8619        .foo {
8620          -webkit-box-shadow: 12px 12px rgba(0, 0, 0, .4);
8621          -moz-box-shadow: 12px 12px rgba(0, 0, 0, .6);
8622        }
8623      "#},
8624      Browsers {
8625        chrome: Some(4 << 16),
8626        ..Browsers::default()
8627      },
8628    );
8629
8630    prefix_test(
8631      ".foo {
8632        -webkit-box-shadow: 12px 12px #0006;
8633        -moz-box-shadow: 12px 12px #0006;
8634        box-shadow: 12px 12px #0006;
8635      }",
8636      indoc! { r#"
8637        .foo {
8638          box-shadow: 12px 12px #0006;
8639        }
8640      "#},
8641      Browsers {
8642        chrome: Some(95 << 16),
8643        ..Browsers::default()
8644      },
8645    );
8646
8647    prefix_test(
8648      ".foo { box-shadow: var(--foo) 12px lab(40% 56.6 39) }",
8649      indoc! { r#"
8650        .foo {
8651          box-shadow: var(--foo) 12px #b32323;
8652        }
8653
8654        @supports (color: lab(0% 0 0)) {
8655          .foo {
8656            box-shadow: var(--foo) 12px lab(40% 56.6 39);
8657          }
8658        }
8659      "#},
8660      Browsers {
8661        chrome: Some(90 << 16),
8662        ..Browsers::default()
8663      },
8664    );
8665
8666    prefix_test(
8667      r#"
8668      .foo {
8669        box-shadow: 0px 0px 22px red;
8670        box-shadow: 0px 0px max(2cqw, 22px) red;
8671      }
8672    "#,
8673      indoc! {r#"
8674      .foo {
8675        box-shadow: 0 0 22px red;
8676        box-shadow: 0 0 max(2cqw, 22px) red;
8677      }
8678    "#
8679      },
8680      Browsers {
8681        safari: Some(14 << 16),
8682        ..Browsers::default()
8683      },
8684    );
8685    prefix_test(
8686      r#"
8687      .foo {
8688        box-shadow: 0px 0px 22px red;
8689        box-shadow: 0px 0px max(2cqw, 22px) red;
8690      }
8691    "#,
8692      indoc! {r#"
8693      .foo {
8694        box-shadow: 0 0 max(2cqw, 22px) red;
8695      }
8696    "#
8697      },
8698      Browsers {
8699        safari: Some(16 << 16),
8700        ..Browsers::default()
8701      },
8702    );
8703
8704    prefix_test(
8705      r#"
8706      .foo {
8707        box-shadow: 0px 0px 22px red;
8708        box-shadow: 0px 0px 22px lab(40% 56.6 39);
8709      }
8710    "#,
8711      indoc! {r#"
8712      .foo {
8713        box-shadow: 0 0 22px red;
8714        box-shadow: 0 0 22px lab(40% 56.6 39);
8715      }
8716    "#
8717      },
8718      Browsers {
8719        safari: Some(14 << 16),
8720        ..Browsers::default()
8721      },
8722    );
8723    prefix_test(
8724      r#"
8725      .foo {
8726        box-shadow: 0px 0px 22px red;
8727        box-shadow: 0px 0px 22px lab(40% 56.6 39);
8728      }
8729    "#,
8730      indoc! {r#"
8731      .foo {
8732        box-shadow: 0 0 22px lab(40% 56.6 39);
8733      }
8734    "#
8735      },
8736      Browsers {
8737        safari: Some(16 << 16),
8738        ..Browsers::default()
8739      },
8740    );
8741
8742    prefix_test(
8743      r#"
8744      .foo {
8745        box-shadow: var(--fallback);
8746        box-shadow: 0px 0px 22px lab(40% 56.6 39);
8747      }
8748    "#,
8749      indoc! {r#"
8750      .foo {
8751        box-shadow: var(--fallback);
8752        box-shadow: 0 0 22px lab(40% 56.6 39);
8753      }
8754    "#
8755      },
8756      Browsers {
8757        safari: Some(16 << 16),
8758        ..Browsers::default()
8759      },
8760    );
8761  }
8762
8763  #[test]
8764  fn test_selector_compatibility() {
8765    fn selectors(source: &str) -> crate::selector::SelectorList<'_> {
8766      let stylesheet = StyleSheet::parse(
8767        source,
8768        ParserOptions {
8769          flags: ParserFlags::SCROLL_NAVIGATION_CONTROLS,
8770          ..ParserOptions::default()
8771        },
8772      )
8773      .unwrap();
8774      match &stylesheet.rules.0[0] {
8775        CssRule::Style(rule) => rule.selectors.clone(),
8776        _ => unreachable!(),
8777      }
8778    }
8779
8780    let target_current = selectors("a:target-current { color: green }");
8781    assert!(!crate::selector::is_compatible(
8782      &target_current.0,
8783      Browsers {
8784        chrome: Some(134 << 16),
8785        ..Browsers::default()
8786      }
8787      .into()
8788    ));
8789    assert!(crate::selector::is_compatible(
8790      &target_current.0,
8791      Browsers {
8792        chrome: Some(135 << 16),
8793        ..Browsers::default()
8794      }
8795      .into()
8796    ));
8797
8798    let target_before = selectors("a:target-before { color: green }");
8799    assert!(!crate::selector::is_compatible(
8800      &target_before.0,
8801      Browsers {
8802        chrome: Some(141 << 16),
8803        ..Browsers::default()
8804      }
8805      .into()
8806    ));
8807    assert!(crate::selector::is_compatible(
8808      &target_before.0,
8809      Browsers {
8810        chrome: Some(142 << 16),
8811        ..Browsers::default()
8812      }
8813      .into()
8814    ));
8815
8816    let target_after = selectors("a:target-after { color: green }");
8817    assert!(crate::selector::is_compatible(
8818      &target_after.0,
8819      Browsers {
8820        chrome: Some(142 << 16),
8821        ..Browsers::default()
8822      }
8823      .into()
8824    ));
8825  }
8826
8827  #[test]
8828  fn test_media() {
8829    minify_test(
8830      "@media (min-width: 240px) { .foo { color: chartreuse }}",
8831      "@media (width>=240px){.foo{color:#7fff00}}",
8832    );
8833    minify_test(
8834      "@media (width < 240px) { .foo { color: chartreuse }}",
8835      "@media (width<240px){.foo{color:#7fff00}}",
8836    );
8837    minify_test(
8838      "@media (width <= 240px) { .foo { color: chartreuse }}",
8839      "@media (width<=240px){.foo{color:#7fff00}}",
8840    );
8841    minify_test(
8842      "@media (width > 240px) { .foo { color: chartreuse }}",
8843      "@media (width>240px){.foo{color:#7fff00}}",
8844    );
8845    minify_test(
8846      "@media (width >= 240px) { .foo { color: chartreuse }}",
8847      "@media (width>=240px){.foo{color:#7fff00}}",
8848    );
8849    minify_test(
8850      "@media (240px < width) { .foo { color: chartreuse }}",
8851      "@media (width>240px){.foo{color:#7fff00}}",
8852    );
8853    minify_test(
8854      "@media (240px <= width) { .foo { color: chartreuse }}",
8855      "@media (width>=240px){.foo{color:#7fff00}}",
8856    );
8857    minify_test(
8858      "@media (240px > width) { .foo { color: chartreuse }}",
8859      "@media (width<240px){.foo{color:#7fff00}}",
8860    );
8861    minify_test(
8862      "@media (240px >= width) { .foo { color: chartreuse }}",
8863      "@media (width<=240px){.foo{color:#7fff00}}",
8864    );
8865    minify_test(
8866      "@media (100px < width < 200px) { .foo { color: chartreuse }}",
8867      "@media (100px<width<200px){.foo{color:#7fff00}}",
8868    );
8869    minify_test(
8870      "@media (100px <= width <= 200px) { .foo { color: chartreuse }}",
8871      "@media (100px<=width<=200px){.foo{color:#7fff00}}",
8872    );
8873    minify_test(
8874      "@media (min-width: 30em) and (max-width: 50em) { .foo { color: chartreuse }}",
8875      "@media (width>=30em) and (width<=50em){.foo{color:#7fff00}}",
8876    );
8877    minify_test(
8878      "@media screen, print { .foo { color: chartreuse }}",
8879      "@media screen,print{.foo{color:#7fff00}}",
8880    );
8881    minify_test(
8882      "@media (hover: hover) { .foo { color: chartreuse }}",
8883      "@media (hover:hover){.foo{color:#7fff00}}",
8884    );
8885    minify_test(
8886      "@media (hover) { .foo { color: chartreuse }}",
8887      "@media (hover){.foo{color:#7fff00}}",
8888    );
8889    minify_test(
8890      "@media (aspect-ratio: 11/5) { .foo { color: chartreuse }}",
8891      "@media (aspect-ratio:11/5){.foo{color:#7fff00}}",
8892    );
8893    minify_test(
8894      "@media (aspect-ratio: 2/1) { .foo { color: chartreuse }}",
8895      "@media (aspect-ratio:2){.foo{color:#7fff00}}",
8896    );
8897    minify_test(
8898      "@media (aspect-ratio: 2) { .foo { color: chartreuse }}",
8899      "@media (aspect-ratio:2){.foo{color:#7fff00}}",
8900    );
8901    minify_test(
8902      "@media not screen and (color) { .foo { color: chartreuse }}",
8903      "@media not screen and (color){.foo{color:#7fff00}}",
8904    );
8905    minify_test(
8906      "@media only screen and (color) { .foo { color: chartreuse }}",
8907      "@media only screen and (color){.foo{color:#7fff00}}",
8908    );
8909    minify_test(
8910      "@media (update: slow) or (hover: none) { .foo { color: chartreuse }}",
8911      "@media (update:slow) or (hover:none){.foo{color:#7fff00}}",
8912    );
8913    minify_test(
8914      "@media (width < 600px) and (height < 600px) { .foo { color: chartreuse }}",
8915      "@media (width<600px) and (height<600px){.foo{color:#7fff00}}",
8916    );
8917    minify_test(
8918      "@media (not (color)) or (hover) { .foo { color: chartreuse }}",
8919      "@media (not (color)) or (hover){.foo{color:#7fff00}}",
8920    );
8921    error_test(
8922      "@media (example, all,), speech { .foo { color: chartreuse }}",
8923      ParserError::UnexpectedToken(Token::Comma),
8924    );
8925    error_test(
8926      "@media &test, speech { .foo { color: chartreuse }}",
8927      ParserError::UnexpectedToken(Token::Delim('&')),
8928    );
8929    error_test(
8930      "@media &test { .foo { color: chartreuse }}",
8931      ParserError::UnexpectedToken(Token::Delim('&')),
8932    );
8933    minify_test(
8934      "@media (min-width: calc(200px + 40px)) { .foo { color: chartreuse }}",
8935      "@media (width>=240px){.foo{color:#7fff00}}",
8936    );
8937    minify_test(
8938      "@media (min-width: calc(1em + 5px)) { .foo { color: chartreuse }}",
8939      "@media (width>=calc(1em + 5px)){.foo{color:#7fff00}}",
8940    );
8941    minify_test("@media { .foo { color: chartreuse }}", ".foo{color:#7fff00}");
8942    minify_test("@media all { .foo { color: chartreuse }}", ".foo{color:#7fff00}");
8943    minify_test(
8944      "@media not (((color) or (hover))) { .foo { color: chartreuse }}",
8945      "@media not ((color) or (hover)){.foo{color:#7fff00}}",
8946    );
8947    minify_test(
8948      "@media (hover) and ((color) and (test)) { .foo { color: chartreuse }}",
8949      "@media (hover) and (color) and (test){.foo{color:#7fff00}}",
8950    );
8951    minify_test(
8952      "@media (grid: 1) { .foo { color: chartreuse }}",
8953      "@media (grid:1){.foo{color:#7fff00}}",
8954    );
8955    minify_test(
8956      "@media (width >= calc(2px + 4px)) { .foo { color: chartreuse }}",
8957      "@media (width>=6px){.foo{color:#7fff00}}",
8958    );
8959
8960    prefix_test(
8961      r#"
8962        @media (width >= 240px) {
8963          .foo {
8964            color: chartreuse;
8965          }
8966        }
8967      "#,
8968      indoc! { r#"
8969        @media (min-width: 240px) {
8970          .foo {
8971            color: #7fff00;
8972          }
8973        }
8974      "#},
8975      Browsers {
8976        firefox: Some(60 << 16),
8977        ..Browsers::default()
8978      },
8979    );
8980
8981    prefix_test(
8982      r#"
8983        @media (width >= 240px) {
8984          .foo {
8985            color: chartreuse;
8986          }
8987        }
8988      "#,
8989      indoc! { r#"
8990        @media (width >= 240px) {
8991          .foo {
8992            color: #7fff00;
8993          }
8994        }
8995      "#},
8996      Browsers {
8997        firefox: Some(64 << 16),
8998        ..Browsers::default()
8999      },
9000    );
9001
9002    prefix_test(
9003      r#"
9004        @media (color > 2) {
9005          .foo {
9006            color: chartreuse;
9007          }
9008        }
9009      "#,
9010      indoc! { r#"
9011        @media not (max-color: 2) {
9012          .foo {
9013            color: #7fff00;
9014          }
9015        }
9016      "#},
9017      Browsers {
9018        firefox: Some(60 << 16),
9019        ..Browsers::default()
9020      },
9021    );
9022
9023    prefix_test(
9024      r#"
9025        @media (color < 2) {
9026          .foo {
9027            color: chartreuse;
9028          }
9029        }
9030      "#,
9031      indoc! { r#"
9032        @media not (min-color: 2) {
9033          .foo {
9034            color: #7fff00;
9035          }
9036        }
9037      "#},
9038      Browsers {
9039        firefox: Some(60 << 16),
9040        ..Browsers::default()
9041      },
9042    );
9043
9044    prefix_test(
9045      r#"
9046        @media (width > 240px) {
9047          .foo {
9048            color: chartreuse;
9049          }
9050        }
9051      "#,
9052      indoc! { r#"
9053        @media not (max-width: 240px) {
9054          .foo {
9055            color: #7fff00;
9056          }
9057        }
9058      "#},
9059      Browsers {
9060        firefox: Some(60 << 16),
9061        ..Browsers::default()
9062      },
9063    );
9064
9065    prefix_test(
9066      r#"
9067        @media (width <= 240px) {
9068          .foo {
9069            color: chartreuse;
9070          }
9071        }
9072      "#,
9073      indoc! { r#"
9074        @media (max-width: 240px) {
9075          .foo {
9076            color: #7fff00;
9077          }
9078        }
9079      "#},
9080      Browsers {
9081        firefox: Some(60 << 16),
9082        ..Browsers::default()
9083      },
9084    );
9085
9086    prefix_test(
9087      r#"
9088        @media (width <= 240px) {
9089          .foo {
9090            color: chartreuse;
9091          }
9092        }
9093      "#,
9094      indoc! { r#"
9095        @media (width <= 240px) {
9096          .foo {
9097            color: #7fff00;
9098          }
9099        }
9100      "#},
9101      Browsers {
9102        firefox: Some(64 << 16),
9103        ..Browsers::default()
9104      },
9105    );
9106
9107    prefix_test(
9108      r#"
9109        @media (width < 240px) {
9110          .foo {
9111            color: chartreuse;
9112          }
9113        }
9114      "#,
9115      indoc! { r#"
9116        @media not (min-width: 240px) {
9117          .foo {
9118            color: #7fff00;
9119          }
9120        }
9121      "#},
9122      Browsers {
9123        firefox: Some(60 << 16),
9124        ..Browsers::default()
9125      },
9126    );
9127
9128    prefix_test(
9129      r#"
9130        @media not (width < 240px) {
9131          .foo {
9132            color: chartreuse;
9133          }
9134        }
9135      "#,
9136      indoc! { r#"
9137        @media (min-width: 240px) {
9138          .foo {
9139            color: #7fff00;
9140          }
9141        }
9142      "#},
9143      Browsers {
9144        firefox: Some(60 << 16),
9145        ..Browsers::default()
9146      },
9147    );
9148
9149    test(
9150      r#"
9151        @media not (width < 240px) {
9152          .foo {
9153            color: chartreuse;
9154          }
9155        }
9156      "#,
9157      indoc! { r#"
9158        @media (width >= 240px) {
9159          .foo {
9160            color: #7fff00;
9161          }
9162        }
9163      "#},
9164    );
9165
9166    prefix_test(
9167      r#"
9168        @media (width < 240px) and (hover) {
9169          .foo {
9170            color: chartreuse;
9171          }
9172        }
9173      "#,
9174      indoc! { r#"
9175        @media (not (min-width: 240px)) and (hover) {
9176          .foo {
9177            color: #7fff00;
9178          }
9179        }
9180      "#},
9181      Browsers {
9182        firefox: Some(60 << 16),
9183        ..Browsers::default()
9184      },
9185    );
9186
9187    prefix_test(
9188      r#"
9189        @media (100px <= width <= 200px) {
9190          .foo {
9191            color: chartreuse;
9192          }
9193        }
9194      "#,
9195      indoc! { r#"
9196        @media (min-width: 100px) and (max-width: 200px) {
9197          .foo {
9198            color: #7fff00;
9199          }
9200        }
9201      "#},
9202      Browsers {
9203        firefox: Some(85 << 16),
9204        ..Browsers::default()
9205      },
9206    );
9207
9208    prefix_test(
9209      r#"
9210        @media not (100px <= width <= 200px) {
9211          .foo {
9212            color: chartreuse;
9213          }
9214        }
9215      "#,
9216      indoc! { r#"
9217        @media not ((min-width: 100px) and (max-width: 200px)) {
9218          .foo {
9219            color: #7fff00;
9220          }
9221        }
9222      "#},
9223      Browsers {
9224        firefox: Some(85 << 16),
9225        ..Browsers::default()
9226      },
9227    );
9228
9229    prefix_test(
9230      r#"
9231        @media (hover) and (100px <= width <= 200px) {
9232          .foo {
9233            color: chartreuse;
9234          }
9235        }
9236      "#,
9237      indoc! { r#"
9238        @media (hover) and (min-width: 100px) and (max-width: 200px) {
9239          .foo {
9240            color: #7fff00;
9241          }
9242        }
9243      "#},
9244      Browsers {
9245        firefox: Some(85 << 16),
9246        ..Browsers::default()
9247      },
9248    );
9249
9250    prefix_test(
9251      r#"
9252        @media (hover) or (100px <= width <= 200px) {
9253          .foo {
9254            color: chartreuse;
9255          }
9256        }
9257      "#,
9258      indoc! { r#"
9259        @media (hover) or ((min-width: 100px) and (max-width: 200px)) {
9260          .foo {
9261            color: #7fff00;
9262          }
9263        }
9264      "#},
9265      Browsers {
9266        firefox: Some(85 << 16),
9267        ..Browsers::default()
9268      },
9269    );
9270
9271    prefix_test(
9272      r#"
9273        @media (100px < width < 200px) {
9274          .foo {
9275            color: chartreuse;
9276          }
9277        }
9278      "#,
9279      indoc! { r#"
9280        @media (not (max-width: 100px)) and (not (min-width: 200px)) {
9281          .foo {
9282            color: #7fff00;
9283          }
9284        }
9285      "#},
9286      Browsers {
9287        firefox: Some(85 << 16),
9288        ..Browsers::default()
9289      },
9290    );
9291
9292    prefix_test(
9293      r#"
9294        @media not (100px < width < 200px) {
9295          .foo {
9296            color: chartreuse;
9297          }
9298        }
9299      "#,
9300      indoc! { r#"
9301        @media not ((not (max-width: 100px)) and (not (min-width: 200px))) {
9302          .foo {
9303            color: #7fff00;
9304          }
9305        }
9306      "#},
9307      Browsers {
9308        firefox: Some(85 << 16),
9309        ..Browsers::default()
9310      },
9311    );
9312
9313    prefix_test(
9314      r#"
9315        @media (200px >= width >= 100px) {
9316          .foo {
9317            color: chartreuse;
9318          }
9319        }
9320      "#,
9321      indoc! { r#"
9322        @media (max-width: 200px) and (min-width: 100px) {
9323          .foo {
9324            color: #7fff00;
9325          }
9326        }
9327      "#},
9328      Browsers {
9329        firefox: Some(85 << 16),
9330        ..Browsers::default()
9331      },
9332    );
9333
9334    test(
9335      r#"
9336      @media not all {
9337        .a {
9338          color: green;
9339        }
9340      }
9341      "#,
9342      "\n",
9343    );
9344
9345    prefix_test(
9346      r#"
9347      @media (width > calc(1px + 1rem)) {
9348        .foo { color: yellow; }
9349      }
9350      "#,
9351      indoc! { r#"
9352        @media not (max-width: calc(1px + 1rem)) {
9353          .foo {
9354            color: #ff0;
9355          }
9356        }
9357      "#},
9358      Browsers {
9359        chrome: Some(85 << 16),
9360        ..Browsers::default()
9361      },
9362    );
9363    prefix_test(
9364      r#"
9365      @media (width > max(10px, 1rem)) {
9366        .foo { color: yellow; }
9367      }
9368      "#,
9369      indoc! { r#"
9370        @media not (max-width: max(10px, 1rem)) {
9371          .foo {
9372            color: #ff0;
9373          }
9374        }
9375      "#},
9376      Browsers {
9377        chrome: Some(85 << 16),
9378        ..Browsers::default()
9379      },
9380    );
9381    prefix_test(
9382      r#"
9383      @media (width > 0) {
9384        .foo { color: yellow; }
9385      }
9386      "#,
9387      indoc! { r#"
9388        @media not (max-width: 0) {
9389          .foo {
9390            color: #ff0;
9391          }
9392        }
9393      "#},
9394      Browsers {
9395        chrome: Some(85 << 16),
9396        ..Browsers::default()
9397      },
9398    );
9399    prefix_test(
9400      r#"
9401      @media (min-resolution: 2dppx) {
9402        .foo { color: yellow; }
9403      }
9404      "#,
9405      indoc! { r#"
9406        @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 2dppx) {
9407          .foo {
9408            color: #ff0;
9409          }
9410        }
9411      "#},
9412      Browsers {
9413        safari: Some(15 << 16),
9414        ..Browsers::default()
9415      },
9416    );
9417    prefix_test(
9418      r#"
9419      @media (min-resolution: 2dppx) {
9420        .foo { color: yellow; }
9421      }
9422      "#,
9423      indoc! { r#"
9424        @media (min--moz-device-pixel-ratio: 2), (min-resolution: 2dppx) {
9425          .foo {
9426            color: #ff0;
9427          }
9428        }
9429      "#},
9430      Browsers {
9431        firefox: Some(10 << 16),
9432        ..Browsers::default()
9433      },
9434    );
9435    prefix_test(
9436      r#"
9437      @media (resolution > 2dppx) {
9438        .foo { color: yellow; }
9439      }
9440      "#,
9441      indoc! { r#"
9442        @media not (-webkit-max-device-pixel-ratio: 2), not (max-resolution: 2dppx) {
9443          .foo {
9444            color: #ff0;
9445          }
9446        }
9447      "#},
9448      Browsers {
9449        safari: Some(15 << 16),
9450        ..Browsers::default()
9451      },
9452    );
9453    prefix_test(
9454      r#"
9455      @media (resolution >= 300dpi) {
9456        .foo { color: yellow; }
9457      }
9458      "#,
9459      indoc! { r#"
9460        @media (-webkit-min-device-pixel-ratio: 3.125), (min-resolution: 300dpi) {
9461          .foo {
9462            color: #ff0;
9463          }
9464        }
9465      "#},
9466      Browsers {
9467        safari: Some(15 << 16),
9468        ..Browsers::default()
9469      },
9470    );
9471    prefix_test(
9472      r#"
9473      @media (min-resolution: 113.38dpcm) {
9474        .foo { color: yellow; }
9475      }
9476      "#,
9477      indoc! { r#"
9478        @media (-webkit-min-device-pixel-ratio: 2.99985), (min--moz-device-pixel-ratio: 2.99985), (min-resolution: 113.38dpcm) {
9479          .foo {
9480            color: #ff0;
9481          }
9482        }
9483      "#},
9484      Browsers {
9485        safari: Some(15 << 16),
9486        firefox: Some(10 << 16),
9487        ..Browsers::default()
9488      },
9489    );
9490    prefix_test(
9491      r#"
9492      @media (color) and (min-resolution: 2dppx) {
9493        .foo { color: yellow; }
9494      }
9495      "#,
9496      indoc! { r#"
9497        @media (color) and (-webkit-min-device-pixel-ratio: 2), (color) and (min-resolution: 2dppx) {
9498          .foo {
9499            color: #ff0;
9500          }
9501        }
9502      "#},
9503      Browsers {
9504        safari: Some(15 << 16),
9505        ..Browsers::default()
9506      },
9507    );
9508    prefix_test(
9509      r#"
9510      @media (min-resolution: 2dppx),
9511             (min-resolution: 192dpi) {
9512        .foo { color: yellow; }
9513      }
9514      "#,
9515      indoc! { r#"
9516        @media (-webkit-min-device-pixel-ratio: 2), (min--moz-device-pixel-ratio: 2), (min-resolution: 2dppx), (min-resolution: 192dpi) {
9517          .foo {
9518            color: #ff0;
9519          }
9520        }
9521      "#},
9522      Browsers {
9523        safari: Some(15 << 16),
9524        firefox: Some(10 << 16),
9525        ..Browsers::default()
9526      },
9527    );
9528    prefix_test(
9529      r#"
9530      @media only screen and (min-resolution: 124.8dpi) {
9531        .foo { color: yellow; }
9532      }
9533      "#,
9534      indoc! { r#"
9535        @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) {
9536          .foo {
9537            color: #ff0;
9538          }
9539        }
9540      "#},
9541      Browsers {
9542        safari: Some(15 << 16),
9543        firefox: Some(10 << 16),
9544        ..Browsers::default()
9545      },
9546    );
9547
9548    test_with_printer_options(
9549      r#"
9550        @media (width < 256px) or (hover: none) {
9551          .foo {
9552            color: #fff;
9553          }
9554        }
9555      "#,
9556      indoc! { r#"
9557        @media (not (min-width: 256px)) or (hover: none) {
9558          .foo {
9559            color: #fff;
9560          }
9561        }
9562      "#},
9563      PrinterOptions {
9564        targets: Targets {
9565          browsers: None,
9566          include: Features::MediaRangeSyntax,
9567          exclude: Features::empty(),
9568        },
9569        ..Default::default()
9570      },
9571    );
9572
9573    error_test(
9574      "@media (min-width: hi) { .foo { color: chartreuse }}",
9575      ParserError::InvalidMediaQuery,
9576    );
9577    error_test(
9578      "@media (width >= hi) { .foo { color: chartreuse }}",
9579      ParserError::InvalidMediaQuery,
9580    );
9581    error_test(
9582      "@media (width >= 2/1) { .foo { color: chartreuse }}",
9583      ParserError::UnexpectedToken(Token::Delim('/')),
9584    );
9585    error_test(
9586      "@media (600px <= min-height) { .foo { color: chartreuse }}",
9587      ParserError::InvalidMediaQuery,
9588    );
9589    error_test(
9590      "@media (scan >= 1) { .foo { color: chartreuse }}",
9591      ParserError::InvalidMediaQuery,
9592    );
9593    error_test(
9594      "@media (min-scan: interlace) { .foo { color: chartreuse }}",
9595      ParserError::InvalidMediaQuery,
9596    );
9597    error_test(
9598      "@media (1px <= width <= bar) { .foo { color: chartreuse }}",
9599      ParserError::InvalidMediaQuery,
9600    );
9601    error_test(
9602      "@media (1px <= min-width <= 2px) { .foo { color: chartreuse }}",
9603      ParserError::InvalidMediaQuery,
9604    );
9605    error_test(
9606      "@media (1px <= scan <= 2px) { .foo { color: chartreuse }}",
9607      ParserError::InvalidMediaQuery,
9608    );
9609    error_test(
9610      "@media (grid: 10) { .foo { color: chartreuse }}",
9611      ParserError::InvalidMediaQuery,
9612    );
9613    error_test(
9614      "@media (prefers-color-scheme = dark) { .foo { color: chartreuse }}",
9615      ParserError::InvalidMediaQuery,
9616    );
9617    error_test(
9618      "@media unknown(foo) {}",
9619      ParserError::UnexpectedToken(crate::properties::custom::Token::Function("unknown".into())),
9620    );
9621
9622    // empty brackets should return a clearer error message
9623    error_test("@media () {}", ParserError::EmptyBracketInCondition);
9624    error_test("@media screen and () {}", ParserError::EmptyBracketInCondition);
9625
9626    error_recovery_test("@media unknown(foo) {}");
9627  }
9628
9629  #[test]
9630  fn test_merge_layers() {
9631    test(
9632      r#"
9633      @layer foo {
9634        .foo {
9635          color: red;
9636        }
9637      }
9638      @layer foo {
9639        .foo {
9640          background: #fff;
9641        }
9642
9643        .baz {
9644          color: #fff;
9645        }
9646      }
9647      "#,
9648      indoc! {r#"
9649      @layer foo {
9650        .foo {
9651          color: red;
9652          background: #fff;
9653        }
9654
9655        .baz {
9656          color: #fff;
9657        }
9658      }
9659    "#},
9660    );
9661    test(
9662      r#"
9663      @layer a {}
9664      @layer b {}
9665
9666      @layer b {
9667        foo {
9668          color: red;
9669        }
9670      }
9671
9672      @layer a {
9673        bar {
9674          color: yellow;
9675        }
9676      }
9677      "#,
9678      indoc! {r#"
9679      @layer a {
9680        bar {
9681          color: #ff0;
9682        }
9683      }
9684
9685      @layer b {
9686        foo {
9687          color: red;
9688        }
9689      }
9690    "#},
9691    );
9692
9693    test(
9694      r#"
9695      @layer a {}
9696      @layer b {}
9697
9698      @layer b {
9699        foo {
9700          color: red;
9701        }
9702      }
9703      "#,
9704      indoc! {r#"
9705      @layer a;
9706
9707      @layer b {
9708        foo {
9709          color: red;
9710        }
9711      }
9712    "#},
9713    );
9714
9715    test(
9716      r#"
9717      @layer a;
9718      @layer b;
9719      @layer c;
9720      "#,
9721      indoc! {r#"
9722      @layer a, b, c;
9723    "#},
9724    );
9725
9726    test(
9727      r#"
9728      @layer a {}
9729      @layer b {}
9730      @layer c {}
9731      "#,
9732      indoc! {r#"
9733      @layer a, b, c;
9734    "#},
9735    );
9736
9737    test(
9738      r#"
9739      @layer a;
9740      @layer b {
9741        .foo {
9742          color: red;
9743        }
9744      }
9745      @layer c {}
9746      "#,
9747      indoc! {r#"
9748      @layer a;
9749
9750      @layer b {
9751        .foo {
9752          color: red;
9753        }
9754      }
9755
9756      @layer c;
9757    "#},
9758    );
9759
9760    test(
9761      r#"
9762      @layer a, b;
9763      @layer c {}
9764
9765      @layer d {
9766        foo {
9767          color: red;
9768        }
9769      }
9770      "#,
9771      indoc! {r#"
9772      @layer a, b, c;
9773
9774      @layer d {
9775        foo {
9776          color: red;
9777        }
9778      }
9779    "#},
9780    );
9781
9782    test(
9783      r#"
9784      @layer a;
9785      @layer b;
9786      @import "a.css" layer(x);
9787      @layer c;
9788
9789      @layer d {
9790        foo {
9791          color: red;
9792        }
9793      }
9794      "#,
9795      indoc! {r#"
9796      @layer a, b;
9797      @import "a.css" layer(x);
9798      @layer c;
9799
9800      @layer d {
9801        foo {
9802          color: red;
9803        }
9804      }
9805    "#},
9806    );
9807
9808    test(
9809      r#"
9810      @layer a, b, c;
9811
9812      @layer a {
9813        foo {
9814          color: red;
9815        }
9816      }
9817      "#,
9818      indoc! {r#"
9819      @layer a {
9820        foo {
9821          color: red;
9822        }
9823      }
9824
9825      @layer b, c;
9826    "#},
9827    );
9828
9829    test(
9830      r#"
9831      @layer a;
9832      @import "foo.css";
9833
9834      @layer a {
9835        foo {
9836          color: red;
9837        }
9838      }
9839      "#,
9840      indoc! {r#"
9841      @layer a;
9842      @import "foo.css";
9843
9844      @layer a {
9845        foo {
9846          color: red;
9847        }
9848      }
9849    "#},
9850    );
9851  }
9852
9853  #[test]
9854  fn test_merge_rules() {
9855    test(
9856      r#"
9857      .foo {
9858        color: red;
9859      }
9860      .bar {
9861        color: red;
9862      }
9863    "#,
9864      indoc! {r#"
9865      .foo, .bar {
9866        color: red;
9867      }
9868    "#},
9869    );
9870    test(
9871      r#"
9872      .foo {
9873        color: red;
9874      }
9875      .foo {
9876        background: green;
9877      }
9878    "#,
9879      indoc! {r#"
9880      .foo {
9881        color: red;
9882        background: green;
9883      }
9884    "#},
9885    );
9886    test(
9887      r#"
9888      .foo {
9889        color: red;
9890      }
9891      .foo {
9892        background: green !important;
9893      }
9894    "#,
9895      indoc! {r#"
9896      .foo {
9897        color: red;
9898        background: green !important;
9899      }
9900    "#},
9901    );
9902    test(
9903      r#"
9904      .foo {
9905        background: red;
9906      }
9907      .foo {
9908        background: green;
9909      }
9910    "#,
9911      indoc! {r#"
9912      .foo {
9913        background: green;
9914      }
9915    "#},
9916    );
9917    test(
9918      r#"
9919      .foo {
9920        --foo: red;
9921        --foo: purple;
9922      }
9923      .foo {
9924        --foo: green;
9925      }
9926    "#,
9927      indoc! {r#"
9928      .foo {
9929        --foo: green;
9930      }
9931    "#},
9932    );
9933    test(
9934      r#"
9935      .foo {
9936        color: red;
9937      }
9938
9939      .bar {
9940        background: green;
9941      }
9942    "#,
9943      indoc! {r#"
9944      .foo {
9945        color: red;
9946      }
9947
9948      .bar {
9949        background: green;
9950      }
9951    "#},
9952    );
9953    test(
9954      r#"
9955      .foo {
9956        color: red;
9957      }
9958
9959      .baz {
9960        color: blue;
9961      }
9962
9963      .bar {
9964        color: red;
9965      }
9966    "#,
9967      indoc! {r#"
9968      .foo {
9969        color: red;
9970      }
9971
9972      .baz {
9973        color: #00f;
9974      }
9975
9976      .bar {
9977        color: red;
9978      }
9979    "#},
9980    );
9981    test(
9982      r#"
9983      .foo {
9984        background: red;
9985      }
9986      .bar {
9987        background: red;
9988      }
9989      .foo {
9990        color: green;
9991      }
9992      .bar {
9993        color: green;
9994      }
9995    "#,
9996      indoc! {r#"
9997      .foo, .bar {
9998        color: green;
9999        background: red;
10000      }
10001    "#},
10002    );
10003    test(
10004      r#"
10005      .foo, .bar {
10006        background: red;
10007      }
10008      .foo {
10009        color: green;
10010      }
10011      .bar {
10012        color: green;
10013      }
10014    "#,
10015      indoc! {r#"
10016      .foo, .bar {
10017        color: green;
10018        background: red;
10019      }
10020    "#},
10021    );
10022    test(
10023      r#"
10024      .foo {
10025        background: red;
10026      }
10027      .foo {
10028        color: green;
10029      }
10030      .bar {
10031        background: red;
10032      }
10033      .bar {
10034        color: green;
10035      }
10036    "#,
10037      indoc! {r#"
10038      .foo, .bar {
10039        color: green;
10040        background: red;
10041      }
10042    "#},
10043    );
10044    test(
10045      r#"
10046      [foo="bar"] {
10047        color: red;
10048      }
10049      .bar {
10050        color: red;
10051      }
10052    "#,
10053      indoc! {r#"
10054      [foo="bar"], .bar {
10055        color: red;
10056      }
10057    "#},
10058    );
10059    test(
10060      r#"
10061      .a {
10062        color: red;
10063      }
10064      .b {
10065        color: green;
10066      }
10067      .a {
10068        color: red;
10069      }
10070    "#,
10071      indoc! {r#"
10072      .b {
10073        color: green;
10074      }
10075
10076      .a {
10077        color: red;
10078      }
10079    "#},
10080    );
10081    test(
10082      r#"
10083      .a {
10084        color: red;
10085      }
10086      .b {
10087        color: green;
10088      }
10089      .a {
10090        color: pink;
10091      }
10092    "#,
10093      indoc! {r#"
10094      .b {
10095        color: green;
10096      }
10097
10098      .a {
10099        color: pink;
10100      }
10101    "#},
10102    );
10103    test(
10104      r#"
10105      .a:foo(#000) {
10106        color: red;
10107      }
10108      .b {
10109        color: green;
10110      }
10111      .a:foo(#ff0) {
10112        color: pink;
10113      }
10114    "#,
10115      indoc! {r#"
10116      .a:foo(#000) {
10117        color: red;
10118      }
10119
10120      .b {
10121        color: green;
10122      }
10123
10124      .a:foo(#ff0) {
10125        color: pink;
10126      }
10127    "#},
10128    );
10129    test(
10130      r#"
10131      .a {
10132        border-radius: 10px;
10133      }
10134      .b {
10135        color: green;
10136      }
10137      .a {
10138        border-radius: 10px;
10139      }
10140    "#,
10141      indoc! {r#"
10142      .b {
10143        color: green;
10144      }
10145
10146      .a {
10147        border-radius: 10px;
10148      }
10149    "#},
10150    );
10151    test(
10152      r#"
10153      .a {
10154        border-radius: 10px;
10155      }
10156      .b {
10157        color: green;
10158      }
10159      .a {
10160        -webkit-border-radius: 10px;
10161      }
10162    "#,
10163      indoc! {r#"
10164      .a {
10165        border-radius: 10px;
10166      }
10167
10168      .b {
10169        color: green;
10170      }
10171
10172      .a {
10173        -webkit-border-radius: 10px;
10174      }
10175    "#},
10176    );
10177    test(
10178      r#"
10179      .a {
10180        border-radius: 10px;
10181      }
10182      .b {
10183        color: green;
10184      }
10185      .a {
10186        border-radius: var(--foo);
10187      }
10188    "#,
10189      indoc! {r#"
10190      .b {
10191        color: green;
10192      }
10193
10194      .a {
10195        border-radius: var(--foo);
10196      }
10197    "#},
10198    );
10199    test(
10200      r#"
10201      .a {
10202        border-radius: 10px;
10203      }
10204      .b {
10205        color: green;
10206      }
10207      .c {
10208        border-radius: 20px;
10209      }
10210    "#,
10211      indoc! {r#"
10212      .a {
10213        border-radius: 10px;
10214      }
10215
10216      .b {
10217        color: green;
10218      }
10219
10220      .c {
10221        border-radius: 20px;
10222      }
10223    "#},
10224    );
10225    test(
10226      r#"
10227      @media print {
10228        .a {
10229          color: red;
10230        }
10231        .b {
10232          color: green;
10233        }
10234        .a {
10235          color: red;
10236        }
10237      }
10238    "#,
10239      indoc! {r#"
10240      @media print {
10241        .b {
10242          color: green;
10243        }
10244
10245        .a {
10246          color: red;
10247        }
10248      }
10249    "#},
10250    );
10251    test(
10252      r#"
10253      .a {
10254        border-radius: 10px;
10255      }
10256      .b {
10257        color: green;
10258      }
10259      .a {
10260        border-radius: 20px;
10261        color: pink;
10262      }
10263    "#,
10264      indoc! {r#"
10265      .a {
10266        border-radius: 10px;
10267      }
10268
10269      .b {
10270        color: green;
10271      }
10272
10273      .a {
10274        color: pink;
10275        border-radius: 20px;
10276      }
10277    "#},
10278    );
10279    test(
10280      r#"
10281      .a {
10282        color: red;
10283      }
10284      .b {
10285        color: green;
10286      }
10287      .a {
10288        color: red;
10289      }
10290      .b {
10291        color: green;
10292      }
10293    "#,
10294      indoc! {r#"
10295      .a {
10296        color: red;
10297      }
10298
10299      .b {
10300        color: green;
10301      }
10302    "#},
10303    );
10304
10305    prefix_test(
10306      r#"
10307      [foo="bar"] {
10308        color: red;
10309      }
10310      .bar {
10311        color: red;
10312      }
10313    "#,
10314      indoc! {r#"
10315      [foo="bar"] {
10316        color: red;
10317      }
10318
10319      .bar {
10320        color: red;
10321      }
10322    "#},
10323      Browsers {
10324        ie: Some(6 << 16),
10325        ..Browsers::default()
10326      },
10327    );
10328
10329    prefix_test(
10330      r#"
10331      [foo="bar"] {
10332        color: red;
10333      }
10334      .bar {
10335        color: red;
10336      }
10337    "#,
10338      indoc! {r#"
10339      [foo="bar"], .bar {
10340        color: red;
10341      }
10342    "#},
10343      Browsers {
10344        ie: Some(10 << 16),
10345        ..Browsers::default()
10346      },
10347    );
10348
10349    test(
10350      r#"
10351      .foo:-moz-read-only {
10352        color: red;
10353      }
10354    "#,
10355      indoc! {r#"
10356      .foo:-moz-read-only {
10357        color: red;
10358      }
10359    "#},
10360    );
10361
10362    test(
10363      r#"
10364      .foo:-moz-read-only {
10365        color: red;
10366      }
10367
10368      .foo:read-only {
10369        color: red;
10370      }
10371    "#,
10372      indoc! {r#"
10373      .foo:-moz-read-only {
10374        color: red;
10375      }
10376
10377      .foo:read-only {
10378        color: red;
10379      }
10380    "#},
10381    );
10382
10383    prefix_test(
10384      r#"
10385      .foo:-moz-read-only {
10386        color: red;
10387      }
10388
10389      .foo:read-only {
10390        color: red;
10391      }
10392    "#,
10393      indoc! {r#"
10394      .foo:read-only {
10395        color: red;
10396      }
10397    "#},
10398      Browsers {
10399        firefox: Some(85 << 16),
10400        ..Browsers::default()
10401      },
10402    );
10403
10404    prefix_test(
10405      r#"
10406      .foo:-moz-read-only {
10407        color: red;
10408      }
10409
10410      .bar {
10411        color: yellow;
10412      }
10413
10414      .foo:read-only {
10415        color: red;
10416      }
10417    "#,
10418      indoc! {r#"
10419      .foo:-moz-read-only {
10420        color: red;
10421      }
10422
10423      .bar {
10424        color: #ff0;
10425      }
10426
10427      .foo:read-only {
10428        color: red;
10429      }
10430    "#},
10431      Browsers {
10432        firefox: Some(85 << 16),
10433        ..Browsers::default()
10434      },
10435    );
10436
10437    prefix_test(
10438      r#"
10439      .foo:-moz-read-only {
10440        color: red;
10441      }
10442
10443      .foo:read-only {
10444        color: red;
10445      }
10446    "#,
10447      indoc! {r#"
10448      .foo:-moz-read-only {
10449        color: red;
10450      }
10451
10452      .foo:read-only {
10453        color: red;
10454      }
10455    "#},
10456      Browsers {
10457        firefox: Some(36 << 16),
10458        ..Browsers::default()
10459      },
10460    );
10461
10462    prefix_test(
10463      r#"
10464      .foo:read-only {
10465        color: red;
10466      }
10467    "#,
10468      indoc! {r#"
10469      .foo:-moz-read-only {
10470        color: red;
10471      }
10472
10473      .foo:read-only {
10474        color: red;
10475      }
10476    "#},
10477      Browsers {
10478        firefox: Some(36 << 16),
10479        ..Browsers::default()
10480      },
10481    );
10482
10483    prefix_test(
10484      r#"
10485      .foo:-webkit-full-screen {
10486        color: red;
10487      }
10488      .foo:-moz-full-screen {
10489        color: red;
10490      }
10491      .foo:-ms-fullscreen {
10492        color: red;
10493      }
10494      .foo:fullscreen {
10495        color: red;
10496      }
10497    "#,
10498      indoc! {r#"
10499      .foo:fullscreen {
10500        color: red;
10501      }
10502    "#},
10503      Browsers {
10504        chrome: Some(96 << 16),
10505        ..Browsers::default()
10506      },
10507    );
10508
10509    prefix_test(
10510      r#"
10511      .foo:fullscreen {
10512        color: red;
10513      }
10514    "#,
10515      indoc! {r#"
10516      .foo:-webkit-full-screen {
10517        color: red;
10518      }
10519
10520      .foo:-moz-full-screen {
10521        color: red;
10522      }
10523
10524      .foo:-ms-fullscreen {
10525        color: red;
10526      }
10527
10528      .foo:fullscreen {
10529        color: red;
10530      }
10531    "#},
10532      Browsers {
10533        chrome: Some(45 << 16),
10534        firefox: Some(45 << 16),
10535        ie: Some(11 << 16),
10536        ..Browsers::default()
10537      },
10538    );
10539
10540    prefix_test(
10541      r#"
10542      .foo::placeholder {
10543        color: red;
10544      }
10545    "#,
10546      indoc! {r#"
10547      .foo::-webkit-input-placeholder {
10548        color: red;
10549      }
10550
10551      .foo::-moz-placeholder {
10552        color: red;
10553      }
10554
10555      .foo::-ms-input-placeholder {
10556        color: red;
10557      }
10558
10559      .foo::placeholder {
10560        color: red;
10561      }
10562    "#},
10563      Browsers {
10564        chrome: Some(45 << 16),
10565        firefox: Some(45 << 16),
10566        ie: Some(11 << 16),
10567        ..Browsers::default()
10568      },
10569    );
10570
10571    prefix_test(
10572      r#"
10573      .foo::file-selector-button {
10574        color: red;
10575      }
10576    "#,
10577      indoc! {r#"
10578      .foo::-webkit-file-upload-button {
10579        color: red;
10580      }
10581
10582      .foo::-ms-browse {
10583        color: red;
10584      }
10585
10586      .foo::file-selector-button {
10587        color: red;
10588      }
10589    "#},
10590      Browsers {
10591        chrome: Some(84 << 16),
10592        ie: Some(10 << 16),
10593        ..Browsers::default()
10594      },
10595    );
10596
10597    prefix_test(
10598      r#"
10599      .foo::file-selector-button {
10600        margin-inline-start: 2px;
10601      }
10602    "#,
10603      indoc! {r#"
10604      .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 {
10605        margin-left: 2px;
10606      }
10607
10608      .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 {
10609        margin-left: 2px;
10610      }
10611
10612      .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 {
10613        margin-left: 2px;
10614      }
10615
10616      .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 {
10617        margin-right: 2px;
10618      }
10619
10620      .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 {
10621        margin-right: 2px;
10622      }
10623
10624      .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 {
10625        margin-right: 2px;
10626      }
10627    "#},
10628      Browsers {
10629        chrome: Some(84 << 16),
10630        ie: Some(10 << 16),
10631        ..Browsers::default()
10632      },
10633    );
10634
10635    prefix_test(
10636      r#"
10637      .foo:placeholder-shown .bar { color: red; }
10638      .foo:autofill .baz { color: red; }
10639      "#,
10640      indoc! {r#"
10641      .foo:placeholder-shown .bar {
10642        color: red;
10643      }
10644
10645      .foo:-webkit-autofill .baz {
10646        color: red;
10647      }
10648
10649      .foo:autofill .baz {
10650        color: red;
10651      }
10652      "#},
10653      Browsers {
10654        chrome: Some(103 << 16),
10655        ..Browsers::default()
10656      },
10657    );
10658
10659    prefix_test(
10660      r#"
10661      .foo:placeholder-shown .bar,.foo:autofill .baz{color:red}
10662      "#,
10663      indoc! {r#"
10664      :-webkit-any(.foo:placeholder-shown .bar, .foo:-webkit-autofill .baz) {
10665        color: red;
10666      }
10667
10668      :is(.foo:placeholder-shown .bar, .foo:autofill .baz) {
10669        color: red;
10670      }
10671      "#},
10672      Browsers {
10673        chrome: Some(103 << 16),
10674        ..Browsers::default()
10675      },
10676    );
10677
10678    prefix_test(
10679      r#"
10680      .foo:placeholder-shown .bar, .foo:-webkit-autofill .baz {
10681        color: red;
10682      }
10683
10684      .foo:placeholder-shown .bar, .foo:autofill .baz {
10685        color: red;
10686      }
10687      "#,
10688      indoc! {r#"
10689      :-webkit-any(.foo:placeholder-shown .bar, .foo:-webkit-autofill .baz) {
10690        color: red;
10691      }
10692
10693      :is(.foo:placeholder-shown .bar, .foo:autofill .baz) {
10694        color: red;
10695      }
10696      "#},
10697      Browsers {
10698        chrome: Some(103 << 16),
10699        ..Browsers::default()
10700      },
10701    );
10702
10703    test(
10704      r#"
10705      .foo:placeholder-shown .bar, .foo:-webkit-autofill .baz {
10706        color: red;
10707      }
10708
10709      .foo:placeholder-shown .bar, .foo:autofill .baz {
10710        color: red;
10711      }
10712      "#,
10713      indoc! {r#"
10714      .foo:placeholder-shown .bar, .foo:-webkit-autofill .baz {
10715        color: red;
10716      }
10717
10718      .foo:placeholder-shown .bar, .foo:autofill .baz {
10719        color: red;
10720      }
10721      "#},
10722    );
10723
10724    prefix_test(
10725      r#"
10726      :hover, :focus-visible {
10727        color: red;
10728      }
10729      "#,
10730      indoc! {r#"
10731      :hover {
10732        color: red;
10733      }
10734
10735      :focus-visible {
10736        color: red;
10737      }
10738      "#},
10739      Browsers {
10740        safari: Some(13 << 16),
10741        ..Browsers::default()
10742      },
10743    );
10744
10745    prefix_test(
10746      r#"
10747      .foo {
10748        color: red;
10749      }
10750
10751      :hover, :focus-visible {
10752        color: red;
10753      }
10754      "#,
10755      indoc! {r#"
10756      .foo, :hover {
10757        color: red;
10758      }
10759
10760      :focus-visible {
10761        color: red;
10762      }
10763      "#},
10764      Browsers {
10765        safari: Some(13 << 16),
10766        ..Browsers::default()
10767      },
10768    );
10769
10770    prefix_test(
10771      r#"
10772      :hover, :focus-visible {
10773        margin-inline-start: 24px;
10774      }
10775      "#,
10776      indoc! {r#"
10777      :hover:not(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
10778        margin-left: 24px;
10779      }
10780
10781      :hover:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) {
10782        margin-right: 24px;
10783      }
10784
10785      :focus-visible:not(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
10786        margin-left: 24px;
10787      }
10788
10789      :focus-visible:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) {
10790        margin-right: 24px;
10791      }
10792      "#},
10793      Browsers {
10794        safari: Some(11 << 16),
10795        ..Browsers::default()
10796      },
10797    );
10798
10799    prefix_test(
10800      r#"
10801      :focus-within, :focus-visible {
10802        color: red;
10803      }
10804      "#,
10805      indoc! {r#"
10806      :focus-within {
10807        color: red;
10808      }
10809
10810      :focus-visible {
10811        color: red;
10812      }
10813      "#},
10814      Browsers {
10815        safari: Some(9 << 16),
10816        ..Browsers::default()
10817      },
10818    );
10819
10820    prefix_test(
10821      r#"
10822      :hover, :focus-visible {
10823        color: red;
10824      }
10825      "#,
10826      indoc! {r#"
10827      :is(:hover, :focus-visible) {
10828        color: red;
10829      }
10830      "#},
10831      Browsers {
10832        safari: Some(14 << 16),
10833        ..Browsers::default()
10834      },
10835    );
10836
10837    prefix_test(
10838      r#"
10839      a::after:hover, a::after:focus-visible {
10840        color: red;
10841      }
10842      "#,
10843      indoc! {r#"
10844      a:after:hover {
10845        color: red;
10846      }
10847
10848      a:after:focus-visible {
10849        color: red;
10850      }
10851      "#},
10852      Browsers {
10853        safari: Some(14 << 16),
10854        ..Browsers::default()
10855      },
10856    );
10857
10858    prefix_test(
10859      r#"
10860      a:not(:hover), a:not(:focus-visible) {
10861        color: red;
10862      }
10863      "#,
10864      indoc! {r#"
10865      :is(a:not(:hover), a:not(:focus-visible)) {
10866        color: red;
10867      }
10868      "#},
10869      Browsers {
10870        safari: Some(14 << 16),
10871        ..Browsers::default()
10872      },
10873    );
10874
10875    prefix_test(
10876      r#"
10877      a:has(:hover), a:has(:focus-visible) {
10878        color: red;
10879      }
10880      "#,
10881      indoc! {r#"
10882      :is(a:has(:hover), a:has(:focus-visible)) {
10883        color: red;
10884      }
10885      "#},
10886      Browsers {
10887        safari: Some(14 << 16),
10888        ..Browsers::default()
10889      },
10890    );
10891
10892    prefix_test(
10893      r#"
10894      .foo.foo:hover, .bar:focus-visible {
10895        color: red;
10896      }
10897      "#,
10898      indoc! {r#"
10899      .foo.foo:hover {
10900        color: red;
10901      }
10902
10903      .bar:focus-visible {
10904        color: red;
10905      }
10906      "#},
10907      Browsers {
10908        safari: Some(14 << 16),
10909        ..Browsers::default()
10910      },
10911    );
10912
10913    prefix_test(
10914      r#"
10915      a::unknown-a, a::unknown-b {
10916        color: red;
10917      }
10918      "#,
10919      indoc! {r#"
10920      a::unknown-a {
10921        color: red;
10922      }
10923
10924      a::unknown-b {
10925        color: red;
10926      }
10927      "#},
10928      Browsers {
10929        safari: Some(14 << 16),
10930        ..Browsers::default()
10931      },
10932    );
10933
10934    nesting_test_with_targets(
10935      r#"
10936      .foo {
10937        padding-inline-start: 3px;
10938
10939        .bar {
10940          padding-inline-start: 5px;
10941        }
10942      }
10943      "#,
10944      indoc! {r#"
10945      .foo:not(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
10946        padding-left: 3px;
10947      }
10948
10949      .foo:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) {
10950        padding-right: 3px;
10951      }
10952
10953      .foo .bar:not(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
10954        padding-left: 5px;
10955      }
10956
10957      .foo .bar:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) {
10958        padding-right: 5px;
10959      }
10960      "#},
10961      Browsers {
10962        safari: Some(12 << 16),
10963        ..Browsers::default()
10964      }
10965      .into(),
10966    );
10967
10968    prefix_test(
10969      r#"
10970      .foo::part(header), .foo::part(body) {
10971        display: none
10972      }
10973      "#,
10974      indoc! {r#"
10975      .foo::part(header), .foo::part(body) {
10976        display: none;
10977      }
10978      "#},
10979      Browsers {
10980        safari: Some(14 << 16),
10981        ..Browsers::default()
10982      },
10983    );
10984
10985    prefix_test(
10986      r#"
10987      .foo :is(.bar) {
10988        color: red;
10989      }
10990      "#,
10991      indoc! {r#"
10992        .foo .bar {
10993          color: red;
10994        }
10995      "#},
10996      Browsers {
10997        chrome: Some(87 << 16),
10998        ..Browsers::default()
10999      },
11000    );
11001
11002    prefix_test(
11003      r#"
11004      .foo :is(.bar), .bar :is(.baz) {
11005        color: red;
11006      }
11007      "#,
11008      indoc! {r#"
11009        .foo .bar, .bar .baz {
11010          color: red;
11011        }
11012      "#},
11013      Browsers {
11014        chrome: Some(87 << 16),
11015        ..Browsers::default()
11016      },
11017    );
11018
11019    prefix_test(
11020      r#"
11021      .foo :is(.bar:focus-visible), .bar :is(.baz:hover) {
11022        color: red;
11023      }
11024      "#,
11025      indoc! {r#"
11026        .bar .baz:hover {
11027          color: red;
11028        }
11029
11030        .foo .bar:focus-visible {
11031          color: red;
11032        }
11033      "#},
11034      Browsers {
11035        chrome: Some(85 << 16),
11036        ..Browsers::default()
11037      },
11038    );
11039
11040    prefix_test(
11041      r#"
11042      *,
11043      ::before,
11044      ::after,
11045      ::backdrop {
11046        padding: 5px;
11047      }
11048      "#,
11049      indoc! {r#"
11050        *, :before, :after {
11051          padding: 5px;
11052        }
11053
11054        ::-webkit-backdrop {
11055          padding: 5px;
11056        }
11057
11058        ::backdrop {
11059          padding: 5px;
11060        }
11061      "#},
11062      Browsers {
11063        chrome: Some(33 << 16),
11064        ..Browsers::default()
11065      },
11066    );
11067
11068    test(
11069      r#"
11070      .foo:-webkit-any(.bar, .baz):after {
11071        color: red;
11072      }
11073
11074      .foo:is(.bar, .baz):after {
11075        color: red;
11076      }
11077      "#,
11078      indoc! {r#"
11079        .foo:-webkit-any(.bar, .baz):after {
11080          color: red;
11081        }
11082
11083        .foo:is(.bar, .baz):after {
11084          color: red;
11085        }
11086      "#},
11087    );
11088
11089    prefix_test(
11090      r#"
11091      .foo:-webkit-any(.bar, .baz):after {
11092        color: red;
11093      }
11094
11095      .foo:is(.bar, .baz):after {
11096        color: red;
11097      }
11098      "#,
11099      indoc! {r#"
11100        .foo:is(.bar, .baz):after {
11101          color: red;
11102        }
11103      "#},
11104      Browsers {
11105        safari: Some(16 << 16),
11106        ..Browsers::default()
11107      },
11108    );
11109
11110    prefix_test(
11111      r#"
11112      .foo:-webkit-any(.bar):after {
11113        color: red;
11114      }
11115
11116      .foo:is(.bar, .baz):after {
11117        color: red;
11118      }
11119      "#,
11120      indoc! {r#"
11121        .foo:-webkit-any(.bar):after {
11122          color: red;
11123        }
11124
11125        .foo:is(.bar, .baz):after {
11126          color: red;
11127        }
11128      "#},
11129      Browsers {
11130        safari: Some(16 << 16),
11131        ..Browsers::default()
11132      },
11133    );
11134
11135    prefix_test(
11136      r#"
11137      .foo:-webkit-any(.bar, .baz):after {
11138        color: red;
11139      }
11140
11141      .foo:is(.bar, .baz):after {
11142        color: red;
11143      }
11144      "#,
11145      indoc! {r#"
11146        .foo:-webkit-any(.bar, .baz):after {
11147          color: red;
11148        }
11149
11150        .foo:is(.bar, .baz):after {
11151          color: red;
11152        }
11153      "#},
11154      Browsers {
11155        safari: Some(12 << 16),
11156        ..Browsers::default()
11157      },
11158    );
11159
11160    prefix_test(
11161      r#"
11162      .foo:-webkit-any(.bar, .baz):after {
11163        color: red;
11164      }
11165
11166      .foo:-moz-any(.bar, .baz):after {
11167        color: red;
11168      }
11169      "#,
11170      indoc! {r#"
11171        .foo:-webkit-any(.bar, .baz):after {
11172          color: red;
11173        }
11174
11175        .foo:-moz-any(.bar, .baz):after {
11176          color: red;
11177        }
11178      "#},
11179      Browsers {
11180        safari: Some(12 << 16),
11181        firefox: Some(67 << 16),
11182        ..Browsers::default()
11183      },
11184    );
11185
11186    prefix_test(
11187      r#"
11188      .a {
11189        padding-inline: var(--foo);
11190      }
11191
11192      .a:-webkit-any(.b, .c) {
11193        padding-inline: var(--foo);
11194      }
11195      "#,
11196      indoc! {r#"
11197        .a {
11198          padding-inline: var(--foo);
11199        }
11200
11201        .a:-webkit-any(.b, .c) {
11202          padding-inline: var(--foo);
11203        }
11204      "#},
11205      Browsers {
11206        safari: Some(12 << 16),
11207        ..Browsers::default()
11208      },
11209    );
11210  }
11211
11212  #[test]
11213  fn test_merge_media_rules() {
11214    test(
11215      r#"
11216      @media (hover) {
11217        .foo {
11218          color: red;
11219        }
11220      }
11221      @media (hover) {
11222        .foo {
11223          background: #fff;
11224        }
11225
11226        .baz {
11227          color: #fff;
11228        }
11229      }
11230      "#,
11231      indoc! {r#"
11232      @media (hover) {
11233        .foo {
11234          color: red;
11235          background: #fff;
11236        }
11237
11238        .baz {
11239          color: #fff;
11240        }
11241      }
11242    "#},
11243    );
11244
11245    test(
11246      r#"
11247      @media (hover) {
11248        .foo {
11249          color: red;
11250        }
11251      }
11252      @media (min-width: 250px) {
11253        .foo {
11254          background: #fff;
11255        }
11256
11257        .baz {
11258          color: #fff;
11259        }
11260      }
11261      "#,
11262      indoc! {r#"
11263      @media (hover) {
11264        .foo {
11265          color: red;
11266        }
11267      }
11268
11269      @media (width >= 250px) {
11270        .foo {
11271          background: #fff;
11272        }
11273
11274        .baz {
11275          color: #fff;
11276        }
11277      }
11278    "#},
11279    );
11280  }
11281
11282  #[test]
11283  fn test_merge_supports() {
11284    test(
11285      r#"
11286      @supports (flex: 1) {
11287        .foo {
11288          color: red;
11289        }
11290      }
11291      @supports (flex: 1) {
11292        .foo {
11293          background: #fff;
11294        }
11295
11296        .baz {
11297          color: #fff;
11298        }
11299      }
11300      "#,
11301      indoc! {r#"
11302      @supports (flex: 1) {
11303        .foo {
11304          color: red;
11305          background: #fff;
11306        }
11307
11308        .baz {
11309          color: #fff;
11310        }
11311      }
11312    "#},
11313    );
11314
11315    test(
11316      r#"
11317      @supports (flex: 1) {
11318        .foo {
11319          color: red;
11320        }
11321      }
11322      @supports (display: grid) {
11323        .foo {
11324          background: #fff;
11325        }
11326
11327        .baz {
11328          color: #fff;
11329        }
11330      }
11331      "#,
11332      indoc! {r#"
11333      @supports (flex: 1) {
11334        .foo {
11335          color: red;
11336        }
11337      }
11338
11339      @supports (display: grid) {
11340        .foo {
11341          background: #fff;
11342        }
11343
11344        .baz {
11345          color: #fff;
11346        }
11347      }
11348    "#},
11349    );
11350  }
11351
11352  #[test]
11353  fn test_opacity() {
11354    minify_test(".foo { opacity: 0 }", ".foo{opacity:0}");
11355    minify_test(".foo { opacity: 0% }", ".foo{opacity:0}");
11356    minify_test(".foo { opacity: 0.5 }", ".foo{opacity:.5}");
11357    minify_test(".foo { opacity: 50% }", ".foo{opacity:.5}");
11358    minify_test(".foo { opacity: 1 }", ".foo{opacity:1}");
11359    minify_test(".foo { opacity: 100% }", ".foo{opacity:1}");
11360  }
11361
11362  #[test]
11363  fn test_transitions() {
11364    minify_test(".foo { transition-duration: 500ms }", ".foo{transition-duration:.5s}");
11365    minify_test(".foo { transition-duration: .5s }", ".foo{transition-duration:.5s}");
11366    minify_test(".foo { transition-duration: 99ms }", ".foo{transition-duration:99ms}");
11367    minify_test(".foo { transition-duration: .099s }", ".foo{transition-duration:99ms}");
11368    minify_test(".foo { transition-duration: 2000ms }", ".foo{transition-duration:2s}");
11369    minify_test(".foo { transition-duration: 2s }", ".foo{transition-duration:2s}");
11370    minify_test(
11371      ".foo { transition-duration: calc(1s - 50ms) }",
11372      ".foo{transition-duration:.95s}",
11373    );
11374    minify_test(
11375      ".foo { transition-duration: calc(1s - 50ms + 2s) }",
11376      ".foo{transition-duration:2.95s}",
11377    );
11378    minify_test(
11379      ".foo { transition-duration: calc((1s - 50ms) * 2) }",
11380      ".foo{transition-duration:1.9s}",
11381    );
11382    minify_test(
11383      ".foo { transition-duration: calc(2 * (1s - 50ms)) }",
11384      ".foo{transition-duration:1.9s}",
11385    );
11386    minify_test(
11387      ".foo { transition-duration: calc((2s + 50ms) - (1s - 50ms)) }",
11388      ".foo{transition-duration:1.1s}",
11389    );
11390    minify_test(
11391      ".foo { transition-duration: 500ms, 50ms }",
11392      ".foo{transition-duration:.5s,50ms}",
11393    );
11394    minify_test(".foo { transition-delay: 500ms }", ".foo{transition-delay:.5s}");
11395    minify_test(
11396      ".foo { transition-property: background }",
11397      ".foo{transition-property:background}",
11398    );
11399    minify_test(
11400      ".foo { transition-property: background, opacity }",
11401      ".foo{transition-property:background,opacity}",
11402    );
11403    minify_test(
11404      ".foo { transition-timing-function: linear }",
11405      ".foo{transition-timing-function:linear}",
11406    );
11407    minify_test(
11408      ".foo { transition-timing-function: ease }",
11409      ".foo{transition-timing-function:ease}",
11410    );
11411    minify_test(
11412      ".foo { transition-timing-function: ease-in }",
11413      ".foo{transition-timing-function:ease-in}",
11414    );
11415    minify_test(
11416      ".foo { transition-timing-function: ease-out }",
11417      ".foo{transition-timing-function:ease-out}",
11418    );
11419    minify_test(
11420      ".foo { transition-timing-function: ease-in-out }",
11421      ".foo{transition-timing-function:ease-in-out}",
11422    );
11423    minify_test(
11424      ".foo { transition-timing-function: cubic-bezier(0.25, 0.1, 0.25, 1) }",
11425      ".foo{transition-timing-function:ease}",
11426    );
11427    minify_test(
11428      ".foo { transition-timing-function: cubic-bezier(0.42, 0, 1, 1) }",
11429      ".foo{transition-timing-function:ease-in}",
11430    );
11431    minify_test(
11432      ".foo { transition-timing-function: cubic-bezier(0, 0, 0.58, 1) }",
11433      ".foo{transition-timing-function:ease-out}",
11434    );
11435    minify_test(
11436      ".foo { transition-timing-function: cubic-bezier(0.42, 0, 0.58, 1) }",
11437      ".foo{transition-timing-function:ease-in-out}",
11438    );
11439    minify_test(
11440      ".foo { transition-timing-function: cubic-bezier(0.58, 0.2, 0.11, 1.2) }",
11441      ".foo{transition-timing-function:cubic-bezier(.58,.2,.11,1.2)}",
11442    );
11443    minify_test(
11444      ".foo { transition-timing-function: step-start }",
11445      ".foo{transition-timing-function:step-start}",
11446    );
11447    minify_test(
11448      ".foo { transition-timing-function: step-end }",
11449      ".foo{transition-timing-function:step-end}",
11450    );
11451    minify_test(
11452      ".foo { transition-timing-function: steps(1, start) }",
11453      ".foo{transition-timing-function:step-start}",
11454    );
11455    minify_test(
11456      ".foo { transition-timing-function: steps(1, jump-start) }",
11457      ".foo{transition-timing-function:step-start}",
11458    );
11459    minify_test(
11460      ".foo { transition-timing-function: steps(1, end) }",
11461      ".foo{transition-timing-function:step-end}",
11462    );
11463    minify_test(
11464      ".foo { transition-timing-function: steps(1, jump-end) }",
11465      ".foo{transition-timing-function:step-end}",
11466    );
11467    minify_test(
11468      ".foo { transition-timing-function: steps(5, jump-start) }",
11469      ".foo{transition-timing-function:steps(5,start)}",
11470    );
11471    minify_test(
11472      ".foo { transition-timing-function: steps(5, jump-end) }",
11473      ".foo{transition-timing-function:steps(5,end)}",
11474    );
11475    minify_test(
11476      ".foo { transition-timing-function: steps(5, jump-both) }",
11477      ".foo{transition-timing-function:steps(5,jump-both)}",
11478    );
11479    minify_test(
11480      ".foo { transition-timing-function: ease-in-out, cubic-bezier(0.42, 0, 1, 1) }",
11481      ".foo{transition-timing-function:ease-in-out,ease-in}",
11482    );
11483    minify_test(
11484      ".foo { transition-timing-function: cubic-bezier(0.42, 0, 1, 1), cubic-bezier(0.58, 0.2, 0.11, 1.2) }",
11485      ".foo{transition-timing-function:ease-in,cubic-bezier(.58,.2,.11,1.2)}",
11486    );
11487    minify_test(
11488      ".foo { transition-timing-function: step-start, steps(5, jump-start) }",
11489      ".foo{transition-timing-function:step-start,steps(5,start)}",
11490    );
11491    minify_test(".foo { transition: width 2s ease }", ".foo{transition:width 2s}");
11492    minify_test(
11493      ".foo { transition: width 2s ease, height 1000ms cubic-bezier(0.25, 0.1, 0.25, 1) }",
11494      ".foo{transition:width 2s,height 1s}",
11495    );
11496    minify_test(".foo { transition: width 2s 1s }", ".foo{transition:width 2s 1s}");
11497    minify_test(".foo { transition: width 2s ease 1s }", ".foo{transition:width 2s 1s}");
11498    minify_test(
11499      ".foo { transition: ease-in 1s width 4s }",
11500      ".foo{transition:width 1s ease-in 4s}",
11501    );
11502    minify_test(".foo { transition: opacity 0s .6s }", ".foo{transition:opacity 0s .6s}");
11503    test(
11504      r#"
11505      .foo {
11506        transition-property: opacity;
11507        transition-duration: 0.09s;
11508        transition-timing-function: ease-in-out;
11509        transition-delay: 500ms;
11510      }
11511    "#,
11512      indoc! {r#"
11513      .foo {
11514        transition: opacity 90ms ease-in-out .5s;
11515      }
11516    "#},
11517    );
11518    test(
11519      r#"
11520      .foo {
11521        transition: opacity 2s;
11522        transition-timing-function: ease;
11523        transition-delay: 500ms;
11524      }
11525    "#,
11526      indoc! {r#"
11527      .foo {
11528        transition: opacity 2s .5s;
11529      }
11530    "#},
11531    );
11532    test(
11533      r#"
11534      .foo {
11535        transition: opacity 500ms;
11536        transition-timing-function: var(--ease);
11537      }
11538    "#,
11539      indoc! {r#"
11540      .foo {
11541        transition: opacity .5s;
11542        transition-timing-function: var(--ease);
11543      }
11544    "#},
11545    );
11546    test(
11547      r#"
11548      .foo {
11549        transition-property: opacity;
11550        transition-duration: 0.09s;
11551        transition-timing-function: ease-in-out;
11552        transition-delay: 500ms;
11553        transition: color 2s;
11554      }
11555    "#,
11556      indoc! {r#"
11557      .foo {
11558        transition: color 2s;
11559      }
11560    "#},
11561    );
11562    test(
11563      r#"
11564      .foo {
11565        transition-property: opacity, color;
11566        transition-duration: 2s, 4s;
11567        transition-timing-function: ease-in-out, ease-in;
11568        transition-delay: 500ms, 0s;
11569      }
11570    "#,
11571      indoc! {r#"
11572      .foo {
11573        transition: opacity 2s ease-in-out .5s, color 4s ease-in;
11574      }
11575    "#},
11576    );
11577    test(
11578      r#"
11579      .foo {
11580        transition-property: opacity, color;
11581        transition-duration: 2s;
11582        transition-timing-function: ease-in-out;
11583        transition-delay: 500ms;
11584      }
11585    "#,
11586      indoc! {r#"
11587      .foo {
11588        transition: opacity 2s ease-in-out .5s, color 2s ease-in-out .5s;
11589      }
11590    "#},
11591    );
11592    test(
11593      r#"
11594      .foo {
11595        transition-property: opacity, color, width, height;
11596        transition-duration: 2s, 4s;
11597        transition-timing-function: ease;
11598        transition-delay: 0s;
11599      }
11600    "#,
11601      indoc! {r#"
11602      .foo {
11603        transition: opacity 2s, color 4s, width 2s, height 4s;
11604      }
11605    "#},
11606    );
11607
11608    test(
11609      r#"
11610      .foo {
11611        -webkit-transition-property: opacity, color;
11612        -webkit-transition-duration: 2s, 4s;
11613        -webkit-transition-timing-function: ease-in-out, ease-in;
11614        -webkit-transition-delay: 500ms, 0s;
11615      }
11616    "#,
11617      indoc! {r#"
11618      .foo {
11619        -webkit-transition: opacity 2s ease-in-out .5s, color 4s ease-in;
11620      }
11621    "#},
11622    );
11623
11624    test(
11625      r#"
11626      .foo {
11627        -webkit-transition-property: opacity, color;
11628        -webkit-transition-duration: 2s, 4s;
11629        -webkit-transition-timing-function: ease-in-out, ease-in;
11630        -webkit-transition-delay: 500ms, 0s;
11631        -moz-transition-property: opacity, color;
11632        -moz-transition-duration: 2s, 4s;
11633        -moz-transition-timing-function: ease-in-out, ease-in;
11634        -moz-transition-delay: 500ms, 0s;
11635        transition-property: opacity, color;
11636        transition-duration: 2s, 4s;
11637        transition-timing-function: ease-in-out, ease-in;
11638        transition-delay: 500ms, 0s;
11639      }
11640    "#,
11641      indoc! {r#"
11642      .foo {
11643        -webkit-transition: opacity 2s ease-in-out .5s, color 4s ease-in;
11644        -moz-transition: opacity 2s ease-in-out .5s, color 4s ease-in;
11645        transition: opacity 2s ease-in-out .5s, color 4s ease-in;
11646      }
11647    "#},
11648    );
11649
11650    test(
11651      r#"
11652      .foo {
11653        -webkit-transition-property: opacity, color;
11654        -moz-transition-property: opacity, color;
11655        transition-property: opacity, color;
11656        -webkit-transition-duration: 2s, 4s;
11657        -moz-transition-duration: 2s, 4s;
11658        transition-duration: 2s, 4s;
11659        -webkit-transition-timing-function: ease-in-out, ease-in;
11660        transition-timing-function: ease-in-out, ease-in;
11661        -moz-transition-timing-function: ease-in-out, ease-in;
11662        -webkit-transition-delay: 500ms, 0s;
11663        -moz-transition-delay: 500ms, 0s;
11664        transition-delay: 500ms, 0s;
11665      }
11666    "#,
11667      indoc! {r#"
11668      .foo {
11669        -webkit-transition: opacity 2s ease-in-out .5s, color 4s ease-in;
11670        -moz-transition: opacity 2s ease-in-out .5s, color 4s ease-in;
11671        transition: opacity 2s ease-in-out .5s, color 4s ease-in;
11672      }
11673    "#},
11674    );
11675
11676    test(
11677      r#"
11678      .foo {
11679        -webkit-transition-property: opacity;
11680        -moz-transition-property: color;
11681        transition-property: opacity, color;
11682        -webkit-transition-duration: 2s;
11683        -moz-transition-duration: 4s;
11684        transition-duration: 2s, 4s;
11685        -webkit-transition-timing-function: ease-in-out;
11686        -moz-transition-timing-function: ease-in-out;
11687        transition-timing-function: ease-in-out, ease-in;
11688        -webkit-transition-delay: 500ms;
11689        -moz-transition-delay: 0s;
11690        transition-delay: 500ms, 0s;
11691      }
11692    "#,
11693      indoc! {r#"
11694      .foo {
11695        -webkit-transition-property: opacity;
11696        -moz-transition-property: color;
11697        transition-property: opacity, color;
11698        -webkit-transition-duration: 2s;
11699        -moz-transition-duration: 4s;
11700        transition-duration: 2s, 4s;
11701        -webkit-transition-timing-function: ease-in-out;
11702        -moz-transition-timing-function: ease-in-out;
11703        -webkit-transition-delay: .5s;
11704        transition-timing-function: ease-in-out, ease-in;
11705        -moz-transition-delay: 0s;
11706        transition-delay: .5s, 0s;
11707      }
11708    "#},
11709    );
11710
11711    test(
11712      r#"
11713      .foo {
11714        -webkit-transition-property: opacity;
11715        transition-property: opacity, color;
11716        -moz-transition-property: color;
11717        -webkit-transition-duration: 2s;
11718        transition-duration: 2s, 4s;
11719        -moz-transition-duration: 4s;
11720        -webkit-transition-timing-function: ease-in-out;
11721        transition-timing-function: ease-in-out, ease-in;
11722        -moz-transition-timing-function: ease-in-out;
11723        -webkit-transition-delay: 500ms;
11724        transition-delay: 500ms, 0s;
11725        -moz-transition-delay: 0s;
11726      }
11727    "#,
11728      indoc! {r#"
11729      .foo {
11730        -webkit-transition-property: opacity;
11731        transition-property: opacity, color;
11732        -moz-transition-property: color;
11733        -webkit-transition-duration: 2s;
11734        transition-duration: 2s, 4s;
11735        -moz-transition-duration: 4s;
11736        -webkit-transition-timing-function: ease-in-out;
11737        transition-timing-function: ease-in-out, ease-in;
11738        -webkit-transition-delay: .5s;
11739        -moz-transition-timing-function: ease-in-out;
11740        transition-delay: .5s, 0s;
11741        -moz-transition-delay: 0s;
11742      }
11743    "#},
11744    );
11745
11746    test(
11747      r#"
11748      .foo {
11749        transition: opacity 2s;
11750        -webkit-transition-duration: 2s;
11751      }
11752    "#,
11753      indoc! {r#"
11754      .foo {
11755        transition: opacity 2s;
11756        -webkit-transition-duration: 2s;
11757      }
11758    "#},
11759    );
11760
11761    prefix_test(
11762      r#"
11763      .foo {
11764        transition-property: margin-inline-start;
11765      }
11766    "#,
11767      indoc! {r#"
11768      .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))) {
11769        transition-property: margin-left;
11770      }
11771
11772      .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))) {
11773        transition-property: margin-left;
11774      }
11775
11776      .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)) {
11777        transition-property: margin-right;
11778      }
11779
11780      .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)) {
11781        transition-property: margin-right;
11782      }
11783    "#
11784      },
11785      Browsers {
11786        safari: Some(8 << 16),
11787        ..Browsers::default()
11788      },
11789    );
11790
11791    prefix_test(
11792      r#"
11793      .foo {
11794        transition-property: margin-inline-start, padding-inline-start;
11795      }
11796    "#,
11797      indoc! {r#"
11798      .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))) {
11799        transition-property: margin-left, padding-left;
11800      }
11801
11802      .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))) {
11803        transition-property: margin-left, padding-left;
11804      }
11805
11806      .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)) {
11807        transition-property: margin-right, padding-right;
11808      }
11809
11810      .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)) {
11811        transition-property: margin-right, padding-right;
11812      }
11813    "#
11814      },
11815      Browsers {
11816        safari: Some(8 << 16),
11817        ..Browsers::default()
11818      },
11819    );
11820
11821    prefix_test(
11822      r#"
11823      .foo {
11824        transition-property: margin-inline-start, opacity, padding-inline-start, color;
11825      }
11826    "#,
11827      indoc! {r#"
11828      .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))) {
11829        transition-property: margin-left, opacity, padding-left, color;
11830      }
11831
11832      .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))) {
11833        transition-property: margin-left, opacity, padding-left, color;
11834      }
11835
11836      .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)) {
11837        transition-property: margin-right, opacity, padding-right, color;
11838      }
11839
11840      .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)) {
11841        transition-property: margin-right, opacity, padding-right, color;
11842      }
11843    "#
11844      },
11845      Browsers {
11846        safari: Some(8 << 16),
11847        ..Browsers::default()
11848      },
11849    );
11850
11851    prefix_test(
11852      r#"
11853      .foo {
11854        transition-property: margin-block;
11855      }
11856    "#,
11857      indoc! {r#"
11858      .foo {
11859        transition-property: margin-top, margin-bottom;
11860      }
11861    "#
11862      },
11863      Browsers {
11864        safari: Some(8 << 16),
11865        ..Browsers::default()
11866      },
11867    );
11868
11869    prefix_test(
11870      r#"
11871      .foo {
11872        transition: margin-inline-start 2s;
11873      }
11874    "#,
11875      indoc! {r#"
11876      .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))) {
11877        transition: margin-left 2s;
11878      }
11879
11880      .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))) {
11881        transition: margin-left 2s;
11882      }
11883
11884      .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)) {
11885        transition: margin-right 2s;
11886      }
11887
11888      .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)) {
11889        transition: margin-right 2s;
11890      }
11891    "#
11892      },
11893      Browsers {
11894        safari: Some(8 << 16),
11895        ..Browsers::default()
11896      },
11897    );
11898
11899    prefix_test(
11900      r#"
11901      .foo {
11902        transition: margin-inline-start 2s, padding-inline-start 2s;
11903      }
11904    "#,
11905      indoc! {r#"
11906      .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))) {
11907        transition: margin-left 2s, padding-left 2s;
11908      }
11909
11910      .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))) {
11911        transition: margin-left 2s, padding-left 2s;
11912      }
11913
11914      .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)) {
11915        transition: margin-right 2s, padding-right 2s;
11916      }
11917
11918      .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)) {
11919        transition: margin-right 2s, padding-right 2s;
11920      }
11921    "#
11922      },
11923      Browsers {
11924        safari: Some(8 << 16),
11925        ..Browsers::default()
11926      },
11927    );
11928
11929    prefix_test(
11930      r#"
11931      .foo {
11932        transition: margin-block-start 2s;
11933      }
11934    "#,
11935      indoc! {r#"
11936      .foo {
11937        transition: margin-top 2s;
11938      }
11939    "#
11940      },
11941      Browsers {
11942        safari: Some(8 << 16),
11943        ..Browsers::default()
11944      },
11945    );
11946
11947    prefix_test(
11948      r#"
11949      .foo {
11950        transition: transform;
11951      }
11952    "#,
11953      indoc! {r#"
11954      .foo {
11955        -webkit-transition: -webkit-transform, transform;
11956        transition: -webkit-transform, transform;
11957      }
11958    "#
11959      },
11960      Browsers {
11961        safari: Some(6 << 16),
11962        ..Browsers::default()
11963      },
11964    );
11965
11966    prefix_test(
11967      r#"
11968      .foo {
11969        transition: border-start-start-radius;
11970      }
11971    "#,
11972      indoc! {r#"
11973      .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))) {
11974        -webkit-transition: -webkit-border-top-left-radius, border-top-left-radius;
11975        transition: -webkit-border-top-left-radius, border-top-left-radius;
11976      }
11977
11978      .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)) {
11979        -webkit-transition: -webkit-border-top-right-radius, border-top-right-radius;
11980        transition: -webkit-border-top-right-radius, border-top-right-radius;
11981      }
11982    "#
11983      },
11984      Browsers {
11985        safari: Some(4 << 16),
11986        ..Browsers::default()
11987      },
11988    );
11989
11990    prefix_test(
11991      r#"
11992      .foo {
11993        transition: border-start-start-radius;
11994      }
11995    "#,
11996      indoc! {r#"
11997      .foo:not(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
11998        transition: border-top-left-radius;
11999      }
12000
12001      .foo:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) {
12002        transition: border-top-right-radius;
12003      }
12004    "#
12005      },
12006      Browsers {
12007        safari: Some(12 << 16),
12008        ..Browsers::default()
12009      },
12010    );
12011
12012    test(
12013      r#"
12014      .foo {
12015        -webkit-transition: background 200ms;
12016        -moz-transition: background 200ms;
12017        transition: background 230ms;
12018      }
12019    "#,
12020      indoc! {r#"
12021      .foo {
12022        -webkit-transition: background .2s;
12023        -moz-transition: background .2s;
12024        transition: background .23s;
12025      }
12026    "#},
12027    );
12028
12029    prefix_test(
12030      r#"
12031      .foo {
12032        -webkit-transition: background 200ms;
12033        -moz-transition: background 200ms;
12034        transition: background 230ms;
12035      }
12036    "#,
12037      indoc! {r#"
12038      .foo {
12039        -webkit-transition: background .2s;
12040        -moz-transition: background .2s;
12041        transition: background .23s;
12042      }
12043    "#},
12044      Browsers {
12045        chrome: Some(95 << 16),
12046        ..Browsers::default()
12047      },
12048    );
12049    prefix_test(
12050      r#"
12051       .foo {
12052         transition-property: -webkit-backdrop-filter, backdrop-filter;
12053       }
12054       .bar {
12055         transition-property: backdrop-filter;
12056       }
12057       .baz {
12058         transition-property: -webkit-backdrop-filter;
12059       }
12060     "#,
12061      indoc! {r#"
12062       .foo, .bar {
12063         transition-property: -webkit-backdrop-filter, backdrop-filter;
12064       }
12065
12066       .baz {
12067         transition-property: -webkit-backdrop-filter;
12068       }
12069     "#
12070      },
12071      Browsers {
12072        safari: Some(15 << 16),
12073        ..Browsers::default()
12074      },
12075    );
12076    prefix_test(
12077      r#"
12078       .foo {
12079         transition-property: -webkit-border-radius, -webkit-border-radius, -moz-border-radius;
12080       }
12081     "#,
12082      indoc! {r#"
12083       .foo {
12084         transition-property: -webkit-border-radius, -moz-border-radius;
12085       }
12086     "#
12087      },
12088      Browsers {
12089        safari: Some(15 << 16),
12090        ..Browsers::default()
12091      },
12092    );
12093    prefix_test(
12094      r#"
12095       .foo {
12096         transition: -webkit-backdrop-filter, backdrop-filter;
12097       }
12098       .bar {
12099         transition: backdrop-filter;
12100       }
12101       .baz {
12102         transition: -webkit-backdrop-filter;
12103       }
12104     "#,
12105      indoc! {r#"
12106       .foo, .bar {
12107         transition: -webkit-backdrop-filter, backdrop-filter;
12108       }
12109
12110       .baz {
12111         transition: -webkit-backdrop-filter;
12112       }
12113     "#
12114      },
12115      Browsers {
12116        safari: Some(15 << 16),
12117        ..Browsers::default()
12118      },
12119    );
12120  }
12121
12122  #[test]
12123  fn test_animation() {
12124    minify_test(".foo { animation-name: test }", ".foo{animation-name:test}");
12125    minify_test(".foo { animation-name: \"test\" }", ".foo{animation-name:test}");
12126    minify_test(".foo { animation-name: foo, bar }", ".foo{animation-name:foo,bar}");
12127    minify_test(".foo { animation-name: \"none\" }", ".foo{animation-name:\"none\"}");
12128    minify_test(
12129      ".foo { animation-name: \"none\", foo }",
12130      ".foo{animation-name:\"none\",foo}",
12131    );
12132    let name = crate::properties::animation::AnimationName::parse_string("default");
12133    assert!(matches!(name, Err(..)));
12134
12135    minify_test(".foo { animation-name: none }", ".foo{animation-name:none}");
12136    minify_test(".foo { animation-name: none, none }", ".foo{animation-name:none,none}");
12137
12138    // Test CSS-wide keywords
12139    minify_test(".foo { animation-name: unset }", ".foo{animation-name:unset}");
12140    minify_test(".foo { animation-name: \"unset\" }", ".foo{animation-name:\"unset\"}");
12141    minify_test(".foo { animation-name: \"revert\" }", ".foo{animation-name:\"revert\"}");
12142    minify_test(
12143      ".foo { animation-name: \"unset\", \"revert\"}",
12144      ".foo{animation-name:\"unset\",\"revert\"}",
12145    );
12146    minify_test(
12147      ".foo { animation-name: foo, \"revert\"}",
12148      ".foo{animation-name:foo,\"revert\"}",
12149    );
12150    minify_test(
12151      ".foo { animation-name: \"string\", \"revert\"}",
12152      ".foo{animation-name:string,\"revert\"}",
12153    );
12154    minify_test(
12155      ".foo { animation-name: \"string\", foo, \"revert\"}",
12156      ".foo{animation-name:string,foo,\"revert\"}",
12157    );
12158    minify_test(
12159      ".foo { animation-name: \"default\" }",
12160      ".foo{animation-name:\"default\"}",
12161    );
12162    minify_test(".foo { animation-duration: 100ms }", ".foo{animation-duration:.1s}");
12163    minify_test(
12164      ".foo { animation-duration: 100ms, 2000ms }",
12165      ".foo{animation-duration:.1s,2s}",
12166    );
12167    minify_test(
12168      ".foo { animation-timing-function: ease }",
12169      ".foo{animation-timing-function:ease}",
12170    );
12171    minify_test(
12172      ".foo { animation-timing-function: cubic-bezier(0.42, 0, 1, 1) }",
12173      ".foo{animation-timing-function:ease-in}",
12174    );
12175    minify_test(
12176      ".foo { animation-timing-function: ease, cubic-bezier(0.42, 0, 1, 1) }",
12177      ".foo{animation-timing-function:ease,ease-in}",
12178    );
12179    minify_test(
12180      ".foo { animation-iteration-count: 5 }",
12181      ".foo{animation-iteration-count:5}",
12182    );
12183    minify_test(
12184      ".foo { animation-iteration-count: 2.5 }",
12185      ".foo{animation-iteration-count:2.5}",
12186    );
12187    minify_test(
12188      ".foo { animation-iteration-count: 2.0 }",
12189      ".foo{animation-iteration-count:2}",
12190    );
12191    minify_test(
12192      ".foo { animation-iteration-count: infinite }",
12193      ".foo{animation-iteration-count:infinite}",
12194    );
12195    minify_test(
12196      ".foo { animation-iteration-count: 1, infinite }",
12197      ".foo{animation-iteration-count:1,infinite}",
12198    );
12199    minify_test(
12200      ".foo { animation-direction: reverse }",
12201      ".foo{animation-direction:reverse}",
12202    );
12203    minify_test(
12204      ".foo { animation-direction: alternate, reverse }",
12205      ".foo{animation-direction:alternate,reverse}",
12206    );
12207    minify_test(
12208      ".foo { animation-play-state: paused }",
12209      ".foo{animation-play-state:paused}",
12210    );
12211    minify_test(
12212      ".foo { animation-play-state: running, paused }",
12213      ".foo{animation-play-state:running,paused}",
12214    );
12215    minify_test(".foo { animation-delay: 100ms }", ".foo{animation-delay:.1s}");
12216    minify_test(
12217      ".foo { animation-delay: 100ms, 2000ms }",
12218      ".foo{animation-delay:.1s,2s}",
12219    );
12220    minify_test(
12221      ".foo { animation-fill-mode: forwards }",
12222      ".foo{animation-fill-mode:forwards}",
12223    );
12224    minify_test(
12225      ".foo { animation-fill-mode: Backwards,forwards }",
12226      ".foo{animation-fill-mode:backwards,forwards}",
12227    );
12228    minify_test(".foo { animation: none }", ".foo{animation:none}");
12229    minify_test(".foo { animation: \"none\" }", ".foo{animation:\"none\"}");
12230    minify_test(".foo { animation: \"None\" }", ".foo{animation:\"None\"}");
12231    minify_test(".foo { animation: \"none\", none }", ".foo{animation:\"none\",none}");
12232    minify_test(".foo { animation: none, none }", ".foo{animation:none,none}");
12233    minify_test(".foo { animation: \"none\" none }", ".foo{animation:\"none\"}");
12234    minify_test(".foo { animation: none none }", ".foo{animation:none}");
12235
12236    // Test animation-name + animation-fill-mode
12237    minify_test(
12238      ".foo { animation: 2s both \"none\"}",
12239      ".foo{animation:2s both \"none\"}",
12240    );
12241    minify_test(
12242      ".foo { animation: both \"none\" 2s}",
12243      ".foo{animation:2s both \"none\"}",
12244    );
12245    minify_test(".foo { animation: \"none\" 2s none}", ".foo{animation:2s \"none\"}");
12246    minify_test(".foo { animation: none \"none\" 2s}", ".foo{animation:2s \"none\"}");
12247    minify_test(
12248      ".foo { animation: none, \"none\" 2s forwards}",
12249      ".foo{animation:none,2s forwards \"none\"}",
12250    );
12251
12252    minify_test(".foo { animation: \"unset\" }", ".foo{animation:\"unset\"}");
12253    minify_test(".foo { animation: \"string\" .5s }", ".foo{animation:.5s string}");
12254    minify_test(".foo { animation: \"unset\" .5s }", ".foo{animation:.5s \"unset\"}");
12255    minify_test(
12256      ".foo { animation: none, \"unset\" .5s}",
12257      ".foo{animation:none,.5s \"unset\"}",
12258    );
12259    minify_test(
12260      ".foo { animation: \"unset\" 0s 3s infinite, none }",
12261      ".foo{animation:0s 3s infinite \"unset\",none}",
12262    );
12263
12264    minify_test(".foo { animation: \"infinite\" 2s 1 }", ".foo{animation:2s 1 infinite}");
12265    minify_test(".foo { animation: \"paused\" 2s }", ".foo{animation:2s running paused}");
12266    minify_test(
12267      ".foo { animation: \"forwards\" 2s }",
12268      ".foo{animation:2s none forwards}",
12269    );
12270    minify_test(
12271      ".foo { animation: \"reverse\" 2s }",
12272      ".foo{animation:2s normal reverse}",
12273    );
12274    minify_test(
12275      ".foo { animation: \"reverse\" 2s alternate }",
12276      ".foo{animation:2s alternate reverse}",
12277    );
12278
12279    minify_test(
12280      ".foo { animation: 3s ease-in 1s infinite reverse both running slidein }",
12281      ".foo{animation:3s ease-in 1s infinite reverse both slidein}",
12282    );
12283    minify_test(
12284      ".foo { animation: 3s slidein paused ease 1s 1 reverse both }",
12285      ".foo{animation:3s 1s reverse both paused slidein}",
12286    );
12287    minify_test(".foo { animation: 3s ease ease }", ".foo{animation:3s ease ease}");
12288    minify_test(
12289      ".foo { animation: 3s cubic-bezier(0.25, 0.1, 0.25, 1) foo }",
12290      ".foo{animation:3s foo}",
12291    );
12292    minify_test(
12293      ".foo { animation: foo 0s 3s infinite }",
12294      ".foo{animation:0s 3s infinite foo}",
12295    );
12296    minify_test(".foo { animation: foo 3s --test }", ".foo{animation:3s foo --test}");
12297    minify_test(".foo { animation: foo 3s scroll() }", ".foo{animation:3s foo scroll()}");
12298    minify_test(
12299      ".foo { animation: foo 3s scroll(block) }",
12300      ".foo{animation:3s foo scroll()}",
12301    );
12302    minify_test(
12303      ".foo { animation: foo 3s scroll(root inline) }",
12304      ".foo{animation:3s foo scroll(root inline)}",
12305    );
12306    minify_test(
12307      ".foo { animation: foo 3s scroll(inline root) }",
12308      ".foo{animation:3s foo scroll(root inline)}",
12309    );
12310    minify_test(
12311      ".foo { animation: foo 3s scroll(inline nearest) }",
12312      ".foo{animation:3s foo scroll(inline)}",
12313    );
12314    minify_test(
12315      ".foo { animation: foo 3s view(block) }",
12316      ".foo{animation:3s foo view()}",
12317    );
12318    minify_test(
12319      ".foo { animation: foo 3s view(inline) }",
12320      ".foo{animation:3s foo view(inline)}",
12321    );
12322    minify_test(
12323      ".foo { animation: foo 3s view(inline 10px 10px) }",
12324      ".foo{animation:3s foo view(inline 10px)}",
12325    );
12326    minify_test(
12327      ".foo { animation: foo 3s view(inline 10px 12px) }",
12328      ".foo{animation:3s foo view(inline 10px 12px)}",
12329    );
12330    minify_test(
12331      ".foo { animation: foo 3s view(inline auto auto) }",
12332      ".foo{animation:3s foo view(inline)}",
12333    );
12334    minify_test(".foo { animation: foo 3s auto }", ".foo{animation:3s foo}");
12335    minify_test(".foo { animation-composition: add }", ".foo{animation-composition:add}");
12336    test(
12337      r#"
12338      .foo {
12339        animation-name: foo;
12340        animation-duration: 0.09s;
12341        animation-timing-function: ease-in-out;
12342        animation-iteration-count: 2;
12343        animation-direction: alternate;
12344        animation-play-state: running;
12345        animation-delay: 100ms;
12346        animation-fill-mode: forwards;
12347        animation-timeline: auto;
12348      }
12349    "#,
12350      indoc! {r#"
12351      .foo {
12352        animation: 90ms ease-in-out .1s 2 alternate forwards foo;
12353      }
12354    "#},
12355    );
12356    test(
12357      r#"
12358      .foo {
12359        animation-name: foo, bar;
12360        animation-duration: 0.09s, 200ms;
12361        animation-timing-function: ease-in-out, ease;
12362        animation-iteration-count: 2, 1;
12363        animation-direction: alternate, normal;
12364        animation-play-state: running, paused;
12365        animation-delay: 100ms, 0s;
12366        animation-fill-mode: forwards, none;
12367        animation-timeline: auto, auto;
12368      }
12369    "#,
12370      indoc! {r#"
12371      .foo {
12372        animation: 90ms ease-in-out .1s 2 alternate forwards foo, .2s paused bar;
12373      }
12374    "#},
12375    );
12376    test(
12377      r#"
12378      .foo {
12379        animation: bar 200ms;
12380        animation-timing-function: ease-in-out;
12381      }
12382    "#,
12383      indoc! {r#"
12384      .foo {
12385        animation: .2s ease-in-out bar;
12386      }
12387    "#},
12388    );
12389    test(
12390      r#"
12391      .foo {
12392        animation: bar 200ms;
12393        animation-timing-function: var(--ease);
12394      }
12395    "#,
12396      indoc! {r#"
12397      .foo {
12398        animation: .2s bar;
12399        animation-timing-function: var(--ease);
12400      }
12401    "#},
12402    );
12403    test(
12404      r#"
12405      .foo {
12406        animation-name: foo, bar;
12407        animation-duration: 0.09s;
12408        animation-timing-function: ease-in-out;
12409        animation-iteration-count: 2;
12410        animation-direction: alternate;
12411        animation-play-state: running;
12412        animation-delay: 100ms;
12413        animation-fill-mode: forwards;
12414        animation-timeline: auto;
12415      }
12416    "#,
12417      indoc! {r#"
12418      .foo {
12419        animation-name: foo, bar;
12420        animation-duration: 90ms;
12421        animation-timing-function: ease-in-out;
12422        animation-iteration-count: 2;
12423        animation-direction: alternate;
12424        animation-play-state: running;
12425        animation-delay: .1s;
12426        animation-fill-mode: forwards;
12427        animation-timeline: auto;
12428      }
12429    "#},
12430    );
12431    test(
12432      r#"
12433      .foo {
12434        animation-name: foo;
12435        animation-duration: 0.09s;
12436        animation-timing-function: ease-in-out;
12437        animation-iteration-count: 2;
12438        animation-direction: alternate;
12439        animation-play-state: running;
12440        animation-delay: 100ms;
12441        animation-fill-mode: forwards;
12442        animation-timeline: scroll();
12443      }
12444    "#,
12445      indoc! {r#"
12446      .foo {
12447        animation: 90ms ease-in-out .1s 2 alternate forwards foo scroll();
12448      }
12449    "#},
12450    );
12451    test(
12452      r#"
12453      .foo {
12454        animation-name: foo;
12455        animation-duration: 0.09s;
12456        animation-timing-function: ease-in-out;
12457        animation-iteration-count: 2;
12458        animation-direction: alternate;
12459        animation-play-state: running;
12460        animation-delay: 100ms;
12461        animation-fill-mode: forwards;
12462        animation-timeline: scroll(), view();
12463      }
12464    "#,
12465      indoc! {r#"
12466      .foo {
12467        animation-name: foo;
12468        animation-duration: 90ms;
12469        animation-timing-function: ease-in-out;
12470        animation-iteration-count: 2;
12471        animation-direction: alternate;
12472        animation-play-state: running;
12473        animation-delay: .1s;
12474        animation-fill-mode: forwards;
12475        animation-timeline: scroll(), view();
12476      }
12477    "#},
12478    );
12479    test(
12480      r#"
12481      .foo {
12482        -webkit-animation-name: foo;
12483        -webkit-animation-duration: 0.09s;
12484        -webkit-animation-timing-function: ease-in-out;
12485        -webkit-animation-iteration-count: 2;
12486        -webkit-animation-direction: alternate;
12487        -webkit-animation-play-state: running;
12488        -webkit-animation-delay: 100ms;
12489        -webkit-animation-fill-mode: forwards;
12490      }
12491    "#,
12492      indoc! {r#"
12493      .foo {
12494        -webkit-animation: 90ms ease-in-out .1s 2 alternate forwards foo;
12495      }
12496    "#},
12497    );
12498    test(
12499      r#"
12500      .foo {
12501        -moz-animation: bar 200ms;
12502        -moz-animation-timing-function: ease-in-out;
12503      }
12504    "#,
12505      indoc! {r#"
12506      .foo {
12507        -moz-animation: .2s ease-in-out bar;
12508      }
12509    "#},
12510    );
12511    test(
12512      r#"
12513      .foo {
12514        -webkit-animation: bar 200ms;
12515        -webkit-animation-timing-function: ease-in-out;
12516        -moz-animation: bar 200ms;
12517        -moz-animation-timing-function: ease-in-out;
12518      }
12519    "#,
12520      indoc! {r#"
12521      .foo {
12522        -webkit-animation: .2s ease-in-out bar;
12523        -moz-animation: .2s ease-in-out bar;
12524      }
12525    "#},
12526    );
12527
12528    prefix_test(
12529      r#"
12530      .foo {
12531        animation: .2s ease-in-out bar;
12532      }
12533    "#,
12534      indoc! {r#"
12535      .foo {
12536        -webkit-animation: .2s ease-in-out bar;
12537        -moz-animation: .2s ease-in-out bar;
12538        animation: .2s ease-in-out bar;
12539      }
12540    "#},
12541      Browsers {
12542        firefox: Some(6 << 16),
12543        safari: Some(6 << 16),
12544        ..Browsers::default()
12545      },
12546    );
12547
12548    prefix_test(
12549      r#"
12550      .foo {
12551        -webkit-animation: .2s ease-in-out bar;
12552        -moz-animation: .2s ease-in-out bar;
12553        animation: .2s ease-in-out bar;
12554      }
12555    "#,
12556      indoc! {r#"
12557      .foo {
12558        animation: .2s ease-in-out bar;
12559      }
12560    "#},
12561      Browsers {
12562        firefox: Some(20 << 16),
12563        safari: Some(14 << 16),
12564        ..Browsers::default()
12565      },
12566    );
12567    prefix_test(
12568      r#"
12569      .foo {
12570        animation: 200ms var(--ease) bar;
12571      }
12572    "#,
12573      indoc! {r#"
12574      .foo {
12575        -webkit-animation: .2s var(--ease) bar;
12576        -moz-animation: .2s var(--ease) bar;
12577        animation: .2s var(--ease) bar;
12578      }
12579    "#},
12580      Browsers {
12581        firefox: Some(6 << 16),
12582        safari: Some(6 << 16),
12583        ..Browsers::default()
12584      },
12585    );
12586
12587    prefix_test(
12588      r#"
12589      .foo {
12590        animation: .2s ease-in-out bar scroll();
12591      }
12592    "#,
12593      indoc! {r#"
12594      .foo {
12595        animation: .2s ease-in-out bar;
12596        animation-timeline: scroll();
12597      }
12598    "#},
12599      Browsers {
12600        safari: Some(16 << 16),
12601        ..Browsers::default()
12602      },
12603    );
12604    prefix_test(
12605      r#"
12606      .foo {
12607        animation: .2s ease-in-out bar scroll();
12608      }
12609    "#,
12610      indoc! {r#"
12611      .foo {
12612        animation: .2s ease-in-out bar scroll();
12613      }
12614    "#},
12615      Browsers {
12616        chrome: Some(120 << 16),
12617        ..Browsers::default()
12618      },
12619    );
12620    prefix_test(
12621      r#"
12622      .foo {
12623        animation: .2s ease-in-out bar scroll();
12624      }
12625    "#,
12626      indoc! {r#"
12627      .foo {
12628        -webkit-animation: .2s ease-in-out bar;
12629        animation: .2s ease-in-out bar;
12630        animation-timeline: scroll();
12631      }
12632    "#},
12633      Browsers {
12634        safari: Some(6 << 16),
12635        ..Browsers::default()
12636      },
12637    );
12638
12639    minify_test(
12640      ".foo { animation-range-start: entry 10% }",
12641      ".foo{animation-range-start:entry 10%}",
12642    );
12643    minify_test(
12644      ".foo { animation-range-start: entry 0% }",
12645      ".foo{animation-range-start:entry}",
12646    );
12647    minify_test(
12648      ".foo { animation-range-start: entry }",
12649      ".foo{animation-range-start:entry}",
12650    );
12651    minify_test(".foo { animation-range-start: 50% }", ".foo{animation-range-start:50%}");
12652    minify_test(
12653      ".foo { animation-range-end: exit 10% }",
12654      ".foo{animation-range-end:exit 10%}",
12655    );
12656    minify_test(
12657      ".foo { animation-range-end: exit 100% }",
12658      ".foo{animation-range-end:exit}",
12659    );
12660    minify_test(".foo { animation-range-end: exit }", ".foo{animation-range-end:exit}");
12661    minify_test(".foo { animation-range-end: 50% }", ".foo{animation-range-end:50%}");
12662    minify_test(
12663      ".foo { animation-range: entry 10% exit 90% }",
12664      ".foo{animation-range:entry 10% exit 90%}",
12665    );
12666    minify_test(
12667      ".foo { animation-range: entry 0% exit 100% }",
12668      ".foo{animation-range:entry exit}",
12669    );
12670    minify_test(".foo { animation-range: entry }", ".foo{animation-range:entry}");
12671    minify_test(
12672      ".foo { animation-range: entry 0% entry 100% }",
12673      ".foo{animation-range:entry}",
12674    );
12675    minify_test(".foo { animation-range: 50% normal }", ".foo{animation-range:50%}");
12676    minify_test(
12677      ".foo { animation-range: normal normal }",
12678      ".foo{animation-range:normal}",
12679    );
12680    test(
12681      r#"
12682      .foo {
12683        animation-range-start: entry 10%;
12684        animation-range-end: exit 90%;
12685      }
12686      "#,
12687      indoc! {r#"
12688      .foo {
12689        animation-range: entry 10% exit 90%;
12690      }
12691      "#},
12692    );
12693    test(
12694      r#"
12695      .foo {
12696        animation-range-start: entry 0%;
12697        animation-range-end: entry 100%;
12698      }
12699      "#,
12700      indoc! {r#"
12701      .foo {
12702        animation-range: entry;
12703      }
12704      "#},
12705    );
12706    test(
12707      r#"
12708      .foo {
12709        animation-range-start: entry 0%;
12710        animation-range-end: exit 100%;
12711      }
12712      "#,
12713      indoc! {r#"
12714      .foo {
12715        animation-range: entry exit;
12716      }
12717      "#},
12718    );
12719    test(
12720      r#"
12721      .foo {
12722        animation-range-start: 10%;
12723        animation-range-end: normal;
12724      }
12725      "#,
12726      indoc! {r#"
12727      .foo {
12728        animation-range: 10%;
12729      }
12730      "#},
12731    );
12732    test(
12733      r#"
12734      .foo {
12735        animation-range-start: 10%;
12736        animation-range-end: 90%;
12737      }
12738      "#,
12739      indoc! {r#"
12740      .foo {
12741        animation-range: 10% 90%;
12742      }
12743      "#},
12744    );
12745    test(
12746      r#"
12747      .foo {
12748        animation-range-start: entry 10%;
12749        animation-range-end: exit 100%;
12750      }
12751      "#,
12752      indoc! {r#"
12753      .foo {
12754        animation-range: entry 10% exit;
12755      }
12756      "#},
12757    );
12758    test(
12759      r#"
12760      .foo {
12761        animation-range-start: 10%;
12762        animation-range-end: exit 90%;
12763      }
12764      "#,
12765      indoc! {r#"
12766      .foo {
12767        animation-range: 10% exit 90%;
12768      }
12769      "#},
12770    );
12771    test(
12772      r#"
12773      .foo {
12774        animation-range-start: entry 10%;
12775        animation-range-end: 90%;
12776      }
12777      "#,
12778      indoc! {r#"
12779      .foo {
12780        animation-range: entry 10% 90%;
12781      }
12782      "#},
12783    );
12784    test(
12785      r#"
12786      .foo {
12787        animation-range: entry;
12788        animation-range-end: 90%;
12789      }
12790      "#,
12791      indoc! {r#"
12792      .foo {
12793        animation-range: entry 90%;
12794      }
12795      "#},
12796    );
12797    test(
12798      r#"
12799      .foo {
12800        animation-range: entry;
12801        animation-range-end: var(--end);
12802      }
12803      "#,
12804      indoc! {r#"
12805      .foo {
12806        animation-range: entry;
12807        animation-range-end: var(--end);
12808      }
12809      "#},
12810    );
12811    test(
12812      r#"
12813      .foo {
12814        animation-range-start: entry 10%, entry 50%;
12815        animation-range-end: exit 90%;
12816      }
12817      "#,
12818      indoc! {r#"
12819      .foo {
12820        animation-range-start: entry 10%, entry 50%;
12821        animation-range-end: exit 90%;
12822      }
12823      "#},
12824    );
12825    test(
12826      r#"
12827      .foo {
12828        animation-range-start: entry 10%, entry 50%;
12829        animation-range-end: exit 90%, exit 100%;
12830      }
12831      "#,
12832      indoc! {r#"
12833      .foo {
12834        animation-range: entry 10% exit 90%, entry 50% exit;
12835      }
12836      "#},
12837    );
12838    test(
12839      r#"
12840      .foo {
12841        animation-range: entry;
12842        animation-range-end: 90%;
12843        animation: spin 100ms;
12844      }
12845      "#,
12846      indoc! {r#"
12847      .foo {
12848        animation: .1s spin;
12849      }
12850      "#},
12851    );
12852    test(
12853      r#"
12854      .foo {
12855        animation: spin 100ms;
12856        animation-range: entry;
12857        animation-range-end: 90%;
12858      }
12859      "#,
12860      indoc! {r#"
12861      .foo {
12862        animation: .1s spin;
12863        animation-range: entry 90%;
12864      }
12865      "#},
12866    );
12867    test(
12868      r#"
12869      .foo {
12870        animation-range: entry;
12871        animation-range-end: 90%;
12872        animation: var(--animation) 100ms;
12873      }
12874      "#,
12875      indoc! {r#"
12876      .foo {
12877        animation: var(--animation) .1s;
12878      }
12879      "#},
12880    );
12881  }
12882
12883  #[test]
12884  fn test_transform() {
12885    test(
12886      ".foo { transform: perspective(500px)translate3d(10px, 0, 20px)rotateY(30deg) }",
12887      indoc! {r#"
12888      .foo {
12889        transform: perspective(500px) translate3d(10px, 0, 20px) rotateY(30deg);
12890      }
12891      "#},
12892    );
12893    test(
12894      ".foo { transform: translate3d(12px,50%,3em)scale(2,.5) }",
12895      indoc! {r#"
12896      .foo {
12897        transform: translate3d(12px, 50%, 3em) scale(2, .5);
12898      }
12899      "#},
12900    );
12901    test(
12902      ".foo { transform:matrix(1,2,-1,1,80,80) }",
12903      indoc! {r#"
12904      .foo {
12905        transform: matrix(1, 2, -1, 1, 80, 80);
12906      }
12907      "#},
12908    );
12909
12910    minify_test(
12911      ".foo { transform: scale(  0.5 )translateX(10px ) }",
12912      ".foo{transform:scale(.5)translate(10px)}",
12913    );
12914    minify_test(
12915      ".foo { transform: translate(2px, 3px)",
12916      ".foo{transform:translate(2px,3px)}",
12917    );
12918    minify_test(
12919      ".foo { transform: translate(2px, 0px)",
12920      ".foo{transform:translate(2px)}",
12921    );
12922    minify_test(
12923      ".foo { transform: translate(0px, 2px)",
12924      ".foo{transform:translateY(2px)}",
12925    );
12926    minify_test(".foo { transform: translateX(2px)", ".foo{transform:translate(2px)}");
12927    minify_test(".foo { transform: translateY(2px)", ".foo{transform:translateY(2px)}");
12928    minify_test(".foo { transform: translateZ(2px)", ".foo{transform:translateZ(2px)}");
12929    minify_test(
12930      ".foo { transform: translate3d(2px, 3px, 4px)",
12931      ".foo{transform:translate3d(2px,3px,4px)}",
12932    );
12933    minify_test(
12934      ".foo { transform: translate3d(10%, 20%, 4px)",
12935      ".foo{transform:translate3d(10%,20%,4px)}",
12936    );
12937    minify_test(
12938      ".foo { transform: translate3d(2px, 0px, 0px)",
12939      ".foo{transform:translate(2px)}",
12940    );
12941    minify_test(
12942      ".foo { transform: translate3d(0px, 2px, 0px)",
12943      ".foo{transform:translateY(2px)}",
12944    );
12945    minify_test(
12946      ".foo { transform: translate3d(0px, 0px, 2px)",
12947      ".foo{transform:translateZ(2px)}",
12948    );
12949    minify_test(
12950      ".foo { transform: translate3d(2px, 3px, 0px)",
12951      ".foo{transform:translate(2px,3px)}",
12952    );
12953    minify_test(".foo { transform: scale(2, 3)", ".foo{transform:scale(2,3)}");
12954    minify_test(".foo { transform: scale(10%, 20%)", ".foo{transform:scale(.1,.2)}");
12955    minify_test(".foo { transform: scale(2, 2)", ".foo{transform:scale(2)}");
12956    minify_test(".foo { transform: scale(2, 1)", ".foo{transform:scaleX(2)}");
12957    minify_test(".foo { transform: scale(1, 2)", ".foo{transform:scaleY(2)}");
12958    minify_test(".foo { transform: scaleX(2)", ".foo{transform:scaleX(2)}");
12959    minify_test(".foo { transform: scaleY(2)", ".foo{transform:scaleY(2)}");
12960    minify_test(".foo { transform: scaleZ(2)", ".foo{transform:scaleZ(2)}");
12961    minify_test(".foo { transform: scale3d(2, 3, 4)", ".foo{transform:scale3d(2,3,4)}");
12962    minify_test(".foo { transform: scale3d(2, 1, 1)", ".foo{transform:scaleX(2)}");
12963    minify_test(".foo { transform: scale3d(1, 2, 1)", ".foo{transform:scaleY(2)}");
12964    minify_test(".foo { transform: scale3d(1, 1, 2)", ".foo{transform:scaleZ(2)}");
12965    minify_test(".foo { transform: scale3d(2, 2, 1)", ".foo{transform:scale(2)}");
12966
12967    // transform: scale(), Convert <percentage> to <number>
12968    test(
12969      ".foo { transform: scale3d(50%, 1, 200%) }",
12970      indoc! {r#"
12971      .foo {
12972        transform: scale3d(.5, 1, 2);
12973      }
12974      "#},
12975    );
12976    minify_test(".foo { transform: scale(1%) }", ".foo{transform:scale(.01)}");
12977    minify_test(".foo { transform: scale(0%) }", ".foo{transform:scale(0)}");
12978    minify_test(".foo { transform: scale(0.0%) }", ".foo{transform:scale(0)}");
12979    minify_test(".foo { transform: scale(-0%) }", ".foo{transform:scale(0)}");
12980    minify_test(".foo { transform: scale(-0) }", ".foo{transform:scale(0)}");
12981    minify_test(".foo { transform: scale(-0.0) }", ".foo{transform:scale(0)}");
12982    minify_test(".foo { transform: scale(100%) }", ".foo{transform:scale(1)}");
12983    minify_test(".foo { transform: scale(-100%) }", ".foo{transform:scale(-1)}");
12984    minify_test(".foo { transform: scale(68%) }", ".foo{transform:scale(.68)}");
12985    minify_test(".foo { transform: scale(5.96%) }", ".foo{transform:scale(.0596)}");
12986    // Match WPT coverage for repeated and multi-value percentages.
12987    minify_test(".foo { transform: scale(100%, 100%) }", ".foo{transform:scale(1)}");
12988    minify_test(".foo { transform: scale3d(100%, 100%, 1) }", ".foo{transform:scale(1)}");
12989    minify_test(".foo { transform: scale(-100%, -100%) }", ".foo{transform:scale(-1)}");
12990    minify_test(
12991      ".foo { transform: scale3d(-100%, -100%, 1) }",
12992      ".foo{transform:scale(-1)}",
12993    );
12994    minify_test(".foo { transform: scale(100%, 200%) }", ".foo{transform:scaleY(2)}");
12995    minify_test(
12996      ".foo { transform: scale3d(100%, 200%, 1) }",
12997      ".foo{transform:scaleY(2)}",
12998    );
12999    minify_test(
13000      ".foo { transform: scale3d(100%, 100%, 0%) }",
13001      ".foo{transform:scaleZ(0)}",
13002    );
13003    minify_test(
13004      ".foo { transform: scale3d(100%, 100%, 100%) }",
13005      ".foo{transform:scale(1)}",
13006    );
13007    minify_test(
13008      ".foo { transform: scale3d(-0%, -0%, -0%) }",
13009      ".foo{transform:scale3d(0,0,0)}",
13010    );
13011    // Additional edge cases: mixed inputs and computed percentages.
13012    minify_test(".foo { transform: scale(2, 100%) }", ".foo{transform:scaleX(2)}");
13013    minify_test(".foo { transform: scale(2, -50%) }", ".foo{transform:scale(2,-.5)}");
13014    minify_test(".foo { transform: scale(-90%, -1) }", ".foo{transform:scale(-.9,-1)}");
13015    minify_test(
13016      ".foo { transform: scale(calc(10% + 20%)) }",
13017      ".foo{transform:scale(.3)}",
13018    );
13019    minify_test(
13020      ".foo { transform: scale(calc(150% - 50%), 200%) }",
13021      ".foo{transform:scaleY(2)}",
13022    );
13023    minify_test(
13024      ".foo { transform: scale(200%, calc(50% - 80%)) }",
13025      ".foo{transform:scale(2,-.3)}",
13026    );
13027    // TODO: For infinite decimals, please do not attempt to resolve calc
13028    // Expected: calc(1 / 3)
13029    // https://github.com/parcel-bundler/lightningcss/issues/12
13030    minify_test(
13031      ".foo { transform: scale(calc(100% / 3)) }",
13032      ".foo{transform:scale(.333333)}",
13033    );
13034    // Transform::ScaleX/Y/Z
13035    minify_test(".foo { transform: scaleX(10%) }", ".foo{transform:scaleX(.1)}");
13036    minify_test(".foo { transform: scaleY(20%) }", ".foo{transform:scaleY(.2)}");
13037    minify_test(".foo { transform: scaleZ(30%) }", ".foo{transform:scaleZ(.3)}");
13038    minify_test(".foo { transform: scaleX(0%) }", ".foo{transform:scaleX(0)}");
13039    minify_test(".foo { transform: scaleX(-0%) }", ".foo{transform:scaleX(0)}");
13040    minify_test(
13041      ".foo { transform: scaleX(calc(10% + 20%)) }",
13042      ".foo{transform:scaleX(.3)}",
13043    );
13044    minify_test(
13045      ".foo { transform: scaleX(calc(180% - 20%)) }",
13046      ".foo{transform:scaleX(1.6)}",
13047    );
13048    minify_test(
13049      ".foo { transform: scaleX(calc(50% - 80%)) }",
13050      ".foo{transform:scaleX(-.3)}",
13051    );
13052
13053    minify_test(".foo { transform: rotate(20deg)", ".foo{transform:rotate(20deg)}");
13054    minify_test(".foo { transform: rotateX(20deg)", ".foo{transform:rotateX(20deg)}");
13055    minify_test(".foo { transform: rotateY(20deg)", ".foo{transform:rotateY(20deg)}");
13056    minify_test(".foo { transform: rotateZ(20deg)", ".foo{transform:rotate(20deg)}");
13057    minify_test(".foo { transform: rotate(360deg)", ".foo{transform:rotate(360deg)}");
13058    minify_test(
13059      ".foo { transform: rotate3d(2, 3, 4, 20deg)",
13060      ".foo{transform:rotate3d(2,3,4,20deg)}",
13061    );
13062    minify_test(
13063      ".foo { transform: rotate3d(1, 0, 0, 20deg)",
13064      ".foo{transform:rotateX(20deg)}",
13065    );
13066    minify_test(
13067      ".foo { transform: rotate3d(0, 1, 0, 20deg)",
13068      ".foo{transform:rotateY(20deg)}",
13069    );
13070    minify_test(
13071      ".foo { transform: rotate3d(0, 0, 1, 20deg)",
13072      ".foo{transform:rotate(20deg)}",
13073    );
13074    minify_test(".foo { transform: rotate(405deg)}", ".foo{transform:rotate(405deg)}");
13075    minify_test(".foo { transform: rotateX(405deg)}", ".foo{transform:rotateX(405deg)}");
13076    minify_test(".foo { transform: rotateY(405deg)}", ".foo{transform:rotateY(405deg)}");
13077    minify_test(".foo { transform: rotate(-200deg)}", ".foo{transform:rotate(-200deg)}");
13078    minify_test(".foo { transform: rotate(0)", ".foo{transform:rotate(0)}");
13079    minify_test(".foo { transform: rotate(0deg)", ".foo{transform:rotate(0)}");
13080    minify_test(
13081      ".foo { transform: rotateX(-200deg)}",
13082      ".foo{transform:rotateX(-200deg)}",
13083    );
13084    minify_test(
13085      ".foo { transform: rotateY(-200deg)}",
13086      ".foo{transform:rotateY(-200deg)}",
13087    );
13088    minify_test(
13089      ".foo { transform: rotate3d(1, 1, 0, -200deg)",
13090      ".foo{transform:rotate3d(1,1,0,-200deg)}",
13091    );
13092    minify_test(".foo { transform: skew(20deg)", ".foo{transform:skew(20deg)}");
13093    minify_test(".foo { transform: skew(20deg, 0deg)", ".foo{transform:skew(20deg)}");
13094    minify_test(".foo { transform: skew(0deg, 20deg)", ".foo{transform:skewY(20deg)}");
13095    minify_test(".foo { transform: skewX(20deg)", ".foo{transform:skew(20deg)}");
13096    minify_test(".foo { transform: skewY(20deg)", ".foo{transform:skewY(20deg)}");
13097    minify_test(
13098      ".foo { transform: perspective(10px)",
13099      ".foo{transform:perspective(10px)}",
13100    );
13101    minify_test(
13102      ".foo { transform: matrix(1, 2, -1, 1, 80, 80)",
13103      ".foo{transform:matrix(1,2,-1,1,80,80)}",
13104    );
13105    minify_test(
13106      ".foo { transform: matrix3d(1, 0, 0, 0, 0, 1, 6, 0, 0, 0, 1, 0, 50, 100, 0, 1.1)",
13107      ".foo{transform:matrix3d(1,0,0,0,0,1,6,0,0,0,1,0,50,100,0,1.1)}",
13108    );
13109    // TODO: Re-enable with a better solution
13110    //       See: https://github.com/parcel-bundler/lightningcss/issues/288
13111    // minify_test(
13112    //   ".foo{transform:translate(100px,200px) rotate(45deg) skew(10deg) scale(2)}",
13113    //   ".foo{transform:matrix(1.41421,1.41421,-1.16485,1.66358,100,200)}",
13114    // );
13115    // minify_test(
13116    //   ".foo{transform:translate(200px,300px) translate(100px,200px) scale(2)}",
13117    //   ".foo{transform:matrix(2,0,0,2,300,500)}",
13118    // );
13119    minify_test(
13120      ".foo{transform:translate(100px,200px) rotate(45deg)}",
13121      ".foo{transform:translate(100px,200px)rotate(45deg)}",
13122    );
13123    minify_test(
13124      ".foo{transform:rotate3d(1, 1, 1, 45deg) translate3d(100px, 100px, 10px)}",
13125      ".foo{transform:rotate3d(1,1,1,45deg)translate3d(100px,100px,10px)}",
13126    );
13127    // TODO: Re-enable with a better solution
13128    //       See: https://github.com/parcel-bundler/lightningcss/issues/288
13129    // minify_test(
13130    //   ".foo{transform:translate3d(100px, 100px, 10px) skew(10deg) scale3d(2, 3, 4)}",
13131    //   ".foo{transform:matrix3d(2,0,0,0,.528981,3,0,0,0,0,4,0,100,100,10,1)}",
13132    // );
13133    // minify_test(
13134    //   ".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)}",
13135    //   ".foo{transform:translate3d(100px,100px,10px)rotate3d(1,1,1,45deg)}"
13136    // );
13137    // minify_test(
13138    //   ".foo{transform:matrix3d(1, 0, 0, 0, 0, 0.7071067811865476, 0.7071067811865475, 0, 0, -0.7071067811865475, 0.7071067811865476, 0, 100, 100, 10, 1)}",
13139    //   ".foo{transform:translate3d(100px,100px,10px)rotateX(45deg)}"
13140    // );
13141    // minify_test(
13142    //   ".foo{transform:translate3d(100px, 200px, 10px) translate(100px, 100px)}",
13143    //   ".foo{transform:translate3d(200px,300px,10px)}",
13144    // );
13145    // minify_test(
13146    //   ".foo{transform:rotate(45deg) rotate(45deg)}",
13147    //   ".foo{transform:rotate(90deg)}",
13148    // );
13149    // minify_test(
13150    //   ".foo{transform:matrix(0.7071067811865476, 0.7071067811865475, -0.7071067811865475, 0.7071067811865476, 100, 100)}",
13151    //   ".foo{transform:translate(100px,100px)rotate(45deg)}"
13152    // );
13153    // minify_test(
13154    //   ".foo{transform:translateX(2in) translateX(50px)}",
13155    //   ".foo{transform:translate(242px)}",
13156    // );
13157    minify_test(
13158      ".foo{transform:translateX(calc(2in + 50px))}",
13159      ".foo{transform:translate(242px)}",
13160    );
13161    minify_test(".foo{transform:translateX(50%)}", ".foo{transform:translate(50%)}");
13162    minify_test(
13163      ".foo{transform:translateX(calc(50% - 100px + 20px))}",
13164      ".foo{transform:translate(calc(50% - 80px))}",
13165    );
13166    minify_test(
13167      ".foo{transform:rotate(calc(10deg + 20deg))}",
13168      ".foo{transform:rotate(30deg)}",
13169    );
13170    minify_test(
13171      ".foo{transform:rotate(calc(10deg + 0.349066rad))}",
13172      ".foo{transform:rotate(30deg)}",
13173    );
13174    minify_test(
13175      ".foo{transform:rotate(calc(10deg + 1.5turn))}",
13176      ".foo{transform:rotate(550deg)}",
13177    );
13178    minify_test(
13179      ".foo{transform:rotate(calc(10deg * 2))}",
13180      ".foo{transform:rotate(20deg)}",
13181    );
13182    minify_test(
13183      ".foo{transform:rotate(calc(-10deg * 2))}",
13184      ".foo{transform:rotate(-20deg)}",
13185    );
13186    minify_test(
13187      ".foo{transform:rotate(calc(10deg + var(--test)))}",
13188      ".foo{transform:rotate(calc(10deg + var(--test)))}",
13189    );
13190    minify_test(".foo { transform: scale(calc(.1 + .2))", ".foo{transform:scale(.3)}");
13191
13192    minify_test(
13193      ".foo { -webkit-transform: scale(calc(10% + 20%))",
13194      ".foo{-webkit-transform:scale(.3)}",
13195    );
13196
13197    minify_test(".foo { translate: 1px 2px 3px }", ".foo{translate:1px 2px 3px}");
13198    minify_test(".foo { translate: 1px 0px 0px }", ".foo{translate:1px}");
13199    minify_test(".foo { translate: 1px 2px 0px }", ".foo{translate:1px 2px}");
13200    minify_test(".foo { translate: 1px 0px 2px }", ".foo{translate:1px 0 2px}");
13201    minify_test(".foo { translate: none }", ".foo{translate:none}");
13202    minify_test(".foo { rotate: none }", ".foo{rotate:none}");
13203    minify_test(".foo { rotate: 0deg }", ".foo{rotate:0deg}");
13204    minify_test(".foo { rotate: -0deg }", ".foo{rotate:0deg}");
13205    minify_test(".foo { rotate: 10deg }", ".foo{rotate:10deg}");
13206    minify_test(".foo { rotate: z 10deg }", ".foo{rotate:10deg}");
13207    minify_test(".foo { rotate: 0 0 1 10deg }", ".foo{rotate:10deg}");
13208    minify_test(".foo { rotate: x 10deg }", ".foo{rotate:x 10deg}");
13209    minify_test(".foo { rotate: 1 0 0 10deg }", ".foo{rotate:x 10deg}");
13210    minify_test(".foo { rotate: 2 0 0 10deg }", ".foo{rotate:x 10deg}");
13211    minify_test(".foo { rotate: 0 2 0 10deg }", ".foo{rotate:y 10deg}");
13212    minify_test(".foo { rotate: 0 0 2 10deg }", ".foo{rotate:10deg}");
13213    minify_test(".foo { rotate: 0 0 5.3 10deg }", ".foo{rotate:10deg}");
13214    minify_test(".foo { rotate: 0 0 1 0deg }", ".foo{rotate:0deg}");
13215    minify_test(".foo { rotate: 10deg 0 0 -1 }", ".foo{rotate:-10deg}");
13216    minify_test(".foo { rotate: 10deg 0 0 -233 }", ".foo{rotate:-10deg}");
13217    minify_test(".foo { rotate: -1 0 0 0deg }", ".foo{rotate:x 0deg}");
13218    minify_test(".foo { rotate: 0deg 0 0 1 }", ".foo{rotate:0deg}");
13219    minify_test(".foo { rotate: 0deg 0 0 -1 }", ".foo{rotate:0deg}");
13220    minify_test(".foo { rotate: 0 1 0 10deg }", ".foo{rotate:y 10deg}");
13221    minify_test(".foo { rotate: x 0rad }", ".foo{rotate:x 0deg}");
13222    // TODO: In minify mode, convert units to the shortest form.
13223    // minify_test(".foo { rotate: y 0turn }", ".foo{rotate:y 0deg}");
13224    minify_test(".foo { rotate: z 0deg }", ".foo{rotate:0deg}");
13225    minify_test(".foo { rotate: 10deg y }", ".foo{rotate:y 10deg}");
13226    minify_test(".foo { rotate: 1 1 1 10deg }", ".foo{rotate:1 1 1 10deg}");
13227    minify_test(".foo { scale: 1 }", ".foo{scale:1}");
13228    minify_test(".foo { scale: 1 1 }", ".foo{scale:1}");
13229    minify_test(".foo { scale: 1 1 1 }", ".foo{scale:1}");
13230    minify_test(".foo { scale: none }", ".foo{scale:none}");
13231    minify_test(".foo { scale: 1 0 }", ".foo{scale:1 0}");
13232    minify_test(".foo { scale: 1 0 1 }", ".foo{scale:1 0}");
13233    minify_test(".foo { scale: 1 0 0 }", ".foo{scale:1 0 0}");
13234
13235    // scale, Convert <percentage> to <number>
13236    test(
13237      ".foo { scale: 50% 1 200% }",
13238      indoc! {r#"
13239      .foo {
13240        scale: .5 1 2;
13241      }
13242      "#},
13243    );
13244    minify_test(".foo { scale: 1% }", ".foo{scale:.01}");
13245    minify_test(".foo { scale: 0% }", ".foo{scale:0}");
13246    minify_test(".foo { scale: 0.0% }", ".foo{scale:0}");
13247    minify_test(".foo { scale: -0% }", ".foo{scale:0}");
13248    minify_test(".foo { scale: -0 }", ".foo{scale:0}");
13249    minify_test(".foo { scale: -0.0 }", ".foo{scale:0}");
13250    minify_test(".foo { scale: 100% }", ".foo{scale:1}");
13251    minify_test(".foo { scale: -100% }", ".foo{scale:-1}");
13252    minify_test(".foo { scale: 68% }", ".foo{scale:.68}");
13253    minify_test(".foo { scale: 5.96% }", ".foo{scale:.0596}");
13254    // Match WPT coverage for repeated and multi-value percentages.
13255    minify_test(".foo { scale: 100% 100% }", ".foo{scale:1}");
13256    minify_test(".foo { scale: 100% 100% 1 }", ".foo{scale:1}");
13257    minify_test(".foo { scale: -100% -100% }", ".foo{scale:-1}");
13258    minify_test(".foo { scale: -100% -100% 1 }", ".foo{scale:-1}");
13259    minify_test(".foo { scale: 100% 200% }", ".foo{scale:1 2}");
13260    minify_test(".foo { scale: 100% 200% 1 }", ".foo{scale:1 2}");
13261    minify_test(".foo { scale: 100% 100% 0% }", ".foo{scale:1 1 0}");
13262    minify_test(".foo { scale: 100% 100% 100% }", ".foo{scale:1}");
13263    minify_test(".foo { scale: -0% -0% -0% }", ".foo{scale:0 0 0}");
13264    // Additional edge cases: mixed inputs and computed percentages.
13265    minify_test(".foo { scale: 2 100% }", ".foo{scale:2 1}");
13266    minify_test(".foo { scale: 2 -50% }", ".foo{scale:2 -.5}");
13267    minify_test(".foo { scale: -90% -1 }", ".foo{scale:-.9 -1}");
13268    minify_test(".foo { scale: calc(10% + 20%) }", ".foo{scale:.3}");
13269    minify_test(".foo { scale: calc(150% - 50%) 200% }", ".foo{scale:1 2}");
13270    minify_test(".foo { scale: 200% calc(50% - 80%) }", ".foo{scale:2 -.3}");
13271    // TODO: For infinite decimals, please do not attempt to resolve calc
13272    // Expected: calc(1 / 3)
13273    // https://github.com/parcel-bundler/lightningcss/issues/12
13274    minify_test(".foo { scale: calc(100% / 3) }", ".foo{scale:.333333}");
13275
13276    assert_eq!(
13277      Property::Scale(crate::properties::transform::Scale::XYZ {
13278        x: crate::values::percentage::NumberOrPercentage::Percentage(crate::values::percentage::Percentage(0.5)),
13279        y: crate::values::percentage::NumberOrPercentage::Percentage(crate::values::percentage::Percentage(2.0)),
13280        z: crate::values::percentage::NumberOrPercentage::Percentage(crate::values::percentage::Percentage(1.0)),
13281      })
13282      .to_css_string(
13283        false,
13284        PrinterOptions {
13285          minify: true,
13286          ..PrinterOptions::default()
13287        },
13288      )
13289      .unwrap(),
13290      "scale:.5 2"
13291    );
13292    assert_eq!(
13293      Property::Transform(
13294        crate::properties::transform::TransformList(vec![crate::properties::transform::Transform::ScaleX(
13295          crate::values::percentage::NumberOrPercentage::Percentage(crate::values::percentage::Percentage(0.1)),
13296        )]),
13297        VendorPrefix::None,
13298      )
13299      .to_css_string(
13300        false,
13301        PrinterOptions {
13302          minify: true,
13303          ..PrinterOptions::default()
13304        },
13305      )
13306      .unwrap(),
13307      "transform:scaleX(.1)"
13308    );
13309
13310    // TODO: Re-enable with a better solution
13311    //       See: https://github.com/parcel-bundler/lightningcss/issues/288
13312    // minify_test(".foo { transform: scale(3); scale: 0.5 }", ".foo{transform:scale(1.5)}");
13313    minify_test(".foo { scale: 0.5; transform: scale(3); }", ".foo{transform:scale(3)}");
13314
13315    prefix_test(
13316      r#"
13317      .foo {
13318        transform: scale(0.5);
13319      }
13320    "#,
13321      indoc! {r#"
13322      .foo {
13323        -webkit-transform: scale(.5);
13324        -moz-transform: scale(.5);
13325        transform: scale(.5);
13326      }
13327    "#},
13328      Browsers {
13329        firefox: Some(6 << 16),
13330        safari: Some(6 << 16),
13331        ..Browsers::default()
13332      },
13333    );
13334
13335    prefix_test(
13336      r#"
13337      .foo {
13338        transform: var(--transform);
13339      }
13340    "#,
13341      indoc! {r#"
13342      .foo {
13343        -webkit-transform: var(--transform);
13344        -moz-transform: var(--transform);
13345        transform: var(--transform);
13346      }
13347    "#},
13348      Browsers {
13349        firefox: Some(6 << 16),
13350        safari: Some(6 << 16),
13351        ..Browsers::default()
13352      },
13353    );
13354
13355    test(
13356      r#"
13357      .foo {
13358        transform: translateX(-50%);
13359        transform: translateX(20px);
13360      }
13361      "#,
13362      indoc! {r#"
13363      .foo {
13364        transform: translateX(20px);
13365      }
13366      "#},
13367    );
13368  }
13369
13370  #[test]
13371  pub fn test_gradients() {
13372    minify_test(
13373      ".foo { background: linear-gradient(yellow, blue) }",
13374      ".foo{background:linear-gradient(#ff0,#00f)}",
13375    );
13376    minify_test(
13377      ".foo { background: linear-gradient(to bottom, yellow, blue); }",
13378      ".foo{background:linear-gradient(#ff0,#00f)}",
13379    );
13380    minify_test(
13381      ".foo { background: linear-gradient(180deg, yellow, blue); }",
13382      ".foo{background:linear-gradient(#ff0,#00f)}",
13383    );
13384    minify_test(
13385      ".foo { background: linear-gradient(0.5turn, yellow, blue); }",
13386      ".foo{background:linear-gradient(#ff0,#00f)}",
13387    );
13388    minify_test(
13389      ".foo { background: linear-gradient(yellow 10%, blue 20%) }",
13390      ".foo{background:linear-gradient(#ff0 10%,#00f 20%)}",
13391    );
13392    minify_test(
13393      ".foo { background: linear-gradient(to top, blue, yellow); }",
13394      ".foo{background:linear-gradient(#ff0,#00f)}",
13395    );
13396    minify_test(
13397      ".foo { background: linear-gradient(to top, blue 10%, yellow 20%); }",
13398      ".foo{background:linear-gradient(#ff0 80%,#00f 90%)}",
13399    );
13400    minify_test(
13401      ".foo { background: linear-gradient(to top, blue 10px, yellow 20px); }",
13402      ".foo{background:linear-gradient(0deg,#00f 10px,#ff0 20px)}",
13403    );
13404    minify_test(
13405      ".foo { background: linear-gradient(135deg, yellow, blue); }",
13406      ".foo{background:linear-gradient(135deg,#ff0,#00f)}",
13407    );
13408    minify_test(
13409      ".foo { background: linear-gradient(-1.42109e-14deg, rgba(10, 132, 255, 0.14) 0%, rgba(112, 183, 255, 0.14) 100%); }",
13410      ".foo{background:linear-gradient(-1.42109e-14deg,#0a84ff24 0%,#70b7ff24 100%)}",
13411    );
13412    minify_test(
13413      ".foo { background: linear-gradient(yellow, blue 20%, #0f0); }",
13414      ".foo{background:linear-gradient(#ff0,#00f 20%,#0f0)}",
13415    );
13416    minify_test(
13417      ".foo { background: linear-gradient(to top right, red, white, blue) }",
13418      ".foo{background:linear-gradient(to top right,red,#fff,#00f)}",
13419    );
13420    minify_test(
13421      ".foo { background: linear-gradient(yellow, blue calc(10% * 2), #0f0); }",
13422      ".foo{background:linear-gradient(#ff0,#00f 20%,#0f0)}",
13423    );
13424    minify_test(
13425      ".foo { background: linear-gradient(yellow, 20%, blue); }",
13426      ".foo{background:linear-gradient(#ff0,20%,#00f)}",
13427    );
13428    minify_test(
13429      ".foo { background: linear-gradient(yellow, 50%, blue); }",
13430      ".foo{background:linear-gradient(#ff0,#00f)}",
13431    );
13432    minify_test(
13433      ".foo { background: linear-gradient(yellow, 20px, blue); }",
13434      ".foo{background:linear-gradient(#ff0,20px,#00f)}",
13435    );
13436    minify_test(
13437      ".foo { background: linear-gradient(yellow, 50px, blue); }",
13438      ".foo{background:linear-gradient(#ff0,50px,#00f)}",
13439    );
13440    minify_test(
13441      ".foo { background: linear-gradient(yellow, 50px, blue); }",
13442      ".foo{background:linear-gradient(#ff0,50px,#00f)}",
13443    );
13444    minify_test(
13445      ".foo { background: linear-gradient(yellow, red 30% 40%, blue); }",
13446      ".foo{background:linear-gradient(#ff0,red 30% 40%,#00f)}",
13447    );
13448    minify_test(
13449      ".foo { background: linear-gradient(yellow, red 30%, red 40%, blue); }",
13450      ".foo{background:linear-gradient(#ff0,red 30% 40%,#00f)}",
13451    );
13452    minify_test(
13453      ".foo { background: linear-gradient(0, yellow, blue); }",
13454      ".foo{background:linear-gradient(#00f,#ff0)}",
13455    );
13456    minify_test(
13457      ".foo { background: -webkit-linear-gradient(yellow, blue) }",
13458      ".foo{background:-webkit-linear-gradient(#ff0,#00f)}",
13459    );
13460    minify_test(
13461      ".foo { background: -webkit-linear-gradient(bottom, yellow, blue); }",
13462      ".foo{background:-webkit-linear-gradient(#ff0,#00f)}",
13463    );
13464    minify_test(
13465      ".foo { background: -webkit-linear-gradient(top right, red, white, blue) }",
13466      ".foo{background:-webkit-linear-gradient(top right,red,#fff,#00f)}",
13467    );
13468    minify_test(
13469      ".foo { background: -moz-linear-gradient(yellow, blue) }",
13470      ".foo{background:-moz-linear-gradient(#ff0,#00f)}",
13471    );
13472    minify_test(
13473      ".foo { background: -moz-linear-gradient(bottom, yellow, blue); }",
13474      ".foo{background:-moz-linear-gradient(#ff0,#00f)}",
13475    );
13476    minify_test(
13477      ".foo { background: -moz-linear-gradient(top right, red, white, blue) }",
13478      ".foo{background:-moz-linear-gradient(top right,red,#fff,#00f)}",
13479    );
13480    minify_test(
13481      ".foo { background: -o-linear-gradient(yellow, blue) }",
13482      ".foo{background:-o-linear-gradient(#ff0,#00f)}",
13483    );
13484    minify_test(
13485      ".foo { background: -o-linear-gradient(bottom, yellow, blue); }",
13486      ".foo{background:-o-linear-gradient(#ff0,#00f)}",
13487    );
13488    minify_test(
13489      ".foo { background: -o-linear-gradient(top right, red, white, blue) }",
13490      ".foo{background:-o-linear-gradient(top right,red,#fff,#00f)}",
13491    );
13492    minify_test(
13493      ".foo { background: -webkit-gradient(linear, left top, left bottom, from(blue), to(yellow)) }",
13494      ".foo{background:-webkit-gradient(linear,0 0,0 100%,from(#00f),to(#ff0))}",
13495    );
13496    minify_test(
13497      ".foo { background: -webkit-gradient(linear, left top, left bottom, from(blue), color-stop(50%, red), to(yellow)) }",
13498      ".foo{background:-webkit-gradient(linear,0 0,0 100%,from(#00f),color-stop(.5,red),to(#ff0))}"
13499    );
13500    minify_test(
13501      ".foo { background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, blue), color-stop(50%, red), color-stop(100%, yellow)) }",
13502      ".foo{background:-webkit-gradient(linear,0 0,0 100%,from(#00f),color-stop(.5,red),to(#ff0))}"
13503    );
13504    minify_test(
13505      ".foo { background: repeating-linear-gradient(yellow 10px, blue 50px) }",
13506      ".foo{background:repeating-linear-gradient(#ff0 10px,#00f 50px)}",
13507    );
13508    minify_test(
13509      ".foo { background: -webkit-repeating-linear-gradient(yellow 10px, blue 50px) }",
13510      ".foo{background:-webkit-repeating-linear-gradient(#ff0 10px,#00f 50px)}",
13511    );
13512    minify_test(
13513      ".foo { background: -moz-repeating-linear-gradient(yellow 10px, blue 50px) }",
13514      ".foo{background:-moz-repeating-linear-gradient(#ff0 10px,#00f 50px)}",
13515    );
13516    minify_test(
13517      ".foo { background: -o-repeating-linear-gradient(yellow 10px, blue 50px) }",
13518      ".foo{background:-o-repeating-linear-gradient(#ff0 10px,#00f 50px)}",
13519    );
13520    minify_test(
13521      ".foo { background: radial-gradient(yellow, blue) }",
13522      ".foo{background:radial-gradient(#ff0,#00f)}",
13523    );
13524    minify_test(
13525      ".foo { background: radial-gradient(at top left, yellow, blue) }",
13526      ".foo{background:radial-gradient(at 0 0,#ff0,#00f)}",
13527    );
13528    minify_test(
13529      ".foo { background: radial-gradient(5em circle at top left, yellow, blue) }",
13530      ".foo{background:radial-gradient(5em at 0 0,#ff0,#00f)}",
13531    );
13532    minify_test(
13533      ".foo { background: radial-gradient(circle at 100%, #333, #333 50%, #eee 75%, #333 75%) }",
13534      ".foo{background:radial-gradient(circle at 100%,#333,#333 50%,#eee 75%,#333 75%)}",
13535    );
13536    minify_test(
13537      ".foo { background: radial-gradient(farthest-corner circle at 100% 50%, #333, #333 50%, #eee 75%, #333 75%) }",
13538      ".foo{background:radial-gradient(circle at 100%,#333,#333 50%,#eee 75%,#333 75%)}"
13539    );
13540    minify_test(
13541      ".foo { background: radial-gradient(farthest-corner circle at 50% 50%, #333, #333 50%, #eee 75%, #333 75%) }",
13542      ".foo{background:radial-gradient(circle,#333,#333 50%,#eee 75%,#333 75%)}"
13543    );
13544    minify_test(
13545      ".foo { background: radial-gradient(ellipse at top, #e66465, transparent) }",
13546      ".foo{background:radial-gradient(at top,#e66465,#0000)}",
13547    );
13548    minify_test(
13549      ".foo { background: radial-gradient(20px, yellow, blue) }",
13550      ".foo{background:radial-gradient(20px,#ff0,#00f)}",
13551    );
13552    minify_test(
13553      ".foo { background: radial-gradient(circle 20px, yellow, blue) }",
13554      ".foo{background:radial-gradient(20px,#ff0,#00f)}",
13555    );
13556    minify_test(
13557      ".foo { background: radial-gradient(20px 40px, yellow, blue) }",
13558      ".foo{background:radial-gradient(20px 40px,#ff0,#00f)}",
13559    );
13560    minify_test(
13561      ".foo { background: radial-gradient(ellipse 20px 40px, yellow, blue) }",
13562      ".foo{background:radial-gradient(20px 40px,#ff0,#00f)}",
13563    );
13564    minify_test(
13565      ".foo { background: radial-gradient(ellipse calc(20px + 10px) 40px, yellow, blue) }",
13566      ".foo{background:radial-gradient(30px 40px,#ff0,#00f)}",
13567    );
13568    minify_test(
13569      ".foo { background: radial-gradient(circle farthest-side, yellow, blue) }",
13570      ".foo{background:radial-gradient(circle farthest-side,#ff0,#00f)}",
13571    );
13572    minify_test(
13573      ".foo { background: radial-gradient(farthest-side circle, yellow, blue) }",
13574      ".foo{background:radial-gradient(circle farthest-side,#ff0,#00f)}",
13575    );
13576    minify_test(
13577      ".foo { background: radial-gradient(ellipse farthest-side, yellow, blue) }",
13578      ".foo{background:radial-gradient(farthest-side,#ff0,#00f)}",
13579    );
13580    minify_test(
13581      ".foo { background: radial-gradient(farthest-side ellipse, yellow, blue) }",
13582      ".foo{background:radial-gradient(farthest-side,#ff0,#00f)}",
13583    );
13584    minify_test(
13585      ".foo { background: -webkit-radial-gradient(yellow, blue) }",
13586      ".foo{background:-webkit-radial-gradient(#ff0,#00f)}",
13587    );
13588    minify_test(
13589      ".foo { background: -moz-radial-gradient(yellow, blue) }",
13590      ".foo{background:-moz-radial-gradient(#ff0,#00f)}",
13591    );
13592    minify_test(
13593      ".foo { background: -o-radial-gradient(yellow, blue) }",
13594      ".foo{background:-o-radial-gradient(#ff0,#00f)}",
13595    );
13596    minify_test(
13597      ".foo { background: repeating-radial-gradient(circle 20px, yellow, blue) }",
13598      ".foo{background:repeating-radial-gradient(20px,#ff0,#00f)}",
13599    );
13600    minify_test(
13601      ".foo { background: -webkit-repeating-radial-gradient(circle 20px, yellow, blue) }",
13602      ".foo{background:-webkit-repeating-radial-gradient(20px,#ff0,#00f)}",
13603    );
13604    minify_test(
13605      ".foo { background: -moz-repeating-radial-gradient(circle 20px, yellow, blue) }",
13606      ".foo{background:-moz-repeating-radial-gradient(20px,#ff0,#00f)}",
13607    );
13608    minify_test(
13609      ".foo { background: -o-repeating-radial-gradient(circle 20px, yellow, blue) }",
13610      ".foo{background:-o-repeating-radial-gradient(20px,#ff0,#00f)}",
13611    );
13612    minify_test(
13613      ".foo { background: -webkit-gradient(radial, center center, 0, center center, 100, from(blue), to(yellow)) }",
13614      ".foo{background:-webkit-gradient(radial,50% 50%,0,50% 50%,100,from(#00f),to(#ff0))}"
13615    );
13616    minify_test(
13617      ".foo { background: conic-gradient(#f06, gold) }",
13618      ".foo{background:conic-gradient(#f06,gold)}",
13619    );
13620    minify_test(
13621      ".foo { background: conic-gradient(at 50% 50%, #f06, gold) }",
13622      ".foo{background:conic-gradient(#f06,gold)}",
13623    );
13624    minify_test(
13625      ".foo { background: conic-gradient(from 0deg, #f06, gold) }",
13626      ".foo{background:conic-gradient(#f06,gold)}",
13627    );
13628    minify_test(
13629      ".foo { background: conic-gradient(from 0, #f06, gold) }",
13630      ".foo{background:conic-gradient(#f06,gold)}",
13631    );
13632    minify_test(
13633      ".foo { background: conic-gradient(from 0deg at center, #f06, gold) }",
13634      ".foo{background:conic-gradient(#f06,gold)}",
13635    );
13636    minify_test(
13637      ".foo { background: conic-gradient(white -50%, black 150%) }",
13638      ".foo{background:conic-gradient(#fff -50%,#000 150%)}",
13639    );
13640    minify_test(
13641      ".foo { background: conic-gradient(white -180deg, black 540deg) }",
13642      ".foo{background:conic-gradient(#fff -180deg,#000 540deg)}",
13643    );
13644    minify_test(
13645      ".foo { background: conic-gradient(from 45deg, white, black, white) }",
13646      ".foo{background:conic-gradient(from 45deg,#fff,#000,#fff)}",
13647    );
13648    minify_test(
13649      ".foo { background: repeating-conic-gradient(from 45deg, white, black, white) }",
13650      ".foo{background:repeating-conic-gradient(from 45deg,#fff,#000,#fff)}",
13651    );
13652    minify_test(
13653      ".foo { background: repeating-conic-gradient(black 0deg 25%, white 0deg 50%) }",
13654      ".foo{background:repeating-conic-gradient(#000 0deg 25%,#fff 0deg 50%)}",
13655    );
13656
13657    test(
13658      r#"
13659        .foo {
13660          background: -webkit-gradient(linear, left top, left bottom, from(red), to(blue));
13661          background: -webkit-linear-gradient(red, blue);
13662          background: -moz-linear-gradient(red, blue);
13663          background: -o-linear-gradient(red, blue);
13664          background: linear-gradient(red, blue);
13665        }
13666      "#,
13667      indoc! {r#"
13668        .foo {
13669          background: -webkit-gradient(linear, left top, left bottom, from(red), to(#00f));
13670          background: -webkit-linear-gradient(red, #00f);
13671          background: -moz-linear-gradient(red, #00f);
13672          background: -o-linear-gradient(red, #00f);
13673          background: linear-gradient(red, #00f);
13674        }
13675      "#},
13676    );
13677
13678    prefix_test(
13679      r#"
13680      .foo {
13681        background: -webkit-gradient(linear, left top, left bottom, from(red), to(blue));
13682        background: -webkit-linear-gradient(red, blue);
13683        background: -moz-linear-gradient(red, blue);
13684        background: -o-linear-gradient(red, blue);
13685        background: linear-gradient(red, blue);
13686      }
13687      "#,
13688      indoc! {r#"
13689      .foo {
13690        background: linear-gradient(red, #00f);
13691      }
13692      "#},
13693      Browsers {
13694        chrome: Some(95 << 16),
13695        ..Browsers::default()
13696      },
13697    );
13698    prefix_test(
13699      r#"
13700      .foo {
13701        background: -webkit-gradient(linear, left top, left bottom, from(red), to(blue));
13702        background: -webkit-linear-gradient(red, blue);
13703        background: -moz-linear-gradient(red, blue);
13704        background: -o-linear-gradient(red, blue);
13705      }
13706      "#,
13707      indoc! {r#"
13708      .foo {
13709        background: -webkit-gradient(linear, left top, left bottom, from(red), to(#00f));
13710        background: -webkit-linear-gradient(red, #00f);
13711        background: -moz-linear-gradient(red, #00f);
13712        background: -o-linear-gradient(red, #00f);
13713      }
13714      "#},
13715      Browsers {
13716        chrome: Some(95 << 16),
13717        ..Browsers::default()
13718      },
13719    );
13720    prefix_test(
13721      r#"
13722      .foo {
13723        background-image: linear-gradient(red, blue);
13724      }
13725      "#,
13726      indoc! {r#"
13727      .foo {
13728        background-image: -webkit-gradient(linear, 0 0, 0 100%, from(red), to(#00f));
13729        background-image: -webkit-linear-gradient(top, red, #00f);
13730        background-image: linear-gradient(red, #00f);
13731      }
13732      "#},
13733      Browsers {
13734        chrome: Some(8 << 16),
13735        ..Browsers::default()
13736      },
13737    );
13738    prefix_test(
13739      r#"
13740      .foo {
13741        background-image: linear-gradient(to right, red, blue);
13742      }
13743      "#,
13744      indoc! {r#"
13745      .foo {
13746        background-image: -webkit-gradient(linear, 0 0, 100% 0, from(red), to(#00f));
13747        background-image: -webkit-linear-gradient(left, red, #00f);
13748        background-image: linear-gradient(to right, red, #00f);
13749      }
13750      "#},
13751      Browsers {
13752        chrome: Some(8 << 16),
13753        ..Browsers::default()
13754      },
13755    );
13756    prefix_test(
13757      r#"
13758      .foo {
13759        background-image: linear-gradient(to top, red, blue);
13760      }
13761      "#,
13762      indoc! {r#"
13763      .foo {
13764        background-image: -webkit-gradient(linear, 0 100%, 0 0, from(red), to(#00f));
13765        background-image: -webkit-linear-gradient(red, #00f);
13766        background-image: linear-gradient(to top, red, #00f);
13767      }
13768      "#},
13769      Browsers {
13770        chrome: Some(8 << 16),
13771        ..Browsers::default()
13772      },
13773    );
13774    prefix_test(
13775      r#"
13776      .foo {
13777        background-image: linear-gradient(to left, red, blue);
13778      }
13779      "#,
13780      indoc! {r#"
13781      .foo {
13782        background-image: -webkit-gradient(linear, 100% 0, 0 0, from(red), to(#00f));
13783        background-image: -webkit-linear-gradient(right, red, #00f);
13784        background-image: linear-gradient(to left, red, #00f);
13785      }
13786      "#},
13787      Browsers {
13788        chrome: Some(8 << 16),
13789        ..Browsers::default()
13790      },
13791    );
13792    prefix_test(
13793      r#"
13794      .foo {
13795        background-image: linear-gradient(to left bottom, red, blue);
13796      }
13797      "#,
13798      indoc! {r#"
13799      .foo {
13800        background-image: -webkit-gradient(linear, 100% 0, 0 100%, from(red), to(#00f));
13801        background-image: -webkit-linear-gradient(top right, red, #00f);
13802        background-image: linear-gradient(to bottom left, red, #00f);
13803      }
13804      "#},
13805      Browsers {
13806        chrome: Some(8 << 16),
13807        ..Browsers::default()
13808      },
13809    );
13810    prefix_test(
13811      r#"
13812      .foo {
13813        background-image: linear-gradient(to top right, red, blue);
13814      }
13815      "#,
13816      indoc! {r#"
13817      .foo {
13818        background-image: -webkit-gradient(linear, 0 100%, 100% 0, from(red), to(#00f));
13819        background-image: -webkit-linear-gradient(bottom left, red, #00f);
13820        background-image: linear-gradient(to top right, red, #00f);
13821      }
13822      "#},
13823      Browsers {
13824        chrome: Some(8 << 16),
13825        ..Browsers::default()
13826      },
13827    );
13828    prefix_test(
13829      r#"
13830      .foo {
13831        background-image: linear-gradient(90deg, red, blue);
13832      }
13833      "#,
13834      indoc! {r#"
13835      .foo {
13836        background-image: -webkit-gradient(linear, 0 0, 100% 0, from(red), to(#00f));
13837        background-image: -webkit-linear-gradient(0deg, red, #00f);
13838        background-image: linear-gradient(90deg, red, #00f);
13839      }
13840      "#},
13841      Browsers {
13842        chrome: Some(8 << 16),
13843        ..Browsers::default()
13844      },
13845    );
13846    prefix_test(
13847      r#"
13848      .foo {
13849        background-image: linear-gradient(45deg, red, blue);
13850      }
13851      "#,
13852      indoc! {r#"
13853      .foo {
13854        background-image: -webkit-linear-gradient(45deg, red, #00f);
13855        background-image: linear-gradient(45deg, red, #00f);
13856      }
13857      "#},
13858      Browsers {
13859        chrome: Some(8 << 16),
13860        ..Browsers::default()
13861      },
13862    );
13863    prefix_test(
13864      r#"
13865      .foo {
13866        background-image: linear-gradient(red, blue);
13867      }
13868      "#,
13869      indoc! {r#"
13870      .foo {
13871        background-image: -webkit-linear-gradient(top, red, #00f);
13872        background-image: linear-gradient(red, #00f);
13873      }
13874      "#},
13875      Browsers {
13876        chrome: Some(10 << 16),
13877        ..Browsers::default()
13878      },
13879    );
13880    prefix_test(
13881      r#"
13882      .foo {
13883        background-image: radial-gradient(20px, red, blue);
13884      }
13885      "#,
13886      indoc! {r#"
13887      .foo {
13888        background-image: -webkit-gradient(radial, center center, 0, center center, 20, from(red), to(#00f));
13889        background-image: -webkit-radial-gradient(20px, red, #00f);
13890        background-image: radial-gradient(20px, red, #00f);
13891      }
13892      "#},
13893      Browsers {
13894        chrome: Some(8 << 16),
13895        ..Browsers::default()
13896      },
13897    );
13898    prefix_test(
13899      r#"
13900      .foo {
13901        background-image: radial-gradient(20px at top left, red, blue);
13902      }
13903      "#,
13904      indoc! {r#"
13905      .foo {
13906        background-image: -webkit-gradient(radial, left top, 0, left top, 20, from(red), to(#00f));
13907        background-image: -webkit-radial-gradient(20px at 0 0, red, #00f);
13908        background-image: radial-gradient(20px at 0 0, red, #00f);
13909      }
13910      "#},
13911      Browsers {
13912        chrome: Some(8 << 16),
13913        ..Browsers::default()
13914      },
13915    );
13916    prefix_test(
13917      r#"
13918      .foo {
13919        background-image: radial-gradient(red, blue);
13920      }
13921      "#,
13922      indoc! {r#"
13923      .foo {
13924        background-image: -webkit-radial-gradient(red, #00f);
13925        background-image: radial-gradient(red, #00f);
13926      }
13927      "#},
13928      Browsers {
13929        chrome: Some(8 << 16),
13930        ..Browsers::default()
13931      },
13932    );
13933    prefix_test(
13934      r#"
13935      .foo {
13936        background-image: -webkit-gradient(radial, left top, 0, left top, 20, from(red), to(#00f));
13937        background-image: -webkit-radial-gradient(20px at 0% 0%, red, #00f);
13938        background-image: radial-gradient(20px at 0% 0%, red, #00f);
13939      }
13940      "#,
13941      indoc! {r#"
13942      .foo {
13943        background-image: radial-gradient(20px at 0 0, red, #00f);
13944      }
13945      "#},
13946      Browsers {
13947        chrome: Some(30 << 16),
13948        ..Browsers::default()
13949      },
13950    );
13951    prefix_test(
13952      r#"
13953      .foo {
13954        background: -webkit-gradient(radial, left top, 0, left top, 20, from(red), to(#00f));
13955        background: -webkit-radial-gradient(20px at 0% 0%, red, #00f);
13956        background: radial-gradient(20px at 0% 0%, red, #00f);
13957      }
13958      "#,
13959      indoc! {r#"
13960      .foo {
13961        background: radial-gradient(20px at 0 0, red, #00f);
13962      }
13963      "#},
13964      Browsers {
13965        chrome: Some(30 << 16),
13966        ..Browsers::default()
13967      },
13968    );
13969    prefix_test(
13970      r#"
13971      .foo {
13972        background: radial-gradient(red, blue);
13973      }
13974      "#,
13975      indoc! {r#"
13976      .foo {
13977        background: -webkit-radial-gradient(red, #00f);
13978        background: radial-gradient(red, #00f);
13979      }
13980      "#},
13981      Browsers {
13982        chrome: Some(8 << 16),
13983        ..Browsers::default()
13984      },
13985    );
13986    prefix_test(
13987      r#"
13988      .foo {
13989        background: radial-gradient(red, blue), linear-gradient(yellow, red), url(bg.jpg);
13990      }
13991      "#,
13992      indoc! {r#"
13993      .foo {
13994        background: -webkit-gradient(linear, 0 0, 0 100%, from(#ff0), to(red)), url("bg.jpg");
13995        background: -webkit-radial-gradient(red, #00f), -webkit-linear-gradient(top, #ff0, red), url("bg.jpg");
13996        background: -moz-radial-gradient(red, #00f), -moz-linear-gradient(top, #ff0, red), url("bg.jpg");
13997        background: -o-radial-gradient(red, #00f), -o-linear-gradient(top, #ff0, red), url("bg.jpg");
13998        background: radial-gradient(red, #00f), linear-gradient(#ff0, red), url("bg.jpg");
13999      }
14000      "#},
14001      Browsers {
14002        chrome: Some(8 << 16),
14003        firefox: Some(4 << 16),
14004        opera: Some(11 << 16 | 5 << 8),
14005        ..Browsers::default()
14006      },
14007    );
14008
14009    prefix_test(
14010      r#"
14011      .foo {
14012        background: linear-gradient(yellow, red 30% 40%, blue);
14013      }
14014      "#,
14015      indoc! {r#"
14016      .foo {
14017        background: linear-gradient(#ff0, red 30%, red 40%, #00f);
14018      }
14019      "#},
14020      Browsers {
14021        chrome: Some(70 << 16),
14022        ..Browsers::default()
14023      },
14024    );
14025
14026    prefix_test(
14027      r#"
14028      .foo {
14029        background: linear-gradient(yellow, red 30% 40%, blue);
14030      }
14031      "#,
14032      indoc! {r#"
14033      .foo {
14034        background: linear-gradient(#ff0, red 30% 40%, #00f);
14035      }
14036      "#},
14037      Browsers {
14038        chrome: Some(71 << 16),
14039        ..Browsers::default()
14040      },
14041    );
14042
14043    prefix_test(
14044      ".foo { background: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
14045      indoc! { r#"
14046        .foo {
14047          background: linear-gradient(#ff0f0e, #7773ff);
14048          background: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
14049        }
14050      "#},
14051      Browsers {
14052        chrome: Some(90 << 16),
14053        ..Browsers::default()
14054      },
14055    );
14056
14057    prefix_test(
14058      ".foo { background: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
14059      indoc! { r#"
14060        .foo {
14061          background: linear-gradient(#ff0f0e, #7773ff);
14062          background: linear-gradient(color(display-p3 1 .0000153435 -.00000303562), color(display-p3 .440289 .28452 1.23485));
14063          background: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
14064        }
14065      "#},
14066      Browsers {
14067        chrome: Some(90 << 16),
14068        safari: Some(14 << 16),
14069        ..Browsers::default()
14070      },
14071    );
14072
14073    prefix_test(
14074      ".foo { background: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
14075      indoc! { r#"
14076        .foo {
14077          background: -webkit-linear-gradient(top, #ff0f0e, #7773ff);
14078          background: linear-gradient(#ff0f0e, #7773ff);
14079          background: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
14080        }
14081      "#},
14082      Browsers {
14083        chrome: Some(20 << 16),
14084        ..Browsers::default()
14085      },
14086    );
14087
14088    prefix_test(
14089      ".foo { background: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
14090      indoc! { r#"
14091        .foo {
14092          background: -webkit-gradient(linear, 0 0, 0 100%, from(#ff0f0e), to(#7773ff));
14093          background: -webkit-linear-gradient(top, #ff0f0e, #7773ff);
14094          background: linear-gradient(#ff0f0e, #7773ff);
14095          background: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
14096        }
14097      "#},
14098      Browsers {
14099        chrome: Some(8 << 16),
14100        ..Browsers::default()
14101      },
14102    );
14103
14104    prefix_test(
14105      ".foo { background: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
14106      indoc! { r#"
14107        .foo {
14108          background: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
14109        }
14110      "#},
14111      Browsers {
14112        safari: Some(15 << 16),
14113        ..Browsers::default()
14114      },
14115    );
14116
14117    prefix_test(
14118      ".foo { background-image: linear-gradient(oklab(59.686% 0.1009 0.1192), oklab(54.0% -0.10 -0.02)); }",
14119      indoc! { r#"
14120        .foo {
14121          background-image: linear-gradient(lab(52.2319% 40.1449 59.9171), lab(47.7776% -34.2947 -7.65904));
14122        }
14123      "#},
14124      Browsers {
14125        safari: Some(15 << 16),
14126        ..Browsers::default()
14127      },
14128    );
14129
14130    prefix_test(
14131      ".foo { background-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
14132      indoc! { r#"
14133        .foo {
14134          background-image: linear-gradient(#ff0f0e, #7773ff);
14135          background-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
14136        }
14137      "#},
14138      Browsers {
14139        chrome: Some(90 << 16),
14140        ..Browsers::default()
14141      },
14142    );
14143
14144    prefix_test(
14145      ".foo { background-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
14146      indoc! { r#"
14147        .foo {
14148          background-image: linear-gradient(#ff0f0e, #7773ff);
14149          background-image: linear-gradient(color(display-p3 1 .0000153435 -.00000303562), color(display-p3 .440289 .28452 1.23485));
14150          background-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
14151        }
14152      "#},
14153      Browsers {
14154        chrome: Some(90 << 16),
14155        safari: Some(14 << 16),
14156        ..Browsers::default()
14157      },
14158    );
14159
14160    prefix_test(
14161      ".foo { background-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
14162      indoc! { r#"
14163        .foo {
14164          background-image: -webkit-linear-gradient(top, #ff0f0e, #7773ff);
14165          background-image: linear-gradient(#ff0f0e, #7773ff);
14166          background-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
14167        }
14168      "#},
14169      Browsers {
14170        chrome: Some(20 << 16),
14171        ..Browsers::default()
14172      },
14173    );
14174
14175    prefix_test(
14176      ".foo { background-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
14177      indoc! { r#"
14178        .foo {
14179          background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ff0f0e), to(#7773ff));
14180          background-image: -webkit-linear-gradient(top, #ff0f0e, #7773ff);
14181          background-image: linear-gradient(#ff0f0e, #7773ff);
14182          background-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
14183        }
14184      "#},
14185      Browsers {
14186        chrome: Some(8 << 16),
14187        ..Browsers::default()
14188      },
14189    );
14190
14191    prefix_test(
14192      ".foo { background-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
14193      indoc! { r#"
14194        .foo {
14195          background-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
14196        }
14197      "#},
14198      Browsers {
14199        safari: Some(15 << 16),
14200        ..Browsers::default()
14201      },
14202    );
14203
14204    prefix_test(
14205      ".foo { background-image: linear-gradient(oklab(59.686% 0.1009 0.1192), oklab(54.0% -0.10 -0.02)); }",
14206      indoc! { r#"
14207        .foo {
14208          background-image: linear-gradient(lab(52.2319% 40.1449 59.9171), lab(47.7776% -34.2947 -7.65904));
14209        }
14210      "#},
14211      Browsers {
14212        safari: Some(15 << 16),
14213        ..Browsers::default()
14214      },
14215    );
14216
14217    // Test cases from https://github.com/postcss/autoprefixer/blob/541295c0e6dd348db2d3f52772b59cd403c59d29/test/cases/gradient.css
14218    prefix_test(
14219      r#"
14220        a {
14221          background: linear-gradient(350.5deg, white, black), linear-gradient(-130deg, black, white), linear-gradient(45deg, black, white);
14222        }
14223        b {
14224          background-image: linear-gradient(rgba(0,0,0,1), white), linear-gradient(white, black);
14225        }
14226        strong {
14227          background: linear-gradient(to top, transparent, rgba(0, 0, 0, 0.8) 20px, #000 30px, #000) no-repeat;
14228        }
14229        div {
14230          background-image: radial-gradient(to left, white, black), repeating-linear-gradient(to bottom right, black, white), repeating-radial-gradient(to top, aqua, red);
14231        }
14232        .old-radial {
14233          background: radial-gradient(0 50%, ellipse farthest-corner, black, white);
14234        }
14235        .simple1 {
14236          background: linear-gradient(black, white);
14237        }
14238        .simple2 {
14239          background: linear-gradient(to left, black 0%, rgba(0, 0, 0, 0.5)50%, white 100%);
14240        }
14241        .simple3 {
14242          background: linear-gradient(to left, black 50%, white 100%);
14243        }
14244        .simple4 {
14245          background: linear-gradient(to right top, black, white);
14246        }
14247        .direction {
14248          background: linear-gradient(top left, black, rgba(0, 0, 0, 0.5), white);
14249        }
14250        .silent {
14251          background: -webkit-linear-gradient(top left, black, white);
14252        }
14253        .radial {
14254          background: radial-gradient(farthest-side at 0 50%, white, black);
14255        }
14256        .second {
14257          background: red linear-gradient(red, blue);
14258          background: url('logo.png'), linear-gradient(#fff, #000);
14259        }
14260        .px {
14261          background: linear-gradient(black 0, white 100px);
14262        }
14263        .list {
14264          list-style-image: linear-gradient(white, black);
14265        }
14266        .mask {
14267          mask: linear-gradient(white, black);
14268        }
14269        .newline {
14270          background-image:
14271              linear-gradient( white, black ),
14272              linear-gradient( black, white );
14273        }
14274        .convert {
14275          background: linear-gradient(0deg, white, black);
14276          background: linear-gradient(90deg, white, black);
14277          background: linear-gradient(180deg, white, black);
14278          background: linear-gradient(270deg, white, black);
14279        }
14280        .grad {
14281          background: linear-gradient(1grad, white, black);
14282        }
14283        .rad {
14284          background: linear-gradient(1rad, white, black);
14285        }
14286        .turn {
14287          background: linear-gradient(0.3turn, white, black);
14288        }
14289        .norm {
14290          background: linear-gradient(-90deg, white, black);
14291        }
14292        .mask {
14293          mask-image: radial-gradient(circle at 86% 86%, transparent 8px, black 8px);
14294        }
14295        .cover {
14296          background: radial-gradient(ellipse cover at center, white, black);
14297        }
14298        .contain {
14299          background: radial-gradient(contain at center, white, black);
14300        }
14301        .no-div {
14302          background: linear-gradient(black);
14303        }
14304        .background-shorthand {
14305          background: radial-gradient(#FFF, transparent) 0 0 / cover no-repeat #F0F;
14306        }
14307        .background-advanced {
14308          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%),
14309                      radial-gradient(#FFF, transparent),
14310                      url(path/to/image.jpg) 50%/cover;
14311        }
14312        .multiradial {
14313          mask-image: radial-gradient(circle closest-corner at 100% 50%, #000, transparent);
14314        }
14315        .broken {
14316          mask-image: radial-gradient(white, black);
14317        }
14318        .loop {
14319          background-image: url("https://test.com/lol(test.png"), radial-gradient(yellow, black, yellow);
14320        }
14321        .unitless-zero {
14322          background-image: linear-gradient(0, green, blue);
14323          background: repeating-linear-gradient(0, blue, red 33.3%)
14324        }
14325        .zero-grad {
14326          background: linear-gradient(0grad, green, blue);
14327          background-image: repeating-linear-gradient(0grad, blue, red 33.3%)
14328        }
14329        .zero-rad {
14330          background: linear-gradient(0rad, green, blue);
14331        }
14332        .zero-turn {
14333          background: linear-gradient(0turn, green, blue);
14334        }
14335      "#,
14336      indoc! { r#"
14337        a {
14338          background: -webkit-linear-gradient(99.5deg, #fff, #000), -webkit-linear-gradient(220deg, #000, #fff), -webkit-linear-gradient(45deg, #000, #fff);
14339          background: -o-linear-gradient(99.5deg, #fff, #000), -o-linear-gradient(220deg, #000, #fff), -o-linear-gradient(45deg, #000, #fff);
14340          background: linear-gradient(350.5deg, #fff, #000), linear-gradient(-130deg, #000, #fff), linear-gradient(45deg, #000, #fff);
14341        }
14342
14343        b {
14344          background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#000), to(#fff)), -webkit-gradient(linear, 0 0, 0 100%, from(#fff), to(#000));
14345          background-image: -webkit-linear-gradient(top, #000, #fff), -webkit-linear-gradient(top, #fff, #000);
14346          background-image: -o-linear-gradient(top, #000, #fff), -o-linear-gradient(top, #fff, #000);
14347          background-image: linear-gradient(#000, #fff), linear-gradient(#fff, #000);
14348        }
14349
14350        strong {
14351          background: -webkit-linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, .8) 20px, #000 30px, #000) no-repeat;
14352          background: -o-linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, .8) 20px, #000 30px, #000) no-repeat;
14353          background: linear-gradient(to top, rgba(0, 0, 0, 0), rgba(0, 0, 0, .8) 20px, #000 30px, #000) no-repeat;
14354        }
14355
14356        div {
14357          background-image: radial-gradient(to left, white, black), repeating-linear-gradient(to bottom right, black, white), repeating-radial-gradient(to top, aqua, red);
14358        }
14359
14360        .old-radial {
14361          background: radial-gradient(0 50%, ellipse farthest-corner, black, white);
14362        }
14363
14364        .simple1 {
14365          background: -webkit-gradient(linear, 0 0, 0 100%, from(#000), to(#fff));
14366          background: -webkit-linear-gradient(top, #000, #fff);
14367          background: -o-linear-gradient(top, #000, #fff);
14368          background: linear-gradient(#000, #fff);
14369        }
14370
14371        .simple2 {
14372          background: -webkit-gradient(linear, 100% 0, 0 0, from(#000), color-stop(.5, rgba(0, 0, 0, .5)), to(#fff));
14373          background: -webkit-linear-gradient(right, #000 0%, rgba(0, 0, 0, .5) 50%, #fff 100%);
14374          background: -o-linear-gradient(right, #000 0%, rgba(0, 0, 0, .5) 50%, #fff 100%);
14375          background: linear-gradient(to left, #000 0%, rgba(0, 0, 0, .5) 50%, #fff 100%);
14376        }
14377
14378        .simple3 {
14379          background: -webkit-gradient(linear, 100% 0, 0 0, color-stop(.5, #000), to(#fff));
14380          background: -webkit-linear-gradient(right, #000 50%, #fff 100%);
14381          background: -o-linear-gradient(right, #000 50%, #fff 100%);
14382          background: linear-gradient(to left, #000 50%, #fff 100%);
14383        }
14384
14385        .simple4 {
14386          background: -webkit-gradient(linear, 0 100%, 100% 0, from(#000), to(#fff));
14387          background: -webkit-linear-gradient(bottom left, #000, #fff);
14388          background: -o-linear-gradient(bottom left, #000, #fff);
14389          background: linear-gradient(to top right, #000, #fff);
14390        }
14391
14392        .direction {
14393          background: linear-gradient(top left, black, rgba(0, 0, 0, .5), white);
14394        }
14395
14396        .silent {
14397          background: -webkit-gradient(linear, 100% 100%, 0 0, from(#000), to(#fff));
14398          background: -webkit-linear-gradient(top left, #000, #fff);
14399        }
14400
14401        .radial {
14402          background: -webkit-radial-gradient(farthest-side at 0, #fff, #000);
14403          background: -o-radial-gradient(farthest-side at 0, #fff, #000);
14404          background: radial-gradient(farthest-side at 0, #fff, #000);
14405        }
14406
14407        .second {
14408          background: red -webkit-gradient(linear, 0 0, 0 100%, from(red), to(#00f));
14409          background: red -webkit-linear-gradient(top, red, #00f);
14410          background: red -o-linear-gradient(top, red, #00f);
14411          background: red linear-gradient(red, #00f);
14412          background: url("logo.png"), linear-gradient(#fff, #000);
14413        }
14414
14415        .px {
14416          background: -webkit-linear-gradient(top, #000 0, #fff 100px);
14417          background: -o-linear-gradient(top, #000 0, #fff 100px);
14418          background: linear-gradient(#000 0, #fff 100px);
14419        }
14420
14421        .list {
14422          list-style-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fff), to(#000));
14423          list-style-image: -webkit-linear-gradient(top, #fff, #000);
14424          list-style-image: -o-linear-gradient(top, #fff, #000);
14425          list-style-image: linear-gradient(#fff, #000);
14426        }
14427
14428        .mask {
14429          -webkit-mask: -webkit-gradient(linear, 0 0, 0 100%, from(#fff), to(#000));
14430          -webkit-mask: -webkit-linear-gradient(top, #fff, #000);
14431          -webkit-mask: -o-linear-gradient(top, #fff, #000);
14432          mask: -o-linear-gradient(top, #fff, #000);
14433          -webkit-mask: linear-gradient(#fff, #000);
14434          mask: linear-gradient(#fff, #000);
14435        }
14436
14437        .newline {
14438          background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fff), to(#000)), -webkit-gradient(linear, 0 0, 0 100%, from(#000), to(#fff));
14439          background-image: -webkit-linear-gradient(top, #fff, #000), -webkit-linear-gradient(top, #000, #fff);
14440          background-image: -o-linear-gradient(top, #fff, #000), -o-linear-gradient(top, #000, #fff);
14441          background-image: linear-gradient(#fff, #000), linear-gradient(#000, #fff);
14442        }
14443
14444        .convert {
14445          background: -webkit-gradient(linear, 0 100%, 0 0, from(#fff), to(#000));
14446          background: -webkit-linear-gradient(90deg, #fff, #000);
14447          background: -o-linear-gradient(90deg, #fff, #000);
14448          background: linear-gradient(0deg, #fff, #000);
14449          background: linear-gradient(90deg, #fff, #000);
14450          background: linear-gradient(#fff, #000);
14451          background: linear-gradient(270deg, #fff, #000);
14452        }
14453
14454        .grad {
14455          background: -webkit-linear-gradient(89.1deg, #fff, #000);
14456          background: -o-linear-gradient(89.1deg, #fff, #000);
14457          background: linear-gradient(1grad, #fff, #000);
14458        }
14459
14460        .rad {
14461          background: -webkit-linear-gradient(32.704deg, #fff, #000);
14462          background: -o-linear-gradient(32.704deg, #fff, #000);
14463          background: linear-gradient(57.2958deg, #fff, #000);
14464        }
14465
14466        .turn {
14467          background: -webkit-linear-gradient(342deg, #fff, #000);
14468          background: -o-linear-gradient(342deg, #fff, #000);
14469          background: linear-gradient(.3turn, #fff, #000);
14470        }
14471
14472        .norm {
14473          background: -webkit-linear-gradient(#fff, #000);
14474          background: -o-linear-gradient(#fff, #000);
14475          background: linear-gradient(-90deg, #fff, #000);
14476        }
14477
14478        .mask {
14479          -webkit-mask-image: -webkit-radial-gradient(circle at 86% 86%, rgba(0, 0, 0, 0) 8px, #000 8px);
14480          -webkit-mask-image: -o-radial-gradient(circle at 86% 86%, rgba(0, 0, 0, 0) 8px, #000 8px);
14481          mask-image: -o-radial-gradient(circle at 86% 86%, rgba(0, 0, 0, 0) 8px, #000 8px);
14482          -webkit-mask-image: radial-gradient(circle at 86% 86%, rgba(0, 0, 0, 0) 8px, #000 8px);
14483          mask-image: radial-gradient(circle at 86% 86%, rgba(0, 0, 0, 0) 8px, #000 8px);
14484        }
14485
14486        .cover {
14487          background: radial-gradient(ellipse cover at center, white, black);
14488        }
14489
14490        .contain {
14491          background: radial-gradient(contain at center, white, black);
14492        }
14493
14494        .no-div {
14495          background: -webkit-gradient(linear, 0 0, 0 100%, from(#000));
14496          background: -webkit-linear-gradient(top, #000);
14497          background: -o-linear-gradient(top, #000);
14498          background: linear-gradient(#000);
14499        }
14500
14501        .background-shorthand {
14502          background: #f0f -webkit-radial-gradient(#fff, rgba(0, 0, 0, 0)) 0 0 / cover no-repeat;
14503          background: #f0f -o-radial-gradient(#fff, rgba(0, 0, 0, 0)) 0 0 / cover no-repeat;
14504          background: #f0f radial-gradient(#fff, rgba(0, 0, 0, 0)) 0 0 / cover no-repeat;
14505        }
14506
14507        .background-advanced {
14508          background: url("path/to/image.jpg") 50% / cover;
14509          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;
14510          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;
14511          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;
14512        }
14513
14514        .multiradial {
14515          -webkit-mask-image: -webkit-radial-gradient(circle closest-corner at 100%, #000, rgba(0, 0, 0, 0));
14516          -webkit-mask-image: -o-radial-gradient(circle closest-corner at 100%, #000, rgba(0, 0, 0, 0));
14517          mask-image: -o-radial-gradient(circle closest-corner at 100%, #000, rgba(0, 0, 0, 0));
14518          -webkit-mask-image: radial-gradient(circle closest-corner at 100%, #000, rgba(0, 0, 0, 0));
14519          mask-image: radial-gradient(circle closest-corner at 100%, #000, rgba(0, 0, 0, 0));
14520        }
14521
14522        .broken {
14523          -webkit-mask-image: -webkit-radial-gradient(#fff, #000);
14524          -webkit-mask-image: -o-radial-gradient(#fff, #000);
14525          mask-image: -o-radial-gradient(#fff, #000);
14526          -webkit-mask-image: radial-gradient(#fff, #000);
14527          mask-image: radial-gradient(#fff, #000);
14528        }
14529
14530        .loop {
14531          background-image: url("https://test.com/lol(test.png");
14532          background-image: url("https://test.com/lol(test.png"), -webkit-radial-gradient(#ff0, #000, #ff0);
14533          background-image: url("https://test.com/lol(test.png"), -o-radial-gradient(#ff0, #000, #ff0);
14534          background-image: url("https://test.com/lol(test.png"), radial-gradient(#ff0, #000, #ff0);
14535        }
14536
14537        .unitless-zero {
14538          background-image: -webkit-gradient(linear, 0 100%, 0 0, from(green), to(#00f));
14539          background-image: -webkit-linear-gradient(90deg, green, #00f);
14540          background-image: -o-linear-gradient(90deg, green, #00f);
14541          background-image: linear-gradient(0deg, green, #00f);
14542          background: repeating-linear-gradient(0deg, #00f, red 33.3%);
14543        }
14544
14545        .zero-grad {
14546          background: -webkit-gradient(linear, 0 100%, 0 0, from(green), to(#00f));
14547          background: -webkit-linear-gradient(90deg, green, #00f);
14548          background: -o-linear-gradient(90deg, green, #00f);
14549          background: linear-gradient(0grad, green, #00f);
14550          background-image: repeating-linear-gradient(0grad, #00f, red 33.3%);
14551        }
14552
14553        .zero-rad, .zero-turn {
14554          background: -webkit-gradient(linear, 0 100%, 0 0, from(green), to(#00f));
14555          background: -webkit-linear-gradient(90deg, green, #00f);
14556          background: -o-linear-gradient(90deg, green, #00f);
14557          background: linear-gradient(0deg, green, #00f);
14558        }
14559      "#},
14560      Browsers {
14561        chrome: Some(25 << 16),
14562        opera: Some(12 << 16),
14563        android: Some(2 << 16 | 3 << 8),
14564        ..Browsers::default()
14565      },
14566    );
14567  }
14568
14569  #[test]
14570  fn test_font_face() {
14571    minify_test(
14572      r#"@font-face {
14573      src: url("test.woff");
14574      font-family: "Helvetica";
14575      font-weight: bold;
14576      font-style: italic;
14577    }"#,
14578      "@font-face{src:url(test.woff);font-family:Helvetica;font-weight:700;font-style:italic}",
14579    );
14580    minify_test("@font-face {src: url(test.woff);}", "@font-face{src:url(test.woff)}");
14581    minify_test("@font-face {src: local(\"Test\");}", "@font-face{src:local(Test)}");
14582    minify_test(
14583      "@font-face {src: local(\"Foo Bar\");}",
14584      "@font-face{src:local(Foo Bar)}",
14585    );
14586    minify_test("@font-face {src: local(Test);}", "@font-face{src:local(Test)}");
14587    minify_test("@font-face {src: local(Foo Bar);}", "@font-face{src:local(Foo Bar)}");
14588
14589    minify_test(
14590      "@font-face {src: url(\"test.woff\") format(woff);}",
14591      "@font-face{src:url(test.woff)format(\"woff\")}",
14592    );
14593    minify_test(
14594      "@font-face {src: url(\"test.ttc\") format(collection), url(test.ttf) format(truetype);}",
14595      "@font-face{src:url(test.ttc)format(\"collection\"),url(test.ttf)format(\"truetype\")}",
14596    );
14597    minify_test(
14598      "@font-face {src: url(\"test.otf\") format(opentype) tech(features-aat);}",
14599      "@font-face{src:url(test.otf)format(\"opentype\")tech(features-aat)}",
14600    );
14601    minify_test(
14602      "@font-face {src: url(\"test.woff\") format(woff) tech(color-colrv1);}",
14603      "@font-face{src:url(test.woff)format(\"woff\")tech(color-colrv1)}",
14604    );
14605    minify_test(
14606      "@font-face {src: url(\"test.woff2\") format(woff2) tech(variations);}",
14607      "@font-face{src:url(test.woff2)format(\"woff2\")tech(variations)}",
14608    );
14609    minify_test(
14610      "@font-face {src: url(\"test.woff\") format(woff) tech(palettes);}",
14611      "@font-face{src:url(test.woff)format(\"woff\")tech(palettes)}",
14612    );
14613    // multiple tech
14614    minify_test(
14615      "@font-face {src: url(\"test.woff\") format(woff) tech(features-opentype, color-sbix);}",
14616      "@font-face{src:url(test.woff)format(\"woff\")tech(features-opentype,color-sbix)}",
14617    );
14618    minify_test(
14619      "@font-face {src: url(\"test.woff\")   format(woff)    tech(incremental, color-svg, features-graphite, features-aat);}",
14620      "@font-face{src:url(test.woff)format(\"woff\")tech(incremental,color-svg,features-graphite,features-aat)}",
14621    );
14622    // format() function must precede tech() if both are present
14623    minify_test(
14624      "@font-face {src: url(\"foo.ttf\") format(opentype) tech(color-colrv1);}",
14625      "@font-face{src:url(foo.ttf)format(\"opentype\")tech(color-colrv1)}",
14626    );
14627    // only have tech is valid
14628    minify_test(
14629      "@font-face {src: url(\"foo.ttf\") tech(color-SVG);}",
14630      "@font-face{src:url(foo.ttf)tech(color-svg)}",
14631    );
14632    // CGQAQ: if tech and format both presence, order is matter, tech before format is invalid
14633    // but now just return raw token, we don't have strict mode yet.
14634    // ref: https://github.com/parcel-bundler/lightningcss/pull/255#issuecomment-1219049998
14635    minify_test(
14636      "@font-face {src: url(\"foo.ttf\") tech(palettes  color-colrv0  variations) format(opentype);}",
14637      "@font-face{src:url(foo.ttf) tech(palettes color-colrv0 variations) format(opentype)}",
14638    );
14639    // TODO(CGQAQ): make this test pass when we have strict mode
14640    // ref: https://github.com/web-platform-tests/wpt/blob/9f8a6ccc41aa725e8f51f4f096f686313bb88d8d/css/css-fonts/parsing/font-face-src-tech.html#L45
14641    // error_test(
14642    //   "@font-face {src: url(\"foo.ttf\") tech(features-opentype) format(opentype);}",
14643    //   ParserError::AtRuleBodyInvalid,
14644    // );
14645    // error_test(
14646    //   "@font-face {src: url(\"foo.ttf\") tech();}",
14647    //   ParserError::AtRuleBodyInvalid,
14648    // );
14649    // error_test(
14650    //   "@font-face {src: url(\"foo.ttf\") tech(\"features-opentype\");}",
14651    //   ParserError::AtRuleBodyInvalid,
14652    // );
14653    // error_test(
14654    //   "@font-face {src: url(\"foo.ttf\") tech(\"color-colrv0\");}",
14655    //   ParserError::AtRuleBodyInvalid,
14656    // );
14657    minify_test(
14658      "@font-face {src: local(\"\") url(\"test.woff\");}",
14659      "@font-face{src:local(\"\") url(test.woff)}",
14660    );
14661    minify_test("@font-face {font-weight: 200 400}", "@font-face{font-weight:200 400}");
14662    minify_test("@font-face {font-weight: 400 400}", "@font-face{font-weight:400}");
14663    minify_test(
14664      "@font-face {font-stretch: 50% 200%}",
14665      "@font-face{font-stretch:50% 200%}",
14666    );
14667    minify_test("@font-face {font-stretch: 50% 50%}", "@font-face{font-stretch:50%}");
14668    minify_test("@font-face {unicode-range: U+26;}", "@font-face{unicode-range:U+26}");
14669    minify_test("@font-face {unicode-range: u+26;}", "@font-face{unicode-range:U+26}");
14670    minify_test(
14671      "@font-face {unicode-range: U+0-7F;}",
14672      "@font-face{unicode-range:U+0-7F}",
14673    );
14674    minify_test(
14675      "@font-face {unicode-range: U+0025-00FF;}",
14676      "@font-face{unicode-range:U+25-FF}",
14677    );
14678    minify_test("@font-face {unicode-range: U+4??;}", "@font-face{unicode-range:U+4??}");
14679    minify_test(
14680      "@font-face {unicode-range: U+400-4FF;}",
14681      "@font-face{unicode-range:U+4??}",
14682    );
14683    minify_test(
14684      "@font-face {unicode-range: U+0025-00FF, U+4??;}",
14685      "@font-face{unicode-range:U+25-FF,U+4??}",
14686    );
14687    minify_test(
14688      "@font-face {unicode-range: U+A5, U+4E00-9FFF, U+30??, U+FF00-FF9F;}",
14689      "@font-face{unicode-range:U+A5,U+4E00-9FFF,U+30??,U+FF00-FF9F}",
14690    );
14691    minify_test(
14692      "@font-face {unicode-range: U+????;}",
14693      "@font-face{unicode-range:U+????}",
14694    );
14695    minify_test(
14696      "@font-face {unicode-range: U+0000-FFFF;}",
14697      "@font-face{unicode-range:U+????}",
14698    );
14699    minify_test(
14700      "@font-face {unicode-range: U+10????;}",
14701      "@font-face{unicode-range:U+10????}",
14702    );
14703    minify_test(
14704      "@font-face {unicode-range: U+100000-10FFFF;}",
14705      "@font-face{unicode-range:U+10????}",
14706    );
14707    minify_test(
14708      "@font-face {unicode-range: U+1e1e?;}",
14709      "@font-face{unicode-range:U+1E1E?}",
14710    );
14711    minify_test(
14712      "@font-face {unicode-range: u+????, U+1????, U+10????;}",
14713      "@font-face{unicode-range:U+????,U+1????,U+10????}",
14714    );
14715    minify_test(r#"
14716      @font-face {
14717        font-family: Inter;
14718        font-style: oblique 0deg 10deg;
14719        font-weight: 100 900;
14720        src: url("../fonts/Inter.var.woff2?v=3.19") format("woff2");
14721        font-display: swap;
14722      }
14723    "#, "@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}");
14724    minify_test(r#"
14725    @font-face {
14726      font-family: Inter;
14727      font-style: oblique 14deg 14deg;
14728      font-weight: 100 900;
14729      src: url("../fonts/Inter.var.woff2?v=3.19") format("woff2");
14730      font-display: swap;
14731    }
14732  "#, "@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}");
14733  }
14734
14735  #[test]
14736  fn test_font_palette_values() {
14737    minify_test(
14738      r#"@font-palette-values --Cooler {
14739      font-family: Bixa;
14740      base-palette: 1;
14741      override-colors: 1 #7EB7E4;
14742    }"#,
14743      "@font-palette-values --Cooler{font-family:Bixa;base-palette:1;override-colors:1 #7eb7e4}",
14744    );
14745    minify_test(
14746      r#"@font-palette-values --Cooler {
14747      font-family: Handover Sans;
14748      base-palette: 3;
14749      override-colors: 1 rgb(43, 12, 9), 3 lime;
14750    }"#,
14751      "@font-palette-values --Cooler{font-family:Handover Sans;base-palette:3;override-colors:1 #2b0c09,3 #0f0}",
14752    );
14753    minify_test(r#"@font-palette-values --Cooler {
14754      font-family: Handover Sans;
14755      base-palette: 3;
14756      override-colors: 1 rgb(43, 12, 9), 3 var(--highlight);
14757    }"#, "@font-palette-values --Cooler{font-family:Handover Sans;base-palette:3;override-colors:1 #2b0c09, 3 var(--highlight)}");
14758    prefix_test(
14759      r#"@font-palette-values --Cooler {
14760      font-family: Handover Sans;
14761      base-palette: 3;
14762      override-colors: 1 rgb(43, 12, 9), 3 lch(50.998% 135.363 338);
14763    }"#,
14764      indoc! {r#"@font-palette-values --Cooler {
14765      font-family: Handover Sans;
14766      base-palette: 3;
14767      override-colors: 1 #2b0c09, 3 #ee00be;
14768      override-colors: 1 #2b0c09, 3 lch(50.998% 135.363 338);
14769    }
14770    "#},
14771      Browsers {
14772        chrome: Some(90 << 16),
14773        ..Browsers::default()
14774      },
14775    );
14776    prefix_test(
14777      r#"@font-palette-values --Cooler {
14778      font-family: Handover Sans;
14779      base-palette: 3;
14780      override-colors: 1 var(--foo), 3 lch(50.998% 135.363 338);
14781    }"#,
14782      indoc! {r#"@font-palette-values --Cooler {
14783      font-family: Handover Sans;
14784      base-palette: 3;
14785      override-colors: 1 var(--foo), 3 #ee00be;
14786    }
14787
14788    @supports (color: lab(0% 0 0)) {
14789      @font-palette-values --Cooler {
14790        font-family: Handover Sans;
14791        base-palette: 3;
14792        override-colors: 1 var(--foo), 3 lab(50.998% 125.506 -50.7078);
14793      }
14794    }
14795    "#},
14796      Browsers {
14797        chrome: Some(90 << 16),
14798        ..Browsers::default()
14799      },
14800    );
14801    prefix_test(
14802      r#"@supports (color: lab(0% 0 0)) {
14803      @font-palette-values --Cooler {
14804        font-family: Handover Sans;
14805        base-palette: 3;
14806        override-colors: 1 var(--foo), 3 lab(50.998% 125.506 -50.7078);
14807      }
14808    }"#,
14809      indoc! {r#"@supports (color: lab(0% 0 0)) {
14810      @font-palette-values --Cooler {
14811        font-family: Handover Sans;
14812        base-palette: 3;
14813        override-colors: 1 var(--foo), 3 lab(50.998% 125.506 -50.7078);
14814      }
14815    }
14816    "#},
14817      Browsers {
14818        chrome: Some(90 << 16),
14819        ..Browsers::default()
14820      },
14821    );
14822    minify_test(".foo { font-palette: --Custom; }", ".foo{font-palette:--Custom}");
14823  }
14824
14825  #[test]
14826  fn test_position_try() {
14827    minify_test(
14828      r#"@position-try --outside-right-to-bottom {
14829        left: anchor(left);
14830        margin: 0;
14831        width: auto;
14832      }"#,
14833      "@position-try --outside-right-to-bottom{left:anchor(left);margin:0;width:auto}",
14834    );
14835    test(
14836      r#"@position-try --foo {
14837  top: anchor(bottom);
14838  left: anchor(right);
14839}"#,
14840      indoc! {r#"
14841        @position-try --foo {
14842          top: anchor(bottom);
14843          left: anchor(right);
14844        }
14845      "#},
14846    );
14847    // Nested inside @supports
14848    minify_test(
14849      r#"@supports (anchor-name: --foo) {
14850        @position-try --bar {
14851          top: anchor(bottom);
14852        }
14853      }"#,
14854      "@supports (anchor-name:--foo){@position-try --bar{top:anchor(bottom)}}",
14855    );
14856  }
14857
14858  #[test]
14859  fn test_font_feature_values() {
14860    // https://github.com/clagnut/TODS/blob/e693d52ad411507b960cf01a9734265e3efab102/tods.css#L116-L142
14861    minify_test(
14862      r#"
14863@font-feature-values "Fancy Font Name" {
14864  @styleset { cursive: 1; swoopy: 7 16; }
14865  @character-variant { ampersand: 1; capital-q: 2; }
14866  @stylistic { two-story-g: 1; straight-y: 2; }
14867  @swash { swishy: 1; flowing: 2; }
14868  @ornaments { clover: 1; fleuron: 2; }
14869  @annotation { circled: 1; boxed: 2; }
14870}
14871    "#,
14872      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}}"#,
14873    );
14874
14875    // https://github.com/Sorixelle/srxl.me/blob/4eb4f4a15cb2d21356df24c096d6a819cfdc1a99/public/fonts/inter/inter.css#L201-L222
14876    minify_test(
14877      r#"
14878@font-feature-values "Inter", "Inter var", "Inter var experimental" {
14879  @styleset {
14880    open-digits: 1;
14881    disambiguation: 2;
14882    curved-r: 3;
14883    disambiguation-without-zero: 4;
14884  }
14885
14886  @character-variant {
14887    alt-one: 1;
14888    open-four: 2;
14889    open-six: 3;
14890    open-nine: 4;
14891    lower-l-with-tail: 5;
14892    curved-lower-r: 6;
14893    german-double-s: 7;
14894    upper-i-with-serif: 8;
14895    flat-top-three: 9;
14896    upper-g-with-spur: 10;
14897    single-storey-a: 11;
14898  }
14899}
14900      "#,
14901      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}}"#,
14902    );
14903
14904    // https://github.com/MihailJP/Inconsolata-LGC/blob/7c53cf455787096c93d82d9a51018f12ec39a6e9/Inconsolata-LGC.css#L65-L91
14905    minify_test(
14906      r#"
14907@font-feature-values "Inconsolata LGC" {
14908	@styleset {
14909		alternative-umlaut: 1;
14910	}
14911	@character-variant {
14912		zero-plain: 1 1;
14913		zero-dotted: 1 2;
14914		zero-longslash: 1 3;
14915		r-with-serif: 2 1;
14916		eng-descender: 3 1;
14917		eng-uppercase: 3 2;
14918		dollar-open: 4 1;
14919		dollar-oldstyle: 4 2;
14920		dollar-cifrao: 4 2;
14921		ezh-no-descender: 5 1;
14922		ezh-reversed-sigma: 5 2;
14923		triangle-text-form: 6 1;
14924		el-with-hook-old: 7 1;
14925		qa-enlarged-lowercase: 8 1;
14926		qa-reversed-p: 8 2;
14927		che-with-hook: 9 1;
14928		che-with-hook-alt: 9 2;
14929		ge-with-hook: 10 1;
14930		ge-with-hook-alt: 10 2;
14931		ge-with-stroke-and-descender: 11 1;
14932	}
14933}
14934    "#,
14935      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}}"#,
14936    );
14937
14938    minify_test(
14939      r#"
14940      @font-feature-values "Fancy Font Name" {
14941        @styleset { cursive: 1; swoopy: 7 16; }
14942        @character-variant { ampersand: 1; capital-q: 2; }
14943      }
14944      "#,
14945      r#"@font-feature-values Fancy Font Name{@styleset{cursive:1;swoopy:7 16}@character-variant{ampersand:1;capital-q:2}}"#,
14946    );
14947    minify_test(
14948      r#"
14949      @font-feature-values foo {
14950          @swash { pretty: 0; pretty: 1; cool: 2; }
14951      }
14952      "#,
14953      "@font-feature-values foo{@swash{pretty:1;cool:2}}",
14954    );
14955    minify_test(
14956      r#"
14957      @font-feature-values foo {
14958          @swash { pretty: 1; }
14959          @swash { cool: 2; }
14960      }
14961      "#,
14962      "@font-feature-values foo{@swash{pretty:1;cool:2}}",
14963    );
14964    minify_test(
14965      r#"
14966      @font-feature-values foo {
14967          @swash { pretty: 1; }
14968      }
14969      @font-feature-values foo {
14970          @swash { cool: 2; }
14971      }
14972      "#,
14973      "@font-feature-values foo{@swash{pretty:1;cool:2}}",
14974    );
14975  }
14976
14977  #[test]
14978  fn test_page_rule() {
14979    minify_test("@page {margin: 0.5cm}", "@page{margin:.5cm}");
14980    minify_test("@page :left {margin: 0.5cm}", "@page:left{margin:.5cm}");
14981    minify_test("@page :right {margin: 0.5cm}", "@page:right{margin:.5cm}");
14982    minify_test(
14983      "@page LandscapeTable {margin: 0.5cm}",
14984      "@page LandscapeTable{margin:.5cm}",
14985    );
14986    minify_test(
14987      "@page CompanyLetterHead:first {margin: 0.5cm}",
14988      "@page CompanyLetterHead:first{margin:.5cm}",
14989    );
14990    minify_test("@page:first {margin: 0.5cm}", "@page:first{margin:.5cm}");
14991    minify_test("@page :blank:first {margin: 0.5cm}", "@page:blank:first{margin:.5cm}");
14992    minify_test("@page toc, index {margin: 0.5cm}", "@page toc,index{margin:.5cm}");
14993    minify_test(
14994      r#"
14995    @page :right {
14996      @bottom-left {
14997        margin: 10pt;
14998      }
14999    }
15000    "#,
15001      "@page:right{@bottom-left{margin:10pt}}",
15002    );
15003    minify_test(
15004      r#"
15005    @page :right {
15006      margin: 1in;
15007
15008      @bottom-left {
15009        margin: 10pt;
15010      }
15011    }
15012    "#,
15013      "@page:right{margin:1in;@bottom-left{margin:10pt}}",
15014    );
15015
15016    test(
15017      r#"
15018    @page :right {
15019      @bottom-left {
15020        margin: 10pt;
15021      }
15022    }
15023    "#,
15024      indoc! {r#"
15025      @page :right {
15026        @bottom-left {
15027          margin: 10pt;
15028        }
15029      }
15030      "#},
15031    );
15032
15033    test(
15034      r#"
15035    @page :right {
15036      margin: 1in;
15037
15038      @bottom-left-corner { content: "Foo"; }
15039      @bottom-right-corner { content: "Bar"; }
15040    }
15041    "#,
15042      indoc! {r#"
15043      @page :right {
15044        margin: 1in;
15045
15046        @bottom-left-corner {
15047          content: "Foo";
15048        }
15049
15050        @bottom-right-corner {
15051          content: "Bar";
15052        }
15053      }
15054      "#},
15055    );
15056
15057    error_test(
15058      r#"
15059      @page {
15060        @foo {
15061          margin: 1in;
15062        }
15063      }
15064      "#,
15065      ParserError::AtRuleInvalid("foo".into()),
15066    );
15067
15068    error_test(
15069      r#"
15070      @page {
15071        @top-left-corner {
15072          @bottom-left {
15073            margin: 1in;
15074          }
15075        }
15076      }
15077      "#,
15078      ParserError::AtRuleInvalid("bottom-left".into()),
15079    );
15080  }
15081
15082  #[test]
15083  fn test_supports_rule() {
15084    test(
15085      r#"
15086      @supports (foo: bar) {
15087        .test {
15088          foo: bar;
15089        }
15090      }
15091    "#,
15092      indoc! { r#"
15093      @supports (foo: bar) {
15094        .test {
15095          foo: bar;
15096        }
15097      }
15098    "#},
15099    );
15100    test(
15101      r#"
15102      @supports not (foo: bar) {
15103        .test {
15104          foo: bar;
15105        }
15106      }
15107    "#,
15108      indoc! { r#"
15109      @supports not (foo: bar) {
15110        .test {
15111          foo: bar;
15112        }
15113      }
15114    "#},
15115    );
15116    test(
15117      r#"
15118      @supports (foo: bar) or (bar: baz) {
15119        .test {
15120          foo: bar;
15121        }
15122      }
15123    "#,
15124      indoc! { r#"
15125      @supports (foo: bar) or (bar: baz) {
15126        .test {
15127          foo: bar;
15128        }
15129      }
15130    "#},
15131    );
15132    test(
15133      r#"
15134      @supports (((foo: bar) or (bar: baz))) {
15135        .test {
15136          foo: bar;
15137        }
15138      }
15139    "#,
15140      indoc! { r#"
15141      @supports (foo: bar) or (bar: baz) {
15142        .test {
15143          foo: bar;
15144        }
15145      }
15146    "#},
15147    );
15148    test(
15149      r#"
15150      @supports (foo: bar) and (bar: baz) {
15151        .test {
15152          foo: bar;
15153        }
15154      }
15155    "#,
15156      indoc! { r#"
15157      @supports (foo: bar) and (bar: baz) {
15158        .test {
15159          foo: bar;
15160        }
15161      }
15162    "#},
15163    );
15164    test(
15165      r#"
15166      @supports (((foo: bar) and (bar: baz))) {
15167        .test {
15168          foo: bar;
15169        }
15170      }
15171    "#,
15172      indoc! { r#"
15173      @supports (foo: bar) and (bar: baz) {
15174        .test {
15175          foo: bar;
15176        }
15177      }
15178    "#},
15179    );
15180    test(
15181      r#"
15182      @supports (foo: bar) and (((bar: baz) or (test: foo))) {
15183        .test {
15184          foo: bar;
15185        }
15186      }
15187    "#,
15188      indoc! { r#"
15189      @supports (foo: bar) and ((bar: baz) or (test: foo)) {
15190        .test {
15191          foo: bar;
15192        }
15193      }
15194    "#},
15195    );
15196    test(
15197      r#"
15198      @supports not (((foo: bar) and (bar: baz))) {
15199        .test {
15200          foo: bar;
15201        }
15202      }
15203    "#,
15204      indoc! { r#"
15205      @supports not ((foo: bar) and (bar: baz)) {
15206        .test {
15207          foo: bar;
15208        }
15209      }
15210    "#},
15211    );
15212    test(
15213      r#"
15214      @supports selector(a > b) {
15215        .test {
15216          foo: bar;
15217        }
15218      }
15219    "#,
15220      indoc! { r#"
15221      @supports selector(a > b) {
15222        .test {
15223          foo: bar;
15224        }
15225      }
15226    "#},
15227    );
15228    test(
15229      r#"
15230      @supports unknown(test) {
15231        .test {
15232          foo: bar;
15233        }
15234      }
15235    "#,
15236      indoc! { r#"
15237      @supports unknown(test) {
15238        .test {
15239          foo: bar;
15240        }
15241      }
15242    "#},
15243    );
15244    test(
15245      r#"
15246      @supports (unknown) {
15247        .test {
15248          foo: bar;
15249        }
15250      }
15251    "#,
15252      indoc! { r#"
15253      @supports (unknown) {
15254        .test {
15255          foo: bar;
15256        }
15257      }
15258    "#},
15259    );
15260    test(
15261      r#"
15262      @supports (display: grid) and (not (display: inline-grid)) {
15263        .test {
15264          foo: bar;
15265        }
15266      }
15267    "#,
15268      indoc! { r#"
15269      @supports (display: grid) and (not (display: inline-grid)) {
15270        .test {
15271          foo: bar;
15272        }
15273      }
15274    "#},
15275    );
15276    prefix_test(
15277      r#"
15278      @supports (backdrop-filter: blur(10px)) {
15279        div {
15280          backdrop-filter: blur(10px);
15281        }
15282      }
15283    "#,
15284      indoc! { r#"
15285      @supports ((-webkit-backdrop-filter: blur(10px)) or (backdrop-filter: blur(10px))) {
15286        div {
15287          -webkit-backdrop-filter: blur(10px);
15288          backdrop-filter: blur(10px);
15289        }
15290      }
15291    "#},
15292      Browsers {
15293        safari: Some(14 << 16),
15294        ..Default::default()
15295      },
15296    );
15297    prefix_test(
15298      r#"
15299      @supports ((-webkit-backdrop-filter: blur(10px)) or (backdrop-filter: blur(10px))) {
15300        div {
15301          backdrop-filter: blur(10px);
15302        }
15303      }
15304    "#,
15305      indoc! { r#"
15306      @supports ((-webkit-backdrop-filter: blur(10px)) or (backdrop-filter: blur(10px))) {
15307        div {
15308          -webkit-backdrop-filter: blur(10px);
15309          backdrop-filter: blur(10px);
15310        }
15311      }
15312    "#},
15313      Browsers {
15314        safari: Some(14 << 16),
15315        ..Default::default()
15316      },
15317    );
15318    prefix_test(
15319      r#"
15320      @supports ((-webkit-backdrop-filter: blur(20px)) or (backdrop-filter: blur(10px))) {
15321        div {
15322          backdrop-filter: blur(10px);
15323        }
15324      }
15325    "#,
15326      indoc! { r#"
15327      @supports ((-webkit-backdrop-filter: blur(20px))) or ((-webkit-backdrop-filter: blur(10px)) or (backdrop-filter: blur(10px))) {
15328        div {
15329          -webkit-backdrop-filter: blur(10px);
15330          backdrop-filter: blur(10px);
15331        }
15332      }
15333    "#},
15334      Browsers {
15335        safari: Some(14 << 16),
15336        ..Default::default()
15337      },
15338    );
15339    prefix_test(
15340      r#"
15341      @supports ((-webkit-backdrop-filter: blur(10px)) or (backdrop-filter: blur(10px))) {
15342        div {
15343          backdrop-filter: blur(10px);
15344        }
15345      }
15346    "#,
15347      indoc! { r#"
15348      @supports (backdrop-filter: blur(10px)) {
15349        div {
15350          backdrop-filter: blur(10px);
15351        }
15352      }
15353    "#},
15354      Browsers {
15355        chrome: Some(80 << 16),
15356        ..Default::default()
15357      },
15358    );
15359    minify_test(
15360      r#"
15361      @supports (width: calc(10px * 2)) {
15362        .test {
15363          width: calc(10px * 2);
15364        }
15365      }
15366    "#,
15367      "@supports (width:calc(10px * 2)){.test{width:20px}}",
15368    );
15369    minify_test(
15370      r#"
15371      @supports (color: hsl(0deg, 0%, 0%)) {
15372        .test {
15373          color: hsl(0deg, 0%, 0%);
15374        }
15375      }
15376    "#,
15377      "@supports (color:hsl(0deg, 0%, 0%)){.test{color:#000}}",
15378    );
15379  }
15380
15381  #[test]
15382  fn test_counter_style() {
15383    test(
15384      r#"
15385      @counter-style circled-alpha {
15386        system: fixed;
15387        symbols: Ⓐ Ⓑ Ⓒ;
15388        suffix: " ";
15389      }
15390    "#,
15391      indoc! { r#"
15392      @counter-style circled-alpha {
15393        system: fixed;
15394        symbols: Ⓐ Ⓑ Ⓒ;
15395        suffix: " ";
15396      }
15397    "#},
15398    );
15399  }
15400
15401  #[test]
15402  fn test_namespace() {
15403    minify_test(
15404      "@namespace url(http://toto.example.org);",
15405      "@namespace \"http://toto.example.org\";",
15406    );
15407    minify_test(
15408      "@namespace \"http://toto.example.org\";",
15409      "@namespace \"http://toto.example.org\";",
15410    );
15411    minify_test(
15412      "@namespace toto \"http://toto.example.org\";",
15413      "@namespace toto \"http://toto.example.org\";",
15414    );
15415    minify_test(
15416      "@namespace toto url(http://toto.example.org);",
15417      "@namespace toto \"http://toto.example.org\";",
15418    );
15419
15420    test(
15421      r#"
15422      @namespace "http://example.com/foo";
15423
15424      x {
15425        color: red;
15426      }
15427    "#,
15428      indoc! {r#"
15429      @namespace "http://example.com/foo";
15430
15431      x {
15432        color: red;
15433      }
15434    "#},
15435    );
15436
15437    test(
15438      r#"
15439      @namespace toto "http://toto.example.org";
15440
15441      toto|x {
15442        color: red;
15443      }
15444
15445      [toto|att=val] {
15446        color: blue
15447      }
15448    "#,
15449      indoc! {r#"
15450      @namespace toto "http://toto.example.org";
15451
15452      toto|x {
15453        color: red;
15454      }
15455
15456      [toto|att="val"] {
15457        color: #00f;
15458      }
15459    "#},
15460    );
15461
15462    test(
15463      r#"
15464      @namespace "http://example.com/foo";
15465
15466      |x {
15467        color: red;
15468      }
15469
15470      [|att=val] {
15471        color: blue
15472      }
15473    "#,
15474      indoc! {r#"
15475      @namespace "http://example.com/foo";
15476
15477      |x {
15478        color: red;
15479      }
15480
15481      [att="val"] {
15482        color: #00f;
15483      }
15484    "#},
15485    );
15486
15487    test(
15488      r#"
15489      @namespace "http://example.com/foo";
15490
15491      *|x {
15492        color: red;
15493      }
15494
15495      [*|att=val] {
15496        color: blue
15497      }
15498    "#,
15499      indoc! {r#"
15500      @namespace "http://example.com/foo";
15501
15502      *|x {
15503        color: red;
15504      }
15505
15506      [*|att="val"] {
15507        color: #00f;
15508      }
15509    "#},
15510    );
15511
15512    error_test(
15513      ".foo { color: red } @namespace \"http://example.com/foo\";",
15514      ParserError::UnexpectedNamespaceRule,
15515    );
15516  }
15517
15518  #[test]
15519  fn test_import() {
15520    minify_test("@import url(foo.css);", "@import \"foo.css\";");
15521    minify_test("@import \"foo.css\";", "@import \"foo.css\";");
15522    minify_test("@import url(foo.css) print;", "@import \"foo.css\" print;");
15523    minify_test("@import \"foo.css\" print;", "@import \"foo.css\" print;");
15524    minify_test(
15525      "@import \"foo.css\" screen and (orientation: landscape);",
15526      "@import \"foo.css\" screen and (orientation:landscape);",
15527    );
15528    minify_test(
15529      "@import url(foo.css) supports(display: flex);",
15530      "@import \"foo.css\" supports(display:flex);",
15531    );
15532    minify_test(
15533      "@import url(foo.css) supports(display: flex) print;",
15534      "@import \"foo.css\" supports(display:flex) print;",
15535    );
15536    minify_test(
15537      "@import url(foo.css) supports(not (display: flex));",
15538      "@import \"foo.css\" supports(not (display:flex));",
15539    );
15540    minify_test(
15541      "@import url(foo.css) supports((display: flex));",
15542      "@import \"foo.css\" supports(display:flex);",
15543    );
15544    minify_test("@charset \"UTF-8\"; @import url(foo.css);", "@import \"foo.css\";");
15545    minify_test("@layer foo; @import url(foo.css);", "@layer foo;@import \"foo.css\";");
15546    error_test(
15547      ".foo { color: red } @import url(bar.css);",
15548      ParserError::UnexpectedImportRule,
15549    );
15550    error_test(
15551      "@namespace \"http://example.com/foo\"; @import url(bar.css);",
15552      ParserError::UnexpectedImportRule,
15553    );
15554    error_test(
15555      "@media print { .foo { color: red }} @import url(bar.css);",
15556      ParserError::UnexpectedImportRule,
15557    );
15558    error_test(
15559      "@layer foo; @import url(foo.css); @layer bar; @import url(bar.css)",
15560      ParserError::UnexpectedImportRule,
15561    );
15562    let warnings = error_recovery_test("@import './actual-styles.css';");
15563    assert_eq!(warnings, vec![]);
15564  }
15565
15566  #[test]
15567  fn test_prefixes() {
15568    prefix_test(
15569      r#"
15570      .foo {
15571        -webkit-transition: opacity 200ms;
15572        -moz-transition: opacity 200ms;
15573        transition: opacity 200ms;
15574      }
15575      "#,
15576      indoc! {r#"
15577      .foo {
15578        transition: opacity .2s;
15579      }
15580      "#},
15581      Browsers {
15582        chrome: Some(95 << 16),
15583        ..Browsers::default()
15584      },
15585    );
15586
15587    prefix_test(
15588      ".foo{transition:opacity 200ms}",
15589      indoc! {r#"
15590      .foo {
15591        -webkit-transition: opacity .2s;
15592        -moz-transition: opacity .2s;
15593        transition: opacity .2s;
15594      }
15595      "#},
15596      Browsers {
15597        safari: Some(5 << 16),
15598        firefox: Some(14 << 16),
15599        ..Browsers::default()
15600      },
15601    );
15602  }
15603
15604  #[test]
15605  fn test_display() {
15606    minify_test(".foo { display: block }", ".foo{display:block}");
15607    minify_test(".foo { display: block flow }", ".foo{display:block}");
15608    minify_test(".foo { display: flow-root }", ".foo{display:flow-root}");
15609    minify_test(".foo { display: block flow-root }", ".foo{display:flow-root}");
15610    minify_test(".foo { display: inline }", ".foo{display:inline}");
15611    minify_test(".foo { display: inline flow }", ".foo{display:inline}");
15612    minify_test(".foo { display: inline-block }", ".foo{display:inline-block}");
15613    minify_test(".foo { display: inline flow-root }", ".foo{display:inline-block}");
15614    minify_test(".foo { display: run-in }", ".foo{display:run-in}");
15615    minify_test(".foo { display: run-in flow }", ".foo{display:run-in}");
15616    minify_test(".foo { display: list-item }", ".foo{display:list-item}");
15617    minify_test(".foo { display: block flow list-item }", ".foo{display:list-item}");
15618    minify_test(".foo { display: inline list-item }", ".foo{display:inline list-item}");
15619    minify_test(
15620      ".foo { display: inline flow list-item }",
15621      ".foo{display:inline list-item}",
15622    );
15623    minify_test(".foo { display: flex }", ".foo{display:flex}");
15624    minify_test(".foo { display: block flex }", ".foo{display:flex}");
15625    minify_test(".foo { display: inline-flex }", ".foo{display:inline-flex}");
15626    minify_test(".foo { display: inline flex }", ".foo{display:inline-flex}");
15627    minify_test(".foo { display: grid }", ".foo{display:grid}");
15628    minify_test(".foo { display: block grid }", ".foo{display:grid}");
15629    minify_test(".foo { display: inline-grid }", ".foo{display:inline-grid}");
15630    minify_test(".foo { display: inline grid }", ".foo{display:inline-grid}");
15631    minify_test(".foo { display: ruby }", ".foo{display:ruby}");
15632    minify_test(".foo { display: inline ruby }", ".foo{display:ruby}");
15633    minify_test(".foo { display: block ruby }", ".foo{display:block ruby}");
15634    minify_test(".foo { display: table }", ".foo{display:table}");
15635    minify_test(".foo { display: block table }", ".foo{display:table}");
15636    minify_test(".foo { display: inline-table }", ".foo{display:inline-table}");
15637    minify_test(".foo { display: inline table }", ".foo{display:inline-table}");
15638    minify_test(".foo { display: table-row-group }", ".foo{display:table-row-group}");
15639    minify_test(".foo { display: contents }", ".foo{display:contents}");
15640    minify_test(".foo { display: none }", ".foo{display:none}");
15641    minify_test(".foo { display: -webkit-flex }", ".foo{display:-webkit-flex}");
15642    minify_test(".foo { display: -ms-flexbox }", ".foo{display:-ms-flexbox}");
15643    minify_test(".foo { display: -webkit-box }", ".foo{display:-webkit-box}");
15644    minify_test(".foo { display: -moz-box }", ".foo{display:-moz-box}");
15645    minify_test(
15646      ".foo { display: -webkit-flex; display: -moz-box; display: flex }",
15647      ".foo{display:-webkit-flex;display:-moz-box;display:flex}",
15648    );
15649    minify_test(
15650      ".foo { display: -webkit-flex; display: flex; display: -moz-box }",
15651      ".foo{display:-webkit-flex;display:flex;display:-moz-box}",
15652    );
15653    minify_test(".foo { display: flex; display: grid }", ".foo{display:grid}");
15654    minify_test(
15655      ".foo { display: -webkit-inline-flex; display: -moz-inline-box; display: inline-flex }",
15656      ".foo{display:-webkit-inline-flex;display:-moz-inline-box;display:inline-flex}",
15657    );
15658    minify_test(
15659      ".foo { display: flex; display: var(--grid); }",
15660      ".foo{display:flex;display:var(--grid)}",
15661    );
15662    prefix_test(
15663      ".foo{ display: flex }",
15664      indoc! {r#"
15665      .foo {
15666        display: -webkit-box;
15667        display: -moz-box;
15668        display: -webkit-flex;
15669        display: -ms-flexbox;
15670        display: flex;
15671      }
15672      "#},
15673      Browsers {
15674        safari: Some(4 << 16),
15675        firefox: Some(14 << 16),
15676        ie: Some(10 << 16),
15677        ..Browsers::default()
15678      },
15679    );
15680    prefix_test(
15681      ".foo{ display: flex; display: -webkit-box; }",
15682      indoc! {r#"
15683      .foo {
15684        display: -webkit-box;
15685      }
15686      "#},
15687      Browsers {
15688        safari: Some(4 << 16),
15689        firefox: Some(14 << 16),
15690        ie: Some(10 << 16),
15691        ..Browsers::default()
15692      },
15693    );
15694    prefix_test(
15695      ".foo{ display: -webkit-box; display: flex; }",
15696      indoc! {r#"
15697      .foo {
15698        display: -webkit-box;
15699        display: -moz-box;
15700        display: -webkit-flex;
15701        display: -ms-flexbox;
15702        display: flex;
15703      }
15704      "#},
15705      Browsers {
15706        safari: Some(4 << 16),
15707        firefox: Some(14 << 16),
15708        ie: Some(10 << 16),
15709        ..Browsers::default()
15710      },
15711    );
15712    prefix_test(
15713      r#"
15714      .foo {
15715        display: -webkit-box;
15716        display: -moz-box;
15717        display: -webkit-flex;
15718        display: -ms-flexbox;
15719        display: flex;
15720      }
15721      "#,
15722      indoc! {r#"
15723      .foo {
15724        display: flex;
15725      }
15726      "#},
15727      Browsers {
15728        safari: Some(14 << 16),
15729        ..Browsers::default()
15730      },
15731    );
15732    prefix_test(
15733      r#"
15734      .foo {
15735        display: -webkit-box;
15736        display: flex;
15737        display: -moz-box;
15738        display: -webkit-flex;
15739        display: -ms-flexbox;
15740      }
15741      "#,
15742      indoc! {r#"
15743      .foo {
15744        display: -moz-box;
15745        display: -webkit-flex;
15746        display: -ms-flexbox;
15747      }
15748      "#},
15749      Browsers {
15750        safari: Some(14 << 16),
15751        ..Browsers::default()
15752      },
15753    );
15754    prefix_test(
15755      ".foo{ display: inline-flex }",
15756      indoc! {r#"
15757      .foo {
15758        display: -webkit-inline-box;
15759        display: -moz-inline-box;
15760        display: -webkit-inline-flex;
15761        display: -ms-inline-flexbox;
15762        display: inline-flex;
15763      }
15764      "#},
15765      Browsers {
15766        safari: Some(4 << 16),
15767        firefox: Some(14 << 16),
15768        ie: Some(10 << 16),
15769        ..Browsers::default()
15770      },
15771    );
15772    prefix_test(
15773      r#"
15774      .foo {
15775        display: -webkit-inline-box;
15776        display: -moz-inline-box;
15777        display: -webkit-inline-flex;
15778        display: -ms-inline-flexbox;
15779        display: inline-flex;
15780      }
15781      "#,
15782      indoc! {r#"
15783      .foo {
15784        display: inline-flex;
15785      }
15786      "#},
15787      Browsers {
15788        safari: Some(14 << 16),
15789        ..Browsers::default()
15790      },
15791    );
15792  }
15793
15794  #[test]
15795  fn test_visibility() {
15796    minify_test(".foo { visibility: visible }", ".foo{visibility:visible}");
15797    minify_test(".foo { visibility: hidden }", ".foo{visibility:hidden}");
15798    minify_test(".foo { visibility: collapse }", ".foo{visibility:collapse}");
15799    minify_test(".foo { visibility: Visible }", ".foo{visibility:visible}");
15800  }
15801
15802  #[test]
15803  fn test_text_transform() {
15804    minify_test(".foo { text-transform: uppercase }", ".foo{text-transform:uppercase}");
15805    minify_test(".foo { text-transform: lowercase }", ".foo{text-transform:lowercase}");
15806    minify_test(".foo { text-transform: capitalize }", ".foo{text-transform:capitalize}");
15807    minify_test(".foo { text-transform: none }", ".foo{text-transform:none}");
15808    minify_test(".foo { text-transform: full-width }", ".foo{text-transform:full-width}");
15809    minify_test(
15810      ".foo { text-transform: full-size-kana }",
15811      ".foo{text-transform:full-size-kana}",
15812    );
15813    minify_test(
15814      ".foo { text-transform: uppercase full-width }",
15815      ".foo{text-transform:uppercase full-width}",
15816    );
15817    minify_test(
15818      ".foo { text-transform: full-width uppercase }",
15819      ".foo{text-transform:uppercase full-width}",
15820    );
15821    minify_test(
15822      ".foo { text-transform: uppercase full-width full-size-kana }",
15823      ".foo{text-transform:uppercase full-width full-size-kana}",
15824    );
15825    minify_test(
15826      ".foo { text-transform: full-width uppercase full-size-kana }",
15827      ".foo{text-transform:uppercase full-width full-size-kana}",
15828    );
15829  }
15830
15831  #[test]
15832  fn test_whitespace() {
15833    minify_test(".foo { white-space: normal }", ".foo{white-space:normal}");
15834    minify_test(".foo { white-space: pre }", ".foo{white-space:pre}");
15835    minify_test(".foo { white-space: nowrap }", ".foo{white-space:nowrap}");
15836    minify_test(".foo { white-space: pre-wrap }", ".foo{white-space:pre-wrap}");
15837    minify_test(".foo { white-space: break-spaces }", ".foo{white-space:break-spaces}");
15838    minify_test(".foo { white-space: pre-line }", ".foo{white-space:pre-line}");
15839    minify_test(".foo { white-space: NoWrAp }", ".foo{white-space:nowrap}");
15840  }
15841
15842  #[test]
15843  fn test_tab_size() {
15844    minify_test(".foo { tab-size: 8 }", ".foo{tab-size:8}");
15845    minify_test(".foo { tab-size: 4px }", ".foo{tab-size:4px}");
15846    minify_test(".foo { -moz-tab-size: 4px }", ".foo{-moz-tab-size:4px}");
15847    minify_test(".foo { -o-tab-size: 4px }", ".foo{-o-tab-size:4px}");
15848    prefix_test(
15849      ".foo{ tab-size: 4 }",
15850      indoc! {r#"
15851      .foo {
15852        -moz-tab-size: 4;
15853        -o-tab-size: 4;
15854        tab-size: 4;
15855      }
15856      "#},
15857      Browsers {
15858        safari: Some(8 << 16),
15859        firefox: Some(50 << 16),
15860        opera: Some(12 << 16),
15861        ..Browsers::default()
15862      },
15863    );
15864    prefix_test(
15865      r#"
15866      .foo {
15867        -moz-tab-size: 4;
15868        -o-tab-size: 4;
15869        tab-size: 4;
15870      }
15871      "#,
15872      indoc! {r#"
15873      .foo {
15874        tab-size: 4;
15875      }
15876      "#},
15877      Browsers {
15878        safari: Some(8 << 16),
15879        firefox: Some(94 << 16),
15880        opera: Some(30 << 16),
15881        ..Browsers::default()
15882      },
15883    );
15884  }
15885
15886  #[test]
15887  fn test_word_break() {
15888    minify_test(".foo { word-break: normal }", ".foo{word-break:normal}");
15889    minify_test(".foo { word-break: keep-all }", ".foo{word-break:keep-all}");
15890    minify_test(".foo { word-break: break-all }", ".foo{word-break:break-all}");
15891    minify_test(".foo { word-break: break-word }", ".foo{word-break:break-word}");
15892  }
15893
15894  #[test]
15895  fn test_line_break() {
15896    minify_test(".foo { line-break: auto }", ".foo{line-break:auto}");
15897    minify_test(".foo { line-break: Loose }", ".foo{line-break:loose}");
15898    minify_test(".foo { line-break: anywhere }", ".foo{line-break:anywhere}");
15899  }
15900
15901  #[test]
15902  fn test_wrap() {
15903    minify_test(".foo { overflow-wrap: nOrmal }", ".foo{overflow-wrap:normal}");
15904    minify_test(".foo { overflow-wrap: break-Word }", ".foo{overflow-wrap:break-word}");
15905    minify_test(".foo { overflow-wrap: Anywhere }", ".foo{overflow-wrap:anywhere}");
15906    minify_test(".foo { word-wrap: Normal }", ".foo{word-wrap:normal}");
15907    minify_test(".foo { word-wrap: Break-wOrd }", ".foo{word-wrap:break-word}");
15908    minify_test(".foo { word-wrap: Anywhere }", ".foo{word-wrap:anywhere}");
15909  }
15910
15911  #[test]
15912  fn test_hyphens() {
15913    minify_test(".foo { hyphens: manual }", ".foo{hyphens:manual}");
15914    minify_test(".foo { hyphens: auto }", ".foo{hyphens:auto}");
15915    minify_test(".foo { hyphens: none }", ".foo{hyphens:none}");
15916    minify_test(".foo { -webkit-hyphens: manual }", ".foo{-webkit-hyphens:manual}");
15917    minify_test(".foo { -moz-hyphens: manual }", ".foo{-moz-hyphens:manual}");
15918    minify_test(".foo { -ms-hyphens: manual }", ".foo{-ms-hyphens:manual}");
15919    prefix_test(
15920      ".foo{ hyphens: manual }",
15921      indoc! {r#"
15922      .foo {
15923        -webkit-hyphens: manual;
15924        -moz-hyphens: manual;
15925        -ms-hyphens: manual;
15926        hyphens: manual;
15927      }
15928      "#},
15929      Browsers {
15930        safari: Some(14 << 16),
15931        firefox: Some(40 << 16),
15932        ie: Some(10 << 16),
15933        ..Browsers::default()
15934      },
15935    );
15936    prefix_test(
15937      r#"
15938      .foo {
15939        -webkit-hyphens: manual;
15940        -moz-hyphens: manual;
15941        -ms-hyphens: manual;
15942        hyphens: manual;
15943      }
15944      "#,
15945      indoc! {r#"
15946      .foo {
15947        -webkit-hyphens: manual;
15948        hyphens: manual;
15949      }
15950      "#},
15951      Browsers {
15952        safari: Some(14 << 16),
15953        chrome: Some(88 << 16),
15954        firefox: Some(88 << 16),
15955        edge: Some(79 << 16),
15956        ..Browsers::default()
15957      },
15958    );
15959    prefix_test(
15960      r#"
15961      .foo {
15962        -webkit-hyphens: manual;
15963        -moz-hyphens: manual;
15964        -ms-hyphens: manual;
15965        hyphens: manual;
15966      }
15967      "#,
15968      indoc! {r#"
15969      .foo {
15970        hyphens: manual;
15971      }
15972      "#},
15973      Browsers {
15974        chrome: Some(88 << 16),
15975        firefox: Some(88 << 16),
15976        edge: Some(79 << 16),
15977        ..Browsers::default()
15978      },
15979    );
15980  }
15981
15982  #[test]
15983  fn test_text_align() {
15984    minify_test(".foo { text-align: left }", ".foo{text-align:left}");
15985    minify_test(".foo { text-align: Left }", ".foo{text-align:left}");
15986    minify_test(".foo { text-align: END }", ".foo{text-align:end}");
15987    minify_test(".foo { text-align: left }", ".foo{text-align:left}");
15988
15989    prefix_test(
15990      r#"
15991      .foo {
15992        text-align: start;
15993      }
15994    "#,
15995      indoc! {r#"
15996      .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))) {
15997        text-align: left;
15998      }
15999
16000      .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)) {
16001        text-align: right;
16002      }
16003    "#
16004      },
16005      Browsers {
16006        safari: Some(2 << 16),
16007        ..Browsers::default()
16008      },
16009    );
16010
16011    prefix_test(
16012      r#"
16013      .foo {
16014        text-align: end;
16015      }
16016    "#,
16017      indoc! {r#"
16018      .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))) {
16019        text-align: right;
16020      }
16021
16022      .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)) {
16023        text-align: left;
16024      }
16025    "#
16026      },
16027      Browsers {
16028        safari: Some(2 << 16),
16029        ..Browsers::default()
16030      },
16031    );
16032
16033    prefix_test(
16034      r#"
16035      .foo {
16036        text-align: start;
16037      }
16038    "#,
16039      indoc! {r#"
16040      .foo {
16041        text-align: start;
16042      }
16043    "#
16044      },
16045      Browsers {
16046        safari: Some(14 << 16),
16047        ..Browsers::default()
16048      },
16049    );
16050
16051    prefix_test(
16052      r#"
16053      .foo > .bar {
16054        text-align: start;
16055      }
16056    "#,
16057      indoc! {r#"
16058      .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))) {
16059        text-align: left;
16060      }
16061
16062      .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)) {
16063        text-align: right;
16064      }
16065    "#
16066      },
16067      Browsers {
16068        safari: Some(2 << 16),
16069        ..Browsers::default()
16070      },
16071    );
16072
16073    prefix_test(
16074      r#"
16075      .foo:after {
16076        text-align: start;
16077      }
16078    "#,
16079      indoc! {r#"
16080      .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 {
16081        text-align: left;
16082      }
16083
16084      .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 {
16085        text-align: right;
16086      }
16087    "#
16088      },
16089      Browsers {
16090        safari: Some(2 << 16),
16091        ..Browsers::default()
16092      },
16093    );
16094
16095    prefix_test(
16096      r#"
16097      .foo:hover {
16098        text-align: start;
16099      }
16100    "#,
16101      indoc! {r#"
16102      .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))) {
16103        text-align: left;
16104      }
16105
16106      .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)) {
16107        text-align: right;
16108      }
16109    "#
16110      },
16111      Browsers {
16112        safari: Some(2 << 16),
16113        ..Browsers::default()
16114      },
16115    );
16116  }
16117
16118  #[test]
16119  fn test_text_align_last() {
16120    minify_test(".foo { text-align-last: left }", ".foo{text-align-last:left}");
16121    minify_test(".foo { text-align-last: justify }", ".foo{text-align-last:justify}");
16122    prefix_test(
16123      ".foo{ text-align-last: left }",
16124      indoc! {r#"
16125      .foo {
16126        -moz-text-align-last: left;
16127        text-align-last: left;
16128      }
16129      "#},
16130      Browsers {
16131        firefox: Some(40 << 16),
16132        ..Browsers::default()
16133      },
16134    );
16135    prefix_test(
16136      r#"
16137      .foo {
16138        -moz-text-align-last: left;
16139        text-align-last: left;
16140      }
16141      "#,
16142      indoc! {r#"
16143      .foo {
16144        text-align-last: left;
16145      }
16146      "#},
16147      Browsers {
16148        firefox: Some(88 << 16),
16149        ..Browsers::default()
16150      },
16151    );
16152  }
16153
16154  #[test]
16155  fn test_text_justify() {
16156    minify_test(".foo { text-justify: auto }", ".foo{text-justify:auto}");
16157    minify_test(".foo { text-justify: inter-word }", ".foo{text-justify:inter-word}");
16158  }
16159
16160  #[test]
16161  fn test_word_spacing() {
16162    minify_test(".foo { word-spacing: normal }", ".foo{word-spacing:normal}");
16163    minify_test(".foo { word-spacing: 3px }", ".foo{word-spacing:3px}");
16164  }
16165
16166  #[test]
16167  fn test_letter_spacing() {
16168    minify_test(".foo { letter-spacing: normal }", ".foo{letter-spacing:normal}");
16169    minify_test(".foo { letter-spacing: 3px }", ".foo{letter-spacing:3px}");
16170  }
16171
16172  #[test]
16173  fn test_text_indent() {
16174    minify_test(".foo { text-indent: 20px }", ".foo{text-indent:20px}");
16175    minify_test(".foo { text-indent: 10% }", ".foo{text-indent:10%}");
16176    minify_test(".foo { text-indent: 3em hanging }", ".foo{text-indent:3em hanging}");
16177    minify_test(".foo { text-indent: 3em each-line }", ".foo{text-indent:3em each-line}");
16178    minify_test(
16179      ".foo { text-indent: 3em hanging each-line }",
16180      ".foo{text-indent:3em hanging each-line}",
16181    );
16182    minify_test(
16183      ".foo { text-indent: 3em each-line hanging }",
16184      ".foo{text-indent:3em hanging each-line}",
16185    );
16186    minify_test(
16187      ".foo { text-indent: each-line 3em hanging }",
16188      ".foo{text-indent:3em hanging each-line}",
16189    );
16190    minify_test(
16191      ".foo { text-indent: each-line hanging 3em }",
16192      ".foo{text-indent:3em hanging each-line}",
16193    );
16194  }
16195
16196  #[test]
16197  fn test_text_size_adjust() {
16198    minify_test(".foo { text-size-adjust: none }", ".foo{text-size-adjust:none}");
16199    minify_test(".foo { text-size-adjust: auto }", ".foo{text-size-adjust:auto}");
16200    minify_test(".foo { text-size-adjust: 80% }", ".foo{text-size-adjust:80%}");
16201    prefix_test(
16202      r#"
16203      .foo {
16204        text-size-adjust: none;
16205      }
16206    "#,
16207      indoc! {r#"
16208      .foo {
16209        -webkit-text-size-adjust: none;
16210        -moz-text-size-adjust: none;
16211        -ms-text-size-adjust: none;
16212        text-size-adjust: none;
16213      }
16214    "#},
16215      Browsers {
16216        ios_saf: Some(16 << 16),
16217        edge: Some(15 << 16),
16218        firefox: Some(20 << 16),
16219        ..Browsers::default()
16220      },
16221    );
16222    prefix_test(
16223      r#"
16224      .foo {
16225        -webkit-text-size-adjust: none;
16226        -moz-text-size-adjust: none;
16227        -ms-text-size-adjust: none;
16228        text-size-adjust: none;
16229      }
16230    "#,
16231      indoc! {r#"
16232      .foo {
16233        text-size-adjust: none;
16234      }
16235    "#},
16236      Browsers {
16237        chrome: Some(110 << 16),
16238        ..Browsers::default()
16239      },
16240    );
16241  }
16242
16243  #[test]
16244  fn test_text_decoration() {
16245    minify_test(".foo { text-decoration-line: none }", ".foo{text-decoration-line:none}");
16246    minify_test(
16247      ".foo { text-decoration-line: underline }",
16248      ".foo{text-decoration-line:underline}",
16249    );
16250    minify_test(
16251      ".foo { text-decoration-line: overline }",
16252      ".foo{text-decoration-line:overline}",
16253    );
16254    minify_test(
16255      ".foo { text-decoration-line: line-through }",
16256      ".foo{text-decoration-line:line-through}",
16257    );
16258    minify_test(
16259      ".foo { text-decoration-line: blink }",
16260      ".foo{text-decoration-line:blink}",
16261    );
16262    minify_test(
16263      ".foo { text-decoration-line: underline overline }",
16264      ".foo{text-decoration-line:underline overline}",
16265    );
16266    minify_test(
16267      ".foo { text-decoration-line: overline underline }",
16268      ".foo{text-decoration-line:underline overline}",
16269    );
16270    minify_test(
16271      ".foo { text-decoration-line: overline line-through underline }",
16272      ".foo{text-decoration-line:underline overline line-through}",
16273    );
16274    minify_test(
16275      ".foo { text-decoration-line: spelling-error }",
16276      ".foo{text-decoration-line:spelling-error}",
16277    );
16278    minify_test(
16279      ".foo { text-decoration-line: grammar-error }",
16280      ".foo{text-decoration-line:grammar-error}",
16281    );
16282    minify_test(
16283      ".foo { -webkit-text-decoration-line: overline underline }",
16284      ".foo{-webkit-text-decoration-line:underline overline}",
16285    );
16286    minify_test(
16287      ".foo { -moz-text-decoration-line: overline underline }",
16288      ".foo{-moz-text-decoration-line:underline overline}",
16289    );
16290
16291    minify_test(
16292      ".foo { text-decoration-style: solid }",
16293      ".foo{text-decoration-style:solid}",
16294    );
16295    minify_test(
16296      ".foo { text-decoration-style: dotted }",
16297      ".foo{text-decoration-style:dotted}",
16298    );
16299    minify_test(
16300      ".foo { -webkit-text-decoration-style: solid }",
16301      ".foo{-webkit-text-decoration-style:solid}",
16302    );
16303
16304    minify_test(
16305      ".foo { text-decoration-color: yellow }",
16306      ".foo{text-decoration-color:#ff0}",
16307    );
16308    minify_test(
16309      ".foo { -webkit-text-decoration-color: yellow }",
16310      ".foo{-webkit-text-decoration-color:#ff0}",
16311    );
16312
16313    minify_test(".foo { text-decoration: none }", ".foo{text-decoration:none}");
16314    minify_test(
16315      ".foo { text-decoration: underline dotted }",
16316      ".foo{text-decoration:underline dotted}",
16317    );
16318    minify_test(
16319      ".foo { text-decoration: underline dotted yellow }",
16320      ".foo{text-decoration:underline dotted #ff0}",
16321    );
16322    minify_test(
16323      ".foo { text-decoration: yellow dotted underline }",
16324      ".foo{text-decoration:underline dotted #ff0}",
16325    );
16326    minify_test(
16327      ".foo { text-decoration: underline overline dotted yellow }",
16328      ".foo{text-decoration:underline overline dotted #ff0}",
16329    );
16330    minify_test(
16331      ".foo { -webkit-text-decoration: yellow dotted underline }",
16332      ".foo{-webkit-text-decoration:underline dotted #ff0}",
16333    );
16334    minify_test(
16335      ".foo { -moz-text-decoration: yellow dotted underline }",
16336      ".foo{-moz-text-decoration:underline dotted #ff0}",
16337    );
16338
16339    test(
16340      r#"
16341      .foo {
16342        text-decoration-line: underline;
16343        text-decoration-style: dotted;
16344        text-decoration-color: yellow;
16345        text-decoration-thickness: 2px;
16346      }
16347    "#,
16348      indoc! {r#"
16349      .foo {
16350        text-decoration: underline 2px dotted #ff0;
16351      }
16352    "#},
16353    );
16354
16355    test(
16356      r#"
16357      .foo {
16358        text-decoration: underline;
16359        text-decoration-style: dotted;
16360      }
16361    "#,
16362      indoc! {r#"
16363      .foo {
16364        text-decoration: underline dotted;
16365      }
16366    "#},
16367    );
16368
16369    test(
16370      r#"
16371      .foo {
16372        text-decoration: underline;
16373        text-decoration-style: var(--style);
16374      }
16375    "#,
16376      indoc! {r#"
16377      .foo {
16378        text-decoration: underline;
16379        text-decoration-style: var(--style);
16380      }
16381    "#},
16382    );
16383
16384    test(
16385      r#"
16386      .foo {
16387        -webkit-text-decoration: underline;
16388        -webkit-text-decoration-style: dotted;
16389      }
16390    "#,
16391      indoc! {r#"
16392      .foo {
16393        -webkit-text-decoration: underline dotted;
16394      }
16395    "#},
16396    );
16397
16398    prefix_test(
16399      r#"
16400      .foo {
16401        text-decoration: underline dotted;
16402      }
16403    "#,
16404      indoc! {r#"
16405      .foo {
16406        -webkit-text-decoration: underline dotted;
16407        text-decoration: underline dotted;
16408      }
16409    "#},
16410      Browsers {
16411        safari: Some(8 << 16),
16412        firefox: Some(30 << 16),
16413        ..Browsers::default()
16414      },
16415    );
16416
16417    prefix_test(
16418      r#"
16419      .foo {
16420        text-decoration-line: underline;
16421      }
16422    "#,
16423      indoc! {r#"
16424      .foo {
16425        -webkit-text-decoration-line: underline;
16426        -moz-text-decoration-line: underline;
16427        text-decoration-line: underline;
16428      }
16429    "#},
16430      Browsers {
16431        safari: Some(8 << 16),
16432        firefox: Some(30 << 16),
16433        ..Browsers::default()
16434      },
16435    );
16436
16437    prefix_test(
16438      r#"
16439      .foo {
16440        text-decoration-style: dotted;
16441      }
16442    "#,
16443      indoc! {r#"
16444      .foo {
16445        -webkit-text-decoration-style: dotted;
16446        -moz-text-decoration-style: dotted;
16447        text-decoration-style: dotted;
16448      }
16449    "#},
16450      Browsers {
16451        safari: Some(8 << 16),
16452        firefox: Some(30 << 16),
16453        ..Browsers::default()
16454      },
16455    );
16456
16457    prefix_test(
16458      r#"
16459      .foo {
16460        text-decoration-color: yellow;
16461      }
16462    "#,
16463      indoc! {r#"
16464      .foo {
16465        -webkit-text-decoration-color: #ff0;
16466        -moz-text-decoration-color: #ff0;
16467        text-decoration-color: #ff0;
16468      }
16469    "#},
16470      Browsers {
16471        safari: Some(8 << 16),
16472        firefox: Some(30 << 16),
16473        ..Browsers::default()
16474      },
16475    );
16476
16477    prefix_test(
16478      r#"
16479      .foo {
16480        text-decoration: underline;
16481      }
16482    "#,
16483      indoc! {r#"
16484      .foo {
16485        text-decoration: underline;
16486      }
16487    "#},
16488      Browsers {
16489        safari: Some(8 << 16),
16490        firefox: Some(30 << 16),
16491        ..Browsers::default()
16492      },
16493    );
16494
16495    prefix_test(
16496      r#"
16497      .foo {
16498        -webkit-text-decoration: underline dotted;
16499        text-decoration: underline dotted;
16500      }
16501    "#,
16502      indoc! {r#"
16503      .foo {
16504        -webkit-text-decoration: underline dotted;
16505        text-decoration: underline dotted;
16506      }
16507    "#},
16508      Browsers {
16509        safari: Some(14 << 16),
16510        firefox: Some(45 << 16),
16511        ..Browsers::default()
16512      },
16513    );
16514
16515    prefix_test(
16516      r#"
16517      .foo {
16518        text-decoration: double underline;
16519      }
16520    "#,
16521      indoc! {r#"
16522      .foo {
16523        -webkit-text-decoration: underline double;
16524        text-decoration: underline double;
16525      }
16526    "#},
16527      Browsers {
16528        safari: Some(16 << 16),
16529        ..Browsers::default()
16530      },
16531    );
16532
16533    prefix_test(
16534      r#"
16535      .foo {
16536        text-decoration: underline;
16537        text-decoration-style: double;
16538      }
16539    "#,
16540      indoc! {r#"
16541      .foo {
16542        -webkit-text-decoration: underline double;
16543        text-decoration: underline double;
16544      }
16545    "#},
16546      Browsers {
16547        safari: Some(16 << 16),
16548        ..Browsers::default()
16549      },
16550    );
16551
16552    prefix_test(
16553      r#"
16554      .foo {
16555        text-decoration: underline;
16556        text-decoration-color: red;
16557      }
16558    "#,
16559      indoc! {r#"
16560      .foo {
16561        -webkit-text-decoration: underline red;
16562        text-decoration: underline red;
16563      }
16564    "#},
16565      Browsers {
16566        safari: Some(16 << 16),
16567        ..Browsers::default()
16568      },
16569    );
16570
16571    prefix_test(
16572      r#"
16573      .foo {
16574        text-decoration: var(--test);
16575      }
16576    "#,
16577      indoc! {r#"
16578      .foo {
16579        -webkit-text-decoration: var(--test);
16580        text-decoration: var(--test);
16581      }
16582    "#},
16583      Browsers {
16584        safari: Some(8 << 16),
16585        firefox: Some(30 << 16),
16586        ..Browsers::default()
16587      },
16588    );
16589
16590    minify_test(
16591      ".foo { text-decoration-skip-ink: all }",
16592      ".foo{text-decoration-skip-ink:all}",
16593    );
16594    minify_test(
16595      ".foo { -webkit-text-decoration-skip-ink: all }",
16596      ".foo{-webkit-text-decoration-skip-ink:all}",
16597    );
16598
16599    prefix_test(
16600      r#"
16601      .foo {
16602        text-decoration: lch(50.998% 135.363 338) underline;
16603      }
16604    "#,
16605      indoc! {r#"
16606      .foo {
16607        -webkit-text-decoration: underline #ee00be;
16608        text-decoration: underline #ee00be;
16609        -webkit-text-decoration: underline lch(50.998% 135.363 338);
16610        text-decoration: underline lch(50.998% 135.363 338);
16611      }
16612    "#},
16613      Browsers {
16614        safari: Some(8 << 16),
16615        firefox: Some(30 << 16),
16616        ..Browsers::default()
16617      },
16618    );
16619
16620    prefix_test(
16621      r#"
16622      .foo {
16623        text-decoration-color: lch(50.998% 135.363 338);
16624      }
16625    "#,
16626      indoc! {r#"
16627      .foo {
16628        -webkit-text-decoration-color: #ee00be;
16629        -moz-text-decoration-color: #ee00be;
16630        text-decoration-color: #ee00be;
16631        -webkit-text-decoration-color: lch(50.998% 135.363 338);
16632        -moz-text-decoration-color: lch(50.998% 135.363 338);
16633        text-decoration-color: lch(50.998% 135.363 338);
16634      }
16635    "#},
16636      Browsers {
16637        safari: Some(8 << 16),
16638        firefox: Some(30 << 16),
16639        ..Browsers::default()
16640      },
16641    );
16642
16643    prefix_test(
16644      r#"
16645      .foo {
16646        text-decoration: lch(50.998% 135.363 338) var(--style);
16647      }
16648    "#,
16649      indoc! {r#"
16650      .foo {
16651        text-decoration: #ee00be var(--style);
16652      }
16653
16654      @supports (color: lab(0% 0 0)) {
16655        .foo {
16656          text-decoration: lab(50.998% 125.506 -50.7078) var(--style);
16657        }
16658      }
16659    "#},
16660      Browsers {
16661        chrome: Some(90 << 16),
16662        ..Browsers::default()
16663      },
16664    );
16665
16666    prefix_test(
16667      r#"
16668      @supports (color: lab(0% 0 0)) {
16669        .foo {
16670          text-decoration: lab(50.998% 125.506 -50.7078) var(--style);
16671        }
16672      }
16673    "#,
16674      indoc! {r#"
16675      @supports (color: lab(0% 0 0)) {
16676        .foo {
16677          text-decoration: lab(50.998% 125.506 -50.7078) var(--style);
16678        }
16679      }
16680    "#},
16681      Browsers {
16682        chrome: Some(90 << 16),
16683        ..Browsers::default()
16684      },
16685    );
16686
16687    prefix_test(
16688      r#"
16689      .foo {
16690        text-decoration: underline 10px;
16691      }
16692    "#,
16693      indoc! {r#"
16694      .foo {
16695        text-decoration: underline;
16696        text-decoration-thickness: 10px;
16697      }
16698    "#},
16699      Browsers {
16700        safari: Some(15 << 16),
16701        ..Browsers::default()
16702      },
16703    );
16704
16705    prefix_test(
16706      r#"
16707      .foo {
16708        text-decoration: underline 10px;
16709      }
16710    "#,
16711      indoc! {r#"
16712      .foo {
16713        text-decoration: underline 10px;
16714      }
16715    "#},
16716      Browsers {
16717        chrome: Some(90 << 16),
16718        ..Browsers::default()
16719      },
16720    );
16721
16722    prefix_test(
16723      r#"
16724      .foo {
16725        text-decoration: underline 10%;
16726      }
16727    "#,
16728      indoc! {r#"
16729      .foo {
16730        text-decoration: underline;
16731        text-decoration-thickness: calc(1em / 10);
16732      }
16733    "#},
16734      Browsers {
16735        safari: Some(12 << 16),
16736        ..Browsers::default()
16737      },
16738    );
16739
16740    prefix_test(
16741      r#"
16742      .foo {
16743        text-decoration: underline 10%;
16744      }
16745    "#,
16746      indoc! {r#"
16747      .foo {
16748        text-decoration: underline 10%;
16749      }
16750    "#},
16751      Browsers {
16752        firefox: Some(89 << 16),
16753        ..Browsers::default()
16754      },
16755    );
16756
16757    prefix_test(
16758      r#"
16759      .foo {
16760        text-decoration-thickness: 10%;
16761      }
16762    "#,
16763      indoc! {r#"
16764      .foo {
16765        text-decoration-thickness: calc(1em / 10);
16766      }
16767    "#},
16768      Browsers {
16769        safari: Some(12 << 16),
16770        ..Browsers::default()
16771      },
16772    );
16773
16774    prefix_test(
16775      r#"
16776      .foo {
16777        text-decoration-thickness: 10%;
16778      }
16779    "#,
16780      indoc! {r#"
16781      .foo {
16782        text-decoration-thickness: 10%;
16783      }
16784    "#},
16785      Browsers {
16786        firefox: Some(89 << 16),
16787        ..Browsers::default()
16788      },
16789    );
16790  }
16791
16792  #[test]
16793  fn test_text_emphasis() {
16794    minify_test(".foo { text-emphasis-style: none }", ".foo{text-emphasis-style:none}");
16795    minify_test(
16796      ".foo { text-emphasis-style: filled }",
16797      ".foo{text-emphasis-style:filled}",
16798    );
16799    minify_test(".foo { text-emphasis-style: open }", ".foo{text-emphasis-style:open}");
16800    minify_test(".foo { text-emphasis-style: dot }", ".foo{text-emphasis-style:dot}");
16801    minify_test(
16802      ".foo { text-emphasis-style: filled dot }",
16803      ".foo{text-emphasis-style:dot}",
16804    );
16805    minify_test(
16806      ".foo { text-emphasis-style: dot filled }",
16807      ".foo{text-emphasis-style:dot}",
16808    );
16809    minify_test(
16810      ".foo { text-emphasis-style: open dot }",
16811      ".foo{text-emphasis-style:open dot}",
16812    );
16813    minify_test(
16814      ".foo { text-emphasis-style: dot open }",
16815      ".foo{text-emphasis-style:open dot}",
16816    );
16817    minify_test(".foo { text-emphasis-style: \"x\" }", ".foo{text-emphasis-style:\"x\"}");
16818
16819    minify_test(".foo { text-emphasis-color: yellow }", ".foo{text-emphasis-color:#ff0}");
16820
16821    minify_test(".foo { text-emphasis: none }", ".foo{text-emphasis:none}");
16822    minify_test(".foo { text-emphasis: filled }", ".foo{text-emphasis:filled}");
16823    minify_test(
16824      ".foo { text-emphasis: filled yellow }",
16825      ".foo{text-emphasis:filled #ff0}",
16826    );
16827    minify_test(
16828      ".foo { text-emphasis: dot filled yellow }",
16829      ".foo{text-emphasis:dot #ff0}",
16830    );
16831
16832    test(
16833      r#"
16834      .foo {
16835        text-emphasis-style: filled;
16836        text-emphasis-color: yellow;
16837      }
16838    "#,
16839      indoc! {r#"
16840      .foo {
16841        text-emphasis: filled #ff0;
16842      }
16843    "#},
16844    );
16845
16846    test(
16847      r#"
16848      .foo {
16849        text-emphasis: filled red;
16850        text-emphasis-color: yellow;
16851      }
16852    "#,
16853      indoc! {r#"
16854      .foo {
16855        text-emphasis: filled #ff0;
16856      }
16857    "#},
16858    );
16859
16860    test(
16861      r#"
16862      .foo {
16863        text-emphasis: filled yellow;
16864        text-emphasis-color: var(--color);
16865      }
16866    "#,
16867      indoc! {r#"
16868      .foo {
16869        text-emphasis: filled #ff0;
16870        text-emphasis-color: var(--color);
16871      }
16872    "#},
16873    );
16874
16875    prefix_test(
16876      r#"
16877      .foo {
16878        text-emphasis-style: filled;
16879      }
16880    "#,
16881      indoc! {r#"
16882      .foo {
16883        -webkit-text-emphasis-style: filled;
16884        text-emphasis-style: filled;
16885      }
16886    "#},
16887      Browsers {
16888        safari: Some(10 << 16),
16889        chrome: Some(30 << 16),
16890        firefox: Some(45 << 16),
16891        ..Browsers::default()
16892      },
16893    );
16894
16895    prefix_test(
16896      r#"
16897      .foo {
16898        -webkit-text-emphasis-style: filled;
16899        text-emphasis-style: filled;
16900      }
16901    "#,
16902      indoc! {r#"
16903      .foo {
16904        text-emphasis-style: filled;
16905      }
16906    "#},
16907      Browsers {
16908        safari: Some(10 << 16),
16909        firefox: Some(45 << 16),
16910        ..Browsers::default()
16911      },
16912    );
16913
16914    minify_test(
16915      ".foo { text-emphasis-position: over }",
16916      ".foo{text-emphasis-position:over}",
16917    );
16918    minify_test(
16919      ".foo { text-emphasis-position: under }",
16920      ".foo{text-emphasis-position:under}",
16921    );
16922    minify_test(
16923      ".foo { text-emphasis-position: over right }",
16924      ".foo{text-emphasis-position:over}",
16925    );
16926    minify_test(
16927      ".foo { text-emphasis-position: over left }",
16928      ".foo{text-emphasis-position:over left}",
16929    );
16930
16931    prefix_test(
16932      r#"
16933      .foo {
16934        text-emphasis-position: over;
16935      }
16936    "#,
16937      indoc! {r#"
16938      .foo {
16939        -webkit-text-emphasis-position: over;
16940        text-emphasis-position: over;
16941      }
16942    "#},
16943      Browsers {
16944        safari: Some(10 << 16),
16945        chrome: Some(30 << 16),
16946        firefox: Some(45 << 16),
16947        ..Browsers::default()
16948      },
16949    );
16950
16951    prefix_test(
16952      r#"
16953      .foo {
16954        text-emphasis-position: over left;
16955      }
16956    "#,
16957      indoc! {r#"
16958      .foo {
16959        text-emphasis-position: over left;
16960      }
16961    "#},
16962      Browsers {
16963        safari: Some(10 << 16),
16964        chrome: Some(30 << 16),
16965        firefox: Some(45 << 16),
16966        ..Browsers::default()
16967      },
16968    );
16969
16970    prefix_test(
16971      r#"
16972      .foo {
16973        text-emphasis-position: var(--test);
16974      }
16975    "#,
16976      indoc! {r#"
16977      .foo {
16978        -webkit-text-emphasis-position: var(--test);
16979        text-emphasis-position: var(--test);
16980      }
16981    "#},
16982      Browsers {
16983        safari: Some(10 << 16),
16984        chrome: Some(30 << 16),
16985        firefox: Some(45 << 16),
16986        ..Browsers::default()
16987      },
16988    );
16989
16990    prefix_test(
16991      r#"
16992      .foo {
16993        text-emphasis: filled lch(50.998% 135.363 338);
16994      }
16995    "#,
16996      indoc! {r#"
16997      .foo {
16998        -webkit-text-emphasis: filled #ee00be;
16999        text-emphasis: filled #ee00be;
17000        -webkit-text-emphasis: filled lch(50.998% 135.363 338);
17001        text-emphasis: filled lch(50.998% 135.363 338);
17002      }
17003    "#},
17004      Browsers {
17005        chrome: Some(25 << 16),
17006        firefox: Some(48 << 16),
17007        ..Browsers::default()
17008      },
17009    );
17010
17011    prefix_test(
17012      r#"
17013      .foo {
17014        text-emphasis-color: lch(50.998% 135.363 338);
17015      }
17016    "#,
17017      indoc! {r#"
17018      .foo {
17019        -webkit-text-emphasis-color: #ee00be;
17020        text-emphasis-color: #ee00be;
17021        -webkit-text-emphasis-color: lch(50.998% 135.363 338);
17022        text-emphasis-color: lch(50.998% 135.363 338);
17023      }
17024    "#},
17025      Browsers {
17026        chrome: Some(25 << 16),
17027        firefox: Some(48 << 16),
17028        ..Browsers::default()
17029      },
17030    );
17031
17032    prefix_test(
17033      r#"
17034      .foo {
17035        text-emphasis: lch(50.998% 135.363 338) var(--style);
17036      }
17037    "#,
17038      indoc! {r#"
17039      .foo {
17040        text-emphasis: #ee00be var(--style);
17041      }
17042
17043      @supports (color: lab(0% 0 0)) {
17044        .foo {
17045          text-emphasis: lab(50.998% 125.506 -50.7078) var(--style);
17046        }
17047      }
17048    "#},
17049      Browsers {
17050        safari: Some(8 << 16),
17051        ..Browsers::default()
17052      },
17053    );
17054
17055    prefix_test(
17056      r#"
17057      @supports (color: lab(0% 0 0)) {
17058        .foo {
17059          text-emphasis: lab(50.998% 125.506 -50.7078) var(--style);
17060        }
17061      }
17062    "#,
17063      indoc! {r#"
17064      @supports (color: lab(0% 0 0)) {
17065        .foo {
17066          text-emphasis: lab(50.998% 125.506 -50.7078) var(--style);
17067        }
17068      }
17069    "#},
17070      Browsers {
17071        safari: Some(8 << 16),
17072        ..Browsers::default()
17073      },
17074    );
17075  }
17076
17077  #[test]
17078  fn test_text_shadow() {
17079    minify_test(
17080      ".foo { text-shadow: 1px 1px 2px yellow; }",
17081      ".foo{text-shadow:1px 1px 2px #ff0}",
17082    );
17083    minify_test(
17084      ".foo { text-shadow: 1px 1px 2px 3px yellow; }",
17085      ".foo{text-shadow:1px 1px 2px 3px #ff0}",
17086    );
17087    minify_test(
17088      ".foo { text-shadow: 1px 1px 0 yellow; }",
17089      ".foo{text-shadow:1px 1px #ff0}",
17090    );
17091    minify_test(
17092      ".foo { text-shadow: 1px 1px yellow; }",
17093      ".foo{text-shadow:1px 1px #ff0}",
17094    );
17095    minify_test(
17096      ".foo { text-shadow: 1px 1px yellow, 2px 3px red; }",
17097      ".foo{text-shadow:1px 1px #ff0,2px 3px red}",
17098    );
17099
17100    prefix_test(
17101      ".foo { text-shadow: 12px 12px lab(40% 56.6 39) }",
17102      indoc! { r#"
17103        .foo {
17104          text-shadow: 12px 12px #b32323;
17105          text-shadow: 12px 12px lab(40% 56.6 39);
17106        }
17107      "#},
17108      Browsers {
17109        chrome: Some(4 << 16),
17110        ..Browsers::default()
17111      },
17112    );
17113
17114    prefix_test(
17115      ".foo { text-shadow: 12px 12px lab(40% 56.6 39) }",
17116      indoc! { r#"
17117        .foo {
17118          text-shadow: 12px 12px #b32323;
17119          text-shadow: 12px 12px color(display-p3 .643308 .192455 .167712);
17120          text-shadow: 12px 12px lab(40% 56.6 39);
17121        }
17122      "#},
17123      Browsers {
17124        chrome: Some(90 << 16),
17125        safari: Some(14 << 16),
17126        ..Browsers::default()
17127      },
17128    );
17129
17130    prefix_test(
17131      ".foo { text-shadow: 12px 12px lab(40% 56.6 39), 12px 12px yellow }",
17132      indoc! { r#"
17133        .foo {
17134          text-shadow: 12px 12px #b32323, 12px 12px #ff0;
17135          text-shadow: 12px 12px lab(40% 56.6 39), 12px 12px #ff0;
17136        }
17137      "#},
17138      Browsers {
17139        chrome: Some(4 << 16),
17140        ..Browsers::default()
17141      },
17142    );
17143
17144    prefix_test(
17145      ".foo { text-shadow: var(--foo) 12px lab(40% 56.6 39) }",
17146      indoc! { r#"
17147        .foo {
17148          text-shadow: var(--foo) 12px #b32323;
17149        }
17150
17151        @supports (color: lab(0% 0 0)) {
17152          .foo {
17153            text-shadow: var(--foo) 12px lab(40% 56.6 39);
17154          }
17155        }
17156      "#},
17157      Browsers {
17158        chrome: Some(4 << 16),
17159        ..Browsers::default()
17160      },
17161    );
17162
17163    prefix_test(
17164      r#"
17165        @supports (color: lab(0% 0 0)) {
17166          .foo {
17167            text-shadow: var(--foo) 12px lab(40% 56.6 39);
17168          }
17169        }
17170      "#,
17171      indoc! { r#"
17172        @supports (color: lab(0% 0 0)) {
17173          .foo {
17174            text-shadow: var(--foo) 12px lab(40% 56.6 39);
17175          }
17176        }
17177      "#},
17178      Browsers {
17179        chrome: Some(4 << 16),
17180        ..Browsers::default()
17181      },
17182    );
17183  }
17184
17185  #[test]
17186  fn test_break() {
17187    prefix_test(
17188      r#"
17189      .foo {
17190        box-decoration-break: clone;
17191      }
17192    "#,
17193      indoc! {r#"
17194      .foo {
17195        -webkit-box-decoration-break: clone;
17196        box-decoration-break: clone;
17197      }
17198    "#},
17199      Browsers {
17200        safari: Some(15 << 16),
17201        ..Browsers::default()
17202      },
17203    );
17204
17205    prefix_test(
17206      r#"
17207      .foo {
17208        box-decoration-break: clone;
17209      }
17210    "#,
17211      indoc! {r#"
17212      .foo {
17213        box-decoration-break: clone;
17214      }
17215    "#},
17216      Browsers {
17217        firefox: Some(95 << 16),
17218        ..Browsers::default()
17219      },
17220    );
17221  }
17222
17223  #[test]
17224  fn test_position() {
17225    test(
17226      r#"
17227      .foo {
17228        position: relative;
17229        position: absolute;
17230      }
17231    "#,
17232      indoc! {r#"
17233      .foo {
17234        position: absolute;
17235      }
17236    "#},
17237    );
17238
17239    test(
17240      r#"
17241      .foo {
17242        position: -webkit-sticky;
17243        position: sticky;
17244      }
17245    "#,
17246      indoc! {r#"
17247      .foo {
17248        position: -webkit-sticky;
17249        position: sticky;
17250      }
17251    "#},
17252    );
17253
17254    prefix_test(
17255      r#"
17256      .foo {
17257        position: sticky;
17258      }
17259    "#,
17260      indoc! {r#"
17261      .foo {
17262        position: -webkit-sticky;
17263        position: sticky;
17264      }
17265    "#},
17266      Browsers {
17267        safari: Some(8 << 16),
17268        ..Browsers::default()
17269      },
17270    );
17271
17272    prefix_test(
17273      r#"
17274      .foo {
17275        position: -webkit-sticky;
17276        position: sticky;
17277      }
17278    "#,
17279      indoc! {r#"
17280      .foo {
17281        position: sticky;
17282      }
17283    "#},
17284      Browsers {
17285        safari: Some(13 << 16),
17286        ..Browsers::default()
17287      },
17288    );
17289
17290    test(
17291      r#"
17292      .foo {
17293        top: 0;
17294        left: 0;
17295        bottom: 0;
17296        right: 0;
17297      }
17298    "#,
17299      indoc! {r#"
17300      .foo {
17301        inset: 0;
17302      }
17303    "#},
17304    );
17305
17306    test(
17307      r#"
17308      .foo {
17309        top: 2px;
17310        left: 4px;
17311        bottom: 2px;
17312        right: 4px;
17313      }
17314    "#,
17315      indoc! {r#"
17316      .foo {
17317        inset: 2px 4px;
17318      }
17319    "#},
17320    );
17321
17322    test(
17323      r#"
17324      .foo {
17325        top: 1px;
17326        left: 2px;
17327        bottom: 3px;
17328        right: 4px;
17329      }
17330    "#,
17331      indoc! {r#"
17332      .foo {
17333        inset: 1px 4px 3px 2px;
17334      }
17335    "#},
17336    );
17337
17338    test(
17339      r#"
17340      .foo {
17341        inset-block-start: 2px;
17342        inset-block-end: 2px;
17343        inset-inline-start: 4px;
17344        inset-inline-end: 4px;
17345      }
17346    "#,
17347      indoc! {r#"
17348      .foo {
17349        inset-block: 2px;
17350        inset-inline: 4px;
17351      }
17352    "#},
17353    );
17354
17355    test(
17356      r#"
17357      .foo {
17358        inset-block-start: 2px;
17359        inset-block-end: 3px;
17360        inset-inline-start: 4px;
17361        inset-inline-end: 5px;
17362      }
17363    "#,
17364      indoc! {r#"
17365      .foo {
17366        inset-block: 2px 3px;
17367        inset-inline: 4px 5px;
17368      }
17369    "#},
17370    );
17371
17372    test(
17373      r#"
17374      .foo {
17375        inset-block-start: 2px;
17376        inset-block-end: 3px;
17377        inset: 4px;
17378        inset-inline-start: 4px;
17379        inset-inline-end: 5px;
17380      }
17381    "#,
17382      indoc! {r#"
17383      .foo {
17384        inset: 4px;
17385        inset-inline: 4px 5px;
17386      }
17387    "#},
17388    );
17389
17390    prefix_test(
17391      r#"
17392      .foo {
17393        inset-inline-start: 2px;
17394      }
17395    "#,
17396      indoc! {r#"
17397      .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))) {
17398        left: 2px;
17399      }
17400
17401      .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))) {
17402        left: 2px;
17403      }
17404
17405      .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)) {
17406        right: 2px;
17407      }
17408
17409      .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)) {
17410        right: 2px;
17411      }
17412    "#
17413      },
17414      Browsers {
17415        safari: Some(8 << 16),
17416        ..Browsers::default()
17417      },
17418    );
17419
17420    prefix_test(
17421      r#"
17422      .foo {
17423        inset-inline-start: 2px;
17424        inset-inline-end: 4px;
17425      }
17426    "#,
17427      indoc! {r#"
17428      .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))) {
17429        left: 2px;
17430        right: 4px;
17431      }
17432
17433      .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))) {
17434        left: 2px;
17435        right: 4px;
17436      }
17437
17438      .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)) {
17439        left: 4px;
17440        right: 2px;
17441      }
17442
17443      .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)) {
17444        left: 4px;
17445        right: 2px;
17446      }
17447    "#
17448      },
17449      Browsers {
17450        safari: Some(8 << 16),
17451        ..Browsers::default()
17452      },
17453    );
17454
17455    prefix_test(
17456      r#"
17457      .foo {
17458        inset-inline: 2px;
17459      }
17460    "#,
17461      indoc! {r#"
17462      .foo {
17463        left: 2px;
17464        right: 2px;
17465      }
17466    "#
17467      },
17468      Browsers {
17469        safari: Some(8 << 16),
17470        ..Browsers::default()
17471      },
17472    );
17473
17474    prefix_test(
17475      r#"
17476      .foo {
17477        inset-block-start: 2px;
17478      }
17479    "#,
17480      indoc! {r#"
17481      .foo {
17482        top: 2px;
17483      }
17484    "#
17485      },
17486      Browsers {
17487        safari: Some(8 << 16),
17488        ..Browsers::default()
17489      },
17490    );
17491
17492    prefix_test(
17493      r#"
17494      .foo {
17495        inset-block-end: 2px;
17496      }
17497    "#,
17498      indoc! {r#"
17499      .foo {
17500        bottom: 2px;
17501      }
17502    "#
17503      },
17504      Browsers {
17505        safari: Some(8 << 16),
17506        ..Browsers::default()
17507      },
17508    );
17509
17510    prefix_test(
17511      r#"
17512      .foo {
17513        top: 1px;
17514        left: 2px;
17515        bottom: 3px;
17516        right: 4px;
17517      }
17518    "#,
17519      indoc! {r#"
17520      .foo {
17521        top: 1px;
17522        bottom: 3px;
17523        left: 2px;
17524        right: 4px;
17525      }
17526    "#},
17527      Browsers {
17528        safari: Some(8 << 16),
17529        ..Browsers::default()
17530      },
17531    );
17532  }
17533
17534  #[test]
17535  fn test_overflow() {
17536    minify_test(".foo { overflow: hidden }", ".foo{overflow:hidden}");
17537    minify_test(".foo { overflow: hidden hidden }", ".foo{overflow:hidden}");
17538    minify_test(".foo { overflow: hidden auto }", ".foo{overflow:hidden auto}");
17539
17540    test(
17541      r#"
17542      .foo {
17543        overflow-x: hidden;
17544        overflow-y: auto;
17545      }
17546    "#,
17547      indoc! {r#"
17548      .foo {
17549        overflow: hidden auto;
17550      }
17551    "#},
17552    );
17553
17554    test(
17555      r#"
17556      .foo {
17557        overflow: hidden;
17558        overflow-y: auto;
17559      }
17560    "#,
17561      indoc! {r#"
17562      .foo {
17563        overflow: hidden auto;
17564      }
17565    "#},
17566    );
17567    test(
17568      r#"
17569      .foo {
17570        overflow: hidden;
17571        overflow-y: var(--y);
17572      }
17573    "#,
17574      indoc! {r#"
17575      .foo {
17576        overflow: hidden;
17577        overflow-y: var(--y);
17578      }
17579    "#},
17580    );
17581    prefix_test(
17582      r#"
17583      .foo {
17584        overflow: hidden auto;
17585      }
17586    "#,
17587      indoc! {r#"
17588      .foo {
17589        overflow-x: hidden;
17590        overflow-y: auto;
17591      }
17592    "#},
17593      Browsers {
17594        chrome: Some(67 << 16),
17595        ..Browsers::default()
17596      },
17597    );
17598    prefix_test(
17599      r#"
17600      .foo {
17601        overflow: hidden hidden;
17602      }
17603    "#,
17604      indoc! {r#"
17605      .foo {
17606        overflow: hidden;
17607      }
17608    "#},
17609      Browsers {
17610        chrome: Some(67 << 16),
17611        ..Browsers::default()
17612      },
17613    );
17614    prefix_test(
17615      r#"
17616      .foo {
17617        overflow: hidden auto;
17618      }
17619    "#,
17620      indoc! {r#"
17621      .foo {
17622        overflow: hidden auto;
17623      }
17624    "#},
17625      Browsers {
17626        chrome: Some(68 << 16),
17627        ..Browsers::default()
17628      },
17629    );
17630
17631    minify_test(".foo { text-overflow: ellipsis }", ".foo{text-overflow:ellipsis}");
17632    prefix_test(
17633      r#"
17634      .foo {
17635        text-overflow: ellipsis;
17636      }
17637    "#,
17638      indoc! {r#"
17639      .foo {
17640        -o-text-overflow: ellipsis;
17641        text-overflow: ellipsis;
17642      }
17643    "#},
17644      Browsers {
17645        safari: Some(4 << 16),
17646        opera: Some(10 << 16),
17647        ..Browsers::default()
17648      },
17649    );
17650
17651    prefix_test(
17652      r#"
17653      .foo {
17654        -o-text-overflow: ellipsis;
17655        text-overflow: ellipsis;
17656      }
17657    "#,
17658      indoc! {r#"
17659      .foo {
17660        text-overflow: ellipsis;
17661      }
17662    "#},
17663      Browsers {
17664        safari: Some(4 << 16),
17665        opera: Some(14 << 16),
17666        ..Browsers::default()
17667      },
17668    );
17669  }
17670
17671  #[test]
17672  fn test_ui() {
17673    minify_test(".foo { resize: both }", ".foo{resize:both}");
17674    minify_test(".foo { resize: Horizontal }", ".foo{resize:horizontal}");
17675    minify_test(".foo { cursor: ew-resize }", ".foo{cursor:ew-resize}");
17676    minify_test(
17677      ".foo { cursor: url(\"test.cur\"), ew-resize }",
17678      ".foo{cursor:url(test.cur),ew-resize}",
17679    );
17680    minify_test(
17681      ".foo { cursor: url(\"test.cur\"), url(\"foo.cur\"), ew-resize }",
17682      ".foo{cursor:url(test.cur),url(foo.cur),ew-resize}",
17683    );
17684    minify_test(".foo { caret-color: auto }", ".foo{caret-color:auto}");
17685    minify_test(".foo { caret-color: yellow }", ".foo{caret-color:#ff0}");
17686    minify_test(".foo { caret-shape: block }", ".foo{caret-shape:block}");
17687    minify_test(".foo { caret: yellow block }", ".foo{caret:#ff0 block}");
17688    minify_test(".foo { caret: block yellow }", ".foo{caret:#ff0 block}");
17689    minify_test(".foo { caret: block }", ".foo{caret:block}");
17690    minify_test(".foo { caret: yellow }", ".foo{caret:#ff0}");
17691    minify_test(".foo { caret: auto auto }", ".foo{caret:auto}");
17692    minify_test(".foo { caret: auto }", ".foo{caret:auto}");
17693    minify_test(".foo { caret: yellow auto }", ".foo{caret:#ff0}");
17694    minify_test(".foo { caret: auto block }", ".foo{caret:block}");
17695    minify_test(".foo { user-select: none }", ".foo{user-select:none}");
17696    minify_test(".foo { -webkit-user-select: none }", ".foo{-webkit-user-select:none}");
17697    minify_test(".foo { accent-color: auto }", ".foo{accent-color:auto}");
17698    minify_test(".foo { accent-color: yellow }", ".foo{accent-color:#ff0}");
17699    minify_test(".foo { appearance: None }", ".foo{appearance:none}");
17700    minify_test(
17701      ".foo { -webkit-appearance: textfield }",
17702      ".foo{-webkit-appearance:textfield}",
17703    );
17704
17705    prefix_test(
17706      r#"
17707      .foo {
17708        user-select: none;
17709      }
17710    "#,
17711      indoc! {r#"
17712      .foo {
17713        -webkit-user-select: none;
17714        -moz-user-select: none;
17715        -ms-user-select: none;
17716        user-select: none;
17717      }
17718    "#},
17719      Browsers {
17720        safari: Some(8 << 16),
17721        opera: Some(5 << 16),
17722        firefox: Some(10 << 16),
17723        ie: Some(10 << 16),
17724        ..Browsers::default()
17725      },
17726    );
17727
17728    prefix_test(
17729      r#"
17730      .foo {
17731        -webkit-user-select: none;
17732        -moz-user-select: none;
17733        -ms-user-select: none;
17734        user-select: none;
17735      }
17736    "#,
17737      indoc! {r#"
17738      .foo {
17739        -webkit-user-select: none;
17740        user-select: none;
17741      }
17742    "#},
17743      Browsers {
17744        safari: Some(8 << 16),
17745        opera: Some(80 << 16),
17746        firefox: Some(80 << 16),
17747        edge: Some(80 << 16),
17748        ..Browsers::default()
17749      },
17750    );
17751
17752    prefix_test(
17753      r#"
17754      .foo {
17755        -webkit-user-select: none;
17756        -moz-user-select: none;
17757        -ms-user-select: none;
17758        user-select: none;
17759      }
17760    "#,
17761      indoc! {r#"
17762      .foo {
17763        user-select: none;
17764      }
17765    "#},
17766      Browsers {
17767        opera: Some(80 << 16),
17768        firefox: Some(80 << 16),
17769        edge: Some(80 << 16),
17770        ..Browsers::default()
17771      },
17772    );
17773
17774    prefix_test(
17775      r#"
17776      .foo {
17777        appearance: none;
17778      }
17779    "#,
17780      indoc! {r#"
17781      .foo {
17782        -webkit-appearance: none;
17783        -moz-appearance: none;
17784        -ms-appearance: none;
17785        appearance: none;
17786      }
17787    "#},
17788      Browsers {
17789        safari: Some(8 << 16),
17790        chrome: Some(80 << 16),
17791        firefox: Some(10 << 16),
17792        ie: Some(11 << 16),
17793        ..Browsers::default()
17794      },
17795    );
17796
17797    prefix_test(
17798      r#"
17799      .foo {
17800        -webkit-appearance: none;
17801        -moz-appearance: none;
17802        -ms-appearance: none;
17803        appearance: none;
17804      }
17805    "#,
17806      indoc! {r#"
17807      .foo {
17808        -webkit-appearance: none;
17809        appearance: none;
17810      }
17811    "#},
17812      Browsers {
17813        safari: Some(15 << 16),
17814        chrome: Some(85 << 16),
17815        firefox: Some(80 << 16),
17816        edge: Some(85 << 16),
17817        ..Browsers::default()
17818      },
17819    );
17820
17821    prefix_test(
17822      r#"
17823      .foo {
17824        -webkit-appearance: none;
17825        -moz-appearance: none;
17826        -ms-appearance: none;
17827        appearance: none;
17828      }
17829    "#,
17830      indoc! {r#"
17831      .foo {
17832        appearance: none;
17833      }
17834    "#},
17835      Browsers {
17836        chrome: Some(85 << 16),
17837        firefox: Some(80 << 16),
17838        edge: Some(85 << 16),
17839        ..Browsers::default()
17840      },
17841    );
17842
17843    prefix_test(
17844      ".foo { caret-color: lch(50.998% 135.363 338) }",
17845      indoc! { r#"
17846        .foo {
17847          caret-color: #ee00be;
17848          caret-color: color(display-p3 .972962 -.362078 .804206);
17849          caret-color: lch(50.998% 135.363 338);
17850        }
17851      "#},
17852      Browsers {
17853        chrome: Some(90 << 16),
17854        safari: Some(14 << 16),
17855        ..Browsers::default()
17856      },
17857    );
17858
17859    prefix_test(
17860      ".foo { caret: lch(50.998% 135.363 338) block }",
17861      indoc! { r#"
17862        .foo {
17863          caret: #ee00be block;
17864          caret: color(display-p3 .972962 -.362078 .804206) block;
17865          caret: lch(50.998% 135.363 338) block;
17866        }
17867      "#},
17868      Browsers {
17869        chrome: Some(90 << 16),
17870        safari: Some(14 << 16),
17871        ..Browsers::default()
17872      },
17873    );
17874
17875    prefix_test(
17876      ".foo { caret: lch(50.998% 135.363 338) var(--foo) }",
17877      indoc! { r#"
17878        .foo {
17879          caret: #ee00be var(--foo);
17880        }
17881
17882        @supports (color: lab(0% 0 0)) {
17883          .foo {
17884            caret: lab(50.998% 125.506 -50.7078) var(--foo);
17885          }
17886        }
17887      "#},
17888      Browsers {
17889        chrome: Some(90 << 16),
17890        ..Browsers::default()
17891      },
17892    );
17893
17894    prefix_test(
17895      r#"
17896        @supports (color: lab(0% 0 0)) {
17897          .foo {
17898            caret: lab(50.998% 125.506 -50.7078) var(--foo);
17899          }
17900        }
17901      "#,
17902      indoc! { r#"
17903        @supports (color: lab(0% 0 0)) {
17904          .foo {
17905            caret: lab(50.998% 125.506 -50.7078) var(--foo);
17906          }
17907        }
17908      "#},
17909      Browsers {
17910        chrome: Some(90 << 16),
17911        ..Browsers::default()
17912      },
17913    );
17914  }
17915
17916  #[test]
17917  fn test_list() {
17918    minify_test(".foo { list-style-type: disc; }", ".foo{list-style-type:disc}");
17919    minify_test(".foo { list-style-type: \"★\"; }", ".foo{list-style-type:\"★\"}");
17920    minify_test(
17921      ".foo { list-style-type: symbols(cyclic '○' '●'); }",
17922      ".foo{list-style-type:symbols(cyclic \"○\" \"●\")}",
17923    );
17924    minify_test(
17925      ".foo { list-style-type: symbols('○' '●'); }",
17926      ".foo{list-style-type:symbols(\"○\" \"●\")}",
17927    );
17928    minify_test(
17929      ".foo { list-style-type: symbols(symbolic '○' '●'); }",
17930      ".foo{list-style-type:symbols(\"○\" \"●\")}",
17931    );
17932    minify_test(
17933      ".foo { list-style-type: symbols(symbolic url('ellipse.png')); }",
17934      ".foo{list-style-type:symbols(url(ellipse.png))}",
17935    );
17936    minify_test(
17937      ".foo { list-style-image: url('ellipse.png'); }",
17938      ".foo{list-style-image:url(ellipse.png)}",
17939    );
17940    minify_test(
17941      ".foo { list-style-position: outside; }",
17942      ".foo{list-style-position:outside}",
17943    );
17944    minify_test(
17945      ".foo { list-style: \"★\" url(ellipse.png) outside; }",
17946      ".foo{list-style:url(ellipse.png) \"★\"}",
17947    );
17948    minify_test(".foo { list-style: none; }", ".foo{list-style:none}");
17949    minify_test(".foo { list-style: none none outside; }", ".foo{list-style:none}");
17950    minify_test(".foo { list-style: none none inside; }", ".foo{list-style:inside none}");
17951    minify_test(".foo { list-style: none inside; }", ".foo{list-style:inside none}");
17952    minify_test(".foo { list-style: none disc; }", ".foo{list-style:outside}");
17953    minify_test(".foo { list-style: none inside disc; }", ".foo{list-style:inside}");
17954    minify_test(".foo { list-style: none \"★\"; }", ".foo{list-style:\"★\"}");
17955    minify_test(
17956      ".foo { list-style: none url(foo.png); }",
17957      ".foo{list-style:url(foo.png) none}",
17958    );
17959
17960    test(
17961      r#"
17962      .foo {
17963        list-style-type: disc;
17964        list-style-image: url(ellipse.png);
17965        list-style-position: outside;
17966      }
17967    "#,
17968      indoc! {r#"
17969      .foo {
17970        list-style: url("ellipse.png");
17971      }
17972    "#},
17973    );
17974
17975    test(
17976      r#"
17977      .foo {
17978        list-style: \"★\" url(ellipse.png) outside;
17979        list-style-image: none;
17980      }
17981    "#,
17982      indoc! {r#"
17983      .foo {
17984        list-style: \"★\";
17985      }
17986    "#},
17987    );
17988
17989    test(
17990      r#"
17991      .foo {
17992        list-style: \"★\" url(ellipse.png) outside;
17993        list-style-image: var(--img);
17994      }
17995    "#,
17996      indoc! {r#"
17997      .foo {
17998        list-style: url("ellipse.png") \"★\";
17999        list-style-image: var(--img);
18000      }
18001    "#},
18002    );
18003
18004    prefix_test(
18005      ".foo { list-style-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
18006      indoc! { r#"
18007        .foo {
18008          list-style-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ff0f0e), to(#7773ff));
18009          list-style-image: -webkit-linear-gradient(top, #ff0f0e, #7773ff);
18010          list-style-image: linear-gradient(#ff0f0e, #7773ff);
18011          list-style-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
18012        }
18013      "#},
18014      Browsers {
18015        chrome: Some(8 << 16),
18016        ..Browsers::default()
18017      },
18018    );
18019
18020    prefix_test(
18021      ".foo { list-style: \"★\" linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
18022      indoc! { r#"
18023        .foo {
18024          list-style: linear-gradient(#ff0f0e, #7773ff) "★";
18025          list-style: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) "★";
18026        }
18027      "#},
18028      Browsers {
18029        chrome: Some(90 << 16),
18030        ..Browsers::default()
18031      },
18032    );
18033
18034    prefix_test(
18035      ".foo { list-style: var(--foo) linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
18036      indoc! { r#"
18037        .foo {
18038          list-style: var(--foo) linear-gradient(#ff0f0e, #7773ff);
18039        }
18040
18041        @supports (color: lab(0% 0 0)) {
18042          .foo {
18043            list-style: var(--foo) linear-gradient(lab(56.208% 94.4644 98.8928), lab(51% 70.4544 -115.586));
18044          }
18045        }
18046      "#},
18047      Browsers {
18048        chrome: Some(90 << 16),
18049        ..Browsers::default()
18050      },
18051    );
18052
18053    prefix_test(
18054      r#"
18055        @supports (color: lab(0% 0 0)) {
18056          .foo {
18057            list-style: var(--foo) linear-gradient(lab(56.208% 94.4644 98.8928), lab(51% 70.4544 -115.586));
18058          }
18059        }
18060      "#,
18061      indoc! { r#"
18062        @supports (color: lab(0% 0 0)) {
18063          .foo {
18064            list-style: var(--foo) linear-gradient(lab(56.208% 94.4644 98.8928), lab(51% 70.4544 -115.586));
18065          }
18066        }
18067      "#},
18068      Browsers {
18069        chrome: Some(90 << 16),
18070        ..Browsers::default()
18071      },
18072    );
18073
18074    test(
18075      r#"
18076      .foo {
18077        list-style: inside;
18078        list-style-type: disc;
18079      }
18080    "#,
18081      indoc! {r#"
18082      .foo {
18083        list-style: inside;
18084      }
18085    "#},
18086    );
18087    test(
18088      r#"
18089      .foo {
18090        list-style: inside;
18091        list-style-type: decimal;
18092      }
18093    "#,
18094      indoc! {r#"
18095      .foo {
18096        list-style: inside decimal;
18097      }
18098    "#},
18099    );
18100  }
18101
18102  #[test]
18103  fn test_image_set() {
18104    // Spec: https://drafts.csswg.org/css-images-4/#image-set-notation
18105    // WPT: https://github.com/web-platform-tests/wpt/blob/master/css/css-images/image-set/image-set-parsing.html
18106    // test image-set(<string>)
18107    minify_test(
18108      ".foo { background: image-set(\"foo.png\" 2x, url(bar.png) 1x) }",
18109      ".foo{background:image-set(\"foo.png\" 2x,\"bar.png\" 1x)}",
18110    );
18111
18112    // test image-set(type(<string>))
18113    minify_test(
18114      ".foo { background: image-set('foo.webp' type('webp'), url(foo.jpg)) }",
18115      ".foo{background:image-set(\"foo.webp\" 1x type(\"webp\"),\"foo.jpg\" 1x)}",
18116    );
18117    minify_test(
18118      ".foo { background: image-set('foo.avif' 2x type('image/avif'), url(foo.png)) }",
18119      ".foo{background:image-set(\"foo.avif\" 2x type(\"image/avif\"),\"foo.png\" 1x)}",
18120    );
18121    minify_test(
18122      ".foo { background: image-set(url('example.png') 3x type('image/png')) }",
18123      ".foo{background:image-set(\"example.png\" 3x type(\"image/png\"))}",
18124    );
18125
18126    minify_test(
18127      ".foo { background: image-set(url(example.png) type('image/png') 1x) }",
18128      ".foo{background:image-set(\"example.png\" 1x type(\"image/png\"))}",
18129    );
18130
18131    minify_test(
18132      ".foo { background: -webkit-image-set(url(\"foo.png\") 2x, url(bar.png) 1x) }",
18133      ".foo{background:-webkit-image-set(url(foo.png) 2x,url(bar.png) 1x)}",
18134    );
18135
18136    test(
18137      r#"
18138      .foo {
18139        background: -webkit-image-set(url("foo.png") 2x, url(bar.png) 1x);
18140        background: image-set(url("foo.png") 2x, url(bar.png) 1x);
18141      }
18142    "#,
18143      indoc! {r#"
18144      .foo {
18145        background: -webkit-image-set(url("foo.png") 2x, url("bar.png") 1x);
18146        background: image-set("foo.png" 2x, "bar.png" 1x);
18147      }
18148    "#},
18149    );
18150
18151    // test image-set(<gradient>)
18152    test(
18153      r#"
18154      .foo {
18155        background: image-set(linear-gradient(cornflowerblue, white) 1x, url("detailed-gradient.png") 3x);
18156      }
18157    "#,
18158      indoc! {r#"
18159      .foo {
18160        background: image-set(linear-gradient(#6495ed, #fff) 1x, "detailed-gradient.png" 3x);
18161      }
18162    "#},
18163    );
18164
18165    prefix_test(
18166      r#"
18167      .foo {
18168        background: image-set(url("foo.png") 2x, url(bar.png) 1x);
18169      }
18170    "#,
18171      indoc! {r#"
18172      .foo {
18173        background: -webkit-image-set(url("foo.png") 2x, url("bar.png") 1x);
18174        background: image-set("foo.png" 2x, "bar.png" 1x);
18175      }
18176    "#},
18177      Browsers {
18178        chrome: Some(85 << 16),
18179        firefox: Some(80 << 16),
18180        ..Browsers::default()
18181      },
18182    );
18183
18184    prefix_test(
18185      r#"
18186      .foo {
18187        background: -webkit-image-set(url("foo.png") 2x, url(bar.png) 1x);
18188        background: image-set(url("foo.png") 2x, url(bar.png) 1x);
18189      }
18190    "#,
18191      indoc! {r#"
18192      .foo {
18193        background: -webkit-image-set(url("foo.png") 2x, url("bar.png") 1x);
18194        background: image-set("foo.png" 2x, "bar.png" 1x);
18195      }
18196    "#},
18197      Browsers {
18198        firefox: Some(80 << 16),
18199        ..Browsers::default()
18200      },
18201    );
18202
18203    prefix_test(
18204      r#"
18205      .foo {
18206        background: -webkit-image-set(url("foo.png") 2x, url(bar.png) 1x);
18207      }
18208    "#,
18209      indoc! {r#"
18210      .foo {
18211        background: -webkit-image-set(url("foo.png") 2x, url("bar.png") 1x);
18212      }
18213    "#},
18214      Browsers {
18215        chrome: Some(95 << 16),
18216        ..Browsers::default()
18217      },
18218    );
18219
18220    for property in &[
18221      "background",
18222      "background-image",
18223      "border-image-source",
18224      "border-image",
18225      "border-image-source",
18226      "-webkit-mask-image",
18227      "-webkit-mask",
18228      "list-style-image",
18229      "list-style",
18230    ] {
18231      prefix_test(
18232        &format!(
18233          r#"
18234        .foo {{
18235          {}: url(foo.png);
18236          {}: image-set(url("foo.png") 2x, url(bar.png) 1x);
18237        }}
18238      "#,
18239          property, property
18240        ),
18241        &format!(
18242          indoc! {r#"
18243        .foo {{
18244          {}: url("foo.png");
18245          {}: image-set("foo.png" 2x, "bar.png" 1x);
18246        }}
18247      "#},
18248          property, property
18249        ),
18250        Browsers {
18251          ie: Some(11 << 16),
18252          chrome: Some(95 << 16),
18253          ..Browsers::default()
18254        },
18255      );
18256
18257      prefix_test(
18258        &format!(
18259          r#"
18260        .foo {{
18261          {}: url(foo.png);
18262          {}: image-set(url("foo.png") 2x, url(bar.png) 1x);
18263        }}
18264      "#,
18265          property, property
18266        ),
18267        &format!(
18268          indoc! {r#"
18269        .foo {{
18270          {}: -webkit-image-set(url("foo.png") 2x, url("bar.png") 1x);
18271          {}: image-set("foo.png" 2x, "bar.png" 1x);
18272        }}
18273      "#},
18274          property, property
18275        ),
18276        Browsers {
18277          chrome: Some(95 << 16),
18278          ..Browsers::default()
18279        },
18280      );
18281    }
18282  }
18283
18284  #[test]
18285  fn test_color() {
18286    minify_test(".foo { color: yellow }", ".foo{color:#ff0}");
18287    minify_test(".foo { color: rgb(255, 255, 0) }", ".foo{color:#ff0}");
18288    minify_test(".foo { color: rgba(255, 255, 0, 1) }", ".foo{color:#ff0}");
18289    minify_test(".foo { color: rgba(255, 255, 0, 0.8) }", ".foo{color:#ff0c}");
18290    minify_test(".foo { color: rgb(128, 128, 128) }", ".foo{color:gray}");
18291    minify_test(".foo { color: rgb(123, 255, 255) }", ".foo{color:#7bffff}");
18292    minify_test(".foo { color: rgba(123, 255, 255, 0.5) }", ".foo{color:#7bffff80}");
18293    minify_test(".foo { color: rgb(123 255 255) }", ".foo{color:#7bffff}");
18294    minify_test(".foo { color: rgb(123 255 255 / .5) }", ".foo{color:#7bffff80}");
18295    minify_test(".foo { color: rgb(123 255 255 / 50%) }", ".foo{color:#7bffff80}");
18296    minify_test(".foo { color: rgb(48% 100% 100% / 50%) }", ".foo{color:#7affff80}");
18297    minify_test(".foo { color: hsl(100deg, 100%, 50%) }", ".foo{color:#5f0}");
18298    minify_test(".foo { color: hsl(100, 100%, 50%) }", ".foo{color:#5f0}");
18299    minify_test(".foo { color: hsl(100 100% 50%) }", ".foo{color:#5f0}");
18300    minify_test(".foo { color: hsl(100 100 50) }", ".foo{color:#5f0}");
18301    minify_test(".foo { color: hsl(100, 100%, 50%, .8) }", ".foo{color:#5f0c}");
18302    minify_test(".foo { color: hsl(100 100% 50% / .8) }", ".foo{color:#5f0c}");
18303    minify_test(".foo { color: hsla(100, 100%, 50%, .8) }", ".foo{color:#5f0c}");
18304    minify_test(".foo { color: hsla(100 100% 50% / .8) }", ".foo{color:#5f0c}");
18305    minify_test(".foo { color: transparent }", ".foo{color:#0000}");
18306    minify_test(".foo { color: currentColor }", ".foo{color:currentColor}");
18307    minify_test(".foo { color: ButtonBorder }", ".foo{color:buttonborder}");
18308    minify_test(".foo { color: hwb(194 0% 0%) }", ".foo{color:#00c4ff}");
18309    minify_test(".foo { color: hwb(194 0% 0% / 50%) }", ".foo{color:#00c4ff80}");
18310    minify_test(".foo { color: hwb(194 0% 50%) }", ".foo{color:#006280}");
18311    minify_test(".foo { color: hwb(194 50% 0%) }", ".foo{color:#80e1ff}");
18312    minify_test(".foo { color: hwb(194 50 0) }", ".foo{color:#80e1ff}");
18313    minify_test(".foo { color: hwb(194 50% 50%) }", ".foo{color:gray}");
18314    minify_test(".foo { color: light-dark(#FFF, #FFF) }", ".foo{color:#fff}");
18315    // minify_test(".foo { color: ActiveText }", ".foo{color:ActiveTet}");
18316    minify_test(
18317      ".foo { color: lab(29.2345% 39.3825 20.0664); }",
18318      ".foo{color:lab(29.2345% 39.3825 20.0664)}",
18319    );
18320    minify_test(
18321      ".foo { color: lab(29.2345 39.3825 20.0664); }",
18322      ".foo{color:lab(29.2345% 39.3825 20.0664)}",
18323    );
18324    minify_test(
18325      ".foo { color: lab(29.2345% 39.3825% 20.0664%); }",
18326      ".foo{color:lab(29.2345% 49.2281 25.083)}",
18327    );
18328    minify_test(
18329      ".foo { color: lab(29.2345% 39.3825 20.0664 / 100%); }",
18330      ".foo{color:lab(29.2345% 39.3825 20.0664)}",
18331    );
18332    minify_test(
18333      ".foo { color: lab(29.2345% 39.3825 20.0664 / 50%); }",
18334      ".foo{color:lab(29.2345% 39.3825 20.0664/.5)}",
18335    );
18336    minify_test(
18337      ".foo { color: lch(29.2345% 44.2 27); }",
18338      ".foo{color:lch(29.2345% 44.2 27)}",
18339    );
18340    minify_test(
18341      ".foo { color: lch(29.2345 44.2 27); }",
18342      ".foo{color:lch(29.2345% 44.2 27)}",
18343    );
18344    minify_test(
18345      ".foo { color: lch(29.2345% 44.2% 27deg); }",
18346      ".foo{color:lch(29.2345% 66.3 27)}",
18347    );
18348    minify_test(
18349      ".foo { color: lch(29.2345% 44.2 45deg); }",
18350      ".foo{color:lch(29.2345% 44.2 45)}",
18351    );
18352    minify_test(
18353      ".foo { color: lch(29.2345% 44.2 .5turn); }",
18354      ".foo{color:lch(29.2345% 44.2 180)}",
18355    );
18356    minify_test(
18357      ".foo { color: lch(29.2345% 44.2 27 / 100%); }",
18358      ".foo{color:lch(29.2345% 44.2 27)}",
18359    );
18360    minify_test(
18361      ".foo { color: lch(29.2345% 44.2 27 / 50%); }",
18362      ".foo{color:lch(29.2345% 44.2 27/.5)}",
18363    );
18364    minify_test(
18365      ".foo { color: oklab(40.101% 0.1147 0.0453); }",
18366      ".foo{color:oklab(40.101% .1147 .0453)}",
18367    );
18368    minify_test(
18369      ".foo { color: oklab(.40101 0.1147 0.0453); }",
18370      ".foo{color:oklab(40.101% .1147 .0453)}",
18371    );
18372    minify_test(
18373      ".foo { color: oklab(40.101% 0.1147% 0.0453%); }",
18374      ".foo{color:oklab(40.101% .0004588 .0001812)}",
18375    );
18376    minify_test(
18377      ".foo { color: oklch(40.101% 0.12332 21.555); }",
18378      ".foo{color:oklch(40.101% .12332 21.555)}",
18379    );
18380    minify_test(
18381      ".foo { color: oklch(.40101 0.12332 21.555); }",
18382      ".foo{color:oklch(40.101% .12332 21.555)}",
18383    );
18384    minify_test(
18385      ".foo { color: oklch(40.101% 0.12332% 21.555); }",
18386      ".foo{color:oklch(40.101% .00049328 21.555)}",
18387    );
18388    minify_test(
18389      ".foo { color: oklch(40.101% 0.12332 .5turn); }",
18390      ".foo{color:oklch(40.101% .12332 180)}",
18391    );
18392    minify_test(
18393      ".foo { color: color(display-p3 1 0.5 0); }",
18394      ".foo{color:color(display-p3 1 .5 0)}",
18395    );
18396    minify_test(
18397      ".foo { color: color(display-p3 100% 50% 0%); }",
18398      ".foo{color:color(display-p3 1 .5 0)}",
18399    );
18400    minify_test(
18401      ".foo { color: color(xyz-d50 0.2005 0.14089 0.4472); }",
18402      ".foo{color:color(xyz-d50 .2005 .14089 .4472)}",
18403    );
18404    minify_test(
18405      ".foo { color: color(xyz-d50 20.05% 14.089% 44.72%); }",
18406      ".foo{color:color(xyz-d50 .2005 .14089 .4472)}",
18407    );
18408    minify_test(
18409      ".foo { color: color(xyz-d65 0.2005 0.14089 0.4472); }",
18410      ".foo{color:color(xyz .2005 .14089 .4472)}",
18411    );
18412    minify_test(
18413      ".foo { color: color(xyz-d65 20.05% 14.089% 44.72%); }",
18414      ".foo{color:color(xyz .2005 .14089 .4472)}",
18415    );
18416    minify_test(
18417      ".foo { color: color(xyz 0.2005 0.14089 0.4472); }",
18418      ".foo{color:color(xyz .2005 .14089 .4472)}",
18419    );
18420    minify_test(
18421      ".foo { color: color(xyz 20.05% 14.089% 44.72%); }",
18422      ".foo{color:color(xyz .2005 .14089 .4472)}",
18423    );
18424    minify_test(
18425      ".foo { color: color(xyz 0.2005 0 0); }",
18426      ".foo{color:color(xyz .2005 0 0)}",
18427    );
18428    minify_test(".foo { color: color(xyz 0 0 0); }", ".foo{color:color(xyz 0 0 0)}");
18429    minify_test(".foo { color: color(xyz 0 1 0); }", ".foo{color:color(xyz 0 1 0)}");
18430    minify_test(
18431      ".foo { color: color(xyz 0 1 0 / 20%); }",
18432      ".foo{color:color(xyz 0 1 0/.2)}",
18433    );
18434    minify_test(
18435      ".foo { color: color(xyz 0 0 0 / 20%); }",
18436      ".foo{color:color(xyz 0 0 0/.2)}",
18437    );
18438    minify_test(
18439      ".foo { color: color(display-p3 100% 50% 0 / 20%); }",
18440      ".foo{color:color(display-p3 1 .5 0/.2)}",
18441    );
18442    minify_test(
18443      ".foo { color: color(display-p3 100% 0 0 / 20%); }",
18444      ".foo{color:color(display-p3 1 0 0/.2)}",
18445    );
18446    minify_test(".foo { color: hsl(none none none) }", ".foo{color:#000}");
18447    minify_test(".foo { color: hwb(none none none) }", ".foo{color:red}");
18448    minify_test(".foo { color: rgb(none none none) }", ".foo{color:#000}");
18449
18450    // If the browser doesn't support `#rrggbbaa` color syntax, it is converted to `transparent`.
18451    attr_test(
18452      "color: rgba(0, 0, 0, 0)",
18453      "color:transparent",
18454      true,
18455      Some(Browsers {
18456        chrome: Some(61 << 16), // Chrome >= 62 supports `#rrggbbaa` color.
18457        ..Browsers::default()
18458      }),
18459    );
18460
18461    attr_test(
18462      "color: #0000",
18463      "color:transparent",
18464      true,
18465      Some(Browsers {
18466        chrome: Some(61 << 16), // Chrome >= 62 supports `#rrggbbaa` color.
18467        ..Browsers::default()
18468      }),
18469    );
18470
18471    attr_test(
18472      "color: transparent",
18473      "color:transparent",
18474      true,
18475      Some(Browsers {
18476        chrome: Some(61 << 16),
18477        ..Browsers::default()
18478      }),
18479    );
18480
18481    attr_test(
18482      "color: rgba(0, 0, 0, 0)",
18483      "color: rgba(0, 0, 0, 0)",
18484      false,
18485      Some(Browsers {
18486        chrome: Some(61 << 16),
18487        ..Browsers::default()
18488      }),
18489    );
18490
18491    attr_test(
18492      "color: rgba(255, 0, 0, 0)",
18493      "color:rgba(255,0,0,0)",
18494      true,
18495      Some(Browsers {
18496        chrome: Some(61 << 16),
18497        ..Browsers::default()
18498      }),
18499    );
18500
18501    attr_test(
18502      "color: rgba(255, 0, 0, 0)",
18503      "color:#f000",
18504      true,
18505      Some(Browsers {
18506        chrome: Some(62 << 16),
18507        ..Browsers::default()
18508      }),
18509    );
18510
18511    prefix_test(
18512      ".foo { color: rgba(123, 456, 789, 0.5) }",
18513      indoc! { r#"
18514        .foo {
18515          color: #7bffff80;
18516        }
18517      "#},
18518      Browsers {
18519        chrome: Some(95 << 16),
18520        ..Browsers::default()
18521      },
18522    );
18523
18524    prefix_test(
18525      ".foo { color: rgba(123, 255, 255, 0.5) }",
18526      indoc! { r#"
18527        .foo {
18528          color: rgba(123, 255, 255, .5);
18529        }
18530      "#},
18531      Browsers {
18532        ie: Some(11 << 16),
18533        ..Browsers::default()
18534      },
18535    );
18536
18537    prefix_test(
18538      ".foo { color: #7bffff80 }",
18539      indoc! { r#"
18540        .foo {
18541          color: rgba(123, 255, 255, .5);
18542        }
18543      "#},
18544      Browsers {
18545        ie: Some(11 << 16),
18546        ..Browsers::default()
18547      },
18548    );
18549
18550    prefix_test(
18551      ".foo { color: rgba(123, 456, 789, 0.5) }",
18552      indoc! { r#"
18553        .foo {
18554          color: rgba(123, 255, 255, .5);
18555        }
18556      "#},
18557      Browsers {
18558        firefox: Some(48 << 16),
18559        safari: Some(10 << 16),
18560        ios_saf: Some(9 << 16),
18561        ..Browsers::default()
18562      },
18563    );
18564
18565    prefix_test(
18566      ".foo { color: rgba(123, 456, 789, 0.5) }",
18567      indoc! { r#"
18568        .foo {
18569          color: #7bffff80;
18570        }
18571      "#},
18572      Browsers {
18573        firefox: Some(49 << 16),
18574        safari: Some(10 << 16),
18575        ios_saf: Some(10 << 16),
18576        ..Browsers::default()
18577      },
18578    );
18579
18580    prefix_test(
18581      ".foo { background-color: lab(40% 56.6 39) }",
18582      indoc! { r#"
18583        .foo {
18584          background-color: #b32323;
18585          background-color: lab(40% 56.6 39);
18586        }
18587      "#},
18588      Browsers {
18589        chrome: Some(90 << 16),
18590        ..Browsers::default()
18591      },
18592    );
18593
18594    prefix_test(
18595      ".foo { background-color: lch(40% 68.735435 34.568626) }",
18596      indoc! { r#"
18597        .foo {
18598          background-color: #b32323;
18599          background-color: lch(40% 68.7354 34.5686);
18600        }
18601      "#},
18602      Browsers {
18603        chrome: Some(90 << 16),
18604        ..Browsers::default()
18605      },
18606    );
18607
18608    prefix_test(
18609      ".foo { background-color: oklab(59.686% 0.1009 0.1192); }",
18610      indoc! { r#"
18611        .foo {
18612          background-color: #c65d07;
18613          background-color: lab(52.2319% 40.1449 59.9171);
18614        }
18615      "#},
18616      Browsers {
18617        chrome: Some(90 << 16),
18618        ..Browsers::default()
18619      },
18620    );
18621
18622    prefix_test(
18623      ".foo { background-color: oklch(40% 0.1268735435 34.568626) }",
18624      indoc! { r#"
18625        .foo {
18626          background-color: #7e250f;
18627          background-color: lab(29.2661% 38.2437 35.3889);
18628        }
18629      "#},
18630      Browsers {
18631        chrome: Some(90 << 16),
18632        ..Browsers::default()
18633      },
18634    );
18635
18636    prefix_test(
18637      ".foo { background-color: lab(40% 56.6 39) }",
18638      indoc! { r#"
18639        .foo {
18640          background-color: lab(40% 56.6 39);
18641        }
18642      "#},
18643      Browsers {
18644        safari: Some(15 << 16),
18645        ..Browsers::default()
18646      },
18647    );
18648
18649    prefix_test(
18650      ".foo { background-color: oklab(59.686% 0.1009 0.1192); }",
18651      indoc! { r#"
18652        .foo {
18653          background-color: #c65d07;
18654          background-color: lab(52.2319% 40.1449 59.9171);
18655        }
18656      "#},
18657      Browsers {
18658        chrome: Some(90 << 16),
18659        safari: Some(15 << 16),
18660        ..Browsers::default()
18661      },
18662    );
18663
18664    prefix_test(
18665      ".foo { background-color: oklab(59.686% 0.1009 0.1192); }",
18666      indoc! { r#"
18667        .foo {
18668          background-color: #c65d07;
18669          background-color: color(display-p3 .724144 .386777 .148795);
18670          background-color: lab(52.2319% 40.1449 59.9171);
18671        }
18672      "#},
18673      Browsers {
18674        chrome: Some(90 << 16),
18675        safari: Some(14 << 16),
18676        ..Browsers::default()
18677      },
18678    );
18679
18680    prefix_test(
18681      ".foo { background-color: lab(40% 56.6 39) }",
18682      indoc! { r#"
18683        .foo {
18684          background-color: #b32323;
18685          background-color: color(display-p3 .643308 .192455 .167712);
18686          background-color: lab(40% 56.6 39);
18687        }
18688      "#},
18689      Browsers {
18690        chrome: Some(90 << 16),
18691        safari: Some(14 << 16),
18692        ..Browsers::default()
18693      },
18694    );
18695
18696    prefix_test(
18697      ".foo { background-color: oklch(59.686% 0.15619 49.7694); }",
18698      indoc! { r#"
18699        .foo {
18700          background-color: #c65d06;
18701          background-color: lab(52.2321% 40.1417 59.9527);
18702        }
18703      "#},
18704      Browsers {
18705        chrome: Some(90 << 16),
18706        safari: Some(15 << 16),
18707        ..Browsers::default()
18708      },
18709    );
18710
18711    prefix_test(
18712      ".foo { background-color: color(sRGB 0.41587 0.503670 0.36664); }",
18713      indoc! { r#"
18714        .foo {
18715          background-color: #6a805d;
18716          background-color: color(srgb .41587 .50367 .36664);
18717        }
18718      "#},
18719      Browsers {
18720        chrome: Some(90 << 16),
18721        ..Browsers::default()
18722      },
18723    );
18724
18725    prefix_test(
18726      ".foo { background-color: color(display-p3 0.43313 0.50108 0.37950); }",
18727      indoc! { r#"
18728        .foo {
18729          background-color: #6a805d;
18730          background-color: color(display-p3 .43313 .50108 .3795);
18731        }
18732      "#},
18733      Browsers {
18734        chrome: Some(90 << 16),
18735        ..Browsers::default()
18736      },
18737    );
18738
18739    prefix_test(
18740      ".foo { background-color: color(display-p3 0.43313 0.50108 0.37950); }",
18741      indoc! { r#"
18742        .foo {
18743          background-color: #6a805d;
18744          background-color: color(display-p3 .43313 .50108 .3795);
18745        }
18746      "#},
18747      Browsers {
18748        chrome: Some(90 << 16),
18749        safari: Some(14 << 16),
18750        ..Browsers::default()
18751      },
18752    );
18753
18754    prefix_test(
18755      ".foo { background-color: color(display-p3 0.43313 0.50108 0.37950); }",
18756      indoc! { r#"
18757        .foo {
18758          background-color: color(display-p3 .43313 .50108 .3795);
18759        }
18760      "#},
18761      Browsers {
18762        safari: Some(14 << 16),
18763        ..Browsers::default()
18764      },
18765    );
18766
18767    prefix_test(
18768      ".foo { background-color: color(display-p3 0.43313 0.50108 0.37950); }",
18769      indoc! { r#"
18770        .foo {
18771          background-color: #6a805d;
18772          background-color: color(display-p3 .43313 .50108 .3795);
18773        }
18774      "#},
18775      Browsers {
18776        chrome: Some(90 << 16),
18777        safari: Some(15 << 16),
18778        ..Browsers::default()
18779      },
18780    );
18781
18782    prefix_test(
18783      ".foo { background-color: color(display-p3 0.43313 0.50108 0.37950); }",
18784      indoc! { r#"
18785        .foo {
18786          background-color: #6a805d;
18787          background-color: color(display-p3 .43313 .50108 .3795);
18788        }
18789      "#},
18790      Browsers {
18791        chrome: Some(90 << 16),
18792        ..Browsers::default()
18793      },
18794    );
18795
18796    prefix_test(
18797      ".foo { background-color: color(a98-rgb 0.44091 0.49971 0.37408); }",
18798      indoc! { r#"
18799        .foo {
18800          background-color: #6a805d;
18801          background-color: color(a98-rgb .44091 .49971 .37408);
18802        }
18803      "#},
18804      Browsers {
18805        chrome: Some(90 << 16),
18806        ..Browsers::default()
18807      },
18808    );
18809
18810    prefix_test(
18811      ".foo { background-color: color(a98-rgb 0.44091 0.49971 0.37408); }",
18812      indoc! { r#"
18813        .foo {
18814          background-color: color(a98-rgb .44091 .49971 .37408);
18815        }
18816      "#},
18817      Browsers {
18818        safari: Some(15 << 16),
18819        ..Browsers::default()
18820      },
18821    );
18822
18823    prefix_test(
18824      ".foo { background-color: color(prophoto-rgb 0.36589 0.41717 0.31333); }",
18825      indoc! { r#"
18826        .foo {
18827          background-color: #6a805d;
18828          background-color: color(prophoto-rgb .36589 .41717 .31333);
18829        }
18830      "#},
18831      Browsers {
18832        chrome: Some(90 << 16),
18833        ..Browsers::default()
18834      },
18835    );
18836
18837    prefix_test(
18838      ".foo { background-color: color(rec2020 0.42210 0.47580 0.35605); }",
18839      indoc! { r#"
18840        .foo {
18841          background-color: #728765;
18842          background-color: color(rec2020 .4221 .4758 .35605);
18843        }
18844      "#},
18845      Browsers {
18846        chrome: Some(90 << 16),
18847        ..Browsers::default()
18848      },
18849    );
18850
18851    prefix_test(
18852      ".foo { background-color: color(xyz-d50 0.2005 0.14089 0.4472); }",
18853      indoc! { r#"
18854        .foo {
18855          background-color: #7654cd;
18856          background-color: color(xyz-d50 .2005 .14089 .4472);
18857        }
18858      "#},
18859      Browsers {
18860        chrome: Some(90 << 16),
18861        ..Browsers::default()
18862      },
18863    );
18864
18865    prefix_test(
18866      ".foo { background-color: color(xyz-d65 0.21661 0.14602 0.59452); }",
18867      indoc! { r#"
18868        .foo {
18869          background-color: #7654cd;
18870          background-color: color(xyz .21661 .14602 .59452);
18871        }
18872      "#},
18873      Browsers {
18874        chrome: Some(90 << 16),
18875        ..Browsers::default()
18876      },
18877    );
18878
18879    prefix_test(
18880      ".foo { background-color: lch(50.998% 135.363 338) }",
18881      indoc! { r#"
18882        .foo {
18883          background-color: #ee00be;
18884          background-color: color(display-p3 .972962 -.362078 .804206);
18885          background-color: lch(50.998% 135.363 338);
18886        }
18887      "#},
18888      Browsers {
18889        chrome: Some(90 << 16),
18890        safari: Some(14 << 16),
18891        ..Browsers::default()
18892      },
18893    );
18894
18895    prefix_test(
18896      ".foo { color: lch(50.998% 135.363 338) }",
18897      indoc! { r#"
18898        .foo {
18899          color: #ee00be;
18900          color: color(display-p3 .972962 -.362078 .804206);
18901          color: lch(50.998% 135.363 338);
18902        }
18903      "#},
18904      Browsers {
18905        chrome: Some(90 << 16),
18906        safari: Some(14 << 16),
18907        ..Browsers::default()
18908      },
18909    );
18910
18911    prefix_test(
18912      ".foo { background: var(--image) lch(40% 68.735435 34.568626) }",
18913      indoc! { r#"
18914        .foo {
18915          background: var(--image) #b32323;
18916        }
18917
18918        @supports (color: lab(0% 0 0)) {
18919          .foo {
18920            background: var(--image) lab(40% 56.6 39);
18921          }
18922        }
18923      "#},
18924      Browsers {
18925        chrome: Some(90 << 16),
18926        ..Browsers::default()
18927      },
18928    );
18929
18930    prefix_test(
18931      r#"
18932        @supports (color: lab(0% 0 0)) {
18933          .foo {
18934            background: var(--image) lab(40% 56.6 39);
18935          }
18936        }
18937      "#,
18938      indoc! { r#"
18939        @supports (color: lab(0% 0 0)) {
18940          .foo {
18941            background: var(--image) lab(40% 56.6 39);
18942          }
18943        }
18944      "#},
18945      Browsers {
18946        chrome: Some(90 << 16),
18947        ..Browsers::default()
18948      },
18949    );
18950
18951    prefix_test(
18952      r#"
18953      .foo {
18954        color: red;
18955        color: lab(40% 56.6 39);
18956      }
18957    "#,
18958      indoc! {r#"
18959      .foo {
18960        color: red;
18961        color: lab(40% 56.6 39);
18962      }
18963    "#
18964      },
18965      Browsers {
18966        safari: Some(14 << 16),
18967        ..Browsers::default()
18968      },
18969    );
18970    prefix_test(
18971      r#"
18972      .foo {
18973        color: red;
18974        color: lab(40% 56.6 39);
18975      }
18976    "#,
18977      indoc! {r#"
18978      .foo {
18979        color: lab(40% 56.6 39);
18980      }
18981    "#
18982      },
18983      Browsers {
18984        safari: Some(16 << 16),
18985        ..Browsers::default()
18986      },
18987    );
18988
18989    prefix_test(
18990      r#"
18991      .foo {
18992        color: var(--fallback);
18993        color: lab(40% 56.6 39);
18994      }
18995    "#,
18996      indoc! {r#"
18997      .foo {
18998        color: var(--fallback);
18999        color: lab(40% 56.6 39);
19000      }
19001    "#
19002      },
19003      Browsers {
19004        safari: Some(14 << 16),
19005        ..Browsers::default()
19006      },
19007    );
19008
19009    prefix_test(
19010      r#"
19011      .foo {
19012        color: var(--fallback);
19013        color: lab(40% 56.6 39);
19014      }
19015    "#,
19016      indoc! {r#"
19017      .foo {
19018        color: lab(40% 56.6 39);
19019      }
19020    "#
19021      },
19022      Browsers {
19023        safari: Some(16 << 16),
19024        ..Browsers::default()
19025      },
19026    );
19027
19028    prefix_test(
19029      r#"
19030      .foo {
19031        color: red;
19032        color: var(--foo, lab(40% 56.6 39));
19033      }
19034    "#,
19035      indoc! {r#"
19036      .foo {
19037        color: var(--foo, color(display-p3 .643308 .192455 .167712));
19038      }
19039
19040      @supports (color: lab(0% 0 0)) {
19041        .foo {
19042          color: var(--foo, lab(40% 56.6 39));
19043        }
19044      }
19045    "#
19046      },
19047      Browsers {
19048        safari: Some(14 << 16),
19049        ..Browsers::default()
19050      },
19051    );
19052
19053    prefix_test(
19054      r#"
19055      @supports (color: lab(0% 0 0)) {
19056        .foo {
19057          color: var(--foo, lab(40% 56.6 39));
19058        }
19059      }
19060    "#,
19061      indoc! {r#"
19062      @supports (color: lab(0% 0 0)) {
19063        .foo {
19064          color: var(--foo, lab(40% 56.6 39));
19065        }
19066      }
19067    "#
19068      },
19069      Browsers {
19070        safari: Some(14 << 16),
19071        ..Browsers::default()
19072      },
19073    );
19074
19075    prefix_test(
19076      r#"
19077      .foo {
19078        --a: rgb(0 0 0 / var(--alpha));
19079        --b: rgb(50% 50% 50% / var(--alpha));
19080        --c: rgb(var(--x) 0 0);
19081        --d: rgb(0 var(--x) 0);
19082        --e: rgb(0 0 var(--x));
19083        --f: rgb(var(--x) 0 0 / var(--alpha));
19084        --g: rgb(0 var(--x) 0 / var(--alpha));
19085        --h: rgb(0 0 var(--x) / var(--alpha));
19086        --i: rgb(none 0 0 / var(--alpha));
19087        --j: rgb(from yellow r g b / var(--alpha));
19088      }
19089      "#,
19090      indoc! { r#"
19091        .foo {
19092          --a: rgba(0, 0, 0, var(--alpha));
19093          --b: rgba(128, 128, 128, var(--alpha));
19094          --c: rgb(var(--x) 0 0);
19095          --d: rgb(0 var(--x) 0);
19096          --e: rgb(0 0 var(--x));
19097          --f: rgb(var(--x) 0 0 / var(--alpha));
19098          --g: rgb(0 var(--x) 0 / var(--alpha));
19099          --h: rgb(0 0 var(--x) / var(--alpha));
19100          --i: rgb(none 0 0 / var(--alpha));
19101          --j: rgba(255, 255, 0, var(--alpha));
19102        }
19103      "#},
19104      Browsers {
19105        safari: Some(11 << 16),
19106        ..Browsers::default()
19107      },
19108    );
19109
19110    prefix_test(
19111      r#"
19112      .foo {
19113        --a: rgb(0 0 0 / var(--alpha));
19114        --b: rgb(50% 50% 50% / var(--alpha));
19115        --c: rgb(var(--x) 0 0);
19116        --d: rgb(0 var(--x) 0);
19117        --e: rgb(0 0 var(--x));
19118        --f: rgb(var(--x) 0 0 / var(--alpha));
19119        --g: rgb(0 var(--x) 0 / var(--alpha));
19120        --h: rgb(0 0 var(--x) / var(--alpha));
19121        --i: rgb(none 0 0 / var(--alpha));
19122        --j: rgb(from yellow r g b / var(--alpha));
19123      }
19124      "#,
19125      indoc! { r#"
19126        .foo {
19127          --a: rgb(0 0 0 / var(--alpha));
19128          --b: rgb(128 128 128 / var(--alpha));
19129          --c: rgb(var(--x) 0 0);
19130          --d: rgb(0 var(--x) 0);
19131          --e: rgb(0 0 var(--x));
19132          --f: rgb(var(--x) 0 0 / var(--alpha));
19133          --g: rgb(0 var(--x) 0 / var(--alpha));
19134          --h: rgb(0 0 var(--x) / var(--alpha));
19135          --i: rgb(none 0 0 / var(--alpha));
19136          --j: rgb(255 255 0 / var(--alpha));
19137        }
19138      "#},
19139      Browsers {
19140        safari: Some(13 << 16),
19141        ..Browsers::default()
19142      },
19143    );
19144
19145    prefix_test(
19146      r#"
19147      .foo {
19148        --a: hsl(270 100% 50% / var(--alpha));
19149        --b: hsl(var(--x) 0 0);
19150        --c: hsl(0 var(--x) 0);
19151        --d: hsl(0 0 var(--x));
19152        --e: hsl(var(--x) 0 0 / var(--alpha));
19153        --f: hsl(0 var(--x) 0 / var(--alpha));
19154        --g: hsl(0 0 var(--x) / var(--alpha));
19155        --h: hsl(270 100% 50% / calc(var(--alpha) / 2));
19156        --i: hsl(none 100% 50% / var(--alpha));
19157        --j: hsl(from yellow h s l / var(--alpha));
19158      }
19159      "#,
19160      indoc! { r#"
19161        .foo {
19162          --a: hsla(270, 100%, 50%, var(--alpha));
19163          --b: hsl(var(--x) 0 0);
19164          --c: hsl(0 var(--x) 0);
19165          --d: hsl(0 0 var(--x));
19166          --e: hsl(var(--x) 0 0 / var(--alpha));
19167          --f: hsl(0 var(--x) 0 / var(--alpha));
19168          --g: hsl(0 0 var(--x) / var(--alpha));
19169          --h: hsla(270, 100%, 50%, calc(var(--alpha) / 2));
19170          --i: hsl(none 100% 50% / var(--alpha));
19171          --j: hsla(60, 100%, 50%, var(--alpha));
19172        }
19173      "#},
19174      Browsers {
19175        safari: Some(11 << 16),
19176        ..Browsers::default()
19177      },
19178    );
19179
19180    prefix_test(
19181      r#"
19182      .foo {
19183        --a: hsl(270 100% 50% / var(--alpha));
19184        --b: hsl(var(--x) 0 0);
19185        --c: hsl(0 var(--x) 0);
19186        --d: hsl(0 0 var(--x));
19187        --e: hsl(var(--x) 0 0 / var(--alpha));
19188        --f: hsl(0 var(--x) 0 / var(--alpha));
19189        --g: hsl(0 0 var(--x) / var(--alpha));
19190        --h: hsl(270 100% 50% / calc(var(--alpha) / 2));
19191        --i: hsl(none 100% 50% / var(--alpha));
19192      }
19193      "#,
19194      indoc! { r#"
19195        .foo {
19196          --a: hsl(270 100% 50% / var(--alpha));
19197          --b: hsl(var(--x) 0 0);
19198          --c: hsl(0 var(--x) 0);
19199          --d: hsl(0 0 var(--x));
19200          --e: hsl(var(--x) 0 0 / var(--alpha));
19201          --f: hsl(0 var(--x) 0 / var(--alpha));
19202          --g: hsl(0 0 var(--x) / var(--alpha));
19203          --h: hsl(270 100% 50% / calc(var(--alpha) / 2));
19204          --i: hsl(none 100% 50% / var(--alpha));
19205        }
19206      "#},
19207      Browsers {
19208        safari: Some(13 << 16),
19209        ..Browsers::default()
19210      },
19211    );
19212
19213    test(
19214      r#"
19215      .foo {
19216        --a: rgb(50% 50% 50% / calc(100% / 2));
19217        --b: hsl(calc(360deg / 2) 50% 50%);
19218        --c: oklab(40.101% calc(0.1 + 0.2) 0.0453);
19219        --d: color(display-p3 0.43313 0.50108 calc(0.1 + 0.2));
19220        --e: rgb(calc(255 / 2), calc(255 / 2), calc(255 / 2));
19221      }
19222      "#,
19223      indoc! { r#"
19224        .foo {
19225          --a: #80808080;
19226          --b: #40bfbf;
19227          --c: oklab(40.101% .3 .0453);
19228          --d: color(display-p3 .43313 .50108 .3);
19229          --e: gray;
19230        }
19231      "#},
19232    );
19233  }
19234
19235  #[test]
19236  fn test_relative_color() {
19237    #[track_caller]
19238    fn test(input: &str, output: &str) {
19239      let parsed = match CssColor::parse_string(output) {
19240        Ok(c) => c,
19241        Err(e) => panic!(
19242          "test_relative_color: parse expected output failed\nerror: {e:?}\ninput: {input}\noutput: {output}",
19243        ),
19244      };
19245      let output_css = match parsed.to_css_string(PrinterOptions {
19246        minify: true,
19247        ..PrinterOptions::default()
19248      }) {
19249        Ok(s) => s,
19250        Err(e) => panic!(
19251          "test_relative_color: stringify expected output failed\nerror: {e}\nerror(debug): {e:?}\ninput: {input}\noutput: {output}",
19252        ),
19253      };
19254      minify_test(
19255        &format!(".foo {{ color: {} }}", input),
19256        &format!(".foo{{color:{}}}", output_css),
19257      );
19258    }
19259
19260    test("lab(from indianred calc(l * .8) a b)", "lab(43.1402% 45.7516 23.1557)");
19261    test("lch(from indianred calc(l + 10) c h)", "lch(63.9252% 51.2776 26.8448)");
19262    test("lch(from indianred l calc(c - 50) h)", "lch(53.9252% 1.27763 26.8448)");
19263    test(
19264      "lch(from indianred l c calc(h + 180deg))",
19265      "lch(53.9252% 51.2776 206.845)",
19266    );
19267    test("lch(from orchid l 30 h)", "lch(62.7526% 30 326.969)");
19268    test("lch(from orchid l 30 h)", "lch(62.7526% 30 326.969)");
19269    test("lch(from peru calc(l * 0.8) c h)", "lch(49.8022% 54.0117 63.6804)");
19270    test("rgb(from indianred 255 g b)", "rgb(255, 92, 92)");
19271    test("rgb(from indianred r g b / .5)", "rgba(205, 92, 92, .5)");
19272    test(
19273      "rgb(from rgba(205, 92, 92, .5) r g b / calc(alpha + .2))",
19274      "rgba(205, 92, 92, .7)",
19275    );
19276    test(
19277      "rgb(from rgba(205, 92, 92, .5) r g b / calc(alpha + .2))",
19278      "rgba(205, 92, 92, .7)",
19279    );
19280    test("lch(from indianred l sin(c) h)", "lch(53.9252% .84797 26.8448)");
19281    test("lch(from indianred l sqrt(c) h)", "lch(53.9252% 7.16084 26.8448)");
19282    test("lch(from indianred l c sin(h))", "lch(53.9252% 51.2776 .451575)");
19283    test("lch(from indianred calc(10% + 20%) c h)", "lch(30% 51.2776 26.8448)");
19284    test("lch(from indianred calc(10 + 20) c h)", "lch(30% 51.2776 26.8448)");
19285    test("lch(from indianred l c calc(10 + 20))", "lch(53.9252% 51.2776 30)");
19286    test(
19287      "lch(from indianred l c calc(10deg + 20deg))",
19288      "lch(53.9252% 51.2776 30)",
19289    );
19290    test(
19291      "lch(from indianred l c calc(10deg + 0.35rad))",
19292      "lch(53.9252% 51.2776 30.0535)",
19293    );
19294    minify_test(
19295      ".foo{color:lch(from currentColor l c sin(h))}",
19296      ".foo{color:lch(from currentColor l c sin(h))}",
19297    );
19298
19299    // The following tests were converted from WPT:
19300    // https://github.com/web-platform-tests/wpt/blob/master/css/css-color/parsing/alpha-color-parsing-valid.html
19301
19302    // Basic usage with literal alpha.
19303    test("alpha(from red / 0.5)", "rgba(255, 0, 0, 0.5)");
19304    test("alpha(from blue / 1)", "rgb(0, 0, 255)");
19305    test("alpha(from green / 0)", "rgba(0, 128, 0, 0)");
19306
19307    // Percentage alpha.
19308    test("alpha(from red / 50%)", "rgba(255, 0, 0, 0.5)");
19309    test("alpha(from red / 0%)", "rgba(255, 0, 0, 0)");
19310    test("alpha(from red / 100%)", "rgb(255, 0, 0)");
19311
19312    // None alpha.
19313    test("alpha(from red / none)", "rgba(255, 0, 0, 0)");
19314
19315    // Omitted alpha (defaults to origin's alpha).
19316    test("alpha(from red)", "rgb(255, 0, 0)");
19317    // test() does not support keywords such as currentcolor; change it to minify_test()
19318    minify_test(
19319      ".foo{color:alpha(from currentcolor)}",
19320      ".foo{color:alpha(from currentcolor)}",
19321    );
19322
19323    // Alpha keyword referencing origin's alpha.
19324    minify_test(
19325      ".foo{color:alpha(from currentcolor / alpha)}",
19326      ".foo{color:alpha(from currentcolor / alpha)}",
19327    );
19328    test("alpha(from rgba(255, 0, 0, 0.8) / alpha)", "rgba(255, 0, 0, 0.8)");
19329
19330    // Calc with alpha keyword.
19331    test(
19332      "alpha(from rgba(255, 0, 0, 0.8) / calc(alpha * 0.5))",
19333      "rgba(255, 0, 0, 0.4)",
19334    );
19335    test(
19336      "alpha(from rgba(255, 0, 0, 0.8) / calc(alpha + 0.1))",
19337      "rgba(255, 0, 0, 0.9)",
19338    );
19339
19340    // Supplementary testing
19341    // TODO: calc does not support division by zero yet, so `alpha / 0` fails while `alpha / 1` works.
19342    // Depends on: https://github.com/parcel-bundler/lightningcss/pull/1122
19343    // test(
19344    //   "alpha(from green / calc(alpha / 0))",
19345    //   "rgb(0, 128, 0)",
19346    // );
19347    test("alpha(from green / calc(alpha / 1))", "rgb(0, 128, 0)");
19348
19349    // Test sibling-index() and sibling-count()
19350    minify_test(
19351      ".foo{color:alpha(from green / sibling-index())}",
19352      ".foo{color:alpha(from green / sibling-index())}",
19353    );
19354    minify_test(
19355      ".foo{color:alpha(from green / calc(sibling-index() * 0.2))}",
19356      ".foo{color:alpha(from green / calc(sibling-index() * .2))}",
19357    );
19358    minify_test(
19359      ".foo{color:alpha(from green / sibling-count())}",
19360      ".foo{color:alpha(from green / sibling-count())}",
19361    );
19362
19363    // Nested in other color functions.
19364    minify_test(
19365      ".foo{color:color-mix(in srgb, alpha(from red / 0.5), blue)}",
19366      ".foo{color:#5500aabf}",
19367    );
19368    test("rgb(from alpha(from red / 0.5) r g b / alpha)", "rgba(255, 0, 0, 0.5)");
19369
19370    // Other color functions as origin.
19371    test("alpha(from color-mix(in srgb, red, blue) / 0.5)", "#80008080");
19372    test("alpha(from rgb(from red r g b) / 0.8)", "rgba(255, 0, 0, 0.8)");
19373
19374    // Non-sRGB color spaces preserved.
19375    test(
19376      "alpha(from color(display-p3 1 0 0) / 0.5)",
19377      "color(display-p3 1 0 0 / 0.5)",
19378    );
19379    test("alpha(from lab(50 20 -30) / 0.5)", "lab(50% 20 -30 / 0.5)");
19380    test("alpha(from oklch(0.5 0.2 120) / 0.5)", "oklch(50% 0.2 120 / 0.5)");
19381
19382    // System and named colors.
19383    // https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/system-color#syntax
19384    minify_test(
19385      ".foo{color:alpha(from ActiveText / 0.5)}",
19386      ".foo{color:alpha(from ActiveText / .5)}",
19387    );
19388
19389    // Out-of-range alpha values.
19390    test("alpha(from red / 2)", "rgb(255, 0, 0)");
19391    test("alpha(from red / -1)", "rgba(255, 0, 0, 0)");
19392
19393    // Supplementary testing
19394    // nested alpha() precision.
19395    test("alpha(from alpha(from red / 0.5) / calc(alpha + 0.25))", "#ff0000bf");
19396    test("alpha(from alpha(from red / -0.5) / calc(alpha + 0.6))", "#f009");
19397    test("alpha(from alpha(from green / 0%) / 100%)", "green");
19398
19399    // Unresolved relative colors keep their tokens.
19400    minify_test(
19401      ".foo{color:rgb(from alpha(from currentColor / 0.5) r g b)}",
19402      ".foo{color:rgb(from alpha(from currentColor / .5) r g b)}",
19403    );
19404    minify_test(
19405      ".foo{color:alpha(from red / var(--alpha))}",
19406      ".foo{color:alpha(from red / var(--alpha))}",
19407    );
19408
19409    // RGBA origin alpha preserve/replace.
19410    test("alpha(from rgba(255, 0, 0, 0.3))", "rgba(255, 0, 0, 0.3)");
19411    test("alpha(from rgba(255, 0, 0, 0.3) / 0.8)", "rgba(255, 0, 0, 0.8)");
19412
19413    // color(srgb) preserves its color space.
19414    test("alpha(from color(srgb 1 0 0) / 50%)", "color(srgb 1 0 0 / 0.5)");
19415
19416    // alpha() nested in more relative color functions.
19417    test("hsl(from alpha(from red / 0.5) h s l / alpha)", "rgba(255, 0, 0, 0.5)");
19418    test("hwb(from alpha(from red / 0.5) h w b / alpha)", "rgba(255, 0, 0, 0.5)");
19419    test(
19420      "lab(from alpha(from lab(50% 20 -30) / 0.5) l a b / alpha)",
19421      "lab(50% 20 -30 / 0.5)",
19422    );
19423    test(
19424      "lch(from alpha(from lch(50% 20 30) / 0.5) l c h / alpha)",
19425      "lch(50% 20 30 / 0.5)",
19426    );
19427    test(
19428      "oklab(from alpha(from oklab(50% 0.2 -0.3) / 0.5) l a b / alpha)",
19429      "oklab(50% 0.2 -0.3 / 0.5)",
19430    );
19431    test(
19432      "oklch(from alpha(from oklch(50% 0.2 120) / 0.5) l c h / alpha)",
19433      "oklch(50% 0.2 120 / 0.5)",
19434    );
19435    test(
19436      "color(from alpha(from color(display-p3 1 0 0) / 0.5) display-p3 r g b / alpha)",
19437      "color(display-p3 1 0 0 / 0.5)",
19438    );
19439    test(
19440      "color(from alpha(from red / 1.5) srgb r g b / calc(alpha - 0.2))",
19441      "color(srgb 1 0 0 / 0.8)", // alpha = 1 - 0.2
19442    );
19443
19444    // Test in image()
19445    minify_test(".foo { mask: image(alpha(from red / 1))}", ".foo{mask:image(red)}");
19446
19447    // Test in linear-gradient()
19448    minify_test(
19449      ".foo { mask: linear-gradient(90deg, alpha(from red / 0%), red) }",
19450      ".foo{mask:linear-gradient(90deg,#f000,red)}",
19451    );
19452    // Compare relative color
19453    // TODO: Support <color-interpolation-method>
19454    minify_test(
19455      ".foo { mask: linear-gradient(90deg in hsl longer hue, rgb(from red r g b / 0), red) }",
19456      ".foo{mask:linear-gradient(90deg in hsl longer hue, #f000, red)}",
19457    );
19458    minify_test(
19459      ".foo { mask: linear-gradient(90deg in hsl longer hue, alpha(from red / 0%), red) }",
19460      ".foo{mask:linear-gradient(90deg in hsl longer hue, #f000, red)}",
19461    );
19462
19463    minify_test(
19464      ".foo { color: alpha(from color(display-p3 1 0 0) / 0.5) }",
19465      ".foo{color:color(display-p3 1 0 0/.5)}",
19466    );
19467
19468    // The following tests were converted from WPT: https://github.com/web-platform-tests/wpt/blob/master/css/css-color/parsing/relative-color-valid.html
19469    // Find: test_valid_value\(`color`, `(.*?)`,\s*`(.*?)`\)
19470    // Replace: test("$1", "$2")
19471
19472    // Testing no modifications.
19473    test("rgb(from rebeccapurple r g b)", "#639");
19474    test("rgb(from rebeccapurple r g b / alpha)", "#639");
19475    test("rgb(from rgb(20%, 40%, 60%, 80%) r g b / alpha)", "#369c");
19476    test("rgb(from hsl(120deg 20% 50% / .5) r g b / alpha)", "#66996680");
19477
19478    // Test nesting relative colors.
19479    test("rgb(from rgb(from rebeccapurple r g b) r g b)", "#639");
19480
19481    // Testing non-sRGB origin colors to see gamut mapping.
19482    test("rgb(from color(display-p3 0 1 0) r g b / alpha)", "#00f942"); // Naive clip based mapping would give rgb(0, 255, 0).
19483    test("rgb(from lab(100% 104.3 -50.9) r g b)", "#fff"); // Naive clip based mapping would give rgb(255, 150, 255).
19484    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.
19485    test("rgb(from lch(100% 116 334) r g b)", "#fff"); // Naive clip based mapping would give rgb(255, 150, 255).
19486    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.
19487    test("rgb(from oklab(100% 0.365 -0.16) r g b)", "#fff"); // Naive clip based mapping would give rgb(255, 92, 255).
19488    test("rgb(from oklab(0% 0.365 -0.16) r g b)", "#000"); // Naive clip based mapping would give rgb(19, 0, 24).
19489    test("rgb(from oklch(100% 0.399 336.3) r g b)", "#fff"); // Naive clip based mapping would give rgb(255, 91, 255).
19490    test("rgb(from oklch(0% 0.399 336.3) r g b)", "#000"); // Naive clip based mapping would give rgb(20, 0, 24).
19491
19492    // Testing replacement with 0.
19493    test("rgb(from rebeccapurple 0 0 0)", "rgb(0, 0, 0)");
19494    test("rgb(from rebeccapurple 0 0 0 / 0)", "rgba(0, 0, 0, 0)");
19495    test("rgb(from rebeccapurple 0 g b / alpha)", "rgb(0, 51, 153)");
19496    test("rgb(from rebeccapurple r 0 b / alpha)", "rgb(102, 0, 153)");
19497    test("rgb(from rebeccapurple r g 0 / alpha)", "rgb(102, 51, 0)");
19498    test("rgb(from rebeccapurple r g b / 0)", "rgba(102, 51, 153, 0)");
19499    test(
19500      "rgb(from rgb(20%, 40%, 60%, 80%) 0 g b / alpha)",
19501      "rgba(0, 102, 153, 0.8)",
19502    );
19503    test(
19504      "rgb(from rgb(20%, 40%, 60%, 80%) r 0 b / alpha)",
19505      "rgba(51, 0, 153, 0.8)",
19506    );
19507    test(
19508      "rgb(from rgb(20%, 40%, 60%, 80%) r g 0 / alpha)",
19509      "rgba(51, 102, 0, 0.8)",
19510    );
19511    test("rgb(from rgb(20%, 40%, 60%, 80%) r g b / 0)", "rgba(51, 102, 153, 0)");
19512
19513    // Testing replacement with a number.
19514    test("rgb(from rebeccapurple 25 g b / alpha)", "rgb(25, 51, 153)");
19515    test("rgb(from rebeccapurple r 25 b / alpha)", "rgb(102, 25, 153)");
19516    test("rgb(from rebeccapurple r g 25 / alpha)", "rgb(102, 51, 25)");
19517    test("rgb(from rebeccapurple r g b / .25)", "rgba(102, 51, 153, 0.25)");
19518    test(
19519      "rgb(from rgb(20%, 40%, 60%, 80%) 25 g b / alpha)",
19520      "rgba(25, 102, 153, 0.8)",
19521    );
19522    test(
19523      "rgb(from rgb(20%, 40%, 60%, 80%) r 25 b / alpha)",
19524      "rgba(51, 25, 153, 0.8)",
19525    );
19526    test(
19527      "rgb(from rgb(20%, 40%, 60%, 80%) r g 25 / alpha)",
19528      "rgba(51, 102, 25, 0.8)",
19529    );
19530    test(
19531      "rgb(from rgb(20%, 40%, 60%, 80%) r g b / .20)",
19532      "rgba(51, 102, 153, 0.2)",
19533    );
19534
19535    // Testing replacement with a percentage.
19536    test("rgb(from rebeccapurple 20% g b / alpha)", "rgb(51, 51, 153)");
19537    test("rgb(from rebeccapurple r 20% b / alpha)", "rgb(102, 51, 153)");
19538    test("rgb(from rebeccapurple r g 20% / alpha)", "rgb(102, 51, 51)");
19539    test("rgb(from rebeccapurple r g b / 20%)", "rgba(102, 51, 153, 0.2)");
19540    test(
19541      "rgb(from rgb(20%, 40%, 60%, 80%) 20% g b / alpha)",
19542      "rgba(51, 102, 153, 0.8)",
19543    );
19544    test(
19545      "rgb(from rgb(20%, 40%, 60%, 80%) r 20% b / alpha)",
19546      "rgba(51, 51, 153, 0.8)",
19547    );
19548    test(
19549      "rgb(from rgb(20%, 40%, 60%, 80%) r g 20% / alpha)",
19550      "rgba(51, 102, 51, 0.8)",
19551    );
19552    test(
19553      "rgb(from rgb(20%, 40%, 60%, 80%) r g b / 20%)",
19554      "rgba(51, 102, 153, 0.2)",
19555    );
19556
19557    // Testing replacement with a number for r, g, b but percent for alpha.
19558    test("rgb(from rebeccapurple 25 g b / 25%)", "rgba(25, 51, 153, 0.25)");
19559    test("rgb(from rebeccapurple r 25 b / 25%)", "rgba(102, 25, 153, 0.25)");
19560    test("rgb(from rebeccapurple r g 25 / 25%)", "rgba(102, 51, 25, 0.25)");
19561    test(
19562      "rgb(from rgb(20%, 40%, 60%, 80%) 25 g b / 25%)",
19563      "rgba(25, 102, 153, 0.25)",
19564    );
19565    test(
19566      "rgb(from rgb(20%, 40%, 60%, 80%) r 25 b / 25%)",
19567      "rgba(51, 25, 153, 0.25)",
19568    );
19569    test(
19570      "rgb(from rgb(20%, 40%, 60%, 80%) r g 25 / 25%)",
19571      "rgba(51, 102, 25, 0.25)",
19572    );
19573
19574    // Testing permutation.
19575    test("rgb(from rebeccapurple g b r)", "rgb(51, 153, 102)");
19576    test("rgb(from rebeccapurple b alpha r / g)", "rgba(153, 1, 102, 1)");
19577    test("rgb(from rebeccapurple r r r / r)", "rgba(102, 102, 102, 1)");
19578    test("rgb(from rebeccapurple alpha alpha alpha / alpha)", "rgb(1, 1, 1)");
19579    test("rgb(from rgb(20%, 40%, 60%, 80%) g b r)", "rgb(102, 153, 51)");
19580    test("rgb(from rgb(20%, 40%, 60%, 80%) b alpha r / g)", "rgba(153, 1, 51, 1)");
19581    test("rgb(from rgb(20%, 40%, 60%, 80%) r r r / r)", "rgba(51, 51, 51, 1)");
19582    test(
19583      "rgb(from rgb(20%, 40%, 60%, 80%) alpha alpha alpha / alpha)",
19584      "rgba(1, 1, 1, 0.8)",
19585    );
19586
19587    // Testing mixes of number and percentage. (These would not be allowed in the non-relative syntax).
19588    test("rgb(from rebeccapurple r 20% 10)", "rgb(102, 51, 10)");
19589    test("rgb(from rebeccapurple r 10 20%)", "rgb(102, 10, 51)");
19590    test("rgb(from rebeccapurple 0% 10 10)", "rgb(0, 10, 10)");
19591    test("rgb(from rgb(20%, 40%, 60%, 80%) r 20% 10)", "rgb(51, 51, 10)");
19592    test("rgb(from rgb(20%, 40%, 60%, 80%) r 10 20%)", "rgb(51, 10, 51)");
19593    test("rgb(from rgb(20%, 40%, 60%, 80%) 0% 10 10)", "rgb(0, 10, 10)");
19594
19595    // Testing with calc().
19596    test("rgb(from rebeccapurple calc(r) calc(g) calc(b))", "rgb(102, 51, 153)");
19597    test("rgb(from rebeccapurple r calc(g * 2) 10)", "rgb(102, 102, 10)");
19598    test("rgb(from rebeccapurple b calc(r * .5) 10)", "rgb(153, 51, 10)");
19599    test("rgb(from rebeccapurple r calc(g * .5 + g * .5) 10)", "rgb(102, 51, 10)");
19600    test("rgb(from rebeccapurple r calc(b * .5 - g * .5) 10)", "rgb(102, 51, 10)");
19601    test(
19602      "rgb(from rgb(20%, 40%, 60%, 80%) calc(r) calc(g) calc(b) / calc(alpha))",
19603      "rgba(51, 102, 153, 0.8)",
19604    );
19605
19606    // Testing with 'none'.
19607    test("rgb(from rebeccapurple none none none)", "rgb(0, 0, 0)");
19608    test("rgb(from rebeccapurple none none none / none)", "rgba(0, 0, 0, 0)");
19609    test("rgb(from rebeccapurple r g none)", "rgb(102, 51, 0)");
19610    test("rgb(from rebeccapurple r g none / alpha)", "rgb(102, 51, 0)");
19611    test("rgb(from rebeccapurple r g b / none)", "rgba(102, 51, 153, 0)");
19612    test(
19613      "rgb(from rgb(20% 40% 60% / 80%) r g none / alpha)",
19614      "rgba(51, 102, 0, 0.8)",
19615    );
19616    test("rgb(from rgb(20% 40% 60% / 80%) r g b / none)", "rgba(51, 102, 153, 0)");
19617    // FIXME: Clarify with spec editors if 'none' should pass through to the constants.
19618    test("rgb(from rgb(none none none) r g b)", "rgb(0, 0, 0)");
19619    test("rgb(from rgb(none none none / none) r g b / alpha)", "rgba(0, 0, 0, 0)");
19620    test("rgb(from rgb(20% none 60%) r g b)", "rgb(51, 0, 153)");
19621    test(
19622      "rgb(from rgb(20% 40% 60% / none) r g b / alpha)",
19623      "rgba(51, 102, 153, 0)",
19624    );
19625
19626    // hsl(from ...)
19627
19628    // Testing no modifications.
19629    test("hsl(from rebeccapurple h s l)", "rgb(102, 51, 153)");
19630    test("hsl(from rebeccapurple h s l / alpha)", "rgb(102, 51, 153)");
19631    test(
19632      "hsl(from rgb(20%, 40%, 60%, 80%) h s l / alpha)",
19633      "rgba(51, 102, 153, 0.8)",
19634    );
19635    test(
19636      "hsl(from hsl(120deg 20% 50% / .5) h s l / alpha)",
19637      "rgba(102, 153, 102, 0.5)",
19638    );
19639
19640    // Test nesting relative colors.
19641    test("hsl(from hsl(from rebeccapurple h s l) h s l)", "rgb(102, 51, 153)");
19642
19643    // Testing non-sRGB origin colors to see gamut mapping.
19644    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).
19645    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).
19646    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,
19647    test("hsl(from lch(100% 116 334) h s l)", "rgb(255, 255, 255)"); // Naive clip based mapping would give rgb(255, 150, 255).
19648    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,
19649    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).
19650    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).
19651    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).
19652    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).
19653
19654    // Testing replacement with 0.
19655    test("hsl(from rebeccapurple 0 0% 0%)", "rgb(0, 0, 0)");
19656    test("hsl(from rebeccapurple 0deg 0% 0%)", "rgb(0, 0, 0)");
19657    test("hsl(from rebeccapurple 0 0% 0% / 0)", "rgba(0, 0, 0, 0)");
19658    test("hsl(from rebeccapurple 0deg 0% 0% / 0)", "rgba(0, 0, 0, 0)");
19659    test("hsl(from rebeccapurple 0 s l / alpha)", "rgb(153, 51, 51)");
19660    test("hsl(from rebeccapurple 0deg s l / alpha)", "rgb(153, 51, 51)");
19661    test("hsl(from rebeccapurple h 0% l / alpha)", "rgb(102, 102, 102)");
19662    test("hsl(from rebeccapurple h s 0% / alpha)", "rgb(0, 0, 0)");
19663    test("hsl(from rebeccapurple h s l / 0)", "rgba(102, 51, 153, 0)");
19664    test(
19665      "hsl(from rgb(20%, 40%, 60%, 80%) 0 s l / alpha)",
19666      "rgba(153, 51, 51, 0.8)",
19667    );
19668    test(
19669      "hsl(from rgb(20%, 40%, 60%, 80%) 0deg s l / alpha)",
19670      "rgba(153, 51, 51, 0.8)",
19671    );
19672    test(
19673      "hsl(from rgb(20%, 40%, 60%, 80%) h 0% l / alpha)",
19674      "rgba(102, 102, 102, 0.8)",
19675    );
19676    test("hsl(from rgb(20%, 40%, 60%, 80%) h s 0% / alpha)", "rgba(0, 0, 0, 0.8)");
19677    test("hsl(from rgb(20%, 40%, 60%, 80%) h s l / 0)", "rgba(51, 102, 153, 0)");
19678
19679    // Testing replacement with a constant.
19680    test("hsl(from rebeccapurple 25 s l / alpha)", "rgb(153, 94, 51)");
19681    test("hsl(from rebeccapurple 25deg s l / alpha)", "rgb(153, 94, 51)");
19682    test("hsl(from rebeccapurple h 20% l / alpha)", "rgb(102, 82, 122)");
19683    test("hsl(from rebeccapurple h s 20% / alpha)", "rgb(51, 25, 77)");
19684    test("hsl(from rebeccapurple h s l / .25)", "rgba(102, 51, 153, 0.25)");
19685    test(
19686      "hsl(from rgb(20%, 40%, 60%, 80%) 25 s l / alpha)",
19687      "rgba(153, 94, 51, 0.8)",
19688    );
19689    test(
19690      "hsl(from rgb(20%, 40%, 60%, 80%) 25deg s l / alpha)",
19691      "rgba(153, 94, 51, 0.8)",
19692    );
19693    test(
19694      "hsl(from rgb(20%, 40%, 60%, 80%) h 20% l / alpha)",
19695      "rgba(82, 102, 122, 0.8)",
19696    );
19697    test(
19698      "hsl(from rgb(20%, 40%, 60%, 80%) h s 20% / alpha)",
19699      "rgba(25, 51, 77, 0.8)",
19700    );
19701    test(
19702      "hsl(from rgb(20%, 40%, 60%, 80%) h s l / .2)",
19703      "rgba(51, 102, 153, 0.2)",
19704    );
19705
19706    // Testing valid permutation (types match).
19707    test("hsl(from rebeccapurple h l s)", "rgb(128, 77, 179)");
19708    test(
19709      "hsl(from rebeccapurple h calc(alpha * 100) l / calc(s / 100))",
19710      "rgba(102, 0, 204, 0.5)",
19711    );
19712    test(
19713      "hsl(from rebeccapurple h l l / calc(l / 100))",
19714      "rgba(102, 61, 143, 0.4)",
19715    );
19716    test(
19717      "hsl(from rebeccapurple h calc(alpha * 100) calc(alpha * 100) / calc(alpha * 100))",
19718      "rgb(255, 255, 255)",
19719    );
19720    test("hsl(from rgb(20%, 40%, 60%, 80%) h l s)", "rgb(77, 128, 179)");
19721    test(
19722      "hsl(from rgb(20%, 40%, 60%, 80%) h calc(alpha * 100) l / calc(s / 100))",
19723      "rgba(20, 102, 184, 0.5)",
19724    );
19725    test(
19726      "hsl(from rgb(20%, 40%, 60%, 80%) h l l / calc(l / 100))",
19727      "rgba(61, 102, 143, 0.4)",
19728    );
19729    test(
19730      "hsl(from rgb(20%, 40%, 60%, 80%) h calc(alpha * 100) calc(alpha * 100) / alpha)",
19731      "rgba(163, 204, 245, 0.8)",
19732    );
19733
19734    // Testing with calc().
19735    test("hsl(from rebeccapurple calc(h) calc(s) calc(l))", "rgb(102, 51, 153)");
19736    test(
19737      "hsl(from rgb(20%, 40%, 60%, 80%) calc(h) calc(s) calc(l) / calc(alpha))",
19738      "rgba(51, 102, 153, 0.8)",
19739    );
19740
19741    // Testing with 'none'.
19742    test("hsl(from rebeccapurple none none none)", "rgb(0, 0, 0)");
19743    test("hsl(from rebeccapurple none none none / none)", "rgba(0, 0, 0, 0)");
19744    test("hsl(from rebeccapurple h s none)", "rgb(0, 0, 0)");
19745    test("hsl(from rebeccapurple h s none / alpha)", "rgb(0, 0, 0)");
19746    test("hsl(from rebeccapurple h s l / none)", "rgba(102, 51, 153, 0)");
19747    test("hsl(from rebeccapurple none s l / alpha)", "rgb(153, 51, 51)");
19748    test(
19749      "hsl(from hsl(120deg 20% 50% / .5) h s none / alpha)",
19750      "rgba(0, 0, 0, 0.5)",
19751    );
19752    test(
19753      "hsl(from hsl(120deg 20% 50% / .5) h s l / none)",
19754      "rgba(102, 153, 102, 0)",
19755    );
19756    test(
19757      "hsl(from hsl(120deg 20% 50% / .5) none s l / alpha)",
19758      "rgba(153, 102, 102, 0.5)",
19759    );
19760    // FIXME: Clarify with spec editors if 'none' should pass through to the constants.
19761    test("hsl(from hsl(none none none) h s l)", "rgb(0, 0, 0)");
19762    test("hsl(from hsl(none none none / none) h s l / alpha)", "rgba(0, 0, 0, 0)");
19763    test("hsl(from hsl(120deg none 50% / .5) h s l)", "rgb(128, 128, 128)");
19764    test(
19765      "hsl(from hsl(120deg 20% 50% / none) h s l / alpha)",
19766      "rgba(102, 153, 102, 0)",
19767    );
19768    test(
19769      "hsl(from hsl(none 20% 50% / .5) h s l / alpha)",
19770      "rgba(153, 102, 102, 0.5)",
19771    );
19772
19773    // hwb(from ...)
19774
19775    // Testing no modifications.
19776    test("hwb(from rebeccapurple h w b)", "rgb(102, 51, 153)");
19777    test("hwb(from rebeccapurple h w b / alpha)", "rgb(102, 51, 153)");
19778    test(
19779      "hwb(from rgb(20%, 40%, 60%, 80%) h w b / alpha)",
19780      "rgba(51, 102, 153, 0.8)",
19781    );
19782    test(
19783      "hwb(from hsl(120deg 20% 50% / .5) h w b / alpha)",
19784      "rgba(102, 153, 102, 0.5)",
19785    );
19786
19787    // Test nesting relative colors.
19788    test("hwb(from hwb(from rebeccapurple h w b) h w b)", "rgb(102, 51, 153)");
19789
19790    // Testing non-sRGB origin colors to see gamut mapping.
19791    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).
19792    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).
19793    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,
19794    test("hwb(from lch(100% 116 334) h w b)", "rgb(255, 255, 255)"); // Naive clip based mapping would give rgb(255, 150, 255).
19795    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,
19796    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).
19797    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).
19798    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).
19799    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).
19800
19801    // Testing replacement with 0.
19802    test("hwb(from rebeccapurple 0 0% 0%)", "rgb(255, 0, 0)");
19803    test("hwb(from rebeccapurple 0deg 0% 0%)", "rgb(255, 0, 0)");
19804    test("hwb(from rebeccapurple 0 0% 0% / 0)", "rgba(255, 0, 0, 0)");
19805    test("hwb(from rebeccapurple 0deg 0% 0% / 0)", "rgba(255, 0, 0, 0)");
19806    test("hwb(from rebeccapurple 0 w b / alpha)", "rgb(153, 51, 51)");
19807    test("hwb(from rebeccapurple 0deg w b / alpha)", "rgb(153, 51, 51)");
19808    test("hwb(from rebeccapurple h 0% b / alpha)", "rgb(77, 0, 153)");
19809    test("hwb(from rebeccapurple h w 0% / alpha)", "rgb(153, 51, 255)");
19810    test("hwb(from rebeccapurple h w b / 0)", "rgba(102, 51, 153, 0)");
19811    test(
19812      "hwb(from rgb(20%, 40%, 60%, 80%) 0 w b / alpha)",
19813      "rgba(153, 51, 51, 0.8)",
19814    );
19815    test(
19816      "hwb(from rgb(20%, 40%, 60%, 80%) 0deg w b / alpha)",
19817      "rgba(153, 51, 51, 0.8)",
19818    );
19819    test(
19820      "hwb(from rgb(20%, 40%, 60%, 80%) h 0% b / alpha)",
19821      "rgba(0, 77, 153, 0.8)",
19822    );
19823    test(
19824      "hwb(from rgb(20%, 40%, 60%, 80%) h w 0% / alpha)",
19825      "rgba(51, 153, 255, 0.8)",
19826    );
19827    test("hwb(from rgb(20%, 40%, 60%, 80%) h w b / 0)", "rgba(51, 102, 153, 0)");
19828
19829    // Testing replacement with a constant.
19830    test("hwb(from rebeccapurple 25 w b / alpha)", "rgb(153, 94, 51)");
19831    test("hwb(from rebeccapurple 25deg w b / alpha)", "rgb(153, 94, 51)");
19832    test("hwb(from rebeccapurple h 20% b / alpha)", "rgb(102, 51, 153)");
19833    test("hwb(from rebeccapurple h w 20% / alpha)", "rgb(128, 51, 204)");
19834    test("hwb(from rebeccapurple h w b / .2)", "rgba(102, 51, 153, 0.2)");
19835    test(
19836      "hwb(from rgb(20%, 40%, 60%, 80%) 25 w b / alpha)",
19837      "rgba(153, 94, 51, 0.8)",
19838    );
19839    test(
19840      "hwb(from rgb(20%, 40%, 60%, 80%) 25deg w b / alpha)",
19841      "rgba(153, 94, 51, 0.8)",
19842    );
19843    test(
19844      "hwb(from rgb(20%, 40%, 60%, 80%) h 20% b / alpha)",
19845      "rgba(51, 102, 153, 0.8)",
19846    );
19847    test(
19848      "hwb(from rgb(20%, 40%, 60%, 80%) h w 20% / alpha)",
19849      "rgba(51, 128, 204, 0.8)",
19850    );
19851    test(
19852      "hwb(from rgb(20%, 40%, 60%, 80%) h w b / .2)",
19853      "rgba(51, 102, 153, 0.2)",
19854    );
19855
19856    // Testing valid permutation (types match).
19857    test("hwb(from rebeccapurple h b w)", "rgb(153, 102, 204)");
19858    test(
19859      "hwb(from rebeccapurple h calc(alpha * 100) w / calc(b / 100))",
19860      "rgba(213, 213, 213, 0.4)",
19861    );
19862    test(
19863      "hwb(from rebeccapurple h w w / calc(w / 100))",
19864      "rgba(128, 51, 204, 0.2)",
19865    );
19866    test(
19867      "hwb(from rebeccapurple h calc(alpha * 100) calc(alpha * 100) / alpha)",
19868      "rgb(128, 128, 128)",
19869    );
19870    test("hwb(from rgb(20%, 40%, 60%, 80%) h b w)", "rgb(102, 153, 204)");
19871    test(
19872      "hwb(from rgb(20%, 40%, 60%, 80%) h calc(alpha * 100) w / calc(b / 100))",
19873      "rgba(204, 204, 204, 0.4)",
19874    );
19875    test(
19876      "hwb(from rgb(20%, 40%, 60%, 80%) h w w / calc(w / 100))",
19877      "rgba(51, 128, 204, 0.2)",
19878    );
19879    test(
19880      "hwb(from rgb(20%, 40%, 60%, 80%) h calc(alpha * 100) calc(alpha * 100) / alpha)",
19881      "rgba(128, 128, 128, 0.8)",
19882    );
19883
19884    // Testing with calc().
19885    test("hwb(from rebeccapurple calc(h) calc(w) calc(b))", "rgb(102, 51, 153)");
19886    test(
19887      "hwb(from rgb(20%, 40%, 60%, 80%) calc(h) calc(w) calc(b) / calc(alpha))",
19888      "rgba(51, 102, 153, 0.8)",
19889    );
19890
19891    // Testing with 'none'.
19892    test("hwb(from rebeccapurple none none none)", "rgb(255, 0, 0)");
19893    test("hwb(from rebeccapurple none none none / none)", "rgba(255, 0, 0, 0)");
19894    test("hwb(from rebeccapurple h w none)", "rgb(153, 51, 255)");
19895    test("hwb(from rebeccapurple h w none / alpha)", "rgb(153, 51, 255)");
19896    test("hwb(from rebeccapurple h w b / none)", "rgba(102, 51, 153, 0)");
19897    test("hwb(from rebeccapurple none w b / alpha)", "rgb(153, 51, 51)");
19898    test(
19899      "hwb(from hwb(120deg 20% 50% / .5) h w none / alpha)",
19900      "rgba(51, 255, 51, 0.5)",
19901    );
19902    test(
19903      "hwb(from hwb(120deg 20% 50% / .5) h w b / none)",
19904      "rgba(51, 128, 51, 0)",
19905    );
19906    test(
19907      "hwb(from hwb(120deg 20% 50% / .5) none w b / alpha)",
19908      "rgba(128, 51, 51, 0.5)",
19909    );
19910    // FIXME: Clarify with spec editors if 'none' should pass through to the constants.
19911    test("hwb(from hwb(none none none) h w b)", "rgb(255, 0, 0)");
19912    test(
19913      "hwb(from hwb(none none none / none) h w b / alpha)",
19914      "rgba(255, 0, 0, 0)",
19915    );
19916    test("hwb(from hwb(120deg none 50% / .5) h w b)", "rgb(0, 128, 0)");
19917    test(
19918      "hwb(from hwb(120deg 20% 50% / none) h w b / alpha)",
19919      "rgba(51, 128, 51, 0)",
19920    );
19921    test(
19922      "hwb(from hwb(none 20% 50% / .5) h w b / alpha)",
19923      "rgba(128, 51, 51, 0.5)",
19924    );
19925
19926    for color_space in &["lab", "oklab"] {
19927      // Testing no modifications.
19928      test(
19929        &format!("{}(from {}(25% 20 50) l a b)", color_space, color_space),
19930        &format!("{}(25% 20 50)", color_space),
19931      );
19932      test(
19933        &format!("{}(from {}(25% 20 50) l a b / alpha)", color_space, color_space),
19934        &format!("{}(25% 20 50)", color_space),
19935      );
19936      test(
19937        &format!("{}(from {}(25% 20 50 / 40%) l a b / alpha)", color_space, color_space),
19938        &format!("{}(25% 20 50 / 0.4)", color_space),
19939      );
19940      test(
19941        &format!(
19942          "{}(from {}(200% 300 400 / 500%) l a b / alpha)",
19943          color_space, color_space
19944        ),
19945        &format!("{}(200% 300 400)", color_space),
19946      );
19947      test(
19948        &format!(
19949          "{}(from {}(-200% -300 -400 / -500%) l a b / alpha)",
19950          color_space, color_space
19951        ),
19952        &format!("{}(0% -300 -400 / 0)", color_space),
19953      );
19954
19955      // Test nesting relative colors.
19956      test(
19957        &format!(
19958          "{}(from {}(from {}(25% 20 50) l a b) l a b)",
19959          color_space, color_space, color_space
19960        ),
19961        &format!("{}(25% 20 50)", color_space),
19962      );
19963
19964      // Testing non-${colorSpace} origin to see conversion.
19965      test(
19966        &format!("{}(from color(display-p3 0 0 0) l a b / alpha)", color_space),
19967        &format!("{}(0% 0 0)", color_space),
19968      );
19969
19970      // Testing replacement with 0.
19971      test(
19972        &format!("{}(from {}(25% 20 50) 0% 0 0)", color_space, color_space),
19973        &format!("{}(0% 0 0)", color_space),
19974      );
19975      test(
19976        &format!("{}(from {}(25% 20 50) 0% 0 0 / 0)", color_space, color_space),
19977        &format!("{}(0% 0 0 / 0)", color_space),
19978      );
19979      test(
19980        &format!("{}(from {}(25% 20 50) 0% a b / alpha)", color_space, color_space),
19981        &format!("{}(0% 20 50)", color_space),
19982      );
19983      test(
19984        &format!("{}(from {}(25% 20 50) l 0 b / alpha)", color_space, color_space),
19985        &format!("{}(25% 0 50)", color_space),
19986      );
19987      test(
19988        &format!("{}(from {}(25% 20 50) l a 0 / alpha)", color_space, color_space),
19989        &format!("{}(25% 20 0)", color_space),
19990      );
19991      test(
19992        &format!("{}(from {}(25% 20 50) l a b / 0)", color_space, color_space),
19993        &format!("{}(25% 20 50 / 0)", color_space),
19994      );
19995      test(
19996        &format!("{}(from {}(25% 20 50 / 40%) 0% a b / alpha)", color_space, color_space),
19997        &format!("{}(0% 20 50 / 0.4)", color_space),
19998      );
19999      test(
20000        &format!("{}(from {}(25% 20 50 / 40%) l 0 b / alpha)", color_space, color_space),
20001        &format!("{}(25% 0 50 / 0.4)", color_space),
20002      );
20003      test(
20004        &format!("{}(from {}(25% 20 50 / 40%) l a 0 / alpha)", color_space, color_space),
20005        &format!("{}(25% 20 0 / 0.4)", color_space),
20006      );
20007      test(
20008        &format!("{}(from {}(25% 20 50 / 40%) l a b / 0)", color_space, color_space),
20009        &format!("{}(25% 20 50 / 0)", color_space),
20010      );
20011
20012      // Testing replacement with a constant.
20013      test(
20014        &format!("{}(from {}(25% 20 50) 35% a b / alpha)", color_space, color_space),
20015        &format!("{}(35% 20 50)", color_space),
20016      );
20017      test(
20018        &format!("{}(from {}(25% 20 50) l 35 b / alpha)", color_space, color_space),
20019        &format!("{}(25% 35 50)", color_space),
20020      );
20021      test(
20022        &format!("{}(from {}(25% 20 50) l a 35 / alpha)", color_space, color_space),
20023        &format!("{}(25% 20 35)", color_space),
20024      );
20025      test(
20026        &format!("{}(from {}(25% 20 50) l a b / .35)", color_space, color_space),
20027        &format!("{}(25% 20 50 / 0.35)", color_space),
20028      );
20029      test(
20030        &format!("{}(from {}(25% 20 50 / 40%) 35% a b / alpha)", color_space, color_space),
20031        &format!("{}(35% 20 50 / 0.4)", color_space),
20032      );
20033      test(
20034        &format!("{}(from {}(25% 20 50 / 40%) l 35 b / alpha)", color_space, color_space),
20035        &format!("{}(25% 35 50 / 0.4)", color_space),
20036      );
20037      test(
20038        &format!("{}(from {}(25% 20 50 / 40%) l a 35 / alpha)", color_space, color_space),
20039        &format!("{}(25% 20 35 / 0.4)", color_space),
20040      );
20041      test(
20042        &format!("{}(from {}(25% 20 50 / 40%) l a b / .35)", color_space, color_space),
20043        &format!("{}(25% 20 50 / 0.35)", color_space),
20044      );
20045      test(
20046        &format!(
20047          "{}(from {}(70% 45 30 / 40%) 200% 300 400 / 500)",
20048          color_space, color_space
20049        ),
20050        &format!("{}(200% 300 400)", color_space),
20051      );
20052      test(
20053        &format!(
20054          "{}(from {}(70% 45 30 / 40%) -200% -300 -400 / -500)",
20055          color_space, color_space
20056        ),
20057        &format!("{}(0% -300 -400 / 0)", color_space),
20058      );
20059
20060      // Testing valid permutation (types match).
20061      test(
20062        &format!("{}(from {}(25% 20 50) l b a)", color_space, color_space),
20063        &format!("{}(25% 50 20)", color_space),
20064      );
20065      test(
20066        &format!("{}(from {}(25% 20 50) l a a / a)", color_space, color_space),
20067        &format!("{}(25% 20 20)", color_space),
20068      );
20069      test(
20070        &format!("{}(from {}(25% 20 50 / 40%) l b a)", color_space, color_space),
20071        &format!("{}(25% 50 20)", color_space),
20072      );
20073      test(
20074        &format!("{}(from {}(25% 20 50 / 40%) l a a / a)", color_space, color_space),
20075        &format!("{}(25% 20 20)", color_space),
20076      );
20077
20078      // Testing with calc().
20079      test(
20080        &format!(
20081          "{}(from {}(25% 20 50) calc(l) calc(a) calc(b))",
20082          color_space, color_space
20083        ),
20084        &format!("{}(25% 20 50)", color_space),
20085      );
20086      test(
20087        &format!(
20088          "{}(from {}(25% 20 50 / 40%) calc(l) calc(a) calc(b) / calc(alpha))",
20089          color_space, color_space
20090        ),
20091        &format!("{}(25% 20 50 / 0.4)", color_space),
20092      );
20093
20094      // Testing with 'none'.
20095      test(
20096        &format!("{}(from {}(25% 20 50) none none none)", color_space, color_space),
20097        &format!("{}(none none none)", color_space),
20098      );
20099      test(
20100        &format!("{}(from {}(25% 20 50) none none none / none)", color_space, color_space),
20101        &format!("{}(none none none / none)", color_space),
20102      );
20103      test(
20104        &format!("{}(from {}(25% 20 50) l a none)", color_space, color_space),
20105        &format!("{}(25% 20 none)", color_space),
20106      );
20107      test(
20108        &format!("{}(from {}(25% 20 50) l a none / alpha)", color_space, color_space),
20109        &format!("{}(25% 20 none)", color_space),
20110      );
20111      test(
20112        &format!("{}(from {}(25% 20 50) l a b / none)", color_space, color_space),
20113        &format!("{}(25% 20 50 / none)", color_space),
20114      );
20115      test(
20116        &format!(
20117          "{}(from {}(25% 20 50 / 40%) l a none / alpha)",
20118          color_space, color_space
20119        ),
20120        &format!("{}(25% 20 none / 0.4)", color_space),
20121      );
20122      test(
20123        &format!("{}(from {}(25% 20 50 / 40%) l a b / none)", color_space, color_space),
20124        &format!("{}(25% 20 50 / none)", color_space),
20125      );
20126      // FIXME: Clarify with spec editors if 'none' should pass through to the constants.
20127      test(
20128        &format!("{}(from {}(none none none) l a b)", color_space, color_space),
20129        &format!("{}(0% 0 0)", color_space),
20130      );
20131      test(
20132        &format!(
20133          "{}(from {}(none none none / none) l a b / alpha)",
20134          color_space, color_space
20135        ),
20136        &format!("{}(0% 0 0 / 0)", color_space),
20137      );
20138      test(
20139        &format!("{}(from {}(25% none 50) l a b)", color_space, color_space),
20140        &format!("{}(25% 0 50)", color_space),
20141      );
20142      test(
20143        &format!("{}(from {}(25% 20 50 / none) l a b / alpha)", color_space, color_space),
20144        &format!("{}(25% 20 50 / 0)", color_space),
20145      );
20146    }
20147
20148    // test_valid_value\(`color`, `\$\{colorSpace\}\(from \$\{colorSpace\}\((.*?)`,\s*`\$\{colorSpace\}(.*?)`\)
20149    // test(&format!("{}(from {}($1", color_space, color_space), &format!("{}$2", color_space))
20150
20151    for color_space in &["lch", "oklch"] {
20152      // Testing no modifications.
20153      test(
20154        &format!("{}(from {}(70% 45 30) l c h)", color_space, color_space),
20155        &format!("{}(70% 45 30)", color_space),
20156      );
20157      test(
20158        &format!("{}(from {}(70% 45 30) l c h / alpha)", color_space, color_space),
20159        &format!("{}(70% 45 30)", color_space),
20160      );
20161      test(
20162        &format!("{}(from {}(70% 45 30 / 40%) l c h / alpha)", color_space, color_space),
20163        &format!("{}(70% 45 30 / 0.4)", color_space),
20164      );
20165      test(
20166        &format!(
20167          "{}(from {}(200% 300 400 / 500%) l c h / alpha)",
20168          color_space, color_space
20169        ),
20170        &format!("{}(200% 300 40)", color_space),
20171      );
20172      test(
20173        &format!(
20174          "{}(from {}(-200% -300 -400 / -500%) l c h / alpha)",
20175          color_space, color_space
20176        ),
20177        &format!("{}(0% 0 320 / 0)", color_space),
20178      );
20179
20180      // Test nesting relative colors.
20181      test(
20182        &format!(
20183          "{}(from {}(from {}(70% 45 30) l c h) l c h)",
20184          color_space, color_space, color_space
20185        ),
20186        &format!("{}(70% 45 30)", color_space),
20187      );
20188
20189      // Testing non-sRGB origin colors (no gamut mapping will happen since the destination is not a bounded RGB color space).
20190      test(
20191        &format!("{}(from color(display-p3 0 0 0) l c h / alpha)", color_space),
20192        &format!("{}(0% 0 0)", color_space),
20193      );
20194
20195      // Testing replacement with 0.
20196      test(
20197        &format!("{}(from {}(70% 45 30) 0% 0 0)", color_space, color_space),
20198        &format!("{}(0% 0 0)", color_space),
20199      );
20200      test(
20201        &format!("{}(from {}(70% 45 30) 0% 0 0deg)", color_space, color_space),
20202        &format!("{}(0% 0 0)", color_space),
20203      );
20204      test(
20205        &format!("{}(from {}(70% 45 30) 0% 0 0 / 0)", color_space, color_space),
20206        &format!("{}(0% 0 0 / 0)", color_space),
20207      );
20208      test(
20209        &format!("{}(from {}(70% 45 30) 0% 0 0deg / 0)", color_space, color_space),
20210        &format!("{}(0% 0 0 / 0)", color_space),
20211      );
20212      test(
20213        &format!("{}(from {}(70% 45 30) 0% c h / alpha)", color_space, color_space),
20214        &format!("{}(0% 45 30)", color_space),
20215      );
20216      test(
20217        &format!("{}(from {}(70% 45 30) l 0 h / alpha)", color_space, color_space),
20218        &format!("{}(70% 0 30)", color_space),
20219      );
20220      test(
20221        &format!("{}(from {}(70% 45 30) l c 0 / alpha)", color_space, color_space),
20222        &format!("{}(70% 45 0)", color_space),
20223      );
20224      test(
20225        &format!("{}(from {}(70% 45 30) l c 0deg / alpha)", color_space, color_space),
20226        &format!("{}(70% 45 0)", color_space),
20227      );
20228      test(
20229        &format!("{}(from {}(70% 45 30) l c h / 0)", color_space, color_space),
20230        &format!("{}(70% 45 30 / 0)", color_space),
20231      );
20232      test(
20233        &format!("{}(from {}(70% 45 30 / 40%) 0% c h / alpha)", color_space, color_space),
20234        &format!("{}(0% 45 30 / 0.4)", color_space),
20235      );
20236      test(
20237        &format!("{}(from {}(70% 45 30 / 40%) l 0 h / alpha)", color_space, color_space),
20238        &format!("{}(70% 0 30 / 0.4)", color_space),
20239      );
20240      test(
20241        &format!("{}(from {}(70% 45 30 / 40%) l c 0 / alpha)", color_space, color_space),
20242        &format!("{}(70% 45 0 / 0.4)", color_space),
20243      );
20244      test(
20245        &format!(
20246          "{}(from {}(70% 45 30 / 40%) l c 0deg / alpha)",
20247          color_space, color_space
20248        ),
20249        &format!("{}(70% 45 0 / 0.4)", color_space),
20250      );
20251      test(
20252        &format!("{}(from {}(70% 45 30 / 40%) l c h / 0)", color_space, color_space),
20253        &format!("{}(70% 45 30 / 0)", color_space),
20254      );
20255
20256      // Testing replacement with a constant.
20257      test(
20258        &format!("{}(from {}(70% 45 30) 25% c h / alpha)", color_space, color_space),
20259        &format!("{}(25% 45 30)", color_space),
20260      );
20261      test(
20262        &format!("{}(from {}(70% 45 30) l 25 h / alpha)", color_space, color_space),
20263        &format!("{}(70% 25 30)", color_space),
20264      );
20265      test(
20266        &format!("{}(from {}(70% 45 30) l c 25 / alpha)", color_space, color_space),
20267        &format!("{}(70% 45 25)", color_space),
20268      );
20269      test(
20270        &format!("{}(from {}(70% 45 30) l c 25deg / alpha)", color_space, color_space),
20271        &format!("{}(70% 45 25)", color_space),
20272      );
20273      test(
20274        &format!("{}(from {}(70% 45 30) l c h / .25)", color_space, color_space),
20275        &format!("{}(70% 45 30 / 0.25)", color_space),
20276      );
20277      test(
20278        &format!("{}(from {}(70% 45 30 / 40%) 25% c h / alpha)", color_space, color_space),
20279        &format!("{}(25% 45 30 / 0.4)", color_space),
20280      );
20281      test(
20282        &format!("{}(from {}(70% 45 30 / 40%) l 25 h / alpha)", color_space, color_space),
20283        &format!("{}(70% 25 30 / 0.4)", color_space),
20284      );
20285      test(
20286        &format!("{}(from {}(70% 45 30 / 40%) l c 25 / alpha)", color_space, color_space),
20287        &format!("{}(70% 45 25 / 0.4)", color_space),
20288      );
20289      test(
20290        &format!(
20291          "{}(from {}(70% 45 30 / 40%) l c 25deg / alpha)",
20292          color_space, color_space
20293        ),
20294        &format!("{}(70% 45 25 / 0.4)", color_space),
20295      );
20296      test(
20297        &format!("{}(from {}(70% 45 30 / 40%) l c h / .25)", color_space, color_space),
20298        &format!("{}(70% 45 30 / 0.25)", color_space),
20299      );
20300      test(
20301        &format!(
20302          "{}(from {}(70% 45 30 / 40%) 200% 300 400 / 500)",
20303          color_space, color_space
20304        ),
20305        &format!("{}(200% 300 400)", color_space),
20306      );
20307      test(
20308        &format!(
20309          "{}(from {}(70% 45 30 / 40%) -200% -300 -400 / -500)",
20310          color_space, color_space
20311        ),
20312        &format!("{}(0% 0 -400 / 0)", color_space),
20313      );
20314      test(
20315        &format!(
20316          "{}(from {}(70% 45 30 / 40%) 50% 120 400deg / 500)",
20317          color_space, color_space
20318        ),
20319        &format!("{}(50% 120 400)", color_space),
20320      );
20321      test(
20322        &format!(
20323          "{}(from {}(70% 45 30 / 40%) 50% 120 -400deg / -500)",
20324          color_space, color_space
20325        ),
20326        &format!("{}(50% 120 -400 / 0)", color_space),
20327      );
20328
20329      // Testing valid permutation (types match).
20330      // NOTE: 'c' is a valid hue, as hue is <angle>|<number>.
20331      test(
20332        &format!("{}(from {}(70% 45 30) alpha c h / l)", color_space, color_space),
20333        &format!(
20334          "{}(1 45 30 / {})",
20335          color_space,
20336          if *color_space == "lch" { "1" } else { ".7" }
20337        ),
20338      );
20339      test(
20340        &format!("{}(from {}(70% 45 30) l c c / alpha)", color_space, color_space),
20341        &format!("{}(70% 45 45)", color_space),
20342      );
20343      test(
20344        &format!("{}(from {}(70% 45 30) alpha c h / alpha)", color_space, color_space),
20345        &format!("{}(1 45 30)", color_space),
20346      );
20347      test(
20348        &format!("{}(from {}(70% 45 30) alpha c c / alpha)", color_space, color_space),
20349        &format!("{}(1 45 45)", color_space),
20350      );
20351      test(
20352        &format!("{}(from {}(70% 45 30 / 40%) alpha c h / l)", color_space, color_space),
20353        &format!(
20354          "{}(.4 45 30 / {})",
20355          color_space,
20356          if *color_space == "lch" { "1" } else { ".7" }
20357        ),
20358      );
20359      test(
20360        &format!("{}(from {}(70% 45 30 / 40%) l c c / alpha)", color_space, color_space),
20361        &format!("{}(70% 45 45 / 0.4)", color_space),
20362      );
20363      test(
20364        &format!(
20365          "{}(from {}(70% 45 30 / 40%) alpha c h / alpha)",
20366          color_space, color_space
20367        ),
20368        &format!("{}(.4 45 30 / 0.4)", color_space),
20369      );
20370      test(
20371        &format!(
20372          "{}(from {}(70% 45 30 / 40%) alpha c c / alpha)",
20373          color_space, color_space
20374        ),
20375        &format!("{}(.4 45 45 / 0.4)", color_space),
20376      );
20377
20378      // Testing with calc().
20379      test(
20380        &format!(
20381          "{}(from {}(70% 45 30) calc(l) calc(c) calc(h))",
20382          color_space, color_space
20383        ),
20384        &format!("{}(70% 45 30)", color_space),
20385      );
20386      test(
20387        &format!(
20388          "{}(from {}(70% 45 30 / 40%) calc(l) calc(c) calc(h) / calc(alpha))",
20389          color_space, color_space
20390        ),
20391        &format!("{}(70% 45 30 / 0.4)", color_space),
20392      );
20393
20394      // Testing with 'none'.
20395      test(
20396        &format!("{}(from {}(70% 45 30) none none none)", color_space, color_space),
20397        &format!("{}(none none none)", color_space),
20398      );
20399      test(
20400        &format!("{}(from {}(70% 45 30) none none none / none)", color_space, color_space),
20401        &format!("{}(none none none / none)", color_space),
20402      );
20403      test(
20404        &format!("{}(from {}(70% 45 30) l c none)", color_space, color_space),
20405        &format!("{}(70% 45 none)", color_space),
20406      );
20407      test(
20408        &format!("{}(from {}(70% 45 30) l c none / alpha)", color_space, color_space),
20409        &format!("{}(70% 45 none)", color_space),
20410      );
20411      test(
20412        &format!("{}(from {}(70% 45 30) l c h / none)", color_space, color_space),
20413        &format!("{}(70% 45 30 / none)", color_space),
20414      );
20415      test(
20416        &format!(
20417          "{}(from {}(70% 45 30 / 40%) l c none / alpha)",
20418          color_space, color_space
20419        ),
20420        &format!("{}(70% 45 none / 0.4)", color_space),
20421      );
20422      test(
20423        &format!("{}(from {}(70% 45 30 / 40%) l c h / none)", color_space, color_space),
20424        &format!("{}(70% 45 30 / none)", color_space),
20425      );
20426      // FIXME: Clarify with spec editors if 'none' should pass through to the constants.
20427      test(
20428        &format!("{}(from {}(none none none) l c h)", color_space, color_space),
20429        &format!("{}(0% 0 0)", color_space),
20430      );
20431      test(
20432        &format!(
20433          "{}(from {}(none none none / none) l c h / alpha)",
20434          color_space, color_space
20435        ),
20436        &format!("{}(0% 0 0 / 0)", color_space),
20437      );
20438      test(
20439        &format!("{}(from {}(70% none 30) l c h)", color_space, color_space),
20440        &format!("{}(70% 0 30)", color_space),
20441      );
20442      test(
20443        &format!("{}(from {}(70% 45 30 / none) l c h / alpha)", color_space, color_space),
20444        &format!("{}(70% 45 30 / 0)", color_space),
20445      );
20446    }
20447
20448    // test_valid_value\(`color`, `color\(from color\(\$\{colorSpace\}(.*?) \$\{colorSpace\}(.*?)`,\s*`color\(\$\{colorSpace\}(.*?)`\)
20449    // test(&format!("color(from color({}$1 {}$2", color_space, color_space), &format!("color({}$3", color_space))
20450
20451    for color_space in &["srgb", "srgb-linear", "a98-rgb", "rec2020", "prophoto-rgb"] {
20452      // Testing no modifications.
20453      test(
20454        &format!("color(from color({} 0.7 0.5 0.3) {} r g b)", color_space, color_space),
20455        &format!("color({} 0.7 0.5 0.3)", color_space),
20456      );
20457      test(
20458        &format!(
20459          "color(from color({} 0.7 0.5 0.3) {} r g b / alpha)",
20460          color_space, color_space
20461        ),
20462        &format!("color({} 0.7 0.5 0.3)", color_space),
20463      );
20464      test(
20465        &format!(
20466          "color(from color({} 0.7 0.5 0.3 / 40%) {} r g b)",
20467          color_space, color_space
20468        ),
20469        &format!("color({} 0.7 0.5 0.3)", color_space),
20470      );
20471      test(
20472        &format!(
20473          "color(from color({} 0.7 0.5 0.3 / 40%) {} r g b / alpha)",
20474          color_space, color_space
20475        ),
20476        &format!("color({} 0.7 0.5 0.3 / 0.4)", color_space),
20477      );
20478
20479      // Test nesting relative colors.
20480      test(
20481        &format!(
20482          "color(from color(from color({} 0.7 0.5 0.3) {} r g b) {} r g b)",
20483          color_space, color_space, color_space
20484        ),
20485        &format!("color({} 0.7 0.5 0.3)", color_space),
20486      );
20487
20488      // Testing replacement with 0.
20489      test(
20490        &format!("color(from color({} 0.7 0.5 0.3) {} 0 0 0)", color_space, color_space),
20491        &format!("color({} 0 0 0)", color_space),
20492      );
20493      test(
20494        &format!(
20495          "color(from color({} 0.7 0.5 0.3) {} 0 0 0 / 0)",
20496          color_space, color_space
20497        ),
20498        &format!("color({} 0 0 0 / 0)", color_space),
20499      );
20500      test(
20501        &format!(
20502          "color(from color({} 0.7 0.5 0.3) {} 0 g b / alpha)",
20503          color_space, color_space
20504        ),
20505        &format!("color({} 0 0.5 0.3)", color_space),
20506      );
20507      test(
20508        &format!(
20509          "color(from color({} 0.7 0.5 0.3) {} r 0 b / alpha)",
20510          color_space, color_space
20511        ),
20512        &format!("color({} 0.7 0 0.3)", color_space),
20513      );
20514      test(
20515        &format!(
20516          "color(from color({} 0.7 0.5 0.3) {} r g 0 / alpha)",
20517          color_space, color_space
20518        ),
20519        &format!("color({} 0.7 0.5 0)", color_space),
20520      );
20521      test(
20522        &format!(
20523          "color(from color({} 0.7 0.5 0.3) {} r g b / 0)",
20524          color_space, color_space
20525        ),
20526        &format!("color({} 0.7 0.5 0.3 / 0)", color_space),
20527      );
20528      test(
20529        &format!(
20530          "color(from color({} 0.7 0.5 0.3 / 40%) {} 0 g b / alpha)",
20531          color_space, color_space
20532        ),
20533        &format!("color({} 0 0.5 0.3 / 0.4)", color_space),
20534      );
20535      test(
20536        &format!(
20537          "color(from color({} 0.7 0.5 0.3 / 40%) {} r 0 b / alpha)",
20538          color_space, color_space
20539        ),
20540        &format!("color({} 0.7 0 0.3 / 0.4)", color_space),
20541      );
20542      test(
20543        &format!(
20544          "color(from color({} 0.7 0.5 0.3 / 40%) {} r g 0 / alpha)",
20545          color_space, color_space
20546        ),
20547        &format!("color({} 0.7 0.5 0 / 0.4)", color_space),
20548      );
20549      test(
20550        &format!(
20551          "color(from color({} 0.7 0.5 0.3 / 40%) {} r g b / 0)",
20552          color_space, color_space
20553        ),
20554        &format!("color({} 0.7 0.5 0.3 / 0)", color_space),
20555      );
20556
20557      // Testing replacement with a constant.
20558      test(
20559        &format!(
20560          "color(from color({} 0.7 0.5 0.3) {} 0.2 g b / alpha)",
20561          color_space, color_space
20562        ),
20563        &format!("color({} 0.2 0.5 0.3)", color_space),
20564      );
20565      test(
20566        &format!(
20567          "color(from color({} 0.7 0.5 0.3) {} 20% g b / alpha)",
20568          color_space, color_space
20569        ),
20570        &format!("color({} 0.2 0.5 0.3)", color_space),
20571      );
20572      test(
20573        &format!(
20574          "color(from color({} 0.7 0.5 0.3) {} r 0.2 b / alpha)",
20575          color_space, color_space
20576        ),
20577        &format!("color({} 0.7 0.2 0.3)", color_space),
20578      );
20579      test(
20580        &format!(
20581          "color(from color({} 0.7 0.5 0.3) {} r 20% b / alpha)",
20582          color_space, color_space
20583        ),
20584        &format!("color({} 0.7 0.2 0.3)", color_space),
20585      );
20586      test(
20587        &format!(
20588          "color(from color({} 0.7 0.5 0.3) {} r g 0.2 / alpha)",
20589          color_space, color_space
20590        ),
20591        &format!("color({} 0.7 0.5 0.2)", color_space),
20592      );
20593      test(
20594        &format!(
20595          "color(from color({} 0.7 0.5 0.3) {} r g 20% / alpha)",
20596          color_space, color_space
20597        ),
20598        &format!("color({} 0.7 0.5 0.2)", color_space),
20599      );
20600      test(
20601        &format!(
20602          "color(from color({} 0.7 0.5 0.3) {} r g b / 0.2)",
20603          color_space, color_space
20604        ),
20605        &format!("color({} 0.7 0.5 0.3 / 0.2)", color_space),
20606      );
20607      test(
20608        &format!(
20609          "color(from color({} 0.7 0.5 0.3) {} r g b / 20%)",
20610          color_space, color_space
20611        ),
20612        &format!("color({} 0.7 0.5 0.3 / 0.2)", color_space),
20613      );
20614      test(
20615        &format!(
20616          "color(from color({} 0.7 0.5 0.3 / 40%) {} 0.2 g b / alpha)",
20617          color_space, color_space
20618        ),
20619        &format!("color({} 0.2 0.5 0.3 / 0.4)", color_space),
20620      );
20621      test(
20622        &format!(
20623          "color(from color({} 0.7 0.5 0.3 / 40%) {} 20% g b / alpha)",
20624          color_space, color_space
20625        ),
20626        &format!("color({} 0.2 0.5 0.3 / 0.4)", color_space),
20627      );
20628      test(
20629        &format!(
20630          "color(from color({} 0.7 0.5 0.3 / 40%) {} r 0.2 b / alpha)",
20631          color_space, color_space
20632        ),
20633        &format!("color({} 0.7 0.2 0.3 / 0.4)", color_space),
20634      );
20635      test(
20636        &format!(
20637          "color(from color({} 0.7 0.5 0.3 / 40%) {} r 20% b / alpha)",
20638          color_space, color_space
20639        ),
20640        &format!("color({} 0.7 0.2 0.3 / 0.4)", color_space),
20641      );
20642      test(
20643        &format!(
20644          "color(from color({} 0.7 0.5 0.3 / 40%) {} r g 0.2 / alpha)",
20645          color_space, color_space
20646        ),
20647        &format!("color({} 0.7 0.5 0.2 / 0.4)", color_space),
20648      );
20649      test(
20650        &format!(
20651          "color(from color({} 0.7 0.5 0.3 / 40%) {} r g 20% / alpha)",
20652          color_space, color_space
20653        ),
20654        &format!("color({} 0.7 0.5 0.2 / 0.4)", color_space),
20655      );
20656      test(
20657        &format!(
20658          "color(from color({} 0.7 0.5 0.3 / 40%) {} r g b / 0.2)",
20659          color_space, color_space
20660        ),
20661        &format!("color({} 0.7 0.5 0.3 / 0.2)", color_space),
20662      );
20663      test(
20664        &format!(
20665          "color(from color({} 0.7 0.5 0.3 / 40%) {} r g b / 20%)",
20666          color_space, color_space
20667        ),
20668        &format!("color({} 0.7 0.5 0.3 / 0.2)", color_space),
20669      );
20670      test(
20671        &format!("color(from color({} 0.7 0.5 0.3) {} 2 3 4)", color_space, color_space),
20672        &format!("color({} 2 3 4)", color_space),
20673      );
20674      test(
20675        &format!(
20676          "color(from color({} 0.7 0.5 0.3) {} 2 3 4 / 5)",
20677          color_space, color_space
20678        ),
20679        &format!("color({} 2 3 4)", color_space),
20680      );
20681      test(
20682        &format!(
20683          "color(from color({} 0.7 0.5 0.3) {} -2 -3 -4)",
20684          color_space, color_space
20685        ),
20686        &format!("color({} -2 -3 -4)", color_space),
20687      );
20688      test(
20689        &format!(
20690          "color(from color({} 0.7 0.5 0.3) {} -2 -3 -4 / -5)",
20691          color_space, color_space
20692        ),
20693        &format!("color({} -2 -3 -4 / 0)", color_space),
20694      );
20695      test(
20696        &format!(
20697          "color(from color({} 0.7 0.5 0.3) {} 200% 300% 400%)",
20698          color_space, color_space
20699        ),
20700        &format!("color({} 2 3 4)", color_space),
20701      );
20702      test(
20703        &format!(
20704          "color(from color({} 0.7 0.5 0.3) {} 200% 300% 400% / 500%)",
20705          color_space, color_space
20706        ),
20707        &format!("color({} 2 3 4)", color_space),
20708      );
20709      test(
20710        &format!(
20711          "color(from color({} 0.7 0.5 0.3) {} -200% -300% -400%)",
20712          color_space, color_space
20713        ),
20714        &format!("color({} -2 -3 -4)", color_space),
20715      );
20716      test(
20717        &format!(
20718          "color(from color({} 0.7 0.5 0.3) {} -200% -300% -400% / -500%)",
20719          color_space, color_space
20720        ),
20721        &format!("color({} -2 -3 -4 / 0)", color_space),
20722      );
20723
20724      // Testing valid permutation (types match).
20725      test(
20726        &format!("color(from color({} 0.7 0.5 0.3) {} g b r)", color_space, color_space),
20727        &format!("color({} 0.5 0.3 0.7)", color_space),
20728      );
20729      test(
20730        &format!(
20731          "color(from color({} 0.7 0.5 0.3) {} b alpha r / g)",
20732          color_space, color_space
20733        ),
20734        &format!("color({} 0.3 1 0.7 / 0.5)", color_space),
20735      );
20736      test(
20737        &format!(
20738          "color(from color({} 0.7 0.5 0.3) {} r r r / r)",
20739          color_space, color_space
20740        ),
20741        &format!("color({} 0.7 0.7 0.7 / 0.7)", color_space),
20742      );
20743      test(
20744        &format!(
20745          "color(from color({} 0.7 0.5 0.3) {} alpha alpha alpha / alpha)",
20746          color_space, color_space
20747        ),
20748        &format!("color({} 1 1 1)", color_space),
20749      );
20750      test(
20751        &format!(
20752          "color(from color({} 0.7 0.5 0.3 / 40%) {} g b r)",
20753          color_space, color_space
20754        ),
20755        &format!("color({} 0.5 0.3 0.7)", color_space),
20756      );
20757      test(
20758        &format!(
20759          "color(from color({} 0.7 0.5 0.3 / 40%) {} b alpha r / g)",
20760          color_space, color_space
20761        ),
20762        &format!("color({} 0.3 0.4 0.7 / 0.5)", color_space),
20763      );
20764      test(
20765        &format!(
20766          "color(from color({} 0.7 0.5 0.3 / 40%) {} r r r / r)",
20767          color_space, color_space
20768        ),
20769        &format!("color({} 0.7 0.7 0.7 / 0.7)", color_space),
20770      );
20771      test(
20772        &format!(
20773          "color(from color({} 0.7 0.5 0.3 / 40%) {} alpha alpha alpha / alpha)",
20774          color_space, color_space
20775        ),
20776        &format!("color({} 0.4 0.4 0.4 / 0.4)", color_space),
20777      );
20778
20779      // Testing out of gamut components.
20780      test(
20781        &format!("color(from color({} 1.7 1.5 1.3) {} r g b)", color_space, color_space),
20782        &format!("color({} 1.7 1.5 1.3)", color_space),
20783      );
20784      test(
20785        &format!(
20786          "color(from color({} 1.7 1.5 1.3) {} r g b / alpha)",
20787          color_space, color_space
20788        ),
20789        &format!("color({} 1.7 1.5 1.3)", color_space),
20790      );
20791      test(
20792        &format!(
20793          "color(from color({} 1.7 1.5 1.3 / 140%) {} r g b)",
20794          color_space, color_space
20795        ),
20796        &format!("color({} 1.7 1.5 1.3)", color_space),
20797      );
20798      test(
20799        &format!(
20800          "color(from color({} 1.7 1.5 1.3 / 140%) {} r g b / alpha)",
20801          color_space, color_space
20802        ),
20803        &format!("color({} 1.7 1.5 1.3)", color_space),
20804      );
20805      test(
20806        &format!(
20807          "color(from color({} -0.7 -0.5 -0.3) {} r g b)",
20808          color_space, color_space
20809        ),
20810        &format!("color({} -0.7 -0.5 -0.3)", color_space),
20811      );
20812      test(
20813        &format!(
20814          "color(from color({} -0.7 -0.5 -0.3) {} r g b / alpha)",
20815          color_space, color_space
20816        ),
20817        &format!("color({} -0.7 -0.5 -0.3)", color_space),
20818      );
20819      test(
20820        &format!(
20821          "color(from color({} -0.7 -0.5 -0.3 / -40%) {} r g b)",
20822          color_space, color_space
20823        ),
20824        &format!("color({} -0.7 -0.5 -0.3)", color_space),
20825      );
20826      test(
20827        &format!(
20828          "color(from color({} -0.7 -0.5 -0.3 / -40%) {} r g b / alpha)",
20829          color_space, color_space
20830        ),
20831        &format!("color({} -0.7 -0.5 -0.3 / 0)", color_space),
20832      );
20833
20834      // Testing with calc().
20835      test(
20836        &format!(
20837          "color(from color({} 0.7 0.5 0.3) {} calc(r) calc(g) calc(b))",
20838          color_space, color_space
20839        ),
20840        &format!("color({} 0.7 0.5 0.3)", color_space),
20841      );
20842      test(
20843        &format!(
20844          "color(from color({} 0.7 0.5 0.3 / 40%) {} calc(r) calc(g) calc(b) / calc(alpha))",
20845          color_space, color_space
20846        ),
20847        &format!("color({} 0.7 0.5 0.3 / 0.4)", color_space),
20848      );
20849
20850      // Testing with 'none'.
20851      test(
20852        &format!(
20853          "color(from color({} 0.7 0.5 0.3) {} none none none)",
20854          color_space, color_space
20855        ),
20856        &format!("color({} none none none)", color_space),
20857      );
20858      test(
20859        &format!(
20860          "color(from color({} 0.7 0.5 0.3) {} none none none / none)",
20861          color_space, color_space
20862        ),
20863        &format!("color({} none none none / none)", color_space),
20864      );
20865      test(
20866        &format!(
20867          "color(from color({} 0.7 0.5 0.3) {} r g none)",
20868          color_space, color_space
20869        ),
20870        &format!("color({} 0.7 0.5 none)", color_space),
20871      );
20872      test(
20873        &format!(
20874          "color(from color({} 0.7 0.5 0.3) {} r g none / alpha)",
20875          color_space, color_space
20876        ),
20877        &format!("color({} 0.7 0.5 none)", color_space),
20878      );
20879      test(
20880        &format!(
20881          "color(from color({} 0.7 0.5 0.3) {} r g b / none)",
20882          color_space, color_space
20883        ),
20884        &format!("color({} 0.7 0.5 0.3 / none)", color_space),
20885      );
20886      test(
20887        &format!(
20888          "color(from color({} 0.7 0.5 0.3 / 40%) {} r g none / alpha)",
20889          color_space, color_space
20890        ),
20891        &format!("color({} 0.7 0.5 none / 0.4)", color_space),
20892      );
20893      test(
20894        &format!(
20895          "color(from color({} 0.7 0.5 0.3 / 40%) {} r g b / none)",
20896          color_space, color_space
20897        ),
20898        &format!("color({} 0.7 0.5 0.3 / none)", color_space),
20899      );
20900      // FIXME: Clarify with spec editors if 'none' should pass through to the constants.
20901      test(
20902        &format!(
20903          "color(from color({} none none none) {} r g b)",
20904          color_space, color_space
20905        ),
20906        &format!("color({} 0 0 0)", color_space),
20907      );
20908      test(
20909        &format!(
20910          "color(from color({} none none none / none) {} r g b / alpha)",
20911          color_space, color_space
20912        ),
20913        &format!("color({} 0 0 0 / 0)", color_space),
20914      );
20915      test(
20916        &format!("color(from color({} 0.7 none 0.3) {} r g b)", color_space, color_space),
20917        &format!("color({} 0.7 0 0.3)", color_space),
20918      );
20919      test(
20920        &format!(
20921          "color(from color({} 0.7 0.5 0.3 / none) {} r g b / alpha)",
20922          color_space, color_space
20923        ),
20924        &format!("color({} 0.7 0.5 0.3 / 0)", color_space),
20925      );
20926    }
20927
20928    // test_valid_value\(`color`, `color\(from color\(\$\{colorSpace\}(.*?) \$\{colorSpace\}(.*?)`,\s*`color\(\$\{resultColorSpace\}(.*?)`\)
20929    // test(&format!("color(from color({}$1 {}$2", color_space, color_space), &format!("color({}$3", result_color_space))
20930
20931    for color_space in &["xyz", "xyz-d50", "xyz-d65"] {
20932      let result_color_space = if *color_space == "xyz" { "xyz-d65" } else { color_space };
20933
20934      // Testing no modifications.
20935      test(
20936        &format!("color(from color({} 7 -20.5 100) {} x y z)", color_space, color_space),
20937        &format!("color({} 7 -20.5 100)", result_color_space),
20938      );
20939      test(
20940        &format!(
20941          "color(from color({} 7 -20.5 100) {} x y z / alpha)",
20942          color_space, color_space
20943        ),
20944        &format!("color({} 7 -20.5 100)", result_color_space),
20945      );
20946      test(
20947        &format!(
20948          "color(from color({} 7 -20.5 100 / 40%) {} x y z)",
20949          color_space, color_space
20950        ),
20951        &format!("color({} 7 -20.5 100)", result_color_space),
20952      );
20953      test(
20954        &format!(
20955          "color(from color({} 7 -20.5 100 / 40%) {} x y z / alpha)",
20956          color_space, color_space
20957        ),
20958        &format!("color({} 7 -20.5 100 / 0.4)", result_color_space),
20959      );
20960
20961      // Test nesting relative colors.
20962      test(
20963        &format!(
20964          "color(from color(from color({} 7 -20.5 100) {} x y z) {} x y z)",
20965          color_space, color_space, color_space
20966        ),
20967        &format!("color({} 7 -20.5 100)", result_color_space),
20968      );
20969
20970      // Testing replacement with 0.
20971      test(
20972        &format!("color(from color({} 7 -20.5 100) {} 0 0 0)", color_space, color_space),
20973        &format!("color({} 0 0 0)", result_color_space),
20974      );
20975      test(
20976        &format!(
20977          "color(from color({} 7 -20.5 100) {} 0 0 0 / 0)",
20978          color_space, color_space
20979        ),
20980        &format!("color({} 0 0 0 / 0)", result_color_space),
20981      );
20982      test(
20983        &format!(
20984          "color(from color({} 7 -20.5 100) {} 0 y z / alpha)",
20985          color_space, color_space
20986        ),
20987        &format!("color({} 0 -20.5 100)", result_color_space),
20988      );
20989      test(
20990        &format!(
20991          "color(from color({} 7 -20.5 100) {} x 0 z / alpha)",
20992          color_space, color_space
20993        ),
20994        &format!("color({} 7 0 100)", result_color_space),
20995      );
20996      test(
20997        &format!(
20998          "color(from color({} 7 -20.5 100) {} x y 0 / alpha)",
20999          color_space, color_space
21000        ),
21001        &format!("color({} 7 -20.5 0)", result_color_space),
21002      );
21003      test(
21004        &format!(
21005          "color(from color({} 7 -20.5 100) {} x y z / 0)",
21006          color_space, color_space
21007        ),
21008        &format!("color({} 7 -20.5 100 / 0)", result_color_space),
21009      );
21010      test(
21011        &format!(
21012          "color(from color({} 7 -20.5 100 / 40%) {} 0 y z / alpha)",
21013          color_space, color_space
21014        ),
21015        &format!("color({} 0 -20.5 100 / 0.4)", result_color_space),
21016      );
21017      test(
21018        &format!(
21019          "color(from color({} 7 -20.5 100 / 40%) {} x 0 z / alpha)",
21020          color_space, color_space
21021        ),
21022        &format!("color({} 7 0 100 / 0.4)", result_color_space),
21023      );
21024      test(
21025        &format!(
21026          "color(from color({} 7 -20.5 100 / 40%) {} x y 0 / alpha)",
21027          color_space, color_space
21028        ),
21029        &format!("color({} 7 -20.5 0 / 0.4)", result_color_space),
21030      );
21031      test(
21032        &format!(
21033          "color(from color({} 7 -20.5 100 / 40%) {} x y z / 0)",
21034          color_space, color_space
21035        ),
21036        &format!("color({} 7 -20.5 100 / 0)", result_color_space),
21037      );
21038
21039      // Testing replacement with a constant.
21040      test(
21041        &format!(
21042          "color(from color({} 7 -20.5 100) {} 0.2 y z / alpha)",
21043          color_space, color_space
21044        ),
21045        &format!("color({} 0.2 -20.5 100)", result_color_space),
21046      );
21047      test(
21048        &format!(
21049          "color(from color({} 7 -20.5 100) {} x 0.2 z / alpha)",
21050          color_space, color_space
21051        ),
21052        &format!("color({} 7 0.2 100)", result_color_space),
21053      );
21054      test(
21055        &format!(
21056          "color(from color({} 7 -20.5 100) {} x y 0.2 / alpha)",
21057          color_space, color_space
21058        ),
21059        &format!("color({} 7 -20.5 0.2)", result_color_space),
21060      );
21061      test(
21062        &format!(
21063          "color(from color({} 7 -20.5 100) {} x y z / 0.2)",
21064          color_space, color_space
21065        ),
21066        &format!("color({} 7 -20.5 100 / 0.2)", result_color_space),
21067      );
21068      test(
21069        &format!(
21070          "color(from color({} 7 -20.5 100) {} x y z / 20%)",
21071          color_space, color_space
21072        ),
21073        &format!("color({} 7 -20.5 100 / 0.2)", result_color_space),
21074      );
21075      test(
21076        &format!(
21077          "color(from color({} 7 -20.5 100 / 40%) {} 0.2 y z / alpha)",
21078          color_space, color_space
21079        ),
21080        &format!("color({} 0.2 -20.5 100 / 0.4)", result_color_space),
21081      );
21082      test(
21083        &format!(
21084          "color(from color({} 7 -20.5 100 / 40%) {} x 0.2 z / alpha)",
21085          color_space, color_space
21086        ),
21087        &format!("color({} 7 0.2 100 / 0.4)", result_color_space),
21088      );
21089      test(
21090        &format!(
21091          "color(from color({} 7 -20.5 100 / 40%) {} x y 0.2 / alpha)",
21092          color_space, color_space
21093        ),
21094        &format!("color({} 7 -20.5 0.2 / 0.4)", result_color_space),
21095      );
21096      test(
21097        &format!(
21098          "color(from color({} 7 -20.5 100 / 40%) {} x y z / 0.2)",
21099          color_space, color_space
21100        ),
21101        &format!("color({} 7 -20.5 100 / 0.2)", result_color_space),
21102      );
21103
21104      // Testing valid permutation (types match).
21105      test(
21106        &format!("color(from color({} 7 -20.5 100) {} y z x)", color_space, color_space),
21107        &format!("color({} -20.5 100 7)", result_color_space),
21108      );
21109      test(
21110        &format!(
21111          "color(from color({} 7 -20.5 100) {} x x x / x)",
21112          color_space, color_space
21113        ),
21114        &format!("color({} 7 7 7)", result_color_space),
21115      );
21116      test(
21117        &format!(
21118          "color(from color({} 7 -20.5 100 / 40%) {} y z x)",
21119          color_space, color_space
21120        ),
21121        &format!("color({} -20.5 100 7)", result_color_space),
21122      );
21123      test(
21124        &format!(
21125          "color(from color({} 7 -20.5 100 / 40%) {} x x x / x)",
21126          color_space, color_space
21127        ),
21128        &format!("color({} 7 7 7)", result_color_space),
21129      );
21130
21131      // Testing with calc().
21132      test(
21133        &format!(
21134          "color(from color({} 7 -20.5 100) {} calc(x) calc(y) calc(z))",
21135          color_space, color_space
21136        ),
21137        &format!("color({} 7 -20.5 100)", result_color_space),
21138      );
21139      test(
21140        &format!(
21141          "color(from color({} 7 -20.5 100 / 40%) {} calc(x) calc(y) calc(z) / calc(alpha))",
21142          color_space, color_space
21143        ),
21144        &format!("color({} 7 -20.5 100 / 0.4)", result_color_space),
21145      );
21146
21147      // Testing with 'none'.
21148      test(
21149        &format!(
21150          "color(from color({} 7 -20.5 100) {} none none none)",
21151          color_space, color_space
21152        ),
21153        &format!("color({} none none none)", result_color_space),
21154      );
21155      test(
21156        &format!(
21157          "color(from color({} 7 -20.5 100) {} none none none / none)",
21158          color_space, color_space
21159        ),
21160        &format!("color({} none none none / none)", result_color_space),
21161      );
21162      test(
21163        &format!(
21164          "color(from color({} 7 -20.5 100) {} x y none)",
21165          color_space, color_space
21166        ),
21167        &format!("color({} 7 -20.5 none)", result_color_space),
21168      );
21169      test(
21170        &format!(
21171          "color(from color({} 7 -20.5 100) {} x y none / alpha)",
21172          color_space, color_space
21173        ),
21174        &format!("color({} 7 -20.5 none)", result_color_space),
21175      );
21176      test(
21177        &format!(
21178          "color(from color({} 7 -20.5 100) {} x y z / none)",
21179          color_space, color_space
21180        ),
21181        &format!("color({} 7 -20.5 100 / none)", result_color_space),
21182      );
21183      test(
21184        &format!(
21185          "color(from color({} 7 -20.5 100 / 40%) {} x y none / alpha)",
21186          color_space, color_space
21187        ),
21188        &format!("color({} 7 -20.5 none / 0.4)", result_color_space),
21189      );
21190      test(
21191        &format!(
21192          "color(from color({} 7 -20.5 100 / 40%) {} x y z / none)",
21193          color_space, color_space
21194        ),
21195        &format!("color({} 7 -20.5 100 / none)", result_color_space),
21196      );
21197      // FIXME: Clarify with spec editors if 'none' should pass through to the constants.
21198      test(
21199        &format!(
21200          "color(from color({} none none none) {} x y z)",
21201          color_space, color_space
21202        ),
21203        &format!("color({} 0 0 0)", result_color_space),
21204      );
21205      test(
21206        &format!(
21207          "color(from color({} none none none / none) {} x y z / alpha)",
21208          color_space, color_space
21209        ),
21210        &format!("color({} 0 0 0 / 0)", result_color_space),
21211      );
21212      test(
21213        &format!("color(from color({} 7 none 100) {} x y z)", color_space, color_space),
21214        &format!("color({} 7 0 100)", result_color_space),
21215      );
21216      test(
21217        &format!(
21218          "color(from color({} 7 -20.5 100 / none) {} x y z / alpha)",
21219          color_space, color_space
21220        ),
21221        &format!("color({} 7 -20.5 100 / 0)", result_color_space),
21222      );
21223
21224      // https://github.com/web-platform-tests/wpt/blob/master/css/css-color/parsing/relative-color-invalid.html
21225      minify_test(
21226        ".foo{color:rgb(from rebeccapurple r 10deg 10)}",
21227        ".foo{color:rgb(from rebeccapurple r 10deg 10)}",
21228      );
21229      minify_test(
21230        ".foo{color:rgb(from rebeccapurple l g b)}",
21231        ".foo{color:rgb(from rebeccapurple l g b)}",
21232      );
21233      minify_test(
21234        ".foo{color:hsl(from rebeccapurple s h l)}",
21235        ".foo{color:hsl(from rebeccapurple s h l)}",
21236      );
21237      minify_test(".foo{color:hsl(from rebeccapurple s s s / s)}", ".foo{color:#bfaa40}");
21238      minify_test(
21239        ".foo{color:hsl(from rebeccapurple calc(alpha * 100) calc(alpha * 100) calc(alpha * 100) / alpha)}",
21240        ".foo{color:#fff}",
21241      );
21242    }
21243  }
21244
21245  #[test]
21246  fn test_relative_alpha_color_fallbacks() {
21247    prefix_test(
21248      ".foo { color: alpha(from color(srgb 1 0 0) / 0.5) }",
21249      indoc! { r#"
21250        .foo {
21251          color: #ff000080;
21252          color: color(srgb 1 0 0 / .5);
21253        }
21254      "#},
21255      Browsers {
21256        chrome: Some(90 << 16),
21257        ..Browsers::default()
21258      },
21259    );
21260    prefix_test(
21261      ".foo { color: alpha(from color(display-p3 1 0 0) / 0.5) }",
21262      indoc! { r#"
21263        .foo {
21264          color: #ff0f0e80;
21265          color: color(display-p3 1 0 0 / .5);
21266        }
21267      "#},
21268      Browsers {
21269        chrome: Some(90 << 16),
21270        ..Browsers::default()
21271      },
21272    );
21273  }
21274
21275  #[test]
21276  fn test_color_mix() {
21277    minify_test(
21278      ".foo { color: color-mix(in lab, purple 50%, plum 50%); }",
21279      ".foo{color:lab(51.5117% 43.3777 -29.0443)}",
21280    );
21281    minify_test(
21282      ".foo { color: color-mix(in lch, peru 40%, palegoldenrod); }",
21283      ".foo{color:lch(79.7255% 40.4542 84.7634)}",
21284    );
21285    minify_test(
21286      ".foo { color: color-mix(in lch, teal 65%, olive); }",
21287      ".foo{color:lch(49.4431% 40.4806 162.546)}",
21288    );
21289    minify_test(
21290      ".foo { color: color-mix(in lch, white, black); }",
21291      ".foo{color:lch(50% 0 none)}",
21292    );
21293    minify_test(
21294      ".foo { color: color-mix(in xyz, rgb(82.02% 30.21% 35.02%) 75.23%, rgb(5.64% 55.94% 85.31%)); }",
21295      ".foo{color:color(xyz .287458 .208776 .260566)}",
21296    );
21297    minify_test(
21298      ".foo { color: color-mix(in lch, white, blue); }",
21299      ".foo{color:lch(64.7842% 65.6007 301.364)}",
21300    );
21301    minify_test(
21302      ".foo { color: color-mix(in oklch, white, blue); }",
21303      ".foo{color:oklch(72.6007% .156607 264.052)}",
21304    );
21305    minify_test(
21306      ".foo { color: color-mix(in srgb, white, blue); }",
21307      ".foo{color:#8080ff}",
21308    );
21309    minify_test(
21310      ".foo { color: color-mix(in lch, blue, white); }",
21311      ".foo{color:lch(64.7842% 65.6007 301.364)}",
21312    );
21313    minify_test(
21314      ".foo { color: color-mix(in oklch, blue, white); }",
21315      ".foo{color:oklch(72.6007% .156607 264.052)}",
21316    );
21317    minify_test(
21318      ".foo { color: color-mix(in srgb, blue, white); }",
21319      ".foo{color:#8080ff}",
21320    );
21321    // minify_test(".foo { color: color-mix(in hsl, color(display-p3 0 1 0) 80%, yellow); }", ".foo{color:hsl(108 100% 49.9184%) }");
21322    minify_test(
21323      ".foo { color: color-mix(in hsl, hsl(120 100% 49.898%) 80%, yellow); }",
21324      ".foo{color:#33fe00}",
21325    );
21326    minify_test(
21327      ".foo { color: color-mix(in srgb, rgb(100% 0% 0% / 0.7) 25%, rgb(0% 100% 0% / 0.2)); }",
21328      ".foo{color:#89760053}",
21329    );
21330    minify_test(
21331      ".foo { color: color-mix(in srgb, rgb(100% 0% 0% / 0.7) 20%, rgb(0% 100% 0% / 0.2) 60%); }",
21332      ".foo{color:#89760042}",
21333    );
21334    minify_test(
21335      ".foo { color: color-mix(in lch, color(display-p3 0 1 none), color(display-p3 0 0 1)); }",
21336      ".foo{color:lch(58.8143% 141.732 218.684)}",
21337    );
21338    minify_test(
21339      ".foo { color: color-mix(in srgb, rgb(128 128 none), rgb(none none 128)); }",
21340      ".foo{color:gray}",
21341    );
21342    minify_test(
21343      ".foo { color: color-mix(in srgb, rgb(50% 50% none), rgb(none none 50%)); }",
21344      ".foo{color:gray}",
21345    );
21346    minify_test(
21347      ".foo { color: color-mix(in srgb, rgb(none 50% none), rgb(50% none 50%)); }",
21348      ".foo{color:gray}",
21349    );
21350    minify_test(
21351      ".foo { --color: color-mix(in lch, teal 65%, olive); }",
21352      ".foo{--color:lch(49.4431% 40.4806 162.546)}",
21353    );
21354    minify_test(
21355      ".foo { color: color-mix(in xyz, transparent, green 65%); }",
21356      ".foo{color:color(xyz .0771883 .154377 .0257295/.65)}",
21357    );
21358    prefix_test(
21359      ".foo { color: color-mix(in xyz, transparent, green 65%); }",
21360      indoc! { r#"
21361      .foo {
21362        color: #008000a6;
21363        color: color(xyz .0771883 .154377 .0257295 / .65);
21364      }
21365      "# },
21366      Browsers {
21367        chrome: Some(95 << 16),
21368        ..Default::default()
21369      },
21370    );
21371    minify_test(
21372      ".foo { color: color-mix(in srgb, currentColor, blue); }",
21373      ".foo{color:color-mix(in srgb, currentColor, blue)}",
21374    );
21375    minify_test(
21376      ".foo { color: color-mix(in srgb, blue, currentColor); }",
21377      ".foo{color:color-mix(in srgb, blue, currentColor)}",
21378    );
21379    minify_test(
21380      ".foo { color: color-mix(in srgb, accentcolor, blue); }",
21381      ".foo{color:color-mix(in srgb, accentcolor, blue)}",
21382    );
21383    minify_test(
21384      ".foo { color: color-mix(in srgb, blue, accentcolor); }",
21385      ".foo{color:color-mix(in srgb, blue, accentcolor)}",
21386    );
21387
21388    // regex for converting web platform tests:
21389    // test_computed_value\(.*?, `(.*?)`, `(.*?)`\);
21390    // minify_test(".foo { color: $1 }", ".foo{color:$2}");
21391
21392    // https://github.com/web-platform-tests/wpt/blob/f8c76b11cff66a7adc87264a18e39353cb5a60c9/css/css-color/parsing/color-mix-computed.html
21393    minify_test(
21394      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%)) }",
21395      ".foo{color:#545c3d}",
21396    );
21397    minify_test(
21398      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40%)) }",
21399      ".foo{color:#706a43}",
21400    );
21401    minify_test(
21402      ".foo { color: color-mix(in hsl, 25% hsl(120deg 10% 20%), hsl(30deg 30% 40%)) }",
21403      ".foo{color:#706a43}",
21404    );
21405    minify_test(
21406      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20%), 25% hsl(30deg 30% 40%)) }",
21407      ".foo{color:#3d4936}",
21408    );
21409    minify_test(
21410      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%) 25%) }",
21411      ".foo{color:#3d4936}",
21412    );
21413    minify_test(
21414      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40%) 75%) }",
21415      ".foo{color:#706a43}",
21416    );
21417    minify_test(
21418      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20%) 30%, hsl(30deg 30% 40%) 90%) }",
21419      ".foo{color:#706a43}",
21420    ); // Scale down > 100% sum.
21421    minify_test(
21422      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20%) 12.5%, hsl(30deg 30% 40%) 37.5%) }",
21423      ".foo{color:#706a4380}",
21424    ); // Scale up < 100% sum, causes alpha multiplication.
21425    minify_test(
21426      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20%) 0%, hsl(30deg 30% 40%)) }",
21427      ".foo{color:#856647}",
21428    );
21429
21430    minify_test(
21431      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20% / .4), hsl(30deg 30% 40% / .8)) }",
21432      ".foo{color:#5f694199}",
21433    );
21434    minify_test(
21435      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40% / .8)) }",
21436      ".foo{color:#6c6742d9}",
21437    );
21438    minify_test(
21439      ".foo { color: color-mix(in hsl, 25% hsl(120deg 10% 20% / .4), hsl(30deg 30% 40% / .8)) }",
21440      ".foo{color:#797245b3}",
21441    );
21442    minify_test(
21443      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20% / .4), 25% hsl(30deg 30% 40% / .8)) }",
21444      ".foo{color:#44543b80}",
21445    );
21446    minify_test(
21447      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20% / .4), hsl(30deg 30% 40% / .8) 25%) }",
21448      ".foo{color:#44543b80}",
21449    );
21450    minify_test(
21451      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20% / .4) 25%, hsl(30deg 30% 40% / .8) 75%) }",
21452      ".foo{color:#797245b3}",
21453    );
21454    minify_test(
21455      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20% / .4) 30%, hsl(30deg 30% 40% / .8) 90%) }",
21456      ".foo{color:#797245b3}",
21457    ); // Scale down > 100% sum.
21458    minify_test(
21459      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20% / .4) 12.5%, hsl(30deg 30% 40% / .8) 37.5%) }",
21460      ".foo{color:#79724559}",
21461    ); // Scale up < 100% sum, causes alpha multiplication.
21462    minify_test(
21463      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20% / .4) 0%, hsl(30deg 30% 40% / .8)) }",
21464      ".foo{color:#856647cc}",
21465    );
21466
21467    fn canonicalize(s: &str) -> String {
21468      use crate::traits::{Parse, ToCss};
21469      use crate::values::color::CssColor;
21470      use cssparser::{Parser, ParserInput};
21471
21472      let mut input = ParserInput::new(s);
21473      let mut parser = Parser::new(&mut input);
21474      let v = CssColor::parse(&mut parser).unwrap().to_rgb().unwrap();
21475      format!(".foo{{color:{}}}", v.to_css_string(PrinterOptions::default()).unwrap())
21476    }
21477
21478    // regex for converting web platform tests:
21479    // test_computed_value\(.*?, `(.*?)`, canonicalize\(`(.*?)`\)\);
21480    // minify_test(".foo { color: $1 }", &canonicalize("$2"));
21481
21482    minify_test(
21483      ".foo { color: color-mix(in hsl, hsl(40deg 50% 50%), hsl(60deg 50% 50%)) }",
21484      &canonicalize("hsl(50deg 50% 50%)"),
21485    );
21486    minify_test(
21487      ".foo { color: color-mix(in hsl, hsl(60deg 50% 50%), hsl(40deg 50% 50%)) }",
21488      &canonicalize("hsl(50deg 50% 50%)"),
21489    );
21490    minify_test(
21491      ".foo { color: color-mix(in hsl, hsl(50deg 50% 50%), hsl(330deg 50% 50%)) }",
21492      &canonicalize("hsl(10deg 50% 50%)"),
21493    );
21494    minify_test(
21495      ".foo { color: color-mix(in hsl, hsl(330deg 50% 50%), hsl(50deg 50% 50%)) }",
21496      &canonicalize("hsl(10deg 50% 50%)"),
21497    );
21498    minify_test(
21499      ".foo { color: color-mix(in hsl, hsl(20deg 50% 50%), hsl(320deg 50% 50%)) }",
21500      &canonicalize("hsl(350deg 50% 50%)"),
21501    );
21502    minify_test(
21503      ".foo { color: color-mix(in hsl, hsl(320deg 50% 50%), hsl(20deg 50% 50%)) }",
21504      &canonicalize("hsl(350deg 50% 50%)"),
21505    );
21506
21507    minify_test(
21508      ".foo { color: color-mix(in hsl shorter hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%)) }",
21509      &canonicalize("hsl(50deg 50% 50%)"),
21510    );
21511    minify_test(
21512      ".foo { color: color-mix(in hsl shorter hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%)) }",
21513      &canonicalize("hsl(50deg 50% 50%)"),
21514    );
21515    minify_test(
21516      ".foo { color: color-mix(in hsl shorter hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%)) }",
21517      &canonicalize("hsl(10deg 50% 50%)"),
21518    );
21519    minify_test(
21520      ".foo { color: color-mix(in hsl shorter hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%)) }",
21521      &canonicalize("hsl(10deg 50% 50%)"),
21522    );
21523    minify_test(
21524      ".foo { color: color-mix(in hsl shorter hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%)) }",
21525      &canonicalize("hsl(350deg 50% 50%)"),
21526    );
21527    minify_test(
21528      ".foo { color: color-mix(in hsl shorter hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%)) }",
21529      &canonicalize("hsl(350deg 50% 50%)"),
21530    );
21531
21532    minify_test(
21533      ".foo { color: color-mix(in hsl longer hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%)) }",
21534      &canonicalize("hsl(230deg 50% 50%)"),
21535    );
21536    minify_test(
21537      ".foo { color: color-mix(in hsl longer hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%)) }",
21538      &canonicalize("hsl(230deg 50% 50%)"),
21539    );
21540    minify_test(
21541      ".foo { color: color-mix(in hsl longer hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%)) }",
21542      &canonicalize("hsl(190deg 50% 50%)"),
21543    );
21544    minify_test(
21545      ".foo { color: color-mix(in hsl longer hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%)) }",
21546      &canonicalize("hsl(190deg 50% 50%)"),
21547    );
21548    // minify_test(".foo { color: color-mix(in hsl longer hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%)) }", &canonicalize("hsl(170deg 50% 50%)"));
21549    // minify_test(".foo { color: color-mix(in hsl longer hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%)) }", &canonicalize("hsl(170deg 50% 50%)"));
21550
21551    minify_test(
21552      ".foo { color: color-mix(in hsl increasing hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%)) }",
21553      &canonicalize("hsl(50deg 50% 50%)"),
21554    );
21555    minify_test(
21556      ".foo { color: color-mix(in hsl increasing hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%)) }",
21557      &canonicalize("hsl(230deg 50% 50%)"),
21558    );
21559    minify_test(
21560      ".foo { color: color-mix(in hsl increasing hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%)) }",
21561      &canonicalize("hsl(190deg 50% 50%)"),
21562    );
21563    minify_test(
21564      ".foo { color: color-mix(in hsl increasing hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%)) }",
21565      &canonicalize("hsl(10deg 50% 50%)"),
21566    );
21567    // minify_test(".foo { color: color-mix(in hsl increasing hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%)) }", &canonicalize("hsl(170deg 50% 50%)"));
21568    // minify_test(".foo { color: color-mix(in hsl increasing hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%)) }", &canonicalize("hsl(350deg 50% 50%)"));
21569
21570    minify_test(
21571      ".foo { color: color-mix(in hsl decreasing hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%)) }",
21572      &canonicalize("hsl(230deg 50% 50%)"),
21573    );
21574    minify_test(
21575      ".foo { color: color-mix(in hsl decreasing hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%)) }",
21576      &canonicalize("hsl(50deg 50% 50%)"),
21577    );
21578    minify_test(
21579      ".foo { color: color-mix(in hsl decreasing hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%)) }",
21580      &canonicalize("hsl(10deg 50% 50%)"),
21581    );
21582    minify_test(
21583      ".foo { color: color-mix(in hsl decreasing hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%)) }",
21584      &canonicalize("hsl(190deg 50% 50%)"),
21585    );
21586    minify_test(
21587      ".foo { color: color-mix(in hsl decreasing hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%)) }",
21588      &canonicalize("hsl(350deg 50% 50%)"),
21589    );
21590    // minify_test(".foo { color: color-mix(in hsl decreasing hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%)) }", &canonicalize("hsl(170deg 50% 50%)"));
21591
21592    minify_test(
21593      ".foo { color: color-mix(in hsl specified hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%)) }",
21594      &canonicalize("hsl(50deg 50% 50%)"),
21595    );
21596    minify_test(
21597      ".foo { color: color-mix(in hsl specified hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%)) }",
21598      &canonicalize("hsl(50deg 50% 50%)"),
21599    );
21600    minify_test(
21601      ".foo { color: color-mix(in hsl specified hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%)) }",
21602      &canonicalize("hsl(190deg 50% 50%)"),
21603    );
21604    minify_test(
21605      ".foo { color: color-mix(in hsl specified hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%)) }",
21606      &canonicalize("hsl(190deg 50% 50%)"),
21607    );
21608    // minify_test(".foo { color: color-mix(in hsl specified hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%)) }", &canonicalize("hsl(170deg 50% 50%)"));
21609    // minify_test(".foo { color: color-mix(in hsl specified hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%)) }", &canonicalize("hsl(170deg 50% 50%)"));
21610
21611    minify_test(
21612      ".foo { color: color-mix(in hsl, hsl(none none none), hsl(none none none)) }",
21613      &canonicalize("hsl(none none none)"),
21614    );
21615    minify_test(
21616      ".foo { color: color-mix(in hsl, hsl(none none none), hsl(30deg 40% 80%)) }",
21617      &canonicalize("hsl(30deg 40% 80%)"),
21618    );
21619    minify_test(
21620      ".foo { color: color-mix(in hsl, hsl(120deg 20% 40%), hsl(none none none)) }",
21621      &canonicalize("hsl(120deg 20% 40%)"),
21622    );
21623    minify_test(
21624      ".foo { color: color-mix(in hsl, hsl(120deg 20% none), hsl(30deg 40% 60%)) }",
21625      &canonicalize("hsl(75deg 30% 60%)"),
21626    );
21627    minify_test(
21628      ".foo { color: color-mix(in hsl, hsl(120deg 20% 40%), hsl(30deg 20% none)) }",
21629      &canonicalize("hsl(75deg 20% 40%)"),
21630    );
21631    minify_test(
21632      ".foo { color: color-mix(in hsl, hsl(none 20% 40%), hsl(30deg none 80%)) }",
21633      &canonicalize("hsl(30deg 20% 60%)"),
21634    );
21635
21636    minify_test(
21637      ".foo { color: color-mix(in hsl, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%) }",
21638      &canonicalize("rgb(0, 249, 66)"),
21639    ); // Naive clip based mapping would give rgb(0, 255, 0).
21640    minify_test(
21641      ".foo { color: color-mix(in hsl, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%) }",
21642      &canonicalize("rgb(255, 255, 255)"),
21643    ); // Naive clip based mapping would give rgb(255, 150, 255).
21644    minify_test(
21645      ".foo { color: color-mix(in hsl, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%) }",
21646      &canonicalize("rgb(42, 0, 34)"),
21647    ); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
21648    minify_test(
21649      ".foo { color: color-mix(in hsl, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%) }",
21650      &canonicalize("rgb(255, 255, 255)"),
21651    ); // Naive clip based mapping would give rgb(255, 150, 255).
21652    minify_test(
21653      ".foo { color: color-mix(in hsl, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%) }",
21654      &canonicalize("rgb(42, 0, 34)"),
21655    ); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
21656    minify_test(
21657      ".foo { color: color-mix(in hsl, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%) }",
21658      &canonicalize("rgb(255, 255, 255)"),
21659    ); // Naive clip based mapping would give rgb(255, 92, 255).
21660    minify_test(
21661      ".foo { color: color-mix(in hsl, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%) }",
21662      &canonicalize("rgb(0, 0, 0)"),
21663    ); // Naive clip based mapping would give rgb(19, 0, 24).
21664    minify_test(
21665      ".foo { color: color-mix(in hsl, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%) }",
21666      &canonicalize("rgb(255, 255, 255)"),
21667    ); // Naive clip based mapping would give rgb(255, 91, 255).
21668    minify_test(
21669      ".foo { color: color-mix(in hsl, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%) }",
21670      &canonicalize("rgb(0, 0, 0)"),
21671    ); // Naive clip based mapping would give rgb(20, 0, 24).
21672
21673    minify_test(
21674      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%)) }",
21675      &canonicalize("rgb(147, 179, 52)"),
21676    );
21677    minify_test(
21678      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%)) }",
21679      &canonicalize("rgb(166, 153, 64)"),
21680    );
21681    minify_test(
21682      ".foo { color: color-mix(in hwb, 25% hwb(120deg 10% 20%), hwb(30deg 30% 40%)) }",
21683      &canonicalize("rgb(166, 153, 64)"),
21684    );
21685    minify_test(
21686      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20%), 25% hwb(30deg 30% 40%)) }",
21687      &canonicalize("rgb(96, 191, 39)"),
21688    );
21689    minify_test(
21690      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%) 25%) }",
21691      &canonicalize("rgb(96, 191, 39)"),
21692    );
21693    minify_test(
21694      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%) 75%) }",
21695      &canonicalize("rgb(166, 153, 64)"),
21696    );
21697    minify_test(
21698      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20%) 30%, hwb(30deg 30% 40%) 90%) }",
21699      &canonicalize("rgb(166, 153, 64)"),
21700    ); // Scale down > 100% sum.
21701    minify_test(
21702      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20%) 12.5%, hwb(30deg 30% 40%) 37.5%) }",
21703      &canonicalize("rgba(166, 153, 64, 0.5)"),
21704    ); // Scale up < 100% sum, causes alpha multiplication.
21705    minify_test(
21706      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20%) 0%, hwb(30deg 30% 40%)) }",
21707      &canonicalize("rgb(153, 115, 77)"),
21708    );
21709
21710    minify_test(
21711      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20% / .4), hwb(30deg 30% 40% / .8)) }",
21712      &canonicalize("rgba(143, 170, 60, 0.6)"),
21713    );
21714    minify_test(
21715      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20% / .4) 25%, hwb(30deg 30% 40% / .8)) }",
21716      &canonicalize("rgba(160, 149, 70, 0.7)"),
21717    );
21718    minify_test(
21719      ".foo { color: color-mix(in hwb, 25% hwb(120deg 10% 20% / .4), hwb(30deg 30% 40% / .8)) }",
21720      &canonicalize("rgba(160, 149, 70, 0.7)"),
21721    );
21722    minify_test(
21723      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20%), 25% hwb(30deg 30% 40% / .8)) }",
21724      &canonicalize("rgba(95, 193, 37, 0.95)"),
21725    );
21726    minify_test(
21727      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20% / .4), hwb(30deg 30% 40% / .8) 25%) }",
21728      &canonicalize("rgba(98, 184, 46, 0.5)"),
21729    );
21730    minify_test(
21731      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20% / .4) 25%, hwb(30deg 30% 40% / .8) 75%) }",
21732      &canonicalize("rgba(160, 149, 70, 0.7)"),
21733    );
21734    minify_test(
21735      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20% / .4) 30%, hwb(30deg 30% 40% / .8) 90%) }",
21736      &canonicalize("rgba(160, 149, 70, 0.7)"),
21737    ); // Scale down > 100% sum.
21738    minify_test(
21739      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20% / .4) 12.5%, hwb(30deg 30% 40% / .8) 37.5%) }",
21740      &canonicalize("rgba(160, 149, 70, 0.35)"),
21741    ); // Scale up < 100% sum, causes alpha multiplication.
21742    minify_test(
21743      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20% / .4) 0%, hwb(30deg 30% 40% / .8)) }",
21744      &canonicalize("rgba(153, 115, 77, 0.8)"),
21745    );
21746
21747    //  minify_test(".foo { color: color-mix(in hwb, hwb(40deg 30% 40%), hwb(60deg 30% 40%)) }", &canonicalize("hwb(50deg 30% 40%)"));
21748    //  minify_test(".foo { color: color-mix(in hwb, hwb(60deg 30% 40%), hwb(40deg 30% 40%)) }", &canonicalize("hwb(50deg 30% 40%)"));
21749    minify_test(
21750      ".foo { color: color-mix(in hwb, hwb(50deg 30% 40%), hwb(330deg 30% 40%)) }",
21751      &canonicalize("hwb(10deg 30% 40%)"),
21752    );
21753    minify_test(
21754      ".foo { color: color-mix(in hwb, hwb(330deg 30% 40%), hwb(50deg 30% 40%)) }",
21755      &canonicalize("hwb(10deg 30% 40%)"),
21756    );
21757    minify_test(
21758      ".foo { color: color-mix(in hwb, hwb(20deg 30% 40%), hwb(320deg 30% 40%)) }",
21759      &canonicalize("hwb(350deg 30% 40%)"),
21760    );
21761    minify_test(
21762      ".foo { color: color-mix(in hwb, hwb(320deg 30% 40%), hwb(20deg 30% 40%)) }",
21763      &canonicalize("hwb(350deg 30% 40%)"),
21764    );
21765
21766    //  minify_test(".foo { color: color-mix(in hwb shorter hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%)) }", &canonicalize("hwb(50deg 30% 40%)"));
21767    //  minify_test(".foo { color: color-mix(in hwb shorter hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%)) }", &canonicalize("hwb(50deg 30% 40%)"));
21768    minify_test(
21769      ".foo { color: color-mix(in hwb shorter hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%)) }",
21770      &canonicalize("hwb(10deg 30% 40%)"),
21771    );
21772    minify_test(
21773      ".foo { color: color-mix(in hwb shorter hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%)) }",
21774      &canonicalize("hwb(10deg 30% 40%)"),
21775    );
21776    minify_test(
21777      ".foo { color: color-mix(in hwb shorter hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%)) }",
21778      &canonicalize("hwb(350deg 30% 40%)"),
21779    );
21780    minify_test(
21781      ".foo { color: color-mix(in hwb shorter hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%)) }",
21782      &canonicalize("hwb(350deg 30% 40%)"),
21783    );
21784
21785    minify_test(
21786      ".foo { color: color-mix(in hwb longer hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%)) }",
21787      &canonicalize("hwb(230deg 30% 40%)"),
21788    );
21789    minify_test(
21790      ".foo { color: color-mix(in hwb longer hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%)) }",
21791      &canonicalize("hwb(230deg 30% 40%)"),
21792    );
21793    //  minify_test(".foo { color: color-mix(in hwb longer hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%)) }", &canonicalize("hwb(190deg 30% 40%)"));
21794    //  minify_test(".foo { color: color-mix(in hwb longer hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%)) }", &canonicalize("hwb(190deg 30% 40%)"));
21795    //  minify_test(".foo { color: color-mix(in hwb longer hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%)) }", &canonicalize("hwb(170deg 30% 40%)"));
21796    //  minify_test(".foo { color: color-mix(in hwb longer hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%)) }", &canonicalize("hwb(170deg 30% 40%)"));
21797
21798    // minify_test(".foo { color: color-mix(in hwb increasing hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%)) }", &canonicalize("hwb(50deg 30% 40%)"));
21799    minify_test(
21800      ".foo { color: color-mix(in hwb increasing hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%)) }",
21801      &canonicalize("hwb(230deg 30% 40%)"),
21802    );
21803    // minify_test(".foo { color: color-mix(in hwb increasing hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%)) }", &canonicalize("hwb(190deg 30% 40%)"));
21804    minify_test(
21805      ".foo { color: color-mix(in hwb increasing hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%)) }",
21806      &canonicalize("hwb(10deg 30% 40%)"),
21807    );
21808    // minify_test(".foo { color: color-mix(in hwb increasing hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%)) }", &canonicalize("hwb(170deg 30% 40%)"));
21809    minify_test(
21810      ".foo { color: color-mix(in hwb increasing hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%)) }",
21811      &canonicalize("hwb(350deg 30% 40%)"),
21812    );
21813
21814    minify_test(
21815      ".foo { color: color-mix(in hwb decreasing hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%)) }",
21816      &canonicalize("hwb(230deg 30% 40%)"),
21817    );
21818    // minify_test(".foo { color: color-mix(in hwb decreasing hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%)) }", &canonicalize("hwb(50deg 30% 40%)"));
21819    minify_test(
21820      ".foo { color: color-mix(in hwb decreasing hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%)) }",
21821      &canonicalize("hwb(10deg 30% 40%)"),
21822    );
21823    // minify_test(".foo { color: color-mix(in hwb decreasing hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%)) }", &canonicalize("hwb(190deg 30% 40%)"));
21824    minify_test(
21825      ".foo { color: color-mix(in hwb decreasing hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%)) }",
21826      &canonicalize("hwb(350deg 30% 40%)"),
21827    );
21828    // minify_test(".foo { color: color-mix(in hwb decreasing hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%)) }", &canonicalize("hwb(170deg 30% 40%)"));
21829
21830    // minify_test(".foo { color: color-mix(in hwb specified hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%)) }", &canonicalize("hwb(50deg 30% 40%)"));
21831    // minify_test(".foo { color: color-mix(in hwb specified hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%)) }", &canonicalize("hwb(50deg 30% 40%)"));
21832    // minify_test(".foo { color: color-mix(in hwb specified hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%)) }", &canonicalize("hwb(190deg 30% 40%)"));
21833    // minify_test(".foo { color: color-mix(in hwb specified hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%)) }", &canonicalize("hwb(190deg 30% 40%)"));
21834    // minify_test(".foo { color: color-mix(in hwb specified hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%)) }", &canonicalize("hwb(170deg 30% 40%)"));
21835    // minify_test(".foo { color: color-mix(in hwb specified hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%)) }", &canonicalize("hwb(170deg 30% 40%)"));
21836
21837    minify_test(
21838      ".foo { color: color-mix(in hwb, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%) }",
21839      &canonicalize("rgb(0, 249, 66)"),
21840    ); // Naive clip based mapping would give rgb(0, 255, 0).
21841    minify_test(
21842      ".foo { color: color-mix(in hwb, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%) }",
21843      &canonicalize("rgb(255, 255, 255)"),
21844    ); // Naive clip based mapping would give rgb(255, 150, 255).
21845    minify_test(
21846      ".foo { color: color-mix(in hwb, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%) }",
21847      &canonicalize("rgb(42, 0, 34)"),
21848    ); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
21849    minify_test(
21850      ".foo { color: color-mix(in hwb, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%) }",
21851      &canonicalize("rgb(255, 255, 255)"),
21852    ); // Naive clip based mapping would give rgb(255, 150, 255).
21853    minify_test(
21854      ".foo { color: color-mix(in hwb, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%) }",
21855      &canonicalize("rgb(42, 0, 34)"),
21856    ); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
21857    minify_test(
21858      ".foo { color: color-mix(in hwb, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%) }",
21859      &canonicalize("rgb(255, 255, 255)"),
21860    ); // Naive clip based mapping would give rgb(255, 92, 255).
21861    minify_test(
21862      ".foo { color: color-mix(in hwb, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%) }",
21863      &canonicalize("rgb(0, 0, 0)"),
21864    ); // Naive clip based mapping would give rgb(19, 0, 24).
21865    minify_test(
21866      ".foo { color: color-mix(in hwb, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%) }",
21867      &canonicalize("rgb(255, 255, 255)"),
21868    ); // Naive clip based mapping would give rgb(255, 91, 255).
21869    minify_test(
21870      ".foo { color: color-mix(in hwb, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%) }",
21871      &canonicalize("rgb(0, 0, 0)"),
21872    ); // Naive clip based mapping would give rgb(20, 0, 24).
21873
21874    for color_space in &["lch", "oklch"] {
21875      // regex for converting web platform tests:
21876      // test_computed_value\(.*?, `color-mix\(in \$\{colorSpace\}(.*?), (.*?)\$\{colorSpace\}(.*?) \$\{colorSpace\}(.*?)`, `\$\{colorSpace\}(.*?)`\);
21877      // minify_test(&format!(".foo {{ color: color-mix(in {0}$1, $2{0}$3 {0}$4 }}", color_space), &format!(".foo{{color:{}$5}}", color_space));
21878
21879      minify_test(
21880        &format!(
21881          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg), {0}(50% 60 70deg)) }}",
21882          color_space
21883        ),
21884        &format!(".foo{{color:{}(30% 40 50)}}", color_space),
21885      );
21886      minify_test(
21887        &format!(
21888          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg) 25%, {0}(50% 60 70deg)) }}",
21889          color_space
21890        ),
21891        &format!(".foo{{color:{}(40% 50 60)}}", color_space),
21892      );
21893      minify_test(
21894        &format!(
21895          ".foo {{ color: color-mix(in {0}, 25% {0}(10% 20 30deg), {0}(50% 60 70deg)) }}",
21896          color_space
21897        ),
21898        &format!(".foo{{color:{}(40% 50 60)}}", color_space),
21899      );
21900      minify_test(
21901        &format!(
21902          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg), 25% {0}(50% 60 70deg)) }}",
21903          color_space
21904        ),
21905        &format!(".foo{{color:{}(20% 30 40)}}", color_space),
21906      );
21907      minify_test(
21908        &format!(
21909          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg), {0}(50% 60 70deg) 25%) }}",
21910          color_space
21911        ),
21912        &format!(".foo{{color:{}(20% 30 40)}}", color_space),
21913      );
21914      minify_test(
21915        &format!(
21916          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg) 25%, {0}(50% 60 70deg) 75%) }}",
21917          color_space
21918        ),
21919        &format!(".foo{{color:{}(40% 50 60)}}", color_space),
21920      );
21921      minify_test(
21922        &format!(
21923          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg) 30%, {0}(50% 60 70deg) 90%) }}",
21924          color_space
21925        ),
21926        &format!(".foo{{color:{}(40% 50 60)}}", color_space),
21927      ); // Scale down > 100% sum.
21928      minify_test(
21929        &format!(
21930          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg) 12.5%, {0}(50% 60 70deg) 37.5%) }}",
21931          color_space
21932        ),
21933        &format!(".foo{{color:{}(40% 50 60/.5)}}", color_space),
21934      ); // Scale up < 100% sum, causes alpha multiplication.
21935      minify_test(
21936        &format!(
21937          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg) 0%, {0}(50% 60 70deg)) }}",
21938          color_space
21939        ),
21940        &format!(".foo{{color:{}(50% 60 70)}}", color_space),
21941      );
21942
21943      minify_test(
21944        &format!(
21945          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg / .4), {0}(50% 60 70deg / .8)) }}",
21946          color_space
21947        ),
21948        &format!(".foo{{color:{}(36.6667% 46.6667 50/.6)}}", color_space),
21949      );
21950      minify_test(
21951        &format!(
21952          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg / .4) 25%, {0}(50% 60 70deg / .8)) }}",
21953          color_space
21954        ),
21955        &format!(".foo{{color:{}(44.2857% 54.2857 60/.7)}}", color_space),
21956      );
21957      minify_test(
21958        &format!(
21959          ".foo {{ color: color-mix(in {0}, 25% {0}(10% 20 30deg / .4), {0}(50% 60 70deg / .8)) }}",
21960          color_space
21961        ),
21962        &format!(".foo{{color:{}(44.2857% 54.2857 60/.7)}}", color_space),
21963      );
21964      minify_test(
21965        &format!(
21966          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg / .4), 25% {0}(50% 60 70deg / .8)) }}",
21967          color_space
21968        ),
21969        &format!(".foo{{color:{}(26% 36 40/.5)}}", color_space),
21970      );
21971      minify_test(
21972        &format!(
21973          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg / .4), {0}(50% 60 70deg / .8) 25%) }}",
21974          color_space
21975        ),
21976        &format!(".foo{{color:{}(26% 36 40/.5)}}", color_space),
21977      );
21978      minify_test(
21979        &format!(
21980          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg / .4) 25%, {0}(50% 60 70deg / .8) 75%) }}",
21981          color_space
21982        ),
21983        &format!(".foo{{color:{}(44.2857% 54.2857 60/.7)}}", color_space),
21984      );
21985      minify_test(
21986        &format!(
21987          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg / .4) 30%, {0}(50% 60 70deg / .8) 90%) }}",
21988          color_space
21989        ),
21990        &format!(".foo{{color:{}(44.2857% 54.2857 60/.7)}}", color_space),
21991      ); // Scale down > 100% sum.
21992      minify_test(
21993        &format!(
21994          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg / .4) 12.5%, {0}(50% 60 70deg / .8) 37.5%) }}",
21995          color_space
21996        ),
21997        &format!(".foo{{color:{}(44.2857% 54.2857 60/.35)}}", color_space),
21998      ); // Scale up < 100% sum, causes alpha multiplication.
21999      minify_test(
22000        &format!(
22001          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg / .4) 0%, {0}(50% 60 70deg / .8)) }}",
22002          color_space
22003        ),
22004        &format!(".foo{{color:{}(50% 60 70/.8)}}", color_space),
22005      );
22006
22007      minify_test(
22008        &format!(
22009          ".foo {{ color: color-mix(in {0}, {0}(100% 0 40deg), {0}(100% 0 60deg)) }}",
22010          color_space
22011        ),
22012        &format!(".foo{{color:{}(100% 0 50)}}", color_space),
22013      );
22014      minify_test(
22015        &format!(
22016          ".foo {{ color: color-mix(in {0}, {0}(100% 0 60deg), {0}(100% 0 40deg)) }}",
22017          color_space
22018        ),
22019        &format!(".foo{{color:{}(100% 0 50)}}", color_space),
22020      );
22021      minify_test(
22022        &format!(
22023          ".foo {{ color: color-mix(in {0}, {0}(100% 0 50deg), {0}(100% 0 330deg)) }}",
22024          color_space
22025        ),
22026        &format!(".foo{{color:{}(100% 0 10)}}", color_space),
22027      );
22028      minify_test(
22029        &format!(
22030          ".foo {{ color: color-mix(in {0}, {0}(100% 0 330deg), {0}(100% 0 50deg)) }}",
22031          color_space
22032        ),
22033        &format!(".foo{{color:{}(100% 0 10)}}", color_space),
22034      );
22035      minify_test(
22036        &format!(
22037          ".foo {{ color: color-mix(in {0}, {0}(100% 0 20deg), {0}(100% 0 320deg)) }}",
22038          color_space
22039        ),
22040        &format!(".foo{{color:{}(100% 0 350)}}", color_space),
22041      );
22042      minify_test(
22043        &format!(
22044          ".foo {{ color: color-mix(in {0}, {0}(100% 0 320deg), {0}(100% 0 20deg)) }}",
22045          color_space
22046        ),
22047        &format!(".foo{{color:{}(100% 0 350)}}", color_space),
22048      );
22049
22050      minify_test(
22051        &format!(
22052          ".foo {{ color: color-mix(in {0} shorter hue, {0}(100% 0 40deg), {0}(100% 0 60deg)) }}",
22053          color_space
22054        ),
22055        &format!(".foo{{color:{}(100% 0 50)}}", color_space),
22056      );
22057      minify_test(
22058        &format!(
22059          ".foo {{ color: color-mix(in {0} shorter hue, {0}(100% 0 60deg), {0}(100% 0 40deg)) }}",
22060          color_space
22061        ),
22062        &format!(".foo{{color:{}(100% 0 50)}}", color_space),
22063      );
22064      minify_test(
22065        &format!(
22066          ".foo {{ color: color-mix(in {0} shorter hue, {0}(100% 0 50deg), {0}(100% 0 330deg)) }}",
22067          color_space
22068        ),
22069        &format!(".foo{{color:{}(100% 0 10)}}", color_space),
22070      );
22071      minify_test(
22072        &format!(
22073          ".foo {{ color: color-mix(in {0} shorter hue, {0}(100% 0 330deg), {0}(100% 0 50deg)) }}",
22074          color_space
22075        ),
22076        &format!(".foo{{color:{}(100% 0 10)}}", color_space),
22077      );
22078      minify_test(
22079        &format!(
22080          ".foo {{ color: color-mix(in {0} shorter hue, {0}(100% 0 20deg), {0}(100% 0 320deg)) }}",
22081          color_space
22082        ),
22083        &format!(".foo{{color:{}(100% 0 350)}}", color_space),
22084      );
22085      minify_test(
22086        &format!(
22087          ".foo {{ color: color-mix(in {0} shorter hue, {0}(100% 0 320deg), {0}(100% 0 20deg)) }}",
22088          color_space
22089        ),
22090        &format!(".foo{{color:{}(100% 0 350)}}", color_space),
22091      );
22092
22093      minify_test(
22094        &format!(
22095          ".foo {{ color: color-mix(in {0} longer hue, {0}(100% 0 40deg), {0}(100% 0 60deg)) }}",
22096          color_space
22097        ),
22098        &format!(".foo{{color:{}(100% 0 230)}}", color_space),
22099      );
22100      minify_test(
22101        &format!(
22102          ".foo {{ color: color-mix(in {0} longer hue, {0}(100% 0 60deg), {0}(100% 0 40deg)) }}",
22103          color_space
22104        ),
22105        &format!(".foo{{color:{}(100% 0 230)}}", color_space),
22106      );
22107      minify_test(
22108        &format!(
22109          ".foo {{ color: color-mix(in {0} longer hue, {0}(100% 0 50deg), {0}(100% 0 330deg)) }}",
22110          color_space
22111        ),
22112        &format!(".foo{{color:{}(100% 0 190)}}", color_space),
22113      );
22114      minify_test(
22115        &format!(
22116          ".foo {{ color: color-mix(in {0} longer hue, {0}(100% 0 330deg), {0}(100% 0 50deg)) }}",
22117          color_space
22118        ),
22119        &format!(".foo{{color:{}(100% 0 190)}}", color_space),
22120      );
22121      minify_test(
22122        &format!(
22123          ".foo {{ color: color-mix(in {0} longer hue, {0}(100% 0 20deg), {0}(100% 0 320deg)) }}",
22124          color_space
22125        ),
22126        &format!(".foo{{color:{}(100% 0 170)}}", color_space),
22127      );
22128      minify_test(
22129        &format!(
22130          ".foo {{ color: color-mix(in {0} longer hue, {0}(100% 0 320deg), {0}(100% 0 20deg)) }}",
22131          color_space
22132        ),
22133        &format!(".foo{{color:{}(100% 0 170)}}", color_space),
22134      );
22135
22136      minify_test(
22137        &format!(
22138          ".foo {{ color: color-mix(in {0} increasing hue, {0}(100% 0 40deg), {0}(100% 0 60deg)) }}",
22139          color_space
22140        ),
22141        &format!(".foo{{color:{}(100% 0 50)}}", color_space),
22142      );
22143      minify_test(
22144        &format!(
22145          ".foo {{ color: color-mix(in {0} increasing hue, {0}(100% 0 60deg), {0}(100% 0 40deg)) }}",
22146          color_space
22147        ),
22148        &format!(".foo{{color:{}(100% 0 230)}}", color_space),
22149      );
22150      minify_test(
22151        &format!(
22152          ".foo {{ color: color-mix(in {0} increasing hue, {0}(100% 0 50deg), {0}(100% 0 330deg)) }}",
22153          color_space
22154        ),
22155        &format!(".foo{{color:{}(100% 0 190)}}", color_space),
22156      );
22157      minify_test(
22158        &format!(
22159          ".foo {{ color: color-mix(in {0} increasing hue, {0}(100% 0 330deg), {0}(100% 0 50deg)) }}",
22160          color_space
22161        ),
22162        &format!(".foo{{color:{}(100% 0 10)}}", color_space),
22163      );
22164      minify_test(
22165        &format!(
22166          ".foo {{ color: color-mix(in {0} increasing hue, {0}(100% 0 20deg), {0}(100% 0 320deg)) }}",
22167          color_space
22168        ),
22169        &format!(".foo{{color:{}(100% 0 170)}}", color_space),
22170      );
22171      minify_test(
22172        &format!(
22173          ".foo {{ color: color-mix(in {0} increasing hue, {0}(100% 0 320deg), {0}(100% 0 20deg)) }}",
22174          color_space
22175        ),
22176        &format!(".foo{{color:{}(100% 0 350)}}", color_space),
22177      );
22178
22179      minify_test(
22180        &format!(
22181          ".foo {{ color: color-mix(in {0} decreasing hue, {0}(100% 0 40deg), {0}(100% 0 60deg)) }}",
22182          color_space
22183        ),
22184        &format!(".foo{{color:{}(100% 0 230)}}", color_space),
22185      );
22186      minify_test(
22187        &format!(
22188          ".foo {{ color: color-mix(in {0} decreasing hue, {0}(100% 0 60deg), {0}(100% 0 40deg)) }}",
22189          color_space
22190        ),
22191        &format!(".foo{{color:{}(100% 0 50)}}", color_space),
22192      );
22193      minify_test(
22194        &format!(
22195          ".foo {{ color: color-mix(in {0} decreasing hue, {0}(100% 0 50deg), {0}(100% 0 330deg)) }}",
22196          color_space
22197        ),
22198        &format!(".foo{{color:{}(100% 0 10)}}", color_space),
22199      );
22200      minify_test(
22201        &format!(
22202          ".foo {{ color: color-mix(in {0} decreasing hue, {0}(100% 0 330deg), {0}(100% 0 50deg)) }}",
22203          color_space
22204        ),
22205        &format!(".foo{{color:{}(100% 0 190)}}", color_space),
22206      );
22207      minify_test(
22208        &format!(
22209          ".foo {{ color: color-mix(in {0} decreasing hue, {0}(100% 0 20deg), {0}(100% 0 320deg)) }}",
22210          color_space
22211        ),
22212        &format!(".foo{{color:{}(100% 0 350)}}", color_space),
22213      );
22214      minify_test(
22215        &format!(
22216          ".foo {{ color: color-mix(in {0} decreasing hue, {0}(100% 0 320deg), {0}(100% 0 20deg)) }}",
22217          color_space
22218        ),
22219        &format!(".foo{{color:{}(100% 0 170)}}", color_space),
22220      );
22221
22222      minify_test(
22223        &format!(
22224          ".foo {{ color: color-mix(in {0} specified hue, {0}(100% 0 40deg), {0}(100% 0 60deg)) }}",
22225          color_space
22226        ),
22227        &format!(".foo{{color:{}(100% 0 50)}}", color_space),
22228      );
22229      minify_test(
22230        &format!(
22231          ".foo {{ color: color-mix(in {0} specified hue, {0}(100% 0 60deg), {0}(100% 0 40deg)) }}",
22232          color_space
22233        ),
22234        &format!(".foo{{color:{}(100% 0 50)}}", color_space),
22235      );
22236      minify_test(
22237        &format!(
22238          ".foo {{ color: color-mix(in {0} specified hue, {0}(100% 0 50deg), {0}(100% 0 330deg)) }}",
22239          color_space
22240        ),
22241        &format!(".foo{{color:{}(100% 0 190)}}", color_space),
22242      );
22243      minify_test(
22244        &format!(
22245          ".foo {{ color: color-mix(in {0} specified hue, {0}(100% 0 330deg), {0}(100% 0 50deg)) }}",
22246          color_space
22247        ),
22248        &format!(".foo{{color:{}(100% 0 190)}}", color_space),
22249      );
22250      minify_test(
22251        &format!(
22252          ".foo {{ color: color-mix(in {0} specified hue, {0}(100% 0 20deg), {0}(100% 0 320deg)) }}",
22253          color_space
22254        ),
22255        &format!(".foo{{color:{}(100% 0 170)}}", color_space),
22256      );
22257      minify_test(
22258        &format!(
22259          ".foo {{ color: color-mix(in {0} specified hue, {0}(100% 0 320deg), {0}(100% 0 20deg)) }}",
22260          color_space
22261        ),
22262        &format!(".foo{{color:{}(100% 0 170)}}", color_space),
22263      );
22264
22265      minify_test(
22266        &format!(
22267          ".foo {{ color: color-mix(in {0}, {0}(none none none), {0}(none none none)) }}",
22268          color_space
22269        ),
22270        &format!(".foo{{color:{}(none none none)}}", color_space),
22271      );
22272      minify_test(
22273        &format!(
22274          ".foo {{ color: color-mix(in {0}, {0}(none none none), {0}(50% 60 70deg)) }}",
22275          color_space
22276        ),
22277        &format!(".foo{{color:{}(50% 60 70)}}", color_space),
22278      );
22279      minify_test(
22280        &format!(
22281          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg), {0}(none none none)) }}",
22282          color_space
22283        ),
22284        &format!(".foo{{color:{}(10% 20 30)}}", color_space),
22285      );
22286      minify_test(
22287        &format!(
22288          ".foo {{ color: color-mix(in {0}, {0}(10% 20 none), {0}(50% 60 70deg)) }}",
22289          color_space
22290        ),
22291        &format!(".foo{{color:{}(30% 40 70)}}", color_space),
22292      );
22293      minify_test(
22294        &format!(
22295          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg), {0}(50% 60 none)) }}",
22296          color_space
22297        ),
22298        &format!(".foo{{color:{}(30% 40 30)}}", color_space),
22299      );
22300      minify_test(
22301        &format!(
22302          ".foo {{ color: color-mix(in {0}, {0}(none 20 30deg), {0}(50% none 70deg)) }}",
22303          color_space
22304        ),
22305        &format!(".foo{{color:{}(50% 20 50)}}", color_space),
22306      );
22307      minify_test(
22308        &format!(
22309          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg / none), {0}(50% 60 70deg)) }}",
22310          color_space
22311        ),
22312        &format!(".foo{{color:{}(30% 40 50)}}", color_space),
22313      );
22314      minify_test(
22315        &format!(
22316          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg / none), {0}(50% 60 70deg / 0.5)) }}",
22317          color_space
22318        ),
22319        &format!(".foo{{color:{}(30% 40 50/.5)}}", color_space),
22320      );
22321      minify_test(
22322        &format!(
22323          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg / none), {0}(50% 60 70deg / none)) }}",
22324          color_space
22325        ),
22326        &format!(".foo{{color:{}(30% 40 50/none)}}", color_space),
22327      );
22328    }
22329
22330    for color_space in ["lab", "oklab"] {
22331      minify_test(
22332        &format!(
22333          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30), {0}(50% 60 70)) }}",
22334          color_space
22335        ),
22336        &format!(".foo{{color:{}(30% 40 50)}}", color_space),
22337      );
22338      minify_test(
22339        &format!(
22340          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30) 25%, {0}(50% 60 70)) }}",
22341          color_space
22342        ),
22343        &format!(".foo{{color:{}(40% 50 60)}}", color_space),
22344      );
22345      minify_test(
22346        &format!(
22347          ".foo {{ color: color-mix(in {0}, 25% {0}(10% 20 30), {0}(50% 60 70)) }}",
22348          color_space
22349        ),
22350        &format!(".foo{{color:{}(40% 50 60)}}", color_space),
22351      );
22352      minify_test(
22353        &format!(
22354          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30), 25% {0}(50% 60 70)) }}",
22355          color_space
22356        ),
22357        &format!(".foo{{color:{}(20% 30 40)}}", color_space),
22358      );
22359      minify_test(
22360        &format!(
22361          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30), {0}(50% 60 70) 25%) }}",
22362          color_space
22363        ),
22364        &format!(".foo{{color:{}(20% 30 40)}}", color_space),
22365      );
22366      minify_test(
22367        &format!(
22368          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30) 25%, {0}(50% 60 70) 75%) }}",
22369          color_space
22370        ),
22371        &format!(".foo{{color:{}(40% 50 60)}}", color_space),
22372      );
22373      minify_test(
22374        &format!(
22375          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30) 30%, {0}(50% 60 70) 90%) }}",
22376          color_space
22377        ),
22378        &format!(".foo{{color:{}(40% 50 60)}}", color_space),
22379      ); // Scale down > 100% sum.
22380      minify_test(
22381        &format!(
22382          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30) 12.5%, {0}(50% 60 70) 37.5%) }}",
22383          color_space
22384        ),
22385        &format!(".foo{{color:{}(40% 50 60/.5)}}", color_space),
22386      ); // Scale up < 100% sum, causes alpha multiplication.
22387      minify_test(
22388        &format!(
22389          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30) 0%, {0}(50% 60 70)) }}",
22390          color_space
22391        ),
22392        &format!(".foo{{color:{}(50% 60 70)}}", color_space),
22393      );
22394
22395      minify_test(
22396        &format!(
22397          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30 / .4), {0}(50% 60 70 / .8)) }}",
22398          color_space
22399        ),
22400        &format!(".foo{{color:{}(36.6667% 46.6667 56.6667/.6)}}", color_space),
22401      );
22402      minify_test(
22403        &format!(
22404          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30 / .4) 25%, {0}(50% 60 70 / .8)) }}",
22405          color_space
22406        ),
22407        &format!(".foo{{color:{}(44.2857% 54.2857 64.2857/.7)}}", color_space),
22408      );
22409      minify_test(
22410        &format!(
22411          ".foo {{ color: color-mix(in {0}, 25% {0}(10% 20 30 / .4), {0}(50% 60 70 / .8)) }}",
22412          color_space
22413        ),
22414        &format!(".foo{{color:{}(44.2857% 54.2857 64.2857/.7)}}", color_space),
22415      );
22416      minify_test(
22417        &format!(
22418          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30 / .4), 25% {0}(50% 60 70 / .8)) }}",
22419          color_space
22420        ),
22421        &format!(".foo{{color:{}(26% 36 46/.5)}}", color_space),
22422      );
22423      minify_test(
22424        &format!(
22425          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30 / .4), {0}(50% 60 70 / .8) 25%) }}",
22426          color_space
22427        ),
22428        &format!(".foo{{color:{}(26% 36 46/.5)}}", color_space),
22429      );
22430      minify_test(
22431        &format!(
22432          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30 / .4) 25%, {0}(50% 60 70 / .8) 75%) }}",
22433          color_space
22434        ),
22435        &format!(".foo{{color:{}(44.2857% 54.2857 64.2857/.7)}}", color_space),
22436      );
22437      minify_test(
22438        &format!(
22439          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30 / .4) 30%, {0}(50% 60 70 / .8) 90%) }}",
22440          color_space
22441        ),
22442        &format!(".foo{{color:{}(44.2857% 54.2857 64.2857/.7)}}", color_space),
22443      ); // Scale down > 100% sum.
22444      minify_test(
22445        &format!(
22446          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30 / .4) 12.5%, {0}(50% 60 70 / .8) 37.5%) }}",
22447          color_space
22448        ),
22449        &format!(".foo{{color:{}(44.2857% 54.2857 64.2857/.35)}}", color_space),
22450      ); // Scale up < 100% sum, causes alpha multiplication.
22451      minify_test(
22452        &format!(
22453          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30 / .4) 0%, {0}(50% 60 70 / .8)) }}",
22454          color_space
22455        ),
22456        &format!(".foo{{color:{}(50% 60 70/.8)}}", color_space),
22457      );
22458
22459      minify_test(
22460        &format!(
22461          ".foo {{ color: color-mix(in {0}, {0}(none none none), {0}(none none none)) }}",
22462          color_space
22463        ),
22464        &format!(".foo{{color:{}(none none none)}}", color_space),
22465      );
22466      minify_test(
22467        &format!(
22468          ".foo {{ color: color-mix(in {0}, {0}(none none none), {0}(50% 60 70)) }}",
22469          color_space
22470        ),
22471        &format!(".foo{{color:{}(50% 60 70)}}", color_space),
22472      );
22473      minify_test(
22474        &format!(
22475          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30), {0}(none none none)) }}",
22476          color_space
22477        ),
22478        &format!(".foo{{color:{}(10% 20 30)}}", color_space),
22479      );
22480      minify_test(
22481        &format!(
22482          ".foo {{ color: color-mix(in {0}, {0}(10% 20 none), {0}(50% 60 70)) }}",
22483          color_space
22484        ),
22485        &format!(".foo{{color:{}(30% 40 70)}}", color_space),
22486      );
22487      minify_test(
22488        &format!(
22489          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30), {0}(50% 60 none)) }}",
22490          color_space
22491        ),
22492        &format!(".foo{{color:{}(30% 40 30)}}", color_space),
22493      );
22494      minify_test(
22495        &format!(
22496          ".foo {{ color: color-mix(in {0}, {0}(none 20 30), {0}(50% none 70)) }}",
22497          color_space
22498        ),
22499        &format!(".foo{{color:{}(50% 20 50)}}", color_space),
22500      );
22501      minify_test(
22502        &format!(
22503          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30 / none), {0}(50% 60 70)) }}",
22504          color_space
22505        ),
22506        &format!(".foo{{color:{}(30% 40 50)}}", color_space),
22507      );
22508      minify_test(
22509        &format!(
22510          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30 / none), {0}(50% 60 70 / 0.5)) }}",
22511          color_space
22512        ),
22513        &format!(".foo{{color:{}(30% 40 50/.5)}}", color_space),
22514      );
22515      minify_test(
22516        &format!(
22517          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30 / none), {0}(50% 60 70 / none)) }}",
22518          color_space
22519        ),
22520        &format!(".foo{{color:{}(30% 40 50/none)}}", color_space),
22521      );
22522    }
22523
22524    for color_space in [/*"srgb", */ "srgb-linear", "xyz", "xyz-d50", "xyz-d65"] {
22525      // regex for converting web platform tests:
22526      // test_computed_value\(.*?, `color-mix\(in \$\{colorSpace\}(.*?), (.*?)color\(\$\{colorSpace\}(.*?) color\(\$\{colorSpace\}(.*?)`, `color\(\$\{resultColorSpace\}(.*?)`\);
22527      // 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));
22528
22529      let result_color_space = if color_space == "xyz-d65" { "xyz" } else { color_space };
22530
22531      minify_test(
22532        &format!(
22533          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3), color({0} .5 .6 .7)) }}",
22534          color_space
22535        ),
22536        &format!(".foo{{color:color({} .3 .4 .5)}}", result_color_space),
22537      );
22538      minify_test(
22539        &format!(
22540          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3) 25%, color({0} .5 .6 .7)) }}",
22541          color_space
22542        ),
22543        &format!(".foo{{color:color({} .4 .5 .6)}}", result_color_space),
22544      );
22545      minify_test(
22546        &format!(
22547          ".foo {{ color: color-mix(in {0}, 25% color({0} .1 .2 .3), color({0} .5 .6 .7)) }}",
22548          color_space
22549        ),
22550        &format!(".foo{{color:color({} .4 .5 .6)}}", result_color_space),
22551      );
22552      minify_test(
22553        &format!(
22554          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3), color({0} .5 .6 .7) 25%) }}",
22555          color_space
22556        ),
22557        &format!(".foo{{color:color({} .2 .3 .4)}}", result_color_space),
22558      );
22559      minify_test(
22560        &format!(
22561          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3), 25% color({0} .5 .6 .7)) }}",
22562          color_space
22563        ),
22564        &format!(".foo{{color:color({} .2 .3 .4)}}", result_color_space),
22565      );
22566      minify_test(
22567        &format!(
22568          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3) 25%, color({0} .5 .6 .7) 75%) }}",
22569          color_space
22570        ),
22571        &format!(".foo{{color:color({} .4 .5 .6)}}", result_color_space),
22572      );
22573      minify_test(
22574        &format!(
22575          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3) 30%, color({0} .5 .6 .7) 90%) }}",
22576          color_space
22577        ),
22578        &format!(".foo{{color:color({} .4 .5 .6)}}", result_color_space),
22579      ); // Scale down > 100% sum.
22580      minify_test(
22581        &format!(
22582          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3) 12.5%, color({0} .5 .6 .7) 37.5%) }}",
22583          color_space
22584        ),
22585        &format!(".foo{{color:color({} .4 .5 .6/.5)}}", result_color_space),
22586      ); // Scale up < 100% sum, causes alpha multiplication.
22587      minify_test(
22588        &format!(
22589          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3) 0%, color({0} .5 .6 .7)) }}",
22590          color_space
22591        ),
22592        &format!(".foo{{color:color({} .5 .6 .7)}}", result_color_space),
22593      );
22594
22595      minify_test(
22596        &format!(
22597          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3 / .5), color({0} .5 .6 .7 / .8)) }}",
22598          color_space
22599        ),
22600        &format!(
22601          ".foo{{color:color({} .346154 .446154 .546154/.65)}}",
22602          result_color_space
22603        ),
22604      );
22605      minify_test(
22606        &format!(
22607          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3 / .4) 25%, color({0} .5 .6 .7 / .8)) }}",
22608          color_space
22609        ),
22610        &format!(".foo{{color:color({} .442857 .542857 .642857/.7)}}", result_color_space),
22611      );
22612      minify_test(
22613        &format!(
22614          ".foo {{ color: color-mix(in {0}, 25% color({0} .1 .2 .3 / .4), color({0} .5 .6 .7 / .8)) }}",
22615          color_space
22616        ),
22617        &format!(".foo{{color:color({} .442857 .542857 .642857/.7)}}", result_color_space),
22618      );
22619      minify_test(
22620        &format!(
22621          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3 / .4), color({0} .5 .6 .7 / .8) 25%) }}",
22622          color_space
22623        ),
22624        &format!(".foo{{color:color({} .26 .36 .46/.5)}}", result_color_space),
22625      );
22626      minify_test(
22627        &format!(
22628          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3 / .4), 25% color({0} .5 .6 .7 / .8)) }}",
22629          color_space
22630        ),
22631        &format!(".foo{{color:color({} .26 .36 .46/.5)}}", result_color_space),
22632      );
22633      minify_test(
22634        &format!(
22635          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3 / .4) 25%, color({0} .5 .6 .7 / .8) 75%) }}",
22636          color_space
22637        ),
22638        &format!(".foo{{color:color({} .442857 .542857 .642857/.7)}}", result_color_space),
22639      );
22640      minify_test(
22641        &format!(
22642          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3 / .4) 30%, color({0} .5 .6 .7 / .8) 90%) }}",
22643          color_space
22644        ),
22645        &format!(".foo{{color:color({} .442857 .542857 .642857/.7)}}", result_color_space),
22646      ); // Scale down > 100% sum.
22647      minify_test(
22648        &format!(
22649          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3 / .4) 12.5%, color({0} .5 .6 .7 / .8) 37.5%) }}",
22650          color_space
22651        ),
22652        &format!(
22653          ".foo{{color:color({} .442857 .542857 .642857/.35)}}",
22654          result_color_space
22655        ),
22656      ); // Scale up < 100% sum, causes alpha multiplication.
22657      minify_test(
22658        &format!(
22659          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3 / .4) 0%, color({0} .5 .6 .7 / .8)) }}",
22660          color_space
22661        ),
22662        &format!(".foo{{color:color({} .5 .6 .7/.8)}}", result_color_space),
22663      );
22664
22665      minify_test(
22666        &format!(
22667          ".foo {{ color: color-mix(in {0}, color({0} 2 3 4 / 5), color({0} 4 6 8 / 10)) }}",
22668          color_space
22669        ),
22670        &format!(".foo{{color:color({} 3 4.5 6)}}", result_color_space),
22671      );
22672      minify_test(
22673        &format!(
22674          ".foo {{ color: color-mix(in {0}, color({0} -2 -3 -4), color({0} -4 -6 -8)) }}",
22675          color_space
22676        ),
22677        &format!(".foo{{color:color({} -3 -4.5 -6)}}", result_color_space),
22678      );
22679      minify_test(
22680        &format!(
22681          ".foo {{ color: color-mix(in {0}, color({0} -2 -3 -4 / -5), color({0} -4 -6 -8 / -10)) }}",
22682          color_space
22683        ),
22684        &format!(".foo{{color:color({} 0 0 0/0)}}", result_color_space),
22685      );
22686
22687      minify_test(
22688        &format!(
22689          ".foo {{ color: color-mix(in {0}, color({0} none none none), color({0} none none none)) }}",
22690          color_space
22691        ),
22692        &format!(".foo{{color:color({} none none none)}}", result_color_space),
22693      );
22694      minify_test(
22695        &format!(
22696          ".foo {{ color: color-mix(in {0}, color({0} none none none), color({0} .5 .6 .7)) }}",
22697          color_space
22698        ),
22699        &format!(".foo{{color:color({} .5 .6 .7)}}", result_color_space),
22700      );
22701      minify_test(
22702        &format!(
22703          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3), color({0} none none none)) }}",
22704          color_space
22705        ),
22706        &format!(".foo{{color:color({} .1 .2 .3)}}", result_color_space),
22707      );
22708      minify_test(
22709        &format!(
22710          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 none), color({0} .5 .6 .7)) }}",
22711          color_space
22712        ),
22713        &format!(".foo{{color:color({} .3 .4 .7)}}", result_color_space),
22714      );
22715      minify_test(
22716        &format!(
22717          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3), color({0} .5 .6 none)) }}",
22718          color_space
22719        ),
22720        &format!(".foo{{color:color({} .3 .4 .3)}}", result_color_space),
22721      );
22722      minify_test(
22723        &format!(
22724          ".foo {{ color: color-mix(in {0}, color({0} none .2 .3), color({0} .5 none .7)) }}",
22725          color_space
22726        ),
22727        &format!(".foo{{color:color({} .5 .2 .5)}}", result_color_space),
22728      );
22729      minify_test(
22730        &format!(
22731          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3 / none), color({0} .5 .6 .7)) }}",
22732          color_space
22733        ),
22734        &format!(".foo{{color:color({} .3 .4 .5)}}", result_color_space),
22735      );
22736      minify_test(
22737        &format!(
22738          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3 / none), color({0} .5 .6 .7 / 0.5)) }}",
22739          color_space
22740        ),
22741        &format!(".foo{{color:color({} .3 .4 .5/.5)}}", result_color_space),
22742      );
22743      minify_test(
22744        &format!(
22745          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3 / none), color({0} .5 .6 .7 / none)) }}",
22746          color_space
22747        ),
22748        &format!(".foo{{color:color({} .3 .4 .5/none)}}", result_color_space),
22749      );
22750    }
22751  }
22752
22753  #[test]
22754  fn test_grid() {
22755    minify_test(
22756      ".foo { grid-template-columns: [first nav-start]  150px [main-start] 1fr [last]; }",
22757      ".foo{grid-template-columns:[first nav-start]150px[main-start]1fr[last]}",
22758    );
22759    minify_test(
22760      ".foo { grid-template-columns: 150px 1fr; }",
22761      ".foo{grid-template-columns:150px 1fr}",
22762    );
22763    minify_test(
22764      ".foo { grid-template-columns: repeat(4, 1fr); }",
22765      ".foo{grid-template-columns:repeat(4,1fr)}",
22766    );
22767    minify_test(
22768      ".foo { grid-template-columns: repeat(2, [e] 40px); }",
22769      ".foo{grid-template-columns:repeat(2,[e]40px)}",
22770    );
22771    minify_test(
22772      ".foo { grid-template-columns: repeat(4, [col-start] 250px [col-end]); }",
22773      ".foo{grid-template-columns:repeat(4,[col-start]250px[col-end])}",
22774    );
22775    minify_test(
22776      ".foo { grid-template-columns: repeat(4, [col-start] 60% [col-end]); }",
22777      ".foo{grid-template-columns:repeat(4,[col-start]60%[col-end])}",
22778    );
22779    minify_test(
22780      ".foo { grid-template-columns: repeat(4, [col-start] 1fr [col-end]); }",
22781      ".foo{grid-template-columns:repeat(4,[col-start]1fr[col-end])}",
22782    );
22783    minify_test(
22784      ".foo { grid-template-columns: repeat(4, [col-start] min-content [col-end]); }",
22785      ".foo{grid-template-columns:repeat(4,[col-start]min-content[col-end])}",
22786    );
22787    minify_test(
22788      ".foo { grid-template-columns: repeat(4, [col-start] max-content [col-end]); }",
22789      ".foo{grid-template-columns:repeat(4,[col-start]max-content[col-end])}",
22790    );
22791    minify_test(
22792      ".foo { grid-template-columns: repeat(4, [col-start] auto [col-end]); }",
22793      ".foo{grid-template-columns:repeat(4,[col-start]auto[col-end])}",
22794    );
22795    minify_test(
22796      ".foo { grid-template-columns: repeat(4, [col-start] minmax(100px, 1fr) [col-end]); }",
22797      ".foo{grid-template-columns:repeat(4,[col-start]minmax(100px,1fr)[col-end])}",
22798    );
22799    minify_test(
22800      ".foo { grid-template-columns: repeat(4, [col-start] fit-content(200px) [col-end]); }",
22801      ".foo{grid-template-columns:repeat(4,[col-start]fit-content(200px)[col-end])}",
22802    );
22803    minify_test(
22804      ".foo { grid-template-columns: repeat(4, 10px [col-start] 30% [col-middle] auto [col-end]); }",
22805      ".foo{grid-template-columns:repeat(4,10px[col-start]30%[col-middle]auto[col-end])}",
22806    );
22807    minify_test(
22808      ".foo { grid-template-columns: repeat(5, auto); }",
22809      ".foo{grid-template-columns:repeat(5,auto)}",
22810    );
22811    minify_test(
22812      ".foo { grid-template-columns: repeat(auto-fill, 250px); }",
22813      ".foo{grid-template-columns:repeat(auto-fill,250px)}",
22814    );
22815    minify_test(
22816      ".foo { grid-template-columns: repeat(auto-fit, 250px); }",
22817      ".foo{grid-template-columns:repeat(auto-fit,250px)}",
22818    );
22819    minify_test(
22820      ".foo { grid-template-columns: repeat(auto-fill, [col-start] 250px [col-end]); }",
22821      ".foo{grid-template-columns:repeat(auto-fill,[col-start]250px[col-end])}",
22822    );
22823    minify_test(
22824      ".foo { grid-template-columns: repeat(auto-fill, [col-start] minmax(100px, 1fr) [col-end]); }",
22825      ".foo{grid-template-columns:repeat(auto-fill,[col-start]minmax(100px,1fr)[col-end])}",
22826    );
22827    minify_test(
22828      ".foo { grid-template-columns: minmax(min-content, 1fr); }",
22829      ".foo{grid-template-columns:minmax(min-content,1fr)}",
22830    );
22831    minify_test(
22832      ".foo { grid-template-columns: 200px repeat(auto-fill, 100px) 300px; }",
22833      ".foo{grid-template-columns:200px repeat(auto-fill,100px) 300px}",
22834    );
22835    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]}");
22836    minify_test(
22837      ".foo { grid-template-rows: [linename1 linename2] 100px repeat(auto-fit, [linename1] 300px) [linename3]; }",
22838      ".foo{grid-template-rows:[linename1 linename2]100px repeat(auto-fit,[linename1]300px)[linename3]}",
22839    );
22840
22841    minify_test(".foo { grid-auto-rows: auto; }", ".foo{grid-auto-rows:auto}");
22842    minify_test(".foo { grid-auto-rows: 1fr; }", ".foo{grid-auto-rows:1fr}");
22843    minify_test(".foo { grid-auto-rows: 100px; }", ".foo{grid-auto-rows:100px}");
22844    minify_test(
22845      ".foo { grid-auto-rows: min-content; }",
22846      ".foo{grid-auto-rows:min-content}",
22847    );
22848    minify_test(
22849      ".foo { grid-auto-rows: max-content; }",
22850      ".foo{grid-auto-rows:max-content}",
22851    );
22852    minify_test(
22853      ".foo { grid-auto-rows: minmax(100px,auto); }",
22854      ".foo{grid-auto-rows:minmax(100px,auto)}",
22855    );
22856    minify_test(
22857      ".foo { grid-auto-rows: fit-content(20%); }",
22858      ".foo{grid-auto-rows:fit-content(20%)}",
22859    );
22860    minify_test(
22861      ".foo { grid-auto-rows: 100px minmax(100px, auto) 10% 0.5fr fit-content(400px); }",
22862      ".foo{grid-auto-rows:100px minmax(100px,auto) 10% .5fr fit-content(400px)}",
22863    );
22864    minify_test(
22865      ".foo { grid-auto-columns: 100px minmax(100px, auto) 10% 0.5fr fit-content(400px); }",
22866      ".foo{grid-auto-columns:100px minmax(100px,auto) 10% .5fr fit-content(400px)}",
22867    );
22868
22869    minify_test(
22870      r#"
22871      .foo {
22872        grid-template-areas: "head head"
22873                             "nav  main"
22874                             "foot ....";
22875      }
22876    "#,
22877      ".foo{grid-template-areas:\"head head\"\"nav main\"\"foot.\"}",
22878    );
22879    minify_test(
22880      r#"
22881      .foo {
22882        grid-template-areas: "head head"
22883                             "nav  main"
22884                             ".... foot";
22885      }
22886    "#,
22887      ".foo{grid-template-areas:\"head head\"\"nav main\"\".foot\"}",
22888    );
22889    minify_test(
22890      r#"
22891      .foo {
22892        grid-template-areas: "head head"
22893                             "nav  main"
22894                             ".... ....";
22895      }
22896    "#,
22897      ".foo{grid-template-areas:\"head head\"\"nav main\"\". .\"}",
22898    );
22899
22900    // to grid-* shorthand
22901    minify_test(
22902      r#"
22903      .test-miss-areas {
22904        grid-template-columns: 1fr 90px;
22905        grid-template-rows: auto 80px;
22906        grid-template-areas: "one";
22907      }
22908    "#,
22909      ".test-miss-areas{grid-template:\"one\"\".\"80px/1fr 90px}",
22910    );
22911    test(
22912      r#"
22913      .test-miss-areas-2 {
22914        grid-template-columns: 1fr 1fr 1fr;
22915        grid-template-rows: 30px 60px 100px;
22916        grid-template-areas: "a a a" "b c c";
22917      }
22918    "#,
22919      indoc! { r#"
22920      .test-miss-areas-2 {
22921        grid-template: "a a a" 30px
22922                       "b c c" 60px
22923                       ". . ." 100px
22924                       / 1fr 1fr 1fr;
22925      }
22926    "#},
22927    );
22928
22929    test(
22930      r#"
22931      .test-miss-areas-3 {
22932        grid-template: 30px 60px 100px / 1fr 1fr 1fr;
22933        grid-template-areas: "a a a" "b c c";
22934      }
22935    "#,
22936      indoc! { r#"
22937      .test-miss-areas-3 {
22938        grid-template: "a a a" 30px
22939                       "b c c" 60px
22940                       ". . ." 100px
22941                       / 1fr 1fr 1fr;
22942      }
22943    "#},
22944    );
22945
22946    test(
22947      r#"
22948      .test-miss-areas-4 {
22949        grid: 30px 60px 100px / 1fr 1fr 1fr;
22950        grid-template-areas: "a a a" "b c c";
22951      }
22952    "#,
22953      indoc! { r#"
22954      .test-miss-areas-4 {
22955        grid: "a a a" 30px
22956              "b c c" 60px
22957              ". . ." 100px
22958              / 1fr 1fr 1fr;
22959      }
22960    "#},
22961    );
22962
22963    // test no unreachable error
22964    minify_test(
22965      r#"
22966    .grid-shorthand-areas {
22967      grid: auto / 1fr 3fr;
22968      grid-template-areas: ". content .";
22969    }
22970  "#,
22971      ".grid-shorthand-areas{grid:\".content.\"/1fr 3fr}",
22972    );
22973    minify_test(
22974      r#"
22975    .grid-shorthand-areas-rows {
22976      grid: auto / 1fr 3fr;
22977      grid-template-rows: 20px;
22978      grid-template-areas: ". content .";
22979    }
22980  "#,
22981      ".grid-shorthand-areas-rows{grid:\".content.\"20px/1fr 3fr}",
22982    );
22983
22984    // test grid-auto-flow: row in grid shorthand
22985    test(
22986      r#"
22987      .test-auto-flow-row-1 {
22988        grid: auto-flow   /  1fr 2fr 1fr;
22989        grid-template-areas: "  .   one  .  ";
22990      }
22991    "#,
22992      indoc! { r#"
22993      .test-auto-flow-row-1 {
22994        grid: auto-flow / 1fr 2fr 1fr;
22995        grid-template-areas: ". one .";
22996      }
22997    "#},
22998    );
22999    test(
23000      r#"
23001      .test-auto-flow-row-2 {
23002        grid: auto-flow   auto   /  100px   100px;
23003        grid-template-areas: " one  two ";
23004      }
23005    "#,
23006      indoc! { r#"
23007      .test-auto-flow-row-2 {
23008        grid: auto-flow / 100px 100px;
23009        grid-template-areas: "one two";
23010      }
23011    "#},
23012    );
23013    test(
23014      r#"
23015      .test-auto-flow-dense {
23016        grid: dense auto-flow  /  1fr 2fr;
23017        grid-template-areas: "  .   content  .  ";
23018      }
23019    "#,
23020      indoc! { r#"
23021      .test-auto-flow-dense {
23022        grid: auto-flow dense / 1fr 2fr;
23023        grid-template-areas: ". content .";
23024      }
23025    "#},
23026    );
23027    minify_test(
23028      r#"
23029      .grid-auto-flow-row-auto-rows {
23030        grid: auto-flow 40px / 1fr 90px;
23031        grid-template-areas: "a";
23032      }
23033    "#,
23034      ".grid-auto-flow-row-auto-rows{grid:auto-flow 40px/1fr 90px;grid-template-areas:\"a\"}",
23035    );
23036    minify_test(
23037      r#"
23038      .grid-auto-flow-row-auto-rows-multiple {
23039        grid: auto-flow 40px max-content / 1fr;
23040        grid-template-areas: ". a";
23041      }
23042    "#,
23043      ".grid-auto-flow-row-auto-rows-multiple{grid:auto-flow 40px max-content/1fr;grid-template-areas:\".a\"}",
23044    );
23045
23046    // test grid-auto-flow: column in grid shorthand
23047    test(
23048      r#"
23049      .test-auto-flow-column-1 {
23050        grid: 300px / auto-flow;
23051        grid-template-areas: "  .   one  .  ";
23052      }
23053    "#,
23054      indoc! { r#"
23055      .test-auto-flow-column-1 {
23056        grid: 300px / auto-flow;
23057        grid-template-areas: ". one .";
23058      }
23059    "#},
23060    );
23061    test(
23062      r#"
23063      .test-auto-flow-column-2 {
23064        grid: 200px 1fr / auto-flow auto;
23065        grid-template-areas: "  .   one  .  ";
23066      }
23067    "#,
23068      indoc! { r#"
23069      .test-auto-flow-column-2 {
23070        grid: 200px 1fr / auto-flow;
23071        grid-template-areas: ". one .";
23072      }
23073    "#},
23074    );
23075    test(
23076      r#"
23077      .test-auto-flow-column-dense {
23078        grid: 1fr 2fr / dense auto-flow;
23079        grid-template-areas: "  .   content  .  ";
23080      }
23081    "#,
23082      indoc! { r#"
23083      .test-auto-flow-column-dense {
23084        grid: 1fr 2fr / auto-flow dense;
23085        grid-template-areas: ". content .";
23086      }
23087    "#},
23088    );
23089    minify_test(
23090      r#"
23091      .grid-auto-flow-column-auto-rows {
23092        grid: 1fr 3fr / auto-flow 40px;
23093        grid-template-areas: "a";
23094      }
23095    "#,
23096      ".grid-auto-flow-column-auto-rows{grid:1fr 3fr/auto-flow 40px;grid-template-areas:\"a\"}",
23097    );
23098    minify_test(
23099      r#"
23100      .grid-auto-flow-column-auto-rows-multiple {
23101        grid: 1fr / auto-flow 40px max-content ;
23102        grid-template-areas: ". a";
23103      }
23104    "#,
23105      ".grid-auto-flow-column-auto-rows-multiple{grid:1fr/auto-flow 40px max-content;grid-template-areas:\".a\"}",
23106    );
23107
23108    test(
23109      r#"
23110      .foo {
23111        grid-template-areas: "head head" "nav  main" "foot ....";
23112      }
23113    "#,
23114      indoc! { r#"
23115      .foo {
23116        grid-template-areas: "head head"
23117                             "nav main"
23118                             "foot .";
23119      }
23120    "#},
23121    );
23122
23123    minify_test(
23124      r#"
23125      .foo {
23126        grid-template: [header-top] "a   a   a"     [header-bottom]
23127                       [main-top] "b   b   b" 1fr [main-bottom];
23128      }
23129    "#,
23130      ".foo{grid-template:[header-top]\"a a a\"[header-bottom main-top]\"b b b\"1fr[main-bottom]}",
23131    );
23132    minify_test(
23133      r#"
23134      .foo {
23135        grid-template: "head head"
23136                       "nav  main" 1fr
23137                       "foot ....";
23138      }
23139    "#,
23140      ".foo{grid-template:\"head head\"\"nav main\"1fr\"foot.\"}",
23141    );
23142    minify_test(
23143      r#"
23144      .foo {
23145        grid-template: [header-top] "a   a   a"     [header-bottom]
23146                         [main-top] "b   b   b" 1fr [main-bottom]
23147                                  / auto 1fr auto;
23148      }
23149    "#,
23150      ".foo{grid-template:[header-top]\"a a a\"[header-bottom main-top]\"b b b\"1fr[main-bottom]/auto 1fr auto}",
23151    );
23152
23153    minify_test(
23154      ".foo { grid-template: auto 1fr / auto 1fr auto; }",
23155      ".foo{grid-template:auto 1fr/auto 1fr auto}",
23156    );
23157    minify_test(
23158      ".foo { grid-template: [linename1 linename2] 100px repeat(auto-fit, [linename1] 300px) [linename3] / [linename1 linename2] 100px repeat(auto-fit, [linename1] 300px) [linename3]; }",
23159      ".foo{grid-template:[linename1 linename2]100px repeat(auto-fit,[linename1]300px)[linename3]/[linename1 linename2]100px repeat(auto-fit,[linename1]300px)[linename3]}"
23160    );
23161
23162    test(
23163      ".foo{grid-template:[header-top]\"a a a\"[header-bottom main-top]\"b b b\"1fr[main-bottom]/auto 1fr auto}",
23164      indoc! {r#"
23165        .foo {
23166          grid-template: [header-top] "a a a" [header-bottom]
23167                         [main-top] "b b b" 1fr [main-bottom]
23168                         / auto 1fr auto;
23169        }
23170      "#},
23171    );
23172    test(
23173      ".foo{grid-template:[header-top]\"a a a\"[main-top]\"b b b\"1fr/auto 1fr auto}",
23174      indoc! {r#"
23175        .foo {
23176          grid-template: [header-top] "a a a"
23177                         [main-top] "b b b" 1fr
23178                         / auto 1fr auto;
23179        }
23180      "#},
23181    );
23182
23183    minify_test(".foo { grid-auto-flow: row }", ".foo{grid-auto-flow:row}");
23184    minify_test(".foo { grid-auto-flow: column }", ".foo{grid-auto-flow:column}");
23185    minify_test(".foo { grid-auto-flow: row dense }", ".foo{grid-auto-flow:dense}");
23186    minify_test(".foo { grid-auto-flow: dense row }", ".foo{grid-auto-flow:dense}");
23187    minify_test(
23188      ".foo { grid-auto-flow: column dense }",
23189      ".foo{grid-auto-flow:column dense}",
23190    );
23191    minify_test(
23192      ".foo { grid-auto-flow: dense column }",
23193      ".foo{grid-auto-flow:column dense}",
23194    );
23195
23196    minify_test(".foo { grid: none }", ".foo{grid:none}");
23197    minify_test(".foo { grid: \"a\" 100px \"b\" 1fr }", ".foo{grid:\"a\"100px\"b\"1fr}");
23198    minify_test(
23199      ".foo { grid: [linename1] \"a\" 100px [linename2] }",
23200      ".foo{grid:[linename1]\"a\"100px[linename2]}",
23201    );
23202    minify_test(
23203      ".foo { grid: \"a\" 200px \"b\" min-content }",
23204      ".foo{grid:\"a\"200px\"b\"min-content}",
23205    );
23206    minify_test(
23207      ".foo { grid: \"a\" minmax(100px, max-content) \"b\" 20% }",
23208      ".foo{grid:\"a\"minmax(100px,max-content)\"b\"20%}",
23209    );
23210    minify_test(".foo { grid: 100px / 200px }", ".foo{grid:100px/200px}");
23211    minify_test(
23212      ".foo { grid: minmax(400px, min-content) / repeat(auto-fill, 50px) }",
23213      ".foo{grid:minmax(400px,min-content)/repeat(auto-fill,50px)}",
23214    );
23215
23216    minify_test(".foo { grid: 200px / auto-flow }", ".foo{grid:200px/auto-flow}");
23217    minify_test(".foo { grid: 30% / auto-flow dense }", ".foo{grid:30%/auto-flow dense}");
23218    minify_test(".foo { grid: 30% / dense auto-flow }", ".foo{grid:30%/auto-flow dense}");
23219    minify_test(
23220      ".foo { grid: repeat(3, [line1 line2 line3] 200px) / auto-flow 300px }",
23221      ".foo{grid:repeat(3,[line1 line2 line3]200px)/auto-flow 300px}",
23222    );
23223    minify_test(
23224      ".foo { grid: [line1] minmax(20em, max-content) / auto-flow dense 40% }",
23225      ".foo{grid:[line1]minmax(20em,max-content)/auto-flow dense 40%}",
23226    );
23227    minify_test(".foo { grid: none / auto-flow 1fr }", ".foo{grid:none/auto-flow 1fr}");
23228
23229    minify_test(".foo { grid: auto-flow / 200px }", ".foo{grid:none/200px}");
23230    minify_test(".foo { grid: auto-flow dense / 30% }", ".foo{grid:auto-flow dense/30%}");
23231    minify_test(".foo { grid: dense auto-flow / 30% }", ".foo{grid:auto-flow dense/30%}");
23232    minify_test(
23233      ".foo { grid: auto-flow 300px / repeat(3, [line1 line2 line3] 200px) }",
23234      ".foo{grid:auto-flow 300px/repeat(3,[line1 line2 line3]200px)}",
23235    );
23236    minify_test(
23237      ".foo { grid: auto-flow dense 40% / [line1] minmax(20em, max-content) }",
23238      ".foo{grid:auto-flow dense 40%/[line1]minmax(20em,max-content)}",
23239    );
23240
23241    minify_test(".foo { grid-row-start: auto }", ".foo{grid-row-start:auto}");
23242    minify_test(".foo { grid-row-start: some-area }", ".foo{grid-row-start:some-area}");
23243    minify_test(".foo { grid-row-start: 2 }", ".foo{grid-row-start:2}");
23244    minify_test(
23245      ".foo { grid-row-start: 2 some-line }",
23246      ".foo{grid-row-start:2 some-line}",
23247    );
23248    minify_test(
23249      ".foo { grid-row-start: some-line 2 }",
23250      ".foo{grid-row-start:2 some-line}",
23251    );
23252    minify_test(".foo { grid-row-start: span 3 }", ".foo{grid-row-start:span 3}");
23253    minify_test(
23254      ".foo { grid-row-start: span some-line }",
23255      ".foo{grid-row-start:span some-line}",
23256    );
23257    minify_test(
23258      ".foo { grid-row-start: span some-line 1 }",
23259      ".foo{grid-row-start:span some-line}",
23260    );
23261    minify_test(
23262      ".foo { grid-row-start: span 1 some-line }",
23263      ".foo{grid-row-start:span some-line}",
23264    );
23265    minify_test(
23266      ".foo { grid-row-start: span 5 some-line }",
23267      ".foo{grid-row-start:span 5 some-line}",
23268    );
23269    minify_test(
23270      ".foo { grid-row-start: span some-line 5 }",
23271      ".foo{grid-row-start:span 5 some-line}",
23272    );
23273
23274    minify_test(
23275      ".foo { grid-row-end: span 1 some-line }",
23276      ".foo{grid-row-end:span some-line}",
23277    );
23278    minify_test(
23279      ".foo { grid-column-start: span 1 some-line }",
23280      ".foo{grid-column-start:span some-line}",
23281    );
23282    minify_test(
23283      ".foo { grid-column-end: span 1 some-line }",
23284      ".foo{grid-column-end:span some-line}",
23285    );
23286
23287    minify_test(".foo { grid-row: 1 }", ".foo{grid-row:1}");
23288    minify_test(".foo { grid-row: 1 / auto }", ".foo{grid-row:1}");
23289    minify_test(".foo { grid-row: 1 / 1 }", ".foo{grid-row:1/1}");
23290    minify_test(".foo { grid-row: 1 / 3 }", ".foo{grid-row:1/3}");
23291    minify_test(".foo { grid-row: 1 / span 2 }", ".foo{grid-row:1/span 2}");
23292    minify_test(".foo { grid-row: main-start }", ".foo{grid-row:main-start}");
23293    minify_test(
23294      ".foo { grid-row: main-start / main-end }",
23295      ".foo{grid-row:main-start/main-end}",
23296    );
23297    minify_test(
23298      ".foo { grid-row: main-start / main-start }",
23299      ".foo{grid-row:main-start}",
23300    );
23301    minify_test(".foo { grid-column: 1 / auto }", ".foo{grid-column:1}");
23302
23303    minify_test(".foo { grid-area: a }", ".foo{grid-area:a}");
23304    minify_test(".foo { grid-area: a / a / a / a }", ".foo{grid-area:a}");
23305    minify_test(".foo { grid-area: a / b / a / b }", ".foo{grid-area:a/b}");
23306    minify_test(".foo { grid-area: a / b / c / b }", ".foo{grid-area:a/b/c}");
23307    minify_test(".foo { grid-area: a / b / c / d }", ".foo{grid-area:a/b/c/d}");
23308
23309    minify_test(".foo { grid-area: auto / auto / auto / auto }", ".foo{grid-area:auto}");
23310    minify_test(".foo { grid-area: 1 / auto }", ".foo{grid-area:1}");
23311    minify_test(".foo { grid-area: 1 / 2 / 3 / 4 }", ".foo{grid-area:1/2/3/4}");
23312    minify_test(".foo { grid-area: 1 / 1 / 1 / 1 }", ".foo{grid-area:1/1/1/1}");
23313
23314    test(
23315      r#"
23316        .foo{
23317          grid-template-rows: auto 1fr;
23318          grid-template-columns: auto 1fr auto;
23319          grid-template-areas: none;
23320        }
23321      "#,
23322      indoc! {r#"
23323        .foo {
23324          grid-template: auto 1fr / auto 1fr auto;
23325        }
23326      "#},
23327    );
23328
23329    test(
23330      r#"
23331        .foo{
23332          grid-template-areas: "a a a"
23333                               "b b b";
23334          grid-template-rows: [header-top] auto [header-bottom main-top] 1fr [main-bottom];
23335          grid-template-columns: auto 1fr auto;
23336        }
23337      "#,
23338      indoc! {r#"
23339        .foo {
23340          grid-template: [header-top] "a a a" [header-bottom]
23341                         [main-top] "b b b" 1fr [main-bottom]
23342                         / auto 1fr auto;
23343        }
23344      "#},
23345    );
23346
23347    test(
23348      r#"
23349        .foo{
23350          grid-template-areas: "a a a"
23351                               "b b b";
23352          grid-template-columns: repeat(3, 1fr);
23353          grid-template-rows: auto 1fr;
23354        }
23355      "#,
23356      indoc! {r#"
23357        .foo {
23358          grid-template-rows: auto 1fr;
23359          grid-template-columns: repeat(3, 1fr);
23360          grid-template-areas: "a a a"
23361                               "b b b";
23362        }
23363      "#},
23364    );
23365
23366    test(
23367      r#"
23368        .foo{
23369          grid-template-areas: "a a a"
23370                               "b b b";
23371          grid-template-columns: auto 1fr auto;
23372          grid-template-rows: repeat(2, 1fr);
23373        }
23374      "#,
23375      indoc! {r#"
23376        .foo {
23377          grid-template-rows: repeat(2, 1fr);
23378          grid-template-columns: auto 1fr auto;
23379          grid-template-areas: "a a a"
23380                               "b b b";
23381        }
23382      "#},
23383    );
23384
23385    test(
23386      r#"
23387        .foo{
23388          grid-template-areas: ". a a ."
23389                               ". b b .";
23390          grid-template-rows: auto 1fr;
23391          grid-template-columns: 10px 1fr 1fr 10px;
23392        }
23393      "#,
23394      indoc! {r#"
23395        .foo {
23396          grid-template: ". a a ."
23397                         ". b b ." 1fr
23398                         / 10px 1fr 1fr 10px;
23399        }
23400      "#},
23401    );
23402
23403    test(
23404      r#"
23405        .foo{
23406          grid-template-areas: none;
23407          grid-template-columns: auto 1fr auto;
23408          grid-template-rows: repeat(2, 1fr);
23409        }
23410      "#,
23411      indoc! {r#"
23412        .foo {
23413          grid-template: repeat(2, 1fr) / auto 1fr auto;
23414        }
23415      "#},
23416    );
23417
23418    test(
23419      r#"
23420        .foo{
23421          grid-template-areas: none;
23422          grid-template-columns: none;
23423          grid-template-rows: none;
23424        }
23425      "#,
23426      indoc! {r#"
23427        .foo {
23428          grid-template: none;
23429        }
23430      "#},
23431    );
23432
23433    test(
23434      r#"
23435        .foo{
23436          grid-template-areas: "a a a"
23437                               "b b b";
23438          grid-template-rows: [header-top] auto [header-bottom main-top] 1fr [main-bottom];
23439          grid-template-columns: auto 1fr auto;
23440          grid-auto-flow: row;
23441          grid-auto-rows: auto;
23442          grid-auto-columns: auto;
23443        }
23444      "#,
23445      indoc! {r#"
23446        .foo {
23447          grid: [header-top] "a a a" [header-bottom]
23448                [main-top] "b b b" 1fr [main-bottom]
23449                / auto 1fr auto;
23450        }
23451      "#},
23452    );
23453
23454    test(
23455      r#"
23456        .foo{
23457          grid-template-areas: none;
23458          grid-template-columns: auto 1fr auto;
23459          grid-template-rows: repeat(2, 1fr);
23460          grid-auto-flow: row;
23461          grid-auto-rows: auto;
23462          grid-auto-columns: auto;
23463        }
23464      "#,
23465      indoc! {r#"
23466        .foo {
23467          grid: repeat(2, 1fr) / auto 1fr auto;
23468        }
23469      "#},
23470    );
23471
23472    test(
23473      r#"
23474        .foo{
23475          grid-template-areas: none;
23476          grid-template-columns: none;
23477          grid-template-rows: none;
23478          grid-auto-flow: row;
23479          grid-auto-rows: auto;
23480          grid-auto-columns: auto;
23481        }
23482      "#,
23483      indoc! {r#"
23484        .foo {
23485          grid: none;
23486        }
23487      "#},
23488    );
23489
23490    test(
23491      r#"
23492        .foo{
23493          grid-template-areas: "a a a"
23494                               "b b b";
23495          grid-template-rows: [header-top] auto [header-bottom main-top] 1fr [main-bottom];
23496          grid-template-columns: auto 1fr auto;
23497          grid-auto-flow: column;
23498          grid-auto-rows: 1fr;
23499          grid-auto-columns: 1fr;
23500        }
23501      "#,
23502      indoc! {r#"
23503        .foo {
23504          grid-template: [header-top] "a a a" [header-bottom]
23505                         [main-top] "b b b" 1fr [main-bottom]
23506                         / auto 1fr auto;
23507          grid-auto-rows: 1fr;
23508          grid-auto-columns: 1fr;
23509          grid-auto-flow: column;
23510        }
23511      "#},
23512    );
23513
23514    test(
23515      r#"
23516        .foo{
23517          grid-template-rows: auto 1fr;
23518          grid-template-columns: auto 1fr auto;
23519          grid-template-areas: none;
23520          grid-auto-flow: row;
23521          grid-auto-rows: auto;
23522          grid-auto-columns: auto;
23523        }
23524      "#,
23525      indoc! {r#"
23526        .foo {
23527          grid: auto 1fr / auto 1fr auto;
23528        }
23529      "#},
23530    );
23531
23532    test(
23533      r#"
23534        .foo{
23535          grid-template-rows: auto 1fr;
23536          grid-template-columns: auto 1fr auto;
23537          grid-template-areas: none;
23538          grid-auto-flow: column;
23539          grid-auto-rows: 1fr;
23540          grid-auto-columns: 1fr;
23541        }
23542      "#,
23543      indoc! {r#"
23544        .foo {
23545          grid-template: auto 1fr / auto 1fr auto;
23546          grid-auto-rows: 1fr;
23547          grid-auto-columns: 1fr;
23548          grid-auto-flow: column;
23549        }
23550      "#},
23551    );
23552
23553    test(
23554      r#"
23555        .foo{
23556          grid-template-rows: none;
23557          grid-template-columns: auto 1fr auto;
23558          grid-template-areas: none;
23559          grid-auto-flow: column;
23560          grid-auto-rows: 1fr;
23561          grid-auto-columns: 1fr;
23562        }
23563      "#,
23564      indoc! {r#"
23565        .foo {
23566          grid-template: none / auto 1fr auto;
23567          grid-auto-rows: 1fr;
23568          grid-auto-columns: 1fr;
23569          grid-auto-flow: column;
23570        }
23571      "#},
23572    );
23573
23574    test(
23575      r#"
23576        .foo{
23577          grid-template-rows: none;
23578          grid-template-columns: auto 1fr auto;
23579          grid-template-areas: none;
23580          grid-auto-flow: row;
23581          grid-auto-rows: 1fr;
23582          grid-auto-columns: auto;
23583        }
23584      "#,
23585      indoc! {r#"
23586        .foo {
23587          grid: auto-flow 1fr / auto 1fr auto;
23588        }
23589      "#},
23590    );
23591
23592    test(
23593      r#"
23594        .foo{
23595          grid-template-rows: none;
23596          grid-template-columns: auto 1fr auto;
23597          grid-template-areas: none;
23598          grid-auto-flow: row dense;
23599          grid-auto-rows: 1fr;
23600          grid-auto-columns: auto;
23601        }
23602      "#,
23603      indoc! {r#"
23604        .foo {
23605          grid: auto-flow dense 1fr / auto 1fr auto;
23606        }
23607      "#},
23608    );
23609
23610    test(
23611      r#"
23612        .foo{
23613          grid-template-rows: auto 1fr auto;
23614          grid-template-columns: none;
23615          grid-template-areas: none;
23616          grid-auto-flow: column;
23617          grid-auto-rows: auto;
23618          grid-auto-columns: 1fr;
23619        }
23620      "#,
23621      indoc! {r#"
23622        .foo {
23623          grid: auto 1fr auto / auto-flow 1fr;
23624        }
23625      "#},
23626    );
23627
23628    test(
23629      r#"
23630        .foo{
23631          grid-template-rows: auto 1fr auto;
23632          grid-template-columns: none;
23633          grid-template-areas: none;
23634          grid-auto-flow: column dense;
23635          grid-auto-rows: auto;
23636          grid-auto-columns: 1fr;
23637        }
23638      "#,
23639      indoc! {r#"
23640        .foo {
23641          grid: auto 1fr auto / auto-flow dense 1fr;
23642        }
23643      "#},
23644    );
23645
23646    test(
23647      r#"
23648        .foo{
23649          grid-template-rows: auto 1fr auto;
23650          grid-template-columns: none;
23651          grid-template-areas: none;
23652          grid-auto-flow: var(--auto-flow);
23653          grid-auto-rows: auto;
23654          grid-auto-columns: 1fr;
23655        }
23656      "#,
23657      indoc! {r#"
23658        .foo {
23659          grid-template: auto 1fr auto / none;
23660          grid-auto-flow: var(--auto-flow);
23661          grid-auto-rows: auto;
23662          grid-auto-columns: 1fr;
23663        }
23664      "#},
23665    );
23666
23667    test(
23668      r#"
23669        .foo{
23670          grid: auto 1fr auto / auto-flow dense 1fr;
23671          grid-template-rows: 1fr 1fr 1fr;
23672        }
23673      "#,
23674      indoc! {r#"
23675        .foo {
23676          grid: 1fr 1fr 1fr / auto-flow dense 1fr;
23677        }
23678      "#},
23679    );
23680
23681    test(
23682      r#"
23683        .foo{
23684          grid-row-start: a;
23685          grid-row-end: a;
23686          grid-column-start: a;
23687          grid-column-end: a;
23688        }
23689      "#,
23690      indoc! {r#"
23691        .foo {
23692          grid-area: a;
23693        }
23694      "#},
23695    );
23696
23697    test(
23698      r#"
23699        .foo{
23700          grid-row-start: 1;
23701          grid-row-end: 2;
23702          grid-column-start: 3;
23703          grid-column-end: 4;
23704        }
23705      "#,
23706      indoc! {r#"
23707        .foo {
23708          grid-area: 1 / 3 / 2 / 4;
23709        }
23710      "#},
23711    );
23712
23713    test(
23714      r#"
23715        .foo{
23716          grid-row-start: a;
23717          grid-row-end: a;
23718        }
23719      "#,
23720      indoc! {r#"
23721        .foo {
23722          grid-row: a;
23723        }
23724      "#},
23725    );
23726
23727    test(
23728      r#"
23729        .foo{
23730          grid-column-start: a;
23731          grid-column-end: a;
23732        }
23733      "#,
23734      indoc! {r#"
23735        .foo {
23736          grid-column: a;
23737        }
23738      "#},
23739    );
23740  }
23741
23742  #[test]
23743  fn test_moz_document() {
23744    minify_test(
23745      r#"
23746      @-moz-document url-prefix() {
23747        h1 {
23748          color: yellow;
23749        }
23750      }
23751    "#,
23752      "@-moz-document url-prefix(){h1{color:#ff0}}",
23753    );
23754    minify_test(
23755      r#"
23756      @-moz-document url-prefix("") {
23757        h1 {
23758          color: yellow;
23759        }
23760      }
23761    "#,
23762      "@-moz-document url-prefix(){h1{color:#ff0}}",
23763    );
23764    error_test(
23765      "@-moz-document url-prefix(foo) {}",
23766      ParserError::UnexpectedToken(crate::properties::custom::Token::Ident("foo".into())),
23767    );
23768    error_test(
23769      "@-moz-document url-prefix(\"foo\") {}",
23770      ParserError::UnexpectedToken(crate::properties::custom::Token::String("foo".into())),
23771    );
23772  }
23773
23774  #[test]
23775  fn test_custom_properties() {
23776    minify_test(".foo { --test: ; }", ".foo{--test: }");
23777    minify_test(".foo { --test:  ; }", ".foo{--test: }");
23778    minify_test(".foo { --test: foo; }", ".foo{--test:foo}");
23779    minify_test(".foo { --test:  foo; }", ".foo{--test:foo}");
23780    minify_test(".foo { --test: foo ; }", ".foo{--test:foo}");
23781    minify_test(".foo { --test: foo  ; }", ".foo{--test:foo}");
23782    minify_test(".foo { --test:foo; }", ".foo{--test:foo}");
23783    minify_test(".foo { --test:foo ; }", ".foo{--test:foo}");
23784    minify_test(".foo { --test: var(--foo, 20px); }", ".foo{--test:var(--foo,20px)}");
23785    minify_test(
23786      ".foo { transition: var(--foo, 20px),\nvar(--bar, 40px); }",
23787      ".foo{transition:var(--foo,20px), var(--bar,40px)}",
23788    );
23789    minify_test(
23790      ".foo { background: var(--color) var(--image); }",
23791      ".foo{background:var(--color) var(--image)}",
23792    );
23793    minify_test(
23794      ".foo { height: calc(var(--spectrum-global-dimension-size-300) / 2);",
23795      ".foo{height:calc(var(--spectrum-global-dimension-size-300) / 2)}",
23796    );
23797    minify_test(
23798      ".foo { color: var(--color, rgb(255, 255, 0)); }",
23799      ".foo{color:var(--color,#ff0)}",
23800    );
23801    minify_test(
23802      ".foo { color: var(--color, #ffff00); }",
23803      ".foo{color:var(--color,#ff0)}",
23804    );
23805    minify_test(
23806      ".foo { color: var(--color, rgb(var(--red), var(--green), 0)); }",
23807      ".foo{color:var(--color,rgb(var(--red), var(--green), 0))}",
23808    );
23809    minify_test(".foo { --test: .5s; }", ".foo{--test:.5s}");
23810    minify_test(".foo { --theme-sizes-1\\/12: 2 }", ".foo{--theme-sizes-1\\/12:2}");
23811    minify_test(".foo { --test: 0px; }", ".foo{--test:0px}");
23812    test(
23813      ".foo { transform: var(--bar, ) }",
23814      indoc! {r#"
23815      .foo {
23816        transform: var(--bar, );
23817      }
23818      "#},
23819    );
23820    test(
23821      ".foo { transform: env(--bar, ) }",
23822      indoc! {r#"
23823      .foo {
23824        transform: env(--bar, );
23825      }
23826      "#},
23827    );
23828
23829    // Test attr() function with type() syntax - minified
23830    minify_test(
23831      ".foo { background-color: attr(data-color type(<color>)); }",
23832      ".foo{background-color:attr(data-color type(<color>))}",
23833    );
23834    minify_test(
23835      ".foo { width: attr(data-width type(<length>), 100px); }",
23836      ".foo{width:attr(data-width type(<length>), 100px)}",
23837    );
23838
23839    minify_test(".foo { width: attr( data-foo    % ); }", ".foo{width:attr(data-foo %)}");
23840
23841    // <attr-args> = attr( <declaration-value>, <declaration-value>? )
23842    // Like var(), a bare comma can be used with nothing following it, indicating that the second <declaration-value> was passed, just as an empty sequence.
23843    // Spec: https://drafts.csswg.org/css-values-5/#funcdef-attr
23844    minify_test(
23845      ".foo { width: attr( data-foo    %, ); }",
23846      ".foo{width:attr(data-foo %,)}",
23847    );
23848
23849    minify_test(
23850      ".foo { width: attr( data-foo    px ); }",
23851      ".foo{width:attr(data-foo px)}",
23852    );
23853
23854    minify_test(
23855      ".foo { width: attr(data-foo    number ); }",
23856      ".foo{width:attr(data-foo number)}",
23857    );
23858
23859    minify_test(
23860      ".foo { width: attr(data-foo    raw-string); }",
23861      ".foo{width:attr(data-foo raw-string)}",
23862    );
23863
23864    // Test attr() function with type() syntax - non-minified (issue with extra spaces)
23865    test(
23866      ".foo { background-color: attr(data-color type(<color>)); }",
23867      ".foo {\n  background-color: attr(data-color type(<color>));\n}\n",
23868    );
23869    test(
23870      ".foo { width: attr(data-width type(<length>), 100px); }",
23871      ".foo {\n  width: attr(data-width type(<length>), 100px);\n}\n",
23872    );
23873
23874    prefix_test(
23875      r#"
23876      .foo {
23877        --custom: lab(40% 56.6 39);
23878      }
23879    "#,
23880      indoc! {r#"
23881      .foo {
23882        --custom: #b32323;
23883      }
23884
23885      @supports (color: lab(0% 0 0)) {
23886        .foo {
23887          --custom: lab(40% 56.6 39);
23888        }
23889      }
23890    "#},
23891      Browsers {
23892        chrome: Some(90 << 16),
23893        ..Browsers::default()
23894      },
23895    );
23896
23897    prefix_test(
23898      r#"
23899      @supports (color: lab(0% 0 0)) {
23900        .foo {
23901          --custom: lab(40% 56.6 39);
23902        }
23903      }
23904    "#,
23905      indoc! {r#"
23906      @supports (color: lab(0% 0 0)) {
23907        .foo {
23908          --custom: lab(40% 56.6 39);
23909        }
23910      }
23911    "#},
23912      Browsers {
23913        chrome: Some(90 << 16),
23914        ..Browsers::default()
23915      },
23916    );
23917
23918    prefix_test(
23919      r#"
23920      .foo {
23921        --custom: lab(40% 56.6 39) !important;
23922      }
23923    "#,
23924      indoc! {r#"
23925      .foo {
23926        --custom: #b32323 !important;
23927      }
23928
23929      @supports (color: lab(0% 0 0)) {
23930        .foo {
23931          --custom: lab(40% 56.6 39) !important;
23932        }
23933      }
23934    "#},
23935      Browsers {
23936        chrome: Some(90 << 16),
23937        ..Browsers::default()
23938      },
23939    );
23940
23941    prefix_test(
23942      r#"
23943      @supports (color: lab(0% 0 0)) {
23944        .foo {
23945          --custom: lab(40% 56.6 39) !important;
23946        }
23947      }
23948    "#,
23949      indoc! {r#"
23950      @supports (color: lab(0% 0 0)) {
23951        .foo {
23952          --custom: lab(40% 56.6 39) !important;
23953        }
23954      }
23955    "#},
23956      Browsers {
23957        chrome: Some(90 << 16),
23958        ..Browsers::default()
23959      },
23960    );
23961
23962    prefix_test(
23963      r#"
23964      .foo {
23965        --custom: lab(40% 56.6 39);
23966      }
23967    "#,
23968      indoc! {r#"
23969      .foo {
23970        --custom: #b32323;
23971      }
23972
23973      @supports (color: color(display-p3 0 0 0)) {
23974        .foo {
23975          --custom: color(display-p3 .643308 .192455 .167712);
23976        }
23977      }
23978
23979      @supports (color: lab(0% 0 0)) {
23980        .foo {
23981          --custom: lab(40% 56.6 39);
23982        }
23983      }
23984    "#},
23985      Browsers {
23986        chrome: Some(90 << 16),
23987        safari: Some(14 << 16),
23988        ..Browsers::default()
23989      },
23990    );
23991
23992    prefix_test(
23993      r#"
23994      @supports (color: color(display-p3 0 0 0)) {
23995        .foo {
23996          --custom: color(display-p3 .643308 .192455 .167712);
23997        }
23998      }
23999
24000      @supports (color: lab(0% 0 0)) {
24001        .foo {
24002          --custom: lab(40% 56.6 39);
24003        }
24004      }
24005    "#,
24006      indoc! {r#"
24007      @supports (color: color(display-p3 0 0 0)) {
24008        .foo {
24009          --custom: color(display-p3 .643308 .192455 .167712);
24010        }
24011      }
24012
24013      @supports (color: lab(0% 0 0)) {
24014        .foo {
24015          --custom: lab(40% 56.6 39);
24016        }
24017      }
24018    "#},
24019      Browsers {
24020        chrome: Some(90 << 16),
24021        safari: Some(14 << 16),
24022        ..Browsers::default()
24023      },
24024    );
24025
24026    prefix_test(
24027      r#"
24028      .foo {
24029        --custom: lab(40% 56.6 39);
24030      }
24031    "#,
24032      indoc! {r#"
24033      .foo {
24034        --custom: color(display-p3 .643308 .192455 .167712);
24035      }
24036
24037      @supports (color: lab(0% 0 0)) {
24038        .foo {
24039          --custom: lab(40% 56.6 39);
24040        }
24041      }
24042    "#},
24043      Browsers {
24044        safari: Some(14 << 16),
24045        ..Browsers::default()
24046      },
24047    );
24048
24049    prefix_test(
24050      r#"
24051      .foo {
24052        --custom: lab(40% 56.6 39);
24053      }
24054    "#,
24055      indoc! {r#"
24056      .foo {
24057        --custom: lab(40% 56.6 39);
24058      }
24059    "#},
24060      Browsers {
24061        safari: Some(15 << 16),
24062        ..Browsers::default()
24063      },
24064    );
24065
24066    prefix_test(
24067      r#"
24068      .foo {
24069        --custom: oklab(59.686% 0.1009 0.1192);
24070      }
24071    "#,
24072      indoc! {r#"
24073      .foo {
24074        --custom: lab(52.2319% 40.1449 59.9171);
24075      }
24076    "#},
24077      Browsers {
24078        safari: Some(15 << 16),
24079        ..Browsers::default()
24080      },
24081    );
24082
24083    prefix_test(
24084      r#"
24085      .foo {
24086        --custom: oklab(59.686% 0.1009 0.1192);
24087      }
24088    "#,
24089      indoc! {r#"
24090      .foo {
24091        --custom: color(display-p3 .724144 .386777 .148795);
24092      }
24093
24094      @supports (color: lab(0% 0 0)) {
24095        .foo {
24096          --custom: lab(52.2319% 40.1449 59.9171);
24097        }
24098      }
24099    "#},
24100      Browsers {
24101        safari: Some(14 << 16),
24102        ..Browsers::default()
24103      },
24104    );
24105
24106    prefix_test(
24107      r#"
24108      .foo {
24109        --custom: oklab(59.686% 0.1009 0.1192);
24110      }
24111    "#,
24112      indoc! {r#"
24113      .foo {
24114        --custom: #c65d07;
24115      }
24116
24117      @supports (color: color(display-p3 0 0 0)) {
24118        .foo {
24119          --custom: color(display-p3 .724144 .386777 .148795);
24120        }
24121      }
24122
24123      @supports (color: lab(0% 0 0)) {
24124        .foo {
24125          --custom: lab(52.2319% 40.1449 59.9171);
24126        }
24127      }
24128    "#},
24129      Browsers {
24130        safari: Some(14 << 16),
24131        chrome: Some(90 << 16),
24132        ..Browsers::default()
24133      },
24134    );
24135
24136    prefix_test(
24137      r#"
24138      .foo {
24139        --foo: oklab(59.686% 0.1009 0.1192);
24140        --bar: lab(40% 56.6 39);
24141      }
24142    "#,
24143      indoc! {r#"
24144      .foo {
24145        --foo: #c65d07;
24146        --bar: #b32323;
24147      }
24148
24149      @supports (color: color(display-p3 0 0 0)) {
24150        .foo {
24151          --foo: color(display-p3 .724144 .386777 .148795);
24152          --bar: color(display-p3 .643308 .192455 .167712);
24153        }
24154      }
24155
24156      @supports (color: lab(0% 0 0)) {
24157        .foo {
24158          --foo: lab(52.2319% 40.1449 59.9171);
24159          --bar: lab(40% 56.6 39);
24160        }
24161      }
24162    "#},
24163      Browsers {
24164        safari: Some(14 << 16),
24165        chrome: Some(90 << 16),
24166        ..Browsers::default()
24167      },
24168    );
24169
24170    prefix_test(
24171      r#"
24172      .foo {
24173        --foo: color(display-p3 0 1 0);
24174      }
24175    "#,
24176      indoc! {r#"
24177      .foo {
24178        --foo: #00f942;
24179      }
24180
24181      @supports (color: color(display-p3 0 0 0)) {
24182        .foo {
24183          --foo: color(display-p3 0 1 0);
24184        }
24185      }
24186    "#},
24187      Browsers {
24188        safari: Some(14 << 16),
24189        chrome: Some(90 << 16),
24190        ..Browsers::default()
24191      },
24192    );
24193
24194    prefix_test(
24195      r#"
24196      @supports (color: color(display-p3 0 0 0)) {
24197        .foo {
24198          --foo: color(display-p3 0 1 0);
24199        }
24200      }
24201    "#,
24202      indoc! {r#"
24203      @supports (color: color(display-p3 0 0 0)) {
24204        .foo {
24205          --foo: color(display-p3 0 1 0);
24206        }
24207      }
24208    "#},
24209      Browsers {
24210        safari: Some(14 << 16),
24211        chrome: Some(90 << 16),
24212        ..Browsers::default()
24213      },
24214    );
24215
24216    prefix_test(
24217      r#"
24218      .foo {
24219        --foo: color(display-p3 0 1 0);
24220      }
24221    "#,
24222      indoc! {r#"
24223      .foo {
24224        --foo: color(display-p3 0 1 0);
24225      }
24226    "#},
24227      Browsers {
24228        safari: Some(14 << 16),
24229        ..Browsers::default()
24230      },
24231    );
24232
24233    prefix_test(
24234      r#"
24235      .foo {
24236        --foo: color(display-p3 0 1 0);
24237      }
24238    "#,
24239      indoc! {r#"
24240      .foo {
24241        --foo: #00f942;
24242      }
24243
24244      @supports (color: color(display-p3 0 0 0)) {
24245        .foo {
24246          --foo: color(display-p3 0 1 0);
24247        }
24248      }
24249    "#},
24250      Browsers {
24251        safari: Some(15 << 16),
24252        chrome: Some(90 << 16),
24253        ..Browsers::default()
24254      },
24255    );
24256
24257    prefix_test(
24258      r#"
24259      .foo {
24260        --foo: color(display-p3 0 1 0);
24261      }
24262    "#,
24263      indoc! {r#"
24264      .foo {
24265        --foo: #00f942;
24266      }
24267
24268      @supports (color: color(display-p3 0 0 0)) {
24269        .foo {
24270          --foo: color(display-p3 0 1 0);
24271        }
24272      }
24273    "#},
24274      Browsers {
24275        chrome: Some(90 << 16),
24276        ..Browsers::default()
24277      },
24278    );
24279
24280    prefix_test(
24281      r#"
24282      .foo {
24283        text-decoration: underline;
24284      }
24285
24286      .foo {
24287        --custom: lab(40% 56.6 39);
24288      }
24289    "#,
24290      indoc! {r#"
24291      .foo {
24292        --custom: #b32323;
24293        text-decoration: underline;
24294      }
24295
24296      @supports (color: lab(0% 0 0)) {
24297        .foo {
24298          --custom: lab(40% 56.6 39);
24299        }
24300      }
24301    "#},
24302      Browsers {
24303        chrome: Some(90 << 16),
24304        ..Browsers::default()
24305      },
24306    );
24307
24308    prefix_test(
24309      r#"
24310      .foo {
24311        --custom: lab(40% 56.6 39);
24312      }
24313
24314      .foo {
24315        text-decoration: underline;
24316      }
24317    "#,
24318      indoc! {r#"
24319      .foo {
24320        --custom: #b32323;
24321      }
24322
24323      @supports (color: lab(0% 0 0)) {
24324        .foo {
24325          --custom: lab(40% 56.6 39);
24326        }
24327      }
24328
24329      .foo {
24330        text-decoration: underline;
24331      }
24332    "#},
24333      Browsers {
24334        chrome: Some(90 << 16),
24335        ..Browsers::default()
24336      },
24337    );
24338
24339    prefix_test(
24340      r#"
24341      @keyframes foo {
24342        from {
24343          --custom: lab(40% 56.6 39);
24344        }
24345
24346        to {
24347          --custom: lch(50.998% 135.363 338);
24348        }
24349      }
24350    "#,
24351      indoc! {r#"
24352      @keyframes foo {
24353        from {
24354          --custom: #b32323;
24355        }
24356
24357        to {
24358          --custom: #ee00be;
24359        }
24360      }
24361
24362      @supports (color: lab(0% 0 0)) {
24363        @keyframes foo {
24364          from {
24365            --custom: lab(40% 56.6 39);
24366          }
24367
24368          to {
24369            --custom: lab(50.998% 125.506 -50.7078);
24370          }
24371        }
24372      }
24373    "#},
24374      Browsers {
24375        chrome: Some(90 << 16),
24376        ..Browsers::default()
24377      },
24378    );
24379
24380    prefix_test(
24381      r#"
24382      @supports (color: lab(0% 0 0)) {
24383        @keyframes foo {
24384          from {
24385            --custom: lab(40% 56.6 39);
24386          }
24387
24388          to {
24389            --custom: lab(50.998% 125.506 -50.7078);
24390          }
24391        }
24392      }
24393    "#,
24394      indoc! {r#"
24395      @supports (color: lab(0% 0 0)) {
24396        @keyframes foo {
24397          from {
24398            --custom: lab(40% 56.6 39);
24399          }
24400
24401          to {
24402            --custom: lab(50.998% 125.506 -50.7078);
24403          }
24404        }
24405      }
24406    "#},
24407      Browsers {
24408        chrome: Some(90 << 16),
24409        ..Browsers::default()
24410      },
24411    );
24412
24413    prefix_test(
24414      r#"
24415      @keyframes foo {
24416        from {
24417          --custom: lab(40% 56.6 39);
24418        }
24419
24420        to {
24421          --custom: lch(50.998% 135.363 338);
24422        }
24423      }
24424    "#,
24425      indoc! {r#"
24426      @keyframes foo {
24427        from {
24428          --custom: #b32323;
24429        }
24430
24431        to {
24432          --custom: #ee00be;
24433        }
24434      }
24435
24436      @supports (color: color(display-p3 0 0 0)) {
24437        @keyframes foo {
24438          from {
24439            --custom: color(display-p3 .643308 .192455 .167712);
24440          }
24441
24442          to {
24443            --custom: color(display-p3 .972962 -.362078 .804206);
24444          }
24445        }
24446      }
24447
24448      @supports (color: lab(0% 0 0)) {
24449        @keyframes foo {
24450          from {
24451            --custom: lab(40% 56.6 39);
24452          }
24453
24454          to {
24455            --custom: lab(50.998% 125.506 -50.7078);
24456          }
24457        }
24458      }
24459    "#},
24460      Browsers {
24461        chrome: Some(90 << 16),
24462        safari: Some(14 << 16),
24463        ..Browsers::default()
24464      },
24465    );
24466
24467    prefix_test(
24468      r#"
24469      @supports (color: color(display-p3 0 0 0)) {
24470        @keyframes foo {
24471          from {
24472            --custom: color(display-p3 .643308 .192455 .167712);
24473          }
24474
24475          to {
24476            --custom: color(display-p3 .972962 -.362078 .804206);
24477          }
24478        }
24479      }
24480
24481      @supports (color: lab(0% 0 0)) {
24482        @keyframes foo {
24483          from {
24484            --custom: lab(40% 56.6 39);
24485          }
24486
24487          to {
24488            --custom: lab(50.998% 125.506 -50.7078);
24489          }
24490        }
24491      }
24492    "#,
24493      indoc! {r#"
24494      @supports (color: color(display-p3 0 0 0)) {
24495        @keyframes foo {
24496          from {
24497            --custom: color(display-p3 .643308 .192455 .167712);
24498          }
24499
24500          to {
24501            --custom: color(display-p3 .972962 -.362078 .804206);
24502          }
24503        }
24504      }
24505
24506      @supports (color: lab(0% 0 0)) {
24507        @keyframes foo {
24508          from {
24509            --custom: lab(40% 56.6 39);
24510          }
24511
24512          to {
24513            --custom: lab(50.998% 125.506 -50.7078);
24514          }
24515        }
24516      }
24517    "#},
24518      Browsers {
24519        chrome: Some(90 << 16),
24520        safari: Some(14 << 16),
24521        ..Browsers::default()
24522      },
24523    );
24524
24525    prefix_test(
24526      r#"
24527      @keyframes foo {
24528        from {
24529          --custom: #ff0;
24530          opacity: 0;
24531        }
24532
24533        to {
24534          --custom: lch(50.998% 135.363 338);
24535          opacity: 1;
24536        }
24537      }
24538    "#,
24539      indoc! {r#"
24540      @keyframes foo {
24541        from {
24542          --custom: #ff0;
24543          opacity: 0;
24544        }
24545
24546        to {
24547          --custom: #ee00be;
24548          opacity: 1;
24549        }
24550      }
24551
24552      @supports (color: lab(0% 0 0)) {
24553        @keyframes foo {
24554          from {
24555            --custom: #ff0;
24556            opacity: 0;
24557          }
24558
24559          to {
24560            --custom: lab(50.998% 125.506 -50.7078);
24561            opacity: 1;
24562          }
24563        }
24564      }
24565    "#},
24566      Browsers {
24567        chrome: Some(90 << 16),
24568        ..Browsers::default()
24569      },
24570    );
24571
24572    prefix_test(
24573      r#"
24574      @keyframes foo {
24575        from {
24576          text-decoration: var(--foo) lab(29.2345% 39.3825 20.0664);
24577        }
24578      }
24579    "#,
24580      indoc! {r#"
24581      @keyframes foo {
24582        from {
24583          text-decoration: var(--foo) #7d2329;
24584        }
24585      }
24586
24587      @supports (color: lab(0% 0 0)) {
24588        @keyframes foo {
24589          from {
24590            text-decoration: var(--foo) lab(29.2345% 39.3825 20.0664);
24591          }
24592        }
24593      }
24594    "#},
24595      Browsers {
24596        chrome: Some(90 << 16),
24597        ..Browsers::default()
24598      },
24599    );
24600  }
24601
24602  #[test]
24603  fn test_charset() {
24604    test(
24605      r#"
24606      @charset "UTF-8";
24607
24608      .foo {
24609        color: red;
24610      }
24611
24612      @charset "UTF-8";
24613
24614      .bar {
24615        color: yellow;
24616      }
24617    "#,
24618      indoc! { r#"
24619      .foo {
24620        color: red;
24621      }
24622
24623      .bar {
24624        color: #ff0;
24625      }
24626    "#},
24627    )
24628  }
24629
24630  #[test]
24631  fn test_style_attr() {
24632    attr_test("color: yellow; flex: 1 1 auto", "color: #ff0; flex: auto", false, None);
24633    attr_test("color: yellow; flex: 1 1 auto", "color:#ff0;flex:auto", true, None);
24634    attr_test(
24635      "border-inline-start: 2px solid red",
24636      "border-inline-start: 2px solid red",
24637      false,
24638      Some(Browsers {
24639        safari: Some(12 << 16),
24640        ..Browsers::default()
24641      }),
24642    );
24643    attr_test(
24644      "color: lab(40% 56.6 39);",
24645      "color:#b32323;color:lab(40% 56.6 39)",
24646      true,
24647      Some(Browsers {
24648        safari: Some(8 << 16),
24649        ..Browsers::default()
24650      }),
24651    );
24652    attr_test(
24653      "--foo: lab(40% 56.6 39);",
24654      "--foo:#b32323",
24655      true,
24656      Some(Browsers {
24657        safari: Some(8 << 16),
24658        ..Browsers::default()
24659      }),
24660    );
24661    attr_test(
24662      "text-decoration: var(--foo) lab(40% 56.6 39);",
24663      "text-decoration:var(--foo) #b32323",
24664      true,
24665      Some(Browsers {
24666        chrome: Some(90 << 16),
24667        ..Browsers::default()
24668      }),
24669    );
24670  }
24671
24672  #[test]
24673  fn test_nesting() {
24674    nesting_test(
24675      r#"
24676        .foo {
24677          @apply --mixin;
24678          @apply --mixin-no-args();
24679          @apply --mixin-args(1, 2);
24680          @apply --mixin-with-empty-body {};
24681          @apply --mixin-with-body {
24682            color: red;
24683          }
24684          .bar {
24685            @apply --nested;
24686          }
24687        }
24688      "#,
24689      indoc! {r#"
24690        .foo {
24691          @apply --mixin;
24692          @apply --mixin-no-args();
24693          @apply --mixin-args(1, 2);
24694          @apply --mixin-with-empty-body {
24695            
24696          }
24697          @apply --mixin-with-body {
24698            color: red;
24699          }
24700        }
24701
24702        .foo .bar {
24703          @apply --nested;
24704        }
24705      "#},
24706    );
24707
24708    minify_test(
24709      r#"
24710        .foo {
24711          @apply --mixin;
24712          @apply --mixin-no-args();
24713          @apply --mixin-args(1,2);
24714          @apply --mixin-with-empty-body {};
24715          @apply --mixin-with-body {
24716            color: red;
24717          };
24718          .bar {
24719            @apply --nested;
24720          }
24721        }
24722      "#,
24723      ".foo{@apply --mixin;@apply --mixin-no-args();@apply --mixin-args(1,2);@apply --mixin-with-empty-body{}@apply --mixin-with-body{color: red;}& .bar{@apply --nested;}}",
24724    );
24725
24726    nesting_test(
24727      r#"
24728        .foo {
24729          color: blue;
24730          & > .bar { color: red; }
24731        }
24732      "#,
24733      indoc! {r#"
24734        .foo {
24735          color: #00f;
24736        }
24737
24738        .foo > .bar {
24739          color: red;
24740        }
24741      "#},
24742    );
24743
24744    nesting_test(
24745      r#"
24746        .foo {
24747          color: blue;
24748          &.bar { color: red; }
24749        }
24750      "#,
24751      indoc! {r#"
24752        .foo {
24753          color: #00f;
24754        }
24755
24756        .foo.bar {
24757          color: red;
24758        }
24759      "#},
24760    );
24761
24762    nesting_test(
24763      r#"
24764        .foo, .bar {
24765          color: blue;
24766          & + .baz, &.qux { color: red; }
24767        }
24768      "#,
24769      indoc! {r#"
24770        .foo, .bar {
24771          color: #00f;
24772        }
24773
24774        :is(.foo, .bar) + .baz, :is(.foo, .bar).qux {
24775          color: red;
24776        }
24777      "#},
24778    );
24779
24780    nesting_test(
24781      r#"
24782        .foo {
24783          color: blue;
24784          & .bar & .baz & .qux { color: red; }
24785        }
24786      "#,
24787      indoc! {r#"
24788        .foo {
24789          color: #00f;
24790        }
24791
24792        .foo .bar .foo .baz .foo .qux {
24793          color: red;
24794        }
24795      "#},
24796    );
24797
24798    nesting_test(
24799      r#"
24800        .foo {
24801          color: blue;
24802          & { padding: 2ch; }
24803        }
24804      "#,
24805      indoc! {r#"
24806        .foo {
24807          color: #00f;
24808        }
24809
24810        .foo {
24811          padding: 2ch;
24812        }
24813      "#},
24814    );
24815
24816    nesting_test(
24817      r#"
24818        .foo {
24819          color: blue;
24820          && { padding: 2ch; }
24821        }
24822      "#,
24823      indoc! {r#"
24824        .foo {
24825          color: #00f;
24826        }
24827
24828        .foo.foo {
24829          padding: 2ch;
24830        }
24831      "#},
24832    );
24833
24834    nesting_test(
24835      r#"
24836        .error, .invalid {
24837          &:hover > .baz { color: red; }
24838        }
24839      "#,
24840      indoc! {r#"
24841        :is(.error, .invalid):hover > .baz {
24842          color: red;
24843        }
24844      "#},
24845    );
24846
24847    nesting_test(
24848      r#"
24849        .foo {
24850          &:is(.bar, &.baz) { color: red; }
24851        }
24852      "#,
24853      indoc! {r#"
24854        .foo:is(.bar, .foo.baz) {
24855          color: red;
24856        }
24857      "#},
24858    );
24859
24860    nesting_test(
24861      r#"
24862        figure {
24863          margin: 0;
24864
24865          & > figcaption {
24866            background: hsl(0 0% 0% / 50%);
24867
24868            & > p {
24869              font-size: .9rem;
24870            }
24871          }
24872        }
24873      "#,
24874      indoc! {r#"
24875        figure {
24876          margin: 0;
24877        }
24878
24879        figure > figcaption {
24880          background: #00000080;
24881        }
24882
24883        figure > figcaption > p {
24884          font-size: .9rem;
24885        }
24886      "#},
24887    );
24888
24889    nesting_test(
24890      r#"
24891        .foo {
24892          display: grid;
24893
24894          @media (orientation: landscape) {
24895            grid-auto-flow: column;
24896          }
24897        }
24898      "#,
24899      indoc! {r#"
24900        .foo {
24901          display: grid;
24902        }
24903
24904        @media (orientation: landscape) {
24905          .foo {
24906            grid-auto-flow: column;
24907          }
24908        }
24909      "#},
24910    );
24911
24912    nesting_test(
24913      r#"
24914        .foo {
24915          display: grid;
24916
24917          @media (orientation: landscape) {
24918            grid-auto-flow: column;
24919
24920            @media (width > 1024px) {
24921              max-inline-size: 1024px;
24922            }
24923          }
24924        }
24925      "#,
24926      indoc! {r#"
24927        .foo {
24928          display: grid;
24929        }
24930
24931        @media (orientation: landscape) {
24932          .foo {
24933            grid-auto-flow: column;
24934          }
24935
24936          @media not (max-width: 1024px) {
24937            .foo {
24938              max-inline-size: 1024px;
24939            }
24940          }
24941        }
24942      "#},
24943    );
24944
24945    nesting_test(
24946      r#"
24947        .foo {
24948          @media (min-width: 640px) {
24949            color: red !important;
24950          }
24951        }
24952      "#,
24953      indoc! {r#"
24954        @media (min-width: 640px) {
24955          .foo {
24956            color: red !important;
24957          }
24958        }
24959      "#},
24960    );
24961
24962    nesting_test(
24963      r#"
24964        .foo {
24965          display: grid;
24966
24967          @supports (foo: bar) {
24968            grid-auto-flow: column;
24969          }
24970        }
24971      "#,
24972      indoc! {r#"
24973        .foo {
24974          display: grid;
24975        }
24976
24977        @supports (foo: bar) {
24978          .foo {
24979            grid-auto-flow: column;
24980          }
24981        }
24982      "#},
24983    );
24984
24985    nesting_test(
24986      r#"
24987        .foo {
24988          display: grid;
24989
24990          @container (min-width: 100px) {
24991            grid-auto-flow: column;
24992          }
24993        }
24994      "#,
24995      indoc! {r#"
24996        .foo {
24997          display: grid;
24998        }
24999
25000        @container (width >= 100px) {
25001          .foo {
25002            grid-auto-flow: column;
25003          }
25004        }
25005      "#},
25006    );
25007
25008    nesting_test(
25009      r#"
25010        .foo {
25011          display: grid;
25012
25013          @layer test {
25014            grid-auto-flow: column;
25015          }
25016        }
25017      "#,
25018      indoc! {r#"
25019        .foo {
25020          display: grid;
25021        }
25022
25023        @layer test {
25024          .foo {
25025            grid-auto-flow: column;
25026          }
25027        }
25028      "#},
25029    );
25030
25031    nesting_test(
25032      r#"
25033        .foo {
25034          display: grid;
25035
25036          @layer {
25037            grid-auto-flow: column;
25038          }
25039        }
25040      "#,
25041      indoc! {r#"
25042        .foo {
25043          display: grid;
25044        }
25045
25046        @layer {
25047          .foo {
25048            grid-auto-flow: column;
25049          }
25050        }
25051      "#},
25052    );
25053
25054    nesting_test(
25055      r#"
25056        @namespace "http://example.com/foo";
25057        @namespace toto "http://toto.example.org";
25058
25059        .foo {
25060          &div {
25061            color: red;
25062          }
25063
25064          &* {
25065            color: green;
25066          }
25067
25068          &|x {
25069            color: red;
25070          }
25071
25072          &*|x {
25073            color: green;
25074          }
25075
25076          &toto|x {
25077            color: red;
25078          }
25079        }
25080      "#,
25081      indoc! {r#"
25082        @namespace "http://example.com/foo";
25083        @namespace toto "http://toto.example.org";
25084
25085        div.foo {
25086          color: red;
25087        }
25088
25089        *.foo {
25090          color: green;
25091        }
25092
25093        |x.foo {
25094          color: red;
25095        }
25096
25097        *|x.foo {
25098          color: green;
25099        }
25100
25101        toto|x.foo {
25102          color: red;
25103        }
25104      "#},
25105    );
25106
25107    nesting_test(
25108      r#"
25109        .foo {
25110          &article > figure {
25111            color: red;
25112          }
25113        }
25114      "#,
25115      indoc! {r#"
25116        article.foo > figure {
25117          color: red;
25118        }
25119      "#},
25120    );
25121
25122    nesting_test(
25123      r#"
25124        div {
25125          &.bar {
25126            background: green;
25127          }
25128        }
25129      "#,
25130      indoc! {r#"
25131        div.bar {
25132          background: green;
25133        }
25134      "#},
25135    );
25136
25137    nesting_test(
25138      r#"
25139        div > .foo {
25140          &span {
25141            background: green;
25142          }
25143        }
25144      "#,
25145      indoc! {r#"
25146        span:is(div > .foo) {
25147          background: green;
25148        }
25149      "#},
25150    );
25151
25152    nesting_test(
25153      r#"
25154        .foo {
25155          & h1 {
25156            background: green;
25157          }
25158        }
25159      "#,
25160      indoc! {r#"
25161        .foo h1 {
25162          background: green;
25163        }
25164      "#},
25165    );
25166
25167    nesting_test(
25168      r#"
25169        .foo .bar {
25170          &h1 {
25171            background: green;
25172          }
25173        }
25174      "#,
25175      indoc! {r#"
25176        h1:is(.foo .bar) {
25177          background: green;
25178        }
25179      "#},
25180    );
25181
25182    nesting_test(
25183      r#"
25184        .foo.bar {
25185          &h1 {
25186            background: green;
25187          }
25188        }
25189      "#,
25190      indoc! {r#"
25191        h1.foo.bar {
25192          background: green;
25193        }
25194      "#},
25195    );
25196
25197    nesting_test(
25198      r#"
25199        .foo .bar {
25200          &h1 .baz {
25201            background: green;
25202          }
25203        }
25204      "#,
25205      indoc! {r#"
25206        h1:is(.foo .bar) .baz {
25207          background: green;
25208        }
25209      "#},
25210    );
25211
25212    nesting_test(
25213      r#"
25214        .foo .bar {
25215          &.baz {
25216            background: green;
25217          }
25218        }
25219      "#,
25220      indoc! {r#"
25221        .foo .bar.baz {
25222          background: green;
25223        }
25224      "#},
25225    );
25226
25227    nesting_test(
25228      r#"
25229        .foo {
25230          color: red;
25231          @nest .parent & {
25232            color: blue;
25233          }
25234        }
25235      "#,
25236      indoc! {r#"
25237        .foo {
25238          color: red;
25239        }
25240
25241        .parent .foo {
25242          color: #00f;
25243        }
25244      "#},
25245    );
25246
25247    nesting_test(
25248      r#"
25249        .foo {
25250          color: red;
25251          @nest :not(&) {
25252            color: blue;
25253          }
25254        }
25255      "#,
25256      indoc! {r#"
25257        .foo {
25258          color: red;
25259        }
25260
25261        :not(.foo) {
25262          color: #00f;
25263        }
25264      "#},
25265    );
25266
25267    nesting_test(
25268      r#"
25269        .foo {
25270          color: blue;
25271          @nest .bar & {
25272            color: red;
25273            &.baz {
25274              color: green;
25275            }
25276          }
25277        }
25278      "#,
25279      indoc! {r#"
25280        .foo {
25281          color: #00f;
25282        }
25283
25284        .bar .foo {
25285          color: red;
25286        }
25287
25288        .bar .foo.baz {
25289          color: green;
25290        }
25291      "#},
25292    );
25293
25294    nesting_test(
25295      r#"
25296        .foo {
25297          @nest :not(&) {
25298            color: red;
25299          }
25300
25301          & h1 {
25302            background: green;
25303          }
25304        }
25305      "#,
25306      indoc! {r#"
25307        :not(.foo) {
25308          color: red;
25309        }
25310
25311        .foo h1 {
25312          background: green;
25313        }
25314      "#},
25315    );
25316
25317    nesting_test(
25318      r#"
25319        .foo {
25320          & h1 {
25321            background: green;
25322          }
25323
25324          @nest :not(&) {
25325            color: red;
25326          }
25327        }
25328      "#,
25329      indoc! {r#"
25330        .foo h1 {
25331          background: green;
25332        }
25333
25334        :not(.foo) {
25335          color: red;
25336        }
25337      "#},
25338    );
25339
25340    nesting_test(
25341      r#"
25342        .foo .bar {
25343          @nest h1& {
25344            background: green;
25345          }
25346        }
25347      "#,
25348      indoc! {r#"
25349        h1:is(.foo .bar) {
25350          background: green;
25351        }
25352      "#},
25353    );
25354
25355    nesting_test(
25356      r#"
25357        @namespace "http://example.com/foo";
25358        @namespace toto "http://toto.example.org";
25359
25360        div {
25361          @nest .foo& {
25362            color: red;
25363          }
25364        }
25365
25366        * {
25367          @nest .foo& {
25368            color: red;
25369          }
25370        }
25371
25372        |x {
25373          @nest .foo& {
25374            color: red;
25375          }
25376        }
25377
25378        *|x {
25379          @nest .foo& {
25380            color: red;
25381          }
25382        }
25383
25384        toto|x {
25385          @nest .foo& {
25386            color: red;
25387          }
25388        }
25389      "#,
25390      indoc! {r#"
25391        @namespace "http://example.com/foo";
25392        @namespace toto "http://toto.example.org";
25393
25394        .foo:is(div) {
25395          color: red;
25396        }
25397
25398        .foo:is(*) {
25399          color: red;
25400        }
25401
25402        .foo:is(|x) {
25403          color: red;
25404        }
25405
25406        .foo:is(*|x) {
25407          color: red;
25408        }
25409
25410        .foo:is(toto|x) {
25411          color: red;
25412        }
25413      "#},
25414    );
25415
25416    nesting_test(
25417      r#"
25418        .foo .bar {
25419          @nest h1 .baz& {
25420            background: green;
25421          }
25422        }
25423      "#,
25424      indoc! {r#"
25425        h1 .baz:is(.foo .bar) {
25426          background: green;
25427        }
25428      "#},
25429    );
25430
25431    nesting_test(
25432      r#"
25433        .foo .bar {
25434          @nest .baz& {
25435            background: green;
25436          }
25437        }
25438      "#,
25439      indoc! {r#"
25440        .baz:is(.foo .bar) {
25441          background: green;
25442        }
25443      "#},
25444    );
25445
25446    nesting_test(
25447      r#"
25448        .foo .bar {
25449          @nest .baz & {
25450            background: green;
25451          }
25452        }
25453      "#,
25454      indoc! {r#"
25455        .baz :is(.foo .bar) {
25456          background: green;
25457        }
25458      "#},
25459    );
25460
25461    nesting_test(
25462      r#"
25463        .foo {
25464          color: red;
25465          @nest & > .bar {
25466            color: blue;
25467          }
25468        }
25469      "#,
25470      indoc! {r#"
25471        .foo {
25472          color: red;
25473        }
25474
25475        .foo > .bar {
25476          color: #00f;
25477        }
25478      "#},
25479    );
25480
25481    nesting_test(
25482      r#"
25483      .foo {
25484        color: red;
25485        .bar {
25486          color: blue;
25487        }
25488      }
25489      "#,
25490      indoc! {r#"
25491      .foo {
25492        color: red;
25493      }
25494
25495      .foo .bar {
25496        color: #00f;
25497      }
25498      "#},
25499    );
25500
25501    nesting_test(
25502      r#"
25503      .foo {
25504        color: red;
25505        .bar & {
25506          color: blue;
25507        }
25508      }
25509      "#,
25510      indoc! {r#"
25511      .foo {
25512        color: red;
25513      }
25514
25515      .bar .foo {
25516        color: #00f;
25517      }
25518      "#},
25519    );
25520
25521    nesting_test(
25522      r#"
25523      .foo {
25524        color: red;
25525        + .bar + & { color: blue; }
25526      }
25527      "#,
25528      indoc! {r#"
25529      .foo {
25530        color: red;
25531      }
25532
25533      .foo + .bar + .foo {
25534        color: #00f;
25535      }
25536      "#},
25537    );
25538
25539    nesting_test(
25540      r#"
25541      .foo {
25542        color: red;
25543        .bar & {
25544          color: blue;
25545        }
25546      }
25547      "#,
25548      indoc! {r#"
25549      .foo {
25550        color: red;
25551      }
25552
25553      .bar .foo {
25554        color: #00f;
25555      }
25556      "#},
25557    );
25558
25559    nesting_test(
25560      r#"
25561        .foo {
25562          color: red;
25563          .parent & {
25564            color: blue;
25565          }
25566        }
25567      "#,
25568      indoc! {r#"
25569        .foo {
25570          color: red;
25571        }
25572
25573        .parent .foo {
25574          color: #00f;
25575        }
25576      "#},
25577    );
25578
25579    nesting_test(
25580      r#"
25581        .foo {
25582          color: red;
25583          :not(&) {
25584            color: blue;
25585          }
25586        }
25587      "#,
25588      indoc! {r#"
25589        .foo {
25590          color: red;
25591        }
25592
25593        :not(.foo) {
25594          color: #00f;
25595        }
25596      "#},
25597    );
25598
25599    nesting_test(
25600      r#"
25601        .foo {
25602          color: blue;
25603          .bar & {
25604            color: red;
25605            &.baz {
25606              color: green;
25607            }
25608          }
25609        }
25610      "#,
25611      indoc! {r#"
25612        .foo {
25613          color: #00f;
25614        }
25615
25616        .bar .foo {
25617          color: red;
25618        }
25619
25620        .bar .foo.baz {
25621          color: green;
25622        }
25623      "#},
25624    );
25625
25626    nesting_test(
25627      r#"
25628        .foo {
25629          :not(&) {
25630            color: red;
25631          }
25632
25633          & h1 {
25634            background: green;
25635          }
25636        }
25637      "#,
25638      indoc! {r#"
25639        :not(.foo) {
25640          color: red;
25641        }
25642
25643        .foo h1 {
25644          background: green;
25645        }
25646      "#},
25647    );
25648
25649    nesting_test(
25650      r#"
25651        .foo {
25652          & h1 {
25653            background: green;
25654          }
25655
25656          :not(&) {
25657            color: red;
25658          }
25659        }
25660      "#,
25661      indoc! {r#"
25662        .foo h1 {
25663          background: green;
25664        }
25665
25666        :not(.foo) {
25667          color: red;
25668        }
25669      "#},
25670    );
25671
25672    nesting_test(
25673      r#"
25674        .foo .bar {
25675          :is(h1)& {
25676            background: green;
25677          }
25678        }
25679      "#,
25680      indoc! {r#"
25681        :is(h1):is(.foo .bar) {
25682          background: green;
25683        }
25684      "#},
25685    );
25686
25687    nesting_test(
25688      r#"
25689        @namespace "http://example.com/foo";
25690        @namespace toto "http://toto.example.org";
25691
25692        div {
25693          .foo& {
25694            color: red;
25695          }
25696        }
25697
25698        * {
25699          .foo& {
25700            color: red;
25701          }
25702        }
25703
25704        |x {
25705          .foo& {
25706            color: red;
25707          }
25708        }
25709
25710        *|x {
25711          .foo& {
25712            color: red;
25713          }
25714        }
25715
25716        toto|x {
25717          .foo& {
25718            color: red;
25719          }
25720        }
25721      "#,
25722      indoc! {r#"
25723        @namespace "http://example.com/foo";
25724        @namespace toto "http://toto.example.org";
25725
25726        .foo:is(div) {
25727          color: red;
25728        }
25729
25730        .foo:is(*) {
25731          color: red;
25732        }
25733
25734        .foo:is(|x) {
25735          color: red;
25736        }
25737
25738        .foo:is(*|x) {
25739          color: red;
25740        }
25741
25742        .foo:is(toto|x) {
25743          color: red;
25744        }
25745      "#},
25746    );
25747
25748    nesting_test(
25749      r#"
25750        .foo .bar {
25751          :is(h1) .baz& {
25752            background: green;
25753          }
25754        }
25755      "#,
25756      indoc! {r#"
25757        :is(h1) .baz:is(.foo .bar) {
25758          background: green;
25759        }
25760      "#},
25761    );
25762
25763    nesting_test(
25764      r#"
25765        .foo .bar {
25766          .baz& {
25767            background: green;
25768          }
25769        }
25770      "#,
25771      indoc! {r#"
25772        .baz:is(.foo .bar) {
25773          background: green;
25774        }
25775      "#},
25776    );
25777
25778    nesting_test(
25779      r#"
25780        .foo .bar {
25781          .baz & {
25782            background: green;
25783          }
25784        }
25785      "#,
25786      indoc! {r#"
25787        .baz :is(.foo .bar) {
25788          background: green;
25789        }
25790      "#},
25791    );
25792
25793    nesting_test(
25794      r#"
25795        .foo {
25796          .bar {
25797            color: blue;
25798          }
25799          color: red;
25800        }
25801      "#,
25802      indoc! {r#"
25803        .foo .bar {
25804          color: #00f;
25805        }
25806
25807        .foo {
25808          color: red;
25809        }
25810      "#},
25811    );
25812
25813    nesting_test(
25814      r#"
25815        article {
25816          color: green;
25817          & { color: blue; }
25818          color: red;
25819        }
25820      "#,
25821      indoc! {r#"
25822        article {
25823          color: green;
25824        }
25825
25826        article {
25827          color: #00f;
25828        }
25829
25830        article {
25831          color: red;
25832        }
25833      "#},
25834    );
25835
25836    nesting_test(
25837      r#"
25838        & .foo {
25839          color: red;
25840        }
25841      "#,
25842      indoc! {r#"
25843        :scope .foo {
25844          color: red;
25845        }
25846      "#},
25847    );
25848
25849    nesting_test(
25850      r#"
25851        &.foo {
25852          color: red;
25853        }
25854      "#,
25855      indoc! {r#"
25856        :scope.foo {
25857          color: red;
25858        }
25859      "#},
25860    );
25861
25862    nesting_test(
25863      r#"
25864        .foo& {
25865          color: red;
25866        }
25867      "#,
25868      indoc! {r#"
25869        .foo:scope {
25870          color: red;
25871        }
25872      "#},
25873    );
25874
25875    nesting_test(
25876      r#"
25877        &html {
25878          color: red;
25879        }
25880      "#,
25881      indoc! {r#"
25882        html:scope {
25883          color: red;
25884        }
25885      "#},
25886    );
25887
25888    nesting_test(
25889      r#"
25890        .foo {
25891          color: blue;
25892          div {
25893            color: red;
25894          }
25895        }
25896      "#,
25897      indoc! {r#"
25898        .foo {
25899          color: #00f;
25900        }
25901
25902        .foo div {
25903          color: red;
25904        }
25905      "#},
25906    );
25907
25908    nesting_test(
25909      r#"
25910        div {
25911          color: blue;
25912
25913          button:focus {
25914            color: red;
25915          }
25916        }
25917      "#,
25918      indoc! {r#"
25919        div {
25920          color: #00f;
25921        }
25922
25923        div button:focus {
25924          color: red;
25925        }
25926      "#},
25927    );
25928    nesting_test(
25929      r#"
25930        div {
25931          color: blue;
25932
25933          --button:focus {
25934            color: red;
25935          }
25936        }
25937      "#,
25938      indoc! {r#"
25939        div {
25940          color: #00f;
25941          --button: focus {
25942                    color: red;
25943                  };
25944        }
25945      "#},
25946    );
25947    nesting_test(
25948      r#"
25949      .foo {
25950        &::before, &::after {
25951          background: blue;
25952          @media screen {
25953            background: orange;
25954          }
25955        }
25956      }
25957      "#,
25958      indoc! {r#"
25959      .foo:before, .foo:after {
25960        background: #00f;
25961      }
25962
25963      @media screen {
25964        .foo:before, .foo:after {
25965          background: orange;
25966        }
25967      }
25968      "#},
25969    );
25970
25971    nesting_test_no_targets(
25972      r#"
25973        .foo {
25974          color: blue;
25975          @nest .bar & {
25976            color: red;
25977            &.baz {
25978              color: green;
25979            }
25980          }
25981        }
25982      "#,
25983      indoc! {r#"
25984        .foo {
25985          color: #00f;
25986
25987          @nest .bar & {
25988            color: red;
25989
25990            &.baz {
25991              color: green;
25992            }
25993          }
25994        }
25995      "#},
25996    );
25997
25998    nesting_test_no_targets(
25999      r#"
26000        .foo {
26001          color: blue;
26002          &div {
26003            color: red;
26004          }
26005
26006          &span {
26007            color: purple;
26008          }
26009        }
26010      "#,
26011      indoc! {r#"
26012        .foo {
26013          color: #00f;
26014
26015          &div {
26016            color: red;
26017          }
26018
26019          &span {
26020            color: purple;
26021          }
26022        }
26023      "#},
26024    );
26025
26026    nesting_test_no_targets(
26027      r#"
26028        .error, .invalid {
26029          &:hover > .baz { color: red; }
26030        }
26031      "#,
26032      indoc! {r#"
26033        .error, .invalid {
26034          &:hover > .baz {
26035            color: red;
26036          }
26037        }
26038      "#},
26039    );
26040
26041    nesting_test_with_targets(
26042      r#"
26043        .foo {
26044          color: blue;
26045          & > .bar { color: red; }
26046        }
26047      "#,
26048      indoc! {r#"
26049        .foo {
26050          color: #00f;
26051        }
26052
26053        .foo > .bar {
26054          color: red;
26055        }
26056      "#},
26057      Targets {
26058        browsers: Some(Browsers {
26059          chrome: Some(112 << 16),
26060          ..Browsers::default()
26061        }),
26062        include: Features::Nesting,
26063        exclude: Features::empty(),
26064      },
26065    );
26066    nesting_test_with_targets(
26067      r#"
26068        .foo {
26069          color: blue;
26070          & > .bar { color: red; }
26071        }
26072      "#,
26073      indoc! {r#"
26074        .foo {
26075          color: #00f;
26076
26077          & > .bar {
26078            color: red;
26079          }
26080        }
26081      "#},
26082      Targets {
26083        browsers: Some(Browsers {
26084          chrome: Some(50 << 16),
26085          ..Browsers::default()
26086        }),
26087        include: Features::empty(),
26088        exclude: Features::Nesting,
26089      },
26090    );
26091
26092    let mut stylesheet = StyleSheet::parse(
26093      r#"
26094      .foo {
26095        color: blue;
26096        .bar {
26097          color: red;
26098        }
26099      }
26100      "#,
26101      ParserOptions::default(),
26102    )
26103    .unwrap();
26104    stylesheet.minify(MinifyOptions::default()).unwrap();
26105    let res = stylesheet
26106      .to_css(PrinterOptions {
26107        minify: true,
26108        ..PrinterOptions::default()
26109      })
26110      .unwrap();
26111    assert_eq!(res.code, ".foo{color:#00f;& .bar{color:red}}");
26112
26113    nesting_test_with_targets(
26114      r#"
26115        .a {
26116          &.b,
26117          &.c {
26118            &.d {
26119              color: red;
26120            }
26121          }
26122        }
26123      "#,
26124      indoc! {r#"
26125        .a.b.d {
26126          color: red;
26127        }
26128
26129        .a.c.d {
26130          color: red;
26131        }
26132      "#},
26133      Targets {
26134        browsers: Some(Browsers {
26135          safari: Some(13 << 16),
26136          ..Browsers::default()
26137        }),
26138        include: Features::Nesting,
26139        exclude: Features::empty(),
26140      },
26141    );
26142
26143    minify_test(
26144      r#"
26145    .foo {
26146      color: red;
26147      .bar {
26148        color: green;
26149      }
26150      color: blue;
26151      .baz {
26152        color: pink;
26153      }
26154    }"#,
26155      ".foo{color:red;& .bar{color:green}color:#00f;& .baz{color:pink}}",
26156    );
26157  }
26158
26159  #[test]
26160  fn test_nesting_error_recovery() {
26161    error_recovery_test(
26162      "
26163    .container {
26164      padding: 3rem;
26165      @media (max-width: --styled-jsx-placeholder-0__) {
26166        .responsive {
26167          color: purple;
26168        }
26169      }
26170    }
26171    ",
26172    );
26173  }
26174
26175  #[test]
26176  fn test_css_variable_error_recovery() {
26177    error_recovery_test("
26178    .container {
26179      --local-var: --styled-jsx-placeholder-0__;
26180      color: var(--text-color);
26181      background: linear-gradient(to right, --styled-jsx-placeholder-1__, --styled-jsx-placeholder-2__);
26182
26183      .item {
26184        transform: translate(calc(var(--x) + --styled-jsx-placeholder-3__px), calc(var(--y) + --styled-jsx-placeholder-4__px));
26185      }
26186
26187      div {
26188        margin: calc(10px + --styled-jsx-placeholder-5__px);
26189      }
26190    }
26191  ");
26192  }
26193
26194  #[test]
26195  fn test_css_modules() {
26196    css_modules_test(
26197      r#"
26198      .foo {
26199        color: red;
26200      }
26201
26202      #id {
26203        animation: 2s test;
26204      }
26205
26206      @keyframes test {
26207        from { color: red }
26208        to { color: yellow }
26209      }
26210
26211      @counter-style circles {
26212        symbols: Ⓐ Ⓑ Ⓒ;
26213      }
26214
26215      ul {
26216        list-style: circles;
26217      }
26218
26219      ol {
26220        list-style-type: none;
26221      }
26222
26223      li {
26224        list-style-type: disc;
26225      }
26226
26227      @keyframes fade {
26228        from { opacity: 0 }
26229        to { opacity: 1 }
26230      }
26231    "#,
26232      indoc! {r#"
26233      .EgL3uq_foo {
26234        color: red;
26235      }
26236
26237      #EgL3uq_id {
26238        animation: 2s EgL3uq_test;
26239      }
26240
26241      @keyframes EgL3uq_test {
26242        from {
26243          color: red;
26244        }
26245
26246        to {
26247          color: #ff0;
26248        }
26249      }
26250
26251      @counter-style EgL3uq_circles {
26252        symbols: Ⓐ Ⓑ Ⓒ;
26253      }
26254
26255      ul {
26256        list-style: EgL3uq_circles;
26257      }
26258
26259      ol {
26260        list-style-type: none;
26261      }
26262
26263      li {
26264        list-style-type: disc;
26265      }
26266
26267      @keyframes EgL3uq_fade {
26268        from {
26269          opacity: 0;
26270        }
26271
26272        to {
26273          opacity: 1;
26274        }
26275      }
26276    "#},
26277      map! {
26278        "foo" => "EgL3uq_foo",
26279        "id" => "EgL3uq_id",
26280        "test" => "EgL3uq_test" referenced: true,
26281        "circles" => "EgL3uq_circles" referenced: true,
26282        "fade" => "EgL3uq_fade"
26283      },
26284      HashMap::new(),
26285      Default::default(),
26286      false,
26287    );
26288
26289    css_modules_test(
26290      r#"
26291      .foo {
26292        color: red;
26293      }
26294
26295      #id {
26296        animation: 2s test;
26297      }
26298
26299      @keyframes test {
26300        from { color: red }
26301        to { color: yellow }
26302      }
26303    "#,
26304      indoc! {r#"
26305      .EgL3uq_foo {
26306        color: red;
26307      }
26308
26309      #EgL3uq_id {
26310        animation: 2s test;
26311      }
26312
26313      @keyframes test {
26314        from {
26315          color: red;
26316        }
26317
26318        to {
26319          color: #ff0;
26320        }
26321      }
26322    "#},
26323      map! {
26324        "foo" => "EgL3uq_foo",
26325        "id" => "EgL3uq_id"
26326      },
26327      HashMap::new(),
26328      crate::css_modules::Config {
26329        animation: false,
26330        // custom_idents: false,
26331        ..Default::default()
26332      },
26333      false,
26334    );
26335
26336    css_modules_test(
26337      r#"
26338      @counter-style circles {
26339        symbols: Ⓐ Ⓑ Ⓒ;
26340      }
26341
26342      ul {
26343        list-style: circles;
26344      }
26345
26346      ol {
26347        list-style-type: none;
26348      }
26349
26350      li {
26351        list-style-type: disc;
26352      }
26353    "#,
26354      indoc! {r#"
26355      @counter-style circles {
26356        symbols: Ⓐ Ⓑ Ⓒ;
26357      }
26358
26359      ul {
26360        list-style: circles;
26361      }
26362
26363      ol {
26364        list-style-type: none;
26365      }
26366
26367      li {
26368        list-style-type: disc;
26369      }
26370    "#},
26371      map! {
26372        "circles" => "EgL3uq_circles" referenced: true
26373      },
26374      HashMap::new(),
26375      crate::css_modules::Config {
26376        custom_idents: false,
26377        ..Default::default()
26378      },
26379      false,
26380    );
26381
26382    css_modules_test(
26383      r#"
26384      body {
26385        grid: [header-top] "a a a" [header-bottom]
26386              [main-top] "b b b" 1fr [main-bottom]
26387              / auto 1fr auto;
26388      }
26389
26390      header {
26391        grid-area: a;
26392      }
26393
26394      main {
26395        grid-row: main-top / main-bottom;
26396      }
26397    "#,
26398      indoc! {r#"
26399      body {
26400        grid: [EgL3uq_header-top] "EgL3uq_a EgL3uq_a EgL3uq_a" [EgL3uq_header-bottom]
26401              [EgL3uq_main-top] "EgL3uq_b EgL3uq_b EgL3uq_b" 1fr [EgL3uq_main-bottom]
26402              / auto 1fr auto;
26403      }
26404
26405      header {
26406        grid-area: EgL3uq_a;
26407      }
26408
26409      main {
26410        grid-row: EgL3uq_main-top / EgL3uq_main-bottom;
26411      }
26412    "#},
26413      map! {
26414        "header-top" => "EgL3uq_header-top",
26415        "header-bottom" => "EgL3uq_header-bottom",
26416        "main-top" => "EgL3uq_main-top",
26417        "main-bottom" => "EgL3uq_main-bottom",
26418        "a" => "EgL3uq_a",
26419        "b" => "EgL3uq_b"
26420      },
26421      HashMap::new(),
26422      Default::default(),
26423      false,
26424    );
26425
26426    css_modules_test(
26427      r#"
26428        .grid {
26429          grid-template-areas: "foo";
26430        }
26431
26432        .foo {
26433          grid-area: foo;
26434        }
26435
26436        .bar {
26437          grid-column-start: foo-start;
26438        }
26439      "#,
26440      indoc! {r#"
26441        .EgL3uq_grid {
26442          grid-template-areas: "EgL3uq_foo";
26443        }
26444
26445        .EgL3uq_foo {
26446          grid-area: EgL3uq_foo;
26447        }
26448
26449        .EgL3uq_bar {
26450          grid-column-start: EgL3uq_foo-start;
26451        }
26452      "#},
26453      map! {
26454        "foo" => "EgL3uq_foo",
26455        "foo-start" => "EgL3uq_foo-start",
26456        "grid" => "EgL3uq_grid",
26457        "bar" => "EgL3uq_bar"
26458      },
26459      HashMap::new(),
26460      Default::default(),
26461      false,
26462    );
26463
26464    css_modules_test(
26465      r#"
26466        .grid {
26467          grid-template-areas: "foo";
26468        }
26469
26470        .foo {
26471          grid-area: foo;
26472        }
26473
26474        .bar {
26475          grid-column-start: foo-start;
26476        }
26477      "#,
26478      indoc! {r#"
26479        .EgL3uq_grid {
26480          grid-template-areas: "foo";
26481        }
26482
26483        .EgL3uq_foo {
26484          grid-area: foo;
26485        }
26486
26487        .EgL3uq_bar {
26488          grid-column-start: foo-start;
26489        }
26490      "#},
26491      map! {
26492        "foo" => "EgL3uq_foo",
26493        "grid" => "EgL3uq_grid",
26494        "bar" => "EgL3uq_bar"
26495      },
26496      HashMap::new(),
26497      crate::css_modules::Config {
26498        grid: false,
26499        ..Default::default()
26500      },
26501      false,
26502    );
26503
26504    css_modules_test(
26505      r#"
26506      test {
26507        transition-property: opacity;
26508      }
26509    "#,
26510      indoc! {r#"
26511      test {
26512        transition-property: opacity;
26513      }
26514    "#},
26515      map! {},
26516      HashMap::new(),
26517      Default::default(),
26518      false,
26519    );
26520
26521    css_modules_test(
26522      r#"
26523      :global(.foo) {
26524        color: red;
26525      }
26526
26527      :local(.bar) {
26528        color: yellow;
26529      }
26530
26531      .bar :global(.baz) {
26532        color: purple;
26533      }
26534    "#,
26535      indoc! {r#"
26536      .foo {
26537        color: red;
26538      }
26539
26540      .EgL3uq_bar {
26541        color: #ff0;
26542      }
26543
26544      .EgL3uq_bar .baz {
26545        color: purple;
26546      }
26547    "#},
26548      map! {
26549        "bar" => "EgL3uq_bar"
26550      },
26551      HashMap::new(),
26552      Default::default(),
26553      false,
26554    );
26555
26556    // :global(:local(.hi)) {
26557    //   color: green;
26558    // }
26559
26560    css_modules_test(
26561      r#"
26562      .test {
26563        composes: foo;
26564        background: white;
26565      }
26566
26567      .foo {
26568        color: red;
26569      }
26570    "#,
26571      indoc! {r#"
26572      .EgL3uq_test {
26573        background: #fff;
26574      }
26575
26576      .EgL3uq_foo {
26577        color: red;
26578      }
26579    "#},
26580      map! {
26581        "test" => "EgL3uq_test" "EgL3uq_foo",
26582        "foo" => "EgL3uq_foo"
26583      },
26584      HashMap::new(),
26585      Default::default(),
26586      false,
26587    );
26588
26589    css_modules_test(
26590      r#"
26591      .a, .b {
26592        composes: foo;
26593        background: white;
26594      }
26595
26596      .foo {
26597        color: red;
26598      }
26599    "#,
26600      indoc! {r#"
26601      .EgL3uq_a, .EgL3uq_b {
26602        background: #fff;
26603      }
26604
26605      .EgL3uq_foo {
26606        color: red;
26607      }
26608    "#},
26609      map! {
26610        "a" => "EgL3uq_a" "EgL3uq_foo",
26611        "b" => "EgL3uq_b" "EgL3uq_foo",
26612        "foo" => "EgL3uq_foo"
26613      },
26614      HashMap::new(),
26615      Default::default(),
26616      false,
26617    );
26618
26619    css_modules_test(
26620      r#"
26621      .test {
26622        composes: foo bar;
26623        background: white;
26624      }
26625
26626      .foo {
26627        color: red;
26628      }
26629
26630      .bar {
26631        color: yellow;
26632      }
26633    "#,
26634      indoc! {r#"
26635      .EgL3uq_test {
26636        background: #fff;
26637      }
26638
26639      .EgL3uq_foo {
26640        color: red;
26641      }
26642
26643      .EgL3uq_bar {
26644        color: #ff0;
26645      }
26646    "#},
26647      map! {
26648        "test" => "EgL3uq_test" "EgL3uq_foo" "EgL3uq_bar",
26649        "foo" => "EgL3uq_foo",
26650        "bar" => "EgL3uq_bar"
26651      },
26652      HashMap::new(),
26653      Default::default(),
26654      false,
26655    );
26656
26657    css_modules_test(
26658      r#"
26659      .test {
26660        composes: foo from global;
26661        background: white;
26662      }
26663    "#,
26664      indoc! {r#"
26665      .EgL3uq_test {
26666        background: #fff;
26667      }
26668    "#},
26669      map! {
26670        "test" => "EgL3uq_test" "foo" global: true
26671      },
26672      HashMap::new(),
26673      Default::default(),
26674      false,
26675    );
26676
26677    css_modules_test(
26678      r#"
26679      .test {
26680        composes: foo bar from global;
26681        background: white;
26682      }
26683    "#,
26684      indoc! {r#"
26685      .EgL3uq_test {
26686        background: #fff;
26687      }
26688    "#},
26689      map! {
26690        "test" => "EgL3uq_test" "foo" global: true "bar" global: true
26691      },
26692      HashMap::new(),
26693      Default::default(),
26694      false,
26695    );
26696
26697    css_modules_test(
26698      r#"
26699      .test {
26700        composes: foo from "foo.css";
26701        background: white;
26702      }
26703    "#,
26704      indoc! {r#"
26705      .EgL3uq_test {
26706        background: #fff;
26707      }
26708    "#},
26709      map! {
26710        "test" => "EgL3uq_test" "foo" from "foo.css"
26711      },
26712      HashMap::new(),
26713      Default::default(),
26714      false,
26715    );
26716
26717    css_modules_test(
26718      r#"
26719      .test {
26720        composes: foo bar from "foo.css";
26721        background: white;
26722      }
26723    "#,
26724      indoc! {r#"
26725      .EgL3uq_test {
26726        background: #fff;
26727      }
26728    "#},
26729      map! {
26730        "test" => "EgL3uq_test" "foo" from "foo.css" "bar" from "foo.css"
26731      },
26732      HashMap::new(),
26733      Default::default(),
26734      false,
26735    );
26736
26737    css_modules_test(
26738      r#"
26739      .test {
26740        composes: foo;
26741        composes: foo from "foo.css";
26742        composes: bar from "bar.css";
26743        background: white;
26744      }
26745
26746      .foo {
26747        color: red;
26748      }
26749    "#,
26750      indoc! {r#"
26751      .EgL3uq_test {
26752        background: #fff;
26753      }
26754
26755      .EgL3uq_foo {
26756        color: red;
26757      }
26758    "#},
26759      map! {
26760        "test" => "EgL3uq_test" "EgL3uq_foo" "foo" from "foo.css" "bar" from "bar.css",
26761        "foo" => "EgL3uq_foo"
26762      },
26763      HashMap::new(),
26764      Default::default(),
26765      false,
26766    );
26767
26768    css_modules_test(
26769      r#"
26770      .foo {
26771        color: red;
26772      }
26773    "#,
26774      indoc! {r#"
26775      .test-EgL3uq-foo {
26776        color: red;
26777      }
26778    "#},
26779      map! {
26780        "foo" => "test-EgL3uq-foo"
26781      },
26782      HashMap::new(),
26783      crate::css_modules::Config {
26784        pattern: crate::css_modules::Pattern::parse("test-[hash]-[local]").unwrap(),
26785        ..Default::default()
26786      },
26787      false,
26788    );
26789
26790    let stylesheet = StyleSheet::parse(
26791      r#"
26792        .grid {
26793          grid-template-areas: "foo";
26794        }
26795
26796        .foo {
26797          grid-area: foo;
26798        }
26799
26800        .bar {
26801          grid-column-start: foo-start;
26802        }
26803      "#,
26804      ParserOptions {
26805        css_modules: Some(crate::css_modules::Config {
26806          pattern: crate::css_modules::Pattern::parse("test-[local]-[hash]").unwrap(),
26807          ..Default::default()
26808        }),
26809        ..ParserOptions::default()
26810      },
26811    )
26812    .unwrap();
26813    if let Err(err) = stylesheet.to_css(PrinterOptions::default()) {
26814      assert_eq!(err.kind, PrinterErrorKind::InvalidCssModulesPatternInGrid);
26815    } else {
26816      unreachable!()
26817    }
26818
26819    css_modules_test(
26820      r#"
26821      @property --foo {
26822        syntax: '<color>';
26823        inherits: false;
26824        initial-value: yellow;
26825      }
26826
26827      .foo {
26828        --foo: red;
26829        color: var(--foo);
26830      }
26831    "#,
26832      indoc! {r#"
26833      @property --foo {
26834        syntax: "<color>";
26835        inherits: false;
26836        initial-value: #ff0;
26837      }
26838
26839      .EgL3uq_foo {
26840        --foo: red;
26841        color: var(--foo);
26842      }
26843    "#},
26844      map! {
26845        "foo" => "EgL3uq_foo"
26846      },
26847      HashMap::new(),
26848      Default::default(),
26849      false,
26850    );
26851
26852    css_modules_test(
26853      r#"
26854      @property --foo {
26855        syntax: '<color>';
26856        inherits: false;
26857        initial-value: yellow;
26858      }
26859
26860      @font-palette-values --Cooler {
26861        font-family: Bixa;
26862        base-palette: 1;
26863        override-colors: 1 #7EB7E4;
26864      }
26865
26866      .foo {
26867        --foo: red;
26868        --bar: green;
26869        color: var(--foo);
26870        font-palette: --Cooler;
26871      }
26872
26873      .bar {
26874        color: var(--color from "./b.css");
26875      }
26876    "#,
26877      indoc! {r#"
26878      @property --EgL3uq_foo {
26879        syntax: "<color>";
26880        inherits: false;
26881        initial-value: #ff0;
26882      }
26883
26884      @font-palette-values --EgL3uq_Cooler {
26885        font-family: Bixa;
26886        base-palette: 1;
26887        override-colors: 1 #7eb7e4;
26888      }
26889
26890      .EgL3uq_foo {
26891        --EgL3uq_foo: red;
26892        --EgL3uq_bar: green;
26893        color: var(--EgL3uq_foo);
26894        font-palette: --EgL3uq_Cooler;
26895      }
26896
26897      .EgL3uq_bar {
26898        color: var(--ma1CsG);
26899      }
26900    "#},
26901      map! {
26902        "foo" => "EgL3uq_foo",
26903        "--foo" => "--EgL3uq_foo" referenced: true,
26904        "--bar" => "--EgL3uq_bar",
26905        "bar" => "EgL3uq_bar",
26906        "--Cooler" => "--EgL3uq_Cooler" referenced: true
26907      },
26908      HashMap::from([(
26909        "--ma1CsG".into(),
26910        CssModuleReference::Dependency {
26911          name: "--color".into(),
26912          specifier: "./b.css".into(),
26913        },
26914      )]),
26915      crate::css_modules::Config {
26916        dashed_idents: true,
26917        ..Default::default()
26918      },
26919      false,
26920    );
26921
26922    css_modules_test(
26923      r#"
26924      .test {
26925        animation: rotate var(--duration) linear infinite;
26926      }
26927    "#,
26928      indoc! {r#"
26929      .EgL3uq_test {
26930        animation: EgL3uq_rotate var(--duration) linear infinite;
26931      }
26932    "#},
26933      map! {
26934        "test" => "EgL3uq_test",
26935        "rotate" => "EgL3uq_rotate" referenced: true
26936      },
26937      HashMap::new(),
26938      Default::default(),
26939      false,
26940    );
26941    css_modules_test(
26942      r#"
26943      .test {
26944        animation: none var(--duration);
26945      }
26946    "#,
26947      indoc! {r#"
26948      .EgL3uq_test {
26949        animation: none var(--duration);
26950      }
26951    "#},
26952      map! {
26953        "test" => "EgL3uq_test"
26954      },
26955      HashMap::new(),
26956      Default::default(),
26957      false,
26958    );
26959    css_modules_test(
26960      r#"
26961      .test {
26962        animation: var(--animation);
26963      }
26964    "#,
26965      indoc! {r#"
26966      .EgL3uq_test {
26967        animation: var(--animation);
26968      }
26969    "#},
26970      map! {
26971        "test" => "EgL3uq_test"
26972      },
26973      HashMap::new(),
26974      Default::default(),
26975      false,
26976    );
26977    css_modules_test(
26978      r#"
26979      .test {
26980        animation: rotate var(--duration);
26981      }
26982    "#,
26983      indoc! {r#"
26984      .EgL3uq_test {
26985        animation: rotate var(--duration);
26986      }
26987    "#},
26988      map! {
26989        "test" => "EgL3uq_test"
26990      },
26991      HashMap::new(),
26992      crate::css_modules::Config {
26993        animation: false,
26994        ..Default::default()
26995      },
26996      false,
26997    );
26998    css_modules_test(
26999      r#"
27000      .test {
27001        animation: "rotate" var(--duration);
27002      }
27003    "#,
27004      indoc! {r#"
27005      .EgL3uq_test {
27006        animation: EgL3uq_rotate var(--duration);
27007      }
27008    "#},
27009      map! {
27010        "test" => "EgL3uq_test",
27011        "rotate" => "EgL3uq_rotate" referenced: true
27012      },
27013      HashMap::new(),
27014      crate::css_modules::Config { ..Default::default() },
27015      false,
27016    );
27017
27018    css_modules_test(
27019      r#"
27020      .test {
27021        composes: foo bar from "foo.css";
27022        background: white;
27023      }
27024    "#,
27025      indoc! {r#"
27026      ._5h2kwG-test {
27027        background: #fff;
27028      }
27029    "#},
27030      map! {
27031        "test" => "_5h2kwG-test" "foo" from "foo.css" "bar" from "foo.css"
27032      },
27033      HashMap::new(),
27034      crate::css_modules::Config {
27035        pattern: crate::css_modules::Pattern::parse("[content-hash]-[local]").unwrap(),
27036        ..Default::default()
27037      },
27038      false,
27039    );
27040
27041    css_modules_test(
27042      r#"
27043      .box2 {
27044        @container main (width >= 0) {
27045          background-color: #90ee90;
27046        }
27047      }
27048    "#,
27049      indoc! {r#"
27050      .EgL3uq_box2 {
27051        @container EgL3uq_main (width >= 0) {
27052          background-color: #90ee90;
27053        }
27054      }
27055    "#},
27056      map! {
27057        "main" => "EgL3uq_main",
27058        "box2" => "EgL3uq_box2"
27059      },
27060      HashMap::new(),
27061      crate::css_modules::Config { ..Default::default() },
27062      false,
27063    );
27064
27065    css_modules_test(
27066      r#"
27067      .box2 {
27068        @container main (width >= 0) {
27069          background-color: #90ee90;
27070        }
27071      }
27072    "#,
27073      indoc! {r#"
27074      .EgL3uq_box2 {
27075        @container main (width >= 0) {
27076          background-color: #90ee90;
27077        }
27078      }
27079    "#},
27080      map! {
27081        "box2" => "EgL3uq_box2"
27082      },
27083      HashMap::new(),
27084      crate::css_modules::Config {
27085        container: false,
27086        ..Default::default()
27087      },
27088      false,
27089    );
27090
27091    css_modules_test(
27092      ".foo { view-transition-name: bar }",
27093      ".EgL3uq_foo{view-transition-name:EgL3uq_bar}",
27094      map! {
27095        "foo" => "EgL3uq_foo",
27096        "bar" => "EgL3uq_bar"
27097      },
27098      HashMap::new(),
27099      Default::default(),
27100      true,
27101    );
27102    css_modules_test(
27103      ".foo { view-transition-name: none }",
27104      ".EgL3uq_foo{view-transition-name:none}",
27105      map! {
27106        "foo" => "EgL3uq_foo"
27107      },
27108      HashMap::new(),
27109      Default::default(),
27110      true,
27111    );
27112    css_modules_test(
27113      ".foo { view-transition-name: auto }",
27114      ".EgL3uq_foo{view-transition-name:auto}",
27115      map! {
27116        "foo" => "EgL3uq_foo"
27117      },
27118      HashMap::new(),
27119      Default::default(),
27120      true,
27121    );
27122
27123    css_modules_test(
27124      ".foo { view-transition-class: bar baz qux }",
27125      ".EgL3uq_foo{view-transition-class:EgL3uq_bar EgL3uq_baz EgL3uq_qux}",
27126      map! {
27127        "foo" => "EgL3uq_foo",
27128        "bar" => "EgL3uq_bar",
27129        "baz" => "EgL3uq_baz",
27130        "qux" => "EgL3uq_qux"
27131      },
27132      HashMap::new(),
27133      Default::default(),
27134      true,
27135    );
27136
27137    css_modules_test(
27138      ".foo { view-transition-group: contain }",
27139      ".EgL3uq_foo{view-transition-group:contain}",
27140      map! {
27141        "foo" => "EgL3uq_foo"
27142      },
27143      HashMap::new(),
27144      Default::default(),
27145      true,
27146    );
27147    css_modules_test(
27148      ".foo { view-transition-group: bar }",
27149      ".EgL3uq_foo{view-transition-group:EgL3uq_bar}",
27150      map! {
27151        "foo" => "EgL3uq_foo",
27152        "bar" => "EgL3uq_bar"
27153      },
27154      HashMap::new(),
27155      Default::default(),
27156      true,
27157    );
27158
27159    css_modules_test(
27160      "@view-transition { types: foo bar baz }",
27161      "@view-transition{types:EgL3uq_foo EgL3uq_bar EgL3uq_baz}",
27162      map! {
27163        "foo" => "EgL3uq_foo",
27164        "bar" => "EgL3uq_bar",
27165        "baz" => "EgL3uq_baz"
27166      },
27167      HashMap::new(),
27168      Default::default(),
27169      true,
27170    );
27171
27172    css_modules_test(
27173      ":root:active-view-transition-type(foo, bar) { color: red }",
27174      ":root:active-view-transition-type(EgL3uq_foo,EgL3uq_bar){color:red}",
27175      map! {
27176        "foo" => "EgL3uq_foo",
27177        "bar" => "EgL3uq_bar"
27178      },
27179      HashMap::new(),
27180      Default::default(),
27181      true,
27182    );
27183
27184    for name in &[
27185      "view-transition-group",
27186      "view-transition-image-pair",
27187      "view-transition-new",
27188      "view-transition-old",
27189    ] {
27190      css_modules_test(
27191        &format!(":root::{}(foo) {{position: fixed}}", name),
27192        &format!(":root::{}(EgL3uq_foo){{position:fixed}}", name),
27193        map! {
27194          "foo" => "EgL3uq_foo"
27195        },
27196        HashMap::new(),
27197        Default::default(),
27198        true,
27199      );
27200      css_modules_test(
27201        &format!(":root::{}(.bar) {{position: fixed}}", name),
27202        &format!(":root::{}(.EgL3uq_bar){{position:fixed}}", name),
27203        map! {
27204          "bar" => "EgL3uq_bar"
27205        },
27206        HashMap::new(),
27207        Default::default(),
27208        true,
27209      );
27210      css_modules_test(
27211        &format!(":root::{}(foo.bar.baz) {{position: fixed}}", name),
27212        &format!(":root::{}(EgL3uq_foo.EgL3uq_bar.EgL3uq_baz){{position:fixed}}", name),
27213        map! {
27214          "foo" => "EgL3uq_foo",
27215          "bar" => "EgL3uq_bar",
27216          "baz" => "EgL3uq_baz"
27217        },
27218        HashMap::new(),
27219        Default::default(),
27220        true,
27221      );
27222
27223      css_modules_test(
27224        ":nth-child(1 of .foo) {width: 20px}",
27225        ":nth-child(1 of .EgL3uq_foo){width:20px}",
27226        map! {
27227          "foo" => "EgL3uq_foo"
27228        },
27229        HashMap::new(),
27230        Default::default(),
27231        true,
27232      );
27233      css_modules_test(
27234        ":nth-last-child(1 of .foo) {width: 20px}",
27235        ":nth-last-child(1 of .EgL3uq_foo){width:20px}",
27236        map! {
27237          "foo" => "EgL3uq_foo"
27238        },
27239        HashMap::new(),
27240        Default::default(),
27241        true,
27242      );
27243    }
27244
27245    // Stable hashes between project roots.
27246    fn test_project_root(project_root: &str, filename: &str, hash: &str) {
27247      let stylesheet = StyleSheet::parse(
27248        r#"
27249        .foo {
27250          background: red;
27251        }
27252        "#,
27253        ParserOptions {
27254          filename: filename.into(),
27255          css_modules: Some(Default::default()),
27256          ..ParserOptions::default()
27257        },
27258      )
27259      .unwrap();
27260      let res = stylesheet
27261        .to_css(PrinterOptions {
27262          project_root: Some(project_root),
27263          ..PrinterOptions::default()
27264        })
27265        .unwrap();
27266      assert_eq!(
27267        res.code,
27268        format!(
27269          indoc! {r#"
27270      .{}_foo {{
27271        background: red;
27272      }}
27273      "#},
27274          hash
27275        )
27276      );
27277    }
27278
27279    test_project_root("/foo/bar", "/foo/bar/test.css", "EgL3uq");
27280    test_project_root("/foo", "/foo/test.css", "EgL3uq");
27281    test_project_root("/foo/bar", "/foo/bar/baz/test.css", "xLEkNW");
27282    test_project_root("/foo", "/foo/baz/test.css", "xLEkNW");
27283
27284    let mut stylesheet = StyleSheet::parse(
27285      r#"
27286      .foo {
27287        color: red;
27288        .bar {
27289          color: green;
27290        }
27291        composes: test from "foo.css";
27292      }
27293      "#,
27294      ParserOptions {
27295        filename: "test.css".into(),
27296        css_modules: Some(Default::default()),
27297        ..ParserOptions::default()
27298      },
27299    )
27300    .unwrap();
27301    stylesheet.minify(MinifyOptions::default()).unwrap();
27302    let res = stylesheet
27303      .to_css(PrinterOptions {
27304        targets: Browsers {
27305          chrome: Some(95 << 16),
27306          ..Browsers::default()
27307        }
27308        .into(),
27309        ..Default::default()
27310      })
27311      .unwrap();
27312    assert_eq!(
27313      res.code,
27314      indoc! {r#"
27315    .EgL3uq_foo {
27316      color: red;
27317    }
27318
27319    .EgL3uq_foo .EgL3uq_bar {
27320      color: green;
27321    }
27322
27323
27324    "#}
27325    );
27326    assert_eq!(
27327      res.exports.unwrap(),
27328      map! {
27329        "foo" => "EgL3uq_foo" "test" from "foo.css",
27330        "bar" => "EgL3uq_bar"
27331      }
27332    );
27333  }
27334
27335  #[test]
27336  fn test_pseudo_replacement() {
27337    let source = r#"
27338      .foo:hover {
27339        color: red;
27340      }
27341
27342      .foo:active {
27343        color: yellow;
27344      }
27345
27346      .foo:focus-visible {
27347        color: purple;
27348      }
27349    "#;
27350
27351    let expected = indoc! { r#"
27352      .foo.is-hovered {
27353        color: red;
27354      }
27355
27356      .foo.is-active {
27357        color: #ff0;
27358      }
27359
27360      .foo.focus-visible {
27361        color: purple;
27362      }
27363    "#};
27364
27365    let stylesheet = StyleSheet::parse(&source, ParserOptions::default()).unwrap();
27366    let res = stylesheet
27367      .to_css(PrinterOptions {
27368        pseudo_classes: Some(PseudoClasses {
27369          hover: Some("is-hovered"),
27370          active: Some("is-active"),
27371          focus_visible: Some("focus-visible"),
27372          ..PseudoClasses::default()
27373        }),
27374        ..PrinterOptions::default()
27375      })
27376      .unwrap();
27377    assert_eq!(res.code, expected);
27378
27379    let source = r#"
27380      .foo:hover {
27381        color: red;
27382      }
27383    "#;
27384
27385    let expected = indoc! { r#"
27386      .EgL3uq_foo.EgL3uq_is-hovered {
27387        color: red;
27388      }
27389    "#};
27390
27391    let stylesheet = StyleSheet::parse(
27392      &source,
27393      ParserOptions {
27394        filename: "test.css".into(),
27395        css_modules: Some(Default::default()),
27396        ..ParserOptions::default()
27397      },
27398    )
27399    .unwrap();
27400    let res = stylesheet
27401      .to_css(PrinterOptions {
27402        pseudo_classes: Some(PseudoClasses {
27403          hover: Some("is-hovered"),
27404          ..PseudoClasses::default()
27405        }),
27406        ..PrinterOptions::default()
27407      })
27408      .unwrap();
27409    assert_eq!(res.code, expected);
27410  }
27411
27412  #[test]
27413  fn test_unused_symbols() {
27414    let source = r#"
27415      .foo {
27416        color: red;
27417      }
27418
27419      .bar {
27420        color: green;
27421      }
27422
27423      .bar:hover {
27424        color: purple;
27425      }
27426
27427      .bar .baz {
27428        background: red;
27429      }
27430
27431      .baz:is(.bar) {
27432        background: green;
27433      }
27434
27435      #id {
27436        animation: 2s test;
27437      }
27438
27439      #other_id {
27440        color: red;
27441      }
27442
27443      @keyframes test {
27444        from { color: red }
27445        to { color: yellow }
27446      }
27447
27448      @counter-style circles {
27449        symbols: Ⓐ Ⓑ Ⓒ;
27450      }
27451
27452      @keyframes fade {
27453        from { opacity: 0 }
27454        to { opacity: 1 }
27455      }
27456    "#;
27457
27458    let expected = indoc! {r#"
27459      .foo {
27460        color: red;
27461      }
27462
27463      #id {
27464        animation: 2s test;
27465      }
27466
27467      @keyframes test {
27468        from {
27469          color: red;
27470        }
27471
27472        to {
27473          color: #ff0;
27474        }
27475      }
27476    "#};
27477
27478    let mut stylesheet = StyleSheet::parse(&source, ParserOptions::default()).unwrap();
27479    stylesheet
27480      .minify(MinifyOptions {
27481        unused_symbols: vec!["bar", "other_id", "fade", "circles"]
27482          .iter()
27483          .map(|s| String::from(*s))
27484          .collect(),
27485        ..MinifyOptions::default()
27486      })
27487      .unwrap();
27488    let res = stylesheet.to_css(PrinterOptions::default()).unwrap();
27489    assert_eq!(res.code, expected);
27490
27491    let source = r#"
27492      .foo {
27493        color: red;
27494
27495        &.bar {
27496          color: green;
27497        }
27498      }
27499    "#;
27500
27501    let expected = indoc! {r#"
27502      .foo {
27503        color: red;
27504      }
27505    "#};
27506
27507    let mut stylesheet = StyleSheet::parse(&source, ParserOptions::default()).unwrap();
27508    stylesheet
27509      .minify(MinifyOptions {
27510        unused_symbols: vec!["bar"].iter().map(|s| String::from(*s)).collect(),
27511        ..MinifyOptions::default()
27512      })
27513      .unwrap();
27514    let res = stylesheet.to_css(PrinterOptions::default()).unwrap();
27515    assert_eq!(res.code, expected);
27516
27517    let source = r#"
27518      .foo {
27519        color: red;
27520
27521        &.bar {
27522          color: purple;
27523        }
27524
27525        @nest &.bar {
27526          color: orange;
27527        }
27528
27529        @nest :not(&) {
27530          color: green;
27531        }
27532
27533        @media (orientation: portrait) {
27534          color: brown;
27535        }
27536      }
27537
27538      .x {
27539        color: purple;
27540
27541        &.y {
27542          color: green;
27543        }
27544      }
27545    "#;
27546
27547    let expected = indoc! {r#"
27548      :not(.foo) {
27549        color: green;
27550      }
27551    "#};
27552
27553    let mut stylesheet = StyleSheet::parse(&source, ParserOptions::default()).unwrap();
27554    stylesheet
27555      .minify(MinifyOptions {
27556        unused_symbols: vec!["foo", "x"].iter().map(|s| String::from(*s)).collect(),
27557        ..MinifyOptions::default()
27558      })
27559      .unwrap();
27560    let res = stylesheet
27561      .to_css(PrinterOptions {
27562        targets: Browsers {
27563          chrome: Some(95 << 16),
27564          ..Browsers::default()
27565        }
27566        .into(),
27567        ..PrinterOptions::default()
27568      })
27569      .unwrap();
27570    assert_eq!(res.code, expected);
27571
27572    let source = r#"
27573      @property --EgL3uq_foo {
27574        syntax: "<color>";
27575        inherits: false;
27576        initial-value: #ff0;
27577      }
27578
27579      @font-palette-values --EgL3uq_Cooler {
27580        font-family: Bixa;
27581        base-palette: 1;
27582        override-colors: 1 #7EB7E4;
27583      }
27584
27585      .EgL3uq_foo {
27586        --EgL3uq_foo: red;
27587      }
27588
27589      .EgL3uq_bar {
27590        color: green;
27591      }
27592    "#;
27593
27594    let expected = indoc! {r#"
27595      .EgL3uq_bar {
27596        color: green;
27597      }
27598    "#};
27599
27600    let mut stylesheet = StyleSheet::parse(&source, ParserOptions::default()).unwrap();
27601    stylesheet
27602      .minify(MinifyOptions {
27603        unused_symbols: vec!["--EgL3uq_foo", "--EgL3uq_Cooler"]
27604          .iter()
27605          .map(|s| String::from(*s))
27606          .collect(),
27607        ..MinifyOptions::default()
27608      })
27609      .unwrap();
27610    let res = stylesheet.to_css(PrinterOptions::default()).unwrap();
27611    assert_eq!(res.code, expected);
27612  }
27613
27614  #[test]
27615  fn test_svg() {
27616    use crate::properties::svg;
27617
27618    minify_test(".foo { fill: yellow; }", ".foo{fill:#ff0}");
27619    minify_test(".foo { fill: url(#foo); }", ".foo{fill:url(#foo)}");
27620    minify_test(".foo { fill: url(#foo) none; }", ".foo{fill:url(#foo) none}");
27621    minify_test(".foo { fill: url(#foo) yellow; }", ".foo{fill:url(#foo) #ff0}");
27622    minify_test(".foo { fill: none; }", ".foo{fill:none}");
27623    minify_test(".foo { fill: context-fill; }", ".foo{fill:context-fill}");
27624    minify_test(".foo { fill: context-stroke; }", ".foo{fill:context-stroke}");
27625
27626    minify_test(".foo { stroke: yellow; }", ".foo{stroke:#ff0}");
27627    minify_test(".foo { stroke: url(#foo); }", ".foo{stroke:url(#foo)}");
27628    minify_test(".foo { stroke: url(#foo) none; }", ".foo{stroke:url(#foo) none}");
27629    minify_test(".foo { stroke: url(#foo) yellow; }", ".foo{stroke:url(#foo) #ff0}");
27630    minify_test(".foo { stroke: none; }", ".foo{stroke:none}");
27631    minify_test(".foo { stroke: context-fill; }", ".foo{stroke:context-fill}");
27632    minify_test(".foo { stroke: context-stroke; }", ".foo{stroke:context-stroke}");
27633
27634    minify_test(".foo { marker-start: url(#foo); }", ".foo{marker-start:url(#foo)}");
27635
27636    minify_test(".foo { stroke-dasharray: 4 1 2; }", ".foo{stroke-dasharray:4 1 2}");
27637    minify_test(".foo { stroke-dasharray: 4,1,2; }", ".foo{stroke-dasharray:4 1 2}");
27638    minify_test(".foo { stroke-dasharray: 4, 1, 2; }", ".foo{stroke-dasharray:4 1 2}");
27639    minify_test(
27640      ".foo { stroke-dasharray: 4px, 1px, 2px; }",
27641      ".foo{stroke-dasharray:4 1 2}",
27642    );
27643
27644    minify_test(".foo { mask: url('foo.svg'); }", ".foo{mask:url(foo.svg)}");
27645    minify_test(
27646      ".foo { mask: url(masks.svg#star) luminance }",
27647      ".foo{mask:url(masks.svg#star) luminance}",
27648    );
27649    minify_test(
27650      ".foo { mask: url(masks.svg#star) 40px 20px }",
27651      ".foo{mask:url(masks.svg#star) 40px 20px}",
27652    );
27653    minify_test(
27654      ".foo { mask: url(masks.svg#star) 0 0 / 50px 50px }",
27655      ".foo{mask:url(masks.svg#star) 0 0/50px 50px}",
27656    );
27657    minify_test(
27658      ".foo { mask: url(masks.svg#star) repeat-x }",
27659      ".foo{mask:url(masks.svg#star) repeat-x}",
27660    );
27661    minify_test(
27662      ".foo { mask: url(masks.svg#star) stroke-box }",
27663      ".foo{mask:url(masks.svg#star) stroke-box}",
27664    );
27665    minify_test(
27666      ".foo { mask: url(masks.svg#star) stroke-box stroke-box }",
27667      ".foo{mask:url(masks.svg#star) stroke-box}",
27668    );
27669    minify_test(
27670      ".foo { mask: url(masks.svg#star) border-box }",
27671      ".foo{mask:url(masks.svg#star)}",
27672    );
27673    minify_test(
27674      ".foo { mask: url(masks.svg#star) left / 16px repeat-y, url(masks.svg#circle) right / 16px repeat-y }",
27675      ".foo{mask:url(masks.svg#star) 0/16px repeat-y,url(masks.svg#circle) 100%/16px repeat-y}",
27676    );
27677
27678    minify_test(
27679      ".foo { mask-border: url('border-mask.png') 25; }",
27680      ".foo{mask-border:url(border-mask.png) 25}",
27681    );
27682    minify_test(
27683      ".foo { mask-border: url('border-mask.png') 25 / 35px / 12px space alpha; }",
27684      ".foo{mask-border:url(border-mask.png) 25/35px/12px space}",
27685    );
27686    minify_test(
27687      ".foo { mask-border: url('border-mask.png') 25 / 35px / 12px space luminance; }",
27688      ".foo{mask-border:url(border-mask.png) 25/35px/12px space luminance}",
27689    );
27690    minify_test(
27691      ".foo { mask-border: url('border-mask.png') luminance 25 / 35px / 12px space; }",
27692      ".foo{mask-border:url(border-mask.png) 25/35px/12px space luminance}",
27693    );
27694
27695    minify_test(
27696      ".foo { clip-path: url('clip.svg#star'); }",
27697      ".foo{clip-path:url(clip.svg#star)}",
27698    );
27699    minify_test(".foo { clip-path: margin-box; }", ".foo{clip-path:margin-box}");
27700    minify_test(
27701      ".foo { clip-path: inset(100px 50px); }",
27702      ".foo{clip-path:inset(100px 50px)}",
27703    );
27704    minify_test(
27705      ".foo { clip-path: inset(100px 50px round 5px); }",
27706      ".foo{clip-path:inset(100px 50px round 5px)}",
27707    );
27708    minify_test(
27709      ".foo { clip-path: inset(100px 50px round 5px 5px 5px 5px); }",
27710      ".foo{clip-path:inset(100px 50px round 5px)}",
27711    );
27712    minify_test(".foo { clip-path: circle(50px); }", ".foo{clip-path:circle(50px)}");
27713    minify_test(
27714      ".foo { clip-path: circle(50px at center center); }",
27715      ".foo{clip-path:circle(50px)}",
27716    );
27717    minify_test(
27718      ".foo { clip-path: circle(50px at 50% 50%); }",
27719      ".foo{clip-path:circle(50px)}",
27720    );
27721    minify_test(
27722      ".foo { clip-path: circle(50px at 0 100px); }",
27723      ".foo{clip-path:circle(50px at 0 100px)}",
27724    );
27725    minify_test(
27726      ".foo { clip-path: circle(closest-side at 0 100px); }",
27727      ".foo{clip-path:circle(at 0 100px)}",
27728    );
27729    minify_test(
27730      ".foo { clip-path: circle(farthest-side at 0 100px); }",
27731      ".foo{clip-path:circle(farthest-side at 0 100px)}",
27732    );
27733    minify_test(
27734      ".foo { clip-path: circle(closest-side at 50% 50%); }",
27735      ".foo{clip-path:circle()}",
27736    );
27737    minify_test(
27738      ".foo { clip-path: ellipse(50px 60px at 0 10% 20%); }",
27739      ".foo{clip-path:ellipse(50px 60px at 0 10% 20%)}",
27740    );
27741    minify_test(
27742      ".foo { clip-path: ellipse(50px 60px at center center); }",
27743      ".foo{clip-path:ellipse(50px 60px)}",
27744    );
27745    minify_test(
27746      ".foo { clip-path: ellipse(closest-side closest-side at 50% 50%); }",
27747      ".foo{clip-path:ellipse()}",
27748    );
27749    minify_test(
27750      ".foo { clip-path: ellipse(closest-side closest-side at 10% 20%); }",
27751      ".foo{clip-path:ellipse(at 10% 20%)}",
27752    );
27753    minify_test(
27754      ".foo { clip-path: ellipse(farthest-side closest-side at 10% 20%); }",
27755      ".foo{clip-path:ellipse(farthest-side closest-side at 10% 20%)}",
27756    );
27757    minify_test(
27758      ".foo { clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%); }",
27759      ".foo{clip-path:polygon(50% 0%,100% 50%,50% 100%,0% 50%)}",
27760    );
27761    minify_test(
27762      ".foo { clip-path: polygon(nonzero, 50% 0%, 100% 50%, 50% 100%, 0% 50%); }",
27763      ".foo{clip-path:polygon(50% 0%,100% 50%,50% 100%,0% 50%)}",
27764    );
27765    minify_test(
27766      ".foo { clip-path: polygon(evenodd, 50% 0%, 100% 50%, 50% 100%, 0% 50%); }",
27767      ".foo{clip-path:polygon(evenodd,50% 0%,100% 50%,50% 100%,0% 50%)}",
27768    );
27769    minify_test(
27770      ".foo { clip-path: padding-box circle(50px at 0 100px); }",
27771      ".foo{clip-path:circle(50px at 0 100px) padding-box}",
27772    );
27773    minify_test(
27774      ".foo { clip-path: circle(50px at 0 100px) padding-box; }",
27775      ".foo{clip-path:circle(50px at 0 100px) padding-box}",
27776    );
27777    minify_test(
27778      ".foo { clip-path: circle(50px at 0 100px) border-box; }",
27779      ".foo{clip-path:circle(50px at 0 100px)}",
27780    );
27781
27782    prefix_test(
27783      ".foo { clip-path: circle(50px); }",
27784      indoc! { r#"
27785        .foo {
27786          -webkit-clip-path: circle(50px);
27787          clip-path: circle(50px);
27788        }
27789      "#},
27790      Browsers {
27791        chrome: Some(30 << 16),
27792        ..Browsers::default()
27793      },
27794    );
27795
27796    prefix_test(
27797      ".foo { clip-path: circle(50px); }",
27798      indoc! { r#"
27799        .foo {
27800          clip-path: circle(50px);
27801        }
27802      "#},
27803      Browsers {
27804        chrome: Some(80 << 16),
27805        ..Browsers::default()
27806      },
27807    );
27808
27809    prefix_test(
27810      ".foo { clip-path: circle(50px); }",
27811      indoc! { r#"
27812        .foo {
27813          -webkit-clip-path: circle(50px);
27814          clip-path: circle(50px);
27815        }
27816      "#},
27817      Browsers {
27818        safari: Some(8 << 16),
27819        ..Browsers::default()
27820      },
27821    );
27822
27823    prefix_test(
27824      ".foo { clip-path: circle(50px); }",
27825      indoc! { r#"
27826        .foo {
27827          clip-path: circle(50px);
27828        }
27829      "#},
27830      Browsers {
27831        safari: Some(14 << 16),
27832        ..Browsers::default()
27833      },
27834    );
27835
27836    prefix_test(
27837      ".foo { fill: lch(50.998% 135.363 338) }",
27838      indoc! { r#"
27839        .foo {
27840          fill: #ee00be;
27841          fill: color(display-p3 .972962 -.362078 .804206);
27842          fill: lch(50.998% 135.363 338);
27843        }
27844      "#},
27845      Browsers {
27846        chrome: Some(90 << 16),
27847        safari: Some(14 << 16),
27848        ..Browsers::default()
27849      },
27850    );
27851
27852    prefix_test(
27853      ".foo { stroke: lch(50.998% 135.363 338) }",
27854      indoc! { r#"
27855        .foo {
27856          stroke: #ee00be;
27857          stroke: color(display-p3 .972962 -.362078 .804206);
27858          stroke: lch(50.998% 135.363 338);
27859        }
27860      "#},
27861      Browsers {
27862        chrome: Some(90 << 16),
27863        safari: Some(14 << 16),
27864        ..Browsers::default()
27865      },
27866    );
27867
27868    prefix_test(
27869      ".foo { fill: url(#foo) lch(50.998% 135.363 338) }",
27870      indoc! { r##"
27871        .foo {
27872          fill: url("#foo") #ee00be;
27873          fill: url("#foo") color(display-p3 .972962 -.362078 .804206);
27874          fill: url("#foo") lch(50.998% 135.363 338);
27875        }
27876      "##},
27877      Browsers {
27878        chrome: Some(90 << 16),
27879        safari: Some(14 << 16),
27880        ..Browsers::default()
27881      },
27882    );
27883
27884    prefix_test(
27885      ".foo { fill: var(--url) lch(50.998% 135.363 338) }",
27886      indoc! { r#"
27887        .foo {
27888          fill: var(--url) #ee00be;
27889        }
27890
27891        @supports (color: lab(0% 0 0)) {
27892          .foo {
27893            fill: var(--url) lab(50.998% 125.506 -50.7078);
27894          }
27895        }
27896      "#},
27897      Browsers {
27898        chrome: Some(90 << 16),
27899        ..Browsers::default()
27900      },
27901    );
27902
27903    prefix_test(
27904      r#"
27905        @supports (color: lab(0% 0 0)) {
27906          .foo {
27907            fill: var(--url) lab(50.998% 125.506 -50.7078);
27908          }
27909        }
27910      "#,
27911      indoc! { r#"
27912        @supports (color: lab(0% 0 0)) {
27913          .foo {
27914            fill: var(--url) lab(50.998% 125.506 -50.7078);
27915          }
27916        }
27917      "#},
27918      Browsers {
27919        chrome: Some(90 << 16),
27920        ..Browsers::default()
27921      },
27922    );
27923
27924    prefix_test(
27925      ".foo { mask-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
27926      indoc! { r#"
27927        .foo {
27928          -webkit-mask-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ff0f0e), to(#7773ff));
27929          -webkit-mask-image: -webkit-linear-gradient(top, #ff0f0e, #7773ff);
27930          -webkit-mask-image: linear-gradient(#ff0f0e, #7773ff);
27931          mask-image: linear-gradient(#ff0f0e, #7773ff);
27932          -webkit-mask-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
27933          mask-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
27934        }
27935      "#},
27936      Browsers {
27937        chrome: Some(8 << 16),
27938        ..Browsers::default()
27939      },
27940    );
27941
27942    prefix_test(
27943      ".foo { mask-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
27944      indoc! { r#"
27945        .foo {
27946          -webkit-mask-image: linear-gradient(#ff0f0e, #7773ff);
27947          mask-image: linear-gradient(#ff0f0e, #7773ff);
27948          -webkit-mask-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
27949          mask-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
27950        }
27951      "#},
27952      Browsers {
27953        chrome: Some(95 << 16),
27954        ..Browsers::default()
27955      },
27956    );
27957
27958    prefix_test(
27959      ".foo { mask-image: linear-gradient(red, green) }",
27960      indoc! { r#"
27961        .foo {
27962          -webkit-mask-image: linear-gradient(red, green);
27963          mask-image: linear-gradient(red, green);
27964        }
27965      "#},
27966      Browsers {
27967        chrome: Some(95 << 16),
27968        ..Browsers::default()
27969      },
27970    );
27971
27972    prefix_test(
27973      ".foo { -webkit-mask-image: url(x.svg); mask-image: url(x.svg); }",
27974      indoc! { r#"
27975        .foo {
27976          -webkit-mask-image: url("x.svg");
27977          mask-image: url("x.svg");
27978        }
27979      "#},
27980      Browsers {
27981        chrome: Some(95 << 16),
27982        ..Browsers::default()
27983      },
27984    );
27985
27986    prefix_test(
27987      ".foo { mask: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 40px 20px }",
27988      indoc! { r#"
27989        .foo {
27990          -webkit-mask: -webkit-gradient(linear, 0 0, 0 100%, from(#ff0f0e), to(#7773ff)) 40px 20px;
27991          -webkit-mask: -webkit-linear-gradient(top, #ff0f0e, #7773ff) 40px 20px;
27992          -webkit-mask: linear-gradient(#ff0f0e, #7773ff) 40px 20px;
27993          mask: linear-gradient(#ff0f0e, #7773ff) 40px 20px;
27994          -webkit-mask: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 40px 20px;
27995          mask: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 40px 20px;
27996        }
27997      "#},
27998      Browsers {
27999        chrome: Some(8 << 16),
28000        ..Browsers::default()
28001      },
28002    );
28003
28004    prefix_test(
28005      ".foo { mask: -webkit-linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 40px 20px }",
28006      indoc! { r#"
28007        .foo {
28008          -webkit-mask: -webkit-gradient(linear, 0 0, 0 100%, from(#ff0f0e), to(#7773ff)) 40px 20px;
28009          -webkit-mask: -webkit-linear-gradient(#ff0f0e, #7773ff) 40px 20px;
28010        }
28011      "#},
28012      Browsers {
28013        chrome: Some(8 << 16),
28014        ..Browsers::default()
28015      },
28016    );
28017
28018    prefix_test(
28019      ".foo { mask: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 40px var(--foo) }",
28020      indoc! { r#"
28021        .foo {
28022          -webkit-mask: linear-gradient(#ff0f0e, #7773ff) 40px var(--foo);
28023          mask: linear-gradient(#ff0f0e, #7773ff) 40px var(--foo);
28024        }
28025
28026        @supports (color: lab(0% 0 0)) {
28027          .foo {
28028            -webkit-mask: linear-gradient(lab(56.208% 94.4644 98.8928), lab(51% 70.4544 -115.586)) 40px var(--foo);
28029            mask: linear-gradient(lab(56.208% 94.4644 98.8928), lab(51% 70.4544 -115.586)) 40px var(--foo);
28030          }
28031        }
28032      "#},
28033      Browsers {
28034        chrome: Some(90 << 16),
28035        ..Browsers::default()
28036      },
28037    );
28038
28039    prefix_test(
28040      r#"
28041        @supports (color: lab(0% 0 0)) {
28042          .foo {
28043            mask: linear-gradient(lab(56.208% 94.4644 98.8928), lab(51% 70.4544 -115.586)) 40px var(--foo);
28044          }
28045        }
28046      "#,
28047      indoc! { r#"
28048        @supports (color: lab(0% 0 0)) {
28049          .foo {
28050            -webkit-mask: linear-gradient(lab(56.208% 94.4644 98.8928), lab(51% 70.4544 -115.586)) 40px var(--foo);
28051            mask: linear-gradient(lab(56.208% 94.4644 98.8928), lab(51% 70.4544 -115.586)) 40px var(--foo);
28052          }
28053        }
28054      "#},
28055      Browsers {
28056        chrome: Some(90 << 16),
28057        ..Browsers::default()
28058      },
28059    );
28060
28061    prefix_test(
28062      ".foo { mask: url(masks.svg#star) luminance }",
28063      indoc! { r#"
28064        .foo {
28065          -webkit-mask: url("masks.svg#star");
28066          -webkit-mask-source-type: luminance;
28067          mask: url("masks.svg#star") luminance;
28068        }
28069    "#},
28070      Browsers {
28071        chrome: Some(90 << 16),
28072        ..Browsers::default()
28073      },
28074    );
28075
28076    prefix_test(
28077      ".foo { mask-image: url(masks.svg#star) }",
28078      indoc! { r#"
28079        .foo {
28080          -webkit-mask-image: url("masks.svg#star");
28081          mask-image: url("masks.svg#star");
28082        }
28083    "#},
28084      Browsers {
28085        chrome: Some(90 << 16),
28086        ..Browsers::default()
28087      },
28088    );
28089
28090    prefix_test(
28091      r#"
28092        .foo {
28093          mask-image: url(masks.svg#star);
28094          mask-position: 25% 75%;
28095          mask-size: cover;
28096          mask-repeat: no-repeat;
28097          mask-clip: padding-box;
28098          mask-origin: content-box;
28099          mask-composite: subtract;
28100          mask-mode: luminance;
28101        }
28102      "#,
28103      indoc! { r#"
28104        .foo {
28105          -webkit-mask: url("masks.svg#star") 25% 75% / cover no-repeat content-box padding-box;
28106          -webkit-mask-composite: source-out;
28107          -webkit-mask-source-type: luminance;
28108          mask: url("masks.svg#star") 25% 75% / cover no-repeat content-box padding-box subtract luminance;
28109        }
28110    "#},
28111      Browsers {
28112        chrome: Some(90 << 16),
28113        ..Browsers::default()
28114      },
28115    );
28116
28117    prefix_test(
28118      r#"
28119        .foo {
28120          mask-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
28121          mask-position: 25% 75%;
28122          mask-size: cover;
28123          mask-repeat: no-repeat;
28124          mask-clip: padding-box;
28125          mask-origin: content-box;
28126          mask-composite: subtract;
28127          mask-mode: luminance;
28128        }
28129      "#,
28130      indoc! { r#"
28131        .foo {
28132          -webkit-mask: linear-gradient(#ff0f0e, #7773ff) 25% 75% / cover no-repeat content-box padding-box;
28133          -webkit-mask-composite: source-out;
28134          -webkit-mask-source-type: luminance;
28135          mask: linear-gradient(#ff0f0e, #7773ff) 25% 75% / cover no-repeat content-box padding-box subtract luminance;
28136          -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;
28137          -webkit-mask-composite: source-out;
28138          -webkit-mask-source-type: luminance;
28139          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;
28140        }
28141    "#},
28142      Browsers {
28143        chrome: Some(90 << 16),
28144        ..Browsers::default()
28145      },
28146    );
28147
28148    test(
28149      r#"
28150        .foo {
28151          mask: none center / 100% no-repeat;
28152          mask-image: var(--svg);
28153        }
28154      "#,
28155      indoc! { r#"
28156        .foo {
28157          mask: none center / 100% no-repeat;
28158          mask-image: var(--svg);
28159        }
28160      "#},
28161    );
28162
28163    prefix_test(
28164      r#"
28165        .foo {
28166          mask-composite: subtract;
28167        }
28168      "#,
28169      indoc! { r#"
28170        .foo {
28171          -webkit-mask-composite: source-out;
28172          mask-composite: subtract;
28173        }
28174    "#},
28175      Browsers {
28176        chrome: Some(90 << 16),
28177        ..Browsers::default()
28178      },
28179    );
28180
28181    prefix_test(
28182      r#"
28183        .foo {
28184          mask-mode: luminance;
28185        }
28186      "#,
28187      indoc! { r#"
28188        .foo {
28189          -webkit-mask-source-type: luminance;
28190          mask-mode: luminance;
28191        }
28192    "#},
28193      Browsers {
28194        chrome: Some(90 << 16),
28195        ..Browsers::default()
28196      },
28197    );
28198
28199    prefix_test(
28200      r#"
28201        .foo {
28202          mask-border: url('border-mask.png') 25 / 35px / 12px space luminance;
28203        }
28204      "#,
28205      indoc! { r#"
28206        .foo {
28207          -webkit-mask-box-image: url("border-mask.png") 25 / 35px / 12px space;
28208          mask-border: url("border-mask.png") 25 / 35px / 12px space luminance;
28209        }
28210    "#},
28211      Browsers {
28212        chrome: Some(90 << 16),
28213        ..Browsers::default()
28214      },
28215    );
28216
28217    prefix_test(
28218      r#"
28219        .foo {
28220          mask-border: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 25 / 35px / 12px space luminance;
28221        }
28222      "#,
28223      indoc! { r#"
28224        .foo {
28225          -webkit-mask-box-image: linear-gradient(#ff0f0e, #7773ff) 25 / 35px / 12px space;
28226          mask-border: linear-gradient(#ff0f0e, #7773ff) 25 / 35px / 12px space luminance;
28227          -webkit-mask-box-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 25 / 35px / 12px space;
28228          mask-border: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 25 / 35px / 12px space luminance;
28229        }
28230    "#},
28231      Browsers {
28232        chrome: Some(90 << 16),
28233        ..Browsers::default()
28234      },
28235    );
28236
28237    prefix_test(
28238      r#"
28239        .foo {
28240          mask-border-source: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
28241        }
28242      "#,
28243      indoc! { r#"
28244        .foo {
28245          -webkit-mask-box-image-source: linear-gradient(#ff0f0e, #7773ff);
28246          mask-border-source: linear-gradient(#ff0f0e, #7773ff);
28247          -webkit-mask-box-image-source: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
28248          mask-border-source: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
28249        }
28250    "#},
28251      Browsers {
28252        chrome: Some(90 << 16),
28253        ..Browsers::default()
28254      },
28255    );
28256
28257    prefix_test(
28258      r#"
28259        .foo {
28260          mask-border-source: url(foo.png);
28261          mask-border-slice: 10 40 10 40;
28262          mask-border-width: 10px;
28263          mask-border-outset: 0;
28264          mask-border-repeat: round round;
28265          mask-border-mode: luminance;
28266        }
28267      "#,
28268      indoc! { r#"
28269        .foo {
28270          -webkit-mask-box-image: url("foo.png") 10 40 / 10px round;
28271          mask-border: url("foo.png") 10 40 / 10px round luminance;
28272        }
28273    "#},
28274      Browsers {
28275        chrome: Some(90 << 16),
28276        ..Browsers::default()
28277      },
28278    );
28279
28280    prefix_test(
28281      r#"
28282        .foo {
28283          -webkit-mask-box-image-source: url(foo.png);
28284          -webkit-mask-box-image-slice: 10 40 10 40;
28285          -webkit-mask-box-image-width: 10px;
28286          -webkit-mask-box-image-outset: 0;
28287          -webkit-mask-box-image-repeat: round round;
28288        }
28289      "#,
28290      indoc! { r#"
28291        .foo {
28292          -webkit-mask-box-image: url("foo.png") 10 40 / 10px round;
28293        }
28294    "#},
28295      Browsers {
28296        chrome: Some(90 << 16),
28297        ..Browsers::default()
28298      },
28299    );
28300
28301    prefix_test(
28302      r#"
28303        .foo {
28304          mask-border-slice: 10 40 10 40;
28305        }
28306      "#,
28307      indoc! { r#"
28308        .foo {
28309          -webkit-mask-box-image-slice: 10 40;
28310          mask-border-slice: 10 40;
28311        }
28312    "#},
28313      Browsers {
28314        chrome: Some(90 << 16),
28315        ..Browsers::default()
28316      },
28317    );
28318
28319    prefix_test(
28320      r#"
28321        .foo {
28322          mask-border-slice: var(--foo);
28323        }
28324      "#,
28325      indoc! { r#"
28326        .foo {
28327          -webkit-mask-box-image-slice: var(--foo);
28328          mask-border-slice: var(--foo);
28329        }
28330    "#},
28331      Browsers {
28332        chrome: Some(90 << 16),
28333        ..Browsers::default()
28334      },
28335    );
28336
28337    prefix_test(
28338      r#"
28339        .foo {
28340          mask-border: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) var(--foo);
28341        }
28342      "#,
28343      indoc! { r#"
28344        .foo {
28345          -webkit-mask-box-image: linear-gradient(#ff0f0e, #7773ff) var(--foo);
28346          mask-border: linear-gradient(#ff0f0e, #7773ff) var(--foo);
28347        }
28348
28349        @supports (color: lab(0% 0 0)) {
28350          .foo {
28351            -webkit-mask-box-image: linear-gradient(lab(56.208% 94.4644 98.8928), lab(51% 70.4544 -115.586)) var(--foo);
28352            mask-border: linear-gradient(lab(56.208% 94.4644 98.8928), lab(51% 70.4544 -115.586)) var(--foo);
28353          }
28354        }
28355    "#},
28356      Browsers {
28357        chrome: Some(90 << 16),
28358        ..Browsers::default()
28359      },
28360    );
28361
28362    prefix_test(
28363      r#"
28364        .foo {
28365          transition: mask 200ms;
28366        }
28367      "#,
28368      indoc! { r#"
28369        .foo {
28370          transition: -webkit-mask .2s, mask .2s;
28371        }
28372    "#},
28373      Browsers {
28374        chrome: Some(90 << 16),
28375        ..Browsers::default()
28376      },
28377    );
28378
28379    prefix_test(
28380      r#"
28381        .foo {
28382          transition: mask-border 200ms;
28383        }
28384      "#,
28385      indoc! { r#"
28386        .foo {
28387          transition: -webkit-mask-box-image .2s, mask-border .2s;
28388        }
28389    "#},
28390      Browsers {
28391        chrome: Some(90 << 16),
28392        ..Browsers::default()
28393      },
28394    );
28395
28396    prefix_test(
28397      r#"
28398        .foo {
28399          transition-property: mask;
28400        }
28401      "#,
28402      indoc! { r#"
28403        .foo {
28404          transition-property: -webkit-mask, mask;
28405        }
28406    "#},
28407      Browsers {
28408        chrome: Some(90 << 16),
28409        ..Browsers::default()
28410      },
28411    );
28412
28413    prefix_test(
28414      r#"
28415        .foo {
28416          transition-property: mask-border;
28417        }
28418      "#,
28419      indoc! { r#"
28420        .foo {
28421          transition-property: -webkit-mask-box-image, mask-border;
28422        }
28423    "#},
28424      Browsers {
28425        chrome: Some(90 << 16),
28426        ..Browsers::default()
28427      },
28428    );
28429
28430    prefix_test(
28431      r#"
28432        .foo {
28433          transition-property: mask-composite, mask-mode;
28434        }
28435      "#,
28436      indoc! { r#"
28437        .foo {
28438          transition-property: -webkit-mask-composite, mask-composite, -webkit-mask-source-type, mask-mode;
28439        }
28440    "#},
28441      Browsers {
28442        chrome: Some(90 << 16),
28443        ..Browsers::default()
28444      },
28445    );
28446
28447    let property =
28448      Property::parse_string("text-rendering".into(), "geometricPrecision", ParserOptions::default()).unwrap();
28449    assert_eq!(
28450      property,
28451      Property::TextRendering(svg::TextRendering::GeometricPrecision)
28452    );
28453    let property =
28454      Property::parse_string("shape-rendering".into(), "geometricPrecision", ParserOptions::default()).unwrap();
28455    assert_eq!(
28456      property,
28457      Property::ShapeRendering(svg::ShapeRendering::GeometricPrecision)
28458    );
28459    let property = Property::parse_string("color-interpolation".into(), "sRGB", ParserOptions::default()).unwrap();
28460    assert_eq!(property, Property::ColorInterpolation(svg::ColorInterpolation::SRGB));
28461  }
28462
28463  #[test]
28464  fn test_filter() {
28465    minify_test(
28466      ".foo { filter: url('filters.svg#filter-id'); }",
28467      ".foo{filter:url(filters.svg#filter-id)}",
28468    );
28469    minify_test(".foo { filter: blur(5px); }", ".foo{filter:blur(5px)}");
28470    minify_test(".foo { filter: blur(0px); }", ".foo{filter:blur()}");
28471    minify_test(".foo { filter: brightness(10%); }", ".foo{filter:brightness(10%)}");
28472    minify_test(".foo { filter: brightness(100%); }", ".foo{filter:brightness()}");
28473    minify_test(
28474      ".foo { filter: drop-shadow(16px 16px 20px yellow); }",
28475      ".foo{filter:drop-shadow(16px 16px 20px #ff0)}",
28476    );
28477    minify_test(
28478      ".foo { filter: contrast(175%) brightness(3%); }",
28479      ".foo{filter:contrast(175%)brightness(3%)}",
28480    );
28481    minify_test(".foo { filter: hue-rotate(0) }", ".foo{filter:hue-rotate()}");
28482
28483    prefix_test(
28484      ".foo { filter: blur(5px) }",
28485      indoc! { r#"
28486        .foo {
28487          -webkit-filter: blur(5px);
28488          filter: blur(5px);
28489        }
28490      "#},
28491      Browsers {
28492        chrome: Some(20 << 16),
28493        ..Browsers::default()
28494      },
28495    );
28496
28497    prefix_test(
28498      ".foo { filter: blur(5px) }",
28499      indoc! { r#"
28500        .foo {
28501          filter: blur(5px);
28502        }
28503      "#},
28504      Browsers {
28505        chrome: Some(80 << 16),
28506        ..Browsers::default()
28507      },
28508    );
28509
28510    prefix_test(
28511      ".foo { backdrop-filter: blur(5px) }",
28512      indoc! { r#"
28513        .foo {
28514          backdrop-filter: blur(5px);
28515        }
28516      "#},
28517      Browsers {
28518        chrome: Some(80 << 16),
28519        ..Browsers::default()
28520      },
28521    );
28522
28523    prefix_test(
28524      ".foo { backdrop-filter: blur(5px) }",
28525      indoc! { r#"
28526        .foo {
28527          -webkit-backdrop-filter: blur(5px);
28528          backdrop-filter: blur(5px);
28529        }
28530      "#},
28531      Browsers {
28532        safari: Some(15 << 16),
28533        ..Browsers::default()
28534      },
28535    );
28536    prefix_test(
28537      r#"
28538      .foo {
28539        -webkit-backdrop-filter: blur(8px);
28540        backdrop-filter: blur(8px);
28541      }
28542      "#,
28543      indoc! {r#"
28544      .foo {
28545        -webkit-backdrop-filter: blur(8px);
28546        backdrop-filter: blur(8px);
28547      }
28548      "#},
28549      Browsers {
28550        safari: Some(16 << 16),
28551        ..Browsers::default()
28552      },
28553    );
28554
28555    prefix_test(
28556      ".foo { filter: var(--foo) }",
28557      indoc! { r#"
28558        .foo {
28559          -webkit-filter: var(--foo);
28560          filter: var(--foo);
28561        }
28562      "#},
28563      Browsers {
28564        chrome: Some(20 << 16),
28565        ..Browsers::default()
28566      },
28567    );
28568
28569    prefix_test(
28570      ".foo { filter: drop-shadow(16px 16px 20px lab(40% 56.6 39)) }",
28571      indoc! { r#"
28572        .foo {
28573          -webkit-filter: drop-shadow(16px 16px 20px #b32323);
28574          filter: drop-shadow(16px 16px 20px #b32323);
28575          filter: drop-shadow(16px 16px 20px lab(40% 56.6 39));
28576        }
28577      "#},
28578      Browsers {
28579        chrome: Some(20 << 16),
28580        ..Browsers::default()
28581      },
28582    );
28583
28584    prefix_test(
28585      ".foo { filter: contrast(175%) drop-shadow(16px 16px 20px lab(40% 56.6 39)) }",
28586      indoc! { r#"
28587        .foo {
28588          filter: contrast(175%) drop-shadow(16px 16px 20px #b32323);
28589          filter: contrast(175%) drop-shadow(16px 16px 20px lab(40% 56.6 39));
28590        }
28591      "#},
28592      Browsers {
28593        chrome: Some(4 << 16),
28594        ..Browsers::default()
28595      },
28596    );
28597
28598    prefix_test(
28599      ".foo { filter: drop-shadow(16px 16px 20px lab(40% 56.6 39)) drop-shadow(16px 16px 20px yellow) }",
28600      indoc! { r#"
28601        .foo {
28602          filter: drop-shadow(16px 16px 20px #b32323) drop-shadow(16px 16px 20px #ff0);
28603          filter: drop-shadow(16px 16px 20px lab(40% 56.6 39)) drop-shadow(16px 16px 20px #ff0);
28604        }
28605      "#},
28606      Browsers {
28607        chrome: Some(4 << 16),
28608        ..Browsers::default()
28609      },
28610    );
28611
28612    prefix_test(
28613      ".foo { filter: var(--foo) drop-shadow(16px 16px 20px lab(40% 56.6 39)) }",
28614      indoc! { r#"
28615        .foo {
28616          filter: var(--foo) drop-shadow(16px 16px 20px #b32323);
28617        }
28618
28619        @supports (color: lab(0% 0 0)) {
28620          .foo {
28621            filter: var(--foo) drop-shadow(16px 16px 20px lab(40% 56.6 39));
28622          }
28623        }
28624      "#},
28625      Browsers {
28626        chrome: Some(4 << 16),
28627        ..Browsers::default()
28628      },
28629    );
28630  }
28631
28632  #[test]
28633  fn test_mix_blend_mode() {
28634    minify_test(".foo { mix-blend-mode: normal }", ".foo{mix-blend-mode:normal}");
28635    minify_test(".foo { mix-blend-mode: multiply }", ".foo{mix-blend-mode:multiply}");
28636    minify_test(".foo { mix-blend-mode: screen }", ".foo{mix-blend-mode:screen}");
28637    minify_test(".foo { mix-blend-mode: overlay }", ".foo{mix-blend-mode:overlay}");
28638    minify_test(".foo { mix-blend-mode: darken }", ".foo{mix-blend-mode:darken}");
28639    minify_test(".foo { mix-blend-mode: lighten }", ".foo{mix-blend-mode:lighten}");
28640    minify_test(
28641      ".foo { mix-blend-mode: color-dodge }",
28642      ".foo{mix-blend-mode:color-dodge}",
28643    );
28644    minify_test(".foo { mix-blend-mode: color-burn }", ".foo{mix-blend-mode:color-burn}");
28645    minify_test(".foo { mix-blend-mode: hard-light }", ".foo{mix-blend-mode:hard-light}");
28646    minify_test(".foo { mix-blend-mode: soft-light }", ".foo{mix-blend-mode:soft-light}");
28647    minify_test(".foo { mix-blend-mode: difference }", ".foo{mix-blend-mode:difference}");
28648    minify_test(".foo { mix-blend-mode: exclusion }", ".foo{mix-blend-mode:exclusion}");
28649    minify_test(".foo { mix-blend-mode: hue }", ".foo{mix-blend-mode:hue}");
28650    minify_test(".foo { mix-blend-mode: saturation }", ".foo{mix-blend-mode:saturation}");
28651    minify_test(".foo { mix-blend-mode: color }", ".foo{mix-blend-mode:color}");
28652    minify_test(".foo { mix-blend-mode: luminosity }", ".foo{mix-blend-mode:luminosity}");
28653    minify_test(
28654      ".foo { mix-blend-mode: plus-darker }",
28655      ".foo{mix-blend-mode:plus-darker}",
28656    );
28657    minify_test(
28658      ".foo { mix-blend-mode: plus-lighter }",
28659      ".foo{mix-blend-mode:plus-lighter}",
28660    );
28661  }
28662
28663  #[test]
28664  fn test_viewport() {
28665    minify_test(
28666      r#"
28667    @viewport {
28668      width: 100vw;
28669    }"#,
28670      "@viewport{width:100vw}",
28671    );
28672    minify_test(
28673      r#"
28674    @-ms-viewport {
28675      width: device-width;
28676    }"#,
28677      "@-ms-viewport{width:device-width}",
28678    );
28679  }
28680
28681  #[test]
28682  fn test_at_scope() {
28683    minify_test(
28684      r#"
28685      @scope {
28686        .foo {
28687          display: flex;
28688        }
28689      }
28690      "#,
28691      "@scope{.foo{display:flex}}",
28692    );
28693    minify_test(
28694      r#"
28695      @scope {
28696        :scope {
28697          display: flex;
28698          color: lightblue;
28699        }
28700      }"#,
28701      "@scope{:scope{color:#add8e6;display:flex}}",
28702    );
28703    minify_test(
28704      r#"
28705      @scope (.light-scheme) {
28706        a { color: yellow; }
28707      }
28708      "#,
28709      "@scope(.light-scheme){a{color:#ff0}}",
28710    );
28711    minify_test(
28712      r#"
28713      @scope (.media-object) to (.content > *) {
28714        a { color: yellow; }
28715      }
28716      "#,
28717      "@scope(.media-object) to (.content>*){a{color:#ff0}}",
28718    );
28719    minify_test(
28720      r#"
28721      @scope to (.content > *) {
28722        a { color: yellow; }
28723      }
28724      "#,
28725      "@scope to (.content>*){a{color:#ff0}}",
28726    );
28727    minify_test(
28728      r#"
28729      @scope (#my-component) {
28730        & { color: yellow; }
28731      }
28732      "#,
28733      "@scope(#my-component){&{color:#ff0}}",
28734    );
28735    minify_test(
28736      r#"
28737      @scope (.parent-scope) {
28738        @scope (:scope > .child-scope) to (:scope .limit) {
28739          .content { color: yellow; }
28740        }
28741      }
28742      "#,
28743      "@scope(.parent-scope){@scope(:scope>.child-scope) to (:scope .limit){.content{color:#ff0}}}",
28744    );
28745    minify_test(
28746      r#"
28747      .foo {
28748        @scope (.bar) {
28749          color: yellow;
28750        }
28751      }
28752      "#,
28753      ".foo{@scope(.bar){color:#ff0}}",
28754    );
28755    nesting_test(
28756      r#"
28757      .foo {
28758        @scope (.bar) {
28759          color: yellow;
28760        }
28761      }
28762      "#,
28763      indoc! {r#"
28764        @scope (.bar) {
28765          color: #ff0;
28766        }
28767      "#},
28768    );
28769    nesting_test(
28770      r#"
28771      .parent {
28772        color: blue;
28773
28774        @scope (& > .scope) to (& .limit) {
28775          & .content {
28776            color: yellow;
28777          }
28778        }
28779      }
28780      "#,
28781      indoc! {r#"
28782        .parent {
28783          color: #00f;
28784        }
28785
28786        @scope (.parent > .scope) to (.parent > .scope .limit) {
28787          :scope .content {
28788            color: #ff0;
28789          }
28790        }
28791      "#},
28792    );
28793  }
28794
28795  #[test]
28796  fn test_custom_media() {
28797    custom_media_test(
28798      r#"
28799      @custom-media --modern (color), (hover);
28800
28801      @media (--modern) and (width > 1024px) {
28802        .a {
28803          color: green;
28804        }
28805      }
28806      "#,
28807      indoc! {r#"
28808      @media ((color) or (hover)) and (width > 1024px) {
28809        .a {
28810          color: green;
28811        }
28812      }
28813      "#},
28814    );
28815
28816    custom_media_test(
28817      r#"
28818      @custom-media --color (color);
28819
28820      @media (--color) and (width > 1024px) {
28821        .a {
28822          color: green;
28823        }
28824      }
28825      "#,
28826      indoc! {r#"
28827      @media (color) and (width > 1024px) {
28828        .a {
28829          color: green;
28830        }
28831      }
28832      "#},
28833    );
28834
28835    custom_media_test(
28836      r#"
28837      @custom-media --a (color);
28838      @custom-media --b (--a);
28839
28840      @media (--b) and (width > 1024px) {
28841        .a {
28842          color: green;
28843        }
28844      }
28845      "#,
28846      indoc! {r#"
28847      @media (color) and (width > 1024px) {
28848        .a {
28849          color: green;
28850        }
28851      }
28852      "#},
28853    );
28854
28855    custom_media_test(
28856      r#"
28857      @custom-media --not-color not (color);
28858
28859      @media not (--not-color) {
28860        .a {
28861          color: green;
28862        }
28863      }
28864      "#,
28865      indoc! {r#"
28866      @media (color) {
28867        .a {
28868          color: green;
28869        }
28870      }
28871      "#},
28872    );
28873
28874    custom_media_test(
28875      r#"
28876      @custom-media --color-print print and (color);
28877
28878      @media (--color-print) {
28879        .a {
28880          color: green;
28881        }
28882      }
28883      "#,
28884      indoc! {r#"
28885      @media print and (color) {
28886        .a {
28887          color: green;
28888        }
28889      }
28890      "#},
28891    );
28892
28893    custom_media_test(
28894      r#"
28895      @custom-media --color-print print and (color);
28896
28897      @media print and (--color-print) {
28898        .a {
28899          color: green;
28900        }
28901      }
28902      "#,
28903      indoc! {r#"
28904      @media print and (color) {
28905        .a {
28906          color: green;
28907        }
28908      }
28909      "#},
28910    );
28911
28912    custom_media_test(
28913      r#"
28914      @custom-media --not-color-print not print and (color);
28915
28916      @media not print and (--not-color-print) {
28917        .a {
28918          color: green;
28919        }
28920      }
28921      "#,
28922      indoc! {r#"
28923      @media not print and (color) {
28924        .a {
28925          color: green;
28926        }
28927      }
28928      "#},
28929    );
28930
28931    custom_media_test(
28932      r#"
28933      @custom-media --print print;
28934
28935      @media (--print) {
28936        .a {
28937          color: green;
28938        }
28939      }
28940      "#,
28941      indoc! {r#"
28942      @media print {
28943        .a {
28944          color: green;
28945        }
28946      }
28947      "#},
28948    );
28949
28950    custom_media_test(
28951      r#"
28952      @custom-media --print print;
28953
28954      @media not (--print) {
28955        .a {
28956          color: green;
28957        }
28958      }
28959      "#,
28960      indoc! {r#"
28961      @media not print {
28962        .a {
28963          color: green;
28964        }
28965      }
28966      "#},
28967    );
28968
28969    custom_media_test(
28970      r#"
28971      @custom-media --print not print;
28972
28973      @media not (--print) {
28974        .a {
28975          color: green;
28976        }
28977      }
28978      "#,
28979      indoc! {r#"
28980      @media print {
28981        .a {
28982          color: green;
28983        }
28984      }
28985      "#},
28986    );
28987
28988    custom_media_test(
28989      r#"
28990      @custom-media --print print;
28991
28992      @media ((--print)) {
28993        .a {
28994          color: green;
28995        }
28996      }
28997      "#,
28998      indoc! {r#"
28999      @media print {
29000        .a {
29001          color: green;
29002        }
29003      }
29004      "#},
29005    );
29006
29007    custom_media_test(
29008      r#"
29009      @custom-media --color (color);
29010      @custom-media --print print;
29011
29012      @media (--print) and (--color) {
29013        .a {
29014          color: green;
29015        }
29016      }
29017      "#,
29018      indoc! {r#"
29019      @media print and (color) {
29020        .a {
29021          color: green;
29022        }
29023      }
29024      "#},
29025    );
29026
29027    custom_media_test(
29028      r#"
29029      @custom-media --color (color);
29030      @custom-media --not-print not print;
29031
29032      @media (--not-print) and (--color) {
29033        .a {
29034          color: green;
29035        }
29036      }
29037      "#,
29038      indoc! {r#"
29039      @media not print and (color) {
29040        .a {
29041          color: green;
29042        }
29043      }
29044      "#},
29045    );
29046
29047    custom_media_test(
29048      r#"
29049      @custom-media --color (color);
29050      @custom-media --screen screen;
29051      @custom-media --print print;
29052
29053      @media (--print) and (--color), (--screen) and (--color) {
29054        .a {
29055          color: green;
29056        }
29057      }
29058      "#,
29059      indoc! {r#"
29060      @media print and (color), screen and (color) {
29061        .a {
29062          color: green;
29063        }
29064      }
29065      "#},
29066    );
29067
29068    custom_media_test(
29069      r#"
29070      @custom-media --color print and (color), print and (script);
29071
29072      @media (--color) {
29073        .a {
29074          color: green;
29075        }
29076      }
29077      "#,
29078      indoc! {r#"
29079      @media print and ((color) or (script)) {
29080        .a {
29081          color: green;
29082        }
29083      }
29084      "#},
29085    );
29086
29087    custom_media_test(
29088      r#"
29089      @custom-media --color (color);
29090      @custom-media --not-color not all and (--color);
29091
29092      @media (--not-color) {
29093        .a {
29094          color: green;
29095        }
29096      }
29097      "#,
29098      indoc! {r#"
29099        @media not all and (color) {
29100          .a {
29101            color: green;
29102          }
29103        }
29104      "#},
29105    );
29106
29107    custom_media_test(
29108      r#"
29109      @custom-media --color (color);
29110
29111      @media not all and (--color) {
29112        .a {
29113          color: green;
29114        }
29115      }
29116      "#,
29117      indoc! {r#"
29118        @media not all and (color) {
29119          .a {
29120            color: green;
29121          }
29122        }
29123      "#},
29124    );
29125
29126    custom_media_test(
29127      r#"
29128      @media (--print) {
29129        .a {
29130          color: green;
29131        }
29132      }
29133
29134      @custom-media --print print;
29135      "#,
29136      indoc! {r#"
29137      @media print {
29138        .a {
29139          color: green;
29140        }
29141      }
29142      "#},
29143    );
29144
29145    custom_media_test(
29146      r#"
29147      @custom-media --not-width not (min-width: 300px);
29148      @media screen and ((prefers-color-scheme: dark) or (--not-width)) {
29149        .foo {
29150          order: 6;
29151        }
29152      }
29153      "#,
29154      indoc! {r#"
29155      @media screen and ((prefers-color-scheme: dark) or ((width < 300px))) {
29156        .foo {
29157          order: 6;
29158        }
29159      }
29160      "#},
29161    );
29162
29163    fn custom_media_error_test(source: &str, err: Error<MinifyErrorKind>) {
29164      let mut stylesheet = StyleSheet::parse(
29165        &source,
29166        ParserOptions {
29167          filename: "test.css".into(),
29168          flags: ParserFlags::CUSTOM_MEDIA,
29169          ..ParserOptions::default()
29170        },
29171      )
29172      .unwrap();
29173      let res = stylesheet.minify(MinifyOptions {
29174        targets: Browsers {
29175          chrome: Some(95 << 16),
29176          ..Browsers::default()
29177        }
29178        .into(),
29179        ..MinifyOptions::default()
29180      });
29181      assert_eq!(res, Err(err))
29182    }
29183
29184    custom_media_error_test(
29185      r#"
29186      @custom-media --color-print print and (color);
29187
29188      @media screen and (--color-print) {
29189        .a {
29190          color: green;
29191        }
29192      }
29193      "#,
29194      Error {
29195        kind: MinifyErrorKind::UnsupportedCustomMediaBooleanLogic {
29196          custom_media_loc: Location {
29197            source_index: 0,
29198            line: 1,
29199            column: 7,
29200          },
29201        },
29202        loc: Some(ErrorLocation {
29203          filename: "test.css".into(),
29204          line: 3,
29205          column: 7,
29206        }),
29207      },
29208    );
29209
29210    custom_media_error_test(
29211      r#"
29212      @custom-media --color-print print and (color);
29213
29214      @media not print and (--color-print) {
29215        .a {
29216          color: green;
29217        }
29218      }
29219      "#,
29220      Error {
29221        kind: MinifyErrorKind::UnsupportedCustomMediaBooleanLogic {
29222          custom_media_loc: Location {
29223            source_index: 0,
29224            line: 1,
29225            column: 7,
29226          },
29227        },
29228        loc: Some(ErrorLocation {
29229          filename: "test.css".into(),
29230          line: 3,
29231          column: 7,
29232        }),
29233      },
29234    );
29235
29236    custom_media_error_test(
29237      r#"
29238      @custom-media --color-print print and (color);
29239      @custom-media --color-screen screen and (color);
29240
29241      @media (--color-print) or (--color-screen) {}
29242      "#,
29243      Error {
29244        kind: MinifyErrorKind::UnsupportedCustomMediaBooleanLogic {
29245          custom_media_loc: Location {
29246            source_index: 0,
29247            line: 2,
29248            column: 7,
29249          },
29250        },
29251        loc: Some(ErrorLocation {
29252          filename: "test.css".into(),
29253          line: 4,
29254          column: 7,
29255        }),
29256      },
29257    );
29258
29259    custom_media_error_test(
29260      r#"
29261      @custom-media --color-print print and (color);
29262      @custom-media --color-screen screen and (color);
29263
29264      @media (--color-print) and (--color-screen) {}
29265      "#,
29266      Error {
29267        kind: MinifyErrorKind::UnsupportedCustomMediaBooleanLogic {
29268          custom_media_loc: Location {
29269            source_index: 0,
29270            line: 2,
29271            column: 7,
29272          },
29273        },
29274        loc: Some(ErrorLocation {
29275          filename: "test.css".into(),
29276          line: 4,
29277          column: 7,
29278        }),
29279      },
29280    );
29281
29282    custom_media_error_test(
29283      r#"
29284      @custom-media --screen screen;
29285      @custom-media --print print;
29286
29287      @media (--print) and (--screen) {}
29288      "#,
29289      Error {
29290        kind: MinifyErrorKind::UnsupportedCustomMediaBooleanLogic {
29291          custom_media_loc: Location {
29292            source_index: 0,
29293            line: 1,
29294            column: 7,
29295          },
29296        },
29297        loc: Some(ErrorLocation {
29298          filename: "test.css".into(),
29299          line: 4,
29300          column: 7,
29301        }),
29302      },
29303    );
29304
29305    custom_media_error_test(
29306      r#"
29307      @custom-media --not-print not print and (color);
29308      @custom-media --not-screen not screen and (color);
29309
29310      @media ((script) or ((--not-print) and (--not-screen))) {
29311        .a {
29312          color: green;
29313        }
29314      }
29315      "#,
29316      Error {
29317        kind: MinifyErrorKind::UnsupportedCustomMediaBooleanLogic {
29318          custom_media_loc: Location {
29319            source_index: 0,
29320            line: 2,
29321            column: 7,
29322          },
29323        },
29324        loc: Some(ErrorLocation {
29325          filename: "test.css".into(),
29326          line: 4,
29327          column: 7,
29328        }),
29329      },
29330    );
29331
29332    custom_media_error_test(
29333      r#"
29334      @custom-media --color screen and (color), print and (color);
29335
29336      @media (--color) {
29337        .a {
29338          color: green;
29339        }
29340      }
29341      "#,
29342      Error {
29343        kind: MinifyErrorKind::UnsupportedCustomMediaBooleanLogic {
29344          custom_media_loc: Location {
29345            source_index: 0,
29346            line: 1,
29347            column: 7,
29348          },
29349        },
29350        loc: Some(ErrorLocation {
29351          filename: "test.css".into(),
29352          line: 3,
29353          column: 7,
29354        }),
29355      },
29356    );
29357
29358    custom_media_error_test(
29359      r#"
29360      @media (--not-defined) {
29361        .a {
29362          color: green;
29363        }
29364      }
29365      "#,
29366      Error {
29367        kind: MinifyErrorKind::CustomMediaNotDefined {
29368          name: "--not-defined".into(),
29369        },
29370        loc: Some(ErrorLocation {
29371          filename: "test.css".into(),
29372          line: 1,
29373          column: 7,
29374        }),
29375      },
29376    );
29377
29378    custom_media_error_test(
29379      r#"
29380      @custom-media --circular-mq-a (--circular-mq-b);
29381      @custom-media --circular-mq-b (--circular-mq-a);
29382
29383      @media (--circular-mq-a) {
29384        body {
29385          order: 3;
29386        }
29387      }
29388      "#,
29389      Error {
29390        kind: MinifyErrorKind::CircularCustomMedia {
29391          name: "--circular-mq-a".into(),
29392        },
29393        loc: Some(ErrorLocation {
29394          filename: "test.css".into(),
29395          line: 4,
29396          column: 7,
29397        }),
29398      },
29399    );
29400  }
29401
29402  #[test]
29403  fn test_dependencies() {
29404    fn dep_test(source: &str, expected: &str, deps: Vec<(&str, &str)>) {
29405      let mut stylesheet = StyleSheet::parse(
29406        &source,
29407        ParserOptions {
29408          filename: "test.css".into(),
29409          ..ParserOptions::default()
29410        },
29411      )
29412      .unwrap();
29413      stylesheet.minify(MinifyOptions::default()).unwrap();
29414      let res = stylesheet
29415        .to_css(PrinterOptions {
29416          analyze_dependencies: Some(Default::default()),
29417          minify: true,
29418          ..PrinterOptions::default()
29419        })
29420        .unwrap();
29421      assert_eq!(res.code, expected);
29422      let dependencies = res.dependencies.unwrap();
29423      assert_eq!(dependencies.len(), deps.len());
29424      for (i, (url, placeholder)) in deps.into_iter().enumerate() {
29425        match &dependencies[i] {
29426          Dependency::Url(dep) => {
29427            assert_eq!(dep.url, url);
29428            assert_eq!(dep.placeholder, placeholder);
29429          }
29430          Dependency::Import(dep) => {
29431            assert_eq!(dep.url, url);
29432            assert_eq!(dep.placeholder, placeholder);
29433          }
29434        }
29435      }
29436    }
29437
29438    fn dep_error_test(source: &str, error: PrinterErrorKind) {
29439      let stylesheet = StyleSheet::parse(&source, ParserOptions::default()).unwrap();
29440      let res = stylesheet.to_css(PrinterOptions {
29441        analyze_dependencies: Some(Default::default()),
29442        ..PrinterOptions::default()
29443      });
29444      match res {
29445        Err(e) => assert_eq!(e.kind, error),
29446        _ => unreachable!(),
29447      }
29448    }
29449
29450    dep_test(
29451      ".foo { background: image-set('./img12x.png', './img21x.png' 2x)}",
29452      ".foo{background:image-set(\"hXFI8W\" 1x,\"5TkpBa\" 2x)}",
29453      vec![("./img12x.png", "hXFI8W"), ("./img21x.png", "5TkpBa")],
29454    );
29455
29456    dep_test(
29457      ".foo { background: image-set(url(./img12x.png), url('./img21x.png') 2x)}",
29458      ".foo{background:image-set(\"hXFI8W\" 1x,\"5TkpBa\" 2x)}",
29459      vec![("./img12x.png", "hXFI8W"), ("./img21x.png", "5TkpBa")],
29460    );
29461
29462    dep_test(
29463      ".foo { --test: url(/foo.png) }",
29464      ".foo{--test:url(\"lDnnrG\")}",
29465      vec![("/foo.png", "lDnnrG")],
29466    );
29467
29468    dep_test(
29469      ".foo { --test: url(\"/foo.png\") }",
29470      ".foo{--test:url(\"lDnnrG\")}",
29471      vec![("/foo.png", "lDnnrG")],
29472    );
29473
29474    dep_test(
29475      ".foo { --test: url(\"http://example.com/foo.png\") }",
29476      ".foo{--test:url(\"3X1zSW\")}",
29477      vec![("http://example.com/foo.png", "3X1zSW")],
29478    );
29479
29480    dep_test(
29481      ".foo { --test: url(\"data:image/svg+xml;utf8,<svg></svg>\") }",
29482      ".foo{--test:url(\"-vl-rG\")}",
29483      vec![("data:image/svg+xml;utf8,<svg></svg>", "-vl-rG")],
29484    );
29485
29486    dep_test(
29487      ".foo { background: url(\"foo.png\") var(--test) }",
29488      ".foo{background:url(\"Vwkwkq\") var(--test)}",
29489      vec![("foo.png", "Vwkwkq")],
29490    );
29491
29492    dep_error_test(
29493      ".foo { --test: url(\"foo.png\") }",
29494      PrinterErrorKind::AmbiguousUrlInCustomProperty { url: "foo.png".into() },
29495    );
29496
29497    dep_error_test(
29498      ".foo { --test: url(foo.png) }",
29499      PrinterErrorKind::AmbiguousUrlInCustomProperty { url: "foo.png".into() },
29500    );
29501
29502    dep_error_test(
29503      ".foo { --test: url(./foo.png) }",
29504      PrinterErrorKind::AmbiguousUrlInCustomProperty {
29505        url: "./foo.png".into(),
29506      },
29507    );
29508
29509    dep_test(
29510      ".foo { behavior: url(#foo) }",
29511      ".foo{behavior:url(\"Zn9-2q\")}",
29512      vec![("#foo", "Zn9-2q")],
29513    );
29514
29515    dep_test(
29516      ".foo { --foo: url(#foo) }",
29517      ".foo{--foo:url(\"Zn9-2q\")}",
29518      vec![("#foo", "Zn9-2q")],
29519    );
29520
29521    dep_test(
29522      "@import \"test.css\"; .foo { color: red }",
29523      "@import \"hHsogW\";.foo{color:red}",
29524      vec![("test.css", "hHsogW")],
29525    );
29526  }
29527
29528  #[test]
29529  fn test_api() {
29530    let stylesheet = StyleSheet::parse(".foo:hover { color: red }", ParserOptions::default()).unwrap();
29531    match &stylesheet.rules.0[0] {
29532      CssRule::Style(s) => {
29533        assert_eq!(&s.selectors.to_string(), ".foo:hover");
29534      }
29535      _ => unreachable!(),
29536    }
29537
29538    let color = CssColor::parse_string("#f0f").unwrap();
29539    assert_eq!(color.to_css_string(PrinterOptions::default()).unwrap(), "#f0f");
29540
29541    let rule = CssRule::parse_string(".foo { color: red }", ParserOptions::default()).unwrap();
29542    assert_eq!(
29543      rule.to_css_string(PrinterOptions::default()).unwrap(),
29544      indoc! {r#"
29545    .foo {
29546      color: red;
29547    }"#}
29548    );
29549
29550    let property = Property::parse_string("color".into(), "#f0f", ParserOptions::default()).unwrap();
29551    assert_eq!(
29552      property.to_css_string(false, PrinterOptions::default()).unwrap(),
29553      "color: #f0f"
29554    );
29555    assert_eq!(
29556      property.to_css_string(true, PrinterOptions::default()).unwrap(),
29557      "color: #f0f !important"
29558    );
29559
29560    let code = indoc! { r#"
29561      .foo {
29562        color: green;
29563      }
29564
29565      .bar {
29566        color: red;
29567        background: pink;
29568      }
29569
29570      @media print {
29571        .baz {
29572          color: green;
29573        }
29574      }
29575    "#};
29576    let stylesheet = StyleSheet::parse(code, ParserOptions::default()).unwrap();
29577    if let CssRule::Style(style) = &stylesheet.rules.0[1] {
29578      let (key, val) = style.property_location(code, 0).unwrap();
29579      assert_eq!(
29580        key,
29581        SourceLocation { line: 5, column: 3 }..SourceLocation { line: 5, column: 8 }
29582      );
29583      assert_eq!(
29584        val,
29585        SourceLocation { line: 5, column: 10 }..SourceLocation { line: 5, column: 13 }
29586      );
29587    }
29588
29589    if let CssRule::Style(style) = &stylesheet.rules.0[1] {
29590      let (key, val) = style.property_location(code, 1).unwrap();
29591      assert_eq!(
29592        key,
29593        SourceLocation { line: 6, column: 3 }..SourceLocation { line: 6, column: 13 }
29594      );
29595      assert_eq!(
29596        val,
29597        SourceLocation { line: 6, column: 15 }..SourceLocation { line: 6, column: 19 }
29598      );
29599    }
29600    if let CssRule::Media(media) = &stylesheet.rules.0[2] {
29601      if let CssRule::Style(style) = &media.rules.0[0] {
29602        let (key, val) = style.property_location(code, 0).unwrap();
29603        assert_eq!(
29604          key,
29605          SourceLocation { line: 11, column: 5 }..SourceLocation { line: 11, column: 10 }
29606        );
29607        assert_eq!(
29608          val,
29609          SourceLocation { line: 11, column: 12 }..SourceLocation { line: 11, column: 17 }
29610        );
29611      }
29612    }
29613
29614    let mut property = Property::Transform(Default::default(), VendorPrefix::WebKit);
29615    property.set_prefix(VendorPrefix::None);
29616    assert_eq!(property, Property::Transform(Default::default(), VendorPrefix::None));
29617    property.set_prefix(VendorPrefix::Moz);
29618    assert_eq!(property, Property::Transform(Default::default(), VendorPrefix::Moz));
29619    property.set_prefix(VendorPrefix::WebKit | VendorPrefix::Moz);
29620    assert_eq!(
29621      property,
29622      Property::Transform(Default::default(), VendorPrefix::WebKit | VendorPrefix::Moz)
29623    );
29624
29625    let mut property = Property::TextDecorationLine(Default::default(), VendorPrefix::None);
29626    property.set_prefix(VendorPrefix::Ms);
29627    assert_eq!(
29628      property,
29629      Property::TextDecorationLine(Default::default(), VendorPrefix::None)
29630    );
29631    property.set_prefix(VendorPrefix::WebKit | VendorPrefix::Moz | VendorPrefix::Ms);
29632    assert_eq!(
29633      property,
29634      Property::TextDecorationLine(Default::default(), VendorPrefix::WebKit | VendorPrefix::Moz)
29635    );
29636
29637    let mut property = Property::AccentColor(Default::default());
29638    property.set_prefix(VendorPrefix::WebKit);
29639    assert_eq!(property, Property::AccentColor(Default::default()));
29640  }
29641
29642  #[cfg(feature = "substitute_variables")]
29643  #[test]
29644  fn test_substitute_vars() {
29645    use crate::properties::custom::TokenList;
29646    use crate::traits::ParseWithOptions;
29647
29648    fn test(property: Property, vars: HashMap<&str, &str>, expected: &str) {
29649      if let Property::Unparsed(unparsed) = property {
29650        let vars = vars
29651          .into_iter()
29652          .map(|(k, v)| {
29653            (
29654              k,
29655              TokenList::parse_string_with_options(v, ParserOptions::default()).unwrap(),
29656            )
29657          })
29658          .collect();
29659        let substituted = unparsed.substitute_variables(&vars).unwrap();
29660        assert_eq!(
29661          substituted.to_css_string(false, PrinterOptions::default()).unwrap(),
29662          expected
29663        );
29664      } else {
29665        panic!("Not an unparsed property");
29666      }
29667    }
29668
29669    let property = Property::parse_string("color".into(), "var(--test)", ParserOptions::default()).unwrap();
29670    test(property, HashMap::from([("--test", "yellow")]), "color: #ff0");
29671
29672    let property =
29673      Property::parse_string("color".into(), "var(--test, var(--foo))", ParserOptions::default()).unwrap();
29674    test(property, HashMap::from([("--foo", "yellow")]), "color: #ff0");
29675    let property = Property::parse_string(
29676      "color".into(),
29677      "var(--test, var(--foo, yellow))",
29678      ParserOptions::default(),
29679    )
29680    .unwrap();
29681    test(property, HashMap::new(), "color: #ff0");
29682
29683    let property =
29684      Property::parse_string("width".into(), "calc(var(--a) + var(--b))", ParserOptions::default()).unwrap();
29685    test(property, HashMap::from([("--a", "2px"), ("--b", "4px")]), "width: 6px");
29686
29687    let property = Property::parse_string("color".into(), "var(--a)", ParserOptions::default()).unwrap();
29688    test(
29689      property,
29690      HashMap::from([("--a", "var(--b)"), ("--b", "yellow")]),
29691      "color: #ff0",
29692    );
29693
29694    let property = Property::parse_string("color".into(), "var(--a)", ParserOptions::default()).unwrap();
29695    test(
29696      property,
29697      HashMap::from([("--a", "var(--b)"), ("--b", "var(--c)"), ("--c", "var(--a)")]),
29698      "color: var(--a)",
29699    );
29700  }
29701
29702  #[test]
29703  fn test_layer() {
29704    minify_test("@layer foo;", "@layer foo;");
29705    minify_test("@layer foo, bar;", "@layer foo,bar;");
29706    minify_test("@layer foo.bar;", "@layer foo.bar;");
29707    minify_test("@layer foo.bar, baz;", "@layer foo.bar,baz;");
29708
29709    minify_test(
29710      r#"
29711      @layer foo {
29712        .bar {
29713          color: red;
29714        }
29715      }
29716    "#,
29717      "@layer foo{.bar{color:red}}",
29718    );
29719    minify_test(
29720      r#"
29721      @layer foo.bar {
29722        .bar {
29723          color: red;
29724        }
29725      }
29726    "#,
29727      "@layer foo.bar{.bar{color:red}}",
29728    );
29729    minify_test(r#"
29730      @layer base {
29731        p { max-width: 70ch; }
29732      }
29733
29734      @layer framework {
29735        @layer base {
29736          p { margin-block: 0.75em; }
29737        }
29738
29739        @layer theme {
29740          p { color: #222; }
29741        }
29742      }
29743    "#, "@layer base{p{max-width:70ch}}@layer framework{@layer base{p{margin-block:.75em}}@layer theme{p{color:#222}}}");
29744    minify_test(
29745      r#"
29746      @layer {
29747        .bar {
29748          color: red;
29749        }
29750      }
29751    "#,
29752      "@layer{.bar{color:red}}",
29753    );
29754    minify_test(
29755      r#"
29756      @layer foo\20 bar, baz;
29757    "#,
29758      "@layer foo\\ bar,baz;",
29759    );
29760    minify_test(
29761      r#"
29762      @layer one.two\20 three\#four\.five {
29763        .bar {
29764          color: red;
29765        }
29766      }
29767    "#,
29768      "@layer one.two\\ three\\#four\\.five{.bar{color:red}}",
29769    );
29770
29771    error_test("@layer;", ParserError::UnexpectedToken(Token::Semicolon));
29772    error_test("@layer foo, bar {};", ParserError::AtRuleBodyInvalid);
29773    minify_test("@import 'test.css' layer;", "@import \"test.css\" layer;");
29774    minify_test("@import 'test.css' layer(foo);", "@import \"test.css\" layer(foo);");
29775    minify_test(
29776      "@import 'test.css' layer(foo.bar);",
29777      "@import \"test.css\" layer(foo.bar);",
29778    );
29779    minify_test(
29780      "@import 'test.css' layer(foo\\20 bar);",
29781      "@import \"test.css\" layer(foo\\ bar);",
29782    );
29783    error_test(
29784      "@import 'test.css' layer(foo, bar) {};",
29785      ParserError::UnexpectedToken(Token::Comma),
29786    );
29787    minify_test(
29788      r#"
29789      @layer one {
29790        body {
29791          background: red;
29792        }
29793      }
29794
29795      body {
29796        background: red;
29797      }
29798
29799      @layer two {
29800        body {
29801          background: green;
29802        }
29803      }
29804
29805      @layer one {
29806        body {
29807          background: yellow;
29808        }
29809      }
29810      "#,
29811      "@layer one{body{background:#ff0}}body{background:red}@layer two{body{background:green}}",
29812    );
29813  }
29814
29815  #[test]
29816  fn test_property() {
29817    minify_test(
29818      r#"
29819      @property --property-name {
29820        syntax: '<color>';
29821        inherits: false;
29822        initial-value: yellow;
29823      }
29824    "#,
29825      "@property --property-name{syntax:\"<color>\";inherits:false;initial-value:#ff0}",
29826    );
29827
29828    test(
29829      r#"
29830      @property --property-name {
29831        syntax: '*';
29832        inherits: false;
29833        initial-value: ;
29834      }
29835    "#,
29836      indoc! {r#"
29837      @property --property-name {
29838        syntax: "*";
29839        inherits: false;
29840        initial-value: ;
29841      }
29842    "#},
29843    );
29844
29845    minify_test(
29846      r#"
29847      @property --property-name {
29848        syntax: '*';
29849        inherits: false;
29850        initial-value: ;
29851      }
29852    "#,
29853      "@property --property-name{syntax:\"*\";inherits:false;initial-value:}",
29854    );
29855
29856    test(
29857      r#"
29858      @property --property-name {
29859        syntax: '*';
29860        inherits: false;
29861        initial-value:;
29862      }
29863    "#,
29864      indoc! {r#"
29865      @property --property-name {
29866        syntax: "*";
29867        inherits: false;
29868        initial-value: ;
29869      }
29870    "#},
29871    );
29872
29873    minify_test(
29874      r#"
29875      @property --property-name {
29876        syntax: '*';
29877        inherits: false;
29878        initial-value:;
29879      }
29880    "#,
29881      "@property --property-name{syntax:\"*\";inherits:false;initial-value:}",
29882    );
29883    minify_test(
29884      r#"
29885      @property --property-name {
29886        syntax: '*';
29887        inherits: false;
29888        initial-value: foo bar;
29889      }
29890    "#,
29891      "@property --property-name{syntax:\"*\";inherits:false;initial-value:foo bar}",
29892    );
29893
29894    minify_test(
29895      r#"
29896      @property --property-name {
29897        syntax: '<length>';
29898        inherits: true;
29899        initial-value: 25px;
29900      }
29901    "#,
29902      "@property --property-name{syntax:\"<length>\";inherits:true;initial-value:25px}",
29903    );
29904
29905    minify_test(
29906      r#"
29907      @property --property-name {
29908        syntax: '<string>';
29909        inherits: true;
29910        initial-value: "hi";
29911      }
29912    "#,
29913      "@property --property-name{syntax:\"<string>\";inherits:true;initial-value:\"hi\"}",
29914    );
29915
29916    error_test(
29917      r#"
29918      @property --property-name {
29919        syntax: '<color>';
29920        inherits: false;
29921        initial-value: 25px;
29922      }
29923    "#,
29924      ParserError::UnexpectedToken(crate::properties::custom::Token::Dimension {
29925        has_sign: false,
29926        value: 25.0,
29927        int_value: Some(25),
29928        unit: "px".into(),
29929      }),
29930    );
29931
29932    error_test(
29933      r#"
29934      @property --property-name {
29935        syntax: '<length>';
29936        inherits: false;
29937        initial-value: var(--some-value);
29938      }
29939    "#,
29940      ParserError::UnexpectedToken(crate::properties::custom::Token::Function("var".into())),
29941    );
29942
29943    error_test(
29944      r#"
29945      @property --property-name {
29946        syntax: '<color>';
29947        inherits: false;
29948      }
29949    "#,
29950      ParserError::AtRuleBodyInvalid,
29951    );
29952
29953    minify_test(
29954      r#"
29955      @property --property-name {
29956        syntax: '*';
29957        inherits: false;
29958      }
29959    "#,
29960      "@property --property-name{syntax:\"*\";inherits:false}",
29961    );
29962
29963    error_test(
29964      r#"
29965      @property --property-name {
29966        syntax: '*';
29967      }
29968    "#,
29969      ParserError::AtRuleBodyInvalid,
29970    );
29971
29972    error_test(
29973      r#"
29974      @property --property-name {
29975        inherits: false;
29976      }
29977    "#,
29978      ParserError::AtRuleBodyInvalid,
29979    );
29980
29981    error_test(
29982      r#"
29983      @property property-name {
29984        syntax: '*';
29985        inherits: false;
29986      }
29987    "#,
29988      ParserError::UnexpectedToken(crate::properties::custom::Token::Ident("property-name".into())),
29989    );
29990
29991    minify_test(
29992      r#"
29993      @property --property-name {
29994        syntax: 'custom | <color>';
29995        inherits: false;
29996        initial-value: yellow;
29997      }
29998    "#,
29999      "@property --property-name{syntax:\"custom|<color>\";inherits:false;initial-value:#ff0}",
30000    );
30001
30002    // TODO: Re-enable with a better solution
30003    //       See: https://github.com/parcel-bundler/lightningcss/issues/288
30004    // minify_test(r#"
30005    //   @property --property-name {
30006    //     syntax: '<transform-list>';
30007    //     inherits: false;
30008    //     initial-value: translate(200px,300px) translate(100px,200px) scale(2);
30009    //   }
30010    // "#, "@property --property-name{syntax:\"<transform-list>\";inherits:false;initial-value:matrix(2,0,0,2,300,500)}");
30011
30012    minify_test(
30013      r#"
30014      @property --property-name {
30015        syntax: '<time>';
30016        inherits: false;
30017        initial-value: 1000ms;
30018      }
30019    "#,
30020      "@property --property-name{syntax:\"<time>\";inherits:false;initial-value:1s}",
30021    );
30022
30023    minify_test(
30024      r#"
30025      @property --property-name {
30026        syntax: '<url>';
30027        inherits: false;
30028        initial-value: url("foo.png");
30029      }
30030    "#,
30031      "@property --property-name{syntax:\"<url>\";inherits:false;initial-value:url(foo.png)}",
30032    );
30033
30034    minify_test(
30035      r#"
30036      @property --property-name {
30037        syntax: '<image>';
30038        inherits: false;
30039        initial-value: linear-gradient(yellow, blue);
30040      }
30041    "#,
30042      "@property --property-name{syntax:\"<image>\";inherits:false;initial-value:linear-gradient(#ff0,#00f)}",
30043    );
30044
30045    minify_test(
30046      r#"
30047      @property --property-name {
30048        initial-value: linear-gradient(yellow, blue);
30049        inherits: false;
30050        syntax: '<image>';
30051      }
30052    "#,
30053      "@property --property-name{syntax:\"<image>\";inherits:false;initial-value:linear-gradient(#ff0,#00f)}",
30054    );
30055
30056    test(
30057      r#"
30058      @property --property-name {
30059        syntax: '<length>|none';
30060        inherits: false;
30061        initial-value: none;
30062      }
30063    "#,
30064      indoc! {r#"
30065      @property --property-name {
30066        syntax: "<length> | none";
30067        inherits: false;
30068        initial-value: none;
30069      }
30070    "#},
30071    );
30072
30073    minify_test(
30074      r#"
30075      @property --property-name {
30076        syntax: '<color>#';
30077        inherits: false;
30078        initial-value: yellow, blue;
30079      }
30080    "#,
30081      "@property --property-name{syntax:\"<color>#\";inherits:false;initial-value:#ff0,#00f}",
30082    );
30083    minify_test(
30084      r#"
30085      @property --property-name {
30086        syntax: '<color>+';
30087        inherits: false;
30088        initial-value: yellow blue;
30089      }
30090    "#,
30091      "@property --property-name{syntax:\"<color>+\";inherits:false;initial-value:#ff0 #00f}",
30092    );
30093    minify_test(
30094      r#"
30095      @property --property-name {
30096        syntax: '<color>';
30097        inherits: false;
30098        initial-value: yellow;
30099      }
30100      .foo {
30101        color: var(--property-name)
30102      }
30103      @property --property-name {
30104        syntax: '<color>';
30105        inherits: true;
30106        initial-value: blue;
30107      }
30108    "#,
30109      "@property --property-name{syntax:\"<color>\";inherits:true;initial-value:#00f}.foo{color:var(--property-name)}",
30110    );
30111
30112    test(
30113      r#"
30114      @media (width < 800px) {
30115        @property --property-name {
30116          syntax: '*';
30117          inherits: false;
30118        }
30119      }
30120    "#,
30121      indoc! {r#"
30122        @media (width < 800px) {
30123          @property --property-name {
30124            syntax: "*";
30125            inherits: false
30126          }
30127        }
30128    "#},
30129    );
30130
30131    test(
30132      r#"
30133      @layer foo {
30134        @property --property-name {
30135          syntax: '*';
30136          inherits: false;
30137        }
30138      }
30139    "#,
30140      indoc! {r#"
30141        @layer foo {
30142          @property --property-name {
30143            syntax: "*";
30144            inherits: false
30145          }
30146        }
30147    "#},
30148    );
30149  }
30150
30151  #[test]
30152  fn test_quoting_unquoting_urls() {
30153    // Quotes remain double quotes when not minifying
30154    test(
30155      r#".foo {
30156      background-image: url("0123abcd");
30157    }"#,
30158      r#".foo {
30159  background-image: url("0123abcd");
30160}
30161"#,
30162    );
30163
30164    // Quotes removed when minifying
30165    minify_test(
30166      r#".foo {
30167      background-image: url("0123abcd");
30168    }"#,
30169      r#".foo{background-image:url(0123abcd)}"#,
30170    );
30171
30172    // Doubles quotes added if not present when not minifying
30173    test(
30174      r#".foo {
30175      background-image: url(0123abcd);
30176    }"#,
30177      r#".foo {
30178  background-image: url("0123abcd");
30179}
30180"#,
30181    );
30182
30183    // No quotes changed if not present when not minifying
30184    minify_test(
30185      r#".foo {
30186      background-image: url(0123abcd);
30187    }"#,
30188      r#".foo{background-image:url(0123abcd)}"#,
30189    );
30190  }
30191
30192  #[test]
30193  fn test_zindex() {
30194    minify_test(".foo { z-index: 2 }", ".foo{z-index:2}");
30195    minify_test(".foo { z-index: -2 }", ".foo{z-index:-2}");
30196    minify_test(".foo { z-index: 999999 }", ".foo{z-index:999999}");
30197    minify_test(".foo { z-index: 9999999 }", ".foo{z-index:9999999}");
30198    minify_test(".foo { z-index: -9999999 }", ".foo{z-index:-9999999}");
30199  }
30200
30201  #[test]
30202  #[cfg(feature = "sourcemap")]
30203  fn test_input_source_map() {
30204    let source = r#".imported {
30205      content: "yay, file support!";
30206    }
30207
30208    .selector {
30209      margin: 1em;
30210      background-color: #f60;
30211    }
30212
30213    .selector .nested {
30214      margin: 0.5em;
30215    }
30216
30217    /*# sourceMappingURL=data:application/json;base64,ewoJInZlcnNpb24iOiAzLAoJInNvdXJjZVJvb3QiOiAicm9vdCIsCgkiZmlsZSI6ICJzdGRvdXQiLAoJInNvdXJjZXMiOiBbCgkJInN0ZGluIiwKCQkic2Fzcy9fdmFyaWFibGVzLnNjc3MiLAoJCSJzYXNzL19kZW1vLnNjc3MiCgldLAoJInNvdXJjZXNDb250ZW50IjogWwoJCSJAaW1wb3J0IFwiX3ZhcmlhYmxlc1wiO1xuQGltcG9ydCBcIl9kZW1vXCI7XG5cbi5zZWxlY3RvciB7XG4gIG1hcmdpbjogJHNpemU7XG4gIGJhY2tncm91bmQtY29sb3I6ICRicmFuZENvbG9yO1xuXG4gIC5uZXN0ZWQge1xuICAgIG1hcmdpbjogJHNpemUgLyAyO1xuICB9XG59IiwKCQkiJGJyYW5kQ29sb3I6ICNmNjA7XG4kc2l6ZTogMWVtOyIsCgkJIi5pbXBvcnRlZCB7XG4gIGNvbnRlbnQ6IFwieWF5LCBmaWxlIHN1cHBvcnQhXCI7XG59IgoJXSwKCSJtYXBwaW5ncyI6ICJBRUFBLFNBQVMsQ0FBQztFQUNSLE9BQU8sRUFBRSxvQkFBcUI7Q0FDL0I7O0FGQ0QsU0FBUyxDQUFDO0VBQ1IsTUFBTSxFQ0hELEdBQUc7RURJUixnQkFBZ0IsRUNMTCxJQUFJO0NEVWhCOztBQVBELFNBQVMsQ0FJUCxPQUFPLENBQUM7RUFDTixNQUFNLEVDUEgsS0FBRztDRFFQIiwKCSJuYW1lcyI6IFtdCn0= */"#;
30218
30219    let mut stylesheet = StyleSheet::parse(&source, ParserOptions::default()).unwrap();
30220    stylesheet.minify(MinifyOptions::default()).unwrap();
30221    let mut sm = parcel_sourcemap::SourceMap::new("/");
30222    stylesheet
30223      .to_css(PrinterOptions {
30224        source_map: Some(&mut sm),
30225        minify: true,
30226        ..PrinterOptions::default()
30227      })
30228      .unwrap();
30229    let map = sm.to_json(None).unwrap();
30230    assert_eq!(
30231      map,
30232      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":[]}"#
30233    );
30234  }
30235
30236  #[test]
30237  #[cfg(feature = "sourcemap")]
30238  fn test_source_maps_with_license_comments() {
30239    let source = r#"/*! a single line comment */
30240    /*!
30241      a comment
30242      containing
30243      multiple
30244      lines
30245    */
30246    .a {
30247      display: flex;
30248    }
30249
30250    .b {
30251      display: hidden;
30252    }
30253    "#;
30254
30255    let mut sm = parcel_sourcemap::SourceMap::new("/");
30256    let source_index = sm.add_source("input.css");
30257    sm.set_source_content(source_index as usize, source).unwrap();
30258
30259    let mut stylesheet = StyleSheet::parse(
30260      &source,
30261      ParserOptions {
30262        source_index,
30263        ..Default::default()
30264      },
30265    )
30266    .unwrap();
30267    stylesheet.minify(MinifyOptions::default()).unwrap();
30268    stylesheet
30269      .to_css(PrinterOptions {
30270        source_map: Some(&mut sm),
30271        minify: true,
30272        ..PrinterOptions::default()
30273      })
30274      .unwrap();
30275    let map = sm.to_json(None).unwrap();
30276    assert_eq!(
30277      map,
30278      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":[]}"#
30279    );
30280  }
30281
30282  #[test]
30283  fn test_error_recovery() {
30284    use std::sync::{Arc, RwLock};
30285    let warnings = Some(Arc::new(RwLock::new(Vec::new())));
30286    test_with_options(
30287      r#"
30288      h1(>h1) {
30289        color: red;
30290      }
30291
30292      .foo {
30293        color: red;
30294      }
30295
30296      .clearfix {
30297        *zoom: 1;
30298        background: red;
30299      }
30300
30301      @media (hover) {
30302        h1(>h1) {
30303          color: red;
30304        }
30305
30306        .bar {
30307          color: red;
30308        }
30309      }
30310
30311      input:placeholder {
30312        color: red;
30313      }
30314
30315      input::hover {
30316        color: red;
30317      }
30318    "#,
30319      indoc! { r#"
30320      .foo {
30321        color: red;
30322      }
30323
30324      .clearfix {
30325        background: red;
30326      }
30327
30328      @media (hover) {
30329        .bar {
30330          color: red;
30331        }
30332      }
30333
30334      input:placeholder {
30335        color: red;
30336      }
30337
30338      input::hover {
30339        color: red;
30340      }
30341    "#},
30342      ParserOptions {
30343        filename: "test.css".into(),
30344        error_recovery: true,
30345        warnings: warnings.clone(),
30346        ..ParserOptions::default()
30347      },
30348    );
30349    let w = warnings.unwrap();
30350    let warnings = w.read().unwrap();
30351    assert_eq!(
30352      *warnings,
30353      vec![
30354        Error {
30355          kind: ParserError::SelectorError(SelectorError::EmptySelector),
30356          loc: Some(ErrorLocation {
30357            filename: "test.css".into(),
30358            line: 1,
30359            column: 7
30360          })
30361        },
30362        Error {
30363          kind: ParserError::UnexpectedToken(Token::Semicolon),
30364          loc: Some(ErrorLocation {
30365            filename: "test.css".into(),
30366            line: 10,
30367            column: 17
30368          })
30369        },
30370        Error {
30371          kind: ParserError::SelectorError(SelectorError::EmptySelector),
30372          loc: Some(ErrorLocation {
30373            filename: "test.css".into(),
30374            line: 15,
30375            column: 9
30376          })
30377        },
30378        Error {
30379          kind: ParserError::SelectorError(SelectorError::UnsupportedPseudoClass("placeholder".into())),
30380          loc: Some(ErrorLocation {
30381            filename: "test.css".into(),
30382            line: 24,
30383            column: 13,
30384          }),
30385        },
30386        Error {
30387          kind: ParserError::SelectorError(SelectorError::UnsupportedPseudoElement("hover".into())),
30388          loc: Some(ErrorLocation {
30389            filename: "test.css".into(),
30390            line: 28,
30391            column: 13,
30392          }),
30393        },
30394      ]
30395    )
30396  }
30397
30398  #[test]
30399  fn test_invalid() {
30400    error_test(
30401      ".a{color: hsla(120, 62.32%;}",
30402      ParserError::UnexpectedToken(Token::CloseCurlyBracket),
30403    );
30404    error_test(
30405      ".a{--foo: url(foo\\) b\\)ar)}",
30406      ParserError::UnexpectedToken(Token::BadUrl("foo\\) b\\)ar".into())),
30407    );
30408  }
30409
30410  #[test]
30411  fn test_container_queries() {
30412    // name only (no condition) - new syntax
30413    minify_test(
30414      r#"
30415      @container foo {
30416        .inner {
30417          background: green;
30418        }
30419      }
30420    "#,
30421      "@container foo{.inner{background:green}}",
30422    );
30423
30424    // with name
30425    minify_test(
30426      r#"
30427      @container my-layout (inline-size > 45em) {
30428        .foo {
30429          color: red;
30430        }
30431      }
30432    "#,
30433      "@container my-layout (inline-size>45em){.foo{color:red}}",
30434    );
30435
30436    minify_test(
30437      r#"
30438      @container my-layout ( not (width > 500px) ) {
30439        .foo {
30440          color: red;
30441        }
30442      }
30443    "#,
30444      "@container my-layout not (width>500px){.foo{color:red}}",
30445    );
30446
30447    minify_test(
30448      r#"
30449      @container my-layout not (width > 500px) {
30450        .foo {
30451          color: red;
30452        }
30453      }
30454    "#,
30455      "@container my-layout not (width>500px){.foo{color:red}}",
30456    );
30457
30458    minify_test(
30459      r#"
30460      @container not (width > 500px) {
30461        .foo {
30462          color: red;
30463        }
30464      }
30465    "#,
30466      "@container not (width>500px){.foo{color:red}}",
30467    );
30468
30469    minify_test(
30470      r#"
30471      @container my-layout ((width: 100px) and (not (height: 100px))) {
30472        .foo {
30473          color: red;
30474        }
30475      }
30476    "#,
30477      "@container my-layout (width:100px) and (not (height:100px)){.foo{color:red}}",
30478    );
30479
30480    minify_test(
30481      r#"
30482      @container my-layout (width = max(10px, 10em)) {
30483        .foo {
30484          color: red;
30485        }
30486      }
30487    "#,
30488      "@container my-layout (width=max(10px,10em)){.foo{color:red}}",
30489    );
30490
30491    // without name
30492    minify_test(
30493      r#"
30494      @container (inline-size > 45em) {
30495        .foo {
30496          color: red;
30497        }
30498      }
30499    "#,
30500      "@container (inline-size>45em){.foo{color:red}}",
30501    );
30502
30503    minify_test(
30504      r#"
30505      @container (inline-size > 45em) and (inline-size < 100em) {
30506        .foo {
30507          color: red;
30508        }
30509      }
30510    "#,
30511      "@container (inline-size>45em) and (inline-size<100em){.foo{color:red}}",
30512    );
30513
30514    // calc()
30515    minify_test(
30516      r#"
30517      @container (width > calc(100vw - 50px)) {
30518        .foo {
30519          color: red;
30520        }
30521      }
30522    "#,
30523      "@container (width>calc(100vw - 50px)){.foo{color:red}}",
30524    );
30525
30526    minify_test(
30527      r#"
30528      @container (calc(100vh - 50px) <= height ) {
30529        .foo {
30530          color: red;
30531        }
30532      }
30533    "#,
30534      "@container (height>=calc(100vh - 50px)){.foo{color:red}}",
30535    );
30536
30537    // merge adjacent
30538    minify_test(
30539      r#"
30540      @container my-layout (inline-size > 45em) {
30541        .foo {
30542          color: red;
30543        }
30544      }
30545
30546      @container my-layout (inline-size > 45em) {
30547        .foo {
30548          background: yellow;
30549        }
30550
30551        .bar {
30552          color: white;
30553        }
30554      }
30555    "#,
30556      "@container my-layout (inline-size>45em){.foo{color:red;background:#ff0}.bar{color:#fff}}",
30557    );
30558
30559    minify_test(
30560      r#"
30561    .foo {
30562      container-name: foo bar;
30563      container-type: size;
30564    }
30565    "#,
30566      ".foo{container:foo bar/size}",
30567    );
30568    minify_test(
30569      r#"
30570    .foo {
30571      container-name: foo bar;
30572      container-type: normal;
30573    }
30574    "#,
30575      ".foo{container:foo bar}",
30576    );
30577    minify_test(
30578      ".foo{ container-type: inline-size }",
30579      ".foo{container-type:inline-size}",
30580    );
30581    minify_test(".foo{ container-name: none; }", ".foo{container-name:none}");
30582    minify_test(".foo{ container-name: foo; }", ".foo{container-name:foo}");
30583    minify_test(".foo{ container: foo / normal; }", ".foo{container:foo}");
30584    minify_test(
30585      ".foo{ container: foo / inline-size; }",
30586      ".foo{container:foo/inline-size}",
30587    );
30588    minify_test(".foo { width: calc(1cqw + 2cqw) }", ".foo{width:3cqw}");
30589    minify_test(".foo { width: calc(1cqh + 2cqh) }", ".foo{width:3cqh}");
30590    minify_test(".foo { width: calc(1cqi + 2cqi) }", ".foo{width:3cqi}");
30591    minify_test(".foo { width: calc(1cqb + 2cqb) }", ".foo{width:3cqb}");
30592    minify_test(".foo { width: calc(1cqmin + 2cqmin) }", ".foo{width:3cqmin}");
30593    minify_test(".foo { width: calc(1cqmax + 2cqmax) }", ".foo{width:3cqmax}");
30594
30595    // Unlike in @media, there is no need to convert the range syntax in @container,
30596    // because browsers all support this syntax.
30597    prefix_test(
30598      r#"
30599      @container (width > 100px) {
30600        .foo { padding: 5px; }
30601      }
30602      "#,
30603      indoc! { r#"
30604        @container (width > 100px) {
30605          .foo {
30606            padding: 5px;
30607          }
30608        }
30609      "#},
30610      Browsers {
30611        chrome: Some(105 << 16),
30612        ..Browsers::default()
30613      },
30614    );
30615    prefix_test(
30616      r#"
30617      @container (min-width: 100px) {
30618        .foo { padding: 5px; }
30619      }
30620      "#,
30621      indoc! { r#"
30622        @container (width >= 100px) {
30623          .foo {
30624            padding: 5px;
30625          }
30626        }
30627      "#},
30628      Browsers {
30629        chrome: Some(105 << 16),
30630        ..Browsers::default()
30631      },
30632    );
30633
30634    minify_test(
30635      r#"
30636      @container style(--responsive: true) {
30637        .foo {
30638          color: red;
30639        }
30640      }
30641    "#,
30642      "@container style(--responsive:true){.foo{color:red}}",
30643    );
30644    minify_test(
30645      r#"
30646      @container style(--responsive: true) and style(color: yellow) {
30647        .foo {
30648          color: red;
30649        }
30650      }
30651    "#,
30652      "@container style(--responsive:true) and style(color:#ff0){.foo{color:red}}",
30653    );
30654    minify_test(
30655      r#"
30656      @container not style(--responsive: true) {
30657        .foo {
30658          color: red;
30659        }
30660      }
30661    "#,
30662      "@container not style(--responsive:true){.foo{color:red}}",
30663    );
30664    minify_test(
30665      r#"
30666      @container (inline-size > 45em) and style(--responsive: true) {
30667        .foo {
30668          color: red;
30669        }
30670      }
30671    "#,
30672      "@container (inline-size>45em) and style(--responsive:true){.foo{color:red}}",
30673    );
30674    minify_test(
30675      r#"
30676      @container style((accent-color: yellow) or (--bar: 10px)) {
30677        .foo {
30678          color: red;
30679        }
30680      }
30681    "#,
30682      "@container style((accent-color:#ff0) or (--bar:10px)){.foo{color:red}}",
30683    );
30684    minify_test(
30685      r#"
30686      @container style(not ((width: calc(10px + 20px)) and ((--bar: url(x))))) {
30687        .foo {
30688          color: red;
30689        }
30690      }
30691    "#,
30692      "@container style(not ((width:30px) and (--bar:url(x)))){.foo{color:red}}",
30693    );
30694    minify_test(
30695      r#"
30696      @container style(color: yellow !important) {
30697        .foo {
30698          color: red;
30699        }
30700      }
30701    "#,
30702      "@container style(color:yellow){.foo{color:red}}",
30703    );
30704    minify_test(
30705      r#"
30706      @container style(--foo:) {
30707        .foo {
30708          color: red;
30709        }
30710      }
30711    "#,
30712      "@container style(--foo:){.foo{color:red}}",
30713    );
30714    minify_test(
30715      r#"
30716      @container style(--foo: ) {
30717        .foo {
30718          color: red;
30719        }
30720      }
30721    "#,
30722      "@container style(--foo:){.foo{color:red}}",
30723    );
30724    minify_test(
30725      r#"
30726      @container style(--my-prop: foo - bar ()) {
30727        .foo {
30728          color: red;
30729        }
30730      }
30731    "#,
30732      "@container style(--my-prop:foo - bar ()){.foo{color:red}}",
30733    );
30734    minify_test(
30735      r#"
30736      @container style(--test) {
30737        .foo {
30738          color: red;
30739        }
30740      }
30741    "#,
30742      "@container style(--test){.foo{color:red}}",
30743    );
30744    minify_test(
30745      r#"
30746      @container style(width) {
30747        .foo {
30748          color: red;
30749        }
30750      }
30751    "#,
30752      "@container style(width){.foo{color:red}}",
30753    );
30754    minify_test(
30755      r#"
30756      @container scroll-state(scrollable: top) {
30757        .foo {
30758          color: red;
30759        }
30760      }
30761    "#,
30762      "@container scroll-state(scrollable:top){.foo{color:red}}",
30763    );
30764    minify_test(
30765      r#"
30766      @container scroll-state((stuck: top) and (stuck: left)) {
30767        .foo {
30768          color: red;
30769        }
30770      }
30771    "#,
30772      "@container scroll-state((stuck:top) and (stuck:left)){.foo{color:red}}",
30773    );
30774    minify_test(
30775      r#"
30776      @container scroll-state(not ((scrollable: bottom) and (scrollable: right))) {
30777        .foo {
30778          color: red;
30779        }
30780      }
30781    "#,
30782      "@container scroll-state(not ((scrollable:bottom) and (scrollable:right))){.foo{color:red}}",
30783    );
30784    minify_test(
30785      r#"
30786      @container (scroll-state(scrollable: inline-end)) {
30787        .foo {
30788          color: red;
30789        }
30790      }
30791    "#,
30792      "@container scroll-state(scrollable:inline-end){.foo{color:red}}",
30793    );
30794    minify_test(
30795      r#"
30796      @container not scroll-state(scrollable: top) {
30797        .foo {
30798          color: red;
30799        }
30800      }
30801    "#,
30802      "@container not scroll-state(scrollable:top){.foo{color:red}}",
30803    );
30804
30805    // Disallow 'none', 'not', 'and', 'or' as a `<container-name>`
30806    // https://github.com/w3c/csswg-drafts/issues/7203#issuecomment-1144257312
30807    // https://chromium-review.googlesource.com/c/chromium/src/+/3698402
30808    error_test(
30809      "@container none (width < 100vw) {}",
30810      ParserError::UnexpectedToken(crate::properties::custom::Token::Ident("none".into())),
30811    );
30812
30813    error_test(
30814      "@container and (width < 100vw) {}",
30815      ParserError::UnexpectedToken(crate::properties::custom::Token::Ident("and".into())),
30816    );
30817
30818    error_test(
30819      "@container or (width < 100vw) {}",
30820      ParserError::UnexpectedToken(crate::properties::custom::Token::Ident("or".into())),
30821    );
30822
30823    // Disallow CSS wide keywords as a `<container-name>`
30824    error_test(
30825      "@container revert-layer (width < 100vw) {}",
30826      ParserError::UnexpectedToken(crate::properties::custom::Token::Ident("revert-layer".into())),
30827    );
30828
30829    error_test(
30830      "@container initial (width < 100vw) {}",
30831      ParserError::UnexpectedToken(crate::properties::custom::Token::Ident("initial".into())),
30832    );
30833
30834    // <ident> contains spaces
30835    // https://github.com/web-platform-tests/wpt/blob/39f0da08fbbe33d0582a35749b6dbf8bd067a52d/css/css-contain/container-queries/at-container-parsing.html#L160-L178
30836    error_test(
30837      "@container foo bar (width < 100vw) {}",
30838      ParserError::UnexpectedToken(crate::properties::custom::Token::Ident("bar".into())),
30839    );
30840
30841    error_test("@container (inline-size <= foo) {}", ParserError::InvalidMediaQuery);
30842    error_test("@container (orientation <= 10px) {}", ParserError::InvalidMediaQuery);
30843
30844    error_test(
30845      "@container style(style(--foo: bar)) {}",
30846      ParserError::UnexpectedToken(crate::properties::custom::Token::Function("style".into())),
30847    );
30848    error_test(
30849      "@container scroll-state(scroll-state(scrollable: top)) {}",
30850      ParserError::InvalidMediaQuery,
30851    );
30852    error_test(
30853      "@container unknown(foo) {}",
30854      ParserError::UnexpectedToken(crate::properties::custom::Token::Function("unknown".into())),
30855    );
30856
30857    // empty container (no name and no condition) should error
30858    error_test("@container {}", ParserError::EndOfInput);
30859
30860    // empty brackets should return a clearer error message
30861    error_test("@container () {}", ParserError::EmptyBracketInCondition);
30862
30863    // invalid condition after a name should error
30864    error_test("@container foo () {}", ParserError::EmptyBracketInCondition);
30865    error_test(
30866      "@container foo bar {}",
30867      ParserError::UnexpectedToken(crate::properties::custom::Token::Ident("bar".into())),
30868    );
30869
30870    error_recovery_test("@container unknown(foo) {}");
30871  }
30872
30873  #[test]
30874  fn test_css_modules_value_rule() {
30875    css_modules_error_test(
30876      "@value compact: (max-width: 37.4375em);",
30877      ParserError::DeprecatedCssModulesValueRule,
30878    );
30879  }
30880
30881  #[test]
30882  fn test_unknown_at_rules() {
30883    minify_test("@foo;", "@foo;");
30884    minify_test("@foo bar;", "@foo bar;");
30885    minify_test("@foo (bar: baz);", "@foo (bar: baz);");
30886    test(
30887      r#"@foo test {
30888      div {
30889        color: red;
30890      }
30891    }"#,
30892      indoc! { r#"@foo test {
30893      div {
30894            color: red;
30895          }
30896    }
30897    "#},
30898    );
30899    minify_test(
30900      r#"@foo test {
30901      div {
30902        color: red;
30903      }
30904    }"#,
30905      "@foo test{div { color: red; }}",
30906    );
30907    minify_test(
30908      r#"@foo test {
30909        foo: bar;
30910      }"#,
30911      "@foo test{foo: bar;}",
30912    );
30913    test(
30914      r#"@foo {
30915        foo: bar;
30916      }"#,
30917      indoc! {r#"
30918      @foo {
30919        foo: bar;
30920      }
30921      "#},
30922    );
30923    minify_test(
30924      r#"@foo {
30925        foo: bar;
30926      }"#,
30927      "@foo{foo: bar;}",
30928    );
30929  }
30930
30931  #[test]
30932  fn test_resolution() {
30933    prefix_test(
30934      r#"
30935      @media (resolution: 1dppx) {
30936        body {
30937          background: red;
30938        }
30939      }
30940      "#,
30941      indoc! { r#"
30942      @media (resolution: 1dppx) {
30943        body {
30944          background: red;
30945        }
30946      }
30947      "#},
30948      Browsers {
30949        chrome: Some(50 << 16),
30950        ..Browsers::default()
30951      },
30952    );
30953
30954    prefix_test(
30955      r#"
30956      @media (resolution: 1dppx) {
30957        body {
30958          background: red;
30959        }
30960      }
30961      "#,
30962      indoc! { r#"
30963      @media (resolution: 1x) {
30964        body {
30965          background: red;
30966        }
30967      }
30968      "#},
30969      Browsers {
30970        chrome: Some(95 << 16),
30971        ..Browsers::default()
30972      },
30973    );
30974  }
30975
30976  #[test]
30977  fn test_environment() {
30978    minify_test(
30979      r#"
30980      @media (max-width: env(--branding-small)) {
30981        body {
30982          padding: env(--branding-padding);
30983        }
30984      }
30985    "#,
30986      "@media (width<=env(--branding-small)){body{padding:env(--branding-padding)}}",
30987    );
30988
30989    minify_test(
30990      r#"
30991      @media (max-width: env(--branding-small 1)) {
30992        body {
30993          padding: env(--branding-padding 2);
30994        }
30995      }
30996    "#,
30997      "@media (width<=env(--branding-small 1)){body{padding:env(--branding-padding 2)}}",
30998    );
30999
31000    minify_test(
31001      r#"
31002      @media (max-width: env(--branding-small 1, 20px)) {
31003        body {
31004          padding: env(--branding-padding 2, 20px);
31005        }
31006      }
31007    "#,
31008      "@media (width<=env(--branding-small 1,20px)){body{padding:env(--branding-padding 2,20px)}}",
31009    );
31010
31011    minify_test(
31012      r#"
31013      @media (max-width: env(safe-area-inset-top)) {
31014        body {
31015          padding: env(safe-area-inset-top);
31016        }
31017      }
31018    "#,
31019      "@media (width<=env(safe-area-inset-top)){body{padding:env(safe-area-inset-top)}}",
31020    );
31021
31022    minify_test(
31023      r#"
31024      @media (max-width: env(unknown)) {
31025        body {
31026          padding: env(unknown);
31027        }
31028      }
31029    "#,
31030      "@media (width<=env(unknown)){body{padding:env(unknown)}}",
31031    );
31032
31033    prefix_test(
31034      r#"
31035      .foo {
31036        color: env(--brand-color, color(display-p3 0 1 0));
31037      }
31038    "#,
31039      indoc! {r#"
31040      .foo {
31041        color: env(--brand-color, #00f942);
31042      }
31043
31044      @supports (color: color(display-p3 0 0 0)) {
31045        .foo {
31046          color: env(--brand-color, color(display-p3 0 1 0));
31047        }
31048      }
31049    "#},
31050      Browsers {
31051        safari: Some(15 << 16),
31052        chrome: Some(90 << 16),
31053        ..Browsers::default()
31054      },
31055    );
31056
31057    prefix_test(
31058      r#"
31059      @supports (color: color(display-p3 0 0 0)) {
31060        .foo {
31061          color: env(--brand-color, color(display-p3 0 1 0));
31062        }
31063      }
31064    "#,
31065      indoc! {r#"
31066      @supports (color: color(display-p3 0 0 0)) {
31067        .foo {
31068          color: env(--brand-color, color(display-p3 0 1 0));
31069        }
31070      }
31071    "#},
31072      Browsers {
31073        safari: Some(15 << 16),
31074        chrome: Some(90 << 16),
31075        ..Browsers::default()
31076      },
31077    );
31078
31079    css_modules_test(
31080      r#"
31081      @media (max-width: env(--branding-small)) {
31082        .foo {
31083          color: env(--brand-color);
31084        }
31085      }
31086    "#,
31087      indoc! {r#"
31088      @media (width <= env(--EgL3uq_branding-small)) {
31089        .EgL3uq_foo {
31090          color: env(--EgL3uq_brand-color);
31091        }
31092      }
31093    "#},
31094      map! {
31095        "foo" => "EgL3uq_foo",
31096        "--brand-color" => "--EgL3uq_brand-color" referenced: true,
31097        "--branding-small" => "--EgL3uq_branding-small" referenced: true
31098      },
31099      HashMap::new(),
31100      crate::css_modules::Config {
31101        dashed_idents: true,
31102        ..Default::default()
31103      },
31104      false,
31105    );
31106  }
31107
31108  #[test]
31109  fn test_license_comments() {
31110    minify_test(
31111      r#"
31112      /*! Copyright 2023 Someone awesome */
31113      /* Some other comment */
31114      .foo {
31115        color: red;
31116      }
31117    "#,
31118      indoc! {r#"
31119      /*! Copyright 2023 Someone awesome */
31120      .foo{color:red}"#},
31121    );
31122
31123    minify_test(
31124      r#"
31125      /*! Copyright 2023 Someone awesome */
31126      /*! Copyright 2023 Someone else */
31127      .foo {
31128        color: red;
31129      }
31130    "#,
31131      indoc! {r#"
31132      /*! Copyright 2023 Someone awesome */
31133      /*! Copyright 2023 Someone else */
31134      .foo{color:red}"#},
31135    );
31136  }
31137
31138  #[test]
31139  fn test_starting_style() {
31140    minify_test(
31141      r#"
31142      @starting-style {
31143        h1 {
31144          background: yellow;
31145        }
31146      }
31147      "#,
31148      "@starting-style{h1{background:#ff0}}",
31149    );
31150    minify_test("@starting-style {}", "");
31151
31152    nesting_test(
31153      r#"
31154      h1 {
31155        background: red;
31156        @starting-style {
31157          background: yellow;
31158        }
31159      }
31160      "#,
31161      indoc! {r#"
31162      h1 {
31163        background: red;
31164      }
31165
31166      @starting-style {
31167        h1 {
31168          background: #ff0;
31169        }
31170      }
31171      "#},
31172    );
31173  }
31174
31175  #[test]
31176  fn test_color_scheme() {
31177    minify_test(".foo { color-scheme: normal; }", ".foo{color-scheme:normal}");
31178    minify_test(".foo { color-scheme: light; }", ".foo{color-scheme:light}");
31179    minify_test(".foo { color-scheme: dark; }", ".foo{color-scheme:dark}");
31180    minify_test(".foo { color-scheme: light dark; }", ".foo{color-scheme:light dark}");
31181    minify_test(".foo { color-scheme: dark light; }", ".foo{color-scheme:light dark}");
31182    minify_test(".foo { color-scheme: only light; }", ".foo{color-scheme:light only}");
31183    minify_test(".foo { color-scheme: only dark; }", ".foo{color-scheme:dark only}");
31184    minify_test(".foo { color-scheme: inherit; }", ".foo{color-scheme:inherit}");
31185    minify_test(":root { color-scheme: unset; }", ":root{color-scheme:unset}");
31186    minify_test(".foo { color-scheme: unknow; }", ".foo{color-scheme:unknow}");
31187    minify_test(".foo { color-scheme: only; }", ".foo{color-scheme:only}");
31188    minify_test(".foo { color-scheme: dark foo; }", ".foo{color-scheme:dark foo}");
31189    minify_test(".foo { color-scheme: normal dark; }", ".foo{color-scheme:normal dark}");
31190    minify_test(
31191      ".foo { color-scheme: dark light only; }",
31192      ".foo{color-scheme:light dark only}",
31193    );
31194    minify_test(
31195      ".foo { color-scheme: foo bar light; }",
31196      ".foo{color-scheme:foo bar light}",
31197    );
31198    minify_test(
31199      ".foo { color-scheme: only foo dark bar; }",
31200      ".foo{color-scheme:only foo dark bar}",
31201    );
31202    prefix_test(
31203      ".foo { color-scheme: dark; }",
31204      indoc! { r#"
31205      .foo {
31206        --lightningcss-light: ;
31207        --lightningcss-dark: initial;
31208        color-scheme: dark;
31209      }
31210      "#},
31211      Browsers {
31212        chrome: Some(90 << 16),
31213        ..Browsers::default()
31214      },
31215    );
31216    prefix_test(
31217      ".foo { color-scheme: light; }",
31218      indoc! { r#"
31219      .foo {
31220        --lightningcss-light: initial;
31221        --lightningcss-dark: ;
31222        color-scheme: light;
31223      }
31224      "#},
31225      Browsers {
31226        chrome: Some(90 << 16),
31227        ..Browsers::default()
31228      },
31229    );
31230    prefix_test(
31231      ".foo { color-scheme: light dark; }",
31232      indoc! { r#"
31233      .foo {
31234        --lightningcss-light: initial;
31235        --lightningcss-dark: ;
31236        color-scheme: light dark;
31237      }
31238
31239      @media (prefers-color-scheme: dark) {
31240        .foo {
31241          --lightningcss-light: ;
31242          --lightningcss-dark: initial;
31243        }
31244      }
31245      "#},
31246      Browsers {
31247        chrome: Some(90 << 16),
31248        ..Browsers::default()
31249      },
31250    );
31251    prefix_test(
31252      ".foo { color-scheme: light dark; }",
31253      indoc! { r#"
31254      .foo {
31255        color-scheme: light dark;
31256      }
31257      "#},
31258      Browsers {
31259        firefox: Some(120 << 16),
31260        ..Browsers::default()
31261      },
31262    );
31263
31264    minify_test(
31265      ".foo { color: light-dark(yellow, red); }",
31266      ".foo{color:light-dark(#ff0,red)}",
31267    );
31268    minify_test(
31269      ".foo { color: light-dark(light-dark(yellow, red), light-dark(yellow, red)); }",
31270      ".foo{color:light-dark(#ff0,red)}",
31271    );
31272    minify_test(
31273      ".foo { color: light-dark(rgb(0, 0, 255), hsl(120deg, 50%, 50%)); }",
31274      ".foo{color:light-dark(#00f,#40bf40)}",
31275    );
31276    prefix_test(
31277      ".foo { color: light-dark(oklch(40% 0.1268735435 34.568626), oklab(59.686% 0.1009 0.1192)); }",
31278      indoc! { r#"
31279      .foo {
31280        color: var(--lightningcss-light, #7e250f) var(--lightningcss-dark, #c65d07);
31281        color: var(--lightningcss-light, lab(29.2661% 38.2437 35.3889)) var(--lightningcss-dark, lab(52.2319% 40.1449 59.9171));
31282      }
31283      "#},
31284      Browsers {
31285        chrome: Some(90 << 16),
31286        ..Browsers::default()
31287      },
31288    );
31289    prefix_test(
31290      ".foo { color: light-dark(oklch(40% 0.1268735435 34.568626), oklab(59.686% 0.1009 0.1192)); }",
31291      indoc! { r#"
31292      .foo {
31293        color: light-dark(oklch(40% .126874 34.5686), oklab(59.686% .1009 .1192));
31294      }
31295      "#},
31296      Browsers {
31297        firefox: Some(120 << 16),
31298        ..Browsers::default()
31299      },
31300    );
31301    prefix_test(
31302      r#"
31303      .foo {
31304        box-shadow:
31305            oklch(100% 0 0deg / 50%) 0 0.63rem 0.94rem -0.19rem,
31306            currentColor 0 0.44rem 0.8rem -0.58rem;
31307      }
31308    "#,
31309      indoc! { r#"
31310      .foo {
31311        box-shadow: 0 .63rem .94rem -.19rem #ffffff80, 0 .44rem .8rem -.58rem;
31312        box-shadow: 0 .63rem .94rem -.19rem lab(100% 0 0 / .5), 0 .44rem .8rem -.58rem;
31313      }
31314      "#},
31315      Browsers {
31316        chrome: Some(95 << 16),
31317        ..Browsers::default()
31318      },
31319    );
31320    prefix_test(
31321      r#"
31322      .foo {
31323        box-shadow:
31324            oklch(100% 0 0deg / 50%) 0 0.63rem 0.94rem -0.19rem,
31325            currentColor 0 0.44rem 0.8rem -0.58rem;
31326      }
31327    "#,
31328      indoc! { r#"
31329      .foo {
31330        box-shadow: 0 .63rem .94rem -.19rem color(display-p3 1 1 1 / .5), 0 .44rem .8rem -.58rem;
31331        box-shadow: 0 .63rem .94rem -.19rem lab(100% 0 0 / .5), 0 .44rem .8rem -.58rem;
31332      }
31333      "#},
31334      Browsers {
31335        safari: Some(14 << 16),
31336        ..Browsers::default()
31337      },
31338    );
31339
31340    prefix_test(
31341      ".foo { color: light-dark(var(--light), var(--dark)); }",
31342      indoc! { r#"
31343      .foo {
31344        color: var(--lightningcss-light, var(--light)) var(--lightningcss-dark, var(--dark));
31345      }
31346      "#},
31347      Browsers {
31348        chrome: Some(90 << 16),
31349        ..Browsers::default()
31350      },
31351    );
31352    prefix_test(
31353      ".foo { color: rgb(from light-dark(yellow, red) r g b / 10%); }",
31354      indoc! { r#"
31355      .foo {
31356        color: var(--lightningcss-light, #ffff001a) var(--lightningcss-dark, #ff00001a);
31357      }
31358      "#},
31359      Browsers {
31360        chrome: Some(90 << 16),
31361        ..Browsers::default()
31362      },
31363    );
31364    prefix_test(
31365      ".foo { color: alpha(from light-dark(yellow, red) / 10%); }",
31366      indoc! { r#"
31367      .foo {
31368        color: var(--lightningcss-light, #ffff001a) var(--lightningcss-dark, #ff00001a);
31369      }
31370      "#},
31371      Browsers {
31372        chrome: Some(90 << 16),
31373        ..Browsers::default()
31374      },
31375    );
31376    prefix_test(
31377      ".foo { color: rgb(from light-dark(yellow, red) r g b / var(--alpha)); }",
31378      indoc! { r#"
31379      .foo {
31380        color: var(--lightningcss-light, rgb(255 255 0 / var(--alpha))) var(--lightningcss-dark, rgb(255 0 0 / var(--alpha)));
31381      }
31382      "#},
31383      Browsers {
31384        chrome: Some(90 << 16),
31385        ..Browsers::default()
31386      },
31387    );
31388    prefix_test(
31389      ".foo { color: color(from light-dark(yellow, red) srgb r g b / 10%); }",
31390      indoc! { r#"
31391      .foo {
31392        color: var(--lightningcss-light, #ffff001a) var(--lightningcss-dark, #ff00001a);
31393        color: var(--lightningcss-light, color(srgb 1 1 0 / .1)) var(--lightningcss-dark, color(srgb 1 0 0 / .1));
31394      }
31395      "#},
31396      Browsers {
31397        chrome: Some(90 << 16),
31398        ..Browsers::default()
31399      },
31400    );
31401    prefix_test(
31402      ".foo { color: color-mix(in srgb, light-dark(yellow, red), light-dark(red, pink)); }",
31403      indoc! { r#"
31404      .foo {
31405        color: var(--lightningcss-light, #ff8000) var(--lightningcss-dark, #ff6066);
31406      }
31407      "#},
31408      Browsers {
31409        chrome: Some(90 << 16),
31410        ..Browsers::default()
31411      },
31412    );
31413    nesting_test_with_targets(
31414      r#"
31415        .foo { color-scheme: light; }
31416        .bar { color: light-dark(red, green); }
31417      "#,
31418      indoc! {r#"
31419        .foo {
31420          color-scheme: light;
31421        }
31422
31423        .bar {
31424          color: light-dark(red, green);
31425        }
31426      "#},
31427      Targets {
31428        browsers: Some(Browsers {
31429          safari: Some(13 << 16),
31430          ..Browsers::default()
31431        }),
31432        include: Features::empty(),
31433        exclude: Features::LightDark,
31434      },
31435    );
31436  }
31437
31438  #[test]
31439  fn test_print_color_adjust() {
31440    prefix_test(
31441      ".foo { print-color-adjust: exact; }",
31442      indoc! { r#"
31443      .foo {
31444        -webkit-print-color-adjust: exact;
31445        print-color-adjust: exact;
31446      }
31447      "#},
31448      Browsers {
31449        chrome: Some(135 << 16),
31450        ..Browsers::default()
31451      },
31452    );
31453    prefix_test(
31454      ".foo { print-color-adjust: exact; }",
31455      indoc! { r#"
31456      .foo {
31457        print-color-adjust: exact;
31458      }
31459      "#},
31460      Browsers {
31461        chrome: Some(137 << 16),
31462        ..Browsers::default()
31463      },
31464    );
31465  }
31466
31467  #[test]
31468  fn test_all() {
31469    minify_test(".foo { all: initial; all: initial }", ".foo{all:initial}");
31470    minify_test(".foo { all: initial; all: revert }", ".foo{all:revert}");
31471    minify_test(".foo { background: red; all: revert-layer }", ".foo{all:revert-layer}");
31472    minify_test(
31473      ".foo { background: red; all: revert-layer; background: green }",
31474      ".foo{all:revert-layer;background:green}",
31475    );
31476    minify_test(
31477      ".foo { --test: red; all: revert-layer }",
31478      ".foo{--test:red;all:revert-layer}",
31479    );
31480    minify_test(
31481      ".foo { unicode-bidi: embed; all: revert-layer }",
31482      ".foo{all:revert-layer;unicode-bidi:embed}",
31483    );
31484    minify_test(
31485      ".foo { direction: rtl; all: revert-layer }",
31486      ".foo{all:revert-layer;direction:rtl}",
31487    );
31488    minify_test(
31489      ".foo { direction: rtl; all: revert-layer; direction: ltr }",
31490      ".foo{all:revert-layer;direction:ltr}",
31491    );
31492    minify_test(".foo { background: var(--foo); all: unset; }", ".foo{all:unset}");
31493    minify_test(
31494      ".foo { all: unset; background: var(--foo); }",
31495      ".foo{all:unset;background:var(--foo)}",
31496    );
31497    minify_test(
31498      ".foo {--bar:currentcolor; --foo:1.1em; all:unset}",
31499      ".foo{--bar:currentcolor;--foo:1.1em;all:unset}",
31500    );
31501  }
31502
31503  #[test]
31504  fn test_view_transition() {
31505    minify_test(
31506      "@view-transition { navigation: auto }",
31507      "@view-transition{navigation:auto}",
31508    );
31509    minify_test(
31510      "@view-transition { navigation: auto; types: none; }",
31511      "@view-transition{navigation:auto;types:none}",
31512    );
31513    minify_test(
31514      "@view-transition { navigation: auto; types: foo bar; }",
31515      "@view-transition{navigation:auto;types:foo bar}",
31516    );
31517    minify_test(
31518      "@layer { @view-transition { navigation: auto; types: foo bar; } }",
31519      "@layer{@view-transition{navigation:auto;types:foo bar}}",
31520    );
31521  }
31522
31523  #[test]
31524  fn test_skip_generating_unnecessary_fallbacks() {
31525    prefix_test(
31526      r#"
31527      @supports (color: lab(0% 0 0)) and (color: color(display-p3 0 0 0)) {
31528        .foo {
31529          color: lab(40% 56.6 39);
31530        }
31531
31532        .bar {
31533          color: color(display-p3 .643308 .192455 .167712);
31534        }
31535      }
31536      "#,
31537      indoc! {r#"
31538      @supports (color: lab(0% 0 0)) and (color: color(display-p3 0 0 0)) {
31539        .foo {
31540          color: lab(40% 56.6 39);
31541        }
31542
31543        .bar {
31544          color: color(display-p3 .643308 .192455 .167712);
31545        }
31546      }
31547      "#},
31548      Browsers {
31549        chrome: Some(4 << 16),
31550        ..Browsers::default()
31551      },
31552    );
31553
31554    prefix_test(
31555      r#"
31556      @supports (color: lab(40% 56.6 39)) {
31557        .foo {
31558          color: lab(40% 56.6 39);
31559        }
31560      }
31561      "#,
31562      indoc! {r#"
31563      @supports (color: lab(40% 56.6 39)) {
31564        .foo {
31565          color: lab(40% 56.6 39);
31566        }
31567      }
31568      "#},
31569      Browsers {
31570        chrome: Some(4 << 16),
31571        ..Browsers::default()
31572      },
31573    );
31574
31575    prefix_test(
31576      r#"
31577      @supports (background-color: lab(40% 56.6 39)) {
31578        .foo {
31579          background-color: lab(40% 56.6 39);
31580        }
31581      }
31582      "#,
31583      indoc! {r#"
31584      @supports (background-color: lab(40% 56.6 39)) {
31585        .foo {
31586          background-color: lab(40% 56.6 39);
31587        }
31588      }
31589      "#},
31590      Browsers {
31591        chrome: Some(4 << 16),
31592        ..Browsers::default()
31593      },
31594    );
31595
31596    prefix_test(
31597      r#"
31598      @supports (color: light-dark(#f00, #00f)) {
31599        .foo {
31600          color: light-dark(#ff0, #0ff);
31601        }
31602      }
31603      "#,
31604      indoc! {r#"
31605      @supports (color: light-dark(#f00, #00f)) {
31606        .foo {
31607          color: light-dark(#ff0, #0ff);
31608        }
31609      }
31610      "#},
31611      Browsers {
31612        chrome: Some(4 << 16),
31613        ..Browsers::default()
31614      },
31615    );
31616
31617    // NOTE: fallback for lab is not necessary
31618    prefix_test(
31619      r#"
31620      @supports (color: lab(0% 0 0)) and (not (color: color(display-p3 0 0 0))) {
31621        .foo {
31622          color: lab(40% 56.6 39);
31623        }
31624
31625        .bar {
31626          color: color(display-p3 .643308 .192455 .167712);
31627        }
31628      }
31629      "#,
31630      indoc! {r#"
31631      @supports (color: lab(0% 0 0)) and (not (color: color(display-p3 0 0 0))) {
31632        .foo {
31633          color: #b32323;
31634          color: lab(40% 56.6 39);
31635        }
31636
31637        .bar {
31638          color: #b32323;
31639          color: color(display-p3 .643308 .192455 .167712);
31640        }
31641      }
31642      "#},
31643      Browsers {
31644        chrome: Some(4 << 16),
31645        ..Browsers::default()
31646      },
31647    );
31648
31649    prefix_test(
31650      r#"
31651      @supports (color: lab(0% 0 0)) or (color: color(display-p3 0 0 0)) {
31652        .foo {
31653          color: lab(40% 56.6 39);
31654        }
31655
31656        .bar {
31657          color: color(display-p3 .643308 .192455 .167712);
31658        }
31659      }
31660      "#,
31661      indoc! {r#"
31662      @supports (color: lab(0% 0 0)) or (color: color(display-p3 0 0 0)) {
31663        .foo {
31664          color: #b32323;
31665          color: lab(40% 56.6 39);
31666        }
31667
31668        .bar {
31669          color: #b32323;
31670          color: color(display-p3 .643308 .192455 .167712);
31671        }
31672      }
31673      "#},
31674      Browsers {
31675        chrome: Some(4 << 16),
31676        ..Browsers::default()
31677      },
31678    );
31679  }
31680}