diff --git a/Libraries/LibWeb/CSS/Selector.h b/Libraries/LibWeb/CSS/Selector.h index f1ff146582..84f8ad21fa 100644 --- a/Libraries/LibWeb/CSS/Selector.h +++ b/Libraries/LibWeb/CSS/Selector.h @@ -63,6 +63,7 @@ public: None, HasAttribute, ExactValueMatch, + Contains, }; AttributeMatchType attribute_match_type { AttributeMatchType::None }; diff --git a/Libraries/LibWeb/CSS/SelectorEngine.cpp b/Libraries/LibWeb/CSS/SelectorEngine.cpp index 12470c5d8a..a2a89c911f 100644 --- a/Libraries/LibWeb/CSS/SelectorEngine.cpp +++ b/Libraries/LibWeb/CSS/SelectorEngine.cpp @@ -91,6 +91,10 @@ bool matches(const Selector::SimpleSelector& component, const Element& element) if (element.attribute(component.attribute_name) != component.attribute_value) return false; break; + case Selector::SimpleSelector::AttributeMatchType::Contains: + if (!element.attribute(component.attribute_name).split(' ').contains_slow(component.attribute_value)) + return false; + break; default: break; } diff --git a/Libraries/LibWeb/Dump.cpp b/Libraries/LibWeb/Dump.cpp index 77c3acc95b..42ce636a19 100644 --- a/Libraries/LibWeb/Dump.cpp +++ b/Libraries/LibWeb/Dump.cpp @@ -242,6 +242,9 @@ void dump_selector(const Selector& selector) case Selector::SimpleSelector::AttributeMatchType::ExactValueMatch: attribute_match_type_description = "ExactValueMatch"; break; + case Selector::SimpleSelector::AttributeMatchType::Contains: + attribute_match_type_description = "Contains"; + break; } dbgprintf("%s:%s", type_description, simple_selector.value.characters()); diff --git a/Libraries/LibWeb/Parser/CSSParser.cpp b/Libraries/LibWeb/Parser/CSSParser.cpp index 507ff8320d..a8ac658606 100644 --- a/Libraries/LibWeb/Parser/CSSParser.cpp +++ b/Libraries/LibWeb/Parser/CSSParser.cpp @@ -472,8 +472,13 @@ public: char expected_end_of_attribute_selector = ']'; while (peek() != expected_end_of_attribute_selector) { char ch = consume_one(); - if (ch == '=') { - attribute_match_type = Selector::SimpleSelector::AttributeMatchType::ExactValueMatch; + if (ch == '=' || (ch == '~' && peek() == '=')) { + if (ch == '=') { + attribute_match_type = Selector::SimpleSelector::AttributeMatchType::ExactValueMatch; + } else if (ch == '~') { + consume_one(); + attribute_match_type = Selector::SimpleSelector::AttributeMatchType::Contains; + } attribute_name = String::copy(buffer); buffer.clear(); in_value = true;