Skip to content
byrizkiPublic

About

Printedjs is a modular TypeScript rewrite of legacy Paged.js

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

Printedjs

npm version nuget version CI License: MIT

Modern, high-performance browser-native paginated document rendering.

Printedjs is a modular TypeScript redesign of legacy Paged.js, engineered for high reliability, deterministic lifecycle control, zero core DOM dependencies, and resilient edge-case handling.


Packages

Printedjs is maintained as a modular pnpm monorepo with clean architectural boundaries:

Core & Runtime Packages

Distribution & Tooling Packages

  • @printedjs/minimal — Standalone bundle (printedjs.min.js) with complete engine, plugins, auto-init, and legacy Paged.js migration shims
  • @printedjs/headless-webview — Standalone cross-platform headless webview & vector PDF generator (React Native iOS/Android/Desktop & .NET NuGet)
  • @printedjs/polyfill — Compatibility layer for older browsers, providing DOM and observer polyfills
  • @printedjs/cli — Headless PDF generation CLI (printedjs render) with bundled native webview, Playwright, and Puppeteer drivers
  • @printedjs/devtools — Diagnostic trace collector and non-layout visual inspector overlay

Applications & Demos

  • apps/playground — Interactive developer fixture playground with surface and diagnostics toggles (pnpm dev)
  • apps/minimal-demo — Zero-config standalone demo showcasing static HTML document pagination using @printedjs/minimal (pnpm dev:minimal)

Available Plugins

All core plugins can be loaded together via @printedjs/plugin-preset or installed individually for fine-grained tree-shaking:

Core Plugins

Package Version Purpose
@printedjs/plugin-preset npm Standard bundle combining all core layout plugins
@printedjs/plugin-page-rules npm @page size, margins, orientation, bleeds, and crop marks
@printedjs/plugin-breaks npm CSS break-before, break-after, break-inside, and avoid rules
@printedjs/plugin-strings npm Named strings (string-set, string()) for running headers and footers
@printedjs/plugin-generated-content npm 16 W3C margin boxes, track distribution, and running elements
@printedjs/plugin-counters npm Page numbering (counter(page), counter(pages)), Roman/alpha styles, and target-counter
@printedjs/plugin-footnotes npm W3C GCPM float: footnote, @footnote area, and continuation slicing
@printedjs/plugin-columns npm Multi-column layout (column-count, column-gap, column-span: all, balancing)
@printedjs/plugin-widows-orphans npm Typography constraints at page boundaries (widows, orphans)
@printedjs/plugin-math npm Formula break protection for KaTeX, MathJax, and MathML
@printedjs/plugin-hyphenation npm Soft hyphen preservation and hyphenation normalization
@printedjs/plugin-bookmarks npm Document heading hierarchy extraction and PDF bookmark outline
@printedjs/plugin-lists npm Ordered list numbering and sequence continuity across page splits
@printedjs/plugin-running-headers npm Dynamic running headers and footers utility alias
@printedjs/plugin-views npm Presentation view modes (single page, spread)

Community Plugins

Package Version Purpose
@printedjs/plugin-page-flip npm Interactive 3D flipbook page-turning presentation engine
@printedjs/plugin-eta npm Dynamic pre-pagination document templating powered by Eta

Quick Start

pnpm add @printedjs/browser @printedjs/plugin-preset
import { createRenderer } from "@printedjs/browser";
import { standardPreset } from "@printedjs/plugin-preset";

const target = document.querySelector("#output")!;

const renderer = createRenderer({
	target,
	isolation: "root", // or "iframe" for total style & script sandboxing
	plugins: standardPreset(),
});

const result = await renderer.render({
	content: {
		html: `
      <style>
        @page {
          size: letter;
          margin: 1in;
          @bottom-center {
            content: counter(page);
          }
        }
      </style>
      <h1>Document Title</h1>
      <p>Content flows cleanly across page boundaries.</p>
    `,
	},
});

console.log(`Rendered ${result.pages.length} pages.`);

// Clean up completely with zero DOM residue:
renderer.destroy();

Headless PDF Generation (CLI)

