Skip to content

Commit 176e55d

Browse files
antfuShinigami92
andauthored
feat(create-app): two-level prompt for framework and variants (#2941)
Co-authored-by: Shinigami <[email protected]>
1 parent 81b80c6 commit 176e55d

File tree

1 file changed

+146
-24
lines changed

1 file changed

+146
-24
lines changed

packages/create-app/index.js

+146-24
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,123 @@
44
const fs = require('fs')
55
const path = require('path')
66
const argv = require('minimist')(process.argv.slice(2))
7+
// eslint-disable-next-line node/no-restricted-require
78
const { prompt } = require('enquirer')
89
const {
910
yellow,
1011
green,
1112
cyan,
13+
blue,
1214
magenta,
1315
lightRed,
14-
red,
15-
stripColors
16+
red
1617
} = require('kolorist')
1718

1819
const cwd = process.cwd()
1920

20-
const TEMPLATES = [
21-
yellow('vanilla'),
22-
yellow('vanilla-ts'),
23-
green('vue'),
24-
green('vue-ts'),
25-
cyan('react'),
26-
cyan('react-ts'),
27-
magenta('preact'),
28-
magenta('preact-ts'),
29-
lightRed('lit-element'),
30-
lightRed('lit-element-ts'),
31-
red('svelte'),
32-
red('svelte-ts')
21+
const FRAMEWORKS = [
22+
{
23+
name: 'vanilla',
24+
color: yellow,
25+
variants: [
26+
{
27+
name: 'vanilla',
28+
display: 'JavaScript',
29+
color: yellow
30+
},
31+
{
32+
name: 'vanilla-ts',
33+
display: 'TypeScript',
34+
color: blue
35+
}
36+
]
37+
},
38+
{
39+
name: 'vue',
40+
color: green,
41+
variants: [
42+
{
43+
name: 'vue',
44+
display: 'JavaScript',
45+
color: yellow
46+
},
47+
{
48+
name: 'vue-ts',
49+
display: 'TypeScript',
50+
color: blue
51+
}
52+
]
53+
},
54+
{
55+
name: 'react',
56+
color: cyan,
57+
variants: [
58+
{
59+
name: 'react',
60+
display: 'JavaScript',
61+
color: yellow
62+
},
63+
{
64+
name: 'react-ts',
65+
display: 'TypeScript',
66+
color: blue
67+
}
68+
]
69+
},
70+
{
71+
name: 'preact',
72+
color: magenta,
73+
variants: [
74+
{
75+
name: 'preact',
76+
display: 'JavaScript',
77+
color: yellow
78+
},
79+
{
80+
name: 'preact-ts',
81+
display: 'TypeScript',
82+
color: blue
83+
}
84+
]
85+
},
86+
{
87+
name: 'lit-element',
88+
color: lightRed,
89+
variants: [
90+
{
91+
name: 'lit-element',
92+
display: 'JavaScript',
93+
color: yellow
94+
},
95+
{
96+
name: 'lit-element-ts',
97+
display: 'TypeScript',
98+
color: blue
99+
}
100+
]
101+
},
102+
{
103+
name: 'svelte',
104+
color: red,
105+
variants: [
106+
{
107+
name: 'svelte',
108+
display: 'JavaScript',
109+
color: yellow
110+
},
111+
{
112+
name: 'svelte-ts',
113+
display: 'TypeScript',
114+
color: blue
115+
}
116+
]
117+
}
33118
]
34119

120+
const TEMPLATES = FRAMEWORKS.map(
121+
(f) => (f.variants && f.variants.map((v) => v.name)) || [f.name]
122+
).reduce((a, b) => a.concat(b), [])
123+
35124
const renameFiles = {
36125
_gitignore: '.gitignore'
37126
}
@@ -52,7 +141,6 @@ async function init() {
52141
}
53142
const packageName = await getValidPackageName(targetDir)
54143
const root = path.join(cwd, targetDir)
55-
console.log(`\nScaffolding project in ${root}...`)
56144

57145
if (!fs.existsSync(root)) {
58146
fs.mkdirSync(root, { recursive: true })
@@ -80,29 +168,63 @@ async function init() {
80168

81169
// determine template
82170
let template = argv.t || argv.template
83-
let message = 'Select a template:'
171+
let message = 'Select a framework:'
84172
let isValidTemplate = false
85173

86174
// --template expects a value
87175
if (typeof template === 'string') {
88-
const availableTemplates = TEMPLATES.map(stripColors)
89-
isValidTemplate = availableTemplates.includes(template)
176+
isValidTemplate = TEMPLATES.includes(template)
90177
message = `${template} isn't a valid template. Please choose from below:`
91178
}
92179

93180
if (!template || !isValidTemplate) {
94181
/**
95-
* @type {{ t: string }}
182+
* @type {{ framework: string }}
96183
*/
97-
const { t } = await prompt({
184+
const { framework } = await prompt({
98185
type: 'select',
99-
name: 't',
186+
name: 'framework',
100187
message,
101-
choices: TEMPLATES
188+
format(name) {
189+
const framework = FRAMEWORKS.find((v) => v.name === name)
190+
return framework
191+
? framework.color(framework.display || framework.name)
192+
: name
193+
},
194+
choices: FRAMEWORKS.map((f) => ({
195+
name: f.name,
196+
value: f.name,
197+
message: f.color(f.display || f.name)
198+
}))
102199
})
103-
template = stripColors(t)
200+
const frameworkInfo = FRAMEWORKS.find((f) => f.name === framework)
201+
202+
if (frameworkInfo.variants) {
203+
/**
204+
* @type {{ name: string }}
205+
*/
206+
const { name } = await prompt({
207+
type: 'select',
208+
name: 'name',
209+
format(name) {
210+
const variant = frameworkInfo.variants.find((v) => v.name === name)
211+
return variant ? variant.color(variant.display || variant.name) : name
212+
},
213+
message: 'Select a variant:',
214+
choices: frameworkInfo.variants.map((v) => ({
215+
name: v.name,
216+
value: v.name,
217+
message: v.color(v.display || v.name)
218+
}))
219+
})
220+
template = name
221+
} else {
222+
template = frameworkInfo.name
223+
}
104224
}
105225

226+
console.log(`\nScaffolding project in ${root}...`)
227+
106228
const templateDir = path.join(__dirname, `template-${template}`)
107229

108230
const write = (file, content) => {

0 commit comments

Comments
 (0)