Download pyxtermjs/index.html from ar08/train: direct link, hf CLI and curl.
- Browser
- Download file 6.79 kB
-
https://huggingface.co/spaces/ar08/train/resolve/main/pyxtermjs/index.html
- Command line
-
hf download hf://spaces/ar08/train/pyxtermjs/index.html
-
curl -L -o index.html https://huggingface.co/spaces/ar08/train/resolve/main/pyxtermjs/index.html
6.79 kB
| <html lang="en"> | |
| <head> | |
| <meta charset="utf-8" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
| <title>Enhanced Terminal</title> | |
| <link rel="stylesheet" href="https://unpkg.com/xterm@4.11.0/css/xterm.css" /> | |
| <style> | |
| html { | |
| font-family: Arial, sans-serif; | |
| } | |
| body { | |
| background-color: #1e1e1e; /* Dark grey background */ | |
| color: white; | |
| margin: 0; | |
| padding: 0; | |
| display: flex; | |
| flex-direction: column; | |
| height: 100vh; | |
| } | |
| #status-bar { | |
| background-color: #333; /* Darker background for status bar */ | |
| color: #fff; | |
| padding: 5px 10px; | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| font-size: small; | |
| } | |
| #terminal-container { | |
| flex: 1; | |
| display: flex; | |
| flex-direction: column; | |
| padding: 10px; | |
| } | |
| #terminal { | |
| flex: 1; | |
| width: 100%; | |
| height: 100%; | |
| border: 1px solid #444; /* Border around terminal */ | |
| border-radius: 5px; /* Rounded corners */ | |
| overflow: hidden; /* Hide overflow */ | |
| } | |
| /* Custom scrollbar styles */ | |
| ::-webkit-scrollbar { | |
| width: 12px; | |
| height: 12px; | |
| } | |
| ::-webkit-scrollbar-track { | |
| background: #2e2e2e; /* Darker background for track */ | |
| border-radius: 10px; | |
| } | |
| ::-webkit-scrollbar-thumb { | |
| background-color: #555; /* Grey color for thumb */ | |
| border-radius: 10px; | |
| border: 3px solid #2e2e2e; /* Padding around thumb */ | |
| } | |
| ::-webkit-scrollbar-thumb:hover { | |
| background-color: #777; /* Lighter grey on hover */ | |
| } | |
| .link-container { | |
| text-align: right; | |
| font-size: small; | |
| margin-top: 5px; | |
| } | |
| .link-container a { | |
| color: #1e90ff; /* Link color */ | |
| text-decoration: none; | |
| } | |
| .link-container a:hover { | |
| text-decoration: underline; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div id="status-bar"> | |
| <span>Status: <span id="status">connecting...</span></span> | |
| <span id="resize-status"></span> | |
| </div> | |
| <div id="terminal-container"> | |
| <div id="terminal"></div> | |
| <div class="link-container"> | |
| <a href="https://www.youtube.com/watch?v=o-YBDTqX_ZU">Get Rickrolled</a> | | |
| <a href="https://github.com">GitHub</a> | |
| </div> | |
| </div> | |
| <script src="https://unpkg.com/xterm@4.11.0/lib/xterm.js"></script> | |
| <script src="https://unpkg.com/xterm-addon-fit@0.5.0/lib/xterm-addon-fit.js"></script> | |
| <script src="https://unpkg.com/xterm-addon-web-links@0.4.0/lib/xterm-addon-web-links.js"></script> | |
| <script src="https://unpkg.com/xterm-addon-search@0.8.0/lib/xterm-addon-search.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.min.js"></script> | |
| <script> | |
| const term = new Terminal({ | |
| cursorBlink: true, | |
| macOptionIsMeta: true, | |
| scrollback: true, | |
| }); | |
| const fit = new FitAddon.FitAddon(); | |
| term.loadAddon(fit); | |
| term.loadAddon(new WebLinksAddon.WebLinksAddon()); | |
| term.loadAddon(new SearchAddon.SearchAddon()); | |
| term.open(document.getElementById("terminal")); | |
| fit.fit(); | |
| term.resize(15, 50); | |
| console.log(`size: ${term.cols} columns, ${term.rows} rows`); | |
| fit.fit(); | |
| term.writeln("Welcome to AR-server"); | |
| term.writeln(""); | |
| term.writeln("You can copy with ctrl+shift+x"); | |
| term.writeln("You can paste with ctrl+shift+v"); | |
| term.writeln(''); | |
| term.onData((data) => { | |
| console.log("browser terminal received new data:", data); | |
| socket.emit("pty-input", { input: data }); | |
| }); | |
| const socket = io.connect("/pty"); | |
| const status = document.getElementById("status"); | |
| socket.on("pty-output", function (data) { | |
| console.log("new output received from server:", data.output); | |
| term.write(data.output); | |
| }); | |
| socket.on("connect", () => { | |
| fitToscreen(); | |
| status.innerHTML = '<span style="background-color: lightgreen; padding: 2px 4px; border-radius: 3px;">connected</span>'; | |
| }); | |
| socket.on("disconnect", () => { | |
| status.innerHTML = '<span style="background-color: #ff8383; padding: 2px 4px; border-radius: 3px;">disconnected</span>'; | |
| }); | |
| function fitToscreen() { | |
| fit.fit(); | |
| const dims = { cols: term.cols, rows: term.rows }; | |
| console.log("sending new dimensions to server's pty", dims); | |
| socket.emit("resize", dims); | |
| document.getElementById("resize-status").textContent = `Resized to: ${dims.cols}x${dims.rows}`; | |
| } | |
| function debounce(func, wait_ms) { | |
| let timeout; | |
| return function (...args) { | |
| const context = this; | |
| clearTimeout(timeout); | |
| timeout = setTimeout(() => func.apply(context, args), wait_ms); | |
| }; | |
| } | |
| /** | |
| * Handle copy and paste events | |
| */ | |
| function customKeyEventHandler(e) { | |
| if (e.type !== "keydown") { | |
| return true; | |
| } | |
| if (e.ctrlKey && e.shiftKey) { | |
| const key = e.key.toLowerCase(); | |
| if (key === "v") { | |
| // ctrl+shift+v: paste whatever is in the clipboard | |
| navigator.clipboard.readText().then((toPaste) => { | |
| socket.emit("pty-input", { input: toPaste }); | |
| }); | |
| // Prevent default paste action | |
| e.preventDefault(); | |
| return false; | |
| } else if (key === "c" || key === "x") { | |
| // ctrl+shift+x: copy whatever is highlighted to clipboard | |
| const toCopy = term.getSelection(); | |
| if (toCopy) { | |
| navigator.clipboard.writeText(toCopy).then(() => { | |
| term.focus(); | |
| }); | |
| } | |
| return false; | |
| } | |
| } | |
| return true; | |
| } | |
| const wait_ms = 50; | |
| window.onresize = debounce(fitToscreen, wait_ms); | |
| term.attachCustomKeyEventHandler(customKeyEventHandler); | |
| </script> | |
| </body> | |
| </html> | |