乐趣区

关于前端:结构化文本处理利器-unified-生态介绍

作者:imyzf

概述

Content as structured data.

—— unified 官网题词

unified 是一套文本处理相干的生态体系,联合其生态上的相干插件,可能解决 Markdown、HTML、自然语言等。而 unified 库自身又作为一个对立的执行接口,负责执行器的角色,调用其生态上相干的插件实现解决工作。

从 unified 官网 上能够看到,目前 unified 的应用十分宽泛,包含 Prettier、Node.js 官网、Gatsby 都使用了 unified 的能力实现了一些性能。

图:unified 官网的应用举例

常见的应用场景包含:

  • 基于 Markdown 生成 HTML 页面和站点
  • Markdown/HTML 内容加工解决
  • Markdown 语法查看、格式化
  • 作为底层库,封装特定场景的工具

鉴于目前国内对 unified 体系的介绍文章非常少,本文将对 unified 的相干插件生态、工作原理作介绍,并对一些应用例子作解析,帮忙读者理解 unified 体系的能力、原理和用处。

插件生态

图:unified 生态相干插件

remark

remark 是 Markdown 相干的插件汇合,提供了 Markdown 的解析、批改、转换为 HTML 等能力。

目前提供的一些罕用插件:

  • remark-parse: 提供解析 Markdown 的能力
  • remark-gfm: 提供 GFM (GitHub flavored markdown) 反对
  • remark-lint: 提供 Markdown 的代码查看能力
  • remark-toc: 提供 Markdown 文档目录生成性能
  • remark-html 提供将 Markdown 编译为 HTML 的能力

残缺的插件列表能够参考此处,大概有 150 多个插件可供选择。

咱们能够在我的项目中应用这种便捷的形式调用 remark:

remark() // 一键初始化 Markdown 解析器
  .processSync('# Hello, world!') // 同步解决文本 

等价于如下形式:

unified() // 应用 unified 对立的接口
  .use(remarkParse)  // 应用 Markdown 解析器插件
  .use(remarkStringify) // 应用 Markdown 文本序列化插件
  .processSync('# Hello, world!')

图:remark 应用和转换示例

另外须要留神的是,GitHub 上目前有一个同名我的项目 gnab/remark,其官网为 remarkjs.com,尽管也是与 Markdown 相干的工具,但其与 unified 生态下的 remark 没有任何关系,本文提到的 remark 的官网为 remark.js.org,通过搜索引擎搜寻相干材料时须要防止混同。

rehype

与 remark 相似,rehype 是 HTML 相干的插件汇合,提供了 HTML 的格式化、压缩、文档生成等能力。

相比之下,rehype 的插件绝对较少,只有 40 多个,具体的插件列表能够参考插件列表文档

同时,咱们也能够应用 rehype-remark 和 remark-rehype,实现两种语言的插件体系之间的相互转换。例如上面的例子,能够实现将 stdin 输出的 HTML 内容转换为 Markdown:

import {unified} from 'unified'
import {stream} from 'unified-stream'
import rehypeParse from 'rehype-parse'
import rehypeRemark from 'rehype-remark'
import remarkStringify from 'remark-stringify'

const processor = unified()
  .use(rehypeParse)     // 解析 HTML
  .use(rehypeRemark)    // 转换到 remark 体系
  .use(remarkStringify) // 将语法树转换为 Markdown 字符串

process.stdin.pipe(stream(processor)).pipe(process.stdout)

其余

retext 和 redot 是两个比拟小众的体系,使用量较少,开发也不如前述两个体系沉闷,其用处如下:

  • retext: 提供自然语言的解决能力,包含拼写查看、谬误修改、可读性查看等
  • redot: 提供 graphviz 的解析能力

另外在 Markdown 畛域,有两个命名非 re 结尾的体系,mdx 和 micromark,别离对应特定的 Markdown 应用场景:

  • mdx: 提供在 Markdown 文档中编写 JSX 的能力,实现在文档中引入各类组件,编写可交互的文档
  • micromark: 一个极简的 Markdown 转换库,反对大量扩大插件,适宜简略的 Markdown 转 HTML 场景,同时 remark 也复用了 micromark 的解析能力

