/foodoc

A Bootstrap and Handlebars based JSDoc3 template.

Primary LanguageJavaScriptGNU General Public License v3.0GPL-3.0

FooDoc: Responsive bootstrap template for JSDoc

FooDoc is a Bootstrap and Handlebars based template for JSDoc3. A big thanks must go out to DocStrap as it served as the inspiration for this project.

This project began as a simple modification of DocStrap. Removing the Bootswatch support in favor of my own CSS customizations but it ended up with me re-writing pretty much the entire template, even switching out the template engine to Handlebars.

Modifications on this fork

See Changelog below for information on changes for this fork.

Features

  • Right side Table of Contents which auto hides on pages it's not required on.
  • Basic themeing is supported through the systemColor option and if required further customizations can be supplied using the stylesheets and scripts options.
  • Integrated offline search across all doclets and there members (excludes source files).
  • Syntax highlighting using Prism .
  • Breadcrumbs on every page for easy navigation.
  • Handlebars template engine using precompiled templates to generate documentation.
  • Extended tutorial configuration through the standard .json file approach supported by JSDoc allowing you to supply a structure as well as title and summary info for tutorials.
  • Configurable navbar links including support for larger systems by switching to list pages with the inlineNav option instead of the usual drop downs.
  • Responsive design, the generated documentation works across both desktop and mobile devices thanks to Bootstrap.
  • Makes use of the JSDoc @summary tag where appropriate, this tag now also supports markdown syntax.
  • Ability to nest generated code documentation into "tutorial" menus for a clean menu layout (adjusts crumbs and links accordingly)
  • Optionally adds Mermaid. This allows for markdown in both code and tutorials using the mermaid language specifier..

What it looks like

As this started off as a DocStrap modification I've used it's fixtures code to generate the sample documentation so you can compare the differences between the two.

NOTE: The fixtures code doesn't make use of the @summary tag when describing it's members so it may look a little sparse.

Ooooh, I want it! How do I get it?

At this time, this fork is not in NPM. Until that happens, you must get the source directly from GitHub. One easy answer is to set up your package.json to have a reference to the NPM package https:\\github.com\cmidgley\foodoc.

When using grunt, please look at grunt-jsdoc which you can use with FooDoc.

Command line example

jsdoc -c path/to/conf.json -t ./node_modules/foodoc/template -R README.md -r .

The -c sets the config, the options you can supply in the templates object are listed below in the options.

The -t sets the template. This is the option you need to set to get the FooDoc template to be used.

The -R sets a markdown file to be the front page of the documentation.

The -r tells jsdoc to run recursively.

The . says from current directory.

Configuring the template

FooDoc ships with a conf.json file in the template/ directory. It is just a regular old JSDoc configuration file, but with the following new options:

"templates": {
    "systemName"            : "{string}",
    "systemSummary"         : "{string}",
    "systemLogo"            : "{string}",
    "pageLogo"              : "{string}",
    "systemColor"           : "{string}",
    "footer"                : "{string}",
    "copyright"             : "{string}",
    "includeDate"           : "{boolean}",
    "includeClass"          : "{boolean}",
    "includeGeneratedBy"    : "{boolean}",
    "removeInheritedStubs"  : "{boolean}",
    "removeInheritedPrivate": "{boolean}",
    "dateFormat"            : "{string}",
    "inlineNav"             : "{boolean}",
    "inverseNav"            : "{boolean}",
    "navMembers"            : "{array.<object>}",
    "linenums"              : "{boolean}",
    "showTableOfContents"   : "{boolean}",
    "expandTableOfContents" : "{boolean}",
    "showAccessFilter"      : "{boolean}",
    "defaultFilterInherited": "{boolean}",
    "defaultFilterPublic"   : "{boolean}",
    "defaultFilterProtected": "{boolean}",
    "defaultFilterPrivate"  : "{boolean}",
    "includeMermaid"        : "{boolean}",
    "includeClassDiagrams"  : "{boolean}",
    "analytics"             : "{object}",
    "noRobots"              : "{boolean}",
    "collapseSymbols"       : "{boolean}",
    "methodHeadingReturns"  : "{boolean}",
    "outputSourceFiles"     : "{boolean}",
    "outputSourcePath"      : "{boolean}",
    "sort"                  : "{boolean|string}",
    "search"                : "{boolean}",
    "favicon"               : "{string}",
    "stylesheets"           : "{array.<string>}",
    "scripts"               : "{array.<string>}"
}

