Skip to content
0

Markdown Parser

我们主要介绍两款 Markdown 解析器,分别是 UnifiedJs 和 Markdown-it

UnifiedJs

用于通过语法树解析、检查、转换和序列化内容。其核心功能很轻,

主要的工作都是通过第三方插件来完成的,这给了我们针对目标主观选择插件的灵活性,它的相关生态也非常丰富。不仅如此,已有的差距不满足要求的时候,我们可以自己写一些插件,这也非常简单

下面是官方给出的工作示意:

| ........................ process ........................... |
| .......... parse ... | ... run ... | ... stringify ..........|

          +--------+                     +----------+
Input ->- | Parser | ->- Syntax Tree ->- | Compiler | ->- Output
          +--------+          |          +----------+
                              X
                              |
                       +--------------+
                       | Transformers |
                       +--------------+

主要包含了三个流程:解析、加工、和还原。结合官方的示例代码来看,也能看出这个工作流程:

import rehypeDocument from 'rehype-document'
import rehypeFormat from 'rehype-format'
import rehypeStringify from 'rehype-stringify'
import remarkParse from 'remark-parse'
import remarkRehype from 'remark-rehype'
import {unified} from 'unified'
import {reporter} from 'vfile-reporter'

const file = await unified()
  .use(remarkParse) // 选择一款解析器
  .use(remarkRehype)
  .use(rehypeDocument, {title: '👋🌍'})
  .use(rehypeFormat)
  .use(rehypeStringify) // 选择一款字符串转换器
  .process('# Hello world!') // 目标解析的文本

console.error(reporter(file))
console.log(String(file))

Unified 下面诞生了多个 ecosystem,其中就有用于解析 markdown 的 remark 和用于解析 HTML 的 rehype

插件功能

介绍一些常用的插件

插件功能
remark-parse添加对 markdown 的解析支持
remark-gfm添加对自动链接、脚注、删除线、表格、任务列表的支持
remark-frontmatter添加对 formatter 的支持
remark-math添加对数学公式的支持
remark-toc添加 toc 的支持
remark-rehype将 markdown 转为 HTML 以便支持 rehype
rehype-rewrite遍历 HTML 元素并重写
rehype-document将片段包在 Document 中
rehype-minify压缩 HTML
rehype-format格式化 HTML
rehype-stringify添加对 HTML 的序列化支持

把上面的常用插件看一下,基本就能够理解两者的使用场景,值得一提的关键插件是 remark-rehype,将二者的生态系统打通了

当不需要同时使用 remark 和 rehype 的插件时候,我们也可以不安装 unified 等过多的插件,使用的使用方式更为简洁。

例如只使用 remark 相关插件,用于处理 Markdown

import { remark } from 'remark'
import remarkGfm from 'remark-gfm'

const file = await remark()
  .use(remarkGfm)
  .process(`### Hello World`)

console.log(String(file))

同理,也可以只使用 rehype,来处理 HTML

import { rehype } from 'rehype';
import rehypeRewrite from 'rehype-rewrite';
import rehypeStringify from 'rehype-stringify';

const file = rehype()
  .data('settings', { fragment: true })
  .use(rehypeRewrite, {
    rewrite: (node, index, parent) => {
      if(node.type == 'text' && node.value == 'header') {
        node.value = ''
      }
    }
  })
  .use(stringify)
  .processSync(`<h1>header</h1>`)

console.log(String(file))

Syntax Tree

上面提到了 unified 之后,不得不介绍一下 Syntax Tree

Syntax-tree 是一个包含 100 多个处理基于 unist 的语法树的项目的组织,上面的 remark 和 rehype 的多个插件,其实都是基于这个组织的包简单地封装了一层

这些树通常处理内容

  • unist: Universal Syntax Tree
  • mdast: Markdown AST
  • hast: HTML AST
  • east: ECMAScript AST
  • xast: XML AST
  • nlast: Natural Language AST

每一个 AST 标准中都提供了丰富的工具包,而上面的这些包的本身,由于只是定义了一个标准,所以其包内只有 TS 类型,安装的也都是 @types 下的包,例如:

$ npm i -D @types/mdast @typs/hast @types/east

Released under the MIT License.