File size: 6,789 Bytes
1d8dca3 7c5f4e7 1d8dca3 7c5f4e7 1d8dca3 7c5f4e7 1d8dca3 62af5f0 1d8dca3 7c5f4e7 1d8dca3 7c5f4e7 1d8dca3 7c5f4e7 1d8dca3 7c5f4e7 1d8dca3 7c5f4e7 1d8dca3 7c5f4e7 1d8dca3 7c5f4e7 1d8dca3 7c5f4e7 1d8dca3 7c5f4e7 1d8dca3 7c5f4e7 1d8dca3 7c5f4e7 1d8dca3 7c5f4e7 1d8dca3 8acffa8 9509aed 8acffa8 9509aed 7c5f4e7 20e35db 7c5f4e7 1d8dca3 7c5f4e7 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 | <!DOCTYPE html>
<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>
|