Guide
Node.js
The pdg npm package — render an XML document to a PDF from Node, async or sync, or throw with the engine's diagnostics.
The pdg npm package renders a pdg XML document to PDF bytes in Node. The engine
is packed into the package (one package bundles a prebuilt binary for every
platform), so there's no toolchain to install and nothing to compile.
import { render } from "pdg";
import { writeFile } from "node:fs/promises";
const pdf = await render(xml, { base: "invoices" });
await writeFile("invoice.pdf", pdf);
The XML you pass is the document format documented throughout these guides — see Document structure and the element reference.
ESM, Node ≥ 18, with bundled TypeScript types.
Installation
npm install pdg
Rendering
The document is a string (or Uint8Array); base is the asset directory (see
Assets). Each async function has a synchronous *Sync counterpart.
import {
render,
renderWithMeta,
renderFile,
renderSync,
} from "pdg";
// PDF bytes (a Buffer). Rejects on failure.
const pdf = await render(xml, { base: "." });
// Bytes plus metadata.
const result = await renderWithMeta(xml);
result.pages; // 3
result.bytes; // 48213 (result.pdf.length)
result.objects; // 412
result.timings; // { parseMs, layoutMs, pdfMs }
result.warnings; // [Diagnostic, ...]
result.pdf; // Buffer
// Straight to a file (resolves to the Result).
await renderFile(xml, "report.pdf", { base: "assets" });
// Synchronous variants block the event loop — use the async forms in servers.
const pdfSync = renderSync(xml);
Assets
Relative paths inside the document — <font-face src>, <image src>,
<pdf src> — resolve against base (default: the current working directory).
http(s) URLs and <google-font> faces are fetched by the engine regardless.
await render(xml, { base: new URL("./pdf-assets", import.meta.url).pathname });
Errors and diagnostics
Every error extends PdgError.
RenderError— the engine withheld a PDF (a strict-mode block or a fatal parse/layout error); carries.diagnosticsand the raw.meta.BinaryError— the engine couldn't run (an installation/environment problem).
import { RenderError } from "pdg";
try {
await render(xml);
} catch (err) {
if (err instanceof RenderError) {
for (const d of err.diagnostics) {
d.severity; // "warning" | "error"
d.code; // "unknown-tag", "content-dropped", …
d.message;
d.line;
d.col;
d.trace; // enclosing tags, innermost first
}
}
}
Warnings don't throw — a recoverable render resolves to a Result; read
result.warnings.
Browser
This package spawns a subprocess and is Node-only. To render in the browser, use
the Browser guide and the pdg-browser package, which runs the
engine as WebAssembly.
How it works
The package drives the packed engine over stdio (XML on stdin, PDF on stdout, one
JSON meta object on stderr) behind a single module, so the same engine that powers
the CLI and this playground produces your PDFs. Set the PDG_BINARY environment
variable to override the bundled binary.