关于JSDoc插件¶
创建和启用插件¶
创建和启用新的JSDoc插件需要两个步骤:
创建一个JavaScript模块以包含您的插件代码.
将该模块包含在
plugins
数组中 configured-jsdoc. 您可以指定绝对路径或相对路径。如果使用相对路径,JSDoc将在当前工作目录中搜索插件;配置文件所在的目录;和JSDoc目录,按此顺序。
例如, 如果您的插件是在当前工作目录的 plugins/shout.js
文件中定义的, 那么您应该将字符串 plugins/shout
添加到JSDoc配置中的 plugins
数组中文件:
{
"plugins": ["plugins/shout"]
}
JSDoc按照配置文件中列出的顺序执行插件.
关于JSDoc插件¶
JSDoc 3 的插件系统提供了对解析过程的广泛控制. 插件可以通过执行以下任一操作来影响解析结果:
定义事件处理程序
定义标签
为抽象语法树节点定义访问者
事件处理程序¶
在最高级别, 插件可以为JSDoc触发的特定命名事件注册处理程序. JSDoc会将一个事件对象传递给处理程序. 你的插件模块应该导出一个包含你的处理程序的 handlers
对象, 如下所示:
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
,type
和node
属性. 对象可能还有value
,paramnames
或funcscope
属性, 具体取决于符号.
Event: newDoclet¶
newDoclet
事件是最高级别的事件. 创建新doclet时会触发它. 这意味着已经处理了JSDoc注释或符号, 并且已经创建了将传递给模板的实际doclet.
事件对象包含以下属性:
doclet
: 创建的新doclet.
doclet的属性可以根据doclet表示的注释或符号而有所不同. 您可能会看到的一些常见属性包括:
comment
: JSDoc注释的文本, 如果符号未记录, 则为空字符串.meta
: 描述doclet如何与源文件相关的对象(例如, 源文件中的位置).description
: 正在记录的符号的描述.kind
: 记录的符号类型(例如,class
或function
).name
: 符号的简称(例如,myMethod
).longname
: 完全限定名称, 包括成员信息(例如,MyClass #myMethod
).memberof
: 此符号所属的模块, 命名空间或类(例如,MyClass
), 如果符号没有父符号, 则为空字符串.scope
: 符号在其父级中的范围(例如,global
,static
,instance
或inner
).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)
: 用于定义标签. 第一个参数是标记的名称(例如,param
或overview
). 第二个是包含标记选项的对象. 您可以包含以下任何选项;每个选项的默认值是false
:canHaveType (boolean)
: 如果标记文本可以包含类型表达式(例如@param {string} name - Description
中的{string}
, 则设置为true
.canHaveName (boolean)
: 如果标签文本可以包含名称(例如@param {string} name - Description
中的name
), 则设置为true
.isNamespace (boolean)
: Set totrue
if the tag should be applied to the doclet’s longname as a namespace. For example, the@module
tag sets this option totrue
, and using the tag@module myModuleName
results in the longnamemodule: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 callnormalise('const')
, it returns the stringconstant
.normalize(tagName)
:normalise
的同义词. 可在JSDoc 3.3.0及更高版本中使用.
标签的 onTagged
回调可以修改doclet或标签的内容.
dictionary.defineTag('instance', {
onTagged: function(doclet, tag) {
doclet.scope = "instance";
}
});
defineTag
方法返回一个 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
属性. 如果两者都有, 则触发事件属性中指定的事件. 事件通常是 symbolFound
或 jsdocCommentFound
, 但理论上, 插件可以定义自己的事件并处理它们.
与事件处理程序插件一样, node-visitor插件可以通过在事件对象(e.stopPropagation = true
)上设置 stopPropagation
属性来阻止以后的插件运行. 插件可以通过设置 preventDefault
属性(e.preventDefault = true
)来停止触发事件.
报告错误¶
如果您的插件需要报告错误, 请在 jsdoc/util/logger
模块中使用以下方法之一:
logger.warn
: 警告用户可能出现的问题.logger.error
: 报告插件可以恢复的错误.logger.fatal
: 报告应该导致JSDoc停止运行的错误.
使用这些方法可以创建比简单地抛出错误更好的用户体验.
注意: 不要使用 jsdoc/util/error
模块来报告错误. 此模块已弃用, 将在JSDoc的未来版本中删除.
var logger = require('jsdoc/util/logger');
exports.handlers = {
newDoclet: function(e) {
// Your code here.
if (somethingBadHappened) {
logger.error('Oh, no, something bad happened!');
}
}
};