11/**
2+ * @typedef {import('sax').Tag } Tag
3+ * @typedef {import('unist').Point } Point
24 * @typedef {import('xast').Root } Root
3- * @typedef {import('xast').Element } Element
45 * @typedef {import('xast').Comment } Comment
56 * @typedef {import('xast').Text } Text
67 * @typedef {import('xast').Doctype } Doctype
78 * @typedef {import('xast').RootChildMap } RootChildMap
9+ */
10+
11+ /**
812 * @typedef {RootChildMap[keyof RootChildMap] } Child
9- * @typedef {Root|Child } Node
10- * @typedef {import('unist').Point } Point
11- * @typedef {import('sax').Tag } Tag
13+ * @typedef {Root | Child } Node
1214 */
1315
1416import sax from 'sax'
@@ -21,12 +23,17 @@ const fromCharCode = String.fromCharCode
2123const search = / \r ? \n | \r / g
2224
2325/**
24- * @param {string|Uint8Array } doc
26+ * Parse a string of XML to a xast tree.
27+ *
28+ * @param {string | Uint8Array } doc
29+ * Serialized XML.
30+ * @returns {Root }
31+ * xast root.
2532 */
2633export function fromXml ( doc ) {
2734 // @ts -expect-error `strictEntities` is most definitely fine.
2835 const parser = new Parser ( true , { position : true , strictEntities : true } )
29- /** @type {Array<Node> } */
36+ /** @type {[Root, ... Array<Node>] } */
3037 const stack = [ { type : 'root' , children : [ ] } ]
3138 let position = now ( )
3239
@@ -48,8 +55,12 @@ export function fromXml(doc) {
4855 return stack [ 0 ]
4956
5057 /**
58+ * Crash on a SAX error.
59+ *
5160 * @param {Error } error
61+ * Error.
5262 * @returns {never }
63+ * Never.
5364 */
5465 function onerror ( error ) {
5566 const index = error . message . indexOf ( '\nLine' )
@@ -60,15 +71,22 @@ export function fromXml(doc) {
6071 }
6172
6273 /**
74+ * Crash on an SGML declaration.
75+ *
6376 * @returns {never }
77+ * Never.
6478 */
6579 function onsgmldeclaration ( ) {
6680 fail ( 'Unexpected SGML declaration' , 'unexpected-sgml' )
6781 }
6882
6983 /**
84+ * Handle a doctype.
85+ *
7086 * @param {string } value
87+ * Doctype string.
7188 * @returns {void }
89+ * Nothing.
7290 */
7391 // eslint-disable-next-line complexity
7492 function ondoctype ( value ) {
@@ -77,15 +95,15 @@ export function fromXml(doc) {
7795 const node = { type : 'doctype' , name : '' , public : null , system : null }
7896 let index = - 1
7997 let state = 'BEGIN'
80- /** @type {string| undefined } */
98+ /** @type {string | undefined } */
8199 let returnState
82- /** @type {string| undefined } */
100+ /** @type {string | undefined } */
83101 let buffer
84- /** @type {number| undefined } */
102+ /** @type {number | undefined } */
85103 let bufferIndex
86- /** @type {number| undefined } */
104+ /** @type {number | undefined } */
87105 let start
88- /** @type {number| undefined } */
106+ /** @type {number | undefined } */
89107 let marker
90108
91109 while ( ++ index <= value . length ) {
@@ -326,17 +344,25 @@ export function fromXml(doc) {
326344 }
327345
328346 /**
347+ * Handle a processing instruction.
348+ *
329349 * @param {{name: string, body: string} } value
350+ * Processing instruction token.
330351 * @returns {void }
352+ * Nothing.
331353 */
332354 function onprocessinginstruction ( value ) {
333355 enter ( { type : 'instruction' , name : value . name , value : value . body } )
334356 exit ( )
335357 }
336358
337359 /**
360+ * Handle a comment.
361+ *
338362 * @param {string } value
363+ * Comment value.
339364 * @returns {void }
365+ * Nothing.
340366 */
341367 function oncomment ( value ) {
342368 /** @type {Comment } */
@@ -364,24 +390,35 @@ export function fromXml(doc) {
364390 }
365391
366392 /**
393+ * Handle CDATA opening.
394+ *
367395 * @returns {void }
396+ * Nothing.
368397 */
369398 function oncdataopen ( ) {
370399 enter ( { type : 'cdata' , value : '' } )
371400 }
372401
373402 /**
403+ * Handle CDATA value.
404+ *
374405 * @param {string } value
406+ * CDATA value.
375407 * @returns {void }
408+ * Nothing.
376409 */
377410 function oncdatavalue ( value ) {
378411 // @ts -expect-error: assume literal.
379412 stack [ stack . length - 1 ] . value += value
380413 }
381414
382415 /**
416+ * Handle text.
417+ *
383418 * @param {string } value
419+ * Text value.
384420 * @returns {void }
421+ * Nothing.
385422 */
386423 function ontext ( value ) {
387424 /** @type {Text } */
@@ -421,8 +458,12 @@ export function fromXml(doc) {
421458 }
422459
423460 /**
461+ * Handle tag opening.
462+ *
424463 * @param {Tag } value
464+ * SAX tag.
425465 * @returns {void }
466+ * Nothing.
426467 */
427468 function onopen ( value ) {
428469 enter ( {
@@ -434,8 +475,12 @@ export function fromXml(doc) {
434475 }
435476
436477 /**
478+ * Enter a xast node.
479+ *
437480 * @param {Node } node
481+ * xast node.
438482 * @returns {void }
483+ * Nothing.
439484 */
440485 function enter ( node ) {
441486 // @ts -expect-error Set later.
@@ -447,7 +492,10 @@ export function fromXml(doc) {
447492 }
448493
449494 /**
495+ * Exit a xast node.
496+ *
450497 * @returns {void }
498+ * Nothing.
451499 */
452500 function exit ( ) {
453501 const tail = stack . pop ( )
@@ -458,7 +506,10 @@ export function fromXml(doc) {
458506 }
459507
460508 /**
509+ * Get the current point.
510+ *
461511 * @returns {Point }
512+ * Now.
462513 */
463514 function now ( ) {
464515 return {
@@ -469,20 +520,29 @@ export function fromXml(doc) {
469520 }
470521
471522 /**
523+ * Crash.
524+ *
472525 * @param {string } reason
526+ * Reason for crash.
473527 * @param {string } id
528+ * Id of rule.
474529 * @returns {never }
530+ * Never.
475531 */
476532 function fail ( reason , id ) {
477533 throw new VFileMessage ( reason , now ( ) , 'xast-util-from-xml:' + id )
478534 }
479535}
480536
481537/**
538+ * Check if a code is a name start character.
539+ *
482540 * See: <https://www.w3.org/TR/xml/#NT-NameStartChar>
483541 *
484- * @param {number|null } code
542+ * @param {number | null } code
543+ * Code to check.
485544 * @returns {boolean }
545+ * Whether `code` is a name start character.
486546 */
487547function isNameStartChar ( code ) {
488548 return (
@@ -495,10 +555,14 @@ function isNameStartChar(code) {
495555}
496556
497557/**
558+ * Check if a code is a name continuation character.
559+ *
498560 * See: <https://www.w3.org/TR/xml/#NT-NameChar>
499561 *
500- * @param {number|null } code
562+ * @param {number | null } code
563+ * Code to check.
501564 * @returns {boolean }
565+ * Whether `code` is a name continuation character.
502566 */
503567function isNameChar ( code ) {
504568 return (
@@ -510,16 +574,24 @@ function isNameChar(code) {
510574}
511575
512576/**
513- * @param {number|null } code
577+ * Check if a code is whitespace.
578+ *
579+ * @param {number | null } code
580+ * Code to check.
514581 * @returns {boolean }
582+ * Whether `code` is whitespace.
515583 */
516584function isSpace ( code ) {
517585 return code !== null && / [ \t \n \r ] / . test ( fromCharCode ( code ) )
518586}
519587
520588/**
521- * @param {number|null } code
589+ * Check if a code is a public ID character.
590+
591+ * @param {number | null } code
592+ * Code to check.
522593 * @returns {boolean }
594+ * Whether `code` is a public ID character.
523595 */
524596function isPubidChar ( code ) {
525597 return code !== null && / [ \n \r ! # $ % ' - ; = ? - Z _ a - z ] / . test ( fromCharCode ( code ) )
0 commit comments