snapdragon-node

    3.0.0 • Public • Published

    snapdragon-node NPM version NPM monthly downloads NPM total downloads Linux Build Status

    Class for creating AST nodes.

    Please consider following this project's author, Jon Schlinkert, and consider starring the project to show your ❤️ and support.

    Install

    Install with npm:

    $ npm install --save snapdragon-node

    Usage

    const Node = require('snapdragon-node');
    // either pass on object with "type" and (optional) "val"
    const node1 = new Node({type: 'star', val: '*'});
    // or pass "val" (first) and "type" (second) as string
    const node2 = new Node('*', 'star');
    // both result in => Node { type: 'star', val: '*' }

    Snapdragon usage

    With snapdragon v0.9.0 and higher, it's recommended that you use this.node() to create a new Node inside parser handlers (instead of doing new Node()).

    Snapdragon ^1.0.0

    Example usage inside a snapdragon parser handler function.

    const Node = require('snapdragon-node');
    const Token = require('snapdragon-token');
     
    // create a new AST node
    const node = new Node({ type: 'star', value: '*' });
     
    // convert a Lexer Token into an AST Node
    const token = new Token({ type: 'star', value: '*' });
    const node = new Node(token);

    Node objects

    AST Nodes are represented as Node objects that implement the following interface:

    interface Node {
      type: string;
      value: string | undefined
      nodes: array | undefined
    }
    • type {string} - A string representing the node variant type. This property is often used for classifying the purpose or nature of the node, so that parsers or compilers can determine what to do with it.
    • value {string|undefined} (optional) - In general, value should only be a string when node.nodes is undefined. This is not reinforced, but is considered good practice. Use a different property name to store arbitrary strings on the node when node.nodes is an array.
    • nodes {array|undefined} (optional) - array of child nodes

    A number of useful methods and non-enumerable properties are also exposed for adding, finding and removing child nodes, etc.

    Continue reading the API documentation for more details.

    Node API

    Node

    Create a new AST Node with the given type and value, or an object to initialize with.

    Params

    • type {object|string}: Either an object to initialize with, or a string to be used as the node.type.
    • value {string|boolean}: If the first argument is a string, the second argument may be a string value to set on node.value.
    • clone {boolean}: When an object is passed as the first argument, pass true as the last argument to deep clone values before assigning them to the new node.
    • returns {Object}: node instance

    Example

    console.log(new Node({ type: 'star', value: '*' }));
    console.log(new Node('star', '*'));
    // both result in => Node { type: 'star', value: '*' }

    .clone

    Return a clone of the node. Values that are arrays or plain objects are deeply cloned.

    • returns {Object}: returns a clone of the node

    Example

    const node = new Node({type: 'star', value: '*'});
    consle.log(node.clone() !== node);
    //=> true

    .stringify

    Return a string created from node.value and/or recursively visiting over node.nodes.

    • returns {String}

    Example

    const node = new Node({type: 'star', value: '*'});
    consle.log(node.stringify());
    //=> '*'

    .push

    Push a child node onto the node.nodes array.

    Params

    • node {Object}
    • returns {Number}: Returns the length of node.nodes, like Array.push

    Example

    const foo = new Node({type: 'foo'});
    const bar = new Node({type: 'bar'});
    foo.push(bar);

    .unshift

    Unshift a child node onto node.nodes, and set node as the parent on child.parent.

    Params

    • node {Object}
    • returns {Number}: Returns the length of node.nodes

    Example

    const foo = new Node({type: 'foo'});
    const bar = new Node({type: 'bar'});
    foo.unshift(bar);

    .pop

    Pop a node from node.nodes.

    • returns {Number}: Returns the popped node

    Example

    const node = new Node({type: 'foo'});
    node.push(new Node({type: 'a'}));
    node.push(new Node({type: 'b'}));
    node.push(new Node({type: 'c'}));
    node.push(new Node({type: 'd'}));
    console.log(node.nodes.length);
    //=> 4
    node.pop();
    console.log(node.nodes.length);
    //=> 3

    .shift

    Shift a node from node.nodes.

    • returns {Object}: Returns the shifted node

    Example

    const node = new Node({type: 'foo'});
    node.push(new Node({type: 'a'}));
    node.push(new Node({type: 'b'}));
    node.push(new Node({type: 'c'}));
    node.push(new Node({type: 'd'}));
    console.log(node.nodes.length);
    //=> 4
    node.shift();
    console.log(node.nodes.length);
    //=> 3

    .remove

    Remove node from node.nodes.

    Params

    • node {Object}
    • returns {Object}: Returns the removed node.

    Example

    node.remove(childNode);

    .find

    Get the first child node from node.nodes that matches the given type. If type is a number, the child node at that index is returned.

    Params

    • type {String}
    • returns {Object}: Returns a child node or undefined.

    Example

    const child = node.find(1); //<= index of the node to get
    const child = node.find('foo'); //<= node.type of a child node
    const child = node.find(/^(foo|bar)$/); //<= regex to match node.type
    const child = node.find(['foo', 'bar']); //<= array of node.type(s)

    .has

    Returns true if node.nodes array contains the given node.

    Params

    • type {String}
    • returns {Boolean}

    Example

    const foo = new Node({type: 'foo'});
    const bar = new Node({type: 'bar'});
    cosole.log(foo.has(bar)); // false
    foo.push(bar);
    cosole.log(foo.has(bar)); // true

    .hasType

    Return true if the node.nodes has the given type.

    Params

    • type {String}
    • returns {Boolean}

    Example

    const foo = new Node({type: 'foo'});
    const bar = new Node({type: 'bar'});
    foo.push(bar);
     
    cosole.log(foo.hasType('qux'));          // false
    cosole.log(foo.hasType(/^(qux|bar)$/));  // true
    cosole.log(foo.hasType(['qux', 'bar'])); // true

    .isType

    Return true if the node is the given type.

    Params

    • type {String}
    • returns {Boolean}

    Example

    const node = new Node({type: 'bar'});
    cosole.log(node.isType('foo'));          // false
    cosole.log(node.isType(/^(foo|bar)$/));  // true
    cosole.log(node.isType(['foo', 'bar'])); // true

    .isEmpty

    Returns true if node.value is an empty string, or node.nodes does not contain any non-empty text nodes.

    Params

    • fn {Function}: (optional) Filter function that is called on node and/or child nodes. isEmpty will return false immediately when the filter function returns false on any nodes.
    • returns {Boolean}

    Example

    const node = new Node({type: 'text'});
    node.isEmpty(); //=> true
    node.value = 'foo';
    node.isEmpty(); //=> false

    .isInside

    Returns true if the node has an ancestor node of the given type

    Params

    • type {String}
    • returns {Boolean}

    Example

    const box = new Node({type: 'box'});
    const marble = new Node({type: 'marble'});
    box.push(marble);
    marble.isInside('box'); //=> true

    .siblings

    Get the siblings array, or null if it doesn't exist.

    • returns {Array}

    Example

    const foo = new Node({type: 'foo'});
    const bar = new Node({type: 'bar'});
    const baz = new Node({type: 'baz'});
    foo.push(bar);
    foo.push(baz);
     
    console.log(bar.siblings.length) // 2
    console.log(baz.siblings.length) // 2

    .index

    Calculate the node's current index on node.parent.nodes, or -1 if the node does not have a parent, or is not on node.parent.nodes.

    • returns {Number}

    Example

    const foo = new Node({type: 'foo'});
    const bar = new Node({type: 'bar'});
    const baz = new Node({type: 'baz'});
    const qux = new Node({type: 'qux'});
    foo.push(bar);
    foo.push(baz);
    foo.unshift(qux);
     
    console.log(bar.index) // 1
    console.log(baz.index) // 2
    console.log(qux.index) // 0

    .prev

    Get the previous node from the siblings array or null.

    • returns {Object}

    Example

    const foo = new Node({type: 'foo'});
    const bar = new Node({type: 'bar'});
    const baz = new Node({type: 'baz'});
    foo.push(bar);
    foo.push(baz);
     
    console.log(baz.prev.type) // 'bar'

    .next

    Get the next element from the siblings array, or null if a next node does not exist.

    • returns {Object}

    Example

    const parent = new Node({type: 'root'});
    const foo = new Node({type: 'foo'});
    const bar = new Node({type: 'bar'});
    const baz = new Node({type: 'baz'});
    parent.push(foo);
    parent.push(bar);
    parent.push(baz);
     
    console.log(foo.next.type) // 'bar'
    console.log(bar.next.type) // 'baz'

    .first

    Get the first child node from node.nodes.

    • returns {Object}: The first node, or undefiend

    Example

    const foo = new Node({type: 'foo'});
    const bar = new Node({type: 'bar'});
    const baz = new Node({type: 'baz'});
    const qux = new Node({type: 'qux'});
    foo.push(bar);
    foo.push(baz);
    foo.push(qux);
     
    console.log(foo.first.type) // 'bar'

    .last

    Get the last child node from node.nodes.

    • returns {Object}: The last node, or undefiend

    Example

    const foo = new Node({type: 'foo'});
    const bar = new Node({type: 'bar'});
    const baz = new Node({type: 'baz'});
    const qux = new Node({type: 'qux'});
    foo.push(bar);
    foo.push(baz);
    foo.push(qux);
     
    console.log(foo.last.type) // 'qux'

    .depth

    Get the node.depth. The root node has a depth of 0. Add 1 to child nodes for each level of nesting.

    • returns {Object}: The last node, or undefiend

    Example

    const foo = new Node({type: 'foo'});
    foo.push(bar);
     
    console.log(foo.depth) // 1
    console.log(bar.depth) // 2

    Node#isNode

    Static method that returns true if the given value is a node.

    Params

    • node {Object}
    • returns {Boolean}

    Example

    const Node = require('snapdragon-node');
    const node = new Node({type: 'foo'});
    console.log(Node.isNode(node)); //=> true
    console.log(Node.isNode({})); //=> false

    Non-enumerable properties

    • node.isNode {boolean} - this value is set to true when a node is created. This can be useful in situationas as a fast alternative to using instanceof Node if you need to determine if a value is a node object.
    • node.size {number} - the number of child nodes that have been pushed or unshifted onto node.nodes using the node's API. This is useful for determining if nodes were added to node.nodes without using node.push() or node.unshift() (for example: if (node.nodes && node.size !== node.nodes.length))
    • node.parent {object} (instance of Node)

    Release history

    See the changelog.

    About

    Contributing

    Pull requests and stars are always welcome. For bugs and feature requests, please create an issue.

    Please read the contributing guide for advice on opening issues, pull requests, and coding standards.

    Running Tests

    Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:

    $ npm install && npm test
    Building docs

    (This project's readme.md is generated by verb, please don't edit the readme directly. Any changes to the readme must be made in the .verb.md readme template.)

    To generate the readme, run the following command:

    $ npm install -g verbose/verb#dev verb-generate-readme && verb

    Related projects

    You might also be interested in these projects:

    Author

    Jon Schlinkert

    License

    Copyright © 2018, Jon Schlinkert. Released under the MIT License.


    This file was generated by verb-generate-readme, v0.8.0, on November 24, 2018.

    Install

    npm i snapdragon-node

    DownloadsWeekly Downloads

    17,597,695

    Version

    3.0.0

    License

    MIT

    Unpacked Size

    35.8 kB

    Total Files

    5

    Last publish

    Collaborators

    • danez
    • jonschlinkert