From 8252a6b30ebb2206e5cc5b4ecc3ffab4f2493f05 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Thu, 16 Nov 2017 14:50:04 +0100 Subject: [PATCH] Block API: Ensure backwards compatibility for block matchers --- blocks/api/index.js | 4 ++ blocks/api/matchers.js | 38 ++++++++++ blocks/api/parser.js | 2 +- blocks/api/registration.js | 13 +++- blocks/api/source.js | 82 +++++++++++++++------- blocks/api/test/{source.js => matchers.js} | 4 +- blocks/library/button/index.js | 1 + 7 files changed, 113 insertions(+), 31 deletions(-) create mode 100644 blocks/api/matchers.js rename blocks/api/test/{source.js => matchers.js} (95%) diff --git a/blocks/api/index.js b/blocks/api/index.js index f1c7204ff0c53..a03da6ee9eb70 100644 --- a/blocks/api/index.js +++ b/blocks/api/index.js @@ -15,3 +15,7 @@ export { getBlockTypes, hasBlockSupport, } from './registration'; + +// Deprecated matchers +import * as source from './source'; +export { source }; diff --git a/blocks/api/matchers.js b/blocks/api/matchers.js new file mode 100644 index 0000000000000..0ccf4cf8d8832 --- /dev/null +++ b/blocks/api/matchers.js @@ -0,0 +1,38 @@ +/** + * WordPress dependencies + */ +import { createElement } from '@wordpress/element'; + +/** + * External dependencies + */ +import { nodeListToReact, nodeToReact } from 'dom-react'; +export { attr, prop, html, text, query } from 'hpq'; + +export const children = ( selector ) => { + return ( domNode ) => { + let match = domNode; + + if ( selector ) { + match = domNode.querySelector( selector ); + } + + if ( match ) { + return nodeListToReact( match.childNodes || [], createElement ); + } + + return []; + }; +}; + +export const node = ( selector ) => { + return ( domNode ) => { + let match = domNode; + + if ( selector ) { + match = domNode.querySelector( selector ); + } + + return nodeToReact( match, createElement ); + }; +}; diff --git a/blocks/api/parser.js b/blocks/api/parser.js index 211379bbc2680..ed55b8a7c1a2b 100644 --- a/blocks/api/parser.js +++ b/blocks/api/parser.js @@ -12,7 +12,7 @@ import { getBlockType, getUnknownTypeHandlerName } from './registration'; import { createBlock } from './factory'; import { isValidBlock } from './validation'; import { getCommentDelimitedContent } from './serializer'; -import { attr, prop, html, text, query, node, children } from './source'; +import { attr, prop, html, text, query, node, children } from './matchers'; /** * Returns value coerced to the specified JSON schema type string diff --git a/blocks/api/registration.js b/blocks/api/registration.js index 33cc40342dd5e..cac698008e5fa 100644 --- a/blocks/api/registration.js +++ b/blocks/api/registration.js @@ -3,7 +3,7 @@ /** * External dependencies */ -import { get, isFunction, some } from 'lodash'; +import { get, isFunction, some, mapValues } from 'lodash'; /** * WordPress dependencies @@ -119,6 +119,17 @@ export function registerBlockType( name, settings ) { ...settings, }; + // Resolve deprecated attributes + settings.attributes = mapValues( settings.attributes, ( attribute ) => { + if ( isFunction( attribute.source ) ) { + return { + ...attribute, + ...attribute.source(), + }; + } + return attribute; + } ); + settings = applyFilters( 'registerBlockType', settings, name ); return blocks[ name ] = settings; diff --git a/blocks/api/source.js b/blocks/api/source.js index 0ccf4cf8d8832..a3f4bc4ec412d 100644 --- a/blocks/api/source.js +++ b/blocks/api/source.js @@ -1,38 +1,66 @@ -/** - * WordPress dependencies - */ -import { createElement } from '@wordpress/element'; +function warnAboutDeprecatedMatcher() { + // eslint-disable-next-line no-console + console.warn( + 'Attributes matchers are deprecated and they will be removed in a future version of Gutenberg. ' + + 'Please update your attributes definition https://wordpress.org/gutenberg/handbook/reference/attributes/' + ); +} -/** - * External dependencies - */ -import { nodeListToReact, nodeToReact } from 'dom-react'; -export { attr, prop, html, text, query } from 'hpq'; - -export const children = ( selector ) => { - return ( domNode ) => { - let match = domNode; +export const attr = ( selector, attribute ) => () => { + warnAboutDeprecatedMatcher(); + return { + source: 'attribute', + attribute: attribute === undefined ? selector : attribute, + selector: attribute === undefined ? undefined : selector, + }; +}; - if ( selector ) { - match = domNode.querySelector( selector ); - } +export const prop = ( selector, property ) => () => { + warnAboutDeprecatedMatcher(); + return { + source: 'property', + property: property === undefined ? selector : property, + selector: property === undefined ? undefined : selector, + }; +}; - if ( match ) { - return nodeListToReact( match.childNodes || [], createElement ); - } +export const html = ( selector ) => () => { + warnAboutDeprecatedMatcher(); + return { + source: 'html', + selector, + }; +}; - return []; +export const text = ( selector ) => () => { + warnAboutDeprecatedMatcher(); + return { + source: 'text', + selector, }; }; -export const node = ( selector ) => { - return ( domNode ) => { - let match = domNode; +export const query = ( selector, subMatchers ) => () => { + warnAboutDeprecatedMatcher(); + return { + source: 'query', + selector, + query: subMatchers, + }; +}; - if ( selector ) { - match = domNode.querySelector( selector ); - } +export const children = ( selector ) => () => { + warnAboutDeprecatedMatcher(); + return { + source: 'children', + selector, + }; +}; - return nodeToReact( match, createElement ); +export const node = ( selector ) => () => { + warnAboutDeprecatedMatcher(); + return { + source: 'node', + selector, }; }; diff --git a/blocks/api/test/source.js b/blocks/api/test/matchers.js similarity index 95% rename from blocks/api/test/source.js rename to blocks/api/test/matchers.js index c9e71eb95bb0c..32d1246a2e9d6 100644 --- a/blocks/api/test/source.js +++ b/blocks/api/test/matchers.js @@ -11,9 +11,9 @@ import { renderToString } from '@wordpress/element'; /** * Internal dependencies */ -import * as sources from '../source'; +import * as sources from '../matchers'; -describe( 'sources', () => { +describe( 'matchers', () => { describe( 'children()', () => { it( 'should return a source function', () => { const source = sources.children(); diff --git a/blocks/library/button/index.js b/blocks/library/button/index.js index d5e305a20f565..ef2eb2d1fe71d 100644 --- a/blocks/library/button/index.js +++ b/blocks/library/button/index.js @@ -156,6 +156,7 @@ class ButtonBlock extends Component { , focus && (
event.preventDefault() }>