From d716b5f6fe34c7f96fdcb62f6cc5b069ca579f5b Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 4 Jul 2024 10:00:01 +0200 Subject: [PATCH 01/15] Move bindings registration to editor provider --- packages/editor/src/bindings/index.js | 15 --------------- .../provider}/bindings/pattern-overrides.js | 0 .../provider}/bindings/post-meta.js | 2 +- packages/editor/src/components/provider/index.js | 14 +++++++++++++- 4 files changed, 14 insertions(+), 17 deletions(-) delete mode 100644 packages/editor/src/bindings/index.js rename packages/editor/src/{ => components/provider}/bindings/pattern-overrides.js (100%) rename packages/editor/src/{ => components/provider}/bindings/post-meta.js (96%) diff --git a/packages/editor/src/bindings/index.js b/packages/editor/src/bindings/index.js deleted file mode 100644 index 182edc621453ed..00000000000000 --- a/packages/editor/src/bindings/index.js +++ /dev/null @@ -1,15 +0,0 @@ -/** - * WordPress dependencies - */ -import { store as blocksStore } from '@wordpress/blocks'; -import { dispatch } from '@wordpress/data'; -/** - * Internal dependencies - */ -import { unlock } from '../lock-unlock'; -import patternOverrides from './pattern-overrides'; -import postMeta from './post-meta'; - -const { registerBlockBindingsSource } = unlock( dispatch( blocksStore ) ); -registerBlockBindingsSource( postMeta ); -registerBlockBindingsSource( patternOverrides ); diff --git a/packages/editor/src/bindings/pattern-overrides.js b/packages/editor/src/components/provider/bindings/pattern-overrides.js similarity index 100% rename from packages/editor/src/bindings/pattern-overrides.js rename to packages/editor/src/components/provider/bindings/pattern-overrides.js diff --git a/packages/editor/src/bindings/post-meta.js b/packages/editor/src/components/provider/bindings/post-meta.js similarity index 96% rename from packages/editor/src/bindings/post-meta.js rename to packages/editor/src/components/provider/bindings/post-meta.js index aec890c5ceff87..584244f7b46d66 100644 --- a/packages/editor/src/bindings/post-meta.js +++ b/packages/editor/src/components/provider/bindings/post-meta.js @@ -7,7 +7,7 @@ import { _x } from '@wordpress/i18n'; /** * Internal dependencies */ -import { store as editorStore } from '../store'; +import { store as editorStore } from '../../../store'; export default { name: 'core/post-meta', diff --git a/packages/editor/src/components/provider/index.js b/packages/editor/src/components/provider/index.js index aaf25621d3324b..88bdc85b55cc47 100644 --- a/packages/editor/src/components/provider/index.js +++ b/packages/editor/src/components/provider/index.js @@ -12,7 +12,7 @@ import { } from '@wordpress/block-editor'; import { store as noticesStore } from '@wordpress/notices'; import { privateApis as editPatternsPrivateApis } from '@wordpress/patterns'; -import { createBlock } from '@wordpress/blocks'; +import { createBlock, store as blocksStore } from '@wordpress/blocks'; /** * Internal dependencies @@ -34,6 +34,8 @@ import EditorKeyboardShortcuts from '../global-keyboard-shortcuts'; import PatternRenameModal from '../pattern-rename-modal'; import PatternDuplicateModal from '../pattern-duplicate-modal'; import TemplatePartMenuItems from '../template-part-menu-items'; +import patternOverrides from './bindings/pattern-overrides'; +import postMeta from './bindings/post-meta'; const { ExperimentalBlockEditorProvider } = unlock( blockEditorPrivateApis ); const { PatternsMenuItems } = unlock( editPatternsPrivateApis ); @@ -223,6 +225,9 @@ export const ExperimentalEditorProvider = withRegistryProvider( setRenderingMode, } = unlock( useDispatch( editorStore ) ); const { createWarningNotice } = useDispatch( noticesStore ); + const { registerBlockBindingsSource } = unlock( + useDispatch( blocksStore ) + ); // Ideally this should be synced on each change and not just something you do once. useLayoutEffect( () => { @@ -271,6 +276,13 @@ export const ExperimentalEditorProvider = withRegistryProvider( setRenderingMode( settings.defaultRenderingMode ?? 'post-only' ); }, [ settings.defaultRenderingMode, setRenderingMode ] ); + // Register block bindings sources. + useEffect( () => { + // Initialize core sources. + registerBlockBindingsSource( postMeta ); + registerBlockBindingsSource( patternOverrides ); + }, [ postMeta, patternOverrides, registerBlockBindingsSource ] ); + useHideBlocksFromInserter( post.type, mode ); // Register the editor commands. From 6f2ab12ec032119daff9903ebe842c7c2205687f Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 4 Jul 2024 10:24:05 +0200 Subject: [PATCH 02/15] Remove old bindings import --- packages/editor/src/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/editor/src/index.js b/packages/editor/src/index.js index 1f7bb7699c7040..8d31a0b4ed4c4c 100644 --- a/packages/editor/src/index.js +++ b/packages/editor/src/index.js @@ -1,7 +1,6 @@ /** * Internal dependencies */ -import './bindings'; import './hooks'; export { storeConfig, store } from './store'; From 6cabef4add4171c8263a10cbf8d4e041c6e2ebc3 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 4 Jul 2024 13:23:06 +0200 Subject: [PATCH 03/15] Remove sources from editor provider --- .../provider/bindings/pattern-overrides.js | 92 ------------------- .../components/provider/bindings/post-meta.js | 68 -------------- .../editor/src/components/provider/index.js | 14 +-- 3 files changed, 1 insertion(+), 173 deletions(-) delete mode 100644 packages/editor/src/components/provider/bindings/pattern-overrides.js delete mode 100644 packages/editor/src/components/provider/bindings/post-meta.js diff --git a/packages/editor/src/components/provider/bindings/pattern-overrides.js b/packages/editor/src/components/provider/bindings/pattern-overrides.js deleted file mode 100644 index 54ca77650a5fe9..00000000000000 --- a/packages/editor/src/components/provider/bindings/pattern-overrides.js +++ /dev/null @@ -1,92 +0,0 @@ -/** - * WordPress dependencies - */ -import { _x } from '@wordpress/i18n'; -import { store as blockEditorStore } from '@wordpress/block-editor'; - -const CONTENT = 'content'; - -export default { - name: 'core/pattern-overrides', - label: _x( 'Pattern Overrides', 'block bindings source' ), - getValue( { registry, clientId, context, attributeName } ) { - const patternOverridesContent = context[ 'pattern/overrides' ]; - const { getBlockAttributes } = registry.select( blockEditorStore ); - const currentBlockAttributes = getBlockAttributes( clientId ); - - if ( ! patternOverridesContent ) { - return currentBlockAttributes[ attributeName ]; - } - - const overridableValue = - patternOverridesContent?.[ - currentBlockAttributes?.metadata?.name - ]?.[ attributeName ]; - - // If there is no pattern client ID, or it is not overwritten, return the default value. - if ( overridableValue === undefined ) { - return currentBlockAttributes[ attributeName ]; - } - - return overridableValue === '' ? undefined : overridableValue; - }, - setValues( { registry, clientId, attributes } ) { - const { getBlockAttributes, getBlockParentsByBlockName, getBlocks } = - registry.select( blockEditorStore ); - const currentBlockAttributes = getBlockAttributes( clientId ); - const blockName = currentBlockAttributes?.metadata?.name; - if ( ! blockName ) { - return; - } - - const [ patternClientId ] = getBlockParentsByBlockName( - clientId, - 'core/block', - true - ); - - // If there is no pattern client ID, sync blocks with the same name and same attributes. - if ( ! patternClientId ) { - const syncBlocksWithSameName = ( blocks ) => { - for ( const block of blocks ) { - if ( block.attributes?.metadata?.name === blockName ) { - registry - .dispatch( blockEditorStore ) - .updateBlockAttributes( - block.clientId, - attributes - ); - } - syncBlocksWithSameName( block.innerBlocks ); - } - }; - - syncBlocksWithSameName( getBlocks() ); - return; - } - const currentBindingValue = - getBlockAttributes( patternClientId )?.[ CONTENT ]; - registry - .dispatch( blockEditorStore ) - .updateBlockAttributes( patternClientId, { - [ CONTENT ]: { - ...currentBindingValue, - [ blockName ]: { - ...currentBindingValue?.[ blockName ], - ...Object.entries( attributes ).reduce( - ( acc, [ key, value ] ) => { - // TODO: We need a way to represent `undefined` in the serialized overrides. - // Also see: https://github.com/WordPress/gutenberg/pull/57249#discussion_r1452987871 - // We use an empty string to represent undefined for now until - // we support a richer format for overrides and the block bindings API. - acc[ key ] = value === undefined ? '' : value; - return acc; - }, - {} - ), - }, - }, - } ); - }, - canUserEditValue: () => true, -}; diff --git a/packages/editor/src/components/provider/bindings/post-meta.js b/packages/editor/src/components/provider/bindings/post-meta.js deleted file mode 100644 index 584244f7b46d66..00000000000000 --- a/packages/editor/src/components/provider/bindings/post-meta.js +++ /dev/null @@ -1,68 +0,0 @@ -/** - * WordPress dependencies - */ -import { store as coreDataStore } from '@wordpress/core-data'; -import { _x } from '@wordpress/i18n'; - -/** - * Internal dependencies - */ -import { store as editorStore } from '../../../store'; - -export default { - name: 'core/post-meta', - label: _x( 'Post Meta', 'block bindings source' ), - getPlaceholder( { args } ) { - return args.key; - }, - getValue( { registry, context, args } ) { - return registry - .select( coreDataStore ) - .getEditedEntityRecord( - 'postType', - context?.postType, - context?.postId - ).meta?.[ args.key ]; - }, - setValue( { registry, context, args, value } ) { - registry - .dispatch( coreDataStore ) - .editEntityRecord( 'postType', context?.postType, context?.postId, { - meta: { - [ args.key ]: value, - }, - } ); - }, - canUserEditValue( { select, context, args } ) { - const postType = - context?.postType || select( editorStore ).getCurrentPostType(); - - // Check that editing is happening in the post editor and not a template. - if ( postType === 'wp_template' ) { - return false; - } - - // Check that the custom field is not protected and available in the REST API. - const isFieldExposed = !! select( coreDataStore ).getEntityRecord( - 'postType', - postType, - context?.postId - )?.meta?.[ args.key ]; - - if ( ! isFieldExposed ) { - return false; - } - - // Check that the user has the capability to edit post meta. - const canUserEdit = select( coreDataStore ).canUserEditEntityRecord( - 'postType', - context?.postType, - context?.postId - ); - if ( ! canUserEdit ) { - return false; - } - - return true; - }, -}; diff --git a/packages/editor/src/components/provider/index.js b/packages/editor/src/components/provider/index.js index 88bdc85b55cc47..aaf25621d3324b 100644 --- a/packages/editor/src/components/provider/index.js +++ b/packages/editor/src/components/provider/index.js @@ -12,7 +12,7 @@ import { } from '@wordpress/block-editor'; import { store as noticesStore } from '@wordpress/notices'; import { privateApis as editPatternsPrivateApis } from '@wordpress/patterns'; -import { createBlock, store as blocksStore } from '@wordpress/blocks'; +import { createBlock } from '@wordpress/blocks'; /** * Internal dependencies @@ -34,8 +34,6 @@ import EditorKeyboardShortcuts from '../global-keyboard-shortcuts'; import PatternRenameModal from '../pattern-rename-modal'; import PatternDuplicateModal from '../pattern-duplicate-modal'; import TemplatePartMenuItems from '../template-part-menu-items'; -import patternOverrides from './bindings/pattern-overrides'; -import postMeta from './bindings/post-meta'; const { ExperimentalBlockEditorProvider } = unlock( blockEditorPrivateApis ); const { PatternsMenuItems } = unlock( editPatternsPrivateApis ); @@ -225,9 +223,6 @@ export const ExperimentalEditorProvider = withRegistryProvider( setRenderingMode, } = unlock( useDispatch( editorStore ) ); const { createWarningNotice } = useDispatch( noticesStore ); - const { registerBlockBindingsSource } = unlock( - useDispatch( blocksStore ) - ); // Ideally this should be synced on each change and not just something you do once. useLayoutEffect( () => { @@ -276,13 +271,6 @@ export const ExperimentalEditorProvider = withRegistryProvider( setRenderingMode( settings.defaultRenderingMode ?? 'post-only' ); }, [ settings.defaultRenderingMode, setRenderingMode ] ); - // Register block bindings sources. - useEffect( () => { - // Initialize core sources. - registerBlockBindingsSource( postMeta ); - registerBlockBindingsSource( patternOverrides ); - }, [ postMeta, patternOverrides, registerBlockBindingsSource ] ); - useHideBlocksFromInserter( post.type, mode ); // Register the editor commands. From 4701034310c801ff517008c6d431d6dc651f01bb Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 4 Jul 2024 13:23:58 +0200 Subject: [PATCH 04/15] Create registerBlockBindingsSource --- packages/blocks/src/api/registration.js | 99 ++++++++++++++++++++ packages/blocks/src/store/private-actions.js | 6 +- packages/blocks/src/store/reducer.js | 2 +- 3 files changed, 103 insertions(+), 4 deletions(-) diff --git a/packages/blocks/src/api/registration.js b/packages/blocks/src/api/registration.js index fb21b7083b0c54..98c21eeb0522d6 100644 --- a/packages/blocks/src/api/registration.js +++ b/packages/blocks/src/api/registration.js @@ -758,3 +758,102 @@ export const registerBlockVariation = ( blockName, variation ) => { export const unregisterBlockVariation = ( blockName, variationName ) => { dispatch( blocksStore ).removeBlockVariations( blockName, variationName ); }; + +export const registerBlockBindingsSource = ( source ) => { + const { + name, + label: newLabel, + getValue, + setValue, + setValues, + getPlaceholder, + canUserEditValue, + } = source; + + // Sources could exist because they have been initialized in the server. + const existingSource = unlock( + select( blocksStore ) + ).getBlockBindingsSource( name ); + + // Override the label if provided. + const label = newLabel || existingSource?.label; + + // If the getValue callback is already provided, it shouldn't be overriden. + // It can't rely on name or label because those could be initialized in the server. + if ( existingSource?.getValue ) { + console.error( + 'Block bindings source"' + name + '" is already registered.' + ); + return; + } + + // Check the `name` property is correct. + if ( typeof name !== 'string' ) { + console.error( 'Block bindings source name must be a string.' ); + return; + } + + if ( /[A-Z]+/.test( name ) ) { + console.error( + 'Block bindings source name must not contain uppercase characters.' + ); + return; + } + + if ( ! /^[a-z0-9-]+\/[a-z0-9-]+$/.test( name ) ) { + console.error( + 'Block bindings source name must contain a namespace prefix. Example: my-plugin/my-custom-source' + ); + return; + } + + // Check the `label` property is correct. + if ( typeof label !== 'string' ) { + console.error( 'Block bindings source label must be a string.' ); + return; + } + + // Check the `getValue` property is correct. + if ( getValue && typeof getValue !== 'function' ) { + console.error( 'Block bindings source getValue must be a function.' ); + return; + } + + // Check the `setValue` property is correct. + if ( setValue && typeof setValue !== 'function' ) { + console.error( 'Block bindings source setValue must be a function.' ); + return; + } + + // Check the `setValues` property is correct. + if ( setValues && typeof setValues !== 'function' ) { + console.error( 'Block bindings source setValues must be a function.' ); + return; + } + + // Check the `getPlaceholder` property is correct. + if ( getPlaceholder && typeof getPlaceholder !== 'function' ) { + console.error( + 'Block bindings source getPlaceholder must be a function.' + ); + return; + } + + // Check the `getPlaceholder` property is correct. + if ( canUserEditValue && typeof canUserEditValue !== 'function' ) { + console.error( + 'Block bindings source canUserEditValue must be a function.' + ); + return; + } + + unlock( dispatch( blocksStore ) ).addBlockBindingsSource( { + name, + label, + getValue, + setValue, + setValues, + getPlaceholder, + canUserEditValue, + } ); +}; diff --git a/packages/blocks/src/store/private-actions.js b/packages/blocks/src/store/private-actions.js index dd6650338d9d1a..ace86c913a17b2 100644 --- a/packages/blocks/src/store/private-actions.js +++ b/packages/blocks/src/store/private-actions.js @@ -42,13 +42,13 @@ export function addUnprocessedBlockType( name, blockType ) { } /** - * Register new block bindings source. + * Adds new block bindings source. * * @param {string} source Name of the source to register. */ -export function registerBlockBindingsSource( source ) { +export function addBlockBindingsSource( source ) { return { - type: 'REGISTER_BLOCK_BINDINGS_SOURCE', + type: 'ADD_BLOCK_BINDINGS_SOURCE', sourceName: source.name, sourceLabel: source.label, getValue: source.getValue, diff --git a/packages/blocks/src/store/reducer.js b/packages/blocks/src/store/reducer.js index c00810c534d55d..88004f2482b503 100644 --- a/packages/blocks/src/store/reducer.js +++ b/packages/blocks/src/store/reducer.js @@ -372,7 +372,7 @@ export function collections( state = {}, action ) { } export function blockBindingsSources( state = {}, action ) { - if ( action.type === 'REGISTER_BLOCK_BINDINGS_SOURCE' ) { + if ( action.type === 'ADD_BLOCK_BINDINGS_SOURCE' ) { return { ...state, [ action.sourceName ]: { From db6f4d4df2b3bd2a00cffb947b0078d54483e939 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 4 Jul 2024 13:26:45 +0200 Subject: [PATCH 05/15] Export function as private --- packages/blocks/README.md | 4 ++++ packages/blocks/src/api/index.js | 11 +++++++++++ 2 files changed, 15 insertions(+) diff --git a/packages/blocks/README.md b/packages/blocks/README.md index 40861862585739..d724f986b0ca81 100644 --- a/packages/blocks/README.md +++ b/packages/blocks/README.md @@ -462,6 +462,10 @@ _Returns_ - `Array|string`: A list of blocks or a string, depending on `handlerMode`. +### privateApis + +Undocumented declaration. + ### rawHandler Converts an HTML string to known blocks. diff --git a/packages/blocks/src/api/index.js b/packages/blocks/src/api/index.js index aa72979818c9c7..b4b6b181e7e7ee 100644 --- a/packages/blocks/src/api/index.js +++ b/packages/blocks/src/api/index.js @@ -1,3 +1,9 @@ +/** + * Internal dependencies + */ +import { lock } from '../lock-unlock'; +import { registerBlockBindingsSource } from './registration'; + // The blocktype is the most important concept within the block API. It defines // all aspects of the block configuration and its interfaces, including `edit` // and `save`. The transforms specification allows converting one blocktype to @@ -164,3 +170,8 @@ export { __EXPERIMENTAL_ELEMENTS, __EXPERIMENTAL_PATHS_WITH_OVERRIDE, } from './constants'; + +export const privateApis = {}; +lock( privateApis, { + registerBlockBindingsSource, +} ); From d7767393ec794a6898cff382edfa5743c1aa0a7b Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 4 Jul 2024 13:30:36 +0200 Subject: [PATCH 06/15] Create `registerCoreBlockBindingsSources` function --- packages/editor/src/bindings/api.js | 27 ++++++ .../editor/src/bindings/pattern-overrides.js | 92 +++++++++++++++++++ packages/editor/src/bindings/post-meta.js | 68 ++++++++++++++ packages/editor/src/private-apis.js | 2 + 4 files changed, 189 insertions(+) create mode 100644 packages/editor/src/bindings/api.js create mode 100644 packages/editor/src/bindings/pattern-overrides.js create mode 100644 packages/editor/src/bindings/post-meta.js diff --git a/packages/editor/src/bindings/api.js b/packages/editor/src/bindings/api.js new file mode 100644 index 00000000000000..0037f3334215b8 --- /dev/null +++ b/packages/editor/src/bindings/api.js @@ -0,0 +1,27 @@ +/** + * WordPress dependencies + */ +import { privateApis as blocksPrivateApis } from '@wordpress/blocks'; + +/** + * Internal dependencies + */ +import patternOverrides from './pattern-overrides'; +import postMeta from './post-meta'; +import { unlock } from '../lock-unlock'; + +/** + * Function to register core block bindings sources provided by the editor. + * + * @example + * ```js + * import { registerCoreBlockBindingsSources } from '@wordpress/editor'; + * + * registerCoreBlockBindingsSources(); + * ``` + */ +export function registerCoreBlockBindingsSources() { + const { registerBlockBindingsSource } = unlock( blocksPrivateApis ); + registerBlockBindingsSource( patternOverrides ); + registerBlockBindingsSource( postMeta ); +} diff --git a/packages/editor/src/bindings/pattern-overrides.js b/packages/editor/src/bindings/pattern-overrides.js new file mode 100644 index 00000000000000..54ca77650a5fe9 --- /dev/null +++ b/packages/editor/src/bindings/pattern-overrides.js @@ -0,0 +1,92 @@ +/** + * WordPress dependencies + */ +import { _x } from '@wordpress/i18n'; +import { store as blockEditorStore } from '@wordpress/block-editor'; + +const CONTENT = 'content'; + +export default { + name: 'core/pattern-overrides', + label: _x( 'Pattern Overrides', 'block bindings source' ), + getValue( { registry, clientId, context, attributeName } ) { + const patternOverridesContent = context[ 'pattern/overrides' ]; + const { getBlockAttributes } = registry.select( blockEditorStore ); + const currentBlockAttributes = getBlockAttributes( clientId ); + + if ( ! patternOverridesContent ) { + return currentBlockAttributes[ attributeName ]; + } + + const overridableValue = + patternOverridesContent?.[ + currentBlockAttributes?.metadata?.name + ]?.[ attributeName ]; + + // If there is no pattern client ID, or it is not overwritten, return the default value. + if ( overridableValue === undefined ) { + return currentBlockAttributes[ attributeName ]; + } + + return overridableValue === '' ? undefined : overridableValue; + }, + setValues( { registry, clientId, attributes } ) { + const { getBlockAttributes, getBlockParentsByBlockName, getBlocks } = + registry.select( blockEditorStore ); + const currentBlockAttributes = getBlockAttributes( clientId ); + const blockName = currentBlockAttributes?.metadata?.name; + if ( ! blockName ) { + return; + } + + const [ patternClientId ] = getBlockParentsByBlockName( + clientId, + 'core/block', + true + ); + + // If there is no pattern client ID, sync blocks with the same name and same attributes. + if ( ! patternClientId ) { + const syncBlocksWithSameName = ( blocks ) => { + for ( const block of blocks ) { + if ( block.attributes?.metadata?.name === blockName ) { + registry + .dispatch( blockEditorStore ) + .updateBlockAttributes( + block.clientId, + attributes + ); + } + syncBlocksWithSameName( block.innerBlocks ); + } + }; + + syncBlocksWithSameName( getBlocks() ); + return; + } + const currentBindingValue = + getBlockAttributes( patternClientId )?.[ CONTENT ]; + registry + .dispatch( blockEditorStore ) + .updateBlockAttributes( patternClientId, { + [ CONTENT ]: { + ...currentBindingValue, + [ blockName ]: { + ...currentBindingValue?.[ blockName ], + ...Object.entries( attributes ).reduce( + ( acc, [ key, value ] ) => { + // TODO: We need a way to represent `undefined` in the serialized overrides. + // Also see: https://github.com/WordPress/gutenberg/pull/57249#discussion_r1452987871 + // We use an empty string to represent undefined for now until + // we support a richer format for overrides and the block bindings API. + acc[ key ] = value === undefined ? '' : value; + return acc; + }, + {} + ), + }, + }, + } ); + }, + canUserEditValue: () => true, +}; diff --git a/packages/editor/src/bindings/post-meta.js b/packages/editor/src/bindings/post-meta.js new file mode 100644 index 00000000000000..aec890c5ceff87 --- /dev/null +++ b/packages/editor/src/bindings/post-meta.js @@ -0,0 +1,68 @@ +/** + * WordPress dependencies + */ +import { store as coreDataStore } from '@wordpress/core-data'; +import { _x } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import { store as editorStore } from '../store'; + +export default { + name: 'core/post-meta', + label: _x( 'Post Meta', 'block bindings source' ), + getPlaceholder( { args } ) { + return args.key; + }, + getValue( { registry, context, args } ) { + return registry + .select( coreDataStore ) + .getEditedEntityRecord( + 'postType', + context?.postType, + context?.postId + ).meta?.[ args.key ]; + }, + setValue( { registry, context, args, value } ) { + registry + .dispatch( coreDataStore ) + .editEntityRecord( 'postType', context?.postType, context?.postId, { + meta: { + [ args.key ]: value, + }, + } ); + }, + canUserEditValue( { select, context, args } ) { + const postType = + context?.postType || select( editorStore ).getCurrentPostType(); + + // Check that editing is happening in the post editor and not a template. + if ( postType === 'wp_template' ) { + return false; + } + + // Check that the custom field is not protected and available in the REST API. + const isFieldExposed = !! select( coreDataStore ).getEntityRecord( + 'postType', + postType, + context?.postId + )?.meta?.[ args.key ]; + + if ( ! isFieldExposed ) { + return false; + } + + // Check that the user has the capability to edit post meta. + const canUserEdit = select( coreDataStore ).canUserEditEntityRecord( + 'postType', + context?.postType, + context?.postId + ); + if ( ! canUserEdit ) { + return false; + } + + return true; + }, +}; diff --git a/packages/editor/src/private-apis.js b/packages/editor/src/private-apis.js index 8eeb97375268c3..58688a9099e879 100644 --- a/packages/editor/src/private-apis.js +++ b/packages/editor/src/private-apis.js @@ -24,6 +24,7 @@ import { GlobalStylesProvider, } from './components/global-styles-provider'; import registerDefaultActions from './dataviews/actions'; +import { registerCoreBlockBindingsSources } from './bindings/api'; const { store: interfaceStore, ...remainingInterfaceApis } = interfaceApis; @@ -43,6 +44,7 @@ lock( privateApis, { ViewMoreMenuGroup, ResizableEditor, registerDefaultActions, + registerCoreBlockBindingsSources, // This is a temporary private API while we're updating the site editor to use EditorProvider. useBlockEditorSettings, From d6978d8ca4c61431c67761844ff3b7bd2e2bced7 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 4 Jul 2024 13:31:05 +0200 Subject: [PATCH 07/15] Register core sources in edit-post and edit-site --- packages/edit-post/src/index.js | 2 ++ packages/edit-site/src/index.js | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/edit-post/src/index.js b/packages/edit-post/src/index.js index 0b4cf883d07809..2cbf1958719c68 100644 --- a/packages/edit-post/src/index.js +++ b/packages/edit-post/src/index.js @@ -28,6 +28,7 @@ import { unlock } from './lock-unlock'; const { BackButton: __experimentalMainDashboardButton, registerDefaultActions, + registerCoreBlockBindingsSources, } = unlock( editorPrivateApis ); /** @@ -86,6 +87,7 @@ export function initializeEditor( } registerCoreBlocks(); + registerCoreBlockBindingsSources(); registerLegacyWidgetBlock( { inserter: false } ); registerWidgetGroupBlock( { inserter: false } ); if ( globalThis.IS_GUTENBERG_PLUGIN ) { diff --git a/packages/edit-site/src/index.js b/packages/edit-site/src/index.js index 14f5bb6be650c5..02d974e037c045 100644 --- a/packages/edit-site/src/index.js +++ b/packages/edit-site/src/index.js @@ -28,7 +28,8 @@ import { store as editSiteStore } from './store'; import { unlock } from './lock-unlock'; import App from './components/app'; -const { registerDefaultActions } = unlock( editorPrivateApis ); +const { registerDefaultActions, registerCoreBlockBindingsSources } = + unlock( editorPrivateApis ); /** * Initializes the site editor screen. @@ -45,6 +46,7 @@ export function initializeEditor( id, settings ) { ( { name } ) => name !== 'core/freeform' ); registerCoreBlocks( coreBlocks ); + registerCoreBlockBindingsSources(); dispatch( blocksStore ).setFreeformFallbackBlockName( 'core/html' ); registerLegacyWidgetBlock( { inserter: false } ); registerWidgetGroupBlock( { inserter: false } ); From efc1450a79df5b2bc2d87ba86299c4b4339f3090 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 4 Jul 2024 13:34:46 +0200 Subject: [PATCH 08/15] Don't reuse existing source --- packages/blocks/src/api/registration.js | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/packages/blocks/src/api/registration.js b/packages/blocks/src/api/registration.js index 98c21eeb0522d6..e481aabe00838e 100644 --- a/packages/blocks/src/api/registration.js +++ b/packages/blocks/src/api/registration.js @@ -762,7 +762,7 @@ export const unregisterBlockVariation = ( blockName, variationName ) => { export const registerBlockBindingsSource = ( source ) => { const { name, - label: newLabel, + label, getValue, setValue, setValues, @@ -770,17 +770,11 @@ export const registerBlockBindingsSource = ( source ) => { canUserEditValue, } = source; - // Sources could exist because they have been initialized in the server. + // Check if the source is already registered. const existingSource = unlock( select( blocksStore ) ).getBlockBindingsSource( name ); - - // Override the label if provided. - const label = newLabel || existingSource?.label; - - // If the getValue callback is already provided, it shouldn't be overriden. - // It can't rely on name or label because those could be initialized in the server. - if ( existingSource?.getValue ) { + if ( existingSource ) { console.error( 'Block bindings source"' + name + '" is already registered.' ); From 2a314b1fcc1aa544e05df8a588e89a5959ca6c95 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 4 Jul 2024 13:50:38 +0200 Subject: [PATCH 09/15] Add comment explaining function --- packages/blocks/src/api/registration.js | 30 +++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/packages/blocks/src/api/registration.js b/packages/blocks/src/api/registration.js index e481aabe00838e..326aad25c22005 100644 --- a/packages/blocks/src/api/registration.js +++ b/packages/blocks/src/api/registration.js @@ -759,6 +759,36 @@ export const unregisterBlockVariation = ( blockName, variationName ) => { dispatch( blocksStore ).removeBlockVariations( blockName, variationName ); }; +/** + * Registers a new block bindings source with an object defining its + * behavior. Once registered, the source is available to be connected + * to the supported block attributes. + * + * @param {Object} source Properties of the source to be registered. + * @param {string} source.name The unique and machine-readable name. + * @param {string} source.label Human-readable label. + * @param {Function} [source.getValue] Function to get the value of the source. + * @param {Function} [source.setValue] Function to update the value of the source. + * @param {Function} [source.setValues] Function to update multiple values connected to the source. + * @param {Function} [source.getPlaceholder] Function to get the placeholder when the value is undefined. + * @param {Function} [source.canUserEditValue] Function to determine if the user can edit the value. + * + * @example + * ```js + * import { _x } from '@wordpress/i18n'; + * import { registerBlockBindingsSource } from '@wordpress/blocks' + * + * registerBlockBindingsSource( { + * name: 'plugin/my-custom-source', + * label: _x( 'My Custom Source', 'block bindings source' ), + * getValue: () => 'Value to place in the block attribute', + * setValue: () => updateMyCustomValue(), + * setValues: () => updateMyCustomValuesInBatch(), + * getPlaceholder: () => 'Placeholder text when the value is undefined', + * canUserEditValue: () => true, + * } ); + * ``` + */ export const registerBlockBindingsSource = ( source ) => { const { name, From e8e248cefd5d079090cd72a66b14c84968c1e035 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Thu, 11 Jul 2024 17:47:52 +0200 Subject: [PATCH 10/15] Change the object in registration --- packages/blocks/src/api/registration.js | 10 +--------- packages/blocks/src/store/private-actions.js | 4 ++-- packages/blocks/src/store/reducer.js | 4 ++-- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/packages/blocks/src/api/registration.js b/packages/blocks/src/api/registration.js index 326aad25c22005..971a10c7920c40 100644 --- a/packages/blocks/src/api/registration.js +++ b/packages/blocks/src/api/registration.js @@ -871,13 +871,5 @@ export const registerBlockBindingsSource = ( source ) => { return; } - unlock( dispatch( blocksStore ) ).addBlockBindingsSource( { - name, - label, - getValue, - setValue, - setValues, - getPlaceholder, - canUserEditValue, - } ); + unlock( dispatch( blocksStore ) ).addBlockBindingsSource( source ); }; diff --git a/packages/blocks/src/store/private-actions.js b/packages/blocks/src/store/private-actions.js index ace86c913a17b2..0282e7cf84e37f 100644 --- a/packages/blocks/src/store/private-actions.js +++ b/packages/blocks/src/store/private-actions.js @@ -49,8 +49,8 @@ export function addUnprocessedBlockType( name, blockType ) { export function addBlockBindingsSource( source ) { return { type: 'ADD_BLOCK_BINDINGS_SOURCE', - sourceName: source.name, - sourceLabel: source.label, + name: source.name, + label: source.label, getValue: source.getValue, setValue: source.setValue, setValues: source.setValues, diff --git a/packages/blocks/src/store/reducer.js b/packages/blocks/src/store/reducer.js index 88004f2482b503..e316059b0d072b 100644 --- a/packages/blocks/src/store/reducer.js +++ b/packages/blocks/src/store/reducer.js @@ -375,8 +375,8 @@ export function blockBindingsSources( state = {}, action ) { if ( action.type === 'ADD_BLOCK_BINDINGS_SOURCE' ) { return { ...state, - [ action.sourceName ]: { - label: action.sourceLabel, + [ action.name ]: { + label: action.label, getValue: action.getValue, setValue: action.setValue, setValues: action.setValues, From 2c997279d217957631cf65e94b930e10f88d0d89 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Fri, 12 Jul 2024 09:09:32 +0200 Subject: [PATCH 11/15] Add a few checks more --- packages/blocks/src/api/registration.js | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/packages/blocks/src/api/registration.js b/packages/blocks/src/api/registration.js index 971a10c7920c40..f0faa23f3fcf4c 100644 --- a/packages/blocks/src/api/registration.js +++ b/packages/blocks/src/api/registration.js @@ -812,6 +812,11 @@ export const registerBlockBindingsSource = ( source ) => { } // Check the `name` property is correct. + if ( ! name ) { + console.error( 'Block bindings source must contain a name.' ); + return; + } + if ( typeof name !== 'string' ) { console.error( 'Block bindings source name must be a string.' ); return; @@ -824,14 +829,26 @@ export const registerBlockBindingsSource = ( source ) => { return; } + if ( ! /^[a-z0-9/-]+$/.test( name ) ) { + console.error( + 'Block bindings source name must contain only valid characters: lowercase characters, hyphens, or digits. Example: my-plugin/my-custom-source.' + ); + return; + } + if ( ! /^[a-z0-9-]+\/[a-z0-9-]+$/.test( name ) ) { console.error( - 'Block bindings source name must contain a namespace prefix. Example: my-plugin/my-custom-source' + 'Block bindings source name must contain a namespace and valid characters. Example: my-plugin/my-custom-source.' ); return; } // Check the `label` property is correct. + if ( ! label ) { + console.error( 'Block bindings source must contain a label.' ); + return; + } + if ( typeof label !== 'string' ) { console.error( 'Block bindings source label must be a string.' ); return; @@ -871,5 +888,5 @@ export const registerBlockBindingsSource = ( source ) => { return; } - unlock( dispatch( blocksStore ) ).addBlockBindingsSource( source ); + return unlock( dispatch( blocksStore ) ).addBlockBindingsSource( source ); }; From 715911d0168b64617fe74b768d3608b279cedba2 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Fri, 12 Jul 2024 09:10:20 +0200 Subject: [PATCH 12/15] Add more registration functions --- packages/blocks/src/api/registration.js | 43 +++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/packages/blocks/src/api/registration.js b/packages/blocks/src/api/registration.js index f0faa23f3fcf4c..65f117bd824cb9 100644 --- a/packages/blocks/src/api/registration.js +++ b/packages/blocks/src/api/registration.js @@ -890,3 +890,46 @@ export const registerBlockBindingsSource = ( source ) => { return unlock( dispatch( blocksStore ) ).addBlockBindingsSource( source ); }; + +/** + * Unregisters a block bindings source + * + * @param {string} name The name of the block bindings source to unregister. + * + * @example + * ```js + * import { unregisterBlockBindingsSource } from '@wordpress/blocks'; + * + * unregisterBlockBindingsSource( 'plugin/my-custom-source' ); + * ``` + */ +export function unregisterBlockBindingsSource( name ) { + const oldSource = getBlockBindingsSource( name ); + if ( ! oldSource ) { + console.error( + 'Block bindings source "' + name + '" is not registered.' + ); + return; + } + unlock( dispatch( blocksStore ) ).removeBlockBindings( name ); +} + +/** + * Returns a registered block bindings source. + * + * @param {string} name Block bindings source name. + * + * @return {?Object} Block bindings source. + */ +export function getBlockBindingsSource( name ) { + return unlock( select( blocksStore ) ).getBlockBindingsSource( name ); +} + +/** + * Returns all registered block bindings sources. + * + * @return {Array} Block bindings sources. + */ +export function getBlockBindingsSources() { + return unlock( select( blocksStore ) ).getAllBlockBindingsSources(); +} From 2866f515d48146f0ac70abd971f756e646a03823 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Fri, 12 Jul 2024 09:29:04 +0200 Subject: [PATCH 13/15] Add private action to remove binding source --- packages/blocks/src/store/private-actions.js | 12 +++++++++ packages/blocks/src/store/reducer.js | 28 +++++++++++--------- 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/packages/blocks/src/store/private-actions.js b/packages/blocks/src/store/private-actions.js index 0282e7cf84e37f..a59ed157e98693 100644 --- a/packages/blocks/src/store/private-actions.js +++ b/packages/blocks/src/store/private-actions.js @@ -58,3 +58,15 @@ export function addBlockBindingsSource( source ) { canUserEditValue: source.canUserEditValue, }; } + +/** + * Removes existing block bindings source. + * + * @param {string} name Name of the source to remove. + */ +export function removeBlockBindingsSource( name ) { + return { + type: 'REMOVE_BLOCK_BINDINGS_SOURCE', + name, + }; +} diff --git a/packages/blocks/src/store/reducer.js b/packages/blocks/src/store/reducer.js index e316059b0d072b..1b6d348fd9dddc 100644 --- a/packages/blocks/src/store/reducer.js +++ b/packages/blocks/src/store/reducer.js @@ -372,18 +372,22 @@ export function collections( state = {}, action ) { } export function blockBindingsSources( state = {}, action ) { - if ( action.type === 'ADD_BLOCK_BINDINGS_SOURCE' ) { - return { - ...state, - [ action.name ]: { - label: action.label, - getValue: action.getValue, - setValue: action.setValue, - setValues: action.setValues, - getPlaceholder: action.getPlaceholder, - canUserEditValue: action.canUserEditValue || ( () => false ), - }, - }; + switch ( action.type ) { + case 'ADD_BLOCK_BINDINGS_SOURCE': + return { + ...state, + [ action.name ]: { + label: action.label, + getValue: action.getValue, + setValue: action.setValue, + setValues: action.setValues, + getPlaceholder: action.getPlaceholder, + canUserEditValue: + action.canUserEditValue || ( () => false ), + }, + }; + case 'REMOVE_BLOCK_BINDINGS_SOURCE': + return omit( state, action.name ); } return state; } From 422aef7aa83b3566cee45df11201452755703541 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Fri, 12 Jul 2024 09:31:00 +0200 Subject: [PATCH 14/15] Add unit tests --- packages/blocks/src/api/registration.js | 4 +- packages/blocks/src/api/test/registration.js | 210 +++++++++++++++++++ 2 files changed, 212 insertions(+), 2 deletions(-) diff --git a/packages/blocks/src/api/registration.js b/packages/blocks/src/api/registration.js index 65f117bd824cb9..b80178f8357aa6 100644 --- a/packages/blocks/src/api/registration.js +++ b/packages/blocks/src/api/registration.js @@ -806,7 +806,7 @@ export const registerBlockBindingsSource = ( source ) => { ).getBlockBindingsSource( name ); if ( existingSource ) { console.error( - 'Block bindings source"' + name + '" is already registered.' + 'Block bindings source "' + name + '" is already registered.' ); return; } @@ -911,7 +911,7 @@ export function unregisterBlockBindingsSource( name ) { ); return; } - unlock( dispatch( blocksStore ) ).removeBlockBindings( name ); + unlock( dispatch( blocksStore ) ).removeBlockBindingsSource( name ); } /** diff --git a/packages/blocks/src/api/test/registration.js b/packages/blocks/src/api/test/registration.js index 81f45f1999803e..d86d5d54d6ca99 100644 --- a/packages/blocks/src/api/test/registration.js +++ b/packages/blocks/src/api/test/registration.js @@ -14,8 +14,10 @@ import { registerBlockType, registerBlockCollection, registerBlockVariation, + registerBlockBindingsSource, unregisterBlockCollection, unregisterBlockType, + unregisterBlockBindingsSource, setFreeformContentHandlerName, getFreeformContentHandlerName, setUnregisteredTypeHandlerName, @@ -28,6 +30,7 @@ import { getBlockTypes, getBlockSupport, getBlockVariations, + getBlockBindingsSource, hasBlockSupport, isReusableBlock, unstable__bootstrapServerSideBlockDefinitions, // eslint-disable-line camelcase @@ -1432,6 +1435,213 @@ describe( 'blocks', () => { ] ); } ); } ); + + describe( 'registerBlockBindingsSource', () => { + // Check the name is correct. + it( 'should contain name property', () => { + const source = registerBlockBindingsSource( {} ); + expect( console ).toHaveErroredWith( + 'Block bindings source must contain a name.' + ); + expect( source ).toBeUndefined(); + } ); + + it( 'should reject numbers', () => { + const source = registerBlockBindingsSource( { name: 1 } ); + expect( console ).toHaveErroredWith( + 'Block bindings source name must be a string.' + ); + expect( source ).toBeUndefined(); + } ); + + it( 'should reject names with uppercase characters', () => { + registerBlockBindingsSource( { + name: 'Core/WrongName', + } ); + expect( console ).toHaveErroredWith( + 'Block bindings source name must not contain uppercase characters.' + ); + expect( + getBlockBindingsSource( 'Core/WrongName' ) + ).toBeUndefined(); + } ); + + it( 'should reject names with invalid characters', () => { + registerBlockBindingsSource( { + name: 'core/_wrong_name', + } ); + expect( console ).toHaveErroredWith( + 'Block bindings source name must contain only valid characters: lowercase characters, hyphens, or digits. Example: my-plugin/my-custom-source.' + ); + expect( + getBlockBindingsSource( 'core/_wrong_name' ) + ).toBeUndefined(); + } ); + + it( 'should reject invalid names without namespace', () => { + registerBlockBindingsSource( { + name: 'wrong-name', + } ); + expect( console ).toHaveErroredWith( + 'Block bindings source name must contain a namespace and valid characters. Example: my-plugin/my-custom-source.' + ); + expect( getBlockBindingsSource( 'wrong-name' ) ).toBeUndefined(); + } ); + + // Check the label is correct. + it( 'should contain label property', () => { + registerBlockBindingsSource( { + name: 'core/testing', + } ); + expect( console ).toHaveErroredWith( + 'Block bindings source must contain a label.' + ); + expect( getBlockBindingsSource( 'core/testing' ) ).toBeUndefined(); + } ); + + it( 'should reject invalid label', () => { + registerBlockBindingsSource( { + name: 'core/testing', + label: 1, + } ); + expect( console ).toHaveErroredWith( + 'Block bindings source label must be a string.' + ); + expect( getBlockBindingsSource( 'core/testing' ) ).toBeUndefined(); + } ); + + // Check the `getValue` callback is correct. + it( 'should reject invalid getValue callback', () => { + registerBlockBindingsSource( { + name: 'core/testing', + label: 'testing', + getValue: 'should be a function', + } ); + expect( console ).toHaveErroredWith( + 'Block bindings source getValue must be a function.' + ); + expect( getBlockBindingsSource( 'core/testing' ) ).toBeUndefined(); + } ); + + // Check the `setValue` callback is correct. + it( 'should reject invalid setValue callback', () => { + registerBlockBindingsSource( { + name: 'core/testing', + label: 'testing', + setValue: 'should be a function', + } ); + expect( console ).toHaveErroredWith( + 'Block bindings source setValue must be a function.' + ); + expect( getBlockBindingsSource( 'core/testing' ) ).toBeUndefined(); + } ); + + // Check the `setValues` callback is correct. + it( 'should reject invalid setValues callback', () => { + registerBlockBindingsSource( { + name: 'core/testing', + label: 'testing', + setValues: 'should be a function', + } ); + expect( console ).toHaveErroredWith( + 'Block bindings source setValues must be a function.' + ); + expect( getBlockBindingsSource( 'core/testing' ) ).toBeUndefined(); + } ); + + // Check the `getPlaceholder` callback is correct. + it( 'should reject invalid getPlaceholder callback', () => { + registerBlockBindingsSource( { + name: 'core/testing', + label: 'testing', + getPlaceholder: 'should be a function', + } ); + expect( console ).toHaveErroredWith( + 'Block bindings source getPlaceholder must be a function.' + ); + expect( getBlockBindingsSource( 'core/testing' ) ).toBeUndefined(); + } ); + + // Check the `canUserEditValue` callback is correct. + it( 'should reject invalid canUserEditValue callback', () => { + registerBlockBindingsSource( { + name: 'core/testing', + label: 'testing', + canUserEditValue: 'should be a function', + } ); + expect( console ).toHaveErroredWith( + 'Block bindings source canUserEditValue must be a function.' + ); + expect( getBlockBindingsSource( 'core/testing' ) ).toBeUndefined(); + } ); + + // Check correct sources are registered as expected. + it( 'should register a valid source', () => { + const sourceProperties = { + label: 'Valid Source', + getValue: () => 'value', + setValue: () => 'new value', + setValues: () => 'new values', + getPlaceholder: () => 'placeholder', + canUserEditValue: () => true, + }; + registerBlockBindingsSource( { + name: 'core/valid-source', + ...sourceProperties, + } ); + expect( getBlockBindingsSource( 'core/valid-source' ) ).toEqual( + sourceProperties + ); + unregisterBlockBindingsSource( 'core/valid-source' ); + } ); + + it( 'should register a source with default values', () => { + registerBlockBindingsSource( { + name: 'core/valid-source', + label: 'Valid Source', + } ); + const source = getBlockBindingsSource( 'core/valid-source' ); + expect( source.getValue ).toBeUndefined(); + expect( source.setValue ).toBeUndefined(); + expect( source.setValues ).toBeUndefined(); + expect( source.getPlaceholder ).toBeUndefined(); + expect( source.canUserEditValue() ).toBe( false ); + unregisterBlockBindingsSource( 'core/valid-source' ); + } ); + + it( 'should reject registering the same source twice', () => { + const source = { + name: 'core/test-source', + label: 'Test Source', + }; + registerBlockBindingsSource( source ); + registerBlockBindingsSource( source ); + unregisterBlockBindingsSource( 'core/test-source' ); + expect( console ).toHaveErroredWith( + 'Block bindings source "core/test-source" is already registered.' + ); + } ); + } ); + + describe( 'unregisterBlockBindingsSource', () => { + it( 'should remove an existing block bindings source', () => { + registerBlockBindingsSource( { + name: 'core/test-source', + label: 'Test Source', + } ); + unregisterBlockBindingsSource( 'core/test-source' ); + expect( + getBlockBindingsSource( 'core/test-source' ) + ).toBeUndefined(); + } ); + + it( 'should reject removing a source that does not exist', () => { + unregisterBlockBindingsSource( 'core/non-existing-source' ); + expect( console ).toHaveErroredWith( + 'Block bindings source "core/non-existing-source" is not registered.' + ); + } ); + } ); } ); /* eslint-enable react/forbid-elements */ From c27eed890e3316c3f1fa401f537b942ae0b63f84 Mon Sep 17 00:00:00 2001 From: Mario Santos Date: Fri, 12 Jul 2024 10:05:37 +0200 Subject: [PATCH 15/15] Export all functions as private --- packages/blocks/src/api/index.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/blocks/src/api/index.js b/packages/blocks/src/api/index.js index b4b6b181e7e7ee..803467cb2187e2 100644 --- a/packages/blocks/src/api/index.js +++ b/packages/blocks/src/api/index.js @@ -2,7 +2,12 @@ * Internal dependencies */ import { lock } from '../lock-unlock'; -import { registerBlockBindingsSource } from './registration'; +import { + registerBlockBindingsSource, + unregisterBlockBindingsSource, + getBlockBindingsSource, + getBlockBindingsSources, +} from './registration'; // The blocktype is the most important concept within the block API. It defines // all aspects of the block configuration and its interfaces, including `edit` @@ -174,4 +179,7 @@ export { export const privateApis = {}; lock( privateApis, { registerBlockBindingsSource, + unregisterBlockBindingsSource, + getBlockBindingsSource, + getBlockBindingsSources, } );