obj-console
Version:
Shows JS objects in terminal with custom format in VSCode colors
86 lines (76 loc) • 3.17 kB
text/typescript
import paint from "./paint";
import { FormatOptions, defaults } from "./options";
import { formatScalar } from "./format-scalar";
import { cylceColor } from "./color-scheme";
export { AS_JSON, BRIEF, COLUMNS, COMPACT, ONE_LINE, FormatOptions, defaults } from "./options";
export { colorScheme, cylceColor } from "./color-scheme";
/** Prints object to terminal with colors and custom format */
export function objConsole(data: any, opts?: FormatOptions) {
console.log(objFormat(data, opts));
}
/** Same as objConsole() but uses `process.stdout.write()`
* instead of `console`. Intended to use in test environment
* with "mute" console */
export function objStdout(data: any, opts?: FormatOptions) {
process.stdout.write(objFormat(data, opts) + "\n");
}
/** Format object to ANSI-colored string */
export function objFormat(data: any, opts?: FormatOptions, depth = 0): string {
const localOpts = Object.assign({}, defaults, opts);
if (isScalar(data)) return formatScalar(data, localOpts);
// -- prepare ----
const { padding, maxDepth, align, maxArrayLength, keyQuote, unfoldDepth, omitEolCommas, omitBrackets } = localOpts;
if (depth > maxDepth) return paint.hex("BF360C", "...too deep", !depth);
const isLine = depth >= unfoldDepth;
const bracketsColor = cylceColor(depth);
let eol = isLine ? "" : "\n";
let bracketsPadd = "";
for (let i = depth; i; i--) bracketsPadd += padding;
if (isLine) bracketsPadd = "";
const valPadd = isLine ? "" : bracketsPadd + padding;
const eolComma = eol && omitEolCommas ? "" : ", ";
// -- Arrays ----
if (Array.isArray(data)) {
let s = omitBrackets ? "" : paint.hex(bracketsColor, "[") + eol;
for (let i = 0; i < data.length; i++) {
// if ()
s += valPadd + objFormat(data[i], opts, depth + 1);
if (i < data.length - 1) s += paint.gray(eolComma);
if (maxArrayLength && i > maxArrayLength - 2) {
s += eol + valPadd + "... overall " + data.length + " elements" + eol;
break;
}
s += eol;
}
if (!omitBrackets) s += bracketsPadd + paint.hex(bracketsColor, "]");
return s;
}
// -- Objects ----
if (typeof data === "object") {
let s = omitBrackets ? "" : paint.hex(bracketsColor, "{") + eol;
const keyMaxLen = align ? maxKeyLen(data) : 0;
const keys = Object.keys(data);
// scan key-value pairs ---------------
for (let i = 0; i < keys.length; i++) {
const k = keys[i];
const v = data[k];
s += valPadd + paint.key(keyQuote + k + keyQuote);
s += paint.gray(": ".padEnd(keyMaxLen - k.length + 2));
s += objFormat(v, opts, depth + 1);
if (i < keys.length - 1) s += paint.gray(eolComma);
s += eol;
}
if (!omitBrackets) s += bracketsPadd + paint.hex(bracketsColor, "}");
return s;
}
return "unnknown type " + typeof data + " : " + String(data);
}
/** Length of longest key in object (for alignement) */
function maxKeyLen(data: any) {
const keys = Object.keys(data);
return Math.max(...keys.map((k) => k.length));
}
/** if data is not array or object then TRUE */
function isScalar(data: any) {
return data === null || typeof data !== "object";
}