Convert HTML code to PDFMake format with ease, bridging the gap between HTML content and PDFMake document definitions
npx @tessl/cli install tessl/npm-html-to-pdfmake@2.5.0html-to-pdfmake is a JavaScript library that converts HTML markup into PDFMake document definitions, allowing you to generate PDFs from HTML content while maintaining basic styling and structure. It supports a wide range of HTML elements, CSS properties, and works seamlessly in both browser and Node.js environments.
npm install html-to-pdfmakehtml-to-pdfmake/browser.js// CommonJS (Node.js)
const htmlToPdfmake = require('html-to-pdfmake');
// ES6 (with bundler)
import htmlToPdfmake from 'html-to-pdfmake';For browser usage:
<script src="https://cdn.jsdelivr.net/npm/html-to-pdfmake/browser.js"></script>
<!-- Creates global htmlToPdfmake function -->const htmlToPdfmake = require('html-to-pdfmake');
const jsdom = require('jsdom');
const { JSDOM } = jsdom;
const { window } = new JSDOM('');
// Simple HTML conversion
const html = '<h1>Hello World</h1><p>This is a <strong>bold</strong> paragraph.</p>';
const pdfmakeContent = htmlToPdfmake(html, { window });
// Use with PDFMake
const pdfMake = require('pdfmake/build/pdfmake');
const docDefinition = { content: pdfmakeContent };
pdfMake.createPdf(docDefinition).getBuffer((buffer) => {
require('fs').writeFileSync('output.pdf', buffer);
});html-to-pdfmake is built around several core components:
Main conversion function that transforms HTML markup into PDFMake document definitions.
/**
* Transform HTML code to a PDFMake object
* @param {string} htmlText - The HTML code to transform
* @param {object} [options] - Configuration options
* @returns {object|{content: object, images: object}} PDFMake document definition or content with images
*/
function htmlToPdfmake(htmlText, options);Parameters:
htmlText (string): The HTML code to transformoptions (object, optional): Configuration optionsReturns:
options.imagesByReference is true, returns {content, images} object{text: string} objectComprehensive options object for customizing conversion behavior.
interface ConversionOptions {
/** Override default styles for HTML elements */
defaultStyles?: {
[elementName: string]: object;
};
/** Enable automatic table sizing based on content and CSS properties */
tableAutoSize?: boolean;
/** Handle images by reference instead of embedding (browser only) */
imagesByReference?: boolean;
/** Remove extra blank spaces that may cause extra lines in PDF */
removeExtraBlanks?: boolean;
/** Display elements with display:none or visibility:hidden */
showHidden?: boolean;
/** Don't add 'html-TAG' classes to converted elements */
removeTagClasses?: boolean;
/** Array of CSS property names to ignore during conversion */
ignoreStyles?: string[];
/** Font sizes array for legacy <font> tag size attribute (1-7) */
fontSizes?: number[];
/** Custom function to handle non-standard HTML tags */
customTag?: (params: CustomTagParams) => object;
/** The window object (required for Node.js server-side use) */
window?: Window;
/** Custom text replacement function to modify text content during conversion */
replaceText?: (text: string, parents: Element[]) => string;
}
interface CustomTagParams {
/** The HTML element being processed */
element: Element;
/** Array of parent elements */
parents: Element[];
/** Current PDFMake object being built */
ret: object;
}Default Styles Object:
The library includes built-in default styles for HTML elements, which can be overridden:
const defaultStyles = {
b: { bold: true },
strong: { bold: true },
u: { decoration: 'underline' },
del: { decoration: 'lineThrough' },
s: { decoration: 'lineThrough' },
em: { italics: true },
i: { italics: true },
h1: { fontSize: 24, bold: true, marginBottom: 5 },
h2: { fontSize: 22, bold: true, marginBottom: 5 },
h3: { fontSize: 20, bold: true, marginBottom: 5 },
h4: { fontSize: 18, bold: true, marginBottom: 5 },
h5: { fontSize: 16, bold: true, marginBottom: 5 },
h6: { fontSize: 14, bold: true, marginBottom: 5 },
a: { color: 'blue', decoration: 'underline' },
strike: { decoration: 'lineThrough' },
p: { margin: [0, 5, 0, 10] },
ul: { marginBottom: 5, marginLeft: 5 },
table: { marginBottom: 5 },
th: { bold: true, fillColor: '#EEEEEE' }
};Usage Examples:
// Override default styles
const options = {
window,
defaultStyles: {
h1: { fontSize: 28, bold: true, marginBottom: 8, color: 'darkblue' },
p: { margin: [0, 6, 0, 12], lineHeight: 1.2 },
a: { color: 'purple', decoration: null } // Remove underline from links
}
};
// Enable automatic table sizing
const tableOptions = {
window,
tableAutoSize: true
};
// Handle images by reference (browser only)
const imageOptions = {
imagesByReference: true
};
const result = htmlToPdfmake('<table><tr><td width="200">Cell</td></tr></table>', tableOptions);
// Custom text replacement
const textOptions = {
window,
replaceText: function(text, parents) {
// Replace soft hyphens with non-breaking hyphens for better PDF rendering
return text.replace(/-/g, "\\u2011");
}
};
const htmlWithHyphens = '<p>Some hy-phenated text that might break across lines</p>';
const resultWithReplacement = htmlToPdfmake(htmlWithHyphens, textOptions);Block Elements:
div, p: Basic block containersh1, h2, h3, h4, h5, h6: Headings with built-in stylingtable, thead, tbody, tfoot, tr, th, td: Full table support with rowspan/colspanul, ol, li: Lists with nesting support and custom stylingpre: Preformatted text with whitespace preservationhr: Horizontal rules with customizable styling via data-pdfmakeInline Elements:
span: Generic inline containerstrong, b: Bold text formattingem, i: Italic text formattingu: Underlined texts, del, strike: Strikethrough texta: Links (external URLs and internal anchors with # prefix)sub, sup: Subscript and superscript with offset stylingimg: Images with src or data-src attributessvg: SVG elements (preserved as raw SVG)br: Line breaksfont: Legacy font tag with size and color attribute supportSpecial Elements:
customTag functiondiv[data-pdfmake-type="columns"]: Creates PDFMake columns layoutdata-pdfmake attributes for custom PDFMake propertiesTypography:
font-family: First font in comma-separated listfont-size: Including keyword sizes (xx-small to xxx-large)font-weight: Bold support (bold keyword or numeric >= 700)font-style: Italic supportline-height: Line height with percentage and unit supportcolor: Full color support (hex, rgb, rgba, hsl, hsla, named colors)text-align: Text alignment (left, center, right, justify)text-decoration: underline, lineThrough, overlinetext-indent: Leading indent with unit conversionwhite-space: nowrap, pre variants, break-spacesLayout:
margin: Full margin support with shorthand and individual propertieswidth, height: For tables, images, and table cellsbackground-color: Background colors with opacity supportborder: Complete border support (width, style, color, individual sides)Table-Specific:
rowspan, colspan: Table cell spanning attributesfillColor, fillOpacity: Table cell backgroundsdata-pdfmake: Add custom PDFMake properties via JSON data attribute.
<!-- Table layout -->
<table data-pdfmake='{"layout":"noBorders"}'>
<tr><td>No border table</td></tr>
</table>
<!-- Custom HR styling -->
<hr data-pdfmake='{"width":400,"thickness":2,"color":"red"}'>
<!-- Custom element properties -->
<div data-pdfmake='{"pageBreak":"before","margin":[0,10,0,10]}'>
Content with page break
</div>data-pdfmake-type: Special element type handling.
<!-- Create PDFMake columns layout -->
<div data-pdfmake-type="columns">
<div>Column 1</div>
<div>Column 2</div>
<div>Column 3</div>
</div>Custom Tag Handling:
const options = {
window,
customTag: function({ element, parents, ret }) {
if (element.nodeName === 'HIGHLIGHT') {
ret.background = 'yellow';
ret.color = 'black';
} else if (element.nodeName === 'CALLOUT') {
ret.margin = [10, 5, 10, 5];
ret.fillColor = '#f0f0f0';
ret.border = [true, true, true, true];
}
return ret;
}
};
const html = '<p>Normal text <highlight>highlighted text</highlight> more text</p>';
const result = htmlToPdfmake(html, options);Image Handling by Reference:
// Browser environment only
const html = '<img src="https://example.com/image.jpg" width="200">';
const result = htmlToPdfmake(html, { imagesByReference: true });
// Result structure:
// {
// content: [{ image: 'img_ref_abc123', width: 200, style: ['html-img'] }],
// images: { 'img_ref_abc123': 'https://example.com/image.jpg' }
// }
// Use with PDFMake
pdfMake.createPdf(result).download();Complex Table with Auto-sizing:
const tableHtml = `
<table style="width:100%">
<colgroup>
<col width="30%">
<col width="70%">
</colgroup>
<tr style="height:50px">
<td style="width:200px;background-color:#eee">Header 1</td>
<td>Header 2</td>
</tr>
<tr>
<td rowspan="2" style="height:100px">Spanning cell</td>
<td>Regular cell</td>
</tr>
<tr>
<td>Another cell</td>
</tr>
</table>
`;
const result = htmlToPdfmake(tableHtml, {
window,
tableAutoSize: true
});// Return type when imagesByReference is false (default)
interface PDFMakeDocumentDefinition {
text?: string | PDFMakeElement[];
stack?: PDFMakeElement[];
table?: {
body: PDFMakeElement[][];
widths?: (number | string)[];
heights?: (number | string)[];
};
ul?: PDFMakeElement[];
ol?: PDFMakeElement[];
image?: string;
svg?: string;
canvas?: CanvasElement[];
// ... other PDFMake properties
}
// Return type when imagesByReference is true
interface PDFMakeWithImages {
content: PDFMakeDocumentDefinition;
images: {
[key: string]: string;
};
}
interface PDFMakeElement {
text?: string | PDFMakeElement[];
style?: string[];
bold?: boolean;
italics?: boolean;
decoration?: string[];
color?: string;
background?: string;
fontSize?: number;
font?: string;
alignment?: string;
margin?: number[];
border?: boolean[];
borderColor?: string[];
fillColor?: string;
fillOpacity?: number;
opacity?: number;
lineHeight?: number;
leadingIndent?: number;
noWrap?: boolean;
preserveLeadingSpaces?: boolean;
width?: number | string;
height?: number | string;
colSpan?: number;
rowSpan?: number;
link?: string;
linkToDestination?: string;
nodeName?: string;
id?: string;
[key: string]: any; // Custom data-pdfmake properties
}
interface CanvasElement {
type: string;
x1: number;
y1: number;
x2: number;
y2: number;
lineWidth: number;
lineColor: string;
}