Skip to content

Commit c7e14fb

Browse files
committed
Add attribute equality selectors
1 parent cb3ed67 commit c7e14fb

File tree

3 files changed

+39
-3
lines changed

3 files changed

+39
-3
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ select(ast, 'paragraph emphasis > text')
3131
- [x] Universal selector: `*`
3232
- [ ] Attribute selectors: `text[value*="substr"]`
3333
- [x] Existence: `[value]`
34-
- [ ] Equality: `[value="foo"]`
34+
- [x] Equality: `[value="foo"]`
3535
- [ ] Begins with: `[value^="prefix"]`
3636
- [ ] Containment: `[value*="substr"]`
3737
- [ ] Ends with: `[value$="suffix"]`

lib/select.js

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ select.rule = function (selector, ast) {
4040
break;
4141

4242
default:
43-
throw Error('Unexpected nesting operator: ' + selector.nestingOperator);
43+
throw Error('Undefined nesting operator: ' + selector.nestingOperator);
4444
}
4545

4646
return result;
@@ -85,7 +85,30 @@ function matches (rule, node) {
8585

8686
// Match attributes.
8787
return (rule.attrs || []).every(function (attr) {
88-
return attr.name in node;
88+
switch (attr.operator) {
89+
case undefined:
90+
return attr.name in node;
91+
92+
case '=':
93+
// First, check for special values.
94+
switch (attr.value) {
95+
case 'null':
96+
if (attr.name in node && node[attr.name] == null) return true;
97+
break;
98+
99+
case 'true':
100+
if (node[attr.name] === true) return true;
101+
break;
102+
103+
case 'false':
104+
if (node[attr.name] === false) return true;
105+
break;
106+
}
107+
return node[attr.name] == attr.value;
108+
109+
default:
110+
throw Error('Undefined attribute operator: ' + attr.operator);
111+
}
89112
});
90113
}
91114

test/test.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,20 @@ test('universal selector', function (t) {
102102

103103

104104
test('attribute selectors', function (t) {
105+
t.comment('existence');
105106
t.deepEqual(select(ast, '[depth]'), select(ast, 'heading'));
106107
t.deepEqual(select(ast, '[start][ordered]'), select(ast, 'list'));
108+
109+
t.comment('equality');
110+
t.deepEqual(select(ast, 'heading[depth=1], [depth=3]'), [
111+
path(ast, [0]),
112+
path(ast, [7])
113+
]);
114+
t.deepEqual(select(ast, 'paragraph [type="text"]'),
115+
select(ast, 'paragraph text'));
116+
t.deepEqual(select(ast, '[start=null]'), select(ast, 'list').slice(0, 3));
117+
t.deepEqual(select(ast, '[ordered=true]'), [ast.children[6]]);
118+
t.deepEqual(select(ast, 'list[loose=false]'), select(ast, 'list'));
119+
107120
t.end();
108121
});

0 commit comments

Comments
 (0)