diff --git a/backport-changelog/6.6/6827.md b/backport-changelog/6.6/6827.md new file mode 100644 index 00000000000000..bfe177c4cac0e5 --- /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 diff --git a/lib/block-supports/block-style-variations.php b/lib/block-supports/block-style-variations.php index e078b50b19d5a3..fc12c87fdd2d40 100644 --- a/lib/block-supports/block-style-variations.php +++ b/lib/block-supports/block-style-variations.php @@ -133,8 +133,9 @@ function gutenberg_render_block_style_variation_support_styles( $parsed_block ) array( 'styles' ), array( 'custom' ), array( - 'skip_root_layout_styles' => true, - 'scope' => ".$class_name", + 'include_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 deb4d850d271fb..e3a3d1b1f256c3 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. @@ -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. + * - `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() ) { @@ -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: + * - `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() ) { + 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: + * - `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() ) { + 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['include_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 ), @@ -3323,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( '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 ) { $input = _wp_array_get( $theme_json, $metadata['path'], array() ); 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 b858a2e4140ea9..d3a22335e88433 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 68839ea15d775e..adeb021c078c59 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 311997d46f0ada..3ad8896e735616 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 ] ); diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index cb4d5458111c66..ebfaeeb3d188fd 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -5279,4 +5279,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( 'include_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 ); + } }