av6-pdf-engine 1.0.1 → 1.0.3

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 (178) hide show
  1. package/.prettierignore +4 -0
  2. package/.prettierrc +6 -0
  3. package/README.md +4 -14
  4. package/dist/index.d.mts +296 -0
  5. package/dist/index.d.ts +296 -3
  6. package/dist/index.js +1979 -18
  7. package/dist/index.mjs +1940 -0
  8. package/package.json +12 -25
  9. package/dist/index.d.ts.map +0 -1
  10. package/dist/index.js.map +0 -1
  11. package/dist/renderer-engine/blocks/barcode.d.ts +0 -3
  12. package/dist/renderer-engine/blocks/barcode.d.ts.map +0 -1
  13. package/dist/renderer-engine/blocks/barcode.js +0 -47
  14. package/dist/renderer-engine/blocks/barcode.js.map +0 -1
  15. package/dist/renderer-engine/blocks/columns.d.ts +0 -3
  16. package/dist/renderer-engine/blocks/columns.d.ts.map +0 -1
  17. package/dist/renderer-engine/blocks/columns.js +0 -105
  18. package/dist/renderer-engine/blocks/columns.js.map +0 -1
  19. package/dist/renderer-engine/blocks/image.d.ts +0 -4
  20. package/dist/renderer-engine/blocks/image.d.ts.map +0 -1
  21. package/dist/renderer-engine/blocks/image.js +0 -57
  22. package/dist/renderer-engine/blocks/image.js.map +0 -1
  23. package/dist/renderer-engine/blocks/index.d.ts +0 -8
  24. package/dist/renderer-engine/blocks/index.d.ts.map +0 -1
  25. package/dist/renderer-engine/blocks/index.js +0 -24
  26. package/dist/renderer-engine/blocks/index.js.map +0 -1
  27. package/dist/renderer-engine/blocks/key-value-grid.d.ts +0 -3
  28. package/dist/renderer-engine/blocks/key-value-grid.d.ts.map +0 -1
  29. package/dist/renderer-engine/blocks/key-value-grid.js +0 -245
  30. package/dist/renderer-engine/blocks/key-value-grid.js.map +0 -1
  31. package/dist/renderer-engine/blocks/line.d.ts +0 -3
  32. package/dist/renderer-engine/blocks/line.d.ts.map +0 -1
  33. package/dist/renderer-engine/blocks/line.js +0 -35
  34. package/dist/renderer-engine/blocks/line.js.map +0 -1
  35. package/dist/renderer-engine/blocks/table.d.ts +0 -4
  36. package/dist/renderer-engine/blocks/table.d.ts.map +0 -1
  37. package/dist/renderer-engine/blocks/table.js +0 -201
  38. package/dist/renderer-engine/blocks/table.js.map +0 -1
  39. package/dist/renderer-engine/blocks/text.d.ts +0 -3
  40. package/dist/renderer-engine/blocks/text.d.ts.map +0 -1
  41. package/dist/renderer-engine/blocks/text.js +0 -52
  42. package/dist/renderer-engine/blocks/text.js.map +0 -1
  43. package/dist/renderer-engine/index.d.ts +0 -4
  44. package/dist/renderer-engine/index.d.ts.map +0 -1
  45. package/dist/renderer-engine/index.js +0 -215
  46. package/dist/renderer-engine/index.js.map +0 -1
  47. package/dist/renderer-engine/utils/block-renderer.d.ts +0 -17
  48. package/dist/renderer-engine/utils/block-renderer.d.ts.map +0 -1
  49. package/dist/renderer-engine/utils/block-renderer.js +0 -86
  50. package/dist/renderer-engine/utils/block-renderer.js.map +0 -1
  51. package/dist/renderer-engine/utils/context.d.ts +0 -3
  52. package/dist/renderer-engine/utils/context.d.ts.map +0 -1
  53. package/dist/renderer-engine/utils/context.js +0 -16
  54. package/dist/renderer-engine/utils/context.js.map +0 -1
  55. package/dist/renderer-engine/utils/ensure-space.d.ts +0 -9
  56. package/dist/renderer-engine/utils/ensure-space.d.ts.map +0 -1
  57. package/dist/renderer-engine/utils/ensure-space.js +0 -18
  58. package/dist/renderer-engine/utils/ensure-space.js.map +0 -1
  59. package/dist/renderer-engine/utils/env.d.ts +0 -3
  60. package/dist/renderer-engine/utils/env.d.ts.map +0 -1
  61. package/dist/renderer-engine/utils/env.js +0 -10
  62. package/dist/renderer-engine/utils/env.js.map +0 -1
  63. package/dist/renderer-engine/utils/finish-page.d.ts +0 -13
  64. package/dist/renderer-engine/utils/finish-page.d.ts.map +0 -1
  65. package/dist/renderer-engine/utils/finish-page.js +0 -27
  66. package/dist/renderer-engine/utils/finish-page.js.map +0 -1
  67. package/dist/renderer-engine/utils/footer.d.ts +0 -3
  68. package/dist/renderer-engine/utils/footer.d.ts.map +0 -1
  69. package/dist/renderer-engine/utils/footer.js +0 -89
  70. package/dist/renderer-engine/utils/footer.js.map +0 -1
  71. package/dist/renderer-engine/utils/header.d.ts +0 -3
  72. package/dist/renderer-engine/utils/header.d.ts.map +0 -1
  73. package/dist/renderer-engine/utils/header.js +0 -47
  74. package/dist/renderer-engine/utils/header.js.map +0 -1
  75. package/dist/renderer-engine/utils/image-loader.d.ts +0 -4
  76. package/dist/renderer-engine/utils/image-loader.d.ts.map +0 -1
  77. package/dist/renderer-engine/utils/image-loader.js +0 -52
  78. package/dist/renderer-engine/utils/image-loader.js.map +0 -1
  79. package/dist/renderer-engine/utils/index.d.ts +0 -19
  80. package/dist/renderer-engine/utils/index.d.ts.map +0 -1
  81. package/dist/renderer-engine/utils/index.js +0 -35
  82. package/dist/renderer-engine/utils/index.js.map +0 -1
  83. package/dist/renderer-engine/utils/layout.d.ts +0 -8
  84. package/dist/renderer-engine/utils/layout.d.ts.map +0 -1
  85. package/dist/renderer-engine/utils/layout.js +0 -22
  86. package/dist/renderer-engine/utils/layout.js.map +0 -1
  87. package/dist/renderer-engine/utils/measure-block-height.d.ts +0 -8
  88. package/dist/renderer-engine/utils/measure-block-height.d.ts.map +0 -1
  89. package/dist/renderer-engine/utils/measure-block-height.js +0 -220
  90. package/dist/renderer-engine/utils/measure-block-height.js.map +0 -1
  91. package/dist/renderer-engine/utils/page-background.d.ts +0 -6
  92. package/dist/renderer-engine/utils/page-background.d.ts.map +0 -1
  93. package/dist/renderer-engine/utils/page-background.js +0 -30
  94. package/dist/renderer-engine/utils/page-background.js.map +0 -1
  95. package/dist/renderer-engine/utils/page-flow.d.ts +0 -3
  96. package/dist/renderer-engine/utils/page-flow.d.ts.map +0 -1
  97. package/dist/renderer-engine/utils/page-flow.js +0 -9
  98. package/dist/renderer-engine/utils/page-flow.js.map +0 -1
  99. package/dist/renderer-engine/utils/page-limit.d.ts +0 -8
  100. package/dist/renderer-engine/utils/page-limit.d.ts.map +0 -1
  101. package/dist/renderer-engine/utils/page-limit.js +0 -15
  102. package/dist/renderer-engine/utils/page-limit.js.map +0 -1
  103. package/dist/renderer-engine/utils/qr-bar-code.d.ts +0 -17
  104. package/dist/renderer-engine/utils/qr-bar-code.d.ts.map +0 -1
  105. package/dist/renderer-engine/utils/qr-bar-code.js +0 -141
  106. package/dist/renderer-engine/utils/qr-bar-code.js.map +0 -1
  107. package/dist/renderer-engine/utils/signature.d.ts +0 -20
  108. package/dist/renderer-engine/utils/signature.d.ts.map +0 -1
  109. package/dist/renderer-engine/utils/signature.js +0 -214
  110. package/dist/renderer-engine/utils/signature.js.map +0 -1
  111. package/dist/renderer-engine/utils/start-page-layout.d.ts +0 -20
  112. package/dist/renderer-engine/utils/start-page-layout.d.ts.map +0 -1
  113. package/dist/renderer-engine/utils/start-page-layout.js +0 -34
  114. package/dist/renderer-engine/utils/start-page-layout.js.map +0 -1
  115. package/dist/renderer-engine/utils/styles.d.ts +0 -7
  116. package/dist/renderer-engine/utils/styles.d.ts.map +0 -1
  117. package/dist/renderer-engine/utils/styles.js +0 -124
  118. package/dist/renderer-engine/utils/styles.js.map +0 -1
  119. package/dist/renderer-engine/utils/watermark.d.ts +0 -11
  120. package/dist/renderer-engine/utils/watermark.d.ts.map +0 -1
  121. package/dist/renderer-engine/utils/watermark.js +0 -57
  122. package/dist/renderer-engine/utils/watermark.js.map +0 -1
  123. package/dist/types/barcode.d.ts +0 -23
  124. package/dist/types/barcode.d.ts.map +0 -1
  125. package/dist/types/barcode.js +0 -11
  126. package/dist/types/barcode.js.map +0 -1
  127. package/dist/types/columns.d.ts +0 -14
  128. package/dist/types/columns.d.ts.map +0 -1
  129. package/dist/types/columns.js +0 -3
  130. package/dist/types/columns.js.map +0 -1
  131. package/dist/types/common.d.ts +0 -102
  132. package/dist/types/common.d.ts.map +0 -1
  133. package/dist/types/common.js +0 -3
  134. package/dist/types/common.js.map +0 -1
  135. package/dist/types/context.d.ts +0 -17
  136. package/dist/types/context.d.ts.map +0 -1
  137. package/dist/types/context.js +0 -3
  138. package/dist/types/context.js.map +0 -1
  139. package/dist/types/image.d.ts +0 -13
  140. package/dist/types/image.d.ts.map +0 -1
  141. package/dist/types/image.js +0 -3
  142. package/dist/types/image.js.map +0 -1
  143. package/dist/types/index.d.ts +0 -13
  144. package/dist/types/index.d.ts.map +0 -1
  145. package/dist/types/index.js +0 -29
  146. package/dist/types/index.js.map +0 -1
  147. package/dist/types/key-value-grid.d.ts +0 -34
  148. package/dist/types/key-value-grid.d.ts.map +0 -1
  149. package/dist/types/key-value-grid.js +0 -3
  150. package/dist/types/key-value-grid.js.map +0 -1
  151. package/dist/types/line.d.ts +0 -11
  152. package/dist/types/line.d.ts.map +0 -1
  153. package/dist/types/line.js +0 -3
  154. package/dist/types/line.js.map +0 -1
  155. package/dist/types/page-break.d.ts +0 -5
  156. package/dist/types/page-break.d.ts.map +0 -1
  157. package/dist/types/page-break.js +0 -3
  158. package/dist/types/page-break.js.map +0 -1
  159. package/dist/types/qr.d.ts +0 -22
  160. package/dist/types/qr.d.ts.map +0 -1
  161. package/dist/types/qr.js +0 -10
  162. package/dist/types/qr.js.map +0 -1
  163. package/dist/types/signature.d.ts +0 -12
  164. package/dist/types/signature.d.ts.map +0 -1
  165. package/dist/types/signature.js +0 -3
  166. package/dist/types/signature.js.map +0 -1
  167. package/dist/types/table.d.ts +0 -32
  168. package/dist/types/table.d.ts.map +0 -1
  169. package/dist/types/table.js +0 -3
  170. package/dist/types/table.js.map +0 -1
  171. package/dist/types/text.d.ts +0 -19
  172. package/dist/types/text.d.ts.map +0 -1
  173. package/dist/types/text.js +0 -3
  174. package/dist/types/text.js.map +0 -1
  175. package/dist/types/utility.d.ts +0 -1
  176. package/dist/types/utility.d.ts.map +0 -1
  177. package/dist/types/utility.js +0 -2
  178. package/dist/types/utility.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,19 +1,1980 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./renderer-engine"), exports);
