diff --git a/package-lock.json b/package-lock.json index ec8abf0122ac3..73bb53a64eb80 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9997,6 +9997,7 @@ "check-node-version": "^3.1.1", "commander": "^4.1.0", "execa": "^4.0.0", + "fast-glob": "^2.2.7", "inquirer": "^7.1.0", "lodash": "^4.17.15", "make-dir": "^3.0.0", diff --git a/packages/create-block/CHANGELOG.md b/packages/create-block/CHANGELOG.md index 391c2822b2f5a..d36db25ccae88 100644 --- a/packages/create-block/CHANGELOG.md +++ b/packages/create-block/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Internal + +- Refactored handling of predefined block templates [#22235](https://github.com/WordPress/gutenberg/pull/22235). + ## 0.12.0 (2020-04-30) ### New Features diff --git a/packages/create-block/README.md b/packages/create-block/README.md index bd952cb515d4d..579511ae7b329 100644 --- a/packages/create-block/README.md +++ b/packages/create-block/README.md @@ -38,7 +38,7 @@ $ npm init @wordpress/block [options] [slug] Options: ``` -V, --version output the version number --t, --template template type name, allowed values: "es5", "esnext" (default: "esnext") +-t, --template block template type name, allowed values: "es5", "esnext" (default: "esnext") --namespace internal namespace for the block name --title display title for the block --short-description short description for the block diff --git a/packages/create-block/lib/index.js b/packages/create-block/lib/index.js index d4156437387bf..b87f08b97b4cc 100644 --- a/packages/create-block/lib/index.js +++ b/packages/create-block/lib/index.js @@ -13,7 +13,11 @@ const CLIError = require( './cli-error' ); const log = require( './log' ); const { engines, version } = require( '../package.json' ); const scaffold = require( './scaffold' ); -const { getDefaultValues, getPrompts } = require( './templates' ); +const { + getBlockTemplate, + getDefaultValues, + getPrompts, +} = require( './templates' ); const commandName = `wp-create-block`; program @@ -24,13 +28,13 @@ program 'it is used as the block slug used for its identification, the output ' + 'location for scaffolded files, and the name of the WordPress plugin.' + 'The rest of the configuration is set to all default values unless ' + - 'overriden with some of the options listed below.' + 'overridden with some of the options listed below.' ) .version( version ) .arguments( '[slug]' ) .option( '-t, --template ', - 'template type name, allowed values: "es5", "esnext"', + 'block template type name, allowed values: "es5", "esnext"', 'esnext' ) .option( '--namespace ', 'internal namespace for the block name' ) @@ -41,14 +45,21 @@ program .action( async ( slug, - { category, namespace, shortDescription, template, title } + { + category, + namespace, + shortDescription: description, + template: templateName, + title, + } ) => { await checkSystemRequirements( engines ); try { - const defaultValues = getDefaultValues( template ); + const blockTemplate = await getBlockTemplate( templateName ); + const defaultValues = getDefaultValues( blockTemplate ); const optionsValues = pickBy( { category, - description: shortDescription, + description, namespace, title, } ); @@ -60,14 +71,14 @@ program title: startCase( slug ), ...optionsValues, }; - await scaffold( template, answers ); + await scaffold( blockTemplate, answers ); } else { - const propmpts = getPrompts( template ).filter( + const prompts = getPrompts( blockTemplate ).filter( ( { name } ) => ! Object.keys( optionsValues ).includes( name ) ); - const answers = await inquirer.prompt( propmpts ); - await scaffold( template, { + const answers = await inquirer.prompt( prompts ); + await scaffold( blockTemplate, { ...defaultValues, ...optionsValues, ...answers, diff --git a/packages/create-block/lib/scaffold.js b/packages/create-block/lib/scaffold.js index be9b09588bde6..7ad53a1b623c6 100644 --- a/packages/create-block/lib/scaffold.js +++ b/packages/create-block/lib/scaffold.js @@ -1,21 +1,21 @@ /** * External dependencies */ -const { dirname, join } = require( 'path' ); +const { writeFile } = require( 'fs' ).promises; +const { snakeCase } = require( 'lodash' ); const makeDir = require( 'make-dir' ); -const { readFile, writeFile } = require( 'fs' ).promises; const { render } = require( 'mustache' ); -const { snakeCase } = require( 'lodash' ); +const { dirname } = require( 'path' ); /** * Internal dependencies */ const initWPScripts = require( './init-wp-scripts' ); const { code, info, success } = require( './log' ); -const { hasWPScriptsEnabled, getOutputFiles } = require( './templates' ); +const { hasWPScriptsEnabled } = require( './templates' ); module.exports = async function( - templateName, + blockTemplate, { namespace, slug, @@ -35,6 +35,7 @@ module.exports = async function( info( '' ); info( `Creating a new WordPress block in "${ slug }" folder.` ); + const { outputTemplates } = blockTemplate; const view = { namespace, namespaceSnakeCase: snakeCase( namespace ), @@ -51,25 +52,21 @@ module.exports = async function( textdomain: namespace, }; await Promise.all( - getOutputFiles( templateName ).map( async ( file ) => { - const template = await readFile( - join( - __dirname, - `templates/${ templateName }/${ file }.mustache` - ), - 'utf8' - ); + Object.keys( outputTemplates ).map( async ( outputFile ) => { // Output files can have names that depend on the slug provided. - const outputFilePath = `${ slug }/${ file.replace( + const outputFilePath = `${ slug }/${ outputFile.replace( /\$slug/g, slug ) }`; await makeDir( dirname( outputFilePath ) ); - writeFile( outputFilePath, render( template, view ) ); + writeFile( + outputFilePath, + render( outputTemplates[ outputFile ], view ) + ); } ) ); - if ( hasWPScriptsEnabled( templateName ) ) { + if ( hasWPScriptsEnabled( blockTemplate ) ) { await initWPScripts( view ); } @@ -77,7 +74,7 @@ module.exports = async function( success( `Done: block "${ title }" bootstrapped in the "${ slug }" folder.` ); - if ( hasWPScriptsEnabled( templateName ) ) { + if ( hasWPScriptsEnabled( blockTemplate ) ) { info( '' ); info( 'Inside that directory, you can run several commands:' ); info( '' ); diff --git a/packages/create-block/lib/templates.js b/packages/create-block/lib/templates.js index 7beadd7008cfe..683f9e3b3855b 100644 --- a/packages/create-block/lib/templates.js +++ b/packages/create-block/lib/templates.js @@ -1,91 +1,89 @@ +/** + * External dependencies + */ +const glob = require( 'fast-glob' ); +const { readFile } = require( 'fs' ).promises; +const { fromPairs } = require( 'lodash' ); +const { join } = require( 'path' ); + /** * Internal dependencies */ const CLIError = require( './cli-error' ); const prompts = require( './prompts' ); -const namespace = 'create-block'; -const dashicon = 'smiley'; -const category = 'widgets'; -const author = 'The WordPress Contributors'; -const license = 'GPL-2.0-or-later'; -const licenseURI = 'https://www.gnu.org/licenses/gpl-2.0.html'; -const version = '0.1.0'; - -const templates = { +const predefinedBlockTemplates = { es5: { defaultValues: { - namespace, slug: 'es5-example', title: 'ES5 Example', description: 'Example block written with ES5 standard and no JSX – no build step required.', - dashicon, - category, - author, - license, - licenseURI, - version, }, - outputFiles: [ - '.editorconfig', - 'editor.css', - 'index.js', - '$slug.php', - 'style.css', - 'readme.txt', - ], + wpScripts: false, }, esnext: { defaultValues: { - namespace, slug: 'esnext-example', title: 'ESNext Example', description: 'Example block written with ESNext standard and JSX support – build step required.', - dashicon, - category, - author, - license, - licenseURI, - version, }, - outputFiles: [ - '.editorconfig', - '.gitignore', - 'editor.css', - 'src/edit.js', - 'src/index.js', - 'src/save.js', - '$slug.php', - 'style.css', - 'readme.txt', - ], - wpScriptsEnabled: true, }, }; -const getTemplate = ( templateName ) => { - if ( ! templates[ templateName ] ) { +const getOutputTemplates = async ( name ) => { + const outputTemplatesPath = join( __dirname, 'templates', name ); + const outputTemplatesFiles = await glob( '**/*.mustache', { + cwd: outputTemplatesPath, + dot: true, + } ); + return fromPairs( + await Promise.all( + outputTemplatesFiles.map( async ( outputTemplateFile ) => { + const outputFile = outputTemplateFile.replace( + /\.mustache$/, + '' + ); + const outputTemplate = await readFile( + join( outputTemplatesPath, outputTemplateFile ), + 'utf8' + ); + return [ outputFile, outputTemplate ]; + } ) + ) + ); +}; + +const getBlockTemplate = async ( templateName ) => { + if ( ! predefinedBlockTemplates[ templateName ] ) { throw new CLIError( - `Invalid template type name. Allowed values: ${ Object.keys( - templates + `Invalid block template type name. Allowed values: ${ Object.keys( + predefinedBlockTemplates ).join( ', ' ) }.` ); } - return templates[ templateName ]; -}; - -const getDefaultValues = ( templateName ) => { - return getTemplate( templateName ).defaultValues; + return { + ...predefinedBlockTemplates[ templateName ], + outputTemplates: await getOutputTemplates( templateName ), + }; }; -const getOutputFiles = ( templateName ) => { - return getTemplate( templateName ).outputFiles; +const getDefaultValues = ( blockTemplate ) => { + return { + namespace: 'create-block', + dashicon: 'smiley', + category: 'widgets', + author: 'The WordPress Contributors', + license: 'GPL-2.0-or-later', + licenseURI: 'https://www.gnu.org/licenses/gpl-2.0.html', + version: '0.1.0', + ...blockTemplate.defaultValues, + }; }; -const getPrompts = ( templateName ) => { - const defaultValues = getDefaultValues( templateName ); +const getPrompts = ( blockTemplate ) => { + const defaultValues = getDefaultValues( blockTemplate ); return Object.keys( prompts ).map( ( promptName ) => { return { ...prompts[ promptName ], @@ -94,13 +92,13 @@ const getPrompts = ( templateName ) => { } ); }; -const hasWPScriptsEnabled = ( templateName ) => { - return getTemplate( templateName ).wpScriptsEnabled || false; +const hasWPScriptsEnabled = ( blockTemplate ) => { + return blockTemplate.wpScripts !== false; }; module.exports = { + getBlockTemplate, getDefaultValues, - getOutputFiles, getPrompts, hasWPScriptsEnabled, }; diff --git a/packages/create-block/package.json b/packages/create-block/package.json index 3b949c42fcd51..329a7fcc157f4 100644 --- a/packages/create-block/package.json +++ b/packages/create-block/package.json @@ -34,6 +34,7 @@ "check-node-version": "^3.1.1", "commander": "^4.1.0", "execa": "^4.0.0", + "fast-glob": "^2.2.7", "inquirer": "^7.1.0", "lodash": "^4.17.15", "make-dir": "^3.0.0",