-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
101 lines (91 loc) · 2.93 KB
/
index.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
#!/usr/bin/env node
const fs = require('fs-extra')
const glob = require('fast-glob')
const ejs = require('ejs')
const path = require('path')
const chokidar = require('chokidar')
const condense = require('condense-newlines')
const beautify = require('js-beautify').html
const log = console.log.bind(console)
class compiler {
constructor() {
this.input = this.argv('input')
this.data = this.argv('data')
this.output = this.argv('output')
this.watch = this.argv('watch')
this.delay = this.argv('delay') || 200
this.target = `${this.input}/**/!(_*).ejs`
}
argv(key) {
const arg = process.argv.filter(val => val.startsWith('--' + key))
return arg.length ? arg.pop().split('=').pop() : null
}
async run() {
this.watch ? await this.watcher() : await this.render()
}
async compile(file) {
log(`Processing: ${file}`)
return await new Promise(async resolve => {
let content = await ejs.renderFile(file, fs.readJsonSync(this.data))
content = condense(content)
content = beautify(content, {
indent_size: 2,
unformatted: ['pre', 'code'],
})
let dest = file.replace(this.input, this.output).slice(0, -3) + 'html'
fs.outputFile(dest, content).catch(err => log(err)).finally(resolve)
})
}
async render() {
const start = performance.now()
await Promise.all((await glob(this.target)).map(file => this.compile(file)))
const finish = performance.now()
log(`Done in ${Math.round(finish - start)} ms`)
}
async watcher() {
chokidar.watch(this.input, {
ignoreInitial: true,
})
.on('all', async (event, filePath) => {
const target = filePath.replace(/\\/g, '/')
setTimeout(async () => {
if ((event === 'add' || event === 'change') && target !== this.data) {
const filename = path.basename(target)
if (filename.startsWith('_')) {
await this.setTarget(filename)
}
else {
this.target = target
}
}
else {
this.target = `${this.input}/**/!(_*).ejs`
}
await this.render()
}, this.delay)
})
.on('ready', () => log('Waiting for file changes...'))
}
async setTarget(target) {
return await new Promise(async resolve => {
const partial = path.parse(target).name
let targets = []
await new Promise(async resolve => {
const files = await glob(`${this.input}/**/!(_*).ejs`)
files.forEach(file => {
let content = fs.readFileSync(file, 'utf-8').match(/include\(\s*(['"])(.+?)\1\s*(,\s*({.+?})\s*)?\)/g)
content = content ? content.join('') : ''
if (content.includes(partial + "'") || content.includes(partial + '"')) {
targets.push(file)
}
resolve()
})
})
this.target = targets
resolve()
})
}
}
(async function () {
await new compiler().run()
})()