mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-20 11:36:10 +00:00
LibWeb/CSS: Generate property-filtering code for pseudo-elements
Pseudo-elements have specific rules about which CSS properties can be applied to them. This is a first step to supporting that. - If a property whitelist isn't present, all properties are allowed. - Properties are named as in CSS. - Names of property groups are prefixed with `#`, which makes this match the spec more clearly. These groups are implemented directly in the code generator for now. - Any property name beginning with "FIXME:" is ignored, so we can mark properties we don't implement yet.
This commit is contained in:
parent
193adee164
commit
1108988656
Notes:
github-actions[bot]
2025-03-24 09:51:00 +00:00
Author: https://github.com/AtkinsSJ Commit: https://github.com/LadybirdBrowser/ladybird/commit/11089886562 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/4021
2 changed files with 287 additions and 4 deletions
|
@ -50,19 +50,61 @@
|
|||
"spec": "https://drafts.csswg.org/css-forms-1/#selectordef-fill"
|
||||
},
|
||||
"first-letter": {
|
||||
"spec": "https://drafts.csswg.org/css-pseudo-4/#selectordef-first-letter"
|
||||
"spec": "https://drafts.csswg.org/css-pseudo-4/#selectordef-first-letter",
|
||||
"property-whitelist": [
|
||||
"#font-properties",
|
||||
"color",
|
||||
"opacity",
|
||||
"#background-properties",
|
||||
"#inline-typesetting-properties",
|
||||
"#text-decoration-properties",
|
||||
"#inline-layout-properties",
|
||||
"#margin-properties",
|
||||
"#padding-properties",
|
||||
"#border-properties",
|
||||
"box-shadow"
|
||||
]
|
||||
},
|
||||
"first-line": {
|
||||
"spec": "https://drafts.csswg.org/css-pseudo-4/#selectordef-first-line"
|
||||
"spec": "https://drafts.csswg.org/css-pseudo-4/#selectordef-first-line",
|
||||
"property-whitelist": [
|
||||
"#font-properties",
|
||||
"color",
|
||||
"opacity",
|
||||
"#background-properties",
|
||||
"#inline-typesetting-properties",
|
||||
"#text-decoration-properties",
|
||||
"FIXME: ruby-position",
|
||||
"#inline-layout-properties"
|
||||
]
|
||||
},
|
||||
"marker": {
|
||||
"spec": "https://drafts.csswg.org/css-pseudo-4/#selectordef-marker"
|
||||
},
|
||||
"placeholder": {
|
||||
"spec": "https://drafts.csswg.org/css-pseudo-4/#selectordef-placeholder"
|
||||
"spec": "https://drafts.csswg.org/css-pseudo-4/#selectordef-placeholder",
|
||||
"property-whitelist": [
|
||||
"#font-properties",
|
||||
"color",
|
||||
"opacity",
|
||||
"#background-properties",
|
||||
"#inline-typesetting-properties",
|
||||
"#text-decoration-properties",
|
||||
"FIXME: ruby-position"
|
||||
]
|
||||
},
|
||||
"selection": {
|
||||
"spec": "https://drafts.csswg.org/css-pseudo-4/#selectordef-selection"
|
||||
"spec": "https://drafts.csswg.org/css-pseudo-4/#selectordef-selection",
|
||||
"property-whitelist": [
|
||||
"color",
|
||||
"background-color",
|
||||
"#text-decoration-properties",
|
||||
"text-shadow",
|
||||
"FIXME: stroke-color",
|
||||
"FIXME: fill-color",
|
||||
"stroke-width",
|
||||
"#custom-properties"
|
||||
]
|
||||
},
|
||||
"thumb": {
|
||||
"spec": "https://drafts.csswg.org/css-forms-1/#selectordef-thumb"
|
||||
|
|
|
@ -58,6 +58,7 @@ ErrorOr<void> generate_header_file(JsonObject& pseudo_elements_data, Core::File&
|
|||
|
||||
#include <AK/Optional.h>
|
||||
#include <AK/StringView.h>
|
||||
#include <LibWeb/CSS/PropertyID.h>
|
||||
|
||||
namespace Web::CSS {
|
||||
|
||||
|
@ -85,6 +86,7 @@ Optional<PseudoElement> aliased_pseudo_element_from_string(StringView);
|
|||
StringView pseudo_element_name(PseudoElement);
|
||||
|
||||
bool is_has_allowed_pseudo_element(PseudoElement);
|
||||
bool pseudo_element_supports_property(PseudoElement, PropertyID);
|
||||
|
||||
enum class GeneratedPseudoElement : @generated_pseudo_element_underlying_type@ {
|
||||
)~~~");
|
||||
|
@ -222,6 +224,245 @@ bool is_has_allowed_pseudo_element(PseudoElement pseudo_element)
|
|||
}
|
||||
}
|
||||
|
||||
bool pseudo_element_supports_property(PseudoElement pseudo_element, PropertyID property_id)
|
||||
{
|
||||
switch (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;
|
||||
auto property_whitelist = pseudo_element.get_array("property-whitelist"sv);
|
||||
// No whitelist = accept everything, by falling back to the default case.
|
||||
if (!property_whitelist.has_value())
|
||||
return;
|
||||
|
||||
auto member_generator = generator.fork();
|
||||
member_generator.set("name:titlecase", title_casify(name));
|
||||
member_generator.append(R"~~~(
|
||||
case PseudoElement::@name:titlecase@:
|
||||
switch (property_id) {
|
||||
)~~~");
|
||||
|
||||
property_whitelist->for_each([&](JsonValue const& entry) {
|
||||
auto& property = entry.as_string();
|
||||
if (property.starts_with_bytes("FIXME:"sv))
|
||||
return;
|
||||
|
||||
auto append_property = [&](StringView const& property_name) {
|
||||
auto property_generator = member_generator.fork();
|
||||
property_generator.set("property:titlecase", title_casify(property_name));
|
||||
property_generator.appendln(" case PropertyID::@property:titlecase@:");
|
||||
};
|
||||
|
||||
if (!property.starts_with('#')) {
|
||||
append_property(property);
|
||||
return;
|
||||
}
|
||||
// Categories
|
||||
// TODO: Maybe define these in data somewhere too?
|
||||
if (property == "#background-properties"sv) {
|
||||
// https://drafts.csswg.org/css-backgrounds/#property-index
|
||||
append_property("background"sv);
|
||||
append_property("background-attachment"sv);
|
||||
append_property("background-clip"sv);
|
||||
append_property("background-color"sv);
|
||||
append_property("background-image"sv);
|
||||
append_property("background-origin"sv);
|
||||
append_property("background-position"sv);
|
||||
append_property("background-position-x"sv);
|
||||
append_property("background-position-y"sv);
|
||||
append_property("background-repeat"sv);
|
||||
append_property("background-size"sv);
|
||||
return;
|
||||
}
|
||||
if (property == "#border-properties"sv) {
|
||||
// https://drafts.csswg.org/css-backgrounds/#property-index
|
||||
append_property("border"sv);
|
||||
append_property("border-block-end"sv);
|
||||
append_property("border-block-end-color"sv);
|
||||
append_property("border-block-end-style"sv);
|
||||
append_property("border-block-end-width"sv);
|
||||
append_property("border-block-start"sv);
|
||||
append_property("border-block-start-color"sv);
|
||||
append_property("border-block-start-style"sv);
|
||||
append_property("border-block-start-width"sv);
|
||||
append_property("border-bottom"sv);
|
||||
append_property("border-bottom-color"sv);
|
||||
append_property("border-bottom-left-radius"sv);
|
||||
append_property("border-bottom-right-radius"sv);
|
||||
append_property("border-bottom-style"sv);
|
||||
append_property("border-bottom-width"sv);
|
||||
append_property("border-color"sv);
|
||||
append_property("border-inline-end"sv);
|
||||
append_property("border-inline-end-color"sv);
|
||||
append_property("border-inline-end-style"sv);
|
||||
append_property("border-inline-end-width"sv);
|
||||
append_property("border-inline-start"sv);
|
||||
append_property("border-inline-start-color"sv);
|
||||
append_property("border-inline-start-style"sv);
|
||||
append_property("border-inline-start-width"sv);
|
||||
append_property("border-left"sv);
|
||||
append_property("border-left-color"sv);
|
||||
append_property("border-left-style"sv);
|
||||
append_property("border-left-width"sv);
|
||||
append_property("border-radius"sv);
|
||||
append_property("border-right"sv);
|
||||
append_property("border-right-color"sv);
|
||||
append_property("border-right-style"sv);
|
||||
append_property("border-right-width"sv);
|
||||
append_property("border-style"sv);
|
||||
append_property("border-top"sv);
|
||||
append_property("border-top-color"sv);
|
||||
append_property("border-top-left-radius"sv);
|
||||
append_property("border-top-right-radius"sv);
|
||||
append_property("border-top-style"sv);
|
||||
append_property("border-top-width"sv);
|
||||
append_property("border-width"sv);
|
||||
return;
|
||||
}
|
||||
if (property == "#custom-properties"sv) {
|
||||
append_property("custom"sv);
|
||||
return;
|
||||
}
|
||||
if (property == "#font-properties"sv) {
|
||||
// https://drafts.csswg.org/css-fonts/#property-index
|
||||
append_property("font"sv);
|
||||
append_property("font-family"sv);
|
||||
append_property("font-feature-settings"sv);
|
||||
// FIXME: font-kerning
|
||||
append_property("font-language-override"sv);
|
||||
// FIXME: font-optical-sizing
|
||||
// FIXME: font-palette
|
||||
append_property("font-size"sv);
|
||||
// FIXME: font-size-adjust
|
||||
append_property("font-style"sv);
|
||||
// FIXME: font-synthesis and longhands
|
||||
append_property("font-variant"sv);
|
||||
append_property("font-variant-alternates"sv);
|
||||
append_property("font-variant-caps"sv);
|
||||
append_property("font-variant-east-asian"sv);
|
||||
append_property("font-variant-emoji"sv);
|
||||
append_property("font-variant-ligatures"sv);
|
||||
append_property("font-variant-numeric"sv);
|
||||
append_property("font-variant-position"sv);
|
||||
append_property("font-variation-settings"sv);
|
||||
append_property("font-weight"sv);
|
||||
append_property("font-width"sv);
|
||||
return;
|
||||
}
|
||||
if (property == "#inline-layout-properties"sv) {
|
||||
// https://drafts.csswg.org/css-inline/#property-index
|
||||
// FIXME: alignment-baseline
|
||||
// FIXME: baseline-shift
|
||||
// FIXME: baseline-source
|
||||
// FIXME: dominant-baseline
|
||||
// FIXME: initial-letter
|
||||
// FIXME: initial-letter-align
|
||||
// FIXME: initial-letter-wrap
|
||||
// FIXME: inline-sizing
|
||||
// FIXME: line-edge-fit
|
||||
append_property("line-height"sv);
|
||||
// FIXME: text-box
|
||||
// FIXME: text-box-edge
|
||||
// FIXME: text-box-trim
|
||||
append_property("vertical-align"sv);
|
||||
return;
|
||||
}
|
||||
if (property == "#inline-typesetting-properties"sv) {
|
||||
// https://drafts.csswg.org/css-text-4/#property-index
|
||||
// FIXME: hanging-punctuation
|
||||
// FIXME: hyphenate-character
|
||||
// FIXME: hyphenate-limit-chars
|
||||
// FIXME: hyphenate-limit-last
|
||||
// FIXME: hyphenate-limit-lines
|
||||
// FIXME: hyphenate-limit-zone
|
||||
// FIXME: hyphens
|
||||
append_property("letter-spacing"sv);
|
||||
// FIXME: line-break
|
||||
// FIXME: line-padding
|
||||
// FIXME: overflow-wrap
|
||||
append_property("tab-size"sv);
|
||||
append_property("text-align"sv);
|
||||
// FIXME: text-align-all
|
||||
// FIXME: text-align-last
|
||||
// FIXME: text-autospace
|
||||
// FIXME: text-group-align
|
||||
append_property("text-indent"sv);
|
||||
append_property("text-justify"sv);
|
||||
// FIXME: text-spacing
|
||||
// FIXME: text-spacing-trim
|
||||
append_property("text-transform"sv);
|
||||
// FIXME: text-wrap
|
||||
// FIXME: text-wrap-mode
|
||||
// FIXME: text-wrap-style
|
||||
append_property("white-space"sv);
|
||||
// FIXME: white-space-collapse
|
||||
// FIXME: white-space-trim
|
||||
append_property("word-break"sv);
|
||||
// FIXME: word-space-transform
|
||||
append_property("word-spacing"sv);
|
||||
append_property("word-wrap"sv);
|
||||
// FIXME: wrap-after
|
||||
// FIXME: wrap-before
|
||||
// FIXME: wrap-inside
|
||||
return;
|
||||
}
|
||||
if (property == "#margin-properties"sv) {
|
||||
append_property("margin"sv);
|
||||
append_property("margin-block"sv);
|
||||
append_property("margin-block-end"sv);
|
||||
append_property("margin-block-start"sv);
|
||||
append_property("margin-bottom"sv);
|
||||
append_property("margin-inline"sv);
|
||||
append_property("margin-inline-end"sv);
|
||||
append_property("margin-inline-start"sv);
|
||||
append_property("margin-left"sv);
|
||||
append_property("margin-right"sv);
|
||||
append_property("margin-top"sv);
|
||||
return;
|
||||
}
|
||||
if (property == "#padding-properties"sv) {
|
||||
append_property("padding"sv);
|
||||
append_property("padding-block"sv);
|
||||
append_property("padding-block-end"sv);
|
||||
append_property("padding-block-start"sv);
|
||||
append_property("padding-bottom"sv);
|
||||
append_property("padding-inline"sv);
|
||||
append_property("padding-inline-end"sv);
|
||||
append_property("padding-inline-start"sv);
|
||||
append_property("padding-left"sv);
|
||||
append_property("padding-right"sv);
|
||||
append_property("padding-top"sv);
|
||||
return;
|
||||
}
|
||||
if (property == "#text-decoration-properties"sv) {
|
||||
append_property("text-decoration"sv);
|
||||
append_property("text-decoration-color"sv);
|
||||
append_property("text-decoration-line"sv);
|
||||
append_property("text-decoration-style"sv);
|
||||
append_property("text-decoration-thickness"sv);
|
||||
return;
|
||||
}
|
||||
outln("Error: Unrecognized property group name '{}' in {}", property, name);
|
||||
exit(1);
|
||||
});
|
||||
|
||||
member_generator.append(R"~~~(
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
)~~~");
|
||||
});
|
||||
|
||||
generator.append(R"~~~(
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Optional<GeneratedPseudoElement> to_generated_pseudo_element(PseudoElement pseudo_element)
|
||||
{
|
||||
switch (pseudo_element) {
|
||||
|
|
Loading…
Add table
Reference in a new issue