Skip to content
Merged
13 changes: 4 additions & 9 deletions packages/block-editor/src/hooks/anchor.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,6 @@ import { useBlockEditingMode } from '../components/block-editing-mode';
*/
const ANCHOR_REGEX = /[\s#]/g;

const ANCHOR_SCHEMA = {
type: 'string',
source: 'attribute',
attribute: 'id',
selector: '*',
};

/**
* Filters registered block settings, extending attributes with anchor using ID
* of the first node.
Expand All @@ -44,7 +37,9 @@ export function addAttribute( settings ) {
// Gracefully handle if settings.attributes is undefined.
settings.attributes = {
...settings.attributes,
anchor: ANCHOR_SCHEMA,
anchor: {
type: 'string',
},
};
}

Expand Down Expand Up @@ -90,7 +85,7 @@ function BlockEditAnchorControlPure( { anchor, setAttributes } ) {
onChange={ ( nextValue ) => {
nextValue = nextValue.replace( ANCHOR_REGEX, '-' );
setAttributes( {
anchor: nextValue,
anchor: nextValue !== '' ? nextValue : undefined,

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is necessary to avoid storing an empty string in comment delimiters. Also, without this change, some unit tests would fail.

} );
} }
autoCapitalize="none"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`anchor should set the ID attribute on the block 1`] = `
"<!-- wp:paragraph -->
"<!-- wp:paragraph {"anchor":"my-anchor"} -->
<p id="my-anchor"></p>
<!-- /wp:paragraph -->"
`;
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
exports[`Group block transforms to Columns block 1`] = `
"<!-- wp:columns -->
<div class="wp-block-columns"><!-- wp:column {"width":"100%"} -->
<div class="wp-block-column" style="flex-basis:100%"><!-- wp:group -->
<div class="wp-block-column" style="flex-basis:100%"><!-- wp:group {"anchor":"this-is-another-anchor"} -->
<div id="this-is-another-anchor" class="wp-block-group"><!-- wp:paragraph -->
<p>One.</p>
<!-- /wp:paragraph -->
Expand Down
2 changes: 1 addition & 1 deletion packages/block-library/src/list/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export function createListBlockFromDOMElement( listElement ) {
const type = listElement.getAttribute( 'type' );
const listAttributes = {
ordered: 'OL' === listElement.tagName,
anchor: listElement.id === '' ? undefined : listElement.id,
anchor: listElement.id ? listElement.id : undefined,

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without making this change, the mobile unit tests will fail. See: http://github.com/WordPress/gutenberg/actions/runs/16643294936/job/47097872501

start: listElement.getAttribute( 'start' )
? parseInt( listElement.getAttribute( 'start' ), 10 )
: undefined,
Expand Down
2 changes: 1 addition & 1 deletion packages/block-library/src/separator/transforms.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const transforms = {
blocks: [ 'core/spacer' ], // Transform to Spacer.
transform: ( { anchor } ) => {
return createBlock( 'core/spacer', {
anchor: anchor || '',
anchor: anchor || undefined,
} );
},
},
Expand Down
2 changes: 1 addition & 1 deletion packages/block-library/src/spacer/transforms.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const transforms = {
blocks: [ 'core/separator' ], // Transform to Separator.
transform: ( { anchor } ) => {
return createBlock( 'core/separator', {
anchor: anchor || '',
anchor: anchor || undefined,
} );
},
},
Expand Down
32 changes: 29 additions & 3 deletions packages/blocks/src/api/parser/apply-built-in-validation-fixes.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,21 @@
* Internal dependencies
*/
import { fixCustomClassname } from './fix-custom-classname';
import { fixAriaLabel } from './fix-aria-label';
import { fixGlobalAttribute } from './fix-global-attribute';

const ARIA_LABEL_ATTR_SCHEMA = {
type: 'string',
source: 'attribute',
selector: '[data-aria-label] > *',
attribute: 'aria-label',
};

const ANCHOR_ATTR_SCHEMA = {
type: 'string',
source: 'attribute',
selector: '[data-anchor] > *',
attribute: 'id',
};

/**
* Attempts to fix block invalidation by applying build-in validation fixes
Expand All @@ -26,10 +40,22 @@ export function applyBuiltInValidationFixes( block, blockType ) {
originalContent
);
// Fix block invalidation for ariaLabel attribute.
updatedBlockAttributes = fixAriaLabel(
updatedBlockAttributes = fixGlobalAttribute(
updatedBlockAttributes,
blockType,
originalContent
originalContent,
'ariaLabel',
'data-aria-label',
ARIA_LABEL_ATTR_SCHEMA
);
// Fix block invalidation for anchor attribute.
updatedBlockAttributes = fixGlobalAttribute(
updatedBlockAttributes,
blockType,
originalContent,
'anchor',
'data-anchor',
ANCHOR_ATTR_SCHEMA
);

return {
Expand Down
51 changes: 0 additions & 51 deletions packages/blocks/src/api/parser/fix-aria-label.js

This file was deleted.

63 changes: 63 additions & 0 deletions packages/blocks/src/api/parser/fix-global-attribute.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* Internal dependencies
*/
import { hasBlockSupport } from '../registration';
import { parseWithAttributeSchema } from './get-block-attributes';

/**
* Given an HTML string and an attribute schema, returns the specified attribute
* value from the root element in the markup.
*
* @param {string} innerHTML Markup string from which to extract the attribute.
* @param {string} dataAttribute The data attribute name to use as wrapper.
* @param {Object} attributeSchema The attribute schema configuration.
*
* @return {string} The attribute value assigned to the root element.
*/
export function getHTMLRootElement(
innerHTML,
dataAttribute,
attributeSchema
) {
const parsed = parseWithAttributeSchema(
`<div ${ dataAttribute }>${ innerHTML }</div>`,
attributeSchema
);
return parsed;
}

/**
* Given a parsed set of block attributes, if the block supports the specified attribute
* and the attribute is found in the HTML, the 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.
* @param {string} supportKey The block support key to check and attribute key to set.
* @param {string} dataAttribute The data attribute name to use as wrapper.
* @param {Object} attributeSchema The attribute schema configuration.
*
* @return {Object} Filtered block attributes.
*/
export function fixGlobalAttribute(
blockAttributes,
blockType,
innerHTML,
supportKey,
dataAttribute,
attributeSchema
) {
if ( ! hasBlockSupport( blockType, supportKey, false ) ) {
return blockAttributes;
}
const modifiedBlockAttributes = { ...blockAttributes };
const attributeValue = getHTMLRootElement(
innerHTML,
dataAttribute,
attributeSchema
);
if ( attributeValue ) {
modifiedBlockAttributes[ supportKey ] = attributeValue;
}
return modifiedBlockAttributes;
}
31 changes: 31 additions & 0 deletions packages/blocks/src/api/parser/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,37 @@ describe( 'block parser', () => {
} );
} );

