From cd0af05939345641fb0b99335f87321797d4e86d Mon Sep 17 00:00:00 2001 From: Hendrik Luehrsen Date: Tue, 29 Jan 2019 08:37:27 +0100 Subject: [PATCH] Add innerBlocks as an argument to the transform function (#11979) Co-Authored-By: Hendrik Luehrsen --- .../block-api/block-registration.md | 33 ++++++ packages/blocks/CHANGELOG.md | 6 ++ packages/blocks/src/api/factory.js | 7 +- packages/blocks/src/api/test/factory.js | 100 ++++++++++++++++++ .../plugins/inner-blocks-templates/index.js | 71 ++++++++++--- 5 files changed, 202 insertions(+), 15 deletions(-) diff --git a/docs/designers-developers/developers/block-api/block-registration.md b/docs/designers-developers/developers/block-api/block-registration.md index 90d0752ff170ea..e36628c7249e04 100644 --- a/docs/designers-developers/developers/block-api/block-registration.md +++ b/docs/designers-developers/developers/block-api/block-registration.md @@ -311,6 +311,39 @@ transforms: { ``` {% end %} +A block with innerBlocks can also be transformed from and to another block with innerBlocks. + +{% codetabs %} +{% ES5 %} +```js +transforms: { + to: [ + { + type: 'block', + blocks: [ 'some/block-with-innerblocks' ], + transform: function( attributes, innerBlocks ) { + return createBlock( 'some/other-block-with-innerblocks', attributes, innerBlocks ); + }, + }, + ], +}, +``` +{% ESNext %} +```js +transforms: { + to: [ + { + type: 'block', + blocks: [ 'some/block-with-innerblocks' ], + transform: ( attributes, innerBlocks ) => { + return createBlock( 'some/other-block-with-innerblocks', attributes, innerBlocks); + }, + }, + ], +}, +``` +{% end %} + An optional `isMatch` function can be specified on a transform object. This provides an opportunity to perform additional checks on whether a transform should be possible. Returning `false` from this function will prevent the transform from being displayed as an option to the user. {% codetabs %} diff --git a/packages/blocks/CHANGELOG.md b/packages/blocks/CHANGELOG.md index 1f40a53235f4cd..4d607751d8a31b 100644 --- a/packages/blocks/CHANGELOG.md +++ b/packages/blocks/CHANGELOG.md @@ -1,3 +1,9 @@ +## 6.1.0 (Unreleased) + +### New Feature + +- Blocks' `transforms` will receive `innerBlocks` as the second argument (or an array of each block's respective `innerBlocks` for a multi-transform). + ## 6.0.5 (2019-01-03) ## 6.0.4 (2018-12-12) diff --git a/packages/blocks/src/api/factory.js b/packages/blocks/src/api/factory.js index 9068a8b3d8cd3b..c7bd01f2c699c4 100644 --- a/packages/blocks/src/api/factory.js +++ b/packages/blocks/src/api/factory.js @@ -346,9 +346,12 @@ export function switchToBlockType( blocks, name ) { let transformationResults; if ( transformation.isMultiBlock ) { - transformationResults = transformation.transform( blocksArray.map( ( currentBlock ) => currentBlock.attributes ) ); + transformationResults = transformation.transform( + blocksArray.map( ( currentBlock ) => currentBlock.attributes ), + blocksArray.map( ( currentBlock ) => currentBlock.innerBlocks ) + ); } else { - transformationResults = transformation.transform( firstBlock.attributes ); + transformationResults = transformation.transform( firstBlock.attributes, firstBlock.innerBlocks ); } // Ensure that the transformation function returned an object or an array diff --git a/packages/blocks/src/api/test/factory.js b/packages/blocks/src/api/test/factory.js index eaf222b8b5c866..11249b08d36ced 100644 --- a/packages/blocks/src/api/test/factory.js +++ b/packages/blocks/src/api/test/factory.js @@ -1122,6 +1122,106 @@ describe( 'block factory', () => { value: 'smoked ribs', } ); } ); + + it( 'should pass through inner blocks to transform', () => { + registerBlockType( 'core/updated-columns-block', { + attributes: { + value: { + type: 'string', + }, + }, + transforms: { + from: [ { + type: 'block', + blocks: [ 'core/columns-block' ], + transform( attributes, innerBlocks ) { + return createBlock( + 'core/updated-columns-block', + attributes, + innerBlocks.map( ( innerBlock ) => { + return cloneBlock( innerBlock, { + value: 'after', + } ); + } ), + ); + }, + } ], + }, + save: noop, + category: 'common', + title: 'updated columns block', + } ); + registerBlockType( 'core/columns-block', defaultBlockSettings ); + registerBlockType( 'core/column-block', defaultBlockSettings ); + + const block = createBlock( + 'core/columns-block', + {}, + [ createBlock( 'core/column-block', { value: 'before' } ) ] + ); + + const transformedBlocks = switchToBlockType( block, 'core/updated-columns-block' ); + + expect( transformedBlocks ).toHaveLength( 1 ); + expect( transformedBlocks[ 0 ].innerBlocks ).toHaveLength( 1 ); + expect( transformedBlocks[ 0 ].innerBlocks[ 0 ].attributes.value ).toBe( 'after' ); + } ); + + it( 'should pass through inner blocks to transform (multi)', () => { + registerBlockType( 'core/updated-columns-block', { + attributes: { + value: { + type: 'string', + }, + }, + transforms: { + from: [ { + type: 'block', + blocks: [ 'core/columns-block' ], + isMultiBlock: true, + transform( blocksAttributes, blocksInnerBlocks ) { + return blocksAttributes.map( ( attributes, i ) => { + return createBlock( + 'core/updated-columns-block', + attributes, + blocksInnerBlocks[ i ].map( ( innerBlock ) => { + return cloneBlock( innerBlock, { + value: 'after' + i, + } ); + } ), + ); + } ); + }, + } ], + }, + save: noop, + category: 'common', + title: 'updated columns block', + } ); + registerBlockType( 'core/columns-block', defaultBlockSettings ); + registerBlockType( 'core/column-block', defaultBlockSettings ); + + const blocks = [ + createBlock( + 'core/columns-block', + {}, + [ createBlock( 'core/column-block', { value: 'before' } ) ] + ), + createBlock( + 'core/columns-block', + {}, + [ createBlock( 'core/column-block', { value: 'before' } ) ] + ), + ]; + + const transformedBlocks = switchToBlockType( blocks, 'core/updated-columns-block' ); + + expect( transformedBlocks ).toHaveLength( 2 ); + expect( transformedBlocks[ 0 ].innerBlocks ).toHaveLength( 1 ); + expect( transformedBlocks[ 0 ].innerBlocks[ 0 ].attributes.value ).toBe( 'after0' ); + expect( transformedBlocks[ 1 ].innerBlocks ).toHaveLength( 1 ); + expect( transformedBlocks[ 1 ].innerBlocks[ 0 ].attributes.value ).toBe( 'after1' ); + } ); } ); describe( 'getBlockTransforms', () => { diff --git a/packages/e2e-tests/plugins/inner-blocks-templates/index.js b/packages/e2e-tests/plugins/inner-blocks-templates/index.js index 0922fe106cecf2..6c0b62c51fea4e 100644 --- a/packages/e2e-tests/plugins/inner-blocks-templates/index.js +++ b/packages/e2e-tests/plugins/inner-blocks-templates/index.js @@ -1,5 +1,6 @@ ( function() { var registerBlockType = wp.blocks.registerBlockType; + var createBlock = wp.blocks.createBlock; var el = wp.element.createElement; var InnerBlocks = wp.editor.InnerBlocks; var __ = wp.i18n.__; @@ -28,10 +29,10 @@ edit: function( props ) { return el( - InnerBlocks, - { - template: TEMPLATE, - } + InnerBlocks, + { + template: TEMPLATE, + } ); }, @@ -45,11 +46,11 @@ edit: function( props ) { return el( - InnerBlocks, - { - template: TEMPLATE, - templateLock: 'all', - } + InnerBlocks, + { + template: TEMPLATE, + templateLock: 'all', + } ); }, @@ -63,13 +64,57 @@ edit: function( props ) { return el( - InnerBlocks, - { - template: TEMPLATE_PARAGRAPH_PLACEHOLDER, - } + InnerBlocks, + { + template: TEMPLATE_PARAGRAPH_PLACEHOLDER, + } ); }, save, } ); + + registerBlockType( 'test/test-inner-blocks-transformer-target', { + title: 'Test Inner Blocks transformer target', + icon: 'cart', + category: 'common', + + transforms: { + from: [ + { + type: 'block', + blocks: [ + 'test/i-dont-exist', + 'test/test-inner-blocks-no-locking', + 'test/test-inner-blocks-locking-all', + 'test/test-inner-blocks-paragraph-placeholder' + ], + transform: function( attributes, innerBlocks ) { + return createBlock( 'test/test-inner-blocks-transformer-target', attributes, innerBlocks ); + }, + }, + ], + to: [ + { + type: 'block', + blocks: [ 'test/i-dont-exist' ], + transform: function( attributes, innerBlocks ) { + return createBlock( 'test/test-inner-blocks-transformer-target', attributes, innerBlocks ); + }, + } + ] + }, + + edit: function( props ) { + return el( + InnerBlocks, + { + template: TEMPLATE, + } + ); + }, + + save, + } ); + } )();