diff --git a/.gitignore b/.gitignore
index e3f8c759..1213b7f7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -178,6 +178,8 @@ slides/webgl
/public/css
/public/zh/documents
/public/en/documents
+/public/zh/coding-standard-content.html
+/public/en/coding-standard-content.html
/public/*.html
diff --git a/README.md b/README.md
index 0aa1c614..165cdca7 100644
--- a/README.md
+++ b/README.md
@@ -30,7 +30,17 @@ It will:
### Local Config
-To customize the links of `echarts-examples` and other configurations, you can create a local config file `echarts-doc/config/env.dev-local.js`, which is not tracked by git. The content can be copied from `echarts-doc/config/env.dev.js`, and then modify it as needed. `npm run dev` will use this local config file, if it exists, to replace `echarts-doc/config/env.dev.js`.
+To customize the links of `echarts-examples` and other configurations, you can create a local config file `echarts-doc/config/env.dev-local.js`, which is not tracked by git, and its top-level properties will be used to override the corresponding properties of `echarts-doc/config/env.dev.js` when `npm run dev`.
+
+For example, create a `echarts-doc/config/env.dev-local.js`:
+```js
+module.exports = {
+ // These props will override the same props in `echarts-doc/config/env.dev-local.js`
+ galleryViewPath: 'http://127.0.0.1:3002/en/view.html?local=1&c=',
+ galleryEditorPath: 'http://127.0.0.1:3002/en/editor.html?local=1&c=',
+ EMBEDDED_ECHARTS_SCRIPT_URL: 'http://localhost:8001/echarts/echarts/dist/echarts.js',
+};
+```
## Tips About Writing Doc
diff --git a/build.js b/build.js
index 22e6e729..6430894c 100644
--- a/build.js
+++ b/build.js
@@ -1,344 +1,5 @@
/**
- * ------------------------------------------------------------------------
- * Usage:
- *
- * ```shell
- * node build.js --env asf # build all for asf
- * node build.js --env echartsjs # build all for echartsjs.
- * node build.js --env localsite # build all for localsite.
- * node build.js --env dev # the same as "debug", dev the content of docs.
- * # Check `./config` to see the available env
- * ```
- * ------------------------------------------------------------------------
+ * @file For compatibiliy in case that some CI call this file. May not necessary.
*/
-const md2json = require('./tool/md2json');
-const {extractDesc} = require('./tool/schemaHelper');
-const fs = require('fs');
-const fse = require('fs-extra');
-const marked = require('marked');
-const copydir = require('copy-dir');
-const chalk = require('chalk');
-// const MarkDownTOCRenderer = require('./tool/MarkDownTOCRenderer');
-const argv = require('yargs').argv;
-const path = require('path');
-const assert = require('assert');
-const chokidar = require('chokidar');
-const {debounce} = require('lodash');
-const {getDocJSONPVarNname} = require('./src/shared');
-
-const projectDir = __dirname;
-
-function initEnv() {
- let envType = argv.env;
- let isDev = argv.dev != null || argv.debug != null || argv.env === 'dev';
-
- if (isDev) {
- console.warn('=============================');
- console.warn('!!! THIS IS IN DEV MODE !!!');
- console.warn('=============================');
- envType = 'dev';
- }
-
- if (!envType) {
- throw new Error('--env MUST be specified');
- }
-
- let config = require('./config/env.' + envType);
-
- const localOverridePath = './config/env.' + envType + '-local.js';
- if (fs.existsSync(path.join(__dirname, localOverridePath))) {
- config = require(localOverridePath);
- }
-
- assert(path.isAbsolute(config.releaseDestDir) && path.isAbsolute(config.ecWWWGeneratedDir));
-
- config.envType = envType;
-
- return config;
-}
-
-const config = initEnv();
-
-const languages = ['zh', 'en'];
-
-config.gl = config.gl || {};
-for (let key in config) {
- if (key !== 'gl' && !config.gl.hasOwnProperty(key)) {
- config.gl[key] = config[key];
- }
-}
-
-async function md2jsonAsync(opt) {
-
- var newOpt = Object.assign({
- path: path.join(opt.language, opt.entry, '**/*.md'),
- tplEnv: Object.assign({}, config, {
- galleryViewPath: config.galleryViewPath.replace('${lang}', opt.language),
- galleryEditorPath: config.galleryEditorPath.replace('${lang}', opt.language),
- handbookPath: config.handbookPath.replace('${lang}', opt.language)
- }),
- imageRoot: config.imagePath
- }, opt);
-
- function run(cb) {
- md2json(newOpt).then(schema => {
- writeSingleSchema(schema, opt.language, opt.entry, false);
- writeSingleSchemaPartioned(schema, opt.language, opt.entry, false);
- console.log(chalk.green('generated: ' + opt.language + '/' + opt.entry));
- cb && cb();
- }).catch(e => {
- console.log(e);
- });
- }
-
- var runDebounced = debounce(run, 500, {
- leading: false,
- trailing: true
- });
- return await new Promise((resolve, reject) => {
- run(resolve);
-
- if (argv.watch) {
- chokidar.watch(path.resolve(__dirname, opt.language, opt.entry), {
- ignoreInitial: true
- }).on('all', (event, path) => {
- console.log(path, event);
- runDebounced();
- });
- }
- });
-}
-
-function copyAsset() {
-
- const assetSrcDir = path.resolve(projectDir, 'asset');
-
- function doCopy() {
- for (let lang of languages) {
- const assetDestDir = path.resolve(config.releaseDestDir, `${lang}/documents/asset`);
- copydir.sync(assetSrcDir, assetDestDir);
- }
- }
- var doCopyDebounced = debounce(doCopy, 500, {
- leading: false,
- trailing: true
- });
-
- doCopy();
-
- if (argv.watch) {
- chokidar.watch(assetSrcDir, {
- ignoreInitial: true
- }).on('all', (event, path) => {
- console.log(path, event);
- doCopyDebounced();
- });
- }
- console.log('Copy asset done.');
-}
-
-async function run() {
-
- for (let language of languages) {
- await md2jsonAsync({
- sectionsAnyOf: ['visualMap', 'dataZoom', 'series', 'graphic.elements', 'dataset.transform'],
- entry: 'option',
- language
- });
-
- await md2jsonAsync({
- entry: 'tutorial',
- maxDepth: 1,
- language
- });
-
- await md2jsonAsync({
- entry: 'api',
- language
- });
-
- await md2jsonAsync({
- sectionsAnyOf: ['series'],
- entry: 'option-gl',
- // Overwrite
- tplEnv: config.gl,
- imageRoot: config.gl.imagePath,
- language
- });
- }
-
- console.log('Build doc done.');
-
- copyAsset();
-
- if (!argv.watch) { // Not in watch dev mode
- try {
- // TODO Do we need to debug changelog in the doc folder?
- buildChangelog();
- buildCodeStandard();
-
- copySite();
- }
- catch (e) {
- console.log('Error happens when copying to dest folders.');
- console.log(e);
- }
- }
-
- console.log('All done.');
-}
-
-function buildChangelog() {
- for (let lang of languages) {
- const srcPath = path.resolve(projectDir, `${lang}/changelog.md`);
- const destPath = path.resolve(config.ecWWWGeneratedDir, `${lang}/documents/changelog-content.html`);
- fse.outputFileSync(
- destPath,
- marked(fs.readFileSync(srcPath, 'utf-8')),
- 'utf-8'
- );
- console.log(chalk.green('generated: ' + destPath));
- }
- console.log('Build changelog done.');
-}
-
-function buildCodeStandard() {
- // support for Chinese character
- const customRenderer = new marked.Renderer();
- customRenderer.heading = function(text, level, raw) {
- const id = raw.toLowerCase().replace(/[^\w\u4e00-\u9fa5]+/g, '-');
- return `${text}\n`;
- };
-
- for (let lang of languages) {
- const codeStandardDestPath = path.resolve(config.ecWWWGeneratedDir, `${lang}/coding-standard-content.html`);
- fse.ensureDirSync(path.dirname(codeStandardDestPath));
- fse.outputFileSync(
- codeStandardDestPath,
- marked(fs.readFileSync(`${lang}/coding-standard.md`, 'utf-8'), { renderer: customRenderer }),
- 'utf-8'
- );
- console.log(chalk.green('generated: ' + codeStandardDestPath));
- }
-
- console.log('Build code standard done.');
-}
-
-function copySite() {
- const jsSrcPath = path.resolve(projectDir, 'public/js/doc-bundle.js');
- const cssSrcDir = path.resolve(projectDir, 'public/css');
-
- // Copy js and css of doc site.
- for (let lang of languages) {
- const jsDestPath = path.resolve(config.releaseDestDir, `${lang}/js/doc-bundle.js`);
- fse.copySync(jsSrcPath, jsDestPath);
- console.log(chalk.green(`js copied to: ${jsDestPath}`));
-
- const cssDestDir = path.resolve(config.releaseDestDir, `${lang}/css`);
- fse.copySync(cssSrcDir, cssDestDir);
- console.log(chalk.green(`css copied to: ${cssDestDir}`));
- }
-
- console.log('Copy site done.');
-}
-
-function writeSingleSchema(schema, language, docName, format) {
- const destPath = path.resolve(config.releaseDestDir, `${language}/documents/${docName}.json`);
- fse.ensureDirSync(path.dirname(destPath));
- fse.outputFileSync(
- destPath,
- format ? JSON.stringify(schema, null, 2) : JSON.stringify(schema),
- 'utf-8'
- );
- // console.log(chalk.green('generated: ' + destPath));
-}
-
-function writeSingleSchemaPartioned(schema, language, docName, format) {
- const {outline, descriptions} = extractDesc(schema, docName);
-
- function convertToJS(basename, filePath) {
- const content = fs.readFileSync(filePath, 'utf-8');
- const varName = getDocJSONPVarNname(basename);
- const code = `window.${varName} = ${content}`;
- fs.writeFileSync(filePath.replace(/\.json$/, '.js'), code, 'utf-8');
- }
-
- const outlineBasename = `${docName}-outline.json`;
- const outlineDestPath = path.resolve(config.releaseDestDir, `${language}/documents/${docName}-parts/${outlineBasename}`);
- fse.ensureDirSync(path.dirname(outlineDestPath));
- fse.outputFileSync(
- outlineDestPath,
- format ? JSON.stringify(outline, null, 2) : JSON.stringify(outline),
- 'utf-8'
- );
- convertToJS(outlineBasename, outlineDestPath);
-
- function copyUIControlConfigs(source, target) {
- for (let key in source) {
- if (target[key]) {
- if (source[key].uiControl && !target[key].uiControl) {
- target[key].uiControl = source[key].uiControl;
- }
- if (source[key].exampleBaseOptions && !target[key].exampleBaseOptions) {
- target[key].exampleBaseOptions = source[key].exampleBaseOptions;
- }
- }
- else {
- // console.error(`Unmatched option path ${key}`);
- }
- }
- }
-
- function readOptionDesc(language, partKey) {
- const descDestPath = path.resolve(config.releaseDestDir, `${language}/documents/${docName}-parts/${partKey}.json`);
- try {
- const text = fs.readFileSync(descDestPath, 'utf-8');
- return JSON.parse(text);
- }
- catch(e) {
- return;
- }
- }
-
- function writeOptionDesc(language, partKey, json) {
- const descBasename = `${partKey}.json`;
- const descDestPath = path.resolve(config.releaseDestDir, `${language}/documents/${docName}-parts/${descBasename}`);
- fse.ensureDirSync(path.dirname(descDestPath));
- fse.outputFileSync(
- descDestPath,
- format ? JSON.stringify(json, null, 2) : JSON.stringify(json),
- 'utf-8'
- );
- convertToJS(descBasename, descDestPath);
- }
-
- for (let partKey in descriptions) {
- let partDescriptions = descriptions[partKey];
-
- // Copy ui control config from zh to english.
- if (language === 'zh') {
- languages.forEach(function (otherLang) {
- if (otherLang === 'zh') {
- return;
- }
- const json = readOptionDesc(otherLang, partKey);
- if (json) {
- copyUIControlConfigs(partDescriptions, json);
- writeOptionDesc(otherLang, partKey, json);
- }
- });
- }
- else {
- const json = readOptionDesc('zh', partKey);
- if (json) {
- copyUIControlConfigs(json, partDescriptions);
- }
- }
-
- writeOptionDesc(language, partKey, partDescriptions);
- // console.log(chalk.green('generated: ' + descDestPath));
- }
-};
-
-run();
+require('./build/build-doc.js');
diff --git a/build/build-doc.js b/build/build-doc.js
new file mode 100644
index 00000000..ac0d8e70
--- /dev/null
+++ b/build/build-doc.js
@@ -0,0 +1,337 @@
+/**
+ * ------------------------------------------------------------------------
+ * Usage:
+ *
+ * ```shell
+ * node build.js --env asf # build all for asf
+ * node build.js --env echartsjs # build all for echartsjs.
+ * node build.js --env localsite # build all for localsite.
+ * node build.js --env dev # the same as "debug", dev the content of docs.
+ * # Check `./config` to see the available env
+ * ```
+ * ------------------------------------------------------------------------
+ */
+
+const md2json = require('../tool/md2json');
+const {extractDesc} = require('../tool/schemaHelper');
+const fs = require('fs');
+const fse = require('fs-extra');
+const marked = require('marked');
+const copydir = require('copy-dir');
+const chalk = require('chalk');
+// const MarkDownTOCRenderer = require('./tool/MarkDownTOCRenderer');
+const argv = require('yargs').argv;
+const path = require('path');
+const chokidar = require('chokidar');
+const {debounce} = require('lodash');
+const {getDocJSONPVarNname} = require('../src/shared');
+const {readConfigEnvFile} = require('./helper');
+
+const projectDir = path.resolve(__dirname, '..');
+
+function initEnv() {
+ let envType = argv.env;
+ let isDev = argv.dev != null || argv.debug != null || argv.env === 'dev';
+
+ if (isDev) {
+ console.warn('=============================');
+ console.warn('!!! THIS IS IN DEV MODE !!!');
+ console.warn('=============================');
+ envType = 'dev';
+ }
+
+ if (!envType) {
+ throw new Error('--env MUST be specified');
+ }
+
+ const config = readConfigEnvFile(envType);
+
+ config.envType = envType;
+
+ return config;
+}
+
+const config = initEnv();
+
+const languages = ['zh', 'en'];
+
+config.gl = config.gl || {};
+for (let key in config) {
+ if (key !== 'gl' && !config.gl.hasOwnProperty(key)) {
+ config.gl[key] = config[key];
+ }
+}
+
+async function md2jsonAsync(opt) {
+
+ var newOpt = Object.assign({
+ path: path.join(opt.language, opt.entry, '**/*.md'),
+ tplEnv: Object.assign({}, config, {
+ galleryViewPath: config.galleryViewPath.replace('${lang}', opt.language),
+ galleryEditorPath: config.galleryEditorPath.replace('${lang}', opt.language),
+ handbookPath: config.handbookPath.replace('${lang}', opt.language)
+ }),
+ imageRoot: config.imagePath
+ }, opt);
+
+ function run(cb) {
+ md2json(newOpt).then(schema => {
+ writeSingleSchema(schema, opt.language, opt.entry, false);
+ writeSingleSchemaPartioned(schema, opt.language, opt.entry, false);
+ console.log(chalk.green('generated: ' + opt.language + '/' + opt.entry));
+ cb && cb();
+ }).catch(e => {
+ console.log(e);
+ });
+ }
+
+ var runDebounced = debounce(run, 500, {
+ leading: false,
+ trailing: true
+ });
+ return await new Promise((resolve, reject) => {
+ run(resolve);
+
+ if (argv.watch) {
+ chokidar.watch(path.resolve(projectDir, opt.language, opt.entry), {
+ ignoreInitial: true
+ }).on('all', (event, path) => {
+ console.log(path, event);
+ runDebounced();
+ });
+ }
+ });
+}
+
+function copyAsset() {
+
+ const assetSrcDir = path.resolve(projectDir, 'asset');
+
+ function doCopy() {
+ for (let lang of languages) {
+ const assetDestDir = path.resolve(config.releaseDestDir, `${lang}/documents/asset`);
+ copydir.sync(assetSrcDir, assetDestDir);
+ }
+ }
+ var doCopyDebounced = debounce(doCopy, 500, {
+ leading: false,
+ trailing: true
+ });
+
+ doCopy();
+
+ if (argv.watch) {
+ chokidar.watch(assetSrcDir, {
+ ignoreInitial: true
+ }).on('all', (event, path) => {
+ console.log(path, event);
+ doCopyDebounced();
+ });
+ }
+ console.log('Copy asset done.');
+}
+
+async function run() {
+
+ for (let language of languages) {
+ await md2jsonAsync({
+ sectionsAnyOf: ['visualMap', 'dataZoom', 'series', 'graphic.elements', 'dataset.transform'],
+ entry: 'option',
+ language
+ });
+
+ await md2jsonAsync({
+ entry: 'tutorial',
+ maxDepth: 1,
+ language
+ });
+
+ await md2jsonAsync({
+ entry: 'api',
+ language
+ });
+
+ await md2jsonAsync({
+ sectionsAnyOf: ['series'],
+ entry: 'option-gl',
+ // Overwrite
+ tplEnv: config.gl,
+ imageRoot: config.gl.imagePath,
+ language
+ });
+ }
+
+ console.log('Build doc done.');
+
+ copyAsset();
+
+ if (!argv.watch) { // Not in watch dev mode
+ try {
+ // TODO Do we need to debug changelog in the doc folder?
+ buildChangelog();
+ buildCodeStandard();
+
+ copySite();
+ }
+ catch (e) {
+ console.log('Error happens when copying to dest folders.');
+ console.log(e);
+ }
+ }
+
+ console.log('All done.');
+}
+
+function buildChangelog() {
+ for (let lang of languages) {
+ const srcPath = path.resolve(projectDir, `${lang}/changelog.md`);
+ const destPath = path.resolve(config.ecWWWGeneratedDir, `${lang}/documents/changelog-content.html`);
+ fse.outputFileSync(
+ destPath,
+ marked(fs.readFileSync(srcPath, 'utf-8')),
+ 'utf-8'
+ );
+ console.log(chalk.green('generated: ' + destPath));
+ }
+ console.log('Build changelog done.');
+}
+
+function buildCodeStandard() {
+ // support for Chinese character
+ const customRenderer = new marked.Renderer();
+ customRenderer.heading = function(text, level, raw) {
+ const id = raw.toLowerCase().replace(/[^\w\u4e00-\u9fa5]+/g, '-');
+ return `${text}\n`;
+ };
+
+ for (let lang of languages) {
+ const codeStandardDestPath = path.resolve(config.ecWWWGeneratedDir, `${lang}/coding-standard-content.html`);
+ fse.ensureDirSync(path.dirname(codeStandardDestPath));
+ fse.outputFileSync(
+ codeStandardDestPath,
+ marked(fs.readFileSync(path.resolve(projectDir, `${lang}/coding-standard.md`), 'utf-8'), { renderer: customRenderer }),
+ 'utf-8'
+ );
+ console.log(chalk.green('generated: ' + codeStandardDestPath));
+ }
+
+ console.log('Build code standard done.');
+}
+
+function copySite() {
+ const jsSrcPath = path.resolve(projectDir, 'public/js/doc-bundle.js');
+ const cssSrcDir = path.resolve(projectDir, 'public/css');
+
+ // Copy js and css of doc site.
+ for (let lang of languages) {
+ const jsDestPath = path.resolve(config.releaseDestDir, `${lang}/js/doc-bundle.js`);
+ fse.copySync(jsSrcPath, jsDestPath);
+ console.log(chalk.green(`js copied to: ${jsDestPath}`));
+
+ const cssDestDir = path.resolve(config.releaseDestDir, `${lang}/css`);
+ fse.copySync(cssSrcDir, cssDestDir);
+ console.log(chalk.green(`css copied to: ${cssDestDir}`));
+ }
+
+ console.log('Copy site done.');
+}
+
+function writeSingleSchema(schema, language, docName, format) {
+ const destPath = path.resolve(config.releaseDestDir, `${language}/documents/${docName}.json`);
+ fse.ensureDirSync(path.dirname(destPath));
+ fse.outputFileSync(
+ destPath,
+ format ? JSON.stringify(schema, null, 2) : JSON.stringify(schema),
+ 'utf-8'
+ );
+ // console.log(chalk.green('generated: ' + destPath));
+}
+
+function writeSingleSchemaPartioned(schema, language, docName, format) {
+ const {outline, descriptions} = extractDesc(schema, docName);
+
+ function convertToJS(basename, filePath) {
+ const content = fs.readFileSync(filePath, 'utf-8');
+ const varName = getDocJSONPVarNname(basename);
+ const code = `window.${varName} = ${content}`;
+ fs.writeFileSync(filePath.replace(/\.json$/, '.js'), code, 'utf-8');
+ }
+
+ const outlineBasename = `${docName}-outline.json`;
+ const outlineDestPath = path.resolve(config.releaseDestDir, `${language}/documents/${docName}-parts/${outlineBasename}`);
+ fse.ensureDirSync(path.dirname(outlineDestPath));
+ fse.outputFileSync(
+ outlineDestPath,
+ format ? JSON.stringify(outline, null, 2) : JSON.stringify(outline),
+ 'utf-8'
+ );
+ convertToJS(outlineBasename, outlineDestPath);
+
+ function copyUIControlConfigs(source, target) {
+ for (let key in source) {
+ if (target[key]) {
+ if (source[key].uiControl && !target[key].uiControl) {
+ target[key].uiControl = source[key].uiControl;
+ }
+ if (source[key].exampleBaseOptions && !target[key].exampleBaseOptions) {
+ target[key].exampleBaseOptions = source[key].exampleBaseOptions;
+ }
+ }
+ else {
+ // console.error(`Unmatched option path ${key}`);
+ }
+ }
+ }
+
+ function readOptionDesc(language, partKey) {
+ const descDestPath = path.resolve(config.releaseDestDir, `${language}/documents/${docName}-parts/${partKey}.json`);
+ try {
+ const text = fs.readFileSync(descDestPath, 'utf-8');
+ return JSON.parse(text);
+ }
+ catch(e) {
+ return;
+ }
+ }
+
+ function writeOptionDesc(language, partKey, json) {
+ const descBasename = `${partKey}.json`;
+ const descDestPath = path.resolve(config.releaseDestDir, `${language}/documents/${docName}-parts/${descBasename}`);
+ fse.ensureDirSync(path.dirname(descDestPath));
+ fse.outputFileSync(
+ descDestPath,
+ format ? JSON.stringify(json, null, 2) : JSON.stringify(json),
+ 'utf-8'
+ );
+ convertToJS(descBasename, descDestPath);
+ }
+
+ for (let partKey in descriptions) {
+ let partDescriptions = descriptions[partKey];
+
+ // Copy ui control config from zh to english.
+ if (language === 'zh') {
+ languages.forEach(function (otherLang) {
+ if (otherLang === 'zh') {
+ return;
+ }
+ const json = readOptionDesc(otherLang, partKey);
+ if (json) {
+ copyUIControlConfigs(partDescriptions, json);
+ writeOptionDesc(otherLang, partKey, json);
+ }
+ });
+ }
+ else {
+ const json = readOptionDesc('zh', partKey);
+ if (json) {
+ copyUIControlConfigs(json, partDescriptions);
+ }
+ }
+
+ writeOptionDesc(language, partKey, partDescriptions);
+ // console.log(chalk.green('generated: ' + descDestPath));
+ }
+};
+
+run();
diff --git a/build/helper.js b/build/helper.js
new file mode 100644
index 00000000..6116dd5f
--- /dev/null
+++ b/build/helper.js
@@ -0,0 +1,29 @@
+const fs = require('fs');
+const path = require('path');
+const assert = require('assert');
+
+const ENV_TYPE = ['dev', 'localsite', 'asf'];
+
+/**
+ * @param envType {string} 'dev' | 'localsite' | 'asf'
+ */
+exports.readConfigEnvFile = function (envType) {
+ assert(ENV_TYPE.indexOf(envType) >= 0, 'envType must be one of ' + ENV_TYPE.join(', '));
+
+ const configEnvRelativePath = '../config/env.' + envType + '.js';
+ const configEnvLocalRelativePath = '../config/env.' + envType + '-local.js';
+
+ const config = require(configEnvRelativePath);
+ if (fs.existsSync(path.resolve(__dirname, configEnvLocalRelativePath))) {
+ const configLocal = require(configEnvLocalRelativePath);
+ assert(
+ typeof configLocal === 'object' && !Array.isArray(configLocal),
+ configEnvLocalRelativePath + ' must be an object.'
+ );
+ Object.assign(config, configLocal);
+ }
+
+ assert(path.isAbsolute(config.releaseDestDir) && path.isAbsolute(config.ecWWWGeneratedDir));
+
+ return config;
+};
diff --git a/build/webpack.config.js b/build/webpack.config.js
index 09cbc1ff..e76ee15a 100644
--- a/build/webpack.config.js
+++ b/build/webpack.config.js
@@ -2,57 +2,73 @@ const webpack = require('webpack');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
+const {readConfigEnvFile} = require('./helper');
-/**
- * @type {import('webpack').Configuration}
- */
-module.exports = {
- entry: path.resolve(__dirname, '../src/main.js'),
- output: {
- filename: 'doc-bundle.js',
- path: path.resolve(__dirname, '../public/js'),
- library: 'echartsDoc',
- libraryTarget: 'umd'
- },
- stats: 'minimal',
- module: {
- rules: [{
- test: /\.vue$/,
- use: ['vue-loader']
- }, {
- test: /\.js$/,
- use: ['babel-loader'],
- exclude: /node_modules/
- }, {
- test: /\.css$/,
- use: [MiniCssExtractPlugin.loader, 'css-loader']
- }, {
- test: /\.scss$/,
- use: [MiniCssExtractPlugin.loader, 'css-loader', 'sassjs-loader']
- }, {
- test: /\.(png|jpg|jpeg|gif|eot|ttf|woff|woff2|svg|svgz)(\?.+)?$/,
- use: [{
- loader: 'file-loader',
- options: {
- limit: 10000,
- outputPath: '../css',
- name: '[name].[ext]'
- }
+
+module.exports = (env, argv) => {
+
+ const isDev = argv.mode === 'development';
+
+ let configEnv = {};
+ if (isDev) {
+ configEnv = readConfigEnvFile('dev');
+ }
+
+ return {
+ entry: path.resolve(__dirname, '../src/main.js'),
+ output: {
+ filename: 'doc-bundle.js',
+ path: path.resolve(__dirname, '../public/js'),
+ library: 'echartsDoc',
+ libraryTarget: 'umd'
+ },
+ stats: 'minimal',
+ module: {
+ rules: [{
+ test: /\.vue$/,
+ use: ['vue-loader']
+ }, {
+ test: /\.js$/,
+ use: ['babel-loader'],
+ exclude: /node_modules/
+ }, {
+ test: /\.css$/,
+ use: [MiniCssExtractPlugin.loader, 'css-loader']
+ }, {
+ test: /\.scss$/,
+ use: [MiniCssExtractPlugin.loader, 'css-loader', 'sassjs-loader']
+ }, {
+ test: /\.(png|jpg|jpeg|gif|eot|ttf|woff|woff2|svg|svgz)(\?.+)?$/,
+ use: [{
+ loader: 'file-loader',
+ options: {
+ limit: 10000,
+ outputPath: '../css',
+ name: '[name].[ext]'
+ }
+ }]
}]
- }]
- },
- externals: {
- vue: 'Vue',
- codemirror: 'CodeMirror',
- 'js-beautify': 'beautifier'
- },
- plugins: [
- new webpack.IgnorePlugin({
- resourceRegExp: /^fs$/
- }),
- new VueLoaderPlugin(),
- new MiniCssExtractPlugin({
- filename: '../css/doc-bundle.css'
- })
- ]
+ },
+ externals: {
+ vue: 'Vue',
+ codemirror: 'CodeMirror',
+ 'js-beautify': 'beautifier'
+ },
+ plugins: [
+ new webpack.DefinePlugin({
+ // It can be used in the code directly.
+ INJECTED_CONFIG: JSON.stringify({
+ EMBEDDED_ECHARTS_SCRIPT_URL: configEnv.EMBEDDED_ECHARTS_SCRIPT_URL,
+ })
+ }),
+ new webpack.IgnorePlugin({
+ resourceRegExp: /^fs$/
+ }),
+ new VueLoaderPlugin(),
+ new MiniCssExtractPlugin({
+ filename: '../css/doc-bundle.css'
+ })
+ ]
+ };
};
+
diff --git a/config/env.dev.js b/config/env.dev.js
index 14cba3a5..127270d4 100644
--- a/config/env.dev.js
+++ b/config/env.dev.js
@@ -13,5 +13,7 @@ module.exports = {
},
releaseDestDir: path.resolve(__dirname, '../public'),
- ecWWWGeneratedDir: path.resolve(__dirname, '../../echarts-www/_generated')
+ ecWWWGeneratedDir: path.resolve(__dirname, '../../echarts-www/_generated'),
+
+ EMBEDDED_ECHARTS_SCRIPT_URL: null,
};
\ No newline at end of file
diff --git a/package.json b/package.json
index 9634f9f8..7b21cbcd 100644
--- a/package.json
+++ b/package.json
@@ -7,9 +7,9 @@
"url": "https://github.com/apache/echarts-doc"
},
"scripts": {
- "build": "node build.js --env asf",
- "watch": "node build.js --env dev --watch",
- "localsite": "node build.js --env localsite",
+ "build": "node build/build-doc.js --env asf",
+ "watch": "node build/build-doc.js --env dev --watch",
+ "localsite": "node build/build-doc.js --env localsite",
"build:site": "webpack --config build/webpack.config.js --mode production",
"watch:site": "webpack --config build/webpack.config.js --mode development --devtool inline-source-map --watch",
"server": "node server.js",
diff --git a/src/components/LiveExample.vue b/src/components/LiveExample.vue
index 03a64684..090ce47d 100644
--- a/src/components/LiveExample.vue
+++ b/src/components/LiveExample.vue
@@ -86,7 +86,9 @@ let echartsLoadPromise;
function fetchECharts() {
return echartsLoadPromise || (echartsLoadPromise = new Promise(function (resolve, reject) {
const script = document.createElement('script');
- script.src = (window.ECHARTS_WWW_VENDORS_CDN_ROOT || 'https://fastly.jsdelivr.net/npm/') + 'echarts/dist/echarts.min.js';
+ script.src = INJECTED_CONFIG.EMBEDDED_ECHARTS_SCRIPT_URL
+ ? INJECTED_CONFIG.EMBEDDED_ECHARTS_SCRIPT_URL
+ : (window.ECHARTS_WWW_VENDORS_CDN_ROOT || 'https://fastly.jsdelivr.net/npm/') + 'echarts/dist/echarts.min.js';
script.async = true;
script.onload = function () {
echartsLoadPromise = null;