# @citation-media/html-parser 中文文档

规范地址：https://npmcn.com/package/%40citation-media/html-parser/

版本：0\.8\.2
npm 元数据更新时间：2026-11-04T00:48:18.875Z
中文译文更新时间：2026-11-09T17:52:35.771Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40citation-media/html-parser
原文对照：https://npmcn.com/package/%40citation-media/html-parser/?lang=original
项目主页：https://github.com/Citation-Media/html-parser#readme
源码仓库：https://github.com/Citation-Media/html-parser

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：169 kB，29 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- Node.js 要求：\>=22\.18\.0
- 运行依赖：1 个
- peer 依赖：@mdream/js ^1\.7\.2 \|\| ^2\.0\.3
- 首次发布：2026-09-29T18:20:15.465Z
- 最新版本发布：2026-11-04T00:48:18.565Z
- 近 30 天下载量：2042（2026-10-10 至 2026-11-08，npm 官方下载统计）
- 已发布版本数：14（近 12 个月 14 个）

## 中文简介

HTML 解析器用于任何 JavaScript 运行时间:链接,图像,资源,元数据,JSON-LD,样式,水分,以及文本在一次通过中没有DOM,由mdream的Markdown.

## 安装

```sh
npm install @citation-media/html-parser
```

也可以使用：`pnpm add @citation-media/html-parser`、`yarn add @citation-media/html-parser`、`bun add @citation-media/html-parser`

## README

# @ 引用- 媒体/ html- parser

