From ee301ea2df84e09c7b8ee98c13375a409e1ec26a Mon Sep 17 00:00:00 2001 From: brettlangdon Date: Sun, 25 Jan 2015 19:52:09 -0500 Subject: [PATCH] initial commit --- .gitignore | 1 + LICENSE | 21 +++++++++ README.md | 4 ++ lib/index.js | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 22 ++++++++++ 5 files changed, 169 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 lib/index.js create mode 100644 package.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..55ba1ed --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Brett Langdon + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..b3f352a --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +DocAST +====== + +Documentation generator for JS via AST parsing. diff --git a/lib/index.js b/lib/index.js new file mode 100644 index 0000000..738f244 --- /dev/null +++ b/lib/index.js @@ -0,0 +1,121 @@ +var esprima = require('esprima'); +var fs = require('fs'); + +var skip = /^\s+\*/gm; + +var mapName = function(elm){ + return elm.name; +}; + +var findReturns = function(expr){ + var returns = [] + expr.body.forEach(function(expr){ + if(expr.type === 'ReturnStatement'){ + if(expr.argument.type === 'Literal'){ + returns.push(expr.argument.value); + } else if(expr.argument.type === 'ObjectExpression'){ + returns.push('Object'); + } else if(expr.argument.type === 'ArrayExpression'){ + returns.push('Array'); + } else if(expr.argument.type === 'FunctionExpression'){ + returns.push('Function'); + } + } + }); + return returns; +}; + +var findRaises = function(expr){ + var raises = [] + expr.body.forEach(function(expr){ + if(expr.type === 'ThrowStatement'){ + if(expr.argument.type === 'NewExpression'){ + raises.push(expr.argument.callee.name); + } + } + }); + return raises; +}; + +var parseExpressions = function(expr){ + var expressions = {}; + var _parse = function(expr){ + if(!expr){ + return; + } else if(expr.length && typeof expr.forEach === 'function'){ + return expr.forEach(_parse); + } + + if(expr.type === 'FunctionExpression'){ + expressions[expr.loc.start.line] = { + name: expr.id, + params: expr.params.map(mapName), + returns: findReturns(expr.body), + raises: findRaises(expr.body), + }; + + _parse(expr.body); + } else if(expr.type === 'FunctionDeclaration'){ + expressions[expr.loc.start.line] = { + name: expr.id.name, + params: expr.params.map(mapName), + returns: findReturns(expr.body), + raises: findRaises(expr.body), + }; + + _parse(expr.body); + } else if(expr.type === 'AssignmentExpression' && expr.right.type === 'FunctionExpression'){ + var data = {}; + if(expr.left.type === 'MemberExpression'){ + data.name = expr.left.property.name; + if(expr.left.object.type === 'MemberExpression'){ + if(expr.left.object.property.name === 'prototype'){ + data.class = expr.left.object.object.name; + } + } + } + if(expr.right.type === 'FunctionExpression'){ + data.params = expr.right.params.map(mapName); + data.returns = findReturns(expr.right.body); + data.raises = findRaises(expr.right.body); + } + expressions[expr.loc.start.line] = data; + } else if(expr.type === 'VariableDeclarator' && expr.init.type === 'FunctionExpression'){ + expressions[expr.loc.start.line] = { + name: expr.id.name, + params: expr.init.params.map(mapName), + returns: findReturns(expr.init.body), + raises: findRaises(expr.init.body), + }; + } else { + _parse(expr.expression || expr.callee || expr.body || expr.declarations); + } + }; + _parse(expr); + return expressions; +}; + +module.exports.parseDataFile = function(filename, options){ + return module.exports.parseData(fs.readFileSync(filename, 'utf-8'), options); +}; + +module.exports.parseData = function(contents, options){ + options = options || {}; + var tolerant = (options.tolerant === undefined)? true: options.tolerant; + var parsed = esprima.parse(contents, {comment: true, loc: true, tolerant: tolerant}); + var expressions = parseExpressions(parsed); + + var results = []; + parsed.comments.forEach(function(comment){ + if(comment.type === 'Block'){ + var body = comment.value; + body = body.replace(skip, ''); + results.push({ + doc: body, + data: expressions[comment.loc.end.line + 1], + }); + } + }); + + return results; +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000..5f4f63c --- /dev/null +++ b/package.json @@ -0,0 +1,22 @@ +{ + "name": "DocAST", + "version": "0.1.0", + "description": "Generate JS documentation via AST parsing", + "main": "lib/index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "https://github.com/brettlangdon/docast.git" + }, + "author": "Brett Langdon (http://brett.is)", + "license": "MIT", + "bugs": { + "url": "https://github.com/brettlangdon/docast/issues" + }, + "homepage": "https://github.com/brettlangdon/docast", + "dependencies": { + "esprima": "^1.2.3" + } +}