doczar

0.3.4 • Public • Published

doczar

Doczar (pronounced dōzer) is a simple, explicit documentation generator for javascript, python, ruby, java, c-like languages, and others. It is used to generate its own docs.

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.

Features

  • describe modules and object-oriented structures
  • inheritence, multiple inheritence and Java interface
  • 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
1 Installation
2 Shell Usage
3 Development
4 Comment Syntax
5 Components, Types and Paths
6 Documents and Spares
7 Functions
8 Inheritence
9 Events and Errors
10 Generics
11 Javascript ES6
12 LICENSE

Installation

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

Shell Usage

$ doczar --in=src/**/*.c --out docz
$ doczar --jsmod ./main # outputs to ./docs 
option description
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. doczar does not parse directories - you must select files.
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 @development modifier.
api Display only Components marked with the @api modifier.
raw Log events as json strings instead of pretty printing them.
json Create an index.json file in each directory instead of a rendered index.html.
date Explicitly set the datestamp on each page with any Date-compatible string.

Development

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!

Comment Syntax

Declarations

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 MyClass
    For compatibility purposes, c-like comments support any
    number 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.

/** @module BoxFactory */
int myInt = 42/* @local/int myInt */
 
/** @spare ExtraDocs
    These extra documents are part of the
    [BoxFactory](.) module. Their full
    path is `BoxFactory~ExtraDocs`.
*/

A special markdown caveat: you will need two newlines to terminate a bullet list.

/**     @property/Function doTheThings
    Does all the things. It does:
     * the hottest things
     * the coolest things
     * all the things you could ever
        possibly imagine
 
    And it does them fast!
*/

In python, any "triple" string literal that meets the first-line requirements is a document comment.

def referenceMontyPython (skit):
    """     @property/function referenceMontyPython
        Either triple or triple-double is fine.
    """

Ruby users may use =begin and =end with the same rules.

=begin  @module MyRubyGem
    I don't know very much about Ruby.
=end

Finally, HTML comments are also supported.

