PDF は多くの場所で使われているフォーマットです。その特徴としてどの環境でもほぼ同じ見た目になる点があります(フォントをPDF閲覧用ソフトが自動で補完してくれる環境とそうでない環境で文字化けの差異が起きるケースに遭いました)。このため PDF 出力がシステムの要望に含まれることが度々あります。pdf-lib はそういった PDF を生成、編集できるライブラリの一つです。
リポジトリは次で、ここにある JSFiddle のデモやサンプルコードで大体足ります。
Hopding/pdf-lib: Create and modify PDF documents in any JavaScript environment
インストールは例によって npm でできますが、素では日本語フォントに対応していないため次の様にフォント用の拡張もインストールする必要があります。
npm install --save pdf-lib @pdf-lib/fontkit
使い方は比較的シンプルです。次の様に使えます。
import { PDFDocument } from 'pdf-lib';
import fontkit from '@pdf-lib/fontkit';
/** PDFの生成 */
// まっさらな PDF を用意
const pdfDoc = await PDFDocument.create();
// PDF にフォントを追加
// フォント拡張機能を使うと登録
pdfDoc.registerFontkit(fontkit);
// 日本語フォントを取得
const fontRaw = await fetch('/assets/fonts/ipamp.ttf').then((res) => res.arrayBuffer());
// 日本語フォントを PDF に埋め込み
// 追記: フォントのサブセット化は明示的に指定する必要あり。サブセットならばフルセットよりずっとファイルサイズが小さくなります
const fontIpamp = await pdfDoc.embedFont(fontRaw, {subset: true});
// PDFにページを追加
const A4 = [841.99, 594.35]; // A4サイズ定義
const page = pdfDoc.addPage(A4);
// 日本語フォントで PDF 中に書き込み
page.drawText('こんにちわ', { x: 0, y: 0, font: fontIpamp, size: 6.5 });
// ダウンロード
// Uint8Array 型で PDF のバイナリが生成されます
const pdfBytes = await pdfDoc.save();
// 後はよくある Blob のダウンロードでユーザーにダウンロードさせられます
/* フォントの埋め込み方は他に↓があります。*/
// Base64文字列として埋め込み
const font2 = await pdfDoc.embedFont('AAEAAAAVAQAABABQRFNJRx/upe...');
const font3 = await pdfDoc.embedFont('data:font/opentype;base64,AAEAAA...');
// Node.js や Deno で使う用の readFileSync 結果からの読み込み
import fs from 'fs';
const font4 = await pdfDoc.embedFont(fs.readFileSync('Ubuntu-R.ttf'));
/* PDF の編集は次でできます */
const tempalteRaw = await fetch('/assets/pdf/template.pdf').then((res) => res.arrayBuffer());
// フォントファイル同様に、fetch結果.arrayBuffer() or Base64文字列 or readFileSync結果 のいずれかのPDFデータを渡します
const pdfDoc = await PDFDocument.load(tempalteRaw);
// 既にページがあるので次の様に getPages から編集したいページを選んでどうこうします。
const pages = pdfDoc.getPages();
pages[0].drawText('おはようございます');
またソースコードが TypeScript で記述されており扱いやすいです。