Skip to content

Commit d617634

Browse files
committed
Add support for improved exit error handling
Related-to: 752dc22.
1 parent 77208c8 commit d617634

File tree

3 files changed

+51
-11
lines changed

3 files changed

+51
-11
lines changed

dev/index.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77
* @typedef {import('./lib/index.js').Transform} Transform
88
* @typedef {import('./lib/index.js').Token} Token
99
* @typedef {import('./lib/index.js').CompileContext} CompileContext
10-
* @typedef {import('./lib/index.js').OnError} OnError
10+
* @typedef {import('./lib/index.js').OnEnterError} OnEnterError
11+
* @typedef {import('./lib/index.js').OnExitError} OnExitError
12+
*
13+
* @typedef {import('./lib/index.js').OnEnterError} OnError
14+
* To do: deprecate next major.
1115
*/
1216

1317
export {fromMarkdown} from './lib/index.js'

dev/lib/index.js

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,13 @@
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
@@ -68,9 +69,9 @@
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} */
11341145
function defaultOnError(left, right) {
11351146
if (left) {
11361147
throw new Error(

test/index.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,31 @@ test('mdast-util-from-markdown', (t) => {
288288
'should crash when closing a token when a different one is open'
289289
)
290290

291+
t.throws(
292+
() => {
293+
fromMarkdown('a', {
294+
mdastExtensions: [
295+
{
296+
exit: {
297+
paragraph(token) {
298+
this.exit(
299+
Object.assign({}, token, {type: 'lol'}),
300+
function (a, b) {
301+
t.equal(a.type, 'lol')
302+
t.equal(b.type, 'paragraph')
303+
throw new Error('problem')
304+
}
305+
)
306+
}
307+
}
308+
}
309+
]
310+
})
311+
},
312+
/problem/,
313+
'should crash when closing a token when a different one is open with a custom handler'
314+
)
315+
291316
t.deepEqual(
292317
fromMarkdown('<tel:123>').children[0],
293318
{

0 commit comments

Comments
 (0)