什么是 JSDoc

JSDoc (Github地址) 是一种用于 JavaScript 代码的 API 文档生成工具,它允许开发者通过注释的方式为代码添加文档说明。JSDoc 可以解析这些注释,并生成 HTML 格式的文档,帮助开发者更好地理解和使用代码。JSDoc 采用了 Apache License 2.0 开源协议。VS Code 内置了对 JSDoc 风格注释的支持,在 Javascript 和 TypeScript 代码中书写 JSDoc 风格的注释会自动高亮。

JSDoc 的实现原理

JSDoc 的实现原理主要基于注释解析。开发者在 JavaScript 代码中使用特定格式的注释(通常是以 /** 开头的多行注释),JSDoc 工具会扫描这些注释并提取信息。提取的信息包括函数的参数、返回值、类型、描述等。然后,JSDoc 会将这些信息转换为结构化的文档格式(如 HTML),并生成相应的文档。

JSDoc 常见用法

  1. 基本注释格式:
1
2
3
4
5
6
7
8
/**
* 函数描述
* @param {类型} 参数名 参数描述
* @returns {类型} 返回值描述
*/
function example(param) {
return param;
}
  1. 类型注释:
    可以使用 {} 来指定参数和返回值的类型,例如:
1
2
3
4
5
6
7
8
/**
* @param {string} name 用户名
* @param {number} age 用户年龄
* @returns {boolean} 是否成年
*/
function isAdult(name, age) {
return age >= 18;
}
  1. 模块和类注释:
    JSDoc 也支持模块和类的文档注释:
1
2
3
4
5
6
7
8
9
10
11
12
/**
* @class
*/
class Person {
/**
* @constructor
* @param {string} name
*/
constructor(name) {
this.name = name;
}
}
  1. 使用名称路径
    如果涉及到一个 JavaScript 变量,这个变量在文档中的其他地方,你必须提供一个唯一标识符映射到该变量。名称路径提供了一种这样做的方法,并且消除实例成员,静态成员和内部变量之间的歧义
1
2
3
4
5
6
7
8
/**
* Person#say // 名为"say"的实例方法
* Person.say // 名为"say"的静态方法
* Person~say // 名为"say"的内部函数
* @module foo/bar // 名为"foo/bar"的模块
* @external String // 内置的 string 对象
* @event module:foo/bar.event:MyEvent // 一个名为 module:foo/bar.event:MyEvent 的事件
*/

JSDoc 块标签与内联标签

JSDoc支持两种不同类型的标签:

· 块标签(Block): 这是在一个 JSDoc 注释的最高级别。
· 内联标签(inline): 块标签文本中的标签或说明。

块标签通常会提供有关代码的详细信息,如一个函数接受的参数。内联标签通常链接到文件的其他部分,类似于HTML中的锚(<a>)标记。

块标签总是以 @ 符号开头。除了 JSDoc 注释中最后一个块标记,每个块标签后面必须跟一个换行符。

内联标签也以 @ 符号开。然而,内联标签及其文本必须用花括号 {} 括起来。 { 表示行内联标签的开始,而 } 表示内联标签的结束。如果标签文本中包含 },则必须用 \ 进行转义。在内联标签后,你并不需要使用一个换行符。

大多数 JSDoc 标签是块标签。一般来说,当这个网站上说“JSDoc 标签”,我们真正的意思是“块标签”。block-tags 记录了在 JSDoc 中所有识别的块标签。

如下是一个示例,@param 是一个块标签,而 {@link} 是一个内联标签:

1
2
3
4
5
6
7
8
/**
* Set the shoe's color. Use {@link Shoe#setSize} to set the shoe size.
*
* @param {string} color - The shoe's color.
*/
Shoe.prototype.setColor = function (color) {
// ...
};

JSDoc 命令行

JSDoc 可以使用命令行工具生成文档:

1
2
npm install -g jsdoc
jsdoc yourfile.js

执行该命令后,JSDoc 会在 /out 目录下生成当前目录的文档。JSDoc 支持大量的命令行选项,其中许多选项有长和短两种形式。

短选项 完整选项 描述
-c <value> --configure <value> JSDoc 配置文件的路径。默认为安装 JSDoc 目录下的 conf.jsonconf.json.EXAMPLE
-d <value> --destination <value> 输出生成文档的文件夹路径。默认为 ./out
-e <value> --encoding <value> 源文件的编码。默认为 utf8
-h --help 显示 JSDoc 的命令行选项的信息,然后退出
-p --private 将标记有 @private 标签的标识符也生成到文档中。默认情况下,不包括私有标识符
-r --recurse 扫描源文件和导览时递归到子目录
-t <value> --template <value> 指定模板文件夹的路径。默认为 ./templates/default
-v --version 显示 JSDoc 的版本号,然后退出
--verbose 日志的详细信息到控制台 JSDoc 运行。默认为 false
--debug 显示调试信息到控制台 JSDoc 运行。默认为 false
--pedantic 当 JSDoc 遇到错误时,它将停止运行。默认为 false

JSDoc 配置文件

JSDoc 的命令行选项也可以在配置文件中指定。要使用配置文件运行 JSDoc,需要使用 -c 命令行选项(例如,jsdoc -c /path/to/conf.jsonjsdoc -c /path/to/conf.js)。

默认配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"plugins": [], // 无插件加载
"recurseDepth": 10, // 如果使用 -r 命令行标志启用递归,JSDoc 将搜索 10 层深的文件
"source": { // 源代码配置
"includePattern": ".+\\.js(doc|x)?$", // 只有以 .js、.jsdoc 和 .jsx 结尾的文件将会被处理
"excludePattern": "(^|\\/|\\\\)_" // 任何文件或目录如果以 _ 开始将被忽略
},
"sourceType": "module", // "script",表示脚本文件,"module" 表示模块文件
"tags": { // 标签配置
"allowUnknownTags": true, // 允许使用未知的标签
"dictionaries": ["jsdoc", "closure"] // 允许使用 jsdoc 标签 和 [closure 标签](https://github.com/google/closure-compiler/wiki/Annotating-JavaScript-for-the-Closure-Compiler#jsdoc-tags)
},
"templates": { // 模板配置
"cleverLinks": false, // 链接到源码
"monospaceLinks": false // 源码行号
}
}

JSDoc 插件

在 JSDoc 中,插件的作用是扩展 JSDoc 的功能,比如添加新的标签、解析新的语法等。首先,需要创建一个包含插件代码的 Javascript 模块,然后将该模块添加到 JSDoc 的配置文件 plugin 参数中,以启用插件。

一个 JSDoc 插件可以:
· 定义事件处理程序
· 定义自定义标签,如 @author@version 等。
· 定义一个抽象的解析器,用于解析自定义标签。

JSDoc 插件的事件处理程序包括:
Event: parseBegin: JSDoc 开始加载和解析源文件之前,parseBegin 事件被触发。插件可以通过修改事件的内容,来控制哪些文件将被 JSDoc 解析。(>=JSDoc@3.2.0)
Event: fileBegin: 当解析器即将解析一个文件 fileBegin 事件触发。如果需要,插件可以使用此事件触发每个文件的初始化。
Event: beforeParse: beforeParse 事件在解析开始之前被触发。插件可以使用此方法来修改将被解析的源代码。
Event: jsdocCommentFound: 每当 JSDoc 注释被发现,jsdocCommentFound 事件就会被触发。注释可以或不与任何代码相关联。你可以在注释被处理之前使用此事件修改注释的内容。(>=JSDoc@3.5.0)
Event: symbolFound: 当解析器在代码中遇到一个可能需要被文档化的标识符时,symbolFound 事件就会被触发。
Event: newDoclet: newDoclet事件是最高级别的事件。新的 doclet 已被创建时,它就会被触发。这意味着一个 JSDoc 注释或标识符已被处理,并且实际传递给模板的 doclet 已被创建。
Event: fileComplete: 当解析器解析完一个文件时,fileComplete 事件就会被触发。插件可以使用这个事件来触发每个文件的清理。
Event: parseComplete: JSDoc 解析所有指定的源文件之后,parseComplete 事件就会被触发。(>=JSDoc@3.2.0)
Event: processingComplete: JSDoc 更新反映继承和借来的标识符的解析结果后,processingComplete 事件被触发。(>=JSDoc@3.2.1)

JSDoc 包含一个 Markdown 插件来自动将 Markdown 格式文本转换成 HTML。可以通过如下配置开启:

1
2
3
4
5
6
7
8
9
{
"plugins": ["plugins/markdown"],
"markdown": {
"tags": ["foo", "bar"], // 扩展需解析 markdown 的标签
"excludeTags": ["author"], // 不解析 markdown 的标签
"hardwrap": true, // 是否强制换行(>=JSDoc@3.4.0)
"idInHeadings": true, // 是否在标题中添加 id(>=JSDoc@3.4.0)
}
}

Markdown 插件默认只解析特定的 JSDoc 标签(@author,@classdesc,@description,@param,@property,@return,@see,@throws),可以通过在配置文件的 markdown.tags 字段中添加标签来扩展解析范围。可以通过 markdown.excludeTags 字段来排除默认标签的解析。

其他功能

· JSDoc 支持通过 --tutorials-u 选项提供 JSDoc 要搜索的教程目录从而为 API 文档添加教程。
· JSDoc 支持通过 --package-P 选项指定 package.json 文件的路径从而在生成文档的时候自动使用 package.json 的信息。(>=JSDoc@3.3.0)
· JSDoc 支持通过 --readme-R 选项指定将 README 文件中的信息合并到文档中。(>=JSDoc@3.3.0)