From 34b60127a366182ccedce167c224a105be7c38eb Mon Sep 17 00:00:00 2001 From: Lucas Weng Date: Tue, 29 Apr 2025 08:22:10 +0800 Subject: [PATCH 1/2] Add support for `::highlight` --- scripts/build-prefixes.js | 1 + selectors/parser.rs | 4 ++++ src/compat.rs | 41 +++++++++++++++++++++++++++++++++++++++ src/selector.rs | 12 ++++++++++++ 4 files changed, 58 insertions(+) diff --git a/scripts/build-prefixes.js b/scripts/build-prefixes.js index 029fa54a..a19443e5 100644 --- a/scripts/build-prefixes.js +++ b/scripts/build-prefixes.js @@ -288,6 +288,7 @@ let mdnFeatures = { oklabColors: mdn.css.types.color.oklab.__compat.support, colorFunction: mdn.css.types.color.color.__compat.support, spaceSeparatedColorNotation: mdn.css.types.color.rgb.space_separated_parameters.__compat.support, + highlight: mdn.css.selectors.highlight.__compat.support, textDecorationThicknessPercent: mdn.css.properties['text-decoration-thickness'].percentage.__compat.support, textDecorationThicknessShorthand: mdn.css.properties['text-decoration'].includes_thickness.__compat.support, cue: mdn.css.selectors.cue.__compat.support, diff --git a/selectors/parser.rs b/selectors/parser.rs index ed7b97f1..7329729a 100644 --- a/selectors/parser.rs +++ b/selectors/parser.rs @@ -3933,6 +3933,10 @@ pub mod tests { assert!(parse("foo::details-content").is_ok()); assert!(parse("foo::target-text").is_ok()); + assert!(parse("::highlight").is_err()); + assert!(parse("::highlight()").is_err()); + assert!(parse("::highlight(custom-highlight-name)").is_ok()); + assert!(parse("select::picker").is_err()); assert!(parse("::picker()").is_err()); assert!(parse("::picker(select)").is_ok()); diff --git a/src/compat.rs b/src/compat.rs index fb6dd6d2..4c8c91a1 100644 --- a/src/compat.rs +++ b/src/compat.rs @@ -92,6 +92,7 @@ pub enum Feature { HasSelector, HebrewListStyleType, HexAlphaColors, + Highlight, HiraganaIrohaListStyleType, HiraganaListStyleType, HypotFunction, @@ -2448,6 +2449,46 @@ impl Feature { return false; } } + Feature::Highlight => { + if let Some(version) = browsers.chrome { + if version < 6881280 { + return false; + } + } + if let Some(version) = browsers.edge { + if version < 6881280 { + return false; + } + } + if let Some(version) = browsers.opera { + if version < 4718592 { + return false; + } + } + if let Some(version) = browsers.safari { + if version < 1114624 { + return false; + } + } + if let Some(version) = browsers.ios_saf { + if version < 1114624 { + return false; + } + } + if let Some(version) = browsers.samsung { + if version < 1310720 { + return false; + } + } + if let Some(version) = browsers.android { + if version < 6881280 { + return false; + } + } + if browsers.firefox.is_some() || browsers.ie.is_some() { + return false; + } + } Feature::TextDecorationThicknessPercent => { if let Some(version) = browsers.chrome { if version < 5701632 { diff --git a/src/selector.rs b/src/selector.rs index d5011076..87865bf6 100644 --- a/src/selector.rs +++ b/src/selector.rs @@ -317,6 +317,7 @@ impl<'a, 'o, 'i> parcel_selectors::parser::Parser<'i> for SelectorParser<'a, 'o, let pseudo_element = match_ignore_ascii_case! { &name, "cue" => CueFunction { selector: Box::new(Selector::parse(self, arguments)?) }, "cue-region" => CueRegionFunction { selector: Box::new(Selector::parse(self, arguments)?) }, + "highlight" => HighlightFunction { name: CustomIdent::parse(arguments)? }, "picker" => PickerFunction { identifier: Ident::parse(arguments)? }, "view-transition-group" => ViewTransitionGroup { part: ViewTransitionPartSelector::parse(arguments)? }, "view-transition-image-pair" => ViewTransitionImagePair { part: ViewTransitionPartSelector::parse(arguments)? }, @@ -903,6 +904,11 @@ pub enum PseudoElement<'i> { /// The [::placeholder](https://drafts.csswg.org/css-pseudo-4/#placeholder-pseudo) pseudo element. #[cfg_attr(feature = "serde", serde(with = "PrefixWrapper"))] Placeholder(VendorPrefix), + /// The [::highlight()](https://drafts.csswg.org/css-highlight-api/#custom-highlight-pseudo) functional pseudo element. + HighlightFunction { + /// A custom highlight name. + name: CustomIdent<'i>, + }, /// The [::marker](https://drafts.csswg.org/css-pseudo-4/#marker-pseudo) pseudo element. Marker, /// The [::backdrop](https://fullscreen.spec.whatwg.org/#::backdrop-pseudo-element) pseudo element. @@ -1160,6 +1166,11 @@ where FirstLetter => dest.write_str(":first-letter"), DetailsContent => dest.write_str("::details-content"), TargetText => dest.write_str("::target-text"), + HighlightFunction { name } => { + dest.write_str("::highlight(")?; + name.to_css(dest)?; + dest.write_char(')') + } Marker => dest.write_str("::marker"), Selection(prefix) => write_prefixed!(prefix, "selection"), Cue => dest.write_str("::cue"), @@ -1935,6 +1946,7 @@ pub(crate) fn is_compatible(selectors: &[Selector], targets: Targets) -> bool { PseudoElement::TargetText => Feature::TargetText, PseudoElement::Selection(prefix) if *prefix == VendorPrefix::None => Feature::Selection, PseudoElement::Placeholder(prefix) if *prefix == VendorPrefix::None => Feature::Placeholder, + PseudoElement::HighlightFunction { name: _ } => Feature::Highlight, PseudoElement::Marker => Feature::MarkerPseudo, PseudoElement::Backdrop(prefix) if *prefix == VendorPrefix::None => Feature::Dialog, PseudoElement::Cue => Feature::Cue, From 6d7eceb83d3b5733bc4d0090bedd87e8f9225b02 Mon Sep 17 00:00:00 2001 From: Lucas Weng Date: Sat, 8 Nov 2025 10:44:18 +0800 Subject: [PATCH 2/2] update browser compat data for highlight --- src/compat.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/compat.rs b/src/compat.rs index bf8589b9..0fa40c57 100644 --- a/src/compat.rs +++ b/src/compat.rs @@ -2467,6 +2467,11 @@ impl Feature { return false; } } + if let Some(version) = browsers.firefox { + if version < 9175040 { + return false; + } + } if let Some(version) = browsers.opera { if version < 4718592 { return false; @@ -2492,7 +2497,7 @@ impl Feature { return false; } } - if browsers.firefox.is_some() || browsers.ie.is_some() { + if browsers.ie.is_some() { return false; } }