<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Saurabh Choudhary</title>
    <description>The latest articles on DEV Community by Saurabh Choudhary (@saurabhzaiswal).</description>
    <link>https://dev.to/saurabhzaiswal</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3965731%2F92f14392-09df-4c4f-8e72-e770c5ed2397.jpg</url>
      <title>DEV Community: Saurabh Choudhary</title>
      <link>https://dev.to/saurabhzaiswal</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/saurabhzaiswal"/>
    <language>en</language>
    <item>
      <title>Building a Better PDF Generator in Vue 3 with vue-pdf-export</title>
      <dc:creator>Saurabh Choudhary</dc:creator>
      <pubDate>Sun, 18 Oct 2026 17:39:57 +0000</pubDate>
      <link>https://dev.to/saurabhzaiswal/building-a-better-pdf-generator-in-vue-3-with-vue-pdf-export-416</link>
      <guid>https://dev.to/saurabhzaiswal/building-a-better-pdf-generator-in-vue-3-with-vue-pdf-export-416</guid>
      <description>&lt;p&gt;Hey Vue developers 👋&lt;/p&gt;

&lt;p&gt;I’ve been building &lt;a href="https://www.npmjs.com/package/vue-pdf-export" rel="noopener noreferrer"&gt;&lt;code&gt;vue-pdf-export&lt;/code&gt;&lt;/a&gt;, an open-source Vue 3 + TypeScript library for generating PDFs directly in the browser.&lt;/p&gt;

&lt;p&gt;I started this project because I kept rebuilding the same PDF features across Vue applications: pagination, preview, printing, headers, footers, progress tracking, and long-document support. I wanted a reusable component and composable rather than repeating that infrastructure in every project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In short:&lt;/strong&gt; Generate PDFs from Vue 3 components in the browser using either Canvas rendering or selectable, searchable text. The package also supports smart pagination, tables, headers, footers, watermarks, preview, download, print, and SSR-safe imports for Nuxt 3 and Nuxt 4.&lt;/p&gt;

&lt;p&gt;You can explore the actual PDF output without setting up a project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Live playground:&lt;/strong&gt; &lt;a href="https://vue-pdf-export-playground.vercel.app/" rel="noopener noreferrer"&gt;https://vue-pdf-export-playground.vercel.app/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Full documentation:&lt;/strong&gt; &lt;a href="https://vue-pdf-export-docs.vercel.app/" rel="noopener noreferrer"&gt;https://vue-pdf-export-docs.vercel.app/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Here is what the published package supports:&lt;/p&gt;

&lt;h2&gt;
  
  
  In this guide
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Features and quick start&lt;/li&gt;
&lt;li&gt;Rendering modes: Canvas vs selectable text&lt;/li&gt;
&lt;li&gt;Smart PDF pagination&lt;/li&gt;
&lt;li&gt;Nuxt 3 and Nuxt 4 SSR integration&lt;/li&gt;
&lt;li&gt;API, headers, footers, watermarks, and security&lt;/li&gt;
&lt;li&gt;Programmatic output and TypeScript&lt;/li&gt;
&lt;li&gt;Styling, composition, and playground demos&lt;/li&gt;
&lt;li&gt;Production, performance, and troubleshooting&lt;/li&gt;
&lt;li&gt;Testing and browser support&lt;/li&gt;
&lt;li&gt;Developer FAQ and next steps&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Quick answer - How do I generate a PDF in Vue 3?&lt;/strong&gt; Install &lt;code&gt;vue-pdf-export&lt;/code&gt;, import &lt;code&gt;Html2Pdf&lt;/code&gt; and its stylesheet, place your document in the &lt;code&gt;#pdf-content&lt;/code&gt; slot, and call &lt;code&gt;generatePdf()&lt;/code&gt; from a Vue template ref. Use &lt;code&gt;render-mode="text"&lt;/code&gt; for native searchable/selectable body text; choose &lt;code&gt;render-mode="canvas"&lt;/code&gt; when complex browser CSS fidelity matters most. Both modes generate PDFs in the browser.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Powerful:&lt;/strong&gt; choose Canvas or selectable-text output, use your own Vue document components, and control page breaks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modular:&lt;/strong&gt; use the component or composable, and add only the slots and options your document needs. PDF engines load when generation runs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customizable:&lt;/strong&gt; style exported content with your CSS and export-only options; theme the built-in preview and loader with CSS variables.&lt;/li&gt;
&lt;li&gt;Canvas and selectable-text PDF rendering&lt;/li&gt;
&lt;li&gt;Smart automatic/manual pagination, keep-together blocks and container-aware splitting&lt;/li&gt;
&lt;li&gt;Explicit page breaks, repeated table headers and opt-in pagination diagnostics&lt;/li&gt;
&lt;li&gt;Preview, download, and native browser print&lt;/li&gt;
&lt;li&gt;Blob, ArrayBuffer, Base64, and PDF data-URL output&lt;/li&gt;
&lt;li&gt;Header/footer object options, Vue slots and page targeting&lt;/li&gt;
&lt;li&gt;PDF composition: prepend or append existing PDF pages&lt;/li&gt;
&lt;li&gt;Standard paper formats and custom dimensions in portrait or landscape&lt;/li&gt;
&lt;li&gt;Text, image and trusted HTML watermarks with optional design presets; text marks use reusable vector outlines instead of selectable PDF text&lt;/li&gt;
&lt;li&gt;Password protection, permissions, metadata, and compression&lt;/li&gt;
&lt;li&gt;Clickable PDF links&lt;/li&gt;
&lt;li&gt;Progress reporting, generation metrics, and cancellation&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;data-pdf-ignore&lt;/code&gt; for export-only DOM control&lt;/li&gt;
&lt;li&gt;PDF-only page/body styling and custom CSS&lt;/li&gt;
&lt;li&gt;Large-document rendering optimizations&lt;/li&gt;
&lt;li&gt;Font readiness, optional TTF/TrueType-outline OTF embedding, chart snapshots and SVG fallback&lt;/li&gt;
&lt;li&gt;Opt-in image optimization with explicit quality controls and per-export asset reuse metrics&lt;/li&gt;
&lt;li&gt;Nuxt 3 and Nuxt 4 SSR-safe imports&lt;/li&gt;
&lt;li&gt;TypeScript declarations&lt;/li&gt;
&lt;li&gt;npm, pnpm, Yarn, Yarn PnP, and Bun consumer validation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For detailed API options, examples, renderer notes, styling, pagination,&lt;br&gt;
security, SSR guidance, and production recommendations, see the&lt;br&gt;
&lt;strong&gt;&lt;a href="https://vue-pdf-export-docs.vercel.app/" rel="noopener noreferrer"&gt;full documentation&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Security note:&lt;/strong&gt; Header, footer, and slot HTML is sanitized before entering export staging. Treat caller-provided HTML as untrusted and apply your application’s input validation policy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Privacy and network boundary:&lt;/strong&gt; Ordinary PDF generation happens in your browser and does not upload document content to a package-operated server. URL-based templates, remote fonts/images, and external export stylesheets may still be fetched from their configured origins.&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  Install
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;vue-pdf-export
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Small example
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Html2Pdf&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export/style.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pdfRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;InstanceType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;Html2Pdf&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"pdfRef?.generatePdf()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Generate PDF&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt; &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;"pdfRef"&lt;/span&gt; &lt;span class="na"&gt;filename=&lt;/span&gt;&lt;span class="s"&gt;"report.pdf"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;#pdf-content&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Hello from Vue&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;This content will be exported to PDF.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/Html2Pdf&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;Playground:&lt;br&gt;&lt;br&gt;
&lt;a href="https://vue-pdf-export-playground.vercel.app/" rel="noopener noreferrer"&gt;https://vue-pdf-export-playground.vercel.app/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Documentation:&lt;br&gt;&lt;br&gt;
&lt;a href="https://vue-pdf-export-docs.vercel.app/" rel="noopener noreferrer"&gt;https://vue-pdf-export-docs.vercel.app/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;npm:&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.npmjs.com/package/vue-pdf-export" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/vue-pdf-export&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’d really like feedback from Vue developers who have worked with PDFs in production - especially around pagination, large documents, selectable text, and API ergonomics.&lt;/p&gt;


&lt;h2&gt;
  
  
  Complete Vue 3 PDF generation guide
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Scope:&lt;/strong&gt; This guide describes the currently published &lt;code&gt;vue-pdf-export&lt;/code&gt; functionality and combines practical examples with API detail. Code samples and recorded benchmarks reflect the documented test scenarios; run your own target-browser tests before shipping production PDFs. For the maintained source of truth, use the &lt;a href="https://vue-pdf-export-docs.vercel.app/" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt; and &lt;a href="https://github.com/saurabhzaiswal/vue-pdf-export" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This complete technical guide covers installation, JavaScript and TypeScript usage, components and composables, rendering modes, pagination, styling, page layers, programmatic output, performance, testing, production checks, and browser limitations. It also links to the &lt;a href="https://vue-pdf-export-docs.vercel.app/use-cases/performance-report" rel="noopener noreferrer"&gt;detailed performance engineering report&lt;/a&gt; for reproducible measurements.&lt;/p&gt;
&lt;h2&gt;
  
  
  Get Started
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;vue-pdf-export&lt;/code&gt; is a Vue 3 HTML-to-PDF component and composable for browser applications. Use it from JavaScript or TypeScript.&lt;/p&gt;

&lt;p&gt;The API includes smart split controls, row-aware tables, header/footer objects and Vue slots, PDF composition, expanded paper sizes, font readiness, chart snapshots, SVG fallback, and opt-in image optimization.&lt;/p&gt;

&lt;p&gt;It supports two rendering modes:&lt;/p&gt;

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

&lt;p&gt;It also includes manual and automatic pagination, preview, download, native browser print, Blob/ArrayBuffer/Base64 output, export-only page/body styling, &lt;code&gt;data-pdf-ignore&lt;/code&gt;, custom export CSS, external print stylesheets, forced light/dark themes, width auto-fit, safe filename normalization, progress stages, opt-in generation metrics, current-page progress, cancellation, page targeting, PDF permissions, SSR-safe imports, large-document optimizations, and advanced renderer configuration.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Default rendering mode:&lt;/strong&gt; &lt;code&gt;renderMode="canvas"&lt;/code&gt;. The live playground may select another default for demonstration purposes.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;
  
  
  Highlights
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Browser-side PDF generation with no package-managed upload service&lt;/li&gt;
&lt;li&gt;Canvas and selectable-text rendering&lt;/li&gt;
&lt;li&gt;Blob, ArrayBuffer, raw Base64, and PDF data-URL output&lt;/li&gt;
&lt;li&gt;Native browser print support in both rendering modes&lt;/li&gt;
&lt;li&gt;Incremental page-by-page Canvas rendering when page-break markers are present&lt;/li&gt;
&lt;li&gt;Cooperative cancellation for long-running exports&lt;/li&gt;
&lt;li&gt;Page-aware progress with &lt;code&gt;currentPage&lt;/code&gt; / &lt;code&gt;totalPages&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Opt-in total, stage, and per-page generation timing metrics&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;data-pdf-ignore&lt;/code&gt; for screen-only UI that must stay out of generated PDFs&lt;/li&gt;
&lt;li&gt;Export-only page/body styling without mutating the visible Vue DOM&lt;/li&gt;
&lt;li&gt;Repeated-image caching in selectable-text rendering&lt;/li&gt;
&lt;li&gt;Optional TTF/TrueType-outline OTF embedding for selectable text&lt;/li&gt;
&lt;li&gt;Export-only chart snapshots, SVG fallback and explicit image quality controls&lt;/li&gt;
&lt;li&gt;Text, image and trusted HTML watermark designs with per-export reuse&lt;/li&gt;
&lt;li&gt;Temporary DOM/canvas cleanup between expensive rendering steps&lt;/li&gt;
&lt;li&gt;Password protection, owner password, PDF permission flags, metadata, and compression&lt;/li&gt;
&lt;li&gt;Headers, footers, logos, watermarks, page targeting, and clickable links&lt;/li&gt;
&lt;li&gt;SSR-safe package imports with Nuxt 3 and Nuxt 4 validation&lt;/li&gt;
&lt;li&gt;Packed-consumer verification across npm, pnpm, Yarn, Yarn Plug'n'Play, and Bun&lt;/li&gt;
&lt;li&gt;Large-document stress presets from 5 through 1000 pages, plus custom counts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Presets are test inputs, not a guarantee that every page count will succeed on every device. Test representative documents in your target browsers.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Try it before integrating:&lt;/strong&gt; The &lt;a href="https://vue-pdf-export-playground.vercel.app/" rel="noopener noreferrer"&gt;live playground&lt;/a&gt; exposes package options, output APIs, and diagnostics interactively.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://vue-pdf-export-playground.vercel.app/" rel="noopener noreferrer"&gt;Open the interactive PDF playground&lt;/a&gt;&lt;br&gt;
Open playground&lt;/p&gt;


&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;Install the package using your preferred package manager:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;vue-pdf-export
&lt;span class="c"&gt;# or&lt;/span&gt;
pnpm add vue-pdf-export
&lt;span class="c"&gt;# or&lt;/span&gt;
yarn add vue-pdf-export
&lt;span class="c"&gt;# or&lt;/span&gt;
bun add vue-pdf-export
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Import
&lt;/h4&gt;

&lt;p&gt;TypeScript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;Html2Pdf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;PdfBase64Options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;PdfMetadataOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;PdfOutputFormat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;PdfProgressState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;PdfRenderMode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;PdfSecurityOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;PdfSerializedOutput&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;PdfStylingOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;WatermarkOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export/style.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;JavaScript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Html2Pdf&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export/style.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Package-manager compatibility
&lt;/h4&gt;

&lt;p&gt;The packed package is validated as a consumer installation with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;npm&lt;/li&gt;
&lt;li&gt;pnpm&lt;/li&gt;
&lt;li&gt;Yarn&lt;/li&gt;
&lt;li&gt;Yarn Plug'n'Play&lt;/li&gt;
&lt;li&gt;Bun&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The compatibility fixtures verify installation, TypeScript resolution, production builds, CSS imports, and browser-side PDF generation.&lt;/p&gt;

&lt;h4&gt;
  
  
  Nuxt
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;vue-pdf-export&lt;/code&gt; can be imported during SSR, while PDF generation itself remains browser-only.&lt;/p&gt;

&lt;p&gt;See &lt;a href="https://vue-pdf-export-docs.vercel.app/get-started/nuxt-ssr" rel="noopener noreferrer"&gt;Nuxt 3 &amp;amp; Nuxt 4 SSR&lt;/a&gt; for &lt;code&gt;&amp;lt;ClientOnly&amp;gt;&lt;/code&gt;, lazy-import, and client-event patterns.&lt;/p&gt;




&lt;h3&gt;
  
  
  Quick Start
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Html2Pdf&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export/style.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pdfRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;InstanceType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;Html2Pdf&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;generatePdf&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;blob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;pdfRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;generatePdf&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"generatePdf"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Generate PDF&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt;
    &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;"pdfRef"&lt;/span&gt;
    &lt;span class="na"&gt;filename=&lt;/span&gt;&lt;span class="s"&gt;"my-report"&lt;/span&gt;
    &lt;span class="na"&gt;render-mode=&lt;/span&gt;&lt;span class="s"&gt;"canvas"&lt;/span&gt;
    &lt;span class="na"&gt;:manual-pagination=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
    &lt;span class="na"&gt;:enable-download=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;#pdf-content&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;My Report&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;This content will be rendered into the PDF.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/Html2Pdf&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Plain JavaScript with the Vue Options API
&lt;/h4&gt;

&lt;p&gt;TypeScript is optional. Register &lt;code&gt;Html2Pdf&lt;/code&gt; locally and call &lt;code&gt;generatePdf()&lt;/code&gt; through a template ref. PDF generation runs in the browser after the component mounts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Html2Pdf&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export/style.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Html2Pdf&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;blob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$refs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generatePdf&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;PDF bytes:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"generate"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Generate PDF&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt; &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;"pdf"&lt;/span&gt; &lt;span class="na"&gt;:enable-download=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;#pdf-content&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;gt;&amp;lt;article&amp;gt;&amp;lt;h1&amp;gt;&lt;/span&gt;JavaScript report&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&amp;lt;/article&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;
    &amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/Html2Pdf&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without a pagination height, the renderer handles basic page flow. Set a positive &lt;code&gt;paginateElementsByHeight&lt;/code&gt; when you want the smart DOM planner; see &lt;a href="https://vue-pdf-export-docs.vercel.app/get-started/pagination" rel="noopener noreferrer"&gt;pagination&lt;/a&gt;. The Options API example is based on the library's npm consumer fixture.&lt;/p&gt;




&lt;h3&gt;
  
  
  Rendering Modes
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Canvas mode
&lt;/h4&gt;

&lt;p&gt;Canvas mode is the default and uses the package's existing &lt;code&gt;html2pdf.js&lt;/code&gt; / &lt;code&gt;html2canvas&lt;/code&gt; / &lt;code&gt;jsPDF&lt;/code&gt; pipeline.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt; &lt;span class="na"&gt;render-mode=&lt;/span&gt;&lt;span class="s"&gt;"canvas"&lt;/span&gt; &lt;span class="na"&gt;manual-pagination&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use it when the highest possible browser CSS fidelity is more important than selectable body text.&lt;/p&gt;

&lt;p&gt;Canvas keeps inline SVG in its export staging by default, but the final PDF page is still a raster image. Chart canvases are snapshotted on the private export clone before capture. See &lt;a href="https://vue-pdf-export-docs.vercel.app/use-cases/media-typography" rel="noopener noreferrer"&gt;fonts, charts, SVG and images&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Best for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;complex CSS&lt;/li&gt;
&lt;li&gt;gradients&lt;/li&gt;
&lt;li&gt;shadows&lt;/li&gt;
&lt;li&gt;transforms&lt;/li&gt;
&lt;li&gt;custom web fonts&lt;/li&gt;
&lt;li&gt;visual dashboards&lt;/li&gt;
&lt;li&gt;designs where browser appearance is the priority&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Body content is rasterized, so normal body text is not selectable/searchable.&lt;/p&gt;

&lt;p&gt;A viewer such as Chrome may apply OCR and let users select apparent text in an image-only PDF. A foreground text watermark or some numbering paths can also add native text over a Canvas body. Inspect PDF text operators or extract text with a PDF tool to distinguish native text from viewer OCR.&lt;/p&gt;

&lt;h5&gt;
  
  
  Incremental Canvas rendering
&lt;/h5&gt;

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

&lt;p&gt;This path:&lt;/p&gt;

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

&lt;p&gt;Canvas documents without page-break markers use the whole-document &lt;code&gt;html2pdf.js&lt;/code&gt; worker. Paginated Canvas documents can use page-bounded incremental captures.&lt;/p&gt;

&lt;p&gt;Oversized splittable Canvas sections are measured and re-paginated on private staging DOM before capture. Reused fitting fragments and page-by-page capture reduce repeated work; very large indivisible media can still scale or split. Vue header/footer slots use image captures in Canvas mode and supported text/shape operations in text mode.&lt;/p&gt;

&lt;h4&gt;
  
  
  Selectable text mode
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt; &lt;span class="na"&gt;render-mode=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;manual-pagination&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;In selectable-text mode, inline SVG shapes are rasterized; &lt;code&gt;svgMode="preserve"&lt;/code&gt; cannot turn them into native PDF vectors. Optional TTF or TrueType-outline OTF registration can embed a matching face for real PDF text. Without a registered font, unrecognized CSS families use built-in PDF faces.&lt;/p&gt;

&lt;p&gt;It supports:&lt;/p&gt;

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

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt; &lt;span class="na"&gt;render-mode=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;manual-pagination&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="na"&gt;#pdf-content&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;main&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Selectable report&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;You can select and search this text in the generated PDF.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

      &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://www.npmjs.com/package/vue-pdf-export"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        Open vue-pdf-export on npm
      &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/main&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/Html2Pdf&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Selectable-text mode intentionally favors real PDF text over pixel-perfect parity with every browser CSS feature. See Selectable Text Mode Notes.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  Component Registration
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Local import - recommended
&lt;/h4&gt;

&lt;p&gt;With &lt;code&gt;&amp;lt;script setup&amp;gt;&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Html2Pdf&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export/style.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No &lt;code&gt;components&lt;/code&gt; registration is required.&lt;/p&gt;

&lt;h4&gt;
  
  
  Options API
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Html2Pdf&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export/style.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;Html2Pdf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Global registration
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createApp&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./App.vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Html2Pdf&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export/style.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;component&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Html2Pdf&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Html2Pdf&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#app&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Preview &amp;amp; Download
&lt;/h3&gt;

&lt;p&gt;Add one of these prop combinations to the &lt;a href="https://vue-pdf-export-docs.vercel.app/get-started/quick-start" rel="noopener noreferrer"&gt;complete quick-start component&lt;/a&gt;. Keep &lt;code&gt;manual-pagination&lt;/code&gt; for a simple document, or configure a usable page-height budget for &lt;a href="https://vue-pdf-export-docs.vercel.app/get-started/pagination" rel="noopener noreferrer"&gt;automatic pagination&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Preview only:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt; &lt;span class="na"&gt;:enable-download=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt; &lt;span class="na"&gt;:preview-modal=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Download only:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt; &lt;span class="na"&gt;:enable-download=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="na"&gt;:preview-modal=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Download and preview:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt; &lt;span class="na"&gt;:enable-download=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="na"&gt;:preview-modal=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;enableDownload&lt;/code&gt; and &lt;code&gt;previewModal&lt;/code&gt; are independent.&lt;/p&gt;




&lt;h3&gt;
  
  
  Smart PDF Pagination
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Html2Pdf&lt;/code&gt; runs the shared DOM pagination planner when &lt;code&gt;manualPagination&lt;/code&gt; is &lt;code&gt;false&lt;/code&gt; and &lt;code&gt;paginateElementsByHeight&lt;/code&gt; is supplied. That number is the &lt;strong&gt;usable CSS pixel height after margins and header/footer reservations&lt;/strong&gt;, calculated for your chosen paper size and orientation. It is not a universal A4 constant. Direct &lt;code&gt;useHtml2Pdf()&lt;/code&gt; generation does not run the component planner.&lt;/p&gt;

&lt;p&gt;The component also supports a simple Options API or Composition API PDF without pagination props: the selected renderer handles basic flow. Set a positive finite height to use the smart DOM planner for keep-together rules and table rows. In the playground, manual pagination is the demo default, and the optional media/chart section has an authored break before it. A large section may continue onto another physical page. Oversized rows and unusual CSS still need PDF inspection.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Html2Pdf&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export/style.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Example budget for this application's measured paper geometry and insets.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;usablePageHeightPx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;960&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt;
    &lt;span class="na"&gt;:manual-pagination=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;
    &lt;span class="na"&gt;:paginate-elements-by-height=&lt;/span&gt;&lt;span class="s"&gt;"usablePageHeightPx"&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;#pdf-content&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;section&lt;/span&gt; &lt;span class="na"&gt;data-pdf-split=&lt;/span&gt;&lt;span class="s"&gt;"avoid"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Summary&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Keep this block together if it fits.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;section&lt;/span&gt; &lt;span class="na"&gt;data-pdf-split=&lt;/span&gt;&lt;span class="s"&gt;"container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;header&lt;/span&gt; &lt;span class="na"&gt;data-pdf-split-header&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Repeated section heading&lt;span class="nt"&gt;&amp;lt;/header&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;article&amp;gt;&lt;/span&gt;First child&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;article&amp;gt;&lt;/span&gt;Second child&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/Html2Pdf&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Recalculate the budget when format, orientation, explicit margins, content width or layer heights change. The &lt;a href="https://vue-pdf-export-docs.vercel.app/get-started/paper-formats" rel="noopener noreferrer"&gt;paper format guide&lt;/a&gt; explains geometry.&lt;/p&gt;

&lt;h4&gt;
  
  
  Split controls
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Markup&lt;/th&gt;
&lt;th&gt;Effect&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;data-pdf-split="avoid"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Move a fitting block together; oversized blocks can fall back to child boundaries.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;data-pdf-split="container"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Split long and nested sections around children, accounting for computed padding and flex/grid gaps.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;data-pdf-split-header&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Mark a child heading for repetition when its container continues.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;.pdf-keep-together&lt;/code&gt;, &lt;code&gt;.pdf-no-break&lt;/code&gt;, &lt;code&gt;img&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Existing default avoidance rules.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In supported selectable-text layouts, continuation fragments can retain a frame with page-edge spacing and rounded borders. Renderer CSS support varies. Indivisible oversized media, rowspans and complex nested layouts may still split or scale; inspect representative exports.&lt;/p&gt;

&lt;h4&gt;
  
  
  Explicit page breaks
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;section&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"break-before: page"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Start on a new page.&lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;section&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"break-after: page"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  The next block starts on a new page.
&lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"html2pdf__page-break"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;CSS &lt;code&gt;page-break-before&lt;/code&gt; and &lt;code&gt;page-break-after&lt;/code&gt; are supported alongside modern break properties. Do not put an explicit CSS break on the &lt;code&gt;.html2pdf__page-break&lt;/code&gt; marker: that can produce two breaks or blank pages. &lt;code&gt;manual-pagination="true"&lt;/code&gt; is useful when you author your own markers. Elements without special attributes retain their existing behavior.&lt;/p&gt;

&lt;h4&gt;
  
  
  Long tables
&lt;/h4&gt;

&lt;p&gt;Use one semantic heading and ordinary rows. The planner can split across multiple &lt;code&gt;&amp;lt;tbody&amp;gt;&lt;/code&gt; groups, honor explicit row breaks, move an orphan heading with its first row and repeat &lt;code&gt;&amp;lt;thead&amp;gt;&lt;/code&gt; on continuation pages. Do not manually copy the heading.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;table&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;thead&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;tr&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;th&lt;/span&gt; &lt;span class="na"&gt;scope=&lt;/span&gt;&lt;span class="s"&gt;"col"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;th&lt;/span&gt; &lt;span class="na"&gt;scope=&lt;/span&gt;&lt;span class="s"&gt;"col"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Amount&lt;span class="nt"&gt;&amp;lt;/th&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/thead&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;tbody&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;tr&lt;/span&gt; &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"item in 40"&lt;/span&gt; &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;Item &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;td&amp;gt;&lt;/span&gt;$&lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/tr&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/tbody&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/table&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Selectable-text rendering carries the computed heading background into repeated rows. Canvas continuation fragments suppress a second native heading repetition. Check complex &lt;code&gt;rowspan&lt;/code&gt;, unsupported CSS and oversized rows in the output.&lt;/p&gt;

&lt;h4&gt;
  
  
  Diagnose page boundaries
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Html2Pdf&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PdfPaginationDiagnostic&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export/style.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;onBreak&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;decision&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PdfPaginationDiagnostic&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;decision&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;decision&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;decision&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt;
    &lt;span class="na"&gt;:manual-pagination=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;
    &lt;span class="na"&gt;:paginate-elements-by-height=&lt;/span&gt;&lt;span class="s"&gt;"960"&lt;/span&gt;
    &lt;span class="na"&gt;:pagination-debug=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
    &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;pagination-break=&lt;/span&gt;&lt;span class="s"&gt;"onBreak"&lt;/span&gt;
    &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;pagination-warning=&lt;/span&gt;&lt;span class="s"&gt;"onBreak"&lt;/span&gt;
    &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;pagination-complete=&lt;/span&gt;&lt;span class="s"&gt;"(all) =&amp;gt; console.info(all)"&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;#pdf-content&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;article&amp;gt;&lt;/span&gt;Measured report content&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/Html2Pdf&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Possible diagnostic types are &lt;code&gt;automatic&lt;/code&gt;, &lt;code&gt;manual-break&lt;/code&gt;, &lt;code&gt;break-before&lt;/code&gt;, &lt;code&gt;break-after&lt;/code&gt;, &lt;code&gt;avoid-moved&lt;/code&gt;, &lt;code&gt;container-split&lt;/code&gt;, &lt;code&gt;table-split&lt;/code&gt;, and &lt;code&gt;oversized&lt;/code&gt;. The opt-in overlay and events show planner decisions on the live DOM. The overlay is not a PDF layer or proof of final viewer alignment. Pagination has a finite fallback and cancellation checks; it cannot guarantee that arbitrary text, SVG or CSS never tears.&lt;/p&gt;




&lt;h3&gt;
  
  
  Nuxt 3 &amp;amp; Nuxt 4 SSR
&lt;/h3&gt;

&lt;p&gt;
  &lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fnuxt.com%2Fassets%2Fdesign-kit%2Ficon-green.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fnuxt.com%2Fassets%2Fdesign-kit%2Ficon-green.svg" alt="Nuxt logo" width="512" height="512"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nuxt 3 + Nuxt 4 compatible&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;vue-pdf-export&lt;/code&gt; supports SSR-safe package imports in both &lt;strong&gt;Nuxt 3&lt;/strong&gt; and &lt;strong&gt;Nuxt 4&lt;/strong&gt;. PDF generation itself uses browser APIs and must run on the client.&lt;/p&gt;

&lt;p&gt;Validated integration paths include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;server-side package import&lt;/li&gt;
&lt;li&gt;Nuxt 3 SSR build/runtime&lt;/li&gt;
&lt;li&gt;Nuxt 4 SSR build/runtime&lt;/li&gt;
&lt;li&gt;hydration&lt;/li&gt;
&lt;li&gt;client navigation&lt;/li&gt;
&lt;li&gt;lazy-loaded PDF consumers&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;ClientOnly&amp;gt;&lt;/code&gt; integration&lt;/li&gt;
&lt;li&gt;client-event composable generation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Browser-heavy PDF dependencies are loaded from generation paths instead of being eagerly evaluated during the server import path.&lt;/p&gt;

&lt;h4&gt;
  
  
  Recommended component pattern
&lt;/h4&gt;

&lt;p&gt;Use &lt;code&gt;&amp;lt;ClientOnly&amp;gt;&lt;/code&gt; when the export UI itself does not need to render on the server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Html2Pdf&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export/style.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pdfRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;InstanceType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;Html2Pdf&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;exportPdf&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;pdfRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;generatePdf&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ClientOnly&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt;
      &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;"pdfRef"&lt;/span&gt;
      &lt;span class="na"&gt;filename=&lt;/span&gt;&lt;span class="s"&gt;"nuxt-report.pdf"&lt;/span&gt;
      &lt;span class="na"&gt;:enable-download=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
      &lt;span class="na"&gt;manual-pagination&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;#pdf-content&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;article&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Nuxt report&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;This PDF is generated in the browser.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/Html2Pdf&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"exportPdf"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Export PDF&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/ClientOnly&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Lazy import on a client event
&lt;/h4&gt;

&lt;p&gt;For routes where PDF functionality is only used after a user action, you can lazy-load the package from a client event:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;loadPdfTools&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pdf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is optional. A normal package import is SSR-safe, but lazy loading can help keep PDF-specific code out of paths that never use it.&lt;/p&gt;

&lt;h4&gt;
  
  
  Composable generation
&lt;/h4&gt;

&lt;p&gt;Call browser-side generation from mounted/client UI events rather than server setup work.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useHtml2Pdf&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useHtml2Pdf&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;onExportClick&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cm"&gt;/* browser DOM/content options */&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  What not to do
&lt;/h4&gt;

&lt;p&gt;Do not start PDF generation while Nuxt is rendering on the server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Avoid server-side generation calls.&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// generatePdf() should not be called here.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The supported boundary is simple: &lt;strong&gt;imports may happen during SSR; PDF generation happens in the browser.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nuxt compatibility:&lt;/strong&gt; Nuxt 3 and Nuxt 4 have automated SSR import/hydration fixture coverage. Package import is SSR-safe; actual PDF generation must run in the browser.&lt;/p&gt;
&lt;/blockquote&gt;







&lt;h3&gt;
  
  
  PDF Paper Formats and Orientation
&lt;/h3&gt;

&lt;p&gt;The component accepts a named &lt;code&gt;pdf-format&lt;/code&gt; string and &lt;code&gt;pdf-orientation="portrait|landscape"&lt;/code&gt; (also &lt;code&gt;p|l&lt;/code&gt;). Default format is &lt;code&gt;a4&lt;/code&gt;, default orientation is portrait.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt; &lt;span class="na"&gt;pdf-format=&lt;/span&gt;&lt;span class="s"&gt;"a3"&lt;/span&gt; &lt;span class="na"&gt;pdf-orientation=&lt;/span&gt;&lt;span class="s"&gt;"landscape"&lt;/span&gt; &lt;span class="na"&gt;:manual-pagination=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="na"&gt;#pdf-content&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;article&amp;gt;&lt;/span&gt;Landscape document&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/Html2Pdf&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The source normalizes A0–A10, B0–B10, C0–C10, &lt;code&gt;dl&lt;/code&gt;, &lt;code&gt;letter&lt;/code&gt;, &lt;code&gt;government-letter&lt;/code&gt;, &lt;code&gt;legal&lt;/code&gt;, &lt;code&gt;junior-legal&lt;/code&gt;, &lt;code&gt;ledger&lt;/code&gt;, &lt;code&gt;tabloid&lt;/code&gt;, and &lt;code&gt;credit-card&lt;/code&gt;. The selectable-text adapter and playground picker use these names. Small paper needs compact content; large or complex layouts still need viewer checks.&lt;/p&gt;

&lt;p&gt;For custom dimensions, pass a numeric pair through the lower-level jsPDF options. The component's &lt;code&gt;pdfFormat&lt;/code&gt; prop is a string, so do not bind an array to &lt;code&gt;pdf-format&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt;
  &lt;span class="na"&gt;:manual-pagination=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
  &lt;span class="na"&gt;:html-to-pdf-options=&lt;/span&gt;&lt;span class="s"&gt;"{
    jsPDF: { unit: 'mm', format: [100, 180], orientation: 'portrait' },
  }"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="na"&gt;#pdf-content&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;article&amp;gt;&lt;/span&gt;Custom-size document&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/Html2Pdf&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When using automatic &lt;a href="https://vue-pdf-export-docs.vercel.app/get-started/pagination" rel="noopener noreferrer"&gt;component pagination&lt;/a&gt;, calculate &lt;code&gt;paginate-elements-by-height&lt;/code&gt; as the usable &lt;strong&gt;CSS pixel&lt;/strong&gt; budget for the effective format, orientation, margins and header/footer heights. The playground computes this for its selected geometry. The selectable-text A3 fractional-boundary loop fix prevents a former repeated-page hang; final visual acceptance for all combinations still needs browser inspection.&lt;/p&gt;




&lt;h2&gt;
  
  
  API
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Html2Pdf Component
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Core props
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Prop&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;renderMode&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;`'canvas' \&lt;/td&gt;
&lt;td&gt;'text'`&lt;/td&gt;
&lt;td&gt;&lt;code&gt;'canvas'&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;showLayout&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;boolean&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Show export layout.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;floatLayout&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;boolean&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Use fixed/floating export layout.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;enableDownload&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;boolean&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Download after generation.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;previewModal&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;boolean&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Show PDF preview modal.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;filename&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;timestamp fallback&lt;/td&gt;
&lt;td&gt;PDF filename.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pdfQuality&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;number&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Default html2canvas scale; mainly relevant to canvas mode/images.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pdfFormat&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;PDF format&lt;/td&gt;
&lt;td&gt;&lt;code&gt;'a4'&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;PDF format.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pdfOrientation&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;`'portrait' \&lt;/td&gt;
&lt;td&gt;'landscape'`&lt;/td&gt;
&lt;td&gt;&lt;code&gt;'portrait'&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pdfContentWidth&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;'800px'&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Export wrapper width.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;htmlToPdfOptions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Html2PdfOptions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;package defaults&lt;/td&gt;
&lt;td&gt;Advanced options.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;metadata&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;PdfMetadataOptions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;undefined&lt;/td&gt;
&lt;td&gt;PDF metadata.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;compress&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;boolean&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;undefined&lt;/td&gt;
&lt;td&gt;jsPDF stream compression override.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;security&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;PdfSecurityOptions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;undefined&lt;/td&gt;
&lt;td&gt;Password/security configuration.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;manualPagination&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;boolean&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Manual pagination mode.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;paginateElementsByHeight&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;number&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;undefined&lt;/td&gt;
&lt;td&gt;Positive finite height enables smart DOM pagination; otherwise the renderer handles basic page flow.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;showLoader&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;boolean&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Show loader.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;loaderText&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;'Generating PDF...'&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Loader text.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;watermark&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;WatermarkOptions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;disabled&lt;/td&gt;
&lt;td&gt;Watermark configuration.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;collectMetrics&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;boolean&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Collect total/stage/per-page generation timing metrics.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;styling&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;PdfStylingOptions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;disabled/defaults&lt;/td&gt;
&lt;td&gt;Apply export-only page/body styling, scoped CSS, theme and auto-fit controls.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Header and footer props are documented in their dedicated sections.&lt;/p&gt;

&lt;p&gt;Additional component options include &lt;code&gt;header?: HeaderOptions&lt;/code&gt;, &lt;code&gt;footer?: FooterOptions&lt;/code&gt;, &lt;code&gt;composition?: PdfCompositionOptions&lt;/code&gt;, &lt;code&gt;paginationDebug?: boolean&lt;/code&gt;, &lt;code&gt;pdfTemplate?: PdfTemplateSource&lt;/code&gt;, and &lt;code&gt;templatePosition?: "prepend" | "append" | "both"&lt;/code&gt;. See &lt;a href="https://vue-pdf-export-docs.vercel.app/api/headers" rel="noopener noreferrer"&gt;headers&lt;/a&gt;, &lt;a href="https://vue-pdf-export-docs.vercel.app/api/footers" rel="noopener noreferrer"&gt;footers&lt;/a&gt;, &lt;a href="https://vue-pdf-export-docs.vercel.app/api/composition" rel="noopener noreferrer"&gt;composition&lt;/a&gt;, and &lt;a href="https://vue-pdf-export-docs.vercel.app/get-started/pagination" rel="noopener noreferrer"&gt;pagination&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The component also accepts &lt;code&gt;fonts&lt;/code&gt;, &lt;code&gt;autoOptimize&lt;/code&gt;, and &lt;code&gt;svgMode&lt;/code&gt;. See the &lt;a href="https://vue-pdf-export-docs.vercel.app/use-cases/media-typography" rel="noopener noreferrer"&gt;media and typography guide&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Exposed methods
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Html2PdfInstance&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;generatePdf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;overrides&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;composition&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;PdfCompositionOptions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Blob&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;generatePdfArrayBuffer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;ArrayBuffer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;generatePdfBase64&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;PdfBase64Options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;print&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;closePreview&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;resetPagination&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;cancelGeneration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;generatePdfArrayBuffer()&lt;/code&gt; and &lt;code&gt;generatePdfBase64()&lt;/code&gt; reuse the generated PDF Blob and do not run a second renderer.&lt;/p&gt;

&lt;p&gt;See &lt;a href="https://vue-pdf-export-docs.vercel.app/api/programmatic-api" rel="noopener noreferrer"&gt;Programmatic API&lt;/a&gt; for output examples and cancellation details.&lt;/p&gt;




&lt;h3&gt;
  
  
  Core Props
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Prop&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;renderMode&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;`'canvas' \&lt;/td&gt;
&lt;td&gt;'text'`&lt;/td&gt;
&lt;td&gt;&lt;code&gt;'canvas'&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;showLayout&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;boolean&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Show export layout.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;floatLayout&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;boolean&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Use fixed/floating export layout.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;enableDownload&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;boolean&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Download after generation.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;previewModal&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;boolean&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Show PDF preview modal.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;filename&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;timestamp fallback&lt;/td&gt;
&lt;td&gt;PDF filename.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pdfQuality&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;number&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Default html2canvas scale; mainly relevant to canvas mode/images.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pdfFormat&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;PDF format&lt;/td&gt;
&lt;td&gt;&lt;code&gt;'a4'&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;PDF format.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pdfOrientation&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;`'portrait' \&lt;/td&gt;
&lt;td&gt;'landscape'`&lt;/td&gt;
&lt;td&gt;&lt;code&gt;'portrait'&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pdfContentWidth&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;'800px'&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Export wrapper width.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;htmlToPdfOptions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Html2PdfOptions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;package defaults&lt;/td&gt;
&lt;td&gt;Advanced options.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;metadata&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;PdfMetadataOptions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;undefined&lt;/td&gt;
&lt;td&gt;PDF metadata.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;compress&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;boolean&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;undefined&lt;/td&gt;
&lt;td&gt;jsPDF stream compression override.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;security&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;PdfSecurityOptions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;undefined&lt;/td&gt;
&lt;td&gt;Password/security configuration.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;manualPagination&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;boolean&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Manual pagination mode.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;paginateElementsByHeight&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;number&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;undefined&lt;/td&gt;
&lt;td&gt;Positive finite height activates the smart DOM pagination planner; otherwise the renderer handles basic page flow.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;showLoader&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;boolean&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Show loader.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;loaderText&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;'Generating PDF...'&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Loader text.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;watermark&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;WatermarkOptions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;disabled&lt;/td&gt;
&lt;td&gt;Watermark configuration.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;collectMetrics&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;boolean&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Collect total, stage, and per-page generation metrics.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fonts&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;PdfFontSource[]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;undefined&lt;/td&gt;
&lt;td&gt;Register TTF/TrueType-outline OTF faces for selectable text.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;autoOptimize&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;`boolean \&lt;/td&gt;
&lt;td&gt;PdfImageOptimizationOptions`&lt;/td&gt;
&lt;td&gt;disabled&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;svgMode&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;`'auto' \&lt;/td&gt;
&lt;td&gt;'preserve' \&lt;/td&gt;
&lt;td&gt;'rasterize'`&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;styling&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;PdfStylingOptions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;disabled/defaults&lt;/td&gt;
&lt;td&gt;Export-only page/body styles, scoped CSS, external stylesheets, theme and auto-fit controls.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Header and footer props are documented in their dedicated sections.&lt;/p&gt;

