API

Full README Reference

Full README Reference

This page mirrors the maintained package README so no public option or guidance is hidden from the documentation site.

A Vue + TypeScript HTML-to-PDF component and composable for browser applications.

vue-pdf-export supports two rendering modes:

  • Canvas mode - maximum HTML/CSS visual fidelity through html2pdf.js + html2canvas + jsPDF.
  • Selectable text mode - browser-side vector PDF rendering with real selectable/searchable/copyable text, clickable PDF links, password protection, metadata, compression, page-aware headers/footers, and watermarks.

It also includes manual and automatic pagination, preview, download, print, safe filename normalization, progress stages,custom loaders, current-page progress, cancellation, page targeting, PDF permissions, large-document optimizations, and advanced renderer configuration.

Default package behavior remains renderMode="canvas" for backwards compatibility. The live playground may choose a different default for demonstration purposes.

Highlights

  • Browser-side PDF generation with no package-managed upload service
  • Canvas and selectable-text rendering
  • Incremental page-by-page Canvas rendering when page-break markers are present
  • Cooperative cancellation for long-running exports
  • Page-aware progress with currentPage / totalPages
  • Repeated-image caching in selectable-text rendering
  • Temporary DOM/canvas cleanup between expensive rendering steps
  • Password protection, owner password, PDF permission flags, metadata, and compression
  • Headers, footers, logos, watermarks, page targeting, and clickable links
  • Stress/regression coverage for 10 / 25 / 50 / 100-page documents

Documentation

Live Demo

Try the interactive playground:

vue-pdf-export-playground.vercel.app

The playground demonstrates:

  • Canvas and selectable-text rendering modes
  • Real selectable/searchable text in selectable mode
  • Clickable PDF hyperlinks
  • PDF preview
  • Download
  • Print
  • Manual pagination
  • Automatic height-based pagination
  • Page-break protection helpers
  • Headers and footers
  • Plain-text and trusted HTML header/footer content
  • Optional header/footer logos
  • Custom logo sizing with preserved aspect ratio
  • Header page targeting
  • Page-aware selective header spacing
  • Footer page numbering with Page {n} of {total}
  • Selectable header/footer text in selectable mode
  • Text and image watermarks
  • Background and foreground watermarks
  • Per-page watermark targeting
  • Password-protected PDFs
  • User/open and owner passwords
  • Combined password parts
  • PDF permissions
  • PDF metadata
  • PDF stream compression
  • Numeric progress
  • Named progress stages
  • Custom loaders
  • Advanced html2pdf.js, html2canvas, and jsPDF options

Features

Core PDF workflow

  • Vue component API
  • Vue composable API
  • TypeScript declarations
  • Browser-side PDF generation
  • Two rendering modes: canvas and text
  • PDF Blob output
  • PDF preview modal
  • Browser download
  • Programmatic print
  • Blob URL cleanup
  • Safe filename normalization

Rendering modes

  • canvas - existing html2canvas/html2pdf pipeline for strongest browser CSS fidelity
  • text - vector/browser-layout renderer with selectable/searchable PDF text
  • Default mode is canvas
  • Same public <Html2Pdf> API for both modes
  • Same Blob/preview/download/print flow for both modes
  • Shared header/footer/watermark/metadata post-processing
  • Password protection available in both modes
  • Clickable links available when PDF links are enabled

Pagination and layout

  • Manual pagination
  • Automatic height-based pagination
  • Existing .html2pdf__page-break marker works with both render modes
  • Page-break protection helpers
  • Custom pagebreak.avoid selectors
  • Automatic page-break reset
  • Manual breaks preserved when automatic breaks are reset
  • Page-aware automatic pagination for selectively targeted headers
  • Deterministic export-width support

Headers

  • Header on all pages by default when enabled
  • Header targeting:
    • all
    • first
    • last
    • except-first
    • explicit page arrays
  • Page-aware header spacing
  • Plain-text header content
  • Trusted HTML header content
  • Optional logo
  • Logo URL or data URL
  • Custom logo width and height
  • Aspect-ratio-safe logo rendering
  • Header background color
  • Header text color
  • Selectable header text in selectable-text mode

Footers

  • Footer on every page when enabled
  • HTML footer mode
  • Text footer mode
  • Trusted HTML footer content
  • Built-in page numbering
  • Optional logo
  • Logo URL or data URL
  • Custom logo width and height
  • Aspect-ratio-safe logo rendering
  • Footer background color
  • Footer text color
  • Legacy footer compatibility
  • Selectable footer text and page-number text in selectable-text mode

Security and document options

  • User/open password
  • Owner password
  • Password parts
  • Configurable PDF permissions
  • Password protection in both render modes
  • PDF metadata
  • PDF stream compression

Watermarks

  • Text watermarks
  • Image watermarks
  • Background layer
  • Foreground layer
  • Single mode
  • Repeated/tiled mode
  • Per-page targeting
  • Opacity
  • Rotation
  • Position
  • Sizing
  • Horizontal/vertical spacing
  • Real PDF link annotations
  • <a href="..."> support
  • Clickable links in generated PDFs when links are enabled
  • Link rectangles follow pagination in selectable-text mode
  • Link text remains selectable in selectable-text mode

Developer experience

  • Built-in loader
  • Custom loader slot
  • Numeric progress event
  • Named progress stages
  • CORS-aware image handling
  • Advanced html2pdf configuration
  • Filename sanitization
  • Browser E2E coverage with Chromium, Firefox, and WebKit

Installation

npm install vue-pdf-export

Runtime PDF dependencies are installed automatically.

Import

TypeScript:

import {
  Html2Pdf,
  type PdfMetadataOptions,
  type PdfProgressState,
  type PdfRenderMode,
  type PdfSecurityOptions,
  type WatermarkOptions,
} from 'vue-pdf-export'

import 'vue-pdf-export/style.css'

JavaScript:

import { Html2Pdf } from 'vue-pdf-export'
import 'vue-pdf-export/style.css'

Quick Start

<script setup lang="ts">
import { ref } from 'vue'
import { Html2Pdf } from 'vue-pdf-export'
import 'vue-pdf-export/style.css'

const pdfRef = ref<InstanceType<typeof Html2Pdf> | null>(null)

async function generatePdf() {
  const blob = await pdfRef.value?.generatePdf()
  console.log(blob)
}
</script>

