@use JSDoc

About JSDoc plugins

Creating and Enabling a Plugin

There are two steps required to create and enable a new JSDoc plugin:

  1. Create a JavaScript module to contain your plugin code.
  2. Include that module in the plugins array of JSDoc's configuration file. 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.

For example, if your plugin is defined in the plugins/shout.js file in the current working directory, you would add the string plugins/shout to the plugins array in your JSDoc configuration file:

Adding a plugin to JSDoc's configuration file
{
    "plugins": ["plugins/shout"]
}

JSDoc executes plugins in the order that they are listed in the configuration file.

Authoring JSDoc 3 Plugins

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:

Event Handlers

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 handlers object that contains your handler, like so:

Event-handler plugin for 'newDoclet' events
exports.handlers = {
    newDoclet: function(e) {
        // Do something when we see a new doclet
    }
};

JSDoc fires events in the same order as the underlying code.

An event-handler plugin can stop later plugins from running by setting a stopPropagation property on the event object (e.stopPropagation = true). A plugin can stop the event from firing by setting a preventDefault property (e.preventDefault = true).

Event: parseBegin

The parseBegin 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.

Note: This event is fired in JSDoc 3.2 and later.

The event object contains the following properties:

Event: fileBegin

The fileBegin 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.

The event object contains the following properties:

Event: beforeParse

The beforeParse 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.

The event object contains the following properties:

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:

Example
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

The jsdocCommentFound 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.

The event object contains the following properties:

Event: symbolFound

The symbolFound 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 symbolFound event for each variable, function, and object literal in a source file.

The event object contains the following properties:

Event: newDoclet

The newDoclet 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.

The event object contains the following properties:

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:

To see the doclets that JSDoc generates for your code, run JSDoc with the -X command-line option.

Below is an example of a newDoclet handler that shouts the descriptions:

Example
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

The fileComplete event is fired when the parser has finished parsing a file. Your plugin could use this event to trigger per-file cleanup.

The event object contains the following properties:

Event: parseComplete

The parseComplete event is fired after JSDoc has parsed all of the specified source files.

Note: This event is fired in JSDoc 3.2 and later.

The event object contains the following properties:

Event: processingComplete

The processingComplete event is fired after JSDoc updates the parse results to reflect inherited and borrowed symbols.

Note: This event is fired in JSDoc 3.2.1 and later.

The event object contains the following properties:

Tag Definitions

Adding tags to the tag dictionary is a mid-level way to affect documentation generation. Before a newDoclet 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.

Plugins can define tags by exporting a defineTags function. That function will be passed a dictionary that can be used to define tags, like so:

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

The Dictionary

The dictionary provides the following methods:

A tag's onTagged callback can modify the contents of the doclet or tag.

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

The defineTag method returns a Tag object, which has a synonym method that can be used to declare a synonym for the tag.

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

Node Visitors

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.

Plugins can define a node visitor by exporting an astNodeVisitor object that contains a visitNode function, like so:

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

The function is called on each node with the following parameters:

Making things happen

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 _trigger method since it knows that means an event is fired and then generate documentation for the event.

To make things happen, the visitNode 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 comment property and an event property. If it has both, the event named in the event property is fired. The event is usually symbolFound or jsdocCommentFound, but theoretically, a plugin could define its own events and handle them.

As with event-handler plugins, a node-visitor plugin can stop later plugins from running by setting a stopPropagation property on the event object (e.stopPropagation = true). A plugin can stop the event from firing by setting a preventDefault property (e.preventDefault = true).

Reporting Errors

If your plugin needs to report an error, use one of the following methods in the jsdoc/util/logger module:

Using these methods creates a better user experience than simply throwing an error.

Note: Do not use the jsdoc/util/error module to report errors. This module is deprecated and will be removed in a future version of 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!');
        }
    }
};