@flowaccount/pdfmake 1.0.0 → 1.0.2
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/build/pdfmake.js +32800 -31746
- package/build/pdfmake.min.js +2 -2
- package/build/pdfmake.min.js.map +1 -1
- package/package.json +2 -2
- package/src/documentContext.js +2 -2
- package/src/layoutBuilder.js +264 -5
- package/src/printer.js +113 -8
- package/src/tableProcessor.js +133 -5
package/src/tableProcessor.js
CHANGED
|
@@ -310,6 +310,72 @@ TableProcessor.prototype.drawHorizontalLine = function (lineIndex, writer, overr
|
|
|
310
310
|
}
|
|
311
311
|
};
|
|
312
312
|
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Draws vertical lines to fill the gap when a row is forced to the next page.
|
|
316
|
+
* This prevents missing vertical lines at the bottom of the page.
|
|
317
|
+
* @param {number} rowIndex - The index of the row being forced to next page
|
|
318
|
+
* @param {object} writer - The document writer
|
|
319
|
+
* @param {number} y0 - Starting Y position
|
|
320
|
+
* @param {number} y1 - Ending Y position (page break point)
|
|
321
|
+
*/
|
|
322
|
+
TableProcessor.prototype.drawVerticalLinesForForcedPageBreak = function (rowIndex, writer, y0, y1) {
|
|
323
|
+
if (!this.rowSpanData || rowIndex <= 0) {
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
var body = this.tableNode.table.body;
|
|
328
|
+
var prevRowIndex = rowIndex - 1; // Use previous row for cell border detection
|
|
329
|
+
|
|
330
|
+
// Get X positions for vertical lines (similar logic to endRow's getLineXs)
|
|
331
|
+
var xs = [];
|
|
332
|
+
var cols = 0;
|
|
333
|
+
|
|
334
|
+
for (var i = 0, l = body[prevRowIndex].length; i < l; i++) {
|
|
335
|
+
if (!cols) {
|
|
336
|
+
xs.push({ x: this.rowSpanData[i].left, index: i });
|
|
337
|
+
var item = body[prevRowIndex][i];
|
|
338
|
+
cols = (item._colSpan || item.colSpan || 0);
|
|
339
|
+
}
|
|
340
|
+
if (cols > 0) {
|
|
341
|
+
cols--;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
xs.push({ x: this.rowSpanData[this.rowSpanData.length - 1].left, index: this.rowSpanData.length - 1 });
|
|
345
|
+
|
|
346
|
+
// Draw vertical lines for each column position
|
|
347
|
+
for (var xi = 0, xl = xs.length; xi < xl; xi++) {
|
|
348
|
+
var leftCellBorder = false;
|
|
349
|
+
var colIndex = xs[xi].index;
|
|
350
|
+
|
|
351
|
+
// Check if we need to draw a vertical line at this position
|
|
352
|
+
// based on cell borders from the previous row
|
|
353
|
+
var cell;
|
|
354
|
+
if (colIndex < body[prevRowIndex].length) {
|
|
355
|
+
cell = body[prevRowIndex][colIndex];
|
|
356
|
+
leftCellBorder = cell.border ? cell.border[0] : this.layout.defaultBorder;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// Check cell before
|
|
360
|
+
if (colIndex > 0 && !leftCellBorder) {
|
|
361
|
+
cell = body[prevRowIndex][colIndex - 1];
|
|
362
|
+
leftCellBorder = cell.border ? cell.border[2] : this.layout.defaultBorder;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
if (leftCellBorder) {
|
|
366
|
+
this.drawVerticalLine(
|
|
367
|
+
xs[xi].x,
|
|
368
|
+
y0,
|
|
369
|
+
y1,
|
|
370
|
+
xs[xi].index,
|
|
371
|
+
writer,
|
|
372
|
+
prevRowIndex,
|
|
373
|
+
xi > 0 ? xs[xi - 1].index : null
|
|
374
|
+
);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
};
|
|
378
|
+
|
|
313
379
|
TableProcessor.prototype.drawVerticalLine = function (x, y0, y1, vLineColIndex, writer, vLineRowIndex, beforeVLineColIndex) {
|
|
314
380
|
var width = this.layout.vLineWidth(vLineColIndex, this.tableNode);
|
|
315
381
|
if (width === 0) {
|
|
@@ -409,9 +475,11 @@ TableProcessor.prototype.endTable = function (writer) {
|
|
|
409
475
|
}
|
|
410
476
|
};
|
|
411
477
|
|
|
412
|
-
TableProcessor.prototype.endRow = function (rowIndex, writer, pageBreaks) {
|
|
478
|
+
TableProcessor.prototype.endRow = function (rowIndex, writer, pageBreaks, nextRowCells, layoutBuilder) {
|
|
413
479
|
var l, i;
|
|
414
480
|
var self = this;
|
|
481
|
+
var tableLayout = this.tableNode && this.tableNode._layout;
|
|
482
|
+
var nearBottomThreshold = (tableLayout && tableLayout.nearBottomThreshold) || 20;
|
|
415
483
|
|
|
416
484
|
writer.tracker.stopTracking('pageChanged', this.rowCallback);
|
|
417
485
|
writer.context().moveDown(this.layout.paddingBottom(rowIndex, this.tableNode));
|
|
@@ -437,7 +505,7 @@ TableProcessor.prototype.endRow = function (rowIndex, writer, pageBreaks) {
|
|
|
437
505
|
var pageBreak = pageBreaks[i];
|
|
438
506
|
ys[ys.length - 1].y1 = pageBreak.prevY;
|
|
439
507
|
|
|
440
|
-
ys.push({ y0: pageBreak.y, page: pageBreak.prevPage + 1 });
|
|
508
|
+
ys.push({ y0: pageBreak.y, page: pageBreak.prevPage + 1, forced: pageBreak.forced });
|
|
441
509
|
}
|
|
442
510
|
}
|
|
443
511
|
|
|
@@ -473,11 +541,21 @@ TableProcessor.prototype.endRow = function (rowIndex, writer, pageBreaks) {
|
|
|
473
541
|
}
|
|
474
542
|
|
|
475
543
|
// Draw horizontal lines before the vertical lines so they are not overridden
|
|
544
|
+
// Only set isPageBreak=true when at TRUE page bottom (not just forced breaks)
|
|
545
|
+
var ctx = writer.context();
|
|
546
|
+
var currentPage = ctx.getCurrentPage && ctx.getCurrentPage();
|
|
547
|
+
var pageHeight = currentPage ? (currentPage.pageSize.height - ctx.pageMargins.bottom) : 0;
|
|
548
|
+
|
|
476
549
|
if (willBreak && this.layout.hLineWhenBroken !== false) {
|
|
477
|
-
|
|
550
|
+
// Check if we're at the true page bottom
|
|
551
|
+
var isAtTruePageBottom = (pageHeight - y2) <= nearBottomThreshold;
|
|
552
|
+
this.drawHorizontalLine(rowIndex + 1, writer, y2, true, null, isAtTruePageBottom);
|
|
478
553
|
}
|
|
479
554
|
if (rowBreakWithoutHeader && this.layout.hLineWhenBroken !== false) {
|
|
480
|
-
|
|
555
|
+
// Check if previous segment ended at true page bottom
|
|
556
|
+
var prevSegmentY = (yi > 0) ? ys[yi - 1].y1 : 0;
|
|
557
|
+
var prevWasAtPageBottom = (pageHeight - prevSegmentY) <= nearBottomThreshold;
|
|
558
|
+
this.drawHorizontalLine(rowIndex, writer, y1, true, null, prevWasAtPageBottom);
|
|
481
559
|
}
|
|
482
560
|
|
|
483
561
|
for (i = 0, l = xs.length; i < l; i++) {
|
|
@@ -596,7 +674,57 @@ TableProcessor.prototype.endRow = function (rowIndex, writer, pageBreaks) {
|
|
|
596
674
|
}
|
|
597
675
|
}
|
|
598
676
|
|
|
599
|
-
|
|
677
|
+
// Look ahead: Check if next row will cause a page break
|
|
678
|
+
// If yes, skip drawing the horizontal line at the end of current row
|
|
679
|
+
// This feature is OPT-IN: only enabled when forcePageBreakForAllRows === true
|
|
680
|
+
var shouldSkipHorizontalLine = false;
|
|
681
|
+
|
|
682
|
+
if (nextRowCells && layoutBuilder) {
|
|
683
|
+
// Only perform look-ahead if forcePageBreakForAllRows is explicitly enabled
|
|
684
|
+
// This prevents affecting existing PDFs that don't use this feature
|
|
685
|
+
if (tableLayout && tableLayout.forcePageBreakForAllRows === true) {
|
|
686
|
+
var nextRowEstimatedHeight = 0;
|
|
687
|
+
|
|
688
|
+
// Try to get maximum cell height from next row's measured content
|
|
689
|
+
if (layoutBuilder._getMaxCellHeight) {
|
|
690
|
+
var maxNextCellHeight = layoutBuilder._getMaxCellHeight(nextRowCells);
|
|
691
|
+
if (maxNextCellHeight > 0) {
|
|
692
|
+
nextRowEstimatedHeight = maxNextCellHeight + 10; // Add padding
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
// Fallback: use minRowHeight from table layout
|
|
697
|
+
if (nextRowEstimatedHeight === 0) {
|
|
698
|
+
var footerGapOpt = writer.context()._footerGapOption;
|
|
699
|
+
nextRowEstimatedHeight = (tableLayout && tableLayout.minRowHeight) || (footerGapOpt && footerGapOpt.minRowHeight) || 80;
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
// Check current available height (after current row has been processed)
|
|
703
|
+
var currentAvailableHeight = writer.context().availableHeight;
|
|
704
|
+
|
|
705
|
+
// Skip drawing the horizontal line if EITHER:
|
|
706
|
+
// 1. Next row won't fit (will cause page break), OR
|
|
707
|
+
// 2. We're very close to page bottom (remaining space <= threshold)
|
|
708
|
+
// This prevents duplicate/orphaned lines at page boundaries
|
|
709
|
+
if (nextRowEstimatedHeight > currentAvailableHeight || currentAvailableHeight <= nearBottomThreshold) {
|
|
710
|
+
// Exception: Check if this line should always be drawn (critical boundary)
|
|
711
|
+
// Allow layout to specify via alwaysDrawHLine callback
|
|
712
|
+
var shouldAlwaysDrawLine = false;
|
|
713
|
+
if (typeof tableLayout.alwaysDrawHLine === 'function') {
|
|
714
|
+
shouldAlwaysDrawLine = tableLayout.alwaysDrawHLine(rowIndex + 1, this.tableNode, writer);
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
if (!shouldAlwaysDrawLine) {
|
|
718
|
+
shouldSkipHorizontalLine = true;
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
// Draw horizontal line at the end of the row, unless next row will cause a page break
|
|
725
|
+
if (!shouldSkipHorizontalLine) {
|
|
726
|
+
this.drawHorizontalLine(rowIndex + 1, writer);
|
|
727
|
+
}
|
|
600
728
|
|
|
601
729
|
if (this.headerRows && rowIndex === this.headerRows - 1) {
|
|
602
730
|
this.headerRepeatable = writer.currentBlockToRepeatable();
|