关于JSDoc插件

创建和启用插件

创建和启用新的JSDoc插件需要两个步骤:

  1. 创建一个JavaScript模块以包含您的插件代码.

  2. 将该模块包含在 plugins 数组中 configured-jsdoc. 您可以指定绝对路径或相对路径。如果使用相对路径,JSDoc将在当前工作目录中搜索插件;配置文件所在的目录;和JSDoc目录,按此顺序。

例如, 如果您的插件是在当前工作目录的 plugins/shout.js 文件中定义的, 那么您应该将字符串 plugins/shout 添加到JSDoc配置中的 plugins 数组中文件:

将插件添加到 JSDoc 的配置文件中
{
    "plugins": ["plugins/shout"]
}

JSDoc按照配置文件中列出的顺序执行插件.

关于JSDoc插件

JSDoc 3 的插件系统提供了对解析过程的广泛控制. 插件可以通过执行以下任一操作来影响解析结果:

  • 定义事件处理程序

  • 定义标签

  • 为抽象语法树节点定义访问者

事件处理程序

在最高级别, 插件可以为JSDoc触发的特定命名事件注册处理程序. JSDoc会将一个事件对象传递给处理程序. 你的插件模块应该导出一个包含你的处理程序的 handlers 对象, 如下所示:

‘newDoclet’ 事件的事件处理程序插件
exports.handlers = {
    newDoclet: function(e) {
        // Do something when we see a new doclet
    }
};

JSDoc以与底层代码相同的顺序触发事件.

事件处理程序插件可以通过在事件对象上设置 stopPropagation 属性(e.stopPropagation = true)来阻止以后的插件运行. 插件可以通过设置 preventDefault 属性(e.preventDefault = true)来停止触发事件.

Event: parseBegin

在JSDoc开始加载和解析源文件之前, 会触发 parseBegin 事件. 您的插件可以通过修改事件的内容来控制JSDoc将解析哪些文件.

Note: 此事件在JSDoc 3.2及更高版本中触发.

事件对象包含以下属性:

  • sourcefiles: 要解析的源文件的路径数组.

Event: fileBegin

解析器即将解析文件时 fileBegin 事件. 如有必要, 您的插件可以使用此事件触发每个文件的初始化.

事件对象包含以下属性:

  • filename: 文件的名称.

Event: beforeParse

解析开始之前会触发 beforeParse 事件. 插件可以使用此方法修改将要解析的源代码. 例如, 您的插件可以添加JSDoc注释, 或者它可以删除非有效JavaScript的预处理标记.

事件对象包含以下属性:

  • filename: 文件的名称.

  • source: 文件的内容.

下面是一个示例, 它将函数的虚拟注释添加到源, 以便将其解析并添加到文档中. 这可以用于记录可供用户使用的方法, 但可能不会出现在所记录的源代码中, 例如外部超类提供的方法:

示例
exports.handlers = {
    beforeParse: function(e) {
        var extraDoc = [
            '/**',
            ' * Function provided by a superclass.',
            ' * @name superFunc',
            ' * @memberof ui.mywidget',
            ' * @function',
            ' */'
        ];
        e.source += extraDoc.join('\n');
    }
};

Event: jsdocCommentFound

只要找到JSDoc注释, 就会触发 jsdocCommentFound 事件. 评论可能与任何代码相关, 也可能不相关. 您可以使用此事件在处理注释之前修改注释的内容.

事件对象包含以下属性:

  • filename: 文件的名称.

  • comment: JSDoc评论的文本.

  • lineno: 找到评论的行号.

  • columnno: 找到评论的列号. 可在JSDoc 3.5.0及更高版本中使用.

Event: symbolFound

当解析器遇到可能需要记录的代码中的符号时, 会触发 symbolFound 事件. 例如, 解析器为源文件中的每个变量, 函数和对象文字触发 symbolFound 事件.

事件对象包含以下属性:

  • filename: 文件的名称.

  • comment: 与符号关联的注释文本(如果有).

  • id: 符号的唯一ID.

  • lineno: 找到符号的行号.

  • columnno: 找到符号的列号. 可在JSDoc 3.5.0及更高版本中使用.

  • range: 一个数组, 包含源文件中与该符号关联的第一个和最后一个字符的数字索引.

  • astnode: 抽象语法树中的符号节点.

  • code: 包含代码详细信息的对象. 该对象通常包含 name, typenode 属性. 对象可能还有 value, paramnamesfuncscope 属性, 具体取决于符号.

Event: newDoclet

newDoclet 事件是最高级别的事件. 创建新doclet时会触发它. 这意味着已经处理了JSDoc注释或符号, 并且已经创建了将传递给模板的实际doclet.

事件对象包含以下属性:

  • doclet: 创建的新doclet.

doclet的属性可以根据doclet表示的注释或符号而有所不同. 您可能会看到的一些常见属性包括:

  • comment: JSDoc注释的文本, 如果符号未记录, 则为空字符串.

  • meta: 描述doclet如何与源文件相关的对象(例如, 源文件中的位置).

  • description: 正在记录的符号的描述.

  • kind: 记录的符号类型(例如, classfunction).

  • name: 符号的简称(例如, myMethod).

  • longname: 完全限定名称, 包括成员信息(例如, MyClass #myMethod).

  • memberof: 此符号所属的模块, 命名空间或类(例如, MyClass), 如果符号没有父符号, 则为空字符串.

  • scope: 符号在其父级中的范围(例如, global, static, instanceinner).

  • undocumented: 如果符号没有JSDoc注释, 则设置为 true.

  • defaultvalue: 符号的默认值.

  • type: 包含有关符号类型的详细信息的对象.

  • params: 包含函数参数列表的对象.

  • tags: 包含JSDoc无法识别的标签列表的对象. 只有在JSDoc的配置文件中将 allowUnknownTags 设置为 true 时才可用.

To see the doclets that JSDoc generates for your code, run JSDoc with the -X JSDoc的命令行参数.

下面是一个 newDoclet 处理程序的示例, 该处理程序会对描述进行大喊:

示例
exports.handlers = {
    newDoclet: function(e) {
        // e.doclet will refer to the newly created doclet
        // you can read and modify properties of that doclet if you wish
        if (typeof e.doclet.description === 'string') {
            e.doclet.description = e.doclet.description.toUpperCase();
        }
    }
};

Event: fileComplete

解析器完成解析文件后会触发 fileComplete 事件. 您的插件可以使用此事件来触发每个文件的清理.

事件对象包含以下属性:

  • filename: 文件的名称.

  • source: 文件的内容.

Event: parseComplete

在JSDoc解析了所有指定的源文件之后, 会触发 parseComplete 事件.

Note: 此事件在JSDoc 3.2及更高版本中触发.

事件对象包含以下属性:

  • sourcefiles: 解析源文件的路径数组.

  • doclets: 一组 doclet 对象. 有关每个doclet可以包含的属性的详细信息, 请参阅 newDoclet 事件. 可在JSDoc 3.2.1及更高版本中使用.

Event: processingComplete

在JSDoc更新解析结果以反映继承和借用符号之后, 将触发 processingComplete 事件.

Note: 此事件在JSDoc 3.2.1及更高版本中触发.

事件对象包含以下属性:

  • doclets: An array of doclet objects. See the newDoclet event for details about the properties that each doclet can contain.

标签定义

向标记字典添加标记是影响文档生成的中级方法. 在触发 newDoclet 事件之前, 解析JSDoc注释块以确定描述和可能存在的任何JSDoc标记. 找到标记后, 如果已在标记字典中定义了标记, 则有机会修改doclet.

插件可以通过导出 defineTags 函数来定义标签. 该函数将传递一个字典, 可用于定义标签, 如此:

示例
exports.defineTags = function(dictionary) {
    // define tags here
};

词典

该词典提供以下方法:

  • defineTag(title, opts): 用于定义标签. 第一个参数是标记的名称(例如, paramoverview). 第二个是包含标记选项的对象. 您可以包含以下任何选项;每个选项的默认值是 false:

    • canHaveType (boolean): 如果标记文本可以包含类型表达式(例如 @param {string} name - Description 中的 {string}, 则设置为 true.

    • canHaveName (boolean): 如果标签文本可以包含名称(例如 @param {string} name - Description 中的 name), 则设置为 true.

    • isNamespace (boolean): Set to true if the tag should be applied to the doclet’s longname as a namespace. For example, the @module tag sets this option to true, and using the tag @module myModuleName results in the longname module:myModuleName.

    • mustHaveValue (boolean): 如果标记必须具有值(例如 @name TheName 中的 TheName), 则设置为 true.

    • mustNotHaveDescription (boolean): 如果标签可能有值但是必须没有描述(例如 @tag {typeExpr} TheDescription 中的 TheDescription), 则设置为 true.

    • mustNotHaveValue (boolean): 如果标记必须没有值, 则设置为 true.

    • onTagged (function): 找到标记时执行的回调函数. 该函数传递两个参数: doclet和标记对象.

  • lookUp(tagName): 按名称检索标记对象. 返回标记对象, 包括其选项, 如果未定义标记, 则返回 false.

  • isNamespace(tagName): 如果标记作为命名空间应用于doclet的longname, 则返回 true.

  • normalise(tagName): Returns the canonical name of a tag. For example, the @const tag is a synonym for @constant; as a result, if you call normalise('const'), it returns the string constant.

  • normalize(tagName): normalise 的同义词. 可在JSDoc 3.3.0及更高版本中使用.

标签的 onTagged 回调可以修改doclet或标签的内容.

Defining an onTagged callback
dictionary.defineTag('instance', {
    onTagged: function(doclet, tag) {
        doclet.scope = "instance";
    }
});

defineTag 方法返回一个 Tag 对象, 它有一个 synonym 方法, 可以用来声明标签的同义词.

Defining a tag synonym
dictionary.defineTag('exception', { /* options for exception tag */ })
    .synonym('throws');

节点访客

在最低级别, 插件作者可以通过定义将访问每个节点的节点访问者来处理抽象语法树(AST)中的每个节点. 通过使用node-visitor插件, 您可以修改注释并触发任意代码段的解析器事件.

插件可以通过导出包含 visitNode 函数的 astNodeVisitor 对象来定义节点访问者, 就像这样:

示例
exports.astNodeVisitor = {
    visitNode: function(node, e, parser, currentSourceName) {
        // do all sorts of crazy things here
    }
};

使用以下参数在每个节点上调用该函数:

  • node: The AST node. AST nodes are JavaScript objects that use the format defined by the ESTree spec. You can use AST Explorer to see the AST that will be created for your source code. As of version 3.5.0, JSDoc uses the current version of the Babylon parser with all plugins enabled.

  • e: 事件. 如果节点是解析器处理的节点, 则事件对象将已经填充了上面 symbolFound 事件中描述的相同内容. 否则, 它将是一个空对象, 可在其上设置各种属性.

  • parser: JSDoc解析器实例.

  • currentSourceName: 要解析的文件的名称.

让事情发生

实现节点访问者的主要原因是能够记录通常未记录的内容(如创建类的函数调用)或自动生成未记录的代码的文档. 例如, 插件可能会查找对 _trigger 方法的调用, 因为它知道这意味着事件被触发, 然后生成事件的文档.

为了使事情发生, visitNode 函数应该修改event参数的属性. 一般来说, 目标是构建注释然后获取要触发的事件. 解析器允许所有节点访问者查看节点后, 它会查看事件对象是否具有 comment 属性和 event 属性. 如果两者都有, 则触发事件属性中指定的事件. 事件通常是 symbolFoundjsdocCommentFound , 但理论上, 插件可以定义自己的事件并处理它们.

与事件处理程序插件一样, node-visitor插件可以通过在事件对象(e.stopPropagation = true)上设置 stopPropagation 属性来阻止以后的插件运行. 插件可以通过设置 preventDefault 属性(e.preventDefault = true)来停止触发事件.

报告错误

如果您的插件需要报告错误, 请在 jsdoc/util/logger 模块中使用以下方法之一:

  • logger.warn: 警告用户可能出现的问题.

  • logger.error: 报告插件可以恢复的错误.

  • logger.fatal: 报告应该导致JSDoc停止运行的错误.

使用这些方法可以创建比简单地抛出错误更好的用户体验.

注意: 不要使用 jsdoc/util/error 模块来报告错误. 此模块已弃用, 将在JSDoc的未来版本中删除.

Reporting a non-fatal error
var logger = require('jsdoc/util/logger');

exports.handlers = {
    newDoclet: function(e) {
        // Your code here.

        if (somethingBadHappened) {
            logger.error('Oh, no, something bad happened!');
        }
    }
};