Rather than attempting to document the source code itself, doczar only uses tagged comments. The comment format has been designed for legibility and uses a simple scope model to make documenting large, complex entities easy.
- describe modules and object-oriented structures
- inheritence, multiple inheritence and Java
- Github-flavored markdown with syntax highlighting
- semi-automatic crosslinking
- callbacks and events
- multiple return values and keyword arguments
- function signatures
- automatic Node.js dependency graph documentation
|Table Of Contents|
|5||Components, Types and Paths|
|6||Documents and Spares|
|9||Events and Errors|
doczar is cross-platform. Because pathnames are sanitized differently on Windows, documentation is
best viewed and/or hosted on the same machine where it was generated.
To add the binary
doczar to your executable path:
$ sudo npm install -g doczar
$ doczar --in=src/**/*.c --out docz$ doczar --jsmod ./main # outputs to ./docs
|o, out||Selects a directory to fill with documentation output. The directory need not exist or be empty.|
|i, in||Selects files to document. Parses nix-like wildcards using glob.
|j, js, jsmod||Loads the filename with required and documents every required source file.|
|with||Include a prebuilt standard library in the documentation.|
|dev||Display Components marked with the
|api||Display only Components marked with the
|raw||Log events as json strings instead of pretty printing them.|
|date||Explicitly set the datestamp on each page with any Date-compatible string.|
doczar is developed and maintained by Kevin "Schmidty" Smith under the MIT license. If you want to
see continued development on
doczar, please help me pay my bills!
The simplest form of documentation is a single Declaration in its own block comment with an informational summary. The opening line of a block comment must contain only the characters opening the comment, a Declaration and as many spaces and tabs as you want. On the next line you may begin describing this unit of code with github-flavored markdown.
In languages with c-like block comments (don't forget css) it looks like this:
/** @class MyClassFor compatibility purposes, c-like comments support anynumber of asterisks *immediately after the slash*.*//************* @member MyClass#asteriskCount*Any* number of asterisks (greater than zero).*/
The final newline is not required. This is mainly to support
@module declarations that span
multiple files. See Modules for more information on scope and
/** @module BoxFactory */int myInt = 42; /* @local/int myInt *//** @spare ExtraDocsThese extra documents are part of the[BoxFactory](.) module. Their fullpath is `BoxFactory~ExtraDocs`.*/
A special markdown caveat: you will need two newlines to terminate a bullet list.
/** @property/Function doTheThingsDoes all the things. It does:* the hottest things* the coolest things* all the things you could everpossibly imagineAnd it does them fast!*/
In python, any "triple" string literal that meets the first-line requirements is a document comment.
""" @property/function referenceMontyPythonEither triple or triple-double is fine."""
Ruby users may use
=end with the same rules.
=begin @module MyRubyGemI don't know very much about Ruby.=end
Finally, HTML comments are also supported.
<!-- @module SplashPageGuest user landing page with corporate logo and account login/registration tools.-->
Indentation of a markdown section is automagically normalized to the least-indented line and you may include any number of tab and space characters before any Declaration. You can even break in the middle of a link definition.
/** @member/int fooA contracted document withlittle available horizontalspace that needs a [link]() to asearch engine.*/
To add a child with a standalone doc comment, simply specify a complex path of any length.
/** @class FooClassA simple class.*//** @property/Function FooClass.getDefaultGet a new default instance of FooClass.*//** @returns/FooClass FooClass.getDefault)defaultInstanceReturns a new instance with the default configuration.*/
Once you have opened a declaration, you may write additional declarations which will all be scoped to the enclosing comment.
/** @class MyClassA simple class.@property/Function getAllInstancesA static Function that returns all instances of MyClass.@member/Function doSomethingCoolA member Function on each instance of MyClass.*/
In some languages such as Java, the concept of a module is very specific and
always describe an importable structure. In environments like Node.js where directly importing
submodules is rare, one might use a
@module to describe a type that is involved in processing or
may be returned but which is abstract or cannot be accessed directly.
@module Declaration has an infectious scope. Every Declaration after it is scoped to the
module Component, as are value type paths that begin with a delimiter. See crosslinking for more information. If you want to semantically declare a
affecting the scope, use the
@submodule declaration instead.
The global namespace and the first level of modules live together. Beyond the root, modules possess
their own namespace and are delimited with
/** @module FooThe Foo module.*//** @class BarThe Foo.Bar class.*//** @submodule/class BazThe Foo:Baz class.*//** @property/Function createBar*/
A value type is declared with a forward slash. Multiple value types are declared with the pipe
/** @property/String foobarA String property called "foobar".*//** @property/Number|undefined resultThis property may be either a Number or `undefined`.*/
Modifiers and Flags
Modifiers, and their simpler counterpart Flags, are statements which modify the Declaration directly above them rather than declaring a new Component. Modifiers have serious consequences for the visibility and position of a Component and its children. Flags just render literally as helpful keywords in a contrasting color.
/** @class MyClass@super LisasClass@publicA simple subclass of Lisa's class.@member/String uniqueID@constThis id String is generated at instantiation and becauseit is constant, it will never give you up, never let youdown.*/
Here is a list of the available Modifiers and Flags
@developmenthides this Component unless the --dev flag is used
@apireveals this Component and its ancestors when the --api flag is used
@optionalindicates something which need not exist (usually an argument)
@superinherits from a superclass
@implementsassociates an implemented Java interface
@defaultdescribes a default value. Always use backticks.
Components, Types and Paths
Let's look at all the Components we have available.
These are the only Components which may be used to open a new document comment.
@classinstantiable class objects
@sparebare markdown document
@memberinstance property or method
@throwsconditions causing an exception to be thrown
@enumlist of named values
These may only appear inside a document comment opened by a Primary Component Declaration.
@argumentoptionally-named function or event argument
@kwargpython-style keyword argument
@signaturean alternate function signature
@nameda named value in an
Many of these Component types have their own special path delimiters. This lets us reference more things as paths than in any other document generator. Here they are:
You can use a name starting with a delimiter to imply the Component type of any Inner Declaration,
skipping directly to the value type. You may do this with any of the types listed above as an
entirely optional feature. My personal recommendation is to use it only for
The default delimiter is
/** @class MyClass@Function .getAllInstancesLoad all instances of MyClass.@Number countTotal number of instances.@String #uniqueIDThe unique identifier of this MyClass instance.@Error !EnvironFailureThrows an Error during instantiation if the localenvironment is configured incorrectly.@String (uniqueIDA unique identifier to instantiate with.*/
Feel free to document a type as being a pointer or array.
/** @struct NodeA linked list node.@member/Node* previousPrevious Node in the chain.@member/Node* nextNext Node in the chain.@member/String payloadData stored by this node in the chain.*/
You can easily crosslink to any other defined Component using the normal markdown link syntax. If you start a crosslink path with a delimiter, the target will be rooted to the current module scope.
Furthermore, every defined Component is also a valid type, and the same rule applies when starting a type path with a delimiter.
/** @module MyModuleA simple module.*//** @class MyClassA simple class.*//** @property/Function clone@argument/.MyClass sourceThe [MyClass](.MyClass) instance to clone.@returns/MyModule.MyClassThe fresh [MyClass](MyModule.MyClass) instance.*/
Documents and Spares
You may Declare a Component any number of times. Child Components and documentation accumulates in the order in which it is loaded.
/** @class MyClassSome information about MyClass.*//** @class MyClassSome (more) information about MyClass.*/
Available exclusively as an Inner Declaration,
@load allows you to pull in an external markdown
document. Because in loaded docs it's valuable to support html hash links , i.e.
[more info](#more-info), it is impossible to properly support localized paths when using
Your links will be scoped to the global namespace and any type link starting with a delimiter will
This example is taken directly from the
doczar doc comments.
/** @module doczarSelect, load and parse source files for `doczar`-formatdocumentation comments. Render html output to aconfigured disk location.@spare READMEThis is the rendered output of the `doczar` sourcedocumentation. *View the [source]() on GitHub!*@load./README.md*/
In the first stage of rendering, the markdown document(s) on a Component are moved into new
instances. The normal documentation appearing after a Declaration is moved to the path
~summary is used when a Component is displayed on another Component's output page,
~details is used on a Component's own page. If you choose to manually specify only one of
these two paths, all accumulated documentation not associated with a
@spare will default to the
unspecified path. When both paths are specified, unassociated documentation is appended to
There is no limit to how many spares a Component may have, however their titles are subject to normal namespace restrictions (sorry).
/** @class FooClassBasic information.@spare detailsDetailed information.*//** @class FooClassMore basic information.*//** @class BarClassDetailed information.@spare summaryBasic information.*//** @class BarClassMore detailed information.*/
The Inner Declarations
@returns are used to
describe Functions. During parsing, these Components have special scoping which is designed to help
intuitively document an entire Function in one tag. Never forget that this special scope only
affects these Component types exclusively. The scope will be immediately reset by the first
Here is a simple Function Declaration with
@returns declarations. You may name
your arguments and return values, or not.
/** @property/Function doTheDewDo the Dew until you can't even.@argument/Number volumeVolume of Dew to do, in fluid ounces.@argument/String methodHow to do the Dew.@returns/String messageReturns a hip phase, such as "Totally radical!!!".*/
/** @property/Function sortItemsA sorting function for Item instances.@argument/ItemThe first Item.@argument/ItemThe second Item.@returns/Number-1, 0, or 1.*/
Keyword arguments are as easy as replacing
/** @property/Function tellParrotJokeRepeat some Monty Python jokes about a parrot.@kwarg/String parrotTypeType of parrot to joke about.*/
@callback Declaration expands the
@argument scope in order to document the callback
Function's arguments. You may reclose this scope with any unnamed
@returns Declaration. You may
name your callbacks, or not.
/** @property/Function loadDefinitionsLoad definition file from the remote server.@argument/String hostnameURL of the remote server.@callback@argument/Error|undefined errorIf a fatal Error prevented the file frombeing loaded properly, it is passed tothe callback.@argument/Buffer|undefined definitionsFileThe loaded definitions file, or `undefined`if an Error occured.@returns@argument/Boolean devLogging@optionalActivate development-mode logging messages.*/
Although I've never seen this pattern used, it is possible to document multiple (pythonic)
@returns Declarations on a
@callback. You can still close the scope manually with a blank
/** @property/Function getJiggyWithItGet jiggy with it.@callback onErrorCalled if a fatal Exception occured.@returns/function responseActionWhat to do about the Exception.@returns/Number priorityHow important this reaction is.@returns@callback onSuccessCalled if we got jiggy successfully.@argument/Number jigginessLevelMaximum level of jigginess achieved.*/
If you're writing an overloaded function with multiple signatures or need to document special
permutations of optional arguments,
@signature is there for you. It redefines the return value and
argument signature and documents the signature separately.
When you create a
@signature with an Inner Declaration, the scope rules for Functions and
@argument Components apply.
/** @property/Function writeBufferInterprets the contents of a Buffer as UTF-8and writes it in the sky with smoke signals.@signature/Number (content)Write out the entire Buffer and return thenumber of bytes written.@signature/Number|undefined (content, bytes)Write up to `bytes` bytes of text from`content`. If there is content remaining,returns the number of unwritten bytes.@argument/Buffer contentText content to skywrite.@argument/Number bytesLimit output to a set number of bytes.*/
Signatures may be declared in their own comments.
/** @signature writeBuffer (content, bytes)Write up to `bytes` bytes of text from `content`.If there is content remaining, returns the numberof unwritten bytes.
You may also define a signature with value types. These types have no additional implications, they are only displayed in the documentation (and crosslinked).
/** @property/Function writeOutput information through the Morse telegram interface.@argument contentThe content to send.@signature (String content)Send the content as ascii text, followed by `STOP`.@signature (Number content)Convert the number to ascii text and send, followedby `STOP`.@signature (Array<String> content)Send each message, delimited and terminated with`STOP`.*/
Signatures cannot be inherited or overridden individually.
To inherit static and member properties from another Component of any type, use the
/** @class BaseClassA simple base class.@Function createDefaultCreate and return a default instance.@returns/.BaseClass@Function #toStringProduce a String representation of this instance.*//** @class SubClassA simple subclass.@Function #toStringOverrides `BaseClass#toString`.*/
If a Component with a superclass also has at least one value type that is exactly
"Function", it will also inherit arguments, signatures, return values and thrown exceptions.
Java interfaces are also supported, with
/** @interface UniversalRemoteThe common interface for a universal remote control.@member/Function volumeUpIncrease speaker volume.@member/Function volumeDownDecrease speaker volume.*//** @class Tamtung_Model042_3@implements .UniversalRemote@member/Function volumeUpIncrease speaker volume.@member/Function volumeDownDecrease speaker volume.*/
Events and Errors
Document events with the
@event declaration. Pass information with your Event by attaching
/** @class ElementAn HTML DOM Element.@event clickSent when a user presses down and releases thesame mouse button within the bounding box of thisElement, without exceeding the host browser'sminimum threshold for [drag](Element+drag) events.Unless cancelled, this event bubbles upward andoccurs in parent Elements until the `document` isreached.@argument/MouseEventThe originating mouse event.*/
Cases which cause exceptions to be thrown may be documented with the simple Declaration
You may name your exception cases, or not.
""" @class dictA hash map of Strings to untyped references."""""" @member/function dict#getRetrieve a reference.@throws/KeyError notFoundFailure to find a key results in an exception.@throws/TypeErrorIf the key reference does not implement`__hash__`, a TypeError is raised."""
specify any number of generic types on any type path, including with the use of multiple types and
/** @property/Array<String>|Object<String, String>|undefined fooPropAn Array of Strings, an Object mapping Strings to Strings, or undefined.*/
Generics in Class Declarations.
/** @class Container<Object elemType>A container of arbitrarily-typed references.@function #get@argument/String elemNameThe name of the element to get.@returns/%elemType|nullThe requested element, or `null`.*/
There is standard library coverage for ES6. Call
doczar with the
--with es6 option.
iojs standard libraries will pull in ES6 documentation.
Several additional tricks were added to
doczar itself to support the documentation of
Symbols are supported inline everywhere normal paths are supported. You may use either absolute or locally rooted paths in Symbols.
/** @module MainPackage *//** @class FooListAn Iterable collection of Foos.@member/Function [Symbol.iterator]Create an [Iterator]() that lists all our Foos.@property/Symbol staticSymbolA Symbol stored statically on the FooList class.*//** @member/String FooList#[.FooList.staticSymbol]A String stored on FooList instances, mapped to astatic symbol.*/
/** @class Foo@root@property/Symbol alfaA static Symbol mapped to a String.@property/Symbol [.alfa]A static Symbol mapped to a static Symbol.@property/Symbol [.[.alfa]]Another static Symbol mapped to a static Symbol.@member/String [.[.[.alfa]]]A String mapped to a static Symbol.*/
Rest and Spread
To document use of the
rest keyword or "spread" syntax to accept arbitrary numbers of arguments,
/** @member/Function Foo#methodAlfaA method that takes at least one argument.@argument/String firstArgumentThe first, mandatory argument.@args/Number restArgumentsAn arbitrary number of additional arguments.*/
The MIT License (MIT)
Copyright (c) 2015 Kevin "Schmidty" Smith
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.