How to Use html-to-pdfmake in Node.js vs Browser: Complete Guide

To use html-to-pdfmake in Node.js, you must supply a jsdom window object via the window option, while the browser build automatically uses the native global window without extra configuration.

html-to-pdfmake is a lightweight wrapper that converts HTML strings into PDFMake document-definition objects. Whether you are generating PDFs server-side with Node.js or client-side in a web application, the library shares the same core conversion logic found in index.js. The only difference lies in how the DOM parsing environment is provided.

How html-to-pdfmake Works Across Environments

The library abstracts DOM parsing through a window reference. In the browser, this is the native global object. In Node.js, you must create this context using jsdom.

Node.js Implementation with jsdom

When running in Node.js, html-to-pdfmake relies on the window option to access DOMParser. According to the source code in index.js (lines 21-24), the constructor uses new this.wndw.DOMParser() to parse the HTML string. Without supplying a jsdom window, this call fails because Node.js lacks a native DOM.

The constructor (lines 41-48) stores the provided window, initializes default styles, and creates a random suffix for image references. This setup allows the recursive parseElement function to traverse the DOM tree exactly as it would in a browser.

Browser Implementation

In the browser, the library uses the pre-bundled browser.js file, which exposes a global htmlToPdfmake function. This build automatically references the browser's native window and DOMParser, eliminating the need for jsdom or any manual window injection.

The same parseElement logic handles text nodes, element nodes, tables, lists, and images. Style resolution via applyStyle merges default CSS, inline styles, and class names regardless of the environment.

Complete Node.js Setup Example

To use html-to-pdfmake server-side, install the required dependencies and provide a jsdom window:

// npm install html-to-pdfmake jsdom pdfmake

const pdfMake = require('pdfmake/build/pdfmake');
const pdfFonts = require('pdfmake/build/vfs_fonts');
pdfMake.vfs = pdfFonts; // Required for fonts

const { JSDOM } = require('jsdom');
const htmlToPdfmake = require('html-to-pdfmake');

// Create a jsdom window for DOM parsing
const { window } = new JSDOM('');

const html = `
  <h1>Server-Side PDF</h1>
  <p>This <strong>bold</strong> text renders via Node.js.</p>
`;

const docDefinition = {
  content: htmlToPdfmake(html, { window }) // Pass the window option
};

pdfMake.createPdf(docDefinition).getBuffer((buffer) => {
  require('fs').writeFileSync('output.pdf', buffer);
});

Critical requirements for Node.js:

  • The window option is mandatory and must be a jsdom window object.
  • pdfmake requires virtual font files (vfs) to render text.

Complete Browser Setup Example

For client-side usage, include the bundled script and use the global function:

<!DOCTYPE html>
<html>
<head>
  <!-- pdfmake core and fonts -->
  <script src="https://cdn.jsdelivr.net/npm/pdfmake@latest/build/pdfmake.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/pdfmake@latest/build/vfs_fonts.min.js"></script>
  
  <!-- html-to-pdfmake browser build -->
  <script src="https://cdn.jsdelivr.net/npm/html-to-pdfmake/browser.js"></script>
</head>
<body>
  <script>
    const html = `
      <h1>Client-Side PDF</h1>
      <p>An <em>italic</em> paragraph with an image:</p>
      <img src="https://example.com/logo.png" width="100">
    `;

    // No window argument needed; uses native browser DOM
    const content = htmlToPdfmake(html);
    
    pdfMake.createPdf({ content }).download('browser-output.pdf');
  </script>
</body>
</html>

Key differences from Node.js:

  • No jsdom installation or window option required.
  • The browser.js bundle exposes htmlToPdfmake as a global function.
  • Image handling can use imagesByReference for advanced use cases.

Key Configuration Options

Both environments accept the same options object passed to htmlToPdfmake(html, options):

  • windowRequired in Node.js. A jsdom window object providing DOMParser. In the browser, this is ignored in favor of the global window.
  • defaultStyles – Override default element styling (e.g., h1: { fontSize: 30, bold: true }).
  • tableAutoSize – Boolean to enable automatic table sizing based on CSS width/height attributes and <colgroup> definitions.
  • imagesByReference – Boolean (browser only). When true, images are returned as reference keys rather than embedded data URIs, producing a separate images object in the result.
  • removeTagClasses – Boolean to disable automatic generation of html-TAG classes (e.g., html-div, html-p).
  • customTag – Function callback to intercept specific HTML tags and return custom PDFMake content structures.

Core Source Files and Architecture

The library maintains a single code path for both environments through these key files:

  • index.js – The core implementation containing the htmlToPdfMake class constructor (lines 41-48), DOM parsing logic (lines 21-24), and the recursive parseElement method. This file handles style aggregation via applyStyle and special element processing for tables, images, and lists.
  • browser.js – A UMD bundle that wraps the core logic for browser usage, exposing the global htmlToPdfmake function without requiring module loaders.

Both builds export the same htmlToPdfmake function that instantiates the internal class. The constructor stores the provided window reference (critical for Node.js), initializes default styles, and prepares image reference tracking. The parseElement method then walks the DOM tree depth-first, using searchForStack to determine whether content should render as a PDFMake stack or text node.

Summary

  • html-to-pdfmake converts HTML strings into PDFMake document definitions using a shared core in index.js.
  • Node.js usage requires installing jsdom and passing the resulting window object via the window option.
  • Browser usage loads the pre-bundled browser.js and uses the native global window automatically.
  • Both environments support identical options including defaultStyles, tableAutoSize, and customTag callbacks.
  • The library handles complex elements like tables, images, and nested lists through recursive DOM parsing and style aggregation.

Frequently Asked Questions

Do I need jsdom to use html-to-pdfmake in Node.js?

Yes. The library requires a DOM environment to parse HTML strings. In Node.js, you must install jsdom and pass the resulting window object via the window option: htmlToPdfmake(html, { window: new JSDOM('').window }). Without this, the library cannot access DOMParser and will throw an error.

Can I use html-to-pdfmake in the browser without a bundler?

Yes. The library ships a pre-bundled browser.js file that you can load via CDN or script tag. This exposes a global htmlToPdfmake function that automatically uses the browser's native window and DOMParser. No module bundler or jsdom is required for browser usage.

What is the difference between the index.js and browser.js builds?

index.js is the core CommonJS module designed for Node.js environments where you must manually provide a window object (typically via jsdom). browser.js is a UMD bundle that wraps the same core logic but assumes a global browser window is available. Both expose the same htmlToPdfmake function and support identical configuration options.

Does html-to-pdfmake support images in both Node.js and the browser?

Yes, but with different considerations. In both environments, the library can process <img> tags with src attributes. In the browser, you can set imagesByReference: true to return image references separately from the content definition, which is useful for managing binary image data. In Node.js, ensure your jsdom window can resolve image URLs or use data URIs for embedded images.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →