snapdragon-node
Advanced tools
Comparing version 0.2.0 to 1.0.0
293
index.js
'use strict'; | ||
var utils = require('snapdragon-util'); | ||
var define = require('define-property'); | ||
var isObject = require('isobject'); | ||
var getters = ['siblings', 'index', 'first', 'lext', 'prev', 'next']; | ||
/** | ||
* Create a new AST `Node` with the given `val` and `type`. | ||
* | ||
* ```js | ||
* var node = new Node('*', 'Star'); | ||
* var node = new Node({type: 'star', val: '*'}); | ||
* ``` | ||
* @name Node | ||
* @param {String|Object} `val` Pass a matched substring, or an object to merge onto the node. | ||
* @param {String} `type` The node type to use when `val` is a string. | ||
* @return {Object} node instance | ||
* @api public | ||
*/ | ||
class Node { | ||
@@ -11,3 +27,5 @@ constructor(val, type) { | ||
for (var key in val) { | ||
this[key] = val[key]; | ||
if (getters.indexOf(key) === -1) { | ||
this[key] = val[key]; | ||
} | ||
} | ||
@@ -20,2 +38,16 @@ } else { | ||
/** | ||
* Define a non-enumberable property on the node instance. | ||
* | ||
* ```js | ||
* var node = new Node(); | ||
* node.define('foo', 'something non-enumerable'); | ||
* ``` | ||
* @name .define | ||
* @param {String} `name` | ||
* @param {any} `val` | ||
* @return {Object} returns the node instance | ||
* @api public | ||
*/ | ||
define(name, val) { | ||
@@ -26,17 +58,260 @@ define(this, name, val); | ||
addNode(node) { | ||
/** | ||
* Given node `foo` and node `bar`, push node `bar` onto `foo.nodes`, and | ||
* set `foo` as `bar.parent`. | ||
* | ||
* ```js | ||
* var foo = new Node({type: 'foo'}); | ||
* var bar = new Node({type: 'bar'}); | ||
* foo.pushNode(bar); | ||
* ``` | ||
* @name .pushNode | ||
* @param {Object} `node` | ||
* @return {undefined} | ||
* @api public | ||
*/ | ||
pushNode(node) { | ||
this.nodes = this.nodes || []; | ||
node.define('index', this.nodes.length); | ||
node.define('parent', this); | ||
node.define('siblings', this.nodes); | ||
define(node, 'parent', this); | ||
this.nodes.push(node); | ||
} | ||
prev(n) { | ||
return this.siblings[this.index - (n || 1)] || this.parent.prev(n); | ||
/** | ||
* Alias for [pushNode](#pushNode) for backwards compatibility with 0.1.0. | ||
* @name .addNode | ||
* @api public | ||
*/ | ||
addNode(node) { | ||
return this.pushNode(node); | ||
} | ||
next(n) { | ||
return this.siblings[this.index + (n || 1)] || this.parent.next(n); | ||
/** | ||
* Given node `foo` and node `bar`, unshift node `bar` onto `foo.nodes`, and | ||
* set `foo` as `bar.parent`. | ||
* | ||
* ```js | ||
* var foo = new Node({type: 'foo'}); | ||
* var bar = new Node({type: 'bar'}); | ||
* foo.unshiftNode(bar); | ||
* ``` | ||
* @name .unshiftNode | ||
* @param {Object} `node` | ||
* @return {undefined} | ||
* @api public | ||
*/ | ||
unshiftNode(node) { | ||
this.nodes = this.nodes || []; | ||
define(node, 'parent', this); | ||
this.nodes.unshift(node); | ||
} | ||
/** | ||
* 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. | ||
* | ||
* ```js | ||
* var child = node.getNode(1); //<= index of the node to get | ||
* var child = node.getNode('foo'); | ||
* var child = node.getNode(/^(foo|bar)$/); | ||
* var child = node.getNode(['foo', 'bar']); | ||
* ``` | ||
* @name .getNode | ||
* @param {String} `type` | ||
* @return {Object} Returns a child node or undefined. | ||
* @api public | ||
*/ | ||
getNode(type) { | ||
return utils.getNode(this.nodes, type); | ||
} | ||
/** | ||
* Return true if the node is the given `type`. | ||
* | ||
* ```js | ||
* var 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 | ||
* ``` | ||
* @name .isType | ||
* @param {String} `type` | ||
* @return {Boolean} | ||
* @api public | ||
*/ | ||
isType(type) { | ||
return utils.isType(this, type); | ||
} | ||
/** | ||
* Return true if the `node.nodes` has the given `type`. | ||
* | ||
* ```js | ||
* var foo = new Node({type: 'foo'}); | ||
* var bar = new Node({type: 'bar'}); | ||
* foo.pushNode(bar); | ||
* | ||
* cosole.log(foo.hasType('qux')); // false | ||
* cosole.log(foo.hasType(/^(qux|bar)$/)); // true | ||
* cosole.log(foo.hasType(['qux', 'bar'])); // true | ||
* ``` | ||
* @name .hasType | ||
* @param {String} `type` | ||
* @return {Boolean} | ||
* @api public | ||
*/ | ||
hasType(type) { | ||
return utils.hasType(this, type); | ||
} | ||
/** | ||
* Get the siblings array, or `null` if it doesn't exist. | ||
* | ||
* ```js | ||
* var foo = new Node({type: 'foo'}); | ||
* var bar = new Node({type: 'bar'}); | ||
* var baz = new Node({type: 'baz'}); | ||
* foo.pushNode(bar); | ||
* foo.pushNode(baz); | ||
* | ||
* console.log(bar.siblings.length) // 2 | ||
* console.log(baz.siblings.length) // 2 | ||
* ``` | ||
* @name .siblings | ||
* @return {Array} | ||
* @api public | ||
*/ | ||
get siblings() { | ||
return this.parent ? this.parent.nodes : null; | ||
} | ||
/** | ||
* Get the previous node from the siblings array or `null`. | ||
* | ||
* ```js | ||
* var foo = new Node({type: 'foo'}); | ||
* var bar = new Node({type: 'bar'}); | ||
* var baz = new Node({type: 'baz'}); | ||
* foo.pushNode(bar); | ||
* foo.pushNode(baz); | ||
* | ||
* console.log(baz.prev.type) // 'bar' | ||
* ``` | ||
* @name .prev | ||
* @return {Object} | ||
* @api public | ||
*/ | ||
get prev() { | ||
return this.parent && this.siblings | ||
? this.siblings[this.index - 1] || this.parent.prev | ||
: null; | ||
} | ||
/** | ||
* Get the siblings array, or `null` if it doesn't exist. | ||
* | ||
* ```js | ||
* var foo = new Node({type: 'foo'}); | ||
* var bar = new Node({type: 'bar'}); | ||
* var baz = new Node({type: 'baz'}); | ||
* foo.pushNode(bar); | ||
* foo.pushNode(baz); | ||
* | ||
* console.log(bar.siblings.length) // 2 | ||
* console.log(baz.siblings.length) // 2 | ||
* ``` | ||
* @name .next | ||
* @return {Object} | ||
* @api public | ||
*/ | ||
get next() { | ||
return this.parent && this.siblings | ||
? this.siblings[this.index + 1] || this.parent.next | ||
: null; | ||
} | ||
/** | ||
* Get the node's current index from `node.parent.nodes`. | ||
* This should always be correct, even when the parent adds nodes. | ||
* | ||
* ```js | ||
* var foo = new Node({type: 'foo'}); | ||
* var bar = new Node({type: 'bar'}); | ||
* var baz = new Node({type: 'baz'}); | ||
* var qux = new Node({type: 'qux'}); | ||
* foo.pushNode(bar); | ||
* foo.pushNode(baz); | ||
* foo.unshiftNode(qux); | ||
* | ||
* console.log(bar.index) // 1 | ||
* console.log(baz.index) // 2 | ||
* console.log(qux.index) // 0 | ||
* ``` | ||
* @name .index | ||
* @return {Number} | ||
* @api public | ||
*/ | ||
get index() { | ||
if (!this.siblings) return -1; | ||
for (var i = 0; i < this.siblings.length; i++) { | ||
if (this === this.siblings[i]) { | ||
return i; | ||
} | ||
} | ||
} | ||
/** | ||
* Get the first node from `node.nodes`. | ||
* | ||
* ```js | ||
* var foo = new Node({type: 'foo'}); | ||
* var bar = new Node({type: 'bar'}); | ||
* var baz = new Node({type: 'baz'}); | ||
* var qux = new Node({type: 'qux'}); | ||
* foo.pushNode(bar); | ||
* foo.pushNode(baz); | ||
* foo.pushNode(qux); | ||
* | ||
* console.log(foo.first.type) // 'bar' | ||
* ``` | ||
* @name .first | ||
* @return {Object} The first node, or undefiend | ||
* @api public | ||
*/ | ||
get first() { | ||
return utils.arrayify(this.nodes)[0]; | ||
} | ||
/** | ||
* Get the last node from `node.nodes`. | ||
* | ||
* ```js | ||
* var foo = new Node({type: 'foo'}); | ||
* var bar = new Node({type: 'bar'}); | ||
* var baz = new Node({type: 'baz'}); | ||
* var qux = new Node({type: 'qux'}); | ||
* foo.pushNode(bar); | ||
* foo.pushNode(baz); | ||
* foo.pushNode(qux); | ||
* | ||
* console.log(foo.last.type) // 'qux' | ||
* ``` | ||
* @name .last | ||
* @return {Object} The last node, or undefiend | ||
* @api public | ||
*/ | ||
get last() { | ||
return utils.last(utils.arrayify(this.nodes)); | ||
} | ||
}; | ||
@@ -43,0 +318,0 @@ |
{ | ||
"name": "snapdragon-node", | ||
"description": "Snapdragon utility for creating a new AST node in custom code, such as plugins.", | ||
"version": "0.2.0", | ||
"version": "1.0.0", | ||
"homepage": "https://github.com/jonschlinkert/snapdragon-node", | ||
@@ -24,3 +24,4 @@ "author": "Jon Schlinkert (https://github.com/jonschlinkert)", | ||
"define-property": "^0.2.5", | ||
"isobject": "^3.0.0" | ||
"isobject": "^3.0.0", | ||
"snapdragon-util": "^1.0.0" | ||
}, | ||
@@ -38,3 +39,3 @@ "devDependencies": { | ||
"verb": { | ||
"toc": false, | ||
"toc": "collapsible", | ||
"layout": "default", | ||
@@ -41,0 +42,0 @@ "tasks": [ |
272
README.md
@@ -5,2 +5,10 @@ # snapdragon-node [![NPM version](https://img.shields.io/npm/v/snapdragon-node.svg?style=flat)](https://www.npmjs.com/package/snapdragon-node) [![NPM monthly downloads](https://img.shields.io/npm/dm/snapdragon-node.svg?style=flat)](https://npmjs.org/package/snapdragon-node) [![NPM total downloads](https://img.shields.io/npm/dt/snapdragon-node.svg?style=flat)](https://npmjs.org/package/snapdragon-node) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/snapdragon-node.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/snapdragon-node) | ||
<details> | ||
<summary><strong>Table of Contents</strong></summary> | ||
- [Install](#install) | ||
- [Usage](#usage) | ||
- [API](#api) | ||
- [About](#about) | ||
</details> | ||
## Install | ||
@@ -23,7 +31,18 @@ | ||
// example usage inside a parser visitor function | ||
snapdragon.parser.set('foo', function() { | ||
var pos = this.position(); | ||
// if the regex matches the substring at the current position | ||
// on `this.input`, return the match | ||
var match = this.match(/foo/); | ||
if (match) { | ||
return new Node(pos, match[0]); | ||
// if node.type is not defined on the node, the parser | ||
// will automatically add it | ||
var node = pos(new Node(match[0])); | ||
// or, explictly pass a type | ||
var node = pos(new Node(match[0], 'bar')); | ||
// or | ||
var node = pos(new Node({type: 'bar', val: match[0]})); | ||
return node; | ||
} | ||
@@ -33,2 +52,251 @@ }); | ||
## API | ||
### [Node](index.js#L22) | ||
Create a new AST `Node` with the given `val` and `type`. | ||
**Params** | ||
* `val` **{String|Object}**: Pass a matched substring, or an object to merge onto the node. | ||
* `type` **{String}**: The node type to use when `val` is a string. | ||
* `returns` **{Object}**: node instance | ||
**Example** | ||
```js | ||
var node = new Node('*', 'Star'); | ||
var node = new Node({type: 'star', val: '*'}); | ||
``` | ||
### [.define](index.js#L51) | ||
Define a non-enumberable property on the node instance. | ||
**Params** | ||
* `name` **{String}** | ||
* `val` **{any}** | ||
* `returns` **{Object}**: returns the node instance | ||
**Example** | ||
```js | ||
var node = new Node(); | ||
node.define('foo', 'something non-enumerable'); | ||
``` | ||
### [.pushNode](index.js#L71) | ||
Given node `foo` and node `bar`, push node `bar` onto `foo.nodes`, and set `foo` as `bar.parent`. | ||
**Params** | ||
* `node` **{Object}** | ||
* `returns` **{undefined}** | ||
**Example** | ||
```js | ||
var foo = new Node({type: 'foo'}); | ||
var bar = new Node({type: 'bar'}); | ||
foo.pushNode(bar); | ||
``` | ||
### [.addNode](index.js#L83) | ||
Alias for [pushNode](#pushNode) for backwards compatibility with 0.1.0. | ||
### [.unshiftNode](index.js#L102) | ||
Given node `foo` and node `bar`, unshift node `bar` onto `foo.nodes`, and set `foo` as `bar.parent`. | ||
**Params** | ||
* `node` **{Object}** | ||
* `returns` **{undefined}** | ||
**Example** | ||
```js | ||
var foo = new Node({type: 'foo'}); | ||
var bar = new Node({type: 'bar'}); | ||
foo.unshiftNode(bar); | ||
``` | ||
### [.getNode](index.js#L124) | ||
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** | ||
```js | ||
var child = node.getNode(1); //<= index of the node to get | ||
var child = node.getNode('foo'); | ||
var child = node.getNode(/^(foo|bar)$/); | ||
var child = node.getNode(['foo', 'bar']); | ||
``` | ||
### [.isType](index.js#L143) | ||
Return true if the node is the given `type`. | ||
**Params** | ||
* `type` **{String}** | ||
* `returns` **{Boolean}** | ||
**Example** | ||
```js | ||
var 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 | ||
``` | ||
### [.hasType](index.js#L165) | ||
Return true if the `node.nodes` has the given `type`. | ||
**Params** | ||
* `type` **{String}** | ||
* `returns` **{Boolean}** | ||
**Example** | ||
```js | ||
var foo = new Node({type: 'foo'}); | ||
var bar = new Node({type: 'bar'}); | ||
foo.pushNode(bar); | ||
cosole.log(foo.hasType('qux')); // false | ||
cosole.log(foo.hasType(/^(qux|bar)$/)); // true | ||
cosole.log(foo.hasType(['qux', 'bar'])); // true | ||
``` | ||
### [.siblings](index.js#L187) | ||
Get the siblings array, or `null` if it doesn't exist. | ||
* `returns` **{Array}** | ||
**Example** | ||
```js | ||
var foo = new Node({type: 'foo'}); | ||
var bar = new Node({type: 'bar'}); | ||
var baz = new Node({type: 'baz'}); | ||
foo.pushNode(bar); | ||
foo.pushNode(baz); | ||
console.log(bar.siblings.length) // 2 | ||
console.log(baz.siblings.length) // 2 | ||
``` | ||
### [.prev](index.js#L208) | ||
Get the previous node from the siblings array or `null`. | ||
* `returns` **{Object}** | ||
**Example** | ||
```js | ||
var foo = new Node({type: 'foo'}); | ||
var bar = new Node({type: 'bar'}); | ||
var baz = new Node({type: 'baz'}); | ||
foo.pushNode(bar); | ||
foo.pushNode(baz); | ||
console.log(baz.prev.type) // 'bar' | ||
``` | ||
### [.next](index.js#L232) | ||
Get the siblings array, or `null` if it doesn't exist. | ||
* `returns` **{Object}** | ||
**Example** | ||
```js | ||
var foo = new Node({type: 'foo'}); | ||
var bar = new Node({type: 'bar'}); | ||
var baz = new Node({type: 'baz'}); | ||
foo.pushNode(bar); | ||
foo.pushNode(baz); | ||
console.log(bar.siblings.length) // 2 | ||
console.log(baz.siblings.length) // 2 | ||
``` | ||
### [.index](index.js#L260) | ||
Get the node's current index from `node.parent.nodes`. This should always be correct, even when the parent adds nodes. | ||
* `returns` **{Number}** | ||
**Example** | ||
```js | ||
var foo = new Node({type: 'foo'}); | ||
var bar = new Node({type: 'bar'}); | ||
var baz = new Node({type: 'baz'}); | ||
var qux = new Node({type: 'qux'}); | ||
foo.pushNode(bar); | ||
foo.pushNode(baz); | ||
foo.unshiftNode(qux); | ||
console.log(bar.index) // 1 | ||
console.log(baz.index) // 2 | ||
console.log(qux.index) // 0 | ||
``` | ||
### [.first](index.js#L288) | ||
Get the first node from `node.nodes`. | ||
* `returns` **{Object}**: The first node, or undefiend | ||
**Example** | ||
```js | ||
var foo = new Node({type: 'foo'}); | ||
var bar = new Node({type: 'bar'}); | ||
var baz = new Node({type: 'baz'}); | ||
var qux = new Node({type: 'qux'}); | ||
foo.pushNode(bar); | ||
foo.pushNode(baz); | ||
foo.pushNode(qux); | ||
console.log(foo.first.type) // 'bar' | ||
``` | ||
### [.last](index.js#L311) | ||
Get the last node from `node.nodes`. | ||
* `returns` **{Object}**: The last node, or undefiend | ||
**Example** | ||
```js | ||
var foo = new Node({type: 'foo'}); | ||
var bar = new Node({type: 'bar'}); | ||
var baz = new Node({type: 'baz'}); | ||
var qux = new Node({type: 'qux'}); | ||
foo.pushNode(bar); | ||
foo.pushNode(baz); | ||
foo.pushNode(qux); | ||
console.log(foo.last.type) // 'qux' | ||
``` | ||
## About | ||
@@ -80,2 +348,2 @@ | ||
_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.4.1, on January 20, 2017._ | ||
_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.4.1, on January 21, 2017._ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
18307
289
0
345
3
1
+ Addedsnapdragon-util@^1.0.0
+ Addedis-buffer@1.1.6(transitive)
+ Addedkind-of@3.2.2(transitive)
+ Addedlazy-cache@2.0.2(transitive)
+ Addedset-getter@0.1.1(transitive)
+ Addedsnapdragon-node@1.0.6(transitive)
+ Addedsnapdragon-util@1.0.6(transitive)
+ Addedto-object-path@0.3.0(transitive)