66 * @typedef {import('micromark-util-types').TokenizeContext } TokenizeContext
77 * @typedef {import('micromark-util-types').Value } Value
88 * @typedef {Root|Root['children'][number] } Node
9- * @typedef {import('unist').Parent } Parent
9+ * @typedef {Extract<Node, import('unist').Parent> } Parent
1010 * @typedef {import('unist').Point } Point
1111 * @typedef {import('mdast').Break } Break
1212 * @typedef {import('mdast').Blockquote } Blockquote
1616 * @typedef {import('mdast').Heading } Heading
1717 * @typedef {import('mdast').HTML } HTML
1818 * @typedef {import('mdast').Image } Image
19+ * @typedef {import('mdast').ImageReference } ImageReference
1920 * @typedef {import('mdast').InlineCode } InlineCode
2021 * @typedef {import('mdast').Link } Link
22+ * @typedef {import('mdast').LinkReference } LinkReference
2123 * @typedef {import('mdast').List } List
2224 * @typedef {import('mdast').ListItem } ListItem
2325 * @typedef {import('mdast').Paragraph } Paragraph
2426 * @typedef {import('mdast').Root } Root
2527 * @typedef {import('mdast').Strong } Strong
2628 * @typedef {import('mdast').Text } Text
2729 * @typedef {import('mdast').ThematicBreak } ThematicBreak
30+ * @typedef {import('mdast').PhrasingContent } PhrasingContent
31+ *
32+ * @typedef {Parent & {type: 'fragment', children: PhrasingContent[]} } Fragment
2833 */
2934
3035/**
@@ -536,10 +541,10 @@ function compiler(options = {}) {
536541 * @returns {N }
537542 */
538543 function enter ( node , token ) {
539- /** @type {Parent } */
540- // @ts -expect-error: Assume parent.
541544 const parent = this . stack [ this . stack . length - 1 ]
542545 assert ( parent , 'expected `parent`' )
546+ assert ( 'children' in parent , 'expected `parent`' )
547+ // @ts -expect-error: Assume `Node` can exist as a child of `parent`.
543548 parent . children . push ( node )
544549 this . stack . push ( node )
545550 this . tokenStack . push ( token )
@@ -619,7 +624,8 @@ function compiler(options = {}) {
619624 /** @type {Handle } */
620625 function onenterlistitemvalue ( token ) {
621626 if ( getData ( 'expectingFirstListItemValue' ) ) {
622- this . stack [ this . stack . length - 2 ] . start = Number . parseInt (
627+ const ancestor = /** @type {List } */ ( this . stack [ this . stack . length - 2 ] )
628+ ancestor . start = Number . parseInt (
623629 this . sliceSerialize ( token ) ,
624630 constants . numericBaseDecimal
625631 )
@@ -630,13 +636,15 @@ function compiler(options = {}) {
630636 /** @type {Handle } */
631637 function onexitcodefencedfenceinfo ( ) {
632638 const data = this . resume ( )
633- this . stack [ this . stack . length - 1 ] . lang = data
639+ const node = /** @type {Code } */ ( this . stack [ this . stack . length - 1 ] )
640+ node . lang = data
634641 }
635642
636643 /** @type {Handle } */
637644 function onexitcodefencedfencemeta ( ) {
638645 const data = this . resume ( )
639- this . stack [ this . stack . length - 1 ] . meta = data
646+ const node = /** @type {Code } */ ( this . stack [ this . stack . length - 1 ] )
647+ node . meta = data
640648 }
641649
642650 /** @type {Handle } */
@@ -650,48 +658,52 @@ function compiler(options = {}) {
650658 /** @type {Handle } */
651659 function onexitcodefenced ( ) {
652660 const data = this . resume ( )
661+ const node = /** @type {Code } */ ( this . stack [ this . stack . length - 1 ] )
653662
654- this . stack [ this . stack . length - 1 ] . value = data . replace (
655- / ^ ( \r ? \n | \r ) | ( \r ? \n | \r ) $ / g,
656- ''
657- )
663+ node . value = data . replace ( / ^ ( \r ? \n | \r ) | ( \r ? \n | \r ) $ / g, '' )
658664
659665 setData ( 'flowCodeInside' )
660666 }
661667
662668 /** @type {Handle } */
663669 function onexitcodeindented ( ) {
664670 const data = this . resume ( )
665- this . stack [ this . stack . length - 1 ] . value = data . replace ( / ( \r ? \n | \r ) $ / g, '' )
671+ const node = /** @type {Code } */ ( this . stack [ this . stack . length - 1 ] )
672+
673+ node . value = data . replace ( / ( \r ? \n | \r ) $ / g, '' )
666674 }
667675
668676 /** @type {Handle } */
669677 function onexitdefinitionlabelstring ( token ) {
670678 // Discard label, use the source content instead.
671679 const label = this . resume ( )
672- this . stack [ this . stack . length - 1 ] . label = label
673- this . stack [ this . stack . length - 1 ] . identifier = normalizeIdentifier (
680+ const node = /** @type {Definition } */ ( this . stack [ this . stack . length - 1 ] )
681+ node . label = label
682+ node . identifier = normalizeIdentifier (
674683 this . sliceSerialize ( token )
675684 ) . toLowerCase ( )
676685 }
677686
678687 /** @type {Handle } */
679688 function onexitdefinitiontitlestring ( ) {
680689 const data = this . resume ( )
681- this . stack [ this . stack . length - 1 ] . title = data
690+ const node = /** @type {Definition } */ ( this . stack [ this . stack . length - 1 ] )
691+ node . title = data
682692 }
683693
684694 /** @type {Handle } */
685695 function onexitdefinitiondestinationstring ( ) {
686696 const data = this . resume ( )
687- this . stack [ this . stack . length - 1 ] . url = data
697+ const node = /** @type {Definition } */ ( this . stack [ this . stack . length - 1 ] )
698+ node . url = data
688699 }
689700
690701 /** @type {Handle } */
691702 function onexitatxheadingsequence ( token ) {
692- if ( ! this . stack [ this . stack . length - 1 ] . depth ) {
693- this . stack [ this . stack . length - 1 ] . depth =
694- this . sliceSerialize ( token ) . length
703+ const node = /** @type {Heading } */ ( this . stack [ this . stack . length - 1 ] )
704+ if ( ! node . depth ) {
705+ // @ts -expect-error: assume valid depth.
706+ node . depth = this . sliceSerialize ( token ) . length
695707 }
696708 }
697709
@@ -702,7 +714,9 @@ function compiler(options = {}) {
702714
703715 /** @type {Handle } */
704716 function onexitsetextheadinglinesequence ( token ) {
705- this . stack [ this . stack . length - 1 ] . depth =
717+ const node = /** @type {Heading } */ ( this . stack [ this . stack . length - 1 ] )
718+
719+ node . depth =
706720 this . sliceSerialize ( token ) . charCodeAt ( 0 ) === codes . equalsTo ? 1 : 2
707721 }
708722
@@ -713,18 +727,16 @@ function compiler(options = {}) {
713727
714728 /** @type {Handle } */
715729 function onenterdata ( token ) {
716- /** @type {Parent } */
717- // @ts -expect-error: assume parent.
718- const parent = this . stack [ this . stack . length - 1 ]
730+ const parent = /** @type {Parent } */ ( this . stack [ this . stack . length - 1 ] )
719731 /** @type {Node } */
720- // @ts -expect-error: assume child.
721732 let tail = parent . children [ parent . children . length - 1 ]
722733
723734 if ( ! tail || tail . type !== 'text' ) {
724735 // Add a new text node.
725736 tail = text ( )
726737 // @ts -expect-error: we’ll add `end` later.
727738 tail . position = { start : point ( token . start ) }
739+ // @ts -expect-error: Assume `text` can be added to `parent`.
728740 parent . children . push ( tail )
729741 }
730742
@@ -735,20 +747,20 @@ function compiler(options = {}) {
735747 function onexitdata ( token ) {
736748 const tail = this . stack . pop ( )
737749 assert ( tail , 'expected a `node` to be on the stack' )
750+ assert ( 'value' in tail , 'expected a `literal` to be on the stack' )
738751 assert ( tail . position , 'expected `node` to have an open position' )
739752 tail . value += this . sliceSerialize ( token )
740753 tail . position . end = point ( token . end )
741754 }
742755
743756 /** @type {Handle } */
744757 function onexitlineending ( token ) {
745- /** @type {Parent } */
746- // @ts -expect-error: supposed to be a parent.
747758 const context = this . stack [ this . stack . length - 1 ]
748759 assert ( context , 'expected `node`' )
749760
750761 // If we’re at a hard break, include the line ending in there.
751762 if ( getData ( 'atHardBreak' ) ) {
763+ assert ( 'children' in context , 'expected `parent`' )
752764 const tail = context . children [ context . children . length - 1 ]
753765 assert ( tail . position , 'expected tail to have a starting position' )
754766 tail . position . end = point ( token . end )
@@ -773,93 +785,117 @@ function compiler(options = {}) {
773785 /** @type {Handle } */
774786 function onexithtmlflow ( ) {
775787 const data = this . resume ( )
776- this . stack [ this . stack . length - 1 ] . value = data
788+ const node = /** @type {HTML } */ ( this . stack [ this . stack . length - 1 ] )
789+ node . value = data
777790 }
778791
779792 /** @type {Handle } */
780793 function onexithtmltext ( ) {
781794 const data = this . resume ( )
782- this . stack [ this . stack . length - 1 ] . value = data
795+ const node = /** @type {HTML } */ ( this . stack [ this . stack . length - 1 ] )
796+ node . value = data
783797 }
784798
785799 /** @type {Handle } */
786800 function onexitcodetext ( ) {
787801 const data = this . resume ( )
788- this . stack [ this . stack . length - 1 ] . value = data
802+ const node = /** @type {InlineCode } */ ( this . stack [ this . stack . length - 1 ] )
803+ node . value = data
789804 }
790805
791806 /** @type {Handle } */
792807 function onexitlink ( ) {
793- const context = this . stack [ this . stack . length - 1 ]
808+ const context = /** @type {Link & {identifier: string, label: string} } */ (
809+ this . stack [ this . stack . length - 1 ]
810+ )
794811
795812 // To do: clean.
796813 if ( getData ( 'inReference' ) ) {
797814 context . type += 'Reference'
815+ // @ts -expect-error: mutate.
798816 context . referenceType = getData ( 'referenceType' ) || 'shortcut'
817+ // @ts -expect-error: mutate.
799818 delete context . url
800819 delete context . title
801820 } else {
821+ // @ts -expect-error: mutate.
802822 delete context . identifier
823+ // @ts -expect-error: mutate.
803824 delete context . label
804- delete context . referenceType
805825 }
806826
807827 setData ( 'referenceType' )
808828 }
809829
810830 /** @type {Handle } */
811831 function onexitimage ( ) {
812- const context = this . stack [ this . stack . length - 1 ]
832+ const context = /** @type {Image & {identifier: string, label: string} } */ (
833+ this . stack [ this . stack . length - 1 ]
834+ )
813835
814836 // To do: clean.
815837 if ( getData ( 'inReference' ) ) {
816838 context . type += 'Reference'
839+ // @ts -expect-error: mutate.
817840 context . referenceType = getData ( 'referenceType' ) || 'shortcut'
841+ // @ts -expect-error: mutate.
818842 delete context . url
819843 delete context . title
820844 } else {
845+ // @ts -expect-error: mutate.
821846 delete context . identifier
847+ // @ts -expect-error: mutate.
822848 delete context . label
823- delete context . referenceType
824849 }
825850
826851 setData ( 'referenceType' )
827852 }
828853
829854 /** @type {Handle } */
830855 function onexitlabeltext ( token ) {
831- this . stack [ this . stack . length - 2 ] . identifier = normalizeIdentifier (
856+ const ancestor = /** @type {(Link|Image) & {identifier: string} } */ (
857+ this . stack [ this . stack . length - 2 ]
858+ )
859+
860+ ancestor . identifier = normalizeIdentifier (
832861 this . sliceSerialize ( token )
833862 ) . toLowerCase ( )
834863 }
835864
836865 /** @type {Handle } */
837866 function onexitlabel ( ) {
838- const fragment = this . stack [ this . stack . length - 1 ]
867+ const fragment = /** @type { Fragment } */ ( this . stack [ this . stack . length - 1 ] )
839868 const value = this . resume ( )
869+ const node =
870+ /** @type {(Link|Image) & {identifier: string, label: string} } */ (
871+ this . stack [ this . stack . length - 1 ]
872+ )
840873
841- this . stack [ this . stack . length - 1 ] . label = value
874+ node . label = value
842875
843876 // Assume a reference.
844877 setData ( 'inReference' , true )
845878
846- if ( this . stack [ this . stack . length - 1 ] . type === 'link' ) {
847- this . stack [ this . stack . length - 1 ] . children = fragment . children
879+ if ( node . type === 'link' ) {
880+ // @ts -expect-error: Assume static phrasing content.
881+ node . children = fragment . children
848882 } else {
849- this . stack [ this . stack . length - 1 ] . alt = value
883+ node . alt = value
850884 }
851885 }
852886
853887 /** @type {Handle } */
854888 function onexitresourcedestinationstring ( ) {
855889 const data = this . resume ( )
856- this . stack [ this . stack . length - 1 ] . url = data
890+ const node = /** @type {Link|Image } */ ( this . stack [ this . stack . length - 1 ] )
891+ node . url = data
857892 }
858893
859894 /** @type {Handle } */
860895 function onexitresourcetitlestring ( ) {
861896 const data = this . resume ( )
862- this . stack [ this . stack . length - 1 ] . title = data
897+ const node = /** @type {Link|Image } */ ( this . stack [ this . stack . length - 1 ] )
898+ node . title = data
863899 }
864900
865901 /** @type {Handle } */
@@ -875,8 +911,11 @@ function compiler(options = {}) {
875911 /** @type {Handle } */
876912 function onexitreferencestring ( token ) {
877913 const label = this . resume ( )
878- this . stack [ this . stack . length - 1 ] . label = label
879- this . stack [ this . stack . length - 1 ] . identifier = normalizeIdentifier (
914+ const node = /** @type {LinkReference|ImageReference } */ (
915+ this . stack [ this . stack . length - 1 ]
916+ )
917+ node . label = label
918+ node . identifier = normalizeIdentifier (
880919 this . sliceSerialize ( token )
881920 ) . toLowerCase ( )
882921 setData ( 'referenceType' , 'full' )
@@ -911,21 +950,23 @@ function compiler(options = {}) {
911950 const tail = this . stack . pop ( )
912951 assert ( tail , 'expected `node`' )
913952 assert ( tail . position , 'expected `node.position`' )
953+ assert ( 'value' in tail , 'expected `node.value`' )
914954 tail . value += value
915955 tail . position . end = point ( token . end )
916956 }
917957
918958 /** @type {Handle } */
919959 function onexitautolinkprotocol ( token ) {
920960 onexitdata . call ( this , token )
921- this . stack [ this . stack . length - 1 ] . url = this . sliceSerialize ( token )
961+ const node = /** @type {Link } */ ( this . stack [ this . stack . length - 1 ] )
962+ node . url = this . sliceSerialize ( token )
922963 }
923964
924965 /** @type {Handle } */
925966 function onexitautolinkemail ( token ) {
926967 onexitdata . call ( this , token )
927- this . stack [ this . stack . length - 1 ] . url =
928- 'mailto:' + this . sliceSerialize ( token )
968+ const node = /** @type { Link } */ ( this . stack [ this . stack . length - 1 ] )
969+ node . url = 'mailto:' + this . sliceSerialize ( token )
929970 }
930971
931972 //
@@ -955,7 +996,6 @@ function compiler(options = {}) {
955996 identifier : '' ,
956997 // @ts -expect-error: we’ve always used `null`.
957998 label : null ,
958- // @ts -expect-error: we’ve always used `null`.
959999 title : null ,
9601000 url : ''
9611001 }
@@ -990,7 +1030,6 @@ function compiler(options = {}) {
9901030
9911031 /** @returns {Link } */
9921032 function link ( ) {
993- // @ts -expect-error: we’ve always used `null`.
9941033 return { type : 'link' , title : null , url : '' , children : [ ] }
9951034 }
9961035
0 commit comments