mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 00:57:45 +00:00
LibWeb: Implement the :where() selector
This is identical to :is() except for specificity, so we can use the same code paths. :^)
This commit is contained in:
parent
47eb4b2db7
commit
993653317c
5 changed files with 22 additions and 8 deletions
|
@ -584,13 +584,17 @@ Result<Selector::SimpleSelector, Parser::ParsingResult> Parser::parse_simple_sel
|
|||
};
|
||||
|
||||
auto& pseudo_function = pseudo_class_token.function();
|
||||
if (pseudo_function.name().equals_ignoring_case("is"sv)) {
|
||||
simple_selector.pseudo_class.type = Selector::SimpleSelector::PseudoClass::Type::Is;
|
||||
if (pseudo_function.name().equals_ignoring_case("is"sv)
|
||||
|| pseudo_function.name().equals_ignoring_case("where"sv)) {
|
||||
|
||||
simple_selector.pseudo_class.type = pseudo_function.name().equals_ignoring_case("is"sv)
|
||||
? Selector::SimpleSelector::PseudoClass::Type::Is
|
||||
: Selector::SimpleSelector::PseudoClass::Type::Where;
|
||||
auto function_token_stream = TokenStream(pseudo_function.values());
|
||||
auto is_selector = parse_a_selector_list(function_token_stream, SelectorParsingMode::Forgiving);
|
||||
auto argument_selector_list = parse_a_selector_list(function_token_stream, SelectorParsingMode::Forgiving);
|
||||
// NOTE: Because it's forgiving, even complete garbage will parse OK as an empty selector-list.
|
||||
VERIFY(!is_selector.is_error());
|
||||
simple_selector.pseudo_class.argument_selector_list = is_selector.release_value();
|
||||
VERIFY(!argument_selector_list.is_error());
|
||||
simple_selector.pseudo_class.argument_selector_list = argument_selector_list.release_value();
|
||||
} else if (pseudo_function.name().equals_ignoring_case("not"sv)) {
|
||||
simple_selector.pseudo_class.type = Selector::SimpleSelector::PseudoClass::Type::Not;
|
||||
auto function_token_stream = TokenStream(pseudo_function.values());
|
||||
|
|
|
@ -159,6 +159,7 @@ String Selector::SimpleSelector::serialize() const
|
|||
case Selector::SimpleSelector::PseudoClass::Type::NthLastChild:
|
||||
case Selector::SimpleSelector::PseudoClass::Type::Not:
|
||||
case Selector::SimpleSelector::PseudoClass::Type::Is:
|
||||
case Selector::SimpleSelector::PseudoClass::Type::Where:
|
||||
// Otherwise, append ":" (U+003A), followed by the name of the pseudo-class, followed by "(" (U+0028),
|
||||
// followed by the value of the pseudo-class argument(s) determined as per below, followed by ")" (U+0029), to s.
|
||||
s.append(':');
|
||||
|
@ -169,9 +170,10 @@ String Selector::SimpleSelector::serialize() const
|
|||
// The result of serializing the value using the rules to serialize an <an+b> value.
|
||||
s.append(pseudo_class.nth_child_pattern.serialize());
|
||||
} else if (pseudo_class.type == Selector::SimpleSelector::PseudoClass::Type::Not
|
||||
|| pseudo_class.type == Selector::SimpleSelector::PseudoClass::Type::Is) {
|
||||
|| pseudo_class.type == Selector::SimpleSelector::PseudoClass::Type::Is
|
||||
|| pseudo_class.type == Selector::SimpleSelector::PseudoClass::Type::Where) {
|
||||
// The result of serializing the value using the rules for serializing a group of selectors.
|
||||
// NOTE: `:is()` isn't in the spec for this yet, but it should be!
|
||||
// NOTE: `:is()` and `:where()` aren't in the spec for this yet, but it should be!
|
||||
s.append(serialize_a_group_of_selectors(pseudo_class.argument_selector_list));
|
||||
}
|
||||
s.append(')');
|
||||
|
|
|
@ -77,6 +77,7 @@ public:
|
|||
Checked,
|
||||
Is,
|
||||
Not,
|
||||
Where,
|
||||
Active,
|
||||
};
|
||||
Type type { Type::None };
|
||||
|
@ -216,6 +217,8 @@ constexpr StringView pseudo_class_name(Selector::SimpleSelector::PseudoClass::Ty
|
|||
return "is"sv;
|
||||
case Selector::SimpleSelector::PseudoClass::Type::Not:
|
||||
return "not"sv;
|
||||
case Selector::SimpleSelector::PseudoClass::Type::Where:
|
||||
return "where"sv;
|
||||
case Selector::SimpleSelector::PseudoClass::Type::None:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -155,6 +155,7 @@ static inline bool matches_pseudo_class(CSS::Selector::SimpleSelector::PseudoCla
|
|||
case CSS::Selector::SimpleSelector::PseudoClass::Type::Checked:
|
||||
return matches_checked_pseudo_class(element);
|
||||
case CSS::Selector::SimpleSelector::PseudoClass::Type::Is:
|
||||
case CSS::Selector::SimpleSelector::PseudoClass::Type::Where:
|
||||
for (auto& selector : pseudo_class.argument_selector_list) {
|
||||
if (matches(selector, element))
|
||||
return true;
|
||||
|
|
|
@ -433,11 +433,15 @@ void dump_selector(StringBuilder& builder, CSS::Selector const& selector)
|
|||
case CSS::Selector::SimpleSelector::PseudoClass::Type::Is:
|
||||
pseudo_class_description = "Is";
|
||||
break;
|
||||
case CSS::Selector::SimpleSelector::PseudoClass::Type::Where:
|
||||
pseudo_class_description = "Where";
|
||||
break;
|
||||
}
|
||||
|
||||
builder.appendff(" pseudo_class={}", pseudo_class_description);
|
||||
if (pseudo_class.type == CSS::Selector::SimpleSelector::PseudoClass::Type::Not
|
||||
|| pseudo_class.type == CSS::Selector::SimpleSelector::PseudoClass::Type::Is) {
|
||||
|| pseudo_class.type == CSS::Selector::SimpleSelector::PseudoClass::Type::Is
|
||||
|| pseudo_class.type == CSS::Selector::SimpleSelector::PseudoClass::Type::Where) {
|
||||
builder.append("([");
|
||||
for (auto& selector : pseudo_class.argument_selector_list)
|
||||
dump_selector(builder, selector);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue