From bf62d31b0425dd4b4a316df6c536cfb2317261e9 Mon Sep 17 00:00:00 2001 From: Grzegorz Ziolkowski Date: Fri, 1 Dec 2017 13:16:26 +0100 Subject: [PATCH 1/8] Component: Update withFilter HOC to support more advanced use cases --- components/higher-order/with-filters/index.js | 4 +++- .../higher-order/with-filters/test/index.js | 22 +++++++++++-------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/components/higher-order/with-filters/index.js b/components/higher-order/with-filters/index.js index b753e23d6517ad..28817352cbcdb5 100644 --- a/components/higher-order/with-filters/index.js +++ b/components/higher-order/with-filters/index.js @@ -13,7 +13,9 @@ import { applyFilters } from '@wordpress/hooks'; export default function withFilters( hookName ) { return ( WrappedComponent ) => { const FiltersComponent = ( props ) => { - return applyFilters( hookName, , props ); + const EnhancedComponent = applyFilters( hookName, WrappedComponent, props ); + + return ; }; FiltersComponent.displayName = getWrapperDisplayName( WrappedComponent, 'filters' ); diff --git a/components/higher-order/with-filters/test/index.js b/components/higher-order/with-filters/test/index.js index edeaf48a72101b..8795efade9661a 100644 --- a/components/higher-order/with-filters/test/index.js +++ b/components/higher-order/with-filters/test/index.js @@ -1,12 +1,11 @@ /** * External dependencies */ -import { mount, shallow } from 'enzyme'; +import { shallow } from 'enzyme'; /** * WordPress dependencies */ -import { concatChildren } from '@wordpress/element'; import { addFilter, removeAllFilters } from '@wordpress/hooks'; /** @@ -30,10 +29,11 @@ describe( 'withFilters', () => { } ); it( 'should display a component overridden by the filter', () => { + const OverriddenComponent = () =>
Overridden component
; addFilter( 'EnhancedComponent', - 'test\enhanced-component-override', - () =>
Overridden component
+ 'test/enhanced-component-override', + () => OverriddenComponent ); const wrapper = shallow( ); @@ -45,13 +45,17 @@ describe( 'withFilters', () => { const ComposedComponent = () =>
Composed component
; addFilter( hookName, - 'test\enhanced-component-compose', - ( element ) => concatChildren( element, ) + 'test/enhanced-component-compose', + ( FilteredComponent ) => () => ( +
+ + +
+ ) ); - const wrapper = mount( ); + const wrapper = shallow( ); - expect( wrapper.find( MyComponent ) ).toBePresent(); - expect( wrapper.find( ComposedComponent ) ).toBePresent(); + expect( wrapper.html() ).toBe( '
My component
Composed component
' ); } ); } ); From befeb759f5e6f5c67b4818f55ff941494237cd81 Mon Sep 17 00:00:00 2001 From: Grzegorz Ziolkowski Date: Fri, 1 Dec 2017 17:28:09 +0100 Subject: [PATCH 2/8] Element: Update logic for getWrapperDisplayName method --- element/index.js | 4 ++-- element/test/index.js | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/element/index.js b/element/index.js index 87a964fd1313b3..a1564b63e19db3 100644 --- a/element/index.js +++ b/element/index.js @@ -4,7 +4,7 @@ import { createElement, Component, cloneElement, Children } from 'react'; import { render, findDOMNode, createPortal, unmountComponentAtNode } from 'react-dom'; import { renderToStaticMarkup } from 'react-dom/server'; -import { flowRight, isString, startCase } from 'lodash'; +import { camelCase, flowRight, isString, upperFirst } from 'lodash'; /** * Returns a new element of given type. Type can be either a string tag name or @@ -135,5 +135,5 @@ export { flowRight as compose }; export function getWrapperDisplayName( BaseComponent, wrapperName ) { const { displayName = BaseComponent.name || 'Component' } = BaseComponent; - return `${ startCase( wrapperName ) }(${ displayName })`; + return `${ upperFirst( camelCase( wrapperName ) ) }(${ displayName })`; } diff --git a/element/test/index.js b/element/test/index.js index 82a5da22c5d409..f96cf9b8782378 100644 --- a/element/test/index.js +++ b/element/test/index.js @@ -99,6 +99,10 @@ describe( 'element', () => { expect( getWrapperDisplayName( () =>
, 'test' ) ).toBe( 'Test(Component)' ); } ); + it( 'should use camel case starting with upper for wrapper prefix ', () => { + expect( getWrapperDisplayName( () =>
, 'one-two_threeFOUR' ) ).toBe( 'OneTwoThreeFour(Component)' ); + } ); + it( 'should use function name', () => { function SomeComponent() { return
; From d564276d29b1291f951ee960d634e2346bc37179 Mon Sep 17 00:00:00 2001 From: Grzegorz Ziolkowski Date: Tue, 5 Dec 2017 12:32:17 +0100 Subject: [PATCH 3/8] Hooks: Update all namespaces to use slashes --- blocks/hooks/anchor.js | 6 +++--- blocks/hooks/custom-class-name.js | 6 +++--- blocks/hooks/generated-class-name.js | 2 +- blocks/hooks/matchers.js | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/blocks/hooks/anchor.js b/blocks/hooks/anchor.js index dafa84d2b6059a..3f8ebdb57c631c 100644 --- a/blocks/hooks/anchor.js +++ b/blocks/hooks/anchor.js @@ -94,7 +94,7 @@ export function addSaveProps( extraProps, blockType, attributes ) { } export default function anchor( { addFilter } ) { - addFilter( 'registerBlockType', 'core-anchor-attribute', addAttribute ); - addFilter( 'BlockEdit', 'core-anchor-inspector-control', addInspectorControl ); - addFilter( 'getSaveContent.extraProps', 'core-anchor-save-props', addSaveProps ); + addFilter( 'registerBlockType', 'core/anchor/attribute', addAttribute ); + addFilter( 'BlockEdit', 'core/anchor/inspector-control', addInspectorControl ); + addFilter( 'getSaveContent.extraProps', 'core/anchor/save-props', addSaveProps ); } diff --git a/blocks/hooks/custom-class-name.js b/blocks/hooks/custom-class-name.js index 4e0dec0aea773e..9191c9b446935e 100644 --- a/blocks/hooks/custom-class-name.js +++ b/blocks/hooks/custom-class-name.js @@ -83,7 +83,7 @@ export function addSaveProps( extraProps, blockType, attributes ) { } export default function customClassName( { addFilter } ) { - addFilter( 'registerBlockType', 'core-custom-class-name-attribute', addAttribute ); - addFilter( 'BlockEdit', 'core-custom-class-name-inspector-control', addInspectorControl ); - addFilter( 'getSaveContent.extraProps', 'core-custom-class-name-save-props', addSaveProps ); + addFilter( 'registerBlockType', 'core/custom-class-name/attribute', addAttribute ); + addFilter( 'BlockEdit', 'core/custom-class-name/inspector-control', addInspectorControl ); + addFilter( 'getSaveContent.extraProps', 'core/custom-class-name/save-props', addSaveProps ); } diff --git a/blocks/hooks/generated-class-name.js b/blocks/hooks/generated-class-name.js index dfab31bce7a969..66c08d1e788033 100644 --- a/blocks/hooks/generated-class-name.js +++ b/blocks/hooks/generated-class-name.js @@ -31,5 +31,5 @@ export function addGeneratedClassName( extraProps, blockType ) { } export default function generatedClassName( { addFilter } ) { - addFilter( 'getSaveContent.extraProps', 'core-generated-class-name-save-props', addGeneratedClassName ); + addFilter( 'getSaveContent.extraProps', 'core/generated-class-name/save-props', addGeneratedClassName ); } diff --git a/blocks/hooks/matchers.js b/blocks/hooks/matchers.js index a8890cd7e6226c..ef3f19859584cb 100644 --- a/blocks/hooks/matchers.js +++ b/blocks/hooks/matchers.js @@ -92,5 +92,5 @@ export function resolveAttributes( settings ) { } export default function matchers( { addFilter } ) { - addFilter( 'registerBlockType', 'core-matchers', resolveAttributes ); + addFilter( 'registerBlockType', 'core/matchers', resolveAttributes ); } From 81d56ad5743e3ed2ce2c419b6ee471d5c869057f Mon Sep 17 00:00:00 2001 From: Grzegorz Ziolkowski Date: Wed, 6 Dec 2017 09:28:26 +0100 Subject: [PATCH 4/8] Hooks: Convert all filters for components to behave like HOCs --- blocks/api/registration.js | 6 +++- blocks/api/serializer.js | 2 +- blocks/block-edit/index.js | 10 +++++-- blocks/hooks/anchor.js | 28 +++++++++++-------- blocks/hooks/custom-class-name.js | 27 ++++++++++-------- blocks/hooks/index.js | 24 +--------------- components/higher-order/with-filters/index.js | 12 ++------ .../higher-order/with-filters/test/index.js | 4 ++- docs/extensibility.md | 8 +++--- element/index.js | 2 +- 10 files changed, 56 insertions(+), 67 deletions(-) diff --git a/blocks/api/registration.js b/blocks/api/registration.js index c123a7ea4de1d9..34e26f54fab302 100644 --- a/blocks/api/registration.js +++ b/blocks/api/registration.js @@ -5,10 +5,14 @@ */ import { get, isFunction, some } from 'lodash'; +/** + * WordPress dependencies + */ +import { applyFilters } from '@wordpress/hooks'; + /** * Internal dependencies */ -import { applyFilters } from '../hooks'; import { getCategories } from './categories'; /** diff --git a/blocks/api/serializer.js b/blocks/api/serializer.js index cff0fac73a69ef..2f9288a88cb5cd 100644 --- a/blocks/api/serializer.js +++ b/blocks/api/serializer.js @@ -8,11 +8,11 @@ import { html as beautifyHtml } from 'js-beautify'; * WordPress dependencies */ import { Component, createElement, renderToString, cloneElement, Children } from '@wordpress/element'; +import { applyFilters } from '@wordpress/hooks'; /** * Internal dependencies */ -import { applyFilters } from '../hooks'; import { getBlockType, getUnknownTypeHandlerName } from './registration'; /** diff --git a/blocks/block-edit/index.js b/blocks/block-edit/index.js index 7ecedbabc8b433..dc25eb7bee067d 100644 --- a/blocks/block-edit/index.js +++ b/blocks/block-edit/index.js @@ -1,7 +1,11 @@ +/** + * WordPress dependencies + */ +import { withFilters } from '@wordpress/components'; + /** * Internal dependencies */ -import { applyFilters } from '../hooks'; import { getBlockType } from '../api'; function BlockEdit( props ) { @@ -17,7 +21,7 @@ function BlockEdit( props ) { // them preferencially as the render value for the block. const Edit = blockType.edit || blockType.save; - return applyFilters( 'BlockEdit', , props ); + return ; } -export default BlockEdit; +export default withFilters( 'BlockEdit' )( BlockEdit ); diff --git a/blocks/hooks/anchor.js b/blocks/hooks/anchor.js index 3f8ebdb57c631c..a2e91e80bc1159 100644 --- a/blocks/hooks/anchor.js +++ b/blocks/hooks/anchor.js @@ -6,6 +6,7 @@ import { assign } from 'lodash'; /** * WordPress dependencies */ +import { getWrapperDisplayName } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; /** @@ -46,16 +47,19 @@ export function addAttribute( settings ) { /** * Override the default edit UI to include a new block inspector control for - * assigning the anchor ID, if block supports anchor + * assigning the anchor ID, if block supports anchor. * - * @param {Element} element Original edit element - * @param {Object} props Props passed to BlockEdit - * @return {Element} Filtered edit element + * @param {function|Component} BlockEdit Original component + * @return {function} Wrapped component */ -export function addInspectorControl( element, props ) { - if ( hasBlockSupport( props.name, 'anchor' ) && props.focus ) { - element = [ - element, +export function withInspectorControl( BlockEdit ) { + const WrappedBlockEdit = ( props ) => { + if ( ! hasBlockSupport( props.name, 'anchor' ) || ! props.focus ) { + return ; + } + + return [ + , { nextValue = nextValue.replace( ANCHOR_REGEX, '-' ); - props.setAttributes( { anchor: nextValue, } ); } } /> , ]; - } + }; + WrappedBlockEdit.displayName = getWrapperDisplayName( BlockEdit, 'anchor' ); - return element; + return WrappedBlockEdit; } /** @@ -95,6 +99,6 @@ export function addSaveProps( extraProps, blockType, attributes ) { export default function anchor( { addFilter } ) { addFilter( 'registerBlockType', 'core/anchor/attribute', addAttribute ); - addFilter( 'BlockEdit', 'core/anchor/inspector-control', addInspectorControl ); + addFilter( 'BlockEdit', 'core/anchor/inspector-control', withInspectorControl ); addFilter( 'getSaveContent.extraProps', 'core/anchor/save-props', addSaveProps ); } diff --git a/blocks/hooks/custom-class-name.js b/blocks/hooks/custom-class-name.js index 9191c9b446935e..19bb0cefbd1c4c 100644 --- a/blocks/hooks/custom-class-name.js +++ b/blocks/hooks/custom-class-name.js @@ -7,6 +7,7 @@ import classnames from 'classnames'; /** * WordPress dependencies */ +import { getWrapperDisplayName } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; /** @@ -37,16 +38,19 @@ export function addAttribute( settings ) { /** * Override the default edit UI to include a new block inspector control for - * assigning the anchor ID, if block supports anchor + * assigning the custom class name, if block supports custom class name. * - * @param {Element} element Original edit element - * @param {Object} props Props passed to BlockEdit - * @return {Element} Filtered edit element + * @param {function|Component} BlockEdit Original component + * @return {function} Wrapped component */ -export function addInspectorControl( element, props ) { - if ( hasBlockSupport( props.name, 'customClassName', true ) && props.focus ) { - element = [ - element, +export function withInspectorControl( BlockEdit ) { + const WrappedBlockEdit = ( props ) => { + if ( ! hasBlockSupport( props.name, 'customClassName', true ) || ! props.focus ) { + return ; + } + + return [ + , , ]; - } + }; + WrappedBlockEdit.displayName = getWrapperDisplayName( BlockEdit, 'customClassName' ); - return element; + return WrappedBlockEdit; } /** @@ -84,6 +89,6 @@ export function addSaveProps( extraProps, blockType, attributes ) { export default function customClassName( { addFilter } ) { addFilter( 'registerBlockType', 'core/custom-class-name/attribute', addAttribute ); - addFilter( 'BlockEdit', 'core/custom-class-name/inspector-control', addInspectorControl ); + addFilter( 'BlockEdit', 'core/custom-class-name/inspector-control', withInspectorControl ); addFilter( 'getSaveContent.extraProps', 'core/custom-class-name/save-props', addSaveProps ); } diff --git a/blocks/hooks/index.js b/blocks/hooks/index.js index 0c7da0e97c4675..3d5a8306a18643 100644 --- a/blocks/hooks/index.js +++ b/blocks/hooks/index.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { createHooks } from '@wordpress/hooks'; +import * as hooks from '@wordpress/hooks'; /** * Internal dependencies @@ -11,28 +11,6 @@ import customClassName from './custom-class-name'; import generatedClassName from './generated-class-name'; import matchers from './matchers'; -const hooks = createHooks(); - -const { - addFilter, - removeFilter, - removeAllFilters, - applyFilters, - doingFilter, - didFilter, - hasFilter, -} = hooks; - -export { - addFilter, - removeFilter, - removeAllFilters, - applyFilters, - doingFilter, - didFilter, - hasFilter, -}; - anchor( hooks ); customClassName( hooks ); generatedClassName( hooks ); diff --git a/components/higher-order/with-filters/index.js b/components/higher-order/with-filters/index.js index 28817352cbcdb5..b345596efb9982 100644 --- a/components/higher-order/with-filters/index.js +++ b/components/higher-order/with-filters/index.js @@ -1,7 +1,6 @@ /** * WordPress dependencies */ -import { getWrapperDisplayName } from '@wordpress/element'; import { applyFilters } from '@wordpress/hooks'; /** @@ -11,14 +10,7 @@ import { applyFilters } from '@wordpress/hooks'; * @return {Function} Higher-order component factory. */ export default function withFilters( hookName ) { - return ( WrappedComponent ) => { - const FiltersComponent = ( props ) => { - const EnhancedComponent = applyFilters( hookName, WrappedComponent, props ); - - return ; - }; - FiltersComponent.displayName = getWrapperDisplayName( WrappedComponent, 'filters' ); - - return FiltersComponent; + return ( OriginalComponent ) => { + return applyFilters( hookName, OriginalComponent ); }; } diff --git a/components/higher-order/with-filters/test/index.js b/components/higher-order/with-filters/test/index.js index 8795efade9661a..c7931c43d593f9 100644 --- a/components/higher-order/with-filters/test/index.js +++ b/components/higher-order/with-filters/test/index.js @@ -16,13 +16,13 @@ import withFilters from '../'; describe( 'withFilters', () => { const hookName = 'EnhancedComponent'; const MyComponent = () =>
My component
; - const EnhancedComponent = withFilters( hookName )( MyComponent ); afterEach( () => { removeAllFilters( hookName ); } ); it( 'should display original component when no filters applied', () => { + const EnhancedComponent = withFilters( hookName )( MyComponent ); const wrapper = shallow( ); expect( wrapper.html() ).toBe( '
My component
' ); @@ -35,6 +35,7 @@ describe( 'withFilters', () => { 'test/enhanced-component-override', () => OverriddenComponent ); + const EnhancedComponent = withFilters( hookName )( MyComponent ); const wrapper = shallow( ); @@ -53,6 +54,7 @@ describe( 'withFilters', () => {
) ); + const EnhancedComponent = withFilters( hookName )( MyComponent ); const wrapper = shallow( ); diff --git a/docs/extensibility.md b/docs/extensibility.md index a677cbc003c6fa..15e3d167988171 100644 --- a/docs/extensibility.md +++ b/docs/extensibility.md @@ -96,7 +96,7 @@ To modify the behaviour of existing blocks, Gutenberg exposes a list of filters: - `getSaveContent.extraProps`: A filter that applies to all blocks returning a WP Element in the `save` function. This filter is used to add extra props to the root element of the `save` function. For example: to add a className, an id, or any valid prop for this element. It receives the current props of the `save` element, the block Type and the block attributes as arguments. -- `BlockEdit`: Used to filter the block's `edit` function receiving the WP element returned from the original block `edit` element. +- `BlockEdit`: Used to modify the block's `edit` component. It receives the original block `edit` component and returns a new wrapped component. **Example** @@ -109,9 +109,9 @@ function addBackgroundProp( props ) { } // Adding the filter -wp.blocks.addFilter( +wp.hooks.addFilter( 'getSaveContent.extraProps', - 'myplugin\add-background', + 'myplugin/add-background', addBackgroundProp ); ``` @@ -119,4 +119,4 @@ wp.blocks.addFilter( ## Extending the editor's UI (Slot and Fill) -Coming soon. \ No newline at end of file +Coming soon. diff --git a/element/index.js b/element/index.js index a1564b63e19db3..0094a8392ff74b 100644 --- a/element/index.js +++ b/element/index.js @@ -126,7 +126,7 @@ export { flowRight as compose }; /** * Returns a wrapped version of a React component's display name. - * Higher-order components use wrapDisplayName(). + * Higher-order components use getWrapperDisplayName(). * * @param {Function|Component} BaseComponent used to detect the existing display name. * @param {String} wrapperName Wrapper name to prepend to the display name. From eedd1addfe00ba208ac97117070092c8b24f03ae Mon Sep 17 00:00:00 2001 From: Grzegorz Ziolkowski Date: Wed, 6 Dec 2017 10:13:37 +0100 Subject: [PATCH 5/8] Hooks: Prefix all hook names with blocks --- blocks/api/registration.js | 2 +- blocks/api/serializer.js | 2 +- blocks/block-edit/index.js | 2 +- blocks/hooks/anchor.js | 9 +++++---- blocks/hooks/custom-class-name.js | 9 +++++---- blocks/hooks/generated-class-name.js | 9 +++++++-- blocks/hooks/index.js | 13 ++++--------- blocks/hooks/matchers.js | 9 +++++++-- blocks/hooks/test/anchor.js | 14 ++++++-------- blocks/hooks/test/custom-class-name.js | 14 ++++++-------- blocks/hooks/test/geenerated-class-name.js | 10 ++++------ docs/extensibility.md | 8 ++++---- 12 files changed, 51 insertions(+), 50 deletions(-) diff --git a/blocks/api/registration.js b/blocks/api/registration.js index 34e26f54fab302..9b99cfc2f7e3d5 100644 --- a/blocks/api/registration.js +++ b/blocks/api/registration.js @@ -119,7 +119,7 @@ export function registerBlockType( name, settings ) { ...settings, }; - settings = applyFilters( 'registerBlockType', settings, name ); + settings = applyFilters( 'blocks.registerBlockType', settings, name ); return blocks[ name ] = settings; } diff --git a/blocks/api/serializer.js b/blocks/api/serializer.js index 2f9288a88cb5cd..91ebc6fc0c5f27 100644 --- a/blocks/api/serializer.js +++ b/blocks/api/serializer.js @@ -55,7 +55,7 @@ export function getSaveContent( blockType, attributes ) { } // Applying the filters adding extra props - const props = applyFilters( 'getSaveContent.extraProps', { ...element.props }, blockType, attributes ); + const props = applyFilters( 'blocks.getSaveContent.extraProps', { ...element.props }, blockType, attributes ); return cloneElement( element, props ); }; diff --git a/blocks/block-edit/index.js b/blocks/block-edit/index.js index dc25eb7bee067d..c8bcdeccb8fed4 100644 --- a/blocks/block-edit/index.js +++ b/blocks/block-edit/index.js @@ -24,4 +24,4 @@ function BlockEdit( props ) { return ; } -export default withFilters( 'BlockEdit' )( BlockEdit ); +export default withFilters( 'blocks.BlockEdit' )( BlockEdit ); diff --git a/blocks/hooks/anchor.js b/blocks/hooks/anchor.js index a2e91e80bc1159..8ab77f60459c53 100644 --- a/blocks/hooks/anchor.js +++ b/blocks/hooks/anchor.js @@ -7,6 +7,7 @@ import { assign } from 'lodash'; * WordPress dependencies */ import { getWrapperDisplayName } from '@wordpress/element'; +import { addFilter } from '@wordpress/hooks'; import { __ } from '@wordpress/i18n'; /** @@ -97,8 +98,8 @@ export function addSaveProps( extraProps, blockType, attributes ) { return extraProps; } -export default function anchor( { addFilter } ) { - addFilter( 'registerBlockType', 'core/anchor/attribute', addAttribute ); - addFilter( 'BlockEdit', 'core/anchor/inspector-control', withInspectorControl ); - addFilter( 'getSaveContent.extraProps', 'core/anchor/save-props', addSaveProps ); +export default function anchor() { + addFilter( 'blocks.registerBlockType', 'core/anchor/attribute', addAttribute ); + addFilter( 'blocks.BlockEdit', 'core/anchor/inspector-control', withInspectorControl ); + addFilter( 'blocks.getSaveContent.extraProps', 'core/anchor/save-props', addSaveProps ); } diff --git a/blocks/hooks/custom-class-name.js b/blocks/hooks/custom-class-name.js index 19bb0cefbd1c4c..eb63bf28785d72 100644 --- a/blocks/hooks/custom-class-name.js +++ b/blocks/hooks/custom-class-name.js @@ -8,6 +8,7 @@ import classnames from 'classnames'; * WordPress dependencies */ import { getWrapperDisplayName } from '@wordpress/element'; +import { addFilter } from '@wordpress/hooks'; import { __ } from '@wordpress/i18n'; /** @@ -87,8 +88,8 @@ export function addSaveProps( extraProps, blockType, attributes ) { return extraProps; } -export default function customClassName( { addFilter } ) { - addFilter( 'registerBlockType', 'core/custom-class-name/attribute', addAttribute ); - addFilter( 'BlockEdit', 'core/custom-class-name/inspector-control', withInspectorControl ); - addFilter( 'getSaveContent.extraProps', 'core/custom-class-name/save-props', addSaveProps ); +export default function customClassName() { + addFilter( 'blocks.registerBlockType', 'core/custom-class-name/attribute', addAttribute ); + addFilter( 'blocks.BlockEdit', 'core/custom-class-name/inspector-control', withInspectorControl ); + addFilter( 'blocks.getSaveContent.extraProps', 'core/custom-class-name/save-props', addSaveProps ); } diff --git a/blocks/hooks/generated-class-name.js b/blocks/hooks/generated-class-name.js index 66c08d1e788033..4d5b4fde73801c 100644 --- a/blocks/hooks/generated-class-name.js +++ b/blocks/hooks/generated-class-name.js @@ -3,6 +3,11 @@ */ import classnames from 'classnames'; +/** + * WordPress dependencies + */ +import { addFilter } from '@wordpress/hooks'; + /** * Internal dependencies */ @@ -30,6 +35,6 @@ export function addGeneratedClassName( extraProps, blockType ) { return extraProps; } -export default function generatedClassName( { addFilter } ) { - addFilter( 'getSaveContent.extraProps', 'core/generated-class-name/save-props', addGeneratedClassName ); +export default function generatedClassName() { + addFilter( 'blocks.getSaveContent.extraProps', 'core/generated-class-name/save-props', addGeneratedClassName ); } diff --git a/blocks/hooks/index.js b/blocks/hooks/index.js index 3d5a8306a18643..9a2df3438b30a3 100644 --- a/blocks/hooks/index.js +++ b/blocks/hooks/index.js @@ -1,8 +1,3 @@ -/** - * WordPress dependencies - */ -import * as hooks from '@wordpress/hooks'; - /** * Internal dependencies */ @@ -11,7 +6,7 @@ import customClassName from './custom-class-name'; import generatedClassName from './generated-class-name'; import matchers from './matchers'; -anchor( hooks ); -customClassName( hooks ); -generatedClassName( hooks ); -matchers( hooks ); +anchor(); +customClassName(); +generatedClassName(); +matchers(); diff --git a/blocks/hooks/matchers.js b/blocks/hooks/matchers.js index ef3f19859584cb..84efa94f07d87f 100644 --- a/blocks/hooks/matchers.js +++ b/blocks/hooks/matchers.js @@ -3,6 +3,11 @@ */ import { isFunction, mapValues } from 'lodash'; +/** + * WordPress dependecies + */ +import { addFilter } from '@wordpress/hooks'; + function warnAboutDeprecatedMatcher() { // eslint-disable-next-line no-console console.warn( @@ -91,6 +96,6 @@ export function resolveAttributes( settings ) { return settings; } -export default function matchers( { addFilter } ) { - addFilter( 'registerBlockType', 'core/matchers', resolveAttributes ); +export default function matchers() { + addFilter( 'blocks.registerBlockType', 'core/matchers', resolveAttributes ); } diff --git a/blocks/hooks/test/anchor.js b/blocks/hooks/test/anchor.js index 78c32777e548de..58e75622d4054a 100644 --- a/blocks/hooks/test/anchor.js +++ b/blocks/hooks/test/anchor.js @@ -6,7 +6,7 @@ import { noop } from 'lodash'; /** * WordPress dependencies */ -import { createHooks } from '@wordpress/hooks'; +import { applyFilters, removeAllFilters } from '@wordpress/hooks'; /** * Internal dependencies @@ -14,11 +14,9 @@ import { createHooks } from '@wordpress/hooks'; import anchor from '../anchor'; describe( 'anchor', () => { - const hooks = createHooks(); - let blockSettings; beforeEach( () => { - anchor( hooks ); + anchor(); blockSettings = { save: noop, @@ -28,12 +26,12 @@ describe( 'anchor', () => { } ); afterEach( () => { - hooks.removeAllFilters( 'registerBlockType' ); - hooks.removeAllFilters( 'getSaveContent.extraProps' ); + removeAllFilters( 'blocks.registerBlockType' ); + removeAllFilters( 'blocks.getSaveContent.extraProps' ); } ); describe( 'addAttribute()', () => { - const addAttribute = hooks.applyFilters.bind( null, 'registerBlockType' ); + const addAttribute = applyFilters.bind( null, 'blocks.registerBlockType' ); it( 'should do nothing if the block settings do not define anchor support', () => { const settings = addAttribute( blockSettings ); @@ -54,7 +52,7 @@ describe( 'anchor', () => { } ); describe( 'addSaveProps', () => { - const addSaveProps = hooks.applyFilters.bind( null, 'getSaveContent.extraProps' ); + const addSaveProps = applyFilters.bind( null, 'blocks.getSaveContent.extraProps' ); it( 'should do nothing if the block settings do not define anchor support', () => { const attributes = { anchor: 'foo' }; diff --git a/blocks/hooks/test/custom-class-name.js b/blocks/hooks/test/custom-class-name.js index b297da8205bd8f..92692e2bb81cd7 100644 --- a/blocks/hooks/test/custom-class-name.js +++ b/blocks/hooks/test/custom-class-name.js @@ -6,7 +6,7 @@ import { noop } from 'lodash'; /** * WordPress dependencies */ -import { createHooks } from '@wordpress/hooks'; +import { applyFilters, removeAllFilters } from '@wordpress/hooks'; /** * Internal dependencies @@ -14,11 +14,9 @@ import { createHooks } from '@wordpress/hooks'; import customClassName from '../custom-class-name'; describe( 'custom className', () => { - const hooks = createHooks(); - let blockSettings; beforeEach( () => { - customClassName( hooks ); + customClassName(); blockSettings = { save: noop, @@ -28,12 +26,12 @@ describe( 'custom className', () => { } ); afterEach( () => { - hooks.removeAllFilters( 'registerBlockType' ); - hooks.removeAllFilters( 'getSaveContent.extraProps' ); + removeAllFilters( 'blocks.registerBlockType' ); + removeAllFilters( 'blocks.getSaveContent.extraProps' ); } ); describe( 'addAttribute()', () => { - const addAttribute = hooks.applyFilters.bind( null, 'registerBlockType' ); + const addAttribute = applyFilters.bind( null, 'blocks.registerBlockType' ); it( 'should do nothing if the block settings disable custom className support', () => { const settings = addAttribute( { @@ -54,7 +52,7 @@ describe( 'custom className', () => { } ); describe( 'addSaveProps', () => { - const addSaveProps = hooks.applyFilters.bind( null, 'getSaveContent.extraProps' ); + const addSaveProps = applyFilters.bind( null, 'blocks.getSaveContent.extraProps' ); it( 'should do nothing if the block settings do not define custom className support', () => { const attributes = { className: 'foo' }; diff --git a/blocks/hooks/test/geenerated-class-name.js b/blocks/hooks/test/geenerated-class-name.js index 5749e75bfc760a..2590f402618a91 100644 --- a/blocks/hooks/test/geenerated-class-name.js +++ b/blocks/hooks/test/geenerated-class-name.js @@ -6,7 +6,7 @@ import { noop } from 'lodash'; /** * External dependencies */ -import { createHooks } from '@wordpress/hooks'; +import { applyFilters, removeAllFilters } from '@wordpress/hooks'; /** * Internal dependencies @@ -14,11 +14,9 @@ import { createHooks } from '@wordpress/hooks'; import generatedClassName from '../generated-class-name'; describe( 'generated className', () => { - const hooks = createHooks(); - let blockSettings; beforeEach( () => { - generatedClassName( hooks ); + generatedClassName(); blockSettings = { name: 'chicken/ribs', @@ -29,11 +27,11 @@ describe( 'generated className', () => { } ); afterEach( () => { - hooks.removeAllFilters( 'getSaveContent.extraProps' ); + removeAllFilters( 'blocks.getSaveContent.extraProps' ); } ); describe( 'addSaveProps', () => { - const addSaveProps = hooks.applyFilters.bind( null, 'getSaveContent.extraProps' ); + const addSaveProps = applyFilters.bind( null, 'blocks.getSaveContent.extraProps' ); it( 'should do nothing if the block settings do not define generated className support', () => { const attributes = { className: 'foo' }; diff --git a/docs/extensibility.md b/docs/extensibility.md index 15e3d167988171..fcfe731f43e0c2 100644 --- a/docs/extensibility.md +++ b/docs/extensibility.md @@ -92,11 +92,11 @@ add_filter( 'allowed_block_types', function() { To modify the behaviour of existing blocks, Gutenberg exposes a list of filters: -- `registerBlockType`: Used to filter the block settings. It receives the block settings and the name of the block the registered block as arguments. +- `blocks.registerBlockType`: Used to filter the block settings. It receives the block settings and the name of the block the registered block as arguments. -- `getSaveContent.extraProps`: A filter that applies to all blocks returning a WP Element in the `save` function. This filter is used to add extra props to the root element of the `save` function. For example: to add a className, an id, or any valid prop for this element. It receives the current props of the `save` element, the block Type and the block attributes as arguments. +- `blocks.getSaveContent.extraProps`: A filter that applies to all blocks returning a WP Element in the `save` function. This filter is used to add extra props to the root element of the `save` function. For example: to add a className, an id, or any valid prop for this element. It receives the current props of the `save` element, the block Type and the block attributes as arguments. -- `BlockEdit`: Used to modify the block's `edit` component. It receives the original block `edit` component and returns a new wrapped component. +- `blocks.BlockEdit`: Used to modify the block's `edit` component. It receives the original block `edit` component and returns a new wrapped component. **Example** @@ -110,7 +110,7 @@ function addBackgroundProp( props ) { // Adding the filter wp.hooks.addFilter( - 'getSaveContent.extraProps', + 'blocks.getSaveContent.extraProps', 'myplugin/add-background', addBackgroundProp ); From 0ffd9ef96aafdbe32823096c05ba0a4e670d7752 Mon Sep 17 00:00:00 2001 From: Grzegorz Ziolkowski Date: Wed, 6 Dec 2017 11:44:57 +0100 Subject: [PATCH 6/8] Hooks: Fix rerender issue with block component hooks --- blocks/hooks/anchor.js | 8 +++----- blocks/hooks/custom-class-name.js | 8 +++----- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/blocks/hooks/anchor.js b/blocks/hooks/anchor.js index 8ab77f60459c53..3b740b650c7875 100644 --- a/blocks/hooks/anchor.js +++ b/blocks/hooks/anchor.js @@ -55,13 +55,11 @@ export function addAttribute( settings ) { */ export function withInspectorControl( BlockEdit ) { const WrappedBlockEdit = ( props ) => { - if ( ! hasBlockSupport( props.name, 'anchor' ) || ! props.focus ) { - return ; - } + const hasAnchor = hasBlockSupport( props.name, 'anchor' ) && props.focus; return [ - , - + , + hasAnchor && { - if ( ! hasBlockSupport( props.name, 'customClassName', true ) || ! props.focus ) { - return ; - } + const hasCustomClassName = hasBlockSupport( props.name, 'customClassName', true ) && props.focus; return [ - , - + , + hasCustomClassName && Date: Fri, 8 Dec 2017 12:22:14 +0100 Subject: [PATCH 7/8] Editor: Update hooks integration for BlockListBlock component --- editor/components/block-list/block.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editor/components/block-list/block.js b/editor/components/block-list/block.js index 429a79440c563f..810baff94f969a 100644 --- a/editor/components/block-list/block.js +++ b/editor/components/block-list/block.js @@ -525,7 +525,6 @@ const mapDispatchToProps = ( dispatch, ownProps ) => ( { } ); export default compose( - withFilters( 'Editor.BlockItem' ), connect( mapStateToProps, mapDispatchToProps ), withContext( 'editor' )( ( settings ) => { const { templateLock } = settings; @@ -534,4 +533,5 @@ export default compose( isLocked: !! templateLock, }; } ), + withFilters( 'editor.BlockListBlock' ), )( BlockListBlock ); From a46d71a474339916311a9bacde7fff0a8e439101 Mon Sep 17 00:00:00 2001 From: Grzegorz Ziolkowski Date: Fri, 8 Dec 2017 13:22:45 +0100 Subject: [PATCH 8/8] Extensibility: Make sure all hooks are loaded before blocks are registered --- blocks/api/test/parser.js | 5 +++++ blocks/index.js | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/blocks/api/test/parser.js b/blocks/api/test/parser.js index 0ef4a373566931..fc850a08730a86 100644 --- a/blocks/api/test/parser.js +++ b/blocks/api/test/parser.js @@ -49,6 +49,11 @@ describe( 'block parser', () => { save: ( { attributes } ) => attributes.content, }; + beforeAll( () => { + // Load all hooks that modify blocks + require( 'blocks/hooks' ); + } ); + afterEach( () => { setUnknownTypeHandlerName( undefined ); getBlockTypes().forEach( ( block ) => { diff --git a/blocks/index.js b/blocks/index.js index 36d647567c635a..6fc5b144d9ae78 100644 --- a/blocks/index.js +++ b/blocks/index.js @@ -1,6 +1,7 @@ /** * Internal dependencies */ +import './hooks'; import './library'; // A "block" is the abstract term used to describe units of markup that, @@ -13,7 +14,6 @@ import './library'; // Blocks are inferred from the HTML source of a post through a parsing mechanism // and then stored as objects in state, from which it is then rendered for editing. export * from './api'; -export * from './hooks'; export { default as AlignmentToolbar } from './alignment-toolbar'; export { default as BlockAlignmentToolbar } from './block-alignment-toolbar'; export { default as BlockControls } from './block-controls';