From b2772232ab31daa879cfc70c42b9356a64e456fa Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Fri, 20 May 2022 10:54:46 +0300 Subject: [PATCH] Refactor to use the "style" item in block.json --- lib/blocks.php | 109 ++++++++++++------ .../block-library/src/paragraph/block.json | 22 ++-- schemas/json/block.json | 30 +++-- 3 files changed, 106 insertions(+), 55 deletions(-) diff --git a/lib/blocks.php b/lib/blocks.php index 1ab13b25901730..98a369ad8da4ef 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -354,43 +354,40 @@ function gutenberg_register_legacy_social_link_blocks() { if ( ! function_exists( 'wp_maybe_inline_block_style_parts' ) ) { /** * Inlines tree-shaked CSS for blocks, instead of a single file. - * Filters the settings determined from the block type metadata. * - * @param array $settings Array of determined settings for registering a block type. * @param array $metadata Metadata provided for registering a block type. */ - function wp_maybe_inline_block_style_parts( $settings, $metadata ) { + function wp_maybe_inline_block_style_parts( $metadata ) { - // Bail early if wp_should_load_separate_core_block_assets() is false. - if ( ! wp_should_load_separate_core_block_assets() ) { - return $settings; + // Bail early if style is empty or not an array. + if ( ! isset( $metadata['style'] ) || ! is_array( $metadata['style'] ) ) { + return $metadata; } - // Bail early if `styledClasses` is not set. - if ( empty( $metadata['styledClasses'] ) ) { - return $settings; - } + // Compile an array of style-parts. + $styled_parts = array(); + foreach ( $metadata['style'] as $key => $style ) { + // Skip item if "parts" and "style" are not set, or empty. + if ( empty( $style['parts'] ) || empty( $style['handle'] ) ) { + continue; + } + + // Add the stylesheet to the array to be used below. + $styled_parts[ $style['handle'] ] = $style['parts']; - // Bail early if the block doesn't have a "style" defined. - if ( empty( $settings['style'] ) ) { - return $settings; + // Convert $metadata['style'] to an array removing the "parts" and "handle" keys. + $metadata['style'][ $key ] = $style['handle']; } - // Get the stylesheet handle. - $handle = $settings['style']; - - global $wp_styles; - // Remove the default style. We'll be adding style-parts depending on the block content. - $wp_styles->registered[ $handle ]->src = ''; - // Get the block's folder path which will be later used to get the individual files. - // Use the folder-path of the style.css file if available, otherwise fallback to the block.json parent folder. - $block_path = dirname( $metadata['file'] ); - if ( ! empty( $wp_styles->registered[ $handle ]->extra['path'] ) ) { - $block_path = dirname( $wp_styles->registered[ $handle ]->extra['path'] ); + // Bail early if wp_should_load_separate_core_block_assets() is false. + if ( ! wp_should_load_separate_core_block_assets() ) { + return $metadata; } - // Unset the default style's path to prevent inlining the whole file. - unset( $wp_styles->registered[ $handle ]->extra['path'] ); + // Bail early if there are no styled parts. + if ( empty( $styled_parts ) ) { + return $metadata; + } /** * Callback to add the style-parts to the block. @@ -399,30 +396,66 @@ function wp_maybe_inline_block_style_parts( $settings, $metadata ) { * @param array $block Block object. * @return string Filtered block content. */ - $callback = static function( $block_content, $block ) use ( $handle, $block_path, $metadata ) { + $callback = static function( $block_content, $block ) use ( $metadata, $styled_parts ) { // Check that we're on the right block. if ( $block['blockName'] !== $metadata['name'] ) { return $block_content; } + // Use a static variable to avoid adding the same part more than once. + static $style_parts_added = array(); + if ( ! isset( $style_parts_added[ $block['blockName'] ] ) ) { + $style_parts_added[ $block['blockName'] ] = array(); + } + // Add inline styles for the class-names that exist in the content. - foreach ( $metadata['styledClasses'] as $class_name ) { - if ( false === strpos( $block_content, $class_name ) ) { - continue; + foreach ( $styled_parts as $handle => $styled_parts ) { + + global $wp_styles; + // Remove the default style. We'll be adding style-parts depending on the block content. + $wp_styles->registered[ $handle ]->src = ''; + // Get the block's folder path which will be later used to get the individual files. + // Use the folder-path of the style.css file if available, otherwise fallback to the block.json parent folder. + $block_path = dirname( $metadata['file'] ); + if ( ! empty( $wp_styles->registered[ $handle ]->extra['path'] ) ) { + $block_path = dirname( $wp_styles->registered[ $handle ]->extra['path'] ); } - $file = $block_path . "/styles/{$class_name}.css"; - if ( is_rtl() && file_exists( $block_path . "/styles/{$class_name}-rtl.css" ) ) { - $file = $block_path . "/styles/{$class_name}-rtl.css"; + + // Unset the default style's path to prevent inlining the whole file. + unset( $wp_styles->registered[ $handle ]->extra['path'] ); + + // Add the style-parts to the block. + foreach ( $styled_parts as $part ) { + + // Make sure this part has not already been added. + if ( in_array( $part, $style_parts_added[ $block['blockName'] ], true ) ) { + continue; + } + + // Skip item if the block does not contain the defined string. + if ( false === strpos( $block_content, $part ) ) { + continue; + } + + $file = $block_path . "/styles/{$part}.css"; + if ( is_rtl() && file_exists( $block_path . "/styles/{$part}-rtl.css" ) ) { + $file = $block_path . "/styles/{$part}-rtl.css"; + } + wp_add_inline_style( $handle, file_get_contents( $file ) ); + + // Add the part to the array of added parts. + $style_parts_added[ $block['blockName'] ][] = $part; } - wp_add_inline_style( $handle, file_get_contents( $file ) ); } return $block_content; }; - - // Add the callback to the block's render callback. add_filter( 'render_block', $callback, 10, 2 ); - return $settings; + return $metadata; } } -add_filter( 'block_type_metadata_settings', 'wp_maybe_inline_block_style_parts', 10, 2 ); +/* + * Add the filter. Using a priority of 1 ensures that this filter runs before others, + * so the "style" metadata can be properly formatted for subsequent filters. + */ +add_filter( 'block_type_metadata', 'wp_maybe_inline_block_style_parts', 1, 2 ); diff --git a/packages/block-library/src/paragraph/block.json b/packages/block-library/src/paragraph/block.json index 005522046a4022..58898f65905a51 100644 --- a/packages/block-library/src/paragraph/block.json +++ b/packages/block-library/src/paragraph/block.json @@ -55,14 +55,18 @@ "__unstablePasteTextInline": true }, "editorStyle": "wp-block-paragraph-editor", - "style": "wp-block-paragraph", - "styledClasses": [ - "has-background", - "has-drop-cap", - "has-text-color", - "is-large-text", - "is-larger-text", - "is-regular-text", - "is-small-text" + "style": [ + { + "handle": "wp-block-paragraph", + "parts": [ + "has-background", + "has-drop-cap", + "has-text-color", + "is-large-text", + "is-larger-text", + "is-regular-text", + "is-small-text" + ] + } ] } diff --git a/schemas/json/block.json b/schemas/json/block.json index 5059829b82d0e1..8c6205c2bbd1a8 100644 --- a/schemas/json/block.json +++ b/schemas/json/block.json @@ -473,17 +473,31 @@ { "type": "array", "items": { - "type": "string" + "oneOf": [ + { + "type": "string" + }, + { + "type": "object", + "properties": { + "handle": { + "description": "The stylesheet handle.", + "type": "string" + }, + "parts": { + "description": "An array of class names that have individual stylesheets. If defined, overrides the 'handle' property on the frontend, loading styles only when the class is present.", + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ "handle", "parts" ] + } + ] } } ] - }, - "styledClasses": { - "description": "An array of class names that have individual stylesheets. If defined, overrides the 'style' property on the frontend, loading styles only when the class is present.", - "type": "array", - "items": { - "type": "string" - } } }, "required": [ "name", "title" ],