Skip to content

Commit

Permalink
Handle non JSON-serializable properties
Browse files Browse the repository at this point in the history
  • Loading branch information
rtoal committed Jan 15, 2024
1 parent 81d189e commit bf8ccf9
Showing 1 changed file with 14 additions and 7 deletions.
21 changes: 14 additions & 7 deletions stringify.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,19 @@ export default function stringify(root) {
let lines = []

function view(e) {
if (e === null || typeof e !== "object") return JSON.stringify(e)
if (e.constructor === Function) return "<Function>"
if (e.constructor === BigInt) return e
if (e.type) return e.type
return e.constructor.name
// This local function will never be called with an object. We can
// usually use JSON.stringify, but not always. There are a few special
// cases to handle.
if (typeof e === "function") return "<Function>"
if (typeof e === "symbol") return e.valueOf()
if (typeof e == "bigint") return e
return JSON.stringify(e)
}

function ast(node, indent = 0, prefix = "") {
if (node === null || typeof node !== "object") return

// Esprima's type field is much nicer than the node's constructor name.
let type = node?.type ?? node.constructor.name
let simpleProps = {}
let objectProps = {}
Expand All @@ -20,6 +23,10 @@ export default function stringify(root) {
else simpleProps[k] = v
}

// We want to print the simple properties first, then the object properties.
// Let's keep the display rather light, eliding the display of many of the
// falses and nulls that are basically default cases. Also we don't want to
// show the type field since we're using that at the beginning of a line.
simpleProps = Object.entries(simpleProps)
.filter(([k, v]) => k !== "type" || v !== type)
.filter(
Expand All @@ -41,10 +48,10 @@ export default function stringify(root) {
)
.map(([k, v]) => `<span class='key'>${k}</span>=${view(v)}`)

// Show the line for the current object with its simple properties, then
// for each object property, show them indented on following lines.
let line = `${" ".repeat(indent)}<span class='key'>${prefix}</span>`
if (prefix) line += ": "
line += `<strong>${type}</strong> ${simpleProps.join(" ")}`
lines.push(`<div style='margin-left:${indent * 20}px'>${line}</div>`)
for (let [k, v] of Object.entries(objectProps)) {
if (Array.isArray(v)) {
for (let [i, e] of v.entries()) {
Expand Down

0 comments on commit bf8ccf9

Please # to comment.