Options

  • systemName - "FooDoc" The name of the system being documented. This value is used to generate the home link in the navbar and the page title for the generated README page.
  • systemSummary - "A Bootstrap and Handlebars based JSDoc3 template." The short summary description of the system being documented. This is used as part of the page title for the generated README page.
  • systemColor - "" The primary color used to generate the documentation. This changes the background color of the jumbotron-esque headers on every page, the primary callout border and header colors, the TOC link colors and various other small highlights.
  • systemLogo - "" A small 40x40 pixel image to used in the navbar along with the systemName to create the home link.
  • pageLogo - "" A scaling logo (responsive) of at least 100x100 shown on the right side of the page banner bar (below menu, by titles)
  • footer - "" Additional content to place in the footer element of each page before the copyright and default generated by messages. This can contain HTML.
  • copyright - "FooDoc Copyright © 2016 The contributors to the JSDoc3 and FooDoc projects." A copyright message to display in the footer of each page throughout the documentation. This can contain HTML.
  • includeDate - true Whether or not the date is included as part of the generated by message.
  • dateFormat - Do MMM YYYY If includeDate is true this is the format used to display the date. This makes use of moment.js so any format it supports should be supported here.
  • includeClass - true If the "Class" section should be shown on class pages, which can be redundant with augmented/inherited class lists
  • includeGeneratedBy - true If the page footer should include the "generated by" commentary
  • removeInheritedStubs - false JSDoc by default generates stubs for various inherited classes, such as #InheritedClasss#MyClass. Setting this to true will remove them from the generated documentation.
  • removeInheritedPrivate - true JSDoc by default generates documentation for private methods/members in subclasses, so this option (default on) removes those from documentation to avoid confusion on usage of private members in subclasses.
  • inlineNav - false If your system is quite large the navbar drop downs just don't look good, setting this option to true changes these drop downs to instead just be a link to a list page.
  • inverseNav - true Bootstrap navbars support an inverse mode, this toggles that option for the documentation navbar with true being the dark version.
  • navMembers This option allows you to specify which kinds of documents appear in the navbar, give them a title and provide a short summary which is then used as part of the inlineNav option to generate the list pages. The following shows the default values for this option, you can remove from this array but cannot add new kinds without altering the template. If no documents are registered for a specific kind it is not added to the navbar.
    [
        {"kind": "class", "title": "Classes", "summary": "All documented classes."},
        {"kind": "external", "title": "Externals", "summary": "All documented external members."},
        {"kind": "global", "title": "Globals", "summary": "All documented globals."},
        {"kind": "mixin", "title": "Mixins", "summary": "All documented mixins."},
        {"kind": "interface", "title": "Interfaces", "summary": "All documented interfaces."},
        {"kind": "module", "title": "Modules", "summary": "All documented modules."},
        {"kind": "namespace", "title": "Namespaces", "summary": "All documented namespaces."},
        {"kind": "tutorial", "title": "Tutorials", "summary": "All available tutorials."}
    ]
  • outputSourceFiles - true Whether or not to output pretty printed source file documentation that is linked to from other documents.
  • outputSourcePath - true When outputSourceFiles is false, you may still want to name the file even without a link to the pretty printed output. Set this to true when outputSourceFiles is false. outputSourceFiles when true takes precedence over this setting.
  • linenums - true When true, line numbers will appear in any pretty printed source code blocks. If outputSourceFiles is true this will add an additional link to all documented members pointing to the exact line number in the pretty printed source file the documentation was pulled from.
  • showTableOfContents - true When true, a TOC is generated from all H1, H2, H3 and H4 headings in the generated pages, this includes the README and tutorial pages. If you want to disable this for specific tutorial pages you can set this same option per tutorial in the extended tutorial configuration.
  • expandTableOfContents - false When showTableOfContents is enabled, by default it shows the contents collapsed and as you scroll into each section it auto-expands. Setting this to true will expand all sections in the table of contents without requiring scrolling into the area. This causes all member and method names, as well as H4 level markdown, to be shown all the time.
  • showAccessFilter - true When true, a checkbox list is displayed allowing the user to toggle the visibility of inherited, public, protected and private symbols of the current doclet. Each checkbox will only be displayed if the doclet contains at least one symbol of that type. If there is only a single type available across the entire doclet the filter is not displayed at all.
  • defaultFilterInherited - true When showAccessFilter is enabled, this determines if the default filter setting enables showing inherited members.
  • defaultFilterPublic - true When showAccessFilter is enabled, this determines if the default filter setting enables showing public members.
  • defaultFilterProtected - false When showAccessFilter is enabled, this determines if the default filter setting enables showing protected members.
  • defaultFilterPrivate - false When showAccessFilter is enabled, this determines if the default filter setting enables showing private members.
  • includeMermaid - false When true, includes Mermaid which allows for doing flowcharts, class diagrams and more from within your documentation and rendered onto the pages.
  • includeClassDiagrams - false When true automatically generates Mermaid class diagrams for all classes. Must also set includeMermaid for drawings to be rendered.
  • analytics - {"ua": "", "domain": ""} Adds a Google Analytics code block to the template output e.g. "analytics":{"ua":"UA-XXXXX-XXX", "domain":"XXXX"}
    • ua The google agent (see Google Analytics help for details)
    • domain The domain being served. (see Google Analytics help for details)
  • noRobots - false When true adds metatag to all page headers to disable robots (google, etc) from indexing the content.
  • collapseSymbols - true When true, symbols in generated pages (methods, members, type definitions, etc.) are collapsed so only there title and summary are visible. You can then click on them to reveal more detailed information.
  • methodHeadingReturns - true When true, method headings will contain the return type if one exists.
  • sort - "linenum, longname, version, since" Specifies the sort order of the symbols on a page. They will still be grouped under there own headings (Classes, Members, Methods, etc.) but within these groups they are sorted using the supplied value. By default this sorts symbols first by where they were found in the original source code, then by there longname, then by there version and lastly by there since tag.
  • search - true Whether or not to enable the lunr search component.
  • favicon - "" An image or favicon that will be used as favicon.
  • stylesheets - [] An array of stylesheet urls to include in every page.
  • scripts - [] An array of script urls to include in every page.

