Chapter 18. Documentation

All engineers would rather be writing code than documentation, which is precisely why tools that autogenerate documentation from code are so popular. The trend really began with Javadoc, the tool that automatically creates documentation for Java, and continued into other languages such as JavaScript.

There is a large (and growing) number of documentation generators that work with JavaScript. Some are general-purpose documentation generators that work with any language; others are JavaScript-specific. As with minifiers, the choice of documentation generator is more of a preference than anything else. This chapter covers a few popular choices; there are many more out there. See Appendix B for a full list of alternatives.

JSDoc Toolkit

JSDoc Toolkit is perhaps the most commonly used JavaScript documentation generator. An evolution of the original JSDoc released in 2011, JSDoc Toolkit is used by Google and SproutCore and is often credited with starting the trend of writing JavaScript-specific documentation generators. It uses the same basic syntax as Javadoc, with special multiline comments indicating documentation information. For example:

/**
 * @namespace The main application object.
 */
var MyApplication = {

    /**
     * Adds two numbers together.
     * @param {int} num1 The first number.
     * @param {int} num2 The second number.
     * @returns {int} The sum of the two numbers.
     * @static
     */
    add: function (num1, num2) {
        return num1 + num2;
    }
}

Any object for which there is no constructor to call is considered a namespace in JSDoc. So MyApplication is a namespace and is indicated as such by the @namespace tag followed by the description. The method MyApplication.add() has two parameters, specified by @param and followed by the expected data type, the parameter name, and the description. The method returns a result, so the @return tag indicates the expected data type and describes the return value. The @static tag indicates that the method doesn’t require instantiation of an object to be used.

When JSDoc Toolkit processes JavaScript files, it looks both at the JavaScript code and at the documentation comments to create HTML-based documentation. For full syntax information, see http://code.google.com/p/jsdoc-toolkit/w/list.

JSDoc Toolkit is written almost entirely in JavaScript and uses a custom Rhino launcher JAR file (jsrun.jar) to execute:

java -jar jsrun.jar app/run.js [file]+ -t=[templates] -d=[directory] [options]

The app/run.js file is the main executable for JSDoc toolkit. You can pass in as many JavaScript files as you’d like to document. The -t flag specifies the templates to use (by default, you can use the ones that come with JSDoc Toolkit) and -d specifies the output directory. For example:

java -jar jsrun.jar app/run.js core/core.js -t=templates/jsdoc/ -d=./out

This command creates documentation for core/core.js using the templates in templates/jsdoc/ and outputs the final HTML documentation to the out directory. Because you need to use the JSDoc Toolkit directory several times (for jsrun.jar, app/run.js, and the default templates), it’s best to keep this information in properties, as in the following:

src.dir = ./src
lib.dir = ./lib

jsdoc.dir = ${lib.dir}/jsdoc-toolkit
jsdoc = ${jsdoc.dir}/jsrun.jar
jsdoc.run = ${jsdoc.dir}/app/run.js
jsdoc.templates = ${jsdoc.dir}/templates
jsdoc.output = ./docs

The target for generating documentation is as follows:

<target name="document">       
    <apply executable="java" failonerror="true" parallel="true">
        <fileset dir="${src.dir}" includes="**/*.js" />
        <arg line="-jar"/>
        <arg path="${jsdoc}"/>
        <arg path="${jsdoc.run}" />
        <arg line="-t=${jsdoc.templates}" />
        <arg line="-d=${jsdoc.output}" />
        <srcfile/>
    </apply>
</target>

Because the built files have all comments stripped, the document target generates documentation on the source files instead. Similar to the validate target, the <apply> task has parallel set to "true" so that all of the files are passed on the command line at once. The rest are just <arg> elements specifying the different options. By default, the documentation is generated into a top-level docs directory, but you may want to change that location based on your directory structure.

The Buildr task for JSDoc is <jsdoc> and has a required outputdir attribute. There is also a templates attribute that is optional (if you don’t want to use the default). For example:

<target name="document">       
    <jsdoc outputdir="${jsdoc.output}">
        <fileset dir="${src.dir}" includes="**/*.js" />
    </jsdoc>
</target>

This target functions the same as the previous version but is a bit more obvious about what it’s doing.

YUI Doc

The original version of YUI Doc was written in Python and was used by the YUI library for several years. More recently, a new JavaScript version was created that understands the same syntax. This is the tool that generates the documentation on http://yuilibrary.com. The syntax is very similar to JSDoc, as it is based off of Javadoc-style comments. The biggest difference is that YUI Doc requires you to name your properties and methods in the documentation comment, whereas JSDoc is able to infer the name from looking at the JavaScript code. For example:

/**
 * The main application object.
 * @class MyApplication
 * @static
 */
var MyApplication = {

    /**
     * Adds two numbers together.
     * @param {int} num1 The first number.
     * @param {int} num2 The second number.
     * @returns {int} The sum of the two numbers.
     * @method add
     */
    add: function (num1, num2) {
        return num1 + num2;
    }
}

In YUI Doc terms, MyApplication is a class even though it has no constructor. The class description is the first line, and @class MyApplication identifies the object as a class. Because there is no constructor, the @static tag indicates that MyApplication is an object and all of its methods are accessed statically. The MyApplication.add() method has syntax that’s very similar to JSDoc, with the main difference being the @method tag indicating the method name.

YUI Doc is written in JavaScript and runs on Node.js. It can be installed using npm via:

sudo npm install -g yuidoc

The command line for YUI Doc is simpler than that of JSDoc:

yuidoc [options] [directory]+ -o [directory]

For example:

yuidoc ./src -o ./docs

This command recursively goes through the src directory and parses all JavaScript files it finds. The generated HTML documentation ends up in the docs directory. Even though there are command-line options for YUI Doc, they aren’t necessary in order to get up and running. The properties for YUI Doc are simple:

src.dir = ./src
lib.dir = ./lib

yuidoc = yuidoc
yuidoc.output = ./docs

You may be wondering what the value of having yuidoc = yuidoc is, as it’s redundant. It’s always best to keep application paths as properties, because paths and filenames have a tendency to change over time. Even though these are identical now, there’s no telling if this will remain true in the future. When things change, you want to be able to make a quick change to the properties file rather than going through the build.xml to find where the executable is set.

Because YUI Doc expects one or more directories to be passed in instead of files, the target becomes very simple when there’s just one source directory:

<target name="document">       
    <exec executable="yuidoc" failonerror="true">
        <arg path="${src.dir}"/>
        <arg line="-o" />
        <arg path="${yuidoc.output}"/>
    </exec>
</target>

This target uses <exec> instead of <apply>, because there is only a single directory being passed in. The <exec> task functions similarly to <apply>, except that it doesn’t require a <srcfile> element. The <arg> elements construct the full command line.

The Buildr <yuidoc> task encapsulates this functionality and has two required attributes, inputdir and outputdir, to specify where the JavaScript files are and where the documentation should be generated, respectively. For example:

<target name="document">
    <yuidoc inputdir="${src.dir}" outputdir="${yuidoc.output}"/>
</target>

The <yuidoc> task assumes that you have YUI Doc installed already.