Skip to content

Commit

Permalink
Duotone: Make it possible to define duotone settings in theme.json
Browse files Browse the repository at this point in the history
  • Loading branch information
scruffian committed Aug 30, 2021
1 parent 098bd96 commit 2553492
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 62 deletions.
175 changes: 117 additions & 58 deletions lib/block-supports/duotone.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 <style> tag.
*/
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 = array(
'r' => 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;
}

$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 );

function gutenberg_get_dutone_style( $selectors_group, $duotone_id ) {
ob_start();

?>

<style>
<?php echo $selectors_group; ?> {
filter: url( <?php echo esc_url( '#' . $duotone_id ); ?> );
}
</style>
<?php
$duotone_style = ob_get_clean();
return $duotone_style;
}

/**
* Returns the markup for duotone filters.
*
* @param string $duotone_id
* @param array $duotone_values
* @return string The markup for the <svg> tag.
*/
function gutenberg_get_dutone_svg_filters( $duotone_id, $duotone_values ) {
ob_start();
?>

<svg
xmlns:xlink="http://www.w3.org/1999/xlink"
Expand Down Expand Up @@ -340,8 +311,91 @@ function ( $selector ) use ( $duotone_id ) {
</svg>

<?php
$duotone_svg = ob_get_clean();
return $duotone_svg;
}

$duotone = ob_get_clean();
/**
* Get Duotone colors from array.
*
* @param array $duotone_colors The array of colors that define the duotone style.
* @return array The array of values mapped to rgb.
*/
function get_duotone_color_values( $duotone_colors ) {
$duotone_values = array(
'r' => 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(
Expand All @@ -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;
}

Expand All @@ -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' );
18 changes: 18 additions & 0 deletions lib/class-wp-theme-json-gutenberg.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class WP_Theme_JSON_Gutenberg {
),
'color' => array(
'background' => null,
'duotone' => null,
'gradient' => null,
'text' => null,
),
Expand Down Expand Up @@ -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',
Expand Down Expand Up @@ -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' ),
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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,
Expand Down
7 changes: 4 additions & 3 deletions lib/global-styles.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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 {
Expand Down
3 changes: 2 additions & 1 deletion packages/block-library/src/image/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@
},
"__experimentalBorder": {
"radius": true
}
},
"__experimentalSelector": ".wp-block-image img"
},
"styles": [
{
Expand Down

0 comments on commit 2553492

Please sign in to comment.