<template>
  <button type="button" @click="generatePdf">Generate PDF</button>

  <Html2Pdf
    ref="pdfRef"
    filename="my-report"
    render-mode="canvas"
    :manual-pagination="true"
    :enable-download="true"
  >
    <template #pdf-content>
      <div>
        <h1>My Report</h1>
        <p>This content will be rendered into the PDF.</p>
      </div>
    </template>
  </Html2Pdf>
</template>

Rendering Modes

Canvas mode

Canvas mode is the default and uses the package's existing html2pdf.js / html2canvas / jsPDF pipeline.

<Html2Pdf render-mode="canvas" />

Use it when the highest possible browser CSS fidelity is more important than selectable body text.

Best for:

  • complex CSS
  • gradients
  • shadows
  • transforms
  • custom web fonts
  • visual dashboards
  • designs where browser appearance is the priority

Body content is rasterized, so normal body text is not selectable/searchable.

Incremental Canvas rendering

When the export DOM contains .html2pdf__page-break markers, Canvas mode uses an incremental page-by-page renderer instead of capturing the entire document as one giant canvas.

This path:

  • clones and renders one logical PDF page at a time
  • keeps raster dimensions page-bounded
  • releases temporary page DOM after html2canvas finishes reading it
  • releases canvas backing stores after insertion into jsPDF
  • reports page-level progress
  • yields to the browser between expensive steps
  • supports cooperative cancellation before the next page begins

Canvas documents without page-break markers keep the legacy html2pdf.js worker for backwards compatibility.

Selectable text mode

<Html2Pdf render-mode="text" />

Selectable text mode converts the live browser layout into PDF vector/text operations instead of turning the entire document into a screenshot.

It supports:

  • selectable body text
  • searchable body text
  • copyable body text
  • selectable header/footer text
  • selectable footer page numbers
  • clickable PDF hyperlinks
  • images
  • backgrounds
  • borders
  • basic border radius
  • text color, weight, italic, decoration, alignment, and spacing
  • multi-page output
  • manual page-break markers
  • PDF password protection
  • PDF permissions
  • metadata
  • compression
  • headers, footers, and watermarks

Example:

<Html2Pdf render-mode="text" :security="security" :metadata="metadata" :compress="true">

  <template #pdf-content>
    <main>
      <h1>Selectable report</h1>
      <p>You can select and search this text in the generated PDF.</p>

      <a href="https://www.npmjs.com/package/vue-pdf-export">
        Open vue-pdf-export on npm
      </a>
    </main>
  </template>
</Html2Pdf>

Selectable-text mode intentionally favors real PDF text over pixel-perfect parity with every browser CSS feature. See Selectable Text Mode Notes.

Component Registration

With <script setup>:

<script setup lang="ts">
import { Html2Pdf } from 'vue-pdf-export'
import 'vue-pdf-export/style.css'
</script>

No components registration is required.

Options API

<script lang="ts">
import { defineComponent } from 'vue'
import { Html2Pdf } from 'vue-pdf-export'
import 'vue-pdf-export/style.css'

export default defineComponent({
  components: {
    Html2Pdf,
  },
})
</script>

Global registration

import { createApp } from 'vue'
import App from './App.vue'
import { Html2Pdf } from 'vue-pdf-export'
import 'vue-pdf-export/style.css'

const app = createApp(App)

app.component('Html2Pdf', Html2Pdf)
app.mount('#app')

Preview & Download

Preview only:

<Html2Pdf :enable-download="false" :preview-modal="true" />

Download only:

<Html2Pdf :enable-download="true" :preview-modal="false" />

Download and preview:

<Html2Pdf :enable-download="true" :preview-modal="true" />

enableDownload and previewModal are independent.

Pagination

Manual pagination

<Html2Pdf :manual-pagination="true">
  <template #pdf-content>
    <section>Page one</section>

    <div class="html2pdf__page-break"></div>

    <section>Page two</section>
  </template>
</Html2Pdf>

Recommended helper CSS:

.html2pdf__page-break {
  display: block;
  height: 0;
  clear: both;
}

Do not add break-before or page-break-before to this helper while legacy page-break mode is active. Doing so can create duplicate breaks or blank pages.

The same .html2pdf__page-break marker is recognized by selectable-text mode, so consumers do not need a second pagination API.

Automatic pagination

<Html2Pdf :manual-pagination="false" :paginate-elements-by-height="1100">

  <template #pdf-content>
    <div>
      <section>Block 1</section>
      <section>Block 2</section>
      <section>Block 3</section>
    </div>
  </template>
</Html2Pdf>

The component measures direct child elements and inserts temporary automatic page-break markers when the configured height would be exceeded.

Prevent content from splitting

Default protected selectors:

.pdf-keep-together
.pdf-no-break
img

Example:

<div class="pdf-keep-together">
  <h2>Invoice Summary</h2>
  <p>Keep this block together.</p>
</div>

You can extend page-break avoidance:

<Html2Pdf
  :html-to-pdf-options="{
    pagebreak: {
      avoid: ['.custom-card'],
    },
  }"
/>

Your selectors are merged with package defaults.

No-break helpers are best-effort. A block that is taller than the usable PDF page area may still need to split.

Enable PDF links through htmlToPdfOptions.enableLinks:

const htmlToPdfOptions = {
  enableLinks: true,
}
<Html2Pdf :html-to-pdf-options="htmlToPdfOptions">
  <template #pdf-content>
    <a href="https://www.npmjs.com/package/vue-pdf-export">
      Open vue-pdf-export on npm
    </a>
  </template>
</Html2Pdf>

In selectable-text mode, anchors are converted into real PDF link annotations, so compatible PDF viewers can show the link cursor and open the URL when clicked.

For best selectable-text rendering, keep PDF link styling straightforward. Very large letter-spacing, transforms, or highly compressed fixed-width buttons can create visual differences because browser and PDF font metrics are not identical.

Recommended PDF-friendly link CSS:

.pdf-link {
  display: inline-flex;
  align-items: center;
  width: auto;
  max-width: 100%;
  padding: 8px 12px;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: 0;
  white-space: nowrap;
  text-decoration: underline;
}

Basic header

<Html2Pdf
  :inject-header="true"
  :header-height="58"
  header-text="My Company"
  :header-logo-enabled="true"
  header-logo-url="/logo.png"
  :header-logo-width="120"
  :header-logo-height="32"
  header-background-color="#F8F9FA"
  header-text-color="#5F6368"
/>

Header text

<Html2Pdf :inject-header="true" header-text="Quarterly Report" />

In selectable-text mode, plain header text is added as real PDF text and remains selectable/searchable.

