allow running code in console

This commit is contained in:
Reimar 2025-10-11 21:00:15 +02:00
parent 275029703d
commit 4df6e7bac0
5 changed files with 65 additions and 6 deletions

View File

@ -75,6 +75,7 @@
<div id="console"> <div id="console">
<pre><code id="console-code">Karlkode 1.0</code></pre> <pre><code id="console-code">Karlkode 1.0</code></pre>
<input <input
id="console-input"
type="text" type="text"
placeholder=">" placeholder=">"
> >

View File

@ -3,6 +3,7 @@ export class CodeRunner {
this.console = console; this.console = console;
this.codeStopper = codeStopper; this.codeStopper = codeStopper;
this.isRunning = false; this.isRunning = false;
this.evalScope = {};
window.playgroundConsole = this.console; window.playgroundConsole = this.console;
} }
@ -24,7 +25,8 @@ export class CodeRunner {
); );
try { try {
await import(`data:text/javascript;charset=utf-8,${encodedText}`); const module = await import(`data:text/javascript;charset=utf-8,${encodedText}`);
this.evalScope = Object.assign(this.evalScope, module);
} catch (error) { } catch (error) {
this.console.error(error); this.console.error(error);
} }
@ -43,4 +45,37 @@ export class CodeRunner {
this.run(); this.run();
} }
} }
evaluateCode(code) {
// Move evalScope to window
const oldWindow = {};
for (const prop in this.evalScope) {
if (!this.evalScope.hasOwnProperty(prop)) continue;
oldWindow[prop] = window[prop];
window[prop] = this.evalScope[prop];
}
// Evaluate code
const func = new Function(`"use strict";return ${code}`);
try {
const result = func();
this.console.log(result);
} catch (e) {
this.console.error(e);
if (e instanceof ReferenceError) {
this.console.info("Note: use `export` to allow use of variables within the console");
}
}
// Restore old window props
for (const prop in oldWindow) {
if (!oldWindow.hasOwnProperty(prop)) continue;
window[prop] = oldWindow[prop];
}
}
} }

View File

@ -66,6 +66,7 @@ const saveJsButton = document.querySelector("#save-js");
const saveHtmlButton = document.querySelector("#save-html"); const saveHtmlButton = document.querySelector("#save-html");
const saveKarlkoderButton = document.querySelector("#save-karlkoder"); const saveKarlkoderButton = document.querySelector("#save-karlkoder");
const toggleSpriteEditorButton = document.querySelector("#toggle-sprite-editor-button"); const toggleSpriteEditorButton = document.querySelector("#toggle-sprite-editor-button");
const consoleInput = document.querySelector("#console-input");
const sessionSaveDebounce = new Debounce(1000); const sessionSaveDebounce = new Debounce(1000);
editor.addEventListener("change", () => { editor.addEventListener("change", () => {
@ -217,3 +218,13 @@ saveKarlkoderButton.onclick = () => {
}; };
toggleSpriteEditorButton.addEventListener("click", () => spriteEditor.toggleEditor()); toggleSpriteEditorButton.addEventListener("click", () => spriteEditor.toggleEditor());
consoleInput.onkeydown = (ev) => {
if (ev.key !== "Enter") return;
const code = ev.target.value;
ev.target.value = "";
codeRunner.evaluateCode(code);
};

View File

@ -5,28 +5,30 @@ export class PlaygroundConsole {
log(text) { log(text) {
const el = document.createElement("span"); const el = document.createElement("span");
el.textContent = `\n${text}\n`; el.className = "log";
el.textContent = "" + text;
el.dataset.type = typeof text;
this.elem.appendChild(el); this.elem.appendChild(el);
} }
error(text) { error(text) {
const el = document.createElement("span"); const el = document.createElement("span");
el.className = "error"; el.className = "error";
el.textContent = `\n${text}\n`; el.textContent = "" + text;
this.elem.appendChild(el); this.elem.appendChild(el);
} }
debug(text) { debug(text) {
const el = document.createElement("span"); const el = document.createElement("span");
el.className = "debug"; el.className = "debug";
el.textContent = `\n${text}\n`; el.textContent = "" + text;
this.elem.appendChild(el); this.elem.appendChild(el);
} }
info(text) { info(text) {
const el = document.createElement("span"); const el = document.createElement("span");
el.className = "info"; el.className = "info";
el.textContent = `\n${text}\n`; el.textContent = "" + text;
this.elem.appendChild(el); this.elem.appendChild(el);
} }
} }

View File

@ -104,6 +104,12 @@ div#buttons button {
overflow-y: hidden; overflow-y: hidden;
} }
#console-code {
display: flex;
flex-direction: column;
gap: 5px;
}
#console pre { #console pre {
color: white; color: white;
background-color: black; background-color: black;
@ -126,10 +132,14 @@ div#buttons button {
color: #D32F2F; color: #D32F2F;
} }
#console .info, #console .debug { #console .info, #console .debug, #console .log[data-type=undefined] {
color: #BDBDBD; color: #BDBDBD;
} }
#console .log[data-type=number] {
color: #1976D2;
}
#console input { #console input {
width: 100%; width: 100%;
margin: 0; margin: 0;