From 0f60653105d5f74dc68567b47b625be985f15337 Mon Sep 17 00:00:00 2001 From: Sol Fisher Romanoff Date: Fri, 8 Jul 2022 20:54:26 +0300 Subject: [PATCH] Fix regex matching of MFM tag --- package.json | 2 +- src/index.js | 19 +++++++++++++++++-- test/index.test.js | 10 ++++++++++ 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 85093d0..0096b01 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "marked-mfm", - "version": "0.1.0", + "version": "0.1.1", "description": "Marked.js extension for Misskey-flavored Markdown", "main": "./src/index.js", "type": "module", diff --git a/src/index.js b/src/index.js index a2b2a86..3888c67 100644 --- a/src/index.js +++ b/src/index.js @@ -5,8 +5,23 @@ export default { level: 'inline', start (src) { return src.match(/\$\[/)?.index }, tokenizer (src, tokens) { - const rule = /^\$\[(?[\w\d]+)(?:\.(?\S+))? (?[\S\s]+)\]$/ - const match = rule.exec(src) + // regex doesn't do well finding MFM tags: it's always either too lazy + // or too greedy. + let level = 0 + let walk = 0 + while (level > 0 || walk === 0) { + if (src[walk] + src[walk + 1] === '$[') { + level++ + walk++ + } else if (src[walk] === ']') { + level-- + } + walk++ + } + + // original regex, now definitely on the correct tag + const rule = /^\$\[(?[\w\d]+)(?:\.(?\S+))? (?[\S\s]+)\]/ + const match = rule.exec(src.slice(0, walk)) if (match) { const token = { type: 'mfm', diff --git a/test/index.test.js b/test/index.test.js index 852c8e8..8189d7d 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -17,6 +17,16 @@ describe('marked-mfm', () => { expect(marked('$[x2 x2 $[sparkle sparkle]]')).toBe('

x2 sparkle

\n') }) + test('lazy matching', () => { + marked.use(markedMfm) + expect(marked('$[x2 one] $[x2 two]')).toBe('

one two

\n') + }) + + test('nested & lazy matching', () => { + marked.use(markedMfm) + expect(marked('$[x2 one $[x2 two]] $[x2 three]')).toBe('

one two three

\n') + }) + test('invalid', () => { marked.use(markedMfm) expect(marked('$[invalid $[x2 test]]')).toBe('

$[invalid test]

\n')