Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 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 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 3x 3x 1x 1x 1x 1x 3x 9x 9x 9x 9x 9x 9x 9x 9x 9x 3x 1x 1x 1x 1x 3x 3x 1x 1x 12x 12x 12x 12x 12x 12x 12x 12x 12x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x | type CellFormatter = (str: string, rowIndex: number, colIndex: number) => any
export interface AlignedTextTableOptions {
alignRight?: boolean
maxCharactersPerColumn?: number
maxCharactersPerLine?: number
}
// Output a pretty table for consles
export const toAlignedTextTable = (
headerSlugs: string[],
rows: any[],
options: AlignedTextTableOptions = {}
): string => {
const {
alignRight = true,
maxCharactersPerColumn = 20,
maxCharactersPerLine = 80,
} = options
// Set initial column widths
const colWidths = headerSlugs.map((slug) =>
slug.length > maxCharactersPerColumn
? maxCharactersPerColumn
: slug.length
)
// Expand column widths if needed
rows.forEach((row) => {
headerSlugs.forEach((slug, index) => {
const cellValue = row[slug]
if (!cellValue) return
const length = cellValue.toString().length
if (length > colWidths[index])
colWidths[index] =
length > maxCharactersPerColumn
? maxCharactersPerColumn
: length
})
})
// Drop columns if they exceed the max line width
let runningWidth = 0
const finalHeaderSlugs = headerSlugs.filter((slug, index) => {
runningWidth = runningWidth + colWidths[index]
if (runningWidth <= maxCharactersPerLine) return true
return false
})
const cellFn = (cellText = "", row: number, col: number) => {
const width = colWidths[col]
// Strip newlines in fixedWidth output
const cellValue = cellText?.toString().replace(/\n/g, "\\n") || ""
const cellLength = cellValue.length
if (cellLength > width) return cellValue.substr(0, width - 3) + "..."
const padding = " ".repeat(width - cellLength)
return alignRight ? padding + cellValue : cellValue + padding
}
return (
(finalHeaderSlugs.length !== headerSlugs.length
? `Showing ${finalHeaderSlugs.length} of ${headerSlugs.length} columns\n`
: "") + toDelimited(" ", finalHeaderSlugs, rows, cellFn)
)
}
export const toMarkdownTable = (
slugs: string[],
rows: any[],
formatFn?: CellFormatter
): string =>
[
slugs,
slugs.map(() => "-"),
...rows.map((row) => slugs.map((slug) => row[slug])),
]
.map((row, rowIndex) => {
const formattedValues = row.map((val, colIndex) =>
formatFn ? formatFn(val, rowIndex, colIndex) : val
)
return `|${formattedValues.join("|")}|`
})
.join("\n")
export const toDelimited = (
delimiter: string,
columnSlugs: string[],
rows: any[],
cellFn?: CellFormatter,
rowDelimiter = "\n"
): string => {
const skipHeaderRow = 1
const header = columnSlugs.map((columnName, index) =>
cellFn ? cellFn(columnName, 0, index) : columnName
)
const formattedRows = rows.map((row, rowNumber) =>
columnSlugs.map((slug, columnIndex) =>
cellFn
? cellFn(row[slug], rowNumber + skipHeaderRow, columnIndex)
: row[slug]
)
)
return (
header.join(delimiter) +
rowDelimiter +
formattedRows.map((row) => row.join(delimiter)).join(rowDelimiter)
)
}
|