123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- #!/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();
|