react 中实现 markdown 文件解析+目录

5,455 阅读2分钟

最近有一个需求要把 markdown 文件解析并展示到页面中,要求有目录有样式。

先看一眼实现效果:

react-markdown.gif

样式用的是 github 风格的 markdown 样式:github-markdown-css

markdown 解析 + 目录用的是:

代码实现

先说一下 react-markdown 这个插件,用它来解析 markdown 并不能完全解析,还要用 remark-gfm 辅助解析表格,删除线,脚注等,官方给出的解释如下:

用于启用 GitHub 添加的 Markdown 扩展:自动链接文字(www.x.com)、脚注([^1])、删除线(~~stuff~~)、表格(| cell |…)和任务列表(* [x])。您可以使用此插件添加对解析和序列化它们的支持。GitHub 对 CommonMark 的这些扩展称为GFM(GitHub Flavored Markdown)。

这两个插件作者相同,另外还有其他的辅助插件,有需要可以去官方文档看一下。

目录是用 markdown-navbar 这个插件生成的,个人觉得效果非常完美,但是据观察此插件只能用在 react 项目中。

vue 项目可以用vue-markdown 试一下,我实验过,这个插件可以实现解析,样式和目录,但是目录细节不完善,没有点击,滚动追随等高亮效果,选项有很多,可以自行了解。

另外:github-markdown-css 插件我是直接放的css外链,当然也可以使用npm的方式添加。

主要代码:

import React, { Component } from 'react';
import ReactMarkdown from 'react-markdown';     // 解析 markdown
import remarkGfm from 'remark-gfm';             // markdown 对表格/删除线/脚注等的支持
import MarkNav from 'markdown-navbar';          // markdown 目录
import 'markdown-navbar/dist/navbar.css';

class App extends Component {
  constructor(props) {
    super(props)
    this.state = {
      SourceData: ''
    }
  }

  componentDidMount() {
    var $this = this;
    var xmlhttp = new XMLHttpRequest();

    xmlhttp.onreadystatechange = function () {
      if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
        $this.setState({
          SourceData: xmlhttp.responseText
        })
      }
    }
    // 文件目录在 public/static/test.md 这里不需要写 public 因为打包之后没有此目录。
    xmlhttp.open("GET", "/static/test.md", true); 
    xmlhttp.send();
  }

  render() {
    return (
      <div className="App">
        <div className="leftSide">
          <MarkNav
            className="toc-list"
            source={this.state.SourceData}
            ordered={true}
          />
        </div>
        <div
          className="markdown-body content">
            <ReactMarkdown
              children={this.state.SourceData}
              remarkPlugins={[remarkGfm]}
            />
        </div>
      </div>
    );
  }
}

export default App;

结语

总结一下,github-markdown-css 是作为单独的样式用的,markdown-navbar 只用在react中生成 markdown 目录,至于解析 markdown 文件,其实有很多轮子,比如:marked,react-markdown,vue-markdown等。

如果需要目录,react 中 markdown-navbar 的目录功能能全面。vue 中 vue-markdown 这一个插件就足够了,目录和样式他都有,只是目前来看细节的地方不是那么完善,但是也够用了。

以上这些插件和实现效果是我尝试过的,当然还有其他插件可以实现同等的效果,欢迎探讨。