Skip to content

Commit 5e05a61

Browse files
committed
Add support for null as input in types
1 parent d68e907 commit 5e05a61

File tree

8 files changed

+127
-89
lines changed

8 files changed

+127
-89
lines changed

index.js

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
/**
22
* @typedef {import('unist').Position} Position
33
* @typedef {import('unist').Node} Node
4-
* @typedef {Record<string, unknown> & {type: string, position?: Position|undefined}} NodeLike
4+
* @typedef {import('./lib/types.js').SelectState} SelectState
5+
* @typedef {Record<string, unknown> & {type: string, position?: Position | undefined}} NodeLike
56
*/
67

78
import {any} from './lib/any.js'
89
import {parse} from './lib/parse.js'
10+
import {root} from './lib/util.js'
911

1012
/**
1113
* Check that the given `node` matches `selector`.
@@ -17,13 +19,17 @@ import {parse} from './lib/parse.js'
1719
*
1820
* @param {string} selector
1921
* CSS selector, such as (`heading`, `link, linkReference`).
20-
* @param {Node | NodeLike | undefined} [node]
22+
* @param {Node | NodeLike | null | undefined} [node]
2123
* Node that might match `selector`.
2224
* @returns {boolean}
2325
* Whether `node` matches `selector`.
2426
*/
2527
export function matches(selector, node) {
26-
return Boolean(any(parse(selector), node, {one: true, shallow: true, any})[0])
28+
const state = createState(node)
29+
state.one = true
30+
state.shallow = true
31+
const result = any(parse(selector), node || undefined, state)
32+
return result.length > 0
2733
}
2834

2935
/**
@@ -33,7 +39,7 @@ export function matches(selector, node) {
3339
*
3440
* @param {string} selector
3541
* CSS selector, such as (`heading`, `link, linkReference`).
36-
* @param {Node | NodeLike | undefined} [tree]
42+
* @param {Node | NodeLike | null | undefined} [tree]
3743
* Tree to search.
3844
* @returns {Node | null}
3945
* First node in `tree` that matches `selector` or `null` if nothing is
@@ -42,7 +48,11 @@ export function matches(selector, node) {
4248
* This could be `tree` itself.
4349
*/
4450
export function select(selector, tree) {
45-
return any(parse(selector), tree, {one: true, any})[0] || null
51+
const state = createState(tree)
52+
state.one = true
53+
const result = any(parse(selector), tree || undefined, state)
54+
// To do next major: return `undefined`.
55+
return result[0] || null
4656
}
4757

4858
/**
@@ -52,13 +62,34 @@ export function select(selector, tree) {
5262
*
5363
* @param {string} selector
5464
* CSS selector, such as (`heading`, `link, linkReference`).
55-
* @param {Node | NodeLike | undefined} [tree]
65+
* @param {Node | NodeLike | null | undefined} [tree]
5666
* Tree to search.
5767
* @returns {Array<Node>}
5868
* Nodes in `tree` that match `selector`.
5969
*
6070
* This could include `tree` itself.
6171
*/
6272
export function selectAll(selector, tree) {
63-
return any(parse(selector), tree, {any})
73+
const state = createState(tree)
74+
return any(parse(selector), tree || undefined, state)
75+
}
76+
77+
/**
78+
* @param {Node | null | undefined} tree
79+
* @returns {SelectState}
80+
*/
81+
function createState(tree) {
82+
return {
83+
any,
84+
iterator: undefined,
85+
scopeNodes: tree ? (root(tree) ? tree.children : [tree]) : [],
86+
one: false,
87+
shallow: false,
88+
index: false,
89+
found: false,
90+
typeIndex: undefined,
91+
nodeIndex: undefined,
92+
typeCount: undefined,
93+
nodeCount: undefined
94+
}
6495
}

lib/any.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ const type = zwitch('type', {
2222
})
2323

