mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-09-13 04:52:23 +00:00
LibWeb/CSS: Prepare pseudo-classes for multiple An+B patterns
The upcoming `:heading()` pseudo-class takes multiple comma-separated An+Bs. Also rename this field as the `:nth-[last-]child()` pseudo-classes are only a subset of the users.
This commit is contained in:
parent
c2fc4b25cd
commit
a59c15481f
Notes:
github-actions[bot]
2025-08-13 08:49:02 +00:00
Author: https://github.com/AtkinsSJ
Commit: a59c15481f
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/5830
5 changed files with 15 additions and 14 deletions
|
@ -664,10 +664,10 @@ Parser::ParseErrorOr<Selector::SimpleSelector> Parser::parse_pseudo_simple_selec
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pseudo_class_token.is_function()) {
|
if (pseudo_class_token.is_function()) {
|
||||||
auto parse_nth_child_selector = [this](auto pseudo_class, Vector<ComponentValue> const& function_values, bool allow_of = false) -> ParseErrorOr<Selector::SimpleSelector> {
|
auto parse_an_plus_b_selector = [this](auto pseudo_class, Vector<ComponentValue> const& function_values, bool allow_of) -> ParseErrorOr<Selector::SimpleSelector> {
|
||||||
auto tokens = TokenStream<ComponentValue>(function_values);
|
auto tokens = TokenStream<ComponentValue>(function_values);
|
||||||
auto nth_child_pattern = parse_a_n_plus_b_pattern(tokens);
|
auto an_plus_b_pattern = parse_a_n_plus_b_pattern(tokens);
|
||||||
if (!nth_child_pattern.has_value()) {
|
if (!an_plus_b_pattern.has_value()) {
|
||||||
ErrorReporter::the().report(InvalidPseudoClassOrElementError {
|
ErrorReporter::the().report(InvalidPseudoClassOrElementError {
|
||||||
.name = MUST(String::formatted(":{}", pseudo_class_name(pseudo_class))),
|
.name = MUST(String::formatted(":{}", pseudo_class_name(pseudo_class))),
|
||||||
.value_string = tokens.dump_string(),
|
.value_string = tokens.dump_string(),
|
||||||
|
@ -682,7 +682,7 @@ Parser::ParseErrorOr<Selector::SimpleSelector> Parser::parse_pseudo_simple_selec
|
||||||
.type = Selector::SimpleSelector::Type::PseudoClass,
|
.type = Selector::SimpleSelector::Type::PseudoClass,
|
||||||
.value = Selector::SimpleSelector::PseudoClassSelector {
|
.value = Selector::SimpleSelector::PseudoClassSelector {
|
||||||
.type = pseudo_class,
|
.type = pseudo_class,
|
||||||
.nth_child_pattern = nth_child_pattern.release_value() }
|
.an_plus_b_patterns = Vector { an_plus_b_pattern.release_value() } }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -705,7 +705,7 @@ Parser::ParseErrorOr<Selector::SimpleSelector> Parser::parse_pseudo_simple_selec
|
||||||
.type = Selector::SimpleSelector::Type::PseudoClass,
|
.type = Selector::SimpleSelector::Type::PseudoClass,
|
||||||
.value = Selector::SimpleSelector::PseudoClassSelector {
|
.value = Selector::SimpleSelector::PseudoClassSelector {
|
||||||
.type = pseudo_class,
|
.type = pseudo_class,
|
||||||
.nth_child_pattern = nth_child_pattern.release_value(),
|
.an_plus_b_patterns = Vector { an_plus_b_pattern.release_value() },
|
||||||
.argument_selector_list = move(selector_list) }
|
.argument_selector_list = move(selector_list) }
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -755,9 +755,9 @@ Parser::ParseErrorOr<Selector::SimpleSelector> Parser::parse_pseudo_simple_selec
|
||||||
|
|
||||||
switch (metadata.parameter_type) {
|
switch (metadata.parameter_type) {
|
||||||
case PseudoClassMetadata::ParameterType::ANPlusB:
|
case PseudoClassMetadata::ParameterType::ANPlusB:
|
||||||
return parse_nth_child_selector(pseudo_class, pseudo_function.value, false);
|
return parse_an_plus_b_selector(pseudo_class, pseudo_function.value, false);
|
||||||
case PseudoClassMetadata::ParameterType::ANPlusBOf:
|
case PseudoClassMetadata::ParameterType::ANPlusBOf:
|
||||||
return parse_nth_child_selector(pseudo_class, pseudo_function.value, true);
|
return parse_an_plus_b_selector(pseudo_class, pseudo_function.value, true);
|
||||||
case PseudoClassMetadata::ParameterType::CompoundSelector: {
|
case PseudoClassMetadata::ParameterType::CompoundSelector: {
|
||||||
auto function_token_stream = TokenStream(pseudo_function.value);
|
auto function_token_stream = TokenStream(pseudo_function.value);
|
||||||
auto compound_selector_or_error = parse_compound_selector(function_token_stream);
|
auto compound_selector_or_error = parse_compound_selector(function_token_stream);
|
||||||
|
|
|
@ -460,7 +460,7 @@ String Selector::SimpleSelector::serialize() const
|
||||||
case PseudoClassMetadata::ParameterType::ANPlusB:
|
case PseudoClassMetadata::ParameterType::ANPlusB:
|
||||||
case PseudoClassMetadata::ParameterType::ANPlusBOf:
|
case PseudoClassMetadata::ParameterType::ANPlusBOf:
|
||||||
// The result of serializing the value using the rules to serialize an <an+b> value.
|
// The result of serializing the value using the rules to serialize an <an+b> value.
|
||||||
s.append(pseudo_class.nth_child_pattern.serialize());
|
s.append(pseudo_class.an_plus_b_patterns.first().serialize());
|
||||||
break;
|
break;
|
||||||
case PseudoClassMetadata::ParameterType::CompoundSelector:
|
case PseudoClassMetadata::ParameterType::CompoundSelector:
|
||||||
case PseudoClassMetadata::ParameterType::ForgivingSelectorList:
|
case PseudoClassMetadata::ParameterType::ForgivingSelectorList:
|
||||||
|
|
|
@ -124,9 +124,8 @@ public:
|
||||||
struct PseudoClassSelector {
|
struct PseudoClassSelector {
|
||||||
PseudoClass type;
|
PseudoClass type;
|
||||||
|
|
||||||
// FIXME: We don't need this field on every single SimpleSelector, but it's also annoying to malloc it somewhere.
|
// Used for the :nth-*() pseudo-classes, and :heading()
|
||||||
// Only used when "pseudo_class" is "NthChild" or "NthLastChild".
|
Vector<ANPlusBPattern> an_plus_b_patterns {};
|
||||||
ANPlusBPattern nth_child_pattern {};
|
|
||||||
|
|
||||||
// FIXME: This would make more sense as part of SelectorList but that's currently a `using`
|
// FIXME: This would make more sense as part of SelectorList but that's currently a `using`
|
||||||
bool is_forgiving { false };
|
bool is_forgiving { false };
|
||||||
|
|
|
@ -670,8 +670,9 @@ static inline bool matches_pseudo_class(CSS::Selector::SimpleSelector::PseudoCla
|
||||||
case CSS::PseudoClass::NthLastChild:
|
case CSS::PseudoClass::NthLastChild:
|
||||||
case CSS::PseudoClass::NthOfType:
|
case CSS::PseudoClass::NthOfType:
|
||||||
case CSS::PseudoClass::NthLastOfType: {
|
case CSS::PseudoClass::NthLastOfType: {
|
||||||
auto const step_size = pseudo_class.nth_child_pattern.step_size;
|
auto& an_plus_b = pseudo_class.an_plus_b_patterns.first();
|
||||||
auto const offset = pseudo_class.nth_child_pattern.offset;
|
auto const step_size = an_plus_b.step_size;
|
||||||
|
auto const offset = an_plus_b.offset;
|
||||||
if (step_size == 0 && offset == 0)
|
if (step_size == 0 && offset == 0)
|
||||||
return false; // "If both a and b are equal to zero, the pseudo-class represents no element in the document tree."
|
return false; // "If both a and b are equal to zero, the pseudo-class represents no element in the document tree."
|
||||||
|
|
||||||
|
|
|
@ -563,7 +563,8 @@ void dump_selector(StringBuilder& builder, CSS::Selector const& selector, int in
|
||||||
break;
|
break;
|
||||||
case CSS::PseudoClassMetadata::ParameterType::ANPlusB:
|
case CSS::PseudoClassMetadata::ParameterType::ANPlusB:
|
||||||
case CSS::PseudoClassMetadata::ParameterType::ANPlusBOf: {
|
case CSS::PseudoClassMetadata::ParameterType::ANPlusBOf: {
|
||||||
builder.appendff("(step={}, offset={}", pseudo_class.nth_child_pattern.step_size, pseudo_class.nth_child_pattern.offset);
|
auto& an_plus_b = pseudo_class.an_plus_b_patterns.first();
|
||||||
|
builder.appendff("(step={}, offset={}", an_plus_b.step_size, an_plus_b.offset);
|
||||||
if (!pseudo_class.argument_selector_list.is_empty()) {
|
if (!pseudo_class.argument_selector_list.is_empty()) {
|
||||||
builder.append(", selectors=[\n"sv);
|
builder.append(", selectors=[\n"sv);
|
||||||
for (auto const& child_selector : pseudo_class.argument_selector_list)
|
for (auto const& child_selector : pseudo_class.argument_selector_list)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue