Skip to content

Commit 7744d74

Browse files
committed
Implement sibling operators
1 parent 4e3d9ce commit 7744d74

File tree

3 files changed

+68
-13
lines changed

3 files changed

+68
-13
lines changed

lib/select.js

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,64 @@ select.ruleSet = function (selector, ast) {
1212
select.rule = function (selector, ast) {
1313
var result = [];
1414

15-
(function walk (node) {
15+
switch (selector.nestingOperator) {
16+
case null:
17+
case undefined:
18+
case '>':
19+
walk(ast);
20+
break;
21+
22+
case '+':
23+
if (ast.children && ast.children.length) {
24+
walk(ast.children[0], ast);
25+
}
26+
break;
27+
28+
case '~':
29+
(ast.children || []).forEach(function (node) {
30+
walk(node, ast);
31+
});
32+
break;
33+
34+
default:
35+
throw Error('Unexpected nesting operator: ' + selector.nestingOperator);
36+
}
37+
38+
return result;
39+
40+
function walk (node, parent) {
1641
if (node.type == selector.tagName) {
1742
if (!selector.rule) {
18-
return result.push(node);
19-
}
20-
if (!node.children) {
21-
return;
43+
return append(result, [node]);
2244
}
2345

24-
node.children.forEach(function (childNode) {
25-
[].push.apply(result, select.rule(selector.rule, childNode));
26-
});
46+
if (!selector.rule.nestingOperator || selector.rule.nestingOperator == '>') {
47+
if (!node.children) return;
48+
node.children.forEach(function (childNode) {
49+
[].push.apply(result, select.rule(selector.rule, childNode));
50+
});
51+
}
52+
else {
53+
if (!parent) return;
54+
append(result, select.rule(selector.rule, {
55+
children: parent.children.slice(parent.children.indexOf(node) + 1)
56+
}));
57+
}
2758
}
2859

2960
if (!selector.nestingOperator && node.children) {
30-
node.children.forEach(walk);
61+
node.children.forEach(function (child) {
62+
walk(child, node);
63+
});
3164
}
32-
}(ast));
33-
34-
return result;
65+
}
3566
};
67+
68+
69+
function append (array, elements) {
70+
elements.forEach(function (el) {
71+
if (array.indexOf(el) < 0) {
72+
array.push(el);
73+
}
74+
});
75+
}

lib/selector.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ var Parser = require('css-selector-parser').CssSelectorParser;
55

66
module.exports = function SelectorParser () {
77
var parser = new Parser;
8-
parser.registerNestingOperators('>');
8+
parser.registerNestingOperators('>', '+', '~');
99
return parser.parse.bind(parser);
1010
};

test/test.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,18 @@ test('nesting', function (t) {
4848
]);
4949
t.end();
5050
});
51+
52+
53+
test('siblings', function (t) {
54+
t.deepEqual(select(ast, 'root ~ heading'), []);
55+
t.deepEqual(select(ast, 'heading ~ heading'), [
56+
path(ast, [1]),
57+
path(ast, [7]),
58+
path(ast, [12]),
59+
path(ast, [16])
60+
]);
61+
t.deepEqual(select(ast, 'heading + heading'), [
62+
path(ast, [1])
63+
]);
64+
t.end();
65+
});

0 commit comments

Comments
 (0)