Socket
Socket
Sign inDemoInstall

catharsis

Package Overview
Dependencies
Maintainers
1
Versions
32
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

catharsis - npm Package Compare versions

Comparing version 0.7.1 to 0.8.0

.eslintrc

34

bin/parseType.js

@@ -12,27 +12,45 @@ #!/usr/bin/env node

var typeExpression = process.argv[2];
var jsdoc = process.argv[3] === '--jsdoc' ? true : false;
var parsedType;
var opts = {
jsdoc: jsdoc
describe: false,
jsdoc: false
};
var parsedType;
function usage() {
console.log(util.format('Usage:\n %s typeExpression [--jsdoc]', command));
console.log(util.format('Usage:\n %s typeExpression [--jsdoc] [--describe]', command));
}
function done(err) {
/*eslint no-process-exit: 0 */
process.exit(err === undefined ? 0 : err);
}
process.argv.slice(3).forEach(function(arg) {
var parsedArg = arg.replace(/^\-{2}/, '');
if (opts[parsedArg] !== undefined) {
opts[parsedArg] = true;
} else {
console.error('Unknown option "%s"', arg);
usage();
done(1);
}
});
if (!typeExpression) {
usage();
process.exit(1);
done(1);
} else {
try {
parsedType = catharsis.parse(typeExpression, opts);
if (opts.describe) {
parsedType = catharsis.describe(parsedType);
}
} catch (e) {
console.error(util.format('Unable to parse "%s" (exception follows):', typeExpression));
console.error(e.stack || e.message);
process.exit(1);
done(1);
}
console.log(JSON.stringify(parsedType, null, 2));
process.exit(0);
done();
}

