mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 18:37:35 +00:00
LibWeb: Fix issues with CSS attribute selector handling
This is three small, related changes: 1. Element::has_attribute() now returns true if the attribute exists but has no value. (eg, `<div foo />` -> `has_attribute("foo")`) 2. SelectorEngine::matches_attribute() now makes sure there is a first segment before comparing it, fixing a crash. 3. CSS::Parser now converts attribute names in attribute selectors to lowercase, to match the expectations of the rest of the system. Converting to lowercase is not always correct, depending on language, but since we only currently support HTML, and that expects them to be case-insensitive, it is fine for now.
This commit is contained in:
parent
242c342fad
commit
1b72766e4e
3 changed files with 11 additions and 4 deletions
|
@ -416,7 +416,12 @@ Result<Selector::SimpleSelector, Parser::SelectorParsingResult> Parser::parse_si
|
|||
.type = Selector::SimpleSelector::Type::Attribute,
|
||||
.attribute = {
|
||||
.match_type = Selector::SimpleSelector::Attribute::MatchType::HasAttribute,
|
||||
.name = attribute_part.token().ident(),
|
||||
// FIXME: Case-sensitivity is defined by the document language.
|
||||
// HTML is insensitive with attribute names, and our code generally assumes
|
||||
// they are converted to lowercase, so we do that here too. If we want to be
|
||||
// correct with XML later, we'll need to keep the original case and then do
|
||||
// a case-insensitive compare later.
|
||||
.name = attribute_part.token().ident().to_lowercase_string(),
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -40,9 +40,11 @@ static bool matches_attribute(CSS::Selector::SimpleSelector::Attribute const& at
|
|||
case CSS::Selector::SimpleSelector::Attribute::MatchType::ContainsString:
|
||||
return element.attribute(attribute.name).contains(attribute.value);
|
||||
break;
|
||||
case CSS::Selector::SimpleSelector::Attribute::MatchType::StartsWithSegment:
|
||||
return element.attribute(attribute.name).split_view('-').first() == attribute.value;
|
||||
case CSS::Selector::SimpleSelector::Attribute::MatchType::StartsWithSegment: {
|
||||
auto segments = element.attribute(attribute.name).split_view('-');
|
||||
return !segments.is_empty() && segments.first() == attribute.value;
|
||||
break;
|
||||
}
|
||||
case CSS::Selector::SimpleSelector::Attribute::MatchType::StartsWithString:
|
||||
return element.attribute(attribute.name).starts_with(attribute.value);
|
||||
break;
|
||||
|
|
|
@ -45,7 +45,7 @@ public:
|
|||
// NOTE: This is for the JS bindings
|
||||
const FlyString& namespace_uri() const { return namespace_(); }
|
||||
|
||||
bool has_attribute(const FlyString& name) const { return !attribute(name).is_null(); }
|
||||
bool has_attribute(const FlyString& name) const { return find_attribute(name) != nullptr; }
|
||||
bool has_attributes() const { return !m_attributes.is_empty(); }
|
||||
String attribute(const FlyString& name) const;
|
||||
String get_attribute(const FlyString& name) const { return attribute(name); }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue