Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecation does not work if Block Wrapper does not use blockProps #61833

Open
digamber89 opened this issue May 21, 2024 · 0 comments
Open

Deprecation does not work if Block Wrapper does not use blockProps #61833

digamber89 opened this issue May 21, 2024 · 0 comments
Labels
[Feature] Block API API that allows to express the block paradigm. [Feature] Block Validation/Deprecation Handling block validation to determine accuracy and deprecation [Type] Bug An existing feature does not function as intended

Comments

@digamber89
Copy link

digamber89 commented May 21, 2024

Description

I have created a repo to illustrate the issue.
https://github.com/digamber89/block-deprecation-issue

I am experiencing an issue in WordPress Gutenberg with block deprecation not functioning as intended
For deprecation save output an automatic class wp-block-blockNamesSpace-blockName is appended to the output generated by the save function of the installed block. This addition, while not inherently problematic, is causing difficulties when it comes to block deprecation.

The dilemma arises when a block's save function does not have the automatically added class.
During validation, when checking against deprecation/old block the class is auto inserted which creates a discrepancy between the original saved content and the newly generated content.
For example i will use version 1.0.0 to version 1.1.0 to illustrate in the below example.
Save.js - version 1.0.0

export default function save() {
	return (
		<p>
			{ 'Test Block Deprecation Issue – hello from the saved content!' }
		</p>
	);
}

Lets say we change the block for next update:
Save.js - version 1.1.0 ( change p to div )

export default function save() {
	return (
		<div>
			{ 'Test Block Deprecation Issue – hello from the saved content!' }
		</div>
	);
}

Handling deprecation via index.js - version 1.1.0

registerBlockType(metadata.name, {
	/**
	 * @see ./edit.js
	 */
	edit: Edit,

	/**
	 * @see ./save.js
	 */
	save,
	deprecated: [
		{
			save () {
				return (
					<p>
						{'Test Block Deprecation Issue – hello from the saved content!'}
					</p>
				)
			},
		},
	],
})

This deprecation will not work. Because the block created for the deprecations is auto adding the wp-block-blockNamesSpace-blockName class to the output for the save functions causing the block comparison to return as in correct so the save content is
Saved Content
<p>Test Block Deprecation Issue – hello from the saved content!</p>
But
Save Function Output For Deprecation being compared is
<div className="wp-block-blockNamesSpace-blockName">Test Block Deprecation Issue – hello from the saved content!</div>

To check this I modified
packages/blocks/src/api/validation/index.js

	const isFallbackBlock =
		block.name === getFreeformContentHandlerName() ||
		block.name === getUnregisteredTypeHandlerName()

	// Shortcut to avoid costly validation.
	if (isFallbackBlock) {
		return [true, []]
	}

	const logger = createQueuedLogger()
	const blockType = normalizeBlockType(blockTypeOrName)
	let generatedBlockContent
	try {
		generatedBlockContent = getSaveContent(blockType, block.attributes)
	} catch (error) {
		logger.error(
			'Block validation failed because an error occurred while generating block content:\n\n%s',
			error.toString(),
		)

		return [false, logger.getItems()]
	}

	const isValid = isEquivalentHTML(
		block.originalContent,
		generatedBlockContent,
		logger,
	)
	if (logNow === true) {
		console.log(  'From Post Content', block.originalContent )
		console.log(  'From Save Function', generatedBlockContent )
	}

	if (!isValid) {
		logger.error(
			'Block validation failed for `%s` (%o).\n\nContent generated by `save` function:\n\n%s\n\nContent retrieved from post body:\n\n%s',
			blockType.name,
			blockType,
			generatedBlockContent,
			block.originalContent,
		)
	}

	return [isValid, logger.getItems()]
}

packages/blocks/src/api/parser/apply-block-deprecated-versions.js

export function applyBlockDeprecatedVersions( block, rawBlock, blockType ) {
	const parsedAttributes = rawBlock.attrs;
	const { deprecated: deprecatedDefinitions } = blockType;
	// Bail early if there are no registered deprecations to be handled.
	if ( ! deprecatedDefinitions || ! deprecatedDefinitions.length ) {
		return block;
	}

	// By design, blocks lack any sort of version tracking. Instead, to process
	// outdated content the system operates a queue out of all the defined
	// attribute shapes and tries each definition until the input produces a
	// valid result. This mechanism seeks to avoid polluting the user-space with
	// machine-specific code. An invalid block is thus a block that could not be
	// matched successfully with any of the registered deprecation definitions.
	for ( let i = 0; i < deprecatedDefinitions.length; i++ ) {
		// A block can opt into a migration even if the block is valid by
		// defining `isEligible` on its deprecation. If the block is both valid
		// and does not opt to migrate, skip.
		const { isEligible = stubFalse } = deprecatedDefinitions[ i ];
		if (
			block.isValid &&
			! isEligible( parsedAttributes, block.innerBlocks, {
				blockNode: rawBlock,
				block,
			} )
		) {
			continue;
		}

		// Block type properties which could impact either serialization or
		// parsing are not considered in the deprecated block type by default,
		// and must be explicitly provided.
		const deprecatedBlockType = Object.assign(
			omit( blockType, DEPRECATED_ENTRY_KEYS ),
			deprecatedDefinitions[ i ]
		);

		let migratedBlock = {
			...block,
			attributes: getBlockAttributes(
				deprecatedBlockType,
				block.originalContent,
				parsedAttributes
			),
		};

		let logNow = block.name === 'digthis/block-deprecation-issue';
		// Ignore the deprecation if it produces a block which is not valid.
		let [ isValid ] = validateBlock( migratedBlock, deprecatedBlockType, logNow );
		if(block.name === 'digthis/block-deprecation-issue') {
			console.log('valid',isValid, migratedBlock, deprecatedBlockType);
		}

		// If the migrated block is not valid initially, try the built-in fixes.
		if ( ! isValid ) {
			migratedBlock = applyBuiltInValidationFixes(
				migratedBlock,
				deprecatedBlockType
			);
			[ isValid ] = validateBlock( migratedBlock, deprecatedBlockType, true );
		}

		// An invalid block does not imply incorrect HTML but the fact block
		// source information could be lost on re-serialization.
		if ( ! isValid ) {
			continue;
		}

		let migratedInnerBlocks = migratedBlock.innerBlocks;
		let migratedAttributes = migratedBlock.attributes;

		// A block may provide custom behavior to assign new attributes and/or
		// inner blocks.
		const { migrate } = deprecatedBlockType;
		if ( migrate ) {
			let migrated = migrate( migratedAttributes, block.innerBlocks );
			if ( ! Array.isArray( migrated ) ) {
				migrated = [ migrated ];
			}

			[
				migratedAttributes = parsedAttributes,
				migratedInnerBlocks = block.innerBlocks,
			] = migrated;
		}

		block = {
			...block,
			attributes: migratedAttributes,
			innerBlocks: migratedInnerBlocks,
			isValid: true,
			validationIssues: [],
		};
	}

	return block;
}

To validate that this is the exact issue that's happening.

Step-by-step reproduction instructions

  1. Checkout https://github.com/digamber89/block-deprecation-issue
  2. npm i
  3. npm run start
  4. Add the test block - save.
  5. git checkout deprecate

Expected result Deprecation will work.
But you will still see Attempt block recovery.

Screenshots, screen recording, code snippet

https://go.screenpal.com/watch/cZhrqhVLAoA

Environment info

  • WordPress 6.5.3
  • Gutenberg 18.4.0-rc.1
  • Mac Sonoma 14.4.1

Please confirm that you have searched existing issues in the repo.

Yes

Please confirm that you have tested with all plugins deactivated except Gutenberg.

Yes

@digamber89 digamber89 added the [Type] Bug An existing feature does not function as intended label May 21, 2024
@jordesign jordesign added the [Feature] Block API API that allows to express the block paradigm. label May 24, 2024
@gziolo gziolo added the [Feature] Block Validation/Deprecation Handling block validation to determine accuracy and deprecation label Jun 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Block API API that allows to express the block paradigm. [Feature] Block Validation/Deprecation Handling block validation to determine accuracy and deprecation [Type] Bug An existing feature does not function as intended
Projects
None yet
Development

No branches or pull requests

3 participants