&lt;p&gt;See &lt;a href="https://vue-pdf-export-docs.vercel.app/use-cases/media-typography" rel="noopener noreferrer"&gt;fonts, charts, SVG and images&lt;/a&gt; for examples and limitations of the media options above.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Additional prop&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;header&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;HeaderOptions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Built-in header or slot layout and page targeting.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;footer&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;FooterOptions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Built-in footer or slot layout.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;composition&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;PdfCompositionOptions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Prepend and/or append existing PDF pages.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;pdfTemplate&lt;/code&gt;, &lt;code&gt;templatePosition&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;PdfTemplateSource&lt;/code&gt;, `'prepend'&lt;/td&gt;
&lt;td&gt;'append'&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;{% raw %}&lt;code&gt;paginationDebug&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;boolean&lt;/code&gt;, default &lt;code&gt;false&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Live planner overlay and diagnostic events.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  Advanced html2pdf Options
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;htmlToPdfOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;enableLinks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="na"&gt;pagebreak&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;legacy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;jpeg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;quality&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="na"&gt;html2canvas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;useCORS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#FFFFFF&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="na"&gt;jsPDF&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;unit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;a4&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;orientation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;p&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;hotfixes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;px_scaling&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;optimizeForBrowser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt; &lt;span class="na"&gt;:html-to-pdf-options=&lt;/span&gt;&lt;span class="s"&gt;"htmlToPdfOptions"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Important precedence rules:&lt;/p&gt;

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




&lt;h3&gt;
  
  
  PDF Headers in Vue
&lt;/h3&gt;

&lt;p&gt;Set &lt;code&gt;enabled: true&lt;/code&gt; for a built-in header:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Html2Pdf&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;HeaderOptions&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export/style.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HeaderOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;58&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;pages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;all&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Quarterly report&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;showLogo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;logoUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/logo.png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;logoWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;logoHeight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#F5FBF9&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;textColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#17324A&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt; &lt;span class="na"&gt;:header=&lt;/span&gt;&lt;span class="s"&gt;"header"&lt;/span&gt; &lt;span class="na"&gt;:manual-pagination=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;#pdf-content&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;article&amp;gt;&lt;/span&gt;Document content&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/Html2Pdf&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;enabled&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Render the header.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;height&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;58&lt;/code&gt; via component&lt;/td&gt;
&lt;td&gt;Reserved height in the active jsPDF unit (&lt;code&gt;px&lt;/code&gt; by default).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pages&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;'all'&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;'all'&lt;/code&gt;, &lt;code&gt;'first'&lt;/code&gt;, &lt;code&gt;'last'&lt;/code&gt;, &lt;code&gt;'except-first'&lt;/code&gt;, or a 1-based page number array.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;text&lt;/code&gt; / &lt;code&gt;html&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;empty&lt;/td&gt;
&lt;td&gt;Plain text or trusted HTML; non-empty HTML takes precedence.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;showLogo&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Show an available logo.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;logoUrl&lt;/code&gt; / &lt;code&gt;logoDataUrl&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;empty&lt;/td&gt;
&lt;td&gt;Logo URL or data URL.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;logoWidth&lt;/code&gt; / &lt;code&gt;logoHeight&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;28&lt;/code&gt; CSS px&lt;/td&gt;
&lt;td&gt;Maximum logo box, preserving aspect ratio.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;backgroundColor&lt;/code&gt; / &lt;code&gt;textColor&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;#F8F9FA&lt;/code&gt; / &lt;code&gt;#5F6368&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Built-in layer colors.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Header height reserves space only on targeted generated pages. Explicit top margins still apply. Sanitize user-authored HTML before assigning it to &lt;code&gt;html&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Vue header slot
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Html2Pdf&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ReportHeader&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./ReportHeader.vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export/style.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt;
    &lt;span class="na"&gt;:header=&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;{ height: 58, pages: 'except-first' }"
    :manual-pagination="true"
  &amp;gt;
    &lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;#pdf-content&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;article&amp;gt;&lt;/span&gt;Report body&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="na"&gt;#pdf-header=&lt;/span&gt;&lt;span class="s"&gt;"{ pageNumber, totalPages, orientation }"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;ReportHeader&lt;/span&gt;
        &lt;span class="na"&gt;:page-number=&lt;/span&gt;&lt;span class="s"&gt;"pageNumber"&lt;/span&gt;
        &lt;span class="na"&gt;:total-pages=&lt;/span&gt;&lt;span class="s"&gt;"totalPages"&lt;/span&gt;
        &lt;span class="na"&gt;:orientation=&lt;/span&gt;&lt;span class="s"&gt;"orientation"&lt;/span&gt;
      &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/Html2Pdf&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example, &lt;code&gt;ReportHeader.vue&lt;/code&gt; can keep its own logo and scoped styles:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nx"&gt;defineProps&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;pageNumber&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;totalPages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;orientation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"report-header"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/logo.png"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Company"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"100"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"28"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;strong&amp;gt;&lt;/span&gt;Quarterly report&lt;span class="nt"&gt;&amp;lt;/strong&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;small&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;orientation&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt; · &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;pageNumber&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;/&lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;totalPages&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/small&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;style&lt;/span&gt; &lt;span class="na"&gt;scoped&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nc"&gt;.report-header&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;box-sizing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;border-box&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;16px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#f5fbf9&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#17324a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.report-header&lt;/span&gt; &lt;span class="nt"&gt;small&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;style&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The slot activates the header and owns visible markup. Object text, HTML, logo and colors are not injected into it; object &lt;code&gt;height&lt;/code&gt; and &lt;code&gt;pages&lt;/code&gt; still control layout and targeting. Give the component root &lt;code&gt;width: 100%&lt;/code&gt; and appropriate padding. Scoped and inherited computed styles are snapshotted, subject to renderer support. Text mode emits supported text and shapes as PDF operations; Canvas mode captures an image. Inspect complex CSS and fonts in a viewer.&lt;/p&gt;

&lt;p&gt;See &lt;a href="https://vue-pdf-export-docs.vercel.app/api/footers" rel="noopener noreferrer"&gt;footers&lt;/a&gt; and &lt;a href="https://vue-pdf-export-docs.vercel.app/get-started/pagination" rel="noopener noreferrer"&gt;pagination&lt;/a&gt; for related configuration.&lt;/p&gt;




&lt;h3&gt;
  
  
  PDF Footers in Vue
&lt;/h3&gt;

&lt;p&gt;The built-in footer appears on every generated page. Footers have no separate &lt;code&gt;pages&lt;/code&gt; selector.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Html2Pdf&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;FooterOptions&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export/style.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;footer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FooterOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;58&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;useHtml&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;html&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;strong&amp;gt;My company&amp;lt;/strong&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Page {n} of {total}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt; &lt;span class="na"&gt;:footer=&lt;/span&gt;&lt;span class="s"&gt;"footer"&lt;/span&gt; &lt;span class="na"&gt;:manual-pagination=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;#pdf-content&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;article&amp;gt;&lt;/span&gt;Document content&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/Html2Pdf&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;enabled&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Render the footer.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;height&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;58&lt;/code&gt; via component&lt;/td&gt;
&lt;td&gt;Reserved height in the active jsPDF unit (&lt;code&gt;px&lt;/code&gt; by default).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;useHtml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;component compatibility default &lt;code&gt;true&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;HTML/image or plain-text built-in footer.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;template&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Page {n} of {total}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Generated-page number text.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;text&lt;/code&gt; / &lt;code&gt;html&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;empty&lt;/td&gt;
&lt;td&gt;Body content; non-empty HTML takes precedence in HTML mode.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;showLogo&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Show an available logo.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;logoUrl&lt;/code&gt; / &lt;code&gt;logoDataUrl&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;empty&lt;/td&gt;
&lt;td&gt;Logo URL or data URL.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;logoWidth&lt;/code&gt; / &lt;code&gt;logoHeight&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;26&lt;/code&gt; CSS px&lt;/td&gt;
&lt;td&gt;Maximum logo box.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;backgroundColor&lt;/code&gt; / &lt;code&gt;textColor&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;#F8F9FA&lt;/code&gt; / &lt;code&gt;#5F6368&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Built-in layer colors.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Only use trusted HTML, or sanitize user-authored content first. A remote logo must be accessible under browser CORS rules.&lt;/p&gt;

&lt;h4&gt;
  
  
  Vue footer slot
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Html2Pdf&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export/style.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt; &lt;span class="na"&gt;:footer=&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;{ height: 58 }" :manual-pagination="true"&amp;gt;
    &lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;#pdf-content&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;article&amp;gt;&lt;/span&gt;Document content&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="na"&gt;#pdf-footer=&lt;/span&gt;&lt;span class="s"&gt;"{ pageNumber, totalPages }"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"report-footer"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&lt;/span&gt;My company&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&lt;/span&gt;Page &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;pageNumber&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt; of &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;totalPages&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/Html2Pdf&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;style&lt;/span&gt; &lt;span class="na"&gt;scoped&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nc"&gt;.report-footer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;box-sizing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;border-box&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;space-between&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;style&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The slot activates the footer and owns visible markup. Object text, HTML, logo and template do not appear unless you render them. &lt;code&gt;orientation&lt;/code&gt; is also a slot prop. Text mode renders supported slot text as PDF text; Canvas mode captures an image. Chrome may allow OCR selection on an image PDF, so selection alone does not prove native text is present. Scoped and inherited styles are snapshotted within renderer limits.&lt;/p&gt;

&lt;p&gt;The built-in &lt;code&gt;{total}&lt;/code&gt; and slot &lt;code&gt;totalPages&lt;/code&gt; count generated pages before &lt;a href="https://vue-pdf-export-docs.vercel.app/api/composition" rel="noopener noreferrer"&gt;composition&lt;/a&gt;, excluding inserted template pages.&lt;/p&gt;




&lt;h3&gt;
  
  
  Security
&lt;/h3&gt;

&lt;p&gt;Create password-protected PDFs with the &lt;code&gt;security&lt;/code&gt; prop.&lt;/p&gt;

&lt;h4&gt;
  
  
  Security options
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Option&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;enabled&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;boolean&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;compatibility-resolved&lt;/td&gt;
&lt;td&gt;Explicitly enable/disable the direct security layer.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;userPassword&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;''&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Password required to open the PDF.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ownerPassword&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;''&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Owner-level password used by the PDF encryption layer.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;passwordParts&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;`Array&amp;lt;string \&lt;/td&gt;
&lt;td&gt;number&amp;gt;`&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;passwordSeparator&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;''&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Separator used when joining &lt;code&gt;passwordParts&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;permissions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;PdfPermission[]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;viewer-dependent&lt;/td&gt;
&lt;td&gt;Requested PDF permission flags.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PdfSecurityOptions&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;security&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PdfSecurityOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;userPassword&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;open123&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;ownerPassword&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;owner456&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;print&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;copy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt; &lt;span class="na"&gt;:security=&lt;/span&gt;&lt;span class="s"&gt;"security"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Password protection works in both canvas and selectable-text render modes.&lt;/p&gt;

&lt;h4&gt;
  
  
  Permission flags
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;PdfPermission&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;print&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;modify&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;copy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;annot-forms&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Permission&lt;/th&gt;
&lt;th&gt;What it allows&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;print&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Allows printing when the PDF viewer enforces document permissions.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;copy&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Allows text/content copying and extraction when the viewer enforces permissions.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;modify&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Allows document modification/editing when supported by the viewer.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;annot-forms&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Allows annotations and form-related changes when supported by the viewer.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;PDF permission enforcement depends on the PDF viewer. Password encryption is part of the PDF itself, while permission flags rely on viewer compliance.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Security guidance
&lt;/h4&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Important boundaries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;User/open password&lt;/strong&gt; controls opening an encrypted PDF.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Owner password&lt;/strong&gt; is used by the PDF encryption layer for owner-level access/permission configuration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Permission flags are viewer-dependent.&lt;/strong&gt; Some PDF viewers may not enforce them identically.&lt;/li&gt;
&lt;li&gt;Caller-supplied header, footer, and slot HTML is sanitized with DOMPurify before insertion into export staging. Supply trusted, intentional document content; sanitization is not a substitute for application security.&lt;/li&gt;
&lt;li&gt;Remote images are fetched by the browser. Use trusted origins, correct CORS headers, and avoid exposing secrets in image URLs.&lt;/li&gt;
&lt;li&gt;Passwords exist in browser memory while a PDF is being generated. Do not hard-code sensitive production passwords into public frontend source.&lt;/li&gt;
&lt;li&gt;Generated Blob URLs are cleaned up by the component/composable lifecycle, but applications should still avoid retaining generated Blobs longer than necessary.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;vue-pdf-export&lt;/code&gt; 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.&lt;/p&gt;

&lt;h4&gt;
  
  
  Password parts
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;security&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;passwordParts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;15081999&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4821&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;passwordSeparator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates one final open password:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;15081999-4821
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;passwordParts&lt;/code&gt; do not create multiple independent passwords.&lt;/p&gt;

&lt;p&gt;When &lt;code&gt;security&lt;/code&gt; is omitted, compatible raw &lt;code&gt;htmlToPdfOptions.jsPDF.encryption&lt;/code&gt; values are preserved.&lt;/p&gt;

&lt;p&gt;When &lt;code&gt;security.enabled&lt;/code&gt; is explicitly &lt;code&gt;false&lt;/code&gt;, encryption is removed.&lt;/p&gt;

&lt;h4&gt;
  
  
  Security Model &amp;amp; Boundaries
&lt;/h4&gt;

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

&lt;h4&gt;
  
  
  Verified outcomes
&lt;/h4&gt;

&lt;p&gt;The final regression suite verified:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;50-page Canvas generation&lt;/li&gt;
&lt;li&gt;100-page Canvas generation&lt;/li&gt;
&lt;li&gt;Canvas cancellation and recovery&lt;/li&gt;
&lt;li&gt;selectable-text cancellation and recovery&lt;/li&gt;
&lt;li&gt;repeated-image caching in selectable-text mode&lt;/li&gt;
&lt;li&gt;page-bounded Canvas rendering in image-heavy documents&lt;/li&gt;
&lt;li&gt;temporary rendering cleanup after cancellation/generation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The final unit suite completed with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;19 test files passed
106 / 106 tests passed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  What the package provides
&lt;/h4&gt;

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

&lt;h4&gt;
  
  
  What remains the application's responsibility
&lt;/h4&gt;

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

&lt;h4&gt;
  
  
  Important client-side security note
&lt;/h4&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Minifying the npm distribution is useful for package size and distribution hygiene, but it is &lt;strong&gt;not&lt;/strong&gt; a security boundary.&lt;/p&gt;




&lt;h3&gt;
  
  
  Watermarks
&lt;/h3&gt;

&lt;p&gt;The watermark controls below are available in the published package. Choose an explicit &lt;code&gt;layer&lt;/code&gt; when placement matters.&lt;/p&gt;

&lt;p&gt;An enabled watermark without an explicit &lt;code&gt;layer&lt;/code&gt; uses &lt;strong&gt;foreground&lt;/strong&gt;. Set &lt;code&gt;layer: "background"&lt;/code&gt; if the mark should appear behind supported selectable-text page content. Opaque content can cover a background watermark.&lt;/p&gt;

&lt;h4&gt;
  
  
  Design presets
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;design&lt;/code&gt; supplies defaults; every explicit option overrides its preset. For example, &lt;code&gt;classic&lt;/code&gt; can still be used with &lt;code&gt;type: 'image'&lt;/code&gt; and &lt;code&gt;mode: 'repeat'&lt;/code&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Design&lt;/th&gt;
&lt;th&gt;Default appearance&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;classic&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Existing text/image defaults&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;diagonal&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Single angled status text&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;microtext&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Small, visibly repeated text&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;tile&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Repeated medium text&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;logo&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Single subtle image&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;page-background&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Faint image covering selected pages&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;custom&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Explicit fields only&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;WatermarkOptions&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;watermark&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;WatermarkOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;design&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;classic&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;image&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;repeat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;layer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;foreground&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;imageDataUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;logoPngDataUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;rotation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;gapX&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;gapY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;pages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;all&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;imageDataUrl&lt;/code&gt; supports PNG or JPEG data URLs; &lt;code&gt;imageUrl&lt;/code&gt; supports a reachable URL with appropriate CORS. Width and gaps use the configured jsPDF units. The source aspect ratio determines height when omitted. &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; position a single mark; repeated marks use a grid and gaps. A transparent PNG usually gives the cleanest foreground logo. Dense repeated images are composed into a reusable transparent page sheet. Full-page PNG backgrounds can increase file size.&lt;/p&gt;

&lt;p&gt;For a styled stamp, pass a &lt;strong&gt;trusted mounted element&lt;/strong&gt;, for example &lt;code&gt;watermark: { enabled: true, type: 'html', htmlElement: stampRef.value }&lt;/code&gt; after the ref exists. The element is captured as an image once per export. Do not pass an untrusted HTML string. &lt;code&gt;microtext&lt;/code&gt; is visible decoration, not a digital signature or tamper protection.&lt;/p&gt;

&lt;p&gt;Selectable-text output can draw a real background mark behind its PDF content. Canvas output has opaque raster pages and uses a light foreground fallback to keep a requested background mark visible. An opaque content card can cover a selectable-text background mark. See &lt;a href="https://vue-pdf-export-docs.vercel.app/use-cases/media-typography" rel="noopener noreferrer"&gt;media and typography&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Text watermark
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;WatermarkOptions&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;watermark&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;WatermarkOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;layer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;background&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;repeat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CONFIDENTIAL&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;rotation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;fontSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;gapX&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;gapY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt; &lt;span class="na"&gt;:watermark=&lt;/span&gt;&lt;span class="s"&gt;"watermark"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Foreground watermark
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;watermark&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;layer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;foreground&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;single&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;DRAFT&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;rotation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;fontSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Foreground watermarks are drawn onto final PDF pages with jsPDF.&lt;/p&gt;

&lt;h4&gt;
  
  
  Image watermark
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;watermark&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;layer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;foreground&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;image&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;single&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;imageUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/logo.png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;rotation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;180&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A data URL can also be used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;watermark&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;image&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;imageDataUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;data:image/png;base64,...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;imageDataUrl&lt;/code&gt; takes priority over &lt;code&gt;imageUrl&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Per-page watermark targeting
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;watermark&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;INTERNAL&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;pages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;except-first&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Explicit pages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;watermark&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;INTERNAL&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;pages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Supported targets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;all
first
last
except-first
number[]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;h4&gt;
  
  
  Watermark options
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Option&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;enabled&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;boolean&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Enable/disable watermark.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;type&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;`'text' \&lt;/td&gt;
&lt;td&gt;'image' \&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;{% raw %}&lt;code&gt;design&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;preset name&lt;/td&gt;
&lt;td&gt;Optional design defaults; explicit options take precedence.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;layer&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;`'background' \&lt;/td&gt;
&lt;td&gt;'foreground'`&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;mode&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;`'single' \&lt;/td&gt;
&lt;td&gt;'repeat'`&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;text&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Text content.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fontSize&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;number&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Text size.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fontFamily&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Font family.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fontWeight&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;`string \&lt;/td&gt;
&lt;td&gt;number`&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fontStyle&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;`'normal' \&lt;/td&gt;
&lt;td&gt;'bold' \&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;{% raw %}&lt;code&gt;color&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Watermark color.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;imageUrl&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Image URL.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;imageDataUrl&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Data URL/base64 image.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;width&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;number&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Image width.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;height&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;number&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Optional image height.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;opacity&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;number&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Clamped to &lt;code&gt;0..1&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;rotation&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;number&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Rotation in degrees.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;x&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;number&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Horizontal position.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;y&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;number&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Vertical position.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gapX&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;number&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Horizontal repeat gap.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;gapY&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;number&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Vertical repeat gap.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pages&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;PdfPageTarget&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Target pages.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h3&gt;
  
  
  Metadata &amp;amp; Compression
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Metadata options
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Option&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;title&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;PDF document title.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;author&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;PDF author.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;subject&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;PDF subject.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;keywords&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string[]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;PDF keywords.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;creator&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;PDF creator/application value.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PdfMetadataOptions&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PdfMetadataOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Invoice #1024&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;author&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Acme Inc.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Customer invoice&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;keywords&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;invoice&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2026&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;creator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt; &lt;span class="na"&gt;:metadata=&lt;/span&gt;&lt;span class="s"&gt;"metadata"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Metadata is written to PDF document properties and is not rendered as normal visible page content.&lt;/p&gt;

&lt;p&gt;The direct &lt;code&gt;metadata&lt;/code&gt; prop takes priority over &lt;code&gt;htmlToPdfOptions.metadata&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Compression
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt; &lt;span class="na"&gt;:compress=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;compress&lt;/code&gt; controls jsPDF stream compression.&lt;/p&gt;

&lt;p&gt;It does not lower html2canvas resolution or JPEG image quality.&lt;/p&gt;

&lt;p&gt;If omitted, compatible raw &lt;code&gt;htmlToPdfOptions.jsPDF.compress&lt;/code&gt; is preserved.&lt;/p&gt;




&lt;h3&gt;
  
  
  Programmatic API
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Component methods
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Return&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;generatePdf({ composition? }?)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Promise&amp;lt;Blob&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Generate the PDF and optionally override composition.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;generatePdfArrayBuffer()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Promise&amp;lt;ArrayBuffer&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Generate once, then serialize the resulting Blob to binary bytes.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;generatePdfBase64(options?)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Promise&amp;lt;string&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Generate once, then return raw Base64 or an optional PDF data URL.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;print()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Promise&amp;lt;void&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Generate/open the native browser print flow.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;closePreview()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;void&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Close the active preview flow.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;resetPagination()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;void&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Remove automatically inserted page breaks.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cancelGeneration()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;void&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Request cooperative cancellation of active generation.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Html2PdfInstance&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;generatePdf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;overrides&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;composition&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;PdfCompositionOptions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Blob&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;generatePdfArrayBuffer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;ArrayBuffer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;generatePdfBase64&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;PdfBase64Options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;print&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;closePreview&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;resetPagination&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;cancelGeneration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Recommended ref:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pdfRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;InstanceType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;Html2Pdf&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Generate Blob
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;blob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;pdfRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;generatePdf&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To insert existing PDF pages for this call, use &lt;code&gt;await pdfRef.value?.generatePdf({ composition: { prepend: templatePdf, append: templatePdf } })&lt;/code&gt;. The method option wins over the component prop. See &lt;a href="https://vue-pdf-export-docs.vercel.app/api/composition" rel="noopener noreferrer"&gt;PDF composition&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Blob&lt;/code&gt; remains the recommended default for downloads, previews, object URLs, and very large PDFs.&lt;/p&gt;

&lt;h4&gt;
  
  
  Generate ArrayBuffer
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;arrayBuffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;pdfRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;generatePdfArrayBuffer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use ArrayBuffer when you need raw PDF bytes for binary APIs, workers, storage, cryptographic processing, or transports that accept binary data.&lt;/p&gt;

&lt;h4&gt;
  
  
  Generate Base64
&lt;/h4&gt;

&lt;p&gt;Raw Base64:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;base64&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;pdfRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;generatePdfBase64&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;PDF data URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dataUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;pdfRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;generatePdfBase64&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;dataUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Base64 is convenient for string-only transports, but it is larger than the binary payload and requires additional conversion memory. Prefer Blob or ArrayBuffer for large PDFs.&lt;/p&gt;

&lt;p&gt;The ArrayBuffer and Base64 methods reuse the normal PDF generation flow and serialize the generated Blob. They do &lt;strong&gt;not&lt;/strong&gt; run a second PDF renderer.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For pure programmatic output, disable automatic browser-side download/preview with &lt;code&gt;:enable-download="false"&lt;/code&gt; and &lt;code&gt;:preview-modal="false"&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Low-level output serialization
&lt;/h4&gt;

&lt;p&gt;The output helpers are also available directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;pdfBlobToArrayBuffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;pdfBlobToBase64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;serializePdfOutput&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;pdfBlobToArrayBuffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;base64&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;pdfBlobToBase64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dataUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;pdfBlobToBase64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;dataUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;serializePdfOutput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;arraybuffer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Supported output formats are &lt;code&gt;blob&lt;/code&gt;, &lt;code&gt;arraybuffer&lt;/code&gt;, and &lt;code&gt;base64&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Print
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;pdfRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Print works through the browser print flow in both Canvas and selectable-text rendering modes.&lt;/p&gt;

&lt;h4&gt;
  
  
  Close preview
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;pdfRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;closePreview&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Reset automatic pagination
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;pdfRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;resetPagination&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This removes only automatically inserted page breaks.&lt;/p&gt;

&lt;h4&gt;
  
  
  Cancel active generation
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;pdfRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;cancelGeneration&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;cancelGeneration()&lt;/code&gt; requests cooperative cancellation of the current export.&lt;/p&gt;

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

&lt;h4&gt;
  
  
  Composable
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useHtml2Pdf&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;progress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;stage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;progressState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;pdfUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;lastResult&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;download&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;print&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;cleanup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useHtml2Pdf&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Loader, Progress, Metrics, Events &amp;amp; Slots
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Built-in loader
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt; &lt;span class="na"&gt;:show-loader=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="na"&gt;loader-text=&lt;/span&gt;&lt;span class="s"&gt;"Generating PDF..."&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Disable it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt; &lt;span class="na"&gt;:show-loader=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Numeric progress
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;progress=&lt;/span&gt;&lt;span class="s"&gt;"onProgress"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;onProgress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is generation-stage progress, not byte-level network progress.&lt;/p&gt;

&lt;h4&gt;
  
  
  Rich progress stages
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;progress-stage=&lt;/span&gt;&lt;span class="s"&gt;"onProgressStage"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PdfProgressState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;onProgressStage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PdfProgressState&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;progress&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Current stages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;idle
pagination
images
preparing
rendering
watermark
header
footer
metadata
serializing
complete
error
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Generation metrics
&lt;/h4&gt;

&lt;p&gt;Metrics are opt-in. When disabled, metrics collection does not add generation work.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt; &lt;span class="na"&gt;:collect-metrics=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;generation-complete=&lt;/span&gt;&lt;span class="s"&gt;"onGenerationComplete"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PdfGenerationCompletePayload&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;onGenerationComplete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PdfGenerationCompletePayload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;metrics&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A completed generation can expose total generation time, stage timings, per-page timings, render mode, page count, and generated Blob size.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;GeneratePdfResult&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;jsPDF&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Blob&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;metrics&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;PdfGenerationMetrics&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use timing data for profiling and regression checks rather than as a hard real-time performance guarantee.&lt;/p&gt;

&lt;h4&gt;
  
  
  Custom loader
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Html2Pdf&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="na"&gt;#loader=&lt;/span&gt;&lt;span class="s"&gt;"{ progress, loading, stage, progressState }"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"loading"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;stage&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt; - &lt;span class="si"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;progress&lt;/span&gt; &lt;span class="si"&gt;}}&lt;/span&gt;%
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/Html2Pdf&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Slot values:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;progress&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;number&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;loading&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;boolean&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;stage&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;PdfProgressStage&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;progressState&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;PdfProgressState&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  Events
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt;
  &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;progress=&lt;/span&gt;&lt;span class="s"&gt;"onProgress"&lt;/span&gt;
  &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;progress-stage=&lt;/span&gt;&lt;span class="s"&gt;"onProgressStage"&lt;/span&gt;
  &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;generation-complete=&lt;/span&gt;&lt;span class="s"&gt;"onGenerationComplete"&lt;/span&gt;
  &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;startPagination=&lt;/span&gt;&lt;span class="s"&gt;"onStartPagination"&lt;/span&gt;
  &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;hasPaginated=&lt;/span&gt;&lt;span class="s"&gt;"onPaginated"&lt;/span&gt;
  &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;beforeDownload=&lt;/span&gt;&lt;span class="s"&gt;"onBeforeDownload"&lt;/span&gt;
  &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;hasDownloaded=&lt;/span&gt;&lt;span class="s"&gt;"onDownloaded"&lt;/span&gt;
  &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;closed=&lt;/span&gt;&lt;span class="s"&gt;"onClosed"&lt;/span&gt;
  &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;error=&lt;/span&gt;&lt;span class="s"&gt;"onError"&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Event&lt;/th&gt;
&lt;th&gt;Payload&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;progress&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;number&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Numeric generation progress.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;progressStage&lt;/code&gt; / &lt;code&gt;@progress-stage&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;PdfProgressState&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Named stage and progress.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;generationComplete&lt;/code&gt; / &lt;code&gt;@generation-complete&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;PdfGenerationCompletePayload&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Generation finished; includes opt-in metrics when enabled.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;startPagination&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;td&gt;Pagination started.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;hasPaginated&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;td&gt;Pagination completed.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;beforeDownload&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;BeforeDownloadPayload&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Emitted before generation.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;hasDownloaded&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Blob&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Generated Blob is available.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;closed&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;td&gt;Preview/generation flow closed.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;error&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Error&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Generation or print error.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;paginationBreak&lt;/code&gt; / &lt;code&gt;@pagination-break&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;PdfPaginationDiagnostic&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A planned break; emitted with &lt;code&gt;paginationDebug&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;paginationWarning&lt;/code&gt; / &lt;code&gt;@pagination-warning&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;PdfPaginationDiagnostic&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;An oversized or other planning warning; debug only.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;paginationComplete&lt;/code&gt; / &lt;code&gt;@pagination-complete&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;PdfPaginationDiagnostic[]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;All decisions for this planning pass; debug only.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  Slots
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Slot&lt;/th&gt;
&lt;th&gt;Required&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pdf-content&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;HTML converted to PDF.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;loader&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;Custom loader with &lt;code&gt;{ progress, loading, stage, progressState }&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pdf-header&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;Vue markup for each targeted header page; &lt;code&gt;{ pageNumber, totalPages, orientation }&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pdf-footer&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;Vue markup for each generated footer page; same context.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The layer slots activate their layers, own visible content and render differently in &lt;a href="https://vue-pdf-export-docs.vercel.app/get-started/rendering-modes" rel="noopener noreferrer"&gt;Canvas versus text mode&lt;/a&gt;. Give the slot root full width and explicit padding. &lt;code&gt;header.height&lt;/code&gt;, &lt;code&gt;header.pages&lt;/code&gt; and &lt;code&gt;footer.height&lt;/code&gt; still apply. See copyable &lt;a href="https://vue-pdf-export-docs.vercel.app/api/headers" rel="noopener noreferrer"&gt;header&lt;/a&gt; and &lt;a href="https://vue-pdf-export-docs.vercel.app/api/footers" rel="noopener noreferrer"&gt;footer&lt;/a&gt; examples, and &lt;a href="https://vue-pdf-export-docs.vercel.app/get-started/pagination" rel="noopener noreferrer"&gt;pagination diagnostics&lt;/a&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  TypeScript
&lt;/h3&gt;

&lt;p&gt;The package ships TypeScript declarations.&lt;/p&gt;

&lt;p&gt;The TypeScript declarations include &lt;code&gt;PdfCompositionOptions&lt;/code&gt;, &lt;code&gt;PdfTemplateSource&lt;/code&gt;, &lt;code&gt;PdfPaginationDiagnostic&lt;/code&gt;, and &lt;code&gt;PdfPaginationDiagnosticType&lt;/code&gt;. See the &lt;a href="https://vue-pdf-export-docs.vercel.app/api/typescript" rel="noopener noreferrer"&gt;current TypeScript documentation&lt;/a&gt; for additional details.&lt;/p&gt;

&lt;p&gt;Common types:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;BeforeDownloadPayload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;FooterMode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;FooterOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;PdfCompositionOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;PdfTemplateSource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;PdfPaginationDiagnostic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;PdfPaginationDiagnosticType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;GeneratePdfResult&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;HeaderOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Html2CanvasOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Html2PdfOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Html2PdfProps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;JsPdfOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;PdfAutoFitOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;PdfBase64Options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;PdfEncryptionOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;PdfFormat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;PdfGenerationCompletePayload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;PdfGenerationMetrics&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;PdfImageOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;PdfMargin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;PdfMetadataOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;PdfOrientation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;PdfOutputFormat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;PdfPageBreakOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;PdfPageContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;PdfPageTarget&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;PdfPermission&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;PdfProgressStage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;PdfProgressState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;PdfRenderMode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;PdfSecurityOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;PdfSerializedOutput&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;PdfStyle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;PdfStylingOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;WatermarkLayer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;WatermarkMode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;WatermarkOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;WatermarkType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Render mode type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;PdfRenderMode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;canvas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output types:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;PdfOutputFormat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;blob&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;arraybuffer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;base64&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;PdfBase64Options&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;dataUrl&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;PdfSerializedOutput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Blob&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;ArrayBuffer&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Useful helpers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;createPdfOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;normalizePdfFilename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;pdfBlobToArrayBuffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;pdfBlobToBase64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;resolvePdfPages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;serializePdfOutput&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Filename Normalization
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;normalizePdfFilename&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;normalizePdfFilename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;invoice:/customer?2026&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// invoice--customer-2026.pdf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Normalization:&lt;/p&gt;

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

&lt;p&gt;Examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;normalizePdfFilename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;report&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// report.pdf&lt;/span&gt;

&lt;span class="nf"&gt;normalizePdfFilename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;report.PDF&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// report.pdf&lt;/span&gt;

&lt;span class="nf"&gt;normalizePdfFilename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CON&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// _CON.pdf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  PDF Styling &amp;amp; data-pdf-ignore
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Exclude content from the PDF
&lt;/h4&gt;

&lt;p&gt;Use &lt;code&gt;data-pdf-ignore&lt;/code&gt; for controls, helper UI, debug panels, buttons, or any subtree that should stay visible in the application but not appear in the generated PDF.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Invoice&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;data-pdf-ignore&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Edit invoice&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;aside&lt;/span&gt; &lt;span class="na"&gt;data-pdf-ignore=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    This entire subtree is excluded from the PDF.
  &lt;span class="nt"&gt;&amp;lt;/aside&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;data-pdf-ignore=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Explicit false keeps this content in the PDF.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Markup&lt;/th&gt;
&lt;th&gt;PDF behavior&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;data-pdf-ignore&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;excluded&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;data-pdf-ignore="true"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;excluded&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;data-pdf-ignore="false"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;included&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Ignored content is removed only from the temporary export copy and is also excluded from export pagination measurements.&lt;/p&gt;

&lt;h4&gt;
  
  
  Export-only styling
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;PdfPageContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;PdfStyle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;PdfStylingOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bodyStyle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PdfStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;16px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;fontSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;14px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#17324A&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;styling&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PdfStylingOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="na"&gt;pageBackground&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#FFF8E7&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;bodyBackground&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#F8FAFC&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="na"&gt;pageClass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;invoice-page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;bodyClass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;invoice-body&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="na"&gt;pageStyle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;pageNumber&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;PdfPageContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;24px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2px solid #DCE7E9&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;borderRadius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;12px&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pageNumber&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#FFF7ED&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#FFFFFF&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;

  &lt;span class="nx"&gt;bodyStyle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="na"&gt;cssText&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    .invoice-title {
      font-size: 28px;
      letter-spacing: -0.02em;
    }

    .screen-only {
      display: none;
    }
  `&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="na"&gt;printStylesheetUrls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/pdf/invoice-print.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;

  &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="na"&gt;autoFit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;minScale&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;maxScale&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;allowUpscale&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt; &lt;span class="na"&gt;:styling=&lt;/span&gt;&lt;span class="s"&gt;"styling"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="na"&gt;#pdf-content&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;article&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"invoice-title"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Invoice&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"screen-only"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Application action&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/Html2Pdf&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Styling options
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Option&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;enabled&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;boolean&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Master styling switch.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pageBackground&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;PDF page surface background.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;bodyBackground&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Inner body/content surface background.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pageClass&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Export-only page class names.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;bodyClass&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Export-only body class names.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pageStyle&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;`PdfStyle \&lt;/td&gt;
&lt;td&gt;PdfStyleResolver`&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;bodyStyle&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;PdfStyle&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Static body styles.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cssText&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Export-only scoped CSS text.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;stylesheetUrls&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string[]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;External export stylesheet URLs.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;printStylesheetUrls&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string[]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;External print/export stylesheet URLs.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;theme&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;`'current' \&lt;/td&gt;
&lt;td&gt;'light' \&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;{% raw %}&lt;code&gt;autoFit&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;`boolean \&lt;/td&gt;
&lt;td&gt;PdfAutoFitOptions`&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Temporary export styles, themes, stylesheets, and staging DOM are cleaned up after generation.&lt;/p&gt;

&lt;h4&gt;
  
  
  Customize the built-in preview and loader
&lt;/h4&gt;

&lt;p&gt;In the current documentation version, the built-in preview and loader inherit &lt;code&gt;--vue-pdf-*&lt;/code&gt; CSS variables from an ancestor of &lt;code&gt;&amp;lt;Html2Pdf&amp;gt;&lt;/code&gt;. They have defaults, so theming is optional. These variables style package UI; they do &lt;strong&gt;not&lt;/strong&gt; style the content inside &lt;code&gt;#pdf-content&lt;/code&gt; or the generated PDF. Use your document CSS and the &lt;code&gt;styling&lt;/code&gt; option above for the exported pages.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Html2Pdf&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export/style.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pdfRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;InstanceType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;Html2Pdf&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"report-export"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"pdfRef?.generatePdf()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Preview PDF&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt;
      &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;"pdfRef"&lt;/span&gt;
      &lt;span class="na"&gt;preview-modal&lt;/span&gt;
      &lt;span class="na"&gt;:enable-download=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;
      &lt;span class="na"&gt;manual-pagination&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;#pdf-content&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;article&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;My report&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Content from my Vue app.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/Html2Pdf&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;style&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nc"&gt;.report-export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--vue-pdf-preview-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;900px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--vue-pdf-preview-surface&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#f8fafc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--vue-pdf-preview-close-background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#17324a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--vue-pdf-preview-focus-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#0b9668&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--vue-pdf-loader-surface&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#f8fafc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--vue-pdf-loader-spinner-accent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#0b9668&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;style&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Variable&lt;/th&gt;
&lt;th&gt;Built-in UI area&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;--vue-pdf-preview-width&lt;/code&gt;, &lt;code&gt;--vue-pdf-preview-height&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Desktop dialog size.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;--vue-pdf-preview-mobile-width&lt;/code&gt;, &lt;code&gt;--vue-pdf-preview-mobile-height&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Preview size at widths up to 640px; defaults fill the viewport.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;--vue-pdf-preview-radius&lt;/code&gt;, &lt;code&gt;--vue-pdf-preview-backdrop&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Dialog corners and modal backdrop.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;--vue-pdf-preview-surface&lt;/code&gt;, &lt;code&gt;--vue-pdf-preview-color&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Preview surface and foreground.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;--vue-pdf-preview-close-background&lt;/code&gt;, &lt;code&gt;--vue-pdf-preview-close-color&lt;/code&gt;, &lt;code&gt;--vue-pdf-preview-focus-color&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Close button colors and focus outline.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;--vue-pdf-loader-backdrop&lt;/code&gt;, &lt;code&gt;--vue-pdf-loader-surface&lt;/code&gt;, &lt;code&gt;--vue-pdf-loader-color&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Loader overlay, panel and text.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;--vue-pdf-loader-radius&lt;/code&gt;, &lt;code&gt;--vue-pdf-loader-spinner-track&lt;/code&gt;, &lt;code&gt;--vue-pdf-loader-spinner-accent&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Loader corners and spinner.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;--vue-pdf-layout-background&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Optional visible fixed export layout background.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The preview uses a native dialog: Escape or its labeled close button closes it, focus returns to the previous control, and the dialog fills the mobile viewport by default. The default loader exposes status and bounded progress values and stops its spinner when reduced motion is requested. These controls support keyboard use, but you should still test your document markup and the browser's PDF viewer with your target assistive technology. Replace the default loader with the &lt;a href="https://vue-pdf-export-docs.vercel.app/api/events-slots" rel="noopener noreferrer"&gt;&lt;code&gt;#loader&lt;/code&gt; slot&lt;/a&gt; if your app needs different UI.&lt;/p&gt;




&lt;h3&gt;
  
  
  Compose Existing PDF Pages
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;composition.prepend&lt;/code&gt; and &lt;code&gt;composition.append&lt;/code&gt; insert &lt;strong&gt;whole PDF pages&lt;/strong&gt; before and after generated pages. They do not overlay a page. A two-page template on both sides adds four pages.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Html2Pdf&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PdfCompositionOptions&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export/style.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pdfRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;InstanceType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;Html2Pdf&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;templatePdf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Blob&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;composition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PdfCompositionOptions&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;({});&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;chooseTemplate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;HTMLInputElement&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;?.[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;templatePdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;composition&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;prepend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;append&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;exportPdf&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;templatePdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;pdfRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;generatePdf&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;composition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;composition&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"file"&lt;/span&gt; &lt;span class="na"&gt;accept=&lt;/span&gt;&lt;span class="s"&gt;"application/pdf,.pdf"&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;change=&lt;/span&gt;&lt;span class="s"&gt;"chooseTemplate"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;:disabled=&lt;/span&gt;&lt;span class="s"&gt;"!templatePdf"&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"exportPdf"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Export combined PDF
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt;
    &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;"pdfRef"&lt;/span&gt;
    &lt;span class="na"&gt;:manual-pagination=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
    &lt;span class="na"&gt;:enable-download=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
    &lt;span class="na"&gt;:composition=&lt;/span&gt;&lt;span class="s"&gt;"composition"&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;#pdf-content&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;article&amp;gt;&lt;/span&gt;Generated document&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/Html2Pdf&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;PdfTemplateSource&lt;/code&gt; accepts &lt;code&gt;Blob&lt;/code&gt;, &lt;code&gt;ArrayBuffer&lt;/code&gt;, &lt;code&gt;Uint8Array&lt;/code&gt;, or a URL string pointing to a real PDF. Browser &lt;code&gt;fetch()&lt;/code&gt; of remote URLs needs CORS access. Password-protected template PDFs may not load; verify the source before export. The same source used twice is resolved once per generation. The composition engine loads only when needed.&lt;/p&gt;

&lt;p&gt;Method &lt;code&gt;generatePdf({ composition })&lt;/code&gt; takes precedence over the &lt;code&gt;composition&lt;/code&gt; prop. The object prop takes precedence over the convenience pair &lt;code&gt;pdf-template&lt;/code&gt; and &lt;code&gt;template-position="prepend|append|both"&lt;/code&gt;; that pair defaults to prepend. Composition can also be passed through the lower-level options. Generated headers, footers, watermarks, and &lt;code&gt;{total}&lt;/code&gt; are applied before inserted pages, so their page numbering excludes templates. Cancellation is checked around fetch, parsing, and serialization. The implementation reapplies metadata and encryption to the combined output when configured, but test the resulting permissions and metadata in your target viewers.&lt;/p&gt;

&lt;p&gt;For Blob/ArrayBuffer/Base64 output, see the &lt;a href="https://vue-pdf-export-docs.vercel.app/api/programmatic-api" rel="noopener noreferrer"&gt;programmatic API&lt;/a&gt;. The &lt;a href="https://vue-pdf-export-docs.vercel.app/use-cases/playground" rel="noopener noreferrer"&gt;playground&lt;/a&gt; offers composition upload and page-order checks.&lt;/p&gt;




&lt;h2&gt;
  
  
  Use Cases
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Playground
&lt;/h3&gt;

&lt;p&gt;The live playground is the fastest way to compare Canvas and selectable-text rendering and exercise the package without installing it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://vue-pdf-export-playground.vercel.app/" rel="noopener noreferrer"&gt;Open the interactive PDF playground&lt;/a&gt;&lt;br&gt;
Open the live playground&lt;/p&gt;
&lt;h4&gt;
  
  
  What you can exercise
&lt;/h4&gt;

&lt;p&gt;Upload an existing PDF to try page composition and compare first, last and both insertion. Switch headers and footers between typed objects and Vue slots, inspect smart splitting with table fixtures, show pagination boundaries with the debug toggle, and try different paper sizes. The playground works on desktop, tablet and mobile. Its demo controls and fixtures are not npm exports.&lt;/p&gt;
&lt;h4&gt;
  
  
  Choose a renderer and paper size
&lt;/h4&gt;

&lt;p&gt;Compare Canvas visual capture with &lt;a href="https://vue-pdf-export-docs.vercel.app/use-cases/selectable-text" rel="noopener noreferrer"&gt;selectable-text output&lt;/a&gt;, then choose A/B/C, Letter, Legal or other &lt;a href="https://vue-pdf-export-docs.vercel.app/get-started/paper-formats" rel="noopener noreferrer"&gt;paper formats and orientation&lt;/a&gt;. Use the smart-split and table fixtures to inspect real pagination, including repeated headings.&lt;/p&gt;
&lt;h4&gt;
  
  
  Try headers, footers and composition
&lt;/h4&gt;

&lt;p&gt;Switch between the &lt;a href="https://vue-pdf-export-docs.vercel.app/api/headers" rel="noopener noreferrer"&gt;typed header object and Vue slot&lt;/a&gt; and &lt;a href="https://vue-pdf-export-docs.vercel.app/api/footers" rel="noopener noreferrer"&gt;footer object and Vue slot&lt;/a&gt;. Upload a real PDF for &lt;a href="https://vue-pdf-export-docs.vercel.app/api/composition" rel="noopener noreferrer"&gt;composition&lt;/a&gt;, then compare first/last/both insertion and component-prop, imperative or legacy configuration. Check the generated page count because optional media and authored breaks change the report length.&lt;/p&gt;
&lt;h4&gt;
  
  
  Inspect output and document options
&lt;/h4&gt;

&lt;p&gt;Try &lt;a href="https://vue-pdf-export-docs.vercel.app/api/programmatic-api" rel="noopener noreferrer"&gt;Blob, ArrayBuffer and Base64 output&lt;/a&gt;, PDF preview, download and print. Test &lt;a href="https://vue-pdf-export-docs.vercel.app/api/pdf-styling" rel="noopener noreferrer"&gt;auto-fit and export-only styling&lt;/a&gt;, &lt;a href="https://vue-pdf-export-docs.vercel.app/api/security" rel="noopener noreferrer"&gt;passwords and permissions&lt;/a&gt;, &lt;a href="https://vue-pdf-export-docs.vercel.app/api/watermarks" rel="noopener noreferrer"&gt;watermarks&lt;/a&gt;, metadata and compression. The debug toggle shows pagination boundaries; its overlay is not embedded in the PDF.&lt;/p&gt;

&lt;p&gt;The playground has an optional four-chart ApexCharts sample (bar, line, area, and donut), a custom font picker, image controls, and watermark design presets. Numeric labels and fixed chart callouts can differ between Canvas and selectable text; compare the generated PDFs.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Canvas and selectable-text rendering modes&lt;/li&gt;
&lt;li&gt;selectable/searchable/copyable PDF text&lt;/li&gt;
&lt;li&gt;preview, download and native browser print&lt;/li&gt;
&lt;li&gt;Blob, ArrayBuffer, raw Base64 and PDF data-URL output&lt;/li&gt;
&lt;li&gt;manual and automatic pagination&lt;/li&gt;
&lt;li&gt;headers, footers and logos&lt;/li&gt;
&lt;li&gt;watermarks and page targeting&lt;/li&gt;
&lt;li&gt;passwords, permissions, metadata and compression&lt;/li&gt;
&lt;li&gt;clickable links&lt;/li&gt;
&lt;li&gt;progress stages and page-aware progress&lt;/li&gt;
&lt;li&gt;opt-in total, stage and per-page generation timings&lt;/li&gt;
&lt;li&gt;cancellation and recovery&lt;/li&gt;
&lt;li&gt;&lt;code&gt;data-pdf-ignore&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;export-only page/body backgrounds, classes and styles&lt;/li&gt;
&lt;li&gt;per-page styling callbacks&lt;/li&gt;
&lt;li&gt;scoped custom PDF CSS&lt;/li&gt;
&lt;li&gt;external print stylesheets&lt;/li&gt;
&lt;li&gt;forced current/light/dark themes&lt;/li&gt;
&lt;li&gt;width auto-fit&lt;/li&gt;
&lt;li&gt;generated usage code&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  Stress playground
&lt;/h4&gt;

&lt;p&gt;The interactive &lt;code&gt;/stress.html&lt;/code&gt; presets configure a run; selecting a preset does not start PDF generation. Start a run explicitly and review browser memory and output for your device.&lt;/p&gt;

&lt;p&gt;The dedicated stress page exposes page-count presets for large-document validation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;5&lt;/li&gt;
&lt;li&gt;10&lt;/li&gt;
&lt;li&gt;25&lt;/li&gt;
&lt;li&gt;50&lt;/li&gt;
&lt;li&gt;100&lt;/li&gt;
&lt;li&gt;200&lt;/li&gt;
&lt;li&gt;500&lt;/li&gt;
&lt;li&gt;1000&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://vue-pdf-export-playground.vercel.app/stress.html/" rel="noopener noreferrer"&gt;Open the large-document stress playground&lt;/a&gt;&lt;br&gt;
Open the stress playground&lt;/p&gt;

&lt;p&gt;Heavy and extreme presets can consume significant browser CPU and memory. The stress UI includes warnings and preserves cancellation/recovery behavior.&lt;/p&gt;

&lt;p&gt;The package default remains Canvas mode for backwards compatibility even if the playground chooses text mode for demonstration.&lt;/p&gt;


&lt;h3&gt;
  
  
  Selectable Text Mode
&lt;/h3&gt;

&lt;p&gt;Selectable-text mode uses a browser-layout-to-vector-PDF renderer rather than html2canvas for the main body content.&lt;/p&gt;
&lt;h4&gt;
  
  
  How do I generate a searchable PDF in Vue 3?
&lt;/h4&gt;

&lt;p&gt;Install &lt;code&gt;vue-pdf-export&lt;/code&gt;, import &lt;code&gt;Html2Pdf&lt;/code&gt; and its stylesheet, set &lt;code&gt;render-mode="text"&lt;/code&gt;, then call &lt;code&gt;generatePdf()&lt;/code&gt; from a component ref after the Vue component mounts. The returned value is a PDF &lt;code&gt;Blob&lt;/code&gt;; with &lt;code&gt;enable-download&lt;/code&gt; enabled, the component can also download it. This example uses the current documented package API.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;vue-pdf-export
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Html2Pdf&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export/style.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pdf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;InstanceType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;Html2Pdf&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;downloadReport&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;blob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;generatePdf&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Generated &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; PDF bytes`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"downloadReport"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Download searchable PDF&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt;
    &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;"pdf"&lt;/span&gt;
    &lt;span class="na"&gt;render-mode=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;
    &lt;span class="na"&gt;filename=&lt;/span&gt;&lt;span class="s"&gt;"searchable-report.pdf"&lt;/span&gt;
    &lt;span class="na"&gt;:enable-download=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;#pdf-content&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;article&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Monthly report&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;This body text is selectable and searchable.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/Html2Pdf&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The PDF body text can be selected, copied, and searched in a compatible viewer. Test the result with your fonts and browser: not every CSS effect or glyph has a native-text equivalent. In Nuxt, follow the &lt;a href="https://vue-pdf-export-docs.vercel.app/get-started/nuxt-ssr" rel="noopener noreferrer"&gt;SSR guide&lt;/a&gt; and start generation only in the browser.&lt;/p&gt;

&lt;h4&gt;
  
  
  Vue PDF export: which renderer should I use?
&lt;/h4&gt;

&lt;p&gt;Use &lt;code&gt;renderMode="canvas"&lt;/code&gt; when matching complex browser CSS matters most. It uses the html2pdf.js / html2canvas / jsPDF path, so PDF body text is drawn as an image. Use &lt;code&gt;renderMode="text"&lt;/code&gt; when users need to select, search or copy body text in the PDF. Both modes work through the same Vue component and support preview, download and Blob output. Start with the &lt;a href="https://vue-pdf-export-docs.vercel.app/get-started/quick-start" rel="noopener noreferrer"&gt;Vue quick start&lt;/a&gt;, then compare &lt;a href="https://vue-pdf-export-docs.vercel.app/get-started/rendering-modes" rel="noopener noreferrer"&gt;rendering modes&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The package adds Vue components, typed options, slots and pagination controls around these workflows. Selectable-text mode has its own CSS limits below; it is not a pixel-for-pixel replacement for the Canvas path.&lt;/p&gt;

&lt;h4&gt;
  
  
  What it is designed to preserve
&lt;/h4&gt;

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

&lt;h4&gt;
  
  
  Current limitations
&lt;/h4&gt;

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

&lt;ul&gt;
&lt;li&gt;complex stacking-context / &lt;code&gt;z-index&lt;/code&gt; reordering&lt;/li&gt;
&lt;li&gt;background images and gradients&lt;/li&gt;
&lt;li&gt;shadows&lt;/li&gt;
&lt;li&gt;CSS transforms&lt;/li&gt;
&lt;li&gt;CFF-outline OTF and WOFF/WOFF2 embedding (registered TTF and TrueType-outline OTF are supported)&lt;/li&gt;
&lt;li&gt;some non-WinAnsi glyphs such as CJK/emoji&lt;/li&gt;
&lt;li&gt;pseudo-elements such as &lt;code&gt;::before&lt;/code&gt; / &lt;code&gt;::after&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;native list markers in some layouts&lt;/li&gt;
&lt;li&gt;RTL text&lt;/li&gt;
&lt;li&gt;&lt;code&gt;position: fixed&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;complex rounded clipping&lt;/li&gt;
&lt;li&gt;native &lt;code&gt;break-inside: avoid&lt;/code&gt; semantics inside the vector renderer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For those cases, prefer &lt;code&gt;renderMode="canvas"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;fonts&lt;/code&gt; option can register TTF or TrueType-outline OTF files for selectable text. Without a registered file, unrecognized CSS font families map to built-in PDF fonts. Inline SVG shapes are rasterized in this mode. See &lt;a href="https://vue-pdf-export-docs.vercel.app/use-cases/media-typography" rel="noopener noreferrer"&gt;fonts, charts, SVG and images&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Font metric differences
&lt;/h4&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h4&gt;
  
  
  Header/footer text
&lt;/h4&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h4&gt;
  
  
  Security
&lt;/h4&gt;

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

&lt;h4&gt;
  
  
  Rendering modes reference
&lt;/h4&gt;

&lt;h4&gt;
  
  
  Canvas mode
&lt;/h4&gt;

&lt;p&gt;Canvas mode is the default and uses the package's existing &lt;code&gt;html2pdf.js&lt;/code&gt; / &lt;code&gt;html2canvas&lt;/code&gt; / &lt;code&gt;jsPDF&lt;/code&gt; pipeline.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt; &lt;span class="na"&gt;render-mode=&lt;/span&gt;&lt;span class="s"&gt;"canvas"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use it when the highest possible browser CSS fidelity is more important than selectable body text.&lt;/p&gt;

&lt;p&gt;Best for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;complex CSS&lt;/li&gt;
&lt;li&gt;gradients&lt;/li&gt;
&lt;li&gt;shadows&lt;/li&gt;
&lt;li&gt;transforms&lt;/li&gt;
&lt;li&gt;custom web fonts&lt;/li&gt;
&lt;li&gt;visual dashboards&lt;/li&gt;
&lt;li&gt;designs where browser appearance is the priority&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Body content is rasterized, so normal body text is not selectable/searchable.&lt;/p&gt;

&lt;h5&gt;
  
  
  Incremental Canvas rendering
&lt;/h5&gt;

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

&lt;p&gt;This path:&lt;/p&gt;

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

&lt;p&gt;Canvas documents without page-break markers use the whole-document &lt;code&gt;html2pdf.js&lt;/code&gt; worker; paginated documents can use incremental page captures.&lt;/p&gt;

&lt;h4&gt;
  
  
  Selectable text mode
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt; &lt;span class="na"&gt;render-mode=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;It supports:&lt;/p&gt;

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

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt; &lt;span class="na"&gt;render-mode=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;manual-pagination&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="na"&gt;#pdf-content&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;main&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Selectable report&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;You can select and search this text in the generated PDF.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

      &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://www.npmjs.com/package/vue-pdf-export"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        Open vue-pdf-export on npm
      &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/main&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/Html2Pdf&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Selectable-text mode intentionally favors real PDF text over pixel-perfect parity with every browser CSS feature. See Selectable Text Mode Notes.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  Clickable PDF Links
&lt;/h3&gt;

&lt;p&gt;Enable PDF links through &lt;code&gt;htmlToPdfOptions.enableLinks&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;htmlToPdfOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;enableLinks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt; &lt;span class="na"&gt;:html-to-pdf-options=&lt;/span&gt;&lt;span class="s"&gt;"htmlToPdfOptions"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt; &lt;span class="na"&gt;#pdf-content&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://www.npmjs.com/package/vue-pdf-export"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      Open vue-pdf-export on npm
    &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/Html2Pdf&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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.&lt;/p&gt;

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

&lt;p&gt;Recommended PDF-friendly link CSS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.pdf-link&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;inline-flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8px&lt;/span&gt; &lt;span class="m"&gt;12px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;700&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;line-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;letter-spacing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;white-space&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;nowrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;text-decoration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;underline&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Images &amp;amp; CORS
&lt;/h3&gt;

&lt;p&gt;Remote images must be accessible to the browser during rendering.&lt;/p&gt;

&lt;p&gt;Recommended:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;html2canvas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;useCORS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For external images:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;configure appropriate CORS headers&lt;/li&gt;
&lt;li&gt;avoid inaccessible authenticated image URLs&lt;/li&gt;
&lt;li&gt;prefer data URLs for critical logos when practical&lt;/li&gt;
&lt;li&gt;preserve image aspect ratio&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Normal content image CSS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.pdf-root&lt;/span&gt; &lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;object-fit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;contain&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;h4&gt;
  
  
  Image optimization
&lt;/h4&gt;

&lt;p&gt;Opt-in &lt;code&gt;autoOptimize&lt;/code&gt; provides target DPI, JPEG quality, alpha preservation, size caps, and per-export repeated-image reuse. Existing library image quality remains unchanged when it is disabled. A cross-origin image that cannot be decoded is left unchanged and may still be subject to the renderer’s CORS restrictions.&lt;/p&gt;




&lt;h3&gt;
  
  
  Production Guide
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Use a deterministic export width
&lt;/h4&gt;

&lt;p&gt;A PDF should not unexpectedly reflow because it was generated from a narrow mobile viewport.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.pdf-root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;794px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;box-sizing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;border-box&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Keep export CSS separate from responsive application CSS
&lt;/h4&gt;

&lt;p&gt;The web UI and the PDF document have different layout goals.&lt;/p&gt;

&lt;h4&gt;
  
  
  Choose the renderer intentionally
&lt;/h4&gt;

&lt;p&gt;Use &lt;code&gt;canvas&lt;/code&gt; when exact visual fidelity is the priority.&lt;/p&gt;

&lt;p&gt;Use &lt;code&gt;text&lt;/code&gt; when selectable/searchable/copyable PDF text is the priority and the document uses CSS supported by the vector renderer.&lt;/p&gt;

&lt;h4&gt;
  
  
  Avoid large fixed heights
&lt;/h4&gt;

&lt;p&gt;Prefer &lt;code&gt;min-height&lt;/code&gt; over large fixed &lt;code&gt;height&lt;/code&gt; values where possible.&lt;/p&gt;

&lt;h4&gt;
  
  
  Protect important blocks
&lt;/h4&gt;

&lt;p&gt;Use &lt;code&gt;.pdf-keep-together&lt;/code&gt;, &lt;code&gt;.pdf-no-break&lt;/code&gt;, or carefully chosen &lt;code&gt;pagebreak.avoid&lt;/code&gt; selectors.&lt;/p&gt;

&lt;h4&gt;
  
  
  Preserve image aspect ratios
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;object-fit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;contain&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Keep header/footer content inside configured heights
&lt;/h4&gt;

&lt;p&gt;Very large text or HTML content can overlap PDF content if it exceeds &lt;code&gt;headerHeight&lt;/code&gt; or &lt;code&gt;footerHeight&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Use trusted HTML only
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;headerHtml&lt;/code&gt; and &lt;code&gt;footerHtml&lt;/code&gt; render developer-provided HTML. Header, footer, and slot HTML is sanitized with DOMPurify before export staging. Supply intentional, trusted document markup; sanitization does not turn arbitrary input into trusted application content.&lt;/p&gt;

&lt;h4&gt;
  
  
  Test fonts and media on the target browser
&lt;/h4&gt;

&lt;p&gt;Wait for project fonts and register supported font bytes when exact selectable-text glyphs matter. Keep &lt;code&gt;autoOptimize&lt;/code&gt; opt-in and choose DPI/JPEG quality appropriate to your output. Test SVG icons, chart snapshots, and font fallback in your target browsers.&lt;/p&gt;

&lt;h4&gt;
  
  
  Keep selectable-mode link styles simple
&lt;/h4&gt;

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

&lt;h4&gt;
  
  
  Use reasonable canvas quality
&lt;/h4&gt;

&lt;p&gt;Higher html2canvas scale values consume more memory and CPU.&lt;/p&gt;

&lt;h4&gt;
  
  
  Generate one large document at a time
&lt;/h4&gt;

&lt;p&gt;Multi-page PDF generation can be CPU and memory intensive.&lt;/p&gt;

&lt;h4&gt;
  
  
  Provide cancellation for expensive exports
&lt;/h4&gt;

&lt;p&gt;Expose &lt;code&gt;cancelGeneration()&lt;/code&gt; in long-running workflows so users can stop an export without waiting for the entire document to finish.&lt;/p&gt;

&lt;p&gt;Cancellation is cooperative: already-running synchronous browser/jsPDF work finishes before the next cancellation checkpoint.&lt;/p&gt;

&lt;h4&gt;
  
  
  Test representative content
&lt;/h4&gt;

&lt;p&gt;Test:&lt;/p&gt;

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

&lt;h4&gt;
  
  
  Performance &amp;amp; Large Documents
&lt;/h4&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h4&gt;
  
  
  Large-document work completed
&lt;/h4&gt;

&lt;p&gt;The performance/stability work includes:&lt;/p&gt;

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

&lt;h4&gt;
  
  
  Measured performance improvements
&lt;/h4&gt;

&lt;p&gt;The performance work resulted in several measurable improvements in the benchmark fixtures:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Area&lt;/th&gt;
&lt;th&gt;Before&lt;/th&gt;
&lt;th&gt;After&lt;/th&gt;
&lt;th&gt;Improvement&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;HTML footer without logo&lt;/td&gt;
&lt;td&gt;7.82 s&lt;/td&gt;
&lt;td&gt;1.43 s&lt;/td&gt;
&lt;td&gt;~81.7% less time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HTML footer with logo&lt;/td&gt;
&lt;td&gt;11.81 s&lt;/td&gt;
&lt;td&gt;1.29 s&lt;/td&gt;
&lt;td&gt;~89.1% less time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Footer-heavy PDF size&lt;/td&gt;
&lt;td&gt;~46.7 MB&lt;/td&gt;
&lt;td&gt;~1.0 MB&lt;/td&gt;
&lt;td&gt;~97.9% smaller&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Footer no-logo peak heap&lt;/td&gt;
&lt;td&gt;102.6 MB&lt;/td&gt;
&lt;td&gt;26.5 MB&lt;/td&gt;
&lt;td&gt;~74.2% lower&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Long Canvas capture surface&lt;/td&gt;
&lt;td&gt;~99.96M px&lt;/td&gt;
&lt;td&gt;~1.74M px per page&lt;/td&gt;
&lt;td&gt;~98.26% smaller peak capture geometry&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;The architectural changes behind these results include:&lt;/p&gt;

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

&lt;h4&gt;
  
  
  Incremental Canvas strategy
&lt;/h4&gt;

&lt;p&gt;For Canvas documents with &lt;code&gt;.html2pdf__page-break&lt;/code&gt; markers, each logical page is rendered independently.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;The whole-document &lt;code&gt;html2pdf.js&lt;/code&gt; path is used for Canvas documents without page-break markers.&lt;/p&gt;

&lt;h4&gt;
  
  
  Selectable-text image optimization
&lt;/h4&gt;

&lt;p&gt;Selectable-text rendering uses a &lt;strong&gt;per-generation image cache&lt;/strong&gt; for repeated real &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; sources when the source, target raster dimensions, format, and JPEG quality match.&lt;/p&gt;

&lt;p&gt;Why the cache is intentionally per-generation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;avoids carrying stale DOM/image state across exports&lt;/li&gt;
&lt;li&gt;keeps cache lifetime bounded&lt;/li&gt;
&lt;li&gt;prevents a global cache from becoming a long-lived memory owner&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Canvas elements are not cached because their pixels may change even when their dimensions do not.&lt;/p&gt;

&lt;h4&gt;
  
  
  Cleanup and browser responsiveness
&lt;/h4&gt;

&lt;p&gt;Long exports explicitly release temporary resources where practical:&lt;/p&gt;

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

&lt;p&gt;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.&lt;/p&gt;

&lt;h4&gt;
  
  
  Cancellation and recovery
&lt;/h4&gt;

&lt;p&gt;Both rendering modes support cooperative cancellation.&lt;/p&gt;

&lt;p&gt;The regression suite checks that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;an active long export can be cancelled,&lt;/li&gt;
&lt;li&gt;temporary rendering DOM is cleaned up,&lt;/li&gt;
&lt;li&gt;no successful Blob is exposed for the cancelled run, and&lt;/li&gt;
&lt;li&gt;a new PDF can be generated successfully afterwards.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Page progress
&lt;/h4&gt;

&lt;p&gt;Page-aware renderers can report:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;stage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rendering&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;progress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;currentPage&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;totalPages&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is useful for long reports where a percentage alone does not explain what the renderer is doing.&lt;/p&gt;

&lt;h4&gt;
  
  
  Encrypted Canvas memory behavior
&lt;/h4&gt;

&lt;p&gt;Large encrypted Canvas PDFs can retain substantially more memory than equivalent unencrypted Canvas PDFs in Chromium.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Practical guidance:&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Upstream jsPDF tracking&lt;/strong&gt;: 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.&lt;/p&gt;

&lt;p&gt;Upstream tracking: &lt;a href="https://github.com/parallax/jsPDF/issues/4017" rel="noopener noreferrer"&gt;jsPDF #4017 - encrypted raster PDF memory retention&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This link is included so developers using large encrypted Canvas PDFs can follow the dependency-level investigation directly.&lt;/p&gt;

&lt;h4&gt;
  
  
  Stress/regression coverage
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Area&lt;/th&gt;
&lt;th&gt;Coverage&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Long Canvas documents&lt;/td&gt;
&lt;td&gt;10 / 25 / 50 / 100-page regression fixtures&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Heavy cross-browser smoke&lt;/td&gt;
&lt;td&gt;Chromium plus Firefox/WebKit coverage, with the heaviest 50/100-page cases concentrated in Chromium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Selectable-text long documents&lt;/td&gt;
&lt;td&gt;long multi-page rendering and cancellation/recovery&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Image-heavy selectable mode&lt;/td&gt;
&lt;td&gt;repeated image cache / raster-call regression&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Image-heavy Canvas mode&lt;/td&gt;
&lt;td&gt;page-bounded canvas regression&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cancellation&lt;/td&gt;
&lt;td&gt;Canvas and selectable-text cancellation + recovery&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cleanup&lt;/td&gt;
&lt;td&gt;temporary page/snapshot/fixture cleanup assertions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Features&lt;/td&gt;
&lt;td&gt;headers, footers, watermarks, links, metadata, compression, security&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h4&gt;
  
  
  Recommended large-document configuration
&lt;/h4&gt;

&lt;p&gt;For large Canvas reports:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt; &lt;span class="na"&gt;render-mode=&lt;/span&gt;&lt;span class="s"&gt;"canvas"&lt;/span&gt; &lt;span class="na"&gt;:manual-pagination=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="na"&gt;:pdf-quality=&lt;/span&gt;&lt;span class="s"&gt;"1.5"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use explicit page markers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"html2pdf__page-break"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For text-heavy reports where supported CSS is sufficient:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt; &lt;span class="na"&gt;render-mode=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Selectable-text mode avoids rasterizing the entire body and can be a better fit for long text-first documents.&lt;/p&gt;

&lt;h4&gt;
  
  
  About documents larger than 100 pages
&lt;/h4&gt;

&lt;p&gt;The current automated stress and regression suite verifies large-document behavior through &lt;strong&gt;100-page test fixtures&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This does &lt;strong&gt;not&lt;/strong&gt; mean the package has a hard 100-page limit. PDF generation does not stop at page 100, and larger documents may also work successfully.&lt;/p&gt;

&lt;p&gt;However, documents beyond the tested range depend increasingly on the actual workload, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DOM size and complexity&lt;/li&gt;
&lt;li&gt;number and dimensions of images&lt;/li&gt;
&lt;li&gt;whether images are unique or repeatedly reused&lt;/li&gt;
&lt;li&gt;renderer choice&lt;/li&gt;
&lt;li&gt;browser and device memory&lt;/li&gt;
&lt;li&gt;headers, footers, and watermarks&lt;/li&gt;
&lt;li&gt;encryption and compression&lt;/li&gt;
&lt;li&gt;final PDF serialization cost&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For very large text-first documents, &lt;code&gt;renderMode="text"&lt;/code&gt; 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.&lt;/p&gt;

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

&lt;p&gt;The package also provides page-aware progress and cooperative cancellation so applications can give users meaningful feedback during long exports:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Rendering page 74 of 100
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Troubleshooting
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Selectable text is not pixel-identical to the browser
&lt;/h4&gt;

&lt;p&gt;Use &lt;code&gt;render-mode="canvas"&lt;/code&gt; for maximum CSS fidelity.&lt;/p&gt;

&lt;p&gt;Selectable-text mode intentionally prioritizes real PDF text and vector output.&lt;/p&gt;

&lt;h4&gt;
  
  
  Link looks like text but is not clickable
&lt;/h4&gt;

&lt;p&gt;Make sure links are enabled:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;htmlToPdfOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;enableLinks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also verify the source element is a real anchor with a valid &lt;code&gt;href&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Link text looks stretched
&lt;/h4&gt;

&lt;p&gt;Reduce large &lt;code&gt;letter-spacing&lt;/code&gt;, transforms, and tight fixed widths in selectable-text mode.&lt;/p&gt;

&lt;h4&gt;
  
  
  Logo looks stretched
&lt;/h4&gt;

&lt;p&gt;Header/footer logo dimensions are maximum bounds and preserve the source aspect ratio.&lt;/p&gt;

&lt;p&gt;For normal content images:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;object-fit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;contain&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Header/footer overlaps content
&lt;/h4&gt;

&lt;p&gt;Increase &lt;code&gt;headerHeight&lt;/code&gt; / &lt;code&gt;footerHeight&lt;/code&gt;, or reduce content size.&lt;/p&gt;

&lt;p&gt;For selectively targeted headers, only target pages receive the extra header space. If excluded pages still have top spacing, check explicit &lt;code&gt;htmlToPdfOptions.margin&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Header or footer image is missing
&lt;/h4&gt;

&lt;p&gt;Check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;URL accessibility&lt;/li&gt;
&lt;li&gt;CORS&lt;/li&gt;
&lt;li&gt;data URL validity&lt;/li&gt;
&lt;li&gt;&lt;code&gt;headerLogoEnabled&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;footerLogoEnabled&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A large source logo displayed at a small size is capped to a proportional raster size during selectable-text header/footer preparation. The source file and caller options remain unchanged.&lt;/p&gt;

&lt;h4&gt;
  
  
  HTML header/footer is not visible
&lt;/h4&gt;

&lt;p&gt;Check that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;related header/footer is enabled&lt;/li&gt;
&lt;li&gt;HTML string is non-empty&lt;/li&gt;
&lt;li&gt;footer uses &lt;code&gt;footer-mode="html"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;content fits inside configured height&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Blank page around a manual break
&lt;/h4&gt;

&lt;p&gt;Use only:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.html2pdf__page-break&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;both&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do not add &lt;code&gt;break-before&lt;/code&gt; or &lt;code&gt;page-break-before&lt;/code&gt; to the same helper.&lt;/p&gt;

&lt;h4&gt;
  
  
  Background watermark is hidden
&lt;/h4&gt;

&lt;p&gt;Opaque PDF content can cover a DOM background watermark.&lt;/p&gt;

&lt;p&gt;In selectable-text mode, a requested background watermark is drawn behind PDF content, but opaque cards can cover it. Canvas pages are opaque images, so a requested background mark uses a light foreground fallback to remain visible.&lt;/p&gt;

&lt;h4&gt;
  
  
  PDF is blurry
&lt;/h4&gt;

&lt;p&gt;In canvas mode, increase &lt;code&gt;pdfQuality&lt;/code&gt; or &lt;code&gt;htmlToPdfOptions.html2canvas.scale&lt;/code&gt; carefully.&lt;/p&gt;

&lt;p&gt;Selectable-text body text remains vector text and does not depend on html2canvas resolution.&lt;/p&gt;

&lt;h4&gt;
  
  
  Large document generation is slow
&lt;/h4&gt;

&lt;p&gt;Reduce:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;canvas scale where relevant&lt;/li&gt;
&lt;li&gt;image dimensions&lt;/li&gt;
&lt;li&gt;document complexity&lt;/li&gt;
&lt;li&gt;simultaneous PDF generation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h4&gt;
  
  
  A header or footer appears empty
&lt;/h4&gt;

&lt;p&gt;The component accepts direct props as well as &lt;code&gt;header&lt;/code&gt; and &lt;code&gt;footer&lt;/code&gt; objects. Explicit object fields take priority, while omitted fields may fall back to matching direct props. Check the enabled flag, slot content, object settings, and reserved height. For a new integration, prefer the grouped object API or Vue slots.&lt;/p&gt;

&lt;h4&gt;
  
  
  Table heading repeats twice, or a row crosses a page cut
&lt;/h4&gt;

&lt;p&gt;Use one semantic &lt;code&gt;&amp;lt;thead&amp;gt;&lt;/code&gt; and normal &lt;code&gt;&amp;lt;tbody&amp;gt;&lt;/code&gt; rows. Avoid manually duplicated headings. Try &lt;a href="https://vue-pdf-export-docs.vercel.app/get-started/pagination" rel="noopener noreferrer"&gt;smart pagination&lt;/a&gt; and its diagnostic overlay. Large rowspans, oversized rows and unusual CSS need manual review in both renderers.&lt;/p&gt;

&lt;h4&gt;
  
  
  Canvas PDF appears to have selectable text
&lt;/h4&gt;

&lt;p&gt;Chrome can OCR page images. Foreground text watermarks or some numbering paths may also add native text. Inspect extracted PDF text or text-showing operators rather than relying only on mouse selection. Use &lt;code&gt;render-mode="text"&lt;/code&gt; for native selectable body text.&lt;/p&gt;




&lt;h3&gt;
  
  
  Testing &amp;amp; Browser Support
&lt;/h3&gt;

&lt;p&gt;The package targets modern browsers supported by Vue and the underlying PDF/browser APIs.&lt;/p&gt;

&lt;p&gt;Recommended testing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Chromium / Chrome / Edge&lt;/li&gt;
&lt;li&gt;Firefox&lt;/li&gt;
&lt;li&gt;WebKit&lt;/li&gt;
&lt;li&gt;Safari when Safari is important to production users&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Playwright WebKit tests the WebKit engine; it is not identical to testing the Safari application itself.&lt;/p&gt;

&lt;h4&gt;
  
  
  Testing
&lt;/h4&gt;

&lt;p&gt;The project uses unit, browser, and integration tests for smart splitting, table continuation, slots, PDF composition, page geometry, cancellation, and renderer behavior. Some documented verification runs were followed by targeted fixes; they are not a substitute for rerunning the current suite before release. Inspect representative PDFs, especially continued tables, nested frames, slots, and format/orientation combinations.&lt;/p&gt;

&lt;p&gt;A documentation build does not run the package browser suites. For testing strategy, see the &lt;a href="https://vue-pdf-export-docs.vercel.app/use-cases/testing-browser-support" rel="noopener noreferrer"&gt;testing and browser support guide&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Media and typography verification
&lt;/h4&gt;

&lt;p&gt;Documented media verification includes a 380-test unit run, TypeScript checks, library and playground builds, focused Chromium/WebKit browser exports, and selected rendered-page visual checks. A format/orientation matrix covered 82 combinations. Follow-up pagination and footer changes have narrower checks, including an inspected nine-page selectable-text report. Local Firefox verification remained open because the headless graphics compositor failed at launch. These are named test records rather than a fresh full-suite claim. See &lt;a href="https://vue-pdf-export-docs.vercel.app/use-cases/media-typography" rel="noopener noreferrer"&gt;media and typography&lt;/a&gt; for the tested boundaries.&lt;/p&gt;

&lt;p&gt;The release verification covers major public workflows, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Canvas and selectable-text PDF generation&lt;/li&gt;
&lt;li&gt;Blob, ArrayBuffer and Base64 output APIs&lt;/li&gt;
&lt;li&gt;preview Blob creation&lt;/li&gt;
&lt;li&gt;download&lt;/li&gt;
&lt;li&gt;native browser print flow&lt;/li&gt;
&lt;li&gt;rendering mode routing&lt;/li&gt;
&lt;li&gt;selectable-text generation&lt;/li&gt;
&lt;li&gt;PDF link annotations&lt;/li&gt;
&lt;li&gt;pagination and page-break mapping&lt;/li&gt;
&lt;li&gt;&lt;code&gt;data-pdf-ignore&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;export-only page/body styling&lt;/li&gt;
&lt;li&gt;themes, custom CSS, external stylesheets and auto-fit&lt;/li&gt;
&lt;li&gt;metadata&lt;/li&gt;
&lt;li&gt;compression&lt;/li&gt;
&lt;li&gt;security&lt;/li&gt;
&lt;li&gt;protected/unprotected PDFs&lt;/li&gt;
&lt;li&gt;header page targeting&lt;/li&gt;
&lt;li&gt;selective header spacing&lt;/li&gt;
&lt;li&gt;optional header/footer logos&lt;/li&gt;
&lt;li&gt;custom logo sizing&lt;/li&gt;
&lt;li&gt;header/footer HTML rendering&lt;/li&gt;
&lt;li&gt;selectable header/footer text&lt;/li&gt;
&lt;li&gt;footer page numbering&lt;/li&gt;
&lt;li&gt;per-page watermark targeting&lt;/li&gt;
&lt;li&gt;progress stages&lt;/li&gt;
&lt;li&gt;page-aware &lt;code&gt;currentPage&lt;/code&gt; / &lt;code&gt;totalPages&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;opt-in generation metrics&lt;/li&gt;
&lt;li&gt;cooperative cancellation and recovery&lt;/li&gt;
&lt;li&gt;portrait and landscape layouts&lt;/li&gt;
&lt;li&gt;large-document regression/stress scenarios&lt;/li&gt;
&lt;li&gt;selectable repeated-image caching&lt;/li&gt;
&lt;li&gt;page-bounded Canvas image-heavy rendering&lt;/li&gt;
&lt;li&gt;temporary rendering DOM/snapshot cleanup&lt;/li&gt;
&lt;li&gt;SSR-safe package import&lt;/li&gt;
&lt;li&gt;Nuxt 3 and Nuxt 4 SSR/hydration/client navigation&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Package-manager consumer matrix
&lt;/h4&gt;

&lt;p&gt;Packed-package consumer fixtures run against:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;npm&lt;/li&gt;
&lt;li&gt;pnpm&lt;/li&gt;
&lt;li&gt;Yarn&lt;/li&gt;
&lt;li&gt;Yarn Plug'n'Play&lt;/li&gt;
&lt;li&gt;Bun&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These fixtures verify install behavior, TypeScript resolution, production builds, CSS imports, and runtime PDF generation.&lt;/p&gt;

&lt;p&gt;Because PDF rendering is CPU-heavy, a small Playwright worker count is recommended:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx playwright &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;--workers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use a single worker for heavy stress/regression suites:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx playwright &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;--workers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the package's release checks before publishing changes to the PDF library itself. Application consumers should also test representative real documents on the browsers and devices that matter to their users.&lt;/p&gt;




&lt;h3&gt;
  
  
  Performance Engineering
&lt;/h3&gt;

&lt;p&gt;The large-document milestone was not only a benchmark exercise. It changed the runtime architecture and added repeatable correctness, cleanup and memory diagnostics.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The measurements below are historical fixtures. The latest full browser and stress reruns were not part of this docs update; measure your own document on target devices.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Rendering architecture
&lt;/h4&gt;

&lt;p&gt;The package dynamically loads PDF engines and the optional composition engine, resolves a shared template once, reuses unchanged header/footer and styled slot captures, reduces repeated image waiting, and prunes unrelated app DOM while capturing a layer. Oversized splittable Canvas sections are preflight paginated on private DOM, then fitting fragments are reused. Cooperative yields avoid waiting for hidden-tab animation frames. Generation reuses one final Blob for preview and download, with cleanup, cancellation and opt-in timing metrics.&lt;/p&gt;

&lt;p&gt;A local nine-page Canvas/slot export with watermark off was inspected: 27 image objects and zero PDF text-showing commands; a separate text-mode PDF contained 423 text commands. One local Canvas slot session changed from 26.89 seconds to 12.55 seconds after the refinements, without a controlled benchmark. A separate nine-page text run was about 4.35 seconds; no text-mode speedup was established. These observations do not predict your document's runtime or fidelity. Record browser/device, page count, renderer, assets, quality and cold/warm state when comparing exports.&lt;/p&gt;

&lt;h4&gt;
  
  
  Executive outcome
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;paginated Canvas documents can render page by page instead of one giant document-height canvas&lt;/li&gt;
&lt;li&gt;50-page and 100-page Canvas exports are verified as real, non-empty PDFs on the incremental path&lt;/li&gt;
&lt;li&gt;static HTML footer content is rasterized once and reused across pages&lt;/li&gt;
&lt;li&gt;selectable-text mode caches repeated image sources within one generation&lt;/li&gt;
&lt;li&gt;long work can be cancelled and then safely regenerated&lt;/li&gt;
&lt;li&gt;progress can expose &lt;code&gt;stage&lt;/code&gt;, &lt;code&gt;progress&lt;/code&gt;, &lt;code&gt;currentPage&lt;/code&gt; and &lt;code&gt;totalPages&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;temporary DOM, Canvas backing stores and encoded image references are released earlier&lt;/li&gt;
&lt;li&gt;browser yielding was added between expensive chunks&lt;/li&gt;
&lt;li&gt;encrypted raster memory retention was isolated and reproduced directly in jsPDF&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Phase map
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Phase&lt;/th&gt;
&lt;th&gt;Focus&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Phase 1&lt;/td&gt;
&lt;td&gt;Benchmark/stress foundation&lt;/td&gt;
&lt;td&gt;Actual page count, Blob size, Canvas geometry, timing, memory and progress telemetry.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Phase 2.1&lt;/td&gt;
&lt;td&gt;Static HTML footer bottleneck&lt;/td&gt;
&lt;td&gt;Render once + reuse; major time, output-size and heap reductions in the fixture.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Phase 2.2&lt;/td&gt;
&lt;td&gt;Clean memory isolation&lt;/td&gt;
&lt;td&gt;Fresh-context methodology separated temporary peaks from retained heap.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Phase 2.3A&lt;/td&gt;
&lt;td&gt;Security isolation&lt;/td&gt;
&lt;td&gt;Basic user-password encryption identified as the trigger for high raster retention.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Phase 2.3B&lt;/td&gt;
&lt;td&gt;Large-PDF correctness&lt;/td&gt;
&lt;td&gt;Page count alone was proven insufficient; Blob size and Canvas telemetry were added.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Phase 2.4&lt;/td&gt;
&lt;td&gt;Scaling and cliff diagnostics&lt;/td&gt;
&lt;td&gt;Raster payload + jsPDF encryption pattern isolated; legacy long-canvas failure instrumented.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Phase 3.1&lt;/td&gt;
&lt;td&gt;Incremental Canvas&lt;/td&gt;
&lt;td&gt;Page-bounded captures replaced the giant capture for paginated Canvas documents.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Phase 3.2&lt;/td&gt;
&lt;td&gt;Security re-test&lt;/td&gt;
&lt;td&gt;Giant-canvas issue addressed; encrypted-raster retention remained dependency-level.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Phase 3.2.1&lt;/td&gt;
&lt;td&gt;Raw jsPDF reproduction&lt;/td&gt;
&lt;td&gt;Strongest retention pattern reproduced without Vue component lifecycle.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Phase 3.3&lt;/td&gt;
&lt;td&gt;Cancellation + progress&lt;/td&gt;
&lt;td&gt;Cooperative cancellation, recovery and current-page progress added.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Phase 3.4&lt;/td&gt;
&lt;td&gt;Repeated assets + cleanup&lt;/td&gt;
&lt;td&gt;Per-generation image cache and shorter DOM/Canvas lifetimes.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Phase 3.5&lt;/td&gt;
&lt;td&gt;Routing regression hardening&lt;/td&gt;
&lt;td&gt;Correct incremental Canvas branch restored and protected by 50/100-page E2E tests.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  Headline measured results
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Before&lt;/th&gt;
&lt;th&gt;After&lt;/th&gt;
&lt;th&gt;Improvement&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;HTML footer, no logo&lt;/td&gt;
&lt;td&gt;7.82 s&lt;/td&gt;
&lt;td&gt;1.43 s&lt;/td&gt;
&lt;td&gt;~81.7% less time / 5.47× faster&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HTML footer + logo&lt;/td&gt;
&lt;td&gt;11.81 s&lt;/td&gt;
&lt;td&gt;1.29 s&lt;/td&gt;
&lt;td&gt;~89.1% less time / 9.16× faster&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Footer-heavy PDF&lt;/td&gt;
&lt;td&gt;~46.7 MB&lt;/td&gt;
&lt;td&gt;~1.0 MB&lt;/td&gt;
&lt;td&gt;~97.9% smaller&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No-logo peak heap&lt;/td&gt;
&lt;td&gt;102.6 MB&lt;/td&gt;
&lt;td&gt;26.5 MB&lt;/td&gt;
&lt;td&gt;~74.2% lower&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Giant Canvas capture geometry&lt;/td&gt;
&lt;td&gt;~99.96M px&lt;/td&gt;
&lt;td&gt;~1.74M px/page&lt;/td&gt;
&lt;td&gt;~98.26% lower peak capture area&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These percentages describe specific benchmark fixtures or capture geometry; they are &lt;strong&gt;not&lt;/strong&gt; universal whole-package speed or memory guarantees.&lt;/p&gt;

