Creating Docma Templates


Docma parses JSDoc comments into a Javascript object and builds a SPA (Single Page Application) from the given template. The documentation data is then passed to this styled template within the DocmaWeb instance which is globally available as docma object.

Markdown files are converted to HTML files and created in the same destination directory. The generated application essentially consists of web files that mainly make use of Dust.js internally.

Table of Contents:

Template Structure


Docma templates are node modules with a template directory at the root and a package.json. Below shows the simplest structure for a Docma template module.

🗂 <root>                              Required
   ├── 📃 package.json                    ✔︎     Node.js package definition.
   ├── 📃 index.js                              Optional main file for the Node module.
   ├── 🗂 template/                       ✔︎     Directory that contains web application files.
   │   ├── 📃 index.html                  ✔︎     Main entry point for the web-app. Defined by `mainHTML`.
   │   ├── 🗂 partials/                   ✔︎     Dust.js partials to be compiled.
   │   │   ├── 📃 docma-api.html          ✔︎     Partial for displaying API documentation data.
   │   │   ├── 📃 docma-content.html            Partial for displaying converted markdown and other HTML.
   │   │   └── 📃 docma-404.html                Partial for 404 - Not Found error page.
   │   ├── 🗂 js/
   │   ├── 🗂 css/
   │   └── ...
   ├── 📃 README.md
   ├── 📃 LICENSE
   ├── ...
   :

For a real example, you can check out the default template, Zebra.

Configuration


Configuring package.json

The name of the node package should have docma-template- prefix. For instance, package name of the default template is docma-template-zebra.

Other than name and version, a template module's package.json should have description, repository, license, author and peerDependencies.docma fields defined.

peerDependencies.docma value should indicate a Docma version range that the template supports. Since template modules are introduced with Docma version 2.0.0, a proper example would be ">=2.0.0".

All other fields are optional within package.json.

Below is a simple example for a package.json. (In this case, template is named "Unicorn" and authored by "John Doe".)

{
  "name": "docma-template-unicorn",
  "version": "1.0.0",
  "description": "Unicorn - Docma Template",
  "repository": "john-doe/docma-template-unicorn",
  "license": "MIT",
  "author": "John Doe <[email protected]>",
  "files": [
    "template/",
    "LICENSE"
  ],
  "keywords": [
    "docma",
    "template"
  ],
  "peerDependencies": {
    "docma": ">=2.0.0"
  }
}

Note that Docma is mentioned only within peerDependecies. You should not install a peer dependency with your template module. It will be already required by NPM when the user installs your template.

Template Configuration

All template configuration is optional and should either be defined by a docmaTemplate field in package.json or within a main JS file of the module.

Config Type Default Description
mainHTML String "index.html" Name of the main HTML file which is the entry point of the templated web app.
ignore Array undefined List of files or directories to be ignored when the template files are copied over to the output destination. Globs allowed.
defaultOptions Object undefined Template-specific default options. This object will be merged with the template options defined at build-time.

To include template-specific configuration, add the following to your package.json:

{
    ...
    "docmaTemplate": {
        "mainHTML": "main.html",
        "ignore": [],
        "defaultOptions" = {
            "title": "Docs",
            "header": true,
            // other default options specific to your templated web app
        }
    }
    ...
}

Hooking into Build Process

Template configuration does not include any build configuration. If you need to hook into the documentation build process, you can include a main JS file in your template module.

— Add the following to your package.json:

{
    ...
    "main": "index.js",
    "files": [
        "template/",
        "index.js",
        "LICENSE"
    ],
    ...
}

— Add an index.js file (can be any name) as the module entry point:

'use strict';

module.exports = (template, modules) => {

    // Docma passes the following modules to this template module for your convenience.
    // _, Promise, fs, dust, HtmlParser, utils

    // In this example, we'll only make use of Promise (bluebird) module.
    const { Promise } = modules;

    // Set template main HTML file (default is "index.html")
    template.mainHTML = 'main.html';

    // Template default options.
    template.defaultOptions = {
        title: 'Docs',
        header: true
        // other options specific to your templated web app
    };

    // ignore files relative to /template directory. other files in the root of the module directory are already ignored.
    template.ignore = [];

    // optionally run some code before the build has started.
    template.preBuild(() => {
        // do some sync or async stuff
        return Promise.resolve();
    });

    // optionally run some code after the build has ended.
    template.postBuild(() => {
        // do some sync or async stuff
        template.debug.log('bla bla');
    });
};

