1
1
/**
2
2
* @typedef {import('unist').Node } Node
3
3
* @typedef {import('unist').Parent } Parent
4
- * @typedef {string } Type
4
+ */
5
+
6
+ /**
5
7
* @typedef {Record<string, unknown> } Props
6
- * @typedef {null|undefined|Type|Props|TestFunctionAnything|Array<Type|Props|TestFunctionAnything> } Test
8
+ * @typedef {null | undefined | string | Props | TestFunctionAnything | Array<string | Props | TestFunctionAnything> } Test
9
+ * Check for an arbitrary node, unaware of TypeScript inferral.
7
10
*
8
11
* @callback TestFunctionAnything
9
- * Arbitrary function to define whether a node passes .
12
+ * Check if a node passes a test, unaware of TypeScript inferral .
10
13
* @param {unknown } this
11
- * The to `is` given ` context`
14
+ * The given context.
12
15
* @param {Node } node
13
- * Node to check.
14
- * @param {number|null|undefined } [index]
15
- * Index of `node` in `parent`.
16
- * @param {Parent|null|undefined } [parent]
17
- * Parent of `node`.
18
- * @returns {boolean|void }
19
- * Whether `node` matches.
20
- *
21
- * @callback AssertAnything
22
- * Check if a node is an element and passes a certain node test.
23
- * @param {unknown } [node]
24
- * Thing to check and check that it’s a node.
25
- * @param {number|null|undefined } [index]
26
- * Index of `node` in `parent`.
27
- * @param {Parent|null|undefined } [parent]
28
- * Parent of `node`.
29
- * @returns {boolean }
30
- * Whether `node` matches.
16
+ * A node.
17
+ * @param {number | null | undefined } [index]
18
+ * The node’s position in its parent.
19
+ * @param {Parent | null | undefined } [parent]
20
+ * The node’s parent.
21
+ * @returns {boolean | void }
22
+ * Whether this node passes the test.
31
23
*/
32
24
33
25
/**
34
26
* @template {Node} Kind
27
+ * Node type.
28
+ * @typedef {Kind['type'] | Partial<Kind> | TestFunctionPredicate<Kind> | Array<Kind['type'] | Partial<Kind> | TestFunctionPredicate<Kind>> } PredicateTest
29
+ * Check for a node that can be inferred by TypeScript.
30
+ */
31
+
32
+ /**
33
+ * Check if a node passes a certain test.
34
+ *
35
+ * @template {Node} Kind
36
+ * Node type.
35
37
* @callback TestFunctionPredicate
36
- * Arbitrary function to define whether a node passes, using a TypeScript type
37
- * predicate.
38
+ * Complex test function for a node that can be inferred by TypeScript.
38
39
* @param {Node } node
39
- * Node to check .
40
- * @param {number| null| undefined } [index]
41
- * Index of ` node` in ` parent` .
42
- * @param {Parent| null| undefined } [parent]
43
- * Parent of ` node` .
40
+ * A node .
41
+ * @param {number | null | undefined } [index]
42
+ * The node’s position in its parent.
43
+ * @param {Parent | null | undefined } [parent]
44
+ * The node’s parent .
44
45
* @returns {node is Kind }
45
- * Whether `node` matches.
46
+ * Whether this node passes the test.
47
+ */
48
+
49
+ /**
50
+ * @callback AssertAnything
51
+ * Check that an arbitrary value is a node, unaware of TypeScript inferral.
52
+ * @param {unknown } [node]
53
+ * Anything (typically a node).
54
+ * @param {number | null | undefined } [index]
55
+ * The node’s position in its parent.
56
+ * @param {Parent | null | undefined } [parent]
57
+ * The node’s parent.
58
+ * @returns {boolean }
59
+ * Whether this is a node and passes a test.
46
60
*/
47
61
48
62
/**
63
+ * Check if a node is a node and passes a certain node test.
64
+ *
49
65
* @template {Node} Kind
66
+ * Node type.
50
67
* @callback AssertPredicate
51
- * Check if a node is an element and passes a certain node test, using a
52
- * TypeScript type predicate.
68
+ * Check that an arbitrary value is a specific node, aware of TypeScript.
53
69
* @param {unknown } [node]
54
- * Thing to check and check that it’s a node.
55
- * @param {number| null| undefined } [index]
56
- * Index of ` node` in ` parent` .
57
- * @param {Parent| null| undefined } [parent]
58
- * Parent of ` node` .
70
+ * Anything (typically a node) .
71
+ * @param {number | null | undefined } [index]
72
+ * The node’s position in its parent.
73
+ * @param {Parent | null | undefined } [parent]
74
+ * The node’s parent .
59
75
* @returns {node is Kind }
60
- * Whether ` node` matches .
76
+ * Whether this is a node and passes a test .
61
77
*/
62
78
63
79
/**
64
- * Check if `node` passes a test.
65
- * When a `parent` node is given the `index` of node should also be given.
80
+ * Check if `node` is a `Node` and whether it passes the given test.
66
81
*
67
82
* @param node
68
- * Node to check, can be anything .
83
+ * Thing to check, typically `Node` .
69
84
* @param test
70
- * * when nullish, checks if `node` is a `Node`.
71
- * * when `string`, works like passing `(node) => node.type === test`.
72
- * * when `array`, checks any one of the subtests pass.
73
- * * when `object`, checks that all keys in test are in node, and that they have (strictly) equal values.
74
- * * when `function` checks if function passed the node is true.
85
+ * A check for a specific node.
75
86
* @param index
76
- * Position of ` node` in `parent`, must be a number if ` parent` is also given .
87
+ * The node’s position in its parent.
77
88
* @param parent
78
- * Parent of `node`, must be given if `index` is also given.
79
- * @param context
80
- * Context object to call `test` with
89
+ * The node’s parent.
81
90
* @returns
82
- * Whether test passed and `node` is a `Node` (object with `type` set to
83
- * non-empty `string`).
91
+ * Whether `node` is a node and passes a test.
84
92
*/
85
93
export const is =
86
94
/**
87
95
* @type {(
88
- * (<Kind extends Node>(node: unknown, test: Kind['type']|Partial<Kind>|TestFunctionPredicate<Kind>|Array<Kind['type']|Partial<Kind>|TestFunctionPredicate<Kind>>, index: number, parent: Parent, context?: unknown) => node is Kind) &
89
- * (<Kind extends Node>(node: unknown, test: Kind['type']|Partial<Kind>|TestFunctionPredicate<Kind>|Array<Kind['type']|Partial<Kind>|TestFunctionPredicate<Kind>>, index?: null|undefined, parent?: null|undefined, context?: unknown) => node is Kind) &
96
+ * (() => false) &
97
+ * (<Kind extends Node = Node>(node: unknown, test: PredicateTest<Kind>, index: number, parent: Parent, context?: unknown) => node is Kind) &
98
+ * (<Kind extends Node = Node>(node: unknown, test: PredicateTest<Kind>, index?: null | undefined, parent?: null | undefined, context?: unknown) => node is Kind) &
90
99
* ((node: unknown, test: Test, index: number, parent: Parent, context?: unknown) => boolean) &
91
- * ((node? : unknown, test?: Test, index?: null| undefined, parent?: null| undefined, context?: unknown) => boolean)
100
+ * ((node: unknown, test?: Test, index?: null | undefined, parent?: null | undefined, context?: unknown) => boolean)
92
101
* )}
93
102
*/
94
103
(
95
104
/**
96
105
* @param {unknown } [node]
97
106
* @param {Test } [test]
98
- * @param {number| null| undefined } [index]
99
- * @param {Parent| null| undefined } [parent]
107
+ * @param {number | null | undefined } [index]
108
+ * @param {Parent | null | undefined } [parent]
100
109
* @param {unknown } [context]
101
110
* @returns {boolean }
102
111
*/
@@ -137,28 +146,27 @@ export const is =
137
146
)
138
147
139
148
/**
140
- * Create a test function from `test` that can later be called with a `node`,
141
- * `index`, and `parent`.
149
+ * Generate an assertion from a test.
150
+ *
142
151
* Useful if you’re going to test many nodes, for example when creating a
143
- * utility where something else passes an is- compatible test.
152
+ * utility where something else passes a compatible test.
144
153
*
145
- * The created function is slightly faster that using `is` because it expects
146
- * valid input only.
147
- * Therefore, passing invalid input yields unexpected results.
154
+ * The created function is a bit faster because it expects valid input only:
155
+ * a `node`, `index`, and `parent`.
148
156
*
149
157
* @param test
150
158
* * when nullish, checks if `node` is a `Node`.
151
159
* * when `string`, works like passing `(node) => node.type === test`.
152
- * * when `array`, checks any one of the subtests pass.
153
- * * when `object`, checks that all keys in test are in node, and that they have (strictly) equal values.
154
160
* * when `function` checks if function passed the node is true.
161
+ * * when `object`, checks that all keys in test are in node, and that they have (strictly) equal values.
162
+ * * when `array`, checks if any one of the subtests pass.
155
163
* @returns
156
- * Check function that can be called as `check(node, index, parent)` .
164
+ * An assertion .
157
165
*/
158
166
export const convert =
159
167
/**
160
168
* @type {(
161
- * (<Kind extends Node>(test: Kind['type']|Partial<Kind>|TestFunctionPredicate <Kind>) => AssertPredicate<Kind>) &
169
+ * (<Kind extends Node>(test: PredicateTest <Kind>) => AssertPredicate<Kind>) &
162
170
* ((test?: Test) => AssertAnything)
163
171
* )}
164
172
*/
@@ -189,7 +197,7 @@ export const convert =
189
197
)
190
198
191
199
/**
192
- * @param {Array<Type| Props| TestFunctionAnything> } tests
200
+ * @param {Array<string | Props | TestFunctionAnything> } tests
193
201
* @returns {AssertAnything }
194
202
*/
195
203
function anyFactory ( tests ) {
@@ -220,8 +228,7 @@ function anyFactory(tests) {
220
228
}
221
229
222
230
/**
223
- * Assert each field in `test` is present in `node` and each values are strictly
224
- * equal.
231
+ * Turn an object into a test for a node with a certain fields.
225
232
*
226
233
* @param {Props } check
227
234
* @returns {AssertAnything }
@@ -247,10 +254,9 @@ function propsFactory(check) {
247
254
}
248
255
249
256
/**
250
- * Convert a string into a function which checks a given node’s type
251
- * for said string.
257
+ * Turn a string into a test for a node with a certain type.
252
258
*
253
- * @param {Type } check
259
+ * @param {string } check
254
260
* @returns {AssertAnything }
255
261
*/
256
262
function typeFactory ( check ) {
@@ -265,8 +271,7 @@ function typeFactory(check) {
265
271
}
266
272
267
273
/**
268
- * Convert a string into a function which checks a given node’s type
269
- * for said string.
274
+ * Turn a custom test into a test for a node that passes that test.
270
275
*
271
276
* @param {TestFunctionAnything } check
272
277
* @returns {AssertAnything }
@@ -276,12 +281,18 @@ function castFactory(check) {
276
281
277
282
/**
278
283
* @this {unknown}
284
+ * @param {unknown } node
279
285
* @param {Array<unknown> } parameters
280
286
* @returns {boolean }
281
287
*/
282
- function assertion ( ...parameters ) {
283
- // @ts -expect-error: spreading is fine.
284
- return Boolean ( check . call ( this , ...parameters ) )
288
+ function assertion ( node , ...parameters ) {
289
+ return Boolean (
290
+ node &&
291
+ typeof node === 'object' &&
292
+ 'type' in node &&
293
+ // @ts -expect-error: fine.
294
+ Boolean ( check . call ( this , node , ...parameters ) )
295
+ )
285
296
}
286
297
}
287
298
0 commit comments