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