-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
Blocks: Add enum validation to browser block parser #14810
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -116,6 +116,36 @@ export function isOfTypes( value, types ) { | |
return types.some( ( type ) => isOfType( value, type ) ); | ||
} | ||
|
||
/** | ||
* Returns true if value is valid per the given block attribute schema type | ||
* definition, or false otherwise. | ||
* | ||
* @link https://json-schema.org/latest/json-schema-validation.html#rfc.section.6.1.1 | ||
* | ||
* @param {*} value Value to test. | ||
* @param {?(Array<string>|string)} type Block attribute schema type. | ||
* | ||
* @return {boolean} Whether value is valid. | ||
*/ | ||
export function isValidByType( value, type ) { | ||
return type === undefined || isOfTypes( value, castArray( type ) ); | ||
} | ||
|
||
/** | ||
* Returns true if value is valid per the given block attribute schema enum | ||
* definition, or false otherwise. | ||
* | ||
* @link https://json-schema.org/latest/json-schema-validation.html#rfc.section.6.1.2 | ||
* | ||
* @param {*} value Value to test. | ||
* @param {?Array} enumSet Block attribute schema enum. | ||
* | ||
* @return {boolean} Whether value is valid. | ||
*/ | ||
export function isValidByEnum( value, enumSet ) { | ||
return ! Array.isArray( enumSet ) || enumSet.includes( value ); | ||
} | ||
|
||
/** | ||
* Returns true if the given attribute schema describes a value which may be | ||
* an ambiguous string. | ||
|
@@ -242,7 +272,7 @@ export function parseWithAttributeSchema( innerHTML, attributeSchema ) { | |
* @return {*} Attribute value. | ||
*/ | ||
export function getBlockAttribute( attributeKey, attributeSchema, innerHTML, commentAttributes ) { | ||
const { type } = attributeSchema; | ||
const { type, enum: enumSet } = attributeSchema; | ||
let value; | ||
|
||
switch ( attributeSchema.source ) { | ||
|
@@ -262,9 +292,9 @@ export function getBlockAttribute( attributeKey, attributeSchema, innerHTML, com | |
break; | ||
} | ||
|
||
if ( type !== undefined && ! isOfTypes( value, castArray( type ) ) ) { | ||
// Reject the value if it is not valid of type. Reverting to the | ||
// undefined value ensures the default is restored, if applicable. | ||
if ( ! isValidByType( value, type ) || ! isValidByEnum( value, enumSet ) ) { | ||
// Reject the value if it is not valid. Reverting to the undefined | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should it warn in development mode? I guess the answer should be yes. What's the reason we silently reject it? I don't see it as a blocker but I would like to see a roadmap for making extensibility easier by providing good feedback for developers. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I agree on all accounts. I'm inclined to merge this as-is with consideration that it follows the same precedent established by type validation. I agree we should probably include some feedback here, and will plan to create a follow-up issue. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In fact, I think it's quite similar to the issue at #7653 , which had been closed (as it impacted the server implementation, which we're mirroring now in the client). Which is worth highlighting: Server-side we silently drop the attributes as well: Whatever we choose to do, I'd suggest it be made consistent across the two runtimes. Do you think it'd make sense to reopen #7653 for this? Or create a separate issue? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We rather open a ticket in Trac and new issue on GitHub as those are related things but still different. I think that validation and error handling in Gutenberg are rather randomly added and it should be something that should become the focus. Ideally, there is RFC created with a project-wide proposal rather than trying to fix it case by case. There is this related work needed to implement errors catching in code registered by plugins:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm new to WordPress and was debugging someone else's custom block that was failing validation on reloading the editor. The silent failure here made it very difficult to understand why the block would fail validation upon reloading the editor and I ended up having to use a debugger and trace/read the Gutenberg source back to this section of the code. Was a ticket ever created to track better logging/feedback for errors? I haven't been able to find it. Longer explanation on why I feel this is needed: I had initially missed this bit of explanation in the Block documentation:
Combined with the silent validation failures made me believe that the information was indeed being saved as expected. I validated this by confirming that the expected data was saved in Also, with regards to the Block documentation, I would argue that if no validation feedback will be added, then the above explanation should be moved out of Considerations and more prominently explained at the top of the Attributes section as it's a requirement to making custom blocks work. |
||
// value ensures the default is respected, if applicable. | ||
value = undefined; | ||
} | ||
|
||
|
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.
In case you're wondering:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#Future_reserved_keywords