Documenting a (new) widget

After reading Ronald Treur’s article about Duckumentation on tiDev I decided to give JSDuck a try for some projects and a new widget I was working on. In this blog I want to share my approach for documenting Alloy widgets. I’m looking forward to hear your ideas, so please leave a comment!

New Alloy Form widget

The new widget I’ve used as an example here is a widget to create a Ti.UI.TableView based form which is both easy to implement, customise and extend.

GitHub pages

I wanted to publish the documentation online with minimal effort. Since the widget lives on GitHub, using GitHub pages was the logical choice. This requires the repo to have a gh-pages branch which will be served as a website.

Working copies

Because JSDuck generates most of the documentation from inline docblocks in the code, I have set up multiple working copies on my local machine as follows:

  • ~/form/master: the master branch.
  • ~/form/gh-pages: the gh-pages branch.
  • ~/form/test: the test branch.

This way I can keep the master repo clean by having all jsduck-*.json files in the gh-pages repo, just like I do for testing. When I execute $ jsduck in the gh-pages branch it looks for code in ../master, as the jsduck.json file shows:

  {
      "--title": "Alloy Form Widget - Documentation",
      "--": [
          "../master"
      ],
      "--output": "docs",
      "--welcome": "../master/README.md",
      "--categories": "jsduck-categories.json",
      "--guides": "jsduck-guides.json",
      "--warnings": "-image_unused",
      ..
  }

Re-using README

To stay DRY, I have re-used the master branch’s README as the welcome page. I also wanted to use the test branch README for the testing guide, but this unfortunately copied the whole test app into the guides. Of course I could still use Grunt to copy only the README before running jsduck if I wanted.

Namespacing

I want to be able to also use JSDuck to generate documentation for an app, including this and other widgets it uses. This is why I namespaced the widget controllers and libraries as Widgets.nlFokkezbForm.controllers.* instead of just. controllers.field. In an app’s documentation this will look like:

NOTE: I was in doubt between nlFokkeZB and nl.fokkezb.form. The last would also group different widgets under nl.fokkezb.*, but make the tree deeper and thus more difficult to navigate.

Constructors

The code you’re writing as Alloy controllers are ultimately wrapped by Alloy in a Controller function exported as the CommonJS module.

  ..

  function Controller() {

    ..

    var $ = this;   

    // Your view XML compiled to JS

    // Your controller JS

    ..

    _.extend($, exports);
  }
  ..
  module.exports = Controller;

Since I can’t inject a docblock here, but also because I like to keep my controller code organized, I always wrap the controller’s code to be executed at creation in a self-executing method like this:

  (function constructor(args) {

    // my controller 'constructor' code

  })(arguments[0] || {});

Now I can simply document this as:

  /**
   * Constructor.
   *
   * @method Controller
   * @param args Arguments passed to the controller.

   */
  (function constructor(args) {
  ..

If I’d leave out @method then JSDuck would warn about finding an unnamed method, because it’s self-executing. If I’d use @constructor instead, then JSDuck would use the class and show something like:

  • new Widgets.nlFokkezbForm.controllers.widget( args ) : Widgets.nlFokkezbForm.controllers.widget

Instead I use @method Controller so that the documentation stays close to how it works in the compiled Alloy controller code.

App imagineer: Imagining, Engineering & Speaking about Native mobile Apps with Appcelerator Titanium & Alloy • Meetup organizer • Certified Expert • Titan


Comments

  • Manuel Lehner

    This is really cool. Thanks for sharing your experiences – I will definitely use JSDuck for my next projects.