logo

鱼肚的博客

Don't Repeat Yourself

React中渲染Markdown

最近使用React渲染Markdown,进行了一些简单的探索,和大家分享下相关经验。

基本的Markdown能力

当下有许多成熟的Markdown库,如 marked、react-markdown等,这里我采用的是react-markdown。因其与React有更好的结合。

react-markdown地址:https://www.npmjs.com/package/react-markdown

其用法也比较简单:

1import React from 'react'
2import Markdown from 'react-markdown'
3
4export default props => (
5  <Markdown
6    source={props.content}
7  />
8)

代码语法高亮

如果不做任何配置,React-Markdown会使用 <pre>包裹Markdown中的代码块。

这样虽然也能正常显示,但是没有了语法高亮的功能,不够美观。

好在React-Markdown中提供了自定义renderer的功能,可以自定义渲染逻辑。

首先,在React-Markdown中配置下使用自定义渲染引擎:

1import React from 'react'
2import Markdown from 'react-markdown'
3
4const CodeBlock = ({ language, value }) => <pre>{value}</pre>
5
6export default props => (
7  <Markdown
8    source={props.content}
9    renderers={{ code: CodeBlock }}
10  />
11)

这里我们配置了使用CodeBlock来渲染代码块,目前还是在使用pre进行渲染。

然后,再在CodeBlock中加上语法高亮的支持。

1import React from 'react'
2import Markdown from 'react-markdown'
3import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'
4import { solarizedlight as codeStyle } from 'react-syntax-highlighter/dist/cjs/styles/prism'
5
6const CodeBlock = ({ language, value }) => (
7  <SyntaxHighlighter language={language} style={codeStyle}>
8    {value}
9  </SyntaxHighlighter>
10)
11
12export default props => (
13  <Markdown
14    source={props.content}
15    renderers={{ code: CodeBlock }}
16  />
17)

这里使用了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 文件中:

1<script src="//unpkg.com/mermaid@8.4.8/dist/mermaid.min.js"></script>
2<script>mermaid.initialize({startOnLoad:true});</script>

如果写在React中,则需要处理下{}字符:

1<script src='//unpkg.com/mermaid@8.4.8/dist/mermaid.min.js' />
2<script>mermaid.initialize({'{startOnLoad: true}'});</script>

在开启startOnLoad: true之后,Mermaid会自动处理className中带有mermaid的tag。

因此,CodeBlock中可以做如下的修改:

1import React from 'react'
2import Markdown from 'react-markdown'
3import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'
4import { solarizedlight as codeStyle } from 'react-syntax-highlighter/dist/cjs/styles/prism'
5
6const CodeBlock = ({ language, value }) => (
7  language === 'mermaid'
8    ? return <div className='mermaid'>{value}</div>
9    : <SyntaxHighlighter language={language} style={codeStyle}>
10      {value}
11    </SyntaxHighlighter>
12)
13
14export default props => (
15  <Markdown
16    source={props.content}
17    renderers={{ code: CodeBlock }}
18  />
19)

至此,大功告成。

最后,放个示例mermaid,大家看看效果:

1graph TB
2    c1-->a2
3    subgraph one
4    a1-->a2
5    end
6    subgraph two
7    b1-->b2
8    end
9    subgraph three
10    c1-->c2
11    end