Skip to content

Commit

Permalink
Blocks: Remember raw source block for invalid blocks.
Browse files Browse the repository at this point in the history
Part of #38922

When the editor is unable to validate a block it should preserve the
broken content in the post and show an accurate representation of that
underlying markup in the absence of being able to interact with it.

Currently when showing a preview of an invalid block in the editor we
attempt to re-generate the save output for a block given the attributes
we originally parsed. This is a flawed approach, however, because by
the nature of being invalid we know that there is a problem with those
attributes as they are.

In this patch we're introducing the `source` attribute on a block which
only exists for invalid blocks at the time of this patch. That `source`
carries the original un-processed data for a block node and can be used
to reconstruct the original markup without using garbage data and without
inadvertently changing it through the series of autofixes, deprecations,
and the like that happen during normal block loading.

The noticable change is in `block-list/block` where we will be showing
that reconstruction rather than the re-generated block content. Previously
it was the case that the preview might represent a corrupted version of the
block or show the block as if emptied of all its content. Now, however,
the preview sould accurately reflect the HTML in the source post even
when it's invalid or unrecognized according to the editor.

Further work should take advantage of the `source` property to provide
a more consistent and trusting experience for working with unrecognized
content.
  • Loading branch information
dmsnell committed Mar 4, 2022
1 parent 446d001 commit 3698a70
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 8 deletions.
5 changes: 3 additions & 2 deletions packages/block-editor/src/components/block-list/block.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import {
} from '@wordpress/element';
import {
getBlockType,
getSaveContent,
isUnmodifiedDefaultBlock,
serializeRawBlock,
} from '@wordpress/blocks';
import { withFilters } from '@wordpress/components';
import {
Expand Down Expand Up @@ -74,6 +74,7 @@ function Block( { children, isHtml, ...props } ) {
}

function BlockListBlock( {
block: { source },
mode,
isLocked,
canRemove,
Expand Down Expand Up @@ -155,7 +156,7 @@ function BlockListBlock( {
let block;

if ( ! isValid ) {
const saveContent = getSaveContent( blockType, attributes );
const saveContent = serializeRawBlock( source );

block = (
<Block className="has-warning">
Expand Down
25 changes: 25 additions & 0 deletions packages/blocks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,31 @@ _Returns_

- `string`: The post content.

### serializeRawBlock

Serializes a block node into the native HTML-comment-powered block format.
CAVEAT: This function is intended for reserializing blocks as parsed by
valid parsers and skips any validation steps. This is NOT a generic
serialization function for in-memory blocks. For most purposes, see the
following functions available in the `@wordpress/blocks` package:

_Related_

- serializeBlock
- serialize For more on the format of block nodes as returned by valid parsers:
- `@wordpress/block-serialization-default-parser` package
- `@wordpress/block-serialization-spec-parser` package

_Parameters_

- _rawBlock_ `import(".").WPRawBlock`: A block node as returned by a valid parser.
- _options_ `?Object`: Serialization options.
- _options.isCommentDelimited_ `?boolean`: Whether to output HTML comments around blocks.

_Returns_

- `string`: An HTML string representing a block.

### setCategories

Sets the block categories.
Expand Down
1 change: 1 addition & 0 deletions packages/blocks/src/api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export {
// components whose mechanisms can be shielded from the `edit` implementation
// and just passed along.
export { default as parse } from './parser';
export { serializeRawBlock } from './parser/serialize-raw-block';
export {
getBlockAttributes,
parseWithAttributeSchema,
Expand Down
20 changes: 14 additions & 6 deletions packages/blocks/src/api/parser/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,13 @@ import { applyBuiltInValidationFixes } from './apply-built-in-validation-fixes';
*
* @typedef WPBlock
*
* @property {string} name Block name
* @property {Object } attributes Block raw or comment attributes.
* @property {WPBlock[]} innerBlocks Inner Blocks.
* @property {string} originalContent Original content of the block before validation fixes.
* @property {boolean} isValid Whether the block is valid.
* @property {Object[]} validationIssues Validation issues.
* @property {string} name Block name
* @property {Object } attributes Block raw or comment attributes.
* @property {WPBlock[]} innerBlocks Inner Blocks.
* @property {string} originalContent Original content of the block before validation fixes.
* @property {boolean} isValid Whether the block is valid.
* @property {Object[]} validationIssues Validation issues.
* @property {WPRawBlock} [source] Un-processed original copy of block if created through parser.
*/

/**
Expand Down Expand Up @@ -242,6 +243,13 @@ export function parseRawBlock( rawBlock ) {
blockType
);

if ( ! updatedBlock.isValid ) {
// Preserve the original unprocessed version of the block
// that we received so that we can preserve it in its
// existing state when we save.
updatedBlock.source = rawBlock;
}

if ( ! validatedBlock.isValid && updatedBlock.isValid ) {
/* eslint-disable no-console */
console.groupCollapsed( 'Updated Block: %s', blockType.name );
Expand Down

0 comments on commit 3698a70

Please sign in to comment.