Socket
Socket
Sign inDemoInstall

dom-iterator

Package Overview
Dependencies
Maintainers
1
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

dom-iterator - npm Package Compare versions

Comparing version 0.0.5 to 0.1.0

example.js

14

component.json

@@ -5,5 +5,11 @@ {

"description": "iterate through DOM nodes",
"version": "0.0.5",
"keywords": ["iterate", "dom"],
"dependencies": {},
"version": "0.1.0",
"keywords": [
"iterate",
"dom"
],
"dependencies": {
"component/xor": "0.0.2",
"component/props": "1.1.0"
},
"development": {

@@ -18,2 +24,2 @@ "component/domify": "*",

]
}
}
0.1.0 / 2014-02-07
==================
* tests passing in node
* added: it#select(expr) and it#reject(expr).
* BREAKING removed: it#filter(nodeType)
* added: iterator#revisit(revisit)
* BREAKING traverses closing tags by default
* added: root node
* added: it#closing(), it#opening(), it#atOpening(), it#atClosing()
* BREAKING removed: it#watch(expr, fn)
0.0.5 / 2014-02-05

@@ -3,0 +15,0 @@ ==================

@@ -5,3 +5,4 @@ /**

var slice = Array.prototype.slice;
var xor = require('xor');
var props = require('props');

@@ -18,2 +19,3 @@ /**

* @param {Node} node
* @param {Node} root
* @return {iterator} self

@@ -23,15 +25,20 @@ * @api public

function iterator(node) {
if (!(this instanceof iterator)) return new iterator(node);
function iterator(node, root) {
if (!(this instanceof iterator)) return new iterator(node, root);
this.node = this.start = this.peaked = node;
this.exprs = [];
this.types = false;
this.visitClosing = false;
this.climbing = false;
this.root = root;
this.closingTag = false;
this._revisit = true;
this._selects = [];
this._rejects = [];
if (this.higher(node)) {
throw new Error('root must be a parent or ancestor to node');
}
}
/**
* Filter on the type
* Reset the iterator
*
* @param {Number, ...} filters
* @param {Node} node (optional)
* @return {iterator} self

@@ -41,10 +48,13 @@ * @api public

iterator.prototype.filter = function() {
var args = slice.call(arguments);
var types = this.types = this.types || {};
iterator.prototype.reset = function(node) {
this.node = node || this.start;
return this;
};
for (var i = 0, len = args.length; i < len; i++) {
types[args[i]] = true;
}
/**
* Revisit element nodes. Defaults to `true`
*/
iterator.prototype.revisit = function(revisit) {
this._revisit = undefined == revisit ? true : revisit;
return this;

@@ -54,11 +64,7 @@ };

