JSDoc

Using JSDoc

JSDoc

by John Vincent


Posted on July 1, 2017


The de facto standard for documenting Javascript code.

This stuff ends up sprayed everywhere, so let's create a reference document.

JSDoc

Use JSDoc

Installation and Usage

npm install jsdoc --save-dev

To JSDoc a single file

./node_modules/.bin/jsdoc myJavaScriptFile.js

JSDoc Configuration

My standard JSDoc configuration file

root/jsdoc.json

{
    "tags": {
        "allowUnknownTags": true,
        "dictionaries": ["jsdoc","closure"]
    },
    "source": {
        "include": [ "server.js", "config/", "api/", "public/assets/js", "test/", "scripts/" ],
        "exclude": [ "node_modules" ],
        "includePattern": ".+\\.js(doc|x)?$",
        "excludePattern": "(^|\\/|\\\\)_"
    },
    "plugins": [],
    "templates": {
        "cleverLinks": false,
        "monospaceLinks": false,
        "default": {
            "includeDate": false,
            "outputSourceFiles": true
        }
    },
    "opts": {
        "template": "templates/default",  // same as -t templates/default
        "encoding": "utf8",               // same as -e utf8
        "destination": "./jsdoc/",          // same as -d ./out/
        "recurse": true                  // same as -r
        // "tutorials": "path/to/tutorials" // same as -u path/to/tutorials
    }
}

Notice

  • "source":"include" is an array of directories.
  • "recurse": true will cause JSDoc to look for all .js files within those folders.
  • "includeDate": false else every time you run JSDoc, all files will be changed, a real pain for git.

Note

  • If using jsdoc.json, command line arguments do not work.
  • Sometimes JSDoc runs but does nothing and says nothing about trouble.

The following options are useful for watching JSDoc

"opts": {
    "verbose": true,
    "debug": true
}

Run JSDoc

./node_modules/.bin/jsdoc -c ./jsdoc.json

To execute

npm run jsdoc

package.json

Adding JSDoc as a script, for example

"scripts": {
	"start": "nodemon server.js",
	"test": "mocha ./test",
	"jsdoc": "./node_modules/.bin/jsdoc -c ./jsdoc.json"
}

To run JSDoc

npm run jsdoc

Viewing JSDoc

In project-root/jsdoc.json, notice

"destination": "./jsdoc/"

In browser, open file ./jsdoc/index.html

Example JSDoc

Let's attempt to make some rules

class

/**
 * Utility methods to handle tasks related to the Users object.
 * @class UserUtils
 * @requires SubscriptionUtils
 */
class UserUtils {

exports.module

At the top

  • list the module name
  • list required modules
/**
 * Handle tasks related to the RSS feeds
 *
 * @module rssController
 * @requires SubscriptionModel
 * @requires RssFeeder
 * @requires RssUtils
 */

For each require. Sometimes these do not work.

/**
* @const SubscriptionModel
* @description Mongoose Model of a Mongo collection Subscription
*/
const {SubscriptionModel} = require('../subscription/subscription.model');

or

/**
* @const EmailUtils
* @description Various methods for formatting and sending emails.
*/
const EmailUtils = require('../../config/email');
/** Module for getting a RSS Feed */
const RssFeeder = require('./rss.feeder');

method

It may be necessary to use @method

/**
 * Returns user object for the passed username.
 *
 * @method update_all
 * @param {String} username - username to find
 * @param {Array} _users - all users
 * @return {object} - user object if found, else undefined.
 * @throws {Error} if arguments are not defined
 */
    getUserFromUsers(username, _users) {
        if (username && _users && _users.length) {
            return _users.find(item => username === item.username);
        }
        throw Error('Exception in UserUtils::getUserFromUsers');
    }

Note

@method update_all
@param {String} - always provide object type
@return {object} - always provide object type
@throws {Error} if arguments are not defined

Mongoose Model

/**
 * Handle Mongoose tasks related to the Counter collection
 *
 * @module CounterModel
 * @requires mongoose
 */

Router

/**
 * Handle tasks related to routing requests for user subscriptions
 *
 * @module userSubscriptionRouter
 * @requires express
 * @requires userSubscriptionController
 */

Long description

/**
 * Delete an article.
 * <p>Articles are stored in user.saved or user.read, grouped by subscription.</p>
 * <p>The approach used here is to delete duplicates, if they exist.</p>
 * <pre>
 *    '0b' Base 2:   binary 
 *    '0q' Base 4:   quaternary 
 *    '0o' Base 8:   octal
 *    '0x' Base 16:  hexadecimal
 * </pre>
 * Requires one of the following: 
 * <ul style="list-style: none;">
 *  <li> '0b' Base 2:   binary 
 *  <li> '0q' Base 4:   quaternary 
 *  <li> '0o' Base 8:   octal
 *  <li> '0x' Base 16:  hexadecimal
 * </ul>
 * Returns a subscription from the users.subscription array with
 *          <ul><li>users.subscription.url = passed url.</li></ul>
 * Add subscription.channel to all user.subscription[].<br/>
 * Note that user.subscription.subscribed = true;
/**
 * Return the articles not read by the user, grouped by subscription.
 *
 * <p>Note that subscription object for which the user is subscribed, required additional properties:
 * <ul>
 *      <li>subscribed = true</li>
 *      <li>title = channel.title from subscription</li>
 * </ul>
 * </p>
 * <p>Performs the following:
 * <ul>
 * <li>1. Filter each subscription</li>
 * <li>2. Verify user is subscribed to this subscription</li>
 * <li>3. Set subscribed = true</li>
 * <li>4. Set title to User.subscription.title</li>
 * <li>5. Filter all articles in the subscription</li>
 * <li>6. Remove articles that have been read.</li>
 * <li>7. Remove articles that have been saved.</li>
 * <li>8. Remove subscription if there are no remaining articles</li>
 * <li>9. Return the list of subscriptions.
 * </ul>
 * </p>
 *
 * @param {object} user - user
 * @param {object} allSubscriptions - all subscriptions.
 * @return {array} - articles not read by the user, grouped by subscription.
 * @throws {Error} if arguments are not defined
 */