5454 * @typedef {Partial<NormalizedExtension> } Extension
5555 * An mdast extension changes how markdown tokens are turned into mdast.
5656 *
57- * @typedef {(this: Omit<CompileContext, 'sliceSerialize'>, left: Token|undefined, right: Token) => void } OnError
57+ * @typedef {(this: Omit<CompileContext, 'sliceSerialize'>, left: Token|undefined, right: Token) => void } OnEnterError
58+ * @typedef {(this: Omit<CompileContext, 'sliceSerialize'>, left: Token, right: Token) => void } OnExitError
5859 *
5960 * @typedef CompileContext
6061 * mdast compiler context
6162 * @property {Array<Node | Fragment> } stack
62- * @property {Array<[Token, OnError |undefined]> } tokenStack
63+ * @property {Array<[Token, OnEnterError |undefined]> } tokenStack
6364 * @property {(key: string, value?: unknown) => void } setData
6465 * Set data into the key-value store.
6566 * @property {<K extends string>(key: K) => CompileData[K] } getData
6869 * Capture some of the output data.
6970 * @property {(this: CompileContext) => string } resume
7071 * Stop capturing and access the output data.
71- * @property {<N extends Node>(this: CompileContext, node: N, token: Token, onError?: OnError ) => N } enter
72+ * @property {<N extends Node>(this: CompileContext, node: N, token: Token, onError?: OnEnterError ) => N } enter
7273 * Enter a token.
73- * @property {(this: CompileContext, token: Token) => Node } exit
74+ * @property {(this: CompileContext, token: Token, onError?: OnExitError ) => Node } exit
7475 * Exit a token.
7576 * @property {TokenizeContext['sliceSerialize'] } sliceSerialize
7677 * Get the string value of a token.
@@ -535,7 +536,7 @@ function compiler(options = {}) {
535536 * @this {CompileContext}
536537 * @param {N } node
537538 * @param {Token } token
538- * @param {OnError } [errorHandler]
539+ * @param {OnEnterError } [errorHandler]
539540 * @returns {N }
540541 */
541542 function enter ( node , token , errorHandler ) {
@@ -569,8 +570,14 @@ function compiler(options = {}) {
569570 }
570571 }
571572
572- /** @type {CompileContext['exit'] } */
573- function exit ( token ) {
573+ /**
574+ * @type {CompileContext['exit'] }
575+ * @this {CompileContext}
576+ * @param {Token } token
577+ * @param {OnExitError } [onExitError]
578+ * @returns {Node }
579+ */
580+ function exit ( token , onExitError ) {
574581 const node = this . stack . pop ( )
575582 assert ( node , 'expected `node`' )
576583 const open = this . tokenStack . pop ( )
@@ -584,8 +591,12 @@ function compiler(options = {}) {
584591 '): it’s not open'
585592 )
586593 } else if ( open [ 0 ] . type !== token . type ) {
587- const handler = open [ 1 ] || defaultOnError
588- handler . call ( this , token , open [ 0 ] )
594+ if ( onExitError ) {
595+ onExitError . call ( this , token , open [ 0 ] )
596+ } else {
597+ const handler = open [ 1 ] || defaultOnError
598+ handler . call ( this , token , open [ 0 ] )
599+ }
589600 }
590601
591602 assert ( node . type !== 'fragment' , 'unexpected fragment `exit`ed' )
@@ -1130,7 +1141,7 @@ function extension(combined, extension) {
11301141 }
11311142}
11321143
1133- /** @type {OnError } */
1144+ /** @type {OnEnterError } */
11341145function defaultOnError ( left , right ) {
11351146 if ( left ) {
11361147 throw new Error (
0 commit comments