t-comm
Version:
专业、稳定、纯粹的工具库
333 lines (330 loc) • 10.5 kB
JavaScript
import _classCallCheck from '@babel/runtime/helpers/classCallCheck';
import _createClass from '@babel/runtime/helpers/createClass';
import { getFs } from '../nodejs/fs.mjs';
import { getPath } from '../nodejs/path.mjs';
import { getCheerio } from '../third-party/cheerio.mjs';
import { timeStampFormat } from '../time/time.mjs';
var DEFAULT_EXTRA_CSS = "\n.nav-separator {\n color: hsl(207, 1%, 60%);\n font-size: 12px;\n display: block;\n}\n\nnav ul a, nav ul a:active {\n font-size: 14px;\n}\n";
function getSeparatorStr(content) {
var maxLen = 14;
var lastLen = parseInt("".concat(maxLen - content.length / 2), 10);
var fill = Array.from({
length: lastLen
}).map(function () {
return '-';
}).join('');
return "".concat(fill, " ").concat(content, " ").concat(fill);
}
/**
* 删除重复的部分
* @ignore
*/
function deleteRepeatedSections($) {
var sections = $('section');
var last = '';
sections.map(function (_, section) {
var html = $(section).html().trim();
if (html === last) {
$(section).remove();
} else {
last = html;
}
});
return $;
}
/**
* 替换footer
* @ignore
* @param $ cheerio
* @param author 作者
*/
function replaceFooter($, author) {
var timezone = new Date().getTimezoneOffset() / -60;
var footerContent = "Documentation generated on ".concat(timeStampFormat(Date.now(), 'yyyy-MM-dd hh:mm:ss'), " GMT+0").concat(timezone, "00 ").concat(author && " by ".concat(author), ".");
$('footer').html(footerContent);
}
/**
* 找到 Modules 下的导航列表
* @ignore
* @param $ cheerio
*/
function findModuleNav($) {
var titles = $('body nav h3');
var res;
titles.map(function (_, title) {
if ($(title).html().trim() === 'Modules') {
res = $(title).next();
}
});
return res;
}
/**
* 获取nav头部,比如 tools/url => tools
* @ignore
* @example
* ```ts
* getNavPrefix('tools/url'); // 'tools'
* getNavPrefix('url'); // ''
* ```
*/
function getNavPrefix() {
var nav = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
if (nav.indexOf('/') < 0) {
return '';
}
return nav.split('/')[0];
}
/**
* 给 Modules 下的导航列表插入分隔符
* @ignore
* @param $ cheerio
*/
function insertModuleNavSeparator($) {
var module = findModuleNav($);
if (!module) return;
var last = '';
$(module).children('li').map(function (_, li) {
var _a, _b;
var nav = (_b = (_a = $(li).children('a')) === null || _a === void 0 ? void 0 : _a.html()) === null || _b === void 0 ? void 0 : _b.trim();
var prefix = getNavPrefix(nav);
if (prefix && last !== prefix) {
$(li).before("<li class=\"nav-separator\">".concat(getSeparatorStr(prefix), "</li>"));
}
if (prefix) {
last = prefix;
var navList = nav.split('/');
$(li).children('a').html(navList.slice(1).join('/'));
}
});
}
/**
* 插入分隔符
* @ignore
*/
function insertNavSeparator($, sourceMap) {
var naves = $('nav > ul li');
var cur = '';
naves.map(function (_, dom) {
var _a;
var nav = (_a = $(dom).find('a').attr('href')) === null || _a === void 0 ? void 0 : _a.trim();
if (nav && sourceMap[nav] && cur !== sourceMap[nav]) {
$(dom).before("<li class=\"nav-separator\">".concat(sourceMap[nav], "</li>"));
cur = sourceMap[nav];
}
});
}
/**
* 插入script
* @ignore
*/
function insertScript($) {
var script = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
if (!script) return;
$('head').children().last().after(script);
}
/**
* 默认处理source的方法,默认仅去掉的文件名
* @ignore
* @param source 文件路径
* @returns 处理后的数据
* @example
* ```ts
* defaultNavHandler('base/url/url.ts');
* // 'base/url'
* ```
*/
function defaultNavHandler(source) {
var list = source.split('/');
return list.slice(0, list.length - 1).join('/');
}
var JsDocHandler = /*#__PURE__*/function () {
/**
* 处理jsdoc的脚本
* 1. 增加导航栏的分隔符
* 2. 增加css
* 3. 处理footer
* @constructor
* @param {object} options 配置
* @param {string} [options.docsPath] 文档所在目录位置,默认为`./docs`
* @param {string} [options.author] 作者,默认为空
* @param {string} [options.extraCss] 额外插入的css,默认为`.nav-separator`的一些样式
* @param {string} [options.extraScript] 额外插入的script
* @param {Function} [options.navHandler] 处理API所在文件的方法
* @param {boolean} [options.isHandleNav] 是否处理导航栏,即插入文件名进行分隔,默认为false
*/
function JsDocHandler() {
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
_classCallCheck(this, JsDocHandler);
var _options$docsPath = options.docsPath,
docsPath = _options$docsPath === void 0 ? './docs' : _options$docsPath,
_options$author = options.author,
author = _options$author === void 0 ? '' : _options$author,
_options$extraCss = options.extraCss,
extraCss = _options$extraCss === void 0 ? DEFAULT_EXTRA_CSS : _options$extraCss,
_options$extraScript = options.extraScript,
extraScript = _options$extraScript === void 0 ? '' : _options$extraScript,
_options$navHandler = options.navHandler,
navHandler = _options$navHandler === void 0 ? defaultNavHandler : _options$navHandler,
_options$isHandleNav = options.isHandleNav,
isHandleNav = _options$isHandleNav === void 0 ? false : _options$isHandleNav;
this.docsPath = docsPath;
this.author = author;
this.extraCss = extraCss;
this.extraScript = extraScript;
this.navHandler = navHandler;
this.isHandleNav = isHandleNav;
this.fs = this.getFs();
this.path = getPath();
}
return _createClass(JsDocHandler, [{
key: "run",
value: function run() {
var sourceMap = {};
if (this.isHandleNav) {
sourceMap = this.getGlobalSourceMap();
}
this.handleEveryHtml(sourceMap, this.author);
this.appendCSS(this.extraCss);
this.finished();
}
}, {
key: "getFs",
value: function getFs$1() {
return getFs();
}
}, {
key: "getGlobalSourceMap",
value: function getGlobalSourceMap() {
console.log('[Jsdoc] Parsing nav list of global.html ...');
var file = 'global.html';
var sourceMap = this.getSourceMap(file);
return this.parseSourceMap(sourceMap);
}
/**
* 获取sourceMap,形如:
* ```ts
* {
* NUMBER_CHI_MAP: 'base/number/number.ts',
* parseFunction: 'base/function/function.ts',
* flatten: 'base/list/list.ts',
* }
* ```
* @private
* @param {string} content
* @returns {object} sourceMap
*/
}, {
key: "getSourceMap",
value: function getSourceMap(file) {
var _this = this;
var html = this.path.resolve(this.docsPath, file);
var content = this.fs.readFileSync(html, {
encoding: 'utf-8'
});
var cheerio = getCheerio();
var $ = cheerio.load(content);
var sourceMap = {};
var names = $('#main section article h4.name');
names.map(function (_, dom) {
var id = $(dom).attr('id');
var source = ($(dom).next().find('dd.tag-source ul.dummy li a').html() || '').trim();
source = _this.navHandler(source);
sourceMap["".concat(file, "#").concat(id)] = source;
});
return sourceMap;
}
}, {
key: "handleEveryHtml",
value: function handleEveryHtml(sourceMap, author) {
var _this2 = this;
var files = this.fs.readdirSync(this.docsPath);
files.forEach(function (file) {
if (file.endsWith('.html')) {
var filePath = _this2.path.resolve(_this2.docsPath, file);
var content = _this2.fs.readFileSync(filePath, {
encoding: 'utf-8'
});
var html = _this2.getParsedHtml(content, sourceMap, author);
_this2.fs.writeFileSync(filePath, html, {
encoding: 'utf-8'
});
}
});
}
}, {
key: "parseSourceMap",
value: function parseSourceMap(sourceMap) {
return Object.keys(sourceMap).reduce(function (acc, key) {
var value = sourceMap[key];
acc[key] = getSeparatorStr(value);
return acc;
}, {});
}
}, {
key: "getParsedHtml",
value: function getParsedHtml(content, sourceMap, author) {
var cheerio = getCheerio();
var $ = cheerio.load(content);
var extraScript = this.extraScript;
// 删除重复selection
deleteRepeatedSections($);
// 插入分隔符
insertNavSeparator($, sourceMap);
// Modules下的导航栏插入分隔符
insertModuleNavSeparator($);
// 插入script
insertScript($, extraScript);
// 处理footer
replaceFooter($, author);
return $.html();
}
}, {
key: "appendCSS",
value: function appendCSS(extra) {
console.log('[Jsdoc] Appending extra css ...');
var css = this.path.resolve(this.docsPath, 'styles/jsdoc.css');
var content = this.fs.readFileSync(css, {
encoding: 'utf-8'
});
this.fs.writeFileSync(css, "".concat(content, " \n").concat(extra), {
encoding: 'utf-8'
});
}
}, {
key: "finished",
value: function finished() {
console.log('[Jsdoc] Finished jsdoc local script.');
}
}], [{
key: "init",
value:
/**
* 初始化并运行
* @static
* @param {object} options 配置
* @param {string} [options.docsPath] 文档所在目录位置,默认为`./docs`
* @param {string} [options.author] 作者,默认为空
* @param {string} [options.extraCss] 额外插入的css,默认为`.nav-separator`的一些样式
* @param {string} [options.navHandler] 处理API所在文件的方法
* @param {boolean} [options.isHandleNav] 是否处理导航栏,即插入文件名进行分隔,默认为false
* @returns {object} JsDocHandler实例
* @example
*
* JsDocHandler.init({
* author: 'novlan1',
* docsPath: './docs',
* extraCss: '.some-class{}',
* navHandler(nav) {
*
* }
* })
*
*/
function init(options) {
var handler = new JsDocHandler(options);
handler.run();
return handler;
}
}]);
}();
export { JsDocHandler, defaultNavHandler, getNavPrefix, getSeparatorStr };