Skip to content

Commit fdaff83

Browse files
committed
es5 fallback
1 parent f2134dc commit fdaff83

6 files changed

Lines changed: 581 additions & 2 deletions

File tree

es5/cli-options.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
'use strict';
2+
3+
exports.definitions = [{
4+
name: 'src',
5+
alias: 'f',
6+
type: String,
7+
multiple: true,
8+
defaultOption: true,
9+
description: 'A list of javascript source files (or glob expressions) to parse for documentation. If this option is not set jsdoc-parse will wait for source code on stdin (i.e. `cat *.js | jsdoc-parse <options>`).',
10+
typeLabel: '[underline]{file} ...'
11+
}, {
12+
name: 'private',
13+
alias: 'P',
14+
type: Boolean,
15+
description: 'Include identifiers marked @private in the output'
16+
}, {
17+
name: 'html',
18+
alias: 'H',
19+
type: Boolean,
20+
description: 'Enable experimental parsing of .html files'
21+
}, {
22+
name: 'conf',
23+
type: String,
24+
typeLabel: '[underline]{file}',
25+
description: 'Jsdoc config file.'
26+
}, {
27+
name: 'sort-by',
28+
type: String,
29+
multiple: true,
30+
alias: 's',
31+
description: 'Sort by one of more properties, e.g. `--sort-by kind category`. Defaults to `[ "scope", "category", "kind", "order" ]`. Pass the special value `none` to remove the default sort order. ',
32+
typeLabel: '[underline]{property} ...'
33+
}, {
34+
name: 'stats',
35+
type: Boolean,
36+
description: 'Print a few stats about the doclets parsed'
37+
}];
38+
39+
exports.usage = {
40+
title: 'jsdoc-parse',
41+
description: 'Jsdoc-annotated source code in, JSON format documentation out.',
42+
forms: ['$ jsdoc-parse [-[bold]{PH}] [[bold]{--sort-by} [underline]{fields}] [[bold]{--src} [underline]{file} ...]', '$ jsdoc-parse [bold]{--help}', '$ jsdoc-parse [bold]{--stats}'],
43+
optionNameStyles: 'bold'
44+
};

