From fbc3712c8d5bab35b7d2d0f85878b4830350dc37 Mon Sep 17 00:00:00 2001 From: Ramon Date: Tue, 1 Aug 2023 12:29:34 +1000 Subject: [PATCH] Footnotes: disable for synced patterns and prevent duplication for pages in site editor (#53003) * Initial commit: - Prevent footnote creation withing core/block - Only insert a footnote if one isn't found in the entity block list * Try grabbing controlled blocks from parent post content block * Cache `selectedClientId` Get hasParentCoreBlocks using separate useSelect call. * Rename hasParentCoreBlocks to isBlockWithinPattern Add comments * Removing while loop since we're already fetching the post content parent in the `getBlockParentsByBlockName` call above * Reinstating while loop because it can deal with nested blocks --------- Co-authored-by: Andrew Serong <14988353+andrewserong@users.noreply.github.com> --- .../block-library/src/footnotes/format.js | 52 +++++++++++++++++-- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/packages/block-library/src/footnotes/format.js b/packages/block-library/src/footnotes/format.js index 2086005a50993..c7730c53316b7 100644 --- a/packages/block-library/src/footnotes/format.js +++ b/packages/block-library/src/footnotes/format.js @@ -26,6 +26,10 @@ import { unlock } from '../lock-unlock'; const { usesContextKey } = unlock( privateApis ); export const formatName = 'core/footnote'; + +const POST_CONTENT_BLOCK_NAME = 'core/post-content'; +const SYNCED_PATTERN_BLOCK_NAME = 'core/block'; + export const format = { title: __( 'Footnote' ), tagName: 'sup', @@ -44,13 +48,30 @@ export const format = { const registry = useRegistry(); const { getSelectedBlockClientId, + getBlocks, getBlockRootClientId, getBlockName, - getBlocks, + getBlockParentsByBlockName, } = useSelect( blockEditorStore ); const footnotesBlockType = useSelect( ( select ) => select( blocksStore ).getBlockType( name ) ); + /* + * This useSelect exists because we need to use its return value + * outside the event callback. + */ + const isBlockWithinPattern = useSelect( ( select ) => { + const { + getBlockParentsByBlockName: _getBlockParentsByBlockName, + getSelectedBlockClientId: _getSelectedBlockClientId, + } = select( blockEditorStore ); + const parentCoreBlocks = _getBlockParentsByBlockName( + _getSelectedBlockClientId(), + SYNCED_PATTERN_BLOCK_NAME + ); + return parentCoreBlocks && parentCoreBlocks.length > 0; + }, [] ); + const { selectionChange, insertBlock } = useDispatch( blockEditorStore ); @@ -62,6 +83,11 @@ export const format = { return null; } + // Checks if the selected block lives within a pattern. + if ( isBlockWithinPattern ) { + return null; + } + function onClick() { registry.batch( () => { let id; @@ -86,10 +112,27 @@ export const format = { onChange( newValue ); } + const selectedClientId = getSelectedBlockClientId(); + + /* + * Attempts to find a common parent post content block. + * This allows for locating blocks within a page edited in the site editor. + */ + const parentPostContent = getBlockParentsByBlockName( + selectedClientId, + POST_CONTENT_BLOCK_NAME + ); + + // When called with a post content block, getBlocks will return + // the block with controlled inner blocks included. + const blocks = parentPostContent.length + ? getBlocks( parentPostContent[ 0 ] ) + : getBlocks(); + // BFS search to find the first footnote block. let fnBlock = null; { - const queue = [ ...getBlocks() ]; + const queue = [ ...blocks ]; while ( queue.length ) { const block = queue.shift(); if ( block.name === name ) { @@ -104,12 +147,11 @@ export const format = { // When there is no footnotes block in the post, create one and // insert it at the bottom. if ( ! fnBlock ) { - const clientId = getSelectedBlockClientId(); - let rootClientId = getBlockRootClientId( clientId ); + let rootClientId = getBlockRootClientId( selectedClientId ); while ( rootClientId && - getBlockName( rootClientId ) !== 'core/post-content' + getBlockName( rootClientId ) !== POST_CONTENT_BLOCK_NAME ) { rootClientId = getBlockRootClientId( rootClientId ); }