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

tsara-pdf

v1.0.1

Published

TsaraPDF - Convertit du HTML en PDF paginé avec preview et telechargement

Readme

TsaraPDF

HTML → paginated PDF with built-in preview, customizable headers/footers, and download. Zero runtime dependencies (pure TypeScript + Canvas API).

Features

  • HTML → PDF: pass a CSS selector, an ID, or an HTMLElement.
  • Automatic pagination: splits content into A4 / A3 / A5 / Letter / Legal pages (portrait or landscape) or a custom size.
  • Overflow handled: tables, lists, and long text — tags are closed and reopened on the next page so the markup stays valid.
  • Headers / Footers: static HTML or a (page, total) => string function.
  • Built-in viewer: paginated preview with zoom, print, and download.
  • 3 distribution modes: npm package (ESM), CDN bundle, Chrome MV3 extension.
  • Built-in i18n: EN / FR / ES / DE / RU (viewer, errors, extension) — customizable via setLang / lang option / translations.
  • No runtime dependencies — only typescript as a devDependency.

Project structure

TsaraPDF/
├── src/                  TypeScript source
│   ├── index.ts          Public API (export / preview / toBlob / toDataURL)
│   ├── paginator.ts      Splits HTML → pages
│   ├── renderer.ts       HTML → canvas → PDF blob
│   ├── viewer.ts         Built-in preview UI
│   └── types.ts          Types + PAGE_SIZES + DEFAULT_OPTIONS
├── dist/                 Build output (tsc + bundler)
├── chrome-extension/     Chrome MV3 extension
├── demo/                 Standalone HTML demo
├── scripts/bundle.js     CDN bundler (dist/tsara-pdf.min.js)
└── package.json

Installation

NPM

npm install tsara-pdf
import TsaraPDF from 'tsara-pdf';

TsaraPDF.export('#content', { filename: 'report.pdf' });

CDN / script tag

<script src="path/to/dist/tsara-pdf.min.js"></script>
<script>
  TsaraPDF.export('#content');
</script>

Chrome extension

  1. Open chrome://extensions
  2. Enable Developer mode
  3. Load unpacked extension → select the chrome-extension/ folder
  4. The icon appears in the toolbar: click it to export the current page or the current selection to PDF.

API

// Export with viewer (default)
await TsaraPDF.export('#content', options);

// Alias: same as export({ ...options, showViewer: true })
await TsaraPDF.preview('#content', options);

// Produce a PDF Blob without any UI
const blob = await TsaraPDF.toBlob('#content', options);

// Produce a data URL (base64)
const url = await TsaraPDF.toDataURL('#content', options);

The first argument accepts:

  • a CSS selector ('#content', '.report', 'main > article')
  • or an options object with sourceId or sourceElement

Internationalization

Viewer toolbar, error messages, and the Chrome extension are translated into English, French, Spanish, German, and Russian. By default, TsaraPDF detects navigator.language; you can also force the language globally or per call.

Global language

import TsaraPDF from 'tsara-pdf';

TsaraPDF.setLang('fr');   // 'en' | 'fr' | 'es' | 'de' | 'ru'
TsaraPDF.getLang();       // → 'fr'

Per-call override

TsaraPDF.export('#content', {
  lang: 'de',              // this export will be in German, global untouched
  filename: 'bericht.pdf',
});

Custom translations

To keep a base language but patch a few labels:

TsaraPDF.export('#content', {
  lang: 'fr',
  translations: {
    download: 'Récupérer mon document',
    print: 'Envoyer à l\'imprimante',
  },
});

Or define a full custom language:

TsaraPDF.export('#content', {
  translations: {
    print: 'Drukuj',
    download: 'Pobierz PDF',
    close: 'Zamknij',
    zoomIn: 'Powiększ',
    zoomOut: 'Pomniejsz',
    pagesCount: (n) => `${n} stron`,
    elementNotFound: (s) => `nie znaleziono elementu "${s}"`,
    sourceRequired: 'wymagane sourceId lub sourceElement',
    renderError: (e) => `błąd renderowania: ${e}`,
  },
});

Available keys

