From 3d8e3f547ea7583c080f8088bb37ff656ee7f97d Mon Sep 17 00:00:00 2001 From: Tom MacWright Date: Mon, 30 Mar 2015 13:24:28 -0400 Subject: [PATCH] Add and test filterAccess stream, integrate into binary. Fixes #38 --- bin/documentation.js | 12 +++- streams/filter_access.js | 22 ++++++ streams/flatten.js | 13 ++-- streams/infer_kind.js | 7 +- streams/normalize.js | 6 +- test/fixture/simple-private.input.js | 11 +++ test/fixture/simple-private.output.custom.md | 0 test/fixture/simple-private.output.json | 47 +++++++++++++ test/fixture/simple-private.output.md | 0 test/streams/filter_access.js | 71 ++++++++++++++++++++ test/streams/flatten.js | 4 +- test/test.js | 3 + 12 files changed, 181 insertions(+), 15 deletions(-) create mode 100644 streams/filter_access.js create mode 100644 test/fixture/simple-private.input.js create mode 100644 test/fixture/simple-private.output.custom.md create mode 100644 test/fixture/simple-private.output.json create mode 100644 test/fixture/simple-private.output.md create mode 100644 test/streams/filter_access.js diff --git a/bin/documentation.js b/bin/documentation.js index 44a7757..bf87c05 100755 --- a/bin/documentation.js +++ b/bin/documentation.js @@ -5,16 +5,25 @@ var documentation = require('../'), json = require('../streams/output/json.js'), normalize = require('../streams/normalize.js'), flatten = require('../streams/flatten.js'), + filterAccess = require('../streams/filter_access.js'), path = require('path'); var yargs = require('yargs') .usage('Usage: $0 [options]') + .alias('f', 'format') - .describe('f', 'output format, of [json, md]') .default('f', 'json') + .describe('f', 'output format, of [json, md]') + .describe('mdtemplate', 'markdown template: should be a file with Handlebars syntax') + + .boolean('p') + .describe('p', 'generate documentation tagged as private') + .alias('p', 'private') + .help('h') .alias('h', 'help') + .example('$0 foo.js', 'parse documentation in a given file'), argv = yargs.argv; @@ -45,5 +54,6 @@ if (!formatter) { documentation(inputs) .pipe(normalize()) .pipe(flatten()) + .pipe(filterAccess(argv.private ? [] : undefined)) .pipe(formatter) .pipe(process.stdout); diff --git a/streams/filter_access.js b/streams/filter_access.js new file mode 100644 index 0000000..4f773a2 --- /dev/null +++ b/streams/filter_access.js @@ -0,0 +1,22 @@ +'use strict'; + +var through = require('through'); + +/** + * Exclude given access levels from the generated documentation: this allows + * users to write documentation for non-public members by using the + * `@private` tag. + * + * @public + * @param {Array} [levels=[private]] excluded access levels. + * @name access + * @return {stream.Transform} + */ +module.exports = function (levels) { + levels = levels || ['private']; + return through(function (comment) { + if (levels.indexOf(comment.access) === -1) { + this.push(comment); + } + }); +}; diff --git a/streams/flatten.js b/streams/flatten.js index c786a48..063224b 100644 --- a/streams/flatten.js +++ b/streams/flatten.js @@ -14,6 +14,7 @@ var through = require('through'), * * `@memberof` * * `@classdesc` * * `@kind` + * * `@access` * * The following tags are flattened to a top-level array-valued property: * @@ -33,8 +34,8 @@ var through = require('through'), * @name flatten * @return {stream.Transform} */ -module.exports = function() { - return through(function(comment) { +module.exports = function () { + return through(function (comment) { var result = extend({}, comment); comment.tags.forEach(function (tag) { @@ -89,14 +90,10 @@ var flatteners = { result.scope = 'inner'; }, 'access': function (result, tag) { - if (tag.access === 'public') { - delete result.access; - } else { - result.access = tag.access; - } + result.access = tag.access; }, 'public': function (result, tag) { - delete result.access; + result.access = 'public'; }, 'protected': function (result, tag) { result.access = 'protected'; diff --git a/streams/infer_kind.js b/streams/infer_kind.js index 329b6ca..e3acecf 100644 --- a/streams/infer_kind.js +++ b/streams/infer_kind.js @@ -3,7 +3,8 @@ var through = require('through'); /** - * Create a transform stream that attempts to infer a `kind` tag from other tags or from the context. + * Create a transform stream that attempts to infer a `kind` tag from other + * tags or from the context. * * @name inferKind * @return {stream.Transform} @@ -11,7 +12,9 @@ var through = require('through'); module.exports = function () { return through(function (comment) { function hasTag(title) { - return comment.tags.some(function (tag) { return tag.title === title; }); + return comment.tags.some(function (tag) { + return tag.title === title; + }); } if (!hasTag('kind')) { diff --git a/streams/normalize.js b/streams/normalize.js index 9d35f3b..ac6e36d 100644 --- a/streams/normalize.js +++ b/streams/normalize.js @@ -45,7 +45,9 @@ var through = require('through'), */ module.exports = function () { return through(function (comment) { - this.push(extend({}, comment, { tags: comment.tags.map(normalize) })); + this.push(extend({}, comment, { + tags: comment.tags.map(normalize) + })); }); }; @@ -75,4 +77,4 @@ var synonyms = { function normalize(tag) { var canonical = synonyms[tag.title]; return canonical ? extend({}, tag, { title: canonical }) : tag; -}; +} diff --git a/test/fixture/simple-private.input.js b/test/fixture/simple-private.input.js new file mode 100644 index 0000000..6b347cf --- /dev/null +++ b/test/fixture/simple-private.input.js @@ -0,0 +1,11 @@ +/** + * This function returns the number plus two. + * + * @param {Number} a the number + * @returns {Number} numbertwo + * @private + */ +function returnTwo(a) { + // this returns a + 2 + return a + 2; +} diff --git a/test/fixture/simple-private.output.custom.md b/test/fixture/simple-private.output.custom.md new file mode 100644 index 0000000..e69de29 diff --git a/test/fixture/simple-private.output.json b/test/fixture/simple-private.output.json new file mode 100644 index 0000000..52c05cb --- /dev/null +++ b/test/fixture/simple-private.output.json @@ -0,0 +1,47 @@ +[ + { + "description": "This function returns the number plus two.", + "tags": [ + { + "title": "param", + "description": "the number", + "type": { + "type": "NameExpression", + "name": "Number" + }, + "name": "a" + }, + { + "title": "returns", + "description": "numbertwo", + "type": { + "type": "NameExpression", + "name": "Number" + } + }, + { + "title": "private", + "description": null, + "type": null + }, + { + "title": "name", + "name": "returnTwo" + } + ], + "context": { + "loc": { + "start": { + "line": 8, + "column": 0 + }, + "end": { + "line": 11, + "column": 1 + } + }, + "file": "fixture/simple-private.input.js", + "code": "function returnTwo(a) {\n // this returns a + 2\n return a + 2;\n}" + } + } +] \ No newline at end of file diff --git a/test/fixture/simple-private.output.md b/test/fixture/simple-private.output.md new file mode 100644 index 0000000..e69de29 diff --git a/test/streams/filter_access.js b/test/streams/filter_access.js new file mode 100644 index 0000000..9f827e0 --- /dev/null +++ b/test/streams/filter_access.js @@ -0,0 +1,71 @@ +'use strict'; + +var test = require('prova'), + concat = require('concat-stream'), + parse = require('../../streams/parse'), + flatten = require('../../streams/flatten'), + filterAccess = require('../../streams/filter_access'), + inferName = require('../../streams/infer_name'); + +function evaluate(fn, callback, options) { + var stream = parse(); + + stream + .pipe(inferName()) + .pipe(flatten()) + .pipe(filterAccess(options)) + .pipe(concat(callback)); + + stream.end({ + file: __filename, + source: '(' + fn.toString() + ')' + }); +} + +test('filterAccess default', function (t) { + evaluate(function () { + // ExpressionStatement (comment attached here) + // AssignmentExpression + // MemberExpression + // Identifier + /** Test + * @private + */ + exports.name = test; + }, function (result) { + t.equal(result.length, 0); + t.end(); + }); +}); + +test('filterAccess public', function (t) { + evaluate(function () { + // ExpressionStatement (comment attached here) + // AssignmentExpression + // MemberExpression + // Identifier + /** Test + * @public + */ + exports.name = test; + }, function (result) { + t.equal(result.length, 1); + t.end(); + }); +}); + +test('filterAccess override', function (t) { + evaluate(function () { + // ExpressionStatement (comment attached here) + // AssignmentExpression + // MemberExpression + // Identifier + /** Test + * @private + */ + exports.name = test; + }, function (result) { + t.equal(result.length, 1); + t.end(); + }, []); +}); diff --git a/test/streams/flatten.js b/test/streams/flatten.js index 99120ae..429b39f 100644 --- a/test/streams/flatten.js +++ b/test/streams/flatten.js @@ -136,7 +136,7 @@ test('flatten - access public', function (t) { /** @access public */ return 0; }, function (result) { - t.notOk('access' in result[0]); + t.equal(result[0].access, 'public'); t.end(); }); }); @@ -166,7 +166,7 @@ test('flatten - public', function (t) { /** @public */ return 0; }, function (result) { - t.notOk('access' in result[0]); + t.equal(result[0].access, 'public'); t.end(); }); }); diff --git a/test/test.js b/test/test.js index 52e956a..ef3a097 100644 --- a/test/test.js +++ b/test/test.js @@ -4,6 +4,7 @@ var test = require('prova'), documentation = require('../'), markdown = require('../streams/output/markdown.js'), flatten = require('../streams/flatten.js'), + filterAccess = require('../streams/filter_access.js'), glob = require('glob'), path = require('path'), concat = require('concat-stream'), @@ -58,6 +59,7 @@ test('markdown', function (tt) { tt.test(path.basename(file), function (t) { documentation([file]) .pipe(flatten()) + .pipe((filterAccess())) .pipe(markdown()) .pipe(concat(function (result) { var outputfile = file.replace('.input.js', '.output.md'); @@ -70,6 +72,7 @@ test('markdown', function (tt) { tt.test(path.basename(file) + ' custom', function (t) { documentation([file]) .pipe(flatten()) + .pipe((filterAccess())) .pipe(markdown({ template: path.join(__dirname, '/misc/custom.hbs') }))