@uurtech/jdf 0.2.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uurtech/jdf",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "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.",
5
5
  "license": "MIT",
6
6
  "author": "Ugur Kazdal <ugur@uurtech.com>",
package/src/jdfjs.css CHANGED
@@ -360,3 +360,6 @@ select.jdfjs-form-control {
360
360
  .jdfjs-dark .jdfjs-form-control:disabled {
361
361
  background: #1f2937;
362
362
  }
363
+
364
+ /* Unknown element type — same visible fallback as the desktop reader, never a silent drop. */
365
+ .jdfjs-unknown { font-size: 10px; color: #9ca3af; font-family: ui-monospace, Menlo, monospace; }
@@ -47,8 +47,15 @@ export function renderElement(el: Element, ctx: RenderContext): HTMLElement | nu
47
47
  case "checkbox": inner = renderFormCheckbox(el, ctx); break;
48
48
  case "select": inner = renderFormSelect(el, ctx); break;
49
49
  case "signature": inner = renderFormSignature(el, ctx); break;
50
+ default: {
51
+ // Same visible fallback as the desktop reader — an element must never vanish silently.
52
+ inner = document.createElement("div");
53
+ inner.className = "jdfjs-unknown";
54
+ inner.textContent = `[unknown: ${(el as any).type}]`;
55
+ }
50
56
  }
51
57
  if (!inner) return null;
58
+ wrap.dataset.jdfType = String((el as any).type);
52
59
  wrap.appendChild(inner);
53
60
  return wrap;
54
61
  }
@@ -96,6 +103,7 @@ function textTag(h: TextElement["heading"]): keyof HTMLElementTagNameMap {
96
103
  // ── richtext ────────────────────────────────────────────────────────────────
97
104
  function renderRichText(el: RichTextElement, ctx: RenderContext): HTMLElement {
98
105
  const p = document.createElement("p");
106
+ p.style.whiteSpace = "pre-wrap"; // keep "\n" line breaks (folded paragraphs) — same as the reader
99
107
  p.className = "jdfjs-richtext";
100
108
  p.style.margin = "0";
101
109
  applyStyle(p, resolveStyle(el.style, ctx.styles));
@@ -234,7 +242,9 @@ function renderImage(el: ImageElement, ctx: RenderContext): HTMLElement {
234
242
  wrap.style.height = "100%";
235
243
  const img = document.createElement("img");
236
244
  img.src = imageSrc(el, ctx.resources);
237
- img.alt = el.alt || "";
245
+ // A caption written by `jdf describe` doubles as accessible text and hover title, so the text RAG indexes is the text the reader sees.
246
+ img.alt = el.alt || el.caption || "";
247
+ if (el.caption) img.title = el.caption;
238
248
  img.style.display = "block";
239
249
  img.style.width = "100%";
240
250
  img.style.height = "100%";
@@ -1,3 +1,4 @@
1
+ import { unitToPx } from "@jdf/core";
1
2
  import type { Style, StyleRef } from "@jdf/core";
2
3
 
3
4
  function paddingToCss(p: NonNullable<Style["padding"]>): string {
@@ -16,6 +17,8 @@ export function styleToCss(style: Style): Record<string, string> {
16
17
  if (style.color) css["color"] = style.color;
17
18
  if (style.backgroundColor) css["background-color"] = style.backgroundColor;
18
19
  if (style.textAlign) css["text-align"] = style.textAlign;
20
+ if (style.lineHeight) css["line-height"] = String(style.lineHeight); // unitless, same as the reader
21
+ if (style.textIndent) css["text-indent"] = `${unitToPx(style.textIndent)}px`;
19
22
  if (style.textDecoration) {
20
23
  const td = style.textDecoration === "strikethrough" ? "line-through" : style.textDecoration;
21
24
  css["text-decoration"] = td;