From 31f9955e22ff63ea0372316041fc021f8f8f77c1 Mon Sep 17 00:00:00 2001 From: Chris Dickinson Date: Mon, 15 Jul 2013 11:10:50 -0700 Subject: [PATCH] add support for commas --- index.js | 43 +++++++++++++++++++++++++++++++------------ test/index.js | 4 ++++ tokenizer.js | 9 +++++++++ 3 files changed, 44 insertions(+), 12 deletions(-) diff --git a/index.js b/index.js index d16204d..bec6a3b 100644 --- a/index.js +++ b/index.js @@ -25,9 +25,11 @@ function opt_okay(opts, key) { function parse(selector, options) { var stream = tokenizer() - , bits = [] + , selectors = [[]] , traversal - , length + , bits + + bits = selectors[0] traversal = { '': any_parents @@ -40,9 +42,12 @@ function parse(selector, options) { .on('data', group) .end(selector) - length = bits.length - function group(token) { + if(token.type === 'comma') { + selectors.unshift(bits = []) + return + } + if(token.type === 'op' || token.type === 'any-child') { bits.unshift(traversal[token.data]) bits.unshift(check()) @@ -58,19 +63,33 @@ function parse(selector, options) { } return function(node) { - var current = entry + var current + , length + , orig + + orig = node - for(var i = 0; i < length; i += 2) { - node = current(node, bits[i]) + for(var i = 0, len = selectors.length; i < len; ++i) { + bits = selectors[i] + current = entry + length = bits.length + node = orig - if(!node) { - return false + for(var j = 0; j < length; j += 2) { + node = current(node, bits[j]) + + if(!node) { + break + } + + current = bits[j + 1] } - current = bits[i + 1] + if(j >= length) { + return true + } } - - return true + return false } function check() { diff --git a/test/index.js b/test/index.js index 9b60981..9ef4ab6 100644 --- a/test/index.js +++ b/test/index.js @@ -48,8 +48,12 @@ function test_select_multiple() { parent.parent = root assert.ok(language('#root-id #one-id')(data)) + assert.ok(language('#nope,#root-id #one-id')(data)) + assert.ok(!language('#nope, #nada')(data)) assert.ok(!language('#root-id > #one-id')(data)) assert.ok(language('#root-id > #parent-id > #one-id')(data)) + assert.ok(language('#parent-id > #one-id,\n#root-id > #parent-id > #one-id')(data)) + assert.ok(language('#ok,\n #parent-id > #one-id,\n#root-id > #parent-id > #one-id')(data)) assert.ok(language('.one-class + .two-class')(data2)) assert.ok(!language('.one-class + #one-id')(data)) assert.ok(language('one-tag ~ #three-id')(data3)) diff --git a/tokenizer.js b/tokenizer.js index e224701..50f7bb4 100644 --- a/tokenizer.js +++ b/tokenizer.js @@ -12,6 +12,7 @@ var PSEUDOSTART = 'pseudo-start' , READY = '(ready)' , OPERATION = 'op' , CLASS = 'class' + , COMMA = 'comma' , ATTR = 'attr' , TAG = 'tag' , STAR = '*' @@ -73,6 +74,7 @@ function tokenize() { case ':' === c: state = PSEUDOCLASS; break case '[' === c: state = ATTR_START; break case '*' === c: star(); break + case ',' === c: comma(); break case /[>\+~]/.test(c): state = OPERATION; break case /\s/.test(c): state = ANY_CHILD; break case /[\w\d\-_]/.test(c): state = TAG; --idx; break @@ -86,6 +88,13 @@ function tokenize() { state = READY } + function comma() { + state = COMMA + gathered = [','] + stream.queue(token()) + state = READY + } + function state_op() { if(/[>\+~]/.test(c)) { return gathered.push(c)