2021-04-03 12:04:53 +00:00
|
|
|
|
import assert from 'assert';
|
2021-06-26 14:48:46 +00:00
|
|
|
|
import * as mfm from '../src/index';
|
2021-04-03 12:04:53 +00:00
|
|
|
|
import {
|
2021-06-07 14:27:45 +00:00
|
|
|
|
TEXT, CENTER, FN, UNI_EMOJI, MENTION, EMOJI_CODE, HASHTAG, N_URL, BOLD, SMALL, ITALIC, STRIKE, QUOTE, MATH_BLOCK, SEARCH, CODE_BLOCK, LINK, INLINE_CODE, MATH_INLINE
|
2021-06-26 14:48:46 +00:00
|
|
|
|
} from '../src/index';
|
2021-04-03 12:04:53 +00:00
|
|
|
|
|
2021-04-15 04:51:23 +00:00
|
|
|
|
describe('PlainParser', () => {
|
|
|
|
|
describe('text', () => {
|
|
|
|
|
it('basic', () => {
|
|
|
|
|
const input = 'abc';
|
|
|
|
|
const output = [TEXT('abc')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parsePlain(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('ignore hashtag', () => {
|
|
|
|
|
const input = 'abc#abc';
|
|
|
|
|
const output = [TEXT('abc#abc')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parsePlain(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('keycap number sign', () => {
|
|
|
|
|
const input = 'abc#️⃣abc';
|
|
|
|
|
const output = [TEXT('abc'), UNI_EMOJI('#️⃣'), TEXT('abc')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parsePlain(input), output);
|
|
|
|
|
});
|
|
|
|
|
});
|
2021-06-05 07:46:54 +00:00
|
|
|
|
|
|
|
|
|
describe('emoji', () => {
|
|
|
|
|
it('basic', () => {
|
|
|
|
|
const input = ':foo:';
|
|
|
|
|
const output = [EMOJI_CODE('foo')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parsePlain(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('between texts', () => {
|
|
|
|
|
const input = 'foo:bar:baz';
|
|
|
|
|
const output = [TEXT('foo'), EMOJI_CODE('bar'), TEXT('baz')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parsePlain(input), output);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('disallow other syntaxes', () => {
|
|
|
|
|
const input = 'foo **bar** baz';
|
|
|
|
|
const output = [TEXT('foo **bar** baz')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parsePlain(input), output);
|
|
|
|
|
});
|
2021-04-15 04:51:23 +00:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('FullParser', () => {
|
2021-04-03 12:04:53 +00:00
|
|
|
|
describe('text', () => {
|
2021-04-03 12:34:08 +00:00
|
|
|
|
it('普通のテキストを入力すると1つのテキストノードが返される', () => {
|
2021-04-03 12:04:53 +00:00
|
|
|
|
const input = 'abc';
|
|
|
|
|
const output = [TEXT('abc')];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('quote', () => {
|
2021-04-03 12:34:08 +00:00
|
|
|
|
it('1行の引用ブロックを使用できる', () => {
|
2021-04-03 12:04:53 +00:00
|
|
|
|
const input = '> abc';
|
|
|
|
|
const output = [
|
|
|
|
|
QUOTE([
|
|
|
|
|
TEXT('abc')
|
|
|
|
|
])
|
|
|
|
|
];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
2021-04-03 12:34:08 +00:00
|
|
|
|
it('複数行の引用ブロックを使用できる', () => {
|
2021-04-03 12:04:53 +00:00
|
|
|
|
const input = `
|
|
|
|
|
> abc
|
|
|
|
|
> 123
|
|
|
|
|
`;
|
|
|
|
|
const output = [
|
|
|
|
|
QUOTE([
|
|
|
|
|
TEXT('abc\n123')
|
|
|
|
|
])
|
|
|
|
|
];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
2021-04-03 12:34:08 +00:00
|
|
|
|
it('引用ブロックはブロックをネストできる', () => {
|
2021-04-03 12:04:53 +00:00
|
|
|
|
const input = `
|
|
|
|
|
> <center>
|
|
|
|
|
> a
|
|
|
|
|
> </center>
|
|
|
|
|
`;
|
|
|
|
|
const output = [
|
|
|
|
|
QUOTE([
|
|
|
|
|
CENTER([
|
|
|
|
|
TEXT('a')
|
|
|
|
|
])
|
|
|
|
|
])
|
|
|
|
|
];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
2021-04-03 12:34:08 +00:00
|
|
|
|
it('引用ブロックはインライン構文を含んだブロックをネストできる', () => {
|
2021-04-03 12:04:53 +00:00
|
|
|
|
const input = `
|
|
|
|
|
> <center>
|
|
|
|
|
> I'm @ai, An bot of misskey!
|
|
|
|
|
> </center>
|
|
|
|
|
`;
|
|
|
|
|
const output = [
|
|
|
|
|
QUOTE([
|
|
|
|
|
CENTER([
|
|
|
|
|
TEXT('I\'m '),
|
|
|
|
|
MENTION('ai', null, '@ai'),
|
|
|
|
|
TEXT(', An bot of misskey!'),
|
|
|
|
|
])
|
|
|
|
|
])
|
|
|
|
|
];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
2021-04-17 06:35:07 +00:00
|
|
|
|
it('複数行の引用ブロックでは空行を含めることができる', () => {
|
|
|
|
|
const input = `
|
|
|
|
|
> abc
|
|
|
|
|
>
|
|
|
|
|
> 123
|
|
|
|
|
`;
|
|
|
|
|
const output = [
|
|
|
|
|
QUOTE([
|
|
|
|
|
TEXT('abc\n\n123')
|
|
|
|
|
])
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
it('1行の引用ブロックを空行にはできない', () => {
|
2021-07-31 06:12:43 +00:00
|
|
|
|
const input = '> ';
|
2021-04-17 06:35:07 +00:00
|
|
|
|
const output = [
|
|
|
|
|
TEXT('> ')
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
2021-06-12 03:53:11 +00:00
|
|
|
|
it('引用ブロックの後ろの空行は無視される', () => {
|
|
|
|
|
const input = `
|
|
|
|
|
> foo
|
|
|
|
|
> bar
|
|
|
|
|
|
|
|
|
|
hoge`;
|
|
|
|
|
const output = [
|
|
|
|
|
QUOTE([
|
|
|
|
|
TEXT('foo\nbar')
|
|
|
|
|
]),
|
|
|
|
|
TEXT('hoge')
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('search', () => {
|
2021-04-03 12:34:08 +00:00
|
|
|
|
describe('検索構文を使用できる', () => {
|
2021-04-03 12:04:53 +00:00
|
|
|
|
it('Search', () => {
|
|
|
|
|
const input = 'MFM 書き方 123 Search';
|
|
|
|
|
const output = [
|
2021-04-10 09:09:44 +00:00
|
|
|
|
SEARCH('MFM 書き方 123', input)
|
2021-04-03 12:04:53 +00:00
|
|
|
|
];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
|
|
|
|
it('[Search]', () => {
|
|
|
|
|
const input = 'MFM 書き方 123 [Search]';
|
|
|
|
|
const output = [
|
2021-04-10 09:09:44 +00:00
|
|
|
|
SEARCH('MFM 書き方 123', input)
|
2021-04-03 12:04:53 +00:00
|
|
|
|
];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
|
|
|
|
it('search', () => {
|
|
|
|
|
const input = 'MFM 書き方 123 search';
|
|
|
|
|
const output = [
|
2021-04-10 09:09:44 +00:00
|
|
|
|
SEARCH('MFM 書き方 123', input)
|
2021-04-03 12:04:53 +00:00
|
|
|
|
];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
|
|
|
|
it('[search]', () => {
|
|
|
|
|
const input = 'MFM 書き方 123 [search]';
|
|
|
|
|
const output = [
|
2021-04-10 09:09:44 +00:00
|
|
|
|
SEARCH('MFM 書き方 123', input)
|
2021-04-03 12:04:53 +00:00
|
|
|
|
];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
|
|
|
|
it('検索', () => {
|
|
|
|
|
const input = 'MFM 書き方 123 検索';
|
|
|
|
|
const output = [
|
2021-04-10 09:09:44 +00:00
|
|
|
|
SEARCH('MFM 書き方 123', input)
|
2021-04-03 12:04:53 +00:00
|
|
|
|
];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
|
|
|
|
it('[検索]', () => {
|
|
|
|
|
const input = 'MFM 書き方 123 [検索]';
|
|
|
|
|
const output = [
|
2021-04-10 09:09:44 +00:00
|
|
|
|
SEARCH('MFM 書き方 123', input)
|
2021-04-03 12:04:53 +00:00
|
|
|
|
];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
|
|
|
|
});
|
2021-04-03 12:34:08 +00:00
|
|
|
|
it('ブロックの前後にあるテキストが正しく解釈される', () => {
|
2021-04-03 12:04:53 +00:00
|
|
|
|
const input = 'abc\nhoge piyo bebeyo 検索\n123';
|
|
|
|
|
const output = [
|
|
|
|
|
TEXT('abc'),
|
|
|
|
|
SEARCH('hoge piyo bebeyo', 'hoge piyo bebeyo 検索'),
|
|
|
|
|
TEXT('123')
|
|
|
|
|
];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('code block', () => {
|
2021-04-03 12:34:08 +00:00
|
|
|
|
it('コードブロックを使用できる', () => {
|
2021-04-03 12:04:53 +00:00
|
|
|
|
const input = '```\nabc\n```';
|
|
|
|
|
const output = [CODE_BLOCK('abc', null)];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
2021-06-05 07:23:49 +00:00
|
|
|
|
|
2021-04-03 12:34:08 +00:00
|
|
|
|
it('コードブロックには複数行のコードを入力できる', () => {
|
2021-04-03 12:04:53 +00:00
|
|
|
|
const input = '```\na\nb\nc\n```';
|
|
|
|
|
const output = [CODE_BLOCK('a\nb\nc', null)];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
2021-06-05 07:23:49 +00:00
|
|
|
|
|
2021-04-03 12:34:08 +00:00
|
|
|
|
it('コードブロックは言語を指定できる', () => {
|
2021-04-03 12:04:53 +00:00
|
|
|
|
const input = '```js\nconst a = 1;\n```';
|
|
|
|
|
const output = [CODE_BLOCK('const a = 1;', 'js')];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
2021-06-05 07:23:49 +00:00
|
|
|
|
|
2021-04-03 12:34:08 +00:00
|
|
|
|
it('ブロックの前後にあるテキストが正しく解釈される', () => {
|
2021-04-03 12:04:53 +00:00
|
|
|
|
const input = 'abc\n```\nconst abc = 1;\n```\n123';
|
|
|
|
|
const output = [
|
|
|
|
|
TEXT('abc'),
|
|
|
|
|
CODE_BLOCK('const abc = 1;', null),
|
|
|
|
|
TEXT('123')
|
|
|
|
|
];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
2021-06-05 07:23:49 +00:00
|
|
|
|
|
|
|
|
|
it('ignore internal marker', () => {
|
|
|
|
|
const input = '```\naaa```bbb\n```';
|
|
|
|
|
const output = [CODE_BLOCK('aaa```bbb', null)];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('trim after line break', () => {
|
|
|
|
|
const input = '```\nfoo\n```\nbar';
|
|
|
|
|
const output = [
|
|
|
|
|
CODE_BLOCK('foo', null),
|
|
|
|
|
TEXT('bar'),
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('mathBlock', () => {
|
2021-04-03 12:34:08 +00:00
|
|
|
|
it('1行の数式ブロックを使用できる', () => {
|
|
|
|
|
const input = '\\[math1\\]';
|
|
|
|
|
const output = [
|
|
|
|
|
MATH_BLOCK('math1')
|
|
|
|
|
];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:34:08 +00:00
|
|
|
|
});
|
|
|
|
|
it('ブロックの前後にあるテキストが正しく解釈される', () => {
|
|
|
|
|
const input = 'abc\n\\[math1\\]\n123';
|
2021-04-03 12:04:53 +00:00
|
|
|
|
const output = [
|
|
|
|
|
TEXT('abc'),
|
2021-04-03 12:34:08 +00:00
|
|
|
|
MATH_BLOCK('math1'),
|
|
|
|
|
TEXT('123')
|
|
|
|
|
];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:34:08 +00:00
|
|
|
|
});
|
|
|
|
|
it('行末以外に閉じタグがある場合はマッチしない', () => {
|
|
|
|
|
const input = '\\[aaa\\]after';
|
|
|
|
|
const output = [
|
|
|
|
|
TEXT('\\[aaa\\]after')
|
2021-04-03 12:04:53 +00:00
|
|
|
|
];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
2021-04-03 12:34:08 +00:00
|
|
|
|
it('行頭以外に開始タグがある場合はマッチしない', () => {
|
|
|
|
|
const input = 'before\\[aaa\\]';
|
2021-04-03 12:04:53 +00:00
|
|
|
|
const output = [
|
2021-04-03 12:34:08 +00:00
|
|
|
|
TEXT('before\\[aaa\\]')
|
2021-04-03 12:04:53 +00:00
|
|
|
|
];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('center', () => {
|
|
|
|
|
it('single text', () => {
|
|
|
|
|
const input = '<center>abc</center>';
|
|
|
|
|
const output = [
|
|
|
|
|
CENTER([
|
|
|
|
|
TEXT('abc')
|
|
|
|
|
])
|
|
|
|
|
];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
|
|
|
|
it('multiple text', () => {
|
|
|
|
|
const input = 'before\n<center>\nabc\n123\n\npiyo\n</center>\nafter';
|
|
|
|
|
const output = [
|
|
|
|
|
TEXT('before'),
|
|
|
|
|
CENTER([
|
|
|
|
|
TEXT('abc\n123\n\npiyo')
|
|
|
|
|
]),
|
|
|
|
|
TEXT('after')
|
|
|
|
|
];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('emoji code', () => {
|
|
|
|
|
it('basic', () => {
|
|
|
|
|
const input = ':abc:';
|
|
|
|
|
const output = [EMOJI_CODE('abc')];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('unicode emoji', () => {
|
|
|
|
|
it('basic', () => {
|
|
|
|
|
const input = '今起きた😇';
|
|
|
|
|
const output = [TEXT('今起きた'), UNI_EMOJI('😇')];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
2021-04-15 04:51:23 +00:00
|
|
|
|
|
|
|
|
|
it('keycap number sign', () => {
|
|
|
|
|
const input = 'abc#️⃣123';
|
|
|
|
|
const output = [TEXT('abc'), UNI_EMOJI('#️⃣'), TEXT('123')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('big', () => {
|
|
|
|
|
it('basic', () => {
|
|
|
|
|
const input = '***abc***';
|
|
|
|
|
const output = [
|
|
|
|
|
FN('tada', { }, [
|
|
|
|
|
TEXT('abc')
|
|
|
|
|
])
|
|
|
|
|
];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
|
|
|
|
it('内容にはインライン構文を利用できる', () => {
|
|
|
|
|
const input = '***123**abc**123***';
|
|
|
|
|
const output = [
|
|
|
|
|
FN('tada', { }, [
|
|
|
|
|
TEXT('123'),
|
|
|
|
|
BOLD([
|
|
|
|
|
TEXT('abc')
|
|
|
|
|
]),
|
|
|
|
|
TEXT('123')
|
|
|
|
|
])
|
|
|
|
|
];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
|
|
|
|
it('内容は改行できる', () => {
|
|
|
|
|
const input = '***123\n**abc**\n123***';
|
|
|
|
|
const output = [
|
|
|
|
|
FN('tada', { }, [
|
|
|
|
|
TEXT('123\n'),
|
|
|
|
|
BOLD([
|
|
|
|
|
TEXT('abc')
|
|
|
|
|
]),
|
|
|
|
|
TEXT('\n123')
|
|
|
|
|
])
|
|
|
|
|
];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
2021-09-29 15:39:14 +00:00
|
|
|
|
describe('bold tag', () => {
|
|
|
|
|
it('basic', () => {
|
|
|
|
|
const input = '<b>abc</b>';
|
|
|
|
|
const output = [
|
|
|
|
|
BOLD([
|
|
|
|
|
TEXT('abc')
|
|
|
|
|
])
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
it('inline syntax allowed inside', () => {
|
|
|
|
|
const input = '<b>123~~abc~~123</b>';
|
|
|
|
|
const output = [
|
|
|
|
|
BOLD([
|
|
|
|
|
TEXT('123'),
|
|
|
|
|
STRIKE([
|
|
|
|
|
TEXT('abc')
|
|
|
|
|
]),
|
|
|
|
|
TEXT('123')
|
|
|
|
|
])
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
it('line breaks', () => {
|
|
|
|
|
const input = '<b>123\n~~abc~~\n123</b>';
|
|
|
|
|
const output = [
|
|
|
|
|
BOLD([
|
|
|
|
|
TEXT('123\n'),
|
|
|
|
|
STRIKE([
|
|
|
|
|
TEXT('abc')
|
|
|
|
|
]),
|
|
|
|
|
TEXT('\n123')
|
|
|
|
|
])
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
2021-04-03 12:04:53 +00:00
|
|
|
|
describe('bold', () => {
|
|
|
|
|
it('basic', () => {
|
|
|
|
|
const input = '**abc**';
|
|
|
|
|
const output = [
|
|
|
|
|
BOLD([
|
|
|
|
|
TEXT('abc')
|
|
|
|
|
])
|
|
|
|
|
];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
|
|
|
|
it('内容にはインライン構文を利用できる', () => {
|
|
|
|
|
const input = '**123~~abc~~123**';
|
|
|
|
|
const output = [
|
|
|
|
|
BOLD([
|
|
|
|
|
TEXT('123'),
|
|
|
|
|
STRIKE([
|
|
|
|
|
TEXT('abc')
|
|
|
|
|
]),
|
|
|
|
|
TEXT('123')
|
|
|
|
|
])
|
|
|
|
|
];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
|
|
|
|
it('内容は改行できる', () => {
|
|
|
|
|
const input = '**123\n~~abc~~\n123**';
|
|
|
|
|
const output = [
|
|
|
|
|
BOLD([
|
|
|
|
|
TEXT('123\n'),
|
|
|
|
|
STRIKE([
|
|
|
|
|
TEXT('abc')
|
|
|
|
|
]),
|
|
|
|
|
TEXT('\n123')
|
|
|
|
|
])
|
|
|
|
|
];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('small', () => {
|
|
|
|
|
it('basic', () => {
|
|
|
|
|
const input = '<small>abc</small>';
|
|
|
|
|
const output = [
|
|
|
|
|
SMALL([
|
|
|
|
|
TEXT('abc')
|
|
|
|
|
])
|
|
|
|
|
];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
|
|
|
|
it('内容にはインライン構文を利用できる', () => {
|
|
|
|
|
const input = '<small>abc**123**abc</small>';
|
|
|
|
|
const output = [
|
|
|
|
|
SMALL([
|
|
|
|
|
TEXT('abc'),
|
|
|
|
|
BOLD([
|
|
|
|
|
TEXT('123')
|
|
|
|
|
]),
|
|
|
|
|
TEXT('abc')
|
|
|
|
|
])
|
|
|
|
|
];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
|
|
|
|
it('内容は改行できる', () => {
|
|
|
|
|
const input = '<small>abc\n**123**\nabc</small>';
|
|
|
|
|
const output = [
|
|
|
|
|
SMALL([
|
|
|
|
|
TEXT('abc\n'),
|
|
|
|
|
BOLD([
|
|
|
|
|
TEXT('123')
|
|
|
|
|
]),
|
|
|
|
|
TEXT('\nabc')
|
|
|
|
|
])
|
|
|
|
|
];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
2021-04-15 07:53:55 +00:00
|
|
|
|
describe('italic tag', () => {
|
2021-04-03 12:04:53 +00:00
|
|
|
|
it('basic', () => {
|
|
|
|
|
const input = '<i>abc</i>';
|
|
|
|
|
const output = [
|
|
|
|
|
ITALIC([
|
|
|
|
|
TEXT('abc')
|
|
|
|
|
])
|
|
|
|
|
];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
|
|
|
|
it('内容にはインライン構文を利用できる', () => {
|
|
|
|
|
const input = '<i>abc**123**abc</i>';
|
|
|
|
|
const output = [
|
|
|
|
|
ITALIC([
|
|
|
|
|
TEXT('abc'),
|
|
|
|
|
BOLD([
|
|
|
|
|
TEXT('123')
|
|
|
|
|
]),
|
|
|
|
|
TEXT('abc')
|
|
|
|
|
])
|
|
|
|
|
];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
|
|
|
|
it('内容は改行できる', () => {
|
|
|
|
|
const input = '<i>abc\n**123**\nabc</i>';
|
|
|
|
|
const output = [
|
|
|
|
|
ITALIC([
|
|
|
|
|
TEXT('abc\n'),
|
|
|
|
|
BOLD([
|
|
|
|
|
TEXT('123')
|
|
|
|
|
]),
|
|
|
|
|
TEXT('\nabc')
|
|
|
|
|
])
|
|
|
|
|
];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
2021-04-15 07:53:55 +00:00
|
|
|
|
describe('italic alt 1', () => {
|
2021-04-03 12:04:53 +00:00
|
|
|
|
it('basic', () => {
|
|
|
|
|
const input = '*abc*';
|
|
|
|
|
const output = [
|
|
|
|
|
ITALIC([
|
|
|
|
|
TEXT('abc')
|
|
|
|
|
])
|
|
|
|
|
];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
2021-04-15 07:53:55 +00:00
|
|
|
|
|
|
|
|
|
it('basic 2', () => {
|
|
|
|
|
const input = 'before *abc* after';
|
|
|
|
|
const output = [
|
|
|
|
|
TEXT('before '),
|
|
|
|
|
ITALIC([
|
|
|
|
|
TEXT('abc')
|
|
|
|
|
]),
|
|
|
|
|
TEXT(' after')
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
2021-05-06 15:28:24 +00:00
|
|
|
|
it('ignore a italic syntax if the before char is neither a space nor an LF nor [^a-z0-9]i', () => {
|
|
|
|
|
let input = 'before*abc*after';
|
|
|
|
|
let output: mfm.MfmNode[] = [TEXT('before*abc*after')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
|
|
|
|
|
input = 'あいう*abc*えお';
|
|
|
|
|
output = [
|
|
|
|
|
TEXT('あいう'),
|
|
|
|
|
ITALIC([
|
|
|
|
|
TEXT('abc')
|
|
|
|
|
]),
|
|
|
|
|
TEXT('えお')
|
|
|
|
|
];
|
2021-04-15 07:53:55 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('italic alt 2', () => {
|
|
|
|
|
it('basic', () => {
|
|
|
|
|
const input = '_abc_';
|
|
|
|
|
const output = [
|
|
|
|
|
ITALIC([
|
|
|
|
|
TEXT('abc')
|
|
|
|
|
])
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('basic 2', () => {
|
|
|
|
|
const input = 'before _abc_ after';
|
|
|
|
|
const output = [
|
|
|
|
|
TEXT('before '),
|
|
|
|
|
ITALIC([
|
|
|
|
|
TEXT('abc')
|
|
|
|
|
]),
|
|
|
|
|
TEXT(' after')
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
2021-05-06 15:28:24 +00:00
|
|
|
|
it('ignore a italic syntax if the before char is neither a space nor an LF nor [^a-z0-9]i', () => {
|
|
|
|
|
let input = 'before_abc_after';
|
|
|
|
|
let output: mfm.MfmNode[] = [TEXT('before_abc_after')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
|
|
|
|
|
input = 'あいう_abc_えお';
|
|
|
|
|
output = [
|
|
|
|
|
TEXT('あいう'),
|
|
|
|
|
ITALIC([
|
|
|
|
|
TEXT('abc')
|
|
|
|
|
]),
|
|
|
|
|
TEXT('えお')
|
|
|
|
|
];
|
2021-04-15 07:53:55 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
|
|
|
|
|
2021-09-29 15:39:14 +00:00
|
|
|
|
describe('strike tag', () => {
|
|
|
|
|
it('basic', () => {
|
|
|
|
|
const input = '<s>foo</s>';
|
|
|
|
|
const output = [STRIKE([
|
|
|
|
|
TEXT('foo')
|
|
|
|
|
])];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
2021-06-06 14:54:51 +00:00
|
|
|
|
describe('strike', () => {
|
|
|
|
|
it('basic', () => {
|
|
|
|
|
const input = '~~foo~~';
|
|
|
|
|
const output = [STRIKE([
|
|
|
|
|
TEXT('foo')
|
|
|
|
|
])];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
});
|
2021-04-03 12:04:53 +00:00
|
|
|
|
|
2021-06-05 07:21:22 +00:00
|
|
|
|
describe('inlineCode', () => {
|
|
|
|
|
it('basic', () => {
|
|
|
|
|
const input = '`var x = "Strawberry Pasta";`';
|
|
|
|
|
const output = [INLINE_CODE('var x = "Strawberry Pasta";')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('disallow line break', () => {
|
|
|
|
|
const input = '`foo\nbar`';
|
|
|
|
|
const output = [TEXT('`foo\nbar`')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('disallow ´', () => {
|
|
|
|
|
const input = '`foo´bar`';
|
|
|
|
|
const output = [TEXT('`foo´bar`')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
});
|
2021-04-03 12:04:53 +00:00
|
|
|
|
|
2021-06-07 14:27:45 +00:00
|
|
|
|
describe('mathInline', () => {
|
|
|
|
|
it('basic', () => {
|
|
|
|
|
const input = '\\(x = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}\\)';
|
|
|
|
|
const output = [MATH_INLINE('x = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
});
|
2021-04-03 12:04:53 +00:00
|
|
|
|
|
2021-04-15 06:51:08 +00:00
|
|
|
|
describe('mention', () => {
|
|
|
|
|
it('basic', () => {
|
|
|
|
|
const input = '@abc';
|
|
|
|
|
const output = [MENTION('abc', null, '@abc')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('basic 2', () => {
|
|
|
|
|
const input = 'before @abc after';
|
|
|
|
|
const output = [TEXT('before '), MENTION('abc', null, '@abc'), TEXT(' after')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('basic remote', () => {
|
|
|
|
|
const input = '@abc@misskey.io';
|
|
|
|
|
const output = [MENTION('abc', 'misskey.io', '@abc@misskey.io')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('basic remote 2', () => {
|
|
|
|
|
const input = 'before @abc@misskey.io after';
|
|
|
|
|
const output = [TEXT('before '), MENTION('abc', 'misskey.io', '@abc@misskey.io'), TEXT(' after')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('basic remote 3', () => {
|
|
|
|
|
const input = 'before\n@abc@misskey.io\nafter';
|
|
|
|
|
const output = [TEXT('before\n'), MENTION('abc', 'misskey.io', '@abc@misskey.io'), TEXT('\nafter')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('ignore format of mail address', () => {
|
|
|
|
|
const input = 'abc@example.com';
|
|
|
|
|
const output = [TEXT('abc@example.com')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
2021-05-06 15:28:24 +00:00
|
|
|
|
|
|
|
|
|
it('detect as a mention if the before char is [^a-z0-9]i', () => {
|
|
|
|
|
const input = 'あいう@abc';
|
|
|
|
|
const output = [TEXT('あいう'), MENTION('abc', null, '@abc')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
2021-04-15 06:51:08 +00:00
|
|
|
|
});
|
2021-04-03 12:04:53 +00:00
|
|
|
|
|
|
|
|
|
describe('hashtag', () => {
|
2021-04-15 04:51:23 +00:00
|
|
|
|
it('basic', () => {
|
2021-04-15 05:50:21 +00:00
|
|
|
|
const input = '#abc';
|
|
|
|
|
const output = [HASHTAG('abc')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('basic 2', () => {
|
2021-04-15 04:51:23 +00:00
|
|
|
|
const input = 'before #abc after';
|
|
|
|
|
const output = [TEXT('before '), HASHTAG('abc'), TEXT(' after')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('with keycap number sign', () => {
|
|
|
|
|
const input = '#️⃣abc123 #abc';
|
|
|
|
|
const output = [UNI_EMOJI('#️⃣'), TEXT('abc123 '), HASHTAG('abc')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('with keycap number sign 2', () => {
|
|
|
|
|
const input = `abc
|
|
|
|
|
#️⃣abc`;
|
|
|
|
|
const output = [TEXT('abc\n'), UNI_EMOJI('#️⃣'), TEXT('abc')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
2021-05-06 15:28:24 +00:00
|
|
|
|
it('ignore a hashtag if the before char is neither a space nor an LF nor [^a-z0-9]i', () => {
|
|
|
|
|
let input = 'abc#abc';
|
|
|
|
|
let output: mfm.MfmNode[] = [TEXT('abc#abc')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
|
|
|
|
|
input = 'あいう#abc';
|
|
|
|
|
output = [TEXT('あいう'), HASHTAG('abc')];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
2021-06-05 07:34:38 +00:00
|
|
|
|
|
|
|
|
|
it('ignore comma and period', () => {
|
|
|
|
|
const input = 'Foo #bar, baz #piyo.';
|
|
|
|
|
const output = [TEXT('Foo '), HASHTAG('bar'), TEXT(', baz '), HASHTAG('piyo'), TEXT('.')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('ignore exclamation mark', () => {
|
|
|
|
|
const input = '#Foo!';
|
|
|
|
|
const output = [HASHTAG('Foo'), TEXT('!')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('ignore colon', () => {
|
|
|
|
|
const input = '#Foo:';
|
|
|
|
|
const output = [HASHTAG('Foo'), TEXT(':')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('ignore single quote', () => {
|
|
|
|
|
const input = '#Foo\'';
|
|
|
|
|
const output = [HASHTAG('Foo'), TEXT('\'')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('ignore double quote', () => {
|
|
|
|
|
const input = '#Foo"';
|
|
|
|
|
const output = [HASHTAG('Foo'), TEXT('"')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('ignore square bracket', () => {
|
|
|
|
|
const input = '#Foo]';
|
|
|
|
|
const output = [HASHTAG('Foo'), TEXT(']')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('ignore slash', () => {
|
|
|
|
|
const input = '#foo/bar';
|
|
|
|
|
const output = [HASHTAG('foo'), TEXT('/bar')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
2021-08-28 10:03:01 +00:00
|
|
|
|
it('ignore angle bracket', () => {
|
|
|
|
|
const input = '#foo<bar>';
|
|
|
|
|
const output = [HASHTAG('foo'), TEXT('<bar>')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
2021-06-05 07:34:38 +00:00
|
|
|
|
it('allow including number', () => {
|
|
|
|
|
const input = '#foo123';
|
|
|
|
|
const output = [HASHTAG('foo123')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('with brackets "()"', () => {
|
|
|
|
|
const input = '(#foo)';
|
|
|
|
|
const output = [TEXT('('), HASHTAG('foo'), TEXT(')')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('with brackets "「」"', () => {
|
|
|
|
|
const input = '「#foo」';
|
|
|
|
|
const output = [TEXT('「'), HASHTAG('foo'), TEXT('」')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('with mixed brackets', () => {
|
|
|
|
|
const input = '「#foo(bar)」';
|
|
|
|
|
const output = [TEXT('「'), HASHTAG('foo(bar)'), TEXT('」')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('with brackets "()" (space before)', () => {
|
|
|
|
|
const input = '(bar #foo)';
|
|
|
|
|
const output = [TEXT('(bar '), HASHTAG('foo'), TEXT(')')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('with brackets "「」" (space before)', () => {
|
|
|
|
|
const input = '「bar #foo」';
|
|
|
|
|
const output = [TEXT('「bar '), HASHTAG('foo'), TEXT('」')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('disallow number only', () => {
|
|
|
|
|
const input = '#123';
|
|
|
|
|
const output = [TEXT('#123')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('disallow number only (with brackets)', () => {
|
|
|
|
|
const input = '(#123)';
|
|
|
|
|
const output = [TEXT('(#123)')];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('url', () => {
|
|
|
|
|
it('basic', () => {
|
2021-06-05 06:56:23 +00:00
|
|
|
|
const input = 'https://misskey.io/@ai';
|
|
|
|
|
const output = [
|
|
|
|
|
N_URL('https://misskey.io/@ai'),
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('with other texts', () => {
|
2021-04-03 12:04:53 +00:00
|
|
|
|
const input = 'official instance: https://misskey.io/@ai.';
|
|
|
|
|
const output = [
|
|
|
|
|
TEXT('official instance: '),
|
|
|
|
|
N_URL('https://misskey.io/@ai'),
|
|
|
|
|
TEXT('.')
|
|
|
|
|
];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
2021-06-05 06:56:23 +00:00
|
|
|
|
|
|
|
|
|
it('ignore trailing period', () => {
|
|
|
|
|
const input = 'https://misskey.io/@ai.';
|
|
|
|
|
const output = [
|
|
|
|
|
N_URL('https://misskey.io/@ai'),
|
|
|
|
|
TEXT('.')
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('ignore trailing periods', () => {
|
|
|
|
|
const input = 'https://misskey.io/@ai...';
|
|
|
|
|
const output = [
|
|
|
|
|
N_URL('https://misskey.io/@ai'),
|
|
|
|
|
TEXT('...')
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('with comma', () => {
|
|
|
|
|
const input = 'https://example.com/foo?bar=a,b';
|
|
|
|
|
const output = [
|
|
|
|
|
N_URL('https://example.com/foo?bar=a,b'),
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('ignore trailing comma', () => {
|
|
|
|
|
const input = 'https://example.com/foo, bar';
|
|
|
|
|
const output = [
|
|
|
|
|
N_URL('https://example.com/foo'),
|
|
|
|
|
TEXT(', bar')
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('with brackets', () => {
|
|
|
|
|
const input = 'https://example.com/foo(bar)';
|
|
|
|
|
const output = [
|
|
|
|
|
N_URL('https://example.com/foo(bar)'),
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('ignore parent brackets', () => {
|
|
|
|
|
const input = '(https://example.com/foo)';
|
|
|
|
|
const output = [
|
|
|
|
|
TEXT('('),
|
|
|
|
|
N_URL('https://example.com/foo'),
|
|
|
|
|
TEXT(')'),
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('ignore parent brackets (2)', () => {
|
|
|
|
|
const input = '(foo https://example.com/foo)';
|
|
|
|
|
const output = [
|
|
|
|
|
TEXT('(foo '),
|
|
|
|
|
N_URL('https://example.com/foo'),
|
|
|
|
|
TEXT(')'),
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('ignore parent brackets with internal brackets', () => {
|
|
|
|
|
const input = '(https://example.com/foo(bar))';
|
|
|
|
|
const output = [
|
|
|
|
|
TEXT('('),
|
|
|
|
|
N_URL('https://example.com/foo(bar)'),
|
|
|
|
|
TEXT(')'),
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('ignore parent []', () => {
|
|
|
|
|
const input = 'foo [https://example.com/foo] bar';
|
|
|
|
|
const output = [
|
|
|
|
|
TEXT('foo ['),
|
|
|
|
|
N_URL('https://example.com/foo'),
|
|
|
|
|
TEXT('] bar'),
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('ignore non-ascii characters contained url without angle brackets', () => {
|
|
|
|
|
const input = 'https://大石泉すき.example.com';
|
|
|
|
|
const output = [
|
|
|
|
|
TEXT('https://大石泉すき.example.com'),
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('match non-ascii characters contained url with angle brackets', () => {
|
|
|
|
|
const input = '<https://大石泉すき.example.com>';
|
|
|
|
|
const output = [
|
2021-07-22 11:30:46 +00:00
|
|
|
|
N_URL('https://大石泉すき.example.com', true),
|
2021-06-05 06:56:23 +00:00
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('link', () => {
|
|
|
|
|
it('basic', () => {
|
|
|
|
|
const input = '[official instance](https://misskey.io/@ai).';
|
|
|
|
|
const output = [
|
|
|
|
|
LINK(false, 'https://misskey.io/@ai', [
|
|
|
|
|
TEXT('official instance')
|
|
|
|
|
]),
|
|
|
|
|
TEXT('.')
|
|
|
|
|
];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('silent flag', () => {
|
|
|
|
|
const input = '?[official instance](https://misskey.io/@ai).';
|
|
|
|
|
const output = [
|
|
|
|
|
LINK(true, 'https://misskey.io/@ai', [
|
|
|
|
|
TEXT('official instance')
|
|
|
|
|
]),
|
|
|
|
|
TEXT('.')
|
|
|
|
|
];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
|
|
|
|
|
2021-10-14 11:24:13 +00:00
|
|
|
|
it('with angle brackets url', () => {
|
|
|
|
|
const input = '[official instance](<https://misskey.io/@ai>).';
|
|
|
|
|
const output = [
|
|
|
|
|
LINK(false, 'https://misskey.io/@ai', [
|
|
|
|
|
TEXT('official instance')
|
|
|
|
|
]),
|
|
|
|
|
TEXT('.')
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
2022-01-09 09:21:57 +00:00
|
|
|
|
describe('cannot nest a url in a link label', () => {
|
|
|
|
|
it('basic', () => {
|
|
|
|
|
const input = 'official instance: [https://misskey.io/@ai](https://misskey.io/@ai).';
|
|
|
|
|
const output = [
|
|
|
|
|
TEXT('official instance: '),
|
|
|
|
|
LINK(false, 'https://misskey.io/@ai', [
|
|
|
|
|
TEXT('https://misskey.io/@ai'),
|
|
|
|
|
]),
|
|
|
|
|
TEXT('.'),
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
it('nested', () => {
|
|
|
|
|
const input = 'official instance: [https://misskey.io/@ai**https://misskey.io/@ai**](https://misskey.io/@ai).';
|
|
|
|
|
const output = [
|
|
|
|
|
TEXT('official instance: '),
|
|
|
|
|
LINK(false, 'https://misskey.io/@ai', [
|
|
|
|
|
TEXT('https://misskey.io/@ai'),
|
|
|
|
|
BOLD([
|
|
|
|
|
TEXT('https://misskey.io/@ai'),
|
|
|
|
|
]),
|
|
|
|
|
]),
|
|
|
|
|
TEXT('.'),
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
|
|
|
|
|
2022-01-09 09:21:57 +00:00
|
|
|
|
describe('cannot nest a link in a link label', () => {
|
|
|
|
|
it('basic', () => {
|
|
|
|
|
const input = 'official instance: [[https://misskey.io/@ai](https://misskey.io/@ai)](https://misskey.io/@ai).';
|
|
|
|
|
const output = [
|
|
|
|
|
TEXT('official instance: '),
|
|
|
|
|
LINK(false, 'https://misskey.io/@ai', [
|
|
|
|
|
TEXT('[https://misskey.io/@ai'),
|
|
|
|
|
]),
|
|
|
|
|
TEXT(']('),
|
|
|
|
|
N_URL('https://misskey.io/@ai'),
|
|
|
|
|
TEXT(').'),
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
it('nested', () => {
|
|
|
|
|
const input = 'official instance: [**[https://misskey.io/@ai](https://misskey.io/@ai)**](https://misskey.io/@ai).';
|
|
|
|
|
const output = [
|
|
|
|
|
TEXT('official instance: '),
|
|
|
|
|
LINK(false, 'https://misskey.io/@ai', [
|
|
|
|
|
BOLD([
|
|
|
|
|
TEXT('[https://misskey.io/@ai](https://misskey.io/@ai)'),
|
|
|
|
|
]),
|
|
|
|
|
]),
|
|
|
|
|
TEXT('.'),
|
|
|
|
|
];
|
|
|
|
|
});
|
2021-06-05 06:42:06 +00:00
|
|
|
|
});
|
2021-06-05 07:17:56 +00:00
|
|
|
|
|
2022-01-09 09:21:57 +00:00
|
|
|
|
describe('cannot nest a mention in a link label', () => {
|
|
|
|
|
it('basic', () => {
|
|
|
|
|
const input = '[@example](https://example.com)';
|
|
|
|
|
const output = [
|
|
|
|
|
LINK(false, 'https://example.com', [
|
|
|
|
|
TEXT('@example'),
|
|
|
|
|
]),
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
it('nested', () => {
|
|
|
|
|
const input = '[@example**@example**](https://example.com)';
|
|
|
|
|
const output = [
|
|
|
|
|
LINK(false, 'https://example.com', [
|
|
|
|
|
TEXT('@example'),
|
|
|
|
|
BOLD([
|
|
|
|
|
TEXT('@example'),
|
|
|
|
|
]),
|
|
|
|
|
]),
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
2021-06-26 14:16:09 +00:00
|
|
|
|
});
|
|
|
|
|
|
2021-06-05 07:17:56 +00:00
|
|
|
|
it('with brackets', () => {
|
|
|
|
|
const input = '[foo](https://example.com/foo(bar))';
|
|
|
|
|
const output = [
|
|
|
|
|
LINK(false, 'https://example.com/foo(bar)', [
|
|
|
|
|
TEXT('foo')
|
|
|
|
|
]),
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('with parent brackets', () => {
|
|
|
|
|
const input = '([foo](https://example.com/foo(bar)))';
|
|
|
|
|
const output = [
|
|
|
|
|
TEXT('('),
|
|
|
|
|
LINK(false, 'https://example.com/foo(bar)', [
|
|
|
|
|
TEXT('foo')
|
|
|
|
|
]),
|
|
|
|
|
TEXT(')'),
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
|
|
|
|
|
2021-10-01 13:05:11 +00:00
|
|
|
|
describe('fn', () => {
|
2021-04-18 05:38:15 +00:00
|
|
|
|
it('basic', () => {
|
|
|
|
|
const input = '$[tada abc]';
|
|
|
|
|
const output = [
|
|
|
|
|
FN('tada', { }, [
|
|
|
|
|
TEXT('abc')
|
|
|
|
|
])
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('with a string argument', () => {
|
|
|
|
|
const input = '$[spin.speed=1.1s a]';
|
|
|
|
|
const output = [
|
|
|
|
|
FN('spin', { speed: '1.1s' }, [
|
|
|
|
|
TEXT('a')
|
|
|
|
|
])
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
|
|
|
|
|
2021-06-05 06:42:06 +00:00
|
|
|
|
it('nest', () => {
|
|
|
|
|
const input = '$[spin.speed=1.1s $[shake a]]';
|
|
|
|
|
const output = [
|
|
|
|
|
FN('spin', { speed: '1.1s' }, [
|
|
|
|
|
FN('shake', { }, [
|
|
|
|
|
TEXT('a')
|
|
|
|
|
])
|
|
|
|
|
])
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
|
|
|
|
});
|
2021-10-02 00:26:56 +00:00
|
|
|
|
|
|
|
|
|
it('exists name in the fnNameList', () => {
|
|
|
|
|
const input = '$[spin.speed=1.1s text]';
|
|
|
|
|
const output = [
|
|
|
|
|
FN('spin', { speed: '1.1s' }, [
|
|
|
|
|
TEXT('text')
|
|
|
|
|
])
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input, { fnNameList: ['tada', 'spin'] }), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('not exists name in the fnNameList', () => {
|
|
|
|
|
const input = '$[pope.speed=1.1s text]';
|
|
|
|
|
const output = [
|
|
|
|
|
TEXT('$[pope.speed=1.1s text]')
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input, { fnNameList: ['tada', 'spin'] }), output);
|
|
|
|
|
});
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
|
|
|
|
|
2022-01-05 16:05:37 +00:00
|
|
|
|
describe('nesting limit', () => {
|
|
|
|
|
it('big', () => {
|
|
|
|
|
const input = '<b><b>***abc***</b></b>';
|
|
|
|
|
const output = [
|
|
|
|
|
BOLD([
|
|
|
|
|
BOLD([
|
|
|
|
|
TEXT('**'),
|
|
|
|
|
ITALIC([
|
|
|
|
|
TEXT('abc'),
|
|
|
|
|
]),
|
|
|
|
|
TEXT('**'),
|
|
|
|
|
]),
|
|
|
|
|
]),
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input, { nestLimit: 2 }), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('bold', () => {
|
|
|
|
|
it('basic', () => {
|
|
|
|
|
const input = '<i><i>**abc**</i></i>';
|
|
|
|
|
const output = [
|
|
|
|
|
ITALIC([
|
|
|
|
|
ITALIC([
|
|
|
|
|
TEXT('*'),
|
|
|
|
|
ITALIC([
|
|
|
|
|
TEXT('abc'),
|
|
|
|
|
]),
|
|
|
|
|
TEXT('*'),
|
|
|
|
|
]),
|
|
|
|
|
]),
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input, { nestLimit: 2 }), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('tag', () => {
|
|
|
|
|
const input = '<i><i><b>abc</b></i></i>';
|
|
|
|
|
const output = [
|
|
|
|
|
ITALIC([
|
|
|
|
|
ITALIC([
|
|
|
|
|
TEXT('<b>abc</b>'),
|
|
|
|
|
]),
|
|
|
|
|
]),
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input, { nestLimit: 2 }), output);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('small', () => {
|
|
|
|
|
const input = '<i><i><small>abc</small></i></i>';
|
|
|
|
|
const output = [
|
|
|
|
|
ITALIC([
|
|
|
|
|
ITALIC([
|
|
|
|
|
TEXT('<small>abc</small>'),
|
|
|
|
|
]),
|
|
|
|
|
]),
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input, { nestLimit: 2 }), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('italic', () => {
|
|
|
|
|
const input = '<b><b><i>abc</i></b></b>';
|
|
|
|
|
const output = [
|
|
|
|
|
BOLD([
|
|
|
|
|
BOLD([
|
|
|
|
|
TEXT('<i>abc</i>'),
|
|
|
|
|
]),
|
|
|
|
|
]),
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input, { nestLimit: 2 }), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
describe('strike', () => {
|
|
|
|
|
it('basic', () => {
|
|
|
|
|
const input = '<b><b>~~abc~~</b></b>';
|
|
|
|
|
const output = [
|
|
|
|
|
BOLD([
|
|
|
|
|
BOLD([
|
|
|
|
|
TEXT('~~abc~~'),
|
|
|
|
|
]),
|
|
|
|
|
]),
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input, { nestLimit: 2 }), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('tag', () => {
|
|
|
|
|
const input = '<b><b><s>abc</s></b></b>';
|
|
|
|
|
const output = [
|
|
|
|
|
BOLD([
|
|
|
|
|
BOLD([
|
|
|
|
|
TEXT('<s>abc</s>'),
|
|
|
|
|
]),
|
|
|
|
|
]),
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input, { nestLimit: 2 }), output);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('hashtag', () => {
|
|
|
|
|
const input = '<b><b>#abc(xyz)</b></b>';
|
|
|
|
|
const output = [
|
|
|
|
|
BOLD([
|
|
|
|
|
BOLD([
|
|
|
|
|
HASHTAG('abc'),
|
|
|
|
|
TEXT('(xyz)'),
|
|
|
|
|
]),
|
|
|
|
|
]),
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input, { nestLimit: 2 }), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('url', () => {
|
|
|
|
|
const input = '<b><b>https://example.com/abc(xyz)</b></b>';
|
|
|
|
|
const output = [
|
|
|
|
|
BOLD([
|
|
|
|
|
BOLD([
|
|
|
|
|
N_URL('https://example.com/abc'),
|
|
|
|
|
TEXT('(xyz)'),
|
|
|
|
|
]),
|
|
|
|
|
]),
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input, { nestLimit: 2 }), output);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('fn', () => {
|
|
|
|
|
const input = '<b><b>$[a b]</b></b>';
|
|
|
|
|
const output = [
|
|
|
|
|
BOLD([
|
|
|
|
|
BOLD([
|
|
|
|
|
TEXT('$[a b]'),
|
|
|
|
|
]),
|
|
|
|
|
]),
|
|
|
|
|
];
|
|
|
|
|
assert.deepStrictEqual(mfm.parse(input, { nestLimit: 2 }), output);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
2021-04-03 12:04:53 +00:00
|
|
|
|
it('composite', () => {
|
|
|
|
|
const input =
|
|
|
|
|
`before
|
|
|
|
|
<center>
|
2021-10-01 13:05:11 +00:00
|
|
|
|
Hello $[tada everynyan! 🎉]
|
2021-04-03 12:04:53 +00:00
|
|
|
|
|
|
|
|
|
I'm @ai, A bot of misskey!
|
|
|
|
|
|
|
|
|
|
https://github.com/syuilo/ai
|
|
|
|
|
</center>
|
|
|
|
|
after`;
|
|
|
|
|
const output = [
|
|
|
|
|
TEXT('before'),
|
|
|
|
|
CENTER([
|
|
|
|
|
TEXT('Hello '),
|
|
|
|
|
FN('tada', { }, [
|
|
|
|
|
TEXT('everynyan! '),
|
|
|
|
|
UNI_EMOJI('🎉')
|
|
|
|
|
]),
|
|
|
|
|
TEXT('\n\nI\'m '),
|
|
|
|
|
MENTION('ai', null, '@ai'),
|
|
|
|
|
TEXT(', A bot of misskey!\n\n'),
|
|
|
|
|
N_URL('https://github.com/syuilo/ai')
|
|
|
|
|
]),
|
|
|
|
|
TEXT('after')
|
|
|
|
|
];
|
2021-04-10 08:31:29 +00:00
|
|
|
|
assert.deepStrictEqual(mfm.parse(input), output);
|
2021-04-03 12:04:53 +00:00
|
|
|
|
});
|
|
|
|
|
});
|