You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							255 lines
						
					
					
						
							8.6 KiB
						
					
					
				
			
		
		
	
	
							255 lines
						
					
					
						
							8.6 KiB
						
					
					
				#!/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();
 | 
						|
 |