Skip to content

Commit

Permalink
Fix default duotone preset SVG and style generation (#38681)
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex Lende authored Mar 9, 2022
1 parent 802adbd commit 848db70
Show file tree
Hide file tree
Showing 8 changed files with 221 additions and 173 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ Settings related to colors.
| custom | boolean | true | |
| customDuotone | boolean | true | |
| customGradient | boolean | true | |
| defaultDuotone | boolean | true | |
| defaultGradients | boolean | true | |
| defaultPalette | boolean | true | |
| duotone | array | | colors, name, slug |
Expand Down
208 changes: 117 additions & 91 deletions lib/compat/wordpress-5.9/class-wp-theme-json-5-9.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,79 +69,93 @@ class WP_Theme_JSON_5_9 {
*
* This contains the necessary metadata to process them:
*
* - path => where to find the preset within the settings section
* - override => whether a theme preset with the same slug as a default preset
* can override it
* - value_key => the key that represents the value
* - value_func => optionally, instead of value_key, a function to generate
* the value that takes a preset as an argument
* (either value_key or value_func should be present)
* - css_vars => template string to use in generating the CSS Custom Property.
* Example output: "--wp--preset--duotone--blue: <value>" will generate as many CSS Custom Properties as presets defined
* substituting the $slug for the slug's value for each preset value.
* - classes => array containing a structure with the classes to
* generate for the presets, where for each array item
* the key is the class name and the value the property name.
* The "$slug" substring will be replaced by the slug of each preset.
* For example:
* 'classes' => array(
* '.has-$slug-color' => 'color',
* '.has-$slug-background-color' => 'background-color',
* '.has-$slug-border-color' => 'border-color',
* )
* - properties => array of CSS properties to be used by kses to
* validate the content of each preset
* by means of the remove_insecure_properties method.
* - path => Where to find the preset within the settings section.
* - prevent_override => Whether a theme preset with the same slug as a default preset
* should not override it or the path to a setting for the same
* When defaults.
* The relationship between whether to override the defaults
* and whether the defaults are enabled is inverse:
* - If defaults are enabled => theme presets should not be overriden
* - If defaults are disabled => theme presets should be overriden
* For example, a theme sets defaultPalette to false,
* making the default palette hidden from the user.
* In that case, we want all the theme presets to be present,
* so they should override the defaults by setting this false.
* - value_key => the key that represents the value
* - value_func => optionally, instead of value_key, a function to generate
* the value that takes a preset as an argument
* (either value_key or value_func should be present)
* - css_vars => template string to use in generating the CSS Custom Property.
* Example output: "--wp--preset--duotone--blue: <value>" will generate as many CSS Custom Properties as presets defined
* substituting the $slug for the slug's value for each preset value.
* - classes => array containing a structure with the classes to
* generate for the presets, where for each array item
* the key is the class name and the value the property name.
* The "$slug" substring will be replaced by the slug of each preset.
* For example:
* 'classes' => array(
* '.has-$slug-color' => 'color',
* '.has-$slug-background-color' => 'background-color',
* '.has-$slug-border-color' => 'border-color',
* )
* - properties => array of CSS properties to be used by kses to
* validate the content of each preset
* by means of the remove_insecure_properties method.
*/
const PRESETS_METADATA = array(
array(
'path' => array( 'color', 'palette' ),
'override' => array( 'color', 'defaultPalette' ),
'use_default_names' => false,
'value_key' => 'color',
'css_vars' => '--wp--preset--color--$slug',
'classes' => array(
'path' => array( 'color', 'palette' ),
'prevent_override' => array( 'color', 'defaultPalette' ),
'use_default_presets' => array( 'color', 'defaultPalette' ),
'use_default_names' => false,
'value_key' => 'color',
'css_vars' => '--wp--preset--color--$slug',
'classes' => array(
'.has-$slug-color' => 'color',
'.has-$slug-background-color' => 'background-color',
'.has-$slug-border-color' => 'border-color',
),
'properties' => array( 'color', 'background-color', 'border-color' ),
'properties' => array( 'color', 'background-color', 'border-color' ),
),
array(
'path' => array( 'color', 'gradients' ),
'override' => array( 'color', 'defaultGradients' ),
'use_default_names' => false,
'value_key' => 'gradient',
'css_vars' => '--wp--preset--gradient--$slug',
'classes' => array( '.has-$slug-gradient-background' => 'background' ),
'properties' => array( 'background' ),
'path' => array( 'color', 'gradients' ),
'prevent_override' => array( 'color', 'defaultGradients' ),
'use_default_presets' => array( 'color', 'defaultGradients' ),
'use_default_names' => false,
'value_key' => 'gradient',
'css_vars' => '--wp--preset--gradient--$slug',
'classes' => array( '.has-$slug-gradient-background' => 'background' ),
'properties' => array( 'background' ),
),
array(
'path' => array( 'color', 'duotone' ),
'override' => true,
'use_default_names' => false,
'value_func' => 'gutenberg_get_duotone_filter_property',
'css_vars' => '--wp--preset--duotone--$slug',
'classes' => array(),
'properties' => array( 'filter' ),
'path' => array( 'color', 'duotone' ),
'prevent_override' => array( 'color', 'defaultDuotone' ),
'use_default_presets' => array( 'color', 'defaultDuotone' ),
'use_default_names' => false,
'value_func' => 'gutenberg_get_duotone_filter_property',
'css_vars' => '--wp--preset--duotone--$slug',
'classes' => array(),
'properties' => array( 'filter' ),
),
array(
'path' => array( 'typography', 'fontSizes' ),
'override' => true,
'use_default_names' => true,
'value_key' => 'size',
'css_vars' => '--wp--preset--font-size--$slug',
'classes' => array( '.has-$slug-font-size' => 'font-size' ),
'properties' => array( 'font-size' ),
'path' => array( 'typography', 'fontSizes' ),
'prevent_override' => false,
'use_default_presets' => true,
'use_default_names' => true,
'value_key' => 'size',
'css_vars' => '--wp--preset--font-size--$slug',
'classes' => array( '.has-$slug-font-size' => 'font-size' ),
'properties' => array( 'font-size' ),
),
array(
'path' => array( 'typography', 'fontFamilies' ),
'override' => true,
'use_default_names' => false,
'value_key' => 'fontFamily',
'css_vars' => '--wp--preset--font-family--$slug',
'classes' => array( '.has-$slug-font-family' => 'font-family' ),
'properties' => array( 'font-family' ),
'path' => array( 'typography', 'fontFamilies' ),
'prevent_override' => false,
'use_default_presets' => true,
'use_default_names' => false,
'value_key' => 'fontFamily',
'css_vars' => '--wp--preset--font-family--$slug',
'classes' => array( '.has-$slug-font-family' => 'font-family' ),
'properties' => array( 'font-family' ),
),
);

Expand Down Expand Up @@ -229,6 +243,7 @@ class WP_Theme_JSON_5_9 {
'custom' => null,
'customDuotone' => null,
'customGradient' => null,
'defaultDuotone' => null,
'defaultGradients' => null,
'defaultPalette' => null,
'duotone' => null,
Expand Down Expand Up @@ -1021,9 +1036,14 @@ protected static function scope_selector( $scope, $selector ) {
protected static function get_settings_values_by_slug( $settings, $preset_metadata, $origins ) {
$preset_per_origin = _wp_array_get( $settings, $preset_metadata['path'], array() );

$skip_default_presets = ! static::get_metadata_boolean( $settings, $preset_metadata['use_default_presets'], true );

$result = array();
foreach ( $origins as $origin ) {
if ( ! isset( $preset_per_origin[ $origin ] ) ) {
if (
! isset( $preset_per_origin[ $origin ] ) ||
( 'default' === $origin && $skip_default_presets )
) {
continue;
}
foreach ( $preset_per_origin[ $origin ] as $preset ) {
Expand Down Expand Up @@ -1065,9 +1085,14 @@ protected static function get_settings_slugs( $settings, $preset_metadata, $orig

$preset_per_origin = _wp_array_get( $settings, $preset_metadata['path'], array() );

$skip_default_presets = ! static::get_metadata_boolean( $settings, $preset_metadata['use_default_presets'], true );

$result = array();
foreach ( $origins as $origin ) {
if ( ! isset( $preset_per_origin[ $origin ] ) ) {
if (
! isset( $preset_per_origin[ $origin ] ) ||
( 'default' === $origin && $skip_default_presets )
) {
continue;
}
foreach ( $preset_per_origin[ $origin ] as $preset ) {
Expand Down Expand Up @@ -1470,7 +1495,7 @@ public function merge( $incoming ) {

// Replace the presets.
foreach ( static::PRESETS_METADATA as $preset ) {
$override_preset = static::should_override_preset( $this->theme_json, $node['path'], $preset['override'] );
$override_preset = ! static::get_metadata_boolean( $this->theme_json['settings'], $preset['prevent_override'], true );

foreach ( static::VALID_ORIGINS as $origin ) {
$base_path = array_merge( $node['path'], $preset['path'] );
Expand Down Expand Up @@ -1517,6 +1542,7 @@ public function get_svg_filters( $origins ) {
$blocks_metadata = static::get_blocks_metadata();
$setting_nodes = static::get_setting_nodes( $this->theme_json, $blocks_metadata );

$filters = '';
foreach ( $setting_nodes as $metadata ) {
$node = _wp_array_get( $this->theme_json, $metadata['path'], array() );
if ( empty( $node['color']['duotone'] ) ) {
Expand All @@ -1525,9 +1551,11 @@ public function get_svg_filters( $origins ) {

$duotone_presets = $node['color']['duotone'];

$filters = '';
foreach ( $origins as $origin ) {
if ( ! isset( $duotone_presets[ $origin ] ) ) {
if (
! isset( $duotone_presets[ $origin ] ) ||
( 'default' === $origin && false === $node['color']['defaultDuotone'] )
) {
continue;
}
foreach ( $duotone_presets[ $origin ] as $duotone_preset ) {
Expand All @@ -1540,42 +1568,40 @@ public function get_svg_filters( $origins ) {
}

/**
* Returns whether a presets should be overriden or not.
* For metadata values that can either be booleans or paths to booleans, gets the value.
*
* ```php
* $data = array(
* 'color' => array(
* 'defaultPalette' => true
* )
* );
*
* static::get_metadata_boolean( $data, false );
* // => false
*
* static::get_metadata_boolean( $data, array( 'color', 'defaultPalette' ) );
* // => true
* ```
*
* @param array $theme_json The theme.json like structure to inspect.
* @param array $path Path to inspect.
* @param bool|array $override Data to compute whether to override the preset.
* @param array $data The data to inspect.
* @param bool|array $path Boolean or path to a boolean.
* @param bool $default Default value if the referenced path is missing.
* @return boolean
*/
protected static function should_override_preset( $theme_json, $path, $override ) {
if ( is_bool( $override ) ) {
return $override;
protected static function get_metadata_boolean( $data, $path, $default = false ) {
if ( is_bool( $path ) ) {
return $path;
}

// The relationship between whether to override the defaults
// and whether the defaults are enabled is inverse:
//
// - If defaults are enabled => theme presets should not be overriden
// - If defaults are disabled => theme presets should be overriden
//
// For example, a theme sets defaultPalette to false,
// making the default palette hidden from the user.
// In that case, we want all the theme presets to be present,
// so they should override the defaults.
if ( is_array( $override ) ) {
$value = _wp_array_get( $theme_json, array_merge( $path, $override ) );
if ( is_array( $path ) ) {
$value = _wp_array_get( $data, $path );
if ( isset( $value ) ) {
return ! $value;
return $value;
}

// Search the top-level key if none was found for this node.
$value = _wp_array_get( $theme_json, array_merge( array( 'settings' ), $override ) );
if ( isset( $value ) ) {
return ! $value;
}

return true;
}

return $default;
}

/**
Expand Down
3 changes: 3 additions & 0 deletions lib/compat/wordpress-5.9/class-wp-theme-json-resolver-5-9.php
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,9 @@ public static function get_theme_data( $deprecated = array() ) {
$default_gradients = true;
}
$theme_support_data['settings']['color']['defaultGradients'] = $default_gradients;

// Classic themes without a theme.json don't support global duotone.
$theme_support_data['settings']['color']['defaultDuotone'] = false;
}
$with_theme_supports = new WP_Theme_JSON_Gutenberg( $theme_support_data );
$with_theme_supports->merge( static::$theme );
Expand Down
62 changes: 26 additions & 36 deletions lib/compat/wordpress-5.9/render-svg-filters.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,44 +5,34 @@
* @package gutenberg
*/

/*
* If wp_global_styles_render_svg_filters is defined, it means the plugin
* is running on WordPress 5.9.1, so don't need to render the global styles
* SVG filters as it was already done by WordPress core.
/**
* Render 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.
*/
if ( ! function_exists( 'wp_global_styles_render_svg_filters' ) ) {
/**
* Render 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.
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.
*/
function wp_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 = wp_get_global_styles_svg_filters();
if ( ! empty( $filters ) ) {
echo $filters;
}
if (
is_admin() &&
! get_current_screen()->is_block_editor()
) {
return;
}

add_action(
'wp_body_open',
'wp_global_styles_render_svg_filters'
);
add_action(
'in_admin_header',
'wp_global_styles_render_svg_filters'
);
$filters = gutenberg_get_global_styles_svg_filters();
if ( ! empty( $filters ) ) {
echo $filters;
}
}

// Override actions introduced in 5.9.1 if they exist.
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' );
Loading

0 comments on commit 848db70

Please sign in to comment.