@pdfme/common 6.1.1-dev.5 → 6.1.1-dev.8

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.
package/dist/index.d.ts CHANGED
@@ -2,9 +2,11 @@ import { PDFME_VERSION } from './version.js';
2
2
  import { MM_TO_PT_RATIO, PT_TO_MM_RATIO, PT_TO_PX_RATIO, BLANK_PDF, BLANK_A4_PDF, CUSTOM_A4_PDF, ZOOM, DEFAULT_FONT_NAME } from './constants.js';
3
3
  import type { ChangeSchemaItem, ChangeSchemas, SchemaPageArray, PropPanel, PropPanelSchema, PropPanelWidgetProps, PDFRenderProps, Mode, UIRenderProps, Plugin, Lang, Dict, Size, Schema, SchemaForUI, Font, ColorType, BasePdf, BlankPdf, CustomPdf, Template, CommonOptions, GeneratorOptions, Plugins, PluginRegistry, GenerateProps, UIOptions, UIProps, PreviewProps, DesignerProps, DynamicLayoutArgs, DynamicLayoutCallbackResult, DynamicLayoutPatchArgs, DynamicLayoutResult, GetDynamicLayout } from './types.js';
4
4
  import type { PdfLinkAnnotationRect } from './helper.js';
5
+ import type { PageOrientation, PageSize, PageSizePreset } from './pageSize.js';
5
6
  import { cloneDeep, getFallbackFontName, getDefaultFont, getB64BasePdf, b64toUint8Array, checkFont, checkInputs, checkUIOptions, checkTemplate, checkUIProps, checkPreviewProps, checkDesignerProps, checkGenerateProps, mm2pt, pt2mm, pt2px, px2mm, isHexValid, getInputFromTemplate, isBlankPdf, isUrlSafeToFetch, getInternalLinkTarget, normalizeInternalLinkHref, normalizeLinkHref, normalizeSafeLinkUri, registerInternalLinkAnchor, registerInternalLinkAnnotation, resetInternalLinkAnnotations, applyInternalLinkAnnotations } from './helper.js';
7
+ import { PAGE_SIZE_PRESETS, detectPaperSize, resolvePageSize } from './pageSize.js';
6
8
  import { getDynamicTemplate } from './dynamicTemplate.js';
7
9
  import { replacePlaceholders } from './expression.js';
8
10
  import { pluginRegistry } from './pluginRegistry.js';
9
- export { PDFME_VERSION, MM_TO_PT_RATIO, PT_TO_MM_RATIO, PT_TO_PX_RATIO, BLANK_PDF, BLANK_A4_PDF, CUSTOM_A4_PDF, ZOOM, DEFAULT_FONT_NAME, cloneDeep, getFallbackFontName, getDefaultFont, getB64BasePdf, b64toUint8Array, mm2pt, pt2mm, pt2px, px2mm, isHexValid, getInputFromTemplate, isBlankPdf, getDynamicTemplate, replacePlaceholders, checkFont, checkInputs, checkUIOptions, checkTemplate, checkUIProps, checkPreviewProps, checkDesignerProps, checkGenerateProps, pluginRegistry, isUrlSafeToFetch, getInternalLinkTarget, normalizeInternalLinkHref, normalizeLinkHref, normalizeSafeLinkUri, registerInternalLinkAnchor, registerInternalLinkAnnotation, resetInternalLinkAnnotations, applyInternalLinkAnnotations, };
10
- export type { Lang, Dict, Size, Schema, SchemaForUI, Font, ColorType, BasePdf, BlankPdf, CustomPdf, Template, CommonOptions, GeneratorOptions, Plugin, Plugins, PluginRegistry, GenerateProps, UIOptions, UIProps, PreviewProps, DesignerProps, ChangeSchemaItem, ChangeSchemas, SchemaPageArray, PropPanel, PropPanelSchema, PropPanelWidgetProps, PDFRenderProps, UIRenderProps, Mode, DynamicLayoutArgs, DynamicLayoutCallbackResult, DynamicLayoutPatchArgs, DynamicLayoutResult, GetDynamicLayout, PdfLinkAnnotationRect, };
11
+ export { PDFME_VERSION, MM_TO_PT_RATIO, PT_TO_MM_RATIO, PT_TO_PX_RATIO, BLANK_PDF, BLANK_A4_PDF, CUSTOM_A4_PDF, ZOOM, DEFAULT_FONT_NAME, cloneDeep, getFallbackFontName, getDefaultFont, getB64BasePdf, b64toUint8Array, mm2pt, pt2mm, pt2px, px2mm, isHexValid, getInputFromTemplate, isBlankPdf, getDynamicTemplate, replacePlaceholders, checkFont, checkInputs, checkUIOptions, checkTemplate, checkUIProps, checkPreviewProps, checkDesignerProps, checkGenerateProps, pluginRegistry, isUrlSafeToFetch, getInternalLinkTarget, normalizeInternalLinkHref, normalizeLinkHref, normalizeSafeLinkUri, registerInternalLinkAnchor, registerInternalLinkAnnotation, resetInternalLinkAnnotations, applyInternalLinkAnnotations, PAGE_SIZE_PRESETS, detectPaperSize, resolvePageSize, };
12
+ export type { Lang, Dict, Size, Schema, SchemaForUI, Font, ColorType, BasePdf, BlankPdf, CustomPdf, Template, CommonOptions, GeneratorOptions, Plugin, Plugins, PluginRegistry, GenerateProps, UIOptions, UIProps, PreviewProps, DesignerProps, ChangeSchemaItem, ChangeSchemas, SchemaPageArray, PropPanel, PropPanelSchema, PropPanelWidgetProps, PDFRenderProps, UIRenderProps, Mode, DynamicLayoutArgs, DynamicLayoutCallbackResult, DynamicLayoutPatchArgs, DynamicLayoutResult, GetDynamicLayout, PdfLinkAnnotationRect, PageOrientation, PageSize, PageSizePreset, };
package/dist/index.js CHANGED
@@ -5,6 +5,70 @@ import * as acorn from "acorn";
5
5
  //#region src/version.ts
6
6
  var PDFME_VERSION = "6.1.1";
7
7
  //#endregion
8
+ //#region src/pageSize.ts
9
+ var PAGE_SIZE_PRESETS = {
10
+ A3: {
11
+ width: 297,
12
+ height: 420
13
+ },
14
+ A4: {
15
+ width: 210,
16
+ height: 297
17
+ },
18
+ A5: {
19
+ width: 148,
20
+ height: 210
21
+ },
22
+ A6: {
23
+ width: 105,
24
+ height: 148
25
+ },
26
+ B4: {
27
+ width: 250,
28
+ height: 353
29
+ },
30
+ B5: {
31
+ width: 176,
32
+ height: 250
33
+ },
34
+ B6: {
35
+ width: 125,
36
+ height: 176
37
+ },
38
+ Letter: {
39
+ width: 215.9,
40
+ height: 279.4
41
+ },
42
+ Legal: {
43
+ width: 215.9,
44
+ height: 355.6
45
+ },
46
+ Tabloid: {
47
+ width: 279.4,
48
+ height: 431.8
49
+ }
50
+ };
51
+ var resolvePageSize = (size = "A4", orientation = "portrait") => {
52
+ const resolved = typeof size === "string" ? PAGE_SIZE_PRESETS[size] : {
53
+ width: size.width,
54
+ height: size.height
55
+ };
56
+ if (!resolved) throw new Error(`@pdfme/common: unknown page size preset "${String(size)}"`);
57
+ if (orientation === "landscape") return {
58
+ width: resolved.height,
59
+ height: resolved.width
60
+ };
61
+ return {
62
+ width: resolved.width,
63
+ height: resolved.height
64
+ };
65
+ };
66
+ var detectPaperSize = (width, height, tolerance = 2) => {
67
+ const entries = Object.entries(PAGE_SIZE_PRESETS);
68
+ for (const [name, size] of entries) if (Math.abs(width - size.width) <= tolerance && Math.abs(height - size.height) <= tolerance || Math.abs(width - size.height) <= tolerance && Math.abs(height - size.width) <= tolerance) return `${name} ${width < height ? "portrait" : "landscape"}`;
69
+ return null;
70
+ };
71
+ //#endregion
8
72
  //#region src/constants.ts
