summaryrefslogtreecommitdiff
path: root/node_modules/as-table/as-table.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/as-table/as-table.js')
-rw-r--r--node_modules/as-table/as-table.js89
1 files changed, 89 insertions, 0 deletions
diff --git a/node_modules/as-table/as-table.js b/node_modules/as-table/as-table.js
new file mode 100644
index 0000000..e529987
--- /dev/null
+++ b/node_modules/as-table/as-table.js
@@ -0,0 +1,89 @@
+"use strict";
+
+const O = Object
+ , { first, strlen } = require ('printable-characters') // handles ANSI codes and invisible characters
+ , limit = (s, n) => (first (s, n - 1) + '…')
+
+const asColumns = (rows, cfg_) => {
+
+ const
+
+ zip = (arrs, f) => arrs.reduce ((a, b) => b.map ((b, i) => [...a[i] || [], b]), []).map (args => f (...args)),
+
+ /* Convert cell data to string (converting multiline text to singleline) */
+
+ cells = rows.map (r => r.map (c => c.replace (/\n/g, '\\n'))),
+
+ /* Compute column widths (per row) and max widths (per column) */
+
+ cellWidths = cells.map (r => r.map (strlen)),
+ maxWidths = zip (cellWidths, Math.max),
+
+ /* Default config */
+
+ cfg = O.assign ({
+ delimiter: ' ',
+ minColumnWidths: maxWidths.map (x => 0),
+ maxTotalWidth: 0 }, cfg_),
+
+ delimiterLength = strlen (cfg.delimiter),
+
+ /* Project desired column widths, taking maxTotalWidth and minColumnWidths in account. */
+
+ totalWidth = maxWidths.reduce ((a, b) => a + b, 0),
+ relativeWidths = maxWidths.map (w => w / totalWidth),
+ maxTotalWidth = cfg.maxTotalWidth - (delimiterLength * (maxWidths.length - 1)),
+ excessWidth = Math.max (0, totalWidth - maxTotalWidth),
+ computedWidths = zip ([cfg.minColumnWidths, maxWidths, relativeWidths],
+ (min, max, relative) => Math.max (min, Math.floor (max - excessWidth * relative))),
+
+ /* This is how many symbols we should pad or cut (per column). */
+
+ restCellWidths = cellWidths.map (widths => zip ([computedWidths, widths], (a, b) => a - b))
+
+ /* Perform final composition. */
+
+ return zip ([cells, restCellWidths], (a, b) =>
+ zip ([a, b], (str, w) => (w >= 0)
+ ? (cfg.right ? (' '.repeat (w) + str) : (str + ' '.repeat (w)))
+ : (limit (str, strlen (str) + w))).join (cfg.delimiter))
+}
+
+const asTable = cfg => O.assign (arr => {
+
+/* Print arrays */
+
+ if (arr[0] && Array.isArray (arr[0])) {
+ return asColumns (arr.map (r => r.map (
+ (c, i) => (c === undefined) ? '' : cfg.print (c, i)
+ )
+ ),
+ cfg).join ('\n')
+ }
+
+/* Print objects */
+
+ const colNames = [...new Set ([].concat (...arr.map (O.keys)))],
+ columns = [colNames.map (cfg.title),
+ ...arr.map (o => colNames.map (
+ key => (o[key] === undefined) ? '' : cfg.print (o[key], key)
+ )
+ )
+ ],
+ lines = asColumns (columns, cfg)
+
+ return (cfg.dash ? [lines[0], cfg.dash.repeat (strlen (lines[0])), ...lines.slice (1)] : lines).join ('\n')
+
+}, cfg, {
+
+ configure: newConfig => asTable (O.assign ({}, cfg, newConfig)),
+})
+
+module.exports = asTable ({
+
+ maxTotalWidth: Number.MAX_SAFE_INTEGER,
+ print: String,
+ title: String,
+ dash: '-',
+ right: false
+})