@reportwright/fonts-cjk 0.14.0-rc.1 → 0.14.0-rc.4

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 (2) hide show
  1. package/CHANGELOG.md +44 -1
  2. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -2,10 +2,53 @@
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.14.0-rc.4 — 2026-10-11 (release candidate)
6
+
7
+ ### Summary
8
+ - **Phase B: every report is written by `@reportwright/pdf`.** All 85 gate reports (every repository report, plain and tagged) go through the library; none takes pdf-lib's path. pdf-lib is no longer a runtime dependency of `@reportwright/engine`, `@reportwright/cli` or `@reportwright/viewer`: it is loaded lazily, from the caller's own install (`npm i pdf-lib@1.17.1`), only for `pdfWriter: 'legacy'` and the deprecated `prepare`/`save` (a 501 names the install otherwise). Measured: 500 one-page invoices merge in 1.5 s / 274 MB RSS into 0.44 MB (was 3.9 s / 784 MB / 193 MB); a 600×300 alpha logo exports cold in ~100 ms (was ~270 ms) into 187 KB (was 606 KB); a warm re-export of the same PNG is ~13 ms slower than pdf-lib's cached path.
9
+ - **Tiered writer parity gate** (`node scripts/writer-parity.mjs --baseline pdflib --corpus scripts/parity-corpus.mjs`, `scripts/parity-tiers.mjs`, `scripts/parity-tolerance.json`): tier 1 exact (words and boxes to 0.01 pt, structure tree, canonical drawing commands), tier 2 150 dpi greyscale tolerance, tier 3 600 dpi colour tie-breaker, with a pinned rasteriser. Building it found real bugs: a FAIL in the middle of a row was not counted (it hid veraPDF failures), a failed render counted as "not rendered", and three tagged repository reports failed veraPDF (missing ToUnicode) — all fixed. Tagged streamed pages now carry pdf-lib's exact structure (each item its own marked content; ledger-500 tagged 75 → 88 KB).
10
+ - **Silent wrong reports now fail or warn.** A half-written filter (no expression, op or value, an unknown op) is a validation error; a sort by a bare field name sorts by that field with a did-you-mean warning, and a constant sort or a group on a bare name warns; a near-miss parameter reference is a validation error with a did-you-mean (parameter names match in any case, as the render does); a misspelt style property warns. **Parameter strictness (`strictParameters`):** a value for an undeclared parameter, or not of its type or options, warns in `render()`, is a 400 on `/api/v1/render` and an error in `pw render`. **Grouping case:** comparisons stay case-insensitive by default (as SSRS); a data set's `caseSensitive` holds in the regions over it, RDL's `CaseSensitivity` True imports as `caseSensitive: true`, and the engine README and FEATURES document both. Valid reports' PDFs are byte-identical.
11
+ - **rc.3 CI fixes and the real bugs they found.** CI builds the npm packages before the browser suites and fetches the optional CJK and emoji fonts. Real bugs fixed: the home page offered New report by edit rights on the top folder instead of `canCreateIn` (as the API); the interactive HTML export did not escape `<!--` and `<script` in the inlined viewer bundle; Turbopack left pdf-lib's bindings undefined, so the viewer's accessible and PDF/A exports failed; the designer's browser data requests ignored `PW_INTERNAL_HOSTS`; a SQL query gave up on a pooled connection before its deadline; MySQL storage id-prefix lookups used an invalid `ESCAPE`; pages asked for optional CJK and emoji fonts the server did not have. The e2e suites were brought up to the secure defaults (permissions, users, replicas, sso, tablix, designer-gaps).
12
+ - **Font subsets:** the smaller subsets of `@reportwright/pdf`'s own subsetter do not change engine PDFs in this release; the engine's subsets (HarfBuzz, glyph IDs kept) are unchanged and as large as in rc.3. Renumbering them on the engine side is a follow-up.
13
+ - The render worker bundles the report schema without its prose (510.6 → 507.2 KB gzipped, `validate()` unchanged).
14
+
15
+ ### Test fixes
16
+ - **The "truncated 20,000-row streamed PDF" CI flake was the tests, not the engine.** The tests' `pdftotext` helpers (4 test files) used Node's default 1 MiB `spawnSync` buffer, which cut a 438-page text at page 285 without an error. They now read the whole output (`maxBuffer` 1 GiB) and fail on an error, and the streamed-PDF test checks every page's footer up to the last.
17
+ - The lazy-load test expects the engine bundle to import pdf-lib by its non-literal specifier (B4 made it an optional install); the examples name 0.14.0-rc.4.
18
+
19
+ ### Changed
20
+ - **`@reportwright/pdf` 0.1.0-beta.11** (was beta.9), now on npm and in `package-lock.json`; pdf-lib and `@signpdf/placeholder-pdf-lib` are devDependencies.
21
+ - **`exportPdf` of reports whose pages differ in size, or whose page numbering restarts (`newSection`), no longer loads pdf-lib.** The paged writer writes each page's own height into the outline's places and the links' jumps, and the page labels from the sections. Gate: `node scripts/writer-parity.mjs --baseline pdflib --corpus scripts/parity-corpus.mjs` (pixel-identical, same labels, outline and text).
22
+ - **A batch's merged PDF is made by `@reportwright/pdf`** (`loadPdf` + `mergePdfs`; was pdf-lib's `copyPages`). The pages are pixel- and text-identical; the items' outlines and form fields now come along (pdf-lib dropped the AcroForm, so merged fields were dead; fields keep their names, so the same field in two items is one name twice). Shared fonts and images are written once: 500 one-page invoices merge in 1.5 s and 274 MB RSS into 0.44 MB, against 3.9 s, 784 MB and 193 MB.
23
+ - **`exportPdf` of reports with PNG and JPEG pictures (data URIs) no longer loads pdf-lib.** Pictures are embedded by `@reportwright/pdf` (`embedImage` + `core.imageResource`) behind the engine's own checks (size limits, `pngProblem`, PNG and JPEG only; `IMAGE_LIMITS.pixels` at 8-bit RGBA as `maxDecodedBytes`), with the same warnings when one is left out. 8- and 16-bit, alpha and JPEG pictures are pixel-identical. **A JPEG with an EXIF orientation is now drawn upright** (pdf-lib ignored it). Smaller files (a 600×300 alpha logo: 606 KB → 187 KB) and faster cold exports (~270 → ~100 ms); a warm re-export of the same alpha PNG is ~13 ms slower than pdf-lib's path with its per-process PNG cache (which stays, on that path). SVG and URL pictures stay on pdf-lib for now.
24
+ - **Rounded boxes, SVG path items (charts' lines, areas, pies) and SVG pictures no longer need pdf-lib.** `src/exporters/svgpath.js` is a faithful port of pdf-lib 1.17.1's SVG path code (arcs to Béziers included) that writes the very operators pdf-lib wrote (tested operator for operator), so these pages are pixel-identical; `svgimage.js` has `svgOps`, the operator-text twin of `drawSvg`. Only URL pictures, form fields, PDF/A, tagged, encrypted and signed files stay on pdf-lib's whole-model path now.
25
+ - **`exportPdf` with `pdfa: { icc }` (PDF/A-2b, not tagged) goes through `@reportwright/pdf`**, written as `exportPdfStream` writes PDF/A (XMP, output intent, standard fonts in their embedded stand-ins): pixel-identical to pdf-lib's file, veraPDF 2b passes (alpha pictures included). Tagged (PDF/UA, PDF/A-2a) files and PDF/A without a profile stay on pdf-lib.
26
+ - **Encrypted PDFs (`encrypt`) are written by `@reportwright/pdf`** (AES-256, R6, metadata encrypted), not pdf-lib plus `encrypt.js`: the same `/P` for every permission set (`PERMISSION_BITS` → the library's `permissions`), the same 400s (unknown permission, a password over 127 bytes, PDF/A), pixel-identical after decryption, and no title, URI or text readable in the raw file. Passwords are prepared with SASLprep (the PDF 2.0 rule) instead of NFKC alone; they differ only for passwords with unusual Unicode spaces or ignorable characters. Encrypted files with form fields, tagged or signed stay on pdf-lib for now; `exportPdfStream` still renders encrypted reports whole.
27
+ - **Form fields (text, multiline, check box, drop-down) are made by `@reportwright/pdf`** with appearances drawn exactly as pdf-lib's default providers drew them (`src/exporters/pdffields.js`: the 0.75 pt border, white fill, 1 pt padding, check mark, text placement; shaped values such as Arabic and Devanagari keep the engine's glyphs). Pages are pixel-identical at 72, 150 and 300 dpi; the fields keep their names, values, required and read-only flags, and fill in pdf-lib, pypdf and PyMuPDF (the field font is in the form's /DR now, so pypdf no longer falls back to Helvetica). Field fonts are embedded whole, as before.
28
+ - **Signing goes through `@reportwright/pdf`.** `exportPdf` takes `sign: { signer, reason, location, contactInfo, name }` (a `cmsSigner`/`nodeSigner` signer; the server builds one from `PW_SIGN_P12` with `p12Signer` in `src/server/sign.js`) and signs as the file is written: an invisible field, `adbe.pkcs7.detached` over the whole file, as `@signpdf` signed. A report that still takes pdf-lib's path (tagged) is signed by the library in an incremental update. pdfsig: valid, whole document signed; PDF/A signed files pass veraPDF 2b. The server passes `sign` instead of `prepare`/`save`. **Deprecated:** `prepare` and `save` keep working with a one-time `DeprecationWarning` and go in 0.15. `sign` with `encrypt` or with `prepare` is a 400.
29
+ - **Jumps to a bookmark by name and URL pictures no longer need pdf-lib.** A name resolves to the first bookmark of that name (a missing one makes no link), as before; a URL picture is fetched with `fetchImage` and checked as data URIs are. Every repository report now goes through `@reportwright/pdf`. One text difference: the stress test's Zalgo line extracts its combining marks as themselves; pdf-lib's file extracted them as "贷" (a wrong ToUnicode entry). Pixels identical.
30
+ - **Signing setup is checked and cached.** The `.p12` is opened (its PKCS#12 decrypted) once per process and again only when the file, its size or `PW_SIGN_PASSWORD` changes; the deprecated `@signpdf` signer is made only when its `sign()` is used. A certificate that is expired or not yet valid is refused when it is loaded (a 500 naming `PW_SIGN_P12`).
31
+
32
+ ## 0.14.0-rc.3 — 2026-10-10 (release candidate)
33
+
34
+ ### Fixed (from the rc.2 tester gate)
35
+ - **A cut or damaged font subset no longer reaches the PDF.** `exportPdf` on pdf-lib (images, `pdfWriter: 'legacy'`…) checked a subset only by reading it with fontkit, which reads past a short buffer without complaint, so a truncated subset was embedded as is; the streamed writer's check missed a cut within its 16 bytes of padding. Every path (`exportPdf` on pdf-lib and on `@reportwright/pdf`, `exportPdfStream`, TrueType and CFF fonts) now checks the subset's bytes first: the table directory and every table inside the file, each glyph's `loca` range in order and inside `glyf`, a CFF table's header and Name/Top DICT INDEXes in bounds. A subset that fails, or that cannot be made, embeds the full font with a warning ("The font … is embedded whole: its subset could not be used (…)", `onWarning` / the result's `warnings`). Normal reports are byte-identical.
36
+ - **`import '@reportwright/fonts'` works.** The package had only subpath exports; its root now exports `fontsUrl`, `subsetWasmUrl` and `iccUrl` (with types). `@reportwright/fonts/public/*` is unchanged.
37
+
38
+ ## 0.14.0-rc.2 — 2026-10-10 (release candidate)
39
+
40
+ ### Fixed (from the rc.1 release gate)
41
+ - **Memory of a zebra table in `exportPdfStream`.** A detail row whose style reads `RowNumber()` (`backgroundColor: '=IIf(RowNumber() Mod 2 = 0, "#f3f4f6", "#ffffff")'`) was refused by the streaming planner ("detail expressions", in `r.why`) and rendered whole, so every page stayed in memory: ~3.5–8 KB a row, 558 MB–1 GB at 100,000 rows. It now streams (row styles may read `RowNumber()`, as row values could), and its pages are the whole render's (pixels, text). Peak RSS at 100,000 rows, probe `scripts/eng-probe.mjs`: plain 270 MB, zebra 1,056 → 287 MB, zebra with expression borders and formats 1,261 → 300 MB.
42
+ - **Expression styles that give the same values share one style.** Each row's evaluated style was a new object, and the cell styles built on it a new cache entry per row (garbage V8 collected late: about 2× the peak RSS of a plain table and 2.5× its time). Rows whose expressions give the same plain values now share one frozen style (at most 64 per style), so a zebra table renders at about the plain table's speed (100,000 rows: 5.8 s → 2.1 s; plain 1.6 s). Reports without expression styles are byte-identical; the zebra reports' bytes change only because they now stream (same pages, pixels and text).
43
+ - The zebra PDF stays larger than the plain one (100,000 rows: 7.4 MB against 3.5 MB): each cell's fill is drawn as a rectangle with its colour (`rg … re f`), as the whole render always drew it; there is no resource per row.
44
+
45
+ ### Docs
46
+ - The engine README says when a streamed PDF's memory stays flat, and what "Page N of M" costs (a counting pass: about 1.5–1.8× the time, +10–60 MB at 50,000 rows).
47
+
5
48
  ## 0.14.0-rc.1 — 2026-10-10 (release candidate)
6
49
 
7
50
  ### Changed
8
- - **PDFs are written by `@reportwright/pdf`** (pinned `0.1.0-beta.5`, no dependencies of its own), the streaming PDF writer extracted from the engine. `exportPdfStream` (plain, PDF/A, PDF/UA-tagged, `parallel` workers) and `exportPdf` for reports of text (any font, shaped scripts), boxes, ellipses, lines and links go through it. Images, SVG paths, rounded boxes, form fields, encryption, signing (`prepare`), `save` options, and whole-model PDF/A and tagged files stay on pdf-lib for now.
51
+ - **PDFs are written by `@reportwright/pdf`** (pinned `0.1.0-beta.9`, no dependencies of its own), the streaming PDF writer extracted from the engine. `exportPdfStream` (plain, PDF/A, PDF/UA-tagged, `parallel` workers) and `exportPdf` for reports of text (any font, shaped scripts), boxes, ellipses, lines and links go through it. Images, SVG paths, rounded boxes, form fields, encryption, signing (`prepare`), `save` options, and whole-model PDF/A and tagged files stay on pdf-lib for now.
9
52
  - **The bytes change; the content does not.** `scripts/writer-parity.mjs` exports every report of the gate corpus (the repository's reports, the streaming ledgers, the 54-report tester corpus) with both writers and requires pixel-identical pages (pdftoppm, 72 dpi, zero differing pixels), the same text per page, `qpdf --check` and veraPDF (PDF/A-2b, 2a, PDF/UA-1) passing, the same fonts (embedded, subset), links, outline, structure elements, form fields, attachments, metadata and page labels, and the same bytes on two runs. One accepted difference: right-to-left locale formats (ar-SA, he-IL) no longer carry their invisible bidi marks (U+200F…) in the extracted text, so a viewer copies "Page 1 of 1" instead of "1 of 1 Page"; the words and pixels are the same.
10
53
  - **`exportPdf` of a plain report no longer loads pdf-lib.** A report in embedded fonts (Inter, Noto) exports about twice as fast (one 300-row grouped table: ~110 ms → ~50 ms cold) and with 5–10 MB less memory; its file is about 5% larger (the font subset keeps glyph IDs, as the streaming writer always did).
11
54
  - The file ID of a streamed PDF without `id` is now a hash of its content (it was random): the same report and `creationDate` give the same bytes.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reportwright/fonts-cjk",
3
- "version": "0.14.0-rc.1",
3
+ "version": "0.14.0-rc.4",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },