]>
Commit | Line | Data |
---|---|---|
ae510306 SR |
1 | #!/usr/bin/env node |
2 | ||
3 | var path = require('path'); | |
4 | var program = require('commander'); | |
5 | var fs = require('fs'); | |
6 | var fse = require('fs-extra'); | |
ae510306 | 7 | |
6cae7b58 | 8 | const SUPPORTED_FORMATS = new Set(['amd', 'commonjs', 'systemjs', 'umd']); |
ae510306 SR |
9 | |
10 | program | |
6cae7b58 SR |
11 | .option('--as [format]', `output files using various import formats instead of ES6 import and export. Supports ${Array.from(SUPPORTED_FORMATS)}.`) |
12 | .option('-m, --with-source-maps [type]', 'output source maps when not generating a bundled app (type may be empty for external source maps, inline for inline source maps, or both) ') | |
13 | .option('--with-app', 'process app files as well as core files') | |
ae510306 SR |
14 | .parse(process.argv); |
15 | ||
16 | // the various important paths | |
6cae7b58 | 17 | var main_path = path.resolve(__dirname, '..'); |
ae510306 SR |
18 | var core_path = path.resolve(__dirname, '..', 'core'); |
19 | var app_path = path.resolve(__dirname, '..', 'app'); | |
6cae7b58 | 20 | var vendor_path = path.resolve(__dirname, '..', 'vendor'); |
ae510306 SR |
21 | var out_dir_base = path.resolve(__dirname, '..', 'build'); |
22 | var lib_dir_base = path.resolve(__dirname, '..', 'lib'); | |
23 | ||
6cae7b58 SR |
24 | // walkDir *recursively* walks directories trees, |
25 | // calling the callback for all normal files found. | |
399fa2ee | 26 | var walkDir = function (base_path, cb, filter) { |
6cae7b58 SR |
27 | fs.readdir(base_path, (err, files) => { |
28 | if (err) throw err; | |
ae510306 | 29 | |
6cae7b58 SR |
30 | files.map((filename) => path.join(base_path, filename)).forEach((filepath) => { |
31 | fs.lstat(filepath, (err, stats) => { | |
32 | if (err) throw err; | |
ae510306 | 33 | |
399fa2ee SR |
34 | if (filter !== undefined && !filter(filepath, stats)) return; |
35 | ||
6cae7b58 SR |
36 | if (stats.isSymbolicLink()) return; |
37 | if (stats.isFile()) cb(filepath); | |
399fa2ee | 38 | if (stats.isDirectory()) walkDir(filepath, cb, filter); |
ae510306 SR |
39 | }); |
40 | }); | |
41 | }); | |
6cae7b58 | 42 | }; |
ae510306 | 43 | |
6cae7b58 | 44 | var transform_html = function (new_script) { |
ae510306 SR |
45 | // write out the modified vnc.html file that works with the bundle |
46 | var src_html_path = path.resolve(__dirname, '..', 'vnc.html'); | |
47 | var out_html_path = path.resolve(out_dir_base, 'vnc.html'); | |
6cae7b58 | 48 | fs.readFile(src_html_path, (err, contents_raw) => { |
ae510306 SR |
49 | if (err) { throw err; } |
50 | ||
51 | var contents = contents_raw.toString(); | |
ae510306 SR |
52 | |
53 | var start_marker = '<!-- begin scripts -->\n'; | |
54 | var end_marker = '<!-- end scripts -->'; | |
55 | var start_ind = contents.indexOf(start_marker) + start_marker.length; | |
56 | var end_ind = contents.indexOf(end_marker, start_ind); | |
57 | ||
6cae7b58 | 58 | contents = contents.slice(0, start_ind) + `${new_script}\n` + contents.slice(end_ind); |
ae510306 | 59 | |
6cae7b58 | 60 | console.log(`Writing ${out_html_path}`); |
ae510306 SR |
61 | fs.writeFile(out_html_path, contents, function (err) { |
62 | if (err) { throw err; } | |
ae510306 SR |
63 | }); |
64 | }); | |
6cae7b58 | 65 | } |
ae510306 | 66 | |
6cae7b58 SR |
67 | var make_lib_files = function (import_format, source_maps, with_app_dir) { |
68 | if (!import_format) { | |
69 | throw new Error("you must specify an import format to generate compiled noVNC libraries"); | |
70 | } else if (!SUPPORTED_FORMATS.has(import_format)) { | |
71 | throw new Error(`unsupported output format "${import_format}" for import/export -- only ${Array.from(SUPPORTED_FORMATS)} are supported`); | |
72 | } | |
73 | ||
74 | // NB: we need to make a copy of babel_opts, since babel sets some defaults on it | |
75 | const babel_opts = () => ({ | |
76 | plugins: [`transform-es2015-modules-${import_format}`], | |
77 | ast: false, | |
78 | sourceMaps: source_maps, | |
79 | }); | |
80 | const babel = require('babel-core'); | |
81 | ||
82 | var in_path; | |
83 | if (with_app_dir) { | |
84 | var out_path_base = out_dir_base; | |
85 | in_path = main_path; | |
86 | } else { | |
87 | var out_path_base = lib_dir_base; | |
88 | } | |
89 | ||
90 | fse.ensureDirSync(out_path_base); | |
91 | ||
92 | const helpers = require('./use_require_helpers'); | |
93 | const helper = helpers[import_format]; | |
94 | ||
95 | var handleDir = (js_only, in_path_base, filename) => { | |
96 | const out_path = path.join(out_path_base, path.relative(in_path_base, filename)); | |
97 | if(path.extname(filename) !== '.js') { | |
98 | if (!js_only) { | |
99 | console.log(`Writing ${out_path}`); | |
100 | fse.copy(filename, out_path, (err) => { if (err) throw err; }); | |
ae510306 | 101 | } |
6cae7b58 | 102 | return; // skip non-javascript files |
ae510306 | 103 | } |
ae510306 | 104 | |
6cae7b58 SR |
105 | fse.ensureDir(path.dirname(out_path), () => { |
106 | const opts = babel_opts(); | |
107 | if (helper && helpers.optionsOverride) { | |
108 | helper.optionsOverride(opts); | |
109 | } | |
110 | babel.transformFile(filename, babel_opts(), (err, res) => { | |
111 | console.log(`Writing ${out_path}`); | |
112 | if (err) throw err; | |
113 | var {code, map, ast} = res; | |
114 | if (source_maps === true) { | |
115 | // append URL for external source map | |
116 | code += `\n//# sourceMappingURL=${path.basename(out_path)}.map\n`; | |
117 | } | |
118 | fs.writeFile(out_path, code, (err) => { if (err) throw err; }); | |
119 | if (source_maps === true || source_maps === 'both') { | |
120 | console.log(` and ${out_path}.map`); | |
121 | fs.writeFile(`${out_path}.map`, JSON.stringify(map), (err) => { if (err) throw err; }); | |
122 | } | |
123 | }); | |
124 | }); | |
125 | }; | |
126 | ||
127 | walkDir(core_path, handleDir.bind(null, true, in_path || core_path)); | |
399fa2ee | 128 | walkDir(vendor_path, handleDir.bind(null, true, in_path || main_path), (filepath, stats) => !((stats.isDirectory() && path.basename(filepath) === 'browser-es-module-loader') || path.basename(filepath) === 'sinon.js')); |
6cae7b58 SR |
129 | |
130 | if (with_app_dir) { | |
131 | walkDir(app_path, handleDir.bind(null, false, in_path || app_path)); | |
132 | ||
133 | const out_app_path = path.join(out_path_base, 'app.js'); | |
134 | if (helper && helper.appWriter) { | |
135 | console.log(`Writing ${out_app_path}`); | |
136 | let out_script = helper.appWriter(out_path_base, out_app_path); | |
137 | transform_html(out_script); | |
138 | } else { | |
139 | console.error(`Unable to generate app for the ${import_format} format!`); | |
140 | } | |
141 | } | |
ae510306 SR |
142 | }; |
143 | ||
6cae7b58 | 144 | make_lib_files(program.as, program.withSourceMaps, program.withApp); |