From 06f5975e3df80f1a9f2257a18d7534426c7ef100 Mon Sep 17 00:00:00 2001 From: Kai Hao Date: Tue, 16 Apr 2024 18:11:36 +0800 Subject: [PATCH] Allow overrides of the default list --- packages/block-library/src/block/edit.js | 30 +---------- packages/patterns/src/api/index.js | 45 ++++++++++++++++ packages/patterns/src/api/test/index.js | 69 ++++++++++++++++++++++++ packages/patterns/src/private-apis.js | 8 ++- 4 files changed, 122 insertions(+), 30 deletions(-) create mode 100644 packages/patterns/src/api/test/index.js diff --git a/packages/block-library/src/block/edit.js b/packages/block-library/src/block/edit.js index 616663cbc315f8..da217a99de11eb 100644 --- a/packages/block-library/src/block/edit.js +++ b/packages/block-library/src/block/edit.js @@ -38,7 +38,7 @@ import { name as patternBlockName } from './index'; import { unlock } from '../lock-unlock'; const { useLayoutClasses } = unlock( blockEditorPrivateApis ); -const { isOverridableBlock, PARTIAL_SYNCING_SUPPORTED_BLOCKS } = +const { isOverridableBlock, hasOverridableBlocks, getOverridableAttributes } = unlock( patternsPrivateApis ); const fullAlignments = [ 'full', 'wide', 'left', 'right' ]; @@ -91,34 +91,6 @@ const useInferredLayout = ( blocks, parentLayout ) => { }, [ blocks, parentLayout ] ); }; -function hasOverridableBlocks( blocks ) { - return blocks.some( ( block ) => { - if ( isOverridableBlock( block ) ) return true; - return hasOverridableBlocks( block.innerBlocks ); - } ); -} - -function getOverridableAttributes( block ) { - const set = new Set(); - for ( const [ attributeKey, binding ] of Object.entries( - block.attributes.metadata.bindings - ) ) { - if ( - attributeKey === '__default' && - binding.source === 'core/pattern-overrides' - ) { - PARTIAL_SYNCING_SUPPORTED_BLOCKS[ block.name ].forEach( - ( attribute ) => { - set.add( attribute ); - } - ); - } else if ( binding.source === 'core/pattern-overrides' ) { - set.add( attributeKey ); - } - } - return Array.from( set ); -} - function applyInitialContentValuesToInnerBlocks( blocks, content = {}, diff --git a/packages/patterns/src/api/index.js b/packages/patterns/src/api/index.js index 448001f891fbae..a6a4a08bb324e6 100644 --- a/packages/patterns/src/api/index.js +++ b/packages/patterns/src/api/index.js @@ -22,3 +22,48 @@ export function isOverridableBlock( block ) { ) ); } + +/** + * Determines whether the blocks list has overridable blocks. + * + * @param {WPBlock[]} blocks The blocks list. + * + * @return {boolean} `true` if the list has overridable blocks, `false` otherwise. + */ +export function hasOverridableBlocks( blocks ) { + return blocks.some( ( block ) => { + if ( isOverridableBlock( block ) ) return true; + return hasOverridableBlocks( block.innerBlocks ); + } ); +} + +/** + * Get the overridable attributes for the give block. + * + * @param {WPBlock} block The block to test. + * + * @return {string[]} The attribute names in an array. + */ +export function getOverridableAttributes( block ) { + const set = new Set(); + // get default attributes for the block. + if ( block.attributes.metadata.bindings.__default ) { + PARTIAL_SYNCING_SUPPORTED_BLOCKS[ block.name ].forEach( + ( attribute ) => { + set.add( attribute ); + } + ); + } + // Any additional attributes and overrides. + for ( const [ attributeKey, binding ] of Object.entries( + block.attributes.metadata.bindings + ) ) { + if ( attributeKey === '__default' ) continue; + if ( binding.source === 'core/pattern-overrides' ) { + set.add( attributeKey ); + } else { + set.delete( attributeKey ); + } + } + return Array.from( set ); +} diff --git a/packages/patterns/src/api/test/index.js b/packages/patterns/src/api/test/index.js new file mode 100644 index 00000000000000..81224da8170a1d --- /dev/null +++ b/packages/patterns/src/api/test/index.js @@ -0,0 +1,69 @@ +/** + * Internal dependencies + */ +import { getOverridableAttributes } from '../'; +import { PARTIAL_SYNCING_SUPPORTED_BLOCKS } from '../../constants'; + +/** + * WordPress dependencies + */ +import { createBlock } from '@wordpress/blocks'; +import { registerCoreBlocks } from '@wordpress/block-library'; + +describe( 'getOverridableAttributes', () => { + beforeAll( () => { + registerCoreBlocks(); + } ); + + it( 'should return an array of overridable attributes', () => { + const block = createBlock( 'core/paragraph', { + metadata: { + bindings: { + content: { source: 'core/pattern-overrides' }, + }, + }, + } ); + + const attributes = getOverridableAttributes( block ); + + expect( attributes ).toEqual( [ 'content' ] ); + } ); + + it( 'should return the default list for core blocks', () => { + const block = createBlock( 'core/image', { + metadata: { + bindings: { + __default: { source: 'core/pattern-overrides' }, + }, + }, + } ); + + const attributes = getOverridableAttributes( block ); + + expect( attributes ).toEqual( + PARTIAL_SYNCING_SUPPORTED_BLOCKS[ 'core/image' ] + ); + } ); + + it( 'should allow overrides of the default list', () => { + const block = createBlock( 'core/image', { + metadata: { + bindings: { + __default: { source: 'core/pattern-overrides' }, + alt: { source: 'core/post-meta' }, + width: { source: 'core/pattern-overrides' }, + }, + }, + } ); + + const attributes = getOverridableAttributes( block ); + + const defaultAttributes = new Set( + PARTIAL_SYNCING_SUPPORTED_BLOCKS[ 'core/image' ] + ); + defaultAttributes.delete( 'alt' ); + defaultAttributes.add( 'width' ); + + expect( attributes ).toEqual( Array.from( defaultAttributes ) ); + } ); +} ); diff --git a/packages/patterns/src/private-apis.js b/packages/patterns/src/private-apis.js index 05417de2b2c669..5d11e6aecdded1 100644 --- a/packages/patterns/src/private-apis.js +++ b/packages/patterns/src/private-apis.js @@ -11,7 +11,11 @@ import { default as DuplicatePatternModal, useDuplicatePatternProps, } from './components/duplicate-pattern-modal'; -import { isOverridableBlock } from './api'; +import { + isOverridableBlock, + hasOverridableBlocks, + getOverridableAttributes, +} from './api'; import RenamePatternModal from './components/rename-pattern-modal'; import PatternsMenuItems from './components'; import RenamePatternCategoryModal from './components/rename-pattern-category-modal'; @@ -34,6 +38,8 @@ lock( privateApis, { CreatePatternModalContents, DuplicatePatternModal, isOverridableBlock, + hasOverridableBlocks, + getOverridableAttributes, useDuplicatePatternProps, RenamePatternModal, PatternsMenuItems,