Skip to content

Commit e4f3e84

Browse files
committed
Support custom lang file in build tool.
1 parent dd75802 commit e4f3e84

File tree

4 files changed

+94
-44
lines changed

4 files changed

+94
-44
lines changed

README.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,8 @@ ECharts-GL is an extension pack of echarts, which providing 3D plots, globe visu
123123

124124
## Build
125125

126-
+ Release: `node <echarts_dir>/build/build.js`.
127-
+ Watch: `node <echarts_dir>/build/build.js -w`.
128-
+ Build with certain language: `node <echarts_dir>/build/build.js --lang xx`, where `xx` is the shortcut of the language, and a corresponding file `langXX.js` is required in `<echarts_dir>`.
129-
+ Other usages: `node <echarts_dir>/build/build.js -h`.
126+
Check this tutorial [Create Custom Build of ECharts](https://ecomfe.github.io/echarts-doc/public/en/tutorial.html#Create%20Custom%20Build%20of%20ECharts)
127+
please.
130128

131129
## License
132130

build/build.js

Lines changed: 55 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const {resolve} = require('path');
66
const config = require('./config.js');
77
const commander = require('commander');
88
const {build, watch, color} = require('./helper');
9+
const ecLangPlugin = require('./rollup-plugin-ec-lang');
910

1011
function run() {
1112

@@ -19,31 +20,40 @@ function run() {
1920
* (2) `node ./build/build.js --help` will print helper info and exit.
2021
*/
2122

23+
let descIndent = ' ';
24+
let egIndent = ' ';
25+
2226
commander
2327
.usage('[options]')
2428
.description([
2529
'Build echarts and generate result files in directory `echarts/dist`.',
2630
'',
2731
' For example:',
2832
'',
29-
' node build/build.js --release # Build all to `dist` folder.',
30-
' node build/build.js --type "" # Only generate `dist/echarts.js`.',
31-
' node build/build.js --type common --min # Only generate `dist/echarts.common.min.js`.',
32-
' node build/build.js --type simple --min --lang en # Only generate `dist/echarts-en.simple.min.js`.',
33-
' node build/build.js --min --lang en -i "/my/index.js" -o "/my/ec.js" '
34-
+ '# Take `/my/index.js` as input and generate a bundle `/my/ec.js`, '
35-
+ 'which is in EN language and has been minified.',
33+
egIndent + 'node build/build.js --release'
34+
+ '\n' + descIndent + '# Build all to `dist` folder.',
35+
egIndent + 'node build/build.js --type ""'
36+
+ '\n' + descIndent + '# Only generate `dist/echarts.js`.',
37+
egIndent + 'node build/build.js --type common --min'
38+
+ '\n' + descIndent + '# Only generate `dist/echarts.common.min.js`.',
39+
egIndent + 'node build/build.js --type simple --min --lang en'
40+
+ '\n' + descIndent + '# Only generate `dist/echarts-en.simple.min.js`.',
41+
egIndent + 'node build/build.js --lang "my/lang.js" -i "my/index.js" -o "my/bundle.js"'
42+
+ '\n' + descIndent + '# Take `<cwd>/my/index.js` as input and generate `<cwd>/my/bundle.js`,'
43+
+ '\n' + descIndent + 'where `<cwd>/my/lang.js` is used as language file.',
3644
].join('\n'))
3745
.option(
38-
'-w, --watch',
39-
'Watch modifications of files and auto-compile to dist file (e.g., `echarts/dist/echarts.js`).'
40-
)
46+
'-w, --watch', [
47+
'Watch modifications of files and auto-compile to dist file. For example,',
48+
descIndent + '`echarts/dist/echarts.js`.'
49+
].join('\n'))
4150
.option(
42-
'--lang <language shortcut>',
43-
'Only generate a dist file with specified language in directory `echarts/dist`. '
44-
+ 'A langXX.js file is required in directory `echarts`. '
45-
+ 'e.g., `--lang en`, where a file `langEN.js` is required.'
46-
)
51+
'--lang <language file path or shortcut>', [
52+
'Use the specified file instead of `echarts/src/lang.js`. For example:',
53+
descIndent + '`--lang en` will use `echarts/src/langEN.js`.',
54+
descIndent + '`--lang my/langDE.js` will use `<cwd>/my/langDE.js`. -o must be specified in this case.',
55+
descIndent + '`--lang /my/indexSW.js` will use `/my/indexSW.js`. -o must be specified in this case.'
56+
].join('\n'))
4757
.option(
4858
'--release',
4959
'Build all for release'
@@ -53,10 +63,10 @@ function run() {
5363
'Whether to compress the output file, and remove error-log-print code.'
5464
)
5565
.option(
56-
'--type <type name>',
57-
'Can be "simple" or "common" or "" (default). '
58-
+ 'e.g., `--type ""` or `--type "common"`.'
59-
)
66+
'--type <type name>', [
67+
'Can be "simple" or "common" or "" (default). For example,',
68+
descIndent + '`--type ""` or `--type "common"`.'
69+
].join('\n'))
6070
.option(
6171
'--sourcemap',
6272
'Whether output sourcemap.'
@@ -88,11 +98,8 @@ function run() {
8898
format: commander.format || 'umd'
8999
};
90100

91-
if ((opt.input != null && opt.output == null)
92-
|| (opt.input == null && opt.output != null)
93-
) {
94-
throw new Error('`input` and `output` must be both set.');
95-
}
101+
validateIO(opt.input, opt.output);
102+
validateLang(opt.lang, opt.output);
96103

97104
// Clear `echarts/dist`
98105
if (isRelease) {
@@ -148,14 +155,37 @@ function checkCode(singleConfig) {
148155
// Make sure __DEV__ is eliminated.
149156
let code = fs.readFileSync(singleConfig.output.file, {encoding: 'utf-8'});
150157
if (!code) {
151-
throw new Error(singleConfig.output.file + ' is empty');
158+
throw new Error(`${singleConfig.output.file} is empty`);
152159
}
153160
if (code.indexOf('__DEV__') >= 0) {
154161
throw new Error('__DEV__ is not removed.');
155162
}
156163
console.log(color('fgGreen', 'dim')('Check code: correct.'));
157164
}
158165

166+
function validateIO(input, output) {
167+
if ((input != null && output == null)
168+
|| (input == null && output != null)
169+
) {
170+
throw new Error('`input` and `output` must be both set.');
171+
}
172+
}
173+
174+
function validateLang(lang, output) {
175+
if (!lang) {
176+
return;
177+
}
178+
179+
let langInfo = ecLangPlugin.getLangFileInfo(lang);
180+
181+
if (langInfo.isOuter && !output) {
182+
throw new Error('`-o` or `--output` must be specified if using a file path in `--lang`.');
183+
}
184+
if (!langInfo.absolutePath || !fs.statSync(langInfo.absolutePath).isFile()) {
185+
throw new Error(`File ${langInfo.absolutePath} does not exist yet. Contribution is welcome!`);
186+
}
187+
}
188+
159189
/**
160190
* @param {string} relativePath Based on echarts directory.
161191
* @return {string} Absolute path.

build/config.js

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ function getPathBasedOnECharts(path) {
1111

1212
/**
1313
* @param {boolean} [min=false]
14-
* @param {string} [lang=null] null/undefined/'' or 'en' or 'fi' or ...
14+
* @param {string} [lang=null] null/undefined/'' or 'en' or 'fi' or a file path
1515
*/
1616
function getPlugins(min, lang) {
1717
let plugins = [
@@ -46,7 +46,7 @@ function getPlugins(min, lang) {
4646
* @param {Object} [opt]
4747
* @param {string} [opt.type=''] '' or 'simple' or 'common'
4848
* @param {boolean} [opt.min=false]
49-
* @param {string} [opt.lang=undefined] null/undefined/'' or 'en' or 'fi' or ...
49+
* @param {string} [opt.lang=undefined] null/undefined/'' or 'en' or 'fi' or a file path.
5050
* @param {string} [opt.input=undefined] If set, `opt.output` is required too, and `opt.type` is ignored.
5151
* @param {string} [opt.output=undefined] If set, `opt.input` is required too, and `opt.type` is ignored.
5252
* @param {boolean} [opt.sourcemap] If set, `opt.input` is required too, and `opt.type` is ignored.
@@ -64,9 +64,6 @@ exports.createECharts = function (opt) {
6464
let format = opt.format || 'umd';
6565

6666
if (input != null || output != null) {
67-
if (input == null || output == null) {
68-
throw new Error('`input` and `output` must be both set.');
69-
}
7067
isCustom = true;
7168
// Based on process.cwd();
7269
input = resolve(input);
@@ -155,4 +152,3 @@ exports.createDataTool = function (min) {
155152
}
156153
};
157154
};
158-

build/rollup-plugin-ec-lang.js

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,49 @@
1212
* };
1313
*/
1414

15-
const {dirname, resolve} = require('path');
15+
const {resolve} = require('path');
16+
const {readFileSync} = require('fs');
1617

1718
/**
1819
* @param {Object} [opt]
19-
* @param {string} [opt.lang=null] null/undefined/'' or 'en' or 'fi' or ...
20+
* @param {string} [opt.lang=null] null/undefined/'' or 'en' or 'fi' or a file path.
2021
*/
21-
module.exports = function (opt) {
22+
function getPlugin(opt) {
2223
let lang = opt && opt.lang || '';
2324

2425
return {
25-
resolveId: function (importee, importor) {
26-
if (/\/lang([.]js)?$/.test(importee)) {
27-
return resolve(
28-
dirname(importor),
29-
importee.replace(/\/lang([.]js)?$/, '/lang' + lang.toUpperCase() + '.js')
30-
);
26+
load: function (absolutePath) {
27+
if (/\/src\/lang\.js$/.test(absolutePath)) {
28+
let langPath = getLangFileInfo(lang).absolutePath;
29+
if (langPath) {
30+
absolutePath = langPath;
31+
}
3132
}
33+
return readFileSync(absolutePath, 'utf-8');
3234
}
3335
};
36+
}
37+
38+
/**
39+
* @param {string} lang null/undefined/'' or 'en' or 'fi' or a file path.
40+
* @return {Object} {isOuter, absolutePath}
41+
*/
42+
let getLangFileInfo = getPlugin.getLangFileInfo = function (lang) {
43+
let absolutePath;
44+
let isOuter = false;
45+
46+
if (lang) {
47+
if (/^[a-zA-Z]{2}$/.test(lang)) {
48+
absolutePath = resolve(__dirname, '../', 'src/lang' + lang.toUpperCase() + '.js')
49+
}
50+
else {
51+
isOuter = true;
52+
// `lang` is an absolute path or a relative path based on process.cwd().
53+
absolutePath = resolve(lang);
54+
}
55+
}
56+
57+
return {isOuter, absolutePath};
3458
};
59+
60+
module.exports = getPlugin;

0 commit comments

Comments
 (0)