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#![deny(missing_docs)]
18#![cfg_attr(docsrs, feature(doc_cfg))]
19
20#[cfg(feature = "bundler")]
21#[cfg_attr(docsrs, doc(cfg(feature = "bundler")))]
22pub mod bundler;
23mod compat;
24mod context;
25pub mod css_modules;
26pub mod declaration;
27pub mod dependencies;
28pub mod error;
29mod logical;
30mod macros;
31pub mod media_query;
32mod parser;
33mod prefixes;
34pub mod printer;
35pub mod properties;
36pub mod rules;
37pub mod selector;
38pub mod stylesheet;
39pub mod targets;
40pub mod traits;
41pub mod values;
42pub mod vendor_prefix;
43#[cfg(feature = "visitor")]
44#[cfg_attr(docsrs, doc(cfg(feature = "visitor")))]
45pub mod visitor;
46
47#[cfg(feature = "serde")]
48mod serialization;
49
50#[cfg(test)]
51mod test_helpers;
52
53#[cfg(test)]
54mod tests {
55  use crate::css_modules::{CssModuleExport, CssModuleExports, CssModuleReference, CssModuleReferences};
56  use crate::dependencies::Dependency;
57  use crate::error::{Error, ErrorLocation, MinifyErrorKind, ParserError, PrinterErrorKind, SelectorError};
58  use crate::parser::ParserFlags;
59  use crate::properties::custom::Token;
60  use crate::properties::Property;
61  use crate::rules::CssRule;
62  use crate::rules::Location;
63  use crate::stylesheet::*;
64  use crate::test_helpers::panic_with_test_error;
65  use crate::targets::{Browsers, Features, Targets};
66  use crate::traits::{Parse, ToCss};
67  use crate::values::color::CssColor;
68  use crate::vendor_prefix::VendorPrefix;
69  use cssparser::SourceLocation;
70  use indoc::indoc;
71  use pretty_assertions::assert_eq;
72  use std::collections::HashMap;
73  use std::sync::{Arc, RwLock};
74
75  #[track_caller]
76  fn test(source: &str, expected: &str) {
77    test_with_options(source, expected, ParserOptions::default())
78  }
79
80  #[track_caller]
81  fn test_with_options<'i, 'o>(source: &'i str, expected: &'i str, options: ParserOptions<'o, 'i>) {
82    let mut stylesheet = match StyleSheet::parse(&source, options) {
83      Ok(stylesheet) => stylesheet,
84      Err(e) => panic_with_test_error("test_with_options", "parse", source, e),
85    };
86    if let Err(e) = stylesheet.minify(MinifyOptions::default()) {
87      panic_with_test_error("test_with_options", "minify", source, e);
88    }
89    let res = match stylesheet.to_css(PrinterOptions::default()) {
90      Ok(res) => res,
91      Err(e) => panic_with_test_error("test_with_options", "print", source, e),
92    };
93    assert_eq!(res.code, expected);
94  }
95
96  #[track_caller]
97  fn test_with_printer_options<'i, 'o>(source: &'i str, expected: &'i str, options: PrinterOptions<'o>) {
98    let mut stylesheet = match StyleSheet::parse(&source, ParserOptions::default()) {
99      Ok(stylesheet) => stylesheet,
100      Err(e) => panic_with_test_error("test_with_printer_options", "parse", source, e),
101    };
102    if let Err(e) = stylesheet.minify(MinifyOptions::default()) {
103      panic_with_test_error("test_with_printer_options", "minify", source, e);
104    }
105    let res = match stylesheet.to_css(options) {
106      Ok(res) => res,
107      Err(e) => panic_with_test_error("test_with_printer_options", "print", source, e),
108    };
109    assert_eq!(res.code, expected);
110  }
111
112  #[track_caller]
113  fn minify_test(source: &str, expected: &str) {
114    minify_test_with_options(source, expected, ParserOptions::default())
115  }
116
117  #[track_caller]
118  fn minify_test_with_options<'i, 'o>(source: &'i str, expected: &'i str, options: ParserOptions<'o, 'i>) {
119    let mut stylesheet = match StyleSheet::parse(&source, options) {
120      Ok(stylesheet) => stylesheet,
121      Err(e) => panic_with_test_error("minify_test_with_options", "parse", source, e),
122    };
123    if let Err(e) = stylesheet.minify(MinifyOptions::default()) {
124      panic_with_test_error("minify_test_with_options", "minify", source, e);
125    }
126    let res = match stylesheet.to_css(PrinterOptions {
127      minify: true,
128      ..PrinterOptions::default()
129    }) {
130      Ok(res) => res,
131      Err(e) => panic_with_test_error("minify_test_with_options", "print", source, e),
132    };
133    assert_eq!(res.code, expected);
134  }
135
136  #[track_caller]
137  fn minify_error_test_with_options<'i, 'o>(
138    source: &'i str,
139    error: MinifyErrorKind,
140    options: ParserOptions<'o, 'i>,
141  ) {
142    let mut stylesheet = match StyleSheet::parse(&source, options) {
143      Ok(stylesheet) => stylesheet,
144      Err(e) => panic_with_test_error("minify_error_test_with_options", "parse", source, e),
145    };
146    match stylesheet.minify(MinifyOptions::default()) {
147      Err(e) => assert_eq!(e.kind, error),
148      Ok(()) => panic!(
149        "minify_error_test_with_options: expected minify error {:?}, but minification succeeded.\nsource:\n{source}",
150        error
151      ),
152    }
153  }
154
155  #[track_caller]
156  fn prefix_test(source: &str, expected: &str, targets: Browsers) {
157    let mut stylesheet = match StyleSheet::parse(&source, ParserOptions::default()) {
158      Ok(stylesheet) => stylesheet,
159      Err(e) => panic_with_test_error("prefix_test", "parse", source, e),
160    };
161    if let Err(e) = stylesheet.minify(MinifyOptions {
162      targets: targets.into(),
163      ..MinifyOptions::default()
164    }) {
165      panic_with_test_error("prefix_test", "minify", source, e);
166    }
167    let res = match stylesheet.to_css(PrinterOptions {
168      targets: targets.into(),
169      ..PrinterOptions::default()
170    }) {
171      Ok(res) => res,
172      Err(e) => panic_with_test_error("prefix_test", "print", source, e),
173    };
174    assert_eq!(res.code, expected);
175  }
176
177  #[track_caller]
178  fn attr_test(source: &str, expected: &str, minify: bool, targets: Option<Browsers>) {
179    let mut attr = match StyleAttribute::parse(source, ParserOptions::default()) {
180      Ok(attr) => attr,
181      Err(e) => panic_with_test_error("attr_test", "parse", source, e),
182    };
183    attr.minify(MinifyOptions {
184      targets: targets.into(),
185      ..MinifyOptions::default()
186    });
187    let res = match attr.to_css(PrinterOptions {
188      targets: targets.into(),
189      minify,
190      ..PrinterOptions::default()
191    }) {
192      Ok(res) => res,
193      Err(e) => panic_with_test_error("attr_test", "print", source, e),
194    };
195    assert_eq!(res.code, expected);
196  }
197
198  #[track_caller]
199  fn nesting_test(source: &str, expected: &str) {
200    nesting_test_with_targets(
201      source,
202      expected,
203      Browsers {
204        chrome: Some(95 << 16),
205        ..Browsers::default()
206      }
207      .into(),
208    );
209  }
210
211  #[track_caller]
212  fn nesting_test_with_targets(source: &str, expected: &str, targets: Targets) {
213    let mut stylesheet = match StyleSheet::parse(&source, ParserOptions::default()) {
214      Ok(stylesheet) => stylesheet,
215      Err(e) => panic_with_test_error("nesting_test_with_targets", "parse", source, e),
216    };
217    if let Err(e) = stylesheet.minify(MinifyOptions {
218      targets,
219      ..MinifyOptions::default()
220    }) {
221      panic_with_test_error("nesting_test_with_targets", "minify", source, e);
222    }
223    let res = match stylesheet.to_css(PrinterOptions {
224      targets,
225      ..PrinterOptions::default()
226    }) {
227      Ok(res) => res,
228      Err(e) => panic_with_test_error("nesting_test_with_targets", "print", source, e),
229    };
230    assert_eq!(res.code, expected);
231  }
232
233  #[track_caller]
234  fn nesting_test_no_targets(source: &str, expected: &str) {
235    let mut stylesheet = match StyleSheet::parse(&source, ParserOptions::default()) {
236      Ok(stylesheet) => stylesheet,
237      Err(e) => panic_with_test_error("nesting_test_no_targets", "parse", source, e),
238    };
239    if let Err(e) = stylesheet.minify(MinifyOptions::default()) {
240      panic_with_test_error("nesting_test_no_targets", "minify", source, e);
241    }
242    let res = match stylesheet.to_css(PrinterOptions::default()) {
243      Ok(res) => res,
244      Err(e) => panic_with_test_error("nesting_test_no_targets", "print", source, e),
245    };
246    assert_eq!(res.code, expected);
247  }
248
249  #[track_caller]
250  fn css_modules_test<'i>(
251    source: &'i str,
252    expected: &str,
253    expected_exports: CssModuleExports,
254    expected_references: CssModuleReferences,
255    config: crate::css_modules::Config<'i>,
256    minify: bool,
257  ) {
258    let mut stylesheet = match StyleSheet::parse(
259      &source,
260      ParserOptions {
261        filename: "test.css".into(),
262        css_modules: Some(config),
263        ..ParserOptions::default()
264      },
265    ) {
266      Ok(stylesheet) => stylesheet,
267      Err(e) => panic_with_test_error("css_modules_test", "parse", source, e),
268    };
269    if let Err(e) = stylesheet.minify(MinifyOptions::default()) {
270      panic_with_test_error("css_modules_test", "minify", source, e);
271    }
272    let res = match stylesheet.to_css(PrinterOptions {
273      minify,
274      ..Default::default()
275    }) {
276      Ok(res) => res,
277      Err(e) => panic_with_test_error("css_modules_test", "print", source, e),
278    };
279    assert_eq!(res.code, expected);
280    match res.exports {
281      Some(exports) => assert_eq!(exports, expected_exports),
282      None => panic!("css_modules_test: expected CSS module exports, but got None.\nsource:\n{source}"),
283    }
284    match res.references {
285      Some(references) => assert_eq!(references, expected_references),
286      None => panic!("css_modules_test: expected CSS module references, but got None.\nsource:\n{source}"),
287    }
288  }
289
290  #[track_caller]
291  fn custom_media_test(source: &str, expected: &str) {
292    let mut stylesheet = match StyleSheet::parse(
293      &source,
294      ParserOptions {
295        flags: ParserFlags::CUSTOM_MEDIA,
296        ..ParserOptions::default()
297      },
298    ) {
299      Ok(stylesheet) => stylesheet,
300      Err(e) => panic_with_test_error("custom_media_test", "parse", source, e),
301    };
302    if let Err(e) = stylesheet.minify(MinifyOptions {
303      targets: Browsers {
304        chrome: Some(95 << 16),
305        ..Browsers::default()
306      }
307      .into(),
308      ..MinifyOptions::default()
309    }) {
310      panic_with_test_error("custom_media_test", "minify", source, e);
311    }
312    let res = match stylesheet.to_css(PrinterOptions::default()) {
313      Ok(res) => res,
314      Err(e) => panic_with_test_error("custom_media_test", "print", source, e),
315    };
316    assert_eq!(res.code, expected);
317  }
318
319  fn error_test(source: &str, error: ParserError) {
320    let res = StyleSheet::parse(&source, ParserOptions::default());
321    match res {
322      Ok(_) => unreachable!(),
323      Err(e) => assert_eq!(e.kind, error),
324    }
325  }
326
327  fn error_recovery_test(source: &str) -> Vec<Error<ParserError<'_>>> {
328    let warnings = Arc::new(RwLock::default());
329    {
330      let res = StyleSheet::parse(
331        &source,
332        ParserOptions {
333          error_recovery: true,
334          warnings: Some(warnings.clone()),
335          ..Default::default()
336        },
337      );
338      match res {
339        Ok(..) => {}
340        Err(e) => unreachable!("parser error should be recovered, but got {e:?}"),
341      }
342    }
343    let warnings = match Arc::into_inner(warnings) {
344      Some(warnings) => warnings,
345      None => panic!("error_recovery_test: expected a single Arc owner for warnings"),
346    };
347    match warnings.into_inner() {
348      Ok(warnings) => warnings,
349      Err(e) => panic!("error_recovery_test: warnings lock is poisoned: {e}"),
350    }
351  }
352
353  fn css_modules_error_test(source: &str, error: ParserError) {
354    let res = StyleSheet::parse(
355      &source,
356      ParserOptions {
357        css_modules: Some(Default::default()),
358        ..Default::default()
359      },
360    );
361    match res {
362      Ok(_) => unreachable!(),
363      Err(e) => assert_eq!(e.kind, error),
364    }
365  }
366
367  macro_rules! map(
368    { $($key:expr => $name:literal $(referenced: $referenced: literal)? $($value:literal $(global: $global: literal)? $(from $from:literal)?)*),* } => {
369      {
370        #[allow(unused_mut)]
371        let mut m = HashMap::new();
372        $(
373          #[allow(unused_mut)]
374          let mut v = Vec::new();
375          #[allow(unused_macros)]
376          macro_rules! insert {
377            ($local:literal from $specifier:literal) => {
378              v.push(CssModuleReference::Dependency {
379                name: $local.into(),
380                specifier: $specifier.into()
381              });
382            };
383            ($local:literal global: $is_global: literal) => {
384              v.push(CssModuleReference::Global {
385                name: $local.into()
386              });
387            };
388            ($local:literal) => {
389              v.push(CssModuleReference::Local {
390                name: $local.into()
391              });
392            };
393          }
394          $(
395            insert!($value $(global: $global)? $(from $from)?);
396          )*
397
398          macro_rules! is_referenced {
399            ($ref: literal) => {
400              $ref
401            };
402            () => {
403              false
404            };
405          }
406
407          m.insert($key.into(), CssModuleExport {
408            name: $name.into(),
409            composes: v,
410            is_referenced: is_referenced!($($referenced)?)
411          });
412        )*
413        m
414      }
415    };
416  );
417
418  #[test]
419  pub fn test_border_spacing() {
420    minify_test(
421      r#"
422      .foo {
423        border-spacing: 0px;
424      }
425    "#,
426      indoc! {".foo{border-spacing:0}"
427      },
428    );
429    minify_test(
430      r#"
431      .foo {
432        border-spacing: 0px 0px;
433      }
434    "#,
435      indoc! {".foo{border-spacing:0}"
436      },
437    );
438
439    minify_test(
440      r#"
441      .foo {
442        border-spacing: 12px   0px;
443      }
444    "#,
445      indoc! {".foo{border-spacing:12px 0}"
446      },
447    );
448
449    minify_test(
450      r#"
451      .foo {
452        border-spacing: calc(3px * 2) calc(5px * 0);
453      }
454    "#,
455      indoc! {".foo{border-spacing:6px 0}"
456      },
457    );
458
459    minify_test(
460      r#"
461      .foo {
462        border-spacing: calc(3px * 2) max(0px, 8px);
463      }
464    "#,
465      indoc! {".foo{border-spacing:6px 8px}"
466      },
467    );
468
469    // TODO: The `<length>` in border-spacing cannot have a negative value,
470    // we may need to implement NonNegativeLength like Servo does.
471    // Servo Code: https://github.com/servo/servo/blob/08bc2d53579c9ab85415d4363888881b91df073b/components/style/values/specified/length.rs#L875
472    // CSSWG issue: https://lists.w3.org/Archives/Public/www-style/2008Sep/0161.html
473    // `border-spacing = <length> <length>?`
474    minify_test(
475      r#"
476      .foo {
477        border-spacing: -20px;
478      }
479    "#,
480      indoc! {".foo{border-spacing:-20px}"
481      },
482    );
483  }
484
485  #[test]
486  pub fn test_math_fn() {
487    // max()
488    minify_test(
489      r#"
490      .foo {
491        color: rgb(max(255, 100), 0, 0);
492      }
493    "#,
494      indoc! {".foo{color:red}"
495      },
496    );
497    // min()
498    minify_test(
499      r#"
500      .foo {
501        color: rgb(min(255, 500), 0, 0);
502      }
503    "#,
504      indoc! {".foo{color:red}"
505      },
506    );
507    // abs()
508    minify_test(
509      r#"
510      .foo {
511        color: rgb(abs(-255), 0, 0);
512      }
513    "#,
514      indoc! {".foo{color:red}"
515      },
516    );
517    // clamp()
518    minify_test(
519      r#"
520      .foo {
521        flex: clamp(1, 5.20, 20);
522        color: rgb(clamp(0, 255, 300), 0, 0);
523      }
524    "#,
525      indoc! {".foo{color:red;flex:5.2}"
526      },
527    );
528    // round()
529    minify_test(
530      r#"
531      .round-color {
532        color: rgb(round(down, 255.6, 1), 0, 0);
533      }
534    "#,
535      indoc! {".round-color{color:red}"
536      },
537    );
538    // hypot()
539    minify_test(
540      r#"
541      .hypot-color {
542        color: rgb(hypot(255, 0), 0, 0);
543      }
544    "#,
545      indoc! {".hypot-color{color:red}"
546      },
547    );
548    // sign(), sign(50) = 1
549    minify_test(
550      r#"
551      .sign-color {
552        color: rgb(sign(50), 0, 0);
553      }
554    "#,
555      indoc! {".sign-color{color:#010000}"
556      },
557    );
558    // rem(), rem(21, 2) = 1
559    minify_test(
560      r#"
561      .rem-color {
562        color: rgb(rem(21, 2), 0, 0);
563      }
564    "#,
565      indoc! {".rem-color{color:#010000}"
566      },
567    );
568    // max() in width
569    minify_test(
570      r#"
571      .foo {
572        width: max(200px,   5px);
573      }
574    "#,
575      indoc! {".foo{width:200px}"
576      },
577    );
578    // max() in opacity
579    minify_test(
580      r#"
581      .foo {
582        opacity: max(1, 0.2);
583        filter: invert(min(1, 0.5));
584      }
585    "#,
586      indoc! {".foo{opacity:1;filter:invert(.5)}"
587      },
588    );
589    // TODO: support calc in Integer
590    // minify_test(
591    //   r#"
592    //   .foo {
593    //     z-index: max(100,    20);
594    //   }
595    // "#,
596    //   indoc! {".foo{z-index:100}"
597    //   },
598    // );
599  }
600
601  #[test]
602  pub fn test_border() {
603    test(
604      r#"
605      .foo {
606        border-left: 2px solid red;
607        border-right: 2px solid red;
608        border-bottom: 2px solid red;
609        border-top: 2px solid red;
610      }
611    "#,
612      indoc! {r#"
613      .foo {
614        border: 2px solid red;
615      }
616    "#
617      },
618    );
619
620    test(
621      r#"
622      .foo {
623        border-left-color: red;
624        border-right-color: red;
625        border-bottom-color: red;
626        border-top-color: red;
627      }
628    "#,
629      indoc! {r#"
630      .foo {
631        border-color: red;
632      }
633    "#
634      },
635    );
636
637    test(
638      r#"
639      .foo {
640        border-left-width: thin;
641        border-right-width: thin;
642        border-bottom-width: thin;
643        border-top-width: thin;
644      }
645    "#,
646      indoc! {r#"
647      .foo {
648        border-width: thin;
649      }
650    "#
651      },
652    );
653
654    test(
655      r#"
656      .foo {
657        border-left-style: dotted;
658        border-right-style: dotted;
659        border-bottom-style: dotted;
660        border-top-style: dotted;
661      }
662    "#,
663      indoc! {r#"
664      .foo {
665        border-style: dotted;
666      }
667    "#
668      },
669    );
670
671    test(
672      r#"
673      .foo {
674        border-left-width: thin;
675        border-left-style: dotted;
676        border-left-color: red;
677      }
678    "#,
679      indoc! {r#"
680      .foo {
681        border-left: thin dotted red;
682      }
683    "#
684      },
685    );
686
687    test(
688      r#"
689      .foo {
690        border-left-width: thick;
691        border-left: thin dotted red;
692      }
693    "#,
694      indoc! {r#"
695      .foo {
696        border-left: thin dotted red;
697      }
698    "#
699      },
700    );
701
702    test(
703      r#"
704      .foo {
705        border-left-width: thick;
706        border: thin dotted red;
707      }
708    "#,
709      indoc! {r#"
710      .foo {
711        border: thin dotted red;
712      }
713    "#
714      },
715    );
716
717    test(
718      r#"
719      .foo {
720        border: thin dotted red;
721        border-right-width: thick;
722      }
723    "#,
724      indoc! {r#"
725      .foo {
726        border: thin dotted red;
727        border-right-width: thick;
728      }
729    "#
730      },
731    );
732
733    test(
734      r#"
735      .foo {
736        border: thin dotted red;
737        border-right: thick dotted red;
738      }
739    "#,
740      indoc! {r#"
741      .foo {
742        border: thin dotted red;
743        border-right-width: thick;
744      }
745    "#
746      },
747    );
748
749    test(
750      r#"
751      .foo {
752        border: thin dotted red;
753        border-right-width: thick;
754        border-right-style: solid;
755      }
756    "#,
757      indoc! {r#"
758      .foo {
759        border: thin dotted red;
760        border-right: thick solid red;
761      }
762    "#
763      },
764    );
765
766    test(
767      r#"
768      .foo {
769        border-top: thin dotted red;
770        border-block-start: thick solid green;
771      }
772    "#,
773      indoc! {r#"
774      .foo {
775        border-top: thin dotted red;
776        border-block-start: thick solid green;
777      }
778    "#
779      },
780    );
781
782    test(
783      r#"
784      .foo {
785        border: thin dotted red;
786        border-block-start-width: thick;
787        border-left-width: medium;
788      }
789    "#,
790      indoc! {r#"
791      .foo {
792        border: thin dotted red;
793        border-block-start-width: thick;
794        border-left-width: medium;
795      }
796    "#
797      },
798    );
799
800    test(
801      r#"
802      .foo {
803        border-block-start: thin dotted red;
804        border-inline-end: thin dotted red;
805      }
806    "#,
807      indoc! {r#"
808      .foo {
809        border-block-start: thin dotted red;
810        border-inline-end: thin dotted red;
811      }
812    "#
813      },
814    );
815
816    test(
817      r#"
818      .foo {
819        border-block-start-width: thin;
820        border-block-start-style: dotted;
821        border-block-start-color: red;
822        border-inline-end: thin dotted red;
823      }
824    "#,
825      indoc! {r#"
826      .foo {
827        border-block-start: thin dotted red;
828        border-inline-end: thin dotted red;
829      }
830    "#
831      },
832    );
833
834    test(
835      r#"
836      .foo {
837        border-block-start: thin dotted red;
838        border-block-end: thin dotted red;
839      }
840    "#,
841      indoc! {r#"
842      .foo {
843        border-block: thin dotted red;
844      }
845    "#
846      },
847    );
848
849    minify_test(
850      r#"
851      .foo {
852        border: none;
853      }
854    "#,
855      indoc! {".foo{border:none}"
856      },
857    );
858
859    minify_test(".foo { border-width: 0 0 1px; }", ".foo{border-width:0 0 1px}");
860    test(
861      r#"
862      .foo {
863        border-block-width: 1px;
864        border-inline-width: 1px;
865      }
866    "#,
867      indoc! {r#"
868      .foo {
869        border-width: 1px;
870      }
871    "#
872      },
873    );
874    test(
875      r#"
876      .foo {
877        border-block-start-width: 1px;
878        border-block-end-width: 1px;
879        border-inline-start-width: 1px;
880        border-inline-end-width: 1px;
881      }
882    "#,
883      indoc! {r#"
884      .foo {
885        border-width: 1px;
886      }
887    "#
888      },
889    );
890    test(
891      r#"
892      .foo {
893        border-block-start-width: 1px;
894        border-block-end-width: 1px;
895        border-inline-start-width: 2px;
896        border-inline-end-width: 2px;
897      }
898    "#,
899      indoc! {r#"
900      .foo {
901        border-block-width: 1px;
902        border-inline-width: 2px;
903      }
904    "#
905      },
906    );
907    test(
908      r#"
909      .foo {
910        border-block-start-width: 1px;
911        border-block-end-width: 1px;
912        border-inline-start-width: 2px;
913        border-inline-end-width: 3px;
914      }
915    "#,
916      indoc! {r#"
917      .foo {
918        border-block-width: 1px;
919        border-inline-width: 2px 3px;
920      }
921    "#
922      },
923    );
924
925    minify_test(
926      ".foo { border-bottom: 1px solid var(--spectrum-global-color-gray-200)}",
927      ".foo{border-bottom:1px solid var(--spectrum-global-color-gray-200)}",
928    );
929    test(
930      r#"
931      .foo {
932        border-width: 0;
933        border-bottom: var(--test, 1px) solid;
934      }
935    "#,
936      indoc! {r#"
937      .foo {
938        border-width: 0;
939        border-bottom: var(--test, 1px) solid;
940      }
941    "#
942      },
943    );
944
945    test(
946      r#"
947      .foo {
948        border: 1px solid black;
949        border-width: 1px 1px 0 0;
950      }
951    "#,
952      indoc! {r#"
953      .foo {
954        border: 1px solid #000;
955        border-width: 1px 1px 0 0;
956      }
957    "#},
958    );
959
960    test(
961      r#"
962      .foo {
963        border-top: 1px solid black;
964        border-bottom: 1px solid black;
965        border-left: 2px solid black;
966        border-right: 2px solid black;
967      }
968    "#,
969      indoc! {r#"
970      .foo {
971        border: 1px solid #000;
972        border-width: 1px 2px;
973      }
974    "#},
975    );
976
977    test(
978      r#"
979      .foo {
980        border-top: 1px solid black;
981        border-bottom: 1px solid black;
982        border-left: 2px solid black;
983        border-right: 1px solid black;
984      }
985    "#,
986      indoc! {r#"
987      .foo {
988        border: 1px solid #000;
989        border-left-width: 2px;
990      }
991    "#},
992    );
993
994    test(
995      r#"
996      .foo {
997        border-top: 1px solid black;
998        border-bottom: 1px solid black;
999        border-left: 1px solid red;
1000        border-right: 1px solid red;
1001      }
1002    "#,
1003      indoc! {r#"
1004      .foo {
1005        border: 1px solid #000;
1006        border-color: #000 red;
1007      }
1008    "#},
1009    );
1010
1011    test(
1012      r#"
1013      .foo {
1014        border-block-start: 1px solid black;
1015        border-block-end: 1px solid black;
1016        border-inline-start: 1px solid red;
1017        border-inline-end: 1px solid red;
1018      }
1019    "#,
1020      indoc! {r#"
1021      .foo {
1022        border: 1px solid #000;
1023        border-inline-color: red;
1024      }
1025    "#},
1026    );
1027
1028    test(
1029      r#"
1030      .foo {
1031        border-block-start: 1px solid black;
1032        border-block-end: 1px solid black;
1033        border-inline-start: 2px solid black;
1034        border-inline-end: 2px solid black;
1035      }
1036    "#,
1037      indoc! {r#"
1038      .foo {
1039        border: 1px solid #000;
1040        border-inline-width: 2px;
1041      }
1042    "#},
1043    );
1044
1045    test(
1046      r#"
1047      .foo {
1048        border-block-start: 1px solid black;
1049        border-block-end: 1px solid black;
1050        border-inline-start: 2px solid red;
1051        border-inline-end: 2px solid red;
1052      }
1053    "#,
1054      indoc! {r#"
1055      .foo {
1056        border: 1px solid #000;
1057        border-inline: 2px solid red;
1058      }
1059    "#},
1060    );
1061
1062    test(
1063      r#"
1064      .foo {
1065        border-block-start: 1px solid black;
1066        border-block-end: 1px solid black;
1067        border-inline-start: 2px solid red;
1068        border-inline-end: 3px solid red;
1069      }
1070    "#,
1071      indoc! {r#"
1072      .foo {
1073        border: 1px solid #000;
1074        border-inline-start: 2px solid red;
1075        border-inline-end: 3px solid red;
1076      }
1077    "#},
1078    );
1079
1080    test(
1081      r#"
1082      .foo {
1083        border-block-start: 2px solid black;
1084        border-block-end: 1px solid black;
1085        border-inline-start: 2px solid red;
1086        border-inline-end: 2px solid red;
1087      }
1088    "#,
1089      indoc! {r#"
1090      .foo {
1091        border: 2px solid red;
1092        border-block-start-color: #000;
1093        border-block-end: 1px solid #000;
1094      }
1095    "#},
1096    );
1097
1098    test(
1099      r#"
1100      .foo {
1101        border-block-start: 2px solid red;
1102        border-block-end: 1px solid red;
1103        border-inline-start: 2px solid red;
1104        border-inline-end: 2px solid red;
1105      }
1106    "#,
1107      indoc! {r#"
1108      .foo {
1109        border: 2px solid red;
1110        border-block-end-width: 1px;
1111      }
1112    "#},
1113    );
1114
1115    test(
1116      r#"
1117      .foo {
1118        border-block-start: 2px solid red;
1119        border-block-end: 2px solid red;
1120        border-inline-start: 2px solid red;
1121        border-inline-end: 1px solid red;
1122      }
1123    "#,
1124      indoc! {r#"
1125      .foo {
1126        border: 2px solid red;
1127        border-inline-end-width: 1px;
1128      }
1129    "#},
1130    );
1131
1132    test(
1133      r#"
1134      .foo {
1135        border: 1px solid currentColor;
1136      }
1137    "#,
1138      indoc! {r#"
1139      .foo {
1140        border: 1px solid;
1141      }
1142    "#
1143      },
1144    );
1145
1146    minify_test(
1147      r#"
1148      .foo {
1149        border: 1px solid currentColor;
1150      }
1151    "#,
1152      ".foo{border:1px solid}",
1153    );
1154
1155    prefix_test(
1156      r#"
1157      .foo {
1158        border-block: 2px solid red;
1159      }
1160    "#,
1161      indoc! {r#"
1162      .foo {
1163        border-top: 2px solid red;
1164        border-bottom: 2px solid red;
1165      }
1166    "#
1167      },
1168      Browsers {
1169        safari: Some(8 << 16),
1170        ..Browsers::default()
1171      },
1172    );
1173
1174    prefix_test(
1175      r#"
1176      .foo {
1177        border-block-start: 2px solid red;
1178      }
1179    "#,
1180      indoc! {r#"
1181      .foo {
1182        border-top: 2px solid red;
1183      }
1184    "#
1185      },
1186      Browsers {
1187        safari: Some(8 << 16),
1188        ..Browsers::default()
1189      },
1190    );
1191
1192    prefix_test(
1193      r#"
1194      .foo {
1195        border-block-end: 2px solid red;
1196      }
1197    "#,
1198      indoc! {r#"
1199      .foo {
1200        border-bottom: 2px solid red;
1201      }
1202    "#
1203      },
1204      Browsers {
1205        safari: Some(8 << 16),
1206        ..Browsers::default()
1207      },
1208    );
1209
1210    prefix_test(
1211      r#"
1212      .foo {
1213        border-inline: 2px solid red;
1214      }
1215    "#,
1216      indoc! {r#"
1217      .foo {
1218        border-left: 2px solid red;
1219        border-right: 2px solid red;
1220      }
1221    "#
1222      },
1223      Browsers {
1224        safari: Some(8 << 16),
1225        ..Browsers::default()
1226      },
1227    );
1228
1229    prefix_test(
1230      r#"
1231      .foo {
1232        border-block-width: 2px;
1233      }
1234    "#,
1235      indoc! {r#"
1236      .foo {
1237        border-block-start-width: 2px;
1238        border-block-end-width: 2px;
1239      }
1240    "#
1241      },
1242      Browsers {
1243        safari: Some(13 << 16),
1244        ..Browsers::default()
1245      },
1246    );
1247
1248    prefix_test(
1249      r#"
1250      .foo {
1251        border-block-width: 2px;
1252      }
1253    "#,
1254      indoc! {r#"
1255      .foo {
1256        border-block-width: 2px;
1257      }
1258    "#
1259      },
1260      Browsers {
1261        safari: Some(15 << 16),
1262        ..Browsers::default()
1263      },
1264    );
1265
1266    prefix_test(
1267      r#"
1268      .foo {
1269        border-inline-start: 2px solid red;
1270      }
1271    "#,
1272      indoc! {r#"
1273      .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))) {
1274        border-left: 2px solid red;
1275      }
1276
1277      .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))) {
1278        border-left: 2px solid red;
1279      }
1280
1281      .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)) {
1282        border-right: 2px solid red;
1283      }
1284
1285      .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)) {
1286        border-right: 2px solid red;
1287      }
1288    "#
1289      },
1290      Browsers {
1291        safari: Some(8 << 16),
1292        ..Browsers::default()
1293      },
1294    );
1295
1296    prefix_test(
1297      r#"
1298      .foo {
1299        border-inline-start-width: 2px;
1300      }
1301    "#,
1302      indoc! {r#"
1303      .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))) {
1304        border-left-width: 2px;
1305      }
1306
1307      .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))) {
1308        border-left-width: 2px;
1309      }
1310
1311      .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)) {
1312        border-right-width: 2px;
1313      }
1314
1315      .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)) {
1316        border-right-width: 2px;
1317      }
1318    "#
1319      },
1320      Browsers {
1321        safari: Some(8 << 16),
1322        ..Browsers::default()
1323      },
1324    );
1325
1326    prefix_test(
1327      r#"
1328      .foo {
1329        border-inline-end: 2px solid red;
1330      }
1331    "#,
1332      indoc! {r#"
1333      .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))) {
1334        border-right: 2px solid red;
1335      }
1336
1337      .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))) {
1338        border-right: 2px solid red;
1339      }
1340
1341      .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)) {
1342        border-left: 2px solid red;
1343      }
1344
1345      .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)) {
1346        border-left: 2px solid red;
1347      }
1348    "#
1349      },
1350      Browsers {
1351        safari: Some(8 << 16),
1352        ..Browsers::default()
1353      },
1354    );
1355
1356    prefix_test(
1357      r#"
1358      .foo {
1359        border-inline-start: 2px solid red;
1360        border-inline-end: 5px solid green;
1361      }
1362    "#,
1363      indoc! {r#"
1364      .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))) {
1365        border-left: 2px solid red;
1366        border-right: 5px solid green;
1367      }
1368
1369      .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))) {
1370        border-left: 2px solid red;
1371        border-right: 5px solid green;
1372      }
1373
1374      .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)) {
1375        border-left: 5px solid green;
1376        border-right: 2px solid red;
1377      }
1378
1379      .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)) {
1380        border-left: 5px solid green;
1381        border-right: 2px solid red;
1382      }
1383    "#
1384      },
1385      Browsers {
1386        safari: Some(8 << 16),
1387        ..Browsers::default()
1388      },
1389    );
1390
1391    prefix_test(
1392      r#"
1393      .foo {
1394        border-inline-start: 2px solid red;
1395        border-inline-end: 5px solid green;
1396      }
1397
1398      .bar {
1399        border-inline-start: 1px dotted gray;
1400        border-inline-end: 1px solid black;
1401      }
1402    "#,
1403      indoc! {r#"
1404      .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))) {
1405        border-left: 2px solid red;
1406        border-right: 5px solid green;
1407      }
1408
1409      .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))) {
1410        border-left: 2px solid red;
1411        border-right: 5px solid green;
1412      }
1413
1414      .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)) {
1415        border-left: 5px solid green;
1416        border-right: 2px solid red;
1417      }
1418
1419      .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)) {
1420        border-left: 5px solid green;
1421        border-right: 2px solid red;
1422      }
1423
1424      .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))) {
1425        border-left: 1px dotted gray;
1426        border-right: 1px solid #000;
1427      }
1428
1429      .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))) {
1430        border-left: 1px dotted gray;
1431        border-right: 1px solid #000;
1432      }
1433
1434      .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)) {
1435        border-left: 1px solid #000;
1436        border-right: 1px dotted gray;
1437      }
1438
1439      .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)) {
1440        border-left: 1px solid #000;
1441        border-right: 1px dotted gray;
1442      }
1443    "#
1444      },
1445      Browsers {
1446        safari: Some(8 << 16),
1447        ..Browsers::default()
1448      },
1449    );
1450
1451    prefix_test(
1452      r#"
1453      .foo {
1454        border-inline-width: 2px;
1455      }
1456    "#,
1457      indoc! {r#"
1458      .foo {
1459        border-left-width: 2px;
1460        border-right-width: 2px;
1461      }
1462    "#
1463      },
1464      Browsers {
1465        safari: Some(8 << 16),
1466        ..Browsers::default()
1467      },
1468    );
1469
1470    prefix_test(
1471      r#"
1472      .foo {
1473        border-inline-width: 2px;
1474      }
1475    "#,
1476      indoc! {r#"
1477      .foo {
1478        border-left-width: 2px;
1479        border-right-width: 2px;
1480      }
1481    "#
1482      },
1483      Browsers {
1484        safari: Some(8 << 16),
1485        ..Browsers::default()
1486      },
1487    );
1488
1489    prefix_test(
1490      r#"
1491      .foo {
1492        border-inline-style: solid;
1493      }
1494    "#,
1495      indoc! {r#"
1496      .foo {
1497        border-left-style: solid;
1498        border-right-style: solid;
1499      }
1500    "#
1501      },
1502      Browsers {
1503        safari: Some(8 << 16),
1504        ..Browsers::default()
1505      },
1506    );
1507
1508    prefix_test(
1509      r#"
1510      .foo {
1511        border-inline-color: red;
1512      }
1513    "#,
1514      indoc! {r#"
1515      .foo {
1516        border-left-color: red;
1517        border-right-color: red;
1518      }
1519    "#
1520      },
1521      Browsers {
1522        safari: Some(8 << 16),
1523        ..Browsers::default()
1524      },
1525    );
1526
1527    prefix_test(
1528      r#"
1529      .foo {
1530        border-inline-end: var(--test);
1531      }
1532    "#,
1533      indoc! {r#"
1534      .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))) {
1535        border-right: var(--test);
1536      }
1537
1538      .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))) {
1539        border-right: var(--test);
1540      }
1541
1542      .foo:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
1543        border-left: var(--test);
1544      }
1545
1546      .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)) {
1547        border-left: var(--test);
1548      }
1549    "#
1550      },
1551      Browsers {
1552        safari: Some(8 << 16),
1553        ..Browsers::default()
1554      },
1555    );
1556
1557    prefix_test(
1558      r#"
1559      .foo {
1560        border-inline-start: var(--start);
1561        border-inline-end: var(--end);
1562      }
1563    "#,
1564      indoc! {r#"
1565      .foo:not(:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
1566        border-left: var(--start);
1567        border-right: var(--end);
1568      }
1569
1570      .foo:not(:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi))) {
1571        border-left: var(--start);
1572        border-right: var(--end);
1573      }
1574
1575      .foo:-webkit-any(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
1576        border-right: var(--start);
1577        border-left: var(--end);
1578      }
1579
1580      .foo:is(:lang(ae), :lang(ar), :lang(arc), :lang(bcc), :lang(bqi), :lang(ckb), :lang(dv), :lang(fa), :lang(glk), :lang(he), :lang(ku), :lang(mzn), :lang(nqo), :lang(pnb), :lang(ps), :lang(sd), :lang(ug), :lang(ur), :lang(yi)) {
1581        border-right: var(--start);
1582        border-left: var(--end);
1583      }
1584    "#
1585      },
1586      Browsers {
1587        safari: Some(8 << 16),
1588        ..Browsers::default()
1589      },
1590    );
1591
1592    for prop in &[
1593      "border-inline-start-color",
1594      "border-inline-end-color",
1595      "border-block-start-color",
1596      "border-block-end-color",
1597      "border-top-color",
1598      "border-bottom-color",
1599      "border-left-color",
1600      "border-right-color",
1601      "border-color",
1602      "border-block-color",
1603      "border-inline-color",
1604    ] {
1605      prefix_test(
1606        &format!(
1607          r#"
1608        .foo {{
1609          {}: lab(40% 56.6 39);
1610        }}
1611      "#,
1612          prop
1613        ),
1614        &format!(
1615          indoc! {r#"
1616        .foo {{
1617          {}: #b32323;
1618          {}: lab(40% 56.6 39);
1619        }}
1620      "#},
1621          prop, prop
1622        ),
1623        Browsers {
1624          chrome: Some(90 << 16),
1625          ..Browsers::default()
1626        },
1627      );
1628    }
1629
1630    for prop in &[
1631      "border",
1632      "border-inline",
1633      "border-block",
1634      "border-left",
1635      "border-right",
1636      "border-top",
1637      "border-bottom",
1638      "border-block-start",
1639      "border-block-end",
1640      "border-inline-start",
1641      "border-inline-end",
1642    ] {
1643      prefix_test(
1644        &format!(
1645          r#"
1646        .foo {{
1647          {}: 2px solid lab(40% 56.6 39);
1648        }}
1649      "#,
1650          prop
1651        ),
1652        &format!(
1653          indoc! {r#"
1654        .foo {{
1655          {}: 2px solid #b32323;
1656          {}: 2px solid lab(40% 56.6 39);
1657        }}
1658      "#},
1659          prop, prop
1660        ),
1661        Browsers {
1662          chrome: Some(90 << 16),
1663          ..Browsers::default()
1664        },
1665      );
1666    }
1667
1668    for prop in &[
1669      "border",
1670      "border-inline",
1671      "border-block",
1672      "border-left",
1673      "border-right",
1674      "border-top",
1675      "border-bottom",
1676      "border-block-start",
1677      "border-block-end",
1678      "border-inline-start",
1679      "border-inline-end",
1680    ] {
1681      prefix_test(
1682        &format!(
1683          r#"
1684        .foo {{
1685          {}: var(--border-width) solid lab(40% 56.6 39);
1686        }}
1687      "#,
1688          prop
1689        ),
1690        &format!(
1691          indoc! {r#"
1692        .foo {{
1693          {}: var(--border-width) solid #b32323;
1694        }}
1695
1696        @supports (color: lab(0% 0 0)) {{
1697          .foo {{
1698            {}: var(--border-width) solid lab(40% 56.6 39);
1699          }}
1700        }}
1701      "#},
1702          prop, prop
1703        ),
1704        Browsers {
1705          chrome: Some(90 << 16),
1706          ..Browsers::default()
1707        },
1708      );
1709
1710      prefix_test(
1711        &format!(
1712          r#"
1713        @supports (color: lab(0% 0 0)) {{
1714          .foo {{
1715            {}: var(--border-width) solid lab(40% 56.6 39);
1716          }}
1717        }}
1718      "#,
1719          prop
1720        ),
1721        &format!(
1722          indoc! {r#"
1723        @supports (color: lab(0% 0 0)) {{
1724          .foo {{
1725            {}: var(--border-width) solid lab(40% 56.6 39);
1726          }}
1727        }}
1728      "#},
1729          prop,
1730        ),
1731        Browsers {
1732          chrome: Some(90 << 16),
1733          ..Browsers::default()
1734        },
1735      );
1736    }
1737
1738    prefix_test(
1739      r#"
1740      .foo {
1741        border-inline-start-color: lab(40% 56.6 39);
1742      }
1743    "#,
1744      indoc! {r#"
1745      .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))) {
1746        border-left-color: #b32323;
1747        border-left-color: lab(40% 56.6 39);
1748      }
1749
1750      .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))) {
1751        border-left-color: #b32323;
1752        border-left-color: lab(40% 56.6 39);
1753      }
1754
1755      .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)) {
1756        border-right-color: #b32323;
1757        border-right-color: lab(40% 56.6 39);
1758      }
1759
1760      .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)) {
1761        border-right-color: #b32323;
1762        border-right-color: lab(40% 56.6 39);
1763      }
1764    "#},
1765      Browsers {
1766        safari: Some(8 << 16),
1767        ..Browsers::default()
1768      },
1769    );
1770
1771    prefix_test(
1772      r#"
1773      .foo {
1774        border-inline-end-color: lab(40% 56.6 39);
1775      }
1776    "#,
1777      indoc! {r#"
1778      .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))) {
1779        border-right-color: #b32323;
1780        border-right-color: lab(40% 56.6 39);
1781      }
1782
1783      .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))) {
1784        border-right-color: #b32323;
1785        border-right-color: lab(40% 56.6 39);
1786      }
1787
1788      .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)) {
1789        border-left-color: #b32323;
1790        border-left-color: lab(40% 56.6 39);
1791      }
1792
1793      .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)) {
1794        border-left-color: #b32323;
1795        border-left-color: lab(40% 56.6 39);
1796      }
1797    "#},
1798      Browsers {
1799        safari: Some(8 << 16),
1800        ..Browsers::default()
1801      },
1802    );
1803
1804    prefix_test(
1805      r#"
1806      .foo {
1807        border-inline-start-color: lab(40% 56.6 39);
1808        border-inline-end-color: lch(50.998% 135.363 338);
1809      }
1810    "#,
1811      indoc! {r#"
1812      .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))) {
1813        border-left-color: #b32323;
1814        border-left-color: lab(40% 56.6 39);
1815        border-right-color: #ee00be;
1816        border-right-color: lch(50.998% 135.363 338);
1817      }
1818
1819      .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))) {
1820        border-left-color: #b32323;
1821        border-left-color: lab(40% 56.6 39);
1822        border-right-color: #ee00be;
1823        border-right-color: lch(50.998% 135.363 338);
1824      }
1825
1826      .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)) {
1827        border-left-color: #ee00be;
1828        border-left-color: lch(50.998% 135.363 338);
1829        border-right-color: #b32323;
1830        border-right-color: lab(40% 56.6 39);
1831      }
1832
1833      .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)) {
1834        border-left-color: #ee00be;
1835        border-left-color: lch(50.998% 135.363 338);
1836        border-right-color: #b32323;
1837        border-right-color: lab(40% 56.6 39);
1838      }
1839    "#},
1840      Browsers {
1841        safari: Some(8 << 16),
1842        ..Browsers::default()
1843      },
1844    );
1845
1846    prefix_test(
1847      r#"
1848      .foo {
1849        border-inline-start-color: lab(40% 56.6 39);
1850        border-inline-end-color: lch(50.998% 135.363 338);
1851      }
1852    "#,
1853      indoc! {r#"
1854      .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))) {
1855        border-left-color: #b32323;
1856        border-left-color: color(display-p3 .643308 .192455 .167712);
1857        border-left-color: lab(40% 56.6 39);
1858        border-right-color: #ee00be;
1859        border-right-color: color(display-p3 .972962 -.362078 .804206);
1860        border-right-color: lch(50.998% 135.363 338);
1861      }
1862
1863      .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)) {
1864        border-left-color: #ee00be;
1865        border-left-color: color(display-p3 .972962 -.362078 .804206);
1866        border-left-color: lch(50.998% 135.363 338);
1867        border-right-color: #b32323;
1868        border-right-color: color(display-p3 .643308 .192455 .167712);
1869        border-right-color: lab(40% 56.6 39);
1870      }
1871    "#},
1872      Browsers {
1873        chrome: Some(8 << 16),
1874        safari: Some(14 << 16),
1875        ..Browsers::default()
1876      },
1877    );
1878
1879    prefix_test(
1880      r#"
1881      .foo {
1882        border-inline-start: 2px solid lab(40% 56.6 39);
1883      }
1884    "#,
1885      indoc! {r#"
1886      .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))) {
1887        border-left: 2px solid #b32323;
1888        border-left: 2px solid lab(40% 56.6 39);
1889      }
1890
1891      .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))) {
1892        border-left: 2px solid #b32323;
1893        border-left: 2px solid lab(40% 56.6 39);
1894      }
1895
1896      .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)) {
1897        border-right: 2px solid #b32323;
1898        border-right: 2px solid lab(40% 56.6 39);
1899      }
1900
1901      .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)) {
1902        border-right: 2px solid #b32323;
1903        border-right: 2px solid lab(40% 56.6 39);
1904      }
1905    "#},
1906      Browsers {
1907        safari: Some(8 << 16),
1908        ..Browsers::default()
1909      },
1910    );
1911
1912    prefix_test(
1913      r#"
1914      .foo {
1915        border-inline-end: 2px solid lab(40% 56.6 39);
1916      }
1917    "#,
1918      indoc! {r#"
1919      .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))) {
1920        border-right: 2px solid #b32323;
1921        border-right: 2px solid lab(40% 56.6 39);
1922      }
1923
1924      .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))) {
1925        border-right: 2px solid #b32323;
1926        border-right: 2px solid lab(40% 56.6 39);
1927      }
1928
1929      .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)) {
1930        border-left: 2px solid #b32323;
1931        border-left: 2px solid lab(40% 56.6 39);
1932      }
1933
1934      .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)) {
1935        border-left: 2px solid #b32323;
1936        border-left: 2px solid lab(40% 56.6 39);
1937      }
1938    "#},
1939      Browsers {
1940        safari: Some(8 << 16),
1941        ..Browsers::default()
1942      },
1943    );
1944
1945    prefix_test(
1946      r#"
1947      .foo {
1948        border-inline-end: var(--border-width) solid lab(40% 56.6 39);
1949      }
1950    "#,
1951      indoc! {r#"
1952      .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))) {
1953        border-right: var(--border-width) solid #b32323;
1954      }
1955
1956      .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))) {
1957        border-right: var(--border-width) solid #b32323;
1958      }
1959
1960      @supports (color: lab(0% 0 0)) {
1961        .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))) {
1962          border-right: var(--border-width) solid lab(40% 56.6 39);
1963        }
1964      }
1965
1966      .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)) {
1967        border-left: var(--border-width) solid #b32323;
1968      }
1969
1970      .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)) {
1971        border-left: var(--border-width) solid #b32323;
1972      }
1973
1974      @supports (color: lab(0% 0 0)) {
1975        .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)) {
1976          border-left: var(--border-width) solid lab(40% 56.6 39);
1977        }
1978      }
1979    "#},
1980      Browsers {
1981        safari: Some(8 << 16),
1982        ..Browsers::default()
1983      },
1984    );
1985
1986    prefix_test(
1987      r#"
1988      .foo {
1989        border-inline-start: 2px solid red;
1990        border-inline-end: 2px solid red;
1991      }
1992    "#,
1993      indoc! {r#"
1994      .foo {
1995        border-inline-start: 2px solid red;
1996        border-inline-end: 2px solid red;
1997      }
1998    "#
1999      },
2000      Browsers {
2001        safari: Some(13 << 16),
2002        ..Browsers::default()
2003      },
2004    );
2005
2006    prefix_test(
2007      r#"
2008      .foo {
2009        border-inline-start: 2px solid red;
2010        border-inline-end: 2px solid red;
2011      }
2012    "#,
2013      indoc! {r#"
2014      .foo {
2015        border-inline: 2px solid red;
2016      }
2017    "#
2018      },
2019      Browsers {
2020        safari: Some(15 << 16),
2021        ..Browsers::default()
2022      },
2023    );
2024
2025    prefix_test(
2026      r#"
2027      .foo {
2028        border-width: 22px;
2029        border-width: max(2cqw, 22px);
2030      }
2031    "#,
2032      indoc! {r#"
2033      .foo {
2034        border-width: 22px;
2035        border-width: max(2cqw, 22px);
2036      }
2037    "#
2038      },
2039      Browsers {
2040        safari: Some(14 << 16),
2041        ..Browsers::default()
2042      },
2043    );
2044    prefix_test(
2045      r#"
2046      .foo {
2047        border-width: 22px;
2048        border-width: max(2cqw, 22px);
2049      }
2050    "#,
2051      indoc! {r#"
2052      .foo {
2053        border-width: max(2cqw, 22px);
2054      }
2055    "#
2056      },
2057      Browsers {
2058        safari: Some(16 << 16),
2059        ..Browsers::default()
2060      },
2061    );
2062    prefix_test(
2063      r#"
2064      .foo {
2065        border-color: #4263eb;
2066        border-color: color(display-p3 0 .5 1);
2067      }
2068    "#,
2069      indoc! {r#"
2070      .foo {
2071        border-color: #4263eb;
2072        border-color: color(display-p3 0 .5 1);
2073      }
2074    "#
2075      },
2076      Browsers {
2077        chrome: Some(99 << 16),
2078        ..Browsers::default()
2079      },
2080    );
2081    prefix_test(
2082      r#"
2083      .foo {
2084        border-color: #4263eb;
2085        border-color: color(display-p3 0 .5 1);
2086      }
2087    "#,
2088      indoc! {r#"
2089      .foo {
2090        border-color: color(display-p3 0 .5 1);
2091      }
2092    "#
2093      },
2094      Browsers {
2095        safari: Some(16 << 16),
2096        ..Browsers::default()
2097      },
2098    );
2099    prefix_test(
2100      r#"
2101      .foo {
2102        border: 1px solid #4263eb;
2103        border-color: color(display-p3 0 .5 1);
2104      }
2105    "#,
2106      indoc! {r#"
2107      .foo {
2108        border: 1px solid #4263eb;
2109        border-color: color(display-p3 0 .5 1);
2110      }
2111    "#
2112      },
2113      Browsers {
2114        chrome: Some(99 << 16),
2115        ..Browsers::default()
2116      },
2117    );
2118    prefix_test(
2119      r#"
2120      .foo {
2121        border: 1px solid #4263eb;
2122        border-color: color(display-p3 0 .5 1);
2123      }
2124    "#,
2125      indoc! {r#"
2126      .foo {
2127        border: 1px solid color(display-p3 0 .5 1);
2128      }
2129    "#
2130      },
2131      Browsers {
2132        safari: Some(16 << 16),
2133        ..Browsers::default()
2134      },
2135    );
2136    prefix_test(
2137      r#"
2138      .foo {
2139        border-color: var(--fallback);
2140        border-color: color(display-p3 0 .5 1);
2141      }
2142    "#,
2143      indoc! {r#"
2144      .foo {
2145        border-color: var(--fallback);
2146        border-color: color(display-p3 0 .5 1);
2147      }
2148    "#
2149      },
2150      Browsers {
2151        chrome: Some(99 << 16),
2152        ..Browsers::default()
2153      },
2154    );
2155  }
2156
2157  #[test]
2158  pub fn test_border_image() {
2159    test(
2160      r#"
2161      .foo {
2162        border-image: url(test.png) 60;
2163      }
2164    "#,
2165      indoc! {r#"
2166      .foo {
2167        border-image: url("test.png") 60;
2168      }
2169    "#
2170      },
2171    );
2172
2173    test(
2174      r#"
2175      .foo {
2176        border-image: url(test.png) 60;
2177        border-image-source: url(foo.png);
2178      }
2179    "#,
2180      indoc! {r#"
2181      .foo {
2182        border-image: url("foo.png") 60;
2183      }
2184    "#
2185      },
2186    );
2187
2188    test(
2189      r#"
2190      .foo {
2191        border-image-source: url(foo.png);
2192        border-image-slice: 10 40 10 40 fill;
2193        border-image-width: 10px;
2194        border-image-outset: 0;
2195        border-image-repeat: round round;
2196      }
2197    "#,
2198      indoc! {r#"
2199      .foo {
2200        border-image: url("foo.png") 10 40 fill / 10px round;
2201      }
2202    "#
2203      },
2204    );
2205
2206    test(
2207      r#"
2208      .foo {
2209        border-image: url(foo.png) 60;
2210        border-image-source: var(--test);
2211      }
2212    "#,
2213      indoc! {r#"
2214      .foo {
2215        border-image: url("foo.png") 60;
2216        border-image-source: var(--test);
2217      }
2218    "#
2219      },
2220    );
2221
2222    test(
2223      r#"
2224      .foo {
2225        -webkit-border-image: url("test.png") 60;
2226      }
2227    "#,
2228      indoc! {r#"
2229      .foo {
2230        -webkit-border-image: url("test.png") 60;
2231      }
2232    "#
2233      },
2234    );
2235
2236    test(
2237      r#"
2238      .foo {
2239        -webkit-border-image: url("test.png") 60;
2240        border-image: url("test.png") 60;
2241      }
2242    "#,
2243      indoc! {r#"
2244      .foo {
2245        -webkit-border-image: url("test.png") 60;
2246        border-image: url("test.png") 60;
2247      }
2248    "#
2249      },
2250    );
2251
2252    test(
2253      r#"
2254      .foo {
2255        -webkit-border-image: url("test.png") 60;
2256        border-image-source: url(foo.png);
2257      }
2258    "#,
2259      indoc! {r#"
2260      .foo {
2261        -webkit-border-image: url("test.png") 60;
2262        border-image-source: url("foo.png");
2263      }
2264    "#
2265      },
2266    );
2267
2268    test(
2269      r#"
2270      .foo {
2271        border: 1px solid red;
2272        border-image: url(test.png) 60;
2273      }
2274    "#,
2275      indoc! {r#"
2276      .foo {
2277        border: 1px solid red;
2278        border-image: url("test.png") 60;
2279      }
2280    "#
2281      },
2282    );
2283
2284    test(
2285      r#"
2286      .foo {
2287        border-image: url(test.png) 60;
2288        border: 1px solid red;
2289      }
2290    "#,
2291      indoc! {r#"
2292      .foo {
2293        border: 1px solid red;
2294      }
2295    "#
2296      },
2297    );
2298
2299    test(
2300      r#"
2301      .foo {
2302        border: 1px solid red;
2303        border-image: var(--border-image);
2304      }
2305    "#,
2306      indoc! {r#"
2307      .foo {
2308        border: 1px solid red;
2309        border-image: var(--border-image);
2310      }
2311    "#
2312      },
2313    );
2314
2315    prefix_test(
2316      r#"
2317      .foo {
2318        border-image: url("test.png") 60;
2319      }
2320    "#,
2321      indoc! {r#"
2322      .foo {
2323        -webkit-border-image: url("test.png") 60;
2324        -moz-border-image: url("test.png") 60;
2325        -o-border-image: url("test.png") 60;
2326        border-image: url("test.png") 60;
2327      }
2328    "#
2329      },
2330      Browsers {
2331        safari: Some(4 << 16),
2332        firefox: Some(4 << 16),
2333        opera: Some(12 << 16),
2334        ..Browsers::default()
2335      },
2336    );
2337
2338    prefix_test(
2339      r#"
2340      .foo {
2341        border-image: url(foo.png) 10 40 fill / 10px round;
2342      }
2343    "#,
2344      indoc! {r#"
2345      .foo {
2346        border-image: url("foo.png") 10 40 fill / 10px round;
2347      }
2348    "#
2349      },
2350      Browsers {
2351        safari: Some(4 << 16),
2352        firefox: Some(4 << 16),
2353        opera: Some(12 << 16),
2354        ..Browsers::default()
2355      },
2356    );
2357
2358    prefix_test(
2359      r#"
2360      .foo {
2361        border-image: var(--test) 60;
2362      }
2363    "#,
2364      indoc! {r#"
2365      .foo {
2366        -webkit-border-image: var(--test) 60;
2367        -moz-border-image: var(--test) 60;
2368        -o-border-image: var(--test) 60;
2369        border-image: var(--test) 60;
2370      }
2371    "#
2372      },
2373      Browsers {
2374        safari: Some(4 << 16),
2375        firefox: Some(4 << 16),
2376        opera: Some(12 << 16),
2377        ..Browsers::default()
2378      },
2379    );
2380
2381    prefix_test(
2382      r#"
2383      .foo {
2384        -webkit-border-image: url(foo.png) 60;
2385        -moz-border-image: url(foo.png) 60;
2386        -o-border-image: url(foo.png) 60;
2387        border-image: url(foo.png) 60;
2388      }
2389    "#,
2390      indoc! {r#"
2391      .foo {
2392        border-image: url("foo.png") 60;
2393      }
2394    "#
2395      },
2396      Browsers {
2397        chrome: Some(15 << 16),
2398        ..Browsers::default()
2399      },
2400    );
2401
2402    prefix_test(
2403      r#"
2404      .foo {
2405        border-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 60;
2406      }
2407    "#,
2408      indoc! {r#"
2409      .foo {
2410        -webkit-border-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ff0f0e), to(#7773ff)) 60;
2411        -webkit-border-image: -webkit-linear-gradient(top, #ff0f0e, #7773ff) 60;
2412        border-image: linear-gradient(#ff0f0e, #7773ff) 60;
2413        border-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 60;
2414      }
2415    "#
2416      },
2417      Browsers {
2418        chrome: Some(8 << 16),
2419        ..Browsers::default()
2420      },
2421    );
2422
2423    prefix_test(
2424      r#"
2425      .foo {
2426        border-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 60;
2427      }
2428    "#,
2429      indoc! {r#"
2430      .foo {
2431        -webkit-border-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ff0f0e), to(#7773ff)) 60;
2432        -webkit-border-image: -webkit-linear-gradient(top, #ff0f0e, #7773ff) 60;
2433        -moz-border-image: -moz-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        firefox: Some(4 << 16),
2442        ..Browsers::default()
2443      },
2444    );
2445
2446    prefix_test(
2447      r#"
2448      .foo {
2449        border-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 60;
2450      }
2451    "#,
2452      indoc! {r#"
2453      .foo {
2454        border-image: -webkit-linear-gradient(top, #ff0f0e, #7773ff) 60;
2455        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(15 << 16),
2463        firefox: Some(15 << 16),
2464        ..Browsers::default()
2465      },
2466    );
2467
2468    prefix_test(
2469      r#"
2470      .foo {
2471        border-image-source: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
2472      }
2473    "#,
2474      indoc! {r#"
2475      .foo {
2476        border-image-source: -webkit-linear-gradient(top, #ff0f0e, #7773ff);
2477        border-image-source: linear-gradient(#ff0f0e, #7773ff);
2478        border-image-source: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
2479      }
2480    "#
2481      },
2482      Browsers {
2483        chrome: Some(15 << 16),
2484        ..Browsers::default()
2485      },
2486    );
2487
2488    prefix_test(
2489      r#"
2490      .foo {
2491        border-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) var(--foo);
2492      }
2493    "#,
2494      indoc! {r#"
2495      .foo {
2496        border-image: linear-gradient(#ff0f0e, #7773ff) var(--foo);
2497      }
2498
2499      @supports (color: lab(0% 0 0)) {
2500        .foo {
2501          border-image: linear-gradient(lab(56.208% 94.4644 98.8928), lab(51% 70.4544 -115.586)) var(--foo);
2502        }
2503      }
2504    "#
2505      },
2506      Browsers {
2507        chrome: Some(90 << 16),
2508        ..Browsers::default()
2509      },
2510    );
2511
2512    prefix_test(
2513      r#"
2514      .foo {
2515        border-image-source: linear-gradient(red, green);
2516        border-image-source: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
2517      }
2518    "#,
2519      indoc! {r#"
2520      .foo {
2521        border-image-source: linear-gradient(red, green);
2522        border-image-source: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
2523      }
2524    "#
2525      },
2526      Browsers {
2527        chrome: Some(95 << 16),
2528        ..Browsers::default()
2529      },
2530    );
2531
2532    prefix_test(
2533      r#"
2534      .foo {
2535        border-image-source: linear-gradient(red, green);
2536        border-image-source: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
2537      }
2538    "#,
2539      indoc! {r#"
2540      .foo {
2541        border-image-source: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
2542      }
2543    "#
2544      },
2545      Browsers {
2546        chrome: Some(112 << 16),
2547        ..Browsers::default()
2548      },
2549    );
2550
2551    prefix_test(
2552      r#"
2553      .foo {
2554        border-image: linear-gradient(red, green);
2555        border-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
2556      }
2557    "#,
2558      indoc! {r#"
2559      .foo {
2560        border-image: linear-gradient(red, green);
2561        border-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
2562      }
2563    "#
2564      },
2565      Browsers {
2566        chrome: Some(95 << 16),
2567        ..Browsers::default()
2568      },
2569    );
2570
2571    prefix_test(
2572      r#"
2573      .foo {
2574        border-image: var(--fallback);
2575        border-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
2576      }
2577    "#,
2578      indoc! {r#"
2579      .foo {
2580        border-image: var(--fallback);
2581        border-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
2582      }
2583    "#
2584      },
2585      Browsers {
2586        chrome: Some(95 << 16),
2587        ..Browsers::default()
2588      },
2589    );
2590
2591    prefix_test(
2592      r#"
2593      .foo {
2594        border-image: url("fallback.png") 10 40 fill / 10px;
2595        border-image: url("main.png") 10 40 fill / 10px space;
2596      }
2597    "#,
2598      indoc! {r#"
2599      .foo {
2600        border-image: url("fallback.png") 10 40 fill / 10px;
2601        border-image: url("main.png") 10 40 fill / 10px space;
2602      }
2603    "#
2604      },
2605      Browsers {
2606        chrome: Some(50 << 16),
2607        ..Browsers::default()
2608      },
2609    );
2610
2611    prefix_test(
2612      r#"
2613      .foo {
2614        border-image: url("fallback.png") 10 40 fill / 10px;
2615        border-image: url("main.png") 10 40 fill / 10px space;
2616      }
2617    "#,
2618      indoc! {r#"
2619      .foo {
2620        border-image: url("main.png") 10 40 fill / 10px space;
2621      }
2622    "#
2623      },
2624      Browsers {
2625        chrome: Some(56 << 16),
2626        ..Browsers::default()
2627      },
2628    );
2629
2630    minify_test(".foo { border: none green }", ".foo{border:green}");
2631  }
2632
2633  #[test]
2634  pub fn test_border_radius() {
2635    test(
2636      r#"
2637      .foo {
2638        border-radius: 10px 100px 10px 100px;
2639      }
2640    "#,
2641      indoc! {r#"
2642      .foo {
2643        border-radius: 10px 100px;
2644      }
2645    "#
2646      },
2647    );
2648
2649    test(
2650      r#"
2651      .foo {
2652        border-radius: 10px 100px 10px 100px / 120px 120px;
2653      }
2654    "#,
2655      indoc! {r#"
2656      .foo {
2657        border-radius: 10px 100px / 120px;
2658      }
2659    "#
2660      },
2661    );
2662
2663    test(
2664      r#"
2665      .foo {
2666        border-top-left-radius: 10px 120px;
2667        border-top-right-radius: 100px 120px;
2668        border-bottom-right-radius: 100px 120px;
2669        border-bottom-left-radius: 10px 120px;
2670      }
2671    "#,
2672      indoc! {r#"
2673      .foo {
2674        border-radius: 10px 100px 100px 10px / 120px;
2675      }
2676    "#
2677      },
2678    );
2679
2680    test(
2681      r#"
2682      .foo {
2683        border-top-left-radius: 4px 2px;
2684        border-top-right-radius: 3px 4px;
2685        border-bottom-right-radius: 6px 2px;
2686        border-bottom-left-radius: 3px 4px;
2687      }
2688    "#,
2689      indoc! {r#"
2690      .foo {
2691        border-radius: 4px 3px 6px / 2px 4px;
2692      }
2693    "#
2694      },
2695    );
2696
2697    test(
2698      r#"
2699      .foo {
2700        border-top-left-radius: 1% 2%;
2701        border-top-right-radius: 3% 4%;
2702        border-bottom-right-radius: 5% 6%;
2703        border-bottom-left-radius: 7% 8%;
2704      }
2705    "#,
2706      indoc! {r#"
2707      .foo {
2708        border-radius: 1% 3% 5% 7% / 2% 4% 6% 8%;
2709      }
2710    "#
2711      },
2712    );
2713
2714    test(
2715      r#"
2716      .foo {
2717        border-radius: 10px 100px 10px 100px / 120px 120px;
2718        border-start-start-radius: 10px;
2719      }
2720    "#,
2721      indoc! {r#"
2722      .foo {
2723        border-radius: 10px 100px / 120px;
2724        border-start-start-radius: 10px;
2725      }
2726    "#
2727      },
2728    );
2729
2730    test(
2731      r#"
2732      .foo {
2733        border-start-start-radius: 10px;
2734        border-radius: 10px 100px 10px 100px / 120px 120px;
2735      }
2736    "#,
2737      indoc! {r#"
2738      .foo {
2739        border-radius: 10px 100px / 120px;
2740      }
2741    "#
2742      },
2743    );
2744
2745    test(
2746      r#"
2747      .foo {
2748        border-top-left-radius: 10px 120px;
2749        border-top-right-radius: 100px 120px;
2750        border-start-start-radius: 10px;
2751        border-bottom-right-radius: 100px 120px;
2752        border-bottom-left-radius: 10px 120px;
2753      }
2754    "#,
2755      indoc! {r#"
2756      .foo {
2757        border-top-left-radius: 10px 120px;
2758        border-top-right-radius: 100px 120px;
2759        border-start-start-radius: 10px;
2760        border-bottom-right-radius: 100px 120px;
2761        border-bottom-left-radius: 10px 120px;
2762      }
2763    "#
2764      },
2765    );
2766
2767    test(
2768      r#"
2769      .foo {
2770        border-radius: 10px;
2771        border-top-left-radius: 20px;
2772      }
2773    "#,
2774      indoc! {r#"
2775      .foo {
2776        border-radius: 20px 10px 10px;
2777      }
2778    "#
2779      },
2780    );
2781
2782    test(
2783      r#"
2784      .foo {
2785        border-radius: 10px;
2786        border-top-left-radius: var(--test);
2787      }
2788    "#,
2789      indoc! {r#"
2790      .foo {
2791        border-radius: 10px;
2792        border-top-left-radius: var(--test);
2793      }
2794    "#
2795      },
2796    );
2797
2798    test(
2799      r#"
2800      .foo {
2801        -webkit-border-radius: 10px 100px 10px 100px;
2802        -moz-border-radius: 10px 100px 10px 100px;
2803        border-radius: 10px 100px 10px 100px;
2804      }
2805    "#,
2806      indoc! {r#"
2807      .foo {
2808        -webkit-border-radius: 10px 100px;
2809        -moz-border-radius: 10px 100px;
2810        border-radius: 10px 100px;
2811      }
2812    "#
2813      },
2814    );
2815
2816    test(
2817      r#"
2818      .foo {
2819        -webkit-border-radius: 10px 100px 10px 100px;
2820        -moz-border-radius: 20px;
2821        border-radius: 30px;
2822      }
2823    "#,
2824      indoc! {r#"
2825      .foo {
2826        -webkit-border-radius: 10px 100px;
2827        -moz-border-radius: 20px;
2828        border-radius: 30px;
2829      }
2830    "#
2831      },
2832    );
2833
2834    test(
2835      r#"
2836      .foo {
2837        -webkit-border-top-left-radius: 10px;
2838        -moz-border-top-left-radius: 10px;
2839        border-top-left-radius: 10px;
2840      }
2841    "#,
2842      indoc! {r#"
2843      .foo {
2844        -webkit-border-top-left-radius: 10px;
2845        -moz-border-top-left-radius: 10px;
2846        border-top-left-radius: 10px;
2847      }
2848    "#
2849      },
2850    );
2851
2852    prefix_test(
2853      r#"
2854      .foo {
2855        border-radius: 30px;
2856      }
2857    "#,
2858      indoc! {r#"
2859      .foo {
2860        -webkit-border-radius: 30px;
2861        -moz-border-radius: 30px;
2862        border-radius: 30px;
2863      }
2864    "#
2865      },
2866      Browsers {
2867        safari: Some(4 << 16),
2868        firefox: Some(3 << 16),
2869        ..Browsers::default()
2870      },
2871    );
2872
2873    prefix_test(
2874      r#"
2875      .foo {
2876        border-top-left-radius: 30px;
2877      }
2878    "#,
2879      indoc! {r#"
2880      .foo {
2881        -webkit-border-top-left-radius: 30px;
2882        -moz-border-top-left-radius: 30px;
2883        border-top-left-radius: 30px;
2884      }
2885    "#
2886      },
2887      Browsers {
2888        safari: Some(4 << 16),
2889        firefox: Some(3 << 16),
2890        ..Browsers::default()
2891      },
2892    );
2893
2894    prefix_test(
2895      r#"
2896      .foo {
2897        -webkit-border-radius: 30px;
2898        -moz-border-radius: 30px;
2899        border-radius: 30px;
2900      }
2901    "#,
2902      indoc! {r#"
2903      .foo {
2904        border-radius: 30px;
2905      }
2906    "#
2907      },
2908      Browsers {
2909        safari: Some(14 << 16),
2910        firefox: Some(46 << 16),
2911        ..Browsers::default()
2912      },
2913    );
2914
2915    prefix_test(
2916      r#"
2917      .foo {
2918        -webkit-border-top-left-radius: 30px;
2919        -moz-border-top-left-radius: 30px;
2920        border-top-left-radius: 30px;
2921      }
2922    "#,
2923      indoc! {r#"
2924      .foo {
2925        border-top-left-radius: 30px;
2926      }
2927    "#
2928      },
2929      Browsers {
2930        safari: Some(14 << 16),
2931        firefox: Some(46 << 16),
2932        ..Browsers::default()
2933      },
2934    );
2935
2936    prefix_test(
2937      r#"
2938      .foo {
2939        -webkit-border-radius: 30px;
2940        -moz-border-radius: 30px;
2941      }
2942    "#,
2943      indoc! {r#"
2944      .foo {
2945        -webkit-border-radius: 30px;
2946        -moz-border-radius: 30px;
2947      }
2948    "#
2949      },
2950      Browsers {
2951        safari: Some(14 << 16),
2952        firefox: Some(46 << 16),
2953        ..Browsers::default()
2954      },
2955    );
2956
2957    prefix_test(
2958      r#"
2959      .foo {
2960        -webkit-border-top-left-radius: 30px;
2961        -moz-border-top-right-radius: 30px;
2962        border-bottom-right-radius: 30px;
2963        border-bottom-left-radius: 30px;
2964      }
2965    "#,
2966      indoc! {r#"
2967      .foo {
2968        -webkit-border-top-left-radius: 30px;
2969        -moz-border-top-right-radius: 30px;
2970        border-bottom-right-radius: 30px;
2971        border-bottom-left-radius: 30px;
2972      }
2973    "#
2974      },
2975      Browsers {
2976        safari: Some(14 << 16),
2977        firefox: Some(46 << 16),
2978        ..Browsers::default()
2979      },
2980    );
2981
2982    prefix_test(
2983      r#"
2984      .foo {
2985        border-radius: var(--test);
2986      }
2987    "#,
2988      indoc! {r#"
2989      .foo {
2990        -webkit-border-radius: var(--test);
2991        -moz-border-radius: var(--test);
2992        border-radius: var(--test);
2993      }
2994    "#
2995      },
2996      Browsers {
2997        safari: Some(4 << 16),
2998        firefox: Some(3 << 16),
2999        ..Browsers::default()
3000      },
3001    );
3002
3003    prefix_test(
3004      r#"
3005      .foo {
3006        border-start-start-radius: 5px;
3007      }
3008    "#,
3009      indoc! {r#"
3010      .foo:not(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
3011        border-top-left-radius: 5px;
3012      }
3013
3014      .foo:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) {
3015        border-top-right-radius: 5px;
3016      }
3017    "#
3018      },
3019      Browsers {
3020        safari: Some(12 << 16),
3021        ..Browsers::default()
3022      },
3023    );
3024
3025    prefix_test(
3026      r#"
3027      .foo {
3028        border-start-start-radius: 5px;
3029        border-start-end-radius: 10px;
3030      }
3031    "#,
3032      indoc! {r#"
3033      .foo:not(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
3034        border-top-left-radius: 5px;
3035        border-top-right-radius: 10px;
3036      }
3037
3038      .foo:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) {
3039        border-top-left-radius: 10px;
3040        border-top-right-radius: 5px;
3041      }
3042    "#
3043      },
3044      Browsers {
3045        safari: Some(12 << 16),
3046        ..Browsers::default()
3047      },
3048    );
3049
3050    prefix_test(
3051      r#"
3052      .foo {
3053        border-end-end-radius: 10px;
3054        border-end-start-radius: 5px;
3055      }
3056    "#,
3057      indoc! {r#"
3058      .foo:not(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
3059        border-bottom-right-radius: 10px;
3060        border-bottom-left-radius: 5px;
3061      }
3062
3063      .foo:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) {
3064        border-bottom-right-radius: 5px;
3065        border-bottom-left-radius: 10px;
3066      }
3067    "#
3068      },
3069      Browsers {
3070        safari: Some(12 << 16),
3071        ..Browsers::default()
3072      },
3073    );
3074
3075    prefix_test(
3076      r#"
3077      .foo {
3078        border-start-start-radius: var(--radius);
3079      }
3080    "#,
3081      indoc! {r#"
3082      .foo:not(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
3083        border-top-left-radius: var(--radius);
3084      }
3085
3086      .foo:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) {
3087        border-top-right-radius: var(--radius);
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(--start);
3101        border-start-end-radius: var(--end);
3102      }
3103    "#,
3104      indoc! {r#"
3105      .foo:not(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
3106        border-top-left-radius: var(--start);
3107        border-top-right-radius: var(--end);
3108      }
3109
3110      .foo:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) {
3111        border-top-right-radius: var(--start);
3112        border-top-left-radius: var(--end);
3113      }
3114    "#
3115      },
3116      Browsers {
3117        safari: Some(12 << 16),
3118        ..Browsers::default()
3119      },
3120    );
3121  }
3122
3123  #[test]
3124  pub fn test_outline() {
3125    test(
3126      r#"
3127      .foo {
3128        outline-width: 2px;
3129        outline-style: solid;
3130        outline-color: blue;
3131      }
3132    "#,
3133      indoc! {r#"
3134      .foo {
3135        outline: 2px solid #00f;
3136      }
3137    "#
3138      },
3139    );
3140
3141    test(
3142      r#"
3143      .foo {
3144        outline: 2px solid blue;
3145      }
3146    "#,
3147      indoc! {r#"
3148      .foo {
3149        outline: 2px solid #00f;
3150      }
3151    "#
3152      },
3153    );
3154
3155    test(
3156      r#"
3157      .foo {
3158        outline: 2px solid red;
3159        outline-color: blue;
3160      }
3161    "#,
3162      indoc! {r#"
3163      .foo {
3164        outline: 2px solid #00f;
3165      }
3166    "#
3167      },
3168    );
3169
3170    test(
3171      r#"
3172      .foo {
3173        outline: 2px solid yellow;
3174        outline-color: var(--color);
3175      }
3176    "#,
3177      indoc! {r#"
3178      .foo {
3179        outline: 2px solid #ff0;
3180        outline-color: var(--color);
3181      }
3182    "#
3183      },
3184    );
3185
3186    prefix_test(
3187      ".foo { outline-color: lab(40% 56.6 39) }",
3188      indoc! { r#"
3189        .foo {
3190          outline-color: #b32323;
3191          outline-color: lab(40% 56.6 39);
3192        }
3193      "#},
3194      Browsers {
3195        chrome: Some(90 << 16),
3196        ..Browsers::default()
3197      },
3198    );
3199
3200    prefix_test(
3201      ".foo { outline: 2px solid lab(40% 56.6 39) }",
3202      indoc! { r#"
3203        .foo {
3204          outline: 2px solid #b32323;
3205          outline: 2px solid lab(40% 56.6 39);
3206        }
3207      "#},
3208      Browsers {
3209        chrome: Some(90 << 16),
3210        ..Browsers::default()
3211      },
3212    );
3213
3214    prefix_test(
3215      ".foo { outline: var(--width) solid lab(40% 56.6 39) }",
3216      indoc! { r#"
3217        .foo {
3218          outline: var(--width) solid #b32323;
3219        }
3220
3221        @supports (color: lab(0% 0 0)) {
3222          .foo {
3223            outline: var(--width) solid lab(40% 56.6 39);
3224          }
3225        }
3226      "#},
3227      Browsers {
3228        chrome: Some(90 << 16),
3229        ..Browsers::default()
3230      },
3231    );
3232  }
3233
3234  #[test]
3235  pub fn test_margin() {
3236    test(
3237      r#"
3238      .foo {
3239        margin-left: 10px;
3240        margin-right: 10px;
3241        margin-top: 20px;
3242        margin-bottom: 20px;
3243      }
3244    "#,
3245      indoc! {r#"
3246      .foo {
3247        margin: 20px 10px;
3248      }
3249    "#
3250      },
3251    );
3252
3253    test(
3254      r#"
3255      .foo {
3256        margin-block-start: 15px;
3257        margin-block-end: 15px;
3258      }
3259    "#,
3260      indoc! {r#"
3261      .foo {
3262        margin-block: 15px;
3263      }
3264    "#
3265      },
3266    );
3267
3268    test(
3269      r#"
3270      .foo {
3271        margin-left: 10px;
3272        margin-right: 10px;
3273        margin-inline-start: 15px;
3274        margin-inline-end: 15px;
3275        margin-top: 20px;
3276        margin-bottom: 20px;
3277
3278      }
3279    "#,
3280      indoc! {r#"
3281      .foo {
3282        margin-left: 10px;
3283        margin-right: 10px;
3284        margin-inline: 15px;
3285        margin-top: 20px;
3286        margin-bottom: 20px;
3287      }
3288    "#
3289      },
3290    );
3291
3292    test(
3293      r#"
3294      .foo {
3295        margin: 10px;
3296        margin-top: 20px;
3297      }
3298    "#,
3299      indoc! {r#"
3300      .foo {
3301        margin: 20px 10px 10px;
3302      }
3303    "#
3304      },
3305    );
3306
3307    test(
3308      r#"
3309      .foo {
3310        margin: 10px;
3311        margin-top: var(--top);
3312      }
3313    "#,
3314      indoc! {r#"
3315      .foo {
3316        margin: 10px;
3317        margin-top: var(--top);
3318      }
3319    "#
3320      },
3321    );
3322
3323    prefix_test(
3324      r#"
3325      .foo {
3326        margin-inline-start: 2px;
3327      }
3328    "#,
3329      indoc! {r#"
3330      .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))) {
3331        margin-left: 2px;
3332      }
3333
3334      .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))) {
3335        margin-left: 2px;
3336      }
3337
3338      .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)) {
3339        margin-right: 2px;
3340      }
3341
3342      .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)) {
3343        margin-right: 2px;
3344      }
3345    "#
3346      },
3347      Browsers {
3348        safari: Some(8 << 16),
3349        ..Browsers::default()
3350      },
3351    );
3352
3353    prefix_test(
3354      r#"
3355      .foo {
3356        margin-inline-start: 2px;
3357        margin-inline-end: 4px;
3358      }
3359    "#,
3360      indoc! {r#"
3361      .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))) {
3362        margin-left: 2px;
3363        margin-right: 4px;
3364      }
3365
3366      .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))) {
3367        margin-left: 2px;
3368        margin-right: 4px;
3369      }
3370
3371      .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)) {
3372        margin-left: 4px;
3373        margin-right: 2px;
3374      }
3375
3376      .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)) {
3377        margin-left: 4px;
3378        margin-right: 2px;
3379      }
3380    "#
3381      },
3382      Browsers {
3383        safari: Some(8 << 16),
3384        ..Browsers::default()
3385      },
3386    );
3387
3388    prefix_test(
3389      r#"
3390      .foo {
3391        margin-inline: 2px;
3392      }
3393    "#,
3394      indoc! {r#"
3395      .foo {
3396        margin-left: 2px;
3397        margin-right: 2px;
3398      }
3399    "#
3400      },
3401      Browsers {
3402        safari: Some(8 << 16),
3403        ..Browsers::default()
3404      },
3405    );
3406
3407    prefix_test(
3408      r#"
3409      .foo {
3410        margin-block-start: 2px;
3411      }
3412    "#,
3413      indoc! {r#"
3414      .foo {
3415        margin-top: 2px;
3416      }
3417    "#
3418      },
3419      Browsers {
3420        safari: Some(8 << 16),
3421        ..Browsers::default()
3422      },
3423    );
3424
3425    prefix_test(
3426      r#"
3427      .foo {
3428        margin-block-end: 2px;
3429      }
3430    "#,
3431      indoc! {r#"
3432      .foo {
3433        margin-bottom: 2px;
3434      }
3435    "#
3436      },
3437      Browsers {
3438        safari: Some(8 << 16),
3439        ..Browsers::default()
3440      },
3441    );
3442
3443    prefix_test(
3444      r#"
3445      .foo {
3446        margin-inline-start: 2px;
3447        margin-inline-end: 2px;
3448      }
3449    "#,
3450      indoc! {r#"
3451      .foo {
3452        margin-inline-start: 2px;
3453        margin-inline-end: 2px;
3454      }
3455    "#
3456      },
3457      Browsers {
3458        safari: Some(13 << 16),
3459        ..Browsers::default()
3460      },
3461    );
3462
3463    prefix_test(
3464      r#"
3465      .foo {
3466        margin-inline: 2px;
3467      }
3468    "#,
3469      indoc! {r#"
3470      .foo {
3471        margin-inline-start: 2px;
3472        margin-inline-end: 2px;
3473      }
3474    "#
3475      },
3476      Browsers {
3477        safari: Some(13 << 16),
3478        ..Browsers::default()
3479      },
3480    );
3481
3482    prefix_test(
3483      r#"
3484      .foo {
3485        margin-inline-start: 2px;
3486        margin-inline-end: 2px;
3487      }
3488    "#,
3489      indoc! {r#"
3490      .foo {
3491        margin-inline: 2px;
3492      }
3493    "#
3494      },
3495      Browsers {
3496        safari: Some(15 << 16),
3497        ..Browsers::default()
3498      },
3499    );
3500
3501    prefix_test(
3502      r#"
3503      .foo {
3504        margin-inline: 2px;
3505      }
3506    "#,
3507      indoc! {r#"
3508      .foo {
3509        margin-inline: 2px;
3510      }
3511    "#
3512      },
3513      Browsers {
3514        safari: Some(15 << 16),
3515        ..Browsers::default()
3516      },
3517    );
3518  }
3519
3520  #[test]
3521  fn test_length() {
3522    for prop in &[
3523      "margin-right",
3524      "margin",
3525      "padding-right",
3526      "padding",
3527      "width",
3528      "height",
3529      "min-height",
3530      "max-height",
3531      "line-height",
3532      "border-radius",
3533    ] {
3534      prefix_test(
3535        &format!(
3536          r#"
3537        .foo {{
3538          {}: 22px;
3539          {}: max(4%, 22px);
3540        }}
3541      "#,
3542          prop, prop
3543        ),
3544        &format!(
3545          indoc! {r#"
3546        .foo {{
3547          {}: 22px;
3548          {}: max(4%, 22px);
3549        }}
3550      "#
3551          },
3552          prop, prop
3553        ),
3554        Browsers {
3555          safari: Some(10 << 16),
3556          ..Browsers::default()
3557        },
3558      );
3559
3560      prefix_test(
3561        &format!(
3562          r#"
3563        .foo {{
3564          {}: 22px;
3565          {}: max(4%, 22px);
3566        }}
3567      "#,
3568          prop, prop
3569        ),
3570        &format!(
3571          indoc! {r#"
3572        .foo {{
3573          {}: max(4%, 22px);
3574        }}
3575      "#
3576          },
3577          prop
3578        ),
3579        Browsers {
3580          safari: Some(14 << 16),
3581          ..Browsers::default()
3582        },
3583      );
3584
3585      prefix_test(
3586        &format!(
3587          r#"
3588        .foo {{
3589          {}: 22px;
3590          {}: max(2cqw, 22px);
3591        }}
3592      "#,
3593          prop, prop
3594        ),
3595        &format!(
3596          indoc! {r#"
3597        .foo {{
3598          {}: 22px;
3599          {}: max(2cqw, 22px);
3600        }}
3601      "#
3602          },
3603          prop, prop
3604        ),
3605        Browsers {
3606          safari: Some(14 << 16),
3607          ..Browsers::default()
3608        },
3609      );
3610      prefix_test(
3611        &format!(
3612          r#"
3613        .foo {{
3614          {}: 22px;
3615          {}: max(2cqw, 22px);
3616        }}
3617      "#,
3618          prop, prop
3619        ),
3620        &format!(
3621          indoc! {r#"
3622        .foo {{
3623          {}: max(2cqw, 22px);
3624        }}
3625      "#
3626          },
3627          prop
3628        ),
3629        Browsers {
3630          safari: Some(16 << 16),
3631          ..Browsers::default()
3632        },
3633      );
3634    }
3635  }
3636
3637  #[test]
3638  pub fn test_padding() {
3639    test(
3640      r#"
3641      .foo {
3642        padding-left: 10px;
3643        padding-right: 10px;
3644        padding-top: 20px;
3645        padding-bottom: 20px;
3646      }
3647    "#,
3648      indoc! {r#"
3649      .foo {
3650        padding: 20px 10px;
3651      }
3652    "#
3653      },
3654    );
3655
3656    test(
3657      r#"
3658      .foo {
3659        padding-block-start: 15px;
3660        padding-block-end: 15px;
3661      }
3662    "#,
3663      indoc! {r#"
3664      .foo {
3665        padding-block: 15px;
3666      }
3667    "#
3668      },
3669    );
3670
3671    test(
3672      r#"
3673      .foo {
3674        padding-left: 10px;
3675        padding-right: 10px;
3676        padding-inline-start: 15px;
3677        padding-inline-end: 15px;
3678        padding-top: 20px;
3679        padding-bottom: 20px;
3680
3681      }
3682    "#,
3683      indoc! {r#"
3684      .foo {
3685        padding-left: 10px;
3686        padding-right: 10px;
3687        padding-inline: 15px;
3688        padding-top: 20px;
3689        padding-bottom: 20px;
3690      }
3691    "#
3692      },
3693    );
3694
3695    prefix_test(
3696      r#"
3697      .foo {
3698        padding-inline-start: 2px;
3699      }
3700    "#,
3701      indoc! {r#"
3702      .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))) {
3703        padding-left: 2px;
3704      }
3705
3706      .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))) {
3707        padding-left: 2px;
3708      }
3709
3710      .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)) {
3711        padding-right: 2px;
3712      }
3713
3714      .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)) {
3715        padding-right: 2px;
3716      }
3717    "#
3718      },
3719      Browsers {
3720        safari: Some(8 << 16),
3721        ..Browsers::default()
3722      },
3723    );
3724
3725    prefix_test(
3726      r#"
3727      .foo {
3728        padding-inline-start: 2px;
3729        padding-inline-end: 4px;
3730      }
3731    "#,
3732      indoc! {r#"
3733      .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))) {
3734        padding-left: 2px;
3735        padding-right: 4px;
3736      }
3737
3738      .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))) {
3739        padding-left: 2px;
3740        padding-right: 4px;
3741      }
3742
3743      .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)) {
3744        padding-left: 4px;
3745        padding-right: 2px;
3746      }
3747
3748      .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)) {
3749        padding-left: 4px;
3750        padding-right: 2px;
3751      }
3752    "#
3753      },
3754      Browsers {
3755        safari: Some(8 << 16),
3756        ..Browsers::default()
3757      },
3758    );
3759
3760    prefix_test(
3761      r#"
3762      .foo {
3763        padding-inline-start: var(--padding);
3764      }
3765    "#,
3766      indoc! {r#"
3767      .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))) {
3768        padding-left: var(--padding);
3769      }
3770
3771      .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))) {
3772        padding-left: var(--padding);
3773      }
3774
3775      .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)) {
3776        padding-right: var(--padding);
3777      }
3778
3779      .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)) {
3780        padding-right: var(--padding);
3781      }
3782    "#
3783      },
3784      Browsers {
3785        safari: Some(8 << 16),
3786        ..Browsers::default()
3787      },
3788    );
3789
3790    prefix_test(
3791      r#"
3792      .foo {
3793        padding-inline: 2px;
3794      }
3795    "#,
3796      indoc! {r#"
3797      .foo {
3798        padding-left: 2px;
3799        padding-right: 2px;
3800      }
3801    "#
3802      },
3803      Browsers {
3804        safari: Some(8 << 16),
3805        ..Browsers::default()
3806      },
3807    );
3808
3809    prefix_test(
3810      r#"
3811      .foo {
3812        padding-block-start: 2px;
3813      }
3814    "#,
3815      indoc! {r#"
3816      .foo {
3817        padding-top: 2px;
3818      }
3819    "#
3820      },
3821      Browsers {
3822        safari: Some(8 << 16),
3823        ..Browsers::default()
3824      },
3825    );
3826
3827    prefix_test(
3828      r#"
3829      .foo {
3830        padding-block-end: 2px;
3831      }
3832    "#,
3833      indoc! {r#"
3834      .foo {
3835        padding-bottom: 2px;
3836      }
3837    "#
3838      },
3839      Browsers {
3840        safari: Some(8 << 16),
3841        ..Browsers::default()
3842      },
3843    );
3844
3845    prefix_test(
3846      r#"
3847      .foo {
3848        padding-top: 1px;
3849        padding-left: 2px;
3850        padding-bottom: 3px;
3851        padding-right: 4px;
3852      }
3853    "#,
3854      indoc! {r#"
3855      .foo {
3856        padding: 1px 4px 3px 2px;
3857      }
3858    "#},
3859      Browsers {
3860        safari: Some(8 << 16),
3861        ..Browsers::default()
3862      },
3863    );
3864
3865    prefix_test(
3866      r#"
3867      .foo {
3868        padding-inline-start: 2px;
3869        padding-inline-end: 2px;
3870      }
3871    "#,
3872      indoc! {r#"
3873      .foo {
3874        padding-inline-start: 2px;
3875        padding-inline-end: 2px;
3876      }
3877    "#
3878      },
3879      Browsers {
3880        safari: Some(13 << 16),
3881        ..Browsers::default()
3882      },
3883    );
3884
3885    prefix_test(
3886      r#"
3887      .foo {
3888        padding-inline-start: 2px;
3889        padding-inline-end: 2px;
3890      }
3891    "#,
3892      indoc! {r#"
3893      .foo {
3894        padding-inline: 2px;
3895      }
3896    "#
3897      },
3898      Browsers {
3899        safari: Some(15 << 16),
3900        ..Browsers::default()
3901      },
3902    );
3903  }
3904
3905  #[test]
3906  fn test_scroll_padding() {
3907    prefix_test(
3908      r#"
3909      .foo {
3910        scroll-padding-inline: 2px;
3911      }
3912    "#,
3913      indoc! {r#"
3914      .foo {
3915        scroll-padding-inline: 2px;
3916      }
3917    "#
3918      },
3919      Browsers {
3920        safari: Some(8 << 16),
3921        ..Browsers::default()
3922      },
3923    );
3924  }
3925
3926  #[test]
3927  fn test_size() {
3928    prefix_test(
3929      r#"
3930      .foo {
3931        block-size: 25px;
3932        inline-size: 25px;
3933        min-block-size: 25px;
3934        min-inline-size: 25px;
3935      }
3936    "#,
3937      indoc! {r#"
3938      .foo {
3939        height: 25px;
3940        min-height: 25px;
3941        width: 25px;
3942        min-width: 25px;
3943      }
3944    "#},
3945      Browsers {
3946        safari: Some(8 << 16),
3947        ..Browsers::default()
3948      },
3949    );
3950
3951    prefix_test(
3952      r#"
3953      .foo {
3954        block-size: 25px;
3955        min-block-size: 25px;
3956        inline-size: 25px;
3957        min-inline-size: 25px;
3958      }
3959    "#,
3960      indoc! {r#"
3961      .foo {
3962        block-size: 25px;
3963        min-block-size: 25px;
3964        inline-size: 25px;
3965        min-inline-size: 25px;
3966      }
3967    "#},
3968      Browsers {
3969        safari: Some(14 << 16),
3970        ..Browsers::default()
3971      },
3972    );
3973
3974    prefix_test(
3975      r#"
3976      .foo {
3977        block-size: var(--size);
3978        min-block-size: var(--size);
3979        inline-size: var(--size);
3980        min-inline-size: var(--size);
3981      }
3982    "#,
3983      indoc! {r#"
3984      .foo {
3985        height: var(--size);
3986        min-height: var(--size);
3987        width: var(--size);
3988        min-width: var(--size);
3989      }
3990    "#},
3991      Browsers {
3992        safari: Some(8 << 16),
3993        ..Browsers::default()
3994      },
3995    );
3996
3997    for (in_prop, out_prop) in [
3998      ("width", "width"),
3999      ("height", "height"),
4000      ("block-size", "height"),
4001      ("inline-size", "width"),
4002      ("min-width", "min-width"),
4003      ("min-height", "min-height"),
4004      ("min-block-size", "min-height"),
4005      ("min-inline-size", "min-width"),
4006      ("max-width", "max-width"),
4007      ("max-height", "max-height"),
4008      ("max-block-size", "max-height"),
4009      ("max-inline-size", "max-width"),
4010    ] {
4011      prefix_test(
4012        &format!(
4013          r#"
4014        .foo {{
4015          {}: stretch;
4016        }}
4017      "#,
4018          in_prop
4019        ),
4020        &format!(
4021          indoc! {r#"
4022        .foo {{
4023          {}: -webkit-fill-available;
4024          {}: -moz-available;
4025          {}: stretch;
4026        }}
4027      "#},
4028          out_prop, out_prop, out_prop
4029        ),
4030        Browsers {
4031          safari: Some(8 << 16),
4032          firefox: Some(4 << 16),
4033          ..Browsers::default()
4034        },
4035      );
4036
4037      prefix_test(
4038        &format!(
4039          r#"
4040        .foo {{
4041          {}: -webkit-fill-available;
4042        }}
4043      "#,
4044          in_prop
4045        ),
4046        &format!(
4047          indoc! {r#"
4048        .foo {{
4049          {}: -webkit-fill-available;
4050        }}
4051      "#},
4052          out_prop
4053        ),
4054        Browsers {
4055          safari: Some(8 << 16),
4056          firefox: Some(4 << 16),
4057          ..Browsers::default()
4058        },
4059      );
4060
4061      prefix_test(
4062        &format!(
4063          r#"
4064        .foo {{
4065          {}: 100vw;
4066          {}: -webkit-fill-available;
4067        }}
4068      "#,
4069          in_prop, in_prop
4070        ),
4071        &format!(
4072          indoc! {r#"
4073        .foo {{
4074          {}: 100vw;
4075          {}: -webkit-fill-available;
4076        }}
4077      "#},
4078          out_prop, out_prop
4079        ),
4080        Browsers {
4081          safari: Some(8 << 16),
4082          firefox: Some(4 << 16),
4083          ..Browsers::default()
4084        },
4085      );
4086
4087      prefix_test(
4088        &format!(
4089          r#"
4090        .foo {{
4091          {}: fit-content;
4092        }}
4093      "#,
4094          in_prop
4095        ),
4096        &format!(
4097          indoc! {r#"
4098        .foo {{
4099          {}: -webkit-fit-content;
4100          {}: -moz-fit-content;
4101          {}: fit-content;
4102        }}
4103      "#},
4104          out_prop, out_prop, out_prop
4105        ),
4106        Browsers {
4107          safari: Some(8 << 16),
4108          firefox: Some(4 << 16),
4109          ..Browsers::default()
4110        },
4111      );
4112
4113      prefix_test(
4114        &format!(
4115          r#"
4116        .foo {{
4117          {}: fit-content(50%);
4118        }}
4119      "#,
4120          in_prop
4121        ),
4122        &format!(
4123          indoc! {r#"
4124        .foo {{
4125          {}: fit-content(50%);
4126        }}
4127      "#},
4128          out_prop
4129        ),
4130        Browsers {
4131          safari: Some(8 << 16),
4132          firefox: Some(4 << 16),
4133          ..Browsers::default()
4134        },
4135      );
4136
4137      prefix_test(
4138        &format!(
4139          r#"
4140        .foo {{
4141          {}: min-content;
4142        }}
4143      "#,
4144          in_prop
4145        ),
4146        &format!(
4147          indoc! {r#"
4148        .foo {{
4149          {}: -webkit-min-content;
4150          {}: -moz-min-content;
4151          {}: min-content;
4152        }}
4153      "#},
4154          out_prop, out_prop, out_prop
4155        ),
4156        Browsers {
4157          safari: Some(8 << 16),
4158          firefox: Some(4 << 16),
4159          ..Browsers::default()
4160        },
4161      );
4162
4163      prefix_test(
4164        &format!(
4165          r#"
4166        .foo {{
4167          {}: max-content;
4168        }}
4169      "#,
4170          in_prop
4171        ),
4172        &format!(
4173          indoc! {r#"
4174        .foo {{
4175          {}: -webkit-max-content;
4176          {}: -moz-max-content;
4177          {}: max-content;
4178        }}
4179      "#},
4180          out_prop, out_prop, out_prop
4181        ),
4182        Browsers {
4183          safari: Some(8 << 16),
4184          firefox: Some(4 << 16),
4185          ..Browsers::default()
4186        },
4187      );
4188
4189      prefix_test(
4190        &format!(
4191          r#"
4192        .foo {{
4193          {}: 100%;
4194          {}: max-content;
4195        }}
4196      "#,
4197          in_prop, in_prop
4198        ),
4199        &format!(
4200          indoc! {r#"
4201        .foo {{
4202          {}: 100%;
4203          {}: max-content;
4204        }}
4205      "#},
4206          out_prop, out_prop
4207        ),
4208        Browsers {
4209          safari: Some(8 << 16),
4210          firefox: Some(4 << 16),
4211          ..Browsers::default()
4212        },
4213      );
4214
4215      prefix_test(
4216        &format!(
4217          r#"
4218        .foo {{
4219          {}: var(--fallback);
4220          {}: max-content;
4221        }}
4222      "#,
4223          in_prop, in_prop
4224        ),
4225        &format!(
4226          indoc! {r#"
4227        .foo {{
4228          {}: var(--fallback);
4229          {}: max-content;
4230        }}
4231      "#},
4232          out_prop, out_prop
4233        ),
4234        Browsers {
4235          safari: Some(8 << 16),
4236          firefox: Some(4 << 16),
4237          ..Browsers::default()
4238        },
4239      );
4240    }
4241
4242    minify_test(".foo { aspect-ratio: auto }", ".foo{aspect-ratio:auto}");
4243    minify_test(".foo { aspect-ratio: 2 / 3 }", ".foo{aspect-ratio:2/3}");
4244    minify_test(".foo { aspect-ratio: auto 2 / 3 }", ".foo{aspect-ratio:auto 2/3}");
4245    minify_test(".foo { aspect-ratio: 2 / 3 auto }", ".foo{aspect-ratio:auto 2/3}");
4246
4247    minify_test(
4248      ".foo { width: 200px; width: var(--foo); }",
4249      ".foo{width:200px;width:var(--foo)}",
4250    );
4251    minify_test(
4252      ".foo { width: var(--foo); width: 200px; }",
4253      ".foo{width:var(--foo);width:200px}",
4254    );
4255  }
4256
4257  #[test]
4258  pub fn test_background() {
4259    test(
4260      r#"
4261      .foo {
4262        background: url(img.png);
4263        background-position-x: 20px;
4264        background-position-y: 10px;
4265        background-size: 50px 100px;
4266        background-repeat: repeat no-repeat;
4267      }
4268    "#,
4269      indoc! {r#"
4270      .foo {
4271        background: url("img.png") 20px 10px / 50px 100px repeat-x;
4272      }
4273    "#
4274      },
4275    );
4276
4277    test(
4278      r#"
4279      .foo {
4280        background-color: red;
4281        background-position: 0% 0%;
4282        background-size: auto;
4283        background-repeat: repeat;
4284        background-clip: border-box;
4285        background-origin: padding-box;
4286        background-attachment: scroll;
4287        background-image: none
4288      }
4289    "#,
4290      indoc! {r#"
4291      .foo {
4292        background: red;
4293      }
4294    "#
4295      },
4296    );
4297
4298    test(
4299      r#"
4300      .foo {
4301        background-color: gray;
4302        background-position: 40% 50%;
4303        background-size: 10em auto;
4304        background-repeat: round;
4305        background-clip: border-box;
4306        background-origin: border-box;
4307        background-attachment: fixed;
4308        background-image: url('chess.png');
4309      }
4310    "#,
4311      indoc! {r#"
4312      .foo {
4313        background: gray url("chess.png") 40% / 10em round fixed border-box;
4314      }
4315    "#
4316      },
4317    );
4318
4319    test(
4320      r#"
4321      .foo {
4322        background: url(img.png), url(test.jpg) gray;
4323        background-position-x: right 20px, 10px;
4324        background-position-y: top 20px, 15px;
4325        background-size: 50px 50px, auto;
4326        background-repeat: repeat no-repeat, no-repeat;
4327      }
4328    "#,
4329      indoc! {r#"
4330      .foo {
4331        background: url("img.png") right 20px top 20px / 50px 50px repeat-x, gray url("test.jpg") 10px 15px no-repeat;
4332      }
4333    "#
4334      },
4335    );
4336
4337    minify_test(
4338      r#"
4339      .foo {
4340        background-position: center center;
4341      }
4342    "#,
4343      indoc! {".foo{background-position:50%}"
4344      },
4345    );
4346
4347    test(
4348      r#"
4349      .foo {
4350        background: url(img.png) gray;
4351        background-clip: content-box;
4352        -webkit-background-clip: text;
4353      }
4354    "#,
4355      indoc! {r#"
4356      .foo {
4357        background: gray url("img.png") padding-box content-box;
4358        -webkit-background-clip: text;
4359      }
4360    "#
4361      },
4362    );
4363
4364    test(
4365      r#"
4366      .foo {
4367        background: url(img.png) gray;
4368        -webkit-background-clip: text;
4369        background-clip: content-box;
4370      }
4371    "#,
4372      indoc! {r#"
4373      .foo {
4374        background: gray url("img.png");
4375        -webkit-background-clip: text;
4376        background-clip: content-box;
4377      }
4378    "#
4379      },
4380    );
4381
4382    test(
4383      r#"
4384      .foo {
4385        background: url(img.png) gray;
4386        background-position: var(--pos);
4387      }
4388    "#,
4389      indoc! {r#"
4390      .foo {
4391        background: gray url("img.png");
4392        background-position: var(--pos);
4393      }
4394    "#
4395      },
4396    );
4397
4398    minify_test(
4399      ".foo { background-position: bottom left }",
4400      ".foo{background-position:0 100%}",
4401    );
4402    minify_test(
4403      ".foo { background-position: left 10px center }",
4404      ".foo{background-position:10px}",
4405    );
4406    minify_test(
4407      ".foo { background-position: right 10px center }",
4408      ".foo{background-position:right 10px center}",
4409    );
4410    minify_test(
4411      ".foo { background-position: center top 10px }",
4412      ".foo{background-position:50% 10px}",
4413    );
4414    minify_test(
4415      ".foo { background-position: center bottom 10px }",
4416      ".foo{background-position:center bottom 10px}",
4417    );
4418    minify_test(
4419      ".foo { background-position: center 10px }",
4420      ".foo{background-position:50% 10px}",
4421    );
4422    minify_test(
4423      ".foo { background-position: right 10px top 20px }",
4424      ".foo{background-position:right 10px top 20px}",
4425    );
4426    minify_test(
4427      ".foo { background-position: left 10px top 20px }",
4428      ".foo{background-position:10px 20px}",
4429    );
4430    minify_test(
4431      ".foo { background-position: left 10px bottom 20px }",
4432      ".foo{background-position:left 10px bottom 20px}",
4433    );
4434    minify_test(
4435      ".foo { background-position: left 10px top }",
4436      ".foo{background-position:10px 0}",
4437    );
4438    minify_test(
4439      ".foo { background-position: bottom right }",
4440      ".foo{background-position:100% 100%}",
4441    );
4442    minify_test(
4443      ".foo { background-position: center top }",
4444      ".foo{background-position:top}",
4445    );
4446    minify_test(
4447      ".foo { background-position: center bottom }",
4448      ".foo{background-position:bottom}",
4449    );
4450    minify_test(
4451      ".foo { background-position: left center }",
4452      ".foo{background-position:0}",
4453    );
4454    minify_test(
4455      ".foo { background-position: right center }",
4456      ".foo{background-position:100%}",
4457    );
4458    minify_test(
4459      ".foo { background-position: 20px center }",
4460      ".foo{background-position:20px}",
4461    );
4462
4463    minify_test(
4464      ".foo { background: url('img-sprite.png') no-repeat bottom right }",
4465      ".foo{background:url(img-sprite.png) 100% 100% no-repeat}",
4466    );
4467    minify_test(".foo { background: transparent }", ".foo{background:0 0}");
4468
4469    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\")}");
4470
4471    test(
4472      r#"
4473      .foo {
4474        background: url(img.png);
4475        background-clip: text;
4476      }
4477    "#,
4478      indoc! {r#"
4479      .foo {
4480        background: url("img.png") text;
4481      }
4482    "#
4483      },
4484    );
4485
4486    prefix_test(
4487      r#"
4488      .foo {
4489        background: url(img.png);
4490        background-clip: text;
4491      }
4492    "#,
4493      indoc! {r#"
4494      .foo {
4495        background: url("img.png");
4496        -webkit-background-clip: text;
4497        background-clip: text;
4498      }
4499    "#
4500      },
4501      Browsers {
4502        safari: Some(8 << 16),
4503        ..Browsers::default()
4504      },
4505    );
4506
4507    prefix_test(
4508      r#"
4509      .foo {
4510        background: url(img.png);
4511        background-clip: text;
4512      }
4513    "#,
4514      indoc! {r#"
4515      .foo {
4516        background: url("img.png") text;
4517      }
4518    "#
4519      },
4520      Browsers {
4521        safari: Some(14 << 16),
4522        ..Browsers::default()
4523      },
4524    );
4525
4526    prefix_test(
4527      r#"
4528      .foo {
4529        background: url(img.png) text;
4530      }
4531    "#,
4532      indoc! {r#"
4533      .foo {
4534        background: url("img.png");
4535        -webkit-background-clip: text;
4536        background-clip: text;
4537      }
4538    "#
4539      },
4540      Browsers {
4541        chrome: Some(45 << 16),
4542        ..Browsers::default()
4543      },
4544    );
4545
4546    prefix_test(
4547      r#"
4548      .foo {
4549        background: url(img.png);
4550        -webkit-background-clip: text;
4551      }
4552    "#,
4553      indoc! {r#"
4554      .foo {
4555        background: url("img.png");
4556        -webkit-background-clip: text;
4557      }
4558    "#
4559      },
4560      Browsers {
4561        chrome: Some(45 << 16),
4562        ..Browsers::default()
4563      },
4564    );
4565
4566    prefix_test(
4567      r#"
4568      .foo {
4569        background: url(img.png);
4570        background-clip: text;
4571      }
4572    "#,
4573      indoc! {r#"
4574      .foo {
4575        background: url("img.png");
4576        -webkit-background-clip: text;
4577        background-clip: text;
4578      }
4579    "#
4580      },
4581      Browsers {
4582        safari: Some(14 << 16),
4583        chrome: Some(95 << 16),
4584        ..Browsers::default()
4585      },
4586    );
4587
4588    prefix_test(
4589      r#"
4590      .foo {
4591        background-image: url(img.png);
4592        background-clip: text;
4593      }
4594    "#,
4595      indoc! {r#"
4596      .foo {
4597        background-image: url("img.png");
4598        -webkit-background-clip: text;
4599        background-clip: text;
4600      }
4601    "#
4602      },
4603      Browsers {
4604        safari: Some(8 << 16),
4605        ..Browsers::default()
4606      },
4607    );
4608
4609    prefix_test(
4610      r#"
4611      .foo {
4612        -webkit-background-clip: text;
4613        background-clip: text;
4614      }
4615    "#,
4616      indoc! {r#"
4617      .foo {
4618        -webkit-background-clip: text;
4619        background-clip: text;
4620      }
4621    "#
4622      },
4623      Browsers {
4624        chrome: Some(45 << 16),
4625        ..Browsers::default()
4626      },
4627    );
4628
4629    prefix_test(
4630      r#"
4631      .foo {
4632        background-image: url(img.png);
4633        background-clip: text;
4634      }
4635    "#,
4636      indoc! {r#"
4637      .foo {
4638        background-image: url("img.png");
4639        background-clip: text;
4640      }
4641    "#
4642      },
4643      Browsers {
4644        safari: Some(14 << 16),
4645        ..Browsers::default()
4646      },
4647    );
4648
4649    minify_test(".foo { background: none center }", ".foo{background:50%}");
4650    minify_test(".foo { background: none }", ".foo{background:0 0}");
4651
4652    prefix_test(
4653      r#"
4654      .foo {
4655        background: lab(51.5117% 43.3777 -29.0443);
4656      }
4657    "#,
4658      indoc! {r#"
4659      .foo {
4660        background: #af5cae;
4661        background: lab(51.5117% 43.3777 -29.0443);
4662      }
4663    "#
4664      },
4665      Browsers {
4666        chrome: Some(95 << 16),
4667        safari: Some(15 << 16),
4668        ..Browsers::default()
4669      },
4670    );
4671
4672    prefix_test(
4673      r#"
4674      .foo {
4675        background: lab(51.5117% 43.3777 -29.0443) url(foo.png);
4676      }
4677    "#,
4678      indoc! {r#"
4679      .foo {
4680        background: #af5cae url("foo.png");
4681        background: lab(51.5117% 43.3777 -29.0443) url("foo.png");
4682      }
4683    "#
4684      },
4685      Browsers {
4686        chrome: Some(95 << 16),
4687        safari: Some(15 << 16),
4688        ..Browsers::default()
4689      },
4690    );
4691
4692    prefix_test(
4693      r#"
4694      .foo {
4695        background: lab(51.5117% 43.3777 -29.0443) linear-gradient(lab(52.2319% 40.1449 59.9171), lab(47.7776% -34.2947 -7.65904));
4696      }
4697    "#,
4698      indoc! {r#"
4699      .foo {
4700        background: #af5cae linear-gradient(#c65d07, #00807c);
4701        background: lab(51.5117% 43.3777 -29.0443) linear-gradient(lab(52.2319% 40.1449 59.9171), lab(47.7776% -34.2947 -7.65904));
4702      }
4703    "#
4704      },
4705      Browsers {
4706        chrome: Some(95 << 16),
4707        safari: Some(15 << 16),
4708        ..Browsers::default()
4709      },
4710    );
4711
4712    test(
4713      ".foo { background: calc(var(--v) / 0.3)",
4714      indoc! {r#"
4715      .foo {
4716        background: calc(var(--v) / .3);
4717      }
4718    "#},
4719    );
4720
4721    prefix_test(
4722      r#"
4723      .foo {
4724        background-color: #4263eb;
4725        background-color: color(display-p3 0 .5 1);
4726      }
4727    "#,
4728      indoc! {r#"
4729      .foo {
4730        background-color: #4263eb;
4731        background-color: color(display-p3 0 .5 1);
4732      }
4733    "#
4734      },
4735      Browsers {
4736        chrome: Some(99 << 16),
4737        ..Browsers::default()
4738      },
4739    );
4740    prefix_test(
4741      r#"
4742      .foo {
4743        background-color: #4263eb;
4744        background-color: color(display-p3 0 .5 1);
4745      }
4746    "#,
4747      indoc! {r#"
4748      .foo {
4749        background-color: color(display-p3 0 .5 1);
4750      }
4751    "#
4752      },
4753      Browsers {
4754        safari: Some(16 << 16),
4755        ..Browsers::default()
4756      },
4757    );
4758    prefix_test(
4759      r#"
4760      .foo {
4761        background-image: linear-gradient(red, green);
4762        background-image: linear-gradient(lch(50% 132 50), lch(50% 130 150));
4763      }
4764    "#,
4765      indoc! {r#"
4766      .foo {
4767        background-image: linear-gradient(red, green);
4768        background-image: linear-gradient(lch(50% 132 50), lch(50% 130 150));
4769      }
4770    "#
4771      },
4772      Browsers {
4773        chrome: Some(99 << 16),
4774        ..Browsers::default()
4775      },
4776    );
4777    prefix_test(
4778      r#"
4779      .foo {
4780        background-image: linear-gradient(red, green);
4781        background-image: linear-gradient(lch(50% 132 50), lch(50% 130 150));
4782      }
4783    "#,
4784      indoc! {r#"
4785      .foo {
4786        background-image: linear-gradient(lch(50% 132 50), lch(50% 130 150));
4787      }
4788    "#
4789      },
4790      Browsers {
4791        safari: Some(16 << 16),
4792        ..Browsers::default()
4793      },
4794    );
4795    prefix_test(
4796      r#"
4797      .foo {
4798        background: #4263eb;
4799        background: color(display-p3 0 .5 1);
4800      }
4801    "#,
4802      indoc! {r#"
4803      .foo {
4804        background: #4263eb;
4805        background: color(display-p3 0 .5 1);
4806      }
4807    "#
4808      },
4809      Browsers {
4810        chrome: Some(99 << 16),
4811        ..Browsers::default()
4812      },
4813    );
4814    prefix_test(
4815      r#"
4816      .foo {
4817        background: #4263eb;
4818        background: color(display-p3 0 .5 1);
4819      }
4820    "#,
4821      indoc! {r#"
4822      .foo {
4823        background: color(display-p3 0 .5 1);
4824      }
4825    "#
4826      },
4827      Browsers {
4828        safari: Some(16 << 16),
4829        ..Browsers::default()
4830      },
4831    );
4832    prefix_test(
4833      r#"
4834      .foo {
4835        background: linear-gradient(red, green);
4836        background: linear-gradient(lch(50% 132 50), lch(50% 130 150));
4837      }
4838    "#,
4839      indoc! {r#"
4840      .foo {
4841        background: linear-gradient(red, green);
4842        background: linear-gradient(lch(50% 132 50), lch(50% 130 150));
4843      }
4844    "#
4845      },
4846      Browsers {
4847        chrome: Some(99 << 16),
4848        ..Browsers::default()
4849      },
4850    );
4851    prefix_test(
4852      r#"
4853      .foo {
4854        background: red;
4855        background: linear-gradient(lch(50% 132 50), lch(50% 130 150));
4856      }
4857    "#,
4858      indoc! {r#"
4859      .foo {
4860        background: red;
4861        background: linear-gradient(lch(50% 132 50), lch(50% 130 150));
4862      }
4863    "#
4864      },
4865      Browsers {
4866        chrome: Some(99 << 16),
4867        ..Browsers::default()
4868      },
4869    );
4870    prefix_test(
4871      r#"
4872      .foo {
4873        background: linear-gradient(red, green);
4874        background: linear-gradient(lch(50% 132 50), lch(50% 130 150));
4875      }
4876    "#,
4877      indoc! {r#"
4878      .foo {
4879        background: linear-gradient(lch(50% 132 50), lch(50% 130 150));
4880      }
4881    "#
4882      },
4883      Browsers {
4884        safari: Some(16 << 16),
4885        ..Browsers::default()
4886      },
4887    );
4888    prefix_test(
4889      r#"
4890      .foo {
4891        background: var(--fallback);
4892        background: linear-gradient(lch(50% 132 50), lch(50% 130 150));
4893      }
4894    "#,
4895      indoc! {r#"
4896      .foo {
4897        background: var(--fallback);
4898        background: linear-gradient(lch(50% 132 50), lch(50% 130 150));
4899      }
4900    "#
4901      },
4902      Browsers {
4903        chrome: Some(99 << 16),
4904        ..Browsers::default()
4905      },
4906    );
4907    prefix_test(
4908      r#"
4909      .foo {
4910        background: red url(foo.png);
4911        background: lch(50% 132 50) url(foo.png);
4912      }
4913    "#,
4914      indoc! {r#"
4915      .foo {
4916        background: red url("foo.png");
4917        background: lch(50% 132 50) url("foo.png");
4918      }
4919    "#
4920      },
4921      Browsers {
4922        chrome: Some(99 << 16),
4923        ..Browsers::default()
4924      },
4925    );
4926  }
4927
4928  #[test]
4929  pub fn test_flex() {
4930    test(
4931      r#"
4932      .foo {
4933        flex-direction: column;
4934        flex-wrap: wrap;
4935      }
4936    "#,
4937      indoc! {r#"
4938      .foo {
4939        flex-flow: column wrap;
4940      }
4941    "#
4942      },
4943    );
4944
4945    test(
4946      r#"
4947      .foo {
4948        flex-direction: row;
4949        flex-wrap: wrap;
4950      }
4951    "#,
4952      indoc! {r#"
4953      .foo {
4954        flex-flow: wrap;
4955      }
4956    "#
4957      },
4958    );
4959
4960    test(
4961      r#"
4962      .foo {
4963        flex-direction: row;
4964        flex-wrap: nowrap;
4965      }
4966    "#,
4967      indoc! {r#"
4968      .foo {
4969        flex-flow: row;
4970      }
4971    "#
4972      },
4973    );
4974
4975    test(
4976      r#"
4977      .foo {
4978        flex-direction: column;
4979        flex-wrap: nowrap;
4980      }
4981    "#,
4982      indoc! {r#"
4983      .foo {
4984        flex-flow: column;
4985      }
4986    "#
4987      },
4988    );
4989
4990    test(
4991      r#"
4992      .foo {
4993        flex-grow: 1;
4994        flex-shrink: 1;
4995        flex-basis: 0%;
4996      }
4997    "#,
4998      indoc! {r#"
4999      .foo {
5000        flex: 1;
5001      }
5002    "#
5003      },
5004    );
5005
5006    test(
5007      r#"
5008      .foo {
5009        flex-grow: 1;
5010        flex-shrink: 1;
5011        flex-basis: 0;
5012      }
5013    "#,
5014      indoc! {r#"
5015      .foo {
5016        flex: 1 1 0;
5017      }
5018    "#
5019      },
5020    );
5021
5022    test(
5023      r#"
5024      .foo {
5025        flex-grow: 1;
5026        flex-shrink: 1;
5027        flex-basis: 0px;
5028      }
5029    "#,
5030      indoc! {r#"
5031      .foo {
5032        flex: 1 1 0;
5033      }
5034    "#
5035      },
5036    );
5037
5038    test(
5039      r#"
5040      .foo {
5041        flex-grow: 1;
5042        flex-shrink: 2;
5043        flex-basis: 0%;
5044      }
5045    "#,
5046      indoc! {r#"
5047      .foo {
5048        flex: 1 2;
5049      }
5050    "#
5051      },
5052    );
5053
5054    test(
5055      r#"
5056      .foo {
5057        flex-grow: 2;
5058        flex-shrink: 1;
5059        flex-basis: 0%;
5060      }
5061    "#,
5062      indoc! {r#"
5063      .foo {
5064        flex: 2;
5065      }
5066    "#
5067      },
5068    );
5069
5070    test(
5071      r#"
5072      .foo {
5073        flex-grow: 2;
5074        flex-shrink: 2;
5075        flex-basis: 0%;
5076      }
5077    "#,
5078      indoc! {r#"
5079      .foo {
5080        flex: 2 2;
5081      }
5082    "#
5083      },
5084    );
5085
5086    test(
5087      r#"
5088      .foo {
5089        flex-grow: 1;
5090        flex-shrink: 1;
5091        flex-basis: 10px;
5092      }
5093    "#,
5094      indoc! {r#"
5095      .foo {
5096        flex: 10px;
5097      }
5098    "#
5099      },
5100    );
5101
5102    test(
5103      r#"
5104      .foo {
5105        flex-grow: 2;
5106        flex-shrink: 1;
5107        flex-basis: 10px;
5108      }
5109    "#,
5110      indoc! {r#"
5111      .foo {
5112        flex: 2 10px;
5113      }
5114    "#
5115      },
5116    );
5117
5118    test(
5119      r#"
5120      .foo {
5121        flex-grow: 1;
5122        flex-shrink: 0;
5123        flex-basis: 0%;
5124      }
5125    "#,
5126      indoc! {r#"
5127      .foo {
5128        flex: 1 0;
5129      }
5130    "#
5131      },
5132    );
5133
5134    test(
5135      r#"
5136      .foo {
5137        flex-grow: 1;
5138        flex-shrink: 0;
5139        flex-basis: auto;
5140      }
5141    "#,
5142      indoc! {r#"
5143      .foo {
5144        flex: 1 0 auto;
5145      }
5146    "#
5147      },
5148    );
5149
5150    test(
5151      r#"
5152      .foo {
5153        flex-grow: 1;
5154        flex-shrink: 1;
5155        flex-basis: auto;
5156      }
5157    "#,
5158      indoc! {r#"
5159      .foo {
5160        flex: auto;
5161      }
5162    "#
5163      },
5164    );
5165
5166    test(
5167      r#"
5168      .foo {
5169        flex: 0 0;
5170        flex-grow: 1;
5171      }
5172    "#,
5173      indoc! {r#"
5174      .foo {
5175        flex: 1 0;
5176      }
5177    "#
5178      },
5179    );
5180
5181    test(
5182      r#"
5183      .foo {
5184        flex: 0 0;
5185        flex-grow: var(--grow);
5186      }
5187    "#,
5188      indoc! {r#"
5189      .foo {
5190        flex: 0 0;
5191        flex-grow: var(--grow);
5192      }
5193    "#
5194      },
5195    );
5196
5197    test(
5198      r#"
5199      .foo {
5200        align-content: center;
5201        justify-content: center;
5202      }
5203    "#,
5204      indoc! {r#"
5205      .foo {
5206        place-content: center;
5207      }
5208    "#
5209      },
5210    );
5211
5212    test(
5213      r#"
5214      .foo {
5215        align-content: first baseline;
5216        justify-content: safe right;
5217      }
5218    "#,
5219      indoc! {r#"
5220      .foo {
5221        place-content: baseline safe right;
5222      }
5223    "#
5224      },
5225    );
5226
5227    test(
5228      r#"
5229      .foo {
5230        place-content: first baseline unsafe left;
5231      }
5232    "#,
5233      indoc! {r#"
5234      .foo {
5235        place-content: baseline unsafe left;
5236      }
5237    "#
5238      },
5239    );
5240
5241    test(
5242      r#"
5243      .foo {
5244        place-content: center center;
5245      }
5246    "#,
5247      indoc! {r#"
5248      .foo {
5249        place-content: center;
5250      }
5251    "#
5252      },
5253    );
5254
5255    test(
5256      r#"
5257      .foo {
5258        align-self: center;
5259        justify-self: center;
5260      }
5261    "#,
5262      indoc! {r#"
5263      .foo {
5264        place-self: center;
5265      }
5266    "#
5267      },
5268    );
5269
5270    test(
5271      r#"
5272      .foo {
5273        align-self: center;
5274        justify-self: unsafe left;
5275      }
5276    "#,
5277      indoc! {r#"
5278      .foo {
5279        place-self: center unsafe left;
5280      }
5281    "#
5282      },
5283    );
5284
5285    test(
5286      r#"
5287      .foo {
5288        align-items: center;
5289        justify-items: center;
5290      }
5291    "#,
5292      indoc! {r#"
5293      .foo {
5294        place-items: center;
5295      }
5296    "#
5297      },
5298    );
5299
5300    test(
5301      r#"
5302      .foo {
5303        align-items: center;
5304        justify-items: legacy left;
5305      }
5306    "#,
5307      indoc! {r#"
5308      .foo {
5309        place-items: center legacy left;
5310      }
5311    "#
5312      },
5313    );
5314
5315    test(
5316      r#"
5317      .foo {
5318        place-items: center;
5319        justify-items: var(--justify);
5320      }
5321    "#,
5322      indoc! {r#"
5323      .foo {
5324        place-items: center;
5325        justify-items: var(--justify);
5326      }
5327    "#
5328      },
5329    );
5330
5331    test(
5332      r#"
5333      .foo {
5334        row-gap: 10px;
5335        column-gap: 20px;
5336      }
5337    "#,
5338      indoc! {r#"
5339      .foo {
5340        gap: 10px 20px;
5341      }
5342    "#
5343      },
5344    );
5345
5346    test(
5347      r#"
5348      .foo {
5349        row-gap: 10px;
5350        column-gap: 10px;
5351      }
5352    "#,
5353      indoc! {r#"
5354      .foo {
5355        gap: 10px;
5356      }
5357    "#
5358      },
5359    );
5360
5361    test(
5362      r#"
5363      .foo {
5364        gap: 10px;
5365        column-gap: 20px;
5366      }
5367    "#,
5368      indoc! {r#"
5369      .foo {
5370        gap: 10px 20px;
5371      }
5372    "#
5373      },
5374    );
5375
5376    test(
5377      r#"
5378      .foo {
5379        column-gap: 20px;
5380        gap: 10px;
5381      }
5382    "#,
5383      indoc! {r#"
5384      .foo {
5385        gap: 10px;
5386      }
5387    "#
5388      },
5389    );
5390
5391    test(
5392      r#"
5393      .foo {
5394        row-gap: normal;
5395        column-gap: 20px;
5396      }
5397    "#,
5398      indoc! {r#"
5399      .foo {
5400        gap: normal 20px;
5401      }
5402    "#
5403      },
5404    );
5405
5406    test(
5407      r#"
5408      .foo {
5409        -webkit-flex-grow: 1;
5410        -webkit-flex-shrink: 1;
5411        -webkit-flex-basis: auto;
5412      }
5413    "#,
5414      indoc! {r#"
5415      .foo {
5416        -webkit-flex: auto;
5417      }
5418    "#
5419      },
5420    );
5421    test(
5422      r#"
5423      .foo {
5424        -webkit-flex-grow: 1;
5425        -webkit-flex-shrink: 1;
5426        -webkit-flex-basis: auto;
5427        flex-grow: 1;
5428        flex-shrink: 1;
5429        flex-basis: auto;
5430      }
5431    "#,
5432      indoc! {r#"
5433      .foo {
5434        -webkit-flex: auto;
5435        flex: auto;
5436      }
5437    "#
5438      },
5439    );
5440    prefix_test(
5441      r#"
5442      .foo {
5443        -webkit-box-orient: horizontal;
5444        -webkit-box-direction: normal;
5445        flex-direction: row;
5446      }
5447    "#,
5448      indoc! {r#"
5449      .foo {
5450        -webkit-box-orient: horizontal;
5451        -webkit-box-direction: normal;
5452        -webkit-flex-direction: row;
5453        flex-direction: row;
5454      }
5455    "#},
5456      Browsers {
5457        safari: Some(4 << 16),
5458        ..Browsers::default()
5459      },
5460    );
5461    prefix_test(
5462      r#"
5463      .foo {
5464        flex-direction: row;
5465      }
5466    "#,
5467      indoc! {r#"
5468      .foo {
5469        -webkit-box-orient: horizontal;
5470        -moz-box-orient: horizontal;
5471        -webkit-box-direction: normal;
5472        -moz-box-direction: normal;
5473        -webkit-flex-direction: row;
5474        -ms-flex-direction: row;
5475        flex-direction: row;
5476      }
5477    "#},
5478      Browsers {
5479        safari: Some(4 << 16),
5480        firefox: Some(4 << 16),
5481        ie: Some(10 << 16),
5482        ..Browsers::default()
5483      },
5484    );
5485    prefix_test(
5486      r#"
5487      .foo {
5488        -webkit-box-orient: horizontal;
5489        -webkit-box-direction: normal;
5490        -moz-box-orient: horizontal;
5491        -moz-box-direction: normal;
5492        -webkit-flex-direction: row;
5493        -ms-flex-direction: row;
5494        flex-direction: row;
5495      }
5496    "#,
5497      indoc! {r#"
5498      .foo {
5499        flex-direction: row;
5500      }
5501    "#},
5502      Browsers {
5503        safari: Some(14 << 16),
5504        ..Browsers::default()
5505      },
5506    );
5507    prefix_test(
5508      r#"
5509      .foo {
5510        flex-wrap: wrap;
5511      }
5512    "#,
5513      indoc! {r#"
5514      .foo {
5515        -webkit-box-lines: multiple;
5516        -moz-box-lines: multiple;
5517        -webkit-flex-wrap: wrap;
5518        -ms-flex-wrap: wrap;
5519        flex-wrap: wrap;
5520      }
5521    "#},
5522      Browsers {
5523        safari: Some(4 << 16),
5524        firefox: Some(4 << 16),
5525        ie: Some(10 << 16),
5526        ..Browsers::default()
5527      },
5528    );
5529    prefix_test(
5530      r#"
5531      .foo {
5532        -webkit-box-lines: multiple;
5533        -moz-box-lines: multiple;
5534        -webkit-flex-wrap: wrap;
5535        -ms-flex-wrap: wrap;
5536        flex-wrap: wrap;
5537      }
5538    "#,
5539      indoc! {r#"
5540      .foo {
5541        flex-wrap: wrap;
5542      }
5543    "#},
5544      Browsers {
5545        safari: Some(11 << 16),
5546        ..Browsers::default()
5547      },
5548    );
5549    prefix_test(
5550      r#"
5551      .foo {
5552        flex-flow: row wrap;
5553      }
5554    "#,
5555      indoc! {r#"
5556      .foo {
5557        -webkit-box-orient: horizontal;
5558        -moz-box-orient: horizontal;
5559        -webkit-box-direction: normal;
5560        -moz-box-direction: normal;
5561        -webkit-flex-flow: wrap;
5562        -ms-flex-flow: wrap;
5563        flex-flow: wrap;
5564      }
5565    "#},
5566      Browsers {
5567        safari: Some(4 << 16),
5568        firefox: Some(4 << 16),
5569        ie: Some(10 << 16),
5570        ..Browsers::default()
5571      },
5572    );
5573    prefix_test(
5574      r#"
5575      .foo {
5576        -webkit-box-orient: horizontal;
5577        -moz-box-orient: horizontal;
5578        -webkit-box-direction: normal;
5579        -moz-box-direction: normal;
5580        -webkit-flex-flow: wrap;
5581        -ms-flex-flow: wrap;
5582        flex-flow: wrap;
5583      }
5584    "#,
5585      indoc! {r#"
5586      .foo {
5587        flex-flow: wrap;
5588      }
5589    "#},
5590      Browsers {
5591        safari: Some(11 << 16),
5592        ..Browsers::default()
5593      },
5594    );
5595    prefix_test(
5596      r#"
5597      .foo {
5598        flex-grow: 1;
5599      }
5600    "#,
5601      indoc! {r#"
5602      .foo {
5603        -webkit-box-flex: 1;
5604        -moz-box-flex: 1;
5605        -ms-flex-positive: 1;
5606        -webkit-flex-grow: 1;
5607        flex-grow: 1;
5608      }
5609    "#},
5610      Browsers {
5611        safari: Some(4 << 16),
5612        firefox: Some(4 << 16),
5613        ie: Some(10 << 16),
5614        ..Browsers::default()
5615      },
5616    );
5617    prefix_test(
5618      r#"
5619      .foo {
5620        -webkit-box-flex: 1;
5621        -moz-box-flex: 1;
5622        -ms-flex-positive: 1;
5623        -webkit-flex-grow: 1;
5624        flex-grow: 1;
5625      }
5626    "#,
5627      indoc! {r#"
5628      .foo {
5629        flex-grow: 1;
5630      }
5631    "#},
5632      Browsers {
5633        safari: Some(11 << 16),
5634        ..Browsers::default()
5635      },
5636    );
5637    prefix_test(
5638      r#"
5639      .foo {
5640        flex-shrink: 1;
5641      }
5642    "#,
5643      indoc! {r#"
5644      .foo {
5645        -ms-flex-negative: 1;
5646        -webkit-flex-shrink: 1;
5647        flex-shrink: 1;
5648      }
5649    "#},
5650      Browsers {
5651        safari: Some(4 << 16),
5652        firefox: Some(4 << 16),
5653        ie: Some(10 << 16),
5654        ..Browsers::default()
5655      },
5656    );
5657    prefix_test(
5658      r#"
5659      .foo {
5660        -ms-flex-negative: 1;
5661        -webkit-flex-shrink: 1;
5662        flex-shrink: 1;
5663      }
5664    "#,
5665      indoc! {r#"
5666      .foo {
5667        flex-shrink: 1;
5668      }
5669    "#},
5670      Browsers {
5671        safari: Some(11 << 16),
5672        ..Browsers::default()
5673      },
5674    );
5675    prefix_test(
5676      r#"
5677      .foo {
5678        flex-basis: 1px;
5679      }
5680    "#,
5681      indoc! {r#"
5682      .foo {
5683        -ms-flex-preferred-size: 1px;
5684        -webkit-flex-basis: 1px;
5685        flex-basis: 1px;
5686      }
5687    "#},
5688      Browsers {
5689        safari: Some(4 << 16),
5690        firefox: Some(4 << 16),
5691        ie: Some(10 << 16),
5692        ..Browsers::default()
5693      },
5694    );
5695    prefix_test(
5696      r#"
5697      .foo {
5698        -ms-flex-preferred-size: 1px;
5699        -webkit-flex-basis: 1px;
5700        flex-basis: 1px;
5701      }
5702    "#,
5703      indoc! {r#"
5704      .foo {
5705        flex-basis: 1px;
5706      }
5707    "#},
5708      Browsers {
5709        safari: Some(11 << 16),
5710        ..Browsers::default()
5711      },
5712    );
5713    prefix_test(
5714      r#"
5715      .foo {
5716        flex: 1;
5717      }
5718    "#,
5719      indoc! {r#"
5720      .foo {
5721        -webkit-box-flex: 1;
5722        -moz-box-flex: 1;
5723        -webkit-flex: 1;
5724        -ms-flex: 1;
5725        flex: 1;
5726      }
5727    "#},
5728      Browsers {
5729        safari: Some(4 << 16),
5730        firefox: Some(4 << 16),
5731        ie: Some(10 << 16),
5732        ..Browsers::default()
5733      },
5734    );
5735    prefix_test(
5736      r#"
5737      .foo {
5738        -webkit-box-flex: 1;
5739        -moz-box-flex: 1;
5740        -webkit-flex: 1;
5741        -ms-flex: 1;
5742        flex: 1;
5743      }
5744    "#,
5745      indoc! {r#"
5746      .foo {
5747        flex: 1;
5748      }
5749    "#},
5750      Browsers {
5751        safari: Some(11 << 16),
5752        ..Browsers::default()
5753      },
5754    );
5755    prefix_test(
5756      r#"
5757      .foo {
5758        align-content: space-between;
5759      }
5760    "#,
5761      indoc! {r#"
5762      .foo {
5763        -ms-flex-line-pack: justify;
5764        -webkit-align-content: space-between;
5765        align-content: space-between;
5766      }
5767    "#},
5768      Browsers {
5769        safari: Some(4 << 16),
5770        firefox: Some(4 << 16),
5771        ie: Some(10 << 16),
5772        ..Browsers::default()
5773      },
5774    );
5775    prefix_test(
5776      r#"
5777      .foo {
5778        -ms-flex-line-pack: justify;
5779        -webkit-align-content: space-between;
5780        align-content: space-between;
5781      }
5782    "#,
5783      indoc! {r#"
5784      .foo {
5785        align-content: space-between;
5786      }
5787    "#},
5788      Browsers {
5789        safari: Some(11 << 16),
5790        ..Browsers::default()
5791      },
5792    );
5793    prefix_test(
5794      r#"
5795      .foo {
5796        justify-content: space-between;
5797      }
5798    "#,
5799      indoc! {r#"
5800      .foo {
5801        -webkit-box-pack: justify;
5802        -moz-box-pack: justify;
5803        -ms-flex-pack: justify;
5804        -webkit-justify-content: space-between;
5805        justify-content: space-between;
5806      }
5807    "#},
5808      Browsers {
5809        safari: Some(4 << 16),
5810        firefox: Some(4 << 16),
5811        ie: Some(10 << 16),
5812        ..Browsers::default()
5813      },
5814    );
5815    prefix_test(
5816      r#"
5817      .foo {
5818        -webkit-box-pack: justify;
5819        -moz-box-pack: justify;
5820        -ms-flex-pack: justify;
5821        -webkit-justify-content: space-between;
5822        justify-content: space-between;
5823      }
5824    "#,
5825      indoc! {r#"
5826      .foo {
5827        justify-content: space-between;
5828      }
5829    "#},
5830      Browsers {
5831        safari: Some(11 << 16),
5832        ..Browsers::default()
5833      },
5834    );
5835    prefix_test(
5836      r#"
5837      .foo {
5838        place-content: space-between flex-end;
5839      }
5840    "#,
5841      indoc! {r#"
5842      .foo {
5843        -ms-flex-line-pack: justify;
5844        -webkit-box-pack: end;
5845        -moz-box-pack: end;
5846        -ms-flex-pack: end;
5847        -webkit-align-content: space-between;
5848        align-content: space-between;
5849        -webkit-justify-content: flex-end;
5850        justify-content: flex-end;
5851      }
5852    "#},
5853      Browsers {
5854        safari: Some(4 << 16),
5855        firefox: Some(4 << 16),
5856        ie: Some(10 << 16),
5857        ..Browsers::default()
5858      },
5859    );
5860    prefix_test(
5861      r#"
5862      .foo {
5863        -ms-flex-line-pack: justify;
5864        -webkit-box-pack: end;
5865        -moz-box-pack: end;
5866        -ms-flex-pack: end;
5867        -webkit-align-content: space-between;
5868        -webkit-justify-content: flex-end;
5869        place-content: space-between flex-end;
5870      }
5871    "#,
5872      indoc! {r#"
5873      .foo {
5874        place-content: space-between flex-end;
5875      }
5876    "#},
5877      Browsers {
5878        safari: Some(11 << 16),
5879        ..Browsers::default()
5880      },
5881    );
5882    prefix_test(
5883      r#"
5884      .foo {
5885        place-content: space-between flex-end;
5886      }
5887    "#,
5888      indoc! {r#"
5889      .foo {
5890        align-content: space-between;
5891        justify-content: flex-end;
5892      }
5893    "#},
5894      Browsers {
5895        chrome: Some(30 << 16),
5896        ..Browsers::default()
5897      },
5898    );
5899    prefix_test(
5900      r#"
5901      .foo {
5902        place-content: space-between flex-end;
5903      }
5904    "#,
5905      indoc! {r#"
5906      .foo {
5907        place-content: space-between flex-end;
5908      }
5909    "#},
5910      Browsers {
5911        chrome: Some(60 << 16),
5912        ..Browsers::default()
5913      },
5914    );
5915    prefix_test(
5916      r#"
5917      .foo {
5918        align-self: flex-end;
5919      }
5920    "#,
5921      indoc! {r#"
5922      .foo {
5923        -ms-flex-item-align: end;
5924        -webkit-align-self: flex-end;
5925        align-self: flex-end;
5926      }
5927    "#},
5928      Browsers {
5929        safari: Some(4 << 16),
5930        firefox: Some(4 << 16),
5931        ie: Some(10 << 16),
5932        ..Browsers::default()
5933      },
5934    );
5935    prefix_test(
5936      r#"
5937      .foo {
5938        -ms-flex-item-align: end;
5939        -webkit-align-self: flex-end;
5940        align-self: flex-end;
5941      }
5942    "#,
5943      indoc! {r#"
5944      .foo {
5945        align-self: flex-end;
5946      }
5947    "#},
5948      Browsers {
5949        safari: Some(11 << 16),
5950        ..Browsers::default()
5951      },
5952    );
5953    prefix_test(
5954      r#"
5955      .foo {
5956        place-self: center flex-end;
5957      }
5958    "#,
5959      indoc! {r#"
5960      .foo {
5961        -ms-flex-item-align: center;
5962        -webkit-align-self: center;
5963        align-self: center;
5964        justify-self: flex-end;
5965      }
5966    "#},
5967      Browsers {
5968        safari: Some(4 << 16),
5969        firefox: Some(4 << 16),
5970        ie: Some(10 << 16),
5971        ..Browsers::default()
5972      },
5973    );
5974    prefix_test(
5975      r#"
5976      .foo {
5977        -ms-flex-item-align: center;
5978        -webkit-align-self: center;
5979        place-self: center flex-end;
5980      }
5981    "#,
5982      indoc! {r#"
5983      .foo {
5984        place-self: center flex-end;
5985      }
5986    "#},
5987      Browsers {
5988        safari: Some(11 << 16),
5989        ..Browsers::default()
5990      },
5991    );
5992    prefix_test(
5993      r#"
5994      .foo {
5995        place-self: center flex-end;
5996      }
5997    "#,
5998      indoc! {r#"
5999      .foo {
6000        align-self: center;
6001        justify-self: flex-end;
6002      }
6003    "#},
6004      Browsers {
6005        chrome: Some(57 << 16),
6006        ..Browsers::default()
6007      },
6008    );
6009    prefix_test(
6010      r#"
6011      .foo {
6012        place-self: center flex-end;
6013      }
6014    "#,
6015      indoc! {r#"
6016      .foo {
6017        place-self: center flex-end;
6018      }
6019    "#},
6020      Browsers {
6021        chrome: Some(59 << 16),
6022        ..Browsers::default()
6023      },
6024    );
6025    prefix_test(
6026      r#"
6027      .foo {
6028        align-items: flex-end;
6029      }
6030    "#,
6031      indoc! {r#"
6032      .foo {
6033        -webkit-box-align: end;
6034        -moz-box-align: end;
6035        -ms-flex-align: end;
6036        -webkit-align-items: flex-end;
6037        align-items: flex-end;
6038      }
6039    "#},
6040      Browsers {
6041        safari: Some(4 << 16),
6042        firefox: Some(4 << 16),
6043        ie: Some(10 << 16),
6044        ..Browsers::default()
6045      },
6046    );
6047    prefix_test(
6048      r#"
6049      .foo {
6050        -webkit-box-align: end;
6051        -moz-box-align: end;
6052        -ms-flex-align: end;
6053        -webkit-align-items: flex-end;
6054        align-items: flex-end;
6055      }
6056    "#,
6057      indoc! {r#"
6058      .foo {
6059        align-items: flex-end;
6060      }
6061    "#},
6062      Browsers {
6063        safari: Some(11 << 16),
6064        ..Browsers::default()
6065      },
6066    );
6067    prefix_test(
6068      r#"
6069      .foo {
6070        place-items: flex-end center;
6071      }
6072    "#,
6073      indoc! {r#"
6074      .foo {
6075        -webkit-box-align: end;
6076        -moz-box-align: end;
6077        -ms-flex-align: end;
6078        -webkit-align-items: flex-end;
6079        align-items: flex-end;
6080        justify-items: center;
6081      }
6082    "#},
6083      Browsers {
6084        safari: Some(4 << 16),
6085        firefox: Some(4 << 16),
6086        ie: Some(10 << 16),
6087        ..Browsers::default()
6088      },
6089    );
6090    prefix_test(
6091      r#"
6092      .foo {
6093        -webkit-box-align: end;
6094        -moz-box-align: end;
6095        -ms-flex-align: end;
6096        -webkit-align-items: flex-end;
6097        place-items: flex-end center;
6098      }
6099    "#,
6100      indoc! {r#"
6101      .foo {
6102        place-items: flex-end center;
6103      }
6104    "#},
6105      Browsers {
6106        safari: Some(11 << 16),
6107        ..Browsers::default()
6108      },
6109    );
6110    prefix_test(
6111      r#"
6112      .foo {
6113        place-items: flex-end center;
6114      }
6115    "#,
6116      indoc! {r#"
6117      .foo {
6118        align-items: flex-end;
6119        justify-items: center;
6120      }
6121    "#},
6122      Browsers {
6123        safari: Some(10 << 16),
6124        ..Browsers::default()
6125      },
6126    );
6127    prefix_test(
6128      r#"
6129      .foo {
6130        order: 1;
6131      }
6132    "#,
6133      indoc! {r#"
6134      .foo {
6135        -webkit-box-ordinal-group: 1;
6136        -moz-box-ordinal-group: 1;
6137        -ms-flex-order: 1;
6138        -webkit-order: 1;
6139        order: 1;
6140      }
6141    "#},
6142      Browsers {
6143        safari: Some(4 << 16),
6144        firefox: Some(4 << 16),
6145        ie: Some(10 << 16),
6146        ..Browsers::default()
6147      },
6148    );
6149    prefix_test(
6150      r#"
6151      .foo {
6152        -webkit-box-ordinal-group: 1;
6153        -moz-box-ordinal-group: 1;
6154        -ms-flex-order: 1;
6155        -webkit-order: 1;
6156        order: 1;
6157      }
6158    "#,
6159      indoc! {r#"
6160      .foo {
6161        order: 1;
6162      }
6163    "#},
6164      Browsers {
6165        safari: Some(11 << 16),
6166        ..Browsers::default()
6167      },
6168    );
6169    prefix_test(
6170      r#"
6171      .foo {
6172        -ms-flex: 0 0 8%;
6173        flex: 0 0 5%;
6174      }
6175    "#,
6176      indoc! {r#"
6177      .foo {
6178        -ms-flex: 0 0 8%;
6179        flex: 0 0 5%;
6180      }
6181    "#},
6182      Browsers {
6183        safari: Some(11 << 16),
6184        ..Browsers::default()
6185      },
6186    );
6187  }
6188
6189  #[test]
6190  fn test_font() {
6191    test(
6192      r#"
6193      .foo {
6194        font-family: "Helvetica", "Times New Roman", sans-serif;
6195        font-size: 12px;
6196        font-weight: bold;
6197        font-style: italic;
6198        font-stretch: expanded;
6199        font-variant-caps: small-caps;
6200        line-height: 1.2em;
6201      }
6202    "#,
6203      indoc! {r#"
6204      .foo {
6205        font: italic small-caps bold expanded 12px / 1.2em Helvetica, Times New Roman, sans-serif;
6206      }
6207    "#
6208      },
6209    );
6210
6211    minify_test(
6212      r#"
6213      .foo {
6214        font-family: "Helvetica", "Times New Roman", sans-serif;
6215        font-size: 12px;
6216        font-weight: bold;
6217        font-style: italic;
6218        font-stretch: expanded;
6219        font-variant-caps: small-caps;
6220        line-height: 1.2em;
6221      }
6222    "#,
6223      indoc! {".foo{font:italic small-caps 700 125% 12px/1.2em Helvetica,Times New Roman,sans-serif}"
6224      },
6225    );
6226
6227    test(
6228      r#"
6229      .foo {
6230        font: 12px "Helvetica", "Times New Roman", sans-serif;
6231        line-height: 1.2em;
6232      }
6233    "#,
6234      indoc! {r#"
6235      .foo {
6236        font: 12px / 1.2em Helvetica, Times New Roman, sans-serif;
6237      }
6238    "#
6239      },
6240    );
6241
6242    test(
6243      r#"
6244      .foo {
6245        font: 12px "Helvetica", "Times New Roman", sans-serif;
6246        line-height: var(--lh);
6247      }
6248    "#,
6249      indoc! {r#"
6250      .foo {
6251        font: 12px Helvetica, Times New Roman, sans-serif;
6252        line-height: var(--lh);
6253      }
6254    "#
6255      },
6256    );
6257
6258    minify_test(
6259      r#"
6260      .foo {
6261        font-family: "Helvetica", "Times New Roman", sans-serif;
6262        font-size: 12px;
6263        font-stretch: expanded;
6264      }
6265    "#,
6266      indoc! {".foo{font-family:Helvetica,Times New Roman,sans-serif;font-size:12px;font-stretch:125%}"
6267      },
6268    );
6269
6270    test(
6271      r#"
6272      .foo {
6273        font-family: "Helvetica", "Times New Roman", sans-serif;
6274        font-size: 12px;
6275        font-weight: bold;
6276        font-style: italic;
6277        font-stretch: expanded;
6278        font-variant-caps: all-small-caps;
6279        line-height: 1.2em;
6280      }
6281    "#,
6282      indoc! {r#"
6283      .foo {
6284        font: italic bold expanded 12px / 1.2em Helvetica, Times New Roman, sans-serif;
6285        font-variant-caps: all-small-caps;
6286      }
6287    "#
6288      },
6289    );
6290
6291    minify_test(
6292      ".foo { font: normal normal 600 9px/normal Charcoal; }",
6293      ".foo{font:600 9px Charcoal}",
6294    );
6295    minify_test(
6296      ".foo { font: normal normal 500 medium/normal Charcoal; }",
6297      ".foo{font:500 medium Charcoal}",
6298    );
6299    minify_test(
6300      ".foo { font: normal normal 400 medium Charcoal; }",
6301      ".foo{font:400 medium Charcoal}",
6302    );
6303    minify_test(
6304      ".foo { font: normal normal 500 medium/10px Charcoal; }",
6305      ".foo{font:500 medium/10px Charcoal}",
6306    );
6307    minify_test(
6308      ".foo { font-family: 'sans-serif'; }",
6309      ".foo{font-family:\"sans-serif\"}",
6310    );
6311    minify_test(".foo { font-family: sans-serif; }", ".foo{font-family:sans-serif}");
6312    minify_test(".foo { font-family: 'default'; }", ".foo{font-family:\"default\"}");
6313    minify_test(".foo { font-family: default; }", ".foo{font-family:default}");
6314    minify_test(".foo { font-family: 'inherit'; }", ".foo{font-family:\"inherit\"}");
6315    minify_test(".foo { font-family: inherit; }", ".foo{font-family:inherit}");
6316    minify_test(".foo { font-family: inherit test; }", ".foo{font-family:inherit test}");
6317    minify_test(
6318      ".foo { font-family: 'inherit test'; }",
6319      ".foo{font-family:inherit test}",
6320    );
6321    minify_test(".foo { font-family: revert; }", ".foo{font-family:revert}");
6322    minify_test(".foo { font-family: 'revert'; }", ".foo{font-family:\"revert\"}");
6323    minify_test(".foo { font-family: revert-layer; }", ".foo{font-family:revert-layer}");
6324    minify_test(
6325      ".foo { font-family: revert-layer, serif; }",
6326      ".foo{font-family:revert-layer,serif}",
6327    );
6328    minify_test(
6329      ".foo { font-family: 'revert', sans-serif; }",
6330      ".foo{font-family:\"revert\",sans-serif}",
6331    );
6332    minify_test(
6333      ".foo { font-family: 'revert', foo, sans-serif; }",
6334      ".foo{font-family:\"revert\",foo,sans-serif}",
6335    );
6336    minify_test(".foo { font-family: ''; }", ".foo{font-family:\"\"}");
6337
6338    // font-family in @font-face
6339    minify_test(
6340      "@font-face { font-family: 'revert'; }",
6341      "@font-face{font-family:\"revert\"}",
6342    );
6343    minify_test(
6344      "@font-face { font-family: 'revert-layer'; }",
6345      "@font-face{font-family:\"revert-layer\"}",
6346    );
6347
6348    prefix_test(
6349      r#"
6350      .foo {
6351        font-family: Helvetica, system-ui, sans-serif;
6352      }
6353    "#,
6354      indoc! {r#"
6355      .foo {
6356        font-family: Helvetica, system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Noto Sans, Ubuntu, Cantarell, Helvetica Neue, sans-serif;
6357      }
6358    "#
6359      },
6360      Browsers {
6361        safari: Some(8 << 16),
6362        ..Browsers::default()
6363      },
6364    );
6365
6366    prefix_test(
6367      r#"
6368      .foo {
6369        font: 100%/1.5 Helvetica, system-ui, sans-serif;
6370      }
6371    "#,
6372      indoc! {r#"
6373      .foo {
6374        font: 100% / 1.5 Helvetica, system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Noto Sans, Ubuntu, Cantarell, Helvetica Neue, sans-serif;
6375      }
6376    "#
6377      },
6378      Browsers {
6379        safari: Some(8 << 16),
6380        ..Browsers::default()
6381      },
6382    );
6383
6384    prefix_test(
6385      r#"
6386      .foo {
6387        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";
6388      }
6389    "#,
6390      indoc! {r#"
6391      .foo {
6392        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;
6393      }
6394    "#
6395      },
6396      Browsers {
6397        firefox: Some(91 << 16),
6398        ..Browsers::default()
6399      },
6400    );
6401
6402    prefix_test(
6403      r#"
6404      .foo {
6405        font-size: 22px;
6406        font-size: max(2cqw, 22px);
6407      }
6408    "#,
6409      indoc! {r#"
6410      .foo {
6411        font-size: 22px;
6412        font-size: max(2cqw, 22px);
6413      }
6414    "#
6415      },
6416      Browsers {
6417        safari: Some(14 << 16),
6418        ..Browsers::default()
6419      },
6420    );
6421    prefix_test(
6422      r#"
6423      .foo {
6424        font-size: 22px;
6425        font-size: max(2cqw, 22px);
6426      }
6427    "#,
6428      indoc! {r#"
6429      .foo {
6430        font-size: max(2cqw, 22px);
6431      }
6432    "#
6433      },
6434      Browsers {
6435        safari: Some(16 << 16),
6436        ..Browsers::default()
6437      },
6438    );
6439
6440    prefix_test(
6441      r#"
6442      .foo {
6443        font-size: 22px;
6444        font-size: xxx-large;
6445      }
6446    "#,
6447      indoc! {r#"
6448      .foo {
6449        font-size: 22px;
6450        font-size: xxx-large;
6451      }
6452    "#
6453      },
6454      Browsers {
6455        chrome: Some(70 << 16),
6456        ..Browsers::default()
6457      },
6458    );
6459    prefix_test(
6460      r#"
6461      .foo {
6462        font-size: 22px;
6463        font-size: xxx-large;
6464      }
6465    "#,
6466      indoc! {r#"
6467      .foo {
6468        font-size: xxx-large;
6469      }
6470    "#
6471      },
6472      Browsers {
6473        chrome: Some(80 << 16),
6474        ..Browsers::default()
6475      },
6476    );
6477
6478    prefix_test(
6479      r#"
6480      .foo {
6481        font-weight: 700;
6482        font-weight: 789;
6483      }
6484    "#,
6485      indoc! {r#"
6486      .foo {
6487        font-weight: 700;
6488        font-weight: 789;
6489      }
6490    "#
6491      },
6492      Browsers {
6493        chrome: Some(60 << 16),
6494        ..Browsers::default()
6495      },
6496    );
6497    prefix_test(
6498      r#"
6499      .foo {
6500        font-weight: 700;
6501        font-weight: 789;
6502      }
6503    "#,
6504      indoc! {r#"
6505      .foo {
6506        font-weight: 789;
6507      }
6508    "#
6509      },
6510      Browsers {
6511        chrome: Some(80 << 16),
6512        ..Browsers::default()
6513      },
6514    );
6515
6516    prefix_test(
6517      r#"
6518      .foo {
6519        font-family: Helvetica;
6520        font-family: system-ui;
6521      }
6522    "#,
6523      indoc! {r#"
6524      .foo {
6525        font-family: Helvetica;
6526        font-family: system-ui;
6527      }
6528    "#
6529      },
6530      Browsers {
6531        chrome: Some(50 << 16),
6532        ..Browsers::default()
6533      },
6534    );
6535    prefix_test(
6536      r#"
6537      .foo {
6538        font-family: Helvetica;
6539        font-family: system-ui;
6540      }
6541    "#,
6542      indoc! {r#"
6543      .foo {
6544        font-family: system-ui;
6545      }
6546    "#
6547      },
6548      Browsers {
6549        chrome: Some(80 << 16),
6550        ..Browsers::default()
6551      },
6552    );
6553
6554    prefix_test(
6555      r#"
6556      .foo {
6557        font-style: oblique;
6558        font-style: oblique 40deg;
6559      }
6560    "#,
6561      indoc! {r#"
6562      .foo {
6563        font-style: oblique;
6564        font-style: oblique 40deg;
6565      }
6566    "#
6567      },
6568      Browsers {
6569        firefox: Some(50 << 16),
6570        ..Browsers::default()
6571      },
6572    );
6573    prefix_test(
6574      r#"
6575      .foo {
6576        font-style: oblique;
6577        font-style: oblique 40deg;
6578      }
6579    "#,
6580      indoc! {r#"
6581      .foo {
6582        font-style: oblique 40deg;
6583      }
6584    "#
6585      },
6586      Browsers {
6587        firefox: Some(80 << 16),
6588        ..Browsers::default()
6589      },
6590    );
6591
6592    prefix_test(
6593      r#"
6594      .foo {
6595        font: 22px Helvetica;
6596        font: xxx-large system-ui;
6597      }
6598    "#,
6599      indoc! {r#"
6600      .foo {
6601        font: 22px Helvetica;
6602        font: xxx-large system-ui;
6603      }
6604    "#
6605      },
6606      Browsers {
6607        chrome: Some(70 << 16),
6608        ..Browsers::default()
6609      },
6610    );
6611    prefix_test(
6612      r#"
6613      .foo {
6614        font: 22px Helvetica;
6615        font: xxx-large system-ui;
6616      }
6617    "#,
6618      indoc! {r#"
6619      .foo {
6620        font: xxx-large system-ui;
6621      }
6622    "#
6623      },
6624      Browsers {
6625        chrome: Some(80 << 16),
6626        ..Browsers::default()
6627      },
6628    );
6629
6630    prefix_test(
6631      r#"
6632      .foo {
6633        font: var(--fallback);
6634        font: xxx-large system-ui;
6635      }
6636    "#,
6637      indoc! {r#"
6638      .foo {
6639        font: var(--fallback);
6640        font: xxx-large system-ui;
6641      }
6642    "#
6643      },
6644      Browsers {
6645        chrome: Some(50 << 16),
6646        ..Browsers::default()
6647      },
6648    );
6649  }
6650
6651  #[test]
6652  fn test_vertical_align() {
6653    minify_test(".foo { vertical-align: middle }", ".foo{vertical-align:middle}");
6654    minify_test(".foo { vertical-align: 0.3em }", ".foo{vertical-align:.3em}");
6655  }
6656
6657  #[test]
6658  fn test_selectors() {
6659    minify_test(":nth-col(2n) {width: 20px}", ":nth-col(2n){width:20px}");
6660    minify_test(":nth-col(10n-1) {width: 20px}", ":nth-col(10n-1){width:20px}");
6661    minify_test(":nth-col(-n+2) {width: 20px}", ":nth-col(-n+2){width:20px}");
6662    minify_test(":nth-col(even) {width: 20px}", ":nth-col(2n){width:20px}");
6663    minify_test(":nth-col(odd) {width: 20px}", ":nth-col(odd){width:20px}");
6664    minify_test(":nth-last-col(2n) {width: 20px}", ":nth-last-col(2n){width:20px}");
6665    minify_test(":nth-last-col(10n-1) {width: 20px}", ":nth-last-col(10n-1){width:20px}");
6666    minify_test(":nth-last-col(-n+2) {width: 20px}", ":nth-last-col(-n+2){width:20px}");
6667    minify_test(":nth-last-col(even) {width: 20px}", ":nth-last-col(2n){width:20px}");
6668    minify_test(":nth-last-col(odd) {width: 20px}", ":nth-last-col(odd){width:20px}");
6669    minify_test(":nth-child(odd) {width: 20px}", ":nth-child(odd){width:20px}");
6670    minify_test(":nth-child(2n) {width: 20px}", ":nth-child(2n){width:20px}");
6671    minify_test(":nth-child(2n+1) {width: 20px}", ":nth-child(odd){width:20px}");
6672    minify_test(":first-child {width: 20px}", ":first-child{width:20px}");
6673    minify_test(":nth-child(1) {width: 20px}", ":first-child{width:20px}");
6674    minify_test(":nth-last-child(1) {width: 20px}", ":last-child{width:20px}");
6675    minify_test(":nth-of-type(1) {width: 20px}", ":first-of-type{width:20px}");
6676    minify_test(":nth-last-of-type(1) {width: 20px}", ":last-of-type{width:20px}");
6677    minify_test(
6678      ":nth-child(even of li.important) {width: 20px}",
6679      ":nth-child(2n of li.important){width:20px}",
6680    );
6681    minify_test(
6682      ":nth-child(1 of li.important) {width: 20px}",
6683      ":nth-child(1 of li.important){width:20px}",
6684    );
6685    minify_test(
6686      ":nth-last-child(even of li.important) {width: 20px}",
6687      ":nth-last-child(2n of li.important){width:20px}",
6688    );
6689    minify_test(
6690      ":nth-last-child(1 of li.important) {width: 20px}",
6691      ":nth-last-child(1 of li.important){width:20px}",
6692    );
6693    minify_test(
6694      ":nth-last-child(1 of.important) {width: 20px}",
6695      ":nth-last-child(1 of .important){width:20px}",
6696    );
6697
6698    minify_test("[foo=\"baz\"] {color:red}", "[foo=baz]{color:red}");
6699    minify_test("[foo=\"foo bar\"] {color:red}", "[foo=foo\\ bar]{color:red}");
6700    minify_test("[foo=\"foo bar baz\"] {color:red}", "[foo=\"foo bar baz\"]{color:red}");
6701    minify_test("[foo=\"\"] {color:red}", "[foo=\"\"]{color:red}");
6702    minify_test(
6703      ".test:not([foo=\"bar\"]) {color:red}",
6704      ".test:not([foo=bar]){color:red}",
6705    );
6706    minify_test(".test + .foo {color:red}", ".test+.foo{color:red}");
6707    minify_test(".test ~ .foo {color:red}", ".test~.foo{color:red}");
6708    minify_test(".test .foo {color:red}", ".test .foo{color:red}");
6709    minify_test(
6710      ".custom-range::-webkit-slider-thumb:active {color:red}",
6711      ".custom-range::-webkit-slider-thumb:active{color:red}",
6712    );
6713    minify_test(".test:not(.foo, .bar) {color:red}", ".test:not(.foo,.bar){color:red}");
6714    minify_test(".test:is(.foo, .bar) {color:red}", ".test:is(.foo,.bar){color:red}");
6715    minify_test(
6716      ".test:where(.foo, .bar) {color:red}",
6717      ".test:where(.foo,.bar){color:red}",
6718    );
6719    minify_test(
6720      ".test:where(.foo, .bar) {color:red}",
6721      ".test:where(.foo,.bar){color:red}",
6722    );
6723    minify_test(":host {color:red}", ":host{color:red}");
6724    minify_test(":host(.foo) {color:red}", ":host(.foo){color:red}");
6725    minify_test("::slotted(span) {color:red", "::slotted(span){color:red}");
6726    minify_test(
6727      "custom-element::part(foo) {color:red}",
6728      "custom-element::part(foo){color:red}",
6729    );
6730    minify_test(".sm\\:text-5xl { font-size: 3rem }", ".sm\\:text-5xl{font-size:3rem}");
6731    minify_test("a:has(> img) {color:red}", "a:has(>img){color:red}");
6732    minify_test("dt:has(+ dt) {color:red}", "dt:has(+dt){color:red}");
6733    minify_test(
6734      "section:not(:has(h1, h2, h3, h4, h5, h6)) {color:red}",
6735      "section:not(:has(h1,h2,h3,h4,h5,h6)){color:red}",
6736    );
6737    minify_test(
6738      ":has(.sibling ~ .target) {color:red}",
6739      ":has(.sibling~.target){color:red}",
6740    );
6741    minify_test(".x:has(> .a > .b) {color:red}", ".x:has(>.a>.b){color:red}");
6742    minify_test(".x:has(.bar, #foo) {color:red}", ".x:has(.bar,#foo){color:red}");
6743    minify_test(".x:has(span + span) {color:red}", ".x:has(span+span){color:red}");
6744    minify_test("a:has(:visited) {color:red}", "a:has(:visited){color:red}");
6745    for element in [
6746      "-webkit-scrollbar",
6747      "-webkit-scrollbar-button",
6748      "-webkit-scrollbar-track",
6749      "-webkit-scrollbar-track-piece",
6750      "-webkit-scrollbar-thumb",
6751      "-webkit-scrollbar-corner",
6752      "-webkit-resizer",
6753    ] {
6754      for class in [
6755        "enabled",
6756        "disabled",
6757        "hover",
6758        "active",
6759        "horizontal",
6760        "vertical",
6761        "decrement",
6762        "increment",
6763        "start",
6764        "end",
6765        "double-button",
6766        "single-button",
6767        "no-button",
6768        "corner-present",
6769        "window-inactive",
6770      ] {
6771        minify_test(
6772          &format!("::{}:{} {{color:red}}", element, class),
6773          &format!("::{}:{}{{color:red}}", element, class),
6774        );
6775      }
6776    }
6777    for class in [
6778      "horizontal",
6779      "vertical",
6780      "decrement",
6781      "increment",
6782      "start",
6783      "end",
6784      "double-button",
6785      "single-button",
6786      "no-button",
6787      "corner-present",
6788      "window-inactive",
6789    ] {
6790      error_test(
6791        &format!(":{} {{color:red}}", class),
6792        ParserError::SelectorError(SelectorError::InvalidPseudoClassBeforeWebKitScrollbar),
6793      );
6794    }
6795    for element in [
6796      "-webkit-scrollbar",
6797      "-webkit-scrollbar-button",
6798      "-webkit-scrollbar-track",
6799      "-webkit-scrollbar-track-piece",
6800      "-webkit-scrollbar-thumb",
6801      "-webkit-scrollbar-corner",
6802      "-webkit-resizer",
6803    ] {
6804      error_test(
6805        &format!("::{}:focus {{color:red}}", element),
6806        ParserError::SelectorError(SelectorError::InvalidPseudoClassAfterWebKitScrollbar),
6807      );
6808    }
6809
6810    error_test(
6811      "a::first-letter:last-child {color:red}",
6812      ParserError::SelectorError(SelectorError::InvalidPseudoClassAfterPseudoElement),
6813    );
6814    minify_test(
6815      "a:last-child::first-letter {color:red}",
6816      "a:last-child:first-letter{color:red}",
6817    );
6818
6819    prefix_test(
6820      ".test:not(.foo, .bar) {color:red}",
6821      indoc! {r#"
6822      .test:not(:-webkit-any(.foo, .bar)) {
6823        color: red;
6824      }
6825
6826      .test:not(:is(.foo, .bar)) {
6827        color: red;
6828      }
6829      "#},
6830      Browsers {
6831        safari: Some(8 << 16),
6832        ..Browsers::default()
6833      },
6834    );
6835    prefix_test(
6836      ".test:not(.foo, .bar) {color:red}",
6837      indoc! {r#"
6838      .test:not(.foo, .bar) {
6839        color: red;
6840      }
6841      "#},
6842      Browsers {
6843        safari: Some(11 << 16),
6844        ..Browsers::default()
6845      },
6846    );
6847
6848    minify_test("a:lang(en) {color:red}", "a:lang(en){color:red}");
6849    minify_test("a:lang(en, fr) {color:red}", "a:lang(en,fr){color:red}");
6850    minify_test("a:lang('en') {color:red}", "a:lang(en){color:red}");
6851    minify_test(
6852      "a:-webkit-any(.foo, .bar) {color:red}",
6853      "a:-webkit-any(.foo,.bar){color:red}",
6854    );
6855    minify_test("a:-moz-any(.foo, .bar) {color:red}", "a:-moz-any(.foo,.bar){color:red}");
6856
6857    prefix_test(
6858      "a:is(.foo, .bar) {color:red}",
6859      indoc! {r#"
6860      a:-webkit-any(.foo, .bar) {
6861        color: red;
6862      }
6863
6864      a:-moz-any(.foo, .bar) {
6865        color: red;
6866      }
6867
6868      a:is(.foo, .bar) {
6869        color: red;
6870      }
6871      "#},
6872      Browsers {
6873        safari: Some(11 << 16),
6874        firefox: Some(50 << 16),
6875        ..Browsers::default()
6876      },
6877    );
6878
6879    prefix_test(
6880      "a:is(.foo > .bar) {color:red}",
6881      indoc! {r#"
6882      a:is(.foo > .bar) {
6883        color: red;
6884      }
6885      "#},
6886      Browsers {
6887        safari: Some(11 << 16),
6888        firefox: Some(50 << 16),
6889        ..Browsers::default()
6890      },
6891    );
6892
6893    prefix_test(
6894      "a:lang(en, fr) {color:red}",
6895      indoc! {r#"
6896      a:-webkit-any(:lang(en), :lang(fr)) {
6897        color: red;
6898      }
6899
6900      a:-moz-any(:lang(en), :lang(fr)) {
6901        color: red;
6902      }
6903
6904      a:is(:lang(en), :lang(fr)) {
6905        color: red;
6906      }
6907      "#},
6908      Browsers {
6909        safari: Some(11 << 16),
6910        firefox: Some(50 << 16),
6911        ..Browsers::default()
6912      },
6913    );
6914
6915    prefix_test(
6916      "a:lang(en, fr) {color:red}",
6917      indoc! {r#"
6918      a:is(:lang(en), :lang(fr)) {
6919        color: red;
6920      }
6921      "#},
6922      Browsers {
6923        safari: Some(14 << 16),
6924        firefox: Some(88 << 16),
6925        ..Browsers::default()
6926      },
6927    );
6928
6929    prefix_test(
6930      "a:lang(en, fr) {color:red}",
6931      indoc! {r#"
6932      a:lang(en, fr) {
6933        color: red;
6934      }
6935      "#},
6936      Browsers {
6937        safari: Some(14 << 16),
6938        ..Browsers::default()
6939      },
6940    );
6941
6942    prefix_test(
6943      "a:dir(rtl) {color:red}",
6944      indoc! {r#"
6945      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)) {
6946        color: red;
6947      }
6948
6949      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)) {
6950        color: red;
6951      }
6952
6953      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)) {
6954        color: red;
6955      }
6956      "#},
6957      Browsers {
6958        safari: Some(11 << 16),
6959        firefox: Some(50 << 16),
6960        ..Browsers::default()
6961      },
6962    );
6963
6964    prefix_test(
6965      "a:dir(ltr) {color:red}",
6966      indoc! {r#"
6967      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))) {
6968        color: red;
6969      }
6970
6971      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))) {
6972        color: red;
6973      }
6974
6975      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))) {
6976        color: red;
6977      }
6978      "#},
6979      Browsers {
6980        safari: Some(11 << 16),
6981        firefox: Some(50 << 16),
6982        ..Browsers::default()
6983      },
6984    );
6985
6986    prefix_test(
6987      "a:dir(rtl) {color:red}",
6988      indoc! {r#"
6989      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)) {
6990        color: red;
6991      }
6992      "#},
6993      Browsers {
6994        safari: Some(14 << 16),
6995        firefox: Some(88 << 16),
6996        ..Browsers::default()
6997      },
6998    );
6999
7000    prefix_test(
7001      "a:dir(ltr) {color:red}",
7002      indoc! {r#"
7003      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)) {
7004        color: red;
7005      }
7006      "#},
7007      Browsers {
7008        safari: Some(14 << 16),
7009        firefox: Some(88 << 16),
7010        ..Browsers::default()
7011      },
7012    );
7013
7014    prefix_test(
7015      "a:dir(rtl) {color:red}",
7016      indoc! {r#"
7017      a:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) {
7018        color: red;
7019      }
7020      "#},
7021      Browsers {
7022        safari: Some(14 << 16),
7023        ..Browsers::default()
7024      },
7025    );
7026
7027    prefix_test(
7028      "a:dir(ltr) {color:red}",
7029      indoc! {r#"
7030      a:not(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
7031        color: red;
7032      }
7033      "#},
7034      Browsers {
7035        safari: Some(14 << 16),
7036        ..Browsers::default()
7037      },
7038    );
7039
7040    prefix_test(
7041      "a:is(:dir(rtl)) {color:red}",
7042      indoc! {r#"
7043      a:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) {
7044        color: red;
7045      }
7046      "#},
7047      Browsers {
7048        safari: Some(14 << 16),
7049        ..Browsers::default()
7050      },
7051    );
7052
7053    prefix_test(
7054      "a:where(:dir(rtl)) {color:red}",
7055      indoc! {r#"
7056      a:where(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
7057        color: red;
7058      }
7059      "#},
7060      Browsers {
7061        safari: Some(14 << 16),
7062        ..Browsers::default()
7063      },
7064    );
7065
7066    prefix_test(
7067      "a:has(:dir(rtl)) {color:red}",
7068      indoc! {r#"
7069      a:has(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
7070        color: red;
7071      }
7072      "#},
7073      Browsers {
7074        safari: Some(14 << 16),
7075        ..Browsers::default()
7076      },
7077    );
7078
7079    prefix_test(
7080      "a:not(:dir(rtl)) {color:red}",
7081      indoc! {r#"
7082      a:not(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
7083        color: red;
7084      }
7085      "#},
7086      Browsers {
7087        safari: Some(14 << 16),
7088        ..Browsers::default()
7089      },
7090    );
7091
7092    prefix_test(
7093      "a:dir(rtl)::after {color:red}",
7094      indoc! {r#"
7095      a:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi):after {
7096        color: red;
7097      }
7098      "#},
7099      Browsers {
7100        safari: Some(14 << 16),
7101        ..Browsers::default()
7102      },
7103    );
7104
7105    prefix_test(
7106      "a:dir(rtl) div {color:red}",
7107      indoc! {r#"
7108      a:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) div {
7109        color: red;
7110      }
7111      "#},
7112      Browsers {
7113        safari: Some(14 << 16),
7114        ..Browsers::default()
7115      },
7116    );
7117
7118    minify_test(".foo::cue {color: red}", ".foo::cue{color:red}");
7119    minify_test(".foo::cue-region {color: red}", ".foo::cue-region{color:red}");
7120    minify_test(".foo::cue(b) {color: red}", ".foo::cue(b){color:red}");
7121    minify_test(".foo::cue-region(b) {color: red}", ".foo::cue-region(b){color:red}");
7122    minify_test(
7123      "::cue(v[voice='active']) {color: yellow;}",
7124      "::cue(v[voice=active]){color:#ff0}",
7125    );
7126    minify_test(":foo(bar) { color: yellow }", ":foo(bar){color:#ff0}");
7127    minify_test("::foo(bar) { color: yellow }", "::foo(bar){color:#ff0}");
7128    minify_test("::foo(*) { color: yellow }", "::foo(*){color:#ff0}");
7129
7130    minify_test(":is(.foo) { color: yellow }", ".foo{color:#ff0}");
7131    minify_test(":is(#foo) { color: yellow }", "#foo{color:#ff0}");
7132    minify_test("a:is(.foo) { color: yellow }", "a.foo{color:#ff0}");
7133    minify_test("a:is([data-test]) { color: yellow }", "a[data-test]{color:#ff0}");
7134    minify_test(".foo:is(a) { color: yellow }", ".foo:is(a){color:#ff0}");
7135    minify_test(".foo:is(*|a) { color: yellow }", ".foo:is(*|a){color:#ff0}");
7136    minify_test(".foo:is(*) { color: yellow }", ".foo:is(*){color:#ff0}");
7137    minify_test(
7138      "@namespace svg url(http://www.w3.org/2000/svg); .foo:is(svg|a) { color: yellow }",
7139      "@namespace svg \"http://www.w3.org/2000/svg\";.foo:is(svg|a){color:#ff0}",
7140    );
7141    minify_test("a:is(.foo .bar) { color: yellow }", "a:is(.foo .bar){color:#ff0}");
7142    minify_test(":is(.foo, .bar) { color: yellow }", ":is(.foo,.bar){color:#ff0}");
7143    minify_test("a:is(:not(.foo)) { color: yellow }", "a:not(.foo){color:#ff0}");
7144    minify_test("a:is(:first-child) { color: yellow }", "a:first-child{color:#ff0}");
7145    minify_test("a:is(:has(.foo)) { color: yellow }", "a:has(.foo){color:#ff0}");
7146    minify_test("a:is(:is(.foo)) { color: yellow }", "a.foo{color:#ff0}");
7147    minify_test(":host(:hover) {color: red}", ":host(:hover){color:red}");
7148    minify_test("::slotted(:hover) {color: red}", "::slotted(:hover){color:red}");
7149
7150    minify_test(
7151      ":root::view-transition {position: fixed}",
7152      ":root::view-transition{position:fixed}",
7153    );
7154    minify_test(
7155      ":root:active-view-transition {position: fixed}",
7156      ":root:active-view-transition{position:fixed}",
7157    );
7158    minify_test(
7159      ":root:active-view-transition-type(slide-in) {position: fixed}",
7160      ":root:active-view-transition-type(slide-in){position:fixed}",
7161    );
7162    minify_test(
7163      ":root:active-view-transition-type(slide-in, reverse) {position: fixed}",
7164      ":root:active-view-transition-type(slide-in,reverse){position:fixed}",
7165    );
7166
7167    for name in &[
7168      "view-transition-group",
7169      "view-transition-image-pair",
7170      "view-transition-new",
7171      "view-transition-old",
7172    ] {
7173      minify_test(
7174        &format!(":root::{}(*) {{position: fixed}}", name),
7175        &format!(":root::{}(*){{position:fixed}}", name),
7176      );
7177      minify_test(
7178        &format!(":root::{}(*.class) {{position: fixed}}", name),
7179        &format!(":root::{}(*.class){{position:fixed}}", name),
7180      );
7181      minify_test(
7182        &format!(":root::{}(*.class.class) {{position: fixed}}", name),
7183        &format!(":root::{}(*.class.class){{position:fixed}}", name),
7184      );
7185      minify_test(
7186        &format!(":root::{}(foo) {{position: fixed}}", name),
7187        &format!(":root::{}(foo){{position:fixed}}", name),
7188      );
7189      minify_test(
7190        &format!(":root::{}(foo.class) {{position: fixed}}", name),
7191        &format!(":root::{}(foo.class){{position:fixed}}", name),
7192      );
7193      minify_test(
7194        &format!(":root::{}(foo.bar.baz) {{position: fixed}}", name),
7195        &format!(":root::{}(foo.bar.baz){{position:fixed}}", name),
7196      );
7197      minify_test(
7198        &format!(":root::{}(foo):only-child {{position: fixed}}", name),
7199        &format!(":root::{}(foo):only-child{{position:fixed}}", name),
7200      );
7201      minify_test(
7202        &format!(":root::{}(foo.bar.baz):only-child {{position: fixed}}", name),
7203        &format!(":root::{}(foo.bar.baz):only-child{{position:fixed}}", name),
7204      );
7205      minify_test(
7206        &format!(":root::{}(.foo) {{position: fixed}}", name),
7207        &format!(":root::{}(.foo){{position:fixed}}", name),
7208      );
7209      minify_test(
7210        &format!(":root::{}(.foo.bar) {{position: fixed}}", name),
7211        &format!(":root::{}(.foo.bar){{position:fixed}}", name),
7212      );
7213      minify_test(
7214        &format!(":root::{}(  .foo.bar  ) {{position: fixed}}", name),
7215        &format!(":root::{}(.foo.bar){{position:fixed}}", name),
7216      );
7217      error_test(
7218        &format!(":root::{}(foo):first-child {{position: fixed}}", name),
7219        ParserError::SelectorError(SelectorError::InvalidPseudoClassAfterPseudoElement),
7220      );
7221      error_test(
7222        &format!(":root::{}(foo)::before {{position: fixed}}", name),
7223        ParserError::SelectorError(SelectorError::InvalidState),
7224      );
7225      error_test(
7226        &format!(":root::{}(*.*) {{position: fixed}}", name),
7227        ParserError::SelectorError(SelectorError::InvalidState),
7228      );
7229      error_test(
7230        &format!(":root::{}(*. cls) {{position: fixed}}", name),
7231        ParserError::SelectorError(SelectorError::InvalidState),
7232      );
7233      error_test(
7234        &format!(":root::{}(foo .bar) {{position: fixed}}", name),
7235        ParserError::SelectorError(SelectorError::InvalidState),
7236      );
7237      error_test(
7238        &format!(":root::{}(*.cls. c) {{position: fixed}}", name),
7239        ParserError::SelectorError(SelectorError::InvalidState),
7240      );
7241      error_test(
7242        &format!(":root::{}(*.cls>cls) {{position: fixed}}", name),
7243        ParserError::SelectorError(SelectorError::InvalidState),
7244      );
7245      error_test(
7246        &format!(":root::{}(*.cls.foo.*) {{position: fixed}}", name),
7247        ParserError::SelectorError(SelectorError::InvalidState),
7248      );
7249    }
7250    minify_test(
7251      "wa-checkbox:state(disabled) {color:red}",
7252      "wa-checkbox:state(disabled){color:red}",
7253    );
7254    minify_test(
7255      "button:state(checked) {background:blue}",
7256      "button:state(checked){background:#00f}",
7257    );
7258    minify_test(
7259      "input:state(custom-state) {border:1px solid}",
7260      "input:state(custom-state){border:1px solid}",
7261    );
7262    minify_test(
7263      "button:active:not(:state(disabled))::part(control) {border:1px solid}",
7264      "button:active:not(:state(disabled))::part(control){border:1px solid}",
7265    );
7266    // Test nested CSS with :state() selector
7267    nesting_test(
7268      r#"
7269        custom-element {
7270          color: blue;
7271          &:state(loading) {
7272            opacity: 0.5;
7273            & .spinner {
7274              display: block;
7275            }
7276          }
7277          &:state(error) {
7278            border: 2px solid red;
7279          }
7280        }
7281      "#,
7282      indoc! {r#"
7283        custom-element {
7284          color: #00f;
7285        }
7286
7287        custom-element:state(loading) {
7288          opacity: .5;
7289        }
7290
7291        custom-element:state(loading) .spinner {
7292          display: block;
7293        }
7294
7295        custom-element:state(error) {
7296          border: 2px solid red;
7297        }
7298      "#},
7299    );
7300    minify_test(".foo ::deep .bar {width: 20px}", ".foo ::deep .bar{width:20px}");
7301    minify_test(".foo::deep .bar {width: 20px}", ".foo::deep .bar{width:20px}");
7302    minify_test(".foo ::deep.bar {width: 20px}", ".foo ::deep.bar{width:20px}");
7303    minify_test(".foo ::unknown .bar {width: 20px}", ".foo ::unknown .bar{width:20px}");
7304    minify_test(
7305      ".foo ::unknown(foo) .bar {width: 20px}",
7306      ".foo ::unknown(foo) .bar{width:20px}",
7307    );
7308    minify_test(
7309      ".foo ::unknown:only-child {width: 20px}",
7310      ".foo ::unknown:only-child{width:20px}",
7311    );
7312    minify_test(
7313      ".foo ::unknown(.foo) .bar {width: 20px}",
7314      ".foo ::unknown(.foo) .bar{width:20px}",
7315    );
7316    minify_test(
7317      ".foo ::unknown(.foo .bar / .baz) .bar {width: 20px}",
7318      ".foo ::unknown(.foo .bar / .baz) .bar{width:20px}",
7319    );
7320    minify_test(
7321      ".foo ::unknown(something(foo)) .bar {width: 20px}",
7322      ".foo ::unknown(something(foo)) .bar{width:20px}",
7323    );
7324    minify_test(
7325      ".foo ::unknown([abc]) .bar {width: 20px}",
7326      ".foo ::unknown([abc]) .bar{width:20px}",
7327    );
7328
7329    let deep_options = ParserOptions {
7330      flags: ParserFlags::DEEP_SELECTOR_COMBINATOR,
7331      ..ParserOptions::default()
7332    };
7333
7334    error_test(
7335      ".foo >>> .bar {width: 20px}",
7336      ParserError::SelectorError(SelectorError::DanglingCombinator),
7337    );
7338    error_test(
7339      ".foo /deep/ .bar {width: 20px}",
7340      ParserError::SelectorError(SelectorError::DanglingCombinator),
7341    );
7342    minify_test_with_options(
7343      ".foo >>> .bar {width: 20px}",
7344      ".foo>>>.bar{width:20px}",
7345      deep_options.clone(),
7346    );
7347    minify_test_with_options(
7348      ".foo /deep/ .bar {width: 20px}",
7349      ".foo /deep/ .bar{width:20px}",
7350      deep_options.clone(),
7351    );
7352
7353    let pure_css_module_options = ParserOptions {
7354      css_modules: Some(crate::css_modules::Config {
7355        pure: true,
7356        ..Default::default()
7357      }),
7358      ..ParserOptions::default()
7359    };
7360
7361    minify_error_test_with_options(
7362      "div {width: 20px}",
7363      MinifyErrorKind::ImpureCSSModuleSelector,
7364      pure_css_module_options.clone(),
7365    );
7366    minify_error_test_with_options(
7367      ":global(.foo) {width: 20px}",
7368      MinifyErrorKind::ImpureCSSModuleSelector,
7369      pure_css_module_options.clone(),
7370    );
7371    minify_error_test_with_options(
7372      "[foo=bar] {width: 20px}",
7373      MinifyErrorKind::ImpureCSSModuleSelector,
7374      pure_css_module_options.clone(),
7375    );
7376    minify_error_test_with_options(
7377      "div, .foo {width: 20px}",
7378      MinifyErrorKind::ImpureCSSModuleSelector,
7379      pure_css_module_options.clone(),
7380    );
7381    minify_test_with_options(
7382      ":local(.foo) {width: 20px}",
7383      "._8Z4fiW_foo{width:20px}",
7384      pure_css_module_options.clone(),
7385    );
7386    minify_test_with_options(
7387      "div.my-class {color: red;}",
7388      "div._8Z4fiW_my-class{color:red}",
7389      pure_css_module_options.clone(),
7390    );
7391    minify_test_with_options(
7392      "#id {color: red;}",
7393      "#_8Z4fiW_id{color:red}",
7394      pure_css_module_options.clone(),
7395    );
7396    minify_test_with_options(
7397      "a .my-class{color: red;}",
7398      "a ._8Z4fiW_my-class{color:red}",
7399      pure_css_module_options.clone(),
7400    );
7401    minify_test_with_options(
7402      ".my-class a {color: red;}",
7403      "._8Z4fiW_my-class a{color:red}",
7404      pure_css_module_options.clone(),
7405    );
7406    minify_test_with_options(
7407      ".my-class:is(a) {color: red;}",
7408      "._8Z4fiW_my-class:is(a){color:red}",
7409      pure_css_module_options.clone(),
7410    );
7411    minify_test_with_options(
7412      "div:has(.my-class) {color: red;}",
7413      "div:has(._8Z4fiW_my-class){color:red}",
7414      pure_css_module_options.clone(),
7415    );
7416    minify_test_with_options(
7417      ".foo { html &:hover { a_value: some-value; } }",
7418      "._8Z4fiW_foo{html &:hover{a_value:some-value}}",
7419      pure_css_module_options.clone(),
7420    );
7421    minify_test_with_options(
7422      ".foo { span { color: red; } }",
7423      "._8Z4fiW_foo{& span{color:red}}",
7424      pure_css_module_options.clone(),
7425    );
7426    minify_error_test_with_options(
7427      "html { .foo { span { color: red; } } }",
7428      MinifyErrorKind::ImpureCSSModuleSelector,
7429      pure_css_module_options.clone(),
7430    );
7431    minify_test_with_options(
7432      ".foo { div { span { color: red; } } }",
7433      "._8Z4fiW_foo{& div{& span{color:red}}}",
7434      pure_css_module_options.clone(),
7435    );
7436    minify_error_test_with_options(
7437      "@scope (div) { .foo { color: red } }",
7438      MinifyErrorKind::ImpureCSSModuleSelector,
7439      pure_css_module_options.clone(),
7440    );
7441    minify_error_test_with_options(
7442      "@scope (.a) to (div) { .foo { color: red } }",
7443      MinifyErrorKind::ImpureCSSModuleSelector,
7444      pure_css_module_options.clone(),
7445    );
7446    minify_error_test_with_options(
7447      "@scope (.a) to (.b) { div { color: red } }",
7448      MinifyErrorKind::ImpureCSSModuleSelector,
7449      pure_css_module_options.clone(),
7450    );
7451    minify_test_with_options(
7452      "@scope (.a) to (.b) { .foo { color: red } }",
7453      "@scope(._8Z4fiW_a) to (._8Z4fiW_b){._8Z4fiW_foo{color:red}}",
7454      pure_css_module_options.clone(),
7455    );
7456    minify_test_with_options(
7457      "/* cssmodules-pure-no-check */ :global(.foo) { color: red }",
7458      ".foo{color:red}",
7459      pure_css_module_options.clone(),
7460    );
7461    minify_test_with_options(
7462      "/*! some license */ /* cssmodules-pure-no-check */ :global(.foo) { color: red }",
7463      "/*! some license */\n.foo{color:red}",
7464      pure_css_module_options.clone(),
7465    );
7466
7467    error_test(
7468      "input.defaultCheckbox::before h1 {width: 20px}",
7469      ParserError::SelectorError(SelectorError::UnexpectedSelectorAfterPseudoElement(Token::Ident(
7470        "h1".into(),
7471      ))),
7472    );
7473    error_test(
7474      "input.defaultCheckbox::before .my-class {width: 20px}",
7475      ParserError::SelectorError(SelectorError::UnexpectedSelectorAfterPseudoElement(Token::Delim('.'))),
7476    );
7477    error_test(
7478      "input.defaultCheckbox::before.my-class {width: 20px}",
7479      ParserError::SelectorError(SelectorError::UnexpectedSelectorAfterPseudoElement(Token::Delim('.'))),
7480    );
7481    error_test(
7482      "input.defaultCheckbox::before #id {width: 20px}",
7483      ParserError::SelectorError(SelectorError::UnexpectedSelectorAfterPseudoElement(Token::IDHash(
7484        "id".into(),
7485      ))),
7486    );
7487    error_test(
7488      "input.defaultCheckbox::before#id {width: 20px}",
7489      ParserError::SelectorError(SelectorError::UnexpectedSelectorAfterPseudoElement(Token::IDHash(
7490        "id".into(),
7491      ))),
7492    );
7493    error_test(
7494      "input.defaultCheckbox::before [attr] {width: 20px}",
7495      ParserError::SelectorError(SelectorError::UnexpectedSelectorAfterPseudoElement(
7496        Token::SquareBracketBlock,
7497      )),
7498    );
7499    error_test(
7500      "input.defaultCheckbox::before[attr] {width: 20px}",
7501      ParserError::SelectorError(SelectorError::UnexpectedSelectorAfterPseudoElement(
7502        Token::SquareBracketBlock,
7503      )),
7504    );
7505  }
7506
7507  #[test]
7508  fn test_keyframes() {
7509    minify_test(
7510      r#"
7511      @keyframes "test" {
7512        100% {
7513          background: blue
7514        }
7515      }
7516    "#,
7517      "@keyframes test{to{background:#00f}}",
7518    );
7519    minify_test(
7520      r#"
7521      @keyframes test {
7522        100% {
7523          background: blue
7524        }
7525      }
7526    "#,
7527      "@keyframes test{to{background:#00f}}",
7528    );
7529
7530    // named animation range percentages
7531    minify_test(
7532      r#"
7533      @keyframes test {
7534        entry 0% {
7535          background: blue
7536        }
7537        exit 100% {
7538          background: green
7539        }
7540      }
7541    "#,
7542      "@keyframes test{entry 0%{background:#00f}exit 100%{background:green}}",
7543    );
7544
7545    // CSS-wide keywords and `none` cannot remove quotes.
7546    minify_test(
7547      r#"
7548      @keyframes "revert" {
7549        from {
7550          background: green;
7551        }
7552      }
7553    "#,
7554      "@keyframes \"revert\"{0%{background:green}}",
7555    );
7556
7557    minify_test(
7558      r#"
7559      @keyframes "none" {
7560        from {
7561          background: green;
7562        }
7563      }
7564    "#,
7565      "@keyframes \"none\"{0%{background:green}}",
7566    );
7567
7568    // named animation ranges cannot be used with to or from
7569    minify_test(
7570      r#"
7571      @keyframes test {
7572        entry to {
7573          background: blue
7574        }
7575      }
7576    "#,
7577      "@keyframes test{}",
7578    );
7579
7580    // CSS-wide keywords without quotes throws an error.
7581    error_test(
7582      r#"
7583      @keyframes revert {}
7584    "#,
7585      ParserError::UnexpectedToken(Token::Ident("revert".into())),
7586    );
7587
7588    error_test(
7589      r#"
7590      @keyframes revert-layer {}
7591    "#,
7592      ParserError::UnexpectedToken(Token::Ident("revert-layer".into())),
7593    );
7594
7595    error_test(
7596      r#"
7597      @keyframes none {}
7598    "#,
7599      ParserError::UnexpectedToken(Token::Ident("none".into())),
7600    );
7601
7602    error_test(
7603      r#"
7604      @keyframes NONE {}
7605    "#,
7606      ParserError::UnexpectedToken(Token::Ident("NONE".into())),
7607    );
7608
7609    minify_test(
7610      r#"
7611      @-webkit-keyframes test {
7612        from {
7613          background: green;
7614          background-color: red;
7615        }
7616
7617        100% {
7618          background: blue
7619        }
7620      }
7621    "#,
7622      "@-webkit-keyframes test{0%{background:red}to{background:#00f}}",
7623    );
7624    minify_test(
7625      r#"
7626      @-moz-keyframes test {
7627        from {
7628          background: green;
7629          background-color: red;
7630        }
7631
7632        100% {
7633          background: blue
7634        }
7635      }
7636    "#,
7637      "@-moz-keyframes test{0%{background:red}to{background:#00f}}",
7638    );
7639    minify_test(r#"
7640      @-webkit-keyframes test {
7641        from {
7642          background: green;
7643          background-color: red;
7644        }
7645
7646        100% {
7647          background: blue
7648        }
7649      }
7650      @-moz-keyframes test {
7651        from {
7652          background: green;
7653          background-color: red;
7654        }
7655
7656        100% {
7657          background: blue
7658        }
7659      }
7660    "#, "@-webkit-keyframes test{0%{background:red}to{background:#00f}}@-moz-keyframes test{0%{background:red}to{background:#00f}}");
7661
7662    prefix_test(
7663      r#"
7664      @keyframes test {
7665        from {
7666          background: green;
7667        }
7668        to {
7669          background: blue
7670        }
7671      }
7672    "#,
7673      indoc! { r#"
7674      @-webkit-keyframes test {
7675        from {
7676          background: green;
7677        }
7678
7679        to {
7680          background: #00f;
7681        }
7682      }
7683
7684      @-moz-keyframes test {
7685        from {
7686          background: green;
7687        }
7688
7689        to {
7690          background: #00f;
7691        }
7692      }
7693
7694      @keyframes test {
7695        from {
7696          background: green;
7697        }
7698
7699        to {
7700          background: #00f;
7701        }
7702      }
7703    "#},
7704      Browsers {
7705        safari: Some(5 << 16),
7706        firefox: Some(6 << 16),
7707        ..Browsers::default()
7708      },
7709    );
7710    prefix_test(
7711      r#"
7712      @-webkit-keyframes test {
7713        from {
7714          background: green;
7715        }
7716
7717        to {
7718          background: blue;
7719        }
7720      }
7721      @-moz-keyframes test {
7722        from {
7723          background: green;
7724        }
7725
7726        to {
7727          background: blue;
7728        }
7729      }
7730      @keyframes test {
7731        from {
7732          background: green;
7733        }
7734        to {
7735          background: blue
7736        }
7737      }
7738    "#,
7739      indoc! { r#"
7740      @keyframes test {
7741        from {
7742          background: green;
7743        }
7744
7745        to {
7746          background: #00f;
7747        }
7748      }
7749    "#},
7750      Browsers {
7751        safari: Some(10 << 16),
7752        firefox: Some(17 << 16),
7753        ..Browsers::default()
7754      },
7755    );
7756    prefix_test(
7757      r#"
7758      @-webkit-keyframes test1 {
7759        from {
7760          background: green;
7761        }
7762
7763        to {
7764          background: blue;
7765        }
7766      }
7767
7768      @-moz-keyframes test2 {
7769        from {
7770          background: green;
7771        }
7772
7773        to {
7774          background: blue;
7775        }
7776      }
7777
7778      @keyframes test3 {
7779        from {
7780          background: green;
7781        }
7782        to {
7783          background: blue
7784        }
7785      }
7786    "#,
7787      indoc! { r#"
7788      @-webkit-keyframes test1 {
7789        from {
7790          background: green;
7791        }
7792
7793        to {
7794          background: #00f;
7795        }
7796      }
7797
7798      @-moz-keyframes test2 {
7799        from {
7800          background: green;
7801        }
7802
7803        to {
7804          background: #00f;
7805        }
7806      }
7807
7808      @keyframes test3 {
7809        from {
7810          background: green;
7811        }
7812
7813        to {
7814          background: #00f;
7815        }
7816      }
7817    "#},
7818      Browsers {
7819        safari: Some(10 << 16),
7820        firefox: Some(17 << 16),
7821        ..Browsers::default()
7822      },
7823    );
7824    prefix_test(
7825      r#"
7826      @-webkit-keyframes test {
7827        from {
7828          background: green;
7829        }
7830
7831        to {
7832          background: red;
7833        }
7834      }
7835      @-moz-keyframes test {
7836        from {
7837          background: green;
7838        }
7839
7840        to {
7841          background: pink;
7842        }
7843      }
7844      @keyframes test {
7845        from {
7846          background: green;
7847        }
7848        to {
7849          background: blue
7850        }
7851      }
7852    "#,
7853      indoc! { r#"
7854      @-webkit-keyframes test {
7855        from {
7856          background: green;
7857        }
7858
7859        to {
7860          background: red;
7861        }
7862      }
7863
7864      @-moz-keyframes test {
7865        from {
7866          background: green;
7867        }
7868
7869        to {
7870          background: pink;
7871        }
7872      }
7873
7874      @keyframes test {
7875        from {
7876          background: green;
7877        }
7878
7879        to {
7880          background: #00f;
7881        }
7882      }
7883    "#},
7884      Browsers {
7885        safari: Some(10 << 16),
7886        firefox: Some(17 << 16),
7887        ..Browsers::default()
7888      },
7889    );
7890
7891    minify_test(
7892      r#"
7893      @keyframes test {
7894        100% {
7895          background: blue
7896        }
7897      }
7898
7899      @keyframes test {
7900        100% {
7901          background: red
7902        }
7903      }
7904    "#,
7905      "@keyframes test{to{background:red}}",
7906    );
7907    minify_test(
7908      r#"
7909      @keyframes test {
7910        100% {
7911          background: blue
7912        }
7913      }
7914
7915      @-webkit-keyframes test {
7916        100% {
7917          background: red
7918        }
7919      }
7920    "#,
7921      "@keyframes test{to{background:#00f}}@-webkit-keyframes test{to{background:red}}",
7922    );
7923  }
7924
7925  #[test]
7926  fn test_important() {
7927    test(
7928      r#"
7929      .foo {
7930        align-items: center;
7931        justify-items: center !important;
7932      }
7933    "#,
7934      indoc! {r#"
7935      .foo {
7936        align-items: center;
7937        justify-items: center !important;
7938      }
7939    "#},
7940    );
7941
7942    test(
7943      r#"
7944      .foo {
7945        justify-items: center !important;
7946        align-items: center;
7947      }
7948    "#,
7949      indoc! {r#"
7950      .foo {
7951        align-items: center;
7952        justify-items: center !important;
7953      }
7954    "#},
7955    );
7956
7957    minify_test(
7958      r#"
7959      .foo {
7960        font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace !important;
7961      }
7962    "#,
7963      ".foo{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace!important}",
7964    );
7965  }
7966
7967  #[test]
7968  fn test_calc() {
7969    minify_test(".foo { width: calc(20px * 2) }", ".foo{width:40px}");
7970    minify_test(".foo { font-size: calc(100vw / 35) }", ".foo{font-size:2.85714vw}");
7971    minify_test(".foo { width: calc(20px * 2 * 3) }", ".foo{width:120px}");
7972    minify_test(".foo { width: calc(20px + 30px) }", ".foo{width:50px}");
7973    minify_test(".foo { width: calc(20px + 30px + 40px) }", ".foo{width:90px}");
7974    minify_test(".foo { width: calc(100% - 30px) }", ".foo{width:calc(100% - 30px)}");
7975    minify_test(
7976      ".foo { width: calc(100% - 30px + 20px) }",
7977      ".foo{width:calc(100% - 10px)}",
7978    );
7979    minify_test(
7980      ".foo { width: calc(20px + 100% - 30px) }",
7981      ".foo{width:calc(100% - 10px)}",
7982    );
7983    minify_test(
7984      ".foo { width: calc(20px + 100% + 10vw - 30px) }",
7985      ".foo{width:calc(100% - 10px + 10vw)}",
7986    );
7987    minify_test(
7988      ".foo { width: calc(20px + 100% - 30px) }",
7989      ".foo{width:calc(100% - 10px)}",
7990    );
7991    minify_test(
7992      ".foo { width: calc(2 * (100% - 20px)) }",
7993      ".foo{width:calc(200% - 40px)}",
7994    );
7995    minify_test(
7996      ".foo { width: calc((100% - 20px) * 2) }",
7997      ".foo{width:calc(200% - 40px)}",
7998    );
7999    minify_test(".foo { width: calc(100% - 20px * 2) }", ".foo{width:calc(100% - 40px)}");
8000    minify_test(".foo { width: calc(1px + 1px) }", ".foo{width:2px}");
8001    minify_test(".foo { width: calc(100vw / 2) }", ".foo{width:50vw}");
8002    minify_test(".foo { width: calc(50px - (20px - 30px)) }", ".foo{width:60px}");
8003    minify_test(".foo { width: calc(100px - (100px - 100%)) }", ".foo{width:100%}");
8004    minify_test(
8005      ".foo { width: calc(100px + (100px - 100%)) }",
8006      ".foo{width:calc(200px - 100%)}",
8007    );
8008    minify_test(
8009      ".foo { width: calc(1px - (2em + 3%)) }",
8010      ".foo{width:calc(1px + -2em - 3%)}",
8011    ); // TODO: fix sign
8012    minify_test(
8013      ".foo { width: calc((100vw - 50em) / 2) }",
8014      ".foo{width:calc(50vw - 25em)}",
8015    );
8016    minify_test(
8017      ".foo { width: calc(1px - (2em + 4vh + 3%)) }",
8018      ".foo{width:calc(1px + -2em - 4vh - 3%)}",
8019    ); // TODO
8020    minify_test(
8021      ".foo { width: calc(1px + (2em + (3vh + 4px))) }",
8022      ".foo{width:calc(2em + 3vh + 5px)}",
8023    );
8024    minify_test(
8025      ".foo { width: calc(1px - (2em + 4px - 6vh) / 2) }",
8026      ".foo{width:calc(-1em - 1px + 3vh)}",
8027    );
8028    minify_test(
8029      ".foo { width: calc(100% - calc(50% + 25px)) }",
8030      ".foo{width:calc(50% - 25px)}",
8031    );
8032    minify_test(".foo { width: calc(1px/100) }", ".foo{width:.01px}");
8033    minify_test(
8034      ".foo { width: calc(100vw / 2 - 6px + 0px) }",
8035      ".foo{width:calc(50vw - 6px)}",
8036    );
8037    minify_test(".foo { width: calc(1px + 1) }", ".foo{width:calc(1px + 1)}");
8038    minify_test(
8039      ".foo { width: calc( (1em - calc( 10px + 1em)) / 2) }",
8040      ".foo{width:-5px}",
8041    );
8042    minify_test(
8043      ".foo { width: calc((100px - 1em) + (-50px + 1em)) }",
8044      ".foo{width:50px}",
8045    );
8046    minify_test(
8047      ".foo { width: calc(100% + (2 * 100px) - ((75.37% - 63.5px) - 900px)) }",
8048      ".foo{width:calc(24.63% + 1163.5px)}",
8049    );
8050    minify_test(
8051      ".foo { width: calc(((((100% + (2 * 30px) + 63.5px) / 0.7537) - (100vw - 60px)) / 2) + 30px) }",
8052      ".foo{width:calc(66.3394% + 141.929px - 50vw)}",
8053    );
8054    minify_test(
8055      ".foo { width: calc(((75.37% - 63.5px) - 900px) + (2 * 100px)) }",
8056      ".foo{width:calc(75.37% - 763.5px)}",
8057    );
8058    minify_test(
8059      ".foo { width: calc((900px - (10% - 63.5px)) + (2 * 100px)) }",
8060      ".foo{width:calc(1163.5px - 10%)}",
8061    );
8062    minify_test(".foo { width: calc(500px/0) }", ".foo{width:calc(500px/0)}");
8063    minify_test(".foo { width: calc(500px/2px) }", ".foo{width:calc(500px/2px)}");
8064    minify_test(".foo { width: calc(100% / 3 * 3) }", ".foo{width:100%}");
8065    minify_test(".foo { width: calc(+100px + +100px) }", ".foo{width:200px}");
8066    minify_test(".foo { width: calc(+100px - +100px) }", ".foo{width:0}");
8067    minify_test(".foo { width: calc(200px * +1) }", ".foo{width:200px}");
8068    minify_test(".foo { width: calc(200px / +1) }", ".foo{width:200px}");
8069    minify_test(".foo { width: calc(1.1e+1px + 1.1e+1px) }", ".foo{width:22px}");
8070    minify_test(".foo { border-width: calc(1px + 2px) }", ".foo{border-width:3px}");
8071    minify_test(
8072      ".foo { border-width: calc(1em + 2px + 2em + 3px) }",
8073      ".foo{border-width:calc(3em + 5px)}",
8074    );
8075
8076    minify_test(
8077      ".foo { border-width: min(1em, 2px) }",
8078      ".foo{border-width:min(1em,2px)}",
8079    );
8080    minify_test(
8081      ".foo { border-width: min(1em + 2em, 2px + 2px) }",
8082      ".foo{border-width:min(3em,4px)}",
8083    );
8084    minify_test(
8085      ".foo { border-width: min(1em + 2px, 2px + 1em) }",
8086      ".foo{border-width:min(1em + 2px,2px + 1em)}",
8087    );
8088    minify_test(
8089      ".foo { border-width: min(1em + 2px + 2px, 2px + 1em + 1px) }",
8090      ".foo{border-width:min(1em + 4px,3px + 1em)}",
8091    );
8092    minify_test(
8093      ".foo { border-width: min(2px + 1px, 3px + 4px) }",
8094      ".foo{border-width:3px}",
8095    );
8096    minify_test(
8097      ".foo { border-width: min(1px, 1em, 2px, 3in) }",
8098      ".foo{border-width:min(1px,1em)}",
8099    );
8100
8101    minify_test(
8102      ".foo { border-width: max(1em, 2px) }",
8103      ".foo{border-width:max(1em,2px)}",
8104    );
8105    minify_test(
8106      ".foo { border-width: max(1em + 2em, 2px + 2px) }",
8107      ".foo{border-width:max(3em,4px)}",
8108    );
8109    minify_test(
8110      ".foo { border-width: max(1em + 2px, 2px + 1em) }",
8111      ".foo{border-width:max(1em + 2px,2px + 1em)}",
8112    );
8113    minify_test(
8114      ".foo { border-width: max(1em + 2px + 2px, 2px + 1em + 1px) }",
8115      ".foo{border-width:max(1em + 4px,3px + 1em)}",
8116    );
8117    minify_test(
8118      ".foo { border-width: max(2px + 1px, 3px + 4px) }",
8119      ".foo{border-width:7px}",
8120    );
8121    minify_test(
8122      ".foo { border-width: max(1px, 1em, 2px, 3in) }",
8123      ".foo{border-width:max(3in,1em)}",
8124    );
8125
8126    minify_test(".foo { border-width: clamp(1px, 2px, 3px) }", ".foo{border-width:2px}");
8127    minify_test(".foo { border-width: clamp(1px, 10px, 3px) }", ".foo{border-width:3px}");
8128    minify_test(".foo { border-width: clamp(5px, 2px, 10px) }", ".foo{border-width:5px}");
8129    minify_test(
8130      ".foo { border-width: clamp(100px, 2px, 10px) }",
8131      ".foo{border-width:100px}",
8132    );
8133    minify_test(
8134      ".foo { border-width: clamp(5px + 5px, 5px + 7px, 10px + 20px) }",
8135      ".foo{border-width:12px}",
8136    );
8137
8138    minify_test(
8139      ".foo { border-width: clamp(1em, 2px, 4vh) }",
8140      ".foo{border-width:clamp(1em,2px,4vh)}",
8141    );
8142    minify_test(
8143      ".foo { border-width: clamp(1em, 2em, 4vh) }",
8144      ".foo{border-width:clamp(1em,2em,4vh)}",
8145    );
8146    minify_test(
8147      ".foo { border-width: clamp(1em, 2vh, 4vh) }",
8148      ".foo{border-width:max(1em,2vh)}",
8149    );
8150    minify_test(
8151      ".foo { border-width: clamp(1px, 1px + 2em, 4px) }",
8152      ".foo{border-width:clamp(1px,1px + 2em,4px)}",
8153    );
8154    minify_test(".foo { border-width: clamp(1px, 2pt, 1in) }", ".foo{border-width:2pt}");
8155    minify_test(
8156      ".foo { width: clamp(-100px, 0px, 50% - 50vw); }",
8157      ".foo{width:clamp(-100px,0px,50% - 50vw)}",
8158    );
8159
8160    minify_test(
8161      ".foo { top: calc(-1 * clamp(1.75rem, 8vw, 4rem)) }",
8162      ".foo{top:calc(-1*clamp(1.75rem,8vw,4rem))}",
8163    );
8164    minify_test(
8165      ".foo { top: calc(-1 * min(1.75rem, 8vw, 4rem)) }",
8166      ".foo{top:calc(-1*min(1.75rem,8vw))}",
8167    );
8168    minify_test(
8169      ".foo { top: calc(-1 * max(1.75rem, 8vw, 4rem)) }",
8170      ".foo{top:calc(-1*max(4rem,8vw))}",
8171    );
8172    minify_test(
8173      ".foo { top: calc(clamp(1.75rem, 8vw, 4rem) * -1) }",
8174      ".foo{top:calc(-1*clamp(1.75rem,8vw,4rem))}",
8175    );
8176    minify_test(
8177      ".foo { top: calc(min(1.75rem, 8vw, 4rem) * -1) }",
8178      ".foo{top:calc(-1*min(1.75rem,8vw))}",
8179    );
8180    minify_test(
8181      ".foo { top: calc(max(1.75rem, 8vw, 4rem) * -1) }",
8182      ".foo{top:calc(-1*max(4rem,8vw))}",
8183    );
8184    minify_test(
8185      ".foo { top: calc(clamp(1.75rem, 8vw, 4rem) / 2) }",
8186      ".foo{top:calc(clamp(1.75rem,8vw,4rem)/2)}",
8187    );
8188    minify_test(
8189      ".foo { top: calc(min(1.75rem, 8vw, 4rem) / 2) }",
8190      ".foo{top:calc(min(1.75rem,8vw)/2)}",
8191    );
8192    minify_test(
8193      ".foo { top: calc(max(1.75rem, 8vw, 4rem) / 2) }",
8194      ".foo{top:calc(max(4rem,8vw)/2)}",
8195    );
8196    minify_test(
8197      ".foo { top: calc(0.5 * clamp(1.75rem, 8vw, 4rem)) }",
8198      ".foo{top:calc(clamp(1.75rem,8vw,4rem)/2)}",
8199    );
8200    minify_test(
8201      ".foo { top: calc(1 * clamp(1.75rem, 8vw, 4rem)) }",
8202      ".foo{top:calc(clamp(1.75rem,8vw,4rem))}",
8203    );
8204    minify_test(
8205      ".foo { top: calc(2 * clamp(1.75rem, 8vw, 4rem) / 2) }",
8206      ".foo{top:calc(clamp(1.75rem,8vw,4rem))}",
8207    );
8208
8209    minify_test(".foo { width: max(0px, 1vw) }", ".foo{width:max(0px,1vw)}");
8210
8211    prefix_test(
8212      ".foo { border-width: clamp(1em, 2px, 4vh) }",
8213      indoc! { r#"
8214        .foo {
8215          border-width: max(1em, min(2px, 4vh));
8216        }
8217      "#},
8218      Browsers {
8219        safari: Some(12 << 16),
8220        ..Browsers::default()
8221      },
8222    );
8223
8224    prefix_test(
8225      ".foo { border-width: clamp(1em, 2px, 4vh) }",
8226      indoc! { r#"
8227        .foo {
8228          border-width: clamp(1em, 2px, 4vh);
8229        }
8230      "#},
8231      Browsers {
8232        safari: Some(14 << 16),
8233        ..Browsers::default()
8234      },
8235    );
8236
8237    minify_test(".foo { width: calc(1vh + 2vh) }", ".foo{width:3vh}");
8238    minify_test(".foo { width: calc(1dvh + 2dvh) }", ".foo{width:3dvh}");
8239    minify_test(".foo { width: calc(1lvh + 2lvh) }", ".foo{width:3lvh}");
8240    minify_test(".foo { width: calc(1svh + 2svh) }", ".foo{width:3svh}");
8241    minify_test(".foo { width: calc(1sVmin + 2Svmin) }", ".foo{width:3svmin}");
8242    minify_test(".foo { width: calc(1ic + 2ic) }", ".foo{width:3ic}");
8243    minify_test(".foo { width: calc(1ric + 2ric) }", ".foo{width:3ric}");
8244    minify_test(".foo { width: calc(1cap + 2cap) }", ".foo{width:3cap}");
8245    minify_test(".foo { width: calc(1lh + 2lh) }", ".foo{width:3lh}");
8246    minify_test(".foo { width: calc(1x + 2x) }", ".foo{width:calc(1x + 2x)}");
8247    minify_test(
8248      ".foo { left: calc(50% - 100px + clamp(0px, calc(50vw - 50px), 100px)) }",
8249      ".foo{left:calc(50% - 100px + clamp(0px,50vw - 50px,100px))}",
8250    );
8251    minify_test(
8252      ".foo { left: calc(10px + min(10px, 1rem) + max(2px, 1vw)) }",
8253      ".foo{left:calc(10px + min(10px,1rem) + max(2px,1vw))}",
8254    );
8255    minify_test(".foo { width: round(22px, 5px) }", ".foo{width:20px}");
8256    minify_test(".foo { width: round(nearest, 22px, 5px) }", ".foo{width:20px}");
8257    minify_test(".foo { width: round(down, 22px, 5px) }", ".foo{width:20px}");
8258    minify_test(".foo { width: round(to-zero, 22px, 5px) }", ".foo{width:20px}");
8259    minify_test(".foo { width: round(up, 22px, 5px) }", ".foo{width:25px}");
8260    minify_test(".foo { width: round(23px, 5px) }", ".foo{width:25px}");
8261    minify_test(".foo { width: round(nearest, 23px, 5px) }", ".foo{width:25px}");
8262    minify_test(".foo { width: round(down, 23px, 5px) }", ".foo{width:20px}");
8263    minify_test(".foo { width: round(to-zero, 23px, 5px) }", ".foo{width:20px}");
8264    minify_test(".foo { width: round(up, 23px, 5px) }", ".foo{width:25px}");
8265    minify_test(".foo { width: round(22px, 5vw) }", ".foo{width:round(22px,5vw)}");
8266    minify_test(".foo { rotate: round(22deg, 5deg) }", ".foo{rotate:20deg}");
8267    minify_test(".foo { rotate: round(22deg, 5deg) }", ".foo{rotate:20deg}");
8268    minify_test(
8269      ".foo { transition-duration: round(22ms, 5ms) }",
8270      ".foo{transition-duration:20ms}",
8271    );
8272    minify_test(".foo { margin: round(to-zero, -23px, 5px) }", ".foo{margin:-20px}");
8273    minify_test(".foo { margin: round(nearest, -23px, 5px) }", ".foo{margin:-25px}");
8274    minify_test(".foo { margin: calc(10px * round(22, 5)) }", ".foo{margin:200px}");
8275    minify_test(".foo { width: rem(18px, 5px) }", ".foo{width:3px}");
8276    minify_test(".foo { width: rem(-18px, 5px) }", ".foo{width:-3px}");
8277    minify_test(".foo { width: rem(18px, 5vw) }", ".foo{width:rem(18px,5vw)}");
8278    minify_test(".foo { rotate: rem(-140deg, -90deg) }", ".foo{rotate:-50deg}");
8279    minify_test(".foo { rotate: rem(140deg, -90deg) }", ".foo{rotate:50deg}");
8280    minify_test(".foo { width: calc(10px * rem(18, 5)) }", ".foo{width:30px}");
8281    minify_test(".foo { width: mod(18px, 5px) }", ".foo{width:3px}");
8282    minify_test(".foo { width: mod(-18px, 5px) }", ".foo{width:2px}");
8283    minify_test(".foo { rotate: mod(-140deg, -90deg) }", ".foo{rotate:-50deg}");
8284    minify_test(".foo { rotate: mod(140deg, -90deg) }", ".foo{rotate:-40deg}");
8285    minify_test(".foo { width: mod(18px, 5vw) }", ".foo{width:mod(18px,5vw)}");
8286    minify_test(
8287      ".foo { transform: rotateX(mod(140deg, -90deg)) rotateY(rem(140deg, -90deg)) }",
8288      ".foo{transform:rotateX(-40deg)rotateY(50deg)}",
8289    );
8290    minify_test(".foo { width: calc(10px * mod(18, 5)) }", ".foo{width:30px}");
8291
8292    minify_test(
8293      ".foo { width: calc(100% - 30px - 0) }",
8294      ".foo{width:calc(100% - 30px - 0)}",
8295    );
8296    minify_test(
8297      ".foo { width: calc(100% - 30px - 1 - 2) }",
8298      ".foo{width:calc(100% - 30px - 3)}",
8299    );
8300    minify_test(
8301      ".foo { width: calc(1 - 2 - 100% - 30px) }",
8302      ".foo{width:calc(-1 - 100% - 30px)}",
8303    );
8304    minify_test(
8305      ".foo { width: calc(2 * min(1px, 1vmin) - min(1px, 1vmin)); }",
8306      ".foo{width:calc(2*min(1px,1vmin) - min(1px,1vmin))}",
8307    );
8308    minify_test(
8309      ".foo { width: calc(100% - clamp(1.125rem, 1.25vw, 1.2375rem) - clamp(1.125rem, 1.25vw, 1.2375rem)); }",
8310      ".foo{width:calc(100% - clamp(1.125rem,1.25vw,1.2375rem) - clamp(1.125rem,1.25vw,1.2375rem))}",
8311    );
8312    minify_test(
8313      ".foo { width: calc(100% - 2 (2 * var(--card-margin))); }",
8314      ".foo{width:calc(100% - 2 (2 * var(--card-margin)))}",
8315    );
8316
8317    test(
8318      indoc! {r#"
8319    .test {
8320      width: calc(var(--test) + 2px);
8321      width: calc(var(--test) - 2px);
8322    }
8323    "#},
8324      indoc! {r#"
8325    .test {
8326      width: calc(var(--test) + 2px);
8327      width: calc(var(--test) - 2px);
8328    }
8329    "#},
8330    );
8331  }
8332
8333  #[test]
8334  fn test_trig() {
8335    minify_test(".foo { width: calc(2px * pi); }", ".foo{width:6.28319px}");
8336    minify_test(".foo { width: calc(2px / pi); }", ".foo{width:.63662px}");
8337    // minify_test(
8338    //   ".foo { width: calc(2px * infinity); }",
8339    //   ".foo{width:calc(2px*infinity)}",
8340    // );
8341    // minify_test(
8342    //   ".foo { width: calc(2px * -infinity); }",
8343    //   ".foo{width:calc(2px*-infinity)}",
8344    // );
8345    minify_test(".foo { width: calc(100px * sin(45deg))", ".foo{width:70.7107px}");
8346    minify_test(".foo { width: calc(100px * sin(.125turn))", ".foo{width:70.7107px}");
8347    minify_test(
8348      ".foo { width: calc(100px * sin(3.14159265 / 4))",
8349      ".foo{width:70.7107px}",
8350    );
8351    minify_test(".foo { width: calc(100px * sin(pi / 4))", ".foo{width:70.7107px}");
8352    minify_test(
8353      ".foo { width: calc(100px * sin(22deg + 23deg))",
8354      ".foo{width:70.7107px}",
8355    );
8356
8357    minify_test(".foo { width: calc(2px * cos(45deg))", ".foo{width:1.41421px}");
8358    minify_test(".foo { width: calc(2px * tan(45deg))", ".foo{width:2px}");
8359
8360    minify_test(".foo { rotate: asin(sin(45deg))", ".foo{rotate:45deg}");
8361    minify_test(".foo { rotate: asin(1)", ".foo{rotate:90deg}");
8362    minify_test(".foo { rotate: asin(-1)", ".foo{rotate:-90deg}");
8363    minify_test(".foo { rotate: asin(0.5)", ".foo{rotate:30deg}");
8364    minify_test(".foo { rotate: asin(45deg)", ".foo{rotate:asin(45deg)}"); // invalid
8365    minify_test(".foo { rotate: asin(-20)", ".foo{rotate:asin(-20)}"); // evaluates to NaN
8366    minify_test(".foo { width: asin(sin(45deg))", ".foo{width:asin(sin(45deg))}"); // invalid
8367
8368    minify_test(".foo { rotate: acos(cos(45deg))", ".foo{rotate:45deg}");
8369    minify_test(".foo { rotate: acos(-1)", ".foo{rotate:180deg}");
8370    minify_test(".foo { rotate: acos(0)", ".foo{rotate:90deg}");
8371    minify_test(".foo { rotate: acos(1)", ".foo{rotate:0deg}");
8372    minify_test(".foo { rotate: acos(45deg)", ".foo{rotate:acos(45deg)}"); // invalid
8373    minify_test(".foo { rotate: acos(-20)", ".foo{rotate:acos(-20)}"); // evaluates to NaN
8374
8375    minify_test(".foo { rotate: atan(tan(45deg))", ".foo{rotate:45deg}");
8376    minify_test(".foo { rotate: atan(1)", ".foo{rotate:45deg}");
8377    minify_test(".foo { rotate: atan(0)", ".foo{rotate:0deg}");
8378    minify_test(".foo { rotate: atan(45deg)", ".foo{rotate:atan(45deg)}"); // invalid
8379
8380    minify_test(".foo { rotate: atan2(1px, -1px)", ".foo{rotate:135deg}");
8381    minify_test(".foo { rotate: atan2(1vw, -1vw)", ".foo{rotate:135deg}");
8382    minify_test(".foo { rotate: atan2(1, -1)", ".foo{rotate:135deg}");
8383    minify_test(".foo { rotate: atan2(1ms, -1ms)", ".foo{rotate:135deg}");
8384    minify_test(".foo { rotate: atan2(1%, -1%)", ".foo{rotate:135deg}");
8385    minify_test(".foo { rotate: atan2(1deg, -1deg)", ".foo{rotate:135deg}");
8386    minify_test(".foo { rotate: atan2(1cm, 1mm)", ".foo{rotate:84.2894deg}");
8387    minify_test(".foo { rotate: atan2(0, -1)", ".foo{rotate:180deg}");
8388    minify_test(".foo { rotate: atan2(-1, 1)", ".foo{rotate:-45deg}");
8389    // incompatible units
8390    minify_test(".foo { rotate: atan2(1px, -1vw)", ".foo{rotate:atan2(1px, -1vw)}");
8391
8392    minify_test(".foo { transform: rotate(acos(1)) }", ".foo{transform:rotate(0)}");
8393    minify_test(".foo { transform: rotate(atan(0)) }", ".foo{transform:rotate(0)}");
8394  }
8395
8396  #[test]
8397  fn test_exp() {
8398    minify_test(".foo { width: hypot()", ".foo{width:hypot()}");
8399    minify_test(".foo { width: hypot(1px)", ".foo{width:1px}");
8400    minify_test(".foo { width: hypot(1px, 2px)", ".foo{width:2.23607px}");
8401    minify_test(".foo { width: hypot(1px, 2px, 3px)", ".foo{width:3.74166px}");
8402    minify_test(".foo { width: hypot(1px, 2vw)", ".foo{width:hypot(1px,2vw)}");
8403    minify_test(".foo { width: hypot(1px, 2px, 3vw)", ".foo{width:hypot(1px,2px,3vw)}");
8404    minify_test(".foo { width: calc(100px * hypot(3, 4))", ".foo{width:500px}");
8405    minify_test(".foo { width: calc(1px * pow(2, sqrt(100))", ".foo{width:1024px}");
8406    minify_test(".foo { width: calc(100px * pow(2, pow(2, 2)", ".foo{width:1600px}");
8407    minify_test(".foo { width: calc(1px * log(1))", ".foo{width:0}");
8408    minify_test(".foo { width: calc(1px * log(10, 10))", ".foo{width:1px}");
8409    minify_test(".foo { width: calc(1px * exp(0))", ".foo{width:1px}");
8410    minify_test(".foo { width: calc(1px * log(e))", ".foo{width:1px}");
8411    minify_test(".foo { width: calc(1px * (e - exp(1)))", ".foo{width:0}");
8412    minify_test(
8413      ".foo { width: calc(1px * (exp(log(1) + exp(0)*2))",
8414      ".foo{width:7.38906px}",
8415    );
8416  }
8417
8418  #[test]
8419  fn test_sign() {
8420    minify_test(".foo { width: abs(1px)", ".foo{width:1px}");
8421    minify_test(".foo { width: abs(-1px)", ".foo{width:1px}");
8422    minify_test(".foo { width: abs(1%)", ".foo{width:abs(1%)}"); // spec says percentages must be against resolved value
8423
8424    minify_test(".foo { width: calc(10px * sign(-1vw)", ".foo{width:-10px}");
8425    minify_test(
8426      ".foo { width: calc(10px * sign(1%)",
8427      ".foo{width:calc(10px * sign(1%))}",
8428    );
8429  }
8430
8431  #[test]
8432  fn test_box_shadow() {
8433    minify_test(
8434      ".foo { box-shadow: 64px 64px 12px 40px rgba(0,0,0,0.4) }",
8435      ".foo{box-shadow:64px 64px 12px 40px #0006}",
8436    );
8437    minify_test(
8438      ".foo { box-shadow: 12px 12px 0px 8px rgba(0,0,0,0.4) inset }",
8439      ".foo{box-shadow:inset 12px 12px 0 8px #0006}",
8440    );
8441    minify_test(
8442      ".foo { box-shadow: inset 12px 12px 0px 8px rgba(0,0,0,0.4) }",
8443      ".foo{box-shadow:inset 12px 12px 0 8px #0006}",
8444    );
8445    minify_test(
8446      ".foo { box-shadow: 12px 12px 8px 0px rgba(0,0,0,0.4) }",
8447      ".foo{box-shadow:12px 12px 8px #0006}",
8448    );
8449    minify_test(
8450      ".foo { box-shadow: 12px 12px 0px 0px rgba(0,0,0,0.4) }",
8451      ".foo{box-shadow:12px 12px #0006}",
8452    );
8453    minify_test(
8454      ".foo { box-shadow: 64px 64px 12px 40px rgba(0,0,0,0.4), 12px 12px 0px 8px rgba(0,0,0,0.4) inset }",
8455      ".foo{box-shadow:64px 64px 12px 40px #0006,inset 12px 12px 0 8px #0006}",
8456    );
8457
8458    prefix_test(
8459      ".foo { box-shadow: 12px 12px lab(40% 56.6 39) }",
8460      indoc! { r#"
8461        .foo {
8462          box-shadow: 12px 12px #b32323;
8463          box-shadow: 12px 12px lab(40% 56.6 39);
8464        }
8465      "#},
8466      Browsers {
8467        chrome: Some(90 << 16),
8468        ..Browsers::default()
8469      },
8470    );
8471
8472    prefix_test(
8473      ".foo { box-shadow: 12px 12px lab(40% 56.6 39) }",
8474      indoc! { r#"
8475        .foo {
8476          -webkit-box-shadow: 12px 12px #b32323;
8477          box-shadow: 12px 12px #b32323;
8478          box-shadow: 12px 12px lab(40% 56.6 39);
8479        }
8480      "#},
8481      Browsers {
8482        chrome: Some(4 << 16),
8483        ..Browsers::default()
8484      },
8485    );
8486
8487    prefix_test(
8488      ".foo { box-shadow: 12px 12px lab(40% 56.6 39), 12px 12px yellow }",
8489      indoc! { r#"
8490        .foo {
8491          -webkit-box-shadow: 12px 12px #b32323, 12px 12px #ff0;
8492          box-shadow: 12px 12px #b32323, 12px 12px #ff0;
8493          box-shadow: 12px 12px lab(40% 56.6 39), 12px 12px #ff0;
8494        }
8495      "#},
8496      Browsers {
8497        chrome: Some(4 << 16),
8498        ..Browsers::default()
8499      },
8500    );
8501
8502    prefix_test(
8503      ".foo { -webkit-box-shadow: 12px 12px #0006 }",
8504      indoc! { r#"
8505        .foo {
8506          -webkit-box-shadow: 12px 12px rgba(0, 0, 0, .4);
8507        }
8508      "#},
8509      Browsers {
8510        chrome: Some(4 << 16),
8511        ..Browsers::default()
8512      },
8513    );
8514
8515    prefix_test(
8516      ".foo {
8517        -webkit-box-shadow: 12px 12px #0006;
8518        -moz-box-shadow: 12px 12px #0009;
8519      }",
8520      indoc! { r#"
8521        .foo {
8522          -webkit-box-shadow: 12px 12px rgba(0, 0, 0, .4);
8523          -moz-box-shadow: 12px 12px rgba(0, 0, 0, .6);
8524        }
8525      "#},
8526      Browsers {
8527        chrome: Some(4 << 16),
8528        ..Browsers::default()
8529      },
8530    );
8531
8532    prefix_test(
8533      ".foo {
8534        -webkit-box-shadow: 12px 12px #0006;
8535        -moz-box-shadow: 12px 12px #0006;
8536        box-shadow: 12px 12px #0006;
8537      }",
8538      indoc! { r#"
8539        .foo {
8540          box-shadow: 12px 12px #0006;
8541        }
8542      "#},
8543      Browsers {
8544        chrome: Some(95 << 16),
8545        ..Browsers::default()
8546      },
8547    );
8548
8549    prefix_test(
8550      ".foo { box-shadow: var(--foo) 12px lab(40% 56.6 39) }",
8551      indoc! { r#"
8552        .foo {
8553          box-shadow: var(--foo) 12px #b32323;
8554        }
8555
8556        @supports (color: lab(0% 0 0)) {
8557          .foo {
8558            box-shadow: var(--foo) 12px lab(40% 56.6 39);
8559          }
8560        }
8561      "#},
8562      Browsers {
8563        chrome: Some(90 << 16),
8564        ..Browsers::default()
8565      },
8566    );
8567
8568    prefix_test(
8569      r#"
8570      .foo {
8571        box-shadow: 0px 0px 22px red;
8572        box-shadow: 0px 0px max(2cqw, 22px) red;
8573      }
8574    "#,
8575      indoc! {r#"
8576      .foo {
8577        box-shadow: 0 0 22px red;
8578        box-shadow: 0 0 max(2cqw, 22px) red;
8579      }
8580    "#
8581      },
8582      Browsers {
8583        safari: Some(14 << 16),
8584        ..Browsers::default()
8585      },
8586    );
8587    prefix_test(
8588      r#"
8589      .foo {
8590        box-shadow: 0px 0px 22px red;
8591        box-shadow: 0px 0px max(2cqw, 22px) red;
8592      }
8593    "#,
8594      indoc! {r#"
8595      .foo {
8596        box-shadow: 0 0 max(2cqw, 22px) red;
8597      }
8598    "#
8599      },
8600      Browsers {
8601        safari: Some(16 << 16),
8602        ..Browsers::default()
8603      },
8604    );
8605
8606    prefix_test(
8607      r#"
8608      .foo {
8609        box-shadow: 0px 0px 22px red;
8610        box-shadow: 0px 0px 22px lab(40% 56.6 39);
8611      }
8612    "#,
8613      indoc! {r#"
8614      .foo {
8615        box-shadow: 0 0 22px red;
8616        box-shadow: 0 0 22px lab(40% 56.6 39);
8617      }
8618    "#
8619      },
8620      Browsers {
8621        safari: Some(14 << 16),
8622        ..Browsers::default()
8623      },
8624    );
8625    prefix_test(
8626      r#"
8627      .foo {
8628        box-shadow: 0px 0px 22px red;
8629        box-shadow: 0px 0px 22px lab(40% 56.6 39);
8630      }
8631    "#,
8632      indoc! {r#"
8633      .foo {
8634        box-shadow: 0 0 22px lab(40% 56.6 39);
8635      }
8636    "#
8637      },
8638      Browsers {
8639        safari: Some(16 << 16),
8640        ..Browsers::default()
8641      },
8642    );
8643
8644    prefix_test(
8645      r#"
8646      .foo {
8647        box-shadow: var(--fallback);
8648        box-shadow: 0px 0px 22px lab(40% 56.6 39);
8649      }
8650    "#,
8651      indoc! {r#"
8652      .foo {
8653        box-shadow: var(--fallback);
8654        box-shadow: 0 0 22px lab(40% 56.6 39);
8655      }
8656    "#
8657      },
8658      Browsers {
8659        safari: Some(16 << 16),
8660        ..Browsers::default()
8661      },
8662    );
8663  }
8664
8665  #[test]
8666  fn test_media() {
8667    minify_test(
8668      "@media (min-width: 240px) { .foo { color: chartreuse }}",
8669      "@media (width>=240px){.foo{color:#7fff00}}",
8670    );
8671    minify_test(
8672      "@media (width < 240px) { .foo { color: chartreuse }}",
8673      "@media (width<240px){.foo{color:#7fff00}}",
8674    );
8675    minify_test(
8676      "@media (width <= 240px) { .foo { color: chartreuse }}",
8677      "@media (width<=240px){.foo{color:#7fff00}}",
8678    );
8679    minify_test(
8680      "@media (width > 240px) { .foo { color: chartreuse }}",
8681      "@media (width>240px){.foo{color:#7fff00}}",
8682    );
8683    minify_test(
8684      "@media (width >= 240px) { .foo { color: chartreuse }}",
8685      "@media (width>=240px){.foo{color:#7fff00}}",
8686    );
8687    minify_test(
8688      "@media (240px < width) { .foo { color: chartreuse }}",
8689      "@media (width>240px){.foo{color:#7fff00}}",
8690    );
8691    minify_test(
8692      "@media (240px <= width) { .foo { color: chartreuse }}",
8693      "@media (width>=240px){.foo{color:#7fff00}}",
8694    );
8695    minify_test(
8696      "@media (240px > width) { .foo { color: chartreuse }}",
8697      "@media (width<240px){.foo{color:#7fff00}}",
8698    );
8699    minify_test(
8700      "@media (240px >= width) { .foo { color: chartreuse }}",
8701      "@media (width<=240px){.foo{color:#7fff00}}",
8702    );
8703    minify_test(
8704      "@media (100px < width < 200px) { .foo { color: chartreuse }}",
8705      "@media (100px<width<200px){.foo{color:#7fff00}}",
8706    );
8707    minify_test(
8708      "@media (100px <= width <= 200px) { .foo { color: chartreuse }}",
8709      "@media (100px<=width<=200px){.foo{color:#7fff00}}",
8710    );
8711    minify_test(
8712      "@media (min-width: 30em) and (max-width: 50em) { .foo { color: chartreuse }}",
8713      "@media (width>=30em) and (width<=50em){.foo{color:#7fff00}}",
8714    );
8715    minify_test(
8716      "@media screen, print { .foo { color: chartreuse }}",
8717      "@media screen,print{.foo{color:#7fff00}}",
8718    );
8719    minify_test(
8720      "@media (hover: hover) { .foo { color: chartreuse }}",
8721      "@media (hover:hover){.foo{color:#7fff00}}",
8722    );
8723    minify_test(
8724      "@media (hover) { .foo { color: chartreuse }}",
8725      "@media (hover){.foo{color:#7fff00}}",
8726    );
8727    minify_test(
8728      "@media (aspect-ratio: 11/5) { .foo { color: chartreuse }}",
8729      "@media (aspect-ratio:11/5){.foo{color:#7fff00}}",
8730    );
8731    minify_test(
8732      "@media (aspect-ratio: 2/1) { .foo { color: chartreuse }}",
8733      "@media (aspect-ratio:2){.foo{color:#7fff00}}",
8734    );
8735    minify_test(
8736      "@media (aspect-ratio: 2) { .foo { color: chartreuse }}",
8737      "@media (aspect-ratio:2){.foo{color:#7fff00}}",
8738    );
8739    minify_test(
8740      "@media not screen and (color) { .foo { color: chartreuse }}",
8741      "@media not screen and (color){.foo{color:#7fff00}}",
8742    );
8743    minify_test(
8744      "@media only screen and (color) { .foo { color: chartreuse }}",
8745      "@media only screen and (color){.foo{color:#7fff00}}",
8746    );
8747    minify_test(
8748      "@media (update: slow) or (hover: none) { .foo { color: chartreuse }}",
8749      "@media (update:slow) or (hover:none){.foo{color:#7fff00}}",
8750    );
8751    minify_test(
8752      "@media (width < 600px) and (height < 600px) { .foo { color: chartreuse }}",
8753      "@media (width<600px) and (height<600px){.foo{color:#7fff00}}",
8754    );
8755    minify_test(
8756      "@media (not (color)) or (hover) { .foo { color: chartreuse }}",
8757      "@media (not (color)) or (hover){.foo{color:#7fff00}}",
8758    );
8759    error_test(
8760      "@media (example, all,), speech { .foo { color: chartreuse }}",
8761      ParserError::UnexpectedToken(Token::Comma),
8762    );
8763    error_test(
8764      "@media &test, speech { .foo { color: chartreuse }}",
8765      ParserError::UnexpectedToken(Token::Delim('&')),
8766    );
8767    error_test(
8768      "@media &test { .foo { color: chartreuse }}",
8769      ParserError::UnexpectedToken(Token::Delim('&')),
8770    );
8771    minify_test(
8772      "@media (min-width: calc(200px + 40px)) { .foo { color: chartreuse }}",
8773      "@media (width>=240px){.foo{color:#7fff00}}",
8774    );
8775    minify_test(
8776      "@media (min-width: calc(1em + 5px)) { .foo { color: chartreuse }}",
8777      "@media (width>=calc(1em + 5px)){.foo{color:#7fff00}}",
8778    );
8779    minify_test("@media { .foo { color: chartreuse }}", ".foo{color:#7fff00}");
8780    minify_test("@media all { .foo { color: chartreuse }}", ".foo{color:#7fff00}");
8781    minify_test(
8782      "@media not (((color) or (hover))) { .foo { color: chartreuse }}",
8783      "@media not ((color) or (hover)){.foo{color:#7fff00}}",
8784    );
8785    minify_test(
8786      "@media (hover) and ((color) and (test)) { .foo { color: chartreuse }}",
8787      "@media (hover) and (color) and (test){.foo{color:#7fff00}}",
8788    );
8789    minify_test(
8790      "@media (grid: 1) { .foo { color: chartreuse }}",
8791      "@media (grid:1){.foo{color:#7fff00}}",
8792    );
8793    minify_test(
8794      "@media (width >= calc(2px + 4px)) { .foo { color: chartreuse }}",
8795      "@media (width>=6px){.foo{color:#7fff00}}",
8796    );
8797
8798    prefix_test(
8799      r#"
8800        @media (width >= 240px) {
8801          .foo {
8802            color: chartreuse;
8803          }
8804        }
8805      "#,
8806      indoc! { r#"
8807        @media (min-width: 240px) {
8808          .foo {
8809            color: #7fff00;
8810          }
8811        }
8812      "#},
8813      Browsers {
8814        firefox: Some(60 << 16),
8815        ..Browsers::default()
8816      },
8817    );
8818
8819    prefix_test(
8820      r#"
8821        @media (width >= 240px) {
8822          .foo {
8823            color: chartreuse;
8824          }
8825        }
8826      "#,
8827      indoc! { r#"
8828        @media (width >= 240px) {
8829          .foo {
8830            color: #7fff00;
8831          }
8832        }
8833      "#},
8834      Browsers {
8835        firefox: Some(64 << 16),
8836        ..Browsers::default()
8837      },
8838    );
8839
8840    prefix_test(
8841      r#"
8842        @media (color > 2) {
8843          .foo {
8844            color: chartreuse;
8845          }
8846        }
8847      "#,
8848      indoc! { r#"
8849        @media not (max-color: 2) {
8850          .foo {
8851            color: #7fff00;
8852          }
8853        }
8854      "#},
8855      Browsers {
8856        firefox: Some(60 << 16),
8857        ..Browsers::default()
8858      },
8859    );
8860
8861    prefix_test(
8862      r#"
8863        @media (color < 2) {
8864          .foo {
8865            color: chartreuse;
8866          }
8867        }
8868      "#,
8869      indoc! { r#"
8870        @media not (min-color: 2) {
8871          .foo {
8872            color: #7fff00;
8873          }
8874        }
8875      "#},
8876      Browsers {
8877        firefox: Some(60 << 16),
8878        ..Browsers::default()
8879      },
8880    );
8881
8882    prefix_test(
8883      r#"
8884        @media (width > 240px) {
8885          .foo {
8886            color: chartreuse;
8887          }
8888        }
8889      "#,
8890      indoc! { r#"
8891        @media not (max-width: 240px) {
8892          .foo {
8893            color: #7fff00;
8894          }
8895        }
8896      "#},
8897      Browsers {
8898        firefox: Some(60 << 16),
8899        ..Browsers::default()
8900      },
8901    );
8902
8903    prefix_test(
8904      r#"
8905        @media (width <= 240px) {
8906          .foo {
8907            color: chartreuse;
8908          }
8909        }
8910      "#,
8911      indoc! { r#"
8912        @media (max-width: 240px) {
8913          .foo {
8914            color: #7fff00;
8915          }
8916        }
8917      "#},
8918      Browsers {
8919        firefox: Some(60 << 16),
8920        ..Browsers::default()
8921      },
8922    );
8923
8924    prefix_test(
8925      r#"
8926        @media (width <= 240px) {
8927          .foo {
8928            color: chartreuse;
8929          }
8930        }
8931      "#,
8932      indoc! { r#"
8933        @media (width <= 240px) {
8934          .foo {
8935            color: #7fff00;
8936          }
8937        }
8938      "#},
8939      Browsers {
8940        firefox: Some(64 << 16),
8941        ..Browsers::default()
8942      },
8943    );
8944
8945    prefix_test(
8946      r#"
8947        @media (width < 240px) {
8948          .foo {
8949            color: chartreuse;
8950          }
8951        }
8952      "#,
8953      indoc! { r#"
8954        @media not (min-width: 240px) {
8955          .foo {
8956            color: #7fff00;
8957          }
8958        }
8959      "#},
8960      Browsers {
8961        firefox: Some(60 << 16),
8962        ..Browsers::default()
8963      },
8964    );
8965
8966    prefix_test(
8967      r#"
8968        @media not (width < 240px) {
8969          .foo {
8970            color: chartreuse;
8971          }
8972        }
8973      "#,
8974      indoc! { r#"
8975        @media (min-width: 240px) {
8976          .foo {
8977            color: #7fff00;
8978          }
8979        }
8980      "#},
8981      Browsers {
8982        firefox: Some(60 << 16),
8983        ..Browsers::default()
8984      },
8985    );
8986
8987    test(
8988      r#"
8989        @media not (width < 240px) {
8990          .foo {
8991            color: chartreuse;
8992          }
8993        }
8994      "#,
8995      indoc! { r#"
8996        @media (width >= 240px) {
8997          .foo {
8998            color: #7fff00;
8999          }
9000        }
9001      "#},
9002    );
9003
9004    prefix_test(
9005      r#"
9006        @media (width < 240px) and (hover) {
9007          .foo {
9008            color: chartreuse;
9009          }
9010        }
9011      "#,
9012      indoc! { r#"
9013        @media (not (min-width: 240px)) and (hover) {
9014          .foo {
9015            color: #7fff00;
9016          }
9017        }
9018      "#},
9019      Browsers {
9020        firefox: Some(60 << 16),
9021        ..Browsers::default()
9022      },
9023    );
9024
9025    prefix_test(
9026      r#"
9027        @media (100px <= width <= 200px) {
9028          .foo {
9029            color: chartreuse;
9030          }
9031        }
9032      "#,
9033      indoc! { r#"
9034        @media (min-width: 100px) and (max-width: 200px) {
9035          .foo {
9036            color: #7fff00;
9037          }
9038        }
9039      "#},
9040      Browsers {
9041        firefox: Some(85 << 16),
9042        ..Browsers::default()
9043      },
9044    );
9045
9046    prefix_test(
9047      r#"
9048        @media not (100px <= width <= 200px) {
9049          .foo {
9050            color: chartreuse;
9051          }
9052        }
9053      "#,
9054      indoc! { r#"
9055        @media not ((min-width: 100px) and (max-width: 200px)) {
9056          .foo {
9057            color: #7fff00;
9058          }
9059        }
9060      "#},
9061      Browsers {
9062        firefox: Some(85 << 16),
9063        ..Browsers::default()
9064      },
9065    );
9066
9067    prefix_test(
9068      r#"
9069        @media (hover) and (100px <= width <= 200px) {
9070          .foo {
9071            color: chartreuse;
9072          }
9073        }
9074      "#,
9075      indoc! { r#"
9076        @media (hover) and (min-width: 100px) and (max-width: 200px) {
9077          .foo {
9078            color: #7fff00;
9079          }
9080        }
9081      "#},
9082      Browsers {
9083        firefox: Some(85 << 16),
9084        ..Browsers::default()
9085      },
9086    );
9087
9088    prefix_test(
9089      r#"
9090        @media (hover) or (100px <= width <= 200px) {
9091          .foo {
9092            color: chartreuse;
9093          }
9094        }
9095      "#,
9096      indoc! { r#"
9097        @media (hover) or ((min-width: 100px) and (max-width: 200px)) {
9098          .foo {
9099            color: #7fff00;
9100          }
9101        }
9102      "#},
9103      Browsers {
9104        firefox: Some(85 << 16),
9105        ..Browsers::default()
9106      },
9107    );
9108
9109    prefix_test(
9110      r#"
9111        @media (100px < width < 200px) {
9112          .foo {
9113            color: chartreuse;
9114          }
9115        }
9116      "#,
9117      indoc! { r#"
9118        @media (not (max-width: 100px)) and (not (min-width: 200px)) {
9119          .foo {
9120            color: #7fff00;
9121          }
9122        }
9123      "#},
9124      Browsers {
9125        firefox: Some(85 << 16),
9126        ..Browsers::default()
9127      },
9128    );
9129
9130    prefix_test(
9131      r#"
9132        @media not (100px < width < 200px) {
9133          .foo {
9134            color: chartreuse;
9135          }
9136        }
9137      "#,
9138      indoc! { r#"
9139        @media not ((not (max-width: 100px)) and (not (min-width: 200px))) {
9140          .foo {
9141            color: #7fff00;
9142          }
9143        }
9144      "#},
9145      Browsers {
9146        firefox: Some(85 << 16),
9147        ..Browsers::default()
9148      },
9149    );
9150
9151    prefix_test(
9152      r#"
9153        @media (200px >= width >= 100px) {
9154          .foo {
9155            color: chartreuse;
9156          }
9157        }
9158      "#,
9159      indoc! { r#"
9160        @media (max-width: 200px) and (min-width: 100px) {
9161          .foo {
9162            color: #7fff00;
9163          }
9164        }
9165      "#},
9166      Browsers {
9167        firefox: Some(85 << 16),
9168        ..Browsers::default()
9169      },
9170    );
9171
9172    test(
9173      r#"
9174      @media not all {
9175        .a {
9176          color: green;
9177        }
9178      }
9179      "#,
9180      "\n",
9181    );
9182
9183    prefix_test(
9184      r#"
9185      @media (width > calc(1px + 1rem)) {
9186        .foo { color: yellow; }
9187      }
9188      "#,
9189      indoc! { r#"
9190        @media not (max-width: calc(1px + 1rem)) {
9191          .foo {
9192            color: #ff0;
9193          }
9194        }
9195      "#},
9196      Browsers {
9197        chrome: Some(85 << 16),
9198        ..Browsers::default()
9199      },
9200    );
9201    prefix_test(
9202      r#"
9203      @media (width > max(10px, 1rem)) {
9204        .foo { color: yellow; }
9205      }
9206      "#,
9207      indoc! { r#"
9208        @media not (max-width: max(10px, 1rem)) {
9209          .foo {
9210            color: #ff0;
9211          }
9212        }
9213      "#},
9214      Browsers {
9215        chrome: Some(85 << 16),
9216        ..Browsers::default()
9217      },
9218    );
9219    prefix_test(
9220      r#"
9221      @media (width > 0) {
9222        .foo { color: yellow; }
9223      }
9224      "#,
9225      indoc! { r#"
9226        @media not (max-width: 0) {
9227          .foo {
9228            color: #ff0;
9229          }
9230        }
9231      "#},
9232      Browsers {
9233        chrome: Some(85 << 16),
9234        ..Browsers::default()
9235      },
9236    );
9237    prefix_test(
9238      r#"
9239      @media (min-resolution: 2dppx) {
9240        .foo { color: yellow; }
9241      }
9242      "#,
9243      indoc! { r#"
9244        @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 2dppx) {
9245          .foo {
9246            color: #ff0;
9247          }
9248        }
9249      "#},
9250      Browsers {
9251        safari: Some(15 << 16),
9252        ..Browsers::default()
9253      },
9254    );
9255    prefix_test(
9256      r#"
9257      @media (min-resolution: 2dppx) {
9258        .foo { color: yellow; }
9259      }
9260      "#,
9261      indoc! { r#"
9262        @media (min--moz-device-pixel-ratio: 2), (min-resolution: 2dppx) {
9263          .foo {
9264            color: #ff0;
9265          }
9266        }
9267      "#},
9268      Browsers {
9269        firefox: Some(10 << 16),
9270        ..Browsers::default()
9271      },
9272    );
9273    prefix_test(
9274      r#"
9275      @media (resolution > 2dppx) {
9276        .foo { color: yellow; }
9277      }
9278      "#,
9279      indoc! { r#"
9280        @media not (-webkit-max-device-pixel-ratio: 2), not (max-resolution: 2dppx) {
9281          .foo {
9282            color: #ff0;
9283          }
9284        }
9285      "#},
9286      Browsers {
9287        safari: Some(15 << 16),
9288        ..Browsers::default()
9289      },
9290    );
9291    prefix_test(
9292      r#"
9293      @media (resolution >= 300dpi) {
9294        .foo { color: yellow; }
9295      }
9296      "#,
9297      indoc! { r#"
9298        @media (-webkit-min-device-pixel-ratio: 3.125), (min-resolution: 300dpi) {
9299          .foo {
9300            color: #ff0;
9301          }
9302        }
9303      "#},
9304      Browsers {
9305        safari: Some(15 << 16),
9306        ..Browsers::default()
9307      },
9308    );
9309    prefix_test(
9310      r#"
9311      @media (min-resolution: 113.38dpcm) {
9312        .foo { color: yellow; }
9313      }
9314      "#,
9315      indoc! { r#"
9316        @media (-webkit-min-device-pixel-ratio: 2.99985), (min--moz-device-pixel-ratio: 2.99985), (min-resolution: 113.38dpcm) {
9317          .foo {
9318            color: #ff0;
9319          }
9320        }
9321      "#},
9322      Browsers {
9323        safari: Some(15 << 16),
9324        firefox: Some(10 << 16),
9325        ..Browsers::default()
9326      },
9327    );
9328    prefix_test(
9329      r#"
9330      @media (color) and (min-resolution: 2dppx) {
9331        .foo { color: yellow; }
9332      }
9333      "#,
9334      indoc! { r#"
9335        @media (color) and (-webkit-min-device-pixel-ratio: 2), (color) and (min-resolution: 2dppx) {
9336          .foo {
9337            color: #ff0;
9338          }
9339        }
9340      "#},
9341      Browsers {
9342        safari: Some(15 << 16),
9343        ..Browsers::default()
9344      },
9345    );
9346    prefix_test(
9347      r#"
9348      @media (min-resolution: 2dppx),
9349             (min-resolution: 192dpi) {
9350        .foo { color: yellow; }
9351      }
9352      "#,
9353      indoc! { r#"
9354        @media (-webkit-min-device-pixel-ratio: 2), (min--moz-device-pixel-ratio: 2), (min-resolution: 2dppx), (min-resolution: 192dpi) {
9355          .foo {
9356            color: #ff0;
9357          }
9358        }
9359      "#},
9360      Browsers {
9361        safari: Some(15 << 16),
9362        firefox: Some(10 << 16),
9363        ..Browsers::default()
9364      },
9365    );
9366    prefix_test(
9367      r#"
9368      @media only screen and (min-resolution: 124.8dpi) {
9369        .foo { color: yellow; }
9370      }
9371      "#,
9372      indoc! { r#"
9373        @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) {
9374          .foo {
9375            color: #ff0;
9376          }
9377        }
9378      "#},
9379      Browsers {
9380        safari: Some(15 << 16),
9381        firefox: Some(10 << 16),
9382        ..Browsers::default()
9383      },
9384    );
9385
9386    test_with_printer_options(
9387      r#"
9388        @media (width < 256px) or (hover: none) {
9389          .foo {
9390            color: #fff;
9391          }
9392        }
9393      "#,
9394      indoc! { r#"
9395        @media (not (min-width: 256px)) or (hover: none) {
9396          .foo {
9397            color: #fff;
9398          }
9399        }
9400      "#},
9401      PrinterOptions {
9402        targets: Targets {
9403          browsers: None,
9404          include: Features::MediaRangeSyntax,
9405          exclude: Features::empty(),
9406        },
9407        ..Default::default()
9408      },
9409    );
9410
9411    error_test(
9412      "@media (min-width: hi) { .foo { color: chartreuse }}",
9413      ParserError::InvalidMediaQuery,
9414    );
9415    error_test(
9416      "@media (width >= hi) { .foo { color: chartreuse }}",
9417      ParserError::InvalidMediaQuery,
9418    );
9419    error_test(
9420      "@media (width >= 2/1) { .foo { color: chartreuse }}",
9421      ParserError::UnexpectedToken(Token::Delim('/')),
9422    );
9423    error_test(
9424      "@media (600px <= min-height) { .foo { color: chartreuse }}",
9425      ParserError::InvalidMediaQuery,
9426    );
9427    error_test(
9428      "@media (scan >= 1) { .foo { color: chartreuse }}",
9429      ParserError::InvalidMediaQuery,
9430    );
9431    error_test(
9432      "@media (min-scan: interlace) { .foo { color: chartreuse }}",
9433      ParserError::InvalidMediaQuery,
9434    );
9435    error_test(
9436      "@media (1px <= width <= bar) { .foo { color: chartreuse }}",
9437      ParserError::InvalidMediaQuery,
9438    );
9439    error_test(
9440      "@media (1px <= min-width <= 2px) { .foo { color: chartreuse }}",
9441      ParserError::InvalidMediaQuery,
9442    );
9443    error_test(
9444      "@media (1px <= scan <= 2px) { .foo { color: chartreuse }}",
9445      ParserError::InvalidMediaQuery,
9446    );
9447    error_test(
9448      "@media (grid: 10) { .foo { color: chartreuse }}",
9449      ParserError::InvalidMediaQuery,
9450    );
9451    error_test(
9452      "@media (prefers-color-scheme = dark) { .foo { color: chartreuse }}",
9453      ParserError::InvalidMediaQuery,
9454    );
9455    error_test(
9456      "@media unknown(foo) {}",
9457      ParserError::UnexpectedToken(crate::properties::custom::Token::Function("unknown".into())),
9458    );
9459
9460    // empty brackets should return a clearer error message
9461    error_test("@media () {}", ParserError::EmptyBracketInCondition);
9462    error_test("@media screen and () {}", ParserError::EmptyBracketInCondition);
9463
9464    error_recovery_test("@media unknown(foo) {}");
9465  }
9466
9467  #[test]
9468  fn test_merge_layers() {
9469    test(
9470      r#"
9471      @layer foo {
9472        .foo {
9473          color: red;
9474        }
9475      }
9476      @layer foo {
9477        .foo {
9478          background: #fff;
9479        }
9480
9481        .baz {
9482          color: #fff;
9483        }
9484      }
9485      "#,
9486      indoc! {r#"
9487      @layer foo {
9488        .foo {
9489          color: red;
9490          background: #fff;
9491        }
9492
9493        .baz {
9494          color: #fff;
9495        }
9496      }
9497    "#},
9498    );
9499    test(
9500      r#"
9501      @layer a {}
9502      @layer b {}
9503
9504      @layer b {
9505        foo {
9506          color: red;
9507        }
9508      }
9509
9510      @layer a {
9511        bar {
9512          color: yellow;
9513        }
9514      }
9515      "#,
9516      indoc! {r#"
9517      @layer a {
9518        bar {
9519          color: #ff0;
9520        }
9521      }
9522
9523      @layer b {
9524        foo {
9525          color: red;
9526        }
9527      }
9528    "#},
9529    );
9530
9531    test(
9532      r#"
9533      @layer a {}
9534      @layer b {}
9535
9536      @layer b {
9537        foo {
9538          color: red;
9539        }
9540      }
9541      "#,
9542      indoc! {r#"
9543      @layer a;
9544
9545      @layer b {
9546        foo {
9547          color: red;
9548        }
9549      }
9550    "#},
9551    );
9552
9553    test(
9554      r#"
9555      @layer a;
9556      @layer b;
9557      @layer c;
9558      "#,
9559      indoc! {r#"
9560      @layer a, b, c;
9561    "#},
9562    );
9563
9564    test(
9565      r#"
9566      @layer a {}
9567      @layer b {}
9568      @layer c {}
9569      "#,
9570      indoc! {r#"
9571      @layer a, b, c;
9572    "#},
9573    );
9574
9575    test(
9576      r#"
9577      @layer a;
9578      @layer b {
9579        .foo {
9580          color: red;
9581        }
9582      }
9583      @layer c {}
9584      "#,
9585      indoc! {r#"
9586      @layer a;
9587
9588      @layer b {
9589        .foo {
9590          color: red;
9591        }
9592      }
9593
9594      @layer c;
9595    "#},
9596    );
9597
9598    test(
9599      r#"
9600      @layer a, b;
9601      @layer c {}
9602
9603      @layer d {
9604        foo {
9605          color: red;
9606        }
9607      }
9608      "#,
9609      indoc! {r#"
9610      @layer a, b, c;
9611
9612      @layer d {
9613        foo {
9614          color: red;
9615        }
9616      }
9617    "#},
9618    );
9619
9620    test(
9621      r#"
9622      @layer a;
9623      @layer b;
9624      @import "a.css" layer(x);
9625      @layer c;
9626
9627      @layer d {
9628        foo {
9629          color: red;
9630        }
9631      }
9632      "#,
9633      indoc! {r#"
9634      @layer a, b;
9635      @import "a.css" layer(x);
9636      @layer c;
9637
9638      @layer d {
9639        foo {
9640          color: red;
9641        }
9642      }
9643    "#},
9644    );
9645
9646    test(
9647      r#"
9648      @layer a, b, c;
9649
9650      @layer a {
9651        foo {
9652          color: red;
9653        }
9654      }
9655      "#,
9656      indoc! {r#"
9657      @layer a {
9658        foo {
9659          color: red;
9660        }
9661      }
9662
9663      @layer b, c;
9664    "#},
9665    );
9666
9667    test(
9668      r#"
9669      @layer a;
9670      @import "foo.css";
9671
9672      @layer a {
9673        foo {
9674          color: red;
9675        }
9676      }
9677      "#,
9678      indoc! {r#"
9679      @layer a;
9680      @import "foo.css";
9681
9682      @layer a {
9683        foo {
9684          color: red;
9685        }
9686      }
9687    "#},
9688    );
9689  }
9690
9691  #[test]
9692  fn test_merge_rules() {
9693    test(
9694      r#"
9695      .foo {
9696        color: red;
9697      }
9698      .bar {
9699        color: red;
9700      }
9701    "#,
9702      indoc! {r#"
9703      .foo, .bar {
9704        color: red;
9705      }
9706    "#},
9707    );
9708    test(
9709      r#"
9710      .foo {
9711        color: red;
9712      }
9713      .foo {
9714        background: green;
9715      }
9716    "#,
9717      indoc! {r#"
9718      .foo {
9719        color: red;
9720        background: green;
9721      }
9722    "#},
9723    );
9724    test(
9725      r#"
9726      .foo {
9727        color: red;
9728      }
9729      .foo {
9730        background: green !important;
9731      }
9732    "#,
9733      indoc! {r#"
9734      .foo {
9735        color: red;
9736        background: green !important;
9737      }
9738    "#},
9739    );
9740    test(
9741      r#"
9742      .foo {
9743        background: red;
9744      }
9745      .foo {
9746        background: green;
9747      }
9748    "#,
9749      indoc! {r#"
9750      .foo {
9751        background: green;
9752      }
9753    "#},
9754    );
9755    test(
9756      r#"
9757      .foo {
9758        --foo: red;
9759        --foo: purple;
9760      }
9761      .foo {
9762        --foo: green;
9763      }
9764    "#,
9765      indoc! {r#"
9766      .foo {
9767        --foo: green;
9768      }
9769    "#},
9770    );
9771    test(
9772      r#"
9773      .foo {
9774        color: red;
9775      }
9776
9777      .bar {
9778        background: green;
9779      }
9780    "#,
9781      indoc! {r#"
9782      .foo {
9783        color: red;
9784      }
9785
9786      .bar {
9787        background: green;
9788      }
9789    "#},
9790    );
9791    test(
9792      r#"
9793      .foo {
9794        color: red;
9795      }
9796
9797      .baz {
9798        color: blue;
9799      }
9800
9801      .bar {
9802        color: red;
9803      }
9804    "#,
9805      indoc! {r#"
9806      .foo {
9807        color: red;
9808      }
9809
9810      .baz {
9811        color: #00f;
9812      }
9813
9814      .bar {
9815        color: red;
9816      }
9817    "#},
9818    );
9819    test(
9820      r#"
9821      .foo {
9822        background: red;
9823      }
9824      .bar {
9825        background: red;
9826      }
9827      .foo {
9828        color: green;
9829      }
9830      .bar {
9831        color: green;
9832      }
9833    "#,
9834      indoc! {r#"
9835      .foo, .bar {
9836        color: green;
9837        background: red;
9838      }
9839    "#},
9840    );
9841    test(
9842      r#"
9843      .foo, .bar {
9844        background: red;
9845      }
9846      .foo {
9847        color: green;
9848      }
9849      .bar {
9850        color: green;
9851      }
9852    "#,
9853      indoc! {r#"
9854      .foo, .bar {
9855        color: green;
9856        background: red;
9857      }
9858    "#},
9859    );
9860    test(
9861      r#"
9862      .foo {
9863        background: red;
9864      }
9865      .foo {
9866        color: green;
9867      }
9868      .bar {
9869        background: red;
9870      }
9871      .bar {
9872        color: green;
9873      }
9874    "#,
9875      indoc! {r#"
9876      .foo, .bar {
9877        color: green;
9878        background: red;
9879      }
9880    "#},
9881    );
9882    test(
9883      r#"
9884      [foo="bar"] {
9885        color: red;
9886      }
9887      .bar {
9888        color: red;
9889      }
9890    "#,
9891      indoc! {r#"
9892      [foo="bar"], .bar {
9893        color: red;
9894      }
9895    "#},
9896    );
9897    test(
9898      r#"
9899      .a {
9900        color: red;
9901      }
9902      .b {
9903        color: green;
9904      }
9905      .a {
9906        color: red;
9907      }
9908    "#,
9909      indoc! {r#"
9910      .b {
9911        color: green;
9912      }
9913
9914      .a {
9915        color: red;
9916      }
9917    "#},
9918    );
9919    test(
9920      r#"
9921      .a {
9922        color: red;
9923      }
9924      .b {
9925        color: green;
9926      }
9927      .a {
9928        color: pink;
9929      }
9930    "#,
9931      indoc! {r#"
9932      .b {
9933        color: green;
9934      }
9935
9936      .a {
9937        color: pink;
9938      }
9939    "#},
9940    );
9941    test(
9942      r#"
9943      .a:foo(#000) {
9944        color: red;
9945      }
9946      .b {
9947        color: green;
9948      }
9949      .a:foo(#ff0) {
9950        color: pink;
9951      }
9952    "#,
9953      indoc! {r#"
9954      .a:foo(#000) {
9955        color: red;
9956      }
9957
9958      .b {
9959        color: green;
9960      }
9961
9962      .a:foo(#ff0) {
9963        color: pink;
9964      }
9965    "#},
9966    );
9967    test(
9968      r#"
9969      .a {
9970        border-radius: 10px;
9971      }
9972      .b {
9973        color: green;
9974      }
9975      .a {
9976        border-radius: 10px;
9977      }
9978    "#,
9979      indoc! {r#"
9980      .b {
9981        color: green;
9982      }
9983
9984      .a {
9985        border-radius: 10px;
9986      }
9987    "#},
9988    );
9989    test(
9990      r#"
9991      .a {
9992        border-radius: 10px;
9993      }
9994      .b {
9995        color: green;
9996      }
9997      .a {
9998        -webkit-border-radius: 10px;
9999      }
10000    "#,
10001      indoc! {r#"
10002      .a {
10003        border-radius: 10px;
10004      }
10005
10006      .b {
10007        color: green;
10008      }
10009
10010      .a {
10011        -webkit-border-radius: 10px;
10012      }
10013    "#},
10014    );
10015    test(
10016      r#"
10017      .a {
10018        border-radius: 10px;
10019      }
10020      .b {
10021        color: green;
10022      }
10023      .a {
10024        border-radius: var(--foo);
10025      }
10026    "#,
10027      indoc! {r#"
10028      .b {
10029        color: green;
10030      }
10031
10032      .a {
10033        border-radius: var(--foo);
10034      }
10035    "#},
10036    );
10037    test(
10038      r#"
10039      .a {
10040        border-radius: 10px;
10041      }
10042      .b {
10043        color: green;
10044      }
10045      .c {
10046        border-radius: 20px;
10047      }
10048    "#,
10049      indoc! {r#"
10050      .a {
10051        border-radius: 10px;
10052      }
10053
10054      .b {
10055        color: green;
10056      }
10057
10058      .c {
10059        border-radius: 20px;
10060      }
10061    "#},
10062    );
10063    test(
10064      r#"
10065      @media print {
10066        .a {
10067          color: red;
10068        }
10069        .b {
10070          color: green;
10071        }
10072        .a {
10073          color: red;
10074        }
10075      }
10076    "#,
10077      indoc! {r#"
10078      @media print {
10079        .b {
10080          color: green;
10081        }
10082
10083        .a {
10084          color: red;
10085        }
10086      }
10087    "#},
10088    );
10089    test(
10090      r#"
10091      .a {
10092        border-radius: 10px;
10093      }
10094      .b {
10095        color: green;
10096      }
10097      .a {
10098        border-radius: 20px;
10099        color: pink;
10100      }
10101    "#,
10102      indoc! {r#"
10103      .a {
10104        border-radius: 10px;
10105      }
10106
10107      .b {
10108        color: green;
10109      }
10110
10111      .a {
10112        color: pink;
10113        border-radius: 20px;
10114      }
10115    "#},
10116    );
10117    test(
10118      r#"
10119      .a {
10120        color: red;
10121      }
10122      .b {
10123        color: green;
10124      }
10125      .a {
10126        color: red;
10127      }
10128      .b {
10129        color: green;
10130      }
10131    "#,
10132      indoc! {r#"
10133      .a {
10134        color: red;
10135      }
10136
10137      .b {
10138        color: green;
10139      }
10140    "#},
10141    );
10142
10143    prefix_test(
10144      r#"
10145      [foo="bar"] {
10146        color: red;
10147      }
10148      .bar {
10149        color: red;
10150      }
10151    "#,
10152      indoc! {r#"
10153      [foo="bar"] {
10154        color: red;
10155      }
10156
10157      .bar {
10158        color: red;
10159      }
10160    "#},
10161      Browsers {
10162        ie: Some(6 << 16),
10163        ..Browsers::default()
10164      },
10165    );
10166
10167    prefix_test(
10168      r#"
10169      [foo="bar"] {
10170        color: red;
10171      }
10172      .bar {
10173        color: red;
10174      }
10175    "#,
10176      indoc! {r#"
10177      [foo="bar"], .bar {
10178        color: red;
10179      }
10180    "#},
10181      Browsers {
10182        ie: Some(10 << 16),
10183        ..Browsers::default()
10184      },
10185    );
10186
10187    test(
10188      r#"
10189      .foo:-moz-read-only {
10190        color: red;
10191      }
10192    "#,
10193      indoc! {r#"
10194      .foo:-moz-read-only {
10195        color: red;
10196      }
10197    "#},
10198    );
10199
10200    test(
10201      r#"
10202      .foo:-moz-read-only {
10203        color: red;
10204      }
10205
10206      .foo:read-only {
10207        color: red;
10208      }
10209    "#,
10210      indoc! {r#"
10211      .foo:-moz-read-only {
10212        color: red;
10213      }
10214
10215      .foo:read-only {
10216        color: red;
10217      }
10218    "#},
10219    );
10220
10221    prefix_test(
10222      r#"
10223      .foo:-moz-read-only {
10224        color: red;
10225      }
10226
10227      .foo:read-only {
10228        color: red;
10229      }
10230    "#,
10231      indoc! {r#"
10232      .foo:read-only {
10233        color: red;
10234      }
10235    "#},
10236      Browsers {
10237        firefox: Some(85 << 16),
10238        ..Browsers::default()
10239      },
10240    );
10241
10242    prefix_test(
10243      r#"
10244      .foo:-moz-read-only {
10245        color: red;
10246      }
10247
10248      .bar {
10249        color: yellow;
10250      }
10251
10252      .foo:read-only {
10253        color: red;
10254      }
10255    "#,
10256      indoc! {r#"
10257      .foo:-moz-read-only {
10258        color: red;
10259      }
10260
10261      .bar {
10262        color: #ff0;
10263      }
10264
10265      .foo:read-only {
10266        color: red;
10267      }
10268    "#},
10269      Browsers {
10270        firefox: Some(85 << 16),
10271        ..Browsers::default()
10272      },
10273    );
10274
10275    prefix_test(
10276      r#"
10277      .foo:-moz-read-only {
10278        color: red;
10279      }
10280
10281      .foo:read-only {
10282        color: red;
10283      }
10284    "#,
10285      indoc! {r#"
10286      .foo:-moz-read-only {
10287        color: red;
10288      }
10289
10290      .foo:read-only {
10291        color: red;
10292      }
10293    "#},
10294      Browsers {
10295        firefox: Some(36 << 16),
10296        ..Browsers::default()
10297      },
10298    );
10299
10300    prefix_test(
10301      r#"
10302      .foo:read-only {
10303        color: red;
10304      }
10305    "#,
10306      indoc! {r#"
10307      .foo:-moz-read-only {
10308        color: red;
10309      }
10310
10311      .foo:read-only {
10312        color: red;
10313      }
10314    "#},
10315      Browsers {
10316        firefox: Some(36 << 16),
10317        ..Browsers::default()
10318      },
10319    );
10320
10321    prefix_test(
10322      r#"
10323      .foo:-webkit-full-screen {
10324        color: red;
10325      }
10326      .foo:-moz-full-screen {
10327        color: red;
10328      }
10329      .foo:-ms-fullscreen {
10330        color: red;
10331      }
10332      .foo:fullscreen {
10333        color: red;
10334      }
10335    "#,
10336      indoc! {r#"
10337      .foo:fullscreen {
10338        color: red;
10339      }
10340    "#},
10341      Browsers {
10342        chrome: Some(96 << 16),
10343        ..Browsers::default()
10344      },
10345    );
10346
10347    prefix_test(
10348      r#"
10349      .foo:fullscreen {
10350        color: red;
10351      }
10352    "#,
10353      indoc! {r#"
10354      .foo:-webkit-full-screen {
10355        color: red;
10356      }
10357
10358      .foo:-moz-full-screen {
10359        color: red;
10360      }
10361
10362      .foo:-ms-fullscreen {
10363        color: red;
10364      }
10365
10366      .foo:fullscreen {
10367        color: red;
10368      }
10369    "#},
10370      Browsers {
10371        chrome: Some(45 << 16),
10372        firefox: Some(45 << 16),
10373        ie: Some(11 << 16),
10374        ..Browsers::default()
10375      },
10376    );
10377
10378    prefix_test(
10379      r#"
10380      .foo::placeholder {
10381        color: red;
10382      }
10383    "#,
10384      indoc! {r#"
10385      .foo::-webkit-input-placeholder {
10386        color: red;
10387      }
10388
10389      .foo::-moz-placeholder {
10390        color: red;
10391      }
10392
10393      .foo::-ms-input-placeholder {
10394        color: red;
10395      }
10396
10397      .foo::placeholder {
10398        color: red;
10399      }
10400    "#},
10401      Browsers {
10402        chrome: Some(45 << 16),
10403        firefox: Some(45 << 16),
10404        ie: Some(11 << 16),
10405        ..Browsers::default()
10406      },
10407    );
10408
10409    prefix_test(
10410      r#"
10411      .foo::file-selector-button {
10412        color: red;
10413      }
10414    "#,
10415      indoc! {r#"
10416      .foo::-webkit-file-upload-button {
10417        color: red;
10418      }
10419
10420      .foo::-ms-browse {
10421        color: red;
10422      }
10423
10424      .foo::file-selector-button {
10425        color: red;
10426      }
10427    "#},
10428      Browsers {
10429        chrome: Some(84 << 16),
10430        ie: Some(10 << 16),
10431        ..Browsers::default()
10432      },
10433    );
10434
10435    prefix_test(
10436      r#"
10437      .foo::file-selector-button {
10438        margin-inline-start: 2px;
10439      }
10440    "#,
10441      indoc! {r#"
10442      .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 {
10443        margin-left: 2px;
10444      }
10445
10446      .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 {
10447        margin-left: 2px;
10448      }
10449
10450      .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 {
10451        margin-left: 2px;
10452      }
10453
10454      .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 {
10455        margin-right: 2px;
10456      }
10457
10458      .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 {
10459        margin-right: 2px;
10460      }
10461
10462      .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 {
10463        margin-right: 2px;
10464      }
10465    "#},
10466      Browsers {
10467        chrome: Some(84 << 16),
10468        ie: Some(10 << 16),
10469        ..Browsers::default()
10470      },
10471    );
10472
10473    prefix_test(
10474      r#"
10475      .foo:placeholder-shown .bar { color: red; }
10476      .foo:autofill .baz { color: red; }
10477      "#,
10478      indoc! {r#"
10479      .foo:placeholder-shown .bar {
10480        color: red;
10481      }
10482
10483      .foo:-webkit-autofill .baz {
10484        color: red;
10485      }
10486
10487      .foo:autofill .baz {
10488        color: red;
10489      }
10490      "#},
10491      Browsers {
10492        chrome: Some(103 << 16),
10493        ..Browsers::default()
10494      },
10495    );
10496
10497    prefix_test(
10498      r#"
10499      .foo:placeholder-shown .bar,.foo:autofill .baz{color:red}
10500      "#,
10501      indoc! {r#"
10502      :-webkit-any(.foo:placeholder-shown .bar, .foo:-webkit-autofill .baz) {
10503        color: red;
10504      }
10505
10506      :is(.foo:placeholder-shown .bar, .foo:autofill .baz) {
10507        color: red;
10508      }
10509      "#},
10510      Browsers {
10511        chrome: Some(103 << 16),
10512        ..Browsers::default()
10513      },
10514    );
10515
10516    prefix_test(
10517      r#"
10518      .foo:placeholder-shown .bar, .foo:-webkit-autofill .baz {
10519        color: red;
10520      }
10521
10522      .foo:placeholder-shown .bar, .foo:autofill .baz {
10523        color: red;
10524      }
10525      "#,
10526      indoc! {r#"
10527      :-webkit-any(.foo:placeholder-shown .bar, .foo:-webkit-autofill .baz) {
10528        color: red;
10529      }
10530
10531      :is(.foo:placeholder-shown .bar, .foo:autofill .baz) {
10532        color: red;
10533      }
10534      "#},
10535      Browsers {
10536        chrome: Some(103 << 16),
10537        ..Browsers::default()
10538      },
10539    );
10540
10541    test(
10542      r#"
10543      .foo:placeholder-shown .bar, .foo:-webkit-autofill .baz {
10544        color: red;
10545      }
10546
10547      .foo:placeholder-shown .bar, .foo:autofill .baz {
10548        color: red;
10549      }
10550      "#,
10551      indoc! {r#"
10552      .foo:placeholder-shown .bar, .foo:-webkit-autofill .baz {
10553        color: red;
10554      }
10555
10556      .foo:placeholder-shown .bar, .foo:autofill .baz {
10557        color: red;
10558      }
10559      "#},
10560    );
10561
10562    prefix_test(
10563      r#"
10564      :hover, :focus-visible {
10565        color: red;
10566      }
10567      "#,
10568      indoc! {r#"
10569      :hover {
10570        color: red;
10571      }
10572
10573      :focus-visible {
10574        color: red;
10575      }
10576      "#},
10577      Browsers {
10578        safari: Some(13 << 16),
10579        ..Browsers::default()
10580      },
10581    );
10582
10583    prefix_test(
10584      r#"
10585      .foo {
10586        color: red;
10587      }
10588
10589      :hover, :focus-visible {
10590        color: red;
10591      }
10592      "#,
10593      indoc! {r#"
10594      .foo, :hover {
10595        color: red;
10596      }
10597
10598      :focus-visible {
10599        color: red;
10600      }
10601      "#},
10602      Browsers {
10603        safari: Some(13 << 16),
10604        ..Browsers::default()
10605      },
10606    );
10607
10608    prefix_test(
10609      r#"
10610      :hover, :focus-visible {
10611        margin-inline-start: 24px;
10612      }
10613      "#,
10614      indoc! {r#"
10615      :hover:not(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
10616        margin-left: 24px;
10617      }
10618
10619      :hover:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) {
10620        margin-right: 24px;
10621      }
10622
10623      :focus-visible:not(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
10624        margin-left: 24px;
10625      }
10626
10627      :focus-visible:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) {
10628        margin-right: 24px;
10629      }
10630      "#},
10631      Browsers {
10632        safari: Some(11 << 16),
10633        ..Browsers::default()
10634      },
10635    );
10636
10637    prefix_test(
10638      r#"
10639      :focus-within, :focus-visible {
10640        color: red;
10641      }
10642      "#,
10643      indoc! {r#"
10644      :focus-within {
10645        color: red;
10646      }
10647
10648      :focus-visible {
10649        color: red;
10650      }
10651      "#},
10652      Browsers {
10653        safari: Some(9 << 16),
10654        ..Browsers::default()
10655      },
10656    );
10657
10658    prefix_test(
10659      r#"
10660      :hover, :focus-visible {
10661        color: red;
10662      }
10663      "#,
10664      indoc! {r#"
10665      :is(:hover, :focus-visible) {
10666        color: red;
10667      }
10668      "#},
10669      Browsers {
10670        safari: Some(14 << 16),
10671        ..Browsers::default()
10672      },
10673    );
10674
10675    prefix_test(
10676      r#"
10677      a::after:hover, a::after:focus-visible {
10678        color: red;
10679      }
10680      "#,
10681      indoc! {r#"
10682      a:after:hover {
10683        color: red;
10684      }
10685
10686      a:after:focus-visible {
10687        color: red;
10688      }
10689      "#},
10690      Browsers {
10691        safari: Some(14 << 16),
10692        ..Browsers::default()
10693      },
10694    );
10695
10696    prefix_test(
10697      r#"
10698      a:not(:hover), a:not(:focus-visible) {
10699        color: red;
10700      }
10701      "#,
10702      indoc! {r#"
10703      :is(a:not(:hover), a:not(:focus-visible)) {
10704        color: red;
10705      }
10706      "#},
10707      Browsers {
10708        safari: Some(14 << 16),
10709        ..Browsers::default()
10710      },
10711    );
10712
10713    prefix_test(
10714      r#"
10715      a:has(:hover), a:has(:focus-visible) {
10716        color: red;
10717      }
10718      "#,
10719      indoc! {r#"
10720      :is(a:has(:hover), a:has(:focus-visible)) {
10721        color: red;
10722      }
10723      "#},
10724      Browsers {
10725        safari: Some(14 << 16),
10726        ..Browsers::default()
10727      },
10728    );
10729
10730    prefix_test(
10731      r#"
10732      .foo.foo:hover, .bar:focus-visible {
10733        color: red;
10734      }
10735      "#,
10736      indoc! {r#"
10737      .foo.foo:hover {
10738        color: red;
10739      }
10740
10741      .bar:focus-visible {
10742        color: red;
10743      }
10744      "#},
10745      Browsers {
10746        safari: Some(14 << 16),
10747        ..Browsers::default()
10748      },
10749    );
10750
10751    prefix_test(
10752      r#"
10753      a::unknown-a, a::unknown-b {
10754        color: red;
10755      }
10756      "#,
10757      indoc! {r#"
10758      a::unknown-a {
10759        color: red;
10760      }
10761
10762      a::unknown-b {
10763        color: red;
10764      }
10765      "#},
10766      Browsers {
10767        safari: Some(14 << 16),
10768        ..Browsers::default()
10769      },
10770    );
10771
10772    nesting_test_with_targets(
10773      r#"
10774      .foo {
10775        padding-inline-start: 3px;
10776
10777        .bar {
10778          padding-inline-start: 5px;
10779        }
10780      }
10781      "#,
10782      indoc! {r#"
10783      .foo:not(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
10784        padding-left: 3px;
10785      }
10786
10787      .foo:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) {
10788        padding-right: 3px;
10789      }
10790
10791      .foo .bar:not(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
10792        padding-left: 5px;
10793      }
10794
10795      .foo .bar:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) {
10796        padding-right: 5px;
10797      }
10798      "#},
10799      Browsers {
10800        safari: Some(12 << 16),
10801        ..Browsers::default()
10802      }
10803      .into(),
10804    );
10805
10806    prefix_test(
10807      r#"
10808      .foo::part(header), .foo::part(body) {
10809        display: none
10810      }
10811      "#,
10812      indoc! {r#"
10813      .foo::part(header), .foo::part(body) {
10814        display: none;
10815      }
10816      "#},
10817      Browsers {
10818        safari: Some(14 << 16),
10819        ..Browsers::default()
10820      },
10821    );
10822
10823    prefix_test(
10824      r#"
10825      .foo :is(.bar) {
10826        color: red;
10827      }
10828      "#,
10829      indoc! {r#"
10830        .foo .bar {
10831          color: red;
10832        }
10833      "#},
10834      Browsers {
10835        chrome: Some(87 << 16),
10836        ..Browsers::default()
10837      },
10838    );
10839
10840    prefix_test(
10841      r#"
10842      .foo :is(.bar), .bar :is(.baz) {
10843        color: red;
10844      }
10845      "#,
10846      indoc! {r#"
10847        .foo .bar, .bar .baz {
10848          color: red;
10849        }
10850      "#},
10851      Browsers {
10852        chrome: Some(87 << 16),
10853        ..Browsers::default()
10854      },
10855    );
10856
10857    prefix_test(
10858      r#"
10859      .foo :is(.bar:focus-visible), .bar :is(.baz:hover) {
10860        color: red;
10861      }
10862      "#,
10863      indoc! {r#"
10864        .bar .baz:hover {
10865          color: red;
10866        }
10867
10868        .foo .bar:focus-visible {
10869          color: red;
10870        }
10871      "#},
10872      Browsers {
10873        chrome: Some(85 << 16),
10874        ..Browsers::default()
10875      },
10876    );
10877
10878    prefix_test(
10879      r#"
10880      *,
10881      ::before,
10882      ::after,
10883      ::backdrop {
10884        padding: 5px;
10885      }
10886      "#,
10887      indoc! {r#"
10888        *, :before, :after {
10889          padding: 5px;
10890        }
10891
10892        ::-webkit-backdrop {
10893          padding: 5px;
10894        }
10895
10896        ::backdrop {
10897          padding: 5px;
10898        }
10899      "#},
10900      Browsers {
10901        chrome: Some(33 << 16),
10902        ..Browsers::default()
10903      },
10904    );
10905
10906    test(
10907      r#"
10908      .foo:-webkit-any(.bar, .baz):after {
10909        color: red;
10910      }
10911
10912      .foo:is(.bar, .baz):after {
10913        color: red;
10914      }
10915      "#,
10916      indoc! {r#"
10917        .foo:-webkit-any(.bar, .baz):after {
10918          color: red;
10919        }
10920
10921        .foo:is(.bar, .baz):after {
10922          color: red;
10923        }
10924      "#},
10925    );
10926
10927    prefix_test(
10928      r#"
10929      .foo:-webkit-any(.bar, .baz):after {
10930        color: red;
10931      }
10932
10933      .foo:is(.bar, .baz):after {
10934        color: red;
10935      }
10936      "#,
10937      indoc! {r#"
10938        .foo:is(.bar, .baz):after {
10939          color: red;
10940        }
10941      "#},
10942      Browsers {
10943        safari: Some(16 << 16),
10944        ..Browsers::default()
10945      },
10946    );
10947
10948    prefix_test(
10949      r#"
10950      .foo:-webkit-any(.bar):after {
10951        color: red;
10952      }
10953
10954      .foo:is(.bar, .baz):after {
10955        color: red;
10956      }
10957      "#,
10958      indoc! {r#"
10959        .foo:-webkit-any(.bar):after {
10960          color: red;
10961        }
10962
10963        .foo:is(.bar, .baz):after {
10964          color: red;
10965        }
10966      "#},
10967      Browsers {
10968        safari: Some(16 << 16),
10969        ..Browsers::default()
10970      },
10971    );
10972
10973    prefix_test(
10974      r#"
10975      .foo:-webkit-any(.bar, .baz):after {
10976        color: red;
10977      }
10978
10979      .foo:is(.bar, .baz):after {
10980        color: red;
10981      }
10982      "#,
10983      indoc! {r#"
10984        .foo:-webkit-any(.bar, .baz):after {
10985          color: red;
10986        }
10987
10988        .foo:is(.bar, .baz):after {
10989          color: red;
10990        }
10991      "#},
10992      Browsers {
10993        safari: Some(12 << 16),
10994        ..Browsers::default()
10995      },
10996    );
10997
10998    prefix_test(
10999      r#"
11000      .foo:-webkit-any(.bar, .baz):after {
11001        color: red;
11002      }
11003
11004      .foo:-moz-any(.bar, .baz):after {
11005        color: red;
11006      }
11007      "#,
11008      indoc! {r#"
11009        .foo:-webkit-any(.bar, .baz):after {
11010          color: red;
11011        }
11012
11013        .foo:-moz-any(.bar, .baz):after {
11014          color: red;
11015        }
11016      "#},
11017      Browsers {
11018        safari: Some(12 << 16),
11019        firefox: Some(67 << 16),
11020        ..Browsers::default()
11021      },
11022    );
11023
11024    prefix_test(
11025      r#"
11026      .a {
11027        padding-inline: var(--foo);
11028      }
11029
11030      .a:-webkit-any(.b, .c) {
11031        padding-inline: var(--foo);
11032      }
11033      "#,
11034      indoc! {r#"
11035        .a {
11036          padding-inline: var(--foo);
11037        }
11038
11039        .a:-webkit-any(.b, .c) {
11040          padding-inline: var(--foo);
11041        }
11042      "#},
11043      Browsers {
11044        safari: Some(12 << 16),
11045        ..Browsers::default()
11046      },
11047    );
11048  }
11049
11050  #[test]
11051  fn test_merge_media_rules() {
11052    test(
11053      r#"
11054      @media (hover) {
11055        .foo {
11056          color: red;
11057        }
11058      }
11059      @media (hover) {
11060        .foo {
11061          background: #fff;
11062        }
11063
11064        .baz {
11065          color: #fff;
11066        }
11067      }
11068      "#,
11069      indoc! {r#"
11070      @media (hover) {
11071        .foo {
11072          color: red;
11073          background: #fff;
11074        }
11075
11076        .baz {
11077          color: #fff;
11078        }
11079      }
11080    "#},
11081    );
11082
11083    test(
11084      r#"
11085      @media (hover) {
11086        .foo {
11087          color: red;
11088        }
11089      }
11090      @media (min-width: 250px) {
11091        .foo {
11092          background: #fff;
11093        }
11094
11095        .baz {
11096          color: #fff;
11097        }
11098      }
11099      "#,
11100      indoc! {r#"
11101      @media (hover) {
11102        .foo {
11103          color: red;
11104        }
11105      }
11106
11107      @media (width >= 250px) {
11108        .foo {
11109          background: #fff;
11110        }
11111
11112        .baz {
11113          color: #fff;
11114        }
11115      }
11116    "#},
11117    );
11118  }
11119
11120  #[test]
11121  fn test_merge_supports() {
11122    test(
11123      r#"
11124      @supports (flex: 1) {
11125        .foo {
11126          color: red;
11127        }
11128      }
11129      @supports (flex: 1) {
11130        .foo {
11131          background: #fff;
11132        }
11133
11134        .baz {
11135          color: #fff;
11136        }
11137      }
11138      "#,
11139      indoc! {r#"
11140      @supports (flex: 1) {
11141        .foo {
11142          color: red;
11143          background: #fff;
11144        }
11145
11146        .baz {
11147          color: #fff;
11148        }
11149      }
11150    "#},
11151    );
11152
11153    test(
11154      r#"
11155      @supports (flex: 1) {
11156        .foo {
11157          color: red;
11158        }
11159      }
11160      @supports (display: grid) {
11161        .foo {
11162          background: #fff;
11163        }
11164
11165        .baz {
11166          color: #fff;
11167        }
11168      }
11169      "#,
11170      indoc! {r#"
11171      @supports (flex: 1) {
11172        .foo {
11173          color: red;
11174        }
11175      }
11176
11177      @supports (display: grid) {
11178        .foo {
11179          background: #fff;
11180        }
11181
11182        .baz {
11183          color: #fff;
11184        }
11185      }
11186    "#},
11187    );
11188  }
11189
11190  #[test]
11191  fn test_opacity() {
11192    minify_test(".foo { opacity: 0 }", ".foo{opacity:0}");
11193    minify_test(".foo { opacity: 0% }", ".foo{opacity:0}");
11194    minify_test(".foo { opacity: 0.5 }", ".foo{opacity:.5}");
11195    minify_test(".foo { opacity: 50% }", ".foo{opacity:.5}");
11196    minify_test(".foo { opacity: 1 }", ".foo{opacity:1}");
11197    minify_test(".foo { opacity: 100% }", ".foo{opacity:1}");
11198  }
11199
11200  #[test]
11201  fn test_transitions() {
11202    minify_test(".foo { transition-duration: 500ms }", ".foo{transition-duration:.5s}");
11203    minify_test(".foo { transition-duration: .5s }", ".foo{transition-duration:.5s}");
11204    minify_test(".foo { transition-duration: 99ms }", ".foo{transition-duration:99ms}");
11205    minify_test(".foo { transition-duration: .099s }", ".foo{transition-duration:99ms}");
11206    minify_test(".foo { transition-duration: 2000ms }", ".foo{transition-duration:2s}");
11207    minify_test(".foo { transition-duration: 2s }", ".foo{transition-duration:2s}");
11208    minify_test(
11209      ".foo { transition-duration: calc(1s - 50ms) }",
11210      ".foo{transition-duration:.95s}",
11211    );
11212    minify_test(
11213      ".foo { transition-duration: calc(1s - 50ms + 2s) }",
11214      ".foo{transition-duration:2.95s}",
11215    );
11216    minify_test(
11217      ".foo { transition-duration: calc((1s - 50ms) * 2) }",
11218      ".foo{transition-duration:1.9s}",
11219    );
11220    minify_test(
11221      ".foo { transition-duration: calc(2 * (1s - 50ms)) }",
11222      ".foo{transition-duration:1.9s}",
11223    );
11224    minify_test(
11225      ".foo { transition-duration: calc((2s + 50ms) - (1s - 50ms)) }",
11226      ".foo{transition-duration:1.1s}",
11227    );
11228    minify_test(
11229      ".foo { transition-duration: 500ms, 50ms }",
11230      ".foo{transition-duration:.5s,50ms}",
11231    );
11232    minify_test(".foo { transition-delay: 500ms }", ".foo{transition-delay:.5s}");
11233    minify_test(
11234      ".foo { transition-property: background }",
11235      ".foo{transition-property:background}",
11236    );
11237    minify_test(
11238      ".foo { transition-property: background, opacity }",
11239      ".foo{transition-property:background,opacity}",
11240    );
11241    minify_test(
11242      ".foo { transition-timing-function: linear }",
11243      ".foo{transition-timing-function:linear}",
11244    );
11245    minify_test(
11246      ".foo { transition-timing-function: ease }",
11247      ".foo{transition-timing-function:ease}",
11248    );
11249    minify_test(
11250      ".foo { transition-timing-function: ease-in }",
11251      ".foo{transition-timing-function:ease-in}",
11252    );
11253    minify_test(
11254      ".foo { transition-timing-function: ease-out }",
11255      ".foo{transition-timing-function:ease-out}",
11256    );
11257    minify_test(
11258      ".foo { transition-timing-function: ease-in-out }",
11259      ".foo{transition-timing-function:ease-in-out}",
11260    );
11261    minify_test(
11262      ".foo { transition-timing-function: cubic-bezier(0.25, 0.1, 0.25, 1) }",
11263      ".foo{transition-timing-function:ease}",
11264    );
11265    minify_test(
11266      ".foo { transition-timing-function: cubic-bezier(0.42, 0, 1, 1) }",
11267      ".foo{transition-timing-function:ease-in}",
11268    );
11269    minify_test(
11270      ".foo { transition-timing-function: cubic-bezier(0, 0, 0.58, 1) }",
11271      ".foo{transition-timing-function:ease-out}",
11272    );
11273    minify_test(
11274      ".foo { transition-timing-function: cubic-bezier(0.42, 0, 0.58, 1) }",
11275      ".foo{transition-timing-function:ease-in-out}",
11276    );
11277    minify_test(
11278      ".foo { transition-timing-function: cubic-bezier(0.58, 0.2, 0.11, 1.2) }",
11279      ".foo{transition-timing-function:cubic-bezier(.58,.2,.11,1.2)}",
11280    );
11281    minify_test(
11282      ".foo { transition-timing-function: step-start }",
11283      ".foo{transition-timing-function:step-start}",
11284    );
11285    minify_test(
11286      ".foo { transition-timing-function: step-end }",
11287      ".foo{transition-timing-function:step-end}",
11288    );
11289    minify_test(
11290      ".foo { transition-timing-function: steps(1, start) }",
11291      ".foo{transition-timing-function:step-start}",
11292    );
11293    minify_test(
11294      ".foo { transition-timing-function: steps(1, jump-start) }",
11295      ".foo{transition-timing-function:step-start}",
11296    );
11297    minify_test(
11298      ".foo { transition-timing-function: steps(1, end) }",
11299      ".foo{transition-timing-function:step-end}",
11300    );
11301    minify_test(
11302      ".foo { transition-timing-function: steps(1, jump-end) }",
11303      ".foo{transition-timing-function:step-end}",
11304    );
11305    minify_test(
11306      ".foo { transition-timing-function: steps(5, jump-start) }",
11307      ".foo{transition-timing-function:steps(5,start)}",
11308    );
11309    minify_test(
11310      ".foo { transition-timing-function: steps(5, jump-end) }",
11311      ".foo{transition-timing-function:steps(5,end)}",
11312    );
11313    minify_test(
11314      ".foo { transition-timing-function: steps(5, jump-both) }",
11315      ".foo{transition-timing-function:steps(5,jump-both)}",
11316    );
11317    minify_test(
11318      ".foo { transition-timing-function: ease-in-out, cubic-bezier(0.42, 0, 1, 1) }",
11319      ".foo{transition-timing-function:ease-in-out,ease-in}",
11320    );
11321    minify_test(
11322      ".foo { transition-timing-function: cubic-bezier(0.42, 0, 1, 1), cubic-bezier(0.58, 0.2, 0.11, 1.2) }",
11323      ".foo{transition-timing-function:ease-in,cubic-bezier(.58,.2,.11,1.2)}",
11324    );
11325    minify_test(
11326      ".foo { transition-timing-function: step-start, steps(5, jump-start) }",
11327      ".foo{transition-timing-function:step-start,steps(5,start)}",
11328    );
11329    minify_test(".foo { transition: width 2s ease }", ".foo{transition:width 2s}");
11330    minify_test(
11331      ".foo { transition: width 2s ease, height 1000ms cubic-bezier(0.25, 0.1, 0.25, 1) }",
11332      ".foo{transition:width 2s,height 1s}",
11333    );
11334    minify_test(".foo { transition: width 2s 1s }", ".foo{transition:width 2s 1s}");
11335    minify_test(".foo { transition: width 2s ease 1s }", ".foo{transition:width 2s 1s}");
11336    minify_test(
11337      ".foo { transition: ease-in 1s width 4s }",
11338      ".foo{transition:width 1s ease-in 4s}",
11339    );
11340    minify_test(".foo { transition: opacity 0s .6s }", ".foo{transition:opacity 0s .6s}");
11341    test(
11342      r#"
11343      .foo {
11344        transition-property: opacity;
11345        transition-duration: 0.09s;
11346        transition-timing-function: ease-in-out;
11347        transition-delay: 500ms;
11348      }
11349    "#,
11350      indoc! {r#"
11351      .foo {
11352        transition: opacity 90ms ease-in-out .5s;
11353      }
11354    "#},
11355    );
11356    test(
11357      r#"
11358      .foo {
11359        transition: opacity 2s;
11360        transition-timing-function: ease;
11361        transition-delay: 500ms;
11362      }
11363    "#,
11364      indoc! {r#"
11365      .foo {
11366        transition: opacity 2s .5s;
11367      }
11368    "#},
11369    );
11370    test(
11371      r#"
11372      .foo {
11373        transition: opacity 500ms;
11374        transition-timing-function: var(--ease);
11375      }
11376    "#,
11377      indoc! {r#"
11378      .foo {
11379        transition: opacity .5s;
11380        transition-timing-function: var(--ease);
11381      }
11382    "#},
11383    );
11384    test(
11385      r#"
11386      .foo {
11387        transition-property: opacity;
11388        transition-duration: 0.09s;
11389        transition-timing-function: ease-in-out;
11390        transition-delay: 500ms;
11391        transition: color 2s;
11392      }
11393    "#,
11394      indoc! {r#"
11395      .foo {
11396        transition: color 2s;
11397      }
11398    "#},
11399    );
11400    test(
11401      r#"
11402      .foo {
11403        transition-property: opacity, color;
11404        transition-duration: 2s, 4s;
11405        transition-timing-function: ease-in-out, ease-in;
11406        transition-delay: 500ms, 0s;
11407      }
11408    "#,
11409      indoc! {r#"
11410      .foo {
11411        transition: opacity 2s ease-in-out .5s, color 4s ease-in;
11412      }
11413    "#},
11414    );
11415    test(
11416      r#"
11417      .foo {
11418        transition-property: opacity, color;
11419        transition-duration: 2s;
11420        transition-timing-function: ease-in-out;
11421        transition-delay: 500ms;
11422      }
11423    "#,
11424      indoc! {r#"
11425      .foo {
11426        transition: opacity 2s ease-in-out .5s, color 2s ease-in-out .5s;
11427      }
11428    "#},
11429    );
11430    test(
11431      r#"
11432      .foo {
11433        transition-property: opacity, color, width, height;
11434        transition-duration: 2s, 4s;
11435        transition-timing-function: ease;
11436        transition-delay: 0s;
11437      }
11438    "#,
11439      indoc! {r#"
11440      .foo {
11441        transition: opacity 2s, color 4s, width 2s, height 4s;
11442      }
11443    "#},
11444    );
11445
11446    test(
11447      r#"
11448      .foo {
11449        -webkit-transition-property: opacity, color;
11450        -webkit-transition-duration: 2s, 4s;
11451        -webkit-transition-timing-function: ease-in-out, ease-in;
11452        -webkit-transition-delay: 500ms, 0s;
11453      }
11454    "#,
11455      indoc! {r#"
11456      .foo {
11457        -webkit-transition: opacity 2s ease-in-out .5s, color 4s ease-in;
11458      }
11459    "#},
11460    );
11461
11462    test(
11463      r#"
11464      .foo {
11465        -webkit-transition-property: opacity, color;
11466        -webkit-transition-duration: 2s, 4s;
11467        -webkit-transition-timing-function: ease-in-out, ease-in;
11468        -webkit-transition-delay: 500ms, 0s;
11469        -moz-transition-property: opacity, color;
11470        -moz-transition-duration: 2s, 4s;
11471        -moz-transition-timing-function: ease-in-out, ease-in;
11472        -moz-transition-delay: 500ms, 0s;
11473        transition-property: opacity, color;
11474        transition-duration: 2s, 4s;
11475        transition-timing-function: ease-in-out, ease-in;
11476        transition-delay: 500ms, 0s;
11477      }
11478    "#,
11479      indoc! {r#"
11480      .foo {
11481        -webkit-transition: opacity 2s ease-in-out .5s, color 4s ease-in;
11482        -moz-transition: opacity 2s ease-in-out .5s, color 4s ease-in;
11483        transition: opacity 2s ease-in-out .5s, color 4s ease-in;
11484      }
11485    "#},
11486    );
11487
11488    test(
11489      r#"
11490      .foo {
11491        -webkit-transition-property: opacity, color;
11492        -moz-transition-property: opacity, color;
11493        transition-property: opacity, color;
11494        -webkit-transition-duration: 2s, 4s;
11495        -moz-transition-duration: 2s, 4s;
11496        transition-duration: 2s, 4s;
11497        -webkit-transition-timing-function: ease-in-out, ease-in;
11498        transition-timing-function: ease-in-out, ease-in;
11499        -moz-transition-timing-function: ease-in-out, ease-in;
11500        -webkit-transition-delay: 500ms, 0s;
11501        -moz-transition-delay: 500ms, 0s;
11502        transition-delay: 500ms, 0s;
11503      }
11504    "#,
11505      indoc! {r#"
11506      .foo {
11507        -webkit-transition: opacity 2s ease-in-out .5s, color 4s ease-in;
11508        -moz-transition: opacity 2s ease-in-out .5s, color 4s ease-in;
11509        transition: opacity 2s ease-in-out .5s, color 4s ease-in;
11510      }
11511    "#},
11512    );
11513
11514    test(
11515      r#"
11516      .foo {
11517        -webkit-transition-property: opacity;
11518        -moz-transition-property: color;
11519        transition-property: opacity, color;
11520        -webkit-transition-duration: 2s;
11521        -moz-transition-duration: 4s;
11522        transition-duration: 2s, 4s;
11523        -webkit-transition-timing-function: ease-in-out;
11524        -moz-transition-timing-function: ease-in-out;
11525        transition-timing-function: ease-in-out, ease-in;
11526        -webkit-transition-delay: 500ms;
11527        -moz-transition-delay: 0s;
11528        transition-delay: 500ms, 0s;
11529      }
11530    "#,
11531      indoc! {r#"
11532      .foo {
11533        -webkit-transition-property: opacity;
11534        -moz-transition-property: color;
11535        transition-property: opacity, color;
11536        -webkit-transition-duration: 2s;
11537        -moz-transition-duration: 4s;
11538        transition-duration: 2s, 4s;
11539        -webkit-transition-timing-function: ease-in-out;
11540        -moz-transition-timing-function: ease-in-out;
11541        -webkit-transition-delay: .5s;
11542        transition-timing-function: ease-in-out, ease-in;
11543        -moz-transition-delay: 0s;
11544        transition-delay: .5s, 0s;
11545      }
11546    "#},
11547    );
11548
11549    test(
11550      r#"
11551      .foo {
11552        -webkit-transition-property: opacity;
11553        transition-property: opacity, color;
11554        -moz-transition-property: color;
11555        -webkit-transition-duration: 2s;
11556        transition-duration: 2s, 4s;
11557        -moz-transition-duration: 4s;
11558        -webkit-transition-timing-function: ease-in-out;
11559        transition-timing-function: ease-in-out, ease-in;
11560        -moz-transition-timing-function: ease-in-out;
11561        -webkit-transition-delay: 500ms;
11562        transition-delay: 500ms, 0s;
11563        -moz-transition-delay: 0s;
11564      }
11565    "#,
11566      indoc! {r#"
11567      .foo {
11568        -webkit-transition-property: opacity;
11569        transition-property: opacity, color;
11570        -moz-transition-property: color;
11571        -webkit-transition-duration: 2s;
11572        transition-duration: 2s, 4s;
11573        -moz-transition-duration: 4s;
11574        -webkit-transition-timing-function: ease-in-out;
11575        transition-timing-function: ease-in-out, ease-in;
11576        -webkit-transition-delay: .5s;
11577        -moz-transition-timing-function: ease-in-out;
11578        transition-delay: .5s, 0s;
11579        -moz-transition-delay: 0s;
11580      }
11581    "#},
11582    );
11583
11584    test(
11585      r#"
11586      .foo {
11587        transition: opacity 2s;
11588        -webkit-transition-duration: 2s;
11589      }
11590    "#,
11591      indoc! {r#"
11592      .foo {
11593        transition: opacity 2s;
11594        -webkit-transition-duration: 2s;
11595      }
11596    "#},
11597    );
11598
11599    prefix_test(
11600      r#"
11601      .foo {
11602        transition-property: margin-inline-start;
11603      }
11604    "#,
11605      indoc! {r#"
11606      .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))) {
11607        transition-property: margin-left;
11608      }
11609
11610      .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))) {
11611        transition-property: margin-left;
11612      }
11613
11614      .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)) {
11615        transition-property: margin-right;
11616      }
11617
11618      .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)) {
11619        transition-property: margin-right;
11620      }
11621    "#
11622      },
11623      Browsers {
11624        safari: Some(8 << 16),
11625        ..Browsers::default()
11626      },
11627    );
11628
11629    prefix_test(
11630      r#"
11631      .foo {
11632        transition-property: margin-inline-start, padding-inline-start;
11633      }
11634    "#,
11635      indoc! {r#"
11636      .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))) {
11637        transition-property: margin-left, padding-left;
11638      }
11639
11640      .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))) {
11641        transition-property: margin-left, padding-left;
11642      }
11643
11644      .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)) {
11645        transition-property: margin-right, padding-right;
11646      }
11647
11648      .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)) {
11649        transition-property: margin-right, padding-right;
11650      }
11651    "#
11652      },
11653      Browsers {
11654        safari: Some(8 << 16),
11655        ..Browsers::default()
11656      },
11657    );
11658
11659    prefix_test(
11660      r#"
11661      .foo {
11662        transition-property: margin-inline-start, opacity, padding-inline-start, color;
11663      }
11664    "#,
11665      indoc! {r#"
11666      .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))) {
11667        transition-property: margin-left, opacity, padding-left, color;
11668      }
11669
11670      .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))) {
11671        transition-property: margin-left, opacity, padding-left, color;
11672      }
11673
11674      .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)) {
11675        transition-property: margin-right, opacity, padding-right, color;
11676      }
11677
11678      .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)) {
11679        transition-property: margin-right, opacity, padding-right, color;
11680      }
11681    "#
11682      },
11683      Browsers {
11684        safari: Some(8 << 16),
11685        ..Browsers::default()
11686      },
11687    );
11688
11689    prefix_test(
11690      r#"
11691      .foo {
11692        transition-property: margin-block;
11693      }
11694    "#,
11695      indoc! {r#"
11696      .foo {
11697        transition-property: margin-top, margin-bottom;
11698      }
11699    "#
11700      },
11701      Browsers {
11702        safari: Some(8 << 16),
11703        ..Browsers::default()
11704      },
11705    );
11706
11707    prefix_test(
11708      r#"
11709      .foo {
11710        transition: margin-inline-start 2s;
11711      }
11712    "#,
11713      indoc! {r#"
11714      .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))) {
11715        transition: margin-left 2s;
11716      }
11717
11718      .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))) {
11719        transition: margin-left 2s;
11720      }
11721
11722      .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)) {
11723        transition: margin-right 2s;
11724      }
11725
11726      .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)) {
11727        transition: margin-right 2s;
11728      }
11729    "#
11730      },
11731      Browsers {
11732        safari: Some(8 << 16),
11733        ..Browsers::default()
11734      },
11735    );
11736
11737    prefix_test(
11738      r#"
11739      .foo {
11740        transition: margin-inline-start 2s, padding-inline-start 2s;
11741      }
11742    "#,
11743      indoc! {r#"
11744      .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))) {
11745        transition: margin-left 2s, padding-left 2s;
11746      }
11747
11748      .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))) {
11749        transition: margin-left 2s, padding-left 2s;
11750      }
11751
11752      .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)) {
11753        transition: margin-right 2s, padding-right 2s;
11754      }
11755
11756      .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)) {
11757        transition: margin-right 2s, padding-right 2s;
11758      }
11759    "#
11760      },
11761      Browsers {
11762        safari: Some(8 << 16),
11763        ..Browsers::default()
11764      },
11765    );
11766
11767    prefix_test(
11768      r#"
11769      .foo {
11770        transition: margin-block-start 2s;
11771      }
11772    "#,
11773      indoc! {r#"
11774      .foo {
11775        transition: margin-top 2s;
11776      }
11777    "#
11778      },
11779      Browsers {
11780        safari: Some(8 << 16),
11781        ..Browsers::default()
11782      },
11783    );
11784
11785    prefix_test(
11786      r#"
11787      .foo {
11788        transition: transform;
11789      }
11790    "#,
11791      indoc! {r#"
11792      .foo {
11793        -webkit-transition: -webkit-transform, transform;
11794        transition: -webkit-transform, transform;
11795      }
11796    "#
11797      },
11798      Browsers {
11799        safari: Some(6 << 16),
11800        ..Browsers::default()
11801      },
11802    );
11803
11804    prefix_test(
11805      r#"
11806      .foo {
11807        transition: border-start-start-radius;
11808      }
11809    "#,
11810      indoc! {r#"
11811      .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))) {
11812        -webkit-transition: -webkit-border-top-left-radius, border-top-left-radius;
11813        transition: -webkit-border-top-left-radius, border-top-left-radius;
11814      }
11815
11816      .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)) {
11817        -webkit-transition: -webkit-border-top-right-radius, border-top-right-radius;
11818        transition: -webkit-border-top-right-radius, border-top-right-radius;
11819      }
11820    "#
11821      },
11822      Browsers {
11823        safari: Some(4 << 16),
11824        ..Browsers::default()
11825      },
11826    );
11827
11828    prefix_test(
11829      r#"
11830      .foo {
11831        transition: border-start-start-radius;
11832      }
11833    "#,
11834      indoc! {r#"
11835      .foo:not(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
11836        transition: border-top-left-radius;
11837      }
11838
11839      .foo:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) {
11840        transition: border-top-right-radius;
11841      }
11842    "#
11843      },
11844      Browsers {
11845        safari: Some(12 << 16),
11846        ..Browsers::default()
11847      },
11848    );
11849
11850    test(
11851      r#"
11852      .foo {
11853        -webkit-transition: background 200ms;
11854        -moz-transition: background 200ms;
11855        transition: background 230ms;
11856      }
11857    "#,
11858      indoc! {r#"
11859      .foo {
11860        -webkit-transition: background .2s;
11861        -moz-transition: background .2s;
11862        transition: background .23s;
11863      }
11864    "#},
11865    );
11866
11867    prefix_test(
11868      r#"
11869      .foo {
11870        -webkit-transition: background 200ms;
11871        -moz-transition: background 200ms;
11872        transition: background 230ms;
11873      }
11874    "#,
11875      indoc! {r#"
11876      .foo {
11877        -webkit-transition: background .2s;
11878        -moz-transition: background .2s;
11879        transition: background .23s;
11880      }
11881    "#},
11882      Browsers {
11883        chrome: Some(95 << 16),
11884        ..Browsers::default()
11885      },
11886    );
11887    prefix_test(
11888      r#"
11889       .foo {
11890         transition-property: -webkit-backdrop-filter, backdrop-filter;
11891       }
11892       .bar {
11893         transition-property: backdrop-filter;
11894       }
11895       .baz {
11896         transition-property: -webkit-backdrop-filter;
11897       }
11898     "#,
11899      indoc! {r#"
11900       .foo, .bar {
11901         transition-property: -webkit-backdrop-filter, backdrop-filter;
11902       }
11903
11904       .baz {
11905         transition-property: -webkit-backdrop-filter;
11906       }
11907     "#
11908      },
11909      Browsers {
11910        safari: Some(15 << 16),
11911        ..Browsers::default()
11912      },
11913    );
11914    prefix_test(
11915      r#"
11916       .foo {
11917         transition-property: -webkit-border-radius, -webkit-border-radius, -moz-border-radius;
11918       }
11919     "#,
11920      indoc! {r#"
11921       .foo {
11922         transition-property: -webkit-border-radius, -moz-border-radius;
11923       }
11924     "#
11925      },
11926      Browsers {
11927        safari: Some(15 << 16),
11928        ..Browsers::default()
11929      },
11930    );
11931    prefix_test(
11932      r#"
11933       .foo {
11934         transition: -webkit-backdrop-filter, backdrop-filter;
11935       }
11936       .bar {
11937         transition: backdrop-filter;
11938       }
11939       .baz {
11940         transition: -webkit-backdrop-filter;
11941       }
11942     "#,
11943      indoc! {r#"
11944       .foo, .bar {
11945         transition: -webkit-backdrop-filter, backdrop-filter;
11946       }
11947
11948       .baz {
11949         transition: -webkit-backdrop-filter;
11950       }
11951     "#
11952      },
11953      Browsers {
11954        safari: Some(15 << 16),
11955        ..Browsers::default()
11956      },
11957    );
11958  }
11959
11960  #[test]
11961  fn test_animation() {
11962    minify_test(".foo { animation-name: test }", ".foo{animation-name:test}");
11963    minify_test(".foo { animation-name: \"test\" }", ".foo{animation-name:test}");
11964    minify_test(".foo { animation-name: foo, bar }", ".foo{animation-name:foo,bar}");
11965    minify_test(".foo { animation-name: \"none\" }", ".foo{animation-name:\"none\"}");
11966    minify_test(
11967      ".foo { animation-name: \"none\", foo }",
11968      ".foo{animation-name:\"none\",foo}",
11969    );
11970    let name = crate::properties::animation::AnimationName::parse_string("default");
11971    assert!(matches!(name, Err(..)));
11972
11973    minify_test(".foo { animation-name: none }", ".foo{animation-name:none}");
11974    minify_test(".foo { animation-name: none, none }", ".foo{animation-name:none,none}");
11975
11976    // Test CSS-wide keywords
11977    minify_test(".foo { animation-name: unset }", ".foo{animation-name:unset}");
11978    minify_test(".foo { animation-name: \"unset\" }", ".foo{animation-name:\"unset\"}");
11979    minify_test(".foo { animation-name: \"revert\" }", ".foo{animation-name:\"revert\"}");
11980    minify_test(
11981      ".foo { animation-name: \"unset\", \"revert\"}",
11982      ".foo{animation-name:\"unset\",\"revert\"}",
11983    );
11984    minify_test(
11985      ".foo { animation-name: foo, \"revert\"}",
11986      ".foo{animation-name:foo,\"revert\"}",
11987    );
11988    minify_test(
11989      ".foo { animation-name: \"string\", \"revert\"}",
11990      ".foo{animation-name:string,\"revert\"}",
11991    );
11992    minify_test(
11993      ".foo { animation-name: \"string\", foo, \"revert\"}",
11994      ".foo{animation-name:string,foo,\"revert\"}",
11995    );
11996    minify_test(
11997      ".foo { animation-name: \"default\" }",
11998      ".foo{animation-name:\"default\"}",
11999    );
12000    minify_test(".foo { animation-duration: 100ms }", ".foo{animation-duration:.1s}");
12001    minify_test(
12002      ".foo { animation-duration: 100ms, 2000ms }",
12003      ".foo{animation-duration:.1s,2s}",
12004    );
12005    minify_test(
12006      ".foo { animation-timing-function: ease }",
12007      ".foo{animation-timing-function:ease}",
12008    );
12009    minify_test(
12010      ".foo { animation-timing-function: cubic-bezier(0.42, 0, 1, 1) }",
12011      ".foo{animation-timing-function:ease-in}",
12012    );
12013    minify_test(
12014      ".foo { animation-timing-function: ease, cubic-bezier(0.42, 0, 1, 1) }",
12015      ".foo{animation-timing-function:ease,ease-in}",
12016    );
12017    minify_test(
12018      ".foo { animation-iteration-count: 5 }",
12019      ".foo{animation-iteration-count:5}",
12020    );
12021    minify_test(
12022      ".foo { animation-iteration-count: 2.5 }",
12023      ".foo{animation-iteration-count:2.5}",
12024    );
12025    minify_test(
12026      ".foo { animation-iteration-count: 2.0 }",
12027      ".foo{animation-iteration-count:2}",
12028    );
12029    minify_test(
12030      ".foo { animation-iteration-count: infinite }",
12031      ".foo{animation-iteration-count:infinite}",
12032    );
12033    minify_test(
12034      ".foo { animation-iteration-count: 1, infinite }",
12035      ".foo{animation-iteration-count:1,infinite}",
12036    );
12037    minify_test(
12038      ".foo { animation-direction: reverse }",
12039      ".foo{animation-direction:reverse}",
12040    );
12041    minify_test(
12042      ".foo { animation-direction: alternate, reverse }",
12043      ".foo{animation-direction:alternate,reverse}",
12044    );
12045    minify_test(
12046      ".foo { animation-play-state: paused }",
12047      ".foo{animation-play-state:paused}",
12048    );
12049    minify_test(
12050      ".foo { animation-play-state: running, paused }",
12051      ".foo{animation-play-state:running,paused}",
12052    );
12053    minify_test(".foo { animation-delay: 100ms }", ".foo{animation-delay:.1s}");
12054    minify_test(
12055      ".foo { animation-delay: 100ms, 2000ms }",
12056      ".foo{animation-delay:.1s,2s}",
12057    );
12058    minify_test(
12059      ".foo { animation-fill-mode: forwards }",
12060      ".foo{animation-fill-mode:forwards}",
12061    );
12062    minify_test(
12063      ".foo { animation-fill-mode: Backwards,forwards }",
12064      ".foo{animation-fill-mode:backwards,forwards}",
12065    );
12066    minify_test(".foo { animation: none }", ".foo{animation:none}");
12067    minify_test(".foo { animation: \"none\" }", ".foo{animation:\"none\"}");
12068    minify_test(".foo { animation: \"None\" }", ".foo{animation:\"None\"}");
12069    minify_test(".foo { animation: \"none\", none }", ".foo{animation:\"none\",none}");
12070    minify_test(".foo { animation: none, none }", ".foo{animation:none,none}");
12071    minify_test(".foo { animation: \"none\" none }", ".foo{animation:\"none\"}");
12072    minify_test(".foo { animation: none none }", ".foo{animation:none}");
12073
12074    // Test animation-name + animation-fill-mode
12075    minify_test(
12076      ".foo { animation: 2s both \"none\"}",
12077      ".foo{animation:2s both \"none\"}",
12078    );
12079    minify_test(
12080      ".foo { animation: both \"none\" 2s}",
12081      ".foo{animation:2s both \"none\"}",
12082    );
12083    minify_test(".foo { animation: \"none\" 2s none}", ".foo{animation:2s \"none\"}");
12084    minify_test(".foo { animation: none \"none\" 2s}", ".foo{animation:2s \"none\"}");
12085    minify_test(
12086      ".foo { animation: none, \"none\" 2s forwards}",
12087      ".foo{animation:none,2s forwards \"none\"}",
12088    );
12089
12090    minify_test(".foo { animation: \"unset\" }", ".foo{animation:\"unset\"}");
12091    minify_test(".foo { animation: \"string\" .5s }", ".foo{animation:.5s string}");
12092    minify_test(".foo { animation: \"unset\" .5s }", ".foo{animation:.5s \"unset\"}");
12093    minify_test(
12094      ".foo { animation: none, \"unset\" .5s}",
12095      ".foo{animation:none,.5s \"unset\"}",
12096    );
12097    minify_test(
12098      ".foo { animation: \"unset\" 0s 3s infinite, none }",
12099      ".foo{animation:0s 3s infinite \"unset\",none}",
12100    );
12101
12102    minify_test(".foo { animation: \"infinite\" 2s 1 }", ".foo{animation:2s 1 infinite}");
12103    minify_test(".foo { animation: \"paused\" 2s }", ".foo{animation:2s running paused}");
12104    minify_test(
12105      ".foo { animation: \"forwards\" 2s }",
12106      ".foo{animation:2s none forwards}",
12107    );
12108    minify_test(
12109      ".foo { animation: \"reverse\" 2s }",
12110      ".foo{animation:2s normal reverse}",
12111    );
12112    minify_test(
12113      ".foo { animation: \"reverse\" 2s alternate }",
12114      ".foo{animation:2s alternate reverse}",
12115    );
12116
12117    minify_test(
12118      ".foo { animation: 3s ease-in 1s infinite reverse both running slidein }",
12119      ".foo{animation:3s ease-in 1s infinite reverse both slidein}",
12120    );
12121    minify_test(
12122      ".foo { animation: 3s slidein paused ease 1s 1 reverse both }",
12123      ".foo{animation:3s 1s reverse both paused slidein}",
12124    );
12125    minify_test(".foo { animation: 3s ease ease }", ".foo{animation:3s ease ease}");
12126    minify_test(
12127      ".foo { animation: 3s cubic-bezier(0.25, 0.1, 0.25, 1) foo }",
12128      ".foo{animation:3s foo}",
12129    );
12130    minify_test(
12131      ".foo { animation: foo 0s 3s infinite }",
12132      ".foo{animation:0s 3s infinite foo}",
12133    );
12134    minify_test(".foo { animation: foo 3s --test }", ".foo{animation:3s foo --test}");
12135    minify_test(".foo { animation: foo 3s scroll() }", ".foo{animation:3s foo scroll()}");
12136    minify_test(
12137      ".foo { animation: foo 3s scroll(block) }",
12138      ".foo{animation:3s foo scroll()}",
12139    );
12140    minify_test(
12141      ".foo { animation: foo 3s scroll(root inline) }",
12142      ".foo{animation:3s foo scroll(root inline)}",
12143    );
12144    minify_test(
12145      ".foo { animation: foo 3s scroll(inline root) }",
12146      ".foo{animation:3s foo scroll(root inline)}",
12147    );
12148    minify_test(
12149      ".foo { animation: foo 3s scroll(inline nearest) }",
12150      ".foo{animation:3s foo scroll(inline)}",
12151    );
12152    minify_test(
12153      ".foo { animation: foo 3s view(block) }",
12154      ".foo{animation:3s foo view()}",
12155    );
12156    minify_test(
12157      ".foo { animation: foo 3s view(inline) }",
12158      ".foo{animation:3s foo view(inline)}",
12159    );
12160    minify_test(
12161      ".foo { animation: foo 3s view(inline 10px 10px) }",
12162      ".foo{animation:3s foo view(inline 10px)}",
12163    );
12164    minify_test(
12165      ".foo { animation: foo 3s view(inline 10px 12px) }",
12166      ".foo{animation:3s foo view(inline 10px 12px)}",
12167    );
12168    minify_test(
12169      ".foo { animation: foo 3s view(inline auto auto) }",
12170      ".foo{animation:3s foo view(inline)}",
12171    );
12172    minify_test(".foo { animation: foo 3s auto }", ".foo{animation:3s foo}");
12173    minify_test(".foo { animation-composition: add }", ".foo{animation-composition:add}");
12174    test(
12175      r#"
12176      .foo {
12177        animation-name: foo;
12178        animation-duration: 0.09s;
12179        animation-timing-function: ease-in-out;
12180        animation-iteration-count: 2;
12181        animation-direction: alternate;
12182        animation-play-state: running;
12183        animation-delay: 100ms;
12184        animation-fill-mode: forwards;
12185        animation-timeline: auto;
12186      }
12187    "#,
12188      indoc! {r#"
12189      .foo {
12190        animation: 90ms ease-in-out .1s 2 alternate forwards foo;
12191      }
12192    "#},
12193    );
12194    test(
12195      r#"
12196      .foo {
12197        animation-name: foo, bar;
12198        animation-duration: 0.09s, 200ms;
12199        animation-timing-function: ease-in-out, ease;
12200        animation-iteration-count: 2, 1;
12201        animation-direction: alternate, normal;
12202        animation-play-state: running, paused;
12203        animation-delay: 100ms, 0s;
12204        animation-fill-mode: forwards, none;
12205        animation-timeline: auto, auto;
12206      }
12207    "#,
12208      indoc! {r#"
12209      .foo {
12210        animation: 90ms ease-in-out .1s 2 alternate forwards foo, .2s paused bar;
12211      }
12212    "#},
12213    );
12214    test(
12215      r#"
12216      .foo {
12217        animation: bar 200ms;
12218        animation-timing-function: ease-in-out;
12219      }
12220    "#,
12221      indoc! {r#"
12222      .foo {
12223        animation: .2s ease-in-out bar;
12224      }
12225    "#},
12226    );
12227    test(
12228      r#"
12229      .foo {
12230        animation: bar 200ms;
12231        animation-timing-function: var(--ease);
12232      }
12233    "#,
12234      indoc! {r#"
12235      .foo {
12236        animation: .2s bar;
12237        animation-timing-function: var(--ease);
12238      }
12239    "#},
12240    );
12241    test(
12242      r#"
12243      .foo {
12244        animation-name: foo, bar;
12245        animation-duration: 0.09s;
12246        animation-timing-function: ease-in-out;
12247        animation-iteration-count: 2;
12248        animation-direction: alternate;
12249        animation-play-state: running;
12250        animation-delay: 100ms;
12251        animation-fill-mode: forwards;
12252        animation-timeline: auto;
12253      }
12254    "#,
12255      indoc! {r#"
12256      .foo {
12257        animation-name: foo, bar;
12258        animation-duration: 90ms;
12259        animation-timing-function: ease-in-out;
12260        animation-iteration-count: 2;
12261        animation-direction: alternate;
12262        animation-play-state: running;
12263        animation-delay: .1s;
12264        animation-fill-mode: forwards;
12265        animation-timeline: auto;
12266      }
12267    "#},
12268    );
12269    test(
12270      r#"
12271      .foo {
12272        animation-name: foo;
12273        animation-duration: 0.09s;
12274        animation-timing-function: ease-in-out;
12275        animation-iteration-count: 2;
12276        animation-direction: alternate;
12277        animation-play-state: running;
12278        animation-delay: 100ms;
12279        animation-fill-mode: forwards;
12280        animation-timeline: scroll();
12281      }
12282    "#,
12283      indoc! {r#"
12284      .foo {
12285        animation: 90ms ease-in-out .1s 2 alternate forwards foo scroll();
12286      }
12287    "#},
12288    );
12289    test(
12290      r#"
12291      .foo {
12292        animation-name: foo;
12293        animation-duration: 0.09s;
12294        animation-timing-function: ease-in-out;
12295        animation-iteration-count: 2;
12296        animation-direction: alternate;
12297        animation-play-state: running;
12298        animation-delay: 100ms;
12299        animation-fill-mode: forwards;
12300        animation-timeline: scroll(), view();
12301      }
12302    "#,
12303      indoc! {r#"
12304      .foo {
12305        animation-name: foo;
12306        animation-duration: 90ms;
12307        animation-timing-function: ease-in-out;
12308        animation-iteration-count: 2;
12309        animation-direction: alternate;
12310        animation-play-state: running;
12311        animation-delay: .1s;
12312        animation-fill-mode: forwards;
12313        animation-timeline: scroll(), view();
12314      }
12315    "#},
12316    );
12317    test(
12318      r#"
12319      .foo {
12320        -webkit-animation-name: foo;
12321        -webkit-animation-duration: 0.09s;
12322        -webkit-animation-timing-function: ease-in-out;
12323        -webkit-animation-iteration-count: 2;
12324        -webkit-animation-direction: alternate;
12325        -webkit-animation-play-state: running;
12326        -webkit-animation-delay: 100ms;
12327        -webkit-animation-fill-mode: forwards;
12328      }
12329    "#,
12330      indoc! {r#"
12331      .foo {
12332        -webkit-animation: 90ms ease-in-out .1s 2 alternate forwards foo;
12333      }
12334    "#},
12335    );
12336    test(
12337      r#"
12338      .foo {
12339        -moz-animation: bar 200ms;
12340        -moz-animation-timing-function: ease-in-out;
12341      }
12342    "#,
12343      indoc! {r#"
12344      .foo {
12345        -moz-animation: .2s ease-in-out bar;
12346      }
12347    "#},
12348    );
12349    test(
12350      r#"
12351      .foo {
12352        -webkit-animation: bar 200ms;
12353        -webkit-animation-timing-function: ease-in-out;
12354        -moz-animation: bar 200ms;
12355        -moz-animation-timing-function: ease-in-out;
12356      }
12357    "#,
12358      indoc! {r#"
12359      .foo {
12360        -webkit-animation: .2s ease-in-out bar;
12361        -moz-animation: .2s ease-in-out bar;
12362      }
12363    "#},
12364    );
12365
12366    prefix_test(
12367      r#"
12368      .foo {
12369        animation: .2s ease-in-out bar;
12370      }
12371    "#,
12372      indoc! {r#"
12373      .foo {
12374        -webkit-animation: .2s ease-in-out bar;
12375        -moz-animation: .2s ease-in-out bar;
12376        animation: .2s ease-in-out bar;
12377      }
12378    "#},
12379      Browsers {
12380        firefox: Some(6 << 16),
12381        safari: Some(6 << 16),
12382        ..Browsers::default()
12383      },
12384    );
12385
12386    prefix_test(
12387      r#"
12388      .foo {
12389        -webkit-animation: .2s ease-in-out bar;
12390        -moz-animation: .2s ease-in-out bar;
12391        animation: .2s ease-in-out bar;
12392      }
12393    "#,
12394      indoc! {r#"
12395      .foo {
12396        animation: .2s ease-in-out bar;
12397      }
12398    "#},
12399      Browsers {
12400        firefox: Some(20 << 16),
12401        safari: Some(14 << 16),
12402        ..Browsers::default()
12403      },
12404    );
12405    prefix_test(
12406      r#"
12407      .foo {
12408        animation: 200ms var(--ease) bar;
12409      }
12410    "#,
12411      indoc! {r#"
12412      .foo {
12413        -webkit-animation: .2s var(--ease) bar;
12414        -moz-animation: .2s var(--ease) bar;
12415        animation: .2s var(--ease) bar;
12416      }
12417    "#},
12418      Browsers {
12419        firefox: Some(6 << 16),
12420        safari: Some(6 << 16),
12421        ..Browsers::default()
12422      },
12423    );
12424
12425    prefix_test(
12426      r#"
12427      .foo {
12428        animation: .2s ease-in-out bar scroll();
12429      }
12430    "#,
12431      indoc! {r#"
12432      .foo {
12433        animation: .2s ease-in-out bar;
12434        animation-timeline: scroll();
12435      }
12436    "#},
12437      Browsers {
12438        safari: Some(16 << 16),
12439        ..Browsers::default()
12440      },
12441    );
12442    prefix_test(
12443      r#"
12444      .foo {
12445        animation: .2s ease-in-out bar scroll();
12446      }
12447    "#,
12448      indoc! {r#"
12449      .foo {
12450        animation: .2s ease-in-out bar scroll();
12451      }
12452    "#},
12453      Browsers {
12454        chrome: Some(120 << 16),
12455        ..Browsers::default()
12456      },
12457    );
12458    prefix_test(
12459      r#"
12460      .foo {
12461        animation: .2s ease-in-out bar scroll();
12462      }
12463    "#,
12464      indoc! {r#"
12465      .foo {
12466        -webkit-animation: .2s ease-in-out bar;
12467        animation: .2s ease-in-out bar;
12468        animation-timeline: scroll();
12469      }
12470    "#},
12471      Browsers {
12472        safari: Some(6 << 16),
12473        ..Browsers::default()
12474      },
12475    );
12476
12477    minify_test(
12478      ".foo { animation-range-start: entry 10% }",
12479      ".foo{animation-range-start:entry 10%}",
12480    );
12481    minify_test(
12482      ".foo { animation-range-start: entry 0% }",
12483      ".foo{animation-range-start:entry}",
12484    );
12485    minify_test(
12486      ".foo { animation-range-start: entry }",
12487      ".foo{animation-range-start:entry}",
12488    );
12489    minify_test(".foo { animation-range-start: 50% }", ".foo{animation-range-start:50%}");
12490    minify_test(
12491      ".foo { animation-range-end: exit 10% }",
12492      ".foo{animation-range-end:exit 10%}",
12493    );
12494    minify_test(
12495      ".foo { animation-range-end: exit 100% }",
12496      ".foo{animation-range-end:exit}",
12497    );
12498    minify_test(".foo { animation-range-end: exit }", ".foo{animation-range-end:exit}");
12499    minify_test(".foo { animation-range-end: 50% }", ".foo{animation-range-end:50%}");
12500    minify_test(
12501      ".foo { animation-range: entry 10% exit 90% }",
12502      ".foo{animation-range:entry 10% exit 90%}",
12503    );
12504    minify_test(
12505      ".foo { animation-range: entry 0% exit 100% }",
12506      ".foo{animation-range:entry exit}",
12507    );
12508    minify_test(".foo { animation-range: entry }", ".foo{animation-range:entry}");
12509    minify_test(
12510      ".foo { animation-range: entry 0% entry 100% }",
12511      ".foo{animation-range:entry}",
12512    );
12513    minify_test(".foo { animation-range: 50% normal }", ".foo{animation-range:50%}");
12514    minify_test(
12515      ".foo { animation-range: normal normal }",
12516      ".foo{animation-range:normal}",
12517    );
12518    test(
12519      r#"
12520      .foo {
12521        animation-range-start: entry 10%;
12522        animation-range-end: exit 90%;
12523      }
12524      "#,
12525      indoc! {r#"
12526      .foo {
12527        animation-range: entry 10% exit 90%;
12528      }
12529      "#},
12530    );
12531    test(
12532      r#"
12533      .foo {
12534        animation-range-start: entry 0%;
12535        animation-range-end: entry 100%;
12536      }
12537      "#,
12538      indoc! {r#"
12539      .foo {
12540        animation-range: entry;
12541      }
12542      "#},
12543    );
12544    test(
12545      r#"
12546      .foo {
12547        animation-range-start: entry 0%;
12548        animation-range-end: exit 100%;
12549      }
12550      "#,
12551      indoc! {r#"
12552      .foo {
12553        animation-range: entry exit;
12554      }
12555      "#},
12556    );
12557    test(
12558      r#"
12559      .foo {
12560        animation-range-start: 10%;
12561        animation-range-end: normal;
12562      }
12563      "#,
12564      indoc! {r#"
12565      .foo {
12566        animation-range: 10%;
12567      }
12568      "#},
12569    );
12570    test(
12571      r#"
12572      .foo {
12573        animation-range-start: 10%;
12574        animation-range-end: 90%;
12575      }
12576      "#,
12577      indoc! {r#"
12578      .foo {
12579        animation-range: 10% 90%;
12580      }
12581      "#},
12582    );
12583    test(
12584      r#"
12585      .foo {
12586        animation-range-start: entry 10%;
12587        animation-range-end: exit 100%;
12588      }
12589      "#,
12590      indoc! {r#"
12591      .foo {
12592        animation-range: entry 10% exit;
12593      }
12594      "#},
12595    );
12596    test(
12597      r#"
12598      .foo {
12599        animation-range-start: 10%;
12600        animation-range-end: exit 90%;
12601      }
12602      "#,
12603      indoc! {r#"
12604      .foo {
12605        animation-range: 10% exit 90%;
12606      }
12607      "#},
12608    );
12609    test(
12610      r#"
12611      .foo {
12612        animation-range-start: entry 10%;
12613        animation-range-end: 90%;
12614      }
12615      "#,
12616      indoc! {r#"
12617      .foo {
12618        animation-range: entry 10% 90%;
12619      }
12620      "#},
12621    );
12622    test(
12623      r#"
12624      .foo {
12625        animation-range: entry;
12626        animation-range-end: 90%;
12627      }
12628      "#,
12629      indoc! {r#"
12630      .foo {
12631        animation-range: entry 90%;
12632      }
12633      "#},
12634    );
12635    test(
12636      r#"
12637      .foo {
12638        animation-range: entry;
12639        animation-range-end: var(--end);
12640      }
12641      "#,
12642      indoc! {r#"
12643      .foo {
12644        animation-range: entry;
12645        animation-range-end: var(--end);
12646      }
12647      "#},
12648    );
12649    test(
12650      r#"
12651      .foo {
12652        animation-range-start: entry 10%, entry 50%;
12653        animation-range-end: exit 90%;
12654      }
12655      "#,
12656      indoc! {r#"
12657      .foo {
12658        animation-range-start: entry 10%, entry 50%;
12659        animation-range-end: exit 90%;
12660      }
12661      "#},
12662    );
12663    test(
12664      r#"
12665      .foo {
12666        animation-range-start: entry 10%, entry 50%;
12667        animation-range-end: exit 90%, exit 100%;
12668      }
12669      "#,
12670      indoc! {r#"
12671      .foo {
12672        animation-range: entry 10% exit 90%, entry 50% exit;
12673      }
12674      "#},
12675    );
12676    test(
12677      r#"
12678      .foo {
12679        animation-range: entry;
12680        animation-range-end: 90%;
12681        animation: spin 100ms;
12682      }
12683      "#,
12684      indoc! {r#"
12685      .foo {
12686        animation: .1s spin;
12687      }
12688      "#},
12689    );
12690    test(
12691      r#"
12692      .foo {
12693        animation: spin 100ms;
12694        animation-range: entry;
12695        animation-range-end: 90%;
12696      }
12697      "#,
12698      indoc! {r#"
12699      .foo {
12700        animation: .1s spin;
12701        animation-range: entry 90%;
12702      }
12703      "#},
12704    );
12705    test(
12706      r#"
12707      .foo {
12708        animation-range: entry;
12709        animation-range-end: 90%;
12710        animation: var(--animation) 100ms;
12711      }
12712      "#,
12713      indoc! {r#"
12714      .foo {
12715        animation: var(--animation) .1s;
12716      }
12717      "#},
12718    );
12719  }
12720
12721  #[test]
12722  fn test_transform() {
12723    test(
12724      ".foo { transform: perspective(500px)translate3d(10px, 0, 20px)rotateY(30deg) }",
12725      indoc! {r#"
12726      .foo {
12727        transform: perspective(500px) translate3d(10px, 0, 20px) rotateY(30deg);
12728      }
12729      "#},
12730    );
12731    test(
12732      ".foo { transform: translate3d(12px,50%,3em)scale(2,.5) }",
12733      indoc! {r#"
12734      .foo {
12735        transform: translate3d(12px, 50%, 3em) scale(2, .5);
12736      }
12737      "#},
12738    );
12739    test(
12740      ".foo { transform:matrix(1,2,-1,1,80,80) }",
12741      indoc! {r#"
12742      .foo {
12743        transform: matrix(1, 2, -1, 1, 80, 80);
12744      }
12745      "#},
12746    );
12747
12748    minify_test(
12749      ".foo { transform: scale(  0.5 )translateX(10px ) }",
12750      ".foo{transform:scale(.5)translate(10px)}",
12751    );
12752    minify_test(
12753      ".foo { transform: translate(2px, 3px)",
12754      ".foo{transform:translate(2px,3px)}",
12755    );
12756    minify_test(
12757      ".foo { transform: translate(2px, 0px)",
12758      ".foo{transform:translate(2px)}",
12759    );
12760    minify_test(
12761      ".foo { transform: translate(0px, 2px)",
12762      ".foo{transform:translateY(2px)}",
12763    );
12764    minify_test(".foo { transform: translateX(2px)", ".foo{transform:translate(2px)}");
12765    minify_test(".foo { transform: translateY(2px)", ".foo{transform:translateY(2px)}");
12766    minify_test(".foo { transform: translateZ(2px)", ".foo{transform:translateZ(2px)}");
12767    minify_test(
12768      ".foo { transform: translate3d(2px, 3px, 4px)",
12769      ".foo{transform:translate3d(2px,3px,4px)}",
12770    );
12771    minify_test(
12772      ".foo { transform: translate3d(10%, 20%, 4px)",
12773      ".foo{transform:translate3d(10%,20%,4px)}",
12774    );
12775    minify_test(
12776      ".foo { transform: translate3d(2px, 0px, 0px)",
12777      ".foo{transform:translate(2px)}",
12778    );
12779    minify_test(
12780      ".foo { transform: translate3d(0px, 2px, 0px)",
12781      ".foo{transform:translateY(2px)}",
12782    );
12783    minify_test(
12784      ".foo { transform: translate3d(0px, 0px, 2px)",
12785      ".foo{transform:translateZ(2px)}",
12786    );
12787    minify_test(
12788      ".foo { transform: translate3d(2px, 3px, 0px)",
12789      ".foo{transform:translate(2px,3px)}",
12790    );
12791    minify_test(".foo { transform: scale(2, 3)", ".foo{transform:scale(2,3)}");
12792    minify_test(".foo { transform: scale(10%, 20%)", ".foo{transform:scale(.1,.2)}");
12793    minify_test(".foo { transform: scale(2, 2)", ".foo{transform:scale(2)}");
12794    minify_test(".foo { transform: scale(2, 1)", ".foo{transform:scaleX(2)}");
12795    minify_test(".foo { transform: scale(1, 2)", ".foo{transform:scaleY(2)}");
12796    minify_test(".foo { transform: scaleX(2)", ".foo{transform:scaleX(2)}");
12797    minify_test(".foo { transform: scaleY(2)", ".foo{transform:scaleY(2)}");
12798    minify_test(".foo { transform: scaleZ(2)", ".foo{transform:scaleZ(2)}");
12799    minify_test(".foo { transform: scale3d(2, 3, 4)", ".foo{transform:scale3d(2,3,4)}");
12800    minify_test(".foo { transform: scale3d(2, 1, 1)", ".foo{transform:scaleX(2)}");
12801    minify_test(".foo { transform: scale3d(1, 2, 1)", ".foo{transform:scaleY(2)}");
12802    minify_test(".foo { transform: scale3d(1, 1, 2)", ".foo{transform:scaleZ(2)}");
12803    minify_test(".foo { transform: scale3d(2, 2, 1)", ".foo{transform:scale(2)}");
12804
12805    // transform: scale(), Convert <percentage> to <number>
12806    test(
12807      ".foo { transform: scale3d(50%, 1, 200%) }",
12808      indoc! {r#"
12809      .foo {
12810        transform: scale3d(.5, 1, 2);
12811      }
12812      "#},
12813    );
12814    minify_test(".foo { transform: scale(1%) }", ".foo{transform:scale(.01)}");
12815    minify_test(".foo { transform: scale(0%) }", ".foo{transform:scale(0)}");
12816    minify_test(".foo { transform: scale(0.0%) }", ".foo{transform:scale(0)}");
12817    minify_test(".foo { transform: scale(-0%) }", ".foo{transform:scale(0)}");
12818    minify_test(".foo { transform: scale(-0) }", ".foo{transform:scale(0)}");
12819    minify_test(".foo { transform: scale(-0.0) }", ".foo{transform:scale(0)}");
12820    minify_test(".foo { transform: scale(100%) }", ".foo{transform:scale(1)}");
12821    minify_test(".foo { transform: scale(-100%) }", ".foo{transform:scale(-1)}");
12822    minify_test(".foo { transform: scale(68%) }", ".foo{transform:scale(.68)}");
12823    minify_test(".foo { transform: scale(5.96%) }", ".foo{transform:scale(.0596)}");
12824    // Match WPT coverage for repeated and multi-value percentages.
12825    minify_test(".foo { transform: scale(100%, 100%) }", ".foo{transform:scale(1)}");
12826    minify_test(".foo { transform: scale3d(100%, 100%, 1) }", ".foo{transform:scale(1)}");
12827    minify_test(".foo { transform: scale(-100%, -100%) }", ".foo{transform:scale(-1)}");
12828    minify_test(".foo { transform: scale3d(-100%, -100%, 1) }", ".foo{transform:scale(-1)}");
12829    minify_test(".foo { transform: scale(100%, 200%) }", ".foo{transform:scaleY(2)}");
12830    minify_test(".foo { transform: scale3d(100%, 200%, 1) }", ".foo{transform:scaleY(2)}");
12831    minify_test(".foo { transform: scale3d(100%, 100%, 0%) }", ".foo{transform:scaleZ(0)}");
12832    minify_test(".foo { transform: scale3d(100%, 100%, 100%) }", ".foo{transform:scale(1)}");
12833    minify_test(".foo { transform: scale3d(-0%, -0%, -0%) }", ".foo{transform:scale3d(0,0,0)}");
12834    // Additional edge cases: mixed inputs and computed percentages.
12835    minify_test(".foo { transform: scale(2, 100%) }", ".foo{transform:scaleX(2)}");
12836    minify_test(".foo { transform: scale(2, -50%) }", ".foo{transform:scale(2,-.5)}");
12837    minify_test(".foo { transform: scale(-90%, -1) }", ".foo{transform:scale(-.9,-1)}");
12838    minify_test(".foo { transform: scale(calc(10% + 20%)) }", ".foo{transform:scale(.3)}");
12839    minify_test(".foo { transform: scale(calc(150% - 50%), 200%) }", ".foo{transform:scaleY(2)}");
12840    minify_test(".foo { transform: scale(200%, calc(50% - 80%)) }", ".foo{transform:scale(2,-.3)}");
12841    // TODO: For infinite decimals, please do not attempt to resolve calc
12842    // Expected: calc(1 / 3)
12843    // https://github.com/parcel-bundler/lightningcss/issues/12
12844    minify_test(".foo { transform: scale(calc(100% / 3)) }", ".foo{transform:scale(.333333)}");
12845    // Transform::ScaleX/Y/Z
12846    minify_test(".foo { transform: scaleX(10%) }", ".foo{transform:scaleX(.1)}");
12847    minify_test(".foo { transform: scaleY(20%) }", ".foo{transform:scaleY(.2)}");
12848    minify_test(".foo { transform: scaleZ(30%) }", ".foo{transform:scaleZ(.3)}");
12849    minify_test(".foo { transform: scaleX(0%) }", ".foo{transform:scaleX(0)}");
12850    minify_test(".foo { transform: scaleX(-0%) }", ".foo{transform:scaleX(0)}");
12851    minify_test(".foo { transform: scaleX(calc(10% + 20%)) }", ".foo{transform:scaleX(.3)}");
12852    minify_test(".foo { transform: scaleX(calc(180% - 20%)) }", ".foo{transform:scaleX(1.6)}");
12853    minify_test(".foo { transform: scaleX(calc(50% - 80%)) }", ".foo{transform:scaleX(-.3)}");
12854
12855    minify_test(".foo { transform: rotate(20deg)", ".foo{transform:rotate(20deg)}");
12856    minify_test(".foo { transform: rotateX(20deg)", ".foo{transform:rotateX(20deg)}");
12857    minify_test(".foo { transform: rotateY(20deg)", ".foo{transform:rotateY(20deg)}");
12858    minify_test(".foo { transform: rotateZ(20deg)", ".foo{transform:rotate(20deg)}");
12859    minify_test(".foo { transform: rotate(360deg)", ".foo{transform:rotate(360deg)}");
12860    minify_test(
12861      ".foo { transform: rotate3d(2, 3, 4, 20deg)",
12862      ".foo{transform:rotate3d(2,3,4,20deg)}",
12863    );
12864    minify_test(
12865      ".foo { transform: rotate3d(1, 0, 0, 20deg)",
12866      ".foo{transform:rotateX(20deg)}",
12867    );
12868    minify_test(
12869      ".foo { transform: rotate3d(0, 1, 0, 20deg)",
12870      ".foo{transform:rotateY(20deg)}",
12871    );
12872    minify_test(
12873      ".foo { transform: rotate3d(0, 0, 1, 20deg)",
12874      ".foo{transform:rotate(20deg)}",
12875    );
12876    minify_test(".foo { transform: rotate(405deg)}", ".foo{transform:rotate(405deg)}");
12877    minify_test(".foo { transform: rotateX(405deg)}", ".foo{transform:rotateX(405deg)}");
12878    minify_test(".foo { transform: rotateY(405deg)}", ".foo{transform:rotateY(405deg)}");
12879    minify_test(".foo { transform: rotate(-200deg)}", ".foo{transform:rotate(-200deg)}");
12880    minify_test(".foo { transform: rotate(0)", ".foo{transform:rotate(0)}");
12881    minify_test(".foo { transform: rotate(0deg)", ".foo{transform:rotate(0)}");
12882    minify_test(
12883      ".foo { transform: rotateX(-200deg)}",
12884      ".foo{transform:rotateX(-200deg)}",
12885    );
12886    minify_test(
12887      ".foo { transform: rotateY(-200deg)}",
12888      ".foo{transform:rotateY(-200deg)}",
12889    );
12890    minify_test(
12891      ".foo { transform: rotate3d(1, 1, 0, -200deg)",
12892      ".foo{transform:rotate3d(1,1,0,-200deg)}",
12893    );
12894    minify_test(".foo { transform: skew(20deg)", ".foo{transform:skew(20deg)}");
12895    minify_test(".foo { transform: skew(20deg, 0deg)", ".foo{transform:skew(20deg)}");
12896    minify_test(".foo { transform: skew(0deg, 20deg)", ".foo{transform:skewY(20deg)}");
12897    minify_test(".foo { transform: skewX(20deg)", ".foo{transform:skew(20deg)}");
12898    minify_test(".foo { transform: skewY(20deg)", ".foo{transform:skewY(20deg)}");
12899    minify_test(
12900      ".foo { transform: perspective(10px)",
12901      ".foo{transform:perspective(10px)}",
12902    );
12903    minify_test(
12904      ".foo { transform: matrix(1, 2, -1, 1, 80, 80)",
12905      ".foo{transform:matrix(1,2,-1,1,80,80)}",
12906    );
12907    minify_test(
12908      ".foo { transform: matrix3d(1, 0, 0, 0, 0, 1, 6, 0, 0, 0, 1, 0, 50, 100, 0, 1.1)",
12909      ".foo{transform:matrix3d(1,0,0,0,0,1,6,0,0,0,1,0,50,100,0,1.1)}",
12910    );
12911    // TODO: Re-enable with a better solution
12912    //       See: https://github.com/parcel-bundler/lightningcss/issues/288
12913    // minify_test(
12914    //   ".foo{transform:translate(100px,200px) rotate(45deg) skew(10deg) scale(2)}",
12915    //   ".foo{transform:matrix(1.41421,1.41421,-1.16485,1.66358,100,200)}",
12916    // );
12917    // minify_test(
12918    //   ".foo{transform:translate(200px,300px) translate(100px,200px) scale(2)}",
12919    //   ".foo{transform:matrix(2,0,0,2,300,500)}",
12920    // );
12921    minify_test(
12922      ".foo{transform:translate(100px,200px) rotate(45deg)}",
12923      ".foo{transform:translate(100px,200px)rotate(45deg)}",
12924    );
12925    minify_test(
12926      ".foo{transform:rotate3d(1, 1, 1, 45deg) translate3d(100px, 100px, 10px)}",
12927      ".foo{transform:rotate3d(1,1,1,45deg)translate3d(100px,100px,10px)}",
12928    );
12929    // TODO: Re-enable with a better solution
12930    //       See: https://github.com/parcel-bundler/lightningcss/issues/288
12931    // minify_test(
12932    //   ".foo{transform:translate3d(100px, 100px, 10px) skew(10deg) scale3d(2, 3, 4)}",
12933    //   ".foo{transform:matrix3d(2,0,0,0,.528981,3,0,0,0,0,4,0,100,100,10,1)}",
12934    // );
12935    // minify_test(
12936    //   ".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)}",
12937    //   ".foo{transform:translate3d(100px,100px,10px)rotate3d(1,1,1,45deg)}"
12938    // );
12939    // minify_test(
12940    //   ".foo{transform:matrix3d(1, 0, 0, 0, 0, 0.7071067811865476, 0.7071067811865475, 0, 0, -0.7071067811865475, 0.7071067811865476, 0, 100, 100, 10, 1)}",
12941    //   ".foo{transform:translate3d(100px,100px,10px)rotateX(45deg)}"
12942    // );
12943    // minify_test(
12944    //   ".foo{transform:translate3d(100px, 200px, 10px) translate(100px, 100px)}",
12945    //   ".foo{transform:translate3d(200px,300px,10px)}",
12946    // );
12947    // minify_test(
12948    //   ".foo{transform:rotate(45deg) rotate(45deg)}",
12949    //   ".foo{transform:rotate(90deg)}",
12950    // );
12951    // minify_test(
12952    //   ".foo{transform:matrix(0.7071067811865476, 0.7071067811865475, -0.7071067811865475, 0.7071067811865476, 100, 100)}",
12953    //   ".foo{transform:translate(100px,100px)rotate(45deg)}"
12954    // );
12955    // minify_test(
12956    //   ".foo{transform:translateX(2in) translateX(50px)}",
12957    //   ".foo{transform:translate(242px)}",
12958    // );
12959    minify_test(
12960      ".foo{transform:translateX(calc(2in + 50px))}",
12961      ".foo{transform:translate(242px)}",
12962    );
12963    minify_test(".foo{transform:translateX(50%)}", ".foo{transform:translate(50%)}");
12964    minify_test(
12965      ".foo{transform:translateX(calc(50% - 100px + 20px))}",
12966      ".foo{transform:translate(calc(50% - 80px))}",
12967    );
12968    minify_test(
12969      ".foo{transform:rotate(calc(10deg + 20deg))}",
12970      ".foo{transform:rotate(30deg)}",
12971    );
12972    minify_test(
12973      ".foo{transform:rotate(calc(10deg + 0.349066rad))}",
12974      ".foo{transform:rotate(30deg)}",
12975    );
12976    minify_test(
12977      ".foo{transform:rotate(calc(10deg + 1.5turn))}",
12978      ".foo{transform:rotate(550deg)}",
12979    );
12980    minify_test(
12981      ".foo{transform:rotate(calc(10deg * 2))}",
12982      ".foo{transform:rotate(20deg)}",
12983    );
12984    minify_test(
12985      ".foo{transform:rotate(calc(-10deg * 2))}",
12986      ".foo{transform:rotate(-20deg)}",
12987    );
12988    minify_test(
12989      ".foo{transform:rotate(calc(10deg + var(--test)))}",
12990      ".foo{transform:rotate(calc(10deg + var(--test)))}",
12991    );
12992    minify_test(".foo { transform: scale(calc(.1 + .2))", ".foo{transform:scale(.3)}");
12993
12994    minify_test(
12995      ".foo { -webkit-transform: scale(calc(10% + 20%))",
12996      ".foo{-webkit-transform:scale(.3)}",
12997    );
12998
12999    minify_test(".foo { translate: 1px 2px 3px }", ".foo{translate:1px 2px 3px}");
13000    minify_test(".foo { translate: 1px 0px 0px }", ".foo{translate:1px}");
13001    minify_test(".foo { translate: 1px 2px 0px }", ".foo{translate:1px 2px}");
13002    minify_test(".foo { translate: 1px 0px 2px }", ".foo{translate:1px 0 2px}");
13003    minify_test(".foo { translate: none }", ".foo{translate:none}");
13004    minify_test(".foo { rotate: none }", ".foo{rotate:none}");
13005    minify_test(".foo { rotate: 0deg }", ".foo{rotate:0deg}");
13006    minify_test(".foo { rotate: -0deg }", ".foo{rotate:0deg}");
13007    minify_test(".foo { rotate: 10deg }", ".foo{rotate:10deg}");
13008    minify_test(".foo { rotate: z 10deg }", ".foo{rotate:10deg}");
13009    minify_test(".foo { rotate: 0 0 1 10deg }", ".foo{rotate:10deg}");
13010    minify_test(".foo { rotate: x 10deg }", ".foo{rotate:x 10deg}");
13011    minify_test(".foo { rotate: 1 0 0 10deg }", ".foo{rotate:x 10deg}");
13012    minify_test(".foo { rotate: 2 0 0 10deg }", ".foo{rotate:x 10deg}");
13013    minify_test(".foo { rotate: 0 2 0 10deg }", ".foo{rotate:y 10deg}");
13014    minify_test(".foo { rotate: 0 0 2 10deg }", ".foo{rotate:10deg}");
13015    minify_test(".foo { rotate: 0 0 5.3 10deg }", ".foo{rotate:10deg}");
13016    minify_test(".foo { rotate: 0 0 1 0deg }", ".foo{rotate:0deg}");
13017    minify_test(".foo { rotate: 10deg 0 0 -1 }", ".foo{rotate:-10deg}");
13018    minify_test(".foo { rotate: 10deg 0 0 -233 }", ".foo{rotate:-10deg}");
13019    minify_test(".foo { rotate: -1 0 0 0deg }", ".foo{rotate:x 0deg}");
13020    minify_test(".foo { rotate: 0deg 0 0 1 }", ".foo{rotate:0deg}");
13021    minify_test(".foo { rotate: 0deg 0 0 -1 }", ".foo{rotate:0deg}");
13022    minify_test(".foo { rotate: 0 1 0 10deg }", ".foo{rotate:y 10deg}");
13023    minify_test(".foo { rotate: x 0rad }", ".foo{rotate:x 0deg}");
13024    // TODO: In minify mode, convert units to the shortest form.
13025    // minify_test(".foo { rotate: y 0turn }", ".foo{rotate:y 0deg}");
13026    minify_test(".foo { rotate: z 0deg }", ".foo{rotate:0deg}");
13027    minify_test(".foo { rotate: 10deg y }", ".foo{rotate:y 10deg}");
13028    minify_test(".foo { rotate: 1 1 1 10deg }", ".foo{rotate:1 1 1 10deg}");
13029    minify_test(".foo { scale: 1 }", ".foo{scale:1}");
13030    minify_test(".foo { scale: 1 1 }", ".foo{scale:1}");
13031    minify_test(".foo { scale: 1 1 1 }", ".foo{scale:1}");
13032    minify_test(".foo { scale: none }", ".foo{scale:none}");
13033    minify_test(".foo { scale: 1 0 }", ".foo{scale:1 0}");
13034    minify_test(".foo { scale: 1 0 1 }", ".foo{scale:1 0}");
13035    minify_test(".foo { scale: 1 0 0 }", ".foo{scale:1 0 0}");
13036
13037    // scale, Convert <percentage> to <number>
13038    test(
13039      ".foo { scale: 50% 1 200% }",
13040      indoc! {r#"
13041      .foo {
13042        scale: .5 1 2;
13043      }
13044      "#},
13045    );
13046    minify_test(".foo { scale: 1% }", ".foo{scale:.01}");
13047    minify_test(".foo { scale: 0% }", ".foo{scale:0}");
13048    minify_test(".foo { scale: 0.0% }", ".foo{scale:0}");
13049    minify_test(".foo { scale: -0% }", ".foo{scale:0}");
13050    minify_test(".foo { scale: -0 }", ".foo{scale:0}");
13051    minify_test(".foo { scale: -0.0 }", ".foo{scale:0}");
13052    minify_test(".foo { scale: 100% }", ".foo{scale:1}");
13053    minify_test(".foo { scale: -100% }", ".foo{scale:-1}");
13054    minify_test(".foo { scale: 68% }", ".foo{scale:.68}");
13055    minify_test(".foo { scale: 5.96% }", ".foo{scale:.0596}");
13056    // Match WPT coverage for repeated and multi-value percentages.
13057    minify_test(".foo { scale: 100% 100% }", ".foo{scale:1}");
13058    minify_test(".foo { scale: 100% 100% 1 }", ".foo{scale:1}");
13059    minify_test(".foo { scale: -100% -100% }", ".foo{scale:-1}");
13060    minify_test(".foo { scale: -100% -100% 1 }", ".foo{scale:-1}");
13061    minify_test(".foo { scale: 100% 200% }", ".foo{scale:1 2}");
13062    minify_test(".foo { scale: 100% 200% 1 }", ".foo{scale:1 2}");
13063    minify_test(".foo { scale: 100% 100% 0% }", ".foo{scale:1 1 0}");
13064    minify_test(".foo { scale: 100% 100% 100% }", ".foo{scale:1}");
13065    minify_test(".foo { scale: -0% -0% -0% }", ".foo{scale:0 0 0}");
13066    // Additional edge cases: mixed inputs and computed percentages.
13067    minify_test(".foo { scale: 2 100% }", ".foo{scale:2 1}");
13068    minify_test(".foo { scale: 2 -50% }", ".foo{scale:2 -.5}");
13069    minify_test(".foo { scale: -90% -1 }", ".foo{scale:-.9 -1}");
13070    minify_test(".foo { scale: calc(10% + 20%) }", ".foo{scale:.3}");
13071    minify_test(".foo { scale: calc(150% - 50%) 200% }", ".foo{scale:1 2}");
13072    minify_test(".foo { scale: 200% calc(50% - 80%) }", ".foo{scale:2 -.3}");
13073    // TODO: For infinite decimals, please do not attempt to resolve calc
13074    // Expected: calc(1 / 3)
13075    // https://github.com/parcel-bundler/lightningcss/issues/12
13076    minify_test(".foo { scale: calc(100% / 3) }", ".foo{scale:.333333}");
13077
13078    assert_eq!(
13079      Property::Scale(crate::properties::transform::Scale::XYZ {
13080        x: crate::values::percentage::NumberOrPercentage::Percentage(crate::values::percentage::Percentage(0.5)),
13081        y: crate::values::percentage::NumberOrPercentage::Percentage(crate::values::percentage::Percentage(2.0)),
13082        z: crate::values::percentage::NumberOrPercentage::Percentage(crate::values::percentage::Percentage(1.0)),
13083      })
13084      .to_css_string(
13085        false,
13086        PrinterOptions {
13087          minify: true,
13088          ..PrinterOptions::default()
13089        },
13090      )
13091      .unwrap(),
13092      "scale:.5 2"
13093    );
13094    assert_eq!(
13095      Property::Transform(
13096        crate::properties::transform::TransformList(vec![crate::properties::transform::Transform::ScaleX(
13097          crate::values::percentage::NumberOrPercentage::Percentage(crate::values::percentage::Percentage(0.1)),
13098        )]),
13099        VendorPrefix::None,
13100      )
13101      .to_css_string(
13102        false,
13103        PrinterOptions {
13104          minify: true,
13105          ..PrinterOptions::default()
13106        },
13107      )
13108      .unwrap(),
13109      "transform:scaleX(.1)"
13110    );
13111
13112    // TODO: Re-enable with a better solution
13113    //       See: https://github.com/parcel-bundler/lightningcss/issues/288
13114    // minify_test(".foo { transform: scale(3); scale: 0.5 }", ".foo{transform:scale(1.5)}");
13115    minify_test(".foo { scale: 0.5; transform: scale(3); }", ".foo{transform:scale(3)}");
13116
13117    prefix_test(
13118      r#"
13119      .foo {
13120        transform: scale(0.5);
13121      }
13122    "#,
13123      indoc! {r#"
13124      .foo {
13125        -webkit-transform: scale(.5);
13126        -moz-transform: scale(.5);
13127        transform: scale(.5);
13128      }
13129    "#},
13130      Browsers {
13131        firefox: Some(6 << 16),
13132        safari: Some(6 << 16),
13133        ..Browsers::default()
13134      },
13135    );
13136
13137    prefix_test(
13138      r#"
13139      .foo {
13140        transform: var(--transform);
13141      }
13142    "#,
13143      indoc! {r#"
13144      .foo {
13145        -webkit-transform: var(--transform);
13146        -moz-transform: var(--transform);
13147        transform: var(--transform);
13148      }
13149    "#},
13150      Browsers {
13151        firefox: Some(6 << 16),
13152        safari: Some(6 << 16),
13153        ..Browsers::default()
13154      },
13155    );
13156
13157    test(
13158      r#"
13159      .foo {
13160        transform: translateX(-50%);
13161        transform: translateX(20px);
13162      }
13163      "#,
13164      indoc! {r#"
13165      .foo {
13166        transform: translateX(20px);
13167      }
13168      "#},
13169    );
13170  }
13171
13172  #[test]
13173  pub fn test_gradients() {
13174    minify_test(
13175      ".foo { background: linear-gradient(yellow, blue) }",
13176      ".foo{background:linear-gradient(#ff0,#00f)}",
13177    );
13178    minify_test(
13179      ".foo { background: linear-gradient(to bottom, yellow, blue); }",
13180      ".foo{background:linear-gradient(#ff0,#00f)}",
13181    );
13182    minify_test(
13183      ".foo { background: linear-gradient(180deg, yellow, blue); }",
13184      ".foo{background:linear-gradient(#ff0,#00f)}",
13185    );
13186    minify_test(
13187      ".foo { background: linear-gradient(0.5turn, yellow, blue); }",
13188      ".foo{background:linear-gradient(#ff0,#00f)}",
13189    );
13190    minify_test(
13191      ".foo { background: linear-gradient(yellow 10%, blue 20%) }",
13192      ".foo{background:linear-gradient(#ff0 10%,#00f 20%)}",
13193    );
13194    minify_test(
13195      ".foo { background: linear-gradient(to top, blue, yellow); }",
13196      ".foo{background:linear-gradient(#ff0,#00f)}",
13197    );
13198    minify_test(
13199      ".foo { background: linear-gradient(to top, blue 10%, yellow 20%); }",
13200      ".foo{background:linear-gradient(#ff0 80%,#00f 90%)}",
13201    );
13202    minify_test(
13203      ".foo { background: linear-gradient(to top, blue 10px, yellow 20px); }",
13204      ".foo{background:linear-gradient(0deg,#00f 10px,#ff0 20px)}",
13205    );
13206    minify_test(
13207      ".foo { background: linear-gradient(135deg, yellow, blue); }",
13208      ".foo{background:linear-gradient(135deg,#ff0,#00f)}",
13209    );
13210    minify_test(
13211      ".foo { background: linear-gradient(yellow, blue 20%, #0f0); }",
13212      ".foo{background:linear-gradient(#ff0,#00f 20%,#0f0)}",
13213    );
13214    minify_test(
13215      ".foo { background: linear-gradient(to top right, red, white, blue) }",
13216      ".foo{background:linear-gradient(to top right,red,#fff,#00f)}",
13217    );
13218    minify_test(
13219      ".foo { background: linear-gradient(yellow, blue calc(10% * 2), #0f0); }",
13220      ".foo{background:linear-gradient(#ff0,#00f 20%,#0f0)}",
13221    );
13222    minify_test(
13223      ".foo { background: linear-gradient(yellow, 20%, blue); }",
13224      ".foo{background:linear-gradient(#ff0,20%,#00f)}",
13225    );
13226    minify_test(
13227      ".foo { background: linear-gradient(yellow, 50%, blue); }",
13228      ".foo{background:linear-gradient(#ff0,#00f)}",
13229    );
13230    minify_test(
13231      ".foo { background: linear-gradient(yellow, 20px, blue); }",
13232      ".foo{background:linear-gradient(#ff0,20px,#00f)}",
13233    );
13234    minify_test(
13235      ".foo { background: linear-gradient(yellow, 50px, blue); }",
13236      ".foo{background:linear-gradient(#ff0,50px,#00f)}",
13237    );
13238    minify_test(
13239      ".foo { background: linear-gradient(yellow, 50px, blue); }",
13240      ".foo{background:linear-gradient(#ff0,50px,#00f)}",
13241    );
13242    minify_test(
13243      ".foo { background: linear-gradient(yellow, red 30% 40%, blue); }",
13244      ".foo{background:linear-gradient(#ff0,red 30% 40%,#00f)}",
13245    );
13246    minify_test(
13247      ".foo { background: linear-gradient(yellow, red 30%, red 40%, blue); }",
13248      ".foo{background:linear-gradient(#ff0,red 30% 40%,#00f)}",
13249    );
13250    minify_test(
13251      ".foo { background: linear-gradient(0, yellow, blue); }",
13252      ".foo{background:linear-gradient(#00f,#ff0)}",
13253    );
13254    minify_test(
13255      ".foo { background: -webkit-linear-gradient(yellow, blue) }",
13256      ".foo{background:-webkit-linear-gradient(#ff0,#00f)}",
13257    );
13258    minify_test(
13259      ".foo { background: -webkit-linear-gradient(bottom, yellow, blue); }",
13260      ".foo{background:-webkit-linear-gradient(#ff0,#00f)}",
13261    );
13262    minify_test(
13263      ".foo { background: -webkit-linear-gradient(top right, red, white, blue) }",
13264      ".foo{background:-webkit-linear-gradient(top right,red,#fff,#00f)}",
13265    );
13266    minify_test(
13267      ".foo { background: -moz-linear-gradient(yellow, blue) }",
13268      ".foo{background:-moz-linear-gradient(#ff0,#00f)}",
13269    );
13270    minify_test(
13271      ".foo { background: -moz-linear-gradient(bottom, yellow, blue); }",
13272      ".foo{background:-moz-linear-gradient(#ff0,#00f)}",
13273    );
13274    minify_test(
13275      ".foo { background: -moz-linear-gradient(top right, red, white, blue) }",
13276      ".foo{background:-moz-linear-gradient(top right,red,#fff,#00f)}",
13277    );
13278    minify_test(
13279      ".foo { background: -o-linear-gradient(yellow, blue) }",
13280      ".foo{background:-o-linear-gradient(#ff0,#00f)}",
13281    );
13282    minify_test(
13283      ".foo { background: -o-linear-gradient(bottom, yellow, blue); }",
13284      ".foo{background:-o-linear-gradient(#ff0,#00f)}",
13285    );
13286    minify_test(
13287      ".foo { background: -o-linear-gradient(top right, red, white, blue) }",
13288      ".foo{background:-o-linear-gradient(top right,red,#fff,#00f)}",
13289    );
13290    minify_test(
13291      ".foo { background: -webkit-gradient(linear, left top, left bottom, from(blue), to(yellow)) }",
13292      ".foo{background:-webkit-gradient(linear,0 0,0 100%,from(#00f),to(#ff0))}",
13293    );
13294    minify_test(
13295      ".foo { background: -webkit-gradient(linear, left top, left bottom, from(blue), color-stop(50%, red), to(yellow)) }",
13296      ".foo{background:-webkit-gradient(linear,0 0,0 100%,from(#00f),color-stop(.5,red),to(#ff0))}"
13297    );
13298    minify_test(
13299      ".foo { background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, blue), color-stop(50%, red), color-stop(100%, yellow)) }",
13300      ".foo{background:-webkit-gradient(linear,0 0,0 100%,from(#00f),color-stop(.5,red),to(#ff0))}"
13301    );
13302    minify_test(
13303      ".foo { background: repeating-linear-gradient(yellow 10px, blue 50px) }",
13304      ".foo{background:repeating-linear-gradient(#ff0 10px,#00f 50px)}",
13305    );
13306    minify_test(
13307      ".foo { background: -webkit-repeating-linear-gradient(yellow 10px, blue 50px) }",
13308      ".foo{background:-webkit-repeating-linear-gradient(#ff0 10px,#00f 50px)}",
13309    );
13310    minify_test(
13311      ".foo { background: -moz-repeating-linear-gradient(yellow 10px, blue 50px) }",
13312      ".foo{background:-moz-repeating-linear-gradient(#ff0 10px,#00f 50px)}",
13313    );
13314    minify_test(
13315      ".foo { background: -o-repeating-linear-gradient(yellow 10px, blue 50px) }",
13316      ".foo{background:-o-repeating-linear-gradient(#ff0 10px,#00f 50px)}",
13317    );
13318    minify_test(
13319      ".foo { background: radial-gradient(yellow, blue) }",
13320      ".foo{background:radial-gradient(#ff0,#00f)}",
13321    );
13322    minify_test(
13323      ".foo { background: radial-gradient(at top left, yellow, blue) }",
13324      ".foo{background:radial-gradient(at 0 0,#ff0,#00f)}",
13325    );
13326    minify_test(
13327      ".foo { background: radial-gradient(5em circle at top left, yellow, blue) }",
13328      ".foo{background:radial-gradient(5em at 0 0,#ff0,#00f)}",
13329    );
13330    minify_test(
13331      ".foo { background: radial-gradient(circle at 100%, #333, #333 50%, #eee 75%, #333 75%) }",
13332      ".foo{background:radial-gradient(circle at 100%,#333,#333 50%,#eee 75%,#333 75%)}",
13333    );
13334    minify_test(
13335      ".foo { background: radial-gradient(farthest-corner circle at 100% 50%, #333, #333 50%, #eee 75%, #333 75%) }",
13336      ".foo{background:radial-gradient(circle at 100%,#333,#333 50%,#eee 75%,#333 75%)}"
13337    );
13338    minify_test(
13339      ".foo { background: radial-gradient(farthest-corner circle at 50% 50%, #333, #333 50%, #eee 75%, #333 75%) }",
13340      ".foo{background:radial-gradient(circle,#333,#333 50%,#eee 75%,#333 75%)}"
13341    );
13342    minify_test(
13343      ".foo { background: radial-gradient(ellipse at top, #e66465, transparent) }",
13344      ".foo{background:radial-gradient(at top,#e66465,#0000)}",
13345    );
13346    minify_test(
13347      ".foo { background: radial-gradient(20px, yellow, blue) }",
13348      ".foo{background:radial-gradient(20px,#ff0,#00f)}",
13349    );
13350    minify_test(
13351      ".foo { background: radial-gradient(circle 20px, yellow, blue) }",
13352      ".foo{background:radial-gradient(20px,#ff0,#00f)}",
13353    );
13354    minify_test(
13355      ".foo { background: radial-gradient(20px 40px, yellow, blue) }",
13356      ".foo{background:radial-gradient(20px 40px,#ff0,#00f)}",
13357    );
13358    minify_test(
13359      ".foo { background: radial-gradient(ellipse 20px 40px, yellow, blue) }",
13360      ".foo{background:radial-gradient(20px 40px,#ff0,#00f)}",
13361    );
13362    minify_test(
13363      ".foo { background: radial-gradient(ellipse calc(20px + 10px) 40px, yellow, blue) }",
13364      ".foo{background:radial-gradient(30px 40px,#ff0,#00f)}",
13365    );
13366    minify_test(
13367      ".foo { background: radial-gradient(circle farthest-side, yellow, blue) }",
13368      ".foo{background:radial-gradient(circle farthest-side,#ff0,#00f)}",
13369    );
13370    minify_test(
13371      ".foo { background: radial-gradient(farthest-side circle, yellow, blue) }",
13372      ".foo{background:radial-gradient(circle farthest-side,#ff0,#00f)}",
13373    );
13374    minify_test(
13375      ".foo { background: radial-gradient(ellipse farthest-side, yellow, blue) }",
13376      ".foo{background:radial-gradient(farthest-side,#ff0,#00f)}",
13377    );
13378    minify_test(
13379      ".foo { background: radial-gradient(farthest-side ellipse, yellow, blue) }",
13380      ".foo{background:radial-gradient(farthest-side,#ff0,#00f)}",
13381    );
13382    minify_test(
13383      ".foo { background: -webkit-radial-gradient(yellow, blue) }",
13384      ".foo{background:-webkit-radial-gradient(#ff0,#00f)}",
13385    );
13386    minify_test(
13387      ".foo { background: -moz-radial-gradient(yellow, blue) }",
13388      ".foo{background:-moz-radial-gradient(#ff0,#00f)}",
13389    );
13390    minify_test(
13391      ".foo { background: -o-radial-gradient(yellow, blue) }",
13392      ".foo{background:-o-radial-gradient(#ff0,#00f)}",
13393    );
13394    minify_test(
13395      ".foo { background: repeating-radial-gradient(circle 20px, yellow, blue) }",
13396      ".foo{background:repeating-radial-gradient(20px,#ff0,#00f)}",
13397    );
13398    minify_test(
13399      ".foo { background: -webkit-repeating-radial-gradient(circle 20px, yellow, blue) }",
13400      ".foo{background:-webkit-repeating-radial-gradient(20px,#ff0,#00f)}",
13401    );
13402    minify_test(
13403      ".foo { background: -moz-repeating-radial-gradient(circle 20px, yellow, blue) }",
13404      ".foo{background:-moz-repeating-radial-gradient(20px,#ff0,#00f)}",
13405    );
13406    minify_test(
13407      ".foo { background: -o-repeating-radial-gradient(circle 20px, yellow, blue) }",
13408      ".foo{background:-o-repeating-radial-gradient(20px,#ff0,#00f)}",
13409    );
13410    minify_test(
13411      ".foo { background: -webkit-gradient(radial, center center, 0, center center, 100, from(blue), to(yellow)) }",
13412      ".foo{background:-webkit-gradient(radial,50% 50%,0,50% 50%,100,from(#00f),to(#ff0))}"
13413    );
13414    minify_test(
13415      ".foo { background: conic-gradient(#f06, gold) }",
13416      ".foo{background:conic-gradient(#f06,gold)}",
13417    );
13418    minify_test(
13419      ".foo { background: conic-gradient(at 50% 50%, #f06, gold) }",
13420      ".foo{background:conic-gradient(#f06,gold)}",
13421    );
13422    minify_test(
13423      ".foo { background: conic-gradient(from 0deg, #f06, gold) }",
13424      ".foo{background:conic-gradient(#f06,gold)}",
13425    );
13426    minify_test(
13427      ".foo { background: conic-gradient(from 0, #f06, gold) }",
13428      ".foo{background:conic-gradient(#f06,gold)}",
13429    );
13430    minify_test(
13431      ".foo { background: conic-gradient(from 0deg at center, #f06, gold) }",
13432      ".foo{background:conic-gradient(#f06,gold)}",
13433    );
13434    minify_test(
13435      ".foo { background: conic-gradient(white -50%, black 150%) }",
13436      ".foo{background:conic-gradient(#fff -50%,#000 150%)}",
13437    );
13438    minify_test(
13439      ".foo { background: conic-gradient(white -180deg, black 540deg) }",
13440      ".foo{background:conic-gradient(#fff -180deg,#000 540deg)}",
13441    );
13442    minify_test(
13443      ".foo { background: conic-gradient(from 45deg, white, black, white) }",
13444      ".foo{background:conic-gradient(from 45deg,#fff,#000,#fff)}",
13445    );
13446    minify_test(
13447      ".foo { background: repeating-conic-gradient(from 45deg, white, black, white) }",
13448      ".foo{background:repeating-conic-gradient(from 45deg,#fff,#000,#fff)}",
13449    );
13450    minify_test(
13451      ".foo { background: repeating-conic-gradient(black 0deg 25%, white 0deg 50%) }",
13452      ".foo{background:repeating-conic-gradient(#000 0deg 25%,#fff 0deg 50%)}",
13453    );
13454
13455    test(
13456      r#"
13457        .foo {
13458          background: -webkit-gradient(linear, left top, left bottom, from(red), to(blue));
13459          background: -webkit-linear-gradient(red, blue);
13460          background: -moz-linear-gradient(red, blue);
13461          background: -o-linear-gradient(red, blue);
13462          background: linear-gradient(red, blue);
13463        }
13464      "#,
13465      indoc! {r#"
13466        .foo {
13467          background: -webkit-gradient(linear, left top, left bottom, from(red), to(#00f));
13468          background: -webkit-linear-gradient(red, #00f);
13469          background: -moz-linear-gradient(red, #00f);
13470          background: -o-linear-gradient(red, #00f);
13471          background: linear-gradient(red, #00f);
13472        }
13473      "#},
13474    );
13475
13476    prefix_test(
13477      r#"
13478      .foo {
13479        background: -webkit-gradient(linear, left top, left bottom, from(red), to(blue));
13480        background: -webkit-linear-gradient(red, blue);
13481        background: -moz-linear-gradient(red, blue);
13482        background: -o-linear-gradient(red, blue);
13483        background: linear-gradient(red, blue);
13484      }
13485      "#,
13486      indoc! {r#"
13487      .foo {
13488        background: linear-gradient(red, #00f);
13489      }
13490      "#},
13491      Browsers {
13492        chrome: Some(95 << 16),
13493        ..Browsers::default()
13494      },
13495    );
13496    prefix_test(
13497      r#"
13498      .foo {
13499        background: -webkit-gradient(linear, left top, left bottom, from(red), to(blue));
13500        background: -webkit-linear-gradient(red, blue);
13501        background: -moz-linear-gradient(red, blue);
13502        background: -o-linear-gradient(red, blue);
13503      }
13504      "#,
13505      indoc! {r#"
13506      .foo {
13507        background: -webkit-gradient(linear, left top, left bottom, from(red), to(#00f));
13508        background: -webkit-linear-gradient(red, #00f);
13509        background: -moz-linear-gradient(red, #00f);
13510        background: -o-linear-gradient(red, #00f);
13511      }
13512      "#},
13513      Browsers {
13514        chrome: Some(95 << 16),
13515        ..Browsers::default()
13516      },
13517    );
13518    prefix_test(
13519      r#"
13520      .foo {
13521        background-image: linear-gradient(red, blue);
13522      }
13523      "#,
13524      indoc! {r#"
13525      .foo {
13526        background-image: -webkit-gradient(linear, 0 0, 0 100%, from(red), to(#00f));
13527        background-image: -webkit-linear-gradient(top, red, #00f);
13528        background-image: linear-gradient(red, #00f);
13529      }
13530      "#},
13531      Browsers {
13532        chrome: Some(8 << 16),
13533        ..Browsers::default()
13534      },
13535    );
13536    prefix_test(
13537      r#"
13538      .foo {
13539        background-image: linear-gradient(to right, red, blue);
13540      }
13541      "#,
13542      indoc! {r#"
13543      .foo {
13544        background-image: -webkit-gradient(linear, 0 0, 100% 0, from(red), to(#00f));
13545        background-image: -webkit-linear-gradient(left, red, #00f);
13546        background-image: linear-gradient(to right, red, #00f);
13547      }
13548      "#},
13549      Browsers {
13550        chrome: Some(8 << 16),
13551        ..Browsers::default()
13552      },
13553    );
13554    prefix_test(
13555      r#"
13556      .foo {
13557        background-image: linear-gradient(to top, red, blue);
13558      }
13559      "#,
13560      indoc! {r#"
13561      .foo {
13562        background-image: -webkit-gradient(linear, 0 100%, 0 0, from(red), to(#00f));
13563        background-image: -webkit-linear-gradient(red, #00f);
13564        background-image: linear-gradient(to top, red, #00f);
13565      }
13566      "#},
13567      Browsers {
13568        chrome: Some(8 << 16),
13569        ..Browsers::default()
13570      },
13571    );
13572    prefix_test(
13573      r#"
13574      .foo {
13575        background-image: linear-gradient(to left, red, blue);
13576      }
13577      "#,
13578      indoc! {r#"
13579      .foo {
13580        background-image: -webkit-gradient(linear, 100% 0, 0 0, from(red), to(#00f));
13581        background-image: -webkit-linear-gradient(right, red, #00f);
13582        background-image: linear-gradient(to left, red, #00f);
13583      }
13584      "#},
13585      Browsers {
13586        chrome: Some(8 << 16),
13587        ..Browsers::default()
13588      },
13589    );
13590    prefix_test(
13591      r#"
13592      .foo {
13593        background-image: linear-gradient(to left bottom, red, blue);
13594      }
13595      "#,
13596      indoc! {r#"
13597      .foo {
13598        background-image: -webkit-gradient(linear, 100% 0, 0 100%, from(red), to(#00f));
13599        background-image: -webkit-linear-gradient(top right, red, #00f);
13600        background-image: linear-gradient(to bottom left, red, #00f);
13601      }
13602      "#},
13603      Browsers {
13604        chrome: Some(8 << 16),
13605        ..Browsers::default()
13606      },
13607    );
13608    prefix_test(
13609      r#"
13610      .foo {
13611        background-image: linear-gradient(to top right, red, blue);
13612      }
13613      "#,
13614      indoc! {r#"
13615      .foo {
13616        background-image: -webkit-gradient(linear, 0 100%, 100% 0, from(red), to(#00f));
13617        background-image: -webkit-linear-gradient(bottom left, red, #00f);
13618        background-image: linear-gradient(to top right, red, #00f);
13619      }
13620      "#},
13621      Browsers {
13622        chrome: Some(8 << 16),
13623        ..Browsers::default()
13624      },
13625    );
13626    prefix_test(
13627      r#"
13628      .foo {
13629        background-image: linear-gradient(90deg, red, blue);
13630      }
13631      "#,
13632      indoc! {r#"
13633      .foo {
13634        background-image: -webkit-gradient(linear, 0 0, 100% 0, from(red), to(#00f));
13635        background-image: -webkit-linear-gradient(0deg, red, #00f);
13636        background-image: linear-gradient(90deg, red, #00f);
13637      }
13638      "#},
13639      Browsers {
13640        chrome: Some(8 << 16),
13641        ..Browsers::default()
13642      },
13643    );
13644    prefix_test(
13645      r#"
13646      .foo {
13647        background-image: linear-gradient(45deg, red, blue);
13648      }
13649      "#,
13650      indoc! {r#"
13651      .foo {
13652        background-image: -webkit-linear-gradient(45deg, red, #00f);
13653        background-image: linear-gradient(45deg, red, #00f);
13654      }
13655      "#},
13656      Browsers {
13657        chrome: Some(8 << 16),
13658        ..Browsers::default()
13659      },
13660    );
13661    prefix_test(
13662      r#"
13663      .foo {
13664        background-image: linear-gradient(red, blue);
13665      }
13666      "#,
13667      indoc! {r#"
13668      .foo {
13669        background-image: -webkit-linear-gradient(top, red, #00f);
13670        background-image: linear-gradient(red, #00f);
13671      }
13672      "#},
13673      Browsers {
13674        chrome: Some(10 << 16),
13675        ..Browsers::default()
13676      },
13677    );
13678    prefix_test(
13679      r#"
13680      .foo {
13681        background-image: radial-gradient(20px, red, blue);
13682      }
13683      "#,
13684      indoc! {r#"
13685      .foo {
13686        background-image: -webkit-gradient(radial, center center, 0, center center, 20, from(red), to(#00f));
13687        background-image: -webkit-radial-gradient(20px, red, #00f);
13688        background-image: radial-gradient(20px, red, #00f);
13689      }
13690      "#},
13691      Browsers {
13692        chrome: Some(8 << 16),
13693        ..Browsers::default()
13694      },
13695    );
13696    prefix_test(
13697      r#"
13698      .foo {
13699        background-image: radial-gradient(20px at top left, red, blue);
13700      }
13701      "#,
13702      indoc! {r#"
13703      .foo {
13704        background-image: -webkit-gradient(radial, left top, 0, left top, 20, from(red), to(#00f));
13705        background-image: -webkit-radial-gradient(20px at 0 0, red, #00f);
13706        background-image: radial-gradient(20px at 0 0, red, #00f);
13707      }
13708      "#},
13709      Browsers {
13710        chrome: Some(8 << 16),
13711        ..Browsers::default()
13712      },
13713    );
13714    prefix_test(
13715      r#"
13716      .foo {
13717        background-image: radial-gradient(red, blue);
13718      }
13719      "#,
13720      indoc! {r#"
13721      .foo {
13722        background-image: -webkit-radial-gradient(red, #00f);
13723        background-image: radial-gradient(red, #00f);
13724      }
13725      "#},
13726      Browsers {
13727        chrome: Some(8 << 16),
13728        ..Browsers::default()
13729      },
13730    );
13731    prefix_test(
13732      r#"
13733      .foo {
13734        background-image: -webkit-gradient(radial, left top, 0, left top, 20, from(red), to(#00f));
13735        background-image: -webkit-radial-gradient(20px at 0% 0%, red, #00f);
13736        background-image: radial-gradient(20px at 0% 0%, red, #00f);
13737      }
13738      "#,
13739      indoc! {r#"
13740      .foo {
13741        background-image: radial-gradient(20px at 0 0, red, #00f);
13742      }
13743      "#},
13744      Browsers {
13745        chrome: Some(30 << 16),
13746        ..Browsers::default()
13747      },
13748    );
13749    prefix_test(
13750      r#"
13751      .foo {
13752        background: -webkit-gradient(radial, left top, 0, left top, 20, from(red), to(#00f));
13753        background: -webkit-radial-gradient(20px at 0% 0%, red, #00f);
13754        background: radial-gradient(20px at 0% 0%, red, #00f);
13755      }
13756      "#,
13757      indoc! {r#"
13758      .foo {
13759        background: radial-gradient(20px at 0 0, red, #00f);
13760      }
13761      "#},
13762      Browsers {
13763        chrome: Some(30 << 16),
13764        ..Browsers::default()
13765      },
13766    );
13767    prefix_test(
13768      r#"
13769      .foo {
13770        background: radial-gradient(red, blue);
13771      }
13772      "#,
13773      indoc! {r#"
13774      .foo {
13775        background: -webkit-radial-gradient(red, #00f);
13776        background: radial-gradient(red, #00f);
13777      }
13778      "#},
13779      Browsers {
13780        chrome: Some(8 << 16),
13781        ..Browsers::default()
13782      },
13783    );
13784    prefix_test(
13785      r#"
13786      .foo {
13787        background: radial-gradient(red, blue), linear-gradient(yellow, red), url(bg.jpg);
13788      }
13789      "#,
13790      indoc! {r#"
13791      .foo {
13792        background: -webkit-gradient(linear, 0 0, 0 100%, from(#ff0), to(red)), url("bg.jpg");
13793        background: -webkit-radial-gradient(red, #00f), -webkit-linear-gradient(top, #ff0, red), url("bg.jpg");
13794        background: -moz-radial-gradient(red, #00f), -moz-linear-gradient(top, #ff0, red), url("bg.jpg");
13795        background: -o-radial-gradient(red, #00f), -o-linear-gradient(top, #ff0, red), url("bg.jpg");
13796        background: radial-gradient(red, #00f), linear-gradient(#ff0, red), url("bg.jpg");
13797      }
13798      "#},
13799      Browsers {
13800        chrome: Some(8 << 16),
13801        firefox: Some(4 << 16),
13802        opera: Some(11 << 16 | 5 << 8),
13803        ..Browsers::default()
13804      },
13805    );
13806
13807    prefix_test(
13808      r#"
13809      .foo {
13810        background: linear-gradient(yellow, red 30% 40%, blue);
13811      }
13812      "#,
13813      indoc! {r#"
13814      .foo {
13815        background: linear-gradient(#ff0, red 30%, red 40%, #00f);
13816      }
13817      "#},
13818      Browsers {
13819        chrome: Some(70 << 16),
13820        ..Browsers::default()
13821      },
13822    );
13823
13824    prefix_test(
13825      r#"
13826      .foo {
13827        background: linear-gradient(yellow, red 30% 40%, blue);
13828      }
13829      "#,
13830      indoc! {r#"
13831      .foo {
13832        background: linear-gradient(#ff0, red 30% 40%, #00f);
13833      }
13834      "#},
13835      Browsers {
13836        chrome: Some(71 << 16),
13837        ..Browsers::default()
13838      },
13839    );
13840
13841    prefix_test(
13842      ".foo { background: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
13843      indoc! { r#"
13844        .foo {
13845          background: linear-gradient(#ff0f0e, #7773ff);
13846          background: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
13847        }
13848      "#},
13849      Browsers {
13850        chrome: Some(90 << 16),
13851        ..Browsers::default()
13852      },
13853    );
13854
13855    prefix_test(
13856      ".foo { background: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
13857      indoc! { r#"
13858        .foo {
13859          background: linear-gradient(#ff0f0e, #7773ff);
13860          background: linear-gradient(color(display-p3 1 .0000153435 -.00000303562), color(display-p3 .440289 .28452 1.23485));
13861          background: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
13862        }
13863      "#},
13864      Browsers {
13865        chrome: Some(90 << 16),
13866        safari: Some(14 << 16),
13867        ..Browsers::default()
13868      },
13869    );
13870
13871    prefix_test(
13872      ".foo { background: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
13873      indoc! { r#"
13874        .foo {
13875          background: -webkit-linear-gradient(top, #ff0f0e, #7773ff);
13876          background: linear-gradient(#ff0f0e, #7773ff);
13877          background: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
13878        }
13879      "#},
13880      Browsers {
13881        chrome: Some(20 << 16),
13882        ..Browsers::default()
13883      },
13884    );
13885
13886    prefix_test(
13887      ".foo { background: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
13888      indoc! { r#"
13889        .foo {
13890          background: -webkit-gradient(linear, 0 0, 0 100%, from(#ff0f0e), to(#7773ff));
13891          background: -webkit-linear-gradient(top, #ff0f0e, #7773ff);
13892          background: linear-gradient(#ff0f0e, #7773ff);
13893          background: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
13894        }
13895      "#},
13896      Browsers {
13897        chrome: Some(8 << 16),
13898        ..Browsers::default()
13899      },
13900    );
13901
13902    prefix_test(
13903      ".foo { background: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
13904      indoc! { r#"
13905        .foo {
13906          background: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
13907        }
13908      "#},
13909      Browsers {
13910        safari: Some(15 << 16),
13911        ..Browsers::default()
13912      },
13913    );
13914
13915    prefix_test(
13916      ".foo { background-image: linear-gradient(oklab(59.686% 0.1009 0.1192), oklab(54.0% -0.10 -0.02)); }",
13917      indoc! { r#"
13918        .foo {
13919          background-image: linear-gradient(lab(52.2319% 40.1449 59.9171), lab(47.7776% -34.2947 -7.65904));
13920        }
13921      "#},
13922      Browsers {
13923        safari: Some(15 << 16),
13924        ..Browsers::default()
13925      },
13926    );
13927
13928    prefix_test(
13929      ".foo { background-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
13930      indoc! { r#"
13931        .foo {
13932          background-image: linear-gradient(#ff0f0e, #7773ff);
13933          background-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
13934        }
13935      "#},
13936      Browsers {
13937        chrome: Some(90 << 16),
13938        ..Browsers::default()
13939      },
13940    );
13941
13942    prefix_test(
13943      ".foo { background-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
13944      indoc! { r#"
13945        .foo {
13946          background-image: linear-gradient(#ff0f0e, #7773ff);
13947          background-image: linear-gradient(color(display-p3 1 .0000153435 -.00000303562), color(display-p3 .440289 .28452 1.23485));
13948          background-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
13949        }
13950      "#},
13951      Browsers {
13952        chrome: Some(90 << 16),
13953        safari: Some(14 << 16),
13954        ..Browsers::default()
13955      },
13956    );
13957
13958    prefix_test(
13959      ".foo { background-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
13960      indoc! { r#"
13961        .foo {
13962          background-image: -webkit-linear-gradient(top, #ff0f0e, #7773ff);
13963          background-image: linear-gradient(#ff0f0e, #7773ff);
13964          background-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
13965        }
13966      "#},
13967      Browsers {
13968        chrome: Some(20 << 16),
13969        ..Browsers::default()
13970      },
13971    );
13972
13973    prefix_test(
13974      ".foo { background-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
13975      indoc! { r#"
13976        .foo {
13977          background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ff0f0e), to(#7773ff));
13978          background-image: -webkit-linear-gradient(top, #ff0f0e, #7773ff);
13979          background-image: linear-gradient(#ff0f0e, #7773ff);
13980          background-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
13981        }
13982      "#},
13983      Browsers {
13984        chrome: Some(8 << 16),
13985        ..Browsers::default()
13986      },
13987    );
13988
13989    prefix_test(
13990      ".foo { background-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
13991      indoc! { r#"
13992        .foo {
13993          background-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
13994        }
13995      "#},
13996      Browsers {
13997        safari: Some(15 << 16),
13998        ..Browsers::default()
13999      },
14000    );
14001
14002    prefix_test(
14003      ".foo { background-image: linear-gradient(oklab(59.686% 0.1009 0.1192), oklab(54.0% -0.10 -0.02)); }",
14004      indoc! { r#"
14005        .foo {
14006          background-image: linear-gradient(lab(52.2319% 40.1449 59.9171), lab(47.7776% -34.2947 -7.65904));
14007        }
14008      "#},
14009      Browsers {
14010        safari: Some(15 << 16),
14011        ..Browsers::default()
14012      },
14013    );
14014
14015    // Test cases from https://github.com/postcss/autoprefixer/blob/541295c0e6dd348db2d3f52772b59cd403c59d29/test/cases/gradient.css
14016    prefix_test(
14017      r#"
14018        a {
14019          background: linear-gradient(350.5deg, white, black), linear-gradient(-130deg, black, white), linear-gradient(45deg, black, white);
14020        }
14021        b {
14022          background-image: linear-gradient(rgba(0,0,0,1), white), linear-gradient(white, black);
14023        }
14024        strong {
14025          background: linear-gradient(to top, transparent, rgba(0, 0, 0, 0.8) 20px, #000 30px, #000) no-repeat;
14026        }
14027        div {
14028          background-image: radial-gradient(to left, white, black), repeating-linear-gradient(to bottom right, black, white), repeating-radial-gradient(to top, aqua, red);
14029        }
14030        .old-radial {
14031          background: radial-gradient(0 50%, ellipse farthest-corner, black, white);
14032        }
14033        .simple1 {
14034          background: linear-gradient(black, white);
14035        }
14036        .simple2 {
14037          background: linear-gradient(to left, black 0%, rgba(0, 0, 0, 0.5)50%, white 100%);
14038        }
14039        .simple3 {
14040          background: linear-gradient(to left, black 50%, white 100%);
14041        }
14042        .simple4 {
14043          background: linear-gradient(to right top, black, white);
14044        }
14045        .direction {
14046          background: linear-gradient(top left, black, rgba(0, 0, 0, 0.5), white);
14047        }
14048        .silent {
14049          background: -webkit-linear-gradient(top left, black, white);
14050        }
14051        .radial {
14052          background: radial-gradient(farthest-side at 0 50%, white, black);
14053        }
14054        .second {
14055          background: red linear-gradient(red, blue);
14056          background: url('logo.png'), linear-gradient(#fff, #000);
14057        }
14058        .px {
14059          background: linear-gradient(black 0, white 100px);
14060        }
14061        .list {
14062          list-style-image: linear-gradient(white, black);
14063        }
14064        .mask {
14065          mask: linear-gradient(white, black);
14066        }
14067        .newline {
14068          background-image:
14069              linear-gradient( white, black ),
14070              linear-gradient( black, white );
14071        }
14072        .convert {
14073          background: linear-gradient(0deg, white, black);
14074          background: linear-gradient(90deg, white, black);
14075          background: linear-gradient(180deg, white, black);
14076          background: linear-gradient(270deg, white, black);
14077        }
14078        .grad {
14079          background: linear-gradient(1grad, white, black);
14080        }
14081        .rad {
14082          background: linear-gradient(1rad, white, black);
14083        }
14084        .turn {
14085          background: linear-gradient(0.3turn, white, black);
14086        }
14087        .norm {
14088          background: linear-gradient(-90deg, white, black);
14089        }
14090        .mask {
14091          mask-image: radial-gradient(circle at 86% 86%, transparent 8px, black 8px);
14092        }
14093        .cover {
14094          background: radial-gradient(ellipse cover at center, white, black);
14095        }
14096        .contain {
14097          background: radial-gradient(contain at center, white, black);
14098        }
14099        .no-div {
14100          background: linear-gradient(black);
14101        }
14102        .background-shorthand {
14103          background: radial-gradient(#FFF, transparent) 0 0 / cover no-repeat #F0F;
14104        }
14105        .background-advanced {
14106          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%),
14107                      radial-gradient(#FFF, transparent),
14108                      url(path/to/image.jpg) 50%/cover;
14109        }
14110        .multiradial {
14111          mask-image: radial-gradient(circle closest-corner at 100% 50%, #000, transparent);
14112        }
14113        .broken {
14114          mask-image: radial-gradient(white, black);
14115        }
14116        .loop {
14117          background-image: url("https://test.com/lol(test.png"), radial-gradient(yellow, black, yellow);
14118        }
14119        .unitless-zero {
14120          background-image: linear-gradient(0, green, blue);
14121          background: repeating-linear-gradient(0, blue, red 33.3%)
14122        }
14123        .zero-grad {
14124          background: linear-gradient(0grad, green, blue);
14125          background-image: repeating-linear-gradient(0grad, blue, red 33.3%)
14126        }
14127        .zero-rad {
14128          background: linear-gradient(0rad, green, blue);
14129        }
14130        .zero-turn {
14131          background: linear-gradient(0turn, green, blue);
14132        }
14133      "#,
14134      indoc! { r#"
14135        a {
14136          background: -webkit-linear-gradient(99.5deg, #fff, #000), -webkit-linear-gradient(220deg, #000, #fff), -webkit-linear-gradient(45deg, #000, #fff);
14137          background: -o-linear-gradient(99.5deg, #fff, #000), -o-linear-gradient(220deg, #000, #fff), -o-linear-gradient(45deg, #000, #fff);
14138          background: linear-gradient(350.5deg, #fff, #000), linear-gradient(-130deg, #000, #fff), linear-gradient(45deg, #000, #fff);
14139        }
14140
14141        b {
14142          background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#000), to(#fff)), -webkit-gradient(linear, 0 0, 0 100%, from(#fff), to(#000));
14143          background-image: -webkit-linear-gradient(top, #000, #fff), -webkit-linear-gradient(top, #fff, #000);
14144          background-image: -o-linear-gradient(top, #000, #fff), -o-linear-gradient(top, #fff, #000);
14145          background-image: linear-gradient(#000, #fff), linear-gradient(#fff, #000);
14146        }
14147
14148        strong {
14149          background: -webkit-linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, .8) 20px, #000 30px, #000) no-repeat;
14150          background: -o-linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, .8) 20px, #000 30px, #000) no-repeat;
14151          background: linear-gradient(to top, rgba(0, 0, 0, 0), rgba(0, 0, 0, .8) 20px, #000 30px, #000) no-repeat;
14152        }
14153
14154        div {
14155          background-image: radial-gradient(to left, white, black), repeating-linear-gradient(to bottom right, black, white), repeating-radial-gradient(to top, aqua, red);
14156        }
14157
14158        .old-radial {
14159          background: radial-gradient(0 50%, ellipse farthest-corner, black, white);
14160        }
14161
14162        .simple1 {
14163          background: -webkit-gradient(linear, 0 0, 0 100%, from(#000), to(#fff));
14164          background: -webkit-linear-gradient(top, #000, #fff);
14165          background: -o-linear-gradient(top, #000, #fff);
14166          background: linear-gradient(#000, #fff);
14167        }
14168
14169        .simple2 {
14170          background: -webkit-gradient(linear, 100% 0, 0 0, from(#000), color-stop(.5, rgba(0, 0, 0, .5)), to(#fff));
14171          background: -webkit-linear-gradient(right, #000 0%, rgba(0, 0, 0, .5) 50%, #fff 100%);
14172          background: -o-linear-gradient(right, #000 0%, rgba(0, 0, 0, .5) 50%, #fff 100%);
14173          background: linear-gradient(to left, #000 0%, rgba(0, 0, 0, .5) 50%, #fff 100%);
14174        }
14175
14176        .simple3 {
14177          background: -webkit-gradient(linear, 100% 0, 0 0, color-stop(.5, #000), to(#fff));
14178          background: -webkit-linear-gradient(right, #000 50%, #fff 100%);
14179          background: -o-linear-gradient(right, #000 50%, #fff 100%);
14180          background: linear-gradient(to left, #000 50%, #fff 100%);
14181        }
14182
14183        .simple4 {
14184          background: -webkit-gradient(linear, 0 100%, 100% 0, from(#000), to(#fff));
14185          background: -webkit-linear-gradient(bottom left, #000, #fff);
14186          background: -o-linear-gradient(bottom left, #000, #fff);
14187          background: linear-gradient(to top right, #000, #fff);
14188        }
14189
14190        .direction {
14191          background: linear-gradient(top left, black, rgba(0, 0, 0, .5), white);
14192        }
14193
14194        .silent {
14195          background: -webkit-gradient(linear, 100% 100%, 0 0, from(#000), to(#fff));
14196          background: -webkit-linear-gradient(top left, #000, #fff);
14197        }
14198
14199        .radial {
14200          background: -webkit-radial-gradient(farthest-side at 0, #fff, #000);
14201          background: -o-radial-gradient(farthest-side at 0, #fff, #000);
14202          background: radial-gradient(farthest-side at 0, #fff, #000);
14203        }
14204
14205        .second {
14206          background: red -webkit-gradient(linear, 0 0, 0 100%, from(red), to(#00f));
14207          background: red -webkit-linear-gradient(top, red, #00f);
14208          background: red -o-linear-gradient(top, red, #00f);
14209          background: red linear-gradient(red, #00f);
14210          background: url("logo.png"), linear-gradient(#fff, #000);
14211        }
14212
14213        .px {
14214          background: -webkit-linear-gradient(top, #000 0, #fff 100px);
14215          background: -o-linear-gradient(top, #000 0, #fff 100px);
14216          background: linear-gradient(#000 0, #fff 100px);
14217        }
14218
14219        .list {
14220          list-style-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fff), to(#000));
14221          list-style-image: -webkit-linear-gradient(top, #fff, #000);
14222          list-style-image: -o-linear-gradient(top, #fff, #000);
14223          list-style-image: linear-gradient(#fff, #000);
14224        }
14225
14226        .mask {
14227          -webkit-mask: -webkit-gradient(linear, 0 0, 0 100%, from(#fff), to(#000));
14228          -webkit-mask: -webkit-linear-gradient(top, #fff, #000);
14229          -webkit-mask: -o-linear-gradient(top, #fff, #000);
14230          mask: -o-linear-gradient(top, #fff, #000);
14231          -webkit-mask: linear-gradient(#fff, #000);
14232          mask: linear-gradient(#fff, #000);
14233        }
14234
14235        .newline {
14236          background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fff), to(#000)), -webkit-gradient(linear, 0 0, 0 100%, from(#000), to(#fff));
14237          background-image: -webkit-linear-gradient(top, #fff, #000), -webkit-linear-gradient(top, #000, #fff);
14238          background-image: -o-linear-gradient(top, #fff, #000), -o-linear-gradient(top, #000, #fff);
14239          background-image: linear-gradient(#fff, #000), linear-gradient(#000, #fff);
14240        }
14241
14242        .convert {
14243          background: -webkit-gradient(linear, 0 100%, 0 0, from(#fff), to(#000));
14244          background: -webkit-linear-gradient(90deg, #fff, #000);
14245          background: -o-linear-gradient(90deg, #fff, #000);
14246          background: linear-gradient(0deg, #fff, #000);
14247          background: linear-gradient(90deg, #fff, #000);
14248          background: linear-gradient(#fff, #000);
14249          background: linear-gradient(270deg, #fff, #000);
14250        }
14251
14252        .grad {
14253          background: -webkit-linear-gradient(89.1deg, #fff, #000);
14254          background: -o-linear-gradient(89.1deg, #fff, #000);
14255          background: linear-gradient(1grad, #fff, #000);
14256        }
14257
14258        .rad {
14259          background: -webkit-linear-gradient(32.704deg, #fff, #000);
14260          background: -o-linear-gradient(32.704deg, #fff, #000);
14261          background: linear-gradient(57.2958deg, #fff, #000);
14262        }
14263
14264        .turn {
14265          background: -webkit-linear-gradient(342deg, #fff, #000);
14266          background: -o-linear-gradient(342deg, #fff, #000);
14267          background: linear-gradient(.3turn, #fff, #000);
14268        }
14269
14270        .norm {
14271          background: -webkit-linear-gradient(#fff, #000);
14272          background: -o-linear-gradient(#fff, #000);
14273          background: linear-gradient(-90deg, #fff, #000);
14274        }
14275
14276        .mask {
14277          -webkit-mask-image: -webkit-radial-gradient(circle at 86% 86%, rgba(0, 0, 0, 0) 8px, #000 8px);
14278          -webkit-mask-image: -o-radial-gradient(circle at 86% 86%, rgba(0, 0, 0, 0) 8px, #000 8px);
14279          mask-image: -o-radial-gradient(circle at 86% 86%, rgba(0, 0, 0, 0) 8px, #000 8px);
14280          -webkit-mask-image: radial-gradient(circle at 86% 86%, rgba(0, 0, 0, 0) 8px, #000 8px);
14281          mask-image: radial-gradient(circle at 86% 86%, rgba(0, 0, 0, 0) 8px, #000 8px);
14282        }
14283
14284        .cover {
14285          background: radial-gradient(ellipse cover at center, white, black);
14286        }
14287
14288        .contain {
14289          background: radial-gradient(contain at center, white, black);
14290        }
14291
14292        .no-div {
14293          background: -webkit-gradient(linear, 0 0, 0 100%, from(#000));
14294          background: -webkit-linear-gradient(top, #000);
14295          background: -o-linear-gradient(top, #000);
14296          background: linear-gradient(#000);
14297        }
14298
14299        .background-shorthand {
14300          background: #f0f -webkit-radial-gradient(#fff, rgba(0, 0, 0, 0)) 0 0 / cover no-repeat;
14301          background: #f0f -o-radial-gradient(#fff, rgba(0, 0, 0, 0)) 0 0 / cover no-repeat;
14302          background: #f0f radial-gradient(#fff, rgba(0, 0, 0, 0)) 0 0 / cover no-repeat;
14303        }
14304
14305        .background-advanced {
14306          background: url("path/to/image.jpg") 50% / cover;
14307          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;
14308          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;
14309          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;
14310        }
14311
14312        .multiradial {
14313          -webkit-mask-image: -webkit-radial-gradient(circle closest-corner at 100%, #000, rgba(0, 0, 0, 0));
14314          -webkit-mask-image: -o-radial-gradient(circle closest-corner at 100%, #000, rgba(0, 0, 0, 0));
14315          mask-image: -o-radial-gradient(circle closest-corner at 100%, #000, rgba(0, 0, 0, 0));
14316          -webkit-mask-image: radial-gradient(circle closest-corner at 100%, #000, rgba(0, 0, 0, 0));
14317          mask-image: radial-gradient(circle closest-corner at 100%, #000, rgba(0, 0, 0, 0));
14318        }
14319
14320        .broken {
14321          -webkit-mask-image: -webkit-radial-gradient(#fff, #000);
14322          -webkit-mask-image: -o-radial-gradient(#fff, #000);
14323          mask-image: -o-radial-gradient(#fff, #000);
14324          -webkit-mask-image: radial-gradient(#fff, #000);
14325          mask-image: radial-gradient(#fff, #000);
14326        }
14327
14328        .loop {
14329          background-image: url("https://test.com/lol(test.png");
14330          background-image: url("https://test.com/lol(test.png"), -webkit-radial-gradient(#ff0, #000, #ff0);
14331          background-image: url("https://test.com/lol(test.png"), -o-radial-gradient(#ff0, #000, #ff0);
14332          background-image: url("https://test.com/lol(test.png"), radial-gradient(#ff0, #000, #ff0);
14333        }
14334
14335        .unitless-zero {
14336          background-image: -webkit-gradient(linear, 0 100%, 0 0, from(green), to(#00f));
14337          background-image: -webkit-linear-gradient(90deg, green, #00f);
14338          background-image: -o-linear-gradient(90deg, green, #00f);
14339          background-image: linear-gradient(0deg, green, #00f);
14340          background: repeating-linear-gradient(0deg, #00f, red 33.3%);
14341        }
14342
14343        .zero-grad {
14344          background: -webkit-gradient(linear, 0 100%, 0 0, from(green), to(#00f));
14345          background: -webkit-linear-gradient(90deg, green, #00f);
14346          background: -o-linear-gradient(90deg, green, #00f);
14347          background: linear-gradient(0grad, green, #00f);
14348          background-image: repeating-linear-gradient(0grad, #00f, red 33.3%);
14349        }
14350
14351        .zero-rad, .zero-turn {
14352          background: -webkit-gradient(linear, 0 100%, 0 0, from(green), to(#00f));
14353          background: -webkit-linear-gradient(90deg, green, #00f);
14354          background: -o-linear-gradient(90deg, green, #00f);
14355          background: linear-gradient(0deg, green, #00f);
14356        }
14357      "#},
14358      Browsers {
14359        chrome: Some(25 << 16),
14360        opera: Some(12 << 16),
14361        android: Some(2 << 16 | 3 << 8),
14362        ..Browsers::default()
14363      },
14364    );
14365  }
14366
14367  #[test]
14368  fn test_font_face() {
14369    minify_test(
14370      r#"@font-face {
14371      src: url("test.woff");
14372      font-family: "Helvetica";
14373      font-weight: bold;
14374      font-style: italic;
14375    }"#,
14376      "@font-face{src:url(test.woff);font-family:Helvetica;font-weight:700;font-style:italic}",
14377    );
14378    minify_test("@font-face {src: url(test.woff);}", "@font-face{src:url(test.woff)}");
14379    minify_test("@font-face {src: local(\"Test\");}", "@font-face{src:local(Test)}");
14380    minify_test(
14381      "@font-face {src: local(\"Foo Bar\");}",
14382      "@font-face{src:local(Foo Bar)}",
14383    );
14384    minify_test("@font-face {src: local(Test);}", "@font-face{src:local(Test)}");
14385    minify_test("@font-face {src: local(Foo Bar);}", "@font-face{src:local(Foo Bar)}");
14386
14387    minify_test(
14388      "@font-face {src: url(\"test.woff\") format(woff);}",
14389      "@font-face{src:url(test.woff)format(\"woff\")}",
14390    );
14391    minify_test(
14392      "@font-face {src: url(\"test.ttc\") format(collection), url(test.ttf) format(truetype);}",
14393      "@font-face{src:url(test.ttc)format(\"collection\"),url(test.ttf)format(\"truetype\")}",
14394    );
14395    minify_test(
14396      "@font-face {src: url(\"test.otf\") format(opentype) tech(features-aat);}",
14397      "@font-face{src:url(test.otf)format(\"opentype\")tech(features-aat)}",
14398    );
14399    minify_test(
14400      "@font-face {src: url(\"test.woff\") format(woff) tech(color-colrv1);}",
14401      "@font-face{src:url(test.woff)format(\"woff\")tech(color-colrv1)}",
14402    );
14403    minify_test(
14404      "@font-face {src: url(\"test.woff2\") format(woff2) tech(variations);}",
14405      "@font-face{src:url(test.woff2)format(\"woff2\")tech(variations)}",
14406    );
14407    minify_test(
14408      "@font-face {src: url(\"test.woff\") format(woff) tech(palettes);}",
14409      "@font-face{src:url(test.woff)format(\"woff\")tech(palettes)}",
14410    );
14411    // multiple tech
14412    minify_test(
14413      "@font-face {src: url(\"test.woff\") format(woff) tech(features-opentype, color-sbix);}",
14414      "@font-face{src:url(test.woff)format(\"woff\")tech(features-opentype,color-sbix)}",
14415    );
14416    minify_test(
14417      "@font-face {src: url(\"test.woff\")   format(woff)    tech(incremental, color-svg, features-graphite, features-aat);}",
14418      "@font-face{src:url(test.woff)format(\"woff\")tech(incremental,color-svg,features-graphite,features-aat)}",
14419    );
14420    // format() function must precede tech() if both are present
14421    minify_test(
14422      "@font-face {src: url(\"foo.ttf\") format(opentype) tech(color-colrv1);}",
14423      "@font-face{src:url(foo.ttf)format(\"opentype\")tech(color-colrv1)}",
14424    );
14425    // only have tech is valid
14426    minify_test(
14427      "@font-face {src: url(\"foo.ttf\") tech(color-SVG);}",
14428      "@font-face{src:url(foo.ttf)tech(color-svg)}",
14429    );
14430    // CGQAQ: if tech and format both presence, order is matter, tech before format is invalid
14431    // but now just return raw token, we don't have strict mode yet.
14432    // ref: https://github.com/parcel-bundler/lightningcss/pull/255#issuecomment-1219049998
14433    minify_test(
14434      "@font-face {src: url(\"foo.ttf\") tech(palettes  color-colrv0  variations) format(opentype);}",
14435      "@font-face{src:url(foo.ttf) tech(palettes color-colrv0 variations) format(opentype)}",
14436    );
14437    // TODO(CGQAQ): make this test pass when we have strict mode
14438    // ref: https://github.com/web-platform-tests/wpt/blob/9f8a6ccc41aa725e8f51f4f096f686313bb88d8d/css/css-fonts/parsing/font-face-src-tech.html#L45
14439    // error_test(
14440    //   "@font-face {src: url(\"foo.ttf\") tech(features-opentype) format(opentype);}",
14441    //   ParserError::AtRuleBodyInvalid,
14442    // );
14443    // error_test(
14444    //   "@font-face {src: url(\"foo.ttf\") tech();}",
14445    //   ParserError::AtRuleBodyInvalid,
14446    // );
14447    // error_test(
14448    //   "@font-face {src: url(\"foo.ttf\") tech(\"features-opentype\");}",
14449    //   ParserError::AtRuleBodyInvalid,
14450    // );
14451    // error_test(
14452    //   "@font-face {src: url(\"foo.ttf\") tech(\"color-colrv0\");}",
14453    //   ParserError::AtRuleBodyInvalid,
14454    // );
14455    minify_test(
14456      "@font-face {src: local(\"\") url(\"test.woff\");}",
14457      "@font-face{src:local(\"\") url(test.woff)}",
14458    );
14459    minify_test("@font-face {font-weight: 200 400}", "@font-face{font-weight:200 400}");
14460    minify_test("@font-face {font-weight: 400 400}", "@font-face{font-weight:400}");
14461    minify_test(
14462      "@font-face {font-stretch: 50% 200%}",
14463      "@font-face{font-stretch:50% 200%}",
14464    );
14465    minify_test("@font-face {font-stretch: 50% 50%}", "@font-face{font-stretch:50%}");
14466    minify_test("@font-face {unicode-range: U+26;}", "@font-face{unicode-range:U+26}");
14467    minify_test("@font-face {unicode-range: u+26;}", "@font-face{unicode-range:U+26}");
14468    minify_test(
14469      "@font-face {unicode-range: U+0-7F;}",
14470      "@font-face{unicode-range:U+0-7F}",
14471    );
14472    minify_test(
14473      "@font-face {unicode-range: U+0025-00FF;}",
14474      "@font-face{unicode-range:U+25-FF}",
14475    );
14476    minify_test("@font-face {unicode-range: U+4??;}", "@font-face{unicode-range:U+4??}");
14477    minify_test(
14478      "@font-face {unicode-range: U+400-4FF;}",
14479      "@font-face{unicode-range:U+4??}",
14480    );
14481    minify_test(
14482      "@font-face {unicode-range: U+0025-00FF, U+4??;}",
14483      "@font-face{unicode-range:U+25-FF,U+4??}",
14484    );
14485    minify_test(
14486      "@font-face {unicode-range: U+A5, U+4E00-9FFF, U+30??, U+FF00-FF9F;}",
14487      "@font-face{unicode-range:U+A5,U+4E00-9FFF,U+30??,U+FF00-FF9F}",
14488    );
14489    minify_test(
14490      "@font-face {unicode-range: U+????;}",
14491      "@font-face{unicode-range:U+????}",
14492    );
14493    minify_test(
14494      "@font-face {unicode-range: U+0000-FFFF;}",
14495      "@font-face{unicode-range:U+????}",
14496    );
14497    minify_test(
14498      "@font-face {unicode-range: U+10????;}",
14499      "@font-face{unicode-range:U+10????}",
14500    );
14501    minify_test(
14502      "@font-face {unicode-range: U+100000-10FFFF;}",
14503      "@font-face{unicode-range:U+10????}",
14504    );
14505    minify_test(
14506      "@font-face {unicode-range: U+1e1e?;}",
14507      "@font-face{unicode-range:U+1E1E?}",
14508    );
14509    minify_test(
14510      "@font-face {unicode-range: u+????, U+1????, U+10????;}",
14511      "@font-face{unicode-range:U+????,U+1????,U+10????}",
14512    );
14513    minify_test(r#"
14514      @font-face {
14515        font-family: Inter;
14516        font-style: oblique 0deg 10deg;
14517        font-weight: 100 900;
14518        src: url("../fonts/Inter.var.woff2?v=3.19") format("woff2");
14519        font-display: swap;
14520      }
14521    "#, "@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}");
14522    minify_test(r#"
14523    @font-face {
14524      font-family: Inter;
14525      font-style: oblique 14deg 14deg;
14526      font-weight: 100 900;
14527      src: url("../fonts/Inter.var.woff2?v=3.19") format("woff2");
14528      font-display: swap;
14529    }
14530  "#, "@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}");
14531  }
14532
14533  #[test]
14534  fn test_font_palette_values() {
14535    minify_test(
14536      r#"@font-palette-values --Cooler {
14537      font-family: Bixa;
14538      base-palette: 1;
14539      override-colors: 1 #7EB7E4;
14540    }"#,
14541      "@font-palette-values --Cooler{font-family:Bixa;base-palette:1;override-colors:1 #7eb7e4}",
14542    );
14543    minify_test(
14544      r#"@font-palette-values --Cooler {
14545      font-family: Handover Sans;
14546      base-palette: 3;
14547      override-colors: 1 rgb(43, 12, 9), 3 lime;
14548    }"#,
14549      "@font-palette-values --Cooler{font-family:Handover Sans;base-palette:3;override-colors:1 #2b0c09,3 #0f0}",
14550    );
14551    minify_test(r#"@font-palette-values --Cooler {
14552      font-family: Handover Sans;
14553      base-palette: 3;
14554      override-colors: 1 rgb(43, 12, 9), 3 var(--highlight);
14555    }"#, "@font-palette-values --Cooler{font-family:Handover Sans;base-palette:3;override-colors:1 #2b0c09, 3 var(--highlight)}");
14556    prefix_test(
14557      r#"@font-palette-values --Cooler {
14558      font-family: Handover Sans;
14559      base-palette: 3;
14560      override-colors: 1 rgb(43, 12, 9), 3 lch(50.998% 135.363 338);
14561    }"#,
14562      indoc! {r#"@font-palette-values --Cooler {
14563      font-family: Handover Sans;
14564      base-palette: 3;
14565      override-colors: 1 #2b0c09, 3 #ee00be;
14566      override-colors: 1 #2b0c09, 3 lch(50.998% 135.363 338);
14567    }
14568    "#},
14569      Browsers {
14570        chrome: Some(90 << 16),
14571        ..Browsers::default()
14572      },
14573    );
14574    prefix_test(
14575      r#"@font-palette-values --Cooler {
14576      font-family: Handover Sans;
14577      base-palette: 3;
14578      override-colors: 1 var(--foo), 3 lch(50.998% 135.363 338);
14579    }"#,
14580      indoc! {r#"@font-palette-values --Cooler {
14581      font-family: Handover Sans;
14582      base-palette: 3;
14583      override-colors: 1 var(--foo), 3 #ee00be;
14584    }
14585
14586    @supports (color: lab(0% 0 0)) {
14587      @font-palette-values --Cooler {
14588        font-family: Handover Sans;
14589        base-palette: 3;
14590        override-colors: 1 var(--foo), 3 lab(50.998% 125.506 -50.7078);
14591      }
14592    }
14593    "#},
14594      Browsers {
14595        chrome: Some(90 << 16),
14596        ..Browsers::default()
14597      },
14598    );
14599    prefix_test(
14600      r#"@supports (color: lab(0% 0 0)) {
14601      @font-palette-values --Cooler {
14602        font-family: Handover Sans;
14603        base-palette: 3;
14604        override-colors: 1 var(--foo), 3 lab(50.998% 125.506 -50.7078);
14605      }
14606    }"#,
14607      indoc! {r#"@supports (color: lab(0% 0 0)) {
14608      @font-palette-values --Cooler {
14609        font-family: Handover Sans;
14610        base-palette: 3;
14611        override-colors: 1 var(--foo), 3 lab(50.998% 125.506 -50.7078);
14612      }
14613    }
14614    "#},
14615      Browsers {
14616        chrome: Some(90 << 16),
14617        ..Browsers::default()
14618      },
14619    );
14620    minify_test(".foo { font-palette: --Custom; }", ".foo{font-palette:--Custom}");
14621  }
14622
14623  #[test]
14624  fn test_font_feature_values() {
14625    // https://github.com/clagnut/TODS/blob/e693d52ad411507b960cf01a9734265e3efab102/tods.css#L116-L142
14626    minify_test(
14627      r#"
14628@font-feature-values "Fancy Font Name" {
14629  @styleset { cursive: 1; swoopy: 7 16; }
14630  @character-variant { ampersand: 1; capital-q: 2; }
14631  @stylistic { two-story-g: 1; straight-y: 2; }
14632  @swash { swishy: 1; flowing: 2; }
14633  @ornaments { clover: 1; fleuron: 2; }
14634  @annotation { circled: 1; boxed: 2; }
14635}
14636    "#,
14637      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}}"#,
14638    );
14639
14640    // https://github.com/Sorixelle/srxl.me/blob/4eb4f4a15cb2d21356df24c096d6a819cfdc1a99/public/fonts/inter/inter.css#L201-L222
14641    minify_test(
14642      r#"
14643@font-feature-values "Inter", "Inter var", "Inter var experimental" {
14644  @styleset {
14645    open-digits: 1;
14646    disambiguation: 2;
14647    curved-r: 3;
14648    disambiguation-without-zero: 4;
14649  }
14650
14651  @character-variant {
14652    alt-one: 1;
14653    open-four: 2;
14654    open-six: 3;
14655    open-nine: 4;
14656    lower-l-with-tail: 5;
14657    curved-lower-r: 6;
14658    german-double-s: 7;
14659    upper-i-with-serif: 8;
14660    flat-top-three: 9;
14661    upper-g-with-spur: 10;
14662    single-storey-a: 11;
14663  }
14664}
14665      "#,
14666      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}}"#,
14667    );
14668
14669    // https://github.com/MihailJP/Inconsolata-LGC/blob/7c53cf455787096c93d82d9a51018f12ec39a6e9/Inconsolata-LGC.css#L65-L91
14670    minify_test(
14671      r#"
14672@font-feature-values "Inconsolata LGC" {
14673	@styleset {
14674		alternative-umlaut: 1;
14675	}
14676	@character-variant {
14677		zero-plain: 1 1;
14678		zero-dotted: 1 2;
14679		zero-longslash: 1 3;
14680		r-with-serif: 2 1;
14681		eng-descender: 3 1;
14682		eng-uppercase: 3 2;
14683		dollar-open: 4 1;
14684		dollar-oldstyle: 4 2;
14685		dollar-cifrao: 4 2;
14686		ezh-no-descender: 5 1;
14687		ezh-reversed-sigma: 5 2;
14688		triangle-text-form: 6 1;
14689		el-with-hook-old: 7 1;
14690		qa-enlarged-lowercase: 8 1;
14691		qa-reversed-p: 8 2;
14692		che-with-hook: 9 1;
14693		che-with-hook-alt: 9 2;
14694		ge-with-hook: 10 1;
14695		ge-with-hook-alt: 10 2;
14696		ge-with-stroke-and-descender: 11 1;
14697	}
14698}
14699    "#,
14700      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}}"#,
14701    );
14702
14703    minify_test(
14704      r#"
14705      @font-feature-values "Fancy Font Name" {
14706        @styleset { cursive: 1; swoopy: 7 16; }
14707        @character-variant { ampersand: 1; capital-q: 2; }
14708      }
14709      "#,
14710      r#"@font-feature-values Fancy Font Name{@styleset{cursive:1;swoopy:7 16}@character-variant{ampersand:1;capital-q:2}}"#,
14711    );
14712    minify_test(
14713      r#"
14714      @font-feature-values foo {
14715          @swash { pretty: 0; pretty: 1; cool: 2; }
14716      }
14717      "#,
14718      "@font-feature-values foo{@swash{pretty:1;cool:2}}",
14719    );
14720    minify_test(
14721      r#"
14722      @font-feature-values foo {
14723          @swash { pretty: 1; }
14724          @swash { cool: 2; }
14725      }
14726      "#,
14727      "@font-feature-values foo{@swash{pretty:1;cool:2}}",
14728    );
14729    minify_test(
14730      r#"
14731      @font-feature-values foo {
14732          @swash { pretty: 1; }
14733      }
14734      @font-feature-values foo {
14735          @swash { cool: 2; }
14736      }
14737      "#,
14738      "@font-feature-values foo{@swash{pretty:1;cool:2}}",
14739    );
14740  }
14741
14742  #[test]
14743  fn test_page_rule() {
14744    minify_test("@page {margin: 0.5cm}", "@page{margin:.5cm}");
14745    minify_test("@page :left {margin: 0.5cm}", "@page:left{margin:.5cm}");
14746    minify_test("@page :right {margin: 0.5cm}", "@page:right{margin:.5cm}");
14747    minify_test(
14748      "@page LandscapeTable {margin: 0.5cm}",
14749      "@page LandscapeTable{margin:.5cm}",
14750    );
14751    minify_test(
14752      "@page CompanyLetterHead:first {margin: 0.5cm}",
14753      "@page CompanyLetterHead:first{margin:.5cm}",
14754    );
14755    minify_test("@page:first {margin: 0.5cm}", "@page:first{margin:.5cm}");
14756    minify_test("@page :blank:first {margin: 0.5cm}", "@page:blank:first{margin:.5cm}");
14757    minify_test("@page toc, index {margin: 0.5cm}", "@page toc,index{margin:.5cm}");
14758    minify_test(
14759      r#"
14760    @page :right {
14761      @bottom-left {
14762        margin: 10pt;
14763      }
14764    }
14765    "#,
14766      "@page:right{@bottom-left{margin:10pt}}",
14767    );
14768    minify_test(
14769      r#"
14770    @page :right {
14771      margin: 1in;
14772
14773      @bottom-left {
14774        margin: 10pt;
14775      }
14776    }
14777    "#,
14778      "@page:right{margin:1in;@bottom-left{margin:10pt}}",
14779    );
14780
14781    test(
14782      r#"
14783    @page :right {
14784      @bottom-left {
14785        margin: 10pt;
14786      }
14787    }
14788    "#,
14789      indoc! {r#"
14790      @page :right {
14791        @bottom-left {
14792          margin: 10pt;
14793        }
14794      }
14795      "#},
14796    );
14797
14798    test(
14799      r#"
14800    @page :right {
14801      margin: 1in;
14802
14803      @bottom-left-corner { content: "Foo"; }
14804      @bottom-right-corner { content: "Bar"; }
14805    }
14806    "#,
14807      indoc! {r#"
14808      @page :right {
14809        margin: 1in;
14810
14811        @bottom-left-corner {
14812          content: "Foo";
14813        }
14814
14815        @bottom-right-corner {
14816          content: "Bar";
14817        }
14818      }
14819      "#},
14820    );
14821
14822    error_test(
14823      r#"
14824      @page {
14825        @foo {
14826          margin: 1in;
14827        }
14828      }
14829      "#,
14830      ParserError::AtRuleInvalid("foo".into()),
14831    );
14832
14833    error_test(
14834      r#"
14835      @page {
14836        @top-left-corner {
14837          @bottom-left {
14838            margin: 1in;
14839          }
14840        }
14841      }
14842      "#,
14843      ParserError::AtRuleInvalid("bottom-left".into()),
14844    );
14845  }
14846
14847  #[test]
14848  fn test_supports_rule() {
14849    test(
14850      r#"
14851      @supports (foo: bar) {
14852        .test {
14853          foo: bar;
14854        }
14855      }
14856    "#,
14857      indoc! { r#"
14858      @supports (foo: bar) {
14859        .test {
14860          foo: bar;
14861        }
14862      }
14863    "#},
14864    );
14865    test(
14866      r#"
14867      @supports not (foo: bar) {
14868        .test {
14869          foo: bar;
14870        }
14871      }
14872    "#,
14873      indoc! { r#"
14874      @supports not (foo: bar) {
14875        .test {
14876          foo: bar;
14877        }
14878      }
14879    "#},
14880    );
14881    test(
14882      r#"
14883      @supports (foo: bar) or (bar: baz) {
14884        .test {
14885          foo: bar;
14886        }
14887      }
14888    "#,
14889      indoc! { r#"
14890      @supports (foo: bar) or (bar: baz) {
14891        .test {
14892          foo: bar;
14893        }
14894      }
14895    "#},
14896    );
14897    test(
14898      r#"
14899      @supports (((foo: bar) or (bar: baz))) {
14900        .test {
14901          foo: bar;
14902        }
14903      }
14904    "#,
14905      indoc! { r#"
14906      @supports (foo: bar) or (bar: baz) {
14907        .test {
14908          foo: bar;
14909        }
14910      }
14911    "#},
14912    );
14913    test(
14914      r#"
14915      @supports (foo: bar) and (bar: baz) {
14916        .test {
14917          foo: bar;
14918        }
14919      }
14920    "#,
14921      indoc! { r#"
14922      @supports (foo: bar) and (bar: baz) {
14923        .test {
14924          foo: bar;
14925        }
14926      }
14927    "#},
14928    );
14929    test(
14930      r#"
14931      @supports (((foo: bar) and (bar: baz))) {
14932        .test {
14933          foo: bar;
14934        }
14935      }
14936    "#,
14937      indoc! { r#"
14938      @supports (foo: bar) and (bar: baz) {
14939        .test {
14940          foo: bar;
14941        }
14942      }
14943    "#},
14944    );
14945    test(
14946      r#"
14947      @supports (foo: bar) and (((bar: baz) or (test: foo))) {
14948        .test {
14949          foo: bar;
14950        }
14951      }
14952    "#,
14953      indoc! { r#"
14954      @supports (foo: bar) and ((bar: baz) or (test: foo)) {
14955        .test {
14956          foo: bar;
14957        }
14958      }
14959    "#},
14960    );
14961    test(
14962      r#"
14963      @supports not (((foo: bar) and (bar: baz))) {
14964        .test {
14965          foo: bar;
14966        }
14967      }
14968    "#,
14969      indoc! { r#"
14970      @supports not ((foo: bar) and (bar: baz)) {
14971        .test {
14972          foo: bar;
14973        }
14974      }
14975    "#},
14976    );
14977    test(
14978      r#"
14979      @supports selector(a > b) {
14980        .test {
14981          foo: bar;
14982        }
14983      }
14984    "#,
14985      indoc! { r#"
14986      @supports selector(a > b) {
14987        .test {
14988          foo: bar;
14989        }
14990      }
14991    "#},
14992    );
14993    test(
14994      r#"
14995      @supports unknown(test) {
14996        .test {
14997          foo: bar;
14998        }
14999      }
15000    "#,
15001      indoc! { r#"
15002      @supports unknown(test) {
15003        .test {
15004          foo: bar;
15005        }
15006      }
15007    "#},
15008    );
15009    test(
15010      r#"
15011      @supports (unknown) {
15012        .test {
15013          foo: bar;
15014        }
15015      }
15016    "#,
15017      indoc! { r#"
15018      @supports (unknown) {
15019        .test {
15020          foo: bar;
15021        }
15022      }
15023    "#},
15024    );
15025    test(
15026      r#"
15027      @supports (display: grid) and (not (display: inline-grid)) {
15028        .test {
15029          foo: bar;
15030        }
15031      }
15032    "#,
15033      indoc! { r#"
15034      @supports (display: grid) and (not (display: inline-grid)) {
15035        .test {
15036          foo: bar;
15037        }
15038      }
15039    "#},
15040    );
15041    prefix_test(
15042      r#"
15043      @supports (backdrop-filter: blur(10px)) {
15044        div {
15045          backdrop-filter: blur(10px);
15046        }
15047      }
15048    "#,
15049      indoc! { r#"
15050      @supports ((-webkit-backdrop-filter: blur(10px)) or (backdrop-filter: blur(10px))) {
15051        div {
15052          -webkit-backdrop-filter: blur(10px);
15053          backdrop-filter: blur(10px);
15054        }
15055      }
15056    "#},
15057      Browsers {
15058        safari: Some(14 << 16),
15059        ..Default::default()
15060      },
15061    );
15062    prefix_test(
15063      r#"
15064      @supports ((-webkit-backdrop-filter: blur(10px)) or (backdrop-filter: blur(10px))) {
15065        div {
15066          backdrop-filter: blur(10px);
15067        }
15068      }
15069    "#,
15070      indoc! { r#"
15071      @supports ((-webkit-backdrop-filter: blur(10px)) or (backdrop-filter: blur(10px))) {
15072        div {
15073          -webkit-backdrop-filter: blur(10px);
15074          backdrop-filter: blur(10px);
15075        }
15076      }
15077    "#},
15078      Browsers {
15079        safari: Some(14 << 16),
15080        ..Default::default()
15081      },
15082    );
15083    prefix_test(
15084      r#"
15085      @supports ((-webkit-backdrop-filter: blur(20px)) or (backdrop-filter: blur(10px))) {
15086        div {
15087          backdrop-filter: blur(10px);
15088        }
15089      }
15090    "#,
15091      indoc! { r#"
15092      @supports ((-webkit-backdrop-filter: blur(20px))) or ((-webkit-backdrop-filter: blur(10px)) or (backdrop-filter: blur(10px))) {
15093        div {
15094          -webkit-backdrop-filter: blur(10px);
15095          backdrop-filter: blur(10px);
15096        }
15097      }
15098    "#},
15099      Browsers {
15100        safari: Some(14 << 16),
15101        ..Default::default()
15102      },
15103    );
15104    prefix_test(
15105      r#"
15106      @supports ((-webkit-backdrop-filter: blur(10px)) or (backdrop-filter: blur(10px))) {
15107        div {
15108          backdrop-filter: blur(10px);
15109        }
15110      }
15111    "#,
15112      indoc! { r#"
15113      @supports (backdrop-filter: blur(10px)) {
15114        div {
15115          backdrop-filter: blur(10px);
15116        }
15117      }
15118    "#},
15119      Browsers {
15120        chrome: Some(80 << 16),
15121        ..Default::default()
15122      },
15123    );
15124    minify_test(
15125      r#"
15126      @supports (width: calc(10px * 2)) {
15127        .test {
15128          width: calc(10px * 2);
15129        }
15130      }
15131    "#,
15132      "@supports (width:calc(10px * 2)){.test{width:20px}}",
15133    );
15134    minify_test(
15135      r#"
15136      @supports (color: hsl(0deg, 0%, 0%)) {
15137        .test {
15138          color: hsl(0deg, 0%, 0%);
15139        }
15140      }
15141    "#,
15142      "@supports (color:hsl(0deg, 0%, 0%)){.test{color:#000}}",
15143    );
15144  }
15145
15146  #[test]
15147  fn test_counter_style() {
15148    test(
15149      r#"
15150      @counter-style circled-alpha {
15151        system: fixed;
15152        symbols: Ⓐ Ⓑ Ⓒ;
15153        suffix: " ";
15154      }
15155    "#,
15156      indoc! { r#"
15157      @counter-style circled-alpha {
15158        system: fixed;
15159        symbols: Ⓐ Ⓑ Ⓒ;
15160        suffix: " ";
15161      }
15162    "#},
15163    );
15164  }
15165
15166  #[test]
15167  fn test_namespace() {
15168    minify_test(
15169      "@namespace url(http://toto.example.org);",
15170      "@namespace \"http://toto.example.org\";",
15171    );
15172    minify_test(
15173      "@namespace \"http://toto.example.org\";",
15174      "@namespace \"http://toto.example.org\";",
15175    );
15176    minify_test(
15177      "@namespace toto \"http://toto.example.org\";",
15178      "@namespace toto \"http://toto.example.org\";",
15179    );
15180    minify_test(
15181      "@namespace toto url(http://toto.example.org);",
15182      "@namespace toto \"http://toto.example.org\";",
15183    );
15184
15185    test(
15186      r#"
15187      @namespace "http://example.com/foo";
15188
15189      x {
15190        color: red;
15191      }
15192    "#,
15193      indoc! {r#"
15194      @namespace "http://example.com/foo";
15195
15196      x {
15197        color: red;
15198      }
15199    "#},
15200    );
15201
15202    test(
15203      r#"
15204      @namespace toto "http://toto.example.org";
15205
15206      toto|x {
15207        color: red;
15208      }
15209
15210      [toto|att=val] {
15211        color: blue
15212      }
15213    "#,
15214      indoc! {r#"
15215      @namespace toto "http://toto.example.org";
15216
15217      toto|x {
15218        color: red;
15219      }
15220
15221      [toto|att="val"] {
15222        color: #00f;
15223      }
15224    "#},
15225    );
15226
15227    test(
15228      r#"
15229      @namespace "http://example.com/foo";
15230
15231      |x {
15232        color: red;
15233      }
15234
15235      [|att=val] {
15236        color: blue
15237      }
15238    "#,
15239      indoc! {r#"
15240      @namespace "http://example.com/foo";
15241
15242      |x {
15243        color: red;
15244      }
15245
15246      [att="val"] {
15247        color: #00f;
15248      }
15249    "#},
15250    );
15251
15252    test(
15253      r#"
15254      @namespace "http://example.com/foo";
15255
15256      *|x {
15257        color: red;
15258      }
15259
15260      [*|att=val] {
15261        color: blue
15262      }
15263    "#,
15264      indoc! {r#"
15265      @namespace "http://example.com/foo";
15266
15267      *|x {
15268        color: red;
15269      }
15270
15271      [*|att="val"] {
15272        color: #00f;
15273      }
15274    "#},
15275    );
15276
15277    error_test(
15278      ".foo { color: red } @namespace \"http://example.com/foo\";",
15279      ParserError::UnexpectedNamespaceRule,
15280    );
15281  }
15282
15283  #[test]
15284  fn test_import() {
15285    minify_test("@import url(foo.css);", "@import \"foo.css\";");
15286    minify_test("@import \"foo.css\";", "@import \"foo.css\";");
15287    minify_test("@import url(foo.css) print;", "@import \"foo.css\" print;");
15288    minify_test("@import \"foo.css\" print;", "@import \"foo.css\" print;");
15289    minify_test(
15290      "@import \"foo.css\" screen and (orientation: landscape);",
15291      "@import \"foo.css\" screen and (orientation:landscape);",
15292    );
15293    minify_test(
15294      "@import url(foo.css) supports(display: flex);",
15295      "@import \"foo.css\" supports(display:flex);",
15296    );
15297    minify_test(
15298      "@import url(foo.css) supports(display: flex) print;",
15299      "@import \"foo.css\" supports(display:flex) print;",
15300    );
15301    minify_test(
15302      "@import url(foo.css) supports(not (display: flex));",
15303      "@import \"foo.css\" supports(not (display:flex));",
15304    );
15305    minify_test(
15306      "@import url(foo.css) supports((display: flex));",
15307      "@import \"foo.css\" supports(display:flex);",
15308    );
15309    minify_test("@charset \"UTF-8\"; @import url(foo.css);", "@import \"foo.css\";");
15310    minify_test("@layer foo; @import url(foo.css);", "@layer foo;@import \"foo.css\";");
15311    error_test(
15312      ".foo { color: red } @import url(bar.css);",
15313      ParserError::UnexpectedImportRule,
15314    );
15315    error_test(
15316      "@namespace \"http://example.com/foo\"; @import url(bar.css);",
15317      ParserError::UnexpectedImportRule,
15318    );
15319    error_test(
15320      "@media print { .foo { color: red }} @import url(bar.css);",
15321      ParserError::UnexpectedImportRule,
15322    );
15323    error_test(
15324      "@layer foo; @import url(foo.css); @layer bar; @import url(bar.css)",
15325      ParserError::UnexpectedImportRule,
15326    );
15327    let warnings = error_recovery_test("@import './actual-styles.css';");
15328    assert_eq!(warnings, vec![]);
15329  }
15330
15331  #[test]
15332  fn test_prefixes() {
15333    prefix_test(
15334      r#"
15335      .foo {
15336        -webkit-transition: opacity 200ms;
15337        -moz-transition: opacity 200ms;
15338        transition: opacity 200ms;
15339      }
15340      "#,
15341      indoc! {r#"
15342      .foo {
15343        transition: opacity .2s;
15344      }
15345      "#},
15346      Browsers {
15347        chrome: Some(95 << 16),
15348        ..Browsers::default()
15349      },
15350    );
15351
15352    prefix_test(
15353      ".foo{transition:opacity 200ms}",
15354      indoc! {r#"
15355      .foo {
15356        -webkit-transition: opacity .2s;
15357        -moz-transition: opacity .2s;
15358        transition: opacity .2s;
15359      }
15360      "#},
15361      Browsers {
15362        safari: Some(5 << 16),
15363        firefox: Some(14 << 16),
15364        ..Browsers::default()
15365      },
15366    );
15367  }
15368
15369  #[test]
15370  fn test_display() {
15371    minify_test(".foo { display: block }", ".foo{display:block}");
15372    minify_test(".foo { display: block flow }", ".foo{display:block}");
15373    minify_test(".foo { display: flow-root }", ".foo{display:flow-root}");
15374    minify_test(".foo { display: block flow-root }", ".foo{display:flow-root}");
15375    minify_test(".foo { display: inline }", ".foo{display:inline}");
15376    minify_test(".foo { display: inline flow }", ".foo{display:inline}");
15377    minify_test(".foo { display: inline-block }", ".foo{display:inline-block}");
15378    minify_test(".foo { display: inline flow-root }", ".foo{display:inline-block}");
15379    minify_test(".foo { display: run-in }", ".foo{display:run-in}");
15380    minify_test(".foo { display: run-in flow }", ".foo{display:run-in}");
15381    minify_test(".foo { display: list-item }", ".foo{display:list-item}");
15382    minify_test(".foo { display: block flow list-item }", ".foo{display:list-item}");
15383    minify_test(".foo { display: inline list-item }", ".foo{display:inline list-item}");
15384    minify_test(
15385      ".foo { display: inline flow list-item }",
15386      ".foo{display:inline list-item}",
15387    );
15388    minify_test(".foo { display: flex }", ".foo{display:flex}");
15389    minify_test(".foo { display: block flex }", ".foo{display:flex}");
15390    minify_test(".foo { display: inline-flex }", ".foo{display:inline-flex}");
15391    minify_test(".foo { display: inline flex }", ".foo{display:inline-flex}");
15392    minify_test(".foo { display: grid }", ".foo{display:grid}");
15393    minify_test(".foo { display: block grid }", ".foo{display:grid}");
15394    minify_test(".foo { display: inline-grid }", ".foo{display:inline-grid}");
15395    minify_test(".foo { display: inline grid }", ".foo{display:inline-grid}");
15396    minify_test(".foo { display: ruby }", ".foo{display:ruby}");
15397    minify_test(".foo { display: inline ruby }", ".foo{display:ruby}");
15398    minify_test(".foo { display: block ruby }", ".foo{display:block ruby}");
15399    minify_test(".foo { display: table }", ".foo{display:table}");
15400    minify_test(".foo { display: block table }", ".foo{display:table}");
15401    minify_test(".foo { display: inline-table }", ".foo{display:inline-table}");
15402    minify_test(".foo { display: inline table }", ".foo{display:inline-table}");
15403    minify_test(".foo { display: table-row-group }", ".foo{display:table-row-group}");
15404    minify_test(".foo { display: contents }", ".foo{display:contents}");
15405    minify_test(".foo { display: none }", ".foo{display:none}");
15406    minify_test(".foo { display: -webkit-flex }", ".foo{display:-webkit-flex}");
15407    minify_test(".foo { display: -ms-flexbox }", ".foo{display:-ms-flexbox}");
15408    minify_test(".foo { display: -webkit-box }", ".foo{display:-webkit-box}");
15409    minify_test(".foo { display: -moz-box }", ".foo{display:-moz-box}");
15410    minify_test(
15411      ".foo { display: -webkit-flex; display: -moz-box; display: flex }",
15412      ".foo{display:-webkit-flex;display:-moz-box;display:flex}",
15413    );
15414    minify_test(
15415      ".foo { display: -webkit-flex; display: flex; display: -moz-box }",
15416      ".foo{display:-webkit-flex;display:flex;display:-moz-box}",
15417    );
15418    minify_test(".foo { display: flex; display: grid }", ".foo{display:grid}");
15419    minify_test(
15420      ".foo { display: -webkit-inline-flex; display: -moz-inline-box; display: inline-flex }",
15421      ".foo{display:-webkit-inline-flex;display:-moz-inline-box;display:inline-flex}",
15422    );
15423    minify_test(
15424      ".foo { display: flex; display: var(--grid); }",
15425      ".foo{display:flex;display:var(--grid)}",
15426    );
15427    prefix_test(
15428      ".foo{ display: flex }",
15429      indoc! {r#"
15430      .foo {
15431        display: -webkit-box;
15432        display: -moz-box;
15433        display: -webkit-flex;
15434        display: -ms-flexbox;
15435        display: flex;
15436      }
15437      "#},
15438      Browsers {
15439        safari: Some(4 << 16),
15440        firefox: Some(14 << 16),
15441        ie: Some(10 << 16),
15442        ..Browsers::default()
15443      },
15444    );
15445    prefix_test(
15446      ".foo{ display: flex; display: -webkit-box; }",
15447      indoc! {r#"
15448      .foo {
15449        display: -webkit-box;
15450      }
15451      "#},
15452      Browsers {
15453        safari: Some(4 << 16),
15454        firefox: Some(14 << 16),
15455        ie: Some(10 << 16),
15456        ..Browsers::default()
15457      },
15458    );
15459    prefix_test(
15460      ".foo{ display: -webkit-box; display: flex; }",
15461      indoc! {r#"
15462      .foo {
15463        display: -webkit-box;
15464        display: -moz-box;
15465        display: -webkit-flex;
15466        display: -ms-flexbox;
15467        display: flex;
15468      }
15469      "#},
15470      Browsers {
15471        safari: Some(4 << 16),
15472        firefox: Some(14 << 16),
15473        ie: Some(10 << 16),
15474        ..Browsers::default()
15475      },
15476    );
15477    prefix_test(
15478      r#"
15479      .foo {
15480        display: -webkit-box;
15481        display: -moz-box;
15482        display: -webkit-flex;
15483        display: -ms-flexbox;
15484        display: flex;
15485      }
15486      "#,
15487      indoc! {r#"
15488      .foo {
15489        display: flex;
15490      }
15491      "#},
15492      Browsers {
15493        safari: Some(14 << 16),
15494        ..Browsers::default()
15495      },
15496    );
15497    prefix_test(
15498      r#"
15499      .foo {
15500        display: -webkit-box;
15501        display: flex;
15502        display: -moz-box;
15503        display: -webkit-flex;
15504        display: -ms-flexbox;
15505      }
15506      "#,
15507      indoc! {r#"
15508      .foo {
15509        display: -moz-box;
15510        display: -webkit-flex;
15511        display: -ms-flexbox;
15512      }
15513      "#},
15514      Browsers {
15515        safari: Some(14 << 16),
15516        ..Browsers::default()
15517      },
15518    );
15519    prefix_test(
15520      ".foo{ display: inline-flex }",
15521      indoc! {r#"
15522      .foo {
15523        display: -webkit-inline-box;
15524        display: -moz-inline-box;
15525        display: -webkit-inline-flex;
15526        display: -ms-inline-flexbox;
15527        display: inline-flex;
15528      }
15529      "#},
15530      Browsers {
15531        safari: Some(4 << 16),
15532        firefox: Some(14 << 16),
15533        ie: Some(10 << 16),
15534        ..Browsers::default()
15535      },
15536    );
15537    prefix_test(
15538      r#"
15539      .foo {
15540        display: -webkit-inline-box;
15541        display: -moz-inline-box;
15542        display: -webkit-inline-flex;
15543        display: -ms-inline-flexbox;
15544        display: inline-flex;
15545      }
15546      "#,
15547      indoc! {r#"
15548      .foo {
15549        display: inline-flex;
15550      }
15551      "#},
15552      Browsers {
15553        safari: Some(14 << 16),
15554        ..Browsers::default()
15555      },
15556    );
15557  }
15558
15559  #[test]
15560  fn test_visibility() {
15561    minify_test(".foo { visibility: visible }", ".foo{visibility:visible}");
15562    minify_test(".foo { visibility: hidden }", ".foo{visibility:hidden}");
15563    minify_test(".foo { visibility: collapse }", ".foo{visibility:collapse}");
15564    minify_test(".foo { visibility: Visible }", ".foo{visibility:visible}");
15565  }
15566
15567  #[test]
15568  fn test_text_transform() {
15569    minify_test(".foo { text-transform: uppercase }", ".foo{text-transform:uppercase}");
15570    minify_test(".foo { text-transform: lowercase }", ".foo{text-transform:lowercase}");
15571    minify_test(".foo { text-transform: capitalize }", ".foo{text-transform:capitalize}");
15572    minify_test(".foo { text-transform: none }", ".foo{text-transform:none}");
15573    minify_test(".foo { text-transform: full-width }", ".foo{text-transform:full-width}");
15574    minify_test(
15575      ".foo { text-transform: full-size-kana }",
15576      ".foo{text-transform:full-size-kana}",
15577    );
15578    minify_test(
15579      ".foo { text-transform: uppercase full-width }",
15580      ".foo{text-transform:uppercase full-width}",
15581    );
15582    minify_test(
15583      ".foo { text-transform: full-width uppercase }",
15584      ".foo{text-transform:uppercase full-width}",
15585    );
15586    minify_test(
15587      ".foo { text-transform: uppercase full-width full-size-kana }",
15588      ".foo{text-transform:uppercase full-width full-size-kana}",
15589    );
15590    minify_test(
15591      ".foo { text-transform: full-width uppercase full-size-kana }",
15592      ".foo{text-transform:uppercase full-width full-size-kana}",
15593    );
15594  }
15595
15596  #[test]
15597  fn test_whitespace() {
15598    minify_test(".foo { white-space: normal }", ".foo{white-space:normal}");
15599    minify_test(".foo { white-space: pre }", ".foo{white-space:pre}");
15600    minify_test(".foo { white-space: nowrap }", ".foo{white-space:nowrap}");
15601    minify_test(".foo { white-space: pre-wrap }", ".foo{white-space:pre-wrap}");
15602    minify_test(".foo { white-space: break-spaces }", ".foo{white-space:break-spaces}");
15603    minify_test(".foo { white-space: pre-line }", ".foo{white-space:pre-line}");
15604    minify_test(".foo { white-space: NoWrAp }", ".foo{white-space:nowrap}");
15605  }
15606
15607  #[test]
15608  fn test_tab_size() {
15609    minify_test(".foo { tab-size: 8 }", ".foo{tab-size:8}");
15610    minify_test(".foo { tab-size: 4px }", ".foo{tab-size:4px}");
15611    minify_test(".foo { -moz-tab-size: 4px }", ".foo{-moz-tab-size:4px}");
15612    minify_test(".foo { -o-tab-size: 4px }", ".foo{-o-tab-size:4px}");
15613    prefix_test(
15614      ".foo{ tab-size: 4 }",
15615      indoc! {r#"
15616      .foo {
15617        -moz-tab-size: 4;
15618        -o-tab-size: 4;
15619        tab-size: 4;
15620      }
15621      "#},
15622      Browsers {
15623        safari: Some(8 << 16),
15624        firefox: Some(50 << 16),
15625        opera: Some(12 << 16),
15626        ..Browsers::default()
15627      },
15628    );
15629    prefix_test(
15630      r#"
15631      .foo {
15632        -moz-tab-size: 4;
15633        -o-tab-size: 4;
15634        tab-size: 4;
15635      }
15636      "#,
15637      indoc! {r#"
15638      .foo {
15639        tab-size: 4;
15640      }
15641      "#},
15642      Browsers {
15643        safari: Some(8 << 16),
15644        firefox: Some(94 << 16),
15645        opera: Some(30 << 16),
15646        ..Browsers::default()
15647      },
15648    );
15649  }
15650
15651  #[test]
15652  fn test_word_break() {
15653    minify_test(".foo { word-break: normal }", ".foo{word-break:normal}");
15654    minify_test(".foo { word-break: keep-all }", ".foo{word-break:keep-all}");
15655    minify_test(".foo { word-break: break-all }", ".foo{word-break:break-all}");
15656    minify_test(".foo { word-break: break-word }", ".foo{word-break:break-word}");
15657  }
15658
15659  #[test]
15660  fn test_line_break() {
15661    minify_test(".foo { line-break: auto }", ".foo{line-break:auto}");
15662    minify_test(".foo { line-break: Loose }", ".foo{line-break:loose}");
15663    minify_test(".foo { line-break: anywhere }", ".foo{line-break:anywhere}");
15664  }
15665
15666  #[test]
15667  fn test_wrap() {
15668    minify_test(".foo { overflow-wrap: nOrmal }", ".foo{overflow-wrap:normal}");
15669    minify_test(".foo { overflow-wrap: break-Word }", ".foo{overflow-wrap:break-word}");
15670    minify_test(".foo { overflow-wrap: Anywhere }", ".foo{overflow-wrap:anywhere}");
15671    minify_test(".foo { word-wrap: Normal }", ".foo{word-wrap:normal}");
15672    minify_test(".foo { word-wrap: Break-wOrd }", ".foo{word-wrap:break-word}");
15673    minify_test(".foo { word-wrap: Anywhere }", ".foo{word-wrap:anywhere}");
15674  }
15675
15676  #[test]
15677  fn test_hyphens() {
15678    minify_test(".foo { hyphens: manual }", ".foo{hyphens:manual}");
15679    minify_test(".foo { hyphens: auto }", ".foo{hyphens:auto}");
15680    minify_test(".foo { hyphens: none }", ".foo{hyphens:none}");
15681    minify_test(".foo { -webkit-hyphens: manual }", ".foo{-webkit-hyphens:manual}");
15682    minify_test(".foo { -moz-hyphens: manual }", ".foo{-moz-hyphens:manual}");
15683    minify_test(".foo { -ms-hyphens: manual }", ".foo{-ms-hyphens:manual}");
15684    prefix_test(
15685      ".foo{ hyphens: manual }",
15686      indoc! {r#"
15687      .foo {
15688        -webkit-hyphens: manual;
15689        -moz-hyphens: manual;
15690        -ms-hyphens: manual;
15691        hyphens: manual;
15692      }
15693      "#},
15694      Browsers {
15695        safari: Some(14 << 16),
15696        firefox: Some(40 << 16),
15697        ie: Some(10 << 16),
15698        ..Browsers::default()
15699      },
15700    );
15701    prefix_test(
15702      r#"
15703      .foo {
15704        -webkit-hyphens: manual;
15705        -moz-hyphens: manual;
15706        -ms-hyphens: manual;
15707        hyphens: manual;
15708      }
15709      "#,
15710      indoc! {r#"
15711      .foo {
15712        -webkit-hyphens: manual;
15713        hyphens: manual;
15714      }
15715      "#},
15716      Browsers {
15717        safari: Some(14 << 16),
15718        chrome: Some(88 << 16),
15719        firefox: Some(88 << 16),
15720        edge: Some(79 << 16),
15721        ..Browsers::default()
15722      },
15723    );
15724    prefix_test(
15725      r#"
15726      .foo {
15727        -webkit-hyphens: manual;
15728        -moz-hyphens: manual;
15729        -ms-hyphens: manual;
15730        hyphens: manual;
15731      }
15732      "#,
15733      indoc! {r#"
15734      .foo {
15735        hyphens: manual;
15736      }
15737      "#},
15738      Browsers {
15739        chrome: Some(88 << 16),
15740        firefox: Some(88 << 16),
15741        edge: Some(79 << 16),
15742        ..Browsers::default()
15743      },
15744    );
15745  }
15746
15747  #[test]
15748  fn test_text_align() {
15749    minify_test(".foo { text-align: left }", ".foo{text-align:left}");
15750    minify_test(".foo { text-align: Left }", ".foo{text-align:left}");
15751    minify_test(".foo { text-align: END }", ".foo{text-align:end}");
15752    minify_test(".foo { text-align: left }", ".foo{text-align:left}");
15753
15754    prefix_test(
15755      r#"
15756      .foo {
15757        text-align: start;
15758      }
15759    "#,
15760      indoc! {r#"
15761      .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))) {
15762        text-align: left;
15763      }
15764
15765      .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)) {
15766        text-align: right;
15767      }
15768    "#
15769      },
15770      Browsers {
15771        safari: Some(2 << 16),
15772        ..Browsers::default()
15773      },
15774    );
15775
15776    prefix_test(
15777      r#"
15778      .foo {
15779        text-align: end;
15780      }
15781    "#,
15782      indoc! {r#"
15783      .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))) {
15784        text-align: right;
15785      }
15786
15787      .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)) {
15788        text-align: left;
15789      }
15790    "#
15791      },
15792      Browsers {
15793        safari: Some(2 << 16),
15794        ..Browsers::default()
15795      },
15796    );
15797
15798    prefix_test(
15799      r#"
15800      .foo {
15801        text-align: start;
15802      }
15803    "#,
15804      indoc! {r#"
15805      .foo {
15806        text-align: start;
15807      }
15808    "#
15809      },
15810      Browsers {
15811        safari: Some(14 << 16),
15812        ..Browsers::default()
15813      },
15814    );
15815
15816    prefix_test(
15817      r#"
15818      .foo > .bar {
15819        text-align: start;
15820      }
15821    "#,
15822      indoc! {r#"
15823      .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))) {
15824        text-align: left;
15825      }
15826
15827      .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)) {
15828        text-align: right;
15829      }
15830    "#
15831      },
15832      Browsers {
15833        safari: Some(2 << 16),
15834        ..Browsers::default()
15835      },
15836    );
15837
15838    prefix_test(
15839      r#"
15840      .foo:after {
15841        text-align: start;
15842      }
15843    "#,
15844      indoc! {r#"
15845      .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 {
15846        text-align: left;
15847      }
15848
15849      .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 {
15850        text-align: right;
15851      }
15852    "#
15853      },
15854      Browsers {
15855        safari: Some(2 << 16),
15856        ..Browsers::default()
15857      },
15858    );
15859
15860    prefix_test(
15861      r#"
15862      .foo:hover {
15863        text-align: start;
15864      }
15865    "#,
15866      indoc! {r#"
15867      .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))) {
15868        text-align: left;
15869      }
15870
15871      .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)) {
15872        text-align: right;
15873      }
15874    "#
15875      },
15876      Browsers {
15877        safari: Some(2 << 16),
15878        ..Browsers::default()
15879      },
15880    );
15881  }
15882
15883  #[test]
15884  fn test_text_align_last() {
15885    minify_test(".foo { text-align-last: left }", ".foo{text-align-last:left}");
15886    minify_test(".foo { text-align-last: justify }", ".foo{text-align-last:justify}");
15887    prefix_test(
15888      ".foo{ text-align-last: left }",
15889      indoc! {r#"
15890      .foo {
15891        -moz-text-align-last: left;
15892        text-align-last: left;
15893      }
15894      "#},
15895      Browsers {
15896        firefox: Some(40 << 16),
15897        ..Browsers::default()
15898      },
15899    );
15900    prefix_test(
15901      r#"
15902      .foo {
15903        -moz-text-align-last: left;
15904        text-align-last: left;
15905      }
15906      "#,
15907      indoc! {r#"
15908      .foo {
15909        text-align-last: left;
15910      }
15911      "#},
15912      Browsers {
15913        firefox: Some(88 << 16),
15914        ..Browsers::default()
15915      },
15916    );
15917  }
15918
15919  #[test]
15920  fn test_text_justify() {
15921    minify_test(".foo { text-justify: auto }", ".foo{text-justify:auto}");
15922    minify_test(".foo { text-justify: inter-word }", ".foo{text-justify:inter-word}");
15923  }
15924
15925  #[test]
15926  fn test_word_spacing() {
15927    minify_test(".foo { word-spacing: normal }", ".foo{word-spacing:normal}");
15928    minify_test(".foo { word-spacing: 3px }", ".foo{word-spacing:3px}");
15929  }
15930
15931  #[test]
15932  fn test_letter_spacing() {
15933    minify_test(".foo { letter-spacing: normal }", ".foo{letter-spacing:normal}");
15934    minify_test(".foo { letter-spacing: 3px }", ".foo{letter-spacing:3px}");
15935  }
15936
15937  #[test]
15938  fn test_text_indent() {
15939    minify_test(".foo { text-indent: 20px }", ".foo{text-indent:20px}");
15940    minify_test(".foo { text-indent: 10% }", ".foo{text-indent:10%}");
15941    minify_test(".foo { text-indent: 3em hanging }", ".foo{text-indent:3em hanging}");
15942    minify_test(".foo { text-indent: 3em each-line }", ".foo{text-indent:3em each-line}");
15943    minify_test(
15944      ".foo { text-indent: 3em hanging each-line }",
15945      ".foo{text-indent:3em hanging each-line}",
15946    );
15947    minify_test(
15948      ".foo { text-indent: 3em each-line hanging }",
15949      ".foo{text-indent:3em hanging each-line}",
15950    );
15951    minify_test(
15952      ".foo { text-indent: each-line 3em hanging }",
15953      ".foo{text-indent:3em hanging each-line}",
15954    );
15955    minify_test(
15956      ".foo { text-indent: each-line hanging 3em }",
15957      ".foo{text-indent:3em hanging each-line}",
15958    );
15959  }
15960
15961  #[test]
15962  fn test_text_size_adjust() {
15963    minify_test(".foo { text-size-adjust: none }", ".foo{text-size-adjust:none}");
15964    minify_test(".foo { text-size-adjust: auto }", ".foo{text-size-adjust:auto}");
15965    minify_test(".foo { text-size-adjust: 80% }", ".foo{text-size-adjust:80%}");
15966    prefix_test(
15967      r#"
15968      .foo {
15969        text-size-adjust: none;
15970      }
15971    "#,
15972      indoc! {r#"
15973      .foo {
15974        -webkit-text-size-adjust: none;
15975        -moz-text-size-adjust: none;
15976        -ms-text-size-adjust: none;
15977        text-size-adjust: none;
15978      }
15979    "#},
15980      Browsers {
15981        ios_saf: Some(16 << 16),
15982        edge: Some(15 << 16),
15983        firefox: Some(20 << 16),
15984        ..Browsers::default()
15985      },
15986    );
15987    prefix_test(
15988      r#"
15989      .foo {
15990        -webkit-text-size-adjust: none;
15991        -moz-text-size-adjust: none;
15992        -ms-text-size-adjust: none;
15993        text-size-adjust: none;
15994      }
15995    "#,
15996      indoc! {r#"
15997      .foo {
15998        text-size-adjust: none;
15999      }
16000    "#},
16001      Browsers {
16002        chrome: Some(110 << 16),
16003        ..Browsers::default()
16004      },
16005    );
16006  }
16007
16008  #[test]
16009  fn test_text_decoration() {
16010    minify_test(".foo { text-decoration-line: none }", ".foo{text-decoration-line:none}");
16011    minify_test(
16012      ".foo { text-decoration-line: underline }",
16013      ".foo{text-decoration-line:underline}",
16014    );
16015    minify_test(
16016      ".foo { text-decoration-line: overline }",
16017      ".foo{text-decoration-line:overline}",
16018    );
16019    minify_test(
16020      ".foo { text-decoration-line: line-through }",
16021      ".foo{text-decoration-line:line-through}",
16022    );
16023    minify_test(
16024      ".foo { text-decoration-line: blink }",
16025      ".foo{text-decoration-line:blink}",
16026    );
16027    minify_test(
16028      ".foo { text-decoration-line: underline overline }",
16029      ".foo{text-decoration-line:underline overline}",
16030    );
16031    minify_test(
16032      ".foo { text-decoration-line: overline underline }",
16033      ".foo{text-decoration-line:underline overline}",
16034    );
16035    minify_test(
16036      ".foo { text-decoration-line: overline line-through underline }",
16037      ".foo{text-decoration-line:underline overline line-through}",
16038    );
16039    minify_test(
16040      ".foo { text-decoration-line: spelling-error }",
16041      ".foo{text-decoration-line:spelling-error}",
16042    );
16043    minify_test(
16044      ".foo { text-decoration-line: grammar-error }",
16045      ".foo{text-decoration-line:grammar-error}",
16046    );
16047    minify_test(
16048      ".foo { -webkit-text-decoration-line: overline underline }",
16049      ".foo{-webkit-text-decoration-line:underline overline}",
16050    );
16051    minify_test(
16052      ".foo { -moz-text-decoration-line: overline underline }",
16053      ".foo{-moz-text-decoration-line:underline overline}",
16054    );
16055
16056    minify_test(
16057      ".foo { text-decoration-style: solid }",
16058      ".foo{text-decoration-style:solid}",
16059    );
16060    minify_test(
16061      ".foo { text-decoration-style: dotted }",
16062      ".foo{text-decoration-style:dotted}",
16063    );
16064    minify_test(
16065      ".foo { -webkit-text-decoration-style: solid }",
16066      ".foo{-webkit-text-decoration-style:solid}",
16067    );
16068
16069    minify_test(
16070      ".foo { text-decoration-color: yellow }",
16071      ".foo{text-decoration-color:#ff0}",
16072    );
16073    minify_test(
16074      ".foo { -webkit-text-decoration-color: yellow }",
16075      ".foo{-webkit-text-decoration-color:#ff0}",
16076    );
16077
16078    minify_test(".foo { text-decoration: none }", ".foo{text-decoration:none}");
16079    minify_test(
16080      ".foo { text-decoration: underline dotted }",
16081      ".foo{text-decoration:underline dotted}",
16082    );
16083    minify_test(
16084      ".foo { text-decoration: underline dotted yellow }",
16085      ".foo{text-decoration:underline dotted #ff0}",
16086    );
16087    minify_test(
16088      ".foo { text-decoration: yellow dotted underline }",
16089      ".foo{text-decoration:underline dotted #ff0}",
16090    );
16091    minify_test(
16092      ".foo { text-decoration: underline overline dotted yellow }",
16093      ".foo{text-decoration:underline overline dotted #ff0}",
16094    );
16095    minify_test(
16096      ".foo { -webkit-text-decoration: yellow dotted underline }",
16097      ".foo{-webkit-text-decoration:underline dotted #ff0}",
16098    );
16099    minify_test(
16100      ".foo { -moz-text-decoration: yellow dotted underline }",
16101      ".foo{-moz-text-decoration:underline dotted #ff0}",
16102    );
16103
16104    test(
16105      r#"
16106      .foo {
16107        text-decoration-line: underline;
16108        text-decoration-style: dotted;
16109        text-decoration-color: yellow;
16110        text-decoration-thickness: 2px;
16111      }
16112    "#,
16113      indoc! {r#"
16114      .foo {
16115        text-decoration: underline 2px dotted #ff0;
16116      }
16117    "#},
16118    );
16119
16120    test(
16121      r#"
16122      .foo {
16123        text-decoration: underline;
16124        text-decoration-style: dotted;
16125      }
16126    "#,
16127      indoc! {r#"
16128      .foo {
16129        text-decoration: underline dotted;
16130      }
16131    "#},
16132    );
16133
16134    test(
16135      r#"
16136      .foo {
16137        text-decoration: underline;
16138        text-decoration-style: var(--style);
16139      }
16140    "#,
16141      indoc! {r#"
16142      .foo {
16143        text-decoration: underline;
16144        text-decoration-style: var(--style);
16145      }
16146    "#},
16147    );
16148
16149    test(
16150      r#"
16151      .foo {
16152        -webkit-text-decoration: underline;
16153        -webkit-text-decoration-style: dotted;
16154      }
16155    "#,
16156      indoc! {r#"
16157      .foo {
16158        -webkit-text-decoration: underline dotted;
16159      }
16160    "#},
16161    );
16162
16163    prefix_test(
16164      r#"
16165      .foo {
16166        text-decoration: underline dotted;
16167      }
16168    "#,
16169      indoc! {r#"
16170      .foo {
16171        -webkit-text-decoration: underline dotted;
16172        text-decoration: underline dotted;
16173      }
16174    "#},
16175      Browsers {
16176        safari: Some(8 << 16),
16177        firefox: Some(30 << 16),
16178        ..Browsers::default()
16179      },
16180    );
16181
16182    prefix_test(
16183      r#"
16184      .foo {
16185        text-decoration-line: underline;
16186      }
16187    "#,
16188      indoc! {r#"
16189      .foo {
16190        -webkit-text-decoration-line: underline;
16191        -moz-text-decoration-line: underline;
16192        text-decoration-line: underline;
16193      }
16194    "#},
16195      Browsers {
16196        safari: Some(8 << 16),
16197        firefox: Some(30 << 16),
16198        ..Browsers::default()
16199      },
16200    );
16201
16202    prefix_test(
16203      r#"
16204      .foo {
16205        text-decoration-style: dotted;
16206      }
16207    "#,
16208      indoc! {r#"
16209      .foo {
16210        -webkit-text-decoration-style: dotted;
16211        -moz-text-decoration-style: dotted;
16212        text-decoration-style: dotted;
16213      }
16214    "#},
16215      Browsers {
16216        safari: Some(8 << 16),
16217        firefox: Some(30 << 16),
16218        ..Browsers::default()
16219      },
16220    );
16221
16222    prefix_test(
16223      r#"
16224      .foo {
16225        text-decoration-color: yellow;
16226      }
16227    "#,
16228      indoc! {r#"
16229      .foo {
16230        -webkit-text-decoration-color: #ff0;
16231        -moz-text-decoration-color: #ff0;
16232        text-decoration-color: #ff0;
16233      }
16234    "#},
16235      Browsers {
16236        safari: Some(8 << 16),
16237        firefox: Some(30 << 16),
16238        ..Browsers::default()
16239      },
16240    );
16241
16242    prefix_test(
16243      r#"
16244      .foo {
16245        text-decoration: underline;
16246      }
16247    "#,
16248      indoc! {r#"
16249      .foo {
16250        text-decoration: underline;
16251      }
16252    "#},
16253      Browsers {
16254        safari: Some(8 << 16),
16255        firefox: Some(30 << 16),
16256        ..Browsers::default()
16257      },
16258    );
16259
16260    prefix_test(
16261      r#"
16262      .foo {
16263        -webkit-text-decoration: underline dotted;
16264        text-decoration: underline dotted;
16265      }
16266    "#,
16267      indoc! {r#"
16268      .foo {
16269        -webkit-text-decoration: underline dotted;
16270        text-decoration: underline dotted;
16271      }
16272    "#},
16273      Browsers {
16274        safari: Some(14 << 16),
16275        firefox: Some(45 << 16),
16276        ..Browsers::default()
16277      },
16278    );
16279
16280    prefix_test(
16281      r#"
16282      .foo {
16283        text-decoration: double underline;
16284      }
16285    "#,
16286      indoc! {r#"
16287      .foo {
16288        -webkit-text-decoration: underline double;
16289        text-decoration: underline double;
16290      }
16291    "#},
16292      Browsers {
16293        safari: Some(16 << 16),
16294        ..Browsers::default()
16295      },
16296    );
16297
16298    prefix_test(
16299      r#"
16300      .foo {
16301        text-decoration: underline;
16302        text-decoration-style: double;
16303      }
16304    "#,
16305      indoc! {r#"
16306      .foo {
16307        -webkit-text-decoration: underline double;
16308        text-decoration: underline double;
16309      }
16310    "#},
16311      Browsers {
16312        safari: Some(16 << 16),
16313        ..Browsers::default()
16314      },
16315    );
16316
16317    prefix_test(
16318      r#"
16319      .foo {
16320        text-decoration: underline;
16321        text-decoration-color: red;
16322      }
16323    "#,
16324      indoc! {r#"
16325      .foo {
16326        -webkit-text-decoration: underline red;
16327        text-decoration: underline red;
16328      }
16329    "#},
16330      Browsers {
16331        safari: Some(16 << 16),
16332        ..Browsers::default()
16333      },
16334    );
16335
16336    prefix_test(
16337      r#"
16338      .foo {
16339        text-decoration: var(--test);
16340      }
16341    "#,
16342      indoc! {r#"
16343      .foo {
16344        -webkit-text-decoration: var(--test);
16345        text-decoration: var(--test);
16346      }
16347    "#},
16348      Browsers {
16349        safari: Some(8 << 16),
16350        firefox: Some(30 << 16),
16351        ..Browsers::default()
16352      },
16353    );
16354
16355    minify_test(
16356      ".foo { text-decoration-skip-ink: all }",
16357      ".foo{text-decoration-skip-ink:all}",
16358    );
16359    minify_test(
16360      ".foo { -webkit-text-decoration-skip-ink: all }",
16361      ".foo{-webkit-text-decoration-skip-ink:all}",
16362    );
16363
16364    prefix_test(
16365      r#"
16366      .foo {
16367        text-decoration: lch(50.998% 135.363 338) underline;
16368      }
16369    "#,
16370      indoc! {r#"
16371      .foo {
16372        -webkit-text-decoration: underline #ee00be;
16373        text-decoration: underline #ee00be;
16374        -webkit-text-decoration: underline lch(50.998% 135.363 338);
16375        text-decoration: underline lch(50.998% 135.363 338);
16376      }
16377    "#},
16378      Browsers {
16379        safari: Some(8 << 16),
16380        firefox: Some(30 << 16),
16381        ..Browsers::default()
16382      },
16383    );
16384
16385    prefix_test(
16386      r#"
16387      .foo {
16388        text-decoration-color: lch(50.998% 135.363 338);
16389      }
16390    "#,
16391      indoc! {r#"
16392      .foo {
16393        -webkit-text-decoration-color: #ee00be;
16394        -moz-text-decoration-color: #ee00be;
16395        text-decoration-color: #ee00be;
16396        -webkit-text-decoration-color: lch(50.998% 135.363 338);
16397        -moz-text-decoration-color: lch(50.998% 135.363 338);
16398        text-decoration-color: lch(50.998% 135.363 338);
16399      }
16400    "#},
16401      Browsers {
16402        safari: Some(8 << 16),
16403        firefox: Some(30 << 16),
16404        ..Browsers::default()
16405      },
16406    );
16407
16408    prefix_test(
16409      r#"
16410      .foo {
16411        text-decoration: lch(50.998% 135.363 338) var(--style);
16412      }
16413    "#,
16414      indoc! {r#"
16415      .foo {
16416        text-decoration: #ee00be var(--style);
16417      }
16418
16419      @supports (color: lab(0% 0 0)) {
16420        .foo {
16421          text-decoration: lab(50.998% 125.506 -50.7078) var(--style);
16422        }
16423      }
16424    "#},
16425      Browsers {
16426        chrome: Some(90 << 16),
16427        ..Browsers::default()
16428      },
16429    );
16430
16431    prefix_test(
16432      r#"
16433      @supports (color: lab(0% 0 0)) {
16434        .foo {
16435          text-decoration: lab(50.998% 125.506 -50.7078) var(--style);
16436        }
16437      }
16438    "#,
16439      indoc! {r#"
16440      @supports (color: lab(0% 0 0)) {
16441        .foo {
16442          text-decoration: lab(50.998% 125.506 -50.7078) var(--style);
16443        }
16444      }
16445    "#},
16446      Browsers {
16447        chrome: Some(90 << 16),
16448        ..Browsers::default()
16449      },
16450    );
16451
16452    prefix_test(
16453      r#"
16454      .foo {
16455        text-decoration: underline 10px;
16456      }
16457    "#,
16458      indoc! {r#"
16459      .foo {
16460        text-decoration: underline;
16461        text-decoration-thickness: 10px;
16462      }
16463    "#},
16464      Browsers {
16465        safari: Some(15 << 16),
16466        ..Browsers::default()
16467      },
16468    );
16469
16470    prefix_test(
16471      r#"
16472      .foo {
16473        text-decoration: underline 10px;
16474      }
16475    "#,
16476      indoc! {r#"
16477      .foo {
16478        text-decoration: underline 10px;
16479      }
16480    "#},
16481      Browsers {
16482        chrome: Some(90 << 16),
16483        ..Browsers::default()
16484      },
16485    );
16486
16487    prefix_test(
16488      r#"
16489      .foo {
16490        text-decoration: underline 10%;
16491      }
16492    "#,
16493      indoc! {r#"
16494      .foo {
16495        text-decoration: underline;
16496        text-decoration-thickness: calc(1em / 10);
16497      }
16498    "#},
16499      Browsers {
16500        safari: Some(12 << 16),
16501        ..Browsers::default()
16502      },
16503    );
16504
16505    prefix_test(
16506      r#"
16507      .foo {
16508        text-decoration: underline 10%;
16509      }
16510    "#,
16511      indoc! {r#"
16512      .foo {
16513        text-decoration: underline 10%;
16514      }
16515    "#},
16516      Browsers {
16517        firefox: Some(89 << 16),
16518        ..Browsers::default()
16519      },
16520    );
16521
16522    prefix_test(
16523      r#"
16524      .foo {
16525        text-decoration-thickness: 10%;
16526      }
16527    "#,
16528      indoc! {r#"
16529      .foo {
16530        text-decoration-thickness: calc(1em / 10);
16531      }
16532    "#},
16533      Browsers {
16534        safari: Some(12 << 16),
16535        ..Browsers::default()
16536      },
16537    );
16538
16539    prefix_test(
16540      r#"
16541      .foo {
16542        text-decoration-thickness: 10%;
16543      }
16544    "#,
16545      indoc! {r#"
16546      .foo {
16547        text-decoration-thickness: 10%;
16548      }
16549    "#},
16550      Browsers {
16551        firefox: Some(89 << 16),
16552        ..Browsers::default()
16553      },
16554    );
16555  }
16556
16557  #[test]
16558  fn test_text_emphasis() {
16559    minify_test(".foo { text-emphasis-style: none }", ".foo{text-emphasis-style:none}");
16560    minify_test(
16561      ".foo { text-emphasis-style: filled }",
16562      ".foo{text-emphasis-style:filled}",
16563    );
16564    minify_test(".foo { text-emphasis-style: open }", ".foo{text-emphasis-style:open}");
16565    minify_test(".foo { text-emphasis-style: dot }", ".foo{text-emphasis-style:dot}");
16566    minify_test(
16567      ".foo { text-emphasis-style: filled dot }",
16568      ".foo{text-emphasis-style:dot}",
16569    );
16570    minify_test(
16571      ".foo { text-emphasis-style: dot filled }",
16572      ".foo{text-emphasis-style:dot}",
16573    );
16574    minify_test(
16575      ".foo { text-emphasis-style: open dot }",
16576      ".foo{text-emphasis-style:open dot}",
16577    );
16578    minify_test(
16579      ".foo { text-emphasis-style: dot open }",
16580      ".foo{text-emphasis-style:open dot}",
16581    );
16582    minify_test(".foo { text-emphasis-style: \"x\" }", ".foo{text-emphasis-style:\"x\"}");
16583
16584    minify_test(".foo { text-emphasis-color: yellow }", ".foo{text-emphasis-color:#ff0}");
16585
16586    minify_test(".foo { text-emphasis: none }", ".foo{text-emphasis:none}");
16587    minify_test(".foo { text-emphasis: filled }", ".foo{text-emphasis:filled}");
16588    minify_test(
16589      ".foo { text-emphasis: filled yellow }",
16590      ".foo{text-emphasis:filled #ff0}",
16591    );
16592    minify_test(
16593      ".foo { text-emphasis: dot filled yellow }",
16594      ".foo{text-emphasis:dot #ff0}",
16595    );
16596
16597    test(
16598      r#"
16599      .foo {
16600        text-emphasis-style: filled;
16601        text-emphasis-color: yellow;
16602      }
16603    "#,
16604      indoc! {r#"
16605      .foo {
16606        text-emphasis: filled #ff0;
16607      }
16608    "#},
16609    );
16610
16611    test(
16612      r#"
16613      .foo {
16614        text-emphasis: filled red;
16615        text-emphasis-color: yellow;
16616      }
16617    "#,
16618      indoc! {r#"
16619      .foo {
16620        text-emphasis: filled #ff0;
16621      }
16622    "#},
16623    );
16624
16625    test(
16626      r#"
16627      .foo {
16628        text-emphasis: filled yellow;
16629        text-emphasis-color: var(--color);
16630      }
16631    "#,
16632      indoc! {r#"
16633      .foo {
16634        text-emphasis: filled #ff0;
16635        text-emphasis-color: var(--color);
16636      }
16637    "#},
16638    );
16639
16640    prefix_test(
16641      r#"
16642      .foo {
16643        text-emphasis-style: filled;
16644      }
16645    "#,
16646      indoc! {r#"
16647      .foo {
16648        -webkit-text-emphasis-style: filled;
16649        text-emphasis-style: filled;
16650      }
16651    "#},
16652      Browsers {
16653        safari: Some(10 << 16),
16654        chrome: Some(30 << 16),
16655        firefox: Some(45 << 16),
16656        ..Browsers::default()
16657      },
16658    );
16659
16660    prefix_test(
16661      r#"
16662      .foo {
16663        -webkit-text-emphasis-style: filled;
16664        text-emphasis-style: filled;
16665      }
16666    "#,
16667      indoc! {r#"
16668      .foo {
16669        text-emphasis-style: filled;
16670      }
16671    "#},
16672      Browsers {
16673        safari: Some(10 << 16),
16674        firefox: Some(45 << 16),
16675        ..Browsers::default()
16676      },
16677    );
16678
16679    minify_test(
16680      ".foo { text-emphasis-position: over }",
16681      ".foo{text-emphasis-position:over}",
16682    );
16683    minify_test(
16684      ".foo { text-emphasis-position: under }",
16685      ".foo{text-emphasis-position:under}",
16686    );
16687    minify_test(
16688      ".foo { text-emphasis-position: over right }",
16689      ".foo{text-emphasis-position:over}",
16690    );
16691    minify_test(
16692      ".foo { text-emphasis-position: over left }",
16693      ".foo{text-emphasis-position:over left}",
16694    );
16695
16696    prefix_test(
16697      r#"
16698      .foo {
16699        text-emphasis-position: over;
16700      }
16701    "#,
16702      indoc! {r#"
16703      .foo {
16704        -webkit-text-emphasis-position: over;
16705        text-emphasis-position: over;
16706      }
16707    "#},
16708      Browsers {
16709        safari: Some(10 << 16),
16710        chrome: Some(30 << 16),
16711        firefox: Some(45 << 16),
16712        ..Browsers::default()
16713      },
16714    );
16715
16716    prefix_test(
16717      r#"
16718      .foo {
16719        text-emphasis-position: over left;
16720      }
16721    "#,
16722      indoc! {r#"
16723      .foo {
16724        text-emphasis-position: over left;
16725      }
16726    "#},
16727      Browsers {
16728        safari: Some(10 << 16),
16729        chrome: Some(30 << 16),
16730        firefox: Some(45 << 16),
16731        ..Browsers::default()
16732      },
16733    );
16734
16735    prefix_test(
16736      r#"
16737      .foo {
16738        text-emphasis-position: var(--test);
16739      }
16740    "#,
16741      indoc! {r#"
16742      .foo {
16743        -webkit-text-emphasis-position: var(--test);
16744        text-emphasis-position: var(--test);
16745      }
16746    "#},
16747      Browsers {
16748        safari: Some(10 << 16),
16749        chrome: Some(30 << 16),
16750        firefox: Some(45 << 16),
16751        ..Browsers::default()
16752      },
16753    );
16754
16755    prefix_test(
16756      r#"
16757      .foo {
16758        text-emphasis: filled lch(50.998% 135.363 338);
16759      }
16760    "#,
16761      indoc! {r#"
16762      .foo {
16763        -webkit-text-emphasis: filled #ee00be;
16764        text-emphasis: filled #ee00be;
16765        -webkit-text-emphasis: filled lch(50.998% 135.363 338);
16766        text-emphasis: filled lch(50.998% 135.363 338);
16767      }
16768    "#},
16769      Browsers {
16770        chrome: Some(25 << 16),
16771        firefox: Some(48 << 16),
16772        ..Browsers::default()
16773      },
16774    );
16775
16776    prefix_test(
16777      r#"
16778      .foo {
16779        text-emphasis-color: lch(50.998% 135.363 338);
16780      }
16781    "#,
16782      indoc! {r#"
16783      .foo {
16784        -webkit-text-emphasis-color: #ee00be;
16785        text-emphasis-color: #ee00be;
16786        -webkit-text-emphasis-color: lch(50.998% 135.363 338);
16787        text-emphasis-color: lch(50.998% 135.363 338);
16788      }
16789    "#},
16790      Browsers {
16791        chrome: Some(25 << 16),
16792        firefox: Some(48 << 16),
16793        ..Browsers::default()
16794      },
16795    );
16796
16797    prefix_test(
16798      r#"
16799      .foo {
16800        text-emphasis: lch(50.998% 135.363 338) var(--style);
16801      }
16802    "#,
16803      indoc! {r#"
16804      .foo {
16805        text-emphasis: #ee00be var(--style);
16806      }
16807
16808      @supports (color: lab(0% 0 0)) {
16809        .foo {
16810          text-emphasis: lab(50.998% 125.506 -50.7078) var(--style);
16811        }
16812      }
16813    "#},
16814      Browsers {
16815        safari: Some(8 << 16),
16816        ..Browsers::default()
16817      },
16818    );
16819
16820    prefix_test(
16821      r#"
16822      @supports (color: lab(0% 0 0)) {
16823        .foo {
16824          text-emphasis: lab(50.998% 125.506 -50.7078) var(--style);
16825        }
16826      }
16827    "#,
16828      indoc! {r#"
16829      @supports (color: lab(0% 0 0)) {
16830        .foo {
16831          text-emphasis: lab(50.998% 125.506 -50.7078) var(--style);
16832        }
16833      }
16834    "#},
16835      Browsers {
16836        safari: Some(8 << 16),
16837        ..Browsers::default()
16838      },
16839    );
16840  }
16841
16842  #[test]
16843  fn test_text_shadow() {
16844    minify_test(
16845      ".foo { text-shadow: 1px 1px 2px yellow; }",
16846      ".foo{text-shadow:1px 1px 2px #ff0}",
16847    );
16848    minify_test(
16849      ".foo { text-shadow: 1px 1px 2px 3px yellow; }",
16850      ".foo{text-shadow:1px 1px 2px 3px #ff0}",
16851    );
16852    minify_test(
16853      ".foo { text-shadow: 1px 1px 0 yellow; }",
16854      ".foo{text-shadow:1px 1px #ff0}",
16855    );
16856    minify_test(
16857      ".foo { text-shadow: 1px 1px yellow; }",
16858      ".foo{text-shadow:1px 1px #ff0}",
16859    );
16860    minify_test(
16861      ".foo { text-shadow: 1px 1px yellow, 2px 3px red; }",
16862      ".foo{text-shadow:1px 1px #ff0,2px 3px red}",
16863    );
16864
16865    prefix_test(
16866      ".foo { text-shadow: 12px 12px lab(40% 56.6 39) }",
16867      indoc! { r#"
16868        .foo {
16869          text-shadow: 12px 12px #b32323;
16870          text-shadow: 12px 12px lab(40% 56.6 39);
16871        }
16872      "#},
16873      Browsers {
16874        chrome: Some(4 << 16),
16875        ..Browsers::default()
16876      },
16877    );
16878
16879    prefix_test(
16880      ".foo { text-shadow: 12px 12px lab(40% 56.6 39) }",
16881      indoc! { r#"
16882        .foo {
16883          text-shadow: 12px 12px #b32323;
16884          text-shadow: 12px 12px color(display-p3 .643308 .192455 .167712);
16885          text-shadow: 12px 12px lab(40% 56.6 39);
16886        }
16887      "#},
16888      Browsers {
16889        chrome: Some(90 << 16),
16890        safari: Some(14 << 16),
16891        ..Browsers::default()
16892      },
16893    );
16894
16895    prefix_test(
16896      ".foo { text-shadow: 12px 12px lab(40% 56.6 39), 12px 12px yellow }",
16897      indoc! { r#"
16898        .foo {
16899          text-shadow: 12px 12px #b32323, 12px 12px #ff0;
16900          text-shadow: 12px 12px lab(40% 56.6 39), 12px 12px #ff0;
16901        }
16902      "#},
16903      Browsers {
16904        chrome: Some(4 << 16),
16905        ..Browsers::default()
16906      },
16907    );
16908
16909    prefix_test(
16910      ".foo { text-shadow: var(--foo) 12px lab(40% 56.6 39) }",
16911      indoc! { r#"
16912        .foo {
16913          text-shadow: var(--foo) 12px #b32323;
16914        }
16915
16916        @supports (color: lab(0% 0 0)) {
16917          .foo {
16918            text-shadow: var(--foo) 12px lab(40% 56.6 39);
16919          }
16920        }
16921      "#},
16922      Browsers {
16923        chrome: Some(4 << 16),
16924        ..Browsers::default()
16925      },
16926    );
16927
16928    prefix_test(
16929      r#"
16930        @supports (color: lab(0% 0 0)) {
16931          .foo {
16932            text-shadow: var(--foo) 12px lab(40% 56.6 39);
16933          }
16934        }
16935      "#,
16936      indoc! { r#"
16937        @supports (color: lab(0% 0 0)) {
16938          .foo {
16939            text-shadow: var(--foo) 12px lab(40% 56.6 39);
16940          }
16941        }
16942      "#},
16943      Browsers {
16944        chrome: Some(4 << 16),
16945        ..Browsers::default()
16946      },
16947    );
16948  }
16949
16950  #[test]
16951  fn test_break() {
16952    prefix_test(
16953      r#"
16954      .foo {
16955        box-decoration-break: clone;
16956      }
16957    "#,
16958      indoc! {r#"
16959      .foo {
16960        -webkit-box-decoration-break: clone;
16961        box-decoration-break: clone;
16962      }
16963    "#},
16964      Browsers {
16965        safari: Some(15 << 16),
16966        ..Browsers::default()
16967      },
16968    );
16969
16970    prefix_test(
16971      r#"
16972      .foo {
16973        box-decoration-break: clone;
16974      }
16975    "#,
16976      indoc! {r#"
16977      .foo {
16978        box-decoration-break: clone;
16979      }
16980    "#},
16981      Browsers {
16982        firefox: Some(95 << 16),
16983        ..Browsers::default()
16984      },
16985    );
16986  }
16987
16988  #[test]
16989  fn test_position() {
16990    test(
16991      r#"
16992      .foo {
16993        position: relative;
16994        position: absolute;
16995      }
16996    "#,
16997      indoc! {r#"
16998      .foo {
16999        position: absolute;
17000      }
17001    "#},
17002    );
17003
17004    test(
17005      r#"
17006      .foo {
17007        position: -webkit-sticky;
17008        position: sticky;
17009      }
17010    "#,
17011      indoc! {r#"
17012      .foo {
17013        position: -webkit-sticky;
17014        position: sticky;
17015      }
17016    "#},
17017    );
17018
17019    prefix_test(
17020      r#"
17021      .foo {
17022        position: sticky;
17023      }
17024    "#,
17025      indoc! {r#"
17026      .foo {
17027        position: -webkit-sticky;
17028        position: sticky;
17029      }
17030    "#},
17031      Browsers {
17032        safari: Some(8 << 16),
17033        ..Browsers::default()
17034      },
17035    );
17036
17037    prefix_test(
17038      r#"
17039      .foo {
17040        position: -webkit-sticky;
17041        position: sticky;
17042      }
17043    "#,
17044      indoc! {r#"
17045      .foo {
17046        position: sticky;
17047      }
17048    "#},
17049      Browsers {
17050        safari: Some(13 << 16),
17051        ..Browsers::default()
17052      },
17053    );
17054
17055    test(
17056      r#"
17057      .foo {
17058        top: 0;
17059        left: 0;
17060        bottom: 0;
17061        right: 0;
17062      }
17063    "#,
17064      indoc! {r#"
17065      .foo {
17066        inset: 0;
17067      }
17068    "#},
17069    );
17070
17071    test(
17072      r#"
17073      .foo {
17074        top: 2px;
17075        left: 4px;
17076        bottom: 2px;
17077        right: 4px;
17078      }
17079    "#,
17080      indoc! {r#"
17081      .foo {
17082        inset: 2px 4px;
17083      }
17084    "#},
17085    );
17086
17087    test(
17088      r#"
17089      .foo {
17090        top: 1px;
17091        left: 2px;
17092        bottom: 3px;
17093        right: 4px;
17094      }
17095    "#,
17096      indoc! {r#"
17097      .foo {
17098        inset: 1px 4px 3px 2px;
17099      }
17100    "#},
17101    );
17102
17103    test(
17104      r#"
17105      .foo {
17106        inset-block-start: 2px;
17107        inset-block-end: 2px;
17108        inset-inline-start: 4px;
17109        inset-inline-end: 4px;
17110      }
17111    "#,
17112      indoc! {r#"
17113      .foo {
17114        inset-block: 2px;
17115        inset-inline: 4px;
17116      }
17117    "#},
17118    );
17119
17120    test(
17121      r#"
17122      .foo {
17123        inset-block-start: 2px;
17124        inset-block-end: 3px;
17125        inset-inline-start: 4px;
17126        inset-inline-end: 5px;
17127      }
17128    "#,
17129      indoc! {r#"
17130      .foo {
17131        inset-block: 2px 3px;
17132        inset-inline: 4px 5px;
17133      }
17134    "#},
17135    );
17136
17137    test(
17138      r#"
17139      .foo {
17140        inset-block-start: 2px;
17141        inset-block-end: 3px;
17142        inset: 4px;
17143        inset-inline-start: 4px;
17144        inset-inline-end: 5px;
17145      }
17146    "#,
17147      indoc! {r#"
17148      .foo {
17149        inset: 4px;
17150        inset-inline: 4px 5px;
17151      }
17152    "#},
17153    );
17154
17155    prefix_test(
17156      r#"
17157      .foo {
17158        inset-inline-start: 2px;
17159      }
17160    "#,
17161      indoc! {r#"
17162      .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))) {
17163        left: 2px;
17164      }
17165
17166      .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))) {
17167        left: 2px;
17168      }
17169
17170      .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)) {
17171        right: 2px;
17172      }
17173
17174      .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)) {
17175        right: 2px;
17176      }
17177    "#
17178      },
17179      Browsers {
17180        safari: Some(8 << 16),
17181        ..Browsers::default()
17182      },
17183    );
17184
17185    prefix_test(
17186      r#"
17187      .foo {
17188        inset-inline-start: 2px;
17189        inset-inline-end: 4px;
17190      }
17191    "#,
17192      indoc! {r#"
17193      .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))) {
17194        left: 2px;
17195        right: 4px;
17196      }
17197
17198      .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))) {
17199        left: 2px;
17200        right: 4px;
17201      }
17202
17203      .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)) {
17204        left: 4px;
17205        right: 2px;
17206      }
17207
17208      .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)) {
17209        left: 4px;
17210        right: 2px;
17211      }
17212    "#
17213      },
17214      Browsers {
17215        safari: Some(8 << 16),
17216        ..Browsers::default()
17217      },
17218    );
17219
17220    prefix_test(
17221      r#"
17222      .foo {
17223        inset-inline: 2px;
17224      }
17225    "#,
17226      indoc! {r#"
17227      .foo {
17228        left: 2px;
17229        right: 2px;
17230      }
17231    "#
17232      },
17233      Browsers {
17234        safari: Some(8 << 16),
17235        ..Browsers::default()
17236      },
17237    );
17238
17239    prefix_test(
17240      r#"
17241      .foo {
17242        inset-block-start: 2px;
17243      }
17244    "#,
17245      indoc! {r#"
17246      .foo {
17247        top: 2px;
17248      }
17249    "#
17250      },
17251      Browsers {
17252        safari: Some(8 << 16),
17253        ..Browsers::default()
17254      },
17255    );
17256
17257    prefix_test(
17258      r#"
17259      .foo {
17260        inset-block-end: 2px;
17261      }
17262    "#,
17263      indoc! {r#"
17264      .foo {
17265        bottom: 2px;
17266      }
17267    "#
17268      },
17269      Browsers {
17270        safari: Some(8 << 16),
17271        ..Browsers::default()
17272      },
17273    );
17274
17275    prefix_test(
17276      r#"
17277      .foo {
17278        top: 1px;
17279        left: 2px;
17280        bottom: 3px;
17281        right: 4px;
17282      }
17283    "#,
17284      indoc! {r#"
17285      .foo {
17286        top: 1px;
17287        bottom: 3px;
17288        left: 2px;
17289        right: 4px;
17290      }
17291    "#},
17292      Browsers {
17293        safari: Some(8 << 16),
17294        ..Browsers::default()
17295      },
17296    );
17297  }
17298
17299  #[test]
17300  fn test_overflow() {
17301    minify_test(".foo { overflow: hidden }", ".foo{overflow:hidden}");
17302    minify_test(".foo { overflow: hidden hidden }", ".foo{overflow:hidden}");
17303    minify_test(".foo { overflow: hidden auto }", ".foo{overflow:hidden auto}");
17304
17305    test(
17306      r#"
17307      .foo {
17308        overflow-x: hidden;
17309        overflow-y: auto;
17310      }
17311    "#,
17312      indoc! {r#"
17313      .foo {
17314        overflow: hidden auto;
17315      }
17316    "#},
17317    );
17318
17319    test(
17320      r#"
17321      .foo {
17322        overflow: hidden;
17323        overflow-y: auto;
17324      }
17325    "#,
17326      indoc! {r#"
17327      .foo {
17328        overflow: hidden auto;
17329      }
17330    "#},
17331    );
17332    test(
17333      r#"
17334      .foo {
17335        overflow: hidden;
17336        overflow-y: var(--y);
17337      }
17338    "#,
17339      indoc! {r#"
17340      .foo {
17341        overflow: hidden;
17342        overflow-y: var(--y);
17343      }
17344    "#},
17345    );
17346    prefix_test(
17347      r#"
17348      .foo {
17349        overflow: hidden auto;
17350      }
17351    "#,
17352      indoc! {r#"
17353      .foo {
17354        overflow-x: hidden;
17355        overflow-y: auto;
17356      }
17357    "#},
17358      Browsers {
17359        chrome: Some(67 << 16),
17360        ..Browsers::default()
17361      },
17362    );
17363    prefix_test(
17364      r#"
17365      .foo {
17366        overflow: hidden hidden;
17367      }
17368    "#,
17369      indoc! {r#"
17370      .foo {
17371        overflow: hidden;
17372      }
17373    "#},
17374      Browsers {
17375        chrome: Some(67 << 16),
17376        ..Browsers::default()
17377      },
17378    );
17379    prefix_test(
17380      r#"
17381      .foo {
17382        overflow: hidden auto;
17383      }
17384    "#,
17385      indoc! {r#"
17386      .foo {
17387        overflow: hidden auto;
17388      }
17389    "#},
17390      Browsers {
17391        chrome: Some(68 << 16),
17392        ..Browsers::default()
17393      },
17394    );
17395
17396    minify_test(".foo { text-overflow: ellipsis }", ".foo{text-overflow:ellipsis}");
17397    prefix_test(
17398      r#"
17399      .foo {
17400        text-overflow: ellipsis;
17401      }
17402    "#,
17403      indoc! {r#"
17404      .foo {
17405        -o-text-overflow: ellipsis;
17406        text-overflow: ellipsis;
17407      }
17408    "#},
17409      Browsers {
17410        safari: Some(4 << 16),
17411        opera: Some(10 << 16),
17412        ..Browsers::default()
17413      },
17414    );
17415
17416    prefix_test(
17417      r#"
17418      .foo {
17419        -o-text-overflow: ellipsis;
17420        text-overflow: ellipsis;
17421      }
17422    "#,
17423      indoc! {r#"
17424      .foo {
17425        text-overflow: ellipsis;
17426      }
17427    "#},
17428      Browsers {
17429        safari: Some(4 << 16),
17430        opera: Some(14 << 16),
17431        ..Browsers::default()
17432      },
17433    );
17434  }
17435
17436  #[test]
17437  fn test_ui() {
17438    minify_test(".foo { resize: both }", ".foo{resize:both}");
17439    minify_test(".foo { resize: Horizontal }", ".foo{resize:horizontal}");
17440    minify_test(".foo { cursor: ew-resize }", ".foo{cursor:ew-resize}");
17441    minify_test(
17442      ".foo { cursor: url(\"test.cur\"), ew-resize }",
17443      ".foo{cursor:url(test.cur),ew-resize}",
17444    );
17445    minify_test(
17446      ".foo { cursor: url(\"test.cur\"), url(\"foo.cur\"), ew-resize }",
17447      ".foo{cursor:url(test.cur),url(foo.cur),ew-resize}",
17448    );
17449    minify_test(".foo { caret-color: auto }", ".foo{caret-color:auto}");
17450    minify_test(".foo { caret-color: yellow }", ".foo{caret-color:#ff0}");
17451    minify_test(".foo { caret-shape: block }", ".foo{caret-shape:block}");
17452    minify_test(".foo { caret: yellow block }", ".foo{caret:#ff0 block}");
17453    minify_test(".foo { caret: block yellow }", ".foo{caret:#ff0 block}");
17454    minify_test(".foo { caret: block }", ".foo{caret:block}");
17455    minify_test(".foo { caret: yellow }", ".foo{caret:#ff0}");
17456    minify_test(".foo { caret: auto auto }", ".foo{caret:auto}");
17457    minify_test(".foo { caret: auto }", ".foo{caret:auto}");
17458    minify_test(".foo { caret: yellow auto }", ".foo{caret:#ff0}");
17459    minify_test(".foo { caret: auto block }", ".foo{caret:block}");
17460    minify_test(".foo { user-select: none }", ".foo{user-select:none}");
17461    minify_test(".foo { -webkit-user-select: none }", ".foo{-webkit-user-select:none}");
17462    minify_test(".foo { accent-color: auto }", ".foo{accent-color:auto}");
17463    minify_test(".foo { accent-color: yellow }", ".foo{accent-color:#ff0}");
17464    minify_test(".foo { appearance: None }", ".foo{appearance:none}");
17465    minify_test(
17466      ".foo { -webkit-appearance: textfield }",
17467      ".foo{-webkit-appearance:textfield}",
17468    );
17469
17470    prefix_test(
17471      r#"
17472      .foo {
17473        user-select: none;
17474      }
17475    "#,
17476      indoc! {r#"
17477      .foo {
17478        -webkit-user-select: none;
17479        -moz-user-select: none;
17480        -ms-user-select: none;
17481        user-select: none;
17482      }
17483    "#},
17484      Browsers {
17485        safari: Some(8 << 16),
17486        opera: Some(5 << 16),
17487        firefox: Some(10 << 16),
17488        ie: Some(10 << 16),
17489        ..Browsers::default()
17490      },
17491    );
17492
17493    prefix_test(
17494      r#"
17495      .foo {
17496        -webkit-user-select: none;
17497        -moz-user-select: none;
17498        -ms-user-select: none;
17499        user-select: none;
17500      }
17501    "#,
17502      indoc! {r#"
17503      .foo {
17504        -webkit-user-select: none;
17505        user-select: none;
17506      }
17507    "#},
17508      Browsers {
17509        safari: Some(8 << 16),
17510        opera: Some(80 << 16),
17511        firefox: Some(80 << 16),
17512        edge: Some(80 << 16),
17513        ..Browsers::default()
17514      },
17515    );
17516
17517    prefix_test(
17518      r#"
17519      .foo {
17520        -webkit-user-select: none;
17521        -moz-user-select: none;
17522        -ms-user-select: none;
17523        user-select: none;
17524      }
17525    "#,
17526      indoc! {r#"
17527      .foo {
17528        user-select: none;
17529      }
17530    "#},
17531      Browsers {
17532        opera: Some(80 << 16),
17533        firefox: Some(80 << 16),
17534        edge: Some(80 << 16),
17535        ..Browsers::default()
17536      },
17537    );
17538
17539    prefix_test(
17540      r#"
17541      .foo {
17542        appearance: none;
17543      }
17544    "#,
17545      indoc! {r#"
17546      .foo {
17547        -webkit-appearance: none;
17548        -moz-appearance: none;
17549        -ms-appearance: none;
17550        appearance: none;
17551      }
17552    "#},
17553      Browsers {
17554        safari: Some(8 << 16),
17555        chrome: Some(80 << 16),
17556        firefox: Some(10 << 16),
17557        ie: Some(11 << 16),
17558        ..Browsers::default()
17559      },
17560    );
17561
17562    prefix_test(
17563      r#"
17564      .foo {
17565        -webkit-appearance: none;
17566        -moz-appearance: none;
17567        -ms-appearance: none;
17568        appearance: none;
17569      }
17570    "#,
17571      indoc! {r#"
17572      .foo {
17573        -webkit-appearance: none;
17574        appearance: none;
17575      }
17576    "#},
17577      Browsers {
17578        safari: Some(15 << 16),
17579        chrome: Some(85 << 16),
17580        firefox: Some(80 << 16),
17581        edge: Some(85 << 16),
17582        ..Browsers::default()
17583      },
17584    );
17585
17586    prefix_test(
17587      r#"
17588      .foo {
17589        -webkit-appearance: none;
17590        -moz-appearance: none;
17591        -ms-appearance: none;
17592        appearance: none;
17593      }
17594    "#,
17595      indoc! {r#"
17596      .foo {
17597        appearance: none;
17598      }
17599    "#},
17600      Browsers {
17601        chrome: Some(85 << 16),
17602        firefox: Some(80 << 16),
17603        edge: Some(85 << 16),
17604        ..Browsers::default()
17605      },
17606    );
17607
17608    prefix_test(
17609      ".foo { caret-color: lch(50.998% 135.363 338) }",
17610      indoc! { r#"
17611        .foo {
17612          caret-color: #ee00be;
17613          caret-color: color(display-p3 .972962 -.362078 .804206);
17614          caret-color: lch(50.998% 135.363 338);
17615        }
17616      "#},
17617      Browsers {
17618        chrome: Some(90 << 16),
17619        safari: Some(14 << 16),
17620        ..Browsers::default()
17621      },
17622    );
17623
17624    prefix_test(
17625      ".foo { caret: lch(50.998% 135.363 338) block }",
17626      indoc! { r#"
17627        .foo {
17628          caret: #ee00be block;
17629          caret: color(display-p3 .972962 -.362078 .804206) block;
17630          caret: lch(50.998% 135.363 338) block;
17631        }
17632      "#},
17633      Browsers {
17634        chrome: Some(90 << 16),
17635        safari: Some(14 << 16),
17636        ..Browsers::default()
17637      },
17638    );
17639
17640    prefix_test(
17641      ".foo { caret: lch(50.998% 135.363 338) var(--foo) }",
17642      indoc! { r#"
17643        .foo {
17644          caret: #ee00be var(--foo);
17645        }
17646
17647        @supports (color: lab(0% 0 0)) {
17648          .foo {
17649            caret: lab(50.998% 125.506 -50.7078) var(--foo);
17650          }
17651        }
17652      "#},
17653      Browsers {
17654        chrome: Some(90 << 16),
17655        ..Browsers::default()
17656      },
17657    );
17658
17659    prefix_test(
17660      r#"
17661        @supports (color: lab(0% 0 0)) {
17662          .foo {
17663            caret: lab(50.998% 125.506 -50.7078) var(--foo);
17664          }
17665        }
17666      "#,
17667      indoc! { r#"
17668        @supports (color: lab(0% 0 0)) {
17669          .foo {
17670            caret: lab(50.998% 125.506 -50.7078) var(--foo);
17671          }
17672        }
17673      "#},
17674      Browsers {
17675        chrome: Some(90 << 16),
17676        ..Browsers::default()
17677      },
17678    );
17679  }
17680
17681  #[test]
17682  fn test_list() {
17683    minify_test(".foo { list-style-type: disc; }", ".foo{list-style-type:disc}");
17684    minify_test(".foo { list-style-type: \"★\"; }", ".foo{list-style-type:\"★\"}");
17685    minify_test(
17686      ".foo { list-style-type: symbols(cyclic '○' '●'); }",
17687      ".foo{list-style-type:symbols(cyclic \"○\" \"●\")}",
17688    );
17689    minify_test(
17690      ".foo { list-style-type: symbols('○' '●'); }",
17691      ".foo{list-style-type:symbols(\"○\" \"●\")}",
17692    );
17693    minify_test(
17694      ".foo { list-style-type: symbols(symbolic '○' '●'); }",
17695      ".foo{list-style-type:symbols(\"○\" \"●\")}",
17696    );
17697    minify_test(
17698      ".foo { list-style-type: symbols(symbolic url('ellipse.png')); }",
17699      ".foo{list-style-type:symbols(url(ellipse.png))}",
17700    );
17701    minify_test(
17702      ".foo { list-style-image: url('ellipse.png'); }",
17703      ".foo{list-style-image:url(ellipse.png)}",
17704    );
17705    minify_test(
17706      ".foo { list-style-position: outside; }",
17707      ".foo{list-style-position:outside}",
17708    );
17709    minify_test(
17710      ".foo { list-style: \"★\" url(ellipse.png) outside; }",
17711      ".foo{list-style:url(ellipse.png) \"★\"}",
17712    );
17713    minify_test(".foo { list-style: none; }", ".foo{list-style:none}");
17714    minify_test(".foo { list-style: none none outside; }", ".foo{list-style:none}");
17715    minify_test(".foo { list-style: none none inside; }", ".foo{list-style:inside none}");
17716    minify_test(".foo { list-style: none inside; }", ".foo{list-style:inside none}");
17717    minify_test(".foo { list-style: none disc; }", ".foo{list-style:outside}");
17718    minify_test(".foo { list-style: none inside disc; }", ".foo{list-style:inside}");
17719    minify_test(".foo { list-style: none \"★\"; }", ".foo{list-style:\"★\"}");
17720    minify_test(
17721      ".foo { list-style: none url(foo.png); }",
17722      ".foo{list-style:url(foo.png) none}",
17723    );
17724
17725    test(
17726      r#"
17727      .foo {
17728        list-style-type: disc;
17729        list-style-image: url(ellipse.png);
17730        list-style-position: outside;
17731      }
17732    "#,
17733      indoc! {r#"
17734      .foo {
17735        list-style: url("ellipse.png");
17736      }
17737    "#},
17738    );
17739
17740    test(
17741      r#"
17742      .foo {
17743        list-style: \"★\" url(ellipse.png) outside;
17744        list-style-image: none;
17745      }
17746    "#,
17747      indoc! {r#"
17748      .foo {
17749        list-style: \"★\";
17750      }
17751    "#},
17752    );
17753
17754    test(
17755      r#"
17756      .foo {
17757        list-style: \"★\" url(ellipse.png) outside;
17758        list-style-image: var(--img);
17759      }
17760    "#,
17761      indoc! {r#"
17762      .foo {
17763        list-style: url("ellipse.png") \"★\";
17764        list-style-image: var(--img);
17765      }
17766    "#},
17767    );
17768
17769    prefix_test(
17770      ".foo { list-style-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
17771      indoc! { r#"
17772        .foo {
17773          list-style-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ff0f0e), to(#7773ff));
17774          list-style-image: -webkit-linear-gradient(top, #ff0f0e, #7773ff);
17775          list-style-image: linear-gradient(#ff0f0e, #7773ff);
17776          list-style-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
17777        }
17778      "#},
17779      Browsers {
17780        chrome: Some(8 << 16),
17781        ..Browsers::default()
17782      },
17783    );
17784
17785    prefix_test(
17786      ".foo { list-style: \"★\" linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
17787      indoc! { r#"
17788        .foo {
17789          list-style: linear-gradient(#ff0f0e, #7773ff) "★";
17790          list-style: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) "★";
17791        }
17792      "#},
17793      Browsers {
17794        chrome: Some(90 << 16),
17795        ..Browsers::default()
17796      },
17797    );
17798
17799    prefix_test(
17800      ".foo { list-style: var(--foo) linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
17801      indoc! { r#"
17802        .foo {
17803          list-style: var(--foo) linear-gradient(#ff0f0e, #7773ff);
17804        }
17805
17806        @supports (color: lab(0% 0 0)) {
17807          .foo {
17808            list-style: var(--foo) linear-gradient(lab(56.208% 94.4644 98.8928), lab(51% 70.4544 -115.586));
17809          }
17810        }
17811      "#},
17812      Browsers {
17813        chrome: Some(90 << 16),
17814        ..Browsers::default()
17815      },
17816    );
17817
17818    prefix_test(
17819      r#"
17820        @supports (color: lab(0% 0 0)) {
17821          .foo {
17822            list-style: var(--foo) linear-gradient(lab(56.208% 94.4644 98.8928), lab(51% 70.4544 -115.586));
17823          }
17824        }
17825      "#,
17826      indoc! { r#"
17827        @supports (color: lab(0% 0 0)) {
17828          .foo {
17829            list-style: var(--foo) linear-gradient(lab(56.208% 94.4644 98.8928), lab(51% 70.4544 -115.586));
17830          }
17831        }
17832      "#},
17833      Browsers {
17834        chrome: Some(90 << 16),
17835        ..Browsers::default()
17836      },
17837    );
17838
17839    test(
17840      r#"
17841      .foo {
17842        list-style: inside;
17843        list-style-type: disc;
17844      }
17845    "#,
17846      indoc! {r#"
17847      .foo {
17848        list-style: inside;
17849      }
17850    "#},
17851    );
17852    test(
17853      r#"
17854      .foo {
17855        list-style: inside;
17856        list-style-type: decimal;
17857      }
17858    "#,
17859      indoc! {r#"
17860      .foo {
17861        list-style: inside decimal;
17862      }
17863    "#},
17864    );
17865  }
17866
17867  #[test]
17868  fn test_image_set() {
17869    // Spec: https://drafts.csswg.org/css-images-4/#image-set-notation
17870    // WPT: https://github.com/web-platform-tests/wpt/blob/master/css/css-images/image-set/image-set-parsing.html
17871    // test image-set(<string>)
17872    minify_test(
17873      ".foo { background: image-set(\"foo.png\" 2x, url(bar.png) 1x) }",
17874      ".foo{background:image-set(\"foo.png\" 2x,\"bar.png\" 1x)}",
17875    );
17876
17877    // test image-set(type(<string>))
17878    minify_test(
17879      ".foo { background: image-set('foo.webp' type('webp'), url(foo.jpg)) }",
17880      ".foo{background:image-set(\"foo.webp\" 1x type(\"webp\"),\"foo.jpg\" 1x)}",
17881    );
17882    minify_test(
17883      ".foo { background: image-set('foo.avif' 2x type('image/avif'), url(foo.png)) }",
17884      ".foo{background:image-set(\"foo.avif\" 2x type(\"image/avif\"),\"foo.png\" 1x)}",
17885    );
17886    minify_test(
17887      ".foo { background: image-set(url('example.png') 3x type('image/png')) }",
17888      ".foo{background:image-set(\"example.png\" 3x type(\"image/png\"))}",
17889    );
17890
17891    minify_test(
17892      ".foo { background: image-set(url(example.png) type('image/png') 1x) }",
17893      ".foo{background:image-set(\"example.png\" 1x type(\"image/png\"))}",
17894    );
17895
17896    minify_test(
17897      ".foo { background: -webkit-image-set(url(\"foo.png\") 2x, url(bar.png) 1x) }",
17898      ".foo{background:-webkit-image-set(url(foo.png) 2x,url(bar.png) 1x)}",
17899    );
17900
17901    test(
17902      r#"
17903      .foo {
17904        background: -webkit-image-set(url("foo.png") 2x, url(bar.png) 1x);
17905        background: image-set(url("foo.png") 2x, url(bar.png) 1x);
17906      }
17907    "#,
17908      indoc! {r#"
17909      .foo {
17910        background: -webkit-image-set(url("foo.png") 2x, url("bar.png") 1x);
17911        background: image-set("foo.png" 2x, "bar.png" 1x);
17912      }
17913    "#},
17914    );
17915
17916    // test image-set(<gradient>)
17917    test(
17918      r#"
17919      .foo {
17920        background: image-set(linear-gradient(cornflowerblue, white) 1x, url("detailed-gradient.png") 3x);
17921      }
17922    "#,
17923      indoc! {r#"
17924      .foo {
17925        background: image-set(linear-gradient(#6495ed, #fff) 1x, "detailed-gradient.png" 3x);
17926      }
17927    "#},
17928    );
17929
17930    prefix_test(
17931      r#"
17932      .foo {
17933        background: image-set(url("foo.png") 2x, url(bar.png) 1x);
17934      }
17935    "#,
17936      indoc! {r#"
17937      .foo {
17938        background: -webkit-image-set(url("foo.png") 2x, url("bar.png") 1x);
17939        background: image-set("foo.png" 2x, "bar.png" 1x);
17940      }
17941    "#},
17942      Browsers {
17943        chrome: Some(85 << 16),
17944        firefox: Some(80 << 16),
17945        ..Browsers::default()
17946      },
17947    );
17948
17949    prefix_test(
17950      r#"
17951      .foo {
17952        background: -webkit-image-set(url("foo.png") 2x, url(bar.png) 1x);
17953        background: image-set(url("foo.png") 2x, url(bar.png) 1x);
17954      }
17955    "#,
17956      indoc! {r#"
17957      .foo {
17958        background: -webkit-image-set(url("foo.png") 2x, url("bar.png") 1x);
17959        background: image-set("foo.png" 2x, "bar.png" 1x);
17960      }
17961    "#},
17962      Browsers {
17963        firefox: Some(80 << 16),
17964        ..Browsers::default()
17965      },
17966    );
17967
17968    prefix_test(
17969      r#"
17970      .foo {
17971        background: -webkit-image-set(url("foo.png") 2x, url(bar.png) 1x);
17972      }
17973    "#,
17974      indoc! {r#"
17975      .foo {
17976        background: -webkit-image-set(url("foo.png") 2x, url("bar.png") 1x);
17977      }
17978    "#},
17979      Browsers {
17980        chrome: Some(95 << 16),
17981        ..Browsers::default()
17982      },
17983    );
17984
17985    for property in &[
17986      "background",
17987      "background-image",
17988      "border-image-source",
17989      "border-image",
17990      "border-image-source",
17991      "-webkit-mask-image",
17992      "-webkit-mask",
17993      "list-style-image",
17994      "list-style",
17995    ] {
17996      prefix_test(
17997        &format!(
17998          r#"
17999        .foo {{
18000          {}: url(foo.png);
18001          {}: image-set(url("foo.png") 2x, url(bar.png) 1x);
18002        }}
18003      "#,
18004          property, property
18005        ),
18006        &format!(
18007          indoc! {r#"
18008        .foo {{
18009          {}: url("foo.png");
18010          {}: image-set("foo.png" 2x, "bar.png" 1x);
18011        }}
18012      "#},
18013          property, property
18014        ),
18015        Browsers {
18016          ie: Some(11 << 16),
18017          chrome: Some(95 << 16),
18018          ..Browsers::default()
18019        },
18020      );
18021
18022      prefix_test(
18023        &format!(
18024          r#"
18025        .foo {{
18026          {}: url(foo.png);
18027          {}: image-set(url("foo.png") 2x, url(bar.png) 1x);
18028        }}
18029      "#,
18030          property, property
18031        ),
18032        &format!(
18033          indoc! {r#"
18034        .foo {{
18035          {}: -webkit-image-set(url("foo.png") 2x, url("bar.png") 1x);
18036          {}: image-set("foo.png" 2x, "bar.png" 1x);
18037        }}
18038      "#},
18039          property, property
18040        ),
18041        Browsers {
18042          chrome: Some(95 << 16),
18043          ..Browsers::default()
18044        },
18045      );
18046    }
18047  }
18048
18049  #[test]
18050  fn test_color() {
18051    minify_test(".foo { color: yellow }", ".foo{color:#ff0}");
18052    minify_test(".foo { color: rgb(255, 255, 0) }", ".foo{color:#ff0}");
18053    minify_test(".foo { color: rgba(255, 255, 0, 1) }", ".foo{color:#ff0}");
18054    minify_test(".foo { color: rgba(255, 255, 0, 0.8) }", ".foo{color:#ff0c}");
18055    minify_test(".foo { color: rgb(128, 128, 128) }", ".foo{color:gray}");
18056    minify_test(".foo { color: rgb(123, 255, 255) }", ".foo{color:#7bffff}");
18057    minify_test(".foo { color: rgba(123, 255, 255, 0.5) }", ".foo{color:#7bffff80}");
18058    minify_test(".foo { color: rgb(123 255 255) }", ".foo{color:#7bffff}");
18059    minify_test(".foo { color: rgb(123 255 255 / .5) }", ".foo{color:#7bffff80}");
18060    minify_test(".foo { color: rgb(123 255 255 / 50%) }", ".foo{color:#7bffff80}");
18061    minify_test(".foo { color: rgb(48% 100% 100% / 50%) }", ".foo{color:#7affff80}");
18062    minify_test(".foo { color: hsl(100deg, 100%, 50%) }", ".foo{color:#5f0}");
18063    minify_test(".foo { color: hsl(100, 100%, 50%) }", ".foo{color:#5f0}");
18064    minify_test(".foo { color: hsl(100 100% 50%) }", ".foo{color:#5f0}");
18065    minify_test(".foo { color: hsl(100 100 50) }", ".foo{color:#5f0}");
18066    minify_test(".foo { color: hsl(100, 100%, 50%, .8) }", ".foo{color:#5f0c}");
18067    minify_test(".foo { color: hsl(100 100% 50% / .8) }", ".foo{color:#5f0c}");
18068    minify_test(".foo { color: hsla(100, 100%, 50%, .8) }", ".foo{color:#5f0c}");
18069    minify_test(".foo { color: hsla(100 100% 50% / .8) }", ".foo{color:#5f0c}");
18070    minify_test(".foo { color: transparent }", ".foo{color:#0000}");
18071    minify_test(".foo { color: currentColor }", ".foo{color:currentColor}");
18072    minify_test(".foo { color: ButtonBorder }", ".foo{color:buttonborder}");
18073    minify_test(".foo { color: hwb(194 0% 0%) }", ".foo{color:#00c4ff}");
18074    minify_test(".foo { color: hwb(194 0% 0% / 50%) }", ".foo{color:#00c4ff80}");
18075    minify_test(".foo { color: hwb(194 0% 50%) }", ".foo{color:#006280}");
18076    minify_test(".foo { color: hwb(194 50% 0%) }", ".foo{color:#80e1ff}");
18077    minify_test(".foo { color: hwb(194 50 0) }", ".foo{color:#80e1ff}");
18078    minify_test(".foo { color: hwb(194 50% 50%) }", ".foo{color:gray}");
18079    // minify_test(".foo { color: ActiveText }", ".foo{color:ActiveTet}");
18080    minify_test(
18081      ".foo { color: lab(29.2345% 39.3825 20.0664); }",
18082      ".foo{color:lab(29.2345% 39.3825 20.0664)}",
18083    );
18084    minify_test(
18085      ".foo { color: lab(29.2345 39.3825 20.0664); }",
18086      ".foo{color:lab(29.2345% 39.3825 20.0664)}",
18087    );
18088    minify_test(
18089      ".foo { color: lab(29.2345% 39.3825% 20.0664%); }",
18090      ".foo{color:lab(29.2345% 49.2281 25.083)}",
18091    );
18092    minify_test(
18093      ".foo { color: lab(29.2345% 39.3825 20.0664 / 100%); }",
18094      ".foo{color:lab(29.2345% 39.3825 20.0664)}",
18095    );
18096    minify_test(
18097      ".foo { color: lab(29.2345% 39.3825 20.0664 / 50%); }",
18098      ".foo{color:lab(29.2345% 39.3825 20.0664/.5)}",
18099    );
18100    minify_test(
18101      ".foo { color: lch(29.2345% 44.2 27); }",
18102      ".foo{color:lch(29.2345% 44.2 27)}",
18103    );
18104    minify_test(
18105      ".foo { color: lch(29.2345 44.2 27); }",
18106      ".foo{color:lch(29.2345% 44.2 27)}",
18107    );
18108    minify_test(
18109      ".foo { color: lch(29.2345% 44.2% 27deg); }",
18110      ".foo{color:lch(29.2345% 66.3 27)}",
18111    );
18112    minify_test(
18113      ".foo { color: lch(29.2345% 44.2 45deg); }",
18114      ".foo{color:lch(29.2345% 44.2 45)}",
18115    );
18116    minify_test(
18117      ".foo { color: lch(29.2345% 44.2 .5turn); }",
18118      ".foo{color:lch(29.2345% 44.2 180)}",
18119    );
18120    minify_test(
18121      ".foo { color: lch(29.2345% 44.2 27 / 100%); }",
18122      ".foo{color:lch(29.2345% 44.2 27)}",
18123    );
18124    minify_test(
18125      ".foo { color: lch(29.2345% 44.2 27 / 50%); }",
18126      ".foo{color:lch(29.2345% 44.2 27/.5)}",
18127    );
18128    minify_test(
18129      ".foo { color: oklab(40.101% 0.1147 0.0453); }",
18130      ".foo{color:oklab(40.101% .1147 .0453)}",
18131    );
18132    minify_test(
18133      ".foo { color: oklab(.40101 0.1147 0.0453); }",
18134      ".foo{color:oklab(40.101% .1147 .0453)}",
18135    );
18136    minify_test(
18137      ".foo { color: oklab(40.101% 0.1147% 0.0453%); }",
18138      ".foo{color:oklab(40.101% .0004588 .0001812)}",
18139    );
18140    minify_test(
18141      ".foo { color: oklch(40.101% 0.12332 21.555); }",
18142      ".foo{color:oklch(40.101% .12332 21.555)}",
18143    );
18144    minify_test(
18145      ".foo { color: oklch(.40101 0.12332 21.555); }",
18146      ".foo{color:oklch(40.101% .12332 21.555)}",
18147    );
18148    minify_test(
18149      ".foo { color: oklch(40.101% 0.12332% 21.555); }",
18150      ".foo{color:oklch(40.101% .00049328 21.555)}",
18151    );
18152    minify_test(
18153      ".foo { color: oklch(40.101% 0.12332 .5turn); }",
18154      ".foo{color:oklch(40.101% .12332 180)}",
18155    );
18156    minify_test(
18157      ".foo { color: color(display-p3 1 0.5 0); }",
18158      ".foo{color:color(display-p3 1 .5 0)}",
18159    );
18160    minify_test(
18161      ".foo { color: color(display-p3 100% 50% 0%); }",
18162      ".foo{color:color(display-p3 1 .5 0)}",
18163    );
18164    minify_test(
18165      ".foo { color: color(xyz-d50 0.2005 0.14089 0.4472); }",
18166      ".foo{color:color(xyz-d50 .2005 .14089 .4472)}",
18167    );
18168    minify_test(
18169      ".foo { color: color(xyz-d50 20.05% 14.089% 44.72%); }",
18170      ".foo{color:color(xyz-d50 .2005 .14089 .4472)}",
18171    );
18172    minify_test(
18173      ".foo { color: color(xyz-d65 0.2005 0.14089 0.4472); }",
18174      ".foo{color:color(xyz .2005 .14089 .4472)}",
18175    );
18176    minify_test(
18177      ".foo { color: color(xyz-d65 20.05% 14.089% 44.72%); }",
18178      ".foo{color:color(xyz .2005 .14089 .4472)}",
18179    );
18180    minify_test(
18181      ".foo { color: color(xyz 0.2005 0.14089 0.4472); }",
18182      ".foo{color:color(xyz .2005 .14089 .4472)}",
18183    );
18184    minify_test(
18185      ".foo { color: color(xyz 20.05% 14.089% 44.72%); }",
18186      ".foo{color:color(xyz .2005 .14089 .4472)}",
18187    );
18188    minify_test(
18189      ".foo { color: color(xyz 0.2005 0 0); }",
18190      ".foo{color:color(xyz .2005 0 0)}",
18191    );
18192    minify_test(".foo { color: color(xyz 0 0 0); }", ".foo{color:color(xyz 0 0 0)}");
18193    minify_test(".foo { color: color(xyz 0 1 0); }", ".foo{color:color(xyz 0 1 0)}");
18194    minify_test(
18195      ".foo { color: color(xyz 0 1 0 / 20%); }",
18196      ".foo{color:color(xyz 0 1 0/.2)}",
18197    );
18198    minify_test(
18199      ".foo { color: color(xyz 0 0 0 / 20%); }",
18200      ".foo{color:color(xyz 0 0 0/.2)}",
18201    );
18202    minify_test(
18203      ".foo { color: color(display-p3 100% 50% 0 / 20%); }",
18204      ".foo{color:color(display-p3 1 .5 0/.2)}",
18205    );
18206    minify_test(
18207      ".foo { color: color(display-p3 100% 0 0 / 20%); }",
18208      ".foo{color:color(display-p3 1 0 0/.2)}",
18209    );
18210    minify_test(".foo { color: hsl(none none none) }", ".foo{color:#000}");
18211    minify_test(".foo { color: hwb(none none none) }", ".foo{color:red}");
18212    minify_test(".foo { color: rgb(none none none) }", ".foo{color:#000}");
18213
18214    // If the browser doesn't support `#rrggbbaa` color syntax, it is converted to `transparent`.
18215    attr_test(
18216      "color: rgba(0, 0, 0, 0)",
18217      "color:transparent",
18218      true,
18219      Some(Browsers {
18220        chrome: Some(61 << 16), // Chrome >= 62 supports `#rrggbbaa` color.
18221        ..Browsers::default()
18222      }),
18223    );
18224
18225    attr_test(
18226      "color: #0000",
18227      "color:transparent",
18228      true,
18229      Some(Browsers {
18230        chrome: Some(61 << 16), // Chrome >= 62 supports `#rrggbbaa` color.
18231        ..Browsers::default()
18232      }),
18233    );
18234
18235    attr_test(
18236      "color: transparent",
18237      "color:transparent",
18238      true,
18239      Some(Browsers {
18240        chrome: Some(61 << 16),
18241        ..Browsers::default()
18242      }),
18243    );
18244
18245    attr_test(
18246      "color: rgba(0, 0, 0, 0)",
18247      "color: rgba(0, 0, 0, 0)",
18248      false,
18249      Some(Browsers {
18250        chrome: Some(61 << 16),
18251        ..Browsers::default()
18252      }),
18253    );
18254
18255    attr_test(
18256      "color: rgba(255, 0, 0, 0)",
18257      "color:rgba(255,0,0,0)",
18258      true,
18259      Some(Browsers {
18260        chrome: Some(61 << 16),
18261        ..Browsers::default()
18262      }),
18263    );
18264
18265    attr_test(
18266      "color: rgba(255, 0, 0, 0)",
18267      "color:#f000",
18268      true,
18269      Some(Browsers {
18270        chrome: Some(62 << 16),
18271        ..Browsers::default()
18272      }),
18273    );
18274
18275    prefix_test(
18276      ".foo { color: rgba(123, 456, 789, 0.5) }",
18277      indoc! { r#"
18278        .foo {
18279          color: #7bffff80;
18280        }
18281      "#},
18282      Browsers {
18283        chrome: Some(95 << 16),
18284        ..Browsers::default()
18285      },
18286    );
18287
18288    prefix_test(
18289      ".foo { color: rgba(123, 255, 255, 0.5) }",
18290      indoc! { r#"
18291        .foo {
18292          color: rgba(123, 255, 255, .5);
18293        }
18294      "#},
18295      Browsers {
18296        ie: Some(11 << 16),
18297        ..Browsers::default()
18298      },
18299    );
18300
18301    prefix_test(
18302      ".foo { color: #7bffff80 }",
18303      indoc! { r#"
18304        .foo {
18305          color: rgba(123, 255, 255, .5);
18306        }
18307      "#},
18308      Browsers {
18309        ie: Some(11 << 16),
18310        ..Browsers::default()
18311      },
18312    );
18313
18314    prefix_test(
18315      ".foo { color: rgba(123, 456, 789, 0.5) }",
18316      indoc! { r#"
18317        .foo {
18318          color: rgba(123, 255, 255, .5);
18319        }
18320      "#},
18321      Browsers {
18322        firefox: Some(48 << 16),
18323        safari: Some(10 << 16),
18324        ios_saf: Some(9 << 16),
18325        ..Browsers::default()
18326      },
18327    );
18328
18329    prefix_test(
18330      ".foo { color: rgba(123, 456, 789, 0.5) }",
18331      indoc! { r#"
18332        .foo {
18333          color: #7bffff80;
18334        }
18335      "#},
18336      Browsers {
18337        firefox: Some(49 << 16),
18338        safari: Some(10 << 16),
18339        ios_saf: Some(10 << 16),
18340        ..Browsers::default()
18341      },
18342    );
18343
18344    prefix_test(
18345      ".foo { background-color: lab(40% 56.6 39) }",
18346      indoc! { r#"
18347        .foo {
18348          background-color: #b32323;
18349          background-color: lab(40% 56.6 39);
18350        }
18351      "#},
18352      Browsers {
18353        chrome: Some(90 << 16),
18354        ..Browsers::default()
18355      },
18356    );
18357
18358    prefix_test(
18359      ".foo { background-color: lch(40% 68.735435 34.568626) }",
18360      indoc! { r#"
18361        .foo {
18362          background-color: #b32323;
18363          background-color: lch(40% 68.7354 34.5686);
18364        }
18365      "#},
18366      Browsers {
18367        chrome: Some(90 << 16),
18368        ..Browsers::default()
18369      },
18370    );
18371
18372    prefix_test(
18373      ".foo { background-color: oklab(59.686% 0.1009 0.1192); }",
18374      indoc! { r#"
18375        .foo {
18376          background-color: #c65d07;
18377          background-color: lab(52.2319% 40.1449 59.9171);
18378        }
18379      "#},
18380      Browsers {
18381        chrome: Some(90 << 16),
18382        ..Browsers::default()
18383      },
18384    );
18385
18386    prefix_test(
18387      ".foo { background-color: oklch(40% 0.1268735435 34.568626) }",
18388      indoc! { r#"
18389        .foo {
18390          background-color: #7e250f;
18391          background-color: lab(29.2661% 38.2437 35.3889);
18392        }
18393      "#},
18394      Browsers {
18395        chrome: Some(90 << 16),
18396        ..Browsers::default()
18397      },
18398    );
18399
18400    prefix_test(
18401      ".foo { background-color: lab(40% 56.6 39) }",
18402      indoc! { r#"
18403        .foo {
18404          background-color: lab(40% 56.6 39);
18405        }
18406      "#},
18407      Browsers {
18408        safari: Some(15 << 16),
18409        ..Browsers::default()
18410      },
18411    );
18412
18413    prefix_test(
18414      ".foo { background-color: oklab(59.686% 0.1009 0.1192); }",
18415      indoc! { r#"
18416        .foo {
18417          background-color: #c65d07;
18418          background-color: lab(52.2319% 40.1449 59.9171);
18419        }
18420      "#},
18421      Browsers {
18422        chrome: Some(90 << 16),
18423        safari: Some(15 << 16),
18424        ..Browsers::default()
18425      },
18426    );
18427
18428    prefix_test(
18429      ".foo { background-color: oklab(59.686% 0.1009 0.1192); }",
18430      indoc! { r#"
18431        .foo {
18432          background-color: #c65d07;
18433          background-color: color(display-p3 .724144 .386777 .148795);
18434          background-color: lab(52.2319% 40.1449 59.9171);
18435        }
18436      "#},
18437      Browsers {
18438        chrome: Some(90 << 16),
18439        safari: Some(14 << 16),
18440        ..Browsers::default()
18441      },
18442    );
18443
18444    prefix_test(
18445      ".foo { background-color: lab(40% 56.6 39) }",
18446      indoc! { r#"
18447        .foo {
18448          background-color: #b32323;
18449          background-color: color(display-p3 .643308 .192455 .167712);
18450          background-color: lab(40% 56.6 39);
18451        }
18452      "#},
18453      Browsers {
18454        chrome: Some(90 << 16),
18455        safari: Some(14 << 16),
18456        ..Browsers::default()
18457      },
18458    );
18459
18460    prefix_test(
18461      ".foo { background-color: oklch(59.686% 0.15619 49.7694); }",
18462      indoc! { r#"
18463        .foo {
18464          background-color: #c65d06;
18465          background-color: lab(52.2321% 40.1417 59.9527);
18466        }
18467      "#},
18468      Browsers {
18469        chrome: Some(90 << 16),
18470        safari: Some(15 << 16),
18471        ..Browsers::default()
18472      },
18473    );
18474
18475    prefix_test(
18476      ".foo { background-color: color(sRGB 0.41587 0.503670 0.36664); }",
18477      indoc! { r#"
18478        .foo {
18479          background-color: #6a805d;
18480          background-color: color(srgb .41587 .50367 .36664);
18481        }
18482      "#},
18483      Browsers {
18484        chrome: Some(90 << 16),
18485        ..Browsers::default()
18486      },
18487    );
18488
18489    prefix_test(
18490      ".foo { background-color: color(display-p3 0.43313 0.50108 0.37950); }",
18491      indoc! { r#"
18492        .foo {
18493          background-color: #6a805d;
18494          background-color: color(display-p3 .43313 .50108 .3795);
18495        }
18496      "#},
18497      Browsers {
18498        chrome: Some(90 << 16),
18499        ..Browsers::default()
18500      },
18501    );
18502
18503    prefix_test(
18504      ".foo { background-color: color(display-p3 0.43313 0.50108 0.37950); }",
18505      indoc! { r#"
18506        .foo {
18507          background-color: #6a805d;
18508          background-color: color(display-p3 .43313 .50108 .3795);
18509        }
18510      "#},
18511      Browsers {
18512        chrome: Some(90 << 16),
18513        safari: Some(14 << 16),
18514        ..Browsers::default()
18515      },
18516    );
18517
18518    prefix_test(
18519      ".foo { background-color: color(display-p3 0.43313 0.50108 0.37950); }",
18520      indoc! { r#"
18521        .foo {
18522          background-color: color(display-p3 .43313 .50108 .3795);
18523        }
18524      "#},
18525      Browsers {
18526        safari: Some(14 << 16),
18527        ..Browsers::default()
18528      },
18529    );
18530
18531    prefix_test(
18532      ".foo { background-color: color(display-p3 0.43313 0.50108 0.37950); }",
18533      indoc! { r#"
18534        .foo {
18535          background-color: #6a805d;
18536          background-color: color(display-p3 .43313 .50108 .3795);
18537        }
18538      "#},
18539      Browsers {
18540        chrome: Some(90 << 16),
18541        safari: Some(15 << 16),
18542        ..Browsers::default()
18543      },
18544    );
18545
18546    prefix_test(
18547      ".foo { background-color: color(display-p3 0.43313 0.50108 0.37950); }",
18548      indoc! { r#"
18549        .foo {
18550          background-color: #6a805d;
18551          background-color: color(display-p3 .43313 .50108 .3795);
18552        }
18553      "#},
18554      Browsers {
18555        chrome: Some(90 << 16),
18556        ..Browsers::default()
18557      },
18558    );
18559
18560    prefix_test(
18561      ".foo { background-color: color(a98-rgb 0.44091 0.49971 0.37408); }",
18562      indoc! { r#"
18563        .foo {
18564          background-color: #6a805d;
18565          background-color: color(a98-rgb .44091 .49971 .37408);
18566        }
18567      "#},
18568      Browsers {
18569        chrome: Some(90 << 16),
18570        ..Browsers::default()
18571      },
18572    );
18573
18574    prefix_test(
18575      ".foo { background-color: color(a98-rgb 0.44091 0.49971 0.37408); }",
18576      indoc! { r#"
18577        .foo {
18578          background-color: color(a98-rgb .44091 .49971 .37408);
18579        }
18580      "#},
18581      Browsers {
18582        safari: Some(15 << 16),
18583        ..Browsers::default()
18584      },
18585    );
18586
18587    prefix_test(
18588      ".foo { background-color: color(prophoto-rgb 0.36589 0.41717 0.31333); }",
18589      indoc! { r#"
18590        .foo {
18591          background-color: #6a805d;
18592          background-color: color(prophoto-rgb .36589 .41717 .31333);
18593        }
18594      "#},
18595      Browsers {
18596        chrome: Some(90 << 16),
18597        ..Browsers::default()
18598      },
18599    );
18600
18601    prefix_test(
18602      ".foo { background-color: color(rec2020 0.42210 0.47580 0.35605); }",
18603      indoc! { r#"
18604        .foo {
18605          background-color: #728765;
18606          background-color: color(rec2020 .4221 .4758 .35605);
18607        }
18608      "#},
18609      Browsers {
18610        chrome: Some(90 << 16),
18611        ..Browsers::default()
18612      },
18613    );
18614
18615    prefix_test(
18616      ".foo { background-color: color(xyz-d50 0.2005 0.14089 0.4472); }",
18617      indoc! { r#"
18618        .foo {
18619          background-color: #7654cd;
18620          background-color: color(xyz-d50 .2005 .14089 .4472);
18621        }
18622      "#},
18623      Browsers {
18624        chrome: Some(90 << 16),
18625        ..Browsers::default()
18626      },
18627    );
18628
18629    prefix_test(
18630      ".foo { background-color: color(xyz-d65 0.21661 0.14602 0.59452); }",
18631      indoc! { r#"
18632        .foo {
18633          background-color: #7654cd;
18634          background-color: color(xyz .21661 .14602 .59452);
18635        }
18636      "#},
18637      Browsers {
18638        chrome: Some(90 << 16),
18639        ..Browsers::default()
18640      },
18641    );
18642
18643    prefix_test(
18644      ".foo { background-color: lch(50.998% 135.363 338) }",
18645      indoc! { r#"
18646        .foo {
18647          background-color: #ee00be;
18648          background-color: color(display-p3 .972962 -.362078 .804206);
18649          background-color: lch(50.998% 135.363 338);
18650        }
18651      "#},
18652      Browsers {
18653        chrome: Some(90 << 16),
18654        safari: Some(14 << 16),
18655        ..Browsers::default()
18656      },
18657    );
18658
18659    prefix_test(
18660      ".foo { color: lch(50.998% 135.363 338) }",
18661      indoc! { r#"
18662        .foo {
18663          color: #ee00be;
18664          color: color(display-p3 .972962 -.362078 .804206);
18665          color: lch(50.998% 135.363 338);
18666        }
18667      "#},
18668      Browsers {
18669        chrome: Some(90 << 16),
18670        safari: Some(14 << 16),
18671        ..Browsers::default()
18672      },
18673    );
18674
18675    prefix_test(
18676      ".foo { background: var(--image) lch(40% 68.735435 34.568626) }",
18677      indoc! { r#"
18678        .foo {
18679          background: var(--image) #b32323;
18680        }
18681
18682        @supports (color: lab(0% 0 0)) {
18683          .foo {
18684            background: var(--image) lab(40% 56.6 39);
18685          }
18686        }
18687      "#},
18688      Browsers {
18689        chrome: Some(90 << 16),
18690        ..Browsers::default()
18691      },
18692    );
18693
18694    prefix_test(
18695      r#"
18696        @supports (color: lab(0% 0 0)) {
18697          .foo {
18698            background: var(--image) lab(40% 56.6 39);
18699          }
18700        }
18701      "#,
18702      indoc! { r#"
18703        @supports (color: lab(0% 0 0)) {
18704          .foo {
18705            background: var(--image) lab(40% 56.6 39);
18706          }
18707        }
18708      "#},
18709      Browsers {
18710        chrome: Some(90 << 16),
18711        ..Browsers::default()
18712      },
18713    );
18714
18715    prefix_test(
18716      r#"
18717      .foo {
18718        color: red;
18719        color: lab(40% 56.6 39);
18720      }
18721    "#,
18722      indoc! {r#"
18723      .foo {
18724        color: red;
18725        color: lab(40% 56.6 39);
18726      }
18727    "#
18728      },
18729      Browsers {
18730        safari: Some(14 << 16),
18731        ..Browsers::default()
18732      },
18733    );
18734    prefix_test(
18735      r#"
18736      .foo {
18737        color: red;
18738        color: lab(40% 56.6 39);
18739      }
18740    "#,
18741      indoc! {r#"
18742      .foo {
18743        color: lab(40% 56.6 39);
18744      }
18745    "#
18746      },
18747      Browsers {
18748        safari: Some(16 << 16),
18749        ..Browsers::default()
18750      },
18751    );
18752
18753    prefix_test(
18754      r#"
18755      .foo {
18756        color: var(--fallback);
18757        color: lab(40% 56.6 39);
18758      }
18759    "#,
18760      indoc! {r#"
18761      .foo {
18762        color: var(--fallback);
18763        color: lab(40% 56.6 39);
18764      }
18765    "#
18766      },
18767      Browsers {
18768        safari: Some(14 << 16),
18769        ..Browsers::default()
18770      },
18771    );
18772
18773    prefix_test(
18774      r#"
18775      .foo {
18776        color: var(--fallback);
18777        color: lab(40% 56.6 39);
18778      }
18779    "#,
18780      indoc! {r#"
18781      .foo {
18782        color: lab(40% 56.6 39);
18783      }
18784    "#
18785      },
18786      Browsers {
18787        safari: Some(16 << 16),
18788        ..Browsers::default()
18789      },
18790    );
18791
18792    prefix_test(
18793      r#"
18794      .foo {
18795        color: red;
18796        color: var(--foo, lab(40% 56.6 39));
18797      }
18798    "#,
18799      indoc! {r#"
18800      .foo {
18801        color: var(--foo, color(display-p3 .643308 .192455 .167712));
18802      }
18803
18804      @supports (color: lab(0% 0 0)) {
18805        .foo {
18806          color: var(--foo, lab(40% 56.6 39));
18807        }
18808      }
18809    "#
18810      },
18811      Browsers {
18812        safari: Some(14 << 16),
18813        ..Browsers::default()
18814      },
18815    );
18816
18817    prefix_test(
18818      r#"
18819      @supports (color: lab(0% 0 0)) {
18820        .foo {
18821          color: var(--foo, lab(40% 56.6 39));
18822        }
18823      }
18824    "#,
18825      indoc! {r#"
18826      @supports (color: lab(0% 0 0)) {
18827        .foo {
18828          color: var(--foo, lab(40% 56.6 39));
18829        }
18830      }
18831    "#
18832      },
18833      Browsers {
18834        safari: Some(14 << 16),
18835        ..Browsers::default()
18836      },
18837    );
18838
18839    prefix_test(
18840      r#"
18841      .foo {
18842        --a: rgb(0 0 0 / var(--alpha));
18843        --b: rgb(50% 50% 50% / var(--alpha));
18844        --c: rgb(var(--x) 0 0);
18845        --d: rgb(0 var(--x) 0);
18846        --e: rgb(0 0 var(--x));
18847        --f: rgb(var(--x) 0 0 / var(--alpha));
18848        --g: rgb(0 var(--x) 0 / var(--alpha));
18849        --h: rgb(0 0 var(--x) / var(--alpha));
18850        --i: rgb(none 0 0 / var(--alpha));
18851        --j: rgb(from yellow r g b / var(--alpha));
18852      }
18853      "#,
18854      indoc! { r#"
18855        .foo {
18856          --a: rgba(0, 0, 0, var(--alpha));
18857          --b: rgba(128, 128, 128, var(--alpha));
18858          --c: rgb(var(--x) 0 0);
18859          --d: rgb(0 var(--x) 0);
18860          --e: rgb(0 0 var(--x));
18861          --f: rgb(var(--x) 0 0 / var(--alpha));
18862          --g: rgb(0 var(--x) 0 / var(--alpha));
18863          --h: rgb(0 0 var(--x) / var(--alpha));
18864          --i: rgb(none 0 0 / var(--alpha));
18865          --j: rgba(255, 255, 0, var(--alpha));
18866        }
18867      "#},
18868      Browsers {
18869        safari: Some(11 << 16),
18870        ..Browsers::default()
18871      },
18872    );
18873
18874    prefix_test(
18875      r#"
18876      .foo {
18877        --a: rgb(0 0 0 / var(--alpha));
18878        --b: rgb(50% 50% 50% / var(--alpha));
18879        --c: rgb(var(--x) 0 0);
18880        --d: rgb(0 var(--x) 0);
18881        --e: rgb(0 0 var(--x));
18882        --f: rgb(var(--x) 0 0 / var(--alpha));
18883        --g: rgb(0 var(--x) 0 / var(--alpha));
18884        --h: rgb(0 0 var(--x) / var(--alpha));
18885        --i: rgb(none 0 0 / var(--alpha));
18886        --j: rgb(from yellow r g b / var(--alpha));
18887      }
18888      "#,
18889      indoc! { r#"
18890        .foo {
18891          --a: rgb(0 0 0 / var(--alpha));
18892          --b: rgb(128 128 128 / var(--alpha));
18893          --c: rgb(var(--x) 0 0);
18894          --d: rgb(0 var(--x) 0);
18895          --e: rgb(0 0 var(--x));
18896          --f: rgb(var(--x) 0 0 / var(--alpha));
18897          --g: rgb(0 var(--x) 0 / var(--alpha));
18898          --h: rgb(0 0 var(--x) / var(--alpha));
18899          --i: rgb(none 0 0 / var(--alpha));
18900          --j: rgb(255 255 0 / var(--alpha));
18901        }
18902      "#},
18903      Browsers {
18904        safari: Some(13 << 16),
18905        ..Browsers::default()
18906      },
18907    );
18908
18909    prefix_test(
18910      r#"
18911      .foo {
18912        --a: hsl(270 100% 50% / var(--alpha));
18913        --b: hsl(var(--x) 0 0);
18914        --c: hsl(0 var(--x) 0);
18915        --d: hsl(0 0 var(--x));
18916        --e: hsl(var(--x) 0 0 / var(--alpha));
18917        --f: hsl(0 var(--x) 0 / var(--alpha));
18918        --g: hsl(0 0 var(--x) / var(--alpha));
18919        --h: hsl(270 100% 50% / calc(var(--alpha) / 2));
18920        --i: hsl(none 100% 50% / var(--alpha));
18921        --j: hsl(from yellow h s l / var(--alpha));
18922      }
18923      "#,
18924      indoc! { r#"
18925        .foo {
18926          --a: hsla(270, 100%, 50%, var(--alpha));
18927          --b: hsl(var(--x) 0 0);
18928          --c: hsl(0 var(--x) 0);
18929          --d: hsl(0 0 var(--x));
18930          --e: hsl(var(--x) 0 0 / var(--alpha));
18931          --f: hsl(0 var(--x) 0 / var(--alpha));
18932          --g: hsl(0 0 var(--x) / var(--alpha));
18933          --h: hsla(270, 100%, 50%, calc(var(--alpha) / 2));
18934          --i: hsl(none 100% 50% / var(--alpha));
18935          --j: hsla(60, 100%, 50%, var(--alpha));
18936        }
18937      "#},
18938      Browsers {
18939        safari: Some(11 << 16),
18940        ..Browsers::default()
18941      },
18942    );
18943
18944    prefix_test(
18945      r#"
18946      .foo {
18947        --a: hsl(270 100% 50% / var(--alpha));
18948        --b: hsl(var(--x) 0 0);
18949        --c: hsl(0 var(--x) 0);
18950        --d: hsl(0 0 var(--x));
18951        --e: hsl(var(--x) 0 0 / var(--alpha));
18952        --f: hsl(0 var(--x) 0 / var(--alpha));
18953        --g: hsl(0 0 var(--x) / var(--alpha));
18954        --h: hsl(270 100% 50% / calc(var(--alpha) / 2));
18955        --i: hsl(none 100% 50% / var(--alpha));
18956      }
18957      "#,
18958      indoc! { r#"
18959        .foo {
18960          --a: hsl(270 100% 50% / var(--alpha));
18961          --b: hsl(var(--x) 0 0);
18962          --c: hsl(0 var(--x) 0);
18963          --d: hsl(0 0 var(--x));
18964          --e: hsl(var(--x) 0 0 / var(--alpha));
18965          --f: hsl(0 var(--x) 0 / var(--alpha));
18966          --g: hsl(0 0 var(--x) / var(--alpha));
18967          --h: hsl(270 100% 50% / calc(var(--alpha) / 2));
18968          --i: hsl(none 100% 50% / var(--alpha));
18969        }
18970      "#},
18971      Browsers {
18972        safari: Some(13 << 16),
18973        ..Browsers::default()
18974      },
18975    );
18976
18977    test(
18978      r#"
18979      .foo {
18980        --a: rgb(50% 50% 50% / calc(100% / 2));
18981        --b: hsl(calc(360deg / 2) 50% 50%);
18982        --c: oklab(40.101% calc(0.1 + 0.2) 0.0453);
18983        --d: color(display-p3 0.43313 0.50108 calc(0.1 + 0.2));
18984        --e: rgb(calc(255 / 2), calc(255 / 2), calc(255 / 2));
18985      }
18986      "#,
18987      indoc! { r#"
18988        .foo {
18989          --a: #80808080;
18990          --b: #40bfbf;
18991          --c: oklab(40.101% .3 .0453);
18992          --d: color(display-p3 .43313 .50108 .3);
18993          --e: gray;
18994        }
18995      "#},
18996    );
18997  }
18998
18999  #[test]
19000  fn test_relative_color() {
19001    fn test(input: &str, output: &str) {
19002      let output = CssColor::parse_string(output)
19003        .unwrap()
19004        .to_css_string(PrinterOptions {
19005          minify: true,
19006          ..PrinterOptions::default()
19007        })
19008        .unwrap();
19009      minify_test(
19010        &format!(".foo {{ color: {} }}", input),
19011        &format!(".foo{{color:{}}}", output),
19012      );
19013    }
19014
19015    test("lab(from indianred calc(l * .8) a b)", "lab(43.1402% 45.7516 23.1557)");
19016    test("lch(from indianred calc(l + 10) c h)", "lch(63.9252% 51.2776 26.8448)");
19017    test("lch(from indianred l calc(c - 50) h)", "lch(53.9252% 1.27763 26.8448)");
19018    test(
19019      "lch(from indianred l c calc(h + 180deg))",
19020      "lch(53.9252% 51.2776 206.845)",
19021    );
19022    test("lch(from orchid l 30 h)", "lch(62.7526% 30 326.969)");
19023    test("lch(from orchid l 30 h)", "lch(62.7526% 30 326.969)");
19024    test("lch(from peru calc(l * 0.8) c h)", "lch(49.8022% 54.0117 63.6804)");
19025    test("rgb(from indianred 255 g b)", "rgb(255, 92, 92)");
19026    test("rgb(from indianred r g b / .5)", "rgba(205, 92, 92, .5)");
19027    test(
19028      "rgb(from rgba(205, 92, 92, .5) r g b / calc(alpha + .2))",
19029      "rgba(205, 92, 92, .7)",
19030    );
19031    test(
19032      "rgb(from rgba(205, 92, 92, .5) r g b / calc(alpha + .2))",
19033      "rgba(205, 92, 92, .7)",
19034    );
19035    test("lch(from indianred l sin(c) h)", "lch(53.9252% .84797 26.8448)");
19036    test("lch(from indianred l sqrt(c) h)", "lch(53.9252% 7.16084 26.8448)");
19037    test("lch(from indianred l c sin(h))", "lch(53.9252% 51.2776 .451575)");
19038    test("lch(from indianred calc(10% + 20%) c h)", "lch(30% 51.2776 26.8448)");
19039    test("lch(from indianred calc(10 + 20) c h)", "lch(30% 51.2776 26.8448)");
19040    test("lch(from indianred l c calc(10 + 20))", "lch(53.9252% 51.2776 30)");
19041    test(
19042      "lch(from indianred l c calc(10deg + 20deg))",
19043      "lch(53.9252% 51.2776 30)",
19044    );
19045    test(
19046      "lch(from indianred l c calc(10deg + 0.35rad))",
19047      "lch(53.9252% 51.2776 30.0535)",
19048    );
19049    minify_test(
19050      ".foo{color:lch(from currentColor l c sin(h))}",
19051      ".foo{color:lch(from currentColor l c sin(h))}",
19052    );
19053
19054    // The following tests were converted from WPT: https://github.com/web-platform-tests/wpt/blob/master/css/css-color/parsing/relative-color-valid.html
19055    // Find: test_valid_value\(`color`, `(.*?)`,\s*`(.*?)`\)
19056    // Replace: test("$1", "$2")
19057
19058    // Testing no modifications.
19059    test("rgb(from rebeccapurple r g b)", "#639");
19060    test("rgb(from rebeccapurple r g b / alpha)", "#639");
19061    test("rgb(from rgb(20%, 40%, 60%, 80%) r g b / alpha)", "#369c");
19062    test("rgb(from hsl(120deg 20% 50% / .5) r g b / alpha)", "#66996680");
19063
19064    // Test nesting relative colors.
19065    test("rgb(from rgb(from rebeccapurple r g b) r g b)", "#639");
19066
19067    // Testing non-sRGB origin colors to see gamut mapping.
19068    test("rgb(from color(display-p3 0 1 0) r g b / alpha)", "#00f942"); // Naive clip based mapping would give rgb(0, 255, 0).
19069    test("rgb(from lab(100% 104.3 -50.9) r g b)", "#fff"); // Naive clip based mapping would give rgb(255, 150, 255).
19070    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.
19071    test("rgb(from lch(100% 116 334) r g b)", "#fff"); // Naive clip based mapping would give rgb(255, 150, 255).
19072    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.
19073    test("rgb(from oklab(100% 0.365 -0.16) r g b)", "#fff"); // Naive clip based mapping would give rgb(255, 92, 255).
19074    test("rgb(from oklab(0% 0.365 -0.16) r g b)", "#000"); // Naive clip based mapping would give rgb(19, 0, 24).
19075    test("rgb(from oklch(100% 0.399 336.3) r g b)", "#fff"); // Naive clip based mapping would give rgb(255, 91, 255).
19076    test("rgb(from oklch(0% 0.399 336.3) r g b)", "#000"); // Naive clip based mapping would give rgb(20, 0, 24).
19077
19078    // Testing replacement with 0.
19079    test("rgb(from rebeccapurple 0 0 0)", "rgb(0, 0, 0)");
19080    test("rgb(from rebeccapurple 0 0 0 / 0)", "rgba(0, 0, 0, 0)");
19081    test("rgb(from rebeccapurple 0 g b / alpha)", "rgb(0, 51, 153)");
19082    test("rgb(from rebeccapurple r 0 b / alpha)", "rgb(102, 0, 153)");
19083    test("rgb(from rebeccapurple r g 0 / alpha)", "rgb(102, 51, 0)");
19084    test("rgb(from rebeccapurple r g b / 0)", "rgba(102, 51, 153, 0)");
19085    test(
19086      "rgb(from rgb(20%, 40%, 60%, 80%) 0 g b / alpha)",
19087      "rgba(0, 102, 153, 0.8)",
19088    );
19089    test(
19090      "rgb(from rgb(20%, 40%, 60%, 80%) r 0 b / alpha)",
19091      "rgba(51, 0, 153, 0.8)",
19092    );
19093    test(
19094      "rgb(from rgb(20%, 40%, 60%, 80%) r g 0 / alpha)",
19095      "rgba(51, 102, 0, 0.8)",
19096    );
19097    test("rgb(from rgb(20%, 40%, 60%, 80%) r g b / 0)", "rgba(51, 102, 153, 0)");
19098
19099    // Testing replacement with a number.
19100    test("rgb(from rebeccapurple 25 g b / alpha)", "rgb(25, 51, 153)");
19101    test("rgb(from rebeccapurple r 25 b / alpha)", "rgb(102, 25, 153)");
19102    test("rgb(from rebeccapurple r g 25 / alpha)", "rgb(102, 51, 25)");
19103    test("rgb(from rebeccapurple r g b / .25)", "rgba(102, 51, 153, 0.25)");
19104    test(
19105      "rgb(from rgb(20%, 40%, 60%, 80%) 25 g b / alpha)",
19106      "rgba(25, 102, 153, 0.8)",
19107    );
19108    test(
19109      "rgb(from rgb(20%, 40%, 60%, 80%) r 25 b / alpha)",
19110      "rgba(51, 25, 153, 0.8)",
19111    );
19112    test(
19113      "rgb(from rgb(20%, 40%, 60%, 80%) r g 25 / alpha)",
19114      "rgba(51, 102, 25, 0.8)",
19115    );
19116    test(
19117      "rgb(from rgb(20%, 40%, 60%, 80%) r g b / .20)",
19118      "rgba(51, 102, 153, 0.2)",
19119    );
19120
19121    // Testing replacement with a percentage.
19122    test("rgb(from rebeccapurple 20% g b / alpha)", "rgb(51, 51, 153)");
19123    test("rgb(from rebeccapurple r 20% b / alpha)", "rgb(102, 51, 153)");
19124    test("rgb(from rebeccapurple r g 20% / alpha)", "rgb(102, 51, 51)");
19125    test("rgb(from rebeccapurple r g b / 20%)", "rgba(102, 51, 153, 0.2)");
19126    test(
19127      "rgb(from rgb(20%, 40%, 60%, 80%) 20% g b / alpha)",
19128      "rgba(51, 102, 153, 0.8)",
19129    );
19130    test(
19131      "rgb(from rgb(20%, 40%, 60%, 80%) r 20% b / alpha)",
19132      "rgba(51, 51, 153, 0.8)",
19133    );
19134    test(
19135      "rgb(from rgb(20%, 40%, 60%, 80%) r g 20% / alpha)",
19136      "rgba(51, 102, 51, 0.8)",
19137    );
19138    test(
19139      "rgb(from rgb(20%, 40%, 60%, 80%) r g b / 20%)",
19140      "rgba(51, 102, 153, 0.2)",
19141    );
19142
19143    // Testing replacement with a number for r, g, b but percent for alpha.
19144    test("rgb(from rebeccapurple 25 g b / 25%)", "rgba(25, 51, 153, 0.25)");
19145    test("rgb(from rebeccapurple r 25 b / 25%)", "rgba(102, 25, 153, 0.25)");
19146    test("rgb(from rebeccapurple r g 25 / 25%)", "rgba(102, 51, 25, 0.25)");
19147    test(
19148      "rgb(from rgb(20%, 40%, 60%, 80%) 25 g b / 25%)",
19149      "rgba(25, 102, 153, 0.25)",
19150    );
19151    test(
19152      "rgb(from rgb(20%, 40%, 60%, 80%) r 25 b / 25%)",
19153      "rgba(51, 25, 153, 0.25)",
19154    );
19155    test(
19156      "rgb(from rgb(20%, 40%, 60%, 80%) r g 25 / 25%)",
19157      "rgba(51, 102, 25, 0.25)",
19158    );
19159
19160    // Testing permutation.
19161    test("rgb(from rebeccapurple g b r)", "rgb(51, 153, 102)");
19162    test("rgb(from rebeccapurple b alpha r / g)", "rgba(153, 1, 102, 1)");
19163    test("rgb(from rebeccapurple r r r / r)", "rgba(102, 102, 102, 1)");
19164    test("rgb(from rebeccapurple alpha alpha alpha / alpha)", "rgb(1, 1, 1)");
19165    test("rgb(from rgb(20%, 40%, 60%, 80%) g b r)", "rgb(102, 153, 51)");
19166    test("rgb(from rgb(20%, 40%, 60%, 80%) b alpha r / g)", "rgba(153, 1, 51, 1)");
19167    test("rgb(from rgb(20%, 40%, 60%, 80%) r r r / r)", "rgba(51, 51, 51, 1)");
19168    test(
19169      "rgb(from rgb(20%, 40%, 60%, 80%) alpha alpha alpha / alpha)",
19170      "rgba(1, 1, 1, 0.8)",
19171    );
19172
19173    // Testing mixes of number and percentage. (These would not be allowed in the non-relative syntax).
19174    test("rgb(from rebeccapurple r 20% 10)", "rgb(102, 51, 10)");
19175    test("rgb(from rebeccapurple r 10 20%)", "rgb(102, 10, 51)");
19176    test("rgb(from rebeccapurple 0% 10 10)", "rgb(0, 10, 10)");
19177    test("rgb(from rgb(20%, 40%, 60%, 80%) r 20% 10)", "rgb(51, 51, 10)");
19178    test("rgb(from rgb(20%, 40%, 60%, 80%) r 10 20%)", "rgb(51, 10, 51)");
19179    test("rgb(from rgb(20%, 40%, 60%, 80%) 0% 10 10)", "rgb(0, 10, 10)");
19180
19181    // Testing with calc().
19182    test("rgb(from rebeccapurple calc(r) calc(g) calc(b))", "rgb(102, 51, 153)");
19183    test("rgb(from rebeccapurple r calc(g * 2) 10)", "rgb(102, 102, 10)");
19184    test("rgb(from rebeccapurple b calc(r * .5) 10)", "rgb(153, 51, 10)");
19185    test("rgb(from rebeccapurple r calc(g * .5 + g * .5) 10)", "rgb(102, 51, 10)");
19186    test("rgb(from rebeccapurple r calc(b * .5 - g * .5) 10)", "rgb(102, 51, 10)");
19187    test(
19188      "rgb(from rgb(20%, 40%, 60%, 80%) calc(r) calc(g) calc(b) / calc(alpha))",
19189      "rgba(51, 102, 153, 0.8)",
19190    );
19191
19192    // Testing with 'none'.
19193    test("rgb(from rebeccapurple none none none)", "rgb(0, 0, 0)");
19194    test("rgb(from rebeccapurple none none none / none)", "rgba(0, 0, 0, 0)");
19195    test("rgb(from rebeccapurple r g none)", "rgb(102, 51, 0)");
19196    test("rgb(from rebeccapurple r g none / alpha)", "rgb(102, 51, 0)");
19197    test("rgb(from rebeccapurple r g b / none)", "rgba(102, 51, 153, 0)");
19198    test(
19199      "rgb(from rgb(20% 40% 60% / 80%) r g none / alpha)",
19200      "rgba(51, 102, 0, 0.8)",
19201    );
19202    test("rgb(from rgb(20% 40% 60% / 80%) r g b / none)", "rgba(51, 102, 153, 0)");
19203    // FIXME: Clarify with spec editors if 'none' should pass through to the constants.
19204    test("rgb(from rgb(none none none) r g b)", "rgb(0, 0, 0)");
19205    test("rgb(from rgb(none none none / none) r g b / alpha)", "rgba(0, 0, 0, 0)");
19206    test("rgb(from rgb(20% none 60%) r g b)", "rgb(51, 0, 153)");
19207    test(
19208      "rgb(from rgb(20% 40% 60% / none) r g b / alpha)",
19209      "rgba(51, 102, 153, 0)",
19210    );
19211
19212    // hsl(from ...)
19213
19214    // Testing no modifications.
19215    test("hsl(from rebeccapurple h s l)", "rgb(102, 51, 153)");
19216    test("hsl(from rebeccapurple h s l / alpha)", "rgb(102, 51, 153)");
19217    test(
19218      "hsl(from rgb(20%, 40%, 60%, 80%) h s l / alpha)",
19219      "rgba(51, 102, 153, 0.8)",
19220    );
19221    test(
19222      "hsl(from hsl(120deg 20% 50% / .5) h s l / alpha)",
19223      "rgba(102, 153, 102, 0.5)",
19224    );
19225
19226    // Test nesting relative colors.
19227    test("hsl(from hsl(from rebeccapurple h s l) h s l)", "rgb(102, 51, 153)");
19228
19229    // Testing non-sRGB origin colors to see gamut mapping.
19230    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).
19231    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).
19232    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,
19233    test("hsl(from lch(100% 116 334) h s l)", "rgb(255, 255, 255)"); // Naive clip based mapping would give rgb(255, 150, 255).
19234    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,
19235    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).
19236    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).
19237    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).
19238    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).
19239
19240    // Testing replacement with 0.
19241    test("hsl(from rebeccapurple 0 0% 0%)", "rgb(0, 0, 0)");
19242    test("hsl(from rebeccapurple 0deg 0% 0%)", "rgb(0, 0, 0)");
19243    test("hsl(from rebeccapurple 0 0% 0% / 0)", "rgba(0, 0, 0, 0)");
19244    test("hsl(from rebeccapurple 0deg 0% 0% / 0)", "rgba(0, 0, 0, 0)");
19245    test("hsl(from rebeccapurple 0 s l / alpha)", "rgb(153, 51, 51)");
19246    test("hsl(from rebeccapurple 0deg s l / alpha)", "rgb(153, 51, 51)");
19247    test("hsl(from rebeccapurple h 0% l / alpha)", "rgb(102, 102, 102)");
19248    test("hsl(from rebeccapurple h s 0% / alpha)", "rgb(0, 0, 0)");
19249    test("hsl(from rebeccapurple h s l / 0)", "rgba(102, 51, 153, 0)");
19250    test(
19251      "hsl(from rgb(20%, 40%, 60%, 80%) 0 s l / alpha)",
19252      "rgba(153, 51, 51, 0.8)",
19253    );
19254    test(
19255      "hsl(from rgb(20%, 40%, 60%, 80%) 0deg s l / alpha)",
19256      "rgba(153, 51, 51, 0.8)",
19257    );
19258    test(
19259      "hsl(from rgb(20%, 40%, 60%, 80%) h 0% l / alpha)",
19260      "rgba(102, 102, 102, 0.8)",
19261    );
19262    test("hsl(from rgb(20%, 40%, 60%, 80%) h s 0% / alpha)", "rgba(0, 0, 0, 0.8)");
19263    test("hsl(from rgb(20%, 40%, 60%, 80%) h s l / 0)", "rgba(51, 102, 153, 0)");
19264
19265    // Testing replacement with a constant.
19266    test("hsl(from rebeccapurple 25 s l / alpha)", "rgb(153, 94, 51)");
19267    test("hsl(from rebeccapurple 25deg s l / alpha)", "rgb(153, 94, 51)");
19268    test("hsl(from rebeccapurple h 20% l / alpha)", "rgb(102, 82, 122)");
19269    test("hsl(from rebeccapurple h s 20% / alpha)", "rgb(51, 25, 77)");
19270    test("hsl(from rebeccapurple h s l / .25)", "rgba(102, 51, 153, 0.25)");
19271    test(
19272      "hsl(from rgb(20%, 40%, 60%, 80%) 25 s l / alpha)",
19273      "rgba(153, 94, 51, 0.8)",
19274    );
19275    test(
19276      "hsl(from rgb(20%, 40%, 60%, 80%) 25deg s l / alpha)",
19277      "rgba(153, 94, 51, 0.8)",
19278    );
19279    test(
19280      "hsl(from rgb(20%, 40%, 60%, 80%) h 20% l / alpha)",
19281      "rgba(82, 102, 122, 0.8)",
19282    );
19283    test(
19284      "hsl(from rgb(20%, 40%, 60%, 80%) h s 20% / alpha)",
19285      "rgba(25, 51, 77, 0.8)",
19286    );
19287    test(
19288      "hsl(from rgb(20%, 40%, 60%, 80%) h s l / .2)",
19289      "rgba(51, 102, 153, 0.2)",
19290    );
19291
19292    // Testing valid permutation (types match).
19293    test("hsl(from rebeccapurple h l s)", "rgb(128, 77, 179)");
19294    test(
19295      "hsl(from rebeccapurple h calc(alpha * 100) l / calc(s / 100))",
19296      "rgba(102, 0, 204, 0.5)",
19297    );
19298    test(
19299      "hsl(from rebeccapurple h l l / calc(l / 100))",
19300      "rgba(102, 61, 143, 0.4)",
19301    );
19302    test(
19303      "hsl(from rebeccapurple h calc(alpha * 100) calc(alpha * 100) / calc(alpha * 100))",
19304      "rgb(255, 255, 255)",
19305    );
19306    test("hsl(from rgb(20%, 40%, 60%, 80%) h l s)", "rgb(77, 128, 179)");
19307    test(
19308      "hsl(from rgb(20%, 40%, 60%, 80%) h calc(alpha * 100) l / calc(s / 100))",
19309      "rgba(20, 102, 184, 0.5)",
19310    );
19311    test(
19312      "hsl(from rgb(20%, 40%, 60%, 80%) h l l / calc(l / 100))",
19313      "rgba(61, 102, 143, 0.4)",
19314    );
19315    test(
19316      "hsl(from rgb(20%, 40%, 60%, 80%) h calc(alpha * 100) calc(alpha * 100) / alpha)",
19317      "rgba(163, 204, 245, 0.8)",
19318    );
19319
19320    // Testing with calc().
19321    test("hsl(from rebeccapurple calc(h) calc(s) calc(l))", "rgb(102, 51, 153)");
19322    test(
19323      "hsl(from rgb(20%, 40%, 60%, 80%) calc(h) calc(s) calc(l) / calc(alpha))",
19324      "rgba(51, 102, 153, 0.8)",
19325    );
19326
19327    // Testing with 'none'.
19328    test("hsl(from rebeccapurple none none none)", "rgb(0, 0, 0)");
19329    test("hsl(from rebeccapurple none none none / none)", "rgba(0, 0, 0, 0)");
19330    test("hsl(from rebeccapurple h s none)", "rgb(0, 0, 0)");
19331    test("hsl(from rebeccapurple h s none / alpha)", "rgb(0, 0, 0)");
19332    test("hsl(from rebeccapurple h s l / none)", "rgba(102, 51, 153, 0)");
19333    test("hsl(from rebeccapurple none s l / alpha)", "rgb(153, 51, 51)");
19334    test(
19335      "hsl(from hsl(120deg 20% 50% / .5) h s none / alpha)",
19336      "rgba(0, 0, 0, 0.5)",
19337    );
19338    test(
19339      "hsl(from hsl(120deg 20% 50% / .5) h s l / none)",
19340      "rgba(102, 153, 102, 0)",
19341    );
19342    test(
19343      "hsl(from hsl(120deg 20% 50% / .5) none s l / alpha)",
19344      "rgba(153, 102, 102, 0.5)",
19345    );
19346    // FIXME: Clarify with spec editors if 'none' should pass through to the constants.
19347    test("hsl(from hsl(none none none) h s l)", "rgb(0, 0, 0)");
19348    test("hsl(from hsl(none none none / none) h s l / alpha)", "rgba(0, 0, 0, 0)");
19349    test("hsl(from hsl(120deg none 50% / .5) h s l)", "rgb(128, 128, 128)");
19350    test(
19351      "hsl(from hsl(120deg 20% 50% / none) h s l / alpha)",
19352      "rgba(102, 153, 102, 0)",
19353    );
19354    test(
19355      "hsl(from hsl(none 20% 50% / .5) h s l / alpha)",
19356      "rgba(153, 102, 102, 0.5)",
19357    );
19358
19359    // hwb(from ...)
19360
19361    // Testing no modifications.
19362    test("hwb(from rebeccapurple h w b)", "rgb(102, 51, 153)");
19363    test("hwb(from rebeccapurple h w b / alpha)", "rgb(102, 51, 153)");
19364    test(
19365      "hwb(from rgb(20%, 40%, 60%, 80%) h w b / alpha)",
19366      "rgba(51, 102, 153, 0.8)",
19367    );
19368    test(
19369      "hwb(from hsl(120deg 20% 50% / .5) h w b / alpha)",
19370      "rgba(102, 153, 102, 0.5)",
19371    );
19372
19373    // Test nesting relative colors.
19374    test("hwb(from hwb(from rebeccapurple h w b) h w b)", "rgb(102, 51, 153)");
19375
19376    // Testing non-sRGB origin colors to see gamut mapping.
19377    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).
19378    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).
19379    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,
19380    test("hwb(from lch(100% 116 334) h w b)", "rgb(255, 255, 255)"); // Naive clip based mapping would give rgb(255, 150, 255).
19381    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,
19382    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).
19383    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).
19384    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).
19385    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).
19386
19387    // Testing replacement with 0.
19388    test("hwb(from rebeccapurple 0 0% 0%)", "rgb(255, 0, 0)");
19389    test("hwb(from rebeccapurple 0deg 0% 0%)", "rgb(255, 0, 0)");
19390    test("hwb(from rebeccapurple 0 0% 0% / 0)", "rgba(255, 0, 0, 0)");
19391    test("hwb(from rebeccapurple 0deg 0% 0% / 0)", "rgba(255, 0, 0, 0)");
19392    test("hwb(from rebeccapurple 0 w b / alpha)", "rgb(153, 51, 51)");
19393    test("hwb(from rebeccapurple 0deg w b / alpha)", "rgb(153, 51, 51)");
19394    test("hwb(from rebeccapurple h 0% b / alpha)", "rgb(77, 0, 153)");
19395    test("hwb(from rebeccapurple h w 0% / alpha)", "rgb(153, 51, 255)");
19396    test("hwb(from rebeccapurple h w b / 0)", "rgba(102, 51, 153, 0)");
19397    test(
19398      "hwb(from rgb(20%, 40%, 60%, 80%) 0 w b / alpha)",
19399      "rgba(153, 51, 51, 0.8)",
19400    );
19401    test(
19402      "hwb(from rgb(20%, 40%, 60%, 80%) 0deg w b / alpha)",
19403      "rgba(153, 51, 51, 0.8)",
19404    );
19405    test(
19406      "hwb(from rgb(20%, 40%, 60%, 80%) h 0% b / alpha)",
19407      "rgba(0, 77, 153, 0.8)",
19408    );
19409    test(
19410      "hwb(from rgb(20%, 40%, 60%, 80%) h w 0% / alpha)",
19411      "rgba(51, 153, 255, 0.8)",
19412    );
19413    test("hwb(from rgb(20%, 40%, 60%, 80%) h w b / 0)", "rgba(51, 102, 153, 0)");
19414
19415    // Testing replacement with a constant.
19416    test("hwb(from rebeccapurple 25 w b / alpha)", "rgb(153, 94, 51)");
19417    test("hwb(from rebeccapurple 25deg w b / alpha)", "rgb(153, 94, 51)");
19418    test("hwb(from rebeccapurple h 20% b / alpha)", "rgb(102, 51, 153)");
19419    test("hwb(from rebeccapurple h w 20% / alpha)", "rgb(128, 51, 204)");
19420    test("hwb(from rebeccapurple h w b / .2)", "rgba(102, 51, 153, 0.2)");
19421    test(
19422      "hwb(from rgb(20%, 40%, 60%, 80%) 25 w b / alpha)",
19423      "rgba(153, 94, 51, 0.8)",
19424    );
19425    test(
19426      "hwb(from rgb(20%, 40%, 60%, 80%) 25deg w b / alpha)",
19427      "rgba(153, 94, 51, 0.8)",
19428    );
19429    test(
19430      "hwb(from rgb(20%, 40%, 60%, 80%) h 20% b / alpha)",
19431      "rgba(51, 102, 153, 0.8)",
19432    );
19433    test(
19434      "hwb(from rgb(20%, 40%, 60%, 80%) h w 20% / alpha)",
19435      "rgba(51, 128, 204, 0.8)",
19436    );
19437    test(
19438      "hwb(from rgb(20%, 40%, 60%, 80%) h w b / .2)",
19439      "rgba(51, 102, 153, 0.2)",
19440    );
19441
19442    // Testing valid permutation (types match).
19443    test("hwb(from rebeccapurple h b w)", "rgb(153, 102, 204)");
19444    test(
19445      "hwb(from rebeccapurple h calc(alpha * 100) w / calc(b / 100))",
19446      "rgba(213, 213, 213, 0.4)",
19447    );
19448    test(
19449      "hwb(from rebeccapurple h w w / calc(w / 100))",
19450      "rgba(128, 51, 204, 0.2)",
19451    );
19452    test(
19453      "hwb(from rebeccapurple h calc(alpha * 100) calc(alpha * 100) / alpha)",
19454      "rgb(128, 128, 128)",
19455    );
19456    test("hwb(from rgb(20%, 40%, 60%, 80%) h b w)", "rgb(102, 153, 204)");
19457    test(
19458      "hwb(from rgb(20%, 40%, 60%, 80%) h calc(alpha * 100) w / calc(b / 100))",
19459      "rgba(204, 204, 204, 0.4)",
19460    );
19461    test(
19462      "hwb(from rgb(20%, 40%, 60%, 80%) h w w / calc(w / 100))",
19463      "rgba(51, 128, 204, 0.2)",
19464    );
19465    test(
19466      "hwb(from rgb(20%, 40%, 60%, 80%) h calc(alpha * 100) calc(alpha * 100) / alpha)",
19467      "rgba(128, 128, 128, 0.8)",
19468    );
19469
19470    // Testing with calc().
19471    test("hwb(from rebeccapurple calc(h) calc(w) calc(b))", "rgb(102, 51, 153)");
19472    test(
19473      "hwb(from rgb(20%, 40%, 60%, 80%) calc(h) calc(w) calc(b) / calc(alpha))",
19474      "rgba(51, 102, 153, 0.8)",
19475    );
19476
19477    // Testing with 'none'.
19478    test("hwb(from rebeccapurple none none none)", "rgb(255, 0, 0)");
19479    test("hwb(from rebeccapurple none none none / none)", "rgba(255, 0, 0, 0)");
19480    test("hwb(from rebeccapurple h w none)", "rgb(153, 51, 255)");
19481    test("hwb(from rebeccapurple h w none / alpha)", "rgb(153, 51, 255)");
19482    test("hwb(from rebeccapurple h w b / none)", "rgba(102, 51, 153, 0)");
19483    test("hwb(from rebeccapurple none w b / alpha)", "rgb(153, 51, 51)");
19484    test(
19485      "hwb(from hwb(120deg 20% 50% / .5) h w none / alpha)",
19486      "rgba(51, 255, 51, 0.5)",
19487    );
19488    test(
19489      "hwb(from hwb(120deg 20% 50% / .5) h w b / none)",
19490      "rgba(51, 128, 51, 0)",
19491    );
19492    test(
19493      "hwb(from hwb(120deg 20% 50% / .5) none w b / alpha)",
19494      "rgba(128, 51, 51, 0.5)",
19495    );
19496    // FIXME: Clarify with spec editors if 'none' should pass through to the constants.
19497    test("hwb(from hwb(none none none) h w b)", "rgb(255, 0, 0)");
19498    test(
19499      "hwb(from hwb(none none none / none) h w b / alpha)",
19500      "rgba(255, 0, 0, 0)",
19501    );
19502    test("hwb(from hwb(120deg none 50% / .5) h w b)", "rgb(0, 128, 0)");
19503    test(
19504      "hwb(from hwb(120deg 20% 50% / none) h w b / alpha)",
19505      "rgba(51, 128, 51, 0)",
19506    );
19507    test(
19508      "hwb(from hwb(none 20% 50% / .5) h w b / alpha)",
19509      "rgba(128, 51, 51, 0.5)",
19510    );
19511
19512    for color_space in &["lab", "oklab"] {
19513      // Testing no modifications.
19514      test(
19515        &format!("{}(from {}(25% 20 50) l a b)", color_space, color_space),
19516        &format!("{}(25% 20 50)", color_space),
19517      );
19518      test(
19519        &format!("{}(from {}(25% 20 50) l a b / alpha)", color_space, color_space),
19520        &format!("{}(25% 20 50)", color_space),
19521      );
19522      test(
19523        &format!("{}(from {}(25% 20 50 / 40%) l a b / alpha)", color_space, color_space),
19524        &format!("{}(25% 20 50 / 0.4)", color_space),
19525      );
19526      test(
19527        &format!(
19528          "{}(from {}(200% 300 400 / 500%) l a b / alpha)",
19529          color_space, color_space
19530        ),
19531        &format!("{}(200% 300 400)", color_space),
19532      );
19533      test(
19534        &format!(
19535          "{}(from {}(-200% -300 -400 / -500%) l a b / alpha)",
19536          color_space, color_space
19537        ),
19538        &format!("{}(0% -300 -400 / 0)", color_space),
19539      );
19540
19541      // Test nesting relative colors.
19542      test(
19543        &format!(
19544          "{}(from {}(from {}(25% 20 50) l a b) l a b)",
19545          color_space, color_space, color_space
19546        ),
19547        &format!("{}(25% 20 50)", color_space),
19548      );
19549
19550      // Testing non-${colorSpace} origin to see conversion.
19551      test(
19552        &format!("{}(from color(display-p3 0 0 0) l a b / alpha)", color_space),
19553        &format!("{}(0% 0 0)", color_space),
19554      );
19555
19556      // Testing replacement with 0.
19557      test(
19558        &format!("{}(from {}(25% 20 50) 0% 0 0)", color_space, color_space),
19559        &format!("{}(0% 0 0)", color_space),
19560      );
19561      test(
19562        &format!("{}(from {}(25% 20 50) 0% 0 0 / 0)", color_space, color_space),
19563        &format!("{}(0% 0 0 / 0)", color_space),
19564      );
19565      test(
19566        &format!("{}(from {}(25% 20 50) 0% a b / alpha)", color_space, color_space),
19567        &format!("{}(0% 20 50)", color_space),
19568      );
19569      test(
19570        &format!("{}(from {}(25% 20 50) l 0 b / alpha)", color_space, color_space),
19571        &format!("{}(25% 0 50)", color_space),
19572      );
19573      test(
19574        &format!("{}(from {}(25% 20 50) l a 0 / alpha)", color_space, color_space),
19575        &format!("{}(25% 20 0)", color_space),
19576      );
19577      test(
19578        &format!("{}(from {}(25% 20 50) l a b / 0)", color_space, color_space),
19579        &format!("{}(25% 20 50 / 0)", color_space),
19580      );
19581      test(
19582        &format!("{}(from {}(25% 20 50 / 40%) 0% a b / alpha)", color_space, color_space),
19583        &format!("{}(0% 20 50 / 0.4)", color_space),
19584      );
19585      test(
19586        &format!("{}(from {}(25% 20 50 / 40%) l 0 b / alpha)", color_space, color_space),
19587        &format!("{}(25% 0 50 / 0.4)", color_space),
19588      );
19589      test(
19590        &format!("{}(from {}(25% 20 50 / 40%) l a 0 / alpha)", color_space, color_space),
19591        &format!("{}(25% 20 0 / 0.4)", color_space),
19592      );
19593      test(
19594        &format!("{}(from {}(25% 20 50 / 40%) l a b / 0)", color_space, color_space),
19595        &format!("{}(25% 20 50 / 0)", color_space),
19596      );
19597
19598      // Testing replacement with a constant.
19599      test(
19600        &format!("{}(from {}(25% 20 50) 35% a b / alpha)", color_space, color_space),
19601        &format!("{}(35% 20 50)", color_space),
19602      );
19603      test(
19604        &format!("{}(from {}(25% 20 50) l 35 b / alpha)", color_space, color_space),
19605        &format!("{}(25% 35 50)", color_space),
19606      );
19607      test(
19608        &format!("{}(from {}(25% 20 50) l a 35 / alpha)", color_space, color_space),
19609        &format!("{}(25% 20 35)", color_space),
19610      );
19611      test(
19612        &format!("{}(from {}(25% 20 50) l a b / .35)", color_space, color_space),
19613        &format!("{}(25% 20 50 / 0.35)", color_space),
19614      );
19615      test(
19616        &format!("{}(from {}(25% 20 50 / 40%) 35% a b / alpha)", color_space, color_space),
19617        &format!("{}(35% 20 50 / 0.4)", color_space),
19618      );
19619      test(
19620        &format!("{}(from {}(25% 20 50 / 40%) l 35 b / alpha)", color_space, color_space),
19621        &format!("{}(25% 35 50 / 0.4)", color_space),
19622      );
19623      test(
19624        &format!("{}(from {}(25% 20 50 / 40%) l a 35 / alpha)", color_space, color_space),
19625        &format!("{}(25% 20 35 / 0.4)", color_space),
19626      );
19627      test(
19628        &format!("{}(from {}(25% 20 50 / 40%) l a b / .35)", color_space, color_space),
19629        &format!("{}(25% 20 50 / 0.35)", color_space),
19630      );
19631      test(
19632        &format!(
19633          "{}(from {}(70% 45 30 / 40%) 200% 300 400 / 500)",
19634          color_space, color_space
19635        ),
19636        &format!("{}(200% 300 400)", color_space),
19637      );
19638      test(
19639        &format!(
19640          "{}(from {}(70% 45 30 / 40%) -200% -300 -400 / -500)",
19641          color_space, color_space
19642        ),
19643        &format!("{}(0% -300 -400 / 0)", color_space),
19644      );
19645
19646      // Testing valid permutation (types match).
19647      test(
19648        &format!("{}(from {}(25% 20 50) l b a)", color_space, color_space),
19649        &format!("{}(25% 50 20)", color_space),
19650      );
19651      test(
19652        &format!("{}(from {}(25% 20 50) l a a / a)", color_space, color_space),
19653        &format!("{}(25% 20 20)", color_space),
19654      );
19655      test(
19656        &format!("{}(from {}(25% 20 50 / 40%) l b a)", color_space, color_space),
19657        &format!("{}(25% 50 20)", color_space),
19658      );
19659      test(
19660        &format!("{}(from {}(25% 20 50 / 40%) l a a / a)", color_space, color_space),
19661        &format!("{}(25% 20 20)", color_space),
19662      );
19663
19664      // Testing with calc().
19665      test(
19666        &format!(
19667          "{}(from {}(25% 20 50) calc(l) calc(a) calc(b))",
19668          color_space, color_space
19669        ),
19670        &format!("{}(25% 20 50)", color_space),
19671      );
19672      test(
19673        &format!(
19674          "{}(from {}(25% 20 50 / 40%) calc(l) calc(a) calc(b) / calc(alpha))",
19675          color_space, color_space
19676        ),
19677        &format!("{}(25% 20 50 / 0.4)", color_space),
19678      );
19679
19680      // Testing with 'none'.
19681      test(
19682        &format!("{}(from {}(25% 20 50) none none none)", color_space, color_space),
19683        &format!("{}(none none none)", color_space),
19684      );
19685      test(
19686        &format!("{}(from {}(25% 20 50) none none none / none)", color_space, color_space),
19687        &format!("{}(none none none / none)", color_space),
19688      );
19689      test(
19690        &format!("{}(from {}(25% 20 50) l a none)", color_space, color_space),
19691        &format!("{}(25% 20 none)", color_space),
19692      );
19693      test(
19694        &format!("{}(from {}(25% 20 50) l a none / alpha)", color_space, color_space),
19695        &format!("{}(25% 20 none)", color_space),
19696      );
19697      test(
19698        &format!("{}(from {}(25% 20 50) l a b / none)", color_space, color_space),
19699        &format!("{}(25% 20 50 / none)", color_space),
19700      );
19701      test(
19702        &format!(
19703          "{}(from {}(25% 20 50 / 40%) l a none / alpha)",
19704          color_space, color_space
19705        ),
19706        &format!("{}(25% 20 none / 0.4)", color_space),
19707      );
19708      test(
19709        &format!("{}(from {}(25% 20 50 / 40%) l a b / none)", color_space, color_space),
19710        &format!("{}(25% 20 50 / none)", color_space),
19711      );
19712      // FIXME: Clarify with spec editors if 'none' should pass through to the constants.
19713      test(
19714        &format!("{}(from {}(none none none) l a b)", color_space, color_space),
19715        &format!("{}(0% 0 0)", color_space),
19716      );
19717      test(
19718        &format!(
19719          "{}(from {}(none none none / none) l a b / alpha)",
19720          color_space, color_space
19721        ),
19722        &format!("{}(0% 0 0 / 0)", color_space),
19723      );
19724      test(
19725        &format!("{}(from {}(25% none 50) l a b)", color_space, color_space),
19726        &format!("{}(25% 0 50)", color_space),
19727      );
19728      test(
19729        &format!("{}(from {}(25% 20 50 / none) l a b / alpha)", color_space, color_space),
19730        &format!("{}(25% 20 50 / 0)", color_space),
19731      );
19732    }
19733
19734    // test_valid_value\(`color`, `\$\{colorSpace\}\(from \$\{colorSpace\}\((.*?)`,\s*`\$\{colorSpace\}(.*?)`\)
19735    // test(&format!("{}(from {}($1", color_space, color_space), &format!("{}$2", color_space))
19736
19737    for color_space in &["lch", "oklch"] {
19738      // Testing no modifications.
19739      test(
19740        &format!("{}(from {}(70% 45 30) l c h)", color_space, color_space),
19741        &format!("{}(70% 45 30)", color_space),
19742      );
19743      test(
19744        &format!("{}(from {}(70% 45 30) l c h / alpha)", color_space, color_space),
19745        &format!("{}(70% 45 30)", color_space),
19746      );
19747      test(
19748        &format!("{}(from {}(70% 45 30 / 40%) l c h / alpha)", color_space, color_space),
19749        &format!("{}(70% 45 30 / 0.4)", color_space),
19750      );
19751      test(
19752        &format!(
19753          "{}(from {}(200% 300 400 / 500%) l c h / alpha)",
19754          color_space, color_space
19755        ),
19756        &format!("{}(200% 300 40)", color_space),
19757      );
19758      test(
19759        &format!(
19760          "{}(from {}(-200% -300 -400 / -500%) l c h / alpha)",
19761          color_space, color_space
19762        ),
19763        &format!("{}(0% 0 320 / 0)", color_space),
19764      );
19765
19766      // Test nesting relative colors.
19767      test(
19768        &format!(
19769          "{}(from {}(from {}(70% 45 30) l c h) l c h)",
19770          color_space, color_space, color_space
19771        ),
19772        &format!("{}(70% 45 30)", color_space),
19773      );
19774
19775      // Testing non-sRGB origin colors (no gamut mapping will happen since the destination is not a bounded RGB color space).
19776      test(
19777        &format!("{}(from color(display-p3 0 0 0) l c h / alpha)", color_space),
19778        &format!("{}(0% 0 0)", color_space),
19779      );
19780
19781      // Testing replacement with 0.
19782      test(
19783        &format!("{}(from {}(70% 45 30) 0% 0 0)", color_space, color_space),
19784        &format!("{}(0% 0 0)", color_space),
19785      );
19786      test(
19787        &format!("{}(from {}(70% 45 30) 0% 0 0deg)", color_space, color_space),
19788        &format!("{}(0% 0 0)", color_space),
19789      );
19790      test(
19791        &format!("{}(from {}(70% 45 30) 0% 0 0 / 0)", color_space, color_space),
19792        &format!("{}(0% 0 0 / 0)", color_space),
19793      );
19794      test(
19795        &format!("{}(from {}(70% 45 30) 0% 0 0deg / 0)", color_space, color_space),
19796        &format!("{}(0% 0 0 / 0)", color_space),
19797      );
19798      test(
19799        &format!("{}(from {}(70% 45 30) 0% c h / alpha)", color_space, color_space),
19800        &format!("{}(0% 45 30)", color_space),
19801      );
19802      test(
19803        &format!("{}(from {}(70% 45 30) l 0 h / alpha)", color_space, color_space),
19804        &format!("{}(70% 0 30)", color_space),
19805      );
19806      test(
19807        &format!("{}(from {}(70% 45 30) l c 0 / alpha)", color_space, color_space),
19808        &format!("{}(70% 45 0)", color_space),
19809      );
19810      test(
19811        &format!("{}(from {}(70% 45 30) l c 0deg / alpha)", color_space, color_space),
19812        &format!("{}(70% 45 0)", color_space),
19813      );
19814      test(
19815        &format!("{}(from {}(70% 45 30) l c h / 0)", color_space, color_space),
19816        &format!("{}(70% 45 30 / 0)", color_space),
19817      );
19818      test(
19819        &format!("{}(from {}(70% 45 30 / 40%) 0% c h / alpha)", color_space, color_space),
19820        &format!("{}(0% 45 30 / 0.4)", color_space),
19821      );
19822      test(
19823        &format!("{}(from {}(70% 45 30 / 40%) l 0 h / alpha)", color_space, color_space),
19824        &format!("{}(70% 0 30 / 0.4)", color_space),
19825      );
19826      test(
19827        &format!("{}(from {}(70% 45 30 / 40%) l c 0 / alpha)", color_space, color_space),
19828        &format!("{}(70% 45 0 / 0.4)", color_space),
19829      );
19830      test(
19831        &format!(
19832          "{}(from {}(70% 45 30 / 40%) l c 0deg / alpha)",
19833          color_space, color_space
19834        ),
19835        &format!("{}(70% 45 0 / 0.4)", color_space),
19836      );
19837      test(
19838        &format!("{}(from {}(70% 45 30 / 40%) l c h / 0)", color_space, color_space),
19839        &format!("{}(70% 45 30 / 0)", color_space),
19840      );
19841
19842      // Testing replacement with a constant.
19843      test(
19844        &format!("{}(from {}(70% 45 30) 25% c h / alpha)", color_space, color_space),
19845        &format!("{}(25% 45 30)", color_space),
19846      );
19847      test(
19848        &format!("{}(from {}(70% 45 30) l 25 h / alpha)", color_space, color_space),
19849        &format!("{}(70% 25 30)", color_space),
19850      );
19851      test(
19852        &format!("{}(from {}(70% 45 30) l c 25 / alpha)", color_space, color_space),
19853        &format!("{}(70% 45 25)", color_space),
19854      );
19855      test(
19856        &format!("{}(from {}(70% 45 30) l c 25deg / alpha)", color_space, color_space),
19857        &format!("{}(70% 45 25)", color_space),
19858      );
19859      test(
19860        &format!("{}(from {}(70% 45 30) l c h / .25)", color_space, color_space),
19861        &format!("{}(70% 45 30 / 0.25)", color_space),
19862      );
19863      test(
19864        &format!("{}(from {}(70% 45 30 / 40%) 25% c h / alpha)", color_space, color_space),
19865        &format!("{}(25% 45 30 / 0.4)", color_space),
19866      );
19867      test(
19868        &format!("{}(from {}(70% 45 30 / 40%) l 25 h / alpha)", color_space, color_space),
19869        &format!("{}(70% 25 30 / 0.4)", color_space),
19870      );
19871      test(
19872        &format!("{}(from {}(70% 45 30 / 40%) l c 25 / alpha)", color_space, color_space),
19873        &format!("{}(70% 45 25 / 0.4)", color_space),
19874      );
19875      test(
19876        &format!(
19877          "{}(from {}(70% 45 30 / 40%) l c 25deg / alpha)",
19878          color_space, color_space
19879        ),
19880        &format!("{}(70% 45 25 / 0.4)", color_space),
19881      );
19882      test(
19883        &format!("{}(from {}(70% 45 30 / 40%) l c h / .25)", color_space, color_space),
19884        &format!("{}(70% 45 30 / 0.25)", color_space),
19885      );
19886      test(
19887        &format!(
19888          "{}(from {}(70% 45 30 / 40%) 200% 300 400 / 500)",
19889          color_space, color_space
19890        ),
19891        &format!("{}(200% 300 400)", color_space),
19892      );
19893      test(
19894        &format!(
19895          "{}(from {}(70% 45 30 / 40%) -200% -300 -400 / -500)",
19896          color_space, color_space
19897        ),
19898        &format!("{}(0% 0 -400 / 0)", color_space),
19899      );
19900      test(
19901        &format!(
19902          "{}(from {}(70% 45 30 / 40%) 50% 120 400deg / 500)",
19903          color_space, color_space
19904        ),
19905        &format!("{}(50% 120 400)", color_space),
19906      );
19907      test(
19908        &format!(
19909          "{}(from {}(70% 45 30 / 40%) 50% 120 -400deg / -500)",
19910          color_space, color_space
19911        ),
19912        &format!("{}(50% 120 -400 / 0)", color_space),
19913      );
19914
19915      // Testing valid permutation (types match).
19916      // NOTE: 'c' is a valid hue, as hue is <angle>|<number>.
19917      test(
19918        &format!("{}(from {}(70% 45 30) alpha c h / l)", color_space, color_space),
19919        &format!(
19920          "{}(1 45 30 / {})",
19921          color_space,
19922          if *color_space == "lch" { "1" } else { ".7" }
19923        ),
19924      );
19925      test(
19926        &format!("{}(from {}(70% 45 30) l c c / alpha)", color_space, color_space),
19927        &format!("{}(70% 45 45)", color_space),
19928      );
19929      test(
19930        &format!("{}(from {}(70% 45 30) alpha c h / alpha)", color_space, color_space),
19931        &format!("{}(1 45 30)", color_space),
19932      );
19933      test(
19934        &format!("{}(from {}(70% 45 30) alpha c c / alpha)", color_space, color_space),
19935        &format!("{}(1 45 45)", color_space),
19936      );
19937      test(
19938        &format!("{}(from {}(70% 45 30 / 40%) alpha c h / l)", color_space, color_space),
19939        &format!(
19940          "{}(.4 45 30 / {})",
19941          color_space,
19942          if *color_space == "lch" { "1" } else { ".7" }
19943        ),
19944      );
19945      test(
19946        &format!("{}(from {}(70% 45 30 / 40%) l c c / alpha)", color_space, color_space),
19947        &format!("{}(70% 45 45 / 0.4)", color_space),
19948      );
19949      test(
19950        &format!(
19951          "{}(from {}(70% 45 30 / 40%) alpha c h / alpha)",
19952          color_space, color_space
19953        ),
19954        &format!("{}(.4 45 30 / 0.4)", color_space),
19955      );
19956      test(
19957        &format!(
19958          "{}(from {}(70% 45 30 / 40%) alpha c c / alpha)",
19959          color_space, color_space
19960        ),
19961        &format!("{}(.4 45 45 / 0.4)", color_space),
19962      );
19963
19964      // Testing with calc().
19965      test(
19966        &format!(
19967          "{}(from {}(70% 45 30) calc(l) calc(c) calc(h))",
19968          color_space, color_space
19969        ),
19970        &format!("{}(70% 45 30)", color_space),
19971      );
19972      test(
19973        &format!(
19974          "{}(from {}(70% 45 30 / 40%) calc(l) calc(c) calc(h) / calc(alpha))",
19975          color_space, color_space
19976        ),
19977        &format!("{}(70% 45 30 / 0.4)", color_space),
19978      );
19979
19980      // Testing with 'none'.
19981      test(
19982        &format!("{}(from {}(70% 45 30) none none none)", color_space, color_space),
19983        &format!("{}(none none none)", color_space),
19984      );
19985      test(
19986        &format!("{}(from {}(70% 45 30) none none none / none)", color_space, color_space),
19987        &format!("{}(none none none / none)", color_space),
19988      );
19989      test(
19990        &format!("{}(from {}(70% 45 30) l c none)", color_space, color_space),
19991        &format!("{}(70% 45 none)", color_space),
19992      );
19993      test(
19994        &format!("{}(from {}(70% 45 30) l c none / alpha)", color_space, color_space),
19995        &format!("{}(70% 45 none)", color_space),
19996      );
19997      test(
19998        &format!("{}(from {}(70% 45 30) l c h / none)", color_space, color_space),
19999        &format!("{}(70% 45 30 / none)", color_space),
20000      );
20001      test(
20002        &format!(
20003          "{}(from {}(70% 45 30 / 40%) l c none / alpha)",
20004          color_space, color_space
20005        ),
20006        &format!("{}(70% 45 none / 0.4)", color_space),
20007      );
20008      test(
20009        &format!("{}(from {}(70% 45 30 / 40%) l c h / none)", color_space, color_space),
20010        &format!("{}(70% 45 30 / none)", color_space),
20011      );
20012      // FIXME: Clarify with spec editors if 'none' should pass through to the constants.
20013      test(
20014        &format!("{}(from {}(none none none) l c h)", color_space, color_space),
20015        &format!("{}(0% 0 0)", color_space),
20016      );
20017      test(
20018        &format!(
20019          "{}(from {}(none none none / none) l c h / alpha)",
20020          color_space, color_space
20021        ),
20022        &format!("{}(0% 0 0 / 0)", color_space),
20023      );
20024      test(
20025        &format!("{}(from {}(70% none 30) l c h)", color_space, color_space),
20026        &format!("{}(70% 0 30)", color_space),
20027      );
20028      test(
20029        &format!("{}(from {}(70% 45 30 / none) l c h / alpha)", color_space, color_space),
20030        &format!("{}(70% 45 30 / 0)", color_space),
20031      );
20032    }
20033
20034    // test_valid_value\(`color`, `color\(from color\(\$\{colorSpace\}(.*?) \$\{colorSpace\}(.*?)`,\s*`color\(\$\{colorSpace\}(.*?)`\)
20035    // test(&format!("color(from color({}$1 {}$2", color_space, color_space), &format!("color({}$3", color_space))
20036
20037    for color_space in &["srgb", "srgb-linear", "a98-rgb", "rec2020", "prophoto-rgb"] {
20038      // Testing no modifications.
20039      test(
20040        &format!("color(from color({} 0.7 0.5 0.3) {} r g b)", color_space, color_space),
20041        &format!("color({} 0.7 0.5 0.3)", color_space),
20042      );
20043      test(
20044        &format!(
20045          "color(from color({} 0.7 0.5 0.3) {} r g b / alpha)",
20046          color_space, color_space
20047        ),
20048        &format!("color({} 0.7 0.5 0.3)", color_space),
20049      );
20050      test(
20051        &format!(
20052          "color(from color({} 0.7 0.5 0.3 / 40%) {} r g b)",
20053          color_space, color_space
20054        ),
20055        &format!("color({} 0.7 0.5 0.3)", color_space),
20056      );
20057      test(
20058        &format!(
20059          "color(from color({} 0.7 0.5 0.3 / 40%) {} r g b / alpha)",
20060          color_space, color_space
20061        ),
20062        &format!("color({} 0.7 0.5 0.3 / 0.4)", color_space),
20063      );
20064
20065      // Test nesting relative colors.
20066      test(
20067        &format!(
20068          "color(from color(from color({} 0.7 0.5 0.3) {} r g b) {} r g b)",
20069          color_space, color_space, color_space
20070        ),
20071        &format!("color({} 0.7 0.5 0.3)", color_space),
20072      );
20073
20074      // Testing replacement with 0.
20075      test(
20076        &format!("color(from color({} 0.7 0.5 0.3) {} 0 0 0)", color_space, color_space),
20077        &format!("color({} 0 0 0)", color_space),
20078      );
20079      test(
20080        &format!(
20081          "color(from color({} 0.7 0.5 0.3) {} 0 0 0 / 0)",
20082          color_space, color_space
20083        ),
20084        &format!("color({} 0 0 0 / 0)", color_space),
20085      );
20086      test(
20087        &format!(
20088          "color(from color({} 0.7 0.5 0.3) {} 0 g b / alpha)",
20089          color_space, color_space
20090        ),
20091        &format!("color({} 0 0.5 0.3)", color_space),
20092      );
20093      test(
20094        &format!(
20095          "color(from color({} 0.7 0.5 0.3) {} r 0 b / alpha)",
20096          color_space, color_space
20097        ),
20098        &format!("color({} 0.7 0 0.3)", color_space),
20099      );
20100      test(
20101        &format!(
20102          "color(from color({} 0.7 0.5 0.3) {} r g 0 / alpha)",
20103          color_space, color_space
20104        ),
20105        &format!("color({} 0.7 0.5 0)", color_space),
20106      );
20107      test(
20108        &format!(
20109          "color(from color({} 0.7 0.5 0.3) {} r g b / 0)",
20110          color_space, color_space
20111        ),
20112        &format!("color({} 0.7 0.5 0.3 / 0)", color_space),
20113      );
20114      test(
20115        &format!(
20116          "color(from color({} 0.7 0.5 0.3 / 40%) {} 0 g b / alpha)",
20117          color_space, color_space
20118        ),
20119        &format!("color({} 0 0.5 0.3 / 0.4)", color_space),
20120      );
20121      test(
20122        &format!(
20123          "color(from color({} 0.7 0.5 0.3 / 40%) {} r 0 b / alpha)",
20124          color_space, color_space
20125        ),
20126        &format!("color({} 0.7 0 0.3 / 0.4)", color_space),
20127      );
20128      test(
20129        &format!(
20130          "color(from color({} 0.7 0.5 0.3 / 40%) {} r g 0 / alpha)",
20131          color_space, color_space
20132        ),
20133        &format!("color({} 0.7 0.5 0 / 0.4)", color_space),
20134      );
20135      test(
20136        &format!(
20137          "color(from color({} 0.7 0.5 0.3 / 40%) {} r g b / 0)",
20138          color_space, color_space
20139        ),
20140        &format!("color({} 0.7 0.5 0.3 / 0)", color_space),
20141      );
20142
20143      // Testing replacement with a constant.
20144      test(
20145        &format!(
20146          "color(from color({} 0.7 0.5 0.3) {} 0.2 g b / alpha)",
20147          color_space, color_space
20148        ),
20149        &format!("color({} 0.2 0.5 0.3)", color_space),
20150      );
20151      test(
20152        &format!(
20153          "color(from color({} 0.7 0.5 0.3) {} 20% g b / alpha)",
20154          color_space, color_space
20155        ),
20156        &format!("color({} 0.2 0.5 0.3)", color_space),
20157      );
20158      test(
20159        &format!(
20160          "color(from color({} 0.7 0.5 0.3) {} r 0.2 b / alpha)",
20161          color_space, color_space
20162        ),
20163        &format!("color({} 0.7 0.2 0.3)", color_space),
20164      );
20165      test(
20166        &format!(
20167          "color(from color({} 0.7 0.5 0.3) {} r 20% b / alpha)",
20168          color_space, color_space
20169        ),
20170        &format!("color({} 0.7 0.2 0.3)", color_space),
20171      );
20172      test(
20173        &format!(
20174          "color(from color({} 0.7 0.5 0.3) {} r g 0.2 / alpha)",
20175          color_space, color_space
20176        ),
20177        &format!("color({} 0.7 0.5 0.2)", color_space),
20178      );
20179      test(
20180        &format!(
20181          "color(from color({} 0.7 0.5 0.3) {} r g 20% / alpha)",
20182          color_space, color_space
20183        ),
20184        &format!("color({} 0.7 0.5 0.2)", color_space),
20185      );
20186      test(
20187        &format!(
20188          "color(from color({} 0.7 0.5 0.3) {} r g b / 0.2)",
20189          color_space, color_space
20190        ),
20191        &format!("color({} 0.7 0.5 0.3 / 0.2)", color_space),
20192      );
20193      test(
20194        &format!(
20195          "color(from color({} 0.7 0.5 0.3) {} r g b / 20%)",
20196          color_space, color_space
20197        ),
20198        &format!("color({} 0.7 0.5 0.3 / 0.2)", color_space),
20199      );
20200      test(
20201        &format!(
20202          "color(from color({} 0.7 0.5 0.3 / 40%) {} 0.2 g b / alpha)",
20203          color_space, color_space
20204        ),
20205        &format!("color({} 0.2 0.5 0.3 / 0.4)", color_space),
20206      );
20207      test(
20208        &format!(
20209          "color(from color({} 0.7 0.5 0.3 / 40%) {} 20% g b / alpha)",
20210          color_space, color_space
20211        ),
20212        &format!("color({} 0.2 0.5 0.3 / 0.4)", color_space),
20213      );
20214      test(
20215        &format!(
20216          "color(from color({} 0.7 0.5 0.3 / 40%) {} r 0.2 b / alpha)",
20217          color_space, color_space
20218        ),
20219        &format!("color({} 0.7 0.2 0.3 / 0.4)", color_space),
20220      );
20221      test(
20222        &format!(
20223          "color(from color({} 0.7 0.5 0.3 / 40%) {} r 20% b / alpha)",
20224          color_space, color_space
20225        ),
20226        &format!("color({} 0.7 0.2 0.3 / 0.4)", color_space),
20227      );
20228      test(
20229        &format!(
20230          "color(from color({} 0.7 0.5 0.3 / 40%) {} r g 0.2 / alpha)",
20231          color_space, color_space
20232        ),
20233        &format!("color({} 0.7 0.5 0.2 / 0.4)", color_space),
20234      );
20235      test(
20236        &format!(
20237          "color(from color({} 0.7 0.5 0.3 / 40%) {} r g 20% / alpha)",
20238          color_space, color_space
20239        ),
20240        &format!("color({} 0.7 0.5 0.2 / 0.4)", color_space),
20241      );
20242      test(
20243        &format!(
20244          "color(from color({} 0.7 0.5 0.3 / 40%) {} r g b / 0.2)",
20245          color_space, color_space
20246        ),
20247        &format!("color({} 0.7 0.5 0.3 / 0.2)", color_space),
20248      );
20249      test(
20250        &format!(
20251          "color(from color({} 0.7 0.5 0.3 / 40%) {} r g b / 20%)",
20252          color_space, color_space
20253        ),
20254        &format!("color({} 0.7 0.5 0.3 / 0.2)", color_space),
20255      );
20256      test(
20257        &format!("color(from color({} 0.7 0.5 0.3) {} 2 3 4)", color_space, color_space),
20258        &format!("color({} 2 3 4)", color_space),
20259      );
20260      test(
20261        &format!(
20262          "color(from color({} 0.7 0.5 0.3) {} 2 3 4 / 5)",
20263          color_space, color_space
20264        ),
20265        &format!("color({} 2 3 4)", color_space),
20266      );
20267      test(
20268        &format!(
20269          "color(from color({} 0.7 0.5 0.3) {} -2 -3 -4)",
20270          color_space, color_space
20271        ),
20272        &format!("color({} -2 -3 -4)", color_space),
20273      );
20274      test(
20275        &format!(
20276          "color(from color({} 0.7 0.5 0.3) {} -2 -3 -4 / -5)",
20277          color_space, color_space
20278        ),
20279        &format!("color({} -2 -3 -4 / 0)", color_space),
20280      );
20281      test(
20282        &format!(
20283          "color(from color({} 0.7 0.5 0.3) {} 200% 300% 400%)",
20284          color_space, color_space
20285        ),
20286        &format!("color({} 2 3 4)", color_space),
20287      );
20288      test(
20289        &format!(
20290          "color(from color({} 0.7 0.5 0.3) {} 200% 300% 400% / 500%)",
20291          color_space, color_space
20292        ),
20293        &format!("color({} 2 3 4)", color_space),
20294      );
20295      test(
20296        &format!(
20297          "color(from color({} 0.7 0.5 0.3) {} -200% -300% -400%)",
20298          color_space, color_space
20299        ),
20300        &format!("color({} -2 -3 -4)", color_space),
20301      );
20302      test(
20303        &format!(
20304          "color(from color({} 0.7 0.5 0.3) {} -200% -300% -400% / -500%)",
20305          color_space, color_space
20306        ),
20307        &format!("color({} -2 -3 -4 / 0)", color_space),
20308      );
20309
20310      // Testing valid permutation (types match).
20311      test(
20312        &format!("color(from color({} 0.7 0.5 0.3) {} g b r)", color_space, color_space),
20313        &format!("color({} 0.5 0.3 0.7)", color_space),
20314      );
20315      test(
20316        &format!(
20317          "color(from color({} 0.7 0.5 0.3) {} b alpha r / g)",
20318          color_space, color_space
20319        ),
20320        &format!("color({} 0.3 1 0.7 / 0.5)", color_space),
20321      );
20322      test(
20323        &format!(
20324          "color(from color({} 0.7 0.5 0.3) {} r r r / r)",
20325          color_space, color_space
20326        ),
20327        &format!("color({} 0.7 0.7 0.7 / 0.7)", color_space),
20328      );
20329      test(
20330        &format!(
20331          "color(from color({} 0.7 0.5 0.3) {} alpha alpha alpha / alpha)",
20332          color_space, color_space
20333        ),
20334        &format!("color({} 1 1 1)", color_space),
20335      );
20336      test(
20337        &format!(
20338          "color(from color({} 0.7 0.5 0.3 / 40%) {} g b r)",
20339          color_space, color_space
20340        ),
20341        &format!("color({} 0.5 0.3 0.7)", color_space),
20342      );
20343      test(
20344        &format!(
20345          "color(from color({} 0.7 0.5 0.3 / 40%) {} b alpha r / g)",
20346          color_space, color_space
20347        ),
20348        &format!("color({} 0.3 0.4 0.7 / 0.5)", color_space),
20349      );
20350      test(
20351        &format!(
20352          "color(from color({} 0.7 0.5 0.3 / 40%) {} r r r / r)",
20353          color_space, color_space
20354        ),
20355        &format!("color({} 0.7 0.7 0.7 / 0.7)", color_space),
20356      );
20357      test(
20358        &format!(
20359          "color(from color({} 0.7 0.5 0.3 / 40%) {} alpha alpha alpha / alpha)",
20360          color_space, color_space
20361        ),
20362        &format!("color({} 0.4 0.4 0.4 / 0.4)", color_space),
20363      );
20364
20365      // Testing out of gamut components.
20366      test(
20367        &format!("color(from color({} 1.7 1.5 1.3) {} r g b)", color_space, color_space),
20368        &format!("color({} 1.7 1.5 1.3)", color_space),
20369      );
20370      test(
20371        &format!(
20372          "color(from color({} 1.7 1.5 1.3) {} r g b / alpha)",
20373          color_space, color_space
20374        ),
20375        &format!("color({} 1.7 1.5 1.3)", color_space),
20376      );
20377      test(
20378        &format!(
20379          "color(from color({} 1.7 1.5 1.3 / 140%) {} r g b)",
20380          color_space, color_space
20381        ),
20382        &format!("color({} 1.7 1.5 1.3)", color_space),
20383      );
20384      test(
20385        &format!(
20386          "color(from color({} 1.7 1.5 1.3 / 140%) {} r g b / alpha)",
20387          color_space, color_space
20388        ),
20389        &format!("color({} 1.7 1.5 1.3)", color_space),
20390      );
20391      test(
20392        &format!(
20393          "color(from color({} -0.7 -0.5 -0.3) {} r g b)",
20394          color_space, color_space
20395        ),
20396        &format!("color({} -0.7 -0.5 -0.3)", color_space),
20397      );
20398      test(
20399        &format!(
20400          "color(from color({} -0.7 -0.5 -0.3) {} r g b / alpha)",
20401          color_space, color_space
20402        ),
20403        &format!("color({} -0.7 -0.5 -0.3)", color_space),
20404      );
20405      test(
20406        &format!(
20407          "color(from color({} -0.7 -0.5 -0.3 / -40%) {} r g b)",
20408          color_space, color_space
20409        ),
20410        &format!("color({} -0.7 -0.5 -0.3)", color_space),
20411      );
20412      test(
20413        &format!(
20414          "color(from color({} -0.7 -0.5 -0.3 / -40%) {} r g b / alpha)",
20415          color_space, color_space
20416        ),
20417        &format!("color({} -0.7 -0.5 -0.3 / 0)", color_space),
20418      );
20419
20420      // Testing with calc().
20421      test(
20422        &format!(
20423          "color(from color({} 0.7 0.5 0.3) {} calc(r) calc(g) calc(b))",
20424          color_space, color_space
20425        ),
20426        &format!("color({} 0.7 0.5 0.3)", color_space),
20427      );
20428      test(
20429        &format!(
20430          "color(from color({} 0.7 0.5 0.3 / 40%) {} calc(r) calc(g) calc(b) / calc(alpha))",
20431          color_space, color_space
20432        ),
20433        &format!("color({} 0.7 0.5 0.3 / 0.4)", color_space),
20434      );
20435
20436      // Testing with 'none'.
20437      test(
20438        &format!(
20439          "color(from color({} 0.7 0.5 0.3) {} none none none)",
20440          color_space, color_space
20441        ),
20442        &format!("color({} none none none)", color_space),
20443      );
20444      test(
20445        &format!(
20446          "color(from color({} 0.7 0.5 0.3) {} none none none / none)",
20447          color_space, color_space
20448        ),
20449        &format!("color({} none none none / none)", color_space),
20450      );
20451      test(
20452        &format!(
20453          "color(from color({} 0.7 0.5 0.3) {} r g none)",
20454          color_space, color_space
20455        ),
20456        &format!("color({} 0.7 0.5 none)", color_space),
20457      );
20458      test(
20459        &format!(
20460          "color(from color({} 0.7 0.5 0.3) {} r g none / alpha)",
20461          color_space, color_space
20462        ),
20463        &format!("color({} 0.7 0.5 none)", color_space),
20464      );
20465      test(
20466        &format!(
20467          "color(from color({} 0.7 0.5 0.3) {} r g b / none)",
20468          color_space, color_space
20469        ),
20470        &format!("color({} 0.7 0.5 0.3 / none)", color_space),
20471      );
20472      test(
20473        &format!(
20474          "color(from color({} 0.7 0.5 0.3 / 40%) {} r g none / alpha)",
20475          color_space, color_space
20476        ),
20477        &format!("color({} 0.7 0.5 none / 0.4)", color_space),
20478      );
20479      test(
20480        &format!(
20481          "color(from color({} 0.7 0.5 0.3 / 40%) {} r g b / none)",
20482          color_space, color_space
20483        ),
20484        &format!("color({} 0.7 0.5 0.3 / none)", color_space),
20485      );
20486      // FIXME: Clarify with spec editors if 'none' should pass through to the constants.
20487      test(
20488        &format!(
20489          "color(from color({} none none none) {} r g b)",
20490          color_space, color_space
20491        ),
20492        &format!("color({} 0 0 0)", color_space),
20493      );
20494      test(
20495        &format!(
20496          "color(from color({} none none none / none) {} r g b / alpha)",
20497          color_space, color_space
20498        ),
20499        &format!("color({} 0 0 0 / 0)", color_space),
20500      );
20501      test(
20502        &format!("color(from color({} 0.7 none 0.3) {} r g b)", color_space, color_space),
20503        &format!("color({} 0.7 0 0.3)", color_space),
20504      );
20505      test(
20506        &format!(
20507          "color(from color({} 0.7 0.5 0.3 / none) {} r g b / alpha)",
20508          color_space, color_space
20509        ),
20510        &format!("color({} 0.7 0.5 0.3 / 0)", color_space),
20511      );
20512    }
20513
20514    // test_valid_value\(`color`, `color\(from color\(\$\{colorSpace\}(.*?) \$\{colorSpace\}(.*?)`,\s*`color\(\$\{resultColorSpace\}(.*?)`\)
20515    // test(&format!("color(from color({}$1 {}$2", color_space, color_space), &format!("color({}$3", result_color_space))
20516
20517    for color_space in &["xyz", "xyz-d50", "xyz-d65"] {
20518      let result_color_space = if *color_space == "xyz" { "xyz-d65" } else { color_space };
20519
20520      // Testing no modifications.
20521      test(
20522        &format!("color(from color({} 7 -20.5 100) {} x y z)", color_space, color_space),
20523        &format!("color({} 7 -20.5 100)", result_color_space),
20524      );
20525      test(
20526        &format!(
20527          "color(from color({} 7 -20.5 100) {} x y z / alpha)",
20528          color_space, color_space
20529        ),
20530        &format!("color({} 7 -20.5 100)", result_color_space),
20531      );
20532      test(
20533        &format!(
20534          "color(from color({} 7 -20.5 100 / 40%) {} x y z)",
20535          color_space, color_space
20536        ),
20537        &format!("color({} 7 -20.5 100)", result_color_space),
20538      );
20539      test(
20540        &format!(
20541          "color(from color({} 7 -20.5 100 / 40%) {} x y z / alpha)",
20542          color_space, color_space
20543        ),
20544        &format!("color({} 7 -20.5 100 / 0.4)", result_color_space),
20545      );
20546
20547      // Test nesting relative colors.
20548      test(
20549        &format!(
20550          "color(from color(from color({} 7 -20.5 100) {} x y z) {} x y z)",
20551          color_space, color_space, color_space
20552        ),
20553        &format!("color({} 7 -20.5 100)", result_color_space),
20554      );
20555
20556      // Testing replacement with 0.
20557      test(
20558        &format!("color(from color({} 7 -20.5 100) {} 0 0 0)", color_space, color_space),
20559        &format!("color({} 0 0 0)", result_color_space),
20560      );
20561      test(
20562        &format!(
20563          "color(from color({} 7 -20.5 100) {} 0 0 0 / 0)",
20564          color_space, color_space
20565        ),
20566        &format!("color({} 0 0 0 / 0)", result_color_space),
20567      );
20568      test(
20569        &format!(
20570          "color(from color({} 7 -20.5 100) {} 0 y z / alpha)",
20571          color_space, color_space
20572        ),
20573        &format!("color({} 0 -20.5 100)", result_color_space),
20574      );
20575      test(
20576        &format!(
20577          "color(from color({} 7 -20.5 100) {} x 0 z / alpha)",
20578          color_space, color_space
20579        ),
20580        &format!("color({} 7 0 100)", result_color_space),
20581      );
20582      test(
20583        &format!(
20584          "color(from color({} 7 -20.5 100) {} x y 0 / alpha)",
20585          color_space, color_space
20586        ),
20587        &format!("color({} 7 -20.5 0)", result_color_space),
20588      );
20589      test(
20590        &format!(
20591          "color(from color({} 7 -20.5 100) {} x y z / 0)",
20592          color_space, color_space
20593        ),
20594        &format!("color({} 7 -20.5 100 / 0)", result_color_space),
20595      );
20596      test(
20597        &format!(
20598          "color(from color({} 7 -20.5 100 / 40%) {} 0 y z / alpha)",
20599          color_space, color_space
20600        ),
20601        &format!("color({} 0 -20.5 100 / 0.4)", result_color_space),
20602      );
20603      test(
20604        &format!(
20605          "color(from color({} 7 -20.5 100 / 40%) {} x 0 z / alpha)",
20606          color_space, color_space
20607        ),
20608        &format!("color({} 7 0 100 / 0.4)", result_color_space),
20609      );
20610      test(
20611        &format!(
20612          "color(from color({} 7 -20.5 100 / 40%) {} x y 0 / alpha)",
20613          color_space, color_space
20614        ),
20615        &format!("color({} 7 -20.5 0 / 0.4)", result_color_space),
20616      );
20617      test(
20618        &format!(
20619          "color(from color({} 7 -20.5 100 / 40%) {} x y z / 0)",
20620          color_space, color_space
20621        ),
20622        &format!("color({} 7 -20.5 100 / 0)", result_color_space),
20623      );
20624
20625      // Testing replacement with a constant.
20626      test(
20627        &format!(
20628          "color(from color({} 7 -20.5 100) {} 0.2 y z / alpha)",
20629          color_space, color_space
20630        ),
20631        &format!("color({} 0.2 -20.5 100)", result_color_space),
20632      );
20633      test(
20634        &format!(
20635          "color(from color({} 7 -20.5 100) {} x 0.2 z / alpha)",
20636          color_space, color_space
20637        ),
20638        &format!("color({} 7 0.2 100)", result_color_space),
20639      );
20640      test(
20641        &format!(
20642          "color(from color({} 7 -20.5 100) {} x y 0.2 / alpha)",
20643          color_space, color_space
20644        ),
20645        &format!("color({} 7 -20.5 0.2)", result_color_space),
20646      );
20647      test(
20648        &format!(
20649          "color(from color({} 7 -20.5 100) {} x y z / 0.2)",
20650          color_space, color_space
20651        ),
20652        &format!("color({} 7 -20.5 100 / 0.2)", result_color_space),
20653      );
20654      test(
20655        &format!(
20656          "color(from color({} 7 -20.5 100) {} x y z / 20%)",
20657          color_space, color_space
20658        ),
20659        &format!("color({} 7 -20.5 100 / 0.2)", result_color_space),
20660      );
20661      test(
20662        &format!(
20663          "color(from color({} 7 -20.5 100 / 40%) {} 0.2 y z / alpha)",
20664          color_space, color_space
20665        ),
20666        &format!("color({} 0.2 -20.5 100 / 0.4)", result_color_space),
20667      );
20668      test(
20669        &format!(
20670          "color(from color({} 7 -20.5 100 / 40%) {} x 0.2 z / alpha)",
20671          color_space, color_space
20672        ),
20673        &format!("color({} 7 0.2 100 / 0.4)", result_color_space),
20674      );
20675      test(
20676        &format!(
20677          "color(from color({} 7 -20.5 100 / 40%) {} x y 0.2 / alpha)",
20678          color_space, color_space
20679        ),
20680        &format!("color({} 7 -20.5 0.2 / 0.4)", result_color_space),
20681      );
20682      test(
20683        &format!(
20684          "color(from color({} 7 -20.5 100 / 40%) {} x y z / 0.2)",
20685          color_space, color_space
20686        ),
20687        &format!("color({} 7 -20.5 100 / 0.2)", result_color_space),
20688      );
20689
20690      // Testing valid permutation (types match).
20691      test(
20692        &format!("color(from color({} 7 -20.5 100) {} y z x)", color_space, color_space),
20693        &format!("color({} -20.5 100 7)", result_color_space),
20694      );
20695      test(
20696        &format!(
20697          "color(from color({} 7 -20.5 100) {} x x x / x)",
20698          color_space, color_space
20699        ),
20700        &format!("color({} 7 7 7)", result_color_space),
20701      );
20702      test(
20703        &format!(
20704          "color(from color({} 7 -20.5 100 / 40%) {} y z x)",
20705          color_space, color_space
20706        ),
20707        &format!("color({} -20.5 100 7)", result_color_space),
20708      );
20709      test(
20710        &format!(
20711          "color(from color({} 7 -20.5 100 / 40%) {} x x x / x)",
20712          color_space, color_space
20713        ),
20714        &format!("color({} 7 7 7)", result_color_space),
20715      );
20716
20717      // Testing with calc().
20718      test(
20719        &format!(
20720          "color(from color({} 7 -20.5 100) {} calc(x) calc(y) calc(z))",
20721          color_space, color_space
20722        ),
20723        &format!("color({} 7 -20.5 100)", result_color_space),
20724      );
20725      test(
20726        &format!(
20727          "color(from color({} 7 -20.5 100 / 40%) {} calc(x) calc(y) calc(z) / calc(alpha))",
20728          color_space, color_space
20729        ),
20730        &format!("color({} 7 -20.5 100 / 0.4)", result_color_space),
20731      );
20732
20733      // Testing with 'none'.
20734      test(
20735        &format!(
20736          "color(from color({} 7 -20.5 100) {} none none none)",
20737          color_space, color_space
20738        ),
20739        &format!("color({} none none none)", result_color_space),
20740      );
20741      test(
20742        &format!(
20743          "color(from color({} 7 -20.5 100) {} none none none / none)",
20744          color_space, color_space
20745        ),
20746        &format!("color({} none none none / none)", result_color_space),
20747      );
20748      test(
20749        &format!(
20750          "color(from color({} 7 -20.5 100) {} x y none)",
20751          color_space, color_space
20752        ),
20753        &format!("color({} 7 -20.5 none)", result_color_space),
20754      );
20755      test(
20756        &format!(
20757          "color(from color({} 7 -20.5 100) {} x y none / alpha)",
20758          color_space, color_space
20759        ),
20760        &format!("color({} 7 -20.5 none)", result_color_space),
20761      );
20762      test(
20763        &format!(
20764          "color(from color({} 7 -20.5 100) {} x y z / none)",
20765          color_space, color_space
20766        ),
20767        &format!("color({} 7 -20.5 100 / none)", result_color_space),
20768      );
20769      test(
20770        &format!(
20771          "color(from color({} 7 -20.5 100 / 40%) {} x y none / alpha)",
20772          color_space, color_space
20773        ),
20774        &format!("color({} 7 -20.5 none / 0.4)", result_color_space),
20775      );
20776      test(
20777        &format!(
20778          "color(from color({} 7 -20.5 100 / 40%) {} x y z / none)",
20779          color_space, color_space
20780        ),
20781        &format!("color({} 7 -20.5 100 / none)", result_color_space),
20782      );
20783      // FIXME: Clarify with spec editors if 'none' should pass through to the constants.
20784      test(
20785        &format!(
20786          "color(from color({} none none none) {} x y z)",
20787          color_space, color_space
20788        ),
20789        &format!("color({} 0 0 0)", result_color_space),
20790      );
20791      test(
20792        &format!(
20793          "color(from color({} none none none / none) {} x y z / alpha)",
20794          color_space, color_space
20795        ),
20796        &format!("color({} 0 0 0 / 0)", result_color_space),
20797      );
20798      test(
20799        &format!("color(from color({} 7 none 100) {} x y z)", color_space, color_space),
20800        &format!("color({} 7 0 100)", result_color_space),
20801      );
20802      test(
20803        &format!(
20804          "color(from color({} 7 -20.5 100 / none) {} x y z / alpha)",
20805          color_space, color_space
20806        ),
20807        &format!("color({} 7 -20.5 100 / 0)", result_color_space),
20808      );
20809
20810      // https://github.com/web-platform-tests/wpt/blob/master/css/css-color/parsing/relative-color-invalid.html
20811      minify_test(
20812        ".foo{color:rgb(from rebeccapurple r 10deg 10)}",
20813        ".foo{color:rgb(from rebeccapurple r 10deg 10)}",
20814      );
20815      minify_test(
20816        ".foo{color:rgb(from rebeccapurple l g b)}",
20817        ".foo{color:rgb(from rebeccapurple l g b)}",
20818      );
20819      minify_test(
20820        ".foo{color:hsl(from rebeccapurple s h l)}",
20821        ".foo{color:hsl(from rebeccapurple s h l)}",
20822      );
20823      minify_test(".foo{color:hsl(from rebeccapurple s s s / s)}", ".foo{color:#bfaa40}");
20824      minify_test(
20825        ".foo{color:hsl(from rebeccapurple calc(alpha * 100) calc(alpha * 100) calc(alpha * 100) / alpha)}",
20826        ".foo{color:#fff}",
20827      );
20828    }
20829  }
20830
20831  #[test]
20832  fn test_color_mix() {
20833    minify_test(
20834      ".foo { color: color-mix(in lab, purple 50%, plum 50%); }",
20835      ".foo{color:lab(51.5117% 43.3777 -29.0443)}",
20836    );
20837    minify_test(
20838      ".foo { color: color-mix(in lch, peru 40%, palegoldenrod); }",
20839      ".foo{color:lch(79.7255% 40.4542 84.7634)}",
20840    );
20841    minify_test(
20842      ".foo { color: color-mix(in lch, teal 65%, olive); }",
20843      ".foo{color:lch(49.4431% 40.4806 162.546)}",
20844    );
20845    minify_test(
20846      ".foo { color: color-mix(in lch, white, black); }",
20847      ".foo{color:lch(50% 0 none)}",
20848    );
20849    minify_test(
20850      ".foo { color: color-mix(in xyz, rgb(82.02% 30.21% 35.02%) 75.23%, rgb(5.64% 55.94% 85.31%)); }",
20851      ".foo{color:color(xyz .287458 .208776 .260566)}",
20852    );
20853    minify_test(
20854      ".foo { color: color-mix(in lch, white, blue); }",
20855      ".foo{color:lch(64.7842% 65.6007 301.364)}",
20856    );
20857    minify_test(
20858      ".foo { color: color-mix(in oklch, white, blue); }",
20859      ".foo{color:oklch(72.6007% .156607 264.052)}",
20860    );
20861    minify_test(
20862      ".foo { color: color-mix(in srgb, white, blue); }",
20863      ".foo{color:#8080ff}",
20864    );
20865    minify_test(
20866      ".foo { color: color-mix(in lch, blue, white); }",
20867      ".foo{color:lch(64.7842% 65.6007 301.364)}",
20868    );
20869    minify_test(
20870      ".foo { color: color-mix(in oklch, blue, white); }",
20871      ".foo{color:oklch(72.6007% .156607 264.052)}",
20872    );
20873    minify_test(
20874      ".foo { color: color-mix(in srgb, blue, white); }",
20875      ".foo{color:#8080ff}",
20876    );
20877    // minify_test(".foo { color: color-mix(in hsl, color(display-p3 0 1 0) 80%, yellow); }", ".foo{color:hsl(108 100% 49.9184%) }");
20878    minify_test(
20879      ".foo { color: color-mix(in hsl, hsl(120 100% 49.898%) 80%, yellow); }",
20880      ".foo{color:#33fe00}",
20881    );
20882    minify_test(
20883      ".foo { color: color-mix(in srgb, rgb(100% 0% 0% / 0.7) 25%, rgb(0% 100% 0% / 0.2)); }",
20884      ".foo{color:#89760053}",
20885    );
20886    minify_test(
20887      ".foo { color: color-mix(in srgb, rgb(100% 0% 0% / 0.7) 20%, rgb(0% 100% 0% / 0.2) 60%); }",
20888      ".foo{color:#89760042}",
20889    );
20890    minify_test(
20891      ".foo { color: color-mix(in lch, color(display-p3 0 1 none), color(display-p3 0 0 1)); }",
20892      ".foo{color:lch(58.8143% 141.732 218.684)}",
20893    );
20894    minify_test(
20895      ".foo { color: color-mix(in srgb, rgb(128 128 none), rgb(none none 128)); }",
20896      ".foo{color:gray}",
20897    );
20898    minify_test(
20899      ".foo { color: color-mix(in srgb, rgb(50% 50% none), rgb(none none 50%)); }",
20900      ".foo{color:gray}",
20901    );
20902    minify_test(
20903      ".foo { color: color-mix(in srgb, rgb(none 50% none), rgb(50% none 50%)); }",
20904      ".foo{color:gray}",
20905    );
20906    minify_test(
20907      ".foo { --color: color-mix(in lch, teal 65%, olive); }",
20908      ".foo{--color:lch(49.4431% 40.4806 162.546)}",
20909    );
20910    minify_test(
20911      ".foo { color: color-mix(in xyz, transparent, green 65%); }",
20912      ".foo{color:color(xyz .0771883 .154377 .0257295/.65)}",
20913    );
20914    prefix_test(
20915      ".foo { color: color-mix(in xyz, transparent, green 65%); }",
20916      indoc! { r#"
20917      .foo {
20918        color: #008000a6;
20919        color: color(xyz .0771883 .154377 .0257295 / .65);
20920      }
20921      "# },
20922      Browsers {
20923        chrome: Some(95 << 16),
20924        ..Default::default()
20925      },
20926    );
20927    minify_test(
20928      ".foo { color: color-mix(in srgb, currentColor, blue); }",
20929      ".foo{color:color-mix(in srgb, currentColor, blue)}",
20930    );
20931    minify_test(
20932      ".foo { color: color-mix(in srgb, blue, currentColor); }",
20933      ".foo{color:color-mix(in srgb, blue, currentColor)}",
20934    );
20935    minify_test(
20936      ".foo { color: color-mix(in srgb, accentcolor, blue); }",
20937      ".foo{color:color-mix(in srgb, accentcolor, blue)}",
20938    );
20939    minify_test(
20940      ".foo { color: color-mix(in srgb, blue, accentcolor); }",
20941      ".foo{color:color-mix(in srgb, blue, accentcolor)}",
20942    );
20943
20944    // regex for converting web platform tests:
20945    // test_computed_value\(.*?, `(.*?)`, `(.*?)`\);
20946    // minify_test(".foo { color: $1 }", ".foo{color:$2}");
20947
20948    // https://github.com/web-platform-tests/wpt/blob/f8c76b11cff66a7adc87264a18e39353cb5a60c9/css/css-color/parsing/color-mix-computed.html
20949    minify_test(
20950      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%)) }",
20951      ".foo{color:#545c3d}",
20952    );
20953    minify_test(
20954      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40%)) }",
20955      ".foo{color:#706a43}",
20956    );
20957    minify_test(
20958      ".foo { color: color-mix(in hsl, 25% hsl(120deg 10% 20%), hsl(30deg 30% 40%)) }",
20959      ".foo{color:#706a43}",
20960    );
20961    minify_test(
20962      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20%), 25% hsl(30deg 30% 40%)) }",
20963      ".foo{color:#3d4936}",
20964    );
20965    minify_test(
20966      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%) 25%) }",
20967      ".foo{color:#3d4936}",
20968    );
20969    minify_test(
20970      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40%) 75%) }",
20971      ".foo{color:#706a43}",
20972    );
20973    minify_test(
20974      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20%) 30%, hsl(30deg 30% 40%) 90%) }",
20975      ".foo{color:#706a43}",
20976    ); // Scale down > 100% sum.
20977    minify_test(
20978      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20%) 12.5%, hsl(30deg 30% 40%) 37.5%) }",
20979      ".foo{color:#706a4380}",
20980    ); // Scale up < 100% sum, causes alpha multiplication.
20981    minify_test(
20982      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20%) 0%, hsl(30deg 30% 40%)) }",
20983      ".foo{color:#856647}",
20984    );
20985
20986    minify_test(
20987      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20% / .4), hsl(30deg 30% 40% / .8)) }",
20988      ".foo{color:#5f694199}",
20989    );
20990    minify_test(
20991      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40% / .8)) }",
20992      ".foo{color:#6c6742d9}",
20993    );
20994    minify_test(
20995      ".foo { color: color-mix(in hsl, 25% hsl(120deg 10% 20% / .4), hsl(30deg 30% 40% / .8)) }",
20996      ".foo{color:#797245b3}",
20997    );
20998    minify_test(
20999      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20% / .4), 25% hsl(30deg 30% 40% / .8)) }",
21000      ".foo{color:#44543b80}",
21001    );
21002    minify_test(
21003      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20% / .4), hsl(30deg 30% 40% / .8) 25%) }",
21004      ".foo{color:#44543b80}",
21005    );
21006    minify_test(
21007      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20% / .4) 25%, hsl(30deg 30% 40% / .8) 75%) }",
21008      ".foo{color:#797245b3}",
21009    );
21010    minify_test(
21011      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20% / .4) 30%, hsl(30deg 30% 40% / .8) 90%) }",
21012      ".foo{color:#797245b3}",
21013    ); // Scale down > 100% sum.
21014    minify_test(
21015      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20% / .4) 12.5%, hsl(30deg 30% 40% / .8) 37.5%) }",
21016      ".foo{color:#79724559}",
21017    ); // Scale up < 100% sum, causes alpha multiplication.
21018    minify_test(
21019      ".foo { color: color-mix(in hsl, hsl(120deg 10% 20% / .4) 0%, hsl(30deg 30% 40% / .8)) }",
21020      ".foo{color:#856647cc}",
21021    );
21022
21023    fn canonicalize(s: &str) -> String {
21024      use crate::traits::{Parse, ToCss};
21025      use crate::values::color::CssColor;
21026      use cssparser::{Parser, ParserInput};
21027
21028      let mut input = ParserInput::new(s);
21029      let mut parser = Parser::new(&mut input);
21030      let v = CssColor::parse(&mut parser).unwrap().to_rgb().unwrap();
21031      format!(".foo{{color:{}}}", v.to_css_string(PrinterOptions::default()).unwrap())
21032    }
21033
21034    // regex for converting web platform tests:
21035    // test_computed_value\(.*?, `(.*?)`, canonicalize\(`(.*?)`\)\);
21036    // minify_test(".foo { color: $1 }", &canonicalize("$2"));
21037
21038    minify_test(
21039      ".foo { color: color-mix(in hsl, hsl(40deg 50% 50%), hsl(60deg 50% 50%)) }",
21040      &canonicalize("hsl(50deg 50% 50%)"),
21041    );
21042    minify_test(
21043      ".foo { color: color-mix(in hsl, hsl(60deg 50% 50%), hsl(40deg 50% 50%)) }",
21044      &canonicalize("hsl(50deg 50% 50%)"),
21045    );
21046    minify_test(
21047      ".foo { color: color-mix(in hsl, hsl(50deg 50% 50%), hsl(330deg 50% 50%)) }",
21048      &canonicalize("hsl(10deg 50% 50%)"),
21049    );
21050    minify_test(
21051      ".foo { color: color-mix(in hsl, hsl(330deg 50% 50%), hsl(50deg 50% 50%)) }",
21052      &canonicalize("hsl(10deg 50% 50%)"),
21053    );
21054    minify_test(
21055      ".foo { color: color-mix(in hsl, hsl(20deg 50% 50%), hsl(320deg 50% 50%)) }",
21056      &canonicalize("hsl(350deg 50% 50%)"),
21057    );
21058    minify_test(
21059      ".foo { color: color-mix(in hsl, hsl(320deg 50% 50%), hsl(20deg 50% 50%)) }",
21060      &canonicalize("hsl(350deg 50% 50%)"),
21061    );
21062
21063    minify_test(
21064      ".foo { color: color-mix(in hsl shorter hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%)) }",
21065      &canonicalize("hsl(50deg 50% 50%)"),
21066    );
21067    minify_test(
21068      ".foo { color: color-mix(in hsl shorter hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%)) }",
21069      &canonicalize("hsl(50deg 50% 50%)"),
21070    );
21071    minify_test(
21072      ".foo { color: color-mix(in hsl shorter hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%)) }",
21073      &canonicalize("hsl(10deg 50% 50%)"),
21074    );
21075    minify_test(
21076      ".foo { color: color-mix(in hsl shorter hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%)) }",
21077      &canonicalize("hsl(10deg 50% 50%)"),
21078    );
21079    minify_test(
21080      ".foo { color: color-mix(in hsl shorter hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%)) }",
21081      &canonicalize("hsl(350deg 50% 50%)"),
21082    );
21083    minify_test(
21084      ".foo { color: color-mix(in hsl shorter hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%)) }",
21085      &canonicalize("hsl(350deg 50% 50%)"),
21086    );
21087
21088    minify_test(
21089      ".foo { color: color-mix(in hsl longer hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%)) }",
21090      &canonicalize("hsl(230deg 50% 50%)"),
21091    );
21092    minify_test(
21093      ".foo { color: color-mix(in hsl longer hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%)) }",
21094      &canonicalize("hsl(230deg 50% 50%)"),
21095    );
21096    minify_test(
21097      ".foo { color: color-mix(in hsl longer hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%)) }",
21098      &canonicalize("hsl(190deg 50% 50%)"),
21099    );
21100    minify_test(
21101      ".foo { color: color-mix(in hsl longer hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%)) }",
21102      &canonicalize("hsl(190deg 50% 50%)"),
21103    );
21104    // minify_test(".foo { color: color-mix(in hsl longer hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%)) }", &canonicalize("hsl(170deg 50% 50%)"));
21105    // minify_test(".foo { color: color-mix(in hsl longer hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%)) }", &canonicalize("hsl(170deg 50% 50%)"));
21106
21107    minify_test(
21108      ".foo { color: color-mix(in hsl increasing hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%)) }",
21109      &canonicalize("hsl(50deg 50% 50%)"),
21110    );
21111    minify_test(
21112      ".foo { color: color-mix(in hsl increasing hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%)) }",
21113      &canonicalize("hsl(230deg 50% 50%)"),
21114    );
21115    minify_test(
21116      ".foo { color: color-mix(in hsl increasing hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%)) }",
21117      &canonicalize("hsl(190deg 50% 50%)"),
21118    );
21119    minify_test(
21120      ".foo { color: color-mix(in hsl increasing hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%)) }",
21121      &canonicalize("hsl(10deg 50% 50%)"),
21122    );
21123    // minify_test(".foo { color: color-mix(in hsl increasing hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%)) }", &canonicalize("hsl(170deg 50% 50%)"));
21124    // minify_test(".foo { color: color-mix(in hsl increasing hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%)) }", &canonicalize("hsl(350deg 50% 50%)"));
21125
21126    minify_test(
21127      ".foo { color: color-mix(in hsl decreasing hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%)) }",
21128      &canonicalize("hsl(230deg 50% 50%)"),
21129    );
21130    minify_test(
21131      ".foo { color: color-mix(in hsl decreasing hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%)) }",
21132      &canonicalize("hsl(50deg 50% 50%)"),
21133    );
21134    minify_test(
21135      ".foo { color: color-mix(in hsl decreasing hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%)) }",
21136      &canonicalize("hsl(10deg 50% 50%)"),
21137    );
21138    minify_test(
21139      ".foo { color: color-mix(in hsl decreasing hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%)) }",
21140      &canonicalize("hsl(190deg 50% 50%)"),
21141    );
21142    minify_test(
21143      ".foo { color: color-mix(in hsl decreasing hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%)) }",
21144      &canonicalize("hsl(350deg 50% 50%)"),
21145    );
21146    // minify_test(".foo { color: color-mix(in hsl decreasing hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%)) }", &canonicalize("hsl(170deg 50% 50%)"));
21147
21148    minify_test(
21149      ".foo { color: color-mix(in hsl specified hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%)) }",
21150      &canonicalize("hsl(50deg 50% 50%)"),
21151    );
21152    minify_test(
21153      ".foo { color: color-mix(in hsl specified hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%)) }",
21154      &canonicalize("hsl(50deg 50% 50%)"),
21155    );
21156    minify_test(
21157      ".foo { color: color-mix(in hsl specified hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%)) }",
21158      &canonicalize("hsl(190deg 50% 50%)"),
21159    );
21160    minify_test(
21161      ".foo { color: color-mix(in hsl specified hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%)) }",
21162      &canonicalize("hsl(190deg 50% 50%)"),
21163    );
21164    // minify_test(".foo { color: color-mix(in hsl specified hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%)) }", &canonicalize("hsl(170deg 50% 50%)"));
21165    // minify_test(".foo { color: color-mix(in hsl specified hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%)) }", &canonicalize("hsl(170deg 50% 50%)"));
21166
21167    minify_test(
21168      ".foo { color: color-mix(in hsl, hsl(none none none), hsl(none none none)) }",
21169      &canonicalize("hsl(none none none)"),
21170    );
21171    minify_test(
21172      ".foo { color: color-mix(in hsl, hsl(none none none), hsl(30deg 40% 80%)) }",
21173      &canonicalize("hsl(30deg 40% 80%)"),
21174    );
21175    minify_test(
21176      ".foo { color: color-mix(in hsl, hsl(120deg 20% 40%), hsl(none none none)) }",
21177      &canonicalize("hsl(120deg 20% 40%)"),
21178    );
21179    minify_test(
21180      ".foo { color: color-mix(in hsl, hsl(120deg 20% none), hsl(30deg 40% 60%)) }",
21181      &canonicalize("hsl(75deg 30% 60%)"),
21182    );
21183    minify_test(
21184      ".foo { color: color-mix(in hsl, hsl(120deg 20% 40%), hsl(30deg 20% none)) }",
21185      &canonicalize("hsl(75deg 20% 40%)"),
21186    );
21187    minify_test(
21188      ".foo { color: color-mix(in hsl, hsl(none 20% 40%), hsl(30deg none 80%)) }",
21189      &canonicalize("hsl(30deg 20% 60%)"),
21190    );
21191
21192    minify_test(
21193      ".foo { color: color-mix(in hsl, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%) }",
21194      &canonicalize("rgb(0, 249, 66)"),
21195    ); // Naive clip based mapping would give rgb(0, 255, 0).
21196    minify_test(
21197      ".foo { color: color-mix(in hsl, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%) }",
21198      &canonicalize("rgb(255, 255, 255)"),
21199    ); // Naive clip based mapping would give rgb(255, 150, 255).
21200    minify_test(
21201      ".foo { color: color-mix(in hsl, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%) }",
21202      &canonicalize("rgb(42, 0, 34)"),
21203    ); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
21204    minify_test(
21205      ".foo { color: color-mix(in hsl, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%) }",
21206      &canonicalize("rgb(255, 255, 255)"),
21207    ); // Naive clip based mapping would give rgb(255, 150, 255).
21208    minify_test(
21209      ".foo { color: color-mix(in hsl, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%) }",
21210      &canonicalize("rgb(42, 0, 34)"),
21211    ); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
21212    minify_test(
21213      ".foo { color: color-mix(in hsl, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%) }",
21214      &canonicalize("rgb(255, 255, 255)"),
21215    ); // Naive clip based mapping would give rgb(255, 92, 255).
21216    minify_test(
21217      ".foo { color: color-mix(in hsl, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%) }",
21218      &canonicalize("rgb(0, 0, 0)"),
21219    ); // Naive clip based mapping would give rgb(19, 0, 24).
21220    minify_test(
21221      ".foo { color: color-mix(in hsl, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%) }",
21222      &canonicalize("rgb(255, 255, 255)"),
21223    ); // Naive clip based mapping would give rgb(255, 91, 255).
21224    minify_test(
21225      ".foo { color: color-mix(in hsl, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%) }",
21226      &canonicalize("rgb(0, 0, 0)"),
21227    ); // Naive clip based mapping would give rgb(20, 0, 24).
21228
21229    minify_test(
21230      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%)) }",
21231      &canonicalize("rgb(147, 179, 52)"),
21232    );
21233    minify_test(
21234      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%)) }",
21235      &canonicalize("rgb(166, 153, 64)"),
21236    );
21237    minify_test(
21238      ".foo { color: color-mix(in hwb, 25% hwb(120deg 10% 20%), hwb(30deg 30% 40%)) }",
21239      &canonicalize("rgb(166, 153, 64)"),
21240    );
21241    minify_test(
21242      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20%), 25% hwb(30deg 30% 40%)) }",
21243      &canonicalize("rgb(96, 191, 39)"),
21244    );
21245    minify_test(
21246      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%) 25%) }",
21247      &canonicalize("rgb(96, 191, 39)"),
21248    );
21249    minify_test(
21250      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%) 75%) }",
21251      &canonicalize("rgb(166, 153, 64)"),
21252    );
21253    minify_test(
21254      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20%) 30%, hwb(30deg 30% 40%) 90%) }",
21255      &canonicalize("rgb(166, 153, 64)"),
21256    ); // Scale down > 100% sum.
21257    minify_test(
21258      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20%) 12.5%, hwb(30deg 30% 40%) 37.5%) }",
21259      &canonicalize("rgba(166, 153, 64, 0.5)"),
21260    ); // Scale up < 100% sum, causes alpha multiplication.
21261    minify_test(
21262      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20%) 0%, hwb(30deg 30% 40%)) }",
21263      &canonicalize("rgb(153, 115, 77)"),
21264    );
21265
21266    minify_test(
21267      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20% / .4), hwb(30deg 30% 40% / .8)) }",
21268      &canonicalize("rgba(143, 170, 60, 0.6)"),
21269    );
21270    minify_test(
21271      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20% / .4) 25%, hwb(30deg 30% 40% / .8)) }",
21272      &canonicalize("rgba(160, 149, 70, 0.7)"),
21273    );
21274    minify_test(
21275      ".foo { color: color-mix(in hwb, 25% hwb(120deg 10% 20% / .4), hwb(30deg 30% 40% / .8)) }",
21276      &canonicalize("rgba(160, 149, 70, 0.7)"),
21277    );
21278    minify_test(
21279      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20%), 25% hwb(30deg 30% 40% / .8)) }",
21280      &canonicalize("rgba(95, 193, 37, 0.95)"),
21281    );
21282    minify_test(
21283      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20% / .4), hwb(30deg 30% 40% / .8) 25%) }",
21284      &canonicalize("rgba(98, 184, 46, 0.5)"),
21285    );
21286    minify_test(
21287      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20% / .4) 25%, hwb(30deg 30% 40% / .8) 75%) }",
21288      &canonicalize("rgba(160, 149, 70, 0.7)"),
21289    );
21290    minify_test(
21291      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20% / .4) 30%, hwb(30deg 30% 40% / .8) 90%) }",
21292      &canonicalize("rgba(160, 149, 70, 0.7)"),
21293    ); // Scale down > 100% sum.
21294    minify_test(
21295      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20% / .4) 12.5%, hwb(30deg 30% 40% / .8) 37.5%) }",
21296      &canonicalize("rgba(160, 149, 70, 0.35)"),
21297    ); // Scale up < 100% sum, causes alpha multiplication.
21298    minify_test(
21299      ".foo { color: color-mix(in hwb, hwb(120deg 10% 20% / .4) 0%, hwb(30deg 30% 40% / .8)) }",
21300      &canonicalize("rgba(153, 115, 77, 0.8)"),
21301    );
21302
21303    //  minify_test(".foo { color: color-mix(in hwb, hwb(40deg 30% 40%), hwb(60deg 30% 40%)) }", &canonicalize("hwb(50deg 30% 40%)"));
21304    //  minify_test(".foo { color: color-mix(in hwb, hwb(60deg 30% 40%), hwb(40deg 30% 40%)) }", &canonicalize("hwb(50deg 30% 40%)"));
21305    minify_test(
21306      ".foo { color: color-mix(in hwb, hwb(50deg 30% 40%), hwb(330deg 30% 40%)) }",
21307      &canonicalize("hwb(10deg 30% 40%)"),
21308    );
21309    minify_test(
21310      ".foo { color: color-mix(in hwb, hwb(330deg 30% 40%), hwb(50deg 30% 40%)) }",
21311      &canonicalize("hwb(10deg 30% 40%)"),
21312    );
21313    minify_test(
21314      ".foo { color: color-mix(in hwb, hwb(20deg 30% 40%), hwb(320deg 30% 40%)) }",
21315      &canonicalize("hwb(350deg 30% 40%)"),
21316    );
21317    minify_test(
21318      ".foo { color: color-mix(in hwb, hwb(320deg 30% 40%), hwb(20deg 30% 40%)) }",
21319      &canonicalize("hwb(350deg 30% 40%)"),
21320    );
21321
21322    //  minify_test(".foo { color: color-mix(in hwb shorter hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%)) }", &canonicalize("hwb(50deg 30% 40%)"));
21323    //  minify_test(".foo { color: color-mix(in hwb shorter hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%)) }", &canonicalize("hwb(50deg 30% 40%)"));
21324    minify_test(
21325      ".foo { color: color-mix(in hwb shorter hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%)) }",
21326      &canonicalize("hwb(10deg 30% 40%)"),
21327    );
21328    minify_test(
21329      ".foo { color: color-mix(in hwb shorter hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%)) }",
21330      &canonicalize("hwb(10deg 30% 40%)"),
21331    );
21332    minify_test(
21333      ".foo { color: color-mix(in hwb shorter hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%)) }",
21334      &canonicalize("hwb(350deg 30% 40%)"),
21335    );
21336    minify_test(
21337      ".foo { color: color-mix(in hwb shorter hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%)) }",
21338      &canonicalize("hwb(350deg 30% 40%)"),
21339    );
21340
21341    minify_test(
21342      ".foo { color: color-mix(in hwb longer hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%)) }",
21343      &canonicalize("hwb(230deg 30% 40%)"),
21344    );
21345    minify_test(
21346      ".foo { color: color-mix(in hwb longer hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%)) }",
21347      &canonicalize("hwb(230deg 30% 40%)"),
21348    );
21349    //  minify_test(".foo { color: color-mix(in hwb longer hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%)) }", &canonicalize("hwb(190deg 30% 40%)"));
21350    //  minify_test(".foo { color: color-mix(in hwb longer hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%)) }", &canonicalize("hwb(190deg 30% 40%)"));
21351    //  minify_test(".foo { color: color-mix(in hwb longer hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%)) }", &canonicalize("hwb(170deg 30% 40%)"));
21352    //  minify_test(".foo { color: color-mix(in hwb longer hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%)) }", &canonicalize("hwb(170deg 30% 40%)"));
21353
21354    // minify_test(".foo { color: color-mix(in hwb increasing hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%)) }", &canonicalize("hwb(50deg 30% 40%)"));
21355    minify_test(
21356      ".foo { color: color-mix(in hwb increasing hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%)) }",
21357      &canonicalize("hwb(230deg 30% 40%)"),
21358    );
21359    // minify_test(".foo { color: color-mix(in hwb increasing hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%)) }", &canonicalize("hwb(190deg 30% 40%)"));
21360    minify_test(
21361      ".foo { color: color-mix(in hwb increasing hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%)) }",
21362      &canonicalize("hwb(10deg 30% 40%)"),
21363    );
21364    // minify_test(".foo { color: color-mix(in hwb increasing hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%)) }", &canonicalize("hwb(170deg 30% 40%)"));
21365    minify_test(
21366      ".foo { color: color-mix(in hwb increasing hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%)) }",
21367      &canonicalize("hwb(350deg 30% 40%)"),
21368    );
21369
21370    minify_test(
21371      ".foo { color: color-mix(in hwb decreasing hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%)) }",
21372      &canonicalize("hwb(230deg 30% 40%)"),
21373    );
21374    // minify_test(".foo { color: color-mix(in hwb decreasing hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%)) }", &canonicalize("hwb(50deg 30% 40%)"));
21375    minify_test(
21376      ".foo { color: color-mix(in hwb decreasing hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%)) }",
21377      &canonicalize("hwb(10deg 30% 40%)"),
21378    );
21379    // minify_test(".foo { color: color-mix(in hwb decreasing hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%)) }", &canonicalize("hwb(190deg 30% 40%)"));
21380    minify_test(
21381      ".foo { color: color-mix(in hwb decreasing hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%)) }",
21382      &canonicalize("hwb(350deg 30% 40%)"),
21383    );
21384    // minify_test(".foo { color: color-mix(in hwb decreasing hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%)) }", &canonicalize("hwb(170deg 30% 40%)"));
21385
21386    // minify_test(".foo { color: color-mix(in hwb specified hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%)) }", &canonicalize("hwb(50deg 30% 40%)"));
21387    // minify_test(".foo { color: color-mix(in hwb specified hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%)) }", &canonicalize("hwb(50deg 30% 40%)"));
21388    // minify_test(".foo { color: color-mix(in hwb specified hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%)) }", &canonicalize("hwb(190deg 30% 40%)"));
21389    // minify_test(".foo { color: color-mix(in hwb specified hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%)) }", &canonicalize("hwb(190deg 30% 40%)"));
21390    // minify_test(".foo { color: color-mix(in hwb specified hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%)) }", &canonicalize("hwb(170deg 30% 40%)"));
21391    // minify_test(".foo { color: color-mix(in hwb specified hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%)) }", &canonicalize("hwb(170deg 30% 40%)"));
21392
21393    minify_test(
21394      ".foo { color: color-mix(in hwb, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%) }",
21395      &canonicalize("rgb(0, 249, 66)"),
21396    ); // Naive clip based mapping would give rgb(0, 255, 0).
21397    minify_test(
21398      ".foo { color: color-mix(in hwb, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%) }",
21399      &canonicalize("rgb(255, 255, 255)"),
21400    ); // Naive clip based mapping would give rgb(255, 150, 255).
21401    minify_test(
21402      ".foo { color: color-mix(in hwb, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%) }",
21403      &canonicalize("rgb(42, 0, 34)"),
21404    ); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
21405    minify_test(
21406      ".foo { color: color-mix(in hwb, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%) }",
21407      &canonicalize("rgb(255, 255, 255)"),
21408    ); // Naive clip based mapping would give rgb(255, 150, 255).
21409    minify_test(
21410      ".foo { color: color-mix(in hwb, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%) }",
21411      &canonicalize("rgb(42, 0, 34)"),
21412    ); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black,
21413    minify_test(
21414      ".foo { color: color-mix(in hwb, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%) }",
21415      &canonicalize("rgb(255, 255, 255)"),
21416    ); // Naive clip based mapping would give rgb(255, 92, 255).
21417    minify_test(
21418      ".foo { color: color-mix(in hwb, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%) }",
21419      &canonicalize("rgb(0, 0, 0)"),
21420    ); // Naive clip based mapping would give rgb(19, 0, 24).
21421    minify_test(
21422      ".foo { color: color-mix(in hwb, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%) }",
21423      &canonicalize("rgb(255, 255, 255)"),
21424    ); // Naive clip based mapping would give rgb(255, 91, 255).
21425    minify_test(
21426      ".foo { color: color-mix(in hwb, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%) }",
21427      &canonicalize("rgb(0, 0, 0)"),
21428    ); // Naive clip based mapping would give rgb(20, 0, 24).
21429
21430    for color_space in &["lch", "oklch"] {
21431      // regex for converting web platform tests:
21432      // test_computed_value\(.*?, `color-mix\(in \$\{colorSpace\}(.*?), (.*?)\$\{colorSpace\}(.*?) \$\{colorSpace\}(.*?)`, `\$\{colorSpace\}(.*?)`\);
21433      // minify_test(&format!(".foo {{ color: color-mix(in {0}$1, $2{0}$3 {0}$4 }}", color_space), &format!(".foo{{color:{}$5}}", color_space));
21434
21435      minify_test(
21436        &format!(
21437          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg), {0}(50% 60 70deg)) }}",
21438          color_space
21439        ),
21440        &format!(".foo{{color:{}(30% 40 50)}}", color_space),
21441      );
21442      minify_test(
21443        &format!(
21444          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg) 25%, {0}(50% 60 70deg)) }}",
21445          color_space
21446        ),
21447        &format!(".foo{{color:{}(40% 50 60)}}", color_space),
21448      );
21449      minify_test(
21450        &format!(
21451          ".foo {{ color: color-mix(in {0}, 25% {0}(10% 20 30deg), {0}(50% 60 70deg)) }}",
21452          color_space
21453        ),
21454        &format!(".foo{{color:{}(40% 50 60)}}", color_space),
21455      );
21456      minify_test(
21457        &format!(
21458          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg), 25% {0}(50% 60 70deg)) }}",
21459          color_space
21460        ),
21461        &format!(".foo{{color:{}(20% 30 40)}}", color_space),
21462      );
21463      minify_test(
21464        &format!(
21465          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg), {0}(50% 60 70deg) 25%) }}",
21466          color_space
21467        ),
21468        &format!(".foo{{color:{}(20% 30 40)}}", color_space),
21469      );
21470      minify_test(
21471        &format!(
21472          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg) 25%, {0}(50% 60 70deg) 75%) }}",
21473          color_space
21474        ),
21475        &format!(".foo{{color:{}(40% 50 60)}}", color_space),
21476      );
21477      minify_test(
21478        &format!(
21479          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg) 30%, {0}(50% 60 70deg) 90%) }}",
21480          color_space
21481        ),
21482        &format!(".foo{{color:{}(40% 50 60)}}", color_space),
21483      ); // Scale down > 100% sum.
21484      minify_test(
21485        &format!(
21486          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg) 12.5%, {0}(50% 60 70deg) 37.5%) }}",
21487          color_space
21488        ),
21489        &format!(".foo{{color:{}(40% 50 60/.5)}}", color_space),
21490      ); // Scale up < 100% sum, causes alpha multiplication.
21491      minify_test(
21492        &format!(
21493          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg) 0%, {0}(50% 60 70deg)) }}",
21494          color_space
21495        ),
21496        &format!(".foo{{color:{}(50% 60 70)}}", color_space),
21497      );
21498
21499      minify_test(
21500        &format!(
21501          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg / .4), {0}(50% 60 70deg / .8)) }}",
21502          color_space
21503        ),
21504        &format!(".foo{{color:{}(36.6667% 46.6667 50/.6)}}", color_space),
21505      );
21506      minify_test(
21507        &format!(
21508          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg / .4) 25%, {0}(50% 60 70deg / .8)) }}",
21509          color_space
21510        ),
21511        &format!(".foo{{color:{}(44.2857% 54.2857 60/.7)}}", color_space),
21512      );
21513      minify_test(
21514        &format!(
21515          ".foo {{ color: color-mix(in {0}, 25% {0}(10% 20 30deg / .4), {0}(50% 60 70deg / .8)) }}",
21516          color_space
21517        ),
21518        &format!(".foo{{color:{}(44.2857% 54.2857 60/.7)}}", color_space),
21519      );
21520      minify_test(
21521        &format!(
21522          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg / .4), 25% {0}(50% 60 70deg / .8)) }}",
21523          color_space
21524        ),
21525        &format!(".foo{{color:{}(26% 36 40/.5)}}", color_space),
21526      );
21527      minify_test(
21528        &format!(
21529          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg / .4), {0}(50% 60 70deg / .8) 25%) }}",
21530          color_space
21531        ),
21532        &format!(".foo{{color:{}(26% 36 40/.5)}}", color_space),
21533      );
21534      minify_test(
21535        &format!(
21536          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg / .4) 25%, {0}(50% 60 70deg / .8) 75%) }}",
21537          color_space
21538        ),
21539        &format!(".foo{{color:{}(44.2857% 54.2857 60/.7)}}", color_space),
21540      );
21541      minify_test(
21542        &format!(
21543          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg / .4) 30%, {0}(50% 60 70deg / .8) 90%) }}",
21544          color_space
21545        ),
21546        &format!(".foo{{color:{}(44.2857% 54.2857 60/.7)}}", color_space),
21547      ); // Scale down > 100% sum.
21548      minify_test(
21549        &format!(
21550          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg / .4) 12.5%, {0}(50% 60 70deg / .8) 37.5%) }}",
21551          color_space
21552        ),
21553        &format!(".foo{{color:{}(44.2857% 54.2857 60/.35)}}", color_space),
21554      ); // Scale up < 100% sum, causes alpha multiplication.
21555      minify_test(
21556        &format!(
21557          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg / .4) 0%, {0}(50% 60 70deg / .8)) }}",
21558          color_space
21559        ),
21560        &format!(".foo{{color:{}(50% 60 70/.8)}}", color_space),
21561      );
21562
21563      minify_test(
21564        &format!(
21565          ".foo {{ color: color-mix(in {0}, {0}(100% 0 40deg), {0}(100% 0 60deg)) }}",
21566          color_space
21567        ),
21568        &format!(".foo{{color:{}(100% 0 50)}}", color_space),
21569      );
21570      minify_test(
21571        &format!(
21572          ".foo {{ color: color-mix(in {0}, {0}(100% 0 60deg), {0}(100% 0 40deg)) }}",
21573          color_space
21574        ),
21575        &format!(".foo{{color:{}(100% 0 50)}}", color_space),
21576      );
21577      minify_test(
21578        &format!(
21579          ".foo {{ color: color-mix(in {0}, {0}(100% 0 50deg), {0}(100% 0 330deg)) }}",
21580          color_space
21581        ),
21582        &format!(".foo{{color:{}(100% 0 10)}}", color_space),
21583      );
21584      minify_test(
21585        &format!(
21586          ".foo {{ color: color-mix(in {0}, {0}(100% 0 330deg), {0}(100% 0 50deg)) }}",
21587          color_space
21588        ),
21589        &format!(".foo{{color:{}(100% 0 10)}}", color_space),
21590      );
21591      minify_test(
21592        &format!(
21593          ".foo {{ color: color-mix(in {0}, {0}(100% 0 20deg), {0}(100% 0 320deg)) }}",
21594          color_space
21595        ),
21596        &format!(".foo{{color:{}(100% 0 350)}}", color_space),
21597      );
21598      minify_test(
21599        &format!(
21600          ".foo {{ color: color-mix(in {0}, {0}(100% 0 320deg), {0}(100% 0 20deg)) }}",
21601          color_space
21602        ),
21603        &format!(".foo{{color:{}(100% 0 350)}}", color_space),
21604      );
21605
21606      minify_test(
21607        &format!(
21608          ".foo {{ color: color-mix(in {0} shorter hue, {0}(100% 0 40deg), {0}(100% 0 60deg)) }}",
21609          color_space
21610        ),
21611        &format!(".foo{{color:{}(100% 0 50)}}", color_space),
21612      );
21613      minify_test(
21614        &format!(
21615          ".foo {{ color: color-mix(in {0} shorter hue, {0}(100% 0 60deg), {0}(100% 0 40deg)) }}",
21616          color_space
21617        ),
21618        &format!(".foo{{color:{}(100% 0 50)}}", color_space),
21619      );
21620      minify_test(
21621        &format!(
21622          ".foo {{ color: color-mix(in {0} shorter hue, {0}(100% 0 50deg), {0}(100% 0 330deg)) }}",
21623          color_space
21624        ),
21625        &format!(".foo{{color:{}(100% 0 10)}}", color_space),
21626      );
21627      minify_test(
21628        &format!(
21629          ".foo {{ color: color-mix(in {0} shorter hue, {0}(100% 0 330deg), {0}(100% 0 50deg)) }}",
21630          color_space
21631        ),
21632        &format!(".foo{{color:{}(100% 0 10)}}", color_space),
21633      );
21634      minify_test(
21635        &format!(
21636          ".foo {{ color: color-mix(in {0} shorter hue, {0}(100% 0 20deg), {0}(100% 0 320deg)) }}",
21637          color_space
21638        ),
21639        &format!(".foo{{color:{}(100% 0 350)}}", color_space),
21640      );
21641      minify_test(
21642        &format!(
21643          ".foo {{ color: color-mix(in {0} shorter hue, {0}(100% 0 320deg), {0}(100% 0 20deg)) }}",
21644          color_space
21645        ),
21646        &format!(".foo{{color:{}(100% 0 350)}}", color_space),
21647      );
21648
21649      minify_test(
21650        &format!(
21651          ".foo {{ color: color-mix(in {0} longer hue, {0}(100% 0 40deg), {0}(100% 0 60deg)) }}",
21652          color_space
21653        ),
21654        &format!(".foo{{color:{}(100% 0 230)}}", color_space),
21655      );
21656      minify_test(
21657        &format!(
21658          ".foo {{ color: color-mix(in {0} longer hue, {0}(100% 0 60deg), {0}(100% 0 40deg)) }}",
21659          color_space
21660        ),
21661        &format!(".foo{{color:{}(100% 0 230)}}", color_space),
21662      );
21663      minify_test(
21664        &format!(
21665          ".foo {{ color: color-mix(in {0} longer hue, {0}(100% 0 50deg), {0}(100% 0 330deg)) }}",
21666          color_space
21667        ),
21668        &format!(".foo{{color:{}(100% 0 190)}}", color_space),
21669      );
21670      minify_test(
21671        &format!(
21672          ".foo {{ color: color-mix(in {0} longer hue, {0}(100% 0 330deg), {0}(100% 0 50deg)) }}",
21673          color_space
21674        ),
21675        &format!(".foo{{color:{}(100% 0 190)}}", color_space),
21676      );
21677      minify_test(
21678        &format!(
21679          ".foo {{ color: color-mix(in {0} longer hue, {0}(100% 0 20deg), {0}(100% 0 320deg)) }}",
21680          color_space
21681        ),
21682        &format!(".foo{{color:{}(100% 0 170)}}", color_space),
21683      );
21684      minify_test(
21685        &format!(
21686          ".foo {{ color: color-mix(in {0} longer hue, {0}(100% 0 320deg), {0}(100% 0 20deg)) }}",
21687          color_space
21688        ),
21689        &format!(".foo{{color:{}(100% 0 170)}}", color_space),
21690      );
21691
21692      minify_test(
21693        &format!(
21694          ".foo {{ color: color-mix(in {0} increasing hue, {0}(100% 0 40deg), {0}(100% 0 60deg)) }}",
21695          color_space
21696        ),
21697        &format!(".foo{{color:{}(100% 0 50)}}", color_space),
21698      );
21699      minify_test(
21700        &format!(
21701          ".foo {{ color: color-mix(in {0} increasing hue, {0}(100% 0 60deg), {0}(100% 0 40deg)) }}",
21702          color_space
21703        ),
21704        &format!(".foo{{color:{}(100% 0 230)}}", color_space),
21705      );
21706      minify_test(
21707        &format!(
21708          ".foo {{ color: color-mix(in {0} increasing hue, {0}(100% 0 50deg), {0}(100% 0 330deg)) }}",
21709          color_space
21710        ),
21711        &format!(".foo{{color:{}(100% 0 190)}}", color_space),
21712      );
21713      minify_test(
21714        &format!(
21715          ".foo {{ color: color-mix(in {0} increasing hue, {0}(100% 0 330deg), {0}(100% 0 50deg)) }}",
21716          color_space
21717        ),
21718        &format!(".foo{{color:{}(100% 0 10)}}", color_space),
21719      );
21720      minify_test(
21721        &format!(
21722          ".foo {{ color: color-mix(in {0} increasing hue, {0}(100% 0 20deg), {0}(100% 0 320deg)) }}",
21723          color_space
21724        ),
21725        &format!(".foo{{color:{}(100% 0 170)}}", color_space),
21726      );
21727      minify_test(
21728        &format!(
21729          ".foo {{ color: color-mix(in {0} increasing hue, {0}(100% 0 320deg), {0}(100% 0 20deg)) }}",
21730          color_space
21731        ),
21732        &format!(".foo{{color:{}(100% 0 350)}}", color_space),
21733      );
21734
21735      minify_test(
21736        &format!(
21737          ".foo {{ color: color-mix(in {0} decreasing hue, {0}(100% 0 40deg), {0}(100% 0 60deg)) }}",
21738          color_space
21739        ),
21740        &format!(".foo{{color:{}(100% 0 230)}}", color_space),
21741      );
21742      minify_test(
21743        &format!(
21744          ".foo {{ color: color-mix(in {0} decreasing hue, {0}(100% 0 60deg), {0}(100% 0 40deg)) }}",
21745          color_space
21746        ),
21747        &format!(".foo{{color:{}(100% 0 50)}}", color_space),
21748      );
21749      minify_test(
21750        &format!(
21751          ".foo {{ color: color-mix(in {0} decreasing hue, {0}(100% 0 50deg), {0}(100% 0 330deg)) }}",
21752          color_space
21753        ),
21754        &format!(".foo{{color:{}(100% 0 10)}}", color_space),
21755      );
21756      minify_test(
21757        &format!(
21758          ".foo {{ color: color-mix(in {0} decreasing hue, {0}(100% 0 330deg), {0}(100% 0 50deg)) }}",
21759          color_space
21760        ),
21761        &format!(".foo{{color:{}(100% 0 190)}}", color_space),
21762      );
21763      minify_test(
21764        &format!(
21765          ".foo {{ color: color-mix(in {0} decreasing hue, {0}(100% 0 20deg), {0}(100% 0 320deg)) }}",
21766          color_space
21767        ),
21768        &format!(".foo{{color:{}(100% 0 350)}}", color_space),
21769      );
21770      minify_test(
21771        &format!(
21772          ".foo {{ color: color-mix(in {0} decreasing hue, {0}(100% 0 320deg), {0}(100% 0 20deg)) }}",
21773          color_space
21774        ),
21775        &format!(".foo{{color:{}(100% 0 170)}}", color_space),
21776      );
21777
21778      minify_test(
21779        &format!(
21780          ".foo {{ color: color-mix(in {0} specified hue, {0}(100% 0 40deg), {0}(100% 0 60deg)) }}",
21781          color_space
21782        ),
21783        &format!(".foo{{color:{}(100% 0 50)}}", color_space),
21784      );
21785      minify_test(
21786        &format!(
21787          ".foo {{ color: color-mix(in {0} specified hue, {0}(100% 0 60deg), {0}(100% 0 40deg)) }}",
21788          color_space
21789        ),
21790        &format!(".foo{{color:{}(100% 0 50)}}", color_space),
21791      );
21792      minify_test(
21793        &format!(
21794          ".foo {{ color: color-mix(in {0} specified hue, {0}(100% 0 50deg), {0}(100% 0 330deg)) }}",
21795          color_space
21796        ),
21797        &format!(".foo{{color:{}(100% 0 190)}}", color_space),
21798      );
21799      minify_test(
21800        &format!(
21801          ".foo {{ color: color-mix(in {0} specified hue, {0}(100% 0 330deg), {0}(100% 0 50deg)) }}",
21802          color_space
21803        ),
21804        &format!(".foo{{color:{}(100% 0 190)}}", color_space),
21805      );
21806      minify_test(
21807        &format!(
21808          ".foo {{ color: color-mix(in {0} specified hue, {0}(100% 0 20deg), {0}(100% 0 320deg)) }}",
21809          color_space
21810        ),
21811        &format!(".foo{{color:{}(100% 0 170)}}", color_space),
21812      );
21813      minify_test(
21814        &format!(
21815          ".foo {{ color: color-mix(in {0} specified hue, {0}(100% 0 320deg), {0}(100% 0 20deg)) }}",
21816          color_space
21817        ),
21818        &format!(".foo{{color:{}(100% 0 170)}}", color_space),
21819      );
21820
21821      minify_test(
21822        &format!(
21823          ".foo {{ color: color-mix(in {0}, {0}(none none none), {0}(none none none)) }}",
21824          color_space
21825        ),
21826        &format!(".foo{{color:{}(none none none)}}", color_space),
21827      );
21828      minify_test(
21829        &format!(
21830          ".foo {{ color: color-mix(in {0}, {0}(none none none), {0}(50% 60 70deg)) }}",
21831          color_space
21832        ),
21833        &format!(".foo{{color:{}(50% 60 70)}}", color_space),
21834      );
21835      minify_test(
21836        &format!(
21837          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg), {0}(none none none)) }}",
21838          color_space
21839        ),
21840        &format!(".foo{{color:{}(10% 20 30)}}", color_space),
21841      );
21842      minify_test(
21843        &format!(
21844          ".foo {{ color: color-mix(in {0}, {0}(10% 20 none), {0}(50% 60 70deg)) }}",
21845          color_space
21846        ),
21847        &format!(".foo{{color:{}(30% 40 70)}}", color_space),
21848      );
21849      minify_test(
21850        &format!(
21851          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg), {0}(50% 60 none)) }}",
21852          color_space
21853        ),
21854        &format!(".foo{{color:{}(30% 40 30)}}", color_space),
21855      );
21856      minify_test(
21857        &format!(
21858          ".foo {{ color: color-mix(in {0}, {0}(none 20 30deg), {0}(50% none 70deg)) }}",
21859          color_space
21860        ),
21861        &format!(".foo{{color:{}(50% 20 50)}}", color_space),
21862      );
21863      minify_test(
21864        &format!(
21865          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg / none), {0}(50% 60 70deg)) }}",
21866          color_space
21867        ),
21868        &format!(".foo{{color:{}(30% 40 50)}}", color_space),
21869      );
21870      minify_test(
21871        &format!(
21872          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg / none), {0}(50% 60 70deg / 0.5)) }}",
21873          color_space
21874        ),
21875        &format!(".foo{{color:{}(30% 40 50/.5)}}", color_space),
21876      );
21877      minify_test(
21878        &format!(
21879          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30deg / none), {0}(50% 60 70deg / none)) }}",
21880          color_space
21881        ),
21882        &format!(".foo{{color:{}(30% 40 50/none)}}", color_space),
21883      );
21884    }
21885
21886    for color_space in ["lab", "oklab"] {
21887      minify_test(
21888        &format!(
21889          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30), {0}(50% 60 70)) }}",
21890          color_space
21891        ),
21892        &format!(".foo{{color:{}(30% 40 50)}}", color_space),
21893      );
21894      minify_test(
21895        &format!(
21896          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30) 25%, {0}(50% 60 70)) }}",
21897          color_space
21898        ),
21899        &format!(".foo{{color:{}(40% 50 60)}}", color_space),
21900      );
21901      minify_test(
21902        &format!(
21903          ".foo {{ color: color-mix(in {0}, 25% {0}(10% 20 30), {0}(50% 60 70)) }}",
21904          color_space
21905        ),
21906        &format!(".foo{{color:{}(40% 50 60)}}", color_space),
21907      );
21908      minify_test(
21909        &format!(
21910          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30), 25% {0}(50% 60 70)) }}",
21911          color_space
21912        ),
21913        &format!(".foo{{color:{}(20% 30 40)}}", color_space),
21914      );
21915      minify_test(
21916        &format!(
21917          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30), {0}(50% 60 70) 25%) }}",
21918          color_space
21919        ),
21920        &format!(".foo{{color:{}(20% 30 40)}}", color_space),
21921      );
21922      minify_test(
21923        &format!(
21924          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30) 25%, {0}(50% 60 70) 75%) }}",
21925          color_space
21926        ),
21927        &format!(".foo{{color:{}(40% 50 60)}}", color_space),
21928      );
21929      minify_test(
21930        &format!(
21931          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30) 30%, {0}(50% 60 70) 90%) }}",
21932          color_space
21933        ),
21934        &format!(".foo{{color:{}(40% 50 60)}}", color_space),
21935      ); // Scale down > 100% sum.
21936      minify_test(
21937        &format!(
21938          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30) 12.5%, {0}(50% 60 70) 37.5%) }}",
21939          color_space
21940        ),
21941        &format!(".foo{{color:{}(40% 50 60/.5)}}", color_space),
21942      ); // Scale up < 100% sum, causes alpha multiplication.
21943      minify_test(
21944        &format!(
21945          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30) 0%, {0}(50% 60 70)) }}",
21946          color_space
21947        ),
21948        &format!(".foo{{color:{}(50% 60 70)}}", color_space),
21949      );
21950
21951      minify_test(
21952        &format!(
21953          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30 / .4), {0}(50% 60 70 / .8)) }}",
21954          color_space
21955        ),
21956        &format!(".foo{{color:{}(36.6667% 46.6667 56.6667/.6)}}", color_space),
21957      );
21958      minify_test(
21959        &format!(
21960          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30 / .4) 25%, {0}(50% 60 70 / .8)) }}",
21961          color_space
21962        ),
21963        &format!(".foo{{color:{}(44.2857% 54.2857 64.2857/.7)}}", color_space),
21964      );
21965      minify_test(
21966        &format!(
21967          ".foo {{ color: color-mix(in {0}, 25% {0}(10% 20 30 / .4), {0}(50% 60 70 / .8)) }}",
21968          color_space
21969        ),
21970        &format!(".foo{{color:{}(44.2857% 54.2857 64.2857/.7)}}", color_space),
21971      );
21972      minify_test(
21973        &format!(
21974          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30 / .4), 25% {0}(50% 60 70 / .8)) }}",
21975          color_space
21976        ),
21977        &format!(".foo{{color:{}(26% 36 46/.5)}}", color_space),
21978      );
21979      minify_test(
21980        &format!(
21981          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30 / .4), {0}(50% 60 70 / .8) 25%) }}",
21982          color_space
21983        ),
21984        &format!(".foo{{color:{}(26% 36 46/.5)}}", color_space),
21985      );
21986      minify_test(
21987        &format!(
21988          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30 / .4) 25%, {0}(50% 60 70 / .8) 75%) }}",
21989          color_space
21990        ),
21991        &format!(".foo{{color:{}(44.2857% 54.2857 64.2857/.7)}}", color_space),
21992      );
21993      minify_test(
21994        &format!(
21995          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30 / .4) 30%, {0}(50% 60 70 / .8) 90%) }}",
21996          color_space
21997        ),
21998        &format!(".foo{{color:{}(44.2857% 54.2857 64.2857/.7)}}", color_space),
21999      ); // Scale down > 100% sum.
22000      minify_test(
22001        &format!(
22002          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30 / .4) 12.5%, {0}(50% 60 70 / .8) 37.5%) }}",
22003          color_space
22004        ),
22005        &format!(".foo{{color:{}(44.2857% 54.2857 64.2857/.35)}}", color_space),
22006      ); // Scale up < 100% sum, causes alpha multiplication.
22007      minify_test(
22008        &format!(
22009          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30 / .4) 0%, {0}(50% 60 70 / .8)) }}",
22010          color_space
22011        ),
22012        &format!(".foo{{color:{}(50% 60 70/.8)}}", color_space),
22013      );
22014
22015      minify_test(
22016        &format!(
22017          ".foo {{ color: color-mix(in {0}, {0}(none none none), {0}(none none none)) }}",
22018          color_space
22019        ),
22020        &format!(".foo{{color:{}(none none none)}}", color_space),
22021      );
22022      minify_test(
22023        &format!(
22024          ".foo {{ color: color-mix(in {0}, {0}(none none none), {0}(50% 60 70)) }}",
22025          color_space
22026        ),
22027        &format!(".foo{{color:{}(50% 60 70)}}", color_space),
22028      );
22029      minify_test(
22030        &format!(
22031          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30), {0}(none none none)) }}",
22032          color_space
22033        ),
22034        &format!(".foo{{color:{}(10% 20 30)}}", color_space),
22035      );
22036      minify_test(
22037        &format!(
22038          ".foo {{ color: color-mix(in {0}, {0}(10% 20 none), {0}(50% 60 70)) }}",
22039          color_space
22040        ),
22041        &format!(".foo{{color:{}(30% 40 70)}}", color_space),
22042      );
22043      minify_test(
22044        &format!(
22045          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30), {0}(50% 60 none)) }}",
22046          color_space
22047        ),
22048        &format!(".foo{{color:{}(30% 40 30)}}", color_space),
22049      );
22050      minify_test(
22051        &format!(
22052          ".foo {{ color: color-mix(in {0}, {0}(none 20 30), {0}(50% none 70)) }}",
22053          color_space
22054        ),
22055        &format!(".foo{{color:{}(50% 20 50)}}", color_space),
22056      );
22057      minify_test(
22058        &format!(
22059          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30 / none), {0}(50% 60 70)) }}",
22060          color_space
22061        ),
22062        &format!(".foo{{color:{}(30% 40 50)}}", color_space),
22063      );
22064      minify_test(
22065        &format!(
22066          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30 / none), {0}(50% 60 70 / 0.5)) }}",
22067          color_space
22068        ),
22069        &format!(".foo{{color:{}(30% 40 50/.5)}}", color_space),
22070      );
22071      minify_test(
22072        &format!(
22073          ".foo {{ color: color-mix(in {0}, {0}(10% 20 30 / none), {0}(50% 60 70 / none)) }}",
22074          color_space
22075        ),
22076        &format!(".foo{{color:{}(30% 40 50/none)}}", color_space),
22077      );
22078    }
22079
22080    for color_space in [/*"srgb", */ "srgb-linear", "xyz", "xyz-d50", "xyz-d65"] {
22081      // regex for converting web platform tests:
22082      // test_computed_value\(.*?, `color-mix\(in \$\{colorSpace\}(.*?), (.*?)color\(\$\{colorSpace\}(.*?) color\(\$\{colorSpace\}(.*?)`, `color\(\$\{resultColorSpace\}(.*?)`\);
22083      // 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));
22084
22085      let result_color_space = if color_space == "xyz-d65" { "xyz" } else { color_space };
22086
22087      minify_test(
22088        &format!(
22089          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3), color({0} .5 .6 .7)) }}",
22090          color_space
22091        ),
22092        &format!(".foo{{color:color({} .3 .4 .5)}}", result_color_space),
22093      );
22094      minify_test(
22095        &format!(
22096          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3) 25%, color({0} .5 .6 .7)) }}",
22097          color_space
22098        ),
22099        &format!(".foo{{color:color({} .4 .5 .6)}}", result_color_space),
22100      );
22101      minify_test(
22102        &format!(
22103          ".foo {{ color: color-mix(in {0}, 25% color({0} .1 .2 .3), color({0} .5 .6 .7)) }}",
22104          color_space
22105        ),
22106        &format!(".foo{{color:color({} .4 .5 .6)}}", result_color_space),
22107      );
22108      minify_test(
22109        &format!(
22110          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3), color({0} .5 .6 .7) 25%) }}",
22111          color_space
22112        ),
22113        &format!(".foo{{color:color({} .2 .3 .4)}}", result_color_space),
22114      );
22115      minify_test(
22116        &format!(
22117          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3), 25% color({0} .5 .6 .7)) }}",
22118          color_space
22119        ),
22120        &format!(".foo{{color:color({} .2 .3 .4)}}", result_color_space),
22121      );
22122      minify_test(
22123        &format!(
22124          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3) 25%, color({0} .5 .6 .7) 75%) }}",
22125          color_space
22126        ),
22127        &format!(".foo{{color:color({} .4 .5 .6)}}", result_color_space),
22128      );
22129      minify_test(
22130        &format!(
22131          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3) 30%, color({0} .5 .6 .7) 90%) }}",
22132          color_space
22133        ),
22134        &format!(".foo{{color:color({} .4 .5 .6)}}", result_color_space),
22135      ); // Scale down > 100% sum.
22136      minify_test(
22137        &format!(
22138          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3) 12.5%, color({0} .5 .6 .7) 37.5%) }}",
22139          color_space
22140        ),
22141        &format!(".foo{{color:color({} .4 .5 .6/.5)}}", result_color_space),
22142      ); // Scale up < 100% sum, causes alpha multiplication.
22143      minify_test(
22144        &format!(
22145          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3) 0%, color({0} .5 .6 .7)) }}",
22146          color_space
22147        ),
22148        &format!(".foo{{color:color({} .5 .6 .7)}}", result_color_space),
22149      );
22150
22151      minify_test(
22152        &format!(
22153          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3 / .5), color({0} .5 .6 .7 / .8)) }}",
22154          color_space
22155        ),
22156        &format!(
22157          ".foo{{color:color({} .346154 .446154 .546154/.65)}}",
22158          result_color_space
22159        ),
22160      );
22161      minify_test(
22162        &format!(
22163          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3 / .4) 25%, color({0} .5 .6 .7 / .8)) }}",
22164          color_space
22165        ),
22166        &format!(".foo{{color:color({} .442857 .542857 .642857/.7)}}", result_color_space),
22167      );
22168      minify_test(
22169        &format!(
22170          ".foo {{ color: color-mix(in {0}, 25% color({0} .1 .2 .3 / .4), color({0} .5 .6 .7 / .8)) }}",
22171          color_space
22172        ),
22173        &format!(".foo{{color:color({} .442857 .542857 .642857/.7)}}", result_color_space),
22174      );
22175      minify_test(
22176        &format!(
22177          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3 / .4), color({0} .5 .6 .7 / .8) 25%) }}",
22178          color_space
22179        ),
22180        &format!(".foo{{color:color({} .26 .36 .46/.5)}}", result_color_space),
22181      );
22182      minify_test(
22183        &format!(
22184          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3 / .4), 25% color({0} .5 .6 .7 / .8)) }}",
22185          color_space
22186        ),
22187        &format!(".foo{{color:color({} .26 .36 .46/.5)}}", result_color_space),
22188      );
22189      minify_test(
22190        &format!(
22191          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3 / .4) 25%, color({0} .5 .6 .7 / .8) 75%) }}",
22192          color_space
22193        ),
22194        &format!(".foo{{color:color({} .442857 .542857 .642857/.7)}}", result_color_space),
22195      );
22196      minify_test(
22197        &format!(
22198          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3 / .4) 30%, color({0} .5 .6 .7 / .8) 90%) }}",
22199          color_space
22200        ),
22201        &format!(".foo{{color:color({} .442857 .542857 .642857/.7)}}", result_color_space),
22202      ); // Scale down > 100% sum.
22203      minify_test(
22204        &format!(
22205          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3 / .4) 12.5%, color({0} .5 .6 .7 / .8) 37.5%) }}",
22206          color_space
22207        ),
22208        &format!(
22209          ".foo{{color:color({} .442857 .542857 .642857/.35)}}",
22210          result_color_space
22211        ),
22212      ); // Scale up < 100% sum, causes alpha multiplication.
22213      minify_test(
22214        &format!(
22215          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3 / .4) 0%, color({0} .5 .6 .7 / .8)) }}",
22216          color_space
22217        ),
22218        &format!(".foo{{color:color({} .5 .6 .7/.8)}}", result_color_space),
22219      );
22220
22221      minify_test(
22222        &format!(
22223          ".foo {{ color: color-mix(in {0}, color({0} 2 3 4 / 5), color({0} 4 6 8 / 10)) }}",
22224          color_space
22225        ),
22226        &format!(".foo{{color:color({} 3 4.5 6)}}", result_color_space),
22227      );
22228      minify_test(
22229        &format!(
22230          ".foo {{ color: color-mix(in {0}, color({0} -2 -3 -4), color({0} -4 -6 -8)) }}",
22231          color_space
22232        ),
22233        &format!(".foo{{color:color({} -3 -4.5 -6)}}", result_color_space),
22234      );
22235      minify_test(
22236        &format!(
22237          ".foo {{ color: color-mix(in {0}, color({0} -2 -3 -4 / -5), color({0} -4 -6 -8 / -10)) }}",
22238          color_space
22239        ),
22240        &format!(".foo{{color:color({} 0 0 0/0)}}", result_color_space),
22241      );
22242
22243      minify_test(
22244        &format!(
22245          ".foo {{ color: color-mix(in {0}, color({0} none none none), color({0} none none none)) }}",
22246          color_space
22247        ),
22248        &format!(".foo{{color:color({} none none none)}}", result_color_space),
22249      );
22250      minify_test(
22251        &format!(
22252          ".foo {{ color: color-mix(in {0}, color({0} none none none), color({0} .5 .6 .7)) }}",
22253          color_space
22254        ),
22255        &format!(".foo{{color:color({} .5 .6 .7)}}", result_color_space),
22256      );
22257      minify_test(
22258        &format!(
22259          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3), color({0} none none none)) }}",
22260          color_space
22261        ),
22262        &format!(".foo{{color:color({} .1 .2 .3)}}", result_color_space),
22263      );
22264      minify_test(
22265        &format!(
22266          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 none), color({0} .5 .6 .7)) }}",
22267          color_space
22268        ),
22269        &format!(".foo{{color:color({} .3 .4 .7)}}", result_color_space),
22270      );
22271      minify_test(
22272        &format!(
22273          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3), color({0} .5 .6 none)) }}",
22274          color_space
22275        ),
22276        &format!(".foo{{color:color({} .3 .4 .3)}}", result_color_space),
22277      );
22278      minify_test(
22279        &format!(
22280          ".foo {{ color: color-mix(in {0}, color({0} none .2 .3), color({0} .5 none .7)) }}",
22281          color_space
22282        ),
22283        &format!(".foo{{color:color({} .5 .2 .5)}}", result_color_space),
22284      );
22285      minify_test(
22286        &format!(
22287          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3 / none), color({0} .5 .6 .7)) }}",
22288          color_space
22289        ),
22290        &format!(".foo{{color:color({} .3 .4 .5)}}", result_color_space),
22291      );
22292      minify_test(
22293        &format!(
22294          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3 / none), color({0} .5 .6 .7 / 0.5)) }}",
22295          color_space
22296        ),
22297        &format!(".foo{{color:color({} .3 .4 .5/.5)}}", result_color_space),
22298      );
22299      minify_test(
22300        &format!(
22301          ".foo {{ color: color-mix(in {0}, color({0} .1 .2 .3 / none), color({0} .5 .6 .7 / none)) }}",
22302          color_space
22303        ),
22304        &format!(".foo{{color:color({} .3 .4 .5/none)}}", result_color_space),
22305      );
22306    }
22307  }
22308
22309  #[test]
22310  fn test_grid() {
22311    minify_test(
22312      ".foo { grid-template-columns: [first nav-start]  150px [main-start] 1fr [last]; }",
22313      ".foo{grid-template-columns:[first nav-start]150px[main-start]1fr[last]}",
22314    );
22315    minify_test(
22316      ".foo { grid-template-columns: 150px 1fr; }",
22317      ".foo{grid-template-columns:150px 1fr}",
22318    );
22319    minify_test(
22320      ".foo { grid-template-columns: repeat(4, 1fr); }",
22321      ".foo{grid-template-columns:repeat(4,1fr)}",
22322    );
22323    minify_test(
22324      ".foo { grid-template-columns: repeat(2, [e] 40px); }",
22325      ".foo{grid-template-columns:repeat(2,[e]40px)}",
22326    );
22327    minify_test(
22328      ".foo { grid-template-columns: repeat(4, [col-start] 250px [col-end]); }",
22329      ".foo{grid-template-columns:repeat(4,[col-start]250px[col-end])}",
22330    );
22331    minify_test(
22332      ".foo { grid-template-columns: repeat(4, [col-start] 60% [col-end]); }",
22333      ".foo{grid-template-columns:repeat(4,[col-start]60%[col-end])}",
22334    );
22335    minify_test(
22336      ".foo { grid-template-columns: repeat(4, [col-start] 1fr [col-end]); }",
22337      ".foo{grid-template-columns:repeat(4,[col-start]1fr[col-end])}",
22338    );
22339    minify_test(
22340      ".foo { grid-template-columns: repeat(4, [col-start] min-content [col-end]); }",
22341      ".foo{grid-template-columns:repeat(4,[col-start]min-content[col-end])}",
22342    );
22343    minify_test(
22344      ".foo { grid-template-columns: repeat(4, [col-start] max-content [col-end]); }",
22345      ".foo{grid-template-columns:repeat(4,[col-start]max-content[col-end])}",
22346    );
22347    minify_test(
22348      ".foo { grid-template-columns: repeat(4, [col-start] auto [col-end]); }",
22349      ".foo{grid-template-columns:repeat(4,[col-start]auto[col-end])}",
22350    );
22351    minify_test(
22352      ".foo { grid-template-columns: repeat(4, [col-start] minmax(100px, 1fr) [col-end]); }",
22353      ".foo{grid-template-columns:repeat(4,[col-start]minmax(100px,1fr)[col-end])}",
22354    );
22355    minify_test(
22356      ".foo { grid-template-columns: repeat(4, [col-start] fit-content(200px) [col-end]); }",
22357      ".foo{grid-template-columns:repeat(4,[col-start]fit-content(200px)[col-end])}",
22358    );
22359    minify_test(
22360      ".foo { grid-template-columns: repeat(4, 10px [col-start] 30% [col-middle] auto [col-end]); }",
22361      ".foo{grid-template-columns:repeat(4,10px[col-start]30%[col-middle]auto[col-end])}",
22362    );
22363    minify_test(
22364      ".foo { grid-template-columns: repeat(5, auto); }",
22365      ".foo{grid-template-columns:repeat(5,auto)}",
22366    );
22367    minify_test(
22368      ".foo { grid-template-columns: repeat(auto-fill, 250px); }",
22369      ".foo{grid-template-columns:repeat(auto-fill,250px)}",
22370    );
22371    minify_test(
22372      ".foo { grid-template-columns: repeat(auto-fit, 250px); }",
22373      ".foo{grid-template-columns:repeat(auto-fit,250px)}",
22374    );
22375    minify_test(
22376      ".foo { grid-template-columns: repeat(auto-fill, [col-start] 250px [col-end]); }",
22377      ".foo{grid-template-columns:repeat(auto-fill,[col-start]250px[col-end])}",
22378    );
22379    minify_test(
22380      ".foo { grid-template-columns: repeat(auto-fill, [col-start] minmax(100px, 1fr) [col-end]); }",
22381      ".foo{grid-template-columns:repeat(auto-fill,[col-start]minmax(100px,1fr)[col-end])}",
22382    );
22383    minify_test(
22384      ".foo { grid-template-columns: minmax(min-content, 1fr); }",
22385      ".foo{grid-template-columns:minmax(min-content,1fr)}",
22386    );
22387    minify_test(
22388      ".foo { grid-template-columns: 200px repeat(auto-fill, 100px) 300px; }",
22389      ".foo{grid-template-columns:200px repeat(auto-fill,100px) 300px}",
22390    );
22391    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]}");
22392    minify_test(
22393      ".foo { grid-template-rows: [linename1 linename2] 100px repeat(auto-fit, [linename1] 300px) [linename3]; }",
22394      ".foo{grid-template-rows:[linename1 linename2]100px repeat(auto-fit,[linename1]300px)[linename3]}",
22395    );
22396
22397    minify_test(".foo { grid-auto-rows: auto; }", ".foo{grid-auto-rows:auto}");
22398    minify_test(".foo { grid-auto-rows: 1fr; }", ".foo{grid-auto-rows:1fr}");
22399    minify_test(".foo { grid-auto-rows: 100px; }", ".foo{grid-auto-rows:100px}");
22400    minify_test(
22401      ".foo { grid-auto-rows: min-content; }",
22402      ".foo{grid-auto-rows:min-content}",
22403    );
22404    minify_test(
22405      ".foo { grid-auto-rows: max-content; }",
22406      ".foo{grid-auto-rows:max-content}",
22407    );
22408    minify_test(
22409      ".foo { grid-auto-rows: minmax(100px,auto); }",
22410      ".foo{grid-auto-rows:minmax(100px,auto)}",
22411    );
22412    minify_test(
22413      ".foo { grid-auto-rows: fit-content(20%); }",
22414      ".foo{grid-auto-rows:fit-content(20%)}",
22415    );
22416    minify_test(
22417      ".foo { grid-auto-rows: 100px minmax(100px, auto) 10% 0.5fr fit-content(400px); }",
22418      ".foo{grid-auto-rows:100px minmax(100px,auto) 10% .5fr fit-content(400px)}",
22419    );
22420    minify_test(
22421      ".foo { grid-auto-columns: 100px minmax(100px, auto) 10% 0.5fr fit-content(400px); }",
22422      ".foo{grid-auto-columns:100px minmax(100px,auto) 10% .5fr fit-content(400px)}",
22423    );
22424
22425    minify_test(
22426      r#"
22427      .foo {
22428        grid-template-areas: "head head"
22429                             "nav  main"
22430                             "foot ....";
22431      }
22432    "#,
22433      ".foo{grid-template-areas:\"head head\"\"nav main\"\"foot.\"}",
22434    );
22435    minify_test(
22436      r#"
22437      .foo {
22438        grid-template-areas: "head head"
22439                             "nav  main"
22440                             ".... foot";
22441      }
22442    "#,
22443      ".foo{grid-template-areas:\"head head\"\"nav main\"\".foot\"}",
22444    );
22445    minify_test(
22446      r#"
22447      .foo {
22448        grid-template-areas: "head head"
22449                             "nav  main"
22450                             ".... ....";
22451      }
22452    "#,
22453      ".foo{grid-template-areas:\"head head\"\"nav main\"\". .\"}",
22454    );
22455
22456    // to grid-* shorthand
22457    minify_test(
22458      r#"
22459      .test-miss-areas {
22460        grid-template-columns: 1fr 90px;
22461        grid-template-rows: auto 80px;
22462        grid-template-areas: "one";
22463      }
22464    "#,
22465      ".test-miss-areas{grid-template:\"one\"\".\"80px/1fr 90px}",
22466    );
22467    test(
22468      r#"
22469      .test-miss-areas-2 {
22470        grid-template-columns: 1fr 1fr 1fr;      
22471        grid-template-rows: 30px 60px 100px;
22472        grid-template-areas: "a a a" "b c c";
22473      }
22474    "#,
22475      indoc! { r#"
22476      .test-miss-areas-2 {
22477        grid-template: "a a a" 30px
22478                       "b c c" 60px
22479                       ". . ." 100px
22480                       / 1fr 1fr 1fr;
22481      }
22482    "#},
22483    );
22484
22485    test(
22486      r#"
22487      .test-miss-areas-3 {
22488        grid-template: 30px 60px 100px / 1fr 1fr 1fr;
22489        grid-template-areas: "a a a" "b c c";
22490      }
22491    "#,
22492      indoc! { r#"
22493      .test-miss-areas-3 {
22494        grid-template: "a a a" 30px
22495                       "b c c" 60px
22496                       ". . ." 100px
22497                       / 1fr 1fr 1fr;
22498      }
22499    "#},
22500    );
22501
22502    test(
22503      r#"
22504      .test-miss-areas-4 {
22505        grid: 30px 60px 100px / 1fr 1fr 1fr;
22506        grid-template-areas: "a a a" "b c c";
22507      }
22508    "#,
22509      indoc! { r#"
22510      .test-miss-areas-4 {
22511        grid: "a a a" 30px
22512              "b c c" 60px
22513              ". . ." 100px
22514              / 1fr 1fr 1fr;
22515      }
22516    "#},
22517    );
22518
22519    // test no unreachable error
22520    minify_test(
22521      r#"
22522    .grid-shorthand-areas {
22523      grid: auto / 1fr 3fr;
22524      grid-template-areas: ". content .";
22525    }
22526  "#,
22527      ".grid-shorthand-areas{grid:\".content.\"/1fr 3fr}",
22528    );
22529    minify_test(
22530      r#"
22531    .grid-shorthand-areas-rows {
22532      grid: auto / 1fr 3fr;
22533      grid-template-rows: 20px;
22534      grid-template-areas: ". content .";
22535    }
22536  "#,
22537      ".grid-shorthand-areas-rows{grid:\".content.\"20px/1fr 3fr}",
22538    );
22539
22540    // test grid-auto-flow: row in grid shorthand
22541    test(
22542      r#"
22543      .test-auto-flow-row-1 {
22544        grid: auto-flow   /  1fr 2fr 1fr;
22545        grid-template-areas: "  .   one  .  ";
22546      }
22547    "#,
22548      indoc! { r#"
22549      .test-auto-flow-row-1 {
22550        grid: auto-flow / 1fr 2fr 1fr;
22551        grid-template-areas: ". one .";
22552      }
22553    "#},
22554    );
22555    test(
22556      r#"
22557      .test-auto-flow-row-2 {
22558        grid: auto-flow   auto   /  100px   100px;
22559        grid-template-areas: " one  two ";
22560      }
22561    "#,
22562      indoc! { r#"
22563      .test-auto-flow-row-2 {
22564        grid: auto-flow / 100px 100px;
22565        grid-template-areas: "one two";
22566      }
22567    "#},
22568    );
22569    test(
22570      r#"
22571      .test-auto-flow-dense {
22572        grid: dense auto-flow  /  1fr 2fr;
22573        grid-template-areas: "  .   content  .  ";
22574      }
22575    "#,
22576      indoc! { r#"
22577      .test-auto-flow-dense {
22578        grid: auto-flow dense / 1fr 2fr;
22579        grid-template-areas: ". content .";
22580      }
22581    "#},
22582    );
22583    minify_test(
22584      r#"
22585      .grid-auto-flow-row-auto-rows {
22586        grid: auto-flow 40px / 1fr 90px;
22587        grid-template-areas: "a";
22588      }
22589    "#,
22590      ".grid-auto-flow-row-auto-rows{grid:auto-flow 40px/1fr 90px;grid-template-areas:\"a\"}",
22591    );
22592    minify_test(
22593      r#"
22594      .grid-auto-flow-row-auto-rows-multiple {
22595        grid: auto-flow 40px max-content / 1fr;
22596        grid-template-areas: ". a";
22597      }
22598    "#,
22599      ".grid-auto-flow-row-auto-rows-multiple{grid:auto-flow 40px max-content/1fr;grid-template-areas:\".a\"}",
22600    );
22601
22602    // test grid-auto-flow: column in grid shorthand
22603    test(
22604      r#"
22605      .test-auto-flow-column-1 {
22606        grid: 300px / auto-flow;
22607        grid-template-areas: "  .   one  .  ";
22608      }
22609    "#,
22610      indoc! { r#"
22611      .test-auto-flow-column-1 {
22612        grid: 300px / auto-flow;
22613        grid-template-areas: ". one .";
22614      }
22615    "#},
22616    );
22617    test(
22618      r#"
22619      .test-auto-flow-column-2 {
22620        grid: 200px 1fr / auto-flow auto;
22621        grid-template-areas: "  .   one  .  ";
22622      }
22623    "#,
22624      indoc! { r#"
22625      .test-auto-flow-column-2 {
22626        grid: 200px 1fr / auto-flow;
22627        grid-template-areas: ". one .";
22628      }
22629    "#},
22630    );
22631    test(
22632      r#"
22633      .test-auto-flow-column-dense {
22634        grid: 1fr 2fr / dense auto-flow;
22635        grid-template-areas: "  .   content  .  ";
22636      }
22637    "#,
22638      indoc! { r#"
22639      .test-auto-flow-column-dense {
22640        grid: 1fr 2fr / auto-flow dense;
22641        grid-template-areas: ". content .";
22642      }
22643    "#},
22644    );
22645    minify_test(
22646      r#"
22647      .grid-auto-flow-column-auto-rows {
22648        grid: 1fr 3fr / auto-flow 40px;
22649        grid-template-areas: "a";
22650      }
22651    "#,
22652      ".grid-auto-flow-column-auto-rows{grid:1fr 3fr/auto-flow 40px;grid-template-areas:\"a\"}",
22653    );
22654    minify_test(
22655      r#"
22656      .grid-auto-flow-column-auto-rows-multiple {
22657        grid: 1fr / auto-flow 40px max-content ;
22658        grid-template-areas: ". a";
22659      }
22660    "#,
22661      ".grid-auto-flow-column-auto-rows-multiple{grid:1fr/auto-flow 40px max-content;grid-template-areas:\".a\"}",
22662    );
22663
22664    test(
22665      r#"
22666      .foo {
22667        grid-template-areas: "head head" "nav  main" "foot ....";
22668      }
22669    "#,
22670      indoc! { r#"
22671      .foo {
22672        grid-template-areas: "head head"
22673                             "nav main"
22674                             "foot .";
22675      }
22676    "#},
22677    );
22678
22679    minify_test(
22680      r#"
22681      .foo {
22682        grid-template: [header-top] "a   a   a"     [header-bottom]
22683                       [main-top] "b   b   b" 1fr [main-bottom];
22684      }
22685    "#,
22686      ".foo{grid-template:[header-top]\"a a a\"[header-bottom main-top]\"b b b\"1fr[main-bottom]}",
22687    );
22688    minify_test(
22689      r#"
22690      .foo {
22691        grid-template: "head head"
22692                       "nav  main" 1fr
22693                       "foot ....";
22694      }
22695    "#,
22696      ".foo{grid-template:\"head head\"\"nav main\"1fr\"foot.\"}",
22697    );
22698    minify_test(
22699      r#"
22700      .foo {
22701        grid-template: [header-top] "a   a   a"     [header-bottom]
22702                         [main-top] "b   b   b" 1fr [main-bottom]
22703                                  / auto 1fr auto;
22704      }
22705    "#,
22706      ".foo{grid-template:[header-top]\"a a a\"[header-bottom main-top]\"b b b\"1fr[main-bottom]/auto 1fr auto}",
22707    );
22708
22709    minify_test(
22710      ".foo { grid-template: auto 1fr / auto 1fr auto; }",
22711      ".foo{grid-template:auto 1fr/auto 1fr auto}",
22712    );
22713    minify_test(
22714      ".foo { grid-template: [linename1 linename2] 100px repeat(auto-fit, [linename1] 300px) [linename3] / [linename1 linename2] 100px repeat(auto-fit, [linename1] 300px) [linename3]; }",
22715      ".foo{grid-template:[linename1 linename2]100px repeat(auto-fit,[linename1]300px)[linename3]/[linename1 linename2]100px repeat(auto-fit,[linename1]300px)[linename3]}"
22716    );
22717
22718    test(
22719      ".foo{grid-template:[header-top]\"a a a\"[header-bottom main-top]\"b b b\"1fr[main-bottom]/auto 1fr auto}",
22720      indoc! {r#"
22721        .foo {
22722          grid-template: [header-top] "a a a" [header-bottom]
22723                         [main-top] "b b b" 1fr [main-bottom]
22724                         / auto 1fr auto;
22725        }
22726      "#},
22727    );
22728    test(
22729      ".foo{grid-template:[header-top]\"a a a\"[main-top]\"b b b\"1fr/auto 1fr auto}",
22730      indoc! {r#"
22731        .foo {
22732          grid-template: [header-top] "a a a"
22733                         [main-top] "b b b" 1fr
22734                         / auto 1fr auto;
22735        }
22736      "#},
22737    );
22738
22739    minify_test(".foo { grid-auto-flow: row }", ".foo{grid-auto-flow:row}");
22740    minify_test(".foo { grid-auto-flow: column }", ".foo{grid-auto-flow:column}");
22741    minify_test(".foo { grid-auto-flow: row dense }", ".foo{grid-auto-flow:dense}");
22742    minify_test(".foo { grid-auto-flow: dense row }", ".foo{grid-auto-flow:dense}");
22743    minify_test(
22744      ".foo { grid-auto-flow: column dense }",
22745      ".foo{grid-auto-flow:column dense}",
22746    );
22747    minify_test(
22748      ".foo { grid-auto-flow: dense column }",
22749      ".foo{grid-auto-flow:column dense}",
22750    );
22751
22752    minify_test(".foo { grid: none }", ".foo{grid:none}");
22753    minify_test(".foo { grid: \"a\" 100px \"b\" 1fr }", ".foo{grid:\"a\"100px\"b\"1fr}");
22754    minify_test(
22755      ".foo { grid: [linename1] \"a\" 100px [linename2] }",
22756      ".foo{grid:[linename1]\"a\"100px[linename2]}",
22757    );
22758    minify_test(
22759      ".foo { grid: \"a\" 200px \"b\" min-content }",
22760      ".foo{grid:\"a\"200px\"b\"min-content}",
22761    );
22762    minify_test(
22763      ".foo { grid: \"a\" minmax(100px, max-content) \"b\" 20% }",
22764      ".foo{grid:\"a\"minmax(100px,max-content)\"b\"20%}",
22765    );
22766    minify_test(".foo { grid: 100px / 200px }", ".foo{grid:100px/200px}");
22767    minify_test(
22768      ".foo { grid: minmax(400px, min-content) / repeat(auto-fill, 50px) }",
22769      ".foo{grid:minmax(400px,min-content)/repeat(auto-fill,50px)}",
22770    );
22771
22772    minify_test(".foo { grid: 200px / auto-flow }", ".foo{grid:200px/auto-flow}");
22773    minify_test(".foo { grid: 30% / auto-flow dense }", ".foo{grid:30%/auto-flow dense}");
22774    minify_test(".foo { grid: 30% / dense auto-flow }", ".foo{grid:30%/auto-flow dense}");
22775    minify_test(
22776      ".foo { grid: repeat(3, [line1 line2 line3] 200px) / auto-flow 300px }",
22777      ".foo{grid:repeat(3,[line1 line2 line3]200px)/auto-flow 300px}",
22778    );
22779    minify_test(
22780      ".foo { grid: [line1] minmax(20em, max-content) / auto-flow dense 40% }",
22781      ".foo{grid:[line1]minmax(20em,max-content)/auto-flow dense 40%}",
22782    );
22783    minify_test(".foo { grid: none / auto-flow 1fr }", ".foo{grid:none/auto-flow 1fr}");
22784
22785    minify_test(".foo { grid: auto-flow / 200px }", ".foo{grid:none/200px}");
22786    minify_test(".foo { grid: auto-flow dense / 30% }", ".foo{grid:auto-flow dense/30%}");
22787    minify_test(".foo { grid: dense auto-flow / 30% }", ".foo{grid:auto-flow dense/30%}");
22788    minify_test(
22789      ".foo { grid: auto-flow 300px / repeat(3, [line1 line2 line3] 200px) }",
22790      ".foo{grid:auto-flow 300px/repeat(3,[line1 line2 line3]200px)}",
22791    );
22792    minify_test(
22793      ".foo { grid: auto-flow dense 40% / [line1] minmax(20em, max-content) }",
22794      ".foo{grid:auto-flow dense 40%/[line1]minmax(20em,max-content)}",
22795    );
22796
22797    minify_test(".foo { grid-row-start: auto }", ".foo{grid-row-start:auto}");
22798    minify_test(".foo { grid-row-start: some-area }", ".foo{grid-row-start:some-area}");
22799    minify_test(".foo { grid-row-start: 2 }", ".foo{grid-row-start:2}");
22800    minify_test(
22801      ".foo { grid-row-start: 2 some-line }",
22802      ".foo{grid-row-start:2 some-line}",
22803    );
22804    minify_test(
22805      ".foo { grid-row-start: some-line 2 }",
22806      ".foo{grid-row-start:2 some-line}",
22807    );
22808    minify_test(".foo { grid-row-start: span 3 }", ".foo{grid-row-start:span 3}");
22809    minify_test(
22810      ".foo { grid-row-start: span some-line }",
22811      ".foo{grid-row-start:span some-line}",
22812    );
22813    minify_test(
22814      ".foo { grid-row-start: span some-line 1 }",
22815      ".foo{grid-row-start:span some-line}",
22816    );
22817    minify_test(
22818      ".foo { grid-row-start: span 1 some-line }",
22819      ".foo{grid-row-start:span some-line}",
22820    );
22821    minify_test(
22822      ".foo { grid-row-start: span 5 some-line }",
22823      ".foo{grid-row-start:span 5 some-line}",
22824    );
22825    minify_test(
22826      ".foo { grid-row-start: span some-line 5 }",
22827      ".foo{grid-row-start:span 5 some-line}",
22828    );
22829
22830    minify_test(
22831      ".foo { grid-row-end: span 1 some-line }",
22832      ".foo{grid-row-end:span some-line}",
22833    );
22834    minify_test(
22835      ".foo { grid-column-start: span 1 some-line }",
22836      ".foo{grid-column-start:span some-line}",
22837    );
22838    minify_test(
22839      ".foo { grid-column-end: span 1 some-line }",
22840      ".foo{grid-column-end:span some-line}",
22841    );
22842
22843    minify_test(".foo { grid-row: 1 }", ".foo{grid-row:1}");
22844    minify_test(".foo { grid-row: 1 / auto }", ".foo{grid-row:1}");
22845    minify_test(".foo { grid-row: 1 / 1 }", ".foo{grid-row:1/1}");
22846    minify_test(".foo { grid-row: 1 / 3 }", ".foo{grid-row:1/3}");
22847    minify_test(".foo { grid-row: 1 / span 2 }", ".foo{grid-row:1/span 2}");
22848    minify_test(".foo { grid-row: main-start }", ".foo{grid-row:main-start}");
22849    minify_test(
22850      ".foo { grid-row: main-start / main-end }",
22851      ".foo{grid-row:main-start/main-end}",
22852    );
22853    minify_test(
22854      ".foo { grid-row: main-start / main-start }",
22855      ".foo{grid-row:main-start}",
22856    );
22857    minify_test(".foo { grid-column: 1 / auto }", ".foo{grid-column:1}");
22858
22859    minify_test(".foo { grid-area: a }", ".foo{grid-area:a}");
22860    minify_test(".foo { grid-area: a / a / a / a }", ".foo{grid-area:a}");
22861    minify_test(".foo { grid-area: a / b / a / b }", ".foo{grid-area:a/b}");
22862    minify_test(".foo { grid-area: a / b / c / b }", ".foo{grid-area:a/b/c}");
22863    minify_test(".foo { grid-area: a / b / c / d }", ".foo{grid-area:a/b/c/d}");
22864
22865    minify_test(".foo { grid-area: auto / auto / auto / auto }", ".foo{grid-area:auto}");
22866    minify_test(".foo { grid-area: 1 / auto }", ".foo{grid-area:1}");
22867    minify_test(".foo { grid-area: 1 / 2 / 3 / 4 }", ".foo{grid-area:1/2/3/4}");
22868    minify_test(".foo { grid-area: 1 / 1 / 1 / 1 }", ".foo{grid-area:1/1/1/1}");
22869
22870    test(
22871      r#"
22872        .foo{
22873          grid-template-rows: auto 1fr;
22874          grid-template-columns: auto 1fr auto;
22875          grid-template-areas: none;
22876        }
22877      "#,
22878      indoc! {r#"
22879        .foo {
22880          grid-template: auto 1fr / auto 1fr auto;
22881        }
22882      "#},
22883    );
22884
22885    test(
22886      r#"
22887        .foo{
22888          grid-template-areas: "a a a"
22889                               "b b b";
22890          grid-template-rows: [header-top] auto [header-bottom main-top] 1fr [main-bottom];
22891          grid-template-columns: auto 1fr auto;
22892        }
22893      "#,
22894      indoc! {r#"
22895        .foo {
22896          grid-template: [header-top] "a a a" [header-bottom]
22897                         [main-top] "b b b" 1fr [main-bottom]
22898                         / auto 1fr auto;
22899        }
22900      "#},
22901    );
22902
22903    test(
22904      r#"
22905        .foo{
22906          grid-template-areas: "a a a"
22907                               "b b b";
22908          grid-template-columns: repeat(3, 1fr);
22909          grid-template-rows: auto 1fr;
22910        }
22911      "#,
22912      indoc! {r#"
22913        .foo {
22914          grid-template-rows: auto 1fr;
22915          grid-template-columns: repeat(3, 1fr);
22916          grid-template-areas: "a a a"
22917                               "b b b";
22918        }
22919      "#},
22920    );
22921
22922    test(
22923      r#"
22924        .foo{
22925          grid-template-areas: "a a a"
22926                               "b b b";
22927          grid-template-columns: auto 1fr auto;
22928          grid-template-rows: repeat(2, 1fr);
22929        }
22930      "#,
22931      indoc! {r#"
22932        .foo {
22933          grid-template-rows: repeat(2, 1fr);
22934          grid-template-columns: auto 1fr auto;
22935          grid-template-areas: "a a a"
22936                               "b b b";
22937        }
22938      "#},
22939    );
22940
22941    test(
22942      r#"
22943        .foo{
22944          grid-template-areas: ". a a ."
22945                               ". b b .";
22946          grid-template-rows: auto 1fr;
22947          grid-template-columns: 10px 1fr 1fr 10px;
22948        }
22949      "#,
22950      indoc! {r#"
22951        .foo {
22952          grid-template: ". a a ."
22953                         ". b b ." 1fr
22954                         / 10px 1fr 1fr 10px;
22955        }
22956      "#},
22957    );
22958
22959    test(
22960      r#"
22961        .foo{
22962          grid-template-areas: none;
22963          grid-template-columns: auto 1fr auto;
22964          grid-template-rows: repeat(2, 1fr);
22965        }
22966      "#,
22967      indoc! {r#"
22968        .foo {
22969          grid-template: repeat(2, 1fr) / auto 1fr auto;
22970        }
22971      "#},
22972    );
22973
22974    test(
22975      r#"
22976        .foo{
22977          grid-template-areas: none;
22978          grid-template-columns: none;
22979          grid-template-rows: none;
22980        }
22981      "#,
22982      indoc! {r#"
22983        .foo {
22984          grid-template: none;
22985        }
22986      "#},
22987    );
22988
22989    test(
22990      r#"
22991        .foo{
22992          grid-template-areas: "a a a"
22993                               "b b b";
22994          grid-template-rows: [header-top] auto [header-bottom main-top] 1fr [main-bottom];
22995          grid-template-columns: auto 1fr auto;
22996          grid-auto-flow: row;
22997          grid-auto-rows: auto;
22998          grid-auto-columns: auto;
22999        }
23000      "#,
23001      indoc! {r#"
23002        .foo {
23003          grid: [header-top] "a a a" [header-bottom]
23004                [main-top] "b b b" 1fr [main-bottom]
23005                / auto 1fr auto;
23006        }
23007      "#},
23008    );
23009
23010    test(
23011      r#"
23012        .foo{
23013          grid-template-areas: none;
23014          grid-template-columns: auto 1fr auto;
23015          grid-template-rows: repeat(2, 1fr);
23016          grid-auto-flow: row;
23017          grid-auto-rows: auto;
23018          grid-auto-columns: auto;
23019        }
23020      "#,
23021      indoc! {r#"
23022        .foo {
23023          grid: repeat(2, 1fr) / auto 1fr auto;
23024        }
23025      "#},
23026    );
23027
23028    test(
23029      r#"
23030        .foo{
23031          grid-template-areas: none;
23032          grid-template-columns: none;
23033          grid-template-rows: none;
23034          grid-auto-flow: row;
23035          grid-auto-rows: auto;
23036          grid-auto-columns: auto;
23037        }
23038      "#,
23039      indoc! {r#"
23040        .foo {
23041          grid: none;
23042        }
23043      "#},
23044    );
23045
23046    test(
23047      r#"
23048        .foo{
23049          grid-template-areas: "a a a"
23050                               "b b b";
23051          grid-template-rows: [header-top] auto [header-bottom main-top] 1fr [main-bottom];
23052          grid-template-columns: auto 1fr auto;
23053          grid-auto-flow: column;
23054          grid-auto-rows: 1fr;
23055          grid-auto-columns: 1fr;
23056        }
23057      "#,
23058      indoc! {r#"
23059        .foo {
23060          grid-template: [header-top] "a a a" [header-bottom]
23061                         [main-top] "b b b" 1fr [main-bottom]
23062                         / auto 1fr auto;
23063          grid-auto-rows: 1fr;
23064          grid-auto-columns: 1fr;
23065          grid-auto-flow: column;
23066        }
23067      "#},
23068    );
23069
23070    test(
23071      r#"
23072        .foo{
23073          grid-template-rows: auto 1fr;
23074          grid-template-columns: auto 1fr auto;
23075          grid-template-areas: none;
23076          grid-auto-flow: row;
23077          grid-auto-rows: auto;
23078          grid-auto-columns: auto;
23079        }
23080      "#,
23081      indoc! {r#"
23082        .foo {
23083          grid: auto 1fr / auto 1fr auto;
23084        }
23085      "#},
23086    );
23087
23088    test(
23089      r#"
23090        .foo{
23091          grid-template-rows: auto 1fr;
23092          grid-template-columns: auto 1fr auto;
23093          grid-template-areas: none;
23094          grid-auto-flow: column;
23095          grid-auto-rows: 1fr;
23096          grid-auto-columns: 1fr;
23097        }
23098      "#,
23099      indoc! {r#"
23100        .foo {
23101          grid-template: auto 1fr / auto 1fr auto;
23102          grid-auto-rows: 1fr;
23103          grid-auto-columns: 1fr;
23104          grid-auto-flow: column;
23105        }
23106      "#},
23107    );
23108
23109    test(
23110      r#"
23111        .foo{
23112          grid-template-rows: none;
23113          grid-template-columns: auto 1fr auto;
23114          grid-template-areas: none;
23115          grid-auto-flow: column;
23116          grid-auto-rows: 1fr;
23117          grid-auto-columns: 1fr;
23118        }
23119      "#,
23120      indoc! {r#"
23121        .foo {
23122          grid-template: none / auto 1fr auto;
23123          grid-auto-rows: 1fr;
23124          grid-auto-columns: 1fr;
23125          grid-auto-flow: column;
23126        }
23127      "#},
23128    );
23129
23130    test(
23131      r#"
23132        .foo{
23133          grid-template-rows: none;
23134          grid-template-columns: auto 1fr auto;
23135          grid-template-areas: none;
23136          grid-auto-flow: row;
23137          grid-auto-rows: 1fr;
23138          grid-auto-columns: auto;
23139        }
23140      "#,
23141      indoc! {r#"
23142        .foo {
23143          grid: auto-flow 1fr / auto 1fr auto;
23144        }
23145      "#},
23146    );
23147
23148    test(
23149      r#"
23150        .foo{
23151          grid-template-rows: none;
23152          grid-template-columns: auto 1fr auto;
23153          grid-template-areas: none;
23154          grid-auto-flow: row dense;
23155          grid-auto-rows: 1fr;
23156          grid-auto-columns: auto;
23157        }
23158      "#,
23159      indoc! {r#"
23160        .foo {
23161          grid: auto-flow dense 1fr / auto 1fr auto;
23162        }
23163      "#},
23164    );
23165
23166    test(
23167      r#"
23168        .foo{
23169          grid-template-rows: auto 1fr auto;
23170          grid-template-columns: none;
23171          grid-template-areas: none;
23172          grid-auto-flow: column;
23173          grid-auto-rows: auto;
23174          grid-auto-columns: 1fr;
23175        }
23176      "#,
23177      indoc! {r#"
23178        .foo {
23179          grid: auto 1fr auto / auto-flow 1fr;
23180        }
23181      "#},
23182    );
23183
23184    test(
23185      r#"
23186        .foo{
23187          grid-template-rows: auto 1fr auto;
23188          grid-template-columns: none;
23189          grid-template-areas: none;
23190          grid-auto-flow: column dense;
23191          grid-auto-rows: auto;
23192          grid-auto-columns: 1fr;
23193        }
23194      "#,
23195      indoc! {r#"
23196        .foo {
23197          grid: auto 1fr auto / auto-flow dense 1fr;
23198        }
23199      "#},
23200    );
23201
23202    test(
23203      r#"
23204        .foo{
23205          grid-template-rows: auto 1fr auto;
23206          grid-template-columns: none;
23207          grid-template-areas: none;
23208          grid-auto-flow: var(--auto-flow);
23209          grid-auto-rows: auto;
23210          grid-auto-columns: 1fr;
23211        }
23212      "#,
23213      indoc! {r#"
23214        .foo {
23215          grid-template: auto 1fr auto / none;
23216          grid-auto-flow: var(--auto-flow);
23217          grid-auto-rows: auto;
23218          grid-auto-columns: 1fr;
23219        }
23220      "#},
23221    );
23222
23223    test(
23224      r#"
23225        .foo{
23226          grid: auto 1fr auto / auto-flow dense 1fr;
23227          grid-template-rows: 1fr 1fr 1fr;
23228        }
23229      "#,
23230      indoc! {r#"
23231        .foo {
23232          grid: 1fr 1fr 1fr / auto-flow dense 1fr;
23233        }
23234      "#},
23235    );
23236
23237    test(
23238      r#"
23239        .foo{
23240          grid-row-start: a;
23241          grid-row-end: a;
23242          grid-column-start: a;
23243          grid-column-end: a;
23244        }
23245      "#,
23246      indoc! {r#"
23247        .foo {
23248          grid-area: a;
23249        }
23250      "#},
23251    );
23252
23253    test(
23254      r#"
23255        .foo{
23256          grid-row-start: 1;
23257          grid-row-end: 2;
23258          grid-column-start: 3;
23259          grid-column-end: 4;
23260        }
23261      "#,
23262      indoc! {r#"
23263        .foo {
23264          grid-area: 1 / 3 / 2 / 4;
23265        }
23266      "#},
23267    );
23268
23269    test(
23270      r#"
23271        .foo{
23272          grid-row-start: a;
23273          grid-row-end: a;
23274        }
23275      "#,
23276      indoc! {r#"
23277        .foo {
23278          grid-row: a;
23279        }
23280      "#},
23281    );
23282
23283    test(
23284      r#"
23285        .foo{
23286          grid-column-start: a;
23287          grid-column-end: a;
23288        }
23289      "#,
23290      indoc! {r#"
23291        .foo {
23292          grid-column: a;
23293        }
23294      "#},
23295    );
23296  }
23297
23298  #[test]
23299  fn test_moz_document() {
23300    minify_test(
23301      r#"
23302      @-moz-document url-prefix() {
23303        h1 {
23304          color: yellow;
23305        }
23306      }
23307    "#,
23308      "@-moz-document url-prefix(){h1{color:#ff0}}",
23309    );
23310    minify_test(
23311      r#"
23312      @-moz-document url-prefix("") {
23313        h1 {
23314          color: yellow;
23315        }
23316      }
23317    "#,
23318      "@-moz-document url-prefix(){h1{color:#ff0}}",
23319    );
23320    error_test(
23321      "@-moz-document url-prefix(foo) {}",
23322      ParserError::UnexpectedToken(crate::properties::custom::Token::Ident("foo".into())),
23323    );
23324    error_test(
23325      "@-moz-document url-prefix(\"foo\") {}",
23326      ParserError::UnexpectedToken(crate::properties::custom::Token::String("foo".into())),
23327    );
23328  }
23329
23330  #[test]
23331  fn test_custom_properties() {
23332    minify_test(".foo { --test: ; }", ".foo{--test: }");
23333    minify_test(".foo { --test:  ; }", ".foo{--test: }");
23334    minify_test(".foo { --test: foo; }", ".foo{--test:foo}");
23335    minify_test(".foo { --test:  foo; }", ".foo{--test:foo}");
23336    minify_test(".foo { --test: foo ; }", ".foo{--test:foo}");
23337    minify_test(".foo { --test: foo  ; }", ".foo{--test:foo}");
23338    minify_test(".foo { --test:foo; }", ".foo{--test:foo}");
23339    minify_test(".foo { --test:foo ; }", ".foo{--test:foo}");
23340    minify_test(".foo { --test: var(--foo, 20px); }", ".foo{--test:var(--foo,20px)}");
23341    minify_test(
23342      ".foo { transition: var(--foo, 20px),\nvar(--bar, 40px); }",
23343      ".foo{transition:var(--foo,20px), var(--bar,40px)}",
23344    );
23345    minify_test(
23346      ".foo { background: var(--color) var(--image); }",
23347      ".foo{background:var(--color) var(--image)}",
23348    );
23349    minify_test(
23350      ".foo { height: calc(var(--spectrum-global-dimension-size-300) / 2);",
23351      ".foo{height:calc(var(--spectrum-global-dimension-size-300) / 2)}",
23352    );
23353    minify_test(
23354      ".foo { color: var(--color, rgb(255, 255, 0)); }",
23355      ".foo{color:var(--color,#ff0)}",
23356    );
23357    minify_test(
23358      ".foo { color: var(--color, #ffff00); }",
23359      ".foo{color:var(--color,#ff0)}",
23360    );
23361    minify_test(
23362      ".foo { color: var(--color, rgb(var(--red), var(--green), 0)); }",
23363      ".foo{color:var(--color,rgb(var(--red), var(--green), 0))}",
23364    );
23365    minify_test(".foo { --test: .5s; }", ".foo{--test:.5s}");
23366    minify_test(".foo { --theme-sizes-1\\/12: 2 }", ".foo{--theme-sizes-1\\/12:2}");
23367    minify_test(".foo { --test: 0px; }", ".foo{--test:0px}");
23368    test(
23369      ".foo { transform: var(--bar, ) }",
23370      indoc! {r#"
23371      .foo {
23372        transform: var(--bar, );
23373      }
23374      "#},
23375    );
23376    test(
23377      ".foo { transform: env(--bar, ) }",
23378      indoc! {r#"
23379      .foo {
23380        transform: env(--bar, );
23381      }
23382      "#},
23383    );
23384
23385    // Test attr() function with type() syntax - minified
23386    minify_test(
23387      ".foo { background-color: attr(data-color type(<color>)); }",
23388      ".foo{background-color:attr(data-color type(<color>))}",
23389    );
23390    minify_test(
23391      ".foo { width: attr(data-width type(<length>), 100px); }",
23392      ".foo{width:attr(data-width type(<length>), 100px)}",
23393    );
23394
23395    minify_test(".foo { width: attr( data-foo    % ); }", ".foo{width:attr(data-foo %)}");
23396
23397    // <attr-args> = attr( <declaration-value>, <declaration-value>? )
23398    // 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.
23399    // Spec: https://drafts.csswg.org/css-values-5/#funcdef-attr
23400    minify_test(
23401      ".foo { width: attr( data-foo    %, ); }",
23402      ".foo{width:attr(data-foo %,)}",
23403    );
23404
23405    minify_test(
23406      ".foo { width: attr( data-foo    px ); }",
23407      ".foo{width:attr(data-foo px)}",
23408    );
23409
23410    minify_test(
23411      ".foo { width: attr(data-foo    number ); }",
23412      ".foo{width:attr(data-foo number)}",
23413    );
23414
23415    minify_test(
23416      ".foo { width: attr(data-foo    raw-string); }",
23417      ".foo{width:attr(data-foo raw-string)}",
23418    );
23419
23420    // Test attr() function with type() syntax - non-minified (issue with extra spaces)
23421    test(
23422      ".foo { background-color: attr(data-color type(<color>)); }",
23423      ".foo {\n  background-color: attr(data-color type(<color>));\n}\n",
23424    );
23425    test(
23426      ".foo { width: attr(data-width type(<length>), 100px); }",
23427      ".foo {\n  width: attr(data-width type(<length>), 100px);\n}\n",
23428    );
23429
23430    prefix_test(
23431      r#"
23432      .foo {
23433        --custom: lab(40% 56.6 39);
23434      }
23435    "#,
23436      indoc! {r#"
23437      .foo {
23438        --custom: #b32323;
23439      }
23440
23441      @supports (color: lab(0% 0 0)) {
23442        .foo {
23443          --custom: lab(40% 56.6 39);
23444        }
23445      }
23446    "#},
23447      Browsers {
23448        chrome: Some(90 << 16),
23449        ..Browsers::default()
23450      },
23451    );
23452
23453    prefix_test(
23454      r#"
23455      @supports (color: lab(0% 0 0)) {
23456        .foo {
23457          --custom: lab(40% 56.6 39);
23458        }
23459      }
23460    "#,
23461      indoc! {r#"
23462      @supports (color: lab(0% 0 0)) {
23463        .foo {
23464          --custom: lab(40% 56.6 39);
23465        }
23466      }
23467    "#},
23468      Browsers {
23469        chrome: Some(90 << 16),
23470        ..Browsers::default()
23471      },
23472    );
23473
23474    prefix_test(
23475      r#"
23476      .foo {
23477        --custom: lab(40% 56.6 39) !important;
23478      }
23479    "#,
23480      indoc! {r#"
23481      .foo {
23482        --custom: #b32323 !important;
23483      }
23484
23485      @supports (color: lab(0% 0 0)) {
23486        .foo {
23487          --custom: lab(40% 56.6 39) !important;
23488        }
23489      }
23490    "#},
23491      Browsers {
23492        chrome: Some(90 << 16),
23493        ..Browsers::default()
23494      },
23495    );
23496
23497    prefix_test(
23498      r#"
23499      @supports (color: lab(0% 0 0)) {
23500        .foo {
23501          --custom: lab(40% 56.6 39) !important;
23502        }
23503      }
23504    "#,
23505      indoc! {r#"
23506      @supports (color: lab(0% 0 0)) {
23507        .foo {
23508          --custom: lab(40% 56.6 39) !important;
23509        }
23510      }
23511    "#},
23512      Browsers {
23513        chrome: Some(90 << 16),
23514        ..Browsers::default()
23515      },
23516    );
23517
23518    prefix_test(
23519      r#"
23520      .foo {
23521        --custom: lab(40% 56.6 39);
23522      }
23523    "#,
23524      indoc! {r#"
23525      .foo {
23526        --custom: #b32323;
23527      }
23528
23529      @supports (color: color(display-p3 0 0 0)) {
23530        .foo {
23531          --custom: color(display-p3 .643308 .192455 .167712);
23532        }
23533      }
23534
23535      @supports (color: lab(0% 0 0)) {
23536        .foo {
23537          --custom: lab(40% 56.6 39);
23538        }
23539      }
23540    "#},
23541      Browsers {
23542        chrome: Some(90 << 16),
23543        safari: Some(14 << 16),
23544        ..Browsers::default()
23545      },
23546    );
23547
23548    prefix_test(
23549      r#"
23550      @supports (color: color(display-p3 0 0 0)) {
23551        .foo {
23552          --custom: color(display-p3 .643308 .192455 .167712);
23553        }
23554      }
23555
23556      @supports (color: lab(0% 0 0)) {
23557        .foo {
23558          --custom: lab(40% 56.6 39);
23559        }
23560      }
23561    "#,
23562      indoc! {r#"
23563      @supports (color: color(display-p3 0 0 0)) {
23564        .foo {
23565          --custom: color(display-p3 .643308 .192455 .167712);
23566        }
23567      }
23568
23569      @supports (color: lab(0% 0 0)) {
23570        .foo {
23571          --custom: lab(40% 56.6 39);
23572        }
23573      }
23574    "#},
23575      Browsers {
23576        chrome: Some(90 << 16),
23577        safari: Some(14 << 16),
23578        ..Browsers::default()
23579      },
23580    );
23581
23582    prefix_test(
23583      r#"
23584      .foo {
23585        --custom: lab(40% 56.6 39);
23586      }
23587    "#,
23588      indoc! {r#"
23589      .foo {
23590        --custom: color(display-p3 .643308 .192455 .167712);
23591      }
23592
23593      @supports (color: lab(0% 0 0)) {
23594        .foo {
23595          --custom: lab(40% 56.6 39);
23596        }
23597      }
23598    "#},
23599      Browsers {
23600        safari: Some(14 << 16),
23601        ..Browsers::default()
23602      },
23603    );
23604
23605    prefix_test(
23606      r#"
23607      .foo {
23608        --custom: lab(40% 56.6 39);
23609      }
23610    "#,
23611      indoc! {r#"
23612      .foo {
23613        --custom: lab(40% 56.6 39);
23614      }
23615    "#},
23616      Browsers {
23617        safari: Some(15 << 16),
23618        ..Browsers::default()
23619      },
23620    );
23621
23622    prefix_test(
23623      r#"
23624      .foo {
23625        --custom: oklab(59.686% 0.1009 0.1192);
23626      }
23627    "#,
23628      indoc! {r#"
23629      .foo {
23630        --custom: lab(52.2319% 40.1449 59.9171);
23631      }
23632    "#},
23633      Browsers {
23634        safari: Some(15 << 16),
23635        ..Browsers::default()
23636      },
23637    );
23638
23639    prefix_test(
23640      r#"
23641      .foo {
23642        --custom: oklab(59.686% 0.1009 0.1192);
23643      }
23644    "#,
23645      indoc! {r#"
23646      .foo {
23647        --custom: color(display-p3 .724144 .386777 .148795);
23648      }
23649
23650      @supports (color: lab(0% 0 0)) {
23651        .foo {
23652          --custom: lab(52.2319% 40.1449 59.9171);
23653        }
23654      }
23655    "#},
23656      Browsers {
23657        safari: Some(14 << 16),
23658        ..Browsers::default()
23659      },
23660    );
23661
23662    prefix_test(
23663      r#"
23664      .foo {
23665        --custom: oklab(59.686% 0.1009 0.1192);
23666      }
23667    "#,
23668      indoc! {r#"
23669      .foo {
23670        --custom: #c65d07;
23671      }
23672
23673      @supports (color: color(display-p3 0 0 0)) {
23674        .foo {
23675          --custom: color(display-p3 .724144 .386777 .148795);
23676        }
23677      }
23678
23679      @supports (color: lab(0% 0 0)) {
23680        .foo {
23681          --custom: lab(52.2319% 40.1449 59.9171);
23682        }
23683      }
23684    "#},
23685      Browsers {
23686        safari: Some(14 << 16),
23687        chrome: Some(90 << 16),
23688        ..Browsers::default()
23689      },
23690    );
23691
23692    prefix_test(
23693      r#"
23694      .foo {
23695        --foo: oklab(59.686% 0.1009 0.1192);
23696        --bar: lab(40% 56.6 39);
23697      }
23698    "#,
23699      indoc! {r#"
23700      .foo {
23701        --foo: #c65d07;
23702        --bar: #b32323;
23703      }
23704
23705      @supports (color: color(display-p3 0 0 0)) {
23706        .foo {
23707          --foo: color(display-p3 .724144 .386777 .148795);
23708          --bar: color(display-p3 .643308 .192455 .167712);
23709        }
23710      }
23711
23712      @supports (color: lab(0% 0 0)) {
23713        .foo {
23714          --foo: lab(52.2319% 40.1449 59.9171);
23715          --bar: lab(40% 56.6 39);
23716        }
23717      }
23718    "#},
23719      Browsers {
23720        safari: Some(14 << 16),
23721        chrome: Some(90 << 16),
23722        ..Browsers::default()
23723      },
23724    );
23725
23726    prefix_test(
23727      r#"
23728      .foo {
23729        --foo: color(display-p3 0 1 0);
23730      }
23731    "#,
23732      indoc! {r#"
23733      .foo {
23734        --foo: #00f942;
23735      }
23736
23737      @supports (color: color(display-p3 0 0 0)) {
23738        .foo {
23739          --foo: color(display-p3 0 1 0);
23740        }
23741      }
23742    "#},
23743      Browsers {
23744        safari: Some(14 << 16),
23745        chrome: Some(90 << 16),
23746        ..Browsers::default()
23747      },
23748    );
23749
23750    prefix_test(
23751      r#"
23752      @supports (color: color(display-p3 0 0 0)) {
23753        .foo {
23754          --foo: color(display-p3 0 1 0);
23755        }
23756      }
23757    "#,
23758      indoc! {r#"
23759      @supports (color: color(display-p3 0 0 0)) {
23760        .foo {
23761          --foo: color(display-p3 0 1 0);
23762        }
23763      }
23764    "#},
23765      Browsers {
23766        safari: Some(14 << 16),
23767        chrome: Some(90 << 16),
23768        ..Browsers::default()
23769      },
23770    );
23771
23772    prefix_test(
23773      r#"
23774      .foo {
23775        --foo: color(display-p3 0 1 0);
23776      }
23777    "#,
23778      indoc! {r#"
23779      .foo {
23780        --foo: color(display-p3 0 1 0);
23781      }
23782    "#},
23783      Browsers {
23784        safari: Some(14 << 16),
23785        ..Browsers::default()
23786      },
23787    );
23788
23789    prefix_test(
23790      r#"
23791      .foo {
23792        --foo: color(display-p3 0 1 0);
23793      }
23794    "#,
23795      indoc! {r#"
23796      .foo {
23797        --foo: #00f942;
23798      }
23799
23800      @supports (color: color(display-p3 0 0 0)) {
23801        .foo {
23802          --foo: color(display-p3 0 1 0);
23803        }
23804      }
23805    "#},
23806      Browsers {
23807        safari: Some(15 << 16),
23808        chrome: Some(90 << 16),
23809        ..Browsers::default()
23810      },
23811    );
23812
23813    prefix_test(
23814      r#"
23815      .foo {
23816        --foo: color(display-p3 0 1 0);
23817      }
23818    "#,
23819      indoc! {r#"
23820      .foo {
23821        --foo: #00f942;
23822      }
23823
23824      @supports (color: color(display-p3 0 0 0)) {
23825        .foo {
23826          --foo: color(display-p3 0 1 0);
23827        }
23828      }
23829    "#},
23830      Browsers {
23831        chrome: Some(90 << 16),
23832        ..Browsers::default()
23833      },
23834    );
23835
23836    prefix_test(
23837      r#"
23838      .foo {
23839        text-decoration: underline;
23840      }
23841
23842      .foo {
23843        --custom: lab(40% 56.6 39);
23844      }
23845    "#,
23846      indoc! {r#"
23847      .foo {
23848        --custom: #b32323;
23849        text-decoration: underline;
23850      }
23851
23852      @supports (color: lab(0% 0 0)) {
23853        .foo {
23854          --custom: lab(40% 56.6 39);
23855        }
23856      }
23857    "#},
23858      Browsers {
23859        chrome: Some(90 << 16),
23860        ..Browsers::default()
23861      },
23862    );
23863
23864    prefix_test(
23865      r#"
23866      .foo {
23867        --custom: lab(40% 56.6 39);
23868      }
23869
23870      .foo {
23871        text-decoration: underline;
23872      }
23873    "#,
23874      indoc! {r#"
23875      .foo {
23876        --custom: #b32323;
23877      }
23878
23879      @supports (color: lab(0% 0 0)) {
23880        .foo {
23881          --custom: lab(40% 56.6 39);
23882        }
23883      }
23884
23885      .foo {
23886        text-decoration: underline;
23887      }
23888    "#},
23889      Browsers {
23890        chrome: Some(90 << 16),
23891        ..Browsers::default()
23892      },
23893    );
23894
23895    prefix_test(
23896      r#"
23897      @keyframes foo {
23898        from {
23899          --custom: lab(40% 56.6 39);
23900        }
23901
23902        to {
23903          --custom: lch(50.998% 135.363 338);
23904        }
23905      }
23906    "#,
23907      indoc! {r#"
23908      @keyframes foo {
23909        from {
23910          --custom: #b32323;
23911        }
23912
23913        to {
23914          --custom: #ee00be;
23915        }
23916      }
23917
23918      @supports (color: lab(0% 0 0)) {
23919        @keyframes foo {
23920          from {
23921            --custom: lab(40% 56.6 39);
23922          }
23923
23924          to {
23925            --custom: lab(50.998% 125.506 -50.7078);
23926          }
23927        }
23928      }
23929    "#},
23930      Browsers {
23931        chrome: Some(90 << 16),
23932        ..Browsers::default()
23933      },
23934    );
23935
23936    prefix_test(
23937      r#"
23938      @supports (color: lab(0% 0 0)) {
23939        @keyframes foo {
23940          from {
23941            --custom: lab(40% 56.6 39);
23942          }
23943
23944          to {
23945            --custom: lab(50.998% 125.506 -50.7078);
23946          }
23947        }
23948      }
23949    "#,
23950      indoc! {r#"
23951      @supports (color: lab(0% 0 0)) {
23952        @keyframes foo {
23953          from {
23954            --custom: lab(40% 56.6 39);
23955          }
23956
23957          to {
23958            --custom: lab(50.998% 125.506 -50.7078);
23959          }
23960        }
23961      }
23962    "#},
23963      Browsers {
23964        chrome: Some(90 << 16),
23965        ..Browsers::default()
23966      },
23967    );
23968
23969    prefix_test(
23970      r#"
23971      @keyframes foo {
23972        from {
23973          --custom: lab(40% 56.6 39);
23974        }
23975
23976        to {
23977          --custom: lch(50.998% 135.363 338);
23978        }
23979      }
23980    "#,
23981      indoc! {r#"
23982      @keyframes foo {
23983        from {
23984          --custom: #b32323;
23985        }
23986
23987        to {
23988          --custom: #ee00be;
23989        }
23990      }
23991
23992      @supports (color: color(display-p3 0 0 0)) {
23993        @keyframes foo {
23994          from {
23995            --custom: color(display-p3 .643308 .192455 .167712);
23996          }
23997
23998          to {
23999            --custom: color(display-p3 .972962 -.362078 .804206);
24000          }
24001        }
24002      }
24003
24004      @supports (color: lab(0% 0 0)) {
24005        @keyframes foo {
24006          from {
24007            --custom: lab(40% 56.6 39);
24008          }
24009
24010          to {
24011            --custom: lab(50.998% 125.506 -50.7078);
24012          }
24013        }
24014      }
24015    "#},
24016      Browsers {
24017        chrome: Some(90 << 16),
24018        safari: Some(14 << 16),
24019        ..Browsers::default()
24020      },
24021    );
24022
24023    prefix_test(
24024      r#"
24025      @supports (color: color(display-p3 0 0 0)) {
24026        @keyframes foo {
24027          from {
24028            --custom: color(display-p3 .643308 .192455 .167712);
24029          }
24030
24031          to {
24032            --custom: color(display-p3 .972962 -.362078 .804206);
24033          }
24034        }
24035      }
24036
24037      @supports (color: lab(0% 0 0)) {
24038        @keyframes foo {
24039          from {
24040            --custom: lab(40% 56.6 39);
24041          }
24042
24043          to {
24044            --custom: lab(50.998% 125.506 -50.7078);
24045          }
24046        }
24047      }
24048    "#,
24049      indoc! {r#"
24050      @supports (color: color(display-p3 0 0 0)) {
24051        @keyframes foo {
24052          from {
24053            --custom: color(display-p3 .643308 .192455 .167712);
24054          }
24055
24056          to {
24057            --custom: color(display-p3 .972962 -.362078 .804206);
24058          }
24059        }
24060      }
24061
24062      @supports (color: lab(0% 0 0)) {
24063        @keyframes foo {
24064          from {
24065            --custom: lab(40% 56.6 39);
24066          }
24067
24068          to {
24069            --custom: lab(50.998% 125.506 -50.7078);
24070          }
24071        }
24072      }
24073    "#},
24074      Browsers {
24075        chrome: Some(90 << 16),
24076        safari: Some(14 << 16),
24077        ..Browsers::default()
24078      },
24079    );
24080
24081    prefix_test(
24082      r#"
24083      @keyframes foo {
24084        from {
24085          --custom: #ff0;
24086          opacity: 0;
24087        }
24088
24089        to {
24090          --custom: lch(50.998% 135.363 338);
24091          opacity: 1;
24092        }
24093      }
24094    "#,
24095      indoc! {r#"
24096      @keyframes foo {
24097        from {
24098          --custom: #ff0;
24099          opacity: 0;
24100        }
24101
24102        to {
24103          --custom: #ee00be;
24104          opacity: 1;
24105        }
24106      }
24107
24108      @supports (color: lab(0% 0 0)) {
24109        @keyframes foo {
24110          from {
24111            --custom: #ff0;
24112            opacity: 0;
24113          }
24114
24115          to {
24116            --custom: lab(50.998% 125.506 -50.7078);
24117            opacity: 1;
24118          }
24119        }
24120      }
24121    "#},
24122      Browsers {
24123        chrome: Some(90 << 16),
24124        ..Browsers::default()
24125      },
24126    );
24127
24128    prefix_test(
24129      r#"
24130      @keyframes foo {
24131        from {
24132          text-decoration: var(--foo) lab(29.2345% 39.3825 20.0664);
24133        }
24134      }
24135    "#,
24136      indoc! {r#"
24137      @keyframes foo {
24138        from {
24139          text-decoration: var(--foo) #7d2329;
24140        }
24141      }
24142
24143      @supports (color: lab(0% 0 0)) {
24144        @keyframes foo {
24145          from {
24146            text-decoration: var(--foo) lab(29.2345% 39.3825 20.0664);
24147          }
24148        }
24149      }
24150    "#},
24151      Browsers {
24152        chrome: Some(90 << 16),
24153        ..Browsers::default()
24154      },
24155    );
24156  }
24157
24158  #[test]
24159  fn test_charset() {
24160    test(
24161      r#"
24162      @charset "UTF-8";
24163
24164      .foo {
24165        color: red;
24166      }
24167
24168      @charset "UTF-8";
24169
24170      .bar {
24171        color: yellow;
24172      }
24173    "#,
24174      indoc! { r#"
24175      .foo {
24176        color: red;
24177      }
24178
24179      .bar {
24180        color: #ff0;
24181      }
24182    "#},
24183    )
24184  }
24185
24186  #[test]
24187  fn test_style_attr() {
24188    attr_test("color: yellow; flex: 1 1 auto", "color: #ff0; flex: auto", false, None);
24189    attr_test("color: yellow; flex: 1 1 auto", "color:#ff0;flex:auto", true, None);
24190    attr_test(
24191      "border-inline-start: 2px solid red",
24192      "border-inline-start: 2px solid red",
24193      false,
24194      Some(Browsers {
24195        safari: Some(12 << 16),
24196        ..Browsers::default()
24197      }),
24198    );
24199    attr_test(
24200      "color: lab(40% 56.6 39);",
24201      "color:#b32323;color:lab(40% 56.6 39)",
24202      true,
24203      Some(Browsers {
24204        safari: Some(8 << 16),
24205        ..Browsers::default()
24206      }),
24207    );
24208    attr_test(
24209      "--foo: lab(40% 56.6 39);",
24210      "--foo:#b32323",
24211      true,
24212      Some(Browsers {
24213        safari: Some(8 << 16),
24214        ..Browsers::default()
24215      }),
24216    );
24217    attr_test(
24218      "text-decoration: var(--foo) lab(40% 56.6 39);",
24219      "text-decoration:var(--foo) #b32323",
24220      true,
24221      Some(Browsers {
24222        chrome: Some(90 << 16),
24223        ..Browsers::default()
24224      }),
24225    );
24226  }
24227
24228  #[test]
24229  fn test_nesting() {
24230    nesting_test(
24231      r#"
24232        .foo {
24233          color: blue;
24234          & > .bar { color: red; }
24235        }
24236      "#,
24237      indoc! {r#"
24238        .foo {
24239          color: #00f;
24240        }
24241
24242        .foo > .bar {
24243          color: red;
24244        }
24245      "#},
24246    );
24247
24248    nesting_test(
24249      r#"
24250        .foo {
24251          color: blue;
24252          &.bar { color: red; }
24253        }
24254      "#,
24255      indoc! {r#"
24256        .foo {
24257          color: #00f;
24258        }
24259
24260        .foo.bar {
24261          color: red;
24262        }
24263      "#},
24264    );
24265
24266    nesting_test(
24267      r#"
24268        .foo, .bar {
24269          color: blue;
24270          & + .baz, &.qux { color: red; }
24271        }
24272      "#,
24273      indoc! {r#"
24274        .foo, .bar {
24275          color: #00f;
24276        }
24277
24278        :is(.foo, .bar) + .baz, :is(.foo, .bar).qux {
24279          color: red;
24280        }
24281      "#},
24282    );
24283
24284    nesting_test(
24285      r#"
24286        .foo {
24287          color: blue;
24288          & .bar & .baz & .qux { color: red; }
24289        }
24290      "#,
24291      indoc! {r#"
24292        .foo {
24293          color: #00f;
24294        }
24295
24296        .foo .bar .foo .baz .foo .qux {
24297          color: red;
24298        }
24299      "#},
24300    );
24301
24302    nesting_test(
24303      r#"
24304        .foo {
24305          color: blue;
24306          & { padding: 2ch; }
24307        }
24308      "#,
24309      indoc! {r#"
24310        .foo {
24311          color: #00f;
24312        }
24313
24314        .foo {
24315          padding: 2ch;
24316        }
24317      "#},
24318    );
24319
24320    nesting_test(
24321      r#"
24322        .foo {
24323          color: blue;
24324          && { padding: 2ch; }
24325        }
24326      "#,
24327      indoc! {r#"
24328        .foo {
24329          color: #00f;
24330        }
24331
24332        .foo.foo {
24333          padding: 2ch;
24334        }
24335      "#},
24336    );
24337
24338    nesting_test(
24339      r#"
24340        .error, .invalid {
24341          &:hover > .baz { color: red; }
24342        }
24343      "#,
24344      indoc! {r#"
24345        :is(.error, .invalid):hover > .baz {
24346          color: red;
24347        }
24348      "#},
24349    );
24350
24351    nesting_test(
24352      r#"
24353        .foo {
24354          &:is(.bar, &.baz) { color: red; }
24355        }
24356      "#,
24357      indoc! {r#"
24358        .foo:is(.bar, .foo.baz) {
24359          color: red;
24360        }
24361      "#},
24362    );
24363
24364    nesting_test(
24365      r#"
24366        figure {
24367          margin: 0;
24368
24369          & > figcaption {
24370            background: hsl(0 0% 0% / 50%);
24371
24372            & > p {
24373              font-size: .9rem;
24374            }
24375          }
24376        }
24377      "#,
24378      indoc! {r#"
24379        figure {
24380          margin: 0;
24381        }
24382
24383        figure > figcaption {
24384          background: #00000080;
24385        }
24386
24387        figure > figcaption > p {
24388          font-size: .9rem;
24389        }
24390      "#},
24391    );
24392
24393    nesting_test(
24394      r#"
24395        .foo {
24396          display: grid;
24397
24398          @media (orientation: landscape) {
24399            grid-auto-flow: column;
24400          }
24401        }
24402      "#,
24403      indoc! {r#"
24404        .foo {
24405          display: grid;
24406        }
24407
24408        @media (orientation: landscape) {
24409          .foo {
24410            grid-auto-flow: column;
24411          }
24412        }
24413      "#},
24414    );
24415
24416    nesting_test(
24417      r#"
24418        .foo {
24419          display: grid;
24420
24421          @media (orientation: landscape) {
24422            grid-auto-flow: column;
24423
24424            @media (width > 1024px) {
24425              max-inline-size: 1024px;
24426            }
24427          }
24428        }
24429      "#,
24430      indoc! {r#"
24431        .foo {
24432          display: grid;
24433        }
24434
24435        @media (orientation: landscape) {
24436          .foo {
24437            grid-auto-flow: column;
24438          }
24439
24440          @media not (max-width: 1024px) {
24441            .foo {
24442              max-inline-size: 1024px;
24443            }
24444          }
24445        }
24446      "#},
24447    );
24448
24449    nesting_test(
24450      r#"
24451        .foo {
24452          @media (min-width: 640px) {
24453            color: red !important;
24454          }
24455        }
24456      "#,
24457      indoc! {r#"
24458        @media (min-width: 640px) {
24459          .foo {
24460            color: red !important;
24461          }
24462        }
24463      "#},
24464    );
24465
24466    nesting_test(
24467      r#"
24468        .foo {
24469          display: grid;
24470
24471          @supports (foo: bar) {
24472            grid-auto-flow: column;
24473          }
24474        }
24475      "#,
24476      indoc! {r#"
24477        .foo {
24478          display: grid;
24479        }
24480
24481        @supports (foo: bar) {
24482          .foo {
24483            grid-auto-flow: column;
24484          }
24485        }
24486      "#},
24487    );
24488
24489    nesting_test(
24490      r#"
24491        .foo {
24492          display: grid;
24493
24494          @container (min-width: 100px) {
24495            grid-auto-flow: column;
24496          }
24497        }
24498      "#,
24499      indoc! {r#"
24500        .foo {
24501          display: grid;
24502        }
24503
24504        @container (width >= 100px) {
24505          .foo {
24506            grid-auto-flow: column;
24507          }
24508        }
24509      "#},
24510    );
24511
24512    nesting_test(
24513      r#"
24514        .foo {
24515          display: grid;
24516
24517          @layer test {
24518            grid-auto-flow: column;
24519          }
24520        }
24521      "#,
24522      indoc! {r#"
24523        .foo {
24524          display: grid;
24525        }
24526
24527        @layer test {
24528          .foo {
24529            grid-auto-flow: column;
24530          }
24531        }
24532      "#},
24533    );
24534
24535    nesting_test(
24536      r#"
24537        .foo {
24538          display: grid;
24539
24540          @layer {
24541            grid-auto-flow: column;
24542          }
24543        }
24544      "#,
24545      indoc! {r#"
24546        .foo {
24547          display: grid;
24548        }
24549
24550        @layer {
24551          .foo {
24552            grid-auto-flow: column;
24553          }
24554        }
24555      "#},
24556    );
24557
24558    nesting_test(
24559      r#"
24560        @namespace "http://example.com/foo";
24561        @namespace toto "http://toto.example.org";
24562
24563        .foo {
24564          &div {
24565            color: red;
24566          }
24567
24568          &* {
24569            color: green;
24570          }
24571
24572          &|x {
24573            color: red;
24574          }
24575
24576          &*|x {
24577            color: green;
24578          }
24579
24580          &toto|x {
24581            color: red;
24582          }
24583        }
24584      "#,
24585      indoc! {r#"
24586        @namespace "http://example.com/foo";
24587        @namespace toto "http://toto.example.org";
24588
24589        div.foo {
24590          color: red;
24591        }
24592
24593        *.foo {
24594          color: green;
24595        }
24596
24597        |x.foo {
24598          color: red;
24599        }
24600
24601        *|x.foo {
24602          color: green;
24603        }
24604
24605        toto|x.foo {
24606          color: red;
24607        }
24608      "#},
24609    );
24610
24611    nesting_test(
24612      r#"
24613        .foo {
24614          &article > figure {
24615            color: red;
24616          }
24617        }
24618      "#,
24619      indoc! {r#"
24620        article.foo > figure {
24621          color: red;
24622        }
24623      "#},
24624    );
24625
24626    nesting_test(
24627      r#"
24628        div {
24629          &.bar {
24630            background: green;
24631          }
24632        }
24633      "#,
24634      indoc! {r#"
24635        div.bar {
24636          background: green;
24637        }
24638      "#},
24639    );
24640
24641    nesting_test(
24642      r#"
24643        div > .foo {
24644          &span {
24645            background: green;
24646          }
24647        }
24648      "#,
24649      indoc! {r#"
24650        span:is(div > .foo) {
24651          background: green;
24652        }
24653      "#},
24654    );
24655
24656    nesting_test(
24657      r#"
24658        .foo {
24659          & h1 {
24660            background: green;
24661          }
24662        }
24663      "#,
24664      indoc! {r#"
24665        .foo h1 {
24666          background: green;
24667        }
24668      "#},
24669    );
24670
24671    nesting_test(
24672      r#"
24673        .foo .bar {
24674          &h1 {
24675            background: green;
24676          }
24677        }
24678      "#,
24679      indoc! {r#"
24680        h1:is(.foo .bar) {
24681          background: green;
24682        }
24683      "#},
24684    );
24685
24686    nesting_test(
24687      r#"
24688        .foo.bar {
24689          &h1 {
24690            background: green;
24691          }
24692        }
24693      "#,
24694      indoc! {r#"
24695        h1.foo.bar {
24696          background: green;
24697        }
24698      "#},
24699    );
24700
24701    nesting_test(
24702      r#"
24703        .foo .bar {
24704          &h1 .baz {
24705            background: green;
24706          }
24707        }
24708      "#,
24709      indoc! {r#"
24710        h1:is(.foo .bar) .baz {
24711          background: green;
24712        }
24713      "#},
24714    );
24715
24716    nesting_test(
24717      r#"
24718        .foo .bar {
24719          &.baz {
24720            background: green;
24721          }
24722        }
24723      "#,
24724      indoc! {r#"
24725        .foo .bar.baz {
24726          background: green;
24727        }
24728      "#},
24729    );
24730
24731    nesting_test(
24732      r#"
24733        .foo {
24734          color: red;
24735          @nest .parent & {
24736            color: blue;
24737          }
24738        }
24739      "#,
24740      indoc! {r#"
24741        .foo {
24742          color: red;
24743        }
24744
24745        .parent .foo {
24746          color: #00f;
24747        }
24748      "#},
24749    );
24750
24751    nesting_test(
24752      r#"
24753        .foo {
24754          color: red;
24755          @nest :not(&) {
24756            color: blue;
24757          }
24758        }
24759      "#,
24760      indoc! {r#"
24761        .foo {
24762          color: red;
24763        }
24764
24765        :not(.foo) {
24766          color: #00f;
24767        }
24768      "#},
24769    );
24770
24771    nesting_test(
24772      r#"
24773        .foo {
24774          color: blue;
24775          @nest .bar & {
24776            color: red;
24777            &.baz {
24778              color: green;
24779            }
24780          }
24781        }
24782      "#,
24783      indoc! {r#"
24784        .foo {
24785          color: #00f;
24786        }
24787
24788        .bar .foo {
24789          color: red;
24790        }
24791
24792        .bar .foo.baz {
24793          color: green;
24794        }
24795      "#},
24796    );
24797
24798    nesting_test(
24799      r#"
24800        .foo {
24801          @nest :not(&) {
24802            color: red;
24803          }
24804
24805          & h1 {
24806            background: green;
24807          }
24808        }
24809      "#,
24810      indoc! {r#"
24811        :not(.foo) {
24812          color: red;
24813        }
24814
24815        .foo h1 {
24816          background: green;
24817        }
24818      "#},
24819    );
24820
24821    nesting_test(
24822      r#"
24823        .foo {
24824          & h1 {
24825            background: green;
24826          }
24827
24828          @nest :not(&) {
24829            color: red;
24830          }
24831        }
24832      "#,
24833      indoc! {r#"
24834        .foo h1 {
24835          background: green;
24836        }
24837
24838        :not(.foo) {
24839          color: red;
24840        }
24841      "#},
24842    );
24843
24844    nesting_test(
24845      r#"
24846        .foo .bar {
24847          @nest h1& {
24848            background: green;
24849          }
24850        }
24851      "#,
24852      indoc! {r#"
24853        h1:is(.foo .bar) {
24854          background: green;
24855        }
24856      "#},
24857    );
24858
24859    nesting_test(
24860      r#"
24861        @namespace "http://example.com/foo";
24862        @namespace toto "http://toto.example.org";
24863
24864        div {
24865          @nest .foo& {
24866            color: red;
24867          }
24868        }
24869
24870        * {
24871          @nest .foo& {
24872            color: red;
24873          }
24874        }
24875
24876        |x {
24877          @nest .foo& {
24878            color: red;
24879          }
24880        }
24881
24882        *|x {
24883          @nest .foo& {
24884            color: red;
24885          }
24886        }
24887
24888        toto|x {
24889          @nest .foo& {
24890            color: red;
24891          }
24892        }
24893      "#,
24894      indoc! {r#"
24895        @namespace "http://example.com/foo";
24896        @namespace toto "http://toto.example.org";
24897
24898        .foo:is(div) {
24899          color: red;
24900        }
24901
24902        .foo:is(*) {
24903          color: red;
24904        }
24905
24906        .foo:is(|x) {
24907          color: red;
24908        }
24909
24910        .foo:is(*|x) {
24911          color: red;
24912        }
24913
24914        .foo:is(toto|x) {
24915          color: red;
24916        }
24917      "#},
24918    );
24919
24920    nesting_test(
24921      r#"
24922        .foo .bar {
24923          @nest h1 .baz& {
24924            background: green;
24925          }
24926        }
24927      "#,
24928      indoc! {r#"
24929        h1 .baz:is(.foo .bar) {
24930          background: green;
24931        }
24932      "#},
24933    );
24934
24935    nesting_test(
24936      r#"
24937        .foo .bar {
24938          @nest .baz& {
24939            background: green;
24940          }
24941        }
24942      "#,
24943      indoc! {r#"
24944        .baz:is(.foo .bar) {
24945          background: green;
24946        }
24947      "#},
24948    );
24949
24950    nesting_test(
24951      r#"
24952        .foo .bar {
24953          @nest .baz & {
24954            background: green;
24955          }
24956        }
24957      "#,
24958      indoc! {r#"
24959        .baz :is(.foo .bar) {
24960          background: green;
24961        }
24962      "#},
24963    );
24964
24965    nesting_test(
24966      r#"
24967        .foo {
24968          color: red;
24969          @nest & > .bar {
24970            color: blue;
24971          }
24972        }
24973      "#,
24974      indoc! {r#"
24975        .foo {
24976          color: red;
24977        }
24978
24979        .foo > .bar {
24980          color: #00f;
24981        }
24982      "#},
24983    );
24984
24985    nesting_test(
24986      r#"
24987      .foo {
24988        color: red;
24989        .bar {
24990          color: blue;
24991        }
24992      }
24993      "#,
24994      indoc! {r#"
24995      .foo {
24996        color: red;
24997      }
24998
24999      .foo .bar {
25000        color: #00f;
25001      }
25002      "#},
25003    );
25004
25005    nesting_test(
25006      r#"
25007      .foo {
25008        color: red;
25009        .bar & {
25010          color: blue;
25011        }
25012      }
25013      "#,
25014      indoc! {r#"
25015      .foo {
25016        color: red;
25017      }
25018
25019      .bar .foo {
25020        color: #00f;
25021      }
25022      "#},
25023    );
25024
25025    nesting_test(
25026      r#"
25027      .foo {
25028        color: red;
25029        + .bar + & { color: blue; }
25030      }
25031      "#,
25032      indoc! {r#"
25033      .foo {
25034        color: red;
25035      }
25036
25037      .foo + .bar + .foo {
25038        color: #00f;
25039      }
25040      "#},
25041    );
25042
25043    nesting_test(
25044      r#"
25045      .foo {
25046        color: red;
25047        .bar & {
25048          color: blue;
25049        }
25050      }
25051      "#,
25052      indoc! {r#"
25053      .foo {
25054        color: red;
25055      }
25056
25057      .bar .foo {
25058        color: #00f;
25059      }
25060      "#},
25061    );
25062
25063    nesting_test(
25064      r#"
25065        .foo {
25066          color: red;
25067          .parent & {
25068            color: blue;
25069          }
25070        }
25071      "#,
25072      indoc! {r#"
25073        .foo {
25074          color: red;
25075        }
25076
25077        .parent .foo {
25078          color: #00f;
25079        }
25080      "#},
25081    );
25082
25083    nesting_test(
25084      r#"
25085        .foo {
25086          color: red;
25087          :not(&) {
25088            color: blue;
25089          }
25090        }
25091      "#,
25092      indoc! {r#"
25093        .foo {
25094          color: red;
25095        }
25096
25097        :not(.foo) {
25098          color: #00f;
25099        }
25100      "#},
25101    );
25102
25103    nesting_test(
25104      r#"
25105        .foo {
25106          color: blue;
25107          .bar & {
25108            color: red;
25109            &.baz {
25110              color: green;
25111            }
25112          }
25113        }
25114      "#,
25115      indoc! {r#"
25116        .foo {
25117          color: #00f;
25118        }
25119
25120        .bar .foo {
25121          color: red;
25122        }
25123
25124        .bar .foo.baz {
25125          color: green;
25126        }
25127      "#},
25128    );
25129
25130    nesting_test(
25131      r#"
25132        .foo {
25133          :not(&) {
25134            color: red;
25135          }
25136
25137          & h1 {
25138            background: green;
25139          }
25140        }
25141      "#,
25142      indoc! {r#"
25143        :not(.foo) {
25144          color: red;
25145        }
25146
25147        .foo h1 {
25148          background: green;
25149        }
25150      "#},
25151    );
25152
25153    nesting_test(
25154      r#"
25155        .foo {
25156          & h1 {
25157            background: green;
25158          }
25159
25160          :not(&) {
25161            color: red;
25162          }
25163        }
25164      "#,
25165      indoc! {r#"
25166        .foo h1 {
25167          background: green;
25168        }
25169
25170        :not(.foo) {
25171          color: red;
25172        }
25173      "#},
25174    );
25175
25176    nesting_test(
25177      r#"
25178        .foo .bar {
25179          :is(h1)& {
25180            background: green;
25181          }
25182        }
25183      "#,
25184      indoc! {r#"
25185        :is(h1):is(.foo .bar) {
25186          background: green;
25187        }
25188      "#},
25189    );
25190
25191    nesting_test(
25192      r#"
25193        @namespace "http://example.com/foo";
25194        @namespace toto "http://toto.example.org";
25195
25196        div {
25197          .foo& {
25198            color: red;
25199          }
25200        }
25201
25202        * {
25203          .foo& {
25204            color: red;
25205          }
25206        }
25207
25208        |x {
25209          .foo& {
25210            color: red;
25211          }
25212        }
25213
25214        *|x {
25215          .foo& {
25216            color: red;
25217          }
25218        }
25219
25220        toto|x {
25221          .foo& {
25222            color: red;
25223          }
25224        }
25225      "#,
25226      indoc! {r#"
25227        @namespace "http://example.com/foo";
25228        @namespace toto "http://toto.example.org";
25229
25230        .foo:is(div) {
25231          color: red;
25232        }
25233
25234        .foo:is(*) {
25235          color: red;
25236        }
25237
25238        .foo:is(|x) {
25239          color: red;
25240        }
25241
25242        .foo:is(*|x) {
25243          color: red;
25244        }
25245
25246        .foo:is(toto|x) {
25247          color: red;
25248        }
25249      "#},
25250    );
25251
25252    nesting_test(
25253      r#"
25254        .foo .bar {
25255          :is(h1) .baz& {
25256            background: green;
25257          }
25258        }
25259      "#,
25260      indoc! {r#"
25261        :is(h1) .baz:is(.foo .bar) {
25262          background: green;
25263        }
25264      "#},
25265    );
25266
25267    nesting_test(
25268      r#"
25269        .foo .bar {
25270          .baz& {
25271            background: green;
25272          }
25273        }
25274      "#,
25275      indoc! {r#"
25276        .baz:is(.foo .bar) {
25277          background: green;
25278        }
25279      "#},
25280    );
25281
25282    nesting_test(
25283      r#"
25284        .foo .bar {
25285          .baz & {
25286            background: green;
25287          }
25288        }
25289      "#,
25290      indoc! {r#"
25291        .baz :is(.foo .bar) {
25292          background: green;
25293        }
25294      "#},
25295    );
25296
25297    nesting_test(
25298      r#"
25299        .foo {
25300          .bar {
25301            color: blue;
25302          }
25303          color: red;
25304        }
25305      "#,
25306      indoc! {r#"
25307        .foo .bar {
25308          color: #00f;
25309        }
25310
25311        .foo {
25312          color: red;
25313        }
25314      "#},
25315    );
25316
25317    nesting_test(
25318      r#"
25319        article {
25320          color: green;
25321          & { color: blue; }
25322          color: red;
25323        }
25324      "#,
25325      indoc! {r#"
25326        article {
25327          color: green;
25328        }
25329
25330        article {
25331          color: #00f;
25332        }
25333
25334        article {
25335          color: red;
25336        }
25337      "#},
25338    );
25339
25340    nesting_test(
25341      r#"
25342        & .foo {
25343          color: red;
25344        }
25345      "#,
25346      indoc! {r#"
25347        :scope .foo {
25348          color: red;
25349        }
25350      "#},
25351    );
25352
25353    nesting_test(
25354      r#"
25355        &.foo {
25356          color: red;
25357        }
25358      "#,
25359      indoc! {r#"
25360        :scope.foo {
25361          color: red;
25362        }
25363      "#},
25364    );
25365
25366    nesting_test(
25367      r#"
25368        .foo& {
25369          color: red;
25370        }
25371      "#,
25372      indoc! {r#"
25373        .foo:scope {
25374          color: red;
25375        }
25376      "#},
25377    );
25378
25379    nesting_test(
25380      r#"
25381        &html {
25382          color: red;
25383        }
25384      "#,
25385      indoc! {r#"
25386        html:scope {
25387          color: red;
25388        }
25389      "#},
25390    );
25391
25392    nesting_test(
25393      r#"
25394        .foo {
25395          color: blue;
25396          div {
25397            color: red;
25398          }
25399        }
25400      "#,
25401      indoc! {r#"
25402        .foo {
25403          color: #00f;
25404        }
25405
25406        .foo div {
25407          color: red;
25408        }
25409      "#},
25410    );
25411
25412    nesting_test(
25413      r#"
25414        div {
25415          color: blue;
25416
25417          button:focus {
25418            color: red;
25419          }
25420        }
25421      "#,
25422      indoc! {r#"
25423        div {
25424          color: #00f;
25425        }
25426
25427        div button:focus {
25428          color: red;
25429        }
25430      "#},
25431    );
25432    nesting_test(
25433      r#"
25434        div {
25435          color: blue;
25436
25437          --button:focus {
25438            color: red;
25439          }
25440        }
25441      "#,
25442      indoc! {r#"
25443        div {
25444          color: #00f;
25445          --button: focus {
25446                    color: red;
25447                  };
25448        }
25449      "#},
25450    );
25451    nesting_test(
25452      r#"
25453      .foo {
25454        &::before, &::after {
25455          background: blue;
25456          @media screen {
25457            background: orange;
25458          }
25459        }
25460      }
25461      "#,
25462      indoc! {r#"
25463      .foo:before, .foo:after {
25464        background: #00f;
25465      }
25466
25467      @media screen {
25468        .foo:before, .foo:after {
25469          background: orange;
25470        }
25471      }
25472      "#},
25473    );
25474
25475    nesting_test_no_targets(
25476      r#"
25477        .foo {
25478          color: blue;
25479          @nest .bar & {
25480            color: red;
25481            &.baz {
25482              color: green;
25483            }
25484          }
25485        }
25486      "#,
25487      indoc! {r#"
25488        .foo {
25489          color: #00f;
25490
25491          @nest .bar & {
25492            color: red;
25493
25494            &.baz {
25495              color: green;
25496            }
25497          }
25498        }
25499      "#},
25500    );
25501
25502    nesting_test_no_targets(
25503      r#"
25504        .foo {
25505          color: blue;
25506          &div {
25507            color: red;
25508          }
25509
25510          &span {
25511            color: purple;
25512          }
25513        }
25514      "#,
25515      indoc! {r#"
25516        .foo {
25517          color: #00f;
25518
25519          &div {
25520            color: red;
25521          }
25522
25523          &span {
25524            color: purple;
25525          }
25526        }
25527      "#},
25528    );
25529
25530    nesting_test_no_targets(
25531      r#"
25532        .error, .invalid {
25533          &:hover > .baz { color: red; }
25534        }
25535      "#,
25536      indoc! {r#"
25537        .error, .invalid {
25538          &:hover > .baz {
25539            color: red;
25540          }
25541        }
25542      "#},
25543    );
25544
25545    nesting_test_with_targets(
25546      r#"
25547        .foo {
25548          color: blue;
25549          & > .bar { color: red; }
25550        }
25551      "#,
25552      indoc! {r#"
25553        .foo {
25554          color: #00f;
25555        }
25556
25557        .foo > .bar {
25558          color: red;
25559        }
25560      "#},
25561      Targets {
25562        browsers: Some(Browsers {
25563          chrome: Some(112 << 16),
25564          ..Browsers::default()
25565        }),
25566        include: Features::Nesting,
25567        exclude: Features::empty(),
25568      },
25569    );
25570    nesting_test_with_targets(
25571      r#"
25572        .foo {
25573          color: blue;
25574          & > .bar { color: red; }
25575        }
25576      "#,
25577      indoc! {r#"
25578        .foo {
25579          color: #00f;
25580
25581          & > .bar {
25582            color: red;
25583          }
25584        }
25585      "#},
25586      Targets {
25587        browsers: Some(Browsers {
25588          chrome: Some(50 << 16),
25589          ..Browsers::default()
25590        }),
25591        include: Features::empty(),
25592        exclude: Features::Nesting,
25593      },
25594    );
25595
25596    let mut stylesheet = StyleSheet::parse(
25597      r#"
25598      .foo {
25599        color: blue;
25600        .bar {
25601          color: red;
25602        }
25603      }
25604      "#,
25605      ParserOptions::default(),
25606    )
25607    .unwrap();
25608    stylesheet.minify(MinifyOptions::default()).unwrap();
25609    let res = stylesheet
25610      .to_css(PrinterOptions {
25611        minify: true,
25612        ..PrinterOptions::default()
25613      })
25614      .unwrap();
25615    assert_eq!(res.code, ".foo{color:#00f;& .bar{color:red}}");
25616
25617    nesting_test_with_targets(
25618      r#"
25619        .a {
25620          &.b,
25621          &.c {
25622            &.d {
25623              color: red;
25624            }
25625          }
25626        }
25627      "#,
25628      indoc! {r#"
25629        .a.b.d {
25630          color: red;
25631        }
25632
25633        .a.c.d {
25634          color: red;
25635        }
25636      "#},
25637      Targets {
25638        browsers: Some(Browsers {
25639          safari: Some(13 << 16),
25640          ..Browsers::default()
25641        }),
25642        include: Features::Nesting,
25643        exclude: Features::empty(),
25644      },
25645    );
25646
25647    minify_test(
25648      r#"
25649    .foo {
25650      color: red;
25651      .bar {
25652        color: green;
25653      }
25654      color: blue;
25655      .baz {
25656        color: pink;
25657      }
25658    }"#,
25659      ".foo{color:red;& .bar{color:green}color:#00f;& .baz{color:pink}}",
25660    );
25661  }
25662
25663  #[test]
25664  fn test_nesting_error_recovery() {
25665    error_recovery_test(
25666      "
25667    .container {
25668      padding: 3rem;
25669      @media (max-width: --styled-jsx-placeholder-0__) {
25670        .responsive {
25671          color: purple;
25672        }
25673      }
25674    }
25675    ",
25676    );
25677  }
25678
25679  #[test]
25680  fn test_css_variable_error_recovery() {
25681    error_recovery_test("
25682    .container {
25683      --local-var: --styled-jsx-placeholder-0__;
25684      color: var(--text-color);
25685      background: linear-gradient(to right, --styled-jsx-placeholder-1__, --styled-jsx-placeholder-2__);
25686
25687      .item {
25688        transform: translate(calc(var(--x) + --styled-jsx-placeholder-3__px), calc(var(--y) + --styled-jsx-placeholder-4__px));
25689      }
25690
25691      div {
25692        margin: calc(10px + --styled-jsx-placeholder-5__px);
25693      }
25694    }
25695  ");
25696  }
25697
25698  #[test]
25699  fn test_css_modules() {
25700    css_modules_test(
25701      r#"
25702      .foo {
25703        color: red;
25704      }
25705
25706      #id {
25707        animation: 2s test;
25708      }
25709
25710      @keyframes test {
25711        from { color: red }
25712        to { color: yellow }
25713      }
25714
25715      @counter-style circles {
25716        symbols: Ⓐ Ⓑ Ⓒ;
25717      }
25718
25719      ul {
25720        list-style: circles;
25721      }
25722
25723      ol {
25724        list-style-type: none;
25725      }
25726
25727      li {
25728        list-style-type: disc;
25729      }
25730
25731      @keyframes fade {
25732        from { opacity: 0 }
25733        to { opacity: 1 }
25734      }
25735    "#,
25736      indoc! {r#"
25737      .EgL3uq_foo {
25738        color: red;
25739      }
25740
25741      #EgL3uq_id {
25742        animation: 2s EgL3uq_test;
25743      }
25744
25745      @keyframes EgL3uq_test {
25746        from {
25747          color: red;
25748        }
25749
25750        to {
25751          color: #ff0;
25752        }
25753      }
25754
25755      @counter-style EgL3uq_circles {
25756        symbols: Ⓐ Ⓑ Ⓒ;
25757      }
25758
25759      ul {
25760        list-style: EgL3uq_circles;
25761      }
25762
25763      ol {
25764        list-style-type: none;
25765      }
25766
25767      li {
25768        list-style-type: disc;
25769      }
25770
25771      @keyframes EgL3uq_fade {
25772        from {
25773          opacity: 0;
25774        }
25775
25776        to {
25777          opacity: 1;
25778        }
25779      }
25780    "#},
25781      map! {
25782        "foo" => "EgL3uq_foo",
25783        "id" => "EgL3uq_id",
25784        "test" => "EgL3uq_test" referenced: true,
25785        "circles" => "EgL3uq_circles" referenced: true,
25786        "fade" => "EgL3uq_fade"
25787      },
25788      HashMap::new(),
25789      Default::default(),
25790      false,
25791    );
25792
25793    css_modules_test(
25794      r#"
25795      .foo {
25796        color: red;
25797      }
25798
25799      #id {
25800        animation: 2s test;
25801      }
25802
25803      @keyframes test {
25804        from { color: red }
25805        to { color: yellow }
25806      }
25807    "#,
25808      indoc! {r#"
25809      .EgL3uq_foo {
25810        color: red;
25811      }
25812
25813      #EgL3uq_id {
25814        animation: 2s test;
25815      }
25816
25817      @keyframes test {
25818        from {
25819          color: red;
25820        }
25821
25822        to {
25823          color: #ff0;
25824        }
25825      }
25826    "#},
25827      map! {
25828        "foo" => "EgL3uq_foo",
25829        "id" => "EgL3uq_id"
25830      },
25831      HashMap::new(),
25832      crate::css_modules::Config {
25833        animation: false,
25834        // custom_idents: false,
25835        ..Default::default()
25836      },
25837      false,
25838    );
25839
25840    css_modules_test(
25841      r#"
25842      @counter-style circles {
25843        symbols: Ⓐ Ⓑ Ⓒ;
25844      }
25845
25846      ul {
25847        list-style: circles;
25848      }
25849
25850      ol {
25851        list-style-type: none;
25852      }
25853
25854      li {
25855        list-style-type: disc;
25856      }
25857    "#,
25858      indoc! {r#"
25859      @counter-style circles {
25860        symbols: Ⓐ Ⓑ Ⓒ;
25861      }
25862
25863      ul {
25864        list-style: circles;
25865      }
25866
25867      ol {
25868        list-style-type: none;
25869      }
25870
25871      li {
25872        list-style-type: disc;
25873      }
25874    "#},
25875      map! {
25876        "circles" => "EgL3uq_circles" referenced: true
25877      },
25878      HashMap::new(),
25879      crate::css_modules::Config {
25880        custom_idents: false,
25881        ..Default::default()
25882      },
25883      false,
25884    );
25885
25886    css_modules_test(
25887      r#"
25888      body {
25889        grid: [header-top] "a a a" [header-bottom]
25890              [main-top] "b b b" 1fr [main-bottom]
25891              / auto 1fr auto;
25892      }
25893
25894      header {
25895        grid-area: a;
25896      }
25897
25898      main {
25899        grid-row: main-top / main-bottom;
25900      }
25901    "#,
25902      indoc! {r#"
25903      body {
25904        grid: [EgL3uq_header-top] "EgL3uq_a EgL3uq_a EgL3uq_a" [EgL3uq_header-bottom]
25905              [EgL3uq_main-top] "EgL3uq_b EgL3uq_b EgL3uq_b" 1fr [EgL3uq_main-bottom]
25906              / auto 1fr auto;
25907      }
25908
25909      header {
25910        grid-area: EgL3uq_a;
25911      }
25912
25913      main {
25914        grid-row: EgL3uq_main-top / EgL3uq_main-bottom;
25915      }
25916    "#},
25917      map! {
25918        "header-top" => "EgL3uq_header-top",
25919        "header-bottom" => "EgL3uq_header-bottom",
25920        "main-top" => "EgL3uq_main-top",
25921        "main-bottom" => "EgL3uq_main-bottom",
25922        "a" => "EgL3uq_a",
25923        "b" => "EgL3uq_b"
25924      },
25925      HashMap::new(),
25926      Default::default(),
25927      false,
25928    );
25929
25930    css_modules_test(
25931      r#"
25932        .grid {
25933          grid-template-areas: "foo";
25934        }
25935
25936        .foo {
25937          grid-area: foo;
25938        }
25939
25940        .bar {
25941          grid-column-start: foo-start;
25942        }
25943      "#,
25944      indoc! {r#"
25945        .EgL3uq_grid {
25946          grid-template-areas: "EgL3uq_foo";
25947        }
25948
25949        .EgL3uq_foo {
25950          grid-area: EgL3uq_foo;
25951        }
25952
25953        .EgL3uq_bar {
25954          grid-column-start: EgL3uq_foo-start;
25955        }
25956      "#},
25957      map! {
25958        "foo" => "EgL3uq_foo",
25959        "foo-start" => "EgL3uq_foo-start",
25960        "grid" => "EgL3uq_grid",
25961        "bar" => "EgL3uq_bar"
25962      },
25963      HashMap::new(),
25964      Default::default(),
25965      false,
25966    );
25967
25968    css_modules_test(
25969      r#"
25970        .grid {
25971          grid-template-areas: "foo";
25972        }
25973
25974        .foo {
25975          grid-area: foo;
25976        }
25977
25978        .bar {
25979          grid-column-start: foo-start;
25980        }
25981      "#,
25982      indoc! {r#"
25983        .EgL3uq_grid {
25984          grid-template-areas: "foo";
25985        }
25986
25987        .EgL3uq_foo {
25988          grid-area: foo;
25989        }
25990
25991        .EgL3uq_bar {
25992          grid-column-start: foo-start;
25993        }
25994      "#},
25995      map! {
25996        "foo" => "EgL3uq_foo",
25997        "grid" => "EgL3uq_grid",
25998        "bar" => "EgL3uq_bar"
25999      },
26000      HashMap::new(),
26001      crate::css_modules::Config {
26002        grid: false,
26003        ..Default::default()
26004      },
26005      false,
26006    );
26007
26008    css_modules_test(
26009      r#"
26010      test {
26011        transition-property: opacity;
26012      }
26013    "#,
26014      indoc! {r#"
26015      test {
26016        transition-property: opacity;
26017      }
26018    "#},
26019      map! {},
26020      HashMap::new(),
26021      Default::default(),
26022      false,
26023    );
26024
26025    css_modules_test(
26026      r#"
26027      :global(.foo) {
26028        color: red;
26029      }
26030
26031      :local(.bar) {
26032        color: yellow;
26033      }
26034
26035      .bar :global(.baz) {
26036        color: purple;
26037      }
26038    "#,
26039      indoc! {r#"
26040      .foo {
26041        color: red;
26042      }
26043
26044      .EgL3uq_bar {
26045        color: #ff0;
26046      }
26047
26048      .EgL3uq_bar .baz {
26049        color: purple;
26050      }
26051    "#},
26052      map! {
26053        "bar" => "EgL3uq_bar"
26054      },
26055      HashMap::new(),
26056      Default::default(),
26057      false,
26058    );
26059
26060    // :global(:local(.hi)) {
26061    //   color: green;
26062    // }
26063
26064    css_modules_test(
26065      r#"
26066      .test {
26067        composes: foo;
26068        background: white;
26069      }
26070
26071      .foo {
26072        color: red;
26073      }
26074    "#,
26075      indoc! {r#"
26076      .EgL3uq_test {
26077        background: #fff;
26078      }
26079
26080      .EgL3uq_foo {
26081        color: red;
26082      }
26083    "#},
26084      map! {
26085        "test" => "EgL3uq_test" "EgL3uq_foo",
26086        "foo" => "EgL3uq_foo"
26087      },
26088      HashMap::new(),
26089      Default::default(),
26090      false,
26091    );
26092
26093    css_modules_test(
26094      r#"
26095      .a, .b {
26096        composes: foo;
26097        background: white;
26098      }
26099
26100      .foo {
26101        color: red;
26102      }
26103    "#,
26104      indoc! {r#"
26105      .EgL3uq_a, .EgL3uq_b {
26106        background: #fff;
26107      }
26108
26109      .EgL3uq_foo {
26110        color: red;
26111      }
26112    "#},
26113      map! {
26114        "a" => "EgL3uq_a" "EgL3uq_foo",
26115        "b" => "EgL3uq_b" "EgL3uq_foo",
26116        "foo" => "EgL3uq_foo"
26117      },
26118      HashMap::new(),
26119      Default::default(),
26120      false,
26121    );
26122
26123    css_modules_test(
26124      r#"
26125      .test {
26126        composes: foo bar;
26127        background: white;
26128      }
26129
26130      .foo {
26131        color: red;
26132      }
26133
26134      .bar {
26135        color: yellow;
26136      }
26137    "#,
26138      indoc! {r#"
26139      .EgL3uq_test {
26140        background: #fff;
26141      }
26142
26143      .EgL3uq_foo {
26144        color: red;
26145      }
26146
26147      .EgL3uq_bar {
26148        color: #ff0;
26149      }
26150    "#},
26151      map! {
26152        "test" => "EgL3uq_test" "EgL3uq_foo" "EgL3uq_bar",
26153        "foo" => "EgL3uq_foo",
26154        "bar" => "EgL3uq_bar"
26155      },
26156      HashMap::new(),
26157      Default::default(),
26158      false,
26159    );
26160
26161    css_modules_test(
26162      r#"
26163      .test {
26164        composes: foo from global;
26165        background: white;
26166      }
26167    "#,
26168      indoc! {r#"
26169      .EgL3uq_test {
26170        background: #fff;
26171      }
26172    "#},
26173      map! {
26174        "test" => "EgL3uq_test" "foo" global: true
26175      },
26176      HashMap::new(),
26177      Default::default(),
26178      false,
26179    );
26180
26181    css_modules_test(
26182      r#"
26183      .test {
26184        composes: foo bar from global;
26185        background: white;
26186      }
26187    "#,
26188      indoc! {r#"
26189      .EgL3uq_test {
26190        background: #fff;
26191      }
26192    "#},
26193      map! {
26194        "test" => "EgL3uq_test" "foo" global: true "bar" global: true
26195      },
26196      HashMap::new(),
26197      Default::default(),
26198      false,
26199    );
26200
26201    css_modules_test(
26202      r#"
26203      .test {
26204        composes: foo from "foo.css";
26205        background: white;
26206      }
26207    "#,
26208      indoc! {r#"
26209      .EgL3uq_test {
26210        background: #fff;
26211      }
26212    "#},
26213      map! {
26214        "test" => "EgL3uq_test" "foo" from "foo.css"
26215      },
26216      HashMap::new(),
26217      Default::default(),
26218      false,
26219    );
26220
26221    css_modules_test(
26222      r#"
26223      .test {
26224        composes: foo bar from "foo.css";
26225        background: white;
26226      }
26227    "#,
26228      indoc! {r#"
26229      .EgL3uq_test {
26230        background: #fff;
26231      }
26232    "#},
26233      map! {
26234        "test" => "EgL3uq_test" "foo" from "foo.css" "bar" from "foo.css"
26235      },
26236      HashMap::new(),
26237      Default::default(),
26238      false,
26239    );
26240
26241    css_modules_test(
26242      r#"
26243      .test {
26244        composes: foo;
26245        composes: foo from "foo.css";
26246        composes: bar from "bar.css";
26247        background: white;
26248      }
26249
26250      .foo {
26251        color: red;
26252      }
26253    "#,
26254      indoc! {r#"
26255      .EgL3uq_test {
26256        background: #fff;
26257      }
26258
26259      .EgL3uq_foo {
26260        color: red;
26261      }
26262    "#},
26263      map! {
26264        "test" => "EgL3uq_test" "EgL3uq_foo" "foo" from "foo.css" "bar" from "bar.css",
26265        "foo" => "EgL3uq_foo"
26266      },
26267      HashMap::new(),
26268      Default::default(),
26269      false,
26270    );
26271
26272    css_modules_test(
26273      r#"
26274      .foo {
26275        color: red;
26276      }
26277    "#,
26278      indoc! {r#"
26279      .test-EgL3uq-foo {
26280        color: red;
26281      }
26282    "#},
26283      map! {
26284        "foo" => "test-EgL3uq-foo"
26285      },
26286      HashMap::new(),
26287      crate::css_modules::Config {
26288        pattern: crate::css_modules::Pattern::parse("test-[hash]-[local]").unwrap(),
26289        ..Default::default()
26290      },
26291      false,
26292    );
26293
26294    let stylesheet = StyleSheet::parse(
26295      r#"
26296        .grid {
26297          grid-template-areas: "foo";
26298        }
26299
26300        .foo {
26301          grid-area: foo;
26302        }
26303
26304        .bar {
26305          grid-column-start: foo-start;
26306        }
26307      "#,
26308      ParserOptions {
26309        css_modules: Some(crate::css_modules::Config {
26310          pattern: crate::css_modules::Pattern::parse("test-[local]-[hash]").unwrap(),
26311          ..Default::default()
26312        }),
26313        ..ParserOptions::default()
26314      },
26315    )
26316    .unwrap();
26317    if let Err(err) = stylesheet.to_css(PrinterOptions::default()) {
26318      assert_eq!(err.kind, PrinterErrorKind::InvalidCssModulesPatternInGrid);
26319    } else {
26320      unreachable!()
26321    }
26322
26323    css_modules_test(
26324      r#"
26325      @property --foo {
26326        syntax: '<color>';
26327        inherits: false;
26328        initial-value: yellow;
26329      }
26330
26331      .foo {
26332        --foo: red;
26333        color: var(--foo);
26334      }
26335    "#,
26336      indoc! {r#"
26337      @property --foo {
26338        syntax: "<color>";
26339        inherits: false;
26340        initial-value: #ff0;
26341      }
26342
26343      .EgL3uq_foo {
26344        --foo: red;
26345        color: var(--foo);
26346      }
26347    "#},
26348      map! {
26349        "foo" => "EgL3uq_foo"
26350      },
26351      HashMap::new(),
26352      Default::default(),
26353      false,
26354    );
26355
26356    css_modules_test(
26357      r#"
26358      @property --foo {
26359        syntax: '<color>';
26360        inherits: false;
26361        initial-value: yellow;
26362      }
26363
26364      @font-palette-values --Cooler {
26365        font-family: Bixa;
26366        base-palette: 1;
26367        override-colors: 1 #7EB7E4;
26368      }
26369
26370      .foo {
26371        --foo: red;
26372        --bar: green;
26373        color: var(--foo);
26374        font-palette: --Cooler;
26375      }
26376
26377      .bar {
26378        color: var(--color from "./b.css");
26379      }
26380    "#,
26381      indoc! {r#"
26382      @property --EgL3uq_foo {
26383        syntax: "<color>";
26384        inherits: false;
26385        initial-value: #ff0;
26386      }
26387
26388      @font-palette-values --EgL3uq_Cooler {
26389        font-family: Bixa;
26390        base-palette: 1;
26391        override-colors: 1 #7eb7e4;
26392      }
26393
26394      .EgL3uq_foo {
26395        --EgL3uq_foo: red;
26396        --EgL3uq_bar: green;
26397        color: var(--EgL3uq_foo);
26398        font-palette: --EgL3uq_Cooler;
26399      }
26400
26401      .EgL3uq_bar {
26402        color: var(--ma1CsG);
26403      }
26404    "#},
26405      map! {
26406        "foo" => "EgL3uq_foo",
26407        "--foo" => "--EgL3uq_foo" referenced: true,
26408        "--bar" => "--EgL3uq_bar",
26409        "bar" => "EgL3uq_bar",
26410        "--Cooler" => "--EgL3uq_Cooler" referenced: true
26411      },
26412      HashMap::from([(
26413        "--ma1CsG".into(),
26414        CssModuleReference::Dependency {
26415          name: "--color".into(),
26416          specifier: "./b.css".into(),
26417        },
26418      )]),
26419      crate::css_modules::Config {
26420        dashed_idents: true,
26421        ..Default::default()
26422      },
26423      false,
26424    );
26425
26426    css_modules_test(
26427      r#"
26428      .test {
26429        animation: rotate var(--duration) linear infinite;
26430      }
26431    "#,
26432      indoc! {r#"
26433      .EgL3uq_test {
26434        animation: EgL3uq_rotate var(--duration) linear infinite;
26435      }
26436    "#},
26437      map! {
26438        "test" => "EgL3uq_test",
26439        "rotate" => "EgL3uq_rotate" referenced: true
26440      },
26441      HashMap::new(),
26442      Default::default(),
26443      false,
26444    );
26445    css_modules_test(
26446      r#"
26447      .test {
26448        animation: none var(--duration);
26449      }
26450    "#,
26451      indoc! {r#"
26452      .EgL3uq_test {
26453        animation: none var(--duration);
26454      }
26455    "#},
26456      map! {
26457        "test" => "EgL3uq_test"
26458      },
26459      HashMap::new(),
26460      Default::default(),
26461      false,
26462    );
26463    css_modules_test(
26464      r#"
26465      .test {
26466        animation: var(--animation);
26467      }
26468    "#,
26469      indoc! {r#"
26470      .EgL3uq_test {
26471        animation: var(--animation);
26472      }
26473    "#},
26474      map! {
26475        "test" => "EgL3uq_test"
26476      },
26477      HashMap::new(),
26478      Default::default(),
26479      false,
26480    );
26481    css_modules_test(
26482      r#"
26483      .test {
26484        animation: rotate var(--duration);
26485      }
26486    "#,
26487      indoc! {r#"
26488      .EgL3uq_test {
26489        animation: rotate var(--duration);
26490      }
26491    "#},
26492      map! {
26493        "test" => "EgL3uq_test"
26494      },
26495      HashMap::new(),
26496      crate::css_modules::Config {
26497        animation: false,
26498        ..Default::default()
26499      },
26500      false,
26501    );
26502    css_modules_test(
26503      r#"
26504      .test {
26505        animation: "rotate" var(--duration);
26506      }
26507    "#,
26508      indoc! {r#"
26509      .EgL3uq_test {
26510        animation: EgL3uq_rotate var(--duration);
26511      }
26512    "#},
26513      map! {
26514        "test" => "EgL3uq_test",
26515        "rotate" => "EgL3uq_rotate" referenced: true
26516      },
26517      HashMap::new(),
26518      crate::css_modules::Config { ..Default::default() },
26519      false,
26520    );
26521
26522    css_modules_test(
26523      r#"
26524      .test {
26525        composes: foo bar from "foo.css";
26526        background: white;
26527      }
26528    "#,
26529      indoc! {r#"
26530      ._5h2kwG-test {
26531        background: #fff;
26532      }
26533    "#},
26534      map! {
26535        "test" => "_5h2kwG-test" "foo" from "foo.css" "bar" from "foo.css"
26536      },
26537      HashMap::new(),
26538      crate::css_modules::Config {
26539        pattern: crate::css_modules::Pattern::parse("[content-hash]-[local]").unwrap(),
26540        ..Default::default()
26541      },
26542      false,
26543    );
26544
26545    css_modules_test(
26546      r#"
26547      .box2 {
26548        @container main (width >= 0) {
26549          background-color: #90ee90;
26550        }
26551      }
26552    "#,
26553      indoc! {r#"
26554      .EgL3uq_box2 {
26555        @container EgL3uq_main (width >= 0) {
26556          background-color: #90ee90;
26557        }
26558      }
26559    "#},
26560      map! {
26561        "main" => "EgL3uq_main",
26562        "box2" => "EgL3uq_box2"
26563      },
26564      HashMap::new(),
26565      crate::css_modules::Config { ..Default::default() },
26566      false,
26567    );
26568
26569    css_modules_test(
26570      r#"
26571      .box2 {
26572        @container main (width >= 0) {
26573          background-color: #90ee90;
26574        }
26575      }
26576    "#,
26577      indoc! {r#"
26578      .EgL3uq_box2 {
26579        @container main (width >= 0) {
26580          background-color: #90ee90;
26581        }
26582      }
26583    "#},
26584      map! {
26585        "box2" => "EgL3uq_box2"
26586      },
26587      HashMap::new(),
26588      crate::css_modules::Config {
26589        container: false,
26590        ..Default::default()
26591      },
26592      false,
26593    );
26594
26595    css_modules_test(
26596      ".foo { view-transition-name: bar }",
26597      ".EgL3uq_foo{view-transition-name:EgL3uq_bar}",
26598      map! {
26599        "foo" => "EgL3uq_foo",
26600        "bar" => "EgL3uq_bar"
26601      },
26602      HashMap::new(),
26603      Default::default(),
26604      true,
26605    );
26606    css_modules_test(
26607      ".foo { view-transition-name: none }",
26608      ".EgL3uq_foo{view-transition-name:none}",
26609      map! {
26610        "foo" => "EgL3uq_foo"
26611      },
26612      HashMap::new(),
26613      Default::default(),
26614      true,
26615    );
26616    css_modules_test(
26617      ".foo { view-transition-name: auto }",
26618      ".EgL3uq_foo{view-transition-name:auto}",
26619      map! {
26620        "foo" => "EgL3uq_foo"
26621      },
26622      HashMap::new(),
26623      Default::default(),
26624      true,
26625    );
26626
26627    css_modules_test(
26628      ".foo { view-transition-class: bar baz qux }",
26629      ".EgL3uq_foo{view-transition-class:EgL3uq_bar EgL3uq_baz EgL3uq_qux}",
26630      map! {
26631        "foo" => "EgL3uq_foo",
26632        "bar" => "EgL3uq_bar",
26633        "baz" => "EgL3uq_baz",
26634        "qux" => "EgL3uq_qux"
26635      },
26636      HashMap::new(),
26637      Default::default(),
26638      true,
26639    );
26640
26641    css_modules_test(
26642      ".foo { view-transition-group: contain }",
26643      ".EgL3uq_foo{view-transition-group:contain}",
26644      map! {
26645        "foo" => "EgL3uq_foo"
26646      },
26647      HashMap::new(),
26648      Default::default(),
26649      true,
26650    );
26651    css_modules_test(
26652      ".foo { view-transition-group: bar }",
26653      ".EgL3uq_foo{view-transition-group:EgL3uq_bar}",
26654      map! {
26655        "foo" => "EgL3uq_foo",
26656        "bar" => "EgL3uq_bar"
26657      },
26658      HashMap::new(),
26659      Default::default(),
26660      true,
26661    );
26662
26663    css_modules_test(
26664      "@view-transition { types: foo bar baz }",
26665      "@view-transition{types:EgL3uq_foo EgL3uq_bar EgL3uq_baz}",
26666      map! {
26667        "foo" => "EgL3uq_foo",
26668        "bar" => "EgL3uq_bar",
26669        "baz" => "EgL3uq_baz"
26670      },
26671      HashMap::new(),
26672      Default::default(),
26673      true,
26674    );
26675
26676    css_modules_test(
26677      ":root:active-view-transition-type(foo, bar) { color: red }",
26678      ":root:active-view-transition-type(EgL3uq_foo,EgL3uq_bar){color:red}",
26679      map! {
26680        "foo" => "EgL3uq_foo",
26681        "bar" => "EgL3uq_bar"
26682      },
26683      HashMap::new(),
26684      Default::default(),
26685      true,
26686    );
26687
26688    for name in &[
26689      "view-transition-group",
26690      "view-transition-image-pair",
26691      "view-transition-new",
26692      "view-transition-old",
26693    ] {
26694      css_modules_test(
26695        &format!(":root::{}(foo) {{position: fixed}}", name),
26696        &format!(":root::{}(EgL3uq_foo){{position:fixed}}", name),
26697        map! {
26698          "foo" => "EgL3uq_foo"
26699        },
26700        HashMap::new(),
26701        Default::default(),
26702        true,
26703      );
26704      css_modules_test(
26705        &format!(":root::{}(.bar) {{position: fixed}}", name),
26706        &format!(":root::{}(.EgL3uq_bar){{position:fixed}}", name),
26707        map! {
26708          "bar" => "EgL3uq_bar"
26709        },
26710        HashMap::new(),
26711        Default::default(),
26712        true,
26713      );
26714      css_modules_test(
26715        &format!(":root::{}(foo.bar.baz) {{position: fixed}}", name),
26716        &format!(":root::{}(EgL3uq_foo.EgL3uq_bar.EgL3uq_baz){{position:fixed}}", name),
26717        map! {
26718          "foo" => "EgL3uq_foo",
26719          "bar" => "EgL3uq_bar",
26720          "baz" => "EgL3uq_baz"
26721        },
26722        HashMap::new(),
26723        Default::default(),
26724        true,
26725      );
26726
26727      css_modules_test(
26728        ":nth-child(1 of .foo) {width: 20px}",
26729        ":nth-child(1 of .EgL3uq_foo){width:20px}",
26730        map! {
26731          "foo" => "EgL3uq_foo"
26732        },
26733        HashMap::new(),
26734        Default::default(),
26735        true,
26736      );
26737      css_modules_test(
26738        ":nth-last-child(1 of .foo) {width: 20px}",
26739        ":nth-last-child(1 of .EgL3uq_foo){width:20px}",
26740        map! {
26741          "foo" => "EgL3uq_foo"
26742        },
26743        HashMap::new(),
26744        Default::default(),
26745        true,
26746      );
26747    }
26748
26749    // Stable hashes between project roots.
26750    fn test_project_root(project_root: &str, filename: &str, hash: &str) {
26751      let stylesheet = StyleSheet::parse(
26752        r#"
26753        .foo {
26754          background: red;
26755        }
26756        "#,
26757        ParserOptions {
26758          filename: filename.into(),
26759          css_modules: Some(Default::default()),
26760          ..ParserOptions::default()
26761        },
26762      )
26763      .unwrap();
26764      let res = stylesheet
26765        .to_css(PrinterOptions {
26766          project_root: Some(project_root),
26767          ..PrinterOptions::default()
26768        })
26769        .unwrap();
26770      assert_eq!(
26771        res.code,
26772        format!(
26773          indoc! {r#"
26774      .{}_foo {{
26775        background: red;
26776      }}
26777      "#},
26778          hash
26779        )
26780      );
26781    }
26782
26783    test_project_root("/foo/bar", "/foo/bar/test.css", "EgL3uq");
26784    test_project_root("/foo", "/foo/test.css", "EgL3uq");
26785    test_project_root("/foo/bar", "/foo/bar/baz/test.css", "xLEkNW");
26786    test_project_root("/foo", "/foo/baz/test.css", "xLEkNW");
26787
26788    let mut stylesheet = StyleSheet::parse(
26789      r#"
26790      .foo {
26791        color: red;
26792        .bar {
26793          color: green;
26794        }
26795        composes: test from "foo.css";
26796      }
26797      "#,
26798      ParserOptions {
26799        filename: "test.css".into(),
26800        css_modules: Some(Default::default()),
26801        ..ParserOptions::default()
26802      },
26803    )
26804    .unwrap();
26805    stylesheet.minify(MinifyOptions::default()).unwrap();
26806    let res = stylesheet
26807      .to_css(PrinterOptions {
26808        targets: Browsers {
26809          chrome: Some(95 << 16),
26810          ..Browsers::default()
26811        }
26812        .into(),
26813        ..Default::default()
26814      })
26815      .unwrap();
26816    assert_eq!(
26817      res.code,
26818      indoc! {r#"
26819    .EgL3uq_foo {
26820      color: red;
26821    }
26822
26823    .EgL3uq_foo .EgL3uq_bar {
26824      color: green;
26825    }
26826
26827
26828    "#}
26829    );
26830    assert_eq!(
26831      res.exports.unwrap(),
26832      map! {
26833        "foo" => "EgL3uq_foo" "test" from "foo.css",
26834        "bar" => "EgL3uq_bar"
26835      }
26836    );
26837  }
26838
26839  #[test]
26840  fn test_pseudo_replacement() {
26841    let source = r#"
26842      .foo:hover {
26843        color: red;
26844      }
26845
26846      .foo:active {
26847        color: yellow;
26848      }
26849
26850      .foo:focus-visible {
26851        color: purple;
26852      }
26853    "#;
26854
26855    let expected = indoc! { r#"
26856      .foo.is-hovered {
26857        color: red;
26858      }
26859
26860      .foo.is-active {
26861        color: #ff0;
26862      }
26863
26864      .foo.focus-visible {
26865        color: purple;
26866      }
26867    "#};
26868
26869    let stylesheet = StyleSheet::parse(&source, ParserOptions::default()).unwrap();
26870    let res = stylesheet
26871      .to_css(PrinterOptions {
26872        pseudo_classes: Some(PseudoClasses {
26873          hover: Some("is-hovered"),
26874          active: Some("is-active"),
26875          focus_visible: Some("focus-visible"),
26876          ..PseudoClasses::default()
26877        }),
26878        ..PrinterOptions::default()
26879      })
26880      .unwrap();
26881    assert_eq!(res.code, expected);
26882
26883    let source = r#"
26884      .foo:hover {
26885        color: red;
26886      }
26887    "#;
26888
26889    let expected = indoc! { r#"
26890      .EgL3uq_foo.EgL3uq_is-hovered {
26891        color: red;
26892      }
26893    "#};
26894
26895    let stylesheet = StyleSheet::parse(
26896      &source,
26897      ParserOptions {
26898        filename: "test.css".into(),
26899        css_modules: Some(Default::default()),
26900        ..ParserOptions::default()
26901      },
26902    )
26903    .unwrap();
26904    let res = stylesheet
26905      .to_css(PrinterOptions {
26906        pseudo_classes: Some(PseudoClasses {
26907          hover: Some("is-hovered"),
26908          ..PseudoClasses::default()
26909        }),
26910        ..PrinterOptions::default()
26911      })
26912      .unwrap();
26913    assert_eq!(res.code, expected);
26914  }
26915
26916  #[test]
26917  fn test_unused_symbols() {
26918    let source = r#"
26919      .foo {
26920        color: red;
26921      }
26922
26923      .bar {
26924        color: green;
26925      }
26926
26927      .bar:hover {
26928        color: purple;
26929      }
26930
26931      .bar .baz {
26932        background: red;
26933      }
26934
26935      .baz:is(.bar) {
26936        background: green;
26937      }
26938
26939      #id {
26940        animation: 2s test;
26941      }
26942
26943      #other_id {
26944        color: red;
26945      }
26946
26947      @keyframes test {
26948        from { color: red }
26949        to { color: yellow }
26950      }
26951
26952      @counter-style circles {
26953        symbols: Ⓐ Ⓑ Ⓒ;
26954      }
26955
26956      @keyframes fade {
26957        from { opacity: 0 }
26958        to { opacity: 1 }
26959      }
26960    "#;
26961
26962    let expected = indoc! {r#"
26963      .foo {
26964        color: red;
26965      }
26966
26967      #id {
26968        animation: 2s test;
26969      }
26970
26971      @keyframes test {
26972        from {
26973          color: red;
26974        }
26975
26976        to {
26977          color: #ff0;
26978        }
26979      }
26980    "#};
26981
26982    let mut stylesheet = StyleSheet::parse(&source, ParserOptions::default()).unwrap();
26983    stylesheet
26984      .minify(MinifyOptions {
26985        unused_symbols: vec!["bar", "other_id", "fade", "circles"]
26986          .iter()
26987          .map(|s| String::from(*s))
26988          .collect(),
26989        ..MinifyOptions::default()
26990      })
26991      .unwrap();
26992    let res = stylesheet.to_css(PrinterOptions::default()).unwrap();
26993    assert_eq!(res.code, expected);
26994
26995    let source = r#"
26996      .foo {
26997        color: red;
26998
26999        &.bar {
27000          color: green;
27001        }
27002      }
27003    "#;
27004
27005    let expected = indoc! {r#"
27006      .foo {
27007        color: red;
27008      }
27009    "#};
27010
27011    let mut stylesheet = StyleSheet::parse(&source, ParserOptions::default()).unwrap();
27012    stylesheet
27013      .minify(MinifyOptions {
27014        unused_symbols: vec!["bar"].iter().map(|s| String::from(*s)).collect(),
27015        ..MinifyOptions::default()
27016      })
27017      .unwrap();
27018    let res = stylesheet.to_css(PrinterOptions::default()).unwrap();
27019    assert_eq!(res.code, expected);
27020
27021    let source = r#"
27022      .foo {
27023        color: red;
27024
27025        &.bar {
27026          color: purple;
27027        }
27028
27029        @nest &.bar {
27030          color: orange;
27031        }
27032
27033        @nest :not(&) {
27034          color: green;
27035        }
27036
27037        @media (orientation: portrait) {
27038          color: brown;
27039        }
27040      }
27041
27042      .x {
27043        color: purple;
27044
27045        &.y {
27046          color: green;
27047        }
27048      }
27049    "#;
27050
27051    let expected = indoc! {r#"
27052      :not(.foo) {
27053        color: green;
27054      }
27055    "#};
27056
27057    let mut stylesheet = StyleSheet::parse(&source, ParserOptions::default()).unwrap();
27058    stylesheet
27059      .minify(MinifyOptions {
27060        unused_symbols: vec!["foo", "x"].iter().map(|s| String::from(*s)).collect(),
27061        ..MinifyOptions::default()
27062      })
27063      .unwrap();
27064    let res = stylesheet
27065      .to_css(PrinterOptions {
27066        targets: Browsers {
27067          chrome: Some(95 << 16),
27068          ..Browsers::default()
27069        }
27070        .into(),
27071        ..PrinterOptions::default()
27072      })
27073      .unwrap();
27074    assert_eq!(res.code, expected);
27075
27076    let source = r#"
27077      @property --EgL3uq_foo {
27078        syntax: "<color>";
27079        inherits: false;
27080        initial-value: #ff0;
27081      }
27082
27083      @font-palette-values --EgL3uq_Cooler {
27084        font-family: Bixa;
27085        base-palette: 1;
27086        override-colors: 1 #7EB7E4;
27087      }
27088
27089      .EgL3uq_foo {
27090        --EgL3uq_foo: red;
27091      }
27092
27093      .EgL3uq_bar {
27094        color: green;
27095      }
27096    "#;
27097
27098    let expected = indoc! {r#"
27099      .EgL3uq_bar {
27100        color: green;
27101      }
27102    "#};
27103
27104    let mut stylesheet = StyleSheet::parse(&source, ParserOptions::default()).unwrap();
27105    stylesheet
27106      .minify(MinifyOptions {
27107        unused_symbols: vec!["--EgL3uq_foo", "--EgL3uq_Cooler"]
27108          .iter()
27109          .map(|s| String::from(*s))
27110          .collect(),
27111        ..MinifyOptions::default()
27112      })
27113      .unwrap();
27114    let res = stylesheet.to_css(PrinterOptions::default()).unwrap();
27115    assert_eq!(res.code, expected);
27116  }
27117
27118  #[test]
27119  fn test_svg() {
27120    use crate::properties::svg;
27121
27122    minify_test(".foo { fill: yellow; }", ".foo{fill:#ff0}");
27123    minify_test(".foo { fill: url(#foo); }", ".foo{fill:url(#foo)}");
27124    minify_test(".foo { fill: url(#foo) none; }", ".foo{fill:url(#foo) none}");
27125    minify_test(".foo { fill: url(#foo) yellow; }", ".foo{fill:url(#foo) #ff0}");
27126    minify_test(".foo { fill: none; }", ".foo{fill:none}");
27127    minify_test(".foo { fill: context-fill; }", ".foo{fill:context-fill}");
27128    minify_test(".foo { fill: context-stroke; }", ".foo{fill:context-stroke}");
27129
27130    minify_test(".foo { stroke: yellow; }", ".foo{stroke:#ff0}");
27131    minify_test(".foo { stroke: url(#foo); }", ".foo{stroke:url(#foo)}");
27132    minify_test(".foo { stroke: url(#foo) none; }", ".foo{stroke:url(#foo) none}");
27133    minify_test(".foo { stroke: url(#foo) yellow; }", ".foo{stroke:url(#foo) #ff0}");
27134    minify_test(".foo { stroke: none; }", ".foo{stroke:none}");
27135    minify_test(".foo { stroke: context-fill; }", ".foo{stroke:context-fill}");
27136    minify_test(".foo { stroke: context-stroke; }", ".foo{stroke:context-stroke}");
27137
27138    minify_test(".foo { marker-start: url(#foo); }", ".foo{marker-start:url(#foo)}");
27139
27140    minify_test(".foo { stroke-dasharray: 4 1 2; }", ".foo{stroke-dasharray:4 1 2}");
27141    minify_test(".foo { stroke-dasharray: 4,1,2; }", ".foo{stroke-dasharray:4 1 2}");
27142    minify_test(".foo { stroke-dasharray: 4, 1, 2; }", ".foo{stroke-dasharray:4 1 2}");
27143    minify_test(
27144      ".foo { stroke-dasharray: 4px, 1px, 2px; }",
27145      ".foo{stroke-dasharray:4 1 2}",
27146    );
27147
27148    minify_test(".foo { mask: url('foo.svg'); }", ".foo{mask:url(foo.svg)}");
27149    minify_test(
27150      ".foo { mask: url(masks.svg#star) luminance }",
27151      ".foo{mask:url(masks.svg#star) luminance}",
27152    );
27153    minify_test(
27154      ".foo { mask: url(masks.svg#star) 40px 20px }",
27155      ".foo{mask:url(masks.svg#star) 40px 20px}",
27156    );
27157    minify_test(
27158      ".foo { mask: url(masks.svg#star) 0 0 / 50px 50px }",
27159      ".foo{mask:url(masks.svg#star) 0 0/50px 50px}",
27160    );
27161    minify_test(
27162      ".foo { mask: url(masks.svg#star) repeat-x }",
27163      ".foo{mask:url(masks.svg#star) repeat-x}",
27164    );
27165    minify_test(
27166      ".foo { mask: url(masks.svg#star) stroke-box }",
27167      ".foo{mask:url(masks.svg#star) stroke-box}",
27168    );
27169    minify_test(
27170      ".foo { mask: url(masks.svg#star) stroke-box stroke-box }",
27171      ".foo{mask:url(masks.svg#star) stroke-box}",
27172    );
27173    minify_test(
27174      ".foo { mask: url(masks.svg#star) border-box }",
27175      ".foo{mask:url(masks.svg#star)}",
27176    );
27177    minify_test(
27178      ".foo { mask: url(masks.svg#star) left / 16px repeat-y, url(masks.svg#circle) right / 16px repeat-y }",
27179      ".foo{mask:url(masks.svg#star) 0/16px repeat-y,url(masks.svg#circle) 100%/16px repeat-y}",
27180    );
27181
27182    minify_test(
27183      ".foo { mask-border: url('border-mask.png') 25; }",
27184      ".foo{mask-border:url(border-mask.png) 25}",
27185    );
27186    minify_test(
27187      ".foo { mask-border: url('border-mask.png') 25 / 35px / 12px space alpha; }",
27188      ".foo{mask-border:url(border-mask.png) 25/35px/12px space}",
27189    );
27190    minify_test(
27191      ".foo { mask-border: url('border-mask.png') 25 / 35px / 12px space luminance; }",
27192      ".foo{mask-border:url(border-mask.png) 25/35px/12px space luminance}",
27193    );
27194    minify_test(
27195      ".foo { mask-border: url('border-mask.png') luminance 25 / 35px / 12px space; }",
27196      ".foo{mask-border:url(border-mask.png) 25/35px/12px space luminance}",
27197    );
27198
27199    minify_test(
27200      ".foo { clip-path: url('clip.svg#star'); }",
27201      ".foo{clip-path:url(clip.svg#star)}",
27202    );
27203    minify_test(".foo { clip-path: margin-box; }", ".foo{clip-path:margin-box}");
27204    minify_test(
27205      ".foo { clip-path: inset(100px 50px); }",
27206      ".foo{clip-path:inset(100px 50px)}",
27207    );
27208    minify_test(
27209      ".foo { clip-path: inset(100px 50px round 5px); }",
27210      ".foo{clip-path:inset(100px 50px round 5px)}",
27211    );
27212    minify_test(
27213      ".foo { clip-path: inset(100px 50px round 5px 5px 5px 5px); }",
27214      ".foo{clip-path:inset(100px 50px round 5px)}",
27215    );
27216    minify_test(".foo { clip-path: circle(50px); }", ".foo{clip-path:circle(50px)}");
27217    minify_test(
27218      ".foo { clip-path: circle(50px at center center); }",
27219      ".foo{clip-path:circle(50px)}",
27220    );
27221    minify_test(
27222      ".foo { clip-path: circle(50px at 50% 50%); }",
27223      ".foo{clip-path:circle(50px)}",
27224    );
27225    minify_test(
27226      ".foo { clip-path: circle(50px at 0 100px); }",
27227      ".foo{clip-path:circle(50px at 0 100px)}",
27228    );
27229    minify_test(
27230      ".foo { clip-path: circle(closest-side at 0 100px); }",
27231      ".foo{clip-path:circle(at 0 100px)}",
27232    );
27233    minify_test(
27234      ".foo { clip-path: circle(farthest-side at 0 100px); }",
27235      ".foo{clip-path:circle(farthest-side at 0 100px)}",
27236    );
27237    minify_test(
27238      ".foo { clip-path: circle(closest-side at 50% 50%); }",
27239      ".foo{clip-path:circle()}",
27240    );
27241    minify_test(
27242      ".foo { clip-path: ellipse(50px 60px at 0 10% 20%); }",
27243      ".foo{clip-path:ellipse(50px 60px at 0 10% 20%)}",
27244    );
27245    minify_test(
27246      ".foo { clip-path: ellipse(50px 60px at center center); }",
27247      ".foo{clip-path:ellipse(50px 60px)}",
27248    );
27249    minify_test(
27250      ".foo { clip-path: ellipse(closest-side closest-side at 50% 50%); }",
27251      ".foo{clip-path:ellipse()}",
27252    );
27253    minify_test(
27254      ".foo { clip-path: ellipse(closest-side closest-side at 10% 20%); }",
27255      ".foo{clip-path:ellipse(at 10% 20%)}",
27256    );
27257    minify_test(
27258      ".foo { clip-path: ellipse(farthest-side closest-side at 10% 20%); }",
27259      ".foo{clip-path:ellipse(farthest-side closest-side at 10% 20%)}",
27260    );
27261    minify_test(
27262      ".foo { clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%); }",
27263      ".foo{clip-path:polygon(50% 0%,100% 50%,50% 100%,0% 50%)}",
27264    );
27265    minify_test(
27266      ".foo { clip-path: polygon(nonzero, 50% 0%, 100% 50%, 50% 100%, 0% 50%); }",
27267      ".foo{clip-path:polygon(50% 0%,100% 50%,50% 100%,0% 50%)}",
27268    );
27269    minify_test(
27270      ".foo { clip-path: polygon(evenodd, 50% 0%, 100% 50%, 50% 100%, 0% 50%); }",
27271      ".foo{clip-path:polygon(evenodd,50% 0%,100% 50%,50% 100%,0% 50%)}",
27272    );
27273    minify_test(
27274      ".foo { clip-path: padding-box circle(50px at 0 100px); }",
27275      ".foo{clip-path:circle(50px at 0 100px) padding-box}",
27276    );
27277    minify_test(
27278      ".foo { clip-path: circle(50px at 0 100px) padding-box; }",
27279      ".foo{clip-path:circle(50px at 0 100px) padding-box}",
27280    );
27281    minify_test(
27282      ".foo { clip-path: circle(50px at 0 100px) border-box; }",
27283      ".foo{clip-path:circle(50px at 0 100px)}",
27284    );
27285
27286    prefix_test(
27287      ".foo { clip-path: circle(50px); }",
27288      indoc! { r#"
27289        .foo {
27290          -webkit-clip-path: circle(50px);
27291          clip-path: circle(50px);
27292        }
27293      "#},
27294      Browsers {
27295        chrome: Some(30 << 16),
27296        ..Browsers::default()
27297      },
27298    );
27299
27300    prefix_test(
27301      ".foo { clip-path: circle(50px); }",
27302      indoc! { r#"
27303        .foo {
27304          clip-path: circle(50px);
27305        }
27306      "#},
27307      Browsers {
27308        chrome: Some(80 << 16),
27309        ..Browsers::default()
27310      },
27311    );
27312
27313    prefix_test(
27314      ".foo { clip-path: circle(50px); }",
27315      indoc! { r#"
27316        .foo {
27317          -webkit-clip-path: circle(50px);
27318          clip-path: circle(50px);
27319        }
27320      "#},
27321      Browsers {
27322        safari: Some(8 << 16),
27323        ..Browsers::default()
27324      },
27325    );
27326
27327    prefix_test(
27328      ".foo { clip-path: circle(50px); }",
27329      indoc! { r#"
27330        .foo {
27331          clip-path: circle(50px);
27332        }
27333      "#},
27334      Browsers {
27335        safari: Some(14 << 16),
27336        ..Browsers::default()
27337      },
27338    );
27339
27340    prefix_test(
27341      ".foo { fill: lch(50.998% 135.363 338) }",
27342      indoc! { r#"
27343        .foo {
27344          fill: #ee00be;
27345          fill: color(display-p3 .972962 -.362078 .804206);
27346          fill: lch(50.998% 135.363 338);
27347        }
27348      "#},
27349      Browsers {
27350        chrome: Some(90 << 16),
27351        safari: Some(14 << 16),
27352        ..Browsers::default()
27353      },
27354    );
27355
27356    prefix_test(
27357      ".foo { stroke: lch(50.998% 135.363 338) }",
27358      indoc! { r#"
27359        .foo {
27360          stroke: #ee00be;
27361          stroke: color(display-p3 .972962 -.362078 .804206);
27362          stroke: lch(50.998% 135.363 338);
27363        }
27364      "#},
27365      Browsers {
27366        chrome: Some(90 << 16),
27367        safari: Some(14 << 16),
27368        ..Browsers::default()
27369      },
27370    );
27371
27372    prefix_test(
27373      ".foo { fill: url(#foo) lch(50.998% 135.363 338) }",
27374      indoc! { r##"
27375        .foo {
27376          fill: url("#foo") #ee00be;
27377          fill: url("#foo") color(display-p3 .972962 -.362078 .804206);
27378          fill: url("#foo") lch(50.998% 135.363 338);
27379        }
27380      "##},
27381      Browsers {
27382        chrome: Some(90 << 16),
27383        safari: Some(14 << 16),
27384        ..Browsers::default()
27385      },
27386    );
27387
27388    prefix_test(
27389      ".foo { fill: var(--url) lch(50.998% 135.363 338) }",
27390      indoc! { r#"
27391        .foo {
27392          fill: var(--url) #ee00be;
27393        }
27394
27395        @supports (color: lab(0% 0 0)) {
27396          .foo {
27397            fill: var(--url) lab(50.998% 125.506 -50.7078);
27398          }
27399        }
27400      "#},
27401      Browsers {
27402        chrome: Some(90 << 16),
27403        ..Browsers::default()
27404      },
27405    );
27406
27407    prefix_test(
27408      r#"
27409        @supports (color: lab(0% 0 0)) {
27410          .foo {
27411            fill: var(--url) lab(50.998% 125.506 -50.7078);
27412          }
27413        }
27414      "#,
27415      indoc! { r#"
27416        @supports (color: lab(0% 0 0)) {
27417          .foo {
27418            fill: var(--url) lab(50.998% 125.506 -50.7078);
27419          }
27420        }
27421      "#},
27422      Browsers {
27423        chrome: Some(90 << 16),
27424        ..Browsers::default()
27425      },
27426    );
27427
27428    prefix_test(
27429      ".foo { mask-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
27430      indoc! { r#"
27431        .foo {
27432          -webkit-mask-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ff0f0e), to(#7773ff));
27433          -webkit-mask-image: -webkit-linear-gradient(top, #ff0f0e, #7773ff);
27434          -webkit-mask-image: linear-gradient(#ff0f0e, #7773ff);
27435          mask-image: linear-gradient(#ff0f0e, #7773ff);
27436          -webkit-mask-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
27437          mask-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
27438        }
27439      "#},
27440      Browsers {
27441        chrome: Some(8 << 16),
27442        ..Browsers::default()
27443      },
27444    );
27445
27446    prefix_test(
27447      ".foo { mask-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) }",
27448      indoc! { r#"
27449        .foo {
27450          -webkit-mask-image: linear-gradient(#ff0f0e, #7773ff);
27451          mask-image: linear-gradient(#ff0f0e, #7773ff);
27452          -webkit-mask-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
27453          mask-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
27454        }
27455      "#},
27456      Browsers {
27457        chrome: Some(95 << 16),
27458        ..Browsers::default()
27459      },
27460    );
27461
27462    prefix_test(
27463      ".foo { mask-image: linear-gradient(red, green) }",
27464      indoc! { r#"
27465        .foo {
27466          -webkit-mask-image: linear-gradient(red, green);
27467          mask-image: linear-gradient(red, green);
27468        }
27469      "#},
27470      Browsers {
27471        chrome: Some(95 << 16),
27472        ..Browsers::default()
27473      },
27474    );
27475
27476    prefix_test(
27477      ".foo { -webkit-mask-image: url(x.svg); mask-image: url(x.svg); }",
27478      indoc! { r#"
27479        .foo {
27480          -webkit-mask-image: url("x.svg");
27481          mask-image: url("x.svg");
27482        }
27483      "#},
27484      Browsers {
27485        chrome: Some(95 << 16),
27486        ..Browsers::default()
27487      },
27488    );
27489
27490    prefix_test(
27491      ".foo { mask: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 40px 20px }",
27492      indoc! { r#"
27493        .foo {
27494          -webkit-mask: -webkit-gradient(linear, 0 0, 0 100%, from(#ff0f0e), to(#7773ff)) 40px 20px;
27495          -webkit-mask: -webkit-linear-gradient(top, #ff0f0e, #7773ff) 40px 20px;
27496          -webkit-mask: linear-gradient(#ff0f0e, #7773ff) 40px 20px;
27497          mask: linear-gradient(#ff0f0e, #7773ff) 40px 20px;
27498          -webkit-mask: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 40px 20px;
27499          mask: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 40px 20px;
27500        }
27501      "#},
27502      Browsers {
27503        chrome: Some(8 << 16),
27504        ..Browsers::default()
27505      },
27506    );
27507
27508    prefix_test(
27509      ".foo { mask: -webkit-linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 40px 20px }",
27510      indoc! { r#"
27511        .foo {
27512          -webkit-mask: -webkit-gradient(linear, 0 0, 0 100%, from(#ff0f0e), to(#7773ff)) 40px 20px;
27513          -webkit-mask: -webkit-linear-gradient(#ff0f0e, #7773ff) 40px 20px;
27514        }
27515      "#},
27516      Browsers {
27517        chrome: Some(8 << 16),
27518        ..Browsers::default()
27519      },
27520    );
27521
27522    prefix_test(
27523      ".foo { mask: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 40px var(--foo) }",
27524      indoc! { r#"
27525        .foo {
27526          -webkit-mask: linear-gradient(#ff0f0e, #7773ff) 40px var(--foo);
27527          mask: linear-gradient(#ff0f0e, #7773ff) 40px var(--foo);
27528        }
27529
27530        @supports (color: lab(0% 0 0)) {
27531          .foo {
27532            -webkit-mask: linear-gradient(lab(56.208% 94.4644 98.8928), lab(51% 70.4544 -115.586)) 40px var(--foo);
27533            mask: linear-gradient(lab(56.208% 94.4644 98.8928), lab(51% 70.4544 -115.586)) 40px var(--foo);
27534          }
27535        }
27536      "#},
27537      Browsers {
27538        chrome: Some(90 << 16),
27539        ..Browsers::default()
27540      },
27541    );
27542
27543    prefix_test(
27544      r#"
27545        @supports (color: lab(0% 0 0)) {
27546          .foo {
27547            mask: linear-gradient(lab(56.208% 94.4644 98.8928), lab(51% 70.4544 -115.586)) 40px var(--foo);
27548          }
27549        }
27550      "#,
27551      indoc! { r#"
27552        @supports (color: lab(0% 0 0)) {
27553          .foo {
27554            -webkit-mask: linear-gradient(lab(56.208% 94.4644 98.8928), lab(51% 70.4544 -115.586)) 40px var(--foo);
27555            mask: linear-gradient(lab(56.208% 94.4644 98.8928), lab(51% 70.4544 -115.586)) 40px var(--foo);
27556          }
27557        }
27558      "#},
27559      Browsers {
27560        chrome: Some(90 << 16),
27561        ..Browsers::default()
27562      },
27563    );
27564
27565    prefix_test(
27566      ".foo { mask: url(masks.svg#star) luminance }",
27567      indoc! { r#"
27568        .foo {
27569          -webkit-mask: url("masks.svg#star");
27570          -webkit-mask-source-type: luminance;
27571          mask: url("masks.svg#star") luminance;
27572        }
27573    "#},
27574      Browsers {
27575        chrome: Some(90 << 16),
27576        ..Browsers::default()
27577      },
27578    );
27579
27580    prefix_test(
27581      ".foo { mask-image: url(masks.svg#star) }",
27582      indoc! { r#"
27583        .foo {
27584          -webkit-mask-image: url("masks.svg#star");
27585          mask-image: url("masks.svg#star");
27586        }
27587    "#},
27588      Browsers {
27589        chrome: Some(90 << 16),
27590        ..Browsers::default()
27591      },
27592    );
27593
27594    prefix_test(
27595      r#"
27596        .foo {
27597          mask-image: url(masks.svg#star);
27598          mask-position: 25% 75%;
27599          mask-size: cover;
27600          mask-repeat: no-repeat;
27601          mask-clip: padding-box;
27602          mask-origin: content-box;
27603          mask-composite: subtract;
27604          mask-mode: luminance;
27605        }
27606      "#,
27607      indoc! { r#"
27608        .foo {
27609          -webkit-mask: url("masks.svg#star") 25% 75% / cover no-repeat content-box padding-box;
27610          -webkit-mask-composite: source-out;
27611          -webkit-mask-source-type: luminance;
27612          mask: url("masks.svg#star") 25% 75% / cover no-repeat content-box padding-box subtract luminance;
27613        }
27614    "#},
27615      Browsers {
27616        chrome: Some(90 << 16),
27617        ..Browsers::default()
27618      },
27619    );
27620
27621    prefix_test(
27622      r#"
27623        .foo {
27624          mask-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
27625          mask-position: 25% 75%;
27626          mask-size: cover;
27627          mask-repeat: no-repeat;
27628          mask-clip: padding-box;
27629          mask-origin: content-box;
27630          mask-composite: subtract;
27631          mask-mode: luminance;
27632        }
27633      "#,
27634      indoc! { r#"
27635        .foo {
27636          -webkit-mask: linear-gradient(#ff0f0e, #7773ff) 25% 75% / cover no-repeat content-box padding-box;
27637          -webkit-mask-composite: source-out;
27638          -webkit-mask-source-type: luminance;
27639          mask: linear-gradient(#ff0f0e, #7773ff) 25% 75% / cover no-repeat content-box padding-box subtract luminance;
27640          -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;
27641          -webkit-mask-composite: source-out;
27642          -webkit-mask-source-type: luminance;
27643          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;
27644        }
27645    "#},
27646      Browsers {
27647        chrome: Some(90 << 16),
27648        ..Browsers::default()
27649      },
27650    );
27651
27652    test(
27653      r#"
27654        .foo {
27655          mask: none center / 100% no-repeat;
27656          mask-image: var(--svg);
27657        }
27658      "#,
27659      indoc! { r#"
27660        .foo {
27661          mask: none center / 100% no-repeat;
27662          mask-image: var(--svg);
27663        }
27664      "#},
27665    );
27666
27667    prefix_test(
27668      r#"
27669        .foo {
27670          mask-composite: subtract;
27671        }
27672      "#,
27673      indoc! { r#"
27674        .foo {
27675          -webkit-mask-composite: source-out;
27676          mask-composite: subtract;
27677        }
27678    "#},
27679      Browsers {
27680        chrome: Some(90 << 16),
27681        ..Browsers::default()
27682      },
27683    );
27684
27685    prefix_test(
27686      r#"
27687        .foo {
27688          mask-mode: luminance;
27689        }
27690      "#,
27691      indoc! { r#"
27692        .foo {
27693          -webkit-mask-source-type: luminance;
27694          mask-mode: luminance;
27695        }
27696    "#},
27697      Browsers {
27698        chrome: Some(90 << 16),
27699        ..Browsers::default()
27700      },
27701    );
27702
27703    prefix_test(
27704      r#"
27705        .foo {
27706          mask-border: url('border-mask.png') 25 / 35px / 12px space luminance;
27707        }
27708      "#,
27709      indoc! { r#"
27710        .foo {
27711          -webkit-mask-box-image: url("border-mask.png") 25 / 35px / 12px space;
27712          mask-border: url("border-mask.png") 25 / 35px / 12px space luminance;
27713        }
27714    "#},
27715      Browsers {
27716        chrome: Some(90 << 16),
27717        ..Browsers::default()
27718      },
27719    );
27720
27721    prefix_test(
27722      r#"
27723        .foo {
27724          mask-border: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 25 / 35px / 12px space luminance;
27725        }
27726      "#,
27727      indoc! { r#"
27728        .foo {
27729          -webkit-mask-box-image: linear-gradient(#ff0f0e, #7773ff) 25 / 35px / 12px space;
27730          mask-border: linear-gradient(#ff0f0e, #7773ff) 25 / 35px / 12px space luminance;
27731          -webkit-mask-box-image: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 25 / 35px / 12px space;
27732          mask-border: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) 25 / 35px / 12px space luminance;
27733        }
27734    "#},
27735      Browsers {
27736        chrome: Some(90 << 16),
27737        ..Browsers::default()
27738      },
27739    );
27740
27741    prefix_test(
27742      r#"
27743        .foo {
27744          mask-border-source: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
27745        }
27746      "#,
27747      indoc! { r#"
27748        .foo {
27749          -webkit-mask-box-image-source: linear-gradient(#ff0f0e, #7773ff);
27750          mask-border-source: linear-gradient(#ff0f0e, #7773ff);
27751          -webkit-mask-box-image-source: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
27752          mask-border-source: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364));
27753        }
27754    "#},
27755      Browsers {
27756        chrome: Some(90 << 16),
27757        ..Browsers::default()
27758      },
27759    );
27760
27761    prefix_test(
27762      r#"
27763        .foo {
27764          mask-border-source: url(foo.png);
27765          mask-border-slice: 10 40 10 40;
27766          mask-border-width: 10px;
27767          mask-border-outset: 0;
27768          mask-border-repeat: round round;
27769          mask-border-mode: luminance;
27770        }
27771      "#,
27772      indoc! { r#"
27773        .foo {
27774          -webkit-mask-box-image: url("foo.png") 10 40 / 10px round;
27775          mask-border: url("foo.png") 10 40 / 10px round luminance;
27776        }
27777    "#},
27778      Browsers {
27779        chrome: Some(90 << 16),
27780        ..Browsers::default()
27781      },
27782    );
27783
27784    prefix_test(
27785      r#"
27786        .foo {
27787          -webkit-mask-box-image-source: url(foo.png);
27788          -webkit-mask-box-image-slice: 10 40 10 40;
27789          -webkit-mask-box-image-width: 10px;
27790          -webkit-mask-box-image-outset: 0;
27791          -webkit-mask-box-image-repeat: round round;
27792        }
27793      "#,
27794      indoc! { r#"
27795        .foo {
27796          -webkit-mask-box-image: url("foo.png") 10 40 / 10px round;
27797        }
27798    "#},
27799      Browsers {
27800        chrome: Some(90 << 16),
27801        ..Browsers::default()
27802      },
27803    );
27804
27805    prefix_test(
27806      r#"
27807        .foo {
27808          mask-border-slice: 10 40 10 40;
27809        }
27810      "#,
27811      indoc! { r#"
27812        .foo {
27813          -webkit-mask-box-image-slice: 10 40;
27814          mask-border-slice: 10 40;
27815        }
27816    "#},
27817      Browsers {
27818        chrome: Some(90 << 16),
27819        ..Browsers::default()
27820      },
27821    );
27822
27823    prefix_test(
27824      r#"
27825        .foo {
27826          mask-border-slice: var(--foo);
27827        }
27828      "#,
27829      indoc! { r#"
27830        .foo {
27831          -webkit-mask-box-image-slice: var(--foo);
27832          mask-border-slice: var(--foo);
27833        }
27834    "#},
27835      Browsers {
27836        chrome: Some(90 << 16),
27837        ..Browsers::default()
27838      },
27839    );
27840
27841    prefix_test(
27842      r#"
27843        .foo {
27844          mask-border: linear-gradient(lch(56.208% 136.76 46.312), lch(51% 135.366 301.364)) var(--foo);
27845        }
27846      "#,
27847      indoc! { r#"
27848        .foo {
27849          -webkit-mask-box-image: linear-gradient(#ff0f0e, #7773ff) var(--foo);
27850          mask-border: linear-gradient(#ff0f0e, #7773ff) var(--foo);
27851        }
27852
27853        @supports (color: lab(0% 0 0)) {
27854          .foo {
27855            -webkit-mask-box-image: linear-gradient(lab(56.208% 94.4644 98.8928), lab(51% 70.4544 -115.586)) var(--foo);
27856            mask-border: linear-gradient(lab(56.208% 94.4644 98.8928), lab(51% 70.4544 -115.586)) var(--foo);
27857          }
27858        }
27859    "#},
27860      Browsers {
27861        chrome: Some(90 << 16),
27862        ..Browsers::default()
27863      },
27864    );
27865
27866    prefix_test(
27867      r#"
27868        .foo {
27869          transition: mask 200ms;
27870        }
27871      "#,
27872      indoc! { r#"
27873        .foo {
27874          transition: -webkit-mask .2s, mask .2s;
27875        }
27876    "#},
27877      Browsers {
27878        chrome: Some(90 << 16),
27879        ..Browsers::default()
27880      },
27881    );
27882
27883    prefix_test(
27884      r#"
27885        .foo {
27886          transition: mask-border 200ms;
27887        }
27888      "#,
27889      indoc! { r#"
27890        .foo {
27891          transition: -webkit-mask-box-image .2s, mask-border .2s;
27892        }
27893    "#},
27894      Browsers {
27895        chrome: Some(90 << 16),
27896        ..Browsers::default()
27897      },
27898    );
27899
27900    prefix_test(
27901      r#"
27902        .foo {
27903          transition-property: mask;
27904        }
27905      "#,
27906      indoc! { r#"
27907        .foo {
27908          transition-property: -webkit-mask, mask;
27909        }
27910    "#},
27911      Browsers {
27912        chrome: Some(90 << 16),
27913        ..Browsers::default()
27914      },
27915    );
27916
27917    prefix_test(
27918      r#"
27919        .foo {
27920          transition-property: mask-border;
27921        }
27922      "#,
27923      indoc! { r#"
27924        .foo {
27925          transition-property: -webkit-mask-box-image, mask-border;
27926        }
27927    "#},
27928      Browsers {
27929        chrome: Some(90 << 16),
27930        ..Browsers::default()
27931      },
27932    );
27933
27934    prefix_test(
27935      r#"
27936        .foo {
27937          transition-property: mask-composite, mask-mode;
27938        }
27939      "#,
27940      indoc! { r#"
27941        .foo {
27942          transition-property: -webkit-mask-composite, mask-composite, -webkit-mask-source-type, mask-mode;
27943        }
27944    "#},
27945      Browsers {
27946        chrome: Some(90 << 16),
27947        ..Browsers::default()
27948      },
27949    );
27950
27951    let property =
27952      Property::parse_string("text-rendering".into(), "geometricPrecision", ParserOptions::default()).unwrap();
27953    assert_eq!(
27954      property,
27955      Property::TextRendering(svg::TextRendering::GeometricPrecision)
27956    );
27957    let property =
27958      Property::parse_string("shape-rendering".into(), "geometricPrecision", ParserOptions::default()).unwrap();
27959    assert_eq!(
27960      property,
27961      Property::ShapeRendering(svg::ShapeRendering::GeometricPrecision)
27962    );
27963    let property = Property::parse_string("color-interpolation".into(), "sRGB", ParserOptions::default()).unwrap();
27964    assert_eq!(property, Property::ColorInterpolation(svg::ColorInterpolation::SRGB));
27965  }
27966
27967  #[test]
27968  fn test_filter() {
27969    minify_test(
27970      ".foo { filter: url('filters.svg#filter-id'); }",
27971      ".foo{filter:url(filters.svg#filter-id)}",
27972    );
27973    minify_test(".foo { filter: blur(5px); }", ".foo{filter:blur(5px)}");
27974    minify_test(".foo { filter: blur(0px); }", ".foo{filter:blur()}");
27975    minify_test(".foo { filter: brightness(10%); }", ".foo{filter:brightness(10%)}");
27976    minify_test(".foo { filter: brightness(100%); }", ".foo{filter:brightness()}");
27977    minify_test(
27978      ".foo { filter: drop-shadow(16px 16px 20px yellow); }",
27979      ".foo{filter:drop-shadow(16px 16px 20px #ff0)}",
27980    );
27981    minify_test(
27982      ".foo { filter: contrast(175%) brightness(3%); }",
27983      ".foo{filter:contrast(175%)brightness(3%)}",
27984    );
27985    minify_test(".foo { filter: hue-rotate(0) }", ".foo{filter:hue-rotate()}");
27986
27987    prefix_test(
27988      ".foo { filter: blur(5px) }",
27989      indoc! { r#"
27990        .foo {
27991          -webkit-filter: blur(5px);
27992          filter: blur(5px);
27993        }
27994      "#},
27995      Browsers {
27996        chrome: Some(20 << 16),
27997        ..Browsers::default()
27998      },
27999    );
28000
28001    prefix_test(
28002      ".foo { filter: blur(5px) }",
28003      indoc! { r#"
28004        .foo {
28005          filter: blur(5px);
28006        }
28007      "#},
28008      Browsers {
28009        chrome: Some(80 << 16),
28010        ..Browsers::default()
28011      },
28012    );
28013
28014    prefix_test(
28015      ".foo { backdrop-filter: blur(5px) }",
28016      indoc! { r#"
28017        .foo {
28018          backdrop-filter: blur(5px);
28019        }
28020      "#},
28021      Browsers {
28022        chrome: Some(80 << 16),
28023        ..Browsers::default()
28024      },
28025    );
28026
28027    prefix_test(
28028      ".foo { backdrop-filter: blur(5px) }",
28029      indoc! { r#"
28030        .foo {
28031          -webkit-backdrop-filter: blur(5px);
28032          backdrop-filter: blur(5px);
28033        }
28034      "#},
28035      Browsers {
28036        safari: Some(15 << 16),
28037        ..Browsers::default()
28038      },
28039    );
28040    prefix_test(
28041      r#"
28042      .foo {
28043        -webkit-backdrop-filter: blur(8px);
28044        backdrop-filter: blur(8px);
28045      }
28046      "#,
28047      indoc! {r#"
28048      .foo {
28049        -webkit-backdrop-filter: blur(8px);
28050        backdrop-filter: blur(8px);
28051      }
28052      "#},
28053      Browsers {
28054        safari: Some(16 << 16),
28055        ..Browsers::default()
28056      },
28057    );
28058
28059    prefix_test(
28060      ".foo { filter: var(--foo) }",
28061      indoc! { r#"
28062        .foo {
28063          -webkit-filter: var(--foo);
28064          filter: var(--foo);
28065        }
28066      "#},
28067      Browsers {
28068        chrome: Some(20 << 16),
28069        ..Browsers::default()
28070      },
28071    );
28072
28073    prefix_test(
28074      ".foo { filter: drop-shadow(16px 16px 20px lab(40% 56.6 39)) }",
28075      indoc! { r#"
28076        .foo {
28077          -webkit-filter: drop-shadow(16px 16px 20px #b32323);
28078          filter: drop-shadow(16px 16px 20px #b32323);
28079          filter: drop-shadow(16px 16px 20px lab(40% 56.6 39));
28080        }
28081      "#},
28082      Browsers {
28083        chrome: Some(20 << 16),
28084        ..Browsers::default()
28085      },
28086    );
28087
28088    prefix_test(
28089      ".foo { filter: contrast(175%) drop-shadow(16px 16px 20px lab(40% 56.6 39)) }",
28090      indoc! { r#"
28091        .foo {
28092          filter: contrast(175%) drop-shadow(16px 16px 20px #b32323);
28093          filter: contrast(175%) drop-shadow(16px 16px 20px lab(40% 56.6 39));
28094        }
28095      "#},
28096      Browsers {
28097        chrome: Some(4 << 16),
28098        ..Browsers::default()
28099      },
28100    );
28101
28102    prefix_test(
28103      ".foo { filter: drop-shadow(16px 16px 20px lab(40% 56.6 39)) drop-shadow(16px 16px 20px yellow) }",
28104      indoc! { r#"
28105        .foo {
28106          filter: drop-shadow(16px 16px 20px #b32323) drop-shadow(16px 16px 20px #ff0);
28107          filter: drop-shadow(16px 16px 20px lab(40% 56.6 39)) drop-shadow(16px 16px 20px #ff0);
28108        }
28109      "#},
28110      Browsers {
28111        chrome: Some(4 << 16),
28112        ..Browsers::default()
28113      },
28114    );
28115
28116    prefix_test(
28117      ".foo { filter: var(--foo) drop-shadow(16px 16px 20px lab(40% 56.6 39)) }",
28118      indoc! { r#"
28119        .foo {
28120          filter: var(--foo) drop-shadow(16px 16px 20px #b32323);
28121        }
28122
28123        @supports (color: lab(0% 0 0)) {
28124          .foo {
28125            filter: var(--foo) drop-shadow(16px 16px 20px lab(40% 56.6 39));
28126          }
28127        }
28128      "#},
28129      Browsers {
28130        chrome: Some(4 << 16),
28131        ..Browsers::default()
28132      },
28133    );
28134  }
28135
28136  #[test]
28137  fn test_mix_blend_mode() {
28138    minify_test(
28139      ".foo { mix-blend-mode: normal }",
28140      ".foo{mix-blend-mode:normal}",
28141    );
28142    minify_test(
28143      ".foo { mix-blend-mode: multiply }",
28144      ".foo{mix-blend-mode:multiply}",
28145    );
28146    minify_test(
28147      ".foo { mix-blend-mode: screen }",
28148      ".foo{mix-blend-mode:screen}",
28149    );
28150    minify_test(
28151      ".foo { mix-blend-mode: overlay }",
28152      ".foo{mix-blend-mode:overlay}",
28153    );
28154    minify_test(
28155      ".foo { mix-blend-mode: darken }",
28156      ".foo{mix-blend-mode:darken}",
28157    );
28158    minify_test(
28159      ".foo { mix-blend-mode: lighten }",
28160      ".foo{mix-blend-mode:lighten}",
28161    );
28162    minify_test(
28163      ".foo { mix-blend-mode: color-dodge }",
28164      ".foo{mix-blend-mode:color-dodge}",
28165    );
28166    minify_test(
28167      ".foo { mix-blend-mode: color-burn }",
28168      ".foo{mix-blend-mode:color-burn}",
28169    );
28170    minify_test(
28171      ".foo { mix-blend-mode: hard-light }",
28172      ".foo{mix-blend-mode:hard-light}",
28173    );
28174    minify_test(
28175      ".foo { mix-blend-mode: soft-light }",
28176      ".foo{mix-blend-mode:soft-light}",
28177    );
28178    minify_test(
28179      ".foo { mix-blend-mode: difference }",
28180      ".foo{mix-blend-mode:difference}",
28181    );
28182    minify_test(
28183      ".foo { mix-blend-mode: exclusion }",
28184      ".foo{mix-blend-mode:exclusion}",
28185    );
28186    minify_test(
28187      ".foo { mix-blend-mode: hue }",
28188      ".foo{mix-blend-mode:hue}",
28189    );
28190    minify_test(
28191      ".foo { mix-blend-mode: saturation }",
28192      ".foo{mix-blend-mode:saturation}",
28193    );
28194    minify_test(
28195      ".foo { mix-blend-mode: color }",
28196      ".foo{mix-blend-mode:color}",
28197    );
28198    minify_test(
28199      ".foo { mix-blend-mode: luminosity }",
28200      ".foo{mix-blend-mode:luminosity}",
28201    );
28202    minify_test(
28203      ".foo { mix-blend-mode: plus-darker }",
28204      ".foo{mix-blend-mode:plus-darker}",
28205    );
28206    minify_test(
28207      ".foo { mix-blend-mode: plus-lighter }",
28208      ".foo{mix-blend-mode:plus-lighter}",
28209    );
28210  }
28211
28212  #[test]
28213  fn test_viewport() {
28214    minify_test(
28215      r#"
28216    @viewport {
28217      width: 100vw;
28218    }"#,
28219      "@viewport{width:100vw}",
28220    );
28221    minify_test(
28222      r#"
28223    @-ms-viewport {
28224      width: device-width;
28225    }"#,
28226      "@-ms-viewport{width:device-width}",
28227    );
28228  }
28229
28230  #[test]
28231  fn test_at_scope() {
28232    minify_test(
28233      r#"
28234      @scope {
28235        .foo {
28236          display: flex;
28237        }
28238      }
28239      "#,
28240      "@scope{.foo{display:flex}}",
28241    );
28242    minify_test(
28243      r#"
28244      @scope {
28245        :scope {
28246          display: flex;
28247          color: lightblue;
28248        }
28249      }"#,
28250      "@scope{:scope{color:#add8e6;display:flex}}",
28251    );
28252    minify_test(
28253      r#"
28254      @scope (.light-scheme) {
28255        a { color: yellow; }
28256      }
28257      "#,
28258      "@scope(.light-scheme){a{color:#ff0}}",
28259    );
28260    minify_test(
28261      r#"
28262      @scope (.media-object) to (.content > *) {
28263        a { color: yellow; }
28264      }
28265      "#,
28266      "@scope(.media-object) to (.content>*){a{color:#ff0}}",
28267    );
28268    minify_test(
28269      r#"
28270      @scope to (.content > *) {
28271        a { color: yellow; }
28272      }
28273      "#,
28274      "@scope to (.content>*){a{color:#ff0}}",
28275    );
28276    minify_test(
28277      r#"
28278      @scope (#my-component) {
28279        & { color: yellow; }
28280      }
28281      "#,
28282      "@scope(#my-component){&{color:#ff0}}",
28283    );
28284    minify_test(
28285      r#"
28286      @scope (.parent-scope) {
28287        @scope (:scope > .child-scope) to (:scope .limit) {
28288          .content { color: yellow; }
28289        }
28290      }
28291      "#,
28292      "@scope(.parent-scope){@scope(:scope>.child-scope) to (:scope .limit){.content{color:#ff0}}}",
28293    );
28294    minify_test(
28295      r#"
28296      .foo {
28297        @scope (.bar) {
28298          color: yellow;
28299        }
28300      }
28301      "#,
28302      ".foo{@scope(.bar){color:#ff0}}",
28303    );
28304    nesting_test(
28305      r#"
28306      .foo {
28307        @scope (.bar) {
28308          color: yellow;
28309        }
28310      }
28311      "#,
28312      indoc! {r#"
28313        @scope (.bar) {
28314          color: #ff0;
28315        }
28316      "#},
28317    );
28318    nesting_test(
28319      r#"
28320      .parent {
28321        color: blue;
28322
28323        @scope (& > .scope) to (& .limit) {
28324          & .content {
28325            color: yellow;
28326          }
28327        }
28328      }
28329      "#,
28330      indoc! {r#"
28331        .parent {
28332          color: #00f;
28333        }
28334
28335        @scope (.parent > .scope) to (.parent > .scope .limit) {
28336          :scope .content {
28337            color: #ff0;
28338          }
28339        }
28340      "#},
28341    );
28342  }
28343
28344  #[test]
28345  fn test_custom_media() {
28346    custom_media_test(
28347      r#"
28348      @custom-media --modern (color), (hover);
28349
28350      @media (--modern) and (width > 1024px) {
28351        .a {
28352          color: green;
28353        }
28354      }
28355      "#,
28356      indoc! {r#"
28357      @media ((color) or (hover)) and (width > 1024px) {
28358        .a {
28359          color: green;
28360        }
28361      }
28362      "#},
28363    );
28364
28365    custom_media_test(
28366      r#"
28367      @custom-media --color (color);
28368
28369      @media (--color) and (width > 1024px) {
28370        .a {
28371          color: green;
28372        }
28373      }
28374      "#,
28375      indoc! {r#"
28376      @media (color) and (width > 1024px) {
28377        .a {
28378          color: green;
28379        }
28380      }
28381      "#},
28382    );
28383
28384    custom_media_test(
28385      r#"
28386      @custom-media --a (color);
28387      @custom-media --b (--a);
28388
28389      @media (--b) and (width > 1024px) {
28390        .a {
28391          color: green;
28392        }
28393      }
28394      "#,
28395      indoc! {r#"
28396      @media (color) and (width > 1024px) {
28397        .a {
28398          color: green;
28399        }
28400      }
28401      "#},
28402    );
28403
28404    custom_media_test(
28405      r#"
28406      @custom-media --not-color not (color);
28407
28408      @media not (--not-color) {
28409        .a {
28410          color: green;
28411        }
28412      }
28413      "#,
28414      indoc! {r#"
28415      @media (color) {
28416        .a {
28417          color: green;
28418        }
28419      }
28420      "#},
28421    );
28422
28423    custom_media_test(
28424      r#"
28425      @custom-media --color-print print and (color);
28426
28427      @media (--color-print) {
28428        .a {
28429          color: green;
28430        }
28431      }
28432      "#,
28433      indoc! {r#"
28434      @media print and (color) {
28435        .a {
28436          color: green;
28437        }
28438      }
28439      "#},
28440    );
28441
28442    custom_media_test(
28443      r#"
28444      @custom-media --color-print print and (color);
28445
28446      @media print and (--color-print) {
28447        .a {
28448          color: green;
28449        }
28450      }
28451      "#,
28452      indoc! {r#"
28453      @media print and (color) {
28454        .a {
28455          color: green;
28456        }
28457      }
28458      "#},
28459    );
28460
28461    custom_media_test(
28462      r#"
28463      @custom-media --not-color-print not print and (color);
28464
28465      @media not print and (--not-color-print) {
28466        .a {
28467          color: green;
28468        }
28469      }
28470      "#,
28471      indoc! {r#"
28472      @media not print and (color) {
28473        .a {
28474          color: green;
28475        }
28476      }
28477      "#},
28478    );
28479
28480    custom_media_test(
28481      r#"
28482      @custom-media --print print;
28483
28484      @media (--print) {
28485        .a {
28486          color: green;
28487        }
28488      }
28489      "#,
28490      indoc! {r#"
28491      @media print {
28492        .a {
28493          color: green;
28494        }
28495      }
28496      "#},
28497    );
28498
28499    custom_media_test(
28500      r#"
28501      @custom-media --print print;
28502
28503      @media not (--print) {
28504        .a {
28505          color: green;
28506        }
28507      }
28508      "#,
28509      indoc! {r#"
28510      @media not print {
28511        .a {
28512          color: green;
28513        }
28514      }
28515      "#},
28516    );
28517
28518    custom_media_test(
28519      r#"
28520      @custom-media --print not print;
28521
28522      @media not (--print) {
28523        .a {
28524          color: green;
28525        }
28526      }
28527      "#,
28528      indoc! {r#"
28529      @media print {
28530        .a {
28531          color: green;
28532        }
28533      }
28534      "#},
28535    );
28536
28537    custom_media_test(
28538      r#"
28539      @custom-media --print print;
28540
28541      @media ((--print)) {
28542        .a {
28543          color: green;
28544        }
28545      }
28546      "#,
28547      indoc! {r#"
28548      @media print {
28549        .a {
28550          color: green;
28551        }
28552      }
28553      "#},
28554    );
28555
28556    custom_media_test(
28557      r#"
28558      @custom-media --color (color);
28559      @custom-media --print print;
28560
28561      @media (--print) and (--color) {
28562        .a {
28563          color: green;
28564        }
28565      }
28566      "#,
28567      indoc! {r#"
28568      @media print and (color) {
28569        .a {
28570          color: green;
28571        }
28572      }
28573      "#},
28574    );
28575
28576    custom_media_test(
28577      r#"
28578      @custom-media --color (color);
28579      @custom-media --not-print not print;
28580
28581      @media (--not-print) and (--color) {
28582        .a {
28583          color: green;
28584        }
28585      }
28586      "#,
28587      indoc! {r#"
28588      @media not print and (color) {
28589        .a {
28590          color: green;
28591        }
28592      }
28593      "#},
28594    );
28595
28596    custom_media_test(
28597      r#"
28598      @custom-media --color (color);
28599      @custom-media --screen screen;
28600      @custom-media --print print;
28601
28602      @media (--print) and (--color), (--screen) and (--color) {
28603        .a {
28604          color: green;
28605        }
28606      }
28607      "#,
28608      indoc! {r#"
28609      @media print and (color), screen and (color) {
28610        .a {
28611          color: green;
28612        }
28613      }
28614      "#},
28615    );
28616
28617    custom_media_test(
28618      r#"
28619      @custom-media --color print and (color), print and (script);
28620
28621      @media (--color) {
28622        .a {
28623          color: green;
28624        }
28625      }
28626      "#,
28627      indoc! {r#"
28628      @media print and ((color) or (script)) {
28629        .a {
28630          color: green;
28631        }
28632      }
28633      "#},
28634    );
28635
28636    custom_media_test(
28637      r#"
28638      @custom-media --color (color);
28639      @custom-media --not-color not all and (--color);
28640
28641      @media (--not-color) {
28642        .a {
28643          color: green;
28644        }
28645      }
28646      "#,
28647      indoc! {r#"
28648        @media not all and (color) {
28649          .a {
28650            color: green;
28651          }
28652        }
28653      "#},
28654    );
28655
28656    custom_media_test(
28657      r#"
28658      @custom-media --color (color);
28659
28660      @media not all and (--color) {
28661        .a {
28662          color: green;
28663        }
28664      }
28665      "#,
28666      indoc! {r#"
28667        @media not all and (color) {
28668          .a {
28669            color: green;
28670          }
28671        }
28672      "#},
28673    );
28674
28675    custom_media_test(
28676      r#"
28677      @media (--print) {
28678        .a {
28679          color: green;
28680        }
28681      }
28682
28683      @custom-media --print print;
28684      "#,
28685      indoc! {r#"
28686      @media print {
28687        .a {
28688          color: green;
28689        }
28690      }
28691      "#},
28692    );
28693
28694    custom_media_test(
28695      r#"
28696      @custom-media --not-width not (min-width: 300px);
28697      @media screen and ((prefers-color-scheme: dark) or (--not-width)) {
28698        .foo {
28699          order: 6;
28700        }
28701      }
28702      "#,
28703      indoc! {r#"
28704      @media screen and ((prefers-color-scheme: dark) or ((width < 300px))) {
28705        .foo {
28706          order: 6;
28707        }
28708      }
28709      "#},
28710    );
28711
28712    fn custom_media_error_test(source: &str, err: Error<MinifyErrorKind>) {
28713      let mut stylesheet = StyleSheet::parse(
28714        &source,
28715        ParserOptions {
28716          filename: "test.css".into(),
28717          flags: ParserFlags::CUSTOM_MEDIA,
28718          ..ParserOptions::default()
28719        },
28720      )
28721      .unwrap();
28722      let res = stylesheet.minify(MinifyOptions {
28723        targets: Browsers {
28724          chrome: Some(95 << 16),
28725          ..Browsers::default()
28726        }
28727        .into(),
28728        ..MinifyOptions::default()
28729      });
28730      assert_eq!(res, Err(err))
28731    }
28732
28733    custom_media_error_test(
28734      r#"
28735      @custom-media --color-print print and (color);
28736
28737      @media screen and (--color-print) {
28738        .a {
28739          color: green;
28740        }
28741      }
28742      "#,
28743      Error {
28744        kind: MinifyErrorKind::UnsupportedCustomMediaBooleanLogic {
28745          custom_media_loc: Location {
28746            source_index: 0,
28747            line: 1,
28748            column: 7,
28749          },
28750        },
28751        loc: Some(ErrorLocation {
28752          filename: "test.css".into(),
28753          line: 3,
28754          column: 7,
28755        }),
28756      },
28757    );
28758
28759    custom_media_error_test(
28760      r#"
28761      @custom-media --color-print print and (color);
28762
28763      @media not print and (--color-print) {
28764        .a {
28765          color: green;
28766        }
28767      }
28768      "#,
28769      Error {
28770        kind: MinifyErrorKind::UnsupportedCustomMediaBooleanLogic {
28771          custom_media_loc: Location {
28772            source_index: 0,
28773            line: 1,
28774            column: 7,
28775          },
28776        },
28777        loc: Some(ErrorLocation {
28778          filename: "test.css".into(),
28779          line: 3,
28780          column: 7,
28781        }),
28782      },
28783    );
28784
28785    custom_media_error_test(
28786      r#"
28787      @custom-media --color-print print and (color);
28788      @custom-media --color-screen screen and (color);
28789
28790      @media (--color-print) or (--color-screen) {}
28791      "#,
28792      Error {
28793        kind: MinifyErrorKind::UnsupportedCustomMediaBooleanLogic {
28794          custom_media_loc: Location {
28795            source_index: 0,
28796            line: 2,
28797            column: 7,
28798          },
28799        },
28800        loc: Some(ErrorLocation {
28801          filename: "test.css".into(),
28802          line: 4,
28803          column: 7,
28804        }),
28805      },
28806    );
28807
28808    custom_media_error_test(
28809      r#"
28810      @custom-media --color-print print and (color);
28811      @custom-media --color-screen screen and (color);
28812
28813      @media (--color-print) and (--color-screen) {}
28814      "#,
28815      Error {
28816        kind: MinifyErrorKind::UnsupportedCustomMediaBooleanLogic {
28817          custom_media_loc: Location {
28818            source_index: 0,
28819            line: 2,
28820            column: 7,
28821          },
28822        },
28823        loc: Some(ErrorLocation {
28824          filename: "test.css".into(),
28825          line: 4,
28826          column: 7,
28827        }),
28828      },
28829    );
28830
28831    custom_media_error_test(
28832      r#"
28833      @custom-media --screen screen;
28834      @custom-media --print print;
28835
28836      @media (--print) and (--screen) {}
28837      "#,
28838      Error {
28839        kind: MinifyErrorKind::UnsupportedCustomMediaBooleanLogic {
28840          custom_media_loc: Location {
28841            source_index: 0,
28842            line: 1,
28843            column: 7,
28844          },
28845        },
28846        loc: Some(ErrorLocation {
28847          filename: "test.css".into(),
28848          line: 4,
28849          column: 7,
28850        }),
28851      },
28852    );
28853
28854    custom_media_error_test(
28855      r#"
28856      @custom-media --not-print not print and (color);
28857      @custom-media --not-screen not screen and (color);
28858
28859      @media ((script) or ((--not-print) and (--not-screen))) {
28860        .a {
28861          color: green;
28862        }
28863      }
28864      "#,
28865      Error {
28866        kind: MinifyErrorKind::UnsupportedCustomMediaBooleanLogic {
28867          custom_media_loc: Location {
28868            source_index: 0,
28869            line: 2,
28870            column: 7,
28871          },
28872        },
28873        loc: Some(ErrorLocation {
28874          filename: "test.css".into(),
28875          line: 4,
28876          column: 7,
28877        }),
28878      },
28879    );
28880
28881    custom_media_error_test(
28882      r#"
28883      @custom-media --color screen and (color), print and (color);
28884
28885      @media (--color) {
28886        .a {
28887          color: green;
28888        }
28889      }
28890      "#,
28891      Error {
28892        kind: MinifyErrorKind::UnsupportedCustomMediaBooleanLogic {
28893          custom_media_loc: Location {
28894            source_index: 0,
28895            line: 1,
28896            column: 7,
28897          },
28898        },
28899        loc: Some(ErrorLocation {
28900          filename: "test.css".into(),
28901          line: 3,
28902          column: 7,
28903        }),
28904      },
28905    );
28906
28907    custom_media_error_test(
28908      r#"
28909      @media (--not-defined) {
28910        .a {
28911          color: green;
28912        }
28913      }
28914      "#,
28915      Error {
28916        kind: MinifyErrorKind::CustomMediaNotDefined {
28917          name: "--not-defined".into(),
28918        },
28919        loc: Some(ErrorLocation {
28920          filename: "test.css".into(),
28921          line: 1,
28922          column: 7,
28923        }),
28924      },
28925    );
28926
28927    custom_media_error_test(
28928      r#"
28929      @custom-media --circular-mq-a (--circular-mq-b);
28930      @custom-media --circular-mq-b (--circular-mq-a);
28931
28932      @media (--circular-mq-a) {
28933        body {
28934          order: 3;
28935        }
28936      }
28937      "#,
28938      Error {
28939        kind: MinifyErrorKind::CircularCustomMedia {
28940          name: "--circular-mq-a".into(),
28941        },
28942        loc: Some(ErrorLocation {
28943          filename: "test.css".into(),
28944          line: 4,
28945          column: 7,
28946        }),
28947      },
28948    );
28949  }
28950
28951  #[test]
28952  fn test_dependencies() {
28953    fn dep_test(source: &str, expected: &str, deps: Vec<(&str, &str)>) {
28954      let mut stylesheet = StyleSheet::parse(
28955        &source,
28956        ParserOptions {
28957          filename: "test.css".into(),
28958          ..ParserOptions::default()
28959        },
28960      )
28961      .unwrap();
28962      stylesheet.minify(MinifyOptions::default()).unwrap();
28963      let res = stylesheet
28964        .to_css(PrinterOptions {
28965          analyze_dependencies: Some(Default::default()),
28966          minify: true,
28967          ..PrinterOptions::default()
28968        })
28969        .unwrap();
28970      assert_eq!(res.code, expected);
28971      let dependencies = res.dependencies.unwrap();
28972      assert_eq!(dependencies.len(), deps.len());
28973      for (i, (url, placeholder)) in deps.into_iter().enumerate() {
28974        match &dependencies[i] {
28975          Dependency::Url(dep) => {
28976            assert_eq!(dep.url, url);
28977            assert_eq!(dep.placeholder, placeholder);
28978          }
28979          Dependency::Import(dep) => {
28980            assert_eq!(dep.url, url);
28981            assert_eq!(dep.placeholder, placeholder);
28982          }
28983        }
28984      }
28985    }
28986
28987    fn dep_error_test(source: &str, error: PrinterErrorKind) {
28988      let stylesheet = StyleSheet::parse(&source, ParserOptions::default()).unwrap();
28989      let res = stylesheet.to_css(PrinterOptions {
28990        analyze_dependencies: Some(Default::default()),
28991        ..PrinterOptions::default()
28992      });
28993      match res {
28994        Err(e) => assert_eq!(e.kind, error),
28995        _ => unreachable!(),
28996      }
28997    }
28998
28999    dep_test(
29000      ".foo { background: image-set('./img12x.png', './img21x.png' 2x)}",
29001      ".foo{background:image-set(\"hXFI8W\" 1x,\"5TkpBa\" 2x)}",
29002      vec![("./img12x.png", "hXFI8W"), ("./img21x.png", "5TkpBa")],
29003    );
29004
29005    dep_test(
29006      ".foo { background: image-set(url(./img12x.png), url('./img21x.png') 2x)}",
29007      ".foo{background:image-set(\"hXFI8W\" 1x,\"5TkpBa\" 2x)}",
29008      vec![("./img12x.png", "hXFI8W"), ("./img21x.png", "5TkpBa")],
29009    );
29010
29011    dep_test(
29012      ".foo { --test: url(/foo.png) }",
29013      ".foo{--test:url(\"lDnnrG\")}",
29014      vec![("/foo.png", "lDnnrG")],
29015    );
29016
29017    dep_test(
29018      ".foo { --test: url(\"/foo.png\") }",
29019      ".foo{--test:url(\"lDnnrG\")}",
29020      vec![("/foo.png", "lDnnrG")],
29021    );
29022
29023    dep_test(
29024      ".foo { --test: url(\"http://example.com/foo.png\") }",
29025      ".foo{--test:url(\"3X1zSW\")}",
29026      vec![("http://example.com/foo.png", "3X1zSW")],
29027    );
29028
29029    dep_test(
29030      ".foo { --test: url(\"data:image/svg+xml;utf8,<svg></svg>\") }",
29031      ".foo{--test:url(\"-vl-rG\")}",
29032      vec![("data:image/svg+xml;utf8,<svg></svg>", "-vl-rG")],
29033    );
29034
29035    dep_test(
29036      ".foo { background: url(\"foo.png\") var(--test) }",
29037      ".foo{background:url(\"Vwkwkq\") var(--test)}",
29038      vec![("foo.png", "Vwkwkq")],
29039    );
29040
29041    dep_error_test(
29042      ".foo { --test: url(\"foo.png\") }",
29043      PrinterErrorKind::AmbiguousUrlInCustomProperty { url: "foo.png".into() },
29044    );
29045
29046    dep_error_test(
29047      ".foo { --test: url(foo.png) }",
29048      PrinterErrorKind::AmbiguousUrlInCustomProperty { url: "foo.png".into() },
29049    );
29050
29051    dep_error_test(
29052      ".foo { --test: url(./foo.png) }",
29053      PrinterErrorKind::AmbiguousUrlInCustomProperty {
29054        url: "./foo.png".into(),
29055      },
29056    );
29057
29058    dep_test(
29059      ".foo { behavior: url(#foo) }",
29060      ".foo{behavior:url(\"Zn9-2q\")}",
29061      vec![("#foo", "Zn9-2q")],
29062    );
29063
29064    dep_test(
29065      ".foo { --foo: url(#foo) }",
29066      ".foo{--foo:url(\"Zn9-2q\")}",
29067      vec![("#foo", "Zn9-2q")],
29068    );
29069
29070    dep_test(
29071      "@import \"test.css\"; .foo { color: red }",
29072      "@import \"hHsogW\";.foo{color:red}",
29073      vec![("test.css", "hHsogW")],
29074    );
29075  }
29076
29077  #[test]
29078  fn test_api() {
29079    let stylesheet = StyleSheet::parse(".foo:hover { color: red }", ParserOptions::default()).unwrap();
29080    match &stylesheet.rules.0[0] {
29081      CssRule::Style(s) => {
29082        assert_eq!(&s.selectors.to_string(), ".foo:hover");
29083      }
29084      _ => unreachable!(),
29085    }
29086
29087    let color = CssColor::parse_string("#f0f").unwrap();
29088    assert_eq!(color.to_css_string(PrinterOptions::default()).unwrap(), "#f0f");
29089
29090    let rule = CssRule::parse_string(".foo { color: red }", ParserOptions::default()).unwrap();
29091    assert_eq!(
29092      rule.to_css_string(PrinterOptions::default()).unwrap(),
29093      indoc! {r#"
29094    .foo {
29095      color: red;
29096    }"#}
29097    );
29098
29099    let property = Property::parse_string("color".into(), "#f0f", ParserOptions::default()).unwrap();
29100    assert_eq!(
29101      property.to_css_string(false, PrinterOptions::default()).unwrap(),
29102      "color: #f0f"
29103    );
29104    assert_eq!(
29105      property.to_css_string(true, PrinterOptions::default()).unwrap(),
29106      "color: #f0f !important"
29107    );
29108
29109    let code = indoc! { r#"
29110      .foo {
29111        color: green;
29112      }
29113
29114      .bar {
29115        color: red;
29116        background: pink;
29117      }
29118
29119      @media print {
29120        .baz {
29121          color: green;
29122        }
29123      }
29124    "#};
29125    let stylesheet = StyleSheet::parse(code, ParserOptions::default()).unwrap();
29126    if let CssRule::Style(style) = &stylesheet.rules.0[1] {
29127      let (key, val) = style.property_location(code, 0).unwrap();
29128      assert_eq!(
29129        key,
29130        SourceLocation { line: 5, column: 3 }..SourceLocation { line: 5, column: 8 }
29131      );
29132      assert_eq!(
29133        val,
29134        SourceLocation { line: 5, column: 10 }..SourceLocation { line: 5, column: 13 }
29135      );
29136    }
29137
29138    if let CssRule::Style(style) = &stylesheet.rules.0[1] {
29139      let (key, val) = style.property_location(code, 1).unwrap();
29140      assert_eq!(
29141        key,
29142        SourceLocation { line: 6, column: 3 }..SourceLocation { line: 6, column: 13 }
29143      );
29144      assert_eq!(
29145        val,
29146        SourceLocation { line: 6, column: 15 }..SourceLocation { line: 6, column: 19 }
29147      );
29148    }
29149    if let CssRule::Media(media) = &stylesheet.rules.0[2] {
29150      if let CssRule::Style(style) = &media.rules.0[0] {
29151        let (key, val) = style.property_location(code, 0).unwrap();
29152        assert_eq!(
29153          key,
29154          SourceLocation { line: 11, column: 5 }..SourceLocation { line: 11, column: 10 }
29155        );
29156        assert_eq!(
29157          val,
29158          SourceLocation { line: 11, column: 12 }..SourceLocation { line: 11, column: 17 }
29159        );
29160      }
29161    }
29162
29163    let mut property = Property::Transform(Default::default(), VendorPrefix::WebKit);
29164    property.set_prefix(VendorPrefix::None);
29165    assert_eq!(property, Property::Transform(Default::default(), VendorPrefix::None));
29166    property.set_prefix(VendorPrefix::Moz);
29167    assert_eq!(property, Property::Transform(Default::default(), VendorPrefix::Moz));
29168    property.set_prefix(VendorPrefix::WebKit | VendorPrefix::Moz);
29169    assert_eq!(
29170      property,
29171      Property::Transform(Default::default(), VendorPrefix::WebKit | VendorPrefix::Moz)
29172    );
29173
29174    let mut property = Property::TextDecorationLine(Default::default(), VendorPrefix::None);
29175    property.set_prefix(VendorPrefix::Ms);
29176    assert_eq!(
29177      property,
29178      Property::TextDecorationLine(Default::default(), VendorPrefix::None)
29179    );
29180    property.set_prefix(VendorPrefix::WebKit | VendorPrefix::Moz | VendorPrefix::Ms);
29181    assert_eq!(
29182      property,
29183      Property::TextDecorationLine(Default::default(), VendorPrefix::WebKit | VendorPrefix::Moz)
29184    );
29185
29186    let mut property = Property::AccentColor(Default::default());
29187    property.set_prefix(VendorPrefix::WebKit);
29188    assert_eq!(property, Property::AccentColor(Default::default()));
29189  }
29190
29191  #[cfg(feature = "substitute_variables")]
29192  #[test]
29193  fn test_substitute_vars() {
29194    use crate::properties::custom::TokenList;
29195    use crate::traits::ParseWithOptions;
29196
29197    fn test(property: Property, vars: HashMap<&str, &str>, expected: &str) {
29198      if let Property::Unparsed(unparsed) = property {
29199        let vars = vars
29200          .into_iter()
29201          .map(|(k, v)| {
29202            (
29203              k,
29204              TokenList::parse_string_with_options(v, ParserOptions::default()).unwrap(),
29205            )
29206          })
29207          .collect();
29208        let substituted = unparsed.substitute_variables(&vars).unwrap();
29209        assert_eq!(
29210          substituted.to_css_string(false, PrinterOptions::default()).unwrap(),
29211          expected
29212        );
29213      } else {
29214        panic!("Not an unparsed property");
29215      }
29216    }
29217
29218    let property = Property::parse_string("color".into(), "var(--test)", ParserOptions::default()).unwrap();
29219    test(property, HashMap::from([("--test", "yellow")]), "color: #ff0");
29220
29221    let property =
29222      Property::parse_string("color".into(), "var(--test, var(--foo))", ParserOptions::default()).unwrap();
29223    test(property, HashMap::from([("--foo", "yellow")]), "color: #ff0");
29224    let property = Property::parse_string(
29225      "color".into(),
29226      "var(--test, var(--foo, yellow))",
29227      ParserOptions::default(),
29228    )
29229    .unwrap();
29230    test(property, HashMap::new(), "color: #ff0");
29231
29232    let property =
29233      Property::parse_string("width".into(), "calc(var(--a) + var(--b))", ParserOptions::default()).unwrap();
29234    test(property, HashMap::from([("--a", "2px"), ("--b", "4px")]), "width: 6px");
29235
29236    let property = Property::parse_string("color".into(), "var(--a)", ParserOptions::default()).unwrap();
29237    test(
29238      property,
29239      HashMap::from([("--a", "var(--b)"), ("--b", "yellow")]),
29240      "color: #ff0",
29241    );
29242
29243    let property = Property::parse_string("color".into(), "var(--a)", ParserOptions::default()).unwrap();
29244    test(
29245      property,
29246      HashMap::from([("--a", "var(--b)"), ("--b", "var(--c)"), ("--c", "var(--a)")]),
29247      "color: var(--a)",
29248    );
29249  }
29250
29251  #[test]
29252  fn test_layer() {
29253    minify_test("@layer foo;", "@layer foo;");
29254    minify_test("@layer foo, bar;", "@layer foo,bar;");
29255    minify_test("@layer foo.bar;", "@layer foo.bar;");
29256    minify_test("@layer foo.bar, baz;", "@layer foo.bar,baz;");
29257
29258    minify_test(
29259      r#"
29260      @layer foo {
29261        .bar {
29262          color: red;
29263        }
29264      }
29265    "#,
29266      "@layer foo{.bar{color:red}}",
29267    );
29268    minify_test(
29269      r#"
29270      @layer foo.bar {
29271        .bar {
29272          color: red;
29273        }
29274      }
29275    "#,
29276      "@layer foo.bar{.bar{color:red}}",
29277    );
29278    minify_test(r#"
29279      @layer base {
29280        p { max-width: 70ch; }
29281      }
29282
29283      @layer framework {
29284        @layer base {
29285          p { margin-block: 0.75em; }
29286        }
29287
29288        @layer theme {
29289          p { color: #222; }
29290        }
29291      }
29292    "#, "@layer base{p{max-width:70ch}}@layer framework{@layer base{p{margin-block:.75em}}@layer theme{p{color:#222}}}");
29293    minify_test(
29294      r#"
29295      @layer {
29296        .bar {
29297          color: red;
29298        }
29299      }
29300    "#,
29301      "@layer{.bar{color:red}}",
29302    );
29303    minify_test(
29304      r#"
29305      @layer foo\20 bar, baz;
29306    "#,
29307      "@layer foo\\ bar,baz;",
29308    );
29309    minify_test(
29310      r#"
29311      @layer one.two\20 three\#four\.five {
29312        .bar {
29313          color: red;
29314        }
29315      }
29316    "#,
29317      "@layer one.two\\ three\\#four\\.five{.bar{color:red}}",
29318    );
29319
29320    error_test("@layer;", ParserError::UnexpectedToken(Token::Semicolon));
29321    error_test("@layer foo, bar {};", ParserError::AtRuleBodyInvalid);
29322    minify_test("@import 'test.css' layer;", "@import \"test.css\" layer;");
29323    minify_test("@import 'test.css' layer(foo);", "@import \"test.css\" layer(foo);");
29324    minify_test(
29325      "@import 'test.css' layer(foo.bar);",
29326      "@import \"test.css\" layer(foo.bar);",
29327    );
29328    minify_test(
29329      "@import 'test.css' layer(foo\\20 bar);",
29330      "@import \"test.css\" layer(foo\\ bar);",
29331    );
29332    error_test(
29333      "@import 'test.css' layer(foo, bar) {};",
29334      ParserError::UnexpectedToken(Token::Comma),
29335    );
29336    minify_test(
29337      r#"
29338      @layer one {
29339        body {
29340          background: red;
29341        }
29342      }
29343
29344      body {
29345        background: red;
29346      }
29347
29348      @layer two {
29349        body {
29350          background: green;
29351        }
29352      }
29353
29354      @layer one {
29355        body {
29356          background: yellow;
29357        }
29358      }
29359      "#,
29360      "@layer one{body{background:#ff0}}body{background:red}@layer two{body{background:green}}",
29361    );
29362  }
29363
29364  #[test]
29365  fn test_property() {
29366    minify_test(
29367      r#"
29368      @property --property-name {
29369        syntax: '<color>';
29370        inherits: false;
29371        initial-value: yellow;
29372      }
29373    "#,
29374      "@property --property-name{syntax:\"<color>\";inherits:false;initial-value:#ff0}",
29375    );
29376
29377    test(
29378      r#"
29379      @property --property-name {
29380        syntax: '*';
29381        inherits: false;
29382        initial-value: ;
29383      }
29384    "#,
29385      indoc! {r#"
29386      @property --property-name {
29387        syntax: "*";
29388        inherits: false;
29389        initial-value: ;
29390      }
29391    "#},
29392    );
29393
29394    minify_test(
29395      r#"
29396      @property --property-name {
29397        syntax: '*';
29398        inherits: false;
29399        initial-value: ;
29400      }
29401    "#,
29402      "@property --property-name{syntax:\"*\";inherits:false;initial-value:}",
29403    );
29404
29405    test(
29406      r#"
29407      @property --property-name {
29408        syntax: '*';
29409        inherits: false;
29410        initial-value:;
29411      }
29412    "#,
29413      indoc! {r#"
29414      @property --property-name {
29415        syntax: "*";
29416        inherits: false;
29417        initial-value: ;
29418      }
29419    "#},
29420    );
29421
29422    minify_test(
29423      r#"
29424      @property --property-name {
29425        syntax: '*';
29426        inherits: false;
29427        initial-value:;
29428      }
29429    "#,
29430      "@property --property-name{syntax:\"*\";inherits:false;initial-value:}",
29431    );
29432    minify_test(
29433      r#"
29434      @property --property-name {
29435        syntax: '*';
29436        inherits: false;
29437        initial-value: foo bar;
29438      }
29439    "#,
29440      "@property --property-name{syntax:\"*\";inherits:false;initial-value:foo bar}",
29441    );
29442
29443    minify_test(
29444      r#"
29445      @property --property-name {
29446        syntax: '<length>';
29447        inherits: true;
29448        initial-value: 25px;
29449      }
29450    "#,
29451      "@property --property-name{syntax:\"<length>\";inherits:true;initial-value:25px}",
29452    );
29453
29454    minify_test(
29455      r#"
29456      @property --property-name {
29457        syntax: '<string>';
29458        inherits: true;
29459        initial-value: "hi";
29460      }
29461    "#,
29462      "@property --property-name{syntax:\"<string>\";inherits:true;initial-value:\"hi\"}",
29463    );
29464
29465    error_test(
29466      r#"
29467      @property --property-name {
29468        syntax: '<color>';
29469        inherits: false;
29470        initial-value: 25px;
29471      }
29472    "#,
29473      ParserError::UnexpectedToken(crate::properties::custom::Token::Dimension {
29474        has_sign: false,
29475        value: 25.0,
29476        int_value: Some(25),
29477        unit: "px".into(),
29478      }),
29479    );
29480
29481    error_test(
29482      r#"
29483      @property --property-name {
29484        syntax: '<length>';
29485        inherits: false;
29486        initial-value: var(--some-value);
29487      }
29488    "#,
29489      ParserError::UnexpectedToken(crate::properties::custom::Token::Function("var".into())),
29490    );
29491
29492    error_test(
29493      r#"
29494      @property --property-name {
29495        syntax: '<color>';
29496        inherits: false;
29497      }
29498    "#,
29499      ParserError::AtRuleBodyInvalid,
29500    );
29501
29502    minify_test(
29503      r#"
29504      @property --property-name {
29505        syntax: '*';
29506        inherits: false;
29507      }
29508    "#,
29509      "@property --property-name{syntax:\"*\";inherits:false}",
29510    );
29511
29512    error_test(
29513      r#"
29514      @property --property-name {
29515        syntax: '*';
29516      }
29517    "#,
29518      ParserError::AtRuleBodyInvalid,
29519    );
29520
29521    error_test(
29522      r#"
29523      @property --property-name {
29524        inherits: false;
29525      }
29526    "#,
29527      ParserError::AtRuleBodyInvalid,
29528    );
29529
29530    error_test(
29531      r#"
29532      @property property-name {
29533        syntax: '*';
29534        inherits: false;
29535      }
29536    "#,
29537      ParserError::UnexpectedToken(crate::properties::custom::Token::Ident("property-name".into())),
29538    );
29539
29540    minify_test(
29541      r#"
29542      @property --property-name {
29543        syntax: 'custom | <color>';
29544        inherits: false;
29545        initial-value: yellow;
29546      }
29547    "#,
29548      "@property --property-name{syntax:\"custom|<color>\";inherits:false;initial-value:#ff0}",
29549    );
29550
29551    // TODO: Re-enable with a better solution
29552    //       See: https://github.com/parcel-bundler/lightningcss/issues/288
29553    // minify_test(r#"
29554    //   @property --property-name {
29555    //     syntax: '<transform-list>';
29556    //     inherits: false;
29557    //     initial-value: translate(200px,300px) translate(100px,200px) scale(2);
29558    //   }
29559    // "#, "@property --property-name{syntax:\"<transform-list>\";inherits:false;initial-value:matrix(2,0,0,2,300,500)}");
29560
29561    minify_test(
29562      r#"
29563      @property --property-name {
29564        syntax: '<time>';
29565        inherits: false;
29566        initial-value: 1000ms;
29567      }
29568    "#,
29569      "@property --property-name{syntax:\"<time>\";inherits:false;initial-value:1s}",
29570    );
29571
29572    minify_test(
29573      r#"
29574      @property --property-name {
29575        syntax: '<url>';
29576        inherits: false;
29577        initial-value: url("foo.png");
29578      }
29579    "#,
29580      "@property --property-name{syntax:\"<url>\";inherits:false;initial-value:url(foo.png)}",
29581    );
29582
29583    minify_test(
29584      r#"
29585      @property --property-name {
29586        syntax: '<image>';
29587        inherits: false;
29588        initial-value: linear-gradient(yellow, blue);
29589      }
29590    "#,
29591      "@property --property-name{syntax:\"<image>\";inherits:false;initial-value:linear-gradient(#ff0,#00f)}",
29592    );
29593
29594    minify_test(
29595      r#"
29596      @property --property-name {
29597        initial-value: linear-gradient(yellow, blue);
29598        inherits: false;
29599        syntax: '<image>';
29600      }
29601    "#,
29602      "@property --property-name{syntax:\"<image>\";inherits:false;initial-value:linear-gradient(#ff0,#00f)}",
29603    );
29604
29605    test(
29606      r#"
29607      @property --property-name {
29608        syntax: '<length>|none';
29609        inherits: false;
29610        initial-value: none;
29611      }
29612    "#,
29613      indoc! {r#"
29614      @property --property-name {
29615        syntax: "<length> | none";
29616        inherits: false;
29617        initial-value: none;
29618      }
29619    "#},
29620    );
29621
29622    minify_test(
29623      r#"
29624      @property --property-name {
29625        syntax: '<color>#';
29626        inherits: false;
29627        initial-value: yellow, blue;
29628      }
29629    "#,
29630      "@property --property-name{syntax:\"<color>#\";inherits:false;initial-value:#ff0,#00f}",
29631    );
29632    minify_test(
29633      r#"
29634      @property --property-name {
29635        syntax: '<color>+';
29636        inherits: false;
29637        initial-value: yellow blue;
29638      }
29639    "#,
29640      "@property --property-name{syntax:\"<color>+\";inherits:false;initial-value:#ff0 #00f}",
29641    );
29642    minify_test(
29643      r#"
29644      @property --property-name {
29645        syntax: '<color>';
29646        inherits: false;
29647        initial-value: yellow;
29648      }
29649      .foo {
29650        color: var(--property-name)
29651      }
29652      @property --property-name {
29653        syntax: '<color>';
29654        inherits: true;
29655        initial-value: blue;
29656      }
29657    "#,
29658      "@property --property-name{syntax:\"<color>\";inherits:true;initial-value:#00f}.foo{color:var(--property-name)}",
29659    );
29660
29661    test(
29662      r#"
29663      @media (width < 800px) {
29664        @property --property-name {
29665          syntax: '*';
29666          inherits: false;
29667        }
29668      }
29669    "#,
29670      indoc! {r#"
29671        @media (width < 800px) {
29672          @property --property-name {
29673            syntax: "*";
29674            inherits: false
29675          }
29676        }
29677    "#},
29678    );
29679
29680    test(
29681      r#"
29682      @layer foo {
29683        @property --property-name {
29684          syntax: '*';
29685          inherits: false;
29686        }
29687      }
29688    "#,
29689      indoc! {r#"
29690        @layer foo {
29691          @property --property-name {
29692            syntax: "*";
29693            inherits: false
29694          }
29695        }
29696    "#},
29697    );
29698  }
29699
29700  #[test]
29701  fn test_quoting_unquoting_urls() {
29702    // Quotes remain double quotes when not minifying
29703    test(
29704      r#".foo {
29705      background-image: url("0123abcd");
29706    }"#,
29707      r#".foo {
29708  background-image: url("0123abcd");
29709}
29710"#,
29711    );
29712
29713    // Quotes removed when minifying
29714    minify_test(
29715      r#".foo {
29716      background-image: url("0123abcd");
29717    }"#,
29718      r#".foo{background-image:url(0123abcd)}"#,
29719    );
29720
29721    // Doubles quotes added if not present when not minifying
29722    test(
29723      r#".foo {
29724      background-image: url(0123abcd);
29725    }"#,
29726      r#".foo {
29727  background-image: url("0123abcd");
29728}
29729"#,
29730    );
29731
29732    // No quotes changed if not present when not minifying
29733    minify_test(
29734      r#".foo {
29735      background-image: url(0123abcd);
29736    }"#,
29737      r#".foo{background-image:url(0123abcd)}"#,
29738    );
29739  }
29740
29741  #[test]
29742  fn test_zindex() {
29743    minify_test(".foo { z-index: 2 }", ".foo{z-index:2}");
29744    minify_test(".foo { z-index: -2 }", ".foo{z-index:-2}");
29745    minify_test(".foo { z-index: 999999 }", ".foo{z-index:999999}");
29746    minify_test(".foo { z-index: 9999999 }", ".foo{z-index:9999999}");
29747    minify_test(".foo { z-index: -9999999 }", ".foo{z-index:-9999999}");
29748  }
29749
29750  #[test]
29751  #[cfg(feature = "sourcemap")]
29752  fn test_input_source_map() {
29753    let source = r#".imported {
29754      content: "yay, file support!";
29755    }
29756
29757    .selector {
29758      margin: 1em;
29759      background-color: #f60;
29760    }
29761
29762    .selector .nested {
29763      margin: 0.5em;
29764    }
29765
29766    /*# sourceMappingURL=data:application/json;base64,ewoJInZlcnNpb24iOiAzLAoJInNvdXJjZVJvb3QiOiAicm9vdCIsCgkiZmlsZSI6ICJzdGRvdXQiLAoJInNvdXJjZXMiOiBbCgkJInN0ZGluIiwKCQkic2Fzcy9fdmFyaWFibGVzLnNjc3MiLAoJCSJzYXNzL19kZW1vLnNjc3MiCgldLAoJInNvdXJjZXNDb250ZW50IjogWwoJCSJAaW1wb3J0IFwiX3ZhcmlhYmxlc1wiO1xuQGltcG9ydCBcIl9kZW1vXCI7XG5cbi5zZWxlY3RvciB7XG4gIG1hcmdpbjogJHNpemU7XG4gIGJhY2tncm91bmQtY29sb3I6ICRicmFuZENvbG9yO1xuXG4gIC5uZXN0ZWQge1xuICAgIG1hcmdpbjogJHNpemUgLyAyO1xuICB9XG59IiwKCQkiJGJyYW5kQ29sb3I6ICNmNjA7XG4kc2l6ZTogMWVtOyIsCgkJIi5pbXBvcnRlZCB7XG4gIGNvbnRlbnQ6IFwieWF5LCBmaWxlIHN1cHBvcnQhXCI7XG59IgoJXSwKCSJtYXBwaW5ncyI6ICJBRUFBLFNBQVMsQ0FBQztFQUNSLE9BQU8sRUFBRSxvQkFBcUI7Q0FDL0I7O0FGQ0QsU0FBUyxDQUFDO0VBQ1IsTUFBTSxFQ0hELEdBQUc7RURJUixnQkFBZ0IsRUNMTCxJQUFJO0NEVWhCOztBQVBELFNBQVMsQ0FJUCxPQUFPLENBQUM7RUFDTixNQUFNLEVDUEgsS0FBRztDRFFQIiwKCSJuYW1lcyI6IFtdCn0= */"#;
29767
29768    let mut stylesheet = StyleSheet::parse(&source, ParserOptions::default()).unwrap();
29769    stylesheet.minify(MinifyOptions::default()).unwrap();
29770    let mut sm = parcel_sourcemap::SourceMap::new("/");
29771    stylesheet
29772      .to_css(PrinterOptions {
29773        source_map: Some(&mut sm),
29774        minify: true,
29775        ..PrinterOptions::default()
29776      })
29777      .unwrap();
29778    let map = sm.to_json(None).unwrap();
29779    assert_eq!(
29780      map,
29781      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":[]}"#
29782    );
29783  }
29784
29785  #[test]
29786  #[cfg(feature = "sourcemap")]
29787  fn test_source_maps_with_license_comments() {
29788    let source = r#"/*! a single line comment */
29789    /*!
29790      a comment
29791      containing
29792      multiple
29793      lines
29794    */
29795    .a {
29796      display: flex;
29797    }
29798
29799    .b {
29800      display: hidden;
29801    }
29802    "#;
29803
29804    let mut sm = parcel_sourcemap::SourceMap::new("/");
29805    let source_index = sm.add_source("input.css");
29806    sm.set_source_content(source_index as usize, source).unwrap();
29807
29808    let mut stylesheet = StyleSheet::parse(
29809      &source,
29810      ParserOptions {
29811        source_index,
29812        ..Default::default()
29813      },
29814    )
29815    .unwrap();
29816    stylesheet.minify(MinifyOptions::default()).unwrap();
29817    stylesheet
29818      .to_css(PrinterOptions {
29819        source_map: Some(&mut sm),
29820        minify: true,
29821        ..PrinterOptions::default()
29822      })
29823      .unwrap();
29824    let map = sm.to_json(None).unwrap();
29825    assert_eq!(
29826      map,
29827      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":[]}"#
29828    );
29829  }
29830
29831  #[test]
29832  fn test_error_recovery() {
29833    use std::sync::{Arc, RwLock};
29834    let warnings = Some(Arc::new(RwLock::new(Vec::new())));
29835    test_with_options(
29836      r#"
29837      h1(>h1) {
29838        color: red;
29839      }
29840
29841      .foo {
29842        color: red;
29843      }
29844
29845      .clearfix {
29846        *zoom: 1;
29847        background: red;
29848      }
29849
29850      @media (hover) {
29851        h1(>h1) {
29852          color: red;
29853        }
29854
29855        .bar {
29856          color: red;
29857        }
29858      }
29859
29860      input:placeholder {
29861        color: red;
29862      }
29863
29864      input::hover {
29865        color: red;
29866      }
29867    "#,
29868      indoc! { r#"
29869      .foo {
29870        color: red;
29871      }
29872
29873      .clearfix {
29874        background: red;
29875      }
29876
29877      @media (hover) {
29878        .bar {
29879          color: red;
29880        }
29881      }
29882
29883      input:placeholder {
29884        color: red;
29885      }
29886
29887      input::hover {
29888        color: red;
29889      }
29890    "#},
29891      ParserOptions {
29892        filename: "test.css".into(),
29893        error_recovery: true,
29894        warnings: warnings.clone(),
29895        ..ParserOptions::default()
29896      },
29897    );
29898    let w = warnings.unwrap();
29899    let warnings = w.read().unwrap();
29900    assert_eq!(
29901      *warnings,
29902      vec![
29903        Error {
29904          kind: ParserError::SelectorError(SelectorError::EmptySelector),
29905          loc: Some(ErrorLocation {
29906            filename: "test.css".into(),
29907            line: 1,
29908            column: 7
29909          })
29910        },
29911        Error {
29912          kind: ParserError::UnexpectedToken(Token::Semicolon),
29913          loc: Some(ErrorLocation {
29914            filename: "test.css".into(),
29915            line: 10,
29916            column: 17
29917          })
29918        },
29919        Error {
29920          kind: ParserError::SelectorError(SelectorError::EmptySelector),
29921          loc: Some(ErrorLocation {
29922            filename: "test.css".into(),
29923            line: 15,
29924            column: 9
29925          })
29926        },
29927        Error {
29928          kind: ParserError::SelectorError(SelectorError::UnsupportedPseudoClass("placeholder".into())),
29929          loc: Some(ErrorLocation {
29930            filename: "test.css".into(),
29931            line: 24,
29932            column: 13,
29933          }),
29934        },
29935        Error {
29936          kind: ParserError::SelectorError(SelectorError::UnsupportedPseudoElement("hover".into())),
29937          loc: Some(ErrorLocation {
29938            filename: "test.css".into(),
29939            line: 28,
29940            column: 13,
29941          }),
29942        },
29943      ]
29944    )
29945  }
29946
29947  #[test]
29948  fn test_invalid() {
29949    error_test(
29950      ".a{color: hsla(120, 62.32%;}",
29951      ParserError::UnexpectedToken(Token::CloseCurlyBracket),
29952    );
29953    error_test(
29954      ".a{--foo: url(foo\\) b\\)ar)}",
29955      ParserError::UnexpectedToken(Token::BadUrl("foo\\) b\\)ar".into())),
29956    );
29957  }
29958
29959  #[test]
29960  fn test_container_queries() {
29961    // name only (no condition) - new syntax
29962    minify_test(
29963      r#"
29964      @container foo {
29965        .inner {
29966          background: green;
29967        }
29968      }
29969    "#,
29970      "@container foo{.inner{background:green}}",
29971    );
29972
29973    // with name
29974    minify_test(
29975      r#"
29976      @container my-layout (inline-size > 45em) {
29977        .foo {
29978          color: red;
29979        }
29980      }
29981    "#,
29982      "@container my-layout (inline-size>45em){.foo{color:red}}",
29983    );
29984
29985    minify_test(
29986      r#"
29987      @container my-layout ( not (width > 500px) ) {
29988        .foo {
29989          color: red;
29990        }
29991      }
29992    "#,
29993      "@container my-layout not (width>500px){.foo{color:red}}",
29994    );
29995
29996    minify_test(
29997      r#"
29998      @container my-layout not (width > 500px) {
29999        .foo {
30000          color: red;
30001        }
30002      }
30003    "#,
30004      "@container my-layout not (width>500px){.foo{color:red}}",
30005    );
30006
30007    minify_test(
30008      r#"
30009      @container not (width > 500px) {
30010        .foo {
30011          color: red;
30012        }
30013      }
30014    "#,
30015      "@container not (width>500px){.foo{color:red}}",
30016    );
30017
30018    minify_test(
30019      r#"
30020      @container my-layout ((width: 100px) and (not (height: 100px))) {
30021        .foo {
30022          color: red;
30023        }
30024      }
30025    "#,
30026      "@container my-layout (width:100px) and (not (height:100px)){.foo{color:red}}",
30027    );
30028
30029    minify_test(
30030      r#"
30031      @container my-layout (width = max(10px, 10em)) {
30032        .foo {
30033          color: red;
30034        }
30035      }
30036    "#,
30037      "@container my-layout (width=max(10px,10em)){.foo{color:red}}",
30038    );
30039
30040    // without name
30041    minify_test(
30042      r#"
30043      @container (inline-size > 45em) {
30044        .foo {
30045          color: red;
30046        }
30047      }
30048    "#,
30049      "@container (inline-size>45em){.foo{color:red}}",
30050    );
30051
30052    minify_test(
30053      r#"
30054      @container (inline-size > 45em) and (inline-size < 100em) {
30055        .foo {
30056          color: red;
30057        }
30058      }
30059    "#,
30060      "@container (inline-size>45em) and (inline-size<100em){.foo{color:red}}",
30061    );
30062
30063    // calc()
30064    minify_test(
30065      r#"
30066      @container (width > calc(100vw - 50px)) {
30067        .foo {
30068          color: red;
30069        }
30070      }
30071    "#,
30072      "@container (width>calc(100vw - 50px)){.foo{color:red}}",
30073    );
30074
30075    minify_test(
30076      r#"
30077      @container (calc(100vh - 50px) <= height ) {
30078        .foo {
30079          color: red;
30080        }
30081      }
30082    "#,
30083      "@container (height>=calc(100vh - 50px)){.foo{color:red}}",
30084    );
30085
30086    // merge adjacent
30087    minify_test(
30088      r#"
30089      @container my-layout (inline-size > 45em) {
30090        .foo {
30091          color: red;
30092        }
30093      }
30094
30095      @container my-layout (inline-size > 45em) {
30096        .foo {
30097          background: yellow;
30098        }
30099
30100        .bar {
30101          color: white;
30102        }
30103      }
30104    "#,
30105      "@container my-layout (inline-size>45em){.foo{color:red;background:#ff0}.bar{color:#fff}}",
30106    );
30107
30108    minify_test(
30109      r#"
30110    .foo {
30111      container-name: foo bar;
30112      container-type: size;
30113    }
30114    "#,
30115      ".foo{container:foo bar/size}",
30116    );
30117    minify_test(
30118      r#"
30119    .foo {
30120      container-name: foo bar;
30121      container-type: normal;
30122    }
30123    "#,
30124      ".foo{container:foo bar}",
30125    );
30126    minify_test(
30127      ".foo{ container-type: inline-size }",
30128      ".foo{container-type:inline-size}",
30129    );
30130    minify_test(".foo{ container-name: none; }", ".foo{container-name:none}");
30131    minify_test(".foo{ container-name: foo; }", ".foo{container-name:foo}");
30132    minify_test(".foo{ container: foo / normal; }", ".foo{container:foo}");
30133    minify_test(
30134      ".foo{ container: foo / inline-size; }",
30135      ".foo{container:foo/inline-size}",
30136    );
30137    minify_test(".foo { width: calc(1cqw + 2cqw) }", ".foo{width:3cqw}");
30138    minify_test(".foo { width: calc(1cqh + 2cqh) }", ".foo{width:3cqh}");
30139    minify_test(".foo { width: calc(1cqi + 2cqi) }", ".foo{width:3cqi}");
30140    minify_test(".foo { width: calc(1cqb + 2cqb) }", ".foo{width:3cqb}");
30141    minify_test(".foo { width: calc(1cqmin + 2cqmin) }", ".foo{width:3cqmin}");
30142    minify_test(".foo { width: calc(1cqmax + 2cqmax) }", ".foo{width:3cqmax}");
30143
30144    // Unlike in @media, there is no need to convert the range syntax in @container,
30145    // because browsers all support this syntax.
30146    prefix_test(
30147      r#"
30148      @container (width > 100px) {
30149        .foo { padding: 5px; }
30150      }
30151      "#,
30152      indoc! { r#"
30153        @container (width > 100px) {
30154          .foo {
30155            padding: 5px;
30156          }
30157        }
30158      "#},
30159      Browsers {
30160        chrome: Some(105 << 16),
30161        ..Browsers::default()
30162      },
30163    );
30164    prefix_test(
30165      r#"
30166      @container (min-width: 100px) {
30167        .foo { padding: 5px; }
30168      }
30169      "#,
30170      indoc! { r#"
30171        @container (width >= 100px) {
30172          .foo {
30173            padding: 5px;
30174          }
30175        }
30176      "#},
30177      Browsers {
30178        chrome: Some(105 << 16),
30179        ..Browsers::default()
30180      },
30181    );
30182
30183    minify_test(
30184      r#"
30185      @container style(--responsive: true) {
30186        .foo {
30187          color: red;
30188        }
30189      }
30190    "#,
30191      "@container style(--responsive:true){.foo{color:red}}",
30192    );
30193    minify_test(
30194      r#"
30195      @container style(--responsive: true) and style(color: yellow) {
30196        .foo {
30197          color: red;
30198        }
30199      }
30200    "#,
30201      "@container style(--responsive:true) and style(color:#ff0){.foo{color:red}}",
30202    );
30203    minify_test(
30204      r#"
30205      @container not style(--responsive: true) {
30206        .foo {
30207          color: red;
30208        }
30209      }
30210    "#,
30211      "@container not style(--responsive:true){.foo{color:red}}",
30212    );
30213    minify_test(
30214      r#"
30215      @container (inline-size > 45em) and style(--responsive: true) {
30216        .foo {
30217          color: red;
30218        }
30219      }
30220    "#,
30221      "@container (inline-size>45em) and style(--responsive:true){.foo{color:red}}",
30222    );
30223    minify_test(
30224      r#"
30225      @container style((accent-color: yellow) or (--bar: 10px)) {
30226        .foo {
30227          color: red;
30228        }
30229      }
30230    "#,
30231      "@container style((accent-color:#ff0) or (--bar:10px)){.foo{color:red}}",
30232    );
30233    minify_test(
30234      r#"
30235      @container style(not ((width: calc(10px + 20px)) and ((--bar: url(x))))) {
30236        .foo {
30237          color: red;
30238        }
30239      }
30240    "#,
30241      "@container style(not ((width:30px) and (--bar:url(x)))){.foo{color:red}}",
30242    );
30243    minify_test(
30244      r#"
30245      @container style(color: yellow !important) {
30246        .foo {
30247          color: red;
30248        }
30249      }
30250    "#,
30251      "@container style(color:yellow){.foo{color:red}}",
30252    );
30253    minify_test(
30254      r#"
30255      @container style(--foo:) {
30256        .foo {
30257          color: red;
30258        }
30259      }
30260    "#,
30261      "@container style(--foo:){.foo{color:red}}",
30262    );
30263    minify_test(
30264      r#"
30265      @container style(--foo: ) {
30266        .foo {
30267          color: red;
30268        }
30269      }
30270    "#,
30271      "@container style(--foo:){.foo{color:red}}",
30272    );
30273    minify_test(
30274      r#"
30275      @container style(--my-prop: foo - bar ()) {
30276        .foo {
30277          color: red;
30278        }
30279      }
30280    "#,
30281      "@container style(--my-prop:foo - bar ()){.foo{color:red}}",
30282    );
30283    minify_test(
30284      r#"
30285      @container style(--test) {
30286        .foo {
30287          color: red;
30288        }
30289      }
30290    "#,
30291      "@container style(--test){.foo{color:red}}",
30292    );
30293    minify_test(
30294      r#"
30295      @container style(width) {
30296        .foo {
30297          color: red;
30298        }
30299      }
30300    "#,
30301      "@container style(width){.foo{color:red}}",
30302    );
30303    minify_test(
30304      r#"
30305      @container scroll-state(scrollable: top) {
30306        .foo {
30307          color: red;
30308        }
30309      }
30310    "#,
30311      "@container scroll-state(scrollable:top){.foo{color:red}}",
30312    );
30313    minify_test(
30314      r#"
30315      @container scroll-state((stuck: top) and (stuck: left)) {
30316        .foo {
30317          color: red;
30318        }
30319      }
30320    "#,
30321      "@container scroll-state((stuck:top) and (stuck:left)){.foo{color:red}}",
30322    );
30323    minify_test(
30324      r#"
30325      @container scroll-state(not ((scrollable: bottom) and (scrollable: right))) {
30326        .foo {
30327          color: red;
30328        }
30329      }
30330    "#,
30331      "@container scroll-state(not ((scrollable:bottom) and (scrollable:right))){.foo{color:red}}",
30332    );
30333    minify_test(
30334      r#"
30335      @container (scroll-state(scrollable: inline-end)) {
30336        .foo {
30337          color: red;
30338        }
30339      }
30340    "#,
30341      "@container scroll-state(scrollable:inline-end){.foo{color:red}}",
30342    );
30343    minify_test(
30344      r#"
30345      @container not scroll-state(scrollable: top) {
30346        .foo {
30347          color: red;
30348        }
30349      }
30350    "#,
30351      "@container not scroll-state(scrollable:top){.foo{color:red}}",
30352    );
30353
30354    // Disallow 'none', 'not', 'and', 'or' as a `<container-name>`
30355    // https://github.com/w3c/csswg-drafts/issues/7203#issuecomment-1144257312
30356    // https://chromium-review.googlesource.com/c/chromium/src/+/3698402
30357    error_test(
30358      "@container none (width < 100vw) {}",
30359      ParserError::UnexpectedToken(crate::properties::custom::Token::Ident("none".into())),
30360    );
30361
30362    error_test(
30363      "@container and (width < 100vw) {}",
30364      ParserError::UnexpectedToken(crate::properties::custom::Token::Ident("and".into())),
30365    );
30366
30367    error_test(
30368      "@container or (width < 100vw) {}",
30369      ParserError::UnexpectedToken(crate::properties::custom::Token::Ident("or".into())),
30370    );
30371
30372    // Disallow CSS wide keywords as a `<container-name>`
30373    error_test(
30374      "@container revert-layer (width < 100vw) {}",
30375      ParserError::UnexpectedToken(crate::properties::custom::Token::Ident("revert-layer".into())),
30376    );
30377
30378    error_test(
30379      "@container initial (width < 100vw) {}",
30380      ParserError::UnexpectedToken(crate::properties::custom::Token::Ident("initial".into())),
30381    );
30382
30383    // <ident> contains spaces
30384    // https://github.com/web-platform-tests/wpt/blob/39f0da08fbbe33d0582a35749b6dbf8bd067a52d/css/css-contain/container-queries/at-container-parsing.html#L160-L178
30385    error_test(
30386      "@container foo bar (width < 100vw) {}",
30387      ParserError::UnexpectedToken(crate::properties::custom::Token::Ident("bar".into())),
30388    );
30389
30390    error_test("@container (inline-size <= foo) {}", ParserError::InvalidMediaQuery);
30391    error_test("@container (orientation <= 10px) {}", ParserError::InvalidMediaQuery);
30392
30393    error_test(
30394      "@container style(style(--foo: bar)) {}",
30395      ParserError::UnexpectedToken(crate::properties::custom::Token::Function("style".into())),
30396    );
30397    error_test(
30398      "@container scroll-state(scroll-state(scrollable: top)) {}",
30399      ParserError::InvalidMediaQuery,
30400    );
30401    error_test(
30402      "@container unknown(foo) {}",
30403      ParserError::UnexpectedToken(crate::properties::custom::Token::Function("unknown".into())),
30404    );
30405
30406    // empty container (no name and no condition) should error
30407    error_test("@container {}", ParserError::EndOfInput);
30408
30409    // empty brackets should return a clearer error message
30410    error_test("@container () {}", ParserError::EmptyBracketInCondition);
30411
30412    // invalid condition after a name should error
30413    error_test("@container foo () {}", ParserError::EmptyBracketInCondition);
30414    error_test(
30415      "@container foo bar {}",
30416      ParserError::UnexpectedToken(crate::properties::custom::Token::Ident("bar".into())),
30417    );
30418
30419    error_recovery_test("@container unknown(foo) {}");
30420  }
30421
30422  #[test]
30423  fn test_css_modules_value_rule() {
30424    css_modules_error_test(
30425      "@value compact: (max-width: 37.4375em);",
30426      ParserError::DeprecatedCssModulesValueRule,
30427    );
30428  }
30429
30430  #[test]
30431  fn test_unknown_at_rules() {
30432    minify_test("@foo;", "@foo;");
30433    minify_test("@foo bar;", "@foo bar;");
30434    minify_test("@foo (bar: baz);", "@foo (bar: baz);");
30435    test(
30436      r#"@foo test {
30437      div {
30438        color: red;
30439      }
30440    }"#,
30441      indoc! { r#"@foo test {
30442      div {
30443            color: red;
30444          }
30445    }
30446    "#},
30447    );
30448    minify_test(
30449      r#"@foo test {
30450      div {
30451        color: red;
30452      }
30453    }"#,
30454      "@foo test{div { color: red; }}",
30455    );
30456    minify_test(
30457      r#"@foo test {
30458        foo: bar;
30459      }"#,
30460      "@foo test{foo: bar;}",
30461    );
30462    test(
30463      r#"@foo {
30464        foo: bar;
30465      }"#,
30466      indoc! {r#"
30467      @foo {
30468        foo: bar;
30469      }
30470      "#},
30471    );
30472    minify_test(
30473      r#"@foo {
30474        foo: bar;
30475      }"#,
30476      "@foo{foo: bar;}",
30477    );
30478  }
30479
30480  #[test]
30481  fn test_resolution() {
30482    prefix_test(
30483      r#"
30484      @media (resolution: 1dppx) {
30485        body {
30486          background: red;
30487        }
30488      }
30489      "#,
30490      indoc! { r#"
30491      @media (resolution: 1dppx) {
30492        body {
30493          background: red;
30494        }
30495      }
30496      "#},
30497      Browsers {
30498        chrome: Some(50 << 16),
30499        ..Browsers::default()
30500      },
30501    );
30502
30503    prefix_test(
30504      r#"
30505      @media (resolution: 1dppx) {
30506        body {
30507          background: red;
30508        }
30509      }
30510      "#,
30511      indoc! { r#"
30512      @media (resolution: 1x) {
30513        body {
30514          background: red;
30515        }
30516      }
30517      "#},
30518      Browsers {
30519        chrome: Some(95 << 16),
30520        ..Browsers::default()
30521      },
30522    );
30523  }
30524
30525  #[test]
30526  fn test_environment() {
30527    minify_test(
30528      r#"
30529      @media (max-width: env(--branding-small)) {
30530        body {
30531          padding: env(--branding-padding);
30532        }
30533      }
30534    "#,
30535      "@media (width<=env(--branding-small)){body{padding:env(--branding-padding)}}",
30536    );
30537
30538    minify_test(
30539      r#"
30540      @media (max-width: env(--branding-small 1)) {
30541        body {
30542          padding: env(--branding-padding 2);
30543        }
30544      }
30545    "#,
30546      "@media (width<=env(--branding-small 1)){body{padding:env(--branding-padding 2)}}",
30547    );
30548
30549    minify_test(
30550      r#"
30551      @media (max-width: env(--branding-small 1, 20px)) {
30552        body {
30553          padding: env(--branding-padding 2, 20px);
30554        }
30555      }
30556    "#,
30557      "@media (width<=env(--branding-small 1,20px)){body{padding:env(--branding-padding 2,20px)}}",
30558    );
30559
30560    minify_test(
30561      r#"
30562      @media (max-width: env(safe-area-inset-top)) {
30563        body {
30564          padding: env(safe-area-inset-top);
30565        }
30566      }
30567    "#,
30568      "@media (width<=env(safe-area-inset-top)){body{padding:env(safe-area-inset-top)}}",
30569    );
30570
30571    minify_test(
30572      r#"
30573      @media (max-width: env(unknown)) {
30574        body {
30575          padding: env(unknown);
30576        }
30577      }
30578    "#,
30579      "@media (width<=env(unknown)){body{padding:env(unknown)}}",
30580    );
30581
30582    prefix_test(
30583      r#"
30584      .foo {
30585        color: env(--brand-color, color(display-p3 0 1 0));
30586      }
30587    "#,
30588      indoc! {r#"
30589      .foo {
30590        color: env(--brand-color, #00f942);
30591      }
30592
30593      @supports (color: color(display-p3 0 0 0)) {
30594        .foo {
30595          color: env(--brand-color, color(display-p3 0 1 0));
30596        }
30597      }
30598    "#},
30599      Browsers {
30600        safari: Some(15 << 16),
30601        chrome: Some(90 << 16),
30602        ..Browsers::default()
30603      },
30604    );
30605
30606    prefix_test(
30607      r#"
30608      @supports (color: color(display-p3 0 0 0)) {
30609        .foo {
30610          color: env(--brand-color, color(display-p3 0 1 0));
30611        }
30612      }
30613    "#,
30614      indoc! {r#"
30615      @supports (color: color(display-p3 0 0 0)) {
30616        .foo {
30617          color: env(--brand-color, color(display-p3 0 1 0));
30618        }
30619      }
30620    "#},
30621      Browsers {
30622        safari: Some(15 << 16),
30623        chrome: Some(90 << 16),
30624        ..Browsers::default()
30625      },
30626    );
30627
30628    css_modules_test(
30629      r#"
30630      @media (max-width: env(--branding-small)) {
30631        .foo {
30632          color: env(--brand-color);
30633        }
30634      }
30635    "#,
30636      indoc! {r#"
30637      @media (width <= env(--EgL3uq_branding-small)) {
30638        .EgL3uq_foo {
30639          color: env(--EgL3uq_brand-color);
30640        }
30641      }
30642    "#},
30643      map! {
30644        "foo" => "EgL3uq_foo",
30645        "--brand-color" => "--EgL3uq_brand-color" referenced: true,
30646        "--branding-small" => "--EgL3uq_branding-small" referenced: true
30647      },
30648      HashMap::new(),
30649      crate::css_modules::Config {
30650        dashed_idents: true,
30651        ..Default::default()
30652      },
30653      false,
30654    );
30655  }
30656
30657  #[test]
30658  fn test_license_comments() {
30659    minify_test(
30660      r#"
30661      /*! Copyright 2023 Someone awesome */
30662      /* Some other comment */
30663      .foo {
30664        color: red;
30665      }
30666    "#,
30667      indoc! {r#"
30668      /*! Copyright 2023 Someone awesome */
30669      .foo{color:red}"#},
30670    );
30671
30672    minify_test(
30673      r#"
30674      /*! Copyright 2023 Someone awesome */
30675      /*! Copyright 2023 Someone else */
30676      .foo {
30677        color: red;
30678      }
30679    "#,
30680      indoc! {r#"
30681      /*! Copyright 2023 Someone awesome */
30682      /*! Copyright 2023 Someone else */
30683      .foo{color:red}"#},
30684    );
30685  }
30686
30687  #[test]
30688  fn test_starting_style() {
30689    minify_test(
30690      r#"
30691      @starting-style {
30692        h1 {
30693          background: yellow;
30694        }
30695      }
30696      "#,
30697      "@starting-style{h1{background:#ff0}}",
30698    );
30699    minify_test("@starting-style {}", "");
30700
30701    nesting_test(
30702      r#"
30703      h1 {
30704        background: red;
30705        @starting-style {
30706          background: yellow;
30707        }
30708      }
30709      "#,
30710      indoc! {r#"
30711      h1 {
30712        background: red;
30713      }
30714
30715      @starting-style {
30716        h1 {
30717          background: #ff0;
30718        }
30719      }
30720      "#},
30721    );
30722  }
30723
30724  #[test]
30725  fn test_color_scheme() {
30726    minify_test(".foo { color-scheme: normal; }", ".foo{color-scheme:normal}");
30727    minify_test(".foo { color-scheme: light; }", ".foo{color-scheme:light}");
30728    minify_test(".foo { color-scheme: dark; }", ".foo{color-scheme:dark}");
30729    minify_test(".foo { color-scheme: light dark; }", ".foo{color-scheme:light dark}");
30730    minify_test(".foo { color-scheme: dark light; }", ".foo{color-scheme:light dark}");
30731    minify_test(".foo { color-scheme: only light; }", ".foo{color-scheme:light only}");
30732    minify_test(".foo { color-scheme: only dark; }", ".foo{color-scheme:dark only}");
30733    minify_test(".foo { color-scheme: inherit; }", ".foo{color-scheme:inherit}");
30734    minify_test(":root { color-scheme: unset; }", ":root{color-scheme:unset}");
30735    minify_test(".foo { color-scheme: unknow; }", ".foo{color-scheme:unknow}");
30736    minify_test(".foo { color-scheme: only; }", ".foo{color-scheme:only}");
30737    minify_test(".foo { color-scheme: dark foo; }", ".foo{color-scheme:dark foo}");
30738    minify_test(".foo { color-scheme: normal dark; }", ".foo{color-scheme:normal dark}");
30739    minify_test(
30740      ".foo { color-scheme: dark light only; }",
30741      ".foo{color-scheme:light dark only}",
30742    );
30743    minify_test(".foo { color-scheme: foo bar light; }", ".foo{color-scheme:foo bar light}");
30744    minify_test(
30745      ".foo { color-scheme: only foo dark bar; }",
30746      ".foo{color-scheme:only foo dark bar}",
30747    );
30748    prefix_test(
30749      ".foo { color-scheme: dark; }",
30750      indoc! { r#"
30751      .foo {
30752        --lightningcss-light: ;
30753        --lightningcss-dark: initial;
30754        color-scheme: dark;
30755      }
30756      "#},
30757      Browsers {
30758        chrome: Some(90 << 16),
30759        ..Browsers::default()
30760      },
30761    );
30762    prefix_test(
30763      ".foo { color-scheme: light; }",
30764      indoc! { r#"
30765      .foo {
30766        --lightningcss-light: initial;
30767        --lightningcss-dark: ;
30768        color-scheme: light;
30769      }
30770      "#},
30771      Browsers {
30772        chrome: Some(90 << 16),
30773        ..Browsers::default()
30774      },
30775    );
30776    prefix_test(
30777      ".foo { color-scheme: light dark; }",
30778      indoc! { r#"
30779      .foo {
30780        --lightningcss-light: initial;
30781        --lightningcss-dark: ;
30782        color-scheme: light dark;
30783      }
30784
30785      @media (prefers-color-scheme: dark) {
30786        .foo {
30787          --lightningcss-light: ;
30788          --lightningcss-dark: initial;
30789        }
30790      }
30791      "#},
30792      Browsers {
30793        chrome: Some(90 << 16),
30794        ..Browsers::default()
30795      },
30796    );
30797    prefix_test(
30798      ".foo { color-scheme: light dark; }",
30799      indoc! { r#"
30800      .foo {
30801        color-scheme: light dark;
30802      }
30803      "#},
30804      Browsers {
30805        firefox: Some(120 << 16),
30806        ..Browsers::default()
30807      },
30808    );
30809
30810    minify_test(
30811      ".foo { color: light-dark(yellow, red); }",
30812      ".foo{color:light-dark(#ff0,red)}",
30813    );
30814    minify_test(
30815      ".foo { color: light-dark(light-dark(yellow, red), light-dark(yellow, red)); }",
30816      ".foo{color:light-dark(#ff0,red)}",
30817    );
30818    minify_test(
30819      ".foo { color: light-dark(rgb(0, 0, 255), hsl(120deg, 50%, 50%)); }",
30820      ".foo{color:light-dark(#00f,#40bf40)}",
30821    );
30822    prefix_test(
30823      ".foo { color: light-dark(oklch(40% 0.1268735435 34.568626), oklab(59.686% 0.1009 0.1192)); }",
30824      indoc! { r#"
30825      .foo {
30826        color: var(--lightningcss-light, #7e250f) var(--lightningcss-dark, #c65d07);
30827        color: var(--lightningcss-light, lab(29.2661% 38.2437 35.3889)) var(--lightningcss-dark, lab(52.2319% 40.1449 59.9171));
30828      }
30829      "#},
30830      Browsers {
30831        chrome: Some(90 << 16),
30832        ..Browsers::default()
30833      },
30834    );
30835    prefix_test(
30836      ".foo { color: light-dark(oklch(40% 0.1268735435 34.568626), oklab(59.686% 0.1009 0.1192)); }",
30837      indoc! { r#"
30838      .foo {
30839        color: light-dark(oklch(40% .126874 34.5686), oklab(59.686% .1009 .1192));
30840      }
30841      "#},
30842      Browsers {
30843        firefox: Some(120 << 16),
30844        ..Browsers::default()
30845      },
30846    );
30847    prefix_test(
30848      r#"
30849      .foo {
30850        box-shadow:
30851            oklch(100% 0 0deg / 50%) 0 0.63rem 0.94rem -0.19rem,
30852            currentColor 0 0.44rem 0.8rem -0.58rem;
30853      }
30854    "#,
30855      indoc! { r#"
30856      .foo {
30857        box-shadow: 0 .63rem .94rem -.19rem #ffffff80, 0 .44rem .8rem -.58rem;
30858        box-shadow: 0 .63rem .94rem -.19rem lab(100% 0 0 / .5), 0 .44rem .8rem -.58rem;
30859      }
30860      "#},
30861      Browsers {
30862        chrome: Some(95 << 16),
30863        ..Browsers::default()
30864      },
30865    );
30866    prefix_test(
30867      r#"
30868      .foo {
30869        box-shadow:
30870            oklch(100% 0 0deg / 50%) 0 0.63rem 0.94rem -0.19rem,
30871            currentColor 0 0.44rem 0.8rem -0.58rem;
30872      }
30873    "#,
30874      indoc! { r#"
30875      .foo {
30876        box-shadow: 0 .63rem .94rem -.19rem color(display-p3 1 1 1 / .5), 0 .44rem .8rem -.58rem;
30877        box-shadow: 0 .63rem .94rem -.19rem lab(100% 0 0 / .5), 0 .44rem .8rem -.58rem;
30878      }
30879      "#},
30880      Browsers {
30881        safari: Some(14 << 16),
30882        ..Browsers::default()
30883      },
30884    );
30885
30886    prefix_test(
30887      ".foo { color: light-dark(var(--light), var(--dark)); }",
30888      indoc! { r#"
30889      .foo {
30890        color: var(--lightningcss-light, var(--light)) var(--lightningcss-dark, var(--dark));
30891      }
30892      "#},
30893      Browsers {
30894        chrome: Some(90 << 16),
30895        ..Browsers::default()
30896      },
30897    );
30898    prefix_test(
30899      ".foo { color: rgb(from light-dark(yellow, red) r g b / 10%); }",
30900      indoc! { r#"
30901      .foo {
30902        color: var(--lightningcss-light, #ffff001a) var(--lightningcss-dark, #ff00001a);
30903      }
30904      "#},
30905      Browsers {
30906        chrome: Some(90 << 16),
30907        ..Browsers::default()
30908      },
30909    );
30910    prefix_test(
30911      ".foo { color: rgb(from light-dark(yellow, red) r g b / var(--alpha)); }",
30912      indoc! { r#"
30913      .foo {
30914        color: var(--lightningcss-light, rgb(255 255 0 / var(--alpha))) var(--lightningcss-dark, rgb(255 0 0 / var(--alpha)));
30915      }
30916      "#},
30917      Browsers {
30918        chrome: Some(90 << 16),
30919        ..Browsers::default()
30920      },
30921    );
30922    prefix_test(
30923      ".foo { color: color(from light-dark(yellow, red) srgb r g b / 10%); }",
30924      indoc! { r#"
30925      .foo {
30926        color: var(--lightningcss-light, #ffff001a) var(--lightningcss-dark, #ff00001a);
30927        color: var(--lightningcss-light, color(srgb 1 1 0 / .1)) var(--lightningcss-dark, color(srgb 1 0 0 / .1));
30928      }
30929      "#},
30930      Browsers {
30931        chrome: Some(90 << 16),
30932        ..Browsers::default()
30933      },
30934    );
30935    prefix_test(
30936      ".foo { color: color-mix(in srgb, light-dark(yellow, red), light-dark(red, pink)); }",
30937      indoc! { r#"
30938      .foo {
30939        color: var(--lightningcss-light, #ff8000) var(--lightningcss-dark, #ff6066);
30940      }
30941      "#},
30942      Browsers {
30943        chrome: Some(90 << 16),
30944        ..Browsers::default()
30945      },
30946    );
30947    nesting_test_with_targets(
30948      r#"
30949        .foo { color-scheme: light; }
30950        .bar { color: light-dark(red, green); }
30951      "#,
30952      indoc! {r#"
30953        .foo {
30954          color-scheme: light;
30955        }
30956
30957        .bar {
30958          color: light-dark(red, green);
30959        }
30960      "#},
30961      Targets {
30962        browsers: Some(Browsers {
30963          safari: Some(13 << 16),
30964          ..Browsers::default()
30965        }),
30966        include: Features::empty(),
30967        exclude: Features::LightDark,
30968      },
30969    );
30970  }
30971
30972  #[test]
30973  fn test_print_color_adjust() {
30974    prefix_test(
30975      ".foo { print-color-adjust: exact; }",
30976      indoc! { r#"
30977      .foo {
30978        -webkit-print-color-adjust: exact;
30979        print-color-adjust: exact;
30980      }
30981      "#},
30982      Browsers {
30983        chrome: Some(135 << 16),
30984        ..Browsers::default()
30985      },
30986    );
30987    prefix_test(
30988      ".foo { print-color-adjust: exact; }",
30989      indoc! { r#"
30990      .foo {
30991        print-color-adjust: exact;
30992      }
30993      "#},
30994      Browsers {
30995        chrome: Some(137 << 16),
30996        ..Browsers::default()
30997      },
30998    );
30999  }
31000
31001  #[test]
31002  fn test_all() {
31003    minify_test(".foo { all: initial; all: initial }", ".foo{all:initial}");
31004    minify_test(".foo { all: initial; all: revert }", ".foo{all:revert}");
31005    minify_test(".foo { background: red; all: revert-layer }", ".foo{all:revert-layer}");
31006    minify_test(
31007      ".foo { background: red; all: revert-layer; background: green }",
31008      ".foo{all:revert-layer;background:green}",
31009    );
31010    minify_test(
31011      ".foo { --test: red; all: revert-layer }",
31012      ".foo{--test:red;all:revert-layer}",
31013    );
31014    minify_test(
31015      ".foo { unicode-bidi: embed; all: revert-layer }",
31016      ".foo{all:revert-layer;unicode-bidi:embed}",
31017    );
31018    minify_test(
31019      ".foo { direction: rtl; all: revert-layer }",
31020      ".foo{all:revert-layer;direction:rtl}",
31021    );
31022    minify_test(
31023      ".foo { direction: rtl; all: revert-layer; direction: ltr }",
31024      ".foo{all:revert-layer;direction:ltr}",
31025    );
31026    minify_test(".foo { background: var(--foo); all: unset; }", ".foo{all:unset}");
31027    minify_test(
31028      ".foo { all: unset; background: var(--foo); }",
31029      ".foo{all:unset;background:var(--foo)}",
31030    );
31031    minify_test(
31032      ".foo {--bar:currentcolor; --foo:1.1em; all:unset}",
31033      ".foo{--bar:currentcolor;--foo:1.1em;all:unset}",
31034    );
31035  }
31036
31037  #[test]
31038  fn test_view_transition() {
31039    minify_test(
31040      "@view-transition { navigation: auto }",
31041      "@view-transition{navigation:auto}",
31042    );
31043    minify_test(
31044      "@view-transition { navigation: auto; types: none; }",
31045      "@view-transition{navigation:auto;types:none}",
31046    );
31047    minify_test(
31048      "@view-transition { navigation: auto; types: foo bar; }",
31049      "@view-transition{navigation:auto;types:foo bar}",
31050    );
31051    minify_test(
31052      "@layer { @view-transition { navigation: auto; types: foo bar; } }",
31053      "@layer{@view-transition{navigation:auto;types:foo bar}}",
31054    );
31055  }
31056
31057  #[test]
31058  fn test_skip_generating_unnecessary_fallbacks() {
31059    prefix_test(
31060      r#"
31061      @supports (color: lab(0% 0 0)) and (color: color(display-p3 0 0 0)) {
31062        .foo {
31063          color: lab(40% 56.6 39);
31064        }
31065
31066        .bar {
31067          color: color(display-p3 .643308 .192455 .167712);
31068        }
31069      }
31070      "#,
31071      indoc! {r#"
31072      @supports (color: lab(0% 0 0)) and (color: color(display-p3 0 0 0)) {
31073        .foo {
31074          color: lab(40% 56.6 39);
31075        }
31076
31077        .bar {
31078          color: color(display-p3 .643308 .192455 .167712);
31079        }
31080      }
31081      "#},
31082      Browsers {
31083        chrome: Some(4 << 16),
31084        ..Browsers::default()
31085      },
31086    );
31087
31088    prefix_test(
31089      r#"
31090      @supports (color: lab(40% 56.6 39)) {
31091        .foo {
31092          color: lab(40% 56.6 39);
31093        }
31094      }
31095      "#,
31096      indoc! {r#"
31097      @supports (color: lab(40% 56.6 39)) {
31098        .foo {
31099          color: lab(40% 56.6 39);
31100        }
31101      }
31102      "#},
31103      Browsers {
31104        chrome: Some(4 << 16),
31105        ..Browsers::default()
31106      },
31107    );
31108
31109    prefix_test(
31110      r#"
31111      @supports (background-color: lab(40% 56.6 39)) {
31112        .foo {
31113          background-color: lab(40% 56.6 39);
31114        }
31115      }
31116      "#,
31117      indoc! {r#"
31118      @supports (background-color: lab(40% 56.6 39)) {
31119        .foo {
31120          background-color: lab(40% 56.6 39);
31121        }
31122      }
31123      "#},
31124      Browsers {
31125        chrome: Some(4 << 16),
31126        ..Browsers::default()
31127      },
31128    );
31129
31130    prefix_test(
31131      r#"
31132      @supports (color: light-dark(#f00, #00f)) {
31133        .foo {
31134          color: light-dark(#ff0, #0ff);
31135        }
31136      }
31137      "#,
31138      indoc! {r#"
31139      @supports (color: light-dark(#f00, #00f)) {
31140        .foo {
31141          color: light-dark(#ff0, #0ff);
31142        }
31143      }
31144      "#},
31145      Browsers {
31146        chrome: Some(4 << 16),
31147        ..Browsers::default()
31148      },
31149    );
31150
31151    // NOTE: fallback for lab is not necessary
31152    prefix_test(
31153      r#"
31154      @supports (color: lab(0% 0 0)) and (not (color: color(display-p3 0 0 0))) {
31155        .foo {
31156          color: lab(40% 56.6 39);
31157        }
31158
31159        .bar {
31160          color: color(display-p3 .643308 .192455 .167712);
31161        }
31162      }
31163      "#,
31164      indoc! {r#"
31165      @supports (color: lab(0% 0 0)) and (not (color: color(display-p3 0 0 0))) {
31166        .foo {
31167          color: #b32323;
31168          color: lab(40% 56.6 39);
31169        }
31170
31171        .bar {
31172          color: #b32323;
31173          color: color(display-p3 .643308 .192455 .167712);
31174        }
31175      }
31176      "#},
31177      Browsers {
31178        chrome: Some(4 << 16),
31179        ..Browsers::default()
31180      },
31181    );
31182
31183    prefix_test(
31184      r#"
31185      @supports (color: lab(0% 0 0)) or (color: color(display-p3 0 0 0)) {
31186        .foo {
31187          color: lab(40% 56.6 39);
31188        }
31189
31190        .bar {
31191          color: color(display-p3 .643308 .192455 .167712);
31192        }
31193      }
31194      "#,
31195      indoc! {r#"
31196      @supports (color: lab(0% 0 0)) or (color: color(display-p3 0 0 0)) {
31197        .foo {
31198          color: #b32323;
31199          color: lab(40% 56.6 39);
31200        }
31201
31202        .bar {
31203          color: #b32323;
31204          color: color(display-p3 .643308 .192455 .167712);
31205        }
31206      }
31207      "#},
31208      Browsers {
31209        chrome: Some(4 << 16),
31210        ..Browsers::default()
31211      },
31212    );
31213  }
31214}