From 19603ad9f7e6f045479002e4d372d5b88d0debfd Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Tue, 11 Jun 2024 16:25:41 +1000 Subject: [PATCH 1/8] Global Styles: Prevent duplicate block style variations CSS --- lib/block-supports/block-style-variations.php | 1 + lib/class-wp-theme-json-gutenberg.php | 18 +++++++++++++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/lib/block-supports/block-style-variations.php b/lib/block-supports/block-style-variations.php index e078b50b19d5a..a1f08808c20c4 100644 --- a/lib/block-supports/block-style-variations.php +++ b/lib/block-supports/block-style-variations.php @@ -133,6 +133,7 @@ function gutenberg_render_block_style_variation_support_styles( $parsed_block ) array( 'styles' ), array( 'custom' ), array( + 'block_style_variations' => true, 'skip_root_layout_styles' => true, 'scope' => ".$class_name", ) diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index deb4d850d271f..358561c882ab9 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -1260,6 +1260,7 @@ public function get_settings() { * - 'scope' that makes sure all style are scoped to a given selector * - `root_selector` which overwrites and forces a given selector to be used on the root node * - `skip_root_layout_styles` which omits root layout styles from the generated stylesheet. + * - `block_style_variations` which includes CSS for block style variations. * @return string The resulting stylesheet. */ public function get_stylesheet( $types = array( 'variables', 'styles', 'presets' ), $origins = null, $options = array() ) { @@ -1280,7 +1281,7 @@ public function get_stylesheet( $types = array( 'variables', 'styles', 'presets' } $blocks_metadata = static::get_blocks_metadata(); - $style_nodes = static::get_style_nodes( $this->theme_json, $blocks_metadata ); + $style_nodes = static::get_style_nodes( $this->theme_json, $blocks_metadata, $options ); $setting_nodes = static::get_setting_nodes( $this->theme_json, $blocks_metadata ); $root_style_key = array_search( static::ROOT_BLOCK_SELECTOR, array_column( $style_nodes, 'selector' ), true ); @@ -2487,9 +2488,12 @@ protected static function get_setting_nodes( $theme_json, $selectors = array() ) * * @param array $theme_json The tree to extract style nodes from. * @param array $selectors List of selectors per block. + * @param array $options An array of options to facilitate filtering style node generation + * The options currently supported are: + * - `block_style_variations` which includes CSS for block style variations. * @return array An array of style nodes metadata. */ - protected static function get_style_nodes( $theme_json, $selectors = array() ) { + protected static function get_style_nodes( $theme_json, $selectors = array(), $options = array() ) { $nodes = array(); if ( ! isset( $theme_json['styles'] ) ) { return $nodes; @@ -2533,7 +2537,7 @@ protected static function get_style_nodes( $theme_json, $selectors = array() ) { return $nodes; } - $block_nodes = static::get_block_nodes( $theme_json, $selectors ); + $block_nodes = static::get_block_nodes( $theme_json, $selectors, $options ); foreach ( $block_nodes as $block_node ) { $nodes[] = $block_node; } @@ -2608,9 +2612,12 @@ private static function update_separator_declarations( $declarations ) { * * @param array $theme_json The theme.json converted to an array. * @param array $selectors Optional list of selectors per block. + * @param array $options An array of options to facilitate filtering node generation + * The options currently supported are: + * - `block_style_variations` which includes CSS for block style variations. * @return array The block nodes in theme.json. */ - private static function get_block_nodes( $theme_json, $selectors = array() ) { + private static function get_block_nodes( $theme_json, $selectors = array(), $options = array() ) { $selectors = empty( $selectors ) ? static::get_blocks_metadata() : $selectors; $nodes = array(); if ( ! isset( $theme_json['styles'] ) ) { @@ -2639,7 +2646,8 @@ private static function get_block_nodes( $theme_json, $selectors = array() ) { } $variation_selectors = array(); - if ( isset( $node['variations'] ) ) { + $include_variations = $options['block_style_variations'] ?? false; + if ( $include_variations && isset( $node['variations'] ) ) { foreach ( $node['variations'] as $variation => $node ) { $variation_selectors[] = array( 'path' => array( 'styles', 'blocks', $name, 'variations', $variation ), From becb2a2e914792f98fce1e1f450e27abd716956a Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Fri, 14 Jun 2024 19:24:33 +1000 Subject: [PATCH 2/8] Prevent redundant css in the editor --- .../test/use-global-styles-output.js | 41 +++++++++++++++++-- .../global-styles/use-global-styles-output.js | 3 +- .../src/hooks/block-style-variation.js | 5 ++- 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js index b858a2e4140ea..d3a22335e8843 100644 --- a/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js +++ b/packages/block-editor/src/components/global-styles/test/use-global-styles-output.js @@ -565,9 +565,44 @@ describe( 'global styles renderer', () => { }, }; - expect( toStyles( Object.freeze( tree ), blockSelectors ) ).toEqual( - ':where(body) {margin: 0;}.is-layout-flow > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-flow > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-flow > .aligncenter { margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-constrained > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-constrained > .aligncenter { margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)) { max-width: var(--wp--style--global--content-size); margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > .alignwide { max-width: var(--wp--style--global--wide-size); }body .is-layout-flex { display:flex; }.is-layout-flex { flex-wrap: wrap; align-items: center; }.is-layout-flex > :is(*, div) { margin: 0; }body .is-layout-grid { display:grid; }.is-layout-grid > :is(*, div) { margin: 0; }' + - ':root :where(.is-style-foo.wp-image.wp-image-spacing){padding-top: 2px;}:root :where(.is-style-foo.wp-image.wp-image-border-color){border-color: blue;}:root :where(.is-style-foo.wp-image){color: blue;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }' + const hasBlockGapSupport = false; + const hasFallbackGapSupport = true; + const disableLayoutStyles = true; + const disableRootPadding = true; + const styleOptions = { + blockGap: false, + blockStyles: true, + layoutStyles: false, + marginReset: false, + presets: false, + rootPadding: false, + }; + + // Confirm no variation styles by default. + const withoutVariations = toStyles( + Object.freeze( tree ), + blockSelectors, + hasBlockGapSupport, + hasFallbackGapSupport, + disableLayoutStyles, + disableRootPadding, + styleOptions + ); + expect( withoutVariations ).toEqual( '' ); + + // Includes variation styles when requested. + styleOptions.variationStyles = true; + const withVariations = toStyles( + Object.freeze( tree ), + blockSelectors, + hasBlockGapSupport, + hasFallbackGapSupport, + disableLayoutStyles, + disableRootPadding, + styleOptions + ); + expect( withVariations ).toEqual( + ':root :where(.is-style-foo.wp-image.wp-image-spacing){padding-top: 2px;}:root :where(.is-style-foo.wp-image.wp-image-border-color){border-color: blue;}:root :where(.is-style-foo.wp-image){color: blue;}' ); } ); diff --git a/packages/block-editor/src/components/global-styles/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/use-global-styles-output.js index 68839ea15d775..adeb021c078c5 100644 --- a/packages/block-editor/src/components/global-styles/use-global-styles-output.js +++ b/packages/block-editor/src/components/global-styles/use-global-styles-output.js @@ -881,6 +881,7 @@ export const toStyles = ( marginReset: true, presets: true, rootPadding: true, + variationStyles: false, ...styleOptions, }; const nodesWithStyles = getNodesWithStyles( tree, blockSelectors ); @@ -1010,7 +1011,7 @@ export const toStyles = ( ); } - if ( styleVariationSelectors ) { + if ( options.variationStyles && styleVariationSelectors ) { Object.entries( styleVariationSelectors ).forEach( ( [ styleVariationName, styleVariationSelector ] ) => { const styleVariations = diff --git a/packages/block-editor/src/hooks/block-style-variation.js b/packages/block-editor/src/hooks/block-style-variation.js index 311997d46f0ad..3ad8896e73561 100644 --- a/packages/block-editor/src/hooks/block-style-variation.js +++ b/packages/block-editor/src/hooks/block-style-variation.js @@ -116,7 +116,7 @@ function useBlockProps( { name, className, clientId } ) { const hasBlockGapSupport = false; const hasFallbackGapSupport = true; const disableLayoutStyles = true; - const isTemplate = true; + const disableRootPadding = true; return toStyles( variationConfig, @@ -124,7 +124,7 @@ function useBlockProps( { name, className, clientId } ) { hasBlockGapSupport, hasFallbackGapSupport, disableLayoutStyles, - isTemplate, + disableRootPadding, { blockGap: false, blockStyles: true, @@ -132,6 +132,7 @@ function useBlockProps( { name, className, clientId } ) { marginReset: false, presets: false, rootPadding: false, + variationStyles: true, } ); }, [ variation, settings, styles, getBlockStyles, clientId ] ); From 5200ea4ce229d19b2d204c3adcd2d09eecf11a64 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Fri, 14 Jun 2024 20:18:36 +1000 Subject: [PATCH 3/8] Allow variations data when processing insecure properties --- lib/class-wp-theme-json-gutenberg.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index 358561c882ab9..8878af8e60067 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -3331,7 +3331,8 @@ public static function remove_insecure_properties( $theme_json, $origin = 'theme $theme_json = static::sanitize( $theme_json, $valid_block_names, $valid_element_names, $valid_variations ); $blocks_metadata = static::get_blocks_metadata(); - $style_nodes = static::get_style_nodes( $theme_json, $blocks_metadata ); + $style_options = array( 'block_style_variations' => true ); // Allow variations data. + $style_nodes = static::get_style_nodes( $theme_json, $blocks_metadata, $style_options ); foreach ( $style_nodes as $metadata ) { $input = _wp_array_get( $theme_json, $metadata['path'], array() ); From 2645e69a2ddc7733ebcc626c7956c696e0a6387a Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Fri, 14 Jun 2024 20:44:10 +1000 Subject: [PATCH 4/8] Add unit tests --- phpunit/class-wp-theme-json-test.php | 77 ++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index 59dcf07c040b5..893b827597e12 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -5410,4 +5410,81 @@ public function test_scope_style_node_selectors() { $this->assertEquals( $expected, $actual ); } + + /** + * Block style variations styles aren't generated by default. This test covers + * the `get_block_nodes` does not include variations by default, preventing + * the inclusion of their styles. + */ + public function test_opt_out_of_block_style_variations_by_default() { + $theme_json = new ReflectionClass( 'WP_Theme_JSON_Gutenberg' ); + + $func = $theme_json->getMethod( 'get_block_nodes' ); + $func->setAccessible( true ); + + $theme_json = array( + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, + 'styles' => array( + 'blocks' => array( + 'core/button' => array( + 'variations' => array( + 'outline' => array( + 'color' => array( + 'background' => 'red', + ), + ), + ), + ), + ), + ), + ); + $selectors = array(); + + $block_nodes = $func->invoke( null, $theme_json, $selectors ); + $button_variations = $block_nodes[0]['variations'] ?? array(); + + $this->assertEquals( array(), $button_variations ); + } + + /** + * Block style variations styles aren't generated by default. This test ensures + * variations are included by `get_block_nodes` when requested. + */ + public function test_opt_in_to_block_style_variations() { + $theme_json = new ReflectionClass( 'WP_Theme_JSON_Gutenberg' ); + + $func = $theme_json->getMethod( 'get_block_nodes' ); + $func->setAccessible( true ); + + $theme_json = array( + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, + 'styles' => array( + 'blocks' => array( + 'core/button' => array( + 'variations' => array( + 'outline' => array( + 'color' => array( + 'background' => 'red', + ), + ), + ), + ), + ), + ), + ); + $selectors = array(); + $options = array( 'block_style_variations' => true ); + + $block_nodes = $func->invoke( null, $theme_json, $selectors, $options ); + $button_variations = $block_nodes[0]['variations'] ?? array(); + + $expected = array( + array( + 'path' => array( 'styles', 'blocks', 'core/button', 'variations', 'outline' ), + 'selector' => '.wp-block-button.is-style-outline .wp-block-button__link', + ), + ); + + $this->assertEquals( $expected, $button_variations ); + } } From abf755e29ba539c3fd93488bcc35e8e189942176 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Fri, 14 Jun 2024 22:27:48 +1000 Subject: [PATCH 5/8] Add backport changelog --- backport-changelog/6.6/6827.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 backport-changelog/6.6/6827.md diff --git a/backport-changelog/6.6/6827.md b/backport-changelog/6.6/6827.md new file mode 100644 index 0000000000000..bfe177c4cac0e --- /dev/null +++ b/backport-changelog/6.6/6827.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/6827 + +* https://github.com/WordPress/gutenberg/pull/62465 From a3be836563888c3a935daedccaf1af932e783f3c Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Mon, 17 Jun 2024 13:54:14 +1000 Subject: [PATCH 6/8] Tweak since comment --- lib/class-wp-theme-json-gutenberg.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index 8878af8e60067..361bffeed15be 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -1248,7 +1248,7 @@ public function get_settings() { * * @since 5.8.0 * @since 5.9.0 Removed the `$type` parameter`, added the `$types` and `$origins` parameters. - * @since 6.6.0 Added option to skip root layout styles. + * @since 6.6.0 Added option to skip root layout or block style variation styles. * * @param array $types Types of styles to load. Will load all by default. It accepts: * - `variables`: only the CSS Custom Properties for presets & custom ones. From aacb543f18d715c61cc4dbe055e9607b4ca35845 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Mon, 17 Jun 2024 15:54:53 +1000 Subject: [PATCH 7/8] Prefix block style variations option with clarifying verb --- lib/class-wp-theme-json-gutenberg.php | 10 +++++----- phpunit/class-wp-theme-json-test.php | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index 361bffeed15be..e3a3d1b1f256c 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -1260,7 +1260,7 @@ public function get_settings() { * - 'scope' that makes sure all style are scoped to a given selector * - `root_selector` which overwrites and forces a given selector to be used on the root node * - `skip_root_layout_styles` which omits root layout styles from the generated stylesheet. - * - `block_style_variations` which includes CSS for block style variations. + * - `include_block_style_variations` which includes CSS for block style variations. * @return string The resulting stylesheet. */ public function get_stylesheet( $types = array( 'variables', 'styles', 'presets' ), $origins = null, $options = array() ) { @@ -2490,7 +2490,7 @@ protected static function get_setting_nodes( $theme_json, $selectors = array() ) * @param array $selectors List of selectors per block. * @param array $options An array of options to facilitate filtering style node generation * The options currently supported are: - * - `block_style_variations` which includes CSS for block style variations. + * - `include_block_style_variations` which includes CSS for block style variations. * @return array An array of style nodes metadata. */ protected static function get_style_nodes( $theme_json, $selectors = array(), $options = array() ) { @@ -2614,7 +2614,7 @@ private static function update_separator_declarations( $declarations ) { * @param array $selectors Optional list of selectors per block. * @param array $options An array of options to facilitate filtering node generation * The options currently supported are: - * - `block_style_variations` which includes CSS for block style variations. + * - `include_block_style_variations` which includes CSS for block style variations. * @return array The block nodes in theme.json. */ private static function get_block_nodes( $theme_json, $selectors = array(), $options = array() ) { @@ -2646,7 +2646,7 @@ private static function get_block_nodes( $theme_json, $selectors = array(), $opt } $variation_selectors = array(); - $include_variations = $options['block_style_variations'] ?? false; + $include_variations = $options['include_block_style_variations'] ?? false; if ( $include_variations && isset( $node['variations'] ) ) { foreach ( $node['variations'] as $variation => $node ) { $variation_selectors[] = array( @@ -3331,7 +3331,7 @@ public static function remove_insecure_properties( $theme_json, $origin = 'theme $theme_json = static::sanitize( $theme_json, $valid_block_names, $valid_element_names, $valid_variations ); $blocks_metadata = static::get_blocks_metadata(); - $style_options = array( 'block_style_variations' => true ); // Allow variations data. + $style_options = array( 'include_block_style_variations' => true ); // Allow variations data. $style_nodes = static::get_style_nodes( $theme_json, $blocks_metadata, $style_options ); foreach ( $style_nodes as $metadata ) { diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index 893b827597e12..a69fe09b48eee 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -5473,7 +5473,7 @@ public function test_opt_in_to_block_style_variations() { ), ); $selectors = array(); - $options = array( 'block_style_variations' => true ); + $options = array( 'include_block_style_variations' => true ); $block_nodes = $func->invoke( null, $theme_json, $selectors, $options ); $button_variations = $block_nodes[0]['variations'] ?? array(); From 228a3a6ff4f2565ce699ea88a5b8306434de54dd Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Mon, 17 Jun 2024 16:08:26 +1000 Subject: [PATCH 8/8] Update block style variations option after rename --- lib/block-supports/block-style-variations.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/block-supports/block-style-variations.php b/lib/block-supports/block-style-variations.php index a1f08808c20c4..fc12c87fdd2d4 100644 --- a/lib/block-supports/block-style-variations.php +++ b/lib/block-supports/block-style-variations.php @@ -133,9 +133,9 @@ function gutenberg_render_block_style_variation_support_styles( $parsed_block ) array( 'styles' ), array( 'custom' ), array( - 'block_style_variations' => true, - 'skip_root_layout_styles' => true, - 'scope' => ".$class_name", + 'include_block_style_variations' => true, + 'skip_root_layout_styles' => true, + 'scope' => ".$class_name", ) );