LoginSignup
4
1

More than 3 years have passed since last update.

React + TypeScriptでMarkdownをMathjax + Highlight付きで表示する(メモ)

Last updated at Posted at 2020-07-12

こういう時、あるよね?(たぶん)

React + TypeScriptで、サーバー上に置いたMarkdownを綺麗に表示させたい!(数式、コードも)

で、結構詰まったのでメモ。

ファイルの読み込み

XMLHttpRequestを使って、"source"にMarkdownを読み込みます。

src/Md.tsx
import React, { useEffect } from 'react';
import './Md.css'

export default function Md() {
    const [source, setSource] = React.useState<string>("");
    useEffect(() => {
        const xhr = new XMLHttpRequest();
        xhr.open("GET", "./Problems/p1.md");
        xhr.send();
        xhr.onload = function () {
            if (xhr.status !== 200) {
                alert("Error");
            } else {
                setSource(xhr.responseText);
            }
        }
    }, [])
    return (
        <div className="main">
            \(ax^2+bx+c=0\)
        </div>
    );
}

Mathjaxを入れる

index.htmlに、これを入れるだけです。簡単!

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax
/2.7.7/MathJax.js?config=TeX-AMS_CHTML"></script>

さっきの

\(ax^2+bx+c=0\)

が数式っぽく表示されるようになりました。

MarkdownをHTMLに変換して表示する

これはなんでかわからないんですが、

npm i --save @types/marked marked

でJSとTS両方入れておきます。どっちか欠けてるとできませんでした。なんでだろ

tsxファイルは以下のように修正します。

src/Md.tsx
import React, { useEffect } from 'react';
import marked from 'marked';
import './Md.css'

export default function Md() {
    const [source, setSource] = React.useState<string>("");
    useEffect(() => {
        const xhr = new XMLHttpRequest();
        xhr.open("GET", "./Problems/p1.md");
        xhr.send();
        xhr.onload = function () {
            if (xhr.status !== 200) {
                alert("Error");
            } else {
                setSource(marked(xhr.responseText));
            }
        }
    }, [])
    return (
        <div className="main">
            <div dangerouslySetInnerHTML={{ __html: source }} />
        </div>
    );
}

これで数式が表示されるはず...と思ったらされなくて、数式のバックスラッシュがmarkedで消えてしまうっぽいのでバックスラッシュを2本書くようにします。

Syntax Highlightを付ける

コードを表示する時、Syntax Highlight欲しいですよね?私は欲しいです。

そこで、highlight.jsを使います。

npm i --save hightlight.js @types/hightlight.js

後は、これでOKです。

ハイライトのスタイルはいっぱいあるので、色々試してみて下さい。

src/Md.tsx
import React, { useEffect } from 'react';
import marked from 'marked';
import highlightjs from 'highlight.js';
import 'highlight.js/styles/atelier-lakeside-dark.css'
import './Md.css'

marked.setOptions({
    highlight: function (code, lang) {
        return highlightjs.highlightAuto(code, [lang]).value;
    },
});

export default function Md() {
    const [source, setSource] = React.useState<string>("");
    useEffect(() => {
        const xhr = new XMLHttpRequest();
        xhr.open("GET", "./Problems/p1.md");
        xhr.send();
        xhr.onload = function () {
            if (xhr.status !== 200) {
                alert("Error");
            } else {
                setSource(marked(xhr.responseText));
            }
        }
    }, [])
    return (
        <div className="main">
            <div dangerouslySetInnerHTML={{ __html: source }} />
            \(ax^2+bc+c=0\)
        </div>
    );
}

これで、無事にMarkdownを表示できました。やったー!

コードのフォントはUbuntu Monoを使いました。

image.png

(2021/2/28 追記)
記事中のdangerouslySetInnerHTMLを使うとXSSを引き起こす可能性があります。ユーザ入力を扱う際は気をつけて下さい。

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1