diff options
author | Jonathan Kew <jkew@mozilla.com> | 2023-04-12 21:46:47 +0000 |
---|---|---|
committer | Martin Robinson <mrobinson@igalia.com> | 2023-11-21 15:36:35 +0100 |
commit | a2df8f7ea5e76e7753d9649b7dfb1b0329510078 (patch) | |
tree | af11fd129ae066dcf4ac40d53e78b7c4c3c92b47 /components/style/gecko/selector_parser.rs | |
parent | 13e2d104748b398776e16225024a0717e5c82627 (diff) | |
download | servo-a2df8f7ea5e76e7753d9649b7dfb1b0329510078.tar.gz servo-a2df8f7ea5e76e7753d9649b7dfb1b0329510078.zip |
style: Accept a comma-separated list of language codes in the :lang() pseudo
This is the other extension to the :lang() pseudo-class in Selectors-4.
(Also supported in Safari.)
Depends on D174999
Differential Revision: https://phabricator.services.mozilla.com/D175000
Diffstat (limited to 'components/style/gecko/selector_parser.rs')
-rw-r--r-- | components/style/gecko/selector_parser.rs | 32 |
1 files changed, 27 insertions, 5 deletions
diff --git a/components/style/gecko/selector_parser.rs b/components/style/gecko/selector_parser.rs index f5998611d7c..2beaaa238d2 100644 --- a/components/style/gecko/selector_parser.rs +++ b/components/style/gecko/selector_parser.rs @@ -19,7 +19,7 @@ use dom::{DocumentState, ElementState}; use selectors::parser::SelectorParseErrorKind; use selectors::SelectorList; use std::fmt; -use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss as ToCss_}; +use style_traits::{Comma, CssWriter, OneOrMoreSeparated, ParseError, StyleParseErrorKind, ToCss as ToCss_}; pub use crate::gecko::pseudo_element::{ PseudoElement, EAGER_PSEUDOS, EAGER_PSEUDO_COUNT, PSEUDO_COUNT, @@ -38,7 +38,13 @@ bitflags! { } /// The type used to store the language argument to the `:lang` pseudo-class. -pub type Lang = AtomIdent; +#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)] +pub enum Lang { + /// A single language code. + Single(AtomIdent), + /// A list of language codes. + List(Box<Vec<AtomIdent>>), +} macro_rules! pseudo_class_name { ([$(($css:expr, $name:ident, $state:tt, $flags:tt),)*]) => { @@ -60,6 +66,10 @@ macro_rules! pseudo_class_name { } apply_non_ts_list!(pseudo_class_name); +impl OneOrMoreSeparated for AtomIdent { + type S = Comma; +} + impl ToCss for NonTSPseudoClass { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where @@ -71,7 +81,10 @@ impl ToCss for NonTSPseudoClass { $(NonTSPseudoClass::$name => concat!(":", $css),)* NonTSPseudoClass::Lang(ref s) => { dest.write_str(":lang(")?; - cssparser::ToCss::to_css(s, dest)?; + match &s { + Lang::Single(lang) => cssparser::ToCss::to_css(lang, dest)?, + Lang::List(list) => list.to_css(&mut CssWriter::new(dest))?, + } return dest.write_char(')'); }, NonTSPseudoClass::MozLocaleDir(ref dir) => { @@ -375,8 +388,17 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> { ) -> Result<NonTSPseudoClass, ParseError<'i>> { let pseudo_class = match_ignore_ascii_case! { &name, "lang" => { - let name = parser.expect_ident_or_string()?; - NonTSPseudoClass::Lang(Lang::from(name.as_ref())) + let result = parser.parse_comma_separated(|input| { + Ok(AtomIdent::from(input.expect_ident_or_string()?.as_ref())) + })?; + if result.is_empty() { + return Err(parser.new_custom_error(StyleParseErrorKind::UnspecifiedError)); + } + if result.len() == 1 { + NonTSPseudoClass::Lang(Lang::Single(result[0].clone())) + } else { + NonTSPseudoClass::Lang(Lang::List(Box::new(result))) + } }, "-moz-locale-dir" => { NonTSPseudoClass::MozLocaleDir(Direction::parse(parser)?) |