iflrandevu/data/scripts/jsdoc/node_modules/catharsis/lib/stringify.js
2013-05-20 17:21:58 +00:00

257 lines
5.6 KiB
JavaScript

'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 = '.&lt;';
} 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);
};