html-select
Advanced tools
Comparing version 1.0.0 to 1.1.0
55
index.js
var inherits = require('inherits'); | ||
var Writable = require('readable-stream').Writable; | ||
var parseTag = require('./lib/tag.js'); | ||
var EventEmitter = require('events').EventEmitter; | ||
var copy = require('shallow-copy'); | ||
var parseTag = require('./lib/parse_tag.js'); | ||
var parseSelector = require('./lib/selector.js'); | ||
var match = require('./lib/match.js'); | ||
var copy = require('shallow-copy'); | ||
var Tag = require('./lib/tag.js'); | ||
@@ -30,2 +33,3 @@ var special = (function () { | ||
this.matches = []; | ||
this.streams = []; | ||
} | ||
@@ -44,3 +48,13 @@ | ||
} | ||
else if (type === 'close') { | ||
for (var i = 0; i < this.streams.length; i++) { | ||
var s = this.streams[i]; | ||
var closing = type === 'close' | ||
&& s._row.index === this.stack.length - 1 | ||
; | ||
s._writes ++; | ||
if ((s._writes > 1 || s._outer) && (s._outer || !closing)) { | ||
s.push(buf); | ||
} | ||
} | ||
if (type === 'close') { | ||
var tag = parseTag(buf); | ||
@@ -53,3 +67,9 @@ this._pop(); | ||
Selector.prototype._push = function (tag) { | ||
var row = { tag: tag, matches: [] }; | ||
var self = this; | ||
var row = { | ||
tag: tag, | ||
matches: [], | ||
streams: [], | ||
index: this.stack.length | ||
}; | ||
@@ -62,3 +82,9 @@ for (var i = 0; i < this.matches.length; i++) { | ||
m.index --; | ||
this.cb(fromTag(tag)); | ||
var t = this._fromTag(tag); | ||
t.on('stream', function (s) { | ||
s._row = row; | ||
row.streams.push(s); | ||
self.streams.push(s); | ||
}); | ||
this.cb(t); | ||
} | ||
@@ -76,3 +102,9 @@ else { | ||
if (this.selector.length === 1) { | ||
this.cb(fromTag(tag)); | ||
var t = this._fromTag(tag); | ||
t.on('stream', function (s) { | ||
s._row = row; | ||
row.streams.push(s); | ||
self.streams.push(s); | ||
}); | ||
this.cb(t); | ||
} | ||
@@ -97,6 +129,11 @@ else { | ||
} | ||
for (var i = 0; i < s.streams.length; i++) { | ||
s.streams[i].push(null); | ||
var ix = this.streams.indexOf(s.streams[i]); | ||
if (ix >= 0) this.streams.splice(ix, 1); | ||
} | ||
}; | ||
function fromTag (tag) { | ||
return { name: tag.name, attributes: tag.getAttributes() }; | ||
} | ||
Selector.prototype._fromTag = function (tag) { | ||
return new Tag(tag); | ||
}; |
@@ -1,46 +0,21 @@ | ||
module.exports = function (buf) { | ||
var closing = buf[1] === '/'.charCodeAt(0); | ||
var start = closing ? 2 : 1; | ||
var name; | ||
for (var i = start; i < buf.length; i++) { | ||
var c = String.fromCharCode(buf[i]); | ||
if (/[\s>]/.test(c)) { | ||
name = buf.slice(start, i).toString('utf8'); | ||
break; | ||
} | ||
} | ||
var attr; | ||
return { | ||
name: name, | ||
getAttributes: function () { | ||
if (attr) return attr; | ||
attr = parse(buf, i) | ||
return attr; | ||
} | ||
}; | ||
var inherits = require('inherits'); | ||
var Readable = require('readable-stream').Readable; | ||
var EventEmitter = require('events').EventEmitter; | ||
module.exports = Tag; | ||
inherits(Tag, EventEmitter); | ||
function Tag (tag) { | ||
this.name = tag.name; | ||
this.attributes = tag.getAttributes(); | ||
} | ||
function parse (buf, i) { | ||
var attr = {}; | ||
var s = buf.slice(i, buf.length-1).toString('utf8'); | ||
var parts = s.match(/[^\s=]+\s*=\s*("[^"]+"|'[^']+'|\S+)|[^\s=]+/g) || []; | ||
var key, value; | ||
for (var j = 0; j < parts.length; j++) { | ||
var kv = parts[j].split('='); | ||
key = kv[0]; | ||
if (kv.length > 1) { | ||
value = kv.slice(1).join('='); | ||
if (/^"/.test(value)) { | ||
value = value.replace(/^"/, '').replace(/"$/, ''); | ||
} | ||
else if (/^'/.test(value)) { | ||
value = value.replace(/^'/, '').replace(/'$/, ''); | ||
} | ||
} | ||
else value = true; | ||
attr[key] = value; | ||
} | ||
return attr; | ||
} | ||
Tag.prototype.createReadStream = function (opts) { | ||
var r = new Readable; | ||
if (!opts) opts = {}; | ||
r._writes = 0; | ||
r._outer = Boolean(opts.outer); | ||
r._read = function () {}; | ||
this.emit('stream', r); | ||
return r; | ||
}; |
{ | ||
"name": "html-select", | ||
"version": "1.0.0", | ||
"version": "1.1.0", | ||
"description": "match a tokenized html stream with css selectors", | ||
@@ -18,3 +18,4 @@ "main": "index.js", | ||
"tape": "~2.12.1", | ||
"html-tokenize": "~1.0.0" | ||
"html-tokenize": "~1.0.0", | ||
"concat-stream": "^1.4.5" | ||
}, | ||
@@ -21,0 +22,0 @@ "scripts": { |
@@ -5,5 +5,6 @@ var select = require('../'); | ||
test('quoted attribute', function (t) { | ||
t.plan(1); | ||
t.plan(2); | ||
var s = select('input[type="text"]', function (e) { | ||
t.deepEqual(e, { name: 'input', attributes: { type: 'text' } }); | ||
t.equal(e.name, 'input'); | ||
t.deepEqual(e.attributes, { type: 'text' }); | ||
}); | ||
@@ -20,5 +21,6 @@ s.write([ 'open', '<html>' ]); | ||
test('bare attribute', function (t) { | ||
t.plan(1); | ||
t.plan(2); | ||
var s = select('input[type=text]', function (e) { | ||
t.deepEqual(e, { name: 'input', attributes: { type: 'text' } }); | ||
t.equal(e.name, 'input'); | ||
t.deepEqual(e.attributes, { type: 'text' }); | ||
}); | ||
@@ -25,0 +27,0 @@ s.write([ 'open', '<html>' ]); |
@@ -7,7 +7,8 @@ var select = require('../'); | ||
test('page .content', function (t) { | ||
t.plan(1); | ||
t.plan(2); | ||
fs.createReadStream(__dirname + '/page/index.html') | ||
.pipe(tokenize()) | ||
.pipe(select('.content', function (e) { | ||
t.deepEqual(e, { name: 'div', attributes: { class: 'content' } }); | ||
t.equal(e.name, 'div'); | ||
t.deepEqual(e.attributes, { class: 'content' }); | ||
})) | ||
@@ -17,8 +18,25 @@ ; | ||
test('page *', function (t) { | ||
t.plan(4); | ||
var expected = [ | ||
{ name: 'span', attributes: { class: 'greeting' } }, | ||
{ name: 'span', attributes: { class: 'name' } } | ||
]; | ||
fs.createReadStream(__dirname + '/page/index.html') | ||
.pipe(tokenize()) | ||
.pipe(select('.content *', function (e) { | ||
var x = expected.shift(); | ||
t.equal(e.name, x.name); | ||
t.deepEqual(e.attributes, x.attributes); | ||
})) | ||
; | ||
}); | ||
test('page div.content', function (t) { | ||
t.plan(1); | ||
t.plan(2); | ||
fs.createReadStream(__dirname + '/page/index.html') | ||
.pipe(tokenize()) | ||
.pipe(select('div.content', function (e) { | ||
t.deepEqual(e, { name: 'div', attributes: { class: 'content' } }); | ||
t.equal(e.name, 'div'); | ||
t.deepEqual(e.attributes, { class: 'content' }); | ||
})) | ||
@@ -29,3 +47,3 @@ ; | ||
test('page .name', function (t) { | ||
t.plan(2); | ||
t.plan(4); | ||
var expected = [ | ||
@@ -38,3 +56,5 @@ { name: 'h1', attributes: { class: 'name' } }, | ||
.pipe(select('.name', function (e) { | ||
t.deepEqual(e, expected.shift()); | ||
var x = expected.shift(); | ||
t.equal(e.name, x.name); | ||
t.deepEqual(e.attributes, x.attributes); | ||
})) | ||
@@ -46,7 +66,8 @@ ; | ||
test('page span.greeting', function (t) { | ||
t.plan(1); | ||
t.plan(2); | ||
fs.createReadStream(__dirname + '/page/index.html') | ||
.pipe(tokenize()) | ||
.pipe(select('span.greeting', function (e) { | ||
t.deepEqual(e, { name: 'span', attributes: { class: 'greeting' } }); | ||
t.equal(e.name, 'span'); | ||
t.deepEqual(e.attributes, { class: 'greeting' }); | ||
})) | ||
@@ -57,3 +78,3 @@ ; | ||
test('page .content span', function (t) { | ||
t.plan(2); | ||
t.plan(4); | ||
@@ -67,5 +88,7 @@ var expected = [ | ||
.pipe(select('.content span', function (e) { | ||
t.deepEqual(e, expected.shift()); | ||
var x = expected.shift(); | ||
t.equal(e.name, x.name); | ||
t.deepEqual(e.attributes, x.attributes); | ||
})) | ||
; | ||
}); |
Sorry, the diff of this file is not supported yet
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
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
24444
20
604
156
3
5