From f6f4fc98b21e1e1e79194be17ef08dd83924125e Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Fri, 13 May 2022 13:00:50 +0300 Subject: [PATCH] Define styledClasses in block.json and inline styles --- lib/blocks.php | 72 +++++++++++++++++++ .../block-library/src/paragraph/block.json | 11 ++- schemas/json/block.json | 4 ++ 3 files changed, 86 insertions(+), 1 deletion(-) diff --git a/lib/blocks.php b/lib/blocks.php index 3d673f07522c2d..852fbf2f3e2e7c 100644 --- a/lib/blocks.php +++ b/lib/blocks.php @@ -350,3 +350,75 @@ function gutenberg_register_legacy_social_link_blocks() { } add_action( 'init', '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 ) { + + // Bail early if `styledClasses` is not set. + if ( empty( $metadata['styledClasses'] ) ) { + return $settings; + } + + // Bail early if not a frontend request. + if ( is_admin() || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) { + return $settings; + } + + // Bail early if the block doesn't have a "style" defined. + if ( empty( $settings['style'] ) ) { + return $settings; + } + + // 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'] ); + } + + // Unset the default style's path to prevent inlining the whole file. + unset( $wp_styles->registered[ $handle ]->extra['path'] ); + + /** + * Callback to add the style-parts to the block. + * + * @param string $block_content Rendered block content. + * @param array $block Block object. + * @return string Filtered block content. + */ + $callback = static function( $block_content, $block ) use ( $handle, $block_path, $metadata ) { + // Check that we're on the right block. + if ( $block['blockName'] !== $metadata['name'] ) { + return $block_content; + } + + // 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; + } + wp_add_inline_style( $handle, file_get_contents( $block_path . "/style-part-{$class_name}.css" ) ); + } + return $block_content; + }; + + // Add the callback to the block's render callback. + add_filter( 'render_block', $callback, 10, 2 ); + + return $settings; + } +} +add_filter( 'block_type_metadata_settings', 'wp_maybe_inline_block_style_parts', 10, 2 ); diff --git a/packages/block-library/src/paragraph/block.json b/packages/block-library/src/paragraph/block.json index 2323beff7ae595..005522046a4022 100644 --- a/packages/block-library/src/paragraph/block.json +++ b/packages/block-library/src/paragraph/block.json @@ -55,5 +55,14 @@ "__unstablePasteTextInline": true }, "editorStyle": "wp-block-paragraph-editor", - "style": "wp-block-paragraph" + "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" + ] } diff --git a/schemas/json/block.json b/schemas/json/block.json index 17e9ec519acf64..12567a94941c6d 100644 --- a/schemas/json/block.json +++ b/schemas/json/block.json @@ -477,6 +477,10 @@ } } ] + }, + "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" } }, "required": [ "name", "title" ],