💯
unified を使ってオレオレ Markdown を ReactElement に変換する
一連の unified 記事の最後です。好きなように拡張した Markdown を解析して ReactElement に変換し、レンダリングする方法を書きます。
わからない言葉は用語をまとめた記事を参照してみてください。
現在のベストプラクティス
2021 年 4 月現在、次のパッケージを組み合わせて使うのが良さそうです。
コード例
以前作った Zenn のメッセージ記法を解釈するプラグインを使う際のコード例です。
processor.ts
import React from "react";
import unified from "unified";
import parser from "remark-parse";
import mdast2hast from "remark-rehype";
import compiler from "rehype-react";
import { attacher, handler } from "./zenn-message";
const processor = unified()
.use(parser)
.use(attacher)
.use(mdast2hast, { handlers: { message: handler } })
.use(compiler, { createElement: React.createElement });
export default processor;
変換処理をこのように定義しておいて、次のように使います。
App.tsx
import React from "react";
import processor from "./processor";
const SAMPLE = `
:::message
This is a message
:::
:::message
But this is not a message
::
~~~markdown
# Heading 1
**strong**
~~~
`;
function App() {
return (
<>
<h1>This is a Markdown</h1>
{processor.processSync(SAMPLE).result}
</>
);
}
export default App;
これを表示させると、次のようになります。
意図通りにレンダリングされていますね。
その他の選択肢
remark の中の人に質問して得た情報から判断しています。
remark-react は使わないの?
メンテナンスされなくなる予定です。また、現時点で TypeScript 対応されていません。
react-markdown は?
じゃあreact-markdown は Markdown から ReactElement へライトに変換したい場合を想定したパッケージとのことです。
実際に react-markdown は設定を細かく指定できない分、次のように使うことができて非常に楽です。
import React from "react";
import ReactMarkdown from "react-markdown";
import { render } from "react-dom";
render(<ReactMarkdown># Hello, *world*!</ReactMarkdown>, document.body);
react-remark では Hooks が用意されてるけど…?
React 17 で動かないようです。深追いする気力がなく…。
ただし、今後これがメインでメンテナンスされていくようです。
Discussion