-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add block nesting governance schema updates and docs #43801
Add block nesting governance schema updates and docs #43801
Conversation
👋 Thanks for your first Pull Request and for helping build the future of Gutenberg and WordPress, @alecgeatches! In case you missed it, we'd love to have you join us in our Slack community, where we hold regularly weekly meetings open to anyone to coordinate with each other. If you want to learn more about WordPress development in general, check out the Core Handbook full of helpful information. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you so much for fixing all of those issues that the schema has! And adding the schema validation test is another huge win!
We couldn't find a
draft-04
-compatible setup that would allow for this configuration. Instead, this usesdraft-07
'spropertyNames
feature workaround mentioned in the link above.
The example in that link can be achieved in draft-04, albeit not as cleanly as with draft-07's propertyNames
.
Expand to reference the example from the link.
This fails because an object with both foo
and bar
doesn't pass both tests individually.
{
"type": "object",
"allOf": [
{ "$ref": "#/definitions/foo" },
{ "$ref": "#/definitions/bar" }
],
"definitions": {
"foo": {
"properties": {
"foo": { "type": "string" }
},
"additionalProperties": false
},
"bar": {
"properties": {
"bar": { "type": "number" }
},
"additionalProperties": false
}
}
}
In draft-07 the merging is done like this.
{
"type": "object",
"allOf": [
{ "$ref": "#/definitions/foo" },
{ "$ref": "#/definitions/bar" }
],
"propertyNames": {
"anyOf": [
{ "$ref": "#/definitions/fooNames" },
{ "$ref": "#/definitions/barNames" }
]
},
"definitions": {
"foo": {
"properties": {
"foo": { "type": "string" }
}
},
"fooNames": { "enum": ["foo"] },
"bar": {
"properties": {
"bar": { "type": "number" }
}
},
"barNames": { "enum": ["bar"] }
}
}
In draft-04, you have to manually merge the property names like this.
{
"type": "object",
"allOf": [
{ "$ref": "#/definitions/foo" },
{ "$ref": "#/definitions/bar" },
{
"properties": {
"foo": {},
"bar": {}
},
"additionalProperties": false
}
],
"definitions": {
"foo": {
"properties": {
"foo": { "type": "string" }
}
},
"bar": {
"properties": {
"bar": { "type": "number" }
}
}
}
}
In the theme.json schema, we use the terminology *Complete
when a definition includes the empty properties and "additionalProperties": false
. It makes for a long list of definitions when you need to add every combination manually, but it is possible with to add all of them.
{
"type": "object",
"properties": {
"foo": { "$ref": "#/definitions/fooComplete" },
"bar": { "$ref": "#/definitions/barComplete" },
"foobar": { "$ref": "#/definitions/foobarComplete" }
},
"additionalProperties": false,
"definitions": {
"foo": {
"properties": {
"foo": { "type": "string" }
}
},
"fooComplete": {
"allOf": [
{ "$ref": "#/definitions/foo" },
{
"properties": { "foo": {} },
"additionalProperties": false
}
]
},
"bar": {
"properties": {
"bar": { "type": "number" }
}
},
"barComplete": {
"allOf": [
{ "$ref": "#/definitions/bar" },
{
"properties": { "bar": {} },
"additionalProperties": false
}
]
},
"foobar": {
"allOf": [
{ "$ref": "#/definitions/foo" },
{ "$ref": "#/definitions/bar" }
]
},
"foobarComplete": {
"allOf": [
{ "$ref": "#/definitions/foobar" },
{
"properties": {
"foo": {},
"bar": {}
},
"additionalProperties": false
}
]
}
}
}
Unfortunately, with this method, all places that merge properties need to update their own list of properties when a new property is added to any of the children—draft-07's propertyNames
would avoid the problem.
One more thing to consider is that the WordPress core JSON Schema validator used by the REST API only supports draft-04. If we ever wanted to utilize that for theme.json (we're currently doing custom validation), we'd also want to stick with draft-04.
See if you can refactor it to draft-04 using the method shown above. I personally think that the benefits of sticking to draft-04 are worth the maintenance burden that propertyNames
helps with.
} ); | ||
|
||
test( 'schema valid', () => { | ||
const result = ajv.validate( themeSchema, baseThemeJson ) || ajv.errors; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First off, thank you for adding tests here! Based on the number of things you've had to fix, this is sorely needed.
I think we could validate the schema directly rather than indirectly by validating data. I think you should be able to do something like this with AJV.
const result = ajv.validate( themeSchema, baseThemeJson ) || ajv.errors; | |
const result = ajv.validate( | |
'http://json-schema.org/draft-07/schema#', | |
themeSchema | |
) || ajv.errors; |
}, | ||
"settingsBlocksPropertiesComplete": { | ||
"type": "object", | ||
"properties": { | ||
"core/archives": { | ||
"description": "Archive block. Display a monthly archive of your posts. This block has no block-level settings", | ||
"additionalProperties": false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The archives block does not have any block-level settings, so we should probably update this to add "type": "object"
rather than removing "additionalProperties": false
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, that makes sense to me!
schemas/json/theme.json
Outdated
}, | ||
"core/audio": { | ||
"$ref": "#/definitions/settingsPropertiesComplete" | ||
"$ref": "#/definitions/settingsPropertiesNested" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If a block doesn't support inner blocks, should we allow nested properties?
We're avoiding the specific settings that are available to each block because blocks are getting new supports pretty often and there's a high maintenance overhead for keeping the specifics up to date, but blocks updating to support nesting happens pretty rarely, so I don't think it would be too big of a problem to use settingsPropertiesComplete
for blocks that don't have inner blocks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a great idea - limiting which blocks allow nesting via the schema will also make the intellisense a lot more helpful.
@ajlende Thank you for all of the great feedback! I've applied your guidance using
|
Wouldn't it make sense to put the definition of blocks inside {
"color": {
"text": true
},
"blocks": {
"core/child-block": {
"color": {
"text": false
}
},
"core/parent-block": {
"color": {
"text": false
},
"blocks": {
"core/child-block": {
"color": {
"text": true
}
}
}
}
}
} If we skip And also, wouldn't that make the |
@luisherranz Thank you for the feedback! @ingeniumed and I have been discussing this. We agree it would definitely make the schema changes easier, but we’re not sure if nesting blocks is a cause for confusion:
From the perspective of the designer/developer in Your suggested approach would be good for simplifying the schema changes by namespacing the new changes to a @luisherranz We’d love to hear any follow-up thoughts on this or if anyone else can add in as well. Thank you! We’d also be interested in @dabowman’s opinion here on @luisherranz schema changes above from the designer perspective. |
Sure. Let's bring more opinions: cc @mtias, @mcsf, @youknowriad, @oandregal, @jorgefilipecosta. |
Given our chat with the Gutenberg IO team and @mcsf's comment here with a different approach, we're likely not going to need the schema changes for nesting. However, since the original test changes and schema fixes may provide some value, we're going to split that off into a different PR. We'll plan to keep this PR around for a bit until we're sure #43796 isn't going to be involved. Thank you! |
Please see #44252 for just the test changes to the existing schema. Thank you! |
Closing this issue as the related nesting governance in #43796 has been closed, and the unit test changes from this PR were merged separately in #44252. @ingeniumed has created another (smaller) PR in #45089 to address governance within a plugin. Thank you! |
This PR contains the schema updates to theme.json used in the block nesting implementation in #43796. That PR allows for nesting blocks in theme.json like this:
With the setup above, a
core/child-block
will havecolor.text === true
when nested in acore/parent-block
. We've added this as a separate PR, since these schema changes are a bit more controversial and might be a different discussion.What?
There are a handful of related changes bundled here:
theme-schema.test.js
based on existing block schema tests. The existing schema failed validation with Ajv's strict mode againstdraft-04
, mostly due to some missingtype
identifiers and a handful of other small changes.Why?
Block nesting support has been added to support the
theme.json
parsing and block editor changes in #43796.While we were updating the schema, it seemed like a good idea to put the existing
schemas/json/theme.json
file under test to ensure nothing was getting broken. Since the existing schema did not pass Ajv'sdraft-04
validation, some minor changes were made to fix the errors. These are covered in the How section.How
Validation changes
As discussed above, some minor changes were made to the original schema to make it validate correctly against
draft-04
. To view the original errors, check out theadd/theme-schema-updates-and-docs
branch of the related fork and use the7bc6ee9
commit to view the original errors. Running the test gives this validation result:Click to expand
Those individual fixes are documented in these commits:
Fix missing property object types for errors like:
Remove type conflict in fontWeight for this error:
Refactor fontSizes.fluid into non-union type for this error:
Fix core/archives non-property block having additionalProperties: false for this error:
Some additional fixes in Fix stylesProperties type and Fix styleProperties border direction properties that cropped up after the previous fixes, mostly addressing additional
properties
object types missing. This also fixes theborder
autogenerated documentation fortop
/bottom
/left
/right
.Nested styling changes
To support nested styling, some new definitions were added:
settingsBlocksPropertiesComplete
now wraps asettingsBlocksProperties
definition using the style mentioned in the current PR by @ajlende.settingsNestedPropertiesComplete
was added, which wrapssettingsProperties
andsettingsBlocksProperties
.settingsBlocksProperties
, blocks which support nesting usesettingsNestedPropertiesComplete
, and all other core blocks default to usingsettingsProperties
.There is some duplication due to
draft-04
compatibility. For example, thecore/archives
block settings definitions are repeated in these places:settingsBlocksProperties
(used bysettingsBlocksPropertiesComplete
andsettingsNestedPropertiesComplete
).settingsBlocksPropertiesComplete
(used by the top levelsettings.blocks
definition)settingsNestedPropertiesComplete
(used by blocks that support nesting)As far as we're aware, this is the most succinct way to represent these nested properties in
draft-04
. The previous version of this PR useddraft-07
andpropertyNames
, but after discussion with @ajlende it's been rewritten to bedraft-04
compatible.Testing Instructions
To test theme validation, run:
Schema changes are manually testable by editing an existing theme.json file and setting the schema to the new
theme.json
schema in this branch:Screenshots or screencast
Here's a quick demo showing nested block settings working with the
draft-07
schema with autocompletion in VS Code:theme-json-block-nesting.mp4