diff --git a/src/layout-manager.js b/src/layout-manager.js index 3937452..ecafaf9 100644 --- a/src/layout-manager.js +++ b/src/layout-manager.js @@ -88,14 +88,19 @@ const { ColSpanCell, RowSpanCell } = Cell; } function addRowSpanCells(table) { - table.forEach(function (row, rowIndex) { + table.forEach(function (row) { row.forEach(function (cell) { for (let i = 1; i < cell.rowSpan; i++) { let rowSpanCell = new RowSpanCell(cell); + const line = cell.y + i; rowSpanCell.x = cell.x; - rowSpanCell.y = cell.y + i; + rowSpanCell.y = line; rowSpanCell.colSpan = cell.colSpan; - insertCell(rowSpanCell, table[rowIndex + i]); + if (!table[line]) { + const { x, y } = rowSpanCell; + warn(`${x}-${y}: Expected empty array for row ${line - 1} (line ${line}).`); + } + insertCell(rowSpanCell, table[rowSpanCell.y] || []); } }); }); @@ -110,7 +115,7 @@ const { ColSpanCell, RowSpanCell } = Cell; let colSpanCell = new ColSpanCell(); colSpanCell.x = cell.x + k; colSpanCell.y = cell.y; - cellColumns.splice(columnIndex + 1, 0, colSpanCell); + cellColumns.splice(colSpanCell.x, 0, colSpanCell); } } } @@ -146,7 +151,7 @@ const { ColSpanCell, RowSpanCell } = Cell; cell.x = opts.x; cell.y = opts.y; warn(`Missing cell at ${cell.y}-${cell.x}.`); - insertCell(cell, table[y]); + insertCell(cell, table[y] || []); } } } diff --git a/test/issues/296-test.js b/test/issues/296-test.js new file mode 100644 index 0000000..28fc71a --- /dev/null +++ b/test/issues/296-test.js @@ -0,0 +1,33 @@ +const Table = require('../..'); + +/** + * This test doesn't actually fail it never completes. I could not find a method + * to get the infinite loop to timeout within the test. Not sure how GHA will + * handle this. + */ +test('it should not loop infinitely with invalid table data', async () => { + const table = new Table(); + table.push( + [ + { content: 'A', colSpan: 2 }, + { content: 'B', rowSpan: 3 }, + ], + [], + [{ content: 'C', colSpan: 3 }] + ); + expect(() => table.toString()).not.toThrow(); +}); + +test('it should not error on invalid table data', () => { + const table = new Table({ debug: true }); + table.push( + [ + { content: 'A', colSpan: 2 }, + { content: 'B', rowSpan: 3 }, + ], + [{ content: 'C', colSpan: 3 }] + ); + expect(() => table.toString()).not.toThrow(); + // This expectation can be dropped if the expectation in the code changes + expect(table.messages).toContain('2-2: Expected empty array for row 1 (line 2).'); +});