Extended tutorial configuration

JSDoc supports providing a .json file in your tutorials directory to configure the hierarchical structure and title for tutorials. This template adds two new options to each tutorial in this file.

  • summary A short summary of the tutorial which is used in various places throughout the documentation, most notably in the page header of the tutorial itself.
  • showTableOfContents A boolean value indicating whether or not to generate the Table of Contents for this specific tutorial.
  • replaceWithCodeMenus A boolean value that indicates if the code menus (Class, Modules, ...) should be moved from the top menu bar and instead replace this tutorial item with those menus. You still need an empty markdown file that matches the name as JSDocs requires it.
  • url A string value that if included replaces the normal document link with a specific URL. This can be used to link to third party sites. You still need an empty markdown file that matches the name as JSDocs requires it.

The following shows what the tutorials.json in the fixtures test code contains.

NOTE: The array based syntax for child tutorials is not supported at present and children must be supplied as properties of an object.

{
  "brush-teeth": {
    "title": "Brush Teeth",
    "summary": "How to brush your teeth!",
    "children": {
      "fence-test": {
        "title": "Fence Test",
        "summary": "Testing syntax highlighting.",
        "showTableOfContents": false
      }
    }
  },
  "drive-car": {
    "title": "Drive Car",
    "summary": "How to drive a car!",
    "children": {
        "include-docs": {
            "replaceWithCodeMenus": true
        },
        "GitHub": {
            "title": "Fork on GitHub",
            "summary": "Help improve this project and fork on GitHub",
            "url": "https://github.com/cmidgley/foodoc"
        }
    }
  }
}

Syntax highlighting

FooDoc uses Prism to provide syntax highlighting and supports a couple of ways to specify which language to use.

  • The standard markdown syntax is supported.

    ```html
    <html></html>
    ```
  • Or when using an @example tag in your comments you can add a custom inner tag {@lang languageName} where languageName is one of the default languages supported by Prism (Markup, CSS, C-Like and JavaScript languages are supported by default). You can add this tag anywhere within an @example tags body but keep in mind that there is no white-space processing performed when it is removed prior to rendering.

    /**
     * @example {@lang html}<html></html>
     */

If you need to use a language provided by a Prism plugin you will need to fork the template and add in the specific language yourself. Take a look at the Prism documentation to see a full list of all 119 supported languages.

Mermaid graphics drawings

You can include graphics images of many things, including class diagrams (inclujding automatically generated from your source), flow charts, entity-relationship diagrams and more. This is implemented using a markdown-like language supported by Mermaid.

  • JSDoc comments can use markdown with the Mermaid language specifier followed by mermaid-syntax for drawings. Here is an example within source code documentation:
      /**
      * Example of how a flowchart works
      * 
      * ```mermaid
      *   graph TD;
      *     A-->B;
      *     A-->C;
      *     B-->D;
      *     C-->D;
      * ```
      */
      
    which will render: flowchart and here is an example using it in a tutorial markdown:
    ```mermaid
          classDiagram
              InheritedClass <|-- BaseClass
              AmazingClass <|-- InheritedClass
              SimpleClass <|-- BaseClass
      ```
    which will render: class diagram
  • Classes can automatically generate class diagrams (requires the generateClassDiagrams option), including members, super-classes (with members) and sub-classes (name only)

