# jsPDF
jsPDF is a leading open-source JavaScript library for generating PDF documents entirely in client-side JavaScript. It enables developers to create PDFs dynamically in web browsers or Node.js environments without server-side processing, supporting a wide range of features including text, images, shapes, forms, and HTML-to-PDF conversion. The library works across modern browsers and provides TypeScript support for type-safe development.
The core functionality allows creating PDF documents with customizable page sizes, orientations, and measurement units. jsPDF supports embedding images (JPEG, PNG, GIF, BMP, WebP), drawing vector graphics (lines, rectangles, circles, curves), handling Unicode text with custom TTF fonts, creating interactive forms (AcroForms), and converting HTML content to PDF using html2canvas integration. The library provides both a "compat" API for basic operations and an "advanced" API for complex transformations and patterns.
## Creating a Basic PDF Document
The `jsPDF` constructor creates a new PDF document instance with configurable options for page orientation, measurement units, and paper format.
```javascript
import { jsPDF } from "jspdf";
// Create a default A4 portrait document using millimeters
const doc = new jsPDF();
// Add text at position (10, 10) from top-left corner
doc.text("Hello World!", 10, 10);
// Save the document
doc.save("hello-world.pdf");
// Create a landscape document with custom format
const landscapeDoc = new jsPDF({
orientation: "landscape",
unit: "in",
format: [8.5, 11] // Custom size in inches
});
landscapeDoc.text("Landscape Document", 1, 1);
landscapeDoc.save("landscape.pdf");
// Create with encryption
const secureDoc = new jsPDF({
encryption: {
userPassword: "user123",
ownerPassword: "owner456",
userPermissions: ["print", "copy"]
}
});
secureDoc.text("Secure Content", 10, 10);
secureDoc.save("secure.pdf");
```
## Adding and Formatting Text
The `text()` method adds text to the document with support for alignment, rotation, multi-line text, and various formatting options.
```javascript
import { jsPDF } from "jspdf";
const doc = new jsPDF();
// Basic text at coordinates (x, y in mm)
doc.text("Simple text", 10, 10);
// Set font properties
doc.setFontSize(16);
doc.setFont("helvetica", "bold");
doc.setTextColor(255, 0, 0); // RGB: Red
doc.text("Bold Red Title", 10, 20);
// Multi-line text with alignment
doc.setFontSize(12);
doc.setFont("helvetica", "normal");
doc.setTextColor(0, 0, 0);
doc.text("Left aligned text", 105, 40, { align: "left" });
doc.text("Centered text", 105, 50, { align: "center" });
doc.text("Right aligned text", 105, 60, { align: "right" });
// Rotated text (angle in degrees)
doc.text("Rotated 45 degrees", 50, 100, { angle: 45 });
// Multi-line array
const lines = ["Line 1", "Line 2", "Line 3"];
doc.text(lines, 10, 120);
// Auto-wrap text with maxWidth
const longText = "This is a very long text that will automatically wrap when it exceeds the specified maximum width.";
doc.text(longText, 10, 150, { maxWidth: 80 });
// Justified text
doc.text("This justified text spreads across the available width evenly.", 10, 180, {
align: "justify",
maxWidth: 80
});
doc.save("formatted-text.pdf");
```
## Adding Images
The `addImage()` method embeds images in various formats (JPEG, PNG, GIF, WebP, BMP) with support for scaling, positioning, and compression.
```javascript
import { jsPDF } from "jspdf";
const doc = new jsPDF();
// Add image from base64 data
const imgData = "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD...";
doc.addImage(imgData, "JPEG", 10, 10, 50, 50); // x, y, width, height
// Add image with compression
doc.addImage(imgData, "JPEG", 10, 70, 100, 75, undefined, "FAST");
// Add image with rotation (degrees)
doc.addImage(imgData, "JPEG", 120, 10, 50, 50, undefined, undefined, 45);
// Add image using options object
doc.addImage({
imageData: imgData,
format: "JPEG",
x: 10,
y: 150,
width: 80,
height: 60,
compression: "MEDIUM",
rotation: 0
});
// Get image properties
const props = doc.getImageProperties(imgData);
console.log(`Image: ${props.width}x${props.height}, Format: ${props.fileType}`);
// Add image from HTML canvas element
const canvas = document.getElementById("myCanvas");
doc.addImage(canvas, "PNG", 10, 220, 100, 50);
// Add image from URL (in browser)
const img = new Image();
img.src = "https://example.com/image.png";
img.onload = function() {
doc.addImage(img, "PNG", 10, 10, 100, 100);
doc.save("with-images.pdf");
};
```
## Drawing Shapes and Lines
jsPDF provides methods for drawing vector graphics including rectangles, circles, lines, and custom paths with fill and stroke options.
```javascript
import { jsPDF } from "jspdf";
const doc = new jsPDF();
// Set drawing colors
doc.setDrawColor(0, 0, 255); // Blue stroke
doc.setFillColor(255, 255, 0); // Yellow fill
doc.setLineWidth(0.5);
// Rectangle: x, y, width, height, style
doc.rect(10, 10, 40, 20, "FD"); // F=fill, D=stroke, FD=both
// Rounded rectangle with corner radii
doc.roundedRect(60, 10, 40, 20, 3, 3, "FD");
// Circle: x, y, radius
doc.setFillColor(0, 255, 0);
doc.circle(130, 20, 15, "FD");
// Ellipse: x, y, rx, ry
doc.setFillColor(255, 0, 255);
doc.ellipse(180, 20, 20, 10, "FD");
// Line: x1, y1, x2, y2
doc.setDrawColor(255, 0, 0);
doc.setLineWidth(1);
doc.line(10, 50, 200, 50);
// Triangle using lines
doc.setFillColor(100, 100, 255);
doc.triangle(30, 100, 10, 140, 50, 140, "FD");
// Custom path with bezier curves
doc.setDrawColor(0, 0, 0);
doc.setFillColor(255, 200, 100);
doc.lines(
[
[30, 0], // Line to relative position
[0, 30], // Line down
[10, 10, 20, 0, 30, -10], // Bezier curve (cp1x, cp1y, cp2x, cp2y, x, y)
[-30, -20] // Line back
],
70, 80, // Starting point
[1, 1], // Scale
"FD", // Style
true // Close path
);
// Dashed line
doc.setLineDashPattern([3, 2], 0); // [dash, gap], phase
doc.line(10, 160, 200, 160);
// Reset to solid line
doc.setLineDashPattern([], 0);
doc.save("shapes.pdf");
```
## Multi-Page Documents
The `addPage()` and `setPage()` methods allow creating and navigating between multiple pages in a document.
```javascript
import { jsPDF } from "jspdf";
const doc = new jsPDF();
// First page content
doc.setFontSize(20);
doc.text("Page 1 - Introduction", 10, 20);
doc.setFontSize(12);
doc.text("This is the first page of the document.", 10, 40);
// Add a new page with same format
doc.addPage();
doc.text("Page 2 - Content", 10, 20);
// Add page with different format and orientation
doc.addPage("a5", "landscape");
doc.text("Page 3 - A5 Landscape", 10, 20);
// Add page with custom dimensions [width, height]
doc.addPage([200, 100]);
doc.text("Page 4 - Custom Size", 10, 20);
// Navigate between pages
doc.setPage(1); // Go back to first page
doc.text("Added later to page 1", 10, 60);
doc.setPage(2);
doc.text("Additional content on page 2", 10, 40);
// Get total page count
const totalPages = doc.getNumberOfPages();
console.log(`Document has ${totalPages} pages`);
// Add page numbers to all pages
for (let i = 1; i <= totalPages; i++) {
doc.setPage(i);
doc.setFontSize(10);
doc.text(`Page ${i} of ${totalPages}`, 105, 287, { align: "center" });
}
// Delete a page
doc.deletePage(3); // Remove page 3
// Insert page before another
doc.insertPage(2); // Insert new page before page 2
doc.save("multipage.pdf");
```
## Using Custom Fonts (Unicode/UTF-8 Support)
jsPDF supports custom TTF fonts for Unicode text rendering, enabling support for non-Latin characters and special symbols.
```javascript
import { jsPDF } from "jspdf";
const doc = new jsPDF();
// Method 1: Add font from base64 string (after using font converter)
// First, convert TTF to base64 using: https://rawgit.com/MrRio/jsPDF/master/fontconverter/fontconverter.html
const myFontBase64 = "AAEAAAALAIAAA..."; // Base64-encoded TTF data
doc.addFileToVFS("MyFont.ttf", myFontBase64);
doc.addFont("MyFont.ttf", "MyFont", "normal");
doc.setFont("MyFont");
doc.text("Custom font text with Unicode: ", 10, 20);
// Method 2: Load font dynamically (browser)
async function loadFontAndCreatePDF() {
const doc = new jsPDF();
// Fetch font file
const response = await fetch("./fonts/NotoSans-Regular.ttf");
const fontBuffer = await response.arrayBuffer();
const fontBase64 = btoa(String.fromCharCode(...new Uint8Array(fontBuffer)));
// Add font to document
doc.addFileToVFS("NotoSans-Regular.ttf", fontBase64);
doc.addFont("NotoSans-Regular.ttf", "NotoSans", "normal");
// Use the font
doc.setFont("NotoSans");
doc.setFontSize(14);
// Now Unicode text renders correctly
doc.text("English: Hello World!", 10, 20);
doc.text("Chinese: ", 10, 35);
doc.text("Japanese: ", 10, 50);
doc.text("Arabic: ", 10, 65);
doc.text("Russian: ", 10, 80);
doc.save("unicode-text.pdf");
}
// Standard fonts available without importing
const doc2 = new jsPDF();
doc2.setFont("helvetica", "normal");
doc2.text("Helvetica Normal", 10, 10);
doc2.setFont("helvetica", "bold");
doc2.text("Helvetica Bold", 10, 20);
doc2.setFont("helvetica", "italic");
doc2.text("Helvetica Italic", 10, 30);
doc2.setFont("times", "normal");
doc2.text("Times Roman", 10, 40);
doc2.setFont("courier", "normal");
doc2.text("Courier", 10, 50);
// List all available fonts
const fontList = doc2.getFontList();
console.log("Available fonts:", fontList);
// Output: { helvetica: ['normal', 'bold', 'italic', 'bolditalic'], times: [...], courier: [...] }
doc2.save("standard-fonts.pdf");
```
## Converting HTML to PDF
The `html()` method converts HTML elements or strings to PDF using html2canvas, supporting custom styling and pagination.
```javascript
import { jsPDF } from "jspdf";
// Convert HTML element to PDF
async function htmlElementToPDF() {
const doc = new jsPDF();
const element = document.getElementById("content-to-print");
await doc.html(element, {
callback: function(doc) {
doc.save("from-html-element.pdf");
},
x: 10,
y: 10,
width: 180, // Target width in PDF
windowWidth: 800, // Source window width for rendering
autoPaging: "text", // Auto page break mode: 'text', 'slice', or false
margin: [10, 10, 10, 10] // [top, right, bottom, left] margins
});
}
// Convert HTML string to PDF
async function htmlStringToPDF() {
const doc = new jsPDF("p", "mm", "a4");
const htmlContent = `
Report Title
This is a paragraph with bold and italic text.
Item 1
Item 2
Item 3
Name
Value
Alpha
100
Beta
200
`;
await doc.html(htmlContent, {
callback: function(doc) {
doc.save("from-html-string.pdf");
},
x: 0,
y: 0,
width: 210,
windowWidth: 800,
html2canvas: {
scale: 0.265, // Adjust scale for better quality
useCORS: true, // Enable cross-origin images
logging: false
}
});
}
// HTML to PDF with custom fonts
async function htmlWithCustomFonts() {
const doc = new jsPDF();
await doc.html(document.getElementById("styled-content"), {
callback: function(doc) {
doc.save("styled-html.pdf");
},
fontFaces: [
{
family: "CustomFont",
src: [{ url: "./fonts/CustomFont.ttf", format: "truetype" }]
}
],
width: 180,
windowWidth: 800
});
}
// Call the functions
htmlElementToPDF();
```
## Creating Interactive Forms (AcroForms)
jsPDF supports creating interactive PDF forms with text fields, checkboxes, radio buttons, dropdowns, and buttons.
```javascript
import { jsPDF } from "jspdf";
const doc = new jsPDF();
// Add form title
doc.setFontSize(18);
doc.text("Registration Form", 105, 20, { align: "center" });
doc.setFontSize(12);
// Text field
const textField = new doc.AcroForm.TextField();
textField.fieldName = "fullName";
textField.x = 50;
textField.y = 35;
textField.width = 100;
textField.height = 10;
textField.defaultValue = "Enter your name";
textField.maxLength = 50;
doc.addField(textField);
doc.text("Full Name:", 10, 42);
// Password field
const passwordField = new doc.AcroForm.PasswordField();
passwordField.fieldName = "password";
passwordField.x = 50;
passwordField.y = 50;
passwordField.width = 100;
passwordField.height = 10;
doc.addField(passwordField);
doc.text("Password:", 10, 57);
// Multi-line text area
const textArea = new doc.AcroForm.TextField();
textArea.fieldName = "comments";
textArea.x = 50;
textArea.y = 65;
textArea.width = 100;
textArea.height = 30;
textArea.multiline = true;
doc.addField(textArea);
doc.text("Comments:", 10, 72);
// Checkbox
const checkbox = new doc.AcroForm.CheckBox();
checkbox.fieldName = "agreeTerms";
checkbox.x = 50;
checkbox.y = 105;
checkbox.width = 10;
checkbox.height = 10;
doc.addField(checkbox);
doc.text("I agree to terms:", 10, 112);
// Radio buttons
doc.text("Gender:", 10, 130);
const radioGroup = new doc.AcroForm.RadioButton();
radioGroup.fieldName = "gender";
const maleOption = radioGroup.createOption("male");
maleOption.x = 50;
maleOption.y = 123;
maleOption.width = 10;
maleOption.height = 10;
doc.text("Male", 62, 130);
const femaleOption = radioGroup.createOption("female");
femaleOption.x = 90;
femaleOption.y = 123;
femaleOption.width = 10;
femaleOption.height = 10;
doc.text("Female", 102, 130);
doc.addField(radioGroup);
// Dropdown (ComboBox)
const dropdown = new doc.AcroForm.ComboBox();
dropdown.fieldName = "country";
dropdown.x = 50;
dropdown.y = 140;
dropdown.width = 100;
dropdown.height = 10;
dropdown.setOptions(["USA", "Canada", "UK", "Germany", "France", "Other"]);
dropdown.defaultValue = "USA";
doc.addField(dropdown);
doc.text("Country:", 10, 147);
// List box (multiple selection)
const listBox = new doc.AcroForm.ListBox();
listBox.fieldName = "interests";
listBox.x = 50;
listBox.y = 155;
listBox.width = 100;
listBox.height = 25;
listBox.setOptions(["Sports", "Music", "Technology", "Travel", "Art"]);
listBox.multiSelect = true;
doc.addField(listBox);
doc.text("Interests:", 10, 162);
// Push button
const submitBtn = new doc.AcroForm.PushButton();
submitBtn.fieldName = "submitBtn";
submitBtn.x = 80;
submitBtn.y = 190;
submitBtn.width = 40;
submitBtn.height = 12;
submitBtn.caption = "Submit";
doc.addField(submitBtn);
doc.save("interactive-form.pdf");
```
## Document Properties and Metadata
jsPDF allows setting document metadata including title, author, subject, keywords, and various viewer preferences.
```javascript
import { jsPDF } from "jspdf";
const doc = new jsPDF();
// Set document properties/metadata
doc.setDocumentProperties({
title: "Annual Report 2024",
subject: "Financial Summary",
author: "John Doe",
keywords: "finance, report, annual, 2024",
creator: "MyApp v1.0"
});
// Set creation date
doc.setCreationDate(new Date("2024-01-15"));
// Set display mode when PDF opens
doc.setDisplayMode(
"fullwidth", // Zoom: 'fullwidth', 'fullheight', 'fullpage', 'original', or number/%
"continuous", // Layout: 'continuous', 'single', 'twoleft', 'tworight'
"UseOutlines" // Page mode: 'UseNone', 'UseOutlines', 'UseThumbs', 'FullScreen'
);
// Set viewer preferences
doc.viewerPreferences({
HideToolbar: false,
HideMenubar: false,
HideWindowUI: false,
FitWindow: true,
CenterWindow: true,
DisplayDocTitle: true,
NonFullScreenPageMode: "UseOutlines",
Direction: "L2R",
PrintScaling: "None",
Duplex: "DuplexFlipLongEdge"
});
// Add content
doc.text("Document with metadata and viewer settings", 10, 20);
// Get document info
const creationDate = doc.getCreationDate("jsDate");
console.log("Created:", creationDate);
const fileId = doc.getFileId();
console.log("File ID:", fileId);
doc.save("with-metadata.pdf");
```
## Output Formats and Saving
The `output()` method provides various output formats including raw string, ArrayBuffer, Blob, data URI, and direct save options.
```javascript
import { jsPDF } from "jspdf";
const doc = new jsPDF();
doc.text("Output Example", 10, 10);
// Output as raw PDF string
const pdfString = doc.output();
console.log("PDF string length:", pdfString.length);
// Output as ArrayBuffer (useful for sending to server)
const arrayBuffer = doc.output("arraybuffer");
console.log("ArrayBuffer size:", arrayBuffer.byteLength);
// Output as Blob
const blob = doc.output("blob");
console.log("Blob size:", blob.size);
// Output as Blob URL (for preview in iframe)
const blobUrl = doc.output("bloburl");
document.getElementById("preview-frame").src = blobUrl;
// Output as data URI string
const dataUri = doc.output("datauristring", { filename: "preview.pdf" });
console.log("Data URI starts with:", dataUri.substring(0, 50));
// Open in new window using data URI
doc.output("dataurlnewwindow", { filename: "newwindow.pdf" });
// Navigate current window to PDF
// doc.output("dataurl", { filename: "navigate.pdf" });
// Save with default filename
doc.save("document.pdf");
// Save with Promise (useful for async workflows)
doc.save("async-document.pdf", { returnPromise: true })
.then(() => {
console.log("PDF saved successfully!");
})
.catch((error) => {
console.error("Save failed:", error);
});
// Node.js: File is saved to current working directory
// Browser: File is downloaded via FileSaver.js
```
## Advanced API: Transformations and Graphics State
The advanced API mode enables complex transformations, patterns, and graphics state management for sophisticated PDF generation.
```javascript
import { jsPDF, GState, ShadingPattern, TilingPattern } from "jspdf";
const doc = new jsPDF();
// Switch to advanced API mode
doc.advancedAPI(doc => {
// Matrix transformations
doc.saveGraphicsState();
// Apply transformation matrix: scale, rotate, translate
const matrix = new doc.Matrix(1, 0, 0, 1, 50, 50); // Translate to (50, 50)
doc.setCurrentTransformationMatrix(matrix);
doc.setFillColor(255, 0, 0);
doc.rect(0, 0, 30, 30, "F");
doc.restoreGraphicsState();
// Graphics state with opacity
const gState = new GState({ opacity: 0.5 });
doc.setGState(gState);
doc.setFillColor(0, 0, 255);
doc.rect(60, 60, 40, 40, "F");
// Reset opacity
doc.setGState(new GState({ opacity: 1.0 }));
});
// Create gradient pattern (advanced API)
doc.advancedAPI(doc => {
// Linear gradient
const linearGradient = new ShadingPattern("axial",
[0, 0, 100, 0], // x1, y1, x2, y2
[
{ offset: 0, color: [255, 0, 0] }, // Red at start
{ offset: 0.5, color: [255, 255, 0] }, // Yellow at middle
{ offset: 1, color: [0, 255, 0] } // Green at end
]
);
doc.addShadingPattern("myGradient", linearGradient);
doc.rect(10, 120, 100, 50, null); // Create path without drawing
doc.fill({ key: "myGradient", matrix: doc.unitMatrix });
// Radial gradient
const radialGradient = new ShadingPattern("radial",
[50, 50, 0, 50, 50, 40], // x1, y1, r1, x2, y2, r2
[
{ offset: 0, color: [255, 255, 255] },
{ offset: 1, color: [0, 0, 128] }
]
);
doc.addShadingPattern("radialGrad", radialGradient);
doc.circle(150, 145, 30, null);
doc.fill({ key: "radialGrad", matrix: doc.unitMatrix });
});
// Clipping paths
doc.saveGraphicsState();
doc.circle(50, 230, 25, null);
doc.clip();
doc.discardPath();
// Draw image that gets clipped to circle
doc.setFillColor(100, 200, 100);
doc.rect(20, 200, 60, 60, "F");
doc.restoreGraphicsState();
doc.save("advanced-graphics.pdf");
```
## Working with Outlines and Bookmarks
The outline plugin enables creating a navigable table of contents with hierarchical bookmarks in the PDF document.
```javascript
import { jsPDF } from "jspdf";
const doc = new jsPDF();
// Page 1: Title page
doc.setFontSize(24);
doc.text("Complete Guide", 105, 50, { align: "center" });
// Page 2: Chapter 1
doc.addPage();
doc.setFontSize(18);
doc.text("Chapter 1: Introduction", 10, 20);
doc.setFontSize(12);
doc.text("Welcome to the guide. This chapter covers basics.", 10, 35);
// Page 3: Chapter 1 subsection
doc.addPage();
doc.text("1.1 Getting Started", 10, 20);
// Page 4: Chapter 2
doc.addPage();
doc.setFontSize(18);
doc.text("Chapter 2: Advanced Topics", 10, 20);
// Page 5: Chapter 2 subsection
doc.addPage();
doc.text("2.1 Complex Features", 10, 20);
// Create outline/bookmarks
const root = doc.outline.add(null, "Table of Contents", { pageNumber: 1 });
const ch1 = doc.outline.add(root, "Chapter 1: Introduction", { pageNumber: 2 });
doc.outline.add(ch1, "1.1 Getting Started", { pageNumber: 3 });
const ch2 = doc.outline.add(root, "Chapter 2: Advanced Topics", { pageNumber: 4 });
doc.outline.add(ch2, "2.1 Complex Features", { pageNumber: 5 });
// Set to display outlines when opened
doc.setDisplayMode(null, null, "UseOutlines");
doc.save("with-bookmarks.pdf");
```
## Tables and Cell Layout
The cell plugin provides methods for creating tables with automatic sizing and pagination.
```javascript
import { jsPDF } from "jspdf";
const doc = new jsPDF();
// Simple table using cell method
doc.setFontSize(10);
// Header row
doc.setFillColor(200, 200, 200);
doc.cell(10, 10, 50, 10, "Name", 0, "center");
doc.cell(60, 10, 40, 10, "Age", 0, "center");
doc.cell(100, 10, 50, 10, "City", 0, "center");
// Data rows
doc.setFillColor(255, 255, 255);
doc.cell(10, 20, 50, 10, "John Doe", 1, "left");
doc.cell(60, 20, 40, 10, "28", 1, "center");
doc.cell(100, 20, 50, 10, "New York", 1, "left");
doc.cell(10, 30, 50, 10, "Jane Smith", 2, "left");
doc.cell(60, 30, 40, 10, "34", 2, "center");
doc.cell(100, 30, 50, 10, "Los Angeles", 2, "left");
// Using table() method for automatic formatting
const headers = [
{ name: "id", prompt: "ID", width: 30, align: "center", padding: 2 },
{ name: "name", prompt: "Product Name", width: 65, align: "left", padding: 2 },
{ name: "price", prompt: "Price ($)", width: 35, align: "right", padding: 2 },
{ name: "qty", prompt: "Quantity", width: 35, align: "center", padding: 2 }
];
const data = [
{ id: "001", name: "Widget A", price: "19.99", qty: "150" },
{ id: "002", name: "Widget B", price: "29.99", qty: "75" },
{ id: "003", name: "Gadget X", price: "49.99", qty: "200" },
{ id: "004", name: "Gadget Y", price: "99.99", qty: "50" },
{ id: "005", name: "Tool Z", price: "14.99", qty: "300" }
];
doc.table(10, 60, data, headers, {
fontSize: 10,
padding: 3,
headerBackgroundColor: "#4472C4",
headerTextColor: "#FFFFFF",
autoSize: false,
printHeaders: true
});
// Get text dimensions for custom layouts
const dimensions = doc.getTextDimensions("Sample Text", { fontSize: 12 });
console.log(`Text width: ${dimensions.w}, height: ${dimensions.h}`);
doc.save("tables.pdf");
```
## Adding JavaScript and Auto-Print
jsPDF supports embedding JavaScript for actions and setting auto-print behavior when the PDF opens.
```javascript
import { jsPDF } from "jspdf";
const doc = new jsPDF();
doc.text("This document will print automatically when opened.", 10, 20);
// Method 1: Auto-print using JavaScript
doc.autoPrint({ variant: "javascript" });
// Method 2: Auto-print using non-conforming method (wider support)
// doc.autoPrint({ variant: "non-conform" });
// Add custom JavaScript
doc.addJS(`
app.alert("Welcome to the PDF document!");
// Display document info
var info = this.info;
console.println("Title: " + info.Title);
console.println("Author: " + info.Author);
`);
// Set document title for the JavaScript to access
doc.setDocumentProperties({
title: "Auto-Print Document",
author: "PDF Generator"
});
doc.save("auto-print.pdf");
```
## Working with Annotations and Links
The annotations plugin enables adding text annotations, links, and clickable areas to PDF documents.
```javascript
import { jsPDF } from "jspdf";
const doc = new jsPDF();
// Add text with a link
doc.setFontSize(12);
doc.textWithLink("Visit Google", 10, 20, { url: "https://www.google.com" });
// Internal link to another page
doc.addPage();
doc.text("Page 2: Target Section", 10, 20);
doc.setPage(1);
doc.textWithLink("Go to Page 2", 10, 35, { pageNumber: 2 });
// Create link area (invisible clickable region)
doc.link(10, 50, 50, 10, { url: "https://www.example.com" });
doc.text("Click here for example.com", 10, 55);
// Text annotation (popup note)
doc.createAnnotation({
type: "text",
title: "Note",
bounds: { x: 10, y: 70, w: 30, h: 30 },
contents: "This is an important note about the document.",
open: false,
color: "#FFFF00",
name: "Comment"
});
doc.text("Hover over the icon for a note", 45, 80);
// Free text annotation (text directly on page)
doc.createAnnotation({
type: "freetext",
bounds: { x: 10, y: 100, w: 100, h: 20 },
contents: "This is a free text annotation",
color: "#FF0000"
});
// Get text width for precise link positioning
const linkText = "GitHub Repository";
const textWidth = doc.getTextWidth(linkText);
doc.text(linkText, 10, 140);
doc.link(10, 135, textWidth, 10, { url: "https://github.com/parallax/jsPDF" });
doc.save("with-annotations.pdf");
```
## SVG to PDF Conversion
The SVG plugin allows embedding SVG images directly into PDF documents with full vector quality.
```javascript
import { jsPDF } from "jspdf";
const doc = new jsPDF();
// SVG as string
const svgString = `
`;
// Add SVG to PDF
doc.addSvgAsImage(
svgString,
10, // x position
10, // y position
50, // width
50, // height
undefined, // alias
false, // compression
0 // rotation
);
// Multiple SVG elements
const shapes = `
`;
doc.addSvgAsImage(shapes, 10, 70, 100, 50);
// SVG from DOM element (browser)
const svgElement = document.querySelector("#my-svg");
if (svgElement) {
const svgData = new XMLSerializer().serializeToString(svgElement);
doc.addSvgAsImage(svgData, 10, 130, 80, 80);
}
doc.save("with-svg.pdf");
```
## Running in Node.js
jsPDF works in Node.js for server-side PDF generation, automatically using file system operations instead of browser APIs.
```javascript
// CommonJS syntax for Node.js
const { jsPDF } = require("jspdf");
// Create document
const doc = new jsPDF();
// Security: Restrict file access (recommended)
// Use Node's permission flags: node --permission --allow-fs-read=./fonts,./images ./script.js
// Alternative: Whitelist specific paths (less secure)
doc.allowFsRead = ["./fonts/*", "./images/logo.png"];
// Add content
doc.setFontSize(20);
doc.text("Server-generated PDF", 10, 20);
doc.setFontSize(12);
const timestamp = new Date().toISOString();
doc.text(`Generated at: ${timestamp}`, 10, 35);
// Load and embed image from file system
const fs = require("fs");
const path = require("path");
// Read image as base64
const imagePath = path.join(__dirname, "logo.png");
if (fs.existsSync(imagePath)) {
const imageData = fs.readFileSync(imagePath);
const base64Image = imageData.toString("base64");
doc.addImage(base64Image, "PNG", 10, 50, 50, 50);
}
// Save to file system (synchronous)
doc.save("server-output.pdf"); // Saves to current working directory
// Save with Promise (asynchronous)
doc.save("async-output.pdf", { returnPromise: true })
.then(() => console.log("PDF saved successfully"))
.catch(err => console.error("Error saving PDF:", err));
// Get as buffer for HTTP response
const pdfBuffer = Buffer.from(doc.output("arraybuffer"));
// Example: Express.js response
/*
app.get("/generate-pdf", (req, res) => {
const doc = new jsPDF();
doc.text("Dynamic PDF", 10, 10);
const buffer = Buffer.from(doc.output("arraybuffer"));
res.set({
"Content-Type": "application/pdf",
"Content-Disposition": "attachment; filename=download.pdf",
"Content-Length": buffer.length
});
res.send(buffer);
});
*/
```
jsPDF is an essential library for client-side PDF generation in JavaScript applications. It supports a comprehensive range of features from basic text and image placement to advanced form creation, HTML conversion, and vector graphics. The library's modular plugin architecture allows developers to include only the features they need, keeping bundle sizes manageable.
Common integration patterns include generating invoices and reports from application data, converting web content to downloadable PDFs, creating fillable forms for user input, and building document templates with dynamic content. The library works seamlessly with popular frameworks like React, Angular, and Vue, and its Node.js support enables server-side PDF generation for applications requiring backend processing or batch document creation.