UNPKG

@maistik/nuxt-pdf

Version:

A Nuxt 3 module for server-side PDF generation using Handlebars templates

119 lines (118 loc) 3.79 kB
import FormData from "form-data"; export function createPdfProvider(providerType, config) { switch (providerType) { case "gotenberg": return new GotenbergProvider(config.gotenberg); case "browserless": return new BrowserlessProvider(config.browserless); case "puppeteer": return new PuppeteerProvider(config.puppeteer); default: throw new Error(`Unknown PDF provider: ${providerType}`); } } class GotenbergProvider { constructor(config) { this.config = config; } async generatePdf(html, options) { const form = new FormData(); const htmlBuffer = Buffer.from(html, "utf8"); form.append("files", htmlBuffer, { filename: "index.html", contentType: "text/html", knownLength: htmlBuffer.length }); if (options.format) { const dimensions = this.getPageDimensions(options.format); form.append("paperWidth", dimensions.width); form.append("paperHeight", dimensions.height); } if (options.margin) { form.append("marginTop", (options.margin.top / 25.4).toString()); form.append("marginBottom", (options.margin.bottom / 25.4).toString()); form.append("marginLeft", (options.margin.left / 25.4).toString()); form.append("marginRight", (options.margin.right / 25.4).toString()); } if (options.landscape) { form.append("landscape", "true"); } if (options.printBackground) { form.append("printBackground", "true"); } form.append("waitForNetworkIdle", "true"); form.append("waitDelay", "1s"); const bodyBuffer = form.getBuffer(); const headers = { ...form.getHeaders(), // multipart/form-data; boundary=XXX "Content-Length": bodyBuffer.length.toString() }; const response = await fetch(`${this.config.url}/forms/chromium/convert/html`, { method: "POST", body: bodyBuffer, headers }); if (!response.ok) { throw new Error(`Gotenberg error: ${response.statusText}`); } return Buffer.from(await response.arrayBuffer()); } getPageDimensions(format) { const formats = { A4: { width: "8.27in", height: "11.69in" }, Letter: { width: "8.5in", height: "11in" }, Legal: { width: "8.5in", height: "14in" } }; return formats[format] || formats["A4"]; } } class BrowserlessProvider { constructor(config) { this.config = config; } async generatePdf(html, options) { const response = await fetch(`${this.config.url}/pdf?token=${this.config.apiKey}`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ html, options: { format: options.format || "A4", margin: options.margin, landscape: options.landscape || false, printBackground: options.printBackground !== false } }) }); if (!response.ok) { throw new Error(`Browserless error: ${response.statusText}`); } return Buffer.from(await response.arrayBuffer()); } } class PuppeteerProvider { constructor(config) { this.config = config; } async generatePdf(html, options) { const puppeteer = await import("puppeteer").then((m) => m.default); const browser = await puppeteer.launch(this.config.launchOptions); try { const page = await browser.newPage(); await page.setContent(html, { waitUntil: "networkidle0" }); const pdfOptions = { format: options.format || "A4", margin: options.margin, landscape: options.landscape || false, printBackground: options.printBackground !== false }; const pdfBuffer = await page.pdf(pdfOptions); return Buffer.from(pdfBuffer); } finally { await browser.close(); } } }