mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-09-13 13:02:28 +00:00
LibWeb/CSS: Move An+B matching code into ANPlusBPattern::matches()
Not everything we want to match is an "nth element". Also moved its serialization function's implementation out of the header while I was at it.
This commit is contained in:
parent
a59c15481f
commit
fbae3b824a
Notes:
github-actions[bot]
2025-08-13 08:48:55 +00:00
Author: https://github.com/AtkinsSJ
Commit: fbae3b824a
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/5830
3 changed files with 77 additions and 70 deletions
|
@ -823,4 +823,77 @@ SelectorList adapt_nested_relative_selector_list(SelectorList const& selectors)
|
|||
return new_list;
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/css-syntax-3/#anb-microsyntax
|
||||
bool Selector::SimpleSelector::ANPlusBPattern::matches(int index) const
|
||||
{
|
||||
// "If both a and b are equal to zero, the pseudo-class represents no element in the document tree."
|
||||
if (step_size == 0 && offset == 0)
|
||||
return false;
|
||||
|
||||
// When "step_size == -1", selector represents first "offset" elements in document tree.
|
||||
if (step_size == -1)
|
||||
return !(offset <= 0 || index > offset);
|
||||
|
||||
// When "step_size == 1", selector represents last "offset" elements in document tree.
|
||||
if (step_size == 1)
|
||||
return !(offset < 0 || index < offset);
|
||||
|
||||
// When "step_size == 0", selector picks only the "offset" element.
|
||||
if (step_size == 0)
|
||||
return index == offset;
|
||||
|
||||
// If both are negative, nothing can match.
|
||||
if (step_size < 0 && offset < 0)
|
||||
return false;
|
||||
|
||||
// Like "a % b", but handles negative integers correctly.
|
||||
auto const canonical_modulo = [](int a, int b) -> int {
|
||||
int c = a % b;
|
||||
if ((c < 0 && b > 0) || (c > 0 && b < 0)) {
|
||||
c += b;
|
||||
}
|
||||
return c;
|
||||
};
|
||||
|
||||
// When "step_size < 0", we start at "offset" and count backwards.
|
||||
if (step_size < 0)
|
||||
return index <= offset && canonical_modulo(index - offset, -step_size) == 0;
|
||||
|
||||
// Otherwise, we start at "offset" and count forwards.
|
||||
return index >= offset && canonical_modulo(index - offset, step_size) == 0;
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/css-syntax-3/#serializing-anb
|
||||
String Selector::SimpleSelector::ANPlusBPattern::serialize() const
|
||||
{
|
||||
// 1. If A is zero, return the serialization of B.
|
||||
if (step_size == 0)
|
||||
return String::number(offset);
|
||||
|
||||
// 2. Otherwise, let result initially be an empty string.
|
||||
StringBuilder result;
|
||||
|
||||
// 3.
|
||||
// - A is 1: Append "n" to result.
|
||||
if (step_size == 1)
|
||||
result.append('n');
|
||||
// - A is -1: Append "-n" to result.
|
||||
else if (step_size == -1)
|
||||
result.append("-n"sv);
|
||||
// - A is non-zero: Serialize A and append it to result, then append "n" to result.
|
||||
else if (step_size != 0)
|
||||
result.appendff("{}n", step_size);
|
||||
|
||||
// 4.
|
||||
// - B is greater than zero: Append "+" to result, then append the serialization of B to result.
|
||||
if (offset > 0)
|
||||
result.appendff("+{}", offset);
|
||||
// - B is less than zero: Append the serialization of B to result.
|
||||
else if (offset < 0)
|
||||
result.appendff("{}", offset);
|
||||
|
||||
// 5. Return result.
|
||||
return MUST(result.to_string());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -86,39 +86,8 @@ public:
|
|||
int step_size { 0 }; // "A"
|
||||
int offset = { 0 }; // "B"
|
||||
|
||||
// https://www.w3.org/TR/css-syntax-3/#serializing-anb
|
||||
String serialize() const
|
||||
{
|
||||
// 1. If A is zero, return the serialization of B.
|
||||
if (step_size == 0) {
|
||||
return String::number(offset);
|
||||
}
|
||||
|
||||
// 2. Otherwise, let result initially be an empty string.
|
||||
StringBuilder result;
|
||||
|
||||
// 3.
|
||||
// - A is 1: Append "n" to result.
|
||||
if (step_size == 1)
|
||||
result.append('n');
|
||||
// - A is -1: Append "-n" to result.
|
||||
else if (step_size == -1)
|
||||
result.append("-n"sv);
|
||||
// - A is non-zero: Serialize A and append it to result, then append "n" to result.
|
||||
else if (step_size != 0)
|
||||
result.appendff("{}n", step_size);
|
||||
|
||||
// 4.
|
||||
// - B is greater than zero: Append "+" to result, then append the serialization of B to result.
|
||||
if (offset > 0)
|
||||
result.appendff("+{}", offset);
|
||||
// - B is less than zero: Append the serialization of B to result.
|
||||
if (offset < 0)
|
||||
result.appendff("{}", offset);
|
||||
|
||||
// 5. Return result.
|
||||
return MUST(result.to_string());
|
||||
}
|
||||
bool matches(int index) const;
|
||||
String serialize() const;
|
||||
};
|
||||
|
||||
struct PseudoClassSelector {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2024, Andreas Kling <andreas@ladybird.org>
|
||||
* Copyright (c) 2021-2024, Sam Atkins <sam@ladybird.org>
|
||||
* Copyright (c) 2021-2025, Sam Atkins <sam@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -671,10 +671,6 @@ static inline bool matches_pseudo_class(CSS::Selector::SimpleSelector::PseudoCla
|
|||
case CSS::PseudoClass::NthOfType:
|
||||
case CSS::PseudoClass::NthLastOfType: {
|
||||
auto& an_plus_b = pseudo_class.an_plus_b_patterns.first();
|
||||
auto const step_size = an_plus_b.step_size;
|
||||
auto const offset = an_plus_b.offset;
|
||||
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."
|
||||
|
||||
auto const* parent = element.parent();
|
||||
if (!parent)
|
||||
|
@ -730,38 +726,7 @@ static inline bool matches_pseudo_class(CSS::Selector::SimpleSelector::PseudoCla
|
|||
default:
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
// When "step_size == -1", selector represents first "offset" elements in document tree.
|
||||
if (step_size == -1)
|
||||
return !(offset <= 0 || index > offset);
|
||||
|
||||
// When "step_size == 1", selector represents last "offset" elements in document tree.
|
||||
if (step_size == 1)
|
||||
return !(offset < 0 || index < offset);
|
||||
|
||||
// When "step_size == 0", selector picks only the "offset" element.
|
||||
if (step_size == 0)
|
||||
return index == offset;
|
||||
|
||||
// If both are negative, nothing can match.
|
||||
if (step_size < 0 && offset < 0)
|
||||
return false;
|
||||
|
||||
// Like "a % b", but handles negative integers correctly.
|
||||
auto const canonical_modulo = [](int a, int b) -> int {
|
||||
int c = a % b;
|
||||
if ((c < 0 && b > 0) || (c > 0 && b < 0)) {
|
||||
c += b;
|
||||
}
|
||||
return c;
|
||||
};
|
||||
|
||||
// When "step_size < 0", we start at "offset" and count backwards.
|
||||
if (step_size < 0)
|
||||
return index <= offset && canonical_modulo(index - offset, -step_size) == 0;
|
||||
|
||||
// Otherwise, we start at "offset" and count forwards.
|
||||
return index >= offset && canonical_modulo(index - offset, step_size) == 0;
|
||||
return an_plus_b.matches(index);
|
||||
}
|
||||
case CSS::PseudoClass::Playing: {
|
||||
if (!is<HTML::HTMLMediaElement>(element))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue