diff options
author | Andreas Kling <kling@serenityos.org> | 2022-02-17 22:43:22 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-02-18 01:49:32 +0100 |
commit | 7c33a084fb6e8e751173b6c959c30533b3f02f23 (patch) | |
tree | e5e70482a2a9d383e02b1e443f6806cdd0e47d24 /Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp | |
parent | b9b24cb1c1c73fbcbdc9bec6b9b2bf8e47efa4a6 (diff) | |
download | serenity-7c33a084fb6e8e751173b6c959c30533b3f02f23.zip |
LibWeb: Support CSS :only-of-type selector
This matches any element that doesn't have a sibling with the same tag
name as itself.
Diffstat (limited to 'Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp')
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp | 32 |
1 files changed, 22 insertions, 10 deletions
diff --git a/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp b/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp index cb13ee86ed..40be51417f 100644 --- a/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp +++ b/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp @@ -53,6 +53,24 @@ static inline bool matches_attribute(CSS::Selector::SimpleSelector::Attribute co return false; } +static inline DOM::Element const* previous_sibling_with_same_tag_name(DOM::Element const& element) +{ + for (auto const* sibling = element.previous_element_sibling(); sibling; sibling = sibling->previous_element_sibling()) { + if (sibling->tag_name() == element.tag_name()) + return sibling; + } + return nullptr; +} + +static inline DOM::Element const* next_sibling_with_same_tag_name(DOM::Element const& element) +{ + for (auto const* sibling = element.next_element_sibling(); sibling; sibling = sibling->next_element_sibling()) { + if (sibling->tag_name() == element.tag_name()) + return sibling; + } + return nullptr; +} + static inline bool matches_pseudo_class(CSS::Selector::SimpleSelector::PseudoClass const& pseudo_class, DOM::Element const& element) { switch (pseudo_class.type) { @@ -80,17 +98,11 @@ static inline bool matches_pseudo_class(CSS::Selector::SimpleSelector::PseudoCla case CSS::Selector::SimpleSelector::PseudoClass::Type::Root: return is<HTML::HTMLHtmlElement>(element); case CSS::Selector::SimpleSelector::PseudoClass::Type::FirstOfType: - for (auto* sibling = element.previous_element_sibling(); sibling; sibling = sibling->previous_element_sibling()) { - if (sibling->tag_name() == element.tag_name()) - return false; - } - return true; + return !previous_sibling_with_same_tag_name(element); case CSS::Selector::SimpleSelector::PseudoClass::Type::LastOfType: - for (auto* sibling = element.next_element_sibling(); sibling; sibling = sibling->next_element_sibling()) { - if (sibling->tag_name() == element.tag_name()) - return false; - } - return true; + return !next_sibling_with_same_tag_name(element); + case CSS::Selector::SimpleSelector::PseudoClass::Type::OnlyOfType: + return !previous_sibling_with_same_tag_name(element) && !next_sibling_with_same_tag_name(element); case CSS::Selector::SimpleSelector::PseudoClass::Type::Disabled: if (!element.tag_name().equals_ignoring_case(HTML::TagNames::input)) return false; |