@flowaccount/pdfmake 1.0.6-staging.2 → 1.0.6-staging.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowaccount/pdfmake",
3
- "version": "1.0.6-staging.2",
3
+ "version": "1.0.6-staging.3",
4
4
  "description": "Client/server side PDF printing in pure JavaScript",
5
5
  "main": "src/printer.js",
6
6
  "browser": "build/pdfmake.js",
@@ -595,8 +595,9 @@ LayoutBuilder.prototype.processNode = function (node) {
595
595
  }
596
596
 
597
597
  // Reposition only items that belong to footer stack content
598
- // (filter by Y position to exclude outer table border lines)
599
- for (var i = preRenderState.itemCount; i < currentPage.items.length; i++) {
598
+ // Iterate ALL items (backgrounds are inserted at lower indices, not appended)
599
+ // Filter by Y position to exclude non-footer items
600
+ for (var i = 0; i < currentPage.items.length; i++) {
600
601
  var item = currentPage.items[i];
601
602
 
602
603
  // Skip the guide lines we just added (they're already positioned correctly)
@@ -632,127 +633,121 @@ LayoutBuilder.prototype.processNode = function (node) {
632
633
  ctx.moveDown(gapHeight);
633
634
  }
634
635
  } else {
635
- // MULTI-PAGE: keep remark at top, move footer to bottom, draw guide lines in gap
636
- var currentPage = ctx.getCurrentPage();
637
- var gapHeight = ctx.availableHeight;
636
+ // MULTI-PAGE: Process ALL pages from startPage+1 to current page
637
+ // Only move FOOTER items to bottom, keep remark at top
638
+ var pages = ctx.pages;
639
+ var pageMargins = ctx.pageMargins;
638
640
 
639
641
  // Helper function to recursively find node with _isFooterTable
640
642
  function findFooterTableNode(n) {
641
643
  if (!n) return null;
642
644
  if (n._isFooterTable) return n;
643
-
644
- // Check in stack array
645
645
  if (n.stack && Array.isArray(n.stack)) {
646
646
  for (var i = 0; i < n.stack.length; i++) {
647
647
  var found = findFooterTableNode(n.stack[i]);
648
648
  if (found) return found;
649
649
  }
650
650
  }
651
-
652
- // Check if node is an array (footer might be array of items)
653
651
  if (Array.isArray(n)) {
654
652
  for (var i = 0; i < n.length; i++) {
655
653
  var found = findFooterTableNode(n[i]);
656
654
  if (found) return found;
657
655
  }
658
656
  }
659
-
660
657
  return null;
661
658
  }
662
659
 
663
- if (gapHeight > 0) {
664
- // Find remark bottom Y position (footer starts after remark)
665
- // The remark node has _isRemarkContent marker
666
- var remarkBottomY = 0;
667
- var remarkNode = null;
668
-
669
- // Find the remark node and footer table node in the stack
670
- var footerTableNode = null;
671
- if (node.stack && node.stack.length > 0) {
672
- for (var si = 0; si < node.stack.length; si++) {
673
- if (node.stack[si] && node.stack[si]._isRemarkContent && node.stack[si].remark) {
674
- remarkNode = node.stack[si];
675
- }
676
- }
677
- // Footer table has _isFooterTable marker - search recursively
678
- for (var si = node.stack.length - 1; si >= 0; si--) {
679
- var found = findFooterTableNode(node.stack[si]);
680
- if (found) {
681
- footerTableNode = found;
682
- break;
683
- }
660
+ // Find footer table node to get its height
661
+ var footerTableNode = null;
662
+ if (node.stack && node.stack.length > 0) {
663
+ for (var si = node.stack.length - 1; si >= 0; si--) {
664
+ var found = findFooterTableNode(node.stack[si]);
665
+ if (found) {
666
+ footerTableNode = found;
667
+ break;
684
668
  }
685
669
  }
670
+ }
686
671
 
687
- // Calculate remarkBottomY using footerTableNode._height (correct for multi-page)
688
- // Footer is unbreakable, so its height is always on current page
689
- // remarkNode._height is TOTAL height across all pages - NOT useful for multi-page
690
- var footerStartY = ctx.y; // Default
691
-
692
- if (footerTableNode && (footerTableNode._height || footerTableNode._minHeight)) {
693
- // Use footer table height - this is reliable for multi-page
694
- var footerHeight = footerTableNode._height || footerTableNode._minHeight;
695
- footerStartY = ctx.y - footerHeight;
696
- remarkBottomY = footerStartY; // Remark ends where footer starts
697
- } else {
698
- // Fallback: find lowest text line that's NOT inside footer table
699
- var firstVectorY = ctx.y;
700
- for (var fi = 0; fi < currentPage.items.length; fi++) {
701
- var fitem = currentPage.items[fi];
702
- if (fitem.type === 'vector' && fitem.item && fitem.item.type === 'line') {
703
- var vecY = fitem.item.y1;
704
- if (typeof vecY === 'number' && vecY < firstVectorY) {
705
- firstVectorY = vecY;
672
+ var footerHeight = Math.abs((footerTableNode && footerTableNode._height) || 0);
673
+
674
+ // Only process the LAST page where footer is located
675
+ // Intermediate pages (remark only) should not be repositioned
676
+ var pageIdx = ctx.page;
677
+ if (pageIdx > preRenderState.startPage) {
678
+ var page = pages[pageIdx];
679
+ if (page && page.items && page.items.length > 0) {
680
+ var pageHeight = page.pageSize.height;
681
+ var bottomMargin = pageMargins.bottom;
682
+ var pageBottom = pageHeight - bottomMargin;
683
+
684
+ // Find footer start Y on this page (where footer items begin)
685
+ // Use footerHeight to identify footer area from the bottom of content
686
+ var contentBottom = 0;
687
+ for (var i = 0; i < page.items.length; i++) {
688
+ var item = page.items[i];
689
+ var itemBottom = 0;
690
+ if (item.item) {
691
+ if (typeof item.item.y === 'number') {
692
+ var h = item.item.h || item.item.height || 0;
693
+ itemBottom = item.item.y + h;
706
694
  }
707
- }
708
- }
709
- for (var fi = 0; fi < currentPage.items.length; fi++) {
710
- var fitem = currentPage.items[fi];
711
- if (fitem.type === 'line' && fitem.item) {
712
- var lineY = fitem.item.y || 0;
713
- var lineHeight = fitem.item.getHeight ? fitem.item.getHeight() : 15;
714
- var lineBottom = lineY + lineHeight;
715
- if (lineBottom <= firstVectorY && lineBottom > remarkBottomY) {
716
- remarkBottomY = lineBottom;
695
+ if (typeof item.item.y2 === 'number' && item.item.y2 > itemBottom) {
696
+ itemBottom = item.item.y2;
717
697
  }
718
698
  }
699
+ if (itemBottom > contentBottom) {
700
+ contentBottom = itemBottom;
701
+ }
719
702
  }
720
- footerStartY = remarkBottomY > 0 ? remarkBottomY : firstVectorY;
721
- }
722
-
723
- // MULTI-PAGE: No guide lines - outer table borders extend through blank space
724
- // Only reposition FOOTER items (items at Y >= footerStartY)
725
- for (var i = 0; i < currentPage.items.length; i++) {
726
- var item = currentPage.items[i];
727
703
 
728
- // Skip guide lines we just added
729
- if (item.item && item.item._footerGuideLine) continue;
704
+ // Footer starts at contentBottom - footerHeight
705
+ var footerStartY = contentBottom - footerHeight;
706
+
707
+ // Calculate gap: how much to move footer down
708
+ var gapHeight = pageBottom - contentBottom;
709
+ if (gapHeight > 0) {
710
+ // Only move items that are part of footer (Y >= footerStartY)
711
+ for (var i = 0; i < page.items.length; i++) {
712
+ var item = page.items[i];
713
+ var itemY = null;
714
+ if (item.item && typeof item.item.y1 === 'number') {
715
+ itemY = item.item.y1;
716
+ } else if (item.item && typeof item.item.y === 'number') {
717
+ itemY = item.item.y;
718
+ }
730
719
 
731
- // Get item's starting Y position
732
- var itemY = null;
733
- if (item.item && typeof item.item.y1 === 'number') {
734
- itemY = item.item.y1;
735
- } else if (item.item && typeof item.item.y === 'number') {
736
- itemY = item.item.y;
737
- }
720
+ // Skip items above footer
721
+ if (itemY === null || itemY < footerStartY) continue;
738
722
 
739
- // Only reposition if item is part of footer (Y >= footerStartY)
740
- if (itemY === null || itemY < footerStartY) {
741
- continue;
742
- }
723
+ // Don't move items that are near the top margin (table headers)
724
+ // Use actual header height from repeatables instead of hardcoded threshold
725
+ var repeatableHeaderHeight = 0;
726
+ for (var ri = 0; ri < self.writer.repeatables.length; ri++) {
727
+ repeatableHeaderHeight += self.writer.repeatables[ri].height;
728
+ }
729
+ var headerThreshold = pageMargins.top + repeatableHeaderHeight;
730
+ if (itemY < headerThreshold) continue;
743
731
 
744
- // Reposition this item
745
- if (item.item && typeof item.item.y === 'number') {
746
- item.item.y += gapHeight;
747
- }
748
- if (item.item && typeof item.item.y1 === 'number') {
749
- item.item.y1 += gapHeight;
750
- }
751
- if (item.item && typeof item.item.y2 === 'number') {
752
- item.item.y2 += gapHeight;
732
+ // Move footer item down
733
+ if (item.item && typeof item.item.y === 'number') {
734
+ item.item.y += gapHeight;
735
+ }
736
+ if (item.item && typeof item.item.y1 === 'number') {
737
+ item.item.y1 += gapHeight;
738
+ }
739
+ if (item.item && typeof item.item.y2 === 'number') {
740
+ item.item.y2 += gapHeight;
741
+ }
742
+ }
753
743
  }
754
744
  }
755
- ctx.moveDown(gapHeight);
745
+ }
746
+
747
+ // Also update context for current page
748
+ var lastPageGapHeight = ctx.availableHeight;
749
+ if (lastPageGapHeight > 0) {
750
+ ctx.moveDown(lastPageGapHeight);
756
751
  }
757
752
  }
758
753
  }