diff --git a/packages/mdsvex/src/index.ts b/packages/mdsvex/src/index.ts index 075ded39..e70e30a1 100644 --- a/packages/mdsvex/src/index.ts +++ b/packages/mdsvex/src/index.ts @@ -36,6 +36,7 @@ import { smartypants_transformer, highlight_blocks, code_highlight, + escape_brackets, } from './transformers'; function stringify(this: Processor, options = {}) { @@ -77,6 +78,7 @@ export function transform( .use(markdown) .use(mdsvex_parser) .use(external, { target: false, rel: ['nofollow'] }) + .use(escape_brackets) .use(escape_code, { blocks: !!highlight }) .use(extract_frontmatter, [{ type: fm_opts.type, marker: fm_opts.marker }]) .use(parse_frontmatter, { parse: fm_opts.parse, type: fm_opts.type }); diff --git a/packages/mdsvex/src/transformers/index.ts b/packages/mdsvex/src/transformers/index.ts index afa51bb2..417a1736 100644 --- a/packages/mdsvex/src/transformers/index.ts +++ b/packages/mdsvex/src/transformers/index.ts @@ -65,17 +65,17 @@ export function parse_frontmatter({ return transformer; } -// in code nodes replace the character witrh the html entities -// maybe I'll need more of these - -const entites: Array<[RegExp, string]> = [ - [//g, '>'], - [/{/g, '{'], - [/}/g, '}'], -]; - export function escape_code({ blocks }: { blocks: boolean }): Transformer { + // in code nodes replace the character witrh the html entities + // maybe I'll need more of these + + const entites: Array<[RegExp, string]> = [ + [//g, '>'], + [/{/g, '{'], + [/}/g, '}'], + ]; + return function (tree) { if (!blocks) { visit(tree, 'code', escape); @@ -91,6 +91,34 @@ export function escape_code({ blocks }: { blocks: boolean }): Transformer { }; } +// remark-parse already partially escapes <>'s, but then re-emits them raw in the AST, +// which we stringify raw (Should we be?) +export function escape_brackets(): Transformer { + const entites: Array<[RegExp, string]> = [ + // remark-parse does not transform \< + [/\\ to '>', and > to '>' + [/^>$/g, '>'], + // remark-parse transforms < to '<' + [/^<$/g, '<'], + + // svelte templating {}'s -- similar story. + [/^{$/g, '{'], + [/^}$/g, '}'] + ]; + + return function (tree) { + visit(tree, 'text', escape); + + function escape(node) { + for (let i = 0; i < entites.length; i += 1) { + node.value = node.value.replace(entites[i][0], entites[i][1]); + } + } + }; +} + + // special case - process nodes with retext and smartypants // retext plugins can't work generally due to the difficulties in converting between the two trees diff --git a/packages/mdsvex/test/_fixtures/markdown/input/escaped-html-taglikes.md b/packages/mdsvex/test/_fixtures/markdown/input/escaped-html-taglikes.md new file mode 100644 index 00000000..0922b605 --- /dev/null +++ b/packages/mdsvex/test/_fixtures/markdown/input/escaped-html-taglikes.md @@ -0,0 +1,7 @@ +awa \ + +awoo \ diff --git a/packages/mdsvex/test/_fixtures/markdown/output/escaped-html-taglikes.html b/packages/mdsvex/test/_fixtures/markdown/output/escaped-html-taglikes.html new file mode 100644 index 00000000..a870a492 --- /dev/null +++ b/packages/mdsvex/test/_fixtures/markdown/output/escaped-html-taglikes.html @@ -0,0 +1,4 @@ +

awa <hi>

+

awoo <heyoo

+

And what happens when I escape like <this>?

+

This one shouldn't be \