Skip to content
 
 

Latest commit

 

History

191 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

pdiiif logo

Demo

Sample PDF generated with the library

Library API Documentation

pdiiif is a JavaScript library to create PDFs from IIIF Manifests. For the most part, it runs both in browsers and as a Node.js server-side application. When generating a PDF in the browser, image and OCR downloads happen directly between the user's browser and the IIIF APIs referenced from the Manifest when CORS allows it. The bundled web application can also use the API server to fetch manifests through a small proxy endpoint when manifest CORS headers would otherwise block the browser. Cover pages are generated on the server by default (see this section for more details).

It comes with a small sample web application that demonstrates how to use the library in the browser, you can check out a public instance of it at https://pdiiif.jbaiter.de, the source code is located in the pdiiif-web subdirectory. The web app can be launched with an initial manifest URL via the ?manifest= query parameter, which is useful when opening pdiiif from another application.

A main goal of the library is to be as memory-efficient as possible, by never holding more than a few pages in memory and streaming directly to the user's disk (precise method depends on the environment).

It is also well-suited for embedding in other applications due to its relatively small footprint, for example, the example web application comes in at ~120KiB gzipped with all dependencies.

In addition to the images on the IIIF Canvases referenced in the manifest, the library can create a hidden text layer from OCR associated with each canvas (ALTO or hOCR referenced from a canvas' seeAlso property).

In order to not sever the connection between the PDF and the original IIIF resources on the Web, every PDF generated by pdiiif includes the IIIF Manifest as a PDF attachment, as well as every OCR file referenced in seeAlso. Additionally, pdiiif can generate the PDFs in a way that also makes them valid ZIP files that contain the manifest and all of the images and OCR files, with almost no storage overhead. (thanks to Ange Albertini and his work on Poc||GTFO for the inspiration!)

Features

  • PDF Page for every single-image Canvas in a Manifest
  • Rendering Canvases with multiple images
  • PDF Table of Contents from IIIF Ranges
  • Cover page with metadata, attribution and licensing information
  • Hidden text layer from ALTO or hOCR OCR
  • Render IIIF layers as PDF "optional content groups" that can be toggled
  • Rendering of IIIF Annotations as PDF annotations
  • Include IIIF Manifest and referenced OCR files as PDF attachments
  • Generate polyglot PDFs that are also ZIP files of all resources
  • JPEG optimization and PNG image support
  • Server-assisted manifest fetching for the web app via /api/proxy-manifest
  • Work around duplicate AnnotationPage/Annotation IDs in some malformed IIIF 3 manifests

Quickstart

Besides using the public instance at https://pdiiif.jbaiter.de, you can also run the app yourself. The easiest way to run the bundled web app and API together is with Docker:

docker build . -t pdiiif

# SYS_ADMIN is required for the headless Chromium instance that generates cover page PDFs.
docker run -p 8080:8080 --cap-add=SYS_ADMIN --name pdiiif pdiiif

Open http://localhost:8080 after the container starts.

The included compose file is configured for local container deployment on port 8082:

docker compose up --build
# or: podman-compose up --build

Open http://localhost:8082 when using compose.

For local development, run the API and web app in separate terminals:

pnpm install
pnpm --filter pdiiif-server run dev
pnpm --filter pdiiif-web run dev

The web development server uses http://localhost:31337/api by default.

Deployment

Container images are built from the root Dockerfile. The repository also contains:

  • DEPLOYMENT.md: production deployment runbook, including GHCR image tags, server update commands, and Caddy configuration.
  • docker-compose.yml: local/container deployment configuration with CFG_PORT=8082.
  • quadlets/: rootless Podman quadlet units and a generator script for running pdiiif under user systemd.
  • Caddyfile-addition.txt: reverse proxy snippet for iiif-pdf-a.universiteitleiden.nl.

Cookbook Matrix

The IIIF Cookbook has a matrix of "recipes" with viewer support, here's an overview of the recipe support in pdiiif:

Basic Recipes (4 of 6 supported)
IIIF Properties (8 of 15 supported)
Structuring Resources (3 of 6 supported)
Image Recipes (6 of 6 supported)
Annotation Recipes (4 of 5 supported)
  • Simple Annotation — Tagging: YES
  • Tagging with an External Resource: NO
  • Annotation with a Non-Rectangular Polygon: YES
  • Simplest Annotation: YES
  • Embedded or referenced Annotations: YES

Structure of the repository

  • ./pdiiif-lib: Contains the library source code
  • ./pdiiif-api: Small node.js server application that is responsible for generating the cover pages and that can be used as a fallback for browsers that don't support the Native Filesystem API or service workers.
  • ./pdiiif-web: Sample web application (using Svelte) to demonstrate using pdiiif in the browser
  • ./quadlets: Podman quadlet files for rootless systemd deployment
  • ./DEPLOYMENT.md: Operational notes for GHCR, Podman, Caddy, and production updates

Cover Page Endpoints

pdiiif tries to include a cover page with a thumbnail, descriptive metadata and rights and attribution information. Since typesetting these pages is beyond the scope of what our bespoke PDF generator can provide (most notably, TTF/OTF font retrieval for arbitrary languages/scripts and font subsetting), this cover page currently needs to be generated elsewhere. By default, the library is using a public endpoint at https://pdiiif.jbaiter.de/api/coverpage, which generates a PDF with the default template. The endpoint can be changed with the coverPageEndpoint configuration parameter in the options passed to the convertManifest function.

If you want to customize the template that is being used, you can either host the API provided in this repository yourself (see Quickstart) and override the template by mounting your own custom Handlebars template into the image at /opt/pdiiif/pdiiif-api/dist/assets/coverpage.hbs. For a list of available helpers that you can use, refer to handlebars-helpers. Also available are these two custom helpers:

  • qrcode, takes a value and an optional { width, height, padding, color, background, ecl } options object and returns the value encoded as a SVG QR code image
  • sanitize-html, takes an arbitrary HTML string and sanitizes it according to the IIIF HTML rules

If you want to provide your own implementation, make sure that your HTTP endpoint generates a valid PDF and accepts a JSON POST body with the following shape (i.e. does not throw an error when encountering any of these fields):

{
  title: string;
  manifestUrl: string;
  thumbnail?: {
    url: string;
    iiifImageService?: string;
  };
  provider?: {
    label: string;
    homepage?: string;
    logo?: string;
  };
  requiredStatement?: {
    label: string;
    value: string;
  };
  rights?: {
    text: string;
    url?: string;
    logo?: string;
  };
  // [key, value] pairs, with value either single- or multi-valued
  metadata?: Array<[string, string | Array<string>]>;
  pdiiifVersion: string;
}

About

Create PDFs from IIIF manifests, completely client-side (with server-based fallback for unsupported browsers)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages