diff --git a/blocks/api/query.js b/blocks/api/query.js index 5a91e6503694e..bba0fcc3b6b91 100644 --- a/blocks/api/query.js +++ b/blocks/api/query.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { nodeListToReact } from 'dom-react'; +import { nodeListToReact, nodeToReact } from 'dom-react'; import { flow } from 'lodash'; import { attr as originalAttr, @@ -31,11 +31,11 @@ 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; + return ( domNode ) => { + let match = domNode; if ( selector ) { - match = node.querySelector( selector ); + match = domNode.querySelector( selector ); } if ( match ) { @@ -45,3 +45,14 @@ export const children = withKnownMatcherFlag( ( selector ) => { return []; }; } ); +export const node = withKnownMatcherFlag( ( selector ) => { + return ( domNode ) => { + let match = domNode; + + if ( selector ) { + match = domNode.querySelector( selector ); + } + + return nodeToReact( match, wp.element.createElement ); + }; +} ); diff --git a/blocks/api/test/query.js b/blocks/api/test/query.js index e372cf1df6630..ad2049772b295 100644 --- a/blocks/api/test/query.js +++ b/blocks/api/test/query.js @@ -32,4 +32,21 @@ describe( 'query', () => { expect( wp.element.renderToString( match ) ).to.equal( html ); } ); } ); + + describe( 'node()', () => { + it( 'should return a matcher function', () => { + const matcher = query.node(); + + expect( matcher ).to.be.a( 'function' ); + } ); + + it( 'should return HTML equivalent WPElement of matched element', () => { + // 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, query.node() ); + + expect( wp.element.renderToString( match ) ).to.equal( `${ html }` ); + } ); + } ); } ); diff --git a/blocks/library/quote/index.js b/blocks/library/quote/index.js index dc2a9508b2e7b..66706eb855f31 100644 --- a/blocks/library/quote/index.js +++ b/blocks/library/quote/index.js @@ -2,6 +2,7 @@ * WordPress dependencies */ import { switchChildrenNodeName } from 'element'; +import { isString } from 'lodash'; /** * Internal dependencies @@ -12,7 +13,7 @@ import AlignmentToolbar from '../../alignment-toolbar'; import BlockControls from '../../block-controls'; import Editable from '../../editable'; -const { children, query } = hpq; +const { children, node, query } = hpq; registerBlockType( 'core/quote', { title: wp.i18n.__( 'Quote' ), @@ -20,7 +21,7 @@ registerBlockType( 'core/quote', { category: 'common', attributes: { - value: query( 'blockquote > p', children() ), + value: query( 'blockquote > p', node() ), citation: children( 'footer' ), }, @@ -68,9 +69,23 @@ registerBlockType( 'core/quote', { { type: 'block', blocks: [ 'core/text' ], - transform: ( { value, citation } ) => { + transform: ( { value, citation, ...attrs } ) => { + const textElement = Array.isArray( value ) ? value[ 0 ] : value; + const textContent = isString( textElement ) ? textElement : textElement.props.children; + if ( Array.isArray( value ) || citation ) { + const text = createBlock( 'core/text', { + content: textContent, + } ); + const quote = createBlock( 'core/quote', { + ...attrs, + citation, + value: Array.isArray( value ) ? value.slice( 1 ) : '', + } ); + + return [ text, quote ]; + } return createBlock( 'core/text', { - content: wp.element.concatChildren( value, citation ), + content: textContent, } ); }, }, @@ -92,9 +107,11 @@ registerBlockType( 'core/quote', { type: 'block', blocks: [ 'core/heading' ], transform: ( { value, citation, ...attrs } ) => { + const headingElement = Array.isArray( value ) ? value[ 0 ] : value; + const headingContent = isString( headingElement ) ? headingElement : headingElement.props.children; if ( Array.isArray( value ) || citation ) { const heading = createBlock( 'core/heading', { - content: Array.isArray( value ) ? value[ 0 ] : value, + content: headingContent, } ); const quote = createBlock( 'core/quote', { ...attrs, @@ -105,7 +122,7 @@ registerBlockType( 'core/quote', { return [ heading, quote ]; } return createBlock( 'core/heading', { - content: value, + content: headingContent, } ); }, }, @@ -172,7 +189,7 @@ registerBlockType( 'core/quote', { key={ i } style={ { textAlign: align ? align : null } } > - { paragraph } + { isString( paragraph ) ? paragraph : paragraph.props.children }

) ) } { citation && citation.length > 0 && ( diff --git a/blocks/test/fixtures/core-quote-style-1.json b/blocks/test/fixtures/core-quote-style-1.json index 3781513606303..dd76ad46a3da7 100644 --- a/blocks/test/fixtures/core-quote-style-1.json +++ b/blocks/test/fixtures/core-quote-style-1.json @@ -5,9 +5,10 @@ "attributes": { "style": "1", "value": [ - [ - "The editor will endeavour to create a new page and post building experience that makes writing rich posts effortless, and has “blocks” to make it easy what today might take shortcodes, custom HTML, or “mystery meat” embed discovery." - ] + { + "children": "The editor will endeavour to create a new page and post building experience that makes writing rich posts effortless, and has “blocks” to make it easy what today might take shortcodes, custom HTML, or “mystery meat” embed discovery.", + "type": "p" + } ], "citation": [ "Matt Mullenweg, 2017" diff --git a/blocks/test/fixtures/core-quote-style-2.json b/blocks/test/fixtures/core-quote-style-2.json index ba3c1bd924132..114a32462aea3 100644 --- a/blocks/test/fixtures/core-quote-style-2.json +++ b/blocks/test/fixtures/core-quote-style-2.json @@ -5,9 +5,10 @@ "attributes": { "style": "2", "value": [ - [ - "There is no greater agony than bearing an untold story inside you." - ] + { + "children": "There is no greater agony than bearing an untold story inside you.", + "type": "p" + } ], "citation": [ "Maya Angelou"