From 5958faab8a64e558f48f5bc76d5c933938c51f8a Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Fri, 24 May 2024 18:05:12 +1000
Subject: [PATCH 01/52] Fix list block's has-background padding
---
packages/block-library/src/list/style.scss | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/packages/block-library/src/list/style.scss b/packages/block-library/src/list/style.scss
index badf1b9e560ebd..11f7c4888a5eff 100644
--- a/packages/block-library/src/list/style.scss
+++ b/packages/block-library/src/list/style.scss
@@ -1,8 +1,8 @@
ol,
ul {
box-sizing: border-box;
+}
- &.has-background {
- padding: $block-bg-padding--v $block-bg-padding--h;
- }
+:root :where(ul.has-background, ol.has-background) {
+ padding: $block-bg-padding--v $block-bg-padding--h;
}
From 23537e64f2e549cea010bf35a99fde251f069994 Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Fri, 24 May 2024 18:05:26 +1000
Subject: [PATCH 02/52] Fix paragraph block's has-padding style
---
packages/block-library/src/paragraph/style.scss | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/packages/block-library/src/paragraph/style.scss b/packages/block-library/src/paragraph/style.scss
index 34960bdb2fd589..7bd8c77e85de83 100644
--- a/packages/block-library/src/paragraph/style.scss
+++ b/packages/block-library/src/paragraph/style.scss
@@ -38,7 +38,8 @@ p.has-drop-cap.has-background {
overflow: hidden;
}
-p.has-background {
+// Specificity is reduced to 0-1-0 so global styles can override this.
+:root :where(p.has-background) {
padding: $block-bg-padding--v $block-bg-padding--h;
}
From 16de34e6cccf7e3df13e77dda84a519b33227e71 Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Tue, 9 Apr 2024 13:34:38 +1000
Subject: [PATCH 03/52] Make global styles data available in block editor
---
lib/block-editor-settings.php | 1 +
.../class-wp-rest-block-editor-settings-controller.php | 2 +-
.../editor/src/components/provider/use-block-editor-settings.js | 1 +
3 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/lib/block-editor-settings.php b/lib/block-editor-settings.php
index 53668e114e04cb..ba726ffe2ad5b9 100644
--- a/lib/block-editor-settings.php
+++ b/lib/block-editor-settings.php
@@ -78,6 +78,7 @@ function gutenberg_get_block_editor_settings( $settings ) {
$settings['styles'] = array_merge( $global_styles, get_block_editor_theme_styles() );
+ $settings['__experimentalStyles'] = gutenberg_get_global_styles();
$settings['__experimentalFeatures'] = gutenberg_get_global_settings();
// These settings may need to be updated based on data coming from theme.json sources.
if ( isset( $settings['__experimentalFeatures']['color']['palette'] ) ) {
diff --git a/lib/experimental/class-wp-rest-block-editor-settings-controller.php b/lib/experimental/class-wp-rest-block-editor-settings-controller.php
index 2c4bf29bc21a73..2d0537ca0891c9 100644
--- a/lib/experimental/class-wp-rest-block-editor-settings-controller.php
+++ b/lib/experimental/class-wp-rest-block-editor-settings-controller.php
@@ -155,7 +155,7 @@ public function get_item_schema() {
'__experimentalStyles' => array(
'description' => __( 'Styles consolidated from core, theme, and user origins.', 'gutenberg' ),
'type' => 'object',
- 'context' => array( 'mobile' ),
+ 'context' => array( 'post-editor', 'site-editor', 'widgets-editor', 'mobile' ),
),
'__experimentalEnableQuoteBlockV2' => array(
diff --git a/packages/editor/src/components/provider/use-block-editor-settings.js b/packages/editor/src/components/provider/use-block-editor-settings.js
index 2917c6905e3f0d..bf0f6159f2ff96 100644
--- a/packages/editor/src/components/provider/use-block-editor-settings.js
+++ b/packages/editor/src/components/provider/use-block-editor-settings.js
@@ -41,6 +41,7 @@ const BLOCK_EDITOR_SETTINGS = [
'__experimentalBlockDirectory',
'__experimentalDiscussionSettings',
'__experimentalFeatures',
+ '__experimentalStyles',
'__experimentalGlobalStylesBaseStyles',
'__unstableGalleryWithImageBlocks',
'alignWide',
From 6549ff35308669247a95b411bfd9013a4d669e49 Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Tue, 9 Apr 2024 13:57:32 +1000
Subject: [PATCH 04/52] Update util to retrieve style variations from specified
directory
---
lib/class-wp-theme-json-resolver-gutenberg.php | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/lib/class-wp-theme-json-resolver-gutenberg.php b/lib/class-wp-theme-json-resolver-gutenberg.php
index 0d6aa7bd73fd3a..95ca466140e23f 100644
--- a/lib/class-wp-theme-json-resolver-gutenberg.php
+++ b/lib/class-wp-theme-json-resolver-gutenberg.php
@@ -720,14 +720,17 @@ private static function recursively_iterate_json( $dir ) {
* Returns the style variations defined by the theme (parent and child).
*
* @since 6.2.0 Returns parent theme variations if theme is a child.
+ * @since 6.6.0 Added configurable directory to allow block style variations
+ * to reside in a different directory to theme style variations.
*
+ * @param string $dir Directory to search for variation partials.
* @return array
*/
- public static function get_style_variations() {
+ public static function get_style_variations( $dir = 'styles' ) {
$variation_files = array();
$variations = array();
- $base_directory = get_stylesheet_directory() . '/styles';
- $template_directory = get_template_directory() . '/styles';
+ $base_directory = get_stylesheet_directory() . '/' . $dir;
+ $template_directory = get_template_directory() . '/' . $dir;
if ( is_dir( $base_directory ) ) {
$variation_files = static::recursively_iterate_json( $base_directory );
}
From 7ea4780c4f498d16d1ca470be245ad46fb99feaa Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Tue, 9 Apr 2024 14:07:47 +1000
Subject: [PATCH 05/52] Add filters to resolve shared block style variation
definitions
---
lib/block-supports/variations.php | 184 ++++++++++++++++++++++++++++++
lib/load.php | 1 +
2 files changed, 185 insertions(+)
create mode 100644 lib/block-supports/variations.php
diff --git a/lib/block-supports/variations.php b/lib/block-supports/variations.php
new file mode 100644
index 00000000000000..5ae717ba59245f
--- /dev/null
+++ b/lib/block-supports/variations.php
@@ -0,0 +1,184 @@
+ $variation ) {
+ $supported_blocks = $variation['supportedBlockTypes'] ?? array();
+
+ /*
+ * Standalone theme.json partial files for block style variations
+ * will have their styles under a top-level property by the same name.
+ * Variations defined within an existing theme.json or theme style
+ * variation will themselves already be the required styles data.
+ */
+ $variation_data = $variation['styles'] ?? $variation;
+
+ /*
+ * Block style variations read in via standalone theme.json partials
+ * need to have their name set to the kebab case version of their title.
+ */
+ $variation_name = $have_named_variations ? $key : _wp_to_kebab_case( $variation['title'] );
+
+ if ( empty( $variation_data ) ) {
+ continue;
+ }
+
+ foreach ( $supported_blocks as $block_type ) {
+ $registered_styles = $registry->get_registered_styles_for_block( $block_type );
+
+ if ( ! array_key_exists( $variation_name, $registered_styles ) ) {
+ gutenberg_register_block_style(
+ $block_type,
+ array(
+ 'name' => $variation_name,
+ 'label' => $variation['title'] ?? $variation_name,
+ )
+ );
+ }
+
+ $path = array( $block_type, 'variations', $variation_name );
+ _wp_array_set( $variations_data, $path, $variation_data );
+ }
+ }
+
+ return $variations_data;
+}
+
+/**
+ * Merges variations data with existing theme.json data ensuring that the
+ * current theme.json data values take precedence.
+ *
+ * @param array $variations_data Block style variations data keyed by block type.
+ * @param WP_Theme_JSON_Data_Gutenberg $theme_json Current theme.json data.
+ * @param string $origin Origin for the theme.json data.
+ *
+ * @return WP_Theme_JSON_Gutenberg The merged theme.json data.
+ */
+function gutenberg_merge_block_style_variations_data( $variations_data, $theme_json, $origin = 'theme' ) {
+ if ( empty( $variations_data ) ) {
+ return $theme_json;
+ }
+
+ $variations_theme_json_data = array(
+ 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
+ 'styles' => array( 'blocks' => $variations_data ),
+ );
+
+ $variations_theme_json = new WP_Theme_JSON_Data_Gutenberg( $variations_theme_json_data, $origin );
+
+ /*
+ * Merge the current theme.json data over shared variation data so that
+ * any explicit per block variation values take precedence.
+ */
+ return $variations_theme_json->update_with( $theme_json->get_data() );
+}
+
+/**
+ * Merges any shared block style variation definitions from a theme style
+ * variation into their appropriate block type within theme json styles. Any
+ * custom user selections already made will take precedence over the shared
+ * style variation value.
+ *
+ * @param WP_Theme_JSON_Data_Gutenberg $theme_json Current theme.json data.
+ *
+ * @return WP_Theme_JSON_Data_Gutenberg
+ */
+function gutenberg_resolve_block_style_variations_from_theme_style_variation( $theme_json ) {
+ $theme_json_data = $theme_json->get_data();
+ $shared_variations = $theme_json_data['styles']['blocks']['variations'] ?? array();
+ $variations_data = gutenberg_resolve_and_register_block_style_variations( $shared_variations );
+
+ return gutenberg_merge_block_style_variations_data( $variations_data, $theme_json, 'user' );
+}
+
+/**
+ * Merges block style variation data sourced from standalone partial
+ * theme.json files.
+ *
+ * @param WP_Theme_JSON_Data_Gutenberg $theme_json Current theme.json data.
+ *
+ * @return WP_Theme_JSON_Data_Gutenberg
+ */
+function gutenberg_resolve_block_style_variations_from_theme_json_partials( $theme_json ) {
+ $block_style_variations = WP_Theme_JSON_Resolver_Gutenberg::get_style_variations( '/block-styles' );
+ $variations_data = gutenberg_resolve_and_register_block_style_variations( $block_style_variations );
+
+ return gutenberg_merge_block_style_variations_data( $variations_data, $theme_json );
+}
+
+/**
+ * Merges shared block style variations registered within the
+ * `styles.blocks.variations` property of the primary theme.json file.
+ *
+ * @param WP_Theme_JSON_Data_Gutenberg $theme_json Current theme.json data.
+ *
+ * @return WP_Theme_JSON_Data_Gutenberg
+ */
+function gutenberg_resolve_block_style_variations_from_primary_theme_json( $theme_json ) {
+ $theme_json_data = $theme_json->get_data();
+ $block_style_variations = $theme_json_data['styles']['blocks']['variations'] ?? array();
+ $variations_data = gutenberg_resolve_and_register_block_style_variations( $block_style_variations );
+
+ return gutenberg_merge_block_style_variations_data( $variations_data, $theme_json );
+}
+
+/**
+ * Merges block style variations registered via the block styles registry with a
+ * style object, under their appropriate block types within theme.json styles.
+ * Any variation values defined within the theme.json specific to a block type
+ * will take precedence over these shared definitions.
+ *
+ * @param WP_Theme_JSON_Data_Gutenberg $theme_json Current theme.json data.
+ *
+ * @return WP_Theme_JSON_Data_Gutenberg
+ */
+function gutenberg_resolve_block_style_variations_from_styles_registry( $theme_json ) {
+ $registry = WP_Block_Styles_Registry::get_instance();
+ $styles = $registry->get_all_registered();
+ $variations_data = array();
+
+ foreach ( $styles as $block_type => $variations ) {
+ foreach ( $variations as $variation_name => $variation ) {
+ if ( ! empty( $variation['style_data'] ) ) {
+ $path = array( $block_type, 'variations', $variation_name );
+ _wp_array_set( $variations_data, $path, $variation['style_data'] );
+ }
+ }
+ }
+
+ return gutenberg_merge_block_style_variations_data( $variations_data, $theme_json );
+}
+
+// Register the block support.
+WP_Block_Supports::get_instance()->register( 'variation', array() );
+
+// Resolve block style variations from all their potential sources. The order here is deliberate.
+add_filter( 'wp_theme_json_data_theme', 'gutenberg_resolve_block_style_variations_from_primary_theme_json', 10, 1 );
+add_filter( 'wp_theme_json_data_theme', 'gutenberg_resolve_block_style_variations_from_theme_json_partials', 10, 1 );
+add_filter( 'wp_theme_json_data_theme', 'gutenberg_resolve_block_style_variations_from_styles_registry', 10, 1 );
+
+add_filter( 'wp_theme_json_data_user', 'gutenberg_resolve_block_style_variations_from_theme_style_variation', 10, 1 );
diff --git a/lib/load.php b/lib/load.php
index 357935b4137794..5b0c8fd64ab902 100644
--- a/lib/load.php
+++ b/lib/load.php
@@ -232,6 +232,7 @@ function gutenberg_is_experiment_enabled( $name ) {
require __DIR__ . '/block-supports/duotone.php';
require __DIR__ . '/block-supports/shadow.php';
require __DIR__ . '/block-supports/background.php';
+require __DIR__ . '/block-supports/variations.php';
// Data views.
require_once __DIR__ . '/experimental/data-views.php';
From 93fa1f87c19685f93258e89446f22c58d6dbf0de Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Tue, 9 Apr 2024 14:16:52 +1000
Subject: [PATCH 06/52] Add new top-level theme.json property to identify
supported block types for style variations
---
lib/class-wp-theme-json-gutenberg.php | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php
index 75b9ef60ff1fc8..3d459cadd3b3cf 100644
--- a/lib/class-wp-theme-json-gutenberg.php
+++ b/lib/class-wp-theme-json-gutenberg.php
@@ -353,6 +353,7 @@ class WP_Theme_JSON_Gutenberg {
'patterns',
'settings',
'styles',
+ 'supportedBlockTypes',
'templateParts',
'title',
'version',
From 2c73a6220daa5feaea524ed4757288f64d762e37 Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Tue, 9 Apr 2024 14:21:39 +1000
Subject: [PATCH 07/52] Support skipping root layout styles from theme.json
stylesheet generation
---
lib/class-wp-theme-json-gutenberg.php | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php
index 3d459cadd3b3cf..65a976b93bc26f 100644
--- a/lib/class-wp-theme-json-gutenberg.php
+++ b/lib/class-wp-theme-json-gutenberg.php
@@ -1175,8 +1175,10 @@ public function get_settings() {
* - `presets`: only the classes for the presets.
* @param array $origins A list of origins to include. By default it includes VALID_ORIGINS.
* @param array $options An array of options for now used for internal purposes only (may change without notice).
- * The options currently supported are 'scope' that makes sure all style are scoped to a given selector,
- * and root_selector which overwrites and forces a given selector to be used on the root node.
+ * The options currently supported are:
+ * - 'scope' that makes sure all style are scoped to a given selector
+ * - `root_selector` which overwrites and forces a given selector to be used on the root node
+ * - `skip_root_layout_styles` which omits root layout styles from the generated stylesheet.
* @return string The resulting stylesheet.
*/
public function get_stylesheet( $types = array( 'variables', 'styles', 'presets' ), $origins = null, $options = array() ) {
@@ -1229,7 +1231,7 @@ public function get_stylesheet( $types = array( 'variables', 'styles', 'presets'
}
if ( in_array( 'styles', $types, true ) ) {
- if ( false !== $root_style_key ) {
+ if ( false !== $root_style_key && empty( $options['skip_root_layout_styles'] ) ) {
$stylesheet .= $this->get_root_layout_rules( $style_nodes[ $root_style_key ]['selector'], $style_nodes[ $root_style_key ] );
}
$stylesheet .= $this->get_block_classes( $style_nodes );
From 3af0d247fe73595946f59a44b3e6fc91c5a48f08 Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Tue, 9 Apr 2024 14:30:29 +1000
Subject: [PATCH 08/52] Add variations from block style registry to block
metadata in theme.json
---
lib/class-wp-theme-json-gutenberg.php | 34 ++++++++++++++++++++++++---
1 file changed, 31 insertions(+), 3 deletions(-)
diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php
index 65a976b93bc26f..c4e5f6ace99b75 100644
--- a/lib/class-wp-theme-json-gutenberg.php
+++ b/lib/class-wp-theme-json-gutenberg.php
@@ -1014,12 +1014,31 @@ protected static function prepend_to_selector( $selector, $to_prepend ) {
*/
protected static function get_blocks_metadata() {
// NOTE: the compat/6.1 version of this method in Gutenberg did not have these changes.
- $registry = WP_Block_Type_Registry::get_instance();
- $blocks = $registry->get_all_registered();
+ $registry = WP_Block_Type_Registry::get_instance();
+ $blocks = $registry->get_all_registered();
+ $style_registry = WP_Block_Styles_Registry::get_instance();
// Is there metadata for all currently registered blocks?
$blocks = array_diff_key( $blocks, static::$blocks_metadata );
if ( empty( $blocks ) ) {
+ /*
+ * New block styles may have been registered within WP_Block_Styles_Registry.
+ * Update block metadata for any new block style variations.
+ */
+ $registered_styles = $style_registry->get_all_registered();
+ foreach ( static::$blocks_metadata as $block_name => $block_metadata ) {
+ if ( ! empty( $registered_styles[ $block_name ] ) ) {
+ $style_selectors = $block_metadata['styleVariations'] ?? array();
+
+ foreach ( $registered_styles[ $block_name ] as $block_style ) {
+ if ( ! isset( $style_selectors[ $block_style['name'] ] ) ) {
+ $style_selectors[ $block_style['name'] ] = static::get_block_style_variation_selector( $block_style['name'], $block_metadata['selector'] );
+ }
+ }
+
+ static::$blocks_metadata[ $block_name ]['styleVariations'] = $style_selectors;
+ }
+ }
return static::$blocks_metadata;
}
@@ -1052,11 +1071,20 @@ protected static function get_blocks_metadata() {
}
// If the block has style variations, append their selectors to the block metadata.
+ $style_selectors = array();
if ( ! empty( $block_type->styles ) ) {
- $style_selectors = array();
foreach ( $block_type->styles as $style ) {
$style_selectors[ $style['name'] ] = static::get_block_style_variation_selector( $style['name'], static::$blocks_metadata[ $block_name ]['selector'] );
}
+ }
+
+ // Block style variations can be registered through the WP_Block_Styles_Registry as well as block.json.
+ $registered_styles = $style_registry->get_registered_styles_for_block( $block_name );
+ foreach ( $registered_styles as $style ) {
+ $style_selectors[ $style['name'] ] = static::get_block_style_variation_selector( $style['name'], static::$blocks_metadata[ $block_name ]['selector'] );
+ }
+
+ if ( ! empty( $style_selectors ) ) {
static::$blocks_metadata[ $block_name ]['styleVariations'] = $style_selectors;
}
}
From d966c388daed5084045989b93e032369e5833dd2 Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Tue, 9 Apr 2024 14:38:25 +1000
Subject: [PATCH 09/52] Update theme.json sanitization to support extended
block style variations
---
lib/class-wp-theme-json-gutenberg.php | 32 +++++++++++++++++++++++----
1 file changed, 28 insertions(+), 4 deletions(-)
diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php
index c4e5f6ace99b75..d1da933642e3ac 100644
--- a/lib/class-wp-theme-json-gutenberg.php
+++ b/lib/class-wp-theme-json-gutenberg.php
@@ -875,6 +875,27 @@ protected static function sanitize( $input, $valid_block_names, $valid_element_n
$schema_styles_blocks = array();
$schema_settings_blocks = array();
+
+ /*
+ * Generate a schema for blocks.
+ * - Block styles can contain `elements` & `variations` definitions.
+ * - Variations definitions cannot be nested.
+ * - Variations can contain styles for inner `blocks`.
+ * - Variation inner `blocks` styles can contain `elements`.
+ *
+ * As each variation needs a `blocks` schema but further nested
+ * inner `blocks`, the overall schema will be generated in multiple passes.
+ */
+ foreach ( $valid_block_names as $block ) {
+ $schema_settings_blocks[ $block ] = static::VALID_SETTINGS;
+ $schema_styles_blocks[ $block ] = $styles_non_top_level;
+ $schema_styles_blocks[ $block ]['elements'] = $schema_styles_elements;
+ }
+
+ $block_style_variation_styles = static::VALID_STYLES;
+ $block_style_variation_styles['blocks'] = $schema_styles_blocks;
+ $block_style_variation_styles['elements'] = $schema_styles_elements;
+
foreach ( $valid_block_names as $block ) {
// Build the schema for each block style variation.
$style_variation_names = array();
@@ -891,12 +912,9 @@ protected static function sanitize( $input, $valid_block_names, $valid_element_n
$schema_styles_variations = array();
if ( ! empty( $style_variation_names ) ) {
- $schema_styles_variations = array_fill_keys( $style_variation_names, $styles_non_top_level );
+ $schema_styles_variations = array_fill_keys( $style_variation_names, $block_style_variation_styles );
}
- $schema_settings_blocks[ $block ] = static::VALID_SETTINGS;
- $schema_styles_blocks[ $block ] = $styles_non_top_level;
- $schema_styles_blocks[ $block ]['elements'] = $schema_styles_elements;
$schema_styles_blocks[ $block ]['variations'] = $schema_styles_variations;
}
@@ -907,6 +925,12 @@ protected static function sanitize( $input, $valid_block_names, $valid_element_n
$schema['settings']['blocks'] = $schema_settings_blocks;
$schema['settings']['typography']['fontFamilies'] = static::schema_in_root_and_per_origin( static::FONT_FAMILY_SCHEMA );
+ /*
+ * Shared block style variations can be registered from the theme.json data so we can't
+ * validate them against pre-registered block style variations.
+ */
+ $schema['styles']['blocks']['variations'] = null;
+
// Remove anything that's not present in the schema.
foreach ( array( 'styles', 'settings' ) as $subtree ) {
if ( ! isset( $input[ $subtree ] ) ) {
From daa82d3c7b1d0d22567ee6dfd4a4e20d5fc26d60 Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Tue, 9 Apr 2024 14:40:41 +1000
Subject: [PATCH 10/52] Prevent block style variation element styles from being
removed for users without unfiltered html caps
---
lib/class-wp-theme-json-gutenberg.php | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php
index d1da933642e3ac..e5c6a1b12134f9 100644
--- a/lib/class-wp-theme-json-gutenberg.php
+++ b/lib/class-wp-theme-json-gutenberg.php
@@ -3279,6 +3279,29 @@ public static function remove_insecure_properties( $theme_json ) {
}
$variation_output = static::remove_insecure_styles( $variation_input );
+
+ // Process a variation's elements and element pseudo selector styles.
+ if ( isset( $variation_input['elements'] ) ) {
+ foreach ( $valid_element_names as $element_name ) {
+ $element_input = $variation_input['elements'][ $element_name ] ?? null;
+ if ( $element_input ) {
+ $element_output = static::remove_insecure_styles( $element_input );
+
+ if ( isset( static::VALID_ELEMENT_PSEUDO_SELECTORS[ $element_name ] ) ) {
+ foreach ( static::VALID_ELEMENT_PSEUDO_SELECTORS[ $element_name ] as $pseudo_selector ) {
+ if ( isset( $element_input[ $pseudo_selector ] ) ) {
+ $element_output[ $pseudo_selector ] = static::remove_insecure_styles( $element_input[ $pseudo_selector ] );
+ }
+ }
+ }
+
+ if ( ! empty( $element_output ) ) {
+ _wp_array_set( $variation_output, array( 'elements', $element_name ), $element_output );
+ }
+ }
+ }
+ }
+
if ( ! empty( $variation_output ) ) {
_wp_array_set( $sanitized, $variation['path'], $variation_output );
}
From 6274c28c43013db85ca76ecab0815238518a8f91 Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Tue, 9 Apr 2024 14:55:28 +1000
Subject: [PATCH 11/52] Resolve user origin shared block style variation
definitions e.g. from theme style variation
Add setNestedValue util to editor package
---
.../global-styles-provider/index.js | 51 +++++++++++++++++--
packages/editor/src/utils/set-nested-value.js | 39 ++++++++++++++
2 files changed, 85 insertions(+), 5 deletions(-)
create mode 100644 packages/editor/src/utils/set-nested-value.js
diff --git a/packages/editor/src/components/global-styles-provider/index.js b/packages/editor/src/components/global-styles-provider/index.js
index 9e4ba24e7311fe..e06cae27f16058 100644
--- a/packages/editor/src/components/global-styles-provider/index.js
+++ b/packages/editor/src/components/global-styles-provider/index.js
@@ -16,6 +16,7 @@ import { useMemo, useCallback } from '@wordpress/element';
* Internal dependencies
*/
import { unlock } from '../../lock-unlock';
+import setNestedValue from '../../utils/set-nested-value';
const { GlobalStylesContext, cleanEmptyObject } = unlock(
blockEditorPrivateApis
@@ -30,6 +31,37 @@ export function mergeBaseAndUserConfigs( base, user ) {
} );
}
+function resolveBlockStyleVariations( userConfig ) {
+ const sharedVariations = userConfig.styles?.blocks?.variations;
+
+ if ( ! sharedVariations ) {
+ return userConfig;
+ }
+
+ const variationsConfig = JSON.parse( JSON.stringify( userConfig ) );
+
+ Object.entries( sharedVariations ).forEach(
+ ( [ variationName, variation ] ) => {
+ if ( ! variation?.supportedBlockTypes ) {
+ return;
+ }
+
+ variation.supportedBlockTypes.forEach( ( blockName ) => {
+ const path = [
+ 'styles',
+ 'blocks',
+ blockName,
+ 'variations',
+ variationName,
+ ];
+ setNestedValue( variationsConfig, path, variation );
+ } );
+ }
+ );
+
+ return deepmerge( variationsConfig, userConfig );
+}
+
function useGlobalStylesUserConfig() {
const { globalStylesId, isReady, settings, styles, _links } = useSelect(
( select ) => {
@@ -128,24 +160,33 @@ export function useGlobalStylesContext() {
const [ isUserConfigReady, userConfig, setUserConfig ] =
useGlobalStylesUserConfig();
const [ isBaseConfigReady, baseConfig ] = useGlobalStylesBaseConfig();
+
+ const userConfigWithVariations = useMemo( () => {
+ if ( ! userConfig ) {
+ return userConfig;
+ }
+ return resolveBlockStyleVariations( userConfig );
+ }, [ userConfig ] );
+
const mergedConfig = useMemo( () => {
- if ( ! baseConfig || ! userConfig ) {
+ if ( ! baseConfig || ! userConfigWithVariations ) {
return {};
}
- return mergeBaseAndUserConfigs( baseConfig, userConfig );
- }, [ userConfig, baseConfig ] );
+
+ return mergeBaseAndUserConfigs( baseConfig, userConfigWithVariations );
+ }, [ userConfigWithVariations, baseConfig ] );
const context = useMemo( () => {
return {
isReady: isUserConfigReady && isBaseConfigReady,
- user: userConfig,
+ user: userConfigWithVariations,
base: baseConfig,
merged: mergedConfig,
setUserConfig,
};
}, [
mergedConfig,
- userConfig,
+ userConfigWithVariations,
baseConfig,
setUserConfig,
isUserConfigReady,
diff --git a/packages/editor/src/utils/set-nested-value.js b/packages/editor/src/utils/set-nested-value.js
new file mode 100644
index 00000000000000..ec684e751cd041
--- /dev/null
+++ b/packages/editor/src/utils/set-nested-value.js
@@ -0,0 +1,39 @@
+/**
+ * Sets the value at path of object.
+ * If a portion of path doesn’t exist, it’s created.
+ * Arrays are created for missing index properties while objects are created
+ * for all other missing properties.
+ *
+ * This function intentionally mutates the input object.
+ *
+ * Inspired by _.set().
+ *
+ * @see https://lodash.com/docs/4.17.15#set
+ *
+ * @todo Needs to be deduplicated with its copy in `@wordpress/core-data`.
+ *
+ * @param {Object} object Object to modify
+ * @param {Array} path Path of the property to set.
+ * @param {*} value Value to set.
+ */
+export default function setNestedValue( object, path, value ) {
+ if ( ! object || typeof object !== 'object' ) {
+ return object;
+ }
+
+ path.reduce( ( acc, key, idx ) => {
+ if ( acc[ key ] === undefined ) {
+ if ( Number.isInteger( path[ idx + 1 ] ) ) {
+ acc[ key ] = [];
+ } else {
+ acc[ key ] = {};
+ }
+ }
+ if ( idx === path.length - 1 ) {
+ acc[ key ] = value;
+ }
+ return acc[ key ];
+ }, object );
+
+ return object;
+}
From cf79868f89bf7e6ee6b2649a8c66ee71cabe628b Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Tue, 9 Apr 2024 18:31:51 +1000
Subject: [PATCH 12/52] Update theme.json schema for extended block style
variations
---
schemas/json/theme.json | 416 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 413 insertions(+), 3 deletions(-)
diff --git a/schemas/json/theme.json b/schemas/json/theme.json
index 1443685ff83cb6..f58214c6f774c4 100644
--- a/schemas/json/theme.json
+++ b/schemas/json/theme.json
@@ -1927,6 +1927,9 @@
"stylesBlocksPropertiesComplete": {
"type": "object",
"properties": {
+ "variations": {
+ "$ref": "#/definitions/stylesBlocksSharedVariationProperties"
+ },
"core/archives": {
"$ref": "#/definitions/stylesPropertiesAndElementsComplete"
},
@@ -2250,20 +2253,420 @@
"$ref": "#/definitions/stylesElementsPropertiesComplete"
},
"variations": {
- "$ref": "#/definitions/stylesVariationPropertiesComplete"
+ "$ref": "#/definitions/stylesVariationsPropertiesComplete"
}
},
"additionalProperties": false
}
]
},
- "stylesVariationPropertiesComplete": {
+ "stylesBlocksSharedVariationProperties": {
"type": "object",
"patternProperties": {
"^[a-z][a-z0-9-]*$": {
- "$ref": "#/definitions/stylesPropertiesComplete"
+ "$ref": "#/definitions/stylesSharedVariationProperties"
+ }
+ }
+ },
+ "stylesSharedVariationProperties": {
+ "type": "object",
+ "allOf": [
+ {
+ "$ref": "#/definitions/stylesProperties"
+ },
+ {
+ "properties": {
+ "supportedBlockTypes": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "border": {},
+ "color": {},
+ "dimensions": {},
+ "spacing": {},
+ "typography": {},
+ "filter": {},
+ "shadow": {},
+ "outline": {},
+ "css": {},
+ "elements": {
+ "$ref": "#/definitions/stylesElementsPropertiesComplete"
+ },
+ "blocks": {
+ "$ref": "#/definitions/stylesVariationBlocksPropertiesComplete"
+ }
+ },
+ "additionalProperties": false
+ }
+ ]
+ },
+ "stylesVariationsPropertiesComplete": {
+ "type": "object",
+ "patternProperties": {
+ "^[a-z][a-z0-9-]*$": {
+ "$ref": "#/definitions/stylesVariationPropertiesComplete"
}
}
+ },
+ "stylesVariationPropertiesComplete": {
+ "type": "object",
+ "allOf": [
+ {
+ "$ref": "#/definitions/stylesProperties"
+ },
+ {
+ "properties": {
+ "border": {},
+ "color": {},
+ "dimensions": {},
+ "spacing": {},
+ "typography": {},
+ "filter": {},
+ "shadow": {},
+ "outline": {},
+ "css": {},
+ "elements": {
+ "$ref": "#/definitions/stylesElementsPropertiesComplete"
+ },
+ "blocks": {
+ "$ref": "#/definitions/stylesVariationBlocksPropertiesComplete"
+ }
+ },
+ "additionalProperties": false
+ }
+ ]
+ },
+ "stylesVariationBlocksPropertiesComplete": {
+ "type": "object",
+ "properties": {
+ "core/archives": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/audio": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/avatar": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/block": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/button": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/buttons": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/calendar": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/categories": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/code": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/column": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/columns": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comment-author-avatar": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comment-author-name": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comment-content": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comment-date": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comment-edit-link": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comment-reply-link": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comments": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comments-pagination": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comments-pagination-next": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comments-pagination-numbers": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comments-pagination-previous": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comments-title": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/comment-template": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/cover": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/details": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/embed": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/file": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/freeform": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/gallery": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/group": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/heading": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/home-link": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/html": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/image": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/latest-comments": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/latest-posts": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/list": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/list-item": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/loginout": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/media-text": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/missing": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/more": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/navigation": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/navigation-link": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/navigation-submenu": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/nextpage": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/page-list": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/page-list-item": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/paragraph": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-author": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-author-biography": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-author-name": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-comment": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-comments-count": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-comments-form": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-comments-link": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-content": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-date": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-excerpt": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-featured-image": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-navigation-link": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-template": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-terms": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-time-to-read": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/post-title": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/preformatted": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/pullquote": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/query": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/query-no-results": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/query-pagination": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/query-pagination-next": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/query-pagination-numbers": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/query-pagination-previous": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/query-title": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/quote": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/read-more": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/rss": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/search": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/separator": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/shortcode": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/site-logo": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/site-tagline": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/site-title": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/social-link": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/social-links": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/spacer": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/table": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/table-of-contents": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/tag-cloud": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/template-part": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/term-description": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/text-columns": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/verse": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/video": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/widget-area": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/legacy-widget": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ },
+ "core/widget-group": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ }
+ },
+ "patternProperties": {
+ "^[a-z][a-z0-9-]*/[a-z][a-z0-9-]*$": {
+ "$ref": "#/definitions/stylesVariationBlockPropertiesComplete"
+ }
+ },
+ "additionalProperties": false
+ },
+ "stylesVariationBlockPropertiesComplete": {
+ "type": "object",
+ "allOf": [
+ {
+ "$ref": "#/definitions/stylesProperties"
+ },
+ {
+ "properties": {
+ "border": {},
+ "color": {},
+ "dimensions": {},
+ "spacing": {},
+ "typography": {},
+ "filter": {},
+ "shadow": {},
+ "outline": {},
+ "css": {},
+ "elements": {
+ "$ref": "#/definitions/stylesElementsPropertiesComplete"
+ }
+ },
+ "additionalProperties": false
+ }
+ ]
}
},
"type": "object",
@@ -2285,6 +2688,13 @@
"type": "string",
"description": "Description of the global styles variation."
},
+ "supportedBlockTypes": {
+ "type": "array",
+ "description": "List of block types that can use the block style variation this theme.json file represents.",
+ "items": {
+ "type": "string"
+ }
+ },
"settings": {
"description": "Settings for the block editor and individual blocks. These include things like:\n- Which customization options should be available to the user. \n- The default colors, font sizes... available to the user. \n- CSS custom properties and class names used in styles.\n- And the default layout of the editor (widths and available alignments).",
"type": "object",
From 24b14fa5226fb139834c7381126c028d1d558c9b Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Tue, 9 Apr 2024 15:00:05 +1000
Subject: [PATCH 13/52] Allow non-core block style variations in global styles
variations panel
---
.../variations/variations-panel.js | 21 ++++++++++++++-----
1 file changed, 16 insertions(+), 5 deletions(-)
diff --git a/packages/edit-site/src/components/global-styles/variations/variations-panel.js b/packages/edit-site/src/components/global-styles/variations/variations-panel.js
index 7e52498e0a4385..6c03821705619f 100644
--- a/packages/edit-site/src/components/global-styles/variations/variations-panel.js
+++ b/packages/edit-site/src/components/global-styles/variations/variations-panel.js
@@ -2,16 +2,25 @@
* WordPress dependencies
*/
import { store as blocksStore } from '@wordpress/blocks';
+import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor';
import { useSelect } from '@wordpress/data';
import { __experimentalItemGroup as ItemGroup } from '@wordpress/components';
+
/**
* Internal dependencies
*/
-
import { NavigationButtonAsItem } from '../navigation-button';
+import { unlock } from '../../../lock-unlock';
+
+const { useGlobalStyle } = unlock( blockEditorPrivateApis );
-function getCoreBlockStyles( blockStyles ) {
- return blockStyles?.filter( ( style ) => style.source === 'block' );
+// Only core block styles (source === block) or block styles with a matching
+// theme.json style variation will be configurable via Global Styles.
+function getFilteredBlockStyles( blockStyles, variations ) {
+ return blockStyles?.filter(
+ ( style ) =>
+ style.source === 'block' || variations.includes( style.name )
+ );
}
export function useBlockVariations( name ) {
@@ -22,8 +31,10 @@ export function useBlockVariations( name ) {
},
[ name ]
);
- const coreBlockStyles = getCoreBlockStyles( blockStyles );
- return coreBlockStyles;
+ const [ variations ] = useGlobalStyle( 'variations', name, 'base' );
+ const variationNames = Object.keys( variations ?? {} );
+
+ return getFilteredBlockStyles( blockStyles, variationNames );
}
export function VariationsPanel( { name } ) {
From 35a1d2ff5dd058ae149619888c06654b0aed6cac Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Tue, 9 Apr 2024 16:02:57 +1000
Subject: [PATCH 14/52] Generate per-application variation styles and enforce
unique classname
---
lib/block-supports/variations.php | 157 ++++++++++++++++++++++++++++++
1 file changed, 157 insertions(+)
diff --git a/lib/block-supports/variations.php b/lib/block-supports/variations.php
index 5ae717ba59245f..3cc6509c6ae034 100644
--- a/lib/block-supports/variations.php
+++ b/lib/block-supports/variations.php
@@ -6,6 +6,152 @@
* @package gutenberg
*/
+/**
+ * Get the class name for this application of this block's variation styles.
+ *
+ * @param array $block Block object.
+ * @param string $variation Slug for the variation.
+ *
+ * @return string The unique class name.
+ */
+function gutenberg_get_variation_class_name( $block, $variation ) {
+ return 'is-style-' . $variation . '--' . md5( serialize( $block ) );
+}
+
+/**
+ * Determine a block style variation name from a CSS class string.
+ *
+ * @param string $class_string CSS class string to look for a variation in.
+ *
+ * @return string|null The variation name if found.
+ */
+function gutenberg_get_variation_name_from_class( $class_string ) {
+ if ( ! is_string( $class_string ) ) {
+ return null;
+ }
+
+ preg_match( '/\bis-style-(?!default)(\S+)\b/', $class_string, $matches );
+ return $matches ? $matches[1] : null;
+}
+
+/**
+ * Render the block style variation's styles.
+ *
+ * In the case of nested blocks with variations applies, we want the parent
+ * variation's styles to be rendered before their descendants. This solves the
+ * issue of a block type being styled in both the parent and descendant: we want
+ * the descendant style to take priority, and this is done by loading it after,
+ * in the DOM order. This is why the variation stylesheet generation is in a
+ * different filter.
+ *
+ * @param array $parsed_block The parsed block.
+ *
+ * @return array The same parsed block with variation classname added if appropriate.
+ */
+function gutenberg_render_variation_support_styles( $parsed_block ) {
+ $classes = $parsed_block['attrs']['className'] ?? null;
+ $variation = gutenberg_get_variation_name_from_class( $classes );
+
+ if ( ! $variation ) {
+ return $parsed_block;
+ }
+
+ $tree = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data();
+ $theme_json = $tree->get_raw_data();
+ $variation_data = $theme_json['styles']['blocks'][ $parsed_block['blockName'] ]['variations'][ $variation ] ?? array();
+
+ if ( empty( $variation_data ) ) {
+ return $parsed_block;
+ }
+
+ $config = array(
+ 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
+ 'styles' => $variation_data,
+ );
+
+ $class_name = gutenberg_get_variation_class_name( $parsed_block, $variation );
+ $updated_class_name = $parsed_block['attrs']['className'] . " $class_name";
+
+ $class_name = ".$class_name";
+
+ if ( ! is_admin() ) {
+ remove_filter( 'wp_theme_json_get_style_nodes', 'wp_filter_out_block_nodes' );
+ }
+
+ $variation_theme_json = new WP_Theme_JSON_Gutenberg( $config, 'blocks' );
+ $variation_styles = $variation_theme_json->get_stylesheet(
+ array( 'styles' ),
+ array( 'custom' ),
+ array(
+ 'root_selector' => $class_name,
+ 'skip_root_layout_styles' => true,
+ 'scope' => $class_name,
+ )
+ );
+
+ if ( ! is_admin() ) {
+ add_filter( 'wp_theme_json_get_style_nodes', 'wp_filter_out_block_nodes' );
+ }
+
+ if ( empty( $variation_styles ) ) {
+ return $parsed_block;
+ }
+
+ wp_register_style( 'variation-styles', false, array( 'global-styles' ) );
+ wp_add_inline_style( 'variation-styles', $variation_styles );
+
+ /*
+ * Add variation instance class name to block's className string so it can
+ * be enforced in the block markup via render_block filter.
+ */
+ _wp_array_set( $parsed_block, array( 'attrs', 'className' ), $updated_class_name );
+
+ return $parsed_block;
+}
+
+/**
+ * Ensure the variation block support class name generated and added to
+ * block attributes in the `render_block_data` filter gets applied to the
+ * block's markup.
+ *
+ * @see gutenberg_render_variation_support_styles
+ *
+ * @param string $block_content Rendered block content.
+ * @param array $block Block object.
+ *
+ * @return string Filtered block content.
+ */
+function gutenberg_render_variation_class_name( $block_content, $block ) {
+ if ( ! $block_content || empty( $block['attrs']['className'] ) ) {
+ return $block_content;
+ }
+
+ /*
+ * Matches a class prefixed by `is-style`, followed by the
+ * variation slug, then `--`, and finally a hash.
+ *
+ * See `gutenberg_get_variation_class_name` for class generation.
+ */
+ preg_match( '/\bis-style-(\S+?--\w+)\b/', $block['attrs']['className'], $matches );
+
+ if ( empty( $matches ) ) {
+ return $block_content;
+ }
+
+ $tags = new WP_HTML_Tag_Processor( $block_content );
+
+ if ( $tags->next_tag() ) {
+ /*
+ * Ensure the variation instance class name set in the
+ * `render_block_data` filter is applied in markup.
+ * See `gutenberg_render_variation_support_styles`.
+ */
+ $tags->add_class( $matches[0] );
+ }
+
+ return $tags->get_updated_html();
+}
+
/**
* Collects block style variation data for merging with theme.json data.
* As each block style variation is processed it is registered if it hasn't
@@ -173,9 +319,20 @@ function gutenberg_resolve_block_style_variations_from_styles_registry( $theme_j
return gutenberg_merge_block_style_variations_data( $variations_data, $theme_json );
}
+/**
+ * Enqueues styles for block style variations.
+ */
+function gutenberg_enqueue_variation_styles() {
+ wp_enqueue_style( 'variation-styles' );
+}
+
// Register the block support.
WP_Block_Supports::get_instance()->register( 'variation', array() );
+add_filter( 'render_block_data', 'gutenberg_render_variation_support_styles', 10, 2 );
+add_filter( 'render_block', 'gutenberg_render_variation_class_name', 10, 2 );
+add_action( 'wp_enqueue_scripts', 'gutenberg_enqueue_variation_styles', 1 );
+
// Resolve block style variations from all their potential sources. The order here is deliberate.
add_filter( 'wp_theme_json_data_theme', 'gutenberg_resolve_block_style_variations_from_primary_theme_json', 10, 1 );
add_filter( 'wp_theme_json_data_theme', 'gutenberg_resolve_block_style_variations_from_theme_json_partials', 10, 1 );
From a1ea2e32d1865f3c7fdad82fa87c1f91a300de56 Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Tue, 9 Apr 2024 16:27:48 +1000
Subject: [PATCH 15/52] Update useGlobalStylesOutput hook's node generation to
support extended block style variations
---
.../global-styles/use-global-styles-output.js | 129 +++++++++++++++++-
1 file changed, 123 insertions(+), 6 deletions(-)
diff --git a/packages/block-editor/src/components/global-styles/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/use-global-styles-output.js
index 06d9400416eebb..1044425468d7b6 100644
--- a/packages/block-editor/src/components/global-styles/use-global-styles-output.js
+++ b/packages/block-editor/src/components/global-styles/use-global-styles-output.js
@@ -614,6 +614,33 @@ function pickStyleKeys( treeToPickFrom ) {
return Object.fromEntries( clonedEntries );
}
+function scopeFeatureSelectors( scope, selectors ) {
+ if ( ! scope || ! selectors ) {
+ return;
+ }
+
+ const featureSelectors = JSON.parse( JSON.stringify( selectors ) );
+
+ Object.entries( selectors ).forEach( ( [ feature, selector ] ) => {
+ if ( typeof selector === 'string' ) {
+ featureSelectors[ feature ] = scopeSelector( scope, selector );
+ }
+
+ if ( typeof selector === 'object' ) {
+ Object.entries( selector ).forEach(
+ ( [ subfeature, subfeatureSelector ] ) => {
+ featureSelectors[ feature ][ subfeature ] = scopeSelector(
+ scope,
+ subfeatureSelector
+ );
+ }
+ );
+ }
+ } );
+
+ return featureSelectors;
+}
+
export const getNodesWithStyles = ( tree, blockSelectors ) => {
const nodes = [];
@@ -646,14 +673,104 @@ export const getNodesWithStyles = ( tree, blockSelectors ) => {
if ( node?.variations ) {
const variations = {};
- Object.keys( node.variations ).forEach( ( variation ) => {
- variations[ variation ] = pickStyleKeys(
- node.variations[ variation ]
- );
- } );
+ Object.entries( node.variations ).forEach(
+ ( [ variationName, variation ] ) => {
+ variations[ variationName ] =
+ pickStyleKeys( variation );
+
+ const variationSelector =
+ blockSelectors[ blockName ]
+ .styleVariationSelectors?.[ variationName ];
+
+ // Process the variation's inner element styles.
+ // This comes before the inner block styles so the
+ // element styles within the block type styles take
+ // precedence over these.
+ Object.entries( variation?.elements ?? {} ).forEach(
+ ( [ element, elementStyles ] ) => {
+ if ( elementStyles && ELEMENTS[ element ] ) {
+ nodes.push( {
+ styles: elementStyles,
+ selector: scopeSelector(
+ variationSelector,
+ ELEMENTS[ element ]
+ ),
+ } );
+ }
+ }
+ );
+
+ // Process the variations inner block type styles.
+ Object.entries( variation?.blocks ?? {} ).forEach(
+ ( [
+ variationBlockName,
+ variationBlockStyles,
+ ] ) => {
+ const variationBlockSelector = scopeSelector(
+ variationSelector,
+ blockSelectors[ variationBlockName ]
+ .selector
+ );
+ const variationDuotoneSelector = scopeSelector(
+ variationSelector,
+ blockSelectors[ variationBlockName ]
+ .duotoneSelector
+ );
+ const variationFeatureSelectors =
+ scopeFeatureSelectors(
+ variationSelector,
+ blockSelectors[ variationBlockName ]
+ .featureSelectors
+ );
+
+ nodes.push( {
+ selector: variationBlockSelector,
+ duotoneSelector: variationDuotoneSelector,
+ featureSelectors: variationFeatureSelectors,
+ fallbackGapValue:
+ blockSelectors[ variationBlockName ]
+ .fallbackGapValue,
+ hasLayoutSupport:
+ blockSelectors[ variationBlockName ]
+ .hasLayoutSupport,
+ styles: pickStyleKeys(
+ variationBlockStyles
+ ),
+ } );
+
+ // Process element styles for the inner blocks
+ // of the variation.
+ Object.entries(
+ variationBlockStyles.elements ?? {}
+ ).forEach(
+ ( [
+ variationBlockElement,
+ variationBlockElementStyles,
+ ] ) => {
+ if (
+ variationBlockElementStyles &&
+ ELEMENTS[ variationBlockElement ]
+ ) {
+ nodes.push( {
+ styles: variationBlockElementStyles,
+ selector: scopeSelector(
+ variationBlockSelector,
+ ELEMENTS[
+ variationBlockElement
+ ]
+ ),
+ } );
+ }
+ }
+ );
+ }
+ );
+ }
+ );
blockStyles.variations = variations;
}
- if ( blockStyles && blockSelectors?.[ blockName ]?.selector ) {
+
+ if ( blockSelectors?.[ blockName ]?.selector ) {
nodes.push( {
duotoneSelector:
blockSelectors[ blockName ].duotoneSelector,
From b7219e54fc082fbe744788819b77151059590bb4 Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Tue, 9 Apr 2024 16:51:03 +1000
Subject: [PATCH 16/52] Allow opting out of certain sets of styles when
generating JS global styles stylesheet
---
.../src/components/global-styles/use-global-styles-output.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/block-editor/src/components/global-styles/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/use-global-styles-output.js
index 1044425468d7b6..9aedc3fee71df6 100644
--- a/packages/block-editor/src/components/global-styles/use-global-styles-output.js
+++ b/packages/block-editor/src/components/global-styles/use-global-styles-output.js
@@ -1092,7 +1092,7 @@ export const toStyles = (
return;
}
- // `selector` maybe provided in a form
+ // `selector` may be provided in a form
// where block level selectors have sub element
// selectors appended to them as a comma separated
// string.
From 785d9cdefb67278b873dc0aed5e722721cd747b2 Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Tue, 9 Apr 2024 16:55:49 +1000
Subject: [PATCH 17/52] Support instanced variation selectors via
getBlockSelectors
---
.../global-styles/use-global-styles-output.js | 32 +++++++++++--------
1 file changed, 19 insertions(+), 13 deletions(-)
diff --git a/packages/block-editor/src/components/global-styles/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/use-global-styles-output.js
index 9aedc3fee71df6..baae9669e0c46d 100644
--- a/packages/block-editor/src/components/global-styles/use-global-styles-output.js
+++ b/packages/block-editor/src/components/global-styles/use-global-styles-output.js
@@ -1196,7 +1196,11 @@ const getSelectorsConfig = ( blockType, rootSelector ) => {
return config;
};
-export const getBlockSelectors = ( blockTypes, getBlockStyles ) => {
+export const getBlockSelectors = (
+ blockTypes,
+ getBlockStyles,
+ variationInstanceId
+) => {
const result = {};
blockTypes.forEach( ( blockType ) => {
const name = blockType.name;
@@ -1226,16 +1230,19 @@ export const getBlockSelectors = ( blockTypes, getBlockStyles ) => {
const blockStyleVariations = getBlockStyles( name );
const styleVariationSelectors = {};
- if ( blockStyleVariations?.length ) {
- blockStyleVariations.forEach( ( variation ) => {
- const styleVariationSelector = getBlockStyleVariationSelector(
- variation.name,
- selector
- );
- styleVariationSelectors[ variation.name ] =
- styleVariationSelector;
- } );
- }
+ blockStyleVariations?.forEach( ( variation ) => {
+ const variationSuffix = variationInstanceId
+ ? `-${ variationInstanceId }`
+ : '';
+ const variationName = `${ variation.name }${ variationSuffix }`;
+ const styleVariationSelector = getBlockStyleVariationSelector(
+ variationName,
+ selector
+ );
+
+ styleVariationSelectors[ variationName ] = styleVariationSelector;
+ } );
+
// For each block support feature add any custom selectors.
const featureSelectors = getSelectorsConfig( blockType, selector );
@@ -1248,8 +1255,7 @@ export const getBlockSelectors = ( blockTypes, getBlockStyles ) => {
hasLayoutSupport,
name,
selector,
- styleVariationSelectors: Object.keys( styleVariationSelectors )
- .length
+ styleVariationSelectors: blockStyleVariations?.length
? styleVariationSelectors
: undefined,
};
From e4c21ca475bc7cd4e1b8bfa68a2ab1003f2f2c96 Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Tue, 9 Apr 2024 17:43:21 +1000
Subject: [PATCH 18/52] Add block support hook for variations in the editor
---
.../src/components/global-styles/index.js | 2 +
packages/block-editor/src/hooks/index.js | 2 +
packages/block-editor/src/hooks/utils.js | 2 +-
packages/block-editor/src/hooks/variation.js | 132 ++++++++++++++++++
4 files changed, 137 insertions(+), 1 deletion(-)
create mode 100644 packages/block-editor/src/hooks/variation.js
diff --git a/packages/block-editor/src/components/global-styles/index.js b/packages/block-editor/src/components/global-styles/index.js
index 0e9aeb4c9c84ec..062df0a5606e90 100644
--- a/packages/block-editor/src/components/global-styles/index.js
+++ b/packages/block-editor/src/components/global-styles/index.js
@@ -8,6 +8,8 @@ export {
export { getBlockCSSSelector } from './get-block-css-selector';
export {
getLayoutStyles,
+ getBlockSelectors,
+ toStyles,
useGlobalStylesOutput,
useGlobalStylesOutputWithConfig,
} from './use-global-styles-output';
diff --git a/packages/block-editor/src/hooks/index.js b/packages/block-editor/src/hooks/index.js
index 4a59c2faa0073f..ce47cb5e824412 100644
--- a/packages/block-editor/src/hooks/index.js
+++ b/packages/block-editor/src/hooks/index.js
@@ -24,6 +24,7 @@ import fontSize from './font-size';
import textAlign from './text-align';
import border from './border';
import position from './position';
+import variation from './variation';
import layout from './layout';
import childLayout from './layout-child';
import contentLockUI from './content-lock-ui';
@@ -61,6 +62,7 @@ createBlockListBlockFilter( [
fontSize,
border,
position,
+ variation,
childLayout,
] );
createBlockSaveFilter( [
diff --git a/packages/block-editor/src/hooks/utils.js b/packages/block-editor/src/hooks/utils.js
index 391287afb6ba09..4beb5c9122f537 100644
--- a/packages/block-editor/src/hooks/utils.js
+++ b/packages/block-editor/src/hooks/utils.js
@@ -568,7 +568,7 @@ export function createBlockListBlockFilter( features ) {
useBlockProps,
} = feature;
- const neededProps = {};
+ const neededProps = { clientId: props.clientId };
for ( const key of attributeKeys ) {
if ( props.attributes[ key ] ) {
neededProps[ key ] = props.attributes[ key ];
diff --git a/packages/block-editor/src/hooks/variation.js b/packages/block-editor/src/hooks/variation.js
new file mode 100644
index 00000000000000..fa34ba44c0f8c4
--- /dev/null
+++ b/packages/block-editor/src/hooks/variation.js
@@ -0,0 +1,132 @@
+/**
+ * WordPress dependencies
+ */
+import { getBlockTypes, store as blocksStore } from '@wordpress/blocks';
+import { useSelect } from '@wordpress/data';
+import { useContext, useMemo } from '@wordpress/element';
+
+/**
+ * Internal dependencies
+ */
+import {
+ GlobalStylesContext,
+ toStyles,
+ getBlockSelectors,
+} from '../components/global-styles';
+import { useStyleOverride } from './utils';
+import { store as blockEditorStore } from '../store';
+
+function getVariationNameFromClass( className ) {
+ const match = className?.match( /\bis-style-(?!default)(\S+)\b/ );
+ return match ? match[ 1 ] : null;
+}
+
+function useBlockSyleVariation( name, variation, clientId ) {
+ const { user: userStyles } = useContext( GlobalStylesContext );
+ const { globalSettings, globalStyles } = useSelect( ( select ) => {
+ const { getSettings } = select( blockEditorStore );
+ return {
+ globalSettings: getSettings().__experimentalFeatures,
+ globalStyles: getSettings().__experimentalStyles,
+ };
+ }, [] );
+
+ return useMemo( () => {
+ const styles = userStyles?.styles ?? globalStyles;
+ const variationStyles =
+ styles?.blocks?.[ name ]?.variations?.[ variation ];
+
+ return {
+ settings: userStyles?.settings ?? globalSettings,
+ // The variation style data is all that is needed to generate
+ // the styles for the current application to a block. The variation
+ // name is updated to match the instance specific class name.
+ styles: {
+ blocks: {
+ [ name ]: {
+ variations: {
+ [ `${ variation }-${ clientId }` ]: variationStyles,
+ },
+ },
+ },
+ },
+ };
+ }, [
+ userStyles,
+ globalSettings,
+ globalStyles,
+ variation,
+ clientId,
+ name,
+ ] );
+}
+
+// Rather than leveraging `useInstanceId` here, the `clientId` is used.
+// This is so that the variation style override's ID is predictable
+// when the order of applied style variations changes.
+function useBlockProps( { name, className, clientId } ) {
+ const variation = getVariationNameFromClass( className );
+ const variationClass = `is-style-${ variation }-${ clientId }`;
+
+ const getBlockStyles = useSelect( ( select ) => {
+ return select( blocksStore ).getBlockStyles;
+ }, [] );
+
+ const { settings, styles } = useBlockSyleVariation(
+ name,
+ variation,
+ clientId
+ );
+
+ const variationStyles = useMemo( () => {
+ if ( ! variation ) {
+ return;
+ }
+
+ const variationConfig = { settings, styles };
+ const blockSelectors = getBlockSelectors(
+ getBlockTypes(),
+ getBlockStyles,
+ clientId
+ );
+ const hasBlockGapSupport = false;
+ const hasFallbackGapSupport = true;
+ const disableLayoutStyles = true;
+ const isTemplate = true;
+
+ return toStyles(
+ variationConfig,
+ blockSelectors,
+ hasBlockGapSupport,
+ hasFallbackGapSupport,
+ disableLayoutStyles,
+ isTemplate,
+ {
+ blockGap: false,
+ blockStyles: true,
+ layoutStyles: false,
+ marginReset: false,
+ presets: false,
+ rootPadding: false,
+ }
+ );
+ }, [ variation, settings, styles, getBlockStyles, clientId ] );
+
+ useStyleOverride( {
+ id: `variation-${ clientId }`,
+ css: variationStyles,
+ __unstableType: 'variation',
+ // The clientId will be stored with the override and used to ensure
+ // the order of overrides matches the order of blocks so that the
+ // correct CSS cascade is maintained.
+ clientId,
+ } );
+
+ return variation ? { className: variationClass } : {};
+}
+
+export default {
+ hasSupport: () => true,
+ attributeKeys: [ 'className' ],
+ useBlockProps,
+};
From c8ff6e75cc495fe86fc6474fa7f0a1f400e4fc5c Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Tue, 9 Apr 2024 18:22:29 +1000
Subject: [PATCH 19/52] Sort style overrides by the rendered order of
associated blocks
---
.../src/components/editor-styles/index.js | 26 ++++++++++++++++---
1 file changed, 22 insertions(+), 4 deletions(-)
diff --git a/packages/block-editor/src/components/editor-styles/index.js b/packages/block-editor/src/components/editor-styles/index.js
index 34c4a90020e3be..5e350fb1ebfbb5 100644
--- a/packages/block-editor/src/components/editor-styles/index.js
+++ b/packages/block-editor/src/components/editor-styles/index.js
@@ -68,14 +68,32 @@ function useDarkThemeBodyClassName( styles, scope ) {
}
function EditorStyles( { styles, scope } ) {
- const overrides = useSelect(
- ( select ) => unlock( select( blockEditorStore ) ).getStyleOverrides(),
+ const { overrides, clientIds } = useSelect(
+ ( select ) => ( {
+ overrides: unlock( select( blockEditorStore ) ).getStyleOverrides(),
+ clientIds: select( blockEditorStore ).getClientIdsWithDescendants(),
+ } ),
[]
);
+
const [ transformedStyles, transformedSvgs ] = useMemo( () => {
+ const clientIdMap = clientIds.reduce( ( acc, clientId, index ) => {
+ acc[ clientId ] = index;
+ return acc;
+ }, {} );
+
+ // Sort overrides to match the order of blocks they relate to.
+ // This is useful to maintain the correct CSS cascade order for
+ // nested block style variations.
+ const sortedOverrides = [ ...overrides ].sort( ( a, b ) => {
+ const aIndex = clientIdMap[ a[ 1 ].clientId ] ?? -1;
+ const bIndex = clientIdMap[ b[ 1 ].clientId ] ?? -1;
+ return aIndex - bIndex;
+ } );
+
const _styles = Object.values( styles ?? [] );
- for ( const [ id, override ] of overrides ) {
+ for ( const [ id, override ] of sortedOverrides ) {
const index = _styles.findIndex( ( { id: _id } ) => id === _id );
const overrideWithId = { ...override, id };
if ( index === -1 ) {
@@ -95,7 +113,7 @@ function EditorStyles( { styles, scope } ) {
.map( ( style ) => style.assets )
.join( '' ),
];
- }, [ styles, overrides, scope ] );
+ }, [ styles, overrides, scope, clientIds ] );
return (
<>
From 0f63b37ca387f7e39664a26aeeab5582da9fd0c8 Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Wed, 10 Apr 2024 13:39:55 +1000
Subject: [PATCH 20/52] Add test theme and child theme with block style
variations
---
.../block-styles/block-style-variation-a.json | 10 ++++++++++
.../style.css | 8 ++++++++
.../theme.json | 4 ++++
.../block-styles/block-style-variation-a.json | 10 ++++++++++
.../block-styles/block-style-variation-b.json | 10 ++++++++++
5 files changed, 42 insertions(+)
create mode 100644 phpunit/data/themedir1/block-theme-child-with-block-style-variations/block-styles/block-style-variation-a.json
create mode 100644 phpunit/data/themedir1/block-theme-child-with-block-style-variations/style.css
create mode 100644 phpunit/data/themedir1/block-theme-child-with-block-style-variations/theme.json
create mode 100644 phpunit/data/themedir1/block-theme/block-styles/block-style-variation-a.json
create mode 100644 phpunit/data/themedir1/block-theme/block-styles/block-style-variation-b.json
diff --git a/phpunit/data/themedir1/block-theme-child-with-block-style-variations/block-styles/block-style-variation-a.json b/phpunit/data/themedir1/block-theme-child-with-block-style-variations/block-styles/block-style-variation-a.json
new file mode 100644
index 00000000000000..1daaac0062b9c6
--- /dev/null
+++ b/phpunit/data/themedir1/block-theme-child-with-block-style-variations/block-styles/block-style-variation-a.json
@@ -0,0 +1,10 @@
+{
+ "version": 2,
+ "supportedBlockTypes": [ "core/group", "core/columns", "core/media-text" ],
+ "styles": {
+ "color": {
+ "background": "darkcyan",
+ "text": "aliceblue"
+ }
+ }
+}
diff --git a/phpunit/data/themedir1/block-theme-child-with-block-style-variations/style.css b/phpunit/data/themedir1/block-theme-child-with-block-style-variations/style.css
new file mode 100644
index 00000000000000..c1cc20aaf1f101
--- /dev/null
+++ b/phpunit/data/themedir1/block-theme-child-with-block-style-variations/style.css
@@ -0,0 +1,8 @@
+/*
+Theme Name: Block Theme Child With Block Style Variations Theme
+Theme URI: https://wordpress.org/
+Description: For testing purposes only.
+Template: block-theme
+Version: 1.0.0
+Text Domain: block-theme-child-with-block-style-variations
+*/
diff --git a/phpunit/data/themedir1/block-theme-child-with-block-style-variations/theme.json b/phpunit/data/themedir1/block-theme-child-with-block-style-variations/theme.json
new file mode 100644
index 00000000000000..0da29ef16fd679
--- /dev/null
+++ b/phpunit/data/themedir1/block-theme-child-with-block-style-variations/theme.json
@@ -0,0 +1,4 @@
+{
+ "$schema": "https://schemas.wp.org/trunk/theme.json",
+ "version": 2
+}
diff --git a/phpunit/data/themedir1/block-theme/block-styles/block-style-variation-a.json b/phpunit/data/themedir1/block-theme/block-styles/block-style-variation-a.json
new file mode 100644
index 00000000000000..0ba8417049eb0a
--- /dev/null
+++ b/phpunit/data/themedir1/block-theme/block-styles/block-style-variation-a.json
@@ -0,0 +1,10 @@
+{
+ "version": 2,
+ "supportedBlockTypes": [ "core/group", "core/columns" ],
+ "styles": {
+ "color": {
+ "background": "indigo",
+ "text": "plum"
+ }
+ }
+}
diff --git a/phpunit/data/themedir1/block-theme/block-styles/block-style-variation-b.json b/phpunit/data/themedir1/block-theme/block-styles/block-style-variation-b.json
new file mode 100644
index 00000000000000..6133b3e9f8d591
--- /dev/null
+++ b/phpunit/data/themedir1/block-theme/block-styles/block-style-variation-b.json
@@ -0,0 +1,10 @@
+{
+ "version": 2,
+ "supportedBlockTypes": [ "core/group", "core/columns" ],
+ "styles": {
+ "color": {
+ "background": "midnightblue",
+ "text": "lightblue"
+ }
+ }
+}
From 8786df0a80c67eb03b4230af0a277a22c0eaf76e Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Wed, 10 Apr 2024 13:48:33 +1000
Subject: [PATCH 21/52] Update theme.json resolver unit tests for
get_style_variations
---
phpunit/class-wp-theme-json-resolver-test.php | 164 +++++++++++-------
1 file changed, 106 insertions(+), 58 deletions(-)
diff --git a/phpunit/class-wp-theme-json-resolver-test.php b/phpunit/class-wp-theme-json-resolver-test.php
index 9ba170cd785d22..6aad6029129252 100644
--- a/phpunit/class-wp-theme-json-resolver-test.php
+++ b/phpunit/class-wp-theme-json-resolver-test.php
@@ -981,95 +981,143 @@ public function data_get_merged_data_returns_origin() {
}
/**
- * Tests that get_style_variations returns all variations, including parent theme variations if the theme is a child,
- * and that the child variation overwrites the parent variation of the same name.
+ * Tests that `get_style_variations` returns all the appropriate variations,
+ * including parent variations if the theme is a child, and that the child
+ * variation overwrites the parent variation of the same name.
*
- * @covers WP_Theme_JSON_Resolver_Gutenberg::get_style_variations
+ * Note: This covers both theme style variations (`/styles`) and block style
+ * variations (`/block-styles`).
+ *
+ * @covers WP_Theme_JSON_Resolver::get_style_variations
+ *
+ * @dataProvider data_get_style_variations
+ *
+ * @param string $theme Name of the theme to use.
+ * @param string $dir The directory to retrieve variation json files from.
+ * @param array $expected_variations Collection of expected variations.
*/
- public function test_get_style_variations_returns_all_variations() {
- // Switch to a child theme.
- switch_theme( 'block-theme-child' );
+ public function test_get_style_variations( $theme, $dir, $expected_variations ) {
+ switch_theme( $theme );
wp_set_current_user( self::$administrator_id );
- $actual_settings = WP_Theme_JSON_Resolver_Gutenberg::get_style_variations();
- $expected_settings = array(
- array(
- 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
- 'title' => 'variation-a',
- 'settings' => array(
- 'blocks' => array(
- 'core/paragraph' => array(
- 'color' => array(
- 'palette' => array(
- 'theme' => array(
- array(
- 'slug' => 'dark',
- 'name' => 'Dark',
- 'color' => '#010101',
+ $actual_variations = WP_Theme_JSON_Resolver_Gutenberg::get_style_variations( $dir );
+
+ wp_recursive_ksort( $actual_variations );
+ wp_recursive_ksort( $expected_variations );
+
+ $this->assertSame( $expected_variations, $actual_variations );
+ }
+
+ /**
+ * Data provider for test_get_style_variations
+ *
+ * @return array
+ */
+ public function data_get_style_variations() {
+ return array(
+ 'theme_style_variations' => array(
+ 'theme' => 'block-theme-child',
+ 'dir' => 'styles',
+ 'expected_variations' => array(
+ array(
+ 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
+ 'title' => 'variation-a',
+ 'settings' => array(
+ 'blocks' => array(
+ 'core/paragraph' => array(
+ 'color' => array(
+ 'palette' => array(
+ 'theme' => array(
+ array(
+ 'slug' => 'dark',
+ 'name' => 'Dark',
+ 'color' => '#010101',
+ ),
+ ),
),
),
),
),
),
),
- ),
- ),
- array(
- 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
- 'title' => 'variation-b',
- 'settings' => array(
- 'blocks' => array(
- 'core/post-title' => array(
+ array(
+ 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
+ 'title' => 'variation-b',
+ 'settings' => array(
+ 'blocks' => array(
+ 'core/post-title' => array(
+ 'color' => array(
+ 'palette' => array(
+ 'theme' => array(
+ array(
+ 'slug' => 'dark',
+ 'name' => 'Dark',
+ 'color' => '#010101',
+ ),
+ ),
+ ),
+ ),
+ ),
+ ),
+ ),
+ ),
+ array(
+ 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
+ 'title' => 'Block theme variation',
+ 'settings' => array(
'color' => array(
'palette' => array(
'theme' => array(
array(
- 'slug' => 'dark',
- 'name' => 'Dark',
- 'color' => '#010101',
+ 'slug' => 'foreground',
+ 'name' => 'Foreground',
+ 'color' => '#3F67C6',
),
),
),
),
),
+ 'styles' => array(
+ 'blocks' => array(
+ 'core/post-title' => array(
+ 'typography' => array(
+ 'fontWeight' => '700',
+ ),
+ ),
+ ),
+ ),
),
),
),
- array(
- 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
- 'title' => 'Block theme variation',
- 'settings' => array(
- 'color' => array(
- 'palette' => array(
- 'theme' => array(
- array(
- 'slug' => 'foreground',
- 'name' => 'Foreground',
- 'color' => '#3F67C6',
- ),
+ 'block_style_variations' => array(
+ 'theme' => 'block-theme-child-with-block-style-variations',
+ 'dir' => 'block-styles',
+ 'expected_variations' => array(
+ array(
+ 'supportedBlockTypes' => array( 'core/group', 'core/columns', 'core/media-text' ),
+ 'version' => 2,
+ 'title' => 'block-style-variation-a',
+ 'styles' => array(
+ 'color' => array(
+ 'background' => 'darkcyan',
+ 'text' => 'aliceblue',
),
),
),
- ),
- 'styles' => array(
- 'blocks' => array(
- 'core/post-title' => array(
- 'typography' => array(
- 'fontWeight' => '700',
+ array(
+ 'supportedBlockTypes' => array( 'core/group', 'core/columns' ),
+ 'version' => 2,
+ 'title' => 'block-style-variation-b',
+ 'styles' => array(
+ 'color' => array(
+ 'background' => 'midnightblue',
+ 'text' => 'lightblue',
),
),
),
),
),
);
-
- wp_recursive_ksort( $actual_settings );
- wp_recursive_ksort( $expected_settings );
-
- $this->assertSame(
- $expected_settings,
- $actual_settings
- );
}
public function test_theme_shadow_presets_do_not_override_default_shadow_presets() {
From 5206c337020ee0ef234e78b923791fc1ed8aa29b Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Wed, 10 Apr 2024 14:25:56 +1000
Subject: [PATCH 22/52] Test for variations support resolving variation
definitions into theme.json
---
phpunit/block-supports/variations-test.php | 126 +++++++++++++++++++++
1 file changed, 126 insertions(+)
create mode 100644 phpunit/block-supports/variations-test.php
diff --git a/phpunit/block-supports/variations-test.php b/phpunit/block-supports/variations-test.php
new file mode 100644
index 00000000000000..db842a39c9ee35
--- /dev/null
+++ b/phpunit/block-supports/variations-test.php
@@ -0,0 +1,126 @@
+theme_root = realpath( dirname( __DIR__ ) . '/data/themedir1' );
+
+ $this->orig_theme_dir = $GLOBALS['wp_theme_directories'];
+
+ // /themes is necessary as theme.php functions assume /themes is the root if there is only one root.
+ $GLOBALS['wp_theme_directories'] = array( WP_CONTENT_DIR . '/themes', $this->theme_root );
+
+ add_filter( 'theme_root', array( $this, 'filter_set_theme_root' ) );
+ add_filter( 'stylesheet_root', array( $this, 'filter_set_theme_root' ) );
+ add_filter( 'template_root', array( $this, 'filter_set_theme_root' ) );
+
+ // Clear caches.
+ wp_clean_themes_cache();
+ unset( $GLOBALS['wp_themes'] );
+ }
+
+ public function tear_down() {
+ $GLOBALS['wp_theme_directories'] = $this->orig_theme_dir;
+ wp_clean_themes_cache();
+ unset( $GLOBALS['wp_themes'] );
+
+ // Reset data between tests.
+ _gutenberg_clean_theme_json_caches();
+ parent::tear_down();
+ }
+
+ public function filter_set_theme_root() {
+ return $this->theme_root;
+ }
+
+ /**
+ * Tests that block style variations registered via either
+ * `gutenberg_register_block_style` with a style object, or a standalone
+ * block style variation file within `/block-styles`, are added to the
+ * theme data.
+ */
+ public function test_add_registered_block_styles_to_theme_data() {
+ switch_theme( 'block-theme' );
+
+ $variation_styles_data = array(
+ 'color' => array(
+ 'background' => 'darkslateblue',
+ 'text' => 'lavender',
+ ),
+ 'blocks' => array(
+ 'core/heading' => array(
+ 'color' => array(
+ 'text' => 'violet',
+ ),
+ ),
+ ),
+ 'elements' => array(
+ 'link' => array(
+ 'color' => array(
+ 'text' => 'fuchsia',
+ ),
+ ':hover' => array(
+ 'color' => array(
+ 'text' => 'deeppink',
+ ),
+ ),
+ ),
+ ),
+ );
+
+ register_block_style(
+ 'core/group',
+ array(
+ 'name' => 'my-variation',
+ 'style_data' => $variation_styles_data,
+ )
+ );
+
+ $theme_json = WP_Theme_JSON_Resolver_Gutenberg::get_theme_data()->get_raw_data();
+ $group_styles = $theme_json['styles']['blocks']['core/group'] ?? array();
+ $expected = array(
+ 'variations' => array(
+ 'my-variation' => $variation_styles_data,
+ // The following variations are registered automatically from
+ // their respective JSON files within the theme's `block-styles`
+ // directory.
+ 'block-style-variation-a' => array(
+ 'color' => array(
+ 'background' => 'indigo',
+ 'text' => 'plum',
+ ),
+ ),
+ 'block-style-variation-b' => array(
+ 'color' => array(
+ 'background' => 'midnightblue',
+ 'text' => 'lightblue',
+ ),
+ ),
+ ),
+ );
+
+ unregister_block_style( 'core/group', 'my-variation' );
+
+ $this->assertSameSetsWithIndex( $group_styles, $expected );
+ }
+}
From 6f83b555d03eacb3a1b907ed6cb854de0f6e8d43 Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Fri, 12 Apr 2024 12:30:05 +1000
Subject: [PATCH 23/52] Clean up retrieval of settings and styles
---
packages/block-editor/src/hooks/variation.js | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/packages/block-editor/src/hooks/variation.js b/packages/block-editor/src/hooks/variation.js
index fa34ba44c0f8c4..7cce3f9b1182ed 100644
--- a/packages/block-editor/src/hooks/variation.js
+++ b/packages/block-editor/src/hooks/variation.js
@@ -24,10 +24,11 @@ function getVariationNameFromClass( className ) {
function useBlockSyleVariation( name, variation, clientId ) {
const { user: userStyles } = useContext( GlobalStylesContext );
const { globalSettings, globalStyles } = useSelect( ( select ) => {
- const { getSettings } = select( blockEditorStore );
+ const { __experimentalFeatures, __experimentalStyles } =
+ select( blockEditorStore ).getSettings();
return {
- globalSettings: getSettings().__experimentalFeatures,
- globalStyles: getSettings().__experimentalStyles,
+ globalSettings: __experimentalFeatures,
+ globalStyles: __experimentalStyles,
};
}, [] );
From 611498c1551134e76dcf8dd97cfbd1e0beb07a1b Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Fri, 12 Apr 2024 12:34:19 +1000
Subject: [PATCH 24/52] Use cloneDeep util
---
packages/editor/src/components/global-styles-provider/index.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/packages/editor/src/components/global-styles-provider/index.js b/packages/editor/src/components/global-styles-provider/index.js
index e06cae27f16058..3658d44a9cf256 100644
--- a/packages/editor/src/components/global-styles-provider/index.js
+++ b/packages/editor/src/components/global-styles-provider/index.js
@@ -16,6 +16,7 @@ import { useMemo, useCallback } from '@wordpress/element';
* Internal dependencies
*/
import { unlock } from '../../lock-unlock';
+import cloneDeep from '../../utils/clone-deep';
import setNestedValue from '../../utils/set-nested-value';
const { GlobalStylesContext, cleanEmptyObject } = unlock(
@@ -38,7 +39,7 @@ function resolveBlockStyleVariations( userConfig ) {
return userConfig;
}
- const variationsConfig = JSON.parse( JSON.stringify( userConfig ) );
+ const variationsConfig = cloneDeep( userConfig );
Object.entries( sharedVariations ).forEach(
( [ variationName, variation ] ) => {
From 6be673c570cc7e4118d73790fe4c0fc4ef893bbe Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Fri, 12 Apr 2024 15:41:51 +1000
Subject: [PATCH 25/52] Register block style variations defined in user origin
---
.../global-styles-provider/index.js | 80 ++++++++++++-------
1 file changed, 49 insertions(+), 31 deletions(-)
diff --git a/packages/editor/src/components/global-styles-provider/index.js b/packages/editor/src/components/global-styles-provider/index.js
index 3658d44a9cf256..8029077f2c8f2f 100644
--- a/packages/editor/src/components/global-styles-provider/index.js
+++ b/packages/editor/src/components/global-styles-provider/index.js
@@ -7,6 +7,7 @@ import { isPlainObject } from 'is-plain-object';
/**
* WordPress dependencies
*/
+import { registerBlockStyle, store as blocksStore } from '@wordpress/blocks';
import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor';
import { store as coreStore } from '@wordpress/core-data';
import { useSelect, useDispatch } from '@wordpress/data';
@@ -32,35 +33,57 @@ export function mergeBaseAndUserConfigs( base, user ) {
} );
}
-function resolveBlockStyleVariations( userConfig ) {
- const sharedVariations = userConfig.styles?.blocks?.variations;
+// Resolves shared block style variation definitions from the user origin
+// under their respective block types and registers the block style if required.
+function useResolvedBlockStyleVariationsConfig( userConfig ) {
+ const getBlockStyles = useSelect( ( select ) => {
+ return select( blocksStore ).getBlockStyles;
+ }, [] );
- if ( ! sharedVariations ) {
- return userConfig;
- }
+ return useMemo( () => {
+ const sharedVariations = userConfig?.styles?.blocks?.variations;
- const variationsConfig = cloneDeep( userConfig );
+ if ( ! sharedVariations ) {
+ return userConfig;
+ }
- Object.entries( sharedVariations ).forEach(
- ( [ variationName, variation ] ) => {
- if ( ! variation?.supportedBlockTypes ) {
- return;
+ const variationsConfig = cloneDeep( userConfig );
+
+ Object.entries( sharedVariations ).forEach(
+ ( [ variationName, variation ] ) => {
+ if ( ! variation?.supportedBlockTypes ) {
+ return;
+ }
+
+ variation.supportedBlockTypes.forEach( ( blockName ) => {
+ // Register any block style variations that have been added
+ // by a theme style variation and are not already registered.
+ const blockStyles = getBlockStyles( blockName );
+ const registeredBlockStyle = blockStyles.find(
+ ( { name } ) => name === variationName
+ );
+
+ if ( ! registeredBlockStyle ) {
+ registerBlockStyle( blockName, {
+ name: variationName,
+ label: variationName,
+ } );
+ }
+
+ const path = [
+ 'styles',
+ 'blocks',
+ blockName,
+ 'variations',
+ variationName,
+ ];
+ setNestedValue( variationsConfig, path, variation );
+ } );
}
+ );
- variation.supportedBlockTypes.forEach( ( blockName ) => {
- const path = [
- 'styles',
- 'blocks',
- blockName,
- 'variations',
- variationName,
- ];
- setNestedValue( variationsConfig, path, variation );
- } );
- }
- );
-
- return deepmerge( variationsConfig, userConfig );
+ return deepmerge( variationsConfig, userConfig );
+ }, [ userConfig, getBlockStyles ] );
}
function useGlobalStylesUserConfig() {
@@ -161,13 +184,8 @@ export function useGlobalStylesContext() {
const [ isUserConfigReady, userConfig, setUserConfig ] =
useGlobalStylesUserConfig();
const [ isBaseConfigReady, baseConfig ] = useGlobalStylesBaseConfig();
-
- const userConfigWithVariations = useMemo( () => {
- if ( ! userConfig ) {
- return userConfig;
- }
- return resolveBlockStyleVariations( userConfig );
- }, [ userConfig ] );
+ const userConfigWithVariations =
+ useResolvedBlockStyleVariationsConfig( userConfig );
const mergedConfig = useMemo( () => {
if ( ! baseConfig || ! userConfigWithVariations ) {
From 723ed633042e4584591b27c9bc31d83b104b8e9c Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Mon, 15 Apr 2024 10:44:45 +1000
Subject: [PATCH 26/52] Make PHP function, block support, and register styles
naming consistent
---
lib/block-supports/variations.php | 40 +++++++++++++++----------------
1 file changed, 20 insertions(+), 20 deletions(-)
diff --git a/lib/block-supports/variations.php b/lib/block-supports/variations.php
index 3cc6509c6ae034..ae4de3922f0792 100644
--- a/lib/block-supports/variations.php
+++ b/lib/block-supports/variations.php
@@ -10,11 +10,11 @@
* Get the class name for this application of this block's variation styles.
*
* @param array $block Block object.
- * @param string $variation Slug for the variation.
+ * @param string $variation Slug for the block style variation.
*
* @return string The unique class name.
*/
-function gutenberg_get_variation_class_name( $block, $variation ) {
+function gutenberg_get_block_style_variation_class_name( $block, $variation ) {
return 'is-style-' . $variation . '--' . md5( serialize( $block ) );
}
@@ -23,9 +23,9 @@ function gutenberg_get_variation_class_name( $block, $variation ) {
*
* @param string $class_string CSS class string to look for a variation in.
*
- * @return string|null The variation name if found.
+ * @return string|null The block style variation name if found.
*/
-function gutenberg_get_variation_name_from_class( $class_string ) {
+function gutenberg_get_block_style_variation_name_from_class( $class_string ) {
if ( ! is_string( $class_string ) ) {
return null;
}
@@ -46,11 +46,11 @@ function gutenberg_get_variation_name_from_class( $class_string ) {
*
* @param array $parsed_block The parsed block.
*
- * @return array The same parsed block with variation classname added if appropriate.
+ * @return array The parsed block with block style variation classname added.
*/
-function gutenberg_render_variation_support_styles( $parsed_block ) {
+function gutenberg_render_block_style_variation_support_styles( $parsed_block ) {
$classes = $parsed_block['attrs']['className'] ?? null;
- $variation = gutenberg_get_variation_name_from_class( $classes );
+ $variation = gutenberg_get_block_style_variation_name_from_class( $classes );
if ( ! $variation ) {
return $parsed_block;
@@ -69,7 +69,7 @@ function gutenberg_render_variation_support_styles( $parsed_block ) {
'styles' => $variation_data,
);
- $class_name = gutenberg_get_variation_class_name( $parsed_block, $variation );
+ $class_name = gutenberg_get_block_style_variation_class_name( $parsed_block, $variation );
$updated_class_name = $parsed_block['attrs']['className'] . " $class_name";
$class_name = ".$class_name";
@@ -97,8 +97,8 @@ function gutenberg_render_variation_support_styles( $parsed_block ) {
return $parsed_block;
}
- wp_register_style( 'variation-styles', false, array( 'global-styles' ) );
- wp_add_inline_style( 'variation-styles', $variation_styles );
+ wp_register_style( 'block-style-variation-styles', false, array( 'global-styles' ) );
+ wp_add_inline_style( 'block-style-variation-styles', $variation_styles );
/*
* Add variation instance class name to block's className string so it can
@@ -114,14 +114,14 @@ function gutenberg_render_variation_support_styles( $parsed_block ) {
* block attributes in the `render_block_data` filter gets applied to the
* block's markup.
*
- * @see gutenberg_render_variation_support_styles
+ * @see gutenberg_render_block_style_variation_support_styles
*
* @param string $block_content Rendered block content.
* @param array $block Block object.
*
* @return string Filtered block content.
*/
-function gutenberg_render_variation_class_name( $block_content, $block ) {
+function gutenberg_render_block_style_variation_class_name( $block_content, $block ) {
if ( ! $block_content || empty( $block['attrs']['className'] ) ) {
return $block_content;
}
@@ -130,7 +130,7 @@ function gutenberg_render_variation_class_name( $block_content, $block ) {
* Matches a class prefixed by `is-style`, followed by the
* variation slug, then `--`, and finally a hash.
*
- * See `gutenberg_get_variation_class_name` for class generation.
+ * See `gutenberg_get_block_style_variation_class_name` for class generation.
*/
preg_match( '/\bis-style-(\S+?--\w+)\b/', $block['attrs']['className'], $matches );
@@ -144,7 +144,7 @@ function gutenberg_render_variation_class_name( $block_content, $block ) {
/*
* Ensure the variation instance class name set in the
* `render_block_data` filter is applied in markup.
- * See `gutenberg_render_variation_support_styles`.
+ * See `gutenberg_render_block_style_variation_support_styles`.
*/
$tags->add_class( $matches[0] );
}
@@ -322,16 +322,16 @@ function gutenberg_resolve_block_style_variations_from_styles_registry( $theme_j
/**
* Enqueues styles for block style variations.
*/
-function gutenberg_enqueue_variation_styles() {
- wp_enqueue_style( 'variation-styles' );
+function gutenberg_enqueue_block_style_variation_styles() {
+ wp_enqueue_style( 'block-style-variation-styles' );
}
// Register the block support.
-WP_Block_Supports::get_instance()->register( 'variation', array() );
+WP_Block_Supports::get_instance()->register( 'block-style-variation', array() );
-add_filter( 'render_block_data', 'gutenberg_render_variation_support_styles', 10, 2 );
-add_filter( 'render_block', 'gutenberg_render_variation_class_name', 10, 2 );
-add_action( 'wp_enqueue_scripts', 'gutenberg_enqueue_variation_styles', 1 );
+add_filter( 'render_block_data', 'gutenberg_render_block_style_variation_support_styles', 10, 2 );
+add_filter( 'render_block', 'gutenberg_render_block_style_variation_class_name', 10, 2 );
+add_action( 'wp_enqueue_scripts', 'gutenberg_enqueue_block_style_variation_styles', 1 );
// Resolve block style variations from all their potential sources. The order here is deliberate.
add_filter( 'wp_theme_json_data_theme', 'gutenberg_resolve_block_style_variations_from_primary_theme_json', 10, 1 );
From 09426ff52471fbd8eb54f6c8804e0acf440c2299 Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Mon, 15 Apr 2024 10:54:54 +1000
Subject: [PATCH 27/52] Rename block style variation PHP block support files
---
.../{variations.php => block-style-variations.php} | 0
lib/load.php | 2 +-
...ons-test.php => block-style-variations-test.php} | 13 ++++++++-----
3 files changed, 9 insertions(+), 6 deletions(-)
rename lib/block-supports/{variations.php => block-style-variations.php} (100%)
rename phpunit/block-supports/{variations-test.php => block-style-variations-test.php} (90%)
diff --git a/lib/block-supports/variations.php b/lib/block-supports/block-style-variations.php
similarity index 100%
rename from lib/block-supports/variations.php
rename to lib/block-supports/block-style-variations.php
diff --git a/lib/load.php b/lib/load.php
index 5b0c8fd64ab902..6179ade9a2288e 100644
--- a/lib/load.php
+++ b/lib/load.php
@@ -232,7 +232,7 @@ function gutenberg_is_experiment_enabled( $name ) {
require __DIR__ . '/block-supports/duotone.php';
require __DIR__ . '/block-supports/shadow.php';
require __DIR__ . '/block-supports/background.php';
-require __DIR__ . '/block-supports/variations.php';
+require __DIR__ . '/block-supports/block-style-variations.php';
// Data views.
require_once __DIR__ . '/experimental/data-views.php';
diff --git a/phpunit/block-supports/variations-test.php b/phpunit/block-supports/block-style-variations-test.php
similarity index 90%
rename from phpunit/block-supports/variations-test.php
rename to phpunit/block-supports/block-style-variations-test.php
index db842a39c9ee35..073f137a9e2090 100644
--- a/phpunit/block-supports/variations-test.php
+++ b/phpunit/block-supports/block-style-variations-test.php
@@ -1,12 +1,12 @@
array(
'my-variation' => $variation_styles_data,
- // The following variations are registered automatically from
- // their respective JSON files within the theme's `block-styles`
- // directory.
+
+ /*
+ * The following block style variations are registered
+ * automatically from their respective JSON files within the
+ * theme's `block-styles` directory.
+ */
'block-style-variation-a' => array(
'color' => array(
'background' => 'indigo',
From cefe0cb5bd12466e20cc1ce664c5cb98cb2e03a7 Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Mon, 15 Apr 2024 11:36:48 +1000
Subject: [PATCH 28/52] Rename JS variation block support to block style
variation
---
.../src/hooks/{variation.js => block-style-variation.js} | 0
packages/block-editor/src/hooks/index.js | 4 ++--
2 files changed, 2 insertions(+), 2 deletions(-)
rename packages/block-editor/src/hooks/{variation.js => block-style-variation.js} (100%)
diff --git a/packages/block-editor/src/hooks/variation.js b/packages/block-editor/src/hooks/block-style-variation.js
similarity index 100%
rename from packages/block-editor/src/hooks/variation.js
rename to packages/block-editor/src/hooks/block-style-variation.js
diff --git a/packages/block-editor/src/hooks/index.js b/packages/block-editor/src/hooks/index.js
index ce47cb5e824412..89e6819c1d0314 100644
--- a/packages/block-editor/src/hooks/index.js
+++ b/packages/block-editor/src/hooks/index.js
@@ -24,7 +24,7 @@ import fontSize from './font-size';
import textAlign from './text-align';
import border from './border';
import position from './position';
-import variation from './variation';
+import blockStyleVariation from './block-style-variation';
import layout from './layout';
import childLayout from './layout-child';
import contentLockUI from './content-lock-ui';
@@ -62,7 +62,7 @@ createBlockListBlockFilter( [
fontSize,
border,
position,
- variation,
+ blockStyleVariation,
childLayout,
] );
createBlockSaveFilter( [
From fca19815bc10fe9e06273650d9160fcc06d3d123 Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Mon, 15 Apr 2024 11:43:12 +1000
Subject: [PATCH 29/52] Fix typo
---
lib/block-supports/block-style-variations.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/block-supports/block-style-variations.php b/lib/block-supports/block-style-variations.php
index ae4de3922f0792..ac2581a05310da 100644
--- a/lib/block-supports/block-style-variations.php
+++ b/lib/block-supports/block-style-variations.php
@@ -37,7 +37,7 @@ function gutenberg_get_block_style_variation_name_from_class( $class_string ) {
/**
* Render the block style variation's styles.
*
- * In the case of nested blocks with variations applies, we want the parent
+ * In the case of nested blocks with variations applied, we want the parent
* variation's styles to be rendered before their descendants. This solves the
* issue of a block type being styled in both the parent and descendant: we want
* the descendant style to take priority, and this is done by loading it after,
From 24f1863523070bad0c7b89bb0fdf9af60216ba74 Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Mon, 15 Apr 2024 11:52:57 +1000
Subject: [PATCH 30/52] Tweaks to resolve and register util function
---
lib/block-supports/block-style-variations.php | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/lib/block-supports/block-style-variations.php b/lib/block-supports/block-style-variations.php
index ac2581a05310da..a6fa87b3b57870 100644
--- a/lib/block-supports/block-style-variations.php
+++ b/lib/block-supports/block-style-variations.php
@@ -170,7 +170,7 @@ function gutenberg_resolve_and_register_block_style_variations( $variations ) {
}
$registry = WP_Block_Styles_Registry::get_instance();
- $have_named_variations = array_keys( $variations ) !== range( 0, count( $variations ) - 1 );
+ $have_named_variations = ! wp_is_numeric_array( $variations );
foreach ( $variations as $key => $variation ) {
$supported_blocks = $variation['supportedBlockTypes'] ?? array();
@@ -183,29 +183,32 @@ function gutenberg_resolve_and_register_block_style_variations( $variations ) {
*/
$variation_data = $variation['styles'] ?? $variation;
+ if ( empty( $variation_data ) ) {
+ continue;
+ }
+
/*
* Block style variations read in via standalone theme.json partials
* need to have their name set to the kebab case version of their title.
*/
- $variation_name = $have_named_variations ? $key : _wp_to_kebab_case( $variation['title'] );
-
- if ( empty( $variation_data ) ) {
- continue;
- }
+ $variation_name = $have_named_variations ? $key : _wp_to_kebab_case( $variation['title'] );
+ $variation_label = $variation['title'] ?? $variation_name;
foreach ( $supported_blocks as $block_type ) {
$registered_styles = $registry->get_registered_styles_for_block( $block_type );
+ // Register block style variation if it hasn't already been registered.
if ( ! array_key_exists( $variation_name, $registered_styles ) ) {
gutenberg_register_block_style(
$block_type,
array(
'name' => $variation_name,
- 'label' => $variation['title'] ?? $variation_name,
+ 'label' => $variation_label,
)
);
}
+ // Add block style variation data under current block type.
$path = array( $block_type, 'variations', $variation_name );
_wp_array_set( $variations_data, $path, $variation_data );
}
From c54d3a3d0cf8782418d560281e09500cf1d68ea8 Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Mon, 15 Apr 2024 18:04:38 +1000
Subject: [PATCH 31/52] Consolidate block style variations under theme styles
directory
---
lib/block-supports/block-style-variations.php | 2 +-
...class-wp-theme-json-resolver-gutenberg.php | 35 +++++++++++++++----
phpunit/class-wp-theme-json-resolver-test.php | 13 ++++---
.../block-style-variation-a.json | 1 +
.../block-style-variation-a.json | 1 +
.../block-style-variation-b.json | 1 +
6 files changed, 38 insertions(+), 15 deletions(-)
rename phpunit/data/themedir1/block-theme-child-with-block-style-variations/{block-styles => styles}/block-style-variation-a.json (88%)
rename phpunit/data/themedir1/block-theme/{block-styles => styles}/block-style-variation-a.json (87%)
rename phpunit/data/themedir1/block-theme/{block-styles => styles}/block-style-variation-b.json (87%)
diff --git a/lib/block-supports/block-style-variations.php b/lib/block-supports/block-style-variations.php
index a6fa87b3b57870..ecdc4e1498c557 100644
--- a/lib/block-supports/block-style-variations.php
+++ b/lib/block-supports/block-style-variations.php
@@ -273,7 +273,7 @@ function gutenberg_resolve_block_style_variations_from_theme_style_variation( $t
* @return WP_Theme_JSON_Data_Gutenberg
*/
function gutenberg_resolve_block_style_variations_from_theme_json_partials( $theme_json ) {
- $block_style_variations = WP_Theme_JSON_Resolver_Gutenberg::get_style_variations( '/block-styles' );
+ $block_style_variations = WP_Theme_JSON_Resolver_Gutenberg::get_style_variations( 'block' );
$variations_data = gutenberg_resolve_and_register_block_style_variations( $block_style_variations );
return gutenberg_merge_block_style_variations_data( $variations_data, $theme_json );
diff --git a/lib/class-wp-theme-json-resolver-gutenberg.php b/lib/class-wp-theme-json-resolver-gutenberg.php
index 95ca466140e23f..e886d9047ca0fd 100644
--- a/lib/class-wp-theme-json-resolver-gutenberg.php
+++ b/lib/class-wp-theme-json-resolver-gutenberg.php
@@ -716,21 +716,42 @@ private static function recursively_iterate_json( $dir ) {
return $nested_json_files;
}
+ /**
+ * Determines if a supplied style variation matches the provided scope.
+ *
+ * For backwards compatibility, if a variation does not explicitly define
+ * a scope, it is assumed to be a theme style variation.
+ *
+ * @param array $variation Theme.json shaped style variation object.
+ * @param string $scope Scope to check e.g. theme, block etc.
+ * @return boolean
+ */
+ private static function style_variation_has_scope( $variation, $scope ) {
+ $scopes = $variation['scope'] ?? array();
+
+ if ( count( $scopes ) === 0 ) {
+ return 'theme' === $scope;
+ }
+
+ return in_array( $scope, $scopes, true );
+ }
+
/**
* Returns the style variations defined by the theme (parent and child).
*
* @since 6.2.0 Returns parent theme variations if theme is a child.
- * @since 6.6.0 Added configurable directory to allow block style variations
- * to reside in a different directory to theme style variations.
+ * @since 6.6.0 Added configurable scope parameter to allow filtering
+ * theme.json partial files by the scope to which they
+ * can be applied e.g. theme vs block etc.
*
- * @param string $dir Directory to search for variation partials.
+ * @param string $scope The scope or type of style variation to retrieve e.g. theme, block etc.
* @return array
*/
- public static function get_style_variations( $dir = 'styles' ) {
+ public static function get_style_variations( $scope = 'theme' ) {
$variation_files = array();
$variations = array();
- $base_directory = get_stylesheet_directory() . '/' . $dir;
- $template_directory = get_template_directory() . '/' . $dir;
+ $base_directory = get_stylesheet_directory() . '/styles';
+ $template_directory = get_template_directory() . '/styles';
if ( is_dir( $base_directory ) ) {
$variation_files = static::recursively_iterate_json( $base_directory );
}
@@ -749,7 +770,7 @@ public static function get_style_variations( $dir = 'styles' ) {
ksort( $variation_files );
foreach ( $variation_files as $path => $file ) {
$decoded_file = wp_json_file_decode( $path, array( 'associative' => true ) );
- if ( is_array( $decoded_file ) ) {
+ if ( is_array( $decoded_file ) && static::style_variation_has_scope( $decoded_file, $scope ) ) {
$translated = static::translate( $decoded_file, wp_get_theme()->get( 'TextDomain' ) );
$variation = ( new WP_Theme_JSON_Gutenberg( $translated ) )->get_raw_data();
if ( empty( $variation['title'] ) ) {
diff --git a/phpunit/class-wp-theme-json-resolver-test.php b/phpunit/class-wp-theme-json-resolver-test.php
index 6aad6029129252..8a68c7eed30611 100644
--- a/phpunit/class-wp-theme-json-resolver-test.php
+++ b/phpunit/class-wp-theme-json-resolver-test.php
@@ -985,22 +985,21 @@ public function data_get_merged_data_returns_origin() {
* including parent variations if the theme is a child, and that the child
* variation overwrites the parent variation of the same name.
*
- * Note: This covers both theme style variations (`/styles`) and block style
- * variations (`/block-styles`).
+ * Note: This covers both theme and block style variations.
*
* @covers WP_Theme_JSON_Resolver::get_style_variations
*
* @dataProvider data_get_style_variations
*
* @param string $theme Name of the theme to use.
- * @param string $dir The directory to retrieve variation json files from.
+ * @param string $scope Scope to filter variations by e.g. theme vs block.
* @param array $expected_variations Collection of expected variations.
*/
- public function test_get_style_variations( $theme, $dir, $expected_variations ) {
+ public function test_get_style_variations( $theme, $scope, $expected_variations ) {
switch_theme( $theme );
wp_set_current_user( self::$administrator_id );
- $actual_variations = WP_Theme_JSON_Resolver_Gutenberg::get_style_variations( $dir );
+ $actual_variations = WP_Theme_JSON_Resolver_Gutenberg::get_style_variations( $scope );
wp_recursive_ksort( $actual_variations );
wp_recursive_ksort( $expected_variations );
@@ -1017,7 +1016,7 @@ public function data_get_style_variations() {
return array(
'theme_style_variations' => array(
'theme' => 'block-theme-child',
- 'dir' => 'styles',
+ 'scope' => 'theme',
'expected_variations' => array(
array(
'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
@@ -1091,7 +1090,7 @@ public function data_get_style_variations() {
),
'block_style_variations' => array(
'theme' => 'block-theme-child-with-block-style-variations',
- 'dir' => 'block-styles',
+ 'scope' => 'block',
'expected_variations' => array(
array(
'supportedBlockTypes' => array( 'core/group', 'core/columns', 'core/media-text' ),
diff --git a/phpunit/data/themedir1/block-theme-child-with-block-style-variations/block-styles/block-style-variation-a.json b/phpunit/data/themedir1/block-theme-child-with-block-style-variations/styles/block-style-variation-a.json
similarity index 88%
rename from phpunit/data/themedir1/block-theme-child-with-block-style-variations/block-styles/block-style-variation-a.json
rename to phpunit/data/themedir1/block-theme-child-with-block-style-variations/styles/block-style-variation-a.json
index 1daaac0062b9c6..017bb2148d4771 100644
--- a/phpunit/data/themedir1/block-theme-child-with-block-style-variations/block-styles/block-style-variation-a.json
+++ b/phpunit/data/themedir1/block-theme-child-with-block-style-variations/styles/block-style-variation-a.json
@@ -1,5 +1,6 @@
{
"version": 2,
+ "scope": [ "block" ],
"supportedBlockTypes": [ "core/group", "core/columns", "core/media-text" ],
"styles": {
"color": {
diff --git a/phpunit/data/themedir1/block-theme/block-styles/block-style-variation-a.json b/phpunit/data/themedir1/block-theme/styles/block-style-variation-a.json
similarity index 87%
rename from phpunit/data/themedir1/block-theme/block-styles/block-style-variation-a.json
rename to phpunit/data/themedir1/block-theme/styles/block-style-variation-a.json
index 0ba8417049eb0a..92aed03bb35005 100644
--- a/phpunit/data/themedir1/block-theme/block-styles/block-style-variation-a.json
+++ b/phpunit/data/themedir1/block-theme/styles/block-style-variation-a.json
@@ -1,5 +1,6 @@
{
"version": 2,
+ "scope": [ "block" ],
"supportedBlockTypes": [ "core/group", "core/columns" ],
"styles": {
"color": {
diff --git a/phpunit/data/themedir1/block-theme/block-styles/block-style-variation-b.json b/phpunit/data/themedir1/block-theme/styles/block-style-variation-b.json
similarity index 87%
rename from phpunit/data/themedir1/block-theme/block-styles/block-style-variation-b.json
rename to phpunit/data/themedir1/block-theme/styles/block-style-variation-b.json
index 6133b3e9f8d591..d6afc57b5bad41 100644
--- a/phpunit/data/themedir1/block-theme/block-styles/block-style-variation-b.json
+++ b/phpunit/data/themedir1/block-theme/styles/block-style-variation-b.json
@@ -1,5 +1,6 @@
{
"version": 2,
+ "scope": [ "block" ],
"supportedBlockTypes": [ "core/group", "core/columns" ],
"styles": {
"color": {
From db0402ce10deb4dad2daab4f56c73d5bac72788e Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Tue, 16 Apr 2024 12:25:15 +1000
Subject: [PATCH 32/52] Fix references to /block-styles in comments
---
phpunit/block-supports/block-style-variations-test.php | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/phpunit/block-supports/block-style-variations-test.php b/phpunit/block-supports/block-style-variations-test.php
index 073f137a9e2090..99d87d4736bd1a 100644
--- a/phpunit/block-supports/block-style-variations-test.php
+++ b/phpunit/block-supports/block-style-variations-test.php
@@ -56,8 +56,7 @@ public function filter_set_theme_root() {
/**
* Tests that block style variations registered via either
* `gutenberg_register_block_style` with a style object, or a standalone
- * block style variation file within `/block-styles`, are added to the
- * theme data.
+ * block style variation file within `/styles`, are added to the theme data.
*/
public function test_add_registered_block_styles_to_theme_data() {
switch_theme( 'block-theme' );
@@ -105,7 +104,7 @@ public function test_add_registered_block_styles_to_theme_data() {
/*
* The following block style variations are registered
* automatically from their respective JSON files within the
- * theme's `block-styles` directory.
+ * theme's `/styles` directory.
*/
'block-style-variation-a' => array(
'color' => array(
From 800d452ff69fccb55afd39ee9d756e69371e965f Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Wed, 17 Apr 2024 13:54:13 +1000
Subject: [PATCH 33/52] Switch scoping of variations to check
supportedBlockTypes
---
lib/class-wp-theme-json-resolver-gutenberg.php | 16 ++++++++++------
.../styles/block-style-variation-a.json | 1 -
.../styles/block-style-variation-a.json | 1 -
.../styles/block-style-variation-b.json | 1 -
4 files changed, 10 insertions(+), 9 deletions(-)
diff --git a/lib/class-wp-theme-json-resolver-gutenberg.php b/lib/class-wp-theme-json-resolver-gutenberg.php
index e886d9047ca0fd..d78eda9be0ef51 100644
--- a/lib/class-wp-theme-json-resolver-gutenberg.php
+++ b/lib/class-wp-theme-json-resolver-gutenberg.php
@@ -719,21 +719,25 @@ private static function recursively_iterate_json( $dir ) {
/**
* Determines if a supplied style variation matches the provided scope.
*
- * For backwards compatibility, if a variation does not explicitly define
- * a scope, it is assumed to be a theme style variation.
+ * For backwards compatibility, if a variation does not define any scope
+ * related property, e.g. `supportedBlockTypes`, it is assumed to be a
+ * theme style variation.
*
* @param array $variation Theme.json shaped style variation object.
* @param string $scope Scope to check e.g. theme, block etc.
+ *
* @return boolean
*/
private static function style_variation_has_scope( $variation, $scope ) {
- $scopes = $variation['scope'] ?? array();
+ if ( 'block' === $scope ) {
+ return isset( $variation['supportedBlockTypes'] );
+ }
- if ( count( $scopes ) === 0 ) {
- return 'theme' === $scope;
+ if ( 'theme' === $scope ) {
+ return ! isset( $variation['supportedBlockTypes'] );
}
- return in_array( $scope, $scopes, true );
+ return false;
}
/**
diff --git a/phpunit/data/themedir1/block-theme-child-with-block-style-variations/styles/block-style-variation-a.json b/phpunit/data/themedir1/block-theme-child-with-block-style-variations/styles/block-style-variation-a.json
index 017bb2148d4771..1daaac0062b9c6 100644
--- a/phpunit/data/themedir1/block-theme-child-with-block-style-variations/styles/block-style-variation-a.json
+++ b/phpunit/data/themedir1/block-theme-child-with-block-style-variations/styles/block-style-variation-a.json
@@ -1,6 +1,5 @@
{
"version": 2,
- "scope": [ "block" ],
"supportedBlockTypes": [ "core/group", "core/columns", "core/media-text" ],
"styles": {
"color": {
diff --git a/phpunit/data/themedir1/block-theme/styles/block-style-variation-a.json b/phpunit/data/themedir1/block-theme/styles/block-style-variation-a.json
index 92aed03bb35005..0ba8417049eb0a 100644
--- a/phpunit/data/themedir1/block-theme/styles/block-style-variation-a.json
+++ b/phpunit/data/themedir1/block-theme/styles/block-style-variation-a.json
@@ -1,6 +1,5 @@
{
"version": 2,
- "scope": [ "block" ],
"supportedBlockTypes": [ "core/group", "core/columns" ],
"styles": {
"color": {
diff --git a/phpunit/data/themedir1/block-theme/styles/block-style-variation-b.json b/phpunit/data/themedir1/block-theme/styles/block-style-variation-b.json
index d6afc57b5bad41..6133b3e9f8d591 100644
--- a/phpunit/data/themedir1/block-theme/styles/block-style-variation-b.json
+++ b/phpunit/data/themedir1/block-theme/styles/block-style-variation-b.json
@@ -1,6 +1,5 @@
{
"version": 2,
- "scope": [ "block" ],
"supportedBlockTypes": [ "core/group", "core/columns" ],
"styles": {
"color": {
From 9108b714ae47963467d153b79bcbe94f815655f7 Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Wed, 17 Apr 2024 13:55:56 +1000
Subject: [PATCH 34/52] Move scopeFeatureSelectors to utils and add docblock
---
.../global-styles/use-global-styles-output.js | 28 +------------------
1 file changed, 1 insertion(+), 27 deletions(-)
diff --git a/packages/block-editor/src/components/global-styles/use-global-styles-output.js b/packages/block-editor/src/components/global-styles/use-global-styles-output.js
index baae9669e0c46d..82f09c47905d2c 100644
--- a/packages/block-editor/src/components/global-styles/use-global-styles-output.js
+++ b/packages/block-editor/src/components/global-styles/use-global-styles-output.js
@@ -21,6 +21,7 @@ import {
ROOT_BLOCK_SELECTOR,
ROOT_CSS_PROPERTIES_SELECTOR,
scopeSelector,
+ scopeFeatureSelectors,
appendToSelector,
getBlockStyleVariationSelector,
} from './utils';
@@ -614,33 +615,6 @@ function pickStyleKeys( treeToPickFrom ) {
return Object.fromEntries( clonedEntries );
}
-function scopeFeatureSelectors( scope, selectors ) {
- if ( ! scope || ! selectors ) {
- return;
- }
-
- const featureSelectors = JSON.parse( JSON.stringify( selectors ) );
-
- Object.entries( selectors ).forEach( ( [ feature, selector ] ) => {
- if ( typeof selector === 'string' ) {
- featureSelectors[ feature ] = scopeSelector( scope, selector );
- }
-
- if ( typeof selector === 'object' ) {
- Object.entries( selector ).forEach(
- ( [ subfeature, subfeatureSelector ] ) => {
- featureSelectors[ feature ][ subfeature ] = scopeSelector(
- scope,
- subfeatureSelector
- );
- }
- );
- }
- } );
-
- return featureSelectors;
-}
-
export const getNodesWithStyles = ( tree, blockSelectors ) => {
const nodes = [];
From a524bfb831f4c89caf8f2ad63edccddb06c02035 Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Wed, 17 Apr 2024 14:25:06 +1000
Subject: [PATCH 35/52] Make comment docblock
---
.../src/components/global-styles-provider/index.js | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/packages/editor/src/components/global-styles-provider/index.js b/packages/editor/src/components/global-styles-provider/index.js
index 8029077f2c8f2f..a81cb0c3d7bb10 100644
--- a/packages/editor/src/components/global-styles-provider/index.js
+++ b/packages/editor/src/components/global-styles-provider/index.js
@@ -33,8 +33,13 @@ export function mergeBaseAndUserConfigs( base, user ) {
} );
}
-// Resolves shared block style variation definitions from the user origin
-// under their respective block types and registers the block style if required.
+/**
+ * Resolves shared block style variation definitions from the user origin
+ * under their respective block types and registers the block style if required.
+ *
+ * @param {Object} userConfig Current user origin global styles data.
+ * @return {Object} Updated global styles data.
+ */
function useResolvedBlockStyleVariationsConfig( userConfig ) {
const getBlockStyles = useSelect( ( select ) => {
return select( blocksStore ).getBlockStyles;
From 1cede2ab53cf8a8d76a5810ce18731247f1122aa Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Wed, 17 Apr 2024 14:29:33 +1000
Subject: [PATCH 36/52] Use shorthand for retrieving getBlockStyles from
blocksStore
---
packages/block-editor/src/hooks/block-style-variation.js | 4 +---
.../editor/src/components/global-styles-provider/index.js | 4 +---
2 files changed, 2 insertions(+), 6 deletions(-)
diff --git a/packages/block-editor/src/hooks/block-style-variation.js b/packages/block-editor/src/hooks/block-style-variation.js
index 7cce3f9b1182ed..39568012ec2cb9 100644
--- a/packages/block-editor/src/hooks/block-style-variation.js
+++ b/packages/block-editor/src/hooks/block-style-variation.js
@@ -69,9 +69,7 @@ function useBlockProps( { name, className, clientId } ) {
const variation = getVariationNameFromClass( className );
const variationClass = `is-style-${ variation }-${ clientId }`;
- const getBlockStyles = useSelect( ( select ) => {
- return select( blocksStore ).getBlockStyles;
- }, [] );
+ const { getBlockStyles } = useSelect( blocksStore );
const { settings, styles } = useBlockSyleVariation(
name,
diff --git a/packages/editor/src/components/global-styles-provider/index.js b/packages/editor/src/components/global-styles-provider/index.js
index a81cb0c3d7bb10..26c6ace290acfe 100644
--- a/packages/editor/src/components/global-styles-provider/index.js
+++ b/packages/editor/src/components/global-styles-provider/index.js
@@ -41,9 +41,7 @@ export function mergeBaseAndUserConfigs( base, user ) {
* @return {Object} Updated global styles data.
*/
function useResolvedBlockStyleVariationsConfig( userConfig ) {
- const getBlockStyles = useSelect( ( select ) => {
- return select( blocksStore ).getBlockStyles;
- }, [] );
+ const { getBlockStyles } = useSelect( blocksStore );
return useMemo( () => {
const sharedVariations = userConfig?.styles?.blocks?.variations;
From 402a234a94cb58c250155955e9995f32914864b8 Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Wed, 17 Apr 2024 15:55:39 +1000
Subject: [PATCH 37/52] Split out user origin based block style registration to
useEffect
---
.../global-styles-provider/index.js | 36 ++++++++++++++-----
1 file changed, 28 insertions(+), 8 deletions(-)
diff --git a/packages/editor/src/components/global-styles-provider/index.js b/packages/editor/src/components/global-styles-provider/index.js
index 26c6ace290acfe..3496096c4d5664 100644
--- a/packages/editor/src/components/global-styles-provider/index.js
+++ b/packages/editor/src/components/global-styles-provider/index.js
@@ -11,7 +11,7 @@ import { registerBlockStyle, store as blocksStore } from '@wordpress/blocks';
import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor';
import { store as coreStore } from '@wordpress/core-data';
import { useSelect, useDispatch } from '@wordpress/data';
-import { useMemo, useCallback } from '@wordpress/element';
+import { useEffect, useMemo, useCallback } from '@wordpress/element';
/**
* Internal dependencies
@@ -43,15 +43,15 @@ export function mergeBaseAndUserConfigs( base, user ) {
function useResolvedBlockStyleVariationsConfig( userConfig ) {
const { getBlockStyles } = useSelect( blocksStore );
- return useMemo( () => {
+ // Register any block style variations that have been added
+ // by a theme style variation and are not already registered.
+ useEffect( () => {
const sharedVariations = userConfig?.styles?.blocks?.variations;
if ( ! sharedVariations ) {
- return userConfig;
+ return;
}
- const variationsConfig = cloneDeep( userConfig );
-
Object.entries( sharedVariations ).forEach(
( [ variationName, variation ] ) => {
if ( ! variation?.supportedBlockTypes ) {
@@ -59,8 +59,6 @@ function useResolvedBlockStyleVariationsConfig( userConfig ) {
}
variation.supportedBlockTypes.forEach( ( blockName ) => {
- // Register any block style variations that have been added
- // by a theme style variation and are not already registered.
const blockStyles = getBlockStyles( blockName );
const registeredBlockStyle = blockStyles.find(
( { name } ) => name === variationName
@@ -72,7 +70,27 @@ function useResolvedBlockStyleVariationsConfig( userConfig ) {
label: variationName,
} );
}
+ } );
+ }
+ );
+ }, [ userConfig?.styles?.blocks?.variations, getBlockStyles ] );
+
+ const updatedConfig = useMemo( () => {
+ const sharedVariations = userConfig?.styles?.blocks?.variations;
+
+ if ( ! sharedVariations ) {
+ return userConfig;
+ }
+
+ const variationsConfig = cloneDeep( userConfig );
+ Object.entries( sharedVariations ).forEach(
+ ( [ variationName, variation ] ) => {
+ if ( ! variation?.supportedBlockTypes ) {
+ return;
+ }
+
+ variation.supportedBlockTypes.forEach( ( blockName ) => {
const path = [
'styles',
'blocks',
@@ -86,7 +104,9 @@ function useResolvedBlockStyleVariationsConfig( userConfig ) {
);
return deepmerge( variationsConfig, userConfig );
- }, [ userConfig, getBlockStyles ] );
+ }, [ userConfig ] );
+
+ return updatedConfig;
}
function useGlobalStylesUserConfig() {
From a8690c4fc1bb40126867e099226d96ea380d9404 Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Wed, 17 Apr 2024 17:34:47 +1000
Subject: [PATCH 38/52] Fix issue with application of variations in the site
editor
---
.../block-editor/src/hooks/block-style-variation.js | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/packages/block-editor/src/hooks/block-style-variation.js b/packages/block-editor/src/hooks/block-style-variation.js
index 39568012ec2cb9..e7691b2aea63e3 100644
--- a/packages/block-editor/src/hooks/block-style-variation.js
+++ b/packages/block-editor/src/hooks/block-style-variation.js
@@ -22,7 +22,12 @@ function getVariationNameFromClass( className ) {
}
function useBlockSyleVariation( name, variation, clientId ) {
- const { user: userStyles } = useContext( GlobalStylesContext );
+ // Prefer global styles data in GlobalStylesContext, which are available
+ // if in the site editor. Otherwise fall back to whatever is in the
+ // editor settings and available in the post editor.
+ // This can be updated once the global styles data is consistently
+ // available across the editors.
+ const { merged: mergedConfig } = useContext( GlobalStylesContext );
const { globalSettings, globalStyles } = useSelect( ( select ) => {
const { __experimentalFeatures, __experimentalStyles } =
select( blockEditorStore ).getSettings();
@@ -33,12 +38,12 @@ function useBlockSyleVariation( name, variation, clientId ) {
}, [] );
return useMemo( () => {
- const styles = userStyles?.styles ?? globalStyles;
+ const styles = mergedConfig?.styles ?? globalStyles;
const variationStyles =
styles?.blocks?.[ name ]?.variations?.[ variation ];
return {
- settings: userStyles?.settings ?? globalSettings,
+ settings: mergedConfig?.settings ?? globalSettings,
// The variation style data is all that is needed to generate
// the styles for the current application to a block. The variation
// name is updated to match the instance specific class name.
@@ -53,7 +58,7 @@ function useBlockSyleVariation( name, variation, clientId ) {
},
};
}, [
- userStyles,
+ mergedConfig,
globalSettings,
globalStyles,
variation,
From 2b97374d9cdfb94b24d49465fc1337e3dc24609a Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Thu, 18 Apr 2024 12:34:46 +1000
Subject: [PATCH 39/52] Rename supportedBlockTypes to blockTypes
---
lib/block-supports/block-style-variations.php | 2 +-
lib/class-wp-theme-json-gutenberg.php | 2 +-
lib/class-wp-theme-json-resolver-gutenberg.php | 8 ++++----
.../components/global-styles-provider/index.js | 8 ++++----
phpunit/class-wp-theme-json-resolver-test.php | 16 ++++++++--------
.../styles/block-style-variation-a.json | 2 +-
.../styles/block-style-variation-a.json | 2 +-
.../styles/block-style-variation-b.json | 2 +-
schemas/json/theme.json | 4 ++--
9 files changed, 23 insertions(+), 23 deletions(-)
diff --git a/lib/block-supports/block-style-variations.php b/lib/block-supports/block-style-variations.php
index ecdc4e1498c557..a717bac4a21bab 100644
--- a/lib/block-supports/block-style-variations.php
+++ b/lib/block-supports/block-style-variations.php
@@ -173,7 +173,7 @@ function gutenberg_resolve_and_register_block_style_variations( $variations ) {
$have_named_variations = ! wp_is_numeric_array( $variations );
foreach ( $variations as $key => $variation ) {
- $supported_blocks = $variation['supportedBlockTypes'] ?? array();
+ $supported_blocks = $variation['blockTypes'] ?? array();
/*
* Standalone theme.json partial files for block style variations
diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php
index e5c6a1b12134f9..99de056143dd69 100644
--- a/lib/class-wp-theme-json-gutenberg.php
+++ b/lib/class-wp-theme-json-gutenberg.php
@@ -348,12 +348,12 @@ class WP_Theme_JSON_Gutenberg {
* @var string[]
*/
const VALID_TOP_LEVEL_KEYS = array(
+ 'blockTypes',
'customTemplates',
'description',
'patterns',
'settings',
'styles',
- 'supportedBlockTypes',
'templateParts',
'title',
'version',
diff --git a/lib/class-wp-theme-json-resolver-gutenberg.php b/lib/class-wp-theme-json-resolver-gutenberg.php
index d78eda9be0ef51..f13b1966b72de5 100644
--- a/lib/class-wp-theme-json-resolver-gutenberg.php
+++ b/lib/class-wp-theme-json-resolver-gutenberg.php
@@ -720,8 +720,8 @@ private static function recursively_iterate_json( $dir ) {
* Determines if a supplied style variation matches the provided scope.
*
* For backwards compatibility, if a variation does not define any scope
- * related property, e.g. `supportedBlockTypes`, it is assumed to be a
- * theme style variation.
+ * related property, e.g. `blockTypes`, it is assumed to be a theme style
+ * variation.
*
* @param array $variation Theme.json shaped style variation object.
* @param string $scope Scope to check e.g. theme, block etc.
@@ -730,11 +730,11 @@ private static function recursively_iterate_json( $dir ) {
*/
private static function style_variation_has_scope( $variation, $scope ) {
if ( 'block' === $scope ) {
- return isset( $variation['supportedBlockTypes'] );
+ return isset( $variation['blockTypes'] );
}
if ( 'theme' === $scope ) {
- return ! isset( $variation['supportedBlockTypes'] );
+ return ! isset( $variation['blockTypes'] );
}
return false;
diff --git a/packages/editor/src/components/global-styles-provider/index.js b/packages/editor/src/components/global-styles-provider/index.js
index 3496096c4d5664..cf2bee6dada6cf 100644
--- a/packages/editor/src/components/global-styles-provider/index.js
+++ b/packages/editor/src/components/global-styles-provider/index.js
@@ -54,11 +54,11 @@ function useResolvedBlockStyleVariationsConfig( userConfig ) {
Object.entries( sharedVariations ).forEach(
( [ variationName, variation ] ) => {
- if ( ! variation?.supportedBlockTypes ) {
+ if ( ! variation?.blockTypes ) {
return;
}
- variation.supportedBlockTypes.forEach( ( blockName ) => {
+ variation.blockTypes.forEach( ( blockName ) => {
const blockStyles = getBlockStyles( blockName );
const registeredBlockStyle = blockStyles.find(
( { name } ) => name === variationName
@@ -86,11 +86,11 @@ function useResolvedBlockStyleVariationsConfig( userConfig ) {
Object.entries( sharedVariations ).forEach(
( [ variationName, variation ] ) => {
- if ( ! variation?.supportedBlockTypes ) {
+ if ( ! variation?.blockTypes ) {
return;
}
- variation.supportedBlockTypes.forEach( ( blockName ) => {
+ variation.blockTypes.forEach( ( blockName ) => {
const path = [
'styles',
'blocks',
diff --git a/phpunit/class-wp-theme-json-resolver-test.php b/phpunit/class-wp-theme-json-resolver-test.php
index 8a68c7eed30611..23e2ebfcd673cd 100644
--- a/phpunit/class-wp-theme-json-resolver-test.php
+++ b/phpunit/class-wp-theme-json-resolver-test.php
@@ -1093,10 +1093,10 @@ public function data_get_style_variations() {
'scope' => 'block',
'expected_variations' => array(
array(
- 'supportedBlockTypes' => array( 'core/group', 'core/columns', 'core/media-text' ),
- 'version' => 2,
- 'title' => 'block-style-variation-a',
- 'styles' => array(
+ 'blockTypes' => array( 'core/group', 'core/columns', 'core/media-text' ),
+ 'version' => 2,
+ 'title' => 'block-style-variation-a',
+ 'styles' => array(
'color' => array(
'background' => 'darkcyan',
'text' => 'aliceblue',
@@ -1104,10 +1104,10 @@ public function data_get_style_variations() {
),
),
array(
- 'supportedBlockTypes' => array( 'core/group', 'core/columns' ),
- 'version' => 2,
- 'title' => 'block-style-variation-b',
- 'styles' => array(
+ 'blockTypes' => array( 'core/group', 'core/columns' ),
+ 'version' => 2,
+ 'title' => 'block-style-variation-b',
+ 'styles' => array(
'color' => array(
'background' => 'midnightblue',
'text' => 'lightblue',
diff --git a/phpunit/data/themedir1/block-theme-child-with-block-style-variations/styles/block-style-variation-a.json b/phpunit/data/themedir1/block-theme-child-with-block-style-variations/styles/block-style-variation-a.json
index 1daaac0062b9c6..660e4d9a684a8a 100644
--- a/phpunit/data/themedir1/block-theme-child-with-block-style-variations/styles/block-style-variation-a.json
+++ b/phpunit/data/themedir1/block-theme-child-with-block-style-variations/styles/block-style-variation-a.json
@@ -1,6 +1,6 @@
{
"version": 2,
- "supportedBlockTypes": [ "core/group", "core/columns", "core/media-text" ],
+ "blockTypes": [ "core/group", "core/columns", "core/media-text" ],
"styles": {
"color": {
"background": "darkcyan",
diff --git a/phpunit/data/themedir1/block-theme/styles/block-style-variation-a.json b/phpunit/data/themedir1/block-theme/styles/block-style-variation-a.json
index 0ba8417049eb0a..03b3b0a93d809e 100644
--- a/phpunit/data/themedir1/block-theme/styles/block-style-variation-a.json
+++ b/phpunit/data/themedir1/block-theme/styles/block-style-variation-a.json
@@ -1,6 +1,6 @@
{
"version": 2,
- "supportedBlockTypes": [ "core/group", "core/columns" ],
+ "blockTypes": [ "core/group", "core/columns" ],
"styles": {
"color": {
"background": "indigo",
diff --git a/phpunit/data/themedir1/block-theme/styles/block-style-variation-b.json b/phpunit/data/themedir1/block-theme/styles/block-style-variation-b.json
index 6133b3e9f8d591..161a19bdf4d576 100644
--- a/phpunit/data/themedir1/block-theme/styles/block-style-variation-b.json
+++ b/phpunit/data/themedir1/block-theme/styles/block-style-variation-b.json
@@ -1,6 +1,6 @@
{
"version": 2,
- "supportedBlockTypes": [ "core/group", "core/columns" ],
+ "blockTypes": [ "core/group", "core/columns" ],
"styles": {
"color": {
"background": "midnightblue",
diff --git a/schemas/json/theme.json b/schemas/json/theme.json
index f58214c6f774c4..6a3ec7e81d3947 100644
--- a/schemas/json/theme.json
+++ b/schemas/json/theme.json
@@ -2276,7 +2276,7 @@
},
{
"properties": {
- "supportedBlockTypes": {
+ "blockTypes": {
"type": "array",
"items": {
"type": "string"
@@ -2688,7 +2688,7 @@
"type": "string",
"description": "Description of the global styles variation."
},
- "supportedBlockTypes": {
+ "blockTypes": {
"type": "array",
"description": "List of block types that can use the block style variation this theme.json file represents.",
"items": {
From 92809eaa186edfb0335aad2d89f35a125acef558 Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Sat, 20 Apr 2024 15:44:15 +1000
Subject: [PATCH 40/52] Fix merging of theme style variations config
---
packages/editor/src/components/global-styles-provider/index.js | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/packages/editor/src/components/global-styles-provider/index.js b/packages/editor/src/components/global-styles-provider/index.js
index cf2bee6dada6cf..bb70fce156be9a 100644
--- a/packages/editor/src/components/global-styles-provider/index.js
+++ b/packages/editor/src/components/global-styles-provider/index.js
@@ -17,7 +17,6 @@ import { useEffect, useMemo, useCallback } from '@wordpress/element';
* Internal dependencies
*/
import { unlock } from '../../lock-unlock';
-import cloneDeep from '../../utils/clone-deep';
import setNestedValue from '../../utils/set-nested-value';
const { GlobalStylesContext, cleanEmptyObject } = unlock(
@@ -82,7 +81,7 @@ function useResolvedBlockStyleVariationsConfig( userConfig ) {
return userConfig;
}
- const variationsConfig = cloneDeep( userConfig );
+ const variationsConfig = {};
Object.entries( sharedVariations ).forEach(
( [ variationName, variation ] ) => {
From fca03a005b072a8ccd1e158dec65c181670a4042 Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Mon, 22 Apr 2024 18:09:26 +1000
Subject: [PATCH 41/52] Try optimisation of variation resolution in global
styles provider
---
.../global-styles-provider/index.js | 71 ++++++++++---------
1 file changed, 37 insertions(+), 34 deletions(-)
diff --git a/packages/editor/src/components/global-styles-provider/index.js b/packages/editor/src/components/global-styles-provider/index.js
index bb70fce156be9a..04a42ab7af819c 100644
--- a/packages/editor/src/components/global-styles-provider/index.js
+++ b/packages/editor/src/components/global-styles-provider/index.js
@@ -41,19 +41,21 @@ export function mergeBaseAndUserConfigs( base, user ) {
*/
function useResolvedBlockStyleVariationsConfig( userConfig ) {
const { getBlockStyles } = useSelect( blocksStore );
+ const sharedVariations = userConfig?.styles?.blocks?.variations;
- // Register any block style variations that have been added
- // by a theme style variation and are not already registered.
- useEffect( () => {
- const sharedVariations = userConfig?.styles?.blocks?.variations;
-
+ // Collect block style variation definitions to merge and unregistered
+ // block styles for automatic registration.
+ const [ userConfigToMerge, unregisteredStyles ] = useMemo( () => {
if ( ! sharedVariations ) {
- return;
+ return [];
}
+ const variationsConfigToMerge = {};
+ const unregisteredBlockStyles = [];
+
Object.entries( sharedVariations ).forEach(
( [ variationName, variation ] ) => {
- if ( ! variation?.blockTypes ) {
+ if ( ! variation?.blockTypes?.length ) {
return;
}
@@ -64,32 +66,15 @@ function useResolvedBlockStyleVariationsConfig( userConfig ) {
);
if ( ! registeredBlockStyle ) {
- registerBlockStyle( blockName, {
- name: variationName,
- label: variationName,
- } );
+ unregisteredBlockStyles.push( [
+ blockName,
+ {
+ name: variationName,
+ label: variationName,
+ },
+ ] );
}
- } );
- }
- );
- }, [ userConfig?.styles?.blocks?.variations, getBlockStyles ] );
-
- const updatedConfig = useMemo( () => {
- const sharedVariations = userConfig?.styles?.blocks?.variations;
- if ( ! sharedVariations ) {
- return userConfig;
- }
-
- const variationsConfig = {};
-
- Object.entries( sharedVariations ).forEach(
- ( [ variationName, variation ] ) => {
- if ( ! variation?.blockTypes ) {
- return;
- }
-
- variation.blockTypes.forEach( ( blockName ) => {
const path = [
'styles',
'blocks',
@@ -97,13 +82,31 @@ function useResolvedBlockStyleVariationsConfig( userConfig ) {
'variations',
variationName,
];
- setNestedValue( variationsConfig, path, variation );
+ setNestedValue( variationsConfigToMerge, path, variation );
} );
}
);
- return deepmerge( variationsConfig, userConfig );
- }, [ userConfig ] );
+ return [ variationsConfigToMerge, unregisteredBlockStyles ];
+ }, [ sharedVariations, getBlockStyles ] );
+
+ // Automatically register missing block styles from variations.
+ useEffect(
+ () =>
+ unregisteredStyles?.forEach( ( unregisteredStyle ) =>
+ registerBlockStyle( ...unregisteredStyle )
+ ),
+ [ unregisteredStyles ]
+ );
+
+ // Merge shared block style variation definitions into overall user config.
+ const updatedConfig = useMemo( () => {
+ if ( ! userConfigToMerge ) {
+ return userConfig;
+ }
+
+ return deepmerge( userConfigToMerge, userConfig );
+ }, [ userConfigToMerge, userConfig ] );
return updatedConfig;
}
From 00c22e58d8fbd24e9d82baf4da78d42f9f8d77f6 Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Wed, 24 Apr 2024 13:45:21 +1000
Subject: [PATCH 42/52] Move sorting of style overrides into getStyleOverrides
selector
---
.../src/components/editor-styles/index.js | 25 +++----------------
1 file changed, 4 insertions(+), 21 deletions(-)
diff --git a/packages/block-editor/src/components/editor-styles/index.js b/packages/block-editor/src/components/editor-styles/index.js
index 5e350fb1ebfbb5..2ede3e45566ed1 100644
--- a/packages/block-editor/src/components/editor-styles/index.js
+++ b/packages/block-editor/src/components/editor-styles/index.js
@@ -68,32 +68,15 @@ function useDarkThemeBodyClassName( styles, scope ) {
}
function EditorStyles( { styles, scope } ) {
- const { overrides, clientIds } = useSelect(
- ( select ) => ( {
- overrides: unlock( select( blockEditorStore ) ).getStyleOverrides(),
- clientIds: select( blockEditorStore ).getClientIdsWithDescendants(),
- } ),
+ const overrides = useSelect(
+ ( select ) => unlock( select( blockEditorStore ) ).getStyleOverrides(),
[]
);
const [ transformedStyles, transformedSvgs ] = useMemo( () => {
- const clientIdMap = clientIds.reduce( ( acc, clientId, index ) => {
- acc[ clientId ] = index;
- return acc;
- }, {} );
-
- // Sort overrides to match the order of blocks they relate to.
- // This is useful to maintain the correct CSS cascade order for
- // nested block style variations.
- const sortedOverrides = [ ...overrides ].sort( ( a, b ) => {
- const aIndex = clientIdMap[ a[ 1 ].clientId ] ?? -1;
- const bIndex = clientIdMap[ b[ 1 ].clientId ] ?? -1;
- return aIndex - bIndex;
- } );
-
const _styles = Object.values( styles ?? [] );
- for ( const [ id, override ] of sortedOverrides ) {
+ for ( const [ id, override ] of overrides ) {
const index = _styles.findIndex( ( { id: _id } ) => id === _id );
const overrideWithId = { ...override, id };
if ( index === -1 ) {
@@ -113,7 +96,7 @@ function EditorStyles( { styles, scope } ) {
.map( ( style ) => style.assets )
.join( '' ),
];
- }, [ styles, overrides, scope, clientIds ] );
+ }, [ styles, overrides, scope ] );
return (
<>
From afe5c982067fc11eeeede6913cf3a92cc328a6df Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Wed, 24 Apr 2024 19:49:59 +1000
Subject: [PATCH 43/52] Undo whitespace change
---
packages/block-editor/src/components/editor-styles/index.js | 1 -
1 file changed, 1 deletion(-)
diff --git a/packages/block-editor/src/components/editor-styles/index.js b/packages/block-editor/src/components/editor-styles/index.js
index 2ede3e45566ed1..34c4a90020e3be 100644
--- a/packages/block-editor/src/components/editor-styles/index.js
+++ b/packages/block-editor/src/components/editor-styles/index.js
@@ -72,7 +72,6 @@ function EditorStyles( { styles, scope } ) {
( select ) => unlock( select( blockEditorStore ) ).getStyleOverrides(),
[]
);
-
const [ transformedStyles, transformedSvgs ] = useMemo( () => {
const _styles = Object.values( styles ?? [] );
From 248188914dba663ef09a8e1350beb8b2cef65303 Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Fri, 10 May 2024 10:50:03 +0900
Subject: [PATCH 44/52] Revert "Make global styles data available in block
editor"
This reverts commit 6d0d2078dcd59ae45cd76a8a31c7178fe8360d49.
---
lib/block-editor-settings.php | 1 -
.../class-wp-rest-block-editor-settings-controller.php | 2 +-
.../editor/src/components/provider/use-block-editor-settings.js | 1 -
3 files changed, 1 insertion(+), 3 deletions(-)
diff --git a/lib/block-editor-settings.php b/lib/block-editor-settings.php
index ba726ffe2ad5b9..53668e114e04cb 100644
--- a/lib/block-editor-settings.php
+++ b/lib/block-editor-settings.php
@@ -78,7 +78,6 @@ function gutenberg_get_block_editor_settings( $settings ) {
$settings['styles'] = array_merge( $global_styles, get_block_editor_theme_styles() );
- $settings['__experimentalStyles'] = gutenberg_get_global_styles();
$settings['__experimentalFeatures'] = gutenberg_get_global_settings();
// These settings may need to be updated based on data coming from theme.json sources.
if ( isset( $settings['__experimentalFeatures']['color']['palette'] ) ) {
diff --git a/lib/experimental/class-wp-rest-block-editor-settings-controller.php b/lib/experimental/class-wp-rest-block-editor-settings-controller.php
index 2d0537ca0891c9..2c4bf29bc21a73 100644
--- a/lib/experimental/class-wp-rest-block-editor-settings-controller.php
+++ b/lib/experimental/class-wp-rest-block-editor-settings-controller.php
@@ -155,7 +155,7 @@ public function get_item_schema() {
'__experimentalStyles' => array(
'description' => __( 'Styles consolidated from core, theme, and user origins.', 'gutenberg' ),
'type' => 'object',
- 'context' => array( 'post-editor', 'site-editor', 'widgets-editor', 'mobile' ),
+ 'context' => array( 'mobile' ),
),
'__experimentalEnableQuoteBlockV2' => array(
diff --git a/packages/editor/src/components/provider/use-block-editor-settings.js b/packages/editor/src/components/provider/use-block-editor-settings.js
index bf0f6159f2ff96..2917c6905e3f0d 100644
--- a/packages/editor/src/components/provider/use-block-editor-settings.js
+++ b/packages/editor/src/components/provider/use-block-editor-settings.js
@@ -41,7 +41,6 @@ const BLOCK_EDITOR_SETTINGS = [
'__experimentalBlockDirectory',
'__experimentalDiscussionSettings',
'__experimentalFeatures',
- '__experimentalStyles',
'__experimentalGlobalStylesBaseStyles',
'__unstableGalleryWithImageBlocks',
'alignWide',
From c57996319a1da897c16e4dc6c9a3286da69272a4 Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Fri, 10 May 2024 10:57:20 +0900
Subject: [PATCH 45/52] Switch variation hook to use new global styles editor
setting
---
.../block-editor/src/hooks/block-style-variation.js | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/packages/block-editor/src/hooks/block-style-variation.js b/packages/block-editor/src/hooks/block-style-variation.js
index e7691b2aea63e3..1896c422d12375 100644
--- a/packages/block-editor/src/hooks/block-style-variation.js
+++ b/packages/block-editor/src/hooks/block-style-variation.js
@@ -15,6 +15,7 @@ import {
} from '../components/global-styles';
import { useStyleOverride } from './utils';
import { store as blockEditorStore } from '../store';
+import { globalStylesDataKey } from '../store/private-keys';
function getVariationNameFromClass( className ) {
const match = className?.match( /\bis-style-(?!default)(\S+)\b/ );
@@ -25,15 +26,12 @@ function useBlockSyleVariation( name, variation, clientId ) {
// Prefer global styles data in GlobalStylesContext, which are available
// if in the site editor. Otherwise fall back to whatever is in the
// editor settings and available in the post editor.
- // This can be updated once the global styles data is consistently
- // available across the editors.
const { merged: mergedConfig } = useContext( GlobalStylesContext );
const { globalSettings, globalStyles } = useSelect( ( select ) => {
- const { __experimentalFeatures, __experimentalStyles } =
- select( blockEditorStore ).getSettings();
+ const settings = select( blockEditorStore ).getSettings();
return {
- globalSettings: __experimentalFeatures,
- globalStyles: __experimentalStyles,
+ globalSettings: settings.__experimentalFeatures,
+ globalStyles: settings[ globalStylesDataKey ],
};
}, [] );
From 113c26929a31357cc91f3a71d5b0e28daee9912a Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Fri, 17 May 2024 16:33:02 +1000
Subject: [PATCH 46/52] Fix variations panel in site editor
---
packages/edit-site/src/components/global-styles/screen-block.js | 2 +-
.../src/components/global-styles/variations/variations-panel.js | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/packages/edit-site/src/components/global-styles/screen-block.js b/packages/edit-site/src/components/global-styles/screen-block.js
index 9811f10b834dab..2368f7499acbf6 100644
--- a/packages/edit-site/src/components/global-styles/screen-block.js
+++ b/packages/edit-site/src/components/global-styles/screen-block.js
@@ -235,7 +235,7 @@ function ScreenBlock( { name, variation } ) {
return (
<>
{ hasVariationsPanel && (
diff --git a/packages/edit-site/src/components/global-styles/variations/variations-panel.js b/packages/edit-site/src/components/global-styles/variations/variations-panel.js
index 6c03821705619f..f98cc65e5c95b1 100644
--- a/packages/edit-site/src/components/global-styles/variations/variations-panel.js
+++ b/packages/edit-site/src/components/global-styles/variations/variations-panel.js
@@ -31,7 +31,7 @@ export function useBlockVariations( name ) {
},
[ name ]
);
- const [ variations ] = useGlobalStyle( 'variations', name, 'base' );
+ const [ variations ] = useGlobalStyle( 'variations', name );
const variationNames = Object.keys( variations ?? {} );
return getFilteredBlockStyles( blockStyles, variationNames );
From e8ac4b2d98737b1c83a0fd7cb5f2c9ec6769e2e2 Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Tue, 28 May 2024 13:01:58 +1000
Subject: [PATCH 47/52] Make block style variation retrieval more robust
When old block style variation classes are left in a block's class string and they don't match a current variation, prevent them from blocking the first available variation.
---
lib/block-supports/block-style-variations.php | 29 ++++++++++------
.../src/hooks/block-style-variation.js | 34 +++++++++++++++----
2 files changed, 47 insertions(+), 16 deletions(-)
diff --git a/lib/block-supports/block-style-variations.php b/lib/block-supports/block-style-variations.php
index a717bac4a21bab..3a61cb6e3dd5aa 100644
--- a/lib/block-supports/block-style-variations.php
+++ b/lib/block-supports/block-style-variations.php
@@ -19,19 +19,19 @@ function gutenberg_get_block_style_variation_class_name( $block, $variation ) {
}
/**
- * Determine a block style variation name from a CSS class string.
+ * Determines the block style variation names within a CSS class string.
*
* @param string $class_string CSS class string to look for a variation in.
*
- * @return string|null The block style variation name if found.
+ * @return array|null The block style variation name if found.
*/
function gutenberg_get_block_style_variation_name_from_class( $class_string ) {
if ( ! is_string( $class_string ) ) {
return null;
}
- preg_match( '/\bis-style-(?!default)(\S+)\b/', $class_string, $matches );
- return $matches ? $matches[1] : null;
+ preg_match_all( '/\bis-style-(?!default)(\S+)\b/', $class_string, $matches );
+ return $matches[1] ?? null;
}
/**
@@ -49,16 +49,25 @@ function gutenberg_get_block_style_variation_name_from_class( $class_string ) {
* @return array The parsed block with block style variation classname added.
*/
function gutenberg_render_block_style_variation_support_styles( $parsed_block ) {
- $classes = $parsed_block['attrs']['className'] ?? null;
- $variation = gutenberg_get_block_style_variation_name_from_class( $classes );
+ $classes = $parsed_block['attrs']['className'] ?? null;
+ $variations = gutenberg_get_block_style_variation_name_from_class( $classes );
- if ( ! $variation ) {
+ if ( ! $variations ) {
return $parsed_block;
}
- $tree = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data();
- $theme_json = $tree->get_raw_data();
- $variation_data = $theme_json['styles']['blocks'][ $parsed_block['blockName'] ]['variations'][ $variation ] ?? array();
+ $tree = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data();
+ $theme_json = $tree->get_raw_data();
+
+ // Only the first block style variation with data is supported.
+ $variation_data = array();
+ foreach ( $variations as $variation ) {
+ $variation_data = $theme_json['styles']['blocks'][ $parsed_block['blockName'] ]['variations'][ $variation ] ?? array();
+
+ if ( ! empty( $variation_data ) ) {
+ break;
+ }
+ }
if ( empty( $variation_data ) ) {
return $parsed_block;
diff --git a/packages/block-editor/src/hooks/block-style-variation.js b/packages/block-editor/src/hooks/block-style-variation.js
index 1896c422d12375..ee02b97d216704 100644
--- a/packages/block-editor/src/hooks/block-style-variation.js
+++ b/packages/block-editor/src/hooks/block-style-variation.js
@@ -17,9 +17,30 @@ import { useStyleOverride } from './utils';
import { store as blockEditorStore } from '../store';
import { globalStylesDataKey } from '../store/private-keys';
-function getVariationNameFromClass( className ) {
- const match = className?.match( /\bis-style-(?!default)(\S+)\b/ );
- return match ? match[ 1 ] : null;
+/**
+ * Get the first block style variation that has been registered from the class string.
+ *
+ * @param {string} className CSS class string for a block.
+ * @param {Array} registeredStyles Currently registered block styles.
+ *
+ * @return {string|null} The name of the first registered variation.
+ */
+function getVariationNameFromClass( className, registeredStyles = [] ) {
+ // The global flag affects how capturing groups work in JS. So the regex
+ // below will only return full CSS classes not just the variation name.
+ const matches = className?.match( /\bis-style-(?!default)(\S+)\b/g );
+
+ if ( ! matches ) {
+ return null;
+ }
+
+ for ( const variationClass of matches ) {
+ const variation = variationClass.substring( 9 ); // Remove 'is-style-' prefix.
+ if ( registeredStyles.some( ( style ) => style.name === variation ) ) {
+ return variation;
+ }
+ }
+ return null;
}
function useBlockSyleVariation( name, variation, clientId ) {
@@ -69,11 +90,12 @@ function useBlockSyleVariation( name, variation, clientId ) {
// This is so that the variation style override's ID is predictable
// when the order of applied style variations changes.
function useBlockProps( { name, className, clientId } ) {
- const variation = getVariationNameFromClass( className );
- const variationClass = `is-style-${ variation }-${ clientId }`;
-
const { getBlockStyles } = useSelect( blocksStore );
+ const registeredStyles = getBlockStyles( name );
+ const variation = getVariationNameFromClass( className, registeredStyles );
+ const variationClass = `is-style-${ variation }-${ clientId }`;
+
const { settings, styles } = useBlockSyleVariation(
name,
variation,
From e2d27d30a0f04c876ca3d40a8bc7c5b4c2c07e11 Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Tue, 28 May 2024 13:28:04 +1000
Subject: [PATCH 48/52] Update test block theme json versions to latest
---
.../styles/block-style-variation-a.json | 2 +-
.../block-theme-child-with-block-style-variations/theme.json | 2 +-
.../themedir1/block-theme/styles/block-style-variation-a.json | 2 +-
.../themedir1/block-theme/styles/block-style-variation-b.json | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/phpunit/data/themedir1/block-theme-child-with-block-style-variations/styles/block-style-variation-a.json b/phpunit/data/themedir1/block-theme-child-with-block-style-variations/styles/block-style-variation-a.json
index 660e4d9a684a8a..195321a33b3366 100644
--- a/phpunit/data/themedir1/block-theme-child-with-block-style-variations/styles/block-style-variation-a.json
+++ b/phpunit/data/themedir1/block-theme-child-with-block-style-variations/styles/block-style-variation-a.json
@@ -1,5 +1,5 @@
{
- "version": 2,
+ "version": 3,
"blockTypes": [ "core/group", "core/columns", "core/media-text" ],
"styles": {
"color": {
diff --git a/phpunit/data/themedir1/block-theme-child-with-block-style-variations/theme.json b/phpunit/data/themedir1/block-theme-child-with-block-style-variations/theme.json
index 0da29ef16fd679..a471d8f326a4ab 100644
--- a/phpunit/data/themedir1/block-theme-child-with-block-style-variations/theme.json
+++ b/phpunit/data/themedir1/block-theme-child-with-block-style-variations/theme.json
@@ -1,4 +1,4 @@
{
"$schema": "https://schemas.wp.org/trunk/theme.json",
- "version": 2
+ "version": 3
}
diff --git a/phpunit/data/themedir1/block-theme/styles/block-style-variation-a.json b/phpunit/data/themedir1/block-theme/styles/block-style-variation-a.json
index 03b3b0a93d809e..356bc4fc3de7d3 100644
--- a/phpunit/data/themedir1/block-theme/styles/block-style-variation-a.json
+++ b/phpunit/data/themedir1/block-theme/styles/block-style-variation-a.json
@@ -1,5 +1,5 @@
{
- "version": 2,
+ "version": 3,
"blockTypes": [ "core/group", "core/columns" ],
"styles": {
"color": {
diff --git a/phpunit/data/themedir1/block-theme/styles/block-style-variation-b.json b/phpunit/data/themedir1/block-theme/styles/block-style-variation-b.json
index 161a19bdf4d576..8b79948517255f 100644
--- a/phpunit/data/themedir1/block-theme/styles/block-style-variation-b.json
+++ b/phpunit/data/themedir1/block-theme/styles/block-style-variation-b.json
@@ -1,5 +1,5 @@
{
- "version": 2,
+ "version": 3,
"blockTypes": [ "core/group", "core/columns" ],
"styles": {
"color": {
From e963725146974dd23e5840aa6c188dea865c26de Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Tue, 28 May 2024 14:57:24 +1000
Subject: [PATCH 49/52] Update missed theme json version numbers in tests
---
phpunit/class-wp-theme-json-resolver-test.php | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/phpunit/class-wp-theme-json-resolver-test.php b/phpunit/class-wp-theme-json-resolver-test.php
index 23e2ebfcd673cd..9aa277469fc1eb 100644
--- a/phpunit/class-wp-theme-json-resolver-test.php
+++ b/phpunit/class-wp-theme-json-resolver-test.php
@@ -1094,7 +1094,7 @@ public function data_get_style_variations() {
'expected_variations' => array(
array(
'blockTypes' => array( 'core/group', 'core/columns', 'core/media-text' ),
- 'version' => 2,
+ 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
'title' => 'block-style-variation-a',
'styles' => array(
'color' => array(
@@ -1105,7 +1105,7 @@ public function data_get_style_variations() {
),
array(
'blockTypes' => array( 'core/group', 'core/columns' ),
- 'version' => 2,
+ 'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
'title' => 'block-style-variation-b',
'styles' => array(
'color' => array(
From df4a51858d2821b41fe0702fd309321679a497b7 Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Tue, 28 May 2024 20:43:34 +1000
Subject: [PATCH 50/52] Pass clientId directly through to block props component
---
packages/block-editor/src/hooks/utils.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/packages/block-editor/src/hooks/utils.js b/packages/block-editor/src/hooks/utils.js
index 4beb5c9122f537..c14b6329cf2ec3 100644
--- a/packages/block-editor/src/hooks/utils.js
+++ b/packages/block-editor/src/hooks/utils.js
@@ -568,7 +568,7 @@ export function createBlockListBlockFilter( features ) {
useBlockProps,
} = feature;
- const neededProps = { clientId: props.clientId };
+ const neededProps = {};
for ( const key of attributeKeys ) {
if ( props.attributes[ key ] ) {
neededProps[ key ] = props.attributes[ key ];
@@ -595,6 +595,7 @@ export function createBlockListBlockFilter( features ) {
// function reference.
setAllWrapperProps={ setAllWrapperProps }
name={ props.name }
+ clientId={ props.clientId }
// This component is pure, so only pass needed
// props!!!
{ ...neededProps }
From 33830c4a628890b8d3f6233356aff64a77ebfc90 Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Wed, 29 May 2024 10:52:11 +1000
Subject: [PATCH 51/52] Add @since comments
---
lib/block-supports/block-style-variations.php | 22 +++++++++++++++++++
lib/class-wp-theme-json-gutenberg.php | 4 ++++
...class-wp-theme-json-resolver-gutenberg.php | 6 +++--
.../block-style-variations-test.php | 2 ++
phpunit/class-wp-theme-json-resolver-test.php | 4 ++++
5 files changed, 36 insertions(+), 2 deletions(-)
diff --git a/lib/block-supports/block-style-variations.php b/lib/block-supports/block-style-variations.php
index 3a61cb6e3dd5aa..6fc89b01c6793d 100644
--- a/lib/block-supports/block-style-variations.php
+++ b/lib/block-supports/block-style-variations.php
@@ -9,6 +9,8 @@
/**
* Get the class name for this application of this block's variation styles.
*
+ * @since 6.6.0
+ *
* @param array $block Block object.
* @param string $variation Slug for the block style variation.
*
@@ -21,6 +23,8 @@ function gutenberg_get_block_style_variation_class_name( $block, $variation ) {
/**
* Determines the block style variation names within a CSS class string.
*
+ * @since 6.6.0
+ *
* @param string $class_string CSS class string to look for a variation in.
*
* @return array|null The block style variation name if found.
@@ -44,6 +48,8 @@ function gutenberg_get_block_style_variation_name_from_class( $class_string ) {
* in the DOM order. This is why the variation stylesheet generation is in a
* different filter.
*
+ * @since 6.6.0
+ *
* @param array $parsed_block The parsed block.
*
* @return array The parsed block with block style variation classname added.
@@ -125,6 +131,8 @@ function gutenberg_render_block_style_variation_support_styles( $parsed_block )
*
* @see gutenberg_render_block_style_variation_support_styles
*
+ * @since 6.6.0
+ *
* @param string $block_content Rendered block content.
* @param array $block Block object.
*
@@ -167,6 +175,8 @@ function gutenberg_render_block_style_variation_class_name( $block_content, $blo
* been already. This registration is required for later sanitization of
* theme.json data.
*
+ * @since 6.6.0
+ *
* @param array $variations Shared block style variations.
*
* @return array Block variations data to be merged under styles.blocks
@@ -230,6 +240,8 @@ function gutenberg_resolve_and_register_block_style_variations( $variations ) {
* Merges variations data with existing theme.json data ensuring that the
* current theme.json data values take precedence.
*
+ * @since 6.6.0
+ *
* @param array $variations_data Block style variations data keyed by block type.
* @param WP_Theme_JSON_Data_Gutenberg $theme_json Current theme.json data.
* @param string $origin Origin for the theme.json data.
@@ -261,6 +273,8 @@ function gutenberg_merge_block_style_variations_data( $variations_data, $theme_j
* custom user selections already made will take precedence over the shared
* style variation value.
*
+ * @since 6.6.0
+ *
* @param WP_Theme_JSON_Data_Gutenberg $theme_json Current theme.json data.
*
* @return WP_Theme_JSON_Data_Gutenberg
@@ -277,6 +291,8 @@ function gutenberg_resolve_block_style_variations_from_theme_style_variation( $t
* Merges block style variation data sourced from standalone partial
* theme.json files.
*
+ * @since 6.6.0
+ *
* @param WP_Theme_JSON_Data_Gutenberg $theme_json Current theme.json data.
*
* @return WP_Theme_JSON_Data_Gutenberg
@@ -292,6 +308,8 @@ function gutenberg_resolve_block_style_variations_from_theme_json_partials( $the
* Merges shared block style variations registered within the
* `styles.blocks.variations` property of the primary theme.json file.
*
+ * @since 6.6.0
+ *
* @param WP_Theme_JSON_Data_Gutenberg $theme_json Current theme.json data.
*
* @return WP_Theme_JSON_Data_Gutenberg
@@ -310,6 +328,8 @@ function gutenberg_resolve_block_style_variations_from_primary_theme_json( $them
* Any variation values defined within the theme.json specific to a block type
* will take precedence over these shared definitions.
*
+ * @since 6.6.0
+ *
* @param WP_Theme_JSON_Data_Gutenberg $theme_json Current theme.json data.
*
* @return WP_Theme_JSON_Data_Gutenberg
@@ -333,6 +353,8 @@ function gutenberg_resolve_block_style_variations_from_styles_registry( $theme_j
/**
* Enqueues styles for block style variations.
+ *
+ * @since 6.6.0
*/
function gutenberg_enqueue_block_style_variation_styles() {
wp_enqueue_style( 'block-style-variation-styles' );
diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php
index 99de056143dd69..04fe19027a4d64 100644
--- a/lib/class-wp-theme-json-gutenberg.php
+++ b/lib/class-wp-theme-json-gutenberg.php
@@ -817,6 +817,7 @@ protected static function do_opt_in_into_settings( &$context ) {
*
* @since 5.8.0
* @since 5.9.0 Added the `$valid_block_names` and `$valid_element_name` parameters.
+ * @since 6.6.0 Extended schema definition to allow enhanced block style variations.
*
* @param array $input Structure to sanitize.
* @param array $valid_block_names List of valid block names.
@@ -1033,6 +1034,7 @@ protected static function prepend_to_selector( $selector, $to_prepend ) {
* @since 5.8.0
* @since 5.9.0 Added `duotone` key with CSS selector.
* @since 6.1.0 Added `features` key with block support feature level selectors.
+ * @since 6.6.0 Added non-core block style variations to generated metadata.
*
* @return array Block metadata.
*/
@@ -1220,6 +1222,7 @@ public function get_settings() {
*
* @since 5.8.0
* @since 5.9.0 Removed the `$type` parameter`, added the `$types` and `$origins` parameters.
+ * @since 6.6.0 Added option to skip root layout styles.
*
* @param array $types Types of styles to load. Will load all by default. It accepts:
* - `variables`: only the CSS Custom Properties for presets & custom ones.
@@ -3218,6 +3221,7 @@ protected static function filter_slugs( $node, $slugs ) {
* Removes insecure data from theme.json.
*
* @since 5.9.0
+ * @since 6.6.0 Added support for block style variation element styles.
*
* @param array $theme_json Structure to sanitize.
* @return array Sanitized structure.
diff --git a/lib/class-wp-theme-json-resolver-gutenberg.php b/lib/class-wp-theme-json-resolver-gutenberg.php
index f13b1966b72de5..b21fb956ff8ff7 100644
--- a/lib/class-wp-theme-json-resolver-gutenberg.php
+++ b/lib/class-wp-theme-json-resolver-gutenberg.php
@@ -723,6 +723,8 @@ private static function recursively_iterate_json( $dir ) {
* related property, e.g. `blockTypes`, it is assumed to be a theme style
* variation.
*
+ * @since 6.6.0
+ *
* @param array $variation Theme.json shaped style variation object.
* @param string $scope Scope to check e.g. theme, block etc.
*
@@ -794,7 +796,7 @@ public static function get_style_variations( $scope = 'theme' ) {
*
* @since 6.6.0
*
- * @param WP_Theme_JSON_Gutenberg $theme_json A theme json instance.
+ * @param WP_Theme_JSON_Gutenberg $theme_json A theme json instance.
* @return array An array of resolved paths.
*/
public static function get_resolved_theme_uris( $theme_json ) {
@@ -837,7 +839,7 @@ public static function get_resolved_theme_uris( $theme_json ) {
*
* @since 6.6.0
*
- * @param WP_Theme_JSON_Gutenberg $theme_json A theme json instance.
+ * @param WP_Theme_JSON_Gutenberg $theme_json A theme json instance.
* @return WP_Theme_JSON_Gutenberg Theme merged with resolved paths, if any found.
*/
public static function resolve_theme_file_uris( $theme_json ) {
diff --git a/phpunit/block-supports/block-style-variations-test.php b/phpunit/block-supports/block-style-variations-test.php
index 99d87d4736bd1a..b84267446330cc 100644
--- a/phpunit/block-supports/block-style-variations-test.php
+++ b/phpunit/block-supports/block-style-variations-test.php
@@ -3,6 +3,8 @@
/**
* Test the block style variations block support.
*
+ * @since 6.6.0
+ *
* @package Gutenberg
*/
diff --git a/phpunit/class-wp-theme-json-resolver-test.php b/phpunit/class-wp-theme-json-resolver-test.php
index 9aa277469fc1eb..50e1d9d846899e 100644
--- a/phpunit/class-wp-theme-json-resolver-test.php
+++ b/phpunit/class-wp-theme-json-resolver-test.php
@@ -991,6 +991,8 @@ public function data_get_merged_data_returns_origin() {
*
* @dataProvider data_get_style_variations
*
+ * @since 6.6.0 Added tests for block style variations.
+ *
* @param string $theme Name of the theme to use.
* @param string $scope Scope to filter variations by e.g. theme vs block.
* @param array $expected_variations Collection of expected variations.
@@ -1010,6 +1012,8 @@ public function test_get_style_variations( $theme, $scope, $expected_variations
/**
* Data provider for test_get_style_variations
*
+ * @since 6.6.0 Added data provider for testing theme and block style variations.
+ *
* @return array
*/
public function data_get_style_variations() {
From 168b5e42caa6f92efc21dbc44d6ffa1000cde1da Mon Sep 17 00:00:00 2001
From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com>
Date: Wed, 29 May 2024 13:05:28 +1000
Subject: [PATCH 52/52] Add backport change log
---
backport-changelog/6.6/6662.md | 3 +++
1 file changed, 3 insertions(+)
create mode 100644 backport-changelog/6.6/6662.md
diff --git a/backport-changelog/6.6/6662.md b/backport-changelog/6.6/6662.md
new file mode 100644
index 00000000000000..2dfbc68dd23e03
--- /dev/null
+++ b/backport-changelog/6.6/6662.md
@@ -0,0 +1,3 @@
+https://github.com/WordPress/wordpress-develop/pull/6662
+
+* https://github.com/WordPress/gutenberg/pull/57908