Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting jsdoc and Crockford's design patterns to get along

I'm using Douglas Crockford's design pattern to implement private, privileged and public methods. It basically looks something like this (using RequireJS):

define(function () {
    return function () {
        var that = {},

        _init = function () {
            // "constructor"
        },

        _privateFn = function () {
            return 42;
        };

        that.publicFn = function () {
            return 2 * _privateFn();
        };

        _init(arguments);

        return that;
    };
});

However, I'm having trouble getting the jsdoc toolkit to parse it correctly. I've played around with the @name and @memberOf annotations (like here), but no matter what I do, I just can't get the functions to show up.

Does anyone know a solution?

like image 986
n3rd Avatar asked Feb 07 '11 11:02

n3rd


4 Answers

Okay, I finally figured it out. Here's how you do it:

/**
* @name MyModule
* @namespace
*/
define(['MyModule'], (function () {
    "use strict";

    var Clazz = function (config) {
        var that = {},

        /**
        * @private
        * @type number
        * @name MyModule#_privateField
        * @field
        */
        _privateField = 42,

        /**
        * Returns a private field
        * 
        * @private
        * @memberOf MyModule#
        */
        _privateFn = function () {
            return _privateField;
        };

        /**
        * Uppercases a string value.
        * 
        * @public
        * @name MyModule#publicFn
        * @function
        * @param {string} value The value to uppercase.
        */
        that.publicFn = function (value) {
            return value.toUpperCase();
        };

        return that;
    }

    return Clazz;
}));
like image 187
n3rd Avatar answered Nov 07 '22 10:11

n3rd


I've had similar fun messing around with tags to try to get JsDoc Toolkit to output something sensible where things were being built up dynamically.

Even when I got it working, it ended up with odd quirks which required me to fiddle with the tags again and again, it looked unappealing and still wasn't a substitute for proper documentation - you might as well be reading those comments in the source code.

Honestly, the best thing I ever did was to take the time I was spending jumping through hoops with JsDoc Toolkit and use it to write some real documentation with Sphinx.

In addition to the inherent benefits of any guided documentation written by people for people over auto-generated API docs, Sphinx has JavaScript domain directives which allow you to document the final state of the API which will be exposed to end users, rather than having some code attempt to make sense of the API by looking at trial-and-error comments littered about your code.

like image 44
Jonny Buchanan Avatar answered Nov 07 '22 09:11

Jonny Buchanan


I found this question while searching for a solution to the same problem. I ended up finding a better way to solve this if you don't care about documenting private methods/variables (which you probably shouldn't, given that they're really local variables and can't be accessed from anywhere else). It uses the @alias directive, which is new in JSDoc 3.

/**
* @name MyModule
* @namespace
*/
define(['MyModule'], (function () {
    "use strict";

    var Clazz = function (config) {
        /** @alias MyModule.prototype */
        var that = {};

        /**
        * Uppercases a string value.
        * @param {string} value The value to uppercase.
        */
        that.publicFn = function (value) {
            return value.toUpperCase();
        };

        return that;
    }

    return Clazz;
}));
like image 1
Ben Weissmann Avatar answered Nov 07 '22 08:11

Ben Weissmann


Don't know if this existed when you tried it, but @lendsis significantly nicer to use.

See: http://usejsdoc.org/tags-lends.html

Example:

var Person = makeClass(
/** @lends Person.prototype */
{
    /** @constructs */
    initialize: function(name) {
        this.name = name;
    },
    say: function(message) {
        return this.name + " says: " + message;
    }
});
like image 1
Eli Avatar answered Nov 07 '22 08:11

Eli