Skip to content

Commit

Permalink
Allow longhand and shorthand properties in theme.json and block att…
Browse files Browse the repository at this point in the history
…ributes (#31641)
  • Loading branch information
aaronrobertshaw authored Jun 18, 2021
1 parent 9267fab commit a1eac43
Show file tree
Hide file tree
Showing 11 changed files with 316 additions and 171 deletions.
19 changes: 14 additions & 5 deletions lib/block-supports/border.php
Original file line number Diff line number Diff line change
Expand Up @@ -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( '/(?<!^)[A-Z]/', '-$0', $key ) );
$styles[] = sprintf( 'border-%s-radius: %s;', $corner, $radius );
}
} else {
// This check handles original unitless implementation.
if ( is_numeric( $border_radius ) ) {
$border_radius .= 'px';
}

$styles[] = sprintf( 'border-radius: %s;', $border_radius );
}

$styles[] = sprintf( 'border-radius: %s;', $border_radius );
}

// Border style.
Expand Down
10 changes: 8 additions & 2 deletions lib/block-supports/spacing.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,19 +45,25 @@ function gutenberg_apply_spacing_support( $block_type, $block_attributes ) {

if ( $has_padding_support ) {
$padding_value = _wp_array_get( $block_attributes, array( 'style', 'spacing', 'padding' ), null );
if ( null !== $padding_value ) {

if ( is_array( $padding_value ) ) {
foreach ( $padding_value as $key => $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 );
}
}

Expand Down
182 changes: 46 additions & 136 deletions lib/class-wp-theme-json-gutenberg.php
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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.
*
Expand Down Expand Up @@ -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;
}

Expand All @@ -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:
Expand All @@ -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,
);
}
Expand Down Expand Up @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions lib/compat.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
19 changes: 13 additions & 6 deletions packages/block-editor/src/hooks/style.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
* External dependencies
*/
import {
capitalize,
first,
forEach,
get,
has,
isEmpty,
isString,
kebabCase,
map,
omit,
Expand Down Expand Up @@ -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 ) );
Expand Down
Loading

0 comments on commit a1eac43

Please sign in to comment.