备注:如何在MDAST中解析HTML标签及其内容 第一:为什么 AST 看起来如此,以及为什么 Remark 很可能没有其他选择第二:你能做些什么

问题描述

我正在尝试使用 UnifiedRemark-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 HTMLHTML blocks 指定的内容。具体来说,CommonMark 指定HTML 标签通过,不解析

对于内联 HTML,规范支持内联 HTML 标签,这与支持 内联 HTML 不同。标签只是按原样传递。没有匹配的开始和结束标签。原因如下:

  • 表现
  • 解析器复杂度
  • 仅当 Markdown 没有您需要的功能时,才支持将 HTML 标记作为“使用风险自负”“最后的手段”选项。

对于少量的 HTML 标签,在块级支持打开和关闭标签匹配。 prescriptstyletextarea,后者最近才在规范的 v0.30 中添加。

您可以阅读规范的上述链接部分,并搜索 CommonMark forum 中的讨论以进一步了解原因,但要切入正题,请阅读:

第二:你能做些什么

Remark 是“统一集体的一部分”,它是一个以处理 AST(抽象语法树)为中心的基础设施。从您的问题来看,您似乎已经明白了这一点。

在统一页面上有很多关于如何编写插件的帮助:

但是,了解如何执行此操作并快速实现实现的最佳方法是查看 many existing mdast-specific manipulators