| 
				
					 | 
			2 years ago | |
|---|---|---|
| .. | ||
| bin | 2 years ago | |
| lib | 2 years ago | |
| peg_lib | 2 years ago | |
| peg_src | 2 years ago | |
| schemas | 2 years ago | |
| tests | 2 years ago | |
| .eslintignore | 2 years ago | |
| .eslintrc | 2 years ago | |
| .jscsrc | 2 years ago | |
| .travis.yml | 2 years ago | |
| LICENSE-MIT.txt | 2 years ago | |
| README.md | 2 years ago | |
| index.js | 2 years ago | |
| package.json | 2 years ago | |
The parser can parse:
foo.bar, String[]Array<string>, function(arg1, arg2): retBoolean/"top"/"bottom"(x: number) => string, typeof x, import("./some-module")Array<Array<string>>, function(function(Function))The live demo is available.
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.
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>"
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');
const ast = {
  type: 'NAME',
  name: 'MyClass',
};
const customPublisher = createDefaultPublisher();
customPublisher.NAME = (node, pub) =>
  `<a href="./types/${node.name}.html">${node.name}</a>`;
const string = publish(ast, customPublisher);
The string becomes:
<a href="./types/MyClass.html">MyClass</a>
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
NAMEExample:
/**
 * @type {name}
 */
Structure:
{
  "type": "NAME",
  "name": string
}
MEMBERExample:
/**
 * @type {owner.name}
 * @type {superOwner.owner.name}
 */
Structure:
{
  "type": "MEMBER",
  "name": string,
  "owner": node,
  "hasEventPrefix": boolean
}
INNER_MEMBERExample:
/**
 * @type {owner~name}
 */
Structure:
{
  "type": "INNER_MEMBER",
  "name": string,
  "owner": node,
  "hasEventPrefix": boolean
}
INSTANCE_MEMBERExample:
/**
 * @type {owner#name}
 */
Structure:
{
  "type": "INSTANCE_MEMBER",
  "name": string,
  "owner": node,
  "hasEventPrefix": boolean
}
UNIONExample:
/**
 * @type {left|right}
 * @type {(left|right)}
 * @type {left/right}
 */
Structure:
{
  "type": "UNION",
  "left": node,
  "right": node,
  "meta": {
    "syntax": ("PIPE" or "SLASH")
  }
}
RECORDExample:
/**
 * @type {{}}
 * @type {{ key: value }}
 * @type {{ key: value, anyKey }}
 */
Structure:
{
  "type": "RECORD",
  "entries": [
    recordEntryNode,
    recordEntryNode,
    ...
  ]
}
RECORD_ENTRYStructure:
{
  "type": "RECORD_ENTRY",
  "key": string,
  "value": node (or null)
}
GENERICExample:
/**
 * @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")
  }
}
FUNCTIONExample:
/**
 * @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)
}
OPTIONALExample:
/**
 * @type {Optional=}
 */
Structure:
{
  "type": "OPTIONAL",
  "value": node,
  "meta": {
    "syntax": ("PREFIX_EQUALS_SIGN" or "SUFFIX_EQUALS_SIGN")
  }
}
NULLABLEExample:
/**
 * @type {?Nullable}
 */
Structure:
{
  "type": "NULLABLE",
  "value": node,
  "meta": {
    "syntax": ("PREFIX_QUESTION_MARK" or "SUFFIX_QUESTION_MARK")
  }
}
NOT_NULLABLEExample:
/**
 * @type {!NotNullable}
 */
Structure:
{
  "type": "NOT_NULLABLE",
  "value": node,
  "meta": {
    "syntax": ("PREFIX_BANG" or "SUFFIX_BANG")
  }
}
VARIADICExample:
/**
 * @type {...Variadic}
 * @type {Variadic...}
 * @type {...}
 */
Structure:
{
  "type": "VARIADIC",
  "value": node (or null),
  "meta": {
    "syntax": ("PREFIX_DOTS" or "SUFFIX_DOTS" or "ONLY_DOTS")
  }
}
MODULEExample:
/**
 * @type {module:path/to/file.Module}
 */
Structure:
{
  "type": "MODULE",
  "value": node
}
FILE_PATHExample:
/**
 * @type {module:path/to/file.Module}
 *               ^^^^^^^^^^^^
 */
Structure:
{
  "type": "FILE_PATH",
  "path": string
}
EXTERNALExample:
/**
 * @type {external:External}
 */
Structure:
{
  "type": "EXTERNAL",
  "value": node
}
STRING_VALUEExample:
/**
 * @type {"abc"}
 * @type {"can\"escape"}
 */
Structure:
{
  "type": "STRING_VALUE",
  "string": string
}
NUMBER_VALUEExample:
/**
 * @type {123}
 * @type {0b11}
 * @type {0o77}
 * @type {0xff}
 */
Structure:
{
  "type": "NUMBER_VALUE",
  "number": string
}
ANYExample:
/**
 * @type {*}
 */
Structure:
{
  "type": "ANY"
}
UNKNOWNExample:
/**
 * @type {?}
 */
Structure:
{
  "type": "UNKNOWN"
}
PARENTHESISExample:
/**
 * @type {(Foo)}
 */
Structure:
{
  "type": "PARENTHESIS",
  "value": node
}
We can use a parenthesis to change operator orders.
/**
 * @type {(module:path/to/file.js).foo}
 */