Skip to content
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: Ensure that metadata registered on the server for core block is preserved on the client (try 2) #29302

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions packages/blocks/src/api/registration.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,23 @@ export const serverSideBlockDefinitions = {};
// eslint-disable-next-line camelcase
export function unstable__bootstrapServerSideBlockDefinitions( definitions ) {
for ( const blockName of Object.keys( definitions ) ) {
// Don't overwrite if already set. It covers the case when metadata
// was initialized from the server.
if ( serverSideBlockDefinitions[ blockName ] ) {
// We still need to polyfill `apiVersion` for WordPress version
// lower than 5.7. If it isn't present in the definition shared
// from the server, we try to fallback to the definition passed.
// @see https://github.com/WordPress/gutenberg/pull/29279
if (
serverSideBlockDefinitions[ blockName ].apiVersion ===
undefined &&
definitions[ blockName ].apiVersion
Copy link
Contributor

Choose a reason for hiding this comment

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

I think I spotted a few more differences on the server definition:

  • Missing editorStyle
  • Sometimes items in supports, get expanded in block attributes (I think this is okay)
  • Missing style

Copy link
Contributor

Choose a reason for hiding this comment

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

It might be worth setting up a test case with all block registration items set and then compare to see what's returned.

Copy link
Member Author

@gziolo gziolo Feb 25, 2021

Choose a reason for hiding this comment

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

Missing editorStyle
Missing style

At the moment it's used only on the server to enqueue CSS files, for example:
https://github.com/WordPress/gutenberg/blob/master/docs/designers-developers/developers/block-api/block-metadata.md#editor-style

In the future, we might need it on the client to lazy load CSS or JS files for the block.

Edit: In fact, those fields were used in the past for installing blocks from Block Directory, but it was replaced with a different approach in #24117. However, in practice, Block Directory uses its own endpoint to get the block metadata which is further processed block.json file:

const results = yield apiFetch( {
path: `wp/v2/block-directory/search?term=${ filterValue }`,
} );

Sometimes items in supports, get expanded in block attributes (I think this is okay)

Yes, it's used quite extensively for features built-in in the block editor like alignment, custom class name, anchor, fonts, colors, and other stuff that Global Styles offer. Most (hopefully all) of the hooks that add those fields for attributes respect the version created by developers.

Copy link
Contributor

Choose a reason for hiding this comment

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

Great, sounds like this should be relatively safe to try again. ✨

) {
serverSideBlockDefinitions[ blockName ].apiVersion =
definitions[ blockName ].apiVersion;
}
continue;
}
serverSideBlockDefinitions[ blockName ] = mapKeys(
pickBy( definitions[ blockName ], ( value ) => ! isNil( value ) ),
( value, key ) => camelCase( key )
Expand Down
37 changes: 37 additions & 0 deletions packages/blocks/src/api/test/registration.js
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,43 @@ describe( 'blocks', () => {
} );
} );

// This test can be removed once the polyfill for apiVersion gets removed.
it( 'should apply apiVersion on the client when not set on the server', () => {
const blockName = 'core/test-block-back-compat';
unstable__bootstrapServerSideBlockDefinitions( {
[ blockName ]: {
category: 'widgets',
},
} );
unstable__bootstrapServerSideBlockDefinitions( {
[ blockName ]: {
apiVersion: 2,
category: 'ignored',
},
} );

const blockType = {
title: 'block title',
};
registerBlockType( blockName, blockType );
expect( getBlockType( blockName ) ).toEqual( {
apiVersion: 2,
name: blockName,
save: expect.any( Function ),
title: 'block title',
category: 'widgets',
icon: {
src: blockIcon,
},
attributes: {},
providesContext: {},
usesContext: [],
keywords: [],
supports: {},
styles: [],
} );
} );

it( 'should validate the icon', () => {
const blockType = {
save: noop,
Expand Down
28 changes: 28 additions & 0 deletions packages/e2e-tests/plugins/register-block-type-hooks.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php
/**
* Plugin Name: Gutenberg Test Register Block Type Hooks
* Plugin URI: https://github.com/WordPress/gutenberg
* Author: Gutenberg Team
*
* @package gutenberg-test-register-block-type-hooks
*/

/**
* Changes the category for the paragraph block.
*
* @param array $metadata Array of metadata for registering a block type.
*
* @return array Filtered metadata for registering a block type.
*/
function gutenberg_test_block_type_metadata( $metadata ) {
if ( 'core/paragraph' !== $metadata['name'] ) {
return $metadata;
}

return array_merge(
$metadata,
array( 'category' => 'widgets' )
);
}

add_filter( 'block_type_metadata', 'gutenberg_test_block_type_metadata' );
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* WordPress dependencies
*/
import {
activatePlugin,
createNewPost,
deactivatePlugin,
openGlobalBlockInserter,
} from '@wordpress/e2e-test-utils';

describe( 'Register block type hooks', () => {
beforeEach( async () => {
await activatePlugin( 'gutenberg-test-register-block-type-hooks' );
await createNewPost();
} );

afterEach( async () => {
await deactivatePlugin( 'gutenberg-test-register-block-type-hooks' );
} );

it( 'has a custom category for Paragraph block', async () => {
await openGlobalBlockInserter();

const widgetsCategory = await page.$(
'.block-editor-block-types-list[aria-label="Widgets"]'
);

expect(
await widgetsCategory.$( '.editor-block-list-item-paragraph' )
).toBeDefined();
} );
} );