18
- __exportStar(require("./types"), exports);
19
- //# sourceMappingURL=index.js.map
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ BARCODE_TYPES: () => BARCODE_TYPES,
34
+ QR_ERROR_LEVEL: () => QR_ERROR_LEVEL,
35
+ renderCustomPdf: () => renderCustomPdf,
36
+ renderCustomPdfToBuffer: () => renderCustomPdfToBuffer
37
+ });
38
+ module.exports = __toCommonJS(index_exports);
39
+
40
+ // src/renderer-engine/index.ts
41
+ var import_fs = __toESM(require("fs"));
42
+ var import_pdfkit = __toESM(require("pdfkit"));
43
+
44
+ // src/renderer-engine/blocks/barcode.ts
45
+ var processBarcodeBlock = (doc, ctx, block, y, env, ensureSpaceFor) => {
46
+ const imgSource = block.src;
47
+ const imgWidth = block.width ?? 120;
48
+ const imgHeight = block.height ?? 40;
49
+ const localLeft = block.marginLeft ?? 0;
50
+ const localRight = block.marginRight ?? 0;
51
+ const baseLeft = env.marginLeft + localLeft;
52
+ const availableWidth = Math.max(env.innerWidth - localLeft - localRight, 1);
53
+ const mt = block.marginTop ?? 0;
54
+ const mb = block.marginBottom ?? 0;
55
+ const baseY = y ?? ctx.currentY;
56
+ const startY = baseY + mt;
57
+ const heightNeeded = mt + imgHeight + mb;
58
+ if (y === null) {
59
+ ensureSpaceFor(heightNeeded, env);
60
+ }
61
+ let x = baseLeft;
62
+ if (block.align === "center") {
63
+ x = baseLeft + (availableWidth - imgWidth) / 2;
64
+ } else if (block.align === "right") {
65
+ x = baseLeft + availableWidth - imgWidth;
66
+ }
67
+ const rotation = typeof block.rotate === "number" ? block.rotate : block.orientation === "vertical" ? 90 : 0;
68
+ try {
69
+ drawRotatedImage(doc, imgSource, x, startY, imgWidth, imgHeight, rotation);
70
+ } catch (e) {
71
+ console.warn("Failed to load barcode image:", e);
72
+ }
73
+ const newY = startY + imgHeight + mb;
74
+ if (y === null) ctx.currentY = newY;
75
+ return newY;
76
+ };
77
+
78
+ // src/renderer-engine/blocks/columns.ts
79
+ var processColumnsBlock = (ctx, block, y, env, computeColumnPixelWidths2, renderBlock, ensureSpaceFor, measureBlockHeight) => {
80
+ const blockLeft = block.marginLeft ?? 0;
81
+ const blockRight = block.marginRight ?? 0;
82
+ const baseLeft = env.marginLeft + blockLeft;
83
+ const totalWidth = Math.max(env.innerWidth - blockLeft - blockRight, 1);
84
+ const mt = block.marginTop ?? 0;
85
+ const mb = block.marginBottom ?? 0;
86
+ const cols = block.columns ?? [];
87
+ const n = cols.length;
88
+ if (!n) {
89
+ const baseY0 = y ?? ctx.currentY;
90
+ const endY = baseY0 + mt + mb;
91
+ if (y === null) ctx.currentY = endY;
92
+ return endY;
93
+ }
94
+ let colWidths;
95
+ const mode = block.mode ?? "fixedGap";
96
+ let gap;
97
+ if (mode === "spaceBetween" && n > 1) {
98
+ if (block.widths && block.widths.length === n) {
99
+ colWidths = computeColumnPixelWidths2(block.widths, totalWidth);
100
+ } else {
101
+ colWidths = Array(n).fill(totalWidth / n);
102
+ }
103
+ const totalColsWidth = colWidths.reduce((a, b) => a + b, 0);
104
+ const remaining = Math.max(totalWidth - totalColsWidth, 0);
105
+ gap = remaining / (n - 1);
106
+ } else {
107
+ gap = block.gap ?? 20;
108
+ const totalGapsWidth = gap * (n - 1);
109
+ const widthForCols = Math.max(totalWidth - totalGapsWidth, 1);
110
+ if (block.widths && block.widths.length === n) {
111
+ colWidths = computeColumnPixelWidths2(block.widths, widthForCols);
112
+ } else {
113
+ colWidths = Array(n).fill(widthForCols / n);
114
+ }
115
+ }
116
+ const xBases = [];
117
+ {
118
+ let x = baseLeft;
119
+ for (let i = 0; i < n; i++) {
120
+ xBases.push(x);
121
+ x += colWidths[i] + (i < n - 1 ? gap : 0);
122
+ }
123
+ }
124
+ const measureColHeights = [];
125
+ for (let colIndex = 0; colIndex < n; colIndex++) {
126
+ const colEnvMeasure = {
127
+ marginLeft: 0,
128
+ innerWidth: colWidths[colIndex],
129
+ allowPageBreak: false
130
+ // measure as keep-together
131
+ };
132
+ let h = 0;
133
+ for (const b of cols[colIndex]) {
134
+ if (b.visible === false) continue;
135
+ h += measureBlockHeight(b, colEnvMeasure);
136
+ }
137
+ measureColHeights.push(h);
138
+ }
139
+ const maxColHeight = Math.max(...measureColHeights, 0);
140
+ const totalHeightNeeded = mt + maxColHeight + mb;
141
+ if (y === null) {
142
+ ensureSpaceFor(totalHeightNeeded, env);
143
+ }
144
+ const baseY = y ?? ctx.currentY;
145
+ const startY = baseY + mt;
146
+ const heights = [];
147
+ for (let colIndex = 0; colIndex < n; colIndex++) {
148
+ const colEnv = {
149
+ marginLeft: xBases[colIndex],
150
+ innerWidth: colWidths[colIndex],
151
+ allowPageBreak: false
152
+ // keep whole column block intact on one page
153
+ };
154
+ let colY = startY;
155
+ for (const b of cols[colIndex]) {
156
+ if (b.visible === false) continue;
157
+ colY = renderBlock(b, colY, colEnv);
158
+ }
159
+ heights.push(colY - startY);
160
+ }
161
+ const maxHeight = Math.max(...heights, 0);
162
+ const newY = startY + maxHeight + mb;
163
+ if (y === null) ctx.currentY = newY;
164
+ return newY;
165
+ };
166
+
167
+ // src/renderer-engine/blocks/image.ts
168
+ var drawRotatedImage = (doc, src, x, y, width, height, rotationDeg) => {
169
+ if (!rotationDeg) {
170
+ doc.image(src, x, y, { width, height });
171
+ return;
172
+ }
173
+ const cx = x + width / 2;
174
+ const cy = y + height / 2;
175
+ doc.save();
176
+ doc.rotate(rotationDeg, { origin: [cx, cy] });
177
+ doc.image(src, x, y, { width, height });
178
+ doc.restore();
179
+ };
180
+ var processImageBlock = (doc, ctx, block, y, env, ensureSpaceFor) => {
181
+ const imgSource = block.src;
182
+ const imgWidth = block.width ?? 80;
183
+ const imgHeight = block.height ?? 50;
184
+ const localLeft = block.marginLeft ?? 0;
185
+ const localRight = block.marginRight ?? 0;
186
+ const baseLeft = env.marginLeft + localLeft;
187
+ const availableWidth = Math.max(env.innerWidth - localLeft - localRight, 1);
188
+ const mt = block.marginTop ?? 0;
189
+ const mb = block.marginBottom ?? 0;
190
+ const baseY = y ?? ctx.currentY;
191
+ const startY = baseY + mt;
192
+ const heightNeeded = mt + imgHeight + mb;
193
+ if (y === null) {
194
+ ensureSpaceFor(heightNeeded, env);
195
+ }
196
+ let x = baseLeft;
197
+ if (block.align === "center") {
198
+ x = baseLeft + (availableWidth - imgWidth) / 2;
199
+ } else if (block.align === "right") {
200
+ x = baseLeft + availableWidth - imgWidth;
201
+ }
202
+ try {
203
+ doc.image(imgSource, x, startY, {
204
+ width: imgWidth,
205
+ height: imgHeight
206
+ });
207
+ } catch (e) {
208
+ console.warn("Failed to load image:", e);
209
+ }
210
+ const newY = startY + imgHeight + mb;
211
+ if (y === null) ctx.currentY = newY;
212
+ return newY;
213
+ };
214
+
215
+ // src/renderer-engine/blocks/key-value-grid.ts
216
+ var processKeyValueGridBlock = (doc, ctx, styles, block, y, env, computeColumnPixelWidths2, ensureSpaceFor) => {
217
+ const mt = block.marginTop ?? 0;
218
+ const mb = block.marginBottom ?? 0;
219
+ const rowGap = block.rowGap ?? 4;
220
+ const orientation = block.orientation ?? "horizontal";
221
+ const cols = block.columns ?? [];
222
+ const colCount = cols.length;
223
+ if (!colCount) {
224
+ const baseY2 = y ?? ctx.currentY;
225
+ const endY2 = baseY2 + mt + mb;
226
+ if (y === null) ctx.currentY = endY2;
227
+ return endY2;
228
+ }
229
+ const blockLeft = block.marginLeft ?? 0;
230
+ const blockRight = block.marginRight ?? 0;
231
+ const baseLeft = env.marginLeft + blockLeft;
232
+ const totalWidth = Math.max(env.innerWidth - blockLeft - blockRight, 1);
233
+ const columnGap = block.columnGap ?? 30;
234
+ const totalGapWidth = columnGap * (colCount - 1);
235
+ const widthForCols = Math.max(totalWidth - totalGapWidth, 1);
236
+ let colWidths;
237
+ if (block.columnWidths && block.columnWidths.length === colCount) {
238
+ const safeWidths = block.columnWidths.map(
239
+ (w) => w === void 0 ? "*" : w
240
+ );
241
+ colWidths = computeColumnPixelWidths2(safeWidths, widthForCols);
242
+ } else {
243
+ const equal = widthForCols / colCount;
244
+ colWidths = Array(colCount).fill(equal);
245
+ }
246
+ const xBases = [];
247
+ {
248
+ let x = baseLeft;
249
+ for (let i = 0; i < colCount; i++) {
250
+ xBases.push(x);
251
+ x += colWidths[i] + columnGap;
252
+ }
253
+ }
254
+ const maxRows = Math.max(...cols.map((c) => c.length));
255
+ const separatorText = block.separator;
256
+ const sepBoxWidth = separatorText ? 10 : 0;
257
+ const baseKeyWidthRatio = 0.35;
258
+ const resolveStyled = (base, styleNames) => resolveTextBlock(styles, {
259
+ ...base,
260
+ style: styleNames
261
+ });
262
+ const measureTextHeight = (tb, width) => {
263
+ const fontName = getFontNameForText(tb);
264
+ doc.font(fontName);
265
+ doc.fontSize(tb.fontSize ?? 10);
266
+ return doc.heightOfString(tb.text ?? "", { width });
267
+ };
268
+ const buildKeyBlock = (item) => ({
269
+ type: "text",
270
+ text: item.key ?? "",
271
+ align: block.keyAlign ?? "left",
272
+ ...block.keyTextStyle ?? {},
273
+ ...item.keyTextStyle ?? {}
274
+ });
275
+ const buildValueBlock = (item) => ({
276
+ type: "text",
277
+ text: item.value ?? "",
278
+ align: block.valueAlign ?? "left",
279
+ ...block.valueTextStyle ?? {},
280
+ ...item.valueTextStyle ?? {}
281
+ });
282
+ let totalHeight = mt;
283
+ if (orientation === "vertical") {
284
+ const keyValueGap = block.verticalKeyValueGap ?? 2;
285
+ let maxColHeight = 0;
286
+ for (let colIndex = 0; colIndex < colCount; colIndex++) {
287
+ const col = cols[colIndex];
288
+ const colWidth = colWidths[colIndex];
289
+ let colHeight = 0;
290
+ for (const item of col) {
291
+ const keyStyleNames = item.keyStyle ?? block.keyStyle ?? void 0;
292
+ const valueStyleNames = item.valueStyle ?? block.valueStyle ?? void 0;
293
+ const keyBase = buildKeyBlock(item);
294
+ const keyResolved = resolveStyled(keyBase, keyStyleNames);
295
+ const keyHeight = measureTextHeight(keyResolved, colWidth);
296
+ const valueBase = buildValueBlock(item);
297
+ const valueResolved = resolveStyled(valueBase, valueStyleNames);
298
+ const valueHeight = measureTextHeight(valueResolved, colWidth);
299
+ const rowHeight = keyHeight + keyValueGap + valueHeight;
300
+ colHeight += rowHeight + rowGap;
301
+ }
302
+ if (colHeight > maxColHeight) maxColHeight = colHeight;
303
+ }
304
+ totalHeight += maxColHeight;
305
+ } else {
306
+ for (let rowIndex = 0; rowIndex < maxRows; rowIndex++) {
307
+ let rowHeight = 0;
308
+ for (let colIndex = 0; colIndex < colCount; colIndex++) {
309
+ const col = cols[colIndex];
310
+ const item = col[rowIndex];
311
+ if (!item) continue;
312
+ const colWidth = colWidths[colIndex];
313
+ const keyWidthPx = block.keyWidth === "*" ? Math.max(colWidth * baseKeyWidthRatio, 20) : block.keyWidth ?? 80;
314
+ const keyStyleNames = item.keyStyle ?? block.keyStyle ?? void 0;
315
+ const valueStyleNames = item.valueStyle ?? block.valueStyle ?? void 0;
316
+ const keyBase = buildKeyBlock(item);
317
+ const keyResolved = resolveStyled(keyBase, keyStyleNames);
318
+ const keyHeight = measureTextHeight(keyResolved, keyWidthPx);
319
+ const valueBase = buildValueBlock(item);
320
+ const valueResolved = resolveStyled(valueBase, valueStyleNames);
321
+ const valueXInsideCol = keyWidthPx + (separatorText ? sepBoxWidth + 4 : 4);
322
+ const valueWidth = Math.max(colWidth - valueXInsideCol, 1);
323
+ const valueHeight = measureTextHeight(valueResolved, valueWidth);
324
+ const cellHeight = Math.max(keyHeight, valueHeight);
325
+ if (cellHeight > rowHeight) rowHeight = cellHeight;
326
+ }
327
+ if (rowHeight > 0) {
328
+ totalHeight += rowHeight + rowGap;
329
+ }
330
+ }
331
+ }
332
+ totalHeight += mb;
333
+ if (y === null) {
334
+ ensureSpaceFor(totalHeight, env);
335
+ }
336
+ const baseY = y ?? ctx.currentY;
337
+ let rowY = baseY + mt;
338
+ if (orientation === "vertical") {
339
+ const keyValueGap = block.verticalKeyValueGap ?? 2;
340
+ let maxColBottom = rowY;
341
+ for (let colIndex = 0; colIndex < colCount; colIndex++) {
342
+ const col = cols[colIndex];
343
+ const colWidth = colWidths[colIndex];
344
+ const colX = xBases[colIndex];
345
+ let colY = rowY;
346
+ for (const item of col) {
347
+ const keyStyleNames = item.keyStyle ?? block.keyStyle ?? void 0;
348
+ const valueStyleNames = item.valueStyle ?? block.valueStyle ?? void 0;
349
+ const keyBlock = buildKeyBlock(item);
350
+ const keyResolved = resolveStyled(keyBlock, keyStyleNames);
351
+ const keyHeight = measureTextHeight(keyResolved, colWidth);
352
+ drawStyledText(doc, keyResolved, colX, colY, colWidth);
353
+ colY += keyHeight + keyValueGap;
354
+ const valueBlock = buildValueBlock(item);
355
+ const valueResolved = resolveStyled(valueBlock, valueStyleNames);
356
+ const valueHeight = measureTextHeight(valueResolved, colWidth);
357
+ drawStyledText(doc, valueResolved, colX, colY, colWidth);
358
+ colY += valueHeight + rowGap;
359
+ }
360
+ if (colY > maxColBottom) maxColBottom = colY;
361
+ }
362
+ rowY = maxColBottom;
363
+ } else {
364
+ for (let rowIndex = 0; rowIndex < maxRows; rowIndex++) {
365
+ let rowHeight = 0;
366
+ for (let colIndex = 0; colIndex < colCount; colIndex++) {
367
+ const col = cols[colIndex];
368
+ const item = col[rowIndex];
369
+ if (!item) continue;
370
+ const colWidth = colWidths[colIndex];
371
+ const keyWidthPx = block.keyWidth === "*" ? Math.max(colWidth * baseKeyWidthRatio, 20) : block.keyWidth ?? 80;
372
+ const keyStyleNames = item.keyStyle ?? block.keyStyle ?? void 0;
373
+ const valueStyleNames = item.valueStyle ?? block.valueStyle ?? void 0;
374
+ const keyBase = buildKeyBlock(item);
375
+ const keyResolved = resolveStyled(keyBase, keyStyleNames);
376
+ const keyHeight = measureTextHeight(keyResolved, keyWidthPx);
377
+ const valueBase = buildValueBlock(item);
378
+ const valueResolved = resolveStyled(valueBase, valueStyleNames);
379
+ const valueXInsideCol = keyWidthPx + (separatorText ? sepBoxWidth + 4 : 4);
380
+ const valueWidth = Math.max(colWidth - valueXInsideCol, 1);
381
+ const valueHeight = measureTextHeight(valueResolved, valueWidth);
382
+ const cellHeight = Math.max(keyHeight, valueHeight);
383
+ if (cellHeight > rowHeight) rowHeight = cellHeight;
384
+ }
385
+ if (rowHeight === 0) continue;
386
+ for (let colIndex = 0; colIndex < colCount; colIndex++) {
387
+ const col = cols[colIndex];
388
+ const item = col[rowIndex];
389
+ if (!item) continue;
390
+ const colX = xBases[colIndex];
391
+ const colWidth = colWidths[colIndex];
392
+ const keyWidthPx = block.keyWidth === "*" ? Math.max(colWidth * baseKeyWidthRatio, 20) : block.keyWidth ?? 80;
393
+ const keyStyleNames = item.keyStyle ?? block.keyStyle ?? void 0;
394
+ const valueStyleNames = item.valueStyle ?? block.valueStyle ?? void 0;
395
+ const keyBlock = buildKeyBlock(item);
396
+ const keyResolved = resolveStyled(keyBlock, keyStyleNames);
397
+ drawStyledText(doc, keyResolved, colX, rowY, keyWidthPx);
398
+ if (separatorText) {
399
+ const sepBlock = {
400
+ type: "text",
401
+ text: separatorText,
402
+ align: "left"
403
+ };
404
+ const sepResolved = resolveStyled(sepBlock, keyStyleNames);
405
+ const sepX = colX + keyWidthPx + 2;
406
+ drawStyledText(doc, sepResolved, sepX, rowY, sepBoxWidth);
407
+ }
408
+ const valueX = colX + keyWidthPx + (separatorText ? sepBoxWidth + 4 : 4);
409
+ const valueWidth = Math.max(colWidth - (valueX - colX), 1);
410
+ const valueBlock = buildValueBlock(item);
411
+ const valueResolved = resolveStyled(valueBlock, valueStyleNames);
412
+ drawStyledText(doc, valueResolved, valueX, rowY, valueWidth);
413
+ }
414
+ rowY += rowHeight + rowGap;
415
+ }
416
+ }
417
+ const endY = rowY + mb;
418
+ if (y === null) ctx.currentY = endY;
419
+ return endY;
420
+ };
421
+
422
+ // src/renderer-engine/blocks/line.ts
423
+ var processLineBlock = (doc, ctx, block, y, env, ensureSpaceFor) => {
424
+ const localLeft = block.marginLeft ?? 0;
425
+ const localRight = block.marginRight ?? 0;
426
+ const xLeft = env.marginLeft + localLeft;
427
+ const width = Math.max(env.innerWidth - localLeft - localRight, 1);
428
+ const mt = block.marginTop ?? 0;
429
+ const mb = block.marginBottom ?? 0;
430
+ const baseY = y ?? ctx.currentY;
431
+ const startY = baseY + mt;
432
+ const lineWidth = block.lineWidth ?? 1;
433
+ const heightNeeded = mt + lineWidth + mb;
434
+ if (y === null) {
435
+ ensureSpaceFor(heightNeeded, env);
436
+ }
437
+ doc.save();
438
+ if (block.color) {
439
+ doc.strokeColor(block.color);
440
+ }
441
+ doc.lineWidth(lineWidth);
442
+ doc.moveTo(xLeft, startY).lineTo(xLeft + width, startY).stroke();
443
+ doc.restore();
444
+ const newY = startY + lineWidth + mb;
445
+ if (y === null) ctx.currentY = newY;
446
+ return newY;
447
+ };
448
+
449
+ // src/renderer-engine/blocks/table.ts
450
+ var measureTableHeight = (doc, table, env, styles, computeColumnPixelWidths2) => {
451
+ const localLeft = table.marginLeft ?? 0;
452
+ const localRight = table.marginRight ?? 0;
453
+ const width = Math.max(env.innerWidth - localLeft - localRight, 1);
454
+ const colWidths = computeColumnPixelWidths2(table.widths, width);
455
+ let totalHeight = 0;
456
+ totalHeight += table.marginTop ?? 0;
457
+ table.body.forEach((row) => {
458
+ let rowHeight = 0;
459
+ row.forEach((rawCell, colIndex) => {
460
+ const cell = resolveTableCell(styles, rawCell);
461
+ const colW = colWidths[colIndex] ?? 50;
462
+ const fontSize = cell.fontSize ?? 10;
463
+ const isBold = !!cell.bold;
464
+ const isItalic = !!cell.italic;
465
+ const fontName = cell.font ? cell.font : isBold && isItalic ? "Helvetica-BoldOblique" : isBold ? "Helvetica-Bold" : isItalic ? "Helvetica-Oblique" : "Helvetica";
466
+ doc.font(fontName);
467
+ doc.fontSize(fontSize);
468
+ const h = doc.heightOfString(cell.text, { width: colW });
469
+ rowHeight = Math.max(rowHeight, h + 4);
470
+ });
471
+ totalHeight += rowHeight;
472
+ });
473
+ totalHeight += table.lineGap ?? 6;
474
+ totalHeight += table.marginBottom ?? 0;
475
+ return totalHeight;
476
+ };
477
+ var processTableBlock = (doc, ctx, styles, table, y, env, computeColumnPixelWidths2, bottomLimitForContent, finishPage2) => {
478
+ const localLeft = table.marginLeft ?? 0;
479
+ const localRight = table.marginRight ?? 0;
480
+ const baseLeft = env.marginLeft + localLeft;
481
+ const width = Math.max(env.innerWidth - localLeft - localRight, 1);
482
+ const mt = table.marginTop ?? 0;
483
+ const mb = table.marginBottom ?? 0;
484
+ const baseY = y ?? ctx.currentY;
485
+ const startY = baseY + mt;
486
+ const colWidths = computeColumnPixelWidths2(table.widths, width);
487
+ const layout = table.layout ?? {
488
+ border: "all",
489
+ hLineColor: "#ccc",
490
+ vLineColor: "#ccc"
491
+ };
492
+ const borderAll = layout.border !== "none";
493
+ const headerRows = table.headerRows ?? 0;
494
+ const measureRowHeight = (row) => {
495
+ let rowHeight = 0;
496
+ row.forEach((rawCell, colIndex) => {
497
+ const cell = resolveTableCell(styles, rawCell);
498
+ const colW = colWidths[colIndex] ?? 50;
499
+ const fontSize = cell.fontSize ?? 10;
500
+ const fontName = cell.font ? cell.font : cell.bold ? "Helvetica-Bold" : "Helvetica";
501
+ doc.font(fontName);
502
+ doc.fontSize(fontSize);
503
+ const textWidth = Math.max(colW - 4, 1);
504
+ const h = doc.heightOfString(cell.text, {
505
+ width: textWidth
506
+ }) + 4;
507
+ rowHeight = Math.max(rowHeight, h);
508
+ });
509
+ return rowHeight || 12;
510
+ };
511
+ const drawRow = (row, rowTop2, rowHeight, isHeaderRow, drawTopBorder) => {
512
+ row.forEach((rawCell, colIndex) => {
513
+ const cell = resolveTableCell(styles, rawCell);
514
+ const colW = colWidths[colIndex] ?? 50;
515
+ const x = baseLeft + colWidths.slice(0, colIndex).reduce((a, b) => a + b, 0);
516
+ const fontSize = cell.fontSize ?? 10;
517
+ doc.save();
518
+ if (cell.fillColor) {
519
+ doc.rect(x, rowTop2, colW, rowHeight).fillOpacity(1).fill(cell.fillColor);
520
+ doc.fillOpacity(1);
521
+ }
522
+ const isBold = !!cell.bold;
523
+ const isItalic = !!cell.italic;
524
+ const fontName = cell.font ? cell.font : isBold && isItalic ? "Helvetica-BoldOblique" : isBold ? "Helvetica-Bold" : isItalic ? "Helvetica-Oblique" : "Helvetica";
525
+ doc.font(fontName);
526
+ doc.fontSize(fontSize);
527
+ if (cell.color) {
528
+ doc.fillColor(cell.color);
529
+ } else {
530
+ doc.fillColor("black");
531
+ }
532
+ const align = cell.align ?? "left";
533
+ const textWidth = Math.max(colW - 4, 1);
534
+ const textHeight = doc.heightOfString(cell.text, {
535
+ width: textWidth
536
+ });
537
+ let textY = rowTop2 + 2;
538
+ if (isHeaderRow) {
539
+ const available = rowHeight - 4;
540
+ const offset = Math.max((available - textHeight) / 2, 0);
541
+ textY = rowTop2 + 2 + offset;
542
+ }
543
+ doc.text(cell.text, x + 2, textY, {
544
+ width: textWidth,
545
+ align,
546
+ underline: !!cell.underline,
547
+ strike: !!cell.strike,
548
+ link: cell.link
549
+ });
550
+ doc.restore();
551
+ });
552
+ if (borderAll) {
553
+ const bottomY = rowTop2 + rowHeight;
554
+ doc.save();
555
+ doc.lineWidth(0.5);
556
+ doc.strokeColor(layout.hLineColor ?? "#ccc");
557
+ if (drawTopBorder) {
558
+ doc.moveTo(baseLeft, rowTop2).lineTo(baseLeft + width, rowTop2).stroke();
559
+ }
560
+ doc.moveTo(baseLeft, bottomY).lineTo(baseLeft + width, bottomY).stroke();
561
+ doc.restore();
562
+ doc.save();
563
+ doc.lineWidth(0.5);
564
+ doc.strokeColor(layout.vLineColor ?? "#ccc");
565
+ let x = baseLeft;
566
+ colWidths.forEach((colW) => {
567
+ doc.moveTo(x, rowTop2).lineTo(x, bottomY).stroke();
568
+ x += colW;
569
+ });
570
+ doc.moveTo(baseLeft + width, rowTop2).lineTo(baseLeft + width, bottomY).stroke();
571
+ doc.restore();
572
+ }
573
+ return rowTop2 + rowHeight;
574
+ };
575
+ const drawHeaderRowsOnNewPage = () => {
576
+ if (!headerRows) return doc.page.margins.top + mt;
577
+ let rowTop2 = doc.page.margins.top + mt;
578
+ for (let i = 0; i < headerRows; i++) {
579
+ const headerRow = table.body[i];
580
+ const headerHeight = measureRowHeight(headerRow);
581
+ rowTop2 = drawRow(headerRow, rowTop2, headerHeight, true, true);
582
+ }
583
+ return rowTop2;
584
+ };
585
+ let rowTop = startY;
586
+ table.body.forEach((row, rowIndex) => {
587
+ const isHeaderRow = rowIndex < headerRows;
588
+ const rowHeight = measureRowHeight(row);
589
+ const bottomLimit = bottomLimitForContent();
590
+ if (rowTop + rowHeight > bottomLimit) {
591
+ finishPage2(true);
592
+ rowTop = headerRows ? drawHeaderRowsOnNewPage() : doc.page.margins.top + mt;
593
+ }
594
+ const drawTopBorder = true;
595
+ rowTop = drawRow(row, rowTop, rowHeight, isHeaderRow, drawTopBorder);
596
+ });
597
+ const newY = rowTop + (table.lineGap ?? 6) + mb;
598
+ if (y === null) ctx.currentY = newY;
599
+ return newY;
600
+ };
601
+
602
+ // src/renderer-engine/blocks/text.ts
603
+ var processTextBlock = (doc, ctx, styles, block, y, env, ensureSpaceFor) => {
604
+ const tb = resolveTextBlock(styles, block);
605
+ const localLeft = tb.marginLeft ?? 0;
606
+ const localRight = tb.marginRight ?? 0;
607
+ const xLeft = env.marginLeft + localLeft;
608
+ const width = Math.max(env.innerWidth - localLeft - localRight, 1);
609
+ const baseY = y ?? ctx.currentY;
610
+ const startY = baseY;
611
+ doc.fontSize(tb.fontSize ?? 10);
612
+ const isBold = !!tb.bold;
613
+ const isItalic = !!tb.italic;
614
+ let fontName = tb.font;
615
+ if (!fontName) {
616
+ if (isBold && isItalic) fontName = "Helvetica-BoldOblique";
617
+ else if (isBold) fontName = "Helvetica-Bold";
618
+ else if (isItalic) fontName = "Helvetica-Oblique";
619
+ else fontName = "Helvetica";
620
+ }
621
+ doc.font(fontName);
622
+ if (tb.color) doc.fillColor(tb.color);
623
+ else doc.fillColor("black");
624
+ const textHeight = doc.heightOfString(tb.text, { width });
625
+ if (y === null) {
626
+ const gapCheck = tb.lineGap ?? 4;
627
+ ensureSpaceFor(textHeight + gapCheck, env);
628
+ }
629
+ doc.text(tb.text, xLeft, startY, {
630
+ width,
631
+ align: tb.align ?? "left",
632
+ underline: !!tb.underline,
633
+ strike: !!tb.strike,
634
+ link: tb.link
635
+ });
636
+ const gap = tb.lineGap ?? 4;
637
+ const newY = startY + textHeight + gap;
638
+ if (y === null) ctx.currentY = newY;
639
+ return newY;
640
+ };
641
+
642
+ // src/renderer-engine/utils/block-renderer.ts
643
+ function createBlockRenderer(deps) {
644
+ const {
645
+ doc,
646
+ ctx,
647
+ styles,
648
+ computeColumnPixelWidths: computeColumnPixelWidths2,
649
+ finishPage: finishPage2,
650
+ processSignatureBlock
651
+ } = deps;
652
+ const bottomLimitForContent = createBottomLimitForContent(doc, ctx);
653
+ const ensureSpaceFor = createEnsureSpaceFor(
654
+ ctx,
655
+ bottomLimitForContent,
656
+ finishPage2
657
+ );
658
+ const measureBlockHeight = createMeasureBlockHeight({
659
+ doc,
660
+ styles,
661
+ computeColumnPixelWidths: computeColumnPixelWidths2
662
+ });
663
+ const renderBlock = (block, y, env) => {
664
+ if (block.visible === false) {
665
+ return y ?? ctx.currentY;
666
+ }
667
+ switch (block.type) {
668
+ case "text":
669
+ return processTextBlock(
670
+ doc,
671
+ ctx,
672
+ styles,
673
+ block,
674
+ y,
675
+ env,
676
+ ensureSpaceFor
677
+ );
678
+ case "image":
679
+ return processImageBlock(
680
+ doc,
681
+ ctx,
682
+ block,
683
+ y,
684
+ env,
685
+ ensureSpaceFor
686
+ );
687
+ case "qr": {
688
+ const qb = block;
689
+ const imageLike = {
690
+ type: "image",
691
+ src: qb.src,
692
+ width: qb.size,
693
+ height: qb.size,
694
+ align: qb.align,
695
+ marginTop: qb.marginTop,
696
+ marginBottom: qb.marginBottom,
697
+ marginLeft: qb.marginLeft,
698
+ marginRight: qb.marginRight
699
+ };
700
+ return processImageBlock(doc, ctx, imageLike, y, env, ensureSpaceFor);
701
+ }
702
+ case "barcode":
703
+ return processBarcodeBlock(doc, ctx, block, y, env, ensureSpaceFor);
704
+ case "line":
705
+ return processLineBlock(
706
+ doc,
707
+ ctx,
708
+ block,
709
+ y,
710
+ env,
711
+ ensureSpaceFor
712
+ );
713
+ case "table":
714
+ return processTableBlock(
715
+ doc,
716
+ ctx,
717
+ styles,
718
+ block,
719
+ y,
720
+ env,
721
+ computeColumnPixelWidths2,
722
+ bottomLimitForContent,
723
+ finishPage2
724
+ );
725
+ case "columns":
726
+ return processColumnsBlock(
727
+ ctx,
728
+ block,
729
+ y,
730
+ env,
731
+ computeColumnPixelWidths2,
732
+ renderBlock,
733
+ ensureSpaceFor,
734
+ measureBlockHeight
735
+ );
736
+ case "keyValueGrid":
737
+ return processKeyValueGridBlock(
738
+ doc,
739
+ ctx,
740
+ styles,
741
+ block,
742
+ y,
743
+ env,
744
+ computeColumnPixelWidths2,
745
+ ensureSpaceFor
746
+ );
747
+ case "signature":
748
+ if (!env.allowPageBreak) {
749
+ throw new Error(
750
+ "Signature block is only allowed in main content flow."
751
+ );
752
+ }
753
+ if (y !== null) {
754
+ throw new Error(
755
+ "Signature block must be part of main flow, not drawn at explicit Y."
756
+ );
757
+ }
758
+ processSignatureBlock(block);
759
+ return ctx.currentY;
760
+ case "pageBreak":
761
+ if (!env.allowPageBreak || ctx.inFooter) {
762
+ return y ?? ctx.currentY;
763
+ }
764
+ finishPage2(true);
765
+ return ctx.currentY;
766
+ default:
767
+ return ctx.currentY;
768
+ }
769
+ };
770
+ const renderBlockArray = (blocks, startY, env) => {
771
+ let localY = startY;
772
+ for (const block of blocks) {
773
+ if (block.visible === false) {
774
+ continue;
775
+ }
776
+ localY = renderBlock(block, localY, env);
777
+ }
778
+ return localY;
779
+ };
780
+ return {
781
+ renderBlock,
782
+ renderBlockArray
783
+ };
784
+ }
785
+
786
+ // src/renderer-engine/utils/context.ts
787
+ function createInitialContext(doc) {
788
+ return {
789
+ pageNumber: 1,
790
+ currentY: doc.page.margins.top,
791
+ signatureBlock: null,
792
+ signatureTopY: null,
793
+ signatureHeight: 0,
794
+ signaturePlaced: false,
795
+ afterSignature: false,
796
+ inFooter: false
797
+ };
798
+ }
799
+
800
+ // src/renderer-engine/utils/ensure-space.ts
801
+ function createEnsureSpaceFor(ctx, bottomLimitForContent, finishPage2) {
802
+ return (heightNeeded, env) => {
803
+ if (!env.allowPageBreak || ctx.inFooter) return;
804
+ const bottomLimit = bottomLimitForContent();
805
+ if (ctx.currentY + heightNeeded > bottomLimit) {
806
+ finishPage2(true);
807
+ }
808
+ };
809
+ }
810
+
811
+ // src/renderer-engine/utils/env.ts
812
+ var contentEnv = (doc) => ({
813
+ marginLeft: doc.page.margins.left,
814
+ innerWidth: doc.page.width - doc.page.margins.left - doc.page.margins.right,
815
+ allowPageBreak: true
816
+ });
817
+
818
+ // src/renderer-engine/utils/finish-page.ts
819
+ function finishPage({
820
+ addNewPage,
821
+ doc,
822
+ def,
823
+ ctx,
824
+ footerBandHeight,
825
+ renderBlockArray,
826
+ startNewPageLayout
827
+ }) {
828
+ const mode = def.watermark?.mode;
829
+ if (def.watermark && watermarkUsesLast(mode)) {
830
+ const isLast = !addNewPage;
831
+ drawWatermarkForPage(doc, def.watermark, ctx.pageNumber, isLast);
832
+ }
833
+ if (ctx.signatureBlock && ctx.signatureTopY !== null) {
834
+ const env = contentEnv(doc);
835
+ drawSignatureBlock(
836
+ doc,
837
+ ctx.signatureBlock,
838
+ ctx.signatureTopY,
839
+ env,
840
+ renderBlockArray
841
+ );
842
+ }
843
+ drawFooter(doc, def, ctx, footerBandHeight, renderBlockArray);
844
+ if (addNewPage) {
845
+ doc.addPage();
846
+ ctx.pageNumber += 1;
847
+ startNewPageLayout();
848
+ }
849
+ }
850
+
851
+ // src/renderer-engine/utils/footer.ts
852
+ function normalizeFooter(input, ctx, doc) {
853
+ if (!input) return null;
854
+ if (typeof input === "function") {
855
+ const result = input(ctx.pageNumber, {
856
+ width: doc.page.width,
857
+ height: doc.page.height
858
+ });
859
+ if (!result) return null;
860
+ return normalizeFooter(result, ctx, doc);
861
+ }
862
+ if (input.blocks && Array.isArray(input.blocks)) {
863
+ const f = input;
864
+ return {
865
+ visible: f.visible,
866
+ blocks: f.blocks,
867
+ marginTop: f.marginTop,
868
+ marginBottom: f.marginBottom,
869
+ marginLeft: f.marginLeft,
870
+ marginRight: f.marginRight,
871
+ backgroundColor: f.backgroundColor,
872
+ backgroundImage: f.backgroundImage
873
+ };
874
+ }
875
+ if (input.type) {
876
+ return { blocks: [input] };
877
+ }
878
+ if (Array.isArray(input)) {
879
+ return { blocks: input };
880
+ }
881
+ return null;
882
+ }
883
+ function drawFooter(doc, def, ctx, footerBandHeight, renderBlockArray) {
884
+ const footerConfig = def.footer;
885
+ if (!footerConfig) return;
886
+ const layout = normalizeFooter(footerConfig, ctx, doc);
887
+ if (!layout || !layout.blocks.length) return;
888
+ if (layout.visible === false) return;
889
+ const bandHeight = footerBandHeight;
890
+ if (!bandHeight) return;
891
+ const { marginTop = 4, backgroundColor, backgroundImage, blocks } = layout;
892
+ const footerMarginLeft = layout.marginLeft ?? 0;
893
+ const footerMarginRight = layout.marginRight ?? 0;
894
+ const contentWidth = doc.page.width - footerMarginLeft - footerMarginRight;
895
+ const footerEnv = {
896
+ marginLeft: footerMarginLeft,
897
+ innerWidth: contentWidth,
898
+ allowPageBreak: false
899
+ };
900
+ const pageHeight = doc.page.height;
901
+ const bandTop = pageHeight - bandHeight;
902
+ if (backgroundColor) {
903
+ doc.save();
904
+ doc.rect(0, bandTop, doc.page.width, bandHeight).fill(backgroundColor);
905
+ doc.restore();
906
+ }
907
+ if (backgroundImage) {
908
+ try {
909
+ doc.image(backgroundImage, 0, bandTop, {
910
+ width: doc.page.width,
911
+ height: bandHeight
912
+ });
913
+ } catch (e) {
914
+ console.warn("Failed to load footer background image:", e);
915
+ }
916
+ }
917
+ doc.save();
918
+ doc.rect(footerMarginLeft, bandTop, contentWidth, bandHeight).clip();
919
+ doc.translate(0, bandTop);
920
+ ctx.inFooter = true;
921
+ const localStartY = marginTop;
922
+ renderBlockArray(blocks, localStartY, footerEnv);
923
+ ctx.inFooter = false;
924
+ doc.restore();
925
+ }
926
+
927
+ // src/renderer-engine/utils/header.ts
928
+ function drawHeader(doc, def, headerBandHeight, header, renderBlockArray) {
929
+ if (!header || !header.blocks.length) return;
930
+ if (header.visible === false) return;
931
+ if (!headerBandHeight) return;
932
+ const bandTop = 0;
933
+ const bandHeight = def.margins.top;
934
+ const headerMarginLeft = header.marginLeft ?? 0;
935
+ const headerMarginRight = header.marginRight ?? 0;
936
+ const contentWidth = doc.page.width - headerMarginLeft - headerMarginRight;
937
+ const headerEnv = {
938
+ marginLeft: headerMarginLeft,
939
+ innerWidth: contentWidth,
940
+ allowPageBreak: false
941
+ };
942
+ if (header.backgroundColor) {
943
+ doc.save();
944
+ doc.rect(0, bandTop, doc.page.width, bandHeight).fill(header.backgroundColor);
945
+ doc.restore();
946
+ }
947
+ if (header.backgroundImage) {
948
+ try {
949
+ doc.image(header.backgroundImage, 0, bandTop, {
950
+ width: doc.page.width,
951
+ height: bandHeight
952
+ });
953
+ } catch (e) {
954
+ console.warn("Failed to load header background image:", e);
955
+ }
956
+ }
957
+ doc.save();
958
+ doc.rect(headerMarginLeft, bandTop, contentWidth, bandHeight).clip();
959
+ const startY = bandTop + (header.marginTop ?? 0);
960
+ renderBlockArray(header.blocks, startY, headerEnv);
961
+ doc.restore();
962
+ }
963
+
964
+ // src/renderer-engine/utils/image-loader.ts
965
+ var import_axios = __toESM(require("axios"));
966
+ async function normalizeImageSrc(src) {
967
+ if (!src) return src;
968
+ if (Buffer.isBuffer(src)) return src;
969
+ if (src.startsWith("http://") || src.startsWith("https://")) {
970
+ const res = await import_axios.default.get(src, {
971
+ responseType: "arraybuffer"
972
+ });
973
+ return Buffer.from(res.data);
974
+ }
975
+ return src;
976
+ }
977
+ async function materializeImagesInBlocks(blocks) {
978
+ const out = [];
979
+ for (const block of blocks) {
980
+ if (block.type === "image") {
981
+ const img = { ...block };
982
+ img.src = await normalizeImageSrc(img.src);
983
+ out.push(img);
984
+ } else if (block.type === "columns") {
985
+ out.push({
986
+ ...block,
987
+ columns: await Promise.all(
988
+ block.columns.map((col) => materializeImagesInBlocks(col))
989
+ )
990
+ });
991
+ } else if (block.type === "signature" && block.blocks) {
992
+ out.push({
993
+ ...block,
994
+ blocks: await materializeImagesInBlocks(block.blocks)
995
+ });
996
+ } else {
997
+ out.push(block);
998
+ }
999
+ }
1000
+ return out;
1001
+ }
1002
+
1003
+ // src/renderer-engine/utils/layout.ts
1004
+ function computeColumnPixelWidths(widths, totalWidth) {
1005
+ let fixedTotal = 0;
1006
+ let starCount = 0;
1007
+ widths.forEach((w) => {
1008
+ if (w === "*") starCount++;
1009
+ else fixedTotal += w;
1010
+ });
1011
+ const remaining = Math.max(totalWidth - fixedTotal, 0);
1012
+ const starWidth = starCount > 0 ? remaining / starCount : 0;
1013
+ return widths.map((w) => w === "*" ? starWidth : w);
1014
+ }
1015
+
1016
+ // src/renderer-engine/utils/styles.ts
1017
+ function mergeStyleDefs(styles, names) {
1018
+ const result = {};
1019
+ if (!names || !styles) return result;
1020
+ const arr = Array.isArray(names) ? names : [names];
1021
+ for (const name of arr) {
1022
+ const st = styles[name];
1023
+ if (!st) continue;
1024
+ if (st.fontSize !== void 0) result.fontSize = st.fontSize;
1025
+ if (st.lineGap !== void 0) result.lineGap = st.lineGap;
1026
+ if (st.align !== void 0) result.align = st.align;
1027
+ if (st.bold !== void 0) result.bold = st.bold;
1028
+ if (st.italic !== void 0) result.italic = st.italic;
1029
+ if (st.underline !== void 0) result.underline = st.underline;
1030
+ if (st.strike !== void 0) result.strike = st.strike;
1031
+ if (st.link !== void 0) result.link = st.link;
1032
+ if (st.color !== void 0) result.color = st.color;
1033
+ if (st.fillColor !== void 0) result.fillColor = st.fillColor;
1034
+ if (st.font !== void 0) result.font = st.font;
1035
+ }
1036
+ return result;
1037
+ }
1038
+ function resolveTextBlock(styles, block) {
1039
+ const styleDef = mergeStyleDefs(styles, block.style);
1040
+ return {
1041
+ ...styleDef,
1042
+ ...block,
1043
+ fontSize: block.fontSize ?? styleDef.fontSize,
1044
+ lineGap: block.lineGap ?? styleDef.lineGap,
1045
+ align: block.align ?? styleDef.align,
1046
+ bold: block.bold ?? styleDef.bold,
1047
+ italic: block.italic ?? styleDef.italic,
1048
+ underline: block.underline ?? styleDef.underline,
1049
+ strike: block.strike ?? styleDef.strike,
1050
+ link: block.link ?? styleDef.link,
1051
+ color: block.color ?? styleDef.color,
1052
+ // fillColor: block.fillColor ?? styleDef.fillColor,
1053
+ font: block.font ?? styleDef.font
1054
+ };
1055
+ }
1056
+ function resolveTableCell(styles, cell) {
1057
+ const styleDef = mergeStyleDefs(styles, cell.style);
1058
+ return {
1059
+ ...styleDef,
1060
+ ...cell,
1061
+ fontSize: cell.fontSize ?? styleDef.fontSize,
1062
+ align: cell.align ?? styleDef.align,
1063
+ bold: cell.bold ?? styleDef.bold,
1064
+ italic: cell.italic ?? styleDef.italic,
1065
+ color: cell.color ?? styleDef.color,
1066
+ fillColor: cell.fillColor ?? styleDef.fillColor,
1067
+ font: cell.font ?? styleDef.font
1068
+ };
1069
+ }
1070
+ var getFontNameForText = (tb) => {
1071
+ if (tb.font) return tb.font;
1072
+ const bold = tb.bold ?? false;
1073
+ const italic = tb.italic ?? false;
1074
+ if (bold && italic) return "Helvetica-BoldOblique";
1075
+ if (bold) return "Helvetica-Bold";
1076
+ if (italic) return "Helvetica-Oblique";
1077
+ return "Helvetica";
1078
+ };
1079
+ var drawStyledText = (doc, tb, x, y, width) => {
1080
+ doc.save();
1081
+ doc.fontSize(tb.fontSize ?? 10);
1082
+ doc.font(getFontNameForText(tb));
1083
+ if (tb.color) doc.fillColor(tb.color);
1084
+ else doc.fillColor("black");
1085
+ const textHeight = doc.heightOfString(tb.text, { width });
1086
+ doc.text(tb.text, x, y, {
1087
+ width,
1088
+ align: tb.align ?? "left"
1089
+ });
1090
+ const underline = tb.underline;
1091
+ const strike = tb.strike;
1092
+ if (underline) {
1093
+ const lineY = y + textHeight;
1094
+ doc.moveTo(x, lineY).lineTo(x + width, lineY).stroke();
1095
+ }
1096
+ if (strike) {
1097
+ const lineY = y + textHeight / 2;
1098
+ doc.moveTo(x, lineY).lineTo(x + width, lineY).stroke();
1099
+ }
1100
+ doc.restore();
1101
+ };
1102
+
1103
+ // src/renderer-engine/utils/measure-block-height.ts
1104
+ function createMeasureBlockHeight(deps) {
1105
+ const { doc, styles, computeColumnPixelWidths: computeColumnPixelWidths2 } = deps;
1106
+ const measureText = (b, env) => {
1107
+ const tb = resolveTextBlock(styles, b);
1108
+ const width = Math.max(env.innerWidth, 1);
1109
+ doc.font(getFontNameForText(tb));
1110
+ doc.fontSize(tb.fontSize ?? 10);
1111
+ const h = doc.heightOfString(tb.text ?? "", { width });
1112
+ const gap = tb.lineGap ?? 4;
1113
+ return h + gap;
1114
+ };
1115
+ const measureImageLike = (mt, mb, h) => (mt ?? 0) + h + (mb ?? 0);
1116
+ const measureImage = (b) => {
1117
+ const h = b.height ?? 50;
1118
+ return measureImageLike(b.marginTop, b.marginBottom, h);
1119
+ };
1120
+ const measureQr = (b) => {
1121
+ const size = b.size ?? 80;
1122
+ return measureImageLike(b.marginTop, b.marginBottom, size);
1123
+ };
1124
+ const measureBarcode = (b) => {
1125
+ const h = b.height ?? 40;
1126
+ return measureImageLike(b.marginTop, b.marginBottom, h);
1127
+ };
1128
+ const measureLine = (b) => {
1129
+ const lw = b.lineWidth ?? 1;
1130
+ const mt = b.marginTop ?? 0;
1131
+ const mb = b.marginBottom ?? 0;
1132
+ return mt + lw + mb;
1133
+ };
1134
+ const measureTable = (b, env) => {
1135
+ const mt = b.marginTop ?? 0;
1136
+ const mb = b.marginBottom ?? 0;
1137
+ const ml = b.marginLeft ?? 0;
1138
+ const mr = b.marginRight ?? 0;
1139
+ const innerWidth = Math.max(env.innerWidth - ml - mr, 1);
1140
+ const fakeEnv = {
1141
+ marginLeft: 0,
1142
+ innerWidth,
1143
+ allowPageBreak: false
1144
+ };
1145
+ const h = measureTableHeight(
1146
+ doc,
1147
+ b,
1148
+ fakeEnv,
1149
+ styles,
1150
+ computeColumnPixelWidths2
1151
+ );
1152
+ return mt + h + mb;
1153
+ };
1154
+ const measureColumns = (b, env) => {
1155
+ const mt = b.marginTop ?? 0;
1156
+ const mb = b.marginBottom ?? 0;
1157
+ const blockLeft = b.marginLeft ?? 0;
1158
+ const blockRight = b.marginRight ?? 0;
1159
+ const totalWidth = Math.max(env.innerWidth - blockLeft - blockRight, 1);
1160
+ const cols = b.columns ?? [];
1161
+ const n = cols.length;
1162
+ if (!n) return mt + mb;
1163
+ let colWidths;
1164
+ const mode = b.mode ?? "fixedGap";
1165
+ let gap;
1166
+ if (mode === "spaceBetween" && n > 1) {
1167
+ if (b.widths && b.widths.length === n) {
1168
+ colWidths = computeColumnPixelWidths2(b.widths, totalWidth);
1169
+ } else {
1170
+ colWidths = Array(n).fill(totalWidth / n);
1171
+ }
1172
+ const totalColsWidth = colWidths.reduce((a, x) => a + x, 0);
1173
+ const remaining = Math.max(totalWidth - totalColsWidth, 0);
1174
+ gap = remaining / (n - 1);
1175
+ void gap;
1176
+ } else {
1177
+ gap = b.gap ?? 20;
1178
+ const totalGapsWidth = gap * (n - 1);
1179
+ const widthForCols = Math.max(totalWidth - totalGapsWidth, 1);
1180
+ if (b.widths && b.widths.length === n) {
1181
+ colWidths = computeColumnPixelWidths2(b.widths, widthForCols);
1182
+ } else {
1183
+ colWidths = Array(n).fill(widthForCols / n);
1184
+ }
1185
+ }
1186
+ const heights = [];
1187
+ for (let i = 0; i < n; i++) {
1188
+ const colBlocks = cols[i] ?? [];
1189
+ const colEnv = {
1190
+ marginLeft: 0,
1191
+ innerWidth: colWidths[i],
1192
+ allowPageBreak: false
1193
+ };
1194
+ let colH = 0;
1195
+ for (const child of colBlocks) {
1196
+ if (!child || child.visible === false) continue;
1197
+ colH += measure(child, colEnv);
1198
+ }
1199
+ heights.push(colH);
1200
+ }
1201
+ const maxH = Math.max(...heights, 0);
1202
+ return mt + maxH + mb;
1203
+ };
1204
+ const measureKeyValueGrid = (b, env) => {
1205
+ const mt = b.marginTop ?? 0;
1206
+ const mb = b.marginBottom ?? 0;
1207
+ const rowGap = b.rowGap ?? 4;
1208
+ const orientation = b.orientation ?? "horizontal";
1209
+ const cols = b.columns ?? [];
1210
+ const colCount = cols.length;
1211
+ if (!colCount) return mt + mb;
1212
+ const blockLeft = b.marginLeft ?? 0;
1213
+ const blockRight = b.marginRight ?? 0;
1214
+ const totalWidth = Math.max(env.innerWidth - blockLeft - blockRight, 1);
1215
+ let colWidths;
1216
+ if (b.columnWidths && b.columnWidths.length === colCount) {
1217
+ const safe = b.columnWidths.map((w) => w === void 0 ? "*" : w);
1218
+ colWidths = computeColumnPixelWidths2(safe, totalWidth);
1219
+ } else {
1220
+ colWidths = Array(colCount).fill(totalWidth / colCount);
1221
+ }
1222
+ const separatorText = b.separator;
1223
+ const sepBoxWidth = separatorText ? 10 : 0;
1224
+ const baseKeyWidthRatio = 0.35;
1225
+ const measureKVText = (tb, width) => {
1226
+ const r = resolveTextBlock(styles, tb);
1227
+ const fontName = getFontNameForText(r);
1228
+ doc.font(fontName);
1229
+ doc.fontSize(r.fontSize ?? 10);
1230
+ return doc.heightOfString(r.text ?? "", { width });
1231
+ };
1232
+ let totalHeight = mt;
1233
+ if (orientation === "vertical") {
1234
+ const keyValueGap = b.verticalKeyValueGap ?? 2;
1235
+ let maxColHeight = 0;
1236
+ for (let colIndex = 0; colIndex < colCount; colIndex++) {
1237
+ const col = cols[colIndex] ?? [];
1238
+ const colWidth = colWidths[colIndex];
1239
+ let colHeight = 0;
1240
+ for (const item of col) {
1241
+ const keyH = measureKVText(
1242
+ { type: "text", text: item.key ?? "" },
1243
+ colWidth
1244
+ );
1245
+ const valH = measureKVText(
1246
+ { type: "text", text: item.value ?? "" },
1247
+ colWidth
1248
+ );
1249
+ colHeight += keyH + keyValueGap + valH + rowGap;
1250
+ }
1251
+ if (colHeight > maxColHeight) maxColHeight = colHeight;
1252
+ }
1253
+ totalHeight += maxColHeight;
1254
+ } else {
1255
+ const maxRows = Math.max(...cols.map((c) => c ? c.length : 0), 0);
1256
+ for (let rowIndex = 0; rowIndex < maxRows; rowIndex++) {
1257
+ let rowHeight = 0;
1258
+ for (let colIndex = 0; colIndex < colCount; colIndex++) {
1259
+ const item = cols[colIndex]?.[rowIndex];
1260
+ if (!item) continue;
1261
+ const colWidth = colWidths[colIndex];
1262
+ const keyWidthPx = b.keyWidth === "*" ? Math.max(colWidth * baseKeyWidthRatio, 20) : b.keyWidth ?? 80;
1263
+ const keyH = measureKVText(
1264
+ { type: "text", text: item.key ?? "" },
1265
+ keyWidthPx
1266
+ );
1267
+ const valueXInsideCol = keyWidthPx + (separatorText ? sepBoxWidth + 4 : 4);
1268
+ const valueWidth = Math.max(colWidth - valueXInsideCol, 1);
1269
+ const valH = measureKVText(
1270
+ { type: "text", text: item.value ?? "" },
1271
+ valueWidth
1272
+ );
1273
+ rowHeight = Math.max(rowHeight, Math.max(keyH, valH));
1274
+ }
1275
+ if (rowHeight > 0) totalHeight += rowHeight + rowGap;
1276
+ }
1277
+ }
1278
+ totalHeight += mb;
1279
+ return totalHeight;
1280
+ };
1281
+ const measure = (block, env) => {
1282
+ if (!block || block.visible === false) return 0;
1283
+ switch (block.type) {
1284
+ case "text":
1285
+ return measureText(block, env);
1286
+ case "image":
1287
+ return measureImage(block);
1288
+ case "qr":
1289
+ return measureQr(block);
1290
+ case "barcode":
1291
+ return measureBarcode(block);
1292
+ case "line":
1293
+ return measureLine(block);
1294
+ case "table":
1295
+ return measureTable(block, env);
1296
+ case "columns":
1297
+ return measureColumns(block, env);
1298
+ case "keyValueGrid":
1299
+ return measureKeyValueGrid(block, env);
1300
+ case "signature":
1301
+ return block.height ?? 0;
1302
+ case "pageBreak":
1303
+ return 0;
1304
+ default:
1305
+ return 0;
1306
+ }
1307
+ };
1308
+ return (block, env) => measure(block, env);
1309
+ }
1310
+
1311
+ // src/renderer-engine/utils/page-background.ts
1312
+ function drawPageBackground(doc, pageBackground) {
1313
+ if (!pageBackground) return;
1314
+ const { src, opacity = 1 } = pageBackground;
1315
+ const pageWidth = doc.page.width;
1316
+ const pageHeight = doc.page.height;
1317
+ doc.save();
1318
+ try {
1319
+ if (opacity < 1) {
1320
+ doc.opacity(opacity);
1321
+ }
1322
+ doc.image(src, 0, 0, {
1323
+ width: pageWidth,
1324
+ height: pageHeight
1325
+ });
1326
+ } catch (e) {
1327
+ console.warn("Failed to load page background image:", e);
1328
+ }
1329
+ doc.restore();
1330
+ doc.opacity(1);
1331
+ }
1332
+
1333
+ // src/renderer-engine/utils/page-limit.ts
1334
+ function createBottomLimitForContent(doc, ctx) {
1335
+ return () => {
1336
+ const pageBottomForContent = doc.page.height - doc.page.margins.bottom;
1337
+ return ctx.signatureTopY ?? pageBottomForContent;
1338
+ };
1339
+ }
1340
+
1341
+ // src/renderer-engine/utils/qr-bar-code.ts
1342
+ var import_bwip_js = __toESM(require("bwip-js"));
1343
+ var import_qrcode = __toESM(require("qrcode"));
1344
+ function generateQrBuffer(value, size, version, errorCorrectionLevel) {
1345
+ const options = {
1346
+ width: size,
1347
+ margin: 0
1348
+ };
1349
+ if (version && version >= 1 && version <= 40) {
1350
+ options.version = version;
1351
+ }
1352
+ options.errorCorrectionLevel = errorCorrectionLevel ?? "M";
1353
+ return new Promise((resolve, reject) => {
1354
+ import_qrcode.default.toBuffer(value, options, (err, buffer) => {
1355
+ if (err) {
1356
+ return reject(err);
1357
+ }
1358
+ resolve(buffer);
1359
+ });
1360
+ });
1361
+ }
1362
+ function mapBarcodeTypeToBcid(bcType) {
1363
+ switch (bcType) {
1364
+ case "EAN13":
1365
+ return "ean13";
1366
+ case "CODE39":
1367
+ return "code39";
1368
+ case "ITF":
1369
+ return "interleaved2of5";
1370
+ case "CODE93":
1371
+ return "code93";
1372
+ case "CODE128":
1373
+ default:
1374
+ return "code128";
1375
+ }
1376
+ }
1377
+ function generateBarcodeBuffer(value, options = {}) {
1378
+ const {
1379
+ bcType,
1380
+ scale = 3,
1381
+ barHeight = 10,
1382
+ includetext = false,
1383
+ textalign = "center"
1384
+ } = options;
1385
+ const bcid = mapBarcodeTypeToBcid(bcType);
1386
+ return new Promise((resolve, reject) => {
1387
+ let textValue = value;
1388
+ if (bcType === "EAN13") {
1389
+ const digitsOnly = textValue.replace(/\D/g, "");
1390
+ if (digitsOnly.length === 13) {
1391
+ textValue = digitsOnly.slice(0, 12);
1392
+ } else if (digitsOnly.length === 12) {
1393
+ textValue = textValue;
1394
+ } else {
1395
+ return reject(
1396
+ new Error(
1397
+ `EAN13 barcode value must have 12 or 13 digits, got "${value}"`
1398
+ )
1399
+ );
1400
+ }
1401
+ }
1402
+ const bwipOptions = {
1403
+ bcid,
1404
+ text: textValue,
1405
+ scale,
1406
+ height: barHeight,
1407
+ includetext
1408
+ };
1409
+ bwipOptions.textxalign = textalign;
1410
+ import_bwip_js.default.toBuffer(bwipOptions, (err, png) => {
1411
+ if (err) {
1412
+ return reject(err);
1413
+ }
1414
+ resolve(png);
1415
+ });
1416
+ });
1417
+ }
1418
+ async function materializeQrAndBarcodesInBlocks(blocks) {
1419
+ const out = [];
1420
+ for (const block of blocks) {
1421
+ if (block.type === "columns") {
1422
+ const colBlock = block;
1423
+ const newCols = [];
1424
+ for (const col of colBlock.columns) {
1425
+ newCols.push(await materializeQrAndBarcodesInBlocks(col));
1426
+ }
1427
+ out.push({
1428
+ ...colBlock,
1429
+ columns: newCols
1430
+ });
1431
+ } else if (block.type === "signature") {
1432
+ const sig = block;
1433
+ if (sig.blocks && sig.blocks.length) {
1434
+ const newInner = await materializeQrAndBarcodesInBlocks(sig.blocks);
1435
+ out.push({
1436
+ ...sig,
1437
+ blocks: newInner
1438
+ });
1439
+ } else {
1440
+ out.push(block);
1441
+ }
1442
+ } else if (block.type === "qr") {
1443
+ const qb = { ...block };
1444
+ if (!qb.src && qb.value) {
1445
+ const size = qb.size ?? 80;
1446
+ const buf = await generateQrBuffer(
1447
+ qb.value,
1448
+ size,
1449
+ qb.qrVersion,
1450
+ qb.errorCorrectionLevel
1451
+ );
1452
+ qb.src = buf;
1453
+ }
1454
+ out.push(qb);
1455
+ } else if (block.type === "barcode") {
1456
+ const bb = { ...block };
1457
+ if (!bb.src && bb.value) {
1458
+ const buf = await generateBarcodeBuffer(bb.value, {
1459
+ bcType: bb.bcType,
1460
+ scale: bb.scale,
1461
+ barHeight: bb.barHeight,
1462
+ includetext: bb.includetext,
1463
+ textalign: bb.textalign
1464
+ });
1465
+ bb.src = buf;
1466
+ }
1467
+ out.push(bb);
1468
+ } else {
1469
+ out.push(block);
1470
+ }
1471
+ }
1472
+ return out;
1473
+ }
1474
+
1475
+ // src/renderer-engine/utils/signature.ts
1476
+ function drawSignatureBlock(doc, block, y, env, renderBlockArray) {
1477
+ const localLeft = block.marginLeft ?? 0;
1478
+ const localRight = block.marginRight ?? 0;
1479
+ const bandLeft = env.marginLeft + localLeft;
1480
+ const bandWidth = Math.max(env.innerWidth - localLeft - localRight, 1);
1481
+ const bandHeight = block.height;
1482
+ doc.save();
1483
+ doc.rect(bandLeft, y, bandWidth, bandHeight).clip();
1484
+ if (block.blocks && block.blocks.length) {
1485
+ const sigEnv = {
1486
+ marginLeft: bandLeft,
1487
+ innerWidth: bandWidth,
1488
+ allowPageBreak: false
1489
+ };
1490
+ renderBlockArray(block.blocks, y, sigEnv);
1491
+ } else {
1492
+ const imgWidth = block.width ?? 120;
1493
+ const xCenter = bandLeft + (bandWidth - imgWidth) / 2;
1494
+ if (block.image) {
1495
+ try {
1496
+ doc.image(block.image, xCenter, y, { width: imgWidth });
1497
+ } catch (e) {
1498
+ console.warn("Failed to load signature image:", e);
1499
+ }
1500
+ }
1501
+ const label = block.label ?? "Authorized Signatory";
1502
+ const labelY = y + bandHeight - 14;
1503
+ doc.fontSize(9).text(label, bandLeft, labelY, {
1504
+ width: bandWidth,
1505
+ align: "center"
1506
+ });
1507
+ }
1508
+ doc.restore();
1509
+ }
1510
+ function createProcessSignatureBlock({
1511
+ doc,
1512
+ ctx,
1513
+ styles,
1514
+ finishPage: finishPage2,
1515
+ contentEnvFn
1516
+ }) {
1517
+ return (block) => {
1518
+ if (ctx.signatureBlock) {
1519
+ finishPage2(true);
1520
+ }
1521
+ const env = contentEnvFn(doc);
1522
+ const localLeft = block.marginLeft ?? 0;
1523
+ const localRight = block.marginRight ?? 0;
1524
+ const bandWidth = Math.max(env.innerWidth - localLeft - localRight, 1);
1525
+ let requiredHeight = block.height;
1526
+ if (block.blocks && block.blocks.length) {
1527
+ let required = 0;
1528
+ const measureImageLike = (mt, mb, h) => {
1529
+ return (mt ?? 0) + h + (mb ?? 0);
1530
+ };
1531
+ const measureColumns = (c) => {
1532
+ const blockLeft = c.marginLeft ?? 0;
1533
+ const blockRight = c.marginRight ?? 0;
1534
+ const totalWidth = Math.max(bandWidth - blockLeft - blockRight, 1);
1535
+ const cols = c.columns;
1536
+ const n = cols.length;
1537
+ if (!n) return (c.marginTop ?? 0) + (c.marginBottom ?? 0);
1538
+ let colWidths;
1539
+ let gap;
1540
+ const mode = c.mode ?? "fixedGap";
1541
+ if (mode === "spaceBetween" && n > 1) {
1542
+ if (c.widths && c.widths.length === n) {
1543
+ colWidths = computeColumnPixelWidths(c.widths, totalWidth);
1544
+ } else {
1545
+ const equal = totalWidth / n;
1546
+ colWidths = Array(n).fill(equal);
1547
+ }
1548
+ const totalColsWidth = colWidths.reduce((a, b) => a + b, 0);
1549
+ const remaining = Math.max(totalWidth - totalColsWidth, 0);
1550
+ gap = remaining / (n - 1);
1551
+ } else {
1552
+ gap = c.gap ?? 20;
1553
+ const totalGapsWidth = gap * (n - 1);
1554
+ const widthForCols = Math.max(totalWidth - totalGapsWidth, 1);
1555
+ if (c.widths && c.widths.length === n) {
1556
+ colWidths = computeColumnPixelWidths(c.widths, widthForCols);
1557
+ } else {
1558
+ const equal = widthForCols / n;
1559
+ colWidths = Array(n).fill(equal);
1560
+ }
1561
+ }
1562
+ const mt = c.marginTop ?? 0;
1563
+ const mb = c.marginBottom ?? 0;
1564
+ const colHeights = [];
1565
+ cols.forEach((colBlocks, idx) => {
1566
+ const colEnv = {
1567
+ marginLeft: 0,
1568
+ innerWidth: colWidths[idx],
1569
+ allowPageBreak: false
1570
+ };
1571
+ let colY = 0;
1572
+ for (const b of colBlocks) {
1573
+ colY += measureInnerBlock(b, colEnv);
1574
+ }
1575
+ colHeights.push(colY);
1576
+ });
1577
+ const maxColHeight = Math.max(...colHeights, 0);
1578
+ return mt + maxColHeight + mb;
1579
+ };
1580
+ const innerEnv = {
1581
+ marginLeft: 0,
1582
+ innerWidth: bandWidth,
1583
+ allowPageBreak: false
1584
+ };
1585
+ const measureInnerBlock = (b, envForColumns) => {
1586
+ switch (b.type) {
1587
+ case "text": {
1588
+ const tb = resolveTextBlock(styles, b);
1589
+ const localLeft2 = tb.marginLeft ?? 0;
1590
+ const localRight2 = tb.marginRight ?? 0;
1591
+ const width = Math.max(
1592
+ envForColumns.innerWidth - localLeft2 - localRight2,
1593
+ 1
1594
+ );
1595
+ doc.fontSize(tb.fontSize ?? 10);
1596
+ const isBold = !!tb.bold;
1597
+ const isItalic = !!tb.italic;
1598
+ let fontName = tb.font;
1599
+ if (!fontName) {
1600
+ if (isBold && isItalic) fontName = "Helvetica-BoldOblique";
1601
+ else if (isBold) fontName = "Helvetica-Bold";
1602
+ else if (isItalic) fontName = "Helvetica-Oblique";
1603
+ else fontName = "Helvetica";
1604
+ }
1605
+ doc.font(fontName);
1606
+ const h = doc.heightOfString(tb.text, { width });
1607
+ const gap = tb.lineGap ?? 4;
1608
+ return h + gap;
1609
+ }
1610
+ case "image": {
1611
+ const ib = b;
1612
+ const h = ib.height ?? 50;
1613
+ return measureImageLike(ib.marginTop, ib.marginBottom, h);
1614
+ }
1615
+ case "qr": {
1616
+ const qb = b;
1617
+ const size = qb.size ?? 80;
1618
+ return measureImageLike(qb.marginTop, qb.marginBottom, size);
1619
+ }
1620
+ case "barcode": {
1621
+ const bb = b;
1622
+ const h = bb.height ?? 40;
1623
+ return measureImageLike(bb.marginTop, bb.marginBottom, h);
1624
+ }
1625
+ case "line": {
1626
+ const lb = b;
1627
+ const lw = lb.lineWidth ?? 1;
1628
+ const mt = lb.marginTop ?? 0;
1629
+ const mb = lb.marginBottom ?? 0;
1630
+ return mt + lw + mb;
1631
+ }
1632
+ case "table": {
1633
+ const t = b;
1634
+ const fakeEnv = {
1635
+ marginLeft: t.marginLeft ?? 0,
1636
+ innerWidth: bandWidth - (t.marginLeft ?? 0) - (t.marginRight ?? 0),
1637
+ allowPageBreak: false
1638
+ };
1639
+ return measureTableHeight(
1640
+ doc,
1641
+ t,
1642
+ fakeEnv,
1643
+ styles,
1644
+ computeColumnPixelWidths
1645
+ );
1646
+ }
1647
+ case "columns":
1648
+ return measureColumns(b);
1649
+ case "signature":
1650
+ return b.height;
1651
+ default:
1652
+ return 0;
1653
+ }
1654
+ };
1655
+ for (const inner of block.blocks) {
1656
+ required += measureInnerBlock(inner, innerEnv);
1657
+ }
1658
+ requiredHeight = Math.max(requiredHeight, required);
1659
+ }
1660
+ const sigHeight = requiredHeight;
1661
+ const pageHeight = doc.page.height;
1662
+ const candidateTop = pageHeight - doc.page.margins.bottom - sigHeight;
1663
+ if (ctx.currentY > candidateTop) {
1664
+ finishPage2(true);
1665
+ }
1666
+ const newPageHeight = doc.page.height;
1667
+ const newCandidateTop = newPageHeight - doc.page.margins.bottom - sigHeight;
1668
+ ctx.signatureBlock = { ...block, height: sigHeight };
1669
+ ctx.signatureTopY = newCandidateTop;
1670
+ ctx.signatureHeight = sigHeight;
1671
+ ctx.signaturePlaced = true;
1672
+ ctx.afterSignature = true;
1673
+ };
1674
+ }
1675
+
1676
+ // src/renderer-engine/utils/start-page-layout.ts
1677
+ function createStartNewPageLayout({
1678
+ doc,
1679
+ def,
1680
+ ctx,
1681
+ headerBandHeight,
1682
+ renderBlockArray
1683
+ }) {
1684
+ return () => {
1685
+ drawPageBackground(doc, def.pageBackground);
1686
+ drawHeader(
1687
+ doc,
1688
+ def,
1689
+ headerBandHeight,
1690
+ def.header ?? void 0,
1691
+ renderBlockArray
1692
+ );
1693
+ const mode = def.watermark?.mode;
1694
+ if (def.watermark && !watermarkUsesLast(mode)) {
1695
+ drawWatermarkForPage(doc, def.watermark, ctx.pageNumber, false);
1696
+ }
1697
+ ctx.currentY = doc.page.margins.top;
1698
+ ctx.signatureBlock = null;
1699
+ ctx.signatureTopY = null;
1700
+ ctx.signatureHeight = 0;
1701
+ ctx.signaturePlaced = false;
1702
+ ctx.afterSignature = false;
1703
+ };
1704
+ }
1705
+
1706
+ // src/renderer-engine/utils/watermark.ts
1707
+ function watermarkUsesLast(mode) {
1708
+ return mode === "last" || mode === "firstLast" || mode === "exceptLast" || mode === "exceptFirstLast";
1709
+ }
1710
+ function drawWatermarkForPage(doc, watermark, pageNumber, isLast) {
1711
+ const {
1712
+ text,
1713
+ opacity = 0.06,
1714
+ fontSize = 60,
1715
+ color = "gray",
1716
+ angle = 45,
1717
+ mode = "all"
1718
+ } = watermark;
1719
+ const shouldDraw = (() => {
1720
+ switch (mode) {
1721
+ case "all":
1722
+ return true;
1723
+ case "first":
1724
+ return pageNumber === 1;
1725
+ case "last":
1726
+ return isLast;
1727
+ case "firstLast":
1728
+ return pageNumber === 1 || isLast;
1729
+ case "exceptFirstLast":
1730
+ return pageNumber !== 1 && !isLast;
1731
+ case "exceptFirst":
1732
+ return pageNumber !== 1;
1733
+ case "exceptLast":
1734
+ return !isLast;
1735
+ default:
1736
+ return true;
1737
+ }
1738
+ })();
1739
+ if (!shouldDraw) return;
1740
+ const centerX = doc.page.width / 2;
1741
+ const centerY = doc.page.height / 2;
1742
+ doc.save();
1743
+ doc.fillColor(color);
1744
+ doc.opacity(opacity);
1745
+ doc.fontSize(fontSize);
1746
+ const textWidth = doc.widthOfString(text);
1747
+ const textHeight = doc.currentLineHeight();
1748
+ const x = centerX - textWidth / 2;
1749
+ const y = centerY - textHeight / 2;
1750
+ doc.rotate(angle, { origin: [centerX, centerY] });
1751
+ doc.text(text, x, y);
1752
+ doc.restore();
1753
+ doc.opacity(1);
1754
+ }
1755
+
1756
+ // src/renderer-engine/index.ts
1757
+ async function renderCustomPdf(def, outputPath) {
1758
+ if (def.header) {
1759
+ def.header.blocks = await materializeQrAndBarcodesInBlocks(
1760
+ def.header.blocks
1761
+ );
1762
+ def.header.blocks = await materializeImagesInBlocks(def.header.blocks);
1763
+ }
1764
+ def.content = await materializeQrAndBarcodesInBlocks(def.content);
1765
+ def.content = await materializeImagesInBlocks(def.content);
1766
+ if (def.pageBackground?.src) {
1767
+ def.pageBackground.src = await normalizeImageSrc(def.pageBackground.src);
1768
+ }
1769
+ if (def.header?.backgroundImage) {
1770
+ def.header.backgroundImage = await normalizeImageSrc(
1771
+ def.header.backgroundImage
1772
+ );
1773
+ }
1774
+ if (def.footer && typeof def.footer !== "function") {
1775
+ const footer = def.footer;
1776
+ if (footer.backgroundImage) {
1777
+ footer.backgroundImage = await normalizeImageSrc(footer.backgroundImage);
1778
+ }
1779
+ }
1780
+ return new Promise((resolve, reject) => {
1781
+ const headerBandHeight = def.margins.top ?? 0;
1782
+ const footerBandHeight = def.margins.bottom ?? 0;
1783
+ const doc = new import_pdfkit.default({
1784
+ size: def.pageSize || "A4",
1785
+ margins: {
1786
+ top: headerBandHeight,
1787
+ bottom: footerBandHeight,
1788
+ left: def.margins.left,
1789
+ right: def.margins.right
1790
+ }
1791
+ });
1792
+ if (def.fonts && def.fonts.length) {
1793
+ for (const f of def.fonts) {
1794
+ try {
1795
+ doc.registerFont(f.name, f.src);
1796
+ } catch (e) {
1797
+ console.warn("Failed to register font:", f.name, e);
1798
+ }
1799
+ }
1800
+ }
1801
+ const stream = import_fs.default.createWriteStream(outputPath);
1802
+ doc.pipe(stream);
1803
+ const ctx = createInitialContext(doc);
1804
+ const styles = def.styles ?? {};
1805
+ const finishPage2 = (addNewPage) => finishPage({
1806
+ addNewPage,
1807
+ doc,
1808
+ def,
1809
+ ctx,
1810
+ footerBandHeight,
1811
+ renderBlockArray,
1812
+ startNewPageLayout
1813
+ });
1814
+ const processSignatureBlock = createProcessSignatureBlock({
1815
+ doc,
1816
+ ctx,
1817
+ styles,
1818
+ finishPage: finishPage2,
1819
+ contentEnvFn: contentEnv
1820
+ });
1821
+ const { renderBlock, renderBlockArray } = createBlockRenderer({
1822
+ doc,
1823
+ ctx,
1824
+ styles,
1825
+ computeColumnPixelWidths,
1826
+ finishPage: finishPage2,
1827
+ processSignatureBlock
1828
+ });
1829
+ const startNewPageLayout = createStartNewPageLayout({
1830
+ doc,
1831
+ def,
1832
+ ctx,
1833
+ headerBandHeight,
1834
+ renderBlockArray
1835
+ });
1836
+ startNewPageLayout();
1837
+ for (const block of def.content) {
1838
+ if (block.type === "signature") {
1839
+ processSignatureBlock(block);
1840
+ continue;
1841
+ }
1842
+ if (ctx.afterSignature) {
1843
+ finishPage2(true);
1844
+ ctx.afterSignature = false;
1845
+ }
1846
+ renderBlock(block, null, contentEnv(doc));
1847
+ }
1848
+ finishPage2(false);
1849
+ doc.end();
1850
+ stream.on("finish", () => resolve());
1851
+ stream.on("error", (err) => reject(err));
1852
+ });
1853
+ }
1854
+ async function renderCustomPdfToBuffer(def) {
1855
+ if (def.header) {
1856
+ def.header.blocks = await materializeQrAndBarcodesInBlocks(
1857
+ def.header.blocks
1858
+ );
1859
+ def.header.blocks = await materializeImagesInBlocks(def.header.blocks);
1860
+ }
1861
+ def.content = await materializeQrAndBarcodesInBlocks(def.content);
1862
+ def.content = await materializeImagesInBlocks(def.content);
1863
+ if (def.pageBackground?.src) {
1864
+ def.pageBackground.src = await normalizeImageSrc(def.pageBackground.src);
1865
+ }
1866
+ if (def.header?.backgroundImage) {
1867
+ def.header.backgroundImage = await normalizeImageSrc(
1868
+ def.header.backgroundImage
1869
+ );
1870
+ }
1871
+ if (def.footer && typeof def.footer !== "function") {
1872
+ const footer = def.footer;
1873
+ if (footer.backgroundImage) {
1874
+ footer.backgroundImage = await normalizeImageSrc(footer.backgroundImage);
1875
+ }
1876
+ }
1877
+ return new Promise((resolve, reject) => {
1878
+ const headerBandHeight = def.margins.top ?? 0;
1879
+ const footerBandHeight = def.margins.bottom ?? 0;
1880
+ const doc = new import_pdfkit.default({
1881
+ size: def.pageSize || "A4",
1882
+ margins: {
1883
+ top: headerBandHeight,
1884
+ bottom: footerBandHeight,
1885
+ left: def.margins.left,
1886
+ right: def.margins.right
1887
+ }
1888
+ });
1889
+ const chunks = [];
1890
+ doc.on("data", (chunk) => {
1891
+ chunks.push(chunk);
1892
+ });
1893
+ doc.on("end", () => {
1894
+ resolve(Buffer.concat(chunks));
1895
+ });
1896
+ doc.on("error", (err) => {
1897
+ reject(err);
1898
+ });
1899
+ if (def.fonts && def.fonts.length) {
1900
+ for (const f of def.fonts) {
1901
+ try {
1902
+ doc.registerFont(f.name, f.src);
1903
+ } catch (e) {
1904
+ console.warn("Failed to register font:", f.name, e);
1905
+ }
1906
+ }
1907
+ }
1908
+ const ctx = createInitialContext(doc);
1909
+ const styles = def.styles ?? {};
1910
+ const finishPage2 = (addNewPage) => finishPage({
1911
+ addNewPage,
1912
+ doc,
1913
+ def,
1914
+ ctx,
1915
+ footerBandHeight,
1916
+ renderBlockArray,
1917
+ startNewPageLayout
1918
+ });
1919
+ const processSignatureBlock = createProcessSignatureBlock({
1920
+ doc,
1921
+ ctx,
1922
+ styles,
1923
+ finishPage: finishPage2,
1924
+ contentEnvFn: contentEnv
1925
+ });
1926
+ const { renderBlock, renderBlockArray } = createBlockRenderer({
1927
+ doc,
1928
+ ctx,
1929
+ styles,
1930
+ computeColumnPixelWidths,
1931
+ finishPage: finishPage2,
1932
+ processSignatureBlock
1933
+ });
1934
+ const startNewPageLayout = createStartNewPageLayout({
1935
+ doc,
1936
+ def,
1937
+ ctx,
1938
+ headerBandHeight,
1939
+ renderBlockArray
1940
+ });
1941
+ startNewPageLayout();
1942
+ for (const block of def.content) {
1943
+ if (block.type === "signature") {
1944
+ processSignatureBlock(block);
1945
+ continue;
1946
+ }
1947
+ if (ctx.afterSignature) {
1948
+ finishPage2(true);
1949
+ ctx.afterSignature = false;
1950
+ }
1951
+ renderBlock(block, null, contentEnv(doc));
1952
+ }
1953
+ finishPage2(false);
1954
+ doc.end();
1955
+ });
1956
+ }
1957
+
1958
+ // src/types/barcode.ts
1959
+ var BARCODE_TYPES = {
1960
+ CODE128: "CODE128",
1961
+ EAN13: "EAN13",
1962
+ CODE39: "CODE39",
1963
+ ITF: "ITF",
1964
+ CODE93: "CODE93"
1965
+ };
1966
+
1967
+ // src/types/qr.ts
1968
+ var QR_ERROR_LEVEL = {
1969
+ LOW: "L",
1970
+ MEDIUM: "M",
1971
+ QUARTILE: "Q",
1972
+ HIGH: "H"
1973
+ };
1974
+ // Annotate the CommonJS export names for ESM import in node:
1975
+ 0 && (module.exports = {
1976
+ BARCODE_TYPES,
1977
+ QR_ERROR_LEVEL,
1978
+ renderCustomPdf,
1979
+ renderCustomPdfToBuffer
1980
+ });