@reportwright/engine 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.
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
@@ -170,11 +170,16 @@ and stays in memory for the export: the export's own memory stays flat beside it
170
170
  many.
171
171
 
172
172
  - **Sorts and groups.** A table sort or groups put the rows in order first. In Node the sort spills to the system temp
173
- folder (`spill: { dir, maxMB }`; 2 GB at most), so memory stays flat; `spill: false`, and in a
174
- browser, it is in memory (all the rows: measured about 1.3 KB a row, so keep browser exports under about 100,000 sorted or
175
- grouped rows). When the source already gives the rows in the report's order (`order by region, type` for groups by
176
- region then type), pass `presorted: true`: nothing is sorted or held, each row is checked against the one before as it
177
- passes, and a row out of order stops the export with an error.
173
+ folder (`spill: { dir, maxMB, runMB, mergeMB }`; 2 GB of disk at most; `runMB` (default 8) and `mergeMB` (default 4) set the memory), so memory stays flat: the sort holds about 8 MB of rows while reading
174
+ and 4 MB while merging, whatever the row count (past that many sorted runs, groups of them are merged on disk first).
175
+ `spill: false`, and in a browser, it is in memory (all the rows: measured about 1.3 KB a row, so keep browser exports
176
+ under about 100,000 sorted or grouped rows).
177
+ - **Big grouped reports: sort at the source.** When the source already gives the rows in the report's order (`ORDER BY
178
+ region, type` for groups by region then type), pass `presorted: true`: nothing is sorted or held, each row is checked
179
+ against the one before as it passes, and a row out of order stops the export with an error. It is the cheapest way to
180
+ a large grouped report: a tester's 1,000,000-row grouped ledger (0.13.0, Node 22, 2 vCPU Linux) peaked at 293 MB
181
+ presorted and 386 MB sorted by the engine; the engine's sort holds less since 0.13.1, but it still reads and writes
182
+ every row to disk once more.
178
183
  - **parallel: N** (Node, off by default) lays out and paints with N worker threads; the file is byte for byte the same.
179
184
  Each thread loads the engine and fonts and lays out its own windows: about 150–300 MB a thread (measured: 260 MB
180
185
  serial, 590 MB with 2, 890 MB with 4, for 100,000 rows). It helps only with idle cores and a report whose layout, not
@@ -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 |