From 01ea4bbb3d0cd09ae41baa48eca6f5f18dca0b31 Mon Sep 17 00:00:00 2001 From: Tom Cafferkey Date: Wed, 8 May 2024 10:56:45 +0100 Subject: [PATCH] Convert blocks that are an alias block into their canonical block --- .../src/api/parser/convert-alias-block.js | 21 ++++++++++++++ packages/blocks/src/api/parser/index.js | 29 +++++++++++++++++++ packages/blocks/src/api/serializer.js | 14 +++++---- 3 files changed, 59 insertions(+), 5 deletions(-) create mode 100644 packages/blocks/src/api/parser/convert-alias-block.js diff --git a/packages/blocks/src/api/parser/convert-alias-block.js b/packages/blocks/src/api/parser/convert-alias-block.js new file mode 100644 index 0000000000000..0f58649842da8 --- /dev/null +++ b/packages/blocks/src/api/parser/convert-alias-block.js @@ -0,0 +1,21 @@ +/** + * Convert alias blocks to their canonical form. This function is used + * both in the parser level for previous content and to convert such blocks + * used in Custom Post Types templates. + * + * @param {string} name The block's name + * @param {Object} attributes The block's attributes + * + * @return {[string, Object]} The block's name and attributes, changed accordingly if a match was found + */ +export function convertAliasBlockNameAndAttributes( name, attributes ) { + const canonicalBlockName = attributes.metadata?.alias; + let blockName = name; + const newAttributes = { ...attributes }; + if ( canonicalBlockName ) { + blockName = canonicalBlockName; + newAttributes.metadata.alias = name; + } + + return [ blockName, newAttributes ]; +} diff --git a/packages/blocks/src/api/parser/index.js b/packages/blocks/src/api/parser/index.js index f8ff0c68964dc..d5b1896e8b7ea 100644 --- a/packages/blocks/src/api/parser/index.js +++ b/packages/blocks/src/api/parser/index.js @@ -16,6 +16,7 @@ import { getSaveContent } from '../serializer'; import { validateBlock } from '../validation'; import { createBlock } from '../factory'; import { convertLegacyBlockNameAndAttributes } from './convert-legacy-block'; +import { convertAliasBlockNameAndAttributes } from './convert-alias-block'; import { serializeRawBlock } from './serialize-raw-block'; import { getBlockAttributes } from './get-block-attributes'; import { applyBlockDeprecatedVersions } from './apply-block-deprecated-versions'; @@ -78,6 +79,31 @@ function convertLegacyBlocks( rawBlock ) { }; } +/** + * Convert alias blocks to their canonical form. This function is used + * both in the parser level for previous content and to convert such blocks + * used in Custom Post Types templates. + * + * We are swapping the alias value with the block name depending on whether we are serializing or parsing. + * This is because the alias is used to serialize the block name, but when parsing, we need to convert the alias to the block name. + * + * @param {WPRawBlock} rawBlock + * + * @return {WPRawBlock} The block's name and attributes, changed accordingly if a match was found + */ +function convertAliasBlocks( rawBlock ) { + const [ correctName, correctedAttributes ] = + convertAliasBlockNameAndAttributes( + rawBlock.blockName, + rawBlock.attrs + ); + return { + ...rawBlock, + blockName: correctName, + attrs: correctedAttributes, + }; +} + /** * Normalize the raw block by applying the fallback block name if none given, * sanitize the parsed HTML... @@ -201,6 +227,9 @@ export function parseRawBlock( rawBlock, options ) { // we added this function to properly parse the old content. normalizedBlock = convertLegacyBlocks( normalizedBlock ); + // Convert alias blocks to their canonical form. + normalizedBlock = convertAliasBlocks( normalizedBlock ); + // Try finding the type for known block name. let blockType = getBlockType( normalizedBlock.blockName ); diff --git a/packages/blocks/src/api/serializer.js b/packages/blocks/src/api/serializer.js index 609e62fc7e84b..c2751f79e83e7 100644 --- a/packages/blocks/src/api/serializer.js +++ b/packages/blocks/src/api/serializer.js @@ -21,6 +21,7 @@ import { } from './registration'; import { serializeRawBlock } from './parser/serialize-raw-block'; import { isUnmodifiedDefaultBlock, normalizeBlockType } from './utils'; +import { convertAliasBlockNameAndAttributes } from './parser/convert-alias-block'; /** @typedef {import('./parser').WPBlock} WPBlock */ @@ -322,15 +323,18 @@ export function getCommentDelimitedContent( attributes, content ) { + const [ correctBlockName, correctedAttributes ] = + convertAliasBlockNameAndAttributes( rawBlockName, attributes ); + const serializedAttributes = - attributes && Object.entries( attributes ).length - ? serializeAttributes( attributes ) + ' ' + correctedAttributes && Object.entries( correctedAttributes ).length + ? serializeAttributes( correctedAttributes ) + ' ' : ''; // Strip core blocks of their namespace prefix. - const blockName = rawBlockName?.startsWith( 'core/' ) - ? rawBlockName.slice( 5 ) - : rawBlockName; + const blockName = correctBlockName?.startsWith( 'core/' ) + ? correctBlockName.slice( 5 ) + : correctBlockName; // @todo make the `wp:` prefix potentially configurable.