From a36e884d7eea980b26c789970bd37e7410e0d8d2 Mon Sep 17 00:00:00 2001 From: Jake Holland Date: Thu, 12 Jun 2025 15:41:27 +0100 Subject: [PATCH 1/5] Add a flag to ignore the trailing line break in text height calculations (including tables) --- CHANGELOG.md | 2 ++ lib/line_wrapper.js | 10 ++++++++-- lib/mixins/text.js | 11 ++++++++++- ...re-trailing-line-break-issue-1620-1-snap.png | Bin 0 -> 28910 bytes ...re-trailing-line-break-issue-1620-1-snap.png | Bin 0 -> 14293 bytes tests/visual/table.spec.js | 14 ++++++++++++++ tests/visual/text.spec.js | 11 +++++++++++ 7 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 tests/visual/__image_snapshots__/table-spec-js-table-ignore-trailing-line-break-issue-1620-1-snap.png create mode 100644 tests/visual/__image_snapshots__/text-spec-js-text-ignore-trailing-line-break-issue-1620-1-snap.png diff --git a/CHANGELOG.md b/CHANGELOG.md index d0c64641..323242e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ### Unreleased +- Add a flag to ignore the trailing line break in text height calculations (including tables) + ### [v0.17.1] - 2025-05-02 - Fix null values in table cells rendering as `[object Object]` diff --git a/lib/line_wrapper.js b/lib/line_wrapper.js index 7702dac3..59f77e2e 100644 --- a/lib/line_wrapper.js +++ b/lib/line_wrapper.js @@ -236,11 +236,17 @@ class LineWrapper extends EventEmitter { if (bk.required || !this.canFit(word, w)) { // if the user specified a max height and an ellipsis, and is about to pass the // max height and max columns after the next line, append the ellipsis - const lh = this.document.currentLineHeight(true); + let lh = this.document.currentLineHeight(true); + + if (options.trailingLineBreak === false) { + if (bk.required) lh = this.document.currentLineHeight(); + } + if ( this.height != null && this.ellipsis && - PDFNumber(this.document.y + lh * 2) > this.maxY && + // If the current line and its following one cant fit, then render the ellipsis + PDFNumber(this.document.y + lh + this.document.currentLineHeight(true)) > this.maxY && this.column >= this.columns ) { if (this.ellipsis === true) { diff --git a/lib/mixins/text.js b/lib/mixins/text.js index 168d390f..33ae6ffc 100644 --- a/lib/mixins/text.js +++ b/lib/mixins/text.js @@ -174,6 +174,10 @@ export default { } let contentHeight = this.y - y; + if (options.trailingLineBreak === false) { + const fontGap = this.currentLineHeight(true) - this.currentLineHeight(); + contentHeight -= fontGap; + } // Clamp height to max height if (options.height) contentHeight = Math.min(contentHeight, options.height); @@ -245,7 +249,12 @@ export default { this.y += this.currentLineHeight(true) + lineGap; }); - const height = this.y - y; + let height = this.y - y; + if (options.trailingLineBreak === false) { + const fontGap = this.currentLineHeight(true) - this.currentLineHeight(); + height -= fontGap; + } + this.x = x; this.y = y; diff --git a/tests/visual/__image_snapshots__/table-spec-js-table-ignore-trailing-line-break-issue-1620-1-snap.png b/tests/visual/__image_snapshots__/table-spec-js-table-ignore-trailing-line-break-issue-1620-1-snap.png new file mode 100644 index 0000000000000000000000000000000000000000..ed03dc966def743c53ef0f066dec232422ee4599 GIT binary patch literal 28910 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 Date: Tue, 17 Jun 2025 10:19:35 +0100 Subject: [PATCH 2/5] fix lint issues --- lib/line_wrapper.js | 4 +++- tests/visual/table.spec.js | 4 ++-- tests/visual/text.spec.js | 22 +++++++++++++++++----- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/lib/line_wrapper.js b/lib/line_wrapper.js index 59f77e2e..cde4e143 100644 --- a/lib/line_wrapper.js +++ b/lib/line_wrapper.js @@ -246,7 +246,9 @@ class LineWrapper extends EventEmitter { this.height != null && this.ellipsis && // If the current line and its following one cant fit, then render the ellipsis - PDFNumber(this.document.y + lh + this.document.currentLineHeight(true)) > this.maxY && + PDFNumber( + this.document.y + lh + this.document.currentLineHeight(true), + ) > this.maxY && this.column >= this.columns ) { if (this.ellipsis === true) { diff --git a/tests/visual/table.spec.js b/tests/visual/table.spec.js index 0c0cab88..9df210e8 100644 --- a/tests/visual/table.spec.js +++ b/tests/visual/table.spec.js @@ -426,8 +426,8 @@ describe('table', function () { }); }); - test('ignore trailing line break - issue #1620', function() { - return runDocTest({systemFonts: true}, function(doc) { + test('ignore trailing line break - issue #1620', function () { + return runDocTest({ systemFonts: true }, function (doc) { doc.table({ debug: true, data: [['trailingLineBreak\ndefault (true)']], diff --git a/tests/visual/text.spec.js b/tests/visual/text.spec.js index bf3b7aec..1cb3950f 100644 --- a/tests/visual/text.spec.js +++ b/tests/visual/text.spec.js @@ -183,13 +183,25 @@ describe('text', function () { }); }); - test('ignore trailing line break - issue #1620', function() { - return runDocTest({systemFonts: true}, function(doc) { + test('ignore trailing line break - issue #1620', function () { + return runDocTest({ systemFonts: true }, function (doc) { const text = 'test\ntest'; - let heightWithout = doc.heightOfString(text, {trailingLineBreak: false}); - doc.save().rect(doc.x, doc.y, doc.page.contentWidth, heightWithout).strokeColor("red", 0.3).stroke().restore(); + let heightWithout = doc.heightOfString(text, { + trailingLineBreak: false, + }); + doc + .save() + .rect(doc.x, doc.y, doc.page.contentWidth, heightWithout) + .strokeColor('red', 0.3) + .stroke() + .restore(); let height = doc.heightOfString(text); - doc.save().rect(doc.x, doc.y, doc.page.contentWidth, height).strokeColor("blue", 0.3).stroke().restore(); + doc + .save() + .rect(doc.x, doc.y, doc.page.contentWidth, height) + .strokeColor('blue', 0.3) + .stroke() + .restore(); doc.text(text, { height }); }); }); From ebe9ee5b8fb5acb0a36804e7f706156586be8a70 Mon Sep 17 00:00:00 2001 From: Jake Holland Date: Tue, 17 Jun 2025 13:07:25 +0100 Subject: [PATCH 3/5] add threshold checks --- tests/visual/table.spec.js | 8 ++++++-- tests/visual/text.spec.js | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/tests/visual/table.spec.js b/tests/visual/table.spec.js index 9df210e8..5e085c1c 100644 --- a/tests/visual/table.spec.js +++ b/tests/visual/table.spec.js @@ -426,8 +426,12 @@ describe('table', function () { }); }); - test('ignore trailing line break - issue #1620', function () { - return runDocTest({ systemFonts: true }, function (doc) { + test('ignore trailing line break - issue #1620', function() { + return runDocTest({ + systemFonts: true, + failureThreshold: 0.0002, + failureThresholdType: 'percent', + }, function(doc) { doc.table({ debug: true, data: [['trailingLineBreak\ndefault (true)']], diff --git a/tests/visual/text.spec.js b/tests/visual/text.spec.js index 1cb3950f..95c5203e 100644 --- a/tests/visual/text.spec.js +++ b/tests/visual/text.spec.js @@ -183,8 +183,12 @@ describe('text', function () { }); }); - test('ignore trailing line break - issue #1620', function () { - return runDocTest({ systemFonts: true }, function (doc) { + test('ignore trailing line break - issue #1620', function() { + return runDocTest({ + systemFonts: true, + failureThreshold: 0.0002, + failureThresholdType: 'percent', + }, function(doc) { const text = 'test\ntest'; let heightWithout = doc.heightOfString(text, { trailingLineBreak: false, From 6c9a81ae97d992f6f87ad0c29086e01cac4360fc Mon Sep 17 00:00:00 2001 From: Jake Holland Date: Tue, 17 Jun 2025 13:30:53 +0100 Subject: [PATCH 4/5] fix linting --- tests/visual/table.spec.js | 35 +++++++++++++------------ tests/visual/text.spec.js | 53 ++++++++++++++++++++------------------ 2 files changed, 47 insertions(+), 41 deletions(-) diff --git a/tests/visual/table.spec.js b/tests/visual/table.spec.js index 5e085c1c..dead4272 100644 --- a/tests/visual/table.spec.js +++ b/tests/visual/table.spec.js @@ -426,21 +426,24 @@ describe('table', function () { }); }); - test('ignore trailing line break - issue #1620', function() { - return runDocTest({ - systemFonts: true, - failureThreshold: 0.0002, - failureThresholdType: 'percent', - }, function(doc) { - doc.table({ - debug: true, - data: [['trailingLineBreak\ndefault (true)']], - }); - doc.table({ - debug: true, - defaultStyle: { textOptions: { trailingLineBreak: false } }, - data: [['trailingLineBreak\nfalse']], - }); - }); + test('ignore trailing line break - issue #1620', function () { + return runDocTest( + { + systemFonts: true, + failureThreshold: 0.0002, + failureThresholdType: 'percent', + }, + function (doc) { + doc.table({ + debug: true, + data: [['trailingLineBreak\ndefault (true)']], + }); + doc.table({ + debug: true, + defaultStyle: { textOptions: { trailingLineBreak: false } }, + data: [['trailingLineBreak\nfalse']], + }); + }, + ); }); }); diff --git a/tests/visual/text.spec.js b/tests/visual/text.spec.js index 95c5203e..0ede5935 100644 --- a/tests/visual/text.spec.js +++ b/tests/visual/text.spec.js @@ -183,30 +183,33 @@ describe('text', function () { }); }); - test('ignore trailing line break - issue #1620', function() { - return runDocTest({ - systemFonts: true, - failureThreshold: 0.0002, - failureThresholdType: 'percent', - }, function(doc) { - const text = 'test\ntest'; - let heightWithout = doc.heightOfString(text, { - trailingLineBreak: false, - }); - doc - .save() - .rect(doc.x, doc.y, doc.page.contentWidth, heightWithout) - .strokeColor('red', 0.3) - .stroke() - .restore(); - let height = doc.heightOfString(text); - doc - .save() - .rect(doc.x, doc.y, doc.page.contentWidth, height) - .strokeColor('blue', 0.3) - .stroke() - .restore(); - doc.text(text, { height }); - }); + test('ignore trailing line break - issue #1620', function () { + return runDocTest( + { + systemFonts: true, + failureThreshold: 0.0002, + failureThresholdType: 'percent', + }, + function (doc) { + const text = 'test\ntest'; + let heightWithout = doc.heightOfString(text, { + trailingLineBreak: false, + }); + doc + .save() + .rect(doc.x, doc.y, doc.page.contentWidth, heightWithout) + .strokeColor('red', 0.3) + .stroke() + .restore(); + let height = doc.heightOfString(text); + doc + .save() + .rect(doc.x, doc.y, doc.page.contentWidth, height) + .strokeColor('blue', 0.3) + .stroke() + .restore(); + doc.text(text, { height }); + }, + ); }); }); From 3dfe45a895cc475198b3a60e8293d22b2d6d3ea9 Mon Sep 17 00:00:00 2001 From: Jake Holland Date: Tue, 17 Jun 2025 13:32:52 +0100 Subject: [PATCH 5/5] fix thresholds --- tests/visual/table.spec.js | 2 +- tests/visual/text.spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/visual/table.spec.js b/tests/visual/table.spec.js index dead4272..c7c1c5a3 100644 --- a/tests/visual/table.spec.js +++ b/tests/visual/table.spec.js @@ -430,7 +430,7 @@ describe('table', function () { return runDocTest( { systemFonts: true, - failureThreshold: 0.0002, + failureThreshold: 0.002, failureThresholdType: 'percent', }, function (doc) { diff --git a/tests/visual/text.spec.js b/tests/visual/text.spec.js index 0ede5935..8b4a49ce 100644 --- a/tests/visual/text.spec.js +++ b/tests/visual/text.spec.js @@ -187,7 +187,7 @@ describe('text', function () { return runDocTest( { systemFonts: true, - failureThreshold: 0.0002, + failureThreshold: 0.002, failureThresholdType: 'percent', }, function (doc) {