diff --git a/src/DocumentContext.js b/src/DocumentContext.js index 39ff2fb79..3926bf14c 100644 --- a/src/DocumentContext.js +++ b/src/DocumentContext.js @@ -186,6 +186,16 @@ class DocumentContext extends EventEmitter { let prevPage = this.page; let prevY = this.y; + // If we are in a column group + if (this.snapshots.length > 0) { + let lastSnapshot = this.snapshots[this.snapshots.length - 1]; + // We have to update prevY accordingly by also taking into consideration + // the 'y' of cells that don't break page + if (lastSnapshot.bottomMost && lastSnapshot.bottomMost.y) { + prevY = Math.max(this.y, lastSnapshot.bottomMost.y); + } + } + let createNewPage = nextPageIndex >= this.pages.length; if (createNewPage) { let currentAvailableWidth = this.availableWidth; diff --git a/src/LayoutBuilder.js b/src/LayoutBuilder.js index b08d7f986..41810e1b6 100644 --- a/src/LayoutBuilder.js +++ b/src/LayoutBuilder.js @@ -511,6 +511,22 @@ class LayoutBuilder { } processRow(columns, widths, gaps, tableBody, tableRow, height) { + const updatePageBreakData = (page, prevY) => { + let pageDesc; + // Find page break data for this row and page + for (let i = 0, l = pageBreaks.length; i < l; i++) { + let desc = pageBreaks[i]; + if (desc.prevPage === page) { + pageDesc = desc; + break; + } + } + // If row has page break in this page, update prevY + if (pageDesc) { + pageDesc.prevY = Math.max(pageDesc.prevY, prevY); + } + }; + const storePageBreakData = data => { let pageDesc; @@ -595,6 +611,9 @@ class LayoutBuilder { } } + // If there are page breaks in this row, update data with prevY of last cell + updatePageBreakData(this.writer.context().page, this.writer.context().y); + this.writer.context().completeColumnGroup(height, endingSpanCell); this.writer.removeListener('pageChanged', storePageBreakData); diff --git a/tests/unit/LayoutBuilder.spec.js b/tests/unit/LayoutBuilder.spec.js index c98a7f21c..542b0f51b 100644 --- a/tests/unit/LayoutBuilder.spec.js +++ b/tests/unit/LayoutBuilder.spec.js @@ -1686,13 +1686,24 @@ describe('LayoutBuilder', function () { }); it('on page break should return an entry with ending/starting positions', function () { + var doc = createTable(0, 1, 10, 5, 5); + var result = builder2.processRow(doc.table.body[0], doc.table.widths, doc._offsets.offsets, doc.table.body, 0); + + assert(result.pageBreaks instanceof Array); + assert.equal(result.pageBreaks.length, 1); + assert.equal(result.pageBreaks[0].prevPage, 0); + assert.equal(result.pageBreaks[0].prevY, 40 + 12 * 6); + }); + + it('on page break should return an entry with ending/starting positions 2', function () { var doc = createTable(0, 1, 10, 5); var result = builder2.processRow(doc.table.body[0], doc.table.widths, doc._offsets.offsets, doc.table.body, 0); assert(result.pageBreaks instanceof Array); assert.equal(result.pageBreaks.length, 1); assert.equal(result.pageBreaks[0].prevPage, 0); - assert.equal(result.pageBreaks[0].prevY, 40 + 12 * 5); + + assert.equal(result.pageBreaks[0].prevY, 40 + 12 * 11); }); it('on multi-pass page break (columns or table columns) should treat bottom-most page-break as the ending position ', function () { @@ -1703,7 +1714,7 @@ describe('LayoutBuilder', function () { }); it('on multiple page breaks (more than 2 pages), should return all entries with ending/starting positions', function () { - var doc = createTable(0, 1, 100, 90); + var doc = createTable(0, 1, 100, 90, 90); var result = builder2.processRow(doc.table.body[0], doc.table.widths, doc._offsets.offsets, doc.table.body, 0); assert(result.pageBreaks instanceof Array); @@ -1714,6 +1725,18 @@ describe('LayoutBuilder', function () { assert.equal(result.pageBreaks[1].prevY, 40 + (90 - 60) * 12); }); + it('on multiple page breaks (more than 2 pages), should return all entries with ending/starting positions 2', function () { + var doc = createTable(0, 1, 100, 90); + var result = builder2.processRow(doc.table.body[0], doc.table.widths, doc._offsets.offsets, doc.table.body, 0); + + assert(result.pageBreaks instanceof Array); + assert.equal(result.pageBreaks.length, 2); + assert.equal(result.pageBreaks[0].prevPage, 0); + assert.equal(result.pageBreaks[0].prevY, 40 + 60 * 12); + assert.equal(result.pageBreaks[1].prevPage, 1); + assert.equal(result.pageBreaks[1].prevY, 40 + 41 * 12); + }); + it('on multiple and multi-pass page breaks should calculate bottom-most endings for every page', function () { var doc = createTable(0, 1, 100, 90, 92); var result = builder2.processRow(doc.table.body[0], doc.table.widths, doc._offsets.offsets, doc.table.body, 0); @@ -1727,6 +1750,9 @@ describe('LayoutBuilder', function () { }); }); + + + describe('dynamic header/footer', function () { var docStructure, pdfDocument, styleDictionary, defaultStyle, background, header, footer, watermark, pageBreakBeforeFunction;