11/**
22 * @typedef {import('parse5').Document } P5Document
33 * @typedef {import('parse5').DocumentFragment } P5Fragment
4- * @typedef {import('parse5').Element } P5Element
4+ * @typedef {Omit< import('parse5').Element, 'parentNode'> } P5Element
55 * @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
77 * @typedef {import('parse5').ParserOptions } P5ParserOptions
88 * @typedef {import('unist').Node } UnistNode
99 * @typedef {import('hast').Parent } Parent
3434 * @property {string } lastStartTagName
3535 * @property {number } consumedAfterSnapshot
3636 * @property {boolean } active
37- * @property {HiddenToken } currentCharacterToken
38- * @property {HiddenToken } currentToken
37+ * @property {HiddenToken|undefined } currentCharacterToken
38+ * @property {HiddenToken|undefined } currentToken
3939 * @property {unknown } currentAttr
4040 *
4141 * @typedef {Object.<string, unknown> & {location: P5Location} } HiddenToken
4242 *
4343 * @typedef HiddenPreprocessor
44- * @property {string } html
44+ * @property {string|undefined } html
4545 * @property {number } pos
4646 * @property {number } lastGapPos
4747 * @property {number } lastCharPos
5151 * @property {boolean } endOfChunkHit
5252 *
5353 * @typedef HiddenLocationTracker
54- * @property {P5Location } currentAttrLocation
54+ * @property {P5Location|undefined } currentAttrLocation
5555 * @property {P5Location } ctLoc
5656 * @property {HiddenPosTracker } posTracker
5757 *
6464 * @property {number } line
6565 */
6666
67+ // @ts -expect-error: untyped.
6768import Parser from 'parse5/lib/parser/index.js'
6869import { pointStart , pointEnd } from 'unist-util-position'
6970import { visit } from 'unist-util-visit'
@@ -96,18 +97,20 @@ export function raw(tree, file, options) {
9697 let index = - 1
9798 const parser = new Parser ( parseOptions )
9899 const one = zwitch ( 'type' , {
100+ // @ts -expect-error: hush.
99101 handlers : { root, element, text, comment, doctype, raw : handleRaw } ,
102+ // @ts -expect-error: hush.
100103 unknown
101104 } )
102- /** @type {boolean } */
105+ /** @type {boolean|undefined } */
103106 let stitches
104- /** @type {HiddenTokenizer } */
107+ /** @type {HiddenTokenizer|undefined } */
105108 let tokenizer
106- /** @type {HiddenPreprocessor } */
109+ /** @type {HiddenPreprocessor|undefined } */
107110 let preprocessor
108- /** @type {HiddenPosTracker } */
111+ /** @type {HiddenPosTracker|undefined } */
109112 let posTracker
110- /** @type {HiddenLocationTracker } */
113+ /** @type {HiddenLocationTracker|undefined } */
111114 let locationTracker
112115
113116 if ( isOptions ( file ) ) {
@@ -117,6 +120,7 @@ export function raw(tree, file, options) {
117120
118121 if ( options && options . passThrough ) {
119122 while ( ++ index < options . passThrough . length ) {
123+ // @ts -expect-error: hush.
120124 one . handlers [ options . passThrough [ index ] ] = stitch
121125 }
122126 }
@@ -143,7 +147,7 @@ export function raw(tree, file, options) {
143147 * @type {import('unist-util-visit').Visitor<Stitch> }
144148 */
145149 function mend ( node , index , parent ) {
146- if ( node . value . stitch ) {
150+ if ( node . value . stitch && parent !== null && index !== null ) {
147151 parent . children [ index ] = node . value . stitch
148152 return index
149153 }
@@ -159,17 +163,15 @@ export function raw(tree, file, options) {
159163 tagName : 'template' ,
160164 attrs : [ ] ,
161165 namespaceURI : webNamespaces . html ,
162- childNodes : [ ] ,
163- parentNode : undefined
166+ childNodes : [ ]
164167 }
165168 /** @type {P5Element } */
166169 const mock = {
167170 nodeName : 'documentmock' ,
168171 tagName : 'documentmock' ,
169172 attrs : [ ] ,
170173 namespaceURI : webNamespaces . html ,
171- childNodes : [ ] ,
172- parentNode : undefined
174+ childNodes : [ ]
173175 }
174176 /** @type {P5Fragment } */
175177 const doc = { nodeName : '#document-fragment' , childNodes : [ ] }
@@ -182,6 +184,8 @@ export function raw(tree, file, options) {
182184 parser . _findFormInFragmentContext ( )
183185
184186 tokenizer = parser . tokenizer
187+ /* c8 ignore next */
188+ if ( ! tokenizer ) throw new Error ( 'Expected `tokenizer`' )
185189 preprocessor = tokenizer . preprocessor
186190 locationTracker = tokenizer . __mixins [ 0 ]
187191 posTracker = locationTracker . posTracker
@@ -200,8 +204,10 @@ export function raw(tree, file, options) {
200204 /** @type {P5Document } */
201205 const doc = parser . treeAdapter . createDocument ( )
202206
203- parser . _bootstrap ( doc , null )
207+ parser . _bootstrap ( doc , undefined )
204208 tokenizer = parser . tokenizer
209+ /* c8 ignore next */
210+ if ( ! tokenizer ) throw new Error ( 'Expected `tokenizer`' )
205211 preprocessor = tokenizer . preprocessor
206212 locationTracker = tokenizer . __mixins [ 0 ]
207213 posTracker = locationTracker . posTracker
@@ -302,9 +308,15 @@ export function raw(tree, file, options) {
302308 const column = start . column || 1
303309 const offset = start . offset || 0
304310
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+
305317 // Reset preprocessor:
306318 // See: <https://github.com/inikulin/parse5/blob/9c683e1/packages/parse5/lib/tokenizer/preprocessor.js>.
307- preprocessor . html = null
319+ preprocessor . html = undefined
308320 preprocessor . pos = - 1
309321 preprocessor . lastGapPos = - 1
310322 preprocessor . lastCharPos = - 1
@@ -324,13 +336,13 @@ export function raw(tree, file, options) {
324336
325337 // Reset location tracker:
326338 // 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
328340 locationTracker . ctLoc = createParse5Location ( node )
329341
330342 // See the code for `parse` and `parseFragment`:
331343 // See: <https://github.com/inikulin/parse5/blob/9c683e1/packages/parse5/lib/parser/index.js#L371>.
332344 tokenizer . write ( node . value )
333- parser . _runParsingLoop ( null )
345+ parser . _runParsingLoop ( undefined )
334346
335347 // Process final characters if they’re still there after hibernating.
336348 // Similar to:
@@ -356,24 +368,27 @@ export function raw(tree, file, options) {
356368 // Recurse, because to somewhat handle `[<x>]</x>` (where `[]` denotes the
357369 // passed through node).
358370 if ( 'children' in node ) {
359- // @ts -ignore Assume parent.
371+ // @ts -expect-error Assume parent.
360372 clone . children = raw (
361- // @ts -ignore Assume parent.
373+ // @ts -expect-error Assume parent.
362374 { type : 'root' , children : node . children } ,
363375 file ,
364376 options
365- // @ts -ignore Assume parent.
377+ // @ts -expect-error Assume parent.
366378 ) . children
367379 }
368380
369381 // Hack: `value` is supposed to be a string, but as none of the tools
370382 // (`parse5` or `hast-util-from-parse5`) looks at it, we can pass nodes
371383 // through.
372- // @ts -ignore
384+ // @ts -expect-error
373385 comment ( { value : { stitch : clone } } )
374386 }
375387
376388 function resetTokenizer ( ) {
389+ /* c8 ignore next */
390+ if ( ! tokenizer ) throw new Error ( 'Expected `tokenizer`' )
391+
377392 // Reset tokenizer:
378393 // See: <https://github.com/inikulin/parse5/blob/9c683e1/packages/parse5/lib/tokenizer/index.js#L218-L234>.
379394 // Especially putting it back in the `data` state is useful: some elements,
@@ -389,9 +404,9 @@ export function raw(tree, file, options) {
389404 tokenizer . lastStartTagName = ''
390405 tokenizer . consumedAfterSnapshot = - 1
391406 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
395410 }
396411}
397412
@@ -402,7 +417,7 @@ export function raw(tree, file, options) {
402417function startTag ( node ) {
403418 /** @type {P5Location } */
404419 const location = Object . assign ( createParse5Location ( node ) )
405- // @ts -ignore extra positional info.
420+ // @ts -expect-error extra positional info.
406421 location . startTag = Object . assign ( { } , location )
407422
408423 // Untyped token.
@@ -411,7 +426,6 @@ function startTag(node) {
411426 tagName : node . tagName ,
412427 selfClosing : false ,
413428 attrs : attributes ( node ) ,
414- // @ts -ignore extra positional info.
415429 location
416430 }
417431}
@@ -426,7 +440,7 @@ function attributes(node) {
426440 type : 'element' ,
427441 properties : node . properties ,
428442 children : [ ]
429- // @ts -ignore Assume element.
443+ // @ts -expect-error Assume element.
430444 } ) . attrs
431445}
432446
@@ -437,15 +451,14 @@ function attributes(node) {
437451function endTag ( node ) {
438452 /** @type {P5Location } */
439453 const location = Object . assign ( createParse5Location ( node ) )
440- // @ts -ignore extra positional info.
454+ // @ts -expect-error extra positional info.
441455 location . startTag = Object . assign ( { } , location )
442456
443457 // Untyped token.
444458 return {
445459 type : endTagToken ,
446460 tagName : node . tagName ,
447461 attrs : [ ] ,
448- // @ts -ignore extra positional info.
449462 location
450463 }
451464}
@@ -489,9 +502,9 @@ function createParse5Location(node) {
489502}
490503
491504/**
492- * @param {VFile|Options } value
505+ * @param {VFile|Options|undefined } value
493506 * @return {value is Options }
494507 */
495508function isOptions ( value ) {
496- return value && ! ( 'contents' in value )
509+ return Boolean ( value && ! ( 'contents' in value ) )
497510}
0 commit comments