How to Integrate html-to-pdfmake with pdfmake: A Complete Developer's Guide

html-to-pdfmake converts HTML strings into PDFMake document definitions, allowing you to generate PDFs from HTML content by parsing the DOM, recursively walking the tree, and returning a JSON structure compatible with pdfmake's createPdf() method.

The aymkdn/html-to-pdfmake library serves as a bridge between HTML content and the pdfmake PDF generation engine. When you integrate html-to-pdfmake with pdfmake, you transform rich HTML strings—including tables, images, lists, and styled text—into the document definition format that pdfmake requires to render professional PDF documents.

How html-to-pdfmake Works Under the Hood

Understanding the conversion pipeline helps debug styling issues and optimize performance. The core logic in index.js follows a five-step architectural flow.

DOM Parsing and Tree Traversal

First, the library parses the HTML string using a DOMParser in browser environments or a jsdom window in Node.js. The core htmlToPdfMake.prototype.parseElement method recursively walks every node in the DOM tree, building nested objects like {text:...}, table, or ul/ol structures.

Style Application and Class Generation

As the walker visits each element, applyStyle merges three sources: default element styles built into the library, inline CSS from style attributes, and user-supplied defaultStyles. The library automatically generates class names like html-p or html-h1 for each element unless you set removeTagClasses: true in the options.

Special Element Handling

The converter contains dedicated branches for complex elements. Tables handle column/row spans and auto-sizing via tableAutoSize. Images support reference-based embedding through imagesByReference. SVG paths, <hr> elements, and custom tags processed via the customTag callback all receive specialized treatment in the switch-statement logic of index.js.

How to Integrate html-to-pdfmake with pdfmake in Node.js

Server-side integration requires three components: the converter, pdfmake itself, and a DOM implementation for parsing.

First, install the necessary packages:

npm install html-to-pdfmake pdfmake jsdom

Then implement the conversion pipeline. According to example.js (lines 1-4 and 5-8), you must load pdfmake's virtual font file system and create a jsdom window:

// 1️⃣ Load pdfmake and its virtual file system fonts
const pdfMake   = require('pdfmake/build/pdfmake');
const pdfFonts  = require('pdfmake/build/vfs_fonts');
pdfMake.vfs = pdfFonts;                       // <- make fonts available

// 2️⃣ Create a DOM window for the HTML parser (required in Node)
const {JSDOM}   = require('jsdom');
const {window}  = new JSDOM('').window;      // <-- required for the parser
const htmlToPdf = require('html-to-pdfmake');

// 3️⃣ Your HTML content
const html = `
  <h1>Hello world</h1>
  <p style="color:blue">This is <strong>bold</strong> and <em>italic</em>.</p>
  <img src="https://picsum.photos/seed/picsum/120" />
`;

// 4️⃣ Convert to a pdfmake definition (index.js lines 42-46 show these options)
const content = htmlToPdf(html, { 
  window, 
  tableAutoSize: true 
});

// 5️⃣ Assemble the final doc definition
const docDefinition = {
  content,
  styles: { 
    h1: { fontSize: 24, bold: true } 
  }
};

// 6️⃣ Generate the PDF (as shown in example.js lines 80-84)
pdfMake.createPdf(docDefinition).getBuffer(buf => {
  require('fs').writeFileSync('demo.pdf', buf);
  console.log('→ demo.pdf created');
});

Browser-Side Integration

In browser environments, integration is simpler because the DOM is already available. Load the libraries from a CDN and call the global htmlToPdfmake function exposed by browser.js:

<!DOCTYPE html>
<html>
<head>
  <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>
  <script src="https://cdn.jsdelivr.net/npm/html-to-pdfmake/browser.js"></script>
</head>
<body>
  <button id="download">Download PDF</button>

  <script>
    const html = `
      <h2>Browser demo</h2>
      <p>Simple <strong>HTML → PDF</strong> conversion.</p>
      <hr>
    `;

    document.getElementById('download').onclick = () => {
      // 1️⃣ Convert (no extra options needed in the browser)
      const content = htmlToPdfmake(html); // global from browser.js
      
      // 2️⃣ Build doc definition
      const doc = { content };
      
      // 3️⃣ Create and download
      pdfMake.createPdf(doc).download('browser-demo.pdf');
    };
  </script>
</body>
</html>

Advanced Integration Features

For complex documents, leverage the library's advanced options to handle images, custom elements, and styling.

Handling Images by Reference

When imagesByReference is set to true, the converter returns an object with separate content and images properties rather than embedding image data directly in the content tree. This is handled in the image processing branch of index.js:

const html = `
  <img src="https://picsum.photos/200" />
  <p>Text after image</p>
`;

const result = htmlToPdf(html, {
  window,
  imagesByReference: true  // 👉 returns {content, images}
});

/* result structure:
{
  content: [ … ],
  images: { img_ref_xxxxx: 'https://picsum.photos/200' }
}
*/

const docDefinition = {
  content: result.content,
  images: result.images  // pdfmake resolves these references
};

pdfMake.createPdf(docDefinition).download('advanced.pdf');

Custom Tag Processing

Use the customTag callback to transform non-standard HTML tags into pdfmake-compatible structures. This hook executes within the element processing switch-statement in index.js:

const html = `
  <code typecode="QR" style="foreground:black;background:yellow;fit:300px">
    https://example.com
  </code>
`;

const result = htmlToPdf(html, {
  window,
  customTag: function({element, ret}) {
    if (element.nodeName === 'CODE' && element.getAttribute('typecode') === 'QR') {
      // Turn <code> into a QR node that pdfmake understands
      ret.qr = element.textContent.trim();
      ret.nodeName = 'QR';
    }
    return ret;
  }
});

Key Source Files and Architecture

Understanding the repository structure helps when debugging conversion issues or extending functionality:

File Purpose Key Components
index.js Core conversion engine htmlToPdfMake constructor, parseElement recursive walker, applyStyle method, table/image/SVG handlers
example.js Full Node.js integration demo JSDOM window setup, font loading, document definition assembly, buffer generation (lines 1-84)
browser.js Browser bundle entry point Exposes global htmlToPdfmake function, assumes native DOM
docs/index.html Live browser demonstration Interactive HTML-to-PDF conversion showcase

The architectural flow in index.js follows this pipeline: DOM ParsingRecursive Tree Walking (parseElement) → Style Application (applyStyle) → Specialized Element Handling (tables, images, custom tags) → Document Definition Output.

Summary

  • html-to-pdfmake acts as a bridge that converts HTML strings into PDFMake document definitions, handling the complexity of DOM parsing and style mapping.
  • The integration requires a DOM environment (native in browsers, jsdom in Node.js) passed via the window option to parse the HTML before conversion.
  • Key configuration options include tableAutoSize for intelligent table sizing, imagesByReference for external image handling, and customTag for processing non-standard HTML elements.
  • The core conversion logic resides in index.js, with parseElement handling recursive DOM traversal and applyStyle managing CSS-to-pdfmake property mapping.
  • Both server-side (Node.js with file output) and client-side (browser with download) integrations follow the same pattern: convert HTML to content definition, assemble the document definition object, then call pdfMake.createPdf().

Frequently Asked Questions

What is the relationship between html-to-pdfmake and pdfmake?

html-to-pdfmake is a conversion utility that prepares data for pdfmake, which is the actual PDF generation engine. While pdfmake requires you to construct document definitions using its specific JSON schema, html-to-pdfmake allows you to write content in HTML and automatically transforms it into that schema. The library does not render PDFs itself; it only produces the content structure that pdfmake's createPdf() method consumes.

How do I handle images when integrating html-to-pdfmake with pdfmake?

By default, images are processed as standard HTML image elements within the content tree. For better performance and to enable pdfmake's built-in image caching, set imagesByReference: true in the conversion options. This returns an object with separate content and images properties, where the images object contains URL mappings that pdfmake resolves during rendering. This approach is particularly useful when the same image appears multiple times in your document.

Can I use html-to-pdfmake without a browser environment?

Yes, but you must provide a DOM implementation because the library relies on DOM APIs to parse HTML. In Node.js, install jsdom and pass the window object in the options: { window: new JSDOM('').window }. The example.js file in the repository demonstrates this setup (lines 5-8). Without this DOM environment, the conversion will fail because the code requires DOMParser and other browser APIs to traverse the HTML tree.

How are CSS styles converted to pdfmake compatible properties?

The applyStyle method in index.js handles the conversion by merging three style sources: default element styles built into the library, inline CSS from style attributes, and user-supplied defaultStyles. The library maps common CSS properties (colors, fonts, alignment, borders) to pdfmake's specific JSON format. It also generates automatic class names like html-p or html-h1 for each element unless you disable this with removeTagClasses: true. Complex properties like table borders undergo specific parsing to match pdfmake's cell border structure.

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 →