av6-pdf-engine 1.2.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -34,10 +34,44 @@ __export(index_exports, {
34
34
  PdfEngineError: () => PdfEngineError,
35
35
  PdfEngineErrorCode: () => PdfEngineErrorCode,
36
36
  QR_ERROR_LEVEL: () => QR_ERROR_LEVEL,
37
+ computeColumnPixelWidths: () => computeColumnPixelWidths,
38
+ contentEnv: () => contentEnv,
39
+ createBlockRenderer: () => createBlockRenderer,
40
+ createBottomLimitForContent: () => createBottomLimitForContent,
41
+ createEnsureSpaceFor: () => createEnsureSpaceFor,
42
+ createInitialContext: () => createInitialContext,
43
+ createMeasureBlockHeight: () => createMeasureBlockHeight,
44
+ createProcessSignatureBlock: () => createProcessSignatureBlock,
45
+ createStartNewPageLayout: () => createStartNewPageLayout,
46
+ drawFooter: () => drawFooter,
47
+ drawHeader: () => drawHeader,
48
+ drawPageBackground: () => drawPageBackground,
49
+ drawSignatureBlock: () => drawSignatureBlock,
50
+ drawStyledText: () => drawStyledText,
51
+ drawWatermarkForPage: () => drawWatermarkForPage,
52
+ finishPage: () => finishPage,
53
+ generateBarcodeBuffer: () => generateBarcodeBuffer,
54
+ generateQrBuffer: () => generateQrBuffer,
55
+ getBottomLimitForContent: () => getBottomLimitForContent,
56
+ getFontNameForText: () => getFontNameForText,
57
+ hasPadding: () => hasPadding,
58
+ images: () => images,
37
59
  isPdfEngineError: () => isPdfEngineError,
60
+ mapBarcodeTypeToBcid: () => mapBarcodeTypeToBcid,
61
+ materializeImagesInBlocks: () => materializeImagesInBlocks,
62
+ materializeQrAndBarcodesInBlocks: () => materializeQrAndBarcodesInBlocks,
63
+ mergeStyleDefs: () => mergeStyleDefs,
64
+ normalizeImageSrc: () => normalizeImageSrc,
38
65
  renderCustomPdf: () => renderCustomPdf,
39
66
  renderCustomPdfToBuffer: () => renderCustomPdfToBuffer,
40
- toPdfEngineError: () => toPdfEngineError
67
+ resolveBlockPadding: () => resolveBlockPadding,
68
+ resolveFooterPadding: () => resolveFooterPadding,
69
+ resolveHeaderPadding: () => resolveHeaderPadding,
70
+ resolveSpacing: () => resolveSpacing,
71
+ resolveTableCell: () => resolveTableCell,
72
+ resolveTextBlock: () => resolveTextBlock,
73
+ toPdfEngineError: () => toPdfEngineError,
74
+ watermarkUsesLast: () => watermarkUsesLast
41
75
  });
42
76
  module.exports = __toCommonJS(index_exports);
43
77
 
@@ -73,6 +107,11 @@ function toPdfEngineError(cause, fallback) {
73
107
  });
74
108
  }
75
109
 
110
+ // src/images/index.ts
111
+ var images = {
112
+ default: "data:image/png;base64,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"
113
+ };
114
+
76
115
  // src/renderer-engine/index.ts
77
116
  var import_fs = __toESM(require("fs"));
78
117
  var import_pdfkit = __toESM(require("pdfkit"));
@@ -251,7 +290,7 @@ var drawRotatedImage = (doc, src, x, y, width, height, rotationDeg) => {
251
290
  doc.image(src, x, y, { width, height });
252
291
  doc.restore();
253
292
  };
