| @@ -289,9 +289,8 @@ | ||
| 289 | 289 | 'margin-right' => array( 'spacing', 'margin', 'right' ), |
| 290 | 290 | 'margin-bottom' => array( 'spacing', 'margin', 'bottom' ), |
| 291 | 291 | 'margin-left' => array( 'spacing', 'margin', 'left' ), |
| 292 | 292 | 'min-height' => array( 'dimensions', 'minHeight' ), |
| 293 | - 'min-width' => array( 'dimensions', 'minWidth' ), | |
| 294 | 293 | 'outline-color' => array( 'outline', 'color' ), |
| 295 | 294 | 'outline-offset' => array( 'outline', 'offset' ), |
| 296 | 295 | 'outline-style' => array( 'outline', 'style' ), |
| 297 | 296 | 'outline-width' => array( 'outline', 'width' ), |
| @@ -345,9 +344,8 @@ | ||
| 345 | 344 | array( 'layout', 'wideSize' ), |
| 346 | 345 | ), |
| 347 | 346 | 'background-image' => array( |
| 348 | 347 | array( 'background', 'backgroundImage', 'url' ), |
| 349 | - array( 'background', 'gradient' ), | |
| 350 | 348 | ), |
| 351 | 349 | ); |
| 352 | 350 | |
| 353 | 351 | |
| @@ -398,9 +396,8 @@ | ||
| 398 | 396 | 'useRootPaddingAwareAlignments' => null, |
| 399 | 397 | 'background' => array( |
| 400 | 398 | 'backgroundImage' => null, |
| 401 | 399 | 'backgroundSize' => null, |
| 402 | - 'gradient' => null, | |
| 403 | 400 | ), |
| 404 | 401 | 'border' => array( |
| 405 | 402 | 'color' => null, |
| 406 | 403 | 'radius' => null, |
| @@ -432,9 +429,8 @@ | ||
| 432 | 429 | 'defaultAspectRatios' => null, |
| 433 | 430 | 'dimensionSizes' => null, |
| 434 | 431 | 'height' => null, |
| 435 | 432 | 'minHeight' => null, |
| 436 | - 'minWidth' => null, | |
| 437 | 433 | 'width' => null, |
| 438 | 434 | ), |
| 439 | 435 | 'layout' => array( |
| 440 | 436 | 'contentSize' => null, |
| @@ -532,9 +528,8 @@ | ||
| 532 | 528 | 'backgroundAttachment' => null, |
| 533 | 529 | 'backgroundPosition' => null, |
| 534 | 530 | 'backgroundRepeat' => null, |
| 535 | 531 | 'backgroundSize' => null, |
| 536 | - 'gradient' => null, | |
| 537 | 532 | ), |
| 538 | 533 | 'border' => array( |
| 539 | 534 | 'color' => null, |
| 540 | 535 | 'radius' => null, |
| @@ -553,9 +548,8 @@ | ||
| 553 | 548 | 'dimensions' => array( |
| 554 | 549 | 'aspectRatio' => null, |
| 555 | 550 | 'height' => null, |
| 556 | 551 | 'minHeight' => null, |
| 557 | - 'minWidth' => null, | |
| 558 | 552 | 'width' => null, |
| 559 | 553 | ), |
| 560 | 554 | 'filter' => array( |
| 561 | 555 | 'duotone' => null, |
| @@ -615,47 +609,12 @@ | ||
| 615 | 609 | * @since 7.0.0 |
| 616 | 610 | * @var array |
| 617 | 611 | */ |
| 618 | 612 | const VALID_BLOCK_PSEUDO_SELECTORS = array( |
| 619 | - 'core/button' => array( ':hover', ':focus', ':focus-visible', ':active' ), | |
| 620 | - 'core/navigation-link' => array( ':hover', ':focus', ':focus-visible', ':active' ), | |
| 613 | + 'core/button' => array( ':hover', ':focus', ':focus-visible', ':active' ), | |
| 621 | 614 | ); |
| 622 | 615 | |
| 623 | 616 | /** |
| 624 | - * Responsive breakpoint state keys and their corresponding CSS media queries. | |
| 625 | - * These are available for all blocks and wrap their styles in the given media query. | |
| 626 | - * Keep in sync with RESPONSIVE_BREAKPOINTS in packages/global-styles-engine/src/core/render.tsx. | |
| 627 | - * | |
| 628 | - * @since 7.1.0 | |
| 629 | - * @var array | |
| 630 | - */ | |
| 631 | - const RESPONSIVE_BREAKPOINTS = array( | |
| 632 | - 'mobile' => '@media (width <= 480px)', | |
| 633 | - 'tablet' => '@media (480px < width <= 782px)', | |
| 634 | - ); | |
| 635 | - | |
| 636 | - /** | |
| 637 | - * Custom states for blocks that map to CSS class selectors rather than | |
| 638 | - * CSS pseudo-selectors. Values use the '@' prefix (e.g. '@current') to | |
| 639 | - * distinguish them from real CSS pseudo-selectors. | |
| 640 | - * | |
| 641 | - * The CSS selector for each state is defined in the block's block.json | |
| 642 | - * under `selectors.states`, e.g.: | |
| 643 | - * | |
| 644 | - * "selectors": { "states": { "@current": ".some-css-selector" } } | |
| 645 | - * | |
| 646 | - * This constant controls which states are valid in theme.json for a given | |
| 647 | - * block. Blocks listed here also inherit their VALID_BLOCK_PSEUDO_SELECTORS | |
| 648 | - * as valid sub-states, producing compound selectors such as | |
| 649 | - * `.wp-block-navigation-item.current-menu-item:hover`. | |
| 650 | - * | |
| 651 | - * @var array | |
| 652 | - */ | |
| 653 | - const VALID_BLOCK_CUSTOM_STATES = array( | |
| 654 | - 'core/navigation-link' => array( '@current' ), | |
| 655 | - ); | |
| 656 | - | |
| 657 | - /** | |
| 658 | 617 | * The valid elements that can be found under styles. |
| 659 | 618 | * |
| 660 | 619 | * @since 5.8.0 |
| 661 | 620 | * @since 6.1.0 Added `heading`, `button`, and `caption` elements. |
| @@ -800,9 +759,8 @@ | ||
| 800 | 759 | */ |
| 801 | 760 | const APPEARANCE_TOOLS_OPT_INS = array( |
| 802 | 761 | array( 'background', 'backgroundImage' ), |
| 803 | 762 | array( 'background', 'backgroundSize' ), |
| 804 | - array( 'background', 'gradient' ), | |
| 805 | 763 | array( 'border', 'color' ), |
| 806 | 764 | array( 'border', 'radius' ), |
| 807 | 765 | array( 'border', 'style' ), |
| 808 | 766 | array( 'border', 'width' ), |
| @@ -812,9 +770,8 @@ | ||
| 812 | 770 | array( 'color', 'caption' ), |
| 813 | 771 | array( 'dimensions', 'aspectRatio' ), |
| 814 | 772 | array( 'dimensions', 'height' ), |
| 815 | 773 | array( 'dimensions', 'minHeight' ), |
| 816 | - array( 'dimensions', 'minWidth' ), | |
| 817 | 774 | array( 'dimensions', 'width' ), |
| 818 | 775 | // BEGIN EXPERIMENTAL. |
| 819 | 776 | // Allow `position.fixed` to be opted-in by default. |
| 820 | 777 | // Sticky position support was backported to WordPress 6.2 in https://core.trac.wordpress.org/ticket/57618. |
| @@ -1065,14 +1022,13 @@ | ||
| 1065 | 1022 | $schema = array(); |
| 1066 | 1023 | $schema_styles_elements = array(); |
| 1067 | 1024 | |
| 1068 | 1025 | /* |
| 1069 | - * Set allowed element pseudo selectors and responsive breakpoint states. | |
| 1026 | + * Set allowed element pseudo selectors based on per element allow list. | |
| 1070 | 1027 | * Target data structure in schema: |
| 1071 | 1028 | * e.g. |
| 1072 | 1029 | * - top level elements: `$schema['styles']['elements']['link'][':hover']`. |
| 1073 | 1030 | * - block level elements: `$schema['styles']['blocks']['core/button']['elements']['link'][':hover']`. |
| 1074 | - * - block responsive elements: `$schema['styles']['blocks']['core/button']['tablet']['elements']['link'][':hover']`. | |
| 1075 | 1031 | */ |
| 1076 | 1032 | foreach ( $valid_element_names as $element ) { |
| 1077 | 1033 | $schema_styles_elements[ $element ] = $styles_non_top_level; |
| 1078 | 1034 | |
| @@ -1080,13 +1036,8 @@ | ||
| 1080 | 1036 | foreach ( static::VALID_ELEMENT_PSEUDO_SELECTORS[ $element ] as $pseudo_selector ) { |
| 1081 | 1037 | $schema_styles_elements[ $element ][ $pseudo_selector ] = $styles_non_top_level; |
| 1082 | 1038 | } |
| 1083 | 1039 | } |
| 1084 | - | |
| 1085 | - // Add responsive breakpoint states for elements. | |
| 1086 | - foreach ( array_keys( static::RESPONSIVE_BREAKPOINTS ) as $breakpoint_state ) { | |
| 1087 | - $schema_styles_elements[ $element ][ $breakpoint_state ] = $styles_non_top_level; | |
| 1088 | - } | |
| 1089 | 1040 | } |
| 1090 | 1041 | |
| 1091 | 1042 | $schema_styles_blocks = array(); |
| 1092 | 1043 | $schema_settings_blocks = array(); |
| @@ -1092,15 +1043,15 @@ | ||
| 1092 | 1043 | $schema_settings_blocks = array(); |
| 1093 | 1044 | |
| 1094 | 1045 | /* |
| 1095 | 1046 | * Generate a schema for blocks. |
| 1096 | - * - Block styles can contain `elements`, `variations`, and responsive breakpoint state definitions. | |
| 1047 | + * - Block styles can contain `elements` & `variations` definitions. | |
| 1097 | 1048 | * - Variations definitions cannot be nested. |
| 1098 | - * - Variations can contain styles for inner `blocks`, `elements`, and responsive breakpoint states. | |
| 1099 | - * - Variation inner `blocks` styles can contain `elements` and responsive breakpoint states. | |
| 1049 | + * - Variations can contain styles for inner `blocks`. | |
| 1050 | + * - Variation inner `blocks` styles can contain `elements`. | |
| 1100 | 1051 | * |
| 1101 | - * As each variation needs both a `blocks` schema and responsive `blocks` schemas | |
| 1102 | - * for further nested inner `blocks`, the overall schema is generated in multiple passes. | |
| 1052 | + * As each variation needs a `blocks` schema but further nested | |
| 1053 | + * inner `blocks`, the overall schema will be generated in multiple passes. | |
| 1103 | 1054 | */ |
| 1104 | 1055 | foreach ( $valid_block_names as $block ) { |
| 1105 | 1056 | $schema_settings_blocks[ $block ] = static::VALID_SETTINGS; |
| 1106 | 1057 | $schema_styles_blocks[ $block ] = $styles_non_top_level; |
| @@ -1105,20 +1056,8 @@ | ||
| 1105 | 1056 | $schema_settings_blocks[ $block ] = static::VALID_SETTINGS; |
| 1106 | 1057 | $schema_styles_blocks[ $block ] = $styles_non_top_level; |
| 1107 | 1058 | $schema_styles_blocks[ $block ]['elements'] = $schema_styles_elements; |
| 1108 | 1059 | |
| 1109 | - // Add responsive breakpoint states for all blocks. | |
| 1110 | - foreach ( array_keys( static::RESPONSIVE_BREAKPOINTS ) as $breakpoint_state ) { | |
| 1111 | - $schema_styles_blocks[ $block ][ $breakpoint_state ] = $styles_non_top_level; | |
| 1112 | - $schema_styles_blocks[ $block ][ $breakpoint_state ]['elements'] = $schema_styles_elements; | |
| 1113 | - | |
| 1114 | - if ( isset( static::VALID_BLOCK_PSEUDO_SELECTORS[ $block ] ) ) { | |
| 1115 | - foreach ( static::VALID_BLOCK_PSEUDO_SELECTORS[ $block ] as $pseudo_selector ) { | |
| 1116 | - $schema_styles_blocks[ $block ][ $breakpoint_state ][ $pseudo_selector ] = $styles_non_top_level; | |
| 1117 | - } | |
| 1118 | - } | |
| 1119 | - } | |
| 1120 | - | |
| 1121 | 1060 | // Add pseudo-selectors for blocks that support them. |
| 1122 | 1061 | if ( isset( static::VALID_BLOCK_PSEUDO_SELECTORS[ $block ] ) ) { |
| 1123 | 1062 | foreach ( static::VALID_BLOCK_PSEUDO_SELECTORS[ $block ] as $pseudo_selector ) { |
| 1124 | 1063 | $schema_styles_blocks[ $block ][ $pseudo_selector ] = $styles_non_top_level; |
| @@ -1123,23 +1062,8 @@ | ||
| 1123 | 1062 | foreach ( static::VALID_BLOCK_PSEUDO_SELECTORS[ $block ] as $pseudo_selector ) { |
| 1124 | 1063 | $schema_styles_blocks[ $block ][ $pseudo_selector ] = $styles_non_top_level; |
| 1125 | 1064 | } |
| 1126 | 1065 | } |
| 1127 | - | |
| 1128 | - // Add custom states for blocks that support them (e.g. '@current' for navigation). | |
| 1129 | - if ( isset( static::VALID_BLOCK_CUSTOM_STATES[ $block ] ) ) { | |
| 1130 | - foreach ( static::VALID_BLOCK_CUSTOM_STATES[ $block ] as $custom_state ) { | |
| 1131 | - $custom_state_schema = $styles_non_top_level; | |
| 1132 | - // The same pseudo-selectors valid for the block at the top level | |
| 1133 | - // are also valid within each custom state. | |
| 1134 | - if ( isset( static::VALID_BLOCK_PSEUDO_SELECTORS[ $block ] ) ) { | |
| 1135 | - foreach ( static::VALID_BLOCK_PSEUDO_SELECTORS[ $block ] as $pseudo ) { | |
| 1136 | - $custom_state_schema[ $pseudo ] = $styles_non_top_level; | |
| 1137 | - } | |
| 1138 | - } | |
| 1139 | - $schema_styles_blocks[ $block ][ $custom_state ] = $custom_state_schema; | |
| 1140 | - } | |
| 1141 | - } | |
| 1142 | 1066 | } |
| 1143 | 1067 | |
| 1144 | 1068 | $block_style_variation_styles = static::VALID_STYLES; |
| 1145 | 1069 | $block_style_variation_styles['blocks'] = $schema_styles_blocks; |
| @@ -1163,21 +1087,8 @@ | ||
| 1163 | 1087 | if ( ! empty( $style_variation_names ) ) { |
| 1164 | 1088 | foreach ( $style_variation_names as $variation_name ) { |
| 1165 | 1089 | $variation_schema = $block_style_variation_styles; |
| 1166 | 1090 | |
| 1167 | - // Add responsive breakpoint states to block style variations. | |
| 1168 | - foreach ( array_keys( static::RESPONSIVE_BREAKPOINTS ) as $breakpoint_state ) { | |
| 1169 | - $variation_schema[ $breakpoint_state ] = $styles_non_top_level; | |
| 1170 | - $variation_schema[ $breakpoint_state ]['elements'] = $schema_styles_elements; | |
| 1171 | - $variation_schema[ $breakpoint_state ]['blocks'] = $schema_styles_blocks; | |
| 1172 | - | |
| 1173 | - if ( isset( static::VALID_BLOCK_PSEUDO_SELECTORS[ $block ] ) ) { | |
| 1174 | - foreach ( static::VALID_BLOCK_PSEUDO_SELECTORS[ $block ] as $pseudo_selector ) { | |
| 1175 | - $variation_schema[ $breakpoint_state ][ $pseudo_selector ] = $styles_non_top_level; | |
| 1176 | - } | |
| 1177 | - } | |
| 1178 | - } | |
| 1179 | - | |
| 1180 | 1091 | // Add pseudo-selectors to variations for blocks that support them. |
| 1181 | 1092 | if ( isset( static::VALID_BLOCK_PSEUDO_SELECTORS[ $block ] ) ) { |
| 1182 | 1093 | foreach ( static::VALID_BLOCK_PSEUDO_SELECTORS[ $block ] as $pseudo_selector ) { |
| 1183 | 1094 | $variation_schema[ $pseudo_selector ] = $styles_non_top_level; |
| @@ -1378,13 +1289,8 @@ | ||
| 1378 | 1289 | |
| 1379 | 1290 | if ( ! empty( $style_selectors ) ) { |
| 1380 | 1291 | static::$blocks_metadata[ $block_name ]['styleVariations'] = $style_selectors; |
| 1381 | 1292 | } |
| 1382 | - | |
| 1383 | - // If the block has custom states defined in block.json, store their selectors. | |
| 1384 | - if ( ! empty( $block_type->selectors['states'] ) && is_array( $block_type->selectors['states'] ) ) { | |
| 1385 | - static::$blocks_metadata[ $block_name ]['states'] = $block_type->selectors['states']; | |
| 1386 | - } | |
| 1387 | 1293 | } |
| 1388 | 1294 | |
| 1389 | 1295 | return static::$blocks_metadata; |
| 1390 | 1296 | } |
| @@ -1979,13 +1885,8 @@ | ||
| 1979 | 1885 | } |
| 1980 | 1886 | } |
| 1981 | 1887 | } |
| 1982 | 1888 | } |
| 1983 | - | |
| 1984 | - if ( ! empty( $options['media_query'] ) && ! empty( $block_rules ) ) { | |
| 1985 | - $block_rules = $options['media_query'] . '{' . $block_rules . '}'; | |
| 1986 | - } | |
| 1987 | - | |
| 1988 | 1889 | return $block_rules; |
| 1989 | 1890 | } |
| 1990 | 1891 | |
| 1991 | 1892 | /** |
| @@ -2146,9 +2047,8 @@ | ||
| 2146 | 2047 | * Given a selector and a declaration list, |
| 2147 | 2048 | * creates the corresponding ruleset. |
| 2148 | 2049 | * |
| 2149 | 2050 | * @since 5.8.0 |
| 2150 | - * @since 7.1.0 Skip declarations whose value is not a plain string (booleans, arrays, objects, etc.). | |
| 2151 | 2051 | * |
| 2152 | 2052 | * @param string $selector CSS selector. |
| 2153 | 2053 | * @param array $declarations List of declarations. |
| 2154 | 2054 | * @return string The resulting CSS ruleset. |
| @@ -2160,20 +2060,9 @@ | ||
| 2160 | 2060 | |
| 2161 | 2061 | $declaration_block = array_reduce( |
| 2162 | 2062 | $declarations, |
| 2163 | 2063 | static function ( $carry, $element ) { |
| 2164 | - $value = $element['value']; | |
| 2165 | - | |
| 2166 | - if ( is_numeric( $value ) ) { | |
| 2167 | - $value = (string) $value; | |
| 2168 | - } | |
| 2169 | - | |
| 2170 | - if ( ! is_string( $value ) ) { | |
| 2171 | - return $carry; | |
| 2172 | - } | |
| 2173 | - | |
| 2174 | - return $carry .= $element['name'] . ': ' . $value . ';'; | |
| 2175 | - }, | |
| 2064 | + return $carry .= $element['name'] . ': ' . $element['value'] . ';'; }, | |
| 2176 | 2065 | '' |
| 2177 | 2066 | ); |
| 2178 | 2067 | |
| 2179 | 2068 | return $selector . '{' . $declaration_block . '}'; |
| @@ -2612,23 +2501,14 @@ | ||
| 2612 | 2501 | * If the value is a URL, it will be converted to a CSS `url()` value. |
| 2613 | 2502 | * For an uploaded image (images with a database ID), apply size and position |
| 2614 | 2503 | * defaults equal to those applied in block supports in lib/background.php. |
| 2615 | 2504 | */ |
| 2616 | - if ( 'background-image' === $css_property ) { | |
| 2617 | - $background_image_input = array(); | |
| 2618 | - if ( ! empty( $value ) ) { | |
| 2619 | - $background_image_input['backgroundImage'] = $value; | |
| 2620 | - } | |
| 2621 | - $gradient_value = $styles['background']['gradient'] ?? null; | |
| 2622 | - if ( ! empty( $gradient_value ) ) { | |
| 2623 | - $background_image_input['gradient'] = $gradient_value; | |
| 2624 | - } | |
| 2625 | - if ( ! empty( $background_image_input ) ) { | |
| 2626 | - $background_styles = gutenberg_style_engine_get_styles( | |
| 2627 | - array( 'background' => $background_image_input ) | |
| 2628 | - ); | |
| 2629 | - $value = $background_styles['declarations'][ $css_property ] ?? null; | |
| 2630 | - } | |
| 2505 | + if ( 'background-image' === $css_property && ! empty( $value ) ) { | |
| 2506 | + $background_styles = gutenberg_style_engine_get_styles( | |
| 2507 | + array( 'background' => array( 'backgroundImage' => $value ) ) | |
| 2508 | + ); | |
| 2509 | + | |
| 2510 | + $value = $background_styles['declarations'][ $css_property ]; | |
| 2631 | 2511 | } |
| 2632 | 2512 | if ( empty( $value ) && static::ROOT_BLOCK_SELECTOR !== $selector && ! empty( $styles['background']['backgroundImage']['id'] ) ) { |
| 2633 | 2513 | if ( 'background-size' === $css_property ) { |
| 2634 | 2514 | $value = 'cover'; |
| @@ -3144,209 +3024,61 @@ | ||
| 3144 | 3024 | 'name' => $name, |
| 3145 | 3025 | 'path' => $node_path, |
| 3146 | 3026 | 'selector' => $selector, |
| 3147 | 3027 | 'selectors' => $feature_selectors, |
| 3148 | - 'elements' => $selectors[ $name ]['elements'] ?? array(), | |
| 3149 | 3028 | 'duotone' => $duotone_selector, |
| 3150 | 3029 | 'variations' => $variation_selectors, |
| 3151 | 3030 | 'css' => $selector, |
| 3152 | 3031 | ); |
| 3153 | 3032 | |
| 3154 | - // Responsive block nodes: emit one node per breakpoint that has styles. | |
| 3155 | - // These are rendered immediately after the base block node so that | |
| 3156 | - // the cascade order is: .block{} → @media{.block{}} | |
| 3157 | - foreach ( array_keys( static::RESPONSIVE_BREAKPOINTS ) as $breakpoint ) { | |
| 3158 | - if ( isset( $theme_json['styles']['blocks'][ $name ][ $breakpoint ] ) ) { | |
| 3159 | - $nodes[] = array( | |
| 3160 | - 'name' => $name, | |
| 3161 | - 'path' => array( 'styles', 'blocks', $name, $breakpoint ), | |
| 3162 | - 'media_query' => static::RESPONSIVE_BREAKPOINTS[ $breakpoint ], | |
| 3163 | - 'selector' => $selector, | |
| 3164 | - 'selectors' => $feature_selectors, | |
| 3165 | - 'elements' => $selectors[ $name ]['elements'] ?? array(), | |
| 3166 | - 'variations' => $variation_selectors, | |
| 3167 | - 'css' => $selector, | |
| 3168 | - ); | |
| 3169 | - } | |
| 3170 | - } | |
| 3171 | - | |
| 3172 | 3033 | // Handle any pseudo selectors for the block. |
| 3173 | 3034 | if ( isset( static::VALID_BLOCK_PSEUDO_SELECTORS[ $name ] ) ) { |
| 3174 | 3035 | foreach ( static::VALID_BLOCK_PSEUDO_SELECTORS[ $name ] as $pseudo_selector ) { |
| 3175 | - $has_pseudo = isset( $theme_json['styles']['blocks'][ $name ][ $pseudo_selector ] ); | |
| 3176 | - $has_responsive_pseudo = false; | |
| 3177 | - foreach ( array_keys( static::RESPONSIVE_BREAKPOINTS ) as $breakpoint ) { | |
| 3178 | - if ( isset( $theme_json['styles']['blocks'][ $name ][ $breakpoint ][ $pseudo_selector ] ) ) { | |
| 3179 | - $has_responsive_pseudo = true; | |
| 3180 | - break; | |
| 3181 | - } | |
| 3182 | - } | |
| 3183 | - | |
| 3184 | - if ( ! $has_pseudo && ! $has_responsive_pseudo ) { | |
| 3185 | - continue; | |
| 3186 | - } | |
| 3187 | - | |
| 3188 | - /* | |
| 3189 | - * Append the pseudo-selector to each feature selector so that | |
| 3190 | - * get_feature_declarations_for_node generates CSS scoped to the | |
| 3191 | - * pseudo-state (e.g. '.wp-block-button:hover') rather than the | |
| 3192 | - * default state (e.g. '.wp-block-button'). | |
| 3193 | - */ | |
| 3194 | - $pseudo_feature_selectors = array(); | |
| 3195 | - foreach ( $feature_selectors ?? array() as $feature => $feature_selector ) { | |
| 3196 | - if ( is_array( $feature_selector ) ) { | |
| 3197 | - $pseudo_feature_selectors[ $feature ] = array(); | |
| 3198 | - foreach ( $feature_selector as $subfeature => $subfeature_selector ) { | |
| 3199 | - $pseudo_feature_selectors[ $feature ][ $subfeature ] = static::append_to_selector( $subfeature_selector, $pseudo_selector ); | |
| 3200 | - } | |
| 3201 | - } else { | |
| 3202 | - $pseudo_feature_selectors[ $feature ] = static::append_to_selector( $feature_selector, $pseudo_selector ); | |
| 3203 | - } | |
| 3204 | - } | |
| 3205 | - | |
| 3206 | - if ( $has_pseudo ) { | |
| 3036 | + if ( isset( $theme_json['styles']['blocks'][ $name ][ $pseudo_selector ] ) ) { | |
| 3207 | 3037 | $nodes[] = array( |
| 3208 | 3038 | 'name' => $name, |
| 3209 | 3039 | 'path' => array( 'styles', 'blocks', $name, $pseudo_selector ), |
| 3210 | 3040 | 'selector' => static::append_to_selector( $selector, $pseudo_selector ), |
| 3211 | - 'selectors' => $pseudo_feature_selectors, | |
| 3212 | - 'elements' => $selectors[ $name ]['elements'] ?? array(), | |
| 3041 | + 'selectors' => $feature_selectors, | |
| 3213 | 3042 | 'duotone' => $duotone_selector, |
| 3214 | 3043 | 'variations' => $variation_selectors, |
| 3215 | 3044 | 'css' => static::append_to_selector( $selector, $pseudo_selector ), |
| 3216 | 3045 | ); |
| 3217 | 3046 | } |
| 3218 | - | |
| 3219 | - // Responsive pseudo nodes: emit one node per breakpoint that has | |
| 3220 | - // this pseudo state, immediately after the default pseudo node. | |
| 3221 | - // Cascade order: .block:hover{} → @media{.block:hover{}} | |
| 3222 | - foreach ( array_keys( static::RESPONSIVE_BREAKPOINTS ) as $breakpoint ) { | |
| 3223 | - if ( isset( $theme_json['styles']['blocks'][ $name ][ $breakpoint ][ $pseudo_selector ] ) ) { | |
| 3224 | - $nodes[] = array( | |
| 3225 | - 'name' => $name, | |
| 3226 | - 'path' => array( 'styles', 'blocks', $name, $breakpoint, $pseudo_selector ), | |
| 3227 | - 'media_query' => static::RESPONSIVE_BREAKPOINTS[ $breakpoint ], | |
| 3228 | - 'selector' => static::append_to_selector( $selector, $pseudo_selector ), | |
| 3229 | - 'selectors' => $pseudo_feature_selectors, | |
| 3230 | - 'elements' => $selectors[ $name ]['elements'] ?? array(), | |
| 3231 | - 'variations' => $variation_selectors, | |
| 3232 | - 'css' => static::append_to_selector( $selector, $pseudo_selector ), | |
| 3233 | - ); | |
| 3234 | - } | |
| 3235 | - } | |
| 3236 | 3047 | } |
| 3237 | 3048 | } |
| 3238 | - | |
| 3239 | - // Handle custom states (e.g. '@current' for navigation). | |
| 3240 | - if ( isset( static::VALID_BLOCK_CUSTOM_STATES[ $name ] ) ) { | |
| 3241 | - foreach ( static::VALID_BLOCK_CUSTOM_STATES[ $name ] as $custom_state ) { | |
| 3242 | - if ( | |
| 3243 | - isset( $theme_json['styles']['blocks'][ $name ][ $custom_state ] ) && | |
| 3244 | - isset( $selectors[ $name ]['states'][ $custom_state ] ) | |
| 3245 | - ) { | |
| 3246 | - $custom_css_selector = $selectors[ $name ]['states'][ $custom_state ]; | |
| 3247 | - $nodes[] = array( | |
| 3248 | - 'name' => $name, | |
| 3249 | - 'path' => array( 'styles', 'blocks', $name, $custom_state ), | |
| 3250 | - 'selector' => $custom_css_selector, | |
| 3251 | - 'selectors' => $feature_selectors, | |
| 3252 | - 'elements' => $selectors[ $name ]['elements'] ?? array(), | |
| 3253 | - 'duotone' => $duotone_selector, | |
| 3254 | - 'variations' => $variation_selectors, | |
| 3255 | - 'css' => $custom_css_selector, | |
| 3256 | - ); | |
| 3257 | - | |
| 3258 | - // Sub-pseudo-selectors within the custom state. | |
| 3259 | - if ( isset( static::VALID_BLOCK_PSEUDO_SELECTORS[ $name ] ) ) { | |
| 3260 | - foreach ( static::VALID_BLOCK_PSEUDO_SELECTORS[ $name ] as $pseudo ) { | |
| 3261 | - if ( isset( $theme_json['styles']['blocks'][ $name ][ $custom_state ][ $pseudo ] ) ) { | |
| 3262 | - $compound_css_selector = static::append_to_selector( $custom_css_selector, $pseudo ); | |
| 3263 | - $nodes[] = array( | |
| 3264 | - 'name' => $name, | |
| 3265 | - 'path' => array( 'styles', 'blocks', $name, $custom_state, $pseudo ), | |
| 3266 | - 'selector' => $compound_css_selector, | |
| 3267 | - 'selectors' => $feature_selectors, | |
| 3268 | - 'elements' => $selectors[ $name ]['elements'] ?? array(), | |
| 3269 | - 'duotone' => $duotone_selector, | |
| 3270 | - 'variations' => $variation_selectors, | |
| 3271 | - 'css' => $compound_css_selector, | |
| 3272 | - ); | |
| 3273 | - } | |
| 3274 | - } | |
| 3275 | - } | |
| 3276 | - } | |
| 3277 | - } | |
| 3278 | - } | |
| 3279 | 3049 | } |
| 3280 | 3050 | if ( isset( $theme_json['styles']['blocks'][ $name ]['elements'] ) ) { |
| 3281 | 3051 | foreach ( $theme_json['styles']['blocks'][ $name ]['elements'] as $element => $node ) { |
| 3282 | - $element_path = array( 'styles', 'blocks', $name, 'elements', $element ); | |
| 3052 | + $node_path = array( 'styles', 'blocks', $name, 'elements', $element ); | |
| 3283 | 3053 | if ( $include_node_paths_only ) { |
| 3284 | 3054 | $nodes[] = array( |
| 3285 | - 'path' => $element_path, | |
| 3055 | + 'path' => $node_path, | |
| 3286 | 3056 | ); |
| 3287 | 3057 | continue; |
| 3288 | 3058 | } |
| 3289 | 3059 | |
| 3290 | - $element_selector = $selectors[ $name ]['elements'][ $element ]; | |
| 3291 | - | |
| 3292 | 3060 | $nodes[] = array( |
| 3293 | - 'path' => $element_path, | |
| 3294 | - 'selector' => $element_selector, | |
| 3061 | + 'path' => $node_path, | |
| 3062 | + 'selector' => $selectors[ $name ]['elements'][ $element ], | |
| 3295 | 3063 | ); |
| 3296 | 3064 | |
| 3297 | - // Responsive element nodes: one node per breakpoint that has | |
| 3298 | - // styles for this element. Cascade: a{} → @media{a{}} | |
| 3299 | - foreach ( array_keys( static::RESPONSIVE_BREAKPOINTS ) as $breakpoint ) { | |
| 3300 | - if ( isset( $theme_json['styles']['blocks'][ $name ][ $breakpoint ]['elements'][ $element ] ) ) { | |
| 3301 | - $nodes[] = array( | |
| 3302 | - 'path' => array( 'styles', 'blocks', $name, $breakpoint, 'elements', $element ), | |
| 3303 | - 'selector' => $element_selector, | |
| 3304 | - 'media_query' => static::RESPONSIVE_BREAKPOINTS[ $breakpoint ], | |
| 3305 | - ); | |
| 3306 | - } | |
| 3307 | - } | |
| 3308 | - | |
| 3309 | 3065 | // Handle any pseudo selectors for the element. |
| 3310 | 3066 | if ( isset( static::VALID_ELEMENT_PSEUDO_SELECTORS[ $element ] ) ) { |
| 3311 | 3067 | foreach ( static::VALID_ELEMENT_PSEUDO_SELECTORS[ $element ] as $pseudo_selector ) { |
| 3312 | - // Create element pseudo node if default or any responsive breakpoint has the pseudo. | |
| 3313 | - $has_element_pseudo = isset( $theme_json['styles']['blocks'][ $name ]['elements'][ $element ][ $pseudo_selector ] ); | |
| 3314 | - if ( ! $has_element_pseudo ) { | |
| 3315 | - foreach ( array_keys( static::RESPONSIVE_BREAKPOINTS ) as $bp ) { | |
| 3316 | - if ( isset( $theme_json['styles']['blocks'][ $name ][ $bp ]['elements'][ $element ][ $pseudo_selector ] ) ) { | |
| 3317 | - $has_element_pseudo = true; | |
| 3318 | - break; | |
| 3319 | - } | |
| 3320 | - } | |
| 3321 | - } | |
| 3322 | - | |
| 3323 | - if ( $has_element_pseudo ) { | |
| 3324 | - $element_pseudo_path = array( 'styles', 'blocks', $name, 'elements', $element ); | |
| 3068 | + if ( isset( $theme_json['styles']['blocks'][ $name ]['elements'][ $element ][ $pseudo_selector ] ) ) { | |
| 3069 | + $node_path = array( 'styles', 'blocks', $name, 'elements', $element ); | |
| 3325 | 3070 | if ( $include_node_paths_only ) { |
| 3326 | 3071 | $nodes[] = array( |
| 3327 | - 'path' => $element_pseudo_path, | |
| 3072 | + 'path' => $node_path, | |
| 3328 | 3073 | ); |
| 3329 | 3074 | continue; |
| 3330 | 3075 | } |
| 3331 | 3076 | |
| 3332 | 3077 | $nodes[] = array( |
| 3333 | - 'path' => $element_pseudo_path, | |
| 3334 | - 'selector' => static::append_to_selector( $element_selector, $pseudo_selector ), | |
| 3078 | + 'path' => $node_path, | |
| 3079 | + 'selector' => static::append_to_selector( $selectors[ $name ]['elements'][ $element ], $pseudo_selector ), | |
| 3335 | 3080 | ); |
| 3336 | - | |
| 3337 | - // Responsive element pseudo nodes: one node per breakpoint | |
| 3338 | - // that has this pseudo state for this element. | |
| 3339 | - // Cascade: a:hover{} → @media{a:hover{}} | |
| 3340 | - foreach ( array_keys( static::RESPONSIVE_BREAKPOINTS ) as $breakpoint ) { | |
| 3341 | - if ( isset( $theme_json['styles']['blocks'][ $name ][ $breakpoint ]['elements'][ $element ][ $pseudo_selector ] ) ) { | |
| 3342 | - $nodes[] = array( | |
| 3343 | - 'path' => array( 'styles', 'blocks', $name, $breakpoint, 'elements', $element ), | |
| 3344 | - 'selector' => static::append_to_selector( $element_selector, $pseudo_selector ), | |
| 3345 | - 'media_query' => static::RESPONSIVE_BREAKPOINTS[ $breakpoint ], | |
| 3346 | - ); | |
| 3347 | - } | |
| 3348 | - } | |
| 3349 | 3081 | } |
| 3350 | 3082 | } |
| 3351 | 3083 | } |
| 3352 | 3084 | } |
| @@ -3371,9 +3103,8 @@ | ||
| 3371 | 3103 | $use_root_padding = isset( $this->theme_json['settings']['useRootPaddingAwareAlignments'] ) && true === $this->theme_json['settings']['useRootPaddingAwareAlignments']; |
| 3372 | 3104 | $selector = $block_metadata['selector']; |
| 3373 | 3105 | $settings = $this->theme_json['settings'] ?? null; |
| 3374 | 3106 | $is_root_selector = static::ROOT_BLOCK_SELECTOR === $selector; |
| 3375 | - $media_query = $block_metadata['media_query'] ?? null; | |
| 3376 | 3107 | |
| 3377 | 3108 | $feature_declarations = static::get_feature_declarations_for_node( $block_metadata, $node ); |
| 3378 | 3109 | |
| 3379 | 3110 | // Update text indent selector for paragraph blocks based on the textIndent setting. |
| @@ -3378,21 +3109,17 @@ | ||
| 3378 | 3109 | |
| 3379 | 3110 | // Update text indent selector for paragraph blocks based on the textIndent setting. |
| 3380 | 3111 | $block_name = $block_metadata['name'] ?? null; |
| 3381 | 3112 | $feature_declarations = static::update_paragraph_text_indent_selector( $feature_declarations, $settings, $block_name ); |
| 3382 | - $block_elements = $block_metadata['elements'] ?? array(); | |
| 3383 | 3113 | |
| 3384 | 3114 | // Update button width declarations for percentage values to use calc() with block gap. |
| 3385 | 3115 | $feature_declarations = static::update_button_width_declarations( $feature_declarations, $settings ); |
| 3386 | 3116 | |
| 3387 | 3117 | // If there are style variations, generate the declarations for them, including any feature selectors the block may have. |
| 3388 | - // Responsive nodes (those with a media_query) do not process variations — variation responsive | |
| 3389 | - // CSS is handled by the variation's own responsive nodes or the existing variation loop. | |
| 3390 | 3118 | $style_variation_declarations = array(); |
| 3391 | 3119 | $style_variation_custom_css = array(); |
| 3392 | - $style_variation_responsive_css = array(); | |
| 3393 | 3120 | $style_variation_layout_metadata = array(); |
| 3394 | - if ( ! $media_query && ! empty( $block_metadata['variations'] ) ) { | |
| 3121 | + if ( ! empty( $block_metadata['variations'] ) ) { | |
| 3395 | 3122 | foreach ( $block_metadata['variations'] as $style_variation ) { |
| 3396 | 3123 | $style_variation_node = _wp_array_get( $this->theme_json, $style_variation['path'], array() ); |
| 3397 | 3124 | $clean_style_variation_selector = trim( $style_variation['selector'] ); |
| 3398 | 3125 | |
| @@ -3452,139 +3179,11 @@ | ||
| 3452 | 3179 | 'metadata' => $variation_metadata_with_selector, |
| 3453 | 3180 | 'node' => $style_variation_node, |
| 3454 | 3181 | ); |
| 3455 | 3182 | } |
| 3456 | - | |
| 3457 | - // Store responsive breakpoint CSS for the style variation. | |
| 3458 | - // This includes both base properties and feature-level selectors. | |
| 3459 | - $variation_responsive_css = ''; | |
| 3460 | - | |
| 3461 | - foreach ( array_keys( static::RESPONSIVE_BREAKPOINTS ) as $breakpoint ) { | |
| 3462 | - if ( ! isset( $style_variation_node[ $breakpoint ] ) ) { | |
| 3463 | - continue; | |
| 3464 | - } | |
| 3465 | - | |
| 3466 | - $breakpoint_node = $style_variation_node[ $breakpoint ]; | |
| 3467 | - $breakpoint_media = static::RESPONSIVE_BREAKPOINTS[ $breakpoint ]; | |
| 3468 | - // Process feature-level declarations for this breakpoint. | |
| 3469 | - $breakpoint_feature_declarations = static::get_feature_declarations_for_node( $block_metadata, $breakpoint_node ); | |
| 3470 | - $breakpoint_feature_declarations = static::update_paragraph_text_indent_selector( $breakpoint_feature_declarations, $settings, $block_name ); | |
| 3471 | - $breakpoint_feature_declarations = static::update_button_width_declarations( $breakpoint_feature_declarations, $settings ); | |
| 3472 | - foreach ( $breakpoint_feature_declarations as $feature_selector => $feature_decl ) { | |
| 3473 | - $clean_feature_selector = preg_replace( '/,\s+/', ',', $feature_selector ); | |
| 3474 | - $shortened_selector = str_replace( $block_metadata['selector'], '', $clean_feature_selector ); | |
| 3475 | - | |
| 3476 | - if ( $block_metadata['selector'] && ! str_contains( $clean_feature_selector, $block_metadata['selector'] ) ) { | |
| 3477 | - /* | |
| 3478 | - * Feature selector is block-level (e.g. `.wp-block-button` for | |
| 3479 | - * dimensions/width) — apply the variation class directly to it. | |
| 3480 | - */ | |
| 3481 | - $feature_element_selector = str_replace( $shortened_selector, '', $clean_style_variation_selector ); | |
| 3482 | - $combined_selectors = str_replace( $feature_element_selector, '', $clean_style_variation_selector ); | |
| 3483 | - } else { | |
| 3484 | - // Prepend the variation selector to the current selector. | |
| 3485 | - $split_selectors = explode( ',', $shortened_selector ); | |
| 3486 | - $updated_selectors = array_map( | |
| 3487 | - static function ( $split_selector ) use ( $clean_style_variation_selector ) { | |
| 3488 | - return $clean_style_variation_selector . $split_selector; | |
| 3489 | - }, | |
| 3490 | - $split_selectors | |
| 3491 | - ); | |
| 3492 | - $combined_selectors = implode( ',', $updated_selectors ); | |
| 3493 | - } | |
| 3494 | - | |
| 3495 | - $feature_ruleset = static::to_ruleset( ':root :where(' . $combined_selectors . ')', $feature_decl ); | |
| 3496 | - $variation_responsive_css .= $breakpoint_media . '{' . $feature_ruleset . '}'; | |
| 3497 | - } | |
| 3498 | - | |
| 3499 | - // Process base properties for this breakpoint. | |
| 3500 | - $breakpoint_declarations = static::compute_style_properties( $breakpoint_node, $settings, null, $this->theme_json ); | |
| 3501 | - if ( ! empty( $breakpoint_declarations ) ) { | |
| 3502 | - $base_ruleset = static::to_ruleset( ':root :where(' . $style_variation['selector'] . ')', $breakpoint_declarations ); | |
| 3503 | - $variation_responsive_css .= $breakpoint_media . '{' . $base_ruleset . '}'; | |
| 3504 | - } | |
| 3505 | - | |
| 3506 | - $breakpoint_pseudo_declarations = static::process_pseudo_selectors( $breakpoint_node, $style_variation['selector'], $settings, $block_name ); | |
| 3507 | - foreach ( $breakpoint_pseudo_declarations as $pseudo_selector => $pseudo_declarations ) { | |
| 3508 | - if ( empty( $pseudo_declarations ) ) { | |
| 3509 | - continue; | |
| 3510 | - } | |
| 3511 | - $pseudo_ruleset = static::to_ruleset( ':root :where(' . $pseudo_selector . ')', $pseudo_declarations ); | |
| 3512 | - $variation_responsive_css .= $breakpoint_media . '{' . $pseudo_ruleset . '}'; | |
| 3513 | - } | |
| 3514 | - | |
| 3515 | - // Process custom CSS for this breakpoint. | |
| 3516 | - if ( isset( $breakpoint_node['css'] ) ) { | |
| 3517 | - $breakpoint_custom_css = static::process_blocks_custom_css( $breakpoint_node['css'], $style_variation['selector'] ); | |
| 3518 | - $variation_responsive_css .= $breakpoint_media . '{' . $breakpoint_custom_css . '}'; | |
| 3519 | - } | |
| 3520 | - | |
| 3521 | - // Process blockGap responsive layout styles for this variation. | |
| 3522 | - if ( isset( $breakpoint_node['spacing']['blockGap'] ) ) { | |
| 3523 | - $variation_layout_metadata = $style_variation; | |
| 3524 | - $variation_layout_metadata['selector'] = $style_variation['selector'] . $block_metadata['css']; | |
| 3525 | - $variation_responsive_css .= $this->get_layout_styles( | |
| 3526 | - $variation_layout_metadata, | |
| 3527 | - array( | |
| 3528 | - 'node' => $breakpoint_node, | |
| 3529 | - 'media_query' => $breakpoint_media, | |
| 3530 | - ) | |
| 3531 | - ); | |
| 3532 | - } | |
| 3533 | - | |
| 3534 | - // Process nested element styles for this breakpoint state. | |
| 3535 | - if ( isset( $breakpoint_node['elements'] ) && ! empty( $block_elements ) ) { | |
| 3536 | - foreach ( $breakpoint_node['elements'] as $element_name => $element_node ) { | |
| 3537 | - if ( ! isset( $block_elements[ $element_name ] ) ) { | |
| 3538 | - continue; | |
| 3539 | - } | |
| 3540 | - | |
| 3541 | - $clean_element_selector = preg_replace( '/,\s+/', ',', $block_elements[ $element_name ] ); | |
| 3542 | - $shortened_selector = str_replace( $block_metadata['selector'], '', $clean_element_selector ); | |
| 3543 | - $split_selectors = explode( ',', $shortened_selector ); | |
| 3544 | - $updated_selectors = array_map( | |
| 3545 | - static function ( $split_selector ) use ( $clean_style_variation_selector ) { | |
| 3546 | - return $clean_style_variation_selector . $split_selector; | |
| 3547 | - }, | |
| 3548 | - $split_selectors | |
| 3549 | - ); | |
| 3550 | - $variation_element_selector = implode( ',', $updated_selectors ); | |
| 3551 | - | |
| 3552 | - $element_declarations = static::compute_style_properties( $element_node, $settings, null, $this->theme_json ); | |
| 3553 | - if ( ! empty( $element_declarations ) ) { | |
| 3554 | - $element_ruleset = static::to_ruleset( ':root :where(' . $variation_element_selector . ')', $element_declarations ); | |
| 3555 | - $variation_responsive_css .= $breakpoint_media . '{' . $element_ruleset . '}'; | |
| 3556 | - } | |
| 3557 | - | |
| 3558 | - if ( isset( $element_node['css'] ) ) { | |
| 3559 | - $element_custom_css = static::process_blocks_custom_css( $element_node['css'], $variation_element_selector ); | |
| 3560 | - $variation_responsive_css .= $breakpoint_media . '{' . $element_custom_css . '}'; | |
| 3561 | - } | |
| 3562 | - | |
| 3563 | - if ( isset( static::VALID_ELEMENT_PSEUDO_SELECTORS[ $element_name ] ) ) { | |
| 3564 | - foreach ( static::VALID_ELEMENT_PSEUDO_SELECTORS[ $element_name ] as $pseudo_selector ) { | |
| 3565 | - if ( ! isset( $element_node[ $pseudo_selector ] ) ) { | |
| 3566 | - continue; | |
| 3567 | - } | |
| 3568 | - | |
| 3569 | - $pseudo_declarations = static::compute_style_properties( $element_node[ $pseudo_selector ], $settings, null, $this->theme_json ); | |
| 3570 | - if ( empty( $pseudo_declarations ) ) { | |
| 3571 | - continue; | |
| 3572 | - } | |
| 3573 | - | |
| 3574 | - $pseudo_selector_ruleset = static::to_ruleset( ':root :where(' . static::append_to_selector( $variation_element_selector, $pseudo_selector ) . ')', $pseudo_declarations ); | |
| 3575 | - $variation_responsive_css .= $breakpoint_media . '{' . $pseudo_selector_ruleset . '}'; | |
| 3576 | - } | |
| 3577 | - } | |
| 3578 | - } | |
| 3579 | - } | |
| 3580 | - } | |
| 3581 | - | |
| 3582 | - if ( ! empty( $variation_responsive_css ) ) { | |
| 3583 | - $style_variation_responsive_css[ $style_variation['selector'] ] = $variation_responsive_css; | |
| 3584 | - } | |
| 3585 | 3183 | } |
| 3586 | 3184 | } |
| 3185 | + | |
| 3587 | 3186 | /* |
| 3588 | 3187 | * Get a reference to element name from path. |
| 3589 | 3188 | * $block_metadata['path'] = array( 'styles','elements','link' ); |
| 3590 | 3189 | * Make sure that $block_metadata['path'] describes an element node, like [ 'styles', 'element', 'link' ]. |
| @@ -3600,8 +3199,25 @@ | ||
| 3600 | 3199 | $element_pseudo_allowed = static::VALID_ELEMENT_PSEUDO_SELECTORS[ $current_element ]; |
| 3601 | 3200 | } |
| 3602 | 3201 | |
| 3603 | 3202 | /* |
| 3203 | + * Check if we're processing a block pseudo-selector. | |
| 3204 | + * $block_metadata['path'] = array( 'styles', 'blocks', 'core/button', ':hover' ); | |
| 3205 | + */ | |
| 3206 | + $is_processing_block_pseudo = false; | |
| 3207 | + $block_pseudo_selector = null; | |
| 3208 | + if ( in_array( 'blocks', $block_metadata['path'], true ) && count( $block_metadata['path'] ) >= 4 ) { | |
| 3209 | + $block_name = static::get_block_name_from_metadata_path( $block_metadata ); // 'core/button' | |
| 3210 | + $last_path_element = $block_metadata['path'][ count( $block_metadata['path'] ) - 1 ]; // ':hover' | |
| 3211 | + | |
| 3212 | + if ( isset( static::VALID_BLOCK_PSEUDO_SELECTORS[ $block_name ] ) && | |
| 3213 | + in_array( $last_path_element, static::VALID_BLOCK_PSEUDO_SELECTORS[ $block_name ], true ) ) { | |
| 3214 | + $is_processing_block_pseudo = true; | |
| 3215 | + $block_pseudo_selector = $last_path_element; | |
| 3216 | + } | |
| 3217 | + } | |
| 3218 | + | |
| 3219 | + /* | |
| 3604 | 3220 | * Check for allowed pseudo classes (e.g. ":hover") from the $selector ("a:hover"). |
| 3605 | 3221 | * This also resets the array keys. |
| 3606 | 3222 | */ |
| 3607 | 3223 | $pseudo_matches = array_values( |
| @@ -3628,14 +3244,17 @@ | ||
| 3628 | 3244 | isset( static::VALID_ELEMENT_PSEUDO_SELECTORS[ $current_element ] ) |
| 3629 | 3245 | && in_array( $pseudo_selector, static::VALID_ELEMENT_PSEUDO_SELECTORS[ $current_element ], true ) |
| 3630 | 3246 | ) { |
| 3631 | 3247 | $declarations = static::compute_style_properties( $node[ $pseudo_selector ], $settings, null, $this->theme_json, $selector, $use_root_padding ); |
| 3248 | + } elseif ( $is_processing_block_pseudo ) { | |
| 3249 | + // Process block pseudo-selector styles. | |
| 3250 | + // For block pseudo-selectors, we need to get the block data first, then access the pseudo-selector. | |
| 3251 | + $block_name = static::get_block_name_from_metadata_path( $block_metadata ); // 'core/button' | |
| 3252 | + $block_data = _wp_array_get( $this->theme_json, array( 'styles', 'blocks', $block_name ), array() ); | |
| 3253 | + $pseudo_data = $block_data[ $block_pseudo_selector ] ?? array(); | |
| 3254 | + | |
| 3255 | + $declarations = static::compute_style_properties( $pseudo_data, $settings, null, $this->theme_json, $selector, $use_root_padding ); | |
| 3632 | 3256 | } else { |
| 3633 | - /* | |
| 3634 | - * For block pseudo-selector nodes (e.g. ':hover'), $node has already had any | |
| 3635 | - * feature-selector properties (e.g. writingMode) removed by get_feature_declarations_for_node, | |
| 3636 | - * so those properties are not output twice. | |
| 3637 | - */ | |
| 3638 | 3257 | $declarations = static::compute_style_properties( $node, $settings, null, $this->theme_json, $selector, $use_root_padding ); |
| 3639 | 3258 | } |
| 3640 | 3259 | |
| 3641 | 3260 | $block_rules = ''; |
| @@ -3746,32 +3365,20 @@ | ||
| 3746 | 3365 | } |
| 3747 | 3366 | if ( isset( $style_variation_custom_css[ $style_variation_selector ] ) ) { |
| 3748 | 3367 | $block_rules .= $style_variation_custom_css[ $style_variation_selector ]; |
| 3749 | 3368 | } |
| 3750 | - if ( isset( $style_variation_responsive_css[ $style_variation_selector ] ) ) { | |
| 3751 | - $block_rules .= $style_variation_responsive_css[ $style_variation_selector ]; | |
| 3752 | - } | |
| 3753 | 3369 | } |
| 3754 | 3370 | |
| 3755 | - // Compute selector for block custom CSS. | |
| 3756 | - $css_feature_selector = $block_metadata['selectors']['css'] ?? null; | |
| 3757 | - if ( is_array( $css_feature_selector ) ) { | |
| 3758 | - $css_feature_selector = $css_feature_selector['root'] ?? null; | |
| 3759 | - } | |
| 3760 | - $css_selector = is_string( $css_feature_selector ) ? $css_feature_selector : $selector; | |
| 3761 | - | |
| 3762 | 3371 | // 7. Generate and append any custom CSS rules. |
| 3763 | 3372 | if ( isset( $node['css'] ) && ! $is_root_selector ) { |
| 3373 | + $css_feature_selector = $block_metadata['selectors']['css'] ?? null; | |
| 3374 | + if ( is_array( $css_feature_selector ) ) { | |
| 3375 | + $css_feature_selector = $css_feature_selector['root'] ?? null; | |
| 3376 | + } | |
| 3377 | + $css_selector = is_string( $css_feature_selector ) ? $css_feature_selector : $selector; | |
| 3764 | 3378 | $block_rules .= $this->process_blocks_custom_css( $node['css'], $css_selector ); |
| 3765 | 3379 | } |
| 3766 | 3380 | |
| 3767 | - // 8. Wrap the entire block output in a media query if this is a responsive node. | |
| 3768 | - // Responsive nodes are created by get_block_nodes() for each breakpoint and carry | |
| 3769 | - // a 'media_query' key. | |
| 3770 | - if ( $media_query && ! empty( $block_rules ) ) { | |
| 3771 | - $block_rules = $media_query . '{' . $block_rules . '}'; | |
| 3772 | - } | |
| 3773 | - | |
| 3774 | 3381 | return $block_rules; |
| 3775 | 3382 | } |
| 3776 | 3383 | |
| 3777 | 3384 | /** |
| @@ -4265,12 +3872,8 @@ | ||
| 4265 | 3872 | if ( empty( $input ) ) { |
| 4266 | 3873 | continue; |
| 4267 | 3874 | } |
| 4268 | 3875 | |
| 4269 | - $block_name = in_array( 'blocks', $metadata['path'], true ) | |
| 4270 | - ? static::get_block_name_from_metadata_path( $metadata ) | |
| 4271 | - : null; | |
| 4272 | - | |
| 4273 | 3876 | // The global styles custom CSS is not sanitized, but can only be edited by users with 'edit_css' capability. |
| 4274 | 3877 | if ( isset( $input['css'] ) && current_user_can( 'edit_css' ) ) { |
| 4275 | 3878 | $output = $input; |
| 4276 | 3879 | } else { |
| @@ -4294,36 +3897,8 @@ | ||
| 4294 | 3897 | } |
| 4295 | 3898 | } |
| 4296 | 3899 | } |
| 4297 | 3900 | |
| 4298 | - // Re-add and process responsive breakpoint styles. | |
| 4299 | - foreach ( array_keys( static::RESPONSIVE_BREAKPOINTS ) as $breakpoint ) { | |
| 4300 | - if ( isset( $input[ $breakpoint ] ) ) { | |
| 4301 | - $output[ $breakpoint ] = static::remove_insecure_styles( $input[ $breakpoint ] ); | |
| 4302 | - | |
| 4303 | - if ( isset( $input[ $breakpoint ]['elements'] ) ) { | |
| 4304 | - $output[ $breakpoint ]['elements'] = static::remove_insecure_element_styles( $input[ $breakpoint ]['elements'] ); | |
| 4305 | - } | |
| 4306 | - | |
| 4307 | - if ( isset( $input[ $breakpoint ]['blocks'] ) ) { | |
| 4308 | - $output[ $breakpoint ]['blocks'] = static::remove_insecure_inner_block_styles( $input[ $breakpoint ]['blocks'] ); | |
| 4309 | - } | |
| 4310 | - | |
| 4311 | - if ( $block_name && isset( static::VALID_BLOCK_PSEUDO_SELECTORS[ $block_name ] ) ) { | |
| 4312 | - foreach ( static::VALID_BLOCK_PSEUDO_SELECTORS[ $block_name ] as $pseudo_selector ) { | |
| 4313 | - if ( isset( $input[ $breakpoint ][ $pseudo_selector ] ) ) { | |
| 4314 | - $output[ $breakpoint ][ $pseudo_selector ] = static::remove_insecure_styles( $input[ $breakpoint ][ $pseudo_selector ] ); | |
| 4315 | - } | |
| 4316 | - } | |
| 4317 | - } | |
| 4318 | - | |
| 4319 | - // Responsive custom CSS is allowed for users with 'edit_css' capability. | |
| 4320 | - if ( isset( $input[ $breakpoint ]['css'] ) && current_user_can( 'edit_css' ) ) { | |
| 4321 | - $output[ $breakpoint ]['css'] = $input[ $breakpoint ]['css']; | |
| 4322 | - } | |
| 4323 | - } | |
| 4324 | - } | |
| 4325 | - | |
| 4326 | 3901 | if ( ! empty( $output ) ) { |
| 4327 | 3902 | _wp_array_set( $sanitized, $metadata['path'], $output ); |
| 4328 | 3903 | } |
| 4329 | 3904 | |
| @@ -4343,36 +3918,8 @@ | ||
| 4343 | 3918 | if ( isset( $variation_input['elements'] ) ) { |
| 4344 | 3919 | $variation_output['elements'] = static::remove_insecure_element_styles( $variation_input['elements'] ); |
| 4345 | 3920 | } |
| 4346 | 3921 | |
| 4347 | - // Re-add and process responsive breakpoint styles for variations. | |
| 4348 | - foreach ( array_keys( static::RESPONSIVE_BREAKPOINTS ) as $breakpoint ) { | |
| 4349 | - if ( isset( $variation_input[ $breakpoint ] ) ) { | |
| 4350 | - $variation_output[ $breakpoint ] = static::remove_insecure_styles( $variation_input[ $breakpoint ] ); | |
| 4351 | - | |
| 4352 | - if ( isset( $variation_input[ $breakpoint ]['elements'] ) ) { | |
| 4353 | - $variation_output[ $breakpoint ]['elements'] = static::remove_insecure_element_styles( $variation_input[ $breakpoint ]['elements'] ); | |
| 4354 | - } | |
| 4355 | - | |
| 4356 | - if ( isset( $variation_input[ $breakpoint ]['blocks'] ) ) { | |
| 4357 | - $variation_output[ $breakpoint ]['blocks'] = static::remove_insecure_inner_block_styles( $variation_input[ $breakpoint ]['blocks'] ); | |
| 4358 | - } | |
| 4359 | - | |
| 4360 | - if ( $block_name && isset( static::VALID_BLOCK_PSEUDO_SELECTORS[ $block_name ] ) ) { | |
| 4361 | - foreach ( static::VALID_BLOCK_PSEUDO_SELECTORS[ $block_name ] as $pseudo_selector ) { | |
| 4362 | - if ( isset( $variation_input[ $breakpoint ][ $pseudo_selector ] ) ) { | |
| 4363 | - $variation_output[ $breakpoint ][ $pseudo_selector ] = static::remove_insecure_styles( $variation_input[ $breakpoint ][ $pseudo_selector ] ); | |
| 4364 | - } | |
| 4365 | - } | |
| 4366 | - } | |
| 4367 | - | |
| 4368 | - // Responsive custom CSS is allowed for users with 'edit_css' capability. | |
| 4369 | - if ( isset( $variation_input[ $breakpoint ]['css'] ) && current_user_can( 'edit_css' ) ) { | |
| 4370 | - $variation_output[ $breakpoint ]['css'] = $variation_input[ $breakpoint ]['css']; | |
| 4371 | - } | |
| 4372 | - } | |
| 4373 | - } | |
| 4374 | - | |
| 4375 | 3922 | if ( ! empty( $variation_output ) ) { |
| 4376 | 3923 | _wp_array_set( $sanitized, $variation['path'], $variation_output ); |
| 4377 | 3924 | } |
| 4378 | 3925 | } |
| @@ -4431,23 +3978,8 @@ | ||
| 4431 | 3978 | } |
| 4432 | 3979 | } |
| 4433 | 3980 | } |
| 4434 | 3981 | |
| 4435 | - // Re-add and process responsive breakpoint styles for elements. | |
| 4436 | - foreach ( array_keys( static::RESPONSIVE_BREAKPOINTS ) as $breakpoint ) { | |
| 4437 | - if ( isset( $element_input[ $breakpoint ] ) ) { | |
| 4438 | - $element_output[ $breakpoint ] = static::remove_insecure_styles( $element_input[ $breakpoint ] ); | |
| 4439 | - | |
| 4440 | - if ( isset( static::VALID_ELEMENT_PSEUDO_SELECTORS[ $element_name ] ) ) { | |
| 4441 | - foreach ( static::VALID_ELEMENT_PSEUDO_SELECTORS[ $element_name ] as $pseudo_selector ) { | |
| 4442 | - if ( isset( $element_input[ $breakpoint ][ $pseudo_selector ] ) ) { | |
| 4443 | - $element_output[ $breakpoint ][ $pseudo_selector ] = static::remove_insecure_styles( $element_input[ $breakpoint ][ $pseudo_selector ] ); | |
| 4444 | - } | |
| 4445 | - } | |
| 4446 | - } | |
| 4447 | - } | |
| 4448 | - } | |
| 4449 | - | |
| 4450 | 3982 | $sanitized[ $element_name ] = $element_output; |
| 4451 | 3983 | } |
| 4452 | 3984 | } |
| 4453 | 3985 | return $sanitized; |
| @@ -4467,23 +3999,8 @@ | ||
| 4467 | 3999 | $block_output = static::remove_insecure_styles( $block_input ); |
| 4468 | 4000 | |
| 4469 | 4001 | if ( isset( $block_input['elements'] ) ) { |
| 4470 | 4002 | $block_output['elements'] = static::remove_insecure_element_styles( $block_input['elements'] ); |
| 4471 | - } | |
| 4472 | - | |
| 4473 | - // Re-add and process responsive breakpoint styles for inner blocks. | |
| 4474 | - foreach ( array_keys( static::RESPONSIVE_BREAKPOINTS ) as $breakpoint ) { | |
| 4475 | - if ( isset( $block_input[ $breakpoint ] ) ) { | |
| 4476 | - $block_output[ $breakpoint ] = static::remove_insecure_styles( $block_input[ $breakpoint ] ); | |
| 4477 | - | |
| 4478 | - if ( isset( static::VALID_BLOCK_PSEUDO_SELECTORS[ $block_type ] ) ) { | |
| 4479 | - foreach ( static::VALID_BLOCK_PSEUDO_SELECTORS[ $block_type ] as $pseudo_selector ) { | |
| 4480 | - if ( isset( $block_input[ $breakpoint ][ $pseudo_selector ] ) ) { | |
| 4481 | - $block_output[ $breakpoint ][ $pseudo_selector ] = static::remove_insecure_styles( $block_input[ $breakpoint ][ $pseudo_selector ] ); | |
| 4482 | - } | |
| 4483 | - } | |
| 4484 | - } | |
| 4485 | - } | |
| 4486 | 4003 | } |
| 4487 | 4004 | |
| 4488 | 4005 | $sanitized[ $block_type ] = $block_output; |
| 4489 | 4006 | } |