From c729c3fcee2d3a9b409de41a22115fb696e789ed Mon Sep 17 00:00:00 2001 From: Sam Atkins Date: Mon, 24 Feb 2025 14:59:03 +0000 Subject: [PATCH] LibWeb/CSS: Add custom-ident blacklists to Properties.json These excluded values use a similar notation to the ranges for numeric types: `![foo,bar,baz]` to exclude `foo`, `bar`, and `baz`. --- Documentation/CSSGeneratedFiles.md | 1 + Libraries/LibWeb/CSS/Properties.json | 22 ++++++--- .../LibWeb/GenerateCSSPropertyID.cpp | 48 +++++++++++++++++++ 3 files changed, 64 insertions(+), 7 deletions(-) diff --git a/Documentation/CSSGeneratedFiles.md b/Documentation/CSSGeneratedFiles.md index 87dd4999e3d..1f1ef88f7bb 100644 --- a/Documentation/CSSGeneratedFiles.md +++ b/Documentation/CSSGeneratedFiles.md @@ -72,6 +72,7 @@ The `valid-types` array lists the names of CSS value types, as defined in the la [CSS Values and Units spec](https://www.w3.org/TR/css-values/), without the `<>` around them. For numeric types, we use the [bracketed range notation](https://www.w3.org/TR/css-values-4/#css-bracketed-range-notation), for example `width` can take any non-negative length, so it has `"length [0,∞]"` in its `valid-types` array. +For ``s, the excluded identifiers are placed within `![]`, for example `"custom-ident ![all,none]"`. ## Keywords.json diff --git a/Libraries/LibWeb/CSS/Properties.json b/Libraries/LibWeb/CSS/Properties.json index dc723eea839..28a6302b98d 100644 --- a/Libraries/LibWeb/CSS/Properties.json +++ b/Libraries/LibWeb/CSS/Properties.json @@ -247,7 +247,7 @@ "initial": "none", "valid-types": [ "string", - "custom-ident" + "custom-ident ![none]" ], "valid-identifiers": [ "none" @@ -880,7 +880,15 @@ "affects-layout": false, "animation-type": "discrete", "inherited": true, - "initial": "normal" + "initial": "normal", + "valid-types": [ + "custom-ident ![normal,light,dark,only]" + ], + "valid-identifiers": [ + "normal", + "light", + "dark" + ] }, "column-count": { "animation-type": "by-computed-value", @@ -975,7 +983,7 @@ "inherited": false, "initial": "none", "valid-types": [ - "custom-ident", + "custom-ident ![none]", "integer [-∞,∞]" ], "valid-identifiers": [ @@ -987,7 +995,7 @@ "inherited": false, "initial": "none", "valid-types": [ - "custom-ident", + "custom-ident ![none]", "integer [-∞,∞]" ], "valid-identifiers": [ @@ -999,7 +1007,7 @@ "inherited": false, "initial": "none", "valid-types": [ - "custom-ident", + "custom-ident ![none]", "integer [-∞,∞]" ], "valid-identifiers": [ @@ -2841,7 +2849,7 @@ "initial": "all", "valid-types": [ "string", - "custom-ident" + "custom-ident ![all,none]" ], "valid-identifiers": [ "all", @@ -2902,7 +2910,7 @@ "inherited": false, "initial": "none", "valid-types": [ - "custom-ident" + "custom-ident ![auto,none]" ], "valid-identifiers": [ "none" diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateCSSPropertyID.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateCSSPropertyID.cpp index 4d7c1d080b0..19970462957 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateCSSPropertyID.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateCSSPropertyID.cpp @@ -250,6 +250,7 @@ enum class ValueType { bool property_accepts_type(PropertyID, ValueType); bool property_accepts_keyword(PropertyID, Keyword); Optional property_resolves_percentages_relative_to(PropertyID); +Vector property_custom_ident_blacklist(PropertyID); // These perform range-checking, but are also safe to call with properties that don't accept that type. (They'll just return false.) bool property_accepts_angle(PropertyID, Angle const&); @@ -938,6 +939,53 @@ Optional property_resolves_percentages_relative_to(PropertyID propert } } +Vector property_custom_ident_blacklist(PropertyID property_id) +{ + switch (property_id) { +)~~~"); + + properties.for_each_member([&](auto& name, auto& value) { + VERIFY(value.is_object()); + auto& object = value.as_object(); + if (is_legacy_alias(object)) + return; + + // We only have a custom-ident blacklist if we accept custom idents! + if (auto maybe_valid_types = object.get_array("valid-types"sv); maybe_valid_types.has_value() && !maybe_valid_types->is_empty()) { + auto& valid_types = maybe_valid_types.value(); + for (auto const& valid_type : valid_types.values()) { + auto type_and_parameters = MUST(valid_type.as_string().split(' ')); + if (type_and_parameters.first() != "custom-ident"sv || type_and_parameters.size() == 1) + continue; + VERIFY(type_and_parameters.size() == 2); + + auto parameters_string = type_and_parameters[1].bytes_as_string_view(); + VERIFY(parameters_string.starts_with("!["sv) && parameters_string.ends_with(']')); + auto blacklisted_keywords = parameters_string.substring_view(2, parameters_string.length() - 3).split_view(','); + + auto property_generator = generator.fork(); + property_generator.set("property_name:titlecase", title_casify(name)); + property_generator.append(R"~~~( + case PropertyID::@property_name:titlecase@: + return Vector { )~~~"); + for (auto const& keyword : blacklisted_keywords) { + auto value_generator = property_generator.fork(); + value_generator.set("keyword", keyword); + + value_generator.append("\"@keyword@\"sv, "); + } + + property_generator.appendln("};"); + } + } + }); + + generator.append(R"~~~( + default: + return {}; + } +} + size_t property_maximum_value_count(PropertyID property_id) { switch (property_id) {