-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrenderRows.ts
52 lines (42 loc) · 1.25 KB
/
renderRows.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import type { Cell } from './types.js'
import { renderCell } from './renderCell.js'
import { getCellWidth } from './getCellWidth.js'
export function renderRows(
rows: Cell[][],
maxWidth: number,
): string {
const targetWidths = getTargetWidths(rows, maxWidth)
return rows
.map(row => row.map((cell, idx) => renderCell(cell, targetWidths[idx])).join(''))
.join('\n')
}
function getTargetWidths(
rows: Cell[][],
maxWidth: number,
): number[] {
const availableWidth = maxWidth
const columnWidths = getColumnWidths(rows)
while (isOverflowing(columnWidths, availableWidth))
shrinkWidestColumn(columnWidths)
return columnWidths
}
function getColumnWidths(rows: Cell[][]): number[] {
const result: number[] = []
rows.forEach(row => row.forEach((cell, cellIdx) => {
result[cellIdx] = Math.max(result[cellIdx] ?? 0, getCellWidth(cell))
}))
return result
}
function isOverflowing(
widths: number[],
availableWidth: number,
): boolean {
return widths.reduce((a, b) => a + b, 0) > availableWidth
}
function shrinkWidestColumn(
widths: number[],
): void {
const max = widths.reduce((a, b) => Math.max(a, b), 0)
const idx = widths.indexOf(max)
widths[idx] -= 1
}