diff --git a/packages/block-editor/src/components/rich-text/get-rich-text-values.js b/packages/block-editor/src/components/rich-text/get-rich-text-values.js index 9af2eb054cf6c..bd1c62ea5e6f6 100644 --- a/packages/block-editor/src/components/rich-text/get-rich-text-values.js +++ b/packages/block-editor/src/components/rich-text/get-rich-text-values.js @@ -18,13 +18,13 @@ import { Content } from './content'; * except that it does not render the elements to a string, but instead collects * the values of all rich text `Content` elements. */ -function addValuesForElement( element, ...args ) { +function addValuesForElement( element, values, innerBlocks ) { if ( null === element || undefined === element || false === element ) { return; } if ( Array.isArray( element ) ) { - return addValuesForElements( element, ...args ); + return addValuesForElements( element, values, innerBlocks ); } switch ( typeof element ) { @@ -38,13 +38,12 @@ function addValuesForElement( element, ...args ) { switch ( type ) { case StrictMode: case Fragment: - return addValuesForElements( props.children, ...args ); + return addValuesForElements( props.children, values, innerBlocks ); case RawHTML: return; case InnerBlocks.Content: - return addValuesForBlocks( ...args ); + return addValuesForBlocks( values, innerBlocks ); case Content: - const [ values ] = args; values.push( props.value ); return; } @@ -52,21 +51,19 @@ function addValuesForElement( element, ...args ) { switch ( typeof type ) { case 'string': if ( typeof props.children !== 'undefined' ) { - return addValuesForElements( props.children, ...args ); + return addValuesForElements( + props.children, + values, + innerBlocks + ); } return; case 'function': - if ( - type.prototype && - typeof type.prototype.render === 'function' - ) { - return addValuesForElement( - new type( props ).render(), - ...args - ); - } - - return addValuesForElement( type( props ), ...args ); + const el = + type.prototype && typeof type.prototype.render === 'function' + ? new type( props ).render() + : type( props ); + return addValuesForElement( el, values, innerBlocks ); } } @@ -78,20 +75,17 @@ function addValuesForElements( children, ...args ) { } } -function _getSaveElement( name, attributes, innerBlocks ) { - return getSaveElement( - name, - attributes, - innerBlocks.map( ( block ) => - _getSaveElement( block.name, block.attributes, block.innerBlocks ) - ) - ); -} - function addValuesForBlocks( values, blocks ) { for ( let i = 0; i < blocks.length; i++ ) { const { name, attributes, innerBlocks } = blocks[ i ]; - const saveElement = _getSaveElement( name, attributes, innerBlocks ); + const saveElement = getSaveElement( + name, + attributes, + // Instead of letting save elements use `useInnerBlocksProps.save`, + // force them to use InnerBlocks.Content instead so we can intercept + // a single component. + + ); addValuesForElement( saveElement, values, innerBlocks ); } } diff --git a/packages/blocks/src/api/serializer.js b/packages/blocks/src/api/serializer.js index 92559b1a0e717..6c45f08ee6aab 100644 --- a/packages/blocks/src/api/serializer.js +++ b/packages/blocks/src/api/serializer.js @@ -98,12 +98,11 @@ export function getBlockProps( props = {} ) { */ export function getInnerBlocksProps( props = {} ) { const { innerBlocks } = innerBlocksPropsProvider; - const [ firstBlock ] = innerBlocks ?? []; - if ( ! firstBlock ) return props; - // If the innerBlocks passed to `getSaveElement` are not blocks but already - // components, return the props as is. This is the case for - // `getRichTextValues`. - if ( ! firstBlock.clientId ) return { ...props, children: innerBlocks }; + // Allow a different component to be passed to getSaveElement to handle + // inner blocks, bypassing the default serialisation. + if ( ! Array.isArray( innerBlocks ) ) { + return { ...props, children: innerBlocks }; + } // Value is an array of blocks, so defer to block serializer. const html = serialize( innerBlocks, { isInnerBlocks: true } ); // Use special-cased raw HTML tag to avoid default escaping.