mirror of
https://github.com/gosticks/wordpress-develop.git
synced 2026-06-28 14:20:15 +00:00
Editor: Add viewScriptModule handling to block.json metadata
Syncing changes from the Gutenberg plugin: https://github.com/WordPress/gutenberg/pull/57437. Scripts and styles can be registered for blocks via `block.json` metadata. There is now a Modules API, but was no way to register or associate module assets with blocks via `block.json`. Fixes #60233. Props jonsurrell, gziolo, cbravobernal, luisherranz, youknowriad. git-svn-id: https://develop.svn.wordpress.org/trunk@57565 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
@@ -36,6 +36,7 @@ function remove_block_asset_path_prefix( $asset_handle_or_path ) {
|
||||
*
|
||||
* @since 5.5.0
|
||||
* @since 6.1.0 Added `$index` parameter.
|
||||
* @since 6.5.0 Added support for `viewScriptModule` field.
|
||||
*
|
||||
* @param string $block_name Name of the block.
|
||||
* @param string $field_name Name of the metadata field.
|
||||
@@ -52,6 +53,9 @@ function generate_block_asset_handle( $block_name, $field_name, $index = 0 ) {
|
||||
if ( str_starts_with( $field_name, 'view' ) ) {
|
||||
$asset_handle .= '-view';
|
||||
}
|
||||
if ( str_ends_with( strtolower( $field_name ), 'scriptmodule' ) ) {
|
||||
$asset_handle .= '-script-module';
|
||||
}
|
||||
if ( $index > 0 ) {
|
||||
$asset_handle .= '-' . ( $index + 1 );
|
||||
}
|
||||
@@ -59,12 +63,13 @@ function generate_block_asset_handle( $block_name, $field_name, $index = 0 ) {
|
||||
}
|
||||
|
||||
$field_mappings = array(
|
||||
'editorScript' => 'editor-script',
|
||||
'script' => 'script',
|
||||
'viewScript' => 'view-script',
|
||||
'editorStyle' => 'editor-style',
|
||||
'style' => 'style',
|
||||
'viewStyle' => 'view-style',
|
||||
'editorScript' => 'editor-script',
|
||||
'editorStyle' => 'editor-style',
|
||||
'script' => 'script',
|
||||
'style' => 'style',
|
||||
'viewScript' => 'view-script',
|
||||
'viewScriptModule' => 'view-script-module',
|
||||
'viewStyle' => 'view-style',
|
||||
);
|
||||
$asset_handle = str_replace( '/', '-', $block_name ) .
|
||||
'-' . $field_mappings[ $field_name ];
|
||||
@@ -122,6 +127,62 @@ function get_block_asset_url( $path ) {
|
||||
return plugins_url( basename( $path ), $path );
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a script module ID for the selected block metadata field. It detects
|
||||
* when a path to file was provided and optionally finds a corresponding asset
|
||||
* file with details necessary to register the script module under with an
|
||||
* automatically generated module ID. It returns unprocessed script module
|
||||
* ID otherwise.
|
||||
*
|
||||
* @since 6.5.0
|
||||
*
|
||||
* @param array $metadata Block metadata.
|
||||
* @param string $field_name Field name to pick from metadata.
|
||||
* @param int $index Optional. Index of the script module ID to register when multiple
|
||||
* items passed. Default 0.
|
||||
* @return string|false Script module ID or false on failure.
|
||||
*/
|
||||
function register_block_script_module_id( $metadata, $field_name, $index = 0 ) {
|
||||
if ( empty( $metadata[ $field_name ] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$module_id = $metadata[ $field_name ];
|
||||
if ( is_array( $module_id ) ) {
|
||||
if ( empty( $module_id[ $index ] ) ) {
|
||||
return false;
|
||||
}
|
||||
$module_id = $module_id[ $index ];
|
||||
}
|
||||
|
||||
$module_path = remove_block_asset_path_prefix( $module_id );
|
||||
if ( $module_id === $module_path ) {
|
||||
return $module_id;
|
||||
}
|
||||
|
||||
$path = dirname( $metadata['file'] );
|
||||
$module_asset_raw_path = $path . '/' . substr_replace( $module_path, '.asset.php', - strlen( '.js' ) );
|
||||
$module_id = generate_block_asset_handle( $metadata['name'], $field_name, $index );
|
||||
$module_asset_path = wp_normalize_path(
|
||||
realpath( $module_asset_raw_path )
|
||||
);
|
||||
|
||||
$module_path_norm = wp_normalize_path( realpath( $path . '/' . $module_path ) );
|
||||
$module_uri = get_block_asset_url( $module_path_norm );
|
||||
|
||||
$module_asset = ! empty( $module_asset_path ) ? require $module_asset_path : array();
|
||||
$module_dependencies = isset( $module_asset['dependencies'] ) ? $module_asset['dependencies'] : array();
|
||||
|
||||
wp_register_script_module(
|
||||
$module_id,
|
||||
$module_uri,
|
||||
$module_dependencies,
|
||||
isset( $module_asset['version'] ) ? $module_asset['version'] : false
|
||||
);
|
||||
|
||||
return $module_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a script handle for the selected block metadata field. It detects
|
||||
* when a path to file was provided and optionally finds a corresponding asset
|
||||
@@ -314,7 +375,7 @@ function get_block_metadata_i18n_schema() {
|
||||
* @since 6.1.0 Added support for `render` field.
|
||||
* @since 6.3.0 Added `selectors` field.
|
||||
* @since 6.4.0 Added support for `blockHooks` field.
|
||||
* @since 6.5.0 Added support for `allowedBlocks` and `viewStyle` fields.
|
||||
* @since 6.5.0 Added support for `allowedBlocks`, `viewScriptModule`, and `viewStyle` fields.
|
||||
*
|
||||
* @param string $file_or_folder Path to the JSON file with metadata definition for
|
||||
* the block or path to the folder where the `block.json` file is located.
|
||||
@@ -490,6 +551,40 @@ function register_block_type_from_metadata( $file_or_folder, $args = array() ) {
|
||||
}
|
||||
}
|
||||
|
||||
$module_fields = array(
|
||||
'viewScriptModule' => 'view_script_module_ids',
|
||||
);
|
||||
foreach ( $module_fields as $metadata_field_name => $settings_field_name ) {
|
||||
if ( ! empty( $settings[ $metadata_field_name ] ) ) {
|
||||
$metadata[ $metadata_field_name ] = $settings[ $metadata_field_name ];
|
||||
}
|
||||
if ( ! empty( $metadata[ $metadata_field_name ] ) ) {
|
||||
$modules = $metadata[ $metadata_field_name ];
|
||||
$processed_modules = array();
|
||||
if ( is_array( $modules ) ) {
|
||||
for ( $index = 0; $index < count( $modules ); $index++ ) {
|
||||
$result = register_block_script_module_id(
|
||||
$metadata,
|
||||
$metadata_field_name,
|
||||
$index
|
||||
);
|
||||
if ( $result ) {
|
||||
$processed_modules[] = $result;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = register_block_script_module_id(
|
||||
$metadata,
|
||||
$metadata_field_name
|
||||
);
|
||||
if ( $result ) {
|
||||
$processed_modules[] = $result;
|
||||
}
|
||||
}
|
||||
$settings[ $settings_field_name ] = $processed_modules;
|
||||
}
|
||||
}
|
||||
|
||||
$style_fields = array(
|
||||
'editorStyle' => 'editor_style_handles',
|
||||
'style' => 'style_handles',
|
||||
|
||||
@@ -226,6 +226,14 @@ class WP_Block_Type {
|
||||
*/
|
||||
public $view_script_handles = array();
|
||||
|
||||
/**
|
||||
* Block type front end only script module IDs.
|
||||
*
|
||||
* @since 6.5.0
|
||||
* @var string[]
|
||||
*/
|
||||
public $view_script_module_ids = array();
|
||||
|
||||
/**
|
||||
* Block type editor only style handles.
|
||||
*
|
||||
|
||||
@@ -470,6 +470,12 @@ class WP_Block {
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty( $this->block_type->view_script_module_ids ) ) {
|
||||
foreach ( $this->block_type->view_script_module_ids as $view_script_module_id ) {
|
||||
wp_enqueue_script_module( $view_script_module_id );
|
||||
}
|
||||
}
|
||||
|
||||
if ( ( ! empty( $this->block_type->style_handles ) ) ) {
|
||||
foreach ( $this->block_type->style_handles as $style_handle ) {
|
||||
wp_enqueue_style( $style_handle );
|
||||
|
||||
@@ -240,6 +240,7 @@ class WP_REST_Block_Types_Controller extends WP_REST_Controller {
|
||||
* @since 5.5.0
|
||||
* @since 5.9.0 Renamed `$block_type` to `$item` to match parent class for PHP 8 named parameter support.
|
||||
* @since 6.3.0 Added `selectors` field.
|
||||
* @since 6.5.0 Added `view_script_module_ids` field.
|
||||
*
|
||||
* @param WP_Block_Type $item Block type data.
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
@@ -291,6 +292,7 @@ class WP_REST_Block_Types_Controller extends WP_REST_Controller {
|
||||
'editor_script_handles',
|
||||
'script_handles',
|
||||
'view_script_handles',
|
||||
'view_script_module_ids',
|
||||
'editor_style_handles',
|
||||
'style_handles',
|
||||
'view_style_handles',
|
||||
@@ -584,6 +586,16 @@ class WP_REST_Block_Types_Controller extends WP_REST_Controller {
|
||||
'context' => array( 'embed', 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'view_script_module_ids' => array(
|
||||
'description' => __( 'Public facing script module IDs.' ),
|
||||
'type' => array( 'array' ),
|
||||
'default' => array(),
|
||||
'items' => array(
|
||||
'type' => 'string',
|
||||
),
|
||||
'context' => array( 'embed', 'view', 'edit' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'editor_style_handles' => array(
|
||||
'description' => __( 'Editor style handles.' ),
|
||||
'type' => array( 'array' ),
|
||||
|
||||
@@ -68,6 +68,7 @@
|
||||
"editorScript": "tests-notice-editor-script",
|
||||
"script": "tests-notice-script",
|
||||
"viewScript": [ "tests-notice-view-script", "tests-notice-view-script-2" ],
|
||||
"viewScriptModule": [ "tests-notice-view-script-module", "tests-notice-view-script-module-2" ],
|
||||
"editorStyle": "tests-notice-editor-style",
|
||||
"style": [ "tests-notice-style", "tests-notice-style-2" ],
|
||||
"viewStyle": [ "tests-notice-view-style" ],
|
||||
|
||||
@@ -138,6 +138,7 @@ class Tests_Blocks_Register extends WP_UnitTestCase {
|
||||
|
||||
/**
|
||||
* @ticket 50263
|
||||
* @ticket 60233
|
||||
*/
|
||||
public function test_generate_block_asset_handle() {
|
||||
$block_name = 'unit-tests/my-block';
|
||||
@@ -154,6 +155,18 @@ class Tests_Blocks_Register extends WP_UnitTestCase {
|
||||
'unit-tests-my-block-view-script-100',
|
||||
generate_block_asset_handle( $block_name, 'viewScript', 99 )
|
||||
);
|
||||
$this->assertSame(
|
||||
'unit-tests-my-block-view-script-module',
|
||||
generate_block_asset_handle( $block_name, 'viewScriptModule' )
|
||||
);
|
||||
$this->assertSame(
|
||||
'unit-tests-my-block-view-script-module-2',
|
||||
generate_block_asset_handle( $block_name, 'viewScriptModule', 1 )
|
||||
);
|
||||
$this->assertSame(
|
||||
'unit-tests-my-block-view-script-module-100',
|
||||
generate_block_asset_handle( $block_name, 'viewScriptModule', 99 )
|
||||
);
|
||||
$this->assertSame(
|
||||
'unit-tests-my-block-editor-style-2',
|
||||
generate_block_asset_handle( $block_name, 'editorStyle', 1 )
|
||||
@@ -198,6 +211,52 @@ class Tests_Blocks_Register extends WP_UnitTestCase {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 60233
|
||||
*/
|
||||
public function test_generate_block_asset_handle_core_block_module() {
|
||||
$block_name = 'core/paragraph';
|
||||
|
||||
$this->assertSame(
|
||||
'wp-block-paragraph-editor-script-module',
|
||||
generate_block_asset_handle( $block_name, 'editorScriptModule' )
|
||||
);
|
||||
$this->assertSame(
|
||||
'wp-block-paragraph-editor-script-module-2',
|
||||
generate_block_asset_handle( $block_name, 'editorScriptModule', 1 )
|
||||
);
|
||||
$this->assertSame(
|
||||
'wp-block-paragraph-editor-script-module-100',
|
||||
generate_block_asset_handle( $block_name, 'editorScriptModule', 99 )
|
||||
);
|
||||
|
||||
$this->assertSame(
|
||||
'wp-block-paragraph-view-script-module',
|
||||
generate_block_asset_handle( $block_name, 'viewScriptModule' )
|
||||
);
|
||||
$this->assertSame(
|
||||
'wp-block-paragraph-view-script-module-2',
|
||||
generate_block_asset_handle( $block_name, 'viewScriptModule', 1 )
|
||||
);
|
||||
$this->assertSame(
|
||||
'wp-block-paragraph-view-script-module-100',
|
||||
generate_block_asset_handle( $block_name, 'viewScriptModule', 99 )
|
||||
);
|
||||
|
||||
$this->assertSame(
|
||||
'wp-block-paragraph-script-module',
|
||||
generate_block_asset_handle( $block_name, 'scriptModule' )
|
||||
);
|
||||
$this->assertSame(
|
||||
'wp-block-paragraph-script-module-2',
|
||||
generate_block_asset_handle( $block_name, 'scriptModule', 1 )
|
||||
);
|
||||
$this->assertSame(
|
||||
'wp-block-paragraph-script-module-100',
|
||||
generate_block_asset_handle( $block_name, 'scriptModule', 99 )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 50263
|
||||
*/
|
||||
@@ -231,6 +290,115 @@ class Tests_Blocks_Register extends WP_UnitTestCase {
|
||||
$this->assertFalse( $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 60233
|
||||
*/
|
||||
public function test_field_not_found_register_block_script_module_id() {
|
||||
$result = register_block_script_module_id( array(), 'viewScriptModule' );
|
||||
|
||||
$this->assertFalse( $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 60233
|
||||
*/
|
||||
public function test_empty_string_value_do_not_register_block_script_module_id() {
|
||||
$metadata = array( 'viewScriptModule' => '' );
|
||||
$result = register_block_script_module_id( $metadata, 'viewScriptModule' );
|
||||
|
||||
$this->assertFalse( $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 60233
|
||||
*/
|
||||
public function test_empty_array_value_do_not_register_block_script_module_id() {
|
||||
$metadata = array( 'viewScriptModule' => array() );
|
||||
$result = register_block_script_module_id( $metadata, 'viewScriptModule' );
|
||||
|
||||
$this->assertFalse( $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 60233
|
||||
*/
|
||||
public function test_wrong_array_index_do_not_register_block_script_module_id() {
|
||||
$metadata = array( 'viewScriptModule' => array( 'test-module_id' ) );
|
||||
$result = register_block_script_module_id( $metadata, 'script', 1 );
|
||||
|
||||
$this->assertFalse( $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 60233
|
||||
*/
|
||||
public function test_missing_asset_file_register_block_script_module_id() {
|
||||
$metadata = array(
|
||||
'file' => __FILE__,
|
||||
'name' => 'unit-tests/test-block',
|
||||
'viewScriptModule' => 'file:./blocks/notice/missing-asset.js',
|
||||
);
|
||||
$result = register_block_script_module_id( $metadata, 'viewScriptModule' );
|
||||
|
||||
$this->assertSame( 'unit-tests-test-block-view-script-module', $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 60233
|
||||
*/
|
||||
public function test_handle_passed_register_block_script_module_id() {
|
||||
$metadata = array(
|
||||
'viewScriptModule' => 'test-script-module-id',
|
||||
);
|
||||
$result = register_block_script_module_id( $metadata, 'viewScriptModule' );
|
||||
|
||||
$this->assertSame( 'test-script-module-id', $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 60233
|
||||
*/
|
||||
public function test_handles_passed_register_block_script_module_ids() {
|
||||
$metadata = array(
|
||||
'viewScriptModule' => array( 'test-id', 'test-id-other' ),
|
||||
);
|
||||
|
||||
$result = register_block_script_module_id( $metadata, 'viewScriptModule' );
|
||||
$this->assertSame( 'test-id', $result );
|
||||
|
||||
$result = register_block_script_module_id( $metadata, 'viewScriptModule', 1 );
|
||||
$this->assertSame( 'test-id-other', $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 60233
|
||||
*/
|
||||
public function test_success_register_block_script_module_id() {
|
||||
$metadata = array(
|
||||
'file' => DIR_TESTDATA . '/blocks/notice/block.json',
|
||||
'name' => 'unit-tests/test-block',
|
||||
'viewScriptModule' => 'file:./block.js',
|
||||
);
|
||||
$result = register_block_script_module_id( $metadata, 'viewScriptModule' );
|
||||
|
||||
$this->assertSame( 'unit-tests-test-block-view-script-module', $result );
|
||||
|
||||
// Test the behavior directly within the unit test
|
||||
$this->assertFalse(
|
||||
strpos(
|
||||
wp_normalize_path( realpath( dirname( $metadata['file'] ) . '/' . $metadata['viewScriptModule'] ) ),
|
||||
trailingslashit( wp_normalize_path( get_template_directory() ) )
|
||||
) === 0
|
||||
);
|
||||
|
||||
$this->assertFalse(
|
||||
strpos(
|
||||
wp_normalize_path( realpath( dirname( $metadata['file'] ) . '/' . $metadata['viewScriptModule'] ) ),
|
||||
trailingslashit( wp_normalize_path( get_stylesheet_directory() ) )
|
||||
) === 0
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 50263
|
||||
*/
|
||||
@@ -245,14 +413,14 @@ class Tests_Blocks_Register extends WP_UnitTestCase {
|
||||
|
||||
public function test_handles_passed_register_block_script_handles() {
|
||||
$metadata = array(
|
||||
'script' => array( 'test-script-handle', 'test-script-handle-2' ),
|
||||
'script' => array( 'test-script-handle', 'test-script-handle-other' ),
|
||||
);
|
||||
|
||||
$result = register_block_script_handle( $metadata, 'script' );
|
||||
$this->assertSame( 'test-script-handle', $result );
|
||||
|
||||
$result = register_block_script_handle( $metadata, 'script', 1 );
|
||||
$this->assertSame( 'test-script-handle-2', $result, 1 );
|
||||
$this->assertSame( 'test-script-handle-other', $result );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -751,6 +919,7 @@ class Tests_Blocks_Register extends WP_UnitTestCase {
|
||||
* @ticket 50328
|
||||
* @ticket 57585
|
||||
* @ticket 59797
|
||||
* @ticket 60233
|
||||
*/
|
||||
public function test_block_registers_with_metadata_fixture() {
|
||||
$result = register_block_type_from_metadata(
|
||||
@@ -853,6 +1022,10 @@ class Tests_Blocks_Register extends WP_UnitTestCase {
|
||||
array( 'tests-notice-view-script', 'tests-notice-view-script-2' ),
|
||||
$result->view_script_handles
|
||||
);
|
||||
$this->assertSameSets(
|
||||
array( 'tests-notice-view-script-module', 'tests-notice-view-script-module-2' ),
|
||||
$result->view_script_module_ids
|
||||
);
|
||||
$this->assertSameSets(
|
||||
array( 'tests-notice-editor-style' ),
|
||||
$result->editor_style_handles
|
||||
|
||||
@@ -261,6 +261,7 @@ class REST_Block_Type_Controller_Test extends WP_Test_REST_Controller_Testcase {
|
||||
$this->assertSameSets( array(), $data['editor_script_handles'] );
|
||||
$this->assertSameSets( array(), $data['script_handles'] );
|
||||
$this->assertSameSets( array(), $data['view_script_handles'] );
|
||||
$this->assertSameSets( array(), $data['view_script_module_ids'] );
|
||||
$this->assertSameSets( array(), $data['editor_style_handles'] );
|
||||
$this->assertSameSets( array(), $data['style_handles'] );
|
||||
$this->assertFalse( $data['is_dynamic'] );
|
||||
@@ -339,6 +340,7 @@ class REST_Block_Type_Controller_Test extends WP_Test_REST_Controller_Testcase {
|
||||
$this->assertSameSets( array(), $data['editor_script_handles'] );
|
||||
$this->assertSameSets( array(), $data['script_handles'] );
|
||||
$this->assertSameSets( array(), $data['view_script_handles'] );
|
||||
$this->assertSameSets( array(), $data['view_script_module_ids'] );
|
||||
$this->assertSameSets( array(), $data['editor_style_handles'] );
|
||||
$this->assertSameSets( array(), $data['style_handles'] );
|
||||
$this->assertFalse( $data['is_dynamic'] );
|
||||
@@ -562,7 +564,7 @@ class REST_Block_Type_Controller_Test extends WP_Test_REST_Controller_Testcase {
|
||||
$response = rest_get_server()->dispatch( $request );
|
||||
$data = $response->get_data();
|
||||
$properties = $data['schema']['properties'];
|
||||
$this->assertCount( 32, $properties );
|
||||
$this->assertCount( 33, $properties );
|
||||
$this->assertArrayHasKey( 'api_version', $properties );
|
||||
$this->assertArrayHasKey( 'name', $properties );
|
||||
$this->assertArrayHasKey( 'title', $properties );
|
||||
@@ -586,6 +588,7 @@ class REST_Block_Type_Controller_Test extends WP_Test_REST_Controller_Testcase {
|
||||
$this->assertArrayHasKey( 'editor_script_handles', $properties );
|
||||
$this->assertArrayHasKey( 'script_handles', $properties );
|
||||
$this->assertArrayHasKey( 'view_script_handles', $properties );
|
||||
$this->assertArrayHasKey( 'view_script_module_ids', $properties );
|
||||
$this->assertArrayHasKey( 'editor_style_handles', $properties );
|
||||
$this->assertArrayHasKey( 'style_handles', $properties );
|
||||
$this->assertArrayHasKey( 'view_style_handles', $properties, 'schema must contain view_style_handles' );
|
||||
@@ -718,6 +721,7 @@ class REST_Block_Type_Controller_Test extends WP_Test_REST_Controller_Testcase {
|
||||
'editor_script_handles',
|
||||
'script_handles',
|
||||
'view_script_handles',
|
||||
'view_script_module_ids',
|
||||
'editor_style_handles',
|
||||
'style_handles',
|
||||
// Deprecated fields.
|
||||
|
||||
Reference in New Issue
Block a user