2424
/**
25-
* @param {Selectors|RuleSet|Rule} query
26-
* @param {Node|undefined} node
25+
* @param {Selectors | RuleSet | Rule} query
26+
* @param {Node | undefined} node
2727
* @param {SelectState} state
28-
* @returns {Array.<Node>}
28+
* @returns {Array<Node>}
2929
*/
3030
export function any(query, node, state) {
3131
// @ts-expect-error: fine.
@@ -73,7 +73,7 @@ function rule(query, tree, state) {
7373
query,
7474
tree,
7575
0,
76-
null,
76+
undefined,
7777
configure(query, {
7878
any: state.any,
7979
iterator,
@@ -124,7 +124,7 @@ function configure(query, state) {
124124
return state
125125
}
126126

127-
// Shouldn’t be invoked, all data is handled.
127+
// Shouldn’t be called, all data is handled.
128128
/* c8 ignore next 6 */
129129
/**
130130
* @param {{[x: string]: unknown, type: string}} query
@@ -133,17 +133,17 @@ function unknownType(query) {
133133
throw new Error('Unknown type `' + query.type + '`')
134134
}
135135

136-
// Shouldn’t be invoked, parser gives correct data.
136+
// Shouldn’t be called, parser gives correct data.
137137
/* c8 ignore next 3 */
138138
function invalidType() {
139139
throw new Error('Invalid type')
140140
}
141141

142142
/**
143-
* @param {boolean|undefined} one
143+
* @param {boolean | undefined} one
144144
*/
145145
function collector(one) {
146-
/** @type {Array.<Node>} */
146+
/** @type {Array<Node>} */
147147
const result = []
148148
/** @type {boolean} */
149149
let found
@@ -155,7 +155,7 @@ function collector(one) {
155155
/**
156156
* Append nodes to array, filtering out duplicates.
157157
*
158-
* @param {Node|Array.<Node>} node
158+
* @param {Node | Array<Node>} node
159159
*/
160160
function collect(node) {
161161
let index = -1

lib/attribute.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ function containsArray(query, node) {
7676

7777
// If this is an array, and the query is contained in it, return true.
7878
// Coverage comment in place because TS turns `Array.isArray(unknown)`
79-
// into `Array.<any>` instead of `Array.<unknown>`.
79+
// into `Array<any>` instead of `Array<unknown>`.
8080
// type-coverage:ignore-next-line
8181
if (Array.isArray(value) && value.includes(query.value)) {
8282
return true
@@ -135,7 +135,7 @@ function containsString(query, node) {
135135
return query.value && typeof value === 'string' && value.includes(query.value)
136136
}
137137

138-
// Shouldn’t be invoked, Parser throws an error instead.
138+
// Shouldn’t be called, parser throws an error instead.
139139
/* c8 ignore next 6 */
140140
/**
141141
* @param {{[x: string]: unknown, type: string}} query

lib/nest.js

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ const handle = zwitch('nestingOperator', {
3232
/** @type {Handler} */
3333
export const nest = handle
3434

35-
// Shouldn’t be invoked, parser gives correct data.
35+
// Shouldn’t be called, parser gives correct data.
3636
/* c8 ignore next 6 */
3737
/**
3838
* @param {{[x: string]: unknown, type: string}} query
@@ -93,7 +93,7 @@ function child(query, node, _1, _2, state) {
9393
if (!parent(node)) return
9494
if (node.children.length === 0) return
9595

96-
new WalkIterator(query, node, state).each().done()
96+
new WalkIterator(query, node, state).each(undefined, undefined).done()
9797
}
9898

9999
/** @type {Handler} */
@@ -111,7 +111,7 @@ function adjacentSibling(query, _, index, parent, state) {
111111
new WalkIterator(query, parent, state)
112112
.prefillTypeIndex(0, ++index)
113113
.each(index, ++index)
114-
.prefillTypeIndex(index)
114+
.prefillTypeIndex(index, undefined)
115115
.done()
116116
}
117117

@@ -129,7 +129,7 @@ function generalSibling(query, _, index, parent, state) {
129129

130130
new WalkIterator(query, parent, state)
131131
.prefillTypeIndex(0, ++index)
132-
.each(index)
132+
.each(index, undefined)
133133
.done()
134134
}
135135

@@ -148,15 +148,15 @@ class WalkIterator {
148148
this.parent = parent
149149
/** @type {SelectState} */
150150
this.state = state
151-
/** @type {TypeIndex|undefined} */
151+
/** @type {TypeIndex | undefined} */
152152
this.typeIndex = state.index ? new TypeIndex() : undefined
153-
/** @type {Array.<Function>} */
153+
/** @type {Array<Function>} */
154154
this.delayed = []
155155
}
156156

157157
/**
158-
* @param {number|null|undefined} [x]
159-
* @param {number|null|undefined} [y]
158+
* @param {number | undefined} x
159+
* @param {number | undefined} y
160160
* @returns {this}
161161
*/
162162
prefillTypeIndex(x, y) {
@@ -173,8 +173,8 @@ class WalkIterator {
173173
}
174174

175175
/**
176-
* @param {number|null|undefined} [x]
177-
* @param {number|null|undefined} [y]
176+
* @param {number | undefined} x
177+
* @param {number | undefined} y
178178
* @returns {this}
179179
*/
180180
each(x, y) {
@@ -246,21 +246,21 @@ class WalkIterator {
246246
}
247247

248248
/**
249-
* @param {number|null|undefined} [start]
250-
* @param {number|null|undefined} [end]
249+
* @param {number | undefined} start
250+
* @param {number | undefined} end
251251
* @returns {[number, number]}
252252
*/
253253
defaults(start, end) {
254-
if (start === null || start === undefined || start < 0) start = 0
255-
if (end === null || end === undefined || end > this.parent.children.length)
254+
if (start === undefined || start < 0) start = 0
255+
if (end === undefined || end > this.parent.children.length)
256256
end = this.parent.children.length
257257
return [start, end]
258258
}
259259
}
260260

261261
class TypeIndex {
262262
constructor() {
263-
/** @type {Object.<string, number>} */
263+
/** @type {Record<string, number>} */
264264
this.counts = {}
265265
/** @type {number} */
266266
this.nodes = 0
@@ -283,7 +283,7 @@ class TypeIndex {
283283

284284
/**
285285
* @param {Node} node
286-
* @returns {number|undefined}
286+
* @returns {number | undefined}
287287
*/
288288
count(node) {
289289
return this.counts[node.type]

lib/parse.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ function ruleSet(query) {
7070
function rule(query) {
7171
const pseudos = query.pseudos || []
7272
let index = -1
73-
/** @type {RulePseudo|RulePseudoNth} */
73+
/** @type {RulePseudo | RulePseudoNth} */
7474
let pseudo
7575

7676
while (++index < pseudos.length) {

0 commit comments

Comments
 (0)