あいつの日誌β

働きながら旅しています。

React で Latex を含む Markdown を扱いたいので markdown-it-katex を使った

f:id:okamuuu:20170829141649p:plain

あらすじ

React で Markdown を使いたい場合は react-markdown が存在します。React で latex を使いたい場合は react-katex が存在します。なんだけど MarkdownLatex を含む場合はどうやればいいのか知らないので調べました。

結論

markdown-it とその plugin である markdown-it-katex を使う

Just Do it

準備

create-react-app practice-react-markdown-it-katex && cd $_
getstorybook
yarn add markdown-it markdown-it-katex @storybook/addon-knobs gh-pages

edit stories/index.js

 
 import { Button, Welcome } from '@storybook/react/demo';
 
+import 'katex/dist/katex.min.css'
+import MarkdownIt from 'markdown-it'
+import mk from 'markdown-it-katex'
+
+const md = new MarkdownIt()
+md.use(mk)
+
 storiesOf('Welcome', module).add('to Storybook', () => <Welcome showApp={linkTo('Button')} />);
 
 storiesOf('Button', module)
   .add('with text', () => <Button onClick={action('clicked')}>Hello Button</Button>)
   .add('with some emoji', () => <Button onClick={action('clicked')}><U+1F600> <U+1F60E> <U+1F44D> <U+1F4AF></Button>);
+
+const result = md.render('# Math Rulez! \n  $\\sqrt{3x-1}+(1+x)^2$');
+
+storiesOf('markdown-it', module)
+  .add('katex', () =>
+    <div dangerouslySetInnerHTML={{ __html: result }} />
+  )

yarn run storybookhttp://localhost:6006 で動作確認できます(port は各々の環境によって異なる場合があります)

注意点は下記の2点

  • markdown-it が parse した HTML はJSX(仮想DOM)ではないので React で使う場合は dangerouslySetInnerHTML を使用します
  • katex が使用する CSSmarkdown-it-katex を install したときに node_modules/katex/dist/katex.min.css に入っているはずなのでそれを使用します。

storybook で動作確認

とあるプロジェクトで数学の問題を Markdown 形式で記述しているチームがいるのでこの compnent が要件を満たしているかどうかをチェックしてもらいます。

今回は gh-pages に簡単に上げられるので storybook とその addons を使う事にします

edit .storybook/addons.js

 import '@storybook/addon-actions/register';
 import '@storybook/addon-links/register';
+import '@storybook/addon-knobs/register';

edit stories/index.js

 import { storiesOf } from '@storybook/react';
 import { action } from '@storybook/addon-actions';
 import { linkTo } from '@storybook/addon-links';
+import { withKnobs, text, boolean, number } from '@storybook/addon-knobs';
+
+const stories = storiesOf('Storybook Knobs', module);
+stories.addDecorator(withKnobs)
 
 import { Button, Welcome } from '@storybook/react/demo';
 
@@ -26,3 +30,11 @@ storiesOf('markdown-it', module)
     <div dangerouslySetInnerHTML={{ __html: result }} />
   )
 
+const markdown = '# Math Rulez! \n  $\\sqrt{3x-1}+(1+x)^2$'
+
+stories.add('markdown-it-katex with knobs', () => {
+  const parsedMarkdown = md.render(text('Markdown', markdown))
+  return (
+    <div dangerouslySetInnerHTML={{ __html: parsedMarkdown }} />
+  )
+})

この状態で yarn run storybook を再起動します。右下に KNOBS のタグが追加されているのでここに Latex を含んだ Markdown を入力してもらい、期待動作として正しいのか確認してもらいます。

f:id:okamuuu:20170829141548p:plain

gh-pages

まず github にある自身の repository を用意しておきます。

yarn run build-storybook を実行して、 storybook-static 配下に storybook を静的ファイルとして生成します。その後 $(npm bin)/gh-pages -d storybook-static を実行します。

これでコンテンツ作成チームに記述した Markdown がきちんと動いているかを確認してもらえるようになりました。

まとめ

というわけで無事 React で作られて Component に Latex を導入することができました。

上記の例だと Latex の記述が先頭と最後尾に $ が入ってくる想定になっていますがそこは各自で適宜調整頂ければと思います。

こちらからは以上です。

github.com