diff options
author | Andreas Kling <awesomekling@gmail.com> | 2019-10-06 15:34:42 +0200 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-10-06 15:34:42 +0200 |
commit | 156b35742a947c7179bd4f6cbad363eb8918a261 (patch) | |
tree | 0110320052905159ccc73acc94d0b8fc0e47fce7 /Libraries/LibHTML/CSS/StyleResolver.cpp | |
parent | b587eb2f4d3c8794cf6dd68b0fa9cac65a1424bb (diff) | |
download | serenity-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.cpp | 32 |
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; |