Editor: refactor and stabilize selectors API.
Restructures the block.json selectors API by moving `__experimentalSelector` props into their own config, stabilizing the selectors API, and enabling more flexible styling options. Props ramonopoly, spacedmonkey, aaronrobertshaw, onemaggie. Fixes #58586. Built from https://develop.svn.wordpress.org/trunk@56058 git-svn-id: http://core.svn.wordpress.org/trunk@55570 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
parent
e96961f861
commit
d9e41aa9e9
|
@ -66,6 +66,7 @@ function _wp_add_block_level_presets_class( $block_content, $block ) {
|
||||||
* @internal
|
* @internal
|
||||||
*
|
*
|
||||||
* @since 6.2.0
|
* @since 6.2.0
|
||||||
|
* @since 6.3.0 Updated preset styles to use Selectors API.
|
||||||
* @access private
|
* @access private
|
||||||
*
|
*
|
||||||
* @param string|null $pre_render The pre-rendered content. Default null.
|
* @param string|null $pre_render The pre-rendered content. Default null.
|
||||||
|
@ -95,11 +96,16 @@ function _wp_add_block_level_preset_styles( $pre_render, $block ) {
|
||||||
$registry = WP_Block_Type_Registry::get_instance();
|
$registry = WP_Block_Type_Registry::get_instance();
|
||||||
$blocks = $registry->get_all_registered();
|
$blocks = $registry->get_all_registered();
|
||||||
foreach ( $blocks as $block_type ) {
|
foreach ( $blocks as $block_type ) {
|
||||||
if (
|
/*
|
||||||
isset( $block_type->supports['__experimentalSelector'] ) &&
|
* We only want to append selectors for block's using custom selectors
|
||||||
is_string( $block_type->supports['__experimentalSelector'] )
|
* i.e. not `wp-block-<name>`.
|
||||||
) {
|
*/
|
||||||
$variables_root_selector .= ',' . $block_type->supports['__experimentalSelector'];
|
$has_custom_selector =
|
||||||
|
( isset( $block_type->supports['__experimentalSelector'] ) && is_string( $block_type->supports['__experimentalSelector'] ) ) ||
|
||||||
|
( isset( $block_type->selectors['root'] ) && is_string( $block_type->selectors['root'] ) );
|
||||||
|
|
||||||
|
if ( $has_custom_selector ) {
|
||||||
|
$variables_root_selector .= ',' . wp_get_block_css_selector( $block_type );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$variables_root_selector = WP_Theme_JSON::scope_selector( $class_name, $variables_root_selector );
|
$variables_root_selector = WP_Theme_JSON::scope_selector( $class_name, $variables_root_selector );
|
||||||
|
|
|
@ -879,6 +879,7 @@ class WP_Theme_JSON {
|
||||||
* @since 5.8.0
|
* @since 5.8.0
|
||||||
* @since 5.9.0 Added `duotone` key with CSS selector.
|
* @since 5.9.0 Added `duotone` key with CSS selector.
|
||||||
* @since 6.1.0 Added `features` key with block support feature level selectors.
|
* @since 6.1.0 Added `features` key with block support feature level selectors.
|
||||||
|
* @since 6.3.0 Refactored and stabilized selectors API.
|
||||||
*
|
*
|
||||||
* @return array Block metadata.
|
* @return array Block metadata.
|
||||||
*/
|
*/
|
||||||
|
@ -893,56 +894,33 @@ class WP_Theme_JSON {
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ( $blocks as $block_name => $block_type ) {
|
foreach ( $blocks as $block_name => $block_type ) {
|
||||||
if (
|
$root_selector = wp_get_block_css_selector( $block_type );
|
||||||
isset( $block_type->supports['__experimentalSelector'] ) &&
|
|
||||||
is_string( $block_type->supports['__experimentalSelector'] )
|
static::$blocks_metadata[ $block_name ]['selector'] = $root_selector;
|
||||||
) {
|
static::$blocks_metadata[ $block_name ]['selectors'] = static::get_block_selectors( $block_type, $root_selector );
|
||||||
static::$blocks_metadata[ $block_name ]['selector'] = $block_type->supports['__experimentalSelector'];
|
|
||||||
} else {
|
$elements = static::get_block_element_selectors( $root_selector );
|
||||||
static::$blocks_metadata[ $block_name ]['selector'] = '.wp-block-' . str_replace( '/', '-', str_replace( 'core/', '', $block_name ) );
|
if ( ! empty( $elements ) ) {
|
||||||
|
static::$blocks_metadata[ $block_name ]['elements'] = $elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
// The block may or may not have a duotone selector.
|
||||||
isset( $block_type->supports['color']['__experimentalDuotone'] ) &&
|
$duotone_selector = wp_get_block_css_selector( $block_type, 'filter.duotone' );
|
||||||
is_string( $block_type->supports['color']['__experimentalDuotone'] )
|
|
||||||
) {
|
|
||||||
static::$blocks_metadata[ $block_name ]['duotone'] = $block_type->supports['color']['__experimentalDuotone'];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate block support feature level selectors if opted into
|
// Keep backwards compatibility for support.color.__experimentalDuotone.
|
||||||
// for the current block.
|
if ( null === $duotone_selector ) {
|
||||||
$features = array();
|
$duotone_support = _wp_array_get( $block_type->supports, array( 'color', '__experimentalDuotone' ), null );
|
||||||
foreach ( static::BLOCK_SUPPORT_FEATURE_LEVEL_SELECTORS as $key => $feature ) {
|
|
||||||
if (
|
if ( $duotone_support ) {
|
||||||
isset( $block_type->supports[ $key ]['__experimentalSelector'] ) &&
|
$root_selector = wp_get_block_css_selector( $block_type );
|
||||||
$block_type->supports[ $key ]['__experimentalSelector']
|
$duotone_selector = WP_Theme_JSON::scope_selector( $root_selector, $duotone_support );
|
||||||
) {
|
|
||||||
$features[ $feature ] = static::scope_selector(
|
|
||||||
static::$blocks_metadata[ $block_name ]['selector'],
|
|
||||||
$block_type->supports[ $key ]['__experimentalSelector']
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ! empty( $features ) ) {
|
if ( null !== $duotone_selector ) {
|
||||||
static::$blocks_metadata[ $block_name ]['features'] = $features;
|
static::$blocks_metadata[ $block_name ]['duotone'] = $duotone_selector;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assign defaults, then overwrite those that the block sets by itself.
|
|
||||||
// If the block selector is compounded, will append the element to each
|
|
||||||
// individual block selector.
|
|
||||||
$block_selectors = explode( ',', static::$blocks_metadata[ $block_name ]['selector'] );
|
|
||||||
foreach ( static::ELEMENTS as $el_name => $el_selector ) {
|
|
||||||
$element_selector = array();
|
|
||||||
foreach ( $block_selectors as $selector ) {
|
|
||||||
if ( $selector === $el_selector ) {
|
|
||||||
$element_selector = array( $el_selector );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
$element_selector[] = static::prepend_to_selector( $el_selector, $selector . ' ' );
|
|
||||||
}
|
|
||||||
static::$blocks_metadata[ $block_name ]['elements'][ $el_name ] = implode( ',', $element_selector );
|
|
||||||
}
|
|
||||||
// If the block has style variations, append their selectors to the block metadata.
|
// If the block has style variations, append their selectors to the block metadata.
|
||||||
if ( ! empty( $block_type->styles ) ) {
|
if ( ! empty( $block_type->styles ) ) {
|
||||||
$style_selectors = array();
|
$style_selectors = array();
|
||||||
|
@ -2223,6 +2201,7 @@ class WP_Theme_JSON {
|
||||||
* An internal method to get the block nodes from a theme.json file.
|
* An internal method to get the block nodes from a theme.json file.
|
||||||
*
|
*
|
||||||
* @since 6.1.0
|
* @since 6.1.0
|
||||||
|
* @since 6.3.0 Refactored and stabilized selectors API.
|
||||||
*
|
*
|
||||||
* @param array $theme_json The theme.json converted to an array.
|
* @param array $theme_json The theme.json converted to an array.
|
||||||
* @return array The block nodes in theme.json.
|
* @return array The block nodes in theme.json.
|
||||||
|
@ -2251,8 +2230,8 @@ class WP_Theme_JSON {
|
||||||
}
|
}
|
||||||
|
|
||||||
$feature_selectors = null;
|
$feature_selectors = null;
|
||||||
if ( isset( $selectors[ $name ]['features'] ) ) {
|
if ( isset( $selectors[ $name ]['selectors'] ) ) {
|
||||||
$feature_selectors = $selectors[ $name ]['features'];
|
$feature_selectors = $selectors[ $name ]['selectors'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$variation_selectors = array();
|
$variation_selectors = array();
|
||||||
|
@ -2269,6 +2248,7 @@ class WP_Theme_JSON {
|
||||||
'name' => $name,
|
'name' => $name,
|
||||||
'path' => array( 'styles', 'blocks', $name ),
|
'path' => array( 'styles', 'blocks', $name ),
|
||||||
'selector' => $selector,
|
'selector' => $selector,
|
||||||
|
'selectors' => $feature_selectors,
|
||||||
'duotone' => $duotone_selector,
|
'duotone' => $duotone_selector,
|
||||||
'features' => $feature_selectors,
|
'features' => $feature_selectors,
|
||||||
'variations' => $variation_selectors,
|
'variations' => $variation_selectors,
|
||||||
|
@ -2315,88 +2295,39 @@ class WP_Theme_JSON {
|
||||||
$use_root_padding = isset( $this->theme_json['settings']['useRootPaddingAwareAlignments'] ) && true === $this->theme_json['settings']['useRootPaddingAwareAlignments'];
|
$use_root_padding = isset( $this->theme_json['settings']['useRootPaddingAwareAlignments'] ) && true === $this->theme_json['settings']['useRootPaddingAwareAlignments'];
|
||||||
$selector = $block_metadata['selector'];
|
$selector = $block_metadata['selector'];
|
||||||
$settings = _wp_array_get( $this->theme_json, array( 'settings' ) );
|
$settings = _wp_array_get( $this->theme_json, array( 'settings' ) );
|
||||||
|
$feature_declarations = static::get_feature_declarations_for_node( $block_metadata, $node );
|
||||||
/*
|
|
||||||
* Process style declarations for block support features the current
|
|
||||||
* block contains selectors for. Values for a feature with a custom
|
|
||||||
* selector are filtered from the theme.json node before it is
|
|
||||||
* processed as normal.
|
|
||||||
*/
|
|
||||||
$feature_declarations = array();
|
|
||||||
|
|
||||||
if ( ! empty( $block_metadata['features'] ) ) {
|
|
||||||
foreach ( $block_metadata['features'] as $feature_name => $feature_selector ) {
|
|
||||||
if ( ! empty( $node[ $feature_name ] ) ) {
|
|
||||||
// Create temporary node containing only the feature data
|
|
||||||
// to leverage existing `compute_style_properties` function.
|
|
||||||
$feature = array( $feature_name => $node[ $feature_name ] );
|
|
||||||
// Generate the feature's declarations only.
|
|
||||||
$new_feature_declarations = static::compute_style_properties( $feature, $settings, null, $this->theme_json );
|
|
||||||
|
|
||||||
// Merge new declarations with any that already exist for
|
|
||||||
// the feature selector. This may occur when multiple block
|
|
||||||
// support features use the same custom selector.
|
|
||||||
if ( isset( $feature_declarations[ $feature_selector ] ) ) {
|
|
||||||
foreach ( $new_feature_declarations as $new_feature_declaration ) {
|
|
||||||
$feature_declarations[ $feature_selector ][] = $new_feature_declaration;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$feature_declarations[ $feature_selector ] = $new_feature_declarations;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the feature from the block's node now the
|
|
||||||
// styles will be included under the feature level selector.
|
|
||||||
unset( $node[ $feature_name ] );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there are style variations, generate the declarations for them, including any feature selectors the block may have.
|
// If there are style variations, generate the declarations for them, including any feature selectors the block may have.
|
||||||
$style_variation_declarations = array();
|
$style_variation_declarations = array();
|
||||||
if ( ! empty( $block_metadata['variations'] ) ) {
|
if ( ! empty( $block_metadata['variations'] ) ) {
|
||||||
foreach ( $block_metadata['variations'] as $style_variation ) {
|
foreach ( $block_metadata['variations'] as $style_variation ) {
|
||||||
$style_variation_node = _wp_array_get( $this->theme_json, $style_variation['path'], array() );
|
$style_variation_node = _wp_array_get( $this->theme_json, $style_variation['path'], array() );
|
||||||
$style_variation_selector = $style_variation['selector'];
|
$clean_style_variation_selector = trim( $style_variation['selector'] );
|
||||||
|
|
||||||
// If the block has feature selectors, generate the declarations for them within the current style variation.
|
// Generate any feature/subfeature style declarations for the current style variation.
|
||||||
if ( ! empty( $block_metadata['features'] ) ) {
|
$variation_declarations = static::get_feature_declarations_for_node( $block_metadata, $style_variation_node );
|
||||||
$clean_style_variation_selector = trim( $style_variation_selector );
|
|
||||||
foreach ( $block_metadata['features'] as $feature_name => $feature_selector ) {
|
// Combine selectors with style variation's selector and add to overall style variation declarations.
|
||||||
if ( empty( $style_variation_node[ $feature_name ] ) ) {
|
foreach ( $variation_declarations as $current_selector => $new_declarations ) {
|
||||||
continue;
|
// If current selector includes block classname, remove it but leave the whitespace in.
|
||||||
}
|
$shortened_selector = str_replace( $block_metadata['selector'] . ' ', ' ', $current_selector );
|
||||||
// Prepend the variation selector to the feature selector.
|
|
||||||
$split_feature_selectors = explode( ',', $feature_selector );
|
// Prepend the variation selector to the current selector.
|
||||||
$feature_selectors = array_map(
|
$split_selectors = explode( ',', $shortened_selector );
|
||||||
static function( $split_feature_selector ) use ( $clean_style_variation_selector ) {
|
$updated_selectors = array_map(
|
||||||
return $clean_style_variation_selector . trim( $split_feature_selector );
|
static function( $split_selector ) use ( $clean_style_variation_selector ) {
|
||||||
|
return $clean_style_variation_selector . $split_selector;
|
||||||
},
|
},
|
||||||
$split_feature_selectors
|
$split_selectors
|
||||||
);
|
);
|
||||||
$combined_feature_selectors = implode( ',', $feature_selectors );
|
$combined_selectors = implode( ',', $updated_selectors );
|
||||||
|
|
||||||
// Compute declarations for the feature.
|
// Add the new declarations to the overall results under the modified selector.
|
||||||
$new_feature_declarations = static::compute_style_properties( array( $feature_name => $style_variation_node[ $feature_name ] ), $settings, null, $this->theme_json );
|
$style_variation_declarations[ $combined_selectors ] = $new_declarations;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Merge new declarations with any that already exist for
|
|
||||||
* the feature selector. This may occur when multiple block
|
|
||||||
* support features use the same custom selector.
|
|
||||||
*/
|
|
||||||
if ( isset( $style_variation_declarations[ $combined_feature_selectors ] ) ) {
|
|
||||||
$style_variation_declarations[ $combined_feature_selectors ] = array_merge( $style_variation_declarations[ $combined_feature_selectors ], $new_feature_declarations );
|
|
||||||
} else {
|
|
||||||
$style_variation_declarations[ $combined_feature_selectors ] = $new_feature_declarations;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Remove the feature from the variation's node now the
|
|
||||||
* styles will be included under the feature level selector.
|
|
||||||
*/
|
|
||||||
unset( $style_variation_node[ $feature_name ] );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Compute declarations for remaining styles not covered by feature level selectors.
|
// Compute declarations for remaining styles not covered by feature level selectors.
|
||||||
$style_variation_declarations[ $style_variation_selector ] = static::compute_style_properties( $style_variation_node, $settings, null, $this->theme_json );
|
$style_variation_declarations[ $style_variation['selector'] ] = static::compute_style_properties( $style_variation_node, $settings, null, $this->theme_json );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -2472,8 +2403,7 @@ class WP_Theme_JSON {
|
||||||
|
|
||||||
// 3. Generate and append the rules that use the duotone selector.
|
// 3. Generate and append the rules that use the duotone selector.
|
||||||
if ( isset( $block_metadata['duotone'] ) && ! empty( $declarations_duotone ) ) {
|
if ( isset( $block_metadata['duotone'] ) && ! empty( $declarations_duotone ) ) {
|
||||||
$selector_duotone = static::scope_selector( $block_metadata['selector'], $block_metadata['duotone'] );
|
$block_rules .= static::to_ruleset( $block_metadata['duotone'], $declarations_duotone );
|
||||||
$block_rules .= static::to_ruleset( $selector_duotone, $declarations_duotone );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Generate Layout block gap styles.
|
// 4. Generate Layout block gap styles.
|
||||||
|
@ -3536,6 +3466,159 @@ class WP_Theme_JSON {
|
||||||
return $tree;
|
return $tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the selectors metadata for a block.
|
||||||
|
*
|
||||||
|
* @since 6.3.0
|
||||||
|
*
|
||||||
|
* @param object $block_type The block type.
|
||||||
|
* @param string $root_selector The block's root selector.
|
||||||
|
*
|
||||||
|
* @return array The custom selectors set by the block.
|
||||||
|
*/
|
||||||
|
protected static function get_block_selectors( $block_type, $root_selector ) {
|
||||||
|
if ( ! empty( $block_type->selectors ) ) {
|
||||||
|
return $block_type->selectors;
|
||||||
|
}
|
||||||
|
|
||||||
|
$selectors = array( 'root' => $root_selector );
|
||||||
|
foreach ( static::BLOCK_SUPPORT_FEATURE_LEVEL_SELECTORS as $key => $feature ) {
|
||||||
|
$feature_selector = wp_get_block_css_selector( $block_type, $key );
|
||||||
|
if ( null !== $feature_selector ) {
|
||||||
|
$selectors[ $feature ] = array( 'root' => $feature_selector );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $selectors;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates all the element selectors for a block.
|
||||||
|
*
|
||||||
|
* @since 6.3.0
|
||||||
|
*
|
||||||
|
* @param string $root_selector The block's root CSS selector.
|
||||||
|
* @return array The block's element selectors.
|
||||||
|
*/
|
||||||
|
protected static function get_block_element_selectors( $root_selector ) {
|
||||||
|
// Assign defaults, then override those that the block sets by itself.
|
||||||
|
// If the block selector is compounded, will append the element to each
|
||||||
|
// individual block selector.
|
||||||
|
$block_selectors = explode( ',', $root_selector );
|
||||||
|
$element_selectors = array();
|
||||||
|
|
||||||
|
foreach ( static::ELEMENTS as $el_name => $el_selector ) {
|
||||||
|
$element_selector = array();
|
||||||
|
foreach ( $block_selectors as $selector ) {
|
||||||
|
if ( $selector === $el_selector ) {
|
||||||
|
$element_selector = array( $el_selector );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$element_selector[] = static::prepend_to_selector( $el_selector, $selector . ' ' );
|
||||||
|
}
|
||||||
|
$element_selectors[ $el_name ] = implode( ',', $element_selector );
|
||||||
|
}
|
||||||
|
|
||||||
|
return $element_selectors;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates style declarations for a node's features e.g., color, border,
|
||||||
|
* typography etc. that have custom selectors in their related block's
|
||||||
|
* metadata.
|
||||||
|
*
|
||||||
|
* @since 6.3.0
|
||||||
|
*
|
||||||
|
* @param object $metadata The related block metadata containing selectors.
|
||||||
|
* @param object $node A merged theme.json node for block or variation.
|
||||||
|
*
|
||||||
|
* @return array The style declarations for the node's features with custom
|
||||||
|
* selectors.
|
||||||
|
*/
|
||||||
|
protected function get_feature_declarations_for_node( $metadata, &$node ) {
|
||||||
|
$declarations = array();
|
||||||
|
|
||||||
|
if ( ! isset( $metadata['selectors'] ) ) {
|
||||||
|
return $declarations;
|
||||||
|
}
|
||||||
|
|
||||||
|
$settings = _wp_array_get( $this->theme_json, array( 'settings' ) );
|
||||||
|
|
||||||
|
foreach ( $metadata['selectors'] as $feature => $feature_selectors ) {
|
||||||
|
// Skip if this is the block's root selector or the block doesn't
|
||||||
|
// have any styles for the feature.
|
||||||
|
if ( 'root' === $feature || empty( $node[ $feature ] ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( is_array( $feature_selectors ) ) {
|
||||||
|
foreach ( $feature_selectors as $subfeature => $subfeature_selector ) {
|
||||||
|
if ( 'root' === $subfeature || empty( $node[ $feature ][ $subfeature ] ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create temporary node containing only the subfeature data
|
||||||
|
// to leverage existing `compute_style_properties` function.
|
||||||
|
$subfeature_node = array(
|
||||||
|
$feature => array(
|
||||||
|
$subfeature => $node[ $feature ][ $subfeature ],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Generate style declarations.
|
||||||
|
$new_declarations = static::compute_style_properties( $subfeature_node, $settings, null, $this->theme_json );
|
||||||
|
|
||||||
|
// Merge subfeature declarations into feature declarations.
|
||||||
|
if ( isset( $declarations[ $subfeature_selector ] ) ) {
|
||||||
|
foreach ( $new_declarations as $new_declaration ) {
|
||||||
|
$declarations[ $subfeature_selector ][] = $new_declaration;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$declarations[ $subfeature_selector ] = $new_declarations;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the subfeature from the block's node now its
|
||||||
|
// styles will be included under its own selector not the
|
||||||
|
// block's.
|
||||||
|
unset( $node[ $feature ][ $subfeature ] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now subfeatures have been processed and removed we can process
|
||||||
|
// feature root selector or simple string selector.
|
||||||
|
if (
|
||||||
|
is_string( $feature_selectors ) ||
|
||||||
|
( isset( $feature_selectors['root'] ) && $feature_selectors['root'] )
|
||||||
|
) {
|
||||||
|
$feature_selector = is_string( $feature_selectors ) ? $feature_selectors : $feature_selectors['root'];
|
||||||
|
|
||||||
|
// Create temporary node containing only the feature data
|
||||||
|
// to leverage existing `compute_style_properties` function.
|
||||||
|
$feature_node = array( $feature => $node[ $feature ] );
|
||||||
|
|
||||||
|
// Generate the style declarations.
|
||||||
|
$new_declarations = static::compute_style_properties( $feature_node, $settings, null, $this->theme_json );
|
||||||
|
|
||||||
|
// Merge new declarations with any that already exist for
|
||||||
|
// the feature selector. This may occur when multiple block
|
||||||
|
// support features use the same custom selector.
|
||||||
|
if ( isset( $declarations[ $feature_selector ] ) ) {
|
||||||
|
foreach ( $new_declarations as $new_declaration ) {
|
||||||
|
$declarations[ $feature_selector ][] = $new_declaration;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$declarations[ $feature_selector ] = $new_declarations;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the feature from the block's node now its styles
|
||||||
|
// will be included under its own selector not the block's.
|
||||||
|
unset( $node[ $feature ] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $declarations;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replaces CSS variables with their values in place.
|
* Replaces CSS variables with their values in place.
|
||||||
*
|
*
|
||||||
|
@ -3608,5 +3691,4 @@ class WP_Theme_JSON {
|
||||||
$theme_json->theme_json['styles'] = self::convert_variables_to_value( $styles, $vars );
|
$theme_json->theme_json['styles'] = self::convert_variables_to_value( $styles, $vars );
|
||||||
return $theme_json;
|
return $theme_json;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -443,3 +443,108 @@ function wp_clean_theme_json_cache() {
|
||||||
function wp_get_theme_directory_pattern_slugs() {
|
function wp_get_theme_directory_pattern_slugs() {
|
||||||
return WP_Theme_JSON_Resolver::get_theme_data( array(), array( 'with_supports' => false ) )->get_patterns();
|
return WP_Theme_JSON_Resolver::get_theme_data( array(), array( 'with_supports' => false ) )->get_patterns();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the CSS selector for the block type and property provided,
|
||||||
|
* returning it if available.
|
||||||
|
*
|
||||||
|
* @since 6.3.0
|
||||||
|
*
|
||||||
|
* @param WP_Block_Type $block_type The block's type.
|
||||||
|
* @param string|array $target The desired selector's target, `root` or array path.
|
||||||
|
* @param boolean $fallback Whether to fall back to broader selector.
|
||||||
|
*
|
||||||
|
* @return string|null CSS selector or `null` if no selector available.
|
||||||
|
*/
|
||||||
|
function wp_get_block_css_selector( $block_type, $target = 'root', $fallback = false ) {
|
||||||
|
if ( empty( $target ) ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$has_selectors = ! empty( $block_type->selectors );
|
||||||
|
|
||||||
|
// Root Selector.
|
||||||
|
|
||||||
|
// Calculated before returning as it can be used as fallback for
|
||||||
|
// feature selectors later on.
|
||||||
|
$root_selector = null;
|
||||||
|
|
||||||
|
if ( $has_selectors && isset( $block_type->selectors['root'] ) ) {
|
||||||
|
// Use the selectors API if available.
|
||||||
|
$root_selector = $block_type->selectors['root'];
|
||||||
|
} elseif ( isset( $block_type->supports['__experimentalSelector'] ) && is_string( $block_type->supports['__experimentalSelector'] ) ) {
|
||||||
|
// Use the old experimental selector supports property if set.
|
||||||
|
$root_selector = $block_type->supports['__experimentalSelector'];
|
||||||
|
} else {
|
||||||
|
// If no root selector found, generate default block class selector.
|
||||||
|
$block_name = str_replace( '/', '-', str_replace( 'core/', '', $block_type->name ) );
|
||||||
|
$root_selector = ".wp-block-{$block_name}";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return selector if it's the root target we are looking for.
|
||||||
|
if ( 'root' === $target ) {
|
||||||
|
return $root_selector;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If target is not `root` we have a feature or subfeature as the target.
|
||||||
|
// If the target is a string convert to an array.
|
||||||
|
if ( is_string( $target ) ) {
|
||||||
|
$target = explode( '.', $target );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Feature Selectors ( May fallback to root selector ).
|
||||||
|
if ( 1 === count( $target ) ) {
|
||||||
|
$fallback_selector = $fallback ? $root_selector : null;
|
||||||
|
|
||||||
|
// Prefer the selectors API if available.
|
||||||
|
if ( $has_selectors ) {
|
||||||
|
// Look for selector under `feature.root`.
|
||||||
|
$path = array_merge( $target, array( 'root' ) );
|
||||||
|
$feature_selector = _wp_array_get( $block_type->selectors, $path, null );
|
||||||
|
|
||||||
|
if ( $feature_selector ) {
|
||||||
|
return $feature_selector;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if feature selector is set via shorthand.
|
||||||
|
$feature_selector = _wp_array_get( $block_type->selectors, $target, null );
|
||||||
|
|
||||||
|
return is_string( $feature_selector ) ? $feature_selector : $fallback_selector;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try getting old experimental supports selector value.
|
||||||
|
$path = array_merge( $target, array( '__experimentalSelector' ) );
|
||||||
|
$feature_selector = _wp_array_get( $block_type->supports, $path, null );
|
||||||
|
|
||||||
|
// Nothing to work with, provide fallback or null.
|
||||||
|
if ( null === $feature_selector ) {
|
||||||
|
return $fallback_selector;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scope the feature selector by the block's root selector.
|
||||||
|
return WP_Theme_JSON::scope_selector( $root_selector, $feature_selector );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subfeature selector
|
||||||
|
// This may fallback either to parent feature or root selector.
|
||||||
|
$subfeature_selector = null;
|
||||||
|
|
||||||
|
// Use selectors API if available.
|
||||||
|
if ( $has_selectors ) {
|
||||||
|
$subfeature_selector = _wp_array_get( $block_type->selectors, $target, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only return if we have a subfeature selector.
|
||||||
|
if ( $subfeature_selector ) {
|
||||||
|
return $subfeature_selector;
|
||||||
|
}
|
||||||
|
|
||||||
|
// To this point we don't have a subfeature selector. If a fallback
|
||||||
|
// has been requested, remove subfeature from target path and return
|
||||||
|
// results of a call for the parent feature's selector.
|
||||||
|
if ( $fallback ) {
|
||||||
|
return wp_get_block_css_selector( $block_type, $target[0], $fallback );
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
*
|
*
|
||||||
* @global string $wp_version
|
* @global string $wp_version
|
||||||
*/
|
*/
|
||||||
$wp_version = '6.3-alpha-56057';
|
$wp_version = '6.3-alpha-56058';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
|
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
|
||||||
|
|
Loading…
Reference in New Issue