modify-pdf

Documentation

This is the documentation for the modify-pdf package. This NPM package provides a typesafe layer for simple manipulations of PDFs using the pdf-lib library.

Contents

Creating and loading PDFs

Creating PDFs

An empty PDF can be created with createDocument(). This generates a PDFDocument. See the pdf-lib documentation for more details.

Parameters:

Argument Type
pages PDFPage | undefined

Return type:

Promise<PDFDocument>

Example usage:

import { createDocument } from 'modify-pdf';
import { PDFDocument } from 'pdf-lib';

const document: PDFDocument = await createDocument();

Load PDF from HTML source

Files read from a HTML input can be loaded using loadDocument(). Make sure to pass only PDF documents. If the document fails to load, null is returned. An example of a React component is shown below.

Parameters:

Argument Type
file File

Return type:

PDFDocument | null

Example usage:

import { loadDocument } from 'modify-pdf';
import { PDFDocument } from 'pdf-lib';
import { ChangeEvent, useState } from 'react';

const MyComponent = () => {
    const handleChange = async (e: ChangEvent<HTMLInputElement>) {
        const files = e.target.files;
        if (files && files[0] && files[0].type === 'application/pdf') {
            const document: PDFDocument | null = await loadDocument(files[0]);
            if (document) {
              // Do something
              console.log(document.getTitle());
            }
        }
    };

    return (
        <div>
            <input type="file" onChange={(e) => handleChange(e)} />
        </div>
    );
}

Load PDF from local source

PDFs can be read from local sources using loadLocalDocument(). Provide a location of the file on the local machine to this function. If the document fails to load, null is returned.

Parameters:

Argument Type
src string

Return type:

Promise<PDFDocument | null>

Example usage:

import { loadLocalDocument } from 'modify-pdf'; // uses fs library
import { PDFDocument } from 'pdf-lib';

const document: PDFDocument | null = await loadLocalDocument('example.pdf');

Load PDF from base64 string

PDFs can be directly loaded from base64 strings using loadFromBytes(). This is an async function and returns null if the load fails.

Parameters:

Argument Type
data string

Return type:

Promise<PDFDocument | null>

Example usage:

import { loadFromBytes } from 'modify-pdf';
import { PDFDocument } from 'pdf-lib';

const base64 =
  'JVBERi0xLjcKJYGBgYEKCjUgMCBvYmoKPDwKL0ZpbHRlciAvRmxhdGVEZWNvZGUKL0xlbm' +
  'd0aCAxMDQKPj4Kc3RyZWFtCniccwrhMlAAwaJ0Ln2P1Jyy1JLM5ERdc0MjCwUjE4WQNC4Q' +
  '6cNlCFZkqGCqYGSqEJLLZWNuYGZiZmbkYuZsZmlmZGRgZmluDCQNzc3NTM2NzdzMXMxMjQ' +
  'ztFEKyuEK0uFxDuAAOERdVCmVuZHN0cmVhbQplbmRvYmoKCjYgMCBvYmoKPDwKL0ZpbHRl' +
  'ciAvRmxhdGVEZWNvZGUKL1R5cGUgL09ialN0bQovTiA0Ci9GaXJzdCAyMAovTGVuZ3RoID' +
  'IxNQo+PgpzdHJlYW0KeJxVj9GqwjAMhu/zFHkBzTo3nCCCiiKIHPEICuJF3cKoSCu2E8/b' +
  '20wPIr1p8v9/8kVhgilmGfawX2CGaVrgcAi0/bsy0lrX7IGWpvJ4iJYEN3gEmrrGBlQwGs' +
  'HHO9VBX1wNrxAqMX87RBD5xpJuddqwd82tjAHxzV1U5LPgy52DKXWnr1Lheg+j/c/pzGVr' +
  'iqV0VlwZPXGPCJjElw/ybkwUmeoWgxesDXGhHJC/D/iikp1Av80ptKU0FdBEe25pPihAM1' +
  'u6ytgaaWfs2Hrz35CJT1+EWmAKZW5kc3RyZWFtCmVuZG9iagoKNyAwIG9iago8PAovU2l6' +
  'ZSA4Ci9Sb290IDIgMCBSCi9GaWx0ZXIgL0ZsYXRlRGVjb2RlCi9UeXBlIC9YUmVmCi9MZW' +
  '5ndGggMzgKL1cgWyAxIDIgMiBdCi9JbmRleCBbIDAgOCBdCj4+CnN0cmVhbQp4nBXEwREA' +
  'EBAEsCwz3vrvRmOOyyOoGhZdutHN2MT55fIAVocD+AplbmRzdHJlYW0KZW5kb2JqCgpzdG' +
  'FydHhyZWYKNTEwCiUlRU9G';

