mirror of
https://github.com/jsdoc/jsdoc.git
synced 2025-12-08 19:46:11 +00:00
Merge branch 'types'
This commit is contained in:
commit
4bf63b4185
@ -18,6 +18,7 @@
|
|||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"async": "0.1.22",
|
"async": "0.1.22",
|
||||||
|
"catharsis": "0.5.0",
|
||||||
"crypto-browserify": "git://github.com/dominictarr/crypto-browserify.git#95c5d505",
|
"crypto-browserify": "git://github.com/dominictarr/crypto-browserify.git#95c5d505",
|
||||||
"github-flavored-markdown": "git://github.com/hegemonic/github-flavored-markdown.git",
|
"github-flavored-markdown": "git://github.com/hegemonic/github-flavored-markdown.git",
|
||||||
"js2xmlparser": "0.1.0",
|
"js2xmlparser": "0.1.0",
|
||||||
|
|||||||
10
LICENSE.md
10
LICENSE.md
@ -66,6 +66,16 @@ The source code for Async.js is available at:
|
|||||||
https://github.com/caolan/async
|
https://github.com/caolan/async
|
||||||
|
|
||||||
|
|
||||||
|
## Catharsis ##
|
||||||
|
|
||||||
|
Catharsis is distributed under the MIT license, which is reproduced above.
|
||||||
|
|
||||||
|
Copyright (c) 2012-2013 Jeff Williams.
|
||||||
|
|
||||||
|
The source code for Catharsis is available at:
|
||||||
|
https://github.com/hegemonic/catharsis
|
||||||
|
|
||||||
|
|
||||||
## crypto-browserify ##
|
## crypto-browserify ##
|
||||||
|
|
||||||
License information for crypto-browserify is not available. It is assumed that
|
License information for crypto-browserify is not available. It is assumed that
|
||||||
|
|||||||
@ -146,8 +146,8 @@ exports.defineTags = function(dictionary) {
|
|||||||
// Allow augments value to be specified as a normal type, e.g. {Type}
|
// Allow augments value to be specified as a normal type, e.g. {Type}
|
||||||
onTagText: function(text) {
|
onTagText: function(text) {
|
||||||
var type = require('jsdoc/tag/type'),
|
var type = require('jsdoc/tag/type'),
|
||||||
tagType = type.getTagInfo(text, false, true);
|
tagType = type.parse(text, false, true);
|
||||||
return tagType.type || text;
|
return tagType.typeExpression || text;
|
||||||
},
|
},
|
||||||
onTagged: function(doclet, tag) {
|
onTagged: function(doclet, tag) {
|
||||||
doclet.augment( firstWordOf(tag.value) );
|
doclet.augment( firstWordOf(tag.value) );
|
||||||
|
|||||||
115
lib/jsdoc/tag/inline.js
Normal file
115
lib/jsdoc/tag/inline.js
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/**
|
||||||
|
* @module jsdoc/tag/inline
|
||||||
|
*
|
||||||
|
* @author Jeff Williams <jeffrey.l.williams@gmail.com>
|
||||||
|
* @license Apache License 2.0 - See file 'LICENSE.md' in this project.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Information about the result of extracting an inline tag from a text string.
|
||||||
|
*
|
||||||
|
* @typedef {Object} InlineTagInfo
|
||||||
|
* @memberof module:jsdoc/tag/inline
|
||||||
|
* @property {?string} tag - The tag whose text was found, or `null` if no tag was specified.
|
||||||
|
* @property {string} text - The tag text that was found.
|
||||||
|
* @property {string} newString - The updated text string after extracting or replacing the inline
|
||||||
|
* tag.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function that replaces an inline tag with other text.
|
||||||
|
*
|
||||||
|
* @callback InlineTagReplacer
|
||||||
|
* @memberof module:jsdoc/tag/inline
|
||||||
|
* @param {string} string - The complete string containing the inline tag.
|
||||||
|
* @param {string} completeTag - The entire inline tag, including its enclosing braces.
|
||||||
|
* @param {string} tagText - The text contained in the inline tag.
|
||||||
|
* @return {string} An updated version of the string that contained the inline tag.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @private */
|
||||||
|
function unescapeBraces(text) {
|
||||||
|
return text.replace(/\\\{/g, '{')
|
||||||
|
.replace(/\\\}/g, '}');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace an inline tag with other text.
|
||||||
|
*
|
||||||
|
* To replace untagged text that is enclosed in braces, set the `tag` parameter to `null`.
|
||||||
|
*
|
||||||
|
* @param {string} string - The string in which to replace the inline tag.
|
||||||
|
* @param {?string} tag - The inline tag that must follow the opening brace (for example, `@link`).
|
||||||
|
* @param {module:jsdoc/tag/inline.InlineTagReplacer} replacer - The function that is used to
|
||||||
|
* replace text in the string.
|
||||||
|
* @return {module:jsdoc/tag/inline.InlineTagInfo} The updated string, as well as information about
|
||||||
|
* the inline tag.
|
||||||
|
*/
|
||||||
|
exports.replaceInlineTag = function(string, tag, replacer) {
|
||||||
|
string = string || '';
|
||||||
|
tag = tag || '';
|
||||||
|
|
||||||
|
var count = 0;
|
||||||
|
var position = 0;
|
||||||
|
var completeTag = '';
|
||||||
|
var text = '';
|
||||||
|
var start = '{' + tag;
|
||||||
|
var startIndex = string.indexOf(start);
|
||||||
|
var textStartIndex;
|
||||||
|
|
||||||
|
if (startIndex !== -1) {
|
||||||
|
// advance to the first character after `start`
|
||||||
|
position = textStartIndex = startIndex + start.length;
|
||||||
|
count++;
|
||||||
|
|
||||||
|
while (position < string.length) {
|
||||||
|
switch (string[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) {
|
||||||
|
completeTag = string.slice(startIndex, position + 1);
|
||||||
|
text = string.slice(textStartIndex, position).trim();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
position++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string = replacer.call(this, string, completeTag, text);
|
||||||
|
|
||||||
|
return {
|
||||||
|
tag: tag || null,
|
||||||
|
text: unescapeBraces(text),
|
||||||
|
newString: string.trim()
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract the first portion of a string that is enclosed in braces, with the `tag` parameter
|
||||||
|
* immediately following the opening brace.
|
||||||
|
*
|
||||||
|
* To extract untagged text that is enclosed in braces, omit the `tag` parameter.
|
||||||
|
*
|
||||||
|
* @param {string} string - The string from which to extract text.
|
||||||
|
* @param {?string} tag - The inline tag that must follow the opening brace (for example, `@link`).
|
||||||
|
* @return {module:jsdoc/tag/inline.InlineTagInfo} Information about the string and inline tag.
|
||||||
|
*/
|
||||||
|
exports.extractInlineTag = function(string, tag) {
|
||||||
|
return exports.replaceInlineTag(string, tag, function(string, completeTag,
|
||||||
|
tagText) {
|
||||||
|
return string.replace(completeTag, '');
|
||||||
|
});
|
||||||
|
};
|
||||||
@ -1,59 +1,26 @@
|
|||||||
/**
|
/**
|
||||||
@module jsdoc/tag/type
|
* @module jsdoc/tag/type
|
||||||
|
*
|
||||||
@author Michael Mathews <micmath@gmail.com>
|
* @author Michael Mathews <micmath@gmail.com>
|
||||||
@author Jeff Williams <jeffrey.l.williams@gmail.com>
|
* @author Jeff Williams <jeffrey.l.williams@gmail.com>
|
||||||
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
|
* @license Apache License 2.0 - See file 'LICENSE.md' in this project.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function parseTypes(type) {
|
|
||||||
var types = [];
|
|
||||||
|
|
||||||
if ( type.indexOf('|') !== -1 ) {
|
|
||||||
// remove optional parens, like: { ( string | number ) }
|
|
||||||
// see: http://code.google.com/closure/compiler/docs/js-for-compiler.html#types
|
|
||||||
if ( /^\s*\(\s*(.+)\s*\)\s*$/.test(type) ) {
|
|
||||||
type = RegExp.$1;
|
|
||||||
}
|
|
||||||
types = type.split(/\s*\|\s*/g);
|
|
||||||
}
|
|
||||||
else if (type) {
|
|
||||||
types = [type];
|
|
||||||
}
|
|
||||||
|
|
||||||
return types;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @private */
|
/** @private */
|
||||||
function trim(text) {
|
function getTagInfo(tagValue, canHaveName, canHaveType) {
|
||||||
return text.trim();
|
var extractInlineTag = require('jsdoc/tag/inline').extractInlineTag;
|
||||||
}
|
|
||||||
|
|
||||||
var getTagInfo = exports.getTagInfo = function(tagValue, canHaveName, canHaveType) {
|
var name = '';
|
||||||
var name = '',
|
var typeExpression = '';
|
||||||
type = '',
|
var text = tagValue;
|
||||||
text = tagValue,
|
var typeAndText;
|
||||||
count = 0;
|
var typeOverride;
|
||||||
|
|
||||||
// type expressions start with '{'
|
if (canHaveType) {
|
||||||
if (canHaveType && tagValue[0] === '{') {
|
typeAndText = extractInlineTag(text);
|
||||||
count++;
|
typeExpression = typeAndText.text || typeExpression;
|
||||||
|
text = typeAndText.newString;
|
||||||
// find matching closer '}'
|
|
||||||
for (var i = 1, leni = tagValue.length; i < leni; i++) {
|
|
||||||
if (tagValue[i] === '\\') { i++; continue; } // backslash escapes the next character
|
|
||||||
|
|
||||||
if (tagValue[i] === '{') { count++; }
|
|
||||||
else if (tagValue[i] === '}') { count--; }
|
|
||||||
|
|
||||||
if (count === 0) {
|
|
||||||
type = trim(tagValue.slice(1, i))
|
|
||||||
.replace(/\\\{/g, '{') // unescape escaped curly braces
|
|
||||||
.replace(/\\\}/g, '}');
|
|
||||||
text = trim(tagValue.slice(i+1));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (canHaveName) {
|
if (canHaveName) {
|
||||||
@ -63,32 +30,180 @@ var getTagInfo = exports.getTagInfo = function(tagValue, canHaveName, canHaveTyp
|
|||||||
text = RegExp.$3;
|
text = RegExp.$3;
|
||||||
}
|
}
|
||||||
|
|
||||||
return { name: name, type: type, text: text };
|
// an inline @type tag, like {@type Foo}, overrides the type expression
|
||||||
};
|
if (canHaveType) {
|
||||||
|
typeOverride = extractInlineTag(text, '@type');
|
||||||
|
typeExpression = typeOverride.text || typeExpression;
|
||||||
|
text = typeOverride.newString;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: name,
|
||||||
|
typeExpression: typeExpression,
|
||||||
|
text: text
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@param {string} tagValue
|
* Information provided in a JSDoc tag.
|
||||||
@param {boolean} canHaveName
|
*
|
||||||
@param {boolean} canHaveType
|
* @typedef {Object} TagInfo
|
||||||
@returns {object} Hash with name, type, text, optional, nullable, variable, and defaultvalue properties
|
* @memberof module:jsdoc/tag/type
|
||||||
|
* @property {string} TagInfo.defaultvalue - The default value of the member.
|
||||||
|
* @property {string} TagInfo.name - The name of the member (for example, `myParamName`).
|
||||||
|
* @property {boolean} TagInfo.nullable - Indicates whether the member can be set to `null` or
|
||||||
|
* `undefined`.
|
||||||
|
* @property {boolean} TagInfo.optional - Indicates whether the member is optional.
|
||||||
|
* @property {string} TagInfo.text - Descriptive text for the member (for example, `The user's email
|
||||||
|
* address.`).
|
||||||
|
* @property {Array.<string>} TagInfo.type - The type or types that the member can contain (for
|
||||||
|
* example, `string` or `MyNamespace.MyClass`).
|
||||||
|
* @property {string} TagInfo.typeExpression - The type expression that was parsed to identify the
|
||||||
|
* types.
|
||||||
|
* @property {boolean} TagInfo.variable - Indicates whether the number of members that are provided
|
||||||
|
* can vary (for example, in a function that accepts any number of parameters).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract JSDoc-style type information from the name specified in the tag info, including the
|
||||||
|
* member name; whether the member is optional; and the default value of the member.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {module:jsdoc/tag/type.TagInfo} tagInfo - Information contained in the tag.
|
||||||
|
* @return {module:jsdoc/tag/type.TagInfo} Updated information from the tag.
|
||||||
|
*/
|
||||||
|
function parseName(tagInfo) {
|
||||||
|
// like '[foo]' or '[ foo ]' or '[foo=bar]' or '[ foo=bar ]' or '[ foo = bar ]'
|
||||||
|
if ( /^\[\s*(.+?)\s*\]$/.test(tagInfo.name) ) {
|
||||||
|
tagInfo.name = RegExp.$1;
|
||||||
|
tagInfo.optional = true;
|
||||||
|
|
||||||
|
// like 'foo=bar' or 'foo = bar'
|
||||||
|
if ( /^(.+?)\s*=\s*(.+)$/.test(tagInfo.name) ) {
|
||||||
|
tagInfo.name = RegExp.$1;
|
||||||
|
tagInfo.defaultvalue = RegExp.$2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tagInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @private */
|
||||||
|
function getTypeStrings(parsedType) {
|
||||||
|
var types = [];
|
||||||
|
|
||||||
|
var catharsis = require('catharsis');
|
||||||
|
var TYPES = catharsis.Types;
|
||||||
|
var util = require('util');
|
||||||
|
|
||||||
|
switch(parsedType.type) {
|
||||||
|
case TYPES.AllLiteral:
|
||||||
|
types.push('*');
|
||||||
|
break;
|
||||||
|
case TYPES.FunctionType:
|
||||||
|
types.push('function');
|
||||||
|
break;
|
||||||
|
case TYPES.NameExpression:
|
||||||
|
types.push(parsedType.name);
|
||||||
|
break;
|
||||||
|
case TYPES.NullLiteral:
|
||||||
|
types.push('null');
|
||||||
|
break;
|
||||||
|
case TYPES.RecordType:
|
||||||
|
types.push('Object');
|
||||||
|
break;
|
||||||
|
case TYPES.TypeApplication:
|
||||||
|
types.push( catharsis.stringify(parsedType) );
|
||||||
|
break;
|
||||||
|
case TYPES.TypeUnion:
|
||||||
|
parsedType.elements.forEach(function(element) {
|
||||||
|
types = types.concat( 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract JSDoc-style and Closure Compiler-style type information from the type expression
|
||||||
|
* specified in the tag info.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {module:jsdoc/tag/type.TagInfo} tagInfo - Information contained in the tag.
|
||||||
|
* @return {module:jsdoc/tag/type.TagInfo} Updated information from the tag.
|
||||||
|
*/
|
||||||
|
function parseTypeExpression(tagInfo) {
|
||||||
|
var catharsis = require('catharsis');
|
||||||
|
var util = require('util');
|
||||||
|
|
||||||
|
var errorMessage;
|
||||||
|
var parsedType;
|
||||||
|
|
||||||
|
// don't try to parse empty type expressions
|
||||||
|
if (!tagInfo.typeExpression) {
|
||||||
|
return tagInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
parsedType = catharsis.parse(tagInfo.typeExpression, {jsdoc: true});
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
errorMessage = util.format('unable to parse the type expression "%s": %s',
|
||||||
|
tagInfo.typeExpression, e.message);
|
||||||
|
require('jsdoc/util/error').handle( new Error(errorMessage) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parsedType) {
|
||||||
|
tagInfo.type = tagInfo.type.concat( getTypeStrings(parsedType) );
|
||||||
|
|
||||||
|
['optional', 'nullable', 'variable'].forEach(function(key) {
|
||||||
|
if (parsedType[key] !== null && parsedType[key] !== undefined) {
|
||||||
|
tagInfo[key] = parsedType[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return tagInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: allow users to add/remove type parsers (perhaps via plugins)
|
||||||
|
var typeParsers = [parseName, parseTypeExpression];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the value of a JSDoc tag.
|
||||||
|
*
|
||||||
|
* @param {string} tagValue - The value of the tag. For example, the tag `@param {string} name` has
|
||||||
|
* a value of `{string} name`.
|
||||||
|
* @param {boolean} canHaveName - Indicates whether the value can include a member name.
|
||||||
|
* @param {boolean} canHaveType - Indicates whether the value can include a type expression that
|
||||||
|
* describes the member.
|
||||||
|
* @return {module:jsdoc/tag/type.TagInfo} Information obtained from the tag.
|
||||||
*/
|
*/
|
||||||
exports.parse = function(tagValue, canHaveName, canHaveType) {
|
exports.parse = function(tagValue, canHaveName, canHaveType) {
|
||||||
if (typeof tagValue !== 'string') { tagValue = ''; }
|
if (typeof tagValue !== 'string') { tagValue = ''; }
|
||||||
|
|
||||||
var tagInfo = getTagInfo(tagValue, canHaveName, canHaveType);
|
var tagInfo = getTagInfo(tagValue, canHaveName, canHaveType);
|
||||||
|
tagInfo.type = tagInfo.type || [];
|
||||||
|
|
||||||
// extract JSDoc-style type info, then Closure Compiler-style type info
|
typeParsers.forEach(function(parser) {
|
||||||
tagInfo = require('jsdoc/tag/type/jsdocType').parse(tagInfo);
|
tagInfo = parser.call(this, tagInfo);
|
||||||
tagInfo = require('jsdoc/tag/type/closureCompilerType').parse(tagInfo);
|
});
|
||||||
|
|
||||||
return {
|
// if we wanted a type, but the parsers didn't add any type names, use the type expression
|
||||||
name: tagInfo.name,
|
if (canHaveType && !tagInfo.type.length && tagInfo.typeExpression) {
|
||||||
type: parseTypes(tagInfo.type), // make it into an array
|
tagInfo.type = [tagInfo.typeExpression];
|
||||||
text: tagInfo.text,
|
}
|
||||||
optional: tagInfo.optional,
|
|
||||||
nullable: tagInfo.nullable,
|
return tagInfo;
|
||||||
variable: tagInfo.variable,
|
|
||||||
defaultvalue: tagInfo.defaultvalue
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,64 +0,0 @@
|
|||||||
/**
|
|
||||||
@module jsdoc/tag/type/closureCompilerType
|
|
||||||
|
|
||||||
@author Michael Mathews <micmath@gmail.com>
|
|
||||||
@author Jeff Williams <jeffrey.l.williams@gmail.com>
|
|
||||||
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
|
|
||||||
*/
|
|
||||||
|
|
||||||
function parseOptional(type) {
|
|
||||||
var optional = null;
|
|
||||||
|
|
||||||
// {sometype=} means optional
|
|
||||||
if ( /(.+)=$/.test(type) ) {
|
|
||||||
type = RegExp.$1;
|
|
||||||
optional = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return { type: type, optional: optional };
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseNullable(type) {
|
|
||||||
var nullable = null;
|
|
||||||
|
|
||||||
// {?sometype} means nullable, {!sometype} means not-nullable
|
|
||||||
if ( /^([\?\!])(.+)$/.test(type) ) {
|
|
||||||
type = RegExp.$2;
|
|
||||||
nullable = (RegExp.$1 === '?')? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return { type: type, nullable: nullable };
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseVariable(type) {
|
|
||||||
var variable = null;
|
|
||||||
|
|
||||||
// {...sometype} means variable number of that type
|
|
||||||
if ( /^(\.\.\.)(.+)$/.test(type) ) {
|
|
||||||
type = RegExp.$2;
|
|
||||||
variable = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return { type: type, variable: variable };
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Extract Closure Compiler-style type information from the tag info.
|
|
||||||
@param {object} tagInfo Hash with name, type, and text properties.
|
|
||||||
@return {object} Hash with name, type, text, optional, nullable, variable, and default properties.
|
|
||||||
*/
|
|
||||||
exports.parse = function(tagInfo) {
|
|
||||||
var optional = parseOptional(tagInfo.type),
|
|
||||||
nullable = parseNullable(optional.type),
|
|
||||||
variable = parseVariable(nullable.type);
|
|
||||||
|
|
||||||
return {
|
|
||||||
name: tagInfo.name,
|
|
||||||
type: variable.type,
|
|
||||||
text: tagInfo.text,
|
|
||||||
optional: tagInfo.optional || optional.optional, // don't override if already true
|
|
||||||
nullable: nullable.nullable,
|
|
||||||
variable: variable.variable,
|
|
||||||
defaultvalue: tagInfo.defaultvalue
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@ -1,40 +0,0 @@
|
|||||||
/**
|
|
||||||
@module jsdoc/tag/type/jsdocType
|
|
||||||
|
|
||||||
@author Michael Mathews <micmath@gmail.com>
|
|
||||||
@author Jeff Williams <jeffrey.l.williams@gmail.com>
|
|
||||||
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
Extract JSDoc-style type information from the tag info.
|
|
||||||
@param {object} tagInfo Hash with name, type, text, optional, nullable, variable, and default properties.
|
|
||||||
@return {object} Hash with the same properties as tagInfo.
|
|
||||||
*/
|
|
||||||
exports.parse = function(tagInfo) {
|
|
||||||
var name = tagInfo.name,
|
|
||||||
optional,
|
|
||||||
tagDefault;
|
|
||||||
|
|
||||||
// like '[foo]' or '[ foo ]' or '[foo=bar]' or '[ foo=bar ]' or '[ foo = bar ]'
|
|
||||||
if ( /^\[\s*(.+?)\s*\]$/.test(name) ) {
|
|
||||||
name = RegExp.$1;
|
|
||||||
optional = true;
|
|
||||||
|
|
||||||
// like 'foo=bar' or 'foo = bar'
|
|
||||||
if ( /^(.+?)\s*=\s*(.+)$/.test(name) ) {
|
|
||||||
name = RegExp.$1;
|
|
||||||
tagDefault = RegExp.$2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
name: name,
|
|
||||||
type: tagInfo.type,
|
|
||||||
text: tagInfo.text,
|
|
||||||
optional: optional,
|
|
||||||
nullable: tagInfo.nullable,
|
|
||||||
variable: tagInfo.variable,
|
|
||||||
defaultvalue: tagDefault
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@ -25,7 +25,7 @@ var tutorial = require('jsdoc/tutorial'),
|
|||||||
*/
|
*/
|
||||||
function isTutorialJSON(json) {
|
function isTutorialJSON(json) {
|
||||||
// if conf.title exists or conf.children exists, it is metadata for a tutorial
|
// if conf.title exists or conf.children exists, it is metadata for a tutorial
|
||||||
return (json.hasOwnProperty('title') || json.hasOwnProperty('children'));
|
return (hasOwnProp.call(json, 'title') || hasOwnProp.call(json, 'children'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Helper function that adds tutorial configuration to the `conf` variable.
|
/** Helper function that adds tutorial configuration to the `conf` variable.
|
||||||
@ -50,7 +50,7 @@ function addTutorialConf(name, meta) {
|
|||||||
if (isTutorialJSON(meta)) {
|
if (isTutorialJSON(meta)) {
|
||||||
// if the children are themselves tutorial defintions as opposed to an
|
// if the children are themselves tutorial defintions as opposed to an
|
||||||
// array of strings, add each child.
|
// array of strings, add each child.
|
||||||
if (meta.hasOwnProperty('children') && !Array.isArray(meta.children)) {
|
if (hasOwnProp.call(meta, 'children') && !Array.isArray(meta.children)) {
|
||||||
names = Object.keys(meta.children);
|
names = Object.keys(meta.children);
|
||||||
for (i = 0; i < names.length; ++i) {
|
for (i = 0; i < names.length; ++i) {
|
||||||
addTutorialConf(names[i], meta.children[names[i]]);
|
addTutorialConf(names[i], meta.children[names[i]]);
|
||||||
@ -59,7 +59,7 @@ function addTutorialConf(name, meta) {
|
|||||||
meta.children = names;
|
meta.children = names;
|
||||||
}
|
}
|
||||||
// check if the tutorial has already been defined...
|
// check if the tutorial has already been defined...
|
||||||
if (conf.hasOwnProperty(name)) {
|
if (hasOwnProp.call(conf, name)) {
|
||||||
error.handle(new Error("Tutorial " + name + "'s metadata is defined multiple times, only the first will be used."));
|
error.handle(new Error("Tutorial " + name + "'s metadata is defined multiple times, only the first will be used."));
|
||||||
} else {
|
} else {
|
||||||
conf[name] = meta;
|
conf[name] = meta;
|
||||||
@ -77,7 +77,7 @@ function addTutorialConf(name, meta) {
|
|||||||
@param {tutorial.Tutorial} current - New tutorial.
|
@param {tutorial.Tutorial} current - New tutorial.
|
||||||
*/
|
*/
|
||||||
exports.addTutorial = function(current) {
|
exports.addTutorial = function(current) {
|
||||||
if (tutorials.hasOwnProperty(current.name)) {
|
if (hasOwnProp.call(tutorials, current.name)) {
|
||||||
error.handle(new Error("Tutorial with name " + current.name + " exists more than once, not adding (same name, different file extensions?)"));
|
error.handle(new Error("Tutorial with name " + current.name + " exists more than once, not adding (same name, different file extensions?)"));
|
||||||
} else {
|
} else {
|
||||||
tutorials[current.name] = current;
|
tutorials[current.name] = current;
|
||||||
|
|||||||
@ -100,10 +100,41 @@ var tutorialLinkMap = {
|
|||||||
|
|
||||||
var longnameToUrl = exports.longnameToUrl = linkMap.longnameToUrl;
|
var longnameToUrl = exports.longnameToUrl = linkMap.longnameToUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve an HTML link to the member with the specified longname. If the longname is not
|
||||||
|
* associated with a URL, this method returns the link text, if provided, or the longname.
|
||||||
|
*
|
||||||
|
* This method supports type applications that can contain one or more types, such as
|
||||||
|
* `Array.<MyClass>` or `Array.<(MyClass|YourClass)>`. In these examples, the method attempts to
|
||||||
|
* replace `Array`, `MyClass`, and `YourClass` with links to the appropriate types. The link text
|
||||||
|
* is ignored for type applications.
|
||||||
|
*
|
||||||
|
* @param {string} longname - The longname that is the target of the link.
|
||||||
|
* @param {string=} linktext - The text to display for the link, or `longname` if no text is
|
||||||
|
* provided.
|
||||||
|
* @param {string=} cssClass - The CSS class (or classes) to include in the link's `<a>` tag.
|
||||||
|
* @return {string} The HTML link, or a plain-text string if the link is not available.
|
||||||
|
*/
|
||||||
var linkto = exports.linkto = function(longname, linktext, cssClass) {
|
var linkto = exports.linkto = function(longname, linktext, cssClass) {
|
||||||
|
var catharsis = require('catharsis');
|
||||||
|
|
||||||
var classString = cssClass ? util.format(' class="%s"', cssClass) : '';
|
var classString = cssClass ? util.format(' class="%s"', cssClass) : '';
|
||||||
var text = linktext || longname;
|
var text = linktext || longname;
|
||||||
var url = hasOwnProp.call(longnameToUrl, longname) && longnameToUrl[longname];
|
var url = hasOwnProp.call(longnameToUrl, longname) && longnameToUrl[longname];
|
||||||
|
var parsedType;
|
||||||
|
|
||||||
|
// type applications require special treatment
|
||||||
|
var typeAppInfo = /(\S+)<(\S+)>/.exec(longname);
|
||||||
|
if (typeAppInfo) {
|
||||||
|
typeAppInfo[1] = linkto(typeAppInfo[1], null, cssClass);
|
||||||
|
parsedType = catharsis.parse(typeAppInfo[2], {jsdoc: true});
|
||||||
|
typeAppInfo[2] = catharsis.stringify(parsedType, {
|
||||||
|
cssClass: cssClass,
|
||||||
|
htmlSafe: true,
|
||||||
|
links: longnameToUrl
|
||||||
|
});
|
||||||
|
return typeAppInfo[1] + '<' + typeAppInfo[2] + '>';
|
||||||
|
}
|
||||||
|
|
||||||
if (!url) {
|
if (!url) {
|
||||||
return text;
|
return text;
|
||||||
|
|||||||
16
node_modules/catharsis/LICENSE
generated
vendored
Normal file
16
node_modules/catharsis/LICENSE
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
Copyright (c) 2012-2013 Jeff Williams
|
||||||
|
|
||||||
|
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.
|
||||||
119
node_modules/catharsis/catharsis.js
generated
vendored
Normal file
119
node_modules/catharsis/catharsis.js
generated
vendored
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
/**
|
||||||
|
* catharsis 0.4.2
|
||||||
|
* A parser for Google Closure Compiler type expressions, powered by PEG.js.
|
||||||
|
*
|
||||||
|
* @author Jeff Williams <jeffrey.l.williams@gmail.com>
|
||||||
|
* @license MIT License <http://opensource.org/licenses/mit-license.php/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var parse = require('./lib/parser').parse;
|
||||||
|
var stringify = require('./lib/stringify');
|
||||||
|
|
||||||
|
var typeExpressionCache = {
|
||||||
|
normal: {},
|
||||||
|
jsdoc: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
var parsedTypeCache = {
|
||||||
|
normal: {},
|
||||||
|
htmlSafe: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
function getTypeExpressionCache(options) {
|
||||||
|
if (options.useCache === false) {
|
||||||
|
return null;
|
||||||
|
} else if (options.jsdoc === true) {
|
||||||
|
return typeExpressionCache.jsdoc;
|
||||||
|
} else {
|
||||||
|
return typeExpressionCache.normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getParsedTypeCache(options) {
|
||||||
|
if (options.useCache === false || options.links !== null || options.links !== undefined) {
|
||||||
|
return null;
|
||||||
|
} else if (options.htmlSafe === true) {
|
||||||
|
return parsedTypeCache.htmlSafe;
|
||||||
|
} else {
|
||||||
|
return parsedTypeCache.normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// can't return the original if any of the following are true:
|
||||||
|
// 1. restringification was requested
|
||||||
|
// 2. htmlSafe option was requested
|
||||||
|
// 3. links option was provided
|
||||||
|
// 4. typeExpression property is missing
|
||||||
|
function canReturnOriginalExpression(parsedType, options) {
|
||||||
|
return options.restringify !== true && options.htmlSafe !== true &&
|
||||||
|
(options.links === null || options.links === undefined) &&
|
||||||
|
Object.prototype.hasOwnProperty.call(parsedType, 'typeExpression');
|
||||||
|
}
|
||||||
|
|
||||||
|
function cachedParse(expr, options) {
|
||||||
|
var cache = getTypeExpressionCache(options);
|
||||||
|
var parsedType;
|
||||||
|
|
||||||
|
if (cache && cache[expr]) {
|
||||||
|
return cache[expr];
|
||||||
|
} else {
|
||||||
|
parsedType = parse(expr, options);
|
||||||
|
|
||||||
|
Object.defineProperties(parsedType, {
|
||||||
|
typeExpression: {
|
||||||
|
value: expr
|
||||||
|
},
|
||||||
|
jsdoc: {
|
||||||
|
value: options.jsdoc === true ? true : false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
parsedType = Object.freeze(parsedType);
|
||||||
|
|
||||||
|
if (cache) {
|
||||||
|
cache[expr] = parsedType;
|
||||||
|
}
|
||||||
|
|
||||||
|
return parsedType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function cachedStringify(parsedType, options) {
|
||||||
|
var cache = getParsedTypeCache(options);
|
||||||
|
var json;
|
||||||
|
|
||||||
|
if (canReturnOriginalExpression(parsedType, options)) {
|
||||||
|
return parsedType.typeExpression;
|
||||||
|
} else if (cache) {
|
||||||
|
json = JSON.stringify(parsedType);
|
||||||
|
cache[json] = cache[json] || stringify(parsedType, options);
|
||||||
|
return cache[json];
|
||||||
|
} else {
|
||||||
|
return stringify(parsedType, options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Catharsis() {
|
||||||
|
this.Types = require('./lib/types');
|
||||||
|
}
|
||||||
|
|
||||||
|
Catharsis.prototype.parse = function(typeExpr, options) {
|
||||||
|
options = options || {};
|
||||||
|
|
||||||
|
return cachedParse(typeExpr, options);
|
||||||
|
};
|
||||||
|
|
||||||
|
Catharsis.prototype.stringify = function(parsedType, options) {
|
||||||
|
options = options || {};
|
||||||
|
var result;
|
||||||
|
|
||||||
|
result = cachedStringify(parsedType, options);
|
||||||
|
if (options.validate) {
|
||||||
|
this.parse(result, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = new Catharsis();
|
||||||
3
node_modules/catharsis/lib/parser.js
generated
vendored
Normal file
3
node_modules/catharsis/lib/parser.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
257
node_modules/catharsis/lib/stringify.js
generated
vendored
Normal file
257
node_modules/catharsis/lib/stringify.js
generated
vendored
Normal file
@ -0,0 +1,257 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Types = require('./types');
|
||||||
|
|
||||||
|
function Stringifier(options) {
|
||||||
|
this._options = options || {};
|
||||||
|
|
||||||
|
// in a list of function signature params, repeatable params are stringified differently
|
||||||
|
this._inFunctionSignatureParams = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Stringifier.prototype.applications = function(applications) {
|
||||||
|
if (!applications) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
var parsedApplications = [];
|
||||||
|
var result = '';
|
||||||
|
|
||||||
|
for (var i = 0, l = applications.length; i < l; i++) {
|
||||||
|
parsedApplications.push(this.type(applications[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._options.htmlSafe) {
|
||||||
|
result = '.<';
|
||||||
|
} else {
|
||||||
|
result = '.<';
|
||||||
|
}
|
||||||
|
|
||||||
|
result += parsedApplications.join(', ') + '>';
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
Stringifier.prototype.elements = function(elements) {
|
||||||
|
if (!elements) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = [];
|
||||||
|
|
||||||
|
for (var i = 0, l = elements.length; i < l; i++) {
|
||||||
|
result.push(this.type(elements[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
return '(' + result.join('|') + ')';
|
||||||
|
};
|
||||||
|
|
||||||
|
Stringifier.prototype.name = function(name) {
|
||||||
|
return name || '';
|
||||||
|
};
|
||||||
|
|
||||||
|
Stringifier.prototype['new'] = function(funcNew) {
|
||||||
|
return funcNew ? 'new:' + this.type(funcNew) : '';
|
||||||
|
};
|
||||||
|
|
||||||
|
Stringifier.prototype.nullable = function(nullable) {
|
||||||
|
switch (nullable) {
|
||||||
|
case true:
|
||||||
|
return '?';
|
||||||
|
case false:
|
||||||
|
return '!';
|
||||||
|
default:
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Stringifier.prototype.optional = function(optional) {
|
||||||
|
/*jshint boss: true */ // TODO: remove after JSHint releases the fix for jshint/jshint#878
|
||||||
|
if (optional === true) {
|
||||||
|
return '=';
|
||||||
|
} else {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Stringifier.prototype.params = function(params) {
|
||||||
|
if (!params || params.length === 0) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = [];
|
||||||
|
|
||||||
|
var param;
|
||||||
|
for (var i = 0, l = params.length; i < l; i++) {
|
||||||
|
result.push(this.type(params[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.join(', ');
|
||||||
|
};
|
||||||
|
|
||||||
|
Stringifier.prototype.properties = function(props) {
|
||||||
|
if (!props) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = [];
|
||||||
|
|
||||||
|
for (var i = 0, l = props.length; i < l; i++) {
|
||||||
|
result.push(this._formatNameAndType(props[i].name, props[i].type));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
Stringifier.prototype.result = function(result) {
|
||||||
|
return result ? ': ' + this.type(result) : '';
|
||||||
|
};
|
||||||
|
|
||||||
|
Stringifier.prototype['this'] = function(funcThis) {
|
||||||
|
return funcThis ? 'this:' + this.type(funcThis) : '';
|
||||||
|
};
|
||||||
|
|
||||||
|
Stringifier.prototype.type = function(type) {
|
||||||
|
if (!type) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// nullable comes first
|
||||||
|
var result = this.nullable(type.nullable);
|
||||||
|
|
||||||
|
// next portion varies by type
|
||||||
|
switch(type.type) {
|
||||||
|
case Types.AllLiteral:
|
||||||
|
result += this._formatNameAndType(type, '*');
|
||||||
|
break;
|
||||||
|
case Types.FunctionType:
|
||||||
|
result += this._signature(type);
|
||||||
|
break;
|
||||||
|
case Types.NullLiteral:
|
||||||
|
result += this._formatNameAndType(type, 'null');
|
||||||
|
break;
|
||||||
|
case Types.RecordType:
|
||||||
|
result += this._record(type);
|
||||||
|
break;
|
||||||
|
case Types.TypeApplication:
|
||||||
|
result += this.type(type.expression);
|
||||||
|
result += this.applications(type.applications);
|
||||||
|
break;
|
||||||
|
case Types.UndefinedLiteral:
|
||||||
|
result += this._formatNameAndType(type, 'undefined');
|
||||||
|
break;
|
||||||
|
case Types.TypeUnion:
|
||||||
|
result += this.elements(type.elements);
|
||||||
|
break;
|
||||||
|
case Types.UnknownLiteral:
|
||||||
|
result += this._formatNameAndType(type, '?');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
result += this._formatNameAndType(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
// finally, optionality
|
||||||
|
result += this.optional(type.optional);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
Stringifier.prototype.stringify = Stringifier.prototype.type;
|
||||||
|
|
||||||
|
Stringifier.prototype.key = Stringifier.prototype.type;
|
||||||
|
|
||||||
|
Stringifier.prototype._record = function(type) {
|
||||||
|
var fields = this._recordFields(type.fields);
|
||||||
|
|
||||||
|
return '{' + fields.join(', ') + '}';
|
||||||
|
};
|
||||||
|
|
||||||
|
Stringifier.prototype._recordFields = function(fields) {
|
||||||
|
if (!fields) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = [];
|
||||||
|
|
||||||
|
var field;
|
||||||
|
var keyAndValue;
|
||||||
|
|
||||||
|
for (var i = 0, l = fields.length; i < l; i++) {
|
||||||
|
field = fields[i];
|
||||||
|
|
||||||
|
keyAndValue = this.key(field.key);
|
||||||
|
keyAndValue += field.value ? ': ' + this.type(field.value) : '';
|
||||||
|
|
||||||
|
result.push(keyAndValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
function combineNameAndType(nameString, typeString) {
|
||||||
|
var separator = (nameString && typeString) ? ':' : '';
|
||||||
|
return nameString + separator + typeString;
|
||||||
|
}
|
||||||
|
|
||||||
|
Stringifier.prototype._formatRepeatable = function(nameString, typeString) {
|
||||||
|
var open = this._inFunctionSignatureParams ? '...[' : '...';
|
||||||
|
var close = this._inFunctionSignatureParams ? ']' : '';
|
||||||
|
|
||||||
|
return open + combineNameAndType(nameString, typeString) + close;
|
||||||
|
};
|
||||||
|
|
||||||
|
Stringifier.prototype._formatNameAndType = function(type, literal) {
|
||||||
|
var nameString = type.name || literal || '';
|
||||||
|
var typeString = type.type ? this.type(type.type) : '';
|
||||||
|
var cssClass;
|
||||||
|
var openTag;
|
||||||
|
|
||||||
|
// replace the type with an HTML link if necessary
|
||||||
|
if (this._options.links && Object.prototype.hasOwnProperty.call(this._options.links,
|
||||||
|
nameString)) {
|
||||||
|
cssClass = this._options.cssClass ? ' class="' + this._options.cssClass + '"' : '';
|
||||||
|
|
||||||
|
openTag = '<a href="' + this._options.links[nameString] + '"' + cssClass + '>';
|
||||||
|
nameString = openTag + nameString + '</a>';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type.repeatable === true) {
|
||||||
|
return this._formatRepeatable(nameString, typeString);
|
||||||
|
} else {
|
||||||
|
return combineNameAndType(nameString, typeString);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Stringifier.prototype._signature = function(type) {
|
||||||
|
var params = [];
|
||||||
|
var param;
|
||||||
|
var result;
|
||||||
|
|
||||||
|
// these go within the signature's parens, in this order
|
||||||
|
var props = [
|
||||||
|
'new',
|
||||||
|
'this',
|
||||||
|
'params'
|
||||||
|
];
|
||||||
|
var prop;
|
||||||
|
|
||||||
|
this._inFunctionSignatureParams = true;
|
||||||
|
for (var i = 0, l = props.length; i < l; i++) {
|
||||||
|
prop = props[i];
|
||||||
|
param = this[prop](type[prop]);
|
||||||
|
if (param.length > 0) {
|
||||||
|
params.push(param);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this._inFunctionSignatureParams = false;
|
||||||
|
|
||||||
|
result = 'function(' + params.join(', ') + ')';
|
||||||
|
result += this.result(type.result);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = function(type, options) {
|
||||||
|
return new Stringifier(options).stringify(type);
|
||||||
|
};
|
||||||
24
node_modules/catharsis/lib/types.js
generated
vendored
Normal file
24
node_modules/catharsis/lib/types.js
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = Object.freeze({
|
||||||
|
// `*`
|
||||||
|
AllLiteral: 'AllLiteral',
|
||||||
|
// like `blah` in `{blah: string}`
|
||||||
|
FieldType: 'FieldType',
|
||||||
|
// like `function(string): string`
|
||||||
|
FunctionType: 'FunctionType',
|
||||||
|
// any string literal, such as `string` or `My.Namespace`
|
||||||
|
NameExpression: 'NameExpression',
|
||||||
|
// null
|
||||||
|
NullLiteral: 'NullLiteral',
|
||||||
|
// like `{foo: string}`
|
||||||
|
RecordType: 'RecordType',
|
||||||
|
// like `Array.<string>`
|
||||||
|
TypeApplication: 'TypeApplication',
|
||||||
|
// like `(number|string)`
|
||||||
|
TypeUnion: 'TypeUnion',
|
||||||
|
// undefined
|
||||||
|
UndefinedLiteral: 'UndefinedLiteral',
|
||||||
|
// `?`
|
||||||
|
UnknownLiteral: 'UnknownLiteral'
|
||||||
|
});
|
||||||
44
node_modules/catharsis/package.json
generated
vendored
Normal file
44
node_modules/catharsis/package.json
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "jsdoc",
|
"name": "jsdoc",
|
||||||
"version": "3.2.0-dev",
|
"version": "3.2.0-dev",
|
||||||
"revision": "1359085455394",
|
"revision": "1363617959876",
|
||||||
"description": "An API documentation generator for JavaScript.",
|
"description": "An API documentation generator for JavaScript.",
|
||||||
"keywords": [ "documentation", "javascript" ],
|
"keywords": [ "documentation", "javascript" ],
|
||||||
"licenses": [
|
"licenses": [
|
||||||
@ -18,6 +18,7 @@
|
|||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"async": "0.1.22",
|
"async": "0.1.22",
|
||||||
|
"catharsis": "0.5.0",
|
||||||
"crypto-browserify": "git://github.com/dominictarr/crypto-browserify.git#95c5d505",
|
"crypto-browserify": "git://github.com/dominictarr/crypto-browserify.git#95c5d505",
|
||||||
"github-flavored-markdown": "git://github.com/hegemonic/github-flavored-markdown.git",
|
"github-flavored-markdown": "git://github.com/hegemonic/github-flavored-markdown.git",
|
||||||
"js2xmlparser": "0.1.0",
|
"js2xmlparser": "0.1.0",
|
||||||
|
|||||||
201
test/specs/jsdoc/tag/inline.js
Normal file
201
test/specs/jsdoc/tag/inline.js
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
/*global describe: true, expect: true, it: true */
|
||||||
|
|
||||||
|
describe('jsdoc/tag/inline', function() {
|
||||||
|
var jsdoc = {
|
||||||
|
tag: {
|
||||||
|
inline: require('jsdoc/tag/inline')
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
it('should exist', function() {
|
||||||
|
expect(jsdoc.tag.inline).toBeDefined();
|
||||||
|
expect(typeof jsdoc.tag.inline).toBe('object');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should export a replaceInlineTag function', function() {
|
||||||
|
expect(jsdoc.tag.inline.replaceInlineTag).toBeDefined();
|
||||||
|
expect(typeof jsdoc.tag.inline.replaceInlineTag).toBe('function');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should export an extractInlineTag function', function() {
|
||||||
|
expect(jsdoc.tag.inline.extractInlineTag).toBeDefined();
|
||||||
|
expect(typeof jsdoc.tag.inline.replaceInlineTag).toBe('function');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('replaceInlineTag', function() {
|
||||||
|
it('should throw if the replacer parameter is invalid', function() {
|
||||||
|
function badReplacerUndefined() {
|
||||||
|
jsdoc.tag.inline.replaceInlineTag('foo', '@bar');
|
||||||
|
}
|
||||||
|
|
||||||
|
function badReplacerString() {
|
||||||
|
jsdoc.tag.inline.replaceInlineTag('foo', '@bar', 'hello');
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(badReplacerUndefined).toThrow();
|
||||||
|
expect(badReplacerString).toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not find anything if there is no text in braces', function() {
|
||||||
|
function replacer(string, completeTag, tagText) {
|
||||||
|
expect(string).toBe('braceless text');
|
||||||
|
expect(completeTag).toBe('');
|
||||||
|
expect(tagText).toBe('');
|
||||||
|
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = jsdoc.tag.inline.replaceInlineTag('braceless text', null, replacer);
|
||||||
|
expect(result.tag).toBe(null);
|
||||||
|
expect(result.text).toBe('');
|
||||||
|
expect(result.newString).toBe('braceless text');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should cope with bad escapement at the end of the string', function() {
|
||||||
|
function replacer(string, completeTag, tagText) {
|
||||||
|
expect(string).toBe('bad {escapement \\');
|
||||||
|
expect(completeTag).toBe('');
|
||||||
|
expect(tagText).toBe('');
|
||||||
|
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = jsdoc.tag.inline.replaceInlineTag('bad {escapement \\', null, replacer);
|
||||||
|
expect(result.tag).toBe(null);
|
||||||
|
expect(result.text).toBe('');
|
||||||
|
expect(result.newString).toBe('bad {escapement \\');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle escaped braces correctly', function() {
|
||||||
|
function replacer(string, completeTag, tagText) {
|
||||||
|
expect(string).toBe('a {braces \\} test}');
|
||||||
|
expect(completeTag).toBe('{braces \\} test}');
|
||||||
|
expect(tagText).toBe('braces \\} test');
|
||||||
|
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = jsdoc.tag.inline.replaceInlineTag('a {braces \\} test}', null, replacer);
|
||||||
|
expect(result.tag).toBe(null);
|
||||||
|
expect(result.text).toBe('braces } test');
|
||||||
|
expect(result.newString).toBe('a {braces \\} test}');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should work if the tag is the entire string', function() {
|
||||||
|
function replacer(string, completeTag, tagText) {
|
||||||
|
expect(string).toBe('{text in braces}');
|
||||||
|
expect(completeTag).toBe('{text in braces}');
|
||||||
|
expect(tagText).toBe('text in braces');
|
||||||
|
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = jsdoc.tag.inline.replaceInlineTag('{text in braces}', null, replacer);
|
||||||
|
expect(result.tag).toBe(null);
|
||||||
|
expect(result.text).toBe('text in braces');
|
||||||
|
expect(result.newString).toBe('{text in braces}');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should work if the tag is at the beginning of the string', function() {
|
||||||
|
function replacer(string, completeTag, tagText) {
|
||||||
|
expect(string).toBe('{test string} ahoy');
|
||||||
|
expect(completeTag).toBe('{test string}');
|
||||||
|
expect(tagText).toBe('test string');
|
||||||
|
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = jsdoc.tag.inline.replaceInlineTag('{test string} ahoy', null, replacer);
|
||||||
|
expect(result.tag).toBe(null);
|
||||||
|
expect(result.text).toBe('test string');
|
||||||
|
expect(result.newString).toBe('{test string} ahoy');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should work if the tag is in the middle of the string', function() {
|
||||||
|
function replacer(string, completeTag, tagText) {
|
||||||
|
expect(string).toBe('a {test string} yay');
|
||||||
|
expect(completeTag).toBe('{test string}');
|
||||||
|
expect(tagText).toBe('test string');
|
||||||
|
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = jsdoc.tag.inline.replaceInlineTag('a {test string} yay', null, replacer);
|
||||||
|
expect(result.tag).toBe(null);
|
||||||
|
expect(result.text).toBe('test string');
|
||||||
|
expect(result.newString).toBe('a {test string} yay');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should work if the tag is at the end of the string', function() {
|
||||||
|
function replacer(string, completeTag, tagText) {
|
||||||
|
expect(string).toBe('a {test string}');
|
||||||
|
expect(completeTag).toBe('{test string}');
|
||||||
|
expect(tagText).toBe('test string');
|
||||||
|
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = jsdoc.tag.inline.replaceInlineTag('a {test string}', null, replacer);
|
||||||
|
expect(result.tag).toBe(null);
|
||||||
|
expect(result.text).toBe('test string');
|
||||||
|
expect(result.newString).toBe('a {test string}');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should replace the string with the specified value', function() {
|
||||||
|
function replacer() {
|
||||||
|
return 'REPLACED!';
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = jsdoc.tag.inline.replaceInlineTag('a {test string}', null, replacer);
|
||||||
|
expect(result.newString).toBe('REPLACED!');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should work when there are nested braces', function() {
|
||||||
|
function replacer(string, completeTag, tagText) {
|
||||||
|
expect(string).toBe('some {{double}} braces');
|
||||||
|
expect(completeTag).toBe('{{double}}');
|
||||||
|
expect(tagText).toBe('{double}');
|
||||||
|
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = jsdoc.tag.inline.replaceInlineTag('some {{double}} braces', null,
|
||||||
|
replacer);
|
||||||
|
expect(result.tag).toBe(null);
|
||||||
|
expect(result.text).toBe('{double}');
|
||||||
|
expect(result.newString).toBe('some {{double}} braces');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should work when a tag is specified', function() {
|
||||||
|
function replacer(string, completeTag, tagText) {
|
||||||
|
expect(string).toBe('a {@foo tag} test');
|
||||||
|
expect(completeTag).toBe('{@foo tag}');
|
||||||
|
expect(tagText).toBe('tag');
|
||||||
|
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = jsdoc.tag.inline.replaceInlineTag('a {@foo tag} test', '@foo', replacer);
|
||||||
|
expect(result.tag).toBe('@foo');
|
||||||
|
expect(result.text).toBe('tag');
|
||||||
|
expect(result.newString).toBe('a {@foo tag} test');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// largely covered by the replaceInlineTag tests
|
||||||
|
describe('extractInlineTag', function() {
|
||||||
|
it('should work when there is no tag specified', function() {
|
||||||
|
var result = jsdoc.tag.inline.extractInlineTag('some {braced text}');
|
||||||
|
expect(result.tag).toBe(null);
|
||||||
|
expect(result.text).toBe('braced text');
|
||||||
|
expect(result.newString).toBe('some');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should work when a tag is specified', function() {
|
||||||
|
var result = jsdoc.tag.inline.extractInlineTag('some {@tagged text}', '@tagged');
|
||||||
|
expect(result.tag).toBe('@tagged');
|
||||||
|
expect(result.text).toBe('text');
|
||||||
|
expect(result.newString).toBe('some');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -3,16 +3,16 @@
|
|||||||
function buildText(type, name, desc) {
|
function buildText(type, name, desc) {
|
||||||
var text = '';
|
var text = '';
|
||||||
if (type) {
|
if (type) {
|
||||||
text += "{" + type + "}";
|
text += '{' + type + '}';
|
||||||
if (name || desc) {
|
if (name || desc) {
|
||||||
text += " ";
|
text += ' ';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name) {
|
if (name) {
|
||||||
text += name;
|
text += name;
|
||||||
if (desc) {
|
if (desc) {
|
||||||
text += " ";
|
text += ' ';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,129 +23,157 @@ function buildText(type, name, desc) {
|
|||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
describe("jsdoc/tag/type", function() {
|
describe('jsdoc/tag/type', function() {
|
||||||
var jsdoc = {
|
var jsdoc = {
|
||||||
tag: {
|
tag: {
|
||||||
type: require('jsdoc/tag/type')
|
type: require('jsdoc/tag/type')
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
it("should exist", function() {
|
it('should exist', function() {
|
||||||
expect(jsdoc.tag.type).toBeDefined();
|
expect(jsdoc.tag.type).toBeDefined();
|
||||||
expect(typeof jsdoc.tag.type).toEqual("object");
|
expect(typeof jsdoc.tag.type).toBe('object');
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should export a getTagInfo function", function() {
|
it('should export a parse function', function() {
|
||||||
expect(jsdoc.tag.type.getTagInfo).toBeDefined();
|
|
||||||
expect(typeof jsdoc.tag.type.getTagInfo).toEqual("function");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should export a parse function", function() {
|
|
||||||
expect(jsdoc.tag.type.parse).toBeDefined();
|
expect(jsdoc.tag.type.parse).toBeDefined();
|
||||||
expect(typeof jsdoc.tag.type.parse).toEqual("function");
|
expect(typeof jsdoc.tag.type.parse).toBe('function');
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("getTagInfo", function() {
|
describe('parse', function() {
|
||||||
it("should return an object with name, type, and text properties", function() {
|
it('should return an object with name, type, and text properties', function() {
|
||||||
var info = jsdoc.tag.type.getTagInfo("");
|
var info = jsdoc.tag.type.parse('');
|
||||||
expect(info.name).toBeDefined();
|
expect(info.name).toBeDefined();
|
||||||
expect(info.type).toBeDefined();
|
expect(info.type).toBeDefined();
|
||||||
expect(info.text).toBeDefined();
|
expect(info.text).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should not extract a name or type if canHaveName and canHaveType are not set", function() {
|
it('should not extract a name or type if canHaveName and canHaveType are not set', function() {
|
||||||
var desc = "{number} foo The foo parameter.";
|
var desc = '{number} foo The foo parameter.';
|
||||||
var info = jsdoc.tag.type.getTagInfo(desc);
|
var info = jsdoc.tag.type.parse(desc);
|
||||||
expect(info.type).toEqual('');
|
expect(info.type).toEqual([]);
|
||||||
expect(info.name).toEqual('');
|
expect(info.name).toBe('');
|
||||||
expect(info.text).toEqual(desc);
|
expect(info.text).toBe(desc);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should extract a name, but not a type, if canHaveName === true and canHaveType === false", function() {
|
it('should extract a name, but not a type, if canHaveName === true and canHaveType === false', function() {
|
||||||
var name = "bar";
|
var name = 'bar';
|
||||||
var desc = "The bar parameter.";
|
var desc = 'The bar parameter.';
|
||||||
var info = jsdoc.tag.type.getTagInfo( buildText(null, name, desc), true, false );
|
var info = jsdoc.tag.type.parse( buildText(null, name, desc), true, false );
|
||||||
expect(info.type).toEqual('');
|
expect(info.type).toEqual([]);
|
||||||
expect(info.name).toEqual(name);
|
expect(info.name).toBe(name);
|
||||||
expect(info.text).toEqual(desc);
|
expect(info.text).toBe(desc);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should extract a type, but not a name, if canHaveName === false and canHaveType === true", function() {
|
it('should extract a type, but not a name, if canHaveName === false and canHaveType === true', function() {
|
||||||
var type = "boolean";
|
var type = 'boolean';
|
||||||
var desc = "Set to true on alternate Thursdays.";
|
var desc = 'Set to true on alternate Thursdays.';
|
||||||
var info = jsdoc.tag.type.getTagInfo( buildText(type, null, desc), false, true );
|
var info = jsdoc.tag.type.parse( buildText(type, null, desc), false, true );
|
||||||
expect(info.type).toEqual(type);
|
expect(info.type).toEqual([type]);
|
||||||
expect(info.name).toEqual('');
|
expect(info.name).toBe('');
|
||||||
expect(info.text).toEqual(desc);
|
expect(info.text).toBe(desc);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should extract a name and type if canHaveName and canHaveType are true", function() {
|
it('should extract a name and type if canHaveName and canHaveType are true', function() {
|
||||||
var type = "string";
|
var type = 'string';
|
||||||
var name = "baz";
|
var name = 'baz';
|
||||||
var desc = "The baz parameter.";
|
var desc = 'The baz parameter.';
|
||||||
var info = jsdoc.tag.type.getTagInfo( buildText(type, name, desc), true, true );
|
var info = jsdoc.tag.type.parse( buildText(type, name, desc), true, true );
|
||||||
expect(info.type).toEqual(type);
|
expect(info.type).toEqual([type]);
|
||||||
expect(info.name).toEqual(name);
|
expect(info.name).toBe(name);
|
||||||
expect(info.text).toEqual(desc);
|
expect(info.text).toBe(desc);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should work with JSDoc-style optional parameters", function() {
|
it('should report optional types correctly no matter which syntax we use', function() {
|
||||||
var name = "[qux]";
|
var desc = '{string} [foo]';
|
||||||
var desc = "The qux parameter.";
|
|
||||||
var info = jsdoc.tag.type.getTagInfo( buildText(null, name, desc), true, false );
|
|
||||||
expect(info.name).toEqual(name);
|
|
||||||
expect(info.text).toEqual(desc);
|
|
||||||
|
|
||||||
name = "[ qux ]";
|
|
||||||
info = jsdoc.tag.type.getTagInfo( buildText(null, name, desc), true, false );
|
|
||||||
expect(info.name).toEqual(name);
|
|
||||||
expect(info.text).toEqual(desc);
|
|
||||||
|
|
||||||
name = "[qux=hooray]";
|
|
||||||
info = jsdoc.tag.type.getTagInfo( buildText(null, name, desc), true, false );
|
|
||||||
expect(info.name).toEqual(name);
|
|
||||||
expect(info.text).toEqual(desc);
|
|
||||||
|
|
||||||
name = "[ qux = hooray ]";
|
|
||||||
info = jsdoc.tag.type.getTagInfo( buildText(null, name, desc), true, false );
|
|
||||||
expect(info.name).toEqual(name);
|
|
||||||
expect(info.text).toEqual(desc);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("parse", function() {
|
|
||||||
it("should report optional types correctly no matter which syntax we use", function() {
|
|
||||||
var desc = "{string} [foo]";
|
|
||||||
var info = jsdoc.tag.type.parse(desc, true, true);
|
var info = jsdoc.tag.type.parse(desc, true, true);
|
||||||
expect(info.optional).toEqual(true);
|
expect(info.optional).toBe(true);
|
||||||
|
|
||||||
desc = "{string=} [foo]";
|
desc = '{string=} [foo]';
|
||||||
info = jsdoc.tag.type.parse(desc, true, true);
|
info = jsdoc.tag.type.parse(desc, true, true);
|
||||||
expect(info.optional).toEqual(true);
|
expect(info.optional).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return the types as an array", function() {
|
it('should return the types as an array', function() {
|
||||||
var desc = "{string} foo";
|
var desc = '{string} foo';
|
||||||
var info = jsdoc.tag.type.parse(desc, true, true);
|
var info = jsdoc.tag.type.parse(desc, true, true);
|
||||||
expect(info.type).toEqual( ["string"] );
|
expect(info.type).toEqual( ['string'] );
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should recognize the entire list of possible types", function() {
|
it('should recognize the entire list of possible types', function() {
|
||||||
var desc = "{string|number} foo";
|
var desc = '{(string|number)} foo';
|
||||||
var info = jsdoc.tag.type.parse(desc, true, true);
|
var info = jsdoc.tag.type.parse(desc, true, true);
|
||||||
expect(info.type).toEqual( ["string", "number"] );
|
expect(info.type).toEqual( ['string', 'number'] );
|
||||||
|
|
||||||
desc = "{ string | number } foo";
|
desc = '{ ( string | number ) } foo';
|
||||||
info = jsdoc.tag.type.parse(desc, true, true);
|
info = jsdoc.tag.type.parse(desc, true, true);
|
||||||
expect(info.type).toEqual( ["string", "number"] );
|
expect(info.type).toEqual( ['string', 'number'] );
|
||||||
|
|
||||||
desc = "{ ( string | number)} foo";
|
desc = '{ ( string | number)} foo';
|
||||||
info = jsdoc.tag.type.parse(desc, true, true);
|
info = jsdoc.tag.type.parse(desc, true, true);
|
||||||
expect(info.type).toEqual( ["string", "number"] );
|
expect(info.type).toEqual( ['string', 'number'] );
|
||||||
|
|
||||||
desc = "{(string|number|boolean|function)} foo";
|
desc = '{(string|number|boolean|function)} foo';
|
||||||
info = jsdoc.tag.type.parse(desc, true, true);
|
info = jsdoc.tag.type.parse(desc, true, true);
|
||||||
expect(info.type).toEqual( ["string", "number", "boolean", "function"] );
|
expect(info.type).toEqual( ['string', 'number', 'boolean', 'function'] );
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should override the type expression if an inline @type tag is specified', function() {
|
||||||
|
var desc = '{Object} cookie {@type Monster}';
|
||||||
|
var info = jsdoc.tag.type.parse(desc, true, true);
|
||||||
|
expect(info.type).toEqual( ['Monster'] );
|
||||||
|
expect(info.text).toBe('');
|
||||||
|
|
||||||
|
desc = '{Object} cookie - {@type Monster}';
|
||||||
|
info = jsdoc.tag.type.parse(desc, true, true);
|
||||||
|
expect(info.type).toEqual( ['Monster'] );
|
||||||
|
expect(info.text).toBe('');
|
||||||
|
|
||||||
|
desc = '{Object} cookie - The cookie parameter. {@type Monster}';
|
||||||
|
info = jsdoc.tag.type.parse(desc, true, true);
|
||||||
|
expect(info.type).toEqual( ['Monster'] );
|
||||||
|
expect(info.text).toBe('The cookie parameter.');
|
||||||
|
|
||||||
|
desc = '{Object} cookie - The cookie parameter. {@type (Monster|Jar)}';
|
||||||
|
info = jsdoc.tag.type.parse(desc, true, true);
|
||||||
|
expect(info.type).toEqual( ['Monster', 'Jar'] );
|
||||||
|
expect(info.text).toBe('The cookie parameter.');
|
||||||
|
|
||||||
|
desc = '{Object} cookie - The cookie parameter. {@type (Monster|Jar)} Mmm, cookie.';
|
||||||
|
info = jsdoc.tag.type.parse(desc, true, true);
|
||||||
|
expect(info.type).toEqual( ['Monster', 'Jar'] );
|
||||||
|
expect(info.text).toBe('The cookie parameter. Mmm, cookie.');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('JSDoc-style type info', function() {
|
||||||
|
it('should parse JSDoc-style optional parameters', function() {
|
||||||
|
var name = '[qux]';
|
||||||
|
var desc = 'The qux parameter.';
|
||||||
|
var info = jsdoc.tag.type.parse( buildText(null, name, desc), true, false );
|
||||||
|
expect(info.name).toBe('qux');
|
||||||
|
expect(info.text).toBe(desc);
|
||||||
|
expect(info.optional).toBe(true);
|
||||||
|
|
||||||
|
name = '[ qux ]';
|
||||||
|
info = jsdoc.tag.type.parse( buildText(null, name, desc), true, false );
|
||||||
|
expect(info.name).toBe('qux');
|
||||||
|
expect(info.text).toBe(desc);
|
||||||
|
expect(info.optional).toBe(true);
|
||||||
|
|
||||||
|
name = '[qux=hooray]';
|
||||||
|
info = jsdoc.tag.type.parse( buildText(null, name, desc), true, false );
|
||||||
|
expect(info.name).toBe('qux');
|
||||||
|
expect(info.text).toBe(desc);
|
||||||
|
expect(info.optional).toBe(true);
|
||||||
|
expect(info.defaultvalue).toBe('hooray');
|
||||||
|
|
||||||
|
name = '[ qux = hooray ]';
|
||||||
|
info = jsdoc.tag.type.parse( buildText(null, name, desc), true, false );
|
||||||
|
expect(info.name).toBe('qux');
|
||||||
|
expect(info.text).toBe(desc);
|
||||||
|
expect(info.optional).toBe(true);
|
||||||
|
expect(info.defaultvalue).toBe('hooray');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,25 +0,0 @@
|
|||||||
/*global describe: true, expect: true, it: true */
|
|
||||||
describe('jsdoc/tag/type/closureCompilerType', function() {
|
|
||||||
// TODO: more tests
|
|
||||||
|
|
||||||
var type = require('jsdoc/tag/type/closureCompilerType');
|
|
||||||
|
|
||||||
it('should exist', function() {
|
|
||||||
expect(type).toBeDefined();
|
|
||||||
expect(typeof type).toEqual('object');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should export a parse function', function() {
|
|
||||||
expect(type.parse).toBeDefined();
|
|
||||||
expect(typeof type.parse).toEqual('function');
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('parse', function() {
|
|
||||||
it('should correctly parse types that are both optional and nullable', function() {
|
|
||||||
var info = type.parse( {type: '?string='} );
|
|
||||||
expect(info.type).toEqual('string');
|
|
||||||
expect(info.optional).toEqual(true);
|
|
||||||
expect(info.nullable).toEqual(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@ -1,68 +0,0 @@
|
|||||||
/*global describe: true, expect: true, it: true */
|
|
||||||
|
|
||||||
var hasOwnProp = Object.prototype.hasOwnProperty;
|
|
||||||
|
|
||||||
describe("jsdoc/tag/type/jsdocType", function() {
|
|
||||||
var jsdocType = require("jsdoc/tag/type/jsdocType");
|
|
||||||
|
|
||||||
it("should exist", function() {
|
|
||||||
expect(jsdocType).toBeDefined();
|
|
||||||
expect(typeof jsdocType).toEqual("object");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should export a parse function", function() {
|
|
||||||
expect(jsdocType.parse).toBeDefined();
|
|
||||||
expect(typeof jsdocType.parse).toEqual("function");
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("parse", function() {
|
|
||||||
it("should recognize optional properties without default values", function() {
|
|
||||||
var info = jsdocType.parse( { name: "[foo]" } );
|
|
||||||
expect(info.name).toEqual("foo");
|
|
||||||
expect(info.optional).toEqual(true);
|
|
||||||
expect( info.defaultvalue ).toEqual(null);
|
|
||||||
|
|
||||||
info = jsdocType.parse( { name: "[ bar ]" } );
|
|
||||||
expect(info.name).toEqual("bar");
|
|
||||||
expect(info.optional).toEqual(true);
|
|
||||||
expect( info.defaultvalue ).toEqual(null);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should recognize optional properties with default values", function() {
|
|
||||||
var info = jsdocType.parse( { name: "[foo=bar]" } );
|
|
||||||
expect(info.name).toEqual("foo");
|
|
||||||
expect(info.optional).toEqual(true);
|
|
||||||
expect( info.defaultvalue ).toEqual("bar");
|
|
||||||
|
|
||||||
info = jsdocType.parse( { name: "[ baz = qux ]" } );
|
|
||||||
expect(info.name).toEqual("baz");
|
|
||||||
expect(info.optional).toEqual(true);
|
|
||||||
expect( info.defaultvalue ).toEqual("qux");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should only change the `name`, `optional`, and `defaultvalue` properties", function() {
|
|
||||||
var obj = {
|
|
||||||
name: "[foo=bar]",
|
|
||||||
type: "boolean|string",
|
|
||||||
text: "Sample text.",
|
|
||||||
optional: null,
|
|
||||||
nullable: null,
|
|
||||||
variable: null,
|
|
||||||
defaultvalue: null
|
|
||||||
};
|
|
||||||
var shouldChange = [ "name", "optional", "defaultvalue" ];
|
|
||||||
|
|
||||||
var info = jsdocType.parse(obj);
|
|
||||||
for (var key in info) {
|
|
||||||
if ( hasOwnProp.call(info, key) ) {
|
|
||||||
if ( shouldChange.indexOf(key) !== -1 ) {
|
|
||||||
expect( info[key] ).not.toEqual( obj[key] );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
expect( info[key] ).toEqual( obj[key] );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@ -223,10 +223,12 @@ describe("jsdoc/util/templateHelper", function() {
|
|||||||
describe("linkto", function() {
|
describe("linkto", function() {
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
helper.longnameToUrl.linktoTest = 'test.html';
|
helper.longnameToUrl.linktoTest = 'test.html';
|
||||||
|
helper.longnameToUrl.LinktoFakeClass = 'fakeclass.html';
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function() {
|
afterEach(function() {
|
||||||
delete helper.longnameToUrl.linktoTest;
|
delete helper.longnameToUrl.linktoTest;
|
||||||
|
delete helper.longnameToUrl.LinktoFakeClass;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns the longname if only the longname is specified and has no URL', function() {
|
it('returns the longname if only the longname is specified and has no URL', function() {
|
||||||
@ -260,12 +262,34 @@ describe("jsdoc/util/templateHelper", function() {
|
|||||||
expect(link).toBe('<a href="test.html" class="myclass">link text</a>');
|
expect(link).toBe('<a href="test.html" class="myclass">link text</a>');
|
||||||
});
|
});
|
||||||
|
|
||||||
it("is careful with longnames that are reserved words in JS", function() {
|
it('is careful with longnames that are reserved words in JS', function() {
|
||||||
// we don't have a registered link for 'constructor' so it should return the text 'link text'.
|
// we don't have a registered link for 'constructor' so it should return the text 'link text'.
|
||||||
var link = helper.linkto('constructor', 'link text');
|
var link = helper.linkto('constructor', 'link text');
|
||||||
expect(typeof link).toBe('string');
|
expect(typeof link).toBe('string');
|
||||||
expect(link).toBe('link text');
|
expect(link).toBe('link text');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('works correctly with type applications if only the longname is specified', function() {
|
||||||
|
var link = helper.linkto('Array.<LinktoFakeClass>');
|
||||||
|
expect(link).toBe('Array.<<a href="fakeclass.html">LinktoFakeClass</a>>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('works correctly with type applications if a class is not specified', function() {
|
||||||
|
var link = helper.linkto('Array.<LinktoFakeClass>', 'link text');
|
||||||
|
expect(link).toBe('Array.<<a href="fakeclass.html">LinktoFakeClass</a>>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('works correctly with type applications if a class is specified', function() {
|
||||||
|
var link = helper.linkto('Array.<LinktoFakeClass>', 'link text', 'myclass');
|
||||||
|
expect(link).toBe('Array.<<a href="fakeclass.html" class="myclass">LinktoFakeClass' +
|
||||||
|
'</a>>');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('works correctly with type applications that include a type union', function() {
|
||||||
|
var link = helper.linkto('Array.<(linktoTest|LinktoFakeClass)>', 'link text');
|
||||||
|
expect(link).toBe('Array.<(<a href="test.html">linktoTest</a>|' +
|
||||||
|
'<a href="fakeclass.html">LinktoFakeClass</a>)>');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("htmlsafe", function() {
|
describe("htmlsafe", function() {
|
||||||
|
|||||||
@ -11,7 +11,7 @@ describe("@param tag", function() {
|
|||||||
it('When a symbol has an @param tag with a type before the name, the doclet has a params property that includes that param.', function() {
|
it('When a symbol has an @param tag with a type before the name, the doclet has a params property that includes that param.', function() {
|
||||||
expect(typeof find.params).toBe('object');
|
expect(typeof find.params).toBe('object');
|
||||||
expect(find.params.length).toBe(1);
|
expect(find.params.length).toBe(1);
|
||||||
expect(find.params[0].type.names.join(', ')).toBe('String, Array<String>');
|
expect(find.params[0].type.names.join(', ')).toBe('String, Array.<String>');
|
||||||
expect(find.params[0].name).toBe('targetName');
|
expect(find.params[0].name).toBe('targetName');
|
||||||
expect(find.params[0].description).toBe('The name (or names) of what to find.');
|
expect(find.params[0].description).toBe('The name (or names) of what to find.');
|
||||||
});
|
});
|
||||||
|
|||||||
@ -6,7 +6,7 @@ describe("@returns tag", function() {
|
|||||||
it('When a symbol has an @returns tag with a type and description, the doclet has a returns array that includes that return.', function() {
|
it('When a symbol has an @returns tag with a type and description, the doclet has a returns array that includes that return.', function() {
|
||||||
expect(typeof find.returns).toBe('object');
|
expect(typeof find.returns).toBe('object');
|
||||||
expect(find.returns.length).toBe(1);
|
expect(find.returns.length).toBe(1);
|
||||||
expect(find.returns[0].type.names.join(', ')).toBe('String, Array<String>');
|
expect(find.returns[0].type.names.join(', ')).toBe('String, Array.<String>');
|
||||||
expect(find.returns[0].description).toBe('The names of the found item(s).');
|
expect(find.returns[0].description).toBe('The names of the found item(s).');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ describe("@type tag", function() {
|
|||||||
it('When a symbol has an @type tag, the doclet has a type property set to that value\'s type.', function() {
|
it('When a symbol has an @type tag, the doclet has a type property set to that value\'s type.', function() {
|
||||||
expect(typeof foo.type).toBe('object');
|
expect(typeof foo.type).toBe('object');
|
||||||
expect(typeof foo.type.names).toBe('object');
|
expect(typeof foo.type.names).toBe('object');
|
||||||
expect(foo.type.names.join(', ')).toBe('string, Array<string>');
|
expect(foo.type.names.join(', ')).toBe('string, Array.<string>');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('When a symbol has an @type tag set to a plain string, the doclet has a type property set to that string as if it were a type.', function() {
|
it('When a symbol has an @type tag set to a plain string, the doclet has a type property set to that string as if it were a type.', function() {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user