From 7e6a8f6f85db1449fcaf3fb2442f3aaf05decf32 Mon Sep 17 00:00:00 2001 From: Ben Dwyer Date: Thu, 21 Apr 2022 12:06:08 +0100 Subject: [PATCH 1/5] Global Style: Add Global Styles CSS to inline block CSS --- ...enberg.php => class-wp-theme-json-6-0.php} | 2 +- .../wordpress-6.1/class-wp-theme-json-6-1.php | 190 ++++++++++++++++++ .../class-wp-theme-json-resolver-6-1.php | 36 ++++ .../get-global-styles-and-settings.php | 133 ++++++++++++ lib/compat/wordpress-6.1/script-loader.php | 49 +++++ .../class-wp-theme-json-gutenberg.php | 19 ++ lib/load.php | 7 +- 7 files changed, 434 insertions(+), 2 deletions(-) rename lib/compat/wordpress-6.0/{class-wp-theme-json-gutenberg.php => class-wp-theme-json-6-0.php} (99%) create mode 100644 lib/compat/wordpress-6.1/class-wp-theme-json-6-1.php create mode 100644 lib/compat/wordpress-6.1/class-wp-theme-json-resolver-6-1.php create mode 100644 lib/compat/wordpress-6.1/get-global-styles-and-settings.php create mode 100644 lib/compat/wordpress-6.1/script-loader.php create mode 100644 lib/experimental/class-wp-theme-json-gutenberg.php diff --git a/lib/compat/wordpress-6.0/class-wp-theme-json-gutenberg.php b/lib/compat/wordpress-6.0/class-wp-theme-json-6-0.php similarity index 99% rename from lib/compat/wordpress-6.0/class-wp-theme-json-gutenberg.php rename to lib/compat/wordpress-6.0/class-wp-theme-json-6-0.php index 668082863114fa..1a0945b1754223 100644 --- a/lib/compat/wordpress-6.0/class-wp-theme-json-gutenberg.php +++ b/lib/compat/wordpress-6.0/class-wp-theme-json-6-0.php @@ -14,7 +14,7 @@ * * @access private */ -class WP_Theme_JSON_Gutenberg extends WP_Theme_JSON_5_9 { +class WP_Theme_JSON_6_0 extends WP_Theme_JSON_5_9 { /** * Metadata for style properties. * diff --git a/lib/compat/wordpress-6.1/class-wp-theme-json-6-1.php b/lib/compat/wordpress-6.1/class-wp-theme-json-6-1.php new file mode 100644 index 00000000000000..a22bc75762dd00 --- /dev/null +++ b/lib/compat/wordpress-6.1/class-wp-theme-json-6-1.php @@ -0,0 +1,190 @@ +theme_json, $blocks_metadata, $separate_block_assets ); + $setting_nodes = static::get_setting_nodes( $this->theme_json, $blocks_metadata ); + + $stylesheet = ''; + + if ( in_array( 'variables', $types, true ) ) { + $stylesheet .= $this->get_css_variables( $setting_nodes, $origins ); + } + + if ( in_array( 'styles', $types, true ) ) { + $stylesheet .= $this->get_block_classes( $style_nodes_without_blocks ); + } + + if ( in_array( 'presets', $types, true ) ) { + $stylesheet .= $this->get_preset_classes( $setting_nodes, $origins ); + } + + return $stylesheet; + } + + /** + * Builds metadata for the style nodes, which returns in the form of: + * + * [ + * [ + * 'path' => [ 'path', 'to', 'some', 'node' ], + * 'selector' => 'CSS selector for some node', + * 'duotone' => 'CSS selector for duotone for some node' + * ], + * [ + * 'path' => ['path', 'to', 'other', 'node' ], + * 'selector' => 'CSS selector for other node', + * 'duotone' => null + * ], + * ] + * + * @since 5.8.0 + * + * @param array $theme_json The tree to extract style nodes from. + * @param array $selectors List of selectors per block. + * @param array $exclude_blocks Exclude blocks from the style nodes. + * @return array + */ + protected static function get_style_nodes( $theme_json, $selectors = array(), $exclude_blocks = false ) { + $nodes = array(); + if ( ! isset( $theme_json['styles'] ) ) { + return $nodes; + } + + // Top-level. + $nodes[] = array( + 'path' => array( 'styles' ), + 'selector' => static::ROOT_BLOCK_SELECTOR, + ); + + if ( isset( $theme_json['styles']['elements'] ) ) { + foreach ( $theme_json['styles']['elements'] as $element => $node ) { + $nodes[] = array( + 'path' => array( 'styles', 'elements', $element ), + 'selector' => static::ELEMENTS[ $element ], + ); + } + } + + if ( $exclude_blocks ) { + return $nodes; + } + + // Blocks. + if ( ! isset( $theme_json['styles']['blocks'] ) ) { + return $nodes; + } + + // TODO - test this ( turn off separate assets i think) + $nodes = array_merge( $nodes, static::get_block_nodes_private( $theme_json ) ); + + return $nodes; + } + + // TODO - this is duplicated from get_style_nodes. + public function get_block_nodes() { + return static::get_block_nodes_private( $this->theme_json ); + } + + private static function get_block_nodes_private( $theme_json ) { + $selectors = static::get_blocks_metadata(); + $nodes = array(); + if ( ! isset( $theme_json['styles'] ) ) { + return $nodes; + } + + // Blocks. + if ( ! isset( $theme_json['styles']['blocks'] ) ) { + return $nodes; + } + + foreach ( $theme_json['styles']['blocks'] as $name => $node ) { + $selector = null; + if ( isset( $selectors[ $name ]['selector'] ) ) { + $selector = $selectors[ $name ]['selector']; + } + + $duotone_selector = null; + if ( isset( $selectors[ $name ]['duotone'] ) ) { + $duotone_selector = $selectors[ $name ]['duotone']; + } + + $nodes[] = array( + 'name' => $name, + 'path' => array( 'styles', 'blocks', $name ), + 'selector' => $selector, + 'duotone' => $duotone_selector, + ); + + if ( isset( $theme_json['styles']['blocks'][ $name ]['elements'] ) ) { + foreach ( $theme_json['styles']['blocks'][ $name ]['elements'] as $element => $node ) { + $nodes[] = array( + 'path' => array( 'styles', 'blocks', $name, 'elements', $element ), + 'selector' => $selectors[ $name ]['elements'][ $element ], + ); + } + } + } + + return $nodes; + } + + /** + * Gets the CSS rules for a particular block from theme.json. + * + * @param array $block_metadata Meta data about the block to get styles for. + * + * @return array Styles for the block. + */ + public function get_styles_for_block( $block_metadata ) { + $node = _wp_array_get( $this->theme_json, $block_metadata['path'], array() ); + $selector = $block_metadata['selector']; + $settings = _wp_array_get( $this->theme_json, array( 'settings' ) ); + $declarations = static::compute_style_properties( $node, $settings ); + $block_rules = static::to_ruleset( $selector, $declarations ); + return $block_rules; + } +} diff --git a/lib/compat/wordpress-6.1/class-wp-theme-json-resolver-6-1.php b/lib/compat/wordpress-6.1/class-wp-theme-json-resolver-6-1.php new file mode 100644 index 00000000000000..e155a1db73e81d --- /dev/null +++ b/lib/compat/wordpress-6.1/class-wp-theme-json-resolver-6-1.php @@ -0,0 +1,36 @@ +merge( static::get_core_data() ); + $result->merge( static::get_theme_data() ); + + if ( 'custom' === $origin ) { + $result->merge( static::get_user_data() ); + } + + return $result; + } +} diff --git a/lib/compat/wordpress-6.1/get-global-styles-and-settings.php b/lib/compat/wordpress-6.1/get-global-styles-and-settings.php new file mode 100644 index 00000000000000..f920a6ad35102c --- /dev/null +++ b/lib/compat/wordpress-6.1/get-global-styles-and-settings.php @@ -0,0 +1,133 @@ +get_stylesheet( array( 'variables' ) ); + $types = array_diff( $types, array( 'variables' ) ); + } + + /* + * For the remaining types (presets, styles), we do consider origins: + * + * - themes without theme.json: only the classes for the presets defined by core + * - themes with theme.json: the presets and styles classes, both from core and the theme + */ + $styles_rest = ''; + if ( ! empty( $types ) ) { + $origins = array( 'default', 'theme', 'custom' ); + if ( ! $supports_theme_json ) { + $origins = array( 'default' ); + } + $styles_rest = $tree->get_stylesheet( $types, $origins ); + } + + $stylesheet = $styles_variables . $styles_rest; + + if ( $can_use_cached ) { + // Cache for a minute. + // This cache doesn't need to be any longer, we only want to avoid spikes on high-traffic sites. + set_transient( $transient_name, $stylesheet, MINUTE_IN_SECONDS ); + } + + return $stylesheet; +} + +/** + * Adds global style rules to the inline style for each block. + */ +function wp_add_global_styles_for_blocks() { + $tree = WP_Theme_JSON_Resolver_6_1::get_merged_data(); + // TODO some nodes dont have a name... + $block_nodes = $tree->get_block_nodes(); + + foreach ( $block_nodes as $metadata ) { + + $block_css = $tree->get_styles_for_block( $metadata ); + $block_name = str_replace( 'core/', '', $metadata['name'] ); + wp_add_inline_style( "wp-block-" . $block_name, $block_css ); + + /* this might be needed for duotone styles? + + if ( null === $metadata['selector'] ) { + continue; + } + $node = _wp_array_get( $this->theme_json, $metadata['path'], array() ); + $selector = $metadata['selector']; + $settings = _wp_array_get( $this->theme_json, array( 'settings' ) ); + $declarations = static::compute_style_properties( $node, $settings ); + + // 1. Separate the ones who use the general selector + // and the ones who use the duotone selector. + $declarations_duotone = array(); + foreach ( $declarations as $index => $declaration ) { + if ( 'filter' === $declaration['name'] ) { + unset( $declarations[ $index ] ); + $declarations_duotone[] = $declaration; + } + } + + // 2. Generate the rules that use the general selector. + $block_rules .= static::to_ruleset( $selector, $declarations ); + + // 3. Generate the rules that use the duotone selector. + if ( isset( $metadata['duotone'] ) && ! empty( $declarations_duotone ) ) { + $selector_duotone = static::scope_selector( $metadata['selector'], $metadata['duotone'] ); + $block_rules .= static::to_ruleset( $selector_duotone, $declarations_duotone ); + }*/ + + + } + +} diff --git a/lib/compat/wordpress-6.1/script-loader.php b/lib/compat/wordpress-6.1/script-loader.php new file mode 100644 index 00000000000000..36add7e913e44d --- /dev/null +++ b/lib/compat/wordpress-6.1/script-loader.php @@ -0,0 +1,49 @@ + Date: Thu, 21 Apr 2022 12:18:42 +0100 Subject: [PATCH 2/5] remove unneeded code --- .../class-wp-theme-json-resolver-6-1.php | 36 ------------------- .../get-global-styles-and-settings.php | 2 +- lib/load.php | 1 - 3 files changed, 1 insertion(+), 38 deletions(-) delete mode 100644 lib/compat/wordpress-6.1/class-wp-theme-json-resolver-6-1.php diff --git a/lib/compat/wordpress-6.1/class-wp-theme-json-resolver-6-1.php b/lib/compat/wordpress-6.1/class-wp-theme-json-resolver-6-1.php deleted file mode 100644 index e155a1db73e81d..00000000000000 --- a/lib/compat/wordpress-6.1/class-wp-theme-json-resolver-6-1.php +++ /dev/null @@ -1,36 +0,0 @@ -merge( static::get_core_data() ); - $result->merge( static::get_theme_data() ); - - if ( 'custom' === $origin ) { - $result->merge( static::get_user_data() ); - } - - return $result; - } -} diff --git a/lib/compat/wordpress-6.1/get-global-styles-and-settings.php b/lib/compat/wordpress-6.1/get-global-styles-and-settings.php index f920a6ad35102c..631bc3ad60cfb2 100644 --- a/lib/compat/wordpress-6.1/get-global-styles-and-settings.php +++ b/lib/compat/wordpress-6.1/get-global-styles-and-settings.php @@ -88,7 +88,7 @@ function wp_get_global_stylesheet_gutenberg( $types = array() ) { * Adds global style rules to the inline style for each block. */ function wp_add_global_styles_for_blocks() { - $tree = WP_Theme_JSON_Resolver_6_1::get_merged_data(); + $tree = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data(); // TODO some nodes dont have a name... $block_nodes = $tree->get_block_nodes(); diff --git a/lib/load.php b/lib/load.php index 308bae3c0854c0..1688d65a822631 100644 --- a/lib/load.php +++ b/lib/load.php @@ -126,7 +126,6 @@ function gutenberg_is_experiment_enabled( $name ) { require __DIR__ . '/compat/wordpress-6.1/blocks.php'; require __DIR__ . '/compat/wordpress-6.1/get-global-styles-and-settings.php'; require __DIR__ . '/compat/wordpress-6.1/class-wp-theme-json-6-1.php'; -require __DIR__ . '/compat/wordpress-6.1/class-wp-theme-json-resolver-6-1.php'; require __DIR__ . '/compat/wordpress-6.1/script-loader.php'; // Experimental features. From 109cac5f46a99efba15d95714c18f67fe84678f7 Mon Sep 17 00:00:00 2001 From: Ben Dwyer Date: Thu, 21 Apr 2022 12:49:07 +0100 Subject: [PATCH 3/5] remove old comments --- lib/compat/wordpress-6.1/class-wp-theme-json-6-1.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/compat/wordpress-6.1/class-wp-theme-json-6-1.php b/lib/compat/wordpress-6.1/class-wp-theme-json-6-1.php index a22bc75762dd00..5def1984eb6e26 100644 --- a/lib/compat/wordpress-6.1/class-wp-theme-json-6-1.php +++ b/lib/compat/wordpress-6.1/class-wp-theme-json-6-1.php @@ -118,13 +118,11 @@ protected static function get_style_nodes( $theme_json, $selectors = array(), $e return $nodes; } - // TODO - test this ( turn off separate assets i think) $nodes = array_merge( $nodes, static::get_block_nodes_private( $theme_json ) ); return $nodes; } - // TODO - this is duplicated from get_style_nodes. public function get_block_nodes() { return static::get_block_nodes_private( $this->theme_json ); } From ee5a64a6fc482706ac70c6f7f1adc21243c7a5a5 Mon Sep 17 00:00:00 2001 From: Ben Dwyer Date: Thu, 21 Apr 2022 13:39:21 +0100 Subject: [PATCH 4/5] remove old comments --- .../get-global-styles-and-settings.php | 32 ------------------- 1 file changed, 32 deletions(-) diff --git a/lib/compat/wordpress-6.1/get-global-styles-and-settings.php b/lib/compat/wordpress-6.1/get-global-styles-and-settings.php index 631bc3ad60cfb2..679064c231f2e4 100644 --- a/lib/compat/wordpress-6.1/get-global-styles-and-settings.php +++ b/lib/compat/wordpress-6.1/get-global-styles-and-settings.php @@ -93,41 +93,9 @@ function wp_add_global_styles_for_blocks() { $block_nodes = $tree->get_block_nodes(); foreach ( $block_nodes as $metadata ) { - $block_css = $tree->get_styles_for_block( $metadata ); $block_name = str_replace( 'core/', '', $metadata['name'] ); wp_add_inline_style( "wp-block-" . $block_name, $block_css ); - - /* this might be needed for duotone styles? - - if ( null === $metadata['selector'] ) { - continue; - } - $node = _wp_array_get( $this->theme_json, $metadata['path'], array() ); - $selector = $metadata['selector']; - $settings = _wp_array_get( $this->theme_json, array( 'settings' ) ); - $declarations = static::compute_style_properties( $node, $settings ); - - // 1. Separate the ones who use the general selector - // and the ones who use the duotone selector. - $declarations_duotone = array(); - foreach ( $declarations as $index => $declaration ) { - if ( 'filter' === $declaration['name'] ) { - unset( $declarations[ $index ] ); - $declarations_duotone[] = $declaration; - } - } - - // 2. Generate the rules that use the general selector. - $block_rules .= static::to_ruleset( $selector, $declarations ); - - // 3. Generate the rules that use the duotone selector. - if ( isset( $metadata['duotone'] ) && ! empty( $declarations_duotone ) ) { - $selector_duotone = static::scope_selector( $metadata['selector'], $metadata['duotone'] ); - $block_rules .= static::to_ruleset( $selector_duotone, $declarations_duotone ); - }*/ - - } } From a4e5e0293befdcd0fd83a441ee1b877bb2718c4d Mon Sep 17 00:00:00 2001 From: Ben Dwyer Date: Thu, 21 Apr 2022 15:35:47 +0100 Subject: [PATCH 5/5] linting fixes --- .../wordpress-6.1/class-wp-theme-json-6-1.php | 22 ++++++++++++++----- .../get-global-styles-and-settings.php | 4 ++-- lib/compat/wordpress-6.1/script-loader.php | 5 +++++ 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/lib/compat/wordpress-6.1/class-wp-theme-json-6-1.php b/lib/compat/wordpress-6.1/class-wp-theme-json-6-1.php index 5def1984eb6e26..3a53117593d1eb 100644 --- a/lib/compat/wordpress-6.1/class-wp-theme-json-6-1.php +++ b/lib/compat/wordpress-6.1/class-wp-theme-json-6-1.php @@ -43,10 +43,10 @@ public function get_stylesheet( $types = array( 'variables', 'styles', 'presets' } } - $blocks_metadata = static::get_blocks_metadata(); - $separate_block_assets = wp_should_load_separate_core_block_assets(); + $blocks_metadata = static::get_blocks_metadata(); + $separate_block_assets = wp_should_load_separate_core_block_assets(); $style_nodes_without_blocks = static::get_style_nodes( $this->theme_json, $blocks_metadata, $separate_block_assets ); - $setting_nodes = static::get_setting_nodes( $this->theme_json, $blocks_metadata ); + $setting_nodes = static::get_setting_nodes( $this->theme_json, $blocks_metadata ); $stylesheet = ''; @@ -123,13 +123,25 @@ protected static function get_style_nodes( $theme_json, $selectors = array(), $e return $nodes; } + /** + * A public helper to get the block nodes from a theme.json file. + * + * @return array The block nodes in theme.json. + */ public function get_block_nodes() { return static::get_block_nodes_private( $this->theme_json ); } + /** + * An internal method to get the block nodes from a theme.json file. + * + * @param array $theme_json The theme.json converted to an array. + * + * @return array The block nodes in theme.json. + */ private static function get_block_nodes_private( $theme_json ) { $selectors = static::get_blocks_metadata(); - $nodes = array(); + $nodes = array(); if ( ! isset( $theme_json['styles'] ) ) { return $nodes; } @@ -182,7 +194,7 @@ public function get_styles_for_block( $block_metadata ) { $selector = $block_metadata['selector']; $settings = _wp_array_get( $this->theme_json, array( 'settings' ) ); $declarations = static::compute_style_properties( $node, $settings ); - $block_rules = static::to_ruleset( $selector, $declarations ); + $block_rules = static::to_ruleset( $selector, $declarations ); return $block_rules; } } diff --git a/lib/compat/wordpress-6.1/get-global-styles-and-settings.php b/lib/compat/wordpress-6.1/get-global-styles-and-settings.php index 679064c231f2e4..c15fb46c8f66d5 100644 --- a/lib/compat/wordpress-6.1/get-global-styles-and-settings.php +++ b/lib/compat/wordpress-6.1/get-global-styles-and-settings.php @@ -93,9 +93,9 @@ function wp_add_global_styles_for_blocks() { $block_nodes = $tree->get_block_nodes(); foreach ( $block_nodes as $metadata ) { - $block_css = $tree->get_styles_for_block( $metadata ); + $block_css = $tree->get_styles_for_block( $metadata ); $block_name = str_replace( 'core/', '', $metadata['name'] ); - wp_add_inline_style( "wp-block-" . $block_name, $block_css ); + wp_add_inline_style( 'wp-block-' . $block_name, $block_css ); } } diff --git a/lib/compat/wordpress-6.1/script-loader.php b/lib/compat/wordpress-6.1/script-loader.php index 36add7e913e44d..82548cf7f2d48f 100644 --- a/lib/compat/wordpress-6.1/script-loader.php +++ b/lib/compat/wordpress-6.1/script-loader.php @@ -1,4 +1,9 @@