-
Notifications
You must be signed in to change notification settings - Fork 36
/
build.js
120 lines (107 loc) · 3.1 KB
/
build.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
const { promises: fs, watch } = require('fs')
const path = require("path")
const child_process = require('child_process')
require('events').defaultMaxListeners = 100
const SRC = 'src'
const DIST = 'dist'
const LANG = (process.env.LANG || '').replace(/\..*/, '')
.replace(/[^-0-9a-zA-Z_]/g, '')
const LANG_ARG = LANG ? ` --locale ${LANG} ` : ''
const CSON_BIN_FIX = process.platform === 'win32' ? 'cson2json/../' : ''
const BUILDERS = {
ts: {},
pug: {},
cson: {
to: 'json',
cmd: (s, d) => `cson2json ${CSON_BIN_FIX}${s} > ${d}`,
},
styl: {
to: 'css',
cmd: (s, d) => `stylus < ${s} > ${d}`
}
}
const EXTRA_BUILD = [
`tsc ${LANG_ARG}`,
`pug -P -s -o ${DIST} ${SRC}`,
]
const EXTRA_WATCH = [
`tsc -w --sourceMap ${LANG_ARG}`,
`pug -w -P -s -o ${DIST} ${SRC}`,
]
const DEFAULT_MESSAGES = '_locales/en/messages.cson'
async function mkdirs(d) {
try {
await fs.mkdir(path.dirname(d), { recursive: true })
} catch (error) {
if (error.code !== 'EEXIST') throw error
}
}
function call(cmd) {
return new Promise((resolve, reject) => {
const child = child_process.exec(cmd)
child.stdout.pipe(process.stdout)
child.stderr.pipe(process.stderr)
child.on('error', reject)
child.on('exit', resolve)
})
}
async function build(s) {
let d = path.posix.join(DIST, path.posix.relative(SRC, s))
const ext = s.replace(/.*\./, '')
const builder = BUILDERS[ext]
if (!builder) {
await mkdirs(d)
await new Promise(r => setTimeout(r, 1))
await fs.copyFile(s, d)
return
} else if (builder.cmd) {
d = `${d.slice(0, -ext.length)}${builder.to}`
await mkdirs(d)
await call(builder.cmd(s, d))
}
}
async function buildMessages() {
const d = 'typings/generated/messages.d.ts'
await mkdirs(d)
let content = 'interface I18nMessages {\n'
for (const line of
(await fs.readFile(`${SRC}/${DEFAULT_MESSAGES}`, 'utf-8')).split(/\r|\n/)) {
const [matched, key] = line.match(/^(\w+):\s*(?:#|$)/) || []
if (matched) content += `\t${key}: string\n`
}
content += '}\n'
await fs.writeFile(d, content, 'utf-8')
}
async function listFiles(root) {
return !(await fs.stat(root)).isDirectory() ? [root] :
[].concat(...await Promise.all((await fs.readdir(root)).map(
item => listFiles(path.posix.join(root, item)))))
}
process.chdir(__dirname)
process.env.PATH = './node_modules/.bin' +
(process.platform === 'win32' ? ';' : ':') + process.env.PATH
const argv = process.argv.slice(2)
listFiles(SRC).then(async files => {
if (argv.includes('--watch')) {
let messagesPromise = buildMessages()
const builds = {}
for (const file of files) {
builds[file] = messagesPromise.then(() => build(file))
watch(file, {}, () => {
if (file === `${SRC}/${DEFAULT_MESSAGES}`)
messagesPromise = messagesPromise.then(() => buildMessages())
builds[file] = builds[file].then(() => build(file))
})
}
EXTRA_WATCH.forEach(call)
} else /* build */ {
await buildMessages()
await Promise.all([...files.map(build), ...EXTRA_BUILD.map(call)])
if (argv.includes('--xpi')) {
process.chdir(DIST)
await call(argv.includes('--7z') ?
`7z a "../${DIST}.unsigned.xpi"` :
`zip -r -FS "../${DIST}.unsigned.xpi" *`)
}
}
})