@flowaccount/pdfmake 1.0.7-staging.3 → 1.0.7-staging.4

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.7-staging.3",
3
+ "version": "1.0.7-staging.4",
4
4
  "description": "Client/server side PDF printing in pure JavaScript",
5
5
  "main": "src/printer.js",
6
6
  "browser": "build/pdfmake.js",
@@ -539,13 +539,31 @@ LayoutBuilder.prototype.processNode = function (node) {
539
539
  startPage: ctx.page,
540
540
  availableHeight: ctx.availableHeight,
541
541
  itemCount: currentPage ? currentPage.items.length : 0,
542
- x: ctx.x
542
+ x: ctx.x,
543
+ summaryRenderedPage: null
543
544
  };
544
545
  }
545
546
 
546
547
  // Process the stack
547
548
  self.processVerticalContainer(node);
548
549
 
550
+ // Track which page summary was rendered on (summary is first item, unbreakable)
551
+ if (preRenderState && node.stack && node.stack[0]) {
552
+ var summaryNode = node.stack[0];
553
+ if (summaryNode.summary || summaryNode.unbreakable) {
554
+ // Summary is unbreakable, check if it was pushed to a new page
555
+ // by comparing its height with available space at startPage
556
+ var summaryHeight = Math.abs(summaryNode._height || 0);
557
+ if (summaryHeight <= preRenderState.availableHeight) {
558
+ // Summary fit on startPage
559
+ preRenderState.summaryRenderedPage = preRenderState.startPage;
560
+ } else {
561
+ // Summary was pushed to next page
562
+ preRenderState.summaryRenderedPage = preRenderState.startPage + 1;
563
+ }
564
+ }
565
+ }
566
+
549
567
  // Post-render repositioning
550
568
  if (footerGapEnabled && preRenderState) {
551
569
  var ctx = self.writer.context();
@@ -726,9 +744,12 @@ LayoutBuilder.prototype.processNode = function (node) {
726
744
  sItemY = sItem.item.y1;
727
745
  } else if (sItem.item && typeof sItem.item.y === 'number') {
728
746
  sItemY = sItem.item.y;
747
+ } else if (sItem.item && sItem.item.points && Array.isArray(sItem.item.points) && sItem.item.points.length > 0) {
748
+ // For polylines, use the first point's Y
749
+ sItemY = sItem.item.points[0].y;
729
750
  }
730
751
 
731
- // Skip items fully above footer start
752
+ // Skip items fully above footer start
732
753
  if (sItemY === null || sItemY < startStackStartY) continue;
733
754
 
734
755
  // Move item down
@@ -827,19 +848,35 @@ LayoutBuilder.prototype.processNode = function (node) {
827
848
  if (typeof item.item.y2 === 'number' && item.item.y2 > itemBottom) {
828
849
  itemBottom = item.item.y2;
829
850
  }
851
+ // Handle polylines (points array)
852
+ if (item.item.points && Array.isArray(item.item.points)) {
853
+ for (var pi = 0; pi < item.item.points.length; pi++) {
854
+ if (typeof item.item.points[pi].y === 'number' && item.item.points[pi].y > itemBottom) {
855
+ itemBottom = item.item.points[pi].y;
856
+ }
857
+ }
858
+ }
830
859
  }
831
860
  if (itemBottom > contentBottom) {
832
861
  contentBottom = itemBottom;
833
862
  }
834
863
  }
835
864
 
836
- // Footer starts at contentBottom - footerHeight
837
- var stackStartY = contentBottom - stackHeight;
865
+ // Check if summary is on the last page
866
+ var summaryOnLastPage = (preRenderState.summaryRenderedPage === pageIdx);
838
867
 
