Skip to content

Commit

Permalink
Editor: Backport Duotone fixes for 5.9.1.
Browse files Browse the repository at this point in the history
This changeset is a backport for the following Gutenberg PRs:

- Fix duotone theme cache: WordPress/gutenberg#36236
- Fix duotone render in non-fse themes gutenberg: WordPress/gutenberg#37954
- Duotone: Allow users to specify custom filters gutenberg: WordPress/gutenberg#38442

Props oandregal, scruffian, Mamaduka.
Merges [52757] to the 5.9 branch.
See #55179.

Built from https://develop.svn.wordpress.org/branches/5.9@52759


git-svn-id: http://core.svn.wordpress.org/branches/5.9@52348 1a063a9b-81f0-0310-95a4-ce76da25c4cd
  • Loading branch information
audrasjb committed Feb 17, 2022
1 parent 0711ec9 commit affb772
Show file tree
Hide file tree
Showing 5 changed files with 197 additions and 40 deletions.
140 changes: 102 additions & 38 deletions wp-includes/block-supports/duotone.php
Original file line number Diff line number Diff line change
Expand Up @@ -352,55 +352,61 @@ function wp_tinycolor_string_to_rgb( $color_str ) {
}
}


/**
* Registers the style and colors block attributes for block types that support it.
* Returns the prefixed id for the duotone filter for use as a CSS id.
*
* @since 5.8.0
* @since 5.9.1
* @access private
*
* @param WP_Block_Type $block_type Block Type.
* @param array $preset Duotone preset value as seen in theme.json.
* @return string Duotone filter CSS id.
*/
function wp_register_duotone_support( $block_type ) {
$has_duotone_support = false;
if ( property_exists( $block_type, 'supports' ) ) {
$has_duotone_support = _wp_array_get( $block_type->supports, array( 'color', '__experimentalDuotone' ), false );
function wp_get_duotone_filter_id( $preset ) {
if ( ! isset( $preset['slug'] ) ) {
return '';
}

if ( $has_duotone_support ) {
if ( ! $block_type->attributes ) {
$block_type->attributes = array();
}

if ( ! array_key_exists( 'style', $block_type->attributes ) ) {
$block_type->attributes['style'] = array(
'type' => 'object',
);
}
}
return 'wp-duotone-' . $preset['slug'];
}

/**
* Renders the duotone filter SVG and returns the CSS filter property to
* reference the rendered SVG.
* Returns the CSS filter property url to reference the rendered SVG.
*
* @since 5.9.0
* @access private
*
* @param array $preset Duotone preset value as seen in theme.json.
* @return string Duotone CSS filter property url value.
*/
function wp_get_duotone_filter_property( $preset ) {
$filter_id = wp_get_duotone_filter_id( $preset );
return "url('#" . $filter_id . "')";
}

/**
* Returns the duotone filter SVG string for the preset.
*
* @since 5.9.1
* @access private
*
* @param array $preset Duotone preset value as seen in theme.json.
* @return string Duotone CSS filter property.
* @return string Duotone SVG filter.
*/
function wp_render_duotone_filter_preset( $preset ) {
$duotone_id = $preset['slug'];
$duotone_colors = $preset['colors'];
$filter_id = 'wp-duotone-' . $duotone_id;
function wp_get_duotone_filter_svg( $preset ) {
$filter_id = wp_get_duotone_filter_id( $preset );

$duotone_values = array(
'r' => array(),
'g' => array(),
'b' => array(),
'a' => array(),
);
foreach ( $duotone_colors as $color_str ) {

if ( ! isset( $preset['colors'] ) || ! is_array( $preset['colors'] ) ) {
$preset['colors'] = array();
}

foreach ( $preset['colors'] as $color_str ) {
$color = wp_tinycolor_string_to_rgb( $color_str );

$duotone_values['r'][] = $color['r'] / 255;
Expand Down Expand Up @@ -456,17 +462,34 @@ function wp_render_duotone_filter_preset( $preset ) {
$svg = trim( $svg );
}

add_action(
// Safari doesn't render SVG filters defined in data URIs,
// and SVG filters won't render in the head of a document,
// so the next best place to put the SVG is in the footer.
is_admin() ? 'admin_footer' : 'wp_footer',
function () use ( $svg ) {
echo $svg;
return $svg;
}

/**
* Registers the style and colors block attributes for block types that support it.
*
* @since 5.8.0
* @access private
*
* @param WP_Block_Type $block_type Block Type.
*/
function wp_register_duotone_support( $block_type ) {
$has_duotone_support = false;
if ( property_exists( $block_type, 'supports' ) ) {
$has_duotone_support = _wp_array_get( $block_type->supports, array( 'color', '__experimentalDuotone' ), false );
}

if ( $has_duotone_support ) {
if ( ! $block_type->attributes ) {
$block_type->attributes = array();
}
);

return "url('#" . $filter_id . "')";
if ( ! array_key_exists( 'style', $block_type->attributes ) ) {
$block_type->attributes['style'] = array(
'type' => 'object',
);
}
}
}

/**
Expand Down Expand Up @@ -500,8 +523,9 @@ function wp_render_duotone_support( $block_content, $block ) {
'slug' => uniqid(),
'colors' => $block['attrs']['style']['color']['duotone'],
);
$filter_property = wp_render_duotone_filter_preset( $filter_preset );
$filter_id = 'wp-duotone-' . $filter_preset['slug'];
$filter_property = wp_get_duotone_filter_property( $filter_preset );
$filter_id = wp_get_duotone_filter_id( $filter_preset );
$filter_svg = wp_get_duotone_filter_svg( $filter_preset );

$scope = '.' . $filter_id;
$selectors = explode( ',', $duotone_support );
Expand All @@ -521,6 +545,28 @@ function wp_render_duotone_support( $block_content, $block ) {
wp_add_inline_style( $filter_id, $filter_style );
wp_enqueue_style( $filter_id );

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 ) {
printf(
// Simply accessing el.offsetHeight flushes layout and style
// changes in WebKit without having to wait for setTimeout.
'<script>( function() { var el = document.querySelector( %s ); var display = el.style.display; el.style.display = "none"; el.offsetHeight; el.style.display = display; } )();</script>',
wp_json_encode( $selector )
);
}
}
);

// Like the layout hook, this assumes the hook only applies to blocks with a single wrapper.
return preg_replace(
'/' . preg_quote( 'class="', '/' ) . '/',
Expand All @@ -538,3 +584,21 @@ function wp_render_duotone_support( $block_content, $block ) {
)
);
add_filter( 'render_block', 'wp_render_duotone_support', 10, 2 );

/**
* 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 in the same location as those to satisfy
* Safari's rendering quirks.
*
* @since 5.9.1
*/
function wp_global_styles_render_svg_filters() {
$filters = wp_get_global_styles_svg_filters();
if ( ! empty( $filters ) ) {
echo $filters;
}
}
add_action( 'wp_body_open', 'wp_global_styles_render_svg_filters' );
36 changes: 35 additions & 1 deletion wp-includes/class-wp-theme-json.php
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ class WP_Theme_JSON {
'path' => array( 'color', 'duotone' ),
'override' => true,
'use_default_names' => false,
'value_func' => 'wp_render_duotone_filter_preset',
'value_func' => 'wp_get_duotone_filter_property',
'css_vars' => '--wp--preset--duotone--$slug',
'classes' => array(),
'properties' => array( 'filter' ),
Expand Down Expand Up @@ -1586,6 +1586,40 @@ public function merge( $incoming ) {
}
}

/**
* Converts all filter (duotone) presets into SVGs.
*
* @since 5.9.1
*
* @param array $origins List of origins to process.
* @return string SVG filters.
*/
public function get_svg_filters( $origins ) {
$blocks_metadata = static::get_blocks_metadata();
$setting_nodes = static::get_setting_nodes( $this->theme_json, $blocks_metadata );

foreach ( $setting_nodes as $metadata ) {
$node = _wp_array_get( $this->theme_json, $metadata['path'], array() );
if ( empty( $node['color']['duotone'] ) ) {
continue;
}

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

$filters = '';
foreach ( $origins as $origin ) {
if ( ! isset( $duotone_presets[ $origin ] ) ) {
continue;
}
foreach ( $duotone_presets[ $origin ] as $duotone_preset ) {
$filters .= wp_get_duotone_filter_svg( $duotone_preset );
}
}
}

return $filters;
}

/**
* Returns whether a presets should be overridden or not.
*
Expand Down
17 changes: 17 additions & 0 deletions wp-includes/deprecated.php
Original file line number Diff line number Diff line change
Expand Up @@ -4208,3 +4208,20 @@ function _excerpt_render_inner_columns_blocks( $columns, $allowed_blocks ) {
_deprecated_function( __FUNCTION__, '5.8.0', '_excerpt_render_inner_blocks()' );
return _excerpt_render_inner_blocks( $columns, $allowed_blocks );
}

/**
* Renders the duotone filter SVG and returns the CSS filter property to
* reference the rendered SVG.
*
* @since 5.9.0
* @deprecated 5.9.1 Use `wp_get_duotone_filter_property` introduced in 5.9.1.
*
* @see wp_get_duotone_filter_property()
*
* @param array $preset Duotone preset value as seen in theme.json.
* @return string Duotone CSS filter property.
*/
function wp_render_duotone_filter_preset( $preset ) {
_deprecated_function( __FUNCTION__, '5.9.1', 'wp_get_duotone_filter_property()' );
return wp_get_duotone_filter_property( $preset );
}
42 changes: 42 additions & 0 deletions wp-includes/global-styles-and-settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -150,3 +150,45 @@ function wp_get_global_stylesheet( $types = array() ) {

return $stylesheet;
}

/**
* Returns a string containing the SVGs to be referenced as filters (duotone).
*
* @since 5.9.1
*
* @return string
*/
function wp_get_global_styles_svg_filters() {
// Return cached value if it can be used and exists.
// It's cached by theme to make sure that theme switching clears the cache.
$can_use_cached = (
( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG ) &&
( ! defined( 'SCRIPT_DEBUG' ) || ! SCRIPT_DEBUG ) &&
( ! defined( 'REST_REQUEST' ) || ! REST_REQUEST ) &&
! is_admin()
);
$transient_name = 'global_styles_svg_filters_' . get_stylesheet();
if ( $can_use_cached ) {
$cached = get_transient( $transient_name );
if ( $cached ) {
return $cached;
}
}

$supports_theme_json = WP_Theme_JSON_Resolver::theme_has_support();

$origins = array( 'default', 'theme', 'custom' );
if ( ! $supports_theme_json ) {
$origins = array( 'default' );
}

$tree = WP_Theme_JSON_Resolver::get_merged_data();
$svgs = $tree->get_svg_filters( $origins );

if ( $can_use_cached ) {
// Cache for a minute, same as wp_get_global_stylesheet.
set_transient( $transient_name, $svgs, MINUTE_IN_SECONDS );
}

return $svgs;
}
2 changes: 1 addition & 1 deletion wp-includes/version.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
*
* @global string $wp_version
*/
$wp_version = '5.9.1-alpha-52758';
$wp_version = '5.9.1-alpha-52759';

/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
Expand Down

0 comments on commit affb772

Please sign in to comment.