Skip to content

Commit

Permalink
Blocks: Preserves source of unrecognized blocks inside of Code Editor (
Browse files Browse the repository at this point in the history
…#39523)

Following the work of #38923 where we started preserving the source
content for blocks that the editor fails to recognize, this patch
uses that information in the Code Editor to ensure that we don't
accidentally corrupt or lose content when making edits there.

Previously the `serializeBlock` function, which generates the HTML
for the Code Editor, would try to re-generated the saved content
for blocks that we know are invalid. Because we know the input is
invalid we can guarantee that the output will have even more problems.

Now that `serializeBlock` function is aware of the source content for
a block, and if the block is marked invalid _and_ that source exists
it will pass that along to the output and skip the processing and
re-generation of the saved content. This ensures that errors don't
cascade and that unrelated edits to other blocks from the Code Editor
won't destroy content in the marked-invalid blocks.
  • Loading branch information
dmsnell authored Mar 28, 2022
1 parent b1f1541 commit 58ed1a8
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 2 deletions.
11 changes: 9 additions & 2 deletions packages/blocks/src/api/serializer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down Expand Up @@ -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 );

Expand Down
42 changes: 42 additions & 0 deletions packages/blocks/src/api/test/serializer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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: '<p>Not a quote</p>',
innerBlocks: [],
innerContent: [ '<p>Not a quote</p>' ],
},
};

expect( serializeBlock( block ) ).toBe(
'<!-- wp:quote -->\n<p>Not a quote</p>\n<!-- /wp:quote -->'
);
} );
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( '<!-- wp:quote /-->' );
} );
} );

describe( 'serialize()', () => {
Expand Down

0 comments on commit 58ed1a8

Please sign in to comment.