Support MFM tag options #5

Merged
nbsp merged 2 commits from options into master 2022-07-08 10:07:49 +00:00
2 changed files with 47 additions and 21 deletions

View file

@ -3,38 +3,54 @@ export default {
{ {
name: 'mfm', name: 'mfm',
level: 'inline', level: 'inline',
start(src) { return src.match(/\$\[/)?.index }, start (src) { return src.match(/\$\[/)?.index },
tokenizer (src, tokens) { tokenizer (src, tokens) {
const rule = /^\$\[([\w\d]+) (.+)\]$/ const rule = /^\$\[(?<markup>[\w\d]+)(?:\.(?<options>\S+))? (?<text>.+)\]$/
const match = rule.exec(src) const match = rule.exec(src)
if (match) { if (match) {
const token = { const token = {
type: 'mfm', type: 'mfm',
raw: match[0], raw: match[0],
markup: match[1], markup: match.groups.markup,
text: match[2], options: match.groups.options,
tokens: [] text: match.groups.text,
tokens: [],
} }
this.lexer.inline(token.text, token.tokens) this.lexer.inline(token.text, token.tokens)
return token return token
} }
}, },
renderer (token) { renderer (token) {
const el = tokenClass => `<span style="display: inline-block" class="${tokenClass}">${this.parser.parseInline(token.tokens)}</span>` let options = {}
if (token.options) {
options = token.options.split(',').reduce((i, opt) => {
i[opt.split('=')[0]] = opt.split('=')[1] || true
return i
}, {})
}
const el = (mfmClass, mfmStyle = '') => `<span style="display: inline-block;${mfmStyle}" class="${mfmClass}">${this.parser.parseInline(token.tokens)}</span>`
switch (token.markup) { switch (token.markup) {
case 'x2': case 'x2': {
return el('x2') return el('x2')
break }
case 'twitch': case 'twitch': {
return el('twitch') const speed = options.speed || '0.5s'
break return el('twitch', ` animation: mfm-twitch ${speed} ease infinite;`)
case 'sparkle': }
return el('sparkle') case 'sparkle': {
break return el('sparkle')
default: }
return `$[${token.markup} ${this.parser.parseInline(token.tokens)}]` case 'spin': {
const direction = options.left ? 'reverse' : options.alternate ? 'alternate' : 'normal'
const anime = options.x ? 'mfm-spinX' : options.y ? 'mfm-spinY' : 'mfm-spin'
const speed = options.speed || '1.5s'
return el('spin', ` animation: ${anime} ${speed} linear infinite; animation-direction: ${direction};`)
}
default: {
return `$[${token.markup} ${this.parser.parseInline(token.tokens)}]`
}
} }
}, },
}, },
] ],
} }

View file

@ -4,16 +4,26 @@ import markedMfm from '../src/index.js'
describe('marked-mfm', () => { describe('marked-mfm', () => {
test('inline', () => { test('inline', () => {
marked.use(markedMfm) marked.use(markedMfm)
expect(marked('$[x2 this text is bigger]')).toBe('<p><span style="display: inline-block" class="x2">this text is bigger</span></p>\n') expect(marked('$[x2 this text is bigger]')).toBe('<p><span style="display: inline-block;" class="x2">this text is bigger</span></p>\n')
}) })
test('nested', () => { test('nested', () => {
marked.use(markedMfm) marked.use(markedMfm)
expect(marked('$[twitch twitch $[sparkle sparkle]]')).toBe('<p><span style="display: inline-block" class="twitch">twitch <span style="display: inline-block" class="sparkle">sparkle</span></span></p>\n') expect(marked('$[x2 x2 $[sparkle sparkle]]')).toBe('<p><span style="display: inline-block;" class="x2">x2 <span style="display: inline-block;" class="sparkle">sparkle</span></span></p>\n')
}) })
test('invalid', () => { test('invalid', () => {
marked.use(markedMfm) marked.use(markedMfm)
expect(marked('$[invalid $[x2 test]]')).toBe('<p>$[invalid <span style="display: inline-block" class="x2">test</span>]</p>\n') expect(marked('$[invalid $[x2 test]]')).toBe('<p>$[invalid <span style="display: inline-block;" class="x2">test</span>]</p>\n')
})
test('one option', () => {
marked.use(markedMfm)
expect(marked('$[twitch.speed=2s test]')).toBe('<p><span style="display: inline-block; animation: mfm-twitch 2s ease infinite;" class="twitch">test</span></p>\n')
})
test('multiple options', () => {
marked.use(markedMfm)
expect(marked('$[spin.alternate,speed=0.5s test]')).toBe('<p><span style="display: inline-block; animation: mfm-spin 0.5s linear infinite; animation-direction: alternate;" class="spin">test</span></p>\n')
}) })
}) })