JSPM

  • Created
  • Published
  • Downloads 554467
  • Score
    100M100P100Q180750F
  • License MIT

Strict JsDoc type expression parser.

Package Exports

  • jsdoctypeparser

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (jsdoctypeparser) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

jsdoctypeparser

Build Status NPM version

The parser can parse:

Live demo

The live demo is available.

Usage

Parsing

var parse = require('jsdoctypeparser').parse;

var ast = parse('Array<MyClass>');

The ast becomes:

{
  "type": "GENERIC",
  "subject": {
    "type": "NAME",
    "name": "Array"
  },
  "objects": [
    {
      "type": "NAME",
      "name": "MyClass"
    }
  ],
  "meta": {
    "syntax": "ANGLE_BRACKET"
  }
}

See the AST specifications.

Publishing

We can stringify the AST nodes by using publish.

var publish = require('jsdoctypeparser').publish;

var ast = {
  type: 'GENERIC',
  subject: {
    type: 'NAME',
    name: 'Array'
  },
  objects: [
    {
      type: 'NAME',
      name: 'MyClass'
    }
  ]
};

var string = publish(ast);

The string becomes:

"Array<MyClass>"

Custom publishing

We can change the stringification strategy by using the 2nd parameter of publish(node, publisher). The publisher MUST have handlers for all node types (see lib/NodeType.js).

And we can override default behavior by using createDefaultPublisher.

const {publish, createDefaultPublisher} = require('jsdoctypeparser').publish;

const ast = {
  type: 'NAME',
  name: 'MyClass'
};

const defaultPublisher = createDefaultPublisher();
const customPublisher = Object.create(defaultPublisher, {
  NAME: (node, pub) => {
    return `<a href="./types/${node.name}.html">${node.name}</a>`;
  },
});

const string = publish(ast, customPublisher);

The string becomes:

<a href="./types/MyClass.html">MyClass</a>

Traversing

We can traverse the AST by using traverse. This function takes 3 parameters (a node and an onEnter handler, an onLeave handler). The handlers take a visiting node.

const {parse, traverse} = require('jsdoctypeparser');
const ast = parse('Array<{ key1: function(), key2: A.B.C }>');

funciton onEnter(node) {
  console.log('enter', node.type);
}

funciton onLeave(node) {
  console.log('leave', node.type);
}

traverse(ast, onEnter, onLeave);

The output will be:

enter GENERIC
enter RECORD
enter RECORD_ENTRY
enter FUNCTION
leave FUNCTION
leave RECORD_ENTRY
enter RECORD_ENTRY
enter MEMBER
enter MEMBER
enter NAME
leave NAME
leave MEMBER
leave MEMBER
leave RECORD_ENTRY
leave RECORD
leave GENERIC

AST Specifications

NAME

Example:

/**
 * @type {name}
 */

Structure:

{
  "type": "NAME",
  "name": string
}

MEMBER

Example:

/**
 * @type {owner.name}
 * @type {superOwner.owner.name}
 */

Structure:

{
  "type": "MEMBER",
  "name": string,
  "owner": node
}

INNER_MEMBER

Example:

/**
 * @type {owner~name}
 */

Structure:

{
  "type": "INNER_MEMBER",
  "name": string,
  "owner": node
}

INSTANCE_MEMBER

Example:

/**
 * @type {owner#name}
 */

Structure:

{
  "type": "INSTANCE_MEMBER",
  "name": string,
  "owner": node
}

UNION

Example:

/**
 * @type {left|right}
 * @type {(left|right)}
 * @type {left/right}
 */

Structure:

{
  "type": "UNION",
  "left": node,
  "right": node,
  "meta": {
    "syntax": ("PIPE" or "SLASH")
  }
}

RECORD

Example:

/**
 * @type {{}}
 * @type {{ key: value }}
 * @type {{ key: value, anyKey }}
 */

Structure:

{
  "type": "RECORD",
  "entries": [
    recordEntryNode,
    recordEntryNode,
    ...
  ]
}

RECORD_ENTRY

Structure:

{
  "type": "RECORD_ENTRY",
  "key": string,
  "value": node (or null)
}

GENERIC

Example:

/**
 * @type {Subject<Object, Object>}
 * @type {Object[]}
 */

Structure:

{
  "type": "GENERIC",
  "subject": node,
  "objects": [
    node,
    node,
    ...
  ],
  "meta": {
    "syntax": ("ANGLE_BRACKET" or "ANGLE_BRACKET_WITH_DOT" or "SQUARE_BRACKET")
  }
}

FUNCTION

Example:

/**
 * @type {function()}
 * @type {function(param, param): return}
 * @type {function(this: Context)}
 * @type {function(new: Class)}
 */

Structure:

{
  "type": "FUNCTION",
  "params": [
    node,
    node,
    ...
  ],
  "returns": node (or null),
  "new": node (or null),
  "this": node (or null)
}

OPTIONAL

Example:

/**
 * @type {Optional=}
 */

Structure:

{
  "type": "OPTIONAL",
  "value": node
}

NULLABLE

Example:

/**
 * @type {?Nullable}
 */

Structure:

{
  "type": "NULLABLE",
  "value": node
}

NOT_NULLABLE

Example:

/**
 * @type {!NotNullable}
 */

Structure:

{
  "type": "NOT_NULLABLE",
  "value": node
}

VARIADIC

Example:

/**
 * @type {...Variadic}
 */

Structure:

{
  "type": "VARIADIC",
  "value": node
}

MODULE

Example:

/**
 * @type {module:path/to/file.js}
 */

Structure:

{
  "type": "MODULE",
  "path": string
}

EXTERNAL

Example:

/**
 * @type {external:External}
 */

Structure:

{
  "type": "EXTERNAL",
  "value": node
}

STRING_VALUE

Example:

/**
 * @type {"abc"}
 * @type {"can\"escape"}
 */

Structure:

{
  "type": "STRING_VALUE",
  "string": string
}

NUMBER_VALUE

Example:

/**
 * @type {123}
 * @type {0b11}
 * @type {0o77}
 * @type {0xff}
 */

Structure:

{
  "type": "NUMBER_VALUE",
  "number": string
}

ANY

Example:

/**
 * @type {*}
 */

Structure:

{
  "type": "ANY"
}

UNKNOWN

Example:

/**
 * @type {?}
 */

Structure:

{
  "type": "UNKNOWN"
}

Others

We can use a parenthesis to change operator orders.

/**
 * @type {(module:path/to/file.js).foo}
 */

License

This script licensed under the MIT.