@reportwright/viewer 0.11.0 → 0.12.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 (83) hide show
  1. package/CHANGELOG.md +81 -0
  2. package/README.md +27 -5
  3. package/dist/{chunk-KJTRZJHN.js → chunk-2BPBQMH2.js} +4 -3
  4. package/dist/chunk-2BPBQMH2.js.map +6 -0
  5. package/dist/{chunk-ODREGGKA.js → chunk-3D2KFKG2.js} +5 -4
  6. package/dist/chunk-3D2KFKG2.js.map +6 -0
  7. package/dist/chunk-6TPZ7G74.js +494 -0
  8. package/dist/chunk-6TPZ7G74.js.map +6 -0
  9. package/dist/chunk-BRB34AJ2.js +16 -0
  10. package/dist/{chunk-APRPSQOD.js → chunk-DPVJEFKP.js} +28 -9
  11. package/dist/chunk-DPVJEFKP.js.map +6 -0
  12. package/dist/{chunk-RYHJUQSV.js → chunk-DXHLIJEY.js} +2 -2
  13. package/dist/{chunk-SR2TQ2ZK.js → chunk-F6RMRXIN.js} +2 -2
  14. package/dist/chunk-F6RMRXIN.js.map +6 -0
  15. package/dist/{chunk-3D43XGIN.js → chunk-M6AYND5G.js} +8 -638
  16. package/dist/chunk-M6AYND5G.js.map +6 -0
  17. package/dist/{chunk-HAMBWF6C.js → chunk-NR2G4TMG.js} +39 -31
  18. package/dist/chunk-NR2G4TMG.js.map +6 -0
  19. package/dist/{chunk-66QZ3RDV.js → chunk-PGP3QA6L.js} +526 -508
  20. package/dist/chunk-PGP3QA6L.js.map +6 -0
  21. package/dist/{chunk-N5WHQ4DM.js → chunk-Q6MMPKQA.js} +14 -9
  22. package/dist/chunk-Q6MMPKQA.js.map +6 -0
  23. package/dist/{chunk-SBD55ZES.js → chunk-S2IUUI6N.js} +76 -32
  24. package/dist/chunk-S2IUUI6N.js.map +6 -0
  25. package/dist/chunk-ULKEEARQ.js +553 -0
  26. package/dist/chunk-ULKEEARQ.js.map +6 -0
  27. package/dist/{chunk-WQOBRZAL.js → chunk-VNOWPSE6.js} +579 -1484
  28. package/dist/chunk-VNOWPSE6.js.map +6 -0
  29. package/dist/chunk-Z7MKH66Z.js +642 -0
  30. package/dist/chunk-Z7MKH66Z.js.map +6 -0
  31. package/dist/designer.d.ts +10 -3
  32. package/dist/designer.js +28 -18
  33. package/dist/designer.js.map +1 -1
  34. package/dist/engine.worker.js +71 -0
  35. package/dist/engine.worker.js.map +6 -0
  36. package/dist/peer/chunk-2FZTYEDE.js +15 -0
  37. package/dist/peer/{chunk-776OR56A.js → chunk-6I2EAAVN.js} +39 -31
  38. package/dist/peer/chunk-6I2EAAVN.js.map +6 -0
  39. package/dist/peer/{chunk-IPU2YRL2.js → chunk-BMAXIBP2.js} +28 -9
  40. package/dist/peer/chunk-BMAXIBP2.js.map +6 -0
  41. package/dist/peer/chunk-BQFI3DHK.js +494 -0
  42. package/dist/peer/chunk-BQFI3DHK.js.map +6 -0
  43. package/dist/peer/{chunk-76ZABVTI.js → chunk-R4VX5UC7.js} +4 -3
  44. package/dist/peer/{chunk-5X4ZSSJT.js → chunk-TSC4RAH3.js} +526 -508
  45. package/dist/peer/chunk-TSC4RAH3.js.map +6 -0
  46. package/dist/peer/{chunk-M4AGFUWE.js → chunk-V42KN7HD.js} +2 -2
  47. package/dist/peer/{chunk-Y5CAHLXS.js → chunk-WQGENQZO.js} +5 -4
  48. package/dist/peer/{chunk-EKWTFHVE.js → chunk-WSNRD2AQ.js} +14 -9
  49. package/dist/peer/chunk-WSNRD2AQ.js.map +6 -0
  50. package/dist/peer/designer.js +28 -18
  51. package/dist/peer/designer.js.map +1 -1
  52. package/dist/peer/engine.worker.js +70 -0
  53. package/dist/peer/engine.worker.js.map +6 -0
  54. package/dist/peer/viewer.js +12 -5
  55. package/dist/peer/viewer.js.map +1 -1
  56. package/dist/viewer.d.ts +9 -1
  57. package/dist/viewer.js +12 -5
  58. package/dist/viewer.js.map +1 -1
  59. package/package.json +1 -1
  60. package/dist/chunk-3D43XGIN.js.map +0 -6
  61. package/dist/chunk-66QZ3RDV.js.map +0 -6
  62. package/dist/chunk-AH47FS6Y.js +0 -13
  63. package/dist/chunk-APRPSQOD.js.map +0 -6
  64. package/dist/chunk-HAMBWF6C.js.map +0 -6
  65. package/dist/chunk-N5WHQ4DM.js.map +0 -6
  66. package/dist/chunk-SBD55ZES.js.map +0 -6
  67. package/dist/chunk-SR2TQ2ZK.js.map +0 -6
  68. package/dist/chunk-WQOBRZAL.js.map +0 -6
  69. package/dist/peer/chunk-5X4ZSSJT.js.map +0 -6
  70. package/dist/peer/chunk-6YO42ALN.js +0 -14777
  71. package/dist/peer/chunk-6YO42ALN.js.map +0 -6
  72. package/dist/peer/chunk-76ZABVTI.js.map +0 -6
  73. package/dist/peer/chunk-776OR56A.js.map +0 -6
  74. package/dist/peer/chunk-EKWTFHVE.js.map +0 -6
  75. package/dist/peer/chunk-IMQRHDR4.js +0 -12
  76. package/dist/peer/chunk-IPU2YRL2.js.map +0 -6
  77. package/dist/peer/chunk-Y5CAHLXS.js.map +0 -6
  78. /package/dist/{chunk-AH47FS6Y.js.map → chunk-BRB34AJ2.js.map} +0 -0
  79. /package/dist/{chunk-RYHJUQSV.js.map → chunk-DXHLIJEY.js.map} +0 -0
  80. /package/dist/peer/{chunk-IMQRHDR4.js.map → chunk-2FZTYEDE.js.map} +0 -0
  81. /package/dist/{chunk-KJTRZJHN.js.map → peer/chunk-R4VX5UC7.js.map} +0 -0
  82. /package/dist/peer/{chunk-M4AGFUWE.js.map → chunk-V42KN7HD.js.map} +0 -0
  83. /package/dist/{chunk-ODREGGKA.js.map → peer/chunk-WQGENQZO.js.map} +0 -0
@@ -1,3 +1,6 @@
1
+ import {
2
+ FORMAT_CHAR
3
+ } from "./chunk-ULKEEARQ.js";
1
4
  import {
2
5
  asciiUrl,
3
6
  drillUrl,
@@ -9,25 +12,27 @@ import {
9
12
  import {
10
13
  needsTableData,
11
14
  visualLines
12
- } from "./chunk-SR2TQ2ZK.js";
15
+ } from "./chunk-F6RMRXIN.js";
13
16
  import {
14
- IMAGE_LIMITS,
15
17
  altOf,
16
18
  cellVisuals,
19
+ figures,
20
+ parseColor
21
+ } from "./chunk-M6AYND5G.js";
22
+ import {
23
+ IMAGE_LIMITS,
17
24
  dataUriBytes,
18
25
  dataUriBytesOf,
19
- figures,
20
26
  imageInfoOf,
21
- parseColor,
22
27
  svgLength,
23
28
  svgRootAttrs,
24
29
  xmlAttrs,
25
30
  xmlTags
26
- } from "./chunk-3D43XGIN.js";
31
+ } from "./chunk-Z7MKH66Z.js";
27
32
  import "./chunk-OLLMACWA.js";
28
33
 
29
34
  // src/exporters/pdf.js
30
- import { PDFDocument, PDFName as PDFName3, PDFString as PDFString4, PDFHexString as PDFHexString4, PDFRawStream as PDFRawStream2, rgb as rgb2 } from "pdf-lib";
35
+ import { PDFDocument, PDFName as PDFName3, PDFString as PDFString4, PDFHexString as PDFHexString5, PDFRawStream as PDFRawStream2, rgb as rgb3 } from "pdf-lib";
31
36
  import fontkitModule from "@pdf-lib/fontkit";
32
37
 
33
38
  // src/exporters/pdfa.js
@@ -744,11 +749,8 @@ function pngProblem(b) {
744
749
  return null;
745
750
  }
746
751
 
747
- // src/exporters/pdf.js
748
- var fontkit = (
749
- /** @type {any} */
750
- fontkitModule.default || fontkitModule
751
- );
752
+ // src/exporters/pdfpaint.js
753
+ import { PDFHexString as PDFHexString4, rgb as rgb2 } from "pdf-lib";
752
754
  var colors = /* @__PURE__ */ new Map();
753
755
  var col = (c) => {
754
756
  if (colors.has(c)) return colors.get(c);
@@ -763,181 +765,503 @@ var n4 = (v) => Math.round(v * 1e4) / 1e4;
763
765
  var hex4 = (id) => id.toString(16).padStart(4, "0");
764
766
  var KAPPA = 4 * ((Math.SQRT2 - 1) / 3);
765
767
  var cleanText = (t) => t.replace(/\t|\u0085|\u2028|\u2029/g, " ").replace(/[\b\v]/g, "");
766
- function exportPdf(model, fontStore, opt = {}) {
767
- return withDeadline(
768
- pdfOf(model, fontStore, opt),
769
- /** @type {any} */
770
- opt.timeoutMs
771
- );
772
- }
773
- async function pdfOf(model, fontStore, opt) {
774
- const fixed = fixedDate(opt);
775
- const when = fixed ?? /* @__PURE__ */ new Date();
776
- const fileId = fixed ? await contentId(model, opt, when) : void 0;
777
- const doc = await PDFDocument.create({ updateMetadata: false });
778
- doc.registerFontkit(fontkit);
779
- doc.setTitle(opt.title || "Report");
780
- doc.setProducer("ReportWright");
781
- doc.setCreator("ReportWright");
782
- if (opt.author) doc.setAuthor(opt.author);
783
- setInfoDates(doc, when);
784
- if (fileId) doc.context.trailerInfo.ID = doc.context.obj([PDFHexString4.of(fileId), PDFHexString4.of(fileId)]);
785
- const used = /* @__PURE__ */ new Map();
786
- const shaped = /* @__PURE__ */ new Map();
787
- const spans = /* @__PURE__ */ new WeakMap();
788
- const chars = (key) => {
789
- let c = used.get(key);
790
- if (!c) {
791
- c = /* @__PURE__ */ new Set([32]);
792
- used.set(key, c);
793
- }
794
- return c;
768
+ var formatAt = (run, cl) => {
769
+ const cp = run.text.codePointAt(cl);
770
+ return cp !== void 0 && FORMAT_CHAR.test(String.fromCodePoint(cp));
771
+ };
772
+ function drawRun(c, run, x, y, size, pf, color, spans, texts) {
773
+ const f = pf.embedder.font;
774
+ const per = 1e3 / size;
775
+ const span = (text) => `/Span <</ActualText ${PDFHexString4.fromText(text).toString()}>> BDC
776
+ `;
777
+ c.et();
778
+ c.paint(color, null);
779
+ c.font(pf, size);
780
+ if (!run.rtl) c.s += span(run.text);
781
+ c.s += `BT ${n2(x)} ${n2(y)} Td
782
+ `;
783
+ let arr = "";
784
+ let pen = 0, rise = 0;
785
+ const flush = () => {
786
+ if (arr) c.s += `[${arr}] TJ
787
+ `;
788
+ arr = "";
795
789
  };
796
- for (const pg of model.pages) for (const it of pg.items.flatMap((i) => i.t === "field" ? i.draw.filter((d) => d.t === "text") : i.t === "text" ? [i] : [])) {
797
- for (const l of it.lines) {
798
- if (!l.runs) {
799
- const c = chars(it.font);
800
- for (const ch of l.text) c.add(
801
- /** @type {number} */
802
- ch.codePointAt(0)
803
- );
804
- continue;
805
- }
806
- for (const r of l.runs) {
807
- const c = chars(r.font);
808
- for (const ch of r.text) c.add(
809
- /** @type {number} */
810
- ch.codePointAt(0)
811
- );
812
- let g = shaped.get(r.font);
813
- if (!g) {
814
- g = /* @__PURE__ */ new Map();
815
- shaped.set(r.font, g);
816
- }
817
- glyphText(r, fontStore.get(r.font), g, spans);
818
- }
790
+ const all = run.glyphs;
791
+ const adv = (id) => f.getGlyph(id).advanceWidth;
792
+ let g = all, quietAt = -1;
793
+ if (run.rtl) {
794
+ const hasBase = /* @__PURE__ */ new Set();
795
+ for (let i = 0; i < all.length; i += 4) if (adv(all[i]) > 0) hasBase.add(all[i + 3]);
796
+ const quiet = (i) => spans?.has(all[i + 3]) ? adv(all[i]) === 0 && hasBase.has(all[i + 3]) : texts?.get(all[i]) === "";
797
+ g = [];
798
+ for (const late of [false, true]) {
799
+ if (late) quietAt = g.length;
800
+ for (let i = 0; i < all.length; i += 4) if (quiet(i) === late) g.push(all[i], all[i + 1], all[i + 2], all[i + 3]);
819
801
  }
802
+ if (quietAt === g.length) quietAt = -1;
820
803
  }
821
- const fieldFonts = /* @__PURE__ */ new Set();
822
- for (const pg of model.pages) for (const it of pg.items) if (it.t === "field") fieldFonts.add(fieldFont(it));
823
- const fonts = /* @__PURE__ */ new Map();
824
- const font = async (key) => {
825
- if (!fonts.has(key)) {
826
- const full = fontStore.bytes.get(key);
827
- let bytes = full;
828
- if (!bytes) throw new Error(`Font "${key}" is not loaded`);
829
- const glyphs = shaped.get(key);
830
- if (opt.subset && !fieldFonts.has(key) && !fontStore.get(key)["OS/2"]?.fsType?.noSubsetting) {
831
- const cps = used.get(key) || /* @__PURE__ */ new Set([32]);
832
- try {
833
- const sub = withPadding(await opt.subset(bytes, cps, glyphs ? { glyphs: glyphs.keys() } : void 0));
834
- const f = fontkit.create(sub);
835
- for (const cp of cps) void f.glyphForCodePoint(cp).advanceWidth;
836
- for (const id of glyphs?.keys() || []) void f.getGlyph(id).advanceWidth;
837
- bytes = sub;
838
- } catch {
839
- }
840
- }
841
- const pf = await doc.embedFont(bytes, { subset: false, customName: bytes === full ? void 0 : `${subsetTag(bytes)}+${fontStore.get(key).postscriptName || "Font"}` });
842
- plainEncoding(pf);
843
- if (glyphs) addGlyphs(pf, glyphs, !!opt.tagged);
844
- const file = bytes, e = (
845
- /** @type {any} */
846
- pf.embedder
847
- );
848
- if (!e.isCFF()) e.embedFontStream = async (c) => c.register(PDFRawStream2.of(c.obj({ Filter: "FlateDecode", Length1: file.length }), await deflate(file)));
849
- fonts.set(key, pf);
804
+ const starts = run.rtl ? [...new Set(all.filter((_, i) => i % 4 === 3))].sort((a, b) => a - b) : [];
805
+ let inSpan = false;
806
+ for (let i = 0; i < g.length; i += 4) {
807
+ const id = g[i], gx = g[i + 1], gy = g[i + 2], cl = g[i + 3];
808
+ if (i === quietAt) {
809
+ flush();
810
+ c.s += span("");
811
+ inSpan = true;
812
+ } else if (run.rtl && spans?.has(cl) && (quietAt < 0 || i < quietAt) && (i === 0 || g[i - 1] !== cl)) {
813
+ flush();
814
+ c.s += span(run.text.slice(cl, starts[starts.indexOf(cl) + 1] ?? run.text.length));
815
+ inSpan = true;
850
816
  }
851
- return fonts.get(key);
852
- };
853
- const images = /* @__PURE__ */ new Map();
854
- const image = async (src) => {
855
- if (images.has(src)) return images.get(src);
856
- const out = await loadImage(src).catch((e) => ({ img: null, why: `it could not be embedded (${e?.message || e})` }));
857
- images.set(src, out);
858
- return out;
859
- };
860
- async function loadImage(src) {
861
- const local = /^data:/i.test(src);
862
- if (local && dataUriBytes(src) > IMAGE_LIMITS.bytes) return { img: null, why: "it is larger than the image size limit" };
863
- if (!local && !opt.fetchImage) return { img: null, why: "it is a URL, and no fetchImage was given to load it" };
864
- const bytes = local ? dataUriBytesOf(src) : await opt.fetchImage(src);
865
- if (!bytes?.length) return { img: null, why: "it could not be loaded" };
866
- if (bytes.length > IMAGE_LIMITS.bytes) return { img: null, why: "it is larger than the image size limit" };
867
- const info = imageInfoOf(bytes);
868
- if (info?.type === "svg") {
869
- const svg = parseSvg(new TextDecoder().decode(bytes));
870
- return svg ? { img: { svg, width: svg.w, height: svg.h } } : { img: null, why: "the SVG could not be read" };
817
+ if (gy !== rise) {
818
+ flush();
819
+ c.s += `${n4(gy)} Ts
820
+ `;
821
+ rise = gy;
871
822
  }
872
- if (info?.type === "png") {
873
- const why = "w" in info && !/** @type {any} */
874
- info.suspect && info.w * info.h <= IMAGE_LIMITS.pixels ? pngProblem(bytes) : "too large or animated";
875
- return why ? { img: null, why: `the PNG is not usable (${why})` } : { img: await doc.embedPng(bytes) };
823
+ const adj = Math.round((pen - gx) * per * 1e3) / 1e3;
824
+ if (id === 0 && (c.tagged || formatAt(run, cl))) pen = gx;
825
+ else {
826
+ arr += (adj ? `${adj}` : "") + `<${hex4(id)}>`;
827
+ pen = gx + adv(id) * size / f.unitsPerEm;
828
+ }
829
+ if (inSpan && (i + 4 >= g.length || (quietAt < 0 || i + 4 < quietAt) && g[i + 7] !== cl || i + 4 === quietAt)) {
830
+ flush();
831
+ c.s += "EMC\n";
832
+ inSpan = false;
876
833
  }
877
- if (info?.type === "jpeg") return { img: await doc.embedJpg(bytes) };
878
- return { img: null, why: info ? `${info.type.toUpperCase()} is not embedded (PNG, JPEG and SVG are)` : "it is not a PNG, JPEG or SVG" };
879
834
  }
880
- const ctx = doc.context;
881
- const res = ctx.obj({ Font: {}, ExtGState: {}, XObject: {} });
882
- const resRef = ctx.register(res);
883
- const names = /* @__PURE__ */ new Map();
884
- const nameOf = (kind, key, value) => {
885
- let n = names.get(key);
886
- if (!n) {
887
- n = `${kind[0]}${names.size + 1}`;
888
- names.set(key, n);
889
- res.get(PDFName3.of(kind)).set(PDFName3.of(n), value());
835
+ flush();
836
+ if (rise) c.s += "0 Ts\n";
837
+ c.s += "ET\n";
838
+ if (!run.rtl) c.s += "EMC\n";
839
+ }
840
+ function glyphText(run, font, out, spans) {
841
+ const g = run.glyphs;
842
+ const starts = [...new Set(g.filter((_, i) => i % 4 === 3))].sort((a, b) => a - b);
843
+ for (let k = 0; k < starts.length; k++) {
844
+ const chars = [...run.text.slice(starts[k], starts[k + 1] ?? run.text.length)];
845
+ const ids = [];
846
+ for (let i = 0; i < g.length; i += 4) if (g[i + 3] === starts[k]) ids.push(g[i]);
847
+ const own = new Map(chars.map((ch) => [font.glyphForCodePoint(ch.codePointAt(0)).id, ch]));
848
+ const rest = chars.filter((ch) => !ids.includes(font.glyphForCodePoint(ch.codePointAt(0)).id)).join("");
849
+ const carrier = rest ? ids.find((id) => !own.has(id) && font.getGlyph(id).advanceWidth > 0) ?? ids.find((id) => !own.has(id)) : void 0;
850
+ let ok = !rest || carrier !== void 0;
851
+ const want = /* @__PURE__ */ new Map();
852
+ for (const id of ids) {
853
+ const t = own.get(id) ?? (id === carrier ? rest : "");
854
+ if (want.has(id) && want.get(id) !== t) ok = false;
855
+ want.set(id, t);
890
856
  }
891
- return n;
892
- };
893
- const shared = {
894
- font: (pf) => nameOf("Font", pf, () => pf.ref),
895
- gs: (ca, CA) => nameOf("ExtGState", `gs ${ca} ${CA}`, () => ctx.obj({ Type: "ExtGState", ca, CA })),
896
- image: (img) => nameOf("XObject", img, () => img.ref)
897
- };
898
- const links = [];
899
- const taken = /* @__PURE__ */ new Set();
900
- const uniqueName = (n) => {
901
- let name = n, i = 1;
902
- while (taken.has(name)) name = `${n}_${++i}`;
903
- taken.add(name);
904
- return name;
905
- };
906
- const contents = [];
907
- if (opt.tagged) needsTableData(model, "An accessible PDF");
908
- const tags = opt.tagged ? createTagger(model, doc) : null;
909
- let pi = -1;
910
- const vm = /* @__PURE__ */ new Map();
911
- const vmetrics = (key) => {
912
- let m = vm.get(key);
913
- if (!m) {
914
- const f = fontStore.get(key), u = f?.unitsPerEm || 1e3;
915
- vm.set(key, m = { asc: (f?.ascent ?? u) / u, desc: -(f?.descent ?? 0) / u });
857
+ for (const [id, t] of want) {
858
+ if (!out.has(id)) out.set(id, t);
859
+ else if (out.get(id) !== t) ok = false;
916
860
  }
917
- return m;
918
- };
919
- for (const pg of model.pages) {
920
- pi++;
921
- const H = pg.height ?? model.height;
922
- const p = doc.addPage([pg.width ?? model.width, H]);
923
- p.node.normalize();
924
- p.node.set(PDFName3.of("Resources"), resRef);
925
- const c = new Content(shared);
926
- if (tags) c.tagged = true;
927
- p.maybeEmbedGraphicsState = (o) => c.gsFor(o.opacity ?? 1, o.borderOpacity ?? 1);
928
- const viaPdfLib = (draw) => {
929
- c.et();
930
- c.lineWidth(1);
931
- draw();
932
- const ops = (
933
- /** @type {any} */
934
- p.getContentStream().operators
935
- );
936
- for (const op of ops) c.s += op.toString() + "\n";
937
- ops.length = 0;
938
- };
939
- for (let ii = 0; ii < pg.items.length; ii++) {
940
- const it = pg.items[ii];
861
+ if (!ok && run.rtl && spans) {
862
+ let s = spans.get(run);
863
+ if (!s) spans.set(run, s = /* @__PURE__ */ new Set());
864
+ s.add(starts[k]);
865
+ }
866
+ }
867
+ }
868
+ function insideClip(it, m) {
869
+ const k = it.clip, asc = m.asc * it.size, desc = m.desc * it.size;
870
+ return it.lines.every((l) => l.w != null && !l.runs && l.x >= k.x && l.x + l.w <= k.x + k.w && l.y - asc >= k.y && l.y + desc <= k.y + k.h);
871
+ }
872
+ var Content = class {
873
+ constructor(shared) {
874
+ this.shared = shared;
875
+ this._s = "";
876
+ this.bt = false;
877
+ this.tx = 0;
878
+ this.ty = 0;
879
+ this.st = { fill: "0 0 0", stroke: "0 0 0", lw: 1, dash: "[] 0", ca: 1, CA: 1, font: "", size: 0 };
880
+ this.saved = [];
881
+ this.lines = null;
882
+ this.tagged = false;
883
+ this.artLines = false;
884
+ }
885
+ /**
886
+ * The operators so far. Any other drawing reads or appends to it, so the lines waiting are drawn first: the text
887
+ * of a table's cells stays in one text object (relative moves, which compress to little) instead of one per cell.
888
+ */
889
+ get s() {
890
+ this.flushLines();
891
+ return this._s;
892
+ }
893
+ set s(v) {
894
+ this._s = v;
895
+ }
896
+ /**
897
+ * A straight line. Untagged, it waits until something other than text is drawn (table borders between cell
898
+ * texts); collinear segments that touch, in the same stroke, become one (a row's border is one line).
899
+ * ponytail: lines move after the text drawn just after them; both are thin and do not cover each other.
900
+ */
901
+ line(stroke, w, dash, x1, y1, x2, y2) {
902
+ if (this.tagged && !this.artLines) {
903
+ this.paint(null, stroke, w, dash);
904
+ this._s += `${n2(x1)} ${n2(y1)} m ${n2(x2)} ${n2(y2)} l S
905
+ `;
906
+ return;
907
+ }
908
+ const key = `${stroke.rgb}|${stroke.opacity}|${w}|${(dash || []).join(" ")}`;
909
+ if (this.lines && this.lines.key !== key) this.flushLines();
910
+ this.lines || (this.lines = { key, stroke, w, dash, segs: [] });
911
+ const segs = this.lines.segs, last = segs[segs.length - 1];
912
+ const eq = (a, b) => Math.abs(a - b) < 5e-3;
913
+ if (last && eq(last[1], y1) && eq(last[3], y2) && eq(y1, y2) && eq(last[2], x1)) last[2] = x2;
914
+ else if (last && eq(last[0], x1) && eq(last[2], x2) && eq(x1, x2) && eq(last[3], y1)) last[3] = y2;
915
+ else segs.push([x1, y1, x2, y2]);
916
+ }
917
+ flushLines() {
918
+ const L = this.lines;
919
+ if (!L) return;
920
+ this.lines = null;
921
+ this.et();
922
+ const end = this.artLines ? "EMC\n" : "";
923
+ if (end) this._s += "/Artifact BMC\n";
924
+ this.paint(null, L.stroke, L.w, L.dash);
925
+ const g = L.segs;
926
+ const dy = g.length > 2 ? Math.round((g[1][1] - g[0][1]) * 100) : 0;
927
+ if (dy && g.every((q, i) => q[1] === q[3] && n2(q[0]) === n2(g[0][0]) && n2(q[2]) === n2(g[0][2]) && Math.abs(q[1] - (g[0][1] + i * dy / 100)) < 0.01)) {
928
+ const one = `${n2(g[0][0])} ${n2(g[0][1])} m ${n2(g[0][2])} ${n2(g[0][1])} l S
929
+ `;
930
+ this._s += `q
931
+ ${one}${`1 0 0 1 0 ${dy / 100} cm ${one}`.repeat(g.length - 1)}Q
932
+ ${end}`;
933
+ return;
934
+ }
935
+ this._s += g.map(([a, b, c, d]) => `${n2(a)} ${n2(b)} m ${n2(c)} ${n2(d)} l`).join(" ") + " S\n" + end;
936
+ }
937
+ q() {
938
+ this.et();
939
+ this._s += "q\n";
940
+ this.saved.push({ ...this.st });
941
+ }
942
+ Q() {
943
+ this.et();
944
+ this._s += "Q\n";
945
+ this.st = this.saved.pop();
946
+ }
947
+ /**
948
+ * A line of plain text at (x, y). Lines follow one another in one text object, each placed relative to the
949
+ * last (in whole hundredths, so nothing drifts): most of a table page is these.
950
+ * @param {string} str the glyphs, as a literal string's escaped body (array: a TJ array's body)
951
+ */
952
+ text(pf, size, color, x, y, str, array = false) {
953
+ this.setPaint(color, null);
954
+ this.setFont(pf, size);
955
+ const X = Math.round(x * 10) * 10, Y = Math.round(y * 10) * 10;
956
+ if (!this.bt) {
957
+ this._s += "BT\n";
958
+ this.bt = true;
959
+ this.tx = 0;
960
+ this.ty = 0;
961
+ }
962
+ this._s += array ? `${(X - this.tx) / 100} ${(Y - this.ty) / 100} Td [${str}] TJ
963
+ ` : `${(X - this.tx) / 100} ${(Y - this.ty) / 100} Td (${str}) Tj
964
+ `;
965
+ this.tx = X;
966
+ this.ty = Y;
967
+ }
968
+ /** end the open text object, if any: anything but text needs that (and draws the lines waiting) */
969
+ et() {
970
+ if (this.bt) {
971
+ this._s += "ET\n";
972
+ this.bt = false;
973
+ }
974
+ if (this.lines) this.flushLines();
975
+ }
976
+ lineWidth(w) {
977
+ if (this.lines) this.flushLines();
978
+ this.setLineWidth(w);
979
+ }
980
+ setLineWidth(w) {
981
+ if (this.st.lw !== w) {
982
+ this._s += `${n3(w)} w
983
+ `;
984
+ this.st.lw = w;
985
+ }
986
+ }
987
+ /** the graphics state that sets these opacities, or undefined when they are set already */
988
+ gsFor(ca, CA) {
989
+ return ca === this.st.ca && CA === this.st.CA ? void 0 : this.shared.gs(ca, CA);
990
+ }
991
+ alpha(ca, CA) {
992
+ if (this.lines) this.flushLines();
993
+ this.setAlpha(ca, CA);
994
+ }
995
+ setAlpha(ca, CA) {
996
+ const g = this.gsFor(ca, CA);
997
+ if (g) {
998
+ this._s += `/${g} gs
999
+ `;
1000
+ this.st.ca = ca;
1001
+ this.st.CA = CA;
1002
+ }
1003
+ }
1004
+ /** set up to fill with fill and/or stroke with stroke (width w, dash); the lines waiting are drawn first */
1005
+ paint(fill, stroke, w = 1, dash = null) {
1006
+ if (this.lines) this.flushLines();
1007
+ this.setPaint(fill, stroke, w, dash);
1008
+ }
1009
+ setPaint(fill, stroke, w = 1, dash = null) {
1010
+ const st = this.st;
1011
+ if (fill && fill.rgb !== st.fill) {
1012
+ this._s += `${fill.rgb} rg
1013
+ `;
1014
+ st.fill = fill.rgb;
1015
+ }
1016
+ if (stroke) {
1017
+ if (stroke.rgb !== st.stroke) {
1018
+ this._s += `${stroke.rgb} RG
1019
+ `;
1020
+ st.stroke = stroke.rgb;
1021
+ }
1022
+ this.setLineWidth(w);
1023
+ const d = `[${(dash || []).map(n3).join(" ")}] 0`;
1024
+ if (d !== st.dash) {
1025
+ this._s += `${d} d
1026
+ `;
1027
+ st.dash = d;
1028
+ }
1029
+ }
1030
+ this.setAlpha(fill ? fill.opacity : st.ca, stroke ? stroke.opacity : st.CA);
1031
+ }
1032
+ font(pf, size) {
1033
+ if (this.lines) this.flushLines();
1034
+ this.setFont(pf, size);
1035
+ }
1036
+ setFont(pf, size) {
1037
+ const name = this.shared.font(pf);
1038
+ if (name !== this.st.font || size !== this.st.size) {
1039
+ this._s += `/${name} ${n3(size)} Tf
1040
+ `;
1041
+ this.st.font = name;
1042
+ this.st.size = size;
1043
+ }
1044
+ }
1045
+ };
1046
+ function latin1(s) {
1047
+ const B = (
1048
+ /** @type {any} */
1049
+ globalThis.Buffer
1050
+ );
1051
+ if (B) return B.from(s, "latin1");
1052
+ const out = new Uint8Array(s.length);
1053
+ for (let i = 0; i < s.length; i++) out[i] = s.charCodeAt(i);
1054
+ return out;
1055
+ }
1056
+ async function deflate(bytes) {
1057
+ if (zslots.free > 0) zslots.free--;
1058
+ else await new Promise((ok) => zslots.wait.push(
1059
+ /** @type {() => void} */
1060
+ ok
1061
+ ));
1062
+ try {
1063
+ return await deflateNow(bytes);
1064
+ } finally {
1065
+ const next = zslots.wait.shift();
1066
+ if (next) next();
1067
+ else zslots.free++;
1068
+ }
1069
+ }
1070
+ var zslots = { free: 4, wait: (
1071
+ /** @type {(() => void)[]} */
1072
+ []
1073
+ ) };
1074
+ var NODE_ZLIB = (
1075
+ /** @type {any} */
1076
+ globalThis.process?.getBuiltinModule?.("node:zlib")
1077
+ );
1078
+ async function deflateNow(bytes) {
1079
+ const zlib = NODE_ZLIB;
1080
+ if (zlib) return new Promise((ok, fail) => zlib.deflate(bytes, { level: 9 }, (e, z) => e ? fail(e) : ok(z)));
1081
+ if (typeof CompressionStream === "undefined") return (await import("fflate")).zlibSync(bytes);
1082
+ return new Uint8Array(await new Response(new Blob([bytes]).stream().pipeThrough(new CompressionStream("deflate"))).arrayBuffer());
1083
+ }
1084
+
1085
+ // src/exporters/pdf.js
1086
+ var fontkit = (
1087
+ /** @type {any} */
1088
+ fontkitModule.default || fontkitModule
1089
+ );
1090
+ function exportPdf(model, fontStore, opt = {}) {
1091
+ return withDeadline(
1092
+ pdfOf(model, fontStore, opt),
1093
+ /** @type {any} */
1094
+ opt.timeoutMs
1095
+ );
1096
+ }
1097
+ async function pdfOf(model, fontStore, opt) {
1098
+ const fixed = fixedDate(opt);
1099
+ const when = fixed ?? /* @__PURE__ */ new Date();
1100
+ const fileId = fixed ? await contentId(model, opt, when) : void 0;
1101
+ const doc = await PDFDocument.create({ updateMetadata: false });
1102
+ doc.registerFontkit(fontkit);
1103
+ doc.setTitle(opt.title || "Report");
1104
+ doc.setProducer("ReportWright");
1105
+ doc.setCreator("ReportWright");
1106
+ if (opt.author) doc.setAuthor(opt.author);
1107
+ setInfoDates(doc, when);
1108
+ if (fileId) doc.context.trailerInfo.ID = doc.context.obj([PDFHexString5.of(fileId), PDFHexString5.of(fileId)]);
1109
+ const used = /* @__PURE__ */ new Map();
1110
+ const shaped = /* @__PURE__ */ new Map();
1111
+ const spans = /* @__PURE__ */ new WeakMap();
1112
+ const chars = (key) => {
1113
+ let c = used.get(key);
1114
+ if (!c) {
1115
+ c = /* @__PURE__ */ new Set([32]);
1116
+ used.set(key, c);
1117
+ }
1118
+ return c;
1119
+ };
1120
+ for (const pg of model.pages) for (const it of pg.items.flatMap((i) => i.t === "field" ? i.draw.filter((d) => d.t === "text") : i.t === "text" ? [i] : [])) {
1121
+ for (const l of it.lines) {
1122
+ if (!l.runs) {
1123
+ const c = chars(it.font);
1124
+ for (const ch of l.text) c.add(
1125
+ /** @type {number} */
1126
+ ch.codePointAt(0)
1127
+ );
1128
+ continue;
1129
+ }
1130
+ for (const r of l.runs) {
1131
+ const c = chars(r.font);
1132
+ for (const ch of r.text) c.add(
1133
+ /** @type {number} */
1134
+ ch.codePointAt(0)
1135
+ );
1136
+ let g = shaped.get(r.font);
1137
+ if (!g) {
1138
+ g = /* @__PURE__ */ new Map();
1139
+ shaped.set(r.font, g);
1140
+ }
1141
+ glyphText(r, fontStore.get(r.font), g, spans);
1142
+ }
1143
+ }
1144
+ }
1145
+ const fieldFonts = /* @__PURE__ */ new Set();
1146
+ for (const pg of model.pages) for (const it of pg.items) if (it.t === "field") fieldFonts.add(fieldFont(it));
1147
+ const fonts = /* @__PURE__ */ new Map();
1148
+ const font = async (key) => {
1149
+ if (!fonts.has(key)) {
1150
+ const full = fontStore.bytes.get(key);
1151
+ let bytes = full;
1152
+ if (!bytes) throw new Error(`Font "${key}" is not loaded`);
1153
+ const glyphs = shaped.get(key);
1154
+ if (opt.subset && !fieldFonts.has(key) && !fontStore.get(key)["OS/2"]?.fsType?.noSubsetting) {
1155
+ const cps = used.get(key) || /* @__PURE__ */ new Set([32]);
1156
+ try {
1157
+ const sub = withPadding(await opt.subset(bytes, cps, glyphs ? { glyphs: glyphs.keys() } : void 0));
1158
+ const f = fontkit.create(sub);
1159
+ for (const cp of cps) void f.glyphForCodePoint(cp).advanceWidth;
1160
+ for (const id of glyphs?.keys() || []) void f.getGlyph(id).advanceWidth;
1161
+ bytes = sub;
1162
+ } catch {
1163
+ }
1164
+ }
1165
+ const pf = await doc.embedFont(bytes, { subset: false, customName: bytes === full ? void 0 : `${subsetTag(bytes)}+${fontStore.get(key).postscriptName || "Font"}` });
1166
+ plainEncoding(pf);
1167
+ if (glyphs) addGlyphs(pf, glyphs, !!opt.tagged);
1168
+ const file = bytes, e = (
1169
+ /** @type {any} */
1170
+ pf.embedder
1171
+ );
1172
+ if (!e.isCFF()) e.embedFontStream = async (c) => c.register(PDFRawStream2.of(c.obj({ Filter: "FlateDecode", Length1: file.length }), await deflate(file)));
1173
+ fonts.set(key, pf);
1174
+ }
1175
+ return fonts.get(key);
1176
+ };
1177
+ const images = /* @__PURE__ */ new Map();
1178
+ const image = async (src) => {
1179
+ if (images.has(src)) return images.get(src);
1180
+ const out = await loadImage(src).catch((e) => ({ img: null, why: `it could not be embedded (${e?.message || e})` }));
1181
+ images.set(src, out);
1182
+ return out;
1183
+ };
1184
+ async function loadImage(src) {
1185
+ const local = /^data:/i.test(src);
1186
+ if (local && dataUriBytes(src) > IMAGE_LIMITS.bytes) return { img: null, why: "it is larger than the image size limit" };
1187
+ if (!local && !opt.fetchImage) return { img: null, why: "it is a URL, and no fetchImage was given to load it" };
1188
+ const bytes = local ? dataUriBytesOf(src) : await opt.fetchImage(src);
1189
+ if (!bytes?.length) return { img: null, why: "it could not be loaded" };
1190
+ if (bytes.length > IMAGE_LIMITS.bytes) return { img: null, why: "it is larger than the image size limit" };
1191
+ const info = imageInfoOf(bytes);
1192
+ if (info?.type === "svg") {
1193
+ const svg = parseSvg(new TextDecoder().decode(bytes));
1194
+ return svg ? { img: { svg, width: svg.w, height: svg.h } } : { img: null, why: "the SVG could not be read" };
1195
+ }
1196
+ if (info?.type === "png") {
1197
+ const why = "w" in info && !/** @type {any} */
1198
+ info.suspect && info.w * info.h <= IMAGE_LIMITS.pixels ? pngProblem(bytes) : "too large or animated";
1199
+ return why ? { img: null, why: `the PNG is not usable (${why})` } : { img: await doc.embedPng(bytes) };
1200
+ }
1201
+ if (info?.type === "jpeg") return { img: await doc.embedJpg(bytes) };
1202
+ return { img: null, why: info ? `${info.type.toUpperCase()} is not embedded (PNG, JPEG and SVG are)` : "it is not a PNG, JPEG or SVG" };
1203
+ }
1204
+ const ctx = doc.context;
1205
+ const res = ctx.obj({ Font: {}, ExtGState: {}, XObject: {} });
1206
+ const resRef = ctx.register(res);
1207
+ const names = /* @__PURE__ */ new Map();
1208
+ const nameOf = (kind, key, value) => {
1209
+ let n = names.get(key);
1210
+ if (!n) {
1211
+ n = `${kind[0]}${names.size + 1}`;
1212
+ names.set(key, n);
1213
+ res.get(PDFName3.of(kind)).set(PDFName3.of(n), value());
1214
+ }
1215
+ return n;
1216
+ };
1217
+ const shared = {
1218
+ font: (pf) => nameOf("Font", pf, () => pf.ref),
1219
+ gs: (ca, CA) => nameOf("ExtGState", `gs ${ca} ${CA}`, () => ctx.obj({ Type: "ExtGState", ca, CA })),
1220
+ image: (img) => nameOf("XObject", img, () => img.ref)
1221
+ };
1222
+ const links = [];
1223
+ const taken = /* @__PURE__ */ new Set();
1224
+ const uniqueName = (n) => {
1225
+ let name = n, i = 1;
1226
+ while (taken.has(name)) name = `${n}_${++i}`;
1227
+ taken.add(name);
1228
+ return name;
1229
+ };
1230
+ const contents = [];
1231
+ if (opt.tagged) needsTableData(model, "An accessible PDF");
1232
+ const tags = opt.tagged ? createTagger(model, doc) : null;
1233
+ let pi = -1;
1234
+ const vm = /* @__PURE__ */ new Map();
1235
+ const vmetrics = (key) => {
1236
+ let m = vm.get(key);
1237
+ if (!m) {
1238
+ const f = fontStore.get(key), u = f?.unitsPerEm || 1e3;
1239
+ vm.set(key, m = { asc: (f?.ascent ?? u) / u, desc: -(f?.descent ?? 0) / u });
1240
+ }
1241
+ return m;
1242
+ };
1243
+ for (const pg of model.pages) {
1244
+ pi++;
1245
+ const H = pg.height ?? model.height;
1246
+ const p = doc.addPage([pg.width ?? model.width, H]);
1247
+ p.node.normalize();
1248
+ p.node.set(PDFName3.of("Resources"), resRef);
1249
+ const c = new Content(shared);
1250
+ if (tags) c.tagged = true;
1251
+ p.maybeEmbedGraphicsState = (o) => c.gsFor(o.opacity ?? 1, o.borderOpacity ?? 1);
1252
+ const viaPdfLib = (draw) => {
1253
+ c.et();
1254
+ c.lineWidth(1);
1255
+ draw();
1256
+ const ops = (
1257
+ /** @type {any} */
1258
+ p.getContentStream().operators
1259
+ );
1260
+ for (const op of ops) c.s += op.toString() + "\n";
1261
+ ops.length = 0;
1262
+ };
1263
+ for (let ii = 0; ii < pg.items.length; ii++) {
1264
+ const it = pg.items[ii];
941
1265
  const mark = tags && tags.open(pi, ii, it);
942
1266
  if (mark) {
943
1267
  c.et();
@@ -1028,7 +1352,7 @@ async function pdfOf(model, fontStore, opt) {
1028
1352
  const form = doc.getForm();
1029
1353
  const f = await font(fieldFont(it));
1030
1354
  const name = uniqueName(it.name);
1031
- const box = { x: it.x, y: H - it.y - it.h, width: it.w, height: it.h, borderColor: rgb2(0.61, 0.64, 0.69), borderWidth: 0.75, backgroundColor: rgb2(1, 1, 1) };
1355
+ const box = { x: it.x, y: H - it.y - it.h, width: it.w, height: it.h, borderColor: rgb3(0.61, 0.64, 0.69), borderWidth: 0.75, backgroundColor: rgb3(1, 1, 1) };
1032
1356
  let field;
1033
1357
  if (it.kind === "checkbox") {
1034
1358
  field = form.createCheckBox(name);
@@ -1085,7 +1409,7 @@ async function pdfOf(model, fontStore, opt) {
1085
1409
  if (it.required) field.enableRequired();
1086
1410
  if (it.readOnly) field.enableReadOnly();
1087
1411
  if (tags) {
1088
- field.acroField.dict.set(PDFName3.of("TU"), PDFHexString4.fromText(it.label || it.name || name));
1412
+ field.acroField.dict.set(PDFName3.of("TU"), PDFHexString5.fromText(it.label || it.name || name));
1089
1413
  const w = field.acroField.getWidgets()[0];
1090
1414
  const ref2 = w && doc.context.getObjectRef(w.dict);
1091
1415
  if (ref2) tags.annot(pi, ii, ref2, "field");
@@ -1159,7 +1483,7 @@ async function pdfOf(model, fontStore, opt) {
1159
1483
  const to = l.href ? { A: { Type: "Action", S: "URI", URI: pdfLiteral(asciiUrl(l.href)) } } : { Dest: dest(l.to) };
1160
1484
  if (!l.href && !to.Dest) continue;
1161
1485
  const annot = doc.context.obj({ Type: "Annot", Subtype: "Link", F: 4, Rect: l.rect, Border: [0, 0, 0], ...to });
1162
- if (tags) annot.set(PDFName3.of("Contents"), PDFHexString4.fromText(String(l.text || l.tip || l.href || "Link")));
1486
+ if (tags) annot.set(PDFName3.of("Contents"), PDFHexString5.fromText(String(l.text || l.tip || l.href || "Link")));
1163
1487
  const ref = doc.context.register(annot);
1164
1488
  if (tags) tags.annot(l.pi, l.ii, ref, "link");
1165
1489
  const annots = l.page.node.lookup(PDFName3.of("Annots"));
@@ -1184,124 +1508,28 @@ async function pdfOf(model, fontStore, opt) {
1184
1508
  function coveredText(items, box) {
1185
1509
  const lines = [];
1186
1510
  for (const t of items) if (t.t === "text" && t.lines) {
1187
- for (const l of t.lines) if (l.text?.trim() && l.x >= box.x && l.x <= box.x + box.w && l.y >= box.y && l.y <= box.y + box.h) lines.push(l);
1188
- }
1189
- return lines.sort((a, b) => a.y - b.y || a.x - b.x).map((l) => l.text.trim()).join(" ");
1190
- }
1191
- function fixedDate(opt) {
1192
- if (opt.creationDate !== void 0) {
1193
- if (!(opt.creationDate instanceof Date) || Number.isNaN(opt.creationDate.getTime())) throw Object.assign(new Error("creationDate must be a valid Date"), { status: 400 });
1194
- return opt.creationDate;
1195
- }
1196
- const epoch = globalThis.process?.env?.SOURCE_DATE_EPOCH;
1197
- return epoch && /^\d+$/.test(epoch) ? new Date(Number(epoch) * 1e3) : null;
1198
- }
1199
- async function contentId(model, opt, when) {
1200
- const bytes = new TextEncoder().encode(JSON.stringify([{ ...model, stats: void 0 }, opt.title || "Report", opt.author || "", when.toISOString()]));
1201
- const digest = new Uint8Array(await globalThis.crypto.subtle.digest("SHA-256", bytes));
1202
- return Array.from(digest.subarray(0, 16), (b) => b.toString(16).padStart(2, "0")).join("").toUpperCase();
1203
- }
1204
- function fieldFont(it) {
1205
- for (const d of it.draw) if (d.t === "text") {
1206
- for (const l of d.lines) for (const r of l.runs || []) if (r.font !== it.font && r.text.trim()) return r.font;
1207
- }
1208
- return it.font;
1209
- }
1210
- function drawRun(c, run, x, y, size, pf, color, spans, texts) {
1211
- const f = pf.embedder.font;
1212
- const per = 1e3 / size;
1213
- const span = (text) => `/Span <</ActualText ${PDFHexString4.fromText(text).toString()}>> BDC
1214
- `;
1215
- c.et();
1216
- c.paint(color, null);
1217
- c.font(pf, size);
1218
- if (!run.rtl) c.s += span(run.text);
1219
- c.s += `BT ${n2(x)} ${n2(y)} Td
1220
- `;
1221
- let arr = "";
1222
- let pen = 0, rise = 0;
1223
- const flush = () => {
1224
- if (arr) c.s += `[${arr}] TJ
1225
- `;
1226
- arr = "";
1227
- };
1228
- const all = run.glyphs;
1229
- const adv = (id) => f.getGlyph(id).advanceWidth;
1230
- let g = all, quietAt = -1;
1231
- if (run.rtl) {
1232
- const hasBase = /* @__PURE__ */ new Set();
1233
- for (let i = 0; i < all.length; i += 4) if (adv(all[i]) > 0) hasBase.add(all[i + 3]);
1234
- const quiet = (i) => spans?.has(all[i + 3]) ? adv(all[i]) === 0 && hasBase.has(all[i + 3]) : texts?.get(all[i]) === "";
1235
- g = [];
1236
- for (const late of [false, true]) {
1237
- if (late) quietAt = g.length;
1238
- for (let i = 0; i < all.length; i += 4) if (quiet(i) === late) g.push(all[i], all[i + 1], all[i + 2], all[i + 3]);
1239
- }
1240
- if (quietAt === g.length) quietAt = -1;
1241
- }
1242
- const starts = run.rtl ? [...new Set(all.filter((_, i) => i % 4 === 3))].sort((a, b) => a - b) : [];
1243
- let inSpan = false;
1244
- for (let i = 0; i < g.length; i += 4) {
1245
- const id = g[i], gx = g[i + 1], gy = g[i + 2], cl = g[i + 3];
1246
- if (i === quietAt) {
1247
- flush();
1248
- c.s += span("");
1249
- inSpan = true;
1250
- } else if (run.rtl && spans?.has(cl) && (quietAt < 0 || i < quietAt) && (i === 0 || g[i - 1] !== cl)) {
1251
- flush();
1252
- c.s += span(run.text.slice(cl, starts[starts.indexOf(cl) + 1] ?? run.text.length));
1253
- inSpan = true;
1254
- }
1255
- if (gy !== rise) {
1256
- flush();
1257
- c.s += `${n4(gy)} Ts
1258
- `;
1259
- rise = gy;
1260
- }
1261
- const adj = Math.round((pen - gx) * per * 1e3) / 1e3;
1262
- if (id === 0 && c.tagged) pen = gx;
1263
- else {
1264
- arr += (adj ? `${adj}` : "") + `<${hex4(id)}>`;
1265
- pen = gx + adv(id) * size / f.unitsPerEm;
1266
- }
1267
- if (inSpan && (i + 4 >= g.length || (quietAt < 0 || i + 4 < quietAt) && g[i + 7] !== cl || i + 4 === quietAt)) {
1268
- flush();
1269
- c.s += "EMC\n";
1270
- inSpan = false;
1271
- }
1511
+ for (const l of t.lines) if (l.text?.trim() && l.x >= box.x && l.x <= box.x + box.w && l.y >= box.y && l.y <= box.y + box.h) lines.push(l);
1272
1512
  }
1273
- flush();
1274
- if (rise) c.s += "0 Ts\n";
1275
- c.s += "ET\n";
1276
- if (!run.rtl) c.s += "EMC\n";
1513
+ return lines.sort((a, b) => a.y - b.y || a.x - b.x).map((l) => l.text.trim()).join(" ");
1277
1514
  }
1278
- function glyphText(run, font, out, spans) {
1279
- const g = run.glyphs;
1280
- const starts = [...new Set(g.filter((_, i) => i % 4 === 3))].sort((a, b) => a - b);
1281
- for (let k = 0; k < starts.length; k++) {
1282
- const chars = [...run.text.slice(starts[k], starts[k + 1] ?? run.text.length)];
1283
- const ids = [];
1284
- for (let i = 0; i < g.length; i += 4) if (g[i + 3] === starts[k]) ids.push(g[i]);
1285
- const own = new Map(chars.map((ch) => [font.glyphForCodePoint(ch.codePointAt(0)).id, ch]));
1286
- const rest = chars.filter((ch) => !ids.includes(font.glyphForCodePoint(ch.codePointAt(0)).id)).join("");
1287
- const carrier = rest ? ids.find((id) => !own.has(id) && font.getGlyph(id).advanceWidth > 0) ?? ids.find((id) => !own.has(id)) : void 0;
1288
- let ok = !rest || carrier !== void 0;
1289
- const want = /* @__PURE__ */ new Map();
1290
- for (const id of ids) {
1291
- const t = own.get(id) ?? (id === carrier ? rest : "");
1292
- if (want.has(id) && want.get(id) !== t) ok = false;
1293
- want.set(id, t);
1294
- }
1295
- for (const [id, t] of want) {
1296
- if (!out.has(id)) out.set(id, t);
1297
- else if (out.get(id) !== t) ok = false;
1298
- }
1299
- if (!ok && run.rtl && spans) {
1300
- let s = spans.get(run);
1301
- if (!s) spans.set(run, s = /* @__PURE__ */ new Set());
1302
- s.add(starts[k]);
1303
- }
1515
+ function fixedDate(opt) {
1516
+ if (opt.creationDate !== void 0) {
1517
+ if (!(opt.creationDate instanceof Date) || Number.isNaN(opt.creationDate.getTime())) throw Object.assign(new Error("creationDate must be a valid Date"), { status: 400 });
1518
+ return opt.creationDate;
1519
+ }
1520
+ const epoch = globalThis.process?.env?.SOURCE_DATE_EPOCH;
1521
+ return epoch && /^\d+$/.test(epoch) ? new Date(Number(epoch) * 1e3) : null;
1522
+ }
1523
+ async function contentId(model, opt, when) {
1524
+ const bytes = new TextEncoder().encode(JSON.stringify([{ ...model, stats: void 0 }, opt.title || "Report", opt.author || "", when.toISOString()]));
1525
+ const digest = new Uint8Array(await globalThis.crypto.subtle.digest("SHA-256", bytes));
1526
+ return Array.from(digest.subarray(0, 16), (b) => b.toString(16).padStart(2, "0")).join("").toUpperCase();
1527
+ }
1528
+ function fieldFont(it) {
1529
+ for (const d of it.draw) if (d.t === "text") {
1530
+ for (const l of d.lines) for (const r of l.runs || []) if (r.font !== it.font && r.text.trim()) return r.font;
1304
1531
  }
1532
+ return it.font;
1305
1533
  }
1306
1534
  var pdfLiteral = (s) => PDFString4.of(String(s).replace(/[\\()]/g, "\\$&"));
1307
1535
  function plainEncoding(pf) {
@@ -1319,7 +1547,7 @@ function plainEncoding(pf) {
1319
1547
  }
1320
1548
  return hex2;
1321
1549
  };
1322
- e.encodeText = (text) => PDFHexString4.of(e.hexOf(text));
1550
+ e.encodeText = (text) => PDFHexString5.of(e.hexOf(text));
1323
1551
  e.widthOfTextAtSize = (text, size) => {
1324
1552
  let w = 0;
1325
1553
  for (const ch of text) w += f.glyphForCodePoint(
@@ -1410,7 +1638,7 @@ function addOutline(doc, bookmarks, dest) {
1410
1638
  if (!Dest) continue;
1411
1639
  const level = Math.max(0, Math.min(9, Number(b.level) || 0));
1412
1640
  while (stack[stack.length - 1].level >= level) stack.pop();
1413
- const node2 = { ref: ctx.nextRef(), level, kids: [], Title: PDFHexString4.fromText(b.label), Dest };
1641
+ const node2 = { ref: ctx.nextRef(), level, kids: [], Title: PDFHexString5.fromText(b.label), Dest };
1414
1642
  stack[stack.length - 1].kids.push(node2);
1415
1643
  stack.push(node2);
1416
1644
  }
@@ -1441,216 +1669,6 @@ function subsetTag(bytes) {
1441
1669
  }
1442
1670
  return tag;
1443
1671
  }
1444
- function insideClip(it, m) {
1445
- const k = it.clip, asc = m.asc * it.size, desc = m.desc * it.size;
1446
- return it.lines.every((l) => l.w != null && !l.runs && l.x >= k.x && l.x + l.w <= k.x + k.w && l.y - asc >= k.y && l.y + desc <= k.y + k.h);
1447
- }
1448
- var Content = class {
1449
- constructor(shared) {
1450
- this.shared = shared;
1451
- this._s = "";
1452
- this.bt = false;
1453
- this.tx = 0;
1454
- this.ty = 0;
1455
- this.st = { fill: "0 0 0", stroke: "0 0 0", lw: 1, dash: "[] 0", ca: 1, CA: 1, font: "", size: 0 };
1456
- this.saved = [];
1457
- this.lines = null;
1458
- this.tagged = false;
1459
- }
1460
- /**
1461
- * The operators so far. Any other drawing reads or appends to it, so the lines waiting are drawn first: the text
1462
- * of a table's cells stays in one text object (relative moves, which compress to little) instead of one per cell.
1463
- */
1464
- get s() {
1465
- this.flushLines();
1466
- return this._s;
1467
- }
1468
- set s(v) {
1469
- this._s = v;
1470
- }
1471
- /**
1472
- * A straight line. Untagged, it waits until something other than text is drawn (table borders between cell
1473
- * texts); collinear segments that touch, in the same stroke, become one (a row's border is one line).
1474
- * ponytail: lines move after the text drawn just after them; both are thin and do not cover each other.
1475
- */
1476
- line(stroke, w, dash, x1, y1, x2, y2) {
1477
- if (this.tagged) {
1478
- this.paint(null, stroke, w, dash);
1479
- this._s += `${n2(x1)} ${n2(y1)} m ${n2(x2)} ${n2(y2)} l S
1480
- `;
1481
- return;
1482
- }
1483
- const key = `${stroke.rgb}|${stroke.opacity}|${w}|${(dash || []).join(" ")}`;
1484
- if (this.lines && this.lines.key !== key) this.flushLines();
1485
- this.lines || (this.lines = { key, stroke, w, dash, segs: [] });
1486
- const segs = this.lines.segs, last = segs[segs.length - 1];
1487
- const eq = (a, b) => Math.abs(a - b) < 5e-3;
1488
- if (last && eq(last[1], y1) && eq(last[3], y2) && eq(y1, y2) && eq(last[2], x1)) last[2] = x2;
1489
- else if (last && eq(last[0], x1) && eq(last[2], x2) && eq(x1, x2) && eq(last[3], y1)) last[3] = y2;
1490
- else segs.push([x1, y1, x2, y2]);
1491
- }
1492
- flushLines() {
1493
- const L = this.lines;
1494
- if (!L) return;
1495
- this.lines = null;
1496
- this.et();
1497
- this.paint(null, L.stroke, L.w, L.dash);
1498
- const g = L.segs;
1499
- const dy = g.length > 2 ? Math.round((g[1][1] - g[0][1]) * 100) : 0;
1500
- if (dy && g.every((q, i) => q[1] === q[3] && n2(q[0]) === n2(g[0][0]) && n2(q[2]) === n2(g[0][2]) && Math.abs(q[1] - (g[0][1] + i * dy / 100)) < 0.01)) {
1501
- const one = `${n2(g[0][0])} ${n2(g[0][1])} m ${n2(g[0][2])} ${n2(g[0][1])} l S
1502
- `;
1503
- this._s += `q
1504
- ${one}${`1 0 0 1 0 ${dy / 100} cm ${one}`.repeat(g.length - 1)}Q
1505
- `;
1506
- return;
1507
- }
1508
- this._s += g.map(([a, b, c, d]) => `${n2(a)} ${n2(b)} m ${n2(c)} ${n2(d)} l`).join(" ") + " S\n";
1509
- }
1510
- q() {
1511
- this.et();
1512
- this._s += "q\n";
1513
- this.saved.push({ ...this.st });
1514
- }
1515
- Q() {
1516
- this.et();
1517
- this._s += "Q\n";
1518
- this.st = this.saved.pop();
1519
- }
1520
- /**
1521
- * A line of plain text at (x, y). Lines follow one another in one text object, each placed relative to the
1522
- * last (in whole hundredths, so nothing drifts): most of a table page is these.
1523
- * @param {string} str the glyphs, as a literal string's escaped body (array: a TJ array's body)
1524
- */
1525
- text(pf, size, color, x, y, str, array = false) {
1526
- this.setPaint(color, null);
1527
- this.setFont(pf, size);
1528
- const X = Math.round(x * 10) * 10, Y = Math.round(y * 10) * 10;
1529
- if (!this.bt) {
1530
- this._s += "BT\n";
1531
- this.bt = true;
1532
- this.tx = 0;
1533
- this.ty = 0;
1534
- }
1535
- this._s += array ? `${(X - this.tx) / 100} ${(Y - this.ty) / 100} Td [${str}] TJ
1536
- ` : `${(X - this.tx) / 100} ${(Y - this.ty) / 100} Td (${str}) Tj
1537
- `;
1538
- this.tx = X;
1539
- this.ty = Y;
1540
- }
1541
- /** end the open text object, if any: anything but text needs that (and draws the lines waiting) */
1542
- et() {
1543
- if (this.bt) {
1544
- this._s += "ET\n";
1545
- this.bt = false;
1546
- }
1547
- if (this.lines) this.flushLines();
1548
- }
1549
- lineWidth(w) {
1550
- if (this.lines) this.flushLines();
1551
- this.setLineWidth(w);
1552
- }
1553
- setLineWidth(w) {
1554
- if (this.st.lw !== w) {
1555
- this._s += `${n3(w)} w
1556
- `;
1557
- this.st.lw = w;
1558
- }
1559
- }
1560
- /** the graphics state that sets these opacities, or undefined when they are set already */
1561
- gsFor(ca, CA) {
1562
- return ca === this.st.ca && CA === this.st.CA ? void 0 : this.shared.gs(ca, CA);
1563
- }
1564
- alpha(ca, CA) {
1565
- if (this.lines) this.flushLines();
1566
- this.setAlpha(ca, CA);
1567
- }
1568
- setAlpha(ca, CA) {
1569
- const g = this.gsFor(ca, CA);
1570
- if (g) {
1571
- this._s += `/${g} gs
1572
- `;
1573
- this.st.ca = ca;
1574
- this.st.CA = CA;
1575
- }
1576
- }
1577
- /** set up to fill with fill and/or stroke with stroke (width w, dash); the lines waiting are drawn first */
1578
- paint(fill, stroke, w = 1, dash = null) {
1579
- if (this.lines) this.flushLines();
1580
- this.setPaint(fill, stroke, w, dash);
1581
- }
1582
- setPaint(fill, stroke, w = 1, dash = null) {
1583
- const st = this.st;
1584
- if (fill && fill.rgb !== st.fill) {
1585
- this._s += `${fill.rgb} rg
1586
- `;
1587
- st.fill = fill.rgb;
1588
- }
1589
- if (stroke) {
1590
- if (stroke.rgb !== st.stroke) {
1591
- this._s += `${stroke.rgb} RG
1592
- `;
1593
- st.stroke = stroke.rgb;
1594
- }
1595
- this.setLineWidth(w);
1596
- const d = `[${(dash || []).map(n3).join(" ")}] 0`;
1597
- if (d !== st.dash) {
1598
- this._s += `${d} d
1599
- `;
1600
- st.dash = d;
1601
- }
1602
- }
1603
- this.setAlpha(fill ? fill.opacity : st.ca, stroke ? stroke.opacity : st.CA);
1604
- }
1605
- font(pf, size) {
1606
- if (this.lines) this.flushLines();
1607
- this.setFont(pf, size);
1608
- }
1609
- setFont(pf, size) {
1610
- const name = this.shared.font(pf);
1611
- if (name !== this.st.font || size !== this.st.size) {
1612
- this._s += `/${name} ${n3(size)} Tf
1613
- `;
1614
- this.st.font = name;
1615
- this.st.size = size;
1616
- }
1617
- }
1618
- };
1619
- function latin1(s) {
1620
- const B = (
1621
- /** @type {any} */
1622
- globalThis.Buffer
1623
- );
1624
- if (B) return B.from(s, "latin1");
1625
- const out = new Uint8Array(s.length);
1626
- for (let i = 0; i < s.length; i++) out[i] = s.charCodeAt(i);
1627
- return out;
1628
- }
1629
- async function deflate(bytes) {
1630
- if (zslots.free > 0) zslots.free--;
1631
- else await new Promise((ok) => zslots.wait.push(ok));
1632
- try {
1633
- return await deflateNow(bytes);
1634
- } finally {
1635
- const next = zslots.wait.shift();
1636
- if (next) next();
1637
- else zslots.free++;
1638
- }
1639
- }
1640
- var zslots = { free: 4, wait: (
1641
- /** @type {(() => void)[]} */
1642
- []
1643
- ) };
1644
- var NODE_ZLIB = (
1645
- /** @type {any} */
1646
- globalThis.process?.getBuiltinModule?.("node:zlib")
1647
- );
1648
- async function deflateNow(bytes) {
1649
- const zlib = NODE_ZLIB;
1650
- if (zlib) return new Promise((ok, fail) => zlib.deflate(bytes, { level: 9 }, (e, z) => e ? fail(e) : ok(z)));
1651
- if (typeof CompressionStream === "undefined") return (await import("fflate")).zlibSync(bytes);
1652
- return new Uint8Array(await new Response(new Blob([bytes]).stream().pipeThrough(new CompressionStream("deflate"))).arrayBuffer());
1653
- }
1654
1672
  function roundRect(x, y, w, h, r) {
1655
1673
  r = Math.min(r, w / 2, h / 2);
1656
1674
  return `M ${x + r} ${y} H ${x + w - r} A ${r} ${r} 0 0 1 ${x + w} ${y + r} V ${y + h - r} A ${r} ${r} 0 0 1 ${x + w - r} ${y + h} H ${x + r} A ${r} ${r} 0 0 1 ${x} ${y + h - r} V ${y + r} A ${r} ${r} 0 0 1 ${x + r} ${y} Z`;
@@ -1658,4 +1676,4 @@ function roundRect(x, y, w, h, r) {
1658
1676
  export {
1659
1677
  exportPdf
1660
1678
  };
1661
- //# sourceMappingURL=chunk-66QZ3RDV.js.map
1679
+ //# sourceMappingURL=chunk-PGP3QA6L.js.map