forked from jsdoc/jsdoc.github.io
-
Notifications
You must be signed in to change notification settings - Fork 0
/
about-plugins.html
382 lines (377 loc) · 22 KB
/
about-plugins.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
<!DOCTYPE html>
<!-- THIS IS A GENERATED FILE. DO NOT EDIT. -->
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="description" content="How to create and use JSDoc plugins.">
<title>Use JSDoc: About JSDoc plugins</title>
<link rel="stylesheet" href="styles/usejsdoc.css">
<link rel="stylesheet" href="styles/prettify.css">
<link rel="stylesheet" href="styles/css3-github-ribbon.css">
<script src="scripts/prettify.js"></script>
</head>
<body>
<header>
<a href="./index.html">@use JSDoc</a>
</header>
<article>
<h1>About JSDoc plugins</h1>
<h2>Table of Contents</h2>
<ul>
<li>
<a href="#creating-and-enabling-a-plugin">Creating and Enabling a Plugin</a>
</li>
<li>
<a href="#authoring-jsdoc-3-plugins">Authoring JSDoc 3 Plugins</a>
<ul>
<li>
<a href="#event-handlers">Event Handlers</a>
</li>
<li>
<a href="#tag-definitions">Tag Definitions</a>
</li>
<li>
<a href="#node-visitors">Node Visitors</a>
</li>
</ul>
</li>
<li>
<a href="#reporting-errors">Reporting Errors</a>
</li>
</ul>
<h2 id="creating-and-enabling-a-plugin">Creating and Enabling a Plugin</h2>
<p>There are two steps required to create and enable a new JSDoc plugin:</p>
<ol>
<li>Create a JavaScript module to contain your plugin code.</li>
<li>Include that module in the <code>plugins</code> array of <a href="about-configuring-jsdoc.html">JSDoc's configuration file</a>. You can
specify an absolute or relative path. If you use a relative path, JSDoc searches for the plugin in
the current working directory; the directory where the configuration file is located; and the JSDoc
directory, in that order.</li>
</ol>
<p>For example, if your plugin is defined in the <code>plugins/shout.js</code> file in the current working
directory, you would add the string <code>plugins/shout</code> to the <code>plugins</code> array in your JSDoc
configuration file:</p>
<figure>
<figcaption>Adding a plugin to JSDoc's configuration file</figcaption>
<pre class="prettyprint lang-json"><code>{
"plugins": ["plugins/shout"]
}
</code></pre>
</figure>
<p>JSDoc executes plugins in the order that they are listed in the configuration file.</p>
<h2 id="authoring-jsdoc-3-plugins">Authoring JSDoc 3 Plugins</h2>
<p>JSDoc 3's plugin system offers extensive control over the parsing process. A plugin can affect the
parse results by doing any of the following:</p>
<ul>
<li>Defining event handlers</li>
<li>Defining tags</li>
<li>Defining a visitor for abstract syntax tree nodes</li>
</ul>
<h3 id="event-handlers">Event Handlers</h3>
<p>At the highest level, a plugin may register handlers for specific named events that JSDoc fires.
JSDoc will pass an event object to the handler. Your plugin module should export a <code>handlers</code> object
that contains your handler, like so:</p>
<figure>
<figcaption>Event-handler plugin for 'newDoclet' events</figcaption>
<pre class="prettyprint lang-js"><code>exports.handlers = {
newDoclet: function(e) {
// Do something when we see a new doclet
}
};
</code></pre>
</figure>
<p>JSDoc fires events in the same order as the underlying code.</p>
<p>An event-handler plugin can stop later plugins from running by setting a <code>stopPropagation</code> property
on the event object (<code>e.stopPropagation = true</code>). A plugin can stop the event from firing by setting
a <code>preventDefault</code> property (<code>e.preventDefault = true</code>).</p>
<h4 id="event-parsebegin">Event: parseBegin</h4>
<p>The <code>parseBegin</code> event is fired before JSDoc starts loading and parsing the source files. Your
plugin can control which files JSDoc will parse by modifying the event's contents.</p>
<p><strong>Note</strong>: This event is fired in JSDoc 3.2 and later.</p>
<p>The event object contains the following properties:</p>
<ul>
<li><code>sourcefiles</code>: An array of paths to source files that will be parsed.</li>
</ul>
<h4 id="event-filebegin">Event: fileBegin</h4>
<p>The <code>fileBegin</code> event is fired when the parser is about to parse a file. Your plugin can use this
event to trigger per-file initialization if necessary.</p>
<p>The event object contains the following properties:</p>
<ul>
<li><code>filename</code>: The name of the file.</li>
</ul>
<h4 id="event-beforeparse">Event: beforeParse</h4>
<p>The <code>beforeParse</code> event is fired before parsing has begun. Plugins can use this method to modify the
source code that will be parsed. For instance, your plugin could add a JSDoc comment, or it could
remove preprocessing tags that are not valid JavaScript.</p>
<p>The event object contains the following properties:</p>
<ul>
<li><code>filename</code>: The name of the file.</li>
<li><code>source</code>: The contents of the file.</li>
</ul>
<p>Below is an example that adds a virtual comment for a function to the source so that it will get
parsed and added to the documentation. This might be done to document methods that will be available
to users, but might not appear in the source code being documented, such as methods provided by an
external superclass:</p>
<figure>
<figcaption>Example</figcaption>
<pre class="prettyprint lang-js"><code>exports.handlers = {
beforeParse: function(e) {
var extraDoc = [
'/**',
' * Function provided by a superclass.',
' * @name superFunc',
' * @memberof ui.mywidget',
' * @function',
' */'
];
e.source += extraDoc.join('\n');
}
};
</code></pre>
</figure>
<h4 id="event-jsdoccommentfound">Event: jsdocCommentFound</h4>
<p>The <code>jsdocCommentFound</code> event is fired whenever a JSDoc comment is found. The comment may or may not
be associated with any code. You might use this event to modify the contents of a comment before it
is processed.</p>
<p>The event object contains the following properties:</p>
<ul>
<li><code>filename</code>: The name of the file.</li>
<li><code>comment</code>: The text of the JSDoc comment.</li>
<li><code>lineno</code>: The line number on which the comment was found.</li>
<li><code>columnno</code>: The column number on which the comment was found. Available in JSDoc 3.5.0 and later.</li>
</ul>
<h4 id="event-symbolfound">Event: symbolFound</h4>
<p>The <code>symbolFound</code> event is fired when the parser comes across a symbol in the code that may need to
be documented. For example, the parser fires a <code>symbolFound</code> event for each variable, function, and
object literal in a source file.</p>
<p>The event object contains the following properties:</p>
<ul>
<li><code>filename</code>: The name of the file.</li>
<li><code>comment</code>: The text of the comment associated with the symbol, if any.</li>
<li><code>id</code>: The unique ID of the symbol.</li>
<li><code>lineno</code>: The line number on which the symbol was found.</li>
<li><code>columnno</code>: The column number on which the symbol was found. Available in JSDoc 3.5.0 and later.</li>
<li><code>range</code>: An array containing the numeric index of the first and last characters in the source file
that are associated with the symbol.</li>
<li><code>astnode</code>: The symbol's node from the abstract syntax tree.</li>
<li><code>code</code>: Object with detailed information about the code. This object usually contains <code>name</code>,
<code>type</code>, and <code>node</code> properties. The object might also have <code>value</code>, <code>paramnames</code>, or <code>funcscope</code>
properties depending on the symbol.</li>
</ul>
<h4 id="event-newdoclet">Event: newDoclet</h4>
<p>The <code>newDoclet</code> event is the highest-level event. It is fired when a new doclet has been created.
This means that a JSDoc comment or a symbol has been processed, and the actual doclet that will be
passed to the template has been created.</p>
<p>The event object contains the following properties:</p>
<ul>
<li><code>doclet</code>: The new doclet that was created.</li>
</ul>
<p>The doclet's properties can vary depending on the comment or symbol that the doclet represents. Some
common properties you're likely to see include:</p>
<ul>
<li><code>comment</code>: The text of the JSDoc comment, or an empty string if the symbol is undocumented.</li>
<li><code>meta</code>: Object that describes how the doclet relates to the source file (for example, the location
within the source file).</li>
<li><code>description</code>: A description of the symbol being documented.</li>
<li><code>kind</code>: The kind of symbol being documented (for example, <code>class</code> or <code>function</code>).</li>
<li><code>name</code>: The short name for the symbol (for example, <code>myMethod</code>).</li>
<li><code>longname</code>: The fully qualified name, including memberof info (for example, <code>MyClass#myMethod</code>).</li>
<li><code>memberof</code>: The module, namespace, or class that this symbol belongs to (for example, <code>MyClass</code>),
or an empty string if the symbol does not have a parent.</li>
<li><code>scope</code>: The scope of the symbol within its parent (for example, <code>global</code>, <code>static</code>, <code>instance</code>,
or <code>inner</code>).</li>
<li><code>undocumented</code>: Set to <code>true</code> if the symbol did not have a JSDoc comment.</li>
<li><code>defaultvalue</code>: The default value for a symbol.</li>
<li><code>type</code>: Object containing details about the symbol's type.</li>
<li><code>params</code>: Object containing the list of parameters to a function.</li>
<li><code>tags</code>: Object containing a list of tags that JSDoc did not recognize. Only available if
<code>allowUnknownTags</code> is set to <code>true</code> in JSDoc's configuration file.</li>
</ul>
<p>To see the doclets that JSDoc generates for your code, run JSDoc with the <a href="about-commandline.html"><code>-X</code> command-line
option</a>.</p>
<p>Below is an example of a <code>newDoclet</code> handler that shouts the descriptions:</p>
<figure>
<figcaption>Example</figcaption>
<pre class="prettyprint lang-js"><code>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();
}
}
};
</code></pre>
</figure>
<h4 id="event-filecomplete">Event: fileComplete</h4>
<p>The <code>fileComplete</code> event is fired when the parser has finished parsing a file. Your plugin could use
this event to trigger per-file cleanup.</p>
<p>The event object contains the following properties:</p>
<ul>
<li><code>filename</code>: The name of the file.</li>
<li><code>source</code>: The contents of the file.</li>
</ul>
<h4 id="event-parsecomplete">Event: parseComplete</h4>
<p>The <code>parseComplete</code> event is fired after JSDoc has parsed all of the specified source files.</p>
<p><strong>Note</strong>: This event is fired in JSDoc 3.2 and later.</p>
<p>The event object contains the following properties:</p>
<ul>
<li><code>sourcefiles</code>: An array of paths to source files that were parsed.</li>
<li><code>doclets</code>: An array of doclet objects. See the <a href="#event-newdoclet"><code>newDoclet</code> event</a> for details
about the properties that each doclet can contain. Available in JSDoc 3.2.1 and later.</li>
</ul>
<h4 id="event-processingcomplete">Event: processingComplete</h4>
<p>The <code>processingComplete</code> event is fired after JSDoc updates the parse results to reflect inherited
and borrowed symbols.</p>
<p><strong>Note</strong>: This event is fired in JSDoc 3.2.1 and later.</p>
<p>The event object contains the following properties:</p>
<ul>
<li><code>doclets</code>: An array of doclet objects. See the <a href="#event-newdoclet"><code>newDoclet</code> event</a> for details
about the properties that each doclet can contain.</li>
</ul>
<h3 id="tag-definitions">Tag Definitions</h3>
<p>Adding tags to the tag dictionary is a mid-level way to affect documentation generation. Before a
<code>newDoclet</code> event is triggered, JSDoc comment blocks are parsed to determine the description and any
JSDoc tags that may be present. When a tag is found, if it has been defined in the tag dictionary,
it is given a chance to modify the doclet.</p>
<p>Plugins can define tags by exporting a <code>defineTags</code> function. That function will be passed a
dictionary that can be used to define tags, like so:</p>
<figure>
<figcaption>Example</figcaption>
<pre class="prettyprint lang-js"><code>exports.defineTags = function(dictionary) {
// define tags here
};
</code></pre>
</figure>
<h4 id="the-dictionary">The Dictionary</h4>
<p>The dictionary provides the following methods:</p>
<ul>
<li><code>defineTag(title, opts)</code>: Used to define tags. The first parameter is the name of the tag (for
example, <code>param</code> or <code>overview</code>). The second is an object containing options for the tag. You can
include any of the following options; the default value for each option is <code>false</code>:<ul>
<li><code>canHaveType (boolean)</code>: Set to <code>true</code> if the tag text can include a type expression (such as
<code>{string}</code> in <code>@param {string} name - Description</code>).</li>
<li><code>canHaveName (boolean)</code>: Set to <code>true</code> if the tag text can include a name (such as <code>name</code> in
<code>@param {string} name - Description</code>).</li>
<li><code>isNamespace (boolean)</code>: Set to <code>true</code> if the tag should be applied to the doclet's longname
as a namespace. For example, the <code>@module</code> tag sets this option to <code>true</code>, and using the tag
<code>@module myModuleName</code> results in the longname <code>module:myModuleName</code>.</li>
<li><code>mustHaveValue (boolean)</code>: Set to <code>true</code> if the tag must have a value (such as <code>TheName</code> in
<code>@name TheName</code>).</li>
<li><code>mustNotHaveDescription (boolean)</code>: Set to <code>true</code> if the tag may have a value but must not
have a description (such as <code>TheDescription</code> in <code>@tag {typeExpr} TheDescription</code>).</li>
<li><code>mustNotHaveValue (boolean)</code>: Set to <code>true</code> if the tag must not have a value.</li>
<li><code>onTagged (function)</code>: A callback function executed when the tag is found. The function is
passed two parameters: the doclet and the tag object.</li>
</ul>
</li>
<li><code>lookUp(tagName)</code>: Retrieve a tag object by name. Returns the tag object, including its options,
or <code>false</code> if the tag is not defined.</li>
<li><code>isNamespace(tagName)</code>: Returns <code>true</code> if the tag is applied to a doclet's longname as a
namespace.</li>
<li><code>normalise(tagName)</code>: Returns the canonical name of a tag. For example, the <code>@const</code> tag is a
synonym for <code>@constant</code>; as a result, if you call <code>normalise('const')</code>, it returns the string
<code>constant</code>.</li>
<li><code>normalize(tagName)</code>: Synonym for <code>normalise</code>. Available in JSDoc 3.3.0 and later.</li>
</ul>
<p>A tag's <code>onTagged</code> callback can modify the contents of the doclet or tag.</p>
<figure>
<figcaption>Defining an onTagged callback</figcaption>
<pre class="prettyprint lang-js"><code>dictionary.defineTag('instance', {
onTagged: function(doclet, tag) {
doclet.scope = "instance";
}
});
</code></pre>
</figure>
<p>The <code>defineTag</code> method returns a <code>Tag</code> object, which has a <code>synonym</code> method that can be used to
declare a synonym for the tag.</p>
<figure>
<figcaption>Defining a tag synonym</figcaption>
<pre class="prettyprint lang-js"><code>dictionary.defineTag('exception', { /* options for exception tag */ })
.synonym('throws');
</code></pre>
</figure>
<h3 id="node-visitors">Node Visitors</h3>
<p>At the lowest level, plugin authors can process each node in the abstract syntax tree (AST) by
defining a node visitor that will visit each node. By using a node-visitor plugin, you can modify
comments and trigger parser events for any arbitrary piece of code.</p>
<p>Plugins can define a node visitor by exporting an <code>astNodeVisitor</code> object that contains a
<code>visitNode</code> function, like so:</p>
<figure>
<figcaption>Example</figcaption>
<pre class="prettyprint lang-js"><code>exports.astNodeVisitor = {
visitNode: function(node, e, parser, currentSourceName) {
// do all sorts of crazy things here
}
};
</code></pre>
</figure>
<p>The function is called on each node with the following parameters:</p>
<ul>
<li><code>node</code>: The AST node. AST nodes are JavaScript objects that use the format defined by the <a href="https://github.com/estree/estree">ESTree
spec</a>. You can use <a href="https://astexplorer.net/">AST Explorer</a> 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 <a href="https://github.com/babel/babylon">Babylon</a> parser
with all plugins enabled.</li>
<li><code>e</code>: The event. If the node is one that the parser handles, the event object will already be
populated with the same things described in the <code>symbolFound</code> event above. Otherwise, it will be an
empty object on which to set various properties.</li>
<li><code>parser</code>: The JSDoc parser instance.</li>
<li><code>currentSourceName</code>: The name of the file being parsed.</li>
</ul>
<h4 id="making-things-happen">Making things happen</h4>
<p>The primary reasons to implement a node visitor are to be able to document things that aren't
normally documented (like function calls that create classes) or to auto generate documentation for
code that isn't documented. For instance, a plugin might look for calls to a <code>_trigger</code> method since
it knows that means an event is fired and then generate documentation for the event.</p>
<p>To make things happen, the <code>visitNode</code> function should modify properties of the event parameter. In
general the goal is to construct a comment and then get an event to fire. After the parser lets all
of the node visitors have a look at the node, it looks to see if the event object has a <code>comment</code>
property and an <code>event</code> property. If it has both, the event named in the event property is fired.
The event is usually <code>symbolFound</code> or <code>jsdocCommentFound</code>, but theoretically, a plugin could define
its own events and handle them.</p>
<p>As with event-handler plugins, a node-visitor plugin can stop later plugins from running by setting
a <code>stopPropagation</code> property on the event object (<code>e.stopPropagation = true</code>). A plugin can stop the
event from firing by setting a <code>preventDefault</code> property (<code>e.preventDefault = true</code>).</p>
<h2 id="reporting-errors">Reporting Errors</h2>
<p>If your plugin needs to report an error, use one of the following methods in the <code>jsdoc/util/logger</code>
module:</p>
<ul>
<li><code>logger.warn</code>: Warn the user about a possible problem.</li>
<li><code>logger.error</code>: Report an error from which the plugin can recover.</li>
<li><code>logger.fatal</code>: Report an error that should cause JSDoc to stop running.</li>
</ul>
<p>Using these methods creates a better user experience than simply throwing an error.</p>
<p><strong>Note</strong>: Do not use the <code>jsdoc/util/error</code> module to report errors. This module is deprecated and
will be removed in a future version of JSDoc.</p>
<figure>
<figcaption>Reporting a non-fatal error</figcaption>
<pre class="prettyprint lang-js"><code>var logger = require('jsdoc/util/logger');
exports.handlers = {
newDoclet: function(e) {
// Your code here.
if (somethingBadHappened) {
logger.error('Oh, no, something bad happened!');
}
}
};
</code></pre>
</figure>
</article>
<footer>
<a class="license-badge" href="http://creativecommons.org/licenses/by-sa/3.0/">
<img alt="Creative Commons License" class="license-badge" src="images/cc-by-sa.svg" width="80" height="15" /></a>
<br>
Copyright © 2011-2017 the
<a href="https://github.com/jsdoc3/jsdoc3.github.com/contributors">contributors</a> to the
JSDoc 3 documentation project.
<br>
This website is <a href="https://github.com/jsdoc3/jsdoc3.github.com">open source</a> and is
licensed under the <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/">
Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.
</footer>
<script type="text/javascript">
prettyPrint();
</script>
</body>
</html>