diff --git a/docs/reference-guides/theme-json-reference/theme-json-living.md b/docs/reference-guides/theme-json-reference/theme-json-living.md index 0096a41be04ba..061c1db655729 100644 --- a/docs/reference-guides/theme-json-reference/theme-json-living.md +++ b/docs/reference-guides/theme-json-reference/theme-json-living.md @@ -139,10 +139,10 @@ Border styles. | radius | undefined | | | style | string | | | width | string | | -| top | undefined | | -| right | undefined | | -| bottom | undefined | | -| left | undefined | | +| top | object | color, style, width | +| right | object | color, style, width | +| bottom | object | color, style, width | +| left | object | color, style, width | --- diff --git a/schemas/json/theme.json b/schemas/json/theme.json index 58cfe1ea001f0..0e658ad266624 100644 --- a/schemas/json/theme.json +++ b/schemas/json/theme.json @@ -8,6 +8,7 @@ "reference": "https://developer.wordpress.org/block-editor/how-to-guides/themes/theme-json/" }, "settingsPropertiesAppearanceTools": { + "type": "object", "properties": { "appearanceTools": { "description": "Setting that enables the following UI tools:\n\n- border: color, radius, style, width\n- color: link\n- spacing: blockGap, margin, padding\n- typography: lineHeight", @@ -26,6 +27,7 @@ } }, "settingsPropertiesBorder": { + "type": "object", "properties": { "border": { "description": "Settings related to borders.", @@ -57,6 +59,7 @@ } }, "settingsPropertiesColor": { + "type": "object", "properties": { "color": { "description": "Settings related to colors.", @@ -186,6 +189,7 @@ } }, "settingsPropertiesLayout": { + "type": "object", "properties": { "layout": { "description": "Settings related to layout.", @@ -205,6 +209,7 @@ } }, "settingsPropertiesSpacing": { + "type": "object", "properties": { "spacing": { "description": "Settings related to spacing.", @@ -305,6 +310,7 @@ } }, "settingsPropertiesTypography": { + "type": "object", "properties": { "typography": { "description": "Settings related to typography.", @@ -374,18 +380,25 @@ }, "fluid": { "description": "Specifics the minimum and maximum font size value of a fluid font size. Set to `false` to bypass fluid calculations and use the static `size` value.", - "type": [ "object", "boolean" ], - "properties": { - "min": { - "description": "A min font size for fluid font size calculations in px, rem or em.", - "type": "string" + "oneOf": [ + { + "type": "object", + "properties": { + "min": { + "description": "A min font size for fluid font size calculations in px, rem or em.", + "type": "string" + }, + "max": { + "description": "A max font size for fluid font size calculations in px, rem or em.", + "type": "string" + } + }, + "additionalProperties": false }, - "max": { - "description": "A max font size for fluid font size calculations in px, rem or em.", - "type": "string" + { + "type": "boolean" } - }, - "additionalProperties": false + ] } }, "additionalProperties": false @@ -427,7 +440,6 @@ }, "fontWeight": { "description": "List of available font weights, separated by a space.", - "type": "string", "default": "400", "oneOf": [ { @@ -515,6 +527,7 @@ } }, "settingsPropertiesCustom": { + "type": "object", "properties": { "custom": { "description": "Generate custom CSS custom properties of the form `--wp--custom--{key}--{nested-key}: {value};`. `camelCased` keys are transformed to `kebab-case` as to follow the CSS property naming schema. Keys at different depth levels are separated by `--`, so keys should not include `--` in the name.", @@ -557,6 +570,7 @@ "type": "object", "properties": { "core/archives": { + "type": "object", "description": "Archive block. Display a monthly archive of your posts. This block has no block-level settings", "additionalProperties": false }, @@ -570,11 +584,13 @@ "$ref": "#/definitions/settingsPropertiesComplete" }, "core/button": { + "type": "object", "allOf": [ { "$ref": "#/definitions/settingsPropertiesAppearanceTools" }, { + "type": "object", "properties": { "border": { "description": "Settings related to borders.\nGutenberg plugin required.", @@ -857,6 +873,7 @@ } }, "stylesProperties": { + "type": "object", "properties": { "border": { "description": "Border styles.", @@ -904,60 +921,76 @@ "type": "string" }, "top": { - "color": { - "description": "Sets the `border-top-color` CSS property.", - "type": "string" - }, - "style": { - "description": "Sets the `border-top-style` CSS property.", - "type": "string" + "type": "object", + "properties": { + "color": { + "description": "Sets the `border-top-color` CSS property.", + "type": "string" + }, + "style": { + "description": "Sets the `border-top-style` CSS property.", + "type": "string" + }, + "width": { + "description": "Sets the `border-top-width` CSS property.", + "type": "string" + } }, - "width": { - "description": "Sets the `border-top-width` CSS property.", - "type": "string" - } + "additionalProperties": false }, "right": { - "color": { - "description": "Sets the `border-right-color` CSS property.", - "type": "string" - }, - "style": { - "description": "Sets the `border-right-style` CSS property.", - "type": "string" + "type": "object", + "properties": { + "color": { + "description": "Sets the `border-right-color` CSS property.", + "type": "string" + }, + "style": { + "description": "Sets the `border-right-style` CSS property.", + "type": "string" + }, + "width": { + "description": "Sets the `border-right-width` CSS property.", + "type": "string" + } }, - "width": { - "description": "Sets the `border-right-width` CSS property.", - "type": "string" - } + "additionalProperties": false }, "bottom": { - "color": { - "description": "Sets the `border-bottom-color` CSS property.", - "type": "string" - }, - "style": { - "description": "Sets the `border-bottom-style` CSS property.", - "type": "string" + "type": "object", + "properties": { + "color": { + "description": "Sets the `border-bottom-color` CSS property.", + "type": "string" + }, + "style": { + "description": "Sets the `border-bottom-style` CSS property.", + "type": "string" + }, + "width": { + "description": "Sets the `border-bottom-width` CSS property.", + "type": "string" + } }, - "width": { - "description": "Sets the `border-bottom-width` CSS property.", - "type": "string" - } + "additionalProperties": false }, "left": { - "color": { - "description": "Sets the `border-left-color` CSS property.", - "type": "string" - }, - "style": { - "description": "Sets the `border-left-style` CSS property.", - "type": "string" + "type": "object", + "properties": { + "color": { + "description": "Sets the `border-left-color` CSS property.", + "type": "string" + }, + "style": { + "description": "Sets the `border-left-style` CSS property.", + "type": "string" + }, + "width": { + "description": "Sets the `border-left-width` CSS property.", + "type": "string" + } }, - "width": { - "description": "Sets the `border-left-width` CSS property.", - "type": "string" - } + "additionalProperties": false } }, "additionalProperties": false diff --git a/test/integration/theme-schema.test.js b/test/integration/theme-schema.test.js new file mode 100644 index 0000000000000..0e5ed88a1441e --- /dev/null +++ b/test/integration/theme-schema.test.js @@ -0,0 +1,27 @@ +/** + * External dependencies + */ +import Ajv from 'ajv-draft-04'; + +/** + * Internal dependencies + */ +import themeSchema from '../../schemas/json/theme.json'; + +describe( 'theme.json schema', () => { + const ajv = new Ajv( { + // Used for matching unknown blocks without repeating core blocks names + // with patternProperties in settings.blocks and settings.styles + allowMatchingProperties: true, + } ); + + it( 'strictly adheres to the draft-04 meta schema', () => { + // Use ajv.compile instead of ajv.validateSchema to validate the schema + // because validateSchema only checks syntax, whereas, compile checks + // if the schema is semantically correct with strict mode. + // See https://github.com/ajv-validator/ajv/issues/1434#issuecomment-822982571 + const result = ajv.compile( themeSchema ); + + expect( result.errors ).toBe( null ); + } ); +} );