You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@echarts.apache.org by su...@apache.org on 2025/07/30 13:27:13 UTC
(echarts-doc) branch feat-local-config created (now 32998345)
This is an automated email from the ASF dual-hosted git repository.
sushuang pushed a change to branch feat-local-config
in repository https://gitbox.apache.org/repos/asf/echarts-doc.git
at 32998345 feat: support local config, not tracked by git.
This branch includes the following new commits:
new 32998345 feat: support local config, not tracked by git.
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@echarts.apache.org
For additional commands, e-mail: commits-help@echarts.apache.org
(echarts-doc) 01/01: feat: support local config, not tracked by git.
Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
sushuang pushed a commit to branch feat-local-config
in repository https://gitbox.apache.org/repos/asf/echarts-doc.git
commit 32998345699f8d59551794b700b829a7b71c0a28
Author: 100pah <su...@gmail.com>
AuthorDate: Wed Jul 30 21:26:54 2025 +0800
feat: support local config, not tracked by git.
---
.gitignore | 2 +
README.md | 12 +-
build.js | 343 +----------------------------------------
build.js => build/build-doc.js | 23 +--
build/helper.js | 29 ++++
build/webpack.config.js | 118 ++++++++------
config/env.dev.js | 4 +-
package.json | 6 +-
src/components/LiveExample.vue | 4 +-
9 files changed, 128 insertions(+), 413 deletions(-)
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 `<h${level} id="${id}">${text}</h${level}>\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.js b/build/build-doc.js
similarity index 93%
copy from build.js
copy to build/build-doc.js
index 22e6e729..ac0d8e70 100644
--- a/build.js
+++ b/build/build-doc.js
@@ -12,8 +12,8 @@
* ------------------------------------------------------------------------
*/
-const md2json = require('./tool/md2json');
-const {extractDesc} = require('./tool/schemaHelper');
+const md2json = require('../tool/md2json');
+const {extractDesc} = require('../tool/schemaHelper');
const fs = require('fs');
const fse = require('fs-extra');
const marked = require('marked');
@@ -22,12 +22,12 @@ 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 {getDocJSONPVarNname} = require('../src/shared');
+const {readConfigEnvFile} = require('./helper');
-const projectDir = __dirname;
+const projectDir = path.resolve(__dirname, '..');
function initEnv() {
let envType = argv.env;
@@ -44,14 +44,7 @@ function initEnv() {
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));
+ const config = readConfigEnvFile(envType);
config.envType = envType;
@@ -100,7 +93,7 @@ async function md2jsonAsync(opt) {
run(resolve);
if (argv.watch) {
- chokidar.watch(path.resolve(__dirname, opt.language, opt.entry), {
+ chokidar.watch(path.resolve(projectDir, opt.language, opt.entry), {
ignoreInitial: true
}).on('all', (event, path) => {
console.log(path, event);
@@ -216,7 +209,7 @@ function buildCodeStandard() {
fse.ensureDirSync(path.dirname(codeStandardDestPath));
fse.outputFileSync(
codeStandardDestPath,
- marked(fs.readFileSync(`${lang}/coding-standard.md`, 'utf-8'), { renderer: customRenderer }),
+ marked(fs.readFileSync(path.resolve(projectDir, `${lang}/coding-standard.md`), 'utf-8'), { renderer: customRenderer }),
'utf-8'
);
console.log(chalk.green('generated: ' + codeStandardDestPath));
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;
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@echarts.apache.org
For additional commands, e-mail: commits-help@echarts.apache.org