summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp
diff options
context:
space:
mode:
authorSam Atkins <atkinssj@gmail.com>2021-07-12 14:58:03 +0100
committerAndreas Kling <kling@serenityos.org>2021-07-14 13:31:00 +0200
commit96b2356cbb187424ca3864fb1ca1095275d8ea61 (patch)
treeeaae78d6f07b4d47033d6335bc408831c4a64a79 /Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp
parentdadcb4634430d6e963e53dc8465261fad87470ee (diff)
downloadserenity-96b2356cbb187424ca3864fb1ca1095275d8ea61.zip
LibWeb: Add 'Attribute' as a CSS SimpleSelector::Type
Previously, SimpleSelectors optionally had Attribute-selector data as well as their main type. Now, they're either one or the other, which better matches the spec, and makes parsing and matching more straightforward.
Diffstat (limited to 'Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp')
-rw-r--r--Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp68
1 files changed, 35 insertions, 33 deletions
diff --git a/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp b/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp
index 364a405959..2bfeb77b3d 100644
--- a/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp
+++ b/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * Copyright (c) 2021, Sam Atkins <atkinssj@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@@ -24,6 +25,38 @@ static bool matches_hover_pseudo_class(DOM::Element const& element)
return element.is_ancestor_of(*hovered_node);
}
+static bool matches_attribute(CSS::Selector::SimpleSelector::Attribute const& attribute, DOM::Element const& element)
+{
+ switch (attribute.match_type) {
+ case CSS::Selector::SimpleSelector::Attribute::MatchType::HasAttribute:
+ return element.has_attribute(attribute.name);
+ break;
+ case CSS::Selector::SimpleSelector::Attribute::MatchType::ExactValueMatch:
+ return element.attribute(attribute.name) == attribute.value;
+ break;
+ case CSS::Selector::SimpleSelector::Attribute::MatchType::ContainsWord:
+ return element.attribute(attribute.name).split(' ').contains_slow(attribute.value);
+ break;
+ 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('-').first() == attribute.value;
+ break;
+ case CSS::Selector::SimpleSelector::Attribute::MatchType::StartsWithString:
+ return element.attribute(attribute.name).starts_with(attribute.value);
+ break;
+ case CSS::Selector::SimpleSelector::Attribute::MatchType::EndsWithString:
+ return element.attribute(attribute.name).ends_with(attribute.value);
+ break;
+ case CSS::Selector::SimpleSelector::Attribute::MatchType::None:
+ VERIFY_NOT_REACHED();
+ break;
+ }
+
+ return false;
+}
+
static bool matches(CSS::Selector::SimpleSelector const& component, DOM::Element const& element)
{
switch (component.pseudo_element) {
@@ -171,39 +204,6 @@ static bool matches(CSS::Selector::SimpleSelector const& component, DOM::Element
break;
}
- switch (component.attribute_match_type) {
- case CSS::Selector::SimpleSelector::AttributeMatchType::HasAttribute:
- if (!element.has_attribute(component.attribute_name))
- return false;
- break;
- case CSS::Selector::SimpleSelector::AttributeMatchType::ExactValueMatch:
- if (element.attribute(component.attribute_name) != component.attribute_value)
- return false;
- break;
- case CSS::Selector::SimpleSelector::AttributeMatchType::ContainsWord:
- if (!element.attribute(component.attribute_name).split(' ').contains_slow(component.attribute_value))
- return false;
- break;
- case CSS::Selector::SimpleSelector::AttributeMatchType::ContainsString:
- if (!element.attribute(component.attribute_name).contains(component.attribute_value))
- return false;
- break;
- case CSS::Selector::SimpleSelector::AttributeMatchType::StartsWithSegment:
- if (element.attribute(component.attribute_name).split('-').first() != component.attribute_value)
- return false;
- break;
- case CSS::Selector::SimpleSelector::AttributeMatchType::StartsWithString:
- if (!element.attribute(component.attribute_name).starts_with(component.attribute_value))
- return false;
- break;
- case CSS::Selector::SimpleSelector::AttributeMatchType::EndsWithString:
- if (!element.attribute(component.attribute_name).ends_with(component.attribute_value))
- return false;
- break;
- default:
- break;
- }
-
switch (component.type) {
case CSS::Selector::SimpleSelector::Type::Universal:
return true;
@@ -213,6 +213,8 @@ static bool matches(CSS::Selector::SimpleSelector const& component, DOM::Element
return element.has_class(component.value);
case CSS::Selector::SimpleSelector::Type::TagName:
return component.value == element.local_name();
+ case CSS::Selector::SimpleSelector::Type::Attribute:
+ return matches_attribute(component.attribute, element);
default:
VERIFY_NOT_REACHED();
}