Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions dev/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -1309,9 +1309,15 @@ function extension(combined, extension) {

case 'enter':
case 'exit': {
const left = combined[key]
const right = extension[key]
if (right) {
Object.assign(combined[key], right)
for (const tokenType in right) {
if (right[tokenType]) {
left[tokenType] = combineHandles(
left[tokenType],
right[tokenType]
)
}
}

break
Expand All @@ -1322,6 +1328,22 @@ function extension(combined, extension) {
}
}

/**
* Creates a new handle that calls `right` first, then falls through to `left`
* only if `right` explicitly returns `false`.
* @param {Handle?} left
* @param {Handle} right
* @returns {Handle}
*/
function combineHandles(left, right) {
if (!left) return right

return function (...parameters) {
const rightResult = right.apply(this, parameters)
return rightResult === false ? left.apply(this, parameters) : rightResult
}
}

/** @type {OnEnterError} */
function defaultOnError(left, right) {
if (left) {
Expand Down
8 changes: 6 additions & 2 deletions dev/lib/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,9 +226,13 @@ export type Handles = Record<string, Handle>
* @param token
* Current token.
* @returns
* Nothing.
* Nothing, if the token was fully handled by this extension and should be ignored by previous extensions / default logic.
* Or `false`, if the token has not been handled by this extension and handling should fall back to preceding logic.
*/
export type Handle = (this: CompileContext, token: Token) => undefined | void
export type Handle = (
this: CompileContext,
token: Token
) => undefined | void | false

/**
* Handle the case where the `right` token is open, but it is closed (by the
Expand Down
5 changes: 4 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,10 @@ Handle a token (TypeScript type).

###### Returns

Nothing (`undefined`).
Nothing, if the token was fully handled and should be ignored by previous
extensions / default logic.
Or `false`, if the token has not been handled here and the parser should fall
back to preceding logic.

### `OnEnterError`

Expand Down
45 changes: 45 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,51 @@ test('fromMarkdown', async function (t) {
)
})

await t.test(
'should allow extension handlers to fall through',
async function () {
assert.deepEqual(
fromMarkdown('a\nb', {
mdastExtensions: [
{
enter: {
paragraph() {
return false
}
}
}
]
}),
{
type: 'root',
children: [
{
type: 'paragraph',
children: [
{
type: 'text',
value: 'a\nb',
position: {
start: {line: 1, column: 1, offset: 0},
end: {line: 2, column: 2, offset: 3}
}
}
],
position: {
start: {line: 1, column: 1, offset: 0},
end: {line: 2, column: 2, offset: 3}
}
}
],
position: {
start: {line: 1, column: 1, offset: 0},
end: {line: 2, column: 2, offset: 3}
}
}
)
}
)

await t.test('should support multiple extensions', async function () {
assert.deepEqual(
fromMarkdown('a\nb', {
Expand Down