# Render HTML document to PDF with print bleed and A4 format (Playwright or Puppeteer)
pnpm printedjs render document.html -o document.pdf --format A4 --bleed 3mm --engine playwright
pnpm printedjs render document.html -o document.pdf --format A4 --engine puppeteer

# Live watch mode for iterative document authoring
pnpm printedjs render document.html -o document.pdf --watch

Printedjs vs. Paged.js Feature Comparison

Feature / Capability Printedjs Paged.js
CSS @page Rules (sheet sizes, margins, bleed, crop marks) ✅ ✅
CSS Margin Boxes (16 standard margin boxes) ✅ ✅
Page Counters & Styles (roman, alpha, counter(pages), target-counter) ✅ ✅
Named Strings (string-set, running headers & footers) ✅ ✅
Standard Page Breaks (break-before, break-after, avoid) ✅ ✅
Drop-in <script> Polyfill (auto-render on page load) ✅ ✅
Cross-Browser Engine Parity (Chromium, Firefox, WebKit) ✅ ⚠️
Physical Blank Page Insertion (recto / verso spreads) ✅ ⚠️
Table Header & Footer Repeating (<thead> / <tfoot>) ✅ ⚠️
Multi-Column Formatting (column-count, balancing) ✅ ⚠️
Footnote Layout (float: footnote, continuations) ✅ ⚠️
Cross-Page Table Column Width Synchronization ✅ ❌
Multi-Page Table rowspan Continuation ✅ ❌
Math Formula Break Protection (KaTeX, MathJax, MathML) ✅ ❌
Infinite Loop & Freeze Guard (LayoutProgressGuard) ✅ ❌
DOM Isolation Surfaces (in-place root or sandboxed iframe) ✅ ❌
Clean Teardown (deterministic destroy(), zero DOM residue) ✅ ❌
Pure Zero-DOM Core (headless Node / Worker execution) ✅ ❌
Page Virtualization (smooth scrolling on 200+ pages) ✅ ❌
Incremental Re-Pagination (renderIncremental) ✅ ❌
100% Strict TypeScript (strict types & exported contracts) ✅ ❌
Native Headless PDF CLI (Playwright & Puppeteer drivers) ✅ ❌

Legend: ✅ Full Support  |  ⚠️ Partial / Limited  |  ❌ Unsupported

Bundle Size Comparison

Printedjs delivers a significantly leaner footprint than legacy Paged.js, with tree-shakable modular packages for modern bundlers:

Distribution / Bundle Minified Gzip Brotli vs Paged.js
Paged.js Polyfill (paged.polyfill.min.js) 504.1 KB 99.0 KB 83.6 KB Baseline
Printedjs Standalone Bundle (@printedjs/minimal) 200.1 KB 52.2 KB 44.9 KB -60.3%
Printedjs Browser Renderer (@printedjs/browser) 105.2 KB 19.4 KB 16.7 KB Modular import
Printedjs Core Engine (@printedjs/core) 18.2 KB 4.6 KB 4.1 KB Pure zero-DOM

Documentation


Verification Pipeline

# Verify code formatting, linting, typechecks, and unit test suite
pnpm verify

# Build all packages and applications
pnpm build

# Run browser tests across engines (Chromium, Firefox, WebKit)
pnpm test:browser

# Validate distribution package exports and bundles
pnpm pack:check

Baseline Parity Corpus

Printedjs is rigorously validated against the 122-fixture legacy Paged.js corpus located in tests/fixtures/, with verified accepted baselines in tests/baseline/accepted/.


Credits & Acknowledgments

Printedjs is inspired by and builds upon the pioneering work of Paged.js by the Cabbage Tree Labs community. We are deeply grateful to the Paged.js authors and contributors for championing CSS Paged Media standards in browsers and providing the foundational groundwork that made this project possible.

Special thanks to the Tauri Apps team for Wry, the cross-platform WebView rendering engine in Rust that powers native headless WebView rendering and vector PDF generation on desktop platforms and CLI.

About

Printedjs is a modular TypeScript rewrite of legacy Paged.js

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages