19

Thanks to the answer found here:

https://stackoverflow.com/a/19336366/592495

My JavaScript documentation is well-organized and well-formatted. Each namespace is a "parent" of methods contained within. However, navigation is not quite as granular as I would like.

After compiling/rendering using the node.js tool via a simple command (jsdoc file1.js file2.js), the docs are generated into a default template. This default template displays my namespaces in the sidebar navigation, but it does NOT show methods that each contains.

You can fake a list of methods by adding the @class directive to each method, but as we know, they are not really classes.

I would love to see a sidebar navigation like this:

My Project

 - namespace 1
    - method.a
    - method.b
    - method.c

 -namespace 2
    - method.d
    - method.e

Any direction to documentation I have overlooked would be greatly appreciated.


[edit to add:]

Upon experimentation, @class does almost exactly what I want but with some exceptions:

  • It lists classes above namespaces. I don't like that since the namespaces are the "parents" as it were.

  • JavaScript doesn't have classes in that sense. Not ones that are called "classes" with that nomenclature. It creates a weird disconnect when reading the document to see a list of "classes".

  • It adds the "new" operator automagically. Not all of the methods have constructors... you can see the problem!


[edit: sample code]

So here's the current structure. Before I annotate it with JSDoc comments, here's the basic approach:

var app =  app || {};
app.utils = {
    whizbang: function() {},
    geegolly: function() {}
  };
app.render = {
    thestuff: function(params) {},
    thethings: function(params) {}
  }
}

So, using object literal notation, the top level is a "namespace" for the whole application, but within there are sub-namespaces for different purposes. Here, I have a sub-namespace specific to utilities, and another one specific to rendering. Each can have properties, but more importantly they each contain functions. It is these functions which should appear in the sidebar. Now to flesh it out with my current pattern for JSDoc:

/** 
 * @file MyApp.js This is an awesome description of MyApp.js
 * 
 * @version 0.1
 * @author Greg Pettit
 * @copyright 2015
 * 
 */

/**
 * Description of my main namespace!
 * 
 * @namespace app
 */
var app = app || {};

/**
 * This is a description of my sweet utilities namespace!
 *                                                                              
 * @memberof app
 * @type {object}
 * @namespace app.utils
 */
