From 379fc3c9567b5a042afe05a200be7d794a891558 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Thu, 11 May 2017 10:46:17 +0100 Subject: [PATCH 1/2] List Block: Implement block switcher API --- blocks/library/list/index.js | 69 ++++++++++++++++++++++++++++++++++- blocks/library/quote/index.js | 28 ++++++++++++++ element/index.js | 19 ++++++++++ element/test/index.js | 30 ++++++++++++++- 4 files changed, 144 insertions(+), 2 deletions(-) diff --git a/blocks/library/list/index.js b/blocks/library/list/index.js index 0f852b2507a62d..59fee6911ae25d 100644 --- a/blocks/library/list/index.js +++ b/blocks/library/list/index.js @@ -1,8 +1,13 @@ +/** + * WordPress dependencies + */ +import { switchChildrenNodeName } from 'element'; + /** * Internal dependencies */ import './style.scss'; -import { registerBlock, query as hpq } from '../../api'; +import { registerBlock, query as hpq, createBlock } from '../../api'; import Editable from '../../editable'; const { children, prop } = hpq; @@ -36,6 +41,68 @@ registerBlock( 'core/list', { } ], + transforms: { + from: [ + { + type: 'block', + blocks: [ 'core/text' ], + transform: ( { content } ) => { + return createBlock( 'core/list', { + nodeName: 'ul', + values: switchChildrenNodeName( content, 'li' ) + } ); + } + }, + { + type: 'block', + blocks: [ 'core/heading' ], + transform: ( { content } ) => { + return createBlock( 'core/list', { + nodeName: 'ul', + values: [
  • { content }
  • ] + } ); + } + } + ], + to: [ + { + type: 'block', + blocks: [ 'core/text' ], + transform: ( { values } ) => { + return createBlock( 'core/text', { + content: switchChildrenNodeName( values, 'p' ) + } ); + } + }, + { + type: 'block', + blocks: [ 'core/heading' ], + transform: ( { values, ...attrs } ) => { + if ( Array.isArray( values ) ) { + const heading = createBlock( 'core/heading', { + content: values[ 0 ].props.children + } ); + const blocks = [ heading ]; + + const remainingValues = values.slice( 1 ); + if ( remainingValues.length ) { + const list = createBlock( 'core/list', { + ...attrs, + values: remainingValues + } ); + blocks.push( list ); + } + + return blocks; + } + return createBlock( 'core/heading', { + values + } ); + } + } + ] + }, + edit( { attributes, setAttributes, focus, setFocus } ) { const { nodeName = 'OL', values = [] } = attributes; return ( diff --git a/blocks/library/quote/index.js b/blocks/library/quote/index.js index e525b00824dc84..fc2bfede8f08df 100644 --- a/blocks/library/quote/index.js +++ b/blocks/library/quote/index.js @@ -1,3 +1,8 @@ +/** + * WordPress dependencies + */ +import { switchChildrenNodeName } from 'element'; + /** * Internal dependencies */ @@ -38,6 +43,15 @@ registerBlock( 'core/quote', { } ); } }, + { + type: 'block', + blocks: [ 'core/list' ], + transform: ( { values } ) => { + return createBlock( 'core/quote', { + value: switchChildrenNodeName( values, 'p' ) + } ); + } + }, { type: 'block', blocks: [ 'core/heading' ], @@ -58,6 +72,20 @@ registerBlock( 'core/quote', { } ); } }, + { + type: 'block', + blocks: [ 'core/list' ], + transform: ( { value, citation } ) => { + const valueElements = switchChildrenNodeName( value, 'li' ); + const values = citation + ? wp.element.concatChildren( valueElements,
  • { citation }
  • ) + : valueElements; + return createBlock( 'core/list', { + nodeName: 'ul', + values + } ); + } + }, { type: 'block', blocks: [ 'core/heading' ], diff --git a/element/index.js b/element/index.js index 8c8b2762a88755..82a99fd21ee364 100644 --- a/element/index.js +++ b/element/index.js @@ -4,6 +4,7 @@ import { createElement, Component, cloneElement, Children } from 'react'; import { render } from 'react-dom'; import { renderToStaticMarkup } from 'react-dom/server'; +import { isString } from 'lodash'; /** * Returns a new element of given type. Type can be either a string tag name or @@ -91,3 +92,21 @@ export function concatChildren( ...childrens ) { return memo; }, [] ); } + +/** + * Switches the nodeName of all the elements in the children object + * + * @param {?Object} children Children object + * @param {String} nodeName Node name + * @return {?Object} The updated children object + */ +export function switchChildrenNodeName( children, nodeName ) { + return children && Children.map( children, ( elt, index ) => { + if ( isString( elt ) ) { + return createElement( nodeName, { key: index }, elt ); + } + const { children: childrenProp, ...props } = elt.props; + return createElement( nodeName, { key: index, ...props }, childrenProp ); + } ); +} + diff --git a/element/test/index.js b/element/test/index.js index 842ac6a0465e16..479bf824271f2b 100644 --- a/element/test/index.js +++ b/element/test/index.js @@ -6,7 +6,7 @@ import { expect } from 'chai'; /** * Internal dependencies */ -import { createElement, renderToString, concatChildren } from '../'; +import { createElement, renderToString, concatChildren, switchChildrenNodeName } from '../'; describe( 'element', () => { describe( 'renderToString', () => { @@ -55,4 +55,32 @@ describe( 'element', () => { expect( concat[ 1 ].key ).to.equal( '1,0' ); } ); } ); + + describe( 'switchChildrenNodeName', () => { + it( 'should return undefined for undefined children', () => { + expect( switchChildrenNodeName() ).to.be.undefined(); + } ); + + it( 'should switch strings', () => { + const children = switchChildrenNodeName( [ 'a', 'b' ], 'strong' ); + expect( children.length ).to.equal( 2 ); + expect( children[ 0 ].type ).to.equal( 'strong' ); + expect( children[ 0 ].props.children ).to.equal( 'a' ); + expect( children[ 1 ].type ).to.equal( 'strong' ); + expect( children[ 1 ].props.children ).to.equal( 'b' ); + } ); + + it( 'should switch elements', () => { + const children = switchChildrenNodeName( [ + createElement( 'strong', { align: 'left' }, 'Courgette' ), + createElement( 'strong', {}, 'Concombre' ) + ], 'em' ); + expect( children.length ).to.equal( 2 ); + expect( children[ 0 ].type ).to.equal( 'em' ); + expect( children[ 0 ].props.children ).to.equal( 'Courgette' ); + expect( children[ 0 ].props.align ).to.equal( 'left' ); + expect( children[ 1 ].type ).to.equal( 'em' ); + expect( children[ 1 ].props.children ).to.equal( 'Concombre' ); + } ); + } ); } ); From 1be39e5f341a1195b9f9b0eaaa6b8465b7e22b90 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Thu, 11 May 2017 12:14:03 +0100 Subject: [PATCH 2/2] List Block: Remove heading transformation --- blocks/library/list/index.js | 36 ------------------------------------ 1 file changed, 36 deletions(-) diff --git a/blocks/library/list/index.js b/blocks/library/list/index.js index 59fee6911ae25d..7a7246a1677641 100644 --- a/blocks/library/list/index.js +++ b/blocks/library/list/index.js @@ -52,16 +52,6 @@ registerBlock( 'core/list', { values: switchChildrenNodeName( content, 'li' ) } ); } - }, - { - type: 'block', - blocks: [ 'core/heading' ], - transform: ( { content } ) => { - return createBlock( 'core/list', { - nodeName: 'ul', - values: [
  • { content }
  • ] - } ); - } } ], to: [ @@ -73,32 +63,6 @@ registerBlock( 'core/list', { content: switchChildrenNodeName( values, 'p' ) } ); } - }, - { - type: 'block', - blocks: [ 'core/heading' ], - transform: ( { values, ...attrs } ) => { - if ( Array.isArray( values ) ) { - const heading = createBlock( 'core/heading', { - content: values[ 0 ].props.children - } ); - const blocks = [ heading ]; - - const remainingValues = values.slice( 1 ); - if ( remainingValues.length ) { - const list = createBlock( 'core/list', { - ...attrs, - values: remainingValues - } ); - blocks.push( list ); - } - - return blocks; - } - return createBlock( 'core/heading', { - values - } ); - } } ] },