summaryrefslogtreecommitdiff
path: root/Libraries/LibHTML/CSS/StyleResolver.cpp
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-10-06 15:34:42 +0200
committerAndreas Kling <awesomekling@gmail.com>2019-10-06 15:34:42 +0200
commit156b35742a947c7179bd4f6cbad363eb8918a261 (patch)
tree0110320052905159ccc73acc94d0b8fc0e47fce7 /Libraries/LibHTML/CSS/StyleResolver.cpp
parentb587eb2f4d3c8794cf6dd68b0fa9cac65a1424bb (diff)
downloadserenity-156b35742a947c7179bd4f6cbad363eb8918a261.zip
LibHTML: Implement matching for descendant selectors
The CSS engine now correctly matches selectors like "#foo #bar #baz".
Diffstat (limited to 'Libraries/LibHTML/CSS/StyleResolver.cpp')
-rw-r--r--Libraries/LibHTML/CSS/StyleResolver.cpp32
1 files changed, 27 insertions, 5 deletions
diff --git a/Libraries/LibHTML/CSS/StyleResolver.cpp b/Libraries/LibHTML/CSS/StyleResolver.cpp
index 6f7697ba65..95b7ab8cc2 100644
--- a/Libraries/LibHTML/CSS/StyleResolver.cpp
+++ b/Libraries/LibHTML/CSS/StyleResolver.cpp
@@ -15,12 +15,8 @@ StyleResolver::~StyleResolver()
{
}
-static bool matches(const Selector& selector, const Element& element)
+static bool matches(const Selector::Component& component, const Element& element)
{
- // FIXME: Support compound selectors.
- ASSERT(selector.components().size() == 1);
-
- auto& component = selector.components().first();
switch (component.type) {
case Selector::Component::Type::Id:
return component.value == element.attribute("id");
@@ -33,6 +29,32 @@ static bool matches(const Selector& selector, const Element& element)
}
}
+static bool matches(const Selector& selector, int component_index, const Element& element)
+{
+ auto& component = selector.components()[component_index];
+ if (!matches(component, element))
+ return false;
+ if (component.relation == Selector::Component::Relation::None)
+ return true;
+ if (component.relation == Selector::Component::Relation::Descendant) {
+ ASSERT(component_index != 0);
+ for (auto* ancestor = element.parent(); ancestor; ancestor = ancestor->parent()) {
+ if (!ancestor->is_element())
+ continue;
+ if (matches(selector, component_index - 1, static_cast<const Element&>(*ancestor)))
+ return true;
+ }
+ return false;
+ }
+ ASSERT_NOT_REACHED();
+}
+
+static bool matches(const Selector& selector, const Element& element)
+{
+ ASSERT(!selector.components().is_empty());
+ return matches(selector, selector.components().size() - 1, element);
+}
+
static StyleSheet& default_stylesheet()
{
static StyleSheet* sheet;