From fbc53fe4482c2b30e3f7e3e829c7128beb9fcfd9 Mon Sep 17 00:00:00 2001 From: Reimar Date: Mon, 13 Oct 2025 13:37:21 +0200 Subject: [PATCH] fix errors and warnings in console --- src/index.js | 33 +++++++------- src/playground_console.js | 91 +++++++++++++++++++++++++++++---------- style.css | 21 +++++++-- 3 files changed, 102 insertions(+), 43 deletions(-) diff --git a/src/index.js b/src/index.js index d2c9332..0b44aa7 100644 --- a/src/index.js +++ b/src/index.js @@ -15,8 +15,25 @@ import { ConsoleInput } from "./console_input.js"; import { downloadFile, slugify } from "./utils.js"; import { HtmlExporter } from "./html_exporter.js"; +const editor = ace.edit("editor"); +editor.setTheme("ace/theme/gruvbox"); +editor.session.setMode("ace/mode/javascript"); + +const langTools = ace.require("ace/ext/language_tools"); + +editor.setOptions({ + enableBasicAutocompletion: true, + enableLiveAutocompletion: true, + copyWithEmptySelection: true, +}); + +langTools.setCompleters([new GamelibCompleter(), new TextCompleter()]); + +editor.setValue(sessionStorage.getItem("code") ?? editor.getValue(), -1); + const playgroundConsole = new PlaygroundConsole( document.querySelector("#console-code"), + editor, ); window.addEventListener("DOMContentLoaded", () => { @@ -47,22 +64,6 @@ globalThis.karlkoder = { }, }; -const editor = ace.edit("editor"); -editor.setTheme("ace/theme/gruvbox"); -editor.session.setMode("ace/mode/javascript"); - -const langTools = ace.require("ace/ext/language_tools"); - -editor.setOptions({ - enableBasicAutocompletion: true, - enableLiveAutocompletion: true, - copyWithEmptySelection: true, -}); - -langTools.setCompleters([new GamelibCompleter(), new TextCompleter()]); - -editor.setValue(sessionStorage.getItem("code") ?? editor.getValue(), -1); - const runButton = document.querySelector("#run-button"); const toggleSpriteEditorButton = document.querySelector("#toggle-sprite-editor-button"); const projectName = document.querySelector("#project-name"); diff --git a/src/playground_console.js b/src/playground_console.js index 05e7e8e..8a0714e 100644 --- a/src/playground_console.js +++ b/src/playground_console.js @@ -1,6 +1,33 @@ export class PlaygroundConsole { - constructor(elem) { + constructor(elem, editor) { this.elem = elem; + + // Used within error stack traces + window.gotoLine = (line, col) => { + editor.gotoLine(line, col, true); + editor.focus(); + }; + } + + #formatStacktrace(stack) { + return stack + .replaceAll(window.origin + "/", "") + .replace( + /data:text\/javascript;charset=utf-8,[^:]+:(\d+):(\d+)/, + "karlkoder-playground:$1:$2", + ); + } + + #getTypeName(arg) { + if (arg instanceof Error) { + return "error"; + } + + if (arg === null) { + return "null"; + } + + return typeof arg; } #addKeyValue(entryType, parent, property, arg) { @@ -16,12 +43,13 @@ export class PlaygroundConsole { const value = document.createElement("span"); value.className = entryType; value.textContent = argString; - value.dataset.type = arg === null ? "null" : typeof arg; + value.dataset.type = this.#getTypeName(arg); parent.appendChild(value); } #addEntry(entryType, property, parent, ...args) { for (const arg of args) { + // For objects, show a collapsed list of properties if (typeof arg === "object" && arg !== null) { const summary = document.createElement("summary"); summary.className = entryType; @@ -31,31 +59,47 @@ export class PlaygroundConsole { this.#addKeyValue(entryType, summary, property, arg); const details = document.createElement("details"); + details.className = entryType; details.style.marginLeft = "1rem"; - details.open = entryType === "dir"; + details.open = entryType === "dir"; // Expand if console.dir() is used details.appendChild(summary); - for (const prop in arg) { - if (!arg.hasOwnProperty(prop)) continue; + if (arg instanceof Error) { + // Add error stack trace + const el = document.createElement("p"); + el.innerHTML = this.#formatStacktrace(arg.stack); + details.appendChild(el); + } else { + // Add object properties + for (const prop in arg) { + if (!arg.hasOwnProperty(prop)) continue; - this.#addEntry( - entryType, - prop, - details, - arg.__lookupGetter__(prop) ?? arg[prop], - ); - } + this.#addEntry( + entryType, + prop, + details, + arg.__lookupGetter__(prop) ?? arg[prop], + ); + } - if (Object.getPrototypeOf(arg) && Object.keys(Object.getPrototypeOf(arg)).length) { - this.#addEntry(entryType, "__proto__", details, Object.getPrototypeOf(arg)); + // Add prototype if one exists + if ( + Object.getPrototypeOf(arg) && Object.keys(Object.getPrototypeOf(arg)).length + ) { + this.#addEntry(entryType, "__proto__", details, Object.getPrototypeOf(arg)); + } } parent.appendChild(details); - } else { - const wrapper = document.createElement("p"); - this.#addKeyValue(entryType, wrapper, property, arg); - parent.appendChild(wrapper); + + return; } + + // For non-object values, show it directly + const wrapper = document.createElement("p"); + wrapper.className = entryType; + this.#addKeyValue(entryType, wrapper, property, arg); + parent.appendChild(wrapper); } } @@ -75,11 +119,12 @@ export class PlaygroundConsole { this.#addEntry("info", "", this.elem, ...arguments); } - error(text) { - const el = document.createElement("span"); - el.className = "error"; - el.textContent = "" + text; - this.elem.appendChild(el); + warn() { + this.#addEntry("warn", "", this.elem, ...arguments); + } + + error() { + this.#addEntry("error", "", this.elem, ...arguments); } clear() { diff --git a/style.css b/style.css index 6450258..6cdcb6c 100644 --- a/style.css +++ b/style.css @@ -118,7 +118,6 @@ div#buttons button { overflow-wrap: break-word; word-break: break-all; font-size: 1rem; - padding: 4px 8px; flex: 1; overflow-y: auto; } @@ -128,12 +127,27 @@ div#buttons button { white-space: pre-wrap; } -#console p { +#console p, #console summary { margin: 0; + padding: 0.125rem 0.5rem; +} + +#console a { + color: #2196f3; } #console .error { - color: #d32f2f; + background-color: #4a1305; +} + +#console [data-type="error"] { + color: #ff8a65; + background-color: #4a1305; +} + +#console .warn { + color: #fff176; + background-color: #413d07; } #console .info, @@ -171,7 +185,6 @@ div#buttons button { width: 100%; margin: 0; outline: none; - padding: none; color: white; border: none; background-color: #222;