最近使用React渲染Markdown,进行了一些简单的探索,和大家分享下相关经验。
当下有许多成熟的Markdown库,如 marked、react-markdown等,这里我采用的是react-markdown。因其与React有更好的结合。
react-markdown地址:https://www.npmjs.com/package/react-markdown
其用法也比较简单:
import React from 'react'
import Markdown from 'react-markdown'
export default props => (
<Markdown
source={props.content}
/>
)
如果不做任何配置,React-Markdown会使用 <pre>
包裹Markdown中的代码块。
这样虽然也能正常显示,但是没有了语法高亮的功能,不够美观。
好在React-Markdown中提供了自定义renderer的功能,可以自定义渲染逻辑。
首先,在React-Markdown中配置下使用自定义渲染引擎:
import React from 'react'
import Markdown from 'react-markdown'
const CodeBlock = ({ language, value }) => <pre>{value}</pre>
export default props => (
<Markdown
source={props.content}
renderers={{ code: CodeBlock }}
/>
)
这里我们配置了使用CodeBlock
来渲染代码块,目前还是在使用pre进行渲染。
然后,再在CodeBlock
中加上语法高亮的支持。
import React from 'react'
import Markdown from 'react-markdown'
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'
import { solarizedlight as codeStyle } from 'react-syntax-highlighter/dist/cjs/styles/prism'
const CodeBlock = ({ language, value }) => (
<SyntaxHighlighter language={language} style={codeStyle}>
{value}
</SyntaxHighlighter>
)
export default props => (
<Markdown
source={props.content}
renderers={{ code: CodeBlock }}
/>
)
这里使用了react-syntax-highlighter
库来做语法高亮支持。
它支持多套主题,具体可配置项参考其官方文档。
React Syntax Highlighter地址: https://www.npmjs.com/package/react-syntax-highlighter
有一套名为Mermaid的流程图库,可在Markdown中直接使用,但是目前在各平台的支持度不同步,React-Markdown中也没有默认支持它。
使用Mermaid可以在Markdown中使用指令画出流程图、类图、甘特图、状态图等多种图表,方便好用,具体用法可参考其官方网站。
Mermaid官方网站:https://mermaid-js.github.io/mermaid/#/
Mermaid是一套JS库,可以在网页中直接加载使用,我们可以稍微修改下CodeBlock
组件,对其进行支持。
首先,在页面中加载mermaid.min.js,并启用自动渲染功能。
可直接将其写入 html 文件中:
<script src="//unpkg.com/mermaid@8.4.8/dist/mermaid.min.js"></script>
<script>mermaid.initialize({startOnLoad:true});</script>
如果写在React中,则需要处理下{}字符:
<script src='//unpkg.com/mermaid@8.4.8/dist/mermaid.min.js' />
<script>mermaid.initialize({'{startOnLoad: true}'});</script>
在开启startOnLoad: true
之后,Mermaid会自动处理className中带有mermaid
的tag。
因此,CodeBlock
中可以做如下的修改:
import React from 'react'
import Markdown from 'react-markdown'
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'
import { solarizedlight as codeStyle } from 'react-syntax-highlighter/dist/cjs/styles/prism'
const CodeBlock = ({ language, value }) => (
language === 'mermaid'
? return <div className='mermaid'>{value}</div>
: <SyntaxHighlighter language={language} style={codeStyle}>
{value}
</SyntaxHighlighter>
)
export default props => (
<Markdown
source={props.content}
renderers={{ code: CodeBlock }}
/>
)
至此,大功告成。
最后,放个示例mermaid,大家看看效果:
graph TB
c1-->a2
subgraph one
a1-->a2
end
subgraph two
b1-->b2
end
subgraph three
c1-->c2
end