update build.js

This commit is contained in:
Chris Wanstrath 2025-10-02 13:12:13 -07:00
parent c1faf0e64d
commit dc5499c17d

View File

@ -1,7 +1,8 @@
////
// version: 5933c50
// version: c1faf0e
// src/js/dom.ts
var content2 = $("content");
var cmdLine = $("command-line");
var cmdInput = $("command-textbox");
var scrollback = $("scrollback");
@ -24,7 +25,7 @@ var $$ = (tag, innerHTML = "") => {
};
// src/js/resize.ts
var content2 = document.getElementById("content");
var content3 = document.getElementById("content");
function initResize() {
window.addEventListener("resize", resize);
resize();
@ -38,13 +39,13 @@ function resize() {
}
function resizeTall() {
const scale = Math.min(1, window.innerWidth / 960);
content2.style.transformOrigin = "top center";
content2.style.transform = `scaleX(${scale})`;
content3.style.transformOrigin = "top center";
content3.style.transform = `scaleX(${scale})`;
}
function resizeCinema() {
const scale = Math.min(window.innerWidth / 960, window.innerHeight / 540);
content2.style.transformOrigin = "center center";
content2.style.transform = `scale(${scale})`;
content3.style.transformOrigin = "center center";
content3.style.transform = `scale(${scale})`;
}
// src/shared/utils.ts
@ -63,8 +64,8 @@ function insert(node) {
function addInput(id, input) {
const parent = $$("li.input");
const status = $$("span.status.yellow", "•");
const content3 = $$("span.content", input);
parent.append(status, content3);
const content4 = $$("span.content", input);
parent.append(status, content4);
parent.dataset.id = id;
insert(parent);
scrollback.scrollTop = scrollback.scrollHeight - scrollback.clientHeight;
@ -86,11 +87,11 @@ function addOutput(id, output2) {
const item = $$("li");
item.classList.add("output");
item.dataset.id = id || randomId();
const [format, content3] = processOutput(output2);
const [format, content4] = processOutput(output2);
if (format === "html")
item.innerHTML = content3;
item.innerHTML = content4;
else
item.textContent = content3;
item.textContent = content4;
const input = document.querySelector(`[data-id="${id}"].input`);
if (input instanceof HTMLLIElement) {
input.parentNode.insertBefore(item, input.nextSibling);
@ -108,11 +109,11 @@ function appendOutput(id, output2) {
console.error(`output id ${id} not found`);
return;
}
const [format, content3] = processOutput(output2);
const [format, content4] = processOutput(output2);
if (format === "html")
item.innerHTML += content3;
item.innerHTML += content4;
else
item.textContent += content3;
item.textContent += content4;
autoScroll();
}
function replaceOutput(id, output2) {
@ -121,11 +122,11 @@ function replaceOutput(id, output2) {
console.error(`output id ${id} not found`);
return;
}
const [format, content3] = processOutput(output2);
const [format, content4] = processOutput(output2);
if (format === "html")
item.innerHTML = content3;
item.innerHTML = content4;
else
item.textContent = content3;
item.textContent = content4;
autoScroll();
}
function processOutput(output) {
@ -159,150 +160,32 @@ function handleInputClick(e) {
cmdInput.value = target.textContent;
}
}
function handleOutput(msg) {
const result = msg.data;
setStatus(msg.id, result.status);
addOutput(msg.id, result.output);
}
// src/js/session.ts
var sessionId = randomId();
// src/js/commands.ts
var commands = [];
var browserCommands = {
"browser-session": () => sessionId,
clear: () => scrollback.innerHTML = "",
commands: () => commands.join(" "),
fullscreen: () => document.body.requestFullscreen(),
mode: () => {
document.body.dataset.mode = document.body.dataset.mode === "tall" ? "cinema" : "tall";
resize();
autoScroll();
},
reload: () => window.location.reload()
};
function cacheCommands(cmds) {
commands.length = 0;
commands.push(...cmds);
commands.push(...Object.keys(browserCommands));
commands.sort();
}
// src/js/completion.ts
function initCompletion() {
cmdInput.addEventListener("keydown", handleCompletion);
}
function handleCompletion(e) {
if (e.key !== "Tab")
return;
e.preventDefault();
const input = cmdInput.value;
for (const command of commands) {
if (command.startsWith(input)) {
cmdInput.value = command;
// src/js/stream.ts
function handleStreamStart(msg) {
const id = msg.id;
const status = document.querySelector(`[data-id="${id}"].input .status`);
if (!status)
return;
addOutput(id, msg.data);
status.classList.remove("yellow");
status.classList.add("purple");
}
function handleStreamAppend(msg) {
appendOutput(msg.id, msg.data);
}
function handleStreamReplace(msg) {
replaceOutput(msg.id, msg.data);
}
// src/js/cursor.ts
var cursor = "Û";
var cmdCursor;
var enabled = true;
function initCursor() {
cmdCursor = $("command-cursor");
cmdInput.addEventListener("keydown", showCursor);
document.addEventListener("focus", cursorEnablerHandler, true);
showCursor();
}
function showCursor(e = {}) {
if (!enabled) {
cmdCursor.value = "";
return;
}
if (e.key === "Enter" && !e.shiftKey) {
cmdCursor.value = cursor;
return;
}
requestAnimationFrame(() => cmdCursor.value = buildBlankCursorLine() + cursor);
}
function cursorEnablerHandler(e) {
if (!e.target)
return;
const target = e.target;
enabled = target.id === "command-textbox";
showCursor();
}
function buildBlankCursorLine() {
let line = "";
for (const char of cmdInput.value.slice(0, cmdInput.selectionEnd)) {
line += char === `
` ? char : " ";
}
return line;
}
// src/js/drop.ts
function initDrop() {
["dragenter", "dragover", "dragleave", "drop"].forEach((eventName) => {
document.body.addEventListener(eventName, preventDefaults, false);
});
document.body.addEventListener("drop", handleDrop);
}
function preventDefaults(e) {
e.preventDefault();
e.stopPropagation();
}
function handleDrop(e) {
const fileInput = document.querySelector("input[type=file]");
const files = e.dataTransfer?.files ?? [];
if (files.length > 0) {
const dt = new DataTransfer;
Array.from(files).forEach((f) => dt.items.add(f));
fileInput.files = dt.files;
fileInput.dispatchEvent(new Event("change", { bubbles: true }));
}
}
// src/js/history.ts
var history = ["one", "two", "three"];
var idx = -1;
var savedInput = "";
function initHistory() {
cmdInput.addEventListener("keydown", navigateHistory);
}
function addToHistory(input) {
if (history.length === 0 || history[0] === input)
return;
history.unshift(input);
resetHistory();
}
function resetHistory() {
idx = -1;
savedInput = "";
}
function navigateHistory(e) {
if (cmdLine.dataset.extended)
return;
if (e.key === "ArrowUp" || e.ctrlKey && e.key === "p") {
e.preventDefault();
if (idx >= history.length - 1)
return;
if (idx === -1)
savedInput = cmdInput.value;
cmdInput.value = history[++idx] || "";
if (idx >= history.length)
idx = history.length - 1;
} else if (e.key === "ArrowDown" || e.ctrlKey && e.key === "n") {
e.preventDefault();
if (idx <= 0) {
cmdInput.value = savedInput;
idx = -1;
return;
}
cmdInput.value = history[--idx] || "";
if (idx < -1)
idx = -1;
} else if (idx !== -1) {
resetHistory();
}
}
function handleStreamEnd(_msg) {}
// src/shared/game.ts
class GameContext {
@ -624,28 +507,8 @@ function endGame() {
focusInput();
}
// src/js/shell.ts
function runCommand(input) {
if (!input.trim())
return;
if (input.includes(";")) {
input.split(";").forEach((cmd2) => runCommand(cmd2.trim()));
return;
}
const id = randomId();
addToHistory(input);
addInput(id, input);
const [cmd = "", ..._args] = input.split(" ");
if (browserCommands[cmd]) {
const result = browserCommands[cmd]();
if (typeof result === "string")
addOutput(id, result);
setStatus(id, "ok");
} else {
send({ id, type: "input", data: input });
}
}
async function handleMessage(msg) {
// src/js/dispatch.ts
async function dispatchMessage(msg) {
switch (msg.type) {
case "output":
handleOutput(msg);
@ -671,31 +534,13 @@ async function handleMessage(msg) {
case "game:start":
await handleGameStart(msg);
break;
case "ui:mode":
browserCommands.mode?.(msg.data);
break;
default:
console.error("unknown message type", msg);
}
}
function handleOutput(msg) {
const result = msg.data;
setStatus(msg.id, result.status);
addOutput(msg.id, result.output);
}
function handleStreamStart(msg) {
const id = msg.id;
const status = document.querySelector(`[data-id="${id}"].input .status`);
if (!status)
return;
addOutput(id, msg.data);
status.classList.remove("yellow");
status.classList.add("purple");
}
function handleStreamAppend(msg) {
appendOutput(msg.id, msg.data);
}
function handleStreamReplace(msg) {
replaceOutput(msg.id, msg.data);
}
function handleStreamEnd(_msg) {}
// src/js/websocket.ts
var MAX_RETRIES = 5;
@ -704,7 +549,7 @@ var connected = false;
var msgQueue = [];
var ws = null;
function startConnection() {
const url = new URL("/ws", location.href);
const url = new URL(`/ws?session=${sessionId}`, location.href);
url.protocol = url.protocol.replace("http", "ws");
ws = new WebSocket(url);
ws.onmessage = receive;
@ -730,7 +575,7 @@ function send(msg) {
async function receive(e) {
const data = JSON.parse(e.data);
console.log("<- receive", data);
await handleMessage(data);
await dispatchMessage(data);
}
function retryConnection() {
connected = false;
@ -745,6 +590,112 @@ function retryConnection() {
setTimeout(startConnection, 2000);
}
// src/js/commands.ts
var commands = [];
var browserCommands = {
"browser-session": () => sessionId,
clear: () => scrollback.innerHTML = "",
commands: () => {
return { html: "<div>" + commands.map((cmd) => `<a href="#help ${cmd}">${cmd}</a>`).join("") + "</div>" };
},
fullscreen: () => document.body.requestFullscreen(),
mode: (mode) => {
if (!mode) {
mode = document.body.dataset.mode === "tall" ? "cinema" : "tall";
send({ type: "ui:mode", data: mode });
}
content2.style.display = "";
document.body.dataset.mode = mode;
resize();
autoScroll();
focusInput();
},
reload: () => window.location.reload()
};
function cacheCommands(cmds) {
commands.length = 0;
commands.push(...cmds);
commands.push(...Object.keys(browserCommands));
commands.sort();
console.log("CMDS", commands);
}
// src/js/completion.ts
function initCompletion() {
cmdInput.addEventListener("keydown", handleCompletion);
}
function handleCompletion(e) {
if (e.key !== "Tab")
return;
e.preventDefault();
const input = cmdInput.value;
for (const command of commands) {
if (command.startsWith(input)) {
cmdInput.value = command;
return;
}
}
}
// src/js/cursor.ts
var cursor = "Û";
var cmdCursor;
var enabled = true;
function initCursor() {
cmdCursor = $("command-cursor");
cmdInput.addEventListener("keydown", showCursor);
document.addEventListener("focus", cursorEnablerHandler, true);
showCursor();
}
function showCursor(e = {}) {
if (!enabled) {
cmdCursor.value = "";
return;
}
if (e.key === "Enter" && !e.shiftKey) {
cmdCursor.value = cursor;
return;
}
requestAnimationFrame(() => cmdCursor.value = buildBlankCursorLine() + cursor);
}
function cursorEnablerHandler(e) {
if (!e.target)
return;
const target = e.target;
enabled = target.id === "command-textbox";
showCursor();
}
function buildBlankCursorLine() {
let line = "";
for (const char of cmdInput.value.slice(0, cmdInput.selectionEnd)) {
line += char === `
` ? char : " ";
}
return line;
}
// src/js/drop.ts
function initDrop() {
["dragenter", "dragover", "dragleave", "drop"].forEach((eventName) => {
document.body.addEventListener(eventName, preventDefaults, false);
});
document.body.addEventListener("drop", handleDrop);
}
function preventDefaults(e) {
e.preventDefault();
e.stopPropagation();
}
function handleDrop(e) {
const fileInput = document.querySelector("input[type=file]");
const files = e.dataTransfer?.files ?? [];
if (files.length > 0) {
const dt = new DataTransfer;
Array.from(files).forEach((f) => dt.items.add(f));
fileInput.files = dt.files;
fileInput.dispatchEvent(new Event("change", { bubbles: true }));
}
}
// src/js/editor.ts
var INDENT_SIZE = 2;
function initEditor() {
@ -1008,11 +959,77 @@ function handleGamepad() {
requestAnimationFrame(handleGamepad);
}
// src/js/history.ts
var history = ["one", "two", "three"];
var idx = -1;
var savedInput = "";
function initHistory() {
cmdInput.addEventListener("keydown", navigateHistory);
}
function addToHistory(input) {
if (history.length === 0 || history[0] === input)
return;
history.unshift(input);
resetHistory();
}
function resetHistory() {
idx = -1;
savedInput = "";
}
function navigateHistory(e) {
if (cmdLine.dataset.extended)
return;
if (e.key === "ArrowUp" || e.ctrlKey && e.key === "p") {
e.preventDefault();
if (idx >= history.length - 1)
return;
if (idx === -1)
savedInput = cmdInput.value;
cmdInput.value = history[++idx] || "";
if (idx >= history.length)
idx = history.length - 1;
} else if (e.key === "ArrowDown" || e.ctrlKey && e.key === "n") {
e.preventDefault();
if (idx <= 0) {
cmdInput.value = savedInput;
idx = -1;
return;
}
cmdInput.value = history[--idx] || "";
if (idx < -1)
idx = -1;
} else if (idx !== -1) {
resetHistory();
}
}
// src/js/shell.ts
async function runCommand(input) {
if (!input.trim())
return;
if (input.includes(";")) {
input.split(";").forEach(async (cmd2) => await runCommand(cmd2.trim()));
return;
}
const id = randomId();
addToHistory(input);
addInput(id, input);
const [cmd = "", ...args] = input.split(" ");
if (browserCommands[cmd]) {
const result = await browserCommands[cmd](...args);
if (result)
addOutput(id, result);
setStatus(id, "ok");
} else {
send({ id, type: "input", data: input });
}
}
// src/js/hyperlink.ts
function initHyperlink() {
window.addEventListener("click", handleClick);
}
function handleClick(e) {
async function handleClick(e) {
const target = e.target;
if (!(target instanceof HTMLElement))
return;
@ -1024,7 +1041,7 @@ function handleClick(e) {
return;
if (href.startsWith("#")) {
e.preventDefault();
runCommand(href.slice(1));
await runCommand(href.slice(1));
focusInput();
}
}
@ -1034,7 +1051,7 @@ function initInput() {
cmdInput.addEventListener("keydown", inputHandler);
cmdInput.addEventListener("paste", pasteHandler);
}
function inputHandler(event) {
async function inputHandler(event) {
const target = event.target;
if (target?.id !== cmdInput.id)
return;
@ -1048,7 +1065,7 @@ function inputHandler(event) {
cmdLine.dataset.extended = "true";
} else if (event.key === "Enter") {
event.preventDefault();
runCommand(cmdInput.value);
await runCommand(cmdInput.value);
clearInput();
}
setTimeout(() => {