Skip to content

Commit 6e1fde5

Browse files
committed
Block Editor: Integrate theme config with useEditorFeature
1 parent cf3c160 commit 6e1fde5

11 files changed

Lines changed: 154 additions & 24 deletions

File tree

lib/compat.php

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -44,20 +44,6 @@ function register_block_type_from_metadata( $path, $args = array() ) {
4444
}
4545
}
4646

47-
/**
48-
* Extends block editor settings to determine whether to use drop cap feature.
49-
*
50-
* @param array $settings Default editor settings.
51-
*
52-
* @return array Filtered editor settings.
53-
*/
54-
function gutenberg_extend_settings_drop_cap( $settings ) {
55-
$settings['__experimentalDisableDropCap'] = false;
56-
return $settings;
57-
}
58-
add_filter( 'block_editor_settings', 'gutenberg_extend_settings_drop_cap' );
59-
60-
6147
/**
6248
* Extends block editor settings to include a list of image dimensions per size.
6349
*

lib/editor-features.php

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
/**
3+
* Experimental editor features config functionality.
4+
*
5+
* @package gutenberg
6+
*/
7+
8+
/**
9+
* Returns the default config for editor features,
10+
* or an empty array if none found.
11+
*
12+
* @return array Default features config for the editor.
13+
*/
14+
function gutenberg_experimental_get_editor_features_config() {
15+
$empty_config = array();
16+
$config_path = __DIR__ . '/experimental-default-theme.json';
17+
if ( ! file_exists( $config_path ) ) {
18+
return $empty_config;
19+
}
20+
21+
$theme_config = json_decode(
22+
@file_get_contents( $config_path ),
23+
true
24+
);
25+
if (
26+
empty( $theme_config['global']['features'] ) ||
27+
! is_array( $theme_config['global']['features'] )
28+
) {
29+
return $empty_config;
30+
}
31+
32+
return $theme_config['global']['features'];
33+
}
34+
35+
36+
/**
37+
* Extends editor settings with the features loaded from default config.
38+
*
39+
* @param array $settings Default editor settings.
40+
*
41+
* @return array Filtered editor settings.
42+
*/
43+
function gutenberg_extend_settings_editor_features( $settings ) {
44+
$editor_features = gutenberg_experimental_get_editor_features_config();
45+
$settings['__experimentalFeatures'] = $editor_features;
46+
47+
return $settings;
48+
}
49+
add_filter( 'block_editor_settings', 'gutenberg_extend_settings_editor_features' );
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,11 @@
123123
"value": "linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)"
124124
}
125125
]
126+
},
127+
"features": {
128+
"typography": {
129+
"dropCap": false
130+
}
126131
}
127132
}
128133
}

