I am trying to document my code using JSDoc-toolkit. My code starts by being wrapped with a self-executing anonymous function. How in the world do I document this? I've spent nearly all day on this. JS Docs will not recognize anything inside of the anonymous function closure due to it not knowing what to do with it. It breaks and none of my comments come through.
My code looks something like this.
/**
* #fileoverview BLA BLA BLA
*/
/**
* This is where I don't know what to put.
*/
(function () {
"use strict";
/** or here */
var stlib = function (param, param, param) {
/** or here */
var share = {
/** or here */
config: {
button: DOM Element,
property: blablabla
},
init: function () { ...some init code here}
};
share.init();
};
widgets.add("share", stlib);
}());
Thank you!
You can use #namespace with #name and #lends like this:
/**
* #name MyNamespace
* #namespace Hold all functionality
*/
(function () {
"use strict";
/** #lends MyNamespace*/
var stlib = function (param, param, param) { ...All of my code...};
}());
You can't document nested functions directly. But you can do something like this:
/**
* #module foobar
*/
/**
* #function
* #author Baa
* #name hello
* #description Output a greeting
* #param {String} name - The name of the person to say hello
*/
(function hello(name) {
/**
* #function
* #author Baz
* #inner
* #private
* #memberof module:foobar
* #description Check if the argument is a string (see: {#link module:foobar~hello})
* #param {String} string - The string
* #returns {String} Returns true if string is valid, false otherwise
*/
var isString = function checkString(string) { return typeof string === 'string'; };
if (isString(name))
console.log('Hello ' + name + '!');
}('Mr. Bubbles'));
Here I'm setting checkString as private and inner to be descriptive (since nested functions can't be described), And then I pass in -p to document private functions. Finally, I add a link to the parent function for reference.
I think jsdoc is unnecessarily finicky and needs to be replaced with something better. It's a port of javadoc, so it has a lot of things that are relevant to Java but not JS, and vice versa. There are very common JS idioms, like closures or nested functions, that are hard or impossible to document.
I always check my namepaths and debug using the --explain flag.
Related
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! }
}
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.
I'm trying to find a way to document AMD modules using JSDoc3.
/**
* Module description.
*
* #module path/to/module
*/
define(['jquery', 'underscore'], function (jQuery, _) {
/**
* #param {string} foo Foo-Description
* #param {object} bar Bar-Description
*/
return function (foo, bar) {
// insert code here
};
});
Sadly none of the patterns listed on http://usejsdoc.org/howto-commonjs-modules.html work for me.
How can I generate a proper documentation that lists the parameters and return value of the function exported by the module?
As of the latest stable version (3.2.2) I do not think there is a way to do use jsdoc to produce documentation that will show that the module itself accepts parameters and returns some value. The closest I can come to the ideal is this:
/**
* Module description.
*
* #module path/to/module
*/
define(['jquery', 'underscore'], /** #lends module:path/to/module */
function (jQuery, _) {
/**
* The following function documents the parameters that the module
* takes and its return value. Do not call as
* <code>module.self(...)</code> but as <code>module()</code>.
*
* #param {string} foo Foo-Description
* #param {object} bar Bar-Description
*/
return function self(foo, bar) {
// insert code here
};
});
The generated documentation for the module will have an extra inner function named self.
The following seems to generate a result which looks quite acceptable:
/**
* Module description
*
* #module path/to/module
*/
define(['jquery', 'underscore'], function (jQuery, _) {
/**
* Description for function.
*
* #param {string} foo Foo-Description
* #param {object} bar Bar-Description
*/
var exports = function () {
// insert code here
};
return exports;
});
Which describes the module and the function with something like:
require("path/to/module")(foo, bar)
That's not perfect for AMD modules but I think the reader of the documentation is able to understand what the module exports.
So I have several object definitions that work like this:
(function () {
var parent= constructors.Parent.prototype;
/**
* Creates an instance of Child.
*
* #constructor
* #augments Parent
* #this {Child}
* #param {object} settings
*/
var Child= function(settings) {
constructors.Parent.apply(this, arguments); //calling parent constructor
//constructor code
}
Child.prototype= new constructors.Parent();
/**
* Method1
*
* #this {Child}
* #param {string} param1
* #param {number} param2
*/
Child.prototype.method1= function(param1, param2) {
parent.method1.apply(this,arguments); //calls "super"
//method code
}
constructors.Child= Child;
}());
I do all this so that only global variable is 'constructors' and so that I don't have to say 'construtors.Child' all the time. But JSDoc3 is ignoring my comments and generates nothing on this code. Anyone knows any special tags to fix this? I don't mind if the JSDoc shows my class name as 'Child' or 'constructors.Child', either way is fine.
use #public in front of #class/#module/#namespace
see https://github.com/jsdoc3/jsdoc/issues/442
I'm not sure if this is the right way to do it, but it worked:
On another file I now have the following:
/**
* #module constructors
*/
constructors= {}
And in the file mentioned before I now have:
/**
* #exports constructors
*/
(function () {
var parent= constructors.Parent.prototype;
/**
* Creates an instance of Child.
*
* #constructor
* #augments Parent
* #this {Child}
* #param {object} settings
*/
var Child= function(settings) {
constructors.Parent.apply(this, arguments); //calling parent constructor
//constructor code
}
Child.prototype= new constructors.Parent();
/**
* Method1
*
* #this {Child}
* #param {string} param1
* #param {number} param2
*/
Child.prototype.method1= function(param1, param2) {
parent.method1.apply(this,arguments); //calls "super"
//method code
}
constructors.Child= Child;
}());
I have a class which defines a few instance properties via Object.defineProperties and I'm having great difficulty getting JSDoc 3 to recognize that they belong to their class.
Here's a simplified version of what I'm working with:
/** #exports mymodule */
function mymodule(exports) {
/** #constructor
* #param {String} foo A foo.
* #param {String} bar A bar.
* #classdesc Has a foo and a bar.
*/
function Example(foo, bar) {
Object.defineProperties(this, {
/** A foo and a bar
* #memberof Example
*/
foobar: { enumerable: false, value: foo + bar, writable: false }
});
}
exports.Example = Example;
}
When I run JSDoc, I get output for mymodule, Example, foo, and bar, but not foobar. If I remove the #memberof tag for foobar, it get registered as a global. I've tried #memberof mymmodule~Example, adding #lends to both the Object.defineProperties call and the object passed to it, and converting it to Object.defineProperty, but the results don't change.
How can I document foobar as belonging to Example?
After digging through every example I could find, I finally assembled the necessary incantation — #memberof is indeed the trick, but JSDoc seems to require that modules being used in namepaths be explicitly marked as such. The following worked perfectly:
/** A foo and a bar
*
* #type String
* #instance
* #memberof module:mymodule~Example
*/
You could also try the #lends annotation in place of #memberOf like this :
Object.defineProperties(this, /** #lends Example# */{
/** A foo and a bar */
foobar: { enumerable: false, value: foo + bar, writable: false }
});
Don't forget the sharp symbol after the class name to tell jsdoc members are instance members and not static members.
After fiddling around for many hours, I finally got it to work with #memberOf!. Note the uppercase "O" and the bang "!"
/**
* Description
* #memberOf! MyClass
* #type {String}
*/
var myString;
In case you want to use defineProperty instead, a #type annotation is sufficient (at least for IntelliJ to infer the proper type for the property):
/** #type SomeType */
Object.defineProperty(this, "someProperty", {
get: () => new SomeType()
});
I am trying to understand the JSDoc style for documenting JavaScript that is used with the JavaScript Closure Compiler. I have the JavaScript code below
// ==ClosureCompiler==
// #compilation_level ADVANCED_OPTIMIZATIONS
// ==/ClosureCompiler==
(function(){
/**
* #type Array.<string>
* #private
*/
var sb = [];
/**
* #const
* #type{{append: function(string): SingletonStringBuffer, toString: function(): string}}
*/
window['SingletonStringBuffer'] = {
/**
* #param {string} text
* #return {SingletonStringBuffer}
*/
append: function(text){
sb.push(text);
return SingletonStringBuffer;
},
/**
* #return {string}
*/
toString: function(){
return sb.join("");
}
};
}());
When I do an advanced compile on this code I am receiving 2 warnings.
JSC_TYPE_PARSE_ERROR: Bad type annotation. Unknown type SingletonStringBuffer at line 10 character 35
* #type{{append: function(string): SingletonStringBuffer, toString: function()...
^ JSC_TYPE_PARSE_ERROR: Bad type annotation. Unknown type SingletonStringBuffer at line 15 character 11
* #return {SingletonStringBuffer}
^
The function append returns a deference to the encapsulating object. The variable that it is returning ,SingletonStringBuffer, is declared... so I am not sure what is wrong or how to correct it.
You haven't created a named type as far as the compiler is concerned. For this case, I would expect you to create an interface:
/** #interface */
function StringBuffer() {
}
/**
* #param {string} text
* #return {StringBuffer}
*/
StringBuffer.prototype.append;
etc
This can be declared either in the code (if you are using advanced mode it will be stripped) or in your extern files (if you want the type without the code in simple mode).
You can then use it like so (in your case):
(function(){
/**
* #type Array.<string>
* #private
*/
var sb = [];
/**
* #const
* #type {StringBuffer}
*/
window['SingltonStringBuffer'] = {
/**
* #param {string} text
* #return {StringBuffer}
*/
append: function(text){
sb.push(text);
return SingltonStringBuffer;
},
/**
* #return {string}
*/
toString: function(){
return sb.join("");
}
};
}());
singletons work differently in closure. I have not seen an explicit annotation for it, but the compiler (in advanced mode) has some understanding of certain built-in functions
Singletons would be declared via the goog.addSingletonGetter function, here is a code sample
/**
* #constructor
* #extends {path.to.BaseClass}
*/
path.to.MyClass = function() {
goog.base(this);
};
goog.inherits(path.to.MyClass, path.to.BaseClass);
goog.addSingletonGetter(path.to.MyClass);
and that be it.
PS
you are getting the bad annotation because {SingltonStringBuffer} is never declared as a class.
PPS.
Some rambling on post the fact.
I suspect (but this is untested) that making the constructer private might work. Notice the trailing underscore in the example
/**
* #private -> NOTE THIS IS IN NO WAY VERIFIED
* #constructor
* #extends {path.to.BaseClass}
*/
path.to.MyClass_ = function() {
goog.base(this);
};
goog.inherits(path.to.MyClass, path.to.BaseClass);
goog.addSingletonGetter(path.to.MyClass);