/
whatsupdoc
executable file
·250 lines (207 loc) · 6.06 KB
/
whatsupdoc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
#!/usr/bin/env node
'use strict';
var swig = require('swig');
var fs = require('fs');
var config = require('./config');
var fileHelper = require('./file-helper');
var fileFinder = require('./file-finder');
var patternFinder = require('./pattern-finder');
var docBlocks = require('./doc-blocks');
var util = require('./util');
var path = require('path');
var fs = require('fs');
// global settings
var settings = {};
var directory;
/**
* @name init
* @description Initialize global settings. This is done automatically,
* but you can call it again in case you screwed something up.
* @param {String} [dir] The directory to be scanned.
* @public
*/
var init = function (dir) {
if (dir) {
directory = dir;
}
// set defaults
settings = config.getConfig(dir);
};
/**
* @description generate the API docs
* @method go
* @param {String} [dir = process.cwd()]
* @public
* @return {DocBlock[]} blocks The blocks used to generate
* the documentation.
*/
var go = function (dir) {
var files,
blocks,
stringifiedBlocks;
init(dir);
// find the files
util.log('searching', directory);
util.log('excluding', settings.exclude);
files = fileFinder.getFiles(directory, 'js', settings.exclude);
// find the blocks in each
blocks = getDocBlocksFromFiles(files);
blocks = getPublicBlocks(blocks);
util.log('found %d blocks in %d files', blocks.public.length, files.length);
stringifiedBlocks = stringify(blocks);
writeResults(stringifiedBlocks);
util.log('finished writing documentation\n');
return blocks;
};
/**
* @name writeResults
* @description Writes the api doc string into the
* destination file.
* @param {String} results
* @private
*/
var writeResults = function (results) {
var destinationFile = path.join(directory, settings.outputFile);
var destinationText = fileHelper.readFileSync(destinationFile);
var newText = insertDocs(destinationText, results);
fs.writeFileSync(destinationFile, newText);
};
/**
* @name insertDocs
* @description Inserts docs at the proper place into another string.
* This will replace old docs if found.
* @param {String} target the string docs will be inserted into
* @param {String} docs
* @return {String} updated the updated target
* @private
*/
var insertDocs = function (target, docs) {
var regex = /<!--- whatsupdoc-start(\n|.)+whatsupdoc-end -->\n/g;
if (regex.test(target)) {
target = target.replace(regex, docs);
} else {
target += docs;
}
return target;
};
/**
* @name getPublicBlocks
* @description group blocks by privacy
* @param {DocBlock[]} blocks
* @return {Object}
*/
var getPublicBlocks = function (blocks) {
var grouped = {
'public': []
};
util.each(blocks, function (block) {
if (block.privacy === 'public') {
grouped.public.push(block);
}
});
return grouped;
};
/**
* @description get the DocBlocks from an Array of files
* @function getDocBlocksFromFiles
* @param {String[]} filePaths
* @return {DocBlock[]}
* @private
*/
var getDocBlocksFromFiles = function (filePaths) {
var i, max, result = [];
var getBlocks = function (rawBlocks, filePath) {
var blocks = [];
util.each(rawBlocks, function (block, i) {
blocks.push(
new docBlocks.DocBlock(block, filePath)
);
});
return blocks;
};
util.each(filePaths, function (filePath) {
var rawBlocks = patternFinder.findPattern(settings.docBlockRegex, filePath);
result = result.concat(getBlocks(rawBlocks, filePath));
});
return result;
};
/**
* @description get the result of bunch of
* stringified DocBlocks
* @function stringify
* @param {Object} groupedBlocks
* @return {String}
* @private
*/
var stringify = function (groupedBlocks) {
var result = '';
var templateFilePath = path.join(__dirname, settings.template);
var template = swig.compileFile(templateFilePath);
var stringified = {};
var blockTemplate = getBlockTemplate();
util.each(groupedBlocks, function (blocks, privacy) {
var str = '';
util.each(blocks, function (block) {
str += block.stringify(blockTemplate);
});
stringified[privacy] = str;
});
return template({
'public': stringified.public
});
};
/**
* @name getBlockTemplate
* @description Get the file to use for generating block templates.
* Check working directory and, if not found, use the default.
* @return {String} template the file path of the template to use
* @private
*/
var getBlockTemplate = function () {
var tmplName = settings.blockTemplate;
var blockTemplate = path.join(path.join(process.cwd(), directory), tmplName);
if (!fs.existsSync(blockTemplate)) {
blockTemplate = path.join(__dirname, tmplName);
}
return blockTemplate;
};
/**
* @name configure
* @description Get/set global settings. If no args, return all settings.
* If just name, return that setting. If name & value, set that setting.
* @param {String/Object} [name] setting name - Optionally pass a an Object
* to set multiple values at once.
* @param [value]
* @public value setting value
* @return {Object/String/Number/Boolean} setting Depending on what args
* were passed, this can return all settings as an Object or one setting's
* value.
*/
var configure = function (name, value) {
var result,
args = arguments.length;
if (args === 1) {
if (!(name instanceof Object)) {
result = settings[name];
} else {
util.each(name, function (value, key) {
settings[key] = value;
});
}
} else if (args === 2) {
settings[name] = value;
}
return result === undefined ? settings : result;
};
// ================================================
// TODO: Figure out a better way to determine if
// this is being used from CLI or required in
// another script.
var dir = process.argv[2];
if (dir && dir !== '--reporter') {
go(dir);
} else {
exports.init = init;
exports.configure = configure;
exports.go = go;
}