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

@uurtech/jdf

v0.1.21

Published

Render JDF (JSON Document Format) documents in the browser. Drop-in replacement for embedding PDFs — point at a .jdf file and it appears on the page, fully styled, searchable, with a clickable TOC.

Readme

jdf.js

npm license

Render JDF (JSON Document Format) files in any web page with a single tag. Like PDF.js — but the file you point at is plain JSON, so you can also generate it, diff it, and edit it with any tool.

<link rel="stylesheet" href="https://unpkg.com/@uurtech/[email protected]/dist/jdfjs.css">
<script type="module" src="https://unpkg.com/@uurtech/[email protected]"></script>

<jdf src="/whitepaper.jdf"></jdf>

That's the whole thing. Every <jdf> tag on the page is detected on load and rendered in place.

Install

npm install @uurtech/jdf

Or via CDN — no install at all:

<script type="module" src="https://unpkg.com/@uurtech/[email protected]"></script>

Usage

<jdf src="/doc.jdf"></jdf>

<!-- Configure with attributes -->
<jdf src="/doc.jdf"
     width="800"
     height="600"
     zoom="1.2"
     sidebar="true"
     dark-mode="auto"></jdf>

That is the only embed form. The <jdf> element is registered as a custom element with reactive attributes — change src programmatically and the embed updates:

document.querySelector("jdf").setAttribute("src", "/other.jdf");

Configuration

| Attribute | Type | Default | Notes | |---|---|---|---| | src | string | required | URL to a .jdf (plain JSON) or .jdfx (zip bundle) file. The extension determines the parser. | | width | number (px) or any CSS length | — | e.g. "800" or "100%" | | height | number (px) or any CSS length | 600px | e.g. "80vh" | | zoom | number | 1 | 1 = 100% | | fit | "manual" · "fit-width" · "fit-page" | "manual" | Auto-zoom mode | | sidebar | boolean | false | Show page-thumbnail sidebar | | toolbar | boolean | true | Show toolbar (zoom, page nav) | | dark-mode | "auto" · "light" · "dark" | "auto" | Follows OS by default | | page | integer (0-based) | 0 | Initial page | | manual | boolean | — | Skip auto-init for this element |

Programmatic API

For full control, install via npm and call the JS API directly:

import { embed, render, JDFViewer, jdf } from "@uurtech/jdf";
import "@uurtech/jdf/style.css";

// 1. Embed by URL into any container
const v = await embed("#viewer", "/doc.jdf", {
  zoom: 1.2,
  sidebar: true,
  width: "100%",
  height: "80vh",
  fit: "fit-width",
  onPageChange: (i) => console.log("on page", i),
  onLoad: (doc) => console.log("loaded", doc.meta.title),
});
v.goToPage(2);
v.setZoom(1.5);
v.destroy();

// 2. Render an in-memory document (no fetch)
import type { JdfDocument } from "@uurtech/jdf";
const doc: JdfDocument = {
  $jdf: "1.0.0",
  meta: { title: "Generated", pageSize: "A4" },
  pages: [{
    elements: [
      { type: "text", content: "Hello", heading: 1, position: { x: 0, y: 5 }, width: 166 }
    ],
  }],
};
render("#out", doc);

// 3. Class form for advanced wiring
const el = document.getElementById("v")!;
const v3 = new JDFViewer(el, doc, { darkMode: "dark" });
v3.setDocument(otherDoc); // hot-swap

SPAs / async content

Auto-init runs on DOMContentLoaded and watches the DOM with a MutationObserver, so <jdf> tags added later are picked up automatically. To trigger a manual scan after a route change:

import { jdf } from "@uurtech/jdf";
jdf();                       // scan the whole document
jdf(myContainer);             // scan only inside myContainer

To opt out per element, add manual. To disable auto-init globally, set window.JDFjsAutoInit = false before loading the script.

Hosting .jdf and .jdfx files

Both formats are static — any static host works.

.jdf (plain JSON):

Content-Type: application/json
Cache-Control: public, max-age=3600
Access-Control-Allow-Origin: *

.jdfx (zip bundle, used when the document carries embedded images / fonts):

Content-Type: application/jdf+zip
Cache-Control: public, max-age=3600
Access-Control-Allow-Origin: *

The fetch needs CORS allowed if the file is on a different origin from your page. jdf.js detects the extension on src and parses the right format automatically — <jdf src="/whitepaper.jdfx"> just works.

Browser support

Chrome 88+, Firefox 87+, Safari 14+, Edge 88+.

Feature parity with the desktop reader

jdf.js renders every JDF element type the desktop Reader does:

  • text (with heading: 1-6, align, tocEntry, internal/external link)
  • richtext (per-run bold/italic/underline/strikethrough/color/fontSize/fontFamily/link)
  • image (embedded base64 or URL/path; fit: contain|cover|fill|none)
  • table (headers, alternating rows, configurable borders, column alignment, cell-level styles)
  • list (ordered / unordered, mixed nested)
  • shape (rect, circle, ellipse, line, SVG path; fill, stroke, opacity)
  • collapsible (expandable section)
  • toc (auto-generated, hierarchical, click-to-navigate)

Plus headers/footers (template strings or full element trees), custom page sizes, doc-level / per-page orientation, and internal #page-N link navigation.

License

MIT — see LICENSE.

By Ugur Kazdal (@uurtech).