Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 33 additions & 10 deletions lib/class-wp-theme-json-gutenberg.php
Original file line number Diff line number Diff line change
Expand Up @@ -1278,12 +1278,36 @@ protected static function append_to_selector( $selector, $to_append ) {
if ( ! str_contains( $selector, ',' ) ) {
return $selector . $to_append;
}

/**
* Check for an opportunity to skip the more-costly selector splitting.
* This should be possible if there are no comments, strings, functions,
* URLs, escapes, or comment declaration openers (CDOs).
*
* Note that this means the fast-path will not apply for selectors like
* the following incomplete list:
*
* - `[class ~= "wide"]`
* - `.wp-block:is(.is-style-a, .is-style-b)`
* - `:nth-child(1)`
*
* These syntax forms all present opportunities where a comma may not
* separate selectors. If none of the start characters are present,
* there should be no way for a comma to mean anything other than a
* comma token. The exception are syntax errors, which are not handled here.
*
* @see https://www.w3.org/TR/css-syntax-3/#parse-comma-separated-list-of-component-values
*/
if ( strlen( $selector ) === strcspn( $selector, '/\'"(<\\' ) ) {
return str_replace( ',', $to_append . ',', $selector ) . $to_append;
}

$new_selectors = array();
$selectors = static::split_selector_list( $selector );
foreach ( $selectors as $sel ) {
$new_selectors[] = $sel . $to_append;
}
return implode( ',', $new_selectors );
return implode( ', ', $new_selectors );
}

/**
Expand Down Expand Up @@ -1333,7 +1357,7 @@ protected static function prepend_to_selector( $selector, $to_prepend ) {
$new_selectors[] = $to_prepend . $sel;
}

return implode( ',', $new_selectors );
return implode( ', ', $new_selectors );
}

/**
Expand Down Expand Up @@ -1375,7 +1399,8 @@ protected static function prepend_to_selector( $selector, $to_prepend ) {
*/
protected static function split_selector_list( $selector ): array {
if ( ! str_contains( $selector, ',' ) ) {
return array( $selector );
// See note on trimming CSS whitespace in main loop.
return array( trim( $selector, " \t\n" ) );
}

$selectors = array();
Expand Down Expand Up @@ -1485,7 +1510,8 @@ protected static function split_selector_list( $selector ): array {
}

if ( $was_at < $selector_length ) {
$selectors[] = substr( $selector, $was_at );
// See note on trimming CSS whitespace in main loop.
$selectors[] = trim( substr( $selector, $was_at ), " \t\n" );
}

return $selectors;
Expand Down Expand Up @@ -2474,8 +2500,6 @@ public static function scope_selector( $scope, $selector ) {
$selectors_scoped = array();
foreach ( $scopes as $outer ) {
foreach ( $selectors as $inner ) {
$outer = trim( $outer );
$inner = trim( $inner );
if ( ! empty( $outer ) && ! empty( $inner ) ) {
$selectors_scoped[] = $outer . ' ' . $inner;
} elseif ( empty( $outer ) ) {
Expand Down Expand Up @@ -5597,7 +5621,7 @@ function ( $matches ) use ( $variation_class ) {
);
}

return implode( ',', $result );
return implode( ', ', $result );
}

/**
Expand Down Expand Up @@ -5626,8 +5650,7 @@ protected static function get_block_style_variation_feature_selector( $style_var
$selector_parts = static::split_selector_list( $feature_selector );
$selector_parts = array_map(
static function ( $selector ) use ( $variation_class ) {
$selector = trim( $selector );
$prefix = $variation_class . ' ';
$prefix = $variation_class . ' ';

if ( str_starts_with( $selector, $prefix ) ) {
return substr( $selector, strlen( $prefix ) );
Expand All @@ -5640,7 +5663,7 @@ static function ( $selector ) use ( $variation_class ) {

return static::get_block_style_variation_selector(
$variation_name,
implode( ',', $selector_parts )
implode( ', ', $selector_parts )
);
}

Expand Down
10 changes: 5 additions & 5 deletions phpunit/class-wp-theme-json-test.php
Original file line number Diff line number Diff line change
Expand Up @@ -5020,7 +5020,7 @@ public function test_get_styles_for_block_with_style_variations_and_custom_selec

$actual_styles = $theme_json->get_styles_for_block( $metadata );
$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;}';
$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;}';
$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;}';
$expected = $default_styles . $variation_styles;

unregister_block_style( 'test/milk', 'chocolate' );
Expand Down Expand Up @@ -8236,22 +8236,22 @@ public function data_prepend_to_selector() {
'where with internal commas and top-level comma' => array(
'selector' => ':where(.a, .b),.c',
'to_prepend' => '.scope ',
'expected' => '.scope :where(.a, .b),.scope .c',
'expected' => '.scope :where(.a, .b), .scope .c',
),
'is with internal commas and top-level comma' => array(
'selector' => ':is(.x, .y),.z',
'to_prepend' => '.wrapper ',
'expected' => '.wrapper :is(.x, .y),.wrapper .z',
'expected' => '.wrapper :is(.x, .y), .wrapper .z',
),
'multiple parenthesized selectors with top-level comma' => array(
'selector' => ':where(.a, .b),:is(.c, .d)',
'to_prepend' => '.scope ',
'expected' => '.scope :where(.a, .b),.scope :is(.c, .d)',
'expected' => '.scope :where(.a, .b), .scope :is(.c, .d)',
),
'nested parentheses with commas' => array(
'selector' => ':where(:not(.a, .b), .c),.d',
'to_prepend' => '.scope ',
'expected' => '.scope :where(:not(.a, .b), .c),.scope .d',
'expected' => '.scope :where(:not(.a, .b), .c), .scope .d',
),
);
}
Expand Down
Loading