Skip to content

Commit c049ac6

Browse files
committed
fix for missing table cells in incomplete tables
#282
1 parent 6336d9b commit c049ac6

File tree

3 files changed

+51
-17
lines changed

3 files changed

+51
-17
lines changed

.eslintrc.cjs

+1-1
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ module.exports = {
9090
'max-lines-per-function': ['error', 80],
9191
'max-nested-callbacks': ['error', 4],
9292
'max-params': ['error', 6],
93-
'max-statements': ['error', 35],
93+
'max-statements': ['error', 41],
9494
'max-statements-per-line': ['error', { 'max': 2 }],
9595
'multiline-ternary': ['error', 'always-multiline'],
9696
'newline-per-chained-call': ['error', { 'ignoreChainWithDepth': 3 }],

packages/html-to-text/src/table-printer.js

+33-16
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@ function transposeInPlace (matrix, maxSize) {
1818
const rowI = getRow(matrix, i);
1919
for (let j = 0; j < i; j++) {
2020
const rowJ = getRow(matrix, j);
21-
const temp = rowI[j];
22-
rowI[j] = rowJ[i];
23-
rowJ[i] = temp;
21+
if (rowI[j] || rowJ[i]) {
22+
const temp = rowI[j];
23+
rowI[j] = rowJ[i];
24+
rowJ[i] = temp;
25+
}
2426
}
2527
}
2628
}
@@ -34,10 +36,17 @@ function putCellIntoLayout (cell, layout, baseRow, baseCol) {
3436
}
3537
}
3638

39+
function getOrInitOffset (offsets, index) {
40+
if (offsets[index] === undefined) {
41+
offsets[index] = (index === 0) ? 0 : 1 + getOrInitOffset(offsets, index - 1);
42+
}
43+
return offsets[index];
44+
}
45+
3746
function updateOffset (offsets, base, span, value) {
3847
offsets[base + span] = Math.max(
39-
offsets[base + span] || 0,
40-
offsets[base] + value
48+
getOrInitOffset(offsets, base + span),
49+
getOrInitOffset(offsets, base) + value
4150
);
4251
}
4352

@@ -82,19 +91,27 @@ function tableToString (tableRows, rowSpacing, colSpacing) {
8291
for (let x = 0; x < colNumber; x++) {
8392
let y = 0;
8493
let cell;
85-
while (y < rowNumber && (cell = layout[x][y])) {
86-
if (!cell.rendered) {
87-
let cellWidth = 0;
88-
for (let j = 0; j < cell.lines.length; j++) {
89-
const line = cell.lines[j];
90-
const lineOffset = rowOffsets[y] + j;
91-
outputLines[lineOffset] = (outputLines[lineOffset] || '').padEnd(colOffsets[x]) + line;
92-
cellWidth = (line.length > cellWidth) ? line.length : cellWidth;
94+
const rowsInThisColumn = Math.min(rowNumber, layout[x].length);
95+
while (y < rowsInThisColumn) {
96+
cell = layout[x][y];
97+
if (cell) {
98+
if (!cell.rendered) {
99+
let cellWidth = 0;
100+
for (let j = 0; j < cell.lines.length; j++) {
101+
const line = cell.lines[j];
102+
const lineOffset = rowOffsets[y] + j;
103+
outputLines[lineOffset] = (outputLines[lineOffset] || '').padEnd(colOffsets[x]) + line;
104+
cellWidth = (line.length > cellWidth) ? line.length : cellWidth;
105+
}
106+
updateOffset(colOffsets, x, cell.colspan, cellWidth + colSpacing);
107+
cell.rendered = true;
93108
}
94-
updateOffset(colOffsets, x, cell.colspan, cellWidth + colSpacing);
95-
cell.rendered = true;
109+
y += cell.rowspan;
110+
} else {
111+
const lineOffset = rowOffsets[y];
112+
outputLines[lineOffset] = (outputLines[lineOffset] || '');
113+
y++;
96114
}
97-
y += cell.rowspan;
98115
}
99116
}
100117

packages/html-to-text/test/tags.js

+17
Original file line numberDiff line numberDiff line change
@@ -869,6 +869,23 @@ describe('tags', function () {
869869
expect(htmlToText(html, options)).to.equal(expected);
870870
});
871871

872+
it('should not miss content in tables with variable number of cells per row', function () {
873+
const html = `
874+
<table>
875+
<tr><td>a</td></tr>
876+
<tr><td>b</td><td>c</td></tr>
877+
<tr></tr>
878+
<tr><td>d</td></tr>
879+
</table>`;
880+
const expected = 'a\nb c\n\nd';
881+
const options = {
882+
selectors: [
883+
{ selector: 'table', format: 'dataTable' }
884+
]
885+
};
886+
expect(htmlToText(html, options)).to.equal(expected);
887+
});
888+
872889
});
873890

874891
describe('custom formatting', function () {

0 commit comments

Comments
 (0)