npm.io
0.1.21 • Published 5d ago

@uurtech/jdf

Licence
MIT
Version
0.1.21
Deps
1
Size
2.2 MB
Vulns
0
Weekly
559

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/jdf@0.1.11/dist/jdfjs.css">
<script type="module" src="https://unpkg.com/@uurtech/jdf@0.1.11"></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/jdf@0.1.11"></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).

Keywords