npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

jsdoctypeparser

v9.0.0

Published

Strict JsDoc type expression parser.

Downloads

1,477,870

Readme

jsdoctypeparser

Build Status NPM version

The parser can parse:

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

This script is licensed under the MIT.