Changeset 61607
- Timestamp:
- 02/10/2026 03:19:36 PM (7 weeks ago)
- Location:
- trunk
- Files:
-
- 3 edited
-
src/wp-includes/class-wp-theme-json.php (modified) (8 diffs)
-
src/wp-includes/global-styles-and-settings.php (modified) (1 diff)
-
tests/phpunit/tests/theme/wpThemeJson.php (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/class-wp-theme-json.php
r61570 r61607 611 611 612 612 /** 613 * The valid pseudo-selectors that can be used for blocks. 614 * 615 * @since 7.0 616 * @var array 617 */ 618 const VALID_BLOCK_PSEUDO_SELECTORS = array( 619 'core/button' => array( ':hover', ':focus', ':focus-visible', ':active' ), 620 ); 621 622 /** 613 623 * The valid elements that can be found under styles. 614 624 * … … 700 710 } 701 711 712 713 /** 714 * Processes pseudo-selectors for any node (block or variation). 715 * 716 * @param array $node The node data (block or variation). 717 * @param string $base_selector The base selector. 718 * @param array $settings The theme settings. 719 * @param string $block_name The block name. 720 * @return array Array of pseudo-selector declarations. 721 */ 722 private static function process_pseudo_selectors( $node, $base_selector, $settings, $block_name ) { 723 $pseudo_declarations = array(); 724 725 if ( ! isset( static::VALID_BLOCK_PSEUDO_SELECTORS[ $block_name ] ) ) { 726 return $pseudo_declarations; 727 } 728 729 foreach ( static::VALID_BLOCK_PSEUDO_SELECTORS[ $block_name ] as $pseudo_selector ) { 730 if ( isset( $node[ $pseudo_selector ] ) ) { 731 $combined_selector = static::append_to_selector( $base_selector, $pseudo_selector ); 732 $declarations = static::compute_style_properties( $node[ $pseudo_selector ], $settings, null, null ); 733 $pseudo_declarations[ $combined_selector ] = $declarations; 734 } 735 } 736 737 return $pseudo_declarations; 738 } 739 740 702 741 /** 703 742 * Returns a class name by an element name. … … 1019 1058 $schema_styles_blocks[ $block ] = $styles_non_top_level; 1020 1059 $schema_styles_blocks[ $block ]['elements'] = $schema_styles_elements; 1060 1061 // Add pseudo-selectors for blocks that support them 1062 if ( isset( static::VALID_BLOCK_PSEUDO_SELECTORS[ $block ] ) ) { 1063 foreach ( static::VALID_BLOCK_PSEUDO_SELECTORS[ $block ] as $pseudo_selector ) { 1064 $schema_styles_blocks[ $block ][ $pseudo_selector ] = $styles_non_top_level; 1065 } 1066 } 1021 1067 } 1022 1068 … … 1041 1087 $schema_styles_variations = array(); 1042 1088 if ( ! empty( $style_variation_names ) ) { 1043 $schema_styles_variations = array_fill_keys( $style_variation_names, $block_style_variation_styles ); 1089 foreach ( $style_variation_names as $variation_name ) { 1090 $variation_schema = $block_style_variation_styles; 1091 1092 // Add pseudo-selectors to variations for blocks that support them 1093 if ( isset( static::VALID_BLOCK_PSEUDO_SELECTORS[ $block ] ) ) { 1094 foreach ( static::VALID_BLOCK_PSEUDO_SELECTORS[ $block ] as $pseudo_selector ) { 1095 $variation_schema[ $pseudo_selector ] = $styles_non_top_level; 1096 } 1097 } 1098 1099 $schema_styles_variations[ $variation_name ] = $variation_schema; 1100 } 1044 1101 } 1045 1102 … … 2743 2800 'css' => $selector, 2744 2801 ); 2802 2803 // Handle any pseudo selectors for the block. 2804 if ( isset( static::VALID_BLOCK_PSEUDO_SELECTORS[ $name ] ) ) { 2805 foreach ( static::VALID_BLOCK_PSEUDO_SELECTORS[ $name ] as $pseudo_selector ) { 2806 if ( isset( $theme_json['styles']['blocks'][ $name ][ $pseudo_selector ] ) ) { 2807 $nodes[] = array( 2808 'name' => $name, 2809 'path' => array( 'styles', 'blocks', $name, $pseudo_selector ), 2810 'selector' => static::append_to_selector( $selector, $pseudo_selector ), 2811 'selectors' => $feature_selectors, 2812 'duotone' => $duotone_selector, 2813 'variations' => $variation_selectors, 2814 'css' => static::append_to_selector( $selector, $pseudo_selector ), 2815 ); 2816 } 2817 } 2818 } 2745 2819 } 2746 2820 … … 2839 2913 // Compute declarations for remaining styles not covered by feature level selectors. 2840 2914 $style_variation_declarations[ $style_variation['selector'] ] = static::compute_style_properties( $style_variation_node, $settings, null, $this->theme_json ); 2915 2916 // Process pseudo-selectors for this variation (e.g., :hover, :focus) 2917 $block_name = isset( $block_metadata['name'] ) ? $block_metadata['name'] : ( in_array( 'blocks', $block_metadata['path'], true ) && count( $block_metadata['path'] ) >= 3 ? $block_metadata['path'][2] : null ); 2918 $variation_pseudo_declarations = static::process_pseudo_selectors( $style_variation_node, $style_variation['selector'], $settings, $block_name ); 2919 $style_variation_declarations = array_merge( $style_variation_declarations, $variation_pseudo_declarations ); 2920 2841 2921 // Store custom CSS for the style variation. 2842 2922 if ( isset( $style_variation_node['css'] ) ) { … … 2871 2951 if ( isset( $current_element, static::VALID_ELEMENT_PSEUDO_SELECTORS[ $current_element ] ) ) { 2872 2952 $element_pseudo_allowed = static::VALID_ELEMENT_PSEUDO_SELECTORS[ $current_element ]; 2953 } 2954 2955 /* 2956 * Check if we're processing a block pseudo-selector. 2957 * $block_metadata['path'] = array( 'styles', 'blocks', 'core/button', ':hover' ); 2958 */ 2959 $is_processing_block_pseudo = false; 2960 $block_pseudo_selector = null; 2961 if ( in_array( 'blocks', $block_metadata['path'], true ) && count( $block_metadata['path'] ) >= 4 ) { 2962 $block_name = $block_metadata['path'][2]; // 'core/button' 2963 $last_path_element = $block_metadata['path'][ count( $block_metadata['path'] ) - 1 ]; // ':hover' 2964 2965 if ( isset( static::VALID_BLOCK_PSEUDO_SELECTORS[ $block_name ] ) && 2966 in_array( $last_path_element, static::VALID_BLOCK_PSEUDO_SELECTORS[ $block_name ], true ) ) { 2967 $is_processing_block_pseudo = true; 2968 $block_pseudo_selector = $last_path_element; 2969 } 2873 2970 } 2874 2971 … … 2902 2999 ) { 2903 3000 $declarations = static::compute_style_properties( $node[ $pseudo_selector ], $settings, null, $this->theme_json, $selector, $use_root_padding ); 3001 } elseif ( $is_processing_block_pseudo ) { 3002 // Process block pseudo-selector styles 3003 // For block pseudo-selectors, we need to get the block data first, then access the pseudo-selector 3004 $block_name = $block_metadata['path'][2]; // 'core/button' 3005 $block_data = _wp_array_get( $this->theme_json, array( 'styles', 'blocks', $block_name ), array() ); 3006 $pseudo_data = isset( $block_data[ $block_pseudo_selector ] ) ? $block_data[ $block_pseudo_selector ] : array(); 3007 3008 $declarations = static::compute_style_properties( $pseudo_data, $settings, null, $this->theme_json, $selector, $use_root_padding ); 2904 3009 } else { 2905 3010 $declarations = static::compute_style_properties( $node, $settings, null, $this->theme_json, $selector, $use_root_padding ); -
trunk/src/wp-includes/global-styles-and-settings.php
r61473 r61607 277 277 278 278 if ( $can_use_cached ) { 279 // Use the block name as the key for cached CSS data. Otherwise, use a hash of the metadata.280 $cache_node_key = $metadata['name'] ??md5( wp_json_encode( $metadata ) );279 // Generate a unique cache key based on the full metadata to ensure pseudo-selectors and other variations get unique keys. 280 $cache_node_key = md5( wp_json_encode( $metadata ) ); 281 281 282 282 if ( isset( $cached['blocks'][ $cache_node_key ] ) ) { -
trunk/tests/phpunit/tests/theme/wpThemeJson.php
r61573 r61607 6070 6070 * @ticket 60613 6071 6071 * 6072 * @covers WP_Theme_JSON _Gutenberg::resolve_variables6073 * @covers WP_Theme_JSON _Gutenberg::convert_variables_to_value6072 * @covers WP_Theme_JSON::resolve_variables 6073 * @covers WP_Theme_JSON::convert_variables_to_value 6074 6074 */ 6075 6075 public function test_resolve_variables() { … … 6694 6694 $this->assertEqualSetsWithIndex( $expected, $actual ); 6695 6695 } 6696 6697 /** 6698 * Test that block pseudo selectors are processed correctly. 6699 */ 6700 public function test_block_pseudo_selectors_are_processed() { 6701 $theme_json = new WP_Theme_JSON( 6702 array( 6703 'version' => WP_Theme_JSON::LATEST_SCHEMA, 6704 'styles' => array( 6705 'blocks' => array( 6706 'core/button' => array( 6707 'color' => array( 6708 'text' => 'white', 6709 'background' => 'blue', 6710 ), 6711 ':hover' => array( 6712 'color' => array( 6713 'text' => 'blue', 6714 'background' => 'white', 6715 ), 6716 ), 6717 ':focus' => array( 6718 'color' => array( 6719 'text' => 'red', 6720 'background' => 'yellow', 6721 ), 6722 ), 6723 ), 6724 ), 6725 ), 6726 ) 6727 ); 6728 6729 $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:focus){background-color: yellow;color: red;}'; 6730 $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); 6731 } 6732 6733 /** 6734 * Test that block pseudo selectors are processed correctly within variations. 6735 */ 6736 public function test_block_variation_pseudo_selectors_are_processed() { 6737 register_block_style( 6738 'core/button', 6739 array( 6740 'name' => 'outline', 6741 'label' => 'Outline', 6742 ) 6743 ); 6744 6745 $theme_json = new WP_Theme_JSON( 6746 array( 6747 'version' => WP_Theme_JSON::LATEST_SCHEMA, 6748 'styles' => array( 6749 'blocks' => array( 6750 'core/button' => array( 6751 'color' => array( 6752 'text' => 'white', 6753 'background' => 'blue', 6754 ), 6755 'variations' => array( 6756 'outline' => array( 6757 'color' => array( 6758 'text' => 'currentColor', 6759 'background' => 'transparent', 6760 ), 6761 'border' => array( 6762 'color' => 'currentColor', 6763 'width' => '1px', 6764 'style' => 'solid', 6765 ), 6766 ':hover' => array( 6767 'color' => array( 6768 'text' => 'white', 6769 'background' => 'red', 6770 ), 6771 ), 6772 ':focus' => array( 6773 'color' => array( 6774 'text' => 'black', 6775 'background' => 'yellow', 6776 ), 6777 ), 6778 ), 6779 ), 6780 ), 6781 ), 6782 ), 6783 ) 6784 ); 6785 6786 $expected = ':root :where(.wp-block-button .wp-block-button__link){background-color: blue;color: white;}:root :where(.wp-block-button.is-style-outline .wp-block-button__link){background-color: transparent;border-color: currentColor;border-width: 1px;border-style: solid;color: currentColor;}:root :where(.wp-block-button.is-style-outline .wp-block-button__link:hover){background-color: red;color: white;}:root :where(.wp-block-button.is-style-outline .wp-block-button__link:focus){background-color: yellow;color: black;}'; 6787 $actual = $theme_json->get_stylesheet( 6788 array( 'styles' ), 6789 null, 6790 array( 6791 'skip_root_layout_styles' => true, 6792 'include_block_style_variations' => true, 6793 ) 6794 ); 6795 6796 unregister_block_style( 'core/button', 'outline' ); 6797 6798 $this->assertSame( $expected, $actual ); 6799 } 6800 6801 /** 6802 * Test that non-whitelisted pseudo selectors are ignored for blocks. 6803 */ 6804 public function test_block_pseudo_selectors_ignores_non_whitelisted() { 6805 $theme_json = new WP_Theme_JSON( 6806 array( 6807 'version' => WP_Theme_JSON::LATEST_SCHEMA, 6808 'styles' => array( 6809 'blocks' => array( 6810 'core/button' => array( 6811 'color' => array( 6812 'text' => 'white', 6813 'background' => 'blue', 6814 ), 6815 ':hover' => array( 6816 'color' => array( 6817 'text' => 'blue', 6818 'background' => 'white', 6819 ), 6820 ), 6821 ':levitate' => array( 6822 'color' => array( 6823 'text' => 'yellow', 6824 'background' => 'black', 6825 ), 6826 ), 6827 ), 6828 ), 6829 ), 6830 ) 6831 ); 6832 6833 $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;}'; 6834 $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); 6835 $this->assertStringNotContainsString( '.wp-block-button .wp-block-button__link:levitate{', $theme_json->get_stylesheet( array( 'styles' ) ) ); 6836 } 6837 6838 /** 6839 * Test that blocks without pseudo selector support ignore pseudo selectors. 6840 */ 6841 public function test_blocks_without_pseudo_support_ignore_pseudo_selectors() { 6842 $theme_json = new WP_Theme_JSON( 6843 array( 6844 'version' => WP_Theme_JSON::LATEST_SCHEMA, 6845 'styles' => array( 6846 'blocks' => array( 6847 'core/paragraph' => array( 6848 'color' => array( 6849 'text' => 'black', 6850 ), 6851 ':hover' => array( 6852 'color' => array( 6853 'text' => 'red', 6854 ), 6855 ), 6856 ), 6857 ), 6858 ), 6859 ) 6860 ); 6861 6862 $expected = ':root :where(p){color: black;}'; 6863 $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); 6864 $this->assertStringNotContainsString( 'p:hover{', $theme_json->get_stylesheet( array( 'styles' ) ) ); 6865 } 6866 6867 /** 6868 * Test that block pseudo selectors work with elements within blocks. 6869 */ 6870 public function test_block_pseudo_selectors_with_elements() { 6871 $theme_json = new WP_Theme_JSON( 6872 array( 6873 'version' => WP_Theme_JSON::LATEST_SCHEMA, 6874 'styles' => array( 6875 'blocks' => array( 6876 'core/button' => array( 6877 'color' => array( 6878 'text' => 'white', 6879 'background' => 'blue', 6880 ), 6881 ':hover' => array( 6882 'color' => array( 6883 'text' => 'blue', 6884 'background' => 'white', 6885 ), 6886 ), 6887 'elements' => array( 6888 'button' => array( 6889 'color' => array( 6890 'text' => 'green', 6891 ), 6892 ':hover' => array( 6893 'color' => array( 6894 'text' => 'orange', 6895 ), 6896 ), 6897 ), 6898 ), 6899 ), 6900 ), 6901 ), 6902 ) 6903 ); 6904 6905 $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;}'; 6906 $this->assertSame( $expected, $theme_json->get_stylesheet( array( 'styles' ), null, array( 'skip_root_layout_styles' => true ) ) ); 6907 } 6696 6908 }
Note: See TracChangeset
for help on using the changeset viewer.