Search code examples
javascriptjsdocjsdoc3

JSDoc CommonJS with exports object passed into IIFE


UPDATE: @spenibus helped me reach the conclusion that this may be an issue with JSDoc itself. I added my findings to this open issue on their GitHub. @spenibus found a solution, but it requires a slightly altered version of the IIFE

I'm using an IIFE in a CommonJS module to be able to work with CommonJS and fallback to assigning the interface to the window object if it module.exports doesn't exist. How do I properly document this so that the passed in exports object is treated as module.exports?

/**
 * This is a description
 * @module someModule
 */
(function (exports) {

    /**
     * Returns true if something.
     * @param {String} type
     * @returns {boolean}
     * @static
     */
    var isSomething = function isSomething(type){
        return true;
    };

    exports.isSomething = isSomething;

})(
    //if exports exists, this is a node.js environment so attach public interface to the `exports` object
    //otherwise, fallback to attaching public interface to the `window` object
    (typeof exports === 'undefined') ?
         window
        : exports
);

Solution

  • While JSDoc issue 456 seems relevant that's not getting us anywhere yet.

    I had a look at Use JSDoc: @alias which, while promising, did not offer the same JSDoc output.

    Then I tried something simple, which had me playing the FF7 victory theme in my head, AKA it worked:

    /**
     * This is a description
     * @module someModule
     */
    
    (function() {
    
        // export to window when not used as a module
        if(typeof exports === 'undefined') {
            var exports = window;
        }
    
        /**
         * Returns true if something.
         * @param {String} type
         * @returns {boolean}
         * @static
         */
        exports.isSomething = function(type){
            return true;
        };
    })();
    

    Using jsdoc ./ on the project dir resulted in the same output as if I had not used an IIFE. The basic idea is to always have an object named exports and simply modify what it references.

    Nodejs test

    var mm = require('./module.js');
    
    console.log('--Testing nodejs--');
    console.log(mm);
    

    Output:

    --Testing nodejs--
    { isSomething: [Function] }
    

    Html script test

    <script src="module.js"></script>
    <script>
        console.log('--html script test--');
        console.log(isSomething.toString());
    </script>
    

    Output:

    "--html script test--"
    "function (type){
        return true;
    }"
    

    Update 2015-08-13 05:10 +0000
    Moved window exportation inside the IIFE to avoid extra exports var laying around in html script.