
2025/12/19 3:59
Show HN: TinyPDF – 3kb pdf library (70x smaller than jsPDF)
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
tinypdfは、実際のPDFを生成する最小限で依存関係のないPDF作成ライブラリ(約400行)です。わずか3.3 KBで、jsPDF(229 KB)よりも約70倍小さくなっています。これはTTFフォント、PNG/SVGサポート、HTML→PDF変換、フォーム、暗号化、および圧縮などの機能を省いたためです。
コア機能には、テキスト描画(Helvetica、任意のサイズ、16進数カラー、配置)、図形描画(矩形、線)、JPEG画像埋め込み、カスタムサイズでのマルチページレイアウト、およびヘッダー、リスト、ルール用のMarkdown変換が含まれます。
サポートされていない機能—カスタムフォント、PNG/GIF/SVG、ベクターグラフィックス、フォーム、暗号化、圧縮—は、jsPDFやpdf-libなどのより豊富なライブラリで利用可能です。
クイックスタート:
import { pdf } from 'tinypdf'; const doc = pdf(); doc.page(...); ctx.text(...); ctx.rect(...); ctx.line(...); ctx.image(...); doc.build(); // Uint8Arrayを返します
ヘルパー関数には、ポイント単位の幅を取得する
measureText(str, size)とmarkdown(str, { width, height, margin })があります。これらのプリミティブを使って約50行のコードで請求書例を生成できます。
MITライセンス下で提供されます。
本文
tinypdf – 最小構成の PDF 作成ライブラリ
<400 LOC、依存関係ゼロで実際に PDF を生成します。
なぜ tinypdf なのか?
| tinypdf | jsPDF | |
|---|---|---|
| サイズ | 3.3 KB | 229 KB |
| 依存関係 | 0 | 2 |
約70倍小さくなります。TTF フォント、PNG/SVG、HTML→PDF、フォーム、暗号化・圧縮を除外しました。残るのは「95%のユースケース」:テキストと画像をページに配置することです。
使い道
- 請求書
- 領収書
- レポート
- 発送ラベル
- チケット
- 証明書
- 契約書
- データエクスポート
主な機能
| 機能 | 説明 |
|---|---|
| テキスト | Helvetica、任意のサイズ、16進カラーコード、左/中央/右揃え |
| 図形 | 四角形と線 |
| 画像 | JPEG(写真・ロゴ・署名) |
| ページ | 複数ページ、カスタムサイズ |
| Markdown | ヘッダー・リスト・区切り線付きで Markdown を PDF に変換 |
除外項目:カスタムフォント、PNG/GIF/SVG、ベクターグラフィック、フォーム、暗号化、圧縮、HTML→PDF。必要なら jsPDF や pdf-lib をご利用ください。
クイックスタート
import { pdf } from 'tinypdf'; import { writeFileSync } from 'fs'; const doc = pdf(); doc.page((ctx) => { ctx.rect(50, 700, 200, 40, '#2563eb'); // 青い四角形 ctx.text('Hello PDF!', 60, 712, 24, { color: '#ffffff' }); ctx.line(50, 680, 250, 680, '#000000', 1); // 黒い線 }); writeFileSync('output.pdf', doc.build());
画像を追加
import { readFileSync } from 'fs'; doc.page((ctx) => { const logo = new Uint8Array(readFileSync('logo.jpg')); ctx.image(logo, 50, 700, 100, 50); });
テキスト幅の測定
import { measureText } from 'tinypdf'; measureText('Hello', 12); // → 27.34 (ポイント)
Markdown を PDF に変換
import { markdown } from 'tinypdf'; import { writeFileSync } from 'fs'; const pdf = markdown(` # Hello World A minimal PDF from markdown. ## Features - Headers (h1, h2, h3) - Bullet lists - Numbered lists - Horizontal rules --- Automatic word wrapping and pagination included. `); writeFileSync('output.pdf', pdf);
API 仕様
| メソッド | 説明 |
|---|---|
| ドキュメントを作成 |
| デフォルトサイズ(612×792)でページ追加 |
| カスタムサイズのページ追加 |
| を返す |
options: | テキスト描画 |
| 塗りつぶし四角形 |
| 線 |
| JPEG 画像 |
| テキスト幅(ポイント) |
options: | Markdown を PDF に変換 |
完全な例 – 請求書ジェネレーター(約50行)
import { pdf } from 'tinypdf'; import { writeFileSync } from 'fs'; const doc = pdf(); doc.page(612, 792, (p) => { const margin = 40, pw = 532; // ヘッダー p.rect(margin, 716, pw, 36, '#2563eb'); p.text('INVOICE', 55, 726, 24, { color: '#fff' }); p.text('#INV-2025-001', 472, 728, 12, { color: '#fff' }); // 会社・請求先情報 p.text('Acme Corporation', margin, 670, 16); p.text('123 Business Street', margin, 652, 11, { color: '#666' }); p.text('New York, NY 10001', margin, 638, 11, { color: '#666' }); p.text('Bill To:', 340, 670, 12, { color: '#666' }); p.text('John Smith', 340, 652, 14); p.text('456 Customer Ave', 340, 636, 11, { color: '#666' }); p.text('Los Angeles, CA 90001', 340, 622, 11, { color: '#666' }); // テーブルヘッダー p.rect(margin, 560, pw, 25, '#f3f4f6'); p.text('Description', 50, 568, 11); p.text('Qty', 310, 568, 11); p.text('Price', 380, 568, 11); p.text('Total', 480, 568, 11); const items = [ ['Website Development', '1', '$5,000.00', '$5,000.00'], ['Hosting (Annual)', '1', '$200.00', '$200.00'], ['Maintenance Package', '12', '$150.00', '$1,800.00'], ]; let y = 535; for (const [desc, qty, price, total] of items) { p.text(desc, 50, y, 11); p.text(qty, 310, y, 11); p.text(price, 380, y, 11); p.text(total, 480, y, 11); p.line(margin, y - 15, margin + pw, y - 15, '#e5e7eb', 0.5); y -= 30; } // 合計 p.line(margin, y, margin + pw, y, '#000', 1); p.text('Subtotal:', 380, y - 25, 11); p.text('$7,000.00', 480, y - 25, 11); p.text('Tax (8%):', 380, y - 45, 11); p.text('$560.00', 480, y - 45, 11); p.rect(370, y - 75, 202, 25, '#2563eb'); p.text('Total Due:', 380, y - 63, 12, { color: '#fff' }); p.text('$7,560.00', 480, y - 63, 12, { color: '#fff' }); // フッター p.text('Thank you for your business!', margin, 80, 12, { align: 'center', width: pw, color: '#666' }); p.text('Payment due within 30 days', margin, 62, 10, { align: 'center', width: pw, color: '#999' }); }); writeFileSync('invoice.pdf', doc.build());
ライセンス
MIT