it( 'should apply anchor block validation fixes', () => {
registerBlockType( 'core/test-block', {
...defaultBlockSettings,
attributes: {
fruit: {
type: 'string',
source: 'text',
selector: 'div',
},
},
supports: {
anchor: true,
},
save: ( { attributes } ) => (
<div id={ attributes.anchor }>{ attributes.fruit }</div>
),
} );

const block = parseRawBlock( {
blockName: 'core/test-block',
innerHTML: '<div id="custom-anchor">Bananas</div>',
attrs: { fruit: 'Bananas' },
} );

expect( block.name ).toEqual( 'core/test-block' );
expect( block.attributes ).toEqual( {
fruit: 'Bananas',
anchor: 'custom-anchor',
} );
} );

it( 'should create the requested block if it exists', () => {
registerBlockType( 'core/test-block', defaultBlockSettings );

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<!-- wp:form {"style":{"elements":{"link":{"color":{"text":"#ff0000"}}},"color":{"text":"#ff0000","background":"#00ffff"},"typography":{"fontSize":"30px"},"spacing":{"padding":{"top":"1px","bottom":"1px","left":"2px","right":"2px"},"margin":{"top":"3px","bottom":"3px","left":"4px","right":"4px"}}}} -->
<!-- wp:form {"anchor":"anchor","style":{"elements":{"link":{"color":{"text":"#ff0000"}}},"color":{"text":"#ff0000","background":"#00ffff"},"typography":{"fontSize":"30px"},"spacing":{"padding":{"top":"1px","bottom":"1px","left":"2px","right":"2px"},"margin":{"top":"3px","bottom":"3px","left":"4px","right":"4px"}}}} -->
<form id="anchor" class="wp-block-form has-text-color has-background has-link-color" style="color:#ff0000;background-color:#00ffff;margin-top:3px;margin-right:4px;margin-bottom:3px;margin-left:4px;padding-top:1px;padding-right:2px;padding-bottom:1px;padding-left:2px;font-size:30px" enctype="text/plain"></form>
<!-- /wp:form -->
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<!-- wp:form {"backgroundColor":"accent-1","textColor":"contrast","fontSize":"x-large","style":{"elements":{"link":{"color":{"text":"var:preset|color|contrast"}}},"spacing":{"padding":{"top":"var:preset|spacing|40","bottom":"var:preset|spacing|40","left":"var:preset|spacing|40","right":"var:preset|spacing|40"},"margin":{"top":"var:preset|spacing|40","bottom":"var:preset|spacing|40","left":"var:preset|spacing|40","right":"var:preset|spacing|40"}}}} -->
<!-- wp:form {"backgroundColor":"accent-1","textColor":"contrast","anchor":"anchor","fontSize":"x-large","style":{"elements":{"link":{"color":{"text":"var:preset|color|contrast"}}},"spacing":{"padding":{"top":"var:preset|spacing|40","bottom":"var:preset|spacing|40","left":"var:preset|spacing|40","right":"var:preset|spacing|40"},"margin":{"top":"var:preset|spacing|40","bottom":"var:preset|spacing|40","left":"var:preset|spacing|40","right":"var:preset|spacing|40"}}}} -->
<form id="anchor" class="wp-block-form has-contrast-color has-accent-1-background-color has-text-color has-background has-link-color has-x-large-font-size" style="margin-top:var(--wp--preset--spacing--40);margin-right:var(--wp--preset--spacing--40);margin-bottom:var(--wp--preset--spacing--40);margin-left:var(--wp--preset--spacing--40);padding-top:var(--wp--preset--spacing--40);padding-right:var(--wp--preset--spacing--40);padding-bottom:var(--wp--preset--spacing--40);padding-left:var(--wp--preset--spacing--40)" enctype="text/plain"></form>
<!-- /wp:form -->
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!-- wp:group {"backgroundColor":"lighter-blue","align":"full"} -->
<!-- wp:group {"backgroundColor":"lighter-blue","align":"full","anchor":"test-id"} -->
<div class="wp-block-group alignfull has-lighter-blue-background-color has-background" id="test-id"><!-- wp:paragraph -->
<p>test</p>
<!-- /wp:paragraph --></div>
Expand Down
Loading