From 7aa4c4a2a9c14766b51e03b18709cd0e3a688277 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Tue, 7 Mar 2023 15:13:41 -0600 Subject: [PATCH 01/55] Adds WP_Duotone class to set-up preset and theme-defined blocks using duotone presets --- lib/block-supports/duotone.php | 139 +++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php index ef950f80ce9448..2f55c953ae44e6 100644 --- a/lib/block-supports/duotone.php +++ b/lib/block-supports/duotone.php @@ -561,3 +561,142 @@ static function () use ( $filter_svg, $selector ) { // Remove WordPress core filter to avoid rendering duplicate support elements. remove_filter( 'render_block', 'wp_render_duotone_support', 10, 2 ); add_filter( 'render_block', 'gutenberg_render_duotone_support', 10, 2 ); + + +class WP_Duotone { + /** + * An array of Duotone presets from global, theme, and custom styles. + * + * Example: + * [ + * 'blue-orange' => + * [ + * 'slug' => 'blue-orange', + * 'colors' => [ '#0000ff', '#ffcc00' ], + * ] + * ], + * … + * ] + * + * @since 6.3.0 + * @var array + */ + static $duotone_presets = array(); + + /** + * An array of block names from global, theme, and custom styles that have duotone presets. We'll use this to quickly + * check if a block being rendered needs to have duotone applied, and which duotone preset to use. + * + * Example: + * [ + * 'core/featured-image' => 'blue-orange', + * … + * ] + * + */ + static $duotone_block_names = array(); + + /** + * An array of Duotone SVG and CSS ouput needed for the frontend duotone rendering based on what is + * being ouptput on the page. Organized by a slug of the preset/color group and the information needed + * to generate the SVG and CSS at render. + * + * Example: + * [ + * 'blue-orange' => [ + * 'slug' => 'blue-orange', + * 'colors' => [ '#0000ff', '#ffcc00' ], + * ], + * 'wp-duotone-000000-ffffff-2' => [ + * 'slug' => 'wp-duotone-000000-ffffff-2', + * 'colors' => [ '#000000', '#ffffff' ], + * ], + * ] + * + * @since 6.3.0 + * @var array + */ + static $duotone_output = array(); + + + + /** + * Get all possible duotone presets from global and theme styles and store as slug => [ colors array ] + * We only want to process this one time. On block render we'll access and output only the needed presets for that page. + * + */ + static function gutenberg_save_duotone_presets() { + // Get the per block settings from the theme.json. + $tree = WP_Theme_JSON_Resolver::get_merged_data(); + $settings = $tree->get_settings(); + $presets_by_origin = _wp_array_get( $settings, array( 'color', 'duotone' ), array() ); + $flat_presets = []; + // Flatten the array + foreach( $presets_by_origin as $presets ) { + foreach( $presets as $preset ) { + // $flat_presets[ _wp_to_kebab_case( $preset['slug'] ) ] = $preset; + self::$duotone_presets[ _wp_to_kebab_case( $preset['slug'] ) ] = [ + 'slug' => $preset[ 'slug' ], + 'colors' => $preset[ 'colors' ], + ]; + } + } + } + + static function gutenberg_save_duotone_block_names() { + // Get the per block settings from the theme.json. + $tree = WP_Theme_JSON_Resolver::get_merged_data(); + $block_nodes = $tree->get_styles_block_nodes(); + $theme_json = $tree->get_raw_data(); + + + foreach( $block_nodes as $block_node ) { + // This block definition doesn't include any duotone settings. Skip it. + if ( empty( $block_node['duotone'] ) ) { + continue; + } + + // Value looks like this: 'var(--wp--preset--duotone--blue-orange)' + $duotone_filter_path = array_merge( $block_node['path'], array( 'filter', 'duotone' ) ); + $duotone_filter = _wp_array_get( $theme_json, $duotone_filter_path, array() ); + + if( empty( $duotone_filter ) ) { + continue; + } + + // If it has a duotone preset, save the block name and the preset slug. + self::$duotone_block_names[ $block_node[ 'name' ] ] = self::gutenberg_get_duotone_slug_from_preset_css_variable( $duotone_filter ); + } + } + + static function gutenberg_get_duotone_slug_from_preset_css_variable( $css_variable ) { + if ( ! empty( $css_variable ) ) { + // Get the preset slug from the filter. + // TODO: Support var:preset|duotone|slug syntax. + preg_match('/var\(--wp--preset--duotone--(.*)\)/', $css_variable, $matches ); + if ( $matches[1] ) { + return $matches[1]; + } + } + } + + /** + * Get all possible duotone presets from global and theme styles. We only want to process this one time. On block render we'll access and output only the needed presets for that page. + * + */ + static function gutenberg_identify_used_duotone_blocks( $block_content, $block ) { + // If the block name exists in our pre-defined list of block selectors that use duotone in theme.json (or related), add it to our list of duotone to output + if( array_key_exists( $block['blockName'], self::$duotone_block_names ) ) { + $preset_slug = self::$duotone_block_names[ $block['blockName'] ]; + + self::$duotone_output[ $preset_slug ] = self::$duotone_presets[ $preset_slug ]; + } + + return $block_content; + } +} + + +add_action( 'wp_loaded', array( 'WP_Duotone', 'gutenberg_save_duotone_presets' ), 10 ); +add_action( 'wp_loaded', array( 'WP_Duotone', 'gutenberg_save_duotone_block_names' ), 10 ); +add_filter( 'block_render', array( 'WP_Duotone', 'gutenberg_identify_used_duotone_blocks' ), 10, 2 ); \ No newline at end of file From 23b631b4d6a7c6e03a7dce3415a137d66a2fc419 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Wed, 8 Mar 2023 10:02:01 -0600 Subject: [PATCH 02/55] Fix incorrect filter name --- lib/block-supports/duotone.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php index 2f55c953ae44e6..cc02598b9154ca 100644 --- a/lib/block-supports/duotone.php +++ b/lib/block-supports/duotone.php @@ -699,4 +699,4 @@ static function gutenberg_identify_used_duotone_blocks( $block_content, $block ) add_action( 'wp_loaded', array( 'WP_Duotone', 'gutenberg_save_duotone_presets' ), 10 ); add_action( 'wp_loaded', array( 'WP_Duotone', 'gutenberg_save_duotone_block_names' ), 10 ); -add_filter( 'block_render', array( 'WP_Duotone', 'gutenberg_identify_used_duotone_blocks' ), 10, 2 ); \ No newline at end of file +add_filter( 'render_block', array( 'WP_Duotone', 'gutenberg_identify_used_duotone_blocks' ), 10, 2 ); \ No newline at end of file From 2f63ab2da11615ea18ea2b710021b82727bc4001 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Thu, 9 Mar 2023 10:23:26 -0600 Subject: [PATCH 03/55] Check if duotone filter is applied on a block in theme.json This doesn't do anything at the moment. On block render, it checks if the block has duotone filters set via theme.json/global styles/custom styles and returns early if not. --- lib/block-supports/duotone.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php index cc02598b9154ca..4311234a3acc78 100644 --- a/lib/block-supports/duotone.php +++ b/lib/block-supports/duotone.php @@ -436,11 +436,13 @@ function gutenberg_render_duotone_support( $block_content, $block ) { $duotone_support = _wp_array_get( $block_type->supports, array( 'color', '__experimentalDuotone' ), false ); } + // The block should have a duotone attribute or have duotone defined in its theme.json to be processed. $has_duotone_attribute = isset( $block['attrs']['style']['color']['duotone'] ); - + $has_theme_json_duotone = array_key_exists( $block['blockName'], WP_Duotone::$duotone_block_names ); + if ( ! $duotone_support || - ! $has_duotone_attribute + ( ! $has_duotone_attribute && ! $has_theme_json_duotone ) ) { return $block_content; } From 70581a1194337ad8ec4700cb6436ffbb52b8e2c1 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Thu, 9 Mar 2023 11:14:45 -0600 Subject: [PATCH 04/55] Rename duotone class static variables and functions --- lib/block-supports/duotone.php | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php index 4311234a3acc78..1089bd33efa355 100644 --- a/lib/block-supports/duotone.php +++ b/lib/block-supports/duotone.php @@ -438,11 +438,11 @@ function gutenberg_render_duotone_support( $block_content, $block ) { // The block should have a duotone attribute or have duotone defined in its theme.json to be processed. $has_duotone_attribute = isset( $block['attrs']['style']['color']['duotone'] ); - $has_theme_json_duotone = array_key_exists( $block['blockName'], WP_Duotone::$duotone_block_names ); + $has_global_styles_duotone = array_key_exists( $block['blockName'], WP_Duotone::$global_styles_block_names ); if ( ! $duotone_support || - ( ! $has_duotone_attribute && ! $has_theme_json_duotone ) + ( ! $has_duotone_attribute && ! $has_global_styles_duotone ) ) { return $block_content; } @@ -583,7 +583,7 @@ class WP_Duotone { * @since 6.3.0 * @var array */ - static $duotone_presets = array(); + static $global_styles_presets = array(); /** * An array of block names from global, theme, and custom styles that have duotone presets. We'll use this to quickly @@ -596,7 +596,7 @@ class WP_Duotone { * ] * */ - static $duotone_block_names = array(); + static $global_styles_block_names = array(); /** * An array of Duotone SVG and CSS ouput needed for the frontend duotone rendering based on what is @@ -618,7 +618,7 @@ class WP_Duotone { * @since 6.3.0 * @var array */ - static $duotone_output = array(); + static $output_presets = array(); @@ -627,7 +627,7 @@ class WP_Duotone { * We only want to process this one time. On block render we'll access and output only the needed presets for that page. * */ - static function gutenberg_save_duotone_presets() { + static function save_presets() { // Get the per block settings from the theme.json. $tree = WP_Theme_JSON_Resolver::get_merged_data(); $settings = $tree->get_settings(); @@ -637,7 +637,7 @@ static function gutenberg_save_duotone_presets() { foreach( $presets_by_origin as $presets ) { foreach( $presets as $preset ) { // $flat_presets[ _wp_to_kebab_case( $preset['slug'] ) ] = $preset; - self::$duotone_presets[ _wp_to_kebab_case( $preset['slug'] ) ] = [ + self::$global_styles_presets[ _wp_to_kebab_case( $preset['slug'] ) ] = [ 'slug' => $preset[ 'slug' ], 'colors' => $preset[ 'colors' ], ]; @@ -645,7 +645,10 @@ static function gutenberg_save_duotone_presets() { } } - static function gutenberg_save_duotone_block_names() { + /** + * Scrape all block names from global styles and store in WP_Duotone::$global_styles_block_names + */ + static function save_global_style_block_names() { // Get the per block settings from the theme.json. $tree = WP_Theme_JSON_Resolver::get_merged_data(); $block_nodes = $tree->get_styles_block_nodes(); @@ -667,7 +670,7 @@ static function gutenberg_save_duotone_block_names() { } // If it has a duotone preset, save the block name and the preset slug. - self::$duotone_block_names[ $block_node[ 'name' ] ] = self::gutenberg_get_duotone_slug_from_preset_css_variable( $duotone_filter ); + self::$global_styles_block_names[ $block_node[ 'name' ] ] = self::gutenberg_get_duotone_slug_from_preset_css_variable( $duotone_filter ); } } @@ -688,10 +691,10 @@ static function gutenberg_get_duotone_slug_from_preset_css_variable( $css_variab */ static function gutenberg_identify_used_duotone_blocks( $block_content, $block ) { // If the block name exists in our pre-defined list of block selectors that use duotone in theme.json (or related), add it to our list of duotone to output - if( array_key_exists( $block['blockName'], self::$duotone_block_names ) ) { - $preset_slug = self::$duotone_block_names[ $block['blockName'] ]; + if( array_key_exists( $block['blockName'], self::$global_styles_block_names ) ) { + $preset_slug = self::$global_styles_block_names[ $block['blockName'] ]; - self::$duotone_output[ $preset_slug ] = self::$duotone_presets[ $preset_slug ]; + self::$output_presets[ $preset_slug ] = self::$global_styles_presets[ $preset_slug ]; } return $block_content; @@ -699,6 +702,5 @@ static function gutenberg_identify_used_duotone_blocks( $block_content, $block ) } -add_action( 'wp_loaded', array( 'WP_Duotone', 'gutenberg_save_duotone_presets' ), 10 ); -add_action( 'wp_loaded', array( 'WP_Duotone', 'gutenberg_save_duotone_block_names' ), 10 ); -add_filter( 'render_block', array( 'WP_Duotone', 'gutenberg_identify_used_duotone_blocks' ), 10, 2 ); \ No newline at end of file +add_action( 'wp_loaded', array( 'WP_Duotone', 'save_presets' ), 10 ); +add_action( 'wp_loaded', array( 'WP_Duotone', 'save_global_style_block_names' ), 10 ); \ No newline at end of file From a024ddb03477e9f8c6603538fbbb15b0039041bf Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Thu, 9 Mar 2023 14:19:16 -0600 Subject: [PATCH 05/55] Set WP_Duotone:: array and only output those via wp_footer --- lib/block-supports/duotone.php | 98 ++++++++++++++++++--------- lib/class-wp-theme-json-gutenberg.php | 35 ++++++++++ 2 files changed, 100 insertions(+), 33 deletions(-) diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php index 1089bd33efa355..f2622f099e6adc 100644 --- a/lib/block-supports/duotone.php +++ b/lib/block-supports/duotone.php @@ -458,12 +458,24 @@ function gutenberg_render_duotone_support( $block_content, $block ) { $is_custom = is_array( $duotone_attr ); // Generate the pieces needed for rendering a duotone to the page. - if ( $is_preset ) { + if ( $has_global_styles_duotone ) { + $slug = WP_Duotone::$global_styles_block_names[ $block['blockName'] ]; + + // Utilize existing preset CSS custom property. + $filter_property = "var(--wp--preset--duotone--$slug)"; + + WP_Duotone::$output_presets[ $slug ] = WP_Duotone::$global_styles_presets[ $slug ]; + } elseif ( $is_preset ) { + + // TODO: Extract to set_output_preset( $filter_data ); // Extract the slug from the preset variable string. $slug = str_replace( 'var:preset|duotone|', '', $duotone_attr ); // Utilize existing preset CSS custom property. $filter_property = "var(--wp--preset--duotone--$slug)"; + + WP_Duotone::$output_presets[ $slug ] = WP_Duotone::$global_styles_presets[ $slug ]; + } elseif ( $is_css ) { // Build a unique slug for the filter based on the CSS value. $slug = wp_unique_id( sanitize_key( $duotone_attr . '-' ) ); @@ -474,18 +486,14 @@ function gutenberg_render_duotone_support( $block_content, $block ) { // Build a unique slug for the filter based on the array of colors. $slug = wp_unique_id( sanitize_key( implode( '-', $duotone_attr ) . '-' ) ); - // This has the same shape as a preset, so it can be used in place of a - // preset when getting the filter property and SVG filter. $filter_data = array( 'slug' => $slug, 'colors' => $duotone_attr, ); - // Build a customized CSS filter property for unique slug. $filter_property = gutenberg_get_duotone_filter_property( $filter_data ); - // SVG will be output on the page later. - $filter_svg = gutenberg_get_duotone_filter_svg( $filter_data ); + WP_Duotone::$output_presets[ $slug ] = $filter_data; } // - Applied as a class attribute to the block wrapper. @@ -495,6 +503,12 @@ function gutenberg_render_duotone_support( $block_content, $block ) { // Build the CSS selectors to which the filter will be applied. $selector = WP_Theme_JSON_Gutenberg::scope_selector( '.' . $filter_id, $duotone_support ); + // We only want to add the selector if we have it in the output_presets already, essentially skipping 'unset'. + // TODO: Extract to set_output_preset( $filter_data ); + if( array_key_exists( $slug, WP_Duotone::$output_presets ) ) { + WP_Duotone::$output_presets[ $slug ][ 'selector' ] = $selector; + } + // Calling gutenberg_style_engine_get_stylesheet_from_css_rules ensures that // the styles are rendered in an inline for block supports because we're // using the `context` option to instruct it so. @@ -515,33 +529,7 @@ function gutenberg_render_duotone_support( $block_content, $block ) { 'context' => 'block-supports', ) ); - - // If we needed to generate an SVG, output it on the page. - if ( isset( $filter_svg ) ) { - add_action( - 'wp_footer', - static function () use ( $filter_svg, $selector ) { - echo $filter_svg; - - /* - * Safari renders elements incorrectly on first paint when the - * SVG filter comes after the content that it is filtering, so - * we force a repaint with a WebKit hack which solves the issue. - */ - global $is_safari; - if ( $is_safari ) { - /* - * Simply accessing el.offsetHeight flushes layout and style - * changes in WebKit without having to wait for setTimeout. - */ - printf( - '', - wp_json_encode( $selector ) - ); - } - } - ); - } + // Like the layout hook, this assumes the hook only applies to blocks with a single wrapper. return preg_replace( @@ -552,6 +540,50 @@ static function () use ( $filter_svg, $selector ) { ); } + +add_action( 'wp_footer', + static function () { + + foreach( WP_Duotone::$output_presets as $filter_data ) { + + $filter_property = gutenberg_get_duotone_filter_property( $filter_data ); + // SVG will be output on the page later. + $filter_svg = gutenberg_get_duotone_filter_svg( $filter_data ); + + echo $filter_svg; + + + // This is for classic themes - in block themes, the CSS is added in the head via the value_func. + $duotone_preset_css_var = WP_Theme_JSON_Gutenberg::get_preset_css_var( array( 'color', 'duotone' ), $filter_data[ 'slug'] ); + wp_add_inline_style( 'core-block-supports', 'body{' . $duotone_preset_css_var . ' :' . $filter_property . ';}' ); + + + global $is_safari; + if( $is_safari ) { + duotone_safari_rerender_hack( $selector ); + } + } + } +); + + +/** + * Safari renders elements incorrectly on first paint when the SVG filter comes after the content that it is filtering, + * so we force a repaint with a WebKit hack which solves the issue. + * + * @param string $selector The selector to apply the hack for. + */ +function duotone_safari_rerender_hack( $selector ) { + /* + * Simply accessing el.offsetHeight flushes layout and style + * changes in WebKit without having to wait for setTimeout. + */ + printf( + '', + wp_json_encode( $selector ) + ); +} + // Register the block support. WP_Block_Supports::get_instance()->register( 'duotone', diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index b92e1106c1aa1c..9972e0c3b48f57 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -3480,4 +3480,39 @@ public function set_spacing_sizes() { _wp_array_set( $this->theme_json, array( 'settings', 'spacing', 'spacingSizes', 'default' ), $spacing_sizes ); } + + /** + * Returns the CSS variable for a preset. + * + * @since 6.3.0 + * + * @param array $path Path to the preset. + * @param string $slug Slug of the preset. + * @return string CSS variable. + */ + public static function get_preset_css_var( $path, $slug ) { + $duotone_preset_metadata = static::get_preset_metadata_from_path( $path ); + return static::replace_slug_in_string( $duotone_preset_metadata['css_vars'], $slug ); + } + + /** + * Returns the metadata for a preset. + * + * @since 6.3.0 + * + * @param array $path Path to the preset. + * @return array Preset metadata. + */ + static function get_preset_metadata_from_path( $path ) { + $preset_metadata = array_filter( + static::PRESETS_METADATA, + function( $preset ) use ( &$path ) { + if ( $preset['path'] === $path ) { + return $preset; + } + } + ); + + return reset( $preset_metadata ); + } } From 025654856ed7d8acc6d7b7d58d71e38435151fc5 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Thu, 9 Mar 2023 14:50:56 -0600 Subject: [PATCH 06/55] Only output used duotone presets Co-authored-by: scruffian --- lib/block-supports/duotone.php | 50 +++++++++++++++++-- lib/class-wp-theme-json-gutenberg.php | 6 ++- .../get-global-styles-and-settings.php | 42 ++++++++++++++++ lib/compat/wordpress-6.2/script-loader.php | 34 +++++++++++++ 4 files changed, 127 insertions(+), 5 deletions(-) diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php index f2622f099e6adc..ced6e4e9af195e 100644 --- a/lib/block-supports/duotone.php +++ b/lib/block-supports/duotone.php @@ -659,7 +659,7 @@ class WP_Duotone { * We only want to process this one time. On block render we'll access and output only the needed presets for that page. * */ - static function save_presets() { + static function save_global_styles_presets() { // Get the per block settings from the theme.json. $tree = WP_Theme_JSON_Resolver::get_merged_data(); $settings = $tree->get_settings(); @@ -731,8 +731,52 @@ static function gutenberg_identify_used_duotone_blocks( $block_content, $block ) return $block_content; } + + /** + * Registers the duotone preset. + * + * @param array $settings The block editor settings. + * + * @return array The block editor settings. + */ + public static function duotone_declarations( $declarations, $selector ) { + foreach ( $declarations as $index => $declaration ) { + if ( 'filter' === $declaration['name'] ) { + static::$global_styles_presets[] = $declarations[ $index ]['value']; + } + } + } + + /** + * TODO: Outputs the duotone filter preset CSS like + * Ideally this would be output in the header before core-block-supports-inline-css so that the CSS variable is defined before it is used + * + * Filters the duotone SVG filters to only output the ones being used on the page. + * + * @param array $duotone_preset + * @return string + */ + public static function get_filter_svg( $duotone_preset ) { + + $filters = ''; + + + // Only output the preset if it's used by a block. + if ( array_key_exists( $duotone_preset[ 'slug' ], WP_Duotone::$output_presets ) ) { + // Get the CSS variable for the preset. + $duotone_preset_css_var = WP_Theme_JSON_Gutenberg::get_preset_css_var( array( 'color', 'duotone' ), $duotone_preset['slug'] ); + // Output the CSS for the preset. + // I think we should do this differently, but I'm not sure how. + $filters .= ''; + $filters .= wp_get_duotone_filter_svg( $duotone_preset ); + } + + return $filters; + } } -add_action( 'wp_loaded', array( 'WP_Duotone', 'save_presets' ), 10 ); -add_action( 'wp_loaded', array( 'WP_Duotone', 'save_global_style_block_names' ), 10 ); \ No newline at end of file +add_action( 'wp_loaded', array( 'WP_Duotone', 'save_global_styles_presets' ), 10 ); +add_action( 'wp_loaded', array( 'WP_Duotone', 'save_global_style_block_names' ), 10 ); +add_action( 'theme_json_register_declarations', array( 'WP_Duotone', 'duotone_declarations' ), 10, 2 ); +add_filter( 'theme_json_get_filter_svg', array( 'WP_Duotone', 'get_filter_svg' ), 10, 2 ); \ No newline at end of file diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index 9972e0c3b48f57..fdf7e20363b28a 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -144,7 +144,7 @@ class WP_Theme_JSON_Gutenberg { 'path' => array( 'color', 'duotone' ), 'prevent_override' => array( 'color', 'defaultDuotone' ), 'use_default_names' => false, - 'value_func' => 'gutenberg_get_duotone_filter_property', + 'value_func' => null, // Don't output CSS Custom Properties for duotone. 'css_vars' => '--wp--preset--duotone--$slug', 'classes' => array(), 'properties' => array( 'filter' ), @@ -2435,6 +2435,8 @@ function( $pseudo_selector ) use ( $selector ) { $block_rules = ''; + do_action( 'theme_json_register_declarations', $declarations, $selector ); + /* * 1. Separate the declarations that use the general selector * from the ones using the duotone selector. @@ -2728,7 +2730,7 @@ public function get_svg_filters( $origins ) { continue; } foreach ( $duotone_presets[ $origin ] as $duotone_preset ) { - $filters .= wp_get_duotone_filter_svg( $duotone_preset ); + $filters .= apply_filters( 'theme_json_get_filter_svg', $duotone_preset ); } } } diff --git a/lib/compat/wordpress-6.2/get-global-styles-and-settings.php b/lib/compat/wordpress-6.2/get-global-styles-and-settings.php index e02a0466a0b98f..7019870e87ec65 100644 --- a/lib/compat/wordpress-6.2/get-global-styles-and-settings.php +++ b/lib/compat/wordpress-6.2/get-global-styles-and-settings.php @@ -255,3 +255,45 @@ function _gutenberg_add_non_persistent_theme_json_cache_group() { wp_cache_add_non_persistent_groups( 'theme_json' ); } add_action( 'plugins_loaded', '_gutenberg_add_non_persistent_theme_json_cache_group' ); + + +/** + * Returns a string containing the SVGs to be referenced as filters (duotone). + * + * @since 5.9.1 + * + * @return string + */ +function gutenberg_get_global_styles_svg_filters() { + /* + * Ignore cache when `WP_DEBUG` is enabled, so it doesn't interfere with the theme + * developer's workflow. + * + * @todo Replace `WP_DEBUG` once an "in development mode" check is available in Core. + */ + $can_use_cached = ! WP_DEBUG; + $cache_group = 'theme_json'; + $cache_key = 'wp_get_global_styles_svg_filters'; + if ( $can_use_cached ) { + $cached = wp_cache_get( $cache_key, $cache_group ); + if ( $cached ) { + return $cached; + } + } + + $supports_theme_json = wp_theme_has_theme_json(); + + $origins = array( 'default', 'theme', 'custom' ); + if ( ! $supports_theme_json ) { + $origins = array( 'default' ); + } + + $tree = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data(); + $svgs = $tree->get_svg_filters( $origins ); + + if ( $can_use_cached ) { + wp_cache_set( $cache_key, $svgs, $cache_group ); + } + + return $svgs; +} \ No newline at end of file diff --git a/lib/compat/wordpress-6.2/script-loader.php b/lib/compat/wordpress-6.2/script-loader.php index 149a6a18e14507..23915619ab807f 100644 --- a/lib/compat/wordpress-6.2/script-loader.php +++ b/lib/compat/wordpress-6.2/script-loader.php @@ -191,3 +191,37 @@ function gutenberg_enqueue_global_styles_custom_css() { } } add_action( 'wp_enqueue_scripts', 'gutenberg_enqueue_global_styles_custom_css' ); + + +/** + * Renders the SVG filters supplied by theme.json. + * + * Note that this doesn't render the per-block user-defined + * filters which are handled by wp_render_duotone_support, + * but it should be rendered before the filtered content + * in the body to satisfy Safari's rendering quirks. + * + * @since 5.9.1 + */ +function gutenberg_global_styles_render_svg_filters() { + /* + * When calling via the in_admin_header action, we only want to render the + * SVGs on block editor pages. + */ + if ( + is_admin() && + ! get_current_screen()->is_block_editor() + ) { + return; + } + + $filters = gutenberg_get_global_styles_svg_filters(); + if ( ! empty( $filters ) ) { + echo $filters; + } +} + +remove_action( 'wp_body_open', 'wp_global_styles_render_svg_filters' ); +remove_action( 'in_admin_header', 'wp_global_styles_render_svg_filters' ); +add_action( 'wp_body_open', 'gutenberg_global_styles_render_svg_filters' ); +add_action( 'in_admin_header', 'gutenberg_global_styles_render_svg_filters' ); \ No newline at end of file From 2c283cc2f1da28c4f46c6d59aae81e3a29f795db Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Fri, 10 Mar 2023 08:53:02 -0600 Subject: [PATCH 07/55] Cleanup, removal, and only output used SVG filters and CSS --- lib/block-supports/duotone.php | 74 ++++++++++--------- lib/class-wp-theme-json-gutenberg.php | 2 +- .../get-global-styles-and-settings.php | 42 ----------- lib/compat/wordpress-6.2/script-loader.php | 34 +-------- 4 files changed, 43 insertions(+), 109 deletions(-) diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php index ced6e4e9af195e..387bf32cd437a6 100644 --- a/lib/block-supports/duotone.php +++ b/lib/block-supports/duotone.php @@ -463,7 +463,6 @@ function gutenberg_render_duotone_support( $block_content, $block ) { // Utilize existing preset CSS custom property. $filter_property = "var(--wp--preset--duotone--$slug)"; - WP_Duotone::$output_presets[ $slug ] = WP_Duotone::$global_styles_presets[ $slug ]; } elseif ( $is_preset ) { @@ -552,11 +551,12 @@ static function () { echo $filter_svg; - + // This is for classic themes - in block themes, the CSS is added in the head via the value_func. - $duotone_preset_css_var = WP_Theme_JSON_Gutenberg::get_preset_css_var( array( 'color', 'duotone' ), $filter_data[ 'slug'] ); - wp_add_inline_style( 'core-block-supports', 'body{' . $duotone_preset_css_var . ' :' . $filter_property . ';}' ); - + if( ! wp_is_block_theme() ) { + $duotone_preset_css_var = WP_Theme_JSON_Gutenberg::get_preset_css_var( array( 'color', 'duotone' ), $filter_data[ 'slug'] ); + wp_add_inline_style( 'core-block-supports', 'body{' . $duotone_preset_css_var . ' :' . $filter_property . ';}' ); + } global $is_safari; if( $is_safari ) { @@ -566,6 +566,32 @@ static function () { } ); +/** + * Appends the used duotone fitler CSS Vars to the inline global styles CSS + */ +add_action( 'wp_enqueue_scripts', static function() { + + if( empty( WP_Duotone::$output_presets ) ) { + return; + } + + $duotone_css_vars = ''; + + foreach ( WP_Duotone::$output_presets as $filter_data ) { + if( ! array_key_exists( $filter_data['slug'], WP_Duotone::$global_styles_presets ) ) { + continue; + } + + $filter_property = gutenberg_get_duotone_filter_property( $filter_data ); + + $duotone_preset_css_var = WP_Theme_JSON_Gutenberg::get_preset_css_var( array( 'color', 'duotone' ), $filter_data[ 'slug'] ); + $duotone_css_vars .= $duotone_preset_css_var . ': ' . $filter_property . ';'; + } + + if( ! empty( $duotone_css_vars ) ) { + wp_add_inline_style( 'global-styles', 'body{' . $duotone_css_vars . '}' ); + } +}, 11 ); /** * Safari renders elements incorrectly on first paint when the SVG filter comes after the content that it is filtering, @@ -700,7 +726,6 @@ static function save_global_style_block_names() { if( empty( $duotone_filter ) ) { continue; } - // If it has a duotone preset, save the block name and the preset slug. self::$global_styles_block_names[ $block_node[ 'name' ] ] = self::gutenberg_get_duotone_slug_from_preset_css_variable( $duotone_filter ); } @@ -746,37 +771,18 @@ public static function duotone_declarations( $declarations, $selector ) { } } } - - /** - * TODO: Outputs the duotone filter preset CSS like - * Ideally this would be output in the header before core-block-supports-inline-css so that the CSS variable is defined before it is used - * - * Filters the duotone SVG filters to only output the ones being used on the page. - * - * @param array $duotone_preset - * @return string - */ - public static function get_filter_svg( $duotone_preset ) { - - $filters = ''; - - - // Only output the preset if it's used by a block. - if ( array_key_exists( $duotone_preset[ 'slug' ], WP_Duotone::$output_presets ) ) { - // Get the CSS variable for the preset. - $duotone_preset_css_var = WP_Theme_JSON_Gutenberg::get_preset_css_var( array( 'color', 'duotone' ), $duotone_preset['slug'] ); - // Output the CSS for the preset. - // I think we should do this differently, but I'm not sure how. - $filters .= ''; - $filters .= wp_get_duotone_filter_svg( $duotone_preset ); - } - - return $filters; +} +// +function gutenberg_get_duotone_preset_value( $preset ) { + if( array_key_exists( $preset['slug'], WP_Duotone::$output_presets ) ) { + // This is returning the --wp--preset--duotone--dark-grayscale: CSS VAR NAME; but not removing the full --wp--preset--duotone--dark-grayscale preset name + return gutenberg_get_duotone_filter_property( $preset ); } + + return ''; } add_action( 'wp_loaded', array( 'WP_Duotone', 'save_global_styles_presets' ), 10 ); add_action( 'wp_loaded', array( 'WP_Duotone', 'save_global_style_block_names' ), 10 ); -add_action( 'theme_json_register_declarations', array( 'WP_Duotone', 'duotone_declarations' ), 10, 2 ); -add_filter( 'theme_json_get_filter_svg', array( 'WP_Duotone', 'get_filter_svg' ), 10, 2 ); \ No newline at end of file +add_action( 'theme_json_register_declarations', array( 'WP_Duotone', 'duotone_declarations' ), 10, 2 ); \ No newline at end of file diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index fdf7e20363b28a..52798789bb446b 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -2730,7 +2730,7 @@ public function get_svg_filters( $origins ) { continue; } foreach ( $duotone_presets[ $origin ] as $duotone_preset ) { - $filters .= apply_filters( 'theme_json_get_filter_svg', $duotone_preset ); + $filters .= wp_get_duotone_filter_svg( $duotone_preset ); } } } diff --git a/lib/compat/wordpress-6.2/get-global-styles-and-settings.php b/lib/compat/wordpress-6.2/get-global-styles-and-settings.php index 7019870e87ec65..e02a0466a0b98f 100644 --- a/lib/compat/wordpress-6.2/get-global-styles-and-settings.php +++ b/lib/compat/wordpress-6.2/get-global-styles-and-settings.php @@ -255,45 +255,3 @@ function _gutenberg_add_non_persistent_theme_json_cache_group() { wp_cache_add_non_persistent_groups( 'theme_json' ); } add_action( 'plugins_loaded', '_gutenberg_add_non_persistent_theme_json_cache_group' ); - - -/** - * Returns a string containing the SVGs to be referenced as filters (duotone). - * - * @since 5.9.1 - * - * @return string - */ -function gutenberg_get_global_styles_svg_filters() { - /* - * Ignore cache when `WP_DEBUG` is enabled, so it doesn't interfere with the theme - * developer's workflow. - * - * @todo Replace `WP_DEBUG` once an "in development mode" check is available in Core. - */ - $can_use_cached = ! WP_DEBUG; - $cache_group = 'theme_json'; - $cache_key = 'wp_get_global_styles_svg_filters'; - if ( $can_use_cached ) { - $cached = wp_cache_get( $cache_key, $cache_group ); - if ( $cached ) { - return $cached; - } - } - - $supports_theme_json = wp_theme_has_theme_json(); - - $origins = array( 'default', 'theme', 'custom' ); - if ( ! $supports_theme_json ) { - $origins = array( 'default' ); - } - - $tree = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data(); - $svgs = $tree->get_svg_filters( $origins ); - - if ( $can_use_cached ) { - wp_cache_set( $cache_key, $svgs, $cache_group ); - } - - return $svgs; -} \ No newline at end of file diff --git a/lib/compat/wordpress-6.2/script-loader.php b/lib/compat/wordpress-6.2/script-loader.php index 23915619ab807f..388aa15b030d01 100644 --- a/lib/compat/wordpress-6.2/script-loader.php +++ b/lib/compat/wordpress-6.2/script-loader.php @@ -185,7 +185,7 @@ function gutenberg_enqueue_global_styles_custom_css() { $custom_css = wp_get_custom_css(); $custom_css .= gutenberg_get_global_styles_custom_css(); - + if ( ! empty( $custom_css ) ) { wp_add_inline_style( 'global-styles', $custom_css ); } @@ -193,35 +193,5 @@ function gutenberg_enqueue_global_styles_custom_css() { add_action( 'wp_enqueue_scripts', 'gutenberg_enqueue_global_styles_custom_css' ); -/** - * Renders the SVG filters supplied by theme.json. - * - * Note that this doesn't render the per-block user-defined - * filters which are handled by wp_render_duotone_support, - * but it should be rendered before the filtered content - * in the body to satisfy Safari's rendering quirks. - * - * @since 5.9.1 - */ -function gutenberg_global_styles_render_svg_filters() { - /* - * When calling via the in_admin_header action, we only want to render the - * SVGs on block editor pages. - */ - if ( - is_admin() && - ! get_current_screen()->is_block_editor() - ) { - return; - } - - $filters = gutenberg_get_global_styles_svg_filters(); - if ( ! empty( $filters ) ) { - echo $filters; - } -} - remove_action( 'wp_body_open', 'wp_global_styles_render_svg_filters' ); -remove_action( 'in_admin_header', 'wp_global_styles_render_svg_filters' ); -add_action( 'wp_body_open', 'gutenberg_global_styles_render_svg_filters' ); -add_action( 'in_admin_header', 'gutenberg_global_styles_render_svg_filters' ); \ No newline at end of file +remove_action( 'in_admin_header', 'wp_global_styles_render_svg_filters' ); \ No newline at end of file From 460a4134c877529e86d613832a68700c614cdc1a Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Fri, 10 Mar 2023 09:10:29 -0600 Subject: [PATCH 08/55] Support var:preset|duotone|default-filter syntax for block name styles --- lib/block-supports/duotone.php | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php index 387bf32cd437a6..21ec9cef85a264 100644 --- a/lib/block-supports/duotone.php +++ b/lib/block-supports/duotone.php @@ -719,29 +719,29 @@ static function save_global_style_block_names() { continue; } - // Value looks like this: 'var(--wp--preset--duotone--blue-orange)' + // Value looks like this: 'var(--wp--preset--duotone--blue-orange)' or 'var:preset|duotone|default-filter' $duotone_filter_path = array_merge( $block_node['path'], array( 'filter', 'duotone' ) ); $duotone_filter = _wp_array_get( $theme_json, $duotone_filter_path, array() ); if( empty( $duotone_filter ) ) { continue; } - // If it has a duotone preset, save the block name and the preset slug. - self::$global_styles_block_names[ $block_node[ 'name' ] ] = self::gutenberg_get_duotone_slug_from_preset_css_variable( $duotone_filter ); - } - } + // If it has a duotone filter preset, save the block name and the preset slug. + $slug = self::gutenberg_get_duotone_slug_from_inline_styles( $duotone_filter ); - static function gutenberg_get_duotone_slug_from_preset_css_variable( $css_variable ) { - if ( ! empty( $css_variable ) ) { - // Get the preset slug from the filter. - // TODO: Support var:preset|duotone|slug syntax. - preg_match('/var\(--wp--preset--duotone--(.*)\)/', $css_variable, $matches ); - if ( $matches[1] ) { - return $matches[1]; + if( $slug && $slug !== $duotone_filter) { + self::$global_styles_block_names[ $block_node[ 'name' ] ] = $slug; } } } + /** + * Take a + */ + static function gutenberg_get_duotone_slug_from_inline_styles( $css_variable ) { + return str_replace( [ 'var:preset|duotone|', 'var(--wp--preset--duotone--' ], '', $css_variable ); + } + /** * Get all possible duotone presets from global and theme styles. We only want to process this one time. On block render we'll access and output only the needed presets for that page. * From 2d0e235484d8fbf1ab36a3ba6c29c5aba64d0e87 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Fri, 10 Mar 2023 10:11:42 -0600 Subject: [PATCH 09/55] Refactor to handle both duotone pipe and css var style syntax for duotone preset --- lib/block-supports/duotone.php | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php index 21ec9cef85a264..7c0d2cf3dfa689 100644 --- a/lib/block-supports/duotone.php +++ b/lib/block-supports/duotone.php @@ -453,8 +453,8 @@ function gutenberg_render_duotone_support( $block_content, $block ) { // 3. A CSS string - e.g. 'unset' to remove globally applied duotone. $duotone_attr = $block['attrs']['style']['color']['duotone']; - $is_preset = is_string( $duotone_attr ) && strpos( $duotone_attr, 'var:preset|duotone|' ) === 0; - $is_css = is_string( $duotone_attr ) && strpos( $duotone_attr, 'var:preset|duotone|' ) === false; + $is_preset = is_string( $duotone_attr ) && WP_Duotone::is_preset( $duotone_attr ); + $is_css = is_string( $duotone_attr ) && ! $is_preset; $is_custom = is_array( $duotone_attr ); // Generate the pieces needed for rendering a duotone to the page. @@ -468,7 +468,7 @@ function gutenberg_render_duotone_support( $block_content, $block ) { // TODO: Extract to set_output_preset( $filter_data ); // Extract the slug from the preset variable string. - $slug = str_replace( 'var:preset|duotone|', '', $duotone_attr ); + $slug = WP_Duotone::gutenberg_get_slug_from_attr( $duotone_attr ); // Utilize existing preset CSS custom property. $filter_property = "var(--wp--preset--duotone--$slug)"; @@ -720,26 +720,38 @@ static function save_global_style_block_names() { } // Value looks like this: 'var(--wp--preset--duotone--blue-orange)' or 'var:preset|duotone|default-filter' - $duotone_filter_path = array_merge( $block_node['path'], array( 'filter', 'duotone' ) ); - $duotone_filter = _wp_array_get( $theme_json, $duotone_filter_path, array() ); + $duotone_attr_path = array_merge( $block_node['path'], array( 'filter', 'duotone' ) ); + $duotone_attr = _wp_array_get( $theme_json, $duotone_attr_path, array() ); - if( empty( $duotone_filter ) ) { + if( empty( $duotone_attr ) ) { continue; } // If it has a duotone filter preset, save the block name and the preset slug. - $slug = self::gutenberg_get_duotone_slug_from_inline_styles( $duotone_filter ); + $slug = self::gutenberg_get_slug_from_attr( $duotone_attr ); - if( $slug && $slug !== $duotone_filter) { + if( $slug && $slug !== $duotone_attr) { self::$global_styles_block_names[ $block_node[ 'name' ] ] = $slug; } } } /** - * Take a + * Take the inline CSS duotone variable from a block and return the slug. Handles styles slugs like: + * var:preset|duotone|default-filter + * var(--wp--preset--duotone--blue-orange) + * + * @param string $duotone_attr The duotone attribute from a block. + * @return string The slug of the duotone preset. + */ + static function gutenberg_get_slug_from_attr( $duotone_attr ) { + return str_replace( [ 'var:preset|duotone|', 'var(--wp--preset--duotone--', ')' ], '', $duotone_attr ); + } + + /** + * Check if we have a duotone preset string */ - static function gutenberg_get_duotone_slug_from_inline_styles( $css_variable ) { - return str_replace( [ 'var:preset|duotone|', 'var(--wp--preset--duotone--' ], '', $css_variable ); + static function is_preset( $duotone_attr ) { + return strpos( $duotone_attr, 'var:preset|duotone|' ) === 0 || strpos( $duotone_attr, 'var(--wp--preset--duotone--' ) === 0; } /** From 5f47de7be1d71c7a0780e783b6562d87dc0756de Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Fri, 10 Mar 2023 10:20:37 -0600 Subject: [PATCH 10/55] Renamed output_presets to output, as it also includes custom dutone output. Name could still be better. --- lib/block-supports/duotone.php | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php index 7c0d2cf3dfa689..581e283486c1d8 100644 --- a/lib/block-supports/duotone.php +++ b/lib/block-supports/duotone.php @@ -463,7 +463,7 @@ function gutenberg_render_duotone_support( $block_content, $block ) { // Utilize existing preset CSS custom property. $filter_property = "var(--wp--preset--duotone--$slug)"; - WP_Duotone::$output_presets[ $slug ] = WP_Duotone::$global_styles_presets[ $slug ]; + WP_Duotone::$output[ $slug ] = WP_Duotone::$global_styles_presets[ $slug ]; } elseif ( $is_preset ) { // TODO: Extract to set_output_preset( $filter_data ); @@ -473,7 +473,7 @@ function gutenberg_render_duotone_support( $block_content, $block ) { // Utilize existing preset CSS custom property. $filter_property = "var(--wp--preset--duotone--$slug)"; - WP_Duotone::$output_presets[ $slug ] = WP_Duotone::$global_styles_presets[ $slug ]; + WP_Duotone::$output[ $slug ] = WP_Duotone::$global_styles_presets[ $slug ]; } elseif ( $is_css ) { // Build a unique slug for the filter based on the CSS value. @@ -492,7 +492,7 @@ function gutenberg_render_duotone_support( $block_content, $block ) { // Build a customized CSS filter property for unique slug. $filter_property = gutenberg_get_duotone_filter_property( $filter_data ); - WP_Duotone::$output_presets[ $slug ] = $filter_data; + WP_Duotone::$output[ $slug ] = $filter_data; } // - Applied as a class attribute to the block wrapper. @@ -502,10 +502,10 @@ function gutenberg_render_duotone_support( $block_content, $block ) { // Build the CSS selectors to which the filter will be applied. $selector = WP_Theme_JSON_Gutenberg::scope_selector( '.' . $filter_id, $duotone_support ); - // We only want to add the selector if we have it in the output_presets already, essentially skipping 'unset'. + // We only want to add the selector if we have it in the output already, essentially skipping 'unset'. // TODO: Extract to set_output_preset( $filter_data ); - if( array_key_exists( $slug, WP_Duotone::$output_presets ) ) { - WP_Duotone::$output_presets[ $slug ][ 'selector' ] = $selector; + if( array_key_exists( $slug, WP_Duotone::$output ) ) { + WP_Duotone::$output[ $slug ][ 'selector' ] = $selector; } // Calling gutenberg_style_engine_get_stylesheet_from_css_rules ensures that @@ -543,7 +543,7 @@ function gutenberg_render_duotone_support( $block_content, $block ) { add_action( 'wp_footer', static function () { - foreach( WP_Duotone::$output_presets as $filter_data ) { + foreach( WP_Duotone::$output as $filter_data ) { $filter_property = gutenberg_get_duotone_filter_property( $filter_data ); // SVG will be output on the page later. @@ -571,13 +571,13 @@ static function () { */ add_action( 'wp_enqueue_scripts', static function() { - if( empty( WP_Duotone::$output_presets ) ) { + if( empty( WP_Duotone::$output ) ) { return; } $duotone_css_vars = ''; - foreach ( WP_Duotone::$output_presets as $filter_data ) { + foreach ( WP_Duotone::$output as $filter_data ) { if( ! array_key_exists( $filter_data['slug'], WP_Duotone::$global_styles_presets ) ) { continue; } @@ -676,7 +676,7 @@ class WP_Duotone { * @since 6.3.0 * @var array */ - static $output_presets = array(); + static $output = array(); @@ -763,7 +763,7 @@ static function gutenberg_identify_used_duotone_blocks( $block_content, $block ) if( array_key_exists( $block['blockName'], self::$global_styles_block_names ) ) { $preset_slug = self::$global_styles_block_names[ $block['blockName'] ]; - self::$output_presets[ $preset_slug ] = self::$global_styles_presets[ $preset_slug ]; + self::$output[ $preset_slug ] = self::$global_styles_presets[ $preset_slug ]; } return $block_content; @@ -786,7 +786,7 @@ public static function duotone_declarations( $declarations, $selector ) { } // function gutenberg_get_duotone_preset_value( $preset ) { - if( array_key_exists( $preset['slug'], WP_Duotone::$output_presets ) ) { + if( array_key_exists( $preset['slug'], WP_Duotone::$output ) ) { // This is returning the --wp--preset--duotone--dark-grayscale: CSS VAR NAME; but not removing the full --wp--preset--duotone--dark-grayscale preset name return gutenberg_get_duotone_filter_property( $preset ); } From c39504b973707f4e1853538ad65bb576914d131b Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Fri, 10 Mar 2023 14:40:44 -0600 Subject: [PATCH 11/55] Fix theme json vs block styles duotone order of application Refactored out duotone specific code from theme json gutenberg globla styles. Switched theme_json_register_declarations from action to filter. --- lib/block-supports/duotone.php | 80 ++++++++++++++------------- lib/class-wp-theme-json-gutenberg.php | 39 ++----------- 2 files changed, 48 insertions(+), 71 deletions(-) diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php index 581e283486c1d8..e09152710dd51e 100644 --- a/lib/block-supports/duotone.php +++ b/lib/block-supports/duotone.php @@ -447,52 +447,55 @@ function gutenberg_render_duotone_support( $block_content, $block ) { return $block_content; } - // Possible values for duotone attribute: - // 1. Array of colors - e.g. array('#000000', '#ffffff'). - // 2. Variable for an existing Duotone preset - e.g. 'var:preset|duotone|green-blue'. - // 3. A CSS string - e.g. 'unset' to remove globally applied duotone. - $duotone_attr = $block['attrs']['style']['color']['duotone']; + // Generate the pieces needed for rendering a duotone to the page. + if( $has_duotone_attribute ) { - $is_preset = is_string( $duotone_attr ) && WP_Duotone::is_preset( $duotone_attr ); - $is_css = is_string( $duotone_attr ) && ! $is_preset; - $is_custom = is_array( $duotone_attr ); + // Possible values for duotone attribute: + // 1. Array of colors - e.g. array('#000000', '#ffffff'). + // 2. Variable for an existing Duotone preset - e.g. 'var:preset|duotone|green-blue' or 'var(--wp--preset--duotone--green-blue)'' + // 3. A CSS string - e.g. 'unset' to remove globally applied duotone. - // Generate the pieces needed for rendering a duotone to the page. - if ( $has_global_styles_duotone ) { - $slug = WP_Duotone::$global_styles_block_names[ $block['blockName'] ]; + $duotone_attr = $block['attrs']['style']['color']['duotone']; + $is_preset = is_string( $duotone_attr ) && WP_Duotone::is_preset( $duotone_attr ); + $is_css = is_string( $duotone_attr ) && ! $is_preset; + $is_custom = is_array( $duotone_attr ); - // Utilize existing preset CSS custom property. - $filter_property = "var(--wp--preset--duotone--$slug)"; - WP_Duotone::$output[ $slug ] = WP_Duotone::$global_styles_presets[ $slug ]; - } elseif ( $is_preset ) { + if ( $is_preset ) { - // TODO: Extract to set_output_preset( $filter_data ); - // Extract the slug from the preset variable string. - $slug = WP_Duotone::gutenberg_get_slug_from_attr( $duotone_attr ); + // TODO: Extract to set_output_preset( $filter_data ); + // Extract the slug from the preset variable string. + $slug = WP_Duotone::gutenberg_get_slug_from_attr( $duotone_attr ); - // Utilize existing preset CSS custom property. - $filter_property = "var(--wp--preset--duotone--$slug)"; + // Utilize existing preset CSS custom property. + $filter_property = "var(--wp--preset--duotone--$slug)"; - WP_Duotone::$output[ $slug ] = WP_Duotone::$global_styles_presets[ $slug ]; + WP_Duotone::$output[ $slug ] = WP_Duotone::$global_styles_presets[ $slug ]; - } elseif ( $is_css ) { - // Build a unique slug for the filter based on the CSS value. - $slug = wp_unique_id( sanitize_key( $duotone_attr . '-' ) ); + } elseif ( $is_css ) { + // Build a unique slug for the filter based on the CSS value. + $slug = wp_unique_id( sanitize_key( $duotone_attr . '-' ) ); - // Pass through the CSS value. - $filter_property = $duotone_attr; - } elseif ( $is_custom ) { - // Build a unique slug for the filter based on the array of colors. - $slug = wp_unique_id( sanitize_key( implode( '-', $duotone_attr ) . '-' ) ); + // Pass through the CSS value. + $filter_property = $duotone_attr; + } elseif ( $is_custom ) { + // Build a unique slug for the filter based on the array of colors. + $slug = wp_unique_id( sanitize_key( implode( '-', $duotone_attr ) . '-' ) ); - $filter_data = array( - 'slug' => $slug, - 'colors' => $duotone_attr, - ); - // Build a customized CSS filter property for unique slug. - $filter_property = gutenberg_get_duotone_filter_property( $filter_data ); + $filter_data = array( + 'slug' => $slug, + 'colors' => $duotone_attr, + ); + // Build a customized CSS filter property for unique slug. + $filter_property = gutenberg_get_duotone_filter_property( $filter_data ); + + WP_Duotone::$output[ $slug ] = $filter_data; + } + } elseif ( $has_global_styles_duotone ) { + $slug = WP_Duotone::$global_styles_block_names[ $block['blockName'] ]; - WP_Duotone::$output[ $slug ] = $filter_data; + // Utilize existing preset CSS custom property. + $filter_property = "var(--wp--preset--duotone--$slug)"; + WP_Duotone::$output[ $slug ] = WP_Duotone::$global_styles_presets[ $slug ]; } // - Applied as a class attribute to the block wrapper. @@ -780,8 +783,11 @@ public static function duotone_declarations( $declarations, $selector ) { foreach ( $declarations as $index => $declaration ) { if ( 'filter' === $declaration['name'] ) { static::$global_styles_presets[] = $declarations[ $index ]['value']; + unset( $declarations[ $index ] ); } } + + return $declarations; } } // @@ -797,4 +803,4 @@ function gutenberg_get_duotone_preset_value( $preset ) { add_action( 'wp_loaded', array( 'WP_Duotone', 'save_global_styles_presets' ), 10 ); add_action( 'wp_loaded', array( 'WP_Duotone', 'save_global_style_block_names' ), 10 ); -add_action( 'theme_json_register_declarations', array( 'WP_Duotone', 'duotone_declarations' ), 10, 2 ); \ No newline at end of file +add_filter( 'theme_json_register_declarations', array( 'WP_Duotone', 'duotone_declarations' ), 10, 2 ); \ No newline at end of file diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index 52798789bb446b..a79256d45afbbe 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -2435,46 +2435,17 @@ function( $pseudo_selector ) use ( $selector ) { $block_rules = ''; - do_action( 'theme_json_register_declarations', $declarations, $selector ); - - /* - * 1. Separate the declarations that use the general selector - * from the ones using the duotone selector. - */ - $declarations_duotone = array(); - foreach ( $declarations as $index => $declaration ) { - if ( 'filter' === $declaration['name'] ) { - /* - * 'unset' filters happen when a filter is unset - * in the site-editor UI. Because the 'unset' value - * in the user origin overrides the value in the - * theme origin, we can skip rendering anything - * here as no filter needs to be applied anymore. - * So only add declarations to with values other - * than 'unset'. - */ - if ( 'unset' !== $declaration['value'] ) { - $declarations_duotone[] = $declaration; - } - unset( $declarations[ $index ] ); - } - } + $declarations = apply_filters( 'theme_json_register_declarations', $declarations, $selector ); // Update declarations if there are separators with only background color defined. if ( '.wp-block-separator' === $selector ) { $declarations = static::update_separator_declarations( $declarations ); } - // 2. Generate and append the rules that use the general selector. + // Generate and append the rules that use the general selector. $block_rules .= static::to_ruleset( $selector, $declarations ); - // 3. Generate and append the rules that use the duotone selector. - if ( isset( $block_metadata['duotone'] ) && ! empty( $declarations_duotone ) ) { - $selector_duotone = static::scope_selector( $block_metadata['selector'], $block_metadata['duotone'] ); - $block_rules .= static::to_ruleset( $selector_duotone, $declarations_duotone ); - } - - // 4. Generate Layout block gap styles. + // Generate Layout block gap styles. if ( static::ROOT_BLOCK_SELECTOR !== $selector && ! empty( $block_metadata['name'] ) @@ -2482,12 +2453,12 @@ function( $pseudo_selector ) use ( $selector ) { $block_rules .= $this->get_layout_styles( $block_metadata ); } - // 5. Generate and append the feature level rulesets. + // Generate and append the feature level rulesets. foreach ( $feature_declarations as $feature_selector => $individual_feature_declarations ) { $block_rules .= static::to_ruleset( $feature_selector, $individual_feature_declarations ); } - // 6. Generate and append the style variation rulesets. + // Generate and append the style variation rulesets. foreach ( $style_variation_declarations as $style_variation_selector => $individual_style_variation_declarations ) { $block_rules .= static::to_ruleset( $style_variation_selector, $individual_style_variation_declarations ); } From 1f13855b8f7760ceac8131ca1db9971976c9c376 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Fri, 10 Mar 2023 14:48:03 -0600 Subject: [PATCH 12/55] Renamed filter to be more accurate, but should refactor out Doesn't seem like a legitimately useful filter at the moment. Only for us to be able to use global styles in our duotone-specific output. --- lib/block-supports/duotone.php | 4 ++-- lib/class-wp-theme-json-gutenberg.php | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php index e09152710dd51e..51786ace0c2863 100644 --- a/lib/block-supports/duotone.php +++ b/lib/block-supports/duotone.php @@ -779,7 +779,7 @@ static function gutenberg_identify_used_duotone_blocks( $block_content, $block ) * * @return array The block editor settings. */ - public static function duotone_declarations( $declarations, $selector ) { + public static function duotone_declarations( $declarations ) { foreach ( $declarations as $index => $declaration ) { if ( 'filter' === $declaration['name'] ) { static::$global_styles_presets[] = $declarations[ $index ]['value']; @@ -803,4 +803,4 @@ function gutenberg_get_duotone_preset_value( $preset ) { add_action( 'wp_loaded', array( 'WP_Duotone', 'save_global_styles_presets' ), 10 ); add_action( 'wp_loaded', array( 'WP_Duotone', 'save_global_style_block_names' ), 10 ); -add_filter( 'theme_json_register_declarations', array( 'WP_Duotone', 'duotone_declarations' ), 10, 2 ); \ No newline at end of file +add_filter( 'theme_json_styles_declarations', array( 'WP_Duotone', 'duotone_declarations' ), 10, 1 ); \ No newline at end of file diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index a79256d45afbbe..5d3be516d97e8e 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -2435,7 +2435,9 @@ function( $pseudo_selector ) use ( $selector ) { $block_rules = ''; - $declarations = apply_filters( 'theme_json_register_declarations', $declarations, $selector ); + // TODO: See if we can refactor this out. We only want to scrape the duotone-specific theme json into duotone_declarations in declarations. + // Can we read the theme.json file and grab our duotone-specific declrations easily a different way? + $declarations = apply_filters( 'theme_json_styles_declarations', $declarations ); // Update declarations if there are separators with only background color defined. if ( '.wp-block-separator' === $selector ) { From 0c67759d896e07557b1ad23b388c84193bafb411 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Mon, 13 Mar 2023 16:53:43 -0500 Subject: [PATCH 13/55] Simplify getting global styles presets We were already getting the presets via the global settings, so the filter was unnecessary. --- lib/block-supports/duotone.php | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php index 51786ace0c2863..c43bfea405ab63 100644 --- a/lib/block-supports/duotone.php +++ b/lib/block-supports/duotone.php @@ -690,14 +690,11 @@ class WP_Duotone { */ static function save_global_styles_presets() { // Get the per block settings from the theme.json. - $tree = WP_Theme_JSON_Resolver::get_merged_data(); - $settings = $tree->get_settings(); - $presets_by_origin = _wp_array_get( $settings, array( 'color', 'duotone' ), array() ); - $flat_presets = []; - // Flatten the array + $tree = gutenberg_get_global_settings(); + $presets_by_origin = _wp_array_get( $tree, array( 'color', 'duotone' ), array() ); + foreach( $presets_by_origin as $presets ) { foreach( $presets as $preset ) { - // $flat_presets[ _wp_to_kebab_case( $preset['slug'] ) ] = $preset; self::$global_styles_presets[ _wp_to_kebab_case( $preset['slug'] ) ] = [ 'slug' => $preset[ 'slug' ], 'colors' => $preset[ 'colors' ], @@ -714,7 +711,7 @@ static function save_global_style_block_names() { $tree = WP_Theme_JSON_Resolver::get_merged_data(); $block_nodes = $tree->get_styles_block_nodes(); $theme_json = $tree->get_raw_data(); - + foreach( $block_nodes as $block_node ) { // This block definition doesn't include any duotone settings. Skip it. @@ -780,9 +777,9 @@ static function gutenberg_identify_used_duotone_blocks( $block_content, $block ) * @return array The block editor settings. */ public static function duotone_declarations( $declarations ) { + // TODO: Revert theme_json_styles_declarations filter and file to original state, as we don't need to access it via filter. Let that be a separate PR. foreach ( $declarations as $index => $declaration ) { if ( 'filter' === $declaration['name'] ) { - static::$global_styles_presets[] = $declarations[ $index ]['value']; unset( $declarations[ $index ] ); } } From e41b1e670c2c9b8a200d5b9f24d19d31e36c8fce Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Mon, 13 Mar 2023 17:01:02 -0500 Subject: [PATCH 14/55] Undo theme json class duotone refactoring and remove filter The filter isn't necesary for us to access what we need. I've removed the refactor as it would be a larger change that can be done in a different PR if needed. --- lib/class-wp-theme-json-gutenberg.php | 39 ++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index 5d3be516d97e8e..3d8c6b32f132f8 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -2435,19 +2435,44 @@ function( $pseudo_selector ) use ( $selector ) { $block_rules = ''; - // TODO: See if we can refactor this out. We only want to scrape the duotone-specific theme json into duotone_declarations in declarations. - // Can we read the theme.json file and grab our duotone-specific declrations easily a different way? - $declarations = apply_filters( 'theme_json_styles_declarations', $declarations ); + /* + * 1. Separate the declarations that use the general selector + * from the ones using the duotone selector. + */ + $declarations_duotone = array(); + foreach ( $declarations as $index => $declaration ) { + if ( 'filter' === $declaration['name'] ) { + /* + * 'unset' filters happen when a filter is unset + * in the site-editor UI. Because the 'unset' value + * in the user origin overrides the value in the + * theme origin, we can skip rendering anything + * here as no filter needs to be applied anymore. + * So only add declarations to with values other + * than 'unset'. + */ + if ( 'unset' !== $declaration['value'] ) { + $declarations_duotone[] = $declaration; + } + unset( $declarations[ $index ] ); + } + } // Update declarations if there are separators with only background color defined. if ( '.wp-block-separator' === $selector ) { $declarations = static::update_separator_declarations( $declarations ); } - // Generate and append the rules that use the general selector. + // 2. Generate and append the rules that use the general selector. $block_rules .= static::to_ruleset( $selector, $declarations ); - // Generate Layout block gap styles. + // 3. Generate and append the rules that use the duotone selector. + if ( isset( $block_metadata['duotone'] ) && ! empty( $declarations_duotone ) ) { + $selector_duotone = static::scope_selector( $block_metadata['selector'], $block_metadata['duotone'] ); + $block_rules .= static::to_ruleset( $selector_duotone, $declarations_duotone ); + } + + // 4. Generate Layout block gap styles. if ( static::ROOT_BLOCK_SELECTOR !== $selector && ! empty( $block_metadata['name'] ) @@ -2455,12 +2480,12 @@ function( $pseudo_selector ) use ( $selector ) { $block_rules .= $this->get_layout_styles( $block_metadata ); } - // Generate and append the feature level rulesets. + // 5. Generate and append the feature level rulesets. foreach ( $feature_declarations as $feature_selector => $individual_feature_declarations ) { $block_rules .= static::to_ruleset( $feature_selector, $individual_feature_declarations ); } - // Generate and append the style variation rulesets. + // 6. Generate and append the style variation rulesets. foreach ( $style_variation_declarations as $style_variation_selector => $individual_style_variation_declarations ) { $block_rules .= static::to_ruleset( $style_variation_selector, $individual_style_variation_declarations ); } From 45426d2903fd746633e0faedb1c66cac7cc4deb1 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Mon, 13 Mar 2023 17:05:46 -0500 Subject: [PATCH 15/55] Remove unused code --- lib/block-supports/duotone.php | 46 +--------------------------------- 1 file changed, 1 insertion(+), 45 deletions(-) diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php index c43bfea405ab63..1f32ea9ceae4ee 100644 --- a/lib/block-supports/duotone.php +++ b/lib/block-supports/duotone.php @@ -753,51 +753,7 @@ static function gutenberg_get_slug_from_attr( $duotone_attr ) { static function is_preset( $duotone_attr ) { return strpos( $duotone_attr, 'var:preset|duotone|' ) === 0 || strpos( $duotone_attr, 'var(--wp--preset--duotone--' ) === 0; } - - /** - * Get all possible duotone presets from global and theme styles. We only want to process this one time. On block render we'll access and output only the needed presets for that page. - * - */ - static function gutenberg_identify_used_duotone_blocks( $block_content, $block ) { - // If the block name exists in our pre-defined list of block selectors that use duotone in theme.json (or related), add it to our list of duotone to output - if( array_key_exists( $block['blockName'], self::$global_styles_block_names ) ) { - $preset_slug = self::$global_styles_block_names[ $block['blockName'] ]; - - self::$output[ $preset_slug ] = self::$global_styles_presets[ $preset_slug ]; - } - - return $block_content; - } - - /** - * Registers the duotone preset. - * - * @param array $settings The block editor settings. - * - * @return array The block editor settings. - */ - public static function duotone_declarations( $declarations ) { - // TODO: Revert theme_json_styles_declarations filter and file to original state, as we don't need to access it via filter. Let that be a separate PR. - foreach ( $declarations as $index => $declaration ) { - if ( 'filter' === $declaration['name'] ) { - unset( $declarations[ $index ] ); - } - } - - return $declarations; - } } -// -function gutenberg_get_duotone_preset_value( $preset ) { - if( array_key_exists( $preset['slug'], WP_Duotone::$output ) ) { - // This is returning the --wp--preset--duotone--dark-grayscale: CSS VAR NAME; but not removing the full --wp--preset--duotone--dark-grayscale preset name - return gutenberg_get_duotone_filter_property( $preset ); - } - - return ''; -} - add_action( 'wp_loaded', array( 'WP_Duotone', 'save_global_styles_presets' ), 10 ); -add_action( 'wp_loaded', array( 'WP_Duotone', 'save_global_style_block_names' ), 10 ); -add_filter( 'theme_json_styles_declarations', array( 'WP_Duotone', 'duotone_declarations' ), 10, 1 ); \ No newline at end of file +add_action( 'wp_loaded', array( 'WP_Duotone', 'save_global_style_block_names' ), 10 ); \ No newline at end of file From 3d224bffa36a91927b3b5837d8e1d8ef365f2aef Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Tue, 14 Mar 2023 09:41:05 -0500 Subject: [PATCH 16/55] Rename save_ to set_ class method names --- lib/block-supports/duotone.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php index 1f32ea9ceae4ee..5e09660332d581 100644 --- a/lib/block-supports/duotone.php +++ b/lib/block-supports/duotone.php @@ -581,7 +581,7 @@ static function () { $duotone_css_vars = ''; foreach ( WP_Duotone::$output as $filter_data ) { - if( ! array_key_exists( $filter_data['slug'], WP_Duotone::$global_styles_presets ) ) { + if( ! array_key_exists( $filter_data[ 'slug' ], WP_Duotone::$global_styles_presets ) ) { continue; } @@ -688,7 +688,7 @@ class WP_Duotone { * We only want to process this one time. On block render we'll access and output only the needed presets for that page. * */ - static function save_global_styles_presets() { + static function set_global_styles_presets() { // Get the per block settings from the theme.json. $tree = gutenberg_get_global_settings(); $presets_by_origin = _wp_array_get( $tree, array( 'color', 'duotone' ), array() ); @@ -706,7 +706,7 @@ static function save_global_styles_presets() { /** * Scrape all block names from global styles and store in WP_Duotone::$global_styles_block_names */ - static function save_global_style_block_names() { + static function set_global_style_block_names() { // Get the per block settings from the theme.json. $tree = WP_Theme_JSON_Resolver::get_merged_data(); $block_nodes = $tree->get_styles_block_nodes(); @@ -755,5 +755,5 @@ static function is_preset( $duotone_attr ) { } } -add_action( 'wp_loaded', array( 'WP_Duotone', 'save_global_styles_presets' ), 10 ); -add_action( 'wp_loaded', array( 'WP_Duotone', 'save_global_style_block_names' ), 10 ); \ No newline at end of file +add_action( 'wp_loaded', array( 'WP_Duotone', 'set_global_styles_presets' ), 10 ); +add_action( 'wp_loaded', array( 'WP_Duotone', 'set_global_style_block_names' ), 10 ); \ No newline at end of file From 476fe04eee63a563725d19c88623fc789ebc8607 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Tue, 14 Mar 2023 09:51:09 -0500 Subject: [PATCH 17/55] Fix duotone test to use real global preset value --- phpunit/block-supports/duotone-test.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/phpunit/block-supports/duotone-test.php b/phpunit/block-supports/duotone-test.php index 3588950468aba4..11e586ad0a34af 100644 --- a/phpunit/block-supports/duotone-test.php +++ b/phpunit/block-supports/duotone-test.php @@ -10,10 +10,10 @@ class WP_Block_Supports_Duotone_Test extends WP_UnitTestCase { public function test_gutenberg_render_duotone_support_preset() { $block = array( 'blockName' => 'core/image', - 'attrs' => array( 'style' => array( 'color' => array( 'duotone' => 'var:preset|duotone|slug' ) ) ), + 'attrs' => array( 'style' => array( 'color' => array( 'duotone' => 'var:preset|duotone|blue-orange' ) ) ), ); $block_content = '
'; - $expected = '
'; + $expected = '
'; $this->assertSame( $expected, gutenberg_render_duotone_support( $block_content, $block ) ); } From c23a4a494e2a5d02b8277abb59388a48fa67c45a Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Tue, 14 Mar 2023 10:55:14 -0500 Subject: [PATCH 18/55] Tests for WP_Duotone::gutenberg_get_slug_from_attr() --- phpunit/block-supports/duotone-test.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/phpunit/block-supports/duotone-test.php b/phpunit/block-supports/duotone-test.php index 11e586ad0a34af..4bb35f5979163f 100644 --- a/phpunit/block-supports/duotone-test.php +++ b/phpunit/block-supports/duotone-test.php @@ -37,4 +37,24 @@ public function test_gutenberg_render_duotone_support_custom() { $this->assertMatchesRegularExpression( $expected, gutenberg_render_duotone_support( $block_content, $block ) ); } + public function data_gutenberg_get_slug_from_attr() { + return array( + 'pipe-slug' => array( 'var:preset|duotone|blue-orange', 'blue-orange' ), + 'css-var' => array( 'var(--wp--preset--duotone--blue-orange)', 'blue-orange' ), + 'css-var-weird-chars' => array( 'var(--wp--preset--duotone--.)', '.' ), + 'css-var-missing-end-parenthesis' => array( 'var(--wp--preset--duotone--blue-orange', '' ), + 'invalid' => array( 'not a valid attribute', '' ), + 'css-var-no-value' => array( 'var(--wp--preset--duotone--)', '' ), + 'pipe-slug-no-value' => array( 'var:preset|duotone|', '' ), + 'css-var-spaces' => array( 'var(--wp--preset--duotone-- ', '' ), + 'pipe-slug-spaces' => array( 'var:preset|duotone| ', '' ), + ); + } + + /** + * @dataProvider data_gutenberg_get_slug_from_attr + */ + public function test_gutenberg_get_slug_from_attr( $data_attr, $expected ) { + $this->assertSame( $expected, WP_Duotone::gutenberg_get_slug_from_attr( $data_attr ) ); + } } From 47d86d4a710f9fc6da932d49cdd7e9d16b9ab5ba Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Tue, 14 Mar 2023 10:57:03 -0500 Subject: [PATCH 19/55] Rework gutenberg_get_slug_from_attr to use regex for more accurate matches --- lib/block-supports/duotone.php | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php index 5e09660332d581..a275ef10e6eda9 100644 --- a/lib/block-supports/duotone.php +++ b/lib/block-supports/duotone.php @@ -469,7 +469,13 @@ function gutenberg_render_duotone_support( $block_content, $block ) { // Utilize existing preset CSS custom property. $filter_property = "var(--wp--preset--duotone--$slug)"; + if ( ! array_key_exists( $slug, WP_Duotone::$global_styles_presets ) ) { + // We have a preset slug, but the preset isn't defined in the array so we have no duotone to apply + return; + } + WP_Duotone::$output[ $slug ] = WP_Duotone::$global_styles_presets[ $slug ]; + } elseif ( $is_css ) { // Build a unique slug for the filter based on the CSS value. @@ -495,6 +501,12 @@ function gutenberg_render_duotone_support( $block_content, $block ) { // Utilize existing preset CSS custom property. $filter_property = "var(--wp--preset--duotone--$slug)"; + + if ( ! array_key_exists( $slug, WP_Duotone::$global_styles_presets ) ) { + // We have a preset slug, but the preset isn't defined in the array so we have no duotone to apply + return; + } + WP_Duotone::$output[ $slug ] = WP_Duotone::$global_styles_presets[ $slug ]; } @@ -741,16 +753,21 @@ static function set_global_style_block_names() { * var(--wp--preset--duotone--blue-orange) * * @param string $duotone_attr The duotone attribute from a block. - * @return string The slug of the duotone preset. + * @return string The slug of the duotone preset or an empty string if no slug is found. */ static function gutenberg_get_slug_from_attr( $duotone_attr ) { - return str_replace( [ 'var:preset|duotone|', 'var(--wp--preset--duotone--', ')' ], '', $duotone_attr ); + // Uses Branch Reset Groups `(?|…)` to return one capture group + preg_match( '/(?|var:preset\|duotone\|(\S+)|var\(--wp--preset--duotone--(\S+)\))/', $duotone_attr, $matches ); + + return ! empty( $matches[ 1 ] ) ? $matches[ 1 ] : ''; } /** * Check if we have a duotone preset string */ static function is_preset( $duotone_attr ) { + // TODO: Should we also check if the array_key_exists in self::$global_styles_presets? + // Potential route — rename to is_preset_format and have another check if it's within the global styles presets. return strpos( $duotone_attr, 'var:preset|duotone|' ) === 0 || strpos( $duotone_attr, 'var(--wp--preset--duotone--' ) === 0; } } From a7fab1743c7d960777136f18768839a467827c57 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Tue, 14 Mar 2023 11:17:27 -0500 Subject: [PATCH 20/55] Tests for WP_Duotone::is_preset --- phpunit/block-supports/duotone-test.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/phpunit/block-supports/duotone-test.php b/phpunit/block-supports/duotone-test.php index 4bb35f5979163f..f28f57a59a8941 100644 --- a/phpunit/block-supports/duotone-test.php +++ b/phpunit/block-supports/duotone-test.php @@ -57,4 +57,21 @@ public function data_gutenberg_get_slug_from_attr() { public function test_gutenberg_get_slug_from_attr( $data_attr, $expected ) { $this->assertSame( $expected, WP_Duotone::gutenberg_get_slug_from_attr( $data_attr ) ); } + + public function data_is_preset() { + return array( + 'pipe-slug' => array( 'var:preset|duotone|blue-orange', true ), + 'css-var' => array( 'var(--wp--preset--duotone--blue-orange)', true ), + 'css-var-weird-chars' => array( 'var(--wp--preset--duotone--.)', false ), + 'css-var-missing-end-parenthesis' => array( 'var(--wp--preset--duotone--blue-orange', false ), + 'invalid' => array( 'not a valid attribute', false ), + ); + } + + /** + * @dataProvider data_is_preset + */ + public function test_is_preset( $data_attr, $expected ) { + $this->assertSame( $expected, WP_Duotone::is_preset( $data_attr ) ); + } } From af3a23659cc7fa6e90b37719ab7c9f00254ceff0 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Tue, 14 Mar 2023 11:18:06 -0500 Subject: [PATCH 21/55] Rework is_preset to also check if the preset exists --- lib/block-supports/duotone.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php index a275ef10e6eda9..97dfa77218602b 100644 --- a/lib/block-supports/duotone.php +++ b/lib/block-supports/duotone.php @@ -763,12 +763,12 @@ static function gutenberg_get_slug_from_attr( $duotone_attr ) { } /** - * Check if we have a duotone preset string + * Check if we have a valid duotone preset */ static function is_preset( $duotone_attr ) { - // TODO: Should we also check if the array_key_exists in self::$global_styles_presets? - // Potential route — rename to is_preset_format and have another check if it's within the global styles presets. - return strpos( $duotone_attr, 'var:preset|duotone|' ) === 0 || strpos( $duotone_attr, 'var(--wp--preset--duotone--' ) === 0; + $slug = WP_Duotone::gutenberg_get_slug_from_attr( $duotone_attr ); + + return array_key_exists( $slug, WP_Duotone::$global_styles_presets ); } } From 005baa17dace66e8398658a6c166b5a8eb089327 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Tue, 14 Mar 2023 11:19:49 -0500 Subject: [PATCH 22/55] Remove array_key_exists checks for presets within the block filter --- lib/block-supports/duotone.php | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php index 97dfa77218602b..dbdc2cc541c8d5 100644 --- a/lib/block-supports/duotone.php +++ b/lib/block-supports/duotone.php @@ -469,11 +469,6 @@ function gutenberg_render_duotone_support( $block_content, $block ) { // Utilize existing preset CSS custom property. $filter_property = "var(--wp--preset--duotone--$slug)"; - if ( ! array_key_exists( $slug, WP_Duotone::$global_styles_presets ) ) { - // We have a preset slug, but the preset isn't defined in the array so we have no duotone to apply - return; - } - WP_Duotone::$output[ $slug ] = WP_Duotone::$global_styles_presets[ $slug ]; @@ -501,11 +496,6 @@ function gutenberg_render_duotone_support( $block_content, $block ) { // Utilize existing preset CSS custom property. $filter_property = "var(--wp--preset--duotone--$slug)"; - - if ( ! array_key_exists( $slug, WP_Duotone::$global_styles_presets ) ) { - // We have a preset slug, but the preset isn't defined in the array so we have no duotone to apply - return; - } WP_Duotone::$output[ $slug ] = WP_Duotone::$global_styles_presets[ $slug ]; } From c7160de7304ac8ff3537b89502f134db1d122b12 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Tue, 14 Mar 2023 15:35:46 -0500 Subject: [PATCH 23/55] Return early if no block content For some reason, the render_block filter runs even on blocks that are not included on the page. So, if you have a duotone filter defined in your theme.json, such as for the core/post-featured-image block, it will run the block filter even if no featured image is set. As a result, the duotonen defined in theme.json per block would get output even if that block wasn't in use. The only reliable check I could find to determine if the block was in use or not was to check the block content. By bailing early if no block content, we avoid adding unused SVG to the output. --- lib/block-supports/duotone.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php index dbdc2cc541c8d5..ca8fa1e443b845 100644 --- a/lib/block-supports/duotone.php +++ b/lib/block-supports/duotone.php @@ -441,6 +441,7 @@ function gutenberg_render_duotone_support( $block_content, $block ) { $has_global_styles_duotone = array_key_exists( $block['blockName'], WP_Duotone::$global_styles_block_names ); if ( + empty( $block_content ) || ! $duotone_support || ( ! $has_duotone_attribute && ! $has_global_styles_duotone ) ) { From f5499b4814b48c2da5915ba915740b7f293f04c8 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Tue, 14 Mar 2023 16:13:20 -0500 Subject: [PATCH 24/55] Make linter happy --- lib/block-supports/duotone.php | 218 ++++----------------- lib/class-wp-duotone.php | 150 ++++++++++++++ lib/compat/wordpress-6.2/script-loader.php | 4 +- lib/load.php | 1 + phpunit/block-supports/duotone-test.php | 28 +-- 5 files changed, 207 insertions(+), 194 deletions(-) create mode 100644 lib/class-wp-duotone.php diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php index ca8fa1e443b845..afb521f5ea73eb 100644 --- a/lib/block-supports/duotone.php +++ b/lib/block-supports/duotone.php @@ -437,9 +437,9 @@ function gutenberg_render_duotone_support( $block_content, $block ) { } // The block should have a duotone attribute or have duotone defined in its theme.json to be processed. - $has_duotone_attribute = isset( $block['attrs']['style']['color']['duotone'] ); + $has_duotone_attribute = isset( $block['attrs']['style']['color']['duotone'] ); $has_global_styles_duotone = array_key_exists( $block['blockName'], WP_Duotone::$global_styles_block_names ); - + if ( empty( $block_content ) || ! $duotone_support || @@ -449,7 +449,7 @@ function gutenberg_render_duotone_support( $block_content, $block ) { } // Generate the pieces needed for rendering a duotone to the page. - if( $has_duotone_attribute ) { + if ( $has_duotone_attribute ) { // Possible values for duotone attribute: // 1. Array of colors - e.g. array('#000000', '#ffffff'). @@ -457,13 +457,12 @@ function gutenberg_render_duotone_support( $block_content, $block ) { // 3. A CSS string - e.g. 'unset' to remove globally applied duotone. $duotone_attr = $block['attrs']['style']['color']['duotone']; - $is_preset = is_string( $duotone_attr ) && WP_Duotone::is_preset( $duotone_attr ); - $is_css = is_string( $duotone_attr ) && ! $is_preset; - $is_custom = is_array( $duotone_attr ); + $is_preset = is_string( $duotone_attr ) && WP_Duotone::is_preset( $duotone_attr ); + $is_css = is_string( $duotone_attr ) && ! $is_preset; + $is_custom = is_array( $duotone_attr ); if ( $is_preset ) { - // TODO: Extract to set_output_preset( $filter_data ); // Extract the slug from the preset variable string. $slug = WP_Duotone::gutenberg_get_slug_from_attr( $duotone_attr ); @@ -471,7 +470,6 @@ function gutenberg_render_duotone_support( $block_content, $block ) { $filter_property = "var(--wp--preset--duotone--$slug)"; WP_Duotone::$output[ $slug ] = WP_Duotone::$global_styles_presets[ $slug ]; - } elseif ( $is_css ) { // Build a unique slug for the filter based on the CSS value. @@ -497,7 +495,7 @@ function gutenberg_render_duotone_support( $block_content, $block ) { // Utilize existing preset CSS custom property. $filter_property = "var(--wp--preset--duotone--$slug)"; - + WP_Duotone::$output[ $slug ] = WP_Duotone::$global_styles_presets[ $slug ]; } @@ -509,11 +507,10 @@ function gutenberg_render_duotone_support( $block_content, $block ) { $selector = WP_Theme_JSON_Gutenberg::scope_selector( '.' . $filter_id, $duotone_support ); // We only want to add the selector if we have it in the output already, essentially skipping 'unset'. - // TODO: Extract to set_output_preset( $filter_data ); - if( array_key_exists( $slug, WP_Duotone::$output ) ) { - WP_Duotone::$output[ $slug ][ 'selector' ] = $selector; + if ( array_key_exists( $slug, WP_Duotone::$output ) ) { + WP_Duotone::$output[ $slug ]['selector'] = $selector; } - + // Calling gutenberg_style_engine_get_stylesheet_from_css_rules ensures that // the styles are rendered in an inline for block supports because we're // using the `context` option to instruct it so. @@ -534,7 +531,6 @@ function gutenberg_render_duotone_support( $block_content, $block ) { 'context' => 'block-supports', ) ); - // Like the layout hook, this assumes the hook only applies to blocks with a single wrapper. return preg_replace( @@ -546,27 +542,27 @@ function gutenberg_render_duotone_support( $block_content, $block ) { } -add_action( 'wp_footer', +add_action( + 'wp_footer', static function () { - foreach( WP_Duotone::$output as $filter_data ) { + foreach ( WP_Duotone::$output as $filter_data ) { $filter_property = gutenberg_get_duotone_filter_property( $filter_data ); // SVG will be output on the page later. $filter_svg = gutenberg_get_duotone_filter_svg( $filter_data ); - + echo $filter_svg; - // This is for classic themes - in block themes, the CSS is added in the head via the value_func. - if( ! wp_is_block_theme() ) { - $duotone_preset_css_var = WP_Theme_JSON_Gutenberg::get_preset_css_var( array( 'color', 'duotone' ), $filter_data[ 'slug'] ); + if ( ! wp_is_block_theme() ) { + $duotone_preset_css_var = WP_Theme_JSON_Gutenberg::get_preset_css_var( array( 'color', 'duotone' ), $filter_data['slug'] ); wp_add_inline_style( 'core-block-supports', 'body{' . $duotone_preset_css_var . ' :' . $filter_property . ';}' ); } global $is_safari; - if( $is_safari ) { - duotone_safari_rerender_hack( $selector ); + if ( $is_safari ) { + duotone_safari_rerender_hack( $filter_data['selector'] ); } } } @@ -575,29 +571,33 @@ static function () { /** * Appends the used duotone fitler CSS Vars to the inline global styles CSS */ -add_action( 'wp_enqueue_scripts', static function() { +add_action( + 'wp_enqueue_scripts', + static function() { - if( empty( WP_Duotone::$output ) ) { - return; - } + if ( empty( WP_Duotone::$output ) ) { + return; + } - $duotone_css_vars = ''; + $duotone_css_vars = ''; - foreach ( WP_Duotone::$output as $filter_data ) { - if( ! array_key_exists( $filter_data[ 'slug' ], WP_Duotone::$global_styles_presets ) ) { - continue; - } + foreach ( WP_Duotone::$output as $filter_data ) { + if ( ! array_key_exists( $filter_data['slug'], WP_Duotone::$global_styles_presets ) ) { + continue; + } - $filter_property = gutenberg_get_duotone_filter_property( $filter_data ); - - $duotone_preset_css_var = WP_Theme_JSON_Gutenberg::get_preset_css_var( array( 'color', 'duotone' ), $filter_data[ 'slug'] ); - $duotone_css_vars .= $duotone_preset_css_var . ': ' . $filter_property . ';'; - } + $filter_property = gutenberg_get_duotone_filter_property( $filter_data ); - if( ! empty( $duotone_css_vars ) ) { - wp_add_inline_style( 'global-styles', 'body{' . $duotone_css_vars . '}' ); - } -}, 11 ); + $duotone_preset_css_var = WP_Theme_JSON_Gutenberg::get_preset_css_var( array( 'color', 'duotone' ), $filter_data['slug'] ); + $duotone_css_vars .= $duotone_preset_css_var . ': ' . $filter_property . ';'; + } + + if ( ! empty( $duotone_css_vars ) ) { + wp_add_inline_style( 'global-styles', 'body{' . $duotone_css_vars . '}' ); + } + }, + 11 +); /** * Safari renders elements incorrectly on first paint when the SVG filter comes after the content that it is filtering, @@ -627,141 +627,3 @@ function duotone_safari_rerender_hack( $selector ) { // Remove WordPress core filter to avoid rendering duplicate support elements. remove_filter( 'render_block', 'wp_render_duotone_support', 10, 2 ); add_filter( 'render_block', 'gutenberg_render_duotone_support', 10, 2 ); - - -class WP_Duotone { - /** - * An array of Duotone presets from global, theme, and custom styles. - * - * Example: - * [ - * 'blue-orange' => - * [ - * 'slug' => 'blue-orange', - * 'colors' => [ '#0000ff', '#ffcc00' ], - * ] - * ], - * … - * ] - * - * @since 6.3.0 - * @var array - */ - static $global_styles_presets = array(); - - /** - * An array of block names from global, theme, and custom styles that have duotone presets. We'll use this to quickly - * check if a block being rendered needs to have duotone applied, and which duotone preset to use. - * - * Example: - * [ - * 'core/featured-image' => 'blue-orange', - * … - * ] - * - */ - static $global_styles_block_names = array(); - - /** - * An array of Duotone SVG and CSS ouput needed for the frontend duotone rendering based on what is - * being ouptput on the page. Organized by a slug of the preset/color group and the information needed - * to generate the SVG and CSS at render. - * - * Example: - * [ - * 'blue-orange' => [ - * 'slug' => 'blue-orange', - * 'colors' => [ '#0000ff', '#ffcc00' ], - * ], - * 'wp-duotone-000000-ffffff-2' => [ - * 'slug' => 'wp-duotone-000000-ffffff-2', - * 'colors' => [ '#000000', '#ffffff' ], - * ], - * ] - * - * @since 6.3.0 - * @var array - */ - static $output = array(); - - - - /** - * Get all possible duotone presets from global and theme styles and store as slug => [ colors array ] - * We only want to process this one time. On block render we'll access and output only the needed presets for that page. - * - */ - static function set_global_styles_presets() { - // Get the per block settings from the theme.json. - $tree = gutenberg_get_global_settings(); - $presets_by_origin = _wp_array_get( $tree, array( 'color', 'duotone' ), array() ); - - foreach( $presets_by_origin as $presets ) { - foreach( $presets as $preset ) { - self::$global_styles_presets[ _wp_to_kebab_case( $preset['slug'] ) ] = [ - 'slug' => $preset[ 'slug' ], - 'colors' => $preset[ 'colors' ], - ]; - } - } - } - - /** - * Scrape all block names from global styles and store in WP_Duotone::$global_styles_block_names - */ - static function set_global_style_block_names() { - // Get the per block settings from the theme.json. - $tree = WP_Theme_JSON_Resolver::get_merged_data(); - $block_nodes = $tree->get_styles_block_nodes(); - $theme_json = $tree->get_raw_data(); - - - foreach( $block_nodes as $block_node ) { - // This block definition doesn't include any duotone settings. Skip it. - if ( empty( $block_node['duotone'] ) ) { - continue; - } - - // Value looks like this: 'var(--wp--preset--duotone--blue-orange)' or 'var:preset|duotone|default-filter' - $duotone_attr_path = array_merge( $block_node['path'], array( 'filter', 'duotone' ) ); - $duotone_attr = _wp_array_get( $theme_json, $duotone_attr_path, array() ); - - if( empty( $duotone_attr ) ) { - continue; - } - // If it has a duotone filter preset, save the block name and the preset slug. - $slug = self::gutenberg_get_slug_from_attr( $duotone_attr ); - - if( $slug && $slug !== $duotone_attr) { - self::$global_styles_block_names[ $block_node[ 'name' ] ] = $slug; - } - } - } - - /** - * Take the inline CSS duotone variable from a block and return the slug. Handles styles slugs like: - * var:preset|duotone|default-filter - * var(--wp--preset--duotone--blue-orange) - * - * @param string $duotone_attr The duotone attribute from a block. - * @return string The slug of the duotone preset or an empty string if no slug is found. - */ - static function gutenberg_get_slug_from_attr( $duotone_attr ) { - // Uses Branch Reset Groups `(?|…)` to return one capture group - preg_match( '/(?|var:preset\|duotone\|(\S+)|var\(--wp--preset--duotone--(\S+)\))/', $duotone_attr, $matches ); - - return ! empty( $matches[ 1 ] ) ? $matches[ 1 ] : ''; - } - - /** - * Check if we have a valid duotone preset - */ - static function is_preset( $duotone_attr ) { - $slug = WP_Duotone::gutenberg_get_slug_from_attr( $duotone_attr ); - - return array_key_exists( $slug, WP_Duotone::$global_styles_presets ); - } -} - -add_action( 'wp_loaded', array( 'WP_Duotone', 'set_global_styles_presets' ), 10 ); -add_action( 'wp_loaded', array( 'WP_Duotone', 'set_global_style_block_names' ), 10 ); \ No newline at end of file diff --git a/lib/class-wp-duotone.php b/lib/class-wp-duotone.php new file mode 100644 index 00000000000000..8f15efbecf0ad3 --- /dev/null +++ b/lib/class-wp-duotone.php @@ -0,0 +1,150 @@ + + * [ + * 'slug' => 'blue-orange', + * 'colors' => [ '#0000ff', '#ffcc00' ], + * ] + * ], + * … + * ] + * + * @since 6.3.0 + * @var array + */ + static $global_styles_presets = array(); + + /** + * An array of block names from global, theme, and custom styles that have duotone presets. We'll use this to quickly + * check if a block being rendered needs to have duotone applied, and which duotone preset to use. + * + * Example: + * [ + * 'core/featured-image' => 'blue-orange', + * … + * ] + * + * @since 6.3.0 + * @var array + */ + static $global_styles_block_names = array(); + + /** + * An array of Duotone SVG and CSS ouput needed for the frontend duotone rendering based on what is + * being ouptput on the page. Organized by a slug of the preset/color group and the information needed + * to generate the SVG and CSS at render. + * + * Example: + * [ + * 'blue-orange' => [ + * 'slug' => 'blue-orange', + * 'colors' => [ '#0000ff', '#ffcc00' ], + * ], + * 'wp-duotone-000000-ffffff-2' => [ + * 'slug' => 'wp-duotone-000000-ffffff-2', + * 'colors' => [ '#000000', '#ffffff' ], + * ], + * ] + * + * @since 6.3.0 + * @var array + */ + static $output = array(); + + /** + * Get all possible duotone presets from global and theme styles and store as slug => [ colors array ] + * We only want to process this one time. On block render we'll access and output only the needed presets for that page. + */ + static function set_global_styles_presets() { + // Get the per block settings from the theme.json. + $tree = gutenberg_get_global_settings(); + $presets_by_origin = _wp_array_get( $tree, array( 'color', 'duotone' ), array() ); + + foreach ( $presets_by_origin as $presets ) { + foreach ( $presets as $preset ) { + self::$global_styles_presets[ _wp_to_kebab_case( $preset['slug'] ) ] = array( + 'slug' => $preset['slug'], + 'colors' => $preset['colors'], + ); + } + } + } + + /** + * Scrape all block names from global styles and store in WP_Duotone::$global_styles_block_names + */ + static function set_global_style_block_names() { + // Get the per block settings from the theme.json. + $tree = WP_Theme_JSON_Resolver::get_merged_data(); + $block_nodes = $tree->get_styles_block_nodes(); + $theme_json = $tree->get_raw_data(); + + foreach ( $block_nodes as $block_node ) { + // This block definition doesn't include any duotone settings. Skip it. + if ( empty( $block_node['duotone'] ) ) { + continue; + } + + // Value looks like this: 'var(--wp--preset--duotone--blue-orange)' or 'var:preset|duotone|default-filter'. + $duotone_attr_path = array_merge( $block_node['path'], array( 'filter', 'duotone' ) ); + $duotone_attr = _wp_array_get( $theme_json, $duotone_attr_path, array() ); + + if ( empty( $duotone_attr ) ) { + continue; + } + // If it has a duotone filter preset, save the block name and the preset slug. + $slug = self::gutenberg_get_slug_from_attr( $duotone_attr ); + + if ( $slug && $slug !== $duotone_attr ) { + self::$global_styles_block_names[ $block_node['name'] ] = $slug; + } + } + } + + /** + * Take the inline CSS duotone variable from a block and return the slug. Handles styles slugs like: + * var:preset|duotone|default-filter + * var(--wp--preset--duotone--blue-orange) + * + * @param string $duotone_attr The duotone attribute from a block. + * @return string The slug of the duotone preset or an empty string if no slug is found. + */ + static function gutenberg_get_slug_from_attr( $duotone_attr ) { + // Uses Branch Reset Groups `(?|…)` to return one capture group. + preg_match( '/(?|var:preset\|duotone\|(\S+)|var\(--wp--preset--duotone--(\S+)\))/', $duotone_attr, $matches ); + + return ! empty( $matches[1] ) ? $matches[1] : ''; + } + + /** + * Check if we have a valid duotone preset. + * + * @param string $duotone_attr The duotone attribute from a block. + * @return bool True if the duotone preset present and valid. + */ + static function is_preset( $duotone_attr ) { + $slug = WP_Duotone::gutenberg_get_slug_from_attr( $duotone_attr ); + + return array_key_exists( $slug, WP_Duotone::$global_styles_presets ); + } +} + +add_action( 'wp_loaded', array( 'WP_Duotone', 'set_global_styles_presets' ), 10 ); +add_action( 'wp_loaded', array( 'WP_Duotone', 'set_global_style_block_names' ), 10 ); diff --git a/lib/compat/wordpress-6.2/script-loader.php b/lib/compat/wordpress-6.2/script-loader.php index 388aa15b030d01..876d14902fdcb2 100644 --- a/lib/compat/wordpress-6.2/script-loader.php +++ b/lib/compat/wordpress-6.2/script-loader.php @@ -185,7 +185,7 @@ function gutenberg_enqueue_global_styles_custom_css() { $custom_css = wp_get_custom_css(); $custom_css .= gutenberg_get_global_styles_custom_css(); - + if ( ! empty( $custom_css ) ) { wp_add_inline_style( 'global-styles', $custom_css ); } @@ -194,4 +194,4 @@ function gutenberg_enqueue_global_styles_custom_css() { remove_action( 'wp_body_open', 'wp_global_styles_render_svg_filters' ); -remove_action( 'in_admin_header', 'wp_global_styles_render_svg_filters' ); \ No newline at end of file +remove_action( 'in_admin_header', 'wp_global_styles_render_svg_filters' ); diff --git a/lib/load.php b/lib/load.php index 03406015834eaa..8cc362c5abba7f 100644 --- a/lib/load.php +++ b/lib/load.php @@ -130,6 +130,7 @@ function gutenberg_is_experiment_enabled( $name ) { // Plugin specific code. require __DIR__ . '/class-wp-theme-json-gutenberg.php'; require __DIR__ . '/class-wp-theme-json-resolver-gutenberg.php'; +require __DIR__ . '/class-wp-duotone.php'; require __DIR__ . '/blocks.php'; require __DIR__ . '/client-assets.php'; require __DIR__ . '/demo.php'; diff --git a/phpunit/block-supports/duotone-test.php b/phpunit/block-supports/duotone-test.php index f28f57a59a8941..306ad977fba5db 100644 --- a/phpunit/block-supports/duotone-test.php +++ b/phpunit/block-supports/duotone-test.php @@ -39,15 +39,15 @@ public function test_gutenberg_render_duotone_support_custom() { public function data_gutenberg_get_slug_from_attr() { return array( - 'pipe-slug' => array( 'var:preset|duotone|blue-orange', 'blue-orange' ), - 'css-var' => array( 'var(--wp--preset--duotone--blue-orange)', 'blue-orange' ), - 'css-var-weird-chars' => array( 'var(--wp--preset--duotone--.)', '.' ), - 'css-var-missing-end-parenthesis' => array( 'var(--wp--preset--duotone--blue-orange', '' ), - 'invalid' => array( 'not a valid attribute', '' ), - 'css-var-no-value' => array( 'var(--wp--preset--duotone--)', '' ), - 'pipe-slug-no-value' => array( 'var:preset|duotone|', '' ), - 'css-var-spaces' => array( 'var(--wp--preset--duotone-- ', '' ), - 'pipe-slug-spaces' => array( 'var:preset|duotone| ', '' ), + 'pipe-slug' => array( 'var:preset|duotone|blue-orange', 'blue-orange' ), + 'css-var' => array( 'var(--wp--preset--duotone--blue-orange)', 'blue-orange' ), + 'css-var-weird-chars' => array( 'var(--wp--preset--duotone--.)', '.' ), + 'css-var-missing-end-parenthesis' => array( 'var(--wp--preset--duotone--blue-orange', '' ), + 'invalid' => array( 'not a valid attribute', '' ), + 'css-var-no-value' => array( 'var(--wp--preset--duotone--)', '' ), + 'pipe-slug-no-value' => array( 'var:preset|duotone|', '' ), + 'css-var-spaces' => array( 'var(--wp--preset--duotone-- ', '' ), + 'pipe-slug-spaces' => array( 'var:preset|duotone| ', '' ), ); } @@ -60,11 +60,11 @@ public function test_gutenberg_get_slug_from_attr( $data_attr, $expected ) { public function data_is_preset() { return array( - 'pipe-slug' => array( 'var:preset|duotone|blue-orange', true ), - 'css-var' => array( 'var(--wp--preset--duotone--blue-orange)', true ), - 'css-var-weird-chars' => array( 'var(--wp--preset--duotone--.)', false ), - 'css-var-missing-end-parenthesis' => array( 'var(--wp--preset--duotone--blue-orange', false ), - 'invalid' => array( 'not a valid attribute', false ), + 'pipe-slug' => array( 'var:preset|duotone|blue-orange', true ), + 'css-var' => array( 'var(--wp--preset--duotone--blue-orange)', true ), + 'css-var-weird-chars' => array( 'var(--wp--preset--duotone--.)', false ), + 'css-var-missing-end-parenthesis' => array( 'var(--wp--preset--duotone--blue-orange', false ), + 'invalid' => array( 'not a valid attribute', false ), ); } From 99faa181acec1fb474a8123cd5b947d62eedfa14 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Wed, 15 Mar 2023 11:42:15 -0500 Subject: [PATCH 25/55] Remove unnecessary methods from theme json class There was some duotone specific code within the theme json class that was only used to build a css declaration for duotone css output. It is now handled manually for speed and simplicity. --- lib/block-supports/duotone.php | 9 ++----- lib/class-wp-duotone.php | 27 +++++++++++++++++++++ lib/class-wp-theme-json-gutenberg.php | 35 --------------------------- 3 files changed, 29 insertions(+), 42 deletions(-) diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php index afb521f5ea73eb..7a3469583fae9a 100644 --- a/lib/block-supports/duotone.php +++ b/lib/block-supports/duotone.php @@ -548,7 +548,6 @@ static function () { foreach ( WP_Duotone::$output as $filter_data ) { - $filter_property = gutenberg_get_duotone_filter_property( $filter_data ); // SVG will be output on the page later. $filter_svg = gutenberg_get_duotone_filter_svg( $filter_data ); @@ -556,8 +555,7 @@ static function () { // This is for classic themes - in block themes, the CSS is added in the head via the value_func. if ( ! wp_is_block_theme() ) { - $duotone_preset_css_var = WP_Theme_JSON_Gutenberg::get_preset_css_var( array( 'color', 'duotone' ), $filter_data['slug'] ); - wp_add_inline_style( 'core-block-supports', 'body{' . $duotone_preset_css_var . ' :' . $filter_property . ';}' ); + wp_add_inline_style( 'core-block-supports', 'body{' . WP_Duotone::get_css_declaration( $filter_data ) . '}' ); } global $is_safari; @@ -586,10 +584,7 @@ static function() { continue; } - $filter_property = gutenberg_get_duotone_filter_property( $filter_data ); - - $duotone_preset_css_var = WP_Theme_JSON_Gutenberg::get_preset_css_var( array( 'color', 'duotone' ), $filter_data['slug'] ); - $duotone_css_vars .= $duotone_preset_css_var . ': ' . $filter_property . ';'; + $duotone_css_vars .= WP_Duotone::get_css_declaration( $filter_data ); } if ( ! empty( $duotone_css_vars ) ) { diff --git a/lib/class-wp-duotone.php b/lib/class-wp-duotone.php index 8f15efbecf0ad3..3d342fe9c2aaa9 100644 --- a/lib/class-wp-duotone.php +++ b/lib/class-wp-duotone.php @@ -68,6 +68,9 @@ class WP_Duotone { */ static $output = array(); + + const CSS_VAR_PREFIX = '--wp--preset--duotone--'; + /** * Get all possible duotone presets from global and theme styles and store as slug => [ colors array ] * We only want to process this one time. On block render we'll access and output only the needed presets for that page. @@ -144,6 +147,30 @@ static function is_preset( $duotone_attr ) { return array_key_exists( $slug, WP_Duotone::$global_styles_presets ); } + + /** + * Get the CSS variable name for a duotone preset. + * + * @param string $slug The slug of the duotone preset. + * @return string The CSS variable name. + */ + static function get_css_var( $slug ) { + return self::CSS_VAR_PREFIX . $slug; + } + + /** + * Get the CSS declaration for a duotone preset. + * Example: --wp--preset--duotone--blue-orange: url('#wp-duotone-blue-orange'); + * + * @param array $filter_data The duotone data for presets and custom filters. + * @return string The CSS declaration. + */ + static function get_css_declaration( $filter_data ) { + $filter_property = gutenberg_get_duotone_filter_property( $filter_data ); + $duotone_preset_css_var = WP_Duotone::get_css_var( $filter_data['slug'] ); + return $duotone_preset_css_var . ': ' . $filter_property . ';'; + } + } add_action( 'wp_loaded', array( 'WP_Duotone', 'set_global_styles_presets' ), 10 ); diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index 3d8c6b32f132f8..a65fffe331701b 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -3480,39 +3480,4 @@ public function set_spacing_sizes() { _wp_array_set( $this->theme_json, array( 'settings', 'spacing', 'spacingSizes', 'default' ), $spacing_sizes ); } - - /** - * Returns the CSS variable for a preset. - * - * @since 6.3.0 - * - * @param array $path Path to the preset. - * @param string $slug Slug of the preset. - * @return string CSS variable. - */ - public static function get_preset_css_var( $path, $slug ) { - $duotone_preset_metadata = static::get_preset_metadata_from_path( $path ); - return static::replace_slug_in_string( $duotone_preset_metadata['css_vars'], $slug ); - } - - /** - * Returns the metadata for a preset. - * - * @since 6.3.0 - * - * @param array $path Path to the preset. - * @return array Preset metadata. - */ - static function get_preset_metadata_from_path( $path ) { - $preset_metadata = array_filter( - static::PRESETS_METADATA, - function( $preset ) use ( &$path ) { - if ( $preset['path'] === $path ) { - return $preset; - } - } - ); - - return reset( $preset_metadata ); - } } From f599e585ccebbd2c92cc4b4256832f7c435b988f Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Wed, 15 Mar 2023 11:56:54 -0500 Subject: [PATCH 26/55] Renamed get_css_var to get_css_custom_property name and added get_css_var to be more accurately named Also used these functions throughout duotone.php to refactor for simplicity/consistency. Renamed some declaration variables as well to be more accurately named. --- lib/block-supports/duotone.php | 12 ++++++------ lib/class-wp-duotone.php | 12 ++++++++---- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php index 7a3469583fae9a..21d1f3c7e7998e 100644 --- a/lib/block-supports/duotone.php +++ b/lib/block-supports/duotone.php @@ -467,7 +467,7 @@ function gutenberg_render_duotone_support( $block_content, $block ) { $slug = WP_Duotone::gutenberg_get_slug_from_attr( $duotone_attr ); // Utilize existing preset CSS custom property. - $filter_property = "var(--wp--preset--duotone--$slug)"; + $declaration_value = WP_Duotone::get_css_var( $slug ); WP_Duotone::$output[ $slug ] = WP_Duotone::$global_styles_presets[ $slug ]; @@ -476,7 +476,7 @@ function gutenberg_render_duotone_support( $block_content, $block ) { $slug = wp_unique_id( sanitize_key( $duotone_attr . '-' ) ); // Pass through the CSS value. - $filter_property = $duotone_attr; + $declaration_value = $duotone_attr; } elseif ( $is_custom ) { // Build a unique slug for the filter based on the array of colors. $slug = wp_unique_id( sanitize_key( implode( '-', $duotone_attr ) . '-' ) ); @@ -486,7 +486,7 @@ function gutenberg_render_duotone_support( $block_content, $block ) { 'colors' => $duotone_attr, ); // Build a customized CSS filter property for unique slug. - $filter_property = gutenberg_get_duotone_filter_property( $filter_data ); + $declaration_value = gutenberg_get_duotone_filter_property( $filter_data ); WP_Duotone::$output[ $slug ] = $filter_data; } @@ -494,7 +494,7 @@ function gutenberg_render_duotone_support( $block_content, $block ) { $slug = WP_Duotone::$global_styles_block_names[ $block['blockName'] ]; // Utilize existing preset CSS custom property. - $filter_property = "var(--wp--preset--duotone--$slug)"; + $declaration_value = WP_Duotone::get_css_var( $slug ); WP_Duotone::$output[ $slug ] = WP_Duotone::$global_styles_presets[ $slug ]; } @@ -523,7 +523,7 @@ function gutenberg_render_duotone_support( $block_content, $block ) { // render before global styles, // and they should be overriding the duotone // filters set by global styles. - 'filter' => $filter_property . ' !important', + 'filter' => $declaration_value . ' !important', ), ), ), @@ -553,7 +553,7 @@ static function () { echo $filter_svg; - // This is for classic themes - in block themes, the CSS is added in the head via the value_func. + // This is for classic themes - in block themes, the CSS is added in the head via wp_add_inline_style in the wp_enqueue_scripts action. if ( ! wp_is_block_theme() ) { wp_add_inline_style( 'core-block-supports', 'body{' . WP_Duotone::get_css_declaration( $filter_data ) . '}' ); } diff --git a/lib/class-wp-duotone.php b/lib/class-wp-duotone.php index 3d342fe9c2aaa9..339cbd67d9dd15 100644 --- a/lib/class-wp-duotone.php +++ b/lib/class-wp-duotone.php @@ -154,10 +154,14 @@ static function is_preset( $duotone_attr ) { * @param string $slug The slug of the duotone preset. * @return string The CSS variable name. */ - static function get_css_var( $slug ) { + static function get_css_custom_property_name( $slug ) { return self::CSS_VAR_PREFIX . $slug; } + static function get_css_var( $slug ) { + return 'var(' . self::get_css_custom_property_name( $slug ) . ')'; + } + /** * Get the CSS declaration for a duotone preset. * Example: --wp--preset--duotone--blue-orange: url('#wp-duotone-blue-orange'); @@ -166,9 +170,9 @@ static function get_css_var( $slug ) { * @return string The CSS declaration. */ static function get_css_declaration( $filter_data ) { - $filter_property = gutenberg_get_duotone_filter_property( $filter_data ); - $duotone_preset_css_var = WP_Duotone::get_css_var( $filter_data['slug'] ); - return $duotone_preset_css_var . ': ' . $filter_property . ';'; + $declaration_value = gutenberg_get_duotone_filter_property( $filter_data ); + $duotone_preset_css_property_name = WP_Duotone::get_css_custom_property_name( $filter_data['slug'] ); + return $duotone_preset_css_property_name . ': ' . $declaration_value . ';'; } } From 31da41380cd89f9eb25cd19897ba4408caa6eda0 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Wed, 15 Mar 2023 12:06:26 -0500 Subject: [PATCH 27/55] Renamed get_css_declaration to get_css_custom_property_declaration Added a few comments for accuracy --- lib/block-supports/duotone.php | 11 ++++++++--- lib/class-wp-duotone.php | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php index 21d1f3c7e7998e..13c78312f1e26d 100644 --- a/lib/block-supports/duotone.php +++ b/lib/block-supports/duotone.php @@ -542,6 +542,10 @@ function gutenberg_render_duotone_support( $block_content, $block ) { } + +/** + * Outputs all necessary SVG for duotone filters and CSS for classic themes. + */ add_action( 'wp_footer', static function () { @@ -554,8 +558,9 @@ static function () { echo $filter_svg; // This is for classic themes - in block themes, the CSS is added in the head via wp_add_inline_style in the wp_enqueue_scripts action. + if ( ! wp_is_block_theme() ) { - wp_add_inline_style( 'core-block-supports', 'body{' . WP_Duotone::get_css_declaration( $filter_data ) . '}' ); + wp_add_inline_style( 'core-block-supports', 'body{' . WP_Duotone::get_css_custom_property_declaration( $filter_data ) . '}' ); } global $is_safari; @@ -567,7 +572,7 @@ static function () { ); /** - * Appends the used duotone fitler CSS Vars to the inline global styles CSS + * Appends the used global style duotone filter CSS Vars to the inline global styles CSS */ add_action( 'wp_enqueue_scripts', @@ -584,7 +589,7 @@ static function() { continue; } - $duotone_css_vars .= WP_Duotone::get_css_declaration( $filter_data ); + $duotone_css_vars .= WP_Duotone::get_css_custom_property_declaration( $filter_data ); } if ( ! empty( $duotone_css_vars ) ) { diff --git a/lib/class-wp-duotone.php b/lib/class-wp-duotone.php index 339cbd67d9dd15..285bdb4ef3d7dc 100644 --- a/lib/class-wp-duotone.php +++ b/lib/class-wp-duotone.php @@ -169,7 +169,7 @@ static function get_css_var( $slug ) { * @param array $filter_data The duotone data for presets and custom filters. * @return string The CSS declaration. */ - static function get_css_declaration( $filter_data ) { + static function get_css_custom_property_declaration( $filter_data ) { $declaration_value = gutenberg_get_duotone_filter_property( $filter_data ); $duotone_preset_css_property_name = WP_Duotone::get_css_custom_property_name( $filter_data['slug'] ); return $duotone_preset_css_property_name . ': ' . $declaration_value . ';'; From a656518e6960dd6edaded13fbba747bf404a1907 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Wed, 15 Mar 2023 12:15:17 -0500 Subject: [PATCH 28/55] Rename WP_Duotone to WP_Duotone_Gutenberg to match gutenberg coding styles --- lib/block-supports/duotone.php | 34 +++++++++---------- ...one.php => class-wp-duotone-gutenberg.php} | 16 ++++----- lib/load.php | 2 +- phpunit/block-supports/duotone-test.php | 4 +-- 4 files changed, 28 insertions(+), 28 deletions(-) rename lib/{class-wp-duotone.php => class-wp-duotone-gutenberg.php} (90%) diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php index 13c78312f1e26d..5a3585734463b7 100644 --- a/lib/block-supports/duotone.php +++ b/lib/block-supports/duotone.php @@ -438,7 +438,7 @@ function gutenberg_render_duotone_support( $block_content, $block ) { // The block should have a duotone attribute or have duotone defined in its theme.json to be processed. $has_duotone_attribute = isset( $block['attrs']['style']['color']['duotone'] ); - $has_global_styles_duotone = array_key_exists( $block['blockName'], WP_Duotone::$global_styles_block_names ); + $has_global_styles_duotone = array_key_exists( $block['blockName'], WP_Duotone_Gutenberg::$global_styles_block_names ); if ( empty( $block_content ) || @@ -457,19 +457,19 @@ function gutenberg_render_duotone_support( $block_content, $block ) { // 3. A CSS string - e.g. 'unset' to remove globally applied duotone. $duotone_attr = $block['attrs']['style']['color']['duotone']; - $is_preset = is_string( $duotone_attr ) && WP_Duotone::is_preset( $duotone_attr ); + $is_preset = is_string( $duotone_attr ) && WP_Duotone_Gutenberg::is_preset( $duotone_attr ); $is_css = is_string( $duotone_attr ) && ! $is_preset; $is_custom = is_array( $duotone_attr ); if ( $is_preset ) { // Extract the slug from the preset variable string. - $slug = WP_Duotone::gutenberg_get_slug_from_attr( $duotone_attr ); + $slug = WP_Duotone_Gutenberg::gutenberg_get_slug_from_attr( $duotone_attr ); // Utilize existing preset CSS custom property. - $declaration_value = WP_Duotone::get_css_var( $slug ); + $declaration_value = WP_Duotone_Gutenberg::get_css_var( $slug ); - WP_Duotone::$output[ $slug ] = WP_Duotone::$global_styles_presets[ $slug ]; + WP_Duotone_Gutenberg::$output[ $slug ] = WP_Duotone_Gutenberg::$global_styles_presets[ $slug ]; } elseif ( $is_css ) { // Build a unique slug for the filter based on the CSS value. @@ -488,15 +488,15 @@ function gutenberg_render_duotone_support( $block_content, $block ) { // Build a customized CSS filter property for unique slug. $declaration_value = gutenberg_get_duotone_filter_property( $filter_data ); - WP_Duotone::$output[ $slug ] = $filter_data; + WP_Duotone_Gutenberg::$output[ $slug ] = $filter_data; } } elseif ( $has_global_styles_duotone ) { - $slug = WP_Duotone::$global_styles_block_names[ $block['blockName'] ]; + $slug = WP_Duotone_Gutenberg::$global_styles_block_names[ $block['blockName'] ]; // Utilize existing preset CSS custom property. - $declaration_value = WP_Duotone::get_css_var( $slug ); + $declaration_value = WP_Duotone_Gutenberg::get_css_var( $slug ); - WP_Duotone::$output[ $slug ] = WP_Duotone::$global_styles_presets[ $slug ]; + WP_Duotone_Gutenberg::$output[ $slug ] = WP_Duotone_Gutenberg::$global_styles_presets[ $slug ]; } // - Applied as a class attribute to the block wrapper. @@ -507,8 +507,8 @@ function gutenberg_render_duotone_support( $block_content, $block ) { $selector = WP_Theme_JSON_Gutenberg::scope_selector( '.' . $filter_id, $duotone_support ); // We only want to add the selector if we have it in the output already, essentially skipping 'unset'. - if ( array_key_exists( $slug, WP_Duotone::$output ) ) { - WP_Duotone::$output[ $slug ]['selector'] = $selector; + if ( array_key_exists( $slug, WP_Duotone_Gutenberg::$output ) ) { + WP_Duotone_Gutenberg::$output[ $slug ]['selector'] = $selector; } // Calling gutenberg_style_engine_get_stylesheet_from_css_rules ensures that @@ -550,7 +550,7 @@ function gutenberg_render_duotone_support( $block_content, $block ) { 'wp_footer', static function () { - foreach ( WP_Duotone::$output as $filter_data ) { + foreach ( WP_Duotone_Gutenberg::$output as $filter_data ) { // SVG will be output on the page later. $filter_svg = gutenberg_get_duotone_filter_svg( $filter_data ); @@ -560,7 +560,7 @@ static function () { // This is for classic themes - in block themes, the CSS is added in the head via wp_add_inline_style in the wp_enqueue_scripts action. if ( ! wp_is_block_theme() ) { - wp_add_inline_style( 'core-block-supports', 'body{' . WP_Duotone::get_css_custom_property_declaration( $filter_data ) . '}' ); + wp_add_inline_style( 'core-block-supports', 'body{' . WP_Duotone_Gutenberg::get_css_custom_property_declaration( $filter_data ) . '}' ); } global $is_safari; @@ -578,18 +578,18 @@ static function () { 'wp_enqueue_scripts', static function() { - if ( empty( WP_Duotone::$output ) ) { + if ( empty( WP_Duotone_Gutenberg::$output ) ) { return; } $duotone_css_vars = ''; - foreach ( WP_Duotone::$output as $filter_data ) { - if ( ! array_key_exists( $filter_data['slug'], WP_Duotone::$global_styles_presets ) ) { + foreach ( WP_Duotone_Gutenberg::$output as $filter_data ) { + if ( ! array_key_exists( $filter_data['slug'], WP_Duotone_Gutenberg::$global_styles_presets ) ) { continue; } - $duotone_css_vars .= WP_Duotone::get_css_custom_property_declaration( $filter_data ); + $duotone_css_vars .= WP_Duotone_Gutenberg::get_css_custom_property_declaration( $filter_data ); } if ( ! empty( $duotone_css_vars ) ) { diff --git a/lib/class-wp-duotone.php b/lib/class-wp-duotone-gutenberg.php similarity index 90% rename from lib/class-wp-duotone.php rename to lib/class-wp-duotone-gutenberg.php index 285bdb4ef3d7dc..07adafbdd1ef40 100644 --- a/lib/class-wp-duotone.php +++ b/lib/class-wp-duotone-gutenberg.php @@ -1,6 +1,6 @@ assertSame( $expected, WP_Duotone::gutenberg_get_slug_from_attr( $data_attr ) ); + $this->assertSame( $expected, WP_Duotone_Gutenberg::gutenberg_get_slug_from_attr( $data_attr ) ); } public function data_is_preset() { @@ -72,6 +72,6 @@ public function data_is_preset() { * @dataProvider data_is_preset */ public function test_is_preset( $data_attr, $expected ) { - $this->assertSame( $expected, WP_Duotone::is_preset( $data_attr ) ); + $this->assertSame( $expected, WP_Duotone_Gutenberg::is_preset( $data_attr ) ); } } From 2df2c5cc48ef9cfcfcfc35f350b96461f2cc341d Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Wed, 15 Mar 2023 13:54:24 -0500 Subject: [PATCH 29/55] Move safari rerender hack into WP_Duotone_Gutenberg --- lib/block-supports/duotone.php | 18 +----------------- lib/class-wp-duotone-gutenberg.php | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php index 5a3585734463b7..bed5d4bf2e15d3 100644 --- a/lib/block-supports/duotone.php +++ b/lib/block-supports/duotone.php @@ -565,7 +565,7 @@ static function () { global $is_safari; if ( $is_safari ) { - duotone_safari_rerender_hack( $filter_data['selector'] ); + WP_Duotone_Gutenberg::safari_rerender_hack( $filter_data['selector'] ); } } } @@ -599,22 +599,6 @@ static function() { 11 ); -/** - * Safari renders elements incorrectly on first paint when the SVG filter comes after the content that it is filtering, - * so we force a repaint with a WebKit hack which solves the issue. - * - * @param string $selector The selector to apply the hack for. - */ -function duotone_safari_rerender_hack( $selector ) { - /* - * Simply accessing el.offsetHeight flushes layout and style - * changes in WebKit without having to wait for setTimeout. - */ - printf( - '', - wp_json_encode( $selector ) - ); -} // Register the block support. WP_Block_Supports::get_instance()->register( diff --git a/lib/class-wp-duotone-gutenberg.php b/lib/class-wp-duotone-gutenberg.php index 07adafbdd1ef40..5da8caaba474d2 100644 --- a/lib/class-wp-duotone-gutenberg.php +++ b/lib/class-wp-duotone-gutenberg.php @@ -175,6 +175,24 @@ static function get_css_custom_property_declaration( $filter_data ) { return $duotone_preset_css_property_name . ': ' . $declaration_value . ';'; } + /** + * Safari renders elements incorrectly on first paint when the SVG filter comes after the content that it is filtering, + * so we force a repaint with a WebKit hack which solves the issue. + * + * @param string $selector The selector to apply the hack for. + * @return string The ', + wp_json_encode( $selector ) + ); + } + } add_action( 'wp_loaded', array( 'WP_Duotone_Gutenberg', 'set_global_styles_presets' ), 10 ); From 826cdc988afc4aae8f1fa04ba019624e69998a7b Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Wed, 15 Mar 2023 14:00:44 -0500 Subject: [PATCH 30/55] Move footer action to output SVG into WP_Duotone_Gutenberg. The footer action that output all the footer resources was fully dependent on the WP_Duotone_Gutenberg class, so we should let it handle this action. --- lib/block-supports/duotone.php | 30 ------------------------------ lib/class-wp-duotone-gutenberg.php | 23 +++++++++++++++++++++++ 2 files changed, 23 insertions(+), 30 deletions(-) diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php index bed5d4bf2e15d3..867676b5505d56 100644 --- a/lib/block-supports/duotone.php +++ b/lib/block-supports/duotone.php @@ -541,36 +541,6 @@ function gutenberg_render_duotone_support( $block_content, $block ) { ); } - - -/** - * Outputs all necessary SVG for duotone filters and CSS for classic themes. - */ -add_action( - 'wp_footer', - static function () { - - foreach ( WP_Duotone_Gutenberg::$output as $filter_data ) { - - // SVG will be output on the page later. - $filter_svg = gutenberg_get_duotone_filter_svg( $filter_data ); - - echo $filter_svg; - - // This is for classic themes - in block themes, the CSS is added in the head via wp_add_inline_style in the wp_enqueue_scripts action. - - if ( ! wp_is_block_theme() ) { - wp_add_inline_style( 'core-block-supports', 'body{' . WP_Duotone_Gutenberg::get_css_custom_property_declaration( $filter_data ) . '}' ); - } - - global $is_safari; - if ( $is_safari ) { - WP_Duotone_Gutenberg::safari_rerender_hack( $filter_data['selector'] ); - } - } - } -); - /** * Appends the used global style duotone filter CSS Vars to the inline global styles CSS */ diff --git a/lib/class-wp-duotone-gutenberg.php b/lib/class-wp-duotone-gutenberg.php index 5da8caaba474d2..418bd42758ab89 100644 --- a/lib/class-wp-duotone-gutenberg.php +++ b/lib/class-wp-duotone-gutenberg.php @@ -193,7 +193,30 @@ static function safari_rerender_hack( $selector ) { ); } + /** + * Outputs all necessary SVG for duotone filters, CSS for classic themes, and safari rerendering hack + */ + static function output_footer_assets() { + foreach ( WP_Duotone_Gutenberg::$output as $filter_data ) { + + // SVG will be output on the page later. + $filter_svg = gutenberg_get_duotone_filter_svg( $filter_data ); + + echo $filter_svg; + + // This is for classic themes - in block themes, the CSS is added in the head via wp_add_inline_style in the wp_enqueue_scripts action. + if ( ! wp_is_block_theme() ) { + wp_add_inline_style( 'core-block-supports', 'body{' . WP_Duotone_Gutenberg::get_css_custom_property_declaration( $filter_data ) . '}' ); + } + + global $is_safari; + if ( $is_safari ) { + WP_Duotone_Gutenberg::safari_rerender_hack( $filter_data['selector'] ); + } + } + } } add_action( 'wp_loaded', array( 'WP_Duotone_Gutenberg', 'set_global_styles_presets' ), 10 ); add_action( 'wp_loaded', array( 'WP_Duotone_Gutenberg', 'set_global_style_block_names' ), 10 ); +add_action( 'wp_footer', array( 'WP_Duotone_Gutenberg', 'output_footer_assets' ), 10 ); From 737b9cb7ee06ebe44a09748abaa8a1d6062916c7 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Wed, 15 Mar 2023 14:05:05 -0500 Subject: [PATCH 31/55] Move wp_enqueue_scripts action into WP_Duotone_Gutenberg class. This was fully reliant on the WP_Duotone_Gutenberg::$output, so let the class handle outputting these styles. --- lib/block-supports/duotone.php | 29 ----------------------------- lib/class-wp-duotone-gutenberg.php | 25 +++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 29 deletions(-) diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php index 867676b5505d56..366d3c287a7848 100644 --- a/lib/block-supports/duotone.php +++ b/lib/block-supports/duotone.php @@ -541,35 +541,6 @@ function gutenberg_render_duotone_support( $block_content, $block ) { ); } -/** - * Appends the used global style duotone filter CSS Vars to the inline global styles CSS - */ -add_action( - 'wp_enqueue_scripts', - static function() { - - if ( empty( WP_Duotone_Gutenberg::$output ) ) { - return; - } - - $duotone_css_vars = ''; - - foreach ( WP_Duotone_Gutenberg::$output as $filter_data ) { - if ( ! array_key_exists( $filter_data['slug'], WP_Duotone_Gutenberg::$global_styles_presets ) ) { - continue; - } - - $duotone_css_vars .= WP_Duotone_Gutenberg::get_css_custom_property_declaration( $filter_data ); - } - - if ( ! empty( $duotone_css_vars ) ) { - wp_add_inline_style( 'global-styles', 'body{' . $duotone_css_vars . '}' ); - } - }, - 11 -); - - // Register the block support. WP_Block_Supports::get_instance()->register( 'duotone', diff --git a/lib/class-wp-duotone-gutenberg.php b/lib/class-wp-duotone-gutenberg.php index 418bd42758ab89..86d5334b122272 100644 --- a/lib/class-wp-duotone-gutenberg.php +++ b/lib/class-wp-duotone-gutenberg.php @@ -215,8 +215,33 @@ static function output_footer_assets() { } } } + + /** + * Appends the used global style duotone filter CSS Vars to the inline global styles CSS + */ + static function output_global_styles() { + + if ( empty( WP_Duotone_Gutenberg::$output ) ) { + return; + } + + $duotone_css_vars = ''; + + foreach ( WP_Duotone_Gutenberg::$output as $filter_data ) { + if ( ! array_key_exists( $filter_data['slug'], WP_Duotone_Gutenberg::$global_styles_presets ) ) { + continue; + } + + $duotone_css_vars .= WP_Duotone_Gutenberg::get_css_custom_property_declaration( $filter_data ); + } + + if ( ! empty( $duotone_css_vars ) ) { + wp_add_inline_style( 'global-styles', 'body{' . $duotone_css_vars . '}' ); + } + } } add_action( 'wp_loaded', array( 'WP_Duotone_Gutenberg', 'set_global_styles_presets' ), 10 ); add_action( 'wp_loaded', array( 'WP_Duotone_Gutenberg', 'set_global_style_block_names' ), 10 ); add_action( 'wp_footer', array( 'WP_Duotone_Gutenberg', 'output_footer_assets' ), 10 ); +add_action( 'wp_enqueue_scripts', array( 'WP_Duotone_Gutenberg', 'output_global_styles' ), 11 ); From b18c1a419832543ebb63fe824735fec01c5f75c7 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Wed, 15 Mar 2023 14:18:44 -0500 Subject: [PATCH 32/55] Moved gutenberg_render_duotone_support into WP_Duotone_Gutenberg class. This was very reliant on that class and did the set-up to make it work, so moving it all in to encapsulate it better. --- lib/block-supports/duotone.php | 124 ----------------------- lib/class-wp-duotone-gutenberg.php | 125 +++++++++++++++++++++++- phpunit/block-supports/duotone-test.php | 6 +- 3 files changed, 127 insertions(+), 128 deletions(-) diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php index 366d3c287a7848..d8d14589093ab8 100644 --- a/lib/block-supports/duotone.php +++ b/lib/block-supports/duotone.php @@ -421,126 +421,6 @@ function gutenberg_register_duotone_support( $block_type ) { } } -/** - * Render out the duotone stylesheet and SVG. - * - * @param string $block_content Rendered block content. - * @param array $block Block object. - * @return string Filtered block content. - */ -function gutenberg_render_duotone_support( $block_content, $block ) { - $block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] ); - - $duotone_support = false; - if ( $block_type && property_exists( $block_type, 'supports' ) ) { - $duotone_support = _wp_array_get( $block_type->supports, array( 'color', '__experimentalDuotone' ), false ); - } - - // The block should have a duotone attribute or have duotone defined in its theme.json to be processed. - $has_duotone_attribute = isset( $block['attrs']['style']['color']['duotone'] ); - $has_global_styles_duotone = array_key_exists( $block['blockName'], WP_Duotone_Gutenberg::$global_styles_block_names ); - - if ( - empty( $block_content ) || - ! $duotone_support || - ( ! $has_duotone_attribute && ! $has_global_styles_duotone ) - ) { - return $block_content; - } - - // Generate the pieces needed for rendering a duotone to the page. - if ( $has_duotone_attribute ) { - - // Possible values for duotone attribute: - // 1. Array of colors - e.g. array('#000000', '#ffffff'). - // 2. Variable for an existing Duotone preset - e.g. 'var:preset|duotone|green-blue' or 'var(--wp--preset--duotone--green-blue)'' - // 3. A CSS string - e.g. 'unset' to remove globally applied duotone. - - $duotone_attr = $block['attrs']['style']['color']['duotone']; - $is_preset = is_string( $duotone_attr ) && WP_Duotone_Gutenberg::is_preset( $duotone_attr ); - $is_css = is_string( $duotone_attr ) && ! $is_preset; - $is_custom = is_array( $duotone_attr ); - - if ( $is_preset ) { - - // Extract the slug from the preset variable string. - $slug = WP_Duotone_Gutenberg::gutenberg_get_slug_from_attr( $duotone_attr ); - - // Utilize existing preset CSS custom property. - $declaration_value = WP_Duotone_Gutenberg::get_css_var( $slug ); - - WP_Duotone_Gutenberg::$output[ $slug ] = WP_Duotone_Gutenberg::$global_styles_presets[ $slug ]; - - } elseif ( $is_css ) { - // Build a unique slug for the filter based on the CSS value. - $slug = wp_unique_id( sanitize_key( $duotone_attr . '-' ) ); - - // Pass through the CSS value. - $declaration_value = $duotone_attr; - } elseif ( $is_custom ) { - // Build a unique slug for the filter based on the array of colors. - $slug = wp_unique_id( sanitize_key( implode( '-', $duotone_attr ) . '-' ) ); - - $filter_data = array( - 'slug' => $slug, - 'colors' => $duotone_attr, - ); - // Build a customized CSS filter property for unique slug. - $declaration_value = gutenberg_get_duotone_filter_property( $filter_data ); - - WP_Duotone_Gutenberg::$output[ $slug ] = $filter_data; - } - } elseif ( $has_global_styles_duotone ) { - $slug = WP_Duotone_Gutenberg::$global_styles_block_names[ $block['blockName'] ]; - - // Utilize existing preset CSS custom property. - $declaration_value = WP_Duotone_Gutenberg::get_css_var( $slug ); - - WP_Duotone_Gutenberg::$output[ $slug ] = WP_Duotone_Gutenberg::$global_styles_presets[ $slug ]; - } - - // - Applied as a class attribute to the block wrapper. - // - Used as a selector to apply the filter to the block. - $filter_id = gutenberg_get_duotone_filter_id( array( 'slug' => $slug ) ); - - // Build the CSS selectors to which the filter will be applied. - $selector = WP_Theme_JSON_Gutenberg::scope_selector( '.' . $filter_id, $duotone_support ); - - // We only want to add the selector if we have it in the output already, essentially skipping 'unset'. - if ( array_key_exists( $slug, WP_Duotone_Gutenberg::$output ) ) { - WP_Duotone_Gutenberg::$output[ $slug ]['selector'] = $selector; - } - - // Calling gutenberg_style_engine_get_stylesheet_from_css_rules ensures that - // the styles are rendered in an inline for block supports because we're - // using the `context` option to instruct it so. - gutenberg_style_engine_get_stylesheet_from_css_rules( - array( - array( - 'selector' => $selector, - 'declarations' => array( - // !important is needed because these styles - // render before global styles, - // and they should be overriding the duotone - // filters set by global styles. - 'filter' => $declaration_value . ' !important', - ), - ), - ), - array( - 'context' => 'block-supports', - ) - ); - - // Like the layout hook, this assumes the hook only applies to blocks with a single wrapper. - return preg_replace( - '/' . preg_quote( 'class="', '/' ) . '/', - 'class="' . $filter_id . ' ', - $block_content, - 1 - ); -} - // Register the block support. WP_Block_Supports::get_instance()->register( 'duotone', @@ -548,7 +428,3 @@ function gutenberg_render_duotone_support( $block_content, $block ) { 'register_attribute' => 'gutenberg_register_duotone_support', ) ); - -// Remove WordPress core filter to avoid rendering duplicate support elements. -remove_filter( 'render_block', 'wp_render_duotone_support', 10, 2 ); -add_filter( 'render_block', 'gutenberg_render_duotone_support', 10, 2 ); diff --git a/lib/class-wp-duotone-gutenberg.php b/lib/class-wp-duotone-gutenberg.php index 86d5334b122272..822a0fb078f6a8 100644 --- a/lib/class-wp-duotone-gutenberg.php +++ b/lib/class-wp-duotone-gutenberg.php @@ -239,9 +239,132 @@ static function output_global_styles() { wp_add_inline_style( 'global-styles', 'body{' . $duotone_css_vars . '}' ); } } + + /** + * Render out the duotone stylesheet and SVG. + * + * @param string $block_content Rendered block content. + * @param array $block Block object. + * @return string Filtered block content. + */ + static function render_duotone_support( $block_content, $block ) { + $block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] ); + + $duotone_support = false; + if ( $block_type && property_exists( $block_type, 'supports' ) ) { + $duotone_support = _wp_array_get( $block_type->supports, array( 'color', '__experimentalDuotone' ), false ); + } + + // The block should have a duotone attribute or have duotone defined in its theme.json to be processed. + $has_duotone_attribute = isset( $block['attrs']['style']['color']['duotone'] ); + $has_global_styles_duotone = array_key_exists( $block['blockName'], WP_Duotone_Gutenberg::$global_styles_block_names ); + + if ( + empty( $block_content ) || + ! $duotone_support || + ( ! $has_duotone_attribute && ! $has_global_styles_duotone ) + ) { + return $block_content; + } + + // Generate the pieces needed for rendering a duotone to the page. + if ( $has_duotone_attribute ) { + + // Possible values for duotone attribute: + // 1. Array of colors - e.g. array('#000000', '#ffffff'). + // 2. Variable for an existing Duotone preset - e.g. 'var:preset|duotone|green-blue' or 'var(--wp--preset--duotone--green-blue)'' + // 3. A CSS string - e.g. 'unset' to remove globally applied duotone. + + $duotone_attr = $block['attrs']['style']['color']['duotone']; + $is_preset = is_string( $duotone_attr ) && WP_Duotone_Gutenberg::is_preset( $duotone_attr ); + $is_css = is_string( $duotone_attr ) && ! $is_preset; + $is_custom = is_array( $duotone_attr ); + + if ( $is_preset ) { + + // Extract the slug from the preset variable string. + $slug = WP_Duotone_Gutenberg::gutenberg_get_slug_from_attr( $duotone_attr ); + + // Utilize existing preset CSS custom property. + $declaration_value = WP_Duotone_Gutenberg::get_css_var( $slug ); + + WP_Duotone_Gutenberg::$output[ $slug ] = WP_Duotone_Gutenberg::$global_styles_presets[ $slug ]; + + } elseif ( $is_css ) { + // Build a unique slug for the filter based on the CSS value. + $slug = wp_unique_id( sanitize_key( $duotone_attr . '-' ) ); + + // Pass through the CSS value. + $declaration_value = $duotone_attr; + } elseif ( $is_custom ) { + // Build a unique slug for the filter based on the array of colors. + $slug = wp_unique_id( sanitize_key( implode( '-', $duotone_attr ) . '-' ) ); + + $filter_data = array( + 'slug' => $slug, + 'colors' => $duotone_attr, + ); + // Build a customized CSS filter property for unique slug. + $declaration_value = gutenberg_get_duotone_filter_property( $filter_data ); + + WP_Duotone_Gutenberg::$output[ $slug ] = $filter_data; + } + } elseif ( $has_global_styles_duotone ) { + $slug = WP_Duotone_Gutenberg::$global_styles_block_names[ $block['blockName'] ]; + + // Utilize existing preset CSS custom property. + $declaration_value = WP_Duotone_Gutenberg::get_css_var( $slug ); + + WP_Duotone_Gutenberg::$output[ $slug ] = WP_Duotone_Gutenberg::$global_styles_presets[ $slug ]; + } + + // - Applied as a class attribute to the block wrapper. + // - Used as a selector to apply the filter to the block. + $filter_id = gutenberg_get_duotone_filter_id( array( 'slug' => $slug ) ); + + // Build the CSS selectors to which the filter will be applied. + $selector = WP_Theme_JSON_Gutenberg::scope_selector( '.' . $filter_id, $duotone_support ); + + // We only want to add the selector if we have it in the output already, essentially skipping 'unset'. + if ( array_key_exists( $slug, WP_Duotone_Gutenberg::$output ) ) { + WP_Duotone_Gutenberg::$output[ $slug ]['selector'] = $selector; + } + + // Calling gutenberg_style_engine_get_stylesheet_from_css_rules ensures that + // the styles are rendered in an inline for block supports because we're + // using the `context` option to instruct it so. + gutenberg_style_engine_get_stylesheet_from_css_rules( + array( + array( + 'selector' => $selector, + 'declarations' => array( + // !important is needed because these styles + // render before global styles, + // and they should be overriding the duotone + // filters set by global styles. + 'filter' => $declaration_value . ' !important', + ), + ), + ), + array( + 'context' => 'block-supports', + ) + ); + + // Like the layout hook, this assumes the hook only applies to blocks with a single wrapper. + return preg_replace( + '/' . preg_quote( 'class="', '/' ) . '/', + 'class="' . $filter_id . ' ', + $block_content, + 1 + ); + } } add_action( 'wp_loaded', array( 'WP_Duotone_Gutenberg', 'set_global_styles_presets' ), 10 ); add_action( 'wp_loaded', array( 'WP_Duotone_Gutenberg', 'set_global_style_block_names' ), 10 ); -add_action( 'wp_footer', array( 'WP_Duotone_Gutenberg', 'output_footer_assets' ), 10 ); +// Remove WordPress core filter to avoid rendering duplicate support elements. +remove_filter( 'render_block', 'wp_render_duotone_support', 10, 2 ); +add_filter( 'render_block', array( 'WP_Duotone_Gutenberg', 'render_duotone_support' ), 10, 2 ); add_action( 'wp_enqueue_scripts', array( 'WP_Duotone_Gutenberg', 'output_global_styles' ), 11 ); +add_action( 'wp_footer', array( 'WP_Duotone_Gutenberg', 'output_footer_assets' ), 10 ); diff --git a/phpunit/block-supports/duotone-test.php b/phpunit/block-supports/duotone-test.php index 17b6d0ce1b9538..0aa603e32e44a1 100644 --- a/phpunit/block-supports/duotone-test.php +++ b/phpunit/block-supports/duotone-test.php @@ -14,7 +14,7 @@ public function test_gutenberg_render_duotone_support_preset() { ); $block_content = '
'; $expected = '
'; - $this->assertSame( $expected, gutenberg_render_duotone_support( $block_content, $block ) ); + $this->assertSame( $expected, WP_Duotone_Gutenberg::render_duotone_support( $block_content, $block ) ); } public function test_gutenberg_render_duotone_support_css() { @@ -24,7 +24,7 @@ public function test_gutenberg_render_duotone_support_css() { ); $block_content = '
'; $expected = '/
<\\/figure>/'; - $this->assertMatchesRegularExpression( $expected, gutenberg_render_duotone_support( $block_content, $block ) ); + $this->assertMatchesRegularExpression( $expected, WP_Duotone_Gutenberg::render_duotone_support( $block_content, $block ) ); } public function test_gutenberg_render_duotone_support_custom() { @@ -34,7 +34,7 @@ public function test_gutenberg_render_duotone_support_custom() { ); $block_content = '
'; $expected = '/
<\\/figure>/'; - $this->assertMatchesRegularExpression( $expected, gutenberg_render_duotone_support( $block_content, $block ) ); + $this->assertMatchesRegularExpression( $expected, WP_Duotone_Gutenberg::render_duotone_support( $block_content, $block ) ); } public function data_gutenberg_get_slug_from_attr() { From 3a885b3b8e5f8a4fdb20ddbc6a67d450e61ee4c4 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Wed, 15 Mar 2023 14:26:48 -0500 Subject: [PATCH 33/55] Move scrip-loader modifications to 6.3 release --- lib/compat/wordpress-6.2/script-loader.php | 4 ---- lib/compat/wordpress-6.3/script-loader.php | 15 +++++++++++++++ lib/load.php | 1 + 3 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 lib/compat/wordpress-6.3/script-loader.php diff --git a/lib/compat/wordpress-6.2/script-loader.php b/lib/compat/wordpress-6.2/script-loader.php index 876d14902fdcb2..149a6a18e14507 100644 --- a/lib/compat/wordpress-6.2/script-loader.php +++ b/lib/compat/wordpress-6.2/script-loader.php @@ -191,7 +191,3 @@ function gutenberg_enqueue_global_styles_custom_css() { } } add_action( 'wp_enqueue_scripts', 'gutenberg_enqueue_global_styles_custom_css' ); - - -remove_action( 'wp_body_open', 'wp_global_styles_render_svg_filters' ); -remove_action( 'in_admin_header', 'wp_global_styles_render_svg_filters' ); diff --git a/lib/compat/wordpress-6.3/script-loader.php b/lib/compat/wordpress-6.3/script-loader.php new file mode 100644 index 00000000000000..484f2b85fef18b --- /dev/null +++ b/lib/compat/wordpress-6.3/script-loader.php @@ -0,0 +1,15 @@ + Date: Wed, 15 Mar 2023 14:30:26 -0500 Subject: [PATCH 34/55] Set WP_Duotone_Gutenberg static variables private --- lib/class-wp-duotone-gutenberg.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/class-wp-duotone-gutenberg.php b/lib/class-wp-duotone-gutenberg.php index 822a0fb078f6a8..31ae175b0d5082 100644 --- a/lib/class-wp-duotone-gutenberg.php +++ b/lib/class-wp-duotone-gutenberg.php @@ -29,7 +29,7 @@ class WP_Duotone_Gutenberg { * @since 6.3.0 * @var array */ - static $global_styles_presets = array(); + static private $global_styles_presets = array(); /** * An array of block names from global, theme, and custom styles that have duotone presets. We'll use this to quickly @@ -44,7 +44,7 @@ class WP_Duotone_Gutenberg { * @since 6.3.0 * @var array */ - static $global_styles_block_names = array(); + static private $global_styles_block_names = array(); /** * An array of Duotone SVG and CSS ouput needed for the frontend duotone rendering based on what is @@ -66,7 +66,7 @@ class WP_Duotone_Gutenberg { * @since 6.3.0 * @var array */ - static $output = array(); + static private $output = array(); const CSS_VAR_PREFIX = '--wp--preset--duotone--'; From 19739f3a14bc576fb0b31a7893547942a945c8b3 Mon Sep 17 00:00:00 2001 From: Jerry Jones Date: Wed, 15 Mar 2023 14:37:56 -0500 Subject: [PATCH 35/55] Linting and comments --- lib/class-wp-duotone-gutenberg.php | 7 ++++++- lib/compat/wordpress-6.3/script-loader.php | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/class-wp-duotone-gutenberg.php b/lib/class-wp-duotone-gutenberg.php index 31ae175b0d5082..b02b4c39badee3 100644 --- a/lib/class-wp-duotone-gutenberg.php +++ b/lib/class-wp-duotone-gutenberg.php @@ -158,6 +158,12 @@ static function get_css_custom_property_name( $slug ) { return self::CSS_VAR_PREFIX . $slug; } + /** + * Get the CSS variable for a duotone preset. + * + * @param string $slug The slug of the duotone preset. + * @return string The CSS variable. + */ static function get_css_var( $slug ) { return 'var(' . self::get_css_custom_property_name( $slug ) . ')'; } @@ -180,7 +186,6 @@ static function get_css_custom_property_declaration( $filter_data ) { * so we force a repaint with a WebKit hack which solves the issue. * * @param string $selector The selector to apply the hack for. - * @return string The