mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-20 11:36:10 +00:00
LibWeb/CSS: Implement aliases for pseudo-elements
We previously supported a few -webkit vendor-prefixed pseudo-elements. This patch adds those back, along with -moz equivalents, by aliasing them to standard ones. They behave identically, except for serializing with their original name, just like for unrecognized -webkit pseudo-elements. It's likely to be a while before the forms spec settles and authors start using the new pseudo-elements, so until then, we can still make use of styles they've written for the non-standard ones.
This commit is contained in:
parent
2c86fd539d
commit
193adee164
Notes:
github-actions[bot]
2025-03-24 09:51:08 +00:00
Author: https://github.com/AtkinsSJ Commit: https://github.com/LadybirdBrowser/ladybird/commit/193adee164a Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/4021
3 changed files with 89 additions and 3 deletions
|
@ -430,6 +430,20 @@ Parser::ParseErrorOr<Selector::SimpleSelector> Parser::parse_pseudo_simple_selec
|
|||
};
|
||||
}
|
||||
|
||||
// Aliased pseudo-elements behave like their target pseudo-element, but serialize as themselves. So store their
|
||||
// name like we do for unknown -webkit pseudos below.
|
||||
if (auto pseudo_element = aliased_pseudo_element_from_string(pseudo_name); pseudo_element.has_value()) {
|
||||
// :has() is fussy about pseudo-elements inside it
|
||||
if (m_pseudo_class_context.contains_slow(PseudoClass::Has) && !is_has_allowed_pseudo_element(*pseudo_element)) {
|
||||
return ParseError::SyntaxError;
|
||||
}
|
||||
|
||||
return Selector::SimpleSelector {
|
||||
.type = Selector::SimpleSelector::Type::PseudoElement,
|
||||
.value = Selector::PseudoElementSelector { pseudo_element.release_value(), pseudo_name.to_string().to_ascii_lowercase() }
|
||||
};
|
||||
}
|
||||
|
||||
// https://www.w3.org/TR/selectors-4/#compat
|
||||
// All other pseudo-elements whose names begin with the string “-webkit-” (matched ASCII case-insensitively)
|
||||
// and that are not functional notations must be treated as valid at parse time. (That is, ::-webkit-asdf is
|
||||
|
|
|
@ -1,4 +1,34 @@
|
|||
{
|
||||
"-moz-meter-bar": {
|
||||
"alias-for": "fill"
|
||||
},
|
||||
"-moz-progress-bar": {
|
||||
"alias-for": "fill"
|
||||
},
|
||||
"-moz-range-progress": {
|
||||
"alias-for": "fill"
|
||||
},
|
||||
"-moz-range-track": {
|
||||
"alias-for": "track"
|
||||
},
|
||||
"-moz-range-thumb": {
|
||||
"alias-for": "thumb"
|
||||
},
|
||||
"-webkit-meter-bar": {
|
||||
"alias-for": "track"
|
||||
},
|
||||
"-webkit-progress-bar": {
|
||||
"alias-for": "track"
|
||||
},
|
||||
"-webkit-progress-value": {
|
||||
"alias-for": "fill"
|
||||
},
|
||||
"-webkit-slider-runnable-track": {
|
||||
"alias-for": "track"
|
||||
},
|
||||
"-webkit-slider-thumb": {
|
||||
"alias-for": "thumb"
|
||||
},
|
||||
"after": {
|
||||
"spec": "https://drafts.csswg.org/css-pseudo-4/#selectordef-after",
|
||||
"is-generated": true
|
||||
|
|
|
@ -64,7 +64,11 @@ namespace Web::CSS {
|
|||
enum class PseudoElement : @pseudo_element_underlying_type@ {
|
||||
)~~~");
|
||||
|
||||
pseudo_elements_data.for_each_member([&](auto& name, auto&) {
|
||||
pseudo_elements_data.for_each_member([&](auto& name, JsonValue const& value) {
|
||||
auto& pseudo_element = value.as_object();
|
||||
if (pseudo_element.has("alias-for"sv))
|
||||
return;
|
||||
|
||||
auto member_generator = generator.fork();
|
||||
member_generator.set("name:titlecase", title_casify(name));
|
||||
|
||||
|
@ -77,6 +81,7 @@ enum class PseudoElement : @pseudo_element_underlying_type@ {
|
|||
};
|
||||
|
||||
Optional<PseudoElement> pseudo_element_from_string(StringView);
|
||||
Optional<PseudoElement> aliased_pseudo_element_from_string(StringView);
|
||||
StringView pseudo_element_name(PseudoElement);
|
||||
|
||||
bool is_has_allowed_pseudo_element(PseudoElement);
|
||||
|
@ -119,7 +124,10 @@ Optional<PseudoElement> pseudo_element_from_string(StringView string)
|
|||
{
|
||||
)~~~");
|
||||
|
||||
pseudo_elements_data.for_each_member([&](auto& name, auto&) {
|
||||
pseudo_elements_data.for_each_member([&](auto& name, JsonValue const& value) {
|
||||
auto& pseudo_element = value.as_object();
|
||||
if (pseudo_element.has("alias-for"sv))
|
||||
return;
|
||||
auto member_generator = generator.fork();
|
||||
member_generator.set("name", name);
|
||||
member_generator.set("name:titlecase", title_casify(name));
|
||||
|
@ -135,12 +143,40 @@ Optional<PseudoElement> pseudo_element_from_string(StringView string)
|
|||
return {};
|
||||
}
|
||||
|
||||
Optional<PseudoElement> aliased_pseudo_element_from_string(StringView string)
|
||||
{
|
||||
)~~~");
|
||||
|
||||
pseudo_elements_data.for_each_member([&](auto& name, JsonValue const& value) {
|
||||
auto& pseudo_element = value.as_object();
|
||||
auto alias_for = pseudo_element.get_string("alias-for"sv);
|
||||
if (!alias_for.has_value())
|
||||
return;
|
||||
|
||||
auto member_generator = generator.fork();
|
||||
member_generator.set("name", name);
|
||||
member_generator.set("alias:titlecase", title_casify(alias_for.value()));
|
||||
|
||||
member_generator.append(R"~~~(
|
||||
if (string.equals_ignoring_ascii_case("@name@"sv))
|
||||
return PseudoElement::@alias:titlecase@;
|
||||
)~~~");
|
||||
});
|
||||
|
||||
generator.append(R"~~~(
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
StringView pseudo_element_name(PseudoElement pseudo_element)
|
||||
{
|
||||
switch (pseudo_element) {
|
||||
)~~~");
|
||||
|
||||
pseudo_elements_data.for_each_member([&](auto& name, auto&) {
|
||||
pseudo_elements_data.for_each_member([&](auto& name, JsonValue const& value) {
|
||||
auto& pseudo_element = value.as_object();
|
||||
if (pseudo_element.has("alias-for"sv))
|
||||
return;
|
||||
auto member_generator = generator.fork();
|
||||
member_generator.set("name", name);
|
||||
member_generator.set("name:titlecase", title_casify(name));
|
||||
|
@ -166,6 +202,8 @@ bool is_has_allowed_pseudo_element(PseudoElement pseudo_element)
|
|||
|
||||
pseudo_elements_data.for_each_member([&](auto& name, JsonValue const& value) {
|
||||
auto& pseudo_element = value.as_object();
|
||||
if (pseudo_element.has("alias-for"sv))
|
||||
return;
|
||||
if (!pseudo_element.get_bool("is-allowed-in-has"sv).value_or(false))
|
||||
return;
|
||||
|
||||
|
@ -191,6 +229,8 @@ Optional<GeneratedPseudoElement> to_generated_pseudo_element(PseudoElement pseud
|
|||
|
||||
pseudo_elements_data.for_each_member([&](auto& name, JsonValue const& value) {
|
||||
auto& pseudo_element = value.as_object();
|
||||
if (pseudo_element.has("alias-for"sv))
|
||||
return;
|
||||
if (!pseudo_element.get_bool("is-generated"sv).value_or(false))
|
||||
return;
|
||||
|
||||
|
@ -215,6 +255,8 @@ PseudoElement to_pseudo_element(GeneratedPseudoElement generated_pseudo_element)
|
|||
|
||||
pseudo_elements_data.for_each_member([&](auto& name, JsonValue const& value) {
|
||||
auto& pseudo_element = value.as_object();
|
||||
if (pseudo_element.has("alias-for"sv))
|
||||
return;
|
||||
if (!pseudo_element.get_bool("is-generated"sv).value_or(false))
|
||||
return;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue