diff --git a/dev/index.js b/dev/index.js index 8d41fb2..d74e04d 100644 --- a/dev/index.js +++ b/dev/index.js @@ -9,4 +9,4 @@ * @typedef {import('./lib/index.js').CompileContext} CompileContext */ -export {fromMarkdown} from './lib/index.js' +export {fromMarkdown, md} from './lib/index.js' diff --git a/dev/lib/index.js b/dev/lib/index.js index 13a2395..c7c0a98 100644 --- a/dev/lib/index.js +++ b/dev/lib/index.js @@ -2,8 +2,10 @@ * @typedef {import('micromark-util-types').Encoding} Encoding * @typedef {import('micromark-util-types').Event} Event * @typedef {import('micromark-util-types').ParseOptions} ParseOptions + * @typedef {import('micromark-util-types').State} State * @typedef {import('micromark-util-types').Token} Token * @typedef {import('micromark-util-types').TokenizeContext} TokenizeContext + * @typedef {import('micromark-util-types').Tokenizer} Tokenizer * @typedef {import('micromark-util-types').Value} Value * @typedef {import('unist').Parent} UnistParent * @typedef {import('unist').Point} Point @@ -1142,3 +1144,41 @@ function extension(combined, extension) { } } } + +/** + * @param {TemplateStringsArray} strings + * @param {...Node} values + * @returns {Root} + */ +export function md(strings, ...values) { + // Interleave strings with U+FFFC OBJECT REPLACEMENT CHARACTER. + return fromMarkdown(strings.join('\uFFFC'), { + extensions: [{text: {0xff_fc: {tokenize}}}], + mdastExtensions: [{enter: {expression}}] + }) + + /** @type {Tokenizer} */ + function tokenize(effects, ok) { + return start + + /** @type {State} */ + function start(code) { + effects.enter('expression') + effects.consume(code) + effects.exit('expression') + return ok + } + } + + /** + * @this {CompileContext} + * @returns {void} + */ + function expression() { + const parent = this.stack[this.stack.length - 1] + assert(parent, 'expected `parent`') + assert('children' in parent, 'expected `parent`') + // @ts-expect-error: Assume `Node` can exist as a child of `parent`. + parent.children.push(values.shift()) + } +} diff --git a/test/index.js b/test/index.js index fdf1a9a..97c3ed4 100644 --- a/test/index.js +++ b/test/index.js @@ -3,9 +3,9 @@ */ import assert from 'assert' -import {Buffer} from 'node:buffer' import fs from 'fs' import path from 'path' +import {Buffer} from 'node:buffer' import test from 'tape' import {unified} from 'unified' import rehypeParse from 'rehype-parse' @@ -14,7 +14,7 @@ import {toHast} from 'mdast-util-to-hast' import {toString} from 'mdast-util-to-string' import {toHtml} from 'hast-util-to-html' import {commonmark} from 'commonmark.json' -import {fromMarkdown} from '../dev/index.js' +import {fromMarkdown, md} from '../dev/index.js' const join = path.join @@ -1012,6 +1012,55 @@ test('mdast-util-from-markdown', (t) => { 'should parse a thematic break' ) + t.deepEqual( + md`*${fromMarkdown('a*b')}*`.children[0], + { + type: 'paragraph', + children: [ + { + type: 'emphasis', + children: [ + { + type: 'root', + children: [ + { + type: 'paragraph', + children: [ + { + type: 'text', + value: 'a*b', + position: { + start: {line: 1, column: 1, offset: 0}, + end: {line: 1, column: 4, offset: 3} + } + } + ], + position: { + start: {line: 1, column: 1, offset: 0}, + end: {line: 1, column: 4, offset: 3} + } + } + ], + position: { + start: {line: 1, column: 1, offset: 0}, + end: {line: 1, column: 4, offset: 3} + } + } + ], + position: { + start: {line: 1, column: 1, offset: 0}, + end: {line: 1, column: 4, offset: 3} + } + } + ], + position: { + start: {line: 1, column: 1, offset: 0}, + end: {line: 1, column: 4, offset: 3} + } + }, + 'should substitute an expression' + ) + t.end() })