TypescriptでPDFを生成（Server Side）

## はじめに
今回はTypescriptでPDF出力する際に使用した[pdfmake](http://pdfmake.org/#/)のご紹介です。pdfmakeは[pdfkit](https://pdfkit.org/)のラッパーで、表示したいテキストやレイアウト情報をJSON形式でライブラリの関数に渡すことでPDFを簡単に生成することができます。

## pdfmakeを選んだ理由
[pdf-lib](https://pdf-lib.js.org/)など後発のライブラリもいくつかあるようですが、以下の点で今回は[pdfmake](http://pdfmake.org)を採用しました。

- スター数（[pdfkit](https://pdfkit.org/)よりも多い）
- レイアウトの計算をライブラリ側で行ってくれるのでコード量が少なくて済む
- Playgroundを使って表示を確認しながら開発を進められる
- 日本語フォントが使用できる

## pdfmakeを使った開発の流れ

今回pdfmakeを使って開発を進めた際の流れをまとめてみました。

### 1. まず公式ドキュメントを読む
pdfmakeの開発者向け[ドキュメント](https://pdfmake.github.io/docs/0.1/getting-started/)の `document-definition-object` セクションにざっと目を通してレイアウト/スタイリングの種類と指定方法を一通り理解します。各レイアウト/スタイリングの説明もそこまでボリュームはないので、表の作成や画像の埋め込み（SVGも対応）など、実装に必要そうなところを集中して読めば、そこまで時間はかからないと思います。

### 2. Playgroundでレイアウト
個人的に先にpdfmakeが用意しているライブビュー付きの[Playground](http://pdfmake.org/playground.html)で一通りのレイアウトを仕上げてしまうのが効率的かと思っています。ローカル開発環境でコードを変更してPDF生成、の繰り返しだとあまりに時間がかかってしまいます。ただ注意点として、Playgroundだと日本語の表示ができないため、何かしら英語のテキストを仮に入れておくことになります。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674308/ec1cdf01-9e88-d2a2-3b4f-cd57b9586501.png)

### 3. ライブラリのインストール
```bash

npm i pdfmake
npm i -D @types/pdfmake
```

### 4. 日本語のフォントをダウンロード
GoogleのNoto Sans JPや源ノ角ゴシックなど、オープンソースのフォントはOpenType形式で公開されているのですが、pdfmakeではTrueType形式のフォントを使用する必要があるため、今回は源ノ角ゴシックをTrueType形式に変換した、[源真ゴシック](http://jikasei.me/font/genshin/)を使用させて頂きました。

### 5. `createPdfKitDocument`メソッドにJSON形式のデータを渡す
`createPdfKitDocument`メソッドにJSON形式のデータを渡しPDFを生成し、`fs` を使ってファイルを書き出した例です。

```typescript

import PdfPrinter from "pdfmake";
import fs from "fs";

const fonts = {
  GenShinGothic: {
    normal: "src/assets/fonts/GenShinGothic/GenShinGothic-Normal.ttf",
    bold: "src/assets/fonts/GenShinGothic/GenShinGothic-Normal.ttf",
    italics: "src/assets/fonts/GenShinGothic/GenShinGothic-Normal.ttf",
    bolditalics: "src/assets/fonts/GenShinGothic/GenShinGothic-Normal.ttf",
  },
};

const printer = new PdfPrinter(fonts);

const docDefinition = {
  content: [
    {
      columns: [
        {
          width: "auto",
          text: "カラム 1",
        },
        {
          width: "*",
          text: "カラム 2",
        },
        {
          width: 100,
          text: "カラム 3",
        },
        {
          width: "20%",
          text: "カラム 4",
        },
      ],
      columnGap: 10,
    },
  ],
  defaultStyle: {
    font: "GenShinGothic",
  },
};


const pdfDoc = printer.createPdfKitDocument(docDefinition);
pdfDoc.pipe(fs.createWriteStream("sample.pdf"));
pdfDoc.end();
```

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674308/99fdd196-6c71-9535-8ff5-ae7dbcc43134.png)

### 6. PDFの権限設定

Adobe Acrobatでの編集や画像/テキストのコピーを防ぐなど、出力されるPDFの権限設定が可能です。公式ドキュメントの[こちら](https://pdfmake.github.io/docs/0.1/document-definition-object/security/)に記載があります。

```typescript
var docDefinition = {
  userPassword: '123', // PDFを開くためのパスワード
  ownerPassword: '123456', // 編集を行うためのパスワード
  permissions: {
    printing: 'highResolution', // 印刷時の解像度（highResolution/lowResolution）
    modifying: false, // パスワードなしに編集できるか
    copying: false, // テキストや画像をコピーできるか
    ... // 他にもいくつか設定項目があります
  },
  content: [
    ...
  ]
};
```

## まとめ
以上、TypescriptでPDFを生成するのに便利なpdfmakeのご紹介でした。日本語フォントの扱いで最初につまづきましたが、それ以外はシンプルでとても使いやすい印象でした。