/** * Both used by zrender and echarts. */ const assert = require('assert'); const rollup = require('rollup'); const path = require('path'); const fs = require('fs'); const fsExtra = require('fs-extra'); const babel = require('@babel/core'); const esm2cjsPlugin = require('./babel-plugin-transform-modules-commonjs-ec'); const removeDEVPlugin = require('./babel-plugin-transform-remove-dev'); /** * @param {Array.} configs A list of rollup configs: * See: * For example: * [ * { * ...inputOptions, * output: [outputOptions], * watch: {chokidar, include, exclude} * }, * ... * ] * @return {Promise} */ exports.build = function (configs) { return new Promise(function (promiseResolve, promiseReject) { let index = 0; buildSingle(); function buildSingle() { let singleConfig = configs[index++]; if (!singleConfig) { promiseResolve(); return; } console.log( color('fgCyan', 'dim')('\nBundles '), color('fgCyan')(singleConfig.input), color('fgCyan', 'dim')('=>'), color('fgCyan')(singleConfig.output.file), color('fgCyan', 'dim')(' ...') ); rollup .rollup(singleConfig) .then(function (bundle) { return bundle.write(singleConfig.output); }) .then(function () { console.log( color('fgGreen', 'dim')('Created '), color('fgGreen')(singleConfig.output.file), color('fgGreen', 'dim')(' successfully.') ); buildSingle(); }) .catch(function (err) { console.log(color('fgRed')(err)); promiseReject(); }); } }); }; /** * @param {Object} singleConfig A single rollup config: * See: * For example: * { * ...inputOptions, * output: [outputOptions], * watch: {chokidar, include, exclude} * } */ exports.watch = function (singleConfig) { let watcher = rollup.watch(singleConfig); watcher.on('event', function (event) { // event.code can be one of: // START — the watcher is (re)starting // BUNDLE_START — building an individual bundle // BUNDLE_END — finished building a bundle // END — finished building all bundles // ERROR — encountered an error while bundling // FATAL — encountered an unrecoverable error if (event.code !== 'START' && event.code !== 'END') { console.log( color('fgBlue')('[' + getTimeString() + ']'), color('dim')('build'), event.code.replace(/_/g, ' ').toLowerCase() ); } if (event.code === 'ERROR' || event.code === 'FATAL') { printCodeError(event.error); } if (event.code === 'BUNDLE_END') { printWatchResult(event); } }); }; /** * @param {string} srcDir Absolute directory path. * @param {Function} [cb] Params: { * fileName: like 'some.js', without dir path. * relativePath: relative to srcDir. * absolutePath * } */ exports.travelSrcDir = function (srcDir, cb) { assert(fs.statSync(srcDir).isDirectory()); const regDir = /^[^.].*$/; const regSrc = /^[^.].*[.]js$/; doTravelSrcDir('.'); function doTravelSrcDir(relativePath) { const absolutePath = path.resolve(srcDir, relativePath); fs.readdirSync(absolutePath).forEach(fileName => { const childAbsolutePath = path.resolve(absolutePath, fileName); const stat = fs.statSync(childAbsolutePath); if (stat.isDirectory()) { if (regDir.test(fileName)) { doTravelSrcDir(path.join(relativePath, fileName)); } } else if (stat.isFile()) { if (regSrc.test(fileName)) { cb({fileName, relativePath, absolutePath: childAbsolutePath}); } } }); } }; /** * @param {string} [opt] * @param {string} [opt.inputPath] Absolute input path. * @param {string} [opt.outputPath] Absolute output path. * @param {string} [opt.preamble] * @param {Function} [opt.transform] * @param {Function} [opt.reserveDEV] */ exports.prePulishSrc = function ({inputPath, outputPath, preamble, transform, reserveDEV}) { assert(inputPath && outputPath); console.log( color('fgGreen', 'dim')('[transform] '), color('fgGreen')(inputPath), color('fgGreen', 'dim')('...') ); let plugins = []; !reserveDEV && plugins.push(removeDEVPlugin); plugins.push(esm2cjsPlugin); let {code} = babel.transformFileSync(inputPath, { plugins: plugins }); !reserveDEV && removeDEVPlugin.recheckDEV(code); if (transform) { code = transform({code, inputPath, outputPath}); } if (preamble) { code = preamble + code; } fsExtra.ensureFileSync(outputPath); fs.writeFileSync(outputPath, code, {encoding:'utf-8'}); }; function printWatchResult(event) { console.log( color('fgGreen', 'dim')('Created'), color('fgGreen')(event.output.join(', ')), color('fgGreen', 'dim')('in'), color('fgGreen')(event.duration), color('fgGreen', 'dim')('ms.') ); } function printCodeError(error) { console.log('\n' + color()(error.code)); if (error.code === 'PARSE_ERROR') { console.log( color()('line'), color('fgCyan')(error.loc.line), color()('column'), color('fgCyan')(error.loc.column), color()('in'), color('fgCyan')(error.loc.file) ); } if (error.frame) { console.log('\n' + color('fgRed')(error.frame)); } console.log(color('dim')('\n' + error.stack)); } function getTimeString() { return (new Date()).toLocaleString(); } const COLOR_RESET = '\x1b[0m'; const COLOR_MAP = { bright: '\x1b[1m', dim: '\x1b[2m', underscore: '\x1b[4m', blink: '\x1b[5m', reverse: '\x1b[7m', hidden: '\x1b[8m', fgBlack: '\x1b[30m', fgRed: '\x1b[31m', fgGreen: '\x1b[32m', fgYellow: '\x1b[33m', fgBlue: '\x1b[34m', fgMagenta: '\x1b[35m', fgCyan: '\x1b[36m', fgWhite: '\x1b[37m', bgBlack: '\x1b[40m', bgRed: '\x1b[41m', bgGreen: '\x1b[42m', bgYellow: '\x1b[43m', bgBlue: '\x1b[44m', bgMagenta: '\x1b[45m', bgCyan: '\x1b[46m', bgWhite: '\x1b[47m' }; /** * Print colored text with `console.log`. * * Usage: * let color = require('colorConsole'); * color('fgCyan')('some text'); // cyan text. * color('fgCyan', 'bright')('some text'); // bright cyan text. * color('fgCyan', 'bgRed')('some text') // cyan text and red background. */ let color = exports.color = function () { let prefix = []; for (let i = 0; i < arguments.length; i++) { let color = COLOR_MAP[arguments[i]]; color && prefix.push(color); } prefix = prefix.join(''); return function (text) { return prefix + text + COLOR_RESET; }; };