If you are hand-crafting Mermaid syntax, a great tool to use when building it is the Mermaid Live Editor.

To enable, you must make sure your conf.json file is configured correctly (see the example file template/conf.json):

  • Under "template: {...} you must specify at least one of these options to enable Mermaid:
    • "includeMermaid": true will set up Mermaid, but it will not generate class diagrams automatically for you.
    • "generateClassDiagram": true will cause all class pages to automatically include a class diagram, will auto-set includeMermaid: true.
  • Under "plugins: {...} you must be using the markdown plugin:
    "plugins": [
        "plugins/markdown"
    ]

Quick debugging tip: If you set "includeMermaid": false, the Mermaid markdown will render in the browser so you can verify that it's working, and can view source and copy/paste it over to the Mermaid Live Editor to test.

FAQ

Why another template?

Over the years I have tried quite a few templates available for JSDoc and none of them produced a look I was quite happy with. Some got close like DocStrap, but I still wasn't quite satisfied so I did what all developers do eventually, roll their own. I really liked the clean look of the Bootstrap 3 documentation so I used it as base for the layout and styling for this template.

Why Handlebars?

Personal preference really, Underscore templates work great but due to there ability to have basically any JavaScript in them I've noticed a lot logic which should be handled elsewhere creep into them overtime. It's simply easier to hack it into the template than find where it should be implemented as part of the post processing.

What's different from DocStrap's search?

The lunr search implementation in DocStrap performs all the indexing in the browser using a hidden iframe, this was done to allow the search to work offline when viewing the documentation via the file:// protocol. It does however have the drawback of loading and then indexing what could potentially be a large numbers of documents, on every page load.

While this works I took a different approach and decided to generate the search index and store as part of the documentation process and output the results in two files lunr-data.json and lunr-data.js. These two files are then consumed by the search component when required. The lunr-data.json file is fetched via ajax request if the documentation is served via http:// or https:// protocols while the lunr-data.js file is simply included into the page when using the file:// protocol as you can't perform ajax requests. This ultimately provides us with two primary benefits over DocStrap's implementation:

  1. All indexing of documents is performed only once, when the documentation itself is generated. Due to creating the index directly from the JSDoc doclets it contains more detailed information, including information on members, methods and type definitions, leading to better search results where you can click on a method name and be taken directly to it's documentation.
  2. The index and store information is only loaded into the page when a user performs a search, this greatly improves load speeds.

The following shows the lunr index fields implemented by this template:

