From 41996f187782e619986c777e0cfd01e335ff3a45 Mon Sep 17 00:00:00 2001 From: Ramon Date: Wed, 5 Aug 2026 16:56:50 +1000 Subject: [PATCH 1/4] theme.json schema: fix block pseudo-classes and custom states Every core block is listed under `properties` and was also matched by a `patternProperties` fallback. JSON Schema applies both applicators to a key that matches both, and the fallback restricts `propertyNames` to plain style properties, so the per-block allowances for `:hover`, `:focus`, `:focus-visible`, `:active` and `-current` could never take effect. An `allOf` member can only narrow the set of allowed keys, never widen it. Move the fallback to `additionalProperties`, which applies only to keys that are not listed under `properties`, and keep a `propertyNames` pattern so malformed block names are still rejected. Because all core blocks are enumerated, nothing has to be kept in sync when a block gains support for a new state. Three definitions were composed the same way and are fixed too: - `stylesBlocksCustomStatesProperties` pulled in `stylesPropertiesComplete`, so `:hover` inside `-current` was rejected. It now states its own key set. - `core/navigation-link` had `stylesPropertiesAndElementsComplete` as its first `allOf` member, which rejected its pseudo-classes and `-current`. It now composes the parts and states its own key set, at both block and variation level. - `core/button` stopped accepting `elements` when its bespoke definition replaced the shared one. Restored at both levels. Fixes #81057 --- schemas/json/theme.json | 134 +++++++++++++++++++++++++++++++++++----- 1 file changed, 120 insertions(+), 14 deletions(-) diff --git a/schemas/json/theme.json b/schemas/json/theme.json index 1cc41c9e87b113..89be177e364c18 100644 --- a/schemas/json/theme.json +++ b/schemas/json/theme.json @@ -1996,15 +1996,31 @@ "description": "Styles applied to the current/active item (e.g. .current-menu-item in navigation).", "allOf": [ { - "$ref": "#/definitions/stylesPropertiesComplete" + "$ref": "#/definitions/stylesProperties" }, { "$ref": "#/definitions/stylesBlocksPseudoSelectorsProperties" + }, + { + "type": "object", + "propertyNames": { + "anyOf": [ + { + "$ref": "#/definitions/stylesPropertyNames" + }, + { + "$ref": "#/definitions/stylesBlocksPseudoSelectorsPropertyNames" + } + ] + } } ] } } }, + "stylesBlocksCustomStatesPropertyNames": { + "enum": [ "-current" ] + }, "stylesElementsPseudoSelectorsPropertyNames": { "enum": [ ":active", @@ -2391,6 +2407,9 @@ { "type": "object", "properties": { + "elements": { + "$ref": "#/definitions/stylesElementsPropertiesComplete" + }, "variations": { "type": "object", "patternProperties": { @@ -2438,7 +2457,7 @@ "$ref": "#/definitions/stylesPropertyNames" }, { - "enum": [ "variations" ] + "enum": [ "elements", "variations" ] }, { "$ref": "#/definitions/stylesBlocksResponsiveSelectorsPropertyNames" @@ -2580,7 +2599,7 @@ "core/navigation-link": { "allOf": [ { - "$ref": "#/definitions/stylesPropertiesAndElementsComplete" + "$ref": "#/definitions/stylesProperties" }, { "$ref": "#/definitions/stylesBlocksResponsiveSelectorsProperties" @@ -2590,6 +2609,39 @@ }, { "$ref": "#/definitions/stylesBlocksCustomStatesProperties" + }, + { + "type": "object", + "properties": { + "elements": { + "$ref": "#/definitions/stylesElementsPropertiesComplete" + }, + "variations": { + "$ref": "#/definitions/stylesVariationsPropertiesComplete" + } + } + }, + { + "type": "object", + "propertyNames": { + "anyOf": [ + { + "$ref": "#/definitions/stylesPropertyNames" + }, + { + "enum": [ "elements", "variations" ] + }, + { + "$ref": "#/definitions/stylesBlocksResponsiveSelectorsPropertyNames" + }, + { + "$ref": "#/definitions/stylesBlocksPseudoSelectorsPropertyNames" + }, + { + "$ref": "#/definitions/stylesBlocksCustomStatesPropertyNames" + } + ] + } } ] }, @@ -2765,12 +2817,12 @@ "$ref": "#/definitions/stylesPropertiesAndElementsComplete" } }, - "patternProperties": { - "^[a-z][a-z0-9-]*/[a-z][a-z0-9-]*$": { - "$ref": "#/definitions/stylesPropertiesAndElementsComplete" - } + "propertyNames": { + "pattern": "^[a-z][a-z0-9-]*/[a-z][a-z0-9-]*$" }, - "additionalProperties": false + "additionalProperties": { + "$ref": "#/definitions/stylesPropertiesAndElementsComplete" + } }, "stylesPropertiesAndElementsComplete": { "allOf": [ @@ -2928,6 +2980,14 @@ { "$ref": "#/definitions/stylesBlocksPseudoSelectorsProperties" }, + { + "type": "object", + "properties": { + "elements": { + "$ref": "#/definitions/stylesElementsPropertiesComplete" + } + } + }, { "type": "object", "propertyNames": { @@ -2935,6 +2995,9 @@ { "$ref": "#/definitions/stylesPropertyNames" }, + { + "enum": [ "elements" ] + }, { "$ref": "#/definitions/stylesBlocksResponsiveSelectorsPropertyNames" }, @@ -3073,7 +3136,50 @@ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete" }, "core/navigation-link": { - "$ref": "#/definitions/stylesVariationBlockPropertiesComplete" + "allOf": [ + { + "$ref": "#/definitions/stylesProperties" + }, + { + "$ref": "#/definitions/stylesBlocksResponsiveSelectorsProperties" + }, + { + "$ref": "#/definitions/stylesBlocksPseudoSelectorsProperties" + }, + { + "$ref": "#/definitions/stylesBlocksCustomStatesProperties" + }, + { + "type": "object", + "properties": { + "elements": { + "$ref": "#/definitions/stylesElementsPropertiesComplete" + } + } + }, + { + "type": "object", + "propertyNames": { + "anyOf": [ + { + "$ref": "#/definitions/stylesPropertyNames" + }, + { + "enum": [ "elements" ] + }, + { + "$ref": "#/definitions/stylesBlocksResponsiveSelectorsPropertyNames" + }, + { + "$ref": "#/definitions/stylesBlocksPseudoSelectorsPropertyNames" + }, + { + "$ref": "#/definitions/stylesBlocksCustomStatesPropertyNames" + } + ] + } + } + ] }, "core/navigation-submenu": { "$ref": "#/definitions/stylesVariationBlockPropertiesComplete" @@ -3247,12 +3353,12 @@ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete" } }, - "patternProperties": { - "^[a-z][a-z0-9-]*/[a-z][a-z0-9-]*$": { - "$ref": "#/definitions/stylesVariationBlockPropertiesComplete" - } + "propertyNames": { + "pattern": "^[a-z][a-z0-9-]*/[a-z][a-z0-9-]*$" }, - "additionalProperties": false + "additionalProperties": { + "$ref": "#/definitions/stylesVariationBlockPropertiesComplete" + } }, "stylesVariationBlockPropertiesComplete": { "allOf": [ From 07c8c9287b5465526186d46169e54373a50db63e Mon Sep 17 00:00:00 2001 From: Ramon Date: Wed, 5 Aug 2026 16:59:48 +1000 Subject: [PATCH 2/4] Tests: cover block pseudo-classes and custom states in the theme.json schema `theme-schema.test.js` had no fixture that used a block-level state, which is why the schema shipped twice with `:hover` and `-current` unusable and CI stayed green. It validates every `theme.json` found under `test/` as expected-valid, so a fixture there is picked up without changing the test. Add `fixtures/theme-json/block-states/theme.json` covering the four pseudo-classes on `core/button` and `core/navigation-link`, `-current` on `core/navigation-link` with a nested `:hover`, `elements`, `variations` and `@mobile` on both, and the same states under `styles.variations..blocks`. This file is rejected by the schema as it stands on trunk, so it guards the fix rather than describing it. For the expected-invalid fixtures, keep asserting that these states are refused where they are not supported: - `core/paragraph` with `:hover` - a third-party block with `:hover`, which reaches the fallback through `additionalProperties` - `core/navigation-link` with an unregistered `-other` state - `-current` holding a key that is not a style property or pseudo-class - a `blocks` key that is not a valid block name - `core/paragraph` with `:hover` inside a style variation Two existing fixtures used `core/button`, which no longer reaches the generic fallback they are named after. Point them at `core/paragraph` so they exercise that definition again. --- .../stylesBlocksCustomStatesProperties.json | 13 ++ .../stylesBlocksPropertiesComplete.json | 13 ++ ...ocksPropertiesComplete_navigationLink.json | 15 ++ .../stylesPropertiesAndElementsComplete.json | 2 +- ...sPropertiesAndElementsComplete_pseudo.json | 15 ++ ...pertiesAndElementsComplete_thirdParty.json | 15 ++ ...tylesVariationBlockPropertiesComplete.json | 2 +- ...riationBlockPropertiesComplete_pseudo.json | 19 +++ .../theme-json/block-states/theme.json | 132 ++++++++++++++++++ 9 files changed, 224 insertions(+), 2 deletions(-) create mode 100644 test/integration/fixtures/schemas/stylesBlocksCustomStatesProperties.json create mode 100644 test/integration/fixtures/schemas/stylesBlocksPropertiesComplete.json create mode 100644 test/integration/fixtures/schemas/stylesBlocksPropertiesComplete_navigationLink.json create mode 100644 test/integration/fixtures/schemas/stylesPropertiesAndElementsComplete_pseudo.json create mode 100644 test/integration/fixtures/schemas/stylesPropertiesAndElementsComplete_thirdParty.json create mode 100644 test/integration/fixtures/schemas/stylesVariationBlockPropertiesComplete_pseudo.json create mode 100644 test/integration/fixtures/theme-json/block-states/theme.json diff --git a/test/integration/fixtures/schemas/stylesBlocksCustomStatesProperties.json b/test/integration/fixtures/schemas/stylesBlocksCustomStatesProperties.json new file mode 100644 index 00000000000000..96f507ace6600c --- /dev/null +++ b/test/integration/fixtures/schemas/stylesBlocksCustomStatesProperties.json @@ -0,0 +1,13 @@ +{ + "$schema": "../../../../schemas/json/theme.json", + "version": 3, + "styles": { + "blocks": { + "core/navigation-link": { + "-current": { + "invalidAdditionalProperty": true + } + } + } + } +} diff --git a/test/integration/fixtures/schemas/stylesBlocksPropertiesComplete.json b/test/integration/fixtures/schemas/stylesBlocksPropertiesComplete.json new file mode 100644 index 00000000000000..6b82e7e16c6f60 --- /dev/null +++ b/test/integration/fixtures/schemas/stylesBlocksPropertiesComplete.json @@ -0,0 +1,13 @@ +{ + "$schema": "../../../../schemas/json/theme.json", + "version": 3, + "styles": { + "blocks": { + "notablockname": { + "color": { + "text": "red" + } + } + } + } +} diff --git a/test/integration/fixtures/schemas/stylesBlocksPropertiesComplete_navigationLink.json b/test/integration/fixtures/schemas/stylesBlocksPropertiesComplete_navigationLink.json new file mode 100644 index 00000000000000..b1c2d1235d70ea --- /dev/null +++ b/test/integration/fixtures/schemas/stylesBlocksPropertiesComplete_navigationLink.json @@ -0,0 +1,15 @@ +{ + "$schema": "../../../../schemas/json/theme.json", + "version": 3, + "styles": { + "blocks": { + "core/navigation-link": { + "-other": { + "color": { + "text": "red" + } + } + } + } + } +} diff --git a/test/integration/fixtures/schemas/stylesPropertiesAndElementsComplete.json b/test/integration/fixtures/schemas/stylesPropertiesAndElementsComplete.json index cf9e2c5689534f..5132248e271202 100644 --- a/test/integration/fixtures/schemas/stylesPropertiesAndElementsComplete.json +++ b/test/integration/fixtures/schemas/stylesPropertiesAndElementsComplete.json @@ -3,7 +3,7 @@ "version": 3, "styles": { "blocks": { - "core/button": { + "core/paragraph": { "invalidAdditionalProperty": true } } diff --git a/test/integration/fixtures/schemas/stylesPropertiesAndElementsComplete_pseudo.json b/test/integration/fixtures/schemas/stylesPropertiesAndElementsComplete_pseudo.json new file mode 100644 index 00000000000000..fbb804edc8e1e3 --- /dev/null +++ b/test/integration/fixtures/schemas/stylesPropertiesAndElementsComplete_pseudo.json @@ -0,0 +1,15 @@ +{ + "$schema": "../../../../schemas/json/theme.json", + "version": 3, + "styles": { + "blocks": { + "core/paragraph": { + ":hover": { + "color": { + "text": "red" + } + } + } + } + } +} diff --git a/test/integration/fixtures/schemas/stylesPropertiesAndElementsComplete_thirdParty.json b/test/integration/fixtures/schemas/stylesPropertiesAndElementsComplete_thirdParty.json new file mode 100644 index 00000000000000..a985f60011f94f --- /dev/null +++ b/test/integration/fixtures/schemas/stylesPropertiesAndElementsComplete_thirdParty.json @@ -0,0 +1,15 @@ +{ + "$schema": "../../../../schemas/json/theme.json", + "version": 3, + "styles": { + "blocks": { + "my-plugin/custom-block": { + ":hover": { + "color": { + "text": "red" + } + } + } + } + } +} diff --git a/test/integration/fixtures/schemas/stylesVariationBlockPropertiesComplete.json b/test/integration/fixtures/schemas/stylesVariationBlockPropertiesComplete.json index 42b3e4b2174f50..f699fdd70d84f2 100644 --- a/test/integration/fixtures/schemas/stylesVariationBlockPropertiesComplete.json +++ b/test/integration/fixtures/schemas/stylesVariationBlockPropertiesComplete.json @@ -5,7 +5,7 @@ "variations": { "custom-variation": { "blocks": { - "core/button": { + "core/paragraph": { "invalidAdditionalProperty": true } } diff --git a/test/integration/fixtures/schemas/stylesVariationBlockPropertiesComplete_pseudo.json b/test/integration/fixtures/schemas/stylesVariationBlockPropertiesComplete_pseudo.json new file mode 100644 index 00000000000000..42cd76481290d9 --- /dev/null +++ b/test/integration/fixtures/schemas/stylesVariationBlockPropertiesComplete_pseudo.json @@ -0,0 +1,19 @@ +{ + "$schema": "../../../../schemas/json/theme.json", + "version": 3, + "styles": { + "variations": { + "custom-variation": { + "blocks": { + "core/paragraph": { + ":hover": { + "color": { + "text": "red" + } + } + } + } + } + } + } +} diff --git a/test/integration/fixtures/theme-json/block-states/theme.json b/test/integration/fixtures/theme-json/block-states/theme.json new file mode 100644 index 00000000000000..0f6f114f9689de --- /dev/null +++ b/test/integration/fixtures/theme-json/block-states/theme.json @@ -0,0 +1,132 @@ +{ + "$schema": "../../../../../schemas/json/theme.json", + "version": 3, + "styles": { + "blocks": { + "core/button": { + "color": { + "background": "var(--wp--preset--color--primary)" + }, + ":hover": { + "color": { + "background": "var(--wp--preset--color--secondary)" + } + }, + ":focus": { + "outline": { + "width": "2px" + } + }, + ":focus-visible": { + "outline": { + "width": "2px" + } + }, + ":active": { + "color": { + "background": "var(--wp--preset--color--tertiary)" + } + }, + "@mobile": { + "typography": { + "fontSize": "14px" + } + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + }, + "variations": { + "outline": { + ":hover": { + "color": { + "text": "var(--wp--preset--color--secondary)" + } + } + } + } + }, + "core/navigation-link": { + ":hover": { + "color": { + "text": "var(--wp--preset--color--secondary)" + } + }, + ":focus": { + "color": { + "text": "var(--wp--preset--color--secondary)" + } + }, + ":focus-visible": { + "color": { + "text": "var(--wp--preset--color--secondary)" + } + }, + ":active": { + "color": { + "text": "var(--wp--preset--color--tertiary)" + } + }, + "-current": { + "color": { + "text": "var(--wp--preset--color--primary)" + }, + ":hover": { + "color": { + "text": "var(--wp--preset--color--secondary)" + } + } + }, + "@mobile": { + "typography": { + "fontSize": "14px" + } + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + } + }, + "variations": { + "custom-variation": { + "blocks": { + "core/button": { + ":hover": { + "color": { + "background": "var(--wp--preset--color--secondary)" + } + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + }, + "core/navigation-link": { + ":hover": { + "color": { + "text": "var(--wp--preset--color--secondary)" + } + }, + "-current": { + ":hover": { + "color": { + "text": "var(--wp--preset--color--secondary)" + } + } + } + } + } + } + } + } +} From 0665fe0bf30fc7f4469a04e540ad106bfba1e0f2 Mon Sep 17 00:00:00 2001 From: Ramon Date: Wed, 5 Aug 2026 18:04:04 +1000 Subject: [PATCH 3/4] theme.json schema: allow pseudo-classes in responsive states and variations Sanitization adds a supported block's pseudo-selectors to its responsive breakpoint states and to its block-local style variations (lib/class-wp-theme-json-gutenberg.php:1322-1326 and :1376-1393), and CSS is generated for both (:3648 onward, :3847, :3897). The schema rejected them: - `styles.blocks.core/navigation-link.variations.[":hover"]` - `styles.blocks.["@mobile"][":hover"]` for both supported blocks - the same paths under `styles.variations..blocks` Add three definitions shared by `core/button` and `core/navigation-link`: style properties plus pseudo-selectors, a pseudo-aware responsive state map, and a variations map carrying the block's responsive states and pseudo-selectors. The generic definitions are untouched, so `core/paragraph` still rejects all of it. `-current` stays rejected inside variations. The variation loop never reads VALID_BLOCK_CUSTOM_STATES, so WordPress strips it there, and the schema should not advertise it. `core/button` style variations accept `elements` and `blocks` again. The bespoke definition added in #71418 dropped both, which the generic block-local variation schema has always allowed. --- schemas/json/theme.json | 146 +++++++++++------- ...esBlockVariationsWithPseudoProperties.json | 19 +++ ...esBlocksResponsiveSelectorsProperties.json | 17 ++ ...sponsiveSelectorsWithPseudoProperties.json | 17 ++ .../theme-json/block-states/theme.json | 47 ++++++ 5 files changed, 192 insertions(+), 54 deletions(-) create mode 100644 test/integration/fixtures/schemas/stylesBlockVariationsWithPseudoProperties.json create mode 100644 test/integration/fixtures/schemas/stylesBlocksResponsiveSelectorsProperties.json create mode 100644 test/integration/fixtures/schemas/stylesBlocksResponsiveSelectorsWithPseudoProperties.json diff --git a/schemas/json/theme.json b/schemas/json/theme.json index 89be177e364c18..12ec792927460e 100644 --- a/schemas/json/theme.json +++ b/schemas/json/theme.json @@ -1947,6 +1947,30 @@ "stylesBlocksPseudoSelectorsPropertyNames": { "enum": [ ":hover", ":focus", ":focus-visible", ":active" ] }, + "stylesBlocksPropertiesAndPseudoComplete": { + "description": "Style properties plus the pseudo-selectors available to blocks that support them.", + "allOf": [ + { + "$ref": "#/definitions/stylesProperties" + }, + { + "$ref": "#/definitions/stylesBlocksPseudoSelectorsProperties" + }, + { + "type": "object", + "propertyNames": { + "anyOf": [ + { + "$ref": "#/definitions/stylesPropertyNames" + }, + { + "$ref": "#/definitions/stylesBlocksPseudoSelectorsPropertyNames" + } + ] + } + } + ] + }, "stylesBlocksResponsiveSelectorsProperties": { "description": "Responsive block states keyed by breakpoint name. Each breakpoint supports the same style properties as the default block state.", "type": "object", @@ -1962,6 +1986,67 @@ "stylesBlocksResponsiveSelectorsPropertyNames": { "enum": [ "@mobile", "@tablet" ] }, + "stylesBlocksResponsiveSelectorsWithPseudoProperties": { + "description": "Responsive block states for blocks that support pseudo-selectors. Each breakpoint supports the same style properties as the default block state, plus the block's pseudo-selectors.", + "type": "object", + "properties": { + "@mobile": { + "$ref": "#/definitions/stylesBlocksPropertiesAndPseudoComplete" + }, + "@tablet": { + "$ref": "#/definitions/stylesBlocksPropertiesAndPseudoComplete" + } + } + }, + "stylesBlockVariationsWithPseudoProperties": { + "description": "Block style variations for blocks that support pseudo-selectors. Each variation supports the same style properties, responsive states and pseudo-selectors as the block itself.", + "type": "object", + "patternProperties": { + "^[a-z][a-z0-9-]*$": { + "allOf": [ + { + "$ref": "#/definitions/stylesProperties" + }, + { + "$ref": "#/definitions/stylesBlocksResponsiveSelectorsWithPseudoProperties" + }, + { + "$ref": "#/definitions/stylesBlocksPseudoSelectorsProperties" + }, + { + "type": "object", + "properties": { + "elements": { + "$ref": "#/definitions/stylesElementsPropertiesComplete" + }, + "blocks": { + "$ref": "#/definitions/stylesVariationBlocksPropertiesComplete" + } + } + }, + { + "type": "object", + "propertyNames": { + "anyOf": [ + { + "$ref": "#/definitions/stylesPropertyNames" + }, + { + "enum": [ "elements", "blocks" ] + }, + { + "$ref": "#/definitions/stylesBlocksResponsiveSelectorsPropertyNames" + }, + { + "$ref": "#/definitions/stylesBlocksPseudoSelectorsPropertyNames" + } + ] + } + } + ] + } + } + }, "stylesElementsPseudoSelectorsProperties": { "type": "object", "properties": { @@ -1996,23 +2081,7 @@ "description": "Styles applied to the current/active item (e.g. .current-menu-item in navigation).", "allOf": [ { - "$ref": "#/definitions/stylesProperties" - }, - { - "$ref": "#/definitions/stylesBlocksPseudoSelectorsProperties" - }, - { - "type": "object", - "propertyNames": { - "anyOf": [ - { - "$ref": "#/definitions/stylesPropertyNames" - }, - { - "$ref": "#/definitions/stylesBlocksPseudoSelectorsPropertyNames" - } - ] - } + "$ref": "#/definitions/stylesBlocksPropertiesAndPseudoComplete" } ] } @@ -2402,7 +2471,7 @@ "$ref": "#/definitions/stylesProperties" }, { - "$ref": "#/definitions/stylesBlocksResponsiveSelectorsProperties" + "$ref": "#/definitions/stylesBlocksResponsiveSelectorsWithPseudoProperties" }, { "type": "object", @@ -2411,38 +2480,7 @@ "$ref": "#/definitions/stylesElementsPropertiesComplete" }, "variations": { - "type": "object", - "patternProperties": { - "^[a-z][a-z0-9-]*$": { - "allOf": [ - { - "$ref": "#/definitions/stylesProperties" - }, - { - "$ref": "#/definitions/stylesBlocksResponsiveSelectorsProperties" - }, - { - "$ref": "#/definitions/stylesBlocksPseudoSelectorsProperties" - }, - { - "type": "object", - "propertyNames": { - "anyOf": [ - { - "$ref": "#/definitions/stylesPropertyNames" - }, - { - "$ref": "#/definitions/stylesBlocksResponsiveSelectorsPropertyNames" - }, - { - "$ref": "#/definitions/stylesBlocksPseudoSelectorsPropertyNames" - } - ] - } - } - ] - } - } + "$ref": "#/definitions/stylesBlockVariationsWithPseudoProperties" } } }, @@ -2602,7 +2640,7 @@ "$ref": "#/definitions/stylesProperties" }, { - "$ref": "#/definitions/stylesBlocksResponsiveSelectorsProperties" + "$ref": "#/definitions/stylesBlocksResponsiveSelectorsWithPseudoProperties" }, { "$ref": "#/definitions/stylesBlocksPseudoSelectorsProperties" @@ -2617,7 +2655,7 @@ "$ref": "#/definitions/stylesElementsPropertiesComplete" }, "variations": { - "$ref": "#/definitions/stylesVariationsPropertiesComplete" + "$ref": "#/definitions/stylesBlockVariationsWithPseudoProperties" } } }, @@ -2975,7 +3013,7 @@ "$ref": "#/definitions/stylesProperties" }, { - "$ref": "#/definitions/stylesBlocksResponsiveSelectorsProperties" + "$ref": "#/definitions/stylesBlocksResponsiveSelectorsWithPseudoProperties" }, { "$ref": "#/definitions/stylesBlocksPseudoSelectorsProperties" @@ -3141,7 +3179,7 @@ "$ref": "#/definitions/stylesProperties" }, { - "$ref": "#/definitions/stylesBlocksResponsiveSelectorsProperties" + "$ref": "#/definitions/stylesBlocksResponsiveSelectorsWithPseudoProperties" }, { "$ref": "#/definitions/stylesBlocksPseudoSelectorsProperties" diff --git a/test/integration/fixtures/schemas/stylesBlockVariationsWithPseudoProperties.json b/test/integration/fixtures/schemas/stylesBlockVariationsWithPseudoProperties.json new file mode 100644 index 00000000000000..9e7da3678561be --- /dev/null +++ b/test/integration/fixtures/schemas/stylesBlockVariationsWithPseudoProperties.json @@ -0,0 +1,19 @@ +{ + "$schema": "../../../../schemas/json/theme.json", + "version": 3, + "styles": { + "blocks": { + "core/navigation-link": { + "variations": { + "outline": { + "-current": { + "color": { + "text": "red" + } + } + } + } + } + } + } +} diff --git a/test/integration/fixtures/schemas/stylesBlocksResponsiveSelectorsProperties.json b/test/integration/fixtures/schemas/stylesBlocksResponsiveSelectorsProperties.json new file mode 100644 index 00000000000000..4d2c643c234366 --- /dev/null +++ b/test/integration/fixtures/schemas/stylesBlocksResponsiveSelectorsProperties.json @@ -0,0 +1,17 @@ +{ + "$schema": "../../../../schemas/json/theme.json", + "version": 3, + "styles": { + "blocks": { + "core/paragraph": { + "@mobile": { + ":hover": { + "color": { + "text": "red" + } + } + } + } + } + } +} diff --git a/test/integration/fixtures/schemas/stylesBlocksResponsiveSelectorsWithPseudoProperties.json b/test/integration/fixtures/schemas/stylesBlocksResponsiveSelectorsWithPseudoProperties.json new file mode 100644 index 00000000000000..99a0b59a1bb4f5 --- /dev/null +++ b/test/integration/fixtures/schemas/stylesBlocksResponsiveSelectorsWithPseudoProperties.json @@ -0,0 +1,17 @@ +{ + "$schema": "../../../../schemas/json/theme.json", + "version": 3, + "styles": { + "blocks": { + "core/button": { + "@mobile": { + ":visited": { + "color": { + "text": "red" + } + } + } + } + } + } +} diff --git a/test/integration/fixtures/theme-json/block-states/theme.json b/test/integration/fixtures/theme-json/block-states/theme.json index 0f6f114f9689de..5ca5b9aec6f8b0 100644 --- a/test/integration/fixtures/theme-json/block-states/theme.json +++ b/test/integration/fixtures/theme-json/block-states/theme.json @@ -30,6 +30,11 @@ "@mobile": { "typography": { "fontSize": "14px" + }, + ":hover": { + "color": { + "background": "var(--wp--preset--color--secondary)" + } } }, "elements": { @@ -45,6 +50,20 @@ "color": { "text": "var(--wp--preset--color--secondary)" } + }, + "@mobile": { + ":hover": { + "color": { + "text": "var(--wp--preset--color--secondary)" + } + } + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } } } } @@ -83,6 +102,11 @@ "@mobile": { "typography": { "fontSize": "14px" + }, + ":hover": { + "color": { + "text": "var(--wp--preset--color--secondary)" + } } }, "elements": { @@ -91,6 +115,29 @@ "text": "currentColor" } } + }, + "variations": { + "outline": { + ":hover": { + "color": { + "text": "var(--wp--preset--color--secondary)" + } + }, + "@tablet": { + ":focus": { + "color": { + "text": "var(--wp--preset--color--secondary)" + } + } + }, + "elements": { + "link": { + "color": { + "text": "currentColor" + } + } + } + } } } }, From 58aa81a8f5a999c2788ccd4acb0bffcda420d9d4 Mon Sep 17 00:00:00 2001 From: Ramon Date: Thu, 6 Aug 2026 14:48:37 +1000 Subject: [PATCH 4/4] Tests: keep asserting that unknown keys on core/button are rejected `stylesPropertiesAndElementsComplete.json` used `core/button` to check that the generic block definition rejects unknown keys. `core/button` no longer reaches that definition, so the fixture was pointed at `core/paragraph` and nothing was left covering an unknown key sitting directly on `core/button`. Add a fixture for it. It fails at `#/properties/core~1button/allOf/4/propertyNames`, which is the block's own key list. --- .../stylesBlocksPropertiesComplete_button.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 test/integration/fixtures/schemas/stylesBlocksPropertiesComplete_button.json diff --git a/test/integration/fixtures/schemas/stylesBlocksPropertiesComplete_button.json b/test/integration/fixtures/schemas/stylesBlocksPropertiesComplete_button.json new file mode 100644 index 00000000000000..cf9e2c5689534f --- /dev/null +++ b/test/integration/fixtures/schemas/stylesBlocksPropertiesComplete_button.json @@ -0,0 +1,11 @@ +{ + "$schema": "../../../../schemas/json/theme.json", + "version": 3, + "styles": { + "blocks": { + "core/button": { + "invalidAdditionalProperty": true + } + } + } +}