diff --git a/index.js b/index.js index de942e4f3..180f3d95d 100644 --- a/index.js +++ b/index.js @@ -55,7 +55,12 @@ function pipeline() { * @returns {undefined} */ function expandInputs(indexes, options, callback) { - var inputFn = (options.polyglot || options.shallow) ? shallow : dependency; + var inputFn; + if (options.polyglot || options.shallow || options.documentExported) { + inputFn = shallow; + } else { + inputFn = dependency; + } inputFn(indexes, options, callback); } diff --git a/lib/extractors/comments.js b/lib/extractors/comments.js index 4d0be5dd0..720bfef5f 100644 --- a/lib/extractors/comments.js +++ b/lib/extractors/comments.js @@ -8,11 +8,12 @@ var traverse = require('babel-traverse').default, * @param {string} type comment type to find * @param {boolean} includeContext to include context in the nodes * @param {Object} ast the babel-parsed syntax tree + * @param {Object} data the filename and the source of the file the comment is in * @param {Function} addComment a method that creates a new comment if necessary * @returns {Array} comments * @private */ -function walkComments(type, includeContext, ast, addComment) { +function walkComments(type, includeContext, ast, data, addComment) { var newResults = []; traverse(ast, { @@ -30,7 +31,7 @@ function walkComments(type, includeContext, ast, addComment) { * @return {undefined} this emits data */ function parseComment(comment) { - newResults.push(addComment(comment.value, comment.loc, path, path.node.loc, includeContext)); + newResults.push(addComment(data, comment.value, comment.loc, path, path.node.loc, includeContext)); } (path.node[type] || []) diff --git a/lib/extractors/exported.js b/lib/extractors/exported.js index c512ec358..8645c679a 100644 --- a/lib/extractors/exported.js +++ b/lib/extractors/exported.js @@ -1,6 +1,9 @@ var traverse = require('babel-traverse').default, - isJSDocComment = require('../../lib/is_jsdoc_comment'); - + isJSDocComment = require('../../lib/is_jsdoc_comment'), + t = require('babel-types'), + nodePath = require('path'), + fs = require('fs'), + parseToAst = require('../parsers/parse_to_ast'); /** * Iterate through the abstract syntax tree, finding ES6-style exports, @@ -8,33 +11,87 @@ var traverse = require('babel-traverse').default, * Through inference steps, these comments gain more information and are automatically * documented as well as we can. * @param {Object} ast the babel-parsed syntax tree + * @param {Object} data the name of the file * @param {Function} addComment a method that creates a new comment if necessary * @returns {Array} comments * @private */ -function walkExported(ast, addComment) { +function walkExported(ast, data, addComment) { var newResults = []; + var filename = data.file; + var dataCache = Object.create(null); + + function addBlankComment(data, path, node) { + return addComment(data, '', node.loc, path, node.loc, true); + } + + function getComments(data, path) { + if (!hasJSDocComment(path)) { + return [addBlankComment(data, path, path.node)]; + } + return path.node.leadingComments.filter(isJSDocComment).map(function (comment) { + return addComment(data, comment.value, comment.loc, path, path.node.loc, true); + }).filter(Boolean); + } - function addBlankComment(path, node) { - return addComment('', node.loc, path, node.loc, true); + function addComments(data, path, overrideName) { + var comments = getComments(data, path); + if (overrideName) { + comments.forEach(function (comment) { + comment.name = overrideName; + }); + } + newResults.push.apply(newResults, comments); } traverse(ast, { - enter: function (path) { - if (path.isExportDeclaration()) { - if (!hasJSDocComment(path)) { - if (!path.node.declaration) { - return; - } - const node = path.node.declaration; - newResults.push(addBlankComment(path, node)); + Statement: function (path) { + path.skip(); + }, + ExportDeclaration: function (path) { + var declaration = path.get('declaration'); + if (t.isDeclaration(declaration)) { + traverseExportedSubtree(declaration, data, addComments); + } + + if (path.isExportDefaultDeclaration()) { + if (declaration.isDeclaration()) { + traverseExportedSubtree(declaration, data, addComments); + } else if (declaration.isIdentifier()) { + var binding = declaration.scope.getBinding(declaration.node.name); + traverseExportedSubtree(binding.path, data, addComments); } - } else if ((path.isClassProperty() || path.isClassMethod()) && - !hasJSDocComment(path) && inExportedClass(path)) { - newResults.push(addBlankComment(path, path.node)); - } else if ((path.isObjectProperty() || path.isObjectMethod()) && - !hasJSDocComment(path) && inExportedObject(path)) { - newResults.push(addBlankComment(path, path.node)); + } + + if (t.isExportNamedDeclaration(path)) { + var specifiers = path.get('specifiers'); + var source = path.node.source; + var exportKind = path.node.exportKind; + specifiers.forEach(function (specifier) { + var specData = data; + var local, exported; + if (t.isExportDefaultSpecifier(specifier)) { + local ='default'; + } else { // ExportSpecifier + local = specifier.node.local.name; + } + exported = specifier.node.exported.name; + + var bindingPath; + if (source) { + var tmp = findExportDeclaration(dataCache, local, exportKind, filename, source.value); + bindingPath = tmp.ast; + specData = tmp.data; + } else if (exportKind === 'value') { + bindingPath = path.scope.getBinding(local).path; + } else if (exportKind === 'type') { + bindingPath = findLocalType(path.scope, local); + } else { + throw new Error('Unreachable'); + } + + traverseExportedSubtree(bindingPath, specData, addComments, exported); + }); } } }); @@ -46,18 +103,153 @@ function hasJSDocComment(path) { return path.node.leadingComments && path.node.leadingComments.some(isJSDocComment); } -function inExportedClass(path) { - var c = path.parentPath.parentPath; - return c.isClass() && c.parentPath.isExportDeclaration(); +function traverseExportedSubtree(path, data, addComments, overrideName) { + var attachCommentPath = path; + if (path.parentPath && path.parentPath.isExportDeclaration()) { + attachCommentPath = path.parentPath; + } + addComments(data, attachCommentPath, overrideName); + + if (path.isVariableDeclaration()) { + // TODO: How does JSDoc handle multiple declarations? + path = path.get('declarations')[0].get('init'); + if (!path) { + return; + } + } + + if (path.isClass() || path.isObjectExpression()) { + path.traverse({ + Property: function (path) { + addComments(data, path); + path.skip(); + }, + Method: function (path) { + addComments(data, path); + path.skip(); + } + }); + } } -function inExportedObject(path) { - // ObjectExpression -> VariableDeclarator -> VariableDeclaration -> ExportNamedDeclaration - var p = path.parentPath.parentPath; - if (!p.isVariableDeclarator()) { - return false; +function getCachedData(dataCache, path) { + var value = dataCache[path]; + if (!value) { + var input = fs.readFileSync(path, 'utf-8'); + var ast = parseToAst(input, path); + value = { + data: { + file: path, + source: input + }, + ast: ast + }; + dataCache[path] = value; } - return p.parentPath.parentPath.isExportDeclaration(); + return value; +} + +// Loads a module and finds the exported declaration. +function findExportDeclaration(dataCache, name, exportKind, referrer, filename) { + var depPath = nodePath.resolve(nodePath.dirname(referrer), filename); + var tmp = getCachedData(dataCache, depPath); + var ast = tmp.ast; + var data = tmp.data; + + var rv; + traverse(ast, { + Statement: function (path) { + path.skip(); + }, + ExportDeclaration: function (path) { + if (name === 'default' && path.isExportDefaultDeclaration()) { + rv = path.get('declaration'); + path.stop(); + } else if (path.isExportNamedDeclaration()) { + var declaration = path.get('declaration'); + if (t.isDeclaration(declaration)) { + var bindingName; + if (declaration.isFunctionDeclaration() || declaration.isClassDeclaration() || + declaration.isTypeAlias()) { + bindingName = declaration.node.id.name; + } else if (declaration.isVariableDeclaration()) { + // TODO: Multiple declarations. + bindingName = declaration.node.declarations[0].id.name; + } + if (name === bindingName) { + rv = declaration; + path.stop(); + } else { + path.skip(); + } + return; + } + + // export {x as y} + // export {x as y} from './file.js' + var specifiers = path.get('specifiers'); + var source = path.node.source; + for (var i = 0; i < specifiers.length; i++) { + var specifier = specifiers[i]; + var local, exported; + if (t.isExportDefaultSpecifier(specifier)) { + // export x from ... + local = 'default'; + exported = specifier.node.exported.name; + } else { + // ExportSpecifier + local = specifier.node.local.name; + exported = specifier.node.exported.name; + } + if (exported === name) { + if (source) { + // export {local as exported} from './file.js'; + var tmp = findExportDeclaration(dataCache, local, exportKind, depPath, source.value); + rv = tmp.ast; + data = tmp.data; + if (!rv) { + throw new Error(`${name} is not exported by ${depPath}`); + } + } else { + // export {local as exported} + if (exportKind === 'value') { + rv = path.scope.getBinding(local).path; + } else { + rv = findLocalType(path.scope, local); + } + if (!rv) { + throw new Error(`${depPath} has no binding for ${name}`); + } + } + path.stop(); + return; + } + } + } + } + }); + + return {ast: rv, data: data}; +} + +// Since we cannot use scope.getBinding for types this walks the current scope looking for a +// top-level type alias. +function findLocalType(scope, local) { + var rv; + scope.path.traverse({ + Statement: function (path) { + path.skip(); + }, + TypeAlias: function (path) { + if (path.node.id.name === local) { + rv = path; + path.stop(); + } else { + path.skip(); + } + } + }); + return rv; } module.exports = walkExported; diff --git a/lib/parsers/javascript.js b/lib/parsers/javascript.js index 4de14dce0..73a44316b 100644 --- a/lib/parsers/javascript.js +++ b/lib/parsers/javascript.js @@ -1,11 +1,10 @@ 'use strict'; -var babylon = require('babylon'), - extend = require('extend'), - _ = require('lodash'), +var _ = require('lodash'), parse = require('../../lib/parse'), walkComments = require('../extractors/comments'), - walkExported = require('../extractors/exported'); + walkExported = require('../extractors/exported'), + parseToAst = require('./parse_to_ast'); /** * Left-pad a string so that it can be sorted lexicographically. We sort @@ -33,52 +32,35 @@ function leftPad(str, width) { */ function parseJavaScript(data, options) { options = options || {}; - var visited = {}; + var visited = Object.create(null); - var ast = babylon.parse(data.source, { - allowImportExportEverywhere: true, - sourceType: 'module', - plugins: [ - 'jsx', - 'flow', - 'asyncFunctions', - 'classConstructorCall', - 'doExpressions', - 'trailingFunctionCommas', - 'objectRestSpread', - 'decorators', - 'classProperties', - 'exportExtensions', - 'exponentiationOperator', - 'asyncGenerators', - 'functionBind', - 'functionSent' - ] - }); + var ast = parseToAst(data.source, data.file); + var addComment = _addComment.bind(null, visited); - var addComment = _addComment.bind(null, visited, data); - - return _.flatMap([ + return _.flatMap(options.documentExported ? [ + walkExported + ] : [ walkComments.bind(null, 'leadingComments', true), walkComments.bind(null, 'innerComments', false), - walkComments.bind(null, 'trailingComments', false), - options.documentExported && walkExported - ].filter(Boolean), function (fn) { - return fn(ast, addComment); + walkComments.bind(null, 'trailingComments', false) + ], function (fn) { + return fn(ast, data, addComment); }).filter(Boolean); } function _addComment(visited, data, commentValue, commentLoc, path, nodeLoc, includeContext) { - var context = { - loc: extend({}, JSON.parse(JSON.stringify(nodeLoc))), - file: data.file, - sortKey: data.sortKey + ' ' + leftPad(nodeLoc.start.line, 8) - }; // Avoid visiting the same comment twice as a leading // and trailing node - var key = JSON.stringify(commentLoc); + var key = data.file + ':' + commentLoc.start.line + ':' + commentLoc.start.column; if (!visited[key]) { visited[key] = true; + + var context = { + loc: nodeLoc, + file: data.file, + sortKey: data.sortKey + ' ' + leftPad(nodeLoc.start.line, 8) + }; + if (includeContext) { // This is non-enumerable so that it doesn't get stringified in // output; e.g. by the documentation binary. diff --git a/lib/parsers/parse_to_ast.js b/lib/parsers/parse_to_ast.js new file mode 100644 index 000000000..22700d5f0 --- /dev/null +++ b/lib/parsers/parse_to_ast.js @@ -0,0 +1,30 @@ +'use strict'; + +var babylon = require('babylon'); + +var opts = { + allowImportExportEverywhere: true, + sourceType: 'module', + plugins: [ + 'jsx', + 'flow', + 'asyncFunctions', + 'classConstructorCall', + 'doExpressions', + 'trailingFunctionCommas', + 'objectRestSpread', + 'decorators', + 'classProperties', + 'exportExtensions', + 'exponentiationOperator', + 'asyncGenerators', + 'functionBind', + 'functionSent' + ] +}; + +function parseToAst(source) { + return babylon.parse(source, opts); +} + +module.exports = parseToAst; diff --git a/test/fixture/document-exported.input.js b/test/fixture/document-exported.input.js index 67cf1db5a..3be25eee7 100644 --- a/test/fixture/document-exported.input.js +++ b/test/fixture/document-exported.input.js @@ -17,19 +17,49 @@ export var object = { func: function() {}, }; +/** Should not document this */ class NotExportedClass { + /** Should not document this */ classMethod() {} + /** Should not document this */ get classGetter() {} + /** Should not document this */ set classSetter(v) {} + /** Should not document this */ static staticMethod() {} + /** Should not document this */ static get staticGetter() {} + /** Should not document this */ static set staticSetter(v) {} } +/** Should not document this */ var notExportedObject = { + /** Should not document this */ method() {}, + /** Should not document this */ get getter() {}, + /** Should not document this */ set setter(v) {}, + /** Should not document this */ prop: 42, + /** Should not document this */ func: function() {}, }; + +export {x, y3 as y4} from './document-exported/x.js'; +export z from './document-exported/z.js'; +export y2Default from './document-exported/y.js'; + +function f1() {} +function f2() {} + +export {f1, f2 as f3}; + +export type T = number; +type T2 = string; +type T3 = string; + +export type {T2, T3 as T4}; + +export type {T5} from './document-exported/x.js'; diff --git a/test/fixture/document-exported.output.json b/test/fixture/document-exported.output.json index 872eb6c37..6b63135c5 100644 --- a/test/fixture/document-exported.output.json +++ b/test/fixture/document-exported.output.json @@ -4,8 +4,144 @@ "tags": [], "loc": { "start": { + "line": 1, + "column": 0 + }, + "end": { "line": 3, - "column": 7 + "column": 1 + } + }, + "context": { + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 1 + } + } + }, + "errors": [], + "name": "z", + "kind": "class", + "members": { + "instance": [ + { + "description": "", + "tags": [], + "loc": { + "start": { + "line": 2, + "column": 2 + }, + "end": { + "line": 2, + "column": 14 + } + }, + "context": { + "loc": { + "start": { + "line": 2, + "column": 2 + }, + "end": { + "line": 2, + "column": 14 + } + } + }, + "errors": [], + "name": "zMethod", + "kind": "function", + "memberof": "z", + "scope": "instance", + "members": { + "instance": [], + "static": [] + }, + "path": [ + { + "name": "z", + "kind": "class" + }, + { + "name": "zMethod", + "kind": "function", + "scope": "instance" + } + ], + "namespace": "z#zMethod" + } + ], + "static": [], + "events": [] + }, + "path": [ + { + "name": "z", + "kind": "class" + } + ], + "namespace": "z" + }, + { + "description": "", + "tags": [], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 28 + } + }, + "context": { + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 28 + } + } + }, + "errors": [], + "name": "x", + "kind": "function", + "params": [ + { + "title": "param", + "name": "yparam", + "lineNumber": 1 + } + ], + "members": { + "instance": [], + "static": [] + }, + "path": [ + { + "name": "x", + "kind": "function" + } + ], + "namespace": "x" + }, + { + "description": "", + "tags": [], + "loc": { + "start": { + "line": 3, + "column": 0 }, "end": { "line": 10, @@ -16,7 +152,7 @@ "loc": { "start": { "line": 3, - "column": 7 + "column": 0 }, "end": { "line": 10, @@ -338,13 +474,204 @@ ], "namespace": "Class" }, + { + "description": "", + "tags": [], + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 25 + } + }, + "context": { + "loc": { + "start": { + "line": 3, + "column": 0 + }, + "end": { + "line": 3, + "column": 25 + } + } + }, + "errors": [], + "name": "T5", + "kind": "typedef", + "type": { + "type": "NameExpression", + "name": "boolean" + }, + "members": { + "instance": [], + "static": [] + }, + "path": [ + { + "name": "T5", + "kind": "typedef" + } + ], + "namespace": "T5" + }, + { + "description": "", + "tags": [], + "loc": { + "start": { + "line": 5, + "column": 0 + }, + "end": { + "line": 5, + "column": 18 + } + }, + "context": { + "loc": { + "start": { + "line": 5, + "column": 0 + }, + "end": { + "line": 5, + "column": 18 + } + } + }, + "errors": [], + "name": "y2Default", + "members": { + "instance": [], + "static": [] + }, + "path": [ + { + "name": "y2Default" + } + ], + "namespace": "y2Default" + }, + { + "description": { + "type": "root", + "children": [ + { + "type": "paragraph", + "children": [ + { + "type": "text", + "value": "Description of y3", + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 18, + "offset": 17 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 18, + "offset": 17 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 18, + "offset": 17 + } + } + }, + "tags": [], + "loc": { + "start": { + "line": 7, + "column": 0 + }, + "end": { + "line": 7, + "column": 24 + } + }, + "context": { + "loc": { + "start": { + "line": 8, + "column": 0 + }, + "end": { + "line": 8, + "column": 31 + } + } + }, + "errors": [], + "name": "y4", + "kind": "function", + "params": [ + { + "title": "param", + "name": "p", + "lineNumber": 8, + "type": { + "type": "NameExpression", + "name": "number" + } + } + ], + "returns": [ + { + "type": { + "type": "VoidLiteral" + } + } + ], + "members": { + "instance": [], + "static": [] + }, + "path": [ + { + "name": "y4", + "kind": "function" + } + ], + "namespace": "y4" + }, { "description": "", "tags": [], "loc": { "start": { "line": 12, - "column": 7 + "column": 0 }, "end": { "line": 18, @@ -355,7 +682,7 @@ "loc": { "start": { "line": 12, - "column": 7 + "column": 0 }, "end": { "line": 18, @@ -593,5 +920,217 @@ } ], "namespace": "setter" + }, + { + "description": "", + "tags": [], + "loc": { + "start": { + "line": 54, + "column": 0 + }, + "end": { + "line": 54, + "column": 16 + } + }, + "context": { + "loc": { + "start": { + "line": 54, + "column": 0 + }, + "end": { + "line": 54, + "column": 16 + } + } + }, + "errors": [], + "name": "f1", + "kind": "function", + "members": { + "instance": [], + "static": [] + }, + "path": [ + { + "name": "f1", + "kind": "function" + } + ], + "namespace": "f1" + }, + { + "description": "", + "tags": [], + "loc": { + "start": { + "line": 55, + "column": 0 + }, + "end": { + "line": 55, + "column": 16 + } + }, + "context": { + "loc": { + "start": { + "line": 55, + "column": 0 + }, + "end": { + "line": 55, + "column": 16 + } + } + }, + "errors": [], + "name": "f3", + "kind": "function", + "members": { + "instance": [], + "static": [] + }, + "path": [ + { + "name": "f3", + "kind": "function" + } + ], + "namespace": "f3" + }, + { + "description": "", + "tags": [], + "loc": { + "start": { + "line": 59, + "column": 0 + }, + "end": { + "line": 59, + "column": 23 + } + }, + "context": { + "loc": { + "start": { + "line": 59, + "column": 0 + }, + "end": { + "line": 59, + "column": 23 + } + } + }, + "errors": [], + "name": "T", + "kind": "typedef", + "type": { + "type": "NameExpression", + "name": "number" + }, + "members": { + "instance": [], + "static": [] + }, + "path": [ + { + "name": "T", + "kind": "typedef" + } + ], + "namespace": "T" + }, + { + "description": "", + "tags": [], + "loc": { + "start": { + "line": 60, + "column": 0 + }, + "end": { + "line": 60, + "column": 17 + } + }, + "context": { + "loc": { + "start": { + "line": 60, + "column": 0 + }, + "end": { + "line": 60, + "column": 17 + } + } + }, + "errors": [], + "name": "T2", + "kind": "typedef", + "type": { + "type": "NameExpression", + "name": "string" + }, + "members": { + "instance": [], + "static": [] + }, + "path": [ + { + "name": "T2", + "kind": "typedef" + } + ], + "namespace": "T2" + }, + { + "description": "", + "tags": [], + "loc": { + "start": { + "line": 61, + "column": 0 + }, + "end": { + "line": 61, + "column": 17 + } + }, + "context": { + "loc": { + "start": { + "line": 61, + "column": 0 + }, + "end": { + "line": 61, + "column": 17 + } + } + }, + "errors": [], + "name": "T4", + "kind": "typedef", + "type": { + "type": "NameExpression", + "name": "string" + }, + "members": { + "instance": [], + "static": [] + }, + "path": [ + { + "name": "T4", + "kind": "typedef" + } + ], + "namespace": "T4" } ] \ No newline at end of file diff --git a/test/fixture/document-exported.output.md b/test/fixture/document-exported.output.md index a515467d0..b2681b6b7 100644 --- a/test/fixture/document-exported.output.md +++ b/test/fixture/document-exported.output.md @@ -1,5 +1,15 @@ +# z + +## zMethod + +# x + +**Parameters** + +- `yparam` + # Class ## classMethod @@ -22,6 +32,20 @@ - `v` +# T5 + +# y2Default + +# y4 + +Description of y3 + +**Parameters** + +- `p` **[number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** + +Returns **void** + # object ## prop @@ -37,3 +61,13 @@ **Parameters** - `v` + +# f1 + +# f3 + +# T + +# T2 + +# T4 diff --git a/test/fixture/document-exported.output.md.json b/test/fixture/document-exported.output.md.json index 77eaa00f0..2934d22bd 100644 --- a/test/fixture/document-exported.output.md.json +++ b/test/fixture/document-exported.output.md.json @@ -5,6 +5,73 @@ "type": "html", "value": "" }, + { + "depth": 1, + "type": "heading", + "children": [ + { + "type": "text", + "value": "z" + } + ] + }, + { + "depth": 2, + "type": "heading", + "children": [ + { + "type": "text", + "value": "zMethod" + } + ] + }, + { + "depth": 1, + "type": "heading", + "children": [ + { + "type": "text", + "value": "x" + } + ] + }, + { + "type": "strong", + "children": [ + { + "type": "text", + "value": "Parameters" + } + ] + }, + { + "ordered": false, + "type": "list", + "children": [ + { + "type": "listItem", + "children": [ + { + "type": "paragraph", + "children": [ + { + "type": "inlineCode", + "value": "yparam" + }, + { + "type": "text", + "value": " " + }, + { + "type": "text", + "value": " " + } + ] + } + ] + } + ] + }, { "depth": 1, "type": "heading", @@ -149,6 +216,146 @@ } ] }, + { + "depth": 1, + "type": "heading", + "children": [ + { + "type": "text", + "value": "T5" + } + ] + }, + { + "depth": 1, + "type": "heading", + "children": [ + { + "type": "text", + "value": "y2Default" + } + ] + }, + { + "depth": 1, + "type": "heading", + "children": [ + { + "type": "text", + "value": "y4" + } + ] + }, + { + "type": "paragraph", + "children": [ + { + "type": "text", + "value": "Description of y3", + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 18, + "offset": 17 + }, + "indent": [] + } + } + ], + "position": { + "start": { + "line": 1, + "column": 1, + "offset": 0 + }, + "end": { + "line": 1, + "column": 18, + "offset": 17 + }, + "indent": [] + } + }, + { + "type": "strong", + "children": [ + { + "type": "text", + "value": "Parameters" + } + ] + }, + { + "ordered": false, + "type": "list", + "children": [ + { + "type": "listItem", + "children": [ + { + "type": "paragraph", + "children": [ + { + "type": "inlineCode", + "value": "p" + }, + { + "type": "text", + "value": " " + }, + { + "type": "strong", + "children": [ + { + "href": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", + "url": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number", + "type": "link", + "children": [ + { + "type": "text", + "value": "number" + } + ] + } + ] + }, + { + "type": "text", + "value": " " + } + ] + } + ] + } + ] + }, + { + "type": "paragraph", + "children": [ + { + "type": "text", + "value": "Returns " + }, + { + "type": "strong", + "children": [ + { + "type": "text", + "value": "void" + } + ] + }, + { + "type": "text", + "value": " " + } + ] + }, { "depth": 1, "type": "heading", @@ -245,6 +452,56 @@ ] } ] + }, + { + "depth": 1, + "type": "heading", + "children": [ + { + "type": "text", + "value": "f1" + } + ] + }, + { + "depth": 1, + "type": "heading", + "children": [ + { + "type": "text", + "value": "f3" + } + ] + }, + { + "depth": 1, + "type": "heading", + "children": [ + { + "type": "text", + "value": "T" + } + ] + }, + { + "depth": 1, + "type": "heading", + "children": [ + { + "type": "text", + "value": "T2" + } + ] + }, + { + "depth": 1, + "type": "heading", + "children": [ + { + "type": "text", + "value": "T4" + } + ] } ] } \ No newline at end of file diff --git a/test/fixture/document-exported/x.js b/test/fixture/document-exported/x.js new file mode 100644 index 000000000..1757ae6d0 --- /dev/null +++ b/test/fixture/document-exported/x.js @@ -0,0 +1,3 @@ +export {y as x, y3} from './y.js'; + +export type T5 = boolean; diff --git a/test/fixture/document-exported/y.js b/test/fixture/document-exported/y.js new file mode 100644 index 000000000..822b2fab0 --- /dev/null +++ b/test/fixture/document-exported/y.js @@ -0,0 +1,10 @@ +export function y(yparam) {} + +function y2() {} + +export default y2; + +/** Description of y3 */ +function y3(p: number): void {} + +export {y3}; diff --git a/test/fixture/document-exported/z.js b/test/fixture/document-exported/z.js new file mode 100644 index 000000000..9679f2d9b --- /dev/null +++ b/test/fixture/document-exported/z.js @@ -0,0 +1,3 @@ +export default class z { + zMethod() {} +}