具体的信息能够查看我的项目文档理解,这里不再赘述。

工作原理

unified 的外围机制是基于 AST(abstract syntax trees,形象语法树),在执行插件时 AST 会被传递给插件,能够对其进行各种解决。同时,也能够基于 AST 进行各种语言的转换,例如将 Markdown 文档解析后,转换为 HTML 进行解决,之后再转回 Markdown。

图:unified 工作流程

例如咱们能够在插件中遍历 AST,将所有 heading 节点打印进去:

module.exports = () => tree => {
  visit(tree, 'heading', node => {console.log(node)
  })
}

下面例子中的 visit 办法来自 unist-util-visit 工具,提供了遍历节点的性能。unified 应用了一种称为 unist 或者 UST 的 AST 规范,使得雷同的工具可能在不同的语言上应用。例如针对 Markdown 和 HTML 语言的 AST,因为他们基于雷同的规范,咱们能够应用同样的 visit API 实现同样的性能:

visit(markdownAST, 'images', transformImages)
visit(htmlAST, 'img', transformImgs)

场景举例

接下来将列举一些基于 unified 生态的应用场景,帮忙大家进一步理解其用处。

Node.js 官网

Node.js 官网次要在语法查看、文档构建两个方面应用了 unified:

  • 应用 remark-cli 查看 Markdown 文档,参考其 package.json 中的脚本配置
  • 应用 unified 进行文档构建,参考 generate.mjs 中的代码

dumi

dumi 是一款为组件开发场景定制的文档工具,其外围性能就是将 Markdown 文档转换为 HTML 页面。查看其源码,咱们会发现其应用了 unified 作为转换器,在 remark/index.ts 中引入了 unified,并调用了一些列自定义的或者社区提供的插件进行解决。

因为应用了十分多的自定义插件,dumi 源码能够作为极佳的 unified 插件开发参考例子。例如参考 link.ts,能够理解如何将 Markdown 中的内部链接,通过批改 AST,在生成的页面中减少一个链接小图标,提醒用户这是一个指向内部站点的链接。

文档源码:

[云音乐官网](https://music.163.com/)

转换为:

<a target="_blank" rel="noopener noreferrer" href="https://music.163.com/">
  云音乐官网
  <svg class="__dumi-default-external-link-icon">……</svg>
</a>

react-markdown

react-markdown 作为 remark 体系的一部分,是基于 unified 生态的下层封装,提供了一个可能渲染 Markdown 的 React 组件。在 React 框架中,比起间接应用 remark 将 Markdown 转换为 HTML 再应用 dangerouslySetInnerHTML 渲染,应用 react-markdown 更加安全可靠,应用形式也更加简略便捷。

图:react-markdown 工作原理

上图展现了 react-markdown 的工作原理,流程如下:

  1. 通过 remark 将 Markdown 转换为对应的 AST —— mdast
  2. 应用 remark 插件对 mdast 进行解决
  3. 通过 remark-rehype 将 mdast 转换为 HTML 的 AST —— hast
  4. 应用 rehype 插件对 hast 进行解决
  5. 应用 React 组件渲染 hast 为 React 元素

以上整个流程其实是 Markdown 渲染为 HTML 的通用解决流程,咱们在实现相似的库时,也能够作为参考。

对于作者

目前 unified 生态总共有 333 个开源我的项目(截至 2022.01.05),其外围开发者为 Titus Wormer。从 Wormer 的集体网站能够理解到,他来自荷兰,毕业于阿姆斯特丹应用科学大学,并且已经负责过该大学的讲师。作为一名全职开源贡献者,总共保护了 535 多个我的项目,其中有 50% 的工夫精力投入到 unified 我的项目上。可能凭一己之力,对开源社区作出如此大的奉献,十分值得钦佩。对于他是如何治理 unified 组织的,能够参考 unified collective 文档作进一步理解。

本文公布自 网易云音乐大前端团队,文章未经受权禁止任何模式的转载。咱们长年招收前端、iOS、Android,如果你筹备换工作,又恰好喜爱云音乐,那就退出咱们 grp.music-fe(at)corp.netease.com!

退出移动版