@wordpress/create-block 3.8.0 → 4.0.1-next.d6164808d3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/README.md +17 -2
- package/lib/check-system-requirements.js +17 -13
- package/lib/index.js +77 -44
- package/lib/init-block.js +18 -15
- package/lib/init-package-json.js +10 -7
- package/lib/output.js +8 -6
- package/lib/prompts.js +17 -4
- package/lib/scaffold.js +58 -34
- package/lib/templates/block/index.js.mustache +4 -0
- package/lib/templates/block/save.js.mustache +2 -0
- package/lib/templates/block/template.php.mustache +5 -0
- package/lib/templates/es5/$slug.php.mustache +29 -1
- package/lib/templates/es5/index.js.mustache +2 -2
- package/lib/templates/es5/template.php.mustache +5 -0
- package/lib/templates/plugin/$slug.php.mustache +28 -0
- package/lib/templates.js +60 -6
- package/package.json +5 -6
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 4.0.0-next.0 (2022-08-23)
|
|
6
|
+
|
|
7
|
+
### Breaking Change
|
|
8
|
+
|
|
9
|
+
- Increase the minimum Node.js version to 14 and minimum npm version to 6.14.4 ([#43141](https://github.com/WordPress/gutenberg/pull/43141)).
|
|
10
|
+
|
|
11
|
+
### New Feature
|
|
12
|
+
|
|
13
|
+
- Add `--no-plugin` flag to allow scaffolding of a block in an existing plugin ([#41642](https://github.com/WordPress/gutenberg/pull/41642))
|
|
14
|
+
- Introduce the `--variant` flag to allow selection of a variant as defined in the template ([#41289](https://github.com/WordPress/gutenberg/pull/41289)).
|
|
15
|
+
|
|
5
16
|
## 3.6.0 (2022-07-13)
|
|
6
17
|
|
|
7
18
|
### Enhancement
|
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ $ cd todo-list
|
|
|
20
20
|
$ npm start
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
_(requires `node` version `
|
|
23
|
+
_(requires `node` version `14.0.0` or above, and `npm` version `6.14.4` or above)_
|
|
24
24
|
|
|
25
25
|
It creates a WordPress plugin that you need to [install manually](https://wordpress.org/support/article/managing-plugins/#manual-plugin-installation).
|
|
26
26
|
|
|
@@ -41,6 +41,7 @@ Options:
|
|
|
41
41
|
```bash
|
|
42
42
|
-V, --version output the version number
|
|
43
43
|
-t, --template <name> project template type name; allowed values: "static" (default), "es5", the name of an external npm package, or the path to a local directory
|
|
44
|
+
--no-plugin scaffold block files only
|
|
44
45
|
--namespace <value> internal namespace for the block name
|
|
45
46
|
--title <value> display title for the block and the WordPress plugin
|
|
46
47
|
--short-description <value> short description for the block and the WordPress plugin
|
|
@@ -49,6 +50,7 @@ Options:
|
|
|
49
50
|
--no-wp-scripts disable integration with `@wordpress/scripts` package
|
|
50
51
|
--wp-env enable integration with `@wordpress/env` package
|
|
51
52
|
-h, --help output usage information
|
|
53
|
+
--variant choose a block variant as defined by the template
|
|
52
54
|
```
|
|
53
55
|
|
|
54
56
|
More examples:
|
|
@@ -71,12 +73,25 @@ $ npx @wordpress/create-block --template my-template-package
|
|
|
71
73
|
$ npx @wordpress/create-block --template ./path/to/template-directory
|
|
72
74
|
```
|
|
73
75
|
|
|
74
|
-
4.
|
|
76
|
+
4. Generating a dynamic block based on the built-in template.
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
$ npx @wordpress/create-block --variant dynamic
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
5. Help – you need to use `npx` to output usage information.
|
|
75
83
|
|
|
76
84
|
```bash
|
|
77
85
|
$ npx @wordpress/create-block --help
|
|
78
86
|
```
|
|
79
87
|
|
|
88
|
+
5. No plugin mode – it is also possible to scaffold only block files into the current directory.
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
$ npx @wordpress/create-block --no-plugin
|
|
93
|
+
```
|
|
94
|
+
|
|
80
95
|
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. In most cases, we recommended pairing blocks with WordPress plugins rather than themes, because only using plugin ensures that all blocks still work when your theme changes.
|
|
81
96
|
|
|
82
97
|
## Available Commands
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
const inquirer = require( 'inquirer' );
|
|
5
5
|
const checkSync = require( 'check-node-version' );
|
|
6
6
|
const tools = require( 'check-node-version/tools' );
|
|
7
|
-
const { forEach } = require( 'lodash' );
|
|
8
7
|
const { promisify } = require( 'util' );
|
|
9
8
|
|
|
10
9
|
/**
|
|
@@ -21,13 +20,15 @@ async function checkSystemRequirements( engines ) {
|
|
|
21
20
|
log.error( 'Minimum system requirements not met!' );
|
|
22
21
|
log.info( '' );
|
|
23
22
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
Object.entries( result.versions ).forEach(
|
|
24
|
+
( [ name, { isSatisfied, wanted } ] ) => {
|
|
25
|
+
if ( ! isSatisfied ) {
|
|
26
|
+
log.error(
|
|
27
|
+
`Error: Wanted ${ name } version ${ wanted.raw } (${ wanted.range })`
|
|
28
|
+
);
|
|
29
|
+
}
|
|
29
30
|
}
|
|
30
|
-
|
|
31
|
+
);
|
|
31
32
|
|
|
32
33
|
log.info( '' );
|
|
33
34
|
log.error( 'The program may not complete correctly if you continue.' );
|
|
@@ -46,13 +47,16 @@ async function checkSystemRequirements( engines ) {
|
|
|
46
47
|
log.error( 'Cancelled.' );
|
|
47
48
|
log.info( '' );
|
|
48
49
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
Object.entries( result.versions ).forEach(
|
|
51
|
+
( [ name, { isSatisfied, wanted } ] ) => {
|
|
52
|
+
if ( ! isSatisfied ) {
|
|
53
|
+
log.info(
|
|
54
|
+
tools[ name ].getInstallInstructions( wanted.raw )
|
|
55
|
+
);
|
|
56
|
+
}
|
|
54
57
|
}
|
|
55
|
-
|
|
58
|
+
);
|
|
59
|
+
|
|
56
60
|
process.exit( 1 );
|
|
57
61
|
}
|
|
58
62
|
}
|
package/lib/index.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* External dependencies
|
|
3
3
|
*/
|
|
4
4
|
const inquirer = require( 'inquirer' );
|
|
5
|
+
const { capitalCase } = require( 'change-case' );
|
|
5
6
|
const program = require( 'commander' );
|
|
6
|
-
const { pickBy, startCase } = require( 'lodash' );
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Internal dependencies
|
|
@@ -34,8 +34,8 @@ program
|
|
|
34
34
|
.arguments( '[slug]' )
|
|
35
35
|
.option(
|
|
36
36
|
'-t, --template <name>',
|
|
37
|
-
'project template type name; allowed values: "
|
|
38
|
-
'
|
|
37
|
+
'project template type name; allowed values: "standard", "es5", the name of an external npm package, or the path to a local directory',
|
|
38
|
+
'standard'
|
|
39
39
|
)
|
|
40
40
|
.option( '--namespace <value>', 'internal namespace for the block name' )
|
|
41
41
|
.option(
|
|
@@ -57,10 +57,13 @@ program
|
|
|
57
57
|
'disable integration with `@wordpress/scripts` package'
|
|
58
58
|
)
|
|
59
59
|
.option( '--wp-env', 'enable integration with `@wordpress/env` package' )
|
|
60
|
+
.option( '--no-plugin', 'scaffold only block files' )
|
|
61
|
+
.option( '--variant <variant>', 'the variant of the template to use' )
|
|
60
62
|
.action(
|
|
61
63
|
async (
|
|
62
64
|
slug,
|
|
63
65
|
{
|
|
66
|
+
plugin,
|
|
64
67
|
category,
|
|
65
68
|
namespace,
|
|
66
69
|
shortDescription: description,
|
|
@@ -68,22 +71,27 @@ program
|
|
|
68
71
|
title,
|
|
69
72
|
wpScripts,
|
|
70
73
|
wpEnv,
|
|
74
|
+
variant,
|
|
71
75
|
}
|
|
72
76
|
) => {
|
|
73
77
|
await checkSystemRequirements( engines );
|
|
74
78
|
try {
|
|
75
79
|
const pluginTemplate = await getPluginTemplate( templateName );
|
|
76
|
-
const defaultValues = getDefaultValues(
|
|
77
|
-
|
|
78
|
-
|
|
80
|
+
const defaultValues = getDefaultValues(
|
|
81
|
+
pluginTemplate,
|
|
82
|
+
variant
|
|
83
|
+
);
|
|
84
|
+
const optionsValues = Object.fromEntries(
|
|
85
|
+
Object.entries( {
|
|
86
|
+
plugin,
|
|
79
87
|
category,
|
|
80
88
|
description,
|
|
81
89
|
namespace,
|
|
82
90
|
title,
|
|
83
91
|
wpScripts,
|
|
84
92
|
wpEnv,
|
|
85
|
-
|
|
86
|
-
( value ) => value !== undefined
|
|
93
|
+
variant,
|
|
94
|
+
} ).filter( ( [ , value ] ) => value !== undefined )
|
|
87
95
|
);
|
|
88
96
|
|
|
89
97
|
if ( slug ) {
|
|
@@ -91,59 +99,84 @@ program
|
|
|
91
99
|
...defaultValues,
|
|
92
100
|
slug,
|
|
93
101
|
// Transforms slug to title as a fallback.
|
|
94
|
-
title:
|
|
102
|
+
title: capitalCase( slug ),
|
|
95
103
|
...optionsValues,
|
|
96
104
|
};
|
|
97
105
|
await scaffold( pluginTemplate, answers );
|
|
98
106
|
} else {
|
|
99
107
|
log.info( '' );
|
|
100
108
|
log.info(
|
|
101
|
-
|
|
109
|
+
plugin
|
|
110
|
+
? "Let's customize your WordPress plugin with blocks:"
|
|
111
|
+
: "Let's add a new block to your existing WordPress plugin:"
|
|
102
112
|
);
|
|
103
113
|
|
|
104
114
|
const filterOptionsProvided = ( { name } ) =>
|
|
105
115
|
! Object.keys( optionsValues ).includes( name );
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
116
|
+
|
|
117
|
+
// Get the variant prompt first. This will help get the default values
|
|
118
|
+
const variantPrompt =
|
|
119
|
+
Object.keys( pluginTemplate.variants )?.length > 1
|
|
120
|
+
? getPrompts( pluginTemplate, [ 'variant' ] )
|
|
121
|
+
: false;
|
|
122
|
+
|
|
123
|
+
const variantSelection = variantPrompt
|
|
124
|
+
? await inquirer.prompt( variantPrompt )
|
|
125
|
+
: false;
|
|
126
|
+
|
|
127
|
+
const blockPrompts = getPrompts(
|
|
128
|
+
pluginTemplate,
|
|
129
|
+
[
|
|
130
|
+
'slug',
|
|
131
|
+
'namespace',
|
|
132
|
+
'title',
|
|
133
|
+
'description',
|
|
134
|
+
'dashicon',
|
|
135
|
+
'category',
|
|
136
|
+
],
|
|
137
|
+
variantSelection.variant
|
|
138
|
+
).filter( filterOptionsProvided );
|
|
139
|
+
|
|
114
140
|
const blockAnswers = await inquirer.prompt( blockPrompts );
|
|
115
141
|
|
|
116
|
-
const pluginAnswers =
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
142
|
+
const pluginAnswers = plugin
|
|
143
|
+
? await inquirer
|
|
144
|
+
.prompt( {
|
|
145
|
+
type: 'confirm',
|
|
146
|
+
name: 'configurePlugin',
|
|
147
|
+
message:
|
|
148
|
+
'Do you want to customize the WordPress plugin?',
|
|
149
|
+
default: false,
|
|
150
|
+
} )
|
|
151
|
+
.then( async ( { configurePlugin } ) => {
|
|
152
|
+
if ( ! configurePlugin ) {
|
|
153
|
+
return {};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const pluginPrompts = getPrompts(
|
|
157
|
+
pluginTemplate,
|
|
158
|
+
[
|
|
159
|
+
'pluginURI',
|
|
160
|
+
'version',
|
|
161
|
+
'author',
|
|
162
|
+
'license',
|
|
163
|
+
'licenseURI',
|
|
164
|
+
'domainPath',
|
|
165
|
+
'updateURI',
|
|
166
|
+
]
|
|
167
|
+
).filter( filterOptionsProvided );
|
|
168
|
+
const result = await inquirer.prompt(
|
|
169
|
+
pluginPrompts
|
|
170
|
+
);
|
|
171
|
+
return result;
|
|
172
|
+
} )
|
|
173
|
+
: {};
|
|
128
174
|
|
|
129
|
-
const pluginPrompts = getPrompts( pluginTemplate, [
|
|
130
|
-
'pluginURI',
|
|
131
|
-
'version',
|
|
132
|
-
'author',
|
|
133
|
-
'license',
|
|
134
|
-
'licenseURI',
|
|
135
|
-
'domainPath',
|
|
136
|
-
'updateURI',
|
|
137
|
-
] ).filter( filterOptionsProvided );
|
|
138
|
-
const result = await inquirer.prompt(
|
|
139
|
-
pluginPrompts
|
|
140
|
-
);
|
|
141
|
-
return result;
|
|
142
|
-
} );
|
|
143
175
|
await scaffold( pluginTemplate, {
|
|
144
176
|
...defaultValues,
|
|
145
177
|
...optionsValues,
|
|
146
178
|
...blockAnswers,
|
|
179
|
+
...variantSelection,
|
|
147
180
|
...pluginAnswers,
|
|
148
181
|
} );
|
|
149
182
|
}
|
package/lib/init-block.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* External dependencies
|
|
3
3
|
*/
|
|
4
|
-
const { omitBy } = require( 'lodash' );
|
|
5
4
|
const { dirname, join } = require( 'path' );
|
|
6
5
|
const makeDir = require( 'make-dir' );
|
|
7
6
|
const { writeFile } = require( 'fs' ).promises;
|
|
@@ -15,6 +14,7 @@ const { writeOutputTemplate } = require( './output' );
|
|
|
15
14
|
async function initBlockJSON( {
|
|
16
15
|
$schema,
|
|
17
16
|
apiVersion,
|
|
17
|
+
plugin,
|
|
18
18
|
slug,
|
|
19
19
|
namespace,
|
|
20
20
|
title,
|
|
@@ -33,13 +33,15 @@ async function initBlockJSON( {
|
|
|
33
33
|
info( '' );
|
|
34
34
|
info( 'Creating a "block.json" file.' );
|
|
35
35
|
|
|
36
|
-
const outputFile =
|
|
36
|
+
const outputFile = plugin
|
|
37
|
+
? join( process.cwd(), slug, folderName, 'block.json' )
|
|
38
|
+
: join( process.cwd(), slug, 'block.json' );
|
|
37
39
|
await makeDir( dirname( outputFile ) );
|
|
38
40
|
await writeFile(
|
|
39
41
|
outputFile,
|
|
40
42
|
JSON.stringify(
|
|
41
|
-
|
|
42
|
-
{
|
|
43
|
+
Object.fromEntries(
|
|
44
|
+
Object.entries( {
|
|
43
45
|
$schema,
|
|
44
46
|
apiVersion,
|
|
45
47
|
name: namespace + '/' + slug,
|
|
@@ -54,8 +56,7 @@ async function initBlockJSON( {
|
|
|
54
56
|
editorScript,
|
|
55
57
|
editorStyle,
|
|
56
58
|
style,
|
|
57
|
-
},
|
|
58
|
-
( value ) => ! value
|
|
59
|
+
} ).filter( ( [ , value ] ) => !! value )
|
|
59
60
|
),
|
|
60
61
|
null,
|
|
61
62
|
'\t'
|
|
@@ -65,15 +66,17 @@ async function initBlockJSON( {
|
|
|
65
66
|
|
|
66
67
|
module.exports = async function ( outputTemplates, view ) {
|
|
67
68
|
await Promise.all(
|
|
68
|
-
Object.keys( outputTemplates ).map(
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
join( view.folderName, outputFile ),
|
|
73
|
-
view
|
|
74
|
-
)
|
|
75
|
-
)
|
|
76
|
-
);
|
|
69
|
+
Object.keys( outputTemplates ).map( async ( outputFile ) => {
|
|
70
|
+
const pathName = view.plugin
|
|
71
|
+
? join( view.folderName, outputFile )
|
|
72
|
+
: join( process.cwd(), view.slug, outputFile );
|
|
77
73
|
|
|
74
|
+
await writeOutputTemplate(
|
|
75
|
+
outputTemplates[ outputFile ],
|
|
76
|
+
pathName,
|
|
77
|
+
view
|
|
78
|
+
);
|
|
79
|
+
} )
|
|
80
|
+
);
|
|
78
81
|
await initBlockJSON( view );
|
|
79
82
|
};
|
package/lib/init-package-json.js
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
* External dependencies
|
|
3
3
|
*/
|
|
4
4
|
const { command } = require( 'execa' );
|
|
5
|
-
const { isEmpty, omitBy } = require( 'lodash' );
|
|
6
5
|
const npmPackageArg = require( 'npm-package-arg' );
|
|
7
6
|
const { join } = require( 'path' );
|
|
8
7
|
const writePkg = require( 'write-pkg' );
|
|
@@ -24,6 +23,7 @@ module.exports = async ( {
|
|
|
24
23
|
npmDependencies,
|
|
25
24
|
npmDevDependencies,
|
|
26
25
|
customScripts,
|
|
26
|
+
isDynamicVariant,
|
|
27
27
|
} ) => {
|
|
28
28
|
const cwd = join( process.cwd(), slug );
|
|
29
29
|
|
|
@@ -32,8 +32,8 @@ module.exports = async ( {
|
|
|
32
32
|
|
|
33
33
|
await writePkg(
|
|
34
34
|
cwd,
|
|
35
|
-
|
|
36
|
-
{
|
|
35
|
+
Object.fromEntries(
|
|
36
|
+
Object.entries( {
|
|
37
37
|
name: slug,
|
|
38
38
|
version,
|
|
39
39
|
description,
|
|
@@ -43,19 +43,22 @@ module.exports = async ( {
|
|
|
43
43
|
main: wpScripts && 'build/index.js',
|
|
44
44
|
scripts: {
|
|
45
45
|
...( wpScripts && {
|
|
46
|
-
build:
|
|
46
|
+
build: isDynamicVariant
|
|
47
|
+
? 'wp-scripts build --webpack-copy-php'
|
|
48
|
+
: 'wp-scripts build',
|
|
47
49
|
format: 'wp-scripts format',
|
|
48
50
|
'lint:css': 'wp-scripts lint-style',
|
|
49
51
|
'lint:js': 'wp-scripts lint-js',
|
|
50
52
|
'packages-update': 'wp-scripts packages-update',
|
|
51
53
|
'plugin-zip': 'wp-scripts plugin-zip',
|
|
52
|
-
start:
|
|
54
|
+
start: isDynamicVariant
|
|
55
|
+
? 'wp-scripts start --webpack-copy-php'
|
|
56
|
+
: 'wp-scripts start',
|
|
53
57
|
} ),
|
|
54
58
|
...( wpEnv && { env: 'wp-env' } ),
|
|
55
59
|
...customScripts,
|
|
56
60
|
},
|
|
57
|
-
},
|
|
58
|
-
isEmpty
|
|
61
|
+
} ).filter( ( [ , value ] ) => !! value )
|
|
59
62
|
)
|
|
60
63
|
);
|
|
61
64
|
|
package/lib/output.js
CHANGED
|
@@ -13,13 +13,15 @@ const writeOutputAsset = async ( inputFile, outputFile, view ) => {
|
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
const writeOutputTemplate = async ( inputFile, outputFile, view ) => {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
outputFile.replace( /\$slug/g, view.slug )
|
|
20
|
-
);
|
|
16
|
+
const outputFilePath = view.plugin
|
|
17
|
+
? join( view.slug, outputFile.replace( /\$slug/g, view.slug ) )
|
|
18
|
+
: outputFile;
|
|
21
19
|
await makeDir( dirname( outputFilePath ) );
|
|
22
|
-
|
|
20
|
+
// If the rendered template is empty, don't write it. This is how we can conditionally add template files.
|
|
21
|
+
const renderedFile = render( inputFile, view );
|
|
22
|
+
if ( renderedFile.trim().length ) {
|
|
23
|
+
writeFile( outputFilePath, renderedFile );
|
|
24
|
+
}
|
|
23
25
|
};
|
|
24
26
|
|
|
25
27
|
module.exports = {
|
package/lib/prompts.js
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Capitalizes the first letter in a string.
|
|
3
|
+
*
|
|
4
|
+
* @param {string} str The string whose first letter the function will capitalize.
|
|
5
|
+
*
|
|
6
|
+
* @return {string} Capitalized string.
|
|
3
7
|
*/
|
|
4
|
-
const
|
|
8
|
+
const upperFirst = ( [ firstLetter, ...rest ] ) =>
|
|
9
|
+
firstLetter.toUpperCase() + rest.join( '' );
|
|
5
10
|
|
|
6
11
|
// Block metadata.
|
|
7
12
|
const slug = {
|
|
8
13
|
type: 'input',
|
|
9
14
|
name: 'slug',
|
|
10
15
|
message:
|
|
11
|
-
'The block slug used for identification (also the
|
|
16
|
+
'The block slug used for identification (also the output folder name):',
|
|
12
17
|
validate( input ) {
|
|
13
18
|
if ( ! /^[a-z][a-z0-9\-]*$/.test( input ) ) {
|
|
14
19
|
return 'Invalid block slug specified. Block slug can contain only lowercase alphanumeric characters or dashes, and start with a letter.';
|
|
@@ -56,7 +61,7 @@ const dashicon = {
|
|
|
56
61
|
message:
|
|
57
62
|
'The dashicon to make it easier to identify your block (optional):',
|
|
58
63
|
validate( input ) {
|
|
59
|
-
if (
|
|
64
|
+
if ( input.length && ! /^[a-z][a-z0-9\-]*$/.test( input ) ) {
|
|
60
65
|
return 'Invalid dashicon name specified. Visit https://developer.wordpress.org/resource/dashicons/ to discover available names.';
|
|
61
66
|
}
|
|
62
67
|
|
|
@@ -129,8 +134,16 @@ const updateURI = {
|
|
|
129
134
|
message: 'A custom update URI for the plugin (optional):',
|
|
130
135
|
};
|
|
131
136
|
|
|
137
|
+
const variant = {
|
|
138
|
+
type: 'list',
|
|
139
|
+
name: 'variant',
|
|
140
|
+
message: 'The template variant to use for this block:',
|
|
141
|
+
choices: [],
|
|
142
|
+
};
|
|
143
|
+
|
|
132
144
|
module.exports = {
|
|
133
145
|
slug,
|
|
146
|
+
variant,
|
|
134
147
|
namespace,
|
|
135
148
|
title,
|
|
136
149
|
description,
|
package/lib/scaffold.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* External dependencies
|
|
3
3
|
*/
|
|
4
|
-
const {
|
|
4
|
+
const { pascalCase, snakeCase } = require( 'change-case' );
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Internal dependencies
|
|
@@ -10,18 +10,16 @@ const initBlock = require( './init-block' );
|
|
|
10
10
|
const initPackageJSON = require( './init-package-json' );
|
|
11
11
|
const initWPScripts = require( './init-wp-scripts' );
|
|
12
12
|
const initWPEnv = require( './init-wp-env' );
|
|
13
|
-
const { code, info, success } = require( './log' );
|
|
13
|
+
const { code, info, success, error } = require( './log' );
|
|
14
14
|
const { writeOutputAsset, writeOutputTemplate } = require( './output' );
|
|
15
|
-
|
|
16
|
-
function upperFirst( str ) {
|
|
17
|
-
return str.charAt( 0 ).toUpperCase() + str.substr( 1 );
|
|
18
|
-
}
|
|
15
|
+
const { getTemplateVariantVars } = require( './templates' );
|
|
19
16
|
|
|
20
17
|
module.exports = async (
|
|
21
|
-
{ blockOutputTemplates, pluginOutputTemplates, outputAssets },
|
|
18
|
+
{ blockOutputTemplates, pluginOutputTemplates, outputAssets, variants },
|
|
22
19
|
{
|
|
23
20
|
$schema,
|
|
24
21
|
apiVersion,
|
|
22
|
+
plugin,
|
|
25
23
|
namespace,
|
|
26
24
|
slug,
|
|
27
25
|
title,
|
|
@@ -46,22 +44,39 @@ module.exports = async (
|
|
|
46
44
|
editorScript,
|
|
47
45
|
editorStyle,
|
|
48
46
|
style,
|
|
47
|
+
variant,
|
|
49
48
|
}
|
|
50
49
|
) => {
|
|
51
50
|
slug = slug.toLowerCase();
|
|
52
51
|
namespace = namespace.toLowerCase();
|
|
52
|
+
/**
|
|
53
|
+
* --no-plugin relies on the used template supporting the [blockTemplatesPath property](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-create-block/#blocktemplatespath).
|
|
54
|
+
* If the blockOutputTemplates object has no properties, we can assume that there was a custom --template passed that
|
|
55
|
+
* doesn't support it.
|
|
56
|
+
*/
|
|
57
|
+
if ( ! plugin && Object.keys( blockOutputTemplates ) < 1 ) {
|
|
58
|
+
error(
|
|
59
|
+
'No block files found in the template. Please ensure that the template supports the blockTemplatesPath property.'
|
|
60
|
+
);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
53
63
|
|
|
54
64
|
info( '' );
|
|
55
|
-
info(
|
|
65
|
+
info(
|
|
66
|
+
plugin
|
|
67
|
+
? `Creating a new WordPress plugin in the ${ slug } directory.`
|
|
68
|
+
: `Creating a new block in the ${ slug } directory.`
|
|
69
|
+
);
|
|
56
70
|
|
|
57
71
|
const view = {
|
|
58
72
|
$schema,
|
|
59
73
|
apiVersion,
|
|
74
|
+
plugin,
|
|
60
75
|
namespace,
|
|
61
76
|
namespaceSnakeCase: snakeCase( namespace ),
|
|
62
77
|
slug,
|
|
63
78
|
slugSnakeCase: snakeCase( slug ),
|
|
64
|
-
slugPascalCase:
|
|
79
|
+
slugPascalCase: pascalCase( slug ),
|
|
65
80
|
title,
|
|
66
81
|
description,
|
|
67
82
|
dashicon,
|
|
@@ -85,18 +100,22 @@ module.exports = async (
|
|
|
85
100
|
editorScript,
|
|
86
101
|
editorStyle,
|
|
87
102
|
style,
|
|
103
|
+
...getTemplateVariantVars( variants, variant ),
|
|
104
|
+
...variants[ variant ],
|
|
88
105
|
};
|
|
89
106
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
107
|
+
if ( plugin ) {
|
|
108
|
+
await Promise.all(
|
|
109
|
+
Object.keys( pluginOutputTemplates ).map(
|
|
110
|
+
async ( outputFile ) =>
|
|
111
|
+
await writeOutputTemplate(
|
|
112
|
+
pluginOutputTemplates[ outputFile ],
|
|
113
|
+
outputFile,
|
|
114
|
+
view
|
|
115
|
+
)
|
|
116
|
+
)
|
|
117
|
+
);
|
|
118
|
+
}
|
|
100
119
|
|
|
101
120
|
await Promise.all(
|
|
102
121
|
Object.keys( outputAssets ).map(
|
|
@@ -111,21 +130,26 @@ module.exports = async (
|
|
|
111
130
|
|
|
112
131
|
await initBlock( blockOutputTemplates, view );
|
|
113
132
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
133
|
+
if ( plugin ) {
|
|
134
|
+
await initPackageJSON( view );
|
|
135
|
+
if ( wpScripts ) {
|
|
136
|
+
await initWPScripts( view );
|
|
137
|
+
}
|
|
119
138
|
|
|
120
|
-
|
|
121
|
-
|
|
139
|
+
if ( wpEnv ) {
|
|
140
|
+
await initWPEnv( view );
|
|
141
|
+
}
|
|
122
142
|
}
|
|
123
143
|
|
|
124
144
|
info( '' );
|
|
145
|
+
|
|
125
146
|
success(
|
|
126
|
-
|
|
147
|
+
plugin
|
|
148
|
+
? `Done: WordPress plugin ${ title } bootstrapped in the ${ slug } directory.`
|
|
149
|
+
: `Done: Block "${ title }" bootstrapped in the ${ slug }directory.`
|
|
127
150
|
);
|
|
128
|
-
|
|
151
|
+
|
|
152
|
+
if ( plugin && wpScripts ) {
|
|
129
153
|
info( '' );
|
|
130
154
|
info( 'You can run several commands inside:' );
|
|
131
155
|
info( '' );
|
|
@@ -149,18 +173,18 @@ module.exports = async (
|
|
|
149
173
|
info( '' );
|
|
150
174
|
code( ' $ npm run packages-update' );
|
|
151
175
|
info( ' Updates WordPress packages to the latest version.' );
|
|
176
|
+
info( '' );
|
|
177
|
+
info( 'To enter the directory type:' );
|
|
178
|
+
info( '' );
|
|
179
|
+
code( ` $ cd ${ slug }` );
|
|
152
180
|
}
|
|
153
|
-
|
|
154
|
-
info( 'To enter the directory type:' );
|
|
155
|
-
info( '' );
|
|
156
|
-
code( ` $ cd ${ slug }` );
|
|
157
|
-
if ( wpScripts ) {
|
|
181
|
+
if ( plugin && wpScripts ) {
|
|
158
182
|
info( '' );
|
|
159
183
|
info( 'You can start development with:' );
|
|
160
184
|
info( '' );
|
|
161
185
|
code( ' $ npm start' );
|
|
162
186
|
}
|
|
163
|
-
if ( wpEnv ) {
|
|
187
|
+
if ( plugin && wpEnv ) {
|
|
164
188
|
info( '' );
|
|
165
189
|
info( 'You can start WordPress with:' );
|
|
166
190
|
info( '' );
|
|
@@ -18,7 +18,9 @@ import './style.scss';
|
|
|
18
18
|
* Internal dependencies
|
|
19
19
|
*/
|
|
20
20
|
import Edit from './edit';
|
|
21
|
+
{{#isStaticVariant}}
|
|
21
22
|
import save from './save';
|
|
23
|
+
{{/isStaticVariant}}
|
|
22
24
|
import metadata from './block.json';
|
|
23
25
|
|
|
24
26
|
/**
|
|
@@ -31,8 +33,10 @@ registerBlockType( metadata.name, {
|
|
|
31
33
|
* @see ./edit.js
|
|
32
34
|
*/
|
|
33
35
|
edit: Edit,
|
|
36
|
+
{{#isStaticVariant}}
|
|
34
37
|
/**
|
|
35
38
|
* @see ./save.js
|
|
36
39
|
*/
|
|
37
40
|
save,
|
|
41
|
+
{{/isStaticVariant}}
|
|
38
42
|
} );
|
|
@@ -68,7 +68,7 @@ function {{namespaceSnakeCase}}_{{slugSnakeCase}}_block_init() {
|
|
|
68
68
|
array(),
|
|
69
69
|
filemtime( "$dir/$style_css" )
|
|
70
70
|
);
|
|
71
|
-
|
|
71
|
+
{{^isDynamicVariant}}
|
|
72
72
|
register_block_type(
|
|
73
73
|
'{{namespace}}/{{slug}}',
|
|
74
74
|
array(
|
|
@@ -77,5 +77,33 @@ function {{namespaceSnakeCase}}_{{slugSnakeCase}}_block_init() {
|
|
|
77
77
|
'style' => '{{namespace}}-{{slug}}-block',
|
|
78
78
|
)
|
|
79
79
|
);
|
|
80
|
+
{{/isDynamicVariant}}
|
|
81
|
+
{{#isDynamicVariant}}
|
|
82
|
+
register_block_type(
|
|
83
|
+
'{{namespace}}/{{slug}}',
|
|
84
|
+
array(
|
|
85
|
+
'editor_script' => '{{namespace}}-{{slug}}-block-editor',
|
|
86
|
+
'editor_style' => '{{namespace}}-{{slug}}-block-editor',
|
|
87
|
+
'style' => '{{namespace}}-{{slug}}-block',
|
|
88
|
+
'render_callback' => '{{namespaceSnakeCase}}_{{slugSnakeCase}}_render_callback',
|
|
89
|
+
)
|
|
90
|
+
);
|
|
91
|
+
{{/isDynamicVariant}}
|
|
80
92
|
}
|
|
81
93
|
add_action( 'init', '{{namespaceSnakeCase}}_{{slugSnakeCase}}_block_init' );
|
|
94
|
+
{{#isDynamicVariant}}
|
|
95
|
+
/**
|
|
96
|
+
* Render callback function
|
|
97
|
+
*
|
|
98
|
+
* @param array $attributes The block attributes.
|
|
99
|
+
* @param string $content The block content.
|
|
100
|
+
* @param WP_Block $block Block instance.
|
|
101
|
+
*
|
|
102
|
+
* @return string The rendered output.
|
|
103
|
+
*/
|
|
104
|
+
function {{namespaceSnakeCase}}_{{slugSnakeCase}}_render_callback( $atts, $content, $block) {
|
|
105
|
+
ob_start();
|
|
106
|
+
require plugin_dir_path( __FILE__ ) . '/template.php';
|
|
107
|
+
return ob_get_clean();
|
|
108
|
+
}
|
|
109
|
+
{{/isDynamicVariant}}
|
|
@@ -94,8 +94,7 @@
|
|
|
94
94
|
useBlockProps(),
|
|
95
95
|
__( '{{title}} – hello from the editor!', '{{textdomain}}' )
|
|
96
96
|
);
|
|
97
|
-
},
|
|
98
|
-
|
|
97
|
+
}{{#isStaticVariant}},
|
|
99
98
|
/**
|
|
100
99
|
* The save function defines the way in which the different attributes should be combined
|
|
101
100
|
* into the final markup, which is then serialized by the block editor into `post_content`.
|
|
@@ -111,6 +110,7 @@
|
|
|
111
110
|
'{{title}} – hello from the saved content!',
|
|
112
111
|
);
|
|
113
112
|
},
|
|
113
|
+
{{/isStaticVariant}}
|
|
114
114
|
} );
|
|
115
115
|
}(
|
|
116
116
|
window.wp
|
|
@@ -37,7 +37,35 @@
|
|
|
37
37
|
*
|
|
38
38
|
* @see https://developer.wordpress.org/reference/functions/register_block_type/
|
|
39
39
|
*/
|
|
40
|
+
{{#isStaticVariant}}
|
|
40
41
|
function {{namespaceSnakeCase}}_{{slugSnakeCase}}_block_init() {
|
|
41
42
|
register_block_type( __DIR__ . '/build' );
|
|
42
43
|
}
|
|
43
44
|
add_action( 'init', '{{namespaceSnakeCase}}_{{slugSnakeCase}}_block_init' );
|
|
45
|
+
{{/isStaticVariant}}
|
|
46
|
+
{{#isDynamicVariant}}
|
|
47
|
+
function {{namespaceSnakeCase}}_{{slugSnakeCase}}_block_init() {
|
|
48
|
+
register_block_type(
|
|
49
|
+
__DIR__ . '/build',
|
|
50
|
+
array(
|
|
51
|
+
'render_callback' => '{{namespaceSnakeCase}}_{{slugSnakeCase}}_render_callback',
|
|
52
|
+
)
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
add_action( 'init', '{{namespaceSnakeCase}}_{{slugSnakeCase}}_block_init' );
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Render callback function
|
|
59
|
+
*
|
|
60
|
+
* @param array $attributes The block attributes.
|
|
61
|
+
* @param string $content The block content.
|
|
62
|
+
* @param WP_Block $block Block instance.
|
|
63
|
+
*
|
|
64
|
+
* @return string The rendered output.
|
|
65
|
+
*/
|
|
66
|
+
function {{namespaceSnakeCase}}_{{slugSnakeCase}}_render_callback( $atts, $content, $block) {
|
|
67
|
+
ob_start();
|
|
68
|
+
require plugin_dir_path( __FILE__ ) . 'build/template.php';
|
|
69
|
+
return ob_get_clean();
|
|
70
|
+
}
|
|
71
|
+
{{/isDynamicVariant}}
|
package/lib/templates.js
CHANGED
|
@@ -24,7 +24,7 @@ const predefinedPluginTemplates = {
|
|
|
24
24
|
slug: 'example-static-es5',
|
|
25
25
|
title: 'Example Static (ES5)',
|
|
26
26
|
description:
|
|
27
|
-
'Example
|
|
27
|
+
'Example block scaffolded with Create Block tool – no build step required.',
|
|
28
28
|
dashicon: 'smiley',
|
|
29
29
|
wpScripts: false,
|
|
30
30
|
editorScript: 'file:./index.js',
|
|
@@ -32,18 +32,31 @@ const predefinedPluginTemplates = {
|
|
|
32
32
|
style: 'file:./style.css',
|
|
33
33
|
},
|
|
34
34
|
templatesPath: join( __dirname, 'templates', 'es5' ),
|
|
35
|
+
variants: {
|
|
36
|
+
static: {},
|
|
37
|
+
dynamic: {
|
|
38
|
+
slug: 'example-dynamic-es5',
|
|
39
|
+
title: 'Example Dynamic (ES5)',
|
|
40
|
+
},
|
|
41
|
+
},
|
|
35
42
|
},
|
|
36
|
-
|
|
43
|
+
standard: {
|
|
37
44
|
defaultValues: {
|
|
38
45
|
slug: 'example-static',
|
|
39
46
|
title: 'Example Static',
|
|
40
|
-
description:
|
|
41
|
-
'Example static block scaffolded with Create Block tool.',
|
|
47
|
+
description: 'Example block scaffolded with Create Block tool.',
|
|
42
48
|
dashicon: 'smiley',
|
|
43
49
|
supports: {
|
|
44
50
|
html: false,
|
|
45
51
|
},
|
|
46
52
|
},
|
|
53
|
+
variants: {
|
|
54
|
+
static: {},
|
|
55
|
+
dynamic: {
|
|
56
|
+
slug: 'example-dynamic',
|
|
57
|
+
title: 'Example Dynamic',
|
|
58
|
+
},
|
|
59
|
+
},
|
|
47
60
|
},
|
|
48
61
|
};
|
|
49
62
|
|
|
@@ -100,6 +113,7 @@ const configToTemplate = async ( {
|
|
|
100
113
|
blockTemplatesPath,
|
|
101
114
|
defaultValues = {},
|
|
102
115
|
assetsPath,
|
|
116
|
+
variants,
|
|
103
117
|
...deprecated
|
|
104
118
|
} ) => {
|
|
105
119
|
if ( defaultValues === null || typeof defaultValues !== 'object' ) {
|
|
@@ -129,6 +143,7 @@ const configToTemplate = async ( {
|
|
|
129
143
|
defaultValues,
|
|
130
144
|
outputAssets: assetsPath ? await getOutputAssets( assetsPath ) : {},
|
|
131
145
|
pluginOutputTemplates: await getOutputTemplates( pluginTemplatesPath ),
|
|
146
|
+
variants,
|
|
132
147
|
};
|
|
133
148
|
};
|
|
134
149
|
|
|
@@ -197,7 +212,7 @@ const getPluginTemplate = async ( templateName ) => {
|
|
|
197
212
|
}
|
|
198
213
|
};
|
|
199
214
|
|
|
200
|
-
const getDefaultValues = ( pluginTemplate ) => {
|
|
215
|
+
const getDefaultValues = ( pluginTemplate, variant ) => {
|
|
201
216
|
return {
|
|
202
217
|
$schema: 'https://schemas.wp.org/trunk/block.json',
|
|
203
218
|
apiVersion: 2,
|
|
@@ -216,12 +231,25 @@ const getDefaultValues = ( pluginTemplate ) => {
|
|
|
216
231
|
editorStyle: 'file:./index.css',
|
|
217
232
|
style: 'file:./style-index.css',
|
|
218
233
|
...pluginTemplate.defaultValues,
|
|
234
|
+
...pluginTemplate.variants[ variant ],
|
|
219
235
|
};
|
|
220
236
|
};
|
|
221
237
|
|
|
222
|
-
const getPrompts = ( pluginTemplate, keys ) => {
|
|
238
|
+
const getPrompts = ( pluginTemplate, keys, variant ) => {
|
|
223
239
|
const defaultValues = getDefaultValues( pluginTemplate );
|
|
240
|
+
const variantData = pluginTemplate.variants[ variant ] ?? false;
|
|
224
241
|
return keys.map( ( promptName ) => {
|
|
242
|
+
if ( promptName === 'variant' ) {
|
|
243
|
+
prompts[ promptName ].choices = Object.keys(
|
|
244
|
+
pluginTemplate.variants
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
if ( variantData && variantData[ promptName ] ) {
|
|
248
|
+
return {
|
|
249
|
+
...prompts[ promptName ],
|
|
250
|
+
default: variantData[ promptName ],
|
|
251
|
+
};
|
|
252
|
+
}
|
|
225
253
|
return {
|
|
226
254
|
...prompts[ promptName ],
|
|
227
255
|
default: defaultValues[ promptName ],
|
|
@@ -229,8 +257,34 @@ const getPrompts = ( pluginTemplate, keys ) => {
|
|
|
229
257
|
} );
|
|
230
258
|
};
|
|
231
259
|
|
|
260
|
+
const getTemplateVariantVars = ( variants, variant ) => {
|
|
261
|
+
const variantVars = {};
|
|
262
|
+
if ( variants ) {
|
|
263
|
+
const variantNames = Object.keys( variants );
|
|
264
|
+
const chosenVariant = variant ?? variantNames[ 0 ]; // If no variant is passed, use the first in the array as the default
|
|
265
|
+
|
|
266
|
+
if ( variantNames.includes( chosenVariant ) ) {
|
|
267
|
+
for ( const variantName of variantNames ) {
|
|
268
|
+
const key =
|
|
269
|
+
variantName.charAt( 0 ).toUpperCase() +
|
|
270
|
+
variantName.slice( 1 );
|
|
271
|
+
variantVars[ `is${ key }Variant` ] =
|
|
272
|
+
chosenVariant === variantName ?? false;
|
|
273
|
+
}
|
|
274
|
+
} else {
|
|
275
|
+
throw new CLIError(
|
|
276
|
+
`"${ chosenVariant }" is not a valid variant for this template. Available variants are: ${ variantNames.join(
|
|
277
|
+
', '
|
|
278
|
+
) }`
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return variantVars;
|
|
283
|
+
};
|
|
284
|
+
|
|
232
285
|
module.exports = {
|
|
233
286
|
getPluginTemplate,
|
|
234
287
|
getDefaultValues,
|
|
235
288
|
getPrompts,
|
|
289
|
+
getTemplateVariantVars,
|
|
236
290
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wordpress/create-block",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.1-next.d6164808d3.0",
|
|
4
4
|
"description": "Generates PHP, JS and CSS code for registering a block for a WordPress plugin.",
|
|
5
5
|
"author": "The WordPress Contributors",
|
|
6
6
|
"license": "GPL-2.0-or-later",
|
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
"url": "https://github.com/WordPress/gutenberg/issues"
|
|
21
21
|
},
|
|
22
22
|
"engines": {
|
|
23
|
-
"node": ">=
|
|
24
|
-
"npm": ">=6.
|
|
23
|
+
"node": ">=14",
|
|
24
|
+
"npm": ">=6.14.4"
|
|
25
25
|
},
|
|
26
26
|
"files": [
|
|
27
27
|
"lib"
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"wp-create-block": "./index.js"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@wordpress/lazy-import": "^1.4.
|
|
34
|
+
"@wordpress/lazy-import": "^1.4.3-next.d6164808d3.0",
|
|
35
35
|
"chalk": "^4.0.0",
|
|
36
36
|
"change-case": "^4.1.2",
|
|
37
37
|
"check-node-version": "^4.1.0",
|
|
@@ -39,7 +39,6 @@
|
|
|
39
39
|
"execa": "^4.0.2",
|
|
40
40
|
"fast-glob": "^3.2.7",
|
|
41
41
|
"inquirer": "^7.1.0",
|
|
42
|
-
"lodash": "^4.17.21",
|
|
43
42
|
"make-dir": "^3.0.0",
|
|
44
43
|
"mustache": "^4.0.0",
|
|
45
44
|
"npm-package-arg": "^8.1.5",
|
|
@@ -49,5 +48,5 @@
|
|
|
49
48
|
"publishConfig": {
|
|
50
49
|
"access": "public"
|
|
51
50
|
},
|
|
52
|
-
"gitHead": "
|
|
51
|
+
"gitHead": "ba8a396d2f418e53a6c4c50575582f3f3eb11ff7"
|
|
53
52
|
}
|