summaryrefslogtreecommitdiff
path: root/cli/js/web/console_table.ts
diff options
context:
space:
mode:
authorBartek Iwańczuk <biwanczuk@gmail.com>2020-03-11 10:53:06 +0100
committerGitHub <noreply@github.com>2020-03-11 10:53:06 +0100
commit99a0c6df79b903e4fe72ce066787039bdede3868 (patch)
tree1c0abdb964a2e052b593dc8fa3e515f76dbc0642 /cli/js/web/console_table.ts
parent94f4c6807a34a564f567b984e71e36e9cb9c5005 (diff)
reorg: cli/js/compiler/, move more API to cli/js/web/ (#4310)
- moves compiler implementation to "cli/js/compiler/" directory - moves more APIs to "cli/js/web": * "console.ts" * "console_table.ts" * "performance.ts" * "timers.ts" * "workers.ts" - removes some dead code from "cli/js/"
Diffstat (limited to 'cli/js/web/console_table.ts')
-rw-r--r--cli/js/web/console_table.ts94
1 files changed, 94 insertions, 0 deletions
diff --git a/cli/js/web/console_table.ts b/cli/js/web/console_table.ts
new file mode 100644
index 000000000..276d77f1d
--- /dev/null
+++ b/cli/js/web/console_table.ts
@@ -0,0 +1,94 @@
+// Copyright Joyent, Inc. and other Node contributors. MIT license.
+// Forked from Node's lib/internal/cli_table.js
+
+import { TextEncoder } from "./text_encoding.ts";
+import { hasOwnProperty } from "../util.ts";
+
+const encoder = new TextEncoder();
+
+const tableChars = {
+ middleMiddle: "─",
+ rowMiddle: "┼",
+ topRight: "┐",
+ topLeft: "┌",
+ leftMiddle: "├",
+ topMiddle: "┬",
+ bottomRight: "┘",
+ bottomLeft: "└",
+ bottomMiddle: "┴",
+ rightMiddle: "┤",
+ left: "│ ",
+ right: " │",
+ middle: " │ "
+};
+
+const colorRegExp = /\u001b\[\d\d?m/g;
+
+function removeColors(str: string): string {
+ return str.replace(colorRegExp, "");
+}
+
+function countBytes(str: string): number {
+ const normalized = removeColors(String(str)).normalize("NFC");
+
+ return encoder.encode(normalized).byteLength;
+}
+
+function renderRow(row: string[], columnWidths: number[]): string {
+ let out = tableChars.left;
+ for (let i = 0; i < row.length; i++) {
+ const cell = row[i];
+ const len = countBytes(cell);
+ const needed = (columnWidths[i] - len) / 2;
+ // round(needed) + ceil(needed) will always add up to the amount
+ // of spaces we need while also left justifying the output.
+ out += `${" ".repeat(needed)}${cell}${" ".repeat(Math.ceil(needed))}`;
+ if (i !== row.length - 1) {
+ out += tableChars.middle;
+ }
+ }
+ out += tableChars.right;
+ return out;
+}
+
+export function cliTable(head: string[], columns: string[][]): string {
+ const rows: string[][] = [];
+ const columnWidths = head.map((h: string): number => countBytes(h));
+ const longestColumn = columns.reduce(
+ (n: number, a: string[]): number => Math.max(n, a.length),
+ 0
+ );
+
+ for (let i = 0; i < head.length; i++) {
+ const column = columns[i];
+ for (let j = 0; j < longestColumn; j++) {
+ if (rows[j] === undefined) {
+ rows[j] = [];
+ }
+ const value = (rows[j][i] = hasOwnProperty(column, j) ? column[j] : "");
+ const width = columnWidths[i] || 0;
+ const counted = countBytes(value);
+ columnWidths[i] = Math.max(width, counted);
+ }
+ }
+
+ const divider = columnWidths.map((i: number): string =>
+ tableChars.middleMiddle.repeat(i + 2)
+ );
+
+ let result =
+ `${tableChars.topLeft}${divider.join(tableChars.topMiddle)}` +
+ `${tableChars.topRight}\n${renderRow(head, columnWidths)}\n` +
+ `${tableChars.leftMiddle}${divider.join(tableChars.rowMiddle)}` +
+ `${tableChars.rightMiddle}\n`;
+
+ for (const row of rows) {
+ result += `${renderRow(row, columnWidths)}\n`;
+ }
+
+ result +=
+ `${tableChars.bottomLeft}${divider.join(tableChars.bottomMiddle)}` +
+ tableChars.bottomRight;
+
+ return result;
+}