@shuji-bonji/pdf-writer-mcp 0.3.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +190 -0
- package/README.ja.md +156 -0
- package/README.md +105 -171
- package/dist/config.js +1 -1
- package/dist/config.js.map +1 -1
- package/dist/constants.d.ts +16 -0
- package/dist/constants.js +24 -0
- package/dist/constants.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/services/annotation.d.ts +17 -0
- package/dist/services/annotation.js +90 -0
- package/dist/services/annotation.js.map +1 -0
- package/dist/services/builder.js +32 -4
- package/dist/services/builder.js.map +1 -1
- package/dist/services/editor.d.ts +3 -1
- package/dist/services/editor.js +19 -2
- package/dist/services/editor.js.map +1 -1
- package/dist/services/font-manager.d.ts +1 -1
- package/dist/services/font-manager.js +1 -1
- package/dist/services/font-manager.js.map +1 -1
- package/dist/services/layout.d.ts +17 -1
- package/dist/services/layout.js +46 -13
- package/dist/services/layout.js.map +1 -1
- package/dist/services/outline.d.ts +20 -0
- package/dist/services/outline.js +93 -0
- package/dist/services/outline.js.map +1 -0
- package/dist/services/output.js +2 -2
- package/dist/services/output.js.map +1 -1
- package/dist/services/renderers/markdown.d.ts +1 -1
- package/dist/services/renderers/markdown.js +58 -15
- package/dist/services/renderers/markdown.js.map +1 -1
- package/dist/services/renderers/table.d.ts +1 -1
- package/dist/services/renderers/table.js +30 -16
- package/dist/services/renderers/table.js.map +1 -1
- package/dist/services/renderers/text.d.ts +1 -1
- package/dist/services/renderers/text.js +4 -1
- package/dist/services/renderers/text.js.map +1 -1
- package/dist/services/struct-tree.d.ts +79 -0
- package/dist/services/struct-tree.js +222 -0
- package/dist/services/struct-tree.js.map +1 -0
- package/dist/services/xmp.d.ts +42 -0
- package/dist/services/xmp.js +133 -0
- package/dist/services/xmp.js.map +1 -0
- package/dist/tools/definitions.d.ts +156 -0
- package/dist/tools/definitions.js +89 -0
- package/dist/tools/definitions.js.map +1 -1
- package/dist/tools/handlers.d.ts +2 -0
- package/dist/tools/handlers.js +17 -6
- package/dist/tools/handlers.js.map +1 -1
- package/dist/types/index.d.ts +54 -0
- package/dist/utils/lang.d.ts +18 -0
- package/dist/utils/lang.js +30 -0
- package/dist/utils/lang.js.map +1 -0
- package/dist/utils/validation.d.ts +3 -1
- package/dist/utils/validation.js +82 -5
- package/dist/utils/validation.js.map +1 -1
- package/package.json +14 -3
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## [0.5.0] - 2026-07-16
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- **Tagged PDF / PDF/UA-1 (ISO 14289)** via `tagged: true` on the create tools.
|
|
10
|
+
Output is **verified compliant by veraPDF** (`--flavour ua1`, 106/106 rules) for
|
|
11
|
+
text, Markdown, and table documents.
|
|
12
|
+
|
|
13
|
+
Opt-in by design: existing behaviour is unchanged unless you ask for tagging.
|
|
14
|
+
PDF/UA mandates a document title, so `tagged: true` requires `title`.
|
|
15
|
+
|
|
16
|
+
- Structure tree (`StructTreeRoot`, `StructElem`, `ParentTree`) built from
|
|
17
|
+
pdf-lib's low-level object model — it has no logical-structure API.
|
|
18
|
+
- Every drawn line is wrapped in `/Tag <</MCID n>> BDC … EMC`, and decorations
|
|
19
|
+
(rules, cell borders, code backgrounds) become `/Artifact BMC … EMC` (7.1-3).
|
|
20
|
+
- Markdown maps to structure: headings → `H1`–`H6`, lists → `L`/`LI`/`LBody`,
|
|
21
|
+
tables → `Table`/`TR`/`TH`/`TD`, quotes → `BlockQuote`, code → `Code`.
|
|
22
|
+
- Heading levels are normalised so they start at H1 and never skip (7.4.2).
|
|
23
|
+
A Markdown `# → ###` jump becomes `H1 → H2`; visual sizes are untouched.
|
|
24
|
+
- Table headers carry `/A << /O /Table /Scope /Column >>` (7.5-1).
|
|
25
|
+
- XMP is generated in-house (pdf-lib has no XMP API) with the `pdfuaid`
|
|
26
|
+
declaration **and** the PDF/A extension schema description — veraPDF rejects
|
|
27
|
+
the declaration without it (5-1).
|
|
28
|
+
- `/Lang`, `/ViewerPreferences /DisplayDocTitle`, `/MarkInfo /Marked`.
|
|
29
|
+
|
|
30
|
+
- **`lang` option** (BCP 47). When omitted under `tagged: true` the language is
|
|
31
|
+
inferred from the text and reported via `warnings`. Inference is conservative:
|
|
32
|
+
kana → `ja`, Hangul → `ko`, Han without kana → `ja` *with a warning that it
|
|
33
|
+
could be Chinese*. A wrong `/Lang` makes screen readers mispronounce text, so
|
|
34
|
+
the guess is always surfaced rather than silently applied.
|
|
35
|
+
|
|
36
|
+
### Fixed
|
|
37
|
+
|
|
38
|
+
- **Bullets in unordered lists rendered as `.notdef`** (blank boxes) — a
|
|
39
|
+
regression from 0.3.0. Font subsetting is driven by the *input* text, but the
|
|
40
|
+
Markdown renderer adds characters of its own: `- item` contains no bullet, yet
|
|
41
|
+
`•` is drawn. Those glyphs were missing from the subset. Renderer-generated
|
|
42
|
+
characters are now always subset in (`RENDERER_GENERATED_CHARS`).
|
|
43
|
+
|
|
44
|
+
Text extraction was unaffected, which is why no existing test caught it;
|
|
45
|
+
veraPDF's 7.21.8-1 (no `.notdef` references) is what surfaced it.
|
|
46
|
+
|
|
47
|
+
- XMP metadata is written as UTF-8 bytes. `context.stream(string)` writes one
|
|
48
|
+
byte per character, which mangled Japanese titles.
|
|
49
|
+
|
|
50
|
+
## [Unreleased]
|
|
51
|
+
|
|
52
|
+
### Changed
|
|
53
|
+
|
|
54
|
+
- **biome adopted** for linting and formatting, matching the rest of the family
|
|
55
|
+
(same `biome.json`, same scripts). `npm run check` now runs in CI and in the
|
|
56
|
+
publish workflow. Existing sources were reformatted; the suite is clean.
|
|
57
|
+
- The version is pinned to an exact `2.5.4` rather than a caret range. Biome's
|
|
58
|
+
formatting output changes between minor releases, so a range lets a local
|
|
59
|
+
`npm install` drift ahead of CI and produce spurious diffs.
|
|
60
|
+
|
|
61
|
+
### Fixed
|
|
62
|
+
|
|
63
|
+
- `handleCreateTablePdf` duplicated the Latin-1 check as a regex containing
|
|
64
|
+
control characters; it now reuses the existing `hasNonLatin1` helper.
|
|
65
|
+
- `src/config.ts` imports `node:module` rather than the bare `module` specifier.
|
|
66
|
+
|
|
67
|
+
## [0.4.0] - 2026-07-16
|
|
68
|
+
|
|
69
|
+
### Added
|
|
70
|
+
|
|
71
|
+
- **Editing tools (Tier A, wave 2)**:
|
|
72
|
+
- `add_bookmarks` — set the document outline. Nestable via `children` (up to 8
|
|
73
|
+
levels, 2000 entries). Replaces any existing outline. Titles are written as
|
|
74
|
+
UTF-16BE so CJK round-trips correctly. Open items carry a positive `/Count`,
|
|
75
|
+
collapsed items a negative one, per ISO 32000-1 §12.3.3.
|
|
76
|
+
- `add_annotation` — add a `text` (sticky note), `highlight`, or `square`
|
|
77
|
+
annotation. Coordinates use PDF space (origin bottom-left, points). Colors
|
|
78
|
+
are `#rrggbb`; `contents` and `author` accept CJK.
|
|
79
|
+
|
|
80
|
+
pdf-lib exposes no outline or annotation API, so both are built from the
|
|
81
|
+
low-level object model (`services/outline.ts`, `services/annotation.ts`).
|
|
82
|
+
|
|
83
|
+
## [0.3.1] - 2026-07-16
|
|
84
|
+
|
|
85
|
+
### Fixed
|
|
86
|
+
|
|
87
|
+
- **Text extraction broken for digits in Latin context** (regression introduced in
|
|
88
|
+
0.3.0): `subsetFont` is now called with `noLayoutClosure: true`.
|
|
89
|
+
|
|
90
|
+
pdf-lib's `CustomFontEmbedder` (used with `subset: false`) derives glyphs
|
|
91
|
+
through two independent paths: the CIDs written into the content stream come
|
|
92
|
+
from `font.layout(text)` — **after** GSUB substitution — while the ToUnicode
|
|
93
|
+
CMap is built from `font.characterSet` → `glyphForCodePoint` — **before**
|
|
94
|
+
substitution. Noto Sans JP substitutes ASCII digits with alternate forms in
|
|
95
|
+
Latin context (`layout('English 0')` yields glyph 17460, not 17), so the two
|
|
96
|
+
disagreed and extraction returned wrong characters (`v0.3.0` → `vô.õ.ô`, and
|
|
97
|
+
poppler dropped the digits entirely). Rendering was correct throughout, which
|
|
98
|
+
made this easy to miss.
|
|
99
|
+
|
|
100
|
+
Excluding layout-reachable glyphs from the subset prevents the substitution
|
|
101
|
+
altogether, so `layout()` and `glyphsForString()` agree again. Subsets also got
|
|
102
|
+
smaller as a side effect (9.1 KB → 4.5 KB for a typical page).
|
|
103
|
+
|
|
104
|
+
### Added
|
|
105
|
+
|
|
106
|
+
- `render.test.ts` now asserts that the CIDs written to the page match the
|
|
107
|
+
ToUnicode CMap, so this class of regression fails the suite.
|
|
108
|
+
|
|
109
|
+
## [0.3.0] - 2026-07-16
|
|
110
|
+
|
|
111
|
+
### Fixed
|
|
112
|
+
|
|
113
|
+
- **Japanese text rendered as blank boxes in every viewer** (Chrome, Firefox,
|
|
114
|
+
Acrobat, poppler, Claude Desktop). Font subsetting no longer goes through
|
|
115
|
+
pdf-lib's `embedFont(subset: true)`: fonts are now pre-subset with harfbuzz
|
|
116
|
+
([subset-font](https://github.com/papandreou/subset-font)) and embedded with
|
|
117
|
+
`subset: false`.
|
|
118
|
+
|
|
119
|
+
fontkit's subsetter drops glyph outlines for CJK fonts. Because the ToUnicode
|
|
120
|
+
CMap stayed correct, text extraction kept working and the existing tests
|
|
121
|
+
passed while the visible output was broken.
|
|
122
|
+
|
|
123
|
+
| Approach | PDF size | Rendering |
|
|
124
|
+
|---|---|---|
|
|
125
|
+
| fontkit `subset: true` (previous) | 24 KB | broken |
|
|
126
|
+
| pdf-lib `subset: false` alone | 3.9 MB | correct |
|
|
127
|
+
| harfbuzz + `subset: false` (current) | 14.5 KB | correct |
|
|
128
|
+
|
|
129
|
+
- The note in the design doc claiming poppler's `Embedded font file may be
|
|
130
|
+
invalid` warning was harmless is retracted — poppler followed it with
|
|
131
|
+
`Couldn't create a font`, i.e. the warning was the breakage.
|
|
132
|
+
|
|
133
|
+
### Added
|
|
134
|
+
|
|
135
|
+
- `render.test.ts`: extracts the embedded font program from generated PDFs and
|
|
136
|
+
verifies that every rendered character retains a real glyph outline. Verified
|
|
137
|
+
to fail against the pre-0.3.0 implementation.
|
|
138
|
+
- CI fetches Noto Sans JP and sets `TEST_FONT_PATH`, so the font-dependent tests
|
|
139
|
+
no longer skip.
|
|
140
|
+
|
|
141
|
+
### Changed
|
|
142
|
+
|
|
143
|
+
- `loadFont` split into `openFont` (read + glyph coverage) and `embedFontFor`
|
|
144
|
+
(subset + embed). Subsetting depends on the text being drawn, so embedding is
|
|
145
|
+
deferred until the input is final.
|
|
146
|
+
- **Dependency added**: `subset-font` (harfbuzz/wasm, no native binaries).
|
|
147
|
+
|
|
148
|
+
## [0.2.1] - 2026-07-16
|
|
149
|
+
|
|
150
|
+
### Added
|
|
151
|
+
|
|
152
|
+
- **`onMissingGlyph` option** for the create tools. Characters absent from the
|
|
153
|
+
font (e.g. ✔ U+2714, which Noto Sans JP does not include) were previously
|
|
154
|
+
embedded as `.notdef` and rendered as silent blanks.
|
|
155
|
+
- `error` (default) — list the offending characters and fail
|
|
156
|
+
- `replace` — substitute 〓 and report via `warnings`
|
|
157
|
+
- `ignore` — render as before and report via `warnings`
|
|
158
|
+
- `CreateResult.warnings` reports substituted or ignored characters.
|
|
159
|
+
|
|
160
|
+
## [0.2.0] - 2026-07-16
|
|
161
|
+
|
|
162
|
+
### Added
|
|
163
|
+
|
|
164
|
+
- **Editing tools (Tier A, wave 1)** — the server now edits existing PDFs in
|
|
165
|
+
addition to creating them:
|
|
166
|
+
- `set_metadata` — update Info dictionary fields, preserving the rest
|
|
167
|
+
- `merge_pdfs` — concatenate in order (metadata inherited from the first file)
|
|
168
|
+
- `split_pdf` — one file per page range
|
|
169
|
+
- `extract_pages` — extract in the requested order (doubles as reordering)
|
|
170
|
+
- `delete_pages` — remove pages (deleting all is rejected)
|
|
171
|
+
- `reorder_pages` — reorder by an explicit permutation
|
|
172
|
+
- `rotate_pages` — rotate clockwise, accumulating over existing rotation
|
|
173
|
+
- **Signature guard**: editing a PDF with `/ByteRange` fails by default, since
|
|
174
|
+
pdf-lib rewrites the whole file and would invalidate existing signatures.
|
|
175
|
+
Pass `allowBreakingSignatures: true` to proceed anyway.
|
|
176
|
+
- Page specs (`"1,3-5,8-"`, 1-based, order-preserving, duplicates removed).
|
|
177
|
+
- CI (`ci.yml`) and npm publish via Trusted Publisher / OIDC (`publish.yml`).
|
|
178
|
+
|
|
179
|
+
## [0.1.0] - 2026-07-15
|
|
180
|
+
|
|
181
|
+
Initial release.
|
|
182
|
+
|
|
183
|
+
### Added
|
|
184
|
+
|
|
185
|
+
- `create_text_pdf` — plain text with paragraph breaks, wrapping, pagination
|
|
186
|
+
- `create_markdown_pdf` — headings, lists, code blocks, quotes, rules, tables
|
|
187
|
+
- `create_table_pdf` — ruled tables with automatic column widths and repeated
|
|
188
|
+
headers across page breaks
|
|
189
|
+
- Japanese font embedding, ToUnicode CMap (extractable/searchable text),
|
|
190
|
+
file or base64 output, `asserts`-based input validation.
|
package/README.ja.md
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# pdf-writer-mcp
|
|
2
|
+
|
|
3
|
+
[](https://github.com/shuji-bonji/pdf-writer-mcp/actions/workflows/ci.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/@shuji-bonji/pdf-writer-mcp)
|
|
5
|
+
[](./LICENSE)
|
|
6
|
+
|
|
7
|
+
[English](./README.md)
|
|
8
|
+
|
|
9
|
+
テキスト / Markdown / 表データからの **PDF 生成** と、既存 PDF の **編集**(メタデータ・ページ操作)を行う MCP (Model Context Protocol) サーバです。[pdf-lib](https://pdf-lib.js.org/) をコアに、harfbuzz サブセットによる日本語フォント埋め込みに対応します。
|
|
10
|
+
|
|
11
|
+
[pdf-reader-mcp](https://github.com/shuji-bonji/pdf-reader-mcp)(構造解析)、[pdf-verify-mcp](https://github.com/shuji-bonji/pdf-verify-mcp)(真正性検証)と同じ PDF family の一員です。`pdf-reader-mcp` が「何があるか」を読み、`pdf-verify-mcp` が「本物か」を検証するのに対し、`pdf-writer-mcp` は「それを書く」役割を担います。
|
|
12
|
+
|
|
13
|
+
## ツール
|
|
14
|
+
|
|
15
|
+
### 生成
|
|
16
|
+
|
|
17
|
+
| ツール | 役割 |
|
|
18
|
+
|--------|------|
|
|
19
|
+
| `create_text_pdf` | プレーンテキスト — `\n` で改行、空行で段落区切り、長い行は自動折り返し |
|
|
20
|
+
| `create_markdown_pdf` | Markdown — 見出し / 段落 / 箇条書き・番号リスト / コードブロック / 引用 / 水平線 / 表 |
|
|
21
|
+
| `create_table_pdf` | 罫線付き表 — 列幅の自動算出、セル内折り返し、改ページ時のヘッダ再描画 |
|
|
22
|
+
|
|
23
|
+
共通オプション: `outputPath` / `returnBase64` / `fontPath` / `fontSize` / `pageSize`(A4/A3/A5/LETTER/LEGAL)/ `margin` / `title` / `author` / `onMissingGlyph` / `tagged` / `lang`。
|
|
24
|
+
|
|
25
|
+
### タグ付き PDF / PDF/UA(v0.5.0)
|
|
26
|
+
|
|
27
|
+
`tagged: true` を指定すると、**PDF/UA-1(ISO 14289)準拠のタグ付き PDF**(アクセシブルな PDF)を生成します。veraPDF(`--flavour ua1`)で 106/106 規則の準拠を確認済みです。
|
|
28
|
+
|
|
29
|
+
```jsonc
|
|
30
|
+
{ "markdown": "# 見出し\n\n本文。", "title": "レポート", "tagged": true, "lang": "ja" }
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Markdown は構造木に対応付けられます。見出し → `H1`〜`H6`、リスト → `L`/`LI`/`LBody`、表 → `Table`/`TR`/`TH`/`TD`(ヘッダには `/Scope`)、引用 → `BlockQuote`、コード → `Code`。水平線・罫線・コード背景は Artifact になります。見出しレベルは「H1 始まり・飛ばさない」よう正規化されるため、Markdown の `# → ###` は構造上 `H1 → H2` になります(見た目のサイズは元のままです)。
|
|
34
|
+
|
|
35
|
+
PDF/UA はタイトルを要求するため、`tagged: true` では `title` が必須です。`lang`(BCP 47)は省略すると本文から推定し、`warnings` で報告します。**誤った `/Lang` はスクリーンリーダの誤読を招く**ため、分かっている場合は明示してください。
|
|
36
|
+
|
|
37
|
+
> タグ付けは opt-in です(既定の出力は変わりません)。機械検証は「読み順や代替テキストが**適切か**」までは判定できず、存在の有無しか見られません。人手の確認は依然として必要です。
|
|
38
|
+
|
|
39
|
+
### 編集
|
|
40
|
+
|
|
41
|
+
| ツール | 役割 |
|
|
42
|
+
|--------|------|
|
|
43
|
+
| `set_metadata` | Info 辞書の更新(`title` / `author` / `subject` / `keywords` / `creator`)。指定フィールドのみ変更し、他は保持 |
|
|
44
|
+
| `merge_pdfs` | 2〜50 個の PDF を指定順に結合。メタデータは先頭ファイルから引き継ぎ |
|
|
45
|
+
| `split_pdf` | ページ範囲ごとに 1 ファイルへ分割 |
|
|
46
|
+
| `extract_pages` | 指定順を保持して抽出(並べ替えを兼ねる) |
|
|
47
|
+
| `delete_pages` | ページ削除(全ページの削除はエラー) |
|
|
48
|
+
| `reorder_pages` | 全ページの順列による並べ替え |
|
|
49
|
+
| `rotate_pages` | 時計回りに回転(90/180/270)。既存の回転に加算 |
|
|
50
|
+
| `add_bookmarks` | しおり(アウトライン)の設定。`children` で入れ子にでき、既存のしおりは置換 |
|
|
51
|
+
| `add_annotation` | 付箋(`text`)/ ハイライト(`highlight`)/ 矩形(`square`)の注釈を追加 |
|
|
52
|
+
|
|
53
|
+
共通オプション: `outputPath` / `returnBase64` / `allowBreakingSignatures`。
|
|
54
|
+
|
|
55
|
+
ページ指定は `"1,3-5,8-"` 形式(1 始まり。`-3` は先頭から 3 ページまで、`8-` は 8 ページから最終まで)。指定順を保持し、重複は除去します。
|
|
56
|
+
|
|
57
|
+
> **署名について**: pdf-lib は保存時にファイル全体を再構築するため、編集すると既存の電子署名は必ず無効化されます。`/ByteRange` を含む PDF は既定でエラーとし、`allowBreakingSignatures: true` を指定したときのみ続行します。署名を保持する増分更新はロードマップ参照。
|
|
58
|
+
|
|
59
|
+
## インストール
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"mcpServers": {
|
|
64
|
+
"pdf-writer": {
|
|
65
|
+
"command": "npx",
|
|
66
|
+
"args": ["-y", "@shuji-bonji/pdf-writer-mcp"],
|
|
67
|
+
"env": {
|
|
68
|
+
"PDF_WRITER_FONT": "/absolute/path/to/NotoSansJP-Regular.otf"
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
`PDF_WRITER_FONT` を設定しておくと、各ツールで `fontPath` を省略しても日本語が出せます。
|
|
76
|
+
|
|
77
|
+
## フォント
|
|
78
|
+
|
|
79
|
+
標準 PDF フォント(Helvetica)は **ASCII のみ** です。日本語など非ラテン文字を描画するには、`fontPath` または `PDF_WRITER_FONT` で埋め込み可能な**単一フェイス**のフォント(`.ttf` / `.otf`)を指定してください。
|
|
80
|
+
|
|
81
|
+
- 推奨入手先: [Noto Sans JP (SubsetOTF/JP)](https://github.com/notofonts/noto-cjk/tree/main/Sans/SubsetOTF/JP) — 静的・単一フェイス・SIL OFL。
|
|
82
|
+
- **`.ttc`(TrueTypeCollection)は非対応**です。検知してエラーにするため、単一フェイスを抽出してください:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
python3 -c "from fontTools.ttLib import TTCollection; \
|
|
86
|
+
TTCollection('NotoSansCJK-Regular.ttc').fonts[0].save('NotoSansCJKjp-Regular.otf')"
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### フォント未収録文字(グリフ欠落)
|
|
90
|
+
|
|
91
|
+
フォントに存在しない文字(例: Noto Sans JP に無い ✔ U+2714)は、そのままだと `.notdef` として埋め込まれ、無警告で空白になります。`onMissingGlyph` でこの挙動を選べます。
|
|
92
|
+
|
|
93
|
+
| 値 | 挙動 |
|
|
94
|
+
|----|------|
|
|
95
|
+
| `error`(既定) | 欠落文字を `"✔" (U+2714)` 形式で列挙してエラー |
|
|
96
|
+
| `replace` | 〓 に置換して生成し、`warnings` で報告 |
|
|
97
|
+
| `ignore` | 空白のまま生成し、`warnings` で報告 |
|
|
98
|
+
|
|
99
|
+
## 返り値
|
|
100
|
+
|
|
101
|
+
```jsonc
|
|
102
|
+
{
|
|
103
|
+
"path": "/abs/out.pdf", // outputPath 指定時
|
|
104
|
+
"base64": "JVBERi0xLj...", // returnBase64 指定時、または outputPath 省略時
|
|
105
|
+
"pageCount": 3,
|
|
106
|
+
"bytes": 91788,
|
|
107
|
+
"font": "NotoSansJP-Regular.otf",
|
|
108
|
+
"warnings": ["Replaced 1 unsupported character(s) with \"〓\": \"✔\" (U+2714)"]
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
編集ツールは `font` を除いた同じ形を返します。`split_pdf` は `{ files: [...], count }` を返します。
|
|
113
|
+
|
|
114
|
+
## テキスト抽出
|
|
115
|
+
|
|
116
|
+
生成される PDF はテキストの選択・コピー・全文検索・スクリーンリーダ読み上げが可能です。埋め込みサブセットフォントでも pdf-lib が ToUnicode CMap を出力するためで、この性質は回帰テスト(`extract.test.ts` / `render.test.ts`)で担保しています。
|
|
117
|
+
|
|
118
|
+
> poppler 系のビューアは、OTF/CFF フォントを CIDFontType0 として埋め込む際に `Mismatch between font type and embedded font file` という警告を表示することがあります。これは無害で、描画・抽出とも正常です。
|
|
119
|
+
|
|
120
|
+
## 開発
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
npm install
|
|
124
|
+
npm run build # dist/ に出力
|
|
125
|
+
npm test # vitest
|
|
126
|
+
npm run typecheck # tsc --noEmit
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
日本語フォント依存のテストは `TEST_FONT_PATH` を指定すると有効になります。
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
TEST_FONT_PATH=/path/to/NotoSansJP-Regular.otf npm test
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## 既知の制約
|
|
136
|
+
|
|
137
|
+
- **インライン装飾**: 太字・斜体はサイズ / 字面のみで、書体としては反映されません(1 文書につき単一フォントを埋め込むため)。
|
|
138
|
+
- **`.ttc` フォント**: 単一フェイスへの抽出が必要です(上記参照)。
|
|
139
|
+
- **サブセット名の接頭辞**: 慣習的な `ABCDEF+` を付けないため、一部ツールがサブセットでないと誤認します。描画・抽出には影響せず、PDF/A の厳密対応時のみ問題になります。
|
|
140
|
+
|
|
141
|
+
## ロードマップ
|
|
142
|
+
|
|
143
|
+
- [x] 編集系 Tier A 第1波 — メタデータ・ページ操作(v0.2.0)
|
|
144
|
+
- [x] 編集系 Tier A 第2波 — しおり・注釈(v0.4.0)
|
|
145
|
+
- [x] タグ付き PDF / PDF/UA-1 — veraPDF で準拠を確認(v0.5.0)
|
|
146
|
+
- [ ] 編集系 Tier B — フォーム記入 / フラット化、透かし、添付ファイル、ページ番号スタンプ
|
|
147
|
+
- [ ] 画像の代替テキスト(`Figure` + `/Alt`)、タグ付き出力での注釈の `Annot` タグ内包
|
|
148
|
+
- [ ] `.ttc` からのフェイス自動抽出
|
|
149
|
+
- [ ] 見出し用と本文用のフォント分け(太字フェイス埋め込み)
|
|
150
|
+
- [ ] 画像埋め込み、ヘッダー / フッター
|
|
151
|
+
- [ ] Tier C — 署名を保持する増分更新、本文テキスト編集、タグ木の保守
|
|
152
|
+
- [ ] PDF/A 変換
|
|
153
|
+
|
|
154
|
+
## ライセンス
|
|
155
|
+
|
|
156
|
+
MIT © shuji-bonji
|