From db3b1928c65adfae18f3752a67ca10c529ef74e8 Mon Sep 17 00:00:00 2001 From: Ben Dwyer Date: Fri, 13 Aug 2021 15:14:39 +0100 Subject: [PATCH 01/16] Duotone: Make it possible to define duotone settings in theme.json --- lib/block-supports/duotone.php | 175 +++++++++++++------- lib/class-wp-theme-json-gutenberg.php | 18 ++ lib/global-styles.php | 7 +- packages/block-library/src/image/block.json | 3 +- 4 files changed, 141 insertions(+), 62 deletions(-) diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php index 5869d521b2d380..bd0606be0dc53c 100644 --- a/lib/block-supports/duotone.php +++ b/lib/block-supports/duotone.php @@ -251,64 +251,35 @@ function gutenberg_register_duotone_support( $block_type ) { } /** - * Render out the duotone stylesheet and SVG. + * Returns the markup for duotone style tag. * - * @param string $block_content Rendered block content. - * @param array $block Block object. - * @return string Filtered block content. + * @param string $selectors_group The selector to target. + * @param string $duotone_id The ID of the SVG filter. + * @return string The markup for the + tag. + */ +function gutenberg_get_dutone_svg_filters( $duotone_id, $duotone_values ) { + ob_start(); + ?> array(), + 'g' => array(), + 'b' => array(), + ); + foreach ( $duotone_colors as $color_str ) { + $color = gutenberg_tinycolor_string_to_rgb( $color_str ); + + $duotone_values['r'][] = $color['r'] / 255; + $duotone_values['g'][] = $color['g'] / 255; + $duotone_values['b'][] = $color['b'] / 255; + } + + return $duotone_values; +} + +/** + * Output Duotone markup in the footer. + * + * @param $duotone_markup The markup for the SVG filer, and if necessary the style tag. + */ +function gutenberg_output_duotone_markup( $duotone_markup ) { + add_action( + // Ideally we should use wp_head, but SVG defs can't be put in there. + 'wp_footer', + function () use ( $duotone_markup ) { + echo $duotone_markup; + } + ); +} + +/** + * 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 ); + } + + $has_duotone_attribute = isset( $block['attrs']['style']['color']['duotone'] ); + + if ( + ! $duotone_support || + ! $has_duotone_attribute + ) { + return $block_content; + } + + $duotone_colors = $block['attrs']['style']['color']['duotone']; + + $duotone_values = get_duotone_color_values( $duotone_colors ); + + $duotone_id = 'wp-duotone-filter-' . uniqid(); + + $selectors = explode( ',', $duotone_support ); + $selectors_scoped = array_map( + function ( $selector ) use ( $duotone_id ) { + return '.' . $duotone_id . ' ' . trim( $selector ); + }, + $selectors + ); + $selectors_group = implode( ', ', $selectors_scoped ); + + $duotone_markup = gutenberg_get_dutone_style( $selectors_group, $duotone_id ); + $duotone_markup .= gutenberg_get_dutone_svg_filters( $duotone_id, $duotone_values ); + + gutenberg_output_duotone_markup( $duotone_markup ); // Like the layout hook, this assumes the hook only applies to blocks with a single wrapper. $content = preg_replace( @@ -351,14 +405,6 @@ function ( $selector ) use ( $duotone_id ) { 1 ); - add_action( - // Ideally we should use wp_head, but SVG defs can't be put in there. - 'wp_footer', - function () use ( $duotone ) { - echo $duotone; - } - ); - return $content; } @@ -373,3 +419,16 @@ function () use ( $duotone ) { // 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 ); + +function gutenberg_render_duotone_filters_from_theme_json( $theme_json) { + $theme_json_settings = $theme_json->get_settings(); + if( ! empty( $theme_json_settings['color'] ) && ! empty( $theme_json_settings['color']['duotone'] ) && ! empty( $theme_json_settings['color']['duotone']['theme'] ) ) { + foreach( $theme_json_settings['color']['duotone']['theme'] as $duotone_setting ) { + $duotone_values = get_duotone_color_values( $duotone_setting['colors'] ); + $duotone_id = 'wp-duotone-filter-' . $duotone_setting['slug']; + $duotone_markup = gutenberg_get_dutone_svg_filters( $duotone_id, $duotone_values ); + gutenberg_output_duotone_markup( $duotone_markup ); + } + } +} +add_action( 'gutenberg_experimental_global_styles', 'gutenberg_render_duotone_filters_from_theme_json' ); diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index cf713529b4f70d..34df3005d399e8 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -57,6 +57,7 @@ class WP_Theme_JSON_Gutenberg { ), 'color' => array( 'background' => null, + 'duotone' => null, 'gradient' => null, 'text' => null, ), @@ -181,6 +182,18 @@ class WP_Theme_JSON_Gutenberg { ), ), ), + array( + 'path' => array( 'color', 'duotone' ), + 'value_key' => 'slug', + 'css_var_infix' => 'duotone', + 'value_wrapper' => 'url(#wp-duotone-filter-$s)', + 'classes' => array( + array( + 'class_suffix' => 'duotone', + 'property_name' => 'filter', + ), + ), + ), array( 'path' => array( 'typography', 'fontSizes' ), 'value_key' => 'size', @@ -218,6 +231,7 @@ class WP_Theme_JSON_Gutenberg { 'border-width' => array( 'border', 'width' ), 'border-style' => array( 'border', 'style' ), 'color' => array( 'color', 'text' ), + 'filter' => array( 'color', 'duotone' ), 'font-family' => array( 'typography', 'fontFamily' ), 'font-size' => array( 'typography', 'fontSize' ), 'font-style' => array( 'typography', 'fontStyle' ), @@ -609,6 +623,7 @@ private static function get_merged_preset_by_slug( $preset_per_origin, $value_ke $result[ preg_replace( '/\s+/', '-', $preset['slug'] ) ] = $preset[ $value_key ]; } } + return $result; } @@ -672,6 +687,9 @@ private static function compute_preset_vars( $settings ) { $preset_per_origin = _wp_array_get( $settings, $preset['path'], array() ); $preset_by_slug = self::get_merged_preset_by_slug( $preset_per_origin, $preset['value_key'] ); foreach ( $preset_by_slug as $slug => $value ) { + if ( ! empty( $preset['value_wrapper'] ) ) { + $value = str_replace( '$s', $value, $preset['value_wrapper'] ); + } $declarations[] = array( 'name' => '--wp--preset--' . $preset['css_var_infix'] . '--' . gutenberg_experimental_to_kebab_case( $slug ), 'value' => $value, diff --git a/lib/global-styles.php b/lib/global-styles.php index a749a66c40cf0d..6736c7b7367922 100644 --- a/lib/global-styles.php +++ b/lib/global-styles.php @@ -16,13 +16,13 @@ */ function gutenberg_experimental_global_styles_get_stylesheet( $tree, $type = 'all' ) { // Check if we can use cached. - $can_use_cached = ( + $can_use_cached = false; /*( ( 'all' === $type ) && ( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG ) && ( ! defined( 'SCRIPT_DEBUG' ) || ! SCRIPT_DEBUG ) && ( ! defined( 'REST_REQUEST' ) || ! REST_REQUEST ) && ! is_admin() - ); + );*/ if ( $can_use_cached ) { // Check if we have the styles already cached. @@ -56,12 +56,13 @@ function gutenberg_experimental_global_styles_enqueue_assets() { $settings = gutenberg_get_default_block_editor_settings(); $all = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data( $settings ); - $stylesheet = gutenberg_experimental_global_styles_get_stylesheet( $all ); if ( empty( $stylesheet ) ) { return; } + do_action( 'gutenberg_experimental_global_styles', $all ); + if ( isset( wp_styles()->registered['global-styles'] ) ) { wp_styles()->registered['global-styles']->extra['after'][0] = $stylesheet; } else { diff --git a/packages/block-library/src/image/block.json b/packages/block-library/src/image/block.json index 7aced7d40505e1..1d42c61932a548 100644 --- a/packages/block-library/src/image/block.json +++ b/packages/block-library/src/image/block.json @@ -84,7 +84,8 @@ }, "__experimentalBorder": { "radius": true - } + }, + "__experimentalSelector": ".wp-block-image img" }, "styles": [ { From d2813c70d0cdb0b436de1ee4738b2479e7ce87dc Mon Sep 17 00:00:00 2001 From: Ben Dwyer Date: Mon, 30 Aug 2021 14:57:10 +0100 Subject: [PATCH 02/16] Apply duotone in the editor --- lib/block-supports/duotone.php | 33 ++++++++++++++++------ lib/global-styles.php | 2 -- packages/block-editor/src/hooks/duotone.js | 2 +- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/lib/block-supports/duotone.php b/lib/block-supports/duotone.php index bd0606be0dc53c..1e2ba6743023d3 100644 --- a/lib/block-supports/duotone.php +++ b/lib/block-supports/duotone.php @@ -257,12 +257,13 @@ function gutenberg_register_duotone_support( $block_type ) { * @param string $duotone_id The ID of the SVG filter. * @return string The markup for the
+ onChange( 'unset' ) } + > + { __( 'Disable' ) } + + + onChange( undefined ) } + > + { __( 'Clear' ) } + +
} > { ! disableCustomColors && ! disableCustomDuotone && ( diff --git a/packages/components/src/duotone-picker/duotone-swatch.js b/packages/components/src/duotone-picker/duotone-swatch.js index 1ab35b53034c7d..7e89ef2cc58172 100644 --- a/packages/components/src/duotone-picker/duotone-swatch.js +++ b/packages/components/src/duotone-picker/duotone-swatch.js @@ -6,6 +6,10 @@ import Swatch from '../swatch'; import { getGradientFromCSSColors } from './utils'; function DuotoneSwatch( { values } ) { + if ( typeof values === 'string' ) { + return ; + } + return ( ( { position: ( i * 100 ) / ( colors.length - 1 ), color, From 7d0a0f206b1c3627150312a2f6fb32c7f78e43ef Mon Sep 17 00:00:00 2001 From: Ben Dwyer Date: Tue, 7 Sep 2021 10:21:14 +0100 Subject: [PATCH 15/16] formatting --- packages/block-editor/src/hooks/duotone.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/hooks/duotone.js b/packages/block-editor/src/hooks/duotone.js index 39495d3c4a4af3..031574a8f1319b 100644 --- a/packages/block-editor/src/hooks/duotone.js +++ b/packages/block-editor/src/hooks/duotone.js @@ -76,7 +76,9 @@ function DuotoneFilter( { selector, id, values } ) { filter: unset !important; /* We need !important to overide rules that come from theme.json.*/ } `; - return (