[MFM] Better syntax parsing

Allow nesting by same tag
This commit is contained in:
syuilo 2019-01-31 12:23:45 +09:00
parent bb92158dff
commit b515cc90e9
No known key found for this signature in database
GPG key ID: BDC4C49D06AB9D69
2 changed files with 18 additions and 3 deletions

View file

@ -108,20 +108,20 @@ export const mfmLanguage = P.createLanguage({
strike: r => P.regexp(/~~(.+?)~~/, 1).map(x => createTree('strike', r.inline.atLeast(1).tryParse(x), {})), strike: r => P.regexp(/~~(.+?)~~/, 1).map(x => createTree('strike', r.inline.atLeast(1).tryParse(x), {})),
motion: r => { motion: r => {
const paren = P.regexp(/\(\(\(([\s\S]+?)\)\)\)/, 1); const paren = P.regexp(/\(\(\(([\s\S]+?)\)\)\)/, 1);
const xml = P.regexp(/<motion>(.+?)<\/motion>/, 1); const xml = P.regexp(/<motion>(.+)<\/motion>/, 1);
return P.alt(paren, xml).map(x => createTree('motion', r.inline.atLeast(1).tryParse(x), {})); return P.alt(paren, xml).map(x => createTree('motion', r.inline.atLeast(1).tryParse(x), {}));
}, },
spin: r => { spin: r => {
return P((input, i) => { return P((input, i) => {
const text = input.substr(i); const text = input.substr(i);
const match = text.match(/^<spin(\s[a-z]+?)?>(.+?)<\/spin>/i); const match = text.match(/^<spin(\s[a-z]+?)?>(.+)<\/spin>/i);
if (!match) return P.makeFailure(i, 'not a spin'); if (!match) return P.makeFailure(i, 'not a spin');
return P.makeSuccess(i + match[0].length, { return P.makeSuccess(i + match[0].length, {
content: match[2], attr: match[1] ? match[1].trim() : null content: match[2], attr: match[1] ? match[1].trim() : null
}); });
}).map(x => createTree('spin', r.inline.atLeast(1).tryParse(x.content), { attr: x.attr })); }).map(x => createTree('spin', r.inline.atLeast(1).tryParse(x.content), { attr: x.attr }));
}, },
jump: r => P.regexp(/<jump>(.+?)<\/jump>/, 1).map(x => createTree('jump', r.inline.atLeast(1).tryParse(x), {})), jump: r => P.regexp(/<jump>(.+)<\/jump>/, 1).map(x => createTree('jump', r.inline.atLeast(1).tryParse(x), {})),
flip: r => P.regexp(/<flip>(.+?)<\/flip>/, 1).map(x => createTree('flip', r.inline.atLeast(1).tryParse(x), {})), flip: r => P.regexp(/<flip>(.+?)<\/flip>/, 1).map(x => createTree('flip', r.inline.atLeast(1).tryParse(x), {})),
center: r => r.startOfLine.then(P.regexp(/<center>([\s\S]+?)<\/center>/, 1).map(x => createTree('center', r.inline.atLeast(1).tryParse(x), {}))), center: r => r.startOfLine.then(P.regexp(/<center>([\s\S]+?)<\/center>/, 1).map(x => createTree('center', r.inline.atLeast(1).tryParse(x), {}))),
inlineCode: () => P.regexp(/`([^´\n]+?)`/, 1).map(x => createLeaf('inlineCode', { code: x })), inlineCode: () => P.regexp(/`([^´\n]+?)`/, 1).map(x => createLeaf('inlineCode', { code: x })),

View file

@ -276,6 +276,21 @@ describe('MFM', () => {
}), }),
]); ]);
}); });
it('nested', () => {
const tokens = parse('<spin><spin>:foo:</spin></spin>');
assert.deepStrictEqual(tokens, [
tree('spin', [
tree('spin', [
leaf('emoji', { name: 'foo' })
], {
attr: null
}),
], {
attr: null
}),
]);
});
}); });
it('jump', () => { it('jump', () => {