From d36959d9599483f8c7e442dc3d2b5dfff2d3f1f0 Mon Sep 17 00:00:00 2001 From: Ryan Welcher Date: Mon, 28 Oct 2024 10:05:58 -0400 Subject: [PATCH] Create Block: Adds `--target-dir` flag to allow the tool to target where to scaffold (#53781) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add --targetDir flag to allow targeting a directory where to scaffold the plugin/files. * Not using the targetDir when in --no-plugin mode * Change the name of the flag to match others and update changelog. * WIP commit. * Add logic to generate the paths for the root and block files in one place. * Add a new parameter to allow passing the path once rather than generating it in the function. * Modify the other functions to use the generated paths. * Update the command description. * Update packages/create-block/CHANGELOG.md * Refactor the handling for the root directory * Improve the documentation for target dir * Reorder CLI options in the docs --------- Co-authored-by: Greg Ziółkowski Unlinked contributors: afmarchetti. Co-authored-by: ryanwelcher Co-authored-by: gziolo Co-authored-by: bacoords Co-authored-by: colorful-tones Co-authored-by: brettsmason Co-authored-by: iamleese Co-authored-by: carolinan --- packages/create-block/CHANGELOG.md | 4 +++ packages/create-block/README.md | 31 +++++++++---------- packages/create-block/lib/index.js | 10 ++++-- packages/create-block/lib/init-block.js | 23 +++++++------- .../create-block/lib/init-package-json.js | 10 +++--- packages/create-block/lib/init-wp-env.js | 8 ++--- packages/create-block/lib/init-wp-scripts.js | 11 +++---- packages/create-block/lib/output.js | 8 ++--- packages/create-block/lib/scaffold.js | 14 ++++----- 9 files changed, 60 insertions(+), 59 deletions(-) diff --git a/packages/create-block/CHANGELOG.md b/packages/create-block/CHANGELOG.md index 87e647ec03dc03..9b9504faa1eeab 100644 --- a/packages/create-block/CHANGELOG.md +++ b/packages/create-block/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Enhancement + +- Add `--target-dir` flag to allow indicating where resulting files will be scaffolded ([#53781](https://github.com/WordPress/gutenberg/pull/53781)) + ## 4.53.0 (2024-10-16) ## 4.52.0 (2024-10-03) diff --git a/packages/create-block/README.md b/packages/create-block/README.md index 55cea45c9afe71..907121d3d466a7 100644 --- a/packages/create-block/README.md +++ b/packages/create-block/README.md @@ -18,10 +18,8 @@ $ npm start The `slug` provided (`todo-list` in the example) defines the folder name for the scaffolded plugin and the internal block name. The WordPress plugin generated must [be installed manually](https://wordpress.org/documentation/article/manage-plugins/#manual-plugin-installation-1). - _(requires `node` version `20.10.0` or above, and `npm` version `10.2.3` or above)_ - > [Watch a video introduction to create-block on Learn.wordpress.org](https://learn.wordpress.org/tutorial/using-the-create-block-tool/) ## Usage @@ -42,25 +40,26 @@ $ npx @wordpress/create-block@latest [options] [slug] When no `slug` is provided, the script will run in interactive mode and will start prompting for the input required (`slug`, title, namespace...) to scaffold the project. - ### `slug` The use of `slug` is optional. When provided it triggers the _quick mode_, where this `slug` is used: -- as the block slug (required for its identification) -- as the output location (folder name) for scaffolded files -- as the name of the WordPress plugin. + +- as the block slug (required for its identification) +- as the output location (folder name) for scaffolded files +- as the name of the WordPress plugin. The rest of the configuration is set to all default values unless overridden with some options listed below. ### `options` - ```bash -V, --version output the version number -t, --template project template type name; allowed values: "static" (default), "es5", the name of an external npm package, or the path to a local directory +--variant choose a block variant as defined by the template --no-plugin scaffold block files only +--target-dir the directory where the files will be scaffolded, defaults to the slug --namespace internal namespace for the block name --title display title for the block and the WordPress plugin --short-description short description for the block and the WordPress plugin @@ -69,7 +68,6 @@ The rest of the configuration is set to all default values unless overridden wit --no-wp-scripts disable integration with `@wordpress/scripts` package --wp-env enable integration with `@wordpress/env` package -h, --help output usage information ---variant choose a block variant as defined by the template ``` #### `--template` @@ -94,14 +92,6 @@ With this argument, `create-block` will generate a [dynamic block](https://devel $ npx @wordpress/create-block@latest --variant dynamic ``` -#### `--help` - -With this argument, the `create-block` package outputs usage information. - -```bash -$ npx @wordpress/create-block@latest --help -``` - #### `--no-plugin` With this argument, the `create-block` package runs in _No plugin mode_ which only scaffolds block files into the current directory. @@ -109,6 +99,7 @@ With this argument, the `create-block` package runs in _No plugin mode_ which on ```bash $ npx @wordpress/create-block@latest --no-plugin ``` + #### `--wp-env` With this argument, the `create-block` package will add to the generated plugin the configuration and the script to run [`wp-env` package](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-env/) within the plugin. This will allow you to easily set up a local WordPress environment (via Docker) for building and testing the generated plugin. @@ -117,6 +108,14 @@ With this argument, the `create-block` package will add to the generated plugin $ npx @wordpress/create-block@latest --wp-env ``` +#### `--help` + +With this argument, the `create-block` package outputs usage information. + +```bash +$ npx @wordpress/create-block@latest --help +``` + ## Available commands in the scaffolded project The plugin folder created when executing this command, is a node package with a modern build setup that requires no configuration. diff --git a/packages/create-block/lib/index.js b/packages/create-block/lib/index.js index 8e3d43c140460a..da08bcd4ab1dc7 100644 --- a/packages/create-block/lib/index.js +++ b/packages/create-block/lib/index.js @@ -37,6 +37,12 @@ program 'project template type name; allowed values: "standard", "es5", the name of an external npm package, or the path to a local directory', 'standard' ) + .option( '--variant ', 'the variant of the template to use' ) + .option( '--no-plugin', 'scaffold only block files' ) + .option( + '--target-dir ', + 'the directory where the files will be scaffolded, defaults to the slug' + ) .option( '--namespace ', 'internal namespace for the block name' ) .option( '--title ', @@ -57,8 +63,6 @@ program 'disable integration with `@wordpress/scripts` package' ) .option( '--wp-env', 'enable integration with `@wordpress/env` package' ) - .option( '--no-plugin', 'scaffold only block files' ) - .option( '--variant ', 'the variant of the template to use' ) .action( async ( slug, @@ -72,6 +76,7 @@ program wpScripts, wpEnv, variant, + targetDir, } ) => { await checkSystemRequirements( engines ); @@ -102,6 +107,7 @@ program title, wpScripts, wpEnv, + targetDir, } ).filter( ( [ , value ] ) => value !== undefined ) ); diff --git a/packages/create-block/lib/init-block.js b/packages/create-block/lib/init-block.js index 0882bdd3404631..8074ef1c8d953d 100644 --- a/packages/create-block/lib/init-block.js +++ b/packages/create-block/lib/init-block.js @@ -1,7 +1,7 @@ /** * External dependencies */ -const { dirname, join } = require( 'path' ); +const { join } = require( 'path' ); const makeDir = require( 'make-dir' ); const { writeFile } = require( 'fs' ).promises; @@ -35,16 +35,18 @@ async function initBlockJSON( { viewScript, customBlockJSON, example, + rootDirectory, } ) { info( '' ); info( 'Creating a "block.json" file.' ); - const outputFile = plugin - ? join( process.cwd(), slug, folderName, 'block.json' ) - : join( process.cwd(), slug, 'block.json' ); - await makeDir( dirname( outputFile ) ); + const blockFolderName = plugin + ? join( rootDirectory, folderName ) + : rootDirectory; + await makeDir( blockFolderName ); + await writeFile( - outputFile, + join( blockFolderName, 'block.json' ), JSON.stringify( Object.fromEntries( Object.entries( { @@ -79,13 +81,12 @@ async function initBlockJSON( { module.exports = async function ( outputTemplates, view ) { await Promise.all( Object.keys( outputTemplates ).map( async ( outputFile ) => { - const pathName = view.plugin - ? join( view.folderName, outputFile ) - : join( process.cwd(), view.slug, outputFile ); - await writeOutputTemplate( outputTemplates[ outputFile ], - pathName, + join( + view.plugin ? view.folderName : '', + outputFile.replace( /\$slug/g, view.slug ) + ), view ); } ) diff --git a/packages/create-block/lib/init-package-json.js b/packages/create-block/lib/init-package-json.js index bbc4436ac1d0e5..7a3765139e39d3 100644 --- a/packages/create-block/lib/init-package-json.js +++ b/packages/create-block/lib/init-package-json.js @@ -3,7 +3,6 @@ */ const { command } = require( 'execa' ); const npmPackageArg = require( 'npm-package-arg' ); -const { join } = require( 'path' ); const writePkg = require( 'write-pkg' ); /** @@ -25,14 +24,13 @@ module.exports = async ( { customScripts, isDynamicVariant, customPackageJSON, + rootDirectory, } ) => { - const cwd = join( process.cwd(), slug ); - info( '' ); info( 'Creating a "package.json" file.' ); await writePkg( - cwd, + rootDirectory, Object.fromEntries( Object.entries( { name: slug, @@ -92,7 +90,7 @@ module.exports = async ( { info( '' ); info( `Installing "${ packageArg }".` ); await command( `npm install ${ packageArg }`, { - cwd, + cwd: rootDirectory, } ); } catch ( { message } ) { info( '' ); @@ -115,7 +113,7 @@ module.exports = async ( { info( '' ); info( `Installing "${ packageArg }".` ); await command( `npm install ${ packageArg } --save-dev`, { - cwd, + cwd: rootDirectory, } ); } catch ( { message } ) { info( '' ); diff --git a/packages/create-block/lib/init-wp-env.js b/packages/create-block/lib/init-wp-env.js index 19fd01646cf041..419e8c0991d44c 100644 --- a/packages/create-block/lib/init-wp-env.js +++ b/packages/create-block/lib/init-wp-env.js @@ -10,21 +10,19 @@ const { writeFile } = require( 'fs' ).promises; */ const { info } = require( './log' ); -module.exports = async ( { slug } ) => { - const cwd = join( process.cwd(), slug ); - +module.exports = async ( { rootDirectory } ) => { info( '' ); info( 'Installing `@wordpress/env` package. It might take a couple of minutes...' ); await command( 'npm install @wordpress/env --save-dev', { - cwd, + cwd: rootDirectory, } ); info( '' ); info( 'Configuring `@wordpress/env`...' ); await writeFile( - join( cwd, '.wp-env.json' ), + join( rootDirectory, '.wp-env.json' ), JSON.stringify( { core: 'WordPress/WordPress', diff --git a/packages/create-block/lib/init-wp-scripts.js b/packages/create-block/lib/init-wp-scripts.js index ca0101957f47f1..dbd33ba45187c8 100644 --- a/packages/create-block/lib/init-wp-scripts.js +++ b/packages/create-block/lib/init-wp-scripts.js @@ -2,33 +2,30 @@ * External dependencies */ const { command } = require( 'execa' ); -const { join } = require( 'path' ); /** * Internal dependencies */ const { info } = require( './log' ); -module.exports = async ( { slug } ) => { - const cwd = join( process.cwd(), slug ); - +module.exports = async ( { rootDirectory } ) => { info( '' ); info( 'Installing `@wordpress/scripts` package. It might take a couple of minutes...' ); await command( 'npm install @wordpress/scripts --save-dev', { - cwd, + cwd: rootDirectory, } ); info( '' ); info( 'Formatting JavaScript files.' ); await command( 'npm run format', { - cwd, + cwd: rootDirectory, } ); info( '' ); info( 'Compiling block.' ); await command( 'npm run build', { - cwd, + cwd: rootDirectory, } ); }; diff --git a/packages/create-block/lib/output.js b/packages/create-block/lib/output.js index dd442b17ae0511..71d2e9ebe86e54 100644 --- a/packages/create-block/lib/output.js +++ b/packages/create-block/lib/output.js @@ -7,19 +7,17 @@ const { render } = require( 'mustache' ); const { writeFile } = require( 'fs' ).promises; const writeOutputAsset = async ( inputFile, outputFile, view ) => { - const outputFilePath = join( view.slug, 'assets', outputFile ); + const outputFilePath = join( view.rootDirectory, 'assets', outputFile ); await makeDir( dirname( outputFilePath ) ); writeFile( outputFilePath, inputFile ); }; const writeOutputTemplate = async ( inputFile, outputFile, view ) => { - const outputFilePath = view.plugin - ? join( view.slug, outputFile.replace( /\$slug/g, view.slug ) ) - : outputFile; - await makeDir( dirname( outputFilePath ) ); // If the rendered template is empty, don't write it. This is how we can conditionally add template files. const renderedFile = render( inputFile, view ); if ( renderedFile.trim().length ) { + const outputFilePath = join( view.rootDirectory, outputFile ); + await makeDir( dirname( outputFilePath ) ); writeFile( outputFilePath, renderedFile ); } }; diff --git a/packages/create-block/lib/scaffold.js b/packages/create-block/lib/scaffold.js index b7d4addde6a82c..73b9f549908867 100644 --- a/packages/create-block/lib/scaffold.js +++ b/packages/create-block/lib/scaffold.js @@ -2,6 +2,7 @@ * External dependencies */ const { pascalCase, snakeCase } = require( 'change-case' ); +const { join } = require( 'path' ); /** * Internal dependencies @@ -40,6 +41,7 @@ module.exports = async ( npmDevDependencies, customScripts, folderName, + targetDir, editorScript, editorStyle, style, @@ -56,7 +58,7 @@ module.exports = async ( ) => { slug = slug.toLowerCase(); namespace = namespace.toLowerCase(); - + const rootDirectory = join( process.cwd(), targetDir || slug ); const transformedValues = transformer( { $schema, apiVersion, @@ -94,6 +96,7 @@ module.exports = async ( customBlockJSON, example, textdomain: slug, + rootDirectory, } ); const view = { @@ -117,11 +120,10 @@ module.exports = async ( return; } + const projectType = plugin ? 'plugin' : 'block'; info( '' ); info( - plugin - ? `Creating a new WordPress plugin in the ${ view.slug } directory.` - : `Creating a new block in the ${ view.slug } directory.` + `Creating a new WordPress ${ projectType } in the ${ rootDirectory } directory.` ); if ( plugin ) { @@ -164,9 +166,7 @@ module.exports = async ( info( '' ); success( - plugin - ? `Done: WordPress plugin ${ title } bootstrapped in the ${ slug } directory.` - : `Done: Block "${ title }" bootstrapped in the ${ slug } directory.` + `Done: WordPress ${ projectType } ${ title } bootstrapped in the ${ rootDirectory } directory.` ); if ( plugin && wpScripts ) {