1
+ /**
2
+ * @typedef {import('assert').AssertionError } AssertionError
3
+ * @typedef {import('unist').Node } Node
4
+ * @typedef {import('unist').Parent } Parent
5
+ * @typedef {import('unist').Literal } Literal
6
+ * @typedef {import('unist').Position } Position
7
+ * @typedef {import('unist').Point } Point
8
+ * @typedef {Node & {children: never, value: never} } Void
9
+ */
10
+
1
11
import nodeAssert from 'assert'
2
12
import { inspect } from './inspect.js'
3
13
4
- export var assert = wrap ( assertNode )
5
- assert . parent = wrap ( parent )
6
- assert . text = wrap ( text )
7
- assert . void = wrap ( empty )
14
+ var own = { } . hasOwnProperty
15
+
16
+ /**
17
+ * Assert that `node` is a valid unist node.
18
+ * If `node` is a parent, all children will be asserted too.
19
+ *
20
+ * @param {unknown } [node]
21
+ * @param {Parent } [parent]
22
+ * @returns {asserts node is Node }
23
+ */
24
+ export function assert ( node , parent ) {
25
+ return wrap ( assertNode ) ( node , parent )
26
+ }
27
+
28
+ /**
29
+ * Assert that `node` is a valid unist parent.
30
+ * All children will be asserted too.
31
+ *
32
+ * @param {unknown } [node]
33
+ * @param {Parent } [parent]
34
+ * @returns {asserts node is Parent }
35
+ */
36
+ export function parent ( node , parent ) {
37
+ return wrap ( assertParent ) ( node , parent )
38
+ }
39
+
40
+ /**
41
+ * Assert that `node` is a valid unist literal.
42
+ *
43
+ * @param {unknown } [node]
44
+ * @param {Parent } [parent]
45
+ * @returns {asserts node is Literal }
46
+ */
47
+ export function literal ( node , parent ) {
48
+ return wrap ( assertLiteral ) ( node , parent )
49
+ }
50
+
51
+ /**
52
+ * Assert that `node` is a valid unist node, but neither parent nor literal.
53
+ *
54
+ * @param {unknown } [node]
55
+ * @param {Parent } [parent]
56
+ * @returns {asserts node is Void }
57
+ */
58
+ export function _void ( node , parent ) {
59
+ return wrap ( assertVoid ) ( node , parent )
60
+ }
8
61
9
62
// Identifier to check if a value is seen.
10
63
var ID = '__unist__'
11
64
12
65
// List of specced properties.
13
66
var defined = new Set ( [ 'type' , 'value' , 'children' , 'position' ] )
14
67
15
- // Wrapper around `Node` which adds the current node (and parent, if available),
16
- // to the message.
68
+ /**
69
+ * Wrapper that adds the current node (and parent, if available) to error
70
+ * messages.
71
+ *
72
+ * @param {(node?: unknown, parent?: Parent|null) => asserts node is Node } fn
73
+ * @returns {(node?: unknown, parent?: Parent|null) => asserts node is Node }
74
+ */
17
75
export function wrap ( fn ) {
18
76
return wrapped
19
77
78
+ /**
79
+ * @param {unknown } node
80
+ * @param {Parent } [parent]
81
+ * @throws {AssertionError }
82
+ * @returns {asserts node is T }
83
+ */
20
84
function wrapped ( node , parent ) {
21
85
try {
22
86
fn ( node , parent )
23
87
} catch ( error ) {
24
- if ( ! error [ ID ] ) {
88
+ if ( ! own . call ( error , ID ) ) {
25
89
error [ ID ] = true
26
-
27
90
error . message += ': `' + view ( node ) + '`'
28
-
29
- if ( parent ) {
30
- error . message += ' in `' + view ( parent ) + '`'
31
- }
91
+ if ( parent ) error . message += ' in `' + view ( parent ) + '`'
32
92
}
33
93
34
94
throw error
35
95
}
36
96
}
37
97
}
38
98
39
- // Assert.
99
+ /**
100
+ * Assert.
101
+ *
102
+ * @param {unknown } node
103
+ * @returns {asserts node is Node }
104
+ */
40
105
function assertNode ( node ) {
41
- var type
42
- var children
43
- var value
106
+ var index = - 1
107
+ /** @type {Parent } */
108
+ var parent
109
+ /** @type {unknown } */
110
+ var child
111
+ /** @type {string } */
44
112
var key
45
- var index
46
- var length
47
-
48
- nodeAssert . ok ( node === Object ( node ) , 'node should be an object' )
49
113
50
- type = node . type
51
- children = node . children
52
- value = node . value
114
+ nodeAssert . ok (
115
+ node && typeof node === 'object' && ! Array . isArray ( node ) ,
116
+ 'node should be an object'
117
+ )
53
118
54
- nodeAssert . ok ( 'type' in node , 'node should have a type' )
55
- nodeAssert . strictEqual ( typeof type , 'string' , '`type` should be a string' )
56
- nodeAssert . notStrictEqual ( type , '' , '`type` should not be empty' )
119
+ nodeAssert . ok ( own . call ( node , 'type' ) , 'node should have a type' )
120
+ nodeAssert . strictEqual (
121
+ // @ts -expect-error Looks like an indexed object.
122
+ typeof node . type ,
123
+ 'string' ,
124
+ '`type` should be a string'
125
+ )
126
+ // @ts -expect-error Looks like an indexed object.
127
+ nodeAssert . notStrictEqual ( node . type , '' , '`type` should not be empty' )
57
128
58
- if ( value !== null && value !== undefined ) {
59
- nodeAssert . strictEqual ( typeof value , 'string' , '`value` should be a string' )
129
+ // @ts -expect-error Looks like an indexed object.
130
+ if ( node . value !== null && node . value !== undefined ) {
131
+ nodeAssert . strictEqual (
132
+ // @ts -expect-error Looks like an indexed object.
133
+ typeof node . value ,
134
+ 'string' ,
135
+ '`value` should be a string'
136
+ )
60
137
}
61
138
139
+ // @ts -expect-error Looks like an indexed object.
62
140
position ( node . position )
63
141
64
142
for ( key in node ) {
@@ -67,19 +145,30 @@ function assertNode(node) {
67
145
}
68
146
}
69
147
70
- if ( children !== null && children !== undefined ) {
71
- nodeAssert . ok ( Array . isArray ( children ) , '`children` should be an array' )
148
+ // @ts -expect-error Looks like an indexed object.
149
+ if ( node . children !== null && node . children !== undefined ) {
150
+ // @ts -expect-error Looks like parent.
151
+ parent = node
152
+ nodeAssert . ok (
153
+ Array . isArray ( parent . children ) ,
154
+ '`children` should be an array'
155
+ )
72
156
index = - 1
73
- length = children . length
74
157
75
- while ( ++ index < length ) {
76
- assert ( children [ index ] , node )
158
+ while ( ++ index < parent . children . length ) {
159
+ child = parent . children [ index ]
160
+ assert ( child , parent )
77
161
}
78
162
}
79
163
}
80
164
81
- // Assert `value` (which lives at `key`) can be stringified and re-parsed to the
82
- // same (deep) value.
165
+ /**
166
+ * Assert `value` (which lives at `key`) can be stringified and re-parsed to the
167
+ * same (deep) value.
168
+ *
169
+ * @param {string } key
170
+ * @param {unknown } value
171
+ */
83
172
function vanilla ( key , value ) {
84
173
try {
85
174
nodeAssert . deepStrictEqual ( value , JSON . parse ( JSON . stringify ( value ) ) )
@@ -88,8 +177,13 @@ function vanilla(key, value) {
88
177
}
89
178
}
90
179
91
- // Stringify a value to inspect it.
92
- // Tries `JSON.stringify()`, and if that fails uses `String()` instead.
180
+ /**
181
+ * Stringify a value to inspect it.
182
+ * Tries `JSON.stringify()`, and if that fails uses `String()` instead.
183
+ *
184
+ * @param {unknown } value
185
+ * @returns {string }
186
+ */
93
187
function view ( value ) {
94
188
try {
95
189
return inspect ( value )
@@ -99,8 +193,13 @@ function view(value) {
99
193
}
100
194
}
101
195
102
- // Assert `node` is a parent node.
103
- function parent ( node ) {
196
+ /**
197
+ * Assert `node` is a parent node.
198
+ *
199
+ * @param {Node } node
200
+ * @returns {asserts node is Parent }
201
+ */
202
+ function assertParent ( node ) {
104
203
assertNode ( node )
105
204
106
205
nodeAssert . strictEqual (
@@ -111,20 +210,30 @@ function parent(node) {
111
210
nodeAssert . ok ( 'children' in node , 'parent should have `children`' )
112
211
}
113
212
114
- // Assert `node` is a text node.
115
- function text ( node ) {
213
+ /**
214
+ * Assert `node` is a literal node.
215
+ *
216
+ * @param {Node } node
217
+ * @returns {asserts node is Literal }
218
+ */
219
+ function assertLiteral ( node ) {
116
220
assertNode ( node )
117
221
118
222
nodeAssert . strictEqual (
119
223
'children' in node ,
120
224
false ,
121
- 'text should not have `children`'
225
+ 'literal should not have `children`'
122
226
)
123
- nodeAssert . ok ( 'value' in node , 'text should have `value`' )
227
+ nodeAssert . ok ( 'value' in node , 'literal should have `value`' )
124
228
}
125
229
126
- // Assert `node` is a unist node, but neither parent nor text.
127
- function empty ( node ) {
230
+ /**
231
+ * Assert `node` is a unist node, but neither parent nor literal.
232
+ *
233
+ * @param {Node } node
234
+ * @returns {asserts node is Void }
235
+ */
236
+ function assertVoid ( node ) {
128
237
assertNode ( node )
129
238
130
239
nodeAssert . strictEqual ( 'value' in node , false , 'void should not have `value`' )
@@ -135,7 +244,12 @@ function empty(node) {
135
244
)
136
245
}
137
246
138
- // Assert `position` is a unist position.
247
+ /**
248
+ * Assert `position` is a unist position.
249
+ *
250
+ * @param {Position } position
251
+ * @returns {asserts position is Position }
252
+ */
139
253
function position ( position ) {
140
254
if ( position !== null && position !== undefined ) {
141
255
nodeAssert . ok (
@@ -148,27 +262,36 @@ function position(position) {
148
262
}
149
263
}
150
264
151
- // Assert `point` is a unist point.
152
- function point ( point , name ) {
265
+ /**
266
+ * Assert `point` is a unist point.
267
+ *
268
+ * @param {Point } point
269
+ * @param {string } label
270
+ * @returns {asserts point is Point }
271
+ */
272
+ function point ( point , label ) {
153
273
if ( point !== null && point !== undefined ) {
154
- nodeAssert . ok ( point === Object ( point ) , '`' + name + '` should be an object' )
274
+ nodeAssert . ok (
275
+ point === Object ( point ) ,
276
+ '`' + label + '` should be an object'
277
+ )
155
278
156
279
if ( point . line !== null && point . line !== undefined ) {
157
280
nodeAssert . ok (
158
281
'line' in point ,
159
- '`' + name + '` should have numeric `line`'
282
+ '`' + label + '` should have numeric `line`'
160
283
)
161
- nodeAssert . ok ( point . line >= 1 , '`' + name + '.line` should be gte `1`' )
284
+ nodeAssert . ok ( point . line >= 1 , '`' + label + '.line` should be gte `1`' )
162
285
}
163
286
164
287
if ( point . column !== null && point . column !== undefined ) {
165
288
nodeAssert . ok (
166
289
'column' in point ,
167
- '`' + name + '` should have numeric `column`'
290
+ '`' + label + '` should have numeric `column`'
168
291
)
169
292
nodeAssert . ok (
170
293
point . column >= 1 ,
171
- '`' + name + '.column` should be gte `1`'
294
+ '`' + label + '.column` should be gte `1`'
172
295
)
173
296
}
174
297
}
0 commit comments