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
のエコシステムが追加されたりしたことで使いやすくなった印象がありました。