diff --git a/package.json b/package.json
index 1f44130545..2a862ee774 100644
--- a/package.json
+++ b/package.json
@@ -46,6 +46,7 @@
"@types/is-root": "1.0.0",
"@types/is-url": "1.2.28",
"@types/js-yaml": "3.11.2",
+ "@types/katex": "0.5.0",
"@types/koa": "2.0.46",
"@types/koa-bodyparser": "5.0.1",
"@types/koa-compress": "2.0.8",
@@ -140,6 +141,7 @@
"jsdom": "13.0.0",
"json5": "2.1.0",
"json5-loader": "1.0.1",
+ "katex": "0.10.0",
"koa": "2.6.1",
"koa-bodyparser": "4.2.1",
"koa-compress": "3.0.0",
diff --git a/src/client/app/common/views/components/formula.vue b/src/client/app/common/views/components/formula.vue
new file mode 100644
index 0000000000..930f16b471
--- /dev/null
+++ b/src/client/app/common/views/components/formula.vue
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
diff --git a/src/client/app/common/views/components/misskey-flavored-markdown.ts b/src/client/app/common/views/components/misskey-flavored-markdown.ts
index a985a80ecf..cbc938cf51 100644
--- a/src/client/app/common/views/components/misskey-flavored-markdown.ts
+++ b/src/client/app/common/views/components/misskey-flavored-markdown.ts
@@ -1,5 +1,6 @@
import Vue, { VNode } from 'vue';
import { length } from 'stringz';
+import MkFormula from './formula.vue';
import parse from '../../../../../mfm/parse';
import getAcct from '../../../../../misc/acct/render';
import MkUrl from './url.vue';
@@ -199,6 +200,14 @@ export default Vue.component('misskey-flavored-markdown', {
})];
}
+ case 'math': {
+ return [createElement(MkFormula, {
+ props: {
+ formula: token.formula
+ }
+ })];
+ }
+
case 'search': {
return [createElement(MkGoogle, {
props: {
diff --git a/src/mfm/html.ts b/src/mfm/html.ts
index df9959dc4b..cb7c7e2855 100644
--- a/src/mfm/html.ts
+++ b/src/mfm/html.ts
@@ -53,6 +53,12 @@ const handlers: { [key: string]: (window: any, token: any, mentionedRemoteUsers:
document.body.appendChild(element);
},
+ math({ document }, { formula }) {
+ const element = document.createElement('code');
+ element.textContent = formula;
+ document.body.appendChild(element);
+ },
+
link({ document }, { url, title }) {
const a = document.createElement('a');
a.href = url;
diff --git a/src/mfm/parse/elements/math.ts b/src/mfm/parse/elements/math.ts
new file mode 100644
index 0000000000..b10efe515f
--- /dev/null
+++ b/src/mfm/parse/elements/math.ts
@@ -0,0 +1,20 @@
+/**
+ * Math
+ */
+
+export type TextElementMath = {
+ type: 'math';
+ content: string;
+ formula: string;
+};
+
+export default function(text: string) {
+ const match = text.match(/^\$(.+?)\$/);
+ if (!match) return null;
+ const math = match[0];
+ return {
+ type: 'math',
+ content: math,
+ formula: match[1]
+ } as TextElementMath;
+}
diff --git a/src/mfm/parse/index.ts b/src/mfm/parse/index.ts
index f2beec14ff..46e66ac4c2 100644
--- a/src/mfm/parse/index.ts
+++ b/src/mfm/parse/index.ts
@@ -8,6 +8,7 @@ import { TextElementCode } from './elements/code';
import { TextElementEmoji } from './elements/emoji';
import { TextElementHashtag } from './elements/hashtag';
import { TextElementInlineCode } from './elements/inline-code';
+import { TextElementMath } from './elements/math';
import { TextElementLink } from './elements/link';
import { TextElementMention } from './elements/mention';
import { TextElementQuote } from './elements/quote';
@@ -29,6 +30,7 @@ const elements = [
require('./elements/hashtag'),
require('./elements/code'),
require('./elements/inline-code'),
+ require('./elements/math'),
require('./elements/quote'),
require('./elements/emoji'),
require('./elements/search'),
@@ -42,6 +44,7 @@ export type TextElement = { type: 'text', content: string }
| TextElementEmoji
| TextElementHashtag
| TextElementInlineCode
+ | TextElementMath
| TextElementLink
| TextElementMention
| TextElementQuote
diff --git a/test/mfm.ts b/test/mfm.ts
index 83f04075e2..7bd81a2a6f 100644
--- a/test/mfm.ts
+++ b/test/mfm.ts
@@ -210,6 +210,15 @@ describe('Text', () => {
assert.equal(tokens[0].content, '`var x = "Strawberry Pasta";`');
});
+ it('math', () => {
+ const fomula = 'x = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}.';
+ const text = `$${fomula}$`;
+ const tokens = analyze(text);
+ assert.deepEqual([
+ { type: 'math', content: text, formula: fomula }
+ ], tokens);
+ });
+
it('search', () => {
const tokens1 = analyze('a b c 検索');
assert.deepEqual([