lib/global-styles.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ function gutenberg_experimental_global_styles_get_user_cpt_id() {
171171
*/
172172
function gutenberg_experimental_global_styles_get_core() {
173173
$config = gutenberg_experimental_global_styles_get_from_file(
174-
dirname( dirname( __FILE__ ) ) . '/experimental-default-global-styles.json'
174+
__DIR__ . '/experimental-default-theme.json'
175175
);
176176

177177
return $config;

lib/load.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,5 @@ function gutenberg_is_experiment_enabled( $name ) {
9090
require dirname( __FILE__ ) . '/experiments-page.php';
9191
require dirname( __FILE__ ) . '/customizer.php';
9292
require dirname( __FILE__ ) . '/edit-site-page.php';
93+
require dirname( __FILE__ ) . '/editor-features.php';
9394
require dirname( __FILE__ ) . '/global-styles.php';

packages/block-editor/src/components/use-editor-feature/index.js

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,51 @@
1+
/**
2+
* External dependencies
3+
*/
4+
import { get } from 'lodash';
5+
16
/**
27
* WordPress dependencies
38
*/
49
import { useSelect } from '@wordpress/data';
510

11+
/**
12+
* Internal dependencies
13+
*/
14+
import { useBlockEditContext } from '../block-edit';
15+
616
/**
717
* Hook that retrieves the setting for the given editor feature.
18+
* It works with nested objects using by finding the value at path.
819
*
9-
* @param {string} featureName The name of the feature.
20+
* @param {string} featurePath The path to the feature.
21+
* @param {*} defaultValue Default value to return if not
22+
* explicitly defined.
1023
*
1124
* @return {any} Returns the value defined for the setting.
25+
*
26+
* @example
27+
* ```js
28+
* const isEnabled = useEditorFeature( 'typography.dropCap', false );
29+
* ```
1230
*/
13-
export default function useEditorFeature( featureName ) {
31+
export default function useEditorFeature( featurePath, defaultValue ) {
32+
const { name: blockName } = useBlockEditContext();
33+
const path = `__experimentalFeatures.${ featurePath }`;
34+
1435
const setting = useSelect(
1536
( select ) => {
37+
const { getBlockSupport } = select( 'core/blocks' );
38+
39+
const blockSupportValue = getBlockSupport( blockName, path );
40+
if ( blockSupportValue !== undefined ) {
41+
return blockSupportValue;
42+
}
43+
1644
const { getSettings } = select( 'core/block-editor' );
1745

18-
return getSettings()[ featureName ];
46+
return get( getSettings(), path, defaultValue );
1947
},
20-
[ featureName ]
48+
[ blockName, path ]
2149
);
2250

2351
return setting;

packages/block-library/src/paragraph/block.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@
3232
"lightBlockWrapper": true,
3333
"__experimentalColor": true,
3434
"__experimentalLineHeight": true,
35-
"__experimentalFontSize": true
35+
"__experimentalFontSize": true,
36+
"__experimentalFeatures": {
37+
"typography": {
38+
"dropCap": true
39+
}
40+
}
3641
}
3742
}

packages/block-library/src/paragraph/edit.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ function ParagraphRTLToolbar( { direction, setDirection } ) {
5757
}
5858

5959
function useDropCap( isDropCap, fontSize, styleFontSize ) {
60-
const isDisabled = useEditorFeature( '__experimentalDisableDropCap' );
60+
const isDisabled = ! useEditorFeature( 'typography.dropCap', false );
6161

6262
const [ minimumHeight, setMinimumHeight ] = useState();
6363

packages/blocks/src/store/selectors.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,11 @@ export const getBlockSupport = (
217217
) => {
218218
const blockType = getNormalizedBlockType( state, nameOrType );
219219

220-
return get( blockType, [ 'supports', feature ], defaultSupports );
220+
return get(
221+
blockType,
222+
[ 'supports', ...feature.split( '.' ) ],
223+
defaultSupports
224+
);
221225
};
222226

223227
/**

packages/blocks/src/store/test/selectors.js

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,73 @@
11
/**
22
* External dependencies
33
*/
4-
import { omit } from 'lodash';
4+
import { keyBy, omit } from 'lodash';
55

66
import deepFreeze from 'deep-freeze';
77

88
/**
99
* Internal dependencies
1010
*/
1111
import {
12+
getBlockSupport,
1213
getChildBlockNames,
1314
getDefaultBlockVariation,
1415
getGroupingBlockName,
1516
isMatchingSearchTerm,
1617
} from '../selectors';
1718

1819
describe( 'selectors', () => {
20+
describe( 'getBlockSupport', () => {
21+
const blockName = 'block/name';
22+
const getState = ( blocks ) => {
23+
return deepFreeze( {
24+
blockTypes: keyBy( blocks, 'name' ),
25+
} );
26+
};
27+
28+
it( 'returns default value when config entry not found', () => {
29+
const state = getState( [] );
30+
31+
expect(
32+
getBlockSupport( state, blockName, 'unknown', 'default' )
33+
).toBe( 'default' );
34+
} );
35+
36+
it( 'returns value when config found but falsy', () => {
37+
const state = getState( [
38+
{
39+
name: blockName,
40+
supports: {
41+
falsy: '',
42+
},
43+
},
44+
] );
45+
46+
expect(
47+
getBlockSupport( state, blockName, 'falsy', 'default' )
48+
).toBe( '' );
49+
} );
50+
51+
it( 'works with configs stored as nested objects', () => {
52+
const state = getState( [
53+
{
54+
name: blockName,
55+
supports: {
56+
features: {
57+
foo: {
58+
bar: 'value',
59+
},
60+
},
61+
},
62+
},
63+
] );
64+
65+
expect(
66+
getBlockSupport( state, blockName, 'features.foo.bar' )
67+
).toBe( 'value' );
68+
} );
69+
} );
70+
1971
describe( 'getChildBlockNames', () => {
2072
it( 'should return an empty array if state is empty', () => {
2173
const state = {};

0 commit comments

Comments
 (0)