@reportwright/pdf 0.1.0-beta.4 → 0.1.0-beta.5

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/dist/index.js +32 -9
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -15070,7 +15070,25 @@ function pageText(src, pageDict, resources, raw = false) {
15070
15070
  let chars3 = 0;
15071
15071
  let moved = true;
15072
15072
  const fonts = /* @__PURE__ */ new Map();
15073
- const add2 = (x2, y, end, size, text3, d0, d1, d2, d3) => {
15073
+ let run2 = [];
15074
+ let runs = false;
15075
+ const flush = () => {
15076
+ if (run2.length) {
15077
+ PT[PT.length - 1] += run2.join("");
15078
+ run2 = [];
15079
+ }
15080
+ };
15081
+ const add2 = (x2, y, end, size, text3, d0, d1, d2, d3, glyph = false) => {
15082
+ const n = PT.length - 1;
15083
+ if (glyph && runs && !moved && !(PG[n] & 1) && PD[n] === d3 && PC[n] === d2 && PS[n] === size && d0 >= PA[n] && d0 >= PAE[n] - 0.01 && d0 - PAE[n] <= Math.max(size, 1) * 0.25 && !RTL2.test(text3)) {
15084
+ if ((chars3 += text3.length) > MAX_TEXT_CHARS) throw new PdfReadError("E_BUDGET", `A page makes more than ${MAX_TEXT_CHARS.toLocaleString("en")} characters of text`);
15085
+ run2.push(text3);
15086
+ if (run2.length >= 4096) flush();
15087
+ PAE[n] = Math.max(PAE[n], d1);
15088
+ return;
15089
+ }
15090
+ flush();
15091
+ runs = glyph && !raw && !RTL2.test(text3);
15074
15092
  if (PT.length >= budget.maxTextItems) throw new PdfReadError("E_BUDGET", `A page has more than ${budget.maxTextItems.toLocaleString("en")} pieces of text (budget.maxTextItems)`);
15075
15093
  if ((chars3 += text3.length) > MAX_TEXT_CHARS) throw new PdfReadError("E_BUDGET", `A page makes more than ${MAX_TEXT_CHARS.toLocaleString("en")} characters of text`);
15076
15094
  if (raw) {
@@ -15136,7 +15154,7 @@ function pageText(src, pageDict, resources, raw = false) {
15136
15154
  }
15137
15155
  const n = PT.length - 1;
15138
15156
  if (text3.includes("⁠")) text3 = text3.replaceAll("⁠", "");
15139
- if (text3) add2(x2, y, end, size, text3, d0, d1, d2, d3);
15157
+ if (text3) add2(x2, y, end, size, text3, d0, d1, d2, d3, true);
15140
15158
  else if (n >= 0 && PAE[n] < d1 && PD[n] === d3 && Math.abs(PC[n] - d2) < 0.01) {
15141
15159
  if (raw) PE[n] = end;
15142
15160
  PAE[n] = d1;
@@ -15302,6 +15320,7 @@ function pageText(src, pageDict, resources, raw = false) {
15302
15320
  default:
15303
15321
  }
15304
15322
  }
15323
+ flush();
15305
15324
  if (raw) return PT.map((text3, i2) => ({ x: PX[i2], y: PY[i2], end: PE[i2], size: PS[i2], text: text3, gap: !!(PG[i2] & 1) }));
15306
15325
  const out = [];
15307
15326
  for (let i2 = 0; i2 < PT.length; ) {
@@ -16502,7 +16521,8 @@ async function run(self, sink, o) {
16502
16521
  if (level && o.encrypt) throw new TypeError("save: PDF/A forbids encryption: pass pdfa: false to drop the PDF/A claim and encrypt");
16503
16522
  const keepStruct = single && o.keepStructure !== false && !self.edits.flatten;
16504
16523
  const info = self.info();
16505
- const edited = !!self.edits.info || level?.conformance !== self.pdfa()?.conformance;
16524
+ const tooBig = ["title", "author", "subject", "keywords"].some((k) => typeof info[k] === "string" && info[k].length > INFO_MAX);
16525
+ const edited = !!self.edits.info || tooBig || level?.conformance !== self.pdfa()?.conformance;
16506
16526
  const uaLost = !keepStruct && /pdfuaid:part/.test(self.xmp() ?? "");
16507
16527
  const srcXmp = self.edits.xmp ?? (edited || uaLost || !level && self.pdfa() ? null : self.xmp());
16508
16528
  const created = o.creationDate ?? (info.creationDate instanceof Date ? info.creationDate : /* @__PURE__ */ new Date());
@@ -16938,17 +16958,19 @@ async function saveIncremental(self, o = {}) {
16938
16958
  keepStruct: () => true
16939
16959
  });
16940
16960
  const override = async (n, v) => put(n, await copier.text(self, v), null, v instanceof Map ? v : null);
16941
- let present;
16942
- const objects = [];
16943
- try {
16944
- present = findActive(self, (n, v) => {
16961
+ let scan = SCANS.get(src);
16962
+ if (!scan) try {
16963
+ const objects2 = [];
16964
+ const present2 = findActive(self, (n, v) => {
16945
16965
  const d = v instanceof PdfStream ? v.dict : v;
16946
- if (d instanceof Map && (d.has("ByteRange") || d.has("Perms") || d.has("Lock") || R(d.get("FT")) === "Sig" || d.has("V") || nestedSigs(d).length)) objects.push([n, v]);
16966
+ if (d instanceof Map && (d.has("ByteRange") || d.has("Perms") || d.has("Lock") || R(d.get("FT")) === "Sig" || d.has("V") || nestedSigs(d).length)) objects2.push([n, v]);
16947
16967
  });
16968
+ SCANS.set(src, scan = { present: present2, objects: objects2 });
16948
16969
  } catch (e) {
16949
16970
  throw new PdfReadError("E_ACTIVE", `${who}: the file could not be checked for active content (${/** @type {Error} */
16950
16971
  e.message}); use save() to rewrite the file without it (this invalidates existing signatures)`);
16951
16972
  }
16973
+ const { present, objects } = scan;
16952
16974
  checkSigned(self, sig, o, objects, who);
16953
16975
  if (present.length && !o.keepActiveContent) throw new PdfReadError("E_ACTIVE", `${who}: the file has active content (${present.map((p) => `${p.what} ×${p.count}`).join(", ")}), which an incremental update cannot remove (the original bytes stay). Use save() to rewrite the file without it (this invalidates existing signatures), or pass keepActiveContent: true to keep it knowingly`);
16954
16976
  const fills = await fillReplacements(self, { pdfa: !!self.pdfa(), warn: (m) => warnings.push(m) });
@@ -17400,7 +17422,7 @@ function checkSigned(self, sig, o, objects, who) {
17400
17422
  }
17401
17423
  }
17402
17424
  }
17403
- var SIGN_KEYS, MAX_WIDGET_SHARE, TRANSFORMS, isSigDict;
17425
+ var SIGN_KEYS, SCANS, MAX_WIDGET_SHARE, TRANSFORMS, isSigDict;
17404
17426
  var init_incremental = __esm({
17405
17427
  "src/reader/incremental.js"() {
17406
17428
  init_lexer();
@@ -17416,6 +17438,7 @@ var init_incremental = __esm({
17416
17438
  init_serialize();
17417
17439
  init_serialize();
17418
17440
  SIGN_KEYS = ["field", "signer", "reason", "location", "contactInfo", "name", "date", "timestamp", "subFilter", "reserve", "hash"];
17441
+ SCANS = /* @__PURE__ */ new WeakMap();
17419
17442
  MAX_WIDGET_SHARE = 0.4;
17420
17443
  TRANSFORMS = /* @__PURE__ */ new Set(["DocMDP", "FieldMDP", "UR", "UR3"]);
17421
17444
  isSigDict = (d) => d instanceof Map && d.has("ByteRange") && (d.has("Contents") || d.has("Type") || d.has("Filter"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reportwright/pdf",
3
- "version": "0.1.0-beta.4",
3
+ "version": "0.1.0-beta.5",
4
4
  "description": "A streaming PDF writer for Node and browsers with no runtime dependencies: flat memory, PDF/A-1b to 3a, PDF/UA-1, Factur-X, embedded TrueType with Unicode text.",
5
5
  "type": "module",
6
6
  "license": "MIT",