| @@ -31,10 +31,23 @@ | ||
| 31 | 31 | if ( ! is_string( $value ) || ! str_starts_with( $value, 'var:preset|' ) ) { |
| 32 | 32 | return $value; |
| 33 | 33 | } |
| 34 | 34 | |
| 35 | - $unwrapped_name = str_replace( '|', '--', substr( $value, strlen( 'var:' ) ) ); | |
| 36 | - return "var(--wp--$unwrapped_name)"; | |
| 35 | + $parts = explode( '|', substr( $value, strlen( 'var:' ) ) ); | |
| 36 | + | |
| 37 | + /* | |
| 38 | + * The slug is kebab-cased when the preset's custom property is generated, | |
| 39 | + * so a reference has to be converted the same way or it points at a | |
| 40 | + * property that does not exist (`--wp--preset--font-size--3xl` for a preset | |
| 41 | + * generated as `--wp--preset--font-size--3-xl`). Mirrors | |
| 42 | + * `WP_Theme_JSON_Gutenberg::convert_custom_properties()` and the JS style | |
| 43 | + * engine's `getCSSValueFromRawStyle()`. | |
| 44 | + */ | |
| 45 | + if ( 3 === count( $parts ) ) { | |
| 46 | + $parts[2] = _wp_to_kebab_case( $parts[2] ); | |
| 47 | + } | |
| 48 | + | |
| 49 | + return 'var(--wp--' . implode( '--', $parts ) . ')'; | |
| 37 | 50 | } |
| 38 | 51 | |
| 39 | 52 | /** |
| 40 | 53 | * Normalizes a state style object before generating CSS declarations. |
| @@ -112,14 +125,15 @@ | ||
| 112 | 125 | $has_background_image = isset( $declarations['background-image'] ) && '' !== $declarations['background-image']; |
| 113 | 126 | |
| 114 | 127 | /* |
| 115 | 128 | * When the state sets a solid background-color but no gradient of its own, |
| 116 | - * emit `background-image: unset !important` to clear any gradient (whether | |
| 117 | - * stored as the `background` shorthand or as `background-image`) that was | |
| 118 | - * applied to the default / normal state via an inline style attribute. | |
| 129 | + * emit `background-image: unset` to clear any gradient (whether stored as | |
| 130 | + * the `background` shorthand or as `background-image`) that was applied to | |
| 131 | + * the default / normal state via an inline style attribute. The declaration | |
| 132 | + * is marked important when the state rule is registered with the style engine. | |
| 119 | 133 | */ |
| 120 | 134 | if ( $has_background_color && ! $has_background && ! $has_background_image ) { |
| 121 | - $declarations['background-image'] = 'unset !important'; | |
| 135 | + $declarations['background-image'] = 'unset'; | |
| 122 | 136 | } |
| 123 | 137 | |
| 124 | 138 | return $declarations; |
| 125 | 139 | } |
| @@ -342,13 +356,19 @@ | ||
| 342 | 356 | } |
| 343 | 357 | |
| 344 | 358 | $style = gutenberg_get_state_style_with_fallback_dimension_styles( $style ); |
| 345 | 359 | |
| 346 | - $compiled = gutenberg_style_engine_get_styles( | |
| 360 | + $compiled = gutenberg_style_engine_get_styles( | |
| 347 | 361 | gutenberg_normalize_state_style_for_css_output( $style ) |
| 348 | 362 | ); |
| 363 | + $declarations = $compiled['declarations'] ?? array(); | |
| 364 | + $text_align = $style['typography']['textAlign'] ?? null; | |
| 365 | + // Base text alignment is class-based, so state styles need a declaration. | |
| 366 | + if ( is_string( $text_align ) && '' !== trim( $text_align ) ) { | |
| 367 | + $declarations['text-align'] = $text_align; | |
| 368 | + } | |
| 349 | 369 | |
| 350 | - if ( empty( $compiled['declarations'] ) ) { | |
| 370 | + if ( empty( $declarations ) ) { | |
| 351 | 371 | return; |
| 352 | 372 | } |
| 353 | 373 | |
| 354 | 374 | $css_rules[] = array( |
| @@ -353,9 +373,9 @@ | ||
| 353 | 373 | |
| 354 | 374 | $css_rules[] = array( |
| 355 | 375 | 'state' => $state, |
| 356 | 376 | 'selector' => $selector, |
| 357 | - 'declarations' => $compiled['declarations'], | |
| 377 | + 'declarations' => $declarations, | |
| 358 | 378 | ); |
| 359 | 379 | if ( ! empty( $rules_group ) ) { |
| 360 | 380 | $css_rules[ count( $css_rules ) - 1 ]['rules_group'] = $rules_group; |
| 361 | 381 | } |
| @@ -506,19 +526,31 @@ | ||
| 506 | 526 | return $block_content; |
| 507 | 527 | } |
| 508 | 528 | |
| 509 | 529 | $block_name = $block['blockName']; |
| 530 | + | |
| 531 | + /* | |
| 532 | + * Every CSS rule this function can produce is keyed off the block's `style` | |
| 533 | + * attribute. Without it there is nothing to generate, so bail before doing | |
| 534 | + * any of the lookups below — this runs for every block on every request. | |
| 535 | + */ | |
| 536 | + $raw_style = $block['attrs']['style'] ?? array(); | |
| 537 | + if ( empty( $raw_style ) || ! is_array( $raw_style ) ) { | |
| 538 | + return $block_content; | |
| 539 | + } | |
| 540 | + | |
| 541 | + // Keep the existing block registry lookup here. | |
| 542 | + $style = gutenberg_resolve_style_state_aliases( $raw_style, $block_name ); | |
| 543 | + | |
| 510 | 544 | $block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block_name ); |
| 511 | 545 | if ( ! $block_type ) { |
| 512 | 546 | return $block_content; |
| 513 | 547 | } |
| 514 | 548 | |
| 515 | - $supported_pseudo_states = WP_Theme_JSON_Gutenberg::VALID_BLOCK_PSEUDO_SELECTORS[ $block_name ] ?? array(); | |
| 516 | - $style = gutenberg_resolve_style_state_aliases( | |
| 517 | - $block['attrs']['style'] ?? array(), | |
| 518 | - $block_name | |
| 519 | - ); | |
| 520 | - $css_rules = array(); | |
| 549 | + $supported_pseudo_states = WP_Theme_JSON_Gutenberg::VALID_BLOCK_PSEUDO_SELECTORS[ $block_name ] ?? array(); | |
| 550 | + $css_rules = array(); | |
| 551 | + $viewport_settings = gutenberg_get_global_settings( array( 'viewport' ) ); | |
| 552 | + $responsive_media_queries = WP_Theme_JSON_Gutenberg::get_viewport_media_queries( $viewport_settings ); | |
| 521 | 553 | |
| 522 | 554 | foreach ( $supported_pseudo_states as $pseudo_state ) { |
| 523 | 555 | if ( empty( $style[ $pseudo_state ] ) || ! is_array( $style[ $pseudo_state ] ) ) { |
| 524 | 556 | continue; |
| @@ -532,9 +564,9 @@ | ||
| 532 | 564 | ) |
| 533 | 565 | ); |
| 534 | 566 | } |
| 535 | 567 | |
| 536 | - foreach ( WP_Theme_JSON_Gutenberg::RESPONSIVE_BREAKPOINTS as $breakpoint => $media_query ) { | |
| 568 | + foreach ( $responsive_media_queries as $breakpoint => $media_query ) { | |
| 537 | 569 | if ( empty( $style[ $breakpoint ] ) || ! is_array( $style[ $breakpoint ] ) ) { |
| 538 | 570 | continue; |
| 539 | 571 | } |
| 540 | 572 | |
| @@ -644,28 +676,51 @@ | ||
| 644 | 676 | * with the base layout and target the correct (inner) wrapper element. |
| 645 | 677 | */ |
| 646 | 678 | $style_rules = array(); |
| 647 | 679 | foreach ( $css_rules as $rule ) { |
| 648 | - $declarations = $rule['declarations']; | |
| 649 | - foreach ( $declarations as $property => $value ) { | |
| 650 | - $declarations[ $property ] = is_string( $value ) && str_contains( $value, '!important' ) | |
| 651 | - ? $value | |
| 652 | - : $value . ' !important'; | |
| 680 | + $declarations = $rule['declarations']; | |
| 681 | + $important_declaration_values = gutenberg_get_state_declarations_with_background_resets( $declarations ); | |
| 682 | + $important_declarations = new WP_Style_Engine_CSS_Declarations_Gutenberg(); | |
| 683 | + foreach ( $important_declaration_values as $property => $value ) { | |
| 684 | + $important_declarations->add_declaration( | |
| 685 | + $property, | |
| 686 | + $value, | |
| 687 | + array( | |
| 688 | + 'important' => true, | |
| 689 | + ) | |
| 690 | + ); | |
| 653 | 691 | } |
| 654 | - $declarations = gutenberg_get_state_declarations_with_fallback_border_styles( $declarations ); | |
| 655 | - $declarations = gutenberg_get_state_declarations_with_background_resets( $declarations ); | |
| 656 | - $style_rule = array( | |
| 657 | - 'selector' => gutenberg_build_state_selector( | |
| 658 | - ".$unique_class", | |
| 659 | - $rule['selector'], | |
| 660 | - $rule['state'] | |
| 661 | - ), | |
| 662 | - 'declarations' => $declarations, | |
| 692 | + $selector = gutenberg_build_state_selector( | |
| 693 | + ".$unique_class", | |
| 694 | + $rule['selector'], | |
| 695 | + $rule['state'] | |
| 663 | 696 | ); |
| 697 | + $important_style_rule = array( | |
| 698 | + 'selector' => $selector, | |
| 699 | + 'declarations' => $important_declarations, | |
| 700 | + ); | |
| 664 | 701 | if ( ! empty( $rule['rules_group'] ) ) { |
| 665 | - $style_rule['rules_group'] = $rule['rules_group']; | |
| 702 | + $important_style_rule['rules_group'] = $rule['rules_group']; | |
| 666 | 703 | } |
| 667 | - $style_rules[] = $style_rule; | |
| 704 | + $style_rules[] = $important_style_rule; | |
| 705 | + | |
| 706 | + $fallback_declarations = gutenberg_get_state_declarations_with_fallback_border_styles( $declarations ); | |
| 707 | + foreach ( array_keys( $declarations ) as $property ) { | |
| 708 | + unset( $fallback_declarations[ $property ] ); | |
| 709 | + } | |
| 710 | + | |
| 711 | + if ( empty( $fallback_declarations ) ) { | |
| 712 | + continue; | |
| 713 | + } | |
| 714 | + | |
| 715 | + $fallback_style_rule = array( | |
| 716 | + 'selector' => $selector, | |
| 717 | + 'declarations' => $fallback_declarations, | |
| 718 | + ); | |
| 719 | + if ( ! empty( $rule['rules_group'] ) ) { | |
| 720 | + $fallback_style_rule['rules_group'] = $rule['rules_group']; | |
| 721 | + } | |
| 722 | + $style_rules[] = $fallback_style_rule; | |
| 668 | 723 | } |
| 669 | 724 | |
| 670 | 725 | gutenberg_style_engine_get_stylesheet_from_css_rules( |
| 671 | 726 | $style_rules, |