@pdfme/cli 5.5.10-dev.136 → 6.0.0-dev.1

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.
Files changed (3) hide show
  1. package/README.md +4 -867
  2. package/dist/index.js +1 -1
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,870 +1,7 @@
1
- # @pdfme/cli
1
+ ## @pdfme/cli
2
2
 
3
- pdfme のコマンドラインツール。テンプレート作成・検証・PDF生成・画像変換を CLI で完結できる。
3
+ This package provides the `pdfme` command-line interface for JSON-first pdfme workflows, including PDF generation, validation, diagnostics, example export, and PDF conversion utilities.
4
4
 
5
- ## 背景と設計思想
5
+ Node.js 20 or later is required.
6
6
 
7
- ### なぜ CLI が必要か
8
-
9
- pdfme は PDF テンプレートを JSON で定義し、プログラマティックに PDF を生成するライブラリ。従来の開発フローは「Designer UI でテンプレート作成 → コードから `generate()` 呼び出し → ブラウザで結果確認」というサイクルだった。
10
-
11
- AI エージェント(Claude Code 等)を使った開発では、このフローに根本的な課題がある:
12
-
13
- - **エージェントはブラウザの Designer UI を操作できない**
14
- - **エージェントは PDF ファイルを直接読めない** — 画像に変換する必要がある
15
- - **テンプレート JSON の構造エラーを、PDF 生成を試みるまで検出できない**
16
-
17
- `@pdfme/cli` はこれらを解決し、**AI エージェントが自律的にテンプレート作成から結果検証まで完結できるフィードバックループ**を構築する。
18
-
19
- ```
20
- JSON 編集 → pdfme generate --image → PNG 読み取り → 視覚確認 → 微調整
21
- ```
22
-
23
- ### 設計原則
24
-
25
- - **AI エージェント特化**: `--json` フラグで構造化出力、`--help` に豊富な使用例、エラーメッセージに修正案を含める
26
- - **machine interface 優先**: `--json` 指定時は stdout を JSON のみに固定し、失敗時も構造化エラーを返す
27
- - **日本語ユーザー対応**: CJK 文字を検出すると NotoSansJP を自動ダウンロード&キャッシュし、解決不能時は structured error を返す
28
- - **既存 PDF からのテンプレート作成ワークフロー**: `pdf2img` → `pdf2size` → テンプレート作成 → `generate --image` の一連フローをサポート
29
- - **npx でもローカルでも同等の体験**
30
-
31
- ### pdfme v5 ロードマップにおける位置づけ
32
-
33
- pdfme v5 メジャーバージョンアップは 3 フェーズで構成される:
34
-
35
- | フェーズ | 内容 | 状態 |
36
- |---------|------|------|
37
- | Phase 1 | Vite / Vitest / Oxlint 移行、ESM-only 化 | **完了** |
38
- | Phase 2 | `@pdfme/cli` | **本パッケージ** |
39
- | Phase 3 | Claude Code Skills (`/pdfme-verify` 等) | 未着手 |
40
-
41
- Phase 1 で全パッケージのビルドを Vite library mode + Vitest に統一した。Phase 2 の CLI はその基盤の上に構築され、Phase 3 の Skills が CLI コマンドを活用する。
42
-
43
- ---
44
-
45
- ## インストール
46
-
47
- ```bash
48
- # プロジェクトに追加
49
- npm install -D @pdfme/cli
50
-
51
- # または npx で直接実行
52
- npx @pdfme/cli generate --help
53
- ```
54
-
55
- monorepo でローカルに試す場合は、build 後にエントリポイントを直接実行できる:
56
-
57
- ```bash
58
- npm run build -w packages/cli
59
- node packages/cli/dist/index.js --help
60
- ```
61
-
62
- **要件**: Node.js 20 以上
63
-
64
- ---
65
-
66
- ## コマンド一覧
67
-
68
- | コマンド | 用途 |
69
- |---------|------|
70
- | [`generate`](#pdfme-generate) | テンプレート + 入力データ → PDF + 画像 |
71
- | [`validate`](#pdfme-validate) | テンプレート JSON の構造検証 |
72
- | [`doctor`](#pdfme-doctor) | 実行環境 / job / template の事前診断 |
73
- | [`pdf2img`](#pdfme-pdf2img) | 既存 PDF → 画像変換 (グリッド付き) |
74
- | [`pdf2size`](#pdfme-pdf2size) | PDF のページサイズ取得 |
75
- | [`examples`](#pdfme-examples) | 組み込みテンプレート資産の参照・出力 |
76
-
77
- ---
78
-
79
- ## pdfme generate
80
-
81
- テンプレートと入力データから PDF を生成し、オプションで画像やグリッドオーバーレイも出力する。
82
-
83
- ### 使い方
84
-
85
- ```bash
86
- # 分離形式: テンプレートと入力を別ファイルで指定
87
- pdfme generate -t template.json -i inputs.json -o out.pdf
88
-
89
- # 統合形式: { template, inputs, options? } を含む 1 ファイル
90
- pdfme generate job.json -o out.pdf --image
91
-
92
- # 既存 PDF をベースに、フィールドを重ねて生成
93
- pdfme generate -t template.json --basePdf invoice.pdf -i inputs.json --image --grid
94
-
95
- # JSON 出力 (AI/スクリプト向け)
96
- pdfme generate job.json -o out.pdf --image --json
97
- ```
98
-
99
- ### オプション
100
-
101
- | フラグ | 型 | デフォルト | 説明 |
102
- |--------|------|-----------|------|
103
- | `[file]` | positional | - | 統合ファイル (`{ template, inputs, options? }`) |
104
- | `-t, --template` | string | - | テンプレート JSON ファイル |
105
- | `-i, --inputs` | string | - | 入力データ JSON ファイル |
106
- | `-o, --output` | string | `output.pdf` | 出力 PDF パス |
107
- | `--force` | boolean | false | 暗黙の `output.pdf` 上書きを許可 |
108
- | `--image` | boolean | false | 各ページの PNG 画像も出力 |
109
- | `--imageFormat` | string | `png` | 画像フォーマット (`png` / `jpeg`) |
110
- | `--scale` | string | `1` | 画像レンダリングスケール |
111
- | `--grid` | boolean | false | グリッド+スキーマ境界を画像にオーバーレイ |
112
- | `--gridSize` | string | `10` | グリッド間隔 (mm) |
113
- | `--font` | string | - | カスタムフォント (カンマ区切りで複数可: `"A=a.ttf,B=b.ttf"`) |
114
- | `--basePdf` | string | - | basePdf をファイルパスで上書き |
115
- | `--noAutoFont` | boolean | false | CJK フォント自動ダウンロードを無効化 |
116
- | `-v, --verbose` | boolean | false | 詳細出力 |
117
- | `--json` | boolean | false | 構造化 JSON 出力 |
118
-
119
- `-v, --verbose` を付けると、入力 source、mode、template pages、input 数、output PDF、image 条件、font 前提、`--basePdf` override を stderr に出す。`--json` と併用しても stdout は JSON のまま維持される。
120
-
121
- ### `--json` 契約
122
-
123
- `--json` を指定すると、成功時も失敗時も stdout には JSON のみを出力する。人間向けの補足や warning は stderr に寄せる。
124
-
125
- 成功例:
126
-
127
- ```json
128
- {
129
- "ok": true,
130
- "command": "generate",
131
- "mode": "job",
132
- "templatePageCount": 1,
133
- "inputCount": 1,
134
- "pageCount": 1,
135
- "outputPath": "out.pdf",
136
- "outputBytes": 12345
137
- }
138
- ```
139
-
140
- 失敗例:
141
-
142
- ```json
143
- {
144
- "ok": false,
145
- "error": {
146
- "code": "EARG",
147
- "message": "Invalid value for --scale: expected a positive number, received \"nope\"."
148
- }
149
- }
150
- ```
151
-
152
- ### 統合ファイル形式 (job.json)
153
-
154
- ```json
155
- {
156
- "template": {
157
- "basePdf": { "width": 210, "height": 297, "padding": [20, 20, 20, 20] },
158
- "schemas": [
159
- [
160
- {
161
- "name": "title",
162
- "type": "text",
163
- "position": { "x": 20, "y": 20 },
164
- "width": 170,
165
- "height": 15,
166
- "fontSize": 24,
167
- "alignment": "center",
168
- "content": "Invoice",
169
- "readOnly": true
170
- },
171
- {
172
- "name": "customerName",
173
- "type": "text",
174
- "position": { "x": 20, "y": 50 },
175
- "width": 80,
176
- "height": 10
177
- }
178
- ]
179
- ]
180
- },
181
- "inputs": [
182
- { "customerName": "John Doe" }
183
- ],
184
- "options": {
185
- "font": {
186
- "NotoSansJP": {
187
- "data": "https://fonts.gstatic.com/...",
188
- "fallback": false,
189
- "subset": true
190
- }
191
- }
192
- }
193
- }
194
- ```
195
-
196
- テンプレート JSON 内の `basePdf` にはファイルパスも指定可能:
197
-
198
- ```json
199
- {
200
- "basePdf": "./invoice.pdf",
201
- "schemas": [...]
202
- }
203
- ```
204
-
205
- ### スキーマ型一覧
206
-
207
- `text`, `multiVariableText`, `image`, `signature`, `svg`, `table`, `qrcode`, `ean13`, `ean8`, `code39`, `code128`, `nw7`, `itf14`, `upca`, `upce`, `japanpost`, `gs1datamatrix`, `pdf417`, `line`, `rectangle`, `ellipse`, `date`, `dateTime`, `time`, `select`, `radioGroup`, `checkbox`
208
-
209
- ### --grid の出力
210
-
211
- `--grid` を指定すると、画像に以下がオーバーレイされる:
212
-
213
- - **グリッド線**: `--gridSize` mm 間隔のグレー線
214
- - **スキーマ境界**: 色付き破線矩形 (型ごとに色分け)
215
- - **ラベル**: 各フィールドの `名前 (型)` を矩形左上に表示
216
-
217
- ### CJK フォント自動ダウンロード
218
-
219
- `--font` 未指定時、テンプレートや入力データに CJK 文字 (日本語、中国語、韓国語) が含まれていると、NotoSansJP を自動的にダウンロードしてキャッシュする:
220
-
221
- - キャッシュ場所: `~/.pdfme/fonts/NotoSansJP-Regular.ttf`
222
- - オフラインで自動取得できず、明示的なフォント指定もない場合は structured error (`EFONT`) を返す
223
- - `--noAutoFont` で無効化
224
- - `--noAutoFont` 使用時に CJK が含まれ、明示的なフォント指定がなければ structured error (`EFONT`) を返す
225
-
226
- ### Font Source Contract
227
-
228
- `@pdfme/cli` は「拡張子そのもの」ではなく、**どこからフォントを解決するか**を基準に contract を持つ。
229
-
230
- - `--font name=path.ttf`
231
- - local file 専用
232
- - path は CLI 実行時の `cwd` 基準で解決
233
- - 現時点で強保証するのは `.ttf` のみ
234
- - 同名エントリが `options.font` にあっても `--font` を優先する
235
- - `options.font.<name>.data`
236
- - local `.ttf` path
237
- - unified job / template JSON のあるディレクトリ基準で解決
238
- - public host を向く `https://...` / `http://...` の direct `.ttf` asset URL
239
- - `fonts.gstatic.com/...ttf` のような Google Fonts asset URL は official remote source として扱う
240
- - `.ttf` を表す `data:` URI
241
- - `Uint8Array` / `ArrayBuffer`
242
- - これは programmatic 入力では有効だが、純粋な JSON job では通常使わない
243
- - implicit source
244
- - 常に default `Roboto`
245
- - CJK があり明示 font がなければ auto `NotoSansJP` (cache or download)
246
-
247
- unsupported として fail-fast に寄せるもの:
248
-
249
- - missing local font path
250
- - `.otf` / `.ttc` など `.ttf` 以外を明示する source
251
- - loopback / private host を含む unsafe `http(s)` URL
252
- - `file:` / `ftp:` など非 `http(s)` URL
253
- - `fonts.googleapis.com/css*` のような Google Fonts stylesheet API URL
254
-
255
- 現時点で未サポートのもの:
256
-
257
- - Google Fonts の family / weight / style を declarative に解決する専用 surface
258
- - CSS 経由で font binary を辿る remote font workflow
259
-
260
- warning に留めるもの:
261
-
262
- - public host の `http(s)` URL だが path に拡張子がなく raw `.ttf` asset と明示できない source
263
- - `data:` URI だが media type から `.ttf` と明示できない source
264
-
265
- `doctor fonts` はこの source contract をそのまま machine-readable に返し、`generate` は local path を事前解決して structured error に寄せる。
266
-
267
- ### Remote Font Runtime Contract
268
-
269
- explicit remote font (`options.font.<name>.data = https://...`) は CLI 側で先に解決してから generator に渡す。
270
-
271
- - `generate --json` では network failure / HTTP failure / timeout / size safety limit 超過を `EFONT` で返す
272
- - error details には少なくとも `fontName`, `url`, `provider`, `timeoutMs`, `maxBytes` が入る
273
- - current CLI が cache する remote font は implicit `NotoSansJP` のみ
274
- - explicit remote font 用の cache / offline fallback workflow は current product surface に含めない
275
- - remote fetch timeout は 15 秒
276
- - remote fetch size limit は 32 MiB
277
-
278
- 失敗例:
279
-
280
- ```json
281
- {
282
- "ok": false,
283
- "error": {
284
- "code": "EFONT",
285
- "message": "Failed to fetch remote font data from https://fonts.example.com/network-error.ttf. fetch failed",
286
- "details": {
287
- "fontName": "PinyonScript",
288
- "url": "https://fonts.example.com/network-error.ttf",
289
- "provider": "genericPublic",
290
- "timeoutMs": 15000,
291
- "maxBytes": 33554432
292
- }
293
- }
294
- }
295
- ```
296
-
297
- ### 終了コード
298
-
299
- | コード | 意味 |
300
- |--------|------|
301
- | 0 | 成功 |
302
- | 1 | テンプレート/入力バリデーションエラー |
303
- | 2 | runtime / font 解決エラー |
304
- | 3 | ファイル I/O エラー |
305
-
306
- ---
307
-
308
- ## pdfme validate
309
-
310
- テンプレート JSON の構造を検証する。`generate` の前に実行することで、エラーを早期発見できる。
311
-
312
- ### 使い方
313
-
314
- ```bash
315
- pdfme validate template.json
316
-
317
- # 統合 job をそのまま検証
318
- pdfme validate job.json
319
-
320
- # stdin から検証
321
- cat template.json | pdfme validate - --json
322
-
323
- # JSON 出力
324
- pdfme validate template.json --json
325
-
326
- # Warning もエラー扱いにする
327
- pdfme validate template.json --strict
328
-
329
- # 詳細出力を stderr に出す
330
- pdfme validate template.json -v --json
331
- ```
332
-
333
- ### 検証項目
334
-
335
- | カテゴリ | チェック内容 | レベル |
336
- |----------|------------|--------|
337
- | 構造 | Zod スキーマバリデーション | ERROR |
338
- | 型 | フィールドの type が存在するスキーマ型か | ERROR |
339
- | 重複 | 同一ページ内のフィールド名重複 | ERROR |
340
- | 重複 | 異なるページ間の同名フィールド | WARNING |
341
- | 位置 | フィールドがページ境界外にはみ出し | WARNING |
342
- | basePdf | BlankPdf の場合、width/height/padding が妥当か | ERROR |
343
- | unified job | `template` / `inputs` / `options` の形が `generate` に渡せるか | ERROR |
344
- | top-level | 未知の top-level field | WARNING |
345
-
346
- `validate` は template 単体だけでなく unified job (`{ template, inputs, options? }`) も受理する。`--strict` を付けると warning も exit code 1 に昇格する。
347
- `-v, --verbose` を付けると、入力 source、mode、pages / fields、job 時の input 数、strict 条件、error / warning 件数を stderr に出す。`--json` と併用しても stdout は JSON のまま維持される。
348
-
349
- `--json` では `inputHints` も返す。これにより field ごとの期待入力形式を事前に把握できる。たとえば `text` は plain string、`image` / `signature` / `svg` は `contentKind` 付き string、barcode 系は human-readable `rule` を持つ string、`table` は `string[][]` の nested JSON array、`date` / `time` / `dateTime` は `format` と `canonicalFormat` を持つ string、`select` / `checkbox` は constrained string enum、`radioGroup` は group-aware enum、`multiVariableText` は JSON string object を期待する。
350
-
351
- ```json
352
- [
353
- {
354
- "name": "title",
355
- "type": "text",
356
- "pages": [1],
357
- "required": false,
358
- "expectedInput": { "kind": "string" }
359
- },
360
- {
361
- "name": "invoiceMeta",
362
- "type": "multiVariableText",
363
- "pages": [1],
364
- "required": true,
365
- "expectedInput": {
366
- "kind": "jsonStringObject",
367
- "variableNames": ["inv"],
368
- "example": "{\"inv\":\"INV\"}"
369
- }
370
- },
371
- {
372
- "name": "status",
373
- "type": "select",
374
- "pages": [1],
375
- "required": false,
376
- "expectedInput": {
377
- "kind": "enumString",
378
- "allowedValues": ["draft", "sent"],
379
- "example": "draft"
380
- }
381
- },
382
- {
383
- "name": "approved",
384
- "type": "checkbox",
385
- "pages": [1],
386
- "required": false,
387
- "expectedInput": {
388
- "kind": "enumString",
389
- "allowedValues": ["false", "true"],
390
- "example": "true"
391
- }
392
- },
393
- {
394
- "name": "lineItems",
395
- "type": "table",
396
- "pages": [1],
397
- "required": false,
398
- "expectedInput": {
399
- "kind": "stringMatrix",
400
- "columnCount": 3,
401
- "columnHeaders": ["Item", "Qty", "Price"],
402
- "example": [["Item value", "Qty value", "Price value"]],
403
- "acceptsJsonString": true
404
- }
405
- },
406
- {
407
- "name": "logo",
408
- "type": "image",
409
- "pages": [1],
410
- "required": false,
411
- "expectedInput": {
412
- "kind": "string",
413
- "contentKind": "imageDataUrl"
414
- }
415
- },
416
- {
417
- "name": "orderCode",
418
- "type": "qrcode",
419
- "pages": [1],
420
- "required": false,
421
- "expectedInput": {
422
- "kind": "string",
423
- "contentKind": "barcodeText",
424
- "rule": "Any non-empty string up to 499 characters."
425
- }
426
- },
427
- {
428
- "name": "dueDate",
429
- "type": "date",
430
- "pages": [1],
431
- "required": false,
432
- "expectedInput": {
433
- "kind": "string",
434
- "format": "dd/MM/yyyy",
435
- "canonicalFormat": "yyyy/MM/dd",
436
- "example": "2026/03/28"
437
- }
438
- },
439
- {
440
- "name": "choiceA",
441
- "type": "radioGroup",
442
- "pages": [1],
443
- "required": false,
444
- "expectedInput": {
445
- "kind": "enumString",
446
- "allowedValues": ["false", "true"],
447
- "example": "true",
448
- "groupName": "choices",
449
- "groupMemberNames": ["choiceA", "choiceB"]
450
- }
451
- }
452
- ]
453
- ```
454
-
455
- 型名が不正な場合、Levenshtein 距離に基づく修正候補を提示する:
456
-
457
- ```
458
- ✗ Error: Field "title" has unknown type "textbox". Did you mean: text? Available types: text, image, ...
459
- ```
460
-
461
- ---
462
-
463
- ## pdfme doctor
464
-
465
- `generate` 実行前に、CLI 実行環境や local job/template の準備状態を診断する。`validate` が JSON 構造中心なのに対し、`doctor` は basePdf path、font 前提、cache 状態も含めて見る。
466
-
467
- ### 使い方
468
-
469
- ```bash
470
- # 実行環境の自己診断
471
- pdfme doctor
472
-
473
- # local job / template の診断
474
- pdfme doctor job.json --json
475
-
476
- # stdin から診断
477
- cat job.json | pdfme doctor - --json
478
-
479
- # font source 前提だけを診断
480
- pdfme doctor fonts job.json --json
481
-
482
- # generate --noAutoFont 相当の条件で診断
483
- pdfme doctor job.json --noAutoFont --json
484
-
485
- # generate の出力先 / 画像出力先まで事前診断
486
- pdfme doctor job.json -o artifacts/out.pdf --image --imageFormat jpeg --json
487
-
488
- # 詳細出力を stderr に出す
489
- pdfme doctor job.json -v --json
490
- ```
491
-
492
- ### 何を返すか
493
-
494
- - `pdfme doctor`
495
- - Node version / CLI version / platform / arch
496
- - `cwd` と temp dir の writable 状態
497
- - NotoSansJP cache file の存在と cache dir の writable 状態
498
- - `pdfme doctor <job-or-template>`
499
- - `validate` 相当の pages / fields / errors / warnings
500
- - basePdf の種別と local path 解決結果
501
- - schema types / required official plugins / required fonts
502
- - CJK 検出時に auto-font が必要か、cache があるか、`--noAutoFont` だと blocking になるか
503
- - `generate` 相当の output path safety (`output.pdf` の implicit overwrite guard, writable dir, image output preview)
504
- - `pdfme doctor fonts <job-or-template>`
505
- - `options.font` の source 種別 (`localPath` / `url` / `dataUri` / `inlineBytes` / `invalid`)
506
- - local font path の解決結果と存在確認
507
- - remote source ごとの `provider`, `needsNetwork`, `supportedFormat`
508
- - `.ttf` 以外の unsupported 検出
509
- - implicit default font / auto NotoSansJP を含む effective font 前提
510
-
511
- runtime/path の事前診断には `generate` と同じく `-o, --output`, `--force`, `--image`, `--imageFormat` を使える。`doctor fonts` ではこれらの flag は font diagnosis の health/payload には反映しないが、argument validation 自体は通常どおり行う。
512
- `-v, --verbose` を付けると、target、入力 source、mode、pages / fields、job 時の input 数、estimated pages、output PDF、image 条件、issue / warning 件数を stderr に出す。`--json` と併用しても stdout は JSON のまま維持される。
513
-
514
- ### `--json` 契約
515
-
516
- `doctor` も `validate` と同様に、コマンド自体が実行できた場合は `ok: true` を返し、blocking issue の有無は `healthy` で表す。`target` は `environment` / `input` / `fonts` のいずれかになる。
517
-
518
- font payload の `explicitSources` / `implicitSources` には `needsNetwork` が含まれるため、agent は「その source が今の環境で network 前提か」を事前判定できる。
519
- 同様に `inputHints` には field ごとの期待入力形式が含まれるため、`text` / `image` / `signature` / `svg` / barcode / `table` / `date` / `time` / `dateTime` / `select` / `checkbox` / `radioGroup` / `multiVariableText` の違いを generate 前に判定できる。
520
-
521
- 環境診断の例:
522
-
523
- ```json
524
- {
525
- "ok": true,
526
- "target": "environment",
527
- "healthy": true,
528
- "environment": {
529
- "nodeVersion": "v20.19.3",
530
- "cliVersion": "0.1.0-alpha.0"
531
- },
532
- "issues": [],
533
- "warnings": []
534
- }
535
- ```
536
-
537
- input 診断の例:
538
-
539
- ```json
540
- {
541
- "ok": true,
542
- "command": "doctor",
543
- "target": "input",
544
- "healthy": false,
545
- "mode": "template",
546
- "templatePageCount": 1,
547
- "fieldCount": 1,
548
- "estimatedPageCount": 1,
549
- "validation": {
550
- "valid": true,
551
- "errors": [],
552
- "warnings": []
553
- },
554
- "diagnosis": {
555
- "basePdf": { "kind": "pdfPath", "exists": false },
556
- "fonts": { "missingFonts": ["NotoSerifJP"] },
557
- "runtime": {
558
- "estimatedPages": 1,
559
- "output": {
560
- "path": "output.pdf",
561
- "resolvedPath": "/abs/path/output.pdf",
562
- "implicitDefaultProtected": true
563
- }
564
- }
565
- },
566
- "issues": [
567
- "Base PDF file not found: /abs/path/missing.pdf",
568
- "Refusing to overwrite implicit default output file: /abs/path/output.pdf. Use -o to choose an explicit path or --force to overwrite."
569
- ],
570
- "warnings": []
571
- }
572
- ```
573
-
574
- `image` / `signature` / `svg` では `kind = "string"` のまま、`contentKind` で `imageDataUrl` / `signatureImageDataUrl` / `svgMarkup` を返す。barcode 系では `contentKind = "barcodeText"` と human-readable な `rule` を返す。`table` では `inputHints.expectedInput.kind = "stringMatrix"` と `columnCount` / `columnHeaders` が返る。canonical input は `string[][]` の nested JSON array で、`acceptsJsonString: true` のときは後方互換として JSON string も受理する。`date` / `time` / `dateTime` では `format` と `canonicalFormat` が返る。`example` は current CLI が期待する canonical stored content 例で、`format` は schema 側の format ベースの hint を示す。date 系の actual input validation も canonical stored content 基準で行う。`select` / `checkbox` では `inputHints.expectedInput.kind = "enumString"` と `allowedValues` が返る。`radioGroup` ではそれに加えて `groupName` / `groupMemberNames` が返り、同じ group 内で複数 field を `"true"` にすると `generate --json` / `validate --json` / `doctor --json` は `EVALIDATE` 相当で fail-fast する。`multiVariableText` では expected variable names と JSON string 例が返る。
575
-
576
- ### `multiVariableText` Input Contract
577
-
578
- `multiVariableText` は plain string ではなく、変数名をキーに持つ **JSON string object** を期待する。
579
-
580
- template:
581
-
582
- ```json
583
- {
584
- "name": "invoiceMeta",
585
- "type": "multiVariableText",
586
- "text": "Invoice {inv}",
587
- "variables": ["inv"]
588
- }
589
- ```
590
-
591
- input:
592
-
593
- ```json
594
- [
595
- {
596
- "invoiceMeta": "{\"inv\":\"INV-001\"}"
597
- }
598
- ]
599
- ```
600
-
601
- plain string を渡すと、`generate --json` は `EVALIDATE` で fail-fast し、expected variable names と example を返す。
602
-
603
- font 診断の例:
604
-
605
- ```json
606
- {
607
- "ok": true,
608
- "target": "fonts",
609
- "healthy": false,
610
- "mode": "job",
611
- "diagnosis": {
612
- "fonts": {
613
- "requiredFonts": ["BrandOtf", "BrandTtf"],
614
- "explicitSources": [
615
- { "fontName": "BrandTtf", "kind": "localPath", "supportedFormat": true },
616
- { "fontName": "BrandOtf", "kind": "localPath", "supportedFormat": false }
617
- ]
618
- }
619
- },
620
- "issues": [
621
- "Font file for BrandOtf uses .otf. @pdfme/cli currently guarantees only .ttf custom fonts for BrandOtf."
622
- ],
623
- "warnings": []
624
- }
625
- ```
626
-
627
- blocking issue があれば exit code 1、argument / parse / file I/O 自体に失敗した場合は他 command と同様に structured error (`ok: false`) を返す。
628
-
629
- ---
630
-
631
- ## pdfme pdf2img
632
-
633
- 既存 PDF を画像に変換する。テンプレート作成時にレイアウトを確認したり、basePdf の内容を可視化するのに使う。
634
-
635
- ### 使い方
636
-
637
- ```bash
638
- # 基本
639
- pdfme pdf2img invoice.pdf
640
-
641
- # グリッド付き (mm 座標ラベルも表示)
642
- pdfme pdf2img invoice.pdf --grid --gridSize 10
643
-
644
- # 特定ページのみ
645
- pdfme pdf2img invoice.pdf --pages 1-2
646
-
647
- # 詳細出力を stderr に出す
648
- pdfme pdf2img invoice.pdf -o ./images/ --verbose
649
-
650
- # 出力先指定 + JSON (サイズ情報付き)
651
- pdfme pdf2img invoice.pdf -o ./images/ --json
652
- ```
653
-
654
- `-o, --output` は **ディレクトリ専用**。`page-%d.png` や単一ファイル名はサポートしない。
655
- `-v, --verbose` を付けると、入力、ページ数、対象ページ、出力先、format、scale、grid 条件を stderr に出す。`--json` と併用しても stdout は JSON のまま維持される。
656
-
657
- ### `--json` 出力
658
-
659
- ```json
660
- {
661
- "ok": true,
662
- "command": "pdf2img",
663
- "pageCount": 1,
664
- "selectedPageCount": 1,
665
- "outputDir": "./images",
666
- "outputPaths": ["invoice-1.png"],
667
- "pages": [
668
- { "outputPath": "invoice-1.png", "pageNumber": 1, "width": 210, "height": 297 }
669
- ]
670
- }
671
- ```
672
-
673
- ---
674
-
675
- ## pdfme pdf2size
676
-
677
- PDF のページサイズ (mm) を取得する。A4, Letter 等の標準サイズ名も自動判定。
678
-
679
- ```bash
680
- $ pdfme pdf2size invoice.pdf
681
- Page 1: 210 × 297 mm (A4 portrait)
682
-
683
- $ pdfme pdf2size invoice.pdf --json
684
- {
685
- "ok": true,
686
- "command": "pdf2size",
687
- "pageCount": 1,
688
- "pages": [{ "pageNumber": 1, "width": 210, "height": 297 }]
689
- }
690
- ```
691
-
692
- `-v, --verbose` を付けると、入力とページ数を stderr に出す。`--json` と併用しても stdout は JSON のまま維持される。
693
-
694
- ---
695
-
696
- ## pdfme examples
697
-
698
- `https://playground.pdfme.com/template-assets/` で配信しているテンプレート資産を参照・出力する。AI エージェントがテンプレートを新規作成する際の構造参考として使える。
699
-
700
- ### 使い方
701
-
702
- ```bash
703
- # テンプレート一覧
704
- pdfme examples --list
705
-
706
- # テンプレートを stdout に出力
707
- pdfme examples invoice
708
-
709
- # ファイルに出力
710
- pdfme examples invoice -o template.json
711
-
712
- # テンプレート + サンプル入力を統合形式で出力
713
- pdfme examples invoice --withInputs -o job.json
714
-
715
- # 構造化 JSON で metadata も取得
716
- pdfme examples --list --json
717
-
718
- # source と output 条件を stderr に出す
719
- pdfme examples invoice --withInputs -o job.json -v --json
720
-
721
- # そのまま generate に渡せる
722
- pdfme examples invoice --withInputs -o job.json && pdfme generate job.json --image
723
- ```
724
-
725
- `--withInputs` で出力する job には、必要に応じて `options.font` が含まれる。official examples が使用するフォント URL を同梱するため、template 側の `fontName` と `generate` の入力契約がずれにくい。
726
-
727
- ### 組み込みテンプレート
728
-
729
- 利用可能なテンプレートは `pdfme examples --list` で取得。
730
-
731
- `--json` を付けると manifest metadata も返す。manifest には `path`, `thumbnailPath`, `pageCount`, `fieldCount`, `schemaTypes`, `fontNames`, `hasCJK`, `basePdfKind` などが含まれ、AI/agent が examples を探索しやすい形になっている。
732
- `-v, --verbose` を付けると、base URL、manifest source / URL、template source / URL、mode、output 先を stderr に出す。`--json` と併用しても stdout は JSON のまま維持される。
733
-
734
- ---
735
-
736
- ## 典型的ワークフロー
737
-
738
- ### 1. ゼロからテンプレートを作る (AI エージェント向け)
739
-
740
- ```bash
741
- # 1. 既存テンプレートを参考に構造を把握
742
- pdfme examples invoice --withInputs -o job.json
743
-
744
- # 2. job.json を編集してテンプレートを作成
745
-
746
- # 3. generate 前に doctor で前提を確認
747
- pdfme doctor job.json --json
748
-
749
- # 4. 生成して結果を画像で確認
750
- pdfme generate job.json -o out.pdf --image
751
-
752
- # 5. 画像を確認 → JSON を微調整 → 3 に戻る
753
- ```
754
-
755
- ### 2. 既存 PDF にフィールドを追加する
756
-
757
- ```bash
758
- # 1. 既存 PDF のレイアウトを画像で確認
759
- pdfme pdf2img invoice.pdf --grid --gridSize 10
760
-
761
- # 2. ページサイズを確認
762
- pdfme pdf2size invoice.pdf --json
763
-
764
- # 3. テンプレート JSON を作成 (basePdf にファイルパスを指定)
765
- cat > template.json << 'EOF'
766
- {
767
- "basePdf": "./invoice.pdf",
768
- "schemas": [[
769
- {
770
- "name": "amount",
771
- "type": "text",
772
- "position": { "x": 120, "y": 200 },
773
- "width": 60, "height": 10,
774
- "fontSize": 14, "alignment": "right"
775
- }
776
- ]]
777
- }
778
- EOF
779
-
780
- # 4. 入力データを作成
781
- echo '[{ "amount": "¥1,234,567" }]' > inputs.json
782
-
783
- # 5. 生成前に path / font / basePdf を診断
784
- pdfme doctor template.json -o out.pdf --image --json
785
-
786
- # 6. 生成して結果をグリッド付き画像で確認
787
- pdfme generate -t template.json -i inputs.json -o out.pdf --image --grid
788
-
789
- # 7. 画像を確認 → テンプレートを微調整 → 5 に戻る
790
- ```
791
-
792
- ### 3. CI/CD でのテンプレート検証
793
-
794
- ```bash
795
- # テンプレートの構造エラーをチェック (Warning もエラー扱い)
796
- pdfme validate template.json --strict --json
797
- ```
798
-
799
- ---
800
-
801
- ## アーキテクチャ
802
-
803
- ### ディレクトリ構成
804
-
805
- ```
806
- packages/cli/
807
- ├── src/
808
- │ ├── index.ts # エントリポイント + コマンドルーター
809
- │ ├── commands/
810
- │ │ ├── generate.ts # PDF 生成 + 画像出力
811
- │ │ ├── validate.ts # テンプレート検証
812
- │ │ ├── doctor.ts # 環境 / font / runtime 診断
813
- │ │ ├── pdf2img.ts # PDF → 画像変換
814
- │ │ ├── pdf2size.ts # ページサイズ取得
815
- │ │ └── examples.ts # テンプレート資産参照
816
- │ ├── contract.ts # 共通 error / JSON / 引数契約
817
- │ ├── diagnostics.ts # validate / doctor 用 inspection
818
- │ ├── schema-plugins.ts # 公式 plugin の自動収集
819
- │ ├── grid.ts # グリッド / スキーマ境界オーバーレイ描画
820
- │ ├── fonts.ts # フォント読込 + CJK 自動 DL + キャッシュ
821
- │ ├── example-templates.ts # current official manifest / template 取得
822
- │ ├── example-fonts.ts # official examples 用 font URL 埋め込み
823
- │ ├── cjk-detect.ts # CJK 文字検出
824
- │ ├── version.ts # ビルド時注入の CLI version
825
- │ └── utils.ts # ファイル I/O, 入力形式判定, 用紙サイズ検出
826
- ├── __tests__/
827
- ├── package.json
828
- ├── vite.config.mts # target: node20, ESM, shebang 付きビルド
829
- ├── tsconfig.json # typecheck 用 (composite)
830
- └── tsconfig.build.json # declaration emit 用
831
- ```
832
-
833
- ### 依存関係
834
-
835
- ```
836
- @pdfme/cli
837
- ├── @pdfme/common # 型定義, フォント, バリデーション
838
- ├── @pdfme/schemas # ビルトインスキーマプラグイン (text, image, table, ...)
839
- ├── @pdfme/generator # PDF 生成エンジン
840
- ├── @pdfme/converter # PDF ↔ 画像変換 (内部で @napi-rs/canvas 使用)
841
- └── citty # CLI パーサー (UnJS 製, ゼロ依存, サブコマンド対応)
842
- ```
843
-
844
- ### ビルド
845
-
846
- ```bash
847
- npm run build -w packages/cli
848
- # = vite build (→ dist/index.js, ESM, shebang 付き)
849
- # + tsc -p tsconfig.build.json (→ dist/*.d.ts)
850
- ```
851
-
852
- Vite で `target: node20`, 全依存を external にして単一 `dist/index.js` を出力。`@napi-rs/canvas` 等のネイティブモジュールはバンドルに含めない。
853
-
854
- ---
855
-
856
- ## 既知の制限事項
857
-
858
- - **フォント複数指定**: citty が repeated string args を未サポートのため、カンマ区切り形式 (`--font "A=a.ttf,B=b.ttf"`) を使用
859
- - **カスタムフォント source contract**: 現時点の強保証は local path / `http(s)` URL / `data:` URI の `.ttf`。`.otf` / `.ttc` は unsupported error を返す
860
- - **explicit remote font cache**: current CLI は explicit remote font を保存しない。offline 前提にしたい場合は local `.ttf` か `data:` URI を使う
861
- - **Google Fonts stylesheet API**: `fonts.googleapis.com/css*` は supported source ではない。direct font asset URL を使う
862
- - **examples コマンド**: current の official manifest / template を network 越しに取得する convenience command。取得先は `PDFME_EXAMPLES_BASE_URL` 環境変数で上書き可能
863
- - **NotoSansJP の DL URL**: Google Fonts CDN の可変ウェイトフォント (~16MB) を使用。固定ウェイト版への切り替えでサイズ削減可能
864
-
865
- ## 次の検討トラック
866
-
867
- - command 間 UX parity の見直し: `--verbose` second pass は `generate` / `validate` / `doctor` / `examples` まで拡張済み。次は verbose 以外の flag / payload / human-readable surface を見直す
868
- - input discoverability の改善: `multiVariableText` の期待入力形式を `doctor` / `validate --json` から見つけやすくする
869
- - docs / examples polish: `basePdf` overlay workflow と agent 向け onboarding の discoverability を上げる
870
- - Separate track: Rich Text / Markdown Authoring。CLI hardening とは別に spec から進め、Markdown/Rich Text で本文 PDF を作ってから pdfme template overlay を後段で重ねる workflow を主ユースケースに置く
7
+ For the complete pdfme documentation, see [this link](https://pdfme.com/docs/cli).
package/dist/index.js CHANGED
@@ -2246,7 +2246,7 @@ var pdf2size_default = defineCommand({
2246
2246
  });
2247
2247
  //#endregion
2248
2248
  //#region src/version.ts
2249
- var CLI_VERSION = "5.5.10-dev.136";
2249
+ var CLI_VERSION = "6.0.0-dev.1";
2250
2250
  //#endregion
2251
2251
  //#region src/example-templates.ts
2252
2252
  function getExamplesBaseUrl() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pdfme/cli",
3
- "version": "5.5.10-dev.136",
3
+ "version": "6.0.0-dev.1",
4
4
  "description": "CLI tool for pdfme - generate PDFs, convert images, validate templates",
5
5
  "keywords": [
6
6
  "pdf",