template-helper-apidocs
Version:
Template helper for automatically generating API docs from code comments. This is based on helper-apidocs, but specifically for applications built-with the Template library.
114 lines (97 loc) • 2.82 kB
JavaScript
/**
* Module dependencies
*/
var fs = require('fs');
var path = require('path');
var glob = require('globby');
var bindHelpers = require('template-bind-helpers');
var comments = require('js-comments');
var relative = require('relative');
var isGlob = require('is-glob');
var clone = require('clone-deep');
var merge = require('mixin-deep');
var fileCache = {};
/**
* Generate API docs from code comments for any JavaScript
* files that match the given `patterns`. Note that **only code
* comments with `@api public` will be rendered.**
*
* **Example**
*
* ```js
* apidocs("index.js");
* ```
*
* @param {String} `patterns` Glob patterns for files with code comments to render.
* @param {Object} `options` Options to pass to [js-comments].
* @return {String} Markdown-formatted API documentation
* @api public
*/
module.exports = function apidocs(patterns, opts) {
var options = (this && this.options) || {};
opts = merge({}, options, options.apidocs, opts);
opts.file = opts.file || {};
opts.dest = opts.dest || 'README.md';
opts.cwd = opts.cwd || process.cwd();
var delims = opts.escapeDelims || ['<%%=', '<%='];
var files = cache(patterns, opts);
var len = files.length, i = 0;
var res = '', context = {};
if (this && this.app) {
opts = bindHelpers(this.app, opts, false);
opts.examples = this.app.cache.data.examples || {};
context = this.context;
}
while (len--) {
var fp = files[i++];
var str = fs.readFileSync(fp, 'utf8');
var arr = comments.parse(str, opts);
var checked, n = 0;
arr = filter(arr, opts, checked, n);
var ctx = clone(opts);
ctx.file = ctx.file || {};
ctx.file.path = normalize(ctx.file.path, fp, opts.dest);
ctx.data = context;
res += comments.render(arr, ctx);
}
res = comments.format(res);
if (this && this.app) {
res = res.split(delims[0] || '<%%=').join('__DELIM__');
res = this.app.render(res, opts);
res = res.split('__DELIM__').join(delims[1] || '<%=');
}
return res;
};
function cache(patterns, opts) {
opts = opts || {};
var key = patterns.toString();
if (fileCache.hasOwnProperty(key)) {
return fileCache[key];
}
var files = isGlob(patterns)
? glob.sync(patterns, opts)
: [patterns];
files = files.map(function (fp) {
return path.join(opts.cwd, fp);
});
return (fileCache[key] = files);
}
function normalize(fp, fallback, dest) {
fp = fp || fallback;
if (fp.indexOf('//') === -1) {
return relative(dest, fp);
}
return fp;
}
function filter(arr, opts, checked, n) {
return arr.filter(function (ele, i) {
n = n || 0;
if (!checked && /Copyright/.test(ele.description) && i === 0) {
checked = true;
n++;
}
if (opts.skipFirst && i === n) return false;
return true;
});
}
;