app.utils = {
  /**
   * app.utils.whizbang is an awesome function with magical powers. I sure wish
   * it would appear in the sidebar as a member of app.utils!
   * 
   * @memberof app.utils
   * @method whizbang
   * 
   * @param {method} [successCallback] Method invoked on successful attempt.
   * @param {method} [errorCallback] Method invoked on unsuccessful attempt.
   * 
   */
   whizbang: function(successCallback, errorCallback) { // do utility stuff! }
}

/**
 * This is a description of the best rendering namespace ever.
 *                                                                              
 * @memberof app
 * @type {object}
 * @namespace app.render
 */
app.render = {
  /**
   * app.render.thethings renders the things! I wish it would render to the sidebar...
   * 
   * @memberof app.render
   * @method thethings
   * 
   * @param {method} node The node to which thethings are rendered
   * 
   */
   thethings: function(node) { // do rendering stuff! }
}
Community
  • 1
  • 1
Greg Pettit
  • 10,305
  • 4
  • 47
  • 68
  • 1
    If any hardcore JSDoc users out there are thinking, "Yeah. This can't be done. I've never seen it anyhow," I would appreciate a comment still! – Greg Pettit Jun 17 '15 at 14:55
  • what about the `@namespace` or `@module` tag ? – n00dl3 Jun 18 '15 at 09:22
  • @JuniusRendel, thanks for the comment! I am using `@namespace `throughout, but the functions don't want to be added to it, because JSDoc still wants to be JavaDoc and look for classes. `@module` I honestly haven't investigated too deeply as it seemed to expect exports and so forth. – Greg Pettit Jun 18 '15 at 22:02
  • Ok, I've had a look, and I have no idea. But maybe you could just create a custom jsdoc template that will do what you need, or maybe there's one which will fit your needs better... – n00dl3 Jun 19 '15 at 07:49
  • Thanks @JuniusRendel -- I didn't know that these things could be controlled at the template level. I'll try reading up on how templates work. – Greg Pettit Jun 19 '15 at 15:27
  • I can't for the life of me find where to edit the template! The documentation for the templating system seems to keep bringing me to editing conf.json – Greg Pettit Jun 23 '15 at 13:49
  • have you seen the [jaguarjs template](https://github.com/jsdoc3/jsdoc#user-content-templates-and-build-tools) in the jsdoc3 `README.md` ? It seems they have done what you are looking for, so maybe you can use their template or take a look at what the jaguarjs team have done in their jsdoc comments to do such a thing... – n00dl3 Jun 25 '15 at 09:42
  • Looks promising, Junius! It looks like they want to make node.js soup just to use the template, which is unfortunate. I wish Node projects would be more self-encapsulated... but I digress! Looks promising, will check out! – Greg Pettit Jun 25 '15 at 14:38

1 Answers1

0

Have you tried using the @lends tag? An example of your code and doc comments would be helpful here.

Since I don't know what your code looks like, I'll just give an example of how I use JSDoc with our in-house framework, which has lots of idiosyncracies (hey, I didn't write it, I just have to use it).

Just to give some context, we have a context object that can create apps and modules (apps are just modules with a start method):

/** @namespace MyApp */
var MyApp = context.app('myApp').use('module1', 'module2', 'underscore');

We have a dependency injection system for backbone that uses an angular-style pattern for expressing dependencies:

/** 
* The constructor for MyModel
* @memberof MyApp
* @param {object?} attrs
* @param {object?} options
* @param {AppUtils} appUtils
* @constructor
*/  
MyApp.MyModel = function(attrs, options, appUtils) {
    this.options = options;
    this.utils = appUtils;
}

// This is injected by the dependency resolver at instantiation time
// No additional JSDoc comments are necessary, it actually gets this right
MyApp.MyModel.prototype = {

    idAttribute: 'customId',

    defaults: {
        customId: '',
        name: '',
        birthday: null
    }

};

// Registers MyModel with the IOC container as 'myModelName'
MyApp.model('myModelName', [
    'attrs',
    'options',
    'appUtils'
    MyApp.MyModel
]);

And then a different file can have an instance of myModelName injected by adding it to that dependency array at the bottom.

Funny thing is, JSDoc actually does a pretty good job of understanding that particular arrangement, as long as I don't try to get too fancy... but the following pattern is apparently too confusing for it:

/**
 * @memberof MyApp
 * @param {MyApp.MyModel} myModel
 * @param {urlParser} urlParser
 * @constructor
 */
MyApp.SomeService = function(myModel, urlParser) {

    return {

        foo: function() {
            //whatever
        },

        bar: function() {
            //whatever
        }

    };

};

MyApp.service('someModuleName', [
    'myModelName',
    'urlParser',
    MyApp.SomeService
]);

The only thing that I've found that gives me anything close to the desired output is using the @lends tag to tell JSDoc that a particular object/property/method is "lended" as a different property. For example, to document the attributes property of a backbone model (which is ostensibly defined by its defaults property), we do this:

MyApp.MyModel.prototype = {

    idAttribute: 'customId',

    /** @lends MyApp.MyModel.prototype.attributes */
    defaults: {
        customId: '',
        name: '',
        birthday: null
    }

};

And for that case where the service is returning an object, the only way we've found to get those object properties documented is like this:

/**
 * @memberof MyApp
 * @param {MyApp.MyModel} myModel
 * @param {urlParser} urlParser
 * @constructor
 */
MyApp.SomeService = function(myModel, urlParser) {

    /** @lends  MyApp.SomeService.prototype */
    return {

        foo: function() {
            //whatever
        },

        bar: function() {
            //whatever
        }
    };

};

I have no idea if any of that was useful, but maybe it'll give you some ideas for things you could try with @lends. If you can provide some example code, I can possibly give you a more useful answer.

Isochronous
  • 1,015
  • 9
  • 23
  • I'm not sure that `@lends` is what I'm looking for. I've updated my question with code samples. Junius has pointed me towards the templating system which I guess will be my next port of call. Thanks for the response so far, though! – Greg Pettit Jun 19 '15 at 15:28
  • The templating system does seem to make sense, as it seems like the default template restricts the depth of navigation to two levels, and it seems that you need it to go down to three levels. Please update your question if you figure out how to accomplish your goal! – Isochronous Jun 22 '15 at 17:02
  • I will! I haven't had a chance to roll around back to this yet, but it's still on my radar. I will definitely provide the solution when I find it. – Greg Pettit Jun 22 '15 at 19:12
  • did you locate documentation for doing such modifications? I keep going around in circles both on Google and on their own documentation site. If you've found it and could share it, I would be greatly in your debt!! – Greg Pettit Jun 23 '15 at 13:50