将链接、图像、资源、元数据、标题、类数、JSON-LD、样式、水合物、可见文本和内线代码从HTML中取出,放在页面上一个转接处,写成Markdown [梦想](https://github.com/harlan-zw/mdream) 从被询问时的相同输入。 它用mdream的活化剂来读取页面,它从来没有建立DOM,在Cloudflare Workers,Node.js,Bun,Deno,和浏览器中以平版JavaScript来运行:一个由数兆字节组成的流出页面,其内存成本大约与一个小的一样多.

## 安装

```bash
npm install @citation-media/html-parser @mdream/js
```

`@mdream/js` 是一个同伴依赖, `^1.7.2` 或者说 `^2.0.3`。 。 。 . [取消标题](https://unhead.unjs.io/) 一起来 `head` 选项. `cleanHtml` 以 [HTML 重写器](https://developers.cloudflare.com/workers/runtime-apis/html-rewriter/) 并且只在全球范围内运行: 云旗工人, `wrangler dev`,以及 `@cloudflare/vitest-pool-workers`。 。 。 .

## 解析 A 页

`parseHtml` 只返回您想要的。 输入是作为文本的页面, a `Response` 因此 `fetch`,或一个 `ReadableStream` ; 反应或流被逐块读取. `parseHtmlSync` 对于没有承诺的文字,也要这样做.

```ts
import { parseHtml } from "@citation-media/html-parser";

const response = await fetch("https://example.com/");
const { links, images, meta } = await parseHtml(response, {
  url: response.url,
  links: { kinds: ["internal"], resources: false },
  images: true,
  meta: true,
});
```

| 选项 | 它收集的东西 |
| --- | --- |
| `url` | 要求。 解析相对的URL,并从外部显示内部链接. |
| `links` | `true` 或过滤器 : `kinds` (单位:千美元)`internal`, (中文(简体) ), `external`, (中文(简体) ), `special`, (中文(简体) ), `anchor`和 `resources: false` 来降低PDF等下载. |
| `images` | 图像带有 `alt` (单位:千美元)`null` 当失踪时, `""` 当装饰的时候, `width`, (中文(简体) ), `height`, (中文(简体) ), `loading`,他们是否有 `srcset`,其URL为 `sources`,绝对,没有数据URL,最多20个. |
| `resources` | 脚本 `src`, (中文(简体) ), `type`,属性名称,以及它们是否存在于 `<head>`,帧 URL, `<link>` 要素 `rel` 并且,当他们有一个, `type`,例如 `text/markdown` 用于页面的Markdown版本,以及 `media`,音频、视频、其来源和音轨的URL,a `<picture>`源头,嵌入物和物体,每个都一次. 头部没有经典脚本 `async`, (中文(简体) ), `defer`,或 `nomodule` 屏蔽第一个渲染. |
| `meta` | 标题、描述、语言、犬形URL、机器人、取景口、生成器、Open Graph 图像以及 `properties`,每个 `<meta property>` 例如 `og:title` 或者说 `article:published_time` 根据其小写财产,第一个重复,最多50个。 标题是文件的第一个 `<title>`; 一个 SVG 的 `<title>` 命名图形,不计数. |
| `headings` | 前200个标题及其级别和文本,以及 `headingCounts` 每个水平无限制. |
| `classPrefixes` | 以前缀开头的元素数, 如 `["elementor-", "brxe-", "wp-block-"]`。 。 。 . |
| `context` | CSS 等选择器 `main` 或者说 `article`: 只计算匹配元素内的内容。 当没有匹配时,整页都算数. 它需要类型, `#id`, (中文(简体) ), `.class`属性选择器 `=`, (中文(简体) ), `~=`, (中文(简体) ), `|=`, (中文(简体) ), `^=`, (中文(简体) ), `$=`, (中文(简体) ), `*=` 还有一个 `i` 旗帜, `:first-child`, (中文(简体) ), `:nth-child()`, (中文(简体) ), `:first-of-type`, (中文(简体) ), `:nth-of-type()`, (中文(简体) ), `:not()`,和后代和 `>` 组合器, 如 HTML Rewriter 所做的; 需要元素后出现的选择器, 如 `:last-child` 或者说 `+`,丢出一个 `SyntaxError`。 。 。 . |
| `structuredData` | 该页的JSON -LD作为 `items`,每个节点 `<script type="application/ld+json">` 带有列表和 `@graph` 扩大 `invalid`,以位置和出错表示无效的块。 无论区块在哪里,都读取 `context`。 。 。 . |
| `styles` | 页面本身的 CSS 用于 `readStyles`数字 : `blocks`,每个 `<style>` 块中的文本 `id`· ; `attributes`,每个 `style` 属性及其元素,例如 `div#hero.banner`; 和 : `stylesheets`的绝对 URL `rel="stylesheet"` 链接和样式表预装 `as="style"`编辑 `context`。 。 。 . |
| `hydration` | 将浏览器中的页面水化的框架,或 `null`,参见 [水分](https://npmcn.com/package/%40citation-media/html-parser/#readme-hydration)编辑 `context`。 。 。 . |
| `positions` | 添加一个 `position` 每个图像和Astro岛 [第一个屏幕](https://npmcn.com/package/%40citation-media/html-parser/#readme-first-screen)编辑 `context`。 。 。 . |
| `hidden` | 标记每个链接、图像和隐藏内容 `hidden`,参见 [隐藏内容](https://npmcn.com/package/%40citation-media/html-parser/#readme-hidden-content)数字 : `true` 上面写着什么 或规则 `(tag, attributes, byMarkup) => boolean` 这决定给了它。 直观中重复的链接或图像不被隐藏. |
| `text` | 访问者所读的文本如下: `length` 财务报告和审定财务报表 `content`:没有头,脚本,样式,模板, `<noscript>`,而SVG,白空间倒塌并被一个空间分隔出块状元素. `{ maxLength }` 削减 `content`100,000个字符默认; `length` 计算整个文本。 里面的文字很少, 因为上面写着一个脚本的页面. |
| `inlineCode` | 内容安全政策必须允许: `scripts`,浏览器运行的每个内置脚本的文本,精确地写成散列,没有JSON-LD等数据块或模板; `eventHandlers`,属性,例如 `onclick`· ; `javascriptUrls` 内 `href`, (中文(简体) ), `src`, (中文(简体) ), `action`,以及 `formaction`· ; `styleElements` 财务报告和审定财务报表 `styleAttributes`; 和 : `formActions`,发送到的绝对 URL 表格。 阅读不管 `context`。 。 。 . |
| `ids` | 目标为诸如: `#team` 可以指: 每个元素的 `id` 和每个 `<a>`是因为 `name`,按页面顺序,每页一次,最多5000. 阅读不管 `context`。将其与 `anchor` 链接,或与其连接的内部链接的片段,以查找无端链接. |
| `markdown` | 作为Markdown的页面,由mdream从同一份输入中写出: `true` 对于以完整页面 URL 为基准的mdream 默认,或者mdream 的选项,例如 `{ plugins: [isolateMainPlugin(), filterPlugin({ exclude: ["nav"] })] }` 带有 mdream 2 的插件来源 `@mdream/js/plugins`明确 `origin` 覆盖基地。 mdream的滤波器只有Markdown的形状,从来不是其他选项所收集的. |
| `head` | 这个 `<head>` 作为 [取消标题](https://unhead.unjs.io/) 验证它,看 [头](https://npmcn.com/package/%40citation-media/html-parser/#readme-head)编辑 `context`。 。 。 . |
| `select` | CSS 选择器的元素 `selected` 在同一密钥下: `{ addresses: "address", times: "time[datetime]" }` 给每个匹配的 `tag`, (中文(简体) ), `attributes`,以及 `text` (截至 `textContent`,没有脚本和样式,切为2000个字符),每个键最多200个,按页面顺序排列 `hidden`,无论它是隐藏的内容。 选择者就是那些 `context` 拿着 阅读不管 `context`。 。 。 . |
| `forms` | 页面表格 : `action` (绝对;表格名称无的页本身地址), `method` (单位:千美元)`get`, (中文(简体) ), `post`,或 `dialog`, (中文(简体) ), `id` 财务报告和审定财务报表 `name`, (中文(简体) ), `fields` 与他们的 `tag`, (中文(简体) ), `type` (低级病例, `text` (默认), `name`, (中文(简体) ), `id`, (中文(简体) ), `autocomplete`, (中文(简体) ), `placeholder`, (中文(简体) ), `required`,以及 `label` (单位:千美元) `<label>` 以 `for` 或者把它包起来,否则 `aria-label`),以及 `buttons`,其按钮的文本。 a外的字段 `<form>` 不读 `hidden`,一个表格说它是否是隐藏的内容. |

`readStructuredData(blocks)` 将 JSON- LD 块的文本变成相同的结果, 因为您已经拥有了 。 它只检查每个块是JSON;节点是否包含搜索引擎所期望的属性,由呼叫者决定.

链接被 URL 复制,计数,并按数排序. 每个人带着自己的 `text`, (中文(简体) ), `kind`, (中文(简体) ), `resource`, (中文(简体) ), `count`,并且,在目前, `rel`, (中文(简体) ), `target`,以及 `aria-label`。 URL是绝对的; 路径保留它们的情况。 文本读作 DOM 的 `textContent` 有, 实体解码一次, 白空间崩溃 .

## 隐藏内容

与 `hidden`,每个链接、图像和标题都表示它是否包含标记隐藏的内容:a `<template>`页:1 `<dialog>` 无 `open`,则 `hidden` 属性, `aria-hidden="true"` 或者说 `inert`,或 `display: none` 或者说 `visibility: hidden` 在一个 `style` 属性。 这是 `hidesContent(tag, attributes)`,导出,以及 `hiddenFromReaders(tag, attributes)` 这是它的 `aria-hidden` 财务报告和审定财务报表 `inert` 部分,其中未包括主要地标`<main>` 或者说 `role="main"`: 开放模式对话框,如同意对话框,标出其后页 `aria-hidden` 片刻,不是为好,一个在那个状态中渲染和保存的一页仍然带有标记,而没有任何一页向读者隐瞒其主要内容为好. 课堂上什么也猜不到.

替换规则 `true` 考虑到标记中所说的,决定每个要素: `(tag, attributes, byMarkup) => byMarkup && !attributes.class?.includes("popup")` 保持弹出, 它可能有一个印记 `(tag, attributes, byMarkup) => byMarkup || /\bsr-only\b/.test(attributes.class ?? "")` 也隐藏只读屏幕的文本 。 与 `positions`,同一决定还告知哪些容器隐藏了它们的内容,除了这些类别之外,估计数还单独列出.

页面所重复的链接或图像只有在每次发生时才会被隐藏:一个被关闭的菜单和页眉中的标志在一目了然. 标题按页面顺序列出,包含隐藏的,所以标题大纲可以跳过或显示. `<noscript>` 内容是文本给指示器,从未收集.

## 多个需要的一次通行证

询问所有需要的页面,所以读作一次:

```ts
import { parseHtml } from "@citation-media/html-parser";

const page = await parseHtml(await fetch(url), {
  url,
  links: true,
  meta: true,
  structuredData: true,
  text: true,
  markdown: { plugins: { filter: { exclude: ["script", "style"] } } },
});
```

用于响应或流出 `markdown`,身体被读取一次,并喂食活化剂和mdream的转换器相并. 事实出自于mdream的活化剂,调制以保持白空间和CSS如页面所拥有;Markdown出自mdream的转换器不变. 在从4 KB到1.9 MB的18页上测量,所有选项加在一起,大约需要较早的HTML Rewriter传出时间的七分之一时间,而用Markdown的四分之一事实加上两次Markdown转换的事实.

## 头

与 `head`, (中文(简体) ), `parseHtml` 手执 `<head>` 读取为去首: `elements` 按页面顺序列出标题的元素,每个元素都有其 `attributes`,其卡波语 `weight`,则 `size` 以内含内容的字节表示,标题 `text`· ; `issues` 列出未标题的验证器所找到的东西,每个都带有其 `rule`, 取消标题的英语 `message`页:1 `severity`及其索引 `element`。 。 。 .

```ts
const { head } = await parseHtml(html, { url, head: true });
for (const issue of head.issues) {
  console.log(issue.rule, head.elements[issue.element ?? -1]?.attributes);
}
```

规则是无头的,例如 `render-blocking-script`, (中文(简体) ), `charset-not-early`, (中文(简体) ), `too-many-preloads`, (中文(简体) ), `preload-font-crossorigin`, (中文(简体) ), `preconnect-missing-crossorigin`, (中文(简体) ), `inline-style-size`, (中文(简体) ), `non-absolute-canonical`, (中文(简体) ), `og-image-missing-dimensions`,或 `viewport-user-scalable`。除去头部通常对它制作的标记进行排序并去除;在这里,每个元素都是自己一个重量的条目,所以规则读取了页面的顺序和标记。 关于使用Unhead的API的规则,例如 `invalid-input-shape`关闭. `{ head: { rules } }` 通过 unhead 的规则配置,例如 `{ "too-many-preloads": ["warn", { max: 10 }] }` 或者说 `{ "deprecated-twitter-meta": "off" }`。 。 。 .

`weight` 是 Capo 的顺序, 因为它没有标题来计算它: 越低, 越早一个元素属于, 来自 `-30` 内容-安全政策 `-20` 以圆柱盟誓, `10` 标题,和 `50` 用于屏蔽脚本,以至 `100`。一个重量低于一个的元素在它站得比它应该站得晚。 何所报取,而所言取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取取.

## 水分

与 `hydration`, (中文(简体) ), `parseHtml` 从HTML中得知,当服务器发送时,不运行脚本,一个框架是否将浏览器中的页面水合,并测量其序列化到HTML中的数据,该数据是浏览器在页面响应输入之前处理的.

| `framework` | 标记 | `payloadBytes` 计数 |
| --- | --- | --- |
| `astro` | `<astro-island>` 要素 | 每个岛屿的道具,随着HTML携带它们 |
| `next-pages` | `<script id="__NEXT_DATA__">` | 那个脚本 |
| `next-app` | 开始的内置脚本 `self.__next_f` 流线 | 这些脚本 |
| `nuxt` | `<script id="__NUXT_DATA__">`,或 Nuxt 2's 键 `window.__NUXT__ =` | 那个脚本 |
| `sveltekit` | `__sveltekit_… = {` 内在脚本 | 那个脚本 |
| `remix` | `window.__remixContext =` 或反应路由器 `window.__reactRouterContext =` | 那个脚本 |
| `angular` | 元素带有 `ng-version` | `<script id="ng-state">` |

`payloadBytes` 计数字符,对 JSON 来说,框架写的是它的字节。 阿斯特罗的 `islands` 列出前200个 `uid`, (中文(简体) ), `client` 指令, `component` 文档, `propsBytes`,以及 `serverRendered`,这是 `false` 页:1 `client:only` 岛屿。 一个标记只计算在内线脚本的前1000个字符中,所以捆绑时没有提及. Qwik 恢复水分而不是水分 `null`,如同一个脚本在浏览器中渲染而无需服务器给HTML的页面一样.

## 第一个屏幕

与 `positions`,每个图像和Astro岛得到一个 `position`:在滚动前预计在桌面访问时,仅从标记中估算,没有浏览器. 流传的传出没有大小,所以它读出一个元素之前有多少可见的文本和多少图像,以及它是否坐落在一个隐藏的,滑动的,或者固定的容器中,只有在清楚的情况下才能回答:

| `position` | 何时 |
| --- | --- |
| `hidden` | 标记隐藏在元素内,看 [隐藏内容](https://npmcn.com/package/%40citation-media/html-parser/#readme-hidden-content),或者其类标为闭合或只读屏幕的容器,例如 `modal`, (中文(简体) ), `drawer`, (中文(简体) ), `offcanvas`, (中文(简体) ), `popover`, (中文(简体) ), `tooltip`, (中文(简体) ), `sr-only`,或 `screen-reader-text`。 。 。 . |
| `first-screen` | 可见文本的字符少于200个,且其前没有可见图像. |
| `below` | 之前至少有1500个字符和四分之一的页面可见文本. |
| `unknown` | 一切众生. 旋转木马或滑轮的幻灯片总是 `unknown`,因为标记时将它们并列;头或固定或粘性容器中的元素从不 `below`,因为这类集装箱会留在视线内. |

文字输入 `<nav>` 财务报告和审定财务报表 `<header>`,脚本,样式,模板和隐藏容器不计数. 一个图像的位置是它第一次出现的位置.

从小公司网站WordPress和Astro到SaaS网站和一个有486个图像和岛屿的新闻门户

| `position` | 估计数 | 对 |
| --- | --- | --- |
| `below` | 184 (韩语) | 182个不在第一屏幕中:下面135个,47个没有提供 |
| `first-screen` | 第28条 | 28个不在下方:第一个屏幕为17个,11个未渲染,例如封闭菜单中的图像 |
| `hidden` | 第11个 | 11项未交付 |
| `unknown` | 263 (韩语) |  |

这么说吧 `below` 财务报告和审定财务报表 `first-screen` 是指某一元素不在或不在第一个屏幕以下的可靠说法,以及 `unknown` 涵盖所有元素的一半左右. 其出处顺序与所显示内容不同的布局,例如由CSS重排的网格,仍然可以错误地放置一个元素;对于确切的位置,在浏览器中进行测量.

## 读取页面样式

`readStyles` 在没有浏览器的情况下,从 CSS 文本中绘制 CSS 定义和使用内容的映射: `blocks` 财务报告和审定财务报表 `attributes` `parseHtml` 以 `styles`,以及样式表,您可以获取这些样式表,并且,在一个站点的页面中,缓存.

```ts
import { parseHtml, readStyles } from "@citation-media/html-parser";

const { styles } = await parseHtml(html, { url, styles: true });
const sheets = await Promise.all(
  styles.stylesheets.map(async (href) => ({
    css: await (await fetch(href)).text(),
    origin: href,
  }))
);
const map = readStyles([
  ...sheets,
  ...styles.blocks.map(({ css, id }) => ({
    css,
    origin: `inline#${id ?? ""}`,
  })),
  ...styles.attributes.map(({ css, element }) => ({
    css,
    element,
    origin: "attribute",
  })),
]);
```

| 外地 | 它所持有的 |
| --- | --- |
| `variables` | 每个自定义财产(价值、选择者、来源),有多少声明读取过 `var()`,而且,如果其根本定义决定了其中之一,则 `color` 像六分卫一样 定义 `:root`, (中文(简体) ), `html`,或 `:host` 计算页面, 一个外部 `@media` 先说. |
| `colors` | 每一种颜色都有彩色地产, 和它的正弦, 它的地产, 选择者和来源 `variable` 宣言本身的颜色没有。 内退 `var()` 不计为已写入. |
| `fonts` | 每个 `font-family` 财务报告和审定财务报表 `font` 声明的第一个家族和整个堆栈,在解析变量之后,用它通过的变量. |
| `fontFaces` | 家属 `@font-face` 规则加载,有重量,风格, `font-display`,以及 `src`,无论描述者的顺序如何. |
| `imports` | URL( URL) `@import` 规则装入,按照写法,你也可以得到. |

读取器不是完整的 CSS 解析器: 它遵循评论,字符串, 规则, 例如 `@media` 财务报告和审定财务报表 `@layer`CSS 嵌入,保留声明的最内层选择器,跳过 `@keyframes`,而忽略它无法读取的内容。 无所不为:地图上写着CSS写的东西,而不是哪些元素显示出来. `readDeclarations(css, origin)` 返回一个样式表及其选择者和规则的平面声明.

`parseColor` 读取六分法, `rgb()`, (中文(简体) ), `hsl()`, (中文(简体) ), `oklch()`, (中文(简体) ), `oklab()`,并命名颜色为 SRGB; 取决于元素的颜色,例如 `currentcolor` 或者说 `color-mix()`,为 `null`。 。 。 . `colorsIn` 找到每个颜色的值, `toHex` 写出一个为六位数的十六进制 `colorDistance` 测量两种相距有多远(CIE76 in Lab: under 1,眼睛无法分辨它们).

## 清除页面

`cleanHtml` 返回 HTML而不包含您删除的内容。 EXIF和XMP块和二进制外观文本总是被去掉.

```ts
import { cleanHtml } from "@citation-media/html-parser";

const html = await cleanHtml(page, {
  url: "https://example.com/",
  remove: {
    scripts: true,
    styles: true,
    comments: true,
    cookieConsent: true,
    classes: true,
  },
  links: { kinds: ["internal"] },
  context: "main",
});
```

`remove` 接受 `scripts`, (中文(简体) ), `styles` (带有样式属性和内置SVG),, `comments`, (中文(简体) ), `cookieConsent`, (中文(简体) ), `ariaHidden`, (中文(简体) ), `images`, (中文(简体) ), `classes`, (中文(简体) ), `ids`, (中文(简体) ), `meta`, (中文(简体) ), `linkTags`,以及 `hyphenation`链接 `links` 而不成为他们的文本.

`cookieConsent` 由选择者删除广泛同意工具、 Borlabs Cookie、 Cookiebot、 Usercents、Complianz、 OneTrust、 Real Cookie Banner 等对话框、标语和内容阻断器 `consentSelectors` 列表; 列表导出给在浏览器中将同意工具从其所读取或测量内容中退出的呼叫者.

`ariaHidden` 删除屏幕阅读器没有获得的 : `aria-hidden="true"` 或者说 `inert`,以及仅用于屏幕阅读器的文本,例如跳过链接。 开放模式对话框, 如同意对话框, 标记其背后的页面 `aria-hidden` 一瞬间,不是永远的,当对话框打开时,一个页面被渲染和保存,仍然带有标记. 规则 `hiddenFromReaders(tag, attributes)`,导出给自己读取隐藏内容的呼叫者,将主要地标(`<main>` 或者说 `role="main"`),没有任何一页对读者隐瞒;任何其他 `aria-hidden` 或者说 `inert` 元素计数为隐藏, 因为没有浏览器, 无法显示对话框是否打开 。 浏览器脚本可以添加这个条件.

## 标记

Markdown本身就是梦: `markdown` 选项将页面和选项一起交给它。 要使用Mdream的WebAssembly引擎转换,请输入 `mdream` 软件包,请使用同一文本.

相对的Markdown链接和图像使用完整页面 `url` 作为他们的基地。 例如,与 `url: "https://example.com/guides/start/"`, (中文(简体) ), `next/` 决定: `https://example.com/guides/start/next/`设置 `markdown.origin` 摧毁基地.

## 限制

元素以 HTML 解析器的形式打开并关闭 : `<li>` 财务报告和审定财务报表 `<p>` 关闭下一个起始点,元素在页面末尾关闭. `cleanHtml` 需要 HTML Rewriter, 因此它只在 Cloudflare 的运行时间运行 .

## 开发

开发需要节点(Node.js 22.18或以后),该节点将装载Oxlint和Oxfmt的TypeScript配置; `.nvmrc` 针头节点.js 24.

```bash
npm ci
npm test
npm run check
npm run build
```

工作测试 `@cloudflare/vitest-pool-workers` 和在节点,但 `cleanHtml`,需要 HTML 写入器.

`node --expose-gc bench/parse.mjs <directory of .html files> [dist] [options as JSON]` 剖析每页15次,并打印每页的中位数和总数,以比较变化与 `main`建设( e)`npm run build` 复制 `dist` ) (中文(简体) ). 页面不是寄存器的一部分;取几个不同大小的真页.

## 释放

弹出 `version` 内 `package.json` 并添加一节 `CHANGELOG.md` 打开 `main`,然后按下匹配标签,例如 `v0.2.0`. 发布工作流程以出处发布到npm并创建了GitHub发布.

## 许可证

麻省理工学院

## 常见问题

### @citation-media/html-parser 是什么？

HTML 解析器用于任何 JavaScript 运行时间:链接,图像,资源,元数据,JSON-LD,样式,水分,以及文本在一次通过中没有DOM,由mdream的Markdown\.

### 如何安装 @citation-media/html-parser？

在项目目录运行 npm install @citation-media/html-parser，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：@mdream/js（^1\.7\.2 \|\| ^2\.0\.3）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @citation-media/html-parser 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @citation-media/html-parser 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @citation-media/html-parser 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js \>=22\.18\.0。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### @citation-media/html-parser 可以商用吗？

@citation-media/html-parser 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @citation-media/html-parser 的下载量有多少？

根据 npm 官方下载统计，@citation-media/html-parser 在 2026/10/10 – 2026/11/08 这 30 天内被下载 2,042 次，日均约 68 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @citation-media/html-parser 还在维护吗？

最新版本 0\.8\.2 发布于 2026/11/04（5 天前）；至今共发布 14 个版本，其中过去 12 个月发布了 14 个；首次发布于 2026/09/30。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

