X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=utils%2Fuse_require.js;h=0dbdb0a883450d606558f162544178750d74126b;hb=HEAD;hp=f0383d094269cdb80c5256a48bae149f67315299;hpb=adfc9d3f548b8d3c7aac837bd53c68b16b14b137;p=mirror_novnc.git diff --git a/utils/use_require.js b/utils/use_require.js index f0383d0..5dd900a 100755 --- a/utils/use_require.js +++ b/utils/use_require.js @@ -1,164 +1,138 @@ #!/usr/bin/env node -var path = require('path'); -var program = require('commander'); -var fs = require('fs'); -var fse = require('fs-extra'); - -const SUPPORTED_FORMATS = new Set(['amd', 'commonjs', 'systemjs', 'umd']); +const path = require('path'); +const program = require('commander'); +const fs = require('fs'); +const fse = require('fs-extra'); +const babel = require('@babel/core'); program - .option('--as [format]', `output files using various import formats instead of ES6 import and export. Supports ${Array.from(SUPPORTED_FORMATS)}.`) .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) ') - .option('--with-app', 'process app files as well as core files') + .option('--clean', 'clear the lib folder before building') .parse(process.argv); // the various important paths -var main_path = path.resolve(__dirname, '..'); -var core_path = path.resolve(__dirname, '..', 'core'); -var app_path = path.resolve(__dirname, '..', 'app'); -var vendor_path = path.resolve(__dirname, '..', 'vendor'); -var out_dir_base = path.resolve(__dirname, '..', 'build'); -var lib_dir_base = path.resolve(__dirname, '..', 'lib'); - -const no_copy_files = new Set([ - // skip these -- they don't belong in the processed application - path.join(vendor_path, 'sinon.js'), - path.join(vendor_path, 'browser-es-module-loader'), -]); - -const no_transform_files = new Set([ - // don't transform this -- we want it imported as-is to properly catch loading errors - path.join(app_path, 'error-handler.js'), -]); - -// walkDir *recursively* walks directories trees, -// calling the callback for all normal files found. -var walkDir = function (base_path, cb, filter) { - fs.readdir(base_path, (err, files) => { - if (err) throw err; - - files.map((filename) => path.join(base_path, filename)).forEach((filepath) => { - fs.lstat(filepath, (err, stats) => { - if (err) throw err; - - if (filter !== undefined && !filter(filepath, stats)) return; +const paths = { + main: path.resolve(__dirname, '..'), + core: path.resolve(__dirname, '..', 'core'), + vendor: path.resolve(__dirname, '..', 'vendor'), + libDirBase: path.resolve(__dirname, '..', 'lib'), +}; - if (stats.isSymbolicLink()) return; - if (stats.isFile()) cb(filepath); - if (stats.isDirectory()) walkDir(filepath, cb, filter); - }); +// util.promisify requires Node.js 8.x, so we have our own +function promisify(original) { + return function promiseWrap() { + const args = Array.prototype.slice.call(arguments); + return new Promise((resolve, reject) => { + original.apply(this, args.concat((err, value) => { + if (err) return reject(err); + resolve(value); + })); }); - }); -}; + }; +} -var transform_html = function (new_script) { - // write out the modified vnc.html file that works with the bundle - var src_html_path = path.resolve(__dirname, '..', 'vnc.html'); - var out_html_path = path.resolve(out_dir_base, 'vnc.html'); - fs.readFile(src_html_path, (err, contents_raw) => { - if (err) { throw err; } +const writeFile = promisify(fs.writeFile); - var contents = contents_raw.toString(); +const readdir = promisify(fs.readdir); +const lstat = promisify(fs.lstat); - var start_marker = '\n'; - var end_marker = ''; - var start_ind = contents.indexOf(start_marker) + start_marker.length; - var end_ind = contents.indexOf(end_marker, start_ind); +const ensureDir = promisify(fse.ensureDir); - contents = contents.slice(0, start_ind) + `${new_script}\n` + contents.slice(end_ind); +const babelTransformFile = promisify(babel.transformFile); - console.log(`Writing ${out_html_path}`); - fs.writeFile(out_html_path, contents, function (err) { - if (err) { throw err; } +// walkDir *recursively* walks directories trees, +// calling the callback for all normal files found. +function walkDir(basePath, cb, filter) { + return readdir(basePath) + .then((files) => { + const paths = files.map(filename => path.join(basePath, filename)); + return Promise.all(paths.map(filepath => lstat(filepath) + .then((stats) => { + if (filter !== undefined && !filter(filepath, stats)) return; + + if (stats.isSymbolicLink()) return; + if (stats.isFile()) return cb(filepath); + if (stats.isDirectory()) return walkDir(filepath, cb, filter); + }))); }); - }); } -var make_lib_files = function (import_format, source_maps, with_app_dir) { - if (!import_format) { - throw new Error("you must specify an import format to generate compiled noVNC libraries"); - } else if (!SUPPORTED_FORMATS.has(import_format)) { - throw new Error(`unsupported output format "${import_format}" for import/export -- only ${Array.from(SUPPORTED_FORMATS)} are supported`); - } - - // NB: we need to make a copy of babel_opts, since babel sets some defaults on it - const babel_opts = () => ({ - plugins: [`transform-es2015-modules-${import_format}`], +function makeLibFiles(sourceMaps) { + // NB: we need to make a copy of babelOpts, since babel sets some defaults on it + const babelOpts = () => ({ + plugins: [], + presets: [ + [ '@babel/preset-env', + { modules: 'commonjs' } ] + ], ast: false, - sourceMaps: source_maps, + sourceMaps: sourceMaps, }); - const babel = require('babel-core'); - - var in_path; - if (with_app_dir) { - var out_path_base = out_dir_base; - in_path = main_path; - } else { - var out_path_base = lib_dir_base; - } - - fse.ensureDirSync(out_path_base); - - const helpers = require('./use_require_helpers'); - const helper = helpers[import_format]; - - var handleDir = (js_only, in_path_base, filename) => { - if (no_copy_files.has(filename)) return; - - const out_path = path.join(out_path_base, path.relative(in_path_base, filename)); - if(path.extname(filename) !== '.js') { - if (!js_only) { - console.log(`Writing ${out_path}`); - fse.copy(filename, out_path, (err) => { if (err) throw err; }); - } - return; // skip non-javascript files - } - - fse.ensureDir(path.dirname(out_path), () => { - if (no_transform_files.has(filename)) { - console.log(`Writing ${out_path}`); - fse.copy(filename, out_path, (err) => { if (err) throw err; }); - return; - } - const opts = babel_opts(); - if (helper && helpers.optionsOverride) { - helper.optionsOverride(opts); - } + fse.ensureDirSync(paths.libDirBase); - babel.transformFile(filename, babel_opts(), (err, res) => { - console.log(`Writing ${out_path}`); - if (err) throw err; - var {code, map, ast} = res; - if (source_maps === true) { + const outFiles = []; + + const handleDir = (vendorRewrite, inPathBase, filename) => Promise.resolve() + .then(() => { + const outPath = path.join(paths.libDirBase, path.relative(inPathBase, filename)); + + if (path.extname(filename) !== '.js') { + return; // skip non-javascript files + } + return Promise.resolve() + .then(() => ensureDir(path.dirname(outPath))) + .then(() => { + const opts = babelOpts(); + // Adjust for the fact that we move the core files relative + // to the vendor directory + if (vendorRewrite) { + opts.plugins.push(["import-redirect", + {"root": paths.libDirBase, + "redirect": { "vendor/(.+)": "./vendor/$1"}}]); + } + + return babelTransformFile(filename, opts) + .then((res) => { + console.log(`Writing ${outPath}`); + const {map} = res; + let {code} = res; + if (sourceMaps === true) { // append URL for external source map - code += `\n//# sourceMappingURL=${path.basename(out_path)}.map\n`; - } - fs.writeFile(out_path, code, (err) => { if (err) throw err; }); - if (source_maps === true || source_maps === 'both') { - console.log(` and ${out_path}.map`); - fs.writeFile(`${out_path}.map`, JSON.stringify(map), (err) => { if (err) throw err; }); - } - }); + code += `\n//# sourceMappingURL=${path.basename(outPath)}.map\n`; + } + outFiles.push(`${outPath}`); + return writeFile(outPath, code) + .then(() => { + if (sourceMaps === true || sourceMaps === 'both') { + console.log(` and ${outPath}.map`); + outFiles.push(`${outPath}.map`); + return writeFile(`${outPath}.map`, JSON.stringify(map)); + } + }); + }); + }); }); - }; - walkDir(core_path, handleDir.bind(null, true, in_path || core_path), (filename, stats) => !no_copy_files.has(filename)); - walkDir(vendor_path, handleDir.bind(null, true, in_path || main_path), (filename, stats) => !no_copy_files.has(filename)); - - if (with_app_dir) { - walkDir(app_path, handleDir.bind(null, false, in_path || app_path), (filename, stats) => !no_copy_files.has(filename)); - - const out_app_path = path.join(out_path_base, 'app.js'); - if (helper && helper.appWriter) { - console.log(`Writing ${out_app_path}`); - let out_script = helper.appWriter(out_path_base, out_app_path); - transform_html(out_script); - } else { - console.error(`Unable to generate app for the ${import_format} format!`); - } - } -}; + Promise.resolve() + .then(() => { + const handler = handleDir.bind(null, false, paths.main); + return walkDir(paths.vendor, handler); + }) + .then(() => { + const handler = handleDir.bind(null, true, paths.core); + return walkDir(paths.core, handler); + }) + .catch((err) => { + console.error(`Failure converting modules: ${err}`); + process.exit(1); + }); +} + +if (program.clean) { + console.log(`Removing ${paths.libDirBase}`); + fse.removeSync(paths.libDirBase); +} -make_lib_files(program.as, program.withSourceMaps, program.withApp); +makeLibFiles(program.withSourceMaps);