diff --git a/packages/blocks/src/api/serializer.js b/packages/blocks/src/api/serializer.js index c249df7251db84..8c073c4d6d1791 100644 --- a/packages/blocks/src/api/serializer.js +++ b/packages/blocks/src/api/serializer.js @@ -24,8 +24,11 @@ import { getFreeformContentHandlerName, getUnregisteredTypeHandlerName, } from './registration'; +import { serializeRawBlock } from './parser/serialize-raw-block'; import { isUnmodifiedDefaultBlock, normalizeBlockType } from './utils'; +/** @typedef {import('./parser').WPBlock} WPBlock */ + /** * @typedef {Object} WPBlockSerializationOptions Serialization Options. * @@ -337,12 +340,16 @@ export function getCommentDelimitedContent( * Returns the content of a block, including comment delimiters, determining * serialized attributes and content form from the current state of the block. * - * @param {Object} block Block instance. - * @param {WPBlockSerializationOptions} options Serialization options. + * @param {WPBlock} block Block instance. + * @param {WPBlockSerializationOptions} options Serialization options. * * @return {string} Serialized block. */ export function serializeBlock( block, { isInnerBlocks = false } = {} ) { + if ( ! block.isValid && block.__unstableBlockSource ) { + return serializeRawBlock( block.__unstableBlockSource ); + } + const blockName = block.name; const saveContent = getBlockInnerHTML( block ); diff --git a/packages/blocks/src/api/test/serializer.js b/packages/blocks/src/api/test/serializer.js index 513eadeb84104c..22fa5bc7b6dc6a 100644 --- a/packages/blocks/src/api/test/serializer.js +++ b/packages/blocks/src/api/test/serializer.js @@ -307,6 +307,48 @@ describe( 'block serializer', () => { expect( content ).toBe( 'Bananas' ); } ); + it( 'preserves content from invalid blocks when source information is present', () => { + registerBlockType( 'core/quote', { + category: 'text', + title: 'Quote', + attributes: { content: 'string' }, + save: ( { attributes } ) => + createElement( 'blockquote', {}, attributes.content ), + } ); + + const block = { + ...createBlock( 'core/quote' ), + isValid: false, + __unstableBlockSource: { + blockName: 'quote', + attrs: {}, + innerHTML: '

Not a quote

', + innerBlocks: [], + innerContent: [ '

Not a quote

' ], + }, + }; + + expect( serializeBlock( block ) ).toBe( + '\n

Not a quote

\n' + ); + } ); + it( 're-generates content from invalid blocks when source information is missing (losing content)', () => { + registerBlockType( 'core/quote', { + category: 'text', + title: 'Quote', + attributes: { content: 'string' }, + save: ( { attributes } ) => + createElement( 'blockquote', {}, attributes.content ), + } ); + + // missing attributes as a result of a failed parse + const block = { + ...createBlock( 'core/quote' ), + isValid: false, + }; + + expect( serializeBlock( block ) ).toBe( '' ); + } ); } ); describe( 'serialize()', () => {