UNPKG

ds-algo-study

Version:

Just experimenting with publishing a package

226 lines (213 loc) 6.73 kB
/** * Copyright (c) 2012-2015 Sutoiku * * Transforms the AST into a form that represents a single file with modules and their functions. * * @param {Object} ast * @param {Object} argv Command-line args * @returns {Object} * * @example * { functions: * [ { name: 'testNamed', * params: [ { name: 'file', type: 'String', value: 'filename to parse' } ], * returns: '', * version: '', * description: 'This is a test function\nwith a description on multiple lines' }, * { name: 'testAnonynous', * params: [], * returns: 'the result', * version: '', * description: 'function without name', * type: 'String' } ], * methods: [], * classes: [], * modules: * [ { name: 'test_module', * functions: * [ { name: 'testAnonynous', * params: [], * returns: 'the result', * version: '', * description: 'function without name', * type: 'String' } ], * classes: [], * description: '' } ], * global_functions: * [ { name: 'testNamed', * params: [ { name: 'file', type: 'String', value: 'filename to parse' } ], * returns: '', * version: '', * description: 'This is a test function\nwith a description on multiple lines' } ], * description: 'Some extra text\nSome more extra text', * overview: 'This is the overview', * copyright: '2012 Blah Blah Blah', * license: 'MIT', * author: 'Joe Schmo', * version: '' * } */ module.exports = function(ast, argv) { var result = { functions: [], methods: [], classes: [], modules: [], members: [], globalModule: null, description: '', overview: '', copyright: '', license: '', author: '', version: '', hasMembers: false }; var currentModule = null; var currentClass = null; var currentFunction = null; var ignoreInternal = !argv.All; function initGlobalModule() { var global = {}; global.name = 'Global'; global.functions = []; global.classes = []; result.modules.push(global); result.globalModule = global; } if (!ast) { return null; } ast.forEach(function (tag) { if (ignoreInternal && isInternal(tag)) { return; } switch (tag.kind) { case 'file': result.license = tag.license; result.author = tag.author; result.copyright = tag.copyright; result.overview = tag.description; (currentFunction || result).version = tag.version; (currentFunction || result).deprecated = tag.deprecated || true; break; case 'function': if (tag.undocumented) { break; } var fn = tag; fn.params = tag.params || []; fn.params.forEach(function (p) { p.nested = (p.name.indexOf('.') > -1); }); fn.hasParams = !!fn.params.length; // For the function signature fn.paramsString = fn.params.filter(function (p) { // Filter out nested params return !p.nested; }).map(function(p) { return p.name; }).join(', '); // For param details fn.params.forEach(setPipedTypesString); fn.returns = tag.returns || []; fn.returns.forEach(function(ret) { setPipedTypesString(ret); ret.description = ret.description || false; }); // To avoid reaching to the parent for these fields fn.version = tag.version || false; fn.fires = tag.fires || []; fn.description = tag.description; fn.deprecated = tag.deprecated || false; fn.moduleName = currentModule ? currentModule.name : ''; fn.examples = tag.examples || []; currentFunction = fn; if (currentClass) { currentClass.methods.push(fn); fn.className = currentClass ? currentClass.name : ''; } else if (currentModule) { currentModule.functions.push(fn); } else { if (!result.globalModule) { initGlobalModule(); } result.globalModule.functions.push(fn); } result.functions.push(fn); break; case 'emits': case 'fires': fn.fires.push(tag.name); break; case 'member': if (currentClass && tag.undocumented !== true) { currentClass.members.push(tag); setPipedTypesString(tag); } else if (tag.scope === 'inner' && tag.undocumented !== true) { result.members.push({member: tag.name}); result.hasMembers = true; } break; case 'return': case 'returns': if (currentFunction) { currentFunction.returns = tag.text; currentFunction.type = tag.type; } break; case 'module': case 'namespace': var module = {}; module.name = tag.name; module.longname = tag.longname; module.examples = tag.examples || []; module.functions = []; module.classes = []; module.description = tag.description; module.requires = tag.requires || []; module.hasRequires = !!module.requires.length; module.requires.forEach(function(r, i) { if (!r) { return ''; } module.requires[i] = {req: r}; }); result.modules.push(module); currentModule = module; currentClass = null; break; case 'class': case 'interface': var klass = {}; klass.name = tag.name; klass.longname = tag.longname; klass.methods = []; klass.description = tag.description; klass.members = tag.properties || []; klass.members.forEach(setPipedTypesString); klass.params = tag.params || []; result.classes.push(klass); if (currentModule) { currentModule.classes.push(klass); } else { if (!result.globalModule) { initGlobalModule(); } result.globalModule.classes.push(klass); } currentClass = klass; break; } }); result.classes.forEach(function(klass) { klass.hasMembers = !!klass.members.length; }); return result; }; /** * Attaches a 'typesString' pipe-separated attribute * containing the node's types * @param {AST} node - May or may not contain a type attribute */ function setPipedTypesString(node) { if (!node.type) { return ''; } node.typesString = node.type.names.join(' | '); } function isInternal(tag) { return tag && ((tag.name && tag.name.lastIndexOf('_', 0) === 0) || tag.access === 'private'); }