&lt;h4&gt;
  
  
  Current incremental Canvas correctness
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Requested pages&lt;/th&gt;
&lt;th&gt;Actual pages&lt;/th&gt;
&lt;th&gt;Time&lt;/th&gt;
&lt;th&gt;PDF size&lt;/th&gt;
&lt;th&gt;Largest encoded Canvas&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;1.53 s&lt;/td&gt;
&lt;td&gt;1.5 MB&lt;/td&gt;
&lt;td&gt;1191 × 1461&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;25&lt;/td&gt;
&lt;td&gt;25&lt;/td&gt;
&lt;td&gt;4.33 s&lt;/td&gt;
&lt;td&gt;3.9 MB&lt;/td&gt;
&lt;td&gt;1191 × 1461&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;40&lt;/td&gt;
&lt;td&gt;40&lt;/td&gt;
&lt;td&gt;7.54 s&lt;/td&gt;
&lt;td&gt;6.2 MB&lt;/td&gt;
&lt;td&gt;1191 × 1461&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;50&lt;/td&gt;
&lt;td&gt;50&lt;/td&gt;
&lt;td&gt;9.68 s&lt;/td&gt;
&lt;td&gt;7.8 MB&lt;/td&gt;
&lt;td&gt;1191 × 1461&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;60&lt;/td&gt;
&lt;td&gt;60&lt;/td&gt;
&lt;td&gt;12.56 s&lt;/td&gt;
&lt;td&gt;9.3 MB&lt;/td&gt;
&lt;td&gt;1191 × 1461&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;75&lt;/td&gt;
&lt;td&gt;75&lt;/td&gt;
&lt;td&gt;16.87 s&lt;/td&gt;
&lt;td&gt;11.7 MB&lt;/td&gt;
&lt;td&gt;1191 × 1461&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;25.25 s&lt;/td&gt;
&lt;td&gt;15.8 MB&lt;/td&gt;
&lt;td&gt;1191 × 1461&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The maximum encoded Canvas remained page-sized as the requested page count increased.&lt;/p&gt;

&lt;h4&gt;
  
  
  Encrypted raster PDFs
&lt;/h4&gt;

&lt;p&gt;The strongest high-retention behavior was reproduced with raw jsPDF, so the project documents it as &lt;strong&gt;memory retention&lt;/strong&gt; rather than mislabeling it as a permanent Vue memory leak.&lt;/p&gt;

&lt;p&gt;Upstream issue: &lt;a href="https://github.com/parallax/jsPDF/issues/4017" rel="noopener noreferrer"&gt;jsPDF #4017 - encrypted raster PDF memory retention&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For large text-heavy secured documents whose CSS is supported by the vector renderer, selectable-text mode can be much lighter than raster Canvas mode. This is workload-dependent, not a universal renderer benchmark.&lt;/p&gt;

&lt;h4&gt;
  
  
  Verification mindset
&lt;/h4&gt;

&lt;p&gt;Large exports are checked with more than “the Promise resolved”: actual page count, Blob size, Canvas dimensions, cancellation/recovery and cleanup signals are part of the regression strategy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://vue-pdf-export-docs.vercel.app/use-cases/performance-report" rel="noopener noreferrer"&gt;Read the complete phase-by-phase engineering report&lt;/a&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  Fonts, Charts, SVG and Image Optimization
&lt;/h3&gt;

&lt;p&gt;The following media controls are part of the published &lt;code&gt;vue-pdf-export&lt;/code&gt; API. Use the current official reference when integrating them.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;vue-pdf-export&lt;/code&gt; generates PDFs in the browser from Vue 3 content. It prepares media in a private export clone: it waits for fonts, snapshots chart canvases, applies the SVG policy and optionally optimizes images. The live Vue page stays intact, and temporary DOM, font registrations and caches are cleaned after completion, failure or cancellation.&lt;/p&gt;

&lt;h4&gt;
  
  
  Configure media for a Vue PDF
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Html2Pdf&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;PdfFontSource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;PdfImageOptimizationOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fonts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PdfFontSource&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Report Sans&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/fonts/report-sans.ttf&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ttf&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;autoOptimize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PdfImageOptimizationOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;targetDpi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;144&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;jpegQuality&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.85&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;preserveAlpha&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;cacheRepeated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt;
    &lt;span class="na"&gt;render-mode=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;
    &lt;span class="na"&gt;:fonts=&lt;/span&gt;&lt;span class="s"&gt;"fonts"&lt;/span&gt;
    &lt;span class="na"&gt;:auto-optimize=&lt;/span&gt;&lt;span class="s"&gt;"autoOptimize"&lt;/span&gt;
    &lt;span class="na"&gt;svg-mode=&lt;/span&gt;&lt;span class="s"&gt;"auto"&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;#pdf-content&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;article&amp;gt;&lt;/span&gt;Report content&lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/Html2Pdf&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;fonts&lt;/code&gt;, &lt;code&gt;autoOptimize&lt;/code&gt; and &lt;code&gt;svgMode&lt;/code&gt; can also be passed through &lt;code&gt;htmlToPdfOptions&lt;/code&gt;. Explicit component props win. &lt;code&gt;autoOptimize&lt;/code&gt; is off unless you enable it, so existing image quality stays as configured.&lt;/p&gt;

&lt;h4&gt;
  
  
  Custom fonts and selectable PDF text
&lt;/h4&gt;

&lt;p&gt;Export waits for &lt;code&gt;document.fonts.ready&lt;/code&gt; before layout. With no custom &lt;code&gt;fonts&lt;/code&gt; list, Canvas uses the page's computed CSS font. Selectable-text mode still measures the CSS layout but maps unregistered font families to built-in PDF faces. Register a matching file when the exact project font must appear as selectable text.&lt;/p&gt;

&lt;p&gt;Each &lt;code&gt;PdfFontSource&lt;/code&gt; takes &lt;code&gt;family&lt;/code&gt;, optional &lt;code&gt;style&lt;/code&gt; (&lt;code&gt;normal&lt;/code&gt; or &lt;code&gt;italic&lt;/code&gt;), optional &lt;code&gt;weight&lt;/code&gt;, &lt;code&gt;source&lt;/code&gt; (URL, &lt;code&gt;ArrayBuffer&lt;/code&gt; or &lt;code&gt;Uint8Array&lt;/code&gt;), and optional &lt;code&gt;format&lt;/code&gt; (&lt;code&gt;ttf&lt;/code&gt; or &lt;code&gt;otf&lt;/code&gt;). The CSS &lt;code&gt;font-family&lt;/code&gt; must match &lt;code&gt;family&lt;/code&gt;. Register the bold and italic files separately if the document uses them. The supported OTF path requires TrueType outlines; CFF-outline OTF, WOFF and WOFF2 cannot be embedded by this path. Remote URLs need working CORS, CSP and permission to use the font. Test the actual glyphs and language in a PDF viewer because shaping remains renderer-dependent.&lt;/p&gt;

&lt;h4&gt;
  
  
  Canvas charts and inline SVG
&lt;/h4&gt;

&lt;p&gt;Canvas charts are captured as export-only PNG snapshots. Static numeric labels and fixed callouts can be present in the PDF; live hover tooltips cannot remain interactive in a static document. The four-chart ApexCharts sample is &lt;strong&gt;playground-only&lt;/strong&gt; and does not add ApexCharts to the library's runtime requirements.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;code&gt;svgMode&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;Canvas PDF&lt;/th&gt;
&lt;th&gt;Selectable-text PDF&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;auto&lt;/code&gt; (default)&lt;/td&gt;
&lt;td&gt;Keep inline SVG in staging; the final page is rasterized&lt;/td&gt;
&lt;td&gt;Rasterize SVG because the text renderer does not draw SVG shapes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;preserve&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Keep inline SVG in staging&lt;/td&gt;
&lt;td&gt;Rasterize unsupported SVG shapes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;rasterize&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Snapshot SVG into an image first&lt;/td&gt;
&lt;td&gt;Rasterize SVG&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;External SVG resources, filters, animation and &lt;code&gt;foreignObject&lt;/code&gt; can differ from the live browser. Test representative charts, logos and icons in both &lt;a href="https://vue-pdf-export-docs.vercel.app/get-started/rendering-modes" rel="noopener noreferrer"&gt;rendering modes&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Image quality and per-export reuse
&lt;/h4&gt;

&lt;p&gt;With &lt;code&gt;autoOptimize&lt;/code&gt;, oversized raster images are downscaled from their displayed size and &lt;code&gt;targetDpi&lt;/code&gt; (default 144). &lt;code&gt;maxWidth&lt;/code&gt; and &lt;code&gt;maxHeight&lt;/code&gt; cap output dimensions. &lt;code&gt;jpegQuality&lt;/code&gt; defaults to 0.85 and is limited to 0.1–1. &lt;code&gt;preserveAlpha&lt;/code&gt; defaults to &lt;code&gt;true&lt;/code&gt;, choosing PNG for suitable non-JPEG sources; setting it to &lt;code&gt;false&lt;/code&gt; flattens transparency onto white for JPEG. &lt;code&gt;cacheRepeated&lt;/code&gt; defaults to &lt;code&gt;true&lt;/code&gt; and reuses matching prepared sources, dimensions, format and quality during one export. Selectable-text rendering also has its own per-render image cache. Canvas pages remain raster page images, so object-level reuse is different.&lt;/p&gt;

&lt;p&gt;Repeated image watermarks reuse the prepared source within one export. Sparse layouts reuse a PDF image alias; dense tiled layouts reuse one transparent sheet per page size. Static Canvas footer HTML and unchanged slot captures also reuse preparation. Set &lt;code&gt;collectMetrics&lt;/code&gt; to inspect &lt;code&gt;metrics.media&lt;/code&gt; operation counts, including chart snapshots, SVG rasterizations, optimized images, cache hits, watermark reuse and footer captures. These counters are not a speed or byte-saving guarantee. See &lt;a href="https://vue-pdf-export-docs.vercel.app/api/watermarks" rel="noopener noreferrer"&gt;watermarks&lt;/a&gt; and &lt;a href="https://vue-pdf-export-docs.vercel.app/use-cases/performance-engineering" rel="noopener noreferrer"&gt;performance engineering&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  CORS, failure and cleanup
&lt;/h4&gt;

&lt;p&gt;Use same-origin media, a server that permits the page origin through CORS, or suitable data URLs. If image optimization cannot decode a cross-origin image, it leaves the staging image in place and warns; the renderer may still fail under its own CORS policy. A CORS-tainted watermark raises an error. Remote fonts can also fail during fetch. Private staging and temporary font registrations are cleaned on success, error and cancellation. See &lt;a href="https://vue-pdf-export-docs.vercel.app/use-cases/images-cors" rel="noopener noreferrer"&gt;images and CORS&lt;/a&gt; for recovery steps.&lt;/p&gt;

&lt;h4&gt;
  
  
  Media, pagination and cleanup improvements
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Selectable-text table continuation now places an automatic split and repeated heading before the first row that crowds a measured page boundary. The inspected playground fixture no longer has a row-only page at that boundary. Oversized indivisible cells remain a limit.&lt;/li&gt;
&lt;li&gt;A large source logo used at a small header/footer size is rasterized proportionally for selectable-text output. A local nine-page fixture shrank from about 973 KB to about 300 KB; other documents can differ.&lt;/li&gt;
&lt;li&gt;Canvas page encoding uses &lt;code&gt;toBlob&lt;/code&gt; and binary bytes where available, with a data-URL fallback. The playground’s JPEG quality was set to 0.88 in the measured demo configuration; that setting is not a library default.&lt;/li&gt;
&lt;li&gt;Export HTML paths for headers, footers and slots are sanitized before staging insertion. A cancelled preflight and late-result guard prevent a cancelled generation from opening a completed preview.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;See &lt;a href="https://vue-pdf-export-docs.vercel.app/get-started/pagination" rel="noopener noreferrer"&gt;pagination&lt;/a&gt;, &lt;a href="https://vue-pdf-export-docs.vercel.app/api/security" rel="noopener noreferrer"&gt;security&lt;/a&gt; and &lt;a href="https://vue-pdf-export-docs.vercel.app/use-cases/project-flow" rel="noopener noreferrer"&gt;project flow&lt;/a&gt; for their boundaries.&lt;/p&gt;

&lt;h4&gt;
  
  
  Verification scope
&lt;/h4&gt;

&lt;p&gt;The library's media verification records unit, TypeScript and build checks, Chromium and WebKit exports, and selected visual PDF inspections. Local Firefox verification failed at the headless graphics launch and remains open. Later pagination and footer fixes have narrower checks. These results cover named fixtures, not arbitrary HTML/CSS or a universal speed target. The &lt;a href="https://vue-pdf-export-docs.vercel.app/use-cases/testing-browser-support" rel="noopener noreferrer"&gt;testing guide&lt;/a&gt; explains how to verify your own content.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://vue-pdf-export-docs.vercel.app/use-cases/project-flow" rel="noopener noreferrer"&gt;generation-flow guide&lt;/a&gt; shows where preparation, rendering and cleanup happen in the package.&lt;/p&gt;




&lt;h3&gt;
  
  
  PDF Generation Flow
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;vue-pdf-export&lt;/code&gt; exposes an &lt;code&gt;Html2Pdf&lt;/code&gt; component and a &lt;code&gt;useHtml2Pdf&lt;/code&gt; composable. The component coordinates props, slots, pagination, preview and download. The composable manages generation state, progress, cancellation and output URLs. The core prepares content and chooses a renderer; renderer modules own Canvas or selectable-text output.&lt;/p&gt;

&lt;h4&gt;
  
  
  From Vue content to PDF Blob
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;The component resolves options and, when a positive pagination height is supplied, plans DOM page breaks. Direct composable calls provide their own prepared element and page breaks.&lt;/li&gt;
&lt;li&gt;Core creates a private export staging clone, applies export-only styles and ignore markers, waits for fonts and images, and prepares chart, SVG and image assets. The live Vue page is left alone.&lt;/li&gt;
&lt;li&gt;Selectable-text mode maps supported DOM text, shapes, images and links into PDF operations. Canvas mode captures page images, one page at a time when markers are available, or uses its classic html2pdf path otherwise.&lt;/li&gt;
&lt;li&gt;Page styling, watermarks, headers, footers, metadata, optional page composition and security are applied to the PDF.&lt;/li&gt;
&lt;li&gt;One serialized Blob feeds preview, download, print or output conversion. Cleanup releases staging content, temporary fonts and media caches; the UI later revokes its owned Blob URLs.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The public library defaults to Canvas. The playground can use its own demo defaults. Nuxt imports are SSR safe, but PDF generation needs a browser DOM. See &lt;a href="https://vue-pdf-export-docs.vercel.app/get-started/rendering-modes" rel="noopener noreferrer"&gt;rendering modes&lt;/a&gt;, &lt;a href="https://vue-pdf-export-docs.vercel.app/get-started/pagination" rel="noopener noreferrer"&gt;pagination&lt;/a&gt;, &lt;a href="https://vue-pdf-export-docs.vercel.app/use-cases/media-typography" rel="noopener noreferrer"&gt;media preparation&lt;/a&gt; and &lt;a href="https://vue-pdf-export-docs.vercel.app/api/programmatic-api" rel="noopener noreferrer"&gt;programmatic output&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For maintainers, the &lt;a href="https://github.com/saurabhzaiswal/vue-pdf-export" rel="noopener noreferrer"&gt;project repository&lt;/a&gt; includes source code and engineering context. Check the installed package APIs against the current &lt;a href="https://vue-pdf-export-docs.vercel.app/" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  Find answers in the official vue-pdf-export documentation
&lt;/h3&gt;

&lt;p&gt;For integration questions, search the current &lt;a href="https://vue-pdf-export-docs.vercel.app/" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt; and its API reference. Check the package API and browser limitations before copying an example.&lt;/p&gt;

&lt;h4&gt;
  
  
  What can this answer?
&lt;/h4&gt;

&lt;p&gt;Ask about selectable-text PDFs, Canvas rendering, Nuxt integration, page breaks, long tables, headers, footers, watermarks, fonts, image quality, and programmatic output. Cross-check answers against the &lt;a href="https://vue-pdf-export-docs.vercel.app/api/full-reference" rel="noopener noreferrer"&gt;current API reference&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Documentation examples cannot verify arbitrary application CSS or guarantee that a PDF will match every browser layout. Check your own exported PDF. For hands-on examples, see the &lt;a href="https://vue-pdf-export-docs.vercel.app/use-cases/playground" rel="noopener noreferrer"&gt;playground&lt;/a&gt;, &lt;a href="https://vue-pdf-export-docs.vercel.app/get-started/quick-start" rel="noopener noreferrer"&gt;quick start&lt;/a&gt;, &lt;a href="https://vue-pdf-export-docs.vercel.app/get-started/rendering-modes" rel="noopener noreferrer"&gt;rendering modes&lt;/a&gt;, and &lt;a href="https://vue-pdf-export-docs.vercel.app/use-cases/troubleshooting" rel="noopener noreferrer"&gt;troubleshooting&lt;/a&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  Vue to PDF in Vue 3 and Nuxt
&lt;/h3&gt;

&lt;p&gt;To turn a Vue component into a PDF in the browser, install &lt;code&gt;vue-pdf-export&lt;/code&gt;, put the document inside its &lt;code&gt;#pdf-content&lt;/code&gt; slot, and call &lt;code&gt;generatePdf()&lt;/code&gt; from a component ref. Choose Canvas rendering when visual CSS fidelity matters most, or selectable-text rendering when people must search and copy body text.&lt;/p&gt;

&lt;h4&gt;
  
  
  Generate a PDF from a Vue component
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Html2Pdf&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-pdf-export/style.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pdf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;InstanceType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;Html2Pdf&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;downloadReport&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;generatePdf&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"downloadReport"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Download report&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt; &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;"pdf"&lt;/span&gt; &lt;span class="na"&gt;filename=&lt;/span&gt;&lt;span class="s"&gt;"report.pdf"&lt;/span&gt; &lt;span class="na"&gt;render-mode=&lt;/span&gt;&lt;span class="s"&gt;"canvas"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;#pdf-content&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;article&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Report&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Rendered from a Vue component.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/article&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/Html2Pdf&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The package's default is Canvas. The explicit &lt;code&gt;render-mode&lt;/code&gt; above makes the choice visible. For a JavaScript Options API example and download settings, use the &lt;a href="https://vue-pdf-export-docs.vercel.app/get-started/quick-start" rel="noopener noreferrer"&gt;quick start&lt;/a&gt;. For Nuxt 3 and Nuxt 4, import the component safely during SSR and generate only after the browser mounts; see the &lt;a href="https://vue-pdf-export-docs.vercel.app/get-started/nuxt-ssr" rel="noopener noreferrer"&gt;Nuxt guide&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Which Vue PDF approach fits the document?
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Requirement&lt;/th&gt;
&lt;th&gt;Start with&lt;/th&gt;
&lt;th&gt;Tradeoff&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Match browser CSS, charts and visual reports&lt;/td&gt;
&lt;td&gt;&lt;a href="https://vue-pdf-export-docs.vercel.app/get-started/rendering-modes" rel="noopener noreferrer"&gt;Canvas mode&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;The page body becomes an image; readers cannot select its text.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Search, select or copy report text&lt;/td&gt;
&lt;td&gt;&lt;a href="https://vue-pdf-export-docs.vercel.app/use-cases/selectable-text" rel="noopener noreferrer"&gt;Selectable-text mode&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Some CSS, glyph and SVG behavior differs from the browser; test the actual document.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Print an entire server-rendered route without a browser user action&lt;/td&gt;
&lt;td&gt;A server browser such as &lt;a href="https://playwright.dev/docs/api/class-page#page-pdf" rel="noopener noreferrer"&gt;Playwright &lt;code&gt;page.pdf()&lt;/code&gt;&lt;/a&gt; in an appropriate &lt;a href="https://nuxt.com/docs/4.x/directory-structure/server" rel="noopener noreferrer"&gt;Nuxt server route&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;You operate a browser service and handle its server resources and access controls.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Display an existing PDF rather than create one&lt;/td&gt;
&lt;td&gt;A PDF viewer&lt;/td&gt;
&lt;td&gt;Viewing and generating are separate tasks.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The &lt;a href="https://github.com/eKoopmans/html2pdf.js" rel="noopener noreferrer"&gt;html2pdf.js project&lt;/a&gt; documents that its Canvas path renders content as an image, so text is not searchable or selectable. &lt;code&gt;vue-pdf-export&lt;/code&gt; exposes that style of capture as its Canvas mode and also provides a selectable-text renderer. These modes share the &lt;a href="https://vue-pdf-export-docs.vercel.app/api/component" rel="noopener noreferrer"&gt;component API&lt;/a&gt;, &lt;a href="https://vue-pdf-export-docs.vercel.app/get-started/pagination" rel="noopener noreferrer"&gt;pagination controls&lt;/a&gt;, preview, download and print flow.&lt;/p&gt;

&lt;h4&gt;
  
  
  Can Vue-generated PDFs be searched?
&lt;/h4&gt;

&lt;p&gt;Yes, when you use &lt;code&gt;render-mode="text"&lt;/code&gt; for the document body. PDF viewers can then select and search the emitted text. Canvas mode keeps the body as page images. Custom TTF or TrueType-outline OTF files can be registered for selectable text; CFF-outline OTF and WOFF/WOFF2 are not supported for embedding. See &lt;a href="https://vue-pdf-export-docs.vercel.app/use-cases/media-typography" rel="noopener noreferrer"&gt;fonts, charts, SVG and images&lt;/a&gt; for the renderer-specific limits.&lt;/p&gt;

&lt;h4&gt;
  
  
  Can I combine PDFs in Vue?
&lt;/h4&gt;

&lt;p&gt;You can &lt;a href="https://vue-pdf-export-docs.vercel.app/api/composition" rel="noopener noreferrer"&gt;prepend or append existing PDF pages&lt;/a&gt; to a generated document using the published composition options. This combines whole pages; it does not provide arbitrary editing of their internal content.&lt;/p&gt;

&lt;h4&gt;
  
  
  What should I test before shipping?
&lt;/h4&gt;

&lt;p&gt;Export a representative document in each target browser. Check page breaks, font loading, remote-image CORS, output size, links and text selection as applicable. For long reports, use &lt;a href="https://vue-pdf-export-docs.vercel.app/api/events-slots" rel="noopener noreferrer"&gt;page-aware progress, cancellation and generation metrics&lt;/a&gt; and test a realistic page count. The &lt;a href="https://vue-pdf-export-docs.vercel.app/use-cases/production-guide" rel="noopener noreferrer"&gt;production guide&lt;/a&gt; covers release checks.&lt;/p&gt;




&lt;h2&gt;
  
  
  Links and feedback
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://vue-pdf-export-playground.vercel.app/" rel="noopener noreferrer"&gt;Try the live playground&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://vue-pdf-export-docs.vercel.app/" rel="noopener noreferrer"&gt;Read the full documentation&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.npmjs.com/package/vue-pdf-export" rel="noopener noreferrer"&gt;Install from npm&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://github.com/saurabhzaiswal/vue-pdf-export" rel="noopener noreferrer"&gt;Explore the source on GitHub&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are using Vue 3 or Nuxt and have run into PDF pagination, selectable-text, CORS, headers/footers, or browser-memory issues, I would love to hear what you are building and which edge cases are hardest.&lt;/p&gt;

&lt;p&gt;If this project has been useful, you can &lt;a href="https://buymeacoffee.com/saurabhzaiswal" rel="noopener noreferrer"&gt;support its development&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>vue</category>
      <category>opensource</category>
      <category>typescript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Building Better PDF Workflows in Vue 3 with vue-pdf-export</title>
      <dc:creator>Saurabh Choudhary</dc:creator>
      <pubDate>Sat, 12 Sep 2026 16:27:39 +0000</pubDate>
      <link>https://dev.to/saurabhzaiswal/building-better-pdf-workflows-in-vue-3-with-vue-pdf-export-9ed</link>
      <guid>https://dev.to/saurabhzaiswal/building-better-pdf-workflows-in-vue-3-with-vue-pdf-export-9ed</guid>
      <description>&lt;p&gt;Hey Vue developers 👋&lt;/p&gt;

&lt;p&gt;I’ve been working on &lt;code&gt;vue-pdf-export&lt;/code&gt;, a Vue 3 + TypeScript package for generating PDFs directly in the browser.&lt;/p&gt;

&lt;p&gt;I originally created it because I kept rebuilding the same PDF features across different Vue projects - pagination, preview, printing, headers, footers, progress handling, and long-document support.&lt;/p&gt;

&lt;p&gt;Some of the things it supports today:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Canvas and selectable/searchable PDF text&lt;/li&gt;
&lt;li&gt;Automatic and manual pagination&lt;/li&gt;
&lt;li&gt;Preview, download, and browser print&lt;/li&gt;
&lt;li&gt;Headers and footers&lt;/li&gt;
&lt;li&gt;Watermarks&lt;/li&gt;
&lt;li&gt;Password protection and PDF permissions&lt;/li&gt;
&lt;li&gt;Clickable links&lt;/li&gt;
&lt;li&gt;Progress reporting and cancellation&lt;/li&gt;
&lt;li&gt;Blob, ArrayBuffer, and Base64 output&lt;/li&gt;
&lt;li&gt;Export-only styling and &lt;code&gt;data-pdf-ignore&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Nuxt 3 and Nuxt 4 SSR-safe imports&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Install
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;vue-pdf-export
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Small example
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Html2Pdf&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue-pdf-export/style.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pdfRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;InstanceType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;Html2Pdf&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"pdfRef?.generatePdf()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Generate PDF
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt; &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;"pdfRef"&lt;/span&gt; &lt;span class="na"&gt;filename=&lt;/span&gt;&lt;span class="s"&gt;"report.pdf"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;#pdf-content&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Hello from Vue&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;This content will be exported to PDF.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/Html2Pdf&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;Playground:&lt;br&gt;&lt;br&gt;
&lt;a href="https://vue-pdf-export-playground.vercel.app/" rel="noopener noreferrer"&gt;https://vue-pdf-export-playground.vercel.app/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Documentation:&lt;br&gt;&lt;br&gt;
&lt;a href="https://vue-pdf-export-docs.vercel.app/" rel="noopener noreferrer"&gt;https://vue-pdf-export-docs.vercel.app/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;npm:&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.npmjs.com/package/vue-pdf-export" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/vue-pdf-export&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’d really like feedback from Vue developers who have worked with PDFs in production - especially around pagination, large documents, selectable text, and API ergonomics.&lt;/p&gt;

