1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | const cli = require('../cli')
|
7 | const path = require('path')
|
8 | const exists = require('fs').existsSync
|
9 | const ora = require('ora')
|
10 | const home = require('user-home')
|
11 | const rm = require('rimraf').sync
|
12 | const download = require('download-git-repo')
|
13 |
|
14 | const async = require('async')
|
15 | const ms = require('metalsmith')
|
16 | const inquirer = require('inquirer')
|
17 | const render = require('./render').render
|
18 | const getMeta = require('./meta')
|
19 |
|
20 | const OFFICIAL_VUE_TEMPLATE = 'mipengine/mip-cli-template#vue'
|
21 | const OFFICIAL_TEMPLATE = 'mipengine/mip-cli-template'
|
22 |
|
23 | const VUE_TEMPLATE_TMP = path.resolve(home, '.mip-vue-template')
|
24 | const TEMPLATE_TMP = path.resolve(home, '.mip-template')
|
25 |
|
26 | function downloadRepo (isVue, done) {
|
27 | if (typeof isVue === 'function') {
|
28 | done = isVue
|
29 | isVue = false
|
30 | }
|
31 |
|
32 | let template
|
33 | let tmp
|
34 |
|
35 | if (isVue) {
|
36 | template = OFFICIAL_VUE_TEMPLATE
|
37 |
|
38 | tmp = VUE_TEMPLATE_TMP
|
39 | } else {
|
40 | template = OFFICIAL_TEMPLATE
|
41 | tmp = TEMPLATE_TMP
|
42 | }
|
43 |
|
44 | const spinner = ora('正在获取最新模板')
|
45 | spinner.start()
|
46 |
|
47 |
|
48 | if (exists(tmp)) {
|
49 | rm(tmp)
|
50 | }
|
51 |
|
52 |
|
53 | download(template, tmp, {clone: false}, err => {
|
54 | spinner.stop()
|
55 | if (err) {
|
56 | cli.error('Failed to download repo: ' + err.message.trim())
|
57 | return
|
58 | }
|
59 |
|
60 | done()
|
61 | })
|
62 | }
|
63 |
|
64 |
|
65 |
|
66 |
|
67 |
|
68 |
|
69 |
|
70 |
|
71 | function generate (dir, compName, isVue, done) {
|
72 | if (typeof isVue === 'function') {
|
73 | done = isVue
|
74 | isVue = false
|
75 | }
|
76 |
|
77 | let tmp = isVue ? VUE_TEMPLATE_TMP : TEMPLATE_TMP
|
78 | const metalsmith = ms(path.join(tmp, dir))
|
79 | const templatePrompts = getMeta(tmp).prompts
|
80 |
|
81 | metalsmith
|
82 | .use(ask(templatePrompts))
|
83 | .use(renderTemplateFiles())
|
84 | .clean(false)
|
85 | .source('.')
|
86 | .build(err => {
|
87 | done(err)
|
88 | })
|
89 |
|
90 | function ask (templatePrompts) {
|
91 | return (files, metalsmith, done) => {
|
92 |
|
93 | metalsmith.metadata().compName = compName || 'mip-example'
|
94 |
|
95 |
|
96 | if (compName) {
|
97 | metalsmith.destination(path.resolve('./components', compName))
|
98 |
|
99 | let siteName = process.cwd().split(path.sep).pop()
|
100 | metalsmith.metadata().name = siteName
|
101 | return done()
|
102 | }
|
103 |
|
104 | async.eachSeries(Object.keys(templatePrompts), run, () => {
|
105 |
|
106 | metalsmith.destination(path.resolve('./', metalsmith.metadata().name))
|
107 | done()
|
108 | })
|
109 |
|
110 | function run (key, done) {
|
111 | let prompt = templatePrompts[key]
|
112 |
|
113 | inquirer.prompt([{
|
114 | 'type': prompt.type,
|
115 | 'name': key,
|
116 | 'message': prompt.message || prompt.label || key,
|
117 | 'default': prompt.default,
|
118 | 'validate': prompt.validate || (() => true)
|
119 | }]).then(answers => {
|
120 | if (typeof answers[key] === 'string') {
|
121 | metalsmith.metadata()[key] = answers[key].replace(/"/g, '\\"')
|
122 | } else {
|
123 | metalsmith.metadata()[key] = answers[key]
|
124 | }
|
125 | done()
|
126 | }).catch(done)
|
127 | }
|
128 | }
|
129 | }
|
130 |
|
131 | function renderTemplateFiles () {
|
132 | return (files, metalsmith, done) => {
|
133 | let keys = Object.keys(files)
|
134 | async.each(keys, run, done)
|
135 |
|
136 | function run (file, done) {
|
137 | let str = files[file].contents.toString()
|
138 |
|
139 |
|
140 | if (!/{{([^{}]+)}}/g.test(str)) {
|
141 | return done()
|
142 | }
|
143 |
|
144 | let res
|
145 | try {
|
146 | res = render(str, metalsmith.metadata())
|
147 | } catch (err) {
|
148 | return done(err)
|
149 | }
|
150 |
|
151 | files[file].contents = Buffer.from(res)
|
152 | done()
|
153 | }
|
154 | }
|
155 | }
|
156 | }
|
157 |
|
158 | module.exports = {
|
159 | downloadRepo,
|
160 | generate
|
161 | }
|