-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsimple.ts
More file actions
86 lines (76 loc) · 2.41 KB
/
simple.ts
File metadata and controls
86 lines (76 loc) · 2.41 KB
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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/**
* @fileoverview Borderless table renderer — columns separated by
* two spaces, header underlined with `─`. Lighter weight than
* `formatTable` (no box-drawing characters); the right choice when
* the surface is rendering to a context that doesn't reliably
* support box-drawing glyphs.
*/
import colors from '../external/yoctocolors-cjs'
import { ArrayPrototypePush } from '../primordials/array'
import { MathMax } from '../primordials/math'
import { displayWidth, padText } from './padding'
import type { TableColumn } from './types'
/**
* Format data as a simple table without borders.
* Lighter weight alternative to formatTable().
*
* @param data - Array of data objects
* @param columns - Column configuration
* @returns Formatted table string
*
* @example
* import { formatSimpleTable } from '@socketsecurity/lib/tables/simple'
* import colors from 'yoctocolors-cjs'
*
* const data = [
* { name: 'lodash', version: '4.17.21' },
* { name: 'react', version: '18.2.0' },
* ]
* const columns = [
* { key: 'name', header: 'Package' },
* { key: 'version', header: 'Version' },
* ]
* console.log(formatSimpleTable(data, columns))
* // Output:
* // Package Version
* // ─────── ───────
* // lodash 4.17.21
* // react 18.2.0
*/
export function formatSimpleTable(
data: Array<Record<string, unknown>>,
columns: TableColumn[],
): string {
if (data.length === 0) {
return '(no data)'
}
// Calculate column widths
const widths = columns.map(col => {
const headerWidth = displayWidth(col.header)
const maxDataWidth = MathMax(
...data.map(row => displayWidth(String(row[col.key] ?? ''))),
)
return col.width ?? MathMax(headerWidth, maxDataWidth)
})
const lines: string[] = []
// Header row
const headerCells = columns.map((col, i) =>
padText(colors.bold(col.header), widths[i] as number, col.align),
)
ArrayPrototypePush(lines, headerCells.join(' '))
// Header separator
const separators = widths.map(w => colors.dim('─'.repeat(w)))
ArrayPrototypePush(lines, separators.join(' '))
// Data rows
for (const row of data) {
const cells = columns.map((col, i) => {
let value = String(row[col.key] ?? '')
if (col.color) {
value = col.color(value)
}
return padText(value, widths[i] as number, col.align)
})
ArrayPrototypePush(lines, cells.join(' '))
}
return lines.join('\n')
}