forked from stencila/stencila
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmake.js
More file actions
346 lines (301 loc) · 9.48 KB
/
make.js
File metadata and controls
346 lines (301 loc) · 9.48 KB
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
/* globals __dirname, process */
const b = require('substance-bundler')
const fork = require('substance-bundler/extensions/fork')
const install = require('substance-bundler/extensions/install')
const isInstalled = require('substance-bundler/util/isInstalled')
const path = require('path')
const fs = require('fs')
const merge = require('lodash.merge')
/*
Guide: this is a bundler make file.
It is similar to gulp in that you define tasks which
you can connect by adding dependencies.
This file has the following structure:
- Constants:
Put shared settings and literals here to avoid code duplication
- Functions:
All task implementations
- Tasks:
Task definitions
Run `node make --help` to print usage information.
*/
// Constants
// ---------
const COMMON_SETTINGS = (custom) => { return merge({
// paramaters that are passed to the rollup-commonjs-plugin
commonjs: {
namedExports: { 'acorn/dist/walk.js': [ 'simple', 'base' ] }
},
// for libraries that we want to include into the browser bundle
// but need to be pre-bundled (see buildVendor())
// we register a redirect to the the pre-bundled file
alias: {
'sanitize-html': path.join(__dirname, 'vendor/sanitize-html.min.js')
}
}, custom)}
const UNIFIED_MODULES = {
'unified': 'unified',
'unist-util-visit': 'unistVisit',
'unist-util-find': 'unistFind',
'remark-parse': 'remarkParse',
'remark-squeeze-paragraphs': 'remarkSqueezeParagraphs',
'remark-bracketed-spans': 'remarkBracketedSpans',
'remark-slug': 'remarkSlug',
'remark-html': 'remarkHtml',
'remark-stringify': 'remarkStringify',
'rehype-parse': 'rehypeParse',
'rehype-remark': 'rehype2remark',
'rehype-stringify': 'rehypeStringify'
}
const BROWSER_EXTERNALS = {
'substance': 'window.substance',
'substance-mini': 'window.substanceMini',
'brace': 'window.ace',
'd3': 'window.d3',
'katex': 'window.katex'
}
Object.keys(UNIFIED_MODULES).forEach((moduleName) => {
const alias = UNIFIED_MODULES[moduleName]
BROWSER_EXTERNALS[moduleName] = 'window.unifiedHtmlMarkdown.'+alias
})
const EXAMPLE_EXTERNALS = Object.assign({}, BROWSER_EXTERNALS, {
'stencila': 'window.stencila'
})
const BROWSER_TEST_EXTERNALS = Object.assign({}, BROWSER_EXTERNALS, {
'tape': 'substanceTest.test'
})
const NODEJS_EXTERNALS = [
'substance', 'substance-mini', 'brace', 'd3', 'katex'
].concat(Object.keys(UNIFIED_MODULES))
const NODEJS_TEST_EXTERNALS = NODEJS_EXTERNALS.concat(['tape', 'stream'])
// Functions
// ---------
function copyAssets() {
b.copy('./node_modules/font-awesome', './build/font-awesome')
b.copy('./vendor/brace.*', './build/lib/')
b.copy('./node_modules/d3/build/d3.min.js', './build/lib/')
b.copy('./node_modules/katex/dist/', './build/katex')
b.copy('./node_modules/substance/dist/substance.js*', './build/lib/')
b.copy('./node_modules/substance-mini/dist/substance-mini.js*', './build/lib/')
}
function buildCss() {
b.css('src/pagestyle/stencila.css', 'build/stencila.css', {
variables: true
})
}
function buildStencilaBrowser() {
b.js('index.es.js', COMMON_SETTINGS({
dest: 'build/stencila.js',
format: 'umd', moduleName: 'stencila',
globals: BROWSER_EXTERNALS,
external: NODEJS_EXTERNALS
}))
}
function buildStencilaNodeJS() {
b.js('index.es.js', COMMON_SETTINGS({
dest : 'build/stencila.cjs.js',
format: 'cjs',
// brace is not nodejs compatible'
ignore: [ 'brace' ],
// Externals are not include into the bundle
external: NODEJS_EXTERNALS,
}))
}
function buildExamples() {
b.copy('./examples/*/*.html', './build/')
//
;['document', 'sheet', 'dashboard'].forEach((example) => {
b.js(`examples/${example}/app.js`, {
dest: `build/examples/${example}/app.js`,
format: 'umd', moduleName: `${example}Example`,
external: EXAMPLE_EXTERNALS
})
})
}
// reads all fixtures from /tests/ and writes them into a script
function buildTestBackend() {
b.custom('Creating test backend...', {
src: './tests/documents/**/*',
dest: './tmp/test-vfs.js',
execute(files) {
const rootDir = b.rootDir
const vfs = {}
files.forEach((f) => {
if (b.isDirectory(f)) return
let content = fs.readFileSync(f).toString()
let relPath = path.relative(rootDir, f).replace(/\\/g, '/')
vfs[relPath] = content
})
const data = ['export default ', JSON.stringify(vfs, null, 2)].join('')
b.writeSync('tmp/test-vfs.js', data)
}
})
}
function buildBrowserTests() {
b.js('tests/**/*.test.js', COMMON_SETTINGS({
dest: 'tmp/tests.js',
format: 'umd',
moduleName: 'tests',
external: BROWSER_TEST_EXTERNALS
}))
}
function buildNodeJSTests() {
b.js('tests/**/*.test.js', COMMON_SETTINGS({
dest: 'tmp/tests.cjs.js',
format: 'cjs',
external: NODEJS_TEST_EXTERNALS,
// brace is not nodejs compatible'
ignore: [ 'brace' ],
}))
}
function buildInstrumentedTests() {
// TODO: we must include the whole source code to see the real coverage
// right now we only see the coverage on the files which
// are actually imported by tests.
b.js(['index.es.js', 'tests/**/*.test.js'], COMMON_SETTINGS({
dest: 'tmp/tests.cov.js',
format: 'cjs',
istanbul: {
include: ['src/**/*.js']
},
// brace is not nodejs compatible'
ignore: [ 'brace' ],
// these should be used directly from nodejs, not bundled
external: NODEJS_TEST_EXTERNALS.concat(['stream'])
}))
}
function buildSingleTest(testFile) {
const dest = path.join(__dirname, 'tmp', testFile)
b.js(testFile, COMMON_SETTINGS({
dest: dest,
format: 'cjs',
external: NODEJS_TEST_EXTERNALS
}))
return dest
}
// this is not run all the time
// we use it to pre-bundle vendor libraries,
// to speed up bundling within this project
// and to work around problems with using rollup on these projects
function buildVendor() {
install(b, 'browserify', '^14.1.0')
install(b, 'uglify-js-harmony', '^2.7.5')
// minifiedVendor('./node_modules/sanitize-html/index.js', 'sanitize-html', {
// exports: ['default']
// })
// minifiedVendor('./vendor/_brace.js', 'brace')
minifiedVendor('./vendor/_unified.js', 'unified-html-markdown')
}
function minifiedVendor(src, name, opts = {}) {
let tmp = `./vendor/${name}.js`
let _opts = Object.assign({
dest: tmp,
debug: false
})
if (opts.exports) {
_opts.exports = opts.exports
}
if (opts.standalone) {
_opts.browserify = { standalone: name }
}
b.browserify(src, _opts)
if (opts.minify !== false) {
b.minify(tmp, {
debug: false
})
b.rm(tmp)
}
}
// we need this only temporarily, or if we need to work on an
// unpublished version of substance
function buildDeps() {
const subsDist = path.join(__dirname, 'node_modules/substance/dist')
if (!fs.existsSync(path.join(subsDist,'substance.js')) ||
!fs.existsSync(path.join(subsDist, 'substance.cjs.js'))) {
b.make('substance')
}
}
function buildDocumentation() {
const config = require.resolve('./docs/docs.yml')
fork(b, "node_modules/documentation/bin/documentation", "build", "--config", config, "--output", "docs", "--format", "html")
}
function serveDocumentation() {
const config = require.resolve('./docs/docs.yml')
fork(b, "node_modules/documentation/bin/documentation", "serve", "--config", config, "--watch")
}
// Tasks
// -----
b.task('clean', () => {
b.rm('build')
b.rm('tmp')
b.rm('coverage')
})
// This is used to generate the files in ./vendor/
b.task('vendor', buildVendor)
.describe('Creates pre-bundled files in vendor/.')
// NOTE: this will not be necessary if we depend only on npm-published libraries
// At the moment, we use substance from a git branch
b.task('deps', () => {
buildDeps()
})
b.task('assets', () => {
copyAssets()
})
.describe('Copies assets into build folder.')
b.task('css', () => {
buildCss()
})
.describe('Creates a single CSS bundle.')
b.task('stencila', ['clean', 'assets', 'css'], () => {
buildStencilaBrowser()
buildStencilaNodeJS()
})
.describe('Build the stencila library.')
b.task('examples', ['stencila'], () => {
// TODO: Make all examples use the single stencila.js build, so we don't
// need individual builds
buildExamples()
})
.describe('Build the examples.')
b.task('test:backend', () => {
buildTestBackend()
})
b.task('test', ['clean', 'test:backend'], () => {
buildNodeJSTests()
fork(b, 'node_modules/substance-test/bin/test', 'tmp/tests.cjs.js', { verbose: true })
})
.describe('Runs the tests and generates a coverage report.')
b.task('cover', ['clean', 'test:backend'], () => {
buildInstrumentedTests()
fork(b, 'node_modules/substance-test/bin/coverage', 'tmp/tests.cov.js')
})
b.task('test:browser', ['test:backend'], () => {
buildBrowserTests()
})
b.task('test:one', ['test:backend'], () => {
let test = b.argv.f
if (!test) {
console.error("Usage: node make test:one -f <testfile>")
process.exit(-1)
}
let builtTestFile = buildSingleTest(test)
fork(b, 'node_modules/substance-test/bin/test', builtTestFile, { verbose: true })
})
.describe('Runs the tests and generates a coverage report.')
b.task('docs', () => {
if (isInstalled('documentation')) {
buildDocumentation()
} else {
console.error("Please run 'npm install documentation'.\nSkipping task.")
}
})
b.task('docs:serve', () => {
if (isInstalled('documentation')) {
serveDocumentation()
} else {
console.error("Please run 'npm install documentation'.\nSkipping task.")
}
})
b.task('default', ['deps', 'stencila', 'examples'])
.describe('[stencila, examples].')
b.serve({ static: true, route: '/', folder: 'build' })