-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Description
What problem does this address?
In a nutshell, when using filters [blocks/registerBlockType] and/or [editor.BlockEdit] to automatically generate unique block ids, this indicates to the editor that these blocks are now modified.
I know theres several issues about handling unique attributes within Gutenberg, but this deals with auto-generated attributes specifically.
In my opinion, automatically generated attribute values should be optionally ignored when considering if the block has been modified - what we really care about is user input that modifies the block, not something like an automatically generated block ID. we don't care about knowing whether or not the block ID is generated.
Some of this is partially addressed via __unstableMarkNextChangeAsNotPersistent from a UI perspective, however there's a lot of builtin functionality within the editor that utilizes isUnmodifiedBlock specifically, particularly the block inserter.
On a fresh paragraph block, an inserter appears that allows the user to replace that block with another, as core/paragraph functions as a placeholder.
When adding an autogenerated attribute to core/paragraph - or using it in a custom block that then uses setDefaultBlockName to override core/paragraph - this behaviour stops, and the block has been treated as modified despite the user only just clicking add new post and waiting for the page to load.
What is your proposed solution?
I propose adding a flag to the attribute itself that will tell isUnmodifiedBlock to ignore it.
https://github.com/WordPress/gutenberg/blob/trunk/packages/blocks/src/api/utils.js#L40
function isUnmodifiedBlock( block ) {
// Cache a created default block if no cache exists or the default block
// name changed.
if ( ! isUnmodifiedBlock[ block.name ] ) {
isUnmodifiedBlock[ block.name ] = createBlock( block.name );
}
const newBlock = isUnmodifiedBlock[ block.name ];
const blockType = getBlockType( block.name );
return Object.keys( blockType?.attributes ?? {} ).every(
( key ) => {
const attr = blockType.attributes[key];
if (attr?.ignoreModified === true) {
return true;
}
return newBlock.attributes[ key ] === block.attributes[ key ];
}
);
}
ignoreModified kinda sucks as a name, but this is the gist of it.