254
- var processImageBlock = (doc, ctx, block, y, env, ensureSpaceFor) => {
293
+ var processImageBlock = (doc, ctx, block, y, env, ensureSpaceFor, defaultImage) => {
255
294
  const imgSource = block.src;
256
295
  const imgWidth = block.width ?? 80;
257
296
  const imgHeight = block.height ?? 50;
@@ -261,12 +300,11 @@ var processImageBlock = (doc, ctx, block, y, env, ensureSpaceFor) => {
261
300
  const availableWidth = Math.max(env.innerWidth - localLeft - localRight, 1);
262
301
  const mt = block.marginTop ?? 0;
263
302
  const mb = block.marginBottom ?? 0;
264
- const baseY = y ?? ctx.currentY;
265
- const startY = baseY + mt;
266
303
  const heightNeeded = mt + imgHeight + mb;
267
304
  if (y === null) {
268
305
  ensureSpaceFor(heightNeeded, env);
269
306
  }
307
+ const startY = (y ?? ctx.currentY) + mt;
270
308
  let x = baseLeft;
271
309
  if (block.align === "center") {
272
310
  x = baseLeft + (availableWidth - imgWidth) / 2;
@@ -279,7 +317,18 @@ var processImageBlock = (doc, ctx, block, y, env, ensureSpaceFor) => {
279
317
  height: imgHeight
280
318
  });
281
319
  } catch (e) {
282
- console.warn("Failed to load image:", e);
320
+ if (defaultImage !== void 0) {
321
+ try {
322
+ doc.image(defaultImage, x, startY, {
323
+ width: imgWidth,
324
+ height: imgHeight
325
+ });
326
+ } catch {
327
+ console.warn("Failed to render default image fallback:", e);
328
+ }
329
+ } else {
330
+ console.warn("Failed to load image:", e);
331
+ }
283
332
  }
284
333
  const newY = startY + imgHeight + mb;
285
334
  if (y === null) ctx.currentY = newY;
@@ -331,7 +380,7 @@ var processKeyValueGridBlock = (doc, ctx, styles, block, y, env, computeColumnPi
331
380
  ...base,
332
381
  style: styleNames
333
382
  });
334
- const measureTextHeight = (tb, width) => {
383
+ const measureTextHeight2 = (tb, width) => {
335
384
  const fontName = getFontNameForText(tb);
336
385
  doc.font(fontName);
337
386
  doc.fontSize(tb.fontSize ?? 10);
@@ -364,10 +413,10 @@ var processKeyValueGridBlock = (doc, ctx, styles, block, y, env, computeColumnPi
364
413
  const valueStyleNames = item.valueStyle ?? block.valueStyle ?? void 0;
365
414
  const keyBase = buildKeyBlock(item);
366
415
  const keyResolved = resolveStyled(keyBase, keyStyleNames);
367
- const keyHeight = measureTextHeight(keyResolved, colWidth);
416
+ const keyHeight = measureTextHeight2(keyResolved, colWidth);
368
417
  const valueBase = buildValueBlock(item);
369
418
  const valueResolved = resolveStyled(valueBase, valueStyleNames);
370
- const valueHeight = measureTextHeight(valueResolved, colWidth);
419
+ const valueHeight = measureTextHeight2(valueResolved, colWidth);
371
420
  const rowHeight = keyHeight + keyValueGap + valueHeight;
372
421
  colHeight += rowHeight + rowGap;
373
422
  }
@@ -387,12 +436,12 @@ var processKeyValueGridBlock = (doc, ctx, styles, block, y, env, computeColumnPi
387
436
  const valueStyleNames = item.valueStyle ?? block.valueStyle ?? void 0;
388
437
  const keyBase = buildKeyBlock(item);
389
438
  const keyResolved = resolveStyled(keyBase, keyStyleNames);
390
- const keyHeight = measureTextHeight(keyResolved, keyWidthPx);
439
+ const keyHeight = measureTextHeight2(keyResolved, keyWidthPx);
391
440
  const valueBase = buildValueBlock(item);
392
441
  const valueResolved = resolveStyled(valueBase, valueStyleNames);
393
442
  const valueXInsideCol = keyWidthPx + (separatorText ? sepBoxWidth + 4 : 4);
394
443
  const valueWidth = Math.max(colWidth - valueXInsideCol, 1);
395
- const valueHeight = measureTextHeight(valueResolved, valueWidth);
444
+ const valueHeight = measureTextHeight2(valueResolved, valueWidth);
396
445
  const cellHeight = Math.max(keyHeight, valueHeight);
397
446
  if (cellHeight > rowHeight) rowHeight = cellHeight;
398
447
  }
@@ -420,12 +469,12 @@ var processKeyValueGridBlock = (doc, ctx, styles, block, y, env, computeColumnPi
420
469
  const valueStyleNames = item.valueStyle ?? block.valueStyle ?? void 0;
421
470
  const keyBlock = buildKeyBlock(item);
422
471
  const keyResolved = resolveStyled(keyBlock, keyStyleNames);
423
- const keyHeight = measureTextHeight(keyResolved, colWidth);
472
+ const keyHeight = measureTextHeight2(keyResolved, colWidth);
424
473
  drawStyledText(doc, keyResolved, colX, colY, colWidth);
425
474
  colY += keyHeight + keyValueGap;
426
475
  const valueBlock = buildValueBlock(item);
427
476
  const valueResolved = resolveStyled(valueBlock, valueStyleNames);
428
- const valueHeight = measureTextHeight(valueResolved, colWidth);
477
+ const valueHeight = measureTextHeight2(valueResolved, colWidth);
429
478
  drawStyledText(doc, valueResolved, colX, colY, colWidth);
430
479
  colY += valueHeight + rowGap;
431
480
  }
@@ -445,12 +494,12 @@ var processKeyValueGridBlock = (doc, ctx, styles, block, y, env, computeColumnPi
445
494
  const valueStyleNames = item.valueStyle ?? block.valueStyle ?? void 0;
446
495
  const keyBase = buildKeyBlock(item);
447
496
  const keyResolved = resolveStyled(keyBase, keyStyleNames);
448
- const keyHeight = measureTextHeight(keyResolved, keyWidthPx);
497
+ const keyHeight = measureTextHeight2(keyResolved, keyWidthPx);
449
498
  const valueBase = buildValueBlock(item);
450
499
  const valueResolved = resolveStyled(valueBase, valueStyleNames);
451
500
  const valueXInsideCol = keyWidthPx + (separatorText ? sepBoxWidth + 4 : 4);
452
501
  const valueWidth = Math.max(colWidth - valueXInsideCol, 1);
453
- const valueHeight = measureTextHeight(valueResolved, valueWidth);
502
+ const valueHeight = measureTextHeight2(valueResolved, valueWidth);
454
503
  const cellHeight = Math.max(keyHeight, valueHeight);
455
504
  if (cellHeight > rowHeight) rowHeight = cellHeight;
456
505
  }
@@ -491,6 +540,149 @@ var processKeyValueGridBlock = (doc, ctx, styles, block, y, env, computeColumnPi
491
540
  return endY;
492
541
  };
493
542
 
543
+ // src/renderer-engine/blocks/list.ts
544
+ var DEFAULT_BULLET = "\u2022";
545
+ var DEFAULT_MARKER_GAP = 6;
546
+ var DEFAULT_ITEM_GAP = 4;
547
+ var MARKER_PADDING = 2;
548
+ var normalizeListItem = (item) => typeof item === "string" ? { text: item } : item;
549
+ var buildTextBlock = (list, item) => ({
550
+ type: "text",
551
+ text: item.text ?? "",
552
+ fontSize: item.fontSize ?? list.fontSize,
553
+ lineGap: item.lineGap ?? list.lineGap,
554
+ color: item.color ?? list.color,
555
+ bold: item.bold,
556
+ italic: item.italic,
557
+ underline: item.underline,
558
+ strike: item.strike,
559
+ link: item.link,
560
+ font: item.font,
561
+ style: item.style ?? list.style
562
+ });
563
+ var getMarker = (list, index) => {
564
+ if ((list.listStyle ?? "bullet") === "number") {
565
+ const start = list.start ?? 1;
566
+ return `${start + index}.`;
567
+ }
568
+ return list.bullet ?? DEFAULT_BULLET;
569
+ };
570
+ var applyTextOptions = (doc, tb) => {
571
+ doc.fontSize(tb.fontSize ?? 10);
572
+ doc.font(getFontNameForText(tb));
573
+ if (tb.color) doc.fillColor(tb.color);
574
+ else doc.fillColor("black");
575
+ };
576
+ var measureTextHeight = (doc, tb, width) => {
577
+ applyTextOptions(doc, tb);
578
+ const lineGap = tb.lineGap ?? 4;
579
+ return doc.heightOfString(tb.text ?? "", { width, lineGap });
580
+ };
581
+ var measureMarkerWidth = (doc, marker, tb) => {
582
+ applyTextOptions(doc, tb);
583
+ return doc.widthOfString(marker) + MARKER_PADDING;
584
+ };
585
+ var computeMarkerWidth = (doc, list, items, tbSample) => {
586
+ if (list.markerWidth !== void 0) return list.markerWidth;
587
+ let maxW = 0;
588
+ for (let i = 0; i < items.length; i++) {
589
+ const marker = getMarker(list, i);
590
+ const w = measureMarkerWidth(doc, marker, tbSample);
591
+ if (w > maxW) maxW = w;
592
+ }
593
+ return maxW;
594
+ };
595
+ var measureItemHeight = (doc, list, item, index, markerWidth, textWidth, styles) => {
596
+ const tb = resolveTextBlock(styles, buildTextBlock(list, item));
597
+ const marker = getMarker(list, index);
598
+ const markerTb = { ...tb, text: marker, underline: false, strike: false, link: void 0 };
599
+ const markerH = measureTextHeight(doc, markerTb, markerWidth);
600
+ const textH = measureTextHeight(doc, tb, textWidth);
601
+ const lineGap = tb.lineGap ?? 4;
602
+ return Math.max(markerH, textH) + lineGap;
603
+ };
604
+ var measureListHeight = (doc, styles, block, env) => {
605
+ const items = (block.items ?? []).map(normalizeListItem);
606
+ const mt = block.marginTop ?? 0;
607
+ const mb = block.marginBottom ?? 0;
608
+ const itemGap = block.itemGap ?? DEFAULT_ITEM_GAP;
609
+ const markerGap = block.markerGap ?? DEFAULT_MARKER_GAP;
610
+ if (!items.length) return mt + mb;
611
+ const localLeft = block.marginLeft ?? 0;
612
+ const localRight = block.marginRight ?? 0;
613
+ const innerWidth = Math.max(env.innerWidth - localLeft - localRight, 1);
614
+ const firstResolved = resolveTextBlock(styles, buildTextBlock(block, items[0]));
615
+ const markerWidth = computeMarkerWidth(doc, block, items, firstResolved);
616
+ const textWidth = Math.max(innerWidth - markerWidth - markerGap, 1);
617
+ let total = mt;
618
+ for (let i = 0; i < items.length; i++) {
619
+ total += measureItemHeight(doc, block, items[i], i, markerWidth, textWidth, styles);
620
+ if (i < items.length - 1) total += itemGap;
621
+ }
622
+ return total + mb;
623
+ };
624
+ var drawListText = (doc, tb, x, y, width) => {
625
+ applyTextOptions(doc, tb);
626
+ const lineGap = tb.lineGap ?? 4;
627
+ doc.text(tb.text ?? "", x, y, {
628
+ width,
629
+ align: tb.align ?? "left",
630
+ underline: !!tb.underline,
631
+ strike: !!tb.strike,
632
+ link: tb.link,
633
+ lineGap
634
+ });
635
+ };
636
+ var processListBlock = (doc, ctx, styles, block, y, env, ensureSpaceFor) => {
637
+ const items = (block.items ?? []).map(normalizeListItem);
638
+ const mt = block.marginTop ?? 0;
639
+ const mb = block.marginBottom ?? 0;
640
+ const itemGap = block.itemGap ?? DEFAULT_ITEM_GAP;
641
+ const markerGap = block.markerGap ?? DEFAULT_MARKER_GAP;
642
+ const localLeft = block.marginLeft ?? 0;
643
+ const localRight = block.marginRight ?? 0;
644
+ const xLeft = env.marginLeft + localLeft;
645
+ const innerWidth = Math.max(env.innerWidth - localLeft - localRight, 1);
646
+ if (!items.length) {
647
+ const endY2 = (y ?? ctx.currentY) + mt + mb;
648
+ if (y === null) ctx.currentY = endY2;
649
+ return endY2;
650
+ }
651
+ const firstResolved = resolveTextBlock(styles, buildTextBlock(block, items[0]));
652
+ const markerWidth = computeMarkerWidth(doc, block, items, firstResolved);
653
+ const textX = xLeft + markerWidth + markerGap;
654
+ const textWidth = Math.max(innerWidth - markerWidth - markerGap, 1);
655
+ if (y !== null) {
656
+ let drawY = y + mt;
657
+ for (let i = 0; i < items.length; i++) {
658
+ if (i > 0) drawY += itemGap;
659
+ const tb = resolveTextBlock(styles, buildTextBlock(block, items[i]));
660
+ const marker = getMarker(block, i);
661
+ const markerTb = { ...tb, text: marker, underline: false, strike: false, link: void 0 };
662
+ const itemHeight = measureItemHeight(doc, block, items[i], i, markerWidth, textWidth, styles);
663
+ drawListText(doc, markerTb, xLeft, drawY, markerWidth);
664
+ drawListText(doc, tb, textX, drawY, textWidth);
665
+ drawY += itemHeight;
666
+ }
667
+ return drawY + mb;
668
+ }
669
+ for (let i = 0; i < items.length; i++) {
670
+ const leading = i === 0 ? mt : itemGap;
671
+ const itemHeight = measureItemHeight(doc, block, items[i], i, markerWidth, textWidth, styles);
672
+ ensureSpaceFor(leading + itemHeight, env);
673
+ const drawY = ctx.currentY + leading;
674
+ const tb = resolveTextBlock(styles, buildTextBlock(block, items[i]));
675
+ const marker = getMarker(block, i);
676
+ const markerTb = { ...tb, text: marker, underline: false, strike: false, link: void 0 };
677
+ drawListText(doc, markerTb, xLeft, drawY, markerWidth);
678
+ drawListText(doc, tb, textX, drawY, textWidth);
679
+ ctx.currentY = drawY + itemHeight;
680
+ }
681
+ const endY = ctx.currentY + mb;
682
+ ctx.currentY = endY;
683
+ return endY;
684
+ };
685
+
494
686
  // src/renderer-engine/blocks/line.ts
495
687
  var processLineBlock = (doc, ctx, block, y, env, ensureSpaceFor) => {
496
688
  const localLeft = block.marginLeft ?? 0;
@@ -499,13 +691,12 @@ var processLineBlock = (doc, ctx, block, y, env, ensureSpaceFor) => {
499
691
  const width = Math.max(env.innerWidth - localLeft - localRight, 1);
500
692
  const mt = block.marginTop ?? 0;
501
693
  const mb = block.marginBottom ?? 0;
502
- const baseY = y ?? ctx.currentY;
503
- const startY = baseY + mt;
504
694
  const lineWidth = block.lineWidth ?? 1;
505
695
  const heightNeeded = mt + lineWidth + mb;
506
696
  if (y === null) {
507
697
  ensureSpaceFor(heightNeeded, env);
508
698
  }
699
+ const startY = (y ?? ctx.currentY) + mt;
509
700
  doc.save();
510
701
  if (block.color) {
511
702
  doc.strokeColor(block.color);
@@ -518,7 +709,99 @@ var processLineBlock = (doc, ctx, block, y, env, ensureSpaceFor) => {
518
709
  return newY;
519
710
  };
520
711
 
712
+ // src/renderer-engine/blocks/shape.ts
713
+ var processShapeBlock = (doc, ctx, block, y, env, ensureSpaceFor) => {
714
+ const mt = block.marginTop ?? 0;
715
+ const mb = block.marginBottom ?? 0;
716
+ const ml = block.marginLeft ?? 0;
717
+ const mr = block.marginRight ?? 0;
718
+ const lineWidth = block.lineWidth ?? 1;
719
+ const width = block.width ?? Math.max(env.innerWidth - ml - mr, 1);
720
+ const height = block.height ?? lineWidth;
721
+ const heightNeeded = mt + height + mb;
722
+ if (y === null) {
723
+ ensureSpaceFor(heightNeeded, env);
724
+ }
725
+ const startY = (y ?? ctx.currentY) + mt;
726
+ const availableWidth = Math.max(env.innerWidth - ml - mr, 1);
727
+ let x = env.marginLeft + ml;
728
+ if (block.align === "center") {
729
+ x = env.marginLeft + ml + (availableWidth - width) / 2;
730
+ } else if (block.align === "right") {
731
+ x = env.marginLeft + ml + availableWidth - width;
732
+ }
733
+ const drawY = startY;
734
+ doc.save();
735
+ if (typeof block.opacity === "number") {
736
+ doc.opacity(block.opacity);
737
+ }
738
+ doc.lineWidth(lineWidth);
739
+ if (block.strokeColor) {
740
+ doc.strokeColor(block.strokeColor);
741
+ }
742
+ if (block.fillColor) {
743
+ doc.fillColor(block.fillColor);
744
+ }
745
+ switch (block.shape) {
746
+ case "rect":
747
+ doc.rect(x, drawY, width, height);
748
+ break;
749
+ case "roundedRect":
750
+ doc.roundedRect(x, drawY, width, height, block.radius ?? 6);
751
+ break;
752
+ case "circle": {
753
+ const radius = block.radius ?? Math.min(width, height) / 2;
754
+ doc.circle(x + radius, drawY + radius, radius);
755
+ break;
756
+ }
757
+ case "ellipse":
758
+ doc.ellipse(x + width / 2, drawY + height / 2, width / 2, height / 2);
759
+ break;
760
+ case "line":
761
+ doc.moveTo(x, drawY).lineTo(x + width, drawY);
762
+ break;
763
+ case "polygon":
764
+ if (block.points?.length) {
765
+ const [first, ...rest] = block.points;
766
+ doc.moveTo(x + first.x, drawY + first.y);
767
+ rest.forEach((point) => {
768
+ doc.lineTo(x + point.x, drawY + point.y);
769
+ });
770
+ doc.closePath();
771
+ }
772
+ break;
773
+ case "path":
774
+ if (block.path) {
775
+ const safePath = block.path.trim().replace(/[\n\r\t]+/g, " ").replace(/\s+/g, " ");
776
+ if (safePath.includes("undefined") || safePath.includes("NaN")) {
777
+ throw new Error(`Invalid shape path: ${safePath}`);
778
+ }
779
+ doc.translate(x, drawY);
780
+ doc.path(safePath);
781
+ }
782
+ break;
783
+ }
784
+ if (block.fillColor && block.strokeColor) {
785
+ doc.fillAndStroke(block.fillColor, block.strokeColor);
786
+ } else if (block.fillColor) {
787
+ doc.fill(block.fillColor);
788
+ } else {
789
+ doc.stroke();
790
+ }
791
+ doc.restore();
792
+ const newY = startY + height + mb;
793
+ if (y === null) {
794
+ ctx.currentY = newY;
795
+ }
796
+ return newY;
797
+ };
798
+
521
799
  // src/renderer-engine/blocks/table.ts
800
+ var shouldSkipHeaderOnlyTable = (table, rows) => {
801
+ const headerRows = table.headerRows ?? 0;
802
+ if (headerRows <= 0) return false;
803
+ return rows.length <= headerRows;
804
+ };
522
805
  var normalizeSpan = (value) => {
523
806
  if (!value || value < 1) return 1;
524
807
  return Math.floor(value);
@@ -589,6 +872,7 @@ var toTableCell = (rawBlock) => {
589
872
  const tableCellInput = isTableCellInput(rawBlock) ? rawBlock : void 0;
590
873
  return {
591
874
  text: rawBlock.text,
875
+ blocks: tableCellInput?.blocks,
592
876
  italic: rawBlock.italic,
593
877
  underline: rawBlock.underline,
594
878
  link: rawBlock.link,
@@ -605,7 +889,8 @@ var toTableCell = (rawBlock) => {
605
889
  paddingTop: tableCellInput?.paddingTop,
606
890
  paddingRight: tableCellInput?.paddingRight,
607
891
  paddingBottom: tableCellInput?.paddingBottom,
608
- paddingLeft: tableCellInput?.paddingLeft
892
+ paddingLeft: tableCellInput?.paddingLeft,
893
+ border: tableCellInput?.border
609
894
  };
610
895
  };
611
896
  var resolvePathValue = (obj, dottedPath) => {
@@ -628,7 +913,7 @@ var interpolateCellText = (text, item, rowIndex) => {
628
913
  };
629
914
  var applyIterableData = (cell, item, rowIndex) => ({
630
915
  ...cell,
631
- text: interpolateCellText(cell.text, item, rowIndex)
916
+ text: cell.text !== void 0 ? interpolateCellText(cell.text, item, rowIndex) : void 0
632
917
  });
633
918
  var expandIterableRow = (table, bodyDef) => {
634
919
  const templateRow = bodyDef.content.map(toTableCell).filter((cell) => cell !== null);
@@ -658,11 +943,22 @@ var normalizeTableRows = (table) => {
658
943
  }
659
944
  return rows;
660
945
  };
661
- var measureTableHeight = (doc, table, env, styles, computeColumnPixelWidths2) => {
946
+ var measureCellHeight = (doc, cell, textWidth, paddingTop, paddingBottom, measureBlockHeightFn) => {
947
+ if (cell.blocks?.length && measureBlockHeightFn) {
948
+ const cellEnv = { marginLeft: 0, innerWidth: textWidth, allowPageBreak: false };
949
+ const contentH = cell.blocks.filter((b) => b.visible !== false).reduce((acc, b) => acc + measureBlockHeightFn(b, cellEnv), 0);
950
+ return contentH + paddingTop + paddingBottom;
951
+ }
952
+ return doc.heightOfString(cell.text ?? "", { width: textWidth }) + paddingTop + paddingBottom;
953
+ };
954
+ var measureTableHeight = (doc, table, env, styles, computeColumnPixelWidths2, measureBlockHeightFn) => {
662
955
  const localLeft = table.marginLeft ?? 0;
663
956
  const localRight = table.marginRight ?? 0;
664
957
  const width = Math.max(env.innerWidth - localLeft - localRight, 1);
665
958
  const rows = normalizeTableRows(table);
959
+ if (shouldSkipHeaderOnlyTable(table, rows)) {
960
+ return 0;
961
+ }
666
962
  const totalCols = table.widths.length;
667
963
  const colWidths = computeColumnPixelWidths2(table.widths, width);
668
964
  const rowHeights = [];
@@ -681,9 +977,11 @@ var measureTableHeight = (doc, table, env, styles, computeColumnPixelWidths2) =>
681
977
  const paddingBottom = cell.paddingBottom ?? 2;
682
978
  const colW = getPlacedCellWidth(colWidths, startCol, colSpan);
683
979
  const textWidth = Math.max(colW - paddingLeft - paddingRight, 1);
684
- doc.font(getCellFontName(cell));
685
- doc.fontSize(cell.fontSize ?? 10);
686
- const h = doc.heightOfString(cell.text, { width: textWidth }) + paddingTop + paddingBottom;
980
+ if (!cell.blocks?.length) {
981
+ doc.font(getCellFontName(cell));
982
+ doc.fontSize(cell.fontSize ?? 10);
983
+ }
984
+ const h = measureCellHeight(doc, cell, textWidth, paddingTop, paddingBottom, measureBlockHeightFn);
687
985
  rowHeight = Math.max(rowHeight, h);
688
986
  });
689
987
  rowHeights.push(rowHeight);
@@ -700,9 +998,11 @@ var measureTableHeight = (doc, table, env, styles, computeColumnPixelWidths2) =>
700
998
  const paddingBottom = cell.paddingBottom ?? 2;
701
999
  const colW = getPlacedCellWidth(colWidths, startCol, colSpan);
702
1000
  const textWidth = Math.max(colW - paddingLeft - paddingRight, 1);
703
- doc.font(getCellFontName(cell));
704
- doc.fontSize(cell.fontSize ?? 10);
705
- const neededHeight = doc.heightOfString(cell.text, { width: textWidth }) + paddingTop + paddingBottom;
1001
+ if (!cell.blocks?.length) {
1002
+ doc.font(getCellFontName(cell));
1003
+ doc.fontSize(cell.fontSize ?? 10);
1004
+ }
1005
+ const neededHeight = measureCellHeight(doc, cell, textWidth, paddingTop, paddingBottom, measureBlockHeightFn);
706
1006
  const currentGroupHeight = getRowSpanGroupHeight(rowHeights, rowIndex, rowSpan);
707
1007
  if (neededHeight > currentGroupHeight) {
708
1008
  const deficit = neededHeight - currentGroupHeight;
@@ -717,7 +1017,7 @@ var measureTableHeight = (doc, table, env, styles, computeColumnPixelWidths2) =>
717
1017
  totalHeight += table.marginBottom ?? 0;
718
1018
  return totalHeight;
719
1019
  };
720
- var processTableBlock = (doc, ctx, styles, table, y, env, computeColumnPixelWidths2, bottomLimitForContent, finishPage2) => {
1020
+ var processTableBlock = (doc, ctx, styles, table, y, env, computeColumnPixelWidths2, bottomLimitForContent, finishPage2, renderBlockFn, measureBlockHeightFn) => {
721
1021
  const localLeft = table.marginLeft ?? 0;
722
1022
  const localRight = table.marginRight ?? 0;
723
1023
  const baseLeft = env.marginLeft + localLeft;
@@ -733,9 +1033,11 @@ var processTableBlock = (doc, ctx, styles, table, y, env, computeColumnPixelWidt
733
1033
  hLineColor: "#ccc",
734
1034
  vLineColor: "#ccc"
735
1035
  };
736
- const borderAll = layout.border !== "none";
737
1036
  const headerRows = table.headerRows ?? 0;
738
1037
  const rows = normalizeTableRows(table);
1038
+ if (shouldSkipHeaderOnlyTable(table, rows)) {
1039
+ return baseY;
1040
+ }
739
1041
  const buildPlacementAndHeights = (rows2) => {
740
1042
  const placedRows = [];
741
1043
  const rowHeights = [];
@@ -753,9 +1055,11 @@ var processTableBlock = (doc, ctx, styles, table, y, env, computeColumnPixelWidt
753
1055
  const paddingBottom = cell.paddingBottom ?? 2;
754
1056
  const colW = getPlacedCellWidth(colWidths, startCol, colSpan);
755
1057
  const textWidth = Math.max(colW - paddingLeft - paddingRight, 1);
756
- doc.font(getCellFontName(cell));
757
- doc.fontSize(cell.fontSize ?? 10);
758
- const h = doc.heightOfString(cell.text, { width: textWidth }) + paddingTop + paddingBottom;
1058
+ if (!cell.blocks?.length) {
1059
+ doc.font(getCellFontName(cell));
1060
+ doc.fontSize(cell.fontSize ?? 10);
1061
+ }
1062
+ const h = measureCellHeight(doc, cell, textWidth, paddingTop, paddingBottom, measureBlockHeightFn);
759
1063
  rowHeight = Math.max(rowHeight, h);
760
1064
  });
761
1065
  rowHeights.push(rowHeight);
@@ -772,9 +1076,11 @@ var processTableBlock = (doc, ctx, styles, table, y, env, computeColumnPixelWidt
772
1076
  const paddingBottom = cell.paddingBottom ?? 2;
773
1077
  const colW = getPlacedCellWidth(colWidths, startCol, colSpan);
774
1078
  const textWidth = Math.max(colW - paddingLeft - paddingRight, 1);
775
- doc.font(getCellFontName(cell));
776
- doc.fontSize(cell.fontSize ?? 10);
777
- const neededHeight = doc.heightOfString(cell.text, { width: textWidth }) + paddingTop + paddingBottom;
1079
+ if (!cell.blocks?.length) {
1080
+ doc.font(getCellFontName(cell));
1081
+ doc.fontSize(cell.fontSize ?? 10);
1082
+ }
1083
+ const neededHeight = measureCellHeight(doc, cell, textWidth, paddingTop, paddingBottom, measureBlockHeightFn);
778
1084
  const currentGroupHeight = getRowSpanGroupHeight(rowHeights, rowIndex, rowSpan);
779
1085
  if (neededHeight > currentGroupHeight) {
780
1086
  const deficit = neededHeight - currentGroupHeight;
@@ -797,47 +1103,60 @@ var processTableBlock = (doc, ctx, styles, table, y, env, computeColumnPixelWidt
797
1103
  const paddingTop = cell.paddingTop ?? 2;
798
1104
  const paddingBottom = cell.paddingBottom ?? 2;
799
1105
  doc.save();
800
- if (cell.fillColor) {
801
- doc.rect(x, rowTop2, colW, drawHeight).fillOpacity(1).fill(cell.fillColor);
1106
+ const columnStyle = table.layout?.columnStyles?.[startCol];
1107
+ const rowStyle = table.layout?.rowStyles?.[rowIndex];
1108
+ const fillColor = cell.fillColor ?? rowStyle?.fillColor ?? columnStyle?.fillColor;
1109
+ if (fillColor) {
1110
+ doc.rect(x, rowTop2, colW, drawHeight).fillOpacity(1).fill(fillColor);
802
1111
  doc.fillOpacity(1);
803
1112
  }
804
- doc.font(getCellFontName(cell));
805
- doc.fontSize(fontSize);
806
- doc.fillColor(cell.color ?? "black");
807
- const align = cell.align ?? "left";
808
1113
  const textWidth = Math.max(colW - paddingLeft - paddingRight, 1);
809
- const textHeight = doc.heightOfString(cell.text, { width: textWidth });
810
- let textY = rowTop2 + paddingTop;
811
- if (isHeaderRow) {
812
- const available = Math.max(drawHeight - paddingTop - paddingBottom, 0);
813
- const offset = Math.max((available - textHeight) / 2, 0);
814
- textY = rowTop2 + paddingTop + offset;
1114
+ const textY = rowTop2 + paddingTop;
1115
+ if (cell.blocks?.length && renderBlockFn) {
1116
+ const cellEnv = {
1117
+ marginLeft: x + paddingLeft,
1118
+ innerWidth: textWidth,
1119
+ allowPageBreak: false
1120
+ };
1121
+ const savedY = ctx.currentY;
1122
+ let contentY = textY;
1123
+ for (const block of cell.blocks) {
1124
+ if (!block || block.visible === false) continue;
1125
+ if (block.type === "signature" || block.type === "pageBreak") continue;
1126
+ contentY = renderBlockFn(block, contentY, cellEnv);
1127
+ }
1128
+ ctx.currentY = savedY;
1129
+ } else {
1130
+ doc.font(getCellFontName(cell));
1131
+ doc.fontSize(fontSize);
1132
+ doc.fillColor(cell.color ?? "black");
1133
+ const align = cell.align ?? "left";
1134
+ const textHeight = doc.heightOfString(cell.text ?? "", { width: textWidth });
1135
+ let paintY = textY;
1136
+ if (isHeaderRow) {
1137
+ const available = Math.max(drawHeight - paddingTop - paddingBottom, 0);
1138
+ const offset = Math.max((available - textHeight) / 2, 0);
1139
+ paintY = rowTop2 + paddingTop + offset;
1140
+ }
1141
+ doc.text(cell.text ?? "", x + paddingLeft, paintY, {
1142
+ width: textWidth,
1143
+ align,
1144
+ underline: !!cell.underline,
1145
+ strike: !!cell.strike,
1146
+ link: cell.link
1147
+ });
815
1148
  }
816
- doc.text(cell.text, x + paddingLeft, textY, {
817
- width: textWidth,
818
- align,
819
- underline: !!cell.underline,
820
- strike: !!cell.strike,
821
- link: cell.link
822
- });
823
1149
  doc.restore();
824
- if (borderAll) {
825
- const bottomY = rowTop2 + drawHeight;
826
- doc.save();
827
- doc.lineWidth(0.5);
828
- doc.strokeColor(layout.hLineColor ?? "#ccc");
829
- if (drawTopBorder) {
830
- doc.moveTo(x, rowTop2).lineTo(x + colW, rowTop2).stroke();
831
- }
832
- doc.moveTo(x, bottomY).lineTo(x + colW, bottomY).stroke();
833
- doc.restore();
834
- doc.save();
835
- doc.lineWidth(0.5);
836
- doc.strokeColor(layout.vLineColor ?? "#ccc");
837
- doc.moveTo(x, rowTop2).lineTo(x, bottomY).stroke();
838
- doc.moveTo(x + colW, rowTop2).lineTo(x + colW, bottomY).stroke();
839
- doc.restore();
1150
+ const effectiveBorder = getEffectiveCellBorder({
1151
+ table,
1152
+ cell,
1153
+ rowIndex,
1154
+ startCol
1155
+ });
1156
+ if (!drawTopBorder) {
1157
+ effectiveBorder.top.visible = false;
840
1158
  }
1159
+ drawCellBorder(doc, effectiveBorder, x, rowTop2, colW, drawHeight);
841
1160
  });
842
1161
  return rowTop2 + rowHeight;
843
1162
  };
@@ -877,16 +1196,133 @@ var processTableBlock = (doc, ctx, styles, table, y, env, computeColumnPixelWidt
877
1196
  if (y === null) ctx.currentY = newY;
878
1197
  return newY;
879
1198
  };
1199
+ var SIDES = ["top", "right", "bottom", "left"];
1200
+ var DEFAULT_BORDER_COLOR = "#ccc";
1201
+ var DEFAULT_BORDER_WIDTH = 0.5;
1202
+ var isBorderStyleObject = (value) => {
1203
+ return !!value && typeof value === "object" && !Array.isArray(value);
1204
+ };
1205
+ var normalizeOneSideBorder = (value, fallback) => {
1206
+ if (value === void 0) return fallback;
1207
+ if (typeof value === "boolean") {
1208
+ return {
1209
+ ...fallback,
1210
+ visible: value
1211
+ };
1212
+ }
1213
+ return {
1214
+ visible: value.visible ?? fallback.visible,
1215
+ color: value.color ?? fallback.color,
1216
+ width: value.width ?? fallback.width,
1217
+ dash: value.dash ?? fallback.dash
1218
+ };
1219
+ };
1220
+ var normalizeCellBorder = (input, fallback) => {
1221
+ if (input === void 0) return fallback;
1222
+ if (typeof input === "boolean") {
1223
+ return SIDES.reduce((acc, side) => {
1224
+ acc[side] = {
1225
+ ...fallback[side],
1226
+ visible: input
1227
+ };
1228
+ return acc;
1229
+ }, {});
1230
+ }
1231
+ if (isBorderStyleObject(input) && ("visible" in input || "color" in input || "width" in input || "dash" in input)) {
1232
+ return SIDES.reduce((acc, side) => {
1233
+ acc[side] = normalizeOneSideBorder(input, fallback[side]);
1234
+ return acc;
1235
+ }, {});
1236
+ }
1237
+ const sideInput = input;
1238
+ return SIDES.reduce((acc, side) => {
1239
+ acc[side] = normalizeOneSideBorder(sideInput[side], fallback[side]);
1240
+ return acc;
1241
+ }, {});
1242
+ };
1243
+ var createDefaultTableBorder = (layout) => {
1244
+ const visible = layout?.border !== "none";
1245
+ const hColor = layout?.hLineColor ?? layout?.borderColor ?? DEFAULT_BORDER_COLOR;
1246
+ const vColor = layout?.vLineColor ?? layout?.borderColor ?? DEFAULT_BORDER_COLOR;
1247
+ const width = layout?.borderWidth ?? DEFAULT_BORDER_WIDTH;
1248
+ return {
1249
+ top: {
1250
+ visible,
1251
+ color: hColor,
1252
+ width,
1253
+ dash: layout?.borderDash
1254
+ },
1255
+ bottom: {
1256
+ visible,
1257
+ color: hColor,
1258
+ width,
1259
+ dash: layout?.borderDash
1260
+ },
1261
+ left: {
1262
+ visible,
1263
+ color: vColor,
1264
+ width,
1265
+ dash: layout?.borderDash
1266
+ },
1267
+ right: {
1268
+ visible,
1269
+ color: vColor,
1270
+ width,
1271
+ dash: layout?.borderDash
1272
+ }
1273
+ };
1274
+ };
1275
+ var getEffectiveCellBorder = (args) => {
1276
+ const { table, cell, rowIndex, startCol } = args;
1277
+ const tableBorder = createDefaultTableBorder(table.layout);
1278
+ const columnBorder = normalizeCellBorder(table.layout?.columnStyles?.[startCol]?.border, tableBorder);
1279
+ const rowBorder = normalizeCellBorder(table.layout?.rowStyles?.[rowIndex]?.border, columnBorder);
1280
+ return normalizeCellBorder(cell.border, rowBorder);
1281
+ };
1282
+ var drawBorderSide = (doc, side, border, x, y, width, height) => {
1283
+ if (!border.visible || border.width <= 0) return;
1284
+ doc.save();
1285
+ doc.lineWidth(border.width);
1286
+ doc.strokeColor(border.color);
1287
+ if (border.dash?.length) {
1288
+ doc.dash(border.dash[0], {
1289
+ space: border.dash[1] ?? border.dash[0]
1290
+ });
1291
+ } else {
1292
+ doc.undash();
1293
+ }
1294
+ switch (side) {
1295
+ case "top":
1296
+ doc.moveTo(x, y).lineTo(x + width, y).stroke();
1297
+ break;
1298
+ case "right":
1299
+ doc.moveTo(x + width, y).lineTo(x + width, y + height).stroke();
1300
+ break;
1301
+ case "bottom":
1302
+ doc.moveTo(x, y + height).lineTo(x + width, y + height).stroke();
1303
+ break;
1304
+ case "left":
1305
+ doc.moveTo(x, y).lineTo(x, y + height).stroke();
1306
+ break;
1307
+ }
1308
+ doc.restore();
1309
+ };
1310
+ var drawCellBorder = (doc, border, x, y, width, height) => {
1311
+ drawBorderSide(doc, "top", border.top, x, y, width, height);
1312
+ drawBorderSide(doc, "right", border.right, x, y, width, height);
1313
+ drawBorderSide(doc, "bottom", border.bottom, x, y, width, height);
1314
+ drawBorderSide(doc, "left", border.left, x, y, width, height);
1315
+ };
880
1316
 
881
1317
  // src/renderer-engine/blocks/text.ts
882
1318
  var processTextBlock = (doc, ctx, styles, block, y, env, ensureSpaceFor) => {
883
1319
  const tb = resolveTextBlock(styles, block);
1320
+ const mt = tb.marginTop ?? 0;
1321
+ const mb = tb.marginBottom ?? 0;
884
1322
  const localLeft = tb.marginLeft ?? 0;
885
1323
  const localRight = tb.marginRight ?? 0;
886
1324
  const xLeft = env.marginLeft + localLeft;
887
1325
  const width = Math.max(env.innerWidth - localLeft - localRight, 1);
888
- const baseY = y ?? ctx.currentY;
889
- const startY = baseY;
890
1326
  doc.fontSize(tb.fontSize ?? 10);
891
1327
  const isBold = !!tb.bold;
892
1328
  const isItalic = !!tb.italic;
@@ -900,11 +1336,12 @@ var processTextBlock = (doc, ctx, styles, block, y, env, ensureSpaceFor) => {
900
1336
  doc.font(fontName);
901
1337
  if (tb.color) doc.fillColor(tb.color);
902
1338
  else doc.fillColor("black");
903
- const textHeight = doc.heightOfString(tb.text, { width });
1339
+ const lineGap = tb.lineGap ?? 4;
1340
+ const textHeight = doc.heightOfString(tb.text, { width, lineGap });
904
1341
  if (y === null) {
905
- const gapCheck = tb.lineGap ?? 4;
906
- ensureSpaceFor(textHeight + gapCheck, env);
1342
+ ensureSpaceFor(mt + textHeight + lineGap + mb, env);
907
1343
  }
1344
+ const startY = (y ?? ctx.currentY) + mt;
908
1345
  doc.text(tb.text, xLeft, startY, {
909
1346
  width,
910
1347
  align: tb.align ?? "left",
@@ -912,358 +1349,82 @@ var processTextBlock = (doc, ctx, styles, block, y, env, ensureSpaceFor) => {
912
1349
  strike: !!tb.strike,
913
1350
  link: tb.link
914
1351
  });
915
- const gap = tb.lineGap ?? 4;
916
- const newY = startY + textHeight + gap;
1352
+ const newY = doc.y + lineGap + mb;
917
1353
  if (y === null) ctx.currentY = newY;
918
1354
  return newY;
919
1355
  };
920
1356
 
921
- // src/renderer-engine/utils/block-renderer.ts
922
- function createBlockRenderer(deps) {
923
- const { doc, ctx, styles, computeColumnPixelWidths: computeColumnPixelWidths2, finishPage: finishPage2, processSignatureBlock } = deps;
924
- const bottomLimitForContent = createBottomLimitForContent(doc, ctx);
925
- const ensureSpaceFor = createEnsureSpaceFor(ctx, bottomLimitForContent, finishPage2);
926
- const measureBlockHeight = createMeasureBlockHeight({
927
- doc,
928
- styles,
929
- computeColumnPixelWidths: computeColumnPixelWidths2
930
- });
931
- const renderBlock = (block, y, env) => {
932
- if (block.visible === false) {
933
- return y ?? ctx.currentY;
934
- }
935
- switch (block.type) {
936
- case "text":
937
- return processTextBlock(doc, ctx, styles, block, y, env, ensureSpaceFor);
938
- case "image":
939
- return processImageBlock(doc, ctx, block, y, env, ensureSpaceFor);
940
- case "qr": {
941
- const qb = block;
942
- const imageLike = {
943
- type: "image",
944
- src: qb.src,
945
- width: qb.size,
946
- height: qb.size,
947
- align: qb.align,
948
- marginTop: qb.marginTop,
949
- marginBottom: qb.marginBottom,
950
- marginLeft: qb.marginLeft,
951
- marginRight: qb.marginRight
952
- };
953
- return processImageBlock(doc, ctx, imageLike, y, env, ensureSpaceFor);
954
- }
955
- case "barcode":
956
- return processBarcodeBlock(doc, ctx, block, y, env, ensureSpaceFor);
957
- case "line":
958
- return processLineBlock(doc, ctx, block, y, env, ensureSpaceFor);
959
- case "table":
960
- return processTableBlock(
961
- doc,
962
- ctx,
963
- styles,
964
- block,
965
- y,
966
- env,
967
- computeColumnPixelWidths2,
968
- bottomLimitForContent,
969
- finishPage2
970
- );
971
- case "columns":
972
- return processColumnsBlock(
973
- ctx,
974
- block,
975
- y,
976
- env,
977
- computeColumnPixelWidths2,
978
- renderBlock,
979
- ensureSpaceFor,
980
- measureBlockHeight
981
- );
982
- case "keyValueGrid":
983
- return processKeyValueGridBlock(
984
- doc,
985
- ctx,
986
- styles,
987
- block,
988
- y,
989
- env,
990
- computeColumnPixelWidths2,
991
- ensureSpaceFor
992
- );
993
- case "signature":
994
- if (!env.allowPageBreak) {
995
- throw new PdfEngineError({
996
- code: "PDF_ERROR_SIGNATURE_NOT_IN_MAIN_FLOW" /* PDF_ERROR_SIGNATURE_NOT_IN_MAIN_FLOW */,
997
- message: "Signature block is only allowed in main content flow.",
998
- statusCode: 400,
999
- details: { blockType: "signature" }
1000
- });
1001
- }
1002
- if (y !== null) {
1003
- throw new PdfEngineError({
1004
- code: "PDF_ERROR_SIGNATURE_EXPLICIT_Y_FORBIDDEN" /* PDF_ERROR_SIGNATURE_EXPLICIT_Y_FORBIDDEN */,
1005
- message: "Signature block must be part of main flow, not drawn at explicit Y.",
1006
- statusCode: 400,
1007
- details: { blockType: "signature", y }
1008
- });
1009
- }
1010
- processSignatureBlock(block);
1011
- return ctx.currentY;
1012
- case "pageBreak":
1013
- if (!env.allowPageBreak || ctx.inFooter) {
1014
- return y ?? ctx.currentY;
1015
- }
1016
- finishPage2(true);
1017
- return ctx.currentY;
1018
- default:
1019
- return ctx.currentY;
1020
- }
1021
- };
1022
- const renderBlockArray = (blocks, startY, env) => {
1023
- let localY = startY;
1024
- for (const block of blocks) {
1025
- if (block.visible === false) {
1026
- continue;
1027
- }
1028
- localY = renderBlock(block, localY, env);
1029
- }
1030
- return localY;
1031
- };
1032
- return {
1033
- renderBlock,
1034
- renderBlockArray
1035
- };
1036
- }
1037
-
1038
- // src/renderer-engine/utils/context.ts
1039
- function createInitialContext(doc) {
1040
- return {
1041
- pageNumber: 1,
1042
- currentY: doc.page.margins.top,
1043
- signatureBlock: null,
1044
- signatureTopY: null,
1045
- signatureHeight: 0,
1046
- signaturePlaced: false,
1047
- afterSignature: false,
1048
- inFooter: false
1049
- };
1050
- }
1051
-
1052
1357
  // src/renderer-engine/utils/ensure-space.ts
1053
- function createEnsureSpaceFor(ctx, bottomLimitForContent, finishPage2) {
1358
+ function createEnsureSpaceFor(ctx, doc, bottomLimitForContent, finishPage2) {
1054
1359
  return (heightNeeded, env) => {
1055
1360
  if (!env.allowPageBreak || ctx.inFooter) return;
1056
1361
  const bottomLimit = bottomLimitForContent();
1362
+ const fullContentHeight = bottomLimit - doc.page.margins.top;
1363
+ if (heightNeeded > fullContentHeight) {
1364
+ console.warn(
1365
+ `[pdf-engine] Block height (${Math.round(heightNeeded)}pt) exceeds page content area (${Math.round(fullContentHeight)}pt). Content will overflow.`
1366
+ );
1367
+ }
1057
1368
  if (ctx.currentY + heightNeeded > bottomLimit) {
1058
1369
  finishPage2(true);
1059
1370
  }
1060
1371
  };
1061
1372
  }
1062
1373
 
1063
- // src/renderer-engine/utils/env.ts
1064
- var contentEnv = (doc) => ({
1065
- marginLeft: doc.page.margins.left,
1066
- innerWidth: doc.page.width - doc.page.margins.left - doc.page.margins.right,
1067
- allowPageBreak: true
1374
+ // src/renderer-engine/utils/spacing.ts
1375
+ var emptySpacing = () => ({
1376
+ top: 0,
1377
+ right: 0,
1378
+ bottom: 0,
1379
+ left: 0
1068
1380
  });
1069
-
1070
- // src/renderer-engine/utils/finish-page.ts
1071
- function finishPage({
1072
- addNewPage,
1073
- doc,
1074
- def,
1075
- ctx,
1076
- footerBandHeight,
1077
- renderBlockArray,
1078
- startNewPageLayout
1079
- }) {
1080
- const mode = def.watermark?.mode;
1081
- if (def.watermark && watermarkUsesLast(mode)) {
1082
- const isLast = !addNewPage;
1083
- drawWatermarkForPage(doc, def.watermark, ctx.pageNumber, isLast);
1381
+ var resolveSpacing = (value, overrides) => {
1382
+ const result = emptySpacing();
1383
+ if (typeof value === "number") {
1384
+ result.top = value;
1385
+ result.right = value;
1386
+ result.bottom = value;
1387
+ result.left = value;
1388
+ } else if (value) {
1389
+ result.top = value.top ?? 0;
1390
+ result.right = value.right ?? 0;
1391
+ result.bottom = value.bottom ?? 0;
1392
+ result.left = value.left ?? 0;
1084
1393
  }
1085
- if (ctx.signatureBlock && ctx.signatureTopY !== null) {
1086
- const env = contentEnv(doc);
1087
- drawSignatureBlock(doc, ctx.signatureBlock, ctx.signatureTopY, env, renderBlockArray);
1088
- }
1089
- drawFooter(doc, def, ctx, footerBandHeight, renderBlockArray);
1090
- if (addNewPage) {
1091
- doc.addPage();
1092
- ctx.pageNumber += 1;
1093
- startNewPageLayout();
1094
- }
1095
- }
1096
-
1097
- // src/renderer-engine/utils/footer.ts
1098
- function normalizeFooter(input, ctx, doc) {
1099
- if (!input) return null;
1100
- if (typeof input === "function") {
1101
- const result = input(ctx.pageNumber, {
1102
- width: doc.page.width,
1103
- height: doc.page.height
1104
- });
1105
- if (!result) return null;
1106
- return normalizeFooter(result, ctx, doc);
1107
- }
1108
- if (input.blocks && Array.isArray(input.blocks)) {
1109
- const f = input;
1110
- return {
1111
- visible: f.visible,
1112
- blocks: f.blocks,
1113
- marginTop: f.marginTop,
1114
- marginBottom: f.marginBottom,
1115
- marginLeft: f.marginLeft,
1116
- marginRight: f.marginRight,
1117
- backgroundColor: f.backgroundColor,
1118
- backgroundImage: f.backgroundImage
1119
- };
1120
- }
1121
- if (input.type) {
1122
- return { blocks: [input] };
1123
- }
1124
- if (Array.isArray(input)) {
1125
- return { blocks: input };
1126
- }
1127
- return null;
1128
- }
1129
- function drawFooter(doc, def, ctx, footerBandHeight, renderBlockArray) {
1130
- const footerConfig = def.footer;
1131
- if (!footerConfig) return;
1132
- const layout = normalizeFooter(footerConfig, ctx, doc);
1133
- if (!layout || !layout.blocks.length) return;
1134
- if (layout.visible === false) return;
1135
- const bandHeight = footerBandHeight;
1136
- if (!bandHeight) return;
1137
- const { marginTop = 4, backgroundColor, backgroundImage, blocks } = layout;
1138
- const footerMarginLeft = layout.marginLeft ?? 0;
1139
- const footerMarginRight = layout.marginRight ?? 0;
1140
- const contentWidth = doc.page.width - footerMarginLeft - footerMarginRight;
1141
- const footerEnv = {
1142
- marginLeft: footerMarginLeft,
1143
- innerWidth: contentWidth,
1144
- allowPageBreak: false
1145
- };
1146
- const pageHeight = doc.page.height;
1147
- const bandTop = pageHeight - bandHeight;
1148
- if (backgroundColor) {
1149
- doc.save();
1150
- doc.rect(0, bandTop, doc.page.width, bandHeight).fill(backgroundColor);
1151
- doc.restore();
1152
- }
1153
- if (backgroundImage) {
1154
- try {
1155
- doc.image(backgroundImage, 0, bandTop, {
1156
- width: doc.page.width,
1157
- height: bandHeight
1158
- });
1159
- } catch (e) {
1160
- console.warn("Failed to load footer background image:", e);
1161
- }
1162
- }
1163
- doc.save();
1164
- doc.rect(footerMarginLeft, bandTop, contentWidth, bandHeight).clip();
1165
- doc.translate(0, bandTop);
1166
- ctx.inFooter = true;
1167
- const localStartY = marginTop;
1168
- renderBlockArray(blocks, localStartY, footerEnv);
1169
- ctx.inFooter = false;
1170
- doc.restore();
1171
- }
1172
-
1173
- // src/renderer-engine/utils/header.ts
1174
- function drawHeader(doc, def, headerBandHeight, header, renderBlockArray) {
1175
- if (!header || !header.blocks.length) return;
1176
- if (header.visible === false) return;
1177
- if (!headerBandHeight) return;
1178
- const bandTop = 0;
1179
- const bandHeight = def.margins.top;
1180
- const headerMarginLeft = header.marginLeft ?? 0;
1181
- const headerMarginRight = header.marginRight ?? 0;
1182
- const contentWidth = doc.page.width - headerMarginLeft - headerMarginRight;
1183
- const headerEnv = {
1184
- marginLeft: headerMarginLeft,
1185
- innerWidth: contentWidth,
1186
- allowPageBreak: false
1394
+ return {
1395
+ top: overrides?.top ?? result.top,
1396
+ right: overrides?.right ?? result.right,
1397
+ bottom: overrides?.bottom ?? result.bottom,
1398
+ left: overrides?.left ?? result.left
1187
1399
  };
1188
- if (header.backgroundColor) {
1189
- doc.save();
1190
- doc.rect(0, bandTop, doc.page.width, bandHeight).fill(header.backgroundColor);
1191
- doc.restore();
1192
- }
1193
- if (header.backgroundImage) {
1194
- try {
1195
- doc.image(header.backgroundImage, 0, bandTop, {
1196
- width: doc.page.width,
1197
- height: bandHeight
1198
- });
1199
- } catch (e) {
1200
- console.warn("Failed to load header background image:", e);
1201
- }
1202
- }
1203
- doc.save();
1204
- doc.rect(headerMarginLeft, bandTop, contentWidth, bandHeight).clip();
1205
- const startY = bandTop + (header.marginTop ?? 0);
1206
- renderBlockArray(header.blocks, startY, headerEnv);
1207
- doc.restore();
1208
- }
1209
-
1210
- // src/renderer-engine/utils/image-loader.ts
1211
- var import_axios = __toESM(require("axios"));
1212
- async function normalizeImageSrc(src) {
1213
- if (!src) return src;
1214
- if (Buffer.isBuffer(src)) return src;
1215
- if (src.startsWith("http://") || src.startsWith("https://")) {
1216
- try {
1217
- const res = await import_axios.default.get(src, { responseType: "arraybuffer" });
1218
- return Buffer.from(res.data);
1219
- } catch (e) {
1220
- throw toPdfEngineError(e, {
1221
- code: "PDF_ERROR_IMAGE_FETCH_FAILED" /* PDF_ERROR_IMAGE_FETCH_FAILED */,
1222
- message: "Failed to fetch remote image for PDF.",
1223
- statusCode: 422,
1224
- details: { url: src },
1225
- retryable: false
1226
- });
1227
- }
1228
- }
1229
- return src;
1230
- }
1231
- async function materializeImagesInBlocks(blocks) {
1232
- const out = [];
1233
- for (const block of blocks) {
1234
- if (block.type === "image") {
1235
- const img = { ...block };
1236
- img.src = await normalizeImageSrc(img.src);
1237
- out.push(img);
1238
- } else if (block.type === "columns") {
1239
- out.push({
1240
- ...block,
1241
- columns: await Promise.all(block.columns.map((col) => materializeImagesInBlocks(col)))
1242
- });
1243
- } else if (block.type === "signature" && block.blocks) {
1244
- out.push({
1245
- ...block,
1246
- blocks: await materializeImagesInBlocks(block.blocks)
1247
- });
1248
- } else {
1249
- out.push(block);
1250
- }
1251
- }
1252
- return out;
1253
- }
1254
-
1255
- // src/renderer-engine/utils/layout.ts
1256
- function computeColumnPixelWidths(widths, totalWidth) {
1257
- let fixedTotal = 0;
1258
- let starCount = 0;
1259
- widths.forEach((w) => {
1260
- if (w === "*") starCount++;
1261
- else fixedTotal += w;
1400
+ };
1401
+ var resolveBlockPadding = (block) => {
1402
+ return resolveSpacing(block.padding, {
1403
+ top: block.paddingTop,
1404
+ right: block.paddingRight,
1405
+ bottom: block.paddingBottom,
1406
+ left: block.paddingLeft
1262
1407
  });
1263
- const remaining = Math.max(totalWidth - fixedTotal, 0);
1264
- const starWidth = starCount > 0 ? remaining / starCount : 0;
1265
- return widths.map((w) => w === "*" ? starWidth : w);
1266
- }
1408
+ };
1409
+ var resolveHeaderPadding = (header) => {
1410
+ return resolveSpacing(header.padding, {
1411
+ top: header.paddingTop,
1412
+ right: header.paddingRight,
1413
+ bottom: header.paddingBottom,
1414
+ left: header.paddingLeft
1415
+ });
1416
+ };
1417
+ var resolveFooterPadding = (footer) => {
1418
+ return resolveSpacing(footer.padding, {
1419
+ top: footer.paddingTop,
1420
+ right: footer.paddingRight,
1421
+ bottom: footer.paddingBottom,
1422
+ left: footer.paddingLeft
1423
+ });
1424
+ };
1425
+ var hasPadding = (padding) => {
1426
+ return padding.top > 0 || padding.right > 0 || padding.bottom > 0 || padding.left > 0;
1427
+ };
1267
1428
 
1268
1429
  // src/renderer-engine/utils/styles.ts
1269
1430
  function mergeStyleDefs(styles, names) {
@@ -1359,191 +1520,772 @@ var drawStyledText = (doc, tb, x, y, width) => {
1359
1520
  // src/renderer-engine/utils/measure-block-height.ts
1360
1521
  function createMeasureBlockHeight(deps) {
1361
1522
  const { doc, styles, computeColumnPixelWidths: computeColumnPixelWidths2 } = deps;
1362
- const measureText = (b, env) => {
1363
- const tb = resolveTextBlock(styles, b);
1364
- const width = Math.max(env.innerWidth, 1);
1523
+ const measureText = (block, env) => {
1524
+ const tb = resolveTextBlock(styles, block);
1525
+ const mt = tb.marginTop ?? 0;
1526
+ const mb = tb.marginBottom ?? 0;
1527
+ const localLeft = tb.marginLeft ?? 0;
1528
+ const localRight = tb.marginRight ?? 0;
1529
+ const width = Math.max(env.innerWidth - localLeft - localRight, 1);
1365
1530
  doc.font(getFontNameForText(tb));
1366
1531
  doc.fontSize(tb.fontSize ?? 10);
1367
- const h = doc.heightOfString(tb.text ?? "", { width });
1368
- const gap = tb.lineGap ?? 4;
1369
- return h + gap;
1532
+ const lineGap = tb.lineGap ?? 4;
1533
+ const height = doc.heightOfString(tb.text ?? "", { width, lineGap });
1534
+ return mt + height + lineGap + mb;
1370
1535
  };
1371
- const measureImageLike = (mt, mb, h) => (mt ?? 0) + h + (mb ?? 0);
1372
- const measureImage = (b) => {
1373
- const h = b.height ?? 50;
1374
- return measureImageLike(b.marginTop, b.marginBottom, h);
1536
+ const measureImage = (block) => {
1537
+ return (block.marginTop ?? 0) + (block.height ?? 50) + (block.marginBottom ?? 0);
1375
1538
  };
1376
- const measureQr = (b) => {
1377
- const size = b.size ?? 80;
1378
- return measureImageLike(b.marginTop, b.marginBottom, size);
1539
+ const measureQr = (block) => {
1540
+ return (block.marginTop ?? 0) + (block.size ?? 80) + (block.marginBottom ?? 0);
1379
1541
  };
1380
- const measureBarcode = (b) => {
1381
- const h = b.height ?? 40;
1382
- return measureImageLike(b.marginTop, b.marginBottom, h);
1542
+ const measureBarcode = (block) => {
1543
+ return (block.marginTop ?? 0) + (block.height ?? 40) + (block.marginBottom ?? 0);
1383
1544
  };
1384
- const measureLine = (b) => {
1385
- const lw = b.lineWidth ?? 1;
1386
- const mt = b.marginTop ?? 0;
1387
- const mb = b.marginBottom ?? 0;
1388
- return mt + lw + mb;
1545
+ const measureShape = (block) => {
1546
+ return (block.marginTop ?? 0) + (block.height ?? block.lineWidth ?? 1) + (block.marginBottom ?? 0);
1389
1547
  };
1390
- const measureTable = (b, env) => {
1391
- const mt = b.marginTop ?? 0;
1392
- const mb = b.marginBottom ?? 0;
1393
- const ml = b.marginLeft ?? 0;
1394
- const mr = b.marginRight ?? 0;
1395
- const innerWidth = Math.max(env.innerWidth - ml - mr, 1);
1396
- const fakeEnv = {
1397
- marginLeft: 0,
1398
- innerWidth,
1399
- allowPageBreak: false
1400
- };
1401
- const h = measureTableHeight(doc, b, fakeEnv, styles, computeColumnPixelWidths2);
1402
- return mt + h + mb;
1548
+ const measureLine = (block) => {
1549
+ return (block.marginTop ?? 0) + (block.lineWidth ?? 1) + (block.marginBottom ?? 0);
1403
1550
  };
1404
- const measureColumns = (b, env) => {
1405
- const mt = b.marginTop ?? 0;
1406
- const mb = b.marginBottom ?? 0;
1407
- const blockLeft = b.marginLeft ?? 0;
1408
- const blockRight = b.marginRight ?? 0;
1551
+ const measureColumns = (block, env) => {
1552
+ const mt = block.marginTop ?? 0;
1553
+ const mb = block.marginBottom ?? 0;
1554
+ const blockLeft = block.marginLeft ?? 0;
1555
+ const blockRight = block.marginRight ?? 0;
1409
1556
  const totalWidth = Math.max(env.innerWidth - blockLeft - blockRight, 1);
1410
- const cols = b.columns ?? [];
1557
+ const cols = block.columns ?? [];
1411
1558
  const n = cols.length;
1412
1559
  if (!n) return mt + mb;
1413
1560
  let colWidths;
1414
- const mode = b.mode ?? "fixedGap";
1415
- let gap;
1561
+ const mode = block.mode ?? "fixedGap";
1416
1562
  if (mode === "spaceBetween" && n > 1) {
1417
- if (b.widths && b.widths.length === n) {
1418
- colWidths = computeColumnPixelWidths2(b.widths, totalWidth);
1563
+ if (block.widths && block.widths.length === n) {
1564
+ colWidths = computeColumnPixelWidths2(block.widths, totalWidth);
1419
1565
  } else {
1420
1566
  colWidths = Array(n).fill(totalWidth / n);
1421
1567
  }
1422
- const totalColsWidth = colWidths.reduce((a, x) => a + x, 0);
1423
- const remaining = Math.max(totalWidth - totalColsWidth, 0);
1424
- gap = remaining / (n - 1);
1425
- void gap;
1426
1568
  } else {
1427
- gap = b.gap ?? 20;
1569
+ const gap = block.gap ?? 20;
1428
1570
  const totalGapsWidth = gap * (n - 1);
1429
1571
  const widthForCols = Math.max(totalWidth - totalGapsWidth, 1);
1430
- if (b.widths && b.widths.length === n) {
1431
- colWidths = computeColumnPixelWidths2(b.widths, widthForCols);
1572
+ if (block.widths && block.widths.length === n) {
1573
+ colWidths = computeColumnPixelWidths2(block.widths, widthForCols);
1432
1574
  } else {
1433
1575
  colWidths = Array(n).fill(widthForCols / n);
1434
1576
  }
1435
1577
  }
1436
- const heights = [];
1437
- for (let i = 0; i < n; i++) {
1438
- const colBlocks = cols[i] ?? [];
1439
- const colEnv = {
1440
- marginLeft: 0,
1441
- innerWidth: colWidths[i],
1442
- allowPageBreak: false
1443
- };
1444
- let colH = 0;
1445
- for (const child of colBlocks) {
1446
- if (!child || child.visible === false) continue;
1447
- colH += measure(child, colEnv);
1578
+ const heights = [];
1579
+ for (let i = 0; i < n; i++) {
1580
+ const colBlocks = cols[i] ?? [];
1581
+ const colEnv = {
1582
+ marginLeft: 0,
1583
+ innerWidth: colWidths[i],
1584
+ allowPageBreak: false
1585
+ };
1586
+ let colHeight = 0;
1587
+ for (const child of colBlocks) {
1588
+ if (!child || child.visible === false) continue;
1589
+ colHeight += measure(child, colEnv);
1590
+ }
1591
+ heights.push(colHeight);
1592
+ }
1593
+ return mt + Math.max(...heights, 0) + mb;
1594
+ };
1595
+ const measureTable = (block, env) => {
1596
+ const mt = block.marginTop ?? 0;
1597
+ const mb = block.marginBottom ?? 0;
1598
+ const ml = block.marginLeft ?? 0;
1599
+ const mr = block.marginRight ?? 0;
1600
+ const innerWidth = Math.max(env.innerWidth - ml - mr, 1);
1601
+ const fakeEnv = {
1602
+ marginLeft: 0,
1603
+ innerWidth,
1604
+ allowPageBreak: false
1605
+ };
1606
+ const height = measureTableHeight(doc, block, fakeEnv, styles, computeColumnPixelWidths2, measure);
1607
+ return mt + height + mb;
1608
+ };
1609
+ const measureKeyValueGrid = (block, env) => {
1610
+ const mt = block.marginTop ?? 0;
1611
+ const mb = block.marginBottom ?? 0;
1612
+ const ml = block.marginLeft ?? 0;
1613
+ const mr = block.marginRight ?? 0;
1614
+ const totalWidth = Math.max(env.innerWidth - ml - mr, 1);
1615
+ const cols = block.columns ?? [];
1616
+ const colCount = cols.length;
1617
+ if (!colCount) return mt + mb;
1618
+ const rowGap = block.rowGap ?? 4;
1619
+ const keyValueGap = block.verticalKeyValueGap ?? 2;
1620
+ const separatorText = block.separator ?? "";
1621
+ const separatorWidth = separatorText ? doc.widthOfString(separatorText) : 0;
1622
+ let colWidths;
1623
+ if (block.columnWidths && block.columnWidths.length === colCount) {
1624
+ colWidths = computeColumnPixelWidths2(
1625
+ block.columnWidths.map((w) => w ?? "*"),
1626
+ totalWidth
1627
+ );
1628
+ } else {
1629
+ colWidths = Array(colCount).fill(totalWidth / colCount);
1630
+ }
1631
+ const measureTextHeight2 = (text, width) => {
1632
+ doc.fontSize(10);
1633
+ return doc.heightOfString(text ?? "", { width }) + 4;
1634
+ };
1635
+ let totalHeight = mt;
1636
+ if (block.orientation === "vertical") {
1637
+ let maxColHeight = 0;
1638
+ for (let colIndex = 0; colIndex < colCount; colIndex++) {
1639
+ const col = cols[colIndex] ?? [];
1640
+ const colWidth = colWidths[colIndex];
1641
+ let colHeight = 0;
1642
+ for (const item of col) {
1643
+ const keyHeight = measureTextHeight2(item.key ?? "", colWidth);
1644
+ const valueHeight = measureTextHeight2(item.value ?? "", colWidth);
1645
+ colHeight += keyHeight + keyValueGap + valueHeight + rowGap;
1646
+ }
1647
+ maxColHeight = Math.max(maxColHeight, colHeight);
1648
+ }
1649
+ totalHeight += maxColHeight;
1650
+ } else {
1651
+ const maxRows = Math.max(...cols.map((c) => c ? c.length : 0), 0);
1652
+ for (let rowIndex = 0; rowIndex < maxRows; rowIndex++) {
1653
+ let rowHeight = 0;
1654
+ for (let colIndex = 0; colIndex < colCount; colIndex++) {
1655
+ const item = cols[colIndex]?.[rowIndex];
1656
+ if (!item) continue;
1657
+ const colWidth = colWidths[colIndex];
1658
+ const keyWidth = block.keyWidth === "*" ? Math.max(colWidth * 0.35, 20) : block.keyWidth ?? 80;
1659
+ const keyHeight = measureTextHeight2(item.key ?? "", keyWidth);
1660
+ const valueXInsideCol = keyWidth + (separatorText ? separatorWidth + 4 : 4);
1661
+ const valueWidth = Math.max(colWidth - valueXInsideCol, 1);
1662
+ const valueHeight = measureTextHeight2(item.value ?? "", valueWidth);
1663
+ rowHeight = Math.max(rowHeight, keyHeight, valueHeight);
1664
+ }
1665
+ if (rowHeight > 0) {
1666
+ totalHeight += rowHeight + rowGap;
1667
+ }
1668
+ }
1669
+ }
1670
+ return totalHeight + mb;
1671
+ };
1672
+ const stripBoxModelProps = (block) => {
1673
+ return {
1674
+ ...block,
1675
+ marginTop: 0,
1676
+ marginBottom: 0,
1677
+ marginLeft: 0,
1678
+ marginRight: 0,
1679
+ backgroundColor: void 0,
1680
+ backgroundImage: void 0,
1681
+ backgroundOpacity: void 0,
1682
+ backgroundBlocks: void 0,
1683
+ padding: void 0,
1684
+ paddingTop: void 0,
1685
+ paddingRight: void 0,
1686
+ paddingBottom: void 0,
1687
+ paddingLeft: void 0
1688
+ };
1689
+ };
1690
+ const measureRaw = (block, env) => {
1691
+ switch (block.type) {
1692
+ case "text":
1693
+ return measureText(block, env);
1694
+ case "image":
1695
+ return measureImage(block);
1696
+ case "qr":
1697
+ return measureQr(block);
1698
+ case "barcode":
1699
+ return measureBarcode(block);
1700
+ case "line":
1701
+ return measureLine(block);
1702
+ case "shape":
1703
+ return measureShape(block);
1704
+ case "columns":
1705
+ return measureColumns(block, env);
1706
+ case "table":
1707
+ return measureTable(block, env);
1708
+ case "keyValueGrid":
1709
+ return measureKeyValueGrid(block, env);
1710
+ case "list":
1711
+ return measureListHeight(doc, styles, block, env);
1712
+ case "signature":
1713
+ return block.height ?? 0;
1714
+ case "pageBreak":
1715
+ return 0;
1716
+ default:
1717
+ return 0;
1718
+ }
1719
+ };
1720
+ const measure = (block, env) => {
1721
+ if (!block || block.visible === false) return 0;
1722
+ if (env.isBackgroundLayer) {
1723
+ return measureRaw(block, env);
1724
+ }
1725
+ const padding = resolveBlockPadding(block);
1726
+ const hasBoxBackground = !!block.backgroundColor || !!block.backgroundImage || !!block.backgroundBlocks?.length;
1727
+ const shouldUseBoxModel = hasPadding(padding) || hasBoxBackground;
1728
+ if (!shouldUseBoxModel) {
1729
+ return measureRaw(block, env);
1730
+ }
1731
+ const marginTop = block.marginTop ?? 0;
1732
+ const marginBottom = block.marginBottom ?? 0;
1733
+ const marginLeft = block.marginLeft ?? 0;
1734
+ const marginRight = block.marginRight ?? 0;
1735
+ const outerWidth = Math.max(env.innerWidth - marginLeft - marginRight, 1);
1736
+ const innerWidth = Math.max(outerWidth - padding.left - padding.right, 1);
1737
+ const innerEnv = {
1738
+ ...env,
1739
+ marginLeft: 0,
1740
+ innerWidth
1741
+ };
1742
+ const innerBlock = stripBoxModelProps(block);
1743
+ const innerHeight = measureRaw(innerBlock, innerEnv);
1744
+ return marginTop + padding.top + innerHeight + padding.bottom + marginBottom;
1745
+ };
1746
+ return (block, env) => measure(block, env);
1747
+ }
1748
+
1749
+ // src/renderer-engine/utils/page-limit.ts
1750
+ function createBottomLimitForContent(doc, ctx) {
1751
+ return () => {
1752
+ const pageBottomForContent = doc.page.height - doc.page.margins.bottom;
1753
+ return ctx.signatureTopY ?? pageBottomForContent;
1754
+ };
1755
+ }
1756
+
1757
+ // src/renderer-engine/utils/block-renderer.ts
1758
+ function createBlockRenderer(deps) {
1759
+ const { doc, ctx, styles, computeColumnPixelWidths: computeColumnPixelWidths2, finishPage: finishPage2, processSignatureBlock, defaultImage } = deps;
1760
+ const bottomLimitForContent = createBottomLimitForContent(doc, ctx);
1761
+ const ensureSpaceFor = createEnsureSpaceFor(ctx, doc, bottomLimitForContent, finishPage2);
1762
+ const measureBlockHeight = createMeasureBlockHeight({
1763
+ doc,
1764
+ styles,
1765
+ computeColumnPixelWidths: computeColumnPixelWidths2
1766
+ });
1767
+ const stripBoxModelProps = (block) => {
1768
+ return {
1769
+ ...block,
1770
+ marginTop: 0,
1771
+ marginBottom: 0,
1772
+ marginLeft: 0,
1773
+ marginRight: 0,
1774
+ backgroundColor: void 0,
1775
+ backgroundImage: void 0,
1776
+ backgroundOpacity: void 0,
1777
+ backgroundBlocks: void 0,
1778
+ padding: void 0,
1779
+ paddingTop: void 0,
1780
+ paddingRight: void 0,
1781
+ paddingBottom: void 0,
1782
+ paddingLeft: void 0
1783
+ };
1784
+ };
1785
+ const renderBlockCore = (block, y, env) => {
1786
+ if (block.visible === false) {
1787
+ return y ?? ctx.currentY;
1788
+ }
1789
+ switch (block.type) {
1790
+ case "text":
1791
+ return processTextBlock(doc, ctx, styles, block, y, env, ensureSpaceFor);
1792
+ case "image":
1793
+ return processImageBlock(doc, ctx, block, y, env, ensureSpaceFor, defaultImage);
1794
+ case "qr": {
1795
+ const qb = block;
1796
+ const imageLike = {
1797
+ type: "image",
1798
+ src: qb.src,
1799
+ width: qb.size,
1800
+ height: qb.size,
1801
+ align: qb.align,
1802
+ marginTop: qb.marginTop,
1803
+ marginBottom: qb.marginBottom,
1804
+ marginLeft: qb.marginLeft,
1805
+ marginRight: qb.marginRight
1806
+ };
1807
+ return processImageBlock(doc, ctx, imageLike, y, env, ensureSpaceFor, defaultImage);
1808
+ }
1809
+ case "barcode":
1810
+ return processBarcodeBlock(doc, ctx, block, y, env, ensureSpaceFor);
1811
+ case "line":
1812
+ return processLineBlock(doc, ctx, block, y, env, ensureSpaceFor);
1813
+ case "shape":
1814
+ return processShapeBlock(doc, ctx, block, y, env, ensureSpaceFor);
1815
+ case "columns":
1816
+ return processColumnsBlock(
1817
+ ctx,
1818
+ block,
1819
+ y,
1820
+ env,
1821
+ computeColumnPixelWidths2,
1822
+ renderBlock,
1823
+ ensureSpaceFor,
1824
+ measureBlockHeight
1825
+ );
1826
+ case "table":
1827
+ return processTableBlock(
1828
+ doc,
1829
+ ctx,
1830
+ styles,
1831
+ block,
1832
+ y,
1833
+ env,
1834
+ computeColumnPixelWidths2,
1835
+ bottomLimitForContent,
1836
+ finishPage2,
1837
+ renderBlock,
1838
+ measureBlockHeight
1839
+ );
1840
+ case "keyValueGrid":
1841
+ return processKeyValueGridBlock(
1842
+ doc,
1843
+ ctx,
1844
+ styles,
1845
+ block,
1846
+ y,
1847
+ env,
1848
+ computeColumnPixelWidths2,
1849
+ ensureSpaceFor
1850
+ );
1851
+ case "list":
1852
+ return processListBlock(
1853
+ doc,
1854
+ ctx,
1855
+ styles,
1856
+ block,
1857
+ y,
1858
+ env,
1859
+ ensureSpaceFor
1860
+ );
1861
+ case "pageBreak":
1862
+ finishPage2(true);
1863
+ return ctx.currentY;
1864
+ case "signature":
1865
+ processSignatureBlock(block);
1866
+ return y ?? ctx.currentY;
1867
+ default:
1868
+ throw new PdfEngineError({
1869
+ code: "PDF_ERROR_BLOCK_UNSUPPORTED" /* PDF_ERROR_BLOCK_UNSUPPORTED */,
1870
+ message: `Unsupported block type: ${block.type}`,
1871
+ statusCode: 422,
1872
+ details: { block }
1873
+ });
1874
+ }
1875
+ };
1876
+ const renderBlock = (block, y, env) => {
1877
+ if (block.visible === false) {
1878
+ return y ?? ctx.currentY;
1879
+ }
1880
+ if (env.isBackgroundLayer) {
1881
+ return renderBlockCore(block, y, env);
1882
+ }
1883
+ const padding = resolveBlockPadding(block);
1884
+ const hasBoxBackground = !!block.backgroundColor || !!block.backgroundImage || !!block.backgroundBlocks?.length;
1885
+ const shouldUseBoxModel = hasPadding(padding) || hasBoxBackground;
1886
+ if (!shouldUseBoxModel) {
1887
+ return renderBlockCore(block, y, env);
1888
+ }
1889
+ const marginTop = block.marginTop ?? 0;
1890
+ const marginBottom = block.marginBottom ?? 0;
1891
+ const marginLeft = block.marginLeft ?? 0;
1892
+ const marginRight = block.marginRight ?? 0;
1893
+ const outerX = env.marginLeft + marginLeft;
1894
+ const outerWidth = Math.max(env.innerWidth - marginLeft - marginRight, 1);
1895
+ const innerX = outerX + padding.left;
1896
+ const innerWidth = Math.max(outerWidth - padding.left - padding.right, 1);
1897
+ const innerEnv = {
1898
+ ...env,
1899
+ marginLeft: innerX,
1900
+ innerWidth
1901
+ };
1902
+ const innerBlock = stripBoxModelProps(block);
1903
+ const innerHeight = measureBlockHeight(innerBlock, innerEnv);
1904
+ const boxHeight = padding.top + innerHeight + padding.bottom;
1905
+ const totalHeight = marginTop + boxHeight + marginBottom;
1906
+ if (y === null && env.allowPageBreak !== false && block.type !== "table") {
1907
+ ensureSpaceFor(totalHeight, env);
1908
+ }
1909
+ const finalOuterY = (y ?? ctx.currentY) + marginTop;
1910
+ if (block.backgroundColor) {
1911
+ doc.save();
1912
+ doc.fillOpacity(block.backgroundOpacity ?? 1).rect(outerX, finalOuterY, outerWidth, boxHeight).fill(block.backgroundColor);
1913
+ doc.restore();
1914
+ }
1915
+ if (block.backgroundImage) {
1916
+ try {
1917
+ doc.save();
1918
+ doc.opacity(block.backgroundOpacity ?? 1);
1919
+ doc.image(block.backgroundImage, outerX, finalOuterY, {
1920
+ width: outerWidth,
1921
+ height: boxHeight
1922
+ });
1923
+ doc.restore();
1924
+ } catch (_) {
1925
+ }
1926
+ }
1927
+ if (block.backgroundBlocks?.length) {
1928
+ doc.save();
1929
+ doc.opacity(block.backgroundOpacity ?? 1);
1930
+ renderBlockArray(block.backgroundBlocks, finalOuterY, {
1931
+ ...env,
1932
+ marginLeft: outerX,
1933
+ innerWidth: outerWidth,
1934
+ allowPageBreak: false,
1935
+ isBackgroundLayer: true
1936
+ });
1937
+ doc.restore();
1938
+ }
1939
+ const innerEndY = renderBlockCore(innerBlock, finalOuterY + padding.top, innerEnv);
1940
+ const newY = innerEndY + padding.bottom + marginBottom;
1941
+ if (y === null) {
1942
+ ctx.currentY = newY;
1943
+ }
1944
+ return newY;
1945
+ };
1946
+ const renderBlockArray = (blocks, startY, env) => {
1947
+ let localY = startY;
1948
+ for (const block of blocks) {
1949
+ localY = renderBlock(block, localY, env);
1950
+ }
1951
+ return localY;
1952
+ };
1953
+ return { renderBlock, renderBlockArray, measureBlockHeight };
1954
+ }
1955
+
1956
+ // src/renderer-engine/utils/context.ts
1957
+ function createInitialContext(doc) {
1958
+ return {
1959
+ pageNumber: 1,
1960
+ currentY: doc.page.margins.top,
1961
+ signatureBlock: null,
1962
+ signatureTopY: null,
1963
+ signatureHeight: 0,
1964
+ signaturePlaced: false,
1965
+ afterSignature: false,
1966
+ inFooter: false,
1967
+ inManualPageAdd: false
1968
+ };
1969
+ }
1970
+
1971
+ // src/renderer-engine/utils/env.ts
1972
+ var contentEnv = (doc) => ({
1973
+ marginLeft: doc.page.margins.left,
1974
+ innerWidth: doc.page.width - doc.page.margins.left - doc.page.margins.right,
1975
+ allowPageBreak: true
1976
+ });
1977
+
1978
+ // src/renderer-engine/utils/finish-page.ts
1979
+ function finishPage({
1980
+ addNewPage,
1981
+ doc,
1982
+ def,
1983
+ ctx,
1984
+ footerBandHeight,
1985
+ renderBlockArray,
1986
+ startNewPageLayout
1987
+ }) {
1988
+ const mode = def.watermark?.mode;
1989
+ if (def.watermark && watermarkUsesLast(mode)) {
1990
+ const isLast = !addNewPage;
1991
+ drawWatermarkForPage(doc, def.watermark, ctx.pageNumber, isLast);
1992
+ }
1993
+ if (ctx.signatureBlock && ctx.signatureTopY !== null) {
1994
+ const env = contentEnv(doc);
1995
+ drawSignatureBlock(doc, ctx.signatureBlock, ctx.signatureTopY, env, renderBlockArray);
1996
+ }
1997
+ drawFooter(doc, def, ctx, footerBandHeight, renderBlockArray);
1998
+ if (addNewPage) {
1999
+ ctx.inManualPageAdd = true;
2000
+ doc.addPage();
2001
+ ctx.inManualPageAdd = false;
2002
+ ctx.pageNumber += 1;
2003
+ startNewPageLayout();
2004
+ }
2005
+ }
2006
+
2007
+ // src/renderer-engine/utils/footer.ts
2008
+ function normalizeFooter(input, ctx, doc) {
2009
+ if (!input) return null;
2010
+ if (typeof input === "function") {
2011
+ const result = input(ctx.pageNumber, {
2012
+ width: doc.page.width,
2013
+ height: doc.page.height
2014
+ });
2015
+ if (!result) return null;
2016
+ return normalizeFooter(result, ctx, doc);
2017
+ }
2018
+ if (input.blocks && Array.isArray(input.blocks)) {
2019
+ const footer = input;
2020
+ return {
2021
+ visible: footer.visible,
2022
+ blocks: footer.blocks,
2023
+ backgroundBlocks: footer.backgroundBlocks,
2024
+ marginTop: footer.marginTop,
2025
+ marginBottom: footer.marginBottom,
2026
+ marginLeft: footer.marginLeft,
2027
+ marginRight: footer.marginRight,
2028
+ padding: footer.padding,
2029
+ paddingTop: footer.paddingTop,
2030
+ paddingRight: footer.paddingRight,
2031
+ paddingBottom: footer.paddingBottom,
2032
+ paddingLeft: footer.paddingLeft,
2033
+ backgroundColor: footer.backgroundColor,
2034
+ backgroundImage: footer.backgroundImage,
2035
+ backgroundOpacity: footer.backgroundOpacity
2036
+ };
2037
+ }
2038
+ if (input.type) {
2039
+ return { blocks: [input] };
2040
+ }
2041
+ if (Array.isArray(input)) {
2042
+ return { blocks: input };
2043
+ }
2044
+ return null;
2045
+ }
2046
+ function drawFooter(doc, def, ctx, footerBandHeight, renderBlockArray) {
2047
+ const footerConfig = def.footer;
2048
+ if (!footerConfig) return;
2049
+ const layout = normalizeFooter(footerConfig, ctx, doc);
2050
+ if (!layout) return;
2051
+ if (layout.visible === false) return;
2052
+ const blocks = layout.blocks ?? [];
2053
+ const backgroundBlocks = layout.backgroundBlocks ?? [];
2054
+ if (!blocks.length && !backgroundBlocks.length && !layout.backgroundColor && !layout.backgroundImage) {
2055
+ return;
2056
+ }
2057
+ const bandHeight = footerBandHeight;
2058
+ if (!bandHeight) return;
2059
+ const footerMarginLeft = layout.marginLeft ?? 0;
2060
+ const footerMarginRight = layout.marginRight ?? 0;
2061
+ const outerX = footerMarginLeft;
2062
+ const outerWidth = doc.page.width - footerMarginLeft - footerMarginRight;
2063
+ const padding = resolveFooterPadding(layout);
2064
+ const innerX = outerX + padding.left;
2065
+ const innerWidth = Math.max(outerWidth - padding.left - padding.right, 1);
2066
+ const outerEnv = {
2067
+ marginLeft: outerX,
2068
+ innerWidth: outerWidth,
2069
+ allowPageBreak: false
2070
+ };
2071
+ const innerEnv = {
2072
+ marginLeft: innerX,
2073
+ innerWidth,
2074
+ allowPageBreak: false
2075
+ };
2076
+ const pageHeight = doc.page.height;
2077
+ const bandTop = pageHeight - bandHeight;
2078
+ const backgroundOpacity = layout.backgroundOpacity ?? 1;
2079
+ if (layout.backgroundColor) {
2080
+ doc.save();
2081
+ doc.fillOpacity(backgroundOpacity).rect(0, bandTop, doc.page.width, bandHeight).fill(layout.backgroundColor);
2082
+ doc.restore();
2083
+ }
2084
+ if (layout.backgroundImage) {
2085
+ try {
2086
+ doc.save();
2087
+ doc.opacity(backgroundOpacity);
2088
+ doc.image(layout.backgroundImage, 0, bandTop, {
2089
+ width: doc.page.width,
2090
+ height: bandHeight
2091
+ });
2092
+ doc.restore();
2093
+ } catch (e) {
2094
+ console.warn("Failed to load footer background image:", e);
2095
+ }
2096
+ }
2097
+ doc.save();
2098
+ doc.rect(outerX, bandTop, outerWidth, bandHeight).clip();
2099
+ doc.translate(0, bandTop);
2100
+ ctx.inFooter = true;
2101
+ const localStartY = layout.marginTop ?? 4;
2102
+ if (backgroundBlocks.length) {
2103
+ doc.save();
2104
+ doc.opacity(backgroundOpacity);
2105
+ renderBlockArray(backgroundBlocks, localStartY, {
2106
+ ...outerEnv,
2107
+ allowPageBreak: false,
2108
+ isBackgroundLayer: true
2109
+ });
2110
+ doc.restore();
2111
+ }
2112
+ if (blocks.length) {
2113
+ renderBlockArray(blocks, localStartY + padding.top, innerEnv);
2114
+ }
2115
+ ctx.inFooter = false;
2116
+ doc.restore();
2117
+ }
2118
+
2119
+ // src/renderer-engine/utils/header.ts
2120
+ function drawHeader(doc, def, headerBandHeight, header, renderBlockArray) {
2121
+ if (!header) return;
2122
+ if (header.visible === false) return;
2123
+ if (!headerBandHeight) return;
2124
+ const blocks = header.blocks ?? [];
2125
+ const backgroundBlocks = header.backgroundBlocks ?? [];
2126
+ if (!blocks.length && !backgroundBlocks.length && !header.backgroundColor && !header.backgroundImage) {
2127
+ return;
2128
+ }
2129
+ const bandTop = 0;
2130
+ const bandHeight = def.margins.top;
2131
+ const headerMarginLeft = header.marginLeft ?? 0;
2132
+ const headerMarginRight = header.marginRight ?? 0;
2133
+ const outerX = headerMarginLeft;
2134
+ const outerWidth = doc.page.width - headerMarginLeft - headerMarginRight;
2135
+ const padding = resolveHeaderPadding(header);
2136
+ const innerX = outerX + padding.left;
2137
+ const innerWidth = Math.max(outerWidth - padding.left - padding.right, 1);
2138
+ const outerEnv = {
2139
+ marginLeft: outerX,
2140
+ innerWidth: outerWidth,
2141
+ allowPageBreak: false
2142
+ };
2143
+ const innerEnv = {
2144
+ marginLeft: innerX,
2145
+ innerWidth,
2146
+ allowPageBreak: false
2147
+ };
2148
+ const backgroundOpacity = header.backgroundOpacity ?? 1;
2149
+ if (header.backgroundColor) {
2150
+ doc.save();
2151
+ doc.fillOpacity(backgroundOpacity).rect(0, bandTop, doc.page.width, bandHeight).fill(header.backgroundColor);
2152
+ doc.restore();
2153
+ }
2154
+ if (header.backgroundImage) {
2155
+ try {
2156
+ doc.save();
2157
+ doc.opacity(backgroundOpacity);
2158
+ doc.image(header.backgroundImage, 0, bandTop, {
2159
+ width: doc.page.width,
2160
+ height: bandHeight
2161
+ });
2162
+ doc.restore();
2163
+ } catch (e) {
2164
+ console.warn("Failed to load header background image:", e);
2165
+ }
2166
+ }
2167
+ doc.save();
2168
+ doc.rect(outerX, bandTop, outerWidth, bandHeight).clip();
2169
+ const startY = bandTop + (header.marginTop ?? 0);
2170
+ if (backgroundBlocks.length) {
2171
+ doc.save();
2172
+ doc.opacity(backgroundOpacity);
2173
+ renderBlockArray(backgroundBlocks, startY, {
2174
+ ...outerEnv,
2175
+ allowPageBreak: false,
2176
+ isBackgroundLayer: true
2177
+ });
2178
+ doc.restore();
2179
+ }
2180
+ if (blocks.length) {
2181
+ renderBlockArray(blocks, startY + padding.top, innerEnv);
2182
+ }
2183
+ doc.restore();
2184
+ }
2185
+
2186
+ // src/renderer-engine/utils/image-loader.ts
2187
+ var import_axios = __toESM(require("axios"));
2188
+ async function normalizeImageSrc(src, fallback) {
2189
+ if (!src) return fallback ?? src;
2190
+ if (Buffer.isBuffer(src)) return src;
2191
+ if (src.startsWith("data:")) {
2192
+ const commaIdx = src.indexOf(",");
2193
+ if (commaIdx !== -1) {
2194
+ return Buffer.from(src.slice(commaIdx + 1), "base64");
2195
+ }
2196
+ }
2197
+ if (src.startsWith("http://") || src.startsWith("https://")) {
2198
+ try {
2199
+ const res = await import_axios.default.get(src, {
2200
+ responseType: "arraybuffer"
2201
+ });
2202
+ return Buffer.from(res.data);
2203
+ } catch (e) {
2204
+ if (fallback !== void 0) {
2205
+ console.warn(`Failed to fetch remote image "${src}", using default image.`);
2206
+ return fallback;
1448
2207
  }
1449
- heights.push(colH);
2208
+ throw toPdfEngineError(e, {
2209
+ code: "PDF_ERROR_IMAGE_FETCH_FAILED" /* PDF_ERROR_IMAGE_FETCH_FAILED */,
2210
+ message: "Failed to fetch remote image for PDF.",
2211
+ statusCode: 422,
2212
+ details: { url: src },
2213
+ retryable: false
2214
+ });
1450
2215
  }
1451
- const maxH = Math.max(...heights, 0);
1452
- return mt + maxH + mb;
1453
- };
1454
- const measureKeyValueGrid = (b, env) => {
1455
- const mt = b.marginTop ?? 0;
1456
- const mb = b.marginBottom ?? 0;
1457
- const rowGap = b.rowGap ?? 4;
1458
- const orientation = b.orientation ?? "horizontal";
1459
- const cols = b.columns ?? [];
1460
- const colCount = cols.length;
1461
- if (!colCount) return mt + mb;
1462
- const blockLeft = b.marginLeft ?? 0;
1463
- const blockRight = b.marginRight ?? 0;
1464
- const totalWidth = Math.max(env.innerWidth - blockLeft - blockRight, 1);
1465
- let colWidths;
1466
- if (b.columnWidths && b.columnWidths.length === colCount) {
1467
- const safe = b.columnWidths.map((w) => w === void 0 ? "*" : w);
1468
- colWidths = computeColumnPixelWidths2(safe, totalWidth);
1469
- } else {
1470
- colWidths = Array(colCount).fill(totalWidth / colCount);
2216
+ }
2217
+ return src;
2218
+ }
2219
+ async function materializeImagesInBlocks(blocks, fallback) {
2220
+ const out = [];
2221
+ for (const block of blocks) {
2222
+ const blockAny = { ...block };
2223
+ if (blockAny.backgroundImage) {
2224
+ blockAny.backgroundImage = await normalizeImageSrc(blockAny.backgroundImage, fallback);
1471
2225
  }
1472
- const separatorText = b.separator;
1473
- const sepBoxWidth = separatorText ? 10 : 0;
1474
- const baseKeyWidthRatio = 0.35;
1475
- const measureKVText = (tb, width) => {
1476
- const r = resolveTextBlock(styles, tb);
1477
- const fontName = getFontNameForText(r);
1478
- doc.font(fontName);
1479
- doc.fontSize(r.fontSize ?? 10);
1480
- return doc.heightOfString(r.text ?? "", { width });
1481
- };
1482
- let totalHeight = mt;
1483
- if (orientation === "vertical") {
1484
- const keyValueGap = b.verticalKeyValueGap ?? 2;
1485
- let maxColHeight = 0;
1486
- for (let colIndex = 0; colIndex < colCount; colIndex++) {
1487
- const col = cols[colIndex] ?? [];
1488
- const colWidth = colWidths[colIndex];
1489
- let colHeight = 0;
1490
- for (const item of col) {
1491
- const keyH = measureKVText({ type: "text", text: item.key ?? "" }, colWidth);
1492
- const valH = measureKVText({ type: "text", text: item.value ?? "" }, colWidth);
1493
- colHeight += keyH + keyValueGap + valH + rowGap;
1494
- }
1495
- if (colHeight > maxColHeight) maxColHeight = colHeight;
1496
- }
1497
- totalHeight += maxColHeight;
1498
- } else {
1499
- const maxRows = Math.max(...cols.map((c) => c ? c.length : 0), 0);
1500
- for (let rowIndex = 0; rowIndex < maxRows; rowIndex++) {
1501
- let rowHeight = 0;
1502
- for (let colIndex = 0; colIndex < colCount; colIndex++) {
1503
- const item = cols[colIndex]?.[rowIndex];
1504
- if (!item) continue;
1505
- const colWidth = colWidths[colIndex];
1506
- const keyWidthPx = b.keyWidth === "*" ? Math.max(colWidth * baseKeyWidthRatio, 20) : b.keyWidth ?? 80;
1507
- const keyH = measureKVText({ type: "text", text: item.key ?? "" }, keyWidthPx);
1508
- const valueXInsideCol = keyWidthPx + (separatorText ? sepBoxWidth + 4 : 4);
1509
- const valueWidth = Math.max(colWidth - valueXInsideCol, 1);
1510
- const valH = measureKVText({ type: "text", text: item.value ?? "" }, valueWidth);
1511
- rowHeight = Math.max(rowHeight, Math.max(keyH, valH));
1512
- }
1513
- if (rowHeight > 0) totalHeight += rowHeight + rowGap;
1514
- }
2226
+ if (blockAny.backgroundBlocks?.length) {
2227
+ blockAny.backgroundBlocks = await materializeImagesInBlocks(blockAny.backgroundBlocks, fallback);
1515
2228
  }
1516
- totalHeight += mb;
1517
- return totalHeight;
1518
- };
1519
- const measure = (block, env) => {
1520
- if (!block || block.visible === false) return 0;
1521
- switch (block.type) {
1522
- case "text":
1523
- return measureText(block, env);
1524
- case "image":
1525
- return measureImage(block);
1526
- case "qr":
1527
- return measureQr(block);
1528
- case "barcode":
1529
- return measureBarcode(block);
1530
- case "line":
1531
- return measureLine(block);
1532
- case "table":
1533
- return measureTable(block, env);
1534
- case "columns":
1535
- return measureColumns(block, env);
1536
- case "keyValueGrid":
1537
- return measureKeyValueGrid(block, env);
1538
- case "signature":
1539
- return block.height ?? 0;
1540
- case "pageBreak":
1541
- return 0;
1542
- default:
1543
- return 0;
2229
+ if (block.type === "image") {
2230
+ const img = { ...blockAny };
2231
+ img.src = await normalizeImageSrc(img.src, fallback);
2232
+ out.push(img);
2233
+ } else if (block.type === "columns") {
2234
+ out.push({
2235
+ ...blockAny,
2236
+ columns: await Promise.all(
2237
+ block.columns.map((col) => materializeImagesInBlocks(col, fallback))
2238
+ )
2239
+ });
2240
+ } else if (block.type === "signature" && block.blocks) {
2241
+ out.push({
2242
+ ...blockAny,
2243
+ blocks: await materializeImagesInBlocks(block.blocks, fallback)
2244
+ });
2245
+ } else if (block.type === "table") {
2246
+ const tb = blockAny;
2247
+ const newBody = await Promise.all(
2248
+ tb.body.map(
2249
+ async (entry) => {
2250
+ const materializeCell = async (cell) => {
2251
+ if (!cell.blocks?.length) return cell;
2252
+ return {
2253
+ ...cell,
2254
+ blocks: await materializeImagesInBlocks(cell.blocks, fallback)
2255
+ };
2256
+ };
2257
+ if (Array.isArray(entry)) {
2258
+ return await Promise.all(entry.map(materializeCell));
2259
+ }
2260
+ if (entry && typeof entry === "object" && "content" in entry && Array.isArray(entry.content)) {
2261
+ return {
2262
+ ...entry,
2263
+ content: await Promise.all(entry.content.map(materializeCell))
2264
+ };
2265
+ }
2266
+ return entry;
2267
+ }
2268
+ )
2269
+ );
2270
+ out.push({ ...tb, body: newBody });
2271
+ } else {
2272
+ out.push(blockAny);
1544
2273
  }
1545
- };
1546
- return (block, env) => measure(block, env);
2274
+ }
2275
+ return out;
2276
+ }
2277
+
2278
+ // src/renderer-engine/utils/layout.ts
2279
+ function computeColumnPixelWidths(widths, totalWidth) {
2280
+ let fixedTotal = 0;
2281
+ let starCount = 0;
2282
+ widths.forEach((w) => {
2283
+ if (w === "*") starCount++;
2284
+ else fixedTotal += w;
2285
+ });
2286
+ const remaining = Math.max(totalWidth - fixedTotal, 0);
2287
+ const starWidth = starCount > 0 ? remaining / starCount : 0;
2288
+ return widths.map((w) => w === "*" ? starWidth : w);
1547
2289
  }
1548
2290
 
1549
2291
  // src/renderer-engine/utils/page-background.ts
@@ -1568,12 +2310,10 @@ function drawPageBackground(doc, pageBackground) {
1568
2310
  doc.opacity(1);
1569
2311
  }
1570
2312
 
1571
- // src/renderer-engine/utils/page-limit.ts
1572
- function createBottomLimitForContent(doc, ctx) {
1573
- return () => {
1574
- const pageBottomForContent = doc.page.height - doc.page.margins.bottom;
1575
- return ctx.signatureTopY ?? pageBottomForContent;
1576
- };
2313
+ // src/renderer-engine/utils/page-flow.ts
2314
+ function getBottomLimitForContent(doc, ctx) {
2315
+ const pageBottomForContent = doc.page.height - doc.page.margins.bottom;
2316
+ return ctx.signatureTopY ?? pageBottomForContent;
1577
2317
  }
1578
2318
 
1579
2319
  // src/renderer-engine/utils/qr-bar-code.ts
@@ -1596,7 +2336,10 @@ function generateQrBuffer(value, size, version, errorCorrectionLevel) {
1596
2336
  code: "PDF_ERROR_QR_GENERATION_FAILED" /* PDF_ERROR_QR_GENERATION_FAILED */,
1597
2337
  message: "Failed to generate QR code.",
1598
2338
  statusCode: 500,
1599
- details: { valuePreview: String(value).slice(0, 60), size },
2339
+ details: {
2340
+ valuePreview: String(value).slice(0, 60),
2341
+ size
2342
+ },
1600
2343
  retryable: false
1601
2344
  })
1602
2345
  );
@@ -1623,97 +2366,109 @@ function mapBarcodeTypeToBcid(bcType) {
1623
2366
  function generateBarcodeBuffer(value, options = {}) {
1624
2367
  const { bcType, scale = 3, barHeight = 10, includetext = false, textalign = "center" } = options;
1625
2368
  const bcid = mapBarcodeTypeToBcid(bcType);
2369
+ if (bcType === "EAN13" && !/^\d{12,13}$/.test(value)) {
2370
+ throw toPdfEngineError(new Error("Invalid EAN13 value"), {
2371
+ code: "PDF_ERROR_BARCODE_EAN13_INVALID_LENGTH" /* PDF_ERROR_BARCODE_EAN13_INVALID_LENGTH */,
2372
+ message: "EAN13 barcode value must be 12 or 13 digits.",
2373
+ statusCode: 422,
2374
+ details: { value },
2375
+ retryable: false
2376
+ });
2377
+ }
1626
2378
  return new Promise((resolve, reject) => {
1627
- let textValue = value;
1628
- if (bcType === "EAN13") {
1629
- const digitsOnly = textValue.replace(/\D/g, "");
1630
- if (digitsOnly.length === 13) {
1631
- textValue = digitsOnly.slice(0, 12);
1632
- } else if (digitsOnly.length === 12) {
1633
- textValue = digitsOnly;
1634
- } else {
1635
- return reject(
1636
- new PdfEngineError({
1637
- code: "PDF_ERROR_BARCODE_EAN13_INVALID_LENGTH" /* PDF_ERROR_BARCODE_EAN13_INVALID_LENGTH */,
1638
- message: `EAN13 barcode value must have 12 or 13 digits, got "${value}"`,
1639
- statusCode: 422,
1640
- details: { value },
1641
- retryable: false
1642
- })
1643
- );
1644
- }
1645
- }
1646
- const bwipOptions = {
1647
- bcid,
1648
- text: textValue,
1649
- scale,
1650
- height: barHeight,
1651
- includetext
1652
- };
1653
- bwipOptions.textxalign = textalign;
1654
- import_bwip_js.default.toBuffer(bwipOptions, (err, png) => {
1655
- if (err) {
1656
- return reject(
1657
- toPdfEngineError(err, {
1658
- code: "PDF_ERROR_BARCODE_GENERATION_FAILED" /* PDF_ERROR_BARCODE_GENERATION_FAILED */,
1659
- message: "Failed to generate barcode.",
1660
- statusCode: 500,
1661
- details: { bcType, valuePreview: String(value).slice(0, 60) },
1662
- retryable: false
1663
- })
1664
- );
2379
+ import_bwip_js.default.toBuffer(
2380
+ {
2381
+ bcid,
2382
+ text: value,
2383
+ scale,
2384
+ height: barHeight,
2385
+ includetext,
2386
+ textxalign: textalign
2387
+ },
2388
+ (err, png) => {
2389
+ if (err) {
2390
+ return reject(
2391
+ toPdfEngineError(err, {
2392
+ code: "PDF_ERROR_BARCODE_GENERATION_FAILED" /* PDF_ERROR_BARCODE_GENERATION_FAILED */,
2393
+ message: "Failed to generate barcode.",
2394
+ statusCode: 500,
2395
+ details: {
2396
+ valuePreview: String(value).slice(0, 60),
2397
+ bcType
2398
+ },
2399
+ retryable: false
2400
+ })
2401
+ );
2402
+ }
2403
+ resolve(png);
1665
2404
  }
1666
- resolve(png);
1667
- });
2405
+ );
1668
2406
  });
1669
2407
  }
1670
2408
  async function materializeQrAndBarcodesInBlocks(blocks) {
1671
2409
  const out = [];
1672
2410
  for (const block of blocks) {
1673
- if (block.type === "columns") {
1674
- const colBlock = block;
1675
- const newCols = [];
1676
- for (const col of colBlock.columns) {
1677
- newCols.push(await materializeQrAndBarcodesInBlocks(col));
1678
- }
1679
- out.push({
1680
- ...colBlock,
1681
- columns: newCols
1682
- });
1683
- } else if (block.type === "signature") {
1684
- const sig = block;
1685
- if (sig.blocks && sig.blocks.length) {
1686
- const newInner = await materializeQrAndBarcodesInBlocks(sig.blocks);
1687
- out.push({
1688
- ...sig,
1689
- blocks: newInner
1690
- });
1691
- } else {
1692
- out.push(block);
1693
- }
1694
- } else if (block.type === "qr") {
1695
- const qb = { ...block };
2411
+ const blockAny = { ...block };
2412
+ if (blockAny.backgroundBlocks?.length) {
2413
+ blockAny.backgroundBlocks = await materializeQrAndBarcodesInBlocks(blockAny.backgroundBlocks);
2414
+ }
2415
+ if (block.type === "qr") {
2416
+ const qb = blockAny;
1696
2417
  if (!qb.src && qb.value) {
1697
- const size = qb.size ?? 80;
1698
- const buf = await generateQrBuffer(qb.value, size, qb.qrVersion, qb.errorCorrectionLevel);
1699
- qb.src = buf;
2418
+ qb.size = qb.size ?? 80;
2419
+ qb.src = await generateQrBuffer(qb.value, qb.size, qb.qrVersion, qb.errorCorrectionLevel);
1700
2420
  }
1701
2421
  out.push(qb);
1702
2422
  } else if (block.type === "barcode") {
1703
- const bb = { ...block };
2423
+ const bb = blockAny;
1704
2424
  if (!bb.src && bb.value) {
1705
- const buf = await generateBarcodeBuffer(bb.value, {
2425
+ bb.src = await generateBarcodeBuffer(bb.value, {
1706
2426
  bcType: bb.bcType,
1707
2427
  scale: bb.scale,
1708
2428
  barHeight: bb.barHeight,
1709
2429
  includetext: bb.includetext,
1710
2430
  textalign: bb.textalign
1711
2431
  });
1712
- bb.src = buf;
1713
2432
  }
1714
2433
  out.push(bb);
2434
+ } else if (block.type === "columns") {
2435
+ out.push({
2436
+ ...blockAny,
2437
+ columns: await Promise.all(block.columns.map((col) => materializeQrAndBarcodesInBlocks(col)))
2438
+ });
2439
+ } else if (block.type === "signature" && block.blocks) {
2440
+ out.push({
2441
+ ...blockAny,
2442
+ blocks: await materializeQrAndBarcodesInBlocks(block.blocks)
2443
+ });
2444
+ } else if (block.type === "table") {
2445
+ const tb = blockAny;
2446
+ const newBody = await Promise.all(
2447
+ tb.body.map(
2448
+ async (entry) => {
2449
+ const materializeCell = async (cell) => {
2450
+ if (!cell.blocks?.length) return cell;
2451
+ return {
2452
+ ...cell,
2453
+ blocks: await materializeQrAndBarcodesInBlocks(cell.blocks)
2454
+ };
2455
+ };
2456
+ if (Array.isArray(entry)) {
2457
+ return await Promise.all(entry.map(materializeCell));
2458
+ }
2459
+ if (entry && typeof entry === "object" && "content" in entry && Array.isArray(entry.content)) {
2460
+ return {
2461
+ ...entry,
2462
+ content: await Promise.all(entry.content.map(materializeCell))
2463
+ };
2464
+ }
2465
+ return entry;
2466
+ }
2467
+ )
2468
+ );
2469
+ out.push({ ...tb, body: newBody });
1715
2470
  } else {
1716
- out.push(block);
2471
+ out.push(blockAny);
1717
2472
  }
1718
2473
  }
1719
2474
  return out;
@@ -1967,96 +2722,143 @@ function drawWatermarkForPage(doc, watermark, pageNumber, isLast) {
1967
2722
  }
1968
2723
 
1969
2724
  // src/renderer-engine/index.ts
1970
- async function renderCustomPdf(def, outputPath) {
1971
- if (def.header) {
2725
+ var BUILT_IN_DEFAULT_IMAGE = Buffer.from(images.default.slice(images.default.indexOf(",") + 1), "base64");
2726
+ async function materializeFooterAssets(footer, fallbackImage) {
2727
+ if (!footer) return footer;
2728
+ if (typeof footer === "function") {
2729
+ return footer;
2730
+ }
2731
+ if (Array.isArray(footer)) {
2732
+ let blocks = await materializeQrAndBarcodesInBlocks(footer);
2733
+ blocks = await materializeImagesInBlocks(blocks, fallbackImage);
2734
+ return blocks;
2735
+ }
2736
+ if (footer.type) {
2737
+ let blocks = await materializeQrAndBarcodesInBlocks([footer]);
2738
+ blocks = await materializeImagesInBlocks(blocks, fallbackImage);
2739
+ return blocks[0];
2740
+ }
2741
+ const footerDef = footer;
2742
+ if (footerDef.backgroundImage) {
2743
+ footerDef.backgroundImage = await normalizeImageSrc(footerDef.backgroundImage, fallbackImage);
2744
+ }
2745
+ if (footerDef.blocks?.length) {
2746
+ footerDef.blocks = await materializeQrAndBarcodesInBlocks(footerDef.blocks);
2747
+ footerDef.blocks = await materializeImagesInBlocks(footerDef.blocks, fallbackImage);
2748
+ }
2749
+ if (footerDef.backgroundBlocks?.length) {
2750
+ footerDef.backgroundBlocks = await materializeQrAndBarcodesInBlocks(footerDef.backgroundBlocks);
2751
+ footerDef.backgroundBlocks = await materializeImagesInBlocks(footerDef.backgroundBlocks, fallbackImage);
2752
+ }
2753
+ return footerDef;
2754
+ }
2755
+ async function materializeDocAssets(def, fallbackImage) {
2756
+ if (def.header?.blocks?.length) {
1972
2757
  def.header.blocks = await materializeQrAndBarcodesInBlocks(def.header.blocks);
1973
- def.header.blocks = await materializeImagesInBlocks(def.header.blocks);
2758
+ def.header.blocks = await materializeImagesInBlocks(def.header.blocks, fallbackImage);
2759
+ }
2760
+ if (def.header?.backgroundImage) {
2761
+ def.header.backgroundImage = await normalizeImageSrc(def.header.backgroundImage, fallbackImage);
2762
+ }
2763
+ if (def.header?.backgroundBlocks?.length) {
2764
+ def.header.backgroundBlocks = await materializeQrAndBarcodesInBlocks(def.header.backgroundBlocks);
2765
+ def.header.backgroundBlocks = await materializeImagesInBlocks(def.header.backgroundBlocks, fallbackImage);
1974
2766
  }
1975
2767
  def.content = await materializeQrAndBarcodesInBlocks(def.content);
1976
- def.content = await materializeImagesInBlocks(def.content);
2768
+ def.content = await materializeImagesInBlocks(def.content, fallbackImage);
1977
2769
  if (def.pageBackground?.src) {
1978
- def.pageBackground.src = await normalizeImageSrc(def.pageBackground.src);
2770
+ def.pageBackground.src = await normalizeImageSrc(def.pageBackground.src, fallbackImage);
1979
2771
  }
1980
- if (def.header?.backgroundImage) {
1981
- def.header.backgroundImage = await normalizeImageSrc(def.header.backgroundImage);
2772
+ def.footer = await materializeFooterAssets(def.footer, fallbackImage);
2773
+ }
2774
+ function runRender(doc, def, fallbackImage) {
2775
+ const headerBandHeight = def.margins.top ?? 0;
2776
+ const footerBandHeight = def.margins.bottom ?? 0;
2777
+ if (def.fonts && def.fonts.length) {
2778
+ for (const font of def.fonts) {
2779
+ try {
2780
+ doc.registerFont(font.name, font.src);
2781
+ } catch (e) {
2782
+ console.warn("Failed to register font:", font.name, e);
2783
+ }
2784
+ }
1982
2785
  }
1983
- if (def.footer && typeof def.footer !== "function") {
1984
- const footer = def.footer;
1985
- if (footer.backgroundImage) {
1986
- footer.backgroundImage = await normalizeImageSrc(footer.backgroundImage);
2786
+ const ctx = createInitialContext(doc);
2787
+ const styles = def.styles ?? {};
2788
+ const finishPage2 = (addNewPage) => finishPage({
2789
+ addNewPage,
2790
+ doc,
2791
+ def,
2792
+ ctx,
2793
+ footerBandHeight,
2794
+ renderBlockArray,
2795
+ startNewPageLayout
2796
+ });
2797
+ const processSignatureBlock = createProcessSignatureBlock({
2798
+ doc,
2799
+ ctx,
2800
+ styles,
2801
+ finishPage: finishPage2,
2802
+ contentEnvFn: contentEnv
2803
+ });
2804
+ const { renderBlock, renderBlockArray } = createBlockRenderer({
2805
+ doc,
2806
+ ctx,
2807
+ styles,
2808
+ computeColumnPixelWidths,
2809
+ finishPage: finishPage2,
2810
+ processSignatureBlock,
2811
+ defaultImage: fallbackImage
2812
+ });
2813
+ const startNewPageLayout = createStartNewPageLayout({
2814
+ doc,
2815
+ def,
2816
+ ctx,
2817
+ headerBandHeight,
2818
+ renderBlockArray
2819
+ });
2820
+ doc.on("pageAdded", () => {
2821
+ if (ctx.inManualPageAdd) return;
2822
+ ctx.pageNumber += 1;
2823
+ drawPageBackground(doc, def.pageBackground);
2824
+ drawHeader(doc, def, headerBandHeight, def.header ?? void 0, renderBlockArray);
2825
+ const mode = def.watermark?.mode;
2826
+ if (def.watermark && !watermarkUsesLast(mode)) {
2827
+ drawWatermarkForPage(doc, def.watermark, ctx.pageNumber, false);
2828
+ }
2829
+ ctx.currentY = doc.page.margins.top;
2830
+ });
2831
+ startNewPageLayout();
2832
+ for (const block of def.content) {
2833
+ if (block.type === "signature") {
2834
+ processSignatureBlock(block);
2835
+ continue;
2836
+ }
2837
+ if (ctx.afterSignature) {
2838
+ finishPage2(true);
2839
+ ctx.afterSignature = false;
1987
2840
  }
2841
+ renderBlock(block, null, contentEnv(doc));
1988
2842
  }
2843
+ finishPage2(false);
2844
+ doc.end();
2845
+ }
2846
+ async function renderCustomPdf(def, outputPath) {
2847
+ const fallbackImage = def.defaultImage ?? BUILT_IN_DEFAULT_IMAGE;
2848
+ await materializeDocAssets(def, fallbackImage);
1989
2849
  return new Promise((resolve, reject) => {
1990
- const headerBandHeight = def.margins.top ?? 0;
1991
- const footerBandHeight = def.margins.bottom ?? 0;
1992
2850
  const doc = new import_pdfkit.default({
1993
2851
  size: def.pageSize || "A4",
1994
2852
  layout: def.pageOrientation === "landscape" ? "landscape" : "portrait",
1995
2853
  margins: {
1996
- top: headerBandHeight,
1997
- bottom: footerBandHeight,
2854
+ top: def.margins.top ?? 0,
2855
+ bottom: def.margins.bottom ?? 0,
1998
2856
  left: def.margins.left,
1999
2857
  right: def.margins.right
2000
2858
  }
2001
2859
  });
2002
- if (def.fonts && def.fonts.length) {
2003
- for (const f of def.fonts) {
2004
- try {
2005
- doc.registerFont(f.name, f.src);
2006
- } catch (e) {
2007
- console.warn("Failed to register font:", f.name, e);
2008
- }
2009
- }
2010
- }
2011
2860
  const stream = import_fs.default.createWriteStream(outputPath);
2012
2861
  doc.pipe(stream);
2013
- const ctx = createInitialContext(doc);
2014
- const styles = def.styles ?? {};
2015
- const finishPage2 = (addNewPage) => finishPage({
2016
- addNewPage,
2017
- doc,
2018
- def,
2019
- ctx,
2020
- footerBandHeight,
2021
- renderBlockArray,
2022
- startNewPageLayout
2023
- });
2024
- const processSignatureBlock = createProcessSignatureBlock({
2025
- doc,
2026
- ctx,
2027
- styles,
2028
- finishPage: finishPage2,
2029
- contentEnvFn: contentEnv
2030
- });
2031
- const { renderBlock, renderBlockArray } = createBlockRenderer({
2032
- doc,
2033
- ctx,
2034
- styles,
2035
- computeColumnPixelWidths,
2036
- finishPage: finishPage2,
2037
- processSignatureBlock
2038
- });
2039
- const startNewPageLayout = createStartNewPageLayout({
2040
- doc,
2041
- def,
2042
- ctx,
2043
- headerBandHeight,
2044
- renderBlockArray
2045
- });
2046
- startNewPageLayout();
2047
- for (const block of def.content) {
2048
- if (block.type === "signature") {
2049
- processSignatureBlock(block);
2050
- continue;
2051
- }
2052
- if (ctx.afterSignature) {
2053
- finishPage2(true);
2054
- ctx.afterSignature = false;
2055
- }
2056
- renderBlock(block, null, contentEnv(doc));
2057
- }
2058
- finishPage2(false);
2059
- doc.end();
2060
2862
  stream.on("finish", () => resolve());
2061
2863
  stream.on(
2062
2864
  "error",
@@ -2070,113 +2872,38 @@ async function renderCustomPdf(def, outputPath) {
2070
2872
  })
2071
2873
  )
2072
2874
  );
2875
+ runRender(doc, def, fallbackImage);
2073
2876
  });
2074
2877
  }
2075
2878
  async function renderCustomPdfToBuffer(def) {
2076
- if (def.header) {
2077
- def.header.blocks = await materializeQrAndBarcodesInBlocks(def.header.blocks);
2078
- def.header.blocks = await materializeImagesInBlocks(def.header.blocks);
2079
- }
2080
- def.content = await materializeQrAndBarcodesInBlocks(def.content);
2081
- def.content = await materializeImagesInBlocks(def.content);
2082
- if (def.pageBackground?.src) {
2083
- def.pageBackground.src = await normalizeImageSrc(def.pageBackground.src);
2084
- }
2085
- if (def.header?.backgroundImage) {
2086
- def.header.backgroundImage = await normalizeImageSrc(def.header.backgroundImage);
2087
- }
2088
- if (def.footer && typeof def.footer !== "function") {
2089
- const footer = def.footer;
2090
- if (footer.backgroundImage) {
2091
- footer.backgroundImage = await normalizeImageSrc(footer.backgroundImage);
2092
- }
2093
- }
2879
+ const fallbackImage = def.defaultImage ?? BUILT_IN_DEFAULT_IMAGE;
2880
+ await materializeDocAssets(def, fallbackImage);
2094
2881
  return new Promise((resolve, reject) => {
2095
- const headerBandHeight = def.margins.top ?? 0;
2096
- const footerBandHeight = def.margins.bottom ?? 0;
2097
2882
  const doc = new import_pdfkit.default({
2098
2883
  size: def.pageSize || "A4",
2099
2884
  layout: def.pageOrientation === "landscape" ? "landscape" : "portrait",
2100
2885
  margins: {
2101
- top: headerBandHeight,
2102
- bottom: footerBandHeight,
2886
+ top: def.margins.top ?? 0,
2887
+ bottom: def.margins.bottom ?? 0,
2103
2888
  left: def.margins.left,
2104
2889
  right: def.margins.right
2105
2890
  }
2106
2891
  });
2107
2892
  const chunks = [];
2108
- doc.on("data", (chunk) => {
2109
- chunks.push(chunk);
2110
- });
2111
- doc.on("end", () => {
2112
- resolve(Buffer.concat(chunks));
2113
- });
2114
- doc.on("error", (err) => {
2115
- reject(
2893
+ doc.on("data", (chunk) => chunks.push(chunk));
2894
+ doc.on("end", () => resolve(Buffer.concat(chunks)));
2895
+ doc.on(
2896
+ "error",
2897
+ (err) => reject(
2116
2898
  toPdfEngineError(err, {
2117
2899
  code: "PDF_ERROR_PDFKIT_ERROR" /* PDF_ERROR_PDFKIT_ERROR */,
2118
2900
  message: "PDFKit emitted an error while rendering.",
2119
2901
  statusCode: 500,
2120
2902
  retryable: true
2121
2903
  })
2122
- );
2123
- });
2124
- if (def.fonts && def.fonts.length) {
2125
- for (const f of def.fonts) {
2126
- try {
2127
- doc.registerFont(f.name, f.src);
2128
- } catch (e) {
2129
- console.warn("Failed to register font:", f.name, e);
2130
- }
2131
- }
2132
- }
2133
- const ctx = createInitialContext(doc);
2134
- const styles = def.styles ?? {};
2135
- const finishPage2 = (addNewPage) => finishPage({
2136
- addNewPage,
2137
- doc,
2138
- def,
2139
- ctx,
2140
- footerBandHeight,
2141
- renderBlockArray,
2142
- startNewPageLayout
2143
- });
2144
- const processSignatureBlock = createProcessSignatureBlock({
2145
- doc,
2146
- ctx,
2147
- styles,
2148
- finishPage: finishPage2,
2149
- contentEnvFn: contentEnv
2150
- });
2151
- const { renderBlock, renderBlockArray } = createBlockRenderer({
2152
- doc,
2153
- ctx,
2154
- styles,
2155
- computeColumnPixelWidths,
2156
- finishPage: finishPage2,
2157
- processSignatureBlock
2158
- });
2159
- const startNewPageLayout = createStartNewPageLayout({
2160
- doc,
2161
- def,
2162
- ctx,
2163
- headerBandHeight,
2164
- renderBlockArray
2165
- });
2166
- startNewPageLayout();
2167
- for (const block of def.content) {
2168
- if (block.type === "signature") {
2169
- processSignatureBlock(block);
2170
- continue;
2171
- }
2172
- if (ctx.afterSignature) {
2173
- finishPage2(true);
2174
- ctx.afterSignature = false;
2175
- }
2176
- renderBlock(block, null, contentEnv(doc));
2177
- }
2178
- finishPage2(false);
2179
- doc.end();
2904
+ )
2905
+ );
2906
+ runRender(doc, def, fallbackImage);
2180
2907
  });
2181
2908
  }
2182
2909
  // Annotate the CommonJS export names for ESM import in node:
@@ -2185,8 +2912,42 @@ async function renderCustomPdfToBuffer(def) {
2185
2912
  PdfEngineError,
2186
2913
  PdfEngineErrorCode,
2187
2914
  QR_ERROR_LEVEL,
2915
+ computeColumnPixelWidths,
2916
+ contentEnv,
2917
+ createBlockRenderer,
2918
+ createBottomLimitForContent,
2919
+ createEnsureSpaceFor,
2920
+ createInitialContext,
2921
+ createMeasureBlockHeight,
2922
+ createProcessSignatureBlock,
2923
+ createStartNewPageLayout,
2924
+ drawFooter,
2925
+ drawHeader,
2926
+ drawPageBackground,
2927
+ drawSignatureBlock,
2928
+ drawStyledText,
2929
+ drawWatermarkForPage,
2930
+ finishPage,
2931
+ generateBarcodeBuffer,
2932
+ generateQrBuffer,
2933
+ getBottomLimitForContent,
2934
+ getFontNameForText,
2935
+ hasPadding,
2936
+ images,
2188
2937
  isPdfEngineError,
2938
+ mapBarcodeTypeToBcid,
2939
+ materializeImagesInBlocks,
2940
+ materializeQrAndBarcodesInBlocks,
2941
+ mergeStyleDefs,
2942
+ normalizeImageSrc,
2189
2943
  renderCustomPdf,
2190
2944
  renderCustomPdfToBuffer,
2191
- toPdfEngineError
2945
+ resolveBlockPadding,
2946
+ resolveFooterPadding,
2947
+ resolveHeaderPadding,
2948
+ resolveSpacing,
2949
+ resolveTableCell,
2950
+ resolveTextBlock,
2951
+ toPdfEngineError,
2952
+ watermarkUsesLast
2192
2953
  });