WordPress Version: 6.1
/**
* Render out the duotone stylesheet and SVG.
*
* @since 5.8.0
* @since 6.1.0 Allow unset for preset colors.
* @access private
*
* @param string $block_content Rendered block content.
* @param array $block Block object.
* @return string Filtered block content.
*/
function wp_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;
}
$colors = $block['attrs']['style']['color']['duotone'];
$filter_key = is_array($colors) ? implode('-', $colors) : $colors;
$filter_preset = array('slug' => wp_unique_id(sanitize_key($filter_key . '-')), 'colors' => $colors);
$filter_property = wp_get_duotone_filter_property($filter_preset);
$filter_id = wp_get_duotone_filter_id($filter_preset);
$scope = '.' . $filter_id;
$selectors = explode(',', $duotone_support);
$scoped = array();
foreach ($selectors as $sel) {
$scoped[] = $scope . ' ' . trim($sel);
}
$selector = implode(', ', $scoped);
// !important is needed because these styles render before global styles,
// and they should be overriding the duotone filters set by global styles.
$filter_style = (defined('SCRIPT_DEBUG') && SCRIPT_DEBUG) ? $selector . " {\n\tfilter: " . $filter_property . " !important;\n}\n" : ($selector . '{filter:' . $filter_property . ' !important;}');
wp_register_style($filter_id, false, array(), true, true);
wp_add_inline_style($filter_id, $filter_style);
wp_enqueue_style($filter_id);
if ('unset' !== $colors) {
$filter_svg = wp_get_duotone_filter_svg($filter_preset);
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('<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="', '/') . '/', 'class="' . $filter_id . ' ', $block_content, 1);
}