# @agulbra/uts58 中文文档

规范地址：https://npmcn.com/package/%40agulbra/uts58/

版本：0\.2\.6
npm 元数据更新时间：2026-10-29T16:50:29.829Z
中文译文更新时间：2026-11-05T23:25:54.767Z
软件包许可：BSD-2-Clause

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

原始 npm 页面：https://www.npmjs.com/package/%40agulbra/uts58
原文对照：https://npmcn.com/package/%40agulbra/uts58/?lang=original
项目主页：https://github.com/arnt/uts58#readme
源码仓库：https://github.com/arnt/uts58

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

- 包体积（解压后）：72.5 kB，14 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- Node.js 要求：\>=18
- 运行依赖：1 个
- 首次发布：2026-06-25T12:28:37.578Z
- 最新版本发布：2026-10-29T16:50:29.301Z
- 近 30 天下载量：9640（2026-10-05 至 2026-11-03，npm 官方下载统计）
- 已发布版本数：4（近 12 个月 4 个）

## 中文简介

UTS #58 为JavaScript所提取的网页链接.

## 安装

```sh
npm install @agulbra/uts58
```

也可以使用：`pnpm add @agulbra/uts58`、`yarn add @agulbra/uts58`、`bun add @agulbra/uts58`

## README

# uts 58 号

JavaScript 执行 [UTS58卫星](https://www.unicode.org/reports/tr58/), (中文(简体) ), 用于在运行中文本中查找链接的 Unicode spec 。 说来话长 返回其中的 URL 及其 UTF-16 偏移。 这是港口 页:1 [鲁比 `uts58` 宝石](https://github.com/arnt/uts58);测试套房是 相同,但差别很小.

对相关操作系统进行了广泛测试: [![CI](https://github.com/arnt/uts58/actions/workflows/javascript.yml/badge.svg)](https://github.com/arnt/uts58/actions/workflows/javascript.yml)

## 安装

```sh
npm install @agulbra/uts58
```

仅限ESM;节点18+(使用Unicode属性逃脱并外观后方). 从0.2.4开始 浏览器也应该有用.

## 使用量

```js
import { extractUrls, extractUrlsWithIndices } from '@agulbra/uts58';

extractUrlsWithIndices('see https://example.com/ for details');
// => [{ url: 'https://example.com/', indices: [4, 24] }]

extractUrls('see https://example.com/ for details');
// => ['https://example.com/']
```

API 镜像 `twitter-text`是因为 `Extractor#extractUrlsWithIndices` 密切; 写它是为了提供 马斯托顿式的消费者需要的 两者 上面的顶级函数也会通过 `Extractor#removeOverlappingEntities`: 候选人按开始排序 和任何开始于 早期幸存者的时间段 掉下来了 长度不包含在内;开始较早的候选人 即使后期的胜负更长.

导入 `Extractor` 如果你愿意和别人合并的话 提取器(注释、标签.)和解决所有重叠 他们自己.

承认没有计划的投入 `https://` 预设于 已返回 `url`数字 :

```js
extractUrlsWithIndices('blogspot.com is still a thing');
// => [{ url: 'https://blogspot.com', indices: [0, 12] }]
```

一样 `twitter-text`你可以通过 `{ extractUrlsWithoutProtocol: false }` 只查找从 `http://` 或者说 `https://`默认为 `true`与UTS58相匹配 .

IDN在输出中被解码为使用UTF-8,以便更好的可读性:

```js
extractUrls('xn-----ctdbabcfhu9c2b9l1acccr4c.xn--mgbah1a3hjkrd')[0];
// => 'https://تجربة-القبول-الشامل.موريتانيا'
```

(诚然,如果不能读阿拉伯语,输出不易读取. 不过 无论他们能读哪种语言

跟踪出点、平衡括号、端口、路径、查询和 按规格处理碎片。 输出中的索引为 UTF-16 代码单位抵消( `String.prototype.slice`, (中文(简体) ), `String#length`,DOM,和文本编辑器),所以 `text.slice(start, end)` 返回直接匹配的子字符串,甚至跨字符 在BMP门外 (这与鲁比版本不同. 鲁比喜欢 用代码点抵消, Ruby 宝石跟着 公约. `example.com/🐪/#camel` 是一个很好的测试 区别, 因为emoji是一个代码点 但两个UTF-16单位

## 电子邮件地址

```js
import {
  extractEmailAddresses,
  extractEmailAddressesWithIndices,
  extractEntities,
  extractEntitiesWithIndices,
} from '@agulbra/uts58';

extractEmailAddressesWithIndices('contact info@grå.org today');
// => [{ email: 'info@grå.org', url: 'mailto:info@grå.org', indices: [8, 20] }]

extractEmailAddresses('contact info@grå.org today');
// => ['info@grå.org']
```

每一个结果都带着光 `email` (单位:千美元) `mailto:` `url`,所以这个 直接掉入任何已经形成 `url` 实体。 这个 域名的IDN-解码方式与输入方式相同 `extractUrls`和领先 `mailto:` 在输入中吸收为 `indices` 每UTS58 5.2.

一个简单的地址与空域重叠 `extractUrls` 会发现 之后 `@`。 。 。 . `extractEntitiesWithIndices` 运行两个提取器, 排序并删除重叠。 电子邮件地址开始 并赢得它内部的域:

```js
extractEntities('mail arnt@grå.org or see blogspot.com');
// => ['mailto:arnt@grå.org', 'https://blogspot.com']
```

## 选择公共后缀检查

决定是否 `something.example` 是一个可信的链接,提取器 对照一个公共后缀表检查主机. 哪张桌子是捆绑时间 选择 :

| 导入 | 图表 | 击出 |
| --- | --- | --- |
| `@agulbra/uts58` (默认) | 公共后缀列表, ICANN 部分 | ~5 KB 键 |
| `@agulbra/uts58/iana` | IANA 根区 TLDs | ~5 KB 键 |
| `@agulbra/uts58/core` | 没有,你提供支票 | 0个KB |

三个都暴露了同一个API. 两张桌子大小差不多 并且几乎同意每个东道主。 区别在于检查有多严格 是为少数只登记在第二位的TLD 级别. `@agulbra/uts58/iana` 仅问“最正确的标签是真实的 TLD":足以告诉 `blogspot.jp` 从 `blogspot.exe` 和拒绝 类似 `example.cmo`但它对待一个赤裸裸 `foo.za` 作为 难以置信。 默认 `@agulbra/uts58` 携带 PSL,它知道 南非登记 `co.za` 编号 : `org.za` 故你应当否认赤裸的 `foo.za`如果这种区别对你无关紧要的话,表格就是 可互换.

也没有复制 PSL 的通配符/例外规则: 这里的问题是 "这可能是一个链接" 不是"哪里是确切的可登记边界" 所以 统一会员制是它所做的一切。 PSL 表格相应折叠, 这就是为什么gzip表只比IANA列表大出几字节.

`@agulbra/uts58/core` 捆绑完全没有表格,然后插入自己的表格 像这样检查 :

```js
import { Extractor } from '@agulbra/uts58/core';
import { parse } from 'tldts';

const ex = new Extractor({
  isPlausibleHost: (host) => {
    const p = parse(host);
    return !!p.domain && p.isIcann && p.publicSuffix !== 'invalid';
  },
});
ex.extractUrls('see example.com here');
```

这条路线也是你如何用PSL语义 来取回精确的PSL语义的 依赖您选择的不是这个包的力量 。 ()`@agulbra/uts58` 本身仅取决于 `punycode`. ) (中文(简体) )

## 建议的试验案例和显著行为

有一些尖锐的边缘 你也许应该覆盖 在自己的测试.

**这个 `href` 而可见文本不是相同的字符串.** 对于 `see example.com here`,则 `indices` 间距 `example.com`不过 `url` 时间更长 `https://example.com`。 。 。 . 使用 `url` 联 合 国 `href` 属性,将原始文本从 `indices` 对于可见的内容。 比较一下 `text.slice(start, end) === url` 所有无计划的投入都将失败, 和每个IDN上的A-标签被解码.

**没有 `autoLink`。 。 。 .** 这个包裹是提取的,它不渲染。 还有 无等值 `twitter-text`是因为 `autoLink`, (中文(简体) ), `autoLinkUrlsCustom`, (中文(简体) ), `htmlEscape`等——构建HTML是呼叫者的工作. 此代码 不决定逃跑.

**没有提及,标签,现金,答复.** UTS58没有定义 他们,所以这个包裹也没有。 如果你需要的话,快跑 `twitter-text` (或另作取出者) 合并到 `Extractor#removeOverlappingEntities`。 。 。 .

**重叠解析为起步取胜,不是最长取胜.** 这需要测试 当您从多个提取器合并实体时. `ask alice@example.com/02074960909 for details` 说明为什么 生下来的 提取器查找两个邮件 `alice@example.com` 时间 `[4, 21]` ưμ㼯a `https://example.com/02074960909` 时间 `[10, 33]`。初赢保持 `alice@example.com`人类读者可能认为 至少一个读了02074960909的电话号码. 最长的赢会保持更长的时间 `https://example.com/02074960909`。 。 。 .

**`maxLength` 测量匹配输入跨度.** 不是返回的 URL . 如果您通过 12 个码口, 密码会保留 `blogspot.com` (12) 和 减 `https://example.com`,即使输入跨度和 `url` 刚好 那边一样 非对称性出现了相反的方式 `example.com` (11个输入cp,19英吋) `url`),其中12个上限允许代码 检测链接.

虽然大部分API都以UTF-16(如"弦")来计算 类, MaxLength 使用代码点。 原因是大多数API 用于软件开发,但最大Length是用于终端用户 代码点更接近终端用户所看到的。“qq”和“qq”都是其中之一 代码长。 (这还不算完美: "é"可能是其中之一或 2个代码长而"Q"为2个. 生平艰难. )

**`mailto:` 被吸收为 `indices`。 。 。 .** 每UTS58 5.2,输入 `mailto:abcd@example.com` 返回覆盖 整个23码点运行, 不只是地址。 这个 `email` 字段还原 保持赤裸的地址。 如果您的链接传输代码假设跨度 从本地部分开始, 邮件输入会给它带来惊喜 .

## 什么不在这里

-   **链接验证.** 已识别的 URL 不被获取、 正常化 除了IDN解码, 或者他们的主机名在 DNS 中检查。 有一个 \* 未试图检查可能的攻击`Мышκин.рф` 财务报告和审定财务报表 `Мышкин.рф` 注意希腊卡帕在中间 王子的名字).

## 重生成生成的表格

`src/constants.js` (链接终止和括号表) ruby 参考文献 `constants.rb`数字 :

```sh
npm run maketables
```

写着 `../ruby/lib/uts58/constants.rb` 默认; 传递指向路径 在别的地方. `constants.rb` 本身在鲁比一侧产生,在那里 `tools/maketables.rb` 下载 UTS58 数据文件(`LinkTerm.txt` 财务报告和审定财务报表 `LinkBracket.txt`直接从unicode.org, 所以真理的来源是 Unicode发布数据.

`src/tlds-iana.js` 财务报告和审定财务报表 `src/suffixes-psl.js` 是公共后缀表格. 没有争吵,他们从他们的神话来源获得 (单位:千美元)[冰岛](https://data.iana.org/TLD/tlds-alpha-by-domain.txt), (中文(简体) ), [PSL 软件](https://publicsuffix.org/list/public_suffix_list.dat)) (中文(简体) ). 通过本地 线下再生路径 :

```sh
npm run maketlds
npm run maketlds -- /path/to/tlds-alpha-by-domain.txt /path/to/public_suffix_list.dat
```

## 许可证

BSD-2-克劳斯. 见 `LICENSE`。 。 。 .

FWIW,我写这个作为我在ICANN工作的一部分,并将保持为 同一作品的一部分。 (我解决了与Unicode有关的 域、电子邮件地址和类似地址,因此更多人,更多 以他们喜欢的方式使用互联网

## 常见问题

### @agulbra/uts58 是什么？

UTS \#58 为JavaScript所提取的网页链接\.

### 如何安装 @agulbra/uts58？

在项目目录运行 npm install @agulbra/uts58，或使用 pnpm add / yarn add / bun add。

### @agulbra/uts58 支持 TypeScript 吗？

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

### @agulbra/uts58 支持 ESM 还是 CommonJS？

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

### @agulbra/uts58 需要什么版本的 Node\.js？

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

### @agulbra/uts58 可以商用吗？

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

### @agulbra/uts58 的下载量有多少？

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

### @agulbra/uts58 还在维护吗？

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

