Files
whistle/docs/script/docify.js
T
2018-04-16 01:43:29 +08:00

223 lines
5.6 KiB
JavaScript

'use strict';
/* eslint-disable no-console */
const fs = require('fs');
const path = require('path');
const startCase = require('lodash.startcase');
const correctAnchor = require('./correct-anchor');
const config = require('./config');
const langs = config.langs;
const docConfig = require('../config.json');
const docsDir = path.join(__dirname, '../');
const watchMode = process.argv[2] === '-w';
let cache = {};
start();
function start(){
build();
if (watchMode) {
watch();
}
}
function build() {
sammary();
cache = {};
combo();
}
function watch(){
fs.watch(docsDir, { recursive: true }, (eventType, filename) => {
if (filename.indexOf('/_book') >= 0) {
return;
}
if (filename.indexOf('/script') >= 0) {
return;
}
const ignores = langs.reduce((result, lang) => {
result.push(`${lang}/README.md`);
result.push(`${lang}/SUMMARY.md`);
return result;
}, []);
const isConfigFile = filename === 'config.json';
if (isConfigFile) {
console.warn('Please restart the docs:watch cmd !');
return;
}
const isWatchTarget = langs.some(lang => {
return filename.startsWith(lang) && ignores.indexOf(filename) < 0;
});
if (isWatchTarget) {
console.log(`file: ${filename} type: ${eventType}`);
build();
}
});
langs.forEach((lang) => {
console.info(`***** start watching ${docsDir}/${lang}/*.md *****`);
});
}
function getFilename({ lang, parentPaths, slug, isDir }) {
let filename = '';
if (isDir) {
filename = path.join(docsDir, lang, parentPaths.join('/'), isDir ? slug : '', 'README.md');
if (fs.existsSync(filename)) {
return filename;
}
}
filename = path.join(docsDir, lang, parentPaths.join('/'), `${slug}.md`);
if (fs.existsSync(filename)) {
return filename;
}
return '';
}
function getFileId(arr) {
return arr.join('_');
}
function generateNavTitle({ parentPaths, item, sign, lang }) {
const isDir = typeof item === 'object' && item.catalog && item.catalog.length;
const slug = typeof item === 'string' ? item : typeof item === 'object' ? item.name : '';
const sign_ = sign || '*';
if (!slug) {
return null;
}
const filename = getFilename({
lang, parentPaths, slug, isDir
});
const anchor = filename ? getFileId(parentPaths.concat(slug)) : '';
const prefix = parentPaths.reduce((pre, next) => {
return pre += '\t';
}, '');
const title = typeof item === 'string' ? prettyCatalog(item) : item.i18n ?
item.i18n[lang] || item.i18n['en-us'] || prettyCatalog(item.name) : prettyCatalog(item.name);
return `${prefix}${sign_} [${title}](README.md#${anchor})`;
}
function appendTitleAnchor(content, anchor) {
return content.replace(/(\#+.*)/, (match, p1) => {
return `${p1} {#${anchor}}`;
});
}
function walk({ catalog, lang, result, parentPaths, fn }) {
if (!catalog || !catalog.length) {
return result;
}
return catalog.reduce((result, item) => {
const slug = typeof item === 'string' ? item : typeof item === 'object' ? item.name : '';
if (slug) {
const isDir = item.catalog && item.catalog.length;
fn({ parentPaths, lang, item, isDir, result });
if (isDir) {
parentPaths.push(slug);
result = walk({ catalog: item.catalog, lang, result, parentPaths, fn });
parentPaths.pop();
}
}
return result;
}, result);
}
/**
* generate `SUMMARY.md` by `config.json`
*/
function sammary() {
const nodeFn = function ({ parentPaths, lang, item, isDir, result }) {
const navTitle = generateNavTitle({ parentPaths, item, sign: isDir ? '-' : '*', lang });
result.push(navTitle);
};
langs.forEach(dir => {
const SUMMARY = 'SUMMARY.md';
const targetFile = path.join(docsDir, `${dir}/${SUMMARY}`);
const result = walk({
catalog: docConfig.catalog,
lang: dir,
result: [],
parentPaths: [],
fn: nodeFn
});
if (result && result.length) {
result.unshift('# whistle\n');
fs.writeFileSync(targetFile, result.join('\n'));
}
});
}
function combo() {
const nodeFn = function ({ parentPaths, lang, item, result }) {
const isDir = typeof item === 'object' && item.catalog && item.catalog.length;
const slug = typeof item === 'string' ? item : typeof item === 'object' ? item.name : '';
const filename = getFilename({
parentPaths, lang, slug, isDir
});
const fileId = getFileId(parentPaths.concat(slug));
if (filename) {
let content = fs.readFileSync(filename).toString();
content = appendTitleAnchor(content, fileId);
content = correctAnchor({rootPath: path.join(docsDir, lang) , absFilename: filename, content})
cache[fileId] = content;
result.push(fileId);
}
};
langs.forEach(dir => {
const README = 'README.md';
const targetFile = path.join(docsDir, `${dir}/${README}`);
const result = walk({
catalog: docConfig.catalog,
lang: dir,
result: [],
parentPaths: [],
fn: nodeFn
});
if (result && result.length) {
const content = result.reduce((pre, next) => {
if (cache[next]) {
pre += cache[next] + '\n\n';
}
return pre;
}, '');
fs.writeFileSync(targetFile, content);
}
});
}
function isChinese(string) {
var req = /[\u4E00-\u9FA5]|[\uFE30-\uFFA0]/gi;
if (!req.exec(string)) {
return false;
} else {
return true;
}
}
function isNonAscii(string) {
var regExp = /^[ -~\t\n\r]+$/gi;
return !regExp.test(string);
}
function prettyCatalog(fileName) {
if (isChinese(fileName) || isNonAscii(fileName)) {
return fileName;
}
return startCase(fileName);
}