aboutsummaryrefslogtreecommitdiffstats
path: root/components/style/gecko/selector_parser.rs
diff options
context:
space:
mode:
authorJonathan Kew <jkew@mozilla.com>2023-04-12 21:46:47 +0000
committerMartin Robinson <mrobinson@igalia.com>2023-11-21 15:36:35 +0100
commita2df8f7ea5e76e7753d9649b7dfb1b0329510078 (patch)
treeaf11fd129ae066dcf4ac40d53e78b7c4c3c92b47 /components/style/gecko/selector_parser.rs
parent13e2d104748b398776e16225024a0717e5c82627 (diff)
downloadservo-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.rs32
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)?)