npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@encryptioner/html-to-pdf-generator

v1.0.3

Published

Modern multi-page PDF generator from HTML content with smart pagination and styling support

Downloads

515

Readme

HTML to PDF Generator

A modern, framework-agnostic library for converting HTML content to professional multi-page PDFs with smart pagination and rich features.

npm version License: MIT

📦 NPM Package: https://www.npmjs.com/package/@encryptioner/html-to-pdf-generator


📚 Documentation

Complete documentation is available in the documentation folder:

Framework Guides

Feature Documentation


✨ Features

Core Features

  • 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

Advanced Features

  • 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

📦 Installation

npm install @encryptioner/html-to-pdf-generator
pnpm add @encryptioner/html-to-pdf-generator
yarn add @encryptioner/html-to-pdf-generator

🚀 Quick Start

Vanilla JavaScript/TypeScript

import { 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'
  }
});

From HTML String

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'
  }
});

React

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>
  );
}

Vue 3

<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>

Svelte

<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>

🔧 Advanced Usage

Watermarks

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
  }
});

Headers & Footers

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

PDF Security

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

PDF Preview

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

Batch Generation

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`);

Using the PDFGenerator Class

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);

🖥️ MCP Server (Model Context Protocol)

The package includes an MCP server for server-side PDF generation, enabling Claude Desktop and other MCP clients to generate PDFs.

Quick Setup for Claude Desktop

  1. Build the package:

    pnpm install && pnpm run build
  2. Add to Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json on macOS):

    {
      "mcpServers": {
        "html-to-pdf": {
          "command": "node",
          "args": ["/absolute/path/to/html-to-pdf-generator/mcp/dist/index.js"]
        }
      }
    }
  3. 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]

MCP Tools Available

  • generate_pdf - Generate PDF from HTML with full feature support
  • generate_batch_pdf - Combine multiple HTML sections into one PDF
  • generate_pdf_from_url - Convert web pages to PDF (CORS-aware)

📖 Full MCP Documentation: See mcp/README.md for complete setup, API reference, and examples.


📖 API Options

PDFGeneratorOptions

| 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


🔍 Browser Compatibility

  • ✅ Chrome/Edge 90+
  • ✅ Firefox 88+
  • ✅ Safari 14+
  • ✅ Modern mobile browsers

Note: Requires browser support for html2canvas and jsPDF.


🤝 Contributing

We welcome contributions! Please see our Contributing Guide for details.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

📝 License

MIT License - see LICENSE.md for details.


🐛 Issues & Support


🙏 Acknowledgments

Built with:


📊 Package Stats

  • 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