Files
DodoSSH/src/DodoSSH.Client.Shell/WebAssets/terminal.html
T
jaap-jan 6806e542f9
ci / build and test (push) Successful in 3m37s
ci / android head (push) Successful in 3m45s
ci / api image (push) Successful in 8s
ci / desktop nightly (push) Successful in 1m44s
Terminal: measure characters with Unicode 11 widths, so an emoji takes the two columns the remote counts
2026-10-04 13:55:20 +02:00

59 lines
2.6 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>DodoSSH terminal</title>
<!--
Load-bearing on a phone, and missing until a terminal was first pinch-zoomed on one. Without it an
Android WebView lays the page out at a notional 980 CSS pixels wide and scales the result down to
fit, so a terminal sized to fill the window renders small and is then offered to the user as
something to zoom around in. width=device-width makes one CSS pixel one layout pixel, which is what
the fit addon has been assuming all along, and what a desktop WebView gives for free.
viewport-fit=cover so the page reaches under a phone's rounded corners rather than being
letterboxed; the shell keeps its own chrome clear of the system insets already.
user-scalable=no is here for completeness and is NOT what stops the pinching — Blink has ignored it
since Chrome 48, WebView included. The knob that works is on the WebView; see TerminalScreen in the
Android head.
-->
<meta name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover">
<!--
A restrictive CSP. The page is served over loopback from our own process, but it hosts a
terminal — arbitrary remote output is written into it — so the cheapest insurance against a
future mistake is forbidding anything this page does not already need. No remote origins,
no inline script, no eval. 'self' covers the loopback origin the host serves from, and the
WebSocket connects to that same origin.
-->
<meta http-equiv="Content-Security-Policy"
content="default-src 'none';
script-src 'self';
style-src 'self';
font-src 'self';
img-src 'self' data:;
connect-src ws://127.0.0.1:*;
base-uri 'none';
form-action 'none'">
<link rel="stylesheet" href="/vendor/xterm.css">
<link rel="stylesheet" href="/terminal.css">
</head>
<body>
<!--
The token and socket URL are substituted by the host when it serves this file, so neither is
ever written to disk and neither appears in a URL.
-->
<div id="root" data-token="__DODOSSH_TOKEN__" data-socket="__DODOSSH_SOCKET__"></div>
<div id="status" role="status" aria-live="polite">Connecting…</div>
<script src="/vendor/xterm.js"></script>
<script src="/vendor/addon-fit.js"></script>
<script src="/vendor/addon-webgl.js"></script>
<script src="/vendor/addon-unicode11.js"></script>
<script src="/terminal.js"></script>
</body>
</html>