# @folsom/tspdf 中文文档

规范地址：https://npmcn.com/package/%40folsom/tspdf/

版本：0\.1\.0
npm 元数据更新时间：2026-07-31T03:58:40.456Z
中文译文更新时间：2026-11-15T04:37:49.410Z
软件包许可：MIT

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

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

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

- 包体积（解压后）：789 kB，11 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- Node.js 要求：\>=18
- 运行依赖：3 个
- 首次发布：2026-07-31T03:58:39.938Z
- 最新版本发布：2026-07-31T03:58:40.273Z
- 近 30 天下载量：2206（2026-10-15 至 2026-11-13，npm 官方下载统计）
- 已发布版本数：1（近 12 个月 1 个）

## 中文简介

一个纯TypeScript PDF核心:懒散的解析,仅附件写入,AcroForm读取/填充/平面/合成,并取出文本. 没有瓦斯姆.

## 安装

```sh
npm install @folsom/tspdf
```

也可以使用：`pnpm add @folsom/tspdf`、`yarn add @folsom/tspdf`、`bun add @folsom/tspdf`

## README

# tspdf 缩写

TypeScript 的快捷,可依赖的光线PDF格式和文本. 没有瓦斯姆.

[![npm](https://img.shields.io/npm/v/@folsom/tspdf.svg)](https://www.npmjs.com/package/@folsom/tspdf) [![bundle size](https://img.shields.io/bundlephobia/minzip/@folsom/tspdf)](https://bundlephobia.com/package/@folsom/tspdf) [![license](https://img.shields.io/npm/l/@folsom/tspdf.svg)](https://npmcn.com/package/%40folsom/tspdf/LICENSE)

-   读取并填充 AcroForm 字段,包括复选框、收音机和下拉
-   生成字段外观( E)`/DA`,自动大小,对齐,梳理,多行)
-   将窗体平整为页面内容
-   提取和搜索页面文本
-   合并、分拆、复制、重排和旋转页面
-   读写 `/Info` 和 XMP 元数据、大纲、页面标签、附件
-   打开加密文件(R2通过R6:RC4,AESV2,AESV3)
-   递增保存该附件而不是重写
-   在节点和浏览器中相同的构建

运行在 `@noble/hashes`, (中文(简体) ), `@noble/ciphers` 财务报告和审定财务报表 `fflate`没有别的.

## 目录

-   [安装](https://npmcn.com/package/%40folsom/tspdf/#readme-installation)
-   [使用量](https://npmcn.com/package/%40folsom/tspdf/#readme-usage)
    -   [阅读文档](https://npmcn.com/package/%40folsom/tspdf/#readme-reading-a-document)
    -   [填写表格](https://npmcn.com/package/%40folsom/tspdf/#readme-filling-a-form)
    -   [检查字段](https://npmcn.com/package/%40folsom/tspdf/#readme-inspecting-fields)
    -   [处理页面](https://npmcn.com/package/%40folsom/tspdf/#readme-working-with-pages)
    -   [文本和搜索](https://npmcn.com/package/%40folsom/tspdf/#readme-text-and-search)
    -   [平滑](https://npmcn.com/package/%40folsom/tspdf/#readme-flattening)
    -   [组合文档](https://npmcn.com/package/%40folsom/tspdf/#readme-assembling-documents)
    -   [元数据和导航](https://npmcn.com/package/%40folsom/tspdf/#readme-metadata-and-navigation)
    -   [同步装入](https://npmcn.com/package/%40folsom/tspdf/#readme-async-loading)
    -   [权限](https://npmcn.com/package/%40folsom/tspdf/#readme-permissions)
    -   [未信任输入](https://npmcn.com/package/%40folsom/tspdf/#readme-untrusted-input)
    -   [逃入对象模型](https://npmcn.com/package/%40folsom/tspdf/#readme-escaping-to-the-object-model)
-   [业绩](https://npmcn.com/package/%40folsom/tspdf/#readme-performance)
-   [限制](https://npmcn.com/package/%40folsom/tspdf/#readme-limitations)
-   [如何测试](https://npmcn.com/package/%40folsom/tspdf/#readme-how-it-is-tested)
-   [捐款](https://npmcn.com/package/%40folsom/tspdf/#readme-contributing)
-   [许可证](https://npmcn.com/package/%40folsom/tspdf/#readme-license)

## 安装

```bash
bun add @folsom/tspdf     # or npm / pnpm / yarn
```

## 使用量

### 阅读文档

```ts
import { PdfDocument } from "@folsom/tspdf";

const doc = PdfDocument.open(bytes);

doc.pageCount;      // 2
doc.encrypted;      // false
doc.info.title;     // "2025 Form 1040"
```

### 填写表格

```ts
const form = doc.form();

form.field("f1_01")?.setValue("Ada Lovelace");
form.field("c1_checkbox")?.setValue(true);
form.field("dropdown")?.setValue("Option B");

const { bytes } = doc.save();
```

保存附件 。 原始字节是输出的字节前缀, 因此设置一个值 a 780 KB文档增加了约500字节,而不是重写文件. 以往的每一次修订都保留 完好无损,这对签署的文件很重要.

`setValue` 报告发生了什么,而不是扔:

```ts
const r = form.field("f1_01")?.setValue("a name longer than the field allows");

r?.ok;         // false if the field is read-only or the value is not a valid choice
r?.written;    // what was stored, truncated to /MaxLen if necessary
r?.reason;     // why, when ok is false
```

### 检查字段

```ts
for (const f of form.allFields()) {
  f.name;        // "topmostSubform[0].Page1[0].f1_01[0]"
  f.kind;        // "text" | "checkbox" | "radio" | "choice" | "signature" | "pushbutton"
  f.value;       // current /V, or null
  f.options;     // /Opt choices
  f.maxLen;      // 0 when unset
  f.readOnly;
}

form.fieldNames();
```

### 处理页面

```ts
const page = doc.page(0);

page.size;               // { width: 612, height: 792 }, after rotation
page.label;              // "i", "ii", "1" ... per /PageLabels
page.widgets();          // widget annotations on this page
page.box("CropBox");
page.setRotation(90);
```

### 文本和搜索

```ts
page.text();                    // whole page as a string
page.search("gross income");    // [{ page, box, quads, text }, ...]
page.glyphs();                  // per-glyph boxes, for layout work

doc.search("income");           // every page
```

搜索默认会崩溃白空间, 因为 PDF 将文字显示操作符的字词断开 不断的,一个字形的匹配 发现远远低于你预期.

### 平滑

```ts
const { baked, dropped, skipped } = doc.flatten();
const { bytes } = doc.save();
```

外观被画入页面内容并去掉表单. 无法烘烤的部件 (隐藏,没有矩形,堕落的盒子) `/Annots` 报告于 `skipped`。 。 。 .

### 组合文档

```ts
import { createDocument, addPage, copyPages, mergeDocuments, splitDocument } from "@folsom/tspdf";

const merged = mergeDocuments([a, b]);
const [chapter1, chapter2] = splitDocument(doc, [[0, 4], [5, 9]]);   // inclusive ranges

const dst = createDocument();
addPage(dst);
copyPages(src, dst, [0, 2, 4]);   // omit indices to copy every page
```

复制页保留其格式字段:被移植的部件被重新植入目的地的下面 `/AcroForm`,因此合并或分拆的文档仍然可以填充.

### 元数据和导航

```ts
doc.info;            // { title, author, subject, keywords, creator, producer, ... }
doc.setInfo({ title: "Filed 2025" });

doc.outline;         // [{ title, page, children }, ...]
doc.pageLabels;      // ["i", "ii", "1", "2", ...]
doc.attachments;     // [{ name, description, data }, ...]
```

### 同步装入

`open()` 在每个平台上是同步的. `load()` 解码结构流与前端 平台的本土 `DecompressionStream`,这在浏览器中更快,之后的每个查询 保持同步 .

```ts
const doc = await PdfDocument.load(bytes, { pages: [0] });
```

### 权限

文件可通过下列途径限制填充、修改和复制: `/P`tspdf执行这些旗帜,所以 限制操作会丢出, 除非您选择退出 :

```ts
doc.page(0).text();                            // PermissionDenied on a copy-restricted file
doc.page(0).text({ allowRestricted: true });   // your call

doc.permissions;   // { print, modify, copy, annotate, fillForms, ... }
```

这些旗帜不是安全边界,因为持有文件的人可以剥去. 他们是 因此,绕过一个是决定而不是意外.

### 未信任输入

打开 PDF 表示解析一个敌对的数据结构. 两个界限默认关闭 :

```ts
PdfDocument.open(bytes, {
  timeoutMs: 5_000,                    // bounds parsing, page walks and xref recovery
  decodeBudget: 64 * 1024 * 1024,      // total decompressed bytes for the document
});
```

超过预算的流解码为空并设置 `doc.budgetExhausted` 而不是抛出, 因此,一个炸弹会降解 而不是拆除过程.

### 逃入对象模型

外表覆盖了常见案件. 为了其他一切, `@folsom/tspdf/lowlevel` 暴露出生层 :

```ts
import { N, isDict, isStream } from "@folsom/tspdf/lowlevel";

const cat = doc.dict(doc.trailer.get(N.Root));
const custom = doc.dict(cat?.get(N.AcroForm));
```

数值类型(`PdfDict`, (中文(简体) ), `PdfStream`, (中文(简体) ), `PdfValue`)从包根再出口,所以 签名无需导入即可保留名称 `lowlevel`。 。 。 .

每一个外观方法代表到自由函数,也可以输出. `doc.page(0).text()` 财务报告和审定财务报表 `getPageText(doc, 0)` 是同一个代码.

## 业绩

重现为 `bun run bench`在f990.pdf上被测量,778 KB有1075个田地.

|  | tspdf 缩写 | pdfium | 木兰花 | pdf-lib 系统 |
| --- | --- | --- | --- | --- |
| 打开 + 读取所有字段 | **7.3 分钟** | 34.4 毫秒(秒) | 20.8毫秒(每秒) | 221.2毫秒(秒) |
| 填入20个字段并保存 | **7.0 ms( 分钟)** | 无 | 径43.8分 | 549.7毫秒(分钟) |
| 平整并保存 | **11.7个毫秒** | 无 | 无 | 525.4 ms (英语) |
| 摘录文本, 一页 | **2.6个毫秒** | 4.8 毫秒( 秒) | 无 | 无 |
| 输出大小 | **790 KB (韩语)** | 无 | 1842 KB (英语) | 1492 KB (韩语) |

两种情况不同: mupdf 和 pdf-lib 读取列只获取字段名称 pdfium 构建了一个比 tspdf 更丰富的文本页面,排序为读取顺序并导出来自 格莱弗轮廓.

持有文档即是不同之处。 木兹 `fill()` 费用是否相同 您设置一个值或200个值, 因为每次呼叫都会重开并重排文件 :

| 设定值 | 木兰花 | tspdf 缩写 | 附 录 |
| --- | --- | --- | --- |
| 1个 | 6.50 毫秒(千分秒) | **0.060毫秒(分钟)** | 0.5 KB (韩语) |
| 10个 | 6.20分钟 | **0.116 毫秒(秒)** | 4.3 KB (韩语) |
| 200个 | 6.57个毫秒 | **0.848 分钟** | 76.0 KB (韩语) |

新鲜过程的冷起步是36.8 ms 与 pdfium 86.9 ms 和 mupdf 的 67.9 ms 相对应 用于处理一个文件和退出的 CLI 的编号.

## 限制

tspdf 无法渲染。 没有光栅,也没有计划。 如果您需要像素, 请使用 pdfium 或 mu. 它还没有:

-   解码图像解码器. DCT, JPX, JBIG2, CCITTFax 和 Brotli 流作为原始字节返回, 带有一个 `undecoded` 旗帜而不是扔出,所以结构和文本仍然用于使用它们的文件.
-   嵌入或子集字体,或嵌入图像. 标准14度标准.
-   画. 没有 `drawText` 编号 : `drawRectangle` 编号 : `drawImage`。 。 。 .
-   读取嵌入式字体程序. 宽和 Unicode 来源于字体词典,而非 TrueType/CFF (英语) `cmap`,它是剩余文本提取出错的主要来源.
-   处理带有打出 API 的部件以外的注释, 虽然它们在回转中幸存下来 .
-   接受用户密码。 处理者假设一个空的,这就是权限锁定的大小写: 大多数公布的表格使用。 它报告这种假设失败时.
-   支持预定义的 CJK CMaps 或垂直写入. 命名的非身份编码作为 2字节身份和身份-V横向排列.
-   创建数字签名,尽管现有签名在增量节约后仍然有效.

## 如何测试

`bun run test` 进行全程检查:122次行为检查,检查过程中产生的PDF,没有 固定文件,没有甲骨文. `test/fixtures.ts` 建造它们;增加一个案例,而不是实施 二进制.

更深的门将 tspdf 与 pdf 和 mupdf 作为 oracles 而不是 自己的 期望,需要根据 `../data`实地 按记录比较记录(46个政府和公司表格的9418个部件,无 匹配; 将书面文件交回两个引擎读取; 生成的外观是 由mupdf进行光化,并比较了墨水覆盖. 文本提取与 pdfium 关于99.80% 字符键.

更宽的覆盖范围来自pdf.js和pdfium regress corpora,932个文件,每个文件都存在 因为他们打破了一个解析器。 tspdf打开了其中908个;pdfium打开了896. 在他们之间 从 R2 到 R6 、 经典和流 xrefs 、 对象流和 恢复路径.

## 捐款

```bash
bun install
bun run build     # dist/ with .js and .d.ts
bun run check     # typecheck, lint, format
bun run test
bun run bench
```

差分的门需要 pdf 和 mupdf 的基线 外加一个体 `../data`数字 :

```bash
bun run gate:diff        # field-for-field against pdfium
bun run gate:roundtrip   # fill, save, re-read with pdfium and mupdf
bun run gate:text        # extraction and window agreement
bun run gate:appearance  # generated /AP against mupdf's rendering
bun run gate:wild <dir>  # obscure and hostile corpora
```

`bun run gate:spec` 不需要这些,而是工作时要跑的.

`test/fetch-corpus.sh` 取出野兽尸体 mupdf、pdfium和pdf-lib是使用的依赖关系 仅作为测量基线.

`test/pdfium.ts` 是 pdfium 甲骨文: 生于 `FPDF_*` 对 WASM 模块绑定 `@hyzyla/pdfium` 已经是船了 因为它出版的包装只覆盖了渲染 它故意不进口任何东西 从 `src/` 一个与它判断的东西共享代码的神谕 证明什么也没有.

`src/` 按子系统分类: `core` (字节、对象、词典、解析器), `codec` (过滤器,密码), `doc`, (中文(简体) ), `text`, (中文(简体) ), `form`, (中文(简体) ), `write`复合模块名称为kebab-case(`page-labels.ts`) (中文(简体) ).

## 许可证

麻省理工学院

## 常见问题

### @folsom/tspdf 是什么？

一个纯TypeScript PDF核心:懒散的解析,仅附件写入,AcroForm读取/填充/平面/合成,并取出文本\. 没有瓦斯姆\.

### 如何安装 @folsom/tspdf？

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

### @folsom/tspdf 支持 TypeScript 吗？

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

### @folsom/tspdf 支持 ESM 还是 CommonJS？

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

### @folsom/tspdf 需要什么版本的 Node\.js？

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

### @folsom/tspdf 可以商用吗？

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

### @folsom/tspdf 的下载量有多少？

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

### @folsom/tspdf 还在维护吗？

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

