Skip to content

Commit

Permalink
Global Styles: Prevent duplicate block style variations CSS (WordPres…
Browse files Browse the repository at this point in the history
…s#62465)

Co-authored-by: aaronrobertshaw <[email protected]>
Co-authored-by: oandregal <[email protected]>
Co-authored-by: colorful-tones <[email protected]>
  • Loading branch information
4 people authored and huubl committed Jun 17, 2024
1 parent 9067221 commit f647b07
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 15 deletions.
3 changes: 3 additions & 0 deletions backport-changelog/6.6/6827.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
https://github.com/WordPress/wordpress-develop/pull/6827

* https://github.com/WordPress/gutenberg/pull/62465
5 changes: 3 additions & 2 deletions lib/block-supports/block-style-variations.php
Original file line number Diff line number Diff line change
Expand Up @@ -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",
)
);

Expand Down
23 changes: 16 additions & 7 deletions lib/class-wp-theme-json-gutenberg.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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() ) {
Expand All @@ -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 );
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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'] ) ) {
Expand Down Expand Up @@ -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 ),
Expand Down Expand Up @@ -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() );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;}'
);
} );

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -881,6 +881,7 @@ export const toStyles = (
marginReset: true,
presets: true,
rootPadding: true,
variationStyles: false,
...styleOptions,
};
const nodesWithStyles = getNodesWithStyles( tree, blockSelectors );
Expand Down Expand Up @@ -1010,7 +1011,7 @@ export const toStyles = (
);
}

if ( styleVariationSelectors ) {
if ( options.variationStyles && styleVariationSelectors ) {
Object.entries( styleVariationSelectors ).forEach(
( [ styleVariationName, styleVariationSelector ] ) => {
const styleVariations =
Expand Down
5 changes: 3 additions & 2 deletions packages/block-editor/src/hooks/block-style-variation.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,22 +116,23 @@ function useBlockProps( { name, className, clientId } ) {
const hasBlockGapSupport = false;
const hasFallbackGapSupport = true;
const disableLayoutStyles = true;
const isTemplate = true;
const disableRootPadding = true;

return toStyles(
variationConfig,
blockSelectors,
hasBlockGapSupport,
hasFallbackGapSupport,
disableLayoutStyles,
isTemplate,
disableRootPadding,
{
blockGap: false,
blockStyles: true,
layoutStyles: false,
marginReset: false,
presets: false,
rootPadding: false,
variationStyles: true,
}
);
}, [ variation, settings, styles, getBlockStyles, clientId ] );
Expand Down
77 changes: 77 additions & 0 deletions phpunit/class-wp-theme-json-test.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
}
}

0 comments on commit f647b07

Please sign in to comment.