From 48c7ee11281622ab506d2dd7e249f59315b61e2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Ka=CC=88gy?= Date: Thu, 30 Apr 2020 14:47:58 +0200 Subject: [PATCH 01/20] initial working implementation --- packages/create-block/lib/index.js | 8 ++- packages/create-block/lib/scaffold.js | 64 ++++++++++++----- packages/create-block/lib/templates.js | 98 +++++++++++++++++++++++--- 3 files changed, 137 insertions(+), 33 deletions(-) diff --git a/packages/create-block/lib/index.js b/packages/create-block/lib/index.js index d4156437387bf..317eb90d59f28 100644 --- a/packages/create-block/lib/index.js +++ b/packages/create-block/lib/index.js @@ -13,7 +13,7 @@ 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 { getDefaultValues, getPrompts, deleteFolderRecursive } = require( './templates' ); const commandName = `wp-create-block`; program @@ -45,7 +45,7 @@ program ) => { await checkSystemRequirements( engines ); try { - const defaultValues = getDefaultValues( template ); + const defaultValues = await getDefaultValues( template ); const optionsValues = pickBy( { category, description: shortDescription, @@ -62,7 +62,7 @@ program }; await scaffold( template, answers ); } else { - const propmpts = getPrompts( template ).filter( + const propmpts = await getPrompts( template ).filter( ( { name } ) => ! Object.keys( optionsValues ).includes( name ) ); @@ -73,6 +73,8 @@ program ...answers, } ); } + + deleteFolderRecursive( '/temp' ); } catch ( error ) { if ( error instanceof CLIError ) { log.error( error.message ); diff --git a/packages/create-block/lib/scaffold.js b/packages/create-block/lib/scaffold.js index be9b09588bde6..64239d4dc62c0 100644 --- a/packages/create-block/lib/scaffold.js +++ b/packages/create-block/lib/scaffold.js @@ -12,7 +12,7 @@ const { snakeCase } = require( 'lodash' ); */ const initWPScripts = require( './init-wp-scripts' ); const { code, info, success } = require( './log' ); -const { hasWPScriptsEnabled, getOutputFiles } = require( './templates' ); +const { hasWPScriptsEnabled, getOutputFiles, isCoreTemplate } = require( './templates' ); module.exports = async function( templateName, @@ -50,24 +50,50 @@ module.exports = async function( licenseURI, textdomain: namespace, }; - await Promise.all( - getOutputFiles( templateName ).map( async ( file ) => { - const template = await readFile( - join( - __dirname, - `templates/${ templateName }/${ file }.mustache` - ), - 'utf8' - ); - // Output files can have names that depend on the slug provided. - const outputFilePath = `${ slug }/${ file.replace( - /\$slug/g, - slug - ) }`; - await makeDir( dirname( outputFilePath ) ); - writeFile( outputFilePath, render( template, view ) ); - } ) - ); + + if ( await isCoreTemplate( templateName ) ) { + + await Promise.all( + (await getOutputFiles( templateName )).map( async ( file ) => { + const template = await readFile( + join( + __dirname, + `templates/${ templateName }/${ file }.mustache` + ), + 'utf8' + ); + // Output files can have names that depend on the slug provided. + const outputFilePath = `${ slug }/${ file.replace( + /\$slug/g, + slug + ) }`; + await makeDir( dirname( outputFilePath ) ); + writeFile( outputFilePath, render( template, view ) ); + } ) + ); + + } else { + + await Promise.all( + (await getOutputFiles( templateName )).map( async ( file ) => { + const template = await readFile( + join( + process.cwd(), + `temp/node_modules/${ templateName }/${ file }.mustache` + ), + 'utf8' + ); + // Output files can have names that depend on the slug provided. + const outputFilePath = `${ slug }/${ file.replace( + /\$slug/g, + slug + ) }`; + await makeDir( dirname( outputFilePath ) ); + writeFile( outputFilePath, render( template, view ) ); + } ) + ); + + } if ( hasWPScriptsEnabled( templateName ) ) { await initWPScripts( view ); diff --git a/packages/create-block/lib/templates.js b/packages/create-block/lib/templates.js index 7beadd7008cfe..3a797465ec6fb 100644 --- a/packages/create-block/lib/templates.js +++ b/packages/create-block/lib/templates.js @@ -3,6 +3,13 @@ */ const CLIError = require( './cli-error' ); const prompts = require( './prompts' ); +const { command } = require( 'execa' ); +const fs, { existsSync } = require( 'fs' ); +const path, { join } = require( 'path' ); +const { readFile } = require( 'fs' ).promises; +const makeDir = require( 'make-dir' ); + +const log = require( './log' ); const namespace = 'create-block'; const dashicon = 'smiley'; @@ -65,27 +72,41 @@ const templates = { }, }; -const getTemplate = ( templateName ) => { - if ( ! templates[ templateName ] ) { +const getTemplate = async ( templateName ) => { + + if ( await isCoreTemplate( templateName ) ) { + return templates[ templateName ]; + } + + // throw a CLIError if the the template is neither a core one nor an external one + if ( ! await isExternalTemplate( templateName ) && ! await isCoreTemplate( templateName ) ) { throw new CLIError( - `Invalid template type name. Allowed values: ${ Object.keys( + `Invalid template type name. Either use one of the Core templates: ${ Object.keys( templates - ).join( ', ' ) }.` + ).join( ', ' ) }. \n \n or a valid npm package name.` ); } - return templates[ templateName ]; + + await downloadExternalTemplate( templateName ); + + const rawPackageInfo = await readFile( join( process.cwd(), 'temp', 'node_modules', templateName, 'template.json' ) ); + const packageInfo = JSON.parse( rawPackageInfo ); + return packageInfo; + }; -const getDefaultValues = ( templateName ) => { - return getTemplate( templateName ).defaultValues; +const getDefaultValues = async ( templateName ) => { + const template = await getTemplate( templateName ); + return template.defaultValues; }; -const getOutputFiles = ( templateName ) => { - return getTemplate( templateName ).outputFiles; +const getOutputFiles = async ( templateName ) => { + const template = await getTemplate( templateName ); + return template.outputFiles; }; -const getPrompts = ( templateName ) => { - const defaultValues = getDefaultValues( templateName ); +const getPrompts = async ( templateName ) => { + const defaultValues = await getDefaultValues( templateName ); return Object.keys( prompts ).map( ( promptName ) => { return { ...prompts[ promptName ], @@ -98,9 +119,64 @@ const hasWPScriptsEnabled = ( templateName ) => { return getTemplate( templateName ).wpScriptsEnabled || false; }; +const isCoreTemplate = async templateName => templates[ templateName ] || false; + +const isExternalTemplate = async templateName => { + try { + await command( `npm view ${ templateName }` ); + return true; + } catch ( error ) { + return false; + } +} + +const downloadExternalTemplate = async templateName => { + try { + const cwd = join( process.cwd(), 'temp' ); + + if ( existsSync( join( cwd, 'node_modules', templateName ) ) ) { + return true; + }; + + // mkdir temp + await makeDir( cwd ); + + // npm init + await command( 'npm init -y', {cwd} ); + + // npm install my-template --save + await command( `npm install ${templateName} --save`, {cwd} ); + + return true; + + } catch ( error ) { + log.error( 'There has been an error:' ); + log.error( error ); + return false; + } +} + + +const deleteFolderRecursive = function(path) { + if (fs.existsSync(path)) { + fs.readdirSync(path).forEach((file, index) => { + const curPath = Path.join(path, file); + if (fs.lstatSync(curPath).isDirectory()) { // recurse + deleteFolderRecursive(curPath); + } else { // delete file + fs.unlinkSync(curPath); + } + }); + fs.rmdirSync(path); + } +}; + module.exports = { getDefaultValues, getOutputFiles, getPrompts, hasWPScriptsEnabled, + isCoreTemplate, + isExternalTemplate, + deleteFolderRecursive, }; From 14611a361c3f2125ee3fc8ffd5d8cba6e85756db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Ka=CC=88gy?= Date: Thu, 30 Apr 2020 14:57:11 +0200 Subject: [PATCH 02/20] cleanup functions --- packages/create-block/lib/index.js | 4 +- packages/create-block/lib/scaffold.js | 61 +++++++++----------------- packages/create-block/lib/templates.js | 20 +-------- 3 files changed, 24 insertions(+), 61 deletions(-) diff --git a/packages/create-block/lib/index.js b/packages/create-block/lib/index.js index 317eb90d59f28..e8a178090bbcf 100644 --- a/packages/create-block/lib/index.js +++ b/packages/create-block/lib/index.js @@ -3,6 +3,7 @@ */ const inquirer = require( 'inquirer' ); const program = require( 'commander' ); +const { join } = require( 'path' ); const { pickBy, startCase } = require( 'lodash' ); /** @@ -13,7 +14,7 @@ const CLIError = require( './cli-error' ); const log = require( './log' ); const { engines, version } = require( '../package.json' ); const scaffold = require( './scaffold' ); -const { getDefaultValues, getPrompts, deleteFolderRecursive } = require( './templates' ); +const { getDefaultValues, getPrompts } = require( './templates' ); const commandName = `wp-create-block`; program @@ -74,7 +75,6 @@ program } ); } - deleteFolderRecursive( '/temp' ); } catch ( error ) { if ( error instanceof CLIError ) { log.error( error.message ); diff --git a/packages/create-block/lib/scaffold.js b/packages/create-block/lib/scaffold.js index 64239d4dc62c0..9273ce3d5c7f1 100644 --- a/packages/create-block/lib/scaffold.js +++ b/packages/create-block/lib/scaffold.js @@ -51,49 +51,28 @@ module.exports = async function( textdomain: namespace, }; - if ( await isCoreTemplate( templateName ) ) { + const coreTemplate = await isCoreTemplate( templateName ); - await Promise.all( - (await getOutputFiles( templateName )).map( async ( file ) => { - const template = await readFile( - join( - __dirname, - `templates/${ templateName }/${ file }.mustache` - ), - 'utf8' - ); - // Output files can have names that depend on the slug provided. - const outputFilePath = `${ slug }/${ file.replace( - /\$slug/g, - slug - ) }`; - await makeDir( dirname( outputFilePath ) ); - writeFile( outputFilePath, render( template, view ) ); - } ) - ); + const templateDirectory = coreTemplate ? join( __dirname, 'templates' ) : join( process.cwd(), "temp", "node_modules" ); - } else { - - await Promise.all( - (await getOutputFiles( templateName )).map( async ( file ) => { - const template = await readFile( - join( - process.cwd(), - `temp/node_modules/${ templateName }/${ file }.mustache` - ), - 'utf8' - ); - // Output files can have names that depend on the slug provided. - const outputFilePath = `${ slug }/${ file.replace( - /\$slug/g, - slug - ) }`; - await makeDir( dirname( outputFilePath ) ); - writeFile( outputFilePath, render( template, view ) ); - } ) - ); - - } + await Promise.all( + (await getOutputFiles( templateName )).map( async ( file ) => { + const template = await readFile( + join( + templateDirectory, + `${ templateName }/${ file }.mustache` + ), + 'utf8' + ); + // Output files can have names that depend on the slug provided. + const outputFilePath = `${ slug }/${ file.replace( + /\$slug/g, + slug + ) }`; + await makeDir( dirname( outputFilePath ) ); + writeFile( outputFilePath, render( template, view ) ); + } ) + ); if ( hasWPScriptsEnabled( templateName ) ) { await initWPScripts( view ); diff --git a/packages/create-block/lib/templates.js b/packages/create-block/lib/templates.js index 3a797465ec6fb..d7cad3e0dee8c 100644 --- a/packages/create-block/lib/templates.js +++ b/packages/create-block/lib/templates.js @@ -4,8 +4,8 @@ const CLIError = require( './cli-error' ); const prompts = require( './prompts' ); const { command } = require( 'execa' ); -const fs, { existsSync } = require( 'fs' ); -const path, { join } = require( 'path' ); +const { existsSync, readdirSync, lstatSync, unlinkSync, rmdirSync } = require( 'fs' ); +const { join } = require( 'path' ); const { readFile } = require( 'fs' ).promises; const makeDir = require( 'make-dir' ); @@ -156,21 +156,6 @@ const downloadExternalTemplate = async templateName => { } } - -const deleteFolderRecursive = function(path) { - if (fs.existsSync(path)) { - fs.readdirSync(path).forEach((file, index) => { - const curPath = Path.join(path, file); - if (fs.lstatSync(curPath).isDirectory()) { // recurse - deleteFolderRecursive(curPath); - } else { // delete file - fs.unlinkSync(curPath); - } - }); - fs.rmdirSync(path); - } -}; - module.exports = { getDefaultValues, getOutputFiles, @@ -178,5 +163,4 @@ module.exports = { hasWPScriptsEnabled, isCoreTemplate, isExternalTemplate, - deleteFolderRecursive, }; From 3714b20c49f48b4e9f8707ff800e604125f4a2a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Ka=CC=88gy?= Date: Fri, 8 May 2020 06:50:36 +0200 Subject: [PATCH 03/20] fix getPrompts --- packages/create-block/lib/index.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/create-block/lib/index.js b/packages/create-block/lib/index.js index e8a178090bbcf..867b8ae134aff 100644 --- a/packages/create-block/lib/index.js +++ b/packages/create-block/lib/index.js @@ -3,7 +3,6 @@ */ const inquirer = require( 'inquirer' ); const program = require( 'commander' ); -const { join } = require( 'path' ); const { pickBy, startCase } = require( 'lodash' ); /** @@ -63,11 +62,12 @@ program }; await scaffold( template, answers ); } else { - const propmpts = await getPrompts( template ).filter( + const propmpts = await getPrompts( template ); + const filteredPrompts = propmpts.filter( ( { name } ) => ! Object.keys( optionsValues ).includes( name ) ); - const answers = await inquirer.prompt( propmpts ); + const answers = await inquirer.prompt( filteredPrompts ); await scaffold( template, { ...defaultValues, ...optionsValues, From b0b617f93023c6d2c58f394d58b00fd431f86bfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Ka=CC=88gy?= Date: Fri, 8 May 2020 06:51:00 +0200 Subject: [PATCH 04/20] fix improve error message --- packages/create-block/lib/templates.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/create-block/lib/templates.js b/packages/create-block/lib/templates.js index d7cad3e0dee8c..1a13809dfa004 100644 --- a/packages/create-block/lib/templates.js +++ b/packages/create-block/lib/templates.js @@ -4,7 +4,7 @@ const CLIError = require( './cli-error' ); const prompts = require( './prompts' ); const { command } = require( 'execa' ); -const { existsSync, readdirSync, lstatSync, unlinkSync, rmdirSync } = require( 'fs' ); +const { existsSync } = require( 'fs' ); const { join } = require( 'path' ); const { readFile } = require( 'fs' ).promises; const makeDir = require( 'make-dir' ); @@ -150,7 +150,7 @@ const downloadExternalTemplate = async templateName => { return true; } catch ( error ) { - log.error( 'There has been an error:' ); + log.error( 'There has been an error while trying to download the package from NPM:' ); log.error( error ); return false; } From e81dd272eb80a36161380512e19a9ef2a49577ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Ka=CC=88gy?= Date: Fri, 8 May 2020 07:00:03 +0200 Subject: [PATCH 05/20] add template to prompts --- packages/create-block/lib/index.js | 3 ++- packages/create-block/lib/prompts.js | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/packages/create-block/lib/index.js b/packages/create-block/lib/index.js index 867b8ae134aff..6cc596ca5240d 100644 --- a/packages/create-block/lib/index.js +++ b/packages/create-block/lib/index.js @@ -68,7 +68,8 @@ program ! Object.keys( optionsValues ).includes( name ) ); const answers = await inquirer.prompt( filteredPrompts ); - await scaffold( template, { + + await scaffold( answers.template, { ...defaultValues, ...optionsValues, ...answers, diff --git a/packages/create-block/lib/prompts.js b/packages/create-block/lib/prompts.js index 5624f984f8292..1501235859674 100644 --- a/packages/create-block/lib/prompts.js +++ b/packages/create-block/lib/prompts.js @@ -17,6 +17,20 @@ const slug = { }, }; +const template = { + type: 'input', + name: 'template', + message: + 'The template used to scaffold the block (es5 | esnext | name of a npm repository)', + validate( input ) { + if ( ! /^[a-z][a-z0-9\-]*$/.test( input ) ) { + return 'Invalid block template name specified. Template can contain only lowercase alphanumeric characters or dashes, and start with a letter.'; + } + + return true; + } +} + const namespace = { type: 'input', name: 'namespace', @@ -109,6 +123,7 @@ const version = { module.exports = { slug, + template, namespace, title, description, From db935987ab74c20fc21fe73171d85e10bc3f2565 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Ka=CC=88gy?= Date: Fri, 8 May 2020 07:06:05 +0200 Subject: [PATCH 06/20] fix remove unneccecary call of checkIsCoreTemplate --- packages/create-block/lib/scaffold.js | 4 ++-- packages/create-block/lib/templates.js | 13 +++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/create-block/lib/scaffold.js b/packages/create-block/lib/scaffold.js index 9273ce3d5c7f1..44ba6a2db3a50 100644 --- a/packages/create-block/lib/scaffold.js +++ b/packages/create-block/lib/scaffold.js @@ -12,7 +12,7 @@ const { snakeCase } = require( 'lodash' ); */ const initWPScripts = require( './init-wp-scripts' ); const { code, info, success } = require( './log' ); -const { hasWPScriptsEnabled, getOutputFiles, isCoreTemplate } = require( './templates' ); +const { hasWPScriptsEnabled, getOutputFiles, checkIsCoreTemplate } = require( './templates' ); module.exports = async function( templateName, @@ -51,7 +51,7 @@ module.exports = async function( textdomain: namespace, }; - const coreTemplate = await isCoreTemplate( templateName ); + const coreTemplate = await checkIsCoreTemplate( templateName ); const templateDirectory = coreTemplate ? join( __dirname, 'templates' ) : join( process.cwd(), "temp", "node_modules" ); diff --git a/packages/create-block/lib/templates.js b/packages/create-block/lib/templates.js index 1a13809dfa004..47df87bc1b3c9 100644 --- a/packages/create-block/lib/templates.js +++ b/packages/create-block/lib/templates.js @@ -74,12 +74,13 @@ const templates = { const getTemplate = async ( templateName ) => { - if ( await isCoreTemplate( templateName ) ) { + const isCoreTemplate = await checkIsCoreTemplate( templateName ); + if ( isCoreTemplate ) { return templates[ templateName ]; } // throw a CLIError if the the template is neither a core one nor an external one - if ( ! await isExternalTemplate( templateName ) && ! await isCoreTemplate( templateName ) ) { + if ( ! await checkIsExternalTemplate( templateName ) && ! isCoreTemplate ) { throw new CLIError( `Invalid template type name. Either use one of the Core templates: ${ Object.keys( templates @@ -119,9 +120,9 @@ const hasWPScriptsEnabled = ( templateName ) => { return getTemplate( templateName ).wpScriptsEnabled || false; }; -const isCoreTemplate = async templateName => templates[ templateName ] || false; +const checkIsCoreTemplate = async templateName => templates[ templateName ] || false; -const isExternalTemplate = async templateName => { +const checkIsExternalTemplate = async templateName => { try { await command( `npm view ${ templateName }` ); return true; @@ -161,6 +162,6 @@ module.exports = { getOutputFiles, getPrompts, hasWPScriptsEnabled, - isCoreTemplate, - isExternalTemplate, + checkIsCoreTemplate, + checkIsExternalTemplate, }; From 4b55cdfe50f8dc526535719e10c5a9b4c85ecd35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Ka=CC=88gy?= Date: Fri, 8 May 2020 07:19:42 +0200 Subject: [PATCH 07/20] add documentation for external package support --- packages/create-block/README.md | 53 +++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/packages/create-block/README.md b/packages/create-block/README.md index bd952cb515d4d..10a8df5fd54f9 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 template name: "es5", "esnext" or the name of an external npm package (default: "esnext") --namespace internal namespace for the block name --title display title for the block --short-description short description for the block @@ -65,9 +65,9 @@ More examples: When you scaffold a block, you must provide at least a `slug` name, the `namespace` which usually corresponds to either the `theme` or `plugin` name, and the `category`. In most cases, we recommended pairing blocks with plugins rather than themes, because only using plugin ensures that all blocks still work when your theme changes. -## Available Commands +## Available Commands [ESNext template] -Inside that bootstrapped directory _(it doesn't apply to `es5` template)_, you can run several commands: +When bootstraped with the `esnext` templateyou can run several commands inside the directory: ```bash $ npm start @@ -99,6 +99,53 @@ $ npm run packages-update ``` Updates WordPress packages to the latest version. [Learn more](/packages/scripts#packages-update). +## External Templates +Since version 0.12.0 it is possible to use external templates hosted on NPM. These templates need to contain `.mustache` files that will be used in the scaffolding and one `template.json` for the metadata. + +### Availabe Variables: +- `namespace` +- `slug` +- `title` +- `textdomain` +- `description` +- `category` +- `dashicon` +- `license` +- `licenseURI` +- `namespaceSnakeCase` +- `slugSnakeCase` + +### `template.json` +```json +{ + "defaultValues": { + "namespace": "create-block", + "slug": "esnext-example", + "title": "ESNext Example", + "description": + "Example block written with ESNext standard and JSX support – build step required.", + "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" + }, + "outputFiles": [ + ".editorconfig", + ".gitignore", + "editor.css", + "src/edit.js", + "src/index.js", + "src/save.js", + "$slug.php", + "style.css", + "readme.txt" + ], + "wpScriptsEnabled": true +} +``` + ## WP-CLI Another way of making a developer’s life easier is to use [WP-CLI](https://wp-cli.org), which provides a command-line interface for many actions you might perform on the WordPress instance. One of the commands `wp scaffold block` was used as the baseline for this tool and ES5 template in particular. From 62811e37bc6b705afff3c42315befa24136cc3f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Ka=CC=88gy?= Date: Fri, 8 May 2020 11:09:10 +0200 Subject: [PATCH 08/20] fix linting errors --- packages/create-block/lib/index.js | 1 - packages/create-block/lib/prompts.js | 4 +-- packages/create-block/lib/scaffold.js | 12 ++++++-- packages/create-block/lib/templates.js | 41 ++++++++++++++++---------- 4 files changed, 37 insertions(+), 21 deletions(-) diff --git a/packages/create-block/lib/index.js b/packages/create-block/lib/index.js index 6cc596ca5240d..6d46223707635 100644 --- a/packages/create-block/lib/index.js +++ b/packages/create-block/lib/index.js @@ -75,7 +75,6 @@ program ...answers, } ); } - } catch ( error ) { if ( error instanceof CLIError ) { log.error( error.message ); diff --git a/packages/create-block/lib/prompts.js b/packages/create-block/lib/prompts.js index 1501235859674..7e677e666ef94 100644 --- a/packages/create-block/lib/prompts.js +++ b/packages/create-block/lib/prompts.js @@ -28,8 +28,8 @@ const template = { } return true; - } -} + }, +}; const namespace = { type: 'input', diff --git a/packages/create-block/lib/scaffold.js b/packages/create-block/lib/scaffold.js index 44ba6a2db3a50..9bcee5dad9a76 100644 --- a/packages/create-block/lib/scaffold.js +++ b/packages/create-block/lib/scaffold.js @@ -12,7 +12,11 @@ const { snakeCase } = require( 'lodash' ); */ const initWPScripts = require( './init-wp-scripts' ); const { code, info, success } = require( './log' ); -const { hasWPScriptsEnabled, getOutputFiles, checkIsCoreTemplate } = require( './templates' ); +const { + hasWPScriptsEnabled, + getOutputFiles, + checkIsCoreTemplate, +} = require( './templates' ); module.exports = async function( templateName, @@ -53,10 +57,12 @@ module.exports = async function( const coreTemplate = await checkIsCoreTemplate( templateName ); - const templateDirectory = coreTemplate ? join( __dirname, 'templates' ) : join( process.cwd(), "temp", "node_modules" ); + const templateDirectory = coreTemplate + ? join( __dirname, 'templates' ) + : join( process.cwd(), 'temp', 'node_modules' ); await Promise.all( - (await getOutputFiles( templateName )).map( async ( file ) => { + ( await getOutputFiles( templateName ) ).map( async ( file ) => { const template = await readFile( join( templateDirectory, diff --git a/packages/create-block/lib/templates.js b/packages/create-block/lib/templates.js index 47df87bc1b3c9..1dc0588591b73 100644 --- a/packages/create-block/lib/templates.js +++ b/packages/create-block/lib/templates.js @@ -4,7 +4,7 @@ const CLIError = require( './cli-error' ); const prompts = require( './prompts' ); const { command } = require( 'execa' ); -const { existsSync } = require( 'fs' ); +const { existsSync } = require( 'fs' ); const { join } = require( 'path' ); const { readFile } = require( 'fs' ).promises; const makeDir = require( 'make-dir' ); @@ -73,14 +73,16 @@ const templates = { }; const getTemplate = async ( templateName ) => { - const isCoreTemplate = await checkIsCoreTemplate( templateName ); if ( isCoreTemplate ) { return templates[ templateName ]; } // throw a CLIError if the the template is neither a core one nor an external one - if ( ! await checkIsExternalTemplate( templateName ) && ! isCoreTemplate ) { + if ( + ! ( await checkIsExternalTemplate( templateName ) ) && + ! isCoreTemplate + ) { throw new CLIError( `Invalid template type name. Either use one of the Core templates: ${ Object.keys( templates @@ -90,10 +92,17 @@ const getTemplate = async ( templateName ) => { await downloadExternalTemplate( templateName ); - const rawPackageInfo = await readFile( join( process.cwd(), 'temp', 'node_modules', templateName, 'template.json' ) ); + const rawPackageInfo = await readFile( + join( + process.cwd(), + 'temp', + 'node_modules', + templateName, + 'template.json' + ) + ); const packageInfo = JSON.parse( rawPackageInfo ); return packageInfo; - }; const getDefaultValues = async ( templateName ) => { @@ -120,42 +129,44 @@ const hasWPScriptsEnabled = ( templateName ) => { return getTemplate( templateName ).wpScriptsEnabled || false; }; -const checkIsCoreTemplate = async templateName => templates[ templateName ] || false; +const checkIsCoreTemplate = async ( templateName ) => + templates[ templateName ] || false; -const checkIsExternalTemplate = async templateName => { +const checkIsExternalTemplate = async ( templateName ) => { try { await command( `npm view ${ templateName }` ); return true; } catch ( error ) { return false; } -} +}; -const downloadExternalTemplate = async templateName => { +const downloadExternalTemplate = async ( templateName ) => { try { const cwd = join( process.cwd(), 'temp' ); if ( existsSync( join( cwd, 'node_modules', templateName ) ) ) { return true; - }; + } // mkdir temp await makeDir( cwd ); // npm init - await command( 'npm init -y', {cwd} ); + await command( 'npm init -y', { cwd } ); // npm install my-template --save - await command( `npm install ${templateName} --save`, {cwd} ); + await command( `npm install ${ templateName } --save`, { cwd } ); return true; - } catch ( error ) { - log.error( 'There has been an error while trying to download the package from NPM:' ); + log.error( + 'There has been an error while trying to download the package from NPM:' + ); log.error( error ); return false; } -} +}; module.exports = { getDefaultValues, From 11072bf800ea83a039219594835c4f8586136eaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Ka=CC=88gy?= Date: Fri, 8 May 2020 11:22:12 +0200 Subject: [PATCH 09/20] fix suggetions from @gziolo --- packages/create-block/lib/scaffold.js | 6 +-- packages/create-block/lib/templates.js | 62 ++++++++++++-------------- packages/create-block/package.json | 1 + 3 files changed, 32 insertions(+), 37 deletions(-) diff --git a/packages/create-block/lib/scaffold.js b/packages/create-block/lib/scaffold.js index 9bcee5dad9a76..805a44bf08e39 100644 --- a/packages/create-block/lib/scaffold.js +++ b/packages/create-block/lib/scaffold.js @@ -15,7 +15,7 @@ const { code, info, success } = require( './log' ); const { hasWPScriptsEnabled, getOutputFiles, - checkIsCoreTemplate, + isCoreTemplate, } = require( './templates' ); module.exports = async function( @@ -55,9 +55,7 @@ module.exports = async function( textdomain: namespace, }; - const coreTemplate = await checkIsCoreTemplate( templateName ); - - const templateDirectory = coreTemplate + const templateDirectory = isCoreTemplate( templateName ) ? join( __dirname, 'templates' ) : join( process.cwd(), 'temp', 'node_modules' ); diff --git a/packages/create-block/lib/templates.js b/packages/create-block/lib/templates.js index 1dc0588591b73..fa831d5a2af62 100644 --- a/packages/create-block/lib/templates.js +++ b/packages/create-block/lib/templates.js @@ -8,6 +8,8 @@ const { existsSync } = require( 'fs' ); const { join } = require( 'path' ); const { readFile } = require( 'fs' ).promises; const makeDir = require( 'make-dir' ); +const os = require( 'os' ); +const { v4: uuid } = require( 'uuid' ); const log = require( './log' ); @@ -19,7 +21,7 @@ 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 coreTemplates = { es5: { defaultValues: { namespace, @@ -72,36 +74,24 @@ const templates = { }, }; +const tempFolder = join( os.tmpdir(), uuid() ); + const getTemplate = async ( templateName ) => { - const isCoreTemplate = await checkIsCoreTemplate( templateName ); - if ( isCoreTemplate ) { - return templates[ templateName ]; + if ( coreTemplates[ templateName ] ) { + return coreTemplates[ templateName ]; } // throw a CLIError if the the template is neither a core one nor an external one - if ( - ! ( await checkIsExternalTemplate( templateName ) ) && - ! isCoreTemplate - ) { + if ( ! ( await isExternalTemplate( templateName ) ) ) { throw new CLIError( `Invalid template type name. Either use one of the Core templates: ${ Object.keys( - templates + coreTemplates ).join( ', ' ) }. \n \n or a valid npm package name.` ); } - await downloadExternalTemplate( templateName ); - - const rawPackageInfo = await readFile( - join( - process.cwd(), - 'temp', - 'node_modules', - templateName, - 'template.json' - ) - ); - const packageInfo = JSON.parse( rawPackageInfo ); + const packageInfo = await downloadExternalTemplate( templateName ); + return packageInfo; }; @@ -129,10 +119,10 @@ const hasWPScriptsEnabled = ( templateName ) => { return getTemplate( templateName ).wpScriptsEnabled || false; }; -const checkIsCoreTemplate = async ( templateName ) => - templates[ templateName ] || false; +const isCoreTemplate = ( templateName ) => + coreTemplates[ templateName ] || false; -const checkIsExternalTemplate = async ( templateName ) => { +const isExternalTemplate = async ( templateName ) => { try { await command( `npm view ${ templateName }` ); return true; @@ -143,22 +133,28 @@ const checkIsExternalTemplate = async ( templateName ) => { const downloadExternalTemplate = async ( templateName ) => { try { - const cwd = join( process.cwd(), 'temp' ); + const cwd = tempFolder; if ( existsSync( join( cwd, 'node_modules', templateName ) ) ) { return true; } - // mkdir temp await makeDir( cwd ); - - // npm init await command( 'npm init -y', { cwd } ); - - // npm install my-template --save await command( `npm install ${ templateName } --save`, { cwd } ); - return true; + const rawPackageInfo = await readFile( + join( + process.cwd(), + 'temp', + 'node_modules', + templateName, + 'template.json' + ) + ); + const packageInfo = JSON.parse( rawPackageInfo ); + + return packageInfo; } catch ( error ) { log.error( 'There has been an error while trying to download the package from NPM:' @@ -173,6 +169,6 @@ module.exports = { getOutputFiles, getPrompts, hasWPScriptsEnabled, - checkIsCoreTemplate, - checkIsExternalTemplate, + isCoreTemplate, + isExternalTemplate, }; diff --git a/packages/create-block/package.json b/packages/create-block/package.json index 7d39d685f51d4..a783f4b4d8530 100644 --- a/packages/create-block/package.json +++ b/packages/create-block/package.json @@ -38,6 +38,7 @@ "lodash": "^4.17.15", "make-dir": "^3.0.0", "mustache": "^4.0.0", + "uuid": "^8.0.0", "write-pkg": "^4.0.0" }, "publishConfig": { From 7036078170d9510006b3b0296f232918c1fbe4f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Ka=CC=88gy?= Date: Fri, 8 May 2020 11:28:38 +0200 Subject: [PATCH 10/20] remove template from prompts --- packages/create-block/lib/index.js | 2 +- packages/create-block/lib/prompts.js | 15 --------------- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/packages/create-block/lib/index.js b/packages/create-block/lib/index.js index 6d46223707635..43fd7d7963cb6 100644 --- a/packages/create-block/lib/index.js +++ b/packages/create-block/lib/index.js @@ -69,7 +69,7 @@ program ); const answers = await inquirer.prompt( filteredPrompts ); - await scaffold( answers.template, { + await scaffold( template, { ...defaultValues, ...optionsValues, ...answers, diff --git a/packages/create-block/lib/prompts.js b/packages/create-block/lib/prompts.js index 7e677e666ef94..5624f984f8292 100644 --- a/packages/create-block/lib/prompts.js +++ b/packages/create-block/lib/prompts.js @@ -17,20 +17,6 @@ const slug = { }, }; -const template = { - type: 'input', - name: 'template', - message: - 'The template used to scaffold the block (es5 | esnext | name of a npm repository)', - validate( input ) { - if ( ! /^[a-z][a-z0-9\-]*$/.test( input ) ) { - return 'Invalid block template name specified. Template can contain only lowercase alphanumeric characters or dashes, and start with a letter.'; - } - - return true; - }, -}; - const namespace = { type: 'input', name: 'namespace', @@ -123,7 +109,6 @@ const version = { module.exports = { slug, - template, namespace, title, description, From 4b0b246f97e8b075ef1df48eddb664c951693413 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Ka=CC=88gy?= Date: Sat, 9 May 2020 18:42:54 +0200 Subject: [PATCH 11/20] fix use correct temp folder across the board --- packages/create-block/lib/scaffold.js | 32 +++++++++++--------------- packages/create-block/lib/templates.js | 21 ++++++++++------- 2 files changed, 26 insertions(+), 27 deletions(-) diff --git a/packages/create-block/lib/scaffold.js b/packages/create-block/lib/scaffold.js index 805a44bf08e39..321c41995c292 100644 --- a/packages/create-block/lib/scaffold.js +++ b/packages/create-block/lib/scaffold.js @@ -16,6 +16,7 @@ const { hasWPScriptsEnabled, getOutputFiles, isCoreTemplate, + tempFolder, } = require( './templates' ); module.exports = async function( @@ -57,26 +58,19 @@ module.exports = async function( const templateDirectory = isCoreTemplate( templateName ) ? join( __dirname, 'templates' ) - : join( process.cwd(), 'temp', 'node_modules' ); + : join( tempFolder, 'node_modules' ); - await Promise.all( - ( await getOutputFiles( templateName ) ).map( async ( file ) => { - const template = await readFile( - join( - templateDirectory, - `${ templateName }/${ file }.mustache` - ), - 'utf8' - ); - // Output files can have names that depend on the slug provided. - const outputFilePath = `${ slug }/${ file.replace( - /\$slug/g, - slug - ) }`; - await makeDir( dirname( outputFilePath ) ); - writeFile( outputFilePath, render( template, view ) ); - } ) - ); + const outputFiles = await getOutputFiles( templateName ); + outputFiles.map( async ( file ) => { + const template = await readFile( + join( templateDirectory, `${ templateName }/${ file }.mustache` ), + 'utf8' + ); + // Output files can have names that depend on the slug provided. + const outputFilePath = `${ slug }/${ file.replace( /\$slug/g, slug ) }`; + await makeDir( dirname( outputFilePath ) ); + writeFile( outputFilePath, render( template, view ) ); + } ); if ( hasWPScriptsEnabled( templateName ) ) { await initWPScripts( view ); diff --git a/packages/create-block/lib/templates.js b/packages/create-block/lib/templates.js index fa831d5a2af62..5efa586e454c5 100644 --- a/packages/create-block/lib/templates.js +++ b/packages/create-block/lib/templates.js @@ -136,7 +136,17 @@ const downloadExternalTemplate = async ( templateName ) => { const cwd = tempFolder; if ( existsSync( join( cwd, 'node_modules', templateName ) ) ) { - return true; + const rawPackageInfo = await readFile( + join( + tempFolder, + 'node_modules', + templateName, + 'template.json' + ) + ); + const packageInfo = JSON.parse( rawPackageInfo ); + + return packageInfo; } await makeDir( cwd ); @@ -144,13 +154,7 @@ const downloadExternalTemplate = async ( templateName ) => { await command( `npm install ${ templateName } --save`, { cwd } ); const rawPackageInfo = await readFile( - join( - process.cwd(), - 'temp', - 'node_modules', - templateName, - 'template.json' - ) + join( tempFolder, 'node_modules', templateName, 'template.json' ) ); const packageInfo = JSON.parse( rawPackageInfo ); @@ -171,4 +175,5 @@ module.exports = { hasWPScriptsEnabled, isCoreTemplate, isExternalTemplate, + tempFolder, }; From 86f7327bbbc486a06a0e8e9998aa0b37e191e5c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Ka=CC=88gy?= Date: Sat, 9 May 2020 22:02:26 +0200 Subject: [PATCH 12/20] fix remove temp folder after done with scaffold --- packages/create-block/lib/scaffold.js | 3 +++ packages/create-block/package.json | 1 + 2 files changed, 4 insertions(+) diff --git a/packages/create-block/lib/scaffold.js b/packages/create-block/lib/scaffold.js index 321c41995c292..ba099380a527c 100644 --- a/packages/create-block/lib/scaffold.js +++ b/packages/create-block/lib/scaffold.js @@ -6,6 +6,7 @@ const makeDir = require( 'make-dir' ); const { readFile, writeFile } = require( 'fs' ).promises; const { render } = require( 'mustache' ); const { snakeCase } = require( 'lodash' ); +const raimraf = require( 'rimraf' ).sync; /** * Internal dependencies @@ -76,6 +77,8 @@ module.exports = async function( await initWPScripts( view ); } + raimraf( tempFolder ); + info( '' ); success( `Done: block "${ title }" bootstrapped in the "${ slug }" folder.` diff --git a/packages/create-block/package.json b/packages/create-block/package.json index a783f4b4d8530..b3f5188f4c670 100644 --- a/packages/create-block/package.json +++ b/packages/create-block/package.json @@ -38,6 +38,7 @@ "lodash": "^4.17.15", "make-dir": "^3.0.0", "mustache": "^4.0.0", + "rimraf": "^3.0.2", "uuid": "^8.0.0", "write-pkg": "^4.0.0" }, From 083a990cbe04846b9924d52168cd79839832e268 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Ka=CC=88gy?= Date: Sat, 9 May 2020 22:37:26 +0200 Subject: [PATCH 13/20] fix hasWPScriptsEnabled to be async --- packages/create-block/lib/scaffold.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/create-block/lib/scaffold.js b/packages/create-block/lib/scaffold.js index ba099380a527c..c122400fe0d6b 100644 --- a/packages/create-block/lib/scaffold.js +++ b/packages/create-block/lib/scaffold.js @@ -73,7 +73,8 @@ module.exports = async function( writeFile( outputFilePath, render( template, view ) ); } ); - if ( hasWPScriptsEnabled( templateName ) ) { + const wpScriptsEnabled = await hasWPScriptsEnabled( templateName ); + if ( wpScriptsEnabled ) { await initWPScripts( view ); } @@ -83,7 +84,7 @@ module.exports = async function( success( `Done: block "${ title }" bootstrapped in the "${ slug }" folder.` ); - if ( hasWPScriptsEnabled( templateName ) ) { + if ( wpScriptsEnabled ) { info( '' ); info( 'Inside that directory, you can run several commands:' ); info( '' ); From ea9dc1b309d6b632f4f08f0325bd055e0c2b4719 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Ka=CC=88gy?= Date: Sat, 9 May 2020 22:39:26 +0200 Subject: [PATCH 14/20] fix has wpScriptsEnabled --- packages/create-block/lib/templates.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/create-block/lib/templates.js b/packages/create-block/lib/templates.js index 5efa586e454c5..98c675c48c5e1 100644 --- a/packages/create-block/lib/templates.js +++ b/packages/create-block/lib/templates.js @@ -115,8 +115,9 @@ const getPrompts = async ( templateName ) => { } ); }; -const hasWPScriptsEnabled = ( templateName ) => { - return getTemplate( templateName ).wpScriptsEnabled || false; +const hasWPScriptsEnabled = async ( templateName ) => { + const template = await getTemplate( templateName ); + return template.wpScriptsEnabled || false; }; const isCoreTemplate = ( templateName ) => From 5be44ccf17c54622cea9e243e4be46df59ffc58e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20K=C3=A4gy?= Date: Fri, 15 May 2020 09:19:24 +0200 Subject: [PATCH 15/20] Update packages/create-block/lib/templates.js Co-authored-by: Andrew Duthie --- packages/create-block/lib/templates.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/create-block/lib/templates.js b/packages/create-block/lib/templates.js index 98c675c48c5e1..c41dbdcf71cfc 100644 --- a/packages/create-block/lib/templates.js +++ b/packages/create-block/lib/templates.js @@ -84,9 +84,9 @@ const getTemplate = async ( templateName ) => { // throw a CLIError if the the template is neither a core one nor an external one if ( ! ( await isExternalTemplate( templateName ) ) ) { throw new CLIError( - `Invalid template type name. Either use one of the Core templates: ${ Object.keys( + `Invalid template type name. Provide either a valid npm package name, or use one of the Core templates: ${ Object.keys( coreTemplates - ).join( ', ' ) }. \n \n or a valid npm package name.` + ).join( ', ' ) }.` ); } From 22cdbb3e34833214f6e538bb22ca3d0a57b8caae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20K=C3=A4gy?= Date: Fri, 15 May 2020 09:19:50 +0200 Subject: [PATCH 16/20] Update packages/create-block/README.md Co-authored-by: Andrew Duthie --- packages/create-block/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/create-block/README.md b/packages/create-block/README.md index 10a8df5fd54f9..81effd23a0d70 100644 --- a/packages/create-block/README.md +++ b/packages/create-block/README.md @@ -102,7 +102,7 @@ Updates WordPress packages to the latest version. [Learn more](/packages/scripts ## External Templates Since version 0.12.0 it is possible to use external templates hosted on NPM. These templates need to contain `.mustache` files that will be used in the scaffolding and one `template.json` for the metadata. -### Availabe Variables: +### Available Variables: - `namespace` - `slug` - `title` From fac8b180312dbd0feaac232011572452f4dd8ffb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20K=C3=A4gy?= Date: Fri, 15 May 2020 09:20:00 +0200 Subject: [PATCH 17/20] Update packages/create-block/README.md Co-authored-by: Andrew Duthie --- packages/create-block/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/create-block/README.md b/packages/create-block/README.md index 81effd23a0d70..fd375b8bc77e4 100644 --- a/packages/create-block/README.md +++ b/packages/create-block/README.md @@ -67,7 +67,7 @@ When you scaffold a block, you must provide at least a `slug` name, the `namespa ## Available Commands [ESNext template] -When bootstraped with the `esnext` templateyou can run several commands inside the directory: +When bootstraped with the `esnext` template, you can run several commands inside the directory: ```bash $ npm start From 0a7169e1c640bafa6d2f3ff852611cdecb604994 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Ka=CC=88gy?= Date: Fri, 15 May 2020 09:21:34 +0200 Subject: [PATCH 18/20] fix typos --- packages/create-block/lib/index.js | 4 ++-- packages/create-block/lib/scaffold.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/create-block/lib/index.js b/packages/create-block/lib/index.js index 43fd7d7963cb6..16c87897a9930 100644 --- a/packages/create-block/lib/index.js +++ b/packages/create-block/lib/index.js @@ -62,8 +62,8 @@ program }; await scaffold( template, answers ); } else { - const propmpts = await getPrompts( template ); - const filteredPrompts = propmpts.filter( + const prompts = await getPrompts( template ); + const filteredPrompts = prompts.filter( ( { name } ) => ! Object.keys( optionsValues ).includes( name ) ); diff --git a/packages/create-block/lib/scaffold.js b/packages/create-block/lib/scaffold.js index c122400fe0d6b..e2006ca3e09dd 100644 --- a/packages/create-block/lib/scaffold.js +++ b/packages/create-block/lib/scaffold.js @@ -6,7 +6,7 @@ const makeDir = require( 'make-dir' ); const { readFile, writeFile } = require( 'fs' ).promises; const { render } = require( 'mustache' ); const { snakeCase } = require( 'lodash' ); -const raimraf = require( 'rimraf' ).sync; +const rimraf = require( 'rimraf' ).sync; /** * Internal dependencies @@ -78,7 +78,7 @@ module.exports = async function( await initWPScripts( view ); } - raimraf( tempFolder ); + rimraf( tempFolder ); info( '' ); success( From 06a30517720f8e0336a1b197b2e34fdb2fa58150 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Ka=CC=88gy?= Date: Fri, 15 May 2020 09:26:06 +0200 Subject: [PATCH 19/20] fix spelling of overridden --- packages/create-block/lib/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/create-block/lib/index.js b/packages/create-block/lib/index.js index 16c87897a9930..56119498179af 100644 --- a/packages/create-block/lib/index.js +++ b/packages/create-block/lib/index.js @@ -24,7 +24,7 @@ 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]' ) From 574f212fe6aff1ebe320f7378a082a7619018031 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Ka=CC=88gy?= Date: Fri, 29 May 2020 19:33:44 +0200 Subject: [PATCH 20/20] resolved merge conflicts --- packages/create-block/lib/index.js | 33 +++--- packages/create-block/lib/scaffold.js | 58 +++++------ packages/create-block/lib/templates.js | 133 +++++++++++++------------ packages/create-block/package.json | 1 + 4 files changed, 115 insertions(+), 110 deletions(-) diff --git a/packages/create-block/lib/index.js b/packages/create-block/lib/index.js index 56119498179af..9e219270ca028 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 @@ -30,7 +34,7 @@ program .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 = await getDefaultValues( template ); + const blockTemplate = await getBlockTemplate( templateName ); + const defaultValues = getDefaultValues( blockTemplate ); const optionsValues = pickBy( { category, - description: shortDescription, + description, namespace, title, } ); @@ -60,16 +71,14 @@ program title: startCase( slug ), ...optionsValues, }; - await scaffold( template, answers ); + await scaffold( blockTemplate, answers ); } else { - const prompts = await getPrompts( template ); - const filteredPrompts = prompts.filter( + const prompts = getPrompts( blockTemplate ).filter( ( { name } ) => ! Object.keys( optionsValues ).includes( name ) ); - const answers = await inquirer.prompt( filteredPrompts ); - - await scaffold( template, { + const answers = await inquirer.prompt( prompts ); + await scaffold( blockTemplate, { ...defaultValues, ...optionsValues, ...answers, @@ -85,7 +94,7 @@ program } } ) - .on( '--help', function() { + .on( '--help', () => { log.info( '' ); log.info( 'Examples:' ); log.info( ` $ ${ commandName }` ); diff --git a/packages/create-block/lib/scaffold.js b/packages/create-block/lib/scaffold.js index e2006ca3e09dd..5ccadb31a9a63 100644 --- a/packages/create-block/lib/scaffold.js +++ b/packages/create-block/lib/scaffold.js @@ -1,27 +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 rimraf = require( 'rimraf' ).sync; +const { dirname } = require( 'path' ); /** * Internal dependencies */ const initWPScripts = require( './init-wp-scripts' ); const { code, info, success } = require( './log' ); -const { - hasWPScriptsEnabled, - getOutputFiles, - isCoreTemplate, - tempFolder, -} = require( './templates' ); +const { hasWPScriptsEnabled } = require( './templates' ); -module.exports = async function( - templateName, +module.exports = async ( + blockTemplate, { namespace, slug, @@ -34,13 +28,14 @@ module.exports = async function( licenseURI, version, } -) { +) => { slug = slug.toLowerCase(); namespace = namespace.toLowerCase(); info( '' ); info( `Creating a new WordPress block in "${ slug }" folder.` ); + const { outputTemplates } = blockTemplate; const view = { namespace, namespaceSnakeCase: snakeCase( namespace ), @@ -56,35 +51,30 @@ module.exports = async function( licenseURI, textdomain: namespace, }; + await Promise.all( + Object.keys( outputTemplates ).map( async ( outputFile ) => { + // Output files can have names that depend on the slug provided. + const outputFilePath = `${ slug }/${ outputFile.replace( + /\$slug/g, + slug + ) }`; + await makeDir( dirname( outputFilePath ) ); + writeFile( + outputFilePath, + render( outputTemplates[ outputFile ], view ) + ); + } ) + ); - const templateDirectory = isCoreTemplate( templateName ) - ? join( __dirname, 'templates' ) - : join( tempFolder, 'node_modules' ); - - const outputFiles = await getOutputFiles( templateName ); - outputFiles.map( async ( file ) => { - const template = await readFile( - join( templateDirectory, `${ templateName }/${ file }.mustache` ), - 'utf8' - ); - // Output files can have names that depend on the slug provided. - const outputFilePath = `${ slug }/${ file.replace( /\$slug/g, slug ) }`; - await makeDir( dirname( outputFilePath ) ); - writeFile( outputFilePath, render( template, view ) ); - } ); - - const wpScriptsEnabled = await hasWPScriptsEnabled( templateName ); - if ( wpScriptsEnabled ) { + if ( hasWPScriptsEnabled( blockTemplate ) ) { await initWPScripts( view ); } - rimraf( tempFolder ); - info( '' ); success( `Done: block "${ title }" bootstrapped in the "${ slug }" folder.` ); - if ( wpScriptsEnabled ) { + 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 c41dbdcf71cfc..33ffb208611ec 100644 --- a/packages/create-block/lib/templates.js +++ b/packages/create-block/lib/templates.js @@ -1,108 +1,113 @@ /** - * Internal dependencies + * External dependencies */ -const CLIError = require( './cli-error' ); -const prompts = require( './prompts' ); +const glob = require( 'fast-glob' ); +const { readFile } = require( 'fs' ).promises; +const { fromPairs } = require( 'lodash' ); +const { join } = require( 'path' ); const { command } = require( 'execa' ); const { existsSync } = require( 'fs' ); -const { join } = require( 'path' ); -const { readFile } = require( 'fs' ).promises; const makeDir = require( 'make-dir' ); const os = require( 'os' ); const { v4: uuid } = require( 'uuid' ); +/** + * Internal dependencies + */ +const CLIError = require( './cli-error' ); +const prompts = require( './prompts' ); const log = require( './log' ); -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 coreTemplates = { +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 getOutputTemplates = async ( name ) => { + const outputTemplatesPath = isPredefinedTemplate( name ) + ? join( __dirname, 'templates', name ) + : join( tempFolder, 'node_modules', 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 tempFolder = join( os.tmpdir(), uuid() ); -const getTemplate = async ( templateName ) => { - if ( coreTemplates[ templateName ] ) { - return coreTemplates[ templateName ]; +const getBlockTemplate = async ( templateName ) => { + if ( predefinedBlockTemplates[ templateName ] ) { + return { + ...predefinedBlockTemplates[ templateName ], + outputTemplates: await getOutputTemplates( templateName ), + }; } // throw a CLIError if the the template is neither a core one nor an external one if ( ! ( await isExternalTemplate( templateName ) ) ) { throw new CLIError( `Invalid template type name. Provide either a valid npm package name, or use one of the Core templates: ${ Object.keys( - coreTemplates + predefinedBlockTemplates ).join( ', ' ) }.` ); } const packageInfo = await downloadExternalTemplate( templateName ); - return packageInfo; + return { + ...packageInfo, + outputTemplates: await getOutputTemplates( templateName ), + }; }; -const getDefaultValues = async ( templateName ) => { - const template = await getTemplate( templateName ); - return template.defaultValues; +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 getOutputFiles = async ( templateName ) => { - const template = await getTemplate( templateName ); - return template.outputFiles; + const template = await getBlockTemplate( templateName ); + return template.outputTemplates; }; const getPrompts = async ( templateName ) => { @@ -115,13 +120,12 @@ const getPrompts = async ( templateName ) => { } ); }; -const hasWPScriptsEnabled = async ( templateName ) => { - const template = await getTemplate( templateName ); - return template.wpScriptsEnabled || false; +const hasWPScriptsEnabled = ( blockTemplate ) => { + return blockTemplate.wpScripts !== false; }; -const isCoreTemplate = ( templateName ) => - coreTemplates[ templateName ] || false; +const isPredefinedTemplate = ( templateName ) => + predefinedBlockTemplates[ templateName ] || false; const isExternalTemplate = async ( templateName ) => { try { @@ -170,11 +174,12 @@ const downloadExternalTemplate = async ( templateName ) => { }; module.exports = { + getBlockTemplate, getDefaultValues, getOutputFiles, getPrompts, hasWPScriptsEnabled, - isCoreTemplate, + isPredefinedTemplate, isExternalTemplate, tempFolder, }; diff --git a/packages/create-block/package.json b/packages/create-block/package.json index b3f5188f4c670..8cd4a533e3031 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",