npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@zinejs/pdf

v1.0.2

Published

PDF content source for zinejs, powered by pdf.js.

Downloads

1,695

Readme

@zinejs/pdf

PDF content source for zinejs, powered by pdf.js. Renders PDF pages to canvases that @zinejs/core paints as a flipbook.

Docs and examples: zinejs.com/docs · CDN example

Install

npm install @zinejs/core @zinejs/pdf

pdfjs-dist installs with this package. It is loaded lazily (dynamic import) so it never lands in the @zinejs/core bundle. If your app already depends on pdfjs-dist, keep major versions compatible so the worker matches the library.

Usage

import { Zine } from '@zinejs/core'
import { PdfSource } from '@zinejs/pdf'

new Zine(document.getElementById('book'), {
  source: new PdfSource('document.pdf'),
})

Under a bundler that is all you need: the pdf.js worker is resolved for you.

src can also be raw bytes or a pdf.js document you already opened:

new PdfSource(arrayBuffer)
new PdfSource(await getDocument(url).promise)

The pdf.js worker

pdf.js parses and rasterizes in a Web Worker. By default PdfSource finds the worker via Vite's ?url import, webpack's new URL('pdfjs-dist/…', import.meta.url) emit, or the sibling pdfjs-dist install. If that cannot be resolved, it falls back to a jsDelivr URL pinned to the same pdfjs-dist version that loaded, and warns once in the console. Set cdnFallback: false for CSP-restricted or offline apps (then pass workerSrc, or the open fails clearly instead of loading a network worker that CSP would block).

Resolution order: workerSrc option, then pdfjsLib.GlobalWorkerOptions.workerSrc, then that auto-default. Pass workerSrc for CDN / UMD, offline / CSP setups, or if auto-resolve fails in your bundler:

import { PdfSource } from '@zinejs/pdf'
import workerSrc from 'pdfjs-dist/legacy/build/pdf.worker.min.mjs?url'

new PdfSource('document.pdf', { workerSrc })
// CSP / offline: also disable the CDN last resort
new PdfSource('document.pdf', { workerSrc, cdnFallback: false })

pdf.js also loads data files on demand: cmaps/ (CJK and other non-embedded encodings), standard_fonts/ (PDFs that don't embed their fonts), iccs/ (CMYK colour) and wasm/ (JPEG 2000 and JBIG2 image decoders, pdf.js 5+). Without them those pages draw blank images or wrong glyphs. PdfSource points pdf.js at the pdfjs-dist the worker came from, else the same jsDelivr version (when cdnFallback is on). If you self-host the worker elsewhere, copy those four folders under one base and pass it as assetsUrl:

new PdfSource('document.pdf', { workerSrc: '/pdfjs/pdf.worker.min.mjs', assetsUrl: '/pdfjs/' })

Keep the worker on the same build as the library (legacy vs modern). If you already set GlobalWorkerOptions.workerSrc, leave workerSrc off. A pre-created pdf.js document needs no worker from this package.

Vite: exclude from dependency pre-bundling

Vite's dependency optimizer may not be able to follow the worker's ?url import, so pre-bundling @zinejs/pdf fails to start the dev server (Could not load .../pdf.worker.min.mjs?url). Exclude it so Vite's normal pipeline resolves the worker:

// vite.config.js
import { defineConfig } from 'vite'

export default defineConfig({
  optimizeDeps: { exclude: ['@zinejs/pdf'] },
})

(npm create @zinejs sets this up for you in the PDF starter.)

CDN / no bundler: load pdf.js first, expose globalThis.pdfjsLib, then the UMD builds (core first). See the HTML CDN example. A UMD host has no bundler to resolve the worker locally, so it uses your workerSrc, an already-set GlobalWorkerOptions.workerSrc, or the version-matched CDN fallback (matched to the global pdf.js's version; silent here, since a CSP/offline failure surfaces through the browser and pdf.js anyway). Set cdnFallback: false to require explicit configuration instead.

Options

new PdfSource(src, {
  workerSrc,           // override the auto-resolved worker URL
  cdnFallback: true,   // false: never load the worker from jsDelivr (CSP / offline)
  assetsUrl,           // pdfjs-dist root for cmaps / fonts / iccs / wasm (auto-resolved)
  renderScale: 1,      // pages rasterize at renderScale × devicePixelRatio
  preload: 1,          // adjacent pages to prefetch (default 1)
  maxCacheBytes,       // soft cap on cached page bytes (default ~256 MB)
  progressive: false,  // true: low-res first, then crisp
  disableAutoFetch: false, // true: fetch only the ranges visible pages need
  legacy: true,        // false: lean modern pdf.js (recent engines only)
})

Legacy vs modern (legacy)

pdf.js ships two builds. The legacy build is transpiled with polyfills and is the default, so PDF books stay usable on older engines as well as current ones. The modern build is smaller and a touch faster. Pass legacy: false when your audience is on recent browsers:

new PdfSource('document.pdf', { legacy: false })

The flag also picks the matching worker. It is ignored when you pass a pre-created document or set globalThis.pdfjsLib, since those already chose their build.

Mozilla documents legacy as Chrome 125+, Firefox ESR, Safari 18+, and Chromium Edge. We have seen PDF text rasterize correctly back to Chrome 114. Full notes: browser support.