-
Notifications
You must be signed in to change notification settings - Fork 239
Guide
Writing documentation is hard. Writing good documentation is even harder. And for most developers there's a constant pressure to concentrate on all other more important things besides the documentation. There's never enough time for writing docs.
And that's why JSDuck aims to make the process of writing documentation as painless as possible.
First off JSDuck allows you to Markdown for structuring your text:
/**
* Returns description of the time of the day.
*
* Different heuristics are used to come up with the **most** appropriate
* wording for the current user.
*
* @return {String} Possible return values are:
*
* - midday
* - late night
* - early morning
* - just before lunch
* - tea time
*/
getDayTime: function() {
You can also use HTML, because Markdown allows embedding of HTML, which will come in handy if you have a lot of legacy documentation written for ext-doc.
Second, JSDuck tries to infer as much information from code as possible. For this it looks at the code that immediately follows the doc-comment. To see this in action, we have to get into the details...
Documenting an Ext JS 4 class will be a breeze if you are using the standard
Ext.define
syntax:
/**
* A duck, not just a stupid bird.
*/
Ext.define("Duck", {
extend: "Bird",
mixins: {
observe: 'Ext.util.Observable',
fly: 'Fliable'
},
alternateClassName: ['JustDuck', 'MyDuck'],
alias: 'widget.duck',
requires: ['Wing', 'Tail'],
uses: ['Water'],
singleton: true,
JSDuck will automatically recognize that this is a doc-comment for class Duck
and will also understand all the special class configs.
But JavaScript is a dynamic language and there are bazillion ways to define a class. JSDuck will only auto-detect all these properties when you strictly follow the above form. But don't lose hope, you can always use @tags to say things explicitly:
/**
* @class Duck
* A duck, not just a stupid bird.
* @extends Bird
* @mixins Ext.util.Observable
* @mixins Fliable
* @alternateClassName JustDuck
* @alternateClassName MyDuck
* @alias widget.duck
* @requires Wing
* @requires Tail
* @uses Water
* @singleton
*/
(function() {
this.Duck = {
extend: "Bird",
mixins: {
observe: 'Ext.util.Observable',
fly: 'Fliable'
},
alternateClassName: ['JustDuck', 'MyDuck'],
alias: 'widget.duck',
requires: ['Wing', 'Tail'],
uses: ['Water'],
singleton: true,
JSDuck also supports Ext.extend
syntax from Ext JS 3, automatically detecting the name of the class and parent:
/**
* A duck, not just a stupid bird.
* @xtype duck
*/
Duck = Ext.extend(Bird, {
...
});
Ext.reg('duck', Duck); // register xtype
Finally, JSDuck will assume a class definition when doc-comment is followed by assignment to a variable that looks like a class name (begins with uppercase letter):
/**
* A simple class.
*/
namespace.MyClass = {};
It can also be a named function:
/**
* A simple class.
*/
function MyClass(){};
Lastly there are few properties of classes that can't be auto-detected:
-
@hide
,@ignore
or@private
marks the class as being for internal use only. -
@author
and@docauthor
allow documenting the names of code and documentation authors. You might want to check out the--meta-tags
command line option for specifying additional tags like these.
All doc-comments following a class doc-comment will be assumed to be members of that class. There are four types of members: configs, properties, methods, events.
Only methods are auto-detected. Everything not looking like a method will be assumed to be a property. So be sure to always use @event and @cfg for documenting events and configs.
When doc-comment is followed by a function it's auto-detected as method. When auto-detection
fails you can use @method
optionally followed by a function name. A common example where
auto-detection fails is closures:
/**
* Returns a unique ID for use in HTML id attribute.
* @param {String} [prefix="id-"] The prefix for the ID.
* @return {String} the new ID
* @method
*/
getId: (function(){
var map = {};
return function(prefix){ return ++map[prefix || "id-"]; };
})(),
Here you can also see the syntax for optional parameters (these are enclosed in square brackets) and their default values. There's also an old syntax for optional parameters where you write "(optional)" right after parameter name.
I won't bother explaining the normal @param
and @return
syntax and will instead diverge into a more complex example:
/**
* Calculates the score for each item in the array.
*
* @param {Array} array The input array.
*
* @param {Function} fn The callback function.
* For every item in array the function will be called with:
* @param {Mixed} fn.item The item itself.
* @param {Number} fn.index Index of the item.
* @param {Number} fn.return Should return a numeric score between 0 and 1.
*
* @param {Object} scope Value for `this`.
*
* @return {Object[]} Array of objects with fields:
* @return {Mixed} return.item The original item
* @return {Number} return.score The score
*/
score: function(array, fn, scope){
Here you see a syntax for describing parameters and return values of Function or Object type. For objects you can describe each property. For callback functions you can describe the parameters and return value. And of course you can do this all recursively however complex parameters or return values you need.
For template methods, meant to be overridden for extending the class, use the @template
tag to differentiate them in docs.
Constructors are documented just like normal methods:
/**
* Creates new Duck from proper duck egg.
* @param {DuckEgg} egg Egg with DNA configuration for new duck.
*/
constructor: function(egg) {
You can also use the @constructor
tag which for JSDuck means @method constructor
. The @constructor
tag can for legacy reasons be used inside class doc-comment. Don't use it like this in new code.
Events are a lot like methods, except that they don't have return values. Also it probably doesn't make sense to have optional parameters.
/**
* @event
* Triggered after component gets hidden.
* @param {Ext.Component}
*/
"hide",
@event
can be followed by event name, but in the above case it is auto-detected.
Configs are a lot like method parameters. They can have default values and sub-properties.
/**
* @cfg {Object} size Size of the item.
* @cfg {Number} [size.width=0]
* @cfg {Number} [size.height=0]
*/
size: {width: 0, height: 0},
For configs with simple literal values one can take advantage of auto-detection of the type, the name and even of the default value:
/**
* @cfg
* CSS class names to apply for root element.
*/
cls: ["x-component", "x-item"],
The above will be auto detected as config option cls
of type String[]
with default value ["x-component", "x-item"]
.
JsDuck will auto-detect Number
, String
, Boolean
, RegExp
and Function
types. Everything else will be labeled as Object
.
Unlike with parameters, all configs are optional by default. But there is a special syntax for marking up required configs:
/**
* @cfg {Ext.data.Store} store (required)
* The store to use for this view.
*/
For Ext JS 4 configs that get auto-generated get/set methods the @accessor
tag can be used to let JSDuck also generate automatic getter/setter documentation:
Ext.define("MyClass", {
config: {
/**
* @cfg {Ext.data.Store} store (required)
* The store to use for this view.
* @accessor
*/
store: undefined
}
});
This will be interpreted by JSDuck as if you had written:
Ext.define("MyClass", {
config: {
/**
* @cfg {Ext.data.Store} store (required)
* The store to use for this view.
*/
store: undefined
/**
* @method setStore
* Sets the value of {@link #store}.
* @param {Ext.data.Store} store
*/
/**
* @method getStore
* Returns the value of {@link #store}.
* @return {Ext.data.Store}
*/
}
});
Config options may also be defined in eventedConfig:
property which additionally generates a '<config-name>change'
event. To auto-document that event include @evented
tag alongside @accessor
.
Configs can also be part of class doc-comment. This is to support legacy code. Don't use this.
The syntax for @property
is almost the same as for @cfg
(there can be no required properties and @accessor's):
/**
* @property {Boolean} [readOnly=false]
* True when component is in read-only state.
*/
Like with configs, you can take advantage of auto-detection. And with properties you can leave off the @property
tag entirely:
/**
* True when component is in read-only state.
*/
readOnly: false,
For properties there is one extra legacy tag - @type
- which just defines the type of the property:
/**
* True when component is in read-only state.
* @type Boolean
*/
readOnly: getReadOnly(),
All types of members share the following tags:
-
@private
,@ignore
and@hide
remove the member completely from documentation. As if the doc-comment never was there. -
@protected
marks member as protected. (Protected methods should be only called by child classes). -
@static
marks member as static. Note that static members aren't inherited by default. -
@inheritable
makes a static member inheritable. -
@deprecated
marks member as deprecated. It's optionally followed by version number and description. For example@deprecated 4.0.6 Use {@link #foo} instead
. -
@member ClassName
defines that the member belongs to the specified class, not to the one who's doc-comment precedes it. -
@inheritdoc
- inherits documentation from another member - see "Sharing documentation" section for details.
Not all of these will make sense for all types of members.
Throughout this guide you've seen type definitions like {Number}
. These aren't just arbitrary strings enclosed in curly braces - there's a specific syntax for specifying types and JSDuck will check that you follow it. Here's a short overview of supported syntax:
-
{Ext.Element}
- a single Ext.Element. -
{String[]}
- array of strings. -
{String[][]}
- 2D array of strings. -
{Number/String/Boolean}
- either number, string, or boolean. -
{Boolean...}
- variable number of boolean arguments.
JSDuck will also check that you don't reference any unknown types. For example if you specify {Foo}
and you don't have class Foo included to you documentation, JSDuck will produce a warning. Warnings aren't thrown for JavaScript builtin types (Object
, String
, Number
, Boolean
, RegExp
, Function
, Array
, Arguments
, Date
, Error
) and few DOM types (HTMLElement
, XMLElement
, NodeList
, TextNode
, CSSStyleSheet
, CSSStyleRule
, Event
). To make JSDuck ignore some other type names use --external=Foo,Bar,...
To document a variable that can be of any type whatsoever, use the Mixed
type. But try to keep its use to the minimum, always prefer the {Foo/Bar/Baz}
syntax to list possible types.
Inside comments you can link to classes and class members using the
{@link}
tag:
{@link Class#member link text}
For example:
Look at the {@link Duck} class. There are methods like
{@link Duck#fly} and {@link Duck#swim} and even this
{@link Duck#walk particularly slow method}.
Now compare it to {@link #move} method of this class, that does
all the above.
This will produce something like this:
Look at the Duck class. There are methods like Duck.fly and Duck.swim end even this particularly slow method.
Now compare it to move method of this class, that does all of the above.
Sometimes the name is not enough to uniquely identify a class member.
For example Ext.data.Store
has a load
method and load
event.
In such case, prepend cfg-
, property-
, method-
or event-
to
the member name:
Listen to the {@link Ext.data.Store#event-load load event}
Or you might need to reference a static method when an instance method of the same name exists:
Use {@link Ext.form.field.Field#static-method-getName getName} to get class name.
For links to other websites, and things within the docs app itself like guides, use Markdown links:
See [Getting Started Guide](#!/guide/getting_started) or check
out [Sencha website][1] for more.
[1]: http://www.sencha.com/
You can include images inside the documentation using the {@img}
tag:
{@img path/to/image.png alt text}
The paths should be relative to the directory specified by --images
option (there can
be more than one to list multiple search paths).
For ExtJS 4 you can simply refer to the doc-resources directory of downloaded release:
$ jsduck extjs-4.0.7/src --images=extjs-4.0.7/docs/doc-resources --output my-docs
All the linked images will then be copied over to output directory, while {@img}
tags
will become repleced with markup like:
<p><img src="doc-resources/path/to/image.png" alt="alt text"/></p>
For full control over the created markup you can use the --img
command line option.
Sometimes you have documented a config option extensively in parent class:
/**
* @cfg
* Some very long documentation...
*/
shape: 'line',
But in subclass you want to change the default value of the config. Now it would be good if the documentation of subclass reflected this change, but you don't want to duplicate the long documentation again. That's where @inheritdoc
steps in:
/**
* @cfg
* @inheritdoc
*/
shape: 'rectangle'
Another common use of @inheritdoc
is defining an alias for some method. For example Ext.each
is alias for Ext.Array.each
. In such case specify the class and member to inherit:
/**
* @member Ext
* @method each
* @inheritdoc Ext.Array#each
*/
Ext.each = Ext.Array.each