mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +01:00
style: Add support for 's' flag on attribute selectors.
We could keep using ParsedCaseSensitivity::CaseSensitive as a temporary stand-in for "case-sensitive or maybe not depending on what HTML says" until we check the attribute list, but it seems better to make that explicit. Differential Revision: https://phabricator.services.mozilla.com/D14093
This commit is contained in:
parent
901c055519
commit
a519d9ecc3
2 changed files with 73 additions and 25 deletions
|
@ -134,8 +134,13 @@ pub static SELECTOR_WHITESPACE: &'static [char] = &[' ', '\t', '\n', '\r', '\x0C
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
pub enum ParsedCaseSensitivity {
|
pub enum ParsedCaseSensitivity {
|
||||||
CaseSensitive,
|
// 's' was specified.
|
||||||
|
ExplicitCaseSensitive,
|
||||||
|
// 'i' was specified.
|
||||||
AsciiCaseInsensitive,
|
AsciiCaseInsensitive,
|
||||||
|
// No flags were specified and HTML says this is a case-sensitive attribute.
|
||||||
|
CaseSensitive,
|
||||||
|
// No flags were specified and HTML says this is a case-insensitive attribute.
|
||||||
AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument,
|
AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,7 +155,10 @@ impl ParsedCaseSensitivity {
|
||||||
ParsedCaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument => {
|
ParsedCaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument => {
|
||||||
CaseSensitivity::CaseSensitive
|
CaseSensitivity::CaseSensitive
|
||||||
},
|
},
|
||||||
ParsedCaseSensitivity::CaseSensitive => CaseSensitivity::CaseSensitive,
|
ParsedCaseSensitivity::CaseSensitive |
|
||||||
|
ParsedCaseSensitivity::ExplicitCaseSensitive => {
|
||||||
|
CaseSensitivity::CaseSensitive
|
||||||
|
},
|
||||||
ParsedCaseSensitivity::AsciiCaseInsensitive => CaseSensitivity::AsciiCaseInsensitive,
|
ParsedCaseSensitivity::AsciiCaseInsensitive => CaseSensitivity::AsciiCaseInsensitive,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1223,6 +1223,7 @@ impl<Impl: SelectorImpl> ToCss for Component<Impl> {
|
||||||
ParsedCaseSensitivity::CaseSensitive |
|
ParsedCaseSensitivity::CaseSensitive |
|
||||||
ParsedCaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument => {},
|
ParsedCaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument => {},
|
||||||
ParsedCaseSensitivity::AsciiCaseInsensitive => dest.write_str(" i")?,
|
ParsedCaseSensitivity::AsciiCaseInsensitive => dest.write_str(" i")?,
|
||||||
|
ParsedCaseSensitivity::ExplicitCaseSensitive => dest.write_str(" s")?,
|
||||||
}
|
}
|
||||||
dest.write_char(']')
|
dest.write_char(']')
|
||||||
},
|
},
|
||||||
|
@ -1301,6 +1302,7 @@ impl<Impl: SelectorImpl> ToCss for AttrSelectorWithOptionalNamespace<Impl> {
|
||||||
ParsedCaseSensitivity::CaseSensitive |
|
ParsedCaseSensitivity::CaseSensitive |
|
||||||
ParsedCaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument => {},
|
ParsedCaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument => {},
|
||||||
ParsedCaseSensitivity::AsciiCaseInsensitive => dest.write_str(" i")?,
|
ParsedCaseSensitivity::AsciiCaseInsensitive => dest.write_str(" i")?,
|
||||||
|
ParsedCaseSensitivity::ExplicitCaseSensitive => dest.write_str(" i")?,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -1711,24 +1713,15 @@ where
|
||||||
AttrSelectorOperator::Suffix => value.is_empty(),
|
AttrSelectorOperator::Suffix => value.is_empty(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut case_sensitivity = parse_attribute_flags(input)?;
|
let attribute_flags = parse_attribute_flags(input)?;
|
||||||
|
|
||||||
let value = value.as_ref().into();
|
let value = value.as_ref().into();
|
||||||
let local_name_lower;
|
let local_name_lower;
|
||||||
let local_name_is_ascii_lowercase;
|
let local_name_is_ascii_lowercase;
|
||||||
|
let case_sensitivity;
|
||||||
{
|
{
|
||||||
let local_name_lower_cow = to_ascii_lowercase(&local_name);
|
let local_name_lower_cow = to_ascii_lowercase(&local_name);
|
||||||
if let ParsedCaseSensitivity::CaseSensitive = case_sensitivity {
|
case_sensitivity = attribute_flags.to_case_sensitivity(local_name_lower_cow.as_ref(), namespace.is_some());
|
||||||
if namespace.is_none() && include!(concat!(
|
|
||||||
env!("OUT_DIR"),
|
|
||||||
"/ascii_case_insensitive_html_attributes.rs"
|
|
||||||
))
|
|
||||||
.contains(&*local_name_lower_cow)
|
|
||||||
{
|
|
||||||
case_sensitivity =
|
|
||||||
ParsedCaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument
|
|
||||||
}
|
|
||||||
}
|
|
||||||
local_name_lower = local_name_lower_cow.as_ref().into();
|
local_name_lower = local_name_lower_cow.as_ref().into();
|
||||||
local_name_is_ascii_lowercase = matches!(local_name_lower_cow, Cow::Borrowed(..));
|
local_name_is_ascii_lowercase = matches!(local_name_lower_cow, Cow::Borrowed(..));
|
||||||
}
|
}
|
||||||
|
@ -1758,20 +1751,67 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An attribute selector can have 's' or 'i' as flags, or no flags at all.
|
||||||
|
enum AttributeFlags {
|
||||||
|
// Matching should be case-sensitive ('s' flag).
|
||||||
|
CaseSensitive,
|
||||||
|
// Matching should be case-insensitive ('i' flag).
|
||||||
|
AsciiCaseInsensitive,
|
||||||
|
// No flags. Matching behavior depends on the name of the attribute.
|
||||||
|
CaseSensitivityDependsOnName
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AttributeFlags {
|
||||||
|
fn to_case_sensitivity(
|
||||||
|
self,
|
||||||
|
local_name: &str,
|
||||||
|
have_namespace: bool,
|
||||||
|
) -> ParsedCaseSensitivity {
|
||||||
|
match self {
|
||||||
|
AttributeFlags::CaseSensitive =>
|
||||||
|
ParsedCaseSensitivity::ExplicitCaseSensitive,
|
||||||
|
AttributeFlags::AsciiCaseInsensitive =>
|
||||||
|
ParsedCaseSensitivity::AsciiCaseInsensitive,
|
||||||
|
AttributeFlags::CaseSensitivityDependsOnName => {
|
||||||
|
if !have_namespace && include!(concat!(
|
||||||
|
env!("OUT_DIR"),
|
||||||
|
"/ascii_case_insensitive_html_attributes.rs"
|
||||||
|
))
|
||||||
|
.contains(local_name)
|
||||||
|
{
|
||||||
|
ParsedCaseSensitivity::AsciiCaseInsensitiveIfInHtmlElementInHtmlDocument
|
||||||
|
} else {
|
||||||
|
ParsedCaseSensitivity::CaseSensitive
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_attribute_flags<'i, 't>(
|
fn parse_attribute_flags<'i, 't>(
|
||||||
input: &mut CssParser<'i, 't>,
|
input: &mut CssParser<'i, 't>,
|
||||||
) -> Result<ParsedCaseSensitivity, BasicParseError<'i>> {
|
) -> Result<AttributeFlags, BasicParseError<'i>> {
|
||||||
let location = input.current_source_location();
|
let location = input.current_source_location();
|
||||||
match input.next() {
|
let token = match input.next() {
|
||||||
Err(_) => {
|
Ok(t) => t,
|
||||||
// Selectors spec says language-defined, but HTML says sensitive.
|
Err(..) => {
|
||||||
Ok(ParsedCaseSensitivity::CaseSensitive)
|
// Selectors spec says language-defined; HTML says it depends on the
|
||||||
},
|
// exact attribute name.
|
||||||
Ok(&Token::Ident(ref value)) if value.eq_ignore_ascii_case("i") => {
|
return Ok(AttributeFlags::CaseSensitivityDependsOnName);
|
||||||
Ok(ParsedCaseSensitivity::AsciiCaseInsensitive)
|
|
||||||
},
|
|
||||||
Ok(t) => Err(location.new_basic_unexpected_token_error(t.clone())),
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let ident = match *token {
|
||||||
|
Token::Ident(ref i) => i,
|
||||||
|
ref other => return Err(location.new_basic_unexpected_token_error(other.clone())),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(match_ignore_ascii_case! {
|
||||||
|
ident,
|
||||||
|
"i" => AttributeFlags::AsciiCaseInsensitive,
|
||||||
|
"s" => AttributeFlags::CaseSensitive,
|
||||||
|
_ => return Err(location.new_basic_unexpected_token_error(token.clone())),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Level 3: Parse **one** simple_selector. (Though we might insert a second
|
/// Level 3: Parse **one** simple_selector. (Though we might insert a second
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue