### Install LibPDF using Package Managers (Bash) Source: https://libpdf.documenso.com/docs/getting-started/installation Commands to install the LibPDF core package using various package managers: npm, pnpm, yarn, and bun. These commands fetch and install the necessary library files for your project. ```bash npm install @libpdf/core ``` ```bash pnpm add @libpdf/core ``` ```bash yarn add @libpdf/core ``` ```bash bun add @libpdf/core ``` -------------------------------- ### Verify LibPDF Installation (TypeScript) Source: https://libpdf.documenso.com/docs/getting-started/installation A simple TypeScript script to verify the LibPDF installation by creating a new PDF, adding a page, saving it, and logging the resulting byte size. This helps confirm that the library is functioning correctly. ```typescript import { PDF } from "@libpdf/core"; const pdf = PDF.create(); pdf.addPage(); const bytes = await pdf.save(); console.log(`Created PDF with ${bytes.length} bytes`); ``` -------------------------------- ### Load PDF in Browser using JavaScript Source: https://libpdf.documenso.com/docs/getting-started/installation Example of loading a PDF document in a web browser using the LibPDF library. It demonstrates fetching a PDF file, converting it to an ArrayBuffer, and then loading it with `PDF.load()`. ```javascript import { PDF } from "@libpdf/core"; const response = await fetch("/document.pdf"); const bytes = new Uint8Array(await response.arrayBuffer()); const pdf = await PDF.load(bytes); ``` -------------------------------- ### Complete PDF Signing Example with Timestamping Source: https://libpdf.documenso.com/docs/guides/signatures A comprehensive example demonstrating how to sign a PDF document using a P12 certificate, apply a timestamp from a trusted authority, and save the signed document with an incremental update. This example utilizes Node.js file system operations and the LibPDF core library. ```javascript import { readFile, writeFile } from "fs/promises"; import { PDF, P12Signer, HttpTimestampAuthority } from "@libpdf/core"; async function signDocument() { // Load document const pdfBytes = await readFile("contract.pdf"); const pdf = await PDF.load(pdfBytes); // Create signer const p12Bytes = await readFile("my-certificate.p12"); const signer = await P12Signer.create(p12Bytes, "p12-password"); // Create timestamp authority const tsa = new HttpTimestampAuthority("http://timestamp.digicert.com"); // Sign with timestamp const signed = await pdf.sign({ signer, level: "B-LT", timestampAuthority: tsa, reason: "Contract approval", location: "San Francisco, CA", fieldName: "ApprovalSignature", }); // Save with incremental update await writeFile("contract-signed.pdf", signed.bytes); console.log("Document signed successfully"); } signDocument().catch(console.error); ``` -------------------------------- ### Getting Pages: pdf-lib vs LibPDF Source: https://libpdf.documenso.com/docs/migration/from-pdf-lib Provides examples for retrieving pages from a PDF document using pdf-lib and LibPDF. Both libraries offer methods to get all pages, a specific page by index, and the total page count. ```javascript // pdf-lib const pages = pdfDoc.getPages(); const page = pdfDoc.getPage(0); const count = pdfDoc.getPageCount(); // LibPDF const pages = pdf.getPages(); const page = pdf.getPage(0); const count = pdf.getPageCount(); ``` -------------------------------- ### Full Migration Example (pdf-lib to LibPDF) Source: https://libpdf.documenso.com/docs/migration/from-pdf-lib Provides a complete code example demonstrating the migration process from pdf-lib to LibPDF, including updated imports, removal of unnecessary async/await, and simplified standard font usage. ```javascript // Before (pdf-lib) import { PDFDocument, StandardFonts, rgb } from "pdf-lib"; async function createInvoice(data: InvoiceData) { const pdfDoc = await PDFDocument.create(); const font = await pdfDoc.embedFont(StandardFonts.Helvetica); const page = pdfDoc.addPage([612, 792]); page.drawText("INVOICE", { x: 50, y: 750, size: 24, font, color: rgb(0, 0, 0), }); page.drawText(data.customerName, { x: 50, y: 700, size: 12, font, }); return pdfDoc.save(); } // After (@libpdf/core) import { PDF, rgb } from "@libpdf/core"; async function createInvoice(data: InvoiceData) { const pdf = PDF.create(); const page = pdf.addPage({ size: "letter" }); page.drawText("INVOICE", { x: 50, y: 750, size: 24, font: "Helvetica", color: rgb(0, 0, 0), }); page.drawText(data.customerName, { x: 50, y: 700, size: 12, font: "Helvetica", }); return pdf.save(); } ``` -------------------------------- ### Complete PDF Creation Example (JavaScript) Source: https://libpdf.documenso.com/docs/getting-started/create-pdf A comprehensive example demonstrating the creation of a simple invoice PDF. It includes setting metadata, adding a page, drawing text and lines, and saving the PDF to a file. ```javascript import { readFile, writeFile } from "fs/promises"; import { PDF, rgb } from "@libpdf/core"; // Create document const pdf = PDF.create(); pdf.setTitle("Invoice #1234"); // Add page const page = pdf.addPage({ size: "a4" }); // Header page.drawText("INVOICE", { x: 50, y: 780, size: 32, color: rgb(0.2, 0.2, 0.2), }); page.drawText("Invoice #1234", { x: 50, y: 740, size: 14, }); // Line separator page.drawLine({ start: { x: 50, y: 720 }, end: { x: 545, y: 720 }, color: rgb(0.8, 0.8, 0.8), thickness: 1, }); // Content page.drawText("Description: Professional Services", { x: 50, y: 680, size: 12, }); page.drawText("Amount: $1,500.00", { x: 50, y: 660, size: 12, }); // Save const bytes = await pdf.save(); await writeFile("invoice.pdf", bytes); console.log("Created invoice.pdf"); ``` -------------------------------- ### Create Styled PDF Document with libpdf Source: https://libpdf.documenso.com/docs/guides/drawing This example demonstrates how to create a styled PDF document from scratch using the libpdf library. It covers adding pages, drawing rectangles for backgrounds and headers, adding text with specific styling, and drawing lines. The final PDF is saved to a file named 'styled-document.pdf'. ```typescript import { writeFile } from "fs/promises"; import { PDF, rgb } from "@libpdf/core"; const pdf = PDF.create(); const page = pdf.addPage({ size: "a4" }); const { width, height } = page; // Background page.drawRectangle({ x: 0, y: 0, width, height, color: rgb(0.98, 0.98, 1), }); // Header bar page.drawRectangle({ x: 0, y: height - 60, width, height: 60, color: rgb(0.2, 0.4, 0.8), }); page.drawText("Document Title", { x: 50, y: height - 40, size: 24, color: rgb(1, 1, 1), }); // Content page.drawText("Section 1", { x: 50, y: height - 120, size: 18, color: rgb(0.2, 0.2, 0.2), }); page.drawLine({ start: { x: 50, y: height - 130 }, end: { x: width - 50, y: height - 130 }, color: rgb(0.8, 0.8, 0.8), thickness: 1, }); page.drawText("Lorem ipsum dolor sit amet, consectetur adipiscing elit.", { x: 50, y: height - 160, size: 12, maxWidth: width - 100, lineHeight: 18, }); await writeFile("styled-document.pdf", await pdf.save()); ``` -------------------------------- ### Run Verification Script (Bash) Source: https://libpdf.documenso.com/docs/getting-started/installation Commands to execute the TypeScript verification script using either `tsx` (for Node.js environments) or `bun`. These commands will run the script and display the output confirming the PDF creation. ```bash npx tsx verify.ts ``` ```bash bun run verify.ts ``` -------------------------------- ### Quick Start: Sign PDF with Google Cloud KMS Source: https://libpdf.documenso.com/docs/guides/signatures/google-kms A basic example demonstrating how to load a certificate, create a GoogleKmsSigner, load a PDF, sign it using the KMS key, and save the signed PDF. It requires the certificate in DER format and the PDF file. ```typescript import { PDF, GoogleKmsSigner } from "@libpdf/core"; import { readFile, writeFile } from "fs/promises"; // Load your DER-encoded certificate (issued by your CA for the KMS key) const certificate = await readFile("certificate.der"); // Create signer with KMS key reference const signer = await GoogleKmsSigner.create({ keyVersionName: "projects/my-project/locations/us-east1/keyRings/my-ring/cryptoKeys/my-key/cryptoKeyVersions/1", certificate, }); // Sign the PDF const pdf = await PDF.load(await readFile("document.pdf")); const { bytes } = await pdf.sign({ signer }); await writeFile("signed.pdf", bytes); ``` -------------------------------- ### Complete Document Signing Example (JavaScript) Source: https://libpdf.documenso.com/docs/guides/signatures/google-kms A comprehensive example demonstrating how to sign a PDF document using Google Cloud KMS. It includes loading a certificate from Secret Manager, creating a signer with automatic chain building, loading a PDF, applying a timestamp, and saving the signed document. ```javascript import { readFile, writeFile } from "fs/promises"; import { PDF, GoogleKmsSigner, HttpTimestampAuthority } from "@libpdf/core"; async function signWithKms() { // Load certificate from Secret Manager const certificate = await GoogleKmsSigner.getCertificateFromSecretManager( "projects/my-project/secrets/signing-cert/versions/latest", ); // Create KMS signer with automatic chain building const signer = await GoogleKmsSigner.create({ projectId: "my-project", locationId: "us-east1", keyRingId: "document-signing", keyId: "contract-key", certificate, buildChain: true, }); // Load document const pdf = await PDF.load(await readFile("contract.pdf")); // Create timestamp authority for long-term validation const tsa = new HttpTimestampAuthority("http://timestamp.digicert.com"); // Sign with timestamp const { bytes } = await pdf.sign({ signer, level: "B-LT", timestampAuthority: tsa, reason: "Contract approval", location: "Cloud signing service", }); await writeFile("contract-signed.pdf", bytes); console.log("Document signed with KMS"); } signWithKms().catch(console.error); ``` -------------------------------- ### Migrating from pdf-lib Source: https://libpdf.documenso.com/docs/api A guide for users migrating from the pdf-lib library to LibPDF, including a side-by-side comparison. ```APIDOC ## Migrating from pdf-lib Side-by-side comparison and migration guide for pdf-lib users. ``` -------------------------------- ### Sign PDF with Web Crypto API in Browser Source: https://libpdf.documenso.com/docs/guides/signatures This code example demonstrates how to sign a PDF document in a browser environment using the Web Crypto API. It requires a `CryptoKey` object, the DER-encoded X.509 certificate, the key type ('RSA' or 'EC'), and the signature algorithm. ```typescript import { PDF, CryptoKeySigner } from "@libpdf/core"; // Assuming you have a CryptoKey and DER-encoded certificate const signer = new CryptoKeySigner( privateKey, // CryptoKey certificateDer, // Uint8Array (DER-encoded X.509 certificate) "RSA", // KeyType: "RSA" or "EC" "RSASSA-PKCS1-v1_5", // SignatureAlgorithm ); await pdf.sign({ signer }); ``` -------------------------------- ### Apply Basic Signature (B-B) to PDF Source: https://libpdf.documenso.com/docs/guides/signatures This code example shows how to apply a basic digital signature (B-B conformance level) to a PDF document using an existing signer object. This level is suitable for simple signing use cases. ```typescript await pdf.sign({ signer, level: "B-B", }); ``` -------------------------------- ### Draw Custom Paths (Triangle) Source: https://libpdf.documenso.com/docs/guides/drawing Constructs and draws complex shapes using a fluent path API. This example demonstrates drawing a filled triangle with a border. ```javascript // Triangle using the fluent path API page .drawPath() .moveTo(100, 100) .lineTo(150, 200) .lineTo(50, 200) .close() .fillAndStroke({ color: rgb(0.8, 0.2, 0.2), borderColor: rgb(0.4, 0, 0), borderWidth: 2, }); ``` -------------------------------- ### Google Cloud KMS Signing API Source: https://libpdf.documenso.com/docs/guides/signatures/google-kms This section details the process of signing PDF documents using Google Cloud KMS for secure and compliant digital signatures. It covers installation, quick start, authentication, and the creation and usage of the GoogleKmsSigner. ```APIDOC ## Installation The Google Cloud KMS client is an optional peer dependency: ``` npm install @google-cloud/kms ``` For loading certificates from Secret Manager: ``` npm install @google-cloud/secret-manager ``` ## Quick Start ```javascript import { PDF, GoogleKmsSigner } from "@libpdf/core"; import { readFile, writeFile } from "fs/promises"; // Load your DER-encoded certificate (issued by your CA for the KMS key) const certificate = await readFile("certificate.der"); // Create signer with KMS key reference const signer = await GoogleKmsSigner.create({ keyVersionName: "projects/my-project/locations/us-east1/keyRings/my-ring/cryptoKeys/my-key/cryptoKeyVersions/1", certificate, }); // Sign the PDF const pdf = await PDF.load(await readFile("document.pdf")); const { bytes } = await pdf.sign({ signer }); await writeFile("signed.pdf", bytes); ``` ## Authentication `GoogleKmsSigner` uses Application Default Credentials (ADC) by default. Common authentication methods: Method| Environment| Setup ---|---|--- Service Account Key| Any| Set `GOOGLE_APPLICATION_CREDENTIALS` env var User Credentials| Local development| Run `gcloud auth application-default login` Workload Identity| GKE| Configure workload identity for your pod Attached Service Account| GCE/Cloud Run/etc.| Automatic (uses instance metadata) ### Required Permissions The authenticating identity needs these IAM permissions: * `cloudkms.cryptoKeyVersions.useToSign` - Sign with the key * `cloudkms.cryptoKeyVersions.viewPublicKey` - Validate certificate matches * `cloudkms.cryptoKeyVersions.get` - Read key metadata The predefined role `roles/cloudkms.signerVerifier` includes all required permissions. ## GoogleKmsSigner.create(options) Create a new KMS signer instance. ### Parameters #### Path Parameters *None* #### Query Parameters *None* #### Request Body *None* ### Request Example *None* ### Response #### Success Response (200) * **signer** (`GoogleKmsSigner`) - A new instance of the KMS signer. #### Response Example *None* ### Full Resource Name Param| Type| Default| Description ---|---|---|--- `options`| `object`| required| `options.keyVersionName`| `string`| required| Full KMS key version resource name `options.certificate`| `Uint8Array`| required| DER-encoded X.509 certificate for this KMS key `[options.certificateChain]`| `Uint8Array[]`| | Intermediate and root certificates `[options.buildChain]`| `boolean`| `false`| Fetch chain via AIA extensions `[options.chainTimeout]`| `number`| `15000`| Timeout for AIA fetching (ms) `[options.client]`| `KeyManagementServiceClient`| | Pre-configured KMS client ```javascript const signer = await GoogleKmsSigner.create({ keyVersionName: "projects/my-project/locations/us-east1/keyRings/my-ring/cryptoKeys/my-key/cryptoKeyVersions/1", certificate: certificateDer, buildChain: true, // Automatically fetch intermediate certificates }); ``` ### Shorthand Options Instead of a full resource name, you can use shorthand properties: Param| Type| Default| Description ---|---|---|--- `options.projectId`| `string`| required| GCP project ID `options.locationId`| `string`| required| KMS location `options.keyRingId`| `string`| required| Key ring name `options.keyId`| `string`| required| Key name `[options.keyVersion]`| `string`| `"1"`| Key version number ```javascript const signer = await GoogleKmsSigner.create({ projectId: "my-project", locationId: "us-east1", keyRingId: "my-ring", keyId: "my-key", keyVersion: "1", certificate: certificateDer, }); ``` **Returns** : `Promise` **Throws** : `KmsSignerError` if: * Key is not found or not accessible * Key is not enabled * Key algorithm is unsupported * Certificate public key doesn't match the KMS key ## Signer Properties After creation, inspect the signer's detected configuration: ```javascript const signer = await GoogleKmsSigner.create({ keyVersionName: "projects/.../cryptoKeyVersions/1", certificate: certificateDer, }); signer.keyType; // "RSA" or "EC" signer.signatureAlgorithm; // "RSASSA-PKCS1-v1_5", "RSA-PSS", or "ECDSA" signer.digestAlgorithm; // "SHA-256", "SHA-384", or "SHA-512" signer.keyVersionName; // Full resource name signer.certificate; // DER-encoded certificate signer.certificateChain; // Chain certificates (if provided/built) ``` ``` -------------------------------- ### Install LibPDF Core Package (npm) Source: https://libpdf.documenso.com/docs/index Installs the core package for the LibPDF library using npm. This package is required to use LibPDF's functionalities. ```bash npm install @libpdf/core ``` -------------------------------- ### PDF.load() and PDF.save() Source: https://libpdf.documenso.com/docs/guides/drawing Loads an existing PDF document and saves the modified document. ```APIDOC ## POST /websites/libpdf_documenso/pdf/load_save ### Description Loads an existing PDF document from bytes, allows modifications (like adding watermarks), and saves the modified document back into bytes. ### Method POST ### Endpoint /websites/libpdf_documenso/pdf/load_save ### Parameters #### Query Parameters - **pageNumber** (number) - Required - The index of the page to modify (0-based). ### Request Body - **existingBytes** (string) - Required - Base64 encoded bytes of the existing PDF file. - **modifications** (object) - Required - An object containing the modifications to apply. Example: `{"type": "drawText", "options": {"text": "CONFIDENTIAL", "x": 200, "y": 400, "size": 60, "color": "rgb(1, 0, 0)", "opacity": 0.3}}` ### Request Example ```json { "existingBytes": "JVBERi0xLjQKJcO...", "pageNumber": 0, "modifications": { "type": "drawText", "options": { "text": "CONFIDENTIAL", "x": 200, "y": 400, "size": 60, "color": "rgb(1, 0, 0)", "opacity": 0.3 } } } ``` ### Response #### Success Response (200) - **savedBytes** (string) - Base64 encoded bytes of the modified PDF file. #### Response Example ```json { "savedBytes": "JVBERi0xLjQKJcO..." } ``` ``` -------------------------------- ### PDF Incremental Update Trailer Structure Source: https://libpdf.documenso.com/docs/concepts/incremental-saves Provides an example of the trailer structure appended during an incremental PDF update. This trailer includes a pointer to the previous cross-reference (xref) table and the starting byte offset of the new xref table, enabling readers to follow the chain of updates. ```plaintext trailer << /Root 1 0 R /Prev 12345 ← Points to previous xref /Size 50 >> startxref 54321 %%EOF ``` -------------------------------- ### Create an Empty PDF Document (JavaScript) Source: https://libpdf.documenso.com/docs/getting-started/create-pdf Initializes a new PDF document object. This is the starting point for all PDF creation tasks. It requires the '@libpdf/core' library. ```javascript import { PDF } from "@libpdf/core"; const pdf = PDF.create(); ``` -------------------------------- ### Initialize and Fill PDF Form Source: https://libpdf.documenso.com/docs/api/pdf-form Loads a PDF document and fills interactive form fields. This is a common starting point for form manipulation. ```javascript const pdf = await PDF.load(bytes); const form = pdf.getForm(); if (form) { form.fill({ name: "John Doe", email: "john@example.com", agree: true, }); } ``` -------------------------------- ### Create a Gradient Button with LibPDF (JavaScript) Source: https://libpdf.documenso.com/docs/advanced/low-level-drawing A complete example showcasing the creation of a PDF document with a gradient button. It involves creating a linear gradient, a shading pattern, an extended graphics state for shadow effects, and drawing the button with rounded corners. The example utilizes LibPDF's core functionalities for PDF generation and manipulation. ```javascript import { PDF, ops, rgb, Matrix, ColorSpace } from "@libpdf/core"; const pdf = PDF.create(); const page = pdf.addPage(); // Create button gradient const gradient = pdf.createLinearGradient({ angle: 180, // top to bottom length: 40, stops: [ { offset: 0, color: rgb(0.4, 0.6, 1) }, { offset: 1, color: rgb(0.2, 0.4, 0.8) }, ], }); const pattern = pdf.createShadingPattern({ shading: gradient }); const patternName = page.registerPattern(pattern); // Create shadow with transparency const shadow = pdf.createExtGState({ fillOpacity: 0.3 }); const shadowName = page.registerExtGState(shadow); // Draw shadow page.drawOperators([ ops.pushGraphicsState(), ops.setGraphicsState(shadowName), ops.setNonStrokingGray(0), ops.rectangle(103, 697, 150, 40), ops.fill(), ops.popGraphicsState(), ]); // Draw button with gradient page.drawOperators([ ops.setNonStrokingColorSpace(ColorSpace.Pattern), ops.setNonStrokingColorN(patternName), ]); // Rounded rectangle path page .drawPath() .moveTo(110, 700) .lineTo(250, 700) .curveTo(255, 700, 260, 705, 260, 710) .lineTo(260, 730) .curveTo(260, 735, 255, 740, 250, 740) .lineTo(110, 740) .curveTo(105, 740, 100, 735, 100, 730) .lineTo(100, 710) .curveTo(100, 705, 105, 700, 110, 700) .close() .fill({ pattern }); // Add button text page.drawText("Click Me", { x: 145, y: 714, size: 14, color: rgb(1, 1, 1), }); await Bun.write("button.pdf", await pdf.save()); ``` -------------------------------- ### Get and Set Document Keywords Source: https://libpdf.documenso.com/docs/api/pdf Retrieves the document's keywords or sets new keywords. Keywords are used for searching and indexing. ```javascript pdf.setKeywords(["finance", "quarterly", "2024"]); const keywords = pdf.getKeywords(); // ["finance", "quarterly", "2024"] ``` -------------------------------- ### Draw Path Source: https://libpdf.documenso.com/docs/api/pdf-page Starts building a custom path using a fluent API. Returns a PathBuilder object to define path segments and drawing operations. ```APIDOC ## POST /page/drawPath ### Description Start building a custom path with a fluent API. ### Method POST ### Endpoint /page/drawPath ### Parameters No direct parameters for initiating the path. Subsequent calls to the PathBuilder object define the path. ### Request Example ```json { "operations": [ {"type": "moveTo", "x": 100, "y": 100}, {"type": "lineTo", "x": 200, "y": 100}, {"type": "close"}, {"type": "fill", "options": {"color": "rgb(1, 0, 0)"}} ] } ``` ### Response #### Success Response (200) - **status** (string) - Indicates success #### Response Example ```json { "status": "Path drawn successfully" } ``` ### PathBuilder Methods - **moveTo(x, y)**: Move to point - **lineTo(x, y)**: Draw line to point - **curveTo(cp1x, cp1y, cp2x, cp2y, x, y)**: Cubic bezier curve - **quadraticCurveTo(cpx, cpy, x, y)**: Quadratic bezier curve - **appendSvgPath(pathData, options?)**: Append SVG path commands - **close()**: Close the path - **fill(options)**: Fill the path - **stroke(options)**: Stroke the path - **fillAndStroke(options)**: Fill and stroke ``` -------------------------------- ### Get and Set Multiple Metadata Fields Source: https://libpdf.documenso.com/docs/api/pdf Retrieves all metadata fields at once or sets multiple metadata fields (title, author, creationDate, etc.) simultaneously. ```javascript // Get all metadata const metadata = pdf.getMetadata(); // Set multiple fields pdf.setMetadata({ title: "Quarterly Report", author: "Jane Smith", creationDate: new Date(), }); ``` -------------------------------- ### TypeScript Configuration for LibPDF Source: https://libpdf.documenso.com/docs/getting-started/installation Essential settings for the `tsconfig.json` file when using LibPDF with TypeScript. These options ensure proper module resolution and interoperability for ESM projects. ```json { "compilerOptions": { "module": "ESNext", "moduleResolution": "bundler", "esModuleInterop": true } } ``` -------------------------------- ### Load Real PDF Fixtures for Testing Source: https://libpdf.documenso.com/docs/advanced/library-authors Illustrates how to load real PDF files from a fixtures directory for integration testing. It uses Node.js file system promises to read the file content into a Uint8Array. ```typescript import { readFile } from "fs/promises"; import { join } from "path"; async function loadFixture(name: string): Promise { const path = join(__dirname, "fixtures", name); return new Uint8Array(await readFile(path)); } describe("Complex PDFs", () => { it("handles encrypted PDF", async () => { const bytes = await loadFixture("encrypted.pdf"); const result = await myWrapper.process(bytes, { password: "test" }); expect(result).toBeDefined(); }); }); ``` -------------------------------- ### Get Permissions of Encrypted PDF (JavaScript) Source: https://libpdf.documenso.com/docs/guides/encryption Retrieves the current permissions set for an encrypted PDF document after loading it with credentials. This allows checking what actions, such as printing or copying, are permitted. ```javascript const pdf = await PDF.load(bytes, { credentials: "secret" }); if (pdf.isEncrypted) { const permissions = pdf.getPermissions(); console.log("Printing allowed:", permissions.print); console.log("Copying allowed:", permissions.copy); console.log("Modifying allowed:", permissions.modify); } ``` -------------------------------- ### Draw Text with Standard 14 Fonts Source: https://libpdf.documenso.com/docs/guides/fonts Draws text on a PDF page using one of the 14 standard PDF fonts. These fonts are universally available and do not require embedding. The example uses Helvetica. ```javascript import { StandardFonts } from "@libpdf/core"; page.drawText("Hello", { x: 50, y: 700, size: 12, font: StandardFonts.Helvetica, }); ``` -------------------------------- ### Create and Protect PDF with Passwords and Permissions (JavaScript) Source: https://libpdf.documenso.com/docs/guides/encryption Demonstrates how to create a new PDF document, add content, set user and owner passwords, define encryption algorithms, and specify permissions for printing, copying, and modification. It saves the protected PDF to a file. ```javascript import { writeFile } from "fs/promises"; import { PDF } from "@libpdf/core"; // Create a protected document const pdf = PDF.create(); pdf.addPage({ size: "letter" }); const page = pdf.getPage(0); if (page) { page.drawText("Confidential Information", { x: 50, y: 700, size: 24, }); page.drawText("This document is password protected.", { x: 50, y: 650, size: 12, }); } // Add protection pdf.setProtection({ userPassword: "reader123", ownerPassword: "admin456", algorithm: "AES-256", permissions: { print: true, copy: false, modify: false, annotate: false, }, }); // Save with protection await writeFile("protected.pdf", await pdf.save()); console.log("Created protected.pdf"); console.log("User password: reader123"); console.log("Owner password: admin456"); ``` -------------------------------- ### Sign PDF for Long-Term Archival (B-LTA) Source: https://libpdf.documenso.com/docs/guides/signatures This example shows how to sign a PDF with the B-LTA conformance level, the highest level of durability. It includes a document timestamp covering the embedded validation data, enabling indefinite verification of the signature. ```typescript const tsa = new HttpTimestampAuthority("http://timestamp.digicert.com"); await pdf.sign({ signer, level: "B-LTA", timestampAuthority: tsa, }); ``` -------------------------------- ### Loading PDFs: pdf-lib vs LibPDF Source: https://libpdf.documenso.com/docs/migration/from-pdf-lib Demonstrates how to load PDF documents using both pdf-lib and LibPDF. LibPDF uses a similar API to pdf-lib for loading. ```javascript // pdf-lib import { PDFDocument } from "pdf-lib"; const pdfDoc = await PDFDocument.load(bytes); // LibPDF import { PDF } from "@libpdf/core"; const pdf = await PDF.load(bytes); ``` -------------------------------- ### Package.json: Direct Dependency Strategy (Internal Use) Source: https://libpdf.documenso.com/docs/advanced/library-authors Illustrates setting up a package.json for internal use cases where LibPDF is an implementation detail. This approach gives direct control over the exact version and simplifies usage for end-users, suitable for applications. ```json { "name": "my-pdf-service", "dependencies": { "@libpdf/core": "^1.0.0" } } ``` -------------------------------- ### PDF Static Methods for Loading and Creating Source: https://libpdf.documenso.com/docs/api/pdf Provides static methods for the PDF class to load existing PDF documents from bytes or create new ones. Also includes a method for merging multiple PDF sources. ```typescript PDF.load(bytes, options?) PDF.create() PDF.merge(sources, options?) ``` -------------------------------- ### Get Text Field by Name Source: https://libpdf.documenso.com/docs/api/pdf-form Retrieves a text field by its name, providing type-safe access. Allows setting and getting text values. ```javascript const nameField = form.getTextField("name"); if (nameField) { nameField.setValue("John Doe"); console.log(nameField.getValue()); } ``` -------------------------------- ### Adding Pages: pdf-lib vs LibPDF Source: https://libpdf.documenso.com/docs/migration/from-pdf-lib Illustrates how to add pages to a PDF document in both libraries. LibPDF offers preset page sizes in addition to custom dimensions. ```javascript // pdf-lib const page = pdfDoc.addPage(); const page = pdfDoc.addPage([612, 792]); // Custom size // LibPDF const page = pdf.addPage(); const page = pdf.addPage({ width: 612, height: 792 }); const page = pdf.addPage({ size: "letter" }); // Preset sizes ``` -------------------------------- ### Creating PDFs: pdf-lib vs LibPDF Source: https://libpdf.documenso.com/docs/migration/from-pdf-lib Shows the process of creating new PDF documents in pdf-lib and LibPDF. LibPDF's creation is synchronous, unlike pdf-lib's asynchronous approach. ```javascript // pdf-lib import { PDFDocument } from "pdf-lib"; const pdfDoc = await PDFDocument.create(); // LibPDF import { PDF } from "@libpdf/core"; const pdf = PDF.create(); // Note: synchronous ``` -------------------------------- ### Get List Box Field by Name Source: https://libpdf.documenso.com/docs/api/pdf-form Retrieves a list box field by its name, providing type-safe access. Allows setting and getting selected values, which can be multiple. ```javascript const colors = form.getListBox("favorite_colors"); if (colors) { colors.setValue(["red", "blue"]); } ``` -------------------------------- ### Get Dropdown Field by Name Source: https://libpdf.documenso.com/docs/api/pdf-form Retrieves a dropdown (combo box) field by its name, providing type-safe access. Allows setting and getting the selected value, and querying available options. ```javascript const country = form.getDropdown("country"); if (country) { country.setValue("United States"); const options = country.getOptions(); // options: [{ value: "USA", display: "United States" }, ...] } ``` -------------------------------- ### Conditional Imports for Tree Shaking Source: https://libpdf.documenso.com/docs/advanced/library-authors Demonstrates how to structure code for optimal tree shaking by using conditional imports. This allows only the necessary parts of the library to be included in the final bundle, reducing its size. ```typescript // Only imports what you use import { PDF } from "@libpdf/core"; // Signature features not included if not imported import { P12Signer } from "@libpdf/core"; // Good: conditional import async function signIfNeeded(pdf: PDF, shouldSign: boolean) { if (shouldSign) { const { P12Signer } = await import("@libpdf/core"); // ... } } ``` -------------------------------- ### Matrix Transformation Helper Source: https://libpdf.documenso.com/docs/advanced/low-level-drawing Demonstrates using the `Matrix` helper class to construct transformation matrices for translation, rotation, and scaling, then applying them using `ops.concatMatrix()`. ```APIDOC ## Transforms with Matrix Helper ### Description Utilizes the `Matrix` helper class to create and apply complex transformations (translation, rotation, scaling) to the current transformation matrix (CTM) for precise graphical element placement and manipulation. ### Method POST ### Endpoint `/page/drawOperators` ### Parameters #### Request Body - **operators** (Array) - Required - An array of PDF operators, including `ops.pushGraphicsState()`, `ops.concatMatrix(matrix)`, drawing commands, and `ops.popGraphicsState()`. ### Request Example ```json { "operators": [ "ops.pushGraphicsState()", "ops.concatMatrix(Matrix.identity().translate(200, 300).rotate(45).scale(2, 1.5))", "ops.rectangle(0, 0, 100, 50)", "ops.fill()", "ops.popGraphicsState()" ] } ``` ### Response #### Success Response (200) - **success** (boolean) - Indicates if the operation was successful. #### Response Example ```json { "success": true } ``` ### Raw Matrix Components Example ```javascript // Translation: move 100 points right, 200 points up ops.concatMatrix(1, 0, 0, 1, 100, 200); // Scale: 2x horizontal, 0.5x vertical ops.concatMatrix(2, 0, 0, 0.5, 0, 0); // Rotation: 45 degrees around origin const angle = (45 * Math.PI) / 180; ops.concatMatrix(Math.cos(angle), Math.sin(angle), -Math.sin(angle), Math.cos(angle), 0, 0); ``` ``` -------------------------------- ### Get Radio Group Field by Name Source: https://libpdf.documenso.com/docs/api/pdf-form Retrieves a radio button group by its name, providing type-safe access. Allows setting and getting the selected value, and querying available options. ```javascript const payment = form.getRadioGroup("payment_method"); if (payment) { payment.setValue("credit_card"); console.log(payment.getOptions()); // ["credit_card", "paypal", "bank"] } ``` -------------------------------- ### Install Google Cloud KMS and Secret Manager Dependencies Source: https://libpdf.documenso.com/docs/guides/signatures/google-kms Installs the necessary npm packages for Google Cloud KMS and Secret Manager integration with LibPDF. These are optional peer dependencies. ```bash npm install @google-cloud/kms npm install @google-cloud/secret-manager ``` -------------------------------- ### Create GoogleKmsSigner with Shorthand Options Source: https://libpdf.documenso.com/docs/guides/signatures/google-kms Shows how to create a GoogleKmsSigner using shorthand properties for project, location, key ring, key ID, and key version, along with the DER-encoded certificate. ```typescript const signer = await GoogleKmsSigner.create({ projectId: "my-project", locationId: "us-east1", keyRingId: "my-ring", keyId: "my-key", keyVersion: "1", certificate: certificateDer, }); ``` -------------------------------- ### Create Tiling Patterns in PDF Source: https://libpdf.documenso.com/docs/advanced/low-level-drawing Illustrates the creation of tiling patterns, which are repeating patterns defined by a bounding box and drawing operators. These are useful for creating textures like checkerboards. ```javascript const checkerboard = pdf.createTilingPattern({ bbox: { x: 0, y: 0, width: 20, height: 20 }, xStep: 20, yStep: 20, operators: [ ops.setNonStrokingGray(0.8), ops.rectangle(0, 0, 10, 10), ops.rectangle(10, 10, 10, 10), ops.fill(), ], }); const patternName = page.registerPattern(checkerboard); page.drawOperators([ ops.setNonStrokingColorSpace(ColorSpace.Pattern), ops.setNonStrokingColorN(patternName), ops.rectangle(100, 100, 300, 200), ops.fill(), ]); ``` -------------------------------- ### Create and Use PdfStream Streams in TypeScript Source: https://libpdf.documenso.com/docs/concepts/object-model Demonstrates the creation of PdfStream objects, which combine a dictionary with binary data, and how to access dictionary entries and the stream's data. It supports automatic decompression. ```typescript import { PdfStream, PdfName, PdfNumber } from "@libpdf/core"; // Assuming imageBytes is defined elsewhere const imageBytes = new Uint8Array([/* ... image data ... */]); // Create a stream const stream = PdfStream.fromDict( { Type: PdfName.of("XObject"), Subtype: PdfName.of("Image"), Width: PdfNumber.of(100), Height: PdfNumber.of(100), }, imageBytes, ); // Access dictionary entries (PdfStream extends PdfDict) const width = stream.getNumber("Width"); // Get decoded data (decompresses if filtered) const data = stream.getDecodedData(); // Get raw (possibly compressed) data const raw = stream.data; ``` -------------------------------- ### PDF Object Definition Source: https://libpdf.documenso.com/docs/concepts/pdf-structure An example of a PDF object, which forms the content of the document body. Objects are identified by an ID and an optional generation number. This example shows a dictionary object representing the document catalog. ```text 1 0 obj << /Type /Catalog /Pages 2 0 R >> endobj ``` -------------------------------- ### drawSvgPath() - Scaling Source: https://libpdf.documenso.com/docs/guides/drawing Scales SVG paths up or down using the `scale` option. ```APIDOC ## POST /websites/libpdf_documenso/drawSvgPath/scale ### Description Scales SVG paths up or down using the `scale` option. ### Method POST ### Endpoint /websites/libpdf_documenso/drawSvgPath/scale ### Parameters #### Query Parameters - **x** (number) - Required - X position on page - **y** (number) - Required - Y position on page - **scale** (number) - Required - Scale factor - **color** (Color) - Optional - Fill color - **borderColor** (Color) - Optional - Stroke color - **borderWidth** (number) - Optional - Stroke width in points - **windingRule** ("nonzero" | "evenodd") - Optional - Fill rule for overlapping paths - **opacity** (number) - Optional - Opacity (0-1) ### Request Body - **pathData** (string) - Required - SVG path data string ### Request Example ```json { "pathData": "M 12 4 C 12 4 8 0 4 4 C 0 8 0 12 12 22 ...", "x": 100, "y": 700, "scale": 2, "color": "rgb(1, 0, 0)" } ``` ### Response #### Success Response (200) - **message** (string) - Success message #### Response Example ```json { "message": "Scaled SVG path drawn successfully" } ``` ``` -------------------------------- ### Package.json: Peer Dependency Strategy (Recommended) Source: https://libpdf.documenso.com/docs/advanced/library-authors Demonstrates how to configure a package.json file to use a peer dependency for libraries wrapping LibPDF. This allows users to manage the LibPDF version, preventing duplicates and catching conflicts early. ```json { "name": "my-pdf-wrapper", "peerDependencies": { "@libpdf/core": "^1.0.0" }, "devDependencies": { "@libpdf/core": "^1.0.0" } } ``` -------------------------------- ### Create Tiling Pattern Source: https://libpdf.documenso.com/docs/api/pdf Creates a repeating tiling pattern from specified options, including bounding box, step sizes, and content operators. This pattern can be used for filling shapes with repeating elements. ```javascript const pattern = pdf.createTilingPattern({ bbox: { x: 0, y: 0, width: 10, height: 10 }, xStep: 10, yStep: 10, operators: [ops.setNonStrokingGray(0.8), ops.rectangle(0, 0, 5, 5), ops.fill()] }); ``` -------------------------------- ### Loading a PDF with LibPDF Source: https://libpdf.documenso.com/docs/concepts/pdf-structure Demonstrates how to load a PDF file using LibPDF. The library follows a process of reading the trailer, parsing the XRef, loading the catalog and page tree, and deferring the loading of other objects until they are explicitly requested (lazy loading). ```javascript const pdf = await PDF.load(bytes); // The catalog is loaded, but page content isn't parsed yet const page = pdf.getPage(0); // Now page content is loaded on demand if (page) { const text = page.extractText(); } ``` -------------------------------- ### Build and Draw Custom Paths Source: https://libpdf.documenso.com/docs/api/pdf-page Allows building custom vector paths using a fluent API with methods like moveTo, lineTo, curveTo, and close. Paths can be filled, stroked, or both. Supports appending SVG path data. ```javascript // Triangle page .drawPath() .moveTo(100, 100) .lineTo(200, 100) .lineTo(150, 200) .close() .fill({ color: rgb(1, 0, 0) }); // Complex shape page .drawPath() .moveTo(50, 50) .curveTo(100, 100, 150, 100, 200, 50) .lineTo(200, 150) .close() .fillAndStroke({ color: rgb(0.9, 0.9, 1), borderColor: rgb(0, 0, 1), }); ``` ```javascript // Mix PathBuilder methods with SVG path data page .drawPath() .moveTo(50, 500) .lineTo(100, 500) .appendSvgPath("l 30 -30 l 30 30", { flipY: false }) // relative SVG .lineTo(200, 500) .stroke({ borderColor: rgb(0, 0, 0) }); ``` -------------------------------- ### drawRectangle() Source: https://libpdf.documenso.com/docs/guides/drawing Draws a rectangle on the PDF page. Used for backgrounds or visual elements. ```APIDOC ## POST /websites/libpdf_documenso/drawRectangle ### Description Draws a rectangle on the PDF page. This is often used for backgrounds or creating visual elements. ### Method POST ### Endpoint /websites/libpdf_documenso/drawRectangle ### Parameters #### Query Parameters - **x** (number) - Required - X position of the top-left corner - **y** (number) - Required - Y position of the top-left corner - **width** (number) - Required - Width of the rectangle - **height** (number) - Required - Height of the rectangle - **color** (Color) - Optional - Fill color of the rectangle - **borderColor** (Color) - Optional - Stroke color of the rectangle border - **borderWidth** (number) - Optional - Stroke width of the rectangle border - **opacity** (number) - Optional - Opacity of the rectangle (0-1) ### Request Body (No request body required, all parameters are in query) ### Request Example ```json { "x": 0, "y": 0, "width": 612, "height": 792, "color": "rgb(0.95, 0.95, 0.95)" } ``` ### Response #### Success Response (200) - **message** (string) - Success message #### Response Example ```json { "message": "Rectangle drawn successfully" } ``` ```