Skip to content

Commit

Permalink
refactor: share drawing logic (#162)
Browse files Browse the repository at this point in the history
Co-authored-by: Nam Hoang Le <nam.hoang.le@mgm-tp.com>
  • Loading branch information
nam-hle and nhle-mgmtp authored Apr 24, 2021
1 parent 1b56b29 commit 366e380
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 75 deletions.
10 changes: 8 additions & 2 deletions src/drawBorder.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import drawHorizontalContent from './drawHorizontalContent';
import drawContent from './drawContent';
import type {
DrawVerticalLine,
} from './types/api';
Expand All @@ -17,11 +17,17 @@ type Separator = {

const drawBorder = (columnSizeIndex: number[],
config: {separator: Separator, drawVerticalLine: DrawVerticalLine, }): string => {
const {separator, drawVerticalLine} = config;
const columns = columnSizeIndex.map((size) => {
return config.separator.body.repeat(size);
});

return drawHorizontalContent(columns, config);
return drawContent(columns, {
drawSeparator: drawVerticalLine,
endSeparator: separator.right,
middleSeparator: separator.join,
startSeparator: separator.left,
}) + '\n';
};

const drawBorderTop = (columnSizeIndex: number[],
Expand Down
35 changes: 35 additions & 0 deletions src/drawContent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
type SeparatorConfig = {
drawSeparator: (index: number, size: number) => boolean,
startSeparator: string,
middleSeparator: string,
endSeparator: string,
};

/**
* Shared function to draw horizontal borders, rows or the entire table
*/

export default function drawContent (contents: string[], separatorConfig: SeparatorConfig): string {
const {startSeparator, middleSeparator, endSeparator, drawSeparator} = separatorConfig;
const contentSize = contents.length;
const result: string[] = [];

if (drawSeparator(0, contentSize)) {
result.push(startSeparator);
}

contents.forEach((content, index) => {
result.push(content);

// Only append the middle separator if the content is not the last
if (index + 1 < contentSize && drawSeparator(index + 1, contentSize)) {
result.push(middleSeparator);
}
});

if (drawSeparator(contentSize, contentSize)) {
result.push(endSeparator);
}

return result.join('');
}
32 changes: 0 additions & 32 deletions src/drawHorizontalContent.ts

This file was deleted.

19 changes: 9 additions & 10 deletions src/drawRow.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import drawHorizontalContent, {
} from './drawHorizontalContent';
import drawContent from './drawContent';
import type {
DrawVerticalLine,
} from './types/api';
Expand All @@ -11,12 +10,12 @@ export default (row: Row, config: {
border: BodyBorderConfig,
drawVerticalLine: DrawVerticalLine,
}): string => {
return drawHorizontalContent(row, {
...config,
separator: {
join: config.border.bodyJoin,
left: config.border.bodyLeft,
right: config.border.bodyRight,
},
});
const {border, drawVerticalLine} = config;

return drawContent(row, {
drawSeparator: drawVerticalLine,
endSeparator: border.bodyRight,
middleSeparator: border.bodyJoin,
startSeparator: border.bodyLeft,
}) + '\n';
};
51 changes: 20 additions & 31 deletions src/drawTable.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
drawBorderTop, drawBorderJoin, drawBorderBottom,
} from './drawBorder';
import drawContent from './drawContent';
import drawRow from './drawRow';
import type {
TableConfig, Row,
Expand All @@ -10,56 +11,44 @@ import type {
* Group the array into sub-arrays by sizes.
*
* @example
* chunkBySizes(['a', 'b', 'c', 'd', 'e'], [2, 1, 2]) = [ ['a', 'b'], ['c'], ['d', 'e'] ]
* groupBySizes(['a', 'b', 'c', 'd', 'e'], [2, 1, 2]) = [ ['a', 'b'], ['c'], ['d', 'e'] ]
*/

const groupBySizes = <T>(array: T[], sizes: number[]): T[][] => {
let startIndex = 0;

return sizes.map((rowHeight) => {
const chunk = array.slice(startIndex, startIndex + rowHeight);
return sizes.map((size) => {
const group = array.slice(startIndex, startIndex + size);

startIndex += rowHeight;
startIndex += size;

return chunk;
return group;
});
};

const shouldDrawBorderJoin = (rowIndex: number, rowCount: number, config: TableConfig): boolean => {
const {singleLine, drawHorizontalLine} = config;

return !singleLine && rowIndex + 1 < rowCount && drawHorizontalLine(rowIndex + 1, rowCount);
};

export default (rows: Row[], columnWidths: number[], rowHeights: number[], config: TableConfig): string => {
const {
drawHorizontalLine,
singleLine,
} = config;

const groupedRows = groupBySizes(rows, rowHeights).map((group) => {
const contents = groupBySizes(rows, rowHeights).map((group) => {
return group.map((row) => {
return drawRow(row, config);
}).join('');
});

const rowCount = groupedRows.length;
let output = '';

if (drawHorizontalLine(0, rowCount)) {
output += drawBorderTop(columnWidths, config);
}

groupedRows.forEach((row, rowIndex) => {
output += row;

if (shouldDrawBorderJoin(rowIndex, rowCount, config)) {
output += drawBorderJoin(columnWidths, config);
}
return drawContent(contents, {
drawSeparator: (index, size) => {
// Top/bottom border
if (index === 0 || index === size) {
return drawHorizontalLine(index, size);
}

return !singleLine && drawHorizontalLine(index, size);
},
endSeparator: drawBorderBottom(columnWidths, config),
middleSeparator: drawBorderJoin(columnWidths, config),
startSeparator: drawBorderTop(columnWidths, config),
});

if (drawHorizontalLine(rowCount, rowCount)) {
output += drawBorderBottom(columnWidths, config);
}

return output;
};

0 comments on commit 366e380

Please sign in to comment.