From 7922670adb5a6c4f192ca68edb43429fbb9a645b Mon Sep 17 00:00:00 2001 From: ramonjd Date: Tue, 15 Mar 2022 15:51:09 +1100 Subject: [PATCH 01/12] Initial and worst commit --- lib/block-supports/spacing.php | 40 +++- lib/load.php | 5 + .../class-wp-style-engine-gutenberg.php | 179 ++++++++++++++++++ 3 files changed, 217 insertions(+), 7 deletions(-) create mode 100644 lib/style-engine/class-wp-style-engine-gutenberg.php diff --git a/lib/block-supports/spacing.php b/lib/block-supports/spacing.php index 78f5b59f90fb0..46611b2a73e27 100644 --- a/lib/block-supports/spacing.php +++ b/lib/block-supports/spacing.php @@ -45,18 +45,33 @@ function gutenberg_apply_spacing_support( $block_type, $block_attributes ) { $has_padding_support = gutenberg_block_has_support( $block_type, array( 'spacing', 'padding' ), false ); $has_margin_support = gutenberg_block_has_support( $block_type, array( 'spacing', 'margin' ), false ); + $classes = array(); $styles = array(); + $style_engine = WP_Style_Engine_Gutenberg::get_instance(); if ( $has_padding_support ) { $padding_value = _wp_array_get( $block_attributes, array( 'style', 'spacing', 'padding' ), null ); - 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 ( null !== $padding_value ) { + // Challenge: deal with specificity that inline styles bring us. + // We could flag to use `! important` or just leave inline styles for now. + $classes[] = $style_engine->add_style_from_attributes( + 'wp-block-supports', + $block_attributes['style'], + array( 'spacing', 'padding' ), + array( + 'obfuscate' => true, + ) + ); } + +// 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 ) { @@ -71,7 +86,18 @@ function gutenberg_apply_spacing_support( $block_type, $block_attributes ) { } } - return empty( $styles ) ? array() : array( 'style' => implode( ' ', $styles ) ); + // Collect classes and styles. + $attributes = array(); + + if ( ! empty( $classes ) ) { + $attributes['class'] = implode( ' ', $classes ); + } + + if ( ! empty( $styles ) ) { + $attributes['style'] = implode( ' ', $styles ); + } + + return $attributes; } /** diff --git a/lib/load.php b/lib/load.php index c6619708df3df..5d1933c16738e 100644 --- a/lib/load.php +++ b/lib/load.php @@ -121,6 +121,11 @@ function gutenberg_is_experiment_enabled( $name ) { require __DIR__ . '/global-styles.php'; require __DIR__ . '/pwa.php'; +// TODO: Before this PR merges, move this to be a part of the style engine package. +// Part of the build process should be to copy the PHP file to the correct location, +// similar to the loading behaviour in `blocks.php`. +require __DIR__ . '/style-engine/class-wp-style-engine-gutenberg.php'; + require __DIR__ . '/block-supports/elements.php'; require __DIR__ . '/block-supports/colors.php'; require __DIR__ . '/block-supports/typography.php'; diff --git a/lib/style-engine/class-wp-style-engine-gutenberg.php b/lib/style-engine/class-wp-style-engine-gutenberg.php new file mode 100644 index 0000000000000..ee6439baa6926 --- /dev/null +++ b/lib/style-engine/class-wp-style-engine-gutenberg.php @@ -0,0 +1,179 @@ +registered_styles = array(); + } + + public function get_generated_styles() { + $output = ''; + foreach ( $this->registered_styles as $selector => $rules ) { + $output .= "{$selector} {\n"; + + if ( is_string( $rules ) ) { + $output .= ' '; + $output .= $rules; + } else { + foreach ( $rules as $rule => $value ) { + $output .= " {$rule}: {$value};\n"; + } + } + $output .= "}\n"; + } + return $output; + } + + /** + * Stores style rules for a given CSS selector (the key) and returns an associated classname. + * + * @param string $key A class name used to construct a key. + * @param array $options An array of options, rules, and selector for constructing the rules. + * + * @return string The class name for the added style. + */ + public function add_style( $key, $options ) { + $class = ! empty( $options['suffix'] ) ? $key . '-' . sanitize_title( $options['suffix'] ) : $key; + $selector = ! empty( $options['selector'] ) ? ' ' . trim( $options['selector'] ) : ''; + $rules = ! empty( $options['rules'] ) ? $options['rules'] : array(); + $prefix = ! empty( $options['prefix'] ) ? $options['prefix'] : '.'; + + if ( ! $class ) { + return; + } + + if ( ! empty( $options['obfuscate'] ) && $options['obfuscate'] === true ) { + // Will we ever need to decode/decrypt the classname? + // If so, look at openssl_encrypt() + $class = $key . '__' . hash( 'crc32', $class ); + } + + $this->registered_styles[ $prefix . $class . $selector ] = $rules; + + return $class; + } + + /** + * Accepts and parses a Gutenberg attributes->style object and returns add_style() + * Stores style rules for a given CSS selector (the key) and returns an associated classname. + * + * @param string $key A class name used to construct a key. + * @param array $block_styles An array of styles from a block's attributes. + * @param array $path An array of strings representing a path to the style value. + * @param array $options An array of options that add_style() accepts. + * + * @return string The class name for the added style. + */ + public function add_style_from_attributes( $key, $block_attributes, $path, $options ) { + if ( ! is_array( $block_attributes ) || ! is_array( $path ) ) { + return; + } + + $style_value = _wp_array_get( $block_attributes, $path, null ); + $rules = array(); + $suffix = ''; + + /* + // Only expecting padding for now. This will be extracted/abstracted. + // Possibly we'd have parsing rules and extra metadata, e.g., + const STYLE_DEFINITIONS_METADATA = array( + 'spacing' => array( + 'margin' => array( + 'value_func' => 'gutenberg_get_style_engine_css_box_rules', + ), + 'padding' => array( + 'value_func' => 'gutenberg_get_style_engine_css_box_rules', + ), + ), + ); + */ + if ( is_array( $style_value ) ) { + foreach ( $style_value as $property => $value ) { + $rules[ "padding-$property" ] = $value . ' !important'; // Challenge: deal with specificity that inline styles bring us. Maybe we could pass an option. + } + $suffix = implode( '-', array_values( $style_value ) ); + } elseif ( null !== $style_value ) { + $rules[] = sprintf( 'padding: %s !important;', $style_value ); + $suffix = str_replace( ' ', '-', $style_value ); + } + + $options = array_merge( + $options, + array( + 'suffix' => implode( '-', $path ) . '__' . $suffix, + 'rules' => $rules, + ) + ); + + return $this->add_style( + $key, + $options + ); + } + + /** + * Render registered styles as key { ...rules } for final output. + */ + public function output_styles() { + $output = $this->get_generated_styles(); + echo "\n"; + } +} From ff2cd05609de154940ab9e7d2d92e398a9870b9f Mon Sep 17 00:00:00 2001 From: ramonjd Date: Wed, 16 Mar 2022 11:16:03 +1100 Subject: [PATCH 02/12] Adding a style definition box model utility to extract CSS rules from a Gutenberg style attributes object --- .../class-wp-style-engine-gutenberg.php | 62 ++++++++++++------- lib/style-engine/style-definition-utils.php | 27 ++++++++ 2 files changed, 68 insertions(+), 21 deletions(-) create mode 100644 lib/style-engine/style-definition-utils.php diff --git a/lib/style-engine/class-wp-style-engine-gutenberg.php b/lib/style-engine/class-wp-style-engine-gutenberg.php index ee6439baa6926..217c216708602 100644 --- a/lib/style-engine/class-wp-style-engine-gutenberg.php +++ b/lib/style-engine/class-wp-style-engine-gutenberg.php @@ -5,6 +5,8 @@ * @package Gutenberg */ +require_once __DIR__ . '/style-definition-utils.php'; + /** * Singleton class representing the style engine. * @@ -30,6 +32,19 @@ class WP_Style_Engine_Gutenberg { */ private static $instance = null; + /** + * Style definitions that contain the instructions to + * parse/output valid Gutenberg styles. + */ + const STYLE_DEFINITIONS_METADATA = array( + 'spacing' => array( + 'padding' => array( + 'value_key' => 'padding', + 'value_func' => 'gutenberg_get_style_engine_css_box_rules', + ), + ), + ); + /** * Register action for outputting styles when the class is constructed. */ @@ -111,12 +126,35 @@ public function add_style( $key, $options ) { return $class; } + /** + * Returns a CSS ruleset based on the instructions in STYLE_DEFINITIONS_METADATA. + * + * @param string|array $style_value A single raw Gutenberg style attributes value for a CSS property. + * @param array $path An array of strings representing a path to the style value. + * + * @return array The class name for the added style. + */ + protected function get_style_css_rules( $style_value, $path ) { + $style_definition = _wp_array_get( static::STYLE_DEFINITIONS_METADATA, $path, null ); + + if ( $style_definition ) { + if ( + isset( $style_definition['value_func'] ) && + is_callable( $style_definition['value_func'] ) + ) { + return call_user_func( $style_definition['value_func'], $style_value, $style_definition['value_key'] ); + } + } + + return array(); + } + /** * Accepts and parses a Gutenberg attributes->style object and returns add_style() * Stores style rules for a given CSS selector (the key) and returns an associated classname. * * @param string $key A class name used to construct a key. - * @param array $block_styles An array of styles from a block's attributes. + * @param array $block_attributes An array of styles from a block's attributes. * @param array $path An array of strings representing a path to the style value. * @param array $options An array of options that add_style() accepts. * @@ -128,31 +166,13 @@ public function add_style_from_attributes( $key, $block_attributes, $path, $opti } $style_value = _wp_array_get( $block_attributes, $path, null ); - $rules = array(); + $rules = $this->get_style_css_rules( $style_value, $path ); $suffix = ''; - /* - // Only expecting padding for now. This will be extracted/abstracted. - // Possibly we'd have parsing rules and extra metadata, e.g., - const STYLE_DEFINITIONS_METADATA = array( - 'spacing' => array( - 'margin' => array( - 'value_func' => 'gutenberg_get_style_engine_css_box_rules', - ), - 'padding' => array( - 'value_func' => 'gutenberg_get_style_engine_css_box_rules', - ), - ), - ); - */ if ( is_array( $style_value ) ) { - foreach ( $style_value as $property => $value ) { - $rules[ "padding-$property" ] = $value . ' !important'; // Challenge: deal with specificity that inline styles bring us. Maybe we could pass an option. - } $suffix = implode( '-', array_values( $style_value ) ); } elseif ( null !== $style_value ) { - $rules[] = sprintf( 'padding: %s !important;', $style_value ); - $suffix = str_replace( ' ', '-', $style_value ); + $suffix = str_replace( ' ', '-', $style_value ); } $options = array_merge( diff --git a/lib/style-engine/style-definition-utils.php b/lib/style-engine/style-definition-utils.php new file mode 100644 index 0000000000000..43e902f1e3191 --- /dev/null +++ b/lib/style-engine/style-definition-utils.php @@ -0,0 +1,27 @@ + $value ) { + $rules[ "$style_property-$key" ] = $value . ' !important'; // Challenge: deal with specificity that inline styles bring us. Maybe we could pass an option. + } + } elseif ( null !== $style_value ) { + $rules[] = sprintf( "$style_property: %s !important;", $style_value ); + } + return $rules; +} + From 7f75ff77a885f773f789e51bf091388190cb892a Mon Sep 17 00:00:00 2001 From: ramonjd Date: Wed, 16 Mar 2022 12:26:36 +1100 Subject: [PATCH 03/12] Adding inline style capabilities --- lib/block-supports/spacing.php | 55 ++++++++----------- .../class-wp-style-engine-gutenberg.php | 47 +++++++++++++--- lib/style-engine/style-definition-utils.php | 13 +++-- 3 files changed, 72 insertions(+), 43 deletions(-) diff --git a/lib/block-supports/spacing.php b/lib/block-supports/spacing.php index 46611b2a73e27..1049426bd2b07 100644 --- a/lib/block-supports/spacing.php +++ b/lib/block-supports/spacing.php @@ -50,40 +50,33 @@ function gutenberg_apply_spacing_support( $block_type, $block_attributes ) { $style_engine = WP_Style_Engine_Gutenberg::get_instance(); if ( $has_padding_support ) { - $padding_value = _wp_array_get( $block_attributes, array( 'style', 'spacing', 'padding' ), null ); - - if ( null !== $padding_value ) { - // Challenge: deal with specificity that inline styles bring us. - // We could flag to use `! important` or just leave inline styles for now. - $classes[] = $style_engine->add_style_from_attributes( - 'wp-block-supports', - $block_attributes['style'], - array( 'spacing', 'padding' ), - array( - 'obfuscate' => true, - ) - ); - } - -// 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 ); -// } + +/* + // We can also return an obfuscated classname. + // Do we need to add !important rules to the stylesheet in this case + // seeing as they're not inline? + $classes[] = $style_engine->add_style_from_attributes( + 'wp-block-supports', + $block_attributes['style'], + array( 'spacing', 'padding' ), + array( + 'obfuscate' => true, + ) + ); +*/ + + $styles[] = $style_engine->get_inline_styles_from_attributes( + $block_attributes['style'], + array( 'spacing', 'padding' ) + ); } if ( $has_margin_support ) { - $margin_value = _wp_array_get( $block_attributes, array( 'style', 'spacing', 'margin' ), null ); - - 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 ); - } + // As with padding above. + $styles[] = $style_engine->get_inline_styles_from_attributes( + $block_attributes['style'], + array( 'spacing', 'margin' ) + ); } // Collect classes and styles. diff --git a/lib/style-engine/class-wp-style-engine-gutenberg.php b/lib/style-engine/class-wp-style-engine-gutenberg.php index 217c216708602..97a0185eefd47 100644 --- a/lib/style-engine/class-wp-style-engine-gutenberg.php +++ b/lib/style-engine/class-wp-style-engine-gutenberg.php @@ -42,6 +42,10 @@ class WP_Style_Engine_Gutenberg { 'value_key' => 'padding', 'value_func' => 'gutenberg_get_style_engine_css_box_rules', ), + 'margin' => array( + 'value_key' => 'margin', + 'value_func' => 'gutenberg_get_style_engine_css_box_rules', + ), ), ); @@ -115,9 +119,11 @@ public function add_style( $key, $options ) { return; } - if ( ! empty( $options['obfuscate'] ) && $options['obfuscate'] === true ) { + if ( ! empty( $options['obfuscate'] ) && true === $options['obfuscate'] ) { + // Generate a consistent, obfuscated key by hashing a unique class based on the rules. + // Outputs something like .wp-my-key__002d308c. // Will we ever need to decode/decrypt the classname? - // If so, look at openssl_encrypt() + // If so, look at openssl_encrypt(). $class = $key . '__' . hash( 'crc32', $class ); } @@ -149,6 +155,30 @@ protected function get_style_css_rules( $style_value, $path ) { return array(); } + /** + * Returns an CSS ruleset destined to be inserted in an HTML `style` attribute. + * Styles are bundled based on the instructions in STYLE_DEFINITIONS_METADATA. + * + * @param array $block_attributes An array of styles from a block's attributes. + * @param array $path An array of strings representing a path to the style value. + * + * @return string A CSS ruleset formatted to be placed in an HTML `style` attribute. + */ + public function get_inline_styles_from_attributes( $block_attributes, $path ) { + if ( ! is_array( $block_attributes ) || ! is_array( $path ) ) { + return; + } + + $style_value = _wp_array_get( $block_attributes, $path, null ); + $rules = $this->get_style_css_rules( $style_value, $path ); + $output = ''; + + foreach ( $rules as $rule => $value ) { + $output .= "{$rule}: {$value}; "; + } + return $output; + } + /** * Accepts and parses a Gutenberg attributes->style object and returns add_style() * Stores style rules for a given CSS selector (the key) and returns an associated classname. @@ -166,15 +196,16 @@ public function add_style_from_attributes( $key, $block_attributes, $path, $opti } $style_value = _wp_array_get( $block_attributes, $path, null ); - $rules = $this->get_style_css_rules( $style_value, $path ); - $suffix = ''; - if ( is_array( $style_value ) ) { - $suffix = implode( '-', array_values( $style_value ) ); - } elseif ( null !== $style_value ) { - $suffix = str_replace( ' ', '-', $style_value ); + if ( ! $style_value ) { + return; } + $rules = $this->get_style_css_rules( $style_value, $path ); + + // Collect individual CSS property values so we can build a unique classname. + $suffix = is_array( $style_value ) ? implode( '-', array_values( $style_value ) ) : str_replace( ' ', '-', $style_value ); + $options = array_merge( $options, array( diff --git a/lib/style-engine/style-definition-utils.php b/lib/style-engine/style-definition-utils.php index 43e902f1e3191..404283822f539 100644 --- a/lib/style-engine/style-definition-utils.php +++ b/lib/style-engine/style-definition-utils.php @@ -13,14 +13,19 @@ * * @return array The class name for the added style. */ -function gutenberg_get_style_engine_css_box_rules($style_value, string $style_property ) { +function gutenberg_get_style_engine_css_box_rules ( $style_value, $style_property ) { $rules = array(); + + if ( ! $style_value ) { + return $rules; + } + if ( is_array( $style_value ) ) { foreach ( $style_value as $key => $value ) { - $rules[ "$style_property-$key" ] = $value . ' !important'; // Challenge: deal with specificity that inline styles bring us. Maybe we could pass an option. + $rules[ "$style_property-$key" ] = $value; // . ' !important'; Challenge: deal with specificity that inline styles bring us. Maybe we could pass an option. } - } elseif ( null !== $style_value ) { - $rules[] = sprintf( "$style_property: %s !important;", $style_value ); + } else { + $rules[] = sprintf( "$style_property: %s;", $style_value ); } return $rules; } From 3e5cf6f735c2164e6e5fa70746e983fe31124aaf Mon Sep 17 00:00:00 2001 From: ramonjd Date: Wed, 16 Mar 2022 13:17:02 +1100 Subject: [PATCH 04/12] filter out empty values from the array --- lib/block-supports/spacing.php | 47 +++++++----- .../class-wp-style-engine-gutenberg.php | 74 ++++++++++++------- lib/style-engine/style-definition-utils.php | 6 +- 3 files changed, 78 insertions(+), 49 deletions(-) diff --git a/lib/block-supports/spacing.php b/lib/block-supports/spacing.php index 1049426bd2b07..e1efde6f07f5e 100644 --- a/lib/block-supports/spacing.php +++ b/lib/block-supports/spacing.php @@ -45,38 +45,45 @@ function gutenberg_apply_spacing_support( $block_type, $block_attributes ) { $has_padding_support = gutenberg_block_has_support( $block_type, array( 'spacing', 'padding' ), false ); $has_margin_support = gutenberg_block_has_support( $block_type, array( 'spacing', 'margin' ), false ); + $block_styles = isset( $block_attributes['style'] ) ? $block_attributes['style'] : null; $classes = array(); $styles = array(); $style_engine = WP_Style_Engine_Gutenberg::get_instance(); if ( $has_padding_support ) { - -/* - // We can also return an obfuscated classname. - // Do we need to add !important rules to the stylesheet in this case - // seeing as they're not inline? - $classes[] = $style_engine->add_style_from_attributes( - 'wp-block-supports', - $block_attributes['style'], - array( 'spacing', 'padding' ), - array( - 'obfuscate' => true, - ) - ); -*/ - - $styles[] = $style_engine->get_inline_styles_from_attributes( - $block_attributes['style'], + /* + // We can also return an obfuscated classname. + // Do we need to add !important rules to the stylesheet in this case + // seeing as they're not inline? + $classes[] = $style_engine->add_style_from_attributes( + 'wp-block-supports', + $attributes_styles, + array( 'spacing', 'padding' ), + array( + 'obfuscate' => true, + ) + ); + */ + $padding_styles = $style_engine->get_inline_styles_from_attributes( + $block_styles, array( 'spacing', 'padding' ) ); + + if ( $padding_styles ) { + $styles[] = $padding_styles; + } } if ( $has_margin_support ) { // As with padding above. - $styles[] = $style_engine->get_inline_styles_from_attributes( - $block_attributes['style'], + $margin_styles = $style_engine->get_inline_styles_from_attributes( + $block_styles, array( 'spacing', 'margin' ) ); + + if ( $margin_styles ) { + $styles[] = $margin_styles; + } } // Collect classes and styles. @@ -87,7 +94,7 @@ function gutenberg_apply_spacing_support( $block_type, $block_attributes ) { } if ( ! empty( $styles ) ) { - $attributes['style'] = implode( ' ', $styles ); + $attributes['style'] = implode( '', $styles ); } return $attributes; diff --git a/lib/style-engine/class-wp-style-engine-gutenberg.php b/lib/style-engine/class-wp-style-engine-gutenberg.php index 97a0185eefd47..9b8c78c186c04 100644 --- a/lib/style-engine/class-wp-style-engine-gutenberg.php +++ b/lib/style-engine/class-wp-style-engine-gutenberg.php @@ -2,9 +2,12 @@ /** * WP_Style_Engine class * + * Generates classnames and block styles. + * * @package Gutenberg */ +// Load utilities. require_once __DIR__ . '/style-definition-utils.php'; /** @@ -34,17 +37,22 @@ class WP_Style_Engine_Gutenberg { /** * Style definitions that contain the instructions to - * parse/output valid Gutenberg styles. + * parse/output valid Gutenberg styles from a block's attributes. + * For every style definition, the follow properties are valid: + * + * - property_key => the key that represents a valid CSS property, e.g., "margin" or "border". + * - value_func => a function to generate an array of valid CSS rules for a particular style object. + * For example, `'padding' => 'array( 'top' => '1em' )` will return `array( 'padding-top' => '1em' )` */ - const STYLE_DEFINITIONS_METADATA = array( + const BLOCK_STYLE_DEFINITIONS_METADATA = array( 'spacing' => array( 'padding' => array( - 'value_key' => 'padding', - 'value_func' => 'gutenberg_get_style_engine_css_box_rules', + 'property_key' => 'padding', + 'value_func' => 'gutenberg_get_style_engine_css_box_rules', ), - 'margin' => array( - 'value_key' => 'margin', - 'value_func' => 'gutenberg_get_style_engine_css_box_rules', + 'margin' => array( + 'property_key' => 'margin', + 'value_func' => 'gutenberg_get_style_engine_css_box_rules', ), ), ); @@ -79,10 +87,18 @@ public static function get_instance() { return self::$instance; } + /** + * Resets the style store. + */ public function reset() { $this->registered_styles = array(); } + /** + * Compiles and returns styles to be included in an HTML document. + * + * @return string CSS rules to embed in a `\n"; + if ( is_array( $style_value ) ) { + foreach ( $style_value as $key => $value ) { + $rules[ "$style_property-$key" ] = $value; + } + } else { + $rules[ $style_property ] = $style_value; } + return $rules; } diff --git a/lib/style-engine/style-definition-utils.php b/lib/style-engine/style-definition-utils.php deleted file mode 100644 index 9b3c2a9496116..0000000000000 --- a/lib/style-engine/style-definition-utils.php +++ /dev/null @@ -1,32 +0,0 @@ - $value ) { - $rules[ "$style_property-$key" ] = $value; // . ' !important'; Challenge: deal with specificity that inline styles bring us. Maybe we could pass an option. - } - } else { - $rules[ $style_property ] = $style_value; - } - return $rules; -} - diff --git a/phpunit/style-engine/class-wp-style-engine-gutenberg-test.php b/phpunit/style-engine/class-wp-style-engine-gutenberg-test.php index 230e78f812065..a2bbd83a9fe98 100644 --- a/phpunit/style-engine/class-wp-style-engine-gutenberg-test.php +++ b/phpunit/style-engine/class-wp-style-engine-gutenberg-test.php @@ -17,7 +17,7 @@ function test_returns_inline_styles_from_string() { 'padding' => '111px', ), ); - $padding_styles = $style_engine->get_inline_styles_from_attributes( + $padding_styles = $style_engine->get_inline_css_from_block_styles( $block_styles, array( 'spacing', 'padding' ) ); @@ -37,7 +37,7 @@ function test_returns_inline_styles_from_box_rules() { ), ), ); - $padding_styles = $style_engine->get_inline_styles_from_attributes( + $padding_styles = $style_engine->get_inline_css_from_block_styles( $block_styles, array( 'spacing', 'padding' ) ); @@ -52,7 +52,7 @@ function test_returns_empty_string_when_invalid_path_passed() { 'padding' => '111px', ), ); - $padding_styles = $style_engine->get_inline_styles_from_attributes( + $padding_styles = $style_engine->get_inline_css_from_block_styles( $block_styles, null ); From 332e706e44bbd6c0226556282b90b4ad8f20c59b Mon Sep 17 00:00:00 2001 From: ramonjd Date: Wed, 23 Mar 2022 10:34:14 +1100 Subject: [PATCH 07/12] Rename public method to `generate` to reflect current frontend API Add optional options array Explicitly tell `generate()` to return styles so we can open it up to further functionality Update tests --- lib/block-supports/spacing.php | 14 +- .../class-wp-style-engine-gutenberg.php | 49 +++-- .../class-wp-style-engine-gutenberg-test.php | 172 ++++++++++++++---- 3 files changed, 180 insertions(+), 55 deletions(-) diff --git a/lib/block-supports/spacing.php b/lib/block-supports/spacing.php index 69a65516842c6..b2c8d47a4d224 100644 --- a/lib/block-supports/spacing.php +++ b/lib/block-supports/spacing.php @@ -51,9 +51,12 @@ function gutenberg_apply_spacing_support( $block_type, $block_attributes ) { $style_engine = WP_Style_Engine_Gutenberg::get_instance(); if ( $has_padding_support ) { - $padding_styles = $style_engine->get_inline_css_from_block_styles( + $padding_styles = $style_engine->generate( $block_styles, - array( 'spacing', 'padding' ) + array( + 'path' => array( 'spacing', 'padding' ), + 'inline' => true, + ) ); if ( $padding_styles ) { @@ -63,9 +66,12 @@ function gutenberg_apply_spacing_support( $block_type, $block_attributes ) { if ( $has_margin_support ) { // As with padding above. - $margin_styles = $style_engine->get_inline_css_from_block_styles( + $margin_styles = $style_engine->generate( $block_styles, - array( 'spacing', 'margin' ) + array( + 'path' => array( 'spacing', 'margin' ), + 'inline' => true, + ) ); if ( $margin_styles ) { diff --git a/lib/style-engine/class-wp-style-engine-gutenberg.php b/lib/style-engine/class-wp-style-engine-gutenberg.php index 615315ae14897..0ab72dee1d884 100644 --- a/lib/style-engine/class-wp-style-engine-gutenberg.php +++ b/lib/style-engine/class-wp-style-engine-gutenberg.php @@ -37,10 +37,12 @@ class WP_Style_Engine_Gutenberg { 'spacing' => array( 'padding' => array( 'property_key' => 'padding', + 'path' => array( 'spacing', 'padding' ), 'value_func' => 'gutenberg_get_style_engine_css_box_rules', ), 'margin' => array( 'property_key' => 'margin', + 'path' => array( 'spacing', 'margin' ), 'value_func' => 'gutenberg_get_style_engine_css_box_rules', ), ), @@ -85,32 +87,55 @@ protected function get_block_style_css_rules( $style_value, $path ) { } /** - * Returns an CSS ruleset destined to be inserted in an HTML `style` attribute. + * Returns an CSS ruleset. * Styles are bundled based on the instructions in BLOCK_STYLE_DEFINITIONS_METADATA. * - * @param array $block_styles An array of styles from a block's attributes. - * @param array $path An array of strings representing a path to the style value. + * @param array $block_styles An array of styles from a block's attributes. + * @param array $options = array( + * 'inline' => (boolean) Whether to return inline CSS rules destined to be inserted in an HTML `style` attribute. + * 'path' => (array) Specify a block style to generate, otherwise it'll try all in BLOCK_STYLE_DEFINITIONS_METADATA. + * );. * * @return string A CSS ruleset formatted to be placed in an HTML `style` attribute. */ - public function get_inline_css_from_block_styles( $block_styles, $path ) { + public function generate( $block_styles, $options = array() ) { $output = ''; - if ( empty( $block_styles ) || empty( $path ) ) { + if ( empty( $block_styles ) ) { return $output; } - $style_value = _wp_array_get( $block_styles, $path, null ); + $rules = array(); - if ( empty( $style_value ) ) { - return $output; + // If a path to a specific block style is defined, only return rules for that style. + if ( isset( $options['path'] ) && is_array( $options['path'] ) ) { + $style_value = _wp_array_get( $block_styles, $options['path'], null ); + if ( empty( $style_value ) ) { + return $output; + } + $rules = array_merge( $rules, $this->get_block_style_css_rules( $style_value, $options['path'] ) ); + // Otherwise build them all. + } else { + foreach ( self::BLOCK_STYLE_DEFINITIONS_METADATA as $definition_group ) { + foreach ( $definition_group as $style_definition ) { + $style_value = _wp_array_get( $block_styles, $style_definition['path'], null ); + if ( empty( $style_value ) ) { + continue; + } + $rules = array_merge( $rules, $this->get_block_style_css_rules( $style_value, $style_definition['path'] ) ); + } + } } - $rules = $this->get_block_style_css_rules( $style_value, $path ); - - foreach ( $rules as $rule => $value ) { - $output .= "{$rule}:{$value};"; + if ( ! empty( $rules ) ) { + // Generate inline style rules. + if ( isset( $options['inline'] ) && true === $options['inline'] ) { + foreach ( $rules as $rule => $value ) { + $output .= "{$rule}:{$value};"; + } + } } + return $output; } } diff --git a/phpunit/style-engine/class-wp-style-engine-gutenberg-test.php b/phpunit/style-engine/class-wp-style-engine-gutenberg-test.php index a2bbd83a9fe98..3c3a297c09fe3 100644 --- a/phpunit/style-engine/class-wp-style-engine-gutenberg-test.php +++ b/phpunit/style-engine/class-wp-style-engine-gutenberg-test.php @@ -10,53 +10,147 @@ * Tests for registering, storing and generating styles. */ class WP_Style_Engine_Gutenberg_Test extends WP_UnitTestCase { - function test_returns_inline_styles_from_string() { - $style_engine = WP_Style_Engine_Gutenberg::get_instance(); - $block_styles = array( - 'spacing' => array( - 'padding' => '111px', - ), - ); - $padding_styles = $style_engine->get_inline_css_from_block_styles( + /** + * Tests various manifestations of the $block_styles argument. + * + * @dataProvider data_block_styles_fixtures + */ + function test_generate_css( $block_styles, $options, $expected_output ) { + $style_engine = WP_Style_Engine_Gutenberg::get_instance(); + $generated_styles = $style_engine->generate( $block_styles, - array( 'spacing', 'padding' ) + $options ); - $expected = 'padding:111px;'; - $this->assertSame( $expected, $padding_styles ); + $this->assertSame( $expected_output, $generated_styles ); } - function test_returns_inline_styles_from_box_rules() { - $style_engine = WP_Style_Engine_Gutenberg::get_instance(); - $block_styles = array( - 'spacing' => array( - 'padding' => array( - 'top' => '42px', - 'left' => '2%', - 'bottom' => '44px', - 'right' => '5rem', + /** + * Data provider. + * + * @return array + */ + public function data_block_styles_fixtures() { + return array( + 'default_return_value' => array( + 'block_styles' => array(), + 'options' => null, + 'expected_output' => '', + ), + + 'inline_invalid_block_styles_empty' => array( + 'block_styles' => array(), + 'options' => array( + 'path' => array( 'spacing', 'padding' ), + 'inline' => true, ), + 'expected_output' => '', + ), + + 'inline_invalid_block_styles_unknown_style' => array( + 'block_styles' => array( + 'pageBreakAfter' => 'verso', + ), + 'options' => array( + 'inline' => true, + ), + 'expected_output' => '', ), - ); - $padding_styles = $style_engine->get_inline_css_from_block_styles( - $block_styles, - array( 'spacing', 'padding' ) - ); - $expected = 'padding-top:42px;padding-left:2%;padding-bottom:44px;padding-right:5rem;'; - $this->assertSame( $expected, $padding_styles ); - } - function test_returns_empty_string_when_invalid_path_passed() { - $style_engine = WP_Style_Engine_Gutenberg::get_instance(); - $block_styles = array( - 'spacing' => array( - 'padding' => '111px', + 'inline_invalid_block_styles_unknown_definition' => array( + 'block_styles' => array( + 'pageBreakAfter' => 'verso', + ), + 'options' => array( + 'path' => array( 'pageBreakAfter', 'verso' ), + 'inline' => true, + ), + 'expected_output' => '', + ), + + 'inline_invalid_block_styles_unknown_property' => array( + 'block_styles' => array( + 'spacing' => array( + 'gavin' => '1000vw', + ), + ), + 'options' => array( + 'path' => array( 'spacing', 'padding' ), + 'inline' => true, + ), + 'expected_output' => '', + ), + + 'inline_invalid_multiple_style_unknown_property' => array( + 'block_styles' => array( + 'spacing' => array( + 'gavin' => '1000vw', + ), + ), + 'options' => array( + 'inline' => true, + ), + 'expected_output' => '', + ), + + 'inline_valid_single_style_string' => array( + 'block_styles' => array( + 'spacing' => array( + 'margin' => '111px', + ), + ), + 'options' => array( + 'path' => array( 'spacing', 'margin' ), + 'inline' => true, + ), + 'expected_output' => 'margin:111px;', + ), + + 'inline_valid_single_style' => array( + 'block_styles' => array( + 'spacing' => array( + 'padding' => array( + 'top' => '42px', + 'left' => '2%', + 'bottom' => '44px', + 'right' => '5rem', + ), + 'margin' => array( + 'top' => '12rem', + 'left' => '2vh', + 'bottom' => '2px', + 'right' => '10em', + ), + ), + ), + 'options' => array( + 'path' => array( 'spacing', 'padding' ), + 'inline' => true, + ), + 'expected_output' => 'padding-top:42px;padding-left:2%;padding-bottom:44px;padding-right:5rem;', + ), + + 'inline_valid_multiple_style' => array( + 'block_styles' => array( + 'spacing' => array( + 'padding' => array( + 'top' => '42px', + 'left' => '2%', + 'bottom' => '44px', + 'right' => '5rem', + ), + 'margin' => array( + 'top' => '12rem', + 'left' => '2vh', + 'bottom' => '2px', + 'right' => '10em', + ), + ), + ), + 'options' => array( + 'inline' => true, + ), + 'expected_output' => 'padding-top:42px;padding-left:2%;padding-bottom:44px;padding-right:5rem;margin-top:12rem;margin-left:2vh;margin-bottom:2px;margin-right:10em;', ), ); - $padding_styles = $style_engine->get_inline_css_from_block_styles( - $block_styles, - null - ); - $expected = ''; - $this->assertSame( $expected, $padding_styles ); } } From e7a13df7ce3e86326b50c09ca53386bf316104fd Mon Sep 17 00:00:00 2001 From: ramonjd Date: Wed, 23 Mar 2022 19:31:40 +1100 Subject: [PATCH 08/12] Building the spacing block styles before calling generate --- lib/block-supports/spacing.php | 56 ++++++++++------------------------ 1 file changed, 16 insertions(+), 40 deletions(-) diff --git a/lib/block-supports/spacing.php b/lib/block-supports/spacing.php index b2c8d47a4d224..bb24d3d7b052f 100644 --- a/lib/block-supports/spacing.php +++ b/lib/block-supports/spacing.php @@ -42,52 +42,28 @@ function gutenberg_apply_spacing_support( $block_type, $block_attributes ) { if ( gutenberg_skip_spacing_serialization( $block_type ) ) { return array(); } - + $attributes = array(); $has_padding_support = gutenberg_block_has_support( $block_type, array( 'spacing', 'padding' ), false ); $has_margin_support = gutenberg_block_has_support( $block_type, array( 'spacing', 'margin' ), false ); $block_styles = isset( $block_attributes['style'] ) ? $block_attributes['style'] : null; - $classes = array(); - $styles = array(); - $style_engine = WP_Style_Engine_Gutenberg::get_instance(); - - if ( $has_padding_support ) { - $padding_styles = $style_engine->generate( - $block_styles, - array( - 'path' => array( 'spacing', 'padding' ), - 'inline' => true, - ) - ); - - if ( $padding_styles ) { - $styles[] = $padding_styles; - } - } - - if ( $has_margin_support ) { - // As with padding above. - $margin_styles = $style_engine->generate( - $block_styles, - array( - 'path' => array( 'spacing', 'margin' ), - 'inline' => true, - ) - ); - - if ( $margin_styles ) { - $styles[] = $margin_styles; - } - } - - // Collect classes and styles. - $attributes = array(); - if ( ! empty( $classes ) ) { - $attributes['class'] = implode( ' ', $classes ); + if ( ! $block_styles ) { + return $attributes; } - if ( ! empty( $styles ) ) { - $attributes['style'] = implode( '', $styles ); + $style_engine = WP_Style_Engine_Gutenberg::get_instance(); + $spacing_block_styles = array(); + $spacing_block_styles['padding'] = $has_padding_support ? _wp_array_get( $block_styles, array( 'spacing', 'padding' ), null ) : null; + $spacing_block_styles['margin'] = $has_margin_support ? _wp_array_get( $block_styles, array( 'spacing', 'margin' ), null ) : null; + $inline_styles = $style_engine->generate( + array( 'spacing' => $spacing_block_styles ), + array( + 'inline' => true, + ) + ); + + if ( ! empty( $inline_styles ) ) { + $attributes['style'] = $inline_styles; } return $attributes; From ea31bcb9705399651e3a597d4f9efbf8f320cee4 Mon Sep 17 00:00:00 2001 From: ramonjd Date: Thu, 24 Mar 2022 18:53:40 +1100 Subject: [PATCH 09/12] Move box style function into the class Update comments, fix typos Filter CSS output --- .../class-wp-style-engine-gutenberg.php | 55 ++++++++++--------- .../class-wp-style-engine-gutenberg-test.php | 2 +- 2 files changed, 30 insertions(+), 27 deletions(-) diff --git a/lib/style-engine/class-wp-style-engine-gutenberg.php b/lib/style-engine/class-wp-style-engine-gutenberg.php index 0ab72dee1d884..671130a1322c1 100644 --- a/lib/style-engine/class-wp-style-engine-gutenberg.php +++ b/lib/style-engine/class-wp-style-engine-gutenberg.php @@ -19,7 +19,6 @@ class WP_Style_Engine_Gutenberg { /** * Container for the main instance of the class. * - * @since 5.5.0 * @var WP_Style_Engine_Gutenberg|null */ private static $instance = null; @@ -30,6 +29,7 @@ class WP_Style_Engine_Gutenberg { * For every style definition, the follow properties are valid: * * - property_key => the key that represents a valid CSS property, e.g., "margin" or "border". + * - path => a path that accesses the corresponding style value in the block style object. * - value_func => a function to generate an array of valid CSS rules for a particular style object. * For example, `'padding' => 'array( 'top' => '1em' )` will return `array( 'padding-top' => '1em' )` */ @@ -38,12 +38,12 @@ class WP_Style_Engine_Gutenberg { 'padding' => array( 'property_key' => 'padding', 'path' => array( 'spacing', 'padding' ), - 'value_func' => 'gutenberg_get_style_engine_css_box_rules', + 'value_func' => 'self::get_css_box_rules', ), 'margin' => array( 'property_key' => 'margin', 'path' => array( 'spacing', 'margin' ), - 'value_func' => 'gutenberg_get_style_engine_css_box_rules', + 'value_func' => 'self::get_css_box_rules', ), ), ); @@ -69,7 +69,7 @@ public static function get_instance() { * @param string|array $style_value A single raw Gutenberg style attributes value for a CSS property. * @param array $path An array of strings representing a path to the style value. * - * @return array A CSS ruleset compatible with add_style(). + * @return array A CSS ruleset compatible with generate(). */ protected function get_block_style_css_rules( $style_value, $path ) { $style_definition = _wp_array_get( static::BLOCK_STYLE_DEFINITIONS_METADATA, $path, null ); @@ -114,8 +114,8 @@ public function generate( $block_styles, $options = array() ) { return $output; } $rules = array_merge( $rules, $this->get_block_style_css_rules( $style_value, $options['path'] ) ); - // Otherwise build them all. } else { + // Otherwise build them all. foreach ( self::BLOCK_STYLE_DEFINITIONS_METADATA as $definition_group ) { foreach ( $definition_group as $style_definition ) { $style_value = _wp_array_get( $block_styles, $style_definition['path'], null ); @@ -131,36 +131,39 @@ public function generate( $block_styles, $options = array() ) { // Generate inline style rules. if ( isset( $options['inline'] ) && true === $options['inline'] ) { foreach ( $rules as $rule => $value ) { - $output .= "{$rule}:{$value};"; + $filtered_css = esc_html( safecss_filter_attr( "{$rule}:{$value}" ) ); + if ( ! empty( $filtered_css ) ) { + $output .= $filtered_css . ';'; + } } } } return $output; } -} -/** - * Returns a CSS ruleset for box model styles such as margins, padding, and borders. - * - * @param string|array $style_value A single raw Gutenberg style attributes value for a CSS property. - * @param string $style_property The CSS property for which we're creating a rule. - * - * @return array The class name for the added style. - */ -function gutenberg_get_style_engine_css_box_rules( $style_value, $style_property ) { - $rules = array(); + /** + * Returns a CSS ruleset for box model styles such as margins, padding, and borders. + * + * @param string|array $style_value A single raw Gutenberg style attributes value for a CSS property. + * @param string $style_property The CSS property for which we're creating a rule. + * + * @return array The class name for the added style. + */ + public static function get_css_box_rules( $style_value, $style_property ) { + $rules = array(); - if ( ! $style_value ) { - return $rules; - } + if ( ! $style_value ) { + return $rules; + } - if ( is_array( $style_value ) ) { - foreach ( $style_value as $key => $value ) { - $rules[ "$style_property-$key" ] = $value; + if ( is_array( $style_value ) ) { + foreach ( $style_value as $key => $value ) { + $rules[ "$style_property-$key" ] = $value; + } + } else { + $rules[ $style_property ] = $style_value; } - } else { - $rules[ $style_property ] = $style_value; + return $rules; } - return $rules; } diff --git a/phpunit/style-engine/class-wp-style-engine-gutenberg-test.php b/phpunit/style-engine/class-wp-style-engine-gutenberg-test.php index 3c3a297c09fe3..a3e017d0b8744 100644 --- a/phpunit/style-engine/class-wp-style-engine-gutenberg-test.php +++ b/phpunit/style-engine/class-wp-style-engine-gutenberg-test.php @@ -70,7 +70,7 @@ public function data_block_styles_fixtures() { 'inline_invalid_block_styles_unknown_property' => array( 'block_styles' => array( 'spacing' => array( - 'gavin' => '1000vw', + 'gap' => '1000vw', ), ), 'options' => array( From 99b9dbd937785c91e3ce47adb5af9566adca9351 Mon Sep 17 00:00:00 2001 From: ramonjd Date: Thu, 24 Mar 2022 21:40:40 +1100 Subject: [PATCH 10/12] Try: - move style engine into `/packages/style-engine` - create webpack copy pattern for packages with classes - switched class methods to static so we don't have to get the instance --- lib/block-supports/spacing.php | 3 +- lib/load.php | 8 ++-- .../style-engine/class-wp-style-engine.php | 42 ++++++------------- .../class-wp-style-engine-gutenberg-test.php | 3 +- tools/webpack/packages.js | 42 ++++++++++++++++--- 5 files changed, 55 insertions(+), 43 deletions(-) rename lib/style-engine/class-wp-style-engine-gutenberg.php => packages/style-engine/class-wp-style-engine.php (80%) diff --git a/lib/block-supports/spacing.php b/lib/block-supports/spacing.php index bb24d3d7b052f..c23e58ca30e80 100644 --- a/lib/block-supports/spacing.php +++ b/lib/block-supports/spacing.php @@ -51,11 +51,10 @@ function gutenberg_apply_spacing_support( $block_type, $block_attributes ) { return $attributes; } - $style_engine = WP_Style_Engine_Gutenberg::get_instance(); $spacing_block_styles = array(); $spacing_block_styles['padding'] = $has_padding_support ? _wp_array_get( $block_styles, array( 'spacing', 'padding' ), null ) : null; $spacing_block_styles['margin'] = $has_margin_support ? _wp_array_get( $block_styles, array( 'spacing', 'margin' ), null ) : null; - $inline_styles = $style_engine->generate( + $inline_styles = WP_Style_Engine_Gutenberg::generate( array( 'spacing' => $spacing_block_styles ), array( 'inline' => true, diff --git a/lib/load.php b/lib/load.php index 5d1933c16738e..368d7b87117c9 100644 --- a/lib/load.php +++ b/lib/load.php @@ -121,10 +121,10 @@ function gutenberg_is_experiment_enabled( $name ) { require __DIR__ . '/global-styles.php'; require __DIR__ . '/pwa.php'; -// TODO: Before this PR merges, move this to be a part of the style engine package. -// Part of the build process should be to copy the PHP file to the correct location, -// similar to the loading behaviour in `blocks.php`. -require __DIR__ . '/style-engine/class-wp-style-engine-gutenberg.php'; +// Copied package PHP files . +if ( file_exists( __DIR__ . '/style-engine/class-wp-style-engine-gutenberg.php' ) ) { + require __DIR__ . '/style-engine/class-wp-style-engine-gutenberg.php'; +} require __DIR__ . '/block-supports/elements.php'; require __DIR__ . '/block-supports/colors.php'; diff --git a/lib/style-engine/class-wp-style-engine-gutenberg.php b/packages/style-engine/class-wp-style-engine.php similarity index 80% rename from lib/style-engine/class-wp-style-engine-gutenberg.php rename to packages/style-engine/class-wp-style-engine.php index 671130a1322c1..0b2770625fc06 100644 --- a/lib/style-engine/class-wp-style-engine-gutenberg.php +++ b/packages/style-engine/class-wp-style-engine.php @@ -7,6 +7,10 @@ * @package Gutenberg */ +if ( class_exists( 'WP_Style_Engine' ) ) { + return; +} + /** * Singleton class representing the style engine. * @@ -15,14 +19,7 @@ * * @since 6.0.0 */ -class WP_Style_Engine_Gutenberg { - /** - * Container for the main instance of the class. - * - * @var WP_Style_Engine_Gutenberg|null - */ - private static $instance = null; - +class WP_Style_Engine { /** * Style definitions that contain the instructions to * parse/output valid Gutenberg styles from a block's attributes. @@ -38,31 +35,16 @@ class WP_Style_Engine_Gutenberg { 'padding' => array( 'property_key' => 'padding', 'path' => array( 'spacing', 'padding' ), - 'value_func' => 'self::get_css_box_rules', + 'value_func' => 'static::get_css_box_rules', ), 'margin' => array( 'property_key' => 'margin', 'path' => array( 'spacing', 'margin' ), - 'value_func' => 'self::get_css_box_rules', + 'value_func' => 'static::get_css_box_rules', ), ), ); - /** - * Utility method to retrieve the main instance of the class. - * - * The instance will be created if it does not exist yet. - * - * @return WP_Style_Engine_Gutenberg The main instance. - */ - public static function get_instance() { - if ( null === self::$instance ) { - self::$instance = new self(); - } - - return self::$instance; - } - /** * Returns a CSS ruleset based on the instructions in BLOCK_STYLE_DEFINITIONS_METADATA. * @@ -71,7 +53,7 @@ public static function get_instance() { * * @return array A CSS ruleset compatible with generate(). */ - protected function get_block_style_css_rules( $style_value, $path ) { + protected static function get_block_style_css_rules( $style_value, $path ) { $style_definition = _wp_array_get( static::BLOCK_STYLE_DEFINITIONS_METADATA, $path, null ); if ( ! empty( $style_definition ) ) { @@ -98,7 +80,7 @@ protected function get_block_style_css_rules( $style_value, $path ) { * * @return string A CSS ruleset formatted to be placed in an HTML `style` attribute. */ - public function generate( $block_styles, $options = array() ) { + public static function generate( $block_styles, $options = array() ) { $output = ''; if ( empty( $block_styles ) ) { @@ -113,7 +95,7 @@ public function generate( $block_styles, $options = array() ) { if ( empty( $style_value ) ) { return $output; } - $rules = array_merge( $rules, $this->get_block_style_css_rules( $style_value, $options['path'] ) ); + $rules = array_merge( $rules, static::get_block_style_css_rules( $style_value, $options['path'] ) ); } else { // Otherwise build them all. foreach ( self::BLOCK_STYLE_DEFINITIONS_METADATA as $definition_group ) { @@ -122,7 +104,7 @@ public function generate( $block_styles, $options = array() ) { if ( empty( $style_value ) ) { continue; } - $rules = array_merge( $rules, $this->get_block_style_css_rules( $style_value, $style_definition['path'] ) ); + $rules = array_merge( $rules, static::get_block_style_css_rules( $style_value, $style_definition['path'] ) ); } } } @@ -150,7 +132,7 @@ public function generate( $block_styles, $options = array() ) { * * @return array The class name for the added style. */ - public static function get_css_box_rules( $style_value, $style_property ) { + protected static function get_css_box_rules( $style_value, $style_property ) { $rules = array(); if ( ! $style_value ) { diff --git a/phpunit/style-engine/class-wp-style-engine-gutenberg-test.php b/phpunit/style-engine/class-wp-style-engine-gutenberg-test.php index a3e017d0b8744..3c422758e80bf 100644 --- a/phpunit/style-engine/class-wp-style-engine-gutenberg-test.php +++ b/phpunit/style-engine/class-wp-style-engine-gutenberg-test.php @@ -16,8 +16,7 @@ class WP_Style_Engine_Gutenberg_Test extends WP_UnitTestCase { * @dataProvider data_block_styles_fixtures */ function test_generate_css( $block_styles, $options, $expected_output ) { - $style_engine = WP_Style_Engine_Gutenberg::get_instance(); - $generated_styles = $style_engine->generate( + $generated_styles = WP_Style_Engine_Gutenberg::generate( $block_styles, $options ); diff --git a/tools/webpack/packages.js b/tools/webpack/packages.js index 4d02b4b6e2f81..b2781379159af 100644 --- a/tools/webpack/packages.js +++ b/tools/webpack/packages.js @@ -26,6 +26,15 @@ const BUNDLED_PACKAGES = [ '@wordpress/style-engine', ]; +// PHP files in packages that have to be copied over to /lib. +const BUNDLED_PACKAGES_PHP = [ + { + from: './packages/style-engine/', + to: 'lib/style-engine/', + replaceClasses: [ 'WP_Style_Engine' ], + }, +]; + const gutenbergPackages = Object.keys( dependencies ) .filter( ( packageName ) => @@ -99,15 +108,38 @@ module.exports = { ...plugins, new DependencyExtractionWebpackPlugin( { injectPolyfill: true } ), new CopyWebpackPlugin( { - patterns: gutenbergPackages - .map( ( packageName ) => ( { + patterns: [].concat( + gutenbergPackages.map( ( packageName ) => ( { from: '*.css', - context: `./packages/${ packageName }/build-style`, to: `./build/${ packageName }`, transform: stylesTransform, noErrorOnMissing: true, - } ) ) - .concat( vendorsCopyConfig ), + } ) ), + // Packages with PHP files to be parsed and copied to ./lib. + BUNDLED_PACKAGES_PHP.map( + ( { from, to, replaceClasses } ) => ( { + from: `${ from }/*.php`, + to: ( { absoluteFilename } ) => { + const [ , filename ] = absoluteFilename.match( + /([\w-]+)(\.php){1,1}$/ + ); + return join( to, `${ filename }-gutenberg.php` ); + }, + transform: ( content ) => { + const classSuffix = '_Gutenberg'; + content = content.toString(); + // Replace class names. + content = content.replace( + new RegExp( replaceClasses.join( '|' ), 'g' ), + ( match ) => `${ match }${ classSuffix }` + ); + return content; + }, + noErrorOnMissing: true, + } ) + ), + vendorsCopyConfig + ), } ), ].filter( Boolean ), }; From 5e0a9c24a6fc29ba68638aea294b11b3ebcb144d Mon Sep 17 00:00:00 2001 From: ramonjd Date: Thu, 24 Mar 2022 22:07:24 +1100 Subject: [PATCH 11/12] Roll back previous test commit. There were build errors that might best be resolved in another PR. --- lib/block-supports/spacing.php | 3 +- lib/load.php | 8 ++-- .../class-wp-style-engine-gutenberg.php | 38 +++++++++++++---- .../class-wp-style-engine-gutenberg-test.php | 3 +- tools/webpack/packages.js | 42 +++---------------- 5 files changed, 43 insertions(+), 51 deletions(-) rename packages/style-engine/class-wp-style-engine.php => lib/style-engine/class-wp-style-engine-gutenberg.php (80%) diff --git a/lib/block-supports/spacing.php b/lib/block-supports/spacing.php index c23e58ca30e80..bb24d3d7b052f 100644 --- a/lib/block-supports/spacing.php +++ b/lib/block-supports/spacing.php @@ -51,10 +51,11 @@ function gutenberg_apply_spacing_support( $block_type, $block_attributes ) { return $attributes; } + $style_engine = WP_Style_Engine_Gutenberg::get_instance(); $spacing_block_styles = array(); $spacing_block_styles['padding'] = $has_padding_support ? _wp_array_get( $block_styles, array( 'spacing', 'padding' ), null ) : null; $spacing_block_styles['margin'] = $has_margin_support ? _wp_array_get( $block_styles, array( 'spacing', 'margin' ), null ) : null; - $inline_styles = WP_Style_Engine_Gutenberg::generate( + $inline_styles = $style_engine->generate( array( 'spacing' => $spacing_block_styles ), array( 'inline' => true, diff --git a/lib/load.php b/lib/load.php index 368d7b87117c9..5d1933c16738e 100644 --- a/lib/load.php +++ b/lib/load.php @@ -121,10 +121,10 @@ function gutenberg_is_experiment_enabled( $name ) { require __DIR__ . '/global-styles.php'; require __DIR__ . '/pwa.php'; -// Copied package PHP files . -if ( file_exists( __DIR__ . '/style-engine/class-wp-style-engine-gutenberg.php' ) ) { - require __DIR__ . '/style-engine/class-wp-style-engine-gutenberg.php'; -} +// TODO: Before this PR merges, move this to be a part of the style engine package. +// Part of the build process should be to copy the PHP file to the correct location, +// similar to the loading behaviour in `blocks.php`. +require __DIR__ . '/style-engine/class-wp-style-engine-gutenberg.php'; require __DIR__ . '/block-supports/elements.php'; require __DIR__ . '/block-supports/colors.php'; diff --git a/packages/style-engine/class-wp-style-engine.php b/lib/style-engine/class-wp-style-engine-gutenberg.php similarity index 80% rename from packages/style-engine/class-wp-style-engine.php rename to lib/style-engine/class-wp-style-engine-gutenberg.php index 0b2770625fc06..d80ed2e0440e0 100644 --- a/packages/style-engine/class-wp-style-engine.php +++ b/lib/style-engine/class-wp-style-engine-gutenberg.php @@ -1,13 +1,13 @@ get_block_style_css_rules( $style_value, $options['path'] ) ); } else { // Otherwise build them all. foreach ( self::BLOCK_STYLE_DEFINITIONS_METADATA as $definition_group ) { @@ -104,7 +126,7 @@ public static function generate( $block_styles, $options = array() ) { if ( empty( $style_value ) ) { continue; } - $rules = array_merge( $rules, static::get_block_style_css_rules( $style_value, $style_definition['path'] ) ); + $rules = array_merge( $rules, $this->get_block_style_css_rules( $style_value, $style_definition['path'] ) ); } } } @@ -132,7 +154,7 @@ public static function generate( $block_styles, $options = array() ) { * * @return array The class name for the added style. */ - protected static function get_css_box_rules( $style_value, $style_property ) { + public static function get_css_box_rules( $style_value, $style_property ) { $rules = array(); if ( ! $style_value ) { diff --git a/phpunit/style-engine/class-wp-style-engine-gutenberg-test.php b/phpunit/style-engine/class-wp-style-engine-gutenberg-test.php index 3c422758e80bf..a3e017d0b8744 100644 --- a/phpunit/style-engine/class-wp-style-engine-gutenberg-test.php +++ b/phpunit/style-engine/class-wp-style-engine-gutenberg-test.php @@ -16,7 +16,8 @@ class WP_Style_Engine_Gutenberg_Test extends WP_UnitTestCase { * @dataProvider data_block_styles_fixtures */ function test_generate_css( $block_styles, $options, $expected_output ) { - $generated_styles = WP_Style_Engine_Gutenberg::generate( + $style_engine = WP_Style_Engine_Gutenberg::get_instance(); + $generated_styles = $style_engine->generate( $block_styles, $options ); diff --git a/tools/webpack/packages.js b/tools/webpack/packages.js index b2781379159af..4d02b4b6e2f81 100644 --- a/tools/webpack/packages.js +++ b/tools/webpack/packages.js @@ -26,15 +26,6 @@ const BUNDLED_PACKAGES = [ '@wordpress/style-engine', ]; -// PHP files in packages that have to be copied over to /lib. -const BUNDLED_PACKAGES_PHP = [ - { - from: './packages/style-engine/', - to: 'lib/style-engine/', - replaceClasses: [ 'WP_Style_Engine' ], - }, -]; - const gutenbergPackages = Object.keys( dependencies ) .filter( ( packageName ) => @@ -108,38 +99,15 @@ module.exports = { ...plugins, new DependencyExtractionWebpackPlugin( { injectPolyfill: true } ), new CopyWebpackPlugin( { - patterns: [].concat( - gutenbergPackages.map( ( packageName ) => ( { + patterns: gutenbergPackages + .map( ( packageName ) => ( { from: '*.css', + context: `./packages/${ packageName }/build-style`, to: `./build/${ packageName }`, transform: stylesTransform, noErrorOnMissing: true, - } ) ), - // Packages with PHP files to be parsed and copied to ./lib. - BUNDLED_PACKAGES_PHP.map( - ( { from, to, replaceClasses } ) => ( { - from: `${ from }/*.php`, - to: ( { absoluteFilename } ) => { - const [ , filename ] = absoluteFilename.match( - /([\w-]+)(\.php){1,1}$/ - ); - return join( to, `${ filename }-gutenberg.php` ); - }, - transform: ( content ) => { - const classSuffix = '_Gutenberg'; - content = content.toString(); - // Replace class names. - content = content.replace( - new RegExp( replaceClasses.join( '|' ), 'g' ), - ( match ) => `${ match }${ classSuffix }` - ); - return content; - }, - noErrorOnMissing: true, - } ) - ), - vendorsCopyConfig - ), + } ) ) + .concat( vendorsCopyConfig ), } ), ].filter( Boolean ), }; From bf9f4448b66862bc10340518ea909cd124de77c4 Mon Sep 17 00:00:00 2001 From: Ramon Date: Fri, 25 Mar 2022 14:51:26 +1100 Subject: [PATCH 12/12] Apply suggestions from code review - update comments Co-authored-by: Andrew Serong <14988353+andrewserong@users.noreply.github.com> --- lib/load.php | 2 +- phpunit/style-engine/class-wp-style-engine-gutenberg-test.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/load.php b/lib/load.php index 5d1933c16738e..b72686b1f4c42 100644 --- a/lib/load.php +++ b/lib/load.php @@ -121,7 +121,7 @@ function gutenberg_is_experiment_enabled( $name ) { require __DIR__ . '/global-styles.php'; require __DIR__ . '/pwa.php'; -// TODO: Before this PR merges, move this to be a part of the style engine package. +// TODO: Move this to be loaded from the style engine package, via the build directory. // Part of the build process should be to copy the PHP file to the correct location, // similar to the loading behaviour in `blocks.php`. require __DIR__ . '/style-engine/class-wp-style-engine-gutenberg.php'; diff --git a/phpunit/style-engine/class-wp-style-engine-gutenberg-test.php b/phpunit/style-engine/class-wp-style-engine-gutenberg-test.php index a3e017d0b8744..6407d6e74ea37 100644 --- a/phpunit/style-engine/class-wp-style-engine-gutenberg-test.php +++ b/phpunit/style-engine/class-wp-style-engine-gutenberg-test.php @@ -3,7 +3,7 @@ * Tests the Style Engine class and associated functionality. * * @package Gutenberg - * @subpackage block-library + * @subpackage style-engine */ /**