From c9307c6a9cdb997cebf81eb36cdebd2aa9af85df Mon Sep 17 00:00:00 2001 From: Ben Hollis Date: Wed, 3 May 2023 13:08:54 -0700 Subject: [PATCH] Preserve indentation with copy/paste Fixes #191 --- .vscode/launch.json | 2 +- src/jsonformatter.ts | 32 +++++++++++++++++++------------- src/viewer.css | 7 ++++++- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 2a117d4..a4417d6 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,7 +5,7 @@ "version": "0.2.0", "configurations": [ { - "type": "pwa-chrome", + "type": "chrome", "request": "launch", "name": "Launch Chrome against localhost", "url": "https://jsonplaceholder.typicode.com/users", diff --git a/src/jsonformatter.ts b/src/jsonformatter.ts index 58c29c3..a906372 100644 --- a/src/jsonformatter.ts +++ b/src/jsonformatter.ts @@ -10,7 +10,7 @@ export function jsonToHTML(json: any, uri: string) { /** Convert a whole JSON value / JSONP response into an HTML body, without title and scripts */ function jsonToHTMLBody(json: any) { - return `
${valueToHTML(json, "")}
`; + return `
${valueToHTML(json, "", 0)}
`; } /** Produce an error document for when parsing fails. */ @@ -72,15 +72,15 @@ function decorateWithSpan(value: any, className: string) { } // Convert a basic JSON datatype (number, string, boolean, null, object, array) into an HTML fragment. -function valueToHTML(value: any, path: string) { +function valueToHTML(value: any, path: string, indent: number) { const valueType = typeof value; if (value === null) { return decorateWithSpan("null", "null"); } else if (Array.isArray(value)) { - return arrayToHTML(value, path); + return arrayToHTML(value, path, indent); } else if (valueType === "object") { - return objectToHTML(value, path); + return objectToHTML(value, path, indent); } else if (valueType === "number") { return decorateWithSpan(value, "num"); } else if (valueType === "string" && value.charCodeAt(0) === 8203 && !isNaN(value.slice(1))) { @@ -101,7 +101,7 @@ function valueToHTML(value: any, path: string) { } // Convert an array into an HTML fragment -function arrayToHTML(json: any, path: string) { +function arrayToHTML(json: any, path: string, indent: number) { if (json.length === 0) { return "[ ]"; } @@ -109,7 +109,7 @@ function arrayToHTML(json: any, path: string) { let output = ""; for (let i = 0; i < json.length; i++) { const subPath = `${path}[${i}]`; - output += "
  • " + valueToHTML(json[i], subPath); + output += "
  • " + addIndent(indent + 1) + valueToHTML(json[i], subPath, indent + 1); if (i < json.length - 1) { output += ","; } @@ -117,12 +117,16 @@ function arrayToHTML(json: any, path: string) { } return ( (json.length === 0 ? "" : '') + - `[]` + `[${addIndent(indent)}]` ); } +function addIndent(indent: number) { + return `${"  ".repeat(indent)}`; +} + // Convert a JSON object to an HTML fragment -function objectToHTML(json: any, path: string) { +function objectToHTML(json: any, path: string, indent: number) { let numProps = Object.keys(json).length; if (numProps === 0) { return "{ }"; @@ -138,11 +142,11 @@ function objectToHTML(json: any, path: string) { } else { escapedProp = `"${escapedProp}"`; } - output += `
  • "${jsString( + output += `
  • ${addIndent(indent + 1)}"${jsString( prop - )}": ${valueToHTML(json[prop], subPath)}`; + )}": ${valueToHTML(json[prop], subPath, indent + 1)}`; if (numProps > 1) { output += ","; } @@ -150,7 +154,9 @@ function objectToHTML(json: any, path: string) { numProps--; } - return `{}`; + return `{${addIndent( + indent + )}}`; } // Clean up a JSON parsing error message diff --git a/src/viewer.css b/src/viewer.css index 06b6ab5..e2437cb 100644 --- a/src/viewer.css +++ b/src/viewer.css @@ -36,7 +36,7 @@ body { .collapser:before { content: "▸"; - -moz-user-select: none; + user-select: none; } .collapsible.collapsed { @@ -178,4 +178,9 @@ h1 { .errorline { background-color: rgb(32, 29, 29); } +} + +.spacer { + display: inline-block; + width: 0px; } \ No newline at end of file