1 | (function () {
|
2 |
|
3 | var dfm = require('./dfm');
|
4 | var manager = require('./itemManager');
|
5 | var itemHandler = require('./itemHandler');
|
6 | var config = null;
|
7 | var base = '_yamlGeneratorOutput';
|
8 | var globalUid = 'global';
|
9 | var uidPrefix = '';
|
10 | var yamlMime = '### YamlMime:UniversalReference';
|
11 | var outputFileExt = '.yml';
|
12 | var jsdocConfigPath = '_jsdocConfTemp.json';
|
13 | var packageName = '';
|
14 |
|
15 | function setSourceInfo(item, doclet) {
|
16 | if (config.repo) {
|
17 | var path = doclet.meta.path.replace(env.pwd + '\\', '') + '\\' + doclet.meta.filename;
|
18 | if (path.split('\\').length > 2) {
|
19 | path = path.split('\\').splice(2).join('\\');
|
20 | }
|
21 | item.source = {
|
22 | id: item.id,
|
23 | path: path,
|
24 | startLine: doclet.meta.lineno,
|
25 | remote: {
|
26 | branch: config.repo.branch,
|
27 | path: path,
|
28 | repo: config.repo.url
|
29 | }
|
30 | };
|
31 | }
|
32 | }
|
33 |
|
34 | function getClasses(classes, fileMap) {
|
35 | manager.items.forEach(function (item) {
|
36 | switch (item.type) {
|
37 | case 'Class':
|
38 | classes[item.uid] = {
|
39 | items: [item],
|
40 | referenceMap: {}
|
41 | };
|
42 | fileMap[item.uid] = item.uid;
|
43 | break;
|
44 | case 'Constructor':
|
45 | case 'Function':
|
46 | case 'Member':
|
47 | var parentId = item.parent || globalUid;
|
48 | var parent = classes[parentId];
|
49 | if (parent === undefined) {
|
50 | console.log(parentId + ' is not a class, ignored.');
|
51 | break;
|
52 | }
|
53 | parent.items.push(item);
|
54 | if (parentId === globalUid) {
|
55 | (parent.items[0].children = parent.items[0].children || []).push(item.uid);
|
56 | }
|
57 | fileMap[item.uid] = parentId;
|
58 | (item.syntax.parameters || []).forEach(function (p) {
|
59 | (p.type || []).forEach(function (t) {
|
60 | classes[parentId].referenceMap[t] = true;
|
61 | });
|
62 | });
|
63 | if (item.syntax.return) {
|
64 | (item.syntax.return.type || []).forEach(function (t) {
|
65 | classes[parentId].referenceMap[t] = true;
|
66 | });
|
67 | }
|
68 | break;
|
69 | }
|
70 | });
|
71 | return classes;
|
72 | }
|
73 |
|
74 | function serializeIndex(classes) {
|
75 | var serializer = require('js-yaml');
|
76 | var fs = require('fs');
|
77 | if (!fs.existsSync(base)) {
|
78 | fs.mkdirSync(base);
|
79 | }
|
80 |
|
81 | var index = {
|
82 | items: [{
|
83 | uid: packageName,
|
84 | name: packageName,
|
85 | langs: ['js'],
|
86 | type: 'package',
|
87 | summary: '',
|
88 | children: []
|
89 | }],
|
90 | references: []
|
91 | };
|
92 |
|
93 | if (Object.keys(classes).length <= 1) {
|
94 | console.log('Nothing extracted for ' + packageName);
|
95 | return;
|
96 | }
|
97 |
|
98 | for (var id in classes) {
|
99 | var classItem = classes[id];
|
100 | if (id === globalUid) {
|
101 | for (var i = 1; i < classItem.items.length; i++) {
|
102 | index.items[0].children.push(classItem.items[i].uid);
|
103 | index.items.push(classItem.items[i]);
|
104 | }
|
105 | } else {
|
106 | if (classItem.items && classItem.items.length) {
|
107 | index.items[0].children.push(classItem.items[0].uid);
|
108 | index.references.push({
|
109 | uid : classItem.items[0].uid,
|
110 | name : classItem.items[0].name
|
111 | });
|
112 | }
|
113 | }
|
114 | }
|
115 |
|
116 | index = JSON.parse(JSON.stringify(index));
|
117 | fs.writeFileSync(base + '/index.yml', yamlMime + '\n' + serializer.safeDump(index));
|
118 | console.log('index generated.');
|
119 | }
|
120 |
|
121 | function serializeToc(classes, fileMap) {
|
122 | var serializer = require('js-yaml');
|
123 | var fs = require('fs');
|
124 |
|
125 | if (!fs.existsSync(base)) {
|
126 | fs.mkdirSync(base);
|
127 | }
|
128 |
|
129 | var toc = [];
|
130 | for (var id in classes) {
|
131 | var classItem = classes[id];
|
132 |
|
133 | classItem.references = [];
|
134 | for (var r in classItem.referenceMap) {
|
135 | var f = fileMap[r];
|
136 | if (f !== undefined && f !== id) {
|
137 | classItem.references.push({
|
138 | uid: r,
|
139 | name: r.indexOf('.') == -1 ? r : r.substring(r.indexOf('.') + 1),
|
140 | fullName: r,
|
141 | isExternal: f === undefined
|
142 | });
|
143 | }
|
144 | }
|
145 | classItem.referenceMap = undefined;
|
146 | if (classItem.references.length == 0) {
|
147 | classItem.references = undefined;
|
148 | }
|
149 |
|
150 |
|
151 | classItem = JSON.parse(JSON.stringify(classItem));
|
152 |
|
153 |
|
154 | if (id == globalUid) {
|
155 | continue;
|
156 | }
|
157 |
|
158 | var fileName = id.replace(/[ \n\r]/g, '-') + outputFileExt;
|
159 | if (fileName && fileName.split('.').length > 2) {
|
160 | fileName = fileName.split('.').splice(1).join('.');
|
161 | }
|
162 | fs.writeFileSync(base + '/' + fileName, yamlMime + '\n' + serializer.safeDump(classItem));
|
163 | console.log(fileName + ' generated.');
|
164 |
|
165 | var tocItem = {
|
166 | uid: id,
|
167 | name: classItem.items[0].name
|
168 | };
|
169 |
|
170 | toc.push(tocItem);
|
171 | }
|
172 | toc.sort(function (a, b) {
|
173 | var nameA = a.name.toUpperCase();
|
174 | var nameB = b.name.toUpperCase();
|
175 | if (nameA < nameB) {
|
176 | return -1;
|
177 | }
|
178 | if (nameA > nameB) {
|
179 | return 1;
|
180 | }
|
181 |
|
182 | return 0;
|
183 | });
|
184 |
|
185 | fs.writeFileSync(base + '/toc.yml', serializer.safeDump(toc));
|
186 | console.log('toc.yml generated.');
|
187 | }
|
188 |
|
189 | var typeMap = {
|
190 | 'member': itemHandler.handleMember,
|
191 | 'function': itemHandler.handleFunction,
|
192 | 'class': itemHandler.handleClass
|
193 | };
|
194 |
|
195 | exports.handlers = {
|
196 | newDoclet: function (e) {
|
197 | var doclet = e.doclet;
|
198 |
|
199 |
|
200 | if (doclet.memberof !== undefined && manager.itemsMap[uidPrefix + doclet.memberof] === undefined && doclet.kind !== 'class') {
|
201 | return;
|
202 | }
|
203 |
|
204 | if (typeMap[doclet.kind] === undefined) {
|
205 | console.log('unrecognized kind: ' + doclet.kind);
|
206 | return;
|
207 | }
|
208 |
|
209 | if (doclet.memberof === undefined && doclet.kind != 'class' && !(doclet.meta && doclet.meta.code && typeof(doclet.meta.code.name) === 'string' && doclet.meta.code.name.indexOf('exports') == 0)) {
|
210 | return;
|
211 | }
|
212 |
|
213 | if (doclet.kind === 'member' && doclet.scope === 'inner') {
|
214 | return;
|
215 | }
|
216 |
|
217 | if (doclet.access === 'private') {
|
218 | return;
|
219 | }
|
220 |
|
221 | if (doclet.name && doclet.name[0] === '_') {
|
222 | return;
|
223 | }
|
224 |
|
225 |
|
226 | if (doclet.undocumented === true) {
|
227 | return;
|
228 | }
|
229 |
|
230 |
|
231 | if (!doclet.longname) {
|
232 | return;
|
233 | }
|
234 |
|
235 | var item = {
|
236 | uid: uidPrefix + doclet.longname,
|
237 | id: uidPrefix + doclet.longname,
|
238 | parent: (doclet.memberof && doclet.kind !== 'class') ? (uidPrefix + doclet.memberof) : undefined,
|
239 | name: doclet.name,
|
240 | summary: doclet.description ? dfm.convertLinkToGfm(doclet.description, uidPrefix) : dfm.convertLinkToGfm(doclet.summary, uidPrefix)
|
241 | };
|
242 |
|
243 | if (item.parent !== undefined) {
|
244 | var parent = manager.itemsMap[item.parent];
|
245 | (parent.children = parent.children || []).push(item.uid);
|
246 | }
|
247 |
|
248 | item.fullName = (item.parent ? item.parent + '.' : uidPrefix) + item.name;
|
249 |
|
250 |
|
251 | if (doclet.kind === 'class') {
|
252 | setSourceInfo(item, doclet);
|
253 | }
|
254 |
|
255 |
|
256 | if ('tags' in doclet) {
|
257 | item.tags = doclet.tags;
|
258 | }
|
259 |
|
260 | typeMap[doclet.kind](item, doclet, uidPrefix, manager);
|
261 | manager.addItem(item);
|
262 | },
|
263 | parseBegin: function () {
|
264 | var fse = require('fs-extra');
|
265 | config = fse.readJsonSync(jsdocConfigPath);
|
266 |
|
267 | if (config.repo && config.repo.url && !config.repo.url.endsWith('.git')) {
|
268 | config.repo.url = config.repo.url + '.git';
|
269 | }
|
270 |
|
271 |
|
272 | if (config.package) {
|
273 | var packageJson = fse.readJsonSync(config.package);
|
274 | if (packageJson && packageJson.name) {
|
275 | packageName = packageJson.name;
|
276 | globalUid = packageJson.name + '.' + globalUid;
|
277 | uidPrefix = packageJson.name + '.';
|
278 | }
|
279 | }
|
280 | manager.items.push(
|
281 | {
|
282 | uid: globalUid,
|
283 | id: globalUid,
|
284 | name: 'GLOBAL',
|
285 | fullName: 'GLOBAL',
|
286 | type: 'Class',
|
287 | langs: ['js']
|
288 | }
|
289 | );
|
290 | },
|
291 | parseComplete: function () {
|
292 | var classes = {};
|
293 | var fileMap = {};
|
294 | getClasses(classes, fileMap);
|
295 | serializeIndex(classes);
|
296 | serializeToc(classes, fileMap);
|
297 | process.exit(0);
|
298 | }
|
299 | };
|
300 | })();
|