jsdoctypeparser v9.0.0
jsdoctypeparser
The parser can parse:
- JSDoc type expressions
foo.bar
,String[]
- Closure Compiler type expressions
Array<string>
,function(arg1, arg2): ret
- some Typescript types
(x: number) => string
,typeof x
,import("./some-module")
- Complex type expressions
Array<Array<string>>
,function(function(Function))
Live demo
The live demo is available.
Usage (Programmatic)
Parsing
const {parse} = require('jsdoctypeparser');
const 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
.
const {publish} = require('jsdoctypeparser');
const ast = {
type: 'GENERIC',
subject: {
type: 'NAME',
name: 'Array'
},
objects: [
{
type: 'NAME',
name: 'MyClass'
}
]
};
const 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');
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>
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 }>');
function onEnter(node, parentName, parentNode) {
console.log('enter', node.type, parentName, parentNode.type);
}
function onLeave(node, parentName, parentNode) {
console.log('leave', node.type, parentName, parentNode.type);
}
traverse(ast, onEnter, onLeave);
The output will be:
enter GENERIC null null
enter NAME subject GENERIC
leave NAME subject GENERIC
enter RECORD objects GENERIC
enter RECORD_ENTRY entries RECORD
enter FUNCTION value RECORD_ENTRY
leave FUNCTION value RECORD_ENTRY
leave RECORD_ENTRY entries RECORD
enter RECORD_ENTRY entries RECORD
enter MEMBER value RECORD_ENTRY
enter MEMBER owner MEMBER
enter NAME owner MEMBER
leave NAME owner MEMBER
leave MEMBER owner MEMBER
leave MEMBER value RECORD_ENTRY
leave RECORD_ENTRY entries RECORD
leave RECORD objects GENERIC
leave GENERIC null null
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,
"quoteStyle": "none",
"owner": node,
"hasEventPrefix": boolean
}
INNER_MEMBER
Example:
/**
* @type {owner~name}
*/
Structure:
{
"type": "INNER_MEMBER",
"name": string,
"quoteStyle": "none",
"owner": node,
"hasEventPrefix": boolean
}
INSTANCE_MEMBER
Example:
/**
* @type {owner#name}
*/
Structure:
{
"type": "INSTANCE_MEMBER",
"name": string,
"quoteStyle": "none",
"owner": node,
"hasEventPrefix": boolean
}
UNION
Example:
/**
* @type {left|right}
* @type {(left|right)}
*/
Structure:
{
"type": "UNION",
"left": node,
"right": node
}
INTERSECTION
Example:
/**
* @type {left&right}
* @type {(left&right)}
*/
Structure:
{
"type": "INTERSECTION",
"left": node,
"right": node
}
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,
"meta": {
"syntax": ("PREFIX_EQUALS_SIGN" or "SUFFIX_EQUALS_SIGN")
}
}
NULLABLE
Example:
/**
* @type {?Nullable}
*/
Structure:
{
"type": "NULLABLE",
"value": node,
"meta": {
"syntax": ("PREFIX_QUESTION_MARK" or "SUFFIX_QUESTION_MARK")
}
}
NOT_NULLABLE
Example:
/**
* @type {!NotNullable}
*/
Structure:
{
"type": "NOT_NULLABLE",
"value": node,
"meta": {
"syntax": ("PREFIX_BANG" or "SUFFIX_BANG")
}
}
VARIADIC
Example:
/**
* @type {...Variadic}
* @type {Variadic...}
* @type {...}
*/
Structure:
{
"type": "VARIADIC",
"value": node (or null),
"meta": {
"syntax": ("PREFIX_DOTS" or "SUFFIX_DOTS" or "ONLY_DOTS")
}
}
MODULE
Example:
/**
* @type {module:path/to/file.Module}
*/
Structure:
{
"type": "MODULE",
"value": node
}
FILE_PATH
Example:
/**
* @type {module:path/to/file.Module}
* ^^^^^^^^^^^^
*/
Structure:
{
"type": "FILE_PATH",
"path": string
}
EXTERNAL
Example:
/**
* @type {external:External}
*/
Structure:
{
"type": "EXTERNAL",
"value": node
}
STRING_VALUE
Example:
/**
* @type {"abc"}
* @type {"can\"escape"}
*/
Structure:
{
"type": "STRING_VALUE",
"quoteStyle": "double",
"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"
}
PARENTHESIS
Example:
/**
* @type {(Foo)}
*/
Structure:
{
"type": "PARENTHESIS",
"value": node
}
Others
We can use a parenthesis to change operator orders.
/**
* @type {(module:path/to/file.js).foo}
*/
Usage (CLI)
To parse a type into a JSON structure, you may pass a string argument containing the structure to parse (with the JSON results equivalent to the parsing example above):
jsdoctypeparser 'Array<MyClass>'
Note: There is no need to prefix the path to the jsdoctypeparser
binary,
e.g., with ./node_modules/.bin/
when you are running within one of the
package.json
scripts
or if you have installed the package globally.
License
4 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
6 years ago
6 years ago
6 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago