const MAX_JSON_TREE_DEPTH = 8;
function escapeHtml(text) {
return String(text)
.replaceAll('&', '&')
.replaceAll('<', '<')
.replaceAll('>', '>')
.replaceAll('"', '"')
.replaceAll("'", ''');
}
export function renderJsonTree(value, depth = 0) {
if (depth > MAX_JSON_TREE_DEPTH) {
return `<span class="json-scalar json-string">"…"</span>`;
}
if (value === null) {
return `<span class="json-scalar json-null">null</span>`;
}
if (typeof value === 'boolean') {
return `<span class="json-scalar json-boolean">${value}</span>`;
}
if (typeof value === 'number') {
return `<span class="json-scalar json-number">${value}</span>`;
}
if (typeof value === 'string') {
return `<span class="json-scalar json-string">${escapeHtml(JSON.stringify(value))}</span>`;
}
if (Array.isArray(value)) {
if (value.length === 0) return `<span class="json-scalar">[ ]</span>`;
return `<div class="json-tree-array">${value.map((item, i) => {
const isObj = item !== null && typeof item === 'object';
if (isObj) {
const isOpen = depth < 2 ? ' open' : '';
return `<details class="json-tree-node"${isOpen}><summary class="json-tree-summary"><span class="json-tree-key json-tree-idx">[${i}]</span></summary><div class="json-tree-children">${renderJsonTree(item, depth + 1)}</div></details>`;
}
return `<div class="json-tree-leaf"><span class="json-tree-key json-tree-idx">[${i}]</span><span class="json-tree-sep">: </span>${renderJsonTree(item, depth + 1)}</div>`;
}).join('')}</div>`;
}
const keys = Object.keys(value);
if (keys.length === 0) return `<span class="json-scalar">{ }</span>`;
return `<div class="json-tree-obj">${keys.map(k => {
const v = value[k];
const isObj = v !== null && typeof v === 'object';
const keyHtml = `<span class="json-tree-key">${escapeHtml(k)}</span>`;
if (isObj) {
const isOpen = depth < 2 ? ' open' : '';
return `<details class="json-tree-node"${isOpen}><summary class="json-tree-summary">${keyHtml}</summary><div class="json-tree-children">${renderJsonTree(v, depth + 1)}</div></details>`;
}
return `<div class="json-tree-leaf">${keyHtml}<span class="json-tree-sep">: </span>${renderJsonTree(v, depth + 1)}</div>`;
}).join('')}</div>`;
}