Initializing a Template with Docma CLI

You can also use Docma CLI to initialize a new Docma template project. This will generate most files required to author a template; including a main JS file for your module; as shown above in the example.

cd path/to/new-template
docma template init

After or while you're developing your template module, you can use the command below to diagnose your template.

docma template doctor

Templated Web App


HTML

<root>/template/index.html is the default entry point of the generated web application. It should not include any Dust templates, but can of course, include other custom HTML.

It should also include a <div id="docma-main"></div> which all the Dust templates will be compiled into. If you don't define this element, it will be created and dynamically appended to the body of the document.

Example main file (index.html is the default file name):

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
    </head>
    <body>
        <div id="docma-main"></div>
        <div id="my-footer"></div>
    </body>
</html>

An empty body would also be valid but we want the footer to come after docma-main element. So it's explicitly defined.

Note that title of the document is not set. Since this is a template, title will be defined at build time and <title> element will be automatically added to the output document. See Build Configuration.

Partials

Put all Dust.js partials in <root>/template/partials directory.

You can have sub directories within <root>/template/partials but all HTML files in these directories will be treated as if they were at the same level (under <root>/template/partials directory). For example, if you have a template at <root>/template/partials/widgets/menu.html, you should still include it like this: {>"menu"/} not {>"widgets/menu"/} or {>"partials/widgets/menu"/}. That's why all partials should have unique names.

These HTML files under <root>/template/partials are pre-compiled into Javascript and will be included as Dust JS templates. Note that this directory will not be copied over to output directory.

API Documentation Partial

You should include a (documentation) partial and name it docma-api.html. This partial is required and, will be compiled and loaded into your main HTML (i.e. index.html), when navigated. All JSDoc generated documentation data should be displayed within this partial. JSDoc data is accessible via docma.documentation (array). Since docma is global, within a partial you can iterate documentation symbols/items by {#documentation}..{/documentation}.

A simple example for docma-api.html partial:

{>"menu"/}
{#documentation}
    <h4 id="{.|$id}">{longname}</h4>
    <p>{description}</p>
{/documentation}
{>"footer"/}

Content Partial

In order to include other HTML content in the generated output (such as markdown files converted to HTML); you can also create another partial called docma-content.html. This is optional (and will be auto-generated). However, you should always create one for the template, for better layout and style, since the auto-generated partial will have a very basic layout.

Content partial should include a <div id="docma-content"></div> in itself. Docma will load the target content into this element.

This partial will also be compiled and loaded into in your main HTML, when navigated; so all styles and scripts of the main file will still be available.

A simple example for docma-content.html partial:

{>"menu"/}
<div id="docma-content"></div>
{>"footer"/}

DocmaWeb Core

When you build the documentation with your template, a docma-web.js will be generated (and linked in your main HTML); which is the core engine for the documentation web app. This will include everything the app needs such as the documentation data, compiled partials, dustjs engine, etc... (Note that the size of this script depends especially on the generated documentation data.)

See Docma Web API.

Custom Scripts

You have full control over the main HTML file so you can include any Javascript files in it. DocmaWeb core will always be prepended before your scripts; so that you can safely access the global docma object.

Initializing the Web App

In order to make sure you execute some script after Docma is ready:

// run this in any js file in the browser
docma.once('ready', function () {
    // initialize your code here
    // this runs only once
});

The ready event will only be fired once, right after the initial load. To execute some code after each content or page is rendered, you should use the render event instead.

// run this in any js file in the browser
docma.on('render', function (currentRoute) {
    if (!currentRoute) {
        console.log('Page not found!');
        return;
    }
    if (currentRoute.type === DocmaWeb.Route.Type.API) {
        // route generated for JSDoc documentation
        console.log('This is an API documentation route.');
    } else {
        // route generated for markdown/HTML content
        console.log('This is a content route.');
    }
});

CSS

You can include any .css files, anywhere in your template. Since you have control over the main HTML file, you can link any stylesheet in it. As a convention, place all .css files under <root>/template/css.

Other Files

You can include any custom files anywhere under <root>/template directory. They will be copied over into the output directory. If you need to include a file in the template but don't want it to be in the generated output; define it within the ignore option.

Example Template


Docma includes a built-in default template. For an example, you can take a look at its repository or read the details on how to build documentation with the default template, Zebra.