diff --git a/lib/block-supports/border.php b/lib/block-supports/border.php index 9f9053cf970052..34c51eca868811 100644 --- a/lib/block-supports/border.php +++ b/lib/block-supports/border.php @@ -119,7 +119,7 @@ function gutenberg_apply_border_support( $block_type, $block_attributes ) { // Collect classes and styles. $attributes = array(); - $styles = gutenberg_style_engine_generate( array( 'border' => $border_block_styles ) ); + $styles = gutenberg_style_engine_generate( array( 'border' => $border_block_styles ), array( 'css_vars' => true ) ); if ( ! empty( $styles['classnames'] ) ) { $attributes['class'] = $styles['classnames']; diff --git a/lib/block-supports/spacing.php b/lib/block-supports/spacing.php index b20c7d4406f4fd..8366b9775b7488 100644 --- a/lib/block-supports/spacing.php +++ b/lib/block-supports/spacing.php @@ -58,7 +58,8 @@ function gutenberg_apply_spacing_support( $block_type, $block_attributes ) { $spacing_block_styles['padding'] = $has_padding_support && ! $skip_padding ? _wp_array_get( $block_styles, array( 'spacing', 'padding' ), null ) : null; $spacing_block_styles['margin'] = $has_margin_support && ! $skip_margin ? _wp_array_get( $block_styles, array( 'spacing', 'margin' ), null ) : null; $styles = gutenberg_style_engine_generate( - array( 'spacing' => $spacing_block_styles ) + array( 'spacing' => $spacing_block_styles ), + array( 'css_vars' => true ) ); if ( ! empty( $styles['css'] ) ) { diff --git a/packages/style-engine/class-wp-style-engine.php b/packages/style-engine/class-wp-style-engine.php index a1961241047213..dd235d96297971 100644 --- a/packages/style-engine/class-wp-style-engine.php +++ b/packages/style-engine/class-wp-style-engine.php @@ -51,7 +51,7 @@ class WP_Style_Engine { ), 'path' => array( 'color', 'text' ), 'css_vars' => array( - '--wp--preset--color--$slug' => 'color', + 'color' => '--wp--preset--color--$slug', ), 'classnames' => array( 'has-text-color' => true, @@ -148,6 +148,9 @@ class WP_Style_Engine { 'individual' => 'padding-%s', ), 'path' => array( 'spacing', 'padding' ), + 'css_vars' => array( + 'spacing' => '--wp--preset--spacing--$slug', + ), ), 'margin' => array( 'property_keys' => array( @@ -155,6 +158,9 @@ class WP_Style_Engine { 'individual' => 'margin-%s', ), 'path' => array( 'spacing', 'margin' ), + 'css_vars' => array( + 'spacing' => '--wp--preset--spacing--$slug', + ), ), ), 'typography' => array( @@ -246,6 +252,28 @@ protected static function get_slug_from_preset_value( $style_value, $property_ke return null; } + /** + * Generates a css var string, eg var(--wp--preset--color--background) from a preset string, eg. `var:preset|space|50`. + * + * @param string $style_value A single css preset value. + * @param array $css_vars The css var patterns used to generate the var string. + * + * @return string|null The css var, or null if no match for slug found. + */ + protected static function get_css_var_value( $style_value, $css_vars ) { + foreach ( $css_vars as $property_key => $css_var_pattern ) { + $slug = static::get_slug_from_preset_value( $style_value, $property_key ); + if ( $slug ) { + $var = strtr( + $css_var_pattern, + array( '$slug' => $slug ) + ); + return "var($var)"; + } + } + return null; + } + /** * Checks whether an incoming style value is valid. * @@ -317,7 +345,7 @@ protected static function get_css( $style_value, $style_definition, $should_retu isset( $style_definition['value_func'] ) && is_callable( $style_definition['value_func'] ) ) { - return call_user_func( $style_definition['value_func'], $style_value, $style_definition ); + return call_user_func( $style_definition['value_func'], $style_value, $style_definition, $should_return_css_vars ); } $style_properties = $style_definition['property_keys']; @@ -326,15 +354,9 @@ protected static function get_css( $style_value, $style_definition, $should_retu // Check if the value is a CSS preset and there's a corresponding css_var pattern in the style definition. if ( is_string( $style_value ) && strpos( $style_value, 'var:' ) !== false ) { if ( $should_return_css_vars && ! empty( $style_definition['css_vars'] ) ) { - foreach ( $style_definition['css_vars'] as $css_var_pattern => $property_key ) { - $slug = static::get_slug_from_preset_value( $style_value, $property_key ); - if ( $slug ) { - $css_var = strtr( - $css_var_pattern, - array( '$slug' => $slug ) - ); - $rules[ $style_properties['default'] ] = "var($css_var)"; - } + $css_var = static::get_css_var_value( $style_value, $style_definition['css_vars'] ); + if ( $css_var ) { + $rules[ $style_properties['default'] ] = $css_var; } } return $rules; @@ -345,8 +367,13 @@ protected static function get_css( $style_value, $style_definition, $should_retu // for styles such as margins and padding. if ( is_array( $style_value ) ) { foreach ( $style_value as $key => $value ) { - $individual_property = sprintf( $style_properties['individual'], _wp_to_kebab_case( $key ) ); - $rules[ $individual_property ] = $value; + if ( is_string( $value ) && strpos( $value, 'var:' ) !== false && $should_return_css_vars && ! empty( $style_definition['css_vars'] ) ) { + $value = static::get_css_var_value( $value, $style_definition['css_vars'] ); + } + $individual_property = sprintf( $style_properties['individual'], _wp_to_kebab_case( $key ) ); + if ( $value ) { + $rules[ $individual_property ] = $value; + } } } else { $rules[ $style_properties['default'] ] = $style_value; @@ -440,12 +467,13 @@ public function generate( $block_styles, $options ) { * "border-{top|right|bottom|left}-{color|width|style}: {value};" or, * "border-image-{outset|source|width|repeat|slice}: {value};" * - * @param array $style_value A single raw Gutenberg style attributes value for a CSS property. - * @param array $individual_property_definition A single style definition from BLOCK_STYLE_DEFINITIONS_METADATA. + * @param array $style_value A single raw Gutenberg style attributes value for a CSS property. + * @param array $individual_property_definition A single style definition from BLOCK_STYLE_DEFINITIONS_METADATA. + * @param boolean $should_return_css_vars Whether to try to build and return CSS var values. * * @return array The class name for the added style. */ - protected static function get_css_individual_property_rules( $style_value, $individual_property_definition ) { + protected static function get_css_individual_property_rules( $style_value, $individual_property_definition, $should_return_css_vars ) { $rules = array(); if ( ! is_array( $style_value ) || empty( $style_value ) || empty( $individual_property_definition['path'] ) ) { @@ -469,13 +497,8 @@ protected static function get_css_individual_property_rules( $style_value, $indi if ( $style_definition && isset( $style_definition['property_keys']['individual'] ) ) { // Set a CSS var if there is a valid preset value. - $slug = isset( $individual_property_definition['css_vars'][ $css_property ] ) ? static::get_slug_from_preset_value( $value, $css_property ) : null; - if ( $slug ) { - $css_var = strtr( - $individual_property_definition['css_vars'][ $css_property ], - array( '$slug' => $slug ) - ); - $value = "var($css_var)"; + if ( is_string( $value ) && strpos( $value, 'var:' ) !== false && $should_return_css_vars && ! empty( $individual_property_definition['css_vars'] ) ) { + $value = static::get_css_var_value( $value, $individual_property_definition['css_vars'] ); } $individual_css_property = sprintf( $style_definition['property_keys']['individual'], $individual_property_key ); $rules[ $individual_css_property ] = $value; diff --git a/packages/style-engine/phpunit/class-wp-style-engine-test.php b/packages/style-engine/phpunit/class-wp-style-engine-test.php index e8274e85425fa3..9ff42a75f7b449 100644 --- a/packages/style-engine/phpunit/class-wp-style-engine-test.php +++ b/packages/style-engine/phpunit/class-wp-style-engine-test.php @@ -246,6 +246,59 @@ public function data_generate_styles_fixtures() { ), ), + 'valid_spacing_single_preset_values' => array( + 'block_styles' => array( + 'spacing' => array( + 'margin' => 'var:preset|spacing|10', + 'padding' => 'var:preset|spacing|20', + ), + ), + 'options' => array( 'css_vars' => true ), + 'expected_output' => array( + 'css' => 'padding: var(--wp--preset--spacing--20); margin: var(--wp--preset--spacing--10);', + ), + ), + + 'valid_spacing_multi_preset_values' => array( + 'block_styles' => array( + 'spacing' => array( + 'margin' => array( + 'left' => 'var:preset|spacing|10', + 'right' => 'var:preset|spacing|20', + 'top' => '1rem', + 'bottom' => '1rem', + ), + 'padding' => array( + 'left' => 'var:preset|spacing|30', + 'right' => 'var:preset|spacing|40', + 'top' => '14px', + 'bottom' => '14px', + ), + ), + ), + 'options' => array( 'css_vars' => true ), + 'expected_output' => array( + 'css' => 'padding-left: var(--wp--preset--spacing--30); padding-right: var(--wp--preset--spacing--40); padding-top: 14px; padding-bottom: 14px; margin-left: var(--wp--preset--spacing--10); margin-right: var(--wp--preset--spacing--20); margin-top: 1rem; margin-bottom: 1rem;', + ), + ), + + 'invalid_spacing_multi_preset_values' => array( + 'block_styles' => array( + 'spacing' => array( + 'margin' => array( + 'left' => 'var:preset|spaceman|10', + 'right' => 'var:preset|spaceman|20', + 'top' => '1rem', + 'bottom' => '1rem', + ), + ), + ), + 'options' => array( 'css_vars' => true ), + 'expected_output' => array( + 'css' => 'margin-top: 1rem; margin-bottom: 1rem;', + ), + ), + 'invalid_classnames_options' => array( 'block_styles' => array( 'typography' => array( @@ -285,7 +338,7 @@ public function data_generate_styles_fixtures() { ), ), ), - 'options' => array(), + 'options' => array( 'css_vars' => true ), 'expected_output' => array( 'css' => 'border-top-color: #fe1; border-top-width: 1.5rem; border-top-style: dashed; border-right-color: #fe2; border-right-width: 1.4rem; border-right-style: solid; border-bottom-color: #fe3; border-bottom-width: 1.3rem; border-left-color: var(--wp--preset--color--swampy-yellow); border-left-width: 0.5rem; border-left-style: dotted;', ), @@ -315,7 +368,7 @@ public function data_generate_styles_fixtures() { ), ), ), - 'options' => array(), + 'options' => array( 'css_vars' => true ), 'expected_output' => array( 'css' => 'border-bottom-color: var(--wp--preset--color--terrible-lizard);', ),