From 237de4d8662bf268993f1f6da1bcedee3554a67b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Wed, 27 Jan 2021 22:51:44 +0100 Subject: [PATCH 1/4] Separate root and inheritance --- lib/class-wp-theme-json-resolver.php | 15 +++-- lib/class-wp-theme-json.php | 47 +++++++++---- lib/experimental-default-theme.json | 2 +- lib/global-styles.php | 67 ++++++++++--------- .../components/use-editor-feature/index.js | 6 +- .../editor/global-styles-provider.js | 18 +++-- .../edit-site/src/components/editor/utils.js | 21 +++--- .../components/sidebar/color-palette-panel.js | 4 +- .../sidebar/global-styles-sidebar.js | 12 ++-- ...ass-wp-theme-json-legacy-settings-test.php | 28 +++++--- phpunit/class-wp-theme-json-test.php | 54 ++++++++------- 11 files changed, 159 insertions(+), 115 deletions(-) diff --git a/lib/class-wp-theme-json-resolver.php b/lib/class-wp-theme-json-resolver.php index 36bcb603cccd0..d54ae84c8dcd0 100644 --- a/lib/class-wp-theme-json-resolver.php +++ b/lib/class-wp-theme-json-resolver.php @@ -193,7 +193,8 @@ private static function get_core_origin() { return self::$core; } - $config = self::get_from_file( __DIR__ . '/experimental-default-theme.json' ); + $all_blocks = WP_Theme_JSON::ALL_BLOCKS_NAME; + $config = self::get_from_file( __DIR__ . '/experimental-default-theme.json' ); self::translate_presets( $config ); // Start i18n logic to remove when JSON i18 strings are extracted. @@ -211,8 +212,8 @@ private static function get_core_origin() { 'vivid-cyan-blue' => __( 'Vivid cyan blue', 'gutenberg' ), 'vivid-purple' => __( 'Vivid purple', 'gutenberg' ), ); - if ( ! empty( $config['settings']['global']['color']['palette'] ) ) { - foreach ( $config['settings']['global']['color']['palette'] as &$color ) { + if ( ! empty( $config['settings'][ $all_blocks ]['color']['palette'] ) ) { + foreach ( $config['settings'][ $all_blocks ]['color']['palette'] as &$color ) { $color['name'] = $default_colors_i18n[ $color['slug'] ]; } } @@ -231,8 +232,8 @@ private static function get_core_origin() { 'electric-grass' => __( 'Electric grass', 'gutenberg' ), 'midnight' => __( 'Midnight', 'gutenberg' ), ); - if ( ! empty( $config['settings']['global']['color']['gradients'] ) ) { - foreach ( $config['settings']['global']['color']['gradients'] as &$gradient ) { + if ( ! empty( $config['settings'][ $all_blocks ]['color']['gradients'] ) ) { + foreach ( $config['settings'][ $all_blocks ]['color']['gradients'] as &$gradient ) { $gradient['name'] = $default_gradients_i18n[ $gradient['slug'] ]; } } @@ -244,8 +245,8 @@ private static function get_core_origin() { 'large' => __( 'Large', 'gutenberg' ), 'huge' => __( 'Huge', 'gutenberg' ), ); - if ( ! empty( $config['settings']['global']['typography']['fontSizes'] ) ) { - foreach ( $config['settings']['global']['typography']['fontSizes'] as &$font_size ) { + if ( ! empty( $config['settings'][ $all_blocks ]['typography']['fontSizes'] ) ) { + foreach ( $config['settings'][ $all_blocks ]['typography']['fontSizes'] as &$font_size ) { $font_size['name'] = $default_font_sizes_i18n[ $font_size['slug'] ]; } } diff --git a/lib/class-wp-theme-json.php b/lib/class-wp-theme-json.php index 4d117715f0cd1..e433651727f86 100644 --- a/lib/class-wp-theme-json.php +++ b/lib/class-wp-theme-json.php @@ -28,25 +28,40 @@ class WP_Theme_JSON { private static $blocks_metadata = null; /** - * The name of the global block. + * How to address all the blocks + * in the theme.json file. + */ + const ALL_BLOCKS_NAME = '*'; + + /** + * The CSS selector for the * block, + * only using to generate presets. * * @var string */ - const GLOBAL_NAME = 'global'; + const ALL_BLOCKS_SELECTOR = ':root'; /** - * The CSS selector for the global block. + * How to address the root block + * in the theme.json file. * * @var string */ - const GLOBAL_SELECTOR = ':root'; + const ROOT_BLOCK_NAME = 'root'; /** - * The supported properties of the global block. + * The CSS selector for the root block. + * + * @var string + */ + const ROOT_BLOCK_SELECTOR = ':root'; + + /** + * The supported properties of the root block. * * @var array */ - const GLOBAL_SUPPORTS = array( + const ROOT_BLOCK_SUPPORTS = array( '--wp--style--color--link', 'background', 'backgroundColor', @@ -439,7 +454,7 @@ private static function get_case_mappings() { * Example: * * { - * 'global': { + * 'root': { * 'selector': ':root' * 'supports': [ 'fontSize', 'backgroundColor' ], * }, @@ -457,9 +472,17 @@ private static function get_blocks_metadata() { } self::$blocks_metadata = array( - self::GLOBAL_NAME => array( - 'selector' => self::GLOBAL_SELECTOR, - 'supports' => self::GLOBAL_SUPPORTS, + self::ROOT_BLOCK_NAME => array( + 'selector' => self::ROOT_BLOCK_SELECTOR, + 'supports' => self::ROOT_BLOCK_SUPPORTS, + ), + // By make supports an empty array + // this won't have any styles associated + // but still allows adding settings + // and generate presets. + self::ALL_BLOCKS_NAME => array( + 'selector' => self::ALL_BLOCKS_SELECTOR, + 'supports' => array(), ), ); @@ -746,7 +769,7 @@ private static function compute_style_properties( &$declarations, $styles, $supp * @param string $selector Selector wrapping the classes. */ private static function compute_preset_classes( &$stylesheet, $settings, $selector ) { - if ( self::GLOBAL_SELECTOR === $selector ) { + if ( self::ROOT_BLOCK_SELECTOR === $selector ) { // Classes at the global level do not need any CSS prefixed, // and we don't want to increase its specificity. $selector = ''; @@ -987,7 +1010,7 @@ private function get_block_styles() { * Example: * * { - * 'global': { + * 'root': { * 'color': { * 'custom': true * } diff --git a/lib/experimental-default-theme.json b/lib/experimental-default-theme.json index d4c363788d7eb..9e8c3587ba5b0 100644 --- a/lib/experimental-default-theme.json +++ b/lib/experimental-default-theme.json @@ -1,6 +1,6 @@ { "settings": { - "global": { + "*": { "color": { "palette": [ { diff --git a/lib/global-styles.php b/lib/global-styles.php index 0f717938ae078..7fbc1cc9430ed 100644 --- a/lib/global-styles.php +++ b/lib/global-styles.php @@ -22,60 +22,61 @@ function gutenberg_experimental_global_styles_has_theme_json_support() { * @return array Config that adheres to the theme.json schema. */ function gutenberg_experimental_global_styles_get_theme_support_settings( $settings ) { - $theme_settings = array(); - $theme_settings['settings'] = array(); - $theme_settings['settings']['global'] = array(); + $all_blocks = WP_Theme_JSON::ALL_BLOCKS_NAME; + $theme_settings = array(); + $theme_settings['settings'] = array(); + $theme_settings['settings'][ $all_blocks ] = array(); // Deprecated theme supports. if ( isset( $settings['disableCustomColors'] ) ) { - if ( ! isset( $theme_settings['settings']['global']['color'] ) ) { - $theme_settings['settings']['global']['color'] = array(); + if ( ! isset( $theme_settings['settings'][ $all_blocks ]['color'] ) ) { + $theme_settings['settings'][ $all_blocks ]['color'] = array(); } - $theme_settings['settings']['global']['color']['custom'] = ! $settings['disableCustomColors']; + $theme_settings['settings'][ $all_blocks ]['color']['custom'] = ! $settings['disableCustomColors']; } if ( isset( $settings['disableCustomGradients'] ) ) { - if ( ! isset( $theme_settings['settings']['global']['color'] ) ) { - $theme_settings['settings']['global']['color'] = array(); + if ( ! isset( $theme_settings['settings'][ $all_blocks ]['color'] ) ) { + $theme_settings['settings'][ $all_blocks ]['color'] = array(); } - $theme_settings['settings']['global']['color']['customGradient'] = ! $settings['disableCustomGradients']; + $theme_settings['settings'][ $all_blocks ]['color']['customGradient'] = ! $settings['disableCustomGradients']; } if ( isset( $settings['disableCustomFontSizes'] ) ) { - if ( ! isset( $theme_settings['settings']['global']['typography'] ) ) { - $theme_settings['settings']['global']['typography'] = array(); + if ( ! isset( $theme_settings['settings'][ $all_blocks ]['typography'] ) ) { + $theme_settings['settings'][ $all_blocks ]['typography'] = array(); } - $theme_settings['settings']['global']['typography']['customFontSize'] = ! $settings['disableCustomFontSizes']; + $theme_settings['settings'][ $all_blocks ]['typography']['customFontSize'] = ! $settings['disableCustomFontSizes']; } if ( isset( $settings['enableCustomLineHeight'] ) ) { - if ( ! isset( $theme_settings['settings']['global']['typography'] ) ) { - $theme_settings['settings']['global']['typography'] = array(); + if ( ! isset( $theme_settings['settings'][ $all_blocks ]['typography'] ) ) { + $theme_settings['settings'][ $all_blocks ]['typography'] = array(); } - $theme_settings['settings']['global']['typography']['customLineHeight'] = $settings['enableCustomLineHeight']; + $theme_settings['settings'][ $all_blocks ]['typography']['customLineHeight'] = $settings['enableCustomLineHeight']; } if ( isset( $settings['enableCustomUnits'] ) ) { - if ( ! isset( $theme_settings['settings']['global']['spacing'] ) ) { - $theme_settings['settings']['global']['spacing'] = array(); + if ( ! isset( $theme_settings['settings'][ $all_blocks ]['spacing'] ) ) { + $theme_settings['settings'][ $all_blocks ]['spacing'] = array(); } - $theme_settings['settings']['global']['spacing']['units'] = ( true === $settings['enableCustomUnits'] ) ? + $theme_settings['settings'][ $all_blocks ]['spacing']['units'] = ( true === $settings['enableCustomUnits'] ) ? array( 'px', 'em', 'rem', 'vh', 'vw' ) : $settings['enableCustomUnits']; } if ( isset( $settings['colors'] ) ) { - if ( ! isset( $theme_settings['settings']['global']['color'] ) ) { - $theme_settings['settings']['global']['color'] = array(); + if ( ! isset( $theme_settings['settings'][ $all_blocks ]['color'] ) ) { + $theme_settings['settings'][ $all_blocks ]['color'] = array(); } - $theme_settings['settings']['global']['color']['palette'] = $settings['colors']; + $theme_settings['settings'][ $all_blocks ]['color']['palette'] = $settings['colors']; } if ( isset( $settings['gradients'] ) ) { - if ( ! isset( $theme_settings['settings']['global']['color'] ) ) { - $theme_settings['settings']['global']['color'] = array(); + if ( ! isset( $theme_settings['settings'][ $all_blocks ]['color'] ) ) { + $theme_settings['settings'][ $all_blocks ]['color'] = array(); } - $theme_settings['settings']['global']['color']['gradients'] = $settings['gradients']; + $theme_settings['settings'][ $all_blocks ]['color']['gradients'] = $settings['gradients']; } if ( isset( $settings['fontSizes'] ) ) { @@ -86,25 +87,25 @@ function gutenberg_experimental_global_styles_get_theme_support_settings( $setti $font_size['size'] = $font_size['size'] . 'px'; } } - if ( ! isset( $theme_settings['settings']['global']['typography'] ) ) { - $theme_settings['settings']['global']['typography'] = array(); + if ( ! isset( $theme_settings['settings'][ $all_blocks ]['typography'] ) ) { + $theme_settings['settings'][ $all_blocks ]['typography'] = array(); } - $theme_settings['settings']['global']['typography']['fontSizes'] = $font_sizes; + $theme_settings['settings'][ $all_blocks ]['typography']['fontSizes'] = $font_sizes; } // Things that didn't land in core yet, so didn't have a setting assigned. if ( current( (array) get_theme_support( 'custom-spacing' ) ) ) { - if ( ! isset( $theme_settings['settings']['global']['spacing'] ) ) { - $theme_settings['settings']['global']['spacing'] = array(); + if ( ! isset( $theme_settings['settings'][ $all_blocks ]['spacing'] ) ) { + $theme_settings['settings'][ $all_blocks ]['spacing'] = array(); } - $theme_settings['settings']['global']['spacing']['customPadding'] = true; + $theme_settings['settings'][ $all_blocks ]['spacing']['customPadding'] = true; } if ( current( (array) get_theme_support( 'experimental-link-color' ) ) ) { - if ( ! isset( $theme_settings['settings']['global']['color'] ) ) { - $theme_settings['settings']['global']['color'] = array(); + if ( ! isset( $theme_settings['settings'][ $all_blocks ]['color'] ) ) { + $theme_settings['settings'][ $all_blocks ]['color'] = array(); } - $theme_settings['settings']['global']['color']['link'] = true; + $theme_settings['settings'][ $all_blocks ]['color']['link'] = true; } return $theme_settings; diff --git a/packages/block-editor/src/components/use-editor-feature/index.js b/packages/block-editor/src/components/use-editor-feature/index.js index 098ed231d8c18..c521ab16fd0b6 100644 --- a/packages/block-editor/src/components/use-editor-feature/index.js +++ b/packages/block-editor/src/components/use-editor-feature/index.js @@ -98,11 +98,11 @@ export default function useEditorFeature( featurePath ) { } // 1 - Use __experimental features, if available. - // We cascade to the global value if the block one is not available. - const globalPath = `__experimentalFeatures.global.${ featurePath }`; + // We cascade to the * value if the block one is not available. + const fallbackPath = `__experimentalFeatures.*.${ featurePath }`; const blockPath = `__experimentalFeatures.${ context }.${ featurePath }`; const experimentalFeaturesResult = - get( settings, blockPath ) ?? get( settings, globalPath ); + get( settings, blockPath ) ?? get( settings, fallbackPath ); if ( experimentalFeaturesResult !== undefined ) { return experimentalFeaturesResult; } diff --git a/packages/edit-site/src/components/editor/global-styles-provider.js b/packages/edit-site/src/components/editor/global-styles-provider.js index 7b55d3b5a2505..b299179068508 100644 --- a/packages/edit-site/src/components/editor/global-styles-provider.js +++ b/packages/edit-site/src/components/editor/global-styles-provider.js @@ -24,9 +24,11 @@ import { useSelect, useDispatch } from '@wordpress/data'; * Internal dependencies */ import { - GLOBAL_CONTEXT_NAME, - GLOBAL_CONTEXT_SELECTOR, - GLOBAL_CONTEXT_SUPPORTS, + ALL_BLOCKS_NAME, + ALL_BLOCKS_SELECTOR, + ROOT_BLOCK_NAME, + ROOT_BLOCK_SELECTOR, + ROOT_BLOCK_SUPPORTS, getValueFromVariable, getPresetVariable, } from './utils'; @@ -81,9 +83,13 @@ const extractSupportKeys = ( supports ) => { const getContexts = ( blockTypes ) => { const result = { - [ GLOBAL_CONTEXT_NAME ]: { - selector: GLOBAL_CONTEXT_SELECTOR, - supports: GLOBAL_CONTEXT_SUPPORTS, + [ ROOT_BLOCK_NAME ]: { + selector: ROOT_BLOCK_SELECTOR, + supports: ROOT_BLOCK_SUPPORTS, + }, + [ ALL_BLOCKS_NAME ]: { + selector: ALL_BLOCKS_SELECTOR, + supports: [], // by being an empty array, the styles subtree will be ignored }, }; diff --git a/packages/edit-site/src/components/editor/utils.js b/packages/edit-site/src/components/editor/utils.js index 68bf1747cec40..9b5c541b8629b 100644 --- a/packages/edit-site/src/components/editor/utils.js +++ b/packages/edit-site/src/components/editor/utils.js @@ -8,9 +8,11 @@ import { get, find, forEach, camelCase, isString } from 'lodash'; import { useSelect } from '@wordpress/data'; /* Supporting data */ -export const GLOBAL_CONTEXT_NAME = 'global'; -export const GLOBAL_CONTEXT_SELECTOR = ':root'; -export const GLOBAL_CONTEXT_SUPPORTS = [ +export const ALL_BLOCKS_NAME = '*'; +export const ALL_BLOCKS_SELECTOR = ':root'; +export const ROOT_BLOCK_NAME = 'root'; +export const ROOT_BLOCK_SELECTOR = ':root'; +export const ROOT_BLOCK_SUPPORTS = [ '--wp--style--color--link', 'background', 'backgroundColor', @@ -86,10 +88,7 @@ function getPresetMetadataFromStyleProperty( styleProperty ) { export const LINK_COLOR = '--wp--style--color--link'; export const LINK_COLOR_DECLARATION = `a { color: var(${ LINK_COLOR }, #00e); }`; -export function useEditorFeature( - featurePath, - blockName = GLOBAL_CONTEXT_NAME -) { +export function useEditorFeature( featurePath, blockName = ALL_BLOCKS_NAME ) { const settings = useSelect( ( select ) => { return select( 'core/edit-site' ).getSettings(); } ); @@ -100,7 +99,7 @@ export function useEditorFeature( ) ?? get( settings, - `__experimentalFeatures.${ GLOBAL_CONTEXT_NAME }.${ featurePath }` + `__experimentalFeatures.${ ALL_BLOCKS_NAME }.${ featurePath }` ) ); } @@ -116,7 +115,7 @@ export function getPresetVariable( styles, blockName, propertyName, value ) { const { valueKey, path, cssVarInfix } = presetData; const presets = get( styles, [ blockName, ...path ] ) ?? - get( styles, [ GLOBAL_CONTEXT_NAME, ...path ] ); + get( styles, [ ALL_BLOCKS_NAME, ...path ] ); const presetObject = find( presets, ( preset ) => { return preset[ valueKey ] === value; } ); @@ -139,7 +138,7 @@ function getValueFromPresetVariable( } const presets = get( styles, [ blockName, ...presetData.path ] ) ?? - get( styles, [ GLOBAL_CONTEXT_NAME, ...presetData.path ] ); + get( styles, [ ALL_BLOCKS_NAME, ...presetData.path ] ); if ( ! presets ) { return variable; } @@ -157,7 +156,7 @@ function getValueFromPresetVariable( function getValueFromCustomVariable( styles, blockName, variable, path ) { const result = get( styles, [ blockName, 'settings', 'custom', ...path ] ) ?? - get( styles, [ GLOBAL_CONTEXT_NAME, 'settings', 'custom', ...path ] ); + get( styles, [ ALL_BLOCKS_NAME, 'settings', 'custom', ...path ] ); if ( ! result ) { return variable; } diff --git a/packages/edit-site/src/components/sidebar/color-palette-panel.js b/packages/edit-site/src/components/sidebar/color-palette-panel.js index 8ea1d54387563..30782c779e743 100644 --- a/packages/edit-site/src/components/sidebar/color-palette-panel.js +++ b/packages/edit-site/src/components/sidebar/color-palette-panel.js @@ -13,7 +13,7 @@ import { useSelect } from '@wordpress/data'; /** * Internal dependencies */ -import { useEditorFeature, GLOBAL_CONTEXT_NAME } from '../editor/utils'; +import { useEditorFeature, ALL_BLOCKS_NAME } from '../editor/utils'; /** * Shared reference to an empty array for cases where it is important to avoid @@ -45,7 +45,7 @@ export default function ColorPalettePanel( { 'palette', ] ) ?? get( baseStyles, [ - GLOBAL_CONTEXT_NAME, + ALL_BLOCKS_NAME, 'settings', 'color', 'palette', diff --git a/packages/edit-site/src/components/sidebar/global-styles-sidebar.js b/packages/edit-site/src/components/sidebar/global-styles-sidebar.js index 43054233b53cc..cd463ca476b80 100644 --- a/packages/edit-site/src/components/sidebar/global-styles-sidebar.js +++ b/packages/edit-site/src/components/sidebar/global-styles-sidebar.js @@ -24,7 +24,7 @@ import { useGlobalStylesReset, } from '../editor/global-styles-provider'; import DefaultSidebar from './default-sidebar'; -import { GLOBAL_CONTEXT_NAME } from '../editor/utils'; +import { ROOT_BLOCK_NAME } from '../editor/utils'; import { default as TypographyPanel, useHasTypographyPanel, @@ -136,7 +136,7 @@ function GlobalStylesBlockPanels( { ); return map( panels, ( { context, name, wrapperPanelTitle } ) => { - if ( name === GLOBAL_CONTEXT_NAME ) { + if ( name === ROOT_BLOCK_NAME ) { return null; } return ( @@ -168,7 +168,7 @@ export default function GlobalStylesSidebar( { } = useGlobalStylesContext(); const [ canRestart, onReset ] = useGlobalStylesReset(); - if ( typeof contexts !== 'object' || ! contexts?.[ GLOBAL_CONTEXT_NAME ] ) { + if ( typeof contexts !== 'object' || ! contexts?.[ ROOT_BLOCK_NAME ] ) { // No sidebar is shown. return null; } @@ -197,7 +197,7 @@ export default function GlobalStylesSidebar( { > @@ -218,8 +218,8 @@ export default function GlobalStylesSidebar( { array( - 'global' => array(), + $all_blocks => array(), ), ); @@ -54,10 +55,11 @@ function test_legacy_settings_blank() { } function test_legacy_settings_no_theme_support() { - $input = $this->get_editor_settings_no_theme_support(); - $expected = array( + $all_blocks = WP_Theme_JSON::ALL_BLOCKS_NAME; + $input = $this->get_editor_settings_no_theme_support(); + $expected = array( 'settings' => array( - 'global' => array( + $all_blocks => array( 'color' => array( 'custom' => true, 'customGradient' => true, @@ -79,6 +81,7 @@ function test_legacy_settings_no_theme_support() { } function test_legacy_settings_custom_units_can_be_disabled() { + $all_blocks = WP_Theme_JSON::ALL_BLOCKS_NAME; add_theme_support( 'custom-units', array() ); $input = gutenberg_get_common_block_editor_settings(); @@ -88,10 +91,11 @@ function test_legacy_settings_custom_units_can_be_disabled() { $actual = gutenberg_experimental_global_styles_get_theme_support_settings( $input ); - $this->assertEqualSetsWithIndex( $expected, $actual['settings']['global']['spacing'] ); + $this->assertEqualSetsWithIndex( $expected, $actual['settings'][ $all_blocks ]['spacing'] ); } function test_legacy_settings_custom_units_can_be_enabled() { + $all_blocks = WP_Theme_JSON::ALL_BLOCKS_NAME; add_theme_support( 'custom-units' ); $input = gutenberg_get_common_block_editor_settings(); @@ -101,10 +105,11 @@ function test_legacy_settings_custom_units_can_be_enabled() { $actual = gutenberg_experimental_global_styles_get_theme_support_settings( $input ); - $this->assertEqualSetsWithIndex( $expected, $actual['settings']['global']['spacing'] ); + $this->assertEqualSetsWithIndex( $expected, $actual['settings'][ $all_blocks ]['spacing'] ); } function test_legacy_settings_custom_units_can_be_filtered() { + $all_blocks = WP_Theme_JSON::ALL_BLOCKS_NAME; add_theme_support( 'custom-units', 'rem', 'em' ); $input = gutenberg_get_common_block_editor_settings(); @@ -114,11 +119,12 @@ function test_legacy_settings_custom_units_can_be_filtered() { $actual = gutenberg_experimental_global_styles_get_theme_support_settings( $input ); - $this->assertEqualSetsWithIndex( $expected, $actual['settings']['global']['spacing'] ); + $this->assertEqualSetsWithIndex( $expected, $actual['settings'][ $all_blocks ]['spacing'] ); } function test_legacy_settings_filled() { - $input = array( + $all_blocks = WP_Theme_JSON::ALL_BLOCKS_NAME; + $input = array( 'disableCustomColors' => true, 'disableCustomGradients' => true, 'disableCustomFontSizes' => true, @@ -149,7 +155,7 @@ function test_legacy_settings_filled() { $expected = array( 'settings' => array( - 'global' => array( + $all_blocks => array( 'color' => array( 'custom' => false, 'customGradient' => false, diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index 10e567923c4e2..34d916a546f49 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -58,11 +58,12 @@ function test_schema_validation_subtree_is_removed_if_key_invalid() { } function test_schema_validation_subtree_is_removed_if_not_array() { + $root_name = WP_Theme_JSON::ROOT_BLOCK_NAME; $theme_json = new WP_Theme_JSON( array( 'settings' => 'invalid/not/array', 'styles' => array( - 'global' => 'invalid/not/array', + $root_name => 'invalid/not/array', 'core/paragraph' => array( 'invalid/not/array' => false, ), @@ -99,6 +100,7 @@ function test_schema_validation_subtree_is_removed_if_not_array() { } function test_schema_validation_subtree_is_removed_if_empty() { + $root_name = WP_Theme_JSON::ROOT_BLOCK_NAME; $theme_json = new WP_Theme_JSON( array( 'settings' => array( @@ -107,12 +109,12 @@ function test_schema_validation_subtree_is_removed_if_empty() { 'custom' => false, ), ), - 'global' => array( + $root_name => array( 'invalid/key' => false, ), ), 'styles' => array( - 'global' => array( + $root_name => array( 'color' => array( 'link' => 'blue', ), @@ -132,7 +134,7 @@ function test_schema_validation_subtree_is_removed_if_empty() { $expected = array( 'styles' => array( - 'global' => array( + $root_name => array( 'color' => array( 'link' => 'blue', ), @@ -144,10 +146,11 @@ function test_schema_validation_subtree_is_removed_if_empty() { } function test_schema_validation_subtree_is_removed_if_style_not_supported_by_block() { + $root_name = WP_Theme_JSON::ROOT_BLOCK_NAME; $theme_json = new WP_Theme_JSON( array( 'styles' => array( - 'global' => array( + $root_name => array( 'color' => array( 'text' => 'var:preset|color|dark-gray', ), @@ -167,7 +170,7 @@ function test_schema_validation_subtree_is_removed_if_style_not_supported_by_blo $actual = $theme_json->get_raw_data(); $expected = array( 'styles' => array( - 'global' => array( + $root_name => array( 'color' => array( 'text' => 'var:preset|color|dark-gray', ), @@ -178,11 +181,12 @@ function test_schema_validation_subtree_is_removed_if_style_not_supported_by_blo } function test_get_settings() { + $root_name = WP_Theme_JSON::ROOT_BLOCK_NAME; // See schema at WP_Theme_JSON::SCHEMA. $theme_json = new WP_Theme_JSON( array( 'settings' => array( - 'global' => array( + $root_name => array( 'color' => array( 'custom' => false, ), @@ -190,7 +194,7 @@ function test_get_settings() { ), ), 'styles' => array( - 'global' => array( + $root_name => array( 'color' => array( 'link' => 'blue', ), @@ -202,7 +206,7 @@ function test_get_settings() { $result = $theme_json->get_settings(); $expected = array( - 'global' => array( + $root_name => array( 'color' => array( 'custom' => false, ), @@ -213,11 +217,12 @@ function test_get_settings() { } function test_get_stylesheet() { + $root_name = WP_Theme_JSON::ROOT_BLOCK_NAME; // See schema at WP_Theme_JSON::SCHEMA. $theme_json = new WP_Theme_JSON( array( 'settings' => array( - 'global' => array( + $root_name => array( 'color' => array( 'text' => 'value', 'palette' => array( @@ -253,7 +258,7 @@ function test_get_stylesheet() { ), ), 'styles' => array( - 'global' => array( + $root_name => array( 'color' => array( 'link' => '#111', 'text' => 'var:preset|color|grey', @@ -288,9 +293,10 @@ function test_get_stylesheet() { } public function test_merge_incoming_data() { - $initial = array( + $root_name = WP_Theme_JSON::ROOT_BLOCK_NAME; + $initial = array( 'settings' => array( - 'global' => array( + $root_name => array( 'color' => array( 'custom' => false, 'palette' => array( @@ -312,7 +318,7 @@ public function test_merge_incoming_data() { ), ), 'styles' => array( - 'global' => array( + $root_name => array( 'typography' => array( 'fontSize' => '12', ), @@ -342,7 +348,7 @@ public function test_merge_incoming_data() { $add_key_in_settings = array( 'settings' => array( - 'global' => array( + $root_name => array( 'color' => array( 'customGradient' => true, ), @@ -352,7 +358,7 @@ public function test_merge_incoming_data() { $update_key_in_settings = array( 'settings' => array( - 'global' => array( + $root_name => array( 'color' => array( 'custom' => true, ), @@ -396,7 +402,7 @@ public function test_merge_incoming_data() { $update_presets = array( 'settings' => array( - 'global' => array( + $root_name => array( 'color' => array( 'palette' => array( array( @@ -431,7 +437,7 @@ public function test_merge_incoming_data() { $expected = array( 'settings' => array( - 'global' => array( + $root_name => array( 'color' => array( 'custom' => true, 'customGradient' => true, @@ -475,7 +481,7 @@ public function test_merge_incoming_data() { ), ), 'styles' => array( - 'global' => array( + $root_name => array( 'typography' => array( 'fontSize' => '12', ), @@ -580,10 +586,11 @@ function test_remove_insecure_properties_removes_unsafe_styles_sub_properties() } function test_remove_insecure_properties_removes_non_preset_settings() { + $root_name = WP_Theme_JSON::ROOT_BLOCK_NAME; $theme_json = new WP_Theme_JSON( array( 'settings' => array( - 'global' => array( + $root_name => array( 'color' => array( 'custom' => true, 'palette' => array( @@ -616,7 +623,7 @@ function test_remove_insecure_properties_removes_non_preset_settings() { $result = $theme_json->get_raw_data(); $expected = array( 'settings' => array( - 'global' => array( + $root_name => array( 'color' => array( 'palette' => array( array( @@ -643,10 +650,11 @@ function test_remove_insecure_properties_removes_non_preset_settings() { } function test_remove_insecure_properties_removes_unsafe_preset_settings() { + $root_name = WP_Theme_JSON::ROOT_BLOCK_NAME; $theme_json = new WP_Theme_JSON( array( 'settings' => array( - 'global' => array( + $root_name => array( 'color' => array( 'palette' => array( array( @@ -704,7 +712,7 @@ function test_remove_insecure_properties_removes_unsafe_preset_settings() { $result = $theme_json->get_raw_data(); $expected = array( 'settings' => array( - 'global' => array( + $root_name => array( 'color' => array( 'palette' => array( array( From f0681eb2394df26ec9928219ff75538781faea45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Wed, 27 Jan 2021 22:19:18 +0100 Subject: [PATCH 2/4] Update docs --- .../developers/themes/theme-json.md | 78 +++++++++++++------ 1 file changed, 56 insertions(+), 22 deletions(-) diff --git a/docs/designers-developers/developers/themes/theme-json.md b/docs/designers-developers/developers/themes/theme-json.md index 222040b251485..785538dd3195f 100644 --- a/docs/designers-developers/developers/themes/theme-json.md +++ b/docs/designers-developers/developers/themes/theme-json.md @@ -34,6 +34,8 @@ By providing the block style properties in a structured way, the Block Editor ca ## Specification +This specification is the same for the three different origins that use this format: core, themes, and users. Themes can override core's defaults by creating a file called `experimental-theme.json`. Users, via the site editor, will also be also to override theme's or core's preferences via an user interface that is being worked on. + The `experimental-theme.json` file declares how a theme wants the editor configured (`settings`) as well as the style properties it sets (`styles`). ``` @@ -43,9 +45,29 @@ The `experimental-theme.json` file declares how a theme wants the editor configu } ``` -Each one of these sections is sub-divided into "contexts" that loosely map to a block. In general, one block will create one single context ―the paragraph block can be addressed via `core/paragraph`― but there are also cases where one block will create multiple contexts ―the heading block represents different HTML elements, h1 to h6, so it creates one context for each such `core/heading/h1`, `core/heading/h2`, etc. Every context has the same inner structure. +Both settings and styles can contain subsections for any registered block. As a general rule, the names of these subsections will be the block names ― we call them "block selectors". For example, the paragraph block ―whose name is `core/paragraph`― can be addressed in the settings using the key (or "block selector") `core/paragraph`: -This specification is the same for the three different origins that use this format: core, themes, and users. Themes can override core's defaults by creating a file called `experimental-theme.json`. Users, via the site editor, will also be also to override theme's or core's preferences via an user interface that is being worked on. +``` +{ + "settings": { + "core/paragraph": { ... } + } +} +``` + +There are a few cases in whiche a single block can represent different HTML markup. The heading block is one of these, as it represents h1 to h6 HTML elements. In these cases, the block will have as many block selectors as different markup variations ― `core/heading/h1`, `core/heading/h2`, etc, so they can be addressed separately: + +``` +{ + "styles": { + "core/heading/h1": { ... }, + // ... + "core/heading/h6": { ... }, + } +} +``` + +Additionally, there are two other block selectors: `root` and `*`. The `root` block selector represents the root of the site. The `*` block selector represents "all blocks" and will be discussed below in detail. ### Settings @@ -54,7 +76,7 @@ The settings section has the following structure and default values: ``` { "settings": { - "some/context": { + "some/block": { "border": { "customRadius": false /* true to opt-in */ }, @@ -88,39 +110,41 @@ The settings section has the following structure and default values: } ``` -To retain backward compatibility, `add_theme_support` declarations are retrofit in the proper categories. If a theme uses `add_theme_support('disable-custom-colors')`, it'll be the same as set `settings.global.color.custom` to `false`. If the `experimental-theme.json` contains any settings, these will take precedence over the values declared via `add_theme_support`. +Each block can configure any of these settings separately, providing a more fine-grained control over what exists via `add_theme_support`. -Settings can also be controlled by context, providing a more fine-grained control over what exists via `add_theme_support`. As an example, let's say that a theme author wants to enable custom colors for the paragraph block exclusively. This is how it'd be done: +The block settings declared under the `*` block selector affect to all blocks, unless a particular block overwrites it. It's a way to provide inheritance and quickly configure all blocks at once. To retain backward compatibility, the existing `add_theme_support` declarations that configure the block editor are retrofit in the proper categories for the `*` section. If a theme uses `add_theme_support('disable-custom-colors')`, it'll be the same as set `settings.*.color.custom` to `false`. If the `experimental-theme.json` contains any settings, these will take precedence over the values declared via `add_theme_support`. -```json +Let's say a theme author wants to enable custom colors only for the paragraph block. This is how it can be done: + +``` { "settings": { - "global": { + "*": { "color": { - "custom": false + "custom": false // Disable it for all blocks. } }, "core/paragraph": { "color": { - "custom": true + "custom": true // Paragraph overrides the setting. } } } } ``` -Note, however, that not all settings are relevant for all contexts and the blocks they represent. The settings section provides an opt-in/opt-out mechanism for themes, but it's the block's responsibility to add support for the features that are relevant to it. For example, if a block doesn't implement the `dropCap` feature, a theme can't enable it for such a block through `experimental-theme.json`. +Note, however, that not all settings are relevant for all blocks. The settings section provides an opt-in/opt-out mechanism for themes, but it's the block's responsibility to add support for the features that are relevant to it. For example, if a block doesn't implement the `dropCap` feature, a theme can't enable it for such a block through `experimental-theme.json`. #### Presets -Presets are part of the settings section. At the moment, they only work within the `global` context. Each preset value will generate a CSS Custom Property that will be added to the new stylesheet, which follow this naming schema: `--wp--preset--{preset-category}--{preset-slug}`. +Presets are part of the settings section. Each preset value will generate a CSS Custom Property that will be added to the new stylesheet, which follow this naming schema: `--wp--preset--{preset-category}--{preset-slug}`. For example, for this input: ```json { "settings": { - "global": { + "*": { "color": { "palette": [ { @@ -160,7 +184,7 @@ For example, for this input: } ``` -The output to be enqueued will be: +The output will be: ```css :root { @@ -173,18 +197,18 @@ The output to be enqueued will be: } ``` -The goal is that presets can be defined using this format, although, right now, the name property (used in the editor) can't be translated from this file. For that reason, and to maintain backward compatibility, the presets declared via `add_theme_support` will also generate the CSS Custom Properties. If the `experimental-theme.json` contains any presets, these will take precedence over the ones declared via `add_theme_support`. +To maintain backward compatibility, the presets declared via `add_theme_support` will also generate the CSS Custom Properties. If the `experimental-theme.json` contains any presets, these will take precedence over the ones declared via `add_theme_support`. #### Free-form CSS Custom Properties -In addition to create CSS Custom Properties for the presets, the theme.json also allows for themes to create their own, so they don't have to be enqueued separately. Any values declared within the `settings..custom` section will be transformed to CSS Custom Properties following this naming schema: `--wp--custom--`. +In addition to create CSS Custom Properties for the presets, the `experimental-theme.json` also allows for themes to create their own, so they don't have to be enqueued separately. Any values declared within the `settings..custom` section will be transformed to CSS Custom Properties following this naming schema: `--wp--custom--`. For example, for this input: ```json { "settings": { - "global": { + "*": { "custom": { "base-font": 16, "line-height": { @@ -213,12 +237,12 @@ Note that, the name of the variable is created by adding `--` in between each ne ### Styles -Each block declares which style properties it exposes. This has been coined as "implicit style attributes" of the block. These properties are then used to automatically generate the UI controls for the block in the editor, as well as being available through the `experimental-theme.json` file for themes to target. +Each block declares which style properties it exposes via the [block supports mechanism](../block-api/block-supports.md). The support declarations are used to automatically generate the UI controls for the block in the editor, as well as being available through the `experimental-theme.json` file for themes to target. ```json { "styles": { - "some/context": { + "some/block/selector": { "border": { "radius": "value" }, @@ -255,6 +279,11 @@ For example, an input like this: ```json { "styles": { + "root": { + "color": { + "text": "var(--wp--preset--color--primary)" + }, + }, "core/heading/h1": { "color": { "text": "var(--wp--preset--color--primary)" @@ -278,6 +307,9 @@ For example, an input like this: will append the following style rules to the stylesheet: ```css +:root { + color: var(--wp--preset--color--primary); +} h1 { color: var(--wp--preset--color--primary); font-size: calc(1px * var(--wp--preset--font-size--huge)); @@ -288,9 +320,11 @@ h4 { } ``` +The `*` block selector can't be part of the `styles` section and will be ignored if it's present. The `root` block selector will generate a style rule with the `:root` CSS selector. + #### Border Properties -| Context | Radius | +| Block | Radius | | --- | --- | | Group | Yes | | Image | Yes | @@ -299,7 +333,7 @@ h4 { These are the current color properties supported by blocks: -| Context | Background | Gradient | Link | Text | +| Block | Background | Gradient | Link | Text | | --- | --- | --- | --- | --- | | Global | Yes | Yes | Yes | Yes | | Columns | Yes | Yes | Yes | Yes | @@ -327,7 +361,7 @@ These are the current color properties supported by blocks: #### Spacing Properties -| Context | Padding | +| Block | Padding | | --- | --- | | Cover | Yes | | Group | Yes | @@ -336,7 +370,7 @@ These are the current color properties supported by blocks: These are the current typography properties supported by blocks: -| Context | Font Family | Font Size | Font Style | Font Weight | Line Height | Text Decoration | Text Transform | +| Block | Font Family | Font Size | Font Style | Font Weight | Line Height | Text Decoration | Text Transform | | --- | --- | --- | --- | --- | --- | --- | --- | | Global | Yes | Yes | Yes | Yes | Yes | Yes | Yes | | Code | - | Yes | - | - | - | - | - | From 3927fdee955567668bf7d237ba910ffc8f9cb9fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Thu, 28 Jan 2021 09:46:24 +0100 Subject: [PATCH 3/4] Change * to defaults --- lib/class-wp-theme-json.php | 2 +- lib/experimental-default-theme.json | 2 +- .../block-editor/src/components/use-editor-feature/index.js | 6 +++--- packages/edit-site/src/components/editor/utils.js | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/class-wp-theme-json.php b/lib/class-wp-theme-json.php index e433651727f86..6b8f42130e81b 100644 --- a/lib/class-wp-theme-json.php +++ b/lib/class-wp-theme-json.php @@ -31,7 +31,7 @@ class WP_Theme_JSON { * How to address all the blocks * in the theme.json file. */ - const ALL_BLOCKS_NAME = '*'; + const ALL_BLOCKS_NAME = 'defaults'; /** * The CSS selector for the * block, diff --git a/lib/experimental-default-theme.json b/lib/experimental-default-theme.json index 9e8c3587ba5b0..da910ca84747a 100644 --- a/lib/experimental-default-theme.json +++ b/lib/experimental-default-theme.json @@ -1,6 +1,6 @@ { "settings": { - "*": { + "defaults": { "color": { "palette": [ { diff --git a/packages/block-editor/src/components/use-editor-feature/index.js b/packages/block-editor/src/components/use-editor-feature/index.js index c521ab16fd0b6..6422e4f360d0c 100644 --- a/packages/block-editor/src/components/use-editor-feature/index.js +++ b/packages/block-editor/src/components/use-editor-feature/index.js @@ -98,11 +98,11 @@ export default function useEditorFeature( featurePath ) { } // 1 - Use __experimental features, if available. - // We cascade to the * value if the block one is not available. - const fallbackPath = `__experimentalFeatures.*.${ featurePath }`; + // We cascade to the all value if the block one is not available. + const defaultsPath = `__experimentalFeatures.defaults.${ featurePath }`; const blockPath = `__experimentalFeatures.${ context }.${ featurePath }`; const experimentalFeaturesResult = - get( settings, blockPath ) ?? get( settings, fallbackPath ); + get( settings, blockPath ) ?? get( settings, defaultsPath ); if ( experimentalFeaturesResult !== undefined ) { return experimentalFeaturesResult; } diff --git a/packages/edit-site/src/components/editor/utils.js b/packages/edit-site/src/components/editor/utils.js index 9b5c541b8629b..1e06302ddca9f 100644 --- a/packages/edit-site/src/components/editor/utils.js +++ b/packages/edit-site/src/components/editor/utils.js @@ -8,7 +8,7 @@ import { get, find, forEach, camelCase, isString } from 'lodash'; import { useSelect } from '@wordpress/data'; /* Supporting data */ -export const ALL_BLOCKS_NAME = '*'; +export const ALL_BLOCKS_NAME = 'defaults'; export const ALL_BLOCKS_SELECTOR = ':root'; export const ROOT_BLOCK_NAME = 'root'; export const ROOT_BLOCK_SELECTOR = ':root'; From cbdb6c526edff82865e5fc5e3dbdff98724426f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Thu, 28 Jan 2021 09:50:03 +0100 Subject: [PATCH 4/4] Update docs --- .../developers/themes/theme-json.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/designers-developers/developers/themes/theme-json.md b/docs/designers-developers/developers/themes/theme-json.md index 785538dd3195f..df8b74c78b1ce 100644 --- a/docs/designers-developers/developers/themes/theme-json.md +++ b/docs/designers-developers/developers/themes/theme-json.md @@ -67,7 +67,7 @@ There are a few cases in whiche a single block can represent different HTML mark } ``` -Additionally, there are two other block selectors: `root` and `*`. The `root` block selector represents the root of the site. The `*` block selector represents "all blocks" and will be discussed below in detail. +Additionally, there are two other block selectors: `root` and `defaults`. The `root` block selector represents the root of the site. The `defaults` block selector represents the defaults to be used by blocks if they don't declare anything. ### Settings @@ -112,14 +112,14 @@ The settings section has the following structure and default values: Each block can configure any of these settings separately, providing a more fine-grained control over what exists via `add_theme_support`. -The block settings declared under the `*` block selector affect to all blocks, unless a particular block overwrites it. It's a way to provide inheritance and quickly configure all blocks at once. To retain backward compatibility, the existing `add_theme_support` declarations that configure the block editor are retrofit in the proper categories for the `*` section. If a theme uses `add_theme_support('disable-custom-colors')`, it'll be the same as set `settings.*.color.custom` to `false`. If the `experimental-theme.json` contains any settings, these will take precedence over the values declared via `add_theme_support`. +The block settings declared under the `defaults` block selector affect to all blocks, unless a particular block overwrites it. It's a way to provide inheritance and quickly configure all blocks at once. To retain backward compatibility, the existing `add_theme_support` declarations that configure the block editor are retrofit in the proper categories for the `defaults` section. If a theme uses `add_theme_support('disable-custom-colors')`, it'll be the same as set `settings.defaults.color.custom` to `false`. If the `experimental-theme.json` contains any settings, these will take precedence over the values declared via `add_theme_support`. Let's say a theme author wants to enable custom colors only for the paragraph block. This is how it can be done: ``` { "settings": { - "*": { + "defaults": { "color": { "custom": false // Disable it for all blocks. } @@ -144,7 +144,7 @@ For example, for this input: ```json { "settings": { - "*": { + "defaults": { "color": { "palette": [ { @@ -208,7 +208,7 @@ For example, for this input: ```json { "settings": { - "*": { + "defaults": { "custom": { "base-font": 16, "line-height": { @@ -320,7 +320,7 @@ h4 { } ``` -The `*` block selector can't be part of the `styles` section and will be ignored if it's present. The `root` block selector will generate a style rule with the `:root` CSS selector. +The `defaults` block selector can't be part of the `styles` section and will be ignored if it's present. The `root` block selector will generate a style rule with the `:root` CSS selector. #### Border Properties