@@ -11,2 +11,3 @@ /**

var describe = require('./lib/describe');
var parse = require('./lib/parser').parse;

@@ -25,2 +26,6 @@ var stringify = require('./lib/stringify');

var descriptionCache = {
normal: {}
};
function getTypeExpressionCache(options) {

@@ -46,2 +51,10 @@ if (options.useCache === false) {

function getDescriptionCache(options) {
if (options.useCache === false || options.links !== null || options.links !== undefined) {
return null;
} else {
return descriptionCache.normal;
}
}
// can't return the original if any of the following are true:

@@ -58,2 +71,17 @@ // 1. restringification was requested

// Add non-enumerable properties to a result object, then freeze it.
function prepareFrozenObject(obj, expr, options) {
Object.defineProperty(obj, 'jsdoc', {
value: options.jsdoc === true ? true : false
});
if (expr) {
Object.defineProperty(obj, 'typeExpression', {
value: expr
});
}
return Object.freeze(obj);
}
function cachedParse(expr, options) {

@@ -67,13 +95,4 @@ var cache = getTypeExpressionCache(options);

parsedType = parse(expr, options);
parsedType = prepareFrozenObject(parsedType, expr, options);
Object.defineProperties(parsedType, {
typeExpression: {
value: expr
},
jsdoc: {
value: options.jsdoc === true ? true : false
}
});
parsedType = Object.freeze(parsedType);
if (cache) {

@@ -102,2 +121,19 @@ cache[expr] = parsedType;

function cachedDescribe(parsedType, options) {
var cache = getDescriptionCache(options);
var json;
var result;
if (cache) {
json = JSON.stringify(parsedType);
cache[json] = cache[json] || describe(parsedType, options);
return cache[json];
} else {
result = describe(parsedType, options);
result = prepareFrozenObject(result, null, options);
return result;
}
}
function Catharsis() {

@@ -118,5 +154,6 @@ this.Types = require('./lib/types');

Catharsis.prototype.stringify = function(parsedType, options) {
options = options || {};
var result;
options = options || {};
result = cachedStringify(parsedType, options);

@@ -130,2 +167,8 @@ if (options.validate) {

Catharsis.prototype.describe = function(parsedType, options) {
options = options || {};
return cachedDescribe(parsedType, options);
};
module.exports = new Catharsis();

@@ -7,2 +7,3 @@ 'use strict';

this._options = options || {};
this._options.linkClass = this._options.linkClass || this._options.cssClass;

@@ -14,11 +15,11 @@ // in a list of function signature params, repeatable params are stringified differently

Stringifier.prototype.applications = function(applications) {
var result = '';
var strings = [];
if (!applications) {
return '';
return result;
}
var parsedApplications = [];
var result = '';
for (var i = 0, l = applications.length; i < l; i++) {
parsedApplications.push(this.type(applications[i]));
strings.push(this.type(applications[i]));
}

@@ -32,3 +33,3 @@

result += parsedApplications.join(', ') + '>';
result += strings.join(', ') + '>';

@@ -39,13 +40,16 @@ return result;

Stringifier.prototype.elements = function(elements) {
var result = '';
var strings = [];
if (!elements) {
return '';
return result;
}
var result = [];
for (var i = 0, l = elements.length; i < l; i++) {
result.push(this.type(elements[i]));
strings.push(this.type(elements[i]));
}
return '(' + result.join('|') + ')';
result = '(' + strings.join('|') + ')';
return result;
};

@@ -81,27 +85,15 @@

Stringifier.prototype.params = function(params) {
var result = '';
var strings = [];
if (!params || params.length === 0) {
return '';
return result;
}
var result = [];
var param;
for (var i = 0, l = params.length; i < l; i++) {
result.push(this.type(params[i]));
strings.push(this.type(params[i]));
}
return result.join(', ');
};
result = strings.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;

@@ -118,8 +110,7 @@ };

// TODO: refactor for clarity
Stringifier.prototype.type = function(type) {
var result = '';
var typeString = '';
if (!type) {
return result;
return typeString;
}

@@ -129,38 +120,35 @@

case Types.AllLiteral:
result += this._formatRepeatableAndNullable(type, '',
this._formatNameAndType(type, '*'));
typeString = this._formatNameAndType(type, '*');
break;
case Types.FunctionType:
result += this._signature(type);
typeString = this._signature(type);
break;
case Types.NullLiteral:
result += this._formatRepeatableAndNullable(type, '',
this._formatNameAndType(type, 'null'));
typeString = this._formatNameAndType(type, 'null');
break;
case Types.RecordType:
result += this._formatRepeatableAndNullable(type, '', this._record(type));
typeString = this._record(type);
break;
case Types.TypeApplication:
result += this._formatRepeatableAndNullable(type, '', this.type(type.expression));
result += this.applications(type.applications);
typeString = this.type(type.expression) + this.applications(type.applications);
break;
case Types.UndefinedLiteral:
result += this._formatRepeatableAndNullable(type, '',
this._formatNameAndType(type, 'undefined'));
typeString = this._formatNameAndType(type, 'undefined');
break;
case Types.TypeUnion:
result += this._formatRepeatableAndNullable(type, '', this.elements(type.elements));
typeString = this.elements(type.elements);
break;
case Types.UnknownLiteral:
result += this._formatRepeatableAndNullable(type, '',
this._formatNameAndType(type, '?'));
typeString = this._formatNameAndType(type, '?');
break;
default:
result += this._formatRepeatableAndNullable(type, '', this._formatNameAndType(type));
typeString = this._formatNameAndType(type);
}
// finally, optionality
result += this.optional(type.optional);
// add optional/nullable/repeatable modifiers
if (!this._options._ignoreModifiers) {
typeString = this._addModifiers(type, typeString);
}
return result;
return typeString;
};

@@ -179,10 +167,10 @@

Stringifier.prototype._recordFields = function(fields) {
if (!fields) {
return '';
}
var field;
var keyAndValue;
var result = [];
var field;
var keyAndValue;
if (!fields) {
return result;
}

@@ -207,6 +195,9 @@ for (var i = 0, l = fields.length; i < l; i++) {

Stringifier.prototype._formatRepeatableAndNullable = function(type, nameString, typeString) {
// Adds optional, nullable, and repeatable modifiers if necessary.
Stringifier.prototype._addModifiers = function(type, typeString) {
var combined;
var open = '';
var close = '';
var combined;
var optional = '';

@@ -218,22 +209,32 @@ if (type.repeatable) {

combined = this.nullable(type.nullable) + combineNameAndType(nameString, typeString);
combined = this.nullable(type.nullable) + combineNameAndType('', typeString);
optional = this.optional(type.optional);
return open + combined + close;
return open + combined + close + optional;
};
Stringifier.prototype._formatNameAndType = function(type, literal) {
var nameString = type.name || literal || '';
var typeString = type.type ? this.type(type.type) : '';
var cssClass;
Stringifier.prototype._addLinks = function(nameString) {
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 + '"' : '';
var linkClass = '';
var options = this._options;
openTag = '<a href="' + this._options.links[nameString] + '"' + cssClass + '>';
if (options.links && Object.prototype.hasOwnProperty.call(options.links, nameString)) {
if (options.linkClass) {
linkClass = ' class="' + options.linkClass + '"';
}
openTag = '<a href="' + options.links[nameString] + '"' + linkClass + '>';
nameString = openTag + nameString + '</a>';
}
return nameString;
};
Stringifier.prototype._formatNameAndType = function(type, literal) {
var nameString = type.name || literal || '';
var typeString = type.type ? this.type(type.type) : '';
nameString = this._addLinks(nameString);
return combineNameAndType(nameString, typeString);

@@ -243,7 +244,7 @@ };

Stringifier.prototype._signature = function(type) {
var params = [];
var param;
var result;
var signatureBase;
var prop;
var signature;
var params = [];
// these go within the signature's parens, in this order

@@ -255,3 +256,2 @@ var props = [

];
var prop;

@@ -268,7 +268,6 @@ this._inFunctionSignatureParams = true;

signatureBase = 'function(' + params.join(', ') + ')';
result = this._formatRepeatableAndNullable(type, '', signatureBase);
result += this.result(type.result);
signature = 'function(' + params.join(', ') + ')';
signature += this.result(type.result);
return result;
return signature;
};

@@ -275,0 +274,0 @@

{
"version": "0.7.1",
"name": "catharsis",
"description": "A JavaScript parser for Google Closure Compiler and JSDoc type expressions.",
"author": "Jeff Williams <jeffrey.l.williams@gmail.com>",
"repository": {
"type": "git",
"url": "https://github.com/hegemonic/catharsis"
},
"bugs": "https://github.com/hegemonic/catharsis/issues",
"main": "catharsis.js",
"devDependencies": {
"mocha": "1.13.0",
"pegjs": "git+ssh://git@github.com:dmajda/pegjs.git#76cc5d55",
"should": "1.3.0",
"uglify-js": "2.4.0",
"underscore": "1.5.2"
},
"engines": {
"node": ">= 0.6"
},
"scripts": {
"build": "./node_modules/.bin/pegjs ./lib/parser.pegjs",
"prepublish": "./node_modules/.bin/pegjs ./lib/parser.pegjs; ./node_modules/.bin/uglifyjs ./lib/parser.js -o ./lib/parser.js",
"test": "mocha"
},
"licenses": [
{
"type": "MIT",
"url": "http://github.com/hegemonic/catharsis/raw/master/LICENSE"
}
]
"version": "0.8.0",
"name": "catharsis",
"description": "A JavaScript parser for Google Closure Compiler and JSDoc type expressions.",
"author": "Jeff Williams <jeffrey.l.williams@gmail.com>",
"repository": {
"type": "git",
"url": "https://github.com/hegemonic/catharsis"
},
"bugs": "https://github.com/hegemonic/catharsis/issues",
"main": "catharsis.js",
"dependencies": {
"underscore": "~1.6.0",
"underscore-contrib": "~0.2.2"
},
"devDependencies": {
"mocha": "~1.18.2",
"pegjs": "git+ssh://git@github.com:dmajda/pegjs.git#76cc5d55",
"should": "~3.3.1",
"uglify-js": "~2.4.13"
},
"engines": {
"node": ">= 0.8"
},
"scripts": {
"build": "./node_modules/.bin/pegjs ./lib/parser.pegjs",
"prepublish": "./node_modules/.bin/pegjs ./lib/parser.pegjs; ./node_modules/.bin/uglifyjs ./lib/parser.js -o ./lib/parser.js",
"test": "mocha"
},
"licenses": [
{
"type": "MIT",
"url": "http://github.com/hegemonic/catharsis/raw/master/LICENSE"
}
]
}

@@ -13,4 +13,5 @@ # Catharsis #

+ **Fast**. Parse results are cached, so the parser is invoked only when necessary.
+ **Flexible**. Catharsis can convert parse results back into type expressions. In addition, it can
parse [JSDoc](https://github.com/jsdoc3/jsdoc)-style type expressions.
+ **Flexible**. Catharsis can convert a parse result back into a type expression, or into a
description of the type expression. In addition, Catharsis can parse
[JSDoc](https://github.com/jsdoc3/jsdoc)-style type expressions.

@@ -41,8 +42,14 @@

// Converting parse results back to type expressions
catharsis.stringify(parsedType); // !Object
catharsis.stringify(parsedJsdocType); // string[]
catharsis.stringify(parsedJsdocType, {restringify: true}); // Array.<string>
// Converting parse results to descriptions of the type expression
catharsis.describe(parsedType).simple; // non-null Object
catharsis.describe(parsedJsdocType).simple; // Array of string
```
See the `test/specs/` directory for more examples of Catharsis' parse results.
See the [test/specs directory](tree/master/test/specs) for more examples of Catharsis' parse
results.

@@ -53,3 +60,3 @@

### parse(typeExpression, options) ###
Parse `typeExpression`, and return the parse results. Throws an error if the type expression cannot
Parse a type expression, and return the parse results. Throws an error if the type expression cannot
be parsed.

@@ -82,4 +89,4 @@

#### Returns ####
An object containing the parse results. See the `test/specs/` directory for examples of the parse
results for different type expressions.
An object containing the parse results. See the [test/specs directory](tree/master/test/specs) for
examples of the parse results for different type expressions.

@@ -98,10 +105,12 @@ The object also includes two non-enumerable properties:

+ `options`: Options for stringifying the parse results.
+ `options.cssClass`: A CSS class to add to HTML links. Used only if `options.links` is
provided. By default, no CSS class is added.
+ `options.cssClass`: Synonym for `options.linkClass`. Deprecated in version 0.8.0; will be
removed in a future version.
+ `options.htmlSafe`: Specifies whether to return an HTML-safe string that replaces left angle
brackets (`<`) with the corresponding entity (`&lt;`). **Note**: Characters in name expressions
are not escaped.
+ `options.linkClass`: A CSS class to add to HTML links. Used only if `options.links` is
provided. By default, no CSS class is added.
+ `options.links`: An object whose keys are name expressions and whose values are URIs. If a
name expression matches a key in `options.links`, the name expression will be wrapped in an
HTML `<a>` tag that links to the URI. If `options.cssClass` is specified, the `<a>` tag will
HTML `<a>` tag that links to the URI. If `options.linkClass` is specified, the `<a>` tag will
include a `class` attribute. **Note**: When using this option, parsed types are always

@@ -112,4 +121,4 @@ restringified, and the resulting string is not cached.

return the `typeExpression` property without modification when possible. Defaults to `false`.
+ `options.useCache`: Specifies whether to use the cache of stringified parse results. Defaults
to `true`.
+ `options.useCache`: Specifies whether to use the cache of stringified type expressions.
Defaults to `true`.
+ `options.validate`: Specifies whether to validate the stringified parse results by attempting

@@ -122,3 +131,80 @@ to parse them as a type expression. If the stringified results are not parsable by default, you

### describe(parsedType, options) ###
Convert a parsed type to a description of the type expression. This method is especially useful if
your users are not familiar with the syntax for type expressions.
The `describe()` method returns the description in two formats:
+ **Simple format**. A string that provides a complete description of the type expression.
+ **Extended format**. An object that separates out some of the details about the outermost type
expression, such as whether the type is optional, nullable, or repeatable.
For example, if you call `describe('?function(new:MyObject, string)=')`, it returns the following
object:
```js
{
simple: 'optional nullable function(constructs MyObject, string)',
extended: {
description: 'function(string)',
modifiers: {
functionNew: 'Returns MyObject when called with new.',
functionThis: '',
optional: 'Optional.',
nullable: 'May be null.',
repeatable: ''
},
returns: ''
}
}
```
#### Parameters ####
+ `parsedType`: An object containing a parsed Closure Compiler type expression.
+ `options`: Options for creating the description.
+ `options.codeClass`: A CSS class to add to the tag that is wrapped around type names. Used
only if `options.codeTag` is provided. By default, no CSS class is added.
+ `options.codeTag`: The name of an HTML tag (for example, `code`) to wrap around type names.
For example, if this option is set to `code`, the type expression `Array.<string>` would have
the simple description `<code>Array</code> of <code>string</code>`.
+ `options.language`: A string identifying the language in which to generate the description.
The identifier should be an
[ISO 639-1 language code](http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) (for example,
`en`). It can optionally be followed by a hyphen and an
[ISO 3166-1 alpha-2 country code](http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) (for example,
`en-US`). If you use values other than `en`, you must provide translation resources in
`options.resources`. Defaults to `en`.
+ `options.linkClass`: A CSS class to add to HTML links. Used only if `options.links` is
provided. By default, no CSS class is added.
+ `options.links`: An object whose keys are name expressions and whose values are URIs. If a
name expression matches a key in `options.links`, the name expression will be wrapped in an
HTML `<a>` tag that links to the URI. If `options.linkClass` is specified, the `<a>` tag will
include a `class` attribute. **Note**: When using this option, the description is not cached.
+ `options.resources`: An object that specifies how to describe type expressions for a given
language. The object's property names should use the same format as `options.language`. Each
property should contain an object in the same format as the translation resources in
[res/en.json](tree/master/res/en.json). If you specify a value for `options.resources.en`, it
will override the defaults in [res/en.json](tree/master/res/en.json).
+ `options.useCache`: Specifies whether to use the cache of descriptions. Defaults to `true`.
### Returns ###
An object with the following properties:
+ `simple`: A string that provides a complete description of the type expression.
+ `extended`: An object containing details about the outermost type expression.
+ `extended.description`: A string that provides a basic description of the type expression,
excluding the information contained in other properties.
+ `extended.modifiers`: Information about modifiers that apply to the type expression.
+ `extended.modifiers.functionNew`: A string describing what a function returns when called
with `new`. Used only for function types.
+ `extended.modifiers.functionThis`: A string describing what the keyword `this` refers to
within a function. Used only for function types.
+ `extended.modifiers.nullable`: A string indicating whether the type is nullable or
non-nullable.
+ `extended.modifiers.optional`: A string indicating whether the type is optional.
+ `extended.modifiers.repeatable`: A string indicating whether the type can be provided
+ `extended.returns`: A string describing the function's return value. Used only for function
types.
## Installation ##

@@ -133,2 +219,4 @@

git clone git://github.com/hegemonic/catharsis.git
cd catharsis
npm install

@@ -150,2 +238,7 @@

+ 0.8.0 (May 2014):
+ Added a `describe()` method, which converts a parsed type to a description of the type.
+ Added a `linkClass` option to the `stringify()` method, and deprecated the existing `cssClass`
option. The `cssClass` option will be removed in a future release.
+ Clarified and corrected several sections in the `README`.
+ 0.7.1 (April 2014): In record types, property names that begin with a keyword (for example,

@@ -152,0 +245,0 @@ `undefinedHTML`) are now parsed correctly when JSDoc-style type expressions are enabled.

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc