├── test ├── error.js ├── sample.js └── test.js ├── .gitignore ├── .travis.yml ├── readme.md ├── package.json └── index.js /test/error.js: -------------------------------------------------------------------------------- 1 | var; -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 6 4 | 5 | notifications: 6 | email: false 7 | -------------------------------------------------------------------------------- /test/sample.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Foo does stuff 3 | * @param {String} param - This is a sample parameter 4 | * @returns {Boolean} To be or not to be 5 | */ 6 | function foo(param) { 7 | return true; 8 | } -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # JSDoc3 Parser [![npm](http://img.shields.io/npm/v/jsdoc3-parser.svg)](https://npmjs.org/package/jsdoc3-parser) [![npm](http://img.shields.io/npm/dm/jsdoc3-parser.svg)](https://npmjs.org/package/jsdoc3-parser) 2 | 3 | JSDoc is not currently available as a library, so there's no clean way to access 4 | its parser. You can't `require('jsdoc')`, so you have to hack around it by using 5 | the jsdoc binary's `-X` option and parsing the output. 6 | 7 | This is a wrapper around that process. 8 | 9 | ### Usage 10 | 11 | ```javascript 12 | var parser = require('jsdoc3-parser'); 13 | 14 | parser('myfile.js', function(error, ast) { 15 | 16 | }); 17 | ``` 18 | 19 | ### License 20 | 21 | MIT -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | var parser = require('../'), 2 | assert = require('assert'); 3 | 4 | describe('jsdoc3-parser', function() { 5 | it('returns the JSDoc AST for a given JS file', function(done) { 6 | parser(__dirname + '/sample.js', function(err, ast) { 7 | assert.ok(ast); 8 | assert.ok(!err); 9 | done(); 10 | }); 11 | }); 12 | 13 | it('propagates errors from the cli', function(done) { 14 | parser(__dirname + '/error.js', function(err, ast) { 15 | assert.ok(err); 16 | assert.ok(!ast); 17 | done(); 18 | }); 19 | }); 20 | 21 | it('returns an error on non-ast jsdoc output', function() { 22 | parser._onComplete(function(error, stdout) { 23 | assert.ok(error); 24 | assert.ok(!stdout); 25 | }, null, 'omg error'); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jsdoc3-parser", 3 | "version": "3.0.0", 4 | "description": "Get the AST of a file using JSDoc3's parser", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "mocha test/test.js" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git://github.com/mrjoelkemp/jsdoc3-parser.git" 12 | }, 13 | "keywords": [ 14 | "jsdoc", 15 | "parser", 16 | "ast" 17 | ], 18 | "author": "Joel Kemp (http://www.mrjoelkemp.com/)", 19 | "license": "MIT", 20 | "bugs": { 21 | "url": "https://github.com/mrjoelkemp/jsdoc3-parser/issues" 22 | }, 23 | "homepage": "https://github.com/mrjoelkemp/jsdoc3-parser", 24 | "dependencies": { 25 | "jsdoc": "^4.0.0" 26 | }, 27 | "devDependencies": { 28 | "mocha": "~2.1.0" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var execFile = require('child_process').execFile, 2 | fs = require('fs'), 3 | os = require('os'), 4 | path = require('path'); 5 | 6 | /** 7 | * Locates the JSDoc executable command. Since a module is not provided, 8 | * `require.resolve('jsdoc')` does not work and must be done manually. 9 | * 10 | * @param {String} dir - The starting directory to search. 11 | * @return {String} The executable path, or null if not found. 12 | */ 13 | function locateJSDocCommand(dir) { 14 | var executable = os.platform() === 'win32' ? 'jsdoc.cmd' : 'jsdoc', 15 | cmd; 16 | 17 | dir = path.resolve(dir); 18 | 19 | while (dir) { 20 | try { 21 | cmd = path.join(dir, 'node_modules', '.bin', executable); 22 | // End the search if the command is found. 23 | // If not found, an exception is thrown. 24 | fs.statSync(cmd); 25 | break; 26 | 27 | } catch (ex) { 28 | cmd = null; 29 | 30 | // Otherwise, iterate to the parent directory, if possible. 31 | if (path.dirname(dir) === dir) { 32 | break; 33 | } 34 | 35 | dir = path.resolve(path.dirname(dir)); 36 | } 37 | } 38 | 39 | return cmd; 40 | } 41 | 42 | /** 43 | * Parses the given file using JSDoc's parser. 44 | * Since JSDoc doesn't isn't require-able, we need to get the parse info from 45 | * the command line. 46 | * 47 | * @param {String} filename 48 | * @param {Function} cb ({Object}) -> null - Executed with the AST 49 | */ 50 | function jsdocParser(filename, cb) { 51 | var cmd = locateJSDocCommand(__dirname); 52 | 53 | if (!cmd) { 54 | cb(new Error('Could not find jsdoc command.'), null); 55 | return; 56 | } 57 | 58 | execFile(cmd, ['-X', filename], {maxBuffer: 5120 * 1024}, 59 | jsdocParser._onComplete.bind(null, cb)); 60 | } 61 | 62 | /** 63 | * Exposed for testing 64 | * 65 | * @private 66 | * @param {Function} cb 67 | * @param {Object} error 68 | * @param {String} stdout 69 | */ 70 | jsdocParser._onComplete = function(cb, error, stdout) { 71 | if (error) { 72 | cb(error, null); 73 | return; 74 | } 75 | 76 | var parsed; 77 | 78 | try { 79 | parsed = JSON.parse(stdout); 80 | } catch (ex) { 81 | parsed = null; 82 | error = ex; 83 | } 84 | 85 | cb(error, parsed); 86 | }; 87 | 88 | module.exports = jsdocParser; 89 | --------------------------------------------------------------------------------