forked from vuejs/vue-cli
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgenerate.js
137 lines (124 loc) · 3.46 KB
/
generate.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
var Metalsmith = require('metalsmith')
var Handlebars = require('handlebars')
var async = require('async')
var render = require('consolidate').handlebars.render
var path = require('path')
var multimatch = require('multimatch')
var getOptions = require('./options')
var ask = require('./ask')
var filter = require('./filter')
// register handlebars helper
Handlebars.registerHelper('if_eq', function (a, b, opts) {
return a === b
? opts.fn(this)
: opts.inverse(this)
})
Handlebars.registerHelper('unless_eq', function (a, b, opts) {
return a === b
? opts.inverse(this)
: opts.fn(this)
})
/**
* Generate a template given a `src` and `dest`.
*
* @param {String} name
* @param {String} src
* @param {String} dest
* @param {Function} done
*/
module.exports = function generate (name, src, dest, done) {
var opts = getOptions(name, src)
var metalsmith = Metalsmith(path.join(src, 'template'))
var data = Object.assign(metalsmith.metadata(), {
destDirName: name,
inPlace: dest === process.cwd(),
noEscape: true
})
opts.helpers && Object.keys(opts.helpers).map(function (key) {
Handlebars.registerHelper(key, opts.helpers[key])
})
metalsmith
.use(askQuestions(opts.prompts))
.use(filterFiles(opts.filters))
.use(renderTemplateFiles(opts.skipInterpolation))
.clean(false)
.source('.') // start from template root instead of `./src` which is Metalsmith's default for `source`
.destination(dest)
.build(function (err) {
done(err)
logMessage(opts.completeMessage, data)
})
return data
}
/**
* Create a middleware for asking questions.
*
* @param {Object} prompts
* @return {Function}
*/
function askQuestions (prompts) {
return function (files, metalsmith, done) {
ask(prompts, metalsmith.metadata(), done)
}
}
/**
* Create a middleware for filtering files.
*
* @param {Object} filters
* @return {Function}
*/
function filterFiles (filters) {
return function (files, metalsmith, done) {
filter(files, filters, metalsmith.metadata(), done)
}
}
/**
* Template in place plugin.
*
* @param {Object} files
* @param {Metalsmith} metalsmith
* @param {Function} done
*/
function renderTemplateFiles (skipInterpolation) {
skipInterpolation = typeof skipInterpolation === 'string'
? [skipInterpolation]
: skipInterpolation
return function (files, metalsmith, done) {
var keys = Object.keys(files)
var metalsmithMetadata = metalsmith.metadata()
async.each(keys, function (file, next) {
// skipping files with skipInterpolation option
if (skipInterpolation && multimatch([file], skipInterpolation, { dot: true }).length) {
return next()
}
var str = files[file].contents.toString()
// do not attempt to render files that do not have mustaches
if (!/{{([^{}]+)}}/g.test(str)) {
return next()
}
render(str, metalsmithMetadata, function (err, res) {
if (err) return next(err)
files[file].contents = new Buffer(res)
next()
})
}, done)
}
}
/**
* Display template complete message.
*
* @param {String} message
* @param {Object} data
*/
function logMessage (message, data) {
if (!message) return
render(message, data, function (err, res) {
if (err) {
console.error('\n Error when rendering template complete message: ' + err.message.trim())
} else {
console.log('\n' + res.split(/\r?\n/g).map(function (line) {
return ' ' + line
}).join('\n'))
}
})
}