From d5f8be518386d2dfa2bed6364c3ab814b46677c9 Mon Sep 17 00:00:00 2001 From: Nam Hoang Le Date: Wed, 21 Apr 2021 13:15:16 +0700 Subject: [PATCH] Horizontal borders draws wrongly --- src/drawTable.ts | 69 +++++++++++++++++----------------- src/makeConfig.ts | 10 +++-- test/drawTable.ts | 95 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 135 insertions(+), 39 deletions(-) create mode 100644 test/drawTable.ts diff --git a/src/drawTable.ts b/src/drawTable.ts index 7b6bebc..c1c038f 100644 --- a/src/drawTable.ts +++ b/src/drawTable.ts @@ -6,54 +6,53 @@ import type { TableConfig, Row, } from './types/internal'; -export default ( - rows: Row[], - columnSizeIndex: number[], - rowSpanIndex: number[], - config: TableConfig, -): string => { - const { - drawHorizontalLine, - singleLine, - } = config; +/** + * Groups mapped rows into chunks by calculated heights + */ - let output: string; - let realRowIndex: number; - let rowHeight: number; +const groupRows = (rows: Row[], rowHeights: number[], config: TableConfig): Row => { + let startIndex = 0; - const rowCount = rows.length; + return rowHeights.map((rowHeight) => { + const chunk = rows.slice(startIndex, startIndex + rowHeight).map((row) => { + return drawRow(row, config); + }).join(''); - realRowIndex = 0; + startIndex += rowHeight; - output = ''; + return chunk; + }); +}; - if (drawHorizontalLine(realRowIndex, rowCount)) { - output += drawBorderTop(columnSizeIndex, config); - } +const shouldDrawBorderJoin = (rowIndex: number, rowCount: number, config: TableConfig): boolean => { + const {singleLine, drawHorizontalLine} = config; - rows.forEach((row, index0) => { - output += drawRow(row, config); + return !singleLine && rowIndex + 1 < rowCount && drawHorizontalLine(rowIndex + 1, rowCount); +}; - if (!rowHeight) { - rowHeight = rowSpanIndex[realRowIndex]; +export default (rows: Row[], columnWidths: number[], rowHeights: number[], config: TableConfig): string => { + const { + drawHorizontalLine, + } = config; - realRowIndex++; - } + const groupedRows = groupRows(rows, rowHeights, config); + const rowCount = groupedRows.length; + let output = ''; + + if (drawHorizontalLine(0, rowCount)) { + output += drawBorderTop(columnWidths, config); + } - rowHeight--; + groupedRows.forEach((row, rowIndex) => { + output += row; - if ( - !singleLine && - rowHeight === 0 && - index0 !== rowCount - 1 && - drawHorizontalLine(realRowIndex, rowCount) - ) { - output += drawBorderJoin(columnSizeIndex, config); + if (shouldDrawBorderJoin(rowIndex, rowCount, config)) { + output += drawBorderJoin(columnWidths, config); } }); - if (drawHorizontalLine(realRowIndex, rowCount)) { - output += drawBorderBottom(columnSizeIndex, config); + if (drawHorizontalLine(rowCount, rowCount)) { + output += drawBorderBottom(columnWidths, config); } return output; diff --git a/src/makeConfig.ts b/src/makeConfig.ts index 94d1fb4..666f303 100644 --- a/src/makeConfig.ts +++ b/src/makeConfig.ts @@ -29,18 +29,20 @@ const makeColumns = (rows: Row[], columnDefault?: ColumnUserConfig): Indexable => { const maximumColumnWidthIndex = calculateMaximumColumnWidthIndex(rows); - return rows[0].map((_cell, index) => { - return { + return rows[0].reduce>((result, _cell, index) => { + result[index] = { alignment: 'left', paddingLeft: 1, paddingRight: 1, - truncate: Number.POSITIVE_INFINITY, + truncate: Number.MAX_VALUE, width: maximumColumnWidthIndex[index], wrapWord: false, ...columnDefault, ...columns?.[index], }; - }); + + return result; + }, {}); }; /** diff --git a/test/drawTable.ts b/test/drawTable.ts new file mode 100644 index 0000000..63662ea --- /dev/null +++ b/test/drawTable.ts @@ -0,0 +1,95 @@ +/* eslint-disable max-nested-callbacks */ + +import { + expect, +} from 'chai'; +import makeConfig from '../src/makeConfig'; +import table from '../src/table'; +import type { + TableConfig, +} from '../src/types/internal'; + +const data = [ + ['Lorem ipsum', 'dolor sit'], + ['amet', 'consectetur'], + ['adipiscing', 'elit'], +]; + +const basicConfig = makeConfig(data, { + columnDefault: { + width: 5, + }, +}); + +describe('drawTable', () => { + describe('drawHorizontalLine', () => { + context('only draw top and bottom borders', () => { + it('draws proper borders', () => { + const config: TableConfig = { + ...basicConfig, + drawHorizontalLine: (index, size) => { + return index === 0 || index === size; + }, + }; + + expect(table(data, config)).to.be.deep.equal(` +╔═══════╤═══════╗ +║ Lorem │ dolor ║ +║ ipsum │ sit ║ +║ amet │ conse ║ +║ │ ctetu ║ +║ │ r ║ +║ adipi │ elit ║ +║ scing │ ║ +╚═══════╧═══════╝ +`.trimLeft()); + }); + }); + + context('only draw inner borders', () => { + it('draws proper borders', () => { + const config: TableConfig = { + ...basicConfig, + drawHorizontalLine: (index, size) => { + return index > 0 && index < size; + }, + }; + + expect(table(data, config)).to.be.deep.equal(` +║ Lorem │ dolor ║ +║ ipsum │ sit ║ +╟───────┼───────╢ +║ amet │ conse ║ +║ │ ctetu ║ +║ │ r ║ +╟───────┼───────╢ +║ adipi │ elit ║ +║ scing │ ║ +`.trimLeft()); + }); + }); + + context('only draw top and next-to-last borders', () => { + it('draws proper borders', () => { + const config: TableConfig = { + ...basicConfig, + drawHorizontalLine: (index, size) => { + return index === 0 || index === size - 1; + }, + }; + + expect(table(data, config)).to.be.deep.equal(` +╔═══════╤═══════╗ +║ Lorem │ dolor ║ +║ ipsum │ sit ║ +║ amet │ conse ║ +║ │ ctetu ║ +║ │ r ║ +╟───────┼───────╢ +║ adipi │ elit ║ +║ scing │ ║ +`.trimLeft()); + }); + }); + }); +});