From JsDoc to Github Pages in 27 easy steps (aka API Documentation Considered Evil)?

10:17 PM

I ask the question, because I assume it must be (considered evil)--on the subsequent assumption that if it were not (considered evil) that someone, somewhere, somehow would have made it easy. I had a simple vision: take JsDocs from my project, convert them to an API document, publish that document to my Github pages place.

Impossible is nothing.


The short version:

  1. Document your code using the JsDoc v3 API
    1. Follow this API with religious fervor. It is itself not well-documented. 
    2. The use (or omission) of certain tags can have undocumented side effects. The old JsDoc v2 Toolkit is still valuable as a reference.
    3. JsDoc will emit very few exceptions, other than raw syntax exceptions. You can call the jsdoc NPM directly with the --debug flag to hook into the Rhino debugger, but this didn't help me identify the issues.
    4. I finally stumbled on a post by Simon William, which gave me the clues I needed to find the faults in OJ's documentation.
  2. Install the grunt-jsdoc-plugin. Note: this plugin is a thin wrapper around the jsdoc NPM. Nearly every fault you experience will result from jsdoc, not from the grunt-jsdoc-plugin.
    1. +Eugene Krevenets has a good starter post on how to extend this base task in order to skin the output. This will get you closer to controlling the final skin of your API.
    2. If you use Eugene's steps (which I recommend), there is a gotchya inside the configuration file ".jsdocrc". The path of the plugins you specify will use either a relative or an absolute path, which as implemented is actually the worst of both worlds.
  3. Configure your grunt-jsdoc task to use DocStrap for theming. This is a set of Boostrap themes configured to work on jsdoc output.
    1. I have not found a grunt task to automate this, so opted simply to copy the DocStrap project into a folder of my own project and link to it internally. The CSS styling is not as advertised, but it's better than trying to build my own Grunt task to solve the problem.
  4. Sync the API doc output with Github using the Grunt githubPages task. This was actually straightforward and just worked out of the box.
The long version:

A brief backstory. Early last year, we were expanding the team at ChemSW, and I wanted to be able to machine generate documentation from the the XML code comments across our various .NET projects. Aside: I had to look the date up, assuming it was years and years ago--shocking to find in the cold, hard, unrelenting truth of code commits that it was really just July, 01 2012 when I made my first commit on the subject. In spare time over 6-8 weeks or so, I scoured the inter-tubes for a tool which would do such a thing.

After all, Microsoft does this and they make .NET. How hard could it be? Hard. Note: Supposedly GhostDoc could (presumably still does) this; but I'm not interested in negotiating purchase authority. Most paths still lead to Sandcastle, or one of the many forks thereof. As best I remember, Sandcastle was a solution to problems which haven't been imagined yet. In the end, I finally found a tool called Doco, which I was able to fork and make use of. All of this, of course, was for .NET only and didn't include documentation for JavaScript.

For JavaScript, I chose the VsDoc style of documentation, because it purported to support some form of IntelliSense in Visual Studio. It does, and that feature works great until you add your 2nd JS file to the project.

So back to the present. A theme emerges. I recently started breaking new ground on OJ, and I wanted to generate API documentation. I did some research, and the Internet gave me full faith and confidence that JsDoc was finally the format of choice and machines were ready to eat it and spew out well formed HTML.

A few things have happened since then. First, the Chrome Dev team has made it drop-dead simple to debug your CoffeeScript and IcedScript and SASS and Less inside the dev tools. Second, Microsoft abandoned VsDocs when they embraced their own TypeScript. Third, since Grunt is now a de facto standard all its own, it's easier than ever to write your own niche NodeJs task and parse a few thousands files according to whatever regex you want. So more languages, more tools, more variation and a lower-than-ever bar to entry to roll-your-own solutions.

For the past week, I have wrestled with getting various tools to comply with my core requirement: go make me some API docs. I started with the one and only jsdoc Grunt plugin, jsdoc. It didn't work. If you search the Grunt plugins for 'doc', I think you'll find a long list of other well meaning tools, each of which in their own, niche ways also don't work.

There's docco, a tool which dutifully generates a beautiful UI representing your standard comments next to code--it also mangles your actual code documentation comments with the associated code. I get that it's easy to parse out all lines starting with "//" and that it's hard to parse start "/**" and end "*/", but it does not mean I'm interested in the solution to the easy problem.

There's apidoc, a tool which promises to generate the beautiful API docs I want, using a jsdoc-like syntax. In almost every way, the semantics for this documentation is jsdoc, except every tag begins "api" + {tagName}, and it ignores all other tags.

After vetting nearly every other tool out there, I circled back to grunt-jsdoc-plugin and filed a bug. Just 2 days later, and I finally have the problem clearly identified. My code is not explicit enough for JsDoc, by itself, to parse.

/**
 * Method to do something
 * @return {Array} An array
*/
Object.defineProperty(nameSpace, 'method', {
 value:
  function () {

  }
});
In plain JavaScript, I'm simply writing:

/**
 * Method to do something
 * @return {Array} An array
*/
nameSpace.method = function () {}
which JsDoc knows how to interpolate as it parses the AST. In my case, by using Object.defineProperty, I am "obfuscating" the assignment, the name of the property assigned and the type of the value being assigned, JsDoc iterates over this block and sees nothing to report. In this case, it is possible to instruct JsDoc what to do by defining the appropriate tags:

/**
 * @desc Method to do something
 * @name method
 * @return {Array} An array
 * @memberOf nameSpace
*/
Object.defineProperty(nameSpace, 'method', {
 value:
  function () {

  }
});
Presto.

Still. This time I solved the problem the traditional "right" way. By figuring out how to make the existing, seemingly proven tools work. I still have to refactor every code comment in my library before it will begin appearing in the documentation. Would it have been faster to grunt-force my own solution? Maybe next time.

You Might Also Like

0 comments

Public Domain. All content published here is released into the PD, except when otherwise indicated. Powered by Blogger.

Peers

Popular Posts

Like us on Facebook

Flickr Images