256 lines
8.6 KiB
JavaScript
256 lines
8.6 KiB
JavaScript
|
#!/usr/bin/env node
|
||
|
|
||
|
/*
|
||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||
|
* or more contributor license agreements. See the NOTICE file
|
||
|
* distributed with this work for additional information
|
||
|
* regarding copyright ownership. The ASF licenses this file
|
||
|
* to you under the Apache License, Version 2.0 (the
|
||
|
* "License"); you may not use this file except in compliance
|
||
|
* with the License. You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing,
|
||
|
* software distributed under the License is distributed on an
|
||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||
|
* KIND, either express or implied. See the License for the
|
||
|
* specific language governing permissions and limitations
|
||
|
* under the License.
|
||
|
*/
|
||
|
|
||
|
const fsExtra = require('fs-extra');
|
||
|
const fs = require('fs');
|
||
|
const {resolve} = require('path');
|
||
|
const config = require('./config.js');
|
||
|
const commander = require('commander');
|
||
|
const {build, watch, color} = require('zrender/build/helper');
|
||
|
const ecLangPlugin = require('./rollup-plugin-ec-lang');
|
||
|
const prePublish = require('./pre-publish');
|
||
|
const recheckDEV = require('zrender/build/babel-plugin-transform-remove-dev').recheckDEV;
|
||
|
|
||
|
function run() {
|
||
|
|
||
|
/**
|
||
|
* Tips for `commander`:
|
||
|
* (1) If arg xxx not specified, `commander.xxx` is undefined.
|
||
|
* Otherwise:
|
||
|
* If '-x, --xxx', `commander.xxx` can only be true/false, even if '--xxx yyy' input.
|
||
|
* If '-x, --xxx <some>', the 'some' string is required, or otherwise error will be thrown.
|
||
|
* If '-x, --xxx [some]', the 'some' string is optional, that is, `commander.xxx` can be boolean or string.
|
||
|
* (2) `node ./build/build.js --help` will print helper info and exit.
|
||
|
*/
|
||
|
|
||
|
let descIndent = ' ';
|
||
|
let egIndent = ' ';
|
||
|
|
||
|
commander
|
||
|
.usage('[options]')
|
||
|
.description([
|
||
|
'Build echarts and generate result files in directory `echarts/dist`.',
|
||
|
'',
|
||
|
' For example:',
|
||
|
'',
|
||
|
egIndent + 'node build/build.js --release'
|
||
|
+ '\n' + descIndent + '# Build all to `dist` folder.',
|
||
|
egIndent + 'node build/build.js --prepublish'
|
||
|
+ '\n' + descIndent + '# Only prepublish.',
|
||
|
egIndent + 'node build/build.js --removedev'
|
||
|
+ '\n' + descIndent + '# Remove __DEV__ code. If --min, __DEV__ always be removed.',
|
||
|
egIndent + 'node build/build.js --type ""'
|
||
|
+ '\n' + descIndent + '# Only generate `dist/echarts.js`.',
|
||
|
egIndent + 'node build/build.js --type common --min'
|
||
|
+ '\n' + descIndent + '# Only generate `dist/echarts.common.min.js`.',
|
||
|
egIndent + 'node build/build.js --type simple --min --lang en'
|
||
|
+ '\n' + descIndent + '# Only generate `dist/echarts-en.simple.min.js`.',
|
||
|
egIndent + 'node build/build.js --lang "my/lang.js" -i "my/index.js" -o "my/bundle.js"'
|
||
|
+ '\n' + descIndent + '# Take `<cwd>/my/index.js` as input and generate `<cwd>/my/bundle.js`,'
|
||
|
+ '\n' + descIndent + 'where `<cwd>/my/lang.js` is used as language file.',
|
||
|
].join('\n'))
|
||
|
.option(
|
||
|
'-w, --watch', [
|
||
|
'Watch modifications of files and auto-compile to dist file. For example,',
|
||
|
descIndent + '`echarts/dist/echarts.js`.'
|
||
|
].join('\n'))
|
||
|
.option(
|
||
|
'--lang <language file path or shortcut>', [
|
||
|
'Use the specified file instead of `echarts/src/lang.js`. For example:',
|
||
|
descIndent + '`--lang en` will use `echarts/src/langEN.js`.',
|
||
|
descIndent + '`--lang my/langDE.js` will use `<cwd>/my/langDE.js`. -o must be specified in this case.',
|
||
|
descIndent + '`--lang /my/indexSW.js` will use `/my/indexSW.js`. -o must be specified in this case.'
|
||
|
].join('\n'))
|
||
|
.option(
|
||
|
'--release',
|
||
|
'Build all for release'
|
||
|
)
|
||
|
.option(
|
||
|
'--prepublish',
|
||
|
'Build all for release'
|
||
|
)
|
||
|
.option(
|
||
|
'--removedev',
|
||
|
'Remove __DEV__ code. If --min, __DEV__ always be removed.'
|
||
|
)
|
||
|
.option(
|
||
|
'--min',
|
||
|
'Whether to compress the output file, and remove error-log-print code.'
|
||
|
)
|
||
|
.option(
|
||
|
'--type <type name>', [
|
||
|
'Can be "simple" or "common" or "" (default). For example,',
|
||
|
descIndent + '`--type ""` or `--type "common"`.'
|
||
|
].join('\n'))
|
||
|
.option(
|
||
|
'--sourcemap',
|
||
|
'Whether output sourcemap.'
|
||
|
)
|
||
|
.option(
|
||
|
'--format <format>',
|
||
|
'The format of output bundle. Can be "umd", "amd", "iife", "cjs", "es".'
|
||
|
)
|
||
|
.option(
|
||
|
'-i, --input <input file path>',
|
||
|
'If input file path is specified, output file path must be specified too.'
|
||
|
)
|
||
|
.option(
|
||
|
'-o, --output <output file path>',
|
||
|
'If output file path is specified, input file path must be specified too.'
|
||
|
)
|
||
|
.parse(process.argv);
|
||
|
|
||
|
let isWatch = !!commander.watch;
|
||
|
let isRelease = !!commander.release;
|
||
|
let isPrePublish = !!commander.prepublish;
|
||
|
|
||
|
let opt = {
|
||
|
lang: commander.lang,
|
||
|
min: commander.min,
|
||
|
type: commander.type || '',
|
||
|
input: commander.input,
|
||
|
output: commander.output,
|
||
|
format: commander.format,
|
||
|
sourcemap: commander.sourcemap,
|
||
|
removeDev: commander.removedev,
|
||
|
addBundleVersion: isWatch
|
||
|
};
|
||
|
|
||
|
validateIO(opt.input, opt.output);
|
||
|
validateLang(opt.lang, opt.output);
|
||
|
|
||
|
normalizeParams(opt);
|
||
|
|
||
|
// Clear `echarts/dist`
|
||
|
if (isRelease) {
|
||
|
fsExtra.removeSync(getPath('./dist'));
|
||
|
}
|
||
|
|
||
|
if (isWatch) {
|
||
|
watch(config.createECharts(opt));
|
||
|
}
|
||
|
else if (isPrePublish) {
|
||
|
prePublish();
|
||
|
}
|
||
|
else if (isRelease) {
|
||
|
let configs = [];
|
||
|
let configForCheck;
|
||
|
|
||
|
[
|
||
|
{min: false},
|
||
|
{min: true},
|
||
|
{min: false, lang: 'en'},
|
||
|
{min: true, lang: 'en'}
|
||
|
].forEach(function (opt) {
|
||
|
|
||
|
['', 'simple', 'common'].forEach(function (type) {
|
||
|
let singleOpt = Object.assign({type}, opt);
|
||
|
normalizeParams(singleOpt);
|
||
|
let singleConfig = config.createECharts(singleOpt);
|
||
|
configs.push(singleConfig);
|
||
|
|
||
|
if (singleOpt.min && singleOpt.type === '') {
|
||
|
configForCheck = singleConfig;
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
configs.push(
|
||
|
config.createBMap(false),
|
||
|
config.createBMap(true),
|
||
|
config.createDataTool(false),
|
||
|
config.createDataTool(true)
|
||
|
);
|
||
|
|
||
|
build(configs)
|
||
|
.then(function () {
|
||
|
checkCode(configForCheck);
|
||
|
prePublish();
|
||
|
}).catch(handleBuildError);
|
||
|
}
|
||
|
else {
|
||
|
let cfg = config.createECharts(opt);
|
||
|
build([cfg])
|
||
|
.then(function () {
|
||
|
if (opt.removeDev) {
|
||
|
checkCode(cfg);
|
||
|
}
|
||
|
})
|
||
|
.catch(handleBuildError);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function normalizeParams(opt) {
|
||
|
if (opt.sourcemap == null) {
|
||
|
opt.sourcemap = !(opt.min || opt.type);
|
||
|
}
|
||
|
if (opt.removeDev == null) {
|
||
|
opt.removeDev = !!opt.min;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function handleBuildError(err) {
|
||
|
console.log(err);
|
||
|
}
|
||
|
|
||
|
function checkCode(singleConfig) {
|
||
|
// Make sure __DEV__ is eliminated.
|
||
|
let code = fs.readFileSync(singleConfig.output.file, {encoding: 'utf-8'});
|
||
|
if (!code) {
|
||
|
throw new Error(`${singleConfig.output.file} is empty`);
|
||
|
}
|
||
|
recheckDEV(code);
|
||
|
console.log(color('fgGreen', 'dim')('Check code: correct.'));
|
||
|
}
|
||
|
|
||
|
function validateIO(input, output) {
|
||
|
if ((input != null && output == null)
|
||
|
|| (input == null && output != null)
|
||
|
) {
|
||
|
throw new Error('`input` and `output` must be both set.');
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function validateLang(lang, output) {
|
||
|
if (!lang) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
let langInfo = ecLangPlugin.getLangFileInfo(lang);
|
||
|
|
||
|
if (langInfo.isOuter && !output) {
|
||
|
throw new Error('`-o` or `--output` must be specified if using a file path in `--lang`.');
|
||
|
}
|
||
|
if (!langInfo.absolutePath || !fs.statSync(langInfo.absolutePath).isFile()) {
|
||
|
throw new Error(`File ${langInfo.absolutePath} does not exist yet. Contribution is welcome!`);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param {string} relativePath Based on echarts directory.
|
||
|
* @return {string} Absolute path.
|
||
|
*/
|
||
|
function getPath(relativePath) {
|
||
|
return resolve(__dirname, '../', relativePath);
|
||
|
}
|
||
|
|
||
|
run();
|