Takumi

From Puppeteer

Move a Puppeteer PDF template to takumi-pdf.

Start with the HTML you pass to page.setContent(). Pass that string to render() and translate the page options using the table below. Headers and footers use the same pageNumber and totalPages class hooks.

Takumi does not navigate a page or execute its scripts. Generate dynamic content and fetch document images before rendering. Check your template against the supported CSS features.

Before and after

// Puppeteer
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.setContent(html, { waitUntil: "networkidle0" });

const pdf = await page.pdf({
  format: "A4",
  margin: { top: "48px", bottom: "64px", left: "48px", right: "48px" },
  displayHeaderFooter: true,
  footerTemplate: `<div style="font-size:10px;width:100%;text-align:center">
    Page <span class="pageNumber"></span> of <span class="totalPages"></span>
  </div>`,
  printBackground: true,
});

await browser.close();
// takumi-pdf
import {  } from "@takumi-rs/helpers";
import {  } from "takumi-pdf";
import { ,  } from "takumi-pdf/primitives";

const  = await (, {
  : "a4",
  : { : 48, : 64, : 48, : 48 },
  : (
    < ="flex w-full justify-center text-[10px]">
      Page < /> of < />
    </>
  ),
  : await (["Inter"]),
});

render() parses HTML strings, including embedded <style> tags. It also accepts JSX and node trees. Headers and footers accept the same inputs.

Option map

page.pdf()takumi-pdf
format: "A4"size: "a4"
width, heightsize: { width, height }
landscapelandscape
marginmargin, in CSS px
displayHeaderFooter + headerTemplateheader
footerTemplatefooter
pageNumber, totalPages classesthe same classes
date, title, url classesinterpolate the value yourself
tagged (default on)tagged (default on)
outlineoutline
printBackgroundalways on
pathwrite the returned Uint8Array
timeout, waitForFontsnot needed: no page to load
scalenot supported: scale the CSS instead
pageRangespageRanges: [1, { from: 4, to: 8 }]
preferCSSPageSize, @pagenot supported: set size and margin
omitBackgroundnot supported

Margins take numbers in CSS px. Chromium's "0.5in" strings have no equivalent; 48 is that half inch.

Fetching moves to your code

Use prepareImages() to fetch document images before rendering. Parse the HTML first so the helper can inspect its image references:

import {  } from "@takumi-rs/helpers";
import {  } from "@takumi-rs/helpers/html";
import {  } from "takumi-pdf";

const { ,  } = ();
const  = await ({  });

const  = await (, { ,  }); 

prepareImages walks the tree, fetches every remote <img>, background-image, and mask-image URL, and returns the images entries. It takes a fetchCache to reuse bytes, an allowUrl predicate, and a timeout.

Fonts come from the fonts option rather than a CSS @font-face rule. See Fonts & images.

Apply timeouts and URL policies to image fetching. Font URL loaders and googleFonts() also perform requests, so configure their fetch policies separately.

Check browser-dependent features

Chrome is a browser. Takumi is a layout engine with a document-shaped CSS subset.

  • No scripts. Charts and diagrams have to arrive as markup, SVG, or images. A client-side chart library will not run.
  • Narrower CSS. No filter: blur(), drop-shadow(), or backdrop-filter in PDF output. A blurred box-shadow approximates with bands. Grid and flex, transforms, gradients, masks, and clip paths all work.
  • No @page. Page geometry lives in the options.

Keep Puppeteer to reproduce a live web page as it appears in a browser. Move to takumi-pdf for documents written for print, and see Comparison for the measured numbers.

Last updated on

On this page