๐พTableMaker
custom โฉ class โฉ TableMaker
print a table for 2D array of strings (with column settings, optional icons, separators).
replit๏ผ TableMaker (with separators)
const {log} = console;
// โญ TableMaker
class TableMaker {
// โข โญ data : 2D array of strings
// โข โญ columns: column settings (array of [header, align])
// โข table settings: ({spacing: 3, icon: null})
constructor(data, columns, {
spacing = 3, // โญ between columns
padding = 0, // โญ inside column
maxStringLength = 24,
icon = null, // โญ choose icon for each row (function)
iconDescription = `<icon description here>`,
} = {}) {
this.data = data;
this.columnSettings = columns;
this.spacing = spacing;
this.padding = padding;
this.maxStringLength = maxStringLength;
this.icon = icon;
this.iconDescription = iconDescription;
// number of rows/cols (header not included)
this.rows = this.data.length; // โ may include separators
this.cols = this.columnSettings.length;
// truncate strings if needed
this._truncateData();
// init column widths
this._calculateColumnWidths(); // this._widths
// convert data rows to lines
// โญ (1st pass) this.divider still undefined
this._convertDataToLines(); // this._lines
// setup divider
const w = this._lines[0].length;
this.divider = 'โ'.repeat(w+1);
// convert data rows to lines
// โญ (2nd pass) this.divider is defined!
this._convertDataToLines(); // this._lines
}
// truncate data string if needed
_truncateData() {
for (let row of this.data) {
if (row === '---') continue; // skip separator
const max = this.maxStringLength;
for(let [j, s] of row.entries()) {
if (j >= this.cols) break; // skip extra values
if (s.length > max) row[j] = s.slice(0, max-4) + `...`;
}
}
}
// calculate width of every column
_calculateColumnWidths() {
// header widths first
let widths = this.columnSettings.map(s => s[0].length);
// iterate over rows
for (const row of this.data) {
if (row === '---') continue; // โ skip separators
for (const [j, s] of row.entries()) {
if (j >= this.cols) break; // โ extra values ignored
const len = s.length;
if (len > widths[j]) widths[j] = len;
}
}
this._widths = widths;
}
// align text with `width`, `align`
_alignText(text, width, align = TableMaker.align.left) {
let result;
// truncate text if needed
const max = this.maxStringLength;
if (text.length > max) text = text.slice(0, max-3) + '...';
switch (align) {
case TableMaker.align.left:
result = text.padEnd(width, ' ');
break;
case TableMaker.align.right:
result = text.padStart(width, ' ');
break;
case TableMaker.align.center:
const len = text.length;
const padstart = Math.floor((width - len) / 2);
const padend = width - padstart - len;
result = ' '.repeat(padstart) + text + ' '.repeat(padend);
break;
default:
result = text.padEnd(width, ' ');
}
return result;
}
// convert data rows to lines
_convertDataToLines() {
this._lines = this.data.map(row => this._rowToString(row));
}
// data row -> string (with/out icon)
_rowToString(row) {
if (row === '---') return this.divider; // โ separator
const pad = ' '.repeat(this.padding);
const spaces = ' '.repeat(this.spacing);
const rowIcon = this.icon ?. (row);
return (rowIcon ? rowIcon + ' ' : '') + row
.slice(0, this.cols) // โ extra values ignored
.map((v, j) => pad
+ this._alignText(v, this._widths[j], this.columnSettings[j][1])
+ pad
)
.join(spaces);
}
// header row -> string
_header() {
const pad = ' '.repeat(this.padding);
const spaces = ' '.repeat(this.spacing);
const iconPad = this.icon ? `โโโ ${this.iconDescription}\nโ\nโ ` : '';
const row = this.columnSettings.map(s => s[0]);
return iconPad + row
.map((v, j) => pad
+ this._alignText(v, this._widths[j])
+ pad)
.join(spaces);
}
// table -> string
toString() {
const divider = this.divider;
log(`table width: ${divider.length}`);
return this._header() + '\n'
+ divider + '\n'
+ this._lines.join('\n') + '\n'
+ divider + '\n';
}
// print to console
print() {
console.log(this.toString());
}
}
// column alignment
TableMaker.align = {
left: 0, center: 1, right: 2,
dot: 3, // not implemented (may have bugs)
};
// icons
TableMaker.icon = {
diamond: '๐ธ',
star : 'โญ๏ธ',
check : 'โ
',
cross : 'โ',
};
// export
module.exports = { TableMaker };
replit๏ผ TableMaker (with separators)
const {log} = console;
const { testCases } = require('./testCases.js');
const { isPrimitive } = require('./helpers/isObject.js');
const { TableMaker } = require('./helpers/TableMaker.js');
// โญ data (with extra `value`)
const data = testCases.map(testcase => {
if (testcase === '---') return '---';
// test cases: [value, expr, desc]
const value = testcase[0];
const expr = testcase[1] || String(value);
const desc = testcase[2] || '';
const toNum = String(+value);
const toStr = `"${String(value)}"`;
// [expr, desc, num, str, value] (extra `value` is for icon chooser)
return [ expr, desc, toNum, toStr, value];
})
// โญ column settings (4 columns)
const columns = [
['value', ],
['desc', ],
['-> number', TableMaker.align.right],
['-> string', ],
];
// โญ icon chooser
const icon = (row) => isPrimitive(row[4]) ? 'โ
' : 'โ';
// โญ TableMaker
const table = new TableMaker(data, columns, {
icon: icon,
iconDescription: '(primitive?)'
});
table.print();
๐ ็ตๆ๏ผ
โโโ (primitive?)
โ
โ value desc -> number -> string
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
null 0 "null"
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
undefined NaN "undefined"
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
0 0 "0"
โ
Infinity Infinity "Infinity"
โ
NaN NaN "NaN"
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
"" empty str 0 ""
โ
"1.2" numeric 1.2 "1.2"
โ
"one" non-numeric NaN "one"
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
true 1 "true"
โ
false 0 "false"
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ {a:1} NaN "[object Object]"
โ [] empty arr 0 ""
โ [6] one numeric 6 "6"
โ ['a'] any other NaN "a"
โ new Date 1667313821772 "Tue Nov 01 2022 14:...
โ /regex/ NaN "/regex/"
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ () => {} NaN "() => {}"
โ class {} NaN "class {}"
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Last updated