diff --git a/lib/block-supports/border.php b/lib/block-supports/border.php index 9d8d97c690a7b8..c29bfd666efdc7 100644 --- a/lib/block-supports/border.php +++ b/lib/block-supports/border.php @@ -58,12 +58,21 @@ function gutenberg_apply_border_support( $block_type, $block_attributes ) { ) { $border_radius = $block_attributes['style']['border']['radius']; - // This check handles original unitless implementation. - if ( is_numeric( $border_radius ) ) { - $border_radius .= 'px'; + if ( is_array( $border_radius ) ) { + // We have individual border radius corner values. + foreach ( $border_radius as $key => $radius ) { + // Convert CamelCase corner name to kebab-case. + $corner = strtolower( preg_replace( '/(? $value ) { $styles[] = sprintf( 'padding-%s: %s;', $key, $value ); } + } elseif ( null !== $padding_value ) { + $styles[] = sprintf( 'padding: %s;', $padding_value ); } } if ( $has_margin_support ) { $margin_value = _wp_array_get( $block_attributes, array( 'style', 'spacing', 'margin' ), null ); - if ( null !== $margin_value ) { + + if ( is_array( $margin_value ) ) { foreach ( $margin_value as $key => $value ) { $styles[] = sprintf( 'margin-%s: %s;', $key, $value ); } + } elseif ( null !== $margin_value ) { + $styles[] = sprintf( 'margin: %s;', $margin_value ); } } diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index 7ac18b4cd2c9ee..2ca794bd2deeae 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -61,18 +61,8 @@ class WP_Theme_JSON_Gutenberg { 'text' => null, ), 'spacing' => array( - 'margin' => array( - 'top' => null, - 'right' => null, - 'bottom' => null, - 'left' => null, - ), - 'padding' => array( - 'bottom' => null, - 'left' => null, - 'right' => null, - 'top' => null, - ), + 'margin' => null, + 'padding' => null, ), 'typography' => array( 'fontFamily' => null, @@ -208,64 +198,39 @@ class WP_Theme_JSON_Gutenberg { /** * Metadata for style properties. * - * Each property declares: - * - * - 'value': path to the value in theme.json and block attributes. + * Each element is a direct mapping from the CSS property name to the + * path to the value in theme.json & block attributes. */ const PROPERTIES_METADATA = array( - 'background' => array( - 'value' => array( 'color', 'gradient' ), - ), - 'background-color' => array( - 'value' => array( 'color', 'background' ), - ), - 'border-radius' => array( - 'value' => array( 'border', 'radius' ), - ), - 'border-color' => array( - 'value' => array( 'border', 'color' ), - ), - 'border-width' => array( - 'value' => array( 'border', 'width' ), - ), - 'border-style' => array( - 'value' => array( 'border', 'style' ), - ), - 'color' => array( - 'value' => array( 'color', 'text' ), - ), - 'font-family' => array( - 'value' => array( 'typography', 'fontFamily' ), - ), - 'font-size' => array( - 'value' => array( 'typography', 'fontSize' ), - ), - 'font-style' => array( - 'value' => array( 'typography', 'fontStyle' ), - ), - 'font-weight' => array( - 'value' => array( 'typography', 'fontWeight' ), - ), - 'letter-spacing' => array( - 'value' => array( 'typography', 'letterSpacing' ), - ), - 'line-height' => array( - 'value' => array( 'typography', 'lineHeight' ), - ), - 'margin' => array( - 'value' => array( 'spacing', 'margin' ), - 'properties' => array( 'top', 'right', 'bottom', 'left' ), - ), - 'padding' => array( - 'value' => array( 'spacing', 'padding' ), - 'properties' => array( 'top', 'right', 'bottom', 'left' ), - ), - 'text-decoration' => array( - 'value' => array( 'typography', 'textDecoration' ), - ), - 'text-transform' => array( - 'value' => array( 'typography', 'textTransform' ), - ), + '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' ), + 'text-decoration' => array( 'typography', 'textDecoration' ), + 'text-transform' => array( 'typography', 'textTransform' ), ); const ELEMENTS = array( @@ -374,29 +339,6 @@ private static function sanitize( $input, $valid_block_names, $valid_element_nam return $output; } - /** - * Given a CSS property name, returns the property it belongs - * within the self::PROPERTIES_METADATA map. - * - * @param string $css_name The CSS property name. - * - * @return string The property name. - */ - private static function to_property( $css_name ) { - static $to_property; - if ( null === $to_property ) { - foreach ( self::PROPERTIES_METADATA as $key => $metadata ) { - $to_property[ $key ] = $key; - if ( self::has_properties( $metadata ) ) { - foreach ( $metadata['properties'] as $property ) { - $to_property[ $key . '-' . $property ] = $key; - } - } - } - } - return $to_property[ $css_name ]; - } - /** * Returns the metadata for each block. * @@ -556,7 +498,7 @@ private static function flatten_tree( $tree, $prefix = '', $token = '--' ) { private static function get_property_value( $styles, $path ) { $value = _wp_array_get( $styles, $path, '' ); - if ( '' === $value ) { + if ( '' === $value || is_array( $value ) ) { return $value; } @@ -576,21 +518,6 @@ private static function get_property_value( $styles, $path ) { return $value; } - /** - * Whether the metadata contains a key named properties. - * - * @param array $metadata Description of the style property. - * - * @return boolean True if properties exists, false otherwise. - */ - private static function has_properties( $metadata ) { - if ( array_key_exists( 'properties', $metadata ) ) { - return true; - } - - return false; - } - /** * Given a styles array, it extracts the style properties * and adds them to the $declarations array following the format: @@ -612,34 +539,16 @@ private static function compute_style_properties( $styles ) { return $declarations; } - $properties = array(); - foreach ( self::PROPERTIES_METADATA as $name => $metadata ) { - // Some properties can be shorthand properties, meaning that - // they contain multiple values instead of a single one. - // An example of this is the padding property. - if ( self::has_properties( $metadata ) ) { - foreach ( $metadata['properties'] as $property ) { - $properties[] = array( - 'name' => $name . '-' . $property, - 'value' => array_merge( $metadata['value'], array( $property ) ), - ); - } - } else { - $properties[] = array( - 'name' => $name, - 'value' => $metadata['value'], - ); - } - } + foreach ( self::PROPERTIES_METADATA as $css_property => $value_path ) { + $value = self::get_property_value( $styles, $value_path ); - foreach ( $properties as $prop ) { - $value = self::get_property_value( $styles, $prop['value'] ); - if ( empty( $value ) ) { + // Skip if empty or value represents array of longhand values. + if ( empty( $value ) || is_array( $value ) ) { continue; } $declarations[] = array( - 'name' => $prop['name'], + 'name' => $css_property, 'value' => $value, ); } @@ -1252,13 +1161,14 @@ private static function remove_insecure_styles( $input ) { foreach ( $declarations as $declaration ) { if ( self::is_safe_css_declaration( $declaration['name'], $declaration['value'] ) ) { - $property = self::to_property( $declaration['name'] ); - $path = self::PROPERTIES_METADATA[ $property ]['value']; - if ( self::has_properties( self::PROPERTIES_METADATA[ $property ] ) ) { - $declaration_divided = explode( '-', $declaration['name'] ); - $path[] = $declaration_divided[1]; + $path = self::PROPERTIES_METADATA[ $declaration['name'] ]; + + // Check the value isn't an array before adding so as to not + // double up shorthand and longhand styles. + $value = _wp_array_get( $input, $path, array() ); + if ( ! is_array( $value ) ) { + gutenberg_experimental_set( $output, $path, $value ); } - gutenberg_experimental_set( $output, $path, _wp_array_get( $input, $path, array() ) ); } } return $output; diff --git a/lib/compat.php b/lib/compat.php index 72f39e15a42983..917d22fe733704 100644 --- a/lib/compat.php +++ b/lib/compat.php @@ -182,6 +182,10 @@ function gutenberg_override_reusable_block_post_type_labels() { */ function gutenberg_safe_style_attrs( $attrs ) { $attrs[] = 'object-position'; + $attrs[] = 'border-top-left-radius'; + $attrs[] = 'border-top-right-radius'; + $attrs[] = 'border-bottom-right-radius'; + $attrs[] = 'border-bottom-left-radius'; return $attrs; } diff --git a/packages/block-editor/src/hooks/style.js b/packages/block-editor/src/hooks/style.js index f177ed5da8c9bc..8c5d6ce1872f97 100644 --- a/packages/block-editor/src/hooks/style.js +++ b/packages/block-editor/src/hooks/style.js @@ -2,12 +2,12 @@ * External dependencies */ import { - capitalize, first, forEach, get, has, isEmpty, + isString, kebabCase, map, omit, @@ -78,11 +78,18 @@ export function getInlineStyles( styles = {} ) { const subPaths = STYLE_PROPERTY[ propKey ].properties; // Ignore styles on elements because they are handled on the server. if ( has( styles, path ) && 'elements' !== first( path ) ) { - if ( !! subPaths ) { - subPaths.forEach( ( suffix ) => { - output[ - propKey + capitalize( suffix ) - ] = compileStyleValue( get( styles, [ ...path, suffix ] ) ); + // Checking if style value is a string allows for shorthand css + // option and backwards compatibility for border radius support. + const styleValue = get( styles, path ); + + if ( !! subPaths && ! isString( styleValue ) ) { + Object.entries( subPaths ).forEach( ( entry ) => { + const [ name, subPath ] = entry; + const value = get( styleValue, [ subPath ] ); + + if ( value ) { + output[ name ] = compileStyleValue( value ); + } } ); } else { output[ propKey ] = compileStyleValue( get( styles, path ) ); diff --git a/packages/block-editor/src/hooks/test/style.js b/packages/block-editor/src/hooks/test/style.js index 85adb56c802e19..706d9a93ed0ba4 100644 --- a/packages/block-editor/src/hooks/test/style.js +++ b/packages/block-editor/src/hooks/test/style.js @@ -41,4 +41,68 @@ describe( 'getInlineStyles', () => { paddingTop: '10px', } ); } ); + + it( 'should return individual border radius styles', () => { + expect( + getInlineStyles( { + border: { + radius: { + topLeft: '10px', + topRight: '0.5rem', + bottomLeft: '0.5em', + bottomRight: '1em', + }, + }, + } ) + ).toEqual( { + borderTopLeftRadius: '10px', + borderTopRightRadius: '0.5rem', + borderBottomLeftRadius: '0.5em', + borderBottomRightRadius: '1em', + } ); + } ); + + it( 'should support longhand spacing styles', () => { + expect( + getInlineStyles( { + spacing: { + margin: { + top: '10px', + right: '0.5rem', + bottom: '0.5em', + left: '1em', + }, + padding: { + top: '20px', + right: '25px', + bottom: '30px', + left: '35px', + }, + }, + } ) + ).toEqual( { + marginTop: '10px', + marginRight: '0.5rem', + marginBottom: '0.5em', + marginLeft: '1em', + paddingTop: '20px', + paddingRight: '25px', + paddingBottom: '30px', + paddingLeft: '35px', + } ); + } ); + + it( 'should support shorthand spacing styles', () => { + expect( + getInlineStyles( { + spacing: { + margin: '10px', + padding: '20px', + }, + } ) + ).toEqual( { + margin: '10px', + padding: '20px', + } ); + } ); } ); diff --git a/packages/blocks/src/api/constants.js b/packages/blocks/src/api/constants.js index 3a827f444974ea..13d97020aca924 100644 --- a/packages/blocks/src/api/constants.js +++ b/packages/blocks/src/api/constants.js @@ -33,6 +33,12 @@ export const __EXPERIMENTAL_STYLE_PROPERTY = { borderRadius: { value: [ 'border', 'radius' ], support: [ '__experimentalBorder', 'radius' ], + properties: { + borderTopLeftRadius: 'topLeft', + borderTopRightRadius: 'topRight', + borderBottomLeftRadius: 'bottomLeft', + borderBottomRightRadius: 'bottomRight', + }, }, borderStyle: { value: [ 'border', 'style' ], @@ -73,12 +79,22 @@ export const __EXPERIMENTAL_STYLE_PROPERTY = { margin: { value: [ 'spacing', 'margin' ], support: [ 'spacing', 'margin' ], - properties: [ 'top', 'right', 'bottom', 'left' ], + properties: { + marginTop: 'top', + marginRight: 'right', + marginBottom: 'bottom', + marginLeft: 'left', + }, }, padding: { value: [ 'spacing', 'padding' ], support: [ 'spacing', 'padding' ], - properties: [ 'top', 'right', 'bottom', 'left' ], + properties: { + paddingTop: 'top', + paddingRight: 'right', + paddingBottom: 'bottom', + paddingLeft: 'left', + }, }, textDecoration: { value: [ 'typography', 'textDecoration' ], diff --git a/packages/edit-site/src/components/editor/global-styles-renderer.js b/packages/edit-site/src/components/editor/global-styles-renderer.js index bdc46662fb62fc..38d3e06a12b6d9 100644 --- a/packages/edit-site/src/components/editor/global-styles-renderer.js +++ b/packages/edit-site/src/components/editor/global-styles-renderer.js @@ -2,11 +2,11 @@ * External dependencies */ import { - capitalize, first, forEach, get, isEmpty, + isString, kebabCase, pickBy, reduce, @@ -134,21 +134,23 @@ function getStylesDeclarations( blockStyles = {} ) { if ( first( pathToValue ) === 'elements' ) { return declarations; } - if ( !! properties ) { - properties.forEach( ( prop ) => { - if ( - ! get( blockStyles, [ ...pathToValue, prop ], false ) - ) { + + const styleValue = get( blockStyles, pathToValue ); + + if ( !! properties && ! isString( styleValue ) ) { + Object.entries( properties ).forEach( ( entry ) => { + const [ name, prop ] = entry; + + if ( ! get( styleValue, [ prop ], false ) ) { // Do not create a declaration // for sub-properties that don't have any value. return; } - const cssProperty = kebabCase( - `${ key }${ capitalize( prop ) }` - ); + + const cssProperty = kebabCase( name ); declarations.push( `${ cssProperty }: ${ compileStyleValue( - get( blockStyles, [ ...pathToValue, prop ] ) + get( styleValue, [ prop ] ) ) }` ); } ); diff --git a/packages/edit-site/src/components/editor/test/global-styles-renderer.js b/packages/edit-site/src/components/editor/test/global-styles-renderer.js index 56250ebf201bc3..2644ac724a8c18 100644 --- a/packages/edit-site/src/components/editor/test/global-styles-renderer.js +++ b/packages/edit-site/src/components/editor/test/global-styles-renderer.js @@ -293,6 +293,10 @@ describe( 'global styles renderer', () => { }, }, styles: { + spacing: { + margin: '10px', + padding: '10px', + }, color: { background: 'red', }, @@ -304,6 +308,22 @@ describe( 'global styles renderer', () => { }, }, blocks: { + 'core/group': { + spacing: { + margin: { + top: '10px', + right: '20px', + bottom: '30px', + left: '40px', + }, + padding: { + top: '11px', + right: '22px', + bottom: '33px', + left: '44px', + }, + }, + }, 'core/heading': { color: { text: 'orange', @@ -321,6 +341,9 @@ describe( 'global styles renderer', () => { }; const blockSelectors = { + 'core/group': { + selector: '.wp-block-group', + }, 'core/heading': { selector: 'h1,h2,h3,h4,h5,h6', elements: { @@ -342,7 +365,7 @@ describe( 'global styles renderer', () => { }; expect( toStyles( tree, blockSelectors ) ).toEqual( - 'body{background-color: red;}h1{font-size: 42px;}h1,h2,h3,h4,h5,h6{color: orange;}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{color: hotpink;}.has-white-color{color: var(--wp--preset--color--white) !important;}.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}.has-black-color{color: var(--wp--preset--color--black) !important;}.has-black-background-color{background-color: var(--wp--preset--color--black) !important;}.has-black-border-color{border-color: var(--wp--preset--color--black) !important;}' + 'body{background-color: red;margin: 10px;padding: 10px;}h1{font-size: 42px;}.wp-block-group{margin-top: 10px;margin-right: 20px;margin-bottom: 30px;margin-left: 40px;padding-top: 11px;padding-right: 22px;padding-bottom: 33px;padding-left: 44px;}h1,h2,h3,h4,h5,h6{color: orange;}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{color: hotpink;}.has-white-color{color: var(--wp--preset--color--white) !important;}.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}.has-black-color{color: var(--wp--preset--color--black) !important;}.has-black-background-color{background-color: var(--wp--preset--color--black) !important;}.has-black-border-color{border-color: var(--wp--preset--color--black) !important;}' ); } ); } ); diff --git a/packages/edit-site/src/components/sidebar/spacing-panel.js b/packages/edit-site/src/components/sidebar/spacing-panel.js index 987d568aaabdcf..cf224ee63fc25d 100644 --- a/packages/edit-site/src/components/sidebar/spacing-panel.js +++ b/packages/edit-site/src/components/sidebar/spacing-panel.js @@ -46,6 +46,21 @@ function filterValuesBySides( values, sides ) { return filteredValues; } +function splitStyleValue( value ) { + // Check for shorthand value ( a string value ). + if ( value && typeof value === 'string' ) { + // Convert to value for individual sides for BoxControl. + return { + top: value, + right: value, + bottom: value, + left: value, + }; + } + + return value; +} + export default function SpacingPanel( { context, getStyle, setStyle } ) { const { name } = context; const showPaddingControl = useHasPadding( context ); @@ -60,7 +75,7 @@ export default function SpacingPanel( { context, getStyle, setStyle } ) { ], } ); - const paddingValues = getStyle( name, 'padding' ); + const paddingValues = splitStyleValue( getStyle( name, 'padding' ) ); const paddingSides = useCustomSides( name, 'padding' ); const setPaddingValues = ( newPaddingValues ) => { @@ -68,7 +83,7 @@ export default function SpacingPanel( { context, getStyle, setStyle } ) { setStyle( name, 'padding', padding ); }; - const marginValues = getStyle( name, 'margin' ); + const marginValues = splitStyleValue( getStyle( name, 'margin' ) ); const marginSides = useCustomSides( name, 'margin' ); const setMarginValues = ( newMarginValues ) => { diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index 5b9cc20c3233d2..02c7dea4921e71 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -181,6 +181,52 @@ function test_get_settings_presets_are_keyed_by_origin() { $this->assertEqualSetsWithIndex( $expected_no_origin, $actual_no_origin ); } + function test_get_stylesheet_support_for_shorthand_and_longhand_values() { + $theme_json = new WP_Theme_JSON_Gutenberg( + array( + 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, + 'styles' => array( + 'blocks' => array( + 'core/group' => array( + 'border' => array( + 'radius' => '10px', + ), + 'spacing' => array( + 'padding' => '24px', + 'margin' => '1em', + ), + ), + 'core/image' => array( + 'border' => array( + 'radius' => array( + 'topLeft' => '10px', + 'bottomRight' => '1em', + ), + ), + 'spacing' => array( + 'padding' => array( + 'top' => '15px', + ), + 'margin' => array( + 'bottom' => '30px', + ), + ), + ), + ), + ), + ) + ); + + $this->assertEquals( + '.wp-block-group{border-radius: 10px;margin: 1em;padding: 24px;}.wp-block-image{border-top-left-radius: 10px;border-bottom-right-radius: 1em;margin-bottom: 30px;padding-top: 15px;}', + $theme_json->get_stylesheet() + ); + $this->assertEquals( + '.wp-block-group{border-radius: 10px;margin: 1em;padding: 24px;}.wp-block-image{border-top-left-radius: 10px;border-bottom-right-radius: 1em;margin-bottom: 30px;padding-top: 15px;}', + $theme_json->get_stylesheet( 'block_styles' ) + ); + } + function test_get_stylesheet() { $theme_json = new WP_Theme_JSON_Gutenberg( array( @@ -236,6 +282,9 @@ function test_get_stylesheet() { ), 'blocks' => array( 'core/group' => array( + 'border' => array( + 'radius' => '10px', + ), 'elements' => array( 'link' => array( 'color' => array( @@ -244,10 +293,7 @@ function test_get_stylesheet() { ), ), 'spacing' => array( - 'padding' => array( - 'top' => '12px', - 'bottom' => '24px', - ), + 'padding' => '24px', ), ), 'core/heading' => array( @@ -279,6 +325,19 @@ function test_get_stylesheet() { ), ), ), + 'core/image' => array( + 'border' => array( + 'radius' => array( + 'topLeft' => '10px', + 'bottomRight' => '1em', + ), + ), + 'spacing' => array( + 'margin' => array( + 'bottom' => '30px', + ), + ), + ), ), ), 'misc' => 'value', @@ -286,11 +345,11 @@ function test_get_stylesheet() { ); $this->assertEquals( - 'body{--wp--preset--color--grey: grey;--wp--preset--font-family--small: 14px;--wp--preset--font-family--big: 41px;}.wp-block-group{--wp--custom--base-font: 16;--wp--custom--line-height--small: 1.2;--wp--custom--line-height--medium: 1.4;--wp--custom--line-height--large: 1.8;}body{color: var(--wp--preset--color--grey);}a{background-color: #333;color: #111;}.wp-block-group{padding-top: 12px;padding-bottom: 24px;}.wp-block-group a{color: #111;}h1,h2,h3,h4,h5,h6{color: #123456;}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{background-color: #333;color: #111;font-size: 60px;}.wp-block-post-date{color: #123456;}.wp-block-post-date a{background-color: #777;color: #555;}.has-grey-color{color: var(--wp--preset--color--grey) !important;}.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}.has-grey-border-color{border-color: var(--wp--preset--color--grey) !important;}', + 'body{--wp--preset--color--grey: grey;--wp--preset--font-family--small: 14px;--wp--preset--font-family--big: 41px;}.wp-block-group{--wp--custom--base-font: 16;--wp--custom--line-height--small: 1.2;--wp--custom--line-height--medium: 1.4;--wp--custom--line-height--large: 1.8;}body{color: var(--wp--preset--color--grey);}a{background-color: #333;color: #111;}.wp-block-group{border-radius: 10px;padding: 24px;}.wp-block-group a{color: #111;}h1,h2,h3,h4,h5,h6{color: #123456;}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{background-color: #333;color: #111;font-size: 60px;}.wp-block-post-date{color: #123456;}.wp-block-post-date a{background-color: #777;color: #555;}.wp-block-image{border-top-left-radius: 10px;border-bottom-right-radius: 1em;margin-bottom: 30px;}.has-grey-color{color: var(--wp--preset--color--grey) !important;}.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}.has-grey-border-color{border-color: var(--wp--preset--color--grey) !important;}', $theme_json->get_stylesheet() ); $this->assertEquals( - 'body{color: var(--wp--preset--color--grey);}a{background-color: #333;color: #111;}.wp-block-group{padding-top: 12px;padding-bottom: 24px;}.wp-block-group a{color: #111;}h1,h2,h3,h4,h5,h6{color: #123456;}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{background-color: #333;color: #111;font-size: 60px;}.wp-block-post-date{color: #123456;}.wp-block-post-date a{background-color: #777;color: #555;}.has-grey-color{color: var(--wp--preset--color--grey) !important;}.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}.has-grey-border-color{border-color: var(--wp--preset--color--grey) !important;}', + 'body{color: var(--wp--preset--color--grey);}a{background-color: #333;color: #111;}.wp-block-group{border-radius: 10px;padding: 24px;}.wp-block-group a{color: #111;}h1,h2,h3,h4,h5,h6{color: #123456;}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{background-color: #333;color: #111;font-size: 60px;}.wp-block-post-date{color: #123456;}.wp-block-post-date a{background-color: #777;color: #555;}.wp-block-image{border-top-left-radius: 10px;border-bottom-right-radius: 1em;margin-bottom: 30px;}.has-grey-color{color: var(--wp--preset--color--grey) !important;}.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}.has-grey-border-color{border-color: var(--wp--preset--color--grey) !important;}', $theme_json->get_stylesheet( 'block_styles' ) ); $this->assertEquals( @@ -728,6 +787,14 @@ function test_remove_insecure_properties_removes_unsafe_styles_sub_properties() array( 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, 'styles' => array( + 'border' => array( + 'radius' => array( + 'topLeft' => '6px', + 'topRight' => 'var(--top-right, var(--unsafe-fallback))', + 'bottomRight' => '6px', + 'bottomLeft' => '6px', + ), + ), 'spacing' => array( 'padding' => array( 'top' => '1px', @@ -750,6 +817,14 @@ function test_remove_insecure_properties_removes_unsafe_styles_sub_properties() ), 'blocks' => array( 'core/group' => array( + 'border' => array( + 'radius' => array( + 'topLeft' => '5px', + 'topRight' => 'var(--top-right, var(--unsafe-fallback))', + 'bottomRight' => '5px', + 'bottomLeft' => '5px', + ), + ), 'spacing' => array( 'padding' => array( 'top' => '3px', @@ -780,6 +855,13 @@ function test_remove_insecure_properties_removes_unsafe_styles_sub_properties() $expected = array( 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA, 'styles' => array( + 'border' => array( + 'radius' => array( + 'topLeft' => '6px', + 'bottomRight' => '6px', + 'bottomLeft' => '6px', + ), + ), 'spacing' => array( 'padding' => array( 'top' => '1px', @@ -800,6 +882,13 @@ function test_remove_insecure_properties_removes_unsafe_styles_sub_properties() ), 'blocks' => array( 'core/group' => array( + 'border' => array( + 'radius' => array( + 'topLeft' => '5px', + 'bottomRight' => '5px', + 'bottomLeft' => '5px', + ), + ), 'spacing' => array( 'padding' => array( 'top' => '3px', @@ -1004,7 +1093,7 @@ function test_remove_insecure_properties_removes_unsafe_preset_settings() { array( 'name' => 'Blue', 'slug' => 'blue', - 'color' => 'var(--color, var(--unsafe--falback))', + 'color' => 'var(--color, var(--unsafe--fallback))', ), array( 'name' => 'Pink',