html_to_pdf
Generate simple PDF invoice from HTML using puppeteer & handlebars
Introduce
-
Puppeteer is Node.js library giving you access to a headless Chrome browser. This makes it a breeze to generate PDF files with Node.js
-
Handlebars provides the power necessary to let you build semantic templates effectively with no frustration
How to use
- Run
npm install
to install package in package.json - Run
node pdf.js
to generate invoice.pdf
The PDF Invoice from HTML
- Prepare content html (invoice.html)
- Using handlebars to binding data to content html
- Using Puppeteer to generate pdf from final html
const fs = require("fs"); const path = require("path"); const puppeteer = require('puppeteer'); const handlebars = require("handlebars"); (async () => { var dataBinding = { items: [{ name: "item 1", price: 100 }, { name: "item 2", price: 200 }, { name: "item 3", price: 300 } ], total: 600, isWatermark: false } var templateHtml = fs.readFileSync(path.join(process.cwd(), 'invoice.html'), 'utf8'); var template = handlebars.compile(templateHtml); var finalHtml = template(dataBinding); var options = { format: 'A4', headerTemplate: "<p></p>", footerTemplate: "<p></p>", displayHeaderFooter: false, margin: { top: "40px", bottom: "100px" }, printBackground: true, path: 'invoice.pdf' } const browser = await puppeteer.launch({ args: ['--no-sandbox'], headless: true }); const page = await browser.newPage(); await page.goto(`data: text/html,${finalHtml}`, { waitUntil: 'networkidle0' }); await page.pdf(options); await browser.close(); })();
How to display paid stamp watermark on the invoice?
Using handlebars to check param isWatermark
{{#if isWatermark}} <div style="border-width: 6px;border-style: solid; border-color: #008000;border-radius: 8px; color: #008000; opacity:0.6; position: absolute; z-index: 1; left:40%; top:30%; font-size: 60pt;-webkit-transform: rotate(-45deg);-ms-transform: rotate(-45deg);transform: rotate(-45deg); font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif;"> PAID </div> {{/if}}
Change isWatermark: true
and run node pdf.js
again
You can find the source code at Github
Thank your time to read this post
PS:/ This is the first post on dev.to
Top comments (3)
The
data: text/html
trick is cool to avoid having to serve the final HTML to Chrome. I guess if images were involved you'd need to start serving the files from somewhere though.I recently wrote up a bit of an overview of various ways you can use Chrome headless for PDF conversion here.
Thanks for your reply :)
With images, we can convert to base64 and embed to HTML. No need start serving the files from somewhere
Oh yeah, that's clever too!