☰
documentation.js 主题定制完全指南:从默认主题改造到自定义 HTML 生成
2026/10/12 4:36:29 网站建设 项目流程
  • 文档
  • CLI

【免费下载链接】documentation

:book: documentation for modern JavaScript

项目地址:https://gitcode.com/gh_mirrors/do/documentation
点击查看免费下载

本文围绕 documentation.js(本项目即其主仓库,当前版本 14.0.3)的主题机制展开,系统讲解 HTML 输出主题的接口契约、默认主题的目录结构与渲染流程、--theme命令行接入方式、基于默认主题二次开发的完整步骤,以及如何通过documentation.yml注入样式、如何理解 Markdown 输出为何不可主题化。读完本文,你将能够从零搭建自己的 documentation.js 主题,并将其接入documentation build -f html流水线。

主题的本质:一个返回 vinyl File 数组的 Node.js 模块

documentation.js 对"主题"的定义非常开放:主题就是一个 Node.js 模块,导出单个函数,其签名与回调约定如下(源自 docs/THEMING.md 的原始契约描述):

/** * @function * @param {Array<Object>} comments - an array of comments to be output * @param {Object} options - theme options * @param {ThemeCallback} callback - see below */ /** * @callback ThemeCallback * @param {?Error} error * @param {?Array<vinyl.File>} output */

要点拆解:

  • comments:由 documentation.js 解析、推断并分层(nest)后的注释对象数组。它来自 src/index.js 中build()构建的完整管线——inferName、inferKind、inferParams、nest、filterAccess、hierarchy等步骤处理完毕的最终数据,主题拿到的是"可直接渲染"的语义结构,而非原始源码。
  • options:主题选项,即当前构建的完整配置对象(由 src/merge_config.js 合并 CLI 参数、documentation.yml与package.json推断字段后的结果)。
  • callback:错误优先回调,成功时第二个参数必须是一个 vinylFile对象数组。每个File代表一个待输出文件(如index.html、assets/xxx.css),带有path、base、contents等属性。

主题完全可以自由选择 HTML 的生成方式:可以用模板字符串拼接、用 underscore/lodash 模板、用 JSX、用任何你喜欢的渲染库。默认主题就采用了 lodash 模板方案,可作为最佳参考实现。

从当前仓库的源码看,src/output/html.js 的实际加载逻辑为:主题路径解析后通过动态import()加载,并调用其default 导出:

let themePath = config.theme && path.resolve(process.cwd(), config.theme); if (themePath) { if (process.platform === 'win32'){ // On Windows, absolute paths must be prefixed with 'file:///' to avoid the ERR_UNSUPPORTED_ESM_URL_SCHEMA error from import(). themePath = 'file:///' + themePath; } return (await import(themePath)).default(comments, config); } return (await import('../default_theme/index.js')).default(comments, config);

也就是说:只要你的模块export default一个可调用函数,并能消费(comments, config)两个参数,就能被当作主题使用。值得注意的细节:

  • 主题路径基于process.cwd()解析,所以相对路径是相对你运行命令的目录,而不是相对配置文件。
  • Windows 平台下路径会被自动加上file:///前缀,规避 ESM 动态导入的协议错误。
  • 未指定--theme时,回退到仓库内置的 src/default_theme/index.js。

默认主题的目录解剖

默认主题位于 src/default_theme/,其构成在 src/default_theme/README.md 中有明确说明:

文件/目录作用
index._主模板,定义整页 HTML 骨架(<head>、左侧 TOC 导航、右侧内容区)
section._局部模板,渲染每一条 API 文档块(签名、类型、参数、返回值、示例等)
note._局部模板,渲染叙事型 note 区块
section_list._局部模板,渲染成员列表(Static / Instance / Inner / Events)
paramProperty._局部模板,渲染参数属性表格
assets/静态资源:bass.css、github.css、style.css、split.css、anchor.js、split.js、site.js,以及内置的 SourceCodePro 字体族

渲染主流程(源码级)

src/default_theme/index.js 的核心逻辑可概括为四步:

  1. 准备共享工具:创建LinkerStack(命名空间到锚点的解析器)与createFormatters(类型格式化、参数签名、Markdown 渲染等工具);通过hljs.configure(config.hljs || {})配置 highlight.js 代码高亮。
  2. 编译模板:用lodash/template依次读取并编译section_list._、section._、note._、paramProperty._,再以它们为局部函数编译index._主模板。所有模板共享一组imports,包括slug()(GitHub 风格锚点)、signature()/shortSignature()(函数签名)、md()(AST → Markdown)、formatType、autolink、highlight()等。
  3. 渲染整页:pageTemplate({ docs: comments, config })生成完整 HTML 字符串。
  4. 落盘:若配置了config.output,则将assets/目录整体复制到config.output/assets/,并写入config.output/index.html;否则直接返回字符串。

index._的页面结构值得关注:左侧是带Filter搜索框的 TOC(按 namespace 生成锚点,静态/实例/内部/事件成员分组折叠),右侧是正文区;底部挂载anchor.js、split.js、site.js实现锚点与左右分栏交互。section._则负责单条注释的展示:名称 + GitHub 源码链接、签名代码块、类型、Extends、参数表、属性、Returns、Related、Throws、示例(经highlight()高亮)、以及各级成员区块。

命令行接入:--theme/-t

主题通过 CLI 选项接入构建流程。在 src/commands/shared_options.js 中:

theme: { describe: 'specify a theme: this must be a valid theme module', alias: 't' }

配合documentation build命令(src/commands/build.js),典型用法为:

documentation build index.js -f html -o docs --theme node_modules/docjs-theme

几个关联注意点:

  • HTML 输出必须指定输出目录:build命令在-f html且-o缺省(stdout)时会直接报错The HTML output mode requires a destination directory set with -o。因为 HTML 是多文件输出(index.html+assets/),无法写进 stdout。
  • 未指定--theme时走内置默认主题,因此该选项只是"换皮肤"的入口,默认主题就是 src/default_theme。
  • 主题模块既可以指向仓库内路径(如--theme node_modules/docjs-theme),也可以指向本地目录(如--theme my-theme)。

仓库自带的测试 fixturetests/fixture/custom_theme/index.js 给出了一个最小可运行主题:

var File = require('vinyl'); /** * This is a theme only used by documentation to test custom theme * support. */ module.exports = function(comments, options, callback) { return Promise.resolve([ new File({ base: '/', path: '/index.html', contents: Buffer.from('Hello world') }) ]); };

它展示了主题的最低实现形态:接收comments与options,产出一个vinyl.File实例(路径index.html、内容为二进制 Buffer)。对应测试见tests/bin.js 中的write to html with custom theme用例(通过-t fixture/custom_theme --shallow fixture/internal.input.js -f html -o <目录>触发)。

基于默认主题进行二次开发(官方推荐路径)

原文档给出了一条非常实用的"复制改造"路线,适用于不想从零编写模板、只想微调默认主题视觉或布局的场景:

  1. 复制主题源码:把仓库内src/default_theme文件夹的全部内容复制到你项目的某个新目录(例如docjs-theme/)。
  2. 修正内部依赖引用:在你新建的主题index.js中,把原先指向仓库内部模块的require('../')(原文档描述的是该文件第 8、9 行的引用,对应旧版 CommonJS 结构)替换为require('documentation'),然后保存。这样你的主题就与文档生成器本体解耦,可独立安装使用。
    • 提示:当前仓库已迁移为 ESM 模块("type": "module",见 package.json),内置主题 src/default_theme/index.js 通过import { util } from '../index.js'获取LinkerStack与createFormatters。在自建主题中,等价的做法是从documentation包导入util或自行实现模板辅助函数。以仓库当前源码为准:主题只需要对外提供 default 导出函数即可被 src/output/html.js 正确加载。
  3. 将主题作为依赖安装:把该目录放进一个 git 仓库,然后在项目package.json的devDependencies中声明:
    "devDependencies": { "docjs-theme": "my-gh-username/reponame" }

    这样执行依赖安装后,你的主题会出现在项目的node_modules目录中,可被--theme直接引用。

  4. 生成文档验证:在package.json的scripts中配置:
    "scripts": { "docs": "documentation build index.js -f html -o docs --theme node_modules/docjs-theme" }

    之后对主题模板或样式所做的任何修改,都会在你重新运行npm run docs时反映到生成的文档中。

这套流程的妙处在于:主题作为独立 npm 依赖被解析,--theme只是指向node_modules下的模块路径,因此可以跨项目复用、版本化管理。

通过 documentation.yml 注入样式:轻量改版

如果只是想做小范围的样式调整,不必复制整套主题——可以借助documentation.yml的叙事区块在文档 HTML 中注入<style>。

documentation.yml本身用于组织文档目录结构(详见 docs/CONFIG.md):toc数组按顺序排列 API 条目,并允许插入带name+description(Markdown 解释)的叙事区块,还支持file属性引用外部 Markdown 文件、children属性做分组。样式注入正是借助叙事区块的description完成的:

toc: - name: Section Header Name description: | <head> <style> h2{ color:black; } code.black{ background-color: #295377; overflow: hidden; padding: 0.5rem; color: white; font: 0.8rem Inconsolata, monospace; width:100%; } </style> </head> ### Sub Section header Text that describes the section and sub-section here.

运行documentation build --config documentation.yml -f html -o docs后,上述<style>会随该区块进入生成的 HTML。

使用时有两点重要提醒(原文档明确强调):

  • 覆盖优先级:凡是在标准主题中已存在的元素与类,其样式会被documentation.yml中的定义覆盖——也就是说你的自定义 CSS 会与默认主题 CSS 同时存在并发生竞争,容易造成"同一套 CSS 被定义两遍"的困惑。
  • 推荐做法:只用默认 documentation.js 主题中不存在的类来注入样式(例如上面示例里的code.black),避免覆盖行为引发样式漂移;若需要系统性改版,仍应走"复制默认主题"的完整路线。

Markdown 输出为什么不能主题化

原文档明确指出:documentation.js 的默认 Markdown 生成器是不可主题化的。与 HTML 主题(自由模板)不同,Markdown 的输出链路是:

  1. src/output/markdown_ast.js 将注释数据构建为 remark 兼容的抽象语法树(AST)——从源码结构看,它按注释逐条生成标题、类型、参数列表、属性列表、示例代码块、Returns、Throws、Meta 等节点,并支持通过config.hljs配置代码高亮、通过markdownToc/markdownTocMaxDepth控制目录;
  2. src/output/markdown.js 再用remark().use(remarkGfm).stringify(ast)把 AST 序列化成 Markdown 字符串。

这意味着:Markdown 的"主题"实际上是固定管线,没有对外开放的模板钩子。如果你需要 Markdown 里额外的内容或版式,原文档给出的两条出路是:

  • 向默认主题提需求:推动某个能力被合入官方默认 Markdown 生成器;
  • 曲线救国:写一个输出 Markdown 的HTML 主题——因为 HTML 主题对输出内容有完全控制权,你可以在主题内部生成 Markdown 文本(甚至用 vinyl File 输出.md文件),从而绕过固定管线的限制。

如果你只是想要"类似主题"的轻量控制,CLI 层面还有--markdown-toc(是否生成目录,默认 true)与--markdown-toc-max-depth(目录最大深度,默认 6)两个选项可用(见 src/commands/shared_options.js),它们由 src/output/markdown_ast.js 消费。

一张速查表:三种"改外观"手段怎么选

需求手段涉及配置/路径
整体换肤、改布局、完全掌控 HTML自建主题,--theme指向主题模块src/output/html.js、src/commands/shared_options.js
在默认主题基础上小幅调整样式复制 src/default_theme 二次开发,发布为依赖上文"二次开发"四步
只在个别叙事区块做小样式微调documentation.yml中注入<style>docs/CONFIG.md、src/merge_config.js
Markdown 输出的目录/格式微调--markdown-toc、--markdown-toc-max-depthsrc/output/markdown_ast.js
Markdown 深度定制写一个输出 Markdown 的 HTML 主题主题接口同上

最后再强调一遍主题契约的核心:一个导出函数的模块,接收comments与配置,产出 vinylFile数组或直接返回 HTML 字符串。理解了这一点,无论你是复制默认主题微调,还是从零实现一套自己的渲染引擎,都能顺利接入 documentation.js 的 HTML 输出流水线。

  • 文档
  • CLI

【免费下载链接】documentation

:book: documentation for modern JavaScript

项目地址:https://gitcode.com/gh_mirrors/do/documentation
点击查看免费下载

相关推荐

上一篇:终极游戏存档备份指南:用Ludusavi保护你的游戏进度
下一篇:如何用10MB软件替代500MB官方控制中心?G-Helper为华硕笔记本带来全新体验

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询