From 45c0f2043a7d065849882d27ebc04cb63660ff3d Mon Sep 17 00:00:00 2001 From: tellthemachines Date: Fri, 1 Apr 2022 16:09:44 +1100 Subject: [PATCH] Root vars shouldn't apply to block global styles --- .../class-wp-theme-json-gutenberg.php | 149 ++++++++++++++---- .../src/components/block-list/style.scss | 4 +- packages/blocks/src/api/constants.js | 8 +- .../global-styles/use-global-styles-output.js | 7 +- 4 files changed, 125 insertions(+), 43 deletions(-) diff --git a/lib/compat/wordpress-6.0/class-wp-theme-json-gutenberg.php b/lib/compat/wordpress-6.0/class-wp-theme-json-gutenberg.php index 926fda391aa4a..e7dab6cef9885 100644 --- a/lib/compat/wordpress-6.0/class-wp-theme-json-gutenberg.php +++ b/lib/compat/wordpress-6.0/class-wp-theme-json-gutenberg.php @@ -23,37 +23,41 @@ class WP_Theme_JSON_Gutenberg extends WP_Theme_JSON_5_9 { * path to the value in theme.json & block attributes. */ const PROPERTIES_METADATA = array( - 'background' => array( 'color', 'gradient' ), - 'background-color' => array( 'color', 'background' ), - 'border-radius' => array( 'border', 'radius' ), - 'border-top-left-radius' => array( 'border', 'radius', 'topLeft' ), - 'border-top-right-radius' => array( 'border', 'radius', 'topRight' ), - 'border-bottom-left-radius' => array( 'border', 'radius', 'bottomLeft' ), - 'border-bottom-right-radius' => array( 'border', 'radius', 'bottomRight' ), - 'border-color' => array( 'border', 'color' ), - 'border-width' => array( 'border', 'width' ), - 'border-style' => array( 'border', 'style' ), - 'color' => array( 'color', 'text' ), - 'font-family' => array( 'typography', 'fontFamily' ), - 'font-size' => array( 'typography', 'fontSize' ), - 'font-style' => array( 'typography', 'fontStyle' ), - 'font-weight' => array( 'typography', 'fontWeight' ), - 'letter-spacing' => array( 'typography', 'letterSpacing' ), - 'line-height' => array( 'typography', 'lineHeight' ), - 'margin' => array( 'spacing', 'margin' ), - 'margin-top' => array( 'spacing', 'margin', 'top' ), - 'margin-right' => array( 'spacing', 'margin', 'right' ), - 'margin-bottom' => array( 'spacing', 'margin', 'bottom' ), - 'margin-left' => array( 'spacing', 'margin', 'left' ), - 'padding' => array( 'spacing', 'padding' ), - '--wp--style--padding-top' => array( 'spacing', 'padding', 'top' ), - '--wp--style--padding-right' => array( 'spacing', 'padding', 'right' ), - '--wp--style--padding-bottom' => array( 'spacing', 'padding', 'bottom' ), - '--wp--style--padding-left' => array( 'spacing', 'padding', 'left' ), - '--wp--style--block-gap' => array( 'spacing', 'blockGap' ), - 'text-decoration' => array( 'typography', 'textDecoration' ), - 'text-transform' => array( 'typography', 'textTransform' ), - 'filter' => array( 'filter', 'duotone' ), + 'background' => array( 'color', 'gradient' ), + 'background-color' => array( 'color', 'background' ), + 'border-radius' => array( 'border', 'radius' ), + 'border-top-left-radius' => array( 'border', 'radius', 'topLeft' ), + 'border-top-right-radius' => array( 'border', 'radius', 'topRight' ), + 'border-bottom-left-radius' => array( 'border', 'radius', 'bottomLeft' ), + 'border-bottom-right-radius' => array( 'border', 'radius', 'bottomRight' ), + 'border-color' => array( 'border', 'color' ), + 'border-width' => array( 'border', 'width' ), + 'border-style' => array( 'border', 'style' ), + 'color' => array( 'color', 'text' ), + 'font-family' => array( 'typography', 'fontFamily' ), + 'font-size' => array( 'typography', 'fontSize' ), + 'font-style' => array( 'typography', 'fontStyle' ), + 'font-weight' => array( 'typography', 'fontWeight' ), + 'letter-spacing' => array( 'typography', 'letterSpacing' ), + 'line-height' => array( 'typography', 'lineHeight' ), + 'margin' => array( 'spacing', 'margin' ), + 'margin-top' => array( 'spacing', 'margin', 'top' ), + 'margin-right' => array( 'spacing', 'margin', 'right' ), + 'margin-bottom' => array( 'spacing', 'margin', 'bottom' ), + 'margin-left' => array( 'spacing', 'margin', 'left' ), + 'padding' => array( 'spacing', 'padding' ), + 'padding-top' => array( 'spacing', 'padding', 'top' ), + 'padding-right' => array( 'spacing', 'padding', 'right' ), + 'padding-bottom' => array( 'spacing', 'padding', 'bottom' ), + 'padding-left' => array( 'spacing', 'padding', 'left' ), + '--wp--style--root--padding-top' => array( 'spacing', 'padding', 'top' ), + '--wp--style--root--padding-right' => array( 'spacing', 'padding', 'right' ), + '--wp--style--root--padding-bottom' => array( 'spacing', 'padding', 'bottom' ), + '--wp--style--root--padding-left' => array( 'spacing', 'padding', 'left' ), + '--wp--style--block-gap' => array( 'spacing', 'blockGap' ), + 'text-decoration' => array( 'typography', 'textDecoration' ), + 'text-transform' => array( 'typography', 'textTransform' ), + 'filter' => array( 'filter', 'duotone' ), ); /** @@ -110,7 +114,7 @@ protected function get_block_classes( $style_nodes ) { $node = _wp_array_get( $this->theme_json, $metadata['path'], array() ); $selector = $metadata['selector']; $settings = _wp_array_get( $this->theme_json, array( 'settings' ) ); - $declarations = static::compute_style_properties( $node, $settings ); + $declarations = static::compute_style_properties( $node, $settings, null, $selector ); // 1. Separate the ones who use the general selector // and the ones who use the duotone selector. @@ -144,9 +148,9 @@ protected function get_block_classes( $style_nodes ) { } if ( static::ROOT_BLOCK_SELECTOR === $selector ) { - $block_rules .= '.wp-site-blocks { padding-top: var(--wp--style--padding-top); padding-bottom: var(--wp--style--padding-bottom); }'; - $block_rules .= '.wp-site-blocks > * { padding-right: var(--wp--style--padding-right); padding-left: var(--wp--style--padding-left); }'; - $block_rules .= '.wp-site-blocks > * > .alignfull { margin-right: calc(var(--wp--style--padding-right) * -1); margin-left: calc(var(--wp--style--padding-left) * -1); }'; + $block_rules .= '.wp-site-blocks { padding-top: var(--wp--style--root--padding-top); padding-bottom: var(--wp--style--root--padding-bottom); }'; + $block_rules .= '.wp-site-blocks > * { padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); }'; + $block_rules .= '.wp-site-blocks > * > .alignfull { margin-right: calc(var(--wp--style--root--padding-right) * -1); margin-left: calc(var(--wp--style--root--padding-left) * -1); }'; $block_rules .= '.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }'; $block_rules .= '.wp-site-blocks > .alignright { float: right; margin-left: 2em; }'; $block_rules .= '.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }'; @@ -162,6 +166,81 @@ protected function get_block_classes( $style_nodes ) { return $block_rules; } + /** + * Given a styles array, it extracts the style properties + * and adds them to the $declarations array following the format: + * + * ```php + * array( + * 'name' => 'property_name', + * 'value' => 'property_value, + * ) + * ``` + * + * @param array $styles Styles to process. + * @param array $settings Theme settings. + * @param array $properties Properties metadata. + * @param string $selector Selector for styles. + * @return array Returns the modified $declarations. + */ + protected static function compute_style_properties( $styles, $settings = array(), $properties = null, $selector = null ) { + if ( null === $properties ) { + $properties = static::PROPERTIES_METADATA; + } + + $declarations = array(); + $root_variable_duplicates = array(); + + if ( empty( $styles ) ) { + return $declarations; + } + + foreach ( $properties as $css_property => $value_path ) { + $value = static::get_property_value( $styles, $value_path ); + + if ( strpos( $css_property, '--wp--style--root--') === 0 && static::ROOT_BLOCK_SELECTOR !== $selector ) { + continue; + } + + if ( strpos( $css_property, '--wp--style--root--') === 0 ) { + $root_variable_duplicates[] = substr( $css_property, strlen('--wp--style--root--') ); + } + + // Look up protected properties, keyed by value path. + // Skip protected properties that are explicitly set to `null`. + if ( is_array( $value_path ) ) { + $path_string = implode( '.', $value_path ); + if ( + array_key_exists( $path_string, static::PROTECTED_PROPERTIES ) && + _wp_array_get( $settings, static::PROTECTED_PROPERTIES[ $path_string ], null ) === null + ) { + continue; + } + } + + // Skip if empty and not "0" or value represents array of longhand values. + $has_missing_value = empty( $value ) && ! is_numeric( $value ); + if ( $has_missing_value || is_array( $value ) ) { + continue; + } + + $declarations[] = array( + 'name' => $css_property, + 'value' => $value, + ); + } + + // If a variable value is added to the root, the corresponding property should be removed. + foreach ( $root_variable_duplicates as $duplicate ) { + $discard = array_search($duplicate,array_column($declarations, 'name')); + if ( $discard ) { + array_splice($declarations, $discard, 1); + } + } + + return $declarations; + } + /** * Returns a valid theme.json for a theme. * Essentially, it flattens the preset data. diff --git a/packages/block-editor/src/components/block-list/style.scss b/packages/block-editor/src/components/block-list/style.scss index 6827dbdf8d968..e0c9482700a25 100644 --- a/packages/block-editor/src/components/block-list/style.scss +++ b/packages/block-editor/src/components/block-list/style.scss @@ -320,8 +320,8 @@ } .is-root-container > .alignfull { - margin-right: calc(var(--wp--style--padding-right) * -1); - margin-left: calc(var(--wp--style--padding-left) * -1); + margin-right: calc(var(--wp--style--root--padding-right) * -1); + margin-left: calc(var(--wp--style--root--padding-left) * -1); } .wp-block[data-align="left"] > *, diff --git a/packages/blocks/src/api/constants.js b/packages/blocks/src/api/constants.js index f1bd0988a3e21..930ba60d6cbad 100644 --- a/packages/blocks/src/api/constants.js +++ b/packages/blocks/src/api/constants.js @@ -118,22 +118,22 @@ export const __EXPERIMENTAL_STYLE_PROPERTY = { value: [ 'spacing', 'blockGap' ], support: [ 'spacing', 'blockGap' ], }, - '--wp--style--padding-top': { + '--wp--style--root--padding-top': { value: [ 'spacing', 'padding', 'top' ], support: [ 'spacing', 'padding' ], rootOnly: true, }, - '--wp--style--padding-right': { + '--wp--style--root--padding-right': { value: [ 'spacing', 'padding', 'right' ], support: [ 'spacing', 'padding' ], rootOnly: true, }, - '--wp--style--padding-bottom': { + '--wp--style--root--padding-bottom': { value: [ 'spacing', 'padding', 'bottom' ], support: [ 'spacing', 'padding' ], rootOnly: true, }, - '--wp--style--padding-left': { + '--wp--style--root--padding-left': { value: [ 'spacing', 'padding', 'left' ], support: [ 'spacing', 'padding' ], rootOnly: true, diff --git a/packages/edit-site/src/components/global-styles/use-global-styles-output.js b/packages/edit-site/src/components/global-styles/use-global-styles-output.js index 9c517fb5d4557..05f51c7353dc1 100644 --- a/packages/edit-site/src/components/global-styles/use-global-styles-output.js +++ b/packages/edit-site/src/components/global-styles/use-global-styles-output.js @@ -150,7 +150,10 @@ function flattenTree( input = {}, prefix, token ) { function getStylesDeclarations( blockStyles = {}, isRoot = false ) { const output = reduce( STYLE_PROPERTY, - ( declarations, { value, properties, useEngine }, key ) => { + ( declarations, { value, properties, useEngine, rootOnly }, key ) => { + if ( rootOnly && ! isRoot ) { + return declarations; + } const pathToValue = value; if ( first( pathToValue ) === 'elements' || useEngine ) { return declarations; @@ -339,7 +342,7 @@ export const toStyles = ( tree, blockSelectors ) => { const nodesWithSettings = getNodesWithSettings( tree, blockSelectors ); let ruleset = - 'body { padding-right: 0; padding-left: 0; } .wp-site-blocks > * { margin-top: 0; margin-bottom: 0; padding-right: var(--wp--style--padding-right); padding-left: var(--wp--style--padding-left); }.wp-site-blocks > * + * { margin-top: var( --wp--style--block-gap ); }'; + 'body { padding-right: 0; padding-left: 0; } .wp-site-blocks > * { margin-top: 0; margin-bottom: 0; padding-right: var(--wp--style--root--padding-right); padding-left: var(--wp--style--root--padding-left); }.wp-site-blocks > * + * { margin-top: var( --wp--style--block-gap ); }'; nodesWithStyles.forEach( ( { selector, styles } ) => { const isRoot = ROOT_BLOCK_SELECTOR === selector; const declarations = getStylesDeclarations( styles, isRoot );