display = {
function display(v) {
return div({ class: 'reset' }, displayValue(v, new Set()));
}
function displayValue(v, refs) {
if (refs.has(v)) {
return displayCircular(v);
}
if (isPrimitive(v)) {
return displayPrimitive(v);
}
if (isFunction(v)) {
return displayFunction(v);
}
refs.add(v);
if (isArray(v)) {
return displayArray(v, refs);
}
if (isObject(v)) {
return displayObject(v, refs);
}
}
function displayCircular(v) {
return span({}, '⟳ Circular reference');
}
function displayObject(v, refs) {
const children = [
tr({}, th({ colspan: 2 }, v.constructor && v.constructor.name || 'Object')),
...Object.entries(v).map(([k, kv]) => tr({},
th({ scope: 'row', class: 'property-name' }, k),
td({}, displayValue(kv, refs))
))
];
return table({ class: 'object' }, ...children);
}
function displayArray(v, refs) {
const cols = getColumnNames(v);
const children = [
tr({}, th({ colspan: cols.length }, 'Array')),
tr({}, ...cols.map(c => th({ class: 'property-name' }, c))),
...v.map(i => displayRow(i, cols, refs))
];
return table({ class: 'array' }, ...children);
}
function displayRow(v, cols, refs) {
if (isObject(v)) {
return tr({},
...cols.map(c => td({}, c in v ? displayValue(v[c], refs) : ''))
);
}
return tr({}, td({ colspan: cols.length }, displayValue(v, refs)));
}
function displayFunction(v) {
return code({ class: 'function' }, `f(${v.length})`);
}
function getColumnNames(arr) {
const colSet = arr.reduce((cols, v) => {
if (isObject(v)) {
Object.keys(v).forEach(k => cols.add(k));
}
return cols;
}, new Set());
return [...colSet.keys()];
}
function displayPrimitive(v) {
switch (typeof v) {
case 'object':
return displayNull();
case 'undefined':
return displayUndefined();
case 'boolean':
return displayBoolean(v);
case 'number':
return displayNumber(v);
case 'string':
return displayString(v);
case 'bigint':
return displayBigInt(v);
case 'symbol':
return displaySymbol(v);
default:
return v;
}
}
function displaySymbol(v) {
return code({ class: 'symbol' }, v);
}
function displayBigInt(v) {
return em({}, 'BigInt(' + v + ')');
}
function displayString(v) {
return v;
}
function displayNumber(v) {
return em({}, v);
}
function displayUndefined() {
return code({}, 'undefined');
}
function displayNull() {
return code({}, 'null');
}
function displayBoolean(v) {
return code({}, v);
}
function isPrimitive(v) {
return typeof v === 'number'
|| typeof v === 'string'
|| typeof v === 'boolean'
|| typeof v === 'bigint'
|| typeof v === 'undefined'
|| typeof v === 'symbol'
|| v === null;
}
function isFunction(v) {
return typeof v === 'function';
}
function isArray(v) {
return Array.isArray(v);
}
function isObject(v) {
return typeof v === 'object';
}
return display;
}