@reportwright/viewer 0.13.0 → 0.13.1

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.
Files changed (85) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +4 -2
  3. package/THIRD-PARTY-NOTICES.md +1 -1
  4. package/dist/{chunk-DXHLIJEY.js → chunk-47ZAKRVN.js} +6 -6
  5. package/dist/{chunk-L6YEIVVD.js → chunk-B5ZCT3UK.js} +13 -13
  6. package/dist/chunk-CCH7CFU5.js +5026 -0
  7. package/dist/chunk-CCH7CFU5.js.map +6 -0
  8. package/dist/{chunk-CNDUJ7IV.js → chunk-ES2LYZ6S.js} +9 -6
  9. package/dist/chunk-ES2LYZ6S.js.map +6 -0
  10. package/dist/{chunk-BF7GCWZY.js → chunk-GOCWG6FG.js} +3 -3
  11. package/dist/{chunk-IFYCJZNS.js → chunk-GRYITZPG.js} +7 -7
  12. package/dist/{chunk-F5EPQTPF.js → chunk-H422SRD3.js} +8 -8
  13. package/dist/{chunk-FEM2QVOO.js → chunk-JD6EJ3LI.js} +4 -4
  14. package/dist/{chunk-QFLVVM3H.js → chunk-MS2LQC2O.js} +38 -28
  15. package/dist/chunk-MS2LQC2O.js.map +6 -0
  16. package/dist/{chunk-UHHURTSV.js → chunk-PF4RFKX2.js} +7 -7
  17. package/dist/{chunk-TZXEEVKE.js → chunk-PKXTMC4J.js} +87 -42
  18. package/dist/chunk-PKXTMC4J.js.map +6 -0
  19. package/dist/{chunk-UJL7C2AS.js → chunk-U2ZY2NPQ.js} +2 -2
  20. package/dist/{chunk-PQNM6ET7.js → chunk-WOBRKNIA.js} +12 -12
  21. package/dist/{chunk-YIX3OJXU.js → chunk-XXTAPZO4.js} +4 -4
  22. package/dist/{chunk-EK5CJY22.js → chunk-ZGRJJ6OW.js} +38 -23
  23. package/dist/{chunk-EK5CJY22.js.map → chunk-ZGRJJ6OW.js.map} +1 -1
  24. package/dist/designer.js +26 -19
  25. package/dist/designer.js.map +1 -1
  26. package/dist/engine.worker.bwip.js +51422 -0
  27. package/dist/engine.worker.bwip.js.map +6 -0
  28. package/dist/engine.worker.js +45327 -2482
  29. package/dist/engine.worker.js.map +3 -3
  30. package/dist/peer/{chunk-45GVDKP5.js → chunk-3EYYRJR4.js} +7 -7
  31. package/dist/peer/{chunk-VZHHNQYB.js → chunk-3XZY54LM.js} +87 -42
  32. package/dist/peer/chunk-3XZY54LM.js.map +6 -0
  33. package/dist/peer/{chunk-Z5II55QT.js → chunk-5RUNOIS7.js} +4 -4
  34. package/dist/peer/{chunk-2CD5COHN.js → chunk-7IP67PA6.js} +13 -13
  35. package/dist/peer/{chunk-LWXQX3NJ.js → chunk-A6UXBSTP.js} +8 -8
  36. package/dist/peer/{chunk-V42KN7HD.js → chunk-CFTFTV2O.js} +6 -6
  37. package/dist/peer/chunk-JQTRDHQP.js +866 -0
  38. package/dist/peer/chunk-JQTRDHQP.js.map +6 -0
  39. package/dist/peer/chunk-KD6CDYGE.js +5024 -0
  40. package/dist/peer/chunk-KD6CDYGE.js.map +6 -0
  41. package/dist/peer/chunk-MXR6JBMP.js +546 -0
  42. package/dist/peer/chunk-MXR6JBMP.js.map +6 -0
  43. package/dist/peer/chunk-N42DCZZA.js +378 -0
  44. package/dist/peer/chunk-N42DCZZA.js.map +6 -0
  45. package/dist/peer/{chunk-MKY3SDXU.js → chunk-RKFP7SDY.js} +9 -6
  46. package/dist/peer/chunk-RKFP7SDY.js.map +6 -0
  47. package/dist/peer/{chunk-3CBV5SAI.js → chunk-WABYQWMT.js} +12 -12
  48. package/dist/peer/chunk-WVQQCD4M.js +14211 -0
  49. package/dist/peer/chunk-WVQQCD4M.js.map +6 -0
  50. package/dist/peer/{chunk-S6LSPHSU.js → chunk-XHCRHVRK.js} +4 -4
  51. package/dist/peer/{chunk-YITWGAR4.js → chunk-ZS3J4WBH.js} +7 -7
  52. package/dist/peer/designer.js +26 -19
  53. package/dist/peer/designer.js.map +1 -1
  54. package/dist/peer/engine.worker.bwip.js +51422 -0
  55. package/dist/peer/engine.worker.bwip.js.map +6 -0
  56. package/dist/peer/engine.worker.js +45327 -2482
  57. package/dist/peer/engine.worker.js.map +3 -3
  58. package/dist/peer/viewer.js +6 -5
  59. package/dist/peer/viewer.js.map +1 -1
  60. package/dist/viewer.js +6 -5
  61. package/dist/viewer.js.map +1 -1
  62. package/package.json +1 -2
  63. package/dist/chunk-CNDUJ7IV.js.map +0 -6
  64. package/dist/chunk-QFLVVM3H.js.map +0 -6
  65. package/dist/chunk-TZXEEVKE.js.map +0 -6
  66. package/dist/peer/chunk-MKY3SDXU.js.map +0 -6
  67. package/dist/peer/chunk-VZHHNQYB.js.map +0 -6
  68. /package/dist/{chunk-DXHLIJEY.js.map → chunk-47ZAKRVN.js.map} +0 -0
  69. /package/dist/{chunk-L6YEIVVD.js.map → chunk-B5ZCT3UK.js.map} +0 -0
  70. /package/dist/{chunk-BF7GCWZY.js.map → chunk-GOCWG6FG.js.map} +0 -0
  71. /package/dist/{chunk-IFYCJZNS.js.map → chunk-GRYITZPG.js.map} +0 -0
  72. /package/dist/{chunk-F5EPQTPF.js.map → chunk-H422SRD3.js.map} +0 -0
  73. /package/dist/{chunk-FEM2QVOO.js.map → chunk-JD6EJ3LI.js.map} +0 -0
  74. /package/dist/{chunk-UHHURTSV.js.map → chunk-PF4RFKX2.js.map} +0 -0
  75. /package/dist/{chunk-UJL7C2AS.js.map → chunk-U2ZY2NPQ.js.map} +0 -0
  76. /package/dist/{chunk-PQNM6ET7.js.map → chunk-WOBRKNIA.js.map} +0 -0
  77. /package/dist/{chunk-YIX3OJXU.js.map → chunk-XXTAPZO4.js.map} +0 -0
  78. /package/dist/peer/{chunk-45GVDKP5.js.map → chunk-3EYYRJR4.js.map} +0 -0
  79. /package/dist/peer/{chunk-S6LSPHSU.js.map → chunk-5RUNOIS7.js.map} +0 -0
  80. /package/dist/peer/{chunk-2CD5COHN.js.map → chunk-7IP67PA6.js.map} +0 -0
  81. /package/dist/peer/{chunk-LWXQX3NJ.js.map → chunk-A6UXBSTP.js.map} +0 -0
  82. /package/dist/peer/{chunk-V42KN7HD.js.map → chunk-CFTFTV2O.js.map} +0 -0
  83. /package/dist/peer/{chunk-3CBV5SAI.js.map → chunk-WABYQWMT.js.map} +0 -0
  84. /package/dist/peer/{chunk-Z5II55QT.js.map → chunk-XHCRHVRK.js.map} +0 -0
  85. /package/dist/peer/{chunk-YITWGAR4.js.map → chunk-ZS3J4WBH.js.map} +0 -0
