diff --git a/blocks/api/query.js b/blocks/api/query.js index d9813afa62f50..cb448a13ea119 100644 --- a/blocks/api/query.js +++ b/blocks/api/query.js @@ -6,7 +6,7 @@ import { createElement } from 'element'; /** * External dependencies */ -import { nodeListToReact } from 'dom-react'; +import { nodeListToReact, nodeToReact } from 'dom-react'; import { flow } from 'lodash'; import { attr as originalAttr, @@ -36,11 +36,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 ) { @@ -50,3 +50,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 857e9459fc855..2a223d52f65a6 100644 --- a/blocks/api/test/query.js +++ b/blocks/api/test/query.js @@ -37,4 +37,21 @@ describe( 'query', () => { expect( 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 58bfa69cd971a..a58117722c708 100644 --- a/blocks/library/quote/index.js +++ b/blocks/library/quote/index.js @@ -1,10 +1,13 @@ +/** + * External dependencies + */ +import { isString, isObject } from 'lodash'; + /** * WordPress dependencies */ import { __, sprintf } from 'i18n'; -import { concatChildren } from 'element'; import { Toolbar } from 'components'; -import { isObject } from 'lodash'; /** * Internal dependencies @@ -15,7 +18,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: __( 'Quote' ), @@ -23,7 +26,7 @@ registerBlockType( 'core/quote', { category: 'common', attributes: { - value: query( 'blockquote > p', children() ), + value: query( 'blockquote > p', node() ), citation: children( 'footer' ), }, @@ -52,9 +55,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: concatChildren( value, citation ), + content: textContent, } ); }, }, @@ -63,9 +80,11 @@ registerBlockType( 'core/quote', { blocks: [ 'core/heading' ], transform: ( { value, citation, ...attrs } ) => { const isMultiParagraph = Array.isArray( value ) && isObject( value[ 0 ] ) && value[ 0 ].type === 'p'; + const headingElement = isMultiParagraph ? value[ 0 ] : value; + const headingContent = isString( headingElement ) ? headingElement : headingElement.props.children; if ( isMultiParagraph || citation ) { const heading = createBlock( 'core/heading', { - content: Array.isArray( value ) ? value[ 0 ] : value, + content: headingContent, } ); const quote = createBlock( 'core/quote', { ...attrs, @@ -76,7 +95,7 @@ registerBlockType( 'core/quote', { return [ heading, quote ]; } return createBlock( 'core/heading', { - content: value, + content: headingContent, } ); }, }, @@ -152,7 +171,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"