UNPKG

3.41 kBJavaScriptView Raw
1/*!
2 * helper-apidocs <https://github.com/jonschlinkert/helper-apidocs>
3 *
4 * Copyright (c) 2014-2015, Jon Schlinkert.
5 * Licensed under the MIT License.
6 */
7
8'use strict';
9
10/**
11 * Module dependencies
12 */
13
14var path = require('path');
15var glob = require('globby');
16var async = require('async');
17var relative = require('relative');
18var extend = require('extend-shallow');
19var tutil = require('template-utils');
20
21/**
22 * Requires cache
23 */
24
25var requires = {};
26var comments = requires.comments || (requires.comments = require('js-comments'));
27
28/**
29 * Expose `apidocs` helper
30 */
31
32module.exports = apidocs;
33
34/**
35 * `apidocs` helper.
36 */
37/**
38 * Generate API docs from code comments in the JavaScript
39 * files that match the given `patterns`. Only code comments
40 * with `@api public` are rendered.
41 *
42 * @param {String} `patterns`
43 * @param {Object} `options`
44 * @return {String}
45 * @api public
46 */
47
48function apidocs(patterns, options, cb) {
49 // if an object is passed, use the `cwd`
50 if (typeof patterns === 'object' && !Array.isArray(patterns)) {
51 cb = options;
52 options = patterns;
53 patterns = (options && options.cwd) || '*.js';
54 }
55
56 if (typeof options === 'function') {
57 cb = options; options = {};
58 }
59
60 var opts = extend({sep: '\n', dest: 'README.md'}, options);
61 var dest = opts.dest, delims;
62
63 if (dest && dest.indexOf('://') === -1) {
64 dest = relative(dest);
65 }
66
67 opts.cwd = opts.cwd ? path.dirname(opts.cwd) : process.cwd();
68 var app = this && this.app;
69 if (app && app.create) {
70 app.create('apidoc', {isRenderable: true, isPartial: true });
71 delims = opts.delims || app.delims['.*'].original || ['<%', '%>'];
72 }
73
74 // we can't pass the `opts` object to glob because it bugs out
75 glob(patterns, opts, function(err, files) {
76 async.mapSeries(files, function(fp, next) {
77 var res = tutil.headings(comments(fp, dest, opts));
78 // escaped template variables
79 res = tutil.escapeFn(app, delims)(res);
80
81 if (!app) return next(null, tutil.unescapeFn(app)(res));
82
83 app.option('renameKey', function (fp) {
84 return fp;
85 });
86
87
88 app.apidoc({ path: fp, content: res, ext: '.md', engine: '.md' });
89 var file = app.views.apidocs[fp];
90
91 app.render(file, opts, function (err, content) {
92 if (err) return next(err);
93 next(null, tutil.unescapeFn(app)(content));
94 });
95 }, function (err, arr) {
96 if (err) return cb(err);
97 cb(null, arr.join('\n'));
98 });
99 });
100}
101
102apidocs.sync = function(patterns, options) {
103 var opts = extend({sep: '\n', dest: 'README.md'}, options);
104 var dest = opts.dest, delims;
105
106 if (dest && dest.indexOf('://') === -1) {
107 dest = relative(dest);
108 }
109
110 opts.cwd = opts.cwd ? path.dirname(opts.cwd) : process.cwd();
111 var app = this && this.app;
112 if (app && app.create) {
113 app.create('apidoc', {isRenderable: true, isPartial: true });
114 delims = opts.delims || app.delims['.*'].original || ['<%', '%>'];
115 }
116
117 return glob.sync(patterns, opts).map(function (fp) {
118 var res = tutil.headings(comments(fp, dest, opts));
119 res = tutil.escapeFn(app, delims)(res);
120
121 if (!app) { return tutil.unescapeFn(app)(res); }
122
123 fp = relative(fp);
124 app.option('renameKey', function (fp) {
125 return fp;
126 });
127
128 app.apidoc({ path: fp, content: res });
129 var file = app.views.apidocs[fp];
130 return tutil.unescapeFn(app)(app.render(file, opts));
131 }).join('\n');
132};