@pdfme/common 6.2.4 → 6.2.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.
@@ -1,4 +1,10 @@
1
1
  import type { Schema, SchemaPageArray } from './types.js';
2
+ /**
3
+ * False only for strings JSON.parse would reject, so parseData can skip the throw. Index scans, not
4
+ * regexes: V8 keeps the subject of the last successful match (RegExp.input), which would pin a large
5
+ * value after the call.
6
+ */
7
+ export declare const mayBeJson: (value: string) => boolean;
2
8
  /**
3
9
  * Resolve a read-only schema's render value.
4
10
  * Text `content` is an expression template. MVT `content` is a variable JSON
package/dist/helper.d.ts CHANGED
@@ -2,6 +2,11 @@ import type { PDFDocument, PDFPage } from '@pdfme/pdf-lib';
2
2
  import { Template, Font, BasePdf, Plugins, BlankPdf, PdfBytes } from './types.js';
3
3
  export declare const cloneDeep: <T>(value: T) => T;
4
4
  export declare const getFallbackFontName: (font: Font) => string;
5
+ /**
6
+ * The built-in fallback font. Every call returns a new Font object around the same bytes, decoded
7
+ * once and kept for the life of the process: do not modify or transfer them (e.g. in a
8
+ * postMessage transfer list).
9
+ */
5
10
  export declare const getDefaultFont: () => Font;
6
11
  export declare const mm2pt: (mm: number) => number;
7
12
  export declare const pt2mm: (pt: number) => number;
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import { Buffer } from "buffer";
3
3
  import { PDFName } from "@pdfme/pdf-lib";
4
4
  import * as acorn from "acorn";
5
5
  //#region src/version.ts
6
- var PDFME_VERSION = "6.2.4";
6
+ var PDFME_VERSION = "6.2.5";
7
7
  //#endregion
8
8
  //#region src/pageSize.ts
9
9
  var PAGE_SIZE_PRESETS = {
@@ -373,10 +373,19 @@ var getFallbackFontName = (font) => {
373
373
  if (fallbackFontName === initial) throw Error(`[@pdfme/common] fallback flag is not found in font. true fallback flag must be only one.`);
374
374
  return fallbackFontName;
375
375
  };
376
- var getDefaultFont = () => ({ [DEFAULT_FONT_NAME]: {
377
- data: b64toUint8Array(DEFAULT_FONT_VALUE),
378
- fallback: true
379
- } });
376
+ var defaultFontData;
377
+ /**
378
+ * The built-in fallback font. Every call returns a new Font object around the same bytes, decoded
379
+ * once and kept for the life of the process: do not modify or transfer them (e.g. in a
380
+ * postMessage transfer list).
381
+ */
382
+ var getDefaultFont = () => {
383
+ if (!defaultFontData) defaultFontData = b64toUint8Array(DEFAULT_FONT_VALUE);
384
+ return { [DEFAULT_FONT_NAME]: {
385
+ data: defaultFontData,
386
+ fallback: true
387
+ } };
388
+ };
380
389
  var mm2pt = (mm) => {
381
390
  return parseFloat(String(mm)) * MM_TO_PT_RATIO;
382
391
  };
@@ -665,6 +674,50 @@ var checkGenerateProps = (data) => {
665
674
  //#endregion
666
675
  //#region src/expression.ts
667
676
  var expressionCache = /* @__PURE__ */ new Map();
677
+ var isJsonWhitespace = (ch) => ch === " " || ch === " " || ch === "\n" || ch === "\r";
678
+ var isDigit = (ch) => ch !== void 0 && ch >= "0" && ch <= "9";
679
+ var isJsonNumber = (value, start, end) => {
680
+ let i = start;
681
+ if (value[i] === "-") i++;
682
+ if (!isDigit(value[i])) return false;
683
+ if (value[i] === "0") i++;
684
+ else while (i < end && isDigit(value[i])) i++;
685
+ if (value[i] === ".") {
686
+ const digits = ++i;
687
+ while (i < end && isDigit(value[i])) i++;
688
+ if (i === digits) return false;
689
+ }
690
+ if (value[i] === "e" || value[i] === "E") {
691
+ i++;
692
+ if (value[i] === "+" || value[i] === "-") i++;
693
+ const digits = i;
694
+ while (i < end && isDigit(value[i])) i++;
695
+ if (i === digits) return false;
696
+ }
697
+ return i === end;
698
+ };
699
+ /**
700
+ * False only for strings JSON.parse would reject, so parseData can skip the throw. Index scans, not
701
+ * regexes: V8 keeps the subject of the last successful match (RegExp.input), which would pin a large
702
+ * value after the call.
703
+ */
704
+ var mayBeJson = (value) => {
705
+ let start = 0;
706
+ let end = value.length;
707
+ while (start < end && isJsonWhitespace(value[start])) start++;
708
+ while (end > start && isJsonWhitespace(value[end - 1])) end--;
709
+ const first = value[start];
710
+ if (first === "{") {
711
+ let i = start + 1;
712
+ while (i < end && isJsonWhitespace(value[i])) i++;
713
+ return value[i] === "\"" || value[i] === "}";
714
+ }
715
+ if (first === "[" || first === "\"") return true;
716
+ if (first === "t") return end - start === 4 && value.startsWith("true", start);
717
+ if (first === "f") return end - start === 5 && value.startsWith("false", start);
718
+ if (first === "n") return end - start === 4 && value.startsWith("null", start);
719
+ return isJsonNumber(value, start, end);
720
+ };
668
721
  /**
669
722
  * Parse each string value in `data` as JSON, falling back to the original
670
723
  * string on failure. Previously memoized via a module-level `parseDataCache`
@@ -674,10 +727,14 @@ var expressionCache = /* @__PURE__ */ new Map();
674
727
  * base64 (e.g. image schemas) or inputs containing base64 values. Every
675
728
  * unique inputs state pinned its own multi-MB key for the app lifetime.
676
729
  * Parsing is O(fields) and cheap; removing the cache is strictly a win.
730
+ *
731
+ * It is called once per placeholder field, over every field, so most strings are not JSON and
732
+ * a thrown SyntaxError each made it the bulk of a render. Strings that cannot be JSON skip
733
+ * JSON.parse (see mayBeJson); the result is the same.
677
734
  */
678
735
  var parseData = (data) => {
679
736
  return Object.fromEntries(Object.entries(data).map(([key, value]) => {
680
- if (typeof value === "string") try {
737
+ if (typeof value === "string" && mayBeJson(value)) try {
681
738
  return [key, JSON.parse(value)];
682
739
  } catch {
683
740
  return [key, value];