UNPKG

2.51 kBJavaScriptView Raw
1const minimatch = require('minimatch')
2const Metalsmith = require('metalsmith')
3
4const { template } = require('../common')
5
6const filter = filters => (files, metalsmith, next) => {
7 if (!filters) return next()
8 const metadata = metalsmith.metadata()
9 const filenames = Object.keys(files)
10 Object.keys(filters)
11 .filter(glob => !filters[glob](metadata))
12 .forEach(glob => {
13 const match = minimatch.filter(glob, { dot: true, matchBase: true })
14 filenames.forEach(file => match(file) && delete files[file])
15 })
16 next()
17}
18
19const rename = () => (files, metalsmith, next) => {
20 const metadata = metalsmith.metadata()
21
22 const filenames = Object.keys(files)
23 filenames.forEach(original => {
24 // // windows path
25 // original = original.replace('\\', '\\\\')
26 const current = template.render(original, metadata)
27 if (current === original) return
28 // rename it
29 files[current] = files[original]
30 delete files[original]
31 })
32
33 next()
34}
35
36const render = helpers => (files, metalsmith, next) => {
37 const metadata = metalsmith.metadata()
38
39 for (const name in files) {
40 let contents = files[name].contents.toString()
41
42 // ignore files that do not have interpolate
43 // https://github.com/lodash/lodash/blob/master/.internal/reEvaluate.js
44 // https://github.com/lodash/lodash/blob/master/template.js#L19
45 if (!(/<%([\s\S]+?)%>/.test(contents) || /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/.test(contents))) {
46 continue
47 }
48
49 contents = template.render(contents, metadata)
50 files[name].contents = Buffer.from(contents)
51 }
52
53 next()
54}
55
56/**
57 * Generate files from template
58 * @param {String} src source path
59 * @param {String} dest destination path
60 * @param {Object} answers answers
61 * @param {Object} options template options
62 */
63module.exports = (src, dest, answers, options = {}) => new Promise((resolve, reject) => {
64 const { source, metadata, filters, helpers, plugin } = options
65
66 const metalsmith = Metalsmith(src)
67
68 metalsmith.metadata(Object.assign({}, metadata, answers))
69
70 // helpers
71 helpers && template.registerHelpers(helpers)
72
73 // plugin
74 typeof plugin === 'function' && metalsmith.use(plugin)
75
76 // filter
77 metalsmith.use(filter(filters))
78
79 // files rename
80 metalsmith.use(rename())
81
82 // template render
83 metalsmith.use(render(helpers))
84
85 metalsmith.source(source || 'template')
86 metalsmith.destination(dest)
87 metalsmith.clean(false)
88
89 metalsmith.build((err, files) => {
90 if (err) return reject(err)
91 resolve(files)
92 })
93})