Deno で PDF を操作する方法を調べたので、まとめる。
参考
Deno で PDF を操作する
PDF を結合
1 2 3
| import { mergePdfs } from "https://deno.land/x/pdfrex@v0.0.2/mod.ts";
mergePdfs(["page1.pdf", "page2.pdf", "page3.pdf"]);
|
merged.pdf
という名称で指定された PDF が結合したファイルが生成される。
PDF を分割
1 2 3
| import { splitPdf } from "https://deno.land/x/pdfrex@v0.0.2/mod.ts";
splitPdf("merged.pdf");
|
./merged/ ディレクトリに1pずつ分割された PDF が生成される。
pdfrex は回転などもできる紹介があるが、モジュールでは提供されていない。
pdf-lib に依存しているが、このモジュールは3年近く更新されていない様子。
PDF を作る
PDFを作れそうなモジュールはいくつかある。
試してみいたが、Deno で動かすのは難しそうだった。
中を見ると phantom.js か、puppeteer が使われているようだった。
phantom.js はもうメンテされていないので、puppeteer を使うのが良さそう。
以下のような実装でPDFを作ることができる。
マークダウン => PDF
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import puppeteer from "https://deno.land/x/puppeteer@16.2.0/mod.ts"; import { parse as markedParse } from "npm:marked";
const sourceMarkDown = Deno.readTextFileSync("source.md");
const html = markedParse(sourceMarkDown);
console.log(html);
const browser = await puppeteer.launch({}); const page = await browser.newPage(); await page.setContent(`<html><body>` + html + "</body></html>");
await page.pdf({ path: "page.pdf", format: "A4", });
page.close(); browser.close();
Deno.exit();
|
マークダウン => PDF(スタイリング/ヘッダー/フッター)
jsonから設定を読み込む形で、複数のファイルを分割で作成できるようにした。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| import puppeteer from "https://deno.land/x/puppeteer@16.2.0/mod.ts"; import { parse as markedParse } from "npm:marked"; import { parse as jsoncParse } from "jsr:@std/jsonc";
const setupText = Deno.readTextFileSync("setup.json"); const setup = jsoncParse(setupText);
const mds = [];
for (const document of setup.documents) { const mdText = Deno.readTextFileSync(document.file); mds.push(mdText); }
const html = markedParse(mds.join("\n\n"));
const browser = await puppeteer.launch({}); const page = await browser.newPage(); await page.setContent(`<html><body>` + html + "</body></html>");
await page.pdf({ path: "output.pdf", format: "A4", margin: { top: "100px", bottom: "60px" }, displayHeaderFooter: true, headerTemplate: `<div style="display: inline-block; width: 75%; margin: 0 2cm"> <img style="height: 50px;" /> <div style="float: right; font-size: 17pt; text-align: right;">Header</div> </div>`, footerTemplate: ` <div style="margin: 0 2cm; width: 75%; font-size: 17px; text-align: center;"> Footer<span class="pageNumber"></span>/<span class="totalPages "> </div> `, });
page.close(); browser.close();
Deno.exit();
|
次のような、jsonをセットアップ用のjsonを作成する。
1 2 3 4 5 6 7 8 9 10 11
| { "documents": [ { "file": "./source.md" }, { "file": "./source2.md" } ] }
|
読み込み対象のマークダウンには、cssを書けるので、スタイリングも可能。
以下がマークダウンのサンプル。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <style > * { color: #600; }
h1 { page-break-before:always; } </style>
# h1
## h2
### h3
#### h4
##### h5
###### h6
`text`
|
全部赤くして、h1 が入るとページを分けるようにしている。
作成されたファイルは次のようになる。
Deno でPDFを取り扱う方法を調べました。
PDF周りは仕様に大きな動きが無いことから、あまりメンテされていないモジュールでも第一線で使われているように見えます。
npmから直接 puppeteer を使うことは少し難しそうなので、deno.land/x から使うのが良さそうです。
では。