allow multiple values on one line in console

This commit is contained in:
Reimar 2025-10-17 10:12:11 +02:00
parent 245d4b2ad0
commit 2d5f6c17e6
2 changed files with 81 additions and 29 deletions

View File

@ -31,6 +31,10 @@ export class PlaygroundConsole {
} }
getValueString(value) { getValueString(value) {
if (value instanceof Error) {
return value.message;
}
if (typeof value === "function") { if (typeof value === "function") {
return `function ${value.name}()`; return `function ${value.name}()`;
} }
@ -56,7 +60,7 @@ export class PlaygroundConsole {
return " ]"; return " ]";
} }
if (typeof value === "object" && value !== null) { if (typeof value === "object" && value !== null && !(value instanceof Error)) {
return " }"; return " }";
} }
@ -73,9 +77,7 @@ export class PlaygroundConsole {
} }
const valueEl = document.createElement("span"); const valueEl = document.createElement("span");
valueEl.style.display = "list-item"; // Re-add arrow that was removed by applying flex on <summary> valueEl.className = "base-value";
valueEl.style.overflowX = "hidden";
valueEl.style.textOverflow = "ellipsis";
valueEl.textContent = this.getValueString(value); valueEl.textContent = this.getValueString(value);
valueEl.dataset.type = this.getTypeName(value); valueEl.dataset.type = this.getTypeName(value);
parent.appendChild(valueEl); parent.appendChild(valueEl);
@ -93,20 +95,19 @@ export class PlaygroundConsole {
// For objects, show a collapsed list of properties // For objects, show a collapsed list of properties
if (typeof arg === "object" && arg !== null) { if (typeof arg === "object" && arg !== null) {
const summary = document.createElement("summary"); const summary = document.createElement("summary");
summary.style.display = "flex"; summary.className = "value";
summary.style.whiteSpace = "nowrap";
summary.className = entryType;
summary.dataset.type = "object"; summary.dataset.type = "object";
summary.style.marginLeft = "-1rem";
this.addKeyValue(entryType, summary, property, arg); this.addKeyValue(entryType, summary, property, arg);
const details = document.createElement("details"); const details = document.createElement("details");
details.className = entryType; details.className = entryType;
details.style.marginLeft = "1rem";
details.open = entryType === "dir"; // Expand if console.dir() is used details.open = entryType === "dir"; // Expand if console.dir() is used
details.appendChild(summary); details.appendChild(summary);
const object = document.createElement("div");
object.style.marginLeft = "1rem";
if (arg instanceof Error) { if (arg instanceof Error) {
// On Chrome, the first line of the stack trace is the error message repeated // On Chrome, the first line of the stack trace is the error message repeated
if (globalThis.chrome) { if (globalThis.chrome) {
@ -117,14 +118,14 @@ export class PlaygroundConsole {
const el = document.createElement("p"); const el = document.createElement("p");
el.innerHTML = this.formatStacktrace(arg.stack); el.innerHTML = this.formatStacktrace(arg.stack);
details.appendChild(el); object.appendChild(el);
} else { } else {
// Add object properties // Add object properties
for (const prop of Object.getOwnPropertyNames(arg)) { for (const prop of Object.getOwnPropertyNames(arg)) {
this.addEntry( this.addEntry(
entryType, entryType,
prop, prop,
details, object,
arg.__lookupGetter__(prop) ?? arg[prop], arg.__lookupGetter__(prop) ?? arg[prop],
); );
} }
@ -132,20 +133,19 @@ export class PlaygroundConsole {
// Add prototype if one exists // Add prototype if one exists
const prototype = Object.getPrototypeOf(arg); const prototype = Object.getPrototypeOf(arg);
if (prototype && Object.getOwnPropertyNames(prototype).length > 0) { if (prototype && Object.getOwnPropertyNames(prototype).length > 0) {
this.addEntry(entryType, "__proto__", details, prototype); this.addEntry(entryType, "__proto__", object, prototype);
} }
} }
details.appendChild(object);
parent.appendChild(details); parent.appendChild(details);
return details; return details;
} }
// For non-object values, show it directly // For non-object values, show it directly
const wrapper = document.createElement("p"); const wrapper = document.createElement("span");
wrapper.style.display = "flex"; wrapper.className = "value";
wrapper.style.whiteSpace = "nowrap";
wrapper.className = entryType;
this.addKeyValue(entryType, wrapper, property, arg); this.addKeyValue(entryType, wrapper, property, arg);
parent.appendChild(wrapper); parent.appendChild(wrapper);
@ -153,8 +153,11 @@ export class PlaygroundConsole {
} }
addTopLevelEntry(entryType, ...args) { addTopLevelEntry(entryType, ...args) {
const container = document.createElement("p");
container.className = entryType;
for (const arg of args) { for (const arg of args) {
const elem = this.addEntry(entryType, "", this.elem, ...args); const elem = this.addEntry(entryType, "", container, arg);
elem.addEventListener("contextmenu", (ev) => { elem.addEventListener("contextmenu", (ev) => {
// TODO add context menu // TODO add context menu
@ -163,6 +166,7 @@ export class PlaygroundConsole {
}); });
} }
this.elem.appendChild(container);
this.elem.scrollTop = this.elem.scrollHeight; this.elem.scrollTop = this.elem.scrollHeight;
} }

View File

@ -104,13 +104,6 @@ div#buttons button {
overflow-y: hidden; overflow-y: hidden;
} }
#console-code {
display: flex;
flex-direction: column;
gap: 5px;
scroll-behavior: smooth;
}
#console pre { #console pre {
color: white; color: white;
background-color: black; background-color: black;
@ -121,6 +114,9 @@ div#buttons button {
font-size: 1rem; font-size: 1rem;
flex: 1; flex: 1;
overflow-y: auto; overflow-y: auto;
display: flex;
flex-direction: column;
scroll-behavior: smooth;
} }
#console pre { #console pre {
@ -130,13 +126,50 @@ div#buttons button {
#console p, #console summary { #console p, #console summary {
margin: 0; margin: 0;
padding: 0.125rem 0.5rem; padding: 0.125rem 0.5rem 0.125rem 0;
}
#console summary {
white-space: nowrap;
} }
#console a { #console a {
color: #2196f3; color: #2196f3;
} }
#console p {
padding: 0.25rem 0.5rem;
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 0.5rem;
}
#console p ~ p {
border-top: 1px solid #242424;
}
#console p + .warn, #console .warn + p {
border-color: #fbc02d;
}
#console p + .error, #console .error + p {
border-color: #d32f2f;
}
#console p > *:last-child {
flex: 1;
}
#console p > details {
min-width: 130px;
overflow-x: hidden;
}
#console p > details[open] {
min-width: 100%;
}
#console .error { #console .error {
background-color: #4a1305; background-color: #4a1305;
} }
@ -152,7 +185,7 @@ div#buttons button {
} }
#console .input:before { #console .input:before {
content: "> "; content: ">";
} }
#console .input { #console .input {
@ -174,14 +207,29 @@ div#buttons button {
color: #ff9800; color: #ff9800;
} }
#console .log:hover, #console .log .value:hover,
#console .info:hover, #console .info .value:hover,
#console .debug:hover { #console .debug .value:hover {
background-color: #242424; background-color: #242424;
} }
#console .value {
display: flex;
}
#console .base-value {
display: list-item; /* Re-add arrow that was removed by applying flex on <summary> */
overflow-x: hidden;
text-overflow: ellipsis;
}
#console .property + .base-value {
white-space: nowrap;
}
#console .property { #console .property {
color: #9c27b0; color: #9c27b0;
white-space: nowrap;
} }
#console .property + [data-type="string"]:before, #console .property + [data-type="string"]:before,