</description>
      <category>vue</category>
      <category>npm</category>
      <category>nuxt</category>
      <category>typescript</category>
    </item>
    <item>
      <title>I built vue-pdf-export - a Vue 3 PDF Export library for real-world browser apps</title>
      <dc:creator>Saurabh Choudhary</dc:creator>
      <pubDate>Sat, 12 Sep 2026 11:24:34 +0000</pubDate>
      <link>https://dev.to/saurabhzaiswal/i-built-vue-pdf-export-a-vue-3-pdf-export-library-for-real-world-browser-apps-27km</link>
      <guid>https://dev.to/saurabhzaiswal/i-built-vue-pdf-export-a-vue-3-pdf-export-library-for-real-world-browser-apps-27km</guid>
      <description>&lt;p&gt;Hey everyone 👋&lt;/p&gt;

&lt;p&gt;I recently released &lt;a href="https://www.npmjs.com/package/vue-pdf-export" rel="noopener noreferrer"&gt;&lt;code&gt;vue-pdf-export&lt;/code&gt;&lt;/a&gt;, a Vue 3 + TypeScript library for generating PDFs directly in the browser.&lt;/p&gt;

&lt;p&gt;I built it after repeatedly needing the same PDF features across different Vue projects and wanting one reusable solution instead of rebuilding the same logic each time.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it supports
&lt;/h2&gt;

&lt;p&gt;Some of the main features include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Canvas and selectable-text PDF rendering&lt;/li&gt;
&lt;li&gt;Automatic and manual pagination&lt;/li&gt;
&lt;li&gt;Preview, download, and browser print&lt;/li&gt;
&lt;li&gt;Headers and footers&lt;/li&gt;
&lt;li&gt;Watermarks and page targeting&lt;/li&gt;
&lt;li&gt;Clickable PDF links&lt;/li&gt;
&lt;li&gt;Password protection and permissions&lt;/li&gt;
&lt;li&gt;PDF metadata and compression&lt;/li&gt;
&lt;li&gt;Progress reporting and cancellation&lt;/li&gt;
&lt;li&gt;Large-document rendering&lt;/li&gt;
&lt;li&gt;Blob, ArrayBuffer, Base64, and PDF data URL outputs&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;data-pdf-ignore&lt;/code&gt; for excluding UI elements from exports&lt;/li&gt;
&lt;li&gt;Export-only page and body styling&lt;/li&gt;
&lt;li&gt;Nuxt 3 and Nuxt 4 SSR-safe package imports&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The package also has compatibility coverage for npm, pnpm, Yarn, Yarn Plug'n'Play, and Bun.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;vue-pdf-export
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Basic usage
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Html2Pdf&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue-pdf-export/style.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pdf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;InstanceType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;Html2Pdf&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"pdf?.generatePdf()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Generate PDF
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt;
    &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;"pdf"&lt;/span&gt;
    &lt;span class="na"&gt;filename=&lt;/span&gt;&lt;span class="s"&gt;"example.pdf"&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;#pdf-content&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Hello from Vue&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;This content will be exported to PDF.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/Html2Pdf&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Canvas or selectable text
&lt;/h2&gt;

&lt;p&gt;Use Canvas rendering when HTML/CSS fidelity is the priority:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt; &lt;span class="na"&gt;render-mode=&lt;/span&gt;&lt;span class="s"&gt;"canvas"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or use selectable-text rendering when users need to select, search, and copy text from the generated PDF:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt; &lt;span class="na"&gt;render-mode=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes the package useful for both highly visual layouts and text-heavy documents such as reports, invoices, statements, and documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Programmatic output
&lt;/h2&gt;

&lt;p&gt;The generated PDF can also be used directly in your application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;blob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;generatePdf&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;generatePdfArrayBuffer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;base64&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;generatePdfBase64&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is useful when you want to upload, store, preview, or pass the PDF to another API instead of immediately downloading it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nuxt support
&lt;/h2&gt;

&lt;p&gt;The package is designed so importing it does not crash Nuxt SSR.&lt;/p&gt;

&lt;p&gt;Actual PDF generation still happens in the browser, so a typical Nuxt integration can use &lt;code&gt;ClientOnly&lt;/code&gt; or lazy client-side rendering when needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;🧪 &lt;strong&gt;Live Playground&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://vue-pdf-export-playground.vercel.app/" rel="noopener noreferrer"&gt;https://vue-pdf-export-playground.vercel.app/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📖 &lt;strong&gt;Documentation&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://vue-pdf-export-docs.vercel.app/" rel="noopener noreferrer"&gt;https://vue-pdf-export-docs.vercel.app/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📦 &lt;strong&gt;npm&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.npmjs.com/package/vue-pdf-export" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/vue-pdf-export&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;💬 &lt;strong&gt;Feature requests &amp;amp; feedback&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://vue3-pdf-export.canny.io/" rel="noopener noreferrer"&gt;https://vue3-pdf-export.canny.io/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’d really appreciate feedback from Vue and Nuxt developers, especially around real-world PDF edge cases, API ergonomics, pagination, large documents, or features you would expect from a Vue PDF library.&lt;/p&gt;

&lt;p&gt;The project is still evolving, and real-world feedback is one of the most useful inputs for deciding what to improve next.&lt;/p&gt;

</description>
      <category>vue</category>
      <category>nuxt</category>
      <category>typescript</category>
      <category>npm</category>
    </item>
    <item>
      <title>I Kept Rebuilding PDF Features in Vue 3, So I Built vue-pdf-export</title>
      <dc:creator>Saurabh Choudhary</dc:creator>
      <pubDate>Thu, 03 Sep 2026 23:41:35 +0000</pubDate>
      <link>https://dev.to/saurabhzaiswal/generating-pdfs-in-vue-3-was-messy-so-i-built-vue3-pdf-export-3idb</link>
      <guid>https://dev.to/saurabhzaiswal/generating-pdfs-in-vue-3-was-messy-so-i-built-vue3-pdf-export-3idb</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fledtyo9ulq60rb3lozk1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fledtyo9ulq60rb3lozk1.png" alt="vue3-pdf-export logo" width="799" height="164"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  I Kept Rebuilding PDF Features in Vue 3, So I Built &lt;code&gt;vue-pdf-export&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;I recently published &lt;strong&gt;&lt;code&gt;vue-pdf-export&lt;/code&gt;&lt;/strong&gt;, a Vue + TypeScript package for generating PDFs directly from HTML in browser applications.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Vue + TypeScript browser PDF generation with Canvas and selectable-text
rendering, pagination, preview, large-document support, cancellation,
progress reporting, headers, footers, watermarks, security, metadata,
compression, links, and more.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why I built it
&lt;/h2&gt;

&lt;p&gt;Before publishing &lt;code&gt;vue-pdf-export&lt;/code&gt;, I had already worked on PDF generation in different projects, including Google projects, CRM applications, and other Vue-based applications.&lt;/p&gt;

&lt;p&gt;I tried different HTML-to-PDF approaches and existing libraries, but in real projects I often ended up building my own custom Vue PDF component around them to handle the specific requirements I needed.&lt;/p&gt;

&lt;p&gt;Whenever a new project needed PDF generation, I found myself solving many of the same problems again:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;pagination&lt;/li&gt;
&lt;li&gt;page breaks&lt;/li&gt;
&lt;li&gt;preview&lt;/li&gt;
&lt;li&gt;download&lt;/li&gt;
&lt;li&gt;printing&lt;/li&gt;
&lt;li&gt;headers and footers&lt;/li&gt;
&lt;li&gt;image handling&lt;/li&gt;
&lt;li&gt;different PDF options&lt;/li&gt;
&lt;li&gt;loading states&lt;/li&gt;
&lt;li&gt;long-running generation&lt;/li&gt;
&lt;li&gt;browser memory usage&lt;/li&gt;
&lt;li&gt;security and metadata&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This time, instead of creating another project-specific component, I decided to build a cleaner and more complete solution that I could reuse across Vue projects.&lt;/p&gt;

&lt;p&gt;That became &lt;code&gt;vue-pdf-export&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The main reason was simple: I did not want to keep rebuilding the same PDF functionality again and again.&lt;/p&gt;

&lt;p&gt;And if it can also save time for other Vue developers who need similar PDF features, even better.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;vue-pdf-export
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Basic usage
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt; &lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Html2Pdf&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue3-pdf-export&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue3-pdf-export/style.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pdf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;InstanceType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;Html2Pdf&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;generatePdf&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"generate"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Generate PDF
  &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt;
    &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;"pdf"&lt;/span&gt;
    &lt;span class="na"&gt;filename=&lt;/span&gt;&lt;span class="s"&gt;"example.pdf"&lt;/span&gt;
    &lt;span class="na"&gt;:preview-modal=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;#pdf-content&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;main&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Hello from Vue&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;This content will be exported to PDF.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/main&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/Html2Pdf&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Two rendering modes
&lt;/h2&gt;

&lt;p&gt;One of the biggest additions is support for two different PDF rendering strategies.&lt;/p&gt;

&lt;h3&gt;
  
  
  Canvas mode
&lt;/h3&gt;

&lt;p&gt;Canvas mode is the traditional HTML-to-PDF path and is best when browser CSS fidelity is the main priority.&lt;/p&gt;

&lt;p&gt;It uses the familiar html2pdf.js / html2canvas / jsPDF pipeline underneath.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt; &lt;span class="na"&gt;render-mode=&lt;/span&gt;&lt;span class="s"&gt;"canvas"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This remains the package default for backward compatibility.&lt;/p&gt;

&lt;h3&gt;
  
  
  Selectable text mode
&lt;/h3&gt;

&lt;p&gt;Text mode generates real PDF text instead of rasterizing the body into a canvas.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Html2Pdf&lt;/span&gt; &lt;span class="na"&gt;render-mode=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The resulting text can be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;selected&lt;/li&gt;
&lt;li&gt;searched&lt;/li&gt;
&lt;li&gt;copied&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This can be especially useful for reports, invoices, documentation, and other text-heavy PDFs.&lt;/p&gt;

&lt;p&gt;Because this renderer does not behave exactly like a browser layout engine, some advanced CSS may render differently compared with Canvas mode.&lt;/p&gt;

&lt;p&gt;The idea is to let developers choose between maximum browser-style fidelity and real selectable PDF text depending on their use case.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pagination
&lt;/h2&gt;

&lt;p&gt;The package supports both automatic and manual pagination.&lt;/p&gt;

&lt;p&gt;For an explicit manual page break:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"html2pdf__page-break"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are also options for keeping elements together and avoiding unwanted page breaks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Large-document rendering
&lt;/h2&gt;

&lt;p&gt;Large PDFs were one of the areas I wanted to improve significantly.&lt;/p&gt;

&lt;p&gt;Canvas rendering can become expensive when a browser attempts to create one extremely tall canvas for an entire document.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;vue3-pdf-export&lt;/code&gt; can now render paginated Canvas documents incrementally, page by page, instead of depending on one giant full-document capture.&lt;/p&gt;

&lt;p&gt;In one benchmark fixture, the previous long-document capture surface was around:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;99.96 million pixels
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;while incremental rendering kept the maximum capture surface around:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1.74 million pixels per page
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is approximately a 98.26% reduction in peak capture-surface geometry for that fixture.&lt;/p&gt;

&lt;p&gt;This is specifically a rendering-surface measurement, not a claim that total browser memory always drops by the same percentage.&lt;/p&gt;

&lt;p&gt;The current regression suite includes documents across:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10 / 25 / 40 / 50 / 60 / 75 / 100 pages
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;50-page and 100-page Canvas documents are part of the current verified test range.&lt;/p&gt;

&lt;p&gt;100 pages is not a hard package limit. Practical limits still depend on the document, images, browser memory, rendering mode, security settings, and the device being used.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cancellation
&lt;/h2&gt;

&lt;p&gt;Long-running PDF generation can now be cancelled.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;cancelGeneration&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cancellation is cooperative and works across the generation pipeline.&lt;/p&gt;

&lt;p&gt;The library also tests recovery after cancellation, so a new PDF can be generated after an earlier operation was cancelled.&lt;/p&gt;

&lt;p&gt;Some already-running synchronous browser operations cannot always be stopped immediately, but the pipeline checks for cancellation between major stages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Page-aware progress
&lt;/h2&gt;

&lt;p&gt;Progress reporting now includes more than a simple percentage.&lt;/p&gt;

&lt;p&gt;The package can expose:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;current progress&lt;/li&gt;
&lt;li&gt;current page&lt;/li&gt;
&lt;li&gt;total pages&lt;/li&gt;
&lt;li&gt;current processing stage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Stages include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pagination
images
preparing
rendering
watermark
header
footer
metadata
serializing
complete
error
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes it possible to build UI such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Rendering page 18 of 50...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;instead of showing an indefinite spinner.&lt;/p&gt;

&lt;h2&gt;
  
  
  Headers
&lt;/h2&gt;

&lt;p&gt;Headers can contain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;plain text&lt;/li&gt;
&lt;li&gt;trusted HTML&lt;/li&gt;
&lt;li&gt;optional logos&lt;/li&gt;
&lt;li&gt;custom backgrounds and text colors&lt;/li&gt;
&lt;li&gt;configurable logo dimensions&lt;/li&gt;
&lt;li&gt;selected-page targeting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A header can appear on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;all pages&lt;/li&gt;
&lt;li&gt;the first page only&lt;/li&gt;
&lt;li&gt;the last page only&lt;/li&gt;
&lt;li&gt;every page except the first&lt;/li&gt;
&lt;li&gt;explicit page numbers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Selective header targeting also uses page-aware spacing, so header space is reserved only where the header is actually rendered.&lt;/p&gt;

&lt;h2&gt;
  
  
  Footers
&lt;/h2&gt;

&lt;p&gt;Footers support:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTML mode&lt;/li&gt;
&lt;li&gt;text mode&lt;/li&gt;
&lt;li&gt;trusted HTML content&lt;/li&gt;
&lt;li&gt;optional logos&lt;/li&gt;
&lt;li&gt;configurable logo dimensions&lt;/li&gt;
&lt;li&gt;background and text colors&lt;/li&gt;
&lt;li&gt;page-number templates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Page {n} of {total}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Header and footer logos preserve their aspect ratio instead of being stretched into a fixed box.&lt;/p&gt;

&lt;h3&gt;
  
  
  Footer performance improvements
&lt;/h3&gt;

&lt;p&gt;Static HTML footers are now rendered once and reused across pages instead of being rasterized repeatedly.&lt;/p&gt;

&lt;p&gt;In project benchmark fixtures:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HTML footer without logo
7.82s -&amp;gt; 1.43s

HTML footer with logo
11.81s -&amp;gt; 1.29s

Footer-heavy PDF size
~46.7 MB -&amp;gt; ~1.0 MB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These numbers are specific to the benchmark fixtures and should not be treated as universal performance guarantees.&lt;/p&gt;

&lt;h2&gt;
  
  
  Repeated image optimization
&lt;/h2&gt;

&lt;p&gt;Selectable-text rendering now caches repeated images within a single generation.&lt;/p&gt;

&lt;p&gt;If the same image is reused across many pages, the package can avoid repeatedly loading and encoding the same source.&lt;/p&gt;

&lt;p&gt;The cache is scoped to one PDF generation and is cleared afterward.&lt;/p&gt;

&lt;p&gt;This is especially useful for documents containing repeated logos, icons, product images, or other shared assets.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resource cleanup
&lt;/h2&gt;

&lt;p&gt;A lot of work also went into cleaning temporary resources earlier.&lt;/p&gt;

&lt;p&gt;The generation pipeline now handles cleanup of things such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;temporary cloned DOM nodes&lt;/li&gt;
&lt;li&gt;temporary canvases&lt;/li&gt;
&lt;li&gt;encoded image data&lt;/li&gt;
&lt;li&gt;per-generation image caches&lt;/li&gt;
&lt;li&gt;rendering state&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Canvas backing stores are also released when possible after they are no longer needed.&lt;/p&gt;

&lt;p&gt;Repeated-generation and isolation tests were added to help detect regressions in cleanup behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  Browser responsiveness
&lt;/h2&gt;

&lt;p&gt;Large PDF generation is naturally expensive, especially in Canvas mode.&lt;/p&gt;

&lt;p&gt;The pipeline now yields between selected expensive operations so the browser gets opportunities to process UI work while generation is running.&lt;/p&gt;

&lt;p&gt;Combined with cancellation and page-aware progress, this makes long-running generation easier to integrate into real applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Watermarks
&lt;/h2&gt;

&lt;p&gt;Watermarks can be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;text or image&lt;/li&gt;
&lt;li&gt;foreground or background&lt;/li&gt;
&lt;li&gt;single or repeated&lt;/li&gt;
&lt;li&gt;rotated&lt;/li&gt;
&lt;li&gt;positioned&lt;/li&gt;
&lt;li&gt;configured with opacity&lt;/li&gt;
&lt;li&gt;targeted to selected PDF pages&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  PDF security
&lt;/h2&gt;

&lt;p&gt;You can optionally generate password-protected PDFs with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;user/open password&lt;/li&gt;
&lt;li&gt;owner password&lt;/li&gt;
&lt;li&gt;configurable permissions&lt;/li&gt;
&lt;li&gt;password construction from multiple password parts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Supported permission controls include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;print
modify
copy
annot-forms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Metadata and compression
&lt;/h2&gt;

&lt;p&gt;PDF metadata can include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;title&lt;/li&gt;
&lt;li&gt;author&lt;/li&gt;
&lt;li&gt;subject&lt;/li&gt;
&lt;li&gt;keywords&lt;/li&gt;
&lt;li&gt;creator&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;jsPDF stream compression can also be enabled when needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Clickable links
&lt;/h2&gt;

&lt;p&gt;PDF link annotations are also supported, allowing links in generated documents to remain interactive instead of becoming plain visual text.&lt;/p&gt;

&lt;h2&gt;
  
  
  Safer filenames
&lt;/h2&gt;

&lt;p&gt;Generated filenames are normalized before download.&lt;/p&gt;

&lt;p&gt;This includes handling invalid filename characters, whitespace, reserved Windows names, trailing dots or spaces, and overly long filenames.&lt;/p&gt;

&lt;p&gt;Unicode filenames are still preserved.&lt;/p&gt;

&lt;h2&gt;
  
  
  A note about encrypted raster PDFs
&lt;/h2&gt;

&lt;p&gt;While profiling larger secured documents, I found that encrypted raster PDFs could retain significantly more browser memory than equivalent unencrypted PDFs.&lt;/p&gt;

&lt;p&gt;I reproduced the behavior directly with jsPDF outside the main &lt;code&gt;vue3-pdf-export&lt;/code&gt; rendering pipeline.&lt;/p&gt;

&lt;p&gt;That means a substantial part of this behavior appears to come from the underlying PDF library rather than from the Vue component itself.&lt;/p&gt;

&lt;p&gt;I opened an upstream jsPDF issue with the reproduction and benchmark details:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/parallax/jsPDF/issues/4017" rel="noopener noreferrer"&gt;https://github.com/parallax/jsPDF/issues/4017&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For large secured documents, selectable-text mode can sometimes be a useful alternative because text-based PDFs are generally much smaller than equivalent rasterized documents.&lt;/p&gt;

&lt;p&gt;This is still workload-dependent, so applications generating large encrypted PDFs should test their own representative content.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing and performance work
&lt;/h2&gt;

&lt;p&gt;The project now includes automated testing around:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;unit behavior&lt;/li&gt;
&lt;li&gt;Chromium&lt;/li&gt;
&lt;li&gt;Firefox&lt;/li&gt;
&lt;li&gt;WebKit&lt;/li&gt;
&lt;li&gt;large documents&lt;/li&gt;
&lt;li&gt;Canvas rendering&lt;/li&gt;
&lt;li&gt;selectable-text rendering&lt;/li&gt;
&lt;li&gt;cancellation and recovery&lt;/li&gt;
&lt;li&gt;image-heavy documents&lt;/li&gt;
&lt;li&gt;repeated images&lt;/li&gt;
&lt;li&gt;footer optimization&lt;/li&gt;
&lt;li&gt;browser cleanup&lt;/li&gt;
&lt;li&gt;security behavior&lt;/li&gt;
&lt;li&gt;memory measurements&lt;/li&gt;
&lt;li&gt;repeated generation&lt;/li&gt;
&lt;li&gt;stress testing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The current unit suite contains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;19 test files
106 tests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are also dedicated benchmark and Playwright workflows for performance-heavy scenarios.&lt;/p&gt;

&lt;p&gt;For heavy PDF tests, I intentionally run browser work sequentially where appropriate so multiple workers do not distort memory measurements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I built a Vue layer instead of replacing the underlying libraries
&lt;/h2&gt;

&lt;p&gt;The goal was never to pretend that &lt;code&gt;html2pdf.js&lt;/code&gt;, &lt;code&gt;html2canvas&lt;/code&gt;, or &lt;code&gt;jsPDF&lt;/code&gt; do not exist.&lt;/p&gt;

&lt;p&gt;Those libraries still provide important pieces of the Canvas rendering pipeline.&lt;/p&gt;

&lt;p&gt;The goal of &lt;code&gt;vue3-pdf-export&lt;/code&gt; is to provide a Vue-oriented layer around PDF generation so common production requirements do not need to be rebuilt for every application.&lt;/p&gt;

&lt;p&gt;At the same time, developers can still pass advanced html2pdf.js and jsPDF options when the higher-level API is not enough.&lt;/p&gt;

&lt;p&gt;The selectable-text renderer provides another option for cases where real PDF text matters more than exact Canvas-style browser rendering.&lt;/p&gt;

&lt;h2&gt;
  
  
  Current release
&lt;/h2&gt;

&lt;p&gt;The current release is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vue-pdf-export v1.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The project has grown significantly since the original release, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Canvas and selectable-text rendering modes&lt;/li&gt;
&lt;li&gt;incremental page-by-page Canvas generation&lt;/li&gt;
&lt;li&gt;large-document regression coverage&lt;/li&gt;
&lt;li&gt;cancellation and recovery&lt;/li&gt;
&lt;li&gt;current-page / total-page progress&lt;/li&gt;
&lt;li&gt;repeated-image caching&lt;/li&gt;
&lt;li&gt;footer rendering optimization&lt;/li&gt;
&lt;li&gt;earlier DOM and Canvas cleanup&lt;/li&gt;
&lt;li&gt;browser responsiveness improvements&lt;/li&gt;
&lt;li&gt;PDF security&lt;/li&gt;
&lt;li&gt;metadata and compression&lt;/li&gt;
&lt;li&gt;clickable links&lt;/li&gt;
&lt;li&gt;trusted HTML headers and footers&lt;/li&gt;
&lt;li&gt;logo support&lt;/li&gt;
&lt;li&gt;watermarks&lt;/li&gt;
&lt;li&gt;filename normalization&lt;/li&gt;
&lt;li&gt;expanded unit, browser, stress, and performance testing&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9qfvaw4w1z14k3m03c8t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9qfvaw4w1z14k3m03c8t.png" alt="vue-pdf-export Docs" width="800" height="380"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📄 &lt;strong&gt;Explore the documentation&lt;/strong&gt; : &lt;a href="https://vue-pdf-export-docs.vercel.app/" rel="noopener noreferrer"&gt;vue-pdf-export-docs.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🌐 &lt;strong&gt;Live Playground&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Explore the features and generate PDFs directly in the browser:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://vue-pdf-export-playground.vercel.app/" rel="noopener noreferrer"&gt;vue3-pdf-export-playground&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📦 &lt;strong&gt;npm Package&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Install and use the package in your Vue 3 project:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/vue-pdf-export" rel="noopener noreferrer"&gt;npmjs.com/package/vue-pdf-export&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The package is available for Vue 3 applications and continues to evolve around real-world PDF generation requirements.&lt;/p&gt;

&lt;p&gt;If you are building a Vue application that needs client-side PDF generation, I would love to hear about the kinds of documents you are generating and the edge cases you run into.&lt;/p&gt;

&lt;p&gt;If you find a bug, performance cases, or have an idea for an API improvement, feel free to let me know.&lt;/p&gt;

</description>
      <category>vue</category>
      <category>npm</category>
      <category>typescript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Built Log Stripper: A VS Code Extension to Remove Debug Logs Across 23+ Languages</title>
      <dc:creator>Saurabh Choudhary</dc:creator>
      <pubDate>Wed, 03 Jun 2026 07:36:42 +0000</pubDate>
      <link>https://dev.to/saurabhzaiswal/built-log-stripper-a-vs-code-extension-to-remove-debug-logs-across-23-languages-g9h</link>
      <guid>https://dev.to/saurabhzaiswal/built-log-stripper-a-vs-code-extension-to-remove-debug-logs-across-23-languages-g9h</guid>
      <description>&lt;p&gt;Every developer has a version of this story.&lt;/p&gt;

&lt;p&gt;You're about to open a pull request. The code works. The tests pass. Everything looks good.&lt;/p&gt;

&lt;p&gt;Then you do one final scan and find this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;HERE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;final:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then, before the PR:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Search → Delete. Search → Delete. Search → Delete.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I got tired of it. So I built a tool to automate it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Log Stripper?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Log Stripper&lt;/strong&gt; is a VS Code extension that removes debug, log, and print statements from &lt;strong&gt;23+ programming languages&lt;/strong&gt; - with a preview so you always see what will be deleted before anything changes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcboyc43q1b3yqlllnv9i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcboyc43q1b3yqlllnv9i.png" alt="Log Stripper Icon" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://marketplace.visualstudio.com/items?itemName=saurabhchoudhary.log-stripper" rel="noopener noreferrer"&gt;VS Code Marketplace&lt;/a&gt;&lt;br&gt;
🔗 &lt;a href="https://github.com/saurabhzaiswal/Log-Stripper-VS-Code" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The Features
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;🔍 Preview mode&lt;/strong&gt; - &lt;code&gt;Ctrl+Shift+D&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Shows every line that will be removed. You confirm. Only then does anything change.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🎨 Highlight mode&lt;/strong&gt; - &lt;code&gt;Ctrl+Shift+H&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Marks debug lines in red. No file modification. Review first, strip later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🌍  23+ languages&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;JS, TS, Python, Java, Go, Rust, C#, Swift, Kotlin, Dart, Ruby, PHP, C, C++, Shell, Lua, Scala, Elixir, Haskell, R, Vue, Svelte, JSX/TSX&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🏢 Workspace cleanup&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Strip debug statements from an entire project in one command.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why not just use grep/sed?
&lt;/h2&gt;

&lt;p&gt;You could. But:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No preview&lt;/li&gt;
&lt;li&gt;No multiline support&lt;/li&gt;
&lt;li&gt;No VS Code integration&lt;/li&gt;
&lt;li&gt;No safety rules&lt;/li&gt;
&lt;li&gt;Works differently on Windows vs Mac vs Linux
Log Stripper handles all of this inside VS Code with a consistent UX.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  The Interesting Technical Part: Multiline Removal
&lt;/h2&gt;

&lt;p&gt;Removing a single-line &lt;code&gt;console.log("x")&lt;/code&gt; is trivial. The interesting case is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;role:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To remove this correctly, you need to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Find the opening &lt;code&gt;(&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Track paren depth across lines&lt;/li&gt;
&lt;li&gt;Handle parens inside strings (don't count those)&lt;/li&gt;
&lt;li&gt;Find the exact closing &lt;code&gt;)&lt;/code&gt; and optional &lt;code&gt;;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Remove the entire block without touching surrounding code
Here's the core of &lt;code&gt;skipParenBlock&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;skipParenBlock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="nx"&gt;startLine&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;openIdx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;startLine&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;bal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;li&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;startLine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ci&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;openIdx&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;inStr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;li&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;li&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ci&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ci&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inStr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ci&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;inStr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;inStr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;"&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;'&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;inStr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;bal&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;bal&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bal&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;ci&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ci&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;ci&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;endLine&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;li&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;endCol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ci&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;ci&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;li&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;ci&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Architecture Decision
&lt;/h2&gt;

&lt;p&gt;I separated the core logic from the VS Code layer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/
├── extension.ts   ← VS Code commands, UI, workspace
└── stripper.ts    ← Pure logic, zero VS Code deps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why? Because &lt;code&gt;stripper.ts&lt;/code&gt; can be tested without launching a VS Code host:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node &lt;span class="nt"&gt;--test&lt;/span&gt; out-test/test/stripper.test.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;151 tests. Fast. No mocking needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Safety Rules
&lt;/h2&gt;

&lt;p&gt;The extension will &lt;strong&gt;never&lt;/strong&gt; remove:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// console.log("commented") ← comment line, always kept&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;       &lt;span class="err"&gt;←&lt;/span&gt; &lt;span class="nx"&gt;inline&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;always&lt;/span&gt; &lt;span class="nx"&gt;kept&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;doThing&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fallback&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="err"&gt;←&lt;/span&gt; &lt;span class="nx"&gt;inline&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;kept&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Only whole-statement debug calls that are the entire line (after indentation) are removed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Languages Covered
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Language&lt;/th&gt;
&lt;th&gt;Examples&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;JS/TS&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;console.log&lt;/code&gt;, &lt;code&gt;debugger&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;print()&lt;/code&gt;, &lt;code&gt;logging.debug()&lt;/code&gt;, &lt;code&gt;breakpoint()&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Java&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;System.out.println&lt;/code&gt;, &lt;code&gt;logger.debug()&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Go&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;fmt.Println&lt;/code&gt;, &lt;code&gt;log.Fatal&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rust&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;println!&lt;/code&gt;, &lt;code&gt;dbg!&lt;/code&gt;, &lt;code&gt;eprintln!&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C#&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;Console.WriteLine&lt;/code&gt;, &lt;code&gt;Debug.Write&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Swift&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;print()&lt;/code&gt;, &lt;code&gt;NSLog()&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ruby&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;puts&lt;/code&gt;, &lt;code&gt;binding.pry&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PHP&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;var_dump()&lt;/code&gt;, &lt;code&gt;dd()&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Shell&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;echo&lt;/code&gt;, &lt;code&gt;printf&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;...13 more&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install from Marketplace&lt;/span&gt;
code &lt;span class="nt"&gt;--install-extension&lt;/span&gt; saurabhchoudhary.log-stripper
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or search "Log Stripper" in the VS Code extensions panel.&lt;/p&gt;

&lt;p&gt;Open a file with debug statements → &lt;code&gt;Ctrl+Shift+D&lt;/code&gt; → see the preview → confirm.&lt;/p&gt;




&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Toggle Debug Highlights | Highlight/unhighlight debug lines&lt;/code&gt;&lt;/strong&gt;
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhgrpgwbxhy3us1132fx5.png" alt="Toggle Debug Highlights | Highlight/unhighlight debug lines" width="800" height="410"&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Preview &amp;amp; Strip Current File | Shows preview, then strips on confirm&lt;/code&gt;&lt;/strong&gt;
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvprhyo035tbopzpi6qp2.png" alt="Preview &amp;amp; Strip Current File | Shows preview, then strips on confirm" width="800" height="425"&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Command Palette | Strip Entire Workspace | Clean whole project&lt;/code&gt;&lt;/strong&gt;
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5ulbtysszpopdgwx0qn5.png" alt="Command Palette | Strip Entire Workspace | Clean whole project" width="799" height="424"&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Right-click → menu | Strip Current File | Strip without preview&lt;/code&gt;&lt;/strong&gt;
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr3n9kak7vn3m9eo6bogp.png" alt="Right-click → menu | Strip Current File | Strip without preview" width="800" height="450"&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;Editor toolbar icons (eye / eye-closed / trash)&lt;/code&gt;&lt;/strong&gt;
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkiai3594p78j7f12qpt9.png" alt="Editor toolbar icons (eye / eye-closed / trash)" width="800" height="425"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Built this because I couldn't find a tool that did all of this properly. Turned out to be one of the most satisfying weekend projects I've done.&lt;/p&gt;

&lt;p&gt;If you try it, I'd love feedback in the comments or as a GitHub issue. 🙌&lt;/p&gt;

&lt;p&gt;&lt;em&gt;By Saurabh Choudhary - Software Engineer&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Every developer has a version of this story.&lt;/p&gt;

&lt;p&gt;You're about to open a pull request. The code works. The tests pass. You're ready. Then you do one last scroll through the file and see it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;HERE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user data:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userData&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;response&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three debug logs you forgot to remove. You delete them, re-run the linter, and open the PR.&lt;/p&gt;

&lt;p&gt;Two weeks later, someone reports that production logs are noisy with debug output. A developer on your team had left a &lt;code&gt;logger.debug()&lt;/code&gt; in a hot path. Nobody caught it in review.&lt;/p&gt;

&lt;p&gt;This isn't a rare occurrence. It's a pattern that plays out in every team, on every codebase, in every programming language.&lt;/p&gt;

&lt;p&gt;I've experienced it across JavaScript, TypeScript, PHP, Go, Python, Vue.js, NestJS, Laravel, and Angular projects. Different languages, different ecosystems - same repetitive problem.&lt;/p&gt;

&lt;p&gt;Eventually I stopped accepting it as "just part of the workflow" and decided to build a proper solution.&lt;/p&gt;

&lt;p&gt;That solution is &lt;strong&gt;Log Stripper&lt;/strong&gt; - a VS Code extension that removes debug, log, and print statements from 23+ programming languages with a safety-first, preview-driven approach.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;The problem has two dimensions that are easy to underestimate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First: it's repetitive.&lt;/strong&gt; Before every commit, before every PR, before every release, developers go through the same manual process of searching for and deleting debug statements. On large codebases with dozens of files touched in a single feature branch, this becomes genuinely time-consuming.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Second: it's error-prone.&lt;/strong&gt; Humans miss things. A &lt;code&gt;console.log&lt;/code&gt; inside a nested callback, a &lt;code&gt;print()&lt;/code&gt; inside a conditional branch, a &lt;code&gt;System.out.println&lt;/code&gt; buried in a Java service - these are easy to overlook when scanning files manually. And when they slip through, they end up in production.&lt;/p&gt;

&lt;p&gt;There's also a subtler issue: developers working under time pressure will rush the cleanup. The more pressure, the more likely something gets missed.&lt;/p&gt;

&lt;p&gt;This is exactly the kind of task that should be automated. It is deterministic, repetitive, and rule-based. A computer should do it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Existing Workflows Were Frustrating
&lt;/h2&gt;

&lt;p&gt;Before building Log Stripper, I searched for existing solutions.&lt;/p&gt;

&lt;p&gt;I found a few extensions that handled &lt;code&gt;console.log&lt;/code&gt; removal for JavaScript. Some worked well for that specific case. But they had significant limitations:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Language coverage was narrow.&lt;/strong&gt; Most extensions focused exclusively on JavaScript. If you wrote Python, Go, Java, or Rust, you were on your own.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No preview mode.&lt;/strong&gt; Several extensions deleted statements immediately without showing you what would be removed. That's unsafe. A developer who accidentally removes a legitimate logger call in production code will stop trusting the tool immediately.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No highlight mode.&lt;/strong&gt; Sometimes I want to &lt;em&gt;see&lt;/em&gt; the debug statements in a file without removing anything yet. I want to review them, understand them, decide manually. None of the tools I found offered non-destructive inspection.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No workspace cleanup.&lt;/strong&gt; File-by-file cleanup doesn't scale. Before a major release, I want to scan an entire project and clean everything in one pass.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Unreliable multiline handling.&lt;/strong&gt; A &lt;code&gt;console.log&lt;/code&gt; that spans multiple lines is common:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;processing user:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Many tools would only remove the first line and leave the rest, creating syntax errors.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why I Built Log Stripper
&lt;/h2&gt;

&lt;p&gt;The decision to build rather than adapt came down to one realization: the problem deserved a proper solution, not a workaround.&lt;/p&gt;

&lt;p&gt;I wanted an extension that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Worked across every major language I use day-to-day&lt;/li&gt;
&lt;li&gt;Showed a preview before making any changes&lt;/li&gt;
&lt;li&gt;Could highlight debug lines without modifying files&lt;/li&gt;
&lt;li&gt;Could clean an entire workspace safely&lt;/li&gt;
&lt;li&gt;Was smart enough to never break code it shouldn't touch&lt;/li&gt;
&lt;li&gt;Was backed by automated tests
None of those requirements are unreasonable. Together, they're the minimum bar for a tool I'd actually trust.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The weekend I started building it, I intended it to be a one-day project. It grew into something more substantial as I realized the edge cases, the safety requirements, and the value of doing it properly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;p&gt;The most important architectural decision I made was separating the core logic from the VS Code integration layer.&lt;/p&gt;

&lt;p&gt;The repository has two source files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/
├── extension.ts    ← VS Code commands, UI, workspace operations
└── stripper.ts     ← Core strip logic (zero VS Code dependencies)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;stripper.ts&lt;/code&gt; has no awareness of VS Code. It takes a string of text and a language ID, and returns a new string with debug statements removed plus metadata about what was changed. That's it.&lt;/p&gt;

&lt;p&gt;This separation has two major benefits:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Testability.&lt;/strong&gt; I can test the core logic without launching a VS Code Extension Development Host. The 151 automated tests run with a plain &lt;code&gt;node --test&lt;/code&gt; command. Fast, simple, reliable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Maintainability.&lt;/strong&gt; If VS Code changes its API, or if I want to port the logic to a CLI tool or a git pre-commit hook, the core logic doesn't need to change.&lt;/p&gt;

&lt;p&gt;The VS Code layer handles everything user-facing: commands, keybindings, settings, decorations, progress notifications, and workspace file scanning.&lt;/p&gt;




&lt;h2&gt;
  
  
  Multi-Language Support
&lt;/h2&gt;

&lt;p&gt;Supporting 23 languages sounds ambitious. The implementation is actually straightforward once you have the right architecture.&lt;/p&gt;

&lt;p&gt;Each language is a key in the &lt;code&gt;LANGUAGE_PATTERNS&lt;/code&gt; object, and its value is an array of regular expressions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;LANGUAGE_PATTERNS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;javascript&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;(\s&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;console&lt;/span&gt;&lt;span class="se"&gt;\.(&lt;/span&gt;&lt;span class="sr"&gt;log|debug|info|warn|error|trace|...&lt;/span&gt;&lt;span class="se"&gt;)\s&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;(\s&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;debugger&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;*;&lt;/span&gt;&lt;span class="se"&gt;?&lt;/span&gt;&lt;span class="sr"&gt;$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;python&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;(\s&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;print&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;(\s&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;logging&lt;/span&gt;&lt;span class="se"&gt;\.(&lt;/span&gt;&lt;span class="sr"&gt;debug|info|warning|error|critical&lt;/span&gt;&lt;span class="se"&gt;)\s&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;\(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;(\s&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;breakpoint&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;\(\s&lt;/span&gt;&lt;span class="sr"&gt;*&lt;/span&gt;&lt;span class="se"&gt;\)&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="c1"&gt;// ... 21 more languages&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Language aliases handle cases where VS Code's language ID differs from the pattern group:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;LANG_ALIASES&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;svelte&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;javascript&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue-html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;typescriptreact&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;typescript&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the extension receives a file, it looks up the language ID, finds the pattern list, and applies each pattern against every line. If no patterns are found for a language, the file is returned unchanged.&lt;/p&gt;

&lt;p&gt;Adding a new language is a matter of adding one entry to &lt;code&gt;LANGUAGE_PATTERNS&lt;/code&gt; and a set of test cases to &lt;code&gt;stripper.test.ts&lt;/code&gt;. The infrastructure handles the rest.&lt;/p&gt;




&lt;h2&gt;
  
  
  Preview Mode
&lt;/h2&gt;

&lt;p&gt;The preview mode was the feature I was most deliberate about designing.&lt;/p&gt;

&lt;p&gt;When a developer triggers "Preview &amp;amp; Strip" with &lt;code&gt;Ctrl+Shift+D&lt;/code&gt;, the extension:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Runs the stripping logic internally (without modifying the file)&lt;/li&gt;
&lt;li&gt;Collects the list of lines that would be removed&lt;/li&gt;
&lt;li&gt;Shows a modal dialog listing those lines with their line numbers&lt;/li&gt;
&lt;li&gt;Waits for explicit confirmation before making any changes
This turns a potentially destructive operation into a fully transparent, opt-in action. The developer sees exactly what will happen and retains full control.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The modal includes the first 20 matching lines and appends "...and N more" if there are additional matches. This keeps the dialog readable on files with heavy debug coverage.&lt;/p&gt;

&lt;p&gt;If the developer cancels, nothing changes. Not a single character in the file is modified.&lt;/p&gt;




&lt;h2&gt;
  
  
  Highlight Mode
&lt;/h2&gt;

&lt;p&gt;Highlight mode solves a different need: &lt;em&gt;I want to see the debug statements but I'm not ready to remove them yet.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When the developer presses &lt;code&gt;Ctrl+Shift+H&lt;/code&gt;, the extension:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Finds all lines matching debug patterns using &lt;code&gt;findDebugLineIndices()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Applies a VS Code text decoration that highlights those lines in red&lt;/li&gt;
&lt;li&gt;Adds an inline annotation "← debug" at the end of each line
The file is not modified. This is purely a visual overlay.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Pressing &lt;code&gt;Ctrl+Shift+H&lt;/code&gt; again (or clicking the eye-closed icon in the toolbar) removes the highlights.&lt;/p&gt;

&lt;p&gt;The highlight controller also handles three lifecycle events automatically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When you &lt;strong&gt;strip the file&lt;/strong&gt;, highlights are cleared (no red lines on lines that no longer exist)&lt;/li&gt;
&lt;li&gt;When you &lt;strong&gt;edit the file&lt;/strong&gt; and &lt;code&gt;refreshHighlightsOnEdit&lt;/code&gt; is enabled, highlights recompute after a 120ms debounce&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  - When you &lt;strong&gt;switch tabs&lt;/strong&gt; and &lt;code&gt;clearHighlightsOnTabChange&lt;/code&gt; is enabled, highlights are cleared automatically
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Workspace Cleanup
&lt;/h2&gt;

&lt;p&gt;The workspace strip command scans every file in the project matching the supported language extensions and strips debug statements from each one.&lt;/p&gt;

&lt;p&gt;The implementation uses VS Code's &lt;code&gt;workspace.findFiles()&lt;/code&gt; API with exclusion patterns to skip &lt;code&gt;node_modules&lt;/code&gt;, &lt;code&gt;dist&lt;/code&gt;, &lt;code&gt;.git&lt;/code&gt;, &lt;code&gt;vendor&lt;/code&gt;, &lt;code&gt;build&lt;/code&gt;, and &lt;code&gt;out&lt;/code&gt; by default. All exclusion patterns are configurable in settings.&lt;/p&gt;

&lt;p&gt;The operation runs with a progress notification showing the current file being processed and a cancellation option. After completion, a summary shows how many statements were removed across how many files.&lt;/p&gt;

&lt;p&gt;Because this modifies files on disk, the documentation explicitly recommends using version control. A git diff after the workspace strip is always informative.&lt;/p&gt;




&lt;h2&gt;
  
  
  Safety Design
&lt;/h2&gt;

&lt;p&gt;Safety was a first-class concern throughout the design.&lt;/p&gt;

&lt;p&gt;The extension enforces several rules to avoid breaking code it shouldn't touch:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule 1: Whole-line only.&lt;/strong&gt; A debug call is only removed if it is the entire statement on the line (after indentation). This prevents removal of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;         &lt;span class="c1"&gt;// kept - inline with return&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;doWork&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fallback&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// kept - chained&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Rule 2: Comments are never touched.&lt;/strong&gt; Any line where the first non-whitespace characters form a comment prefix (&lt;code&gt;//&lt;/code&gt;, &lt;code&gt;#&lt;/code&gt;, &lt;code&gt;--&lt;/code&gt;, &lt;code&gt;/*&lt;/code&gt;, &lt;code&gt;*&lt;/code&gt;) is skipped entirely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule 3: Multiline paren balancing.&lt;/strong&gt; When a debug call spans multiple lines, the extension tracks open and close parentheses (accounting for parens inside strings) to identify the exact end of the statement. The closing &lt;code&gt;)&lt;/code&gt; and optional &lt;code&gt;;&lt;/code&gt; are consumed, and any remaining code on that final line is preserved.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule 4: No modification on cancel.&lt;/strong&gt; Preview mode never touches the file unless the user explicitly confirms. The stripping logic runs on an in-memory copy of the text, and the result is only written back if the user says yes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Testing Strategy
&lt;/h2&gt;

&lt;p&gt;I wanted the extension to be trustworthy. That required a proper test suite.&lt;/p&gt;

&lt;p&gt;The tests live in &lt;code&gt;test/stripper.test.ts&lt;/code&gt; and use Node's built-in test runner - no Jest, no Mocha, no additional dependencies. The test command is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tsc &lt;span class="nt"&gt;-p&lt;/span&gt; tsconfig.test.json &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; node &lt;span class="nt"&gt;--test&lt;/span&gt; out-test/test/stripper.test.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The 151 test cases cover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every language in &lt;code&gt;LANGUAGE_PATTERNS&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Simple single-line removal&lt;/li&gt;
&lt;li&gt;Multiline call removal with paren balancing&lt;/li&gt;
&lt;li&gt;Comment preservation&lt;/li&gt;
&lt;li&gt;Inline code preservation&lt;/li&gt;
&lt;li&gt;Real-world code samples (NestJS controllers, Python classes, Go functions)&lt;/li&gt;
&lt;li&gt;Language aliases (Vue, Svelte, JSX, TSX)&lt;/li&gt;
&lt;li&gt;Unknown languages (should be a no-op)&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;findDebugLineIndices()&lt;/code&gt; function (used by highlight mode)
Each test specifies the input code, the expected output, and the expected removal count. Any test that would cause the extension to modify code it shouldn't - or fail to modify code it should - is a failing test.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Writing tests before polishing features was the right decision. It caught several edge cases during development and gave me confidence when refactoring the paren-balancing logic.&lt;/p&gt;




&lt;h2&gt;
  
  
  Publishing to the VS Code Marketplace
&lt;/h2&gt;

&lt;p&gt;The Marketplace publishing process is simpler than I expected.&lt;/p&gt;

&lt;p&gt;The key steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a publisher account at &lt;code&gt;marketplace.visualstudio.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Generate a Personal Access Token from Azure DevOps with Marketplace → Manage scope&lt;/li&gt;
&lt;li&gt;Install &lt;code&gt;@vscode/vsce&lt;/code&gt; globally: &lt;code&gt;npm install -g @vscode/vsce&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;vsce package&lt;/code&gt; to create the &lt;code&gt;.vsix&lt;/code&gt; file&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;vsce publish --pat TOKEN&lt;/code&gt; or upload the &lt;code&gt;.vsix&lt;/code&gt; manually via the publisher portal
The &lt;code&gt;.vscodeignore&lt;/code&gt; file controls what goes into the package. I excluded &lt;code&gt;src/&lt;/code&gt;, &lt;code&gt;test/&lt;/code&gt;, and &lt;code&gt;node_modules/&lt;/code&gt; - only the compiled &lt;code&gt;out/&lt;/code&gt; directory ships. This keeps the extension lightweight.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;One thing I'd emphasize: set the &lt;code&gt;repository.url&lt;/code&gt; in &lt;code&gt;package.json&lt;/code&gt; before publishing. It shows up prominently on the Marketplace listing and signals to users that the extension is open source and maintainable.&lt;/p&gt;




&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Separate your core logic from your integration layer.&lt;/strong&gt; This applies far beyond VS Code extensions. Any time you can isolate the testable business logic from the framework or platform code, do it. It makes everything easier.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Safety features build trust.&lt;/strong&gt; The preview mode and the "never remove inline code" rule weren't technically necessary for the extension to work. But they're what make a developer comfortable trusting the tool with real production code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test the edge cases first.&lt;/strong&gt; Multiline calls, strings containing parens, empty files, unsupported languages - these were the cases most likely to cause silent failures. Writing tests for them before the happy path forced me to build robust logic from the start.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ship before it's perfect.&lt;/strong&gt; The first version didn't have highlight mode. The workspace strip was added later. Shipping v1 with the core feature - preview and strip - got real feedback faster than spending another two weeks on features users might not need.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Small tools have real value.&lt;/strong&gt; This isn't a SaaS platform. It's not an AI product. It's a focused tool that does one thing well. Developer tools like this get used quietly but consistently. That's enough.&lt;/p&gt;




&lt;h2&gt;
  
  
  Future Improvements
&lt;/h2&gt;

&lt;p&gt;Several improvements are on the roadmap:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Custom pattern rules.&lt;/strong&gt; Allow developers to define their own patterns to remove. For teams using custom logging frameworks, this would make Log Stripper work with any codebase.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pre-commit hook integration.&lt;/strong&gt; A script or CLI wrapper that can run as a git pre-commit hook, catching debug statements before they ever reach a commit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Team-wide configuration.&lt;/strong&gt; A &lt;code&gt;.logstripper.json&lt;/code&gt; configuration file that defines excluded patterns per project, shareable across a team through version control.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ignore comments.&lt;/strong&gt; A &lt;code&gt;// log-stripper-ignore&lt;/code&gt; annotation that tells the extension to skip a specific line or block.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;More language coverage.&lt;/strong&gt; Zig, Nim, OCaml, and Erlang are candidates for future additions.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Log Stripper is a small tool. It solves one problem, and it solves it well.&lt;/p&gt;

&lt;p&gt;But the process of building it taught me something more valuable than any individual feature: the instinct to look at a repetitive problem and ask "why am I doing this manually?" is one of the most productive instincts an engineer can develop.&lt;/p&gt;

&lt;p&gt;We accept small frictions as part of the job. We work around limitations instead of fixing them. We solve the same problem repeatedly instead of automating it once.&lt;/p&gt;

&lt;p&gt;Log Stripper exists because I stopped accepting one of those frictions.&lt;/p&gt;

&lt;p&gt;If you're reading this and you have something similar - a small repetitive task, an annoying workflow step, a gap in your tooling - build the solution. The process will teach you more than you expect, and the tool will serve you for years.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Try Log Stripper:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;VS Code Marketplace: &lt;a href="https://marketplace.visualstudio.com/items?itemName=saurabhchoudhary.log-stripper" rel="noopener noreferrer"&gt;https://marketplace.visualstudio.com/items?itemName=saurabhchoudhary.log-stripper&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/saurabhzaiswal/Log-Stripper-VS-Code" rel="noopener noreferrer"&gt;https://github.com/saurabhzaiswal/Log-Stripper-VS-Code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm actively improving Log Stripper, so real-world feedback is incredibly valuable.&lt;/p&gt;

&lt;p&gt;If Log Stripper helps keep a few forgotten debug statements out of production, then it has already paid for itself.&lt;/p&gt;




</description>
      <category>vscode</category>
      <category>opensource</category>
      <category>typescript</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
