diff --git a/src/client/components/mfm.ts b/src/client/components/mfm.ts
index e1216614a6..aa9ff0952d 100644
--- a/src/client/components/mfm.ts
+++ b/src/client/components/mfm.ts
@@ -77,9 +77,57 @@ export default defineComponent({
}, genEl(token.children));
}
- case 'big': {
- return h('strong', {
- style: `display: inline-block; font-size: 150%;` + (this.$store.state.device.animatedMfm ? 'animation: anime-tada 1s linear infinite both;' : ''),
+ case 'fn': {
+ // TODO: CSSを文字列で組み立てていくと token.node.props.args.~~~ 経由でCSSインジェクションできるのでよしなにやる
+ let style;
+ switch (token.node.props.name) {
+ case 'tada': {
+ style = `font-size: 150%;` + (this.$store.state.device.animatedMfm ? 'animation: tada 1s linear infinite both;' : '');
+ break;
+ }
+ case 'jelly': {
+ const speed = token.node.props.args.speed || '1s';
+ style = (this.$store.state.device.animatedMfm ? `animation: mfm-rubberBand ${speed} linear infinite both;` : '');
+ break;
+ }
+ case 'twitch': {
+ const speed = token.node.props.args.speed || '0.5s';
+ style = this.$store.state.device.animatedMfm ? `animation: mfm-twitch ${speed} ease infinite;` : '';
+ break;
+ }
+ case 'shake': {
+ const speed = token.node.props.args.speed || '0.5s';
+ style = this.$store.state.device.animatedMfm ? `animation: mfm-shake ${speed} ease infinite;` : '';
+ break;
+ }
+ case 'spin': {
+ const direction =
+ token.node.props.args.left ? 'reverse' :
+ token.node.props.args.alternate ? 'alternate' :
+ 'normal';
+ const anime =
+ token.node.props.args.x ? 'mfm-spinX' :
+ token.node.props.args.y ? 'mfm-spinY' :
+ 'mfm-spin';
+ const speed = token.node.props.args.speed || '1.5s';
+ style = this.$store.state.device.animatedMfm ? `animation: ${anime} ${speed} linear infinite; animation-direction: ${direction};` : '';
+ break;
+ }
+ case 'jump': {
+ style = this.$store.state.device.animatedMfm ? 'animation: mfm-jump 0.75s linear infinite;' : '';
+ break;
+ }
+ case 'flip': {
+ const transform =
+ (token.node.props.args.h && token.node.props.args.v) ? 'scale(-1, -1)' :
+ token.node.props.args.v ? 'scaleY(-1)' :
+ 'scaleX(-1)';
+ style = `transform: ${transform};`;
+ break;
+ }
+ }
+ return h('span', {
+ style: 'display: inline-block;' + style,
}, genEl(token.children));
}
@@ -95,48 +143,6 @@ export default defineComponent({
}, genEl(token.children))];
}
- case 'motion': {
- return h('span', {
- style: 'display: inline-block;' + (this.$store.state.device.animatedMfm ? 'animation: anime-rubberBand 1s linear infinite both;' : ''),
- }, genEl(token.children));
- }
-
- case 'spin': {
- const direction =
- token.node.props.attr == 'left' ? 'reverse' :
- token.node.props.attr == 'alternate' ? 'alternate' :
- 'normal';
- const style = this.$store.state.device.animatedMfm
- ? `animation: anime-spin 1.5s linear infinite; animation-direction: ${direction};` : '';
- return h('span', {
- style: 'display: inline-block;' + style
- }, genEl(token.children));
- }
-
- case 'jump': {
- return h('span', {
- style: this.$store.state.device.animatedMfm ? 'display: inline-block; animation: anime-jump 0.75s linear infinite;' : 'display: inline-block;'
- }, genEl(token.children));
- }
-
- case 'flip': {
- return h('span', {
- style: 'display: inline-block; transform: scaleX(-1);'
- }, genEl(token.children));
- }
-
- case 'twitch': {
- return h('span', {
- style: this.$store.state.device.animatedMfm ? 'display: inline-block; animation: anime-twitch 0.5s ease infinite;' : 'display: inline-block;'
- }, genEl(token.children));
- }
-
- case 'shake': {
- return h('span', {
- style: this.$store.state.device.animatedMfm ? 'display: inline-block; animation: anime-shake 0.5s ease infinite;' : 'display: inline-block;'
- }, genEl(token.children));
- }
-
case 'url': {
return [h(MkUrl, {
key: Math.random(),
@@ -198,12 +204,6 @@ export default defineComponent({
}
}
- case 'title': {
- return [h('div', {
- class: 'title'
- }, genEl(token.children))];
- }
-
case 'emoji': {
return [h(MkEmoji, {
key: Math.random(),
diff --git a/src/client/components/misskey-flavored-markdown.vue b/src/client/components/misskey-flavored-markdown.vue
index a7ef718f60..c922eb1678 100644
--- a/src/client/components/misskey-flavored-markdown.vue
+++ b/src/client/components/misskey-flavored-markdown.vue
@@ -13,6 +13,115 @@ export default defineComponent({
});
+
+
diff --git a/src/client/pages/reversi/game.board.vue b/src/client/pages/reversi/game.board.vue
index 96ea86547d..6559396aca 100644
--- a/src/client/pages/reversi/game.board.vue
+++ b/src/client/pages/reversi/game.board.vue
@@ -11,7 +11,7 @@
{{ $t('_reversi.opponentTurn') }}
- {{ $t('_reversi.myTurn') }}
+ {{ $t('_reversi.myTurn') }}
diff --git a/src/client/style.scss b/src/client/style.scss
index 07abbe0814..9715bde10b 100644
--- a/src/client/style.scss
+++ b/src/client/style.scss
@@ -486,74 +486,7 @@ hr {
90% { opacity: 0; transform: scale(0.5); }
}
-@keyframes anime-spin {
- 0% { transform: rotate(0deg); }
- 100% { transform: rotate(360deg); }
-}
-
-@keyframes anime-jump {
- 0% { transform: translateY(0); }
- 25% { transform: translateY(-16px); }
- 50% { transform: translateY(0); }
- 75% { transform: translateY(-8px); }
- 100% { transform: translateY(0); }
-}
-
-// const val = () => `translate(${Math.floor(Math.random() * 20) - 10}px, ${Math.floor(Math.random() * 20) - 10}px)`;
-// let css = '';
-// for (let i = 0; i <= 100; i += 5) { css += `${i}% { transform: ${val()} }\n`; }
-@keyframes anime-twitch {
- 0% { transform: translate(7px, -2px) }
- 5% { transform: translate(-3px, 1px) }
- 10% { transform: translate(-7px, -1px) }
- 15% { transform: translate(0px, -1px) }
- 20% { transform: translate(-8px, 6px) }
- 25% { transform: translate(-4px, -3px) }
- 30% { transform: translate(-4px, -6px) }
- 35% { transform: translate(-8px, -8px) }
- 40% { transform: translate(4px, 6px) }
- 45% { transform: translate(-3px, 1px) }
- 50% { transform: translate(2px, -10px) }
- 55% { transform: translate(-7px, 0px) }
- 60% { transform: translate(-2px, 4px) }
- 65% { transform: translate(3px, -8px) }
- 70% { transform: translate(6px, 7px) }
- 75% { transform: translate(-7px, -2px) }
- 80% { transform: translate(-7px, -8px) }
- 85% { transform: translate(9px, 3px) }
- 90% { transform: translate(-3px, -2px) }
- 95% { transform: translate(-10px, 2px) }
- 100% { transform: translate(-2px, -6px) }
-}
-
-// const val = () => `translate(${Math.floor(Math.random() * 6) - 3}px, ${Math.floor(Math.random() * 6) - 3}px) rotate(${Math.floor(Math.random() * 24) - 12}deg)`;
-// let css = '';
-// for (let i = 0; i <= 100; i += 5) { css += `${i}% { transform: ${val()} }\n`; }
-@keyframes anime-shake {
- 0% { transform: translate(-3px, -1px) rotate(-8deg) }
- 5% { transform: translate(0px, -1px) rotate(-10deg) }
- 10% { transform: translate(1px, -3px) rotate(0deg) }
- 15% { transform: translate(1px, 1px) rotate(11deg) }
- 20% { transform: translate(-2px, 1px) rotate(1deg) }
- 25% { transform: translate(-1px, -2px) rotate(-2deg) }
- 30% { transform: translate(-1px, 2px) rotate(-3deg) }
- 35% { transform: translate(2px, 1px) rotate(6deg) }
- 40% { transform: translate(-2px, -3px) rotate(-9deg) }
- 45% { transform: translate(0px, -1px) rotate(-12deg) }
- 50% { transform: translate(1px, 2px) rotate(10deg) }
- 55% { transform: translate(0px, -3px) rotate(8deg) }
- 60% { transform: translate(1px, -1px) rotate(8deg) }
- 65% { transform: translate(0px, -1px) rotate(-7deg) }
- 70% { transform: translate(-1px, -3px) rotate(6deg) }
- 75% { transform: translate(0px, -2px) rotate(4deg) }
- 80% { transform: translate(-2px, -1px) rotate(3deg) }
- 85% { transform: translate(1px, -3px) rotate(-10deg) }
- 90% { transform: translate(1px, 0px) rotate(3deg) }
- 95% { transform: translate(-2px, 0px) rotate(-3deg) }
- 100% { transform: translate(2px, 1px) rotate(2deg) }
-}
-
-@keyframes anime-tada {
+@keyframes tada {
from {
transform: scale3d(1, 1, 1);
}
@@ -580,33 +513,3 @@ hr {
transform: scale3d(1, 1, 1);
}
}
-
-@keyframes anime-rubberBand {
- from {
- transform: scale3d(1, 1, 1);
- }
-
- 30% {
- transform: scale3d(1.25, 0.75, 1);
- }
-
- 40% {
- transform: scale3d(0.75, 1.25, 1);
- }
-
- 50% {
- transform: scale3d(1.15, 0.85, 1);
- }
-
- 65% {
- transform: scale3d(0.95, 1.05, 1);
- }
-
- 75% {
- transform: scale3d(1.05, 0.95, 1);
- }
-
- to {
- transform: scale3d(1, 1, 1);
- }
-}
diff --git a/src/mfm/language.ts b/src/mfm/language.ts
index 61d6422558..8e15ca43b9 100644
--- a/src/mfm/language.ts
+++ b/src/mfm/language.ts
@@ -23,7 +23,6 @@ export const mfmLanguage = P.createLanguage({
root: r => P.alt(r.block, r.inline).atLeast(1),
plain: r => P.alt(r.emoji, r.text).atLeast(1),
block: r => P.alt(
- r.title,
r.quote,
r.search,
r.blockCode,
@@ -37,14 +36,6 @@ export const mfmLanguage = P.createLanguage({
return P.makeFailure(i, 'not newline');
}
}),
- title: r => r.startOfLine.then(P((input, i) => {
- const text = input.substr(i);
- const match = text.match(/^([【\[]([^【\[】\]\n]+?)[】\]])(\n|$)/);
- if (!match) return P.makeFailure(i, 'not a title');
- const q = match[2].trim();
- const contents = r.inline.atLeast(1).tryParse(q);
- return P.makeSuccess(i + match[0].length, createTree('title', contents, {}));
- })),
quote: r => r.startOfLine.then(P((input, i) => {
const text = input.substr(i);
if (!text.match(/^>[\s\S]+?/)) return P.makeFailure(i, 'not a quote');
@@ -67,17 +58,10 @@ export const mfmLanguage = P.createLanguage({
return P.makeSuccess(i + match[0].length, createLeaf('blockCode', { code: match[2], lang: match[1] ? match[1].trim() : null }));
})),
inline: r => P.alt(
- r.big,
r.bold,
r.small,
r.italic,
r.strike,
- r.motion,
- r.spin,
- r.jump,
- r.flip,
- r.twitch,
- r.shake,
r.inlineCode,
r.mathInline,
r.mention,
@@ -85,9 +69,9 @@ export const mfmLanguage = P.createLanguage({
r.url,
r.link,
r.emoji,
+ r.fn,
r.text
),
- big: r => P.regexp(/^\*\*\*([\s\S]+?)\*\*\*/, 1).map(x => createTree('big', r.inline.atLeast(1).tryParse(x), {})),
bold: r => {
const asterisk = P.regexp(/\*\*([\s\S]+?)\*\*/, 1);
const underscore = P.regexp(/__([a-zA-Z0-9\s]+?)__/, 1);
@@ -107,25 +91,6 @@ export const mfmLanguage = P.createLanguage({
return P.alt(xml, underscore).map(x => createTree('italic', r.inline.atLeast(1).tryParse(x), {}));
},
strike: r => P.regexp(/~~([^\n~]+?)~~/, 1).map(x => createTree('strike', r.inline.atLeast(1).tryParse(x), {})),
- motion: r => {
- const paren = P.regexp(/\(\(\(([\s\S]+?)\)\)\)/, 1);
- const xml = P.regexp(/(.+?)<\/motion>/, 1);
- return P.alt(paren, xml).map(x => createTree('motion', r.inline.atLeast(1).tryParse(x), {}));
- },
- spin: r => {
- return P((input, i) => {
- const text = input.substr(i);
- const match = text.match(/^(.+?)<\/spin>/i);
- if (!match) return P.makeFailure(i, 'not a spin');
- return P.makeSuccess(i + match[0].length, {
- content: match[2], attr: match[1] ? match[1].trim() : null
- });
- }).map(x => createTree('spin', r.inline.atLeast(1).tryParse(x.content), { attr: x.attr }));
- },
- jump: r => P.regexp(/(.+?)<\/jump>/, 1).map(x => createTree('jump', r.inline.atLeast(1).tryParse(x), {})),
- flip: r => P.regexp(/(.+?)<\/flip>/, 1).map(x => createTree('flip', r.inline.atLeast(1).tryParse(x), {})),
- twitch: r => P.regexp(/(.+?)<\/twitch>/, 1).map(x => createTree('twitch', r.inline.atLeast(1).tryParse(x), {})),
- shake: r => P.regexp(/(.+?)<\/shake>/, 1).map(x => createTree('shake', r.inline.atLeast(1).tryParse(x), {})),
center: r => r.startOfLine.then(P.regexp(/([\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 })),
mathBlock: r => r.startOfLine.then(P.regexp(/\\\[([\s\S]+?)\\\]/, 1).map(x => createLeaf('mathBlock', { formula: x.trim() }))),
@@ -192,5 +157,29 @@ export const mfmLanguage = P.createLanguage({
const code = P.regexp(emojiRegex).map(x => createLeaf('emoji', { emoji: x }));
return P.alt(name, code);
},
+ fn: r => {
+ return P.seqObj(
+ P.string('['), ['fn', P.regexp(/[^\s\n\[\]]+/)] as any, P.string(' '), P.optWhitespace, ['text', P.regexp(/[^\n\[\]]+/)] as any, P.string(']'),
+ ).map((x: any) => {
+ let name = x.fn;
+ const args = {};
+ const separator = x.fn.indexOf('.');
+ if (separator > -1) {
+ name = x.fn.substr(0, separator);
+ for (const arg of x.fn.substr(separator + 1).split(',')) {
+ const kv = arg.split('=');
+ if (kv.length === 1) {
+ args[kv[0]] = true;
+ } else {
+ args[kv[0]] = kv[1];
+ }
+ }
+ }
+ return createTree('fn', r.inline.atLeast(1).tryParse(x.text), {
+ name,
+ args
+ });
+ });
+ },
text: () => P.any.map(x => createLeaf('text', { text: x }))
});
diff --git a/src/mfm/to-html.ts b/src/mfm/to-html.ts
index 36680e374e..ab3f7c3d16 100644
--- a/src/mfm/to-html.ts
+++ b/src/mfm/to-html.ts
@@ -25,12 +25,6 @@ export function toHtml(tokens: MfmForest | null, mentionedRemoteUsers: IMentione
return el;
},
- big(token) {
- const el = doc.createElement('strong');
- appendChildren(token.children, el);
- return el;
- },
-
small(token) {
const el = doc.createElement('small');
appendChildren(token.children, el);
@@ -49,42 +43,12 @@ export function toHtml(tokens: MfmForest | null, mentionedRemoteUsers: IMentione
return el;
},
- motion(token) {
+ fn(token) {
const el = doc.createElement('i');
appendChildren(token.children, el);
return el;
},
- spin(token) {
- const el = doc.createElement('i');
- appendChildren(token.children, el);
- return el;
- },
-
- jump(token) {
- const el = doc.createElement('i');
- appendChildren(token.children, el);
- return el;
- },
-
- twitch(token) {
- const el = doc.createElement('i');
- appendChildren(token.children, el);
- return el;
- },
-
- shake(token) {
- const el = doc.createElement('i');
- appendChildren(token.children, el);
- return el;
- },
-
- flip(token) {
- const el = doc.createElement('span');
- appendChildren(token.children, el);
- return el;
- },
-
blockCode(token) {
const pre = doc.createElement('pre');
const inner = doc.createElement('code');
@@ -157,12 +121,6 @@ export function toHtml(tokens: MfmForest | null, mentionedRemoteUsers: IMentione
return el;
},
- title(token) {
- const el = doc.createElement('h1');
- appendChildren(token.children, el);
- return el;
- },
-
text(token) {
const el = doc.createElement('span');
const nodes = (token.node.props.text as string).split(/\r\n|\r|\n/).map(x => doc.createTextNode(x) as Node);
diff --git a/src/mfm/to-string.ts b/src/mfm/to-string.ts
index 6b8dcf2c39..b70b99cbda 100644
--- a/src/mfm/to-string.ts
+++ b/src/mfm/to-string.ts
@@ -18,10 +18,6 @@ export function toString(tokens: MfmForest | null, opts?: RestoreOptions): strin
return `**${appendChildren(token.children, opts)}**`;
},
- big(token, opts) {
- return `***${appendChildren(token.children, opts)}***`;
- },
-
small(token, opts) {
return `${appendChildren(token.children, opts)}`;
},
@@ -34,30 +30,11 @@ export function toString(tokens: MfmForest | null, opts?: RestoreOptions): strin
return `${appendChildren(token.children, opts)}`;
},
- motion(token, opts) {
- return `${appendChildren(token.children, opts)}`;
- },
-
- spin(token, opts) {
- const attr = token.node.props?.attr;
- const post = attr ? ` ${attr}` : '';
- return `${appendChildren(token.children, opts)}`;
- },
-
- jump(token, opts) {
- return `${appendChildren(token.children, opts)}`;
- },
-
- twitch(token, opts) {
- return `${appendChildren(token.children, opts)}`;
- },
-
- shake(token, opts) {
- return `${appendChildren(token.children, opts)}`;
- },
-
- flip(token, opts) {
- return `${appendChildren(token.children, opts)}`;
+ fn(token, opts) {
+ const name = token.node.props?.name;
+ const args = token.node.props?.args || {};
+ const argsStr = Object.entries(args).map(([k, v]) => v === true ? k : `${k}=${v}`).join(',');
+ return `[${name}${argsStr !== '' ? '.' + argsStr : ''} ${appendChildren(token.children, opts)}]`;
},
blockCode(token) {
@@ -104,10 +81,6 @@ export function toString(tokens: MfmForest | null, opts?: RestoreOptions): strin
return `${appendChildren(token.children, {doNyaize: false}).replace(/^/gm,'>').trim()}\n`;
},
- title(token, opts) {
- return `[${appendChildren(token.children, opts)}]\n`;
- },
-
text(token, opts) {
return (opts && opts.doNyaize) ? nyaize(token.node.props.text) : token.node.props.text;
},
diff --git a/test/mfm.ts b/test/mfm.ts
index 69c340bc0b..6244263a30 100644
--- a/test/mfm.ts
+++ b/test/mfm.ts
@@ -227,16 +227,6 @@ describe('MFM', () => {
});
});
- it('big', () => {
- const tokens = parse('***Strawberry*** Pasta');
- assert.deepStrictEqual(tokens, [
- tree('big', [
- text('Strawberry')
- ], {}),
- text(' Pasta'),
- ]);
- });
-
it('small', () => {
const tokens = parse('smaller');
assert.deepStrictEqual(tokens, [
@@ -246,133 +236,6 @@ describe('MFM', () => {
]);
});
- it('flip', () => {
- const tokens = parse('foo');
- assert.deepStrictEqual(tokens, [
- tree('flip', [
- text('foo')
- ], {}),
- ]);
- });
-
- describe('spin', () => {
- it('text', () => {
- const tokens = parse('foo');
- assert.deepStrictEqual(tokens, [
- tree('spin', [
- text('foo')
- ], {
- attr: null
- }),
- ]);
- });
-
- it('emoji', () => {
- const tokens = parse(':foo:');
- assert.deepStrictEqual(tokens, [
- tree('spin', [
- leaf('emoji', { name: 'foo' })
- ], {
- attr: null
- }),
- ]);
- });
-
- it('with attr', () => {
- const tokens = parse(':foo:');
- assert.deepStrictEqual(tokens, [
- tree('spin', [
- leaf('emoji', { name: 'foo' })
- ], {
- attr: 'left'
- }),
- ]);
- });
-/*
- it('multi', () => {
- const tokens = parse(':foo::foo:');
- assert.deepStrictEqual(tokens, [
- tree('spin', [
- leaf('emoji', { name: 'foo' })
- ], {
- attr: null
- }),
- tree('spin', [
- leaf('emoji', { name: 'foo' })
- ], {
- attr: null
- }),
- ]);
- });
-
- it('nested', () => {
- const tokens = parse(':foo:');
- assert.deepStrictEqual(tokens, [
- tree('spin', [
- tree('spin', [
- leaf('emoji', { name: 'foo' })
- ], {
- attr: null
- }),
- ], {
- attr: null
- }),
- ]);
- });
-*/
- });
-
- it('jump', () => {
- const tokens = parse(':foo:');
- assert.deepStrictEqual(tokens, [
- tree('jump', [
- leaf('emoji', { name: 'foo' })
- ], {}),
- ]);
- });
-
- describe('motion', () => {
- it('by triple brackets', () => {
- const tokens = parse('(((foo)))');
- assert.deepStrictEqual(tokens, [
- tree('motion', [
- text('foo')
- ], {}),
- ]);
- });
-
- it('by triple brackets (with other texts)', () => {
- const tokens = parse('bar(((foo)))bar');
- assert.deepStrictEqual(tokens, [
- text('bar'),
- tree('motion', [
- text('foo')
- ], {}),
- text('bar'),
- ]);
- });
-
- it('by tag', () => {
- const tokens = parse('foo');
- assert.deepStrictEqual(tokens, [
- tree('motion', [
- text('foo')
- ], {}),
- ]);
- });
-
- it('by tag (with other texts)', () => {
- const tokens = parse('barfoobar');
- assert.deepStrictEqual(tokens, [
- text('bar'),
- tree('motion', [
- text('foo')
- ], {}),
- text('bar'),
- ]);
- });
- });
-
describe('mention', () => {
it('local', () => {
const tokens = parse('@himawari foo');
@@ -1310,30 +1173,6 @@ describe('MFM', () => {
it('小さい字', () => {
assert.deepStrictEqual(toString(parse('小さい字')), '小さい字');
});
- it('モーション', () => {
- assert.deepStrictEqual(toString(parse('モーション')), 'モーション');
- });
- it('モーション2', () => {
- assert.deepStrictEqual(toString(parse('(((モーション)))')), 'モーション');
- });
- it('ビッグ+', () => {
- assert.deepStrictEqual(toString(parse('*** ビッグ+ ***')), '*** ビッグ+ ***');
- });
- it('回転', () => {
- assert.deepStrictEqual(toString(parse('回転')), '回転');
- });
- it('右回転', () => {
- assert.deepStrictEqual(toString(parse('右回転')), '右回転');
- });
- it('左回転', () => {
- assert.deepStrictEqual(toString(parse('左回転')), '左回転');
- });
- it('往復回転', () => {
- assert.deepStrictEqual(toString(parse('往復回転')), '往復回転');
- });
- it('ジャンプ', () => {
- assert.deepStrictEqual(toString(parse('ジャンプ')), 'ジャンプ');
- });
it('コードブロック', () => {
assert.deepStrictEqual(toString(parse('```\nコードブロック\n```')), '```\nコードブロック\n```');
});
@@ -1352,12 +1191,6 @@ describe('MFM', () => {
it('詳細なしリンク', () => {
assert.deepStrictEqual(toString(parse('?[詳細なしリンク](http://example.com)')), '?[詳細なしリンク](http://example.com)');
});
- it('【タイトル】', () => {
- assert.deepStrictEqual(toString(parse('【タイトル】')), '[タイトル]');
- });
- it('[タイトル]', () => {
- assert.deepStrictEqual(toString(parse('[タイトル]')), '[タイトル]');
- });
it('インライン数式', () => {
assert.deepStrictEqual(toString(parse('\\(インライン数式\\)')), '\\(インライン数式\\)');
});