react-markdownをv5からv6へアップデートする
Next.jsでreact-markdwonをv5からv6へアップデートした時の備忘録です。
目次
環境
- react-markdown : 5.0.3 -> 6.0.2
- rehype-raw : 5.1.0
アップデートに伴う修正点
修正点は以下のようになりました。
sourceからchildrenに変更renderersからcomponentsに変更- それに伴い
linkをaに変更 CodeBlockの修正
- それに伴い
escapeHtml={false}からrehypePlugins={[rehypeRaw]}に変更
それぞれ個別に見ていきます。
sourceからchildrenに変更
markdownを受け取るpropsがsourceからchildrenに変更になっているため、名前を変更します。
renderersからcomponentsに変更
v5まではrenderersに、markdownに対応した構文(link,delete,break,etc)を指定するようになっており、ユーザーはマークダウンの特性(linkとlinkReferenceの違いなど)を知らなければいけませんでした。
それがv6ではcomponentsに変更され、受け取る値もhtmlのマークアップに対応した形(a,del,br,etc)に変更されました。
- 参考:changelog.md
CodeBlockの修正
上記に伴い、CodeBlockを修正する必要がありました。主な変更点は次の通りです。
- propsの型の変更
- v5では
renderersがinlineCodeとcode別々に分かれていたが、v6ではcomponentsのcodeに統一されたため、inlineのプロパティが追加された languageがなくなり、classMameから取得しなければいけなくなったvalueからchildrenに変更
- v5では
- 最終行の改行を削除する
CodeBlockの変更前と変更後のソース
- 変更前(v5)
CodeBlock.tsx1import { Prism } from 'react-syntax-highlighter'; 2import { a11yDark } from 'react-syntax-highlighter/dist/cjs/styles/prism'; 3 4type Props = { 5 value: string; 6 language: string; 7}; 8 9export const CodeBlock = ({ value, language }: Props) => { 10 const [lang, title] = language ? language.split(':') : ['', null]; 11 return ( 12 <div className="code-block"> 13 {title && <div className="code-block-title">{title}</div>} 14 <div className="code-block-body"> 15 <Prism language={lang} style={a11yDark}> 16 {value} 17 </Prism> 18 </div> 19 </div> 20 ); 21};
- 変更後(v6)
CodeBlock.tsx1import { CodeComponent, ReactMarkdownNames } from 'react-markdown/src/ast-to-react'; 2import { Prism } from 'react-syntax-highlighter'; 3import { a11yDark } from 'react-syntax-highlighter/dist/cjs/styles/prism'; 4 5export const CodeBlock: CodeComponent | ReactMarkdownNames = ({ inline, className, children }) => { 6 const match = /language-(\w+)(:.+)?/.exec(className || ''); 7 const [, title] = match && match[2] ? match[2].split(':') : ['', null]; 8 const lang = match && match[1] ? match[1] : ''; 9 return !inline ? ( 10 <div className="code-block"> 11 {title && <div className="code-block-title">{title}</div>} 12 <div className="code-block-body"> 13 <Prism language={lang} style={a11yDark}> 14 {String(children).replace(/\n$/, '')} 15 </Prism> 16 </div> 17 </div> 18 ) : ( 19 <code className={className}>{children}</code> 20 ); 21};
escapeHtml={false}からrehypePlugins={[rehypeRaw]}に変更
rehypePluginsが追加されたことで、rehypeのプラグインが使用できるようになりました。そのため、v5に存在したいくつかのHTMLパーサーのオプションは廃止されました。allowDangerousHtml,escapeHtmlの代わりにrehype-rawプラグインを使用しています。
変更前と変更後のソース
変更前と変更後の該当ソースの部分は以下の通りとなります。今回は修正していませんが、pluginsはv7ではdeprecateとなるため、代わりのremarkPluginsに変更しておいてもいいと思います。
- 変更前(v5)
1<ReactMarkdown 2 source={markdown} 3 renderers={{ 4 code: CodeBlock, 5 link: LinkBlock, 6 }} 7 plugins={[gfm]} 8 escapeHtml={false} 9>
- 変更後(v6)
1<ReactMarkdown 2 children={markdown} 3 components={{ 4 code: CodeBlock, 5 a: LinkBlock, 6 }} 7 plugins={[gfm]} 8 rehypePlugins={[rehypeRaw]} 9>
おわりに
分かりづらかったrenderersが変更されたり、rehypeのエコシステムが追加されたりしたことで使いやすくなった印象がありました。