const document: PDFDocument | null = await loadFromBytes(base64);

Convert PDF to an object URL

This is useful for displaying the PDF in the DOM e.g. in an iframe. Use the asynchronous documentToBlobUrl() to perform this conversion. An example React component is shown below.

Parameters:

Argument Type
document PDFDocument

Return type:

Promise<string>

Example usage:

import { documentToBlobUrl, createDocument } from 'modify-pdf';
import { PDFDocument } from 'pdf-lib';
import { useState } from 'react';

const MyComponent = () => {
  const [blobUrl, setBlobUrl] = useState<string>();

  const document: PDFDocument = await createDocument(); // example document
  const url: string = await documentToBlobUrl(document);
  setBlobUrl(url);

  return <div>{blobUrl ? <iframe src={blobUrl} /> : null}</div>;
};

Merging PDFs

Merge files

A list of files can be merged to produce a single PDFDocument with the asynchronous mergeFiles() function. This is useful for merging PDF documents provided from a HTML input. The function returns null if the array of files is empty. An example React component is shown below.

Parameters:

Argument Type
files File[]

Return type:

Promise<PDFDocument | null>

Example usage:

import { mergeFiles } from 'modify-pdf';
import { PDFDocument } from 'pdf-lib';

const MyComponent = () => {
    const handleChange = async (e: ChangEvent<HTMLInputElement>) {
        const files = e.target.files;
        // Assemble list of true PDF files
        const pdfFiles: File[] = [];
        for (const file of files) {
            if (file.type === 'application/pdf') {
                pdfFiles.push(file);
            }
        }
        // Now merge files
        const merged: PDFDocument | null = await mergeFiles(pdfFiles);
    };

    return (
        <div>
            <input type="file" onChange={(e) => handleChange(e)} />
        </div>
    );
};

Merge documents

mergeDocuments() can be used to merge PDFDocument[] into a single PDFDocument. This returns null if the array of documents is empty.

Parameters:

Argument Type
documents PDFDocument[]

Return type:

Promise<PDFDocument | null>

Example usage:

import { mergeDocuments } from 'modify-pdf';
import { PDFDocument } from 'pdf-lib';

const documents: PDFDocument[] = [...]; // array of documents;
const merged: PDFDocument | null = await mergeDocuments(documents);

Merge pages

mergePages() can be used to merge individual PDF pages into a PDF document. This returns null if the pages array is empty.

Parameters:

Argument Type
pages PDFPage[]

Return type:

Promise<PDFDocument | null>

Example usage:

import { mergePages } from 'modify-pdf';
import { PDFDocument, PDFPage } from 'pdf-lib';

const pages: PDFPage[] = [...]; // array of pages;
const merged: PDFDocument | null = await mergePages(pages);

Rotating PDFs

Rotate document

Use rotateDocument() to rotate all pages in a PDF document. The rotation angle must be a multiple of 90.

Parameters:

Argument Type
document PDFDocument
angle number (multiple of 90)

Return type:

PDFDocument

Example usage:

import { createDocument, rotateDocument } from 'modify-pdf';
import { PDFDocument } from 'pdf-lib';

const document: PDFDocument = await createDocument(); // example document
const rotated: PDFDocument = rotateDocument(document, 90); // 90° rotation

Rotate page

Use rotatePage() this to rotate an individual page.

Parameters:

Argument Type
page PDFPage
angle number (multiple of 90)

Return type:

PDFPage

Example usage:

import { createDocument, rotatePage } from 'modify-pdf';
import { PDFDocument, PDFPage } from 'pdf-lib';

const document: PDFDocument = await createDocument(); // example document
const page: PDFPage = document.getPage(0); // page 1
const rotated: PDFPage = rotatePage(page, 90); // 90° rotation

Rotate pages

Use rotatePages() to rotate multiple pages in an array of pages. This can optionally take a range to rotate a subset of pages. If no start and end is specified, all pages will be rotated by the same amount.

Parameters:

Argument Type
pages PDFPage
angle number (multiple of 90)
start number | undefined
end number | undefined

Return type:

PDFPage[]

Example usage:

import { createDocument, rotatePages } from 'modify-pdf';
import { PDFPage } from 'pdf-lib';

const pages: PDFPage[] = [...] // example array

const rotatedAll: PDFPage[] = rotatePages(pages, 90); // 90° rotation of all
const rotatedSubset: PDFPage[] = rotatePages(pages, 90, 0, 2, 90); // 90° rotation of indexes 0 -> 2

Rotate page in document

Similar to rotatePage() except that rotatePageInDoc() rotates a specific page inside of a document.

Parameters:

Argument Type
document PDFDocument
angle number (multiple of 90)
index number

Return type:

PDFDocument

Example usage:

import { createDocument, rotatePageInDoc } from 'modify-pdf';
import { PDFDocument } from 'pdf-lib';

const document: PDFDocument = await createDocument(); // example document
const rotated: PDFDocument = await rotatePageInDoc(page, 90, 0); // 90° rotation of page 1

Rotate pages in document

Use rotatePagesInDoc() to rotate a subset of pages within a PDF document. Works similarly to the previous function but it can take an index range for rotation.

Parameters:

Argument Type
document PDFDocument
angle number (multiple of 90)
start number | undefined
end number | undefined

Return type:

PDFDocument

Example usage:

import { createDocument, rotatePagesInDoc } from 'modify-pdf';
import { PDFDocument } from 'pdf-lib';

const document: PDFDocuemnt = await createDocument(); // example document

const rotatedAll: PDFDocument = await rotatePagesInDoc(document, 90); // 90° rotation of all pages
const rotatedSubset: PDFDocument = await rotatePagesInDoc(pages, 90, 0, 2); // 90° rotation of pages 1 -> 3

Copying

Copying documents

Use copyDocument() to return a copy of a PDF document.

Parameters:

Argument Type
document PDFDocument

Return type:

Promise<PDFDocument>

Example usage:

import { createDocument, copyDocument } from 'modify-pdf';
import { PDFDocument } from 'pdf-lib';

const document: PDFDocuemnt = await createDocument(); // example document
const copy: PDFDocument = await copyDocument(document);

Extract a single page

Use extractPage() to copy a single page into a new PDF document. This returns null if the index is invalid.

Parameters:

Argument Type
document PDFDocument
index number

Return type:

Promise<PDFDocument | null>

Example usage:

import { createDocument, extractPage } from 'modify-pdf';
import { PDFDocument } from 'pdf-lib';

const document: PDFDocuemnt = await createDocument(); // example document
const extracted: PDFDocument | null = await extractPage(document, 0); // exrtract page 1

Extract multiple pages

Similar to the above function but extractPages() copies a range of pages to a new document. If the index is invalid, null is returned.

Parameters:

Argument Type
document PDFDocument
start number
end number

Return type:

Promise<PDFDocument | null>

Example usage:

import { createDocument, extractPages } from 'modify-pdf';
import { PDFDocument } from 'pdf-lib';

const document: PDFDocuemnt = await createDocument(); // example document
const extracted: PDFDocument | null = await extractPages(document, 0, 3); // exrtract pages 1 -> 3

Duplicate pages within a document

duplicatePages() duplicates a page range within a document. Pages are duplicated where they occur within the document. If a range is not provided, all pages will be duplicated. If the range is invalid, null is returned.

Parameters:

Argument Type
document PDFDocument
start number | undefined
end number | undefined

Return type:

Promise<PDFDocument | null>

Example usage:

import { createDocument, duplicatePages } from 'modify-pdf';
import { PDFDocument } from 'pdf-lib';

const document: PDFDocuemnt = await createDocument(); // example document
const duplicated: PDFDocument | null = await duplicatePages(document, 0, 3); // duplicate pages 1 -> 3

Inserting pages (WIP)

Needs documenting.

Metadata (WIP)

PDF documents have a range of metadata associated with them.

{
  author: string | undefined;
  creator: string | undefined;
  producer: string | undefined;
  title: string | undefined;
  keywords: string[] | string | undefined;
  subject: string | undefined;
  creationDate: Date | undefined;
  modificationDate: Date | undefined;
  language: string | undefined; // this cannot be read at present
}

Get metadata

getMeta() is used to get the PDF file metadata. If no query is provided, all the metadata is returned.

Parameters:

Argument Type
document PDFDocument
query Meta | undefined

Return type:

Meta

Example usage:

import { createDocument, getMeta, MetaQuery } from 'modify-pdf';
import { PDFDocument } from 'pdf-lib';

const document: PDFDocuemnt = await createDocument(); // example document
const allMeta: MetaQuery = getMeta(document); // get all metadata
const result: Meta = getMeta(document, { title: true }); // get only the title
const title: string | undefined = result.title;

Set metadata

setMeta() is used to set the metadata of a PDF file.

Parameters:

Argument Type
document PDFDocument
meta Meta & {language?: string}

Return type:

void

Example usage:

import { createDocument, getMeta, setMeta, Meta } from 'modify-pdf';
import { PDFDocument } from 'pdf-lib';

const document: PDFDocuemnt = await createDocument(); // example document

const previousMeta: Meta = getMeta(document);
console.log(previousMeta);

const newMeta: Meta = { title: 'Hello world!' };
setMeta(document, newMeta);
const updatedMeta: Meta = getMeta(document);
console.log(updatedMeta);

Reset metadata

resetMeta() sets the metadata to default values. This clears all currently associated metadata.

Parameters:

Argument Type
document PDFDocument
meta Meta & {language?: string}

Return type:

void

Example usage:

import { createDocument, getMeta, resetMeta, Meta } from 'modify-pdf';
import { PDFDocument } from 'pdf-lib';

const document: PDFDocuemnt = await createDocument(); // example document

const previousMeta: Meta = getMeta(document);
console.log(previousMeta);

resetMeta(document);
const newMeta: Meta = getMeta(document);
console.log(newMeta);

Troublshooting

Next.js usage

If you import this library inside of the Next.js framework, you will need to adjust the webpack config since this module imports fs/promises. If you are using Webpack 5, change the following inside of /next.config.js:

/** @type {import('next').NextConfig} */
const nextConfig = {
  webpack: (config, { isServer }) => {
    if (!isServer) {
      config.resolve.fallback = {
        fs: false,
      };
    }

    return config;
  },
};

module.exports = nextConfig;

If using Webpack 4 or older versions of Next.js where this was the default, make the following adjustment to /next.config.js:

/** @type {import('next').NextConfig} */
const nextConfig = {
  webpack: (config, { isServer }) => {
    if (!isServer) {
      config.node = {
        fs: 'empty',
      };
    }

    return config;
  },
};

module.exports = nextConfig;