pdfuse-core
v0.2.0
Published
Browser PDF toolkit: load, merge selected pages, and render previews to canvas. Built on pdf-lib and pdfjs-dist. TypeScript, ESM & CJS.
Downloads
60
Maintainers
Readme
pdfuse-core
pdfuse-core is a small, headless JavaScript / TypeScript library for working with PDFs in the browser. It builds on pdf-lib and pdfjs-dist and gives you typed helpers to:
- Load uploaded PDFs and read page counts
- Merge selected pages from multiple documents into a single downloadable PDF (
Uint8Array) - Render PDF pages to a canvas (thumbnails, previews) — no need to install or wire up
pdfjs-distyourself
Use it in React, Vue, Svelte, or vanilla apps where users pick files with <input type="file"> and you want client-side PDF tooling without a server.
Features
- Merge PDF pages from multiple sources in a custom order
- Render any page of a loaded PDF to an
HTMLCanvasElement - Load PDF from a
Fileand get apdf-libPDFDocumentplus total page count - TypeScript types included (
UploadedPDF,PageSelectionKey, etc.) - ESM and CommonJS builds (
import/require) - Tree-shakeable (
sideEffects: false) — the preview module is a separate subpath, sopdfjs-distis only bundled if you actually use rendering
Installation
npm install pdfuse-corepnpm add pdfuse-coreyarn add pdfuse-corePeer environment: loadPdfDocument uses the browser File and FileReader APIs. The preview module uses pdfjs-dist and renders to a real HTMLCanvasElement. Both are intended for browser runtimes (or compatible environments). The merge helper itself only needs the in-memory PDFDocument instances you already loaded.
Entry points
| Import path | Brings in | Use for |
| ----------------------- | ---------------------------------- | ----------------------------------------- |
| pdfuse-core | pdf-lib | Loading from File, merging pages |
| pdfuse-core/preview | pdfjs-dist | Loading for preview, rendering to canvas |
If you only need merging, importing from pdfuse-core keeps pdfjs-dist out of your bundle.
Quick start
1. Load a PDF from a file input
import { loadPdfDocument } from "pdfuse-core";
async function onFileSelected(file: File) {
const { pdfDoc, totalPages } = await loadPdfDocument(file);
console.log(totalPages, pdfDoc);
}2. Merge selected pages from several PDFs
Each uploaded PDF is represented as an UploadedPDF: metadata plus the loaded pdf-lib document. PageSelectionKey picks a zero-based page from a PDF by its index in your array.
import { loadPdfDocument, mergeSelectedPages } from "pdfuse-core";
import type { UploadedPDF, PageSelectionKey } from "pdfuse-core";
const files: File[] = /* from input or drop zone */;
const pdfs: UploadedPDF[] = await Promise.all(
files.map(async (file, i) => {
const { pdfDoc, totalPages } = await loadPdfDocument(file);
return {
id: `doc-${i}`,
file,
pdfDoc,
totalPages,
};
}),
);
// Order matters: first page of first PDF, then page 3 of second PDF, etc.
const selectedOrder: PageSelectionKey[] = [
{ pdfIndex: 0, pageIndex: 0 },
{ pdfIndex: 1, pageIndex: 2 },
];
const pdfBytes: Uint8Array = await mergeSelectedPages(pdfs, selectedOrder);
// Example: trigger download in the browser
const blob = new Blob([pdfBytes], { type: "application/pdf" });
const url = URL.createObjectURL(blob);
const a = Object.assign(document.createElement("a"), { href: url, download: "merged.pdf" });
a.click();
URL.revokeObjectURL(url);3. Render a page to a canvas (preview / thumbnails)
The preview helpers live at the pdfuse-core/preview subpath so pdfjs-dist is only bundled when you actually use rendering.
Step A: configure the pdfjs worker once at startup. The worker URL is bundler-specific:
// Vite
import { setPdfjsWorker } from "pdfuse-core/preview";
import workerUrl from "pdfjs-dist/build/pdf.worker.mjs?url";
setPdfjsWorker(workerUrl);// Webpack 5 / native ESM
import { setPdfjsWorker } from "pdfuse-core/preview";
setPdfjsWorker(
new URL("pdfjs-dist/build/pdf.worker.mjs", import.meta.url).toString(),
);Step B: load and render.
import { loadPdfForPreview, renderPageToCanvas } from "pdfuse-core/preview";
async function renderFirstPage(file: File, canvas: HTMLCanvasElement) {
const pdf = await loadPdfForPreview(file); // accepts File | Blob | ArrayBuffer | Uint8Array
await renderPageToCanvas(pdf, 1, canvas, { scale: 1.5 });
}loadPdfForPreview returns a pdfjs PDFDocumentProxy. Cache it per file if you plan to render multiple pages — re-loading is wasteful.
API
Default entry — pdfuse-core
| Export | Description |
| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| isPdfFile(file) | Returns true if the File looks like a PDF (MIME type or .pdf extension). |
| loadPdfDocument(file) | Loads a PDF from a File; returns { pdfDoc, totalPages }. Throws if not a PDF, unreadable, or has no pages. Uses ignoreEncryption: true. |
| mergeSelectedPages(pdfs, selectedOrder) | Creates a new PDF containing the chosen pages in order; returns Uint8Array. Skips invalid indices safely. |
Preview entry — pdfuse-core/preview
| Export | Description |
| --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| setPdfjsWorker(workerSrc) | Sets the pdfjs worker source. Call once at app startup before any loadPdfForPreview call. |
| loadPdfForPreview(input) | Loads a PDF for rendering. Accepts File, Blob, ArrayBuffer, or Uint8Array. Returns PDFDocumentProxy. |
| renderPageToCanvas(pdf, pageNumber, canvas, options?) | Renders page pageNumber (1-based) of pdf into canvas. options.scale (default 1.2), options.intent. |
| PDFDocumentProxy, PDFPageProxy | Re-exported pdfjs types so you don't need a separate import type from pdfjs-dist. |
Types
| Type | Purpose |
| ----------------------- | ----------------------------------------------------------------------------- |
| UploadedPDF | id, file, pdfDoc (pdf-lib), totalPages |
| PageSelectionKey | pdfIndex (into the pdfs array), pageIndex (0-based page) |
| LoadedPDF | id, pdfDoc, totalPages (no File) |
| PageSelection | Alternative shape: one LoadedPDF plus pages: number[] |
| PdfPreviewInput | File | Blob | ArrayBuffer | Uint8Array |
| RenderOptions | { scale?: number; intent?: "display" | "print" | "any" } |
Types re-export PDFDocument usage via pdf-lib; advanced edits can use the returned pdfDoc with pdf-lib directly.
Requirements
- Node.js ≥ 18 (for tooling / SSR setups that consume the package)
- Runtime:
loadPdfDocumentexpectsFile+FileReader(browser-style APIs). The preview module expects anHTMLCanvasElementand a bundler that can resolve the pdfjs worker.
Related
- Full app: PDFuse — merge PDFs in the browser
- Source (monorepo): github.com/mahabeer-dev/PDFuse (
packages/core)
License
MIT
