webtty 1.6.1 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,3 @@
1
- import{FitAddon as G,init as y,Terminal as U}from"/dist/ghostty-web.js";var B=new RegExp("\x1B\\[(\\d*) q","g");function W(j,z){let V=j.options.cursorStyle,X=j.options.cursorBlink;B.lastIndex=0;let N=B.exec(z);while(N!==null){let K=N[1]===""?0:Number(N[1]);if(!Number.isNaN(K)&&K>=0&&K<=6)j.options.cursorStyle=K===0||K===1||K===2?"block":K===3||K===4?"underline":"bar",j.options.cursorBlink=K===0||K===1||K===3||K===5;N=B.exec(z)}if((j.options.cursorStyle!==V||j.options.cursorBlink!==X)&&j.renderer&&j.wasmTerm)j.renderer.render(j.wasmTerm,!0,j.viewportY)}var O=window.location.pathname.split("/s/")[1]??"main",P=await fetch("/api/config").then((j)=>j.json());document.title=`${O} | webtty`;await y();var H=new U({cols:P.cols,rows:P.rows,cursorStyle:P.cursorStyle,cursorBlink:P.cursorStyleBlink,fontSize:P.fontSize,fontFamily:P.fontFamily,scrollback:Math.ceil(P.scrollback/80),theme:P.theme}),q=new G;H.loadAddon(q);var Q=document.getElementById("terminal");if(P.theme?.background)Q.style.background=P.theme.background;await H.open(Q);function x(){Q.style.padding="0",q.fit();let j=Q.querySelector("canvas");if(!j)return;let z=Math.max(0,Q.clientWidth-j.offsetWidth),V=Math.max(0,Q.clientHeight-j.offsetHeight);Q.style.paddingLeft=`${Math.floor(z/2)}px`,Q.style.paddingRight=`${Math.ceil(z/2)}px`,Q.style.paddingTop=`${Math.floor(V/2)}px`,Q.style.paddingBottom=`${Math.ceil(V/2)}px`}x();new ResizeObserver(()=>x()).observe(Q,{box:"border-box"});var k=window.location.protocol==="https:"?"wss:":"ws:",J;function L(){let j=`${k}//${window.location.host}/ws/${O}?cols=${H.cols}&rows=${H.rows}`;J=new WebSocket(j);let z="\x1B[2m",V="\x1B[1;33m",X="\x1B[3m",N="\x1B[0m",K=`${z}[${N} ${V}webtty${N} ${z}]${N}`,Z=(_)=>`\r
2
- ${K} ${z}${X}${_}${N}\r
3
- `;J.onopen=()=>{J.send(JSON.stringify({type:"resize",cols:H.cols,rows:H.rows}))},J.onmessage=(_)=>{W(H,_.data),H.write(_.data)},J.onclose=(_)=>{if(_.code===4001){H.write(Z("Session removed.")),setTimeout(()=>window.close(),500);return}if(_.code===1001){H.write(Z("Server stopped.")),setTimeout(()=>window.close(),500);return}H.write(Z("Connection lost. Reconnecting in 2s...")),setTimeout(L,2000)},J.onerror=()=>{H.write(Z("WebSocket error."))}}L();var $=0,Y=0;H.attachCustomWheelEventHandler((j)=>{if(!H.hasMouseTracking())return!1;let z=H.renderer?.getMetrics();if(!z)return!1;let V=j.deltaY<0?-1:1;if(V!==Y)$=0,Y=V;$+=P.mouseScrollSpeed;let X=Math.trunc($);if(X===0)return!0;$-=X;let N=j.target.getBoundingClientRect(),K=Math.max(1,Math.floor((j.clientX-N.left)/z.width)+1),Z=Math.max(1,Math.floor((j.clientY-N.top)/z.height)+1),M=`\x1B[<${V<0?64:65};${K};${Z}M`;if(J&&J.readyState===WebSocket.OPEN)for(let F=0;F<X;F++)J.send(M);return!0});Q.addEventListener("keydown",(j)=>{let z=j.key.toLowerCase(),V=new Set([...j.shiftKey?["shift"]:[],...j.ctrlKey?["ctrl"]:[],...j.altKey?["alt"]:[],...j.metaKey?["meta"]:[]]),X=P.keyboardBindings.find((N)=>{if(N.key.toLowerCase()!==z)return!1;let K=new Set((Array.isArray(N.mods)?N.mods:[]).map((Z)=>Z.toLowerCase()));if(K.size!==V.size)return!1;for(let Z of K)if(!V.has(Z))return!1;return!0});if(!X)return;if(j.preventDefault(),j.stopPropagation(),X.chars&&J.readyState===WebSocket.OPEN)J.send(X.chars)},{capture:!0});H.onData((j)=>{if(J&&J.readyState===WebSocket.OPEN)J.send(j)});H.onResize(({cols:j,rows:z})=>{if(J&&J.readyState===WebSocket.OPEN)J.send(JSON.stringify({type:"resize",cols:j,rows:z}))});if(P.copyOnSelect)H.onSelectionChange(()=>{let j=H.getSelection();if(!j)return;navigator.clipboard.writeText(j).catch(()=>{})});if(P.rightClickBehavior==="copyPaste")Q.addEventListener("contextmenu",(j)=>{let z=H.getSelection();if(!z)return;j.preventDefault(),navigator.clipboard.writeText(z).catch(()=>{}),H.clearSelection()});Q.addEventListener("paste",(j)=>{let z=j.clipboardData;if(!z)return;if(z.getData("text/plain"))return;if(j.preventDefault(),j.stopImmediatePropagation(),J&&J.readyState===WebSocket.OPEN)J.send("\x16")},{capture:!0});
1
+ import{FitAddon as k,init as F,Terminal as T}from"/dist/ghostty-web.js";var Y=new RegExp("\x1B\\[(\\d*) q","g");function L(j,H){let P=j.options.cursorStyle,Z=j.options.cursorBlink;Y.lastIndex=0;let Q=Y.exec(H);while(Q!==null){let N=Q[1]===""?0:Number(Q[1]);if(!Number.isNaN(N)&&N>=0&&N<=6)j.options.cursorStyle=N===0||N===1||N===2?"block":N===3||N===4?"underline":"bar",j.options.cursorBlink=N===0||N===1||N===3||N===5;Q=Y.exec(H)}if((j.options.cursorStyle!==P||j.options.cursorBlink!==Z)&&j.renderer&&j.wasmTerm)j.renderer.render(j.wasmTerm,!0,j.viewportY)}var G=window.location.pathname.split("/s/")[1]??"main",V=await fetch("/api/config").then((j)=>j.json());document.title=`${G} | webtty`;await F();var J=new T({cols:V.cols,rows:V.rows,cursorStyle:V.cursorStyle,cursorBlink:V.cursorStyleBlink,fontSize:V.fontSize,fontFamily:V.fontFamily,scrollback:Math.ceil(V.scrollback/80),theme:V.theme}),O=new k;J.loadAddon(O);var X=document.getElementById("terminal");if(V.theme?.background)X.style.background=V.theme.background;await J.open(X);function q(){X.style.padding="0",O.fit();let j=X.querySelector("canvas");if(!j)return;let H=Math.max(0,X.clientWidth-j.offsetWidth),P=Math.max(0,X.clientHeight-j.offsetHeight);X.style.paddingLeft=`${Math.floor(H/2)}px`,X.style.paddingRight=`${Math.ceil(H/2)}px`,X.style.paddingTop=`${Math.floor(P/2)}px`,X.style.paddingBottom=`${Math.ceil(P/2)}px`}q();new ResizeObserver(()=>q()).observe(X,{box:"border-box"});var C=window.location.protocol==="https:"?"wss:":"ws:",K;function y(){let j=`${C}//${window.location.host}/ws/${G}?cols=${J.cols}&rows=${J.rows}`;K=new WebSocket(j);let H="\x1B[2m",P="\x1B[1;33m",Z="\x1B[3m",Q="\x1B[0m",N=`${H}[${Q} ${P}webtty${Q} ${H}]${Q}`,_=($)=>`\r
2
+ ${N} ${H}${Z}${$}${Q}\r
3
+ `;K.onopen=()=>{K.send(JSON.stringify({type:"resize",cols:J.cols,rows:J.rows}))},K.onmessage=($)=>{L(J,$.data),J.write($.data)},K.onclose=($)=>{if($.code===4001){J.write(_("Session removed.")),setTimeout(()=>window.close(),500);return}if($.code===1001){J.write(_("Server stopped.")),setTimeout(()=>window.close(),500);return}J.write(_("Connection lost. Reconnecting in 2s...")),setTimeout(y,2000)},K.onerror=()=>{J.write(_("WebSocket error."))}}y();var W=0,M=0;J.attachCustomWheelEventHandler((j)=>{if(!J.hasMouseTracking())return!1;let H=J.renderer?.getMetrics();if(!H)return!1;let P=j.deltaY<0?-1:1;if(P!==M)W=0,M=P;W+=V.mouseScrollSpeed;let Z=Math.trunc(W);if(Z===0)return!0;W-=Z;let Q=j.target.getBoundingClientRect(),N=Math.max(1,Math.floor((j.clientX-Q.left)/H.width)+1),_=Math.max(1,Math.floor((j.clientY-Q.top)/H.height)+1),U=`\x1B[<${P<0?64:65};${N};${_}M`;if(K&&K.readyState===WebSocket.OPEN)for(let x=0;x<Z;x++)K.send(U);return!0});X.addEventListener("keydown",(j)=>{let H=j.key.toLowerCase(),P=new Set([...j.shiftKey?["shift"]:[],...j.ctrlKey?["ctrl"]:[],...j.altKey?["alt"]:[],...j.metaKey?["meta"]:[]]),Z=V.keyboardBindings.find((Q)=>{if(Q.key.toLowerCase()!==H)return!1;let N=new Set((Array.isArray(Q.mods)?Q.mods:[]).map((_)=>_.toLowerCase()));if(N.size!==P.size)return!1;for(let _ of N)if(!P.has(_))return!1;return!0});if(!Z)return;if(j.preventDefault(),j.stopPropagation(),Z.chars&&K.readyState===WebSocket.OPEN)K.send(Z.chars)},{capture:!0});var B=Math.min(32,Math.max(6,V.fontSize));window.addEventListener("keydown",(j)=>{if(!j.ctrlKey&&!j.metaKey)return;let H=j.code==="Equal"||j.code==="NumpadAdd",P=j.code==="Minus"&&!j.shiftKey||j.code==="NumpadSubtract",Z=j.code==="Digit0"&&!j.shiftKey||j.code==="Numpad0";if(!H&&!P&&!Z)return;if(j.preventDefault(),j.stopPropagation(),H)B=Math.min(32,B+1);else if(P)B=Math.max(6,B-1);else B=Math.min(32,Math.max(6,V.fontSize));J.options.fontSize=B,q()},{capture:!0});J.onData((j)=>{if(K&&K.readyState===WebSocket.OPEN)K.send(j)});J.onResize(({cols:j,rows:H})=>{if(K&&K.readyState===WebSocket.OPEN)K.send(JSON.stringify({type:"resize",cols:j,rows:H}))});if(V.copyOnSelect)J.onSelectionChange(()=>{let j=J.getSelection();if(!j)return;navigator.clipboard.writeText(j).catch(()=>{})});if(V.rightClickBehavior==="copyPaste")X.addEventListener("contextmenu",(j)=>{let H=J.getSelection();if(!H)return;j.preventDefault(),navigator.clipboard.writeText(H).catch(()=>{}),J.clearSelection()});X.addEventListener("paste",(j)=>{let H=j.clipboardData;if(!H)return;if(H.getData("text/plain"))return;if(j.preventDefault(),j.stopImmediatePropagation(),K&&K.readyState===WebSocket.OPEN)K.send("\x16")},{capture:!0});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webtty",
3
- "version": "1.6.1",
3
+ "version": "1.7.0",
4
4
  "description": "Web TTY for running CLI/TUI applications in a browser tab, across platforms",
5
5
  "license": "MIT",
6
6
  "bin": {