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
@wordpress/blocks: Register block from metadata #55245
@wordpress/blocks: Register block from metadata #55245
Conversation
registerBlockType now accepts input from the block.json metadata WordPress/gutenberg#32030
@ofhouse Thank you for submitting this PR! This is a live comment which I will keep updated. 1 package in this PRCode ReviewsBecause you edited one package and updated the tests (👏), I can help you merge this PR once someone else signs off on it. You can test the changes of this PR in the Playground. Status
All of the items on the list are green. To merge, you need to post a comment including the string "Ready to merge" to bring in your changes. Diagnostic Information: What the bot saw about this PR{
"type": "info",
"now": "-",
"pr_number": 55245,
"author": "ofhouse",
"headCommitOid": "5124723a68244a49b68a49a9a5172736be783377",
"lastPushDate": "2021-09-23T07:22:42.000Z",
"lastActivityDate": "2021-09-23T18:49:45.000Z",
"mergeOfferDate": "2021-09-23T18:46:45.000Z",
"mergeRequestDate": "2021-09-23T18:49:45.000Z",
"mergeRequestUser": "dmsnell",
"hasMergeConflict": false,
"isFirstContribution": false,
"tooManyFiles": false,
"popularityLevel": "Well-liked by everyone",
"pkgInfo": [
{
"name": "wordpress__blocks",
"kind": "edit",
"files": [
{
"path": "types/wordpress__blocks/api/registration.d.ts",
"kind": "definition"
},
{
"path": "types/wordpress__blocks/index.d.ts",
"kind": "definition"
},
{
"path": "types/wordpress__blocks/wordpress__blocks-tests.tsx",
"kind": "test"
}
],
"owners": [
"dsifford",
"sirreal",
"dmsnell"
],
"addedOwners": [],
"deletedOwners": [],
"popularityLevel": "Well-liked by everyone"
}
],
"reviews": [
{
"type": "approved",
"reviewer": "dmsnell",
"date": "2021-09-23T18:46:09.000Z",
"isMaintainer": false
}
],
"mainBotCommentID": 901975566,
"ciResult": "pass"
} |
🔔 @dsifford @sirreal @dmsnell — please review this PR in the next few days. Be sure to explicitly select |
types/wordpress__blocks/index.d.ts
Outdated
readonly attributes: { | ||
readonly [k in keyof T]: any; | ||
}; | ||
readonly innerBlocks?: any[]; |
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.
this isn't really any[]
here since the innerBlocks
need to be blocks. does Block<any>
or Block<unknown>
work?
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.
Block<any>
would not work since it only needs takes the name
and attributes
properties:
example: {
attributes: {
cover: 'https://example.com/image.jpg',
},
innerBlocks: [
{
name: 'core/paragraph',
attributes: {
/* translators: example text. */
content: __(
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent et eros eu felis.'
),
},
},
],
},
Example from here.
Would go with
readonly innerBlocks?: ReadonlyArray<{ name: string; attributes: Record<string, any> }>;
for now.
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 we only need those properties that seems like we could use this to do that…
type InnerBlock = Partial<Block> & Pick<Block, 'name' | 'attributes'>;
this prevents us from needing to duplicate the definitions of the block types and also preserves the fact that in many (all?) cases those other properties will be there, even if not mandatory for some reason. otherwise we're saying, among other things, that it's not possible to have inner blocks which themselves contain 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.
Would generally agree, but the attributes
type seems different:
While Block.attributes
expects a declarative object in the form of:
attributes: {
foo: {
source: 'text';
type: 'string';
}
}
The attributes property of the innerBlocks
seem to be passed by value:
attributes: {
foo: 'bar'
}
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.
While Block.attributes expects a declarative object in the form of:
This is a good point. I think the block attributes types are a big confused at this point. There's the BlockConfiguration
which takes those attribute declarations, but the Block
objects themselves take attributes that are the real types, which cannot be those same types as given for the BlockConfiguration
don't let this hold up the PR. if we can't reuse Block['attributes']
as we ideally would, we can fix that later.
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.
Ah okay, yes your proposed type seem to work fine with the example.
However looking at the implementation it seems that innerBlocks
can be recursive:
I've now updated the type to:
type BlockExampleInnerBlock = ReadonlyArray<
Partial<Block> &
Pick<Block, 'name' | 'attributes'> & {
innerBlocks?: BlockExampleInnerBlock;
}
>;
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.
it seems that innerBlocks can be recursive:
yep! that's one of the reasons I brought it up.
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.
though…we shouldn't limit it to BlockExampleInnerBlock
. I think in this case Pick<Block, 'name' | 'attributes' | 'innerBlocks'>
would work, otherwise what we're saying is not just that the block can be recursive, but that it can only be recursive on its own type.
consider the group block; it can have child blocks of any type because its role is to be a kind of neutral container. if we kept this definition then we wouldn't be able to show any meaningful example for a column block because it would demand we only allow group
blocks to be the children of a group block.
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.
my last comment was wrong; sorry for saying otherwise. I didn't see at first what you were doing here.
concretely though I think we might want to drop attributes
because not every block requires it and I don't want to overconstrain our types on the example code. on the example
property that means maybe mark it also as optional or do this
example?: Readonly<Partial<Block> & Pick<Block, 'name'> & {innerBlocks: ReadonlyArray<BlockExampleInnerBlock>}>;
that's the only thing I think that would likely need to change here. I don't want to hold up this PR and I'm afraid I made comments pushing you to something that I'm now suggesting walking back from. if you don't agree with me I'll still give my approval - these make the types better. primarily I just want to avoid falsely indicating a type error where none exists.
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.
Sorry for the late response, thanks for the detailed explanations 👍
example.name
path doesn't seem to be required from the docs, so I guess
example?: Readonly<Partial<Block> & { innerBlocks: ReadonlyArray<BlockExampleInnerBlock> }>;
is fine here?
@dmsnell Thank you for reviewing this PR! The author has pushed new commits since your last review. Could you take another look and submit a fresh review? |
@dmsnell Thank you for reviewing this PR! The author has pushed new commits since your last review. Could you take another look and submit a fresh review? |
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.
This all seems fine to me. We can update as we go if we find blockers.
Re-ping @ofhouse / @dsifford, @sirreal: This PR has been ready to merge for over a week, and I haven't seen any requests to merge it. I will close it on Oct 1st (in three weeks) if this doesn't happen. (If there's no reason to avoid merging it, please do so. Otherwise, if it shouldn't be merged or if it needs more time, please close it or turn it into a draft.) |
Could someone please merge this? Thanks. |
Sorry for the delay, will try to take another look at it soon. |
@dmsnell Thank you for reviewing this PR! The author has pushed new commits since your last review. Could you take another look and submit a fresh review? |
types/wordpress__blocks/index.d.ts
Outdated
* | ||
* @see {@link https://developer.wordpress.org/block-editor/reference-guides/block-api/block-metadata/#example} | ||
*/ | ||
readonly example?: Readonly<Partial<Block> & { innerBlocks: ReadonlyArray<BlockExampleInnerBlock> }>; |
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.
quick update here: I believe that we need to make innerBlocks
optional here otherwise people will have to provide inner blocks in their examples even if the blocks don't support them.
… & { innerBlocks?: ReadonlyArray<BlockExampleInnerBlock> }
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.
Yes, good point. Fixed it 👍
One quick update and then happy to get this merged. |
@dmsnell Thank you for reviewing this PR! The author has pushed new commits since your last review. Could you take another look and submit a fresh review? |
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.
Thanks!
Ready to merge |
Thanks for merging this! Looks like there's still a bit of an issue though. The following should work, but the 2nd arg is considered invalid: import { registerBlockType } from '@wordpress/blocks'
import edit from './edit'
const metadata = {
apiVersion: 2,
name: 'foo/bar',
category: 'widgets',
attributes: {},
example: {},
title: 'Block title',
textdomain: 'foo',
script: 'file:./script.js',
editorScript: 'file:./editor-script.js',
}
registerBlockType(metadata, { edit }) The problem is that the 2nd arg, while optional, still requires all the same props if present, whereas with the new signature, it shouldn't require any. |
@ZebulanStanphill are you saying that the second argument should be any interest in submitting a small PR to fix that? |
Hi,
the
registerBlockType
method now accepts metadata input from theblock.json
metadata.Changes
registerBlockType
to accept the metadata as first and optionally second argument.Block
type with the missing properties from the metadata (https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration)Related docs
9.1.0
: https://github.com/WordPress/gutenberg/blob/trunk/packages/blocks/CHANGELOG.md#910-2021-05-20registerBlockTypeFromMetadata
in favor ofregisterBlockType
WordPress/gutenberg#32030Please fill in this template.
npm test <package to test>
.Select one of these and delete the others:
If changing an existing definition: