1
1
/**
2
2
* @typedef {import('parse5').Document } P5Document
3
3
* @typedef {import('parse5').DocumentFragment } P5Fragment
4
- * @typedef {import('parse5').Element } P5Element
4
+ * @typedef {Omit< import('parse5').Element, 'parentNode'> } P5Element
5
5
* @typedef {import('parse5').Attribute } P5Attribute
6
- * @typedef {import('parse5').Location } P5Location
6
+ * @typedef {Omit< import('parse5').Location, 'startOffset' | 'endOffset'> & {startOffset: number|undefined, endOffset: number|undefined} } P5Location
7
7
* @typedef {import('parse5').ParserOptions } P5ParserOptions
8
8
* @typedef {import('unist').Node } UnistNode
9
9
* @typedef {import('hast').Parent } Parent
34
34
* @property {string } lastStartTagName
35
35
* @property {number } consumedAfterSnapshot
36
36
* @property {boolean } active
37
- * @property {HiddenToken } currentCharacterToken
38
- * @property {HiddenToken } currentToken
37
+ * @property {HiddenToken|undefined } currentCharacterToken
38
+ * @property {HiddenToken|undefined } currentToken
39
39
* @property {unknown } currentAttr
40
40
*
41
41
* @typedef {Object.<string, unknown> & {location: P5Location} } HiddenToken
42
42
*
43
43
* @typedef HiddenPreprocessor
44
- * @property {string } html
44
+ * @property {string|undefined } html
45
45
* @property {number } pos
46
46
* @property {number } lastGapPos
47
47
* @property {number } lastCharPos
51
51
* @property {boolean } endOfChunkHit
52
52
*
53
53
* @typedef HiddenLocationTracker
54
- * @property {P5Location } currentAttrLocation
54
+ * @property {P5Location|undefined } currentAttrLocation
55
55
* @property {P5Location } ctLoc
56
56
* @property {HiddenPosTracker } posTracker
57
57
*
64
64
* @property {number } line
65
65
*/
66
66
67
+ // @ts -expect-error: untyped.
67
68
import Parser from 'parse5/lib/parser/index.js'
68
69
import { pointStart , pointEnd } from 'unist-util-position'
69
70
import { visit } from 'unist-util-visit'
@@ -96,18 +97,20 @@ export function raw(tree, file, options) {
96
97
let index = - 1
97
98
const parser = new Parser ( parseOptions )
98
99
const one = zwitch ( 'type' , {
100
+ // @ts -expect-error: hush.
99
101
handlers : { root, element, text, comment, doctype, raw : handleRaw } ,
102
+ // @ts -expect-error: hush.
100
103
unknown
101
104
} )
102
- /** @type {boolean } */
105
+ /** @type {boolean|undefined } */
103
106
let stitches
104
- /** @type {HiddenTokenizer } */
107
+ /** @type {HiddenTokenizer|undefined } */
105
108
let tokenizer
106
- /** @type {HiddenPreprocessor } */
109
+ /** @type {HiddenPreprocessor|undefined } */
107
110
let preprocessor
108
- /** @type {HiddenPosTracker } */
111
+ /** @type {HiddenPosTracker|undefined } */
109
112
let posTracker
110
- /** @type {HiddenLocationTracker } */
113
+ /** @type {HiddenLocationTracker|undefined } */
111
114
let locationTracker
112
115
113
116
if ( isOptions ( file ) ) {
@@ -117,6 +120,7 @@ export function raw(tree, file, options) {
117
120
118
121
if ( options && options . passThrough ) {
119
122
while ( ++ index < options . passThrough . length ) {
123
+ // @ts -expect-error: hush.
120
124
one . handlers [ options . passThrough [ index ] ] = stitch
121
125
}
122
126
}
@@ -143,7 +147,7 @@ export function raw(tree, file, options) {
143
147
* @type {import('unist-util-visit').Visitor<Stitch> }
144
148
*/
145
149
function mend ( node , index , parent ) {
146
- if ( node . value . stitch ) {
150
+ if ( node . value . stitch && parent !== null && index !== null ) {
147
151
parent . children [ index ] = node . value . stitch
148
152
return index
149
153
}
@@ -159,17 +163,15 @@ export function raw(tree, file, options) {
159
163
tagName : 'template' ,
160
164
attrs : [ ] ,
161
165
namespaceURI : webNamespaces . html ,
162
- childNodes : [ ] ,
163
- parentNode : undefined
166
+ childNodes : [ ]
164
167
}
165
168
/** @type {P5Element } */
166
169
const mock = {
167
170
nodeName : 'documentmock' ,
168
171
tagName : 'documentmock' ,
169
172
attrs : [ ] ,
170
173
namespaceURI : webNamespaces . html ,
171
- childNodes : [ ] ,
172
- parentNode : undefined
174
+ childNodes : [ ]
173
175
}
174
176
/** @type {P5Fragment } */
175
177
const doc = { nodeName : '#document-fragment' , childNodes : [ ] }
@@ -182,6 +184,8 @@ export function raw(tree, file, options) {
182
184
parser . _findFormInFragmentContext ( )
183
185
184
186
tokenizer = parser . tokenizer
187
+ /* c8 ignore next */
188
+ if ( ! tokenizer ) throw new Error ( 'Expected `tokenizer`' )
185
189
preprocessor = tokenizer . preprocessor
186
190
locationTracker = tokenizer . __mixins [ 0 ]
187
191
posTracker = locationTracker . posTracker
@@ -200,8 +204,10 @@ export function raw(tree, file, options) {
200
204
/** @type {P5Document } */
201
205
const doc = parser . treeAdapter . createDocument ( )
202
206
203
- parser . _bootstrap ( doc , null )
207
+ parser . _bootstrap ( doc , undefined )
204
208
tokenizer = parser . tokenizer
209
+ /* c8 ignore next */
210
+ if ( ! tokenizer ) throw new Error ( 'Expected `tokenizer`' )
205
211
preprocessor = tokenizer . preprocessor
206
212
locationTracker = tokenizer . __mixins [ 0 ]
207
213
posTracker = locationTracker . posTracker
@@ -302,9 +308,15 @@ export function raw(tree, file, options) {
302
308
const column = start . column || 1
303
309
const offset = start . offset || 0
304
310
311
+ /* c8 ignore next 4 */
312
+ if ( ! preprocessor ) throw new Error ( 'Expected `preprocessor`' )
313
+ if ( ! tokenizer ) throw new Error ( 'Expected `tokenizer`' )
314
+ if ( ! posTracker ) throw new Error ( 'Expected `posTracker`' )
315
+ if ( ! locationTracker ) throw new Error ( 'Expected `locationTracker`' )
316
+
305
317
// Reset preprocessor:
306
318
// See: <https://github.com/inikulin/parse5/blob/9c683e1/packages/parse5/lib/tokenizer/preprocessor.js>.
307
- preprocessor . html = null
319
+ preprocessor . html = undefined
308
320
preprocessor . pos = - 1
309
321
preprocessor . lastGapPos = - 1
310
322
preprocessor . lastCharPos = - 1
@@ -324,13 +336,13 @@ export function raw(tree, file, options) {
324
336
325
337
// Reset location tracker:
326
338
// See: <https://github.com/inikulin/parse5/blob/9c683e1/packages/parse5/lib/extensions/location-info/tokenizer-mixin.js>.
327
- locationTracker . currentAttrLocation = null
339
+ locationTracker . currentAttrLocation = undefined
328
340
locationTracker . ctLoc = createParse5Location ( node )
329
341
330
342
// See the code for `parse` and `parseFragment`:
331
343
// See: <https://github.com/inikulin/parse5/blob/9c683e1/packages/parse5/lib/parser/index.js#L371>.
332
344
tokenizer . write ( node . value )
333
- parser . _runParsingLoop ( null )
345
+ parser . _runParsingLoop ( undefined )
334
346
335
347
// Process final characters if they’re still there after hibernating.
336
348
// Similar to:
@@ -356,24 +368,27 @@ export function raw(tree, file, options) {
356
368
// Recurse, because to somewhat handle `[<x>]</x>` (where `[]` denotes the
357
369
// passed through node).
358
370
if ( 'children' in node ) {
359
- // @ts -ignore Assume parent.
371
+ // @ts -expect-error Assume parent.
360
372
clone . children = raw (
361
- // @ts -ignore Assume parent.
373
+ // @ts -expect-error Assume parent.
362
374
{ type : 'root' , children : node . children } ,
363
375
file ,
364
376
options
365
- // @ts -ignore Assume parent.
377
+ // @ts -expect-error Assume parent.
366
378
) . children
367
379
}
368
380
369
381
// Hack: `value` is supposed to be a string, but as none of the tools
370
382
// (`parse5` or `hast-util-from-parse5`) looks at it, we can pass nodes
371
383
// through.
372
- // @ts -ignore
384
+ // @ts -expect-error
373
385
comment ( { value : { stitch : clone } } )
374
386
}
375
387
376
388
function resetTokenizer ( ) {
389
+ /* c8 ignore next */
390
+ if ( ! tokenizer ) throw new Error ( 'Expected `tokenizer`' )
391
+
377
392
// Reset tokenizer:
378
393
// See: <https://github.com/inikulin/parse5/blob/9c683e1/packages/parse5/lib/tokenizer/index.js#L218-L234>.
379
394
// Especially putting it back in the `data` state is useful: some elements,
@@ -389,9 +404,9 @@ export function raw(tree, file, options) {
389
404
tokenizer . lastStartTagName = ''
390
405
tokenizer . consumedAfterSnapshot = - 1
391
406
tokenizer . active = false
392
- tokenizer . currentCharacterToken = null
393
- tokenizer . currentToken = null
394
- tokenizer . currentAttr = null
407
+ tokenizer . currentCharacterToken = undefined
408
+ tokenizer . currentToken = undefined
409
+ tokenizer . currentAttr = undefined
395
410
}
396
411
}
397
412
@@ -402,7 +417,7 @@ export function raw(tree, file, options) {
402
417
function startTag ( node ) {
403
418
/** @type {P5Location } */
404
419
const location = Object . assign ( createParse5Location ( node ) )
405
- // @ts -ignore extra positional info.
420
+ // @ts -expect-error extra positional info.
406
421
location . startTag = Object . assign ( { } , location )
407
422
408
423
// Untyped token.
@@ -411,7 +426,6 @@ function startTag(node) {
411
426
tagName : node . tagName ,
412
427
selfClosing : false ,
413
428
attrs : attributes ( node ) ,
414
- // @ts -ignore extra positional info.
415
429
location
416
430
}
417
431
}
@@ -426,7 +440,7 @@ function attributes(node) {
426
440
type : 'element' ,
427
441
properties : node . properties ,
428
442
children : [ ]
429
- // @ts -ignore Assume element.
443
+ // @ts -expect-error Assume element.
430
444
} ) . attrs
431
445
}
432
446
@@ -437,15 +451,14 @@ function attributes(node) {
437
451
function endTag ( node ) {
438
452
/** @type {P5Location } */
439
453
const location = Object . assign ( createParse5Location ( node ) )
440
- // @ts -ignore extra positional info.
454
+ // @ts -expect-error extra positional info.
441
455
location . startTag = Object . assign ( { } , location )
442
456
443
457
// Untyped token.
444
458
return {
445
459
type : endTagToken ,
446
460
tagName : node . tagName ,
447
461
attrs : [ ] ,
448
- // @ts -ignore extra positional info.
449
462
location
450
463
}
451
464
}
@@ -489,9 +502,9 @@ function createParse5Location(node) {
489
502
}
490
503
491
504
/**
492
- * @param {VFile|Options } value
505
+ * @param {VFile|Options|undefined } value
493
506
* @return {value is Options }
494
507
*/
495
508
function isOptions ( value ) {
496
- return value && ! ( 'contents' in value )
509
+ return Boolean ( value && ! ( 'contents' in value ) )
497
510
}
0 commit comments