diff --git a/Documentation/CSSGeneratedFiles.md b/Documentation/CSSGeneratedFiles.md index ea22f500e71..af0d9b3eb0d 100644 --- a/Documentation/CSSGeneratedFiles.md +++ b/Documentation/CSSGeneratedFiles.md @@ -19,21 +19,22 @@ Each property will have some set of these fields on it: (Note that required fields are not required on properties with `legacy-alias-for` or `logical-alias-for` set.) -| Field | Required | Default | Description | Generated functions | -|----------------------------|----------|---------|-------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `affects-layout` | No | `true` | Boolean. Whether changing this property will invalidate the element's layout. | `bool property_affects_layout(PropertyID)` | -| `affects-stacking-context` | No | `false` | Boolean. Whether this property can cause a new stacking context for the element. | `bool property_affects_stacking_context(PropertyID)` | -| `animation-type` | Yes | | String. How the property should be animated. Defined by the spec. See below. | `AnimationType animation_type_from_longhand_property(PropertyID)` | -| `inherited` | Yes | | Boolean. Whether the property is inherited by its child elements. | `bool is_inherited_property(PropertyID)` | -| `initial` | Yes | | String. The property's initial value if it is not specified. | `NonnullRefPtr property_initial_value(PropertyID)` | -| `legacy-alias-for` | No | Nothing | String. The name of a property this is an alias for. See below. | | -| `logical-alias-for` | No | Nothing | An object. See below. | `bool property_is_logical_alias(PropertyID);`
`PropertyID map_logical_alias_to_physical_property(PropertyID, LogicalAliasMappingContext const&)` | -| `longhands` | No | `[]` | Array of strings. If this is a shorthand, these are the property names that it expands out into. | `Vector longhands_for_shorthand(PropertyID)`
`Vector expanded_longhands_for_shorthand(PropertyID)`
`Vector shorthands_for_longhand(PropertyID)` | -| `max-values` | No | `1` | Integer. How many values can be parsed for this property. eg, `margin` can have up to 4 values. | `size_t property_maximum_value_count(PropertyID)` | -| `percentages-resolve-to` | No | Nothing | String. What type percentages get resolved to. eg, for `width` percentages are resolved to `length` values. | `Optional property_resolves_percentages_relative_to(PropertyID)` | -| `quirks` | No | `[]` | Array of strings. Some properties have special behavior in "quirks mode", which are listed here. See below. | `bool property_has_quirk(PropertyID, Quirk)` | -| `valid-identifiers` | No | `[]` | Array of strings. Which keywords the property accepts. Consider defining an enum instead and putting its name in the `valid-types` array. | `bool property_accepts_keyword(PropertyID, Keyword)` | -| `valid-types` | No | `[]` | Array of strings. Which value types the property accepts. See below. | `bool property_accepts_type(PropertyID, ValueType)` | +| Field | Required | Default | Description | Generated functions | +|-----------------------------------|----------|---------|-------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `affects-layout` | No | `true` | Boolean. Whether changing this property will invalidate the element's layout. | `bool property_affects_layout(PropertyID)` | +| `affects-stacking-context` | No | `false` | Boolean. Whether this property can cause a new stacking context for the element. | `bool property_affects_stacking_context(PropertyID)` | +| `animation-type` | Yes | | String. How the property should be animated. Defined by the spec. See below. | `AnimationType animation_type_from_longhand_property(PropertyID)` | +| `inherited` | Yes | | Boolean. Whether the property is inherited by its child elements. | `bool is_inherited_property(PropertyID)` | +| `initial` | Yes | | String. The property's initial value if it is not specified. | `NonnullRefPtr property_initial_value(PropertyID)` | +| `legacy-alias-for` | No | Nothing | String. The name of a property this is an alias for. See below. | | +| `logical-alias-for` | No | Nothing | An object. See below. | `bool property_is_logical_alias(PropertyID);`
`PropertyID map_logical_alias_to_physical_property(PropertyID, LogicalAliasMappingContext const&)` | +| `longhands` | No | `[]` | Array of strings. If this is a shorthand, these are the property names that it expands out into. | `Vector longhands_for_shorthand(PropertyID)`
`Vector expanded_longhands_for_shorthand(PropertyID)`
`Vector shorthands_for_longhand(PropertyID)` | +| `max-values` | No | `1` | Integer. How many values can be parsed for this property. eg, `margin` can have up to 4 values. | `size_t property_maximum_value_count(PropertyID)` | +| `percentages-resolve-to` | No | Nothing | String. What type percentages get resolved to. eg, for `width` percentages are resolved to `length` values. | `Optional property_resolves_percentages_relative_to(PropertyID)` | +| `positional-value-list-shorthand` | No | `false` | Boolean. Whether this property is a "positional value list shorthand". See below. | `bool property_is_positional_value_list_shorthand(PropertyID)` | +| `quirks` | No | `[]` | Array of strings. Some properties have special behavior in "quirks mode", which are listed here. See below. | `bool property_has_quirk(PropertyID, Quirk)` | +| `valid-identifiers` | No | `[]` | Array of strings. Which keywords the property accepts. Consider defining an enum instead and putting its name in the `valid-types` array. | `bool property_accepts_keyword(PropertyID, Keyword)` | +| `valid-types` | No | `[]` | Array of strings. Which value types the property accepts. See below. | `bool property_accepts_type(PropertyID, ValueType)` | ### `animation-type` @@ -67,6 +68,13 @@ Logical aliases are properties like `margin-block-start`, which may assign a val | `group` | String. Name of the logical property group this is associated with. (See [LogicalPropertyGroups.json](#logicalpropertygroupsjson).) | | `mapping` | String. How this relates to the group. eg, if it's the block end value, `block-end`. | +### `positional-value-list-shorthand` +Some shorthand properties work differently to normal in that mapping of provided values to longhands isn't necessarily +1-to-1 and instead depends on the number of values provided, for example `margin`, `border-width`, `gap`, etc. + +These properties have distinct behaviors in how they are parsed and serialized, having them marked allows us to +implement this behavior in a generic way. + ### `quirks` The [Quirks spec](https://quirks.spec.whatwg.org/#css) defines these. @@ -194,7 +202,7 @@ Each entry has the following properties: | `alias-for` | No | Nothing | Use to specify that this should be treated as an alias for the named pseudo-element. | | `function-syntax` | No | Nothing | Syntax for the function arguments if this is a function-type pseudo-element. Copied directly from the spec. | | `is-allowed-in-has` | No | `false` | Whether this is a [`:has`-allowed pseudo-element](https://drafts.csswg.org/selectors/#has-allowed-pseudo-element). | -| `is-pseudo-root` | No | `false` | Whether this is a [pseudo-element root](https://drafts.csswg.org/css-view-transitions/#pseudo-element-root). | +| `is-pseudo-root` | No | `false` | Whether this is a [pseudo-element root](https://drafts.csswg.org/css-view-transitions/#pseudo-element-root). | | `property-whitelist` | No | Nothing | Some pseudo-elements only permit certain properties. If so, name them in an array here. Some special values are allowed here for categories of properties - see below. | | `spec` | No | Nothing | Link to the spec definition, for reference. Not used in generated code. | | `type` | No | `"identifier"` | What type of pseudo-element is this. Either "identifier", "function", or "both". | diff --git a/Libraries/LibWeb/CSS/Properties.json b/Libraries/LibWeb/CSS/Properties.json index 7eb1d531b22..5d51608567c 100644 --- a/Libraries/LibWeb/CSS/Properties.json +++ b/Libraries/LibWeb/CSS/Properties.json @@ -509,6 +509,7 @@ "border-block-color": { "inherited": false, "initial": "currentcolor", + "positional-value-list-shorthand": true, "longhands": [ "border-block-start-color", "border-block-end-color" @@ -581,6 +582,7 @@ "border-block-style": { "inherited": false, "initial": "none", + "positional-value-list-shorthand": true, "longhands": [ "border-block-start-style", "border-block-end-style" @@ -593,6 +595,7 @@ "border-block-width": { "inherited": false, "initial": "medium", + "positional-value-list-shorthand": true, "longhands": [ "border-block-start-width", "border-block-end-width" @@ -679,6 +682,7 @@ "border-color": { "affects-layout": false, "initial": "currentcolor", + "positional-value-list-shorthand": true, "longhands": [ "border-top-color", "border-right-color", @@ -791,6 +795,7 @@ "border-inline-color": { "inherited": false, "initial": "currentcolor", + "positional-value-list-shorthand": true, "longhands": [ "border-inline-start-color", "border-inline-end-color" @@ -863,6 +868,7 @@ "border-inline-style": { "inherited": false, "initial": "none", + "positional-value-list-shorthand": true, "longhands": [ "border-inline-start-style", "border-inline-end-style" @@ -875,6 +881,7 @@ "border-inline-width": { "inherited": false, "initial": "medium", + "positional-value-list-shorthand": true, "longhands": [ "border-inline-start-width", "border-inline-end-width" @@ -1011,6 +1018,7 @@ }, "border-style": { "initial": "none", + "positional-value-list-shorthand": true, "longhands": [ "border-top-style", "border-right-style", @@ -1089,6 +1097,7 @@ }, "border-width": { "initial": "medium", + "positional-value-list-shorthand": true, "longhands": [ "border-top-width", "border-right-width", @@ -1767,6 +1776,7 @@ "normal" ], "percentages-resolve-to": "length", + "positional-value-list-shorthand": true, "longhands": [ "row-gap", "column-gap" @@ -2018,6 +2028,7 @@ "inset": { "inherited": false, "initial": "auto", + "positional-value-list-shorthand": true, "longhands": [ "top", "right", @@ -2036,6 +2047,7 @@ }, "inset-block": { "initial": "auto", + "positional-value-list-shorthand": true, "longhands": [ "inset-block-start", "inset-block-end" @@ -2066,6 +2078,7 @@ }, "inset-inline": { "initial": "auto", + "positional-value-list-shorthand": true, "longhands": [ "inset-inline-start", "inset-inline-end" @@ -2212,6 +2225,7 @@ "margin": { "inherited": false, "initial": "0", + "positional-value-list-shorthand": true, "longhands": [ "margin-top", "margin-right", @@ -2233,6 +2247,7 @@ }, "margin-block": { "initial": "0", + "positional-value-list-shorthand": true, "longhands": [ "margin-block-start", "margin-block-end" @@ -2277,6 +2292,7 @@ }, "margin-inline": { "initial": "0", + "positional-value-list-shorthand": true, "longhands": [ "margin-inline-start", "margin-inline-end" @@ -2613,6 +2629,7 @@ "overflow-x", "overflow-y" ], + "positional-value-list-shorthand": true, "inherited": false, "initial": "visible", "max-values": 2, @@ -2639,6 +2656,7 @@ "padding": { "inherited": false, "initial": "0", + "positional-value-list-shorthand": true, "longhands": [ "padding-top", "padding-right", @@ -2657,6 +2675,7 @@ }, "padding-block": { "initial": "0", + "positional-value-list-shorthand": true, "longhands": [ "padding-block-start", "padding-block-end" @@ -2695,6 +2714,7 @@ }, "padding-inline": { "initial": "0", + "positional-value-list-shorthand": true, "longhands": [ "padding-inline-start", "padding-inline-end" diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateCSSPropertyID.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateCSSPropertyID.cpp index 885808eb6d9..b9579e789b2 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateCSSPropertyID.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateCSSPropertyID.cpp @@ -323,6 +323,7 @@ Vector const& longhands_for_shorthand(PropertyID); Vector const& expanded_longhands_for_shorthand(PropertyID); bool property_maps_to_shorthand(PropertyID); Vector const& shorthands_for_longhand(PropertyID); +bool property_is_positional_value_list_shorthand(PropertyID); size_t property_maximum_value_count(PropertyID); @@ -1335,6 +1336,33 @@ Vector const& shorthands_for_longhand(PropertyID property_id) } } } +)~~~"); + + generator.append(R"~~~( +bool property_is_positional_value_list_shorthand(PropertyID property_id) +{ + switch (property_id) + { +)~~~"); + properties.for_each_member([&](auto& name, auto& value) { + if (is_legacy_alias(value.as_object())) + return; + + if (value.as_object().has("positional-value-list-shorthand"sv)) { + auto property_generator = generator.fork(); + property_generator.set("name:titlecase", title_casify(name)); + property_generator.append(R"~~~( + case PropertyID::@name:titlecase@: + )~~~"); + } + }); + + generator.append(R"~~~( + return true; + default: + return false; + } +} )~~~"); generator.append(R"~~~(