es5/jsdoc-parse.js

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
'use strict';
2+
3+
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
4+
5+
var cp = require('child_process');
6+
var path = require('path');
7+
var util = require('util');
8+
var a = require('array-tools');
9+
var o = require('object-tools');
10+
var fs = require('fs');
11+
var mfs = require('more-fs');
12+
var fileSet = require('file-set');
13+
var Transform = require('stream').Transform;
14+
var cliOptions = require('./cli-options');
15+
var os = require('os');
16+
17+
module.exports = jsdocParse;
18+
jsdocParse.cliOptions = cliOptions.definitions;
19+
20+
var ParseOptions = function ParseOptions() {
21+
_classCallCheck(this, ParseOptions);
22+
23+
this.src = null;
24+
25+
this.private = false;
26+
27+
this.stats;
28+
29+
this.html = false;
30+
31+
this['sort-by'] = ['scope', 'category', 'kind', 'order'];
32+
};
33+
34+
function jsdocParse(options) {
35+
options = o.extend(new ParseOptions(), options);
36+
var src = options.src;
37+
38+
if (src) {
39+
var inputFiles = fileSet(src);
40+
src = inputFiles.files;
41+
42+
var output = new OutputTransform(options);
43+
44+
if (!src.length) {
45+
var msg = util.format('[jsdoc-parse] please specify valid input files. ');
46+
if (inputFiles.notExisting) {
47+
msg += 'These files do not exist: ' + inputFiles.notExisting.join(', ');
48+
}
49+
50+
process.nextTick(function () {
51+
output.emit('error', new Error(msg));
52+
});
53+
} else {
54+
getJsdocOutput(src, options, function (err, data) {
55+
if (err) {
56+
output.emit('error', err);
57+
} else {
58+
output.end(data);
59+
}
60+
});
61+
}
62+
return output;
63+
} else {
64+
var inputStream = new Transform();
65+
var inputFilePath = mfs.getTempFilePath() + '.js';
66+
67+
var buf = new Buffer(0);
68+
inputStream._transform = function (chunk, enc, done) {
69+
if (chunk) buf = Buffer.concat([buf, chunk]);
70+
done();
71+
};
72+
inputStream._flush = function (done) {
73+
var self = this;
74+
fs.writeFileSync(inputFilePath, buf);
75+
getJsdocOutput([inputFilePath], options, function (err, data) {
76+
if (err) {
77+
done(err);
78+
} else {
79+
try {
80+
data = applyOptions(data, options);
81+
self.push(data);
82+
self.push(null);
83+
done();
84+
} catch (err) {
85+
done(err);
86+
}
87+
}
88+
mfs.deleteFile(inputFilePath);
89+
});
90+
};
91+
return inputStream;
92+
}
93+
}
94+
95+
function OutputTransform(options) {
96+
Transform.call(this);
97+
this.json = new Buffer(0);
98+
this._transform = function (chunk, enc, done) {
99+
if (chunk) this.json = Buffer.concat([this.json, chunk]);
100+
done();
101+
};
102+
this._flush = function () {
103+
try {
104+
this.json = applyOptions(this.json, options);
105+
} catch (err) {
106+
err.message += ' [Problem parsing the JSON data output by jsdoc, input data: ' + this.json.toString().substr(0, 100) + ']';
107+
return this.emit('error', err);
108+
}
109+
this.push(this.json);
110+
this.push(null);
111+
};
112+
}
113+
util.inherits(OutputTransform, Transform);
114+
115+
function getJsdocOutput(src, options, done) {
116+
var jsdocTemplatePath = path.resolve(__dirname, '..', 'lib');
117+
var jsdocPath = path.resolve(__dirname, '../node_modules/.bin/jsdoc');
118+
119+
if (!fs.existsSync(jsdocPath)) {
120+
throw Error('jsdoc-parse: cannot find jsdoc: ' + jsdocPath);
121+
}
122+
var args = [jsdocPath, '--pedantic', '-t', jsdocTemplatePath];
123+
if (options.html) {
124+
args = args.concat(['-c', path.resolve(__dirname, 'default-conf.json')]);
125+
} else if (options.conf) {
126+
args = args.concat(['-c', path.resolve(options.conf)]);
127+
}
128+
args = args.concat(src);
129+
130+
var outputFilePath = os.tmpdir() + '/jsdoc-stdout.json';
131+
var outputFile = fs.openSync(outputFilePath, 'w');
132+
var outputStderrPath = os.tmpdir() + '/jsdoc-stderr.json';
133+
var outputStderr = fs.openSync(outputStderrPath, 'w');
134+
var handle = cp.spawn('node', args, { stdio: [process.stdin, outputFile, outputStderr] });
135+
handle.on('error', done);
136+
handle.on('close', function (code) {
137+
if (code) {
138+
var output = fs.readFileSync(outputStderrPath, 'utf8');
139+
fs.unlinkSync(outputFilePath);
140+
fs.unlinkSync(outputStderrPath);
141+
done(new Error(output));
142+
} else {
143+
var output = fs.readFileSync(outputFilePath, 'utf8');
144+
fs.unlinkSync(outputFilePath);
145+
fs.unlinkSync(outputStderrPath);
146+
done(null, output);
147+
}
148+
});
149+
}
150+
151+
function applyOptions(data, options) {
152+
data = JSON.parse(data.toString());
153+
if (options.stats) {
154+
return JSON.stringify(getStats(data), null, ' ') + '\n';
155+
} else {
156+
data = data.filter(function (item) {
157+
if (options.private) {
158+
return item.ignore === undefined;
159+
} else {
160+
return item.ignore === undefined && item.access !== 'private';
161+
}
162+
});
163+
164+
if (options['sort-by'] && !a(options['sort-by']).contains('none')) {
165+
data = sort(data, options['sort-by']);
166+
}
167+
return JSON.stringify(data, null, ' ') + '\n';
168+
}
169+
}
170+
171+
function getStats(data) {
172+
var stats = {
173+
identifiers: {}
174+
};
175+
var kinds = ['module', 'class', 'constructor', 'mixin', 'member', 'namespace', 'constant', 'function', 'event', 'typedef', 'external'];
176+
kinds.forEach(function (kind) {
177+
stats.identifiers[kind] = a(data).where({ kind: kind }).pluck('longname').val();
178+
});
179+
console.log(stats);
180+
return stats;
181+
}
182+
183+
function sort(array, sortBy) {
184+
var order = {
185+
kind: ['class', 'constructor', 'mixin', 'member', 'namespace', 'constant', 'function', 'event', 'typedef', 'external'],
186+
scope: ['global', 'instance', 'static', 'inner']
187+
};
188+
189+
if (!sortBy) {
190+
return array;
191+
} else {
192+
return a.sortBy(array, sortBy, order);
193+
}
194+
}

es5/publish.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
'use strict';
2+
3+
var o = require('object-tools');
4+
var a = require('array-tools');
5+
var transform = require('./transform');
6+
7+
exports.publish = function (data) {
8+
var query = { '!undocumented': true, '!kind': /package|file/ };
9+
var json = a.where(data().get(), query);
10+
11+
json = json.map(transform.setIsExportedFlag);
12+
json = json.map(transform.setCodename);
13+
json = transform.insertConstructors(json);
14+
15+
json = json.map(function (identifier) {
16+
identifier = transform.setID(identifier);
17+
18+
identifier = transform.removeQuotes(identifier);
19+
identifier = transform.cleanProperties(identifier);
20+
identifier = transform.buildTodoList(identifier);
21+
identifier = transform.extractTypicalName(identifier);
22+
identifier = transform.extractCategory(identifier);
23+
identifier = transform.extractChainable(identifier);
24+
identifier = transform.extractCustomTags(identifier);
25+
identifier = transform.setTypedefScope(identifier);
26+
identifier = transform.renameThisProperty(identifier);
27+
identifier = transform.removeMemberofFromModule(identifier);
28+
return identifier;
29+
});
30+
31+
var exported = a.where(json, { isExported: true });
32+
var newIDs = a.pluck(exported, 'id');
33+
34+
newIDs.forEach(function (newID) {
35+
transform.update(json, { isExported: undefined, '!kind': 'module' }, function (identifier) {
36+
return transform.updateIDReferences(identifier, newID);
37+
});
38+
});
39+
40+
json = json.filter(function (identifier) {
41+
var parent = a.findWhere(json, { id: identifier.memberof });
42+
if (parent && parent.isEnum) {
43+
return false;
44+
} else {
45+
return true;
46+
}
47+
});
48+
49+
json = json.map(transform.removeUnwanted);
50+
json = json.map(transform.sortIdentifier);
51+
52+
json.forEach(function (identifier, index) {
53+
identifier.order = index;
54+
});
55+
56+
console.log(JSON.stringify(json, null, ' '));
57+
};

0 commit comments

Comments
 (0)