From 5b88cc6e3f653b63966fd79b1942a82273912677 Mon Sep 17 00:00:00 2001 From: Andrew Duthie Date: Wed, 3 May 2017 10:18:23 -0400 Subject: [PATCH] Pick only matchers which have internal flag applied --- blocks/api/parser.js | 21 +++++++++++++++------ blocks/api/query.js | 31 ++++++++++++++++++++++++++++--- blocks/api/test/parser.js | 5 +++-- blocks/api/test/query.js | 13 ++++++++++--- 4 files changed, 56 insertions(+), 14 deletions(-) diff --git a/blocks/api/parser.js b/blocks/api/parser.js index fa1a1ad201e49..09ec75a80050e 100644 --- a/blocks/api/parser.js +++ b/blocks/api/parser.js @@ -1,8 +1,8 @@ /** * External dependencies */ -import * as query from 'hpq'; -import { escape, unescape } from 'lodash'; +import { parse as hpqParse } from 'hpq'; +import { escape, unescape, pickBy } from 'lodash'; /** * Internal dependencies @@ -19,10 +19,19 @@ import { createBlock } from './factory'; * @return {Object} Block attributes */ export function parseBlockAttributes( rawContent, blockSettings ) { - if ( 'function' === typeof blockSettings.attributes ) { - return blockSettings.attributes( rawContent ); - } else if ( blockSettings.attributes ) { - return query.parse( rawContent, blockSettings.attributes ); + const { attributes } = blockSettings; + if ( 'function' === typeof attributes ) { + return attributes( rawContent ); + } else if ( attributes ) { + // Matchers are implemented as functions that receive a DOM node from + // which to select data. Use of the DOM is incidental and we shouldn't + // guarantee a contract that this be provided, else block implementers + // may feel compelled to use the node. Instead, matchers are intended + // as a generic interface to query data from any tree shape. Here we + // pick only matchers which include an internal flag. + const knownMatchers = pickBy( attributes, '_wpBlocksKnownMatcher' ); + + return hpqParse( rawContent, knownMatchers ); } return {}; diff --git a/blocks/api/query.js b/blocks/api/query.js index 559a9b67069b5..f9e7782660de9 100644 --- a/blocks/api/query.js +++ b/blocks/api/query.js @@ -2,10 +2,35 @@ * External dependencies */ import { nodeListToReact } from 'dom-react'; +import { flow } from 'lodash'; +import { + attr as originalAttr, + prop as originalProp, + html as originalHtml, + text as originalText, + query as originalQuery +} from 'hpq'; -export * from 'hpq'; +/** + * Given a matcher function creator, returns a new function which applies an + * internal flag to the created matcher. + * + * @param {Function} fn Original matcher function creator + * @return {Function} Modified matcher function creator + */ +function withKnownMatcherFlag( fn ) { + return flow( fn, ( matcher ) => { + matcher._wpBlocksKnownMatcher = true; + return matcher; + } ); +} -export function children( selector ) { +export const attr = withKnownMatcherFlag( originalAttr ); +export const prop = withKnownMatcherFlag( originalProp ); +export const html = withKnownMatcherFlag( originalHtml ); +export const text = withKnownMatcherFlag( originalText ); +export const query = withKnownMatcherFlag( originalQuery ); +export const children = withKnownMatcherFlag( ( selector ) => { return ( node ) => { let match = node; @@ -19,4 +44,4 @@ export function children( selector ) { return []; }; -} +} ); diff --git a/blocks/api/test/parser.js b/blocks/api/test/parser.js index 99671d43cbf15..51c15bd6f92ec 100644 --- a/blocks/api/test/parser.js +++ b/blocks/api/test/parser.js @@ -2,11 +2,11 @@ * External dependencies */ import { expect } from 'chai'; -import { text } from 'hpq'; /** * Internal dependencies */ +import { text } from '../query'; import { getBlockAttributes, parseBlockAttributes, @@ -47,7 +47,8 @@ describe( 'block parser', () => { it( 'should use the query object implementation', () => { const blockSettings = { attributes: { - emphasis: text( 'strong' ) + emphasis: text( 'strong' ), + ignoredDomMatcher: ( node ) => node.innerHTML } }; diff --git a/blocks/api/test/query.js b/blocks/api/test/query.js index 4f1fa45472af6..e372cf1df6630 100644 --- a/blocks/api/test/query.js +++ b/blocks/api/test/query.js @@ -2,16 +2,23 @@ * External dependencies */ import { expect } from 'chai'; +import { parse } from 'hpq'; /** * Internal dependencies */ -import { parse, children } from '../query'; +import * as query from '../query'; describe( 'query', () => { + it( 'should generate matchers which apply internal flag', () => { + for ( const matcherFn in query ) { + expect( query[ matcherFn ]()._wpBlocksKnownMatcher ).to.be.true(); + } + } ); + describe( 'children()', () => { it( 'should return a matcher function', () => { - const matcher = children(); + const matcher = query.children(); expect( matcher ).to.be.a( 'function' ); } ); @@ -20,7 +27,7 @@ describe( 'query', () => { // Assumption here is that we can cleanly convert back and forth // between a string and WPElement representation const html = '

A delicious sundae dessert

'; - const match = parse( html, children() ); + const match = parse( html, query.children() ); expect( wp.element.renderToString( match ) ).to.equal( html ); } );