dgeni-packages
Version:
A collection of dgeni packages for generating documentation from source code
113 lines (101 loc) • 3.16 kB
JavaScript
// Much of this code was inspired by or simply copied from the JSDOC project.
// See https://github.com/jsdoc3/jsdoc/blob/c9b0237c12144cfa48abe5fccd73ba2a1d46553a/lib/jsdoc/tag/type.js
const catharsis = require('catharsis');
var TYPE_EXPRESSION_START = /^\s*\{[^@]/;
/**
* Extract a type expression from the tag text.
*
* @private
* @param {Tag} tag The tag whose type should be extracted
*/
module.exports = function extractTypeTransform() {
return (doc, tag, value) => {
let start, position, count, length, expression;
const match = TYPE_EXPRESSION_START.exec(value);
if (match) {
length = value.length;
// the start is the beginning of the `{`
start = match[0].length - 2;
// advance to the first character in the type expression
position = match[0].length - 1;
count = 1;
while (position < length) {
switch (value[position]) {
case '\\':
// backslash is an escape character, so skip the next character
position++;
break;
case '{':
count++;
break;
case '}':
count--;
break;
default:
// do nothing
}
if (count === 0) {
break;
}
position++;
}
tag.typeExpression = value.slice(start+1, position).trim().replace('\\}', '}').replace('\\{', '{');
try {
tag.type = catharsis.parse(tag.typeExpression, {jsdoc: true});
tag.typeList = getTypeStrings(tag.type);
if ( tag.type.optional ) {
tag.optional = true;
}
tag.description = (value.substring(0, start) + value.substring(position+1)).trim();
} catch(x) {
console.log(tag);
throw new Error('Error parsing the jsdoc type expression "{' + tag.typeExpression + '}"', x);
}
return tag.description;
} else {
return value;
}
};
/** @private */
function getTypeStrings(parsedType) {
const types = [];
const TYPES = catharsis.Types;
const util = require('util');
switch(parsedType.type) {
case TYPES.AllLiteral:
types.push('*');
break;
case TYPES.FunctionType:
types.push(catharsis.stringify(parsedType));
break;
case TYPES.NameExpression:
types.push(parsedType.name);
break;
case TYPES.NullLiteral:
types.push('null');
break;
case TYPES.RecordType:
types.push(catharsis.stringify(parsedType));
break;
case TYPES.TypeApplication:
types.push( catharsis.stringify(parsedType) );
break;
case TYPES.TypeUnion:
parsedType.elements.forEach(element => {
types.push(...getTypeStrings(element));
});
break;
case TYPES.UndefinedLiteral:
types.push('undefined');
break;
case TYPES.UnknownLiteral:
types.push('?');
break;
default:
// this shouldn't happen
throw new Error( util.format('unrecognized type %s in parsed type: %j', parsedType.type,
parsedType) );
}
return types;
}
};