Skip to content

Commit

Permalink
Fix downleveling selectors
Browse files Browse the repository at this point in the history
Fixes #413
  • Loading branch information
devongovett committed Feb 12, 2023
1 parent 59cbc02 commit 31fc453
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 8 deletions.
78 changes: 78 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5627,6 +5627,84 @@ mod tests {
},
);

prefix_test(
"a:is(:dir(rtl)) {color:red}",
indoc! {r#"
a:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) {
color: red;
}
"#},
Browsers {
safari: Some(14 << 16),
..Browsers::default()
},
);

prefix_test(
"a:where(:dir(rtl)) {color:red}",
indoc! {r#"
a:where(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
color: red;
}
"#},
Browsers {
safari: Some(14 << 16),
..Browsers::default()
},
);

prefix_test(
"a:has(:dir(rtl)) {color:red}",
indoc! {r#"
a:has(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
color: red;
}
"#},
Browsers {
safari: Some(14 << 16),
..Browsers::default()
},
);

prefix_test(
"a:not(:dir(rtl)) {color:red}",
indoc! {r#"
a:not(:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi)) {
color: red;
}
"#},
Browsers {
safari: Some(14 << 16),
..Browsers::default()
},
);

prefix_test(
"a:dir(rtl)::after {color:red}",
indoc! {r#"
a:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi):after {
color: red;
}
"#},
Browsers {
safari: Some(14 << 16),
..Browsers::default()
},
);

prefix_test(
"a:dir(rtl) div {color:red}",
indoc! {r#"
a:lang(ae, ar, arc, bcc, bqi, ckb, dv, fa, glk, he, ku, mzn, nqo, pnb, ps, sd, ug, ur, yi) div {
color: red;
}
"#},
Browsers {
safari: Some(14 << 16),
..Browsers::default()
},
);

minify_test(".foo::cue {color: red}", ".foo::cue{color:red}");
minify_test(".foo::cue-region {color: red}", ".foo::cue-region{color:red}");
minify_test(".foo::cue(b) {color: red}", ".foo::cue(b){color:red}");
Expand Down
2 changes: 1 addition & 1 deletion src/rules/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,7 @@ impl<'i, T> CssRuleList<'i, T> {
if let Some(targets) = context.targets {
style.vendor_prefix = get_prefix(&style.selectors);
if style.vendor_prefix.contains(VendorPrefix::None) {
style.vendor_prefix = downlevel_selectors(&mut style.selectors, *targets);
style.vendor_prefix = downlevel_selectors(style.selectors.0.as_mut_slice(), *targets);
}
}

Expand Down
26 changes: 19 additions & 7 deletions src/selector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1655,12 +1655,16 @@ pub(crate) fn is_equivalent<'i>(selectors: &SelectorList<'i>, other: &SelectorLi
pub(crate) fn get_prefix(selectors: &SelectorList) -> VendorPrefix {
let mut prefix = VendorPrefix::empty();
for selector in &selectors.0 {
for component in selector.iter() {
for component in selector.iter_raw_match_order() {
let p = match component {
// Return none rather than empty for these so that we call downlevel_selectors.
Component::NonTSPseudoClass(PseudoClass::Lang { .. })
| Component::NonTSPseudoClass(PseudoClass::Dir { .. })
| Component::Is(..) => VendorPrefix::None,
| Component::Is(..)
| Component::Where(..)
| Component::Has(..)
| Component::Negation(..) => VendorPrefix::None,
Component::Any(prefix, _) => *prefix,
Component::NonTSPseudoClass(pc) => pc.get_prefix(),
Component::PseudoElement(pe) => pe.get_prefix(),
_ => VendorPrefix::empty(),
Expand All @@ -1686,9 +1690,9 @@ const RTL_LANGS: &[&str] = &[

/// Downlevels the given selectors to be compatible with the given browser targets.
/// Returns the necessary vendor prefixes.
pub(crate) fn downlevel_selectors(selectors: &mut SelectorList, targets: Browsers) -> VendorPrefix {
pub(crate) fn downlevel_selectors(selectors: &mut [Selector], targets: Browsers) -> VendorPrefix {
let mut necessary_prefixes = VendorPrefix::empty();
for selector in &mut selectors.0 {
for selector in selectors {
for component in selector.iter_mut_raw_match_order() {
necessary_prefixes |= downlevel_component(component, targets);
}
Expand Down Expand Up @@ -1723,17 +1727,25 @@ fn downlevel_component<'i>(component: &mut Component<'i>, targets: Browsers) ->
}
}
Component::PseudoElement(pe) => pe.get_necessary_prefixes(targets),
Component::Is(ref selectors) => {
Component::Is(selectors) => {
let mut necessary_prefixes = downlevel_selectors(&mut **selectors, targets);

// Convert :is to :-webkit-any/:-moz-any if needed.
// All selectors must be simple, no combinators are supported.
if !Feature::CssMatchesPseudo.is_compatible(targets)
&& selectors.iter().all(|selector| !selector.has_combinator())
{
crate::prefixes::Feature::AnyPseudo.prefixes_for(targets)
necessary_prefixes |= crate::prefixes::Feature::AnyPseudo.prefixes_for(targets)
} else {
VendorPrefix::empty()
necessary_prefixes |= VendorPrefix::empty()
}

necessary_prefixes
}
Component::Where(selectors)
| Component::Any(_, selectors)
| Component::Negation(selectors)
| Component::Has(selectors) => downlevel_selectors(&mut **selectors, targets),
_ => VendorPrefix::empty(),
}
}
Expand Down

0 comments on commit 31fc453

Please sign in to comment.