Make WordPress Core

Changeset 62607


Ignore:
Timestamp:
07/01/2026 07:02:25 AM (6 weeks ago)
Author:
isabel_brison
Message:

Editor: fix inconsistencies in global styles feature selectors.

Corrects feature selector output for block style variations in global styles.

Props isabel_brison, dmsnell, talldanwp, audrasjb, desrosj.
Fixes #65265.

Location:
trunk
Files:
1 added
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/class-wp-theme-json.php

    r62559 r62607  
    758758         * @param array  $settings The theme settings.
    759759         * @param string $block_name The block name.
     760         * @param array|null $block_metadata Metadata about the block to get styles for.
     761         * @param array|null $style_variation Style variation metadata.
    760762         * @return array Array of pseudo-selector declarations.
    761763         */
    762         private static function process_pseudo_selectors( $node, $base_selector, $settings, $block_name ) {
     764        private function process_pseudo_selectors( $node, $base_selector, $settings, $block_name, $block_metadata = null, $style_variation = null ) {
    763765                $pseudo_declarations = array();
     766                $add_declarations    = static function ( $selector, $declarations ) use ( &$pseudo_declarations ) {
     767                        if ( empty( $declarations ) ) {
     768                                return;
     769                        }
     770
     771                        if ( isset( $pseudo_declarations[ $selector ] ) ) {
     772                                $pseudo_declarations[ $selector ] = array_merge(
     773                                        $pseudo_declarations[ $selector ],
     774                                        $declarations
     775                                );
     776                        } else {
     777                                $pseudo_declarations[ $selector ] = $declarations;
     778                        }
     779                };
    764780
    765781                if ( ! isset( static::VALID_BLOCK_PSEUDO_SELECTORS[ $block_name ] ) ) {
     
    769785                foreach ( static::VALID_BLOCK_PSEUDO_SELECTORS[ $block_name ] as $pseudo_selector ) {
    770786                        if ( isset( $node[ $pseudo_selector ] ) ) {
    771                                 $combined_selector                         = static::append_to_selector( $base_selector, $pseudo_selector );
    772                                 $declarations                              = static::compute_style_properties( $node[ $pseudo_selector ], $settings, null, null );
    773                                 $pseudo_declarations[ $combined_selector ] = $declarations;
     787                                $pseudo_node = $node[ $pseudo_selector ];
     788
     789                                if ( is_array( $block_metadata ) ) {
     790                                        $feature_declarations = $this->get_feature_declarations_for_node( $block_metadata, $pseudo_node );
     791                                        $feature_declarations = static::update_paragraph_text_indent_selector( $feature_declarations, $settings, $block_name );
     792
     793                                        foreach ( $feature_declarations as $feature_selector => $declarations ) {
     794                                                $target_selector   = is_array( $style_variation )
     795                                                        ? static::get_block_style_variation_feature_selector( $style_variation, $feature_selector )
     796                                                        : $feature_selector;
     797                                                $combined_selector = static::append_to_selector( $target_selector, $pseudo_selector );
     798
     799                                                $add_declarations( $combined_selector, $declarations );
     800                                        }
     801                                }
     802
     803                                $combined_selector = static::append_to_selector( $base_selector, $pseudo_selector );
     804                                $declarations      = static::compute_style_properties( $pseudo_node, $settings, null, null );
     805                                $add_declarations( $combined_selector, $declarations );
    774806                        }
    775807                }
     
    12281260                }
    12291261                $new_selectors = array();
    1230                 $selectors     = explode( ',', $selector );
     1262                $selectors     = static::split_selector_list( $selector );
    12311263                foreach ( $selectors as $sel ) {
    12321264                        $new_selectors[] = $sel . $to_append;
    12331265                }
    1234                 return implode( ',', $new_selectors );
     1266                return implode( ', ', $new_selectors );
    12351267        }
    12361268
     
    12531285                }
    12541286                $new_selectors = array();
    1255                 $selectors     = explode( ',', $selector );
     1287                $selectors     = static::split_selector_list( $selector );
    12561288                foreach ( $selectors as $sel ) {
    12571289                        $new_selectors[] = $to_prepend . $sel;
    12581290                }
    1259                 return implode( ',', $new_selectors );
     1291                return implode( ', ', $new_selectors );
     1292        }
     1293
     1294        /**
     1295         * Splits a selector list into separate selectors.
     1296         *
     1297         * While selectors are joined by commas, not all commas separate top-level selectors.
     1298         * This method only separates top-level selectors, so some commas may appear inside
     1299         * strings, nested selectors, and comments. Leading and trailing CSS whitespace is
     1300         * trimmed from the returned list items.
     1301         *
     1302         * Non-selector content, such as comments, are retained in the list in the same item
     1303         * as the selector content they follow.
     1304         *
     1305         * Example:
     1306         *
     1307         *     array( '.wp-block' )    === self::split_selector_list( '.wp-block' );
     1308         *     array( '.one', '.two' ) === self::split_selector_list( '.one, .two' );
     1309         *
     1310         *     // Nested selector lists are retained within their containing selector.
     1311         *     array( ':is(.a, .b)', 'c' ) === self::split_selector_list( ':is(.a, .b), .c' );
     1312         *
     1313         *     // Commas within strings do not separate selectors.
     1314         *     $selectors   = self::split_selector_list( '[data-label="Save, continue"],.fallback' );
     1315         *     $selectors === array( '[data-label="Save, continue"]', '.fallback' )
     1316         *
     1317         *     array( 'lang(zh, "*-hant")', '.foo' ) === self::split_selector_list( 'lang(zh, "*-hant"), .foo' );
     1318         *
     1319         *     // Identifiers may contain escaped commas.
     1320         *     array( '.foo\,bar', '.baz' ) === self::split_selector_list( '.foo\,bar,.baz' );
     1321         *
     1322         *     // Comments stay with the selector they follow.
     1323         *     array( '.a /* a, the first *\/', '.b' ) === self::split_selector_list( '.a /* a, the first *\/,.b' );
     1324         *
     1325         * @see https://www.w3.org/TR/selectors/#parse-selector
     1326         * @see https://www.w3.org/TR/css-syntax-3/
     1327         *
     1328         * @since 7.1.0
     1329         *
     1330         * @param string $selector CSS selector list as a string, e.g. '.wp-block .wp-block-paragraph'.
     1331         * @return string[] List of trimmed selectors parsed from input list.
     1332         */
     1333        protected static function split_selector_list( $selector ): array {
     1334                if ( ! str_contains( $selector, ',' ) ) {
     1335                        // See note on trimming CSS whitespace in main loop.
     1336                        return array( trim( $selector, " \t\n" ) );
     1337                }
     1338
     1339                $selectors         = array();
     1340                $selector_length   = strlen( $selector );
     1341                $parentheses_depth = 0;
     1342                $at                = 0;
     1343                $was_at            = 0;
     1344
     1345                while ( $at < $selector_length ) {
     1346                        $next_at = $at + strcspn( $selector, '/,\'"()<-\\', $at );
     1347                        if ( $next_at >= $selector_length ) {
     1348                                break;
     1349                        }
     1350
     1351                        $next_cp = $selector[ $next_at ];
     1352
     1353                        // Escaped syntax characters do not act as delimiters.
     1354                        if ( '\\' === $next_cp ) {
     1355                                $at = min( $next_at + 2, $selector_length );
     1356                                continue;
     1357                        }
     1358
     1359                        /*
     1360                         * Start of a parenthesized expression, which maintains a stack of parentheses.
     1361                         * For the sake of this function, no selector list will be split inside parentheses.
     1362                         * Therefore it’s possible to jump ahead until this list completes.
     1363                         */
     1364                        if ( '(' === $next_cp || ')' === $next_cp ) {
     1365                                $parentheses_depth += '(' === $next_cp ? 1 : -1;
     1366                                $at                 = $next_at + 1;
     1367                                continue;
     1368                        }
     1369
     1370                        // Start of a string, which will be incorporated into the selector in which it’s found.
     1371                        if ( "'" === $next_cp || '"' === $next_cp ) {
     1372                                $end_of_string = $next_at + 1;
     1373                                while ( $end_of_string < $selector_length ) {
     1374                                        $end_of_string += strcspn( $selector, "{$next_cp}\\", $end_of_string );
     1375                                        if ( $end_of_string >= $selector_length ) {
     1376                                                break;
     1377                                        }
     1378
     1379                                        $end_cp = $selector[ $end_of_string ];
     1380
     1381                                        // Skip escaped characters.
     1382                                        if ( '\\' === $end_cp ) {
     1383                                                $end_of_string = $end_of_string + 2;
     1384                                                continue;
     1385                                        }
     1386
     1387                                        if ( $next_cp === $end_cp ) {
     1388                                                ++$end_of_string;
     1389                                                break;
     1390                                        }
     1391
     1392                                        ++$end_of_string;
     1393                                }
     1394
     1395                                $at = $end_of_string;
     1396                                continue;
     1397                        }
     1398
     1399                        // Start of a comment, which will be incorporated into the selector in which it’s found.
     1400                        if ( '/' === $next_cp && ( $next_at + 1 ) < $selector_length && '*' === $selector[ $next_at + 1 ] ) {
     1401                                $comment_end_at = strpos( $selector, '*/', $next_at + 1 );
     1402                                $is_terminated  = false !== $comment_end_at;
     1403                                $after_comment  = $is_terminated ? $comment_end_at + 2 : strlen( $selector );
     1404                                $at             = $after_comment;
     1405                                continue;
     1406                        }
     1407
     1408                        // Start of a CDO or CDC, which will be incorporated into the selector in which it’s found.
     1409                        if (
     1410                                ( '<' === $next_cp && 0 === substr_compare( $selector, '<!--', $next_at, 4 ) ) ||
     1411                                ( '-' === $next_cp && 0 === substr_compare( $selector, '-->', $next_at, 3 ) )
     1412                        ) {
     1413                                $at = $next_at + ( '<' === $next_cp ? 4 : 3 );
     1414                                continue;
     1415                        }
     1416
     1417                        // Everything else is either a comma token or part of a selector.
     1418                        if ( ',' === $next_cp && 0 === $parentheses_depth ) {
     1419                                /**
     1420                                 * Trim each selector so that downstream code doesn’t see whitespace
     1421                                 * as the first character in a selector and get confused.
     1422                                 *
     1423                                 * There is inconsistency in this because comments and other syntax
     1424                                 * are included which are also not part of the selector itself, but
     1425                                 * a tradeoff is made between removing common syntax which carries
     1426                                 * no meaning and rarer syntax which leaves auxiliary information.
     1427                                 *
     1428                                 * > A newline, U+0009 CHARACTER TABULATION, or U+0020 SPACE.
     1429                                 * > Note that U+000D CARRIAGE RETURN and U+000C FORM FEED are
     1430                                 * > not included in this definition, as they are converted
     1431                                 * > to U+000A LINE FEED during preprocessing.
     1432                                 *
     1433                                 * @see https://www.w3.org/TR/css-syntax/#whitespace
     1434                                 * @see https://www.w3.org/TR/css-syntax/#newline
     1435                                 */
     1436                                $selectors[] = trim( substr( $selector, $was_at, $next_at - $was_at ), " \t\n" );
     1437                                $at          = $next_at + 1;
     1438                                $was_at      = $at;
     1439                                continue;
     1440                        }
     1441
     1442                        $at = $next_at + 1;
     1443                }
     1444
     1445                if ( $was_at < $selector_length ) {
     1446                        // See note on trimming CSS whitespace in main loop.
     1447                        $selectors[] = trim( substr( $selector, $was_at ), " \t\n" );
     1448                }
     1449
     1450                return $selectors;
    12601451        }
    12611452
     
    21382329                }
    21392330
    2140                 $scopes    = explode( ',', $scope );
    2141                 $selectors = explode( ',', $selector );
     2331                $scopes    = static::split_selector_list( $scope );
     2332                $selectors = static::split_selector_list( $selector );
    21422333
    21432334                $selectors_scoped = array();
    21442335                foreach ( $scopes as $outer ) {
    21452336                        foreach ( $selectors as $inner ) {
    2146                                 $outer = trim( $outer );
    2147                                 $inner = trim( $inner );
    21482337                                if ( ! empty( $outer ) && ! empty( $inner ) ) {
    21492338                                        $selectors_scoped[] = $outer . ' ' . $inner;
     
    29283117                                        foreach ( $node['variations'] as $variation => $node ) {
    29293118                                                $variation_selectors[] = array(
     3119                                                        'name'     => $variation,
    29303120                                                        'path'     => array( 'styles', 'blocks', $name, 'variations', $variation ),
    29313121                                                        'selector' => $selectors[ $name ]['styleVariations'][ $variation ],
     
    31353325
    31363326                // If there are style variations, generate the declarations for them, including any feature selectors the block may have.
    3137                 $style_variation_declarations    = array();
    3138                 $style_variation_custom_css      = array();
    3139                 $style_variation_responsive_css  = array();
    3140                 $style_variation_layout_metadata = array();
     3327                $style_variation_declarations          = array();
     3328                $style_variation_custom_css            = array();
     3329                $style_variation_responsive_css        = array();
     3330                $style_variation_responsive_pseudo_css = array();
     3331                $style_variation_layout_metadata       = array();
    31413332                if ( ! $media_query && ! empty( $block_metadata['variations'] ) ) {
    31423333                        foreach ( $block_metadata['variations'] as $style_variation ) {
    3143                                 $style_variation_node           = _wp_array_get( $this->theme_json, $style_variation['path'], array() );
    3144                                 $clean_style_variation_selector = trim( $style_variation['selector'] );
     3334                                $style_variation_node = _wp_array_get( $this->theme_json, $style_variation['path'], array() );
    31453335
    31463336                                // Generate any feature/subfeature style declarations for the current style variation.
     
    31523342                                // Combine selectors with style variation's selector and add to overall style variation declarations.
    31533343                                foreach ( $variation_declarations as $current_selector => $new_declarations ) {
    3154                                         /*
    3155                                          * Clean up any whitespace between comma separated selectors.
    3156                                          * This prevents these spaces breaking compound selectors such as:
    3157                                          * - `.wp-block-list:not(.wp-block-list .wp-block-list)`
    3158                                          * - `.wp-block-image img, .wp-block-image.my-class img`
    3159                                          */
    3160                                         $clean_current_selector = preg_replace( '/,\s+/', ',', $current_selector );
    3161                                         $shortened_selector     = str_replace( $block_metadata['selector'], '', $clean_current_selector );
    3162 
    3163                                         // Prepend the variation selector to the current selector.
    3164                                         $split_selectors    = explode( ',', $shortened_selector );
    3165                                         $updated_selectors  = array_map(
    3166                                                 static function ( $split_selector ) use ( $clean_style_variation_selector ) {
    3167                                                         return $clean_style_variation_selector . $split_selector;
    3168                                                 },
    3169                                                 $split_selectors
    3170                                         );
    3171                                         $combined_selectors = implode( ',', $updated_selectors );
     3344                                        $combined_selectors = static::get_block_style_variation_feature_selector( $style_variation, $current_selector );
    31723345
    31733346                                        // Add the new declarations to the overall results under the modified selector.
     
    31863359                                        $block_name = null;
    31873360                                }
    3188                                 $variation_pseudo_declarations = static::process_pseudo_selectors( $style_variation_node, $style_variation['selector'], $settings, $block_name );
     3361                                $variation_pseudo_declarations = $this->process_pseudo_selectors( $style_variation_node, $style_variation['selector'], $settings, $block_name, $block_metadata, $style_variation );
    31893362                                $style_variation_declarations  = array_merge( $style_variation_declarations, $variation_pseudo_declarations );
    31903363
     
    32083381                                // Store responsive breakpoint CSS for the style variation.
    32093382                                // This includes both base properties and feature-level selectors.
    3210                                 $variation_responsive_css = '';
     3383                                $variation_responsive_css        = '';
     3384                                $variation_responsive_pseudo_css = '';
    32113385
    32123386                                foreach ( array_keys( static::RESPONSIVE_BREAKPOINTS ) as $breakpoint ) {
     
    32213395                                        $breakpoint_feature_declarations = static::update_paragraph_text_indent_selector( $breakpoint_feature_declarations, $settings, $block_name );
    32223396                                        foreach ( $breakpoint_feature_declarations as $feature_selector => $feature_decl ) {
    3223                                                 $clean_feature_selector = preg_replace( '/,\s+/', ',', $feature_selector );
    3224                                                 $shortened_selector     = str_replace( $block_metadata['selector'], '', $clean_feature_selector );
    3225 
    3226                                                 if ( $block_metadata['selector'] && ! str_contains( $clean_feature_selector, $block_metadata['selector'] ) ) {
    3227                                                         /*
    3228                                                          * Feature selector is block-level (e.g. `.wp-block-button` for
    3229                                                          * dimensions/width) — apply the variation class directly to it.
    3230                                                          */
    3231                                                         $feature_element_selector = str_replace( $shortened_selector, '', $clean_style_variation_selector );
    3232                                                         $combined_selectors       = str_replace( $feature_element_selector, '', $clean_style_variation_selector );
    3233                                                 } else {
    3234                                                         // Prepend the variation selector to the current selector.
    3235                                                         $split_selectors    = explode( ',', $shortened_selector );
    3236                                                         $updated_selectors  = array_map(
    3237                                                                 static function ( $split_selector ) use ( $clean_style_variation_selector ) {
    3238                                                                         return $clean_style_variation_selector . $split_selector;
    3239                                                                 },
    3240                                                                 $split_selectors
    3241                                                         );
    3242                                                         $combined_selectors = implode( ',', $updated_selectors );
    3243                                                 }
     3397                                                $combined_selectors = static::get_block_style_variation_feature_selector( $style_variation, $feature_selector );
    32443398
    32453399                                                $feature_ruleset           = static::to_ruleset( ':root :where(' . $combined_selectors . ')', $feature_decl );
     
    32543408                                        }
    32553409
    3256                                         $breakpoint_pseudo_declarations = static::process_pseudo_selectors( $breakpoint_node, $style_variation['selector'], $settings, $block_name );
     3410                                        $breakpoint_pseudo_declarations = $this->process_pseudo_selectors( $breakpoint_node, $style_variation['selector'], $settings, $block_name, $block_metadata, $style_variation );
    32573411                                        foreach ( $breakpoint_pseudo_declarations as $pseudo_selector => $pseudo_declarations ) {
    32583412                                                if ( empty( $pseudo_declarations ) ) {
    32593413                                                        continue;
    32603414                                                }
    3261                                                 $pseudo_ruleset            = static::to_ruleset( ':root :where(' . $pseudo_selector . ')', $pseudo_declarations );
    3262                                                 $variation_responsive_css .= $breakpoint_media . '{' . $pseudo_ruleset . '}';
     3415                                                $pseudo_ruleset                   = static::to_ruleset( ':root :where(' . $pseudo_selector . ')', $pseudo_declarations );
     3416                                                $variation_responsive_pseudo_css .= $breakpoint_media . '{' . $pseudo_ruleset . '}';
    32633417                                        }
    32643418
     
    32893443                                                        }
    32903444
    3291                                                         $clean_element_selector     = preg_replace( '/,\s+/', ',', $block_elements[ $element_name ] );
    3292                                                         $shortened_selector         = str_replace( $block_metadata['selector'], '', $clean_element_selector );
    3293                                                         $split_selectors            = explode( ',', $shortened_selector );
    3294                                                         $updated_selectors          = array_map(
    3295                                                                 static function ( $split_selector ) use ( $clean_style_variation_selector ) {
    3296                                                                         return $clean_style_variation_selector . $split_selector;
    3297                                                                 },
    3298                                                                 $split_selectors
    3299                                                         );
    3300                                                         $variation_element_selector = implode( ',', $updated_selectors );
     3445                                                        $variation_element_selector = static::get_block_style_variation_feature_selector( $style_variation, $block_elements[ $element_name ] );
    33013446
    33023447                                                        $element_declarations = static::compute_style_properties( $element_node, $settings, null, $this->theme_json );
     
    33223467                                                                        }
    33233468
    3324                                                                         $pseudo_selector_ruleset   = static::to_ruleset( ':root :where(' . static::append_to_selector( $variation_element_selector, $pseudo_selector ) . ')', $pseudo_declarations );
    3325                                                                         $variation_responsive_css .= $breakpoint_media . '{' . $pseudo_selector_ruleset . '}';
     3469                                                                        $pseudo_selector_ruleset          = static::to_ruleset( ':root :where(' . static::append_to_selector( $variation_element_selector, $pseudo_selector ) . ')', $pseudo_declarations );
     3470                                                                        $variation_responsive_pseudo_css .= $breakpoint_media . '{' . $pseudo_selector_ruleset . '}';
    33263471                                                                }
    33273472                                                        }
     
    33323477                                if ( ! empty( $variation_responsive_css ) ) {
    33333478                                        $style_variation_responsive_css[ $style_variation['selector'] ] = $variation_responsive_css;
     3479                                }
     3480                                if ( ! empty( $variation_responsive_pseudo_css ) ) {
     3481                                        $style_variation_responsive_pseudo_css[ $style_variation['selector'] ] = $variation_responsive_pseudo_css;
    33343482                                }
    33353483                        }
     
    35203668                                $block_rules .= $style_variation_responsive_css[ $style_variation_selector ];
    35213669                        }
     3670                }
     3671                /*
     3672                 * Responsive pseudo styles must be output after default pseudo styles
     3673                 * so viewport state styles win in the cascade.
     3674                 */
     3675                foreach ( $style_variation_responsive_pseudo_css as $responsive_pseudo_css ) {
     3676                        $block_rules .= $responsive_pseudo_css;
    35223677                }
    35233678
     
    51985353
    51995354                $limit          = 1;
    5200                 $selector_parts = explode( ',', $block_selector );
     5355                $selector_parts = static::split_selector_list( $block_selector );
    52015356                $result         = array();
    52025357
     
    52125367                }
    52135368
    5214                 return implode( ',', $result );
     5369                return implode( ', ', $result );
     5370        }
     5371
     5372        /**
     5373         * Applies a block style variation class to a feature selector.
     5374         *
     5375         * Feature selectors can target a different element than the block's root
     5376         * selector. For example, the Button block's root selector targets the inner
     5377         * link, while its dimensions width selector targets the outer wrapper. Apply
     5378         * the variation class directly to the selector that will receive the
     5379         * declarations instead of deriving it by subtracting the root selector from
     5380         * the feature selector.
     5381         *
     5382         * @since 7.0.0
     5383         *
     5384         * @param array  $style_variation Style variation metadata.
     5385         * @param string $feature_selector CSS selector for the feature.
     5386         * @return string Feature selector with block style variation selector added.
     5387         */
     5388        protected static function get_block_style_variation_feature_selector( $style_variation, $feature_selector ) {
     5389                $variation_path = $style_variation['path'] ?? array();
     5390                $variation_name = $style_variation['name'] ?? ( is_array( $variation_path ) ? end( $variation_path ) : null );
     5391
     5392                if ( ! $variation_name ) {
     5393                        return $style_variation['selector'] ?? $feature_selector;
     5394                }
     5395
     5396                $variation_class = ".is-style-$variation_name";
     5397                $selector_parts  = static::split_selector_list( $feature_selector );
     5398                $selector_parts  = array_map(
     5399                        static function ( $selector ) use ( $variation_class ) {
     5400                                $prefix = $variation_class . ' ';
     5401
     5402                                if ( str_starts_with( $selector, $prefix ) ) {
     5403                                        return substr( $selector, strlen( $prefix ) );
     5404                                }
     5405
     5406                                return $selector;
     5407                        },
     5408                        $selector_parts
     5409                );
     5410
     5411                return static::get_block_style_variation_selector(
     5412                        $variation_name,
     5413                        implode( ', ', $selector_parts )
     5414                );
    52155415        }
    52165416
  • trunk/tests/phpunit/tests/theme/wpThemeJson.php

    r62559 r62607  
    51265126         */
    51275127        public function test_get_styles_for_block_with_style_variations_and_custom_selectors() {
     5128                $color_selector = '.wp-block-test-milk .liquid, .wp-block-test-milk:is(.frothed, .steamed) .foam, .wp-block-test-milk:not(.spoiled), .wp-block-test-milk.in-bottle';
     5129
    51285130                register_block_type(
    51295131                        'test/milk',
     
    51325134                                'selectors'   => array(
    51335135                                        'root'  => '.milk',
    5134                                         'color' => '.wp-block-test-milk .liquid, .wp-block-test-milk:not(.spoiled), .wp-block-test-milk.in-bottle',
     5136                                        'color' => $color_selector,
    51355137                                ),
    51365138                        )
     
    51725174                        'selector'   => '.wp-block-test-milk',
    51735175                        'selectors'  => array(
    5174                                 'color' => '.wp-block-test-milk .liquid, .wp-block-test-milk:not(.spoiled), .wp-block-test-milk.in-bottle',
     5176                                'color' => $color_selector,
    51755177                        ),
    51765178                        'variations' => array(
     
    51835185
    51845186                $actual_styles    = $theme_json->get_styles_for_block( $metadata );
    5185                 $default_styles   = ':root :where(.wp-block-test-milk .liquid, .wp-block-test-milk:not(.spoiled), .wp-block-test-milk.in-bottle){background-color: white;}';
    5186                 $variation_styles = ':root :where(.is-style-chocolate.wp-block-test-milk .liquid,.is-style-chocolate.wp-block-test-milk:not(.spoiled),.is-style-chocolate.wp-block-test-milk.in-bottle){background-color: #35281E;}';
     5187                $default_styles   = ':root :where(.wp-block-test-milk .liquid, .wp-block-test-milk:is(.frothed, .steamed) .foam, .wp-block-test-milk:not(.spoiled), .wp-block-test-milk.in-bottle){background-color: white;}';
     5188                $variation_styles = ':root :where(.wp-block-test-milk.is-style-chocolate .liquid, .wp-block-test-milk.is-style-chocolate:is(.frothed, .steamed) .foam, .wp-block-test-milk.is-style-chocolate:not(.spoiled), .wp-block-test-milk.in-bottle.is-style-chocolate){background-color: #35281E;}';
    51875189                $expected         = $default_styles . $variation_styles;
    51885190
     
    67856787                                'expected' => '.wp-block.is-style-custom:is(.outer .inner:first-child)',
    67866788                        ),
     6789                        ':is with selector list'   => array(
     6790                                'selector' => '.wp-block:is(.outer, .inner:first-child) .content, .wp-block-alternative',
     6791                                'expected' => '.wp-block.is-style-custom:is(.outer, .inner:first-child) .content, .wp-block-alternative.is-style-custom',
     6792                        ),
    67876793                        ':not selector'            => array(
    67886794                                'selector' => '.wp-block:not(.outer .inner:first-child)',
     
    69346940                $expected = array(
    69356941                        array(
     6942                                'name'     => 'outline',
    69366943                                'path'     => array( 'styles', 'blocks', 'core/button', 'variations', 'outline' ),
    69376944                                'selector' => '.wp-block-button.is-style-outline .wp-block-button__link',
     
    73627369                );
    73637370
    7364                 $expected = ':root :where(.wp-block-button .wp-block-button__link){background-color: blue;color: white;}:root :where(.wp-block-button .wp-block-button__link:hover){background-color: white;color: blue;}:root :where(.wp-block-button .wp-block-button__link .wp-element-button,.wp-block-button .wp-block-button__link  .wp-block-button__link){color: green;}:root :where(.wp-block-button .wp-block-button__link .wp-element-button:hover,.wp-block-button .wp-block-button__link .wp-block-button__link:hover){color: orange;}';
     7371                $expected = ':root :where(.wp-block-button .wp-block-button__link){background-color: blue;color: white;}:root :where(.wp-block-button .wp-block-button__link:hover){background-color: white;color: blue;}:root :where(.wp-block-button .wp-block-button__link .wp-element-button, .wp-block-button .wp-block-button__link .wp-block-button__link){color: green;}:root :where(.wp-block-button .wp-block-button__link .wp-element-button:hover, .wp-block-button .wp-block-button__link .wp-block-button__link:hover){color: orange;}';
    73657372                $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) );
    73667373        }
Note: See TracChangeset for help on using the changeset viewer.