Header HTML

Use headerHtml for trusted developer-controlled markup:

<Html2Pdf
  :inject-header="true"
  header-html="<strong>Quarterly <span style='color:#13B981'>Report</span></strong>"
/>

When headerHtml is non-empty, it takes precedence over headerText.

headerHtml is intentionally trusted HTML. Do not pass unsanitized user input.

Selectable-text mode may flatten complex header HTML to text where necessary so the text can remain selectable. Use canvas mode when exact rich-HTML header styling is more important than text selection.

Header logos are enabled by default.

<Html2Pdf :inject-header="true" :header-logo-enabled="false" header-text="Text-only header" />

The header itself remains enabled.

Header logo sizing

<Html2Pdf
  :inject-header="true"
  header-logo-url="/wide-logo.png"
  :header-logo-width="160"
  :header-logo-height="36"
/>

headerLogoWidth and headerLogoHeight define the maximum logo box. The original image aspect ratio is preserved.

Default logo box:

28 × 28 CSS pixels

Header page targeting

First page:

<Html2Pdf :inject-header="true" header-pages="first" />

Last page:

<Html2Pdf :inject-header="true" header-pages="last" />

Skip first:

<Html2Pdf :inject-header="true" header-pages="except-first" />

Explicit pages:

<Html2Pdf :inject-header="true" :header-pages="[1, 3, 5]" />

Supported type:

type PdfPageTarget = 'all' | 'first' | 'last' | 'except-first' | number[]

Page-aware header spacing

Selective headers reserve header space only on pages that actually receive the header.

header-pages="first"

Page 1 -> header + header space
Page 2 -> no header + no extra header space
Page 3 -> no header + no extra header space

Automatic pagination also accounts for this selective spacing.

Any top margin explicitly supplied through htmlToPdfOptions.margin remains independent and is not removed.

Header props

PropTypeDefaultDescription
injectHeaderbooleanfalseEnable header rendering.
headerHeightnumber58Header height in the current jsPDF unit.
headerTextstring''Plain-text header content.
headerHtmlstring''Trusted HTML header content; takes precedence over headerText.
headerLogoEnabledbooleantrueShow/hide the header logo.
headerLogoUrlstring''Logo URL.
headerLogoDataUrlstring''Logo data URL/base64.
headerLogoWidthnumber28Maximum logo width in CSS pixels.
headerLogoHeightnumber28Maximum logo height in CSS pixels.
headerBackgroundColorstring#F8F9FAHeader background.
headerTextColorstring#5F6368Header text/fallback color.
headerPagesPdfPageTargetall-page behaviorHeader page targeting.
<Html2Pdf
  :inject-footer="true"
  :footer-height="58"
  footer-mode="html"
  footer-text="My Company"
  footer-template="Page {n} of {total}"
/>

If injectFooter is false, the package does not reserve footer-specific bottom space. Any explicit bottom margin supplied through htmlToPdfOptions.margin remains.

<Html2Pdf
  :inject-footer="true"
  footer-mode="html"
  footer-html="<strong>My Company</strong>"
  footer-template="Page {n} of {total}"
/>

When footerHtml is non-empty in HTML mode, it takes precedence over footerText.

footerHtml is intentionally trusted HTML. Do not pass unsanitized user input.

<Html2Pdf
  :inject-footer="true"
  footer-mode="text"
  footer-text="My Company"
  footer-template="Page {n} of {total}"
/>

In selectable-text mode, footer text and the page-number template are emitted as selectable PDF text.

Footer logos are enabled by default.

<Html2Pdf
  :inject-footer="true"
  :footer-logo-enabled="false"
  footer-mode="text"
  footer-text="Text-only footer"
/>
<Html2Pdf
  :inject-footer="true"
  :footer-logo-enabled="true"
  footer-logo-url="/wide-logo.png"
  :footer-logo-width="150"
  :footer-logo-height="30"
/>

The logo keeps its original aspect ratio.

Default logo box:

26 × 26 CSS pixels

Supported placeholders:

{n}
{total}

Example:

Page {n} of {total}

Output:

Page 2 of 5

The footer template is the package's built-in page-numbering mechanism. There is no separate dedicated page-numbering API.

The old prop remains supported:

<Html2Pdf :use-footer-component="true" />

Prefer:

<Html2Pdf footer-mode="html" />

or:

<Html2Pdf footer-mode="text" />

When footerMode is explicitly provided, it takes priority over useFooterComponent.

PropTypeDefaultDescription
injectFooterbooleanfalseEnable footer rendering.
footerHeightnumber58Footer height in the current jsPDF unit.
footerMode`'html' \'text'`compatibility-resolved
footerTextstring''Plain-text footer content / HTML-mode fallback.
footerHtmlstring''Trusted HTML footer content.
footerTemplatestringPage {n} of {total}Page number/footer template.
footerLogoEnabledbooleantrueShow/hide footer logo.
footerLogoUrlstring''Logo URL.
footerLogoDataUrlstring''Logo data URL/base64.
footerLogoWidthnumber26Maximum logo width in CSS pixels.
footerLogoHeightnumber26Maximum logo height in CSS pixels.
footerBackgroundColorstring#F8F9FAFooter background.
footerTextColorstring#5F6368Footer text/fallback color.
useFooterComponentbooleantrueDeprecated compatibility option.

Security

Create password-protected PDFs with the security prop.

import type { PdfSecurityOptions } from 'vue-pdf-export'

const security: PdfSecurityOptions = {
  enabled: true,
  userPassword: 'open123',
  ownerPassword: 'owner456',
  permissions: ['print', 'copy'],
}
<Html2Pdf :security="security" />

Password protection works in both canvas and selectable-text render modes.

Permission flags

type PdfPermission = 'print' | 'modify' | 'copy' | 'annot-forms'
PermissionWhat it allows
printAllows printing when the PDF viewer enforces document permissions.
copyAllows text/content copying and extraction when the viewer enforces permissions.
modifyAllows document modification/editing when supported by the viewer.
annot-formsAllows annotations and form-related changes when supported by the viewer.

PDF permission enforcement depends on the PDF viewer. Password encryption is part of the PDF itself, while permission flags rely on viewer compliance.

Security guidance

The package can generate encrypted/password-protected PDFs, but PDF security should be treated as one layer of application security rather than a replacement for access control.

