// data types function nullV() { return 'null'; } function boolV(val) { return '' + html(val) + ''; } function numV(val) { return '' + html(val) + ''; } function stringV(val) { return '"' + jstr(val) + '"'; } function linkV(val) { return '"' + jstr(val) + '"'; } function propK(key) { return '"' + jstr(key) + '"'; } function wrapJSONP(callback, json, suffix) { return `${callback}(${json})${suffix}`; } function errorPage(error, json) { return '

Error parsing JSON:
' + error + '

Content:

' + html(json) + '
'; } // helper function indent(nl, level) { return nl ? nl + '  '.repeat(level) : ''; } function jstr(s) { return html(JSON.stringify(s).slice(1, -1)); } function html(s) { return (s + '').replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>'); } // formatter entry point function init() { document.body.innerHTML = parse(document.getElementById('json').textContent); } function parse(raw) { let data = raw, callback = '', suffix = ''; // matches "callback({json});" ... original had \s -> [\s\u200B\uFEFF] let match = /^\s*([\w$\[\]\.]+)\s*\(\s*([\[{][\s\S]*[\]}])\s*\)([\s;]*)$/m.exec(raw); if (match && match.length === 4) { callback = match[1]; data = match[2]; suffix = match[3].replace(/[^;]+/g, ''); } try { let root = nested(JSON.parse(data), 0, '
'); if (callback) return wrapJSONP(callback, root, suffix); return root; } catch (e) { return errorPage(e, raw); } } function nested(val, level, nl) { if (null === val) return nullV(); switch (typeof val) { case 'boolean': return boolV(val); case 'number': return numV(val); case 'string': return (/^(\w+):\/\/[^\s]+$/i.test(val)) ? linkV(val) : stringV(val); case 'object': return (Array.isArray(val)) ? array(val, level + 1, nl) : dict(val, level + 1, nl); } return '<-unsupported-type->'; } function dict(dict, level, nl) { let output = ''; for (let key in dict) { if (output) output += indent(',
', level); output += propK(key) + ': ' + nested(dict[key], level, '
'); } if (!output) return '{}'; return '{' + foldableContent(output, level, nl) + '}'; } function array(arr, level, nl) { let output = ''; for (let i = 0; i < arr.length; i++) { if (i > 0) output += indent(',
', level); output += nested(arr[i], level, '
'); } if (!output) return '[]'; return '[' + foldableContent(output, level, nl) + ']'; } // foldable content function foldableContent(output, level, nl) { let collapsible = ''; return collapsible + '' + indent(nl, level) + output + indent('
', level - 1) + '
' + collapsible } function fold(sender) { let folder = sender.parentNode; folder.classList.toggle('closed'); } function highlight(sender, show) { let folder = sender.parentNode; show ? folder.classList.add('highlight') : folder.classList.remove('highlight'); }