ypu
This commit is contained in:
parent
cc7ac8fa69
commit
7c1285fdfa
1 changed files with 140 additions and 73 deletions
|
|
@ -70,32 +70,24 @@ HTML_PAGE = """<!DOCTYPE html>
|
|||
border: 1px solid #2b2b2b;
|
||||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45);
|
||||
padding: 12px;
|
||||
width: auto;
|
||||
height: auto;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
#terminal .xterm {
|
||||
width: auto !important;
|
||||
height: auto !important;
|
||||
}
|
||||
#terminal .xterm-viewport {
|
||||
background-color: #000 !important;
|
||||
overflow: hidden !important;
|
||||
width: auto !important;
|
||||
}
|
||||
#terminal .xterm-rows,
|
||||
#terminal .xterm-scroll-area {
|
||||
width: auto !important;
|
||||
height: auto !important;
|
||||
}
|
||||
#terminal .xterm-screen {
|
||||
width: auto !important;
|
||||
height: auto !important;
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
}
|
||||
#terminal .xterm .xterm-helper-textarea {
|
||||
width: 0 !important;
|
||||
height: 0 !important;
|
||||
}
|
||||
#terminal .xterm-viewport,
|
||||
#terminal .xterm-screen,
|
||||
#terminal .xterm-rows,
|
||||
#terminal .xterm-scroll-area {
|
||||
width: 640px !important;
|
||||
height: 400px !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
|
@ -107,21 +99,87 @@ HTML_PAGE = """<!DOCTYPE html>
|
|||
<script type="module">
|
||||
import { Terminal } from "https://cdn.jsdelivr.net/npm/xterm@5.3.0/+esm";
|
||||
|
||||
const INITIAL_COLS = 80;
|
||||
const INITIAL_ROWS = 25;
|
||||
(async () => {
|
||||
const COLS = 80;
|
||||
const ROWS = 25;
|
||||
const CHAR_HEIGHT = 16;
|
||||
const VIEWPORT_WIDTH = 640;
|
||||
const VIEWPORT_HEIGHT = 400;
|
||||
const TARGET_ROW_HEIGHT = VIEWPORT_HEIGHT / ROWS;
|
||||
|
||||
const terminalHost = document.getElementById("terminal");
|
||||
|
||||
async function waitForDosvgaFont() {
|
||||
if (!document.fonts || typeof document.fonts.load !== "function") {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await Promise.race([
|
||||
document.fonts.load(`${CHAR_HEIGHT}px "DOSVGA"`),
|
||||
new Promise((resolve) => setTimeout(resolve, 2000)),
|
||||
]);
|
||||
} catch (err) {
|
||||
console.debug("DOSVGA font load race rejected", err);
|
||||
}
|
||||
}
|
||||
|
||||
function applyViewportClamp() {
|
||||
terminalHost.style.width = `${VIEWPORT_WIDTH}px`;
|
||||
terminalHost.style.height = `${VIEWPORT_HEIGHT}px`;
|
||||
|
||||
const viewport = terminalHost.querySelector(".xterm-viewport");
|
||||
if (viewport) {
|
||||
viewport.style.width = `${VIEWPORT_WIDTH}px`;
|
||||
viewport.style.height = `${VIEWPORT_HEIGHT}px`;
|
||||
viewport.style.overflow = "hidden";
|
||||
}
|
||||
|
||||
const scrollArea = terminalHost.querySelector(".xterm-scroll-area");
|
||||
if (scrollArea) {
|
||||
scrollArea.style.width = `${VIEWPORT_WIDTH}px`;
|
||||
scrollArea.style.height = `${VIEWPORT_HEIGHT}px`;
|
||||
}
|
||||
|
||||
const screen = terminalHost.querySelector(".xterm-screen");
|
||||
if (screen) {
|
||||
screen.style.width = `${VIEWPORT_WIDTH}px`;
|
||||
screen.style.height = `${VIEWPORT_HEIGHT}px`;
|
||||
}
|
||||
|
||||
const rows = terminalHost.querySelector(".xterm-rows");
|
||||
if (rows) {
|
||||
rows.style.width = `${VIEWPORT_WIDTH}px`;
|
||||
rows.style.height = `${VIEWPORT_HEIGHT}px`;
|
||||
const rowDivs = rows.querySelectorAll("div");
|
||||
rowDivs.forEach((div) => {
|
||||
div.style.height = `${TARGET_ROW_HEIGHT}px`;
|
||||
div.style.lineHeight = `${TARGET_ROW_HEIGHT}px`;
|
||||
div.style.width = `${VIEWPORT_WIDTH}px`;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
await waitForDosvgaFont();
|
||||
|
||||
const term = new Terminal({
|
||||
rendererType: "canvas",
|
||||
cursorBlink: true,
|
||||
convertEol: true,
|
||||
fontFamily: "DOSVGA, Fira Code, Cascadia Mono, Hack, monospace",
|
||||
fontSize: 16,
|
||||
cols: INITIAL_COLS,
|
||||
rows: INITIAL_ROWS,
|
||||
fontSize: CHAR_HEIGHT,
|
||||
lineHeight: 1,
|
||||
cols: COLS,
|
||||
rows: ROWS,
|
||||
theme: {
|
||||
background: "#000000",
|
||||
foreground: "#f5f5f5"
|
||||
},
|
||||
});
|
||||
term.open(document.getElementById("terminal"));
|
||||
|
||||
term.open(terminalHost);
|
||||
term.resize(COLS, ROWS);
|
||||
applyViewportClamp();
|
||||
|
||||
const wsProtocol = window.location.protocol === "https:" ? "wss" : "ws";
|
||||
const socket = new WebSocket(`${wsProtocol}://${window.location.host}/ws`);
|
||||
|
|
@ -139,6 +197,7 @@ HTML_PAGE = """<!DOCTYPE html>
|
|||
socket.addEventListener("open", () => {
|
||||
socket.send(JSON.stringify({ type: "resize", cols: term.cols, rows: term.rows }));
|
||||
term.focus();
|
||||
applyViewportClamp();
|
||||
});
|
||||
|
||||
socket.addEventListener("message", (event) => {
|
||||
|
|
@ -169,7 +228,15 @@ HTML_PAGE = """<!DOCTYPE html>
|
|||
|
||||
term.onResize(({ cols, rows }) => {
|
||||
socket.send(JSON.stringify({ type: "resize", cols, rows }));
|
||||
applyViewportClamp();
|
||||
});
|
||||
|
||||
term.onRender(() => {
|
||||
applyViewportClamp();
|
||||
});
|
||||
|
||||
window.addEventListener("resize", () => applyViewportClamp(), { passive: true });
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue