From 165e6c7ae17bff97b0a354e45ece4573d5dc9e36 Mon Sep 17 00:00:00 2001 From: ramon Date: Thu, 27 Jul 2023 08:03:44 +1000 Subject: [PATCH 1/6] Initial commit: - Prevent footnote creation withing core/block - Only insert a footnote if one isn't found in the entity block list --- .../block-library/src/footnotes/format.js | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/packages/block-library/src/footnotes/format.js b/packages/block-library/src/footnotes/format.js index 2086005a509931..6b007e357dc113 100644 --- a/packages/block-library/src/footnotes/format.js +++ b/packages/block-library/src/footnotes/format.js @@ -16,6 +16,7 @@ import { } from '@wordpress/block-editor'; import { useSelect, useDispatch, useRegistry } from '@wordpress/data'; import { createBlock, store as blocksStore } from '@wordpress/blocks'; +import { useEntityBlockEditor } from '@wordpress/core-data'; /** * Internal dependencies @@ -34,23 +35,26 @@ export const format = { 'data-fn': 'data-fn', }, contentEditable: false, - [ usesContextKey ]: [ 'postType' ], + [ usesContextKey ]: [ 'postType', 'postId' ], edit: function Edit( { value, onChange, isObjectActive, - context: { postType }, + context: { postType, postId }, } ) { const registry = useRegistry(); const { getSelectedBlockClientId, getBlockRootClientId, getBlockName, - getBlocks, + getBlockParentsByBlockName, } = useSelect( blockEditorStore ); const footnotesBlockType = useSelect( ( select ) => select( blocksStore ).getBlockType( name ) ); + const [ blocks ] = useEntityBlockEditor( 'postType', postType, { + id: postId, + } ); const { selectionChange, insertBlock } = useDispatch( blockEditorStore ); @@ -62,6 +66,16 @@ export const format = { return null; } + // Checks if the selected block lives within a pattern. + if ( + getBlockParentsByBlockName( + getSelectedBlockClientId(), + 'core/block' + ).length > 0 + ) { + return null; + } + function onClick() { registry.batch( () => { let id; @@ -86,19 +100,8 @@ export const format = { onChange( newValue ); } - // BFS search to find the first footnote block. - let fnBlock = null; - { - const queue = [ ...getBlocks() ]; - while ( queue.length ) { - const block = queue.shift(); - if ( block.name === name ) { - fnBlock = block; - break; - } - queue.push( ...block.innerBlocks ); - } - } + // Finds the first footnote block. + let fnBlock = blocks?.find( ( block ) => block.name === name ); // Maybe this should all also be moved to the entity provider. // When there is no footnotes block in the post, create one and From f6087c7dd1f59a86744a13cc19461159bb6e8001 Mon Sep 17 00:00:00 2001 From: Andrew Serong <14988353+andrewserong@users.noreply.github.com> Date: Thu, 27 Jul 2023 15:48:24 +1000 Subject: [PATCH 2/6] Try grabbing controlled blocks from parent post content block --- .../block-library/src/footnotes/format.js | 37 +++++++++++++++---- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/packages/block-library/src/footnotes/format.js b/packages/block-library/src/footnotes/format.js index 6b007e357dc113..4272c545c0dd12 100644 --- a/packages/block-library/src/footnotes/format.js +++ b/packages/block-library/src/footnotes/format.js @@ -16,7 +16,6 @@ import { } from '@wordpress/block-editor'; import { useSelect, useDispatch, useRegistry } from '@wordpress/data'; import { createBlock, store as blocksStore } from '@wordpress/blocks'; -import { useEntityBlockEditor } from '@wordpress/core-data'; /** * Internal dependencies @@ -35,16 +34,17 @@ export const format = { 'data-fn': 'data-fn', }, contentEditable: false, - [ usesContextKey ]: [ 'postType', 'postId' ], + [ usesContextKey ]: [ 'postType' ], edit: function Edit( { value, onChange, isObjectActive, - context: { postType, postId }, + context: { postType }, } ) { const registry = useRegistry(); const { getSelectedBlockClientId, + getBlocks, getBlockRootClientId, getBlockName, getBlockParentsByBlockName, @@ -52,9 +52,6 @@ export const format = { const footnotesBlockType = useSelect( ( select ) => select( blocksStore ).getBlockType( name ) ); - const [ blocks ] = useEntityBlockEditor( 'postType', postType, { - id: postId, - } ); const { selectionChange, insertBlock } = useDispatch( blockEditorStore ); @@ -100,8 +97,32 @@ export const format = { onChange( newValue ); } - // Finds the first footnote block. - let fnBlock = blocks?.find( ( block ) => block.name === name ); + // Attempt to find a common parent post content block. + // This allows for locating blocks within a page edited in the site editor. + const parentPostContent = getBlockParentsByBlockName( + getSelectedBlockClientId(), + 'core/post-content' + ); + + // 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 = [ ...blocks ]; + while ( queue.length ) { + const block = queue.shift(); + if ( block.name === name ) { + fnBlock = block; + break; + } + queue.push( ...block.innerBlocks ); + } + } // Maybe this should all also be moved to the entity provider. // When there is no footnotes block in the post, create one and From 6fbe676397a8a962eded2e05526511045e9a0441 Mon Sep 17 00:00:00 2001 From: ramon Date: Mon, 31 Jul 2023 12:29:52 +1000 Subject: [PATCH 3/6] Cache `selectedClientId` Get hasParentCoreBlocks using separate useSelect call. --- .../block-library/src/footnotes/format.js | 40 +++++++++++++------ 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/packages/block-library/src/footnotes/format.js b/packages/block-library/src/footnotes/format.js index 4272c545c0dd12..1aa10f1eb6e20c 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', @@ -52,6 +56,18 @@ export const format = { const footnotesBlockType = useSelect( ( select ) => select( blocksStore ).getBlockType( name ) ); + const hasParentCoreBlocks = 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 ); @@ -64,12 +80,7 @@ export const format = { } // Checks if the selected block lives within a pattern. - if ( - getBlockParentsByBlockName( - getSelectedBlockClientId(), - 'core/block' - ).length > 0 - ) { + if ( hasParentCoreBlocks ) { return null; } @@ -97,11 +108,15 @@ export const format = { onChange( newValue ); } - // Attempt to find a common parent post content block. - // This allows for locating blocks within a page edited in the site editor. + 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( - getSelectedBlockClientId(), - 'core/post-content' + selectedClientId, + POST_CONTENT_BLOCK_NAME ); // When called with a post content block, getBlocks will return @@ -128,12 +143,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 ); } From 2764baa6dbcf337163b5ac6852ff2b268021977b Mon Sep 17 00:00:00 2001 From: ramon Date: Mon, 31 Jul 2023 17:08:04 +1000 Subject: [PATCH 4/6] Rename hasParentCoreBlocks to isBlockWithinPattern Add comments --- packages/block-library/src/footnotes/format.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/block-library/src/footnotes/format.js b/packages/block-library/src/footnotes/format.js index 1aa10f1eb6e20c..c7730c53316b77 100644 --- a/packages/block-library/src/footnotes/format.js +++ b/packages/block-library/src/footnotes/format.js @@ -56,7 +56,11 @@ export const format = { const footnotesBlockType = useSelect( ( select ) => select( blocksStore ).getBlockType( name ) ); - const hasParentCoreBlocks = useSelect( ( select ) => { + /* + * This useSelect exists because we need to use its return value + * outside the event callback. + */ + const isBlockWithinPattern = useSelect( ( select ) => { const { getBlockParentsByBlockName: _getBlockParentsByBlockName, getSelectedBlockClientId: _getSelectedBlockClientId, @@ -80,7 +84,7 @@ export const format = { } // Checks if the selected block lives within a pattern. - if ( hasParentCoreBlocks ) { + if ( isBlockWithinPattern ) { return null; } From b22b26e339c3492241f6db3a665c7ef06b8210dc Mon Sep 17 00:00:00 2001 From: ramon Date: Tue, 1 Aug 2023 10:46:50 +1000 Subject: [PATCH 5/6] Removing while loop since we're already fetching the post content parent in the `getBlockParentsByBlockName` call above --- packages/block-library/src/footnotes/format.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/block-library/src/footnotes/format.js b/packages/block-library/src/footnotes/format.js index c7730c53316b77..56175fbd6eec84 100644 --- a/packages/block-library/src/footnotes/format.js +++ b/packages/block-library/src/footnotes/format.js @@ -50,7 +50,6 @@ export const format = { getSelectedBlockClientId, getBlocks, getBlockRootClientId, - getBlockName, getBlockParentsByBlockName, } = useSelect( blockEditorStore ); const footnotesBlockType = useSelect( ( select ) => @@ -149,11 +148,8 @@ export const format = { if ( ! fnBlock ) { let rootClientId = getBlockRootClientId( selectedClientId ); - while ( - rootClientId && - getBlockName( rootClientId ) !== POST_CONTENT_BLOCK_NAME - ) { - rootClientId = getBlockRootClientId( rootClientId ); + if ( parentPostContent.length ) { + rootClientId = parentPostContent[ 0 ]; } fnBlock = createBlock( name ); From f2f7194672b1cbd48aa5c86c31e61a39020eb657 Mon Sep 17 00:00:00 2001 From: ramon Date: Tue, 1 Aug 2023 11:48:03 +1000 Subject: [PATCH 6/6] Reinstating while loop because it can deal with nested blocks --- packages/block-library/src/footnotes/format.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/block-library/src/footnotes/format.js b/packages/block-library/src/footnotes/format.js index 56175fbd6eec84..c7730c53316b77 100644 --- a/packages/block-library/src/footnotes/format.js +++ b/packages/block-library/src/footnotes/format.js @@ -50,6 +50,7 @@ export const format = { getSelectedBlockClientId, getBlocks, getBlockRootClientId, + getBlockName, getBlockParentsByBlockName, } = useSelect( blockEditorStore ); const footnotesBlockType = useSelect( ( select ) => @@ -148,8 +149,11 @@ export const format = { if ( ! fnBlock ) { let rootClientId = getBlockRootClientId( selectedClientId ); - if ( parentPostContent.length ) { - rootClientId = parentPostContent[ 0 ]; + while ( + rootClientId && + getBlockName( rootClientId ) !== POST_CONTENT_BLOCK_NAME + ) { + rootClientId = getBlockRootClientId( rootClientId ); } fnBlock = createBlock( name );