Skip to content

Commit

Permalink
Global Styles: Add scoping of feature level selectors for custom bloc…
Browse files Browse the repository at this point in the history
…k style variations (#61033)

Co-authored-by: aaronrobertshaw <[email protected]>
Co-authored-by: talldan <[email protected]>
  • Loading branch information
3 people committed Apr 29, 2024
1 parent 649eddf commit 01b24ce
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 1 deletion.
35 changes: 34 additions & 1 deletion lib/class-wp-theme-json-gutenberg.php
Original file line number Diff line number Diff line change
Expand Up @@ -1196,7 +1196,7 @@ public function get_stylesheet( $types = array( 'variables', 'styles', 'presets'
$node['selector'] = static::scope_selector( $options['scope'], $node['selector'] );
}
foreach ( $style_nodes as &$node ) {
$node['selector'] = static::scope_selector( $options['scope'], $node['selector'] );
$node = static::scope_style_node_selectors( $options['scope'], $node );
}
unset( $node );
}
Expand Down Expand Up @@ -1856,6 +1856,39 @@ public static function scope_selector( $scope, $selector ) {
return $result;
}

/**
* Scopes the selectors for a given style node. This includes the primary
* selector, i.e. `$node['selector']`, as well as any custom selectors for
* features and subfeatures, e.g. `$node['selectors']['border']` etc.
*
* @since 6.6.0
*
* @param string $scope Selector to scope to.
* @param array $node Style node with selectors to scope.
*
* @return array Node with updated selectors.
*/
protected static function scope_style_node_selectors( $scope, $node ) {
$node['selector'] = static::scope_selector( $scope, $node['selector'] );

if ( empty( $node['selectors'] ) ) {
return $node;
}

foreach ( $node['selectors'] as $feature => $selector ) {
if ( is_string( $selector ) ) {
$node['selectors'][ $feature ] = static::scope_selector( $scope, $selector );
}
if ( is_array( $selector ) ) {
foreach ( $selector as $subfeature => $subfeature_selector ) {
$node['selectors'][ $feature ][ $subfeature ] = static::scope_selector( $scope, $subfeature_selector );
}
}
}

return $node;
}

/**
* Gets preset values keyed by slugs based on settings and metadata.
*
Expand Down
45 changes: 45 additions & 0 deletions phpunit/class-wp-theme-json-test.php
Original file line number Diff line number Diff line change
Expand Up @@ -5345,4 +5345,49 @@ public function data_get_block_style_variation_selector() {
),
);
}

/**
* Tests the correct scoping of selectors for a style node.
*/
public function test_scope_style_node_selectors() {
$theme_json = new ReflectionClass( 'WP_Theme_JSON_Gutenberg' );

$func = $theme_json->getMethod( 'scope_style_node_selectors' );
$func->setAccessible( true );

$node = array(
'name' => 'core/image',
'path' => array( 'styles', 'blocks', 'core/image' ),
'selector' => '.wp-block-image',
'selectors' => array(
'root' => '.wp-block-image',
'border' => '.wp-block-image img, .wp-block-image .wp-block-image__crop-area, .wp-block-image .components-placeholder',
'typography' => array(
'textDecoration' => '.wp-block-image caption',
),
'filter' => array(
'duotone' => '.wp-block-image img, .wp-block-image .components-placeholder',
),
),
);

$actual = $func->invoke( null, '.custom-scope', $node );
$expected = array(
'name' => 'core/image',
'path' => array( 'styles', 'blocks', 'core/image' ),
'selector' => '.custom-scope .wp-block-image',
'selectors' => array(
'root' => '.custom-scope .wp-block-image',
'border' => '.custom-scope .wp-block-image img, .custom-scope .wp-block-image .wp-block-image__crop-area, .custom-scope .wp-block-image .components-placeholder',
'typography' => array(
'textDecoration' => '.custom-scope .wp-block-image caption',
),
'filter' => array(
'duotone' => '.custom-scope .wp-block-image img, .custom-scope .wp-block-image .components-placeholder',
),
),
);

$this->assertEquals( $expected, $actual );
}
}

0 comments on commit 01b24ce

Please sign in to comment.