Changeset 50973
- Timestamp:
- 05/24/2021 05:38:59 PM (4 years ago)
- Location:
- trunk
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/block-editor.php
r50963 r50973 244 244 ); 245 245 246 $editor_settings['__experimentalFeatures'] = WP_Theme_JSON_Resolver::get_merged_data( $editor_settings )->get_settings(); 247 246 $theme_json = WP_Theme_JSON_Resolver::get_merged_data( $editor_settings ); 247 248 if ( WP_Theme_JSON_Resolver::theme_has_support() ) { 249 $editor_settings['styles'][] = array( 'css' => $theme_json->get_stylesheet( 'block_styles' ) ); 250 $editor_settings['styles'][] = array( 251 'css' => $theme_json->get_stylesheet( 'css_variables' ), 252 '__experimentalNoWrapper' => true, 253 ); 254 } 255 256 $editor_settings['__experimentalFeatures'] = $theme_json->get_settings(); 248 257 // These settings may need to be updated based on data coming from theme.json sources. 249 258 if ( isset( $editor_settings['__experimentalFeatures']['color']['palette'] ) ) { -
trunk/src/wp-includes/class-wp-theme-json.php
r50967 r50973 24 24 25 25 /** 26 * Holds the allowed block names extracted from block.json. 27 * Shared among all instances so we only process it once. 26 * Holds block metadata extracted from block.json 27 * to be shared among all instances so we don't 28 * process it twice. 28 29 * 29 30 * @since 5.8.0 30 31 * @var array 31 32 */ 32 private static $allowed_block_names = null; 33 33 private static $blocks_metadata = null; 34 35 /** 36 * The CSS selector for the top-level styles. 37 * 38 * @since 5.8.0 39 * @var string 40 */ 41 const ROOT_BLOCK_SELECTOR = 'body'; 42 43 /** 44 * Presets are a set of values that serve 45 * to bootstrap some styles: colors, font sizes, etc. 46 * 47 * They are a unkeyed array of values such as: 48 * 49 * ```php 50 * array( 51 * array( 52 * 'slug' => 'unique-name-within-the-set', 53 * 'name' => 'Name for the UI', 54 * <value_key> => 'value' 55 * ), 56 * ) 57 * ``` 58 * 59 * This contains the necessary metadata to process them: 60 * 61 * - path => where to find the preset within the settings section 62 * 63 * - value_key => the key that represents the value 64 * 65 * - css_var_infix => infix to use in generating the CSS Custom Property. Example: 66 * --wp--preset--<preset_infix>--<slug>: <preset_value> 67 * 68 * - classes => array containing a structure with the classes to 69 * generate for the presets. Each class should have 70 * the class suffix and the property name. Example: 71 * 72 * .has-<slug>-<class_suffix> { 73 * <property_name>: <preset_value> 74 * } 75 * 76 * @since 5.8.0 77 * @var array 78 */ 79 const PRESETS_METADATA = array( 80 array( 81 'path' => array( 'color', 'palette' ), 82 'value_key' => 'color', 83 'css_var_infix' => 'color', 84 'classes' => array( 85 array( 86 'class_suffix' => 'color', 87 'property_name' => 'color', 88 ), 89 array( 90 'class_suffix' => 'background-color', 91 'property_name' => 'background-color', 92 ), 93 ), 94 ), 95 array( 96 'path' => array( 'color', 'gradients' ), 97 'value_key' => 'gradient', 98 'css_var_infix' => 'gradient', 99 'classes' => array( 100 array( 101 'class_suffix' => 'gradient-background', 102 'property_name' => 'background', 103 ), 104 ), 105 ), 106 array( 107 'path' => array( 'typography', 'fontSizes' ), 108 'value_key' => 'size', 109 'css_var_infix' => 'font-size', 110 'classes' => array( 111 array( 112 'class_suffix' => 'font-size', 113 'property_name' => 'font-size', 114 ), 115 ), 116 ), 117 ); 118 119 /** 120 * Metadata for style properties. 121 * 122 * Each property declares: 123 * 124 * - 'value': path to the value in theme.json and block attributes. 125 * 126 * @since 5.8.0 127 * @var array 128 */ 129 const PROPERTIES_METADATA = array( 130 'background' => array( 131 'value' => array( 'color', 'gradient' ), 132 ), 133 'background-color' => array( 134 'value' => array( 'color', 'background' ), 135 ), 136 'color' => array( 137 'value' => array( 'color', 'text' ), 138 ), 139 'font-size' => array( 140 'value' => array( 'typography', 'fontSize' ), 141 ), 142 'line-height' => array( 143 'value' => array( 'typography', 'lineHeight' ), 144 ), 145 'margin' => array( 146 'value' => array( 'spacing', 'margin' ), 147 'properties' => array( 'top', 'right', 'bottom', 'left' ), 148 ), 149 'padding' => array( 150 'value' => array( 'spacing', 'padding' ), 151 'properties' => array( 'top', 'right', 'bottom', 'left' ), 152 ), 153 ); 154 155 /** 156 * @since 5.8.0 157 * @var array 158 */ 34 159 const ALLOWED_TOP_LEVEL_KEYS = array( 160 'settings', 161 'styles', 35 162 'version', 36 'settings',37 163 ); 38 164 165 /** 166 * @since 5.8.0 167 * @var array 168 */ 39 169 const ALLOWED_SETTINGS = array( 40 170 'color' => array( … … 61 191 ); 62 192 193 /** 194 * @since 5.8.0 195 * @var array 196 */ 197 const ALLOWED_STYLES = array( 198 'color' => array( 199 'background' => null, 200 'gradient' => null, 201 'text' => null, 202 ), 203 'spacing' => array( 204 'margin' => array( 205 'top' => null, 206 'right' => null, 207 'bottom' => null, 208 'left' => null, 209 ), 210 'padding' => array( 211 'bottom' => null, 212 'left' => null, 213 'right' => null, 214 'top' => null, 215 ), 216 ), 217 'typography' => array( 218 'fontSize' => null, 219 'lineHeight' => null, 220 ), 221 ); 222 223 /** 224 * @since 5.8.0 225 * @var array 226 */ 227 const ELEMENTS = array( 228 'link' => 'a', 229 'h1' => 'h1', 230 'h2' => 'h2', 231 'h3' => 'h3', 232 'h4' => 'h4', 233 'h5' => 'h5', 234 'h6' => 'h6', 235 ); 236 237 /** 238 * @since 5.8.0 239 * @var int 240 */ 63 241 const LATEST_SCHEMA = 1; 64 242 … … 80 258 81 259 /** 82 * Returns the allowed block names.83 *84 * @since 5.8.085 *86 * @return array87 */88 private static function get_allowed_block_names() {89 if ( null !== self::$allowed_block_names ) {90 return self::$allowed_block_names;91 }92 93 self::$allowed_block_names = array_keys( WP_Block_Type_Registry::get_instance()->get_all_registered() );94 95 return self::$allowed_block_names;96 }97 98 /**99 260 * Sanitizes the input according to the schemas. 100 261 * … … 111 272 } 112 273 113 $allowed_blocks = self::get_allowed_block_names(); 114 115 $output = array_intersect_key( $input, array_flip( self::ALLOWED_TOP_LEVEL_KEYS ) ); 274 $allowed_top_level_keys = self::ALLOWED_TOP_LEVEL_KEYS; 275 $allowed_settings = self::ALLOWED_SETTINGS; 276 $allowed_styles = self::ALLOWED_STYLES; 277 $allowed_blocks = array_keys( self::get_blocks_metadata() ); 278 $allowed_elements = array_keys( self::ELEMENTS ); 279 280 $output = array_intersect_key( $input, array_flip( $allowed_top_level_keys ) ); 116 281 117 282 // Build the schema. 118 283 $schema = array(); 284 $schema_styles_elements = array(); 285 foreach ( $allowed_elements as $element ) { 286 $schema_styles_elements[ $element ] = $allowed_styles; 287 } 288 $schema_styles_blocks = array(); 119 289 $schema_settings_blocks = array(); 120 290 foreach ( $allowed_blocks as $block ) { 121 $schema_settings_blocks[ $block ] = self::ALLOWED_SETTINGS; 122 } 123 $schema['settings'] = self::ALLOWED_SETTINGS; 291 $schema_settings_blocks[ $block ] = $allowed_settings; 292 $schema_styles_blocks[ $block ] = $allowed_styles; 293 $schema_styles_blocks[ $block ]['elements'] = $schema_styles_elements; 294 } 295 $schema['styles'] = $allowed_styles; 296 $schema['styles']['blocks'] = $schema_styles_blocks; 297 $schema['styles']['elements'] = $schema_styles_elements; 298 $schema['settings'] = $allowed_settings; 124 299 $schema['settings']['blocks'] = $schema_settings_blocks; 125 300 126 301 // Remove anything that's not present in the schema. 127 foreach ( array( 's ettings' ) as $subtree ) {302 foreach ( array( 'styles', 'settings' ) as $subtree ) { 128 303 if ( ! isset( $input[ $subtree ] ) ) { 129 304 continue; … … 148 323 149 324 /** 325 * Returns the metadata for each block. 326 * 327 * Example: 328 * 329 * { 330 * 'core/paragraph': { 331 * 'selector': 'p', 332 * 'elements': { 333 * 'link' => 'link selector', 334 * 'etc' => 'element selector' 335 * } 336 * }, 337 * 'core/heading': { 338 * 'selector': 'h1', 339 * 'elements': {} 340 * } 341 * 'core/group': { 342 * 'selector': '.wp-block-group', 343 * 'elements': {} 344 * } 345 * } 346 * 347 * @since 5.8.0 348 * 349 * @return array Block metadata. 350 */ 351 private static function get_blocks_metadata() { 352 if ( null !== self::$blocks_metadata ) { 353 return self::$blocks_metadata; 354 } 355 356 self::$blocks_metadata = array(); 357 358 $registry = WP_Block_Type_Registry::get_instance(); 359 $blocks = $registry->get_all_registered(); 360 foreach ( $blocks as $block_name => $block_type ) { 361 if ( 362 isset( $block_type->supports['__experimentalSelector'] ) && 363 is_string( $block_type->supports['__experimentalSelector'] ) 364 ) { 365 self::$blocks_metadata[ $block_name ]['selector'] = $block_type->supports['__experimentalSelector']; 366 } else { 367 self::$blocks_metadata[ $block_name ]['selector'] = '.wp-block-' . str_replace( '/', '-', str_replace( 'core/', '', $block_name ) ); 368 } 369 370 // Assign defaults, then overwrite those that the block sets by itself. 371 // If the block selector is compounded, will append the element to each 372 // individual block selector. 373 $block_selectors = explode( ',', self::$blocks_metadata[ $block_name ]['selector'] ); 374 foreach ( self::ELEMENTS as $el_name => $el_selector ) { 375 $element_selector = array(); 376 foreach ( $block_selectors as $selector ) { 377 $element_selector[] = $selector . ' ' . $el_selector; 378 } 379 self::$blocks_metadata[ $block_name ]['elements'][ $el_name ] = implode( ',', $element_selector ); 380 } 381 } 382 383 return self::$blocks_metadata; 384 } 385 386 /** 150 387 * Given a tree, removes the keys that are not present in the schema. 151 388 * … … 156 393 * @param array $tree Input to process. 157 394 * @param array $schema Schema to adhere to. 395 * 158 396 * @return array Returns the modified $tree. 159 397 */ … … 211 449 212 450 /** 451 * Returns the stylesheet that results of processing 452 * the theme.json structure this object represents. 453 * 454 * @since 5.8.0 455 * 456 * @param string $type Type of stylesheet we want accepts 'all', 'block_styles', and 'css_variables'. 457 * 458 * @return string Stylesheet. 459 */ 460 public function get_stylesheet( $type = 'all' ) { 461 $blocks_metadata = self::get_blocks_metadata(); 462 $style_nodes = self::get_style_nodes( $this->theme_json, $blocks_metadata ); 463 $setting_nodes = self::get_setting_nodes( $this->theme_json, $blocks_metadata ); 464 465 switch ( $type ) { 466 case 'block_styles': 467 return $this->get_block_styles( $style_nodes, $setting_nodes ); 468 case 'css_variables': 469 return $this->get_css_variables( $setting_nodes ); 470 default: 471 return $this->get_css_variables( $setting_nodes ) . $this->get_block_styles( $style_nodes, $setting_nodes ); 472 } 473 474 } 475 476 /** 477 * Converts each style section into a list of rulesets 478 * containing the block styles to be appended to the stylesheet. 479 * 480 * See glossary at https://developer.mozilla.org/en-US/docs/Web/CSS/Syntax 481 * 482 * For each section this creates a new ruleset such as: 483 * 484 * block-selector { 485 * style-property-one: value; 486 * } 487 * 488 * Additionally, it'll also create new rulesets 489 * as classes for each preset value such as: 490 * 491 * .has-value-color { 492 * color: value; 493 * } 494 * 495 * .has-value-background-color { 496 * background-color: value; 497 * } 498 * 499 * .has-value-font-size { 500 * font-size: value; 501 * } 502 * 503 * .has-value-gradient-background { 504 * background: value; 505 * } 506 * 507 * p.has-value-gradient-background { 508 * background: value; 509 * } 510 * 511 * @since 5.8.0 512 * 513 * @param array $style_nodes Nodes with styles. 514 * @param array $setting_nodes Nodes with settings. 515 * 516 * @return string The new stylesheet. 517 */ 518 private function get_block_styles( $style_nodes, $setting_nodes ) { 519 $block_rules = ''; 520 foreach ( $style_nodes as $metadata ) { 521 if ( null === $metadata['selector'] ) { 522 continue; 523 } 524 525 $node = _wp_array_get( $this->theme_json, $metadata['path'], array() ); 526 $selector = $metadata['selector']; 527 $declarations = self::compute_style_properties( $node ); 528 $block_rules .= self::to_ruleset( $selector, $declarations ); 529 } 530 531 $preset_rules = ''; 532 foreach ( $setting_nodes as $metadata ) { 533 if ( null === $metadata['selector'] ) { 534 continue; 535 } 536 537 $selector = $metadata['selector']; 538 $node = _wp_array_get( $this->theme_json, $metadata['path'], array() ); 539 $preset_rules .= self::compute_preset_classes( $node, $selector ); 540 } 541 542 return $block_rules . $preset_rules; 543 } 544 545 /** 546 * Converts each styles section into a list of rulesets 547 * to be appended to the stylesheet. 548 * These rulesets contain all the css variables (custom variables and preset variables). 549 * 550 * See glossary at https://developer.mozilla.org/en-US/docs/Web/CSS/Syntax 551 * 552 * For each section this creates a new ruleset such as: 553 * 554 * block-selector { 555 * --wp--preset--category--slug: value; 556 * --wp--custom--variable: value; 557 * } 558 * 559 * @since 5.8.0 560 * 561 * @param array $nodes Nodes with settings. 562 * 563 * @return string The new stylesheet. 564 */ 565 private function get_css_variables( $nodes ) { 566 $stylesheet = ''; 567 foreach ( $nodes as $metadata ) { 568 if ( null === $metadata['selector'] ) { 569 continue; 570 } 571 572 $selector = $metadata['selector']; 573 574 $node = _wp_array_get( $this->theme_json, $metadata['path'], array() ); 575 $declarations = array_merge( self::compute_preset_vars( $node ), self::compute_theme_vars( $node ) ); 576 577 $stylesheet .= self::to_ruleset( $selector, $declarations ); 578 } 579 580 return $stylesheet; 581 } 582 583 /** 584 * Given a selector and a declaration list, 585 * creates the corresponding ruleset. 586 * 587 * To help debugging, will add some space 588 * if SCRIPT_DEBUG is defined and true. 589 * 590 * @since 5.8.0 591 * 592 * @param string $selector CSS selector. 593 * @param array $declarations List of declarations. 594 * 595 * @return string CSS ruleset. 596 */ 597 private static function to_ruleset( $selector, $declarations ) { 598 if ( empty( $declarations ) ) { 599 return ''; 600 } 601 602 $declaration_block = array_reduce( 603 $declarations, 604 function ( $carry, $element ) { 605 return $carry .= $element['name'] . ': ' . $element['value'] . ';'; }, 606 '' 607 ); 608 609 return $selector . '{' . $declaration_block . '}'; 610 } 611 612 /** 613 * Given a settings array, it returns the generated rulesets 614 * for the preset classes. 615 * 616 * @since 5.8.0 617 * 618 * @param array $settings Settings to process. 619 * @param string $selector Selector wrapping the classes. 620 * 621 * @return string The result of processing the presets. 622 */ 623 private static function compute_preset_classes( $settings, $selector ) { 624 if ( self::ROOT_BLOCK_SELECTOR === $selector ) { 625 // Classes at the global level do not need any CSS prefixed, 626 // and we don't want to increase its specificity. 627 $selector = ''; 628 } 629 630 $stylesheet = ''; 631 foreach ( self::PRESETS_METADATA as $preset ) { 632 $values = _wp_array_get( $settings, $preset['path'], array() ); 633 foreach ( $values as $value ) { 634 foreach ( $preset['classes'] as $class ) { 635 $stylesheet .= self::to_ruleset( 636 $selector . '.has-' . $value['slug'] . '-' . $class['class_suffix'], 637 array( 638 array( 639 'name' => $class['property_name'], 640 'value' => $value[ $preset['value_key'] ] . ' !important', 641 ), 642 ) 643 ); 644 } 645 } 646 } 647 648 return $stylesheet; 649 } 650 651 /** 652 * Given the block settings, it extracts the CSS Custom Properties 653 * for the presets and adds them to the $declarations array 654 * following the format: 655 * 656 * ```php 657 * array( 658 * 'name' => 'property_name', 659 * 'value' => 'property_value, 660 * ) 661 * ``` 662 * 663 * @since 5.8.0 664 * 665 * @param array $settings Settings to process. 666 * 667 * @return array Returns the modified $declarations. 668 */ 669 private static function compute_preset_vars( $settings ) { 670 $declarations = array(); 671 foreach ( self::PRESETS_METADATA as $preset ) { 672 $values = _wp_array_get( $settings, $preset['path'], array() ); 673 foreach ( $values as $value ) { 674 $declarations[] = array( 675 'name' => '--wp--preset--' . $preset['css_var_infix'] . '--' . $value['slug'], 676 'value' => $value[ $preset['value_key'] ], 677 ); 678 } 679 } 680 681 return $declarations; 682 } 683 684 /** 685 * Given an array of settings, it extracts the CSS Custom Properties 686 * for the custom values and adds them to the $declarations 687 * array following the format: 688 * 689 * ```php 690 * array( 691 * 'name' => 'property_name', 692 * 'value' => 'property_value, 693 * ) 694 * ``` 695 * 696 * @since 5.8.0 697 * 698 * @param array $settings Settings to process. 699 * 700 * @return array Returns the modified $declarations. 701 */ 702 private static function compute_theme_vars( $settings ) { 703 $declarations = array(); 704 $custom_values = _wp_array_get( $settings, array( 'custom' ), array() ); 705 $css_vars = self::flatten_tree( $custom_values ); 706 foreach ( $css_vars as $key => $value ) { 707 $declarations[] = array( 708 'name' => '--wp--custom--' . $key, 709 'value' => $value, 710 ); 711 } 712 713 return $declarations; 714 } 715 716 /** 717 * Given a tree, it creates a flattened one 718 * by merging the keys and binding the leaf values 719 * to the new keys. 720 * 721 * It also transforms camelCase names into kebab-case 722 * and substitutes '/' by '-'. 723 * 724 * This is thought to be useful to generate 725 * CSS Custom Properties from a tree, 726 * although there's nothing in the implementation 727 * of this function that requires that format. 728 * 729 * For example, assuming the given prefix is '--wp' 730 * and the token is '--', for this input tree: 731 * 732 * { 733 * 'some/property': 'value', 734 * 'nestedProperty': { 735 * 'sub-property': 'value' 736 * } 737 * } 738 * 739 * it'll return this output: 740 * 741 * { 742 * '--wp--some-property': 'value', 743 * '--wp--nested-property--sub-property': 'value' 744 * } 745 * 746 * @since 5.8.0 747 * 748 * @param array $tree Input tree to process. 749 * @param string $prefix Prefix to prepend to each variable. '' by default. 750 * @param string $token Token to use between levels. '--' by default. 751 * 752 * @return array The flattened tree. 753 */ 754 private static function flatten_tree( $tree, $prefix = '', $token = '--' ) { 755 $result = array(); 756 foreach ( $tree as $property => $value ) { 757 $new_key = $prefix . str_replace( 758 '/', 759 '-', 760 strtolower( preg_replace( '/(?<!^)[A-Z]/', '-$0', $property ) ) // CamelCase to kebab-case. 761 ); 762 763 if ( is_array( $value ) ) { 764 $new_prefix = $new_key . $token; 765 $result = array_merge( 766 $result, 767 self::flatten_tree( $value, $new_prefix, $token ) 768 ); 769 } else { 770 $result[ $new_key ] = $value; 771 } 772 } 773 return $result; 774 } 775 776 /** 777 * Given a styles array, it extracts the style properties 778 * and adds them to the $declarations array following the format: 779 * 780 * ```php 781 * array( 782 * 'name' => 'property_name', 783 * 'value' => 'property_value, 784 * ) 785 * ``` 786 * 787 * @since 5.8.0 788 * 789 * @param array $styles Styles to process. 790 * 791 * @return array Returns the modified $declarations. 792 */ 793 private static function compute_style_properties( $styles ) { 794 $declarations = array(); 795 if ( empty( $styles ) ) { 796 return $declarations; 797 } 798 799 $properties = array(); 800 foreach ( self::PROPERTIES_METADATA as $name => $metadata ) { 801 // Some properties can be shorthand properties, meaning that 802 // they contain multiple values instead of a single one. 803 // An example of this is the padding property. 804 if ( self::has_properties( $metadata ) ) { 805 foreach ( $metadata['properties'] as $property ) { 806 $properties[] = array( 807 'name' => $name . '-' . $property, 808 'value' => array_merge( $metadata['value'], array( $property ) ), 809 ); 810 } 811 } else { 812 $properties[] = array( 813 'name' => $name, 814 'value' => $metadata['value'], 815 ); 816 } 817 } 818 819 foreach ( $properties as $prop ) { 820 $value = self::get_property_value( $styles, $prop['value'] ); 821 if ( empty( $value ) ) { 822 continue; 823 } 824 825 $declarations[] = array( 826 'name' => $prop['name'], 827 'value' => $value, 828 ); 829 } 830 831 return $declarations; 832 } 833 834 /** 835 * Whether the metadata contains a key named properties. 836 * 837 * @since 5.8.0 838 * 839 * @param array $metadata Description of the style property. 840 * 841 * @return boolean True if properties exists, false otherwise. 842 */ 843 private static function has_properties( $metadata ) { 844 if ( array_key_exists( 'properties', $metadata ) ) { 845 return true; 846 } 847 848 return false; 849 } 850 851 /** 852 * Returns the style property for the given path. 853 * 854 * It also converts CSS Custom Property stored as 855 * "var:preset|color|secondary" to the form 856 * "--wp--preset--color--secondary". 857 * 858 * @since 5.8.0 859 * 860 * @param array $styles Styles subtree. 861 * @param array $path Which property to process. 862 * 863 * @return string Style property value. 864 */ 865 private static function get_property_value( $styles, $path ) { 866 $value = _wp_array_get( $styles, $path, '' ); 867 868 if ( '' === $value ) { 869 return $value; 870 } 871 872 $prefix = 'var:'; 873 $prefix_len = strlen( $prefix ); 874 $token_in = '|'; 875 $token_out = '--'; 876 if ( 0 === strncmp( $value, $prefix, $prefix_len ) ) { 877 $unwrapped_name = str_replace( 878 $token_in, 879 $token_out, 880 substr( $value, $prefix_len ) 881 ); 882 $value = "var(--wp--$unwrapped_name)"; 883 } 884 885 return $value; 886 } 887 888 /** 213 889 * Builds metadata for the setting nodes, which returns in the form of: 214 890 * 215 * [ 216 * [ 217 * 'path' => ['path', 'to', 'some', 'node' ] 218 * ], 219 * [ 220 * 'path' => [ 'path', 'to', 'other', 'node' ] 221 * ], 222 * ] 891 * [ 892 * [ 893 * 'path' => ['path', 'to', 'some', 'node' ], 894 * 'selector' => 'CSS selector for some node' 895 * ], 896 * [ 897 * 'path' => [ 'path', 'to', 'other', 'node' ], 898 * 'selector' => 'CSS selector for other node' 899 * ], 900 * ] 223 901 * 224 902 * @since 5.8.0 225 903 * 226 904 * @param array $theme_json The tree to extract setting nodes from. 905 * @param array $selectors List of selectors per block. 906 * 227 907 * @return array 228 908 */ 229 private static function get_setting_nodes( $theme_json ) {909 private static function get_setting_nodes( $theme_json, $selectors = array() ) { 230 910 $nodes = array(); 231 911 if ( ! isset( $theme_json['settings'] ) ) { … … 235 915 // Top-level. 236 916 $nodes[] = array( 237 'path' => array( 'settings' ), 917 'path' => array( 'settings' ), 918 'selector' => self::ROOT_BLOCK_SELECTOR, 238 919 ); 239 920 … … 244 925 245 926 foreach ( $theme_json['settings']['blocks'] as $name => $node ) { 927 $selector = null; 928 if ( isset( $selectors[ $name ]['selector'] ) ) { 929 $selector = $selectors[ $name ]['selector']; 930 } 931 246 932 $nodes[] = array( 247 'path' => array( 'settings', 'blocks', $name ), 933 'path' => array( 'settings', 'blocks', $name ), 934 'selector' => $selector, 248 935 ); 936 } 937 938 return $nodes; 939 } 940 941 942 /** 943 * Builds metadata for the style nodes, which returns in the form of: 944 * 945 * [ 946 * [ 947 * 'path' => [ 'path', 'to', 'some', 'node' ], 948 * 'selector' => 'CSS selector for some node' 949 * ], 950 * [ 951 * 'path' => ['path', 'to', 'other', 'node' ], 952 * 'selector' => 'CSS selector for other node' 953 * ], 954 * ] 955 * 956 * @since 5.8.0 957 * 958 * @param array $theme_json The tree to extract style nodes from. 959 * @param array $selectors List of selectors per block. 960 * 961 * @return array 962 */ 963 private static function get_style_nodes( $theme_json, $selectors = array() ) { 964 $nodes = array(); 965 if ( ! isset( $theme_json['styles'] ) ) { 966 return $nodes; 967 } 968 969 // Top-level. 970 $nodes[] = array( 971 'path' => array( 'styles' ), 972 'selector' => self::ROOT_BLOCK_SELECTOR, 973 ); 974 975 if ( isset( $theme_json['styles']['elements'] ) ) { 976 foreach ( $theme_json['styles']['elements'] as $element => $node ) { 977 $nodes[] = array( 978 'path' => array( 'styles', 'elements', $element ), 979 'selector' => self::ELEMENTS[ $element ], 980 ); 981 } 982 } 983 984 // Blocks. 985 if ( ! isset( $theme_json['styles']['blocks'] ) ) { 986 return $nodes; 987 } 988 989 foreach ( $theme_json['styles']['blocks'] as $name => $node ) { 990 $selector = null; 991 if ( isset( $selectors[ $name ]['selector'] ) ) { 992 $selector = $selectors[ $name ]['selector']; 993 } 994 995 $nodes[] = array( 996 'path' => array( 'styles', 'blocks', $name ), 997 'selector' => $selector, 998 ); 999 1000 if ( isset( $theme_json['styles']['blocks'][ $name ]['elements'] ) ) { 1001 foreach ( $theme_json['styles']['blocks'][ $name ]['elements'] as $element => $node ) { 1002 $nodes[] = array( 1003 'path' => array( 'styles', 'blocks', $name, 'elements', $element ), 1004 'selector' => $selectors[ $name ]['elements'][ $element ], 1005 ); 1006 } 1007 } 249 1008 } 250 1009 -
trunk/src/wp-includes/default-filters.php
r50836 r50973 536 536 add_action( 'wp_enqueue_scripts', 'wp_localize_jquery_ui_datepicker', 1000 ); 537 537 add_action( 'wp_enqueue_scripts', 'wp_common_block_scripts_and_styles' ); 538 add_action( 'wp_enqueue_scripts', 'wp_enqueue_global_styles' ); 538 539 add_action( 'admin_enqueue_scripts', 'wp_localize_jquery_ui_datepicker', 1000 ); 539 540 add_action( 'admin_enqueue_scripts', 'wp_common_block_scripts_and_styles' ); -
trunk/src/wp-includes/script-loader.php
r50934 r50973 2234 2234 2235 2235 /** 2236 * Enqueues the global styles defined via theme.json. 2237 * 2238 * @since 5.8.0 2239 * 2240 * @return void 2241 */ 2242 function wp_enqueue_global_styles() { 2243 if ( ! WP_Theme_JSON_Resolver::theme_has_support() ) { 2244 return; 2245 } 2246 2247 $can_use_cache = ( 2248 ( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG ) && 2249 ( ! defined( 'SCRIPT_DEBUG' ) || ! SCRIPT_DEBUG ) && 2250 ( ! defined( 'REST_REQUEST' ) || ! REST_REQUEST ) && 2251 ! is_admin() 2252 ); 2253 2254 $stylesheet = null; 2255 if ( $can_use_cache ) { 2256 $cache = get_transient( 'global_styles' ); 2257 if ( $cache ) { 2258 $stylesheet = $cache; 2259 } 2260 } 2261 2262 if ( null === $stylesheet ) { 2263 $settings = get_default_block_editor_settings(); 2264 $theme_json = WP_Theme_JSON_Resolver::get_merged_data( $settings ); 2265 $stylesheet = $theme_json->get_stylesheet(); 2266 2267 if ( $can_use_cache ) { 2268 set_transient( 'global_styles', $stylesheet, MINUTE_IN_SECONDS ); 2269 } 2270 } 2271 2272 if ( empty( $stylesheet ) ) { 2273 return; 2274 } 2275 2276 wp_register_style( 'global-styles', false, array(), true, true ); 2277 wp_add_inline_style( 'global-styles', $stylesheet ); 2278 wp_enqueue_style( 'global-styles' ); 2279 } 2280 2281 /** 2236 2282 * Checks if the editor scripts and styles for all registered block types 2237 2283 * should be enqueued on the current screen. -
trunk/tests/phpunit/tests/theme/wpThemeJson.php
r50967 r50973 35 35 ), 36 36 'styles' => array( 37 'color' => array( 38 'link' => 'blue', 37 'elements' => array( 38 'link' => array( 39 'color' => array( 40 'text' => '#111', 41 ), 42 ), 39 43 ), 40 44 ), … … 58 62 59 63 $this->assertEqualSetsWithIndex( $expected, $actual ); 64 } 65 66 function test_get_stylesheet() { 67 $theme_json = new WP_Theme_JSON( 68 array( 69 'version' => WP_Theme_JSON::LATEST_SCHEMA, 70 'settings' => array( 71 'color' => array( 72 'text' => 'value', 73 'palette' => array( 74 array( 75 'slug' => 'grey', 76 'color' => 'grey', 77 ), 78 ), 79 ), 80 'misc' => 'value', 81 'blocks' => array( 82 'core/group' => array( 83 'custom' => array( 84 'base-font' => 16, 85 'line-height' => array( 86 'small' => 1.2, 87 'medium' => 1.4, 88 'large' => 1.8, 89 ), 90 ), 91 ), 92 ), 93 ), 94 'styles' => array( 95 'color' => array( 96 'text' => 'var:preset|color|grey', 97 ), 98 'misc' => 'value', 99 'elements' => array( 100 'link' => array( 101 'color' => array( 102 'text' => '#111', 103 'background' => '#333', 104 ), 105 ), 106 ), 107 'blocks' => array( 108 'core/group' => array( 109 'elements' => array( 110 'link' => array( 111 'color' => array( 112 'text' => '#111', 113 ), 114 ), 115 ), 116 'spacing' => array( 117 'padding' => array( 118 'top' => '12px', 119 'bottom' => '24px', 120 ), 121 ), 122 ), 123 'core/heading' => array( 124 'color' => array( 125 'text' => '#123456', 126 ), 127 'elements' => array( 128 'link' => array( 129 'color' => array( 130 'text' => '#111', 131 'background' => '#333', 132 ), 133 'typography' => array( 134 'fontSize' => '60px', 135 ), 136 ), 137 ), 138 ), 139 'core/post-date' => array( 140 'color' => array( 141 'text' => '#123456', 142 ), 143 'elements' => array( 144 'link' => array( 145 'color' => array( 146 'background' => '#777', 147 'text' => '#555', 148 ), 149 ), 150 ), 151 ), 152 ), 153 ), 154 'misc' => 'value', 155 ) 156 ); 157 158 $this->assertEquals( 159 'body{--wp--preset--color--grey: grey;}.wp-block-group{--wp--custom--base-font: 16;--wp--custom--line-height--small: 1.2;--wp--custom--line-height--medium: 1.4;--wp--custom--line-height--large: 1.8;}body{color: var(--wp--preset--color--grey);}a{background-color: #333;color: #111;}.wp-block-group{padding-top: 12px;padding-bottom: 24px;}.wp-block-group a{color: #111;}h1,h2,h3,h4,h5,h6{color: #123456;}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{background-color: #333;color: #111;font-size: 60px;}.wp-block-post-date{color: #123456;}.wp-block-post-date a{background-color: #777;color: #555;}.has-grey-color{color: grey !important;}.has-grey-background-color{background-color: grey !important;}', 160 $theme_json->get_stylesheet() 161 ); 162 $this->assertEquals( 163 'body{color: var(--wp--preset--color--grey);}a{background-color: #333;color: #111;}.wp-block-group{padding-top: 12px;padding-bottom: 24px;}.wp-block-group a{color: #111;}h1,h2,h3,h4,h5,h6{color: #123456;}h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{background-color: #333;color: #111;font-size: 60px;}.wp-block-post-date{color: #123456;}.wp-block-post-date a{background-color: #777;color: #555;}.has-grey-color{color: grey !important;}.has-grey-background-color{background-color: grey !important;}', 164 $theme_json->get_stylesheet( 'block_styles' ) 165 ); 166 $this->assertEquals( 167 'body{--wp--preset--color--grey: grey;}.wp-block-group{--wp--custom--base-font: 16;--wp--custom--line-height--small: 1.2;--wp--custom--line-height--medium: 1.4;--wp--custom--line-height--large: 1.8;}', 168 $theme_json->get_stylesheet( 'css_variables' ) 169 ); 170 } 171 172 function test_get_stylesheet_preset_rules_come_after_block_rules() { 173 $theme_json = new WP_Theme_JSON( 174 array( 175 'version' => WP_Theme_JSON::LATEST_SCHEMA, 176 'settings' => array( 177 'blocks' => array( 178 'core/group' => array( 179 'color' => array( 180 'palette' => array( 181 array( 182 'slug' => 'grey', 183 'color' => 'grey', 184 ), 185 ), 186 ), 187 ), 188 ), 189 ), 190 'styles' => array( 191 'blocks' => array( 192 'core/group' => array( 193 'color' => array( 194 'text' => 'red', 195 ), 196 ), 197 ), 198 ), 199 ) 200 ); 201 202 $this->assertEquals( 203 '.wp-block-group{--wp--preset--color--grey: grey;}.wp-block-group{color: red;}.wp-block-group.has-grey-color{color: grey !important;}.wp-block-group.has-grey-background-color{background-color: grey !important;}', 204 $theme_json->get_stylesheet() 205 ); 206 $this->assertEquals( 207 '.wp-block-group{color: red;}.wp-block-group.has-grey-color{color: grey !important;}.wp-block-group.has-grey-background-color{background-color: grey !important;}', 208 $theme_json->get_stylesheet( 'block_styles' ) 209 ); 210 } 211 212 public function test_get_stylesheet_preset_values_are_marked_as_important() { 213 $theme_json = new WP_Theme_JSON( 214 array( 215 'version' => WP_Theme_JSON::LATEST_SCHEMA, 216 'settings' => array( 217 'color' => array( 218 'palette' => array( 219 array( 220 'slug' => 'grey', 221 'color' => 'grey', 222 ), 223 ), 224 ), 225 ), 226 'styles' => array( 227 'blocks' => array( 228 'core/paragraph' => array( 229 'color' => array( 230 'text' => 'red', 231 'background' => 'blue', 232 ), 233 'typography' => array( 234 'fontSize' => '12px', 235 'lineHeight' => '1.3', 236 ), 237 ), 238 ), 239 ), 240 ) 241 ); 242 243 $this->assertEquals( 244 'body{--wp--preset--color--grey: grey;}p{background-color: blue;color: red;font-size: 12px;line-height: 1.3;}.has-grey-color{color: grey !important;}.has-grey-background-color{background-color: grey !important;}', 245 $theme_json->get_stylesheet() 246 ); 60 247 } 61 248 … … 251 438 'color' => array( 252 439 'custom' => false, 440 ), 441 ), 442 ), 443 ), 444 'styles' => array( 445 'typography' => array( 446 'fontSize' => '12', 447 ), 448 'blocks' => array( 449 'core/group' => array( 450 'spacing' => array( 451 'padding' => array( 452 'top' => '12px', 453 'bottom' => '12px', 454 ), 455 ), 456 ), 457 'core/list' => array( 458 'typography' => array( 459 'fontSize' => '12', 460 ), 461 'color' => array( 462 'background' => 'brown', 253 463 ), 254 464 ),
Note: See TracChangeset
for help on using the changeset viewer.