kung-foodoc
v0.7.0
Published
A Bootstrap 5 and Handlebars based JSDoc 4 template.
Maintainers
Readme
Kung FooDoc
A Bootstrap 5 and Handlebars based template for JSDoc 4.
Fork of FooDoc by Steve Usher, inspired by DocStrap.
Features
- Right side Table of Contents which auto hides on pages it's not required on.
- Basic themeing is supported through the
systemColoroption and if required further customizations can be supplied using thestylesheetsandscriptsoptions. - 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
.jsonfile 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
inlineNavoption instead of the usual drop downs. - Responsive design, the generated documentation works across both desktop and mobile devices thanks to Bootstrap 5.
- Makes use of the JSDoc
@summarytag where appropriate, this tag now also supports markdown syntax.
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.
- The default template options
- The template with the
inlineNavoption set totrue - The template using the
systemLogoandsystemColoroptions - The template with the
collapseSymbolsoption set tofalse
I want it! How do I get it?
If you manage your own version of jsdoc:
npm install kung-foodocCommand line example
jsdoc -c path/to/conf.json -t ./node_modules/kung-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 JSDoc configuration file, but with the following new options:
"templates": {
"systemName" : "{string}",
"systemSummary" : "{string}",
"systemLogo" : "{string}",
"systemColor" : "{string}",
"footer" : "{string}",
"copyright" : "{string}",
"includeDate" : "{boolean}",
"dateFormat" : "{string}",
"inlineNav" : "{boolean}",
"inverseNav" : "{boolean}",
"navMembers" : "{array.<object>}",
"linenums" : "{boolean}",
"showTableOfContents" : "{boolean}",
"showAccessFilter" : "{boolean}",
"analytics" : "{object}",
"collapseSymbols" : "{boolean}",
"methodHeadingReturns" : "{boolean}",
"outputSourceFiles" : "{boolean}",
"outputSourcePath" : "{boolean}",
"sourceRootPath" : "{string}",
"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.systemLogo -
""A small 40x40 pixel image to used in the navbar along with thesystemNameto create the home link.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.footer -
""Additional content to place in the footer element of each page before thecopyrightand 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 -
trueWhether or not the date is included as part of the generated by message.dateFormat -
Do MMM YYYYIfincludeDateis true this is the format used to display the date. This makes use of dayjs so any format it supports should be supported here.inlineNav -
falseIf 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 -
trueBootstrap navbars support an inverse mode, this toggles that option for the documentation navbar withtruebeing 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
inlineNavoption 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 -
trueWhether or not to output pretty printed source file documentation that is linked to from other documents.outputSourcePath -
falseWhenoutputSourceFilesisfalse, you may still want to name the file even without a link to the pretty printed output. Set this totruewhenoutputSourceFilesisfalse.outputSourceFileswhentruetakes precedence over this setting.sourceRootPath -
nullThe root path to strip from source file paths when generating source links. Whennull, the common prefix of all source file paths is computed automatically. Set this if the automatic detection doesn't produce the desired result.linenums -
trueWhentrue, line numbers will appear in any pretty printed source code blocks. IfoutputSourceFilesistruethis 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 -
trueWhentrue, a TOC is generated from allH1,H2,H3andH4headings 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.showAccessFilter -
trueWhentrue, 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.analytics -
nullAdds 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)
collapseSymbols -
trueWhentrue, 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 -
trueWhentrue, 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 -
trueWhether or not to enable the lunr search component.favicon -
nullAn 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.
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!"
}
}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.
<pre>```html
<html></html>
```</pre>Or when using an
@exampletag in your comments you can add a custom inner tag{@lang languageName}wherelanguageNameis 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@exampletags 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.
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 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:
- 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.
- 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');
// documents are added during index construction (lunr 2.x)
documents.forEach(function (doc) { this.add(doc); }, this);
});- longname
This is basically a doclet id and is the fully qualified name of a documented symbol. e.g.
MyApi.utils.fetchorMyApi.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.fetchorMyApi.Class#fetch) they would both have the same name offetch. - 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#fetchwould 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.
Source Code as Documentation
The template source code in src/ is heavily documented and can serve as example documentation for how FooDoc works:
src/publish.js- Entry point; documents the three-phase pipeline (configure, postProcess, publish).src/utils/template.js- Core orchestrator; documents configuration, data access, and the publishing lifecycle.src/utils/docletHelper.js- Per-doclet field computation; documents signatures, titles, params, examples, and access filter logic.src/utils/postProcessor.js- Doclet registration and enrichment; documents the two-pass processing pipeline and navbar building.src/utils/handlebarsHelper.js- Handlebars helpers; documents rendering, detail rows, callouts, and the symbol-kinds abstraction.src/utils/lunrHelper.js- Search indexing; documents the build-time/runtime search architecture.src/tmpl/- Every.hbstemplate has a block comment explaining its role, which blocks it overrides, and how data flows through it.src/static/js/- Frontend components (TOC, search, access filter, symbols, examples) are documented with JSDoc.
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.4.0
- Removed unused
disablePackagePathtemplate option. - Fixed
outputSourcePathdefault documented astruewhen code default wasfalse. - Documented previously undocumented
sourceRootPathtemplate option. - Audited all 26 template options for correct usage and documentation.
0.3.0
- Refactored
tag/_details.hbsfrom 251 lines to 24 using new detail-row Handlebars helpers. - Refactored
site/_layout.hbssecondary symbol sections from 9 repetitive blocks to a single{{#each (symbol-kinds)}}loop. - Refactored
access-filter.jsfrom 4 duplicate methods to a single parameterized_setAccess()factory. - Added comprehensive JSDoc documentation to all 5
src/utils/modules (template, docletHelper, postProcessor, handlebarsHelper, lunrHelper). - Added block comments to all 12
.hbstemplates explaining their role, overridable blocks, and data flow. - Documented
publish.jsentry point and frontend JS components. - Net reduction of ~300 lines of template source code with no functional changes.
0.2.0
- Migrated from JSDoc 3 to JSDoc 4.0.5.
- Migrated from Bootstrap 3 to Bootstrap 5.3.8.
- Replaced Bootstrap Icons with Phosphor Icons via CDN.
- Replaced moment.js (deprecated) with dayjs.
- Replaced TaffyDB compatibility layer for JSDoc 4's @jsdoc/salty.
- Replaced grunt-jsdoc with a custom Grunt task for JSDoc 4 support.
- Updated lunr from 1.x to 2.x (immutable index built at generation time).
- Updated cheerio, sanitize-html, handlebars, prismjs, jQuery, and all Grunt plugins.
- Removed
extendandmomentdependencies in favor of native alternatives. - Introduced CSS custom properties (
--fd-*) for theming;systemColornow sets a single variable. - Improved access filter with visual feedback (checked/unchecked states, empty state messages).
- Resolved all critical and high security vulnerabilities.
