mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 05:07:35 +00:00
LibJS+WebContent+Browser+js: Implement console.group() methods
This implements: - console.group() - console.groupCollapsed() - console.groupEnd() In the Browser, we use `<details>` for the groups, which is not actually implemented yet, so groups are always open. In the REPL, groups are non-interactive, but still indent any output. This looks weird since the console prompt and return values remain on the far left, but this matches what Node does so it's probably fine. :^) I expect `console.group()` is not used much outside of browsers.
This commit is contained in:
parent
ff5e07d718
commit
d702678d16
10 changed files with 281 additions and 25 deletions
|
@ -111,6 +111,12 @@ void ConsoleWidget::handle_console_messages(i32 start_index, const Vector<String
|
|||
print_html(message);
|
||||
} else if (type == "clear") {
|
||||
clear_output();
|
||||
} else if (type == "group") {
|
||||
begin_group(message, true);
|
||||
} else if (type == "groupCollapsed") {
|
||||
begin_group(message, false);
|
||||
} else if (type == "groupEnd") {
|
||||
end_group();
|
||||
} else {
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
@ -138,26 +144,85 @@ void ConsoleWidget::print_source_line(StringView source)
|
|||
void ConsoleWidget::print_html(StringView line)
|
||||
{
|
||||
StringBuilder builder;
|
||||
|
||||
int parent_id = m_group_stack.is_empty() ? 0 : m_group_stack.last().id;
|
||||
if (parent_id == 0) {
|
||||
builder.append(R"~~~(
|
||||
var parentGroup = document.body;
|
||||
)~~~");
|
||||
} else {
|
||||
builder.appendff(R"~~~(
|
||||
var parentGroup = document.getElementById("group_{}");
|
||||
)~~~",
|
||||
parent_id);
|
||||
}
|
||||
|
||||
builder.append(R"~~~(
|
||||
var p = document.createElement("p");
|
||||
p.innerHTML = ")~~~");
|
||||
builder.append_escaped_for_json(line);
|
||||
builder.append(R"~~~("
|
||||
document.body.appendChild(p);
|
||||
parentGroup.appendChild(p);
|
||||
)~~~");
|
||||
m_output_view->run_javascript(builder.string_view());
|
||||
// FIXME: Make it scroll to the bottom, using `window.scrollTo()` in the JS above.
|
||||
// We used to call `m_output_view->scroll_to_bottom();` here, but that does not work because
|
||||
// it runs synchronously, meaning it happens before the HTML is output via IPC above.
|
||||
// (See also: begin_group())
|
||||
}
|
||||
|
||||
void ConsoleWidget::clear_output()
|
||||
{
|
||||
m_group_stack.clear();
|
||||
m_output_view->run_javascript(R"~~~(
|
||||
document.body.innerHTML = "";
|
||||
)~~~");
|
||||
}
|
||||
|
||||
void ConsoleWidget::begin_group(StringView label, bool start_expanded)
|
||||
{
|
||||
StringBuilder builder;
|
||||
int parent_id = m_group_stack.is_empty() ? 0 : m_group_stack.last().id;
|
||||
if (parent_id == 0) {
|
||||
builder.append(R"~~~(
|
||||
var parentGroup = document.body;
|
||||
)~~~");
|
||||
} else {
|
||||
builder.appendff(R"~~~(
|
||||
var parentGroup = document.getElementById("group_{}");
|
||||
)~~~",
|
||||
parent_id);
|
||||
}
|
||||
|
||||
Group group;
|
||||
group.id = m_next_group_id++;
|
||||
group.label = label;
|
||||
|
||||
builder.appendff(R"~~~(
|
||||
var group = document.createElement("details");
|
||||
group.id = "group_{}";
|
||||
var label = document.createElement("summary");
|
||||
label.innerText = ")~~~",
|
||||
group.id);
|
||||
builder.append_escaped_for_json(label);
|
||||
builder.append(R"~~~(";
|
||||
group.appendChild(label);
|
||||
parentGroup.appendChild(group);
|
||||
)~~~");
|
||||
|
||||
if (start_expanded)
|
||||
builder.append("group.open = true;");
|
||||
|
||||
m_output_view->run_javascript(builder.string_view());
|
||||
// FIXME: Scroll console to bottom - see note in print_html()
|
||||
m_group_stack.append(group);
|
||||
}
|
||||
|
||||
void ConsoleWidget::end_group()
|
||||
{
|
||||
m_group_stack.take_last();
|
||||
}
|
||||
|
||||
void ConsoleWidget::reset()
|
||||
{
|
||||
clear_output();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue