ブログ内でmermaidを使いたい欲が自分の中で高まったので、対応しました。のメモです。
ブログでは、react-markdownのライブラリを用いて、markdownをHTMLに変換しています。
react-markdownをmermaidに対応させる拡張プラグインがあればサクッと...と思っていましたが、よさげなものが見当たらなかったので、mermaidのライブラリから自作で対応します。
と言っても、mermaidのドキュメントを見る限り、行うことはシンプルで、展開するDOM要素をmermaid.run
のnodesに指定すればよさそうなので、その通りやります。
まずはインストール
$ npm install mermaid
mermaidの表示を行うコンポーネントです。childrenでmermaidで表示する内容を受け取ります。
mermaid.run
で指定するnodesにはuseRefで対応させます。
'use client'; import mermaid from 'mermaid'; import { memo, useEffect, useRef, type ReactNode } from 'react'; mermaid.initialize({ startOnLoad: false, theme: 'dark', }); // eslint-disable-next-line react/display-name const Mermaid = memo(({ children }: { children: ReactNode }) => { const ref = useRef<HTMLDivElement>(null); useEffect(() => { if (ref.current) { mermaid.run({ nodes: [ref.current] }); } }, []); return ( <div className="mermaid" ref={ref}> {children} </div> ); }); export default Mermaid;
また、react-markdownのコンポーネントでは、SyntaxHighlighter
の拡張プラグインの前段で先ほどのMermaidコンポーネントに渡します。
code(props) { // eslint-disable-next-line const { children, className, node, ref, ...rest } = props; if (className === 'language-mermaid') { return <Mermaid>{children}</Mermaid>; } const match = /language-(\w+)/.exec(className || ''); return match ? ( <SyntaxHighlighter {...rest} PreTag="div" language={match[1]} style={coldarkDark}> {String(children).replace(/\n$/, '')} </SyntaxHighlighter> ) : ( <code {...rest} className={className}> {children} </code> ); },
Sequence diagrams
のサンプルを表示してみます。
888。新しい機能も問題なく表示されるか確認します。
ちゃんと表示されました。