package/CHANGELOG.md CHANGED
@@ -2,6 +2,21 @@
2
2
 
3
3
  All `@reportwright/*` packages (formerly `@pagewrightjs/*`) share one version. The versioning policy is in [CONTRIBUTING.md](CONTRIBUTING.md#versioning-semver).
4
4
 
5
+ ## 0.13.1 — 2026-10-09
6
+
7
+ ### Fixed
8
+ - **N10: the CJK fonts are named Regular in the PDF.** `@reportwright/fonts-cjk` downloads variable TrueType fonts whose default instance is Thin; 0.13.0 cut and renamed the subset at Regular, but `exportPdf` and `exportPdfStream` built the BaseFont from the full font's PostScript name, so pdffonts showed `NotoSansJP-Thin` / `NotoSansKR-Thin`. Both now take the name from the subset they embed (`NotoSansJP-Regular`). Test: tests/engine/b11-cjk-names.test.js (the downloaded fonts are tested when present).
9
+ - **N44: a streamed tagged PDF's memory stays flat.** The writer kept where each object is in arrays of 7 bytes an object that doubled; a tagged million-row ledger has 8–11 million objects (an element per cell), most of tagging's ~125 MB at 1M rows. They are now blocks of 16,384 entries, each deflated (~2 KB) once the numbers are two blocks past; the tagger lets go of a page's elements when it ends. Same file byte for byte (but its ID): veraPDF UA-1 and A-2a pass, same `pdfinfo -struct` tree. Off-heap peak at 50k/100k/200k rows: 16.8/29.1/36.6 MB before, 6.7/7.3/9.3 MB after (RSS ~205 MB either way). Test: tests/engine/b11-n44-tagged-memory.test.js.
10
+ - **N45: `pw render` stopped by a signal leaves no temporary file.** SIGTERM (Docker, Kubernetes, CI), SIGINT (Ctrl+C) and SIGHUP remove `<file>.<pid>.part`, keep an older PDF at the path as it was, and exit 143, 130 or 129. Before, every one of them left the `.part` file. Test: tests/engine/b10-perf-cli.test.js.
11
+ - **N41: a copied worker starts.** The npm package's `engine.worker.js` bundles its libraries (bidi-js, fontkit) instead of importing them by name, so an esbuild app that copies it next to its bundle renders in the worker (it crashed with "Failed to resolve module specifier bidi-js" and fell back to the main thread). Barcodes and the standard-font metrics are files next to it (`engine.worker.bwip.js`, `engine.worker.stdfonts.js`), as in the browser build; the README says to copy `engine.worker*.js`. Test: tests/e2e/b11-esbuild-worker.mjs.
12
+ - **N40: `fonts` is optional.** `render()`, `exportPdf()`, `exportPdfStream()` and the Word, Excel and PowerPoint exports use one default store over `@reportwright/fonts` when given none, and an export loads the fonts the model uses into whatever store it gets, so render and export need not share a store (it failed with "this.loader is not a function" or 'Font "Helvetica" is not loaded'). A report in the standard PDF fonts needs no store and no fonts package (a bold title in a Helvetica report no longer loads Inter-Bold); a font that cannot load says "Install @reportwright/fonts, or pass { fontStore }". Test: tests/engine/b11-fonts-n40.test.js, and the packed packages in all four combinations (packages.test.js).
13
+ - **N19: one warning prefix.** The engine package's console warnings and deprecations start with `[reportwright]`, as the rest do (they said `[@reportwright/engine]`).
14
+ - **N43: the standard-font metrics are a table.** Helvetica, Times, Courier, Symbol and ZapfDingbats widths and font-wide metrics are generated once from the Adobe AFM data (`scripts/gen-standard-metrics.mjs` → `src/engine/text/standard-metrics.js`, 22 KB, 5 KB gzipped) instead of decompressed with pako from `@pdf-lib/standard-fonts` at every cold start; that package is no longer a dependency of `@reportwright/engine` or `@reportwright/viewer` (pdf-lib still installs it for itself), and the viewer's `engine.worker.stdfonts.js` is gone (the table is in the worker: 588 → 594 KB gzipped, about 100 KB gzipped less in all). PDFs are byte-identical. A new process making a 1-page Helvetica invoice: median of 10, 115 → 94 ms on an M2 (Node 20). Test: tests/engine/b11-fonts-n43.test.js.
15
+ - **N42: the designer Outline passes axe.** It was a `listbox` whose rows also hold their move buttons (a listbox may hold only options: aria-required-children, critical). The rows are now toggle buttons (`aria-pressed`) in a labelled group, with the same keyboard: one Tab stop, Up/Down/Home/End, Enter or Space selects.
16
+ - **N44: a large sort's memory stays flat.** The disk spill behind grouped and sorted streamed reports held a 1,000-row batch from every sorted run while merging (50 runs at 1,000,000 rows), so its memory grew with the rows. Runs are now about 8 MB (at most 10,000 rows), batches 200 rows, and the merge holds about 4 MB: past that many runs, groups of runs are merged on disk first. A 200,000-row grouped ledger: 280 → 232 MB peak; the same with 50 runs (the run count of 1,000,000 rows): 296 → 240 MB. `spillSorter({ runMB, mergeMB })` sets them. The engine README recommends `presorted: true` with ORDER BY at the source for big grouped reports. Test: tests/engine/b11-mem-spill.test.js.
17
+ - **SILENT-6: an item taller than the page warns in `validate()`.** A body item taller than the room the page has for the body (the page less its margins, page header and footer, a body section's own page and bands counted) warns with both heights and what the render does: its lower part is cut at the page bottom (a text box's text of more than one line continues on the next page). Tables, matrices, lists and subreports, which split by their rows, and pageless pages are quiet. `render()` keeps its own warning where it cuts (with the page number) and does not repeat validate's. Test: tests/engine/b11-mem-silent6-tall.test.js.
18
+ - **N37: repeated copies cascade.** Ctrl+D (Duplicate) and Paste put a copy 12 pt right and down, and 12 more while an item already sits there, so copying the same item again and again fans the copies out instead of stacking them on the first copy. A pasted coordinate that is not a finite number starts at 0, and the steps are bounded, so a paste of hostile JSON (`1e309`, 2^60) cannot hang the tab. Test: tests/engine/b11-mem-designer-cascade.test.js.
19
+
5
20
  ## 0.13.0 — 2026-10-09
6
21
 
7
22
  A minor release: new options (`largeReportRows`, `signal`, `warnOnLeave`, `onDirtyChange`), the 14 standard PDF fonts, streamed Excel and Word exports, and warnings where mistakes used to be silent. The tester's 0.12.1 tickets are fixed except where noted; fonts are still TTF (WOFF2 is not done).
package/README.md CHANGED
@@ -11,8 +11,10 @@ The viewer renders in a Web Worker (`engine.worker.js`, one self-contained file
11
11
 
12
12
  - **Vite 7**: set `worker: { format: 'es' }` in `vite.config.js`. Without it the build fails with
13
13
  `Invalid value "iife" for option "worker.format"`.
14
- - **esbuild** (plain bundling) does not follow `new Worker(new URL(...))`: copy `node_modules/@reportwright/viewer/dist/engine.worker.js`
15
- next to your bundle (it is one file; its only imports are the package's own dependencies).
14
+ - **esbuild** (plain bundling) does not follow `new Worker(new URL(...))`: copy the worker files next to your bundle:
15
+ `cp node_modules/@reportwright/viewer/dist/engine.worker*.js dist/`. `engine.worker.js` has no imports (its libraries are
16
+ inside it); `engine.worker.bwip.js` (barcodes) loads only when a report
17
+ needs it. Without it those reports render on the main thread, with the warning below.
16
18
 
17
19
  If the worker cannot load, the viewer still renders, on the main thread (slow and janky at 100k rows), and logs once
18
20
  `[reportwright] worker did not load (<reason>); rendering on the main thread`. `handle.usesWorker` tells you which one you got.
@@ -9,7 +9,7 @@ ReportWright is MIT licensed (see LICENSE). It ships or bundles the following th
9
9
  | [HarfBuzz](https://github.com/harfbuzz/harfbuzz), compiled to WebAssembly by [harfbuzzjs](https://github.com/harfbuzz/harfbuzzjs) | harfbuzzjs 1.6.2 | HarfBuzz: "Old MIT" (below); harfbuzzjs: MIT, Copyright (c) 2019-2026 The harfbuzzjs project authors | text shaping (`harfbuzz.wasm`) and font subsetting (`harfbuzz-subset.wasm`) |
10
10
  | [pdf-lib](https://github.com/Hopding/pdf-lib) | 1.17.1 | MIT, Copyright (c) 2019 Andrew Dillon | the classic PDF writer (encryption, `prepare`, `save`) |
11
11
  | [@pdf-lib/fontkit](https://github.com/Hopding/fontkit) | 1.1.1 | MIT | reading font files |
12
- | [@pdf-lib/standard-fonts](https://github.com/Hopding/standard-fonts) | 1.0.0 | MIT; the metrics are Adobe's AFM files for the 14 standard PDF fonts | Helvetica, Times and Courier widths |
12
+ | [@pdf-lib/standard-fonts](https://github.com/Hopding/standard-fonts) | 1.0.0 | MIT; the metrics are Adobe's AFM files for the 14 standard PDF fonts | Helvetica, Times and Courier widths: generated from its AFM data into src/engine/text/standard-metrics.js (scripts/gen-standard-metrics.mjs); the package itself is not a runtime dependency |
13
13
  | [bwip-js](https://github.com/metafloor/bwip-js) | 4.11.4 | MIT | barcodes |
14
14
  | [fflate](https://github.com/101arrowz/fflate) | 0.8.3 | MIT | zip and deflate (Excel, Word, PowerPoint, PDF streams) |
15
15
  | [bidi-js](https://github.com/lojjic/bidi-js) | 1.0.3 | MIT | right-to-left text |
@@ -1,13 +1,13 @@
1
- import {
2
- formatValue,
3
- isoDate,
4
- roundHalfAway
5
- } from "./chunk-GJS242RR.js";
6
1
  import {
7
2
  mergedRegions,
8
3
  needsTableData,
9
4
  textRows
10
5
  } from "./chunk-F6RMRXIN.js";
6
+ import {
7
+ formatValue,
8
+ isoDate,
9
+ roundHalfAway
10
+ } from "./chunk-GJS242RR.js";
11
11
  import "./chunk-OLLMACWA.js";
12
12
 
13
13
  // src/exporters/csv.js
@@ -95,4 +95,4 @@ export {
95
95
  exportCsv,
96
96
  writeCsvStream
97
97
  };
98
- //# sourceMappingURL=chunk-DXHLIJEY.js.map
98
+ //# sourceMappingURL=chunk-47ZAKRVN.js.map
@@ -22,13 +22,10 @@ import {
22
22
  serverPdfUrl,
23
23
  subsetter,
24
24
  usingWorker
25
- } from "./chunk-CNDUJ7IV.js";
25
+ } from "./chunk-ES2LYZ6S.js";
26
26
  import {
27
27
  NO_CJK_FONTS
28
28
  } from "./chunk-BR5K6SBL.js";
29
- import {
30
- safeUrl
31
- } from "./chunk-72S6DETS.js";
32
29
  import {
33
30
  needsExportData
34
31
  } from "./chunk-F6RMRXIN.js";
@@ -36,10 +33,13 @@ import {
36
33
  fontKeysOf,
37
34
  linkTitle,
38
35
  pageToSvg
39
- } from "./chunk-UJL7C2AS.js";
36
+ } from "./chunk-U2ZY2NPQ.js";
37
+ import {
38
+ safeUrl
39
+ } from "./chunk-72S6DETS.js";
40
40
  import {
41
41
  CORE_FONT_KEY
42
- } from "./chunk-QFLVVM3H.js";
42
+ } from "./chunk-MS2LQC2O.js";
43
43
  import {
44
44
  __commonJS,
45
45
  __toESM
@@ -19475,10 +19475,10 @@ async function exportBlob(fmt, model, def, opt = {}) {
19475
19475
  const o = { ...EXPORT_DEFAULTS, ...opt.options || {} };
19476
19476
  const lang = def.locale || opt.lang || "en";
19477
19477
  if (fmt === "json") return new Blob([JSON.stringify(model)], { type: "application/json" });
19478
- if (fmt === "csv") return new Blob([(await import("./chunk-DXHLIJEY.js")).exportCsv(model, { locale: def.locale, currency: def.currency })], { type: "text/csv;charset=utf-8" });
19478
+ if (fmt === "csv") return new Blob([(await import("./chunk-47ZAKRVN.js")).exportCsv(model, { locale: def.locale, currency: def.currency })], { type: "text/csv;charset=utf-8" });
19479
19479
  if (fmt === "html" && opt.interactive !== false && o.html === "interactive") {
19480
19480
  try {
19481
- const { exportInteractiveHtml } = await import("./chunk-UHHURTSV.js");
19481
+ const { exportInteractiveHtml } = await import("./chunk-PF4RFKX2.js");
19482
19482
  const { html } = await exportInteractiveHtml(def, { params: opt.params, reportId: opt.reportId, lang: opt.lang, model });
19483
19483
  return new Blob([html], { type: "text/html;charset=utf-8" });
19484
19484
  } catch (e) {
@@ -19488,19 +19488,19 @@ async function exportBlob(fmt, model, def, opt = {}) {
19488
19488
  }
19489
19489
  if (fmt === "html") {
19490
19490
  const store = await loadedFonts(model);
19491
- const { exportHtml } = await import("./chunk-PQNM6ET7.js");
19491
+ const { exportHtml } = await import("./chunk-WOBRKNIA.js");
19492
19492
  return new Blob([await exportHtml(model, { fonts: store, title: def.name, subset: subsetter, drillBase: origin(), static: o.html === "static", locale: def.locale, currency: def.currency, lang: opt.lang, strings: opt.strings })], { type: "text/html;charset=utf-8" });
19493
19493
  }
19494
19494
  if (fmt === "docx") {
19495
- const { exportDocx } = await import("./chunk-FEM2QVOO.js");
19495
+ const { exportDocx } = await import("./chunk-JD6EJ3LI.js");
19496
19496
  return new Blob([await exportDocx(model, { title: def.name, lang, fontStore: await loadedFonts(model), fetchImage })], { type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document" });
19497
19497
  }
19498
19498
  if (fmt === "pptx") {
19499
- const { exportPptx } = await import("./chunk-IFYCJZNS.js");
19499
+ const { exportPptx } = await import("./chunk-GRYITZPG.js");
19500
19500
  return new Blob([await exportPptx(model, { title: def.name, lang, fontStore: await loadedFonts(model), fetchImage })], { type: "application/vnd.openxmlformats-officedocument.presentationml.presentation" });
19501
19501
  }
19502
19502
  if (fmt === "xlsx") {
19503
- const { exportXlsx } = await import("./chunk-F5EPQTPF.js");
19503
+ const { exportXlsx } = await import("./chunk-H422SRD3.js");
19504
19504
  const bytes = await exportXlsx(model, { currency: def.currency, title: def.name, formulas: o.formulas, fontStore: await loadedFonts(model), fetchImage });
19505
19505
  return new Blob([bytes], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
19506
19506
  }
@@ -20708,4 +20708,4 @@ export {
20708
20708
  ReportViewer,
20709
20709
  uiFontCss
20710
20710
  };
20711
- //# sourceMappingURL=chunk-L6YEIVVD.js.map
20711
+ //# sourceMappingURL=chunk-B5ZCT3UK.js.map