From 51d5372bc4d5a9daa6260f1c5d4619d4f43aa299 Mon Sep 17 00:00:00 2001 From: Aki Hamano <54422211+t-hamano@users.noreply.github.com> Date: Tue, 4 Feb 2025 10:49:25 +0900 Subject: [PATCH] Block support: Preserve aria-label value in comment delimiter (#69002) Co-authored-by: t-hamano Co-authored-by: Mamaduka Co-authored-by: fabiankaegy --- packages/block-editor/src/hooks/aria-label.js | 11 ++-- .../parser/apply-built-in-validation-fixes.js | 18 +++++-- .../blocks/src/api/parser/fix-aria-label.js | 51 +++++++++++++++++++ packages/blocks/src/api/parser/test/index.js | 33 ++++++++++++ 4 files changed, 102 insertions(+), 11 deletions(-) create mode 100644 packages/blocks/src/api/parser/fix-aria-label.js diff --git a/packages/block-editor/src/hooks/aria-label.js b/packages/block-editor/src/hooks/aria-label.js index 7f93aa4ff8c8b2..89de261a169385 100644 --- a/packages/block-editor/src/hooks/aria-label.js +++ b/packages/block-editor/src/hooks/aria-label.js @@ -4,13 +4,6 @@ import { addFilter } from '@wordpress/hooks'; import { hasBlockSupport } from '@wordpress/blocks'; -const ARIA_LABEL_SCHEMA = { - type: 'string', - source: 'attribute', - attribute: 'aria-label', - selector: '*', -}; - /** * Filters registered block settings, extending attributes with ariaLabel using aria-label * of the first node. @@ -28,7 +21,9 @@ export function addAttribute( settings ) { // Gracefully handle if settings.attributes is undefined. settings.attributes = { ...settings.attributes, - ariaLabel: ARIA_LABEL_SCHEMA, + ariaLabel: { + type: 'string', + }, }; } diff --git a/packages/blocks/src/api/parser/apply-built-in-validation-fixes.js b/packages/blocks/src/api/parser/apply-built-in-validation-fixes.js index 13dbb1e6825c96..52d6583265e6b9 100644 --- a/packages/blocks/src/api/parser/apply-built-in-validation-fixes.js +++ b/packages/blocks/src/api/parser/apply-built-in-validation-fixes.js @@ -2,6 +2,7 @@ * Internal dependencies */ import { fixCustomClassname } from './fix-custom-classname'; +import { fixAriaLabel } from './fix-aria-label'; /** * Attempts to fix block invalidation by applying build-in validation fixes @@ -15,11 +16,22 @@ import { fixCustomClassname } from './fix-custom-classname'; * @return {WPBlock} Fixed block object */ export function applyBuiltInValidationFixes( block, blockType ) { - const updatedBlockAttributes = fixCustomClassname( - block.attributes, + const { attributes, originalContent } = block; + let updatedBlockAttributes = attributes; + + // Fix block invalidation for className attribute. + updatedBlockAttributes = fixCustomClassname( + attributes, + blockType, + originalContent + ); + // Fix block invalidation for ariaLabel attribute. + updatedBlockAttributes = fixAriaLabel( + updatedBlockAttributes, blockType, - block.originalContent + originalContent ); + return { ...block, attributes: updatedBlockAttributes, diff --git a/packages/blocks/src/api/parser/fix-aria-label.js b/packages/blocks/src/api/parser/fix-aria-label.js new file mode 100644 index 00000000000000..79fa30c713da20 --- /dev/null +++ b/packages/blocks/src/api/parser/fix-aria-label.js @@ -0,0 +1,51 @@ +/** + * Internal dependencies + */ +import { hasBlockSupport } from '../registration'; +import { parseWithAttributeSchema } from './get-block-attributes'; + +const ARIA_LABEL_ATTR_SCHEMA = { + type: 'string', + source: 'attribute', + selector: '[data-aria-label] > *', + attribute: 'aria-label', +}; + +/** + * Given an HTML string, returns the aria-label attribute assigned to + * the root element in the markup. + * + * @param {string} innerHTML Markup string from which to extract the aria-label. + * + * @return {string} The aria-label assigned to the root element. + */ +export function getHTMLRootElementAriaLabel( innerHTML ) { + const parsed = parseWithAttributeSchema( + `
${ innerHTML }
`, + ARIA_LABEL_ATTR_SCHEMA + ); + return parsed; +} + +/** + * Given a parsed set of block attributes, if the block supports ariaLabel + * and an aria-label attribute is found, the aria-label attribute is assigned + * to the block attributes. + * + * @param {Object} blockAttributes Original block attributes. + * @param {Object} blockType Block type settings. + * @param {string} innerHTML Original block markup. + * + * @return {Object} Filtered block attributes. + */ +export function fixAriaLabel( blockAttributes, blockType, innerHTML ) { + if ( ! hasBlockSupport( blockType, 'ariaLabel', false ) ) { + return blockAttributes; + } + const modifiedBlockAttributes = { ...blockAttributes }; + const ariaLabel = getHTMLRootElementAriaLabel( innerHTML ); + if ( ariaLabel ) { + modifiedBlockAttributes.ariaLabel = ariaLabel; + } + return modifiedBlockAttributes; +} diff --git a/packages/blocks/src/api/parser/test/index.js b/packages/blocks/src/api/parser/test/index.js index 42923a7d3eeb35..452fca329af76b 100644 --- a/packages/blocks/src/api/parser/test/index.js +++ b/packages/blocks/src/api/parser/test/index.js @@ -82,6 +82,39 @@ describe( 'block parser', () => { } ); } ); + it( 'should apply aria-label block validation fixes', () => { + registerBlockType( 'core/test-block', { + ...defaultBlockSettings, + attributes: { + fruit: { + type: 'string', + source: 'text', + selector: 'div', + }, + }, + supports: { + ariaLabel: true, + }, + save: ( { attributes } ) => ( +
+ { attributes.fruit } +
+ ), + } ); + + const block = parseRawBlock( { + blockName: 'core/test-block', + innerHTML: '
Bananas
', + attrs: { fruit: 'Bananas' }, + } ); + + expect( block.name ).toEqual( 'core/test-block' ); + expect( block.attributes ).toEqual( { + fruit: 'Bananas', + ariaLabel: 'custom-label', + } ); + } ); + it( 'should create the requested block if it exists', () => { registerBlockType( 'core/test-block', defaultBlockSettings );