| Key | Type | Usage | |-------------------|--------------------------------|-------| | print | string | "Print" button | | download | string | "Download" button | | close | string | Close-cross tooltip / aria-label | | zoomIn | string | Zoom-in button tooltip | | zoomOut | string | Zoom-out button tooltip | | pagesCount | (n: number) => string | Pluralized page counter (N pages) | | elementNotFound | (selector: string) => string | "Selector not found" error | | sourceRequired | string | Missing sourceId / sourceElement error | | renderError | (err: string) => string | HTML render error |

Chrome extension

The extension popup includes a language selector (top-right corner). The choice is persisted in localStorage and forwarded to TsaraPDF.export when exporting.

Options

| Option | Type | Default | Description | |----------------|-----------------------------------|-------------------------------|-------------| | filename | string | 'document.pdf' | Name of the downloaded file. | | pageSize | 'A4' \| 'A3' \| 'A5' \| 'Letter' \| 'Legal' \| {width, height} | 'A4' | Page format. Dimensions in mm when passed as an object. | | orientation | 'portrait' \| 'landscape' | 'portrait' | Page orientation. | | margin | {top, right, bottom, left} | {15, 15, 20, 15} | Margins in mm. | | header | string \| (page, total) => string | '' | HTML repeated at the top of every page. | | footer | string \| (page, total) => string | ${page} / ${total} (centered) | HTML repeated at the bottom of every page. | | scale | number | 2 | Render scale (2 = retina). | | imageQuality | number (0–1) | 0.95 | JPEG quality for pages. | | css | string | '' | Extra CSS injected before render (no <style> wrapper needed). | | showViewer | boolean | true | Show the preview after generation. | | onProgress | (current, total) => void | — | Callback invoked for each rendered page. | | lang | 'en' \| 'fr' \| 'es' \| 'de' \| 'ru' | auto (navigator.language) | Language for this export (overrides the global setLang). | | translations | Partial<Translations> | — | Label overrides (see Internationalization). | | viewMode | 'all' \| 'single' | 'all' | Initial viewer mode. See Navigation. |

Navigation

The viewer offers two display modes, switchable from the toolbar:

  • All pages ('all', default) — continuous vertical scroll.
  • Page by page ('single') — one page at a time with a nav bar:
    • ◀ Previous / Next ▶ buttons
    • Numeric input to jump to a specific page (press Enter to apply)
    • Keyboard shortcuts: / , PageUp / PageDown, Space (next), Home / End, Esc (close)

Start directly in page-by-page mode:

TsaraPDF.export('#content', { viewMode: 'single' });

Labels Previous / Next / Page X of Y follow the active language (see Internationalization).

Examples

Dynamic header / footer

TsaraPDF.export('#report', {
  filename: 'report-Q1.pdf',
  pageSize: 'A4',
  margin: { top: 25, right: 15, bottom: 25, left: 15 },
  header: (page, total) =>
    `<div style="font-size:10px;color:#666">Q1 Report — page ${page}/${total}</div>`,
  footer: (page) =>
    `<div style="text-align:right;font-size:9px;color:#999">© 2026 — ${page}</div>`,
});

No viewer, with progress

await TsaraPDF.export('#content', {
  showViewer: false,
  onProgress: (current, total) => {
    console.log(`Rendering page ${current}/${total}`);
  },
});

Server-friendly generation (no UI)

const blob = await TsaraPDF.toBlob('#invoice', { pageSize: 'A4' });
const formData = new FormData();
formData.append('file', blob, 'invoice.pdf');
await fetch('/upload', { method: 'POST', body: formData });

Custom format

TsaraPDF.export('#ticket', {
  pageSize: { width: 80, height: 200 },  // 80mm ticket
  margin: { top: 5, right: 5, bottom: 5, left: 5 },
  showViewer: false,
});

Demo

npm run demo
# or
open demo/index.html

Build

npm install
npm run build         # tsc + bundler → dist/tsara-pdf.min.js
npm run dev           # tsc --watch

Artifacts generated in dist/:

  • index.js + *.js.map (compiled ES modules)
  • *.d.ts (TypeScript declarations)
  • tsara-pdf.min.js (CDN IIFE bundle, auto-exposes window.TsaraPDF)

Requirements

  • Node 18+ and npm (for the build)
  • Modern browser with Canvas API support (recent Chrome/Firefox/Safari/Edge)

License

MIT © Abraham Mahasongona