Skip to content
Merged
26 changes: 25 additions & 1 deletion packages/blocks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,31 @@ _Parameters_

### registerBlockType

Undocumented declaration.
Registers a new block provided a unique name and an object defining its behavior. Once registered, the block is made available as an option to any editor interface where blocks are implemented.

Copilot AI Apr 27, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Grammar: “Registers a new block provided a unique name…” reads like a typo; consider “providing” (or “given”) for correct phrasing. This text comes from the source JSDoc, so fixing it there will keep regenerated docs clean.

Suggested change
Registers a new block provided a unique name and an object defining its behavior. Once registered, the block is made available as an option to any editor interface where blocks are implemented.
Registers a new block given a unique name and an object defining its behavior. Once registered, the block is made available as an option to any editor interface where blocks are implemented.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be an error in the doc itself and not in the scope of this PR?
cc: @manzoorwanijk @aduth

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we can ignore that.


For more in-depth information on registering a custom block see the [Create a block tutorial](https://developer.wordpress.org/block-editor/getting-started/create-block/).

_Usage_

```js
import { __ } from '@wordpress/i18n';
import { registerBlockType } from '@wordpress/blocks';

registerBlockType( 'namespace/block-name', {
title: __( 'My First Block' ),
edit: () => <div>{ __( 'Hello from the editor!' ) }</div>,
save: () => <div>Hello from the saved content!</div>,
} );
```

_Parameters_

- _blockNameOrMetadata_ `BlockConfiguration< Attributes >`: Block type name or its metadata.

Copilot AI Apr 27, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The generated docs list _blockNameOrMetadata_ as BlockConfiguration< Attributes >, but the same section’s usage example calls registerBlockType( 'namespace/block-name', … ) and the API overloads accept a string name. The rendered parameter type here looks misleading; it should reflect the overload set (e.g., string | BlockConfiguration<…> or separate overload signatures).

Suggested change
- _blockNameOrMetadata_ `BlockConfiguration< Attributes >`: Block type name or its metadata.
- _blockNameOrMetadata_ `string | BlockConfiguration< Attributes >`: Block type name or its metadata.

Copilot uses AI. Check for mistakes.
- _settings_ `Partial< BlockConfiguration< Attributes > >`: Block settings.

_Returns_

- `BlockType | undefined`: The block, if it has been successfully registered; otherwise `undefined`.

### registerBlockVariation

Expand Down
32 changes: 26 additions & 6 deletions packages/docgen/lib/get-intermediate-representation.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,17 @@ const hasClassWithName = ( node, name ) =>
const hasFunctionWithName = ( node, name ) =>
node.type === 'FunctionDeclaration' && node.id.name === name;

const hasTSDeclareFunction = ( node, name ) =>
node.type === 'TSDeclareFunction' && node.id?.name === name;

// Matches the concrete implementation node (FunctionDeclaration with a body),
// as opposed to a TypeScript overload signature (TSDeclareFunction).
const hasImplementationWithName = ( node, name ) =>
hasFunctionWithName( node, name ) ||
( node.type === 'ExportNamedDeclaration' &&
node.declaration &&
hasFunctionWithName( node.declaration, name ) );

const hasVariableWithName = ( node, name ) =>
node.type === 'VariableDeclaration' &&
node.declarations.some( ( declaration ) => {
Expand All @@ -32,6 +43,8 @@ const hasNamedExportWithName = ( node, name ) =>
node.type === 'ExportNamedDeclaration' &&
( ( node.declaration && hasClassWithName( node.declaration, name ) ) ||
( node.declaration && hasFunctionWithName( node.declaration, name ) ) ||
( node.declaration &&
hasTSDeclareFunction( node.declaration, name ) ) ||
( node.declaration && hasVariableWithName( node.declaration, name ) ) );

const hasImportWithName = ( node, name ) =>
Expand Down Expand Up @@ -96,14 +109,21 @@ const getJSDoc = ( token, entry, ast, parseDependency ) => {
hasImportWithName( node, entry.localName )
Comment thread
Infinite-Null marked this conversation as resolved.
Resolved
);
} );
if ( candidates.length !== 1 ) {
if ( candidates.length === 0 ) {
return doc;
}
const node = candidates[ 0 ];
if ( isImportDeclaration( node ) ) {
doc = getJSDocFromDependency( node, entry, parseDependency );
} else {
doc = getJSDocFromToken( node );
const implementationNode = candidates.find( ( node ) =>
hasImplementationWithName( node, entry.localName )
);
for ( const node of candidates ) {
if ( isImportDeclaration( node ) ) {
doc = getJSDocFromDependency( node, entry, parseDependency );
} else {
doc = getJSDocFromToken( node, implementationNode ?? node );
}
if ( doc !== undefined ) {
return doc;
}
}
Comment thread
Infinite-Null marked this conversation as resolved.
Resolved
return doc;
}
Expand Down
12 changes: 8 additions & 4 deletions packages/docgen/lib/get-jsdoc-from-token.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,14 @@ const getTypeAnnotation = require( './get-type-annotation' );
* a object representing the leading JSDoc comment of the token,
* if any.
*
* @param {Object} token Espree token.
* @param {Object} token Espree token to extract the leading JSDoc comment from.
* @param {Object} [typeAnnotationToken] Espree token to use for type inference. Defaults to `token`.
* Pass the function implementation node when the JSDoc lives on
* an overload signature so that inferred types reflect the
* implementation's parameter/return types.
* @return {Object} Object representing the JSDoc comment.
*/
module.exports = ( token ) => {
module.exports = ( token, typeAnnotationToken = token ) => {
let jsdoc;
const comments = getLeadingComments( token );
if ( comments && /^\*\r?\n/.test( comments ) ) {
Expand All @@ -44,7 +48,7 @@ module.exports = ( token ) => {

return {
...tag,
type: getTypeAnnotation( tag, token, index ),
type: getTypeAnnotation( tag, typeAnnotationToken, index ),
description:
tag.description === '\n'
? tag.description.trim()
Expand All @@ -55,7 +59,7 @@ module.exports = ( token ) => {
if ( jsdoc.tags.length === 0 ) {
const potentialTypeAnnotation = getTypeAnnotation(
{ tag: 'type' },
token,
typeAnnotationToken,
0
);
if ( potentialTypeAnnotation ) {
Expand Down
38 changes: 38 additions & 0 deletions packages/docgen/test/get-intermediate-representation.js
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,44 @@ describe( 'Intermediate Representation', () => {
} );
} );

describe( 'TypeScript function overloads', () => {
it( 'extracts description from first overload signature and infers types from the implementation', () =>
expect(
parse( `
Comment thread
Infinite-Null marked this conversation as resolved.
Resolved
/**
* Registers a new block.
* @param blockNameOrMetadata Block type name or its metadata.
* @param settings Block settings.
* @return The block, if registered; otherwise undefined.
*/
export function registerBlockType( blockNameOrMetadata: object, settings?: object ): object | undefined;
export function registerBlockType( blockNameOrMetadata: string, settings: object ): object | undefined;
export function registerBlockType( blockNameOrMetadata: string | object, settings?: object ): object | undefined {
return undefined;
}
` )
).toEqual( [
expect.objectContaining( {
description: 'Registers a new block.',
name: 'registerBlockType',
Comment thread
Infinite-Null marked this conversation as resolved.
Resolved
tags: expect.arrayContaining( [
expect.objectContaining( {
tag: 'param',
name: 'blockNameOrMetadata',
// Type comes from the implementation signature (string | object),
// not the first overload signature (object).
type: 'string | object',
} ),
expect.objectContaining( {
tag: 'return',
// Return type comes from the implementation signature.
type: 'object | undefined',
} ),
] ),
} ),
] ) );
} );

describe( 'JSDoc in module dependency through import', () => {
describe( 'default export', () => {
it( 'default import', () =>
Expand Down
Loading