@pdfme/schemas 6.2.3-dev.6 → 6.2.3-dev.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,394 @@
1
1
  import { A as getBoxVerticalInset, D as getBoxContentArea, E as createBoxDimension, F as ALIGN_LEFT, I as ALIGN_RIGHT, N as ALIGN_CENTER, O as getBoxDimensionPropPanelSchema, V as DEFAULT_FONT_COLOR, b as splitTextToSize, g as getFontKitFont, it as VERTICAL_ALIGN_MIDDLE, l as getTableBodyRange, o as createTableBodySplitRange, rt as VERTICAL_ALIGN_BOTTOM, x as widthOfTextAtSize, z as DEFAULT_ALIGNMENT } from "./splitRange-B6311Noc.js";
2
2
  import { cloneDeep, getDefaultFont, getFallbackFontName, isBlankPdf, mm2pt, pt2mm } from "@pdfme/common";
3
+ import { Buffer } from "buffer";
4
+ import jpegJsModule from "jpeg-js";
5
+ import UPNGModule from "@pdf-lib/upng";
6
+ //#region src/graphics/imagehelper.ts
7
+ var decoder = new TextDecoder();
8
+ var toUTF8String = (input, start = 0, end = input.length) => decoder.decode(input.slice(start, end));
9
+ var toHexString = (input, start = 0, end = input.length) => input.slice(start, end).reduce((memo, i) => memo + ("0" + i.toString(16)).slice(-2), "");
10
+ var readUInt16BE = (input, offset = 0) => input[offset] * 256 + input[offset + 1];
11
+ var readUInt32BE = (input, offset = 0) => input[offset] * 2 ** 24 + input[offset + 1] * 2 ** 16 + input[offset + 2] * 256 + input[offset + 3];
12
+ var extractSize = (input, index) => {
13
+ return {
14
+ height: readUInt16BE(input, index),
15
+ width: readUInt16BE(input, index + 2)
16
+ };
17
+ };
18
+ var validateInput = (input, index) => {
19
+ if (index > input.length) throw new TypeError("Corrupt JPG, exceeded buffer limits");
20
+ if (input[index] !== 255) throw new TypeError("Invalid JPG, marker table corrupted");
21
+ };
22
+ var JPG = {
23
+ validate: (input) => toHexString(input, 0, 2) === "ffd8",
24
+ calculate(input) {
25
+ input = input.slice(4);
26
+ let next;
27
+ while (input.length) {
28
+ const i = readUInt16BE(input, 0);
29
+ validateInput(input, i);
30
+ next = input[i + 1];
31
+ if (next === 192 || next === 193 || next === 194) return extractSize(input, i + 5);
32
+ input = input.slice(i + 2);
33
+ }
34
+ throw new TypeError("Invalid JPG, no size found");
35
+ }
36
+ };
37
+ var pngSignature = "PNG\r\n\n";
38
+ var pngImageHeaderChunkName = "IHDR";
39
+ var pngFriedChunkName = "CgBI";
40
+ var typeHandlers = {
41
+ jpg: JPG,
42
+ png: {
43
+ validate(input) {
44
+ if (pngSignature === toUTF8String(input, 1, 8)) {
45
+ let chunkName = toUTF8String(input, 12, 16);
46
+ if (chunkName === pngFriedChunkName) chunkName = toUTF8String(input, 28, 32);
47
+ if (chunkName !== pngImageHeaderChunkName) throw new TypeError("Invalid PNG");
48
+ return true;
49
+ }
50
+ return false;
51
+ },
52
+ calculate(input) {
53
+ if (toUTF8String(input, 12, 16) === pngFriedChunkName) return {
54
+ height: readUInt32BE(input, 36),
55
+ width: readUInt32BE(input, 32)
56
+ };
57
+ return {
58
+ height: readUInt32BE(input, 20),
59
+ width: readUInt32BE(input, 16)
60
+ };
61
+ }
62
+ }
63
+ };
64
+ function detector(input) {
65
+ const firstBytes = {
66
+ 137: "png",
67
+ 255: "jpg"
68
+ };
69
+ const byte = input[0];
70
+ if (byte in firstBytes) {
71
+ const type = firstBytes[byte];
72
+ if (type && typeHandlers[type].validate(input)) return type;
73
+ }
74
+ return Object.keys(typeHandlers).find((key) => typeHandlers[key].validate(input));
75
+ }
76
+ /**
77
+ * FNV-1a 32-bit fingerprint of an image data URL.
78
+ * Image embed cache keys are `${type}:${length}:${hash}` and must keep this hash.
79
+ */
80
+ var hashImageDataUrl = (value) => {
81
+ let hash = 2166136261;
82
+ for (let i = 0; i < value.length; i++) {
83
+ hash ^= value.charCodeAt(i);
84
+ hash = Math.imul(hash, 16777619);
85
+ }
86
+ return (hash >>> 0).toString(16).padStart(8, "0");
87
+ };
88
+ var getImageDimension = (value) => {
89
+ if (typeof value !== "string") return imageSize(Buffer.from(value));
90
+ const idx = value.indexOf(";base64,");
91
+ const imgBase64 = value.substring(idx + 8, value.length);
92
+ return imageSize(Buffer.from(imgBase64, "base64"));
93
+ };
94
+ var imageSize = (imgBuffer) => {
95
+ const type = detector(imgBuffer);
96
+ if (typeof type !== "undefined" && type in typeHandlers) {
97
+ const size = typeHandlers[type].calculate(imgBuffer);
98
+ if (size !== void 0) return size;
99
+ }
100
+ throw new TypeError("[@pdfme/schemas/images] Unsupported file type: " + (type === void 0 ? "undefined" : type));
101
+ };
102
+ //#endregion
103
+ //#region src/graphics/orientation.ts
104
+ var isJpegJsApi = (value) => !!value && typeof value === "object" && typeof value.decode === "function" && typeof value.encode === "function";
105
+ var isUPNGApi = (value) => !!value && typeof value === "object" && typeof value.decode === "function" && typeof value.toRGBA8 === "function" && typeof value.encode === "function";
106
+ var resolveExport = (value, guard, label) => {
107
+ let current = value;
108
+ while (current && typeof current === "object") {
109
+ if (guard(current)) return current;
110
+ current = current.default;
111
+ }
112
+ throw new TypeError(`Failed to resolve ${label} exports`);
113
+ };
114
+ var jpegJs = resolveExport(jpegJsModule, isJpegJsApi, "jpeg-js");
115
+ var UPNG = resolveExport(UPNGModule, isUPNGApi, "@pdf-lib/upng");
116
+ var JPEG_ENCODE_QUALITY = 90;
117
+ var JPEG_MAX_MEMORY_MB = 512;
118
+ var JPEG_SOI_0 = 255;
119
+ var JPEG_SOI_1 = 216;
120
+ var PNG_SIGNATURE = new Uint8Array([
121
+ 137,
122
+ 80,
123
+ 78,
124
+ 71,
125
+ 13,
126
+ 10,
127
+ 26,
128
+ 10
129
+ ]);
130
+ var toArrayBuffer = (bytes) => {
131
+ const copy = new Uint8Array(bytes.byteLength);
132
+ copy.set(bytes);
133
+ return copy.buffer;
134
+ };
135
+ var isPngSignature = (bytes) => {
136
+ if (bytes.length < PNG_SIGNATURE.length) return false;
137
+ for (let i = 0; i < PNG_SIGNATURE.length; i++) if (bytes[i] !== PNG_SIGNATURE[i]) return false;
138
+ return true;
139
+ };
140
+ var detectImageFormat = (bytes) => {
141
+ if (bytes.length >= 2 && bytes[0] === JPEG_SOI_0 && bytes[1] === JPEG_SOI_1) return "jpeg";
142
+ if (isPngSignature(bytes)) return "png";
143
+ return "other";
144
+ };
145
+ /** TIFF/IFD0: returns 1..8 or undefined. Never throws. */
146
+ var parseTiffOrientation = (tiff) => {
147
+ try {
148
+ if (tiff.length < 8) return void 0;
149
+ const le = tiff[0] === 73 && tiff[1] === 73;
150
+ if (!le && !(tiff[0] === 77 && tiff[1] === 77)) return void 0;
151
+ const view = new DataView(tiff.buffer, tiff.byteOffset, tiff.byteLength);
152
+ if (view.getUint16(2, le) !== 42) return void 0;
153
+ const ifd = view.getUint32(4, le);
154
+ if (ifd + 2 > tiff.length) return void 0;
155
+ const n = view.getUint16(ifd, le);
156
+ for (let i = 0; i < n; i++) {
157
+ const entry = ifd + 2 + i * 12;
158
+ if (entry + 12 > tiff.length) return void 0;
159
+ if (view.getUint16(entry, le) !== 274) continue;
160
+ if (view.getUint16(entry + 2, le) !== 3) return void 0;
161
+ if (view.getUint32(entry + 4, le) !== 1) return void 0;
162
+ const val = view.getUint16(entry + 8, le);
163
+ return val >= 1 && val <= 8 ? val : void 0;
164
+ }
165
+ return;
166
+ } catch {
167
+ return;
168
+ }
169
+ };
170
+ var isExifApp1Payload = (segment) => segment.length >= 6 && segment[0] === 69 && segment[1] === 120 && segment[2] === 105 && segment[3] === 102 && segment[4] === 0 && segment[5] === 0;
171
+ /** Standalone JPEG markers have no length field (TEM, RST0–7, SOI). */
172
+ var isStandaloneJpegMarker = (marker) => marker === 1 || marker >= 208 && marker <= 216;
173
+ /**
174
+ * JPEG: scan APP1 'Exif\0\0' segments; stop at SOS/EOI.
175
+ * Skips 0xFF fill/padding and standalone markers. If an Exif APP1 has no
176
+ * valid Orientation, keep scanning for a later one.
177
+ */
178
+ var getJpegOrientation = (bytes) => {
179
+ if (bytes.length < 2 || bytes[0] !== JPEG_SOI_0 || bytes[1] !== JPEG_SOI_1) return void 0;
180
+ let pos = 2;
181
+ while (pos < bytes.length) {
182
+ if (bytes[pos] !== 255) return void 0;
183
+ while (pos < bytes.length && bytes[pos] === 255) pos++;
184
+ if (pos >= bytes.length) return void 0;
185
+ const marker = bytes[pos++];
186
+ if (isStandaloneJpegMarker(marker)) continue;
187
+ if (marker === 218 || marker === 217) return void 0;
188
+ if (pos + 2 > bytes.length) return void 0;
189
+ const size = bytes[pos] << 8 | bytes[pos + 1];
190
+ if (size < 2 || pos + size > bytes.length) return void 0;
191
+ if (marker === 225 && size >= 8) {
192
+ const segment = bytes.subarray(pos + 2, pos + size);
193
+ if (isExifApp1Payload(segment)) {
194
+ const orientation = parseTiffOrientation(segment.subarray(6));
195
+ if (orientation !== void 0) return orientation;
196
+ }
197
+ }
198
+ pos += size;
199
+ }
200
+ };
201
+ /**
202
+ * PNG: scan chunks for eXIf (raw TIFF payload). Skip IDAT and other
203
+ * ancillary chunks; eXIf may appear after image data. Stop at IEND.
204
+ */
205
+ var getPngOrientation = (bytes) => {
206
+ if (!isPngSignature(bytes)) return void 0;
207
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
208
+ let pos = 8;
209
+ while (pos + 12 <= bytes.length) {
210
+ const length = view.getUint32(pos);
211
+ if (pos + 12 + length > bytes.length) return void 0;
212
+ const type = String.fromCharCode(bytes[pos + 4], bytes[pos + 5], bytes[pos + 6], bytes[pos + 7]);
213
+ if (type === "eXIf") return parseTiffOrientation(bytes.subarray(pos + 8, pos + 8 + length));
214
+ if (type === "IEND") return void 0;
215
+ pos += 12 + length;
216
+ }
217
+ };
218
+ var orientationSwapsDimensions = (orientation) => orientation >= 5;
219
+ /**
220
+ * Map source (x, y) into destination (dx, dy) for EXIF orientations 2–8.
221
+ * Orientations 5–8 swap width and height.
222
+ */
223
+ var transformRgba = (src, width, height, orientation) => {
224
+ const swap = orientationSwapsDimensions(orientation);
225
+ const destWidth = swap ? height : width;
226
+ const destHeight = swap ? width : height;
227
+ const dest = new Uint8Array(destWidth * destHeight * 4);
228
+ for (let y = 0; y < height; y++) for (let x = 0; x < width; x++) {
229
+ let dx = x;
230
+ let dy = y;
231
+ switch (orientation) {
232
+ case 2:
233
+ dx = width - 1 - x;
234
+ dy = y;
235
+ break;
236
+ case 3:
237
+ dx = width - 1 - x;
238
+ dy = height - 1 - y;
239
+ break;
240
+ case 4:
241
+ dx = x;
242
+ dy = height - 1 - y;
243
+ break;
244
+ case 5:
245
+ dx = y;
246
+ dy = x;
247
+ break;
248
+ case 6:
249
+ dx = height - 1 - y;
250
+ dy = x;
251
+ break;
252
+ case 7:
253
+ dx = height - 1 - y;
254
+ dy = width - 1 - x;
255
+ break;
256
+ case 8:
257
+ dx = y;
258
+ dy = width - 1 - x;
259
+ }
260
+ const srcIndex = (y * width + x) * 4;
261
+ const destIndex = (dy * destWidth + dx) * 4;
262
+ dest[destIndex] = src[srcIndex];
263
+ dest[destIndex + 1] = src[srcIndex + 1];
264
+ dest[destIndex + 2] = src[srcIndex + 2];
265
+ dest[destIndex + 3] = src[srcIndex + 3];
266
+ }
267
+ return {
268
+ data: dest,
269
+ width: destWidth,
270
+ height: destHeight
271
+ };
272
+ };
273
+ var bakeJpegOrientation = (bytes) => {
274
+ const orientation = getJpegOrientation(bytes);
275
+ if (!orientation || orientation === 1) return bytes;
276
+ const raw = jpegJs.decode(bytes, {
277
+ useTArray: true,
278
+ formatAsRGBA: true,
279
+ maxMemoryUsageInMB: JPEG_MAX_MEMORY_MB
280
+ });
281
+ const transformed = transformRgba(raw.data, raw.width, raw.height, orientation);
282
+ return new Uint8Array(jpegJs.encode({
283
+ data: transformed.data,
284
+ width: transformed.width,
285
+ height: transformed.height
286
+ }, JPEG_ENCODE_QUALITY).data);
287
+ };
288
+ var bakePngOrientation = (bytes) => {
289
+ const orientation = getPngOrientation(bytes);
290
+ if (!orientation || orientation === 1) return bytes;
291
+ const img = UPNG.decode(toArrayBuffer(bytes));
292
+ const transformed = transformRgba(new Uint8Array(UPNG.toRGBA8(img)[0]), img.width, img.height, orientation);
293
+ return new Uint8Array(UPNG.encode([toArrayBuffer(transformed.data)], transformed.width, transformed.height, 0));
294
+ };
295
+ /**
296
+ * One normalize path for JPEG and PNG. Tag absent/1 is a byte-identical
297
+ * passthrough. Tag 2–8 decodes, transforms pixels, and re-encodes without
298
+ * an orientation tag. May throw on decode/encode failure — callers fall back.
299
+ */
300
+ var normalizeImageOrientation = (bytes) => {
301
+ const kind = detectImageFormat(bytes);
302
+ if (kind === "jpeg") return bakeJpegOrientation(bytes);
303
+ if (kind === "png") return bakePngOrientation(bytes);
304
+ return bytes;
305
+ };
306
+ var TABLE_IMAGE_DATA_URL_PATTERN = /^data:image\/(png|jpe?g);base64,/i;
307
+ //#endregion
308
+ //#region src/tables/types.ts
309
+ var TABLE_CELL_TYPES = ["text", "image"];
310
+ //#endregion
311
+ //#region src/tables/imageCell.ts
312
+ var DIMENSION_CACHE_PREFIX = "tableImageDim:";
313
+ var WARN_CACHE_PREFIX = "tableImageWarned:";
314
+ var FAILED_DIMENSION = null;
315
+ var isTableCellType = (value) => typeof value === "string" && TABLE_CELL_TYPES.some((cellType) => cellType === value);
316
+ var isDimension = (value) => {
317
+ if (!value || typeof value !== "object") return false;
318
+ const record = value;
319
+ return typeof record.width === "number" && typeof record.height === "number";
320
+ };
321
+ var dataUrlToBytes = (value) => {
322
+ const index = value.indexOf(";base64,");
323
+ const base64 = index >= 0 ? value.slice(index + 8) : value;
324
+ return new Uint8Array(Buffer.from(base64, "base64"));
325
+ };
326
+ var applyOrientation = (dimension, bytes) => {
327
+ const format = detectImageFormat(bytes);
328
+ const orientation = format === "jpeg" ? getJpegOrientation(bytes) : format === "png" ? getPngOrientation(bytes) : void 0;
329
+ if (orientation !== void 0 && orientationSwapsDimensions(orientation)) return {
330
+ width: dimension.height,
331
+ height: dimension.width
332
+ };
333
+ return dimension;
334
+ };
335
+ var isTableImageDataUrl = (value) => TABLE_IMAGE_DATA_URL_PATTERN.test(value);
336
+ var imageCacheSuffix = (value) => `${value.length}:${hashImageDataUrl(value)}`;
337
+ var resolveImageDimension = (value, cache) => {
338
+ if (!isTableImageDataUrl(value)) return void 0;
339
+ const key = `${DIMENSION_CACHE_PREFIX}${imageCacheSuffix(value)}`;
340
+ const cached = cache.get(key);
341
+ if (cached === FAILED_DIMENSION) return void 0;
342
+ if (isDimension(cached)) return cached;
343
+ try {
344
+ const bytes = dataUrlToBytes(value);
345
+ const dimension = applyOrientation(getImageDimension(bytes), bytes);
346
+ cache.set(key, dimension);
347
+ return dimension;
348
+ } catch {
349
+ cache.set(key, FAILED_DIMENSION);
350
+ return;
351
+ }
352
+ };
353
+ var warnInvalidTableImageOnce = (value, columnIndex, cache) => {
354
+ if (value == null || value === "") return;
355
+ const key = `${WARN_CACHE_PREFIX}${imageCacheSuffix(value)}`;
356
+ if (cache.has(key)) return;
357
+ cache.set(key, true);
358
+ console.warn(`[@pdfme/schemas/table] unsupported image in column ${columnIndex}; only PNG/JPEG data URL is supported`);
359
+ };
360
+ var normalizeTableCellType = (value, columnIndex, cache) => {
361
+ if (value == null) return void 0;
362
+ if (isTableCellType(value)) return value;
363
+ const warnKey = `tableCellTypeWarned:${String(value)}`;
364
+ if (!cache.has(warnKey)) {
365
+ cache.set(warnKey, true);
366
+ console.warn(`[@pdfme/schemas/table] unsupported cell type "${String(value)}" in column ${columnIndex}; treating as text`);
367
+ }
368
+ return "text";
369
+ };
370
+ var normalizeTableImageHeightMode = (value) => value === "fixed" || value === "auto" ? value : void 0;
371
+ var normalizeTableImageHeight = (value) => typeof value === "number" && Number.isFinite(value) ? value : void 0;
372
+ var getTableImageObjectPosition = (alignment, verticalAlignment) => {
373
+ return `${alignment === "center" || alignment === "right" ? alignment : "left"} ${verticalAlignment === "top" ? "top" : verticalAlignment === "bottom" ? "bottom" : "center"}`;
374
+ };
375
+ var resolveFixedTableImageHeight = (imageHeight) => typeof imageHeight === "number" && Number.isFinite(imageHeight) && imageHeight > 0 ? imageHeight : 20;
376
+ /**
377
+ * Fixed height is kept for empty and invalid values so rows in the column stay aligned.
378
+ * Auto height is 0 unless a PNG/JPEG data URL resolves.
379
+ */
380
+ var resolveTableImageContentHeight = (arg) => {
381
+ const mode = arg.mode ?? "fixed";
382
+ if (!arg.value) return mode === "auto" ? 0 : resolveFixedTableImageHeight(arg.imageHeight);
383
+ const dimension = resolveImageDimension(arg.value, arg.cache);
384
+ if (!dimension || dimension.width <= 0) {
385
+ warnInvalidTableImageOnce(arg.value, arg.columnIndex, arg.cache);
386
+ return mode === "auto" ? 0 : resolveFixedTableImageHeight(arg.imageHeight);
387
+ }
388
+ if (mode === "auto") return arg.contentWidth * dimension.height / dimension.width;
389
+ return resolveFixedTableImageHeight(arg.imageHeight);
390
+ };
391
+ //#endregion
3
392
  //#region \0@oxc-project+runtime@0.151.0/helpers/esm/typeof.js
4
393
  function _typeof(o) {
5
394
  "@babel/helpers - typeof";
@@ -50,6 +439,7 @@ var Cell = class {
50
439
  _defineProperty(this, "wrappedWidth", 0);
51
440
  _defineProperty(this, "minReadableWidth", 0);
52
441
  _defineProperty(this, "minWidth", 0);
442
+ _defineProperty(this, "imageContentHeight", 0);
53
443
  _defineProperty(this, "width", 0);
54
444
  _defineProperty(this, "height", 0);
55
445
  _defineProperty(this, "x", 0);
@@ -60,8 +450,13 @@ var Cell = class {
60
450
  const splitRegex = /\r\n|\r|\n/g;
61
451
  this.text = raw.split(splitRegex);
62
452
  }
453
+ isImage() {
454
+ return this.section !== "head" && this.styles.cellType === "image";
455
+ }
63
456
  getContentHeight() {
64
- const height = (Array.isArray(this.text) ? this.text.length : 1) * (pt2mm(this.styles.fontSize) * this.styles.lineHeight) + getBoxVerticalInset(getCellBoxStyle(this));
457
+ const verticalInset = getBoxVerticalInset(getCellBoxStyle(this));
458
+ if (this.isImage()) return Math.max(this.imageContentHeight + verticalInset, this.styles.minCellHeight);
459
+ const height = (Array.isArray(this.text) ? this.text.length : 1) * (pt2mm(this.styles.fontSize) * this.styles.lineHeight) + verticalInset;
65
460
  return Math.max(height, this.styles.minCellHeight);
66
461
  }
67
462
  padding(name) {
@@ -128,11 +523,12 @@ var Table = class Table {
128
523
  this.body = content.body;
129
524
  }
130
525
  static async create(arg) {
131
- const { input, content, font, _cache } = arg;
526
+ const { input, content, font, basePdf, _cache } = arg;
132
527
  const table = new Table(input, content);
133
528
  await calculateWidths({
134
529
  table,
135
530
  font,
531
+ basePdf,
136
532
  _cache
137
533
  });
138
534
  return table;
@@ -154,7 +550,7 @@ var Table = class Table {
154
550
  }
155
551
  };
156
552
  async function calculateWidths(arg) {
157
- const { table, font, _cache } = arg;
553
+ const { table, font, basePdf, _cache } = arg;
158
554
  const getFontKitFontByFontName = (fontName) => getFontKitFont(fontName, font, _cache);
159
555
  await calculate(table, getFontKitFontByFontName);
160
556
  const resizableColumns = [];
@@ -173,7 +569,7 @@ async function calculateWidths(arg) {
173
569
  if (resizeWidth) resizeWidth = resizeColumns(resizableColumns, resizeWidth, (column) => column.minWidth);
174
570
  resizeWidth = Math.abs(resizeWidth);
175
571
  applyColSpans(table);
176
- await fitContent(table, getFontKitFontByFontName);
572
+ await fitContent(table, getFontKitFontByFontName, basePdf, _cache);
177
573
  applyRowSpans(table);
178
574
  }
179
575
  function applyRowSpans(table) {
@@ -229,7 +625,15 @@ function applyColSpans(table) {
229
625
  }
230
626
  }
231
627
  }
232
- async function fitContent(table, getFontKitFontByFontName) {
628
+ var autoImageHeightLimit = (table, cell, basePdf) => {
629
+ if (!isBlankPdf(basePdf)) return void 0;
630
+ const [paddingTop, , paddingBottom] = basePdf.padding;
631
+ const pageContentHeight = basePdf.height - paddingTop - paddingBottom;
632
+ const headHeight = table.settings.templateShowHead ? table.head.reduce((sum, row) => sum + row.height, 0) : 0;
633
+ const verticalInset = getBoxVerticalInset(getCellBoxStyle(cell));
634
+ return pageContentHeight - headHeight - verticalInset - 1;
635
+ };
636
+ async function fitContent(table, getFontKitFontByFontName, basePdf, cache) {
233
637
  const rowSpanHeight = {
234
638
  count: 0,
235
639
  height: 0
@@ -238,7 +642,6 @@ async function fitContent(table, getFontKitFontByFontName) {
238
642
  for (const column of table.columns) {
239
643
  const cell = row.cells[column.index];
240
644
  if (!cell) continue;
241
- const fontKitFont = await getFontKitFontByFontName(cell.styles.fontName);
242
645
  const contentArea = getBoxContentArea({
243
646
  position: {
244
647
  x: 0,
@@ -248,13 +651,31 @@ async function fitContent(table, getFontKitFontByFontName) {
248
651
  height: cell.height,
249
652
  ...getCellBoxStyle(cell)
250
653
  });
251
- cell.text = splitTextToSize({
252
- value: cell.raw,
253
- characterSpacing: cell.styles.characterSpacing,
254
- boxWidthInPt: mm2pt(contentArea.width),
255
- fontSize: cell.styles.fontSize,
256
- fontKitFont
257
- });
654
+ if (cell.isImage()) {
655
+ cell.text = [];
656
+ let imageContentHeight = resolveTableImageContentHeight({
657
+ value: cell.raw,
658
+ mode: cell.styles.imageHeightMode,
659
+ imageHeight: cell.styles.imageHeight,
660
+ contentWidth: contentArea.width,
661
+ columnIndex: column.index,
662
+ cache
663
+ });
664
+ if ((cell.styles.imageHeightMode ?? "fixed") === "auto") {
665
+ const limit = autoImageHeightLimit(table, cell, basePdf);
666
+ if (limit !== void 0) imageContentHeight = Math.min(imageContentHeight, Math.max(0, limit));
667
+ }
668
+ cell.imageContentHeight = imageContentHeight;
669
+ } else {
670
+ const fontKitFont = await getFontKitFontByFontName(cell.styles.fontName);
671
+ cell.text = splitTextToSize({
672
+ value: cell.raw,
673
+ characterSpacing: cell.styles.characterSpacing,
674
+ boxWidthInPt: mm2pt(contentArea.width),
675
+ fontSize: cell.styles.fontSize,
676
+ fontKitFont
677
+ });
678
+ }
258
679
  cell.contentHeight = cell.getContentHeight();
259
680
  let realContentHeight = cell.contentHeight;
260
681
  if (rowSpanHeight && rowSpanHeight.count > 0) {
@@ -291,6 +712,13 @@ async function calculate(table, getFontKitFontByFontName) {
291
712
  const cell = row.cells[column.index];
292
713
  if (!cell) continue;
293
714
  const hPadding = cell.padding("right") + cell.padding("left");
715
+ if (cell.isImage()) {
716
+ cell.contentWidth = hPadding;
717
+ cell.minReadableWidth = hPadding;
718
+ cell.minWidth = cell.styles.cellWidth;
719
+ cell.wrappedWidth = cell.styles.cellWidth;
720
+ continue;
721
+ }
294
722
  const fontKitFont = await getFontKitFontByFontName(cell.styles.fontName);
295
723
  cell.contentWidth = getStringWidth(cell, fontKitFont) + hPadding;
296
724
  cell.minReadableWidth = getStringWidth(Object.assign(cell, { text: cell.text.join(" ").split(/\s+/) }), fontKitFont) + hPadding;
@@ -404,24 +832,43 @@ function mapCellStyle(style) {
404
832
  };
405
833
  return Object.fromEntries(Object.entries(mapping).filter(([, value]) => value !== void 0));
406
834
  }
407
- function getTableOptions(schema, body) {
835
+ function getTableOptions(schema, body, cache) {
408
836
  const columnStylesWidth = schema.headWidthPercentages.reduce((acc, cur, i) => ({
409
837
  ...acc,
410
838
  [i]: { cellWidth: schema.width * (cur / 100) }
411
839
  }), {});
412
- const columnStylesAlignment = Object.entries(schema.columnStyles.alignment || {}).reduce((acc, [key, value]) => ({
840
+ const alignmentMap = schema.columnStyles.alignment || {};
841
+ const cellTypeMap = schema.columnStyles.cellType || {};
842
+ const imageHeightModeMap = schema.columnStyles.imageHeightMode || {};
843
+ const imageHeightMap = schema.columnStyles.imageHeight || {};
844
+ const columnStylesAlignment = Object.entries(alignmentMap).reduce((acc, [key, value]) => ({
413
845
  ...acc,
414
846
  [key]: { alignment: value }
415
847
  }), {});
416
- const allKeys = /* @__PURE__ */ new Set([...Object.keys(columnStylesWidth).map(Number), ...Object.keys(columnStylesAlignment).map(Number)]);
848
+ const allKeys = /* @__PURE__ */ new Set([
849
+ ...Object.keys(columnStylesWidth).map(Number),
850
+ ...Object.keys(columnStylesAlignment).map(Number),
851
+ ...Object.keys(cellTypeMap).map(Number),
852
+ ...Object.keys(imageHeightModeMap).map(Number),
853
+ ...Object.keys(imageHeightMap).map(Number)
854
+ ]);
417
855
  const columnStyles = Array.from(allKeys).reduce((acc, key) => {
418
856
  const widthStyle = columnStylesWidth[key] || {};
419
857
  const alignmentStyle = columnStylesAlignment[key] || {};
858
+ const cellType = normalizeTableCellType(cellTypeMap[key], key, cache);
859
+ const imageHeightMode = normalizeTableImageHeightMode(imageHeightModeMap[key]);
860
+ const imageHeight = normalizeTableImageHeight(imageHeightMap[key]);
861
+ const imageStyle = {
862
+ ...cellType ? { cellType } : {},
863
+ ...imageHeightMode ? { imageHeightMode } : {},
864
+ ...imageHeight !== void 0 ? { imageHeight } : {}
865
+ };
420
866
  return {
421
867
  ...acc,
422
868
  [key]: {
423
869
  ...widthStyle,
424
- ...alignmentStyle
870
+ ...alignmentStyle,
871
+ ...imageStyle
425
872
  }
426
873
  };
427
874
  }, {});
@@ -471,14 +918,15 @@ function parseContent4Input(options) {
471
918
  body
472
919
  };
473
920
  }
474
- function parseInput(schema, body) {
475
- const options = getTableOptions(schema, body);
921
+ function parseInput(schema, body, cache, templateShowHead) {
922
+ const options = getTableOptions(schema, body, cache);
476
923
  const styles = parseStyles(options);
477
924
  const settings = {
478
925
  startY: options.startY,
479
926
  margin: options.margin,
480
927
  tableWidth: options.tableWidth,
481
928
  showHead: options.showHead,
929
+ templateShowHead,
482
930
  tableLineWidth: options.tableLineWidth ?? 0,
483
931
  tableLineColor: options.tableLineColor ?? ""
484
932
  };
@@ -498,14 +946,16 @@ function createSingleTable(body, args) {
498
946
  schema.bodyStyles.alternateBackgroundColor = schema.bodyStyles.backgroundColor;
499
947
  schema.bodyStyles.backgroundColor = alternateBackgroundColor;
500
948
  }
949
+ const templateShowHead = schema.showHead !== false;
501
950
  schema.showHead = schema.showHead === false ? false : !schema.__isSplit || schema.repeatHead === true;
502
- const input = parseInput(schema, body);
951
+ const input = parseInput(schema, body, _cache, templateShowHead);
503
952
  const font = options.font || getDefaultFont();
504
953
  const content = parseContent4Table(input, getFallbackFontName(font));
505
954
  return Table.create({
506
955
  input,
507
956
  content,
508
957
  font,
958
+ basePdf,
509
959
  _cache
510
960
  });
511
961
  }
@@ -750,9 +1200,11 @@ var getDynamicHeightsForTable = async (value, args) => {
750
1200
  const initialPageIndex = Math.max(0, Math.floor((schema.position.y - paddingTop) / pageContentHeight));
751
1201
  const headRowCount = schema.showHead ? table.head.length : 0;
752
1202
  const SAFETY_MARGIN = .5;
1203
+ const EPSILON = .01;
753
1204
  let currentPageIndex = initialPageIndex;
754
1205
  let currentPageY = schema.position.y;
755
1206
  let rowsOnCurrentPage = 0;
1207
+ let headerTravelsWithBody = false;
756
1208
  const result = [];
757
1209
  for (let i = 0; i < baseHeights.length; i++) {
758
1210
  const isBodyRow = i >= headRowCount;
@@ -760,26 +1212,37 @@ var getDynamicHeightsForTable = async (value, args) => {
760
1212
  while (true) {
761
1213
  const currentPageStartY = getPageStartY(currentPageIndex);
762
1214
  const remainingHeight = currentPageStartY + pageContentHeight - currentPageY;
763
- const totalRowHeight = rowHeight + (isBodyRow && rowsOnCurrentPage === 0 && currentPageIndex > initialPageIndex ? headerHeight : 0);
764
- if (totalRowHeight > remainingHeight - SAFETY_MARGIN) {
1215
+ const totalRowHeight = rowHeight + (isBodyRow && rowsOnCurrentPage === 0 && currentPageIndex > initialPageIndex && !headerTravelsWithBody ? headerHeight : 0);
1216
+ if (totalRowHeight > remainingHeight - SAFETY_MARGIN + EPSILON) {
765
1217
  if (rowsOnCurrentPage === 0 && Math.abs(currentPageY - currentPageStartY) < SAFETY_MARGIN) {
766
1218
  result.push(totalRowHeight);
767
1219
  currentPageY += totalRowHeight;
768
1220
  rowsOnCurrentPage++;
1221
+ headerTravelsWithBody = false;
769
1222
  break;
770
1223
  }
1224
+ const headerWouldBeAlone = !headerTravelsWithBody && currentPageIndex === initialPageIndex && isBodyRow && headRowCount > 0 && result.length === headRowCount && rowsOnCurrentPage === headRowCount;
771
1225
  currentPageIndex++;
772
- currentPageY = getPageStartY(currentPageIndex);
773
- rowsOnCurrentPage = 0;
1226
+ if (headerWouldBeAlone) {
1227
+ headerTravelsWithBody = true;
1228
+ currentPageY = getPageStartY(currentPageIndex) + headerHeight;
1229
+ rowsOnCurrentPage = headRowCount;
1230
+ } else {
1231
+ headerTravelsWithBody = false;
1232
+ currentPageY = getPageStartY(currentPageIndex);
1233
+ rowsOnCurrentPage = 0;
1234
+ }
774
1235
  continue;
775
1236
  }
776
1237
  result.push(totalRowHeight);
777
1238
  currentPageY += totalRowHeight;
778
1239
  rowsOnCurrentPage++;
1240
+ if (isBodyRow) headerTravelsWithBody = false;
779
1241
  if (currentPageY >= currentPageStartY + pageContentHeight - SAFETY_MARGIN) {
780
1242
  currentPageIndex++;
781
1243
  currentPageY = getPageStartY(currentPageIndex);
782
1244
  rowsOnCurrentPage = 0;
1245
+ headerTravelsWithBody = false;
783
1246
  }
784
1247
  break;
785
1248
  }
@@ -803,6 +1266,6 @@ var getDynamicLayoutForTable = async (value, args) => {
803
1266
  };
804
1267
  };
805
1268
  //#endregion
806
- export { getCellPropPanelSchema as a, remapColumnStylesOnRemove as c, createSingleTable as d, getBodyWithSchemaRange as i, HEX_COLOR_PATTERN as l, getDynamicLayoutForTable as n, getColumnStylesPropPanelSchema as o, getBody as r, getDefaultCellStyles as s, getDynamicHeightsForTable as t, OPAQUE_HEX_COLOR_PATTERN as u };
1269
+ export { hashImageDataUrl as _, getCellPropPanelSchema as a, remapColumnStylesOnRemove as c, createSingleTable as d, getTableImageObjectPosition as f, normalizeImageOrientation as g, detectImageFormat as h, getBodyWithSchemaRange as i, HEX_COLOR_PATTERN as l, warnInvalidTableImageOnce as m, getDynamicLayoutForTable as n, getColumnStylesPropPanelSchema as o, resolveImageDimension as p, getBody as r, getDefaultCellStyles as s, getDynamicHeightsForTable as t, OPAQUE_HEX_COLOR_PATTERN as u };
807
1270
 
808
- //# sourceMappingURL=dynamicTemplate-Zqt6kNsE.js.map
1271
+ //# sourceMappingURL=dynamicTemplate-BJxwjEWl.js.map