问题描述
我正在尝试使用 Unified 和 Remark-Parse 解析 GitHub 风格的降价文件以生成 MDAST。我能够正确且轻松地解析其中的大部分内容,但是我无法解析来自 AST 的 HTML 标签及其内容。
在 AST 中,HTML 标签及其内容被表示为兄弟姐妹,而不是父子。例如 <sub>hi</sub>
被解析为
[
{
"type": "paragraph","children": [
{
"type": "html","value": "<sub>",},{
"type": "text","value": "hi",{
"type": "html","value": "</sub>",}
]
}
]
理想情况下,我希望它被解析为
[
{
"type": "paragraph","value": "sub","children": [
{
"type": "text",]
},]
}
]
以便我可以访问标签类型及其内容。 (具体来说,我的目标是跳过标签及其内容,因为我的目的不需要它们)
这是我目前使用的配置:
import unified from 'unified';
import markdown from 'remark-parse';
import type {Block} from '@notionhq/client/build/src/api-types';
import {parseRoot} from './internal';
import gfm from 'remark-gfm';
export function parseBody(body: string): Block[] {
const tokens = unified().use(markdown).use(gfm).parse(body);
return parseRoot(tokens);
}
所以,我的问题是:有没有办法配置 Remark 来做到这一点/是否有 Remark 插件来做到这一点?如果没有,我将如何创建一个这样做的插件?
谢谢。
解决方法
第一:为什么 AST 看起来如此,以及为什么 Remark 很可能没有其他选择
AST 以这种方式表示它的原因是因为这是 CommonMark 规范为 raw inline HTML 和 HTML blocks 指定的内容。具体来说,CommonMark 指定HTML 标签通过,不解析。
对于内联 HTML,规范支持内联 HTML 标签,这与支持 内联 HTML 不同。标签只是按原样传递。没有匹配的开始和结束标签。原因如下:
- 表现
- 解析器复杂度
- 仅当 Markdown 没有您需要的功能时,才支持将 HTML 标记作为“使用风险自负”“最后的手段”选项。
对于少量的 HTML 标签,在块级支持打开和关闭标签匹配。 pre
、script
、style
和 textarea
,后者最近才在规范的 v0.30 中添加。
您可以阅读规范的上述链接部分,并搜索 CommonMark forum 中的讨论以进一步了解原因,但要切入正题,请阅读:
-
This explanation within the spec 表示所做的选择。
跳到 [本论坛的 Raw HTML 部分](https://talk.commonmark.org/t/beyond-markdown/2787?u=vas)由 CommonMark 规范作者和维护者 John MacFarlane (@jgm) 发表的帖子。>
-
This forum question 以及 this one 和 @jgm 的回答。
第二:你能做些什么
Remark 是“统一集体的一部分”,它是一个以处理 AST(抽象语法树)为中心的基础设施。从您的问题来看,您似乎已经明白了这一点。
在统一页面上有很多关于如何编写插件的帮助:
但是,了解如何执行此操作并快速实现实现的最佳方法是查看 many existing mdast-specific manipulators。