diff --git a/packages/editor/src/components/post-actions/actions.js b/packages/editor/src/components/post-actions/actions.js index e1d024dacce578..726c8c279b9f7e 100644 --- a/packages/editor/src/components/post-actions/actions.js +++ b/packages/editor/src/components/post-actions/actions.js @@ -1,13 +1,6 @@ -/** - * External dependencies - */ -import { paramCase as kebabCase } from 'change-case'; -import { downloadZip } from 'client-zip'; - /** * WordPress dependencies */ -import { downloadBlob } from '@wordpress/blob'; import { external, trash, backup } from '@wordpress/icons'; import { addQueryArgs } from '@wordpress/url'; import { useDispatch, useSelect } from '@wordpress/data'; @@ -39,6 +32,7 @@ import { import { store as editorStore } from '../../store'; import { unlock } from '../../lock-unlock'; import isTemplateRevertable from '../../store/utils/is-template-revertable'; +import { exportPatternAsJSONAction } from './export-pattern-as-json-action'; // Patterns. export const { @@ -734,35 +728,35 @@ const resetTemplateAction = { if ( items[ 0 ].type === TEMPLATE_PART_POST_TYPE ) { await removeTemplates( items ); } else { - for ( const template of items ) { + for ( const template of items ) { if ( template.type === TEMPLATE_POST_TYPE ) { - await revertTemplate( template, { - allowUndo: false, - } ); - await saveEditedEntityRecord( - 'postType', - template.type, - template.id - ); - } + await revertTemplate( template, { + allowUndo: false, + } ); + await saveEditedEntityRecord( + 'postType', + template.type, + template.id + ); + } } - createSuccessNotice( - items.length > 1 - ? sprintf( - /* translators: The number of items. */ - __( '%s items reset.' ), - items.length - ) - : sprintf( - /* translators: The template/part's name. */ - __( '"%s" reset.' ), + createSuccessNotice( + items.length > 1 + ? sprintf( + /* translators: The number of items. */ + __( '%s items reset.' ), + items.length + ) + : sprintf( + /* translators: The template/part's name. */ + __( '"%s" reset.' ), decodeEntities( getItemTitle( items[ 0 ] ) ) - ), - { - type: 'snackbar', - id: 'revert-template-action', - } - ); + ), + { + type: 'snackbar', + id: 'revert-template-action', + } + ); } } catch ( error ) { let fallbackErrorMessage; @@ -1024,55 +1018,6 @@ const renameTemplateAction = { }, }; -function getJsonFromItem( item ) { - return JSON.stringify( - { - __file: item.type, - title: item.title || item.name, - content: item.patternPost.content.raw, - syncStatus: item.patternPost.wp_pattern_sync_status, - }, - null, - 2 - ); -} - -export const exportPatternAsJSONAction = { - id: 'export-pattern', - label: __( 'Export as JSON' ), - supportsBulk: true, - isEligible: ( item ) => item.type === PATTERN_TYPES.user, - callback: async ( items ) => { - if ( items.length === 1 ) { - return downloadBlob( - `${ kebabCase( items[ 0 ].title || items[ 0 ].name ) }.json`, - getJsonFromItem( items[ 0 ] ), - 'application/json' - ); - } - const nameCount = {}; - const filesToZip = items.map( ( item ) => { - const name = kebabCase( item.title || item.name ); - nameCount[ name ] = ( nameCount[ name ] || 0 ) + 1; - return { - name: `${ - name + - ( nameCount[ name ] > 1 - ? '-' + ( nameCount[ name ] - 1 ) - : '' ) - }.json`, - lastModified: new Date(), - input: getJsonFromItem( item ), - }; - } ); - return downloadBlob( - __( 'patterns-export' ) + '.zip', - await downloadZip( filesToZip ).blob(), - 'application/zip' - ); - }, -}; - const canDeleteOrReset = ( item ) => { const isTemplatePart = item.type === TEMPLATE_PART_POST_TYPE; const isUserPattern = item.type === PATTERN_TYPES.user; diff --git a/packages/editor/src/components/post-actions/export-pattern-as-json-action.js b/packages/editor/src/components/post-actions/export-pattern-as-json-action.js new file mode 100644 index 00000000000000..8fc96ea8fd2340 --- /dev/null +++ b/packages/editor/src/components/post-actions/export-pattern-as-json-action.js @@ -0,0 +1,69 @@ +/** + * External dependencies + */ +import { paramCase as kebabCase } from 'change-case'; +import { downloadZip } from 'client-zip'; + +/** + * WordPress dependencies + */ +import { downloadBlob } from '@wordpress/blob'; +import { __ } from '@wordpress/i18n'; +import { privateApis as patternsPrivateApis } from '@wordpress/patterns'; + +/** + * Internal dependencies + */ +import { unlock } from '../../lock-unlock'; + +// Patterns. +export const { PATTERN_TYPES } = unlock( patternsPrivateApis ); + +function getJsonFromItem( item ) { + return JSON.stringify( + { + __file: item.type, + title: item.title || item.name, + content: item.patternPost.content.raw, + syncStatus: item.patternPost.wp_pattern_sync_status, + }, + null, + 2 + ); +} + +export const exportPatternAsJSONAction = { + id: 'export-pattern', + label: __( 'Export as JSON' ), + supportsBulk: true, + isEligible: ( item ) => item.type === PATTERN_TYPES.user, + callback: async ( items ) => { + if ( items.length === 1 ) { + return downloadBlob( + `${ kebabCase( items[ 0 ].title || items[ 0 ].name ) }.json`, + getJsonFromItem( items[ 0 ] ), + 'application/json' + ); + } + const nameCount = {}; + const filesToZip = items.map( ( item ) => { + const name = kebabCase( item.title || item.name ); + nameCount[ name ] = ( nameCount[ name ] || 0 ) + 1; + return { + name: `${ + name + + ( nameCount[ name ] > 1 + ? '-' + ( nameCount[ name ] - 1 ) + : '' ) + }.json`, + lastModified: new Date(), + input: getJsonFromItem( item ), + }; + } ); + return downloadBlob( + __( 'patterns-export' ) + '.zip', + await downloadZip( filesToZip ).blob(), + 'application/zip' + ); + }, +}; diff --git a/packages/editor/src/components/post-actions/export-pattern-as-json-action.native.js b/packages/editor/src/components/post-actions/export-pattern-as-json-action.native.js new file mode 100644 index 00000000000000..b09f5a034a5525 --- /dev/null +++ b/packages/editor/src/components/post-actions/export-pattern-as-json-action.native.js @@ -0,0 +1,4 @@ +// Client-zip is meant to be used in a browser and is therefore released as an ES6 module only, +// in order for the native build to succeed we are importing a null action and avoiding importing +// the non working in native context client-zip module. +export const exportPatternAsJSONAction = null; diff --git a/test/native/setup.js b/test/native/setup.js index c2fb8fca1c2b1c..4fd511f38e91b1 100644 --- a/test/native/setup.js +++ b/test/native/setup.js @@ -281,15 +281,6 @@ jest.mock( '@wordpress/compose', () => { }; } ); -/** - * client-zip is meant to be used in a browser and is therefore released as an ES6 module only, - * in order to use it in node environment, we need to mock it. - * See: https://github.com/Touffy/client-zip/issues/28 - */ -jest.mock( 'client-zip', () => ( { - downloadZip: jest.fn(), -} ) ); - jest.spyOn( Image, 'getSize' ).mockImplementation( ( url, success ) => success( 0, 0 ) );