Make WordPress Core

Changeset 56101

Timestamp:
06/29/2023 06:19:41 AM (17 months ago)
Author:
isabel_brison
Message:

Editor: update duotone support.

Updates duotone support after stabilisation of selectors API and adds a few small code quality and UI improvements.

Props onemaggie, peterwilsoncc, ajlende, audrasjb, mikeschroder, ramonopoly.
Fixes #58555.

Location:
trunk
Files:
2 added
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/block-supports/duotone.php

    r55988 r56101  
    3333 */
    3434
    35 /**
    36  * Takes input from [0, n] and returns it as [0, 1].
    37  *
    38  * Direct port of TinyColor's function, lightly simplified to maintain
    39  * consistency with TinyColor.
    40  *
    41  * @see https://github.com/bgrins/TinyColor
    42  *
    43  * @since 5.8.0
    44  * @access private
    45  *
    46  * @param mixed $n   Number of unknown type.
    47  * @param int   $max Upper value of the range to bound to.
    48  * @return float Value in the range [0, 1].
    49  */
    50 function wp_tinycolor_bound01( $n, $max ) {
    51     if ( 'string' === gettype( $n ) && str_contains( $n, '.' ) && 1 === (float) $n ) {
    52         $n = '100%';
    53     }
    54 
    55     $n = min( $max, max( 0, (float) $n ) );
    56 
    57     // Automatically convert percentage into number.
    58     if ( 'string' === gettype( $n ) && str_contains( $n, '%' ) ) {
    59         $n = (int) ( $n * $max ) / 100;
    60     }
    61 
    62     // Handle floating point rounding errors.
    63     if ( ( abs( $n - $max ) < 0.000001 ) ) {
    64         return 1.0;
    65     }
    66 
    67     // Convert into [0, 1] range if it isn't already.
    68     return ( $n % $max ) / (float) $max;
    69 }
    70 
    71 /**
    72  * Direct port of tinycolor's boundAlpha function to maintain consistency with
    73  * how tinycolor works.
    74  *
    75  * @see https://github.com/bgrins/TinyColor
    76  *
    77  * @since 5.9.0
    78  * @access private
    79  *
    80  * @param mixed $n Number of unknown type.
    81  * @return float Value in the range [0,1].
    82  */
    83 function _wp_tinycolor_bound_alpha( $n ) {
    84     if ( is_numeric( $n ) ) {
    85         $n = (float) $n;
    86         if ( $n >= 0 && $n <= 1 ) {
    87             return $n;
    88         }
    89     }
    90     return 1;
    91 }
    92 
    93 /**
    94  * Rounds and converts values of an RGB object.
    95  *
    96  * Direct port of TinyColor's function, lightly simplified to maintain
    97  * consistency with TinyColor.
    98  *
    99  * @see https://github.com/bgrins/TinyColor
    100  *
    101  * @since 5.8.0
    102  * @access private
    103  *
    104  * @param array $rgb_color RGB object.
    105  * @return array Rounded and converted RGB object.
    106  */
    107 function wp_tinycolor_rgb_to_rgb( $rgb_color ) {
    108     return array(
    109         'r' => wp_tinycolor_bound01( $rgb_color['r'], 255 ) * 255,
    110         'g' => wp_tinycolor_bound01( $rgb_color['g'], 255 ) * 255,
    111         'b' => wp_tinycolor_bound01( $rgb_color['b'], 255 ) * 255,
    112     );
    113 }
    114 
    115 /**
    116  * Helper function for hsl to rgb conversion.
    117  *
    118  * Direct port of TinyColor's function, lightly simplified to maintain
    119  * consistency with TinyColor.
    120  *
    121  * @see https://github.com/bgrins/TinyColor
    122  *
    123  * @since 5.8.0
    124  * @access private
    125  *
    126  * @param float $p first component.
    127  * @param float $q second component.
    128  * @param float $t third component.
    129  * @return float R, G, or B component.
    130  */
    131 function wp_tinycolor_hue_to_rgb( $p, $q, $t ) {
    132     if ( $t < 0 ) {
    133         ++$t;
    134     }
    135     if ( $t > 1 ) {
    136         --$t;
    137     }
    138     if ( $t < 1 / 6 ) {
    139         return $p + ( $q - $p ) * 6 * $t;
    140     }
    141     if ( $t < 1 / 2 ) {
    142         return $q;
    143     }
    144     if ( $t < 2 / 3 ) {
    145         return $p + ( $q - $p ) * ( 2 / 3 - $t ) * 6;
    146     }
    147     return $p;
    148 }
    149 
    150 /**
    151  * Converts an HSL object to an RGB object with converted and rounded values.
    152  *
    153  * Direct port of TinyColor's function, lightly simplified to maintain
    154  * consistency with TinyColor.
    155  *
    156  * @see https://github.com/bgrins/TinyColor
    157  *
    158  * @since 5.8.0
    159  * @access private
    160  *
    161  * @param array $hsl_color HSL object.
    162  * @return array Rounded and converted RGB object.
    163  */
    164 function wp_tinycolor_hsl_to_rgb( $hsl_color ) {
    165     $h = wp_tinycolor_bound01( $hsl_color['h'], 360 );
    166     $s = wp_tinycolor_bound01( $hsl_color['s'], 100 );
    167     $l = wp_tinycolor_bound01( $hsl_color['l'], 100 );
    168 
    169     if ( 0 === $s ) {
    170         // Achromatic.
    171         $r = $l;
    172         $g = $l;
    173         $b = $l;
    174     } else {
    175         $q = $l < 0.5 ? $l * ( 1 + $s ) : $l + $s - $l * $s;
    176         $p = 2 * $l - $q;
    177         $r = wp_tinycolor_hue_to_rgb( $p, $q, $h + 1 / 3 );
    178         $g = wp_tinycolor_hue_to_rgb( $p, $q, $h );
    179         $b = wp_tinycolor_hue_to_rgb( $p, $q, $h - 1 / 3 );
    180     }
    181 
    182     return array(
    183         'r' => $r * 255,
    184         'g' => $g * 255,
    185         'b' => $b * 255,
    186     );
    187 }
    188 
    189 /**
    190  * Parses hex, hsl, and rgb CSS strings using the same regex as TinyColor v1.4.2
    191  * used in the JavaScript. Only colors output from react-color are implemented.
    192  *
    193  * Direct port of TinyColor's function, lightly simplified to maintain
    194  * consistency with TinyColor.
    195  *
    196  * @see https://github.com/bgrins/TinyColor
    197  * @see https://github.com/casesandberg/react-color/
    198  *
    199  * @since 5.8.0
    200  * @since 5.9.0 Added alpha processing.
    201  * @access private
    202  *
    203  * @param string $color_str CSS color string.
    204  * @return array RGB object.
    205  */
    206 function wp_tinycolor_string_to_rgb( $color_str ) {
    207     $color_str = strtolower( trim( $color_str ) );
    208 
    209     $css_integer = '[-\\+]?\\d+%?';
    210     $css_number  = '[-\\+]?\\d*\\.\\d+%?';
    211 
    212     $css_unit = '(?:' . $css_number . ')|(?:' . $css_integer . ')';
    213 
    214     $permissive_match3 = '[\\s|\\(]+(' . $css_unit . ')[,|\\s]+(' . $css_unit . ')[,|\\s]+(' . $css_unit . ')\\s*\\)?';
    215     $permissive_match4 = '[\\s|\\(]+(' . $css_unit . ')[,|\\s]+(' . $css_unit . ')[,|\\s]+(' . $css_unit . ')[,|\\s]+(' . $css_unit . ')\\s*\\)?';
    216 
    217     $rgb_regexp = '/^rgb' . $permissive_match3 . '$/';
    218     if ( preg_match( $rgb_regexp, $color_str, $match ) ) {
    219         $rgb = wp_tinycolor_rgb_to_rgb(
    220             array(
    221                 'r' => $match[1],
    222                 'g' => $match[2],
    223                 'b' => $match[3],
    224             )
    225         );
    226 
    227         $rgb['a'] = 1;
    228 
    229         return $rgb;
    230     }
    231 
    232     $rgba_regexp = '/^rgba' . $permissive_match4 . '$/';
    233     if ( preg_match( $rgba_regexp, $color_str, $match ) ) {
    234         $rgb = wp_tinycolor_rgb_to_rgb(
    235             array(
    236                 'r' => $match[1],
    237                 'g' => $match[2],
    238                 'b' => $match[3],
    239             )
    240         );
    241 
    242         $rgb['a'] = _wp_tinycolor_bound_alpha( $match[4] );
    243 
    244         return $rgb;
    245     }
    246 
    247     $hsl_regexp = '/^hsl' . $permissive_match3 . '$/';
    248     if ( preg_match( $hsl_regexp, $color_str, $match ) ) {
    249         $rgb = wp_tinycolor_hsl_to_rgb(
    250             array(
    251                 'h' => $match[1],
    252                 's' => $match[2],
    253                 'l' => $match[3],
    254             )
    255         );
    256 
    257         $rgb['a'] = 1;
    258 
    259         return $rgb;
    260     }
    261 
    262     $hsla_regexp = '/^hsla' . $permissive_match4 . '$/';
    263     if ( preg_match( $hsla_regexp, $color_str, $match ) ) {
    264         $rgb = wp_tinycolor_hsl_to_rgb(
    265             array(
    266                 'h' => $match[1],
    267                 's' => $match[2],
    268                 'l' => $match[3],
    269             )
    270         );
    271 
    272         $rgb['a'] = _wp_tinycolor_bound_alpha( $match[4] );
    273 
    274         return $rgb;
    275     }
    276 
    277     $hex8_regexp = '/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/';
    278     if ( preg_match( $hex8_regexp, $color_str, $match ) ) {
    279         $rgb = wp_tinycolor_rgb_to_rgb(
    280             array(
    281                 'r' => base_convert( $match[1], 16, 10 ),
    282                 'g' => base_convert( $match[2], 16, 10 ),
    283                 'b' => base_convert( $match[3], 16, 10 ),
    284             )
    285         );
    286 
    287         $rgb['a'] = _wp_tinycolor_bound_alpha(
    288             base_convert( $match[4], 16, 10 ) / 255
    289         );
    290 
    291         return $rgb;
    292     }
    293 
    294     $hex6_regexp = '/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/';
    295     if ( preg_match( $hex6_regexp, $color_str, $match ) ) {
    296         $rgb = wp_tinycolor_rgb_to_rgb(
    297             array(
    298                 'r' => base_convert( $match[1], 16, 10 ),
    299                 'g' => base_convert( $match[2], 16, 10 ),
    300                 'b' => base_convert( $match[3], 16, 10 ),
    301             )
    302         );
    303 
    304         $rgb['a'] = 1;
    305 
    306         return $rgb;
    307     }
    308 
    309     $hex4_regexp = '/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/';
    310     if ( preg_match( $hex4_regexp, $color_str, $match ) ) {
    311         $rgb = wp_tinycolor_rgb_to_rgb(
    312             array(
    313                 'r' => base_convert( $match[1] . $match[1], 16, 10 ),
    314                 'g' => base_convert( $match[2] . $match[2], 16, 10 ),
    315                 'b' => base_convert( $match[3] . $match[3], 16, 10 ),
    316             )
    317         );
    318 
    319         $rgb['a'] = _wp_tinycolor_bound_alpha(
    320             base_convert( $match[4] . $match[4], 16, 10 ) / 255
    321         );
    322 
    323         return $rgb;
    324     }
    325 
    326     $hex3_regexp = '/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/';
    327     if ( preg_match( $hex3_regexp, $color_str, $match ) ) {
    328         $rgb = wp_tinycolor_rgb_to_rgb(
    329             array(
    330                 'r' => base_convert( $match[1] . $match[1], 16, 10 ),
    331                 'g' => base_convert( $match[2] . $match[2], 16, 10 ),
    332                 'b' => base_convert( $match[3] . $match[3], 16, 10 ),
    333             )
    334         );
    335 
    336         $rgb['a'] = 1;
    337 
    338         return $rgb;
    339     }
    340 
    341     /*
    342      * The JS color picker considers the string "transparent" to be a hex value,
    343      * so we need to handle it here as a special case.
    344      */
    345     if ( 'transparent' === $color_str ) {
    346         return array(
    347             'r' => 0,
    348             'g' => 0,
    349             'b' => 0,
    350             'a' => 0,
    351         );
    352     }
    353 }
    354 
    355 /**
    356  * Returns the prefixed id for the duotone filter for use as a CSS id.
    357  *
    358  * @since 5.9.1
    359  * @access private
    360  *
    361  * @param array $preset Duotone preset value as seen in theme.json.
    362  * @return string Duotone filter CSS id.
    363  */
    364 function wp_get_duotone_filter_id( $preset ) {
    365     if ( ! isset( $preset['slug'] ) ) {
    366         return '';
    367     }
    368 
    369     return 'wp-duotone-' . $preset['slug'];
    370 }
    371 
    372 /**
    373  * Returns the CSS filter property url to reference the rendered SVG.
    374  *
    375  * @since 5.9.0
    376  * @since 6.1.0 Allow unset for preset colors.
    377  * @access private
    378  *
    379  * @param array $preset Duotone preset value as seen in theme.json.
    380  * @return string Duotone CSS filter property url value.
    381  */
    382 function wp_get_duotone_filter_property( $preset ) {
    383     if ( isset( $preset['colors'] ) && 'unset' === $preset['colors'] ) {
    384         return 'none';
    385     }
    386     $filter_id = wp_get_duotone_filter_id( $preset );
    387     return "url('#" . $filter_id . "')";
    388 }
    389 
    390 /**
    391  * Returns the duotone filter SVG string for the preset.
    392  *
    393  * @since 5.9.1
    394  * @access private
    395  *
    396  * @param array $preset Duotone preset value as seen in theme.json.
    397  * @return string Duotone SVG filter.
    398  */
    399 function wp_get_duotone_filter_svg( $preset ) {
    400     $filter_id = wp_get_duotone_filter_id( $preset );
    401 
    402     $duotone_values = array(
    403         'r' => array(),
    404         'g' => array(),
    405         'b' => array(),
    406         'a' => array(),
    407     );
    408 
    409     if ( ! isset( $preset['colors'] ) || ! is_array( $preset['colors'] ) ) {
    410         $preset['colors'] = array();
    411     }
    412 
    413     foreach ( $preset['colors'] as $color_str ) {
    414         $color = wp_tinycolor_string_to_rgb( $color_str );
    415 
    416         $duotone_values['r'][] = $color['r'] / 255;
    417         $duotone_values['g'][] = $color['g'] / 255;
    418         $duotone_values['b'][] = $color['b'] / 255;
    419         $duotone_values['a'][] = $color['a'];
    420     }
    421 
    422     ob_start();
    423 
    424     ?>
    425 
    426     <svg
    427         xmlns="http://www.w3.org/2000/svg"
    428         viewBox="0 0 0 0"
    429         width="0"
    430         height="0"
    431         focusable="false"
    432         role="none"
    433         style="visibility: hidden; position: absolute; left: -9999px; overflow: hidden;"
    434     >
    435         <defs>
    436             <filter id="<?php echo esc_attr( $filter_id ); ?>">
    437                 <feColorMatrix
    438                     color-interpolation-filters="sRGB"
    439                     type="matrix"
    440                     values="
    441                         .299 .587 .114 0 0
    442                         .299 .587 .114 0 0
    443                         .299 .587 .114 0 0
    444                         .299 .587 .114 0 0
    445                     "
    446                 />
    447                 <feComponentTransfer color-interpolation-filters="sRGB" >
    448                     <feFuncR type="table" tableValues="<?php echo esc_attr( implode( ' ', $duotone_values['r'] ) ); ?>" />
    449                     <feFuncG type="table" tableValues="<?php echo esc_attr( implode( ' ', $duotone_values['g'] ) ); ?>" />
    450                     <feFuncB type="table" tableValues="<?php echo esc_attr( implode( ' ', $duotone_values['b'] ) ); ?>" />
    451                     <feFuncA type="table" tableValues="<?php echo esc_attr( implode( ' ', $duotone_values['a'] ) ); ?>" />
    452                 </feComponentTransfer>
    453                 <feComposite in2="SourceGraphic" operator="in" />
    454             </filter>
    455         </defs>
    456     </svg>
    457 
    458     <?php
    459 
    460     $svg = ob_get_clean();
    461 
    462     if ( ! SCRIPT_DEBUG ) {
    463         // Clean up the whitespace.
    464         $svg = preg_replace( "/[\r\n\t ]+/", ' ', $svg );
    465         $svg = str_replace( '> <', '><', $svg );
    466         $svg = trim( $svg );
    467     }
    468 
    469     return $svg;
    470 }
    471 
    472 /**
    473  * Registers the style and colors block attributes for block types that support it.
    474  *
    475  * @since 5.8.0
    476  * @access private
    477  *
    478  * @param WP_Block_Type $block_type Block Type.
    479  */
    480 function wp_register_duotone_support( $block_type ) {
    481     $has_duotone_support = false;
    482     if ( property_exists( $block_type, 'supports' ) ) {
    483         $has_duotone_support = _wp_array_get( $block_type->supports, array( 'color', '__experimentalDuotone' ), false );
    484     }
    485 
    486     if ( $has_duotone_support ) {
    487         if ( ! $block_type->attributes ) {
    488             $block_type->attributes = array();
    489         }
    490 
    491         if ( ! array_key_exists( 'style', $block_type->attributes ) ) {
    492             $block_type->attributes['style'] = array(
    493                 'type' => 'object',
    494             );
    495         }
    496     }
    497 }
    498 
    499 /**
    500  * Renders out the duotone stylesheet and SVG.
    501  *
    502  * @since 5.8.0
    503  * @since 6.1.0 Allow unset for preset colors.
    504  * @access private
    505  *
    506  * @param string $block_content Rendered block content.
    507  * @param array  $block         Block object.
    508  * @return string Filtered block content.
    509  */
    510 function wp_render_duotone_support( $block_content, $block ) {
    511     $block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
    512 
    513     $duotone_support = false;
    514     if ( $block_type && property_exists( $block_type, 'supports' ) ) {
    515         $duotone_support = _wp_array_get( $block_type->supports, array( 'color', '__experimentalDuotone' ), false );
    516     }
    517 
    518     $has_duotone_attribute = isset( $block['attrs']['style']['color']['duotone'] );
    519 
    520     if (
    521         ! $duotone_support ||
    522         ! $has_duotone_attribute
    523     ) {
    524         return $block_content;
    525     }
    526 
    527     $colors          = $block['attrs']['style']['color']['duotone'];
    528     $filter_key      = is_array( $colors ) ? implode( '-', $colors ) : $colors;
    529     $filter_preset   = array(
    530         'slug'   => wp_unique_id( sanitize_key( $filter_key . '-' ) ),
    531         'colors' => $colors,
    532     );
    533     $filter_property = wp_get_duotone_filter_property( $filter_preset );
    534     $filter_id       = wp_get_duotone_filter_id( $filter_preset );
    535 
    536     $scope     = '.' . $filter_id;
    537     $selectors = explode( ',', $duotone_support );
    538     $scoped    = array();
    539     foreach ( $selectors as $sel ) {
    540         $scoped[] = $scope . ' ' . trim( $sel );
    541     }
    542     $selector = implode( ', ', $scoped );
    543 
    544     // !important is needed because these styles render before global styles,
    545     // and they should be overriding the duotone filters set by global styles.
    546     $filter_style = SCRIPT_DEBUG
    547         ? $selector . " {\n\tfilter: " . $filter_property . " !important;\n}\n"
    548         : $selector . '{filter:' . $filter_property . ' !important;}';
    549 
    550     wp_register_style( $filter_id, false );
    551     wp_add_inline_style( $filter_id, $filter_style );
    552     wp_enqueue_style( $filter_id );
    553 
    554     if ( 'unset' !== $colors ) {
    555         $filter_svg = wp_get_duotone_filter_svg( $filter_preset );
    556         add_action(
    557             'wp_footer',
    558             static function () use ( $filter_svg, $selector ) {
    559                 echo $filter_svg;
    560 
    561                 /*
    562                  * Safari renders elements incorrectly on first paint when the
    563                  * SVG filter comes after the content that it is filtering, so
    564                  * we force a repaint with a WebKit hack which solves the issue.
    565                  */
    566                 global $is_safari;
    567                 if ( $is_safari ) {
    568                     /*
    569                      * Simply accessing el.offsetHeight flushes layout and style
    570                      * changes in WebKit without having to wait for setTimeout.
    571                      */
    572                     printf(
    573                         '<script>( function() { var el = document.querySelector( %s ); var display = el.style.display; el.style.display = "none"; el.offsetHeight; el.style.display = display; } )();</script>',
    574                         wp_json_encode( $selector )
    575                     );
    576                 }
    577             }
    578         );
    579     }
    580 
    581     // Like the layout hook, this assumes the hook only applies to blocks with a single wrapper.
    582     return preg_replace(
    583         '/' . preg_quote( 'class="', '/' ) . '/',
    584         'class="' . $filter_id . ' ',
    585         $block_content,
    586         1
    587     );
    588 }
    589 
    59035// Register the block support.
    59136WP_Block_Supports::get_instance()->register(
    59237    'duotone',
    59338    array(
    594         'register_attribute' => 'wp_register_duotone_support',
     39        'register_attribute' => ,
    59540    )
    59641);
    597 add_filter( 'render_block', 'wp_render_duotone_support', 10, 2 );
     42
     43// Set up metadata prior to rendering any blocks.
     44add_action( 'wp_loaded', array( 'WP_Duotone', 'set_global_styles_presets' ), 10 );
     45add_action( 'wp_loaded', array( 'WP_Duotone', 'set_global_style_block_names' ), 10 );
     46
     47// Add classnames to blocks using duotone support.
     48add_filter( 'render_block', array( 'WP_Duotone', 'render_duotone_support' ), 10, 2 );
     49
     50// Enqueue styles.
     51// Block styles (core-block-supports-inline-css) before the style engine (wp_enqueue_stored_styles).
     52// Global styles (global-styles-inline-css) after the other global styles (wp_enqueue_global_styles).
     53add_action( 'wp_enqueue_scripts', array( 'WP_Duotone', 'output_block_styles' ), 9 );
     54add_action( 'wp_enqueue_scripts', array( 'WP_Duotone', 'output_global_styles' ), 11 );
     55
     56// Add SVG filters to the footer. Also, for classic themes, output block styles (core-block-supports-inline-css).
     57add_action( 'wp_footer', array( 'WP_Duotone', 'output_footer_assets' ), 10 );
     58
     59// Add styles and SVGs for use in the editor via the EditorStyles component.
     60add_filter( 'block_editor_settings_all', array( 'WP_Duotone', 'add_editor_settings' ), 10 );
     61
     62// Migrate the old experimental duotone support flag.
     63add_filter( 'block_type_metadata_settings', array( 'WP_Duotone', 'migrate_experimental_duotone_support_flag' ), 10, 2 );
  • trunk/src/wp-includes/class-wp-theme-json.php

    r56083 r56101  
    115115     *              `prevent_override` value for `color.duotone` to use `color.defaultDuotone`.
    116116     * @since 6.2.0 Added 'shadow' presets.
     117
    117118     * @var array
    118119     */
     
    144145            'prevent_override'  => array( 'color', 'defaultDuotone' ),
    145146            'use_default_names' => false,
    146             'value_func'        => 'wp_get_duotone_filter_property',
    147             'css_vars'          => '--wp--preset--duotone--$slug',
     147            'value_func'        =>
     148            'css_vars'          => ,
    148149            'classes'           => array(),
    149150            'properties'        => array( 'filter' ),
  • trunk/src/wp-includes/default-filters.php

    r56030 r56101  
    607607add_action( 'wp_footer', 'wp_enqueue_stored_styles', 1 );
    608608
    609 // SVG filters like duotone have to be loaded at the beginning of the body in both admin and the front-end.
    610 add_action( 'wp_body_open', 'wp_global_styles_render_svg_filters' );
    611 add_action( 'in_admin_header', 'wp_global_styles_render_svg_filters' );
    612 
    613609add_action( 'wp_default_styles', 'wp_default_styles' );
    614610add_filter( 'style_loader_src', 'wp_style_loader_src', 10, 2 );
  • trunk/src/wp-includes/deprecated.php

    r56037 r56101  
    48054805    return $image;
    48064806}
     4807
     4808
     4809
     4810
     4811
     4812
     4813
     4814
     4815
     4816
     4817
     4818
     4819
     4820
     4821
     4822
     4823
     4824
     4825
     4826
     4827
     4828
     4829
     4830
     4831
     4832
     4833
     4834
     4835
     4836
     4837
     4838
     4839
     4840
     4841
     4842
     4843
     4844
     4845
     4846
     4847
     4848
     4849
     4850
     4851
     4852
     4853
     4854
     4855
     4856
     4857
     4858
     4859
     4860
     4861
     4862
     4863
     4864
     4865
     4866
     4867
     4868
     4869
     4870
     4871
     4872
     4873
     4874
     4875
     4876
     4877
     4878
     4879
     4880
     4881
     4882
     4883
     4884
     4885
     4886
     4887
     4888
     4889
     4890
     4891
     4892
     4893
     4894
     4895
     4896
     4897
     4898
     4899
     4900
     4901
     4902
     4903
     4904
     4905
     4906
     4907
     4908
     4909
     4910
     4911
     4912
     4913
     4914
     4915
     4916
     4917
     4918
     4919
     4920
     4921
     4922
     4923
     4924
     4925
     4926
     4927
     4928
     4929
     4930
     4931
     4932
     4933
     4934
     4935
     4936
     4937
     4938
     4939
     4940
     4941
     4942
     4943
     4944
     4945
     4946
     4947
     4948
     4949
     4950
     4951
     4952
     4953
     4954
     4955
     4956
     4957
     4958
     4959
     4960
     4961
     4962
     4963
     4964
     4965
     4966
     4967
     4968
     4969
     4970
     4971
     4972
     4973
     4974
     4975
     4976
     4977
     4978
     4979
     4980
     4981
     4982
     4983
     4984
     4985
     4986
     4987
     4988
     4989
     4990
     4991
     4992
     4993
     4994
     4995
     4996
     4997
     4998
     4999
     5000
     5001
     5002
     5003
     5004
     5005
     5006
     5007
     5008
     5009
     5010
     5011
     5012
     5013
     5014
     5015
     5016
     5017
     5018
     5019
     5020
     5021
     5022
     5023
     5024
     5025
     5026
     5027
     5028
     5029
     5030
     5031
     5032
     5033
     5034
     5035
     5036
     5037
     5038
     5039
     5040
     5041
     5042
     5043
     5044
     5045
     5046
     5047
     5048
     5049
     5050
     5051
     5052
     5053
     5054
     5055
     5056
     5057
     5058
     5059
     5060
     5061
     5062
     5063
     5064
     5065
     5066
     5067
     5068
     5069
     5070
     5071
     5072
     5073
     5074
     5075
     5076
     5077
     5078
     5079
     5080
     5081
     5082
     5083
     5084
     5085
     5086
     5087
     5088
     5089
     5090
     5091
     5092
     5093
     5094
     5095
     5096
     5097
     5098
     5099
     5100
     5101
     5102
     5103
     5104
     5105
     5106
     5107
     5108
     5109
     5110
     5111
     5112
     5113
     5114
     5115
     5116
     5117
     5118
     5119
     5120
     5121
     5122
     5123
     5124
     5125
     5126
     5127
     5128
     5129
     5130
     5131
     5132
     5133
     5134
     5135
     5136
     5137
     5138
     5139
     5140
     5141
     5142
     5143
     5144
     5145
     5146
     5147
     5148
     5149
     5150
     5151
     5152
     5153
     5154
     5155
     5156
     5157
     5158
     5159
     5160
     5161
     5162
     5163
     5164
     5165
     5166
     5167
     5168
     5169
     5170
     5171
     5172
     5173
     5174
     5175
     5176
     5177
     5178
     5179
     5180
     5181
     5182
     5183
     5184
     5185
     5186
     5187
     5188
     5189
     5190
     5191
     5192
     5193
     5194
     5195
     5196
     5197
     5198
     5199
     5200
     5201
     5202
     5203
     5204
     5205
     5206
     5207
     5208
     5209
     5210
     5211
     5212
     5213
     5214
     5215
     5216
     5217
     5218
     5219
     5220
     5221
     5222
     5223
     5224
     5225
     5226
     5227
     5228
     5229
     5230
     5231
     5232
     5233
     5234
     5235
     5236
     5237
     5238
     5239
     5240
     5241
     5242
     5243
     5244
     5245
     5246
     5247
     5248
     5249
     5250
     5251
     5252
     5253
     5254
     5255
     5256
     5257
     5258
     5259
     5260
     5261
     5262
     5263
     5264
     5265
     5266
     5267
     5268
     5269
     5270
     5271
     5272
     5273
     5274
     5275
     5276
     5277
     5278
     5279
     5280
     5281
     5282
     5283
     5284
     5285
     5286
     5287
     5288
     5289
     5290
     5291
     5292
     5293
     5294
     5295
     5296
     5297
     5298
     5299
     5300
     5301
     5302
     5303
     5304
  • trunk/src/wp-includes/global-styles-and-settings.php

    r56094 r56101  
    287287
    288288    return $stylesheet;
    289 }
    290 
    291 /**
    292  * Returns a string containing the SVGs to be referenced as filters (duotone).
    293  *
    294  * @since 5.9.1
    295  *
    296  * @return string
    297  */
    298 function wp_get_global_styles_svg_filters() {
    299     /*
    300      * Ignore cache when the development mode is set to 'theme', so it doesn't interfere with the theme
    301      * developer's workflow.
    302      */
    303     $can_use_cached = wp_get_development_mode() !== 'theme';
    304     $cache_group    = 'theme_json';
    305     $cache_key      = 'wp_get_global_styles_svg_filters';
    306     if ( $can_use_cached ) {
    307         $cached = wp_cache_get( $cache_key, $cache_group );
    308         if ( $cached ) {
    309             return $cached;
    310         }
    311     }
    312 
    313     $supports_theme_json = wp_theme_has_theme_json();
    314 
    315     $origins = array( 'default', 'theme', 'custom' );
    316     if ( ! $supports_theme_json ) {
    317         $origins = array( 'default' );
    318     }
    319 
    320     $tree = WP_Theme_JSON_Resolver::get_merged_data();
    321     $svgs = $tree->get_svg_filters( $origins );
    322 
    323     if ( $can_use_cached ) {
    324         wp_cache_set( $cache_key, $svgs, $cache_group );
    325     }
    326 
    327     return $svgs;
    328289}
    329290
  • trunk/src/wp-includes/script-loader.php

    r56064 r56101  
    24812481
    24822482/**
    2483  * Renders the SVG filters supplied by theme.json.
    2484  *
    2485  * Note that this doesn't render the per-block user-defined
    2486  * filters which are handled by wp_render_duotone_support,
    2487  * but it should be rendered before the filtered content
    2488  * in the body to satisfy Safari's rendering quirks.
    2489  *
    2490  * @since 5.9.1
    2491  */
    2492 function wp_global_styles_render_svg_filters() {
    2493     /*
    2494      * When calling via the in_admin_header action, we only want to render the
    2495      * SVGs on block editor pages.
    2496      */
    2497     if (
    2498         is_admin() &&
    2499         ! get_current_screen()->is_block_editor()
    2500     ) {
    2501         return;
    2502     }
    2503 
    2504     $filters = wp_get_global_styles_svg_filters();
    2505     if ( ! empty( $filters ) ) {
    2506         echo $filters;
    2507     }
    2508 }
    2509 
    2510 /**
    25112483 * Checks if the editor scripts and styles for all registered block types
    25122484 * should be enqueued on the current screen.
  • trunk/src/wp-settings.php

    r56082 r56101  
    176176require ABSPATH . WPINC . '/class-wp-theme-json.php';
    177177require ABSPATH . WPINC . '/class-wp-theme-json-resolver.php';
     178
    178179require ABSPATH . WPINC . '/global-styles-and-settings.php';
    179180require ABSPATH . WPINC . '/class-wp-block-template.php';
  • trunk/tests/phpunit/tests/theme/wpGetGlobalStylesSvgFilters.php

    r56042 r56101  
    1 <?php
    2 /**
    3  * Tests wp_get_global_styles_svg_filters().
    4  *
    5  * @group themes
    6  */
    7 class Tests_Theme_wpGetGlobalStylesSvgFilters extends WP_UnitTestCase {
    8     public function set_up() {
    9         parent::set_up();
    10         // Clear caches.
    11         wp_clean_themes_cache();
    12     }
    13 
    14     public function tear_down() {
    15         wp_clean_themes_cache();
    16 
    17         parent::tear_down();
    18     }
    19 
    20     /**
    21      * Tests that switching themes recalculates the svgs.
    22      *
    23      * @covers ::wp_get_global_styles_svg_filters
    24      *
    25      * @ticket 57568
    26      */
    27     public function test_switching_themes_should_recalculate_svg() {
    28         $svg_for_default_theme = wp_get_global_styles_svg_filters();
    29         switch_theme( 'block-theme' );
    30         $svg_for_block_theme = wp_get_global_styles_svg_filters();
    31         switch_theme( WP_DEFAULT_THEME );
    32 
    33         $this->assertStringContainsString( '<svg', $svg_for_default_theme, 'Default theme should contain SVG' );
    34         $this->assertStringContainsString( '<svg', $svg_for_default_theme, 'Block theme should contain SVG' );
    35         $this->assertNotSame( $svg_for_default_theme, $svg_for_block_theme, 'Cache value should have changed' );
    36     }
    37 
    38     /**
    39      * Tests that the function relies on the development mode for whether to use caching.
    40      *
    41      * @ticket 57487
    42      *
    43      * @covers ::wp_get_global_styles_svg_filters
    44      */
    45     public function test_caching_is_used_when_developing_theme() {
    46         global $_wp_tests_development_mode;
    47 
    48         switch_theme( 'block-theme' );
    49 
    50         // Store SVG in cache.
    51         $svg = '<svg></svg>';
    52         wp_cache_set( 'wp_get_global_styles_svg_filters', $svg, 'theme_json' );
    53 
    54         // By default, caching should be used, so the above value will be returned.
    55         $_wp_tests_development_mode = '';
    56         $this->assertSame( $svg, wp_get_global_styles_svg_filters(), 'Caching was not used despite development mode disabled' );
    57 
    58         // When the development mode is set to 'theme', caching should not be used.
    59         $_wp_tests_development_mode = 'theme';
    60         $this->assertNotSame( $svg, wp_get_global_styles_svg_filters(), 'Caching was used despite theme development mode' );
    61     }
    62 }
  • trunk/tests/phpunit/tests/theme/wpThemeJson.php

    r56083 r56101  
    637637        );
    638638
    639         $variables = "body{--wp--preset--color--grey: grey;--wp--preset--gradient--custom-gradient: linear-gradient(135deg,rgba(0,0,0) 0%,rgb(0,0,0) 100%);--wp--preset--duotone--custom-duotone: url('#wp-duotone-custom-duotone');--wp--preset--font-family--small: 14px;--wp--preset--font-family--big: 41px;}.wp-block-group{--wp--custom--base-font: 16;--wp--custom--line-height--small: 1.2;--wp--custom--line-height--medium: 1.4;--wp--custom--line-height--large: 1.8;}";
     639        $variables = ;
    640640        $styles    = 'body { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}body .is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}body .is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}body .is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}body .is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}body .is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}body .is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}body .is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){max-width: var(--wp--style--global--content-size);margin-left: auto !important;margin-right: auto !important;}body .is-layout-constrained > .alignwide{max-width: var(--wp--style--global--wide-size);}body .is-layout-flex{display: flex;}body .is-layout-flex{flex-wrap: wrap;align-items: center;}body .is-layout-flex > *{margin: 0;}body .is-layout-grid{display: grid;}body .is-layout-grid > *{margin: 0;}body{color: var(--wp--preset--color--grey);}a:where(:not(.wp-element-button)){background-color: #333;color: #111;}.wp-element-button, .wp-block-button__link{box-shadow: 10px 10px 5px 0px rgba(0,0,0,0.66);}.wp-block-group{background: var(--wp--preset--gradient--custom-gradient);border-radius: 10px;padding: 24px;}.wp-block-group a:where(:not(.wp-element-button)){color: #111;}.wp-block-heading{color: #123456;}.wp-block-heading a:where(:not(.wp-element-button)){background-color: #333;color: #111;font-size: 60px;}.wp-block-post-date{color: #123456;}.wp-block-post-date a:where(:not(.wp-element-button)){background-color: #777;color: #555;}.wp-block-post-excerpt{column-count: 2;}.wp-block-image{margin-bottom: 30px;}.wp-block-image img, .wp-block-image .wp-block-image__crop-area, .wp-block-image .components-placeholder{border-top-left-radius: 10px;border-bottom-right-radius: 1em;}.wp-block-image img, .wp-block-image .components-placeholder{filter: var(--wp--preset--duotone--custom-duotone);}';
    641641        $presets   = '.has-grey-color{color: var(--wp--preset--color--grey) !important;}.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}.has-grey-border-color{border-color: var(--wp--preset--color--grey) !important;}.has-custom-gradient-gradient-background{background: var(--wp--preset--gradient--custom-gradient) !important;}.has-small-font-family{font-family: var(--wp--preset--font-family--small) !important;}.has-big-font-family{font-family: var(--wp--preset--font-family--big) !important;}';
Note: See TracChangeset for help on using the changeset viewer.