/**
* Reset the iterator
*
* @param {Node} node (optional)
* @return {iterator} self
* @api public
* Jump to the opening tag
*/
iterator.prototype.reset = function(node) {
this.node = node || this.start;
iterator.prototype.opening = function() {
if (1 == this.node.nodeType) this.closingTag = false;
return this;

@@ -68,65 +74,47 @@ };

/**
* Next node
*
* @param {Number} type
* @return {Node|null}
* @api public
* Jump to the closing tag
*/
iterator.prototype.next = traverse('nextSibling', 'firstChild');
iterator.prototype.atOpening = function() {
return !this.closingTag;
};
/**
* Previous node
*
* @param {Number} type
* @return {Node|null}
* @api public
* Jump to the closing tag
*/
iterator.prototype.previous =
iterator.prototype.prev = traverse('previousSibling', 'lastChild');
iterator.prototype.closing = function() {
if (1 == this.node.nodeType) this.closingTag = true;
return this;
};
/**
* Peak in either direction
* `n` nodes. Peak backwards
* using negative numbers.
*
* @param {Number} n (optional)
* @return {Node|null}
* @api public
* Jump to the closing tag
*/
iterator.prototype.peak = function(n) {
n = undefined == n ? 1 : n;
var node;
iterator.prototype.atClosing = function() {
return this.closingTag;
};
if (!n) return this.node;
else if (n > 0) while(n--) node = this.next(0, true);
else while(n++) node = this.prev(0, true);
this.peaked = node;
return node;
}
/**
* Visit closing tags
* Next node
*
* @param {Number} type
* @return {Node|null}
* @api public
*/
iterator.prototype.closing = function(close) {
this.visitClosing = close;
return this;
}
iterator.prototype.next = traverse('nextSibling', 'firstChild');
/**
* Add a plugin
* Previous node
*
* @param {Function} fn
* @return {iterator}
* @param {Number} type
* @return {Node|null}
* @api public
*/
iterator.prototype.use = function(fn) {
fn(this);
return this;
}
iterator.prototype.previous =
iterator.prototype.prev = traverse('previousSibling', 'lastChild');

@@ -143,27 +131,35 @@ /**

function traverse(dir, child) {
return function walk(i, peak) {
var next = dir == 'nextSibling';
return function walk(expr, peak) {
expr = this.compile(expr);
var node = (peak) ? this.peaked : this.peaked = this.node;
var closing = this.visitClosing;
var start = this.start;
var types = this.types;
var exprs = this.exprs;
var climbing = (closing) ? this.climbing : false;
var closing = this.closingTag;
var revisit = this._revisit;
while (node) {
if (!climbing && node[child]) {
if (xor(next, closing) && node[child]) {
// element with children: <em>...</em>
node = node[child];
closing = !next;
} else if (1 == node.nodeType && !node[child] && xor(next, closing)) {
// empty element tag: <em></em>
closing = next;
if (!revisit) continue;
} else if (node[dir]) {
// element has a neighbor: ...<em></em>...
node = node[dir];
climbing = false;
closing = !next;
} else {
// done with current layer, move up.
node = node.parentNode;
climbing = true;
if (!closing) continue;
closing = next;
if (!revisit) continue;
}
this.climbing = climbing;
if (!node || this.higher(node, this.root)) break;
if (!types || types[node.nodeType]) {
if (expr(node) && this.selects(node) && this.rejects(node)) {
if (peak) this.peaked = node;
else this.node = node;
this.closingTag = closing;
return node;

@@ -176,1 +172,143 @@ }

}
/**
* Select nodes that cause `expr(node)`
* to be truthy
*
* @param {Number|String|Function} expr
* @return {iterator} self
* @api public
*/
iterator.prototype.select = function(expr) {
expr = this.compile(expr);
this._selects.push(expr);
return this;
};
/**
* Run through the selects ORing each
*
* @return {Boolean}
* @api private
*/
iterator.prototype.selects = function(node) {
var exprs = this._selects;
var len = exprs.length;
if (!len) return true;
for (var i = 0; i < len; i++) {
if (exprs[i](node)) return true;
};
return false;
};
/**
* Select nodes that cause `expr(node)`
* to be falsy
*
* @param {Number|String|Function} expr
* @return {iterator} self
* @api public
*/
iterator.prototype.reject = function(expr) {
expr = this.compile(expr);
this._rejects.push(expr);
return this;
};
/**
* Run through the reject expressions ANDing each
*
* @return {Boolean}
* @api private
*/
iterator.prototype.rejects = function(node) {
var exprs = this._rejects;
var len = exprs.length;
if (!len) return true;
for (var i = 0; i < len; i++) {
if (exprs[i](node)) return false;
};
return true;
};
/**
* Check if node is higher
* than root.
*
* @param {Node} node
* @param {Node} root
* @return {Boolean}
* @api private
*/
iterator.prototype.higher = function(node) {
var root = this.root;
if (!root) return false;
node = node.parentNode;
while (node && node != root) node = node.parentNode;
return node != root;
};
/**
* Compile an expression
*
* @param {String|Function|Number} expr
* @return {Function}
*/
iterator.prototype.compile = function(expr) {
switch (typeof expr) {
case 'number':
return function(node) { return expr == node.nodeType; };
case 'string':
return new Function('node', 'return ' + props(expr, 'node.'));
case 'function':
return expr;
default:
return function() { return true; };
}
};
/**
* Peak in either direction
* `n` nodes. Peak backwards
* using negative numbers.
*
* @param {Number} n (optional)
* @return {Node|null}
* @api public
*/
iterator.prototype.peak = function(expr, n) {
if (arguments.length == 1) n = expr, expr = true;
n = undefined == n ? 1 : n;
var node;
if (!n) return this.node;
else if (n > 0) while(n--) node = this.next(expr, true);
else while(n++) node = this.prev(expr, true);
this.peaked = node;
return node;
};
/**
* Add a plugin
*
* @param {Function} fn
* @return {iterator}
* @api public
*/
iterator.prototype.use = function(fn) {
fn(this);
return this;
};
{
"name": "dom-iterator",
"version": "0.0.5",
"version": "0.1.0",
"description": "iterator for mini-html-parser",

@@ -10,6 +10,12 @@ "main": "index.js",

},
"dependencies": {
"xor": "component/xor#0.0.2",
"props": "component/props#1.0.3"
},
"devDependencies": {
"component-test": "~0.1.2"
"mini-html-parser": "0.0.3",
"mocha": "~1.17.1"
},
"scripts": {
"postinstall": "make npm",
"test": "make test"

@@ -32,2 +38,2 @@ },

"homepage": "https://github.com/MatthewMueller/dom-iterator"
}
}
# dom-iterator
Iterate over DOM nodes. A better [NodeIterator](https://developer.mozilla.org/en-US/docs/Web/API/NodeIterator). Travels in both directions.
Feature-rich, well-tested Iterator for traversing DOM nodes. A better version of [NodeIterator](https://developer.mozilla.org/en-US/docs/Web/API/NodeIterator). Travels in both directions.
Can be used in node.js with [mini-html-parser](http://github.com/matthewmueller/mini-html-parser).
## Installation

@@ -12,2 +14,6 @@

With node.js:
$ npm install dom-iterator
## Example

@@ -26,6 +32,12 @@

### `iterator(node)`
### `iterator(node, root)`
Initialize an iterator starting on the `node`.
Initialize an iterator starting on the `node`. Optionally you can
specify a `root` to limit your traversal to a particular subtree.
`root` must be either a parent or an ancestor of `node`.
```js
var it = iterator(el.firstChild, el)
```
### `iterator#next()`

@@ -40,2 +52,6 @@

Here's a look at how the DOM is traversed:
![next](https://i.cloudup.com/kl80e5axNP.png)
### `iterator#prev()`, `iterator#previous()`

@@ -50,29 +66,81 @@

### `iterator.filter(type)`
Here's a look at how the DOM is traversed:
Only select nodes of `type`. Pass additional arguments for each type.
![prev](https://i.cloudup.com/EkaCyvdwvF.png)
### `iterator.select(expr)`
iterate over nodes that pass the expression `expr`. The `expr` can be an
enum, number, string or function. If it's a number, the `nodeType` is compared.
This function can be chained where all expressions are OR-ed.
```js
// using numbers
it.filter(1, 2)
it.select(Node.ElementNode)
.select(8)
.select('nodeValue == "sloth"')
.select(fn)
```
// using enums
it.filter(Node.COMMENT_NODE, Node.TEXT_NODE)
This is basically saying, "select all element nodes or comment nodes
or nodes with the nodeValue "sloth" or nodes that pass the function `fn`".
### `iterator.reject(expr)`
iterate over nodes that do not pass the expression `expr`. The `expr` can be an
enum, number, string or function. If it's a number, the `nodeType` is compared.
This function can be chained where all expressions are AND-ed.
```js
it.reject(Node.ElementNode)
.reject(8)
.reject('nodeValue == "sloth"')
.reject(fn)
```
### `iterator.closing(visit)`
This is basically saying, "reject all element nodes and comment nodes
and nodes with the nodeValue sloth and nodes that pass the function `fn`".
Visit the elements as they close. Defaults to `false`
### `iterator.revisit(revisit)`
You can also skip over elements you already visited, by setting `revisit` to false. By default, `revisit` is set to `true`.
```js
var dom = domify('<em>hi</em>')
var it = it(dom).closing(true);
it.next() "EM"
it.next() "hi"
it.next() "EM"
it.revisit(false);
```
Here's how that would change the iterator:
**it.next():**
![next](https://i.cloudup.com/VX6BbZEuzf.png)
**it.prev()**
![prev](https://i.cloudup.com/NEKe6F4EUX.png)
### `iterator.opening()`
Jump to the opening tag of an element. This is the default.
```js
var dom = domify('<em>hi</em>');
var it = it(dom).opening()
it.next() // 'hi'
```
### `iterator.closing()`
Jump to the closing tag of an element
```js
var dom = domify('<em>hi</em>');
var it = it(dom).closing()
it.prev() // 'hi'
```
### `iterator.peak([n])`
Sometimes you want to peak on the following or previous node without actually visiting it. With `peak` you can peak forward or backwards `n` steps. If no `n` is given, peak forward 1 step. Peaking chains until you run `it.next()` or `it.prev()`.
Sometimes you want to peak on the following or previous node without actually visiting it. With `peak` you can peak forward or backwards `n` steps. If no `n` is given, peak forward 1 step.

@@ -92,11 +160,2 @@ Peaking forward:

Chaining:
```js
var node;
while (node = it.peak()) {
// ...
}
```
### `iterator.reset([newNode])`

@@ -103,0 +162,0 @@

@@ -5,6 +5,13 @@ /**

var iterator = require('dom-iterator');
var domify = require('domify');
var assert = require('assert');
try {
var iterator = require('dom-iterator');
var parse = require('domify');
} catch (e) {
var iterator = require('../');
var parse = function(str) { return require('mini-html-parser')(str).parse(); }
}
/**

@@ -15,98 +22,209 @@ * Tests

describe('iterator', function() {
var dom, i;
var dom, i, article;
beforeEach(function() {
dom = domify('<body>hi<article><em>whatever</em>omg<strong></strong></article>bye</body>');
dom = parse('<body>hi<article><em>whatever</em>omg<strong></strong></article>bye</body>');
article = dom.childNodes[1];
});
describe('elements', function() {
describe('(dom)', function() {
it('should iterate from the top', function() {
i = iterator(dom).filter(Node.ELEMENT_NODE);
verify(i, 'next', ['ARTICLE', 'EM', 'STRONG', null])
i.reset()
verify(i, 'prev', ['ARTICLE', 'STRONG', 'EM', null])
i = iterator(dom);
assert('<body>' == format(i));
assert('hi' == format(i.next(), i));
assert('<article>' == format(i.next(), i));
assert('<em>' == format(i.next(), i));
assert('whatever' == format(i.next(), i));
assert('</em>' == format(i.next(), i));
assert('omg' == format(i.next(), i));
assert('<strong>' == format(i.next(), i));
assert('</strong>' == format(i.next(), i));
assert('</article>' == format(i.next(), i));
assert('bye' == format(i.next(), i));
assert('</body>' == format(i.next(), i));
assert(null == i.next());
assert(null == i.next());
assert(null == i.next());
assert('</body>' == format(i))
assert('bye' == format(i.prev(), i))
assert('</article>' == format(i.prev(), i))
})
it('should iterate from the middle', function() {
i = iterator(dom.querySelector('article')).filter(Node.ELEMENT_NODE);
verify(i, 'next', ['EM', 'STRONG', null])
i.reset()
verify(i, 'prev', ['STRONG', 'EM', null])
})
it('should iterate from the middle (opening)', function() {
i = iterator(article)
it('should iterate from the bottom', function() {
i = iterator(dom.querySelector('em').firstChild).filter(Node.ELEMENT_NODE);
verify(i, 'next', ['STRONG', null])
i.reset()
verify(i, 'prev', [null])
})
});
assert('<article>' == format(i))
assert('hi' == format(i.prev(), i))
assert('<body>' == format(i.prev(), i))
assert(null == i.prev());
describe('text nodes', function() {
it('should iterate from the top', function() {
i = iterator(dom).filter(Node.TEXT_NODE);
verify(i, 'next', ['hi', 'whatever', 'omg', 'bye', null])
i.reset()
verify(i, 'prev', ['bye', 'omg', 'whatever', 'hi', null])
i.reset();
assert('<article>' == format(i))
assert('<em>' == format(i.next(), i));
assert('whatever' == format(i.next(), i));
assert('</em>' == format(i.next(), i));
assert('omg' == format(i.next(), i));
assert('<strong>' == format(i.next(), i));
assert('</strong>' == format(i.next(), i));
assert('</article>' == format(i.next(), i));
assert('bye' == format(i.next(), i));
assert('</body>' == format(i.next(), i));
assert(null == i.next());
})
it('should iterate from the middle', function() {
i = iterator(dom.querySelector('article')).filter(Node.TEXT_NODE);
verify(i, 'next', ['whatever', 'omg', 'bye', null])
i.reset()
verify(i, 'prev', ['omg', 'whatever', 'hi', null])
it('should iterate from the middle (closing)', function() {
i = iterator(article).closing();
assert('</article>' == format(i));
assert('bye' == format(i.next(), i));
assert('</body>' == format(i.next(), i));
assert(null == i.next());
i.reset();
assert('</article>' == format(i))
assert('</strong>' == format(i.prev(), i))
assert('<strong>' == format(i.prev(), i))
assert('omg' == format(i.prev(), i))
assert('</em>' == format(i.prev(), i))
assert('whatever' == format(i.prev(), i))
assert('<em>' == format(i.prev(), i))
assert('<article>' == format(i.prev(), i))
assert('hi' == format(i.prev(), i))
assert('<body>' == format(i.prev(), i))
assert(null == i.prev());
})
it('should iterate from the bottom', function() {
i = iterator(dom.querySelector('em').firstChild).filter(Node.TEXT_NODE);
verify(i, 'next', ['omg', 'bye', null])
i.reset()
verify(i, 'prev', ['hi', null])
i = iterator(dom).closing();
assert('</body>' == format(i));
assert('bye' == format(i.prev(), i))
assert('</article>' == format(i.prev(), i))
assert('</strong>' == format(i.prev(), i))
assert('<strong>' == format(i.prev(), i))
assert('omg' == format(i.prev(), i))
assert('</em>' == format(i.prev(), i))
assert('whatever' == format(i.prev(), i))
assert('<em>' == format(i.prev(), i))
assert('<article>' == format(i.prev(), i))
assert('hi' == format(i.prev(), i))
assert('<body>' == format(i.prev(), i))
assert(null == i.prev());
assert(null == i.prev());
assert(null == i.prev());
assert('<body>' == format(i))
assert('hi' == format(i.next(), i))
assert('<article>' == format(i.next(), i))
})
});
it('should work in both directions', function() {
dom = domify('hi <strong>jimbo</strong>')
i = iterator(dom).filter(Node.TEXT_NODE);
assert('hi ' == i.next().nodeValue);
assert('jimbo' == i.next().nodeValue);
describe('(dom, root)', function() {
it('should support roots to limit iterator (opening)', function() {
i = iterator(article.firstChild, article)
assert('<em>' == format(i))
assert(null == i.prev());
assert(null == i.prev());
assert('<em>' == format(i))
assert('whatever' == format(i.next(), i));
assert('</em>' == format(i.next(), i));
assert('omg' == format(i.next(), i));
assert('<strong>' == format(i.next(), i));
assert('</strong>' == format(i.next(), i));
assert(null == i.next());
assert('hi ' == i.prev().nodeValue);
assert(null == i.next());
assert('</strong>' == format(i));
})
it('should support roots to limit iterator (closing)', function() {
i = iterator(article.lastChild, article).closing();
assert('</strong>' == format(i))
assert(null == i.next());
assert(null == i.next());
assert('<strong>' == format(i.prev(), i))
assert('omg' == format(i.prev(), i))
assert('</em>' == format(i.prev(), i))
assert('whatever' == format(i.prev(), i))
assert('<em>' == format(i.prev(), i))
assert(null == i.prev());
assert(null == i.prev());
assert('<em>' == format(i))
})
});
describe('atOpening() & atClosing()', function() {
it('should accurately return atOpening() or atClosing()', function() {
i = iterator(dom);
assert(i.atOpening());
i.next() // hi
assert(i.atOpening());
i.next() // article
assert(i.atOpening());
i.next() // em
assert(i.atOpening());
i.next() // whatever
assert(i.atOpening());
i.next() // /em
assert(i.atClosing());
i.next() // omg
assert(i.atOpening());
i.next() // strong
assert(i.atOpening());
i.next() // /strong
assert(i.atClosing());
i.next() // /article
assert(i.atClosing());
i.next() // bye
assert(i.atOpening());
i.next() // /body
assert(i.atClosing());
i.next() // /body
assert(i.atClosing());
i.next() // /body
assert(i.atClosing());
})
})
describe('all nodes', function() {
it('should iterate from the top', function() {
i = iterator(dom);
verify(i, 'next', ['hi', 'ARTICLE', 'EM', 'whatever', 'omg', 'STRONG', 'bye', null]);
i.reset();
verify(i, 'prev', ['bye', 'ARTICLE', 'STRONG', 'omg', 'EM', 'whatever', 'hi', null]);
describe('revisit(false)', function() {
it('from top: should ignore the element if you pass it again', function() {
i = iterator(dom).revisit(false);
assert('<body>' == format(i));
assert('hi' == format(i.next(), i));
assert('<article>' == format(i.next(), i));
assert('<em>' == format(i.next(), i));
assert('whatever' == format(i.next(), i));
assert('omg' == format(i.next(), i));
assert('<strong>' == format(i.next(), i));
assert('bye' == format(i.next(), i));
assert(null == i.next());
assert(null == i.next());
assert(null == i.next());
assert('bye' == format(i));
assert('</article>' == format(i.prev(), i));
assert('</strong>' == format(i.prev(), i));
assert('omg' == format(i.prev(), i));
});
it('should iterate from middle', function() {
i = iterator(dom.querySelector('article'));
verify(i, 'next', ['EM', 'whatever', 'omg', 'STRONG', 'bye', null]);
i.reset();
verify(i, 'prev', ['STRONG', 'omg', 'EM', 'whatever', 'hi', null]);
it('from bottom: should ignore the element if you pass it again', function() {
i = iterator(dom).revisit(false).closing();
assert('</body>' == format(i));
assert('bye' == format(i.prev(), i))
assert('</article>' == format(i.prev(), i))
assert('</strong>' == format(i.prev(), i))
assert('omg' == format(i.prev(), i))
assert('</em>' == format(i.prev(), i))
assert('whatever' == format(i.prev(), i))
assert('hi' == format(i.prev(), i))
assert(null == i.prev());
assert(null == i.prev());
assert(null == i.prev());
assert('hi' == format(i));
assert('<article>' == format(i.next(), i));
assert('<em>' == format(i.next(), i));
assert('whatever' == format(i.next(), i));
});
});
it('should iterate from bottom', function() {
i = iterator(dom.querySelector('em').firstChild);
verify(i, 'next', ['omg', 'STRONG', 'bye', null])
i.reset();
verify(i, 'prev', ['hi', null]);
})
})
describe('reset', function() {
it('should allow you to pass a new node', function() {
i = iterator(dom.querySelector('em').firstChild);
verify(i, 'next', ['omg', 'STRONG', 'bye', null])
i.reset(dom);
verify(i, 'next', ['hi', 'ARTICLE', 'EM', 'whatever', 'omg', 'STRONG', 'bye', null]);
})
})
describe('peak', function() {

@@ -117,3 +235,3 @@

assert('hi' == i.peak().nodeValue);
assert('BODY' == i.node.tagName);
assert('BODY' == i.node.nodeName);
assert('hi' == i.next().nodeValue)

@@ -123,6 +241,6 @@ })

it('should allow you to peak behind', function() {
i = iterator(dom.querySelector('article'));
assert('STRONG' == i.peak(-1).tagName);
assert('ARTICLE' == i.node.tagName);
assert('STRONG' == i.prev().tagName)
i = iterator(article).closing();
assert('STRONG' == i.peak(-1).nodeName);
assert('ARTICLE' == i.node.nodeName);
assert('STRONG' == i.prev().nodeName)
})

@@ -132,4 +250,4 @@

i = iterator(dom);
assert('EM' == i.peak(3).tagName);
assert('BODY' == i.node.tagName);
assert('EM' == i.peak(3).nodeName);
assert('BODY' == i.node.nodeName);
assert('hi' == i.next().nodeValue)

@@ -139,37 +257,134 @@ })

it('should allow you to peak behind multiple nodes', function() {
i = iterator(dom.querySelector('article'));
assert('EM' == i.peak(-3).tagName);
assert('ARTICLE' == i.node.tagName);
assert('STRONG' == i.prev().tagName)
i = iterator(article).closing();
assert('omg' == i.peak(-3).nodeValue);
assert('ARTICLE' == i.node.nodeName);
assert('STRONG' == i.prev().nodeName)
})
})
it('should support chaining, saving the peak offset', function() {
describe('it.{next,prev}(expr)', function() {
it('should work with numbers', function() {
i = iterator(dom);
assert('hi' == i.peak().nodeValue)
assert('ARTICLE' == i.peak().tagName)
assert('BODY' == i.node.tagName);
assert('hi' == i.next().nodeValue)
assert('hi' == i.peak().nodeValue)
assert('hi' == format(i.next(3), i));
assert('<article>' == format(i.next(1), i));
assert('<em>' == format(i.next(1), i));
assert('whatever' == format(i.next(3), i));
assert('</em>' == format(i.next(1), i));
assert('<strong>' == format(i.next(1), i));
assert('</strong>' == format(i.next(1), i));
assert('omg' == format(i.prev(3), i));
assert('whatever' == format(i.prev(3), i));
assert('hi' == format(i.prev(3), i));
});
it('should work with strings', function() {
i = iterator(dom);
assert('omg' == i.next('nodeValue == "omg"').nodeValue);
assert('bye' == i.next('nodeType == 3 && nodeValue == "bye"').nodeValue);
assert('omg' == i.prev('nodeType == 3 && nodeValue == "omg"').nodeValue);
assert('BODY' == i.prev('nodeType == 1 && nodeName == "BODY"').nodeName);
assert(null == i.prev('nodeType == 1 && nodeName == "BODY"'));
assert('<body>' == format(i))
})
it('should work with functions', function() {
i = iterator(dom);
assert('omg' == i.next(function(node) { return node.nodeValue == 'omg'}).nodeValue);
assert('BODY' == i.prev(function(node) { return node.nodeName == 'BODY'}).nodeName);
})
})
describe('closing(true)', function() {
it('should visit closing', function() {
i = iterator(dom).closing(true);
verify(i, 'next', ['hi', 'ARTICLE', 'EM', 'whatever', 'EM', 'omg', 'STRONG', 'ARTICLE', 'bye', 'BODY', null])
i.reset();
verify(i, 'prev', [null])
});
describe('it.select(expr)', function() {
it('should work with numbers', function() {
i = iterator(dom)
.select(3)
.select(8);
assert('<body>' == format(i));
assert('hi' == format(i.next(), i))
assert('whatever' == format(i.next(), i))
assert('omg' == format(i.next(), i))
assert('bye' == format(i.next(), i))
assert(null == i.next());
assert('bye' == format(i));
assert('omg' == format(i.prev(), i))
assert('whatever' == format(i.prev(), i))
assert('hi' == format(i.prev(), i))
assert(null == i.prev());
assert('hi' == format(i))
})
it('should work with strings', function() {
i = iterator(dom)
.select('nodeValue == "omg"')
.select('nodeName == "ARTICLE"');
assert('<body>' == format(i));
assert('<article>' == format(i.next(), i));
assert('omg' == format(i.next(), i));
assert('</article>' == format(i.next(), i));
assert(null == i.next());
assert('</article>' == format(i));
})
});
describe('it.reject(expr)', function() {
it('should work with numbers', function() {
i = iterator(dom)
.reject(1)
.reject(8);
assert('<body>' == format(i));
assert('hi' == format(i.next(), i))
assert('whatever' == format(i.next(), i))
assert('omg' == format(i.next(), i))
assert('bye' == format(i.next(), i))
assert(null == i.next());
assert('bye' == format(i));
assert('omg' == format(i.prev(), i))
assert('whatever' == format(i.prev(), i))
assert('hi' == format(i.prev(), i))
assert(null == i.prev());
assert('hi' == format(i))
})
function verify(it, dir, expected) {
expected.forEach(function(expect) {
var n = it[dir]();
if (null == expect) return assert(null == n, 'it.' + dir + '() should be null');
assert(n, 'it.' + dir + '() should not be null. Expected: ' + expect)
var prop = n.nodeType == 1 ? 'nodeName' : 'nodeValue';
assert(expect == n[prop], 'expected ' + expect + ' got ' + n[prop]);
});
it('should work with strings', function() {
i = iterator(dom)
.reject('nodeValue == "omg"')
.reject('nodeName == "ARTICLE"');
assert('<body>' == format(i));
assert('hi' == format(i.next(), i));
assert('<em>' == format(i.next(), i));
assert('whatever' == format(i.next(), i));
assert('</em>' == format(i.next(), i));
assert('<strong>' == format(i.next(), i));
assert('</strong>' == format(i.next(), i));
assert('bye' == format(i.next(), i));
assert('</body>' == format(i.next(), i));
assert(null == i.next());
assert(null == i.next());
assert(null == i.next());
assert('</body>' == format(i))
assert('bye' == format(i.prev(), i))
assert('</strong>' == format(i.prev(), i))
})
});
function format(node, it) {
if (arguments.length == 1) it = node, node = it.node;
var name = node.nodeName.toLowerCase();
var type = node.nodeType;
var closing = it.atClosing();
var out = null;
if (3 == type) {
out = node.nodeValue;
} else if (1 == type) {
out = it.atClosing() ? '</' + name + '>' : '<' + name + '>';
}
return out;
}
})

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc