modern-pdf-lib 0.13.0 → 0.14.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.
@@ -5,12 +5,26 @@ const encoder = new TextEncoder();
5
5
  /** Format a number for PDF output (no trailing zeros). */
6
6
  function formatNumber(value) {
7
7
  if (Number.isInteger(value)) return value.toString();
8
- const s = value.toFixed(10).replace(/\.?0+$/, "");
9
- return s === "-0" ? "0" : s;
8
+ const s = value.toFixed(10);
9
+ let end = s.length;
10
+ while (end > 0 && s.charCodeAt(end - 1) === 48) end--;
11
+ if (end > 0 && s.charCodeAt(end - 1) === 46) end--;
12
+ const trimmed = end === s.length ? s : s.slice(0, end);
13
+ return trimmed === "-0" ? "0" : trimmed;
10
14
  }
11
15
  /** Escape bytes for a PDF literal string `(…)`. */
12
16
  function escapeLiteralString(str) {
13
- return str.replace(/\\/g, "\\\\").replace(/\(/g, "\\(").replace(/\)/g, "\\)").replace(/\r/g, "\\r").replace(/\n/g, "\\n");
17
+ const parts = [];
18
+ for (let i = 0; i < str.length; i++) {
19
+ const c = str.charCodeAt(i);
20
+ if (c === 92) parts.push("\\\\");
21
+ else if (c === 40) parts.push("\\(");
22
+ else if (c === 41) parts.push("\\)");
23
+ else if (c === 13) parts.push("\\r");
24
+ else if (c === 10) parts.push("\\n");
25
+ else parts.push(str[i]);
26
+ }
27
+ return parts.join("");
14
28
  }
15
29
  /** Convert bytes to hex pairs (delegates to Uint8Array.prototype.toHex). */
16
30
  function bytesToHex(data) {
@@ -116,13 +130,13 @@ var PdfName = class PdfName {
116
130
  return cached;
117
131
  }
118
132
  serialize(writer) {
119
- let encoded = "/";
133
+ const parts = ["/"];
120
134
  for (let i = 1; i < this.value.length; i++) {
121
135
  const code = this.value.charCodeAt(i);
122
- if (code !== void 0 && code >= 33 && code <= 126 && code !== 35) encoded += this.value.at(i);
123
- else encoded += "#" + (code ?? 0).toString(16).padStart(2, "0");
136
+ if (code >= 33 && code <= 126 && code !== 35) parts.push(this.value[i]);
137
+ else parts.push("#" + code.toString(16).padStart(2, "0"));
124
138
  }
125
- writer.writeString(encoded);
139
+ writer.writeString(parts.join(""));
126
140
  }
127
141
  };
128
142
  /** A PDF array `[…]`. */
@@ -133,7 +147,7 @@ var PdfArray = class PdfArray {
133
147
  this.items = items;
134
148
  }
135
149
  static of(items) {
136
- return new PdfArray([...items]);
150
+ return new PdfArray(items.slice());
137
151
  }
138
152
  /** Convenience: create an array of PdfNumbers. */
139
153
  static fromNumbers(values) {
@@ -529,4 +543,4 @@ function buildDocumentStructure(pages, meta, registry, options) {
529
543
 
530
544
  //#endregion
531
545
  export { formatPdfDate as a, PdfBool as c, PdfNull as d, PdfNumber as f, PdfString as g, PdfStream as h, buildPageTree as i, PdfDict as l, PdfRef as m, buildDocumentStructure as n, pdfCatalog_exports as o, PdfObjectRegistry as p, buildInfoDict as r, PdfArray as s, buildCatalog as t, PdfName as u };
532
- //# sourceMappingURL=pdfCatalog-CTfeeqtF.mjs.map
546
+ //# sourceMappingURL=pdfCatalog-BB2Wnmud.mjs.map
@@ -5,12 +5,26 @@ const encoder = new TextEncoder();
5
5
  /** Format a number for PDF output (no trailing zeros). */
6
6
  function formatNumber(value) {
7
7
  if (Number.isInteger(value)) return value.toString();
8
- const s = value.toFixed(10).replace(/\.?0+$/, "");
9
- return s === "-0" ? "0" : s;
8
+ const s = value.toFixed(10);
9
+ let end = s.length;
10
+ while (end > 0 && s.charCodeAt(end - 1) === 48) end--;
11
+ if (end > 0 && s.charCodeAt(end - 1) === 46) end--;
12
+ const trimmed = end === s.length ? s : s.slice(0, end);
13
+ return trimmed === "-0" ? "0" : trimmed;
10
14
  }
11
15
  /** Escape bytes for a PDF literal string `(…)`. */
12
16
  function escapeLiteralString(str) {
13
- return str.replace(/\\/g, "\\\\").replace(/\(/g, "\\(").replace(/\)/g, "\\)").replace(/\r/g, "\\r").replace(/\n/g, "\\n");
17
+ const parts = [];
18
+ for (let i = 0; i < str.length; i++) {
19
+ const c = str.charCodeAt(i);
20
+ if (c === 92) parts.push("\\\\");
21
+ else if (c === 40) parts.push("\\(");
22
+ else if (c === 41) parts.push("\\)");
23
+ else if (c === 13) parts.push("\\r");
24
+ else if (c === 10) parts.push("\\n");
25
+ else parts.push(str[i]);
26
+ }
27
+ return parts.join("");
14
28
  }
15
29
  /** Convert bytes to hex pairs (delegates to Uint8Array.prototype.toHex). */
16
30
  function bytesToHex(data) {
@@ -116,13 +130,13 @@ var PdfName = class PdfName {
116
130
  return cached;
117
131
  }
118
132
  serialize(writer) {
119
- let encoded = "/";
133
+ const parts = ["/"];
120
134
  for (let i = 1; i < this.value.length; i++) {
121
135
  const code = this.value.charCodeAt(i);
122
- if (code !== void 0 && code >= 33 && code <= 126 && code !== 35) encoded += this.value.at(i);
123
- else encoded += "#" + (code ?? 0).toString(16).padStart(2, "0");
136
+ if (code >= 33 && code <= 126 && code !== 35) parts.push(this.value[i]);
137
+ else parts.push("#" + code.toString(16).padStart(2, "0"));
124
138
  }
125
- writer.writeString(encoded);
139
+ writer.writeString(parts.join(""));
126
140
  }
127
141
  };
128
142
  /** A PDF array `[…]`. */
@@ -133,7 +147,7 @@ var PdfArray = class PdfArray {
133
147
  this.items = items;
134
148
  }
135
149
  static of(items) {
136
- return new PdfArray([...items]);
150
+ return new PdfArray(items.slice());
137
151
  }
138
152
  /** Convenience: create an array of PdfNumbers. */
139
153
  static fromNumbers(values) {
@@ -624,4 +638,4 @@ Object.defineProperty(exports, 'pdfCatalog_exports', {
624
638
  return pdfCatalog_exports;
625
639
  }
626
640
  });
627
- //# sourceMappingURL=pdfCatalog-y_XG8Hq1.cjs.map
641
+ //# sourceMappingURL=pdfCatalog-COKoYQ8C.cjs.map
@@ -1,5 +1,5 @@
1
1
  const require_rolldown_runtime = require('./rolldown-runtime-CKhH4XqG.cjs');
2
- const require_pdfCatalog = require('./pdfCatalog-y_XG8Hq1.cjs');
2
+ const require_pdfCatalog = require('./pdfCatalog-COKoYQ8C.cjs');
3
3
 
4
4
  //#region src/core/operators/text.ts
5
5
  /**
@@ -1551,29 +1551,45 @@ const NAMED_COLORS = {
1551
1551
  *
1552
1552
  * @returns RGB values (0-255) or `undefined` if not parseable.
1553
1553
  */
1554
+ /** Cache for parsed SVG colors — high hit rate since SVGs reuse colors. */
1555
+ const colorCache = /* @__PURE__ */ new Map();
1554
1556
  function parseSvgColor(colorStr) {
1555
1557
  if (!colorStr) return void 0;
1558
+ const cached = colorCache.get(colorStr);
1559
+ if (cached !== void 0) return cached;
1560
+ if (colorCache.has(colorStr)) return void 0;
1556
1561
  const s = colorStr.trim().toLowerCase();
1557
- if (s === "none" || s === "transparent") return;
1562
+ if (s === "none" || s === "transparent") {
1563
+ colorCache.set(colorStr, void 0);
1564
+ return;
1565
+ }
1558
1566
  if (s.length === 7 && s[0] === "#") {
1559
1567
  const r = parseInt(s.slice(1, 3), 16);
1560
1568
  const g = parseInt(s.slice(3, 5), 16);
1561
1569
  const b = parseInt(s.slice(5, 7), 16);
1562
- if (!isNaN(r) && !isNaN(g) && !isNaN(b)) return {
1563
- r,
1564
- g,
1565
- b
1566
- };
1570
+ if (!isNaN(r) && !isNaN(g) && !isNaN(b)) {
1571
+ const result = {
1572
+ r,
1573
+ g,
1574
+ b
1575
+ };
1576
+ colorCache.set(colorStr, result);
1577
+ return result;
1578
+ }
1567
1579
  }
1568
1580
  if (s.length === 4 && s[0] === "#") {
1569
1581
  const r = parseInt(s[1] + s[1], 16);
1570
1582
  const g = parseInt(s[2] + s[2], 16);
1571
1583
  const b = parseInt(s[3] + s[3], 16);
1572
- if (!isNaN(r) && !isNaN(g) && !isNaN(b)) return {
1573
- r,
1574
- g,
1575
- b
1576
- };
1584
+ if (!isNaN(r) && !isNaN(g) && !isNaN(b)) {
1585
+ const result = {
1586
+ r,
1587
+ g,
1588
+ b
1589
+ };
1590
+ colorCache.set(colorStr, result);
1591
+ return result;
1592
+ }
1577
1593
  }
1578
1594
  const rgbaMatch = /^rgba?\(\s*([\d.]+)\s*[,\s]\s*([\d.]+)\s*[,\s]\s*([\d.]+)(?:\s*[,/\s]\s*([\d.]+))?\s*\)$/.exec(s);
1579
1595
  if (rgbaMatch) {
@@ -1581,19 +1597,26 @@ function parseSvgColor(colorStr) {
1581
1597
  const g = Math.round(parseFloat(rgbaMatch[2]));
1582
1598
  const b = Math.round(parseFloat(rgbaMatch[3]));
1583
1599
  const a = rgbaMatch[4] !== void 0 ? parseFloat(rgbaMatch[4]) : void 0;
1584
- return {
1600
+ const result = {
1585
1601
  r,
1586
1602
  g,
1587
1603
  b,
1588
1604
  ...a !== void 0 ? { a } : {}
1589
1605
  };
1606
+ colorCache.set(colorStr, result);
1607
+ return result;
1590
1608
  }
1591
1609
  const named = NAMED_COLORS[s];
1592
- if (named) return {
1593
- r: named[0],
1594
- g: named[1],
1595
- b: named[2]
1596
- };
1610
+ if (named) {
1611
+ const result = {
1612
+ r: named[0],
1613
+ g: named[1],
1614
+ b: named[2]
1615
+ };
1616
+ colorCache.set(colorStr, result);
1617
+ return result;
1618
+ }
1619
+ colorCache.set(colorStr, void 0);
1597
1620
  }
1598
1621
  /**
1599
1622
  * Parse an SVG `transform` attribute into a 2D affine matrix.
@@ -5658,4 +5681,4 @@ Object.defineProperty(exports, 'wrapText', {
5658
5681
  return wrapText;
5659
5682
  }
5660
5683
  });
5661
- //# sourceMappingURL=pdfPage-BebMv6fN.cjs.map
5684
+ //# sourceMappingURL=pdfPage-DBfdinTR.cjs.map
@@ -1,5 +1,5 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-95iHPtFO.mjs";
2
- import { a as formatPdfDate, c as PdfBool, f as PdfNumber, g as PdfString, h as PdfStream, l as PdfDict, s as PdfArray, u as PdfName } from "./pdfCatalog-CTfeeqtF.mjs";
2
+ import { a as formatPdfDate, c as PdfBool, f as PdfNumber, g as PdfString, h as PdfStream, l as PdfDict, s as PdfArray, u as PdfName } from "./pdfCatalog-BB2Wnmud.mjs";
3
3
 
4
4
  //#region src/core/operators/text.ts
5
5
  /**
@@ -1551,29 +1551,45 @@ const NAMED_COLORS = {
1551
1551
  *
1552
1552
  * @returns RGB values (0-255) or `undefined` if not parseable.
1553
1553
  */
1554
+ /** Cache for parsed SVG colors — high hit rate since SVGs reuse colors. */
1555
+ const colorCache = /* @__PURE__ */ new Map();
1554
1556
  function parseSvgColor(colorStr) {
1555
1557
  if (!colorStr) return void 0;
1558
+ const cached = colorCache.get(colorStr);
1559
+ if (cached !== void 0) return cached;
1560
+ if (colorCache.has(colorStr)) return void 0;
1556
1561
  const s = colorStr.trim().toLowerCase();
1557
- if (s === "none" || s === "transparent") return;
1562
+ if (s === "none" || s === "transparent") {
1563
+ colorCache.set(colorStr, void 0);
1564
+ return;
1565
+ }
1558
1566
  if (s.length === 7 && s[0] === "#") {
1559
1567
  const r = parseInt(s.slice(1, 3), 16);
1560
1568
  const g = parseInt(s.slice(3, 5), 16);
1561
1569
  const b = parseInt(s.slice(5, 7), 16);
1562
- if (!isNaN(r) && !isNaN(g) && !isNaN(b)) return {
1563
- r,
1564
- g,
1565
- b
1566
- };
1570
+ if (!isNaN(r) && !isNaN(g) && !isNaN(b)) {
1571
+ const result = {
1572
+ r,
1573
+ g,
1574
+ b
1575
+ };
1576
+ colorCache.set(colorStr, result);
1577
+ return result;
1578
+ }
1567
1579
  }
1568
1580
  if (s.length === 4 && s[0] === "#") {
1569
1581
  const r = parseInt(s[1] + s[1], 16);
1570
1582
  const g = parseInt(s[2] + s[2], 16);
1571
1583
  const b = parseInt(s[3] + s[3], 16);
1572
- if (!isNaN(r) && !isNaN(g) && !isNaN(b)) return {
1573
- r,
1574
- g,
1575
- b
1576
- };
1584
+ if (!isNaN(r) && !isNaN(g) && !isNaN(b)) {
1585
+ const result = {
1586
+ r,
1587
+ g,
1588
+ b
1589
+ };
1590
+ colorCache.set(colorStr, result);
1591
+ return result;
1592
+ }
1577
1593
  }
1578
1594
  const rgbaMatch = /^rgba?\(\s*([\d.]+)\s*[,\s]\s*([\d.]+)\s*[,\s]\s*([\d.]+)(?:\s*[,/\s]\s*([\d.]+))?\s*\)$/.exec(s);
1579
1595
  if (rgbaMatch) {
@@ -1581,19 +1597,26 @@ function parseSvgColor(colorStr) {
1581
1597
  const g = Math.round(parseFloat(rgbaMatch[2]));
1582
1598
  const b = Math.round(parseFloat(rgbaMatch[3]));
1583
1599
  const a = rgbaMatch[4] !== void 0 ? parseFloat(rgbaMatch[4]) : void 0;
1584
- return {
1600
+ const result = {
1585
1601
  r,
1586
1602
  g,
1587
1603
  b,
1588
1604
  ...a !== void 0 ? { a } : {}
1589
1605
  };
1606
+ colorCache.set(colorStr, result);
1607
+ return result;
1590
1608
  }
1591
1609
  const named = NAMED_COLORS[s];
1592
- if (named) return {
1593
- r: named[0],
1594
- g: named[1],
1595
- b: named[2]
1596
- };
1610
+ if (named) {
1611
+ const result = {
1612
+ r: named[0],
1613
+ g: named[1],
1614
+ b: named[2]
1615
+ };
1616
+ colorCache.set(colorStr, result);
1617
+ return result;
1618
+ }
1619
+ colorCache.set(colorStr, void 0);
1597
1620
  }
1598
1621
  /**
1599
1622
  * Parse an SVG `transform` attribute into a 2D affine matrix.
@@ -4969,4 +4992,4 @@ var PdfPage = class PdfPage {
4969
4992
 
4970
4993
  //#endregion
4971
4994
  export { colorToComponents as $, setTextMatrix as $t, beginMarkedContent as A, fill as At, radians as B, setLineJoin as Bt, AnnotationFlags as C, closeFillEvenOddAndStroke as Ct, createAnnotation as D, curveToInitial as Dt, buildAnnotationDict as E, curveToFinal as Et, endMarkedContent as F, moveTo as Ft, saveState as G, endText as Gt, restoreState as H, setMiterLimit as Ht, wrapInMarkedContent as I, rectangle as It, skew as J, nextLine as Jt, scale as K, moveText as Kt, concatMatrix as L, setDashPattern as Lt, beginMarkedContentWithProperties as M, fillEvenOdd as Mt, createMarkedContentScope as N, fillEvenOddAndStroke as Nt, beginArtifact as O, ellipsePath as Ot, endArtifact as P, lineTo as Pt, cmyk as Q, setLeading as Qt, degrees as R, setFlatness as Rt, parseSvgTransform as S, closeFillAndStroke as St, annotationFromDict as T, curveTo as Tt, rotate as U, stroke as Ut, radiansToDegrees as V, setLineWidth as Vt, rotationMatrix as W, beginText as Wt, applyFillColor as X, setFont as Xt, translate as Y, setCharacterSpacing as Yt, applyStrokeColor as Z, setFontSize as Zt, drawSvgOnPage as _, drawXObject as _t, buildGradientObjects as a, showTextHex as an, setFillColorCmyk as at, parseSvgColor as b, clipEvenOdd as bt, radialGradient as c, setFillingColor as ct, getRedactionMarks as d, setStrokeColorGray as dt, setTextRenderingMode as en, componentsToColor as et, markForRedaction as f, setStrokeColorRgb as ft, endLayerContent as g, drawImageXObject as gt, beginLayerContent as h, drawImageWithMatrix as ht, wrapText as i, showTextArray as in, setFillColor as it, beginMarkedContentSequence as j, fillAndStroke as jt, beginArtifactWithType as k, endPath as kt, tilingPattern as l, setStrokeColor as lt, PdfLayerManager as m, setStrokingColor as mt, PdfPage as n, setWordSpacing as nn, rgb as nt, buildPatternObjects as o, showTextNextLine as on, setFillColorGray as ot, PdfLayer as p, setStrokeColorSpace as pt, setGraphicsState as q, moveTextSetLeading as qt, pdfPage_exports as r, showText as rn, setColorSpace as rt, linearGradient as s, showTextWithSpacing as sn, setFillColorRgb as st, PageSizes as t, setTextRise as tn, grayscale as tt, applyRedactions as u, setStrokeColorCmyk as ut, svgToPdfOperators as v, circlePath as vt, PdfAnnotation as w, closePath as wt, parseSvgPath as x, closeAndStroke as xt, parseSvg as y, clip as yt, degreesToRadians as z, setLineCap as zt };
4972
- //# sourceMappingURL=pdfPage-B7vA518n.mjs.map
4995
+ //# sourceMappingURL=pdfPage-N1K2U3jI.mjs.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "modern-pdf-lib",
3
- "version": "0.13.0",
3
+ "version": "0.14.1",
4
4
  "description": "A modern, WASM-accelerated PDF creation engine for every JavaScript runtime",
5
5
  "type": "module",
6
6
  "exports": {