Important boundaries:

  • User/open password controls opening an encrypted PDF.
  • Owner password is used by the PDF encryption layer for owner-level access/permission configuration.
  • Permission flags are viewer-dependent. Some PDF viewers may not enforce them identically.
  • headerHtml and footerHtml are intentionally trusted developer HTML. Do not pass unsanitized user-controlled HTML.
  • Remote images are fetched by the browser. Use trusted origins, correct CORS headers, and avoid exposing secrets in image URLs.
  • Passwords exist in browser memory while a PDF is being generated. Do not hard-code sensitive production passwords into public frontend source.
  • Generated Blob URLs are cleaned up by the component/composable lifecycle, but applications should still avoid retaining generated Blobs longer than necessary.

vue-pdf-export is a client-side library and does not require a package-operated server to generate a PDF. Your application, remote assets, analytics, and surrounding infrastructure may still perform their own network requests.

Password parts

const security = {
  enabled: true,
  passwordParts: ['15081999', 4821],
  passwordSeparator: '-',
}

This creates one final open password:

15081999-4821

passwordParts do not create multiple independent passwords.

When security is omitted, compatible raw htmlToPdfOptions.jsPDF.encryption values are preserved.

When security.enabled is explicitly false, encryption is removed.

Metadata

import type { PdfMetadataOptions } from 'vue-pdf-export'

const metadata: PdfMetadataOptions = {
  title: 'Invoice #1024',
  author: 'Acme Inc.',
  subject: 'Customer invoice',
  keywords: ['invoice', '2026'],
  creator: 'vue-pdf-export',
}
<Html2Pdf :metadata="metadata" />

Metadata is written to PDF document properties and is not rendered as normal visible page content.

The direct metadata prop takes priority over htmlToPdfOptions.metadata.

Compression

<Html2Pdf :compress="true" />

compress controls jsPDF stream compression.

It does not lower html2canvas resolution or JPEG image quality.

If omitted, compatible raw htmlToPdfOptions.jsPDF.compress is preserved.

Watermarks

Text watermark

import type { WatermarkOptions } from 'vue-pdf-export'

const watermark: WatermarkOptions = {
  enabled: true,
  layer: 'background',
  type: 'text',
  mode: 'repeat',
  text: 'CONFIDENTIAL',
  opacity: 0.1,
  rotation: -35,
  fontSize: 36,
  gapX: 100,
  gapY: 90,
}
<Html2Pdf :watermark="watermark" />

Foreground watermark

const watermark = {
  enabled: true,
  layer: 'foreground',
  type: 'text',
  mode: 'single',
  text: 'DRAFT',
  opacity: 0.15,
  rotation: -30,
  fontSize: 60,
  x: 0.5,
  y: 0.5,
}

Foreground watermarks are drawn onto final PDF pages with jsPDF.

Image watermark

const watermark = {
  enabled: true,
  layer: 'foreground',
  type: 'image',
  mode: 'single',
  imageUrl: '/logo.png',
  opacity: 0.1,
  rotation: -25,
  width: 180,
  x: 0.5,
  y: 0.5,
}

A data URL can also be used:

const watermark = {
  enabled: true,
  type: 'image',
  imageDataUrl: 'data:image/png;base64,...',
}

imageDataUrl takes priority over imageUrl.

Per-page watermark targeting

const watermark = {
  enabled: true,
  type: 'text',
  text: 'INTERNAL',
  pages: 'except-first',
}

Explicit pages:

const watermark = {
  enabled: true,
  text: 'INTERNAL',
  pages: [1, 3, 5],
}

Supported targets:

all
first
last
except-first
number[]

For selective targeting, a requested background watermark may be applied during final PDF post-processing so selected-page behavior can be preserved.

Watermark options

OptionTypeDescription
enabledbooleanEnable/disable watermark.
type`'text' \'image'`
layer`'background' \'foreground'`
mode`'single' \'repeat'`
textstringText content.
fontSizenumberText size.
fontFamilystringFont family.
fontWeight`string \number`
fontStyle`'normal' \'bold' \
colorstringWatermark color.
imageUrlstringImage URL.
imageDataUrlstringData URL/base64 image.
widthnumberImage width.
heightnumberOptional image height.
opacitynumberClamped to 0..1.
rotationnumberRotation in degrees.
xnumberHorizontal position.
ynumberVertical position.
gapXnumberHorizontal repeat gap.
gapYnumberVertical repeat gap.
pagesPdfPageTargetTarget pages.

Loader & Progress

Built-in loader

<Html2Pdf :show-loader="true" loader-text="Generating PDF..." />

Disable it:

<Html2Pdf :show-loader="false" />

Numeric progress

<Html2Pdf @progress="onProgress" />
function onProgress(value: number) {
  console.log(value)
}

This is generation-stage progress, not byte-level network progress.

Rich progress stages

<Html2Pdf @progress-stage="onProgressStage" />
import type { PdfProgressState } from 'vue-pdf-export'

function onProgressStage(state: PdfProgressState) {
  console.log(state.stage, state.progress)
}

Current stages:


idle

pagination

images

preparing

rendering

watermark

header

footer

metadata

serializing

complete

error

Custom loader

<Html2Pdf>
  <template #loader="{ progress, loading, stage, progressState }">
    <div v-if="loading">
      {{ stage }} - {{ progress }}%
    </div>
  </template>
</Html2Pdf>

Slot values:

ValueType
progressnumber
loadingboolean
stagePdfProgressStage
progressStatePdfProgressState

Programmatic API

Component methods:

interface Html2PdfInstance {
  generatePdf: () => Promise<Blob>
  print: () => Promise<void>
  closePreview: () => void
  resetPagination: () => void
  cancelGeneration(): => void 
}

Recommended ref:

const pdfRef = ref<InstanceType<typeof Html2Pdf> | null>(null)

Generate

const blob = await pdfRef.value?.generatePdf()

Print

await pdfRef.value?.print()

Close preview

pdfRef.value?.closePreview()

Reset automatic pagination

pdfRef.value?.resetPagination()

This removes only automatically inserted page breaks.

Cancel active generation

pdfRef.value?.cancelGeneration()

cancelGeneration() requests cooperative cancellation of the current export.

  • Incremental Canvas rendering checks cancellation around page capture, encoding, insertion, and browser-yield points.
  • Selectable-text rendering checks cancellation while walking the DOM, materializing images, paginating, and rendering pages.
  • Synchronous browser/jsPDF work such as an already-running toDataURL() or final pdf.output('blob') call cannot be interrupted in the middle; cancellation takes effect at the next safe checkpoint.
  • Cancellation is treated as an expected abort flow and is not emitted as the component's normal error event.

Composable

import { useHtml2Pdf } from 'vue-pdf-export'

const {
  loading,
  progress,
  stage,
  progressState,
  error,
  pdfUrl,
  lastResult,
  generate,
  download,
  print,
  cleanup,
} = useHtml2Pdf()

Events

<Html2Pdf
  @progress="onProgress"
  @progress-stage="onProgressStage"
  @startPagination="onStartPagination"
  @hasPaginated="onPaginated"
  @beforeDownload="onBeforeDownload"
  @hasDownloaded="onDownloaded"
  @closed="onClosed"
  @error="onError"
/>
EventPayloadDescription
progressnumberNumeric generation progress.
progressStage / @progress-stagePdfProgressStateNamed stage and progress.
startPaginationnonePagination started.
hasPaginatednonePagination completed.
beforeDownloadBeforeDownloadPayloadEmitted before generation.
hasDownloadedBlobGenerated Blob is available.
closednonePreview/generation flow closed.
errorErrorGeneration or print error.

Slots

SlotRequiredDescription
pdf-contentyesHTML converted to PDF.
loadernoCustom loader with { progress, loading, stage, progressState }.

Core Props

PropTypeDefaultDescription
renderMode`'canvas' \'text'`'canvas'
showLayoutbooleanfalseShow export layout.
floatLayoutbooleanfalseUse fixed/floating export layout.
enableDownloadbooleantrueDownload after generation.
previewModalbooleanfalseShow PDF preview modal.
filenamestringtimestamp fallbackPDF filename.
pdfQualitynumber2Default html2canvas scale; mainly relevant to canvas mode/images.
pdfFormatPDF format'a4'PDF format.
pdfOrientation`'portrait' \'landscape'`'portrait'
pdfContentWidthstring'800px'Export wrapper width.
htmlToPdfOptionsHtml2PdfOptionspackage defaultsAdvanced options.
metadataPdfMetadataOptionsundefinedPDF metadata.
compressbooleanundefinedjsPDF stream compression override.
securityPdfSecurityOptionsundefinedPassword/security configuration.
manualPaginationbooleanfalseManual pagination mode.
paginateElementsByHeightnumberrequired for auto modeAutomatic page height.
showLoaderbooleantrueShow loader.
loaderTextstring'Generating PDF...'Loader text.
watermarkWatermarkOptionsdisabledWatermark configuration.

Header and footer props are documented in their dedicated sections.

Advanced html2pdf Options

const htmlToPdfOptions = {
  margin: [0, 0, 0, 0],
  enableLinks: true,

  pagebreak: {
    mode: ['css', 'legacy'],
  },

  image: {
    type: 'jpeg',
    quality: 1,
  },

  html2canvas: {
    scale: 3,
    useCORS: true,
    backgroundColor: '#FFFFFF',
  },

  jsPDF: {
    unit: 'px',
    format: 'a4',
    orientation: 'p',
    hotfixes: ['px_scaling'],
    optimizeForBrowser: true,
  },
}
<Html2Pdf :html-to-pdf-options="htmlToPdfOptions" />

Important precedence rules:

  • metadata overrides raw htmlToPdfOptions.metadata when provided.
  • compress overrides raw htmlToPdfOptions.jsPDF.compress when provided.
  • security.enabled: true overrides raw jsPDF encryption.
  • security.enabled: false removes raw encryption.
  • Non-empty headerHtml takes precedence over headerText.
  • In HTML footer mode, non-empty footerHtml takes precedence over footerText.
  • headerLogoEnabled controls only header logo visibility.
  • footerLogoEnabled controls only footer logo visibility.
  • Explicit user margins remain even when header/footer rendering is disabled.
  • enableLinks: true enables generated PDF link annotations.

Filename Normalization

import { normalizePdfFilename } from 'vue-pdf-export'

normalizePdfFilename('invoice:/customer?2026')
// invoice--customer-2026.pdf

Normalization:

  • adds exactly one .pdf extension
  • prevents duplicate .pdf
  • sanitizes unsafe filename/path characters
  • trims trailing dots and spaces
  • falls back to a timestamp for empty names
  • protects Windows reserved device names such as CON and LPT1
  • preserves Unicode
  • limits excessively long base names

Examples:

normalizePdfFilename('report')
// report.pdf

normalizePdfFilename('report.PDF')
// report.pdf

normalizePdfFilename('CON')
// _CON.pdf

normalizePdfFilename(' ग्राहक रिपोर्ट ')
// ग्राहक रिपोर्ट.pdf

Full Example

<script setup lang="ts">
import { ref } from 'vue'

import {
  Html2Pdf,
  type PdfMetadataOptions,
  type PdfProgressState,
  type PdfSecurityOptions,
  type WatermarkOptions,
} from 'vue-pdf-export'

import 'vue-pdf-export/style.css'

const pdfRef = ref<InstanceType<typeof Html2Pdf> | null>(null)

const security: PdfSecurityOptions = {
  enabled: true,
  userPassword: 'customer-1024',
  ownerPassword: 'owner-1024',
  permissions: ['print', 'copy'],
}

const metadata: PdfMetadataOptions = {
  title: 'Invoice #1024',
  author: 'Acme Inc.',
  subject: 'Customer invoice',
  keywords: ['invoice', 'customer'],
  creator: 'vue-pdf-export',
}

const watermark: WatermarkOptions = {
  enabled: true,
  type: 'text',
  layer: 'foreground',
  mode: 'repeat',
  text: 'CONFIDENTIAL',
  opacity: 0.08,
  rotation: -30,
  pages: 'except-first',
}

const htmlToPdfOptions = {
  enableLinks: true,
}

function onProgressStage(state: PdfProgressState) {
  console.log(state.stage, state.progress)
}

async function generatePdf() {
  await pdfRef.value?.generatePdf()
}
</script>

<template>
  <button type="button" @click="generatePdf">Generate PDF</button>

  <Html2Pdf
    ref="pdfRef"
    render-mode="text"
    filename="invoice-1024"
    :enable-download="true"
    :preview-modal="true"
    :manual-pagination="true"
    :inject-header="true"
    header-text="Acme Inc."
    :header-logo-enabled="true"
    header-logo-url="/logo.png"
    :header-logo-width="120"
    :header-logo-height="30"
    header-pages="first"
    :inject-footer="true"
    footer-mode="text"
    footer-text="Acme Inc."
    footer-template="Page {n} of {total}"
    :security="security"
    :metadata="metadata"
    :compress="true"
    :watermark="watermark"
    :html-to-pdf-options="htmlToPdfOptions"
    @progress-stage="onProgressStage"
  >
    <template #pdf-content>
      <main class="pdf-root">
        <section class="pdf-keep-together">
          <h1>Invoice #1024</h1>
          <p>This text is selectable and searchable in text mode.</p>

          <a href="https://www.npmjs.com/package/vue-pdf-export"> View package on npm </a>
        </section>

        <div class="html2pdf__page-break"></div>

        <section>
          <h2>Terms</h2>
          <p>Additional content...</p>
        </section>
      </main>
    </template>
  </Html2Pdf>
</template>

<style scoped>
.pdf-root {
  width: 794px;
  box-sizing: border-box;
}

.html2pdf__page-break {
  display: block;
  height: 0;
  clear: both;
}
</style>

Images & CORS

Remote images must be accessible to the browser during rendering.

Recommended:

html2canvas: {
  useCORS: true,
}

For external images:

  • configure appropriate CORS headers
  • avoid inaccessible authenticated image URLs
  • prefer data URLs for critical logos when practical
  • preserve image aspect ratio

Normal content image CSS:

.pdf-root img {
  max-width: 100%;
  height: auto;
  object-fit: contain;
}

Header/footer logo sizing is already aspect-ratio-safe internally. Their width and height props define maximum bounds instead of forced image dimensions.

Production Guide

Use a deterministic export width

A PDF should not unexpectedly reflow because it was generated from a narrow mobile viewport.

.pdf-root {
  width: 794px;
  box-sizing: border-box;
}

Keep export CSS separate from responsive application CSS

The web UI and the PDF document have different layout goals.

Choose the renderer intentionally

Use canvas when exact visual fidelity is the priority.

Use text when selectable/searchable/copyable PDF text is the priority and the document uses CSS supported by the vector renderer.

Avoid large fixed heights

Prefer min-height over large fixed height values where possible.

Protect important blocks

Use .pdf-keep-together, .pdf-no-break, or carefully chosen pagebreak.avoid selectors.

Preserve image aspect ratios

img {
  max-width: 100%;
  height: auto;
  object-fit: contain;
}

Keep header/footer content inside configured heights

Very large text or HTML content can overlap PDF content if it exceeds headerHeight or footerHeight.

Use trusted HTML only

headerHtml and footerHtml intentionally render developer-provided HTML.

Never pass unsanitized user-controlled content.

Avoid excessive letter spacing, transforms, or tightly fixed widths for PDF links/buttons when using selectable-text mode.

Use reasonable canvas quality

Higher html2canvas scale values consume more memory and CPU.

Generate one large document at a time

Multi-page PDF generation can be CPU and memory intensive.

Provide cancellation for expensive exports

Expose cancelGeneration() in long-running workflows so users can stop an export without waiting for the entire document to finish.

Cancellation is cooperative: already-running synchronous browser/jsPDF work finishes before the next cancellation checkpoint.

Test representative content

Test:

  • shortest document
  • longest document
  • missing fields
  • very long text
  • wide/square/tall logos
  • remote images
  • links
  • manual and automatic pagination
  • header/footer enabled and disabled
  • logo enabled and disabled
  • trusted HTML header/footer
  • selective header pages
  • watermark targeting
  • password protection
  • every permission combination important to your app
  • metadata
  • compression
  • both render modes

Performance & Large Documents

Large client-side PDF generation is constrained by browser memory, canvas limits, image size, document complexity, encryption overhead, and the device running the page. The package therefore uses multiple strategies rather than assuming one renderer is safe for every document.

Large-document work completed

The performance/stability work includes:

  • 10 / 25 / 50 / 100-page benchmark and regression fixtures
  • generation-time and PDF-size measurement
  • browser-memory experiments and repeated-generation testing
  • raw Canvas/jsPDF isolation tests to separate package behavior from dependency behavior
  • page-by-page incremental Canvas rendering for paginated documents
  • temporary DOM cleanup after page capture
  • canvas backing-store release after raster insertion
  • selectable-text image materialization with per-generation repeated-image caching
  • cooperative browser yielding during expensive loops
  • cancellation and recovery testing
  • page-aware progress reporting
  • long-document Playwright stress/regression coverage
  • image-heavy, mixed-content, header/footer, watermark, metadata, compression, links, and security scenarios

Measured performance improvements

The performance work resulted in several measurable improvements in the benchmark fixtures:

AreaBeforeAfterImprovement
HTML footer without logo7.82 s1.43 s~81.7% less time
HTML footer with logo11.81 s1.29 s~89.1% less time
Footer-heavy PDF size~46.7 MB~1.0 MB~97.9% smaller
Footer no-logo peak heap102.6 MB26.5 MB~74.2% lower
Long Canvas capture surface~99.96M px~1.74M px per page~98.26% smaller peak capture geometry

These measurements are tied to the project's benchmark fixtures and test environment. They should not be interpreted as a universal percentage improvement for every PDF.

The architectural changes behind these results include:

  • rendering static HTML footers once and reusing them across pages
  • page-by-page Canvas rendering for paginated documents
  • releasing temporary DOM and canvas backing stores earlier
  • caching repeated selectable-mode images within one generation
  • yielding between expensive rendering steps
  • adding cancellation and page-aware progress

Incremental Canvas strategy

For Canvas documents with .html2pdf__page-break markers, each logical page is rendered independently.

This avoids the old failure mode where a long document could become one extremely tall browser canvas. In regression testing, the incremental path restored correct 50-page and 100-page Canvas PDF output while keeping individual captures page-bounded.

The legacy whole-document html2pdf.js path is retained for Canvas documents that do not contain page-break markers.

Selectable-text image optimization

Selectable-text rendering uses a per-generation image cache for repeated real <img> sources when the source, target raster dimensions, format, and JPEG quality match.

Why the cache is intentionally per-generation:

  • avoids carrying stale DOM/image state across exports
  • keeps cache lifetime bounded
  • prevents a global cache from becoming a long-lived memory owner

Canvas elements are not cached because their pixels may change even when their dimensions do not.

Cleanup and browser responsiveness

Long exports explicitly release temporary resources where practical:

  • off-screen incremental page DOM is removed after html2canvas no longer needs it
  • temporary canvas backing stores are reset after serialization/insertion
  • selectable image-materialization canvases are released after encoding
  • per-generation image caches are cleared after use
  • rendering loops periodically yield with browser scheduling checkpoints

Yielding does not make CPU-heavy work free, but it gives the browser opportunities to process progress updates and cancellation rather than monopolizing the main thread for the entire export.

Cancellation and recovery

Both rendering modes support cooperative cancellation.

The regression suite checks that:

  1. an active long export can be cancelled,
  2. temporary rendering DOM is cleaned up,
  3. no successful Blob is exposed for the cancelled run, and
  4. a new PDF can be generated successfully afterwards.

Page progress

Page-aware renderers can report:

{
  stage: 'rendering',
  progress: number,
  currentPage?: number,
  totalPages?: number,
}

This is useful for long reports where a percentage alone does not explain what the renderer is doing.

Encrypted Canvas memory behavior

Large encrypted Canvas PDFs can retain substantially more memory than equivalent unencrypted Canvas PDFs in Chromium.

Isolation testing reproduced the severe encrypted-raster retention pattern with raw jsPDF usage, outside the Vue component lifecycle. For that reason this is tracked as an upstream/dependency concern rather than described as a confirmed Vue memory leak.

Practical guidance:

  • avoid unnecessarily high Canvas scale values
  • resize oversized images before PDF generation
  • generate one very large document at a time
  • prefer selectable-text mode when it meets the document's visual requirements
  • test encrypted long documents on representative target devices
  • consider splitting exceptionally large documents when browser memory is constrained

Upstream jsPDF tracking: large encrypted Canvas PDFs can show substantially higher memory retention than equivalent unencrypted Canvas PDFs in Chromium. The same encrypted-raster pattern was reproduced in a raw jsPDF-only test outside the Vue component lifecycle, so this is tracked as an upstream/dependency concern rather than described as a confirmed Vue memory leak. See jsPDF issue #4017.

Upstream tracking: jsPDF #4017 - encrypted raster PDF memory retention.

This link is included so developers using large encrypted Canvas PDFs can follow the dependency-level investigation directly.

Stress/regression coverage

AreaCoverage
Long Canvas documents10 / 25 / 50 / 100-page regression fixtures
Heavy cross-browser smokeChromium plus Firefox/WebKit coverage, with the heaviest 50/100-page cases concentrated in Chromium
Selectable-text long documentslong multi-page rendering and cancellation/recovery
Image-heavy selectable moderepeated image cache / raster-call regression
Image-heavy Canvas modepage-bounded canvas regression
CancellationCanvas and selectable-text cancellation + recovery
Cleanuptemporary page/snapshot/fixture cleanup assertions
Featuresheaders, footers, watermarks, links, metadata, compression, security

These tests validate the package's test fixtures and supported paths; they are not a universal guarantee that every arbitrary 100-page web document will fit every browser/device memory budget.

For large Canvas reports:

<Html2Pdf render-mode="canvas" :manual-pagination="true" :pdf-quality="1.5" />

Use explicit page markers:

<div class="html2pdf__page-break"></div>

For text-heavy reports where supported CSS is sufficient:

<Html2Pdf render-mode="text" />

Selectable-text mode avoids rasterizing the entire body and can be a better fit for long text-first documents.

About documents larger than 100 pages

The current automated stress and regression suite verifies large-document behavior through 100-page test fixtures.

This does not mean the package has a hard 100-page limit. PDF generation does not stop at page 100, and larger documents may also work successfully.

However, documents beyond the tested range depend increasingly on the actual workload, including:

  • DOM size and complexity
  • number and dimensions of images
  • whether images are unique or repeatedly reused
  • renderer choice
  • browser and device memory
  • headers, footers, and watermarks
  • encryption and compression
  • final PDF serialization cost

For very large text-first documents, renderMode="text" is generally the preferred starting point when its supported CSS is sufficient, because body text is represented as PDF text/vector operations instead of full-page raster screenshots.

For large Canvas documents, use deterministic pagination/page-break markers so the incremental renderer can keep individual Canvas captures page-bounded.

The package also provides page-aware progress and cooperative cancellation so applications can give users meaningful feedback during long exports:

Rendering page 74 of 100

Security Model & Boundaries

vue-pdf-export provides PDF security features and conservative browser-side cleanup, but no client-side PDF package can make an application "100% secure" by itself.

Verified outcomes

The final regression suite verified:

  • 50-page Canvas generation
  • 100-page Canvas generation
  • Canvas cancellation and recovery
  • selectable-text cancellation and recovery
  • repeated-image caching in selectable-text mode
  • page-bounded Canvas rendering in image-heavy documents
  • temporary rendering cleanup after cancellation/generation

The final unit suite completed with:

19 test files passed
106 / 106 tests passed

What the package provides

  • jsPDF-backed PDF encryption/password protection
  • separate user/open and owner password inputs
  • supported permission flags for print, modify, copy, and annotation/forms
  • explicit security.enabled: false handling to remove inherited raw encryption
  • metadata/compression processing without sending the document to a package-operated backend
  • Blob URL cleanup in the component/composable lifecycle
  • cancellation cleanup for temporary rendering structures
  • filename normalization that removes unsafe path/filename characters and protects Windows reserved names

What remains the application's responsibility

  • sanitizing any untrusted HTML before passing it to headerHtml or footerHtml
  • protecting passwords, tokens, customer data, and remote asset URLs
  • server-side authorization before sensitive data reaches the browser
  • selecting CORS-safe and trusted image origins
  • deciding whether client-side PDF generation is appropriate for highly sensitive documents
  • validating the behavior of permission flags in the PDF viewers used by your customers

Important client-side security note

Anything available to frontend JavaScript can potentially be inspected by a user who controls that browser session. Do not treat a frontend bundle, minification, or obfuscation as a secret-storage mechanism.

Minifying the npm distribution is useful for package size and distribution hygiene, but it is not a security boundary.

Selectable Text Mode Notes

Selectable-text mode uses a browser-layout-to-vector-PDF renderer rather than html2canvas for the main body content.

What it is designed to preserve

  • real PDF text
  • selection/search/copy
  • text line placement based on browser layout
  • common font weight/style/color/alignment
  • backgrounds
  • borders
  • images
  • opacity
  • overflow clipping
  • multi-page layout
  • clickable links

Current limitations

Some browser CSS/features are not fully reproduced in selectable-text mode, including or depending on renderer support:

  • complex stacking-context / z-index reordering
  • background images and gradients
  • shadows
  • CSS transforms
  • custom TTF/web-font embedding
  • some non-WinAnsi glyphs such as CJK/emoji
  • pseudo-elements such as ::before / ::after
  • native list markers in some layouts
  • RTL text
  • position: fixed
  • complex rounded clipping
  • native break-inside: avoid semantics inside the vector renderer

For those cases, prefer renderMode="canvas".

Font metric differences

Selectable text uses PDF font metrics, which can differ slightly from browser web-font metrics. Most normal text is visually close, but highly stylized button/link text with large letter spacing or fixed widths can look different.

Header/footer text

In selectable-text mode, plain header/footer text and footer page-number text are emitted as real selectable PDF text. Complex HTML styling may be simplified to preserve selectability.

Security

Selectable-text mode supports PDF encryption because the vendored vector renderer passes the package's jsPDF constructor options at document creation time.

Troubleshooting

Selectable text is not pixel-identical to the browser

Use render-mode="canvas" for maximum CSS fidelity.

Selectable-text mode intentionally prioritizes real PDF text and vector output.

Make sure links are enabled:

const htmlToPdfOptions = {
  enableLinks: true,
}

Also verify the source element is a real anchor with a valid href.

Reduce large letter-spacing, transforms, and tight fixed widths in selectable-text mode.

Logo looks stretched

Header/footer logo dimensions are maximum bounds and preserve the source aspect ratio.

For normal content images:

img {
  width: auto;
  height: auto;
  max-width: 100%;
  object-fit: contain;
}

Header/footer overlaps content

Increase headerHeight / footerHeight, or reduce content size.

For selectively targeted headers, only target pages receive the extra header space. If excluded pages still have top spacing, check explicit htmlToPdfOptions.margin.

Check:

  • URL accessibility
  • CORS
  • data URL validity
  • headerLogoEnabled
  • footerLogoEnabled

HTML header/footer is not visible

Check that:

  • related header/footer is enabled
  • HTML string is non-empty
  • footer uses footer-mode="html"
  • content fits inside configured height

Blank page around a manual break

Use only:

.html2pdf__page-break {
  display: block;
  height: 0;
  clear: both;
}

Do not add break-before or page-break-before to the same helper.

Background watermark is hidden

Opaque PDF content can cover a DOM background watermark.

Use a foreground watermark or transparent export content where appropriate.

PDF is blurry

In canvas mode, increase pdfQuality or htmlToPdfOptions.html2canvas.scale carefully.

Selectable-text body text remains vector text and does not depend on html2canvas resolution.

Large document generation is slow

Reduce:

  • canvas scale where relevant
  • image dimensions
  • document complexity
  • simultaneous PDF generation

Large encrypted Canvas PDFs can show substantially higher memory retention than unencrypted Canvas PDFs in Chromium. Raw jsPDF-only isolation reproduced the same encrypted-raster retention pattern outside the Vue lifecycle, so this is tracked as an upstream/dependency concern rather than described as a confirmed permanent Vue memory leak. Selectable-text mode did not show the same severe raster-memory pattern in the package benchmarks.

Browser Support

The package targets modern browsers supported by Vue and the underlying PDF/browser APIs.

Recommended testing:

  • Chromium / Chrome / Edge
  • Firefox
  • WebKit
  • Safari when Safari is important to production users

Playwright WebKit tests the WebKit engine; it is not identical to testing the Safari application itself.

Testing

The project includes unit/integration and browser E2E coverage for major workflows, including:

  • PDF generation
  • preview Blob creation
  • download
  • print flow
  • rendering mode routing
  • selectable-text generation
  • PDF link annotations
  • pagination and page-break mapping
  • metadata
  • compression
  • security
  • protected/unprotected PDFs
  • header page targeting
  • selective header spacing
  • optional header/footer logos
  • custom logo sizing
  • header/footer HTML rendering
  • selectable header/footer text
  • footer page numbering
  • per-page watermark targeting
  • progress stages
  • page-aware currentPage / totalPages
  • cooperative cancellation and recovery
  • 10 / 25 / 50 / 100-page large-document regression fixtures
  • selectable repeated-image caching
  • page-bounded Canvas image-heavy rendering
  • temporary rendering DOM/snapshot cleanup

Because PDF rendering is CPU-heavy, a small Playwright worker count is recommended:

npx playwright test --workers=2

Because large PDF rendering is CPU- and memory-intensive, use a single worker for heavy stress/regression suites:

npx playwright test --workers=1

Run the full release checks before publishing:


npm run type-check

npm run build

npm run build:demo

npm run test:unit:run

npx playwright test e2e/generate-pdf.spec.ts --workers=2

npm publish --dry-run

TypeScript

The package ships TypeScript declarations.

Common types:

import type {
  BeforeDownloadPayload,
  FooterMode,
  FooterOptions,
  GeneratePdfResult,
  HeaderOptions,
  Html2CanvasOptions,
  Html2PdfOptions,
  Html2PdfProps,
  JsPdfOptions,
  PdfEncryptionOptions,
  PdfFormat,
  PdfImageOptions,
  PdfMargin,
  PdfMetadataOptions,
  PdfOrientation,
  PdfPageBreakOptions,
  PdfPageTarget,
  PdfPermission,
  PdfProgressStage,
  PdfProgressState,
  PdfRenderMode,
  PdfSecurityOptions,
  WatermarkLayer,
  WatermarkMode,
  WatermarkOptions,
  WatermarkType,
} from 'vue-pdf-export'

Render mode type:

export type PdfRenderMode = 'canvas' | 'text'

Useful helpers:

import { createPdfOptions, normalizePdfFilename, resolvePdfPages } from 'vue-pdf-export'

Community

The package source is currently maintained privately, but feedback and feature requests are welcome.

Acknowledgements

Selectable-text rendering in vue-pdf-export is based on and adapted from @timkozlov/html-to-pdf, created by @Canelex and released under the MIT License.

A big thank you to the author for the browser DOM-to-vector-PDF work that made real selectable/searchable text practical in this package.

Upstream project: Canelex/html-to-pdf.

vue-pdf-export vendors and adapts that renderer for integration with its own API, including areas such as jsPDF constructor options/security, existing page-break compatibility, shared PDF post-processing, and package-specific behavior. The original license notice is retained with the vendored source.

License

MIT © 2026 Saurabh Choudhary

Third-party vendored code remains subject to its original copyright and MIT license notices.

Support the project

If vue-pdf-export is useful in your project, you can support its continued development:

Support is optional. Bug reports, feedback, and feature requests are also welcome through the project feedback board.

Copyright © 2026