-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
Parser: Parse superfluous classes as custom classes #7538
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import { assign } from 'lodash'; | ||
import { assign, difference, compact } from 'lodash'; | ||
import classnames from 'classnames'; | ||
|
||
/** | ||
|
@@ -11,7 +11,11 @@ import { createHigherOrderComponent, Fragment } from '@wordpress/element'; | |
import { addFilter } from '@wordpress/hooks'; | ||
import { TextControl } from '@wordpress/components'; | ||
import { __ } from '@wordpress/i18n'; | ||
import { hasBlockSupport } from '@wordpress/blocks'; | ||
import { | ||
hasBlockSupport, | ||
parseWithAttributeSchema, | ||
getSaveContent, | ||
} from '@wordpress/blocks'; | ||
|
||
/** | ||
* Internal dependencies | ||
|
@@ -93,6 +97,65 @@ export function addSaveProps( extraProps, blockType, attributes ) { | |
return extraProps; | ||
} | ||
|
||
/** | ||
* Given an HTML string, returns an array of class names assigned to the root | ||
* element in the markup. | ||
* | ||
* @param {string} innerHTML Markup string from which to extract classes. | ||
* | ||
* @return {string[]} Array of class names assigned to the root element. | ||
*/ | ||
export function getHTMLRootElementClasses( innerHTML ) { | ||
innerHTML = `<div data-custom-class-name>${ innerHTML }</div>`; | ||
|
||
const parsed = parseWithAttributeSchema( innerHTML, { | ||
type: 'string', | ||
source: 'attribute', | ||
selector: '[data-custom-class-name] > *', | ||
attribute: 'class', | ||
} ); | ||
|
||
return parsed ? parsed.trim().split( /\s+/ ) : []; | ||
} | ||
|
||
/** | ||
* Given a parsed set of block attributes, if the block supports custom class | ||
* names and an unknown class (per the block's serialization behavior) is | ||
* found, the unknown classes are treated as custom classes. This prevents the | ||
* block from being considered as invalid. | ||
* | ||
* @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 addParsedDifference( blockAttributes, blockType, innerHTML ) { | ||
if ( hasBlockSupport( blockType, 'customClassName', true ) ) { | ||
// To determine difference, serialize block given the known set of | ||
// attributes. If there are classes which are mismatched with the | ||
// incoming HTML of the block, add to filtered result. | ||
const serialized = getSaveContent( blockType, blockAttributes ); | ||
const classes = getHTMLRootElementClasses( serialized ); | ||
const parsedClasses = getHTMLRootElementClasses( innerHTML ); | ||
const customClasses = difference( parsedClasses, classes ); | ||
|
||
const filteredClassName = compact( [ | ||
blockAttributes.className, | ||
...customClasses, | ||
] ).join( ' ' ); | ||
|
||
if ( filteredClassName ) { | ||
blockAttributes.className = filteredClassName; | ||
} else { | ||
delete blockAttributes.className; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not certain why we're deleting the className attribute in this case? This creates this bug #9991. Can you clarify a bit? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh actually the filsterClassName variable have been removed at some point which is causing the bug. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
} | ||
} | ||
|
||
return blockAttributes; | ||
} | ||
|
||
addFilter( 'blocks.registerBlockType', 'core/custom-class-name/attribute', addAttribute ); | ||
addFilter( 'editor.BlockEdit', 'core/editor/custom-class-name/with-inspector-control', withInspectorControl ); | ||
addFilter( 'blocks.getSaveContent.extraProps', 'core/custom-class-name/save-props', addSaveProps ); | ||
addFilter( 'blocks.getBlockAttributes', 'core/custom-class-name/addParsedDifference', addParsedDifference ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want to document this or keep it "secret" for now :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fine to document. Will add.