作者: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 的工作原理,流程如下:
- 通过 remark 将 Markdown 转换为对应的 AST —— mdast
- 应用 remark 插件对 mdast 进行解决
- 通过 remark-rehype 将 mdast 转换为 HTML 的 AST —— hast
- 应用 rehype 插件对 hast 进行解决
- 应用 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!