<!--    @module SplashPage
    Guest 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 foo
    A contracted document with
    little available horizontal
    space that needs a [link]
    (http://google.com) to a
    search engine.
*/

To add a child with a standalone doc comment, simply specify a complex path of any length.

/**     @class FooClass
    A simple class.
*/
/**     @property/Function FooClass.getDefault
    Get a new default instance of FooClass.
*/
/**     @returns/FooClass FooClass.getDefault)defaultInstance
    Returns a new instance with the default configuration.
*/

Inner Declarations

Once you have opened a declaration, you may write additional declarations which will all be scoped to the enclosing comment.

/**     @class MyClass
    A simple class.
@property/Function getAllInstances
    A static Function that returns all instances of MyClass.
@member/Function doSomethingCool
    A member Function on each instance of MyClass.
*/

Modules

In some languages such as Java, the concept of a module is very specific and @module declarations 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.

The @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 @module without 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 Foo
    The Foo module.
*/
/**     @class Bar
    The Foo.Bar class.
*/
/**     @submodule/class Baz
    The Foo:Baz class.
*/
/**     @property/Function createBar
 
*/

Value Types

A value type is declared with a forward slash. Multiple value types are declared with the pipe | character.

/**     @property/String foobar
    A String property called "foobar".
*/
/**     @property/Number|undefined result
    This 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
    @public
    A simple subclass of Lisa's class.
@member/String uniqueID
    @const
    This id String is generated at instantiation and because
    it is constant, it will never give you up, never let you
    down.
*/

Here is a list of the available Modifiers and Flags

Modifiers

  • @development hides this Component unless the --dev flag is used
  • @api reveals this Component and its ancestors when the --api flag is used
  • @optional indicates something which need not exist (usually an argument)
  • @super inherits from a superclass
  • @implements associates an implemented Java interface
  • @default describes a default value. Always use backticks.

Flags

  • @public
  • @protected
  • @private
  • @abstract
  • @final
  • @volatile

Components, Types and Paths

Let's look at all the Components we have available.

Primary Components

These are the only Components which may be used to open a new document comment.

  • @module organizational Component
  • @class instantiable class objects
  • @struct c-like structures
  • @interface Java interface
  • @spare bare markdown document
  • @property static property
  • @member instance property or method
  • @event event descriptions
  • @throws conditions causing an exception to be thrown
  • @enum list of named values

Inner Components

These may only appear inside a document comment opened by a Primary Component Declaration.

  • @argument optionally-named function or event argument
  • @kwarg python-style keyword argument
  • @callback callback function
  • @returns return value
  • @signature an alternate function signature
  • @named a named value in an @enum.

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:

Special Delimiters

  • ~ @spare
  • . @property
  • # @member
  • ( @argument
  • ) @returns
  • ! @throws
  • + @event
  • & @signature

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 @property and @member.

The default delimiter is ".", for @property.

/**     @class MyClass
@Function .getAllInstances
    Load all instances of MyClass.
@Number count
    Total number of instances.
@String #uniqueID
    The unique identifier of this MyClass instance.
@Error !EnvironFailure
    Throws an Error during instantiation if the local
    environment is configured incorrectly.
@String (uniqueID
    A unique identifier to instantiate with.
*/

Feel free to document a type as being a pointer or array.

/**     @struct Node
    A linked list node.
@member/Node* previous
    Previous Node in the chain.
@member/Node* next
    Next Node in the chain.
@member/String[] payload
    Data stored by this node in the chain.
*/

Crosslinking

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 MyModule
    A simple module.
*/
/**     @class MyClass
    A simple class.
*/
/**     @property/Function clone
@argument/.MyClass source
    The [MyClass](.MyClass) instance to clone.
@returns/MyModule.MyClass
    The 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 MyClass
    Some information about MyClass.
*/
/**     @class MyClass
    Some (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 @load. Your links will be scoped to the global namespace and any type link starting with a delimiter will be rejected.

This example is taken directly from the doczar doc comments.

/**     @module doczar
    Select, load and parse source files for `doczar`-format
    documentation comments. Render html output to a
    configured disk location.
@spare README
    This is the rendered output of the `doczar` source
    documentation. *View the [source]
    (https://github.com/shenanigans/node-doczar) on GitHub!*
    @load
        ./README.md
*/

In the first stage of rendering, the markdown document(s) on a Component are moved into new @spare instances. The normal documentation appearing after a Declaration is moved to the path ~summary. When available, ~summary is used when a Component is displayed on another Component's output page, and ~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 ~details.

There is no limit to how many spares a Component may have, however their titles are subject to normal namespace restrictions (sorry).

/**     @class FooClass
    Basic information.
@spare details
    Detailed information.
*/
/**     @class FooClass
    More basic information.
*/
/**     @class BarClass
    Detailed information.
@spare summary
    Basic information.
*/
/**     @class BarClass
    More detailed information.
*/

Functions

The Inner Declarations @argument, @kwarg, @callback, @signature and @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 normal Declaration.

Here is a simple Function Declaration with @argument and @returns declarations. You may name your arguments and return values, or not.

/**     @property/Function doTheDew
    Do the Dew until you can't even.
@argument/Number volume
    Volume of Dew to do, in fluid ounces.
@argument/String method
    How to do the Dew.
@returns/String message
    Returns a hip phase, such as "Totally radical!!!".
*/
/**     @property/Function sortItems
    A sorting function for Item instances.
@argument/Item
    The first Item.
@argument/Item
    The second Item.
@returns/Number
    -1, 0, or 1.
*/

Keyword arguments are as easy as replacing @argument with @kwarg.

/**     @property/Function tellParrotJoke
    Repeat some Monty Python jokes about a parrot.
@kwarg/String parrotType
    Type of parrot to joke about.
*/

Callback Functions

The @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 loadDefinitions
    Load definition file from the remote server.
@argument/String hostname
    URL of the remote server.
@callback
    @argument/Error|undefined error
        If a fatal Error prevented the file from
        being loaded properly, it is passed to
        the callback.
    @argument/Buffer|undefined definitionsFile
        The loaded definitions file, or `undefined`
        if an Error occured.
    @returns
@argument/Boolean devLogging
    @optional
    Activate 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 @returns Declaration.

/**     @property/Function getJiggyWithIt
    Get jiggy with it.
@callback onError
    Called if a fatal Exception occured.
    @returns/function responseAction
        What to do about the Exception.
    @returns/Number priority
        How important this reaction is.
    @returns
@callback onSuccess
    Called if we got jiggy successfully.
    @argument/Number jigginessLevel
        Maximum level of jigginess achieved.
*/

Function Signatures

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 writeBuffer
    Interprets the contents of a Buffer as UTF-8
    and writes it in the sky with smoke signals.
@signature/Number (content)
    Write out the entire Buffer and return the
    number 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 content
    Text content to skywrite.
@argument/Number bytes
    Limit 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 number
    of 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 write
    Output information through the Morse telegram interface.
@argument content
    The 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, followed
    by `STOP`.
@signature (Array<String> content)
    Send each message, delimited and terminated with
    `STOP`.
*/

Signatures cannot be inherited or overridden individually.

Inheritence

To inherit static and member properties from another Component of any type, use the @super modifier.

/**     @class BaseClass
    A simple base class.
@Function createDefault
    Create and return a default instance.
    @returns/.BaseClass
@Function #toString
    Produce a String representation of this instance.
*/
/**     @class SubClass
    A simple subclass.
@Function #toString
    Overrides `BaseClass#toString`.
*/

If a Component with a superclass also has at least one value type that is exactly "function" or "Function", it will also inherit arguments, signatures, return values and thrown exceptions.

Java interfaces are also supported, with @interface and @implements.

/**     @interface UniversalRemote
    The common interface for a universal remote control.
@member/Function volumeUp
    Increase speaker volume.
@member/Function volumeDown
    Decrease speaker volume.
*/
/**     @class Tamtung_Model042_3
    @implements .UniversalRemote
@member/Function volumeUp
    Increase speaker volume.
@member/Function volumeDown
    Decrease speaker volume.
*/

Events and Errors

Document events with the @event declaration. Pass information with your Event by attaching @argument Components.

/**     @class Element
    An HTML DOM Element.
@event click
    Sent when a user presses down and releases the
    same mouse button within the bounding box of this
    Element, without exceeding the host browser's
    minimum threshold for [drag](Element+drag) events.
    Unless cancelled, this event bubbles upward and
    occurs in parent Elements until the `document` is
    reached.
    @argument/MouseEvent
        The originating mouse event.
*/

Cases which cause exceptions to be thrown may be documented with the simple Declaration @throws. You may name your exception cases, or not.

class dict:
    """     @class dict
        A hash map of Strings to untyped references.
    """
    def get (self, key):
        """     @member/function dict#get
            Retrieve a reference.
        @throws/KeyError notFound
            Failure to find a key results in an exception.
        @throws/TypeError
            If the key reference does not implement
            `__hash__`, a TypeError is raised.
        """

Generics

Type paths support generics (java), templates (c++) and arrays-of-things (javascript). You may specify any number of generic types on any type path, including with the use of multiple types and pipes |.

/**     @property/Array<String>|Object<String, String>|undefined fooProp
    An Array of Strings, an Object mapping Strings to Strings, or undefined.
*/

Coming Soon

Generics in Class Declarations.

/**     @class Container<Object elemType>
    A container of arbitrarily-typed references.
@function #get
    @argument/String elemName
        The name of the element to get.
    @returns/%elemType|null
        The requested element, or `null`.
*/

Javascript ES6

There is standard library coverage for ES6. Call doczar with the --with es6 option. Additionally, the browser-strict and iojs standard libraries will pull in ES6 documentation.

Several additional tricks were added to doczar itself to support the documentation of ES6 scripts.

Symbols

Symbols are supported inline everywhere normal paths are supported. You may use either absolute or locally rooted paths in Symbols.

/**     @module MainPackage */
 
/**     @class FooList
    An Iterable collection of Foos.
@member/Function [Symbol.iterator]
    Create an [Iterator]() that lists all our Foos.
@property/Symbol staticSymbol
    A Symbol stored statically on the FooList class.
*/
 
/**     @member/String FooList#[.FooList.staticSymbol]
    A String stored on FooList instances, mapped to a
    static symbol.
*/

The History Channel Presents: Ancient Symbols

/**     @class Foo
    @root
@property/Symbol alfa
    A 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, use the @args declaration.

/**     @member/Function Foo#methodAlfa
    A method that takes at least one argument.
@argument/String firstArgument
    The first, mandatory argument.
@args/Number restArguments
    An arbitrary number of additional arguments.
*/

LICENSE

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.

Dependents (0)

Package Sidebar

Install

npm i doczar

Weekly Downloads

6

Version

0.3.4

License

MIT

Last publish

Collaborators

  • shenanigans