9
73
  var PT_TO_PX_RATIO = 1.333;
10
74
  var PT_TO_MM_RATIO = .3528;
@@ -14,8 +78,7 @@ var ZOOM = 3.7795275591;
14
78
  * Blank A4 PDF size.
15
79
  */
16
80
  var BLANK_A4_PDF = {
17
- width: 210,
18
- height: 297,
81
+ ...PAGE_SIZE_PRESETS.A4,
19
82
  padding: [
20
83
  10,
21
84
  10,
@@ -105,6 +168,9 @@ z.object({
105
168
  "schemas.text.max": z.string(),
106
169
  "schemas.text.fit": z.string(),
107
170
  "schemas.text.dynamicFontSize": z.string(),
171
+ "schemas.text.overflow": z.string(),
172
+ "schemas.text.overflowVisible": z.string(),
173
+ "schemas.text.overflowExpand": z.string(),
108
174
  "schemas.text.format": z.string(),
109
175
  "schemas.text.plain": z.string(),
110
176
  "schemas.text.inlineMarkdown": z.string(),
@@ -179,6 +245,10 @@ var Schema = z.object({
179
245
  start: z.number(),
180
246
  end: z.number().optional()
181
247
  }).optional(),
248
+ __textLineRange: z.object({
249
+ start: z.number(),
250
+ end: z.number().optional()
251
+ }).optional(),
182
252
  __isSplit: z.boolean().optional()
183
253
  }).passthrough();
184
254
  var SchemaForUIAdditionalInfo = z.object({ id: z.string() });
@@ -571,200 +641,6 @@ var checkGenerateProps = (data) => {
571
641
  checkProps(data, GenerateProps);
572
642
  };
573
643
  //#endregion
574
- //#region src/dynamicTemplate.ts
575
- /** Floating point tolerance for comparisons */
576
- var EPSILON = .01;
577
- /** Calculate the content height of a page (drawable area excluding padding) */
578
- var getContentHeight = (basePdf) => basePdf.height - basePdf.padding[0] - basePdf.padding[2];
579
- /** Get the input value for a schema */
580
- var getSchemaValue = (schema, input) => (schema.readOnly ? schema.content : input?.[schema.name]) || "";
581
- /**
582
- * Normalize schemas within a single page into layout items.
583
- * Returns items sorted by Y coordinate with their order preserved.
584
- */
585
- function normalizePageSchemas(pageSchemas, paddingTop) {
586
- const items = [];
587
- const orderMap = /* @__PURE__ */ new Map();
588
- pageSchemas.forEach((schema, index) => {
589
- const localY = Math.max(0, schema.position.y - paddingTop);
590
- items.push({
591
- schema: cloneDeep(schema),
592
- baseY: localY,
593
- height: schema.height,
594
- dynamicLayout: { heights: [schema.height] }
595
- });
596
- orderMap.set(schema.name, index);
597
- });
598
- items.sort((a, b) => {
599
- if (Math.abs(a.baseY - b.baseY) > EPSILON) return a.baseY - b.baseY;
600
- return (orderMap.get(a.schema.name) ?? 0) - (orderMap.get(b.schema.name) ?? 0);
601
- });
602
- return {
603
- items,
604
- orderMap
605
- };
606
- }
607
- /**
608
- * Place height units on pages, splitting across pages as needed.
609
- * @returns The final global Y coordinate after placement
610
- */
611
- function placeUnitsOnPages(schema, dynamicLayout, startGlobalY, contentHeight, paddingTop, pages) {
612
- const dynamicHeights = dynamicLayout.heights;
613
- let currentUnitIndex = 0;
614
- let currentPageIndex = Math.floor(startGlobalY / contentHeight);
615
- let currentYInPage = startGlobalY % contentHeight;
616
- if (currentYInPage < 0) currentYInPage = 0;
617
- let actualGlobalEndY = 0;
618
- const isSplittable = dynamicHeights.length > 1;
619
- while (currentUnitIndex < dynamicHeights.length) {
620
- while (pages.length <= currentPageIndex) pages.push([]);
621
- const spaceLeft = contentHeight - currentYInPage;
622
- if (dynamicHeights[currentUnitIndex] > spaceLeft + EPSILON) {
623
- if (!(Math.abs(spaceLeft - contentHeight) <= EPSILON)) {
624
- currentPageIndex++;
625
- currentYInPage = 0;
626
- continue;
627
- }
628
- }
629
- let chunkHeight = 0;
630
- const startUnitIndex = currentUnitIndex;
631
- while (currentUnitIndex < dynamicHeights.length) {
632
- const h = dynamicHeights[currentUnitIndex];
633
- if (currentYInPage + chunkHeight + h <= contentHeight + EPSILON) {
634
- chunkHeight += h;
635
- currentUnitIndex++;
636
- } else break;
637
- }
638
- const isAtPageTop = currentYInPage <= EPSILON;
639
- if (dynamicLayout.avoidFirstUnitOnly && isSplittable && startUnitIndex === 0 && currentUnitIndex === 1 && dynamicHeights.length > 1 && !isAtPageTop) {
640
- currentUnitIndex = 0;
641
- currentPageIndex++;
642
- currentYInPage = 0;
643
- continue;
644
- }
645
- if (currentUnitIndex === startUnitIndex) {
646
- chunkHeight += dynamicHeights[currentUnitIndex];
647
- currentUnitIndex++;
648
- }
649
- const patch = dynamicLayout.patchSplitSchema?.({
650
- schema,
651
- start: startUnitIndex,
652
- end: currentUnitIndex,
653
- isSplit: startUnitIndex > 0,
654
- chunkHeight
655
- }) ?? {};
656
- const newSchema = {
657
- ...schema,
658
- ...patch,
659
- height: chunkHeight,
660
- position: {
661
- ...schema.position,
662
- y: currentYInPage + paddingTop
663
- }
664
- };
665
- pages[currentPageIndex].push(newSchema);
666
- currentYInPage += chunkHeight;
667
- if (currentYInPage >= contentHeight - EPSILON) {
668
- currentPageIndex++;
669
- currentYInPage = 0;
670
- }
671
- actualGlobalEndY = currentPageIndex * contentHeight + currentYInPage;
672
- }
673
- return actualGlobalEndY;
674
- }
675
- /** Sort elements within each page by their original order */
676
- function sortPagesByOrder(pages, orderMap) {
677
- pages.forEach((page) => {
678
- page.sort((a, b) => (orderMap.get(a.name) ?? 0) - (orderMap.get(b.name) ?? 0));
679
- });
680
- }
681
- /** Remove trailing empty pages */
682
- function removeTrailingEmptyPages(pages) {
683
- while (pages.length > 1 && pages[pages.length - 1].length === 0) pages.pop();
684
- }
685
- /**
686
- * Process a single template page that has dynamic content.
687
- * Uses the same layout algorithm as the original implementation,
688
- * but scoped to a single page's schemas.
689
- */
690
- function processDynamicPage(items, orderMap, contentHeight, paddingTop) {
691
- const pages = [];
692
- let totalYOffset = 0;
693
- for (const item of items) {
694
- const currentGlobalStartY = item.baseY + totalYOffset;
695
- totalYOffset = placeUnitsOnPages(item.schema, item.dynamicLayout, currentGlobalStartY, contentHeight, paddingTop, pages) - (item.baseY + item.height);
696
- }
697
- sortPagesByOrder(pages, orderMap);
698
- removeTrailingEmptyPages(pages);
699
- return pages;
700
- }
701
- var normalizeDynamicLayoutResult = (result) => {
702
- const dynamicLayout = Array.isArray(result) ? { heights: result } : result;
703
- return {
704
- ...dynamicLayout,
705
- heights: dynamicLayout.heights.length === 0 ? [0] : dynamicLayout.heights
706
- };
707
- };
708
- /**
709
- * Process a template containing tables with dynamic heights
710
- * and generate a new template with proper page breaks.
711
- *
712
- * Processing is done page-by-page:
713
- * - Pages with height changes are processed with full layout calculations
714
- * - Pages without height changes are copied as-is (no offset propagation between pages)
715
- *
716
- * This reduces computation cost by:
717
- * 1. Limiting layout calculations to pages that need them
718
- * 2. Avoiding cross-page offset propagation for static pages
719
- */
720
- var getDynamicTemplate = async (arg) => {
721
- const { template, input, options, _cache, getDynamicHeights } = arg;
722
- const basePdf = template.basePdf;
723
- if (!isBlankPdf(basePdf)) return template;
724
- const contentHeight = getContentHeight(basePdf);
725
- const paddingTop = basePdf.padding[0];
726
- const resultPages = [];
727
- const PARALLEL_LIMIT = 10;
728
- for (let pageIndex = 0; pageIndex < template.schemas.length; pageIndex++) {
729
- const pageSchemas = template.schemas[pageIndex];
730
- const { items, orderMap } = normalizePageSchemas(pageSchemas, paddingTop);
731
- for (let i = 0; i < items.length; i += PARALLEL_LIMIT) {
732
- const chunk = items.slice(i, i + PARALLEL_LIMIT);
733
- const chunkResults = await Promise.all(chunk.map((item) => {
734
- return getDynamicHeights(getSchemaValue(item.schema, input), {
735
- schema: item.schema,
736
- basePdf,
737
- options,
738
- _cache
739
- }).then(normalizeDynamicLayoutResult);
740
- }));
741
- for (let j = 0; j < chunkResults.length; j++) items[i + j].dynamicLayout = chunkResults[j];
742
- }
743
- const processedPages = processDynamicPage(items, orderMap, contentHeight, paddingTop);
744
- resultPages.push(...processedPages);
745
- }
746
- removeTrailingEmptyPages(resultPages);
747
- if (resultPages.length === template.schemas.length) {
748
- let unchanged = true;
749
- for (let i = 0; i < resultPages.length && unchanged; i++) {
750
- if (resultPages[i].length !== template.schemas[i].length) {
751
- unchanged = false;
752
- break;
753
- }
754
- for (let j = 0; j < resultPages[i].length && unchanged; j++) {
755
- const orig = template.schemas[i][j];
756
- const result = resultPages[i][j];
757
- if (Math.abs(orig.height - result.height) > EPSILON || Math.abs(orig.position.y - result.position.y) > EPSILON) unchanged = false;
758
- }
759
- }
760
- if (unchanged) return template;
761
- }
762
- return {
763
- basePdf,
764
- schemas: resultPages
765
- };
766
- };
767
- //#endregion
768
644
  //#region src/expression.ts
769
645
  var expressionCache = /* @__PURE__ */ new Map();
770
646
  /**
@@ -1084,6 +960,208 @@ var replacePlaceholders = (arg) => {
1084
960
  });
1085
961
  };
1086
962
  //#endregion
963
+ //#region src/dynamicTemplate.ts
964
+ /** Floating point tolerance for comparisons */
965
+ var EPSILON = .01;
966
+ /** Calculate the content height of a page (drawable area excluding padding) */
967
+ var getContentHeight = (basePdf) => basePdf.height - basePdf.padding[0] - basePdf.padding[2];
968
+ /** Get the input value for a schema */
969
+ var getSchemaValue = (schema, input, schemas) => {
970
+ if (!schema.readOnly) return input?.[schema.name] || "";
971
+ if (schema.type !== "text" && schema.type !== "multiVariableText") return schema.content || "";
972
+ return replacePlaceholders({
973
+ content: schema.content || "",
974
+ variables: input,
975
+ schemas
976
+ });
977
+ };
978
+ /**
979
+ * Normalize schemas within a single page into layout items.
980
+ * Returns items sorted by Y coordinate with their order preserved.
981
+ */
982
+ function normalizePageSchemas(pageSchemas, paddingTop) {
983
+ const items = [];
984
+ const orderMap = /* @__PURE__ */ new Map();
985
+ pageSchemas.forEach((schema, index) => {
986
+ const localY = Math.max(0, schema.position.y - paddingTop);
987
+ items.push({
988
+ schema: cloneDeep(schema),
989
+ baseY: localY,
990
+ height: schema.height,
991
+ dynamicLayout: { heights: [schema.height] }
992
+ });
993
+ orderMap.set(schema.name, index);
994
+ });
995
+ items.sort((a, b) => {
996
+ if (Math.abs(a.baseY - b.baseY) > EPSILON) return a.baseY - b.baseY;
997
+ return (orderMap.get(a.schema.name) ?? 0) - (orderMap.get(b.schema.name) ?? 0);
998
+ });
999
+ return {
1000
+ items,
1001
+ orderMap
1002
+ };
1003
+ }
1004
+ /**
1005
+ * Place height units on pages, splitting across pages as needed.
1006
+ * @returns The final global Y coordinate after placement
1007
+ */
1008
+ function placeUnitsOnPages(schema, dynamicLayout, startGlobalY, contentHeight, paddingTop, pages) {
1009
+ const dynamicHeights = dynamicLayout.heights;
1010
+ let currentUnitIndex = 0;
1011
+ let currentPageIndex = Math.floor(startGlobalY / contentHeight);
1012
+ let currentYInPage = startGlobalY % contentHeight;
1013
+ if (currentYInPage < 0) currentYInPage = 0;
1014
+ let actualGlobalEndY = 0;
1015
+ const isSplittable = dynamicHeights.length > 1;
1016
+ while (currentUnitIndex < dynamicHeights.length) {
1017
+ while (pages.length <= currentPageIndex) pages.push([]);
1018
+ const spaceLeft = contentHeight - currentYInPage;
1019
+ if (dynamicHeights[currentUnitIndex] > spaceLeft + EPSILON) {
1020
+ if (!(Math.abs(spaceLeft - contentHeight) <= EPSILON)) {
1021
+ currentPageIndex++;
1022
+ currentYInPage = 0;
1023
+ continue;
1024
+ }
1025
+ }
1026
+ let chunkHeight = 0;
1027
+ const startUnitIndex = currentUnitIndex;
1028
+ while (currentUnitIndex < dynamicHeights.length) {
1029
+ const h = dynamicHeights[currentUnitIndex];
1030
+ if (currentYInPage + chunkHeight + h <= contentHeight + EPSILON) {
1031
+ chunkHeight += h;
1032
+ currentUnitIndex++;
1033
+ } else break;
1034
+ }
1035
+ const isAtPageTop = currentYInPage <= EPSILON;
1036
+ if (dynamicLayout.avoidFirstUnitOnly && isSplittable && startUnitIndex === 0 && currentUnitIndex === 1 && dynamicHeights.length > 1 && !isAtPageTop) {
1037
+ currentUnitIndex = 0;
1038
+ currentPageIndex++;
1039
+ currentYInPage = 0;
1040
+ continue;
1041
+ }
1042
+ if (currentUnitIndex === startUnitIndex) {
1043
+ chunkHeight += dynamicHeights[currentUnitIndex];
1044
+ currentUnitIndex++;
1045
+ }
1046
+ const patch = dynamicLayout.patchSplitSchema?.({
1047
+ schema,
1048
+ start: startUnitIndex,
1049
+ end: currentUnitIndex,
1050
+ isSplit: startUnitIndex > 0,
1051
+ chunkHeight
1052
+ }) ?? {};
1053
+ const newSchema = {
1054
+ ...schema,
1055
+ ...patch,
1056
+ height: chunkHeight,
1057
+ position: {
1058
+ ...schema.position,
1059
+ y: currentYInPage + paddingTop
1060
+ }
1061
+ };
1062
+ pages[currentPageIndex].push(newSchema);
1063
+ currentYInPage += chunkHeight;
1064
+ if (currentYInPage >= contentHeight - EPSILON) {
1065
+ currentPageIndex++;
1066
+ currentYInPage = 0;
1067
+ }
1068
+ actualGlobalEndY = currentPageIndex * contentHeight + currentYInPage;
1069
+ }
1070
+ return actualGlobalEndY;
1071
+ }
1072
+ /** Sort elements within each page by their original order */
1073
+ function sortPagesByOrder(pages, orderMap) {
1074
+ pages.forEach((page) => {
1075
+ page.sort((a, b) => (orderMap.get(a.name) ?? 0) - (orderMap.get(b.name) ?? 0));
1076
+ });
1077
+ }
1078
+ /** Remove trailing empty pages */
1079
+ function removeTrailingEmptyPages(pages) {
1080
+ while (pages.length > 1 && pages[pages.length - 1].length === 0) pages.pop();
1081
+ }
1082
+ /**
1083
+ * Process a single template page that has dynamic content.
1084
+ * Uses the same layout algorithm as the original implementation,
1085
+ * but scoped to a single page's schemas.
1086
+ */
1087
+ function processDynamicPage(items, orderMap, contentHeight, paddingTop) {
1088
+ const pages = [];
1089
+ let totalYOffset = 0;
1090
+ for (const item of items) {
1091
+ const currentGlobalStartY = item.baseY + totalYOffset;
1092
+ totalYOffset = placeUnitsOnPages(item.schema, item.dynamicLayout, currentGlobalStartY, contentHeight, paddingTop, pages) - (item.baseY + item.height);
1093
+ }
1094
+ sortPagesByOrder(pages, orderMap);
1095
+ removeTrailingEmptyPages(pages);
1096
+ return pages;
1097
+ }
1098
+ var normalizeDynamicLayoutResult = (result) => {
1099
+ const dynamicLayout = Array.isArray(result) ? { heights: result } : result;
1100
+ return {
1101
+ ...dynamicLayout,
1102
+ heights: dynamicLayout.heights.length === 0 ? [0] : dynamicLayout.heights
1103
+ };
1104
+ };
1105
+ /**
1106
+ * Process a template containing tables with dynamic heights
1107
+ * and generate a new template with proper page breaks.
1108
+ *
1109
+ * Processing is done page-by-page:
1110
+ * - Pages with height changes are processed with full layout calculations
1111
+ * - Pages without height changes are copied as-is (no offset propagation between pages)
1112
+ *
1113
+ * This reduces computation cost by:
1114
+ * 1. Limiting layout calculations to pages that need them
1115
+ * 2. Avoiding cross-page offset propagation for static pages
1116
+ */
1117
+ var getDynamicTemplate = async (arg) => {
1118
+ const { template, input, options, _cache, getDynamicHeights } = arg;
1119
+ const basePdf = template.basePdf;
1120
+ if (!isBlankPdf(basePdf)) return template;
1121
+ const contentHeight = getContentHeight(basePdf);
1122
+ const paddingTop = basePdf.padding[0];
1123
+ const resultPages = [];
1124
+ const PARALLEL_LIMIT = 10;
1125
+ for (let pageIndex = 0; pageIndex < template.schemas.length; pageIndex++) {
1126
+ const pageSchemas = template.schemas[pageIndex];
1127
+ const { items, orderMap } = normalizePageSchemas(pageSchemas, paddingTop);
1128
+ for (let i = 0; i < items.length; i += PARALLEL_LIMIT) {
1129
+ const chunk = items.slice(i, i + PARALLEL_LIMIT);
1130
+ const chunkResults = await Promise.all(chunk.map((item) => {
1131
+ return getDynamicHeights(getSchemaValue(item.schema, input, template.schemas), {
1132
+ schema: item.schema,
1133
+ basePdf,
1134
+ options,
1135
+ _cache
1136
+ }).then(normalizeDynamicLayoutResult);
1137
+ }));
1138
+ for (let j = 0; j < chunkResults.length; j++) items[i + j].dynamicLayout = chunkResults[j];
1139
+ }
1140
+ const processedPages = processDynamicPage(items, orderMap, contentHeight, paddingTop);
1141
+ resultPages.push(...processedPages);
1142
+ }
1143
+ removeTrailingEmptyPages(resultPages);
1144
+ if (resultPages.length === template.schemas.length) {
1145
+ let unchanged = true;
1146
+ for (let i = 0; i < resultPages.length && unchanged; i++) {
1147
+ if (resultPages[i].length !== template.schemas[i].length) {
1148
+ unchanged = false;
1149
+ break;
1150
+ }
1151
+ for (let j = 0; j < resultPages[i].length && unchanged; j++) {
1152
+ const orig = template.schemas[i][j];
1153
+ const result = resultPages[i][j];
1154
+ if (Math.abs(orig.height - result.height) > EPSILON || Math.abs(orig.position.y - result.position.y) > EPSILON) unchanged = false;
1155
+ }
1156
+ }
1157
+ if (unchanged) return template;
1158
+ }
1159
+ return {
1160
+ basePdf,
1161
+ schemas: resultPages
1162
+ };
1163
+ };
1164
+ //#endregion
1087
1165
  //#region src/pluginRegistry.ts
1088
1166
  /**
1089
1167
  * Wraps plugins collection with utility methods
@@ -1110,6 +1188,6 @@ var pluginRegistry = (plugins) => {
1110
1188
  };
1111
1189
  };
1112
1190
  //#endregion
1113
- export { BLANK_A4_PDF, BLANK_PDF, CUSTOM_A4_PDF, DEFAULT_FONT_NAME, MM_TO_PT_RATIO, PDFME_VERSION, PT_TO_MM_RATIO, PT_TO_PX_RATIO, ZOOM, applyInternalLinkAnnotations, b64toUint8Array, checkDesignerProps, checkFont, checkGenerateProps, checkInputs, checkPreviewProps, checkTemplate, checkUIOptions, checkUIProps, cloneDeep, getB64BasePdf, getDefaultFont, getDynamicTemplate, getFallbackFontName, getInputFromTemplate, getInternalLinkTarget, isBlankPdf, isHexValid, isUrlSafeToFetch, mm2pt, normalizeInternalLinkHref, normalizeLinkHref, normalizeSafeLinkUri, pluginRegistry, pt2mm, pt2px, px2mm, registerInternalLinkAnchor, registerInternalLinkAnnotation, replacePlaceholders, resetInternalLinkAnnotations };
1191
+ export { BLANK_A4_PDF, BLANK_PDF, CUSTOM_A4_PDF, DEFAULT_FONT_NAME, MM_TO_PT_RATIO, PAGE_SIZE_PRESETS, PDFME_VERSION, PT_TO_MM_RATIO, PT_TO_PX_RATIO, ZOOM, applyInternalLinkAnnotations, b64toUint8Array, checkDesignerProps, checkFont, checkGenerateProps, checkInputs, checkPreviewProps, checkTemplate, checkUIOptions, checkUIProps, cloneDeep, detectPaperSize, getB64BasePdf, getDefaultFont, getDynamicTemplate, getFallbackFontName, getInputFromTemplate, getInternalLinkTarget, isBlankPdf, isHexValid, isUrlSafeToFetch, mm2pt, normalizeInternalLinkHref, normalizeLinkHref, normalizeSafeLinkUri, pluginRegistry, pt2mm, pt2px, px2mm, registerInternalLinkAnchor, registerInternalLinkAnnotation, replacePlaceholders, resetInternalLinkAnnotations, resolvePageSize };
1114
1192
 
1115
1193
  //# sourceMappingURL=index.js.map