Skip to content

Commit

Permalink
Merge pull request #4009 from WordPress/update/generated-class-name-e…
Browse files Browse the repository at this point in the history
…dit-block

Blocks: Move logic for generating class name to BlockEdit component
  • Loading branch information
gziolo authored Dec 18, 2017
2 parents 5c33f6f + 3650811 commit 227a93f
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 41 deletions.
7 changes: 6 additions & 1 deletion blocks/api/index.js
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down
39 changes: 29 additions & 10 deletions blocks/api/serializer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

Expand All @@ -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 );
}

/**
Expand Down
21 changes: 18 additions & 3 deletions blocks/block-edit/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
/**
* External dependencies
*/
import classnames from 'classnames';

/**
* WordPress dependencies
*/
Expand All @@ -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 <Edit { ...editProps } />;
return <Edit { ...props } className={ className } />;
}

export default withFilters( 'blocks.BlockEdit' )( BlockEdit );
19 changes: 19 additions & 0 deletions blocks/block-edit/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 } ) => <div className={ className } />;
const attributes = {
className: 'my-class',
};
registerBlockType( 'core/test-block', {
edit,
save: noop,
category: 'common',
title: 'block title',
} );

const wrapper = shallow(
<BlockEdit name="core/test-block" attributes={ attributes } />
);

expect( wrapper.prop( 'className' ) ).toBe( 'wp-block-test-block my-class' );
} );
} );
19 changes: 8 additions & 11 deletions blocks/library/block/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
*/
import { pickBy, noop } from 'lodash';
import { connect } from 'react-redux';
import classnames from 'classnames';

/**
* WordPress dependencies
Expand All @@ -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 {
Expand Down Expand Up @@ -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
<div key="edit" style={ { pointerEvents: isEditing ? 'auto' : 'none' } }>
<BlockEdit
{ ...this.props }
name={ reusableBlock.type }
focus={ isEditing ? focus : null }
attributes={ reusableBlockAttributes }
setAttributes={ isEditing ? this.setAttributes : noop }
className={ className }
/>
</div>,
focus && (
Expand Down Expand Up @@ -167,6 +160,10 @@ registerBlockType( 'core/block', {
},
},

supports: {
customClassName: false,
},

edit: ConnectedReusableBlockEdit,
save: () => null,
} );
22 changes: 6 additions & 16 deletions editor/components/block-list/block.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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 (
Expand Down Expand Up @@ -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 }
Expand All @@ -434,11 +426,9 @@ export class BlockListBlock extends Component {
<BlockHtml uid={ block.uid } />
) }
{ ! isValid && [
createElement( blockType.save, {
key: 'invalid-preview',
attributes: block.attributes,
className,
} ),
<div key="invalid-preview">
{ getSaveElement( blockType, block.attributes ) }
</div>,
<InvalidBlockWarning
key="invalid-warning"
block={ block }
Expand Down

0 comments on commit 227a93f

Please sign in to comment.