blob: 9722ff440178b19010e4ead5d4dcfab5e37cb953 [file] [log] [blame]
/**
* ------------------------------------------------------------------------
* 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, extractOptionKeys} = 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.debounce');
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);
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)
}),
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));
const content = JSON.stringify(json, null, 2);
fse.outputFileSync(
descDestPath,
// format ? JSON.stringify(partDescriptions, null, 2) : JSON.stringify(partDescriptions),
content,
'utf-8'
);
// Convnert to JS
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();