Skip to content

Commit 22df6d4

Browse files
committed
Rewrite library
1 parent 4c1c17e commit 22df6d4

26 files changed

+2872
-1124
lines changed

index.js

Lines changed: 12 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,20 @@
11
'use strict'
22

3-
var debug = require('debug')('unist-util-select')
4-
var parseSelector = require('./lib/selector')
5-
var matchSelector = require('./lib/select')
3+
exports.matches = matches
4+
exports.selectAll = selectAll
5+
exports.select = select
66

7-
module.exports = select
7+
var any = require('./lib/any')
8+
var parse = require('./lib/parse')
89

9-
select.one = selectOne
10-
11-
function select(ast, selector) {
12-
if (arguments.length === 1) {
13-
return select.bind(this, ast)
14-
}
15-
16-
debug('Selector: %j', selector)
17-
selector = parseSelector(selector)
18-
debug(
19-
'AST: %s',
20-
JSON.stringify(selector, null, 2).replace(/(^|\n)/g, '\n ')
21-
)
22-
return selector ? matchSelector[selector.type](selector, ast) : []
10+
function matches(selector, node) {
11+
return Boolean(any(parse(selector), node, {one: true, shallow: true})[0])
2312
}
2413

25-
function selectOne(ast, selector) {
26-
if (arguments.length === 1) {
27-
return selectOne.bind(this, ast)
28-
}
29-
30-
var nodes = select(ast, selector)
31-
32-
if (nodes.length === 0) {
33-
throw new Error('Node not found by ' + JSON.stringify(selector))
34-
}
35-
36-
if (nodes.length > 1) {
37-
throw new Error(
38-
'Node matched by ' + JSON.stringify(selector) + ' is not unique'
39-
)
40-
}
14+
function select(selector, node) {
15+
return any(parse(selector), node, {one: true})[0] || null
16+
}
4117

42-
return nodes[0]
18+
function selectAll(selector, node) {
19+
return any(parse(selector), node, {})
4320
}

lib/any.js

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
'use strict'
2+
3+
module.exports = match
4+
5+
var zwitch = require('zwitch')
6+
var needsIndex = require('./pseudo').needsIndex
7+
var test = require('./test')
8+
var nest = require('./nest')
9+
10+
var type = zwitch('type')
11+
var handlers = type.handlers
12+
13+
type.unknown = unknownType
14+
type.invalid = invalidType
15+
handlers.selectors = selectors
16+
handlers.ruleSet = ruleSet
17+
handlers.rule = rule
18+
19+
function match(query, node, state) {
20+
return query && node ? type(query, node, state) : []
21+
}
22+
23+
function selectors(query, node, state) {
24+
var collect = collector(state.one)
25+
var ruleSets = query.selectors
26+
var length = ruleSets.length
27+
var index = -1
28+
29+
while (++index < length) {
30+
collect(ruleSet(ruleSets[index], node, state))
31+
}
32+
33+
return collect.result
34+
}
35+
36+
function ruleSet(query, node, state) {
37+
return rule(query.rule, node, state)
38+
}
39+
40+
function rule(query, tree, state) {
41+
var collect = collector(state.one)
42+
var opts = {
43+
scopeNodes: tree.type === 'root' ? tree.children : [tree],
44+
iterator: match,
45+
one: state.one,
46+
shallow: state.shallow
47+
}
48+
49+
if (state.shallow && query.rule) {
50+
throw new Error('Expected selector without nesting')
51+
}
52+
53+
nest(query, tree, 0, null, configure(query, opts))
54+
55+
return collect.result
56+
57+
function match(query, node, index, parent, state) {
58+
if (test(query, node, index, parent, state)) {
59+
if (query.rule) {
60+
nest(query.rule, node, index, parent, configure(query.rule, state))
61+
} else {
62+
collect(node)
63+
state.found = true
64+
}
65+
}
66+
}
67+
68+
function configure(query, state) {
69+
var pseudos = query.pseudos
70+
var length = pseudos && pseudos.length
71+
var index = -1
72+
73+
while (++index < length) {
74+
if (needsIndex.indexOf(pseudos[index].name) !== -1) {
75+
state.index = true
76+
break
77+
}
78+
}
79+
80+
return state
81+
}
82+
}
83+
84+
/* istanbul ignore next - Shouldn’t be invoked, all data is handled. */
85+
function unknownType(query) {
86+
throw new Error('Unknown type `' + query.type + '`')
87+
}
88+
89+
/* istanbul ignore next - Shouldn’t be invoked, parser gives correct data. */
90+
function invalidType() {
91+
throw new Error('Invalid type')
92+
}
93+
94+
function collector(one) {
95+
var result = []
96+
var found
97+
98+
collect.result = result
99+
100+
return collect
101+
102+
/* Append nodes to array, filtering out duplicates. */
103+
function collect(source) {
104+
if ('length' in source) {
105+
collectAll()
106+
} else {
107+
collectOne(source)
108+
}
109+
110+
function collectAll() {
111+
var length = source.length
112+
var index = -1
113+
114+
while (++index < length) {
115+
collectOne(source[index])
116+
}
117+
}
118+
119+
function collectOne(node) {
120+
if (one) {
121+
/* istanbul ignore if - shouldn’t happen, safeguards performance problems. */
122+
if (found) {
123+
throw new Error('Cannot collect multiple nodes')
124+
}
125+
126+
found = true
127+
}
128+
129+
if (result.indexOf(node) === -1) {
130+
result.push(node)
131+
}
132+
}
133+
}
134+
}

lib/ast-walkers.js

Lines changed: 0 additions & 144 deletions
This file was deleted.

0 commit comments

Comments
 (0)