839
- // Calculate gap: how much to move footer down
840
- var gapHeight = pageBottom - contentBottom;
841
- if (gapHeight > 0) {
842
- // Only move items that are part of footer (Y >= footerStartY)
868
+ var stackStartY;
869
+ if (summaryOnLastPage) {
870
+ // Summary is on this page - move all: summary + remark + footer together
871
+ // Calculate header threshold for this page
872
+ var repeatableHeaderHeight = 0;
873
+ for (var ri = 0; ri < self.writer.repeatables.length; ri++) {
874
+ repeatableHeaderHeight += self.writer.repeatables[ri].height;
875
+ }
876
+ var headerThreshold = pageMargins.top + repeatableHeaderHeight;
877
+
878
+ // Find minimum Y of all items below header threshold
879
+ stackStartY = contentBottom;
843
880
  for (var i = 0; i < page.items.length; i++) {
844
881
  var item = page.items[i];
845
882
  var itemY = null;
@@ -848,23 +885,92 @@ LayoutBuilder.prototype.processNode = function (node) {
848
885
  } else if (item.item && typeof item.item.y === 'number') {
849
886
  itemY = item.item.y;
850
887
  } else if (item.item && item.item.points && Array.isArray(item.item.points) && item.item.points.length > 0) {
851
- // For polylines, use the first point's Y
852
888
  itemY = item.item.points[0].y;
853
889
  }
890
+ if (itemY !== null && itemY >= headerThreshold && itemY < stackStartY) {
891
+ stackStartY = itemY;
892
+ }
893
+ }
854
894
 
855
- // Skip items above footer
856
- if (itemY === null || itemY < stackStartY) continue;
895
+ // Draw guide lines in the gap area (same as single-page)
896
+ var gapHeightForLines = pageBottom - contentBottom;
897
+ if (gapHeightForLines > 0) {
898
+ var colSpec = node._footerGapOption && node._footerGapOption.columns ? node._footerGapOption.columns : (self._footerGapOption && self._footerGapOption.columns);
899
+ if (colSpec) {
900
+ var rawWidths = colSpec.content && colSpec.content.vLines ? colSpec.content.vLines : [];
901
+ if (rawWidths && rawWidths.length > 1) {
902
+ var style = (colSpec.style || {});
903
+ var lw = style.lineWidth != null ? style.lineWidth : 0.5;
904
+ var lc = style.color || '#000000';
905
+ var dashCfg = style.dash;
906
+ var includeOuter = colSpec.includeOuter !== false;
907
+ var startIndex = includeOuter ? 0 : 1;
908
+ var endIndex = includeOuter ? rawWidths.length : rawWidths.length - 1;
909
+ var pageX = preRenderState.x || pageMargins.left;
910
+
911
+ for (var ci = startIndex; ci < endIndex; ci++) {
912
+ var xGuide = pageX + rawWidths[ci] - 0.25;
913
+ page.items.push({
914
+ type: 'vector',
915
+ item: {
916
+ type: 'line',
917
+ x1: xGuide,
918
+ y1: stackStartY,
919
+ x2: xGuide,
920
+ y2: stackStartY + gapHeightForLines,
921
+ lineWidth: lw,
922
+ lineColor: lc,
923
+ dash: dashCfg ? {
924
+ length: dashCfg.length,
925
+ space: dashCfg.space != null ? dashCfg.space : dashCfg.gap
926
+ } : undefined,
927
+ _footerGuideLine: true
928
+ }
929
+ });
930
+ }
931
+ }
932
+ }
933
+ }
934
+ } else {
935
+ // Summary is NOT on this page - move only footer
936
+ stackStartY = contentBottom - stackHeight;
937
+ }
857
938
 
858
- // Don't move items that are near the top margin (table headers)
859
- // Use actual header height from repeatables instead of hardcoded threshold
939
+ // Calculate gap: how much to move footer stack down
940
+ var gapHeight = pageBottom - contentBottom;
941
+ if (gapHeight > 0) {
942
+ // Calculate header threshold if not already calculated
943
+ if (typeof headerThreshold === 'undefined') {
860
944
  var repeatableHeaderHeight = 0;
861
945
  for (var ri = 0; ri < self.writer.repeatables.length; ri++) {
862
946
  repeatableHeaderHeight += self.writer.repeatables[ri].height;
863
947
  }
864
- var headerThreshold = pageMargins.top + repeatableHeaderHeight;
948
+ headerThreshold = pageMargins.top + repeatableHeaderHeight;
949
+ }
950
+
951
+ // Move all items that are part of footer stack (Y >= stackStartY)
952
+ for (var i = 0; i < page.items.length; i++) {
953
+ var item = page.items[i];
954
+
955
+ // Skip guide lines (they're already positioned correctly)
956
+ if (item.item && item.item._footerGuideLine) continue;
957
+
958
+ var itemY = null;
959
+ if (item.item && typeof item.item.y1 === 'number') {
960
+ itemY = item.item.y1;
961
+ } else if (item.item && typeof item.item.y === 'number') {
962
+ itemY = item.item.y;
963
+ } else if (item.item && item.item.points && Array.isArray(item.item.points) && item.item.points.length > 0) {
964
+ itemY = item.item.points[0].y;
965
+ }
966
+
967
+ // Skip items above footer stack
968
+ if (itemY === null || itemY < stackStartY) continue;
969
+
970
+ // Skip items in header area (repeated headers)
865
971
  if (itemY < headerThreshold) continue;
866
972
 
867
- // Move footer item down
973
+ // Move footer stack item down
868
974
  if (item.item && typeof item.item.y === 'number') {
869
975
  item.item.y += gapHeight;
870
976
  }