mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-09-21 16:58:58 +00:00
LibWeb/CSS: Serialize :heading(...) pseudo-class properly
We originally had special handling for `:host()` as that had been the only pseudo-class that could be both an identifier or a function. However, this meant duplicating the serialization logic, and also we had to manually remember to add the same hack for any other identifier-and-function cases. Which I forgot to do with `:heading()`! So instead, for these cases, detect if they actually have arguments specified and use that to determine which form to serialize as. We do still have to write a check for each one of these pseudo-classes, but the VERIFY should make it easier to remember.
This commit is contained in:
parent
277b81ca97
commit
9ffc15ba3f
Notes:
github-actions[bot]
2025-08-28 10:41:37 +00:00
Author: https://github.com/AtkinsSJ
Commit: 9ffc15ba3f
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/6009
Reviewed-by: https://github.com/gmta ✅
3 changed files with 88 additions and 14 deletions
|
@ -427,22 +427,24 @@ String Selector::SimpleSelector::serialize() const
|
|||
auto& pseudo_class = this->pseudo_class();
|
||||
|
||||
auto metadata = pseudo_class_metadata(pseudo_class.type);
|
||||
// HACK: `:host()` has both a function and a non-function form, so handle that first.
|
||||
// It's also not in the spec.
|
||||
if (pseudo_class.type == PseudoClass::Host) {
|
||||
if (pseudo_class.argument_selector_list.is_empty()) {
|
||||
s.append(':');
|
||||
s.append(pseudo_class_name(pseudo_class.type));
|
||||
} else {
|
||||
s.append(':');
|
||||
s.append(pseudo_class_name(pseudo_class.type));
|
||||
s.append('(');
|
||||
s.append(serialize_a_group_of_selectors(pseudo_class.argument_selector_list));
|
||||
s.append(')');
|
||||
bool accepts_arguments = [&]() {
|
||||
if (!metadata.is_valid_as_function)
|
||||
return false;
|
||||
if (!metadata.is_valid_as_identifier)
|
||||
return true;
|
||||
// For pseudo-classes with both a function and identifier form, see if they have arguments.
|
||||
switch (pseudo_class.type) {
|
||||
case PseudoClass::Heading:
|
||||
return !pseudo_class.an_plus_b_patterns.is_empty();
|
||||
case PseudoClass::Host:
|
||||
return !pseudo_class.argument_selector_list.is_empty();
|
||||
default:
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
}();
|
||||
|
||||
// If the pseudo-class does not accept arguments append ":" (U+003A), followed by the name of the pseudo-class, to s.
|
||||
else if (metadata.is_valid_as_identifier) {
|
||||
if (!accepts_arguments) {
|
||||
s.append(':');
|
||||
s.append(pseudo_class_name(pseudo_class.type));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 28 tests
|
||||
|
||||
17 Pass
|
||||
11 Fail
|
||||
Pass ":heading" should be a valid selector
|
||||
Pass ":heading(2)" should be a valid selector
|
||||
Pass ":heading(99999)" should be a valid selector
|
||||
Pass ":heading(0)" should be a valid selector
|
||||
Pass ":heading(0, 1, 2)" should be a valid selector
|
||||
Pass ":heading(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)" should be a valid selector
|
||||
Pass ":heading(-1)" should be a valid selector
|
||||
Pass "h1:heading" should be a valid selector
|
||||
Pass "h1:heading(1)" should be a valid selector
|
||||
Pass "h1:heading(2)" should be a valid selector
|
||||
Pass ":heading()" should be an invalid selector
|
||||
Pass ":heading(1.0)" should be an invalid selector
|
||||
Pass ":heading(1.4)" should be an invalid selector
|
||||
Fail ":heading(n)" should be an invalid selector
|
||||
Fail ":heading(odd)" should be an invalid selector
|
||||
Fail ":heading(even)" should be an invalid selector
|
||||
Fail ":heading(2n)" should be an invalid selector
|
||||
Fail ":heading(2n+1)" should be an invalid selector
|
||||
Fail ":heading(2n+2)" should be an invalid selector
|
||||
Fail ":heading(-n+3)" should be an invalid selector
|
||||
Fail ":heading(2n, 3n)" should be an invalid selector
|
||||
Fail ":heading(2, 3n)" should be an invalid selector
|
||||
Fail ":heading(2 of .foo)" should be an invalid selector
|
||||
Fail ":heading(2n of .foo)" should be an invalid selector
|
||||
Pass ":heading(calc(1))" should be an invalid selector
|
||||
Pass ":heading(max(1, 2))" should be an invalid selector
|
||||
Pass ":heading(min(1, 2)" should be an invalid selector
|
||||
Pass ":heading(var(--level))" should be an invalid selector
|
|
@ -0,0 +1,38 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Selectors: The heading pseudo-classes</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/selectors-5/#headings">
|
||||
<script src="../../../resources/testharness.js"></script>
|
||||
<script src="../../../resources/testharnessreport.js"></script>
|
||||
<script src="../../../css/support/parsing-testcommon.js"></script>
|
||||
<script>
|
||||
test_valid_selector(':heading');
|
||||
test_valid_selector(':heading(2)');
|
||||
test_valid_selector(':heading(99999)');
|
||||
test_valid_selector(':heading(0)');
|
||||
test_valid_selector(':heading(0, 1, 2)');
|
||||
test_valid_selector(':heading(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)');
|
||||
test_valid_selector(':heading(-1)');
|
||||
test_valid_selector('h1:heading');
|
||||
test_valid_selector('h1:heading(1)');
|
||||
test_valid_selector('h1:heading(2)');
|
||||
|
||||
test_invalid_selector(':heading()');
|
||||
test_invalid_selector(':heading(1.0)');
|
||||
test_invalid_selector(':heading(1.4)');
|
||||
test_invalid_selector(':heading(n)');
|
||||
test_invalid_selector(':heading(odd)');
|
||||
test_invalid_selector(':heading(even)');
|
||||
test_invalid_selector(':heading(2n)');
|
||||
test_invalid_selector(':heading(2n+1)');
|
||||
test_invalid_selector(':heading(2n+2)');
|
||||
test_invalid_selector(':heading(-n+3)');
|
||||
test_invalid_selector(':heading(2n, 3n)');
|
||||
test_invalid_selector(':heading(2, 3n)');
|
||||
test_invalid_selector(':heading(2 of .foo)');
|
||||
test_invalid_selector(':heading(2n of .foo)');
|
||||
test_invalid_selector(':heading(calc(1))');
|
||||
test_invalid_selector(':heading(max(1, 2))');
|
||||
test_invalid_selector(':heading(min(1, 2)');
|
||||
test_invalid_selector(':heading(var(--level))');
|
||||
</script>
|
Loading…
Add table
Add a link
Reference in a new issue