diff --git a/blocks/api/index.js b/blocks/api/index.js index c4fd64bcf4c76d..7f0653a133c5b3 100644 --- a/blocks/api/index.js +++ b/blocks/api/index.js @@ -1,7 +1,12 @@ export { createBlock, getPossibleBlockTransformations, switchToBlockType, createReusableBlock } from './factory'; export { default as parse, getBlockAttributes } from './parser'; export { default as rawHandler } from './raw-handling'; -export { default as serialize, getBlockDefaultClassname, getBlockContent } from './serializer'; +export { + default as serialize, + getBlockContent, + getBlockDefaultClassname, + getSaveElement, +} from './serializer'; export { isValidBlock } from './validation'; export { getCategories } from './categories'; export { diff --git a/blocks/api/serializer.js b/blocks/api/serializer.js index 91ebc6fc0c5f27..24b903997c3fc4 100644 --- a/blocks/api/serializer.js +++ b/blocks/api/serializer.js @@ -28,24 +28,25 @@ export function getBlockDefaultClassname( blockName ) { /** * Given a block type containg a save render implementation and attributes, returns the - * static markup to be saved. + * enhanced element to be saved or string when raw HTML expected. * * @param {Object} blockType Block type * @param {Object} attributes Block attributes - * @return {string} Save content + * @return {Object|string} Save content */ -export function getSaveContent( blockType, attributes ) { +export function getSaveElement( blockType, attributes ) { const { save } = blockType; - let saveContent; + + let saveElement; if ( save.prototype instanceof Component ) { - saveContent = createElement( save, { attributes } ); + saveElement = createElement( save, { attributes } ); } else { - saveContent = save( { attributes } ); + saveElement = save( { attributes } ); // Special-case function render implementation to allow raw HTML return - if ( 'string' === typeof saveContent ) { - return saveContent; + if ( 'string' === typeof saveElement ) { + return saveElement; } } @@ -59,10 +60,28 @@ export function getSaveContent( blockType, attributes ) { return cloneElement( element, props ); }; - const contentWithExtraProps = Children.map( saveContent, addExtraContainerProps ); + + return Children.map( saveElement, addExtraContainerProps ); +} + +/** + * Given a block type containg a save render implementation and attributes, returns the + * static markup to be saved. + * + * @param {Object} blockType Block type + * @param {Object} attributes Block attributes + * @return {string} Save content + */ +export function getSaveContent( blockType, attributes ) { + const saveElement = getSaveElement( blockType, attributes ); + + // Special-case function render implementation to allow raw HTML return + if ( 'string' === typeof saveElement ) { + return saveElement; + } // Otherwise, infer as element - return renderToString( contentWithExtraProps ); + return renderToString( saveElement ); } /** diff --git a/blocks/block-edit/index.js b/blocks/block-edit/index.js index 87d89199fa014f..8d2c93d9f24d53 100644 --- a/blocks/block-edit/index.js +++ b/blocks/block-edit/index.js @@ -1,3 +1,8 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; + /** * WordPress dependencies */ @@ -6,22 +11,32 @@ import { withFilters } from '@wordpress/components'; /** * Internal dependencies */ -import { getBlockType } from '../api'; +import { + getBlockType, + getBlockDefaultClassname, + hasBlockSupport, +} from '../api'; export function BlockEdit( props ) { - const { name, ...editProps } = props; + const { name, attributes = {} } = props; const blockType = getBlockType( name ); if ( ! blockType ) { return null; } + // Generate a class name for the block's editable form + const generatedClassName = hasBlockSupport( blockType, 'className', true ) ? + getBlockDefaultClassname( name ) : + null; + const className = classnames( generatedClassName, attributes.className ); + // `edit` and `save` are functions or components describing the markup // with which a block is displayed. If `blockType` is valid, assign // them preferencially as the render value for the block. const Edit = blockType.edit || blockType.save; - return ; + return ; } export default withFilters( 'blocks.BlockEdit' )( BlockEdit ); diff --git a/blocks/block-edit/test/index.js b/blocks/block-edit/test/index.js index b02185797b43bc..47a853fa373079 100644 --- a/blocks/block-edit/test/index.js +++ b/blocks/block-edit/test/index.js @@ -53,4 +53,23 @@ describe( 'BlockEdit', () => { expect( wrapper.type() ).toBe( save ); } ); + + it( 'should combine the default class name with a custom one', () => { + const edit = ( { className } ) =>
; + const attributes = { + className: 'my-class', + }; + registerBlockType( 'core/test-block', { + edit, + save: noop, + category: 'common', + title: 'block title', + } ); + + const wrapper = shallow( + + ); + + expect( wrapper.prop( 'className' ) ).toBe( 'wp-block-test-block my-class' ); + } ); } ); diff --git a/blocks/library/block/index.js b/blocks/library/block/index.js index 6f8bb6be3ac277..0988ca56ab53b9 100644 --- a/blocks/library/block/index.js +++ b/blocks/library/block/index.js @@ -3,7 +3,6 @@ */ import { pickBy, noop } from 'lodash'; import { connect } from 'react-redux'; -import classnames from 'classnames'; /** * WordPress dependencies @@ -15,7 +14,8 @@ import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ -import { getBlockType, registerBlockType, hasBlockSupport, getBlockDefaultClassname } from '../../api'; +import BlockEdit from '../../block-edit'; +import { registerBlockType } from '../../api'; import ReusableBlockEditPanel from './edit-panel'; class ReusableBlockEdit extends Component { @@ -86,23 +86,16 @@ class ReusableBlockEdit extends Component { } const reusableBlockAttributes = { ...reusableBlock.attributes, ...attributes }; - const blockType = getBlockType( reusableBlock.type ); - const BlockEdit = blockType.edit || blockType.save; - - // Generate a class name for the block's editable form - const generatedClassName = hasBlockSupport( blockType, 'className', true ) ? - getBlockDefaultClassname( reusableBlock.type ) : - null; - const className = classnames( generatedClassName, reusableBlockAttributes.className ); + return [ // We fake the block being read-only by wrapping it with an element that has pointer-events: none
, focus && ( @@ -167,6 +160,10 @@ registerBlockType( 'core/block', { }, }, + supports: { + customClassName: false, + }, + edit: ConnectedReusableBlockEdit, save: () => null, } ); diff --git a/editor/components/block-list/block.js b/editor/components/block-list/block.js index 50fb5b47a2ae9f..3a7818d4e2feff 100644 --- a/editor/components/block-list/block.js +++ b/editor/components/block-list/block.js @@ -8,14 +8,13 @@ import { get, partial, reduce, size } from 'lodash'; /** * WordPress dependencies */ -import { Component, compose, createElement } from '@wordpress/element'; +import { Component, compose } from '@wordpress/element'; import { keycodes } from '@wordpress/utils'; import { - getBlockType, BlockEdit, - getBlockDefaultClassname, createBlock, - hasBlockSupport, + getBlockType, + getSaveElement, isReusableBlock, } from '@wordpress/blocks'; import { withFilters, withContext } from '@wordpress/components'; @@ -377,12 +376,6 @@ export class BlockListBlock extends Component { wrapperProps = blockType.getEditWrapperProps( block.attributes ); } - // Generate a class name for the block's editable form - const generatedClassName = hasBlockSupport( blockType, 'className', true ) ? - getBlockDefaultClassname( block.name ) : - null; - const className = classnames( generatedClassName, block.attributes.className ); - // Disable reason: Each block can be selected by clicking on it /* eslint-disable jsx-a11y/no-static-element-interactions, jsx-a11y/onclick-has-role, jsx-a11y/click-events-have-key-events */ return ( @@ -424,7 +417,6 @@ export class BlockListBlock extends Component { onReplace={ isLocked ? undefined : onReplace } setFocus={ partial( onFocus, block.uid ) } mergeBlocks={ isLocked ? undefined : this.mergeBlocks } - className={ className } id={ block.uid } isSelectionEnabled={ this.props.isSelectionEnabled } toggleSelection={ this.props.toggleSelection } @@ -434,11 +426,9 @@ export class BlockListBlock extends Component { ) } { ! isValid && [ - createElement( blockType.save, { - key: 'invalid-preview', - attributes: block.attributes, - className, - } ), +
+ { getSaveElement( blockType, block.attributes ) } +
,