mirror of
https://github.com/documentationjs/documentation.git
synced 2026-01-18 14:17:30 +00:00
Combine flatten and normalize into a single step; alphabetize
This commit is contained in:
parent
47eb1eaf26
commit
c0efef36ae
342
lib/parse.js
342
lib/parse.js
@ -1,203 +1,177 @@
|
||||
'use strict';
|
||||
|
||||
var doctrine = require('doctrine');
|
||||
var extend = require('extend');
|
||||
|
||||
var synonyms = {
|
||||
'virtual': 'abstract',
|
||||
'extends': 'augments',
|
||||
'constructor': 'class',
|
||||
'const': 'constant',
|
||||
'defaultvalue': 'default',
|
||||
'desc': 'description',
|
||||
'host': 'external',
|
||||
'fileoverview': 'file',
|
||||
'overview': 'file',
|
||||
'emits': 'fires',
|
||||
'func': 'function',
|
||||
'method': 'function',
|
||||
'var': 'member',
|
||||
'arg': 'param',
|
||||
'argument': 'param',
|
||||
'prop': 'property',
|
||||
'return': 'returns',
|
||||
'exception': 'throws',
|
||||
'linkcode': 'link',
|
||||
'linkplain': 'link'
|
||||
};
|
||||
|
||||
/**
|
||||
* Normalizes synonymous tags to the canonical tag type listed on http://usejsdoc.org/.
|
||||
*
|
||||
* For example, given the input object:
|
||||
*
|
||||
* { tags: [
|
||||
* { title: "virtual" },
|
||||
* { title: "return", ... }
|
||||
* ]}
|
||||
*
|
||||
* The output object will be:
|
||||
*
|
||||
* { tags: [
|
||||
* { title: "abstract" },
|
||||
* { title: "returns", ... }
|
||||
* ]}
|
||||
*
|
||||
* The following synonyms are normalized:
|
||||
*
|
||||
* * virtual -> abstract
|
||||
* * extends -> augments
|
||||
* * constructor -> class
|
||||
* * const -> constant
|
||||
* * defaultvalue -> default
|
||||
* * desc -> description
|
||||
* * host -> external
|
||||
* * fileoverview, overview -> file
|
||||
* * emits -> fires
|
||||
* * func, method -> function
|
||||
* * var -> member
|
||||
* * arg, argument -> param
|
||||
* * prop -> property
|
||||
* * return -> returns
|
||||
* * exception -> throws
|
||||
* * linkcode, linkplain -> link
|
||||
*
|
||||
* @param {Object} comment parsed comment
|
||||
* @return {Object} comment with normalized properties
|
||||
* @private
|
||||
*/
|
||||
function normalize(comment) {
|
||||
return extend({}, comment, {
|
||||
tags: comment.tags.map(function (tag) {
|
||||
var canonical = synonyms[tag.title];
|
||||
return canonical ? extend({}, tag, { title: canonical }) : tag;
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
function flattenName(result, tag) {
|
||||
result[tag.title] = tag.name;
|
||||
}
|
||||
|
||||
function flattenDescription(result, tag) {
|
||||
result[tag.title] = tag.description;
|
||||
}
|
||||
|
||||
function flattenTypedName(result, tag) {
|
||||
result[tag.title] = {
|
||||
name: tag.name
|
||||
};
|
||||
|
||||
if (tag.type) {
|
||||
result[tag.title].type = tag.type;
|
||||
}
|
||||
}
|
||||
|
||||
var flatteners = {
|
||||
'name': flattenName,
|
||||
'function': flattenName,
|
||||
'mixin': flattenName,
|
||||
'access': function (result, tag) {
|
||||
result.access = tag.access;
|
||||
},
|
||||
'alias': flattenName,
|
||||
'memberof': flattenDescription,
|
||||
'version': flattenDescription,
|
||||
'since': flattenDescription,
|
||||
'copyright': flattenDescription,
|
||||
'author': flattenDescription,
|
||||
'license': flattenDescription,
|
||||
'classdesc': flattenDescription,
|
||||
'lends': flattenDescription,
|
||||
'event': flattenDescription,
|
||||
'external': flattenDescription,
|
||||
'file': flattenDescription,
|
||||
'callback': flattenDescription,
|
||||
'description': flattenDescription,
|
||||
'summary': flattenDescription,
|
||||
'deprecated': flattenDescription,
|
||||
'class': flattenTypedName,
|
||||
'constant': flattenTypedName,
|
||||
'member': flattenTypedName,
|
||||
'module': flattenTypedName,
|
||||
'namespace': flattenTypedName,
|
||||
'typedef': flattenTypedName,
|
||||
'kind': function (result, tag) {
|
||||
result.kind = tag.kind;
|
||||
},
|
||||
'property': function (result, tag) {
|
||||
if (!result.properties) {
|
||||
result.properties = [];
|
||||
}
|
||||
result.properties.push(tag);
|
||||
},
|
||||
'param': function (result, tag) {
|
||||
if (!result.params) {
|
||||
result.params = [];
|
||||
}
|
||||
result.params.push(tag);
|
||||
},
|
||||
'throws': function (result, tag) {
|
||||
if (!result.throws) {
|
||||
result.throws = [];
|
||||
}
|
||||
result.throws.push(tag);
|
||||
},
|
||||
'returns': function (result, tag) {
|
||||
if (!result.returns) {
|
||||
result.returns = [];
|
||||
}
|
||||
result.returns.push(tag);
|
||||
},
|
||||
'arg': synonym('param'),
|
||||
'argument': synonym('param'),
|
||||
'augments': function (result, tag) {
|
||||
if (!result.augments) {
|
||||
result.augments = [];
|
||||
}
|
||||
result.augments.push(tag);
|
||||
},
|
||||
'author': flattenDescription,
|
||||
'callback': flattenDescription,
|
||||
'class': flattenTypedName,
|
||||
'classdesc': flattenDescription,
|
||||
'const': synonym('constant'),
|
||||
'constant': flattenTypedName,
|
||||
'constructor': synonym('class'),
|
||||
'copyright': flattenDescription,
|
||||
'defaultvalue': synonym('default'),
|
||||
'deprecated': flattenDescription,
|
||||
'desc': synonym('description'),
|
||||
'description': flattenDescription,
|
||||
'emits': synonym('fires'),
|
||||
'event': flattenDescription,
|
||||
'example': function (result, tag) {
|
||||
if (!result.examples) {
|
||||
result.examples = [];
|
||||
}
|
||||
result.examples.push(tag);
|
||||
},
|
||||
'exception': synonym('throws'),
|
||||
'extends': synonym('augments'),
|
||||
'external': flattenDescription,
|
||||
'file': flattenDescription,
|
||||
'fileoverview': synonym('file'),
|
||||
'func': synonym('function'),
|
||||
'function': flattenName,
|
||||
'global': function (result) {
|
||||
result.scope = 'global';
|
||||
},
|
||||
'host': synonym('external'),
|
||||
'inner': function (result) {
|
||||
result.scope = 'inner';
|
||||
},
|
||||
'instance': function (result) {
|
||||
result.scope = 'instance';
|
||||
},
|
||||
'kind': function (result, tag) {
|
||||
result.kind = tag.kind;
|
||||
},
|
||||
'lends': flattenDescription,
|
||||
'license': flattenDescription,
|
||||
'linkcode': synonym('link'),
|
||||
'linkplain': synonym('link'),
|
||||
'member': flattenTypedName,
|
||||
'memberof': flattenDescription,
|
||||
'method': synonym('function'),
|
||||
'mixin': flattenName,
|
||||
'module': flattenTypedName,
|
||||
'name': flattenName,
|
||||
'namespace': flattenTypedName,
|
||||
'overview': synonym('file'),
|
||||
'param': function (result, tag) {
|
||||
if (!result.params) {
|
||||
result.params = [];
|
||||
}
|
||||
result.params.push(tag);
|
||||
},
|
||||
'private': function (result) {
|
||||
result.access = 'private';
|
||||
},
|
||||
'prop': synonym('property'),
|
||||
'property': function (result, tag) {
|
||||
if (!result.properties) {
|
||||
result.properties = [];
|
||||
}
|
||||
result.properties.push(tag);
|
||||
},
|
||||
'protected': function (result) {
|
||||
result.access = 'protected';
|
||||
},
|
||||
'public': function (result) {
|
||||
result.access = 'public';
|
||||
},
|
||||
'return': synonym('returns'),
|
||||
'returns': function (result, tag) {
|
||||
if (!result.returns) {
|
||||
result.returns = [];
|
||||
}
|
||||
result.returns.push(tag);
|
||||
},
|
||||
'see': function (result, tag) {
|
||||
if (!result.sees) {
|
||||
result.sees = [];
|
||||
}
|
||||
result.sees.push(tag.description);
|
||||
},
|
||||
'since': flattenDescription,
|
||||
'static': function (result) {
|
||||
result.scope = 'static';
|
||||
},
|
||||
'summary': flattenDescription,
|
||||
'throws': function (result, tag) {
|
||||
if (!result.throws) {
|
||||
result.throws = [];
|
||||
}
|
||||
result.throws.push(tag);
|
||||
},
|
||||
'todo': function (result, tag) {
|
||||
if (!result.todos) {
|
||||
result.todos = [];
|
||||
}
|
||||
result.todos.push(tag.description);
|
||||
},
|
||||
'global': function (result) {
|
||||
result.scope = 'global';
|
||||
},
|
||||
'static': function (result) {
|
||||
result.scope = 'static';
|
||||
},
|
||||
'instance': function (result) {
|
||||
result.scope = 'instance';
|
||||
},
|
||||
'inner': function (result) {
|
||||
result.scope = 'inner';
|
||||
},
|
||||
'access': function (result, tag) {
|
||||
result.access = tag.access;
|
||||
},
|
||||
'public': function (result) {
|
||||
result.access = 'public';
|
||||
},
|
||||
'protected': function (result) {
|
||||
result.access = 'protected';
|
||||
},
|
||||
'private': function (result) {
|
||||
result.access = 'private';
|
||||
}
|
||||
'typedef': flattenTypedName,
|
||||
'var': synonym('member'),
|
||||
'version': flattenDescription,
|
||||
'virtual': synonym('abstract')
|
||||
};
|
||||
|
||||
function synonym(key) {
|
||||
return function (result, tag) {
|
||||
return flatteners[key](result, tag, key);
|
||||
};
|
||||
}
|
||||
|
||||
function flattenName(result, tag, key) {
|
||||
result[key] = tag.name;
|
||||
}
|
||||
|
||||
function flattenDescription(result, tag, key) {
|
||||
result[key] = tag.description;
|
||||
}
|
||||
|
||||
function flattenTypedName(result, tag, key) {
|
||||
result[key] = {
|
||||
name: tag.name
|
||||
};
|
||||
|
||||
if (tag.type) {
|
||||
result[key].type = tag.type;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flattens tags in an opinionated way.
|
||||
* Parse a comment with doctrine, decorate the result with file position and code
|
||||
* context, handle parsing errors, and fix up various infelicities in the structure
|
||||
* outputted by doctrine.
|
||||
*
|
||||
* The following tags are treated as synonyms for a canonical tag:
|
||||
*
|
||||
* * `@virtual` -> `@abstract`
|
||||
* * `@extends` -> `@augments`
|
||||
* * `@constructor` -> `@class`
|
||||
* * `@const` -> `@constant`
|
||||
* * `@defaultvalue` -> `@default`
|
||||
* * `@desc` -> `@description`
|
||||
* * `@host` -> `@external`
|
||||
* * `@fileoverview`, `@overview` -> `@file`
|
||||
* * `@emits` -> `@fires`
|
||||
* * `@func`, `@method` -> `@function`
|
||||
* * `@var` -> `@member`
|
||||
* * `@arg`, `@argument` -> `@param`
|
||||
* * `@prop` -> `@property`
|
||||
* * `@return` -> `@returns`
|
||||
* * `@exception` -> `@throws`
|
||||
* * `@linkcode`, `@linkplain` -> `@link`
|
||||
*
|
||||
* The following tags are assumed to be singletons, and are flattened
|
||||
* to a top-level property on the result whose value is extracted from
|
||||
@ -245,30 +219,11 @@ var flatteners = {
|
||||
* The assumed default value is `"public"`, so `@access public` or `@public`
|
||||
* tags result in no `access` property.
|
||||
*
|
||||
* @param {Object} comment a parsed comment
|
||||
* @return {Object} comment with tags flattened
|
||||
* @private
|
||||
*/
|
||||
function flatten(comment) {
|
||||
var result = extend({}, comment);
|
||||
|
||||
comment.tags.forEach(function (tag) {
|
||||
(flatteners[tag.title] || function () {})(result, tag);
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a comment with doctrine, decorate the result with file position and code
|
||||
* context, handle parsing errors, and fix up various infelicities in the structure
|
||||
* outputted by doctrine.
|
||||
*
|
||||
* @param {string} comment input to be parsed
|
||||
* @param {Object} loc location of the input
|
||||
* @param {Object} context code context of the input
|
||||
* @return {Object} an object conforming to the
|
||||
* [documentation JSON API](https://github.com/documentationjs/api-json) schema
|
||||
* @return {Comment} an object conforming to the
|
||||
* [documentation schema](https://github.com/documentationjs/api-json)
|
||||
*/
|
||||
function parseJSDoc(comment, loc, context) {
|
||||
var result = doctrine.parse(comment, {
|
||||
@ -286,20 +241,17 @@ function parseJSDoc(comment, loc, context) {
|
||||
result.context = context;
|
||||
result.errors = [];
|
||||
|
||||
var i = 0;
|
||||
while (i < result.tags.length) {
|
||||
var tag = result.tags[i];
|
||||
result.tags.forEach(function (tag) {
|
||||
if (tag.errors) {
|
||||
for (var j = 0; j < tag.errors.length; j++) {
|
||||
result.errors.push({message: tag.errors[j]});
|
||||
}
|
||||
result.tags.splice(i, 1);
|
||||
} else {
|
||||
i++;
|
||||
(flatteners[tag.title] || function () {})(result, tag, tag.title);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return flatten(normalize(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
module.exports = parseJSDoc;
|
||||
|
||||
@ -40,7 +40,7 @@
|
||||
"description": "This function returns the number one.",
|
||||
"tags": [
|
||||
{
|
||||
"title": "returns",
|
||||
"title": "return",
|
||||
"description": "numberone",
|
||||
"lineNumber": 2,
|
||||
"type": {
|
||||
@ -75,7 +75,7 @@
|
||||
"errors": [],
|
||||
"returns": [
|
||||
{
|
||||
"title": "returns",
|
||||
"title": "return",
|
||||
"description": "numberone",
|
||||
"lineNumber": 2,
|
||||
"type": {
|
||||
@ -128,7 +128,7 @@
|
||||
"column": 2
|
||||
}
|
||||
},
|
||||
"code": "'use strict';\n\nvar otherDep = require('external2');\n\n/**\n * This function returns the number one.\n * @return {Number} numberone\n */\nmodule.exports = function () {\n // this returns 1\n return otherDep() - 1;\n};\n"
|
||||
"code": "'use strict';\n\nvar otherDep = require('external2');\n\n/**\n * This function returns the number one.\n * @returns {Number} numberone\n */\nmodule.exports = function () {\n // this returns 1\n return otherDep() - 1;\n};\n"
|
||||
},
|
||||
"errors": [],
|
||||
"returns": [
|
||||
|
||||
@ -12,7 +12,7 @@ var area = function() {
|
||||
|
||||
/**
|
||||
* Sets the chart data.
|
||||
* @method
|
||||
* @function
|
||||
*/
|
||||
chart.data = function(_) {
|
||||
};
|
||||
|
||||
@ -33,7 +33,7 @@
|
||||
"column": 2
|
||||
}
|
||||
},
|
||||
"code": "/**\n * an area chart generator\n * @returns {area} chart\n */\nvar area = function() {\n\n /**\n * @class area\n */\n var chart = function(selection) {\n };\n\n /**\n * Sets the chart data.\n * @method\n */\n chart.data = function(_) {\n };\n\n return chart;\n};\n"
|
||||
"code": "/**\n * an area chart generator\n * @returns {area} chart\n */\nvar area = function() {\n\n /**\n * @class area\n */\n var chart = function(selection) {\n };\n\n /**\n * Sets the chart data.\n * @function\n */\n chart.data = function(_) {\n };\n\n return chart;\n};\n"
|
||||
},
|
||||
"errors": [],
|
||||
"returns": [
|
||||
@ -89,7 +89,7 @@
|
||||
"column": 4
|
||||
}
|
||||
},
|
||||
"code": "/**\n * an area chart generator\n * @returns {area} chart\n */\nvar area = function() {\n\n /**\n * @class area\n */\n var chart = function(selection) {\n };\n\n /**\n * Sets the chart data.\n * @method\n */\n chart.data = function(_) {\n };\n\n return chart;\n};\n"
|
||||
"code": "/**\n * an area chart generator\n * @returns {area} chart\n */\nvar area = function() {\n\n /**\n * @class area\n */\n var chart = function(selection) {\n };\n\n /**\n * Sets the chart data.\n * @function\n */\n chart.data = function(_) {\n };\n\n return chart;\n};\n"
|
||||
},
|
||||
"errors": [],
|
||||
"class": {
|
||||
@ -143,7 +143,7 @@
|
||||
"column": 4
|
||||
}
|
||||
},
|
||||
"code": "/**\n * an area chart generator\n * @returns {area} chart\n */\nvar area = function() {\n\n /**\n * @class area\n */\n var chart = function(selection) {\n };\n\n /**\n * Sets the chart data.\n * @method\n */\n chart.data = function(_) {\n };\n\n return chart;\n};\n"
|
||||
"code": "/**\n * an area chart generator\n * @returns {area} chart\n */\nvar area = function() {\n\n /**\n * @class area\n */\n var chart = function(selection) {\n };\n\n /**\n * Sets the chart data.\n * @function\n */\n chart.data = function(_) {\n };\n\n return chart;\n};\n"
|
||||
},
|
||||
"errors": [
|
||||
{
|
||||
|
||||
2
test/fixture/node_modules/external/lib/main.js
generated
vendored
2
test/fixture/node_modules/external/lib/main.js
generated
vendored
@ -4,7 +4,7 @@ var otherDep = require('external2');
|
||||
|
||||
/**
|
||||
* This function returns the number one.
|
||||
* @return {Number} numberone
|
||||
* @returns {Number} numberone
|
||||
*/
|
||||
module.exports = function () {
|
||||
// this returns 1
|
||||
|
||||
2
test/fixture/node_modules/external2/index.js
generated
vendored
2
test/fixture/node_modules/external2/index.js
generated
vendored
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* This function returns the number one.
|
||||
* @return {Number} numberone
|
||||
* @returns {Number} numberone
|
||||
*/
|
||||
module.exports = function () {
|
||||
// this returns 1
|
||||
|
||||
@ -3,5 +3,5 @@ function fooBaz() {
|
||||
}
|
||||
/**
|
||||
* this is a type
|
||||
* @return {number} nothing
|
||||
* @returns {number} nothing
|
||||
*/
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
/**
|
||||
* ONE
|
||||
* @return {number} something
|
||||
* @returns {number} something
|
||||
*/
|
||||
function fooBar() {
|
||||
return 1;
|
||||
}
|
||||
/**
|
||||
* TWO
|
||||
* @return {number} something
|
||||
* @returns {number} something
|
||||
*/
|
||||
function fooBaz() {
|
||||
return 2;
|
||||
|
||||
@ -33,7 +33,7 @@
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"code": "/**\n * ONE\n * @return {number} something\n */\nfunction fooBar() {\n return 1;\n}\n/**\n * TWO\n * @return {number} something\n */\nfunction fooBaz() {\n return 2;\n}\n/**\n * this is a type\n * @class Something\n */\n"
|
||||
"code": "/**\n * ONE\n * @returns {number} something\n */\nfunction fooBar() {\n return 1;\n}\n/**\n * TWO\n * @returns {number} something\n */\nfunction fooBaz() {\n return 2;\n}\n/**\n * this is a type\n * @class Something\n */\n"
|
||||
},
|
||||
"errors": [],
|
||||
"returns": [
|
||||
@ -91,7 +91,7 @@
|
||||
"column": 1
|
||||
}
|
||||
},
|
||||
"code": "/**\n * ONE\n * @return {number} something\n */\nfunction fooBar() {\n return 1;\n}\n/**\n * TWO\n * @return {number} something\n */\nfunction fooBaz() {\n return 2;\n}\n/**\n * this is a type\n * @class Something\n */\n"
|
||||
"code": "/**\n * ONE\n * @returns {number} something\n */\nfunction fooBar() {\n return 1;\n}\n/**\n * TWO\n * @returns {number} something\n */\nfunction fooBaz() {\n return 2;\n}\n/**\n * this is a type\n * @class Something\n */\n"
|
||||
},
|
||||
"errors": [],
|
||||
"returns": [
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user