var index = lunr(function(){
    this.field('longname', {boost: 1000});
    this.field('name', {boost: 500});
    this.field('tags', {boost: 300});
    this.field('kind', {boost: 110});
    this.field('title', {boost: 100});
    this.field('summary', {boost: 70});
    this.field('description', {boost: 50});
    this.field('body');
    this.ref('id');
});
  • longname This is basically a doclet id and is the fully qualified name of a documented symbol. e.g. MyApi.utils.fetch or MyApi.Class#fetch. This has the highest weighting of 1000 as if someone types in the exact longname it should be the first result!
  • name This is the short or "friendly" name of a doclet, using the two examples from above (MyApi.utils.fetch or MyApi.Class#fetch) they would both have the same name of fetch.
  • tags This is a space delimited string of any tags generated for the doclet. At present this simply provides multiple variations of the longname to aid in searching, for example the longname MyApi.utils#fetch would be added to the tags as the following; utils#fetch fetch.
  • kind This is the kind or type of the doclet (class, namespace, function, etc.).
  • title This is the page title the doclet uses when generating a page.
  • summary This is the HTML sanitized doclet summary, in the case of a tutorial or the readme this is the summary value supplied through either the extended configuration or options.
  • description This is the HTML sanitized doclet description.
  • body This is the full text of the main content section of the generated HTML for the doclet. Any matches against this have the lowest possible weighting.

Why Prism instead of Sunlight?

Quite simply Sunlight is no longer maintained and while it does work I prefer Prism which is actively maintained and follows HTML5 standards.

Getting started with the source code

The most important tools to understand, or at least know about and research as needed, are:

  • JSDoc: Obviously...!
  • Handlebars: This is the template engine used. The templates are located in src\tmpl, and the JavaScript support code is in src\utils.
  • TaffyDB: This is the database used by JSDoc, and all doclets are held in there. You can generally find this database as template.raw.data

This project requires building to be used, as the .js/.css/.hbs/etc files are pre-processed, using Grunt (with build commands also located in package.json).

  • The examples and templates directories are built from grunt. If you run the clean command, they will be removed which can make finding source and browsing the structure easier.
  • If you change source (under src) it will not be used until you build (such as the default grunt build, template, or all). Processes all the source into the templates directory.
  • Running templates builds just the templates, whereas default and all (and several others) also runs JSDoc on the test-src directory and outputs this into the examples directory.
  • The templates directory is pushed to GitHub, but examples is not. This means that after making changes, you should run one of the build options that generates templates, and push those back to GitHub to use them.

To Do

  • Refactor and document the template source code. Now that I know how it all works I can slim down source code and then heavily document it so I can use it as the example documentation.

Changelog

All releases prior to 1.0.0 are considered pre-release, i.e. I'm not finished changing stuff yet so anything can happen ;)

0.10.0 (on cmidgley/foodoc fork)

  • Adds several formatting features, including page header logos, several fixes to the styles, optional "generated by" content
  • Optionally removes the inherited class stubs, which IMHO clutters the documentation
  • Optionally removes the "Class" section from generated document, which is mostly redundant with the inherited/Augments section
  • Renamed several items, including "Tutorials" are now "Resources" (more generic), and Augments is now Inherits
  • Improved responsive design, especially on mobile devices
  • Changed filter to be responsive and stick to the top
  • Adds the ability to embed the generated code documentation (classes, functions, etc) within a "tutorial" style menu
  • Fixes several problems, including errors with latest JQuery and "constructor" error loading default json files
  • Several style changes, including default color, hiding the document "kind" (README, CLASS, etc), and lots of style changes throughout. All can be overridden with personal stylesheets, and all have comments in the CSS files (except color changes)
  • Adds support for Mermaid when includeMermaid: true is used. See [Mermaid](#Mermaid graphics drawings) for more information on configuration and use.
  • Adds support for automatically generating class diagrams based on classes and members when includeClassDiagrams: true is used.
  • Adds settings for how the access filter should default, using new options defaultFilterInherited, defaultFilterPublic, defaultFilterProtected, and defaultFilterPrivate. Default is protected and private unchecked.
  • Auto-expands hidden sections (when collapseSymbols is enabled) when page loads and anchor tag references a hidden section

0.0.9

  • Fixed issue with the footer option not rendering HTML as it was intended.
  • Fixed the missing global.html issue.
  • Updated the copyright option to also allow HTML in it's content.
  • Updated the _navbar.hbs so that if an item has no members it is simply rendered as a link instead of an empty dropdown.
  • Updated the base CSS to apply a background color to the <html/> element that matches the footer. This stops the page looking 'incomplete' or 'broken' as there is no longer any whitespace below the footer.

0.0.8

  • Updated the navbar dropdowns and the table of contents to handle long lists. If the list exceeds the viewport it now displays a scrollbar. (@mistic100)
  • Fixed missing Google Analytics code in the _layout.hbs. (@mistic100)
  • Added the favicon option allowing you to supply a path to an image or icon to use as the favicon for the documentation. (@mistic100)
  • Added the showAccessFilter option which allows users to filter the symbols of a doclet in real-time by if they are inherited, public, protected or private.

0.0.7

  • Fixed Prism CSS conflict with .namespace class.
  • Updated Gruntfile to compile and minify all used prism files (including customized plugins) into single includes.
  • Added in the Prism Normalize Whitespace plugin to perform some additional processing to clean up any extra whitespace in examples.

0.0.6

  • Replaced Sunlight syntax highlighter with Prism as it is maintained and it's just generally better.

0.0.5

  • Updated TOC to align with crumbs.
  • Fixed anchor-links not showing on hover.
  • Updated the search input size to match the TOC.

0.0.4

  • Added missing {@run } javascript and css as well as some additional styling for related tutorials.

0.0.3

  • Fixed page symbols not generating details correctly when displayed as primary header.

0.0.2

  • Fixed missing moment.js dependency in the npm package.
  • Added .npmignore to exclude the generated examples directory.
  • Updated the lunrHelper.js to write files directly to the output directory instead of to the template/static one and then copying it across.

0.0.1

  • Initial check in of template.