diff --git a/packages/block-editor/src/hooks/anchor.js b/packages/block-editor/src/hooks/anchor.js index bed166dceb8807..dc8e1396879d1b 100644 --- a/packages/block-editor/src/hooks/anchor.js +++ b/packages/block-editor/src/hooks/anchor.js @@ -153,7 +153,48 @@ export function addSaveProps( extraProps, blockType, attributes ) { return extraProps; } +/** + * Make sure the anchor continues to stay unique when the block is cloned + * + * @param {string} blockType type of the block + * @param {Object} block cloned block object + * @return {Object} modified cloned block object + */ +export function cloneAttribute( blockType, block ) { + if ( + hasBlockSupport( blockType, 'anchor' ) && + has( block, 'attributes.anchor' ) + ) { + // check wether the anchor already ends with a `-${number}` + const index = block.attributes.anchor.lastIndexOf( '-' ); + const result = block.attributes.anchor.substring( index + 1 ); + + // store the anchor without the `-${number}` + const shortendAnchor = + index > 0 + ? block.attributes.anchor.substring( 0, index ) + : block.attributes.anchor; + + // generate the suffix number + let suffix = 1; + if ( result ) { + const number = parseInt( result ); + + if ( number ) { + suffix = number + 1; + } + } + + // add the suffix to the anchor + block.attributes.anchor = `${ shortendAnchor }-${ suffix }`; + } + + // return the modified cloned block + return block; +} + addFilter( 'blocks.registerBlockType', 'core/anchor/attribute', addAttribute ); +addFilter( 'blocks.cloneBlock', 'core/anchor/clone', cloneAttribute ); addFilter( 'editor.BlockEdit', 'core/editor/anchor/with-inspector-control', diff --git a/packages/blocks/src/api/factory.js b/packages/blocks/src/api/factory.js index 4abd12a802f03f..83a23ac47986be 100644 --- a/packages/blocks/src/api/factory.js +++ b/packages/blocks/src/api/factory.js @@ -118,7 +118,14 @@ export function __experimentalCloneSanitizedBlock( } ); - return { + /** + * Filters the cloned block. + * The entire new block object is passed and can be modified + * + * @param {string} blockType block type of the block being transformed. + * @param {Object} block cloned block object + */ + return applyFilters( 'blocks.cloneBlock', block.name, { ...block, clientId, attributes: sanitizedAttributes, @@ -127,7 +134,7 @@ export function __experimentalCloneSanitizedBlock( block.innerBlocks.map( ( innerBlock ) => __experimentalCloneSanitizedBlock( innerBlock ) ), - }; + } ); } /**