A modern, framework-agnostic library for converting HTML content to professional multi-page PDFs with smart pagination and rich features.
π¦ NPM Package: https://www.npmjs.com/package/@encryptioner/html-to-pdf-generator
Complete documentation is available in the documentation folder:
- π Full Documentation Index - Complete guide and API reference
- π Quick Start Guide - Get started in 5 minutes
- βοΈ Installation Guide - Detailed installation instructions
- π¨ API Reference - All options and configurations
- Multi-Page Generation
- Image Handling
- Table Support
- Page Breaks
- Color Management
- Watermarks
- Headers & Footers
- Metadata
- Security & Encryption
- PDF Preview
- Batch Generation
- β Multi-page support with smart pagination
- β Framework adapters for React, Vue, Svelte, and vanilla JS
- β OKLCH color support with automatic Tailwind CSS compatibility
- β Image optimization with SVG conversion and DPI control
- β Table pagination with automatic header repetition
- β Smart page breaks with orphan prevention
- β HTML string support for generating PDFs from HTML markup
- β TypeScript support with full type definitions
- β Progress tracking with real-time callbacks
- β Watermarks - Add text or image watermarks with opacity control
- β Headers/Footers - Dynamic templates with variables ({{pageNumber}}, {{totalPages}}, {{date}}, {{title}})
- β PDF Metadata - Set title, author, subject, keywords, and creation date
- β PDF Security - Password protection and permission controls (printing, copying, modifying)
- β PDF Preview - Real-time PDF preview with live updates and debouncing
- β Batch generation - Combine multiple HTML sections into one PDF
- β Media type emulation - Apply @media print styles automatically
- β External CSS - Automatic loading and processing of stylesheets
- β Background images - Proper handling of CSS background images
- β Custom CSS injection - Add custom styles before rendering
npm install @encryptioner/html-to-pdf-generatorpnpm add @encryptioner/html-to-pdf-generatoryarn add @encryptioner/html-to-pdf-generatorimport { generatePDF } from '@encryptioner/html-to-pdf-generator';
const element = document.getElementById('my-content');
await generatePDF(element, 'my-document.pdf', {
format: 'a4',
orientation: 'portrait',
margins: [10, 10, 10, 10], // [top, right, bottom, left] in mm
showPageNumbers: true,
watermark: {
text: 'CONFIDENTIAL',
opacity: 0.1,
position: 'diagonal'
}
});import { generatePDFFromHTML } from '@encryptioner/html-to-pdf-generator';
const html = `
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: Arial, sans-serif; }
.header { color: #333; font-size: 24px; }
</style>
</head>
<body>
<h1 class="header">My Document</h1>
<p>This is a paragraph with some content.</p>
</body>
</html>
`;
await generatePDFFromHTML(html, 'document.pdf', {
format: 'a4',
metadata: {
title: 'My Document',
author: 'John Doe'
}
});import { usePDFGenerator } from '@encryptioner/html-to-pdf-generator/react';
function MyComponent() {
const { targetRef, generatePDF, isGenerating, progress } = usePDFGenerator({
filename: 'my-document.pdf',
format: 'a4',
showPageNumbers: true,
});
return (
<div>
<div ref={targetRef}>
<h1>Content to convert to PDF</h1>
<p>This will be in your PDF document</p>
</div>
<button onClick={generatePDF} disabled={isGenerating}>
{isGenerating ? `Generating... ${progress}%` : 'Download PDF'}
</button>
</div>
);
}<script setup>
import { usePDFGenerator } from '@encryptioner/html-to-pdf-generator/vue';
const { targetRef, generatePDF, isGenerating, progress } = usePDFGenerator({
filename: 'my-document.pdf',
format: 'a4',
showPageNumbers: true,
});
</script>
<template>
<div>
<div ref="targetRef">
<h1>Content to convert to PDF</h1>
<p>This will be in your PDF document</p>
</div>
<button @click="generatePDF" :disabled="isGenerating">
{{ isGenerating ? `Generating... ${progress}%` : 'Download PDF' }}
</button>
</div>
</template><script>
import { createPDFGenerator } from '@encryptioner/html-to-pdf-generator/svelte';
let targetElement;
const { generatePDF, isGenerating, progress } = createPDFGenerator({
filename: 'my-document.pdf',
format: 'a4',
showPageNumbers: true,
});
const handleDownload = () => {
if (targetElement) {
generatePDF(targetElement);
}
};
</script>
<div bind:this={targetElement}>
<h1>Content to convert to PDF</h1>
<p>This will be in your PDF document</p>
</div>
<button on:click={handleDownload} disabled={$isGenerating}>
{$isGenerating ? `Generating... ${$progress}%` : 'Download PDF'}
</button>await generatePDF(element, 'document.pdf', {
watermark: {
text: 'CONFIDENTIAL',
opacity: 0.1,
position: 'diagonal', // 'center' | 'diagonal' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'
fontSize: 48,
color: '#999999',
rotation: 45
}
});await generatePDF(element, 'document.pdf', {
metadata: {
title: 'Annual Report 2024'
},
headerTemplate: {
template: '<div style="text-align: center;">{{title}} - {{date}}</div>',
height: 15,
css: 'font-size: 11px; border-bottom: 1px solid #ccc;'
},
footerTemplate: {
template: '<div style="text-align: center;">Page {{pageNumber}} of {{totalPages}}</div>',
height: 12
}
});Available template variables:
{{pageNumber}}- Current page number{{totalPages}}- Total number of pages{{date}}- Current date{{title}}- Document title from metadata
Password protect your PDFs and control permissions:
await generatePDF(element, 'secure.pdf', {
securityOptions: {
enabled: true,
userPassword: 'secret123', // Password to open PDF
ownerPassword: 'admin456', // Password to change permissions
permissions: {
printing: 'highResolution', // 'none' | 'lowResolution' | 'highResolution'
modifying: false, // Disable modifications
copying: false, // Disable text copying
annotating: false, // Disable annotations
fillingForms: false // Disable form filling
}
}
});Note: jsPDF uses RC4 40-bit encryption, which provides basic protection but is not suitable for highly sensitive documents. For stronger encryption, consider server-side solutions.
Full security documentation: documentation/advanced/security.md
Display a real-time preview of your PDF with automatic updates as content changes:
import { PDFGenerator } from '@encryptioner/html-to-pdf-generator';
const generator = new PDFGenerator({
format: 'a4',
previewOptions: {
containerId: 'pdf-preview', // ID of container element (required)
liveUpdate: true, // Auto-update when content changes
debounce: 500, // Wait 500ms after changes before updating
scale: 1, // Lower scale for faster preview
quality: 0.7 // Lower quality for faster preview
}
});
// Start preview
const contentElement = document.getElementById('content');
await generator.startPreview(contentElement);
// Preview automatically updates as content changes
// Manually update if needed: await generator.updatePreview();
// Stop preview and download final high-quality PDF
generator.stopPreview();
await generator.generatePDF(contentElement, 'final.pdf');HTML Structure:
<div id="content">
<!-- Your content to preview -->
</div>
<div id="pdf-preview" style="width: 100%; height: 600px; border: 1px solid #ccc;"></div>Full preview documentation: documentation/advanced/preview.md
import { generateBatchPDF } from '@encryptioner/html-to-pdf-generator';
const items = [
{
content: document.getElementById('section-1'),
pageCount: 2,
title: 'Introduction',
newPage: true // Start on a new page
},
{
content: document.getElementById('section-2'),
pageCount: 3,
title: 'Content',
newPage: true
}
];
const result = await generateBatchPDF(items, 'combined.pdf', {
showPageNumbers: true
});
console.log(`Generated ${result.totalPages} pages`);import { PDFGenerator } from '@encryptioner/html-to-pdf-generator';
const generator = new PDFGenerator({
format: 'a4',
orientation: 'portrait',
margins: [15, 15, 15, 15],
showPageNumbers: true,
pageNumberPosition: 'footer',
compress: true,
onProgress: (progress) => {
console.log(`Generating PDF: ${progress}%`);
},
onComplete: (blob) => {
console.log(`PDF generated! Size: ${blob.size} bytes`);
},
onError: (error) => {
console.error('PDF generation failed:', error);
},
});
// Generate PDF
await generator.generatePDF(element, 'document.pdf');
// Or get blob without downloading
const blob = await generator.generateBlob(element);The package includes an MCP server for server-side PDF generation, enabling Claude Desktop and other MCP clients to generate PDFs.
-
Build the package:
pnpm install && pnpm run build -
Add to Claude Desktop config (
~/Library/Application Support/Claude/claude_desktop_config.jsonon macOS):{ "mcpServers": { "html-to-pdf": { "command": "node", "args": ["/absolute/path/to/html-to-pdf-generator/mcp/dist/index.js"] } } } -
Restart Claude Desktop and use PDF generation in your conversations:
You: Generate a PDF invoice with these items and save to /tmp/invoice.pdf Claude: [Uses generate_pdf tool to create PDF]
generate_pdf- Generate PDF from HTML with full feature supportgenerate_batch_pdf- Combine multiple HTML sections into one PDFgenerate_pdf_from_url- Convert web pages to PDF (CORS-aware)
π Full MCP Documentation: See mcp/README.md for complete setup, API reference, and examples.
| Option | Type | Default | Description |
|---|---|---|---|
format |
'a4' | 'letter' | 'a3' | 'legal' |
'a4' |
Paper format |
orientation |
'portrait' | 'landscape' |
'portrait' |
Page orientation |
margins |
[number, number, number, number] |
[10, 10, 10, 10] |
Margins [top, right, bottom, left] in mm |
compress |
boolean |
true |
Enable PDF compression |
scale |
number |
2 |
HTML2Canvas scale factor (1-4) |
imageQuality |
number |
0.85 |
JPEG quality (0-1) |
showPageNumbers |
boolean |
false |
Show page numbers |
pageNumberPosition |
'header' | 'footer' |
'footer' |
Page number position |
customCSS |
string |
'' |
Custom CSS to inject |
watermark |
WatermarkOptions |
undefined |
Watermark configuration |
headerTemplate |
HeaderFooterTemplate |
undefined |
Header template |
footerTemplate |
HeaderFooterTemplate |
undefined |
Footer template |
metadata |
PDFMetadata |
undefined |
PDF metadata |
securityOptions |
PDFSecurityOptions |
undefined |
Security & encryption settings |
emulateMediaType |
'screen' | 'print' |
'screen' |
Media type to emulate |
onProgress |
(progress: number) => void |
- | Progress callback (0-100) |
onComplete |
(blob: Blob) => void |
- | Completion callback |
onError |
(error: Error) => void |
- | Error callback |
Full API documentation: documentation/api/options.md
- β Chrome/Edge 90+
- β Firefox 88+
- β Safari 14+
- β Modern mobile browsers
Note: Requires browser support for html2canvas and jsPDF.
We welcome contributions! Please see our Contributing Guide for details.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
MIT License - see LICENSE.md for details.
- Issues: GitHub Issues
- Email: mir.ankur.ruet13@gmail.com
Built with:
- jsPDF - PDF generation
- html2canvas-pro - HTML to canvas rendering
- pdf-lib - PDF merging
- Bundle Size: ~400KB (minified)
- Dependencies: 3 core dependencies
- TypeScript: Full type definitions included
- Tree-shakeable: ESM and CJS builds
- Framework Support: React, Vue, Svelte, Vanilla JS
- Server-Side: Node.js with Puppeteer
Ready to get started? β Quick Start Guide