LibWeb/CSS: Parse the ::slotted pseudo-element

This commit is contained in:
Shannon Booth 2025-07-12 16:15:06 +12:00 committed by Sam Atkins
commit 9054ff29f0
Notes: github-actions[bot] 2025-07-15 12:55:25 +00:00
10 changed files with 141 additions and 21 deletions

View file

@ -466,6 +466,20 @@ Parser::ParseErrorOr<Selector::SimpleSelector> Parser::parse_pseudo_simple_selec
return ParseError::SyntaxError;
}
break;
case PseudoElementMetadata::ParameterType::CompoundSelector: {
auto compound_selector_or_error = parse_compound_selector(function_tokens);
if (compound_selector_or_error.is_error() || !compound_selector_or_error.value().has_value()) {
dbgln_if(CSS_PARSER_DEBUG, "Failed to parse ::{}() parameter as a compound selector", pseudo_name);
return ParseError::SyntaxError;
}
auto compound_selector = compound_selector_or_error.release_value().release_value();
compound_selector.combinator = Selector::Combinator::None;
Vector compound_selectors { move(compound_selector) };
value = Selector::create(move(compound_selectors));
break;
}
case PseudoElementMetadata::ParameterType::PTNameSelector: {
// <pt-name-selector> = '*' | <custom-ident>
// https://drafts.csswg.org/css-view-transitions-1/#typedef-pt-name-selector

View file

@ -110,6 +110,11 @@
"slider-track": {
"spec": "https://drafts.csswg.org/css-forms-1/#selectordef-slider-track"
},
"slotted": {
"spec": "https://drafts.csswg.org/css-scoping/#slotted-pseudo",
"type": "function",
"function-syntax": "<compound-selector>"
},
"view-transition": {
"spec": "https://drafts.csswg.org/css-view-transitions-1/#selectordef-view-transition",
"is-pseudo-root": true

View file

@ -294,6 +294,11 @@ String Selector::PseudoElementSelector::serialize() const
}
m_value.visit(
[&builder](NonnullRefPtr<Selector> const& compund_selector) {
builder.append('(');
builder.append(compund_selector->serialize());
builder.append(')');
},
[&builder](PTNameSelector const& pt_name_selector) {
builder.append('(');
if (pt_name_selector.is_universal)

View file

@ -31,7 +31,7 @@ public:
FlyString value {};
};
using Value = Variant<Empty, PTNameSelector>;
using Value = Variant<Empty, PTNameSelector, NonnullRefPtr<Selector>>;
explicit PseudoElementSelector(PseudoElement type, Value value = {})
: m_type(type)
@ -60,10 +60,13 @@ public:
PTNameSelector const& pt_name_selector() const { return m_value.get<PTNameSelector>(); }
// NOTE: This can't (currently) be a CompoundSelector due to cyclic dependencies.
Selector const& compound_selector() const { return m_value.get<NonnullRefPtr<Selector>>(); }
private:
PseudoElement m_type;
String m_name;
Variant<Empty, PTNameSelector> m_value;
Value m_value;
};
struct SimpleSelector {