@dkkoval/tui-preview 0.1.0 → 0.1.1
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.
- package/dist/TuiPreview.js +7 -96
- package/dist/core/index.d.ts +0 -1
- package/dist/core/index.js +0 -1
- package/dist/core/normalize.js +3 -2
- package/dist/core/wasi.js +10 -3
- package/dist/index.cjs +1 -1
- package/dist/index.js +241 -393
- package/package.json +9 -1
- package/dist/core/ansi.d.ts +0 -15
- package/dist/core/ansi.js +0 -181
package/dist/TuiPreview.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useMemo, useRef, useState } from "react";
|
|
3
|
-
import { ansiToHtml } from "./core/ansi.js";
|
|
4
3
|
import { loadGhostty } from "./core/ghostty.js";
|
|
5
4
|
import { resolveTuiPreviewProps, warnLegacyPropsOnce } from "./core/normalize.js";
|
|
6
5
|
import { WasiBridge, instantiateApp } from "./core/wasi.js";
|
|
@@ -13,19 +12,13 @@ export function TuiPreview(props) {
|
|
|
13
12
|
const [errorMsg, setErrorMsg] = useState("");
|
|
14
13
|
const cellSizeRef = useRef(null);
|
|
15
14
|
const [termSize, setTermSize] = useState(resolved.size);
|
|
16
|
-
const [staticHtml, setStaticHtml] = useState(null);
|
|
17
15
|
useEffect(() => {
|
|
18
16
|
warnLegacyPropsOnce(resolved.usedLegacyProps);
|
|
19
17
|
}, [resolved.usedLegacyProps]);
|
|
20
|
-
// ── Terminal mode effects ────────────────────────────────────────────────
|
|
21
18
|
useEffect(() => {
|
|
22
|
-
if (resolved.mode !== "terminal")
|
|
23
|
-
return;
|
|
24
19
|
setTermSize(resolved.size);
|
|
25
|
-
}, [resolved.
|
|
20
|
+
}, [resolved.fit, resolved.size.cols, resolved.size.rows]);
|
|
26
21
|
useEffect(() => {
|
|
27
|
-
if (resolved.mode !== "terminal")
|
|
28
|
-
return;
|
|
29
22
|
if (resolved.fit !== "container")
|
|
30
23
|
return;
|
|
31
24
|
if (!wrapperRef.current)
|
|
@@ -43,10 +36,8 @@ export function TuiPreview(props) {
|
|
|
43
36
|
});
|
|
44
37
|
observer.observe(wrapperRef.current);
|
|
45
38
|
return () => observer.disconnect();
|
|
46
|
-
}, [resolved.
|
|
39
|
+
}, [resolved.fit, resolved.terminal.fontSize]);
|
|
47
40
|
useEffect(() => {
|
|
48
|
-
if (resolved.mode !== "terminal")
|
|
49
|
-
return;
|
|
50
41
|
if (!termSize || !containerRef.current)
|
|
51
42
|
return;
|
|
52
43
|
let cancelled = false;
|
|
@@ -81,6 +72,10 @@ export function TuiPreview(props) {
|
|
|
81
72
|
});
|
|
82
73
|
termRef.current = term;
|
|
83
74
|
term.open(container);
|
|
75
|
+
// Static mode: hide cursor via DEC PM — app output only, no cursor chrome.
|
|
76
|
+
if (resolved.mode === "static") {
|
|
77
|
+
term.write("\x1b[?25l");
|
|
78
|
+
}
|
|
84
79
|
let appCols = term.cols;
|
|
85
80
|
let appRows = term.rows;
|
|
86
81
|
if (resolved.fit === "container") {
|
|
@@ -156,94 +151,10 @@ export function TuiPreview(props) {
|
|
|
156
151
|
resolved.terminal.cursorBlink,
|
|
157
152
|
resolved.terminal.convertEol,
|
|
158
153
|
]);
|
|
159
|
-
// ── Static mode effect ───────────────────────────────────────────────────
|
|
160
|
-
useEffect(() => {
|
|
161
|
-
if (resolved.mode !== "static")
|
|
162
|
-
return;
|
|
163
|
-
let cancelled = false;
|
|
164
|
-
const setStatusAndNotify = (next) => {
|
|
165
|
-
setStatus(next);
|
|
166
|
-
resolved.onStatusChange?.(next);
|
|
167
|
-
};
|
|
168
|
-
setStatusAndNotify("loading");
|
|
169
|
-
setErrorMsg("");
|
|
170
|
-
setStaticHtml(null);
|
|
171
|
-
async function run() {
|
|
172
|
-
try {
|
|
173
|
-
const decoder = new TextDecoder();
|
|
174
|
-
const chunks = [];
|
|
175
|
-
const bridge = new WasiBridge({
|
|
176
|
-
args: [resolved.wasm.toString(), ...resolved.resolveArgv(resolved.size)],
|
|
177
|
-
env: resolved.env,
|
|
178
|
-
stdout: (data) => chunks.push(new Uint8Array(data)),
|
|
179
|
-
stderr: () => { },
|
|
180
|
-
onExit: (code) => {
|
|
181
|
-
if (!cancelled) {
|
|
182
|
-
const total = chunks.reduce((n, c) => n + c.length, 0);
|
|
183
|
-
const merged = new Uint8Array(total);
|
|
184
|
-
let offset = 0;
|
|
185
|
-
for (const c of chunks) {
|
|
186
|
-
merged.set(c, offset);
|
|
187
|
-
offset += c.length;
|
|
188
|
-
}
|
|
189
|
-
setStaticHtml(ansiToHtml(decoder.decode(merged)));
|
|
190
|
-
setStatusAndNotify("exited");
|
|
191
|
-
resolved.onExit?.(code);
|
|
192
|
-
}
|
|
193
|
-
},
|
|
194
|
-
});
|
|
195
|
-
const wasmApp = await instantiateApp(resolved.wasm, bridge);
|
|
196
|
-
if (cancelled)
|
|
197
|
-
return;
|
|
198
|
-
setStatusAndNotify("running");
|
|
199
|
-
await wasmApp.run();
|
|
200
|
-
}
|
|
201
|
-
catch (e) {
|
|
202
|
-
if (!cancelled) {
|
|
203
|
-
setStatusAndNotify("error");
|
|
204
|
-
setErrorMsg(e instanceof Error ? e.message : String(e));
|
|
205
|
-
resolved.onError?.(e);
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
run();
|
|
210
|
-
return () => { cancelled = true; };
|
|
211
|
-
}, [
|
|
212
|
-
resolved.mode,
|
|
213
|
-
resolved.wasm,
|
|
214
|
-
resolved.resolveArgv,
|
|
215
|
-
resolved.env,
|
|
216
|
-
resolved.size.cols,
|
|
217
|
-
resolved.size.rows,
|
|
218
|
-
resolved.onExit,
|
|
219
|
-
resolved.onError,
|
|
220
|
-
resolved.onStatusChange,
|
|
221
|
-
]);
|
|
222
|
-
// ── Render ───────────────────────────────────────────────────────────────
|
|
223
|
-
const bg = resolved.terminal.theme?.background ?? "#1a1b26";
|
|
224
|
-
const fg = resolved.terminal.theme?.foreground ?? "#a9b1d6";
|
|
225
|
-
if (resolved.mode === "static") {
|
|
226
|
-
return (_jsxs("div", { className: props.className, style: {
|
|
227
|
-
position: "relative",
|
|
228
|
-
background: bg,
|
|
229
|
-
borderRadius: 6,
|
|
230
|
-
overflow: "hidden",
|
|
231
|
-
...props.style,
|
|
232
|
-
}, children: [status === "loading" && _jsx("div", { style: overlayStyle, children: "Loading\u2026" }), status === "error" && (_jsxs("div", { style: { ...overlayStyle, color: "#f7768e" }, children: ["Error: ", errorMsg] })), staticHtml !== null && (_jsx("pre", { style: {
|
|
233
|
-
margin: 0,
|
|
234
|
-
padding: "0.5em",
|
|
235
|
-
fontFamily: resolved.terminal.fontFamily,
|
|
236
|
-
fontSize: resolved.terminal.fontSize,
|
|
237
|
-
color: fg,
|
|
238
|
-
lineHeight: 1.2,
|
|
239
|
-
background: "transparent",
|
|
240
|
-
overflow: "auto",
|
|
241
|
-
}, dangerouslySetInnerHTML: { __html: staticHtml } }))] }));
|
|
242
|
-
}
|
|
243
154
|
return (_jsxs("div", { ref: wrapperRef, className: props.className, style: {
|
|
244
155
|
position: "relative",
|
|
245
156
|
display: "inline-block",
|
|
246
|
-
background:
|
|
157
|
+
background: resolved.terminal.theme?.background ?? "#1a1b26",
|
|
247
158
|
borderRadius: 6,
|
|
248
159
|
overflow: "hidden",
|
|
249
160
|
...props.style,
|
package/dist/core/index.d.ts
CHANGED
package/dist/core/index.js
CHANGED
package/dist/core/normalize.js
CHANGED
|
@@ -44,11 +44,12 @@ export function resolveTuiPreviewProps(props) {
|
|
|
44
44
|
cols: Math.max(1, props.size?.cols ?? DEFAULT_SIZE.cols),
|
|
45
45
|
rows: Math.max(1, props.size?.rows ?? DEFAULT_SIZE.rows),
|
|
46
46
|
};
|
|
47
|
+
const mode = (props.mode ?? "terminal");
|
|
47
48
|
return {
|
|
48
49
|
wasm: props.wasm,
|
|
49
50
|
env: props.env ?? EMPTY_ENV,
|
|
50
|
-
interactive: props.interactive ?? true,
|
|
51
|
-
mode
|
|
51
|
+
interactive: mode === "static" ? false : (props.interactive ?? true),
|
|
52
|
+
mode,
|
|
52
53
|
fit,
|
|
53
54
|
size,
|
|
54
55
|
terminal: {
|
package/dist/core/wasi.js
CHANGED
|
@@ -191,11 +191,18 @@ export class WasiExitError extends Error {
|
|
|
191
191
|
this.code = code;
|
|
192
192
|
}
|
|
193
193
|
}
|
|
194
|
+
/** Compiled module cache — keyed by URL string, persists for the page lifetime. */
|
|
195
|
+
const moduleCache = new Map();
|
|
194
196
|
/** Load and instantiate a WASM TUI app with a WasiBridge */
|
|
195
197
|
export async function instantiateApp(source, bridge) {
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
|
|
198
|
+
const key = source.toString();
|
|
199
|
+
let module = moduleCache.get(key);
|
|
200
|
+
if (!module) {
|
|
201
|
+
const response = await fetch(source);
|
|
202
|
+
const bytes = await response.arrayBuffer();
|
|
203
|
+
module = await WebAssembly.compile(bytes);
|
|
204
|
+
moduleCache.set(key, module);
|
|
205
|
+
}
|
|
199
206
|
const importObject = {
|
|
200
207
|
wasi_snapshot_preview1: bridge.imports,
|
|
201
208
|
};
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var K=Object.defineProperty;var X=(t,e,n)=>e in t?K(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n;var W=(t,e,n)=>X(t,typeof e!="symbol"?e+"":e,n);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const M=require("react/jsx-runtime"),b=require("react"),j=["#000000","#cd0000","#00cd00","#cdcd00","#0000ee","#cd00cd","#00cdcd","#e5e5e5","#7f7f7f","#ff0000","#00ff00","#ffff00","#5c5cff","#ff00ff","#00ffff","#ffffff"];function Q(t){if(t<16)return j[t];if(t<232){const n=t-16,o=Math.floor(n/36),a=Math.floor(n%36/6),r=n%6,i=c=>c===0?0:c*40+55;return`rgb(${i(o)},${i(a)},${i(r)})`}const e=(t-232)*10+8;return`rgb(${e},${e},${e})`}function V(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function ee(t){let e=null,n=null,o=!1,a=!1,r=!1;const i=[];let c="",u="";function h(){const s=[];return e&&s.push(`color:${e}`),n&&s.push(`background-color:${n}`),o&&s.push("font-weight:bold"),a&&s.push("font-style:italic"),r&&s.push("text-decoration:underline"),s.join(";")}function m(){c&&(i.push(u?`<span style="${u}">${V(c)}</span>`:V(c)),c="")}function v(s){m();let f=0;for(;f<s.length;){const l=s[f];l===0?(e=null,n=null,o=!1,a=!1,r=!1):l===1?o=!0:l===22?o=!1:l===3?a=!0:l===23?a=!1:l===4?r=!0:l===24?r=!1:l>=30&&l<=37?e=j[l-30]:l===38?s[f+1]===2&&f+4<s.length?(e=`rgb(${s[f+2]},${s[f+3]},${s[f+4]})`,f+=4):s[f+1]===5&&f+2<s.length&&(e=Q(s[f+2]),f+=2):l===39?e=null:l>=40&&l<=47?n=j[l-40]:l===48?s[f+1]===2&&f+4<s.length?(n=`rgb(${s[f+2]},${s[f+3]},${s[f+4]})`,f+=4):s[f+1]===5&&f+2<s.length&&(n=Q(s[f+2]),f+=2):l===49?n=null:l>=90&&l<=97?e=j[l-82]:l>=100&&l<=107&&(n=j[l-92]),f++}u=h()}let d=0;for(;d<t.length;){const s=t[d];if(s==="\x1B"&&d+1<t.length&&t[d+1]==="["){const f=d+2;let l=f;for(;l<t.length&&(t.charCodeAt(l)<64||t.charCodeAt(l)>126);)l++;if(l<t.length){if(t[l]==="m"){const F=t.slice(f,l),I=F?F.split(";").map(y=>parseInt(y,10)||0):[0];v(I)}d=l+1}else d++}else if(s==="\r")d++;else{const f=h();f!==u&&(m(),u=f),c+=s,d++}}return m(),i.join("")}let p=null;function te(){return p||(p=Promise.resolve().then(()=>require("./ghostty-web-DkOZu5AZ.cjs")).then(async t=>(await t.init(),t))),p}const k={cols:80,rows:24},G={},ne=[];function re(t){return"wasm"in t}function Y(t){const e=t??ne;return typeof e=="function"?e:()=>e}function ie(t){return t.cols!==void 0||t.rows!==void 0?{fit:"none",size:{cols:Math.max(1,t.cols??k.cols),rows:Math.max(1,t.rows??k.rows)}}:{fit:"container",size:k}}let Z=!1;function se(t){!t||Z||(Z=!0,console.warn("[tui-preview] Legacy props (`app`, `args`, `cols`, `rows`, `fontSize`, `fontFamily`, `theme`) are deprecated. Use `wasm`, `argv`, `fit`, `size`, and `terminal`."))}function oe(t){var o,a,r,i,c,u,h,m,v;if(re(t)){const d=t.fit??(t.size?"none":"container"),s=d==="none"?{cols:Math.max(1,((o=t.size)==null?void 0:o.cols)??k.cols),rows:Math.max(1,((a=t.size)==null?void 0:a.rows)??k.rows)}:{cols:Math.max(1,((r=t.size)==null?void 0:r.cols)??k.cols),rows:Math.max(1,((i=t.size)==null?void 0:i.rows)??k.rows)};return{wasm:t.wasm,env:t.env??G,interactive:t.interactive??!0,mode:t.mode??"terminal",fit:d,size:s,terminal:{fontSize:((c=t.terminal)==null?void 0:c.fontSize)??14,fontFamily:((u=t.terminal)==null?void 0:u.fontFamily)??"monospace",cursorBlink:((h=t.terminal)==null?void 0:h.cursorBlink)??!0,convertEol:((m=t.terminal)==null?void 0:m.convertEol)??!0,theme:(v=t.terminal)==null?void 0:v.theme},resolveArgv:Y(t.argv),onExit:t.onExit,onError:t.onError,onStatusChange:t.onStatusChange,usedLegacyProps:!1}}const{fit:e,size:n}=ie(t);return{wasm:t.app,env:t.env??G,interactive:t.interactive??!0,mode:"terminal",fit:e,size:n,terminal:{fontSize:t.fontSize??14,fontFamily:t.fontFamily??"monospace",cursorBlink:!0,convertEol:!0,theme:t.theme},resolveArgv:Y(t.args),onExit:t.onExit,onError:t.onError,onStatusChange:t.onStatusChange,usedLegacyProps:!0}}const z=0,ce=6,P=8,le=0,J=1,ae=2;class N{constructor(e){W(this,"inputQueue",[]);W(this,"memory");this.opts=e}pushInput(e){const n=typeof e=="string"?new TextEncoder().encode(e):e;this.inputQueue.push(n)}attachMemory(e){this.memory=e}view(){return new DataView(this.memory.buffer)}u8(){return new Uint8Array(this.memory.buffer)}get imports(){return{args_sizes_get:(e,n)=>{const{args:o}=this.opts,a=new TextEncoder,r=o.reduce((i,c)=>i+a.encode(c).length+1,0);return this.view().setUint32(e,o.length,!0),this.view().setUint32(n,r,!0),z},args_get:(e,n)=>{const o=new TextEncoder,a=this.u8(),r=this.view();let i=n;return this.opts.args.forEach((c,u)=>{const h=o.encode(c);a.set(h,i),a[i+h.length]=0,r.setUint32(e+u*4,i,!0),i+=h.length+1}),z},environ_sizes_get:(e,n)=>{const o=this.envEntries(),a=new TextEncoder,r=o.reduce((i,c)=>i+a.encode(c).length+1,0);return this.view().setUint32(e,o.length,!0),this.view().setUint32(n,r,!0),z},environ_get:(e,n)=>{const o=new TextEncoder,a=this.u8(),r=this.view();let i=n;return this.envEntries().forEach((c,u)=>{const h=o.encode(c);a.set(h,i),a[i+h.length]=0,r.setUint32(e+u*4,i,!0),i+=h.length+1}),z},fd_write:(e,n,o,a)=>{if(e!==J&&e!==ae)return P;const r=this.view(),i=this.u8();let c=0;const u=[];for(let v=0;v<o;v++){const d=r.getUint32(n+v*8,!0),s=r.getUint32(n+v*8+4,!0);u.push(i.slice(d,d+s)),c+=s}const h=new Uint8Array(c);let m=0;for(const v of u)h.set(v,m),m+=v.length;return e===J?this.opts.stdout(h):this.opts.stderr(h),r.setUint32(a,c,!0),z},fd_read:(e,n,o,a)=>{if(e!==le)return P;const r=this.inputQueue.shift();if(!r)return ce;const i=this.view(),c=this.u8();let u=0;for(let h=0;h<o&&u<r.length;h++){const m=i.getUint32(n+h*8,!0),v=i.getUint32(n+h*8+4,!0),d=Math.min(v,r.length-u);c.set(r.subarray(u,u+d),m),u+=d}return i.setUint32(a,u,!0),z},poll_oneoff:(e,n,o,a)=>{const r=this.view();let i=0;for(let c=0;c<o;c++){const u=e+c*48,h=r.getUint8(u+8);if(h===0&&this.inputQueue.length>0){const m=n+i*32;r.setBigUint64(m,r.getBigUint64(u,!0),!0),r.setUint16(m+8,0,!0),r.setUint8(m+10,h),i++}}return r.setUint32(a,i,!0),z},proc_exit:e=>{throw this.opts.onExit(e),new H(e)},random_get:(e,n)=>(crypto.getRandomValues(new Uint8Array(this.memory.buffer,e,n)),z),fd_close:()=>z,fd_seek:()=>z,fd_fdstat_get:(e,n)=>(this.view().setUint8(n,e<=2?2:0),z),fd_prestat_get:()=>P,fd_prestat_dir_name:()=>P,path_open:()=>P,sched_yield:()=>z,clock_time_get:(e,n,o)=>{const a=BigInt(Date.now())*1000000n;return this.view().setBigUint64(o,a,!0),z}}}envEntries(){const e={TERM:"xterm-256color",COLORTERM:"truecolor",...this.opts.env};return Object.entries(e).map(([n,o])=>`${n}=${o}`)}}class H extends Error{constructor(e){super(`WASI exit: ${e}`),this.code=e}}async function O(t,e){const o=await(await fetch(t)).arrayBuffer(),a=await WebAssembly.compile(o),r={wasi_snapshot_preview1:e.imports},i=await WebAssembly.instantiate(a,r);e.attachMemory(i.exports.memory);const c=i.exports._start;if(!c)throw new Error("WASM module has no _start export");return{run:async()=>{try{c()}catch(u){if(!(u instanceof H))throw u}}}}function ue(t){var F,I;const e=b.useMemo(()=>oe(t),[t]),n=b.useRef(null),o=b.useRef(null),a=b.useRef(null),[r,i]=b.useState("loading"),[c,u]=b.useState(""),h=b.useRef(null),[m,v]=b.useState(e.size),[d,s]=b.useState(null);b.useEffect(()=>{se(e.usedLegacyProps)},[e.usedLegacyProps]),b.useEffect(()=>{e.mode==="terminal"&&v(e.size)},[e.mode,e.fit,e.size.cols,e.size.rows]),b.useEffect(()=>{if(e.mode!=="terminal"||e.fit!=="container"||!n.current)return;const y=new ResizeObserver(([_])=>{var E,A;const{width:T,height:x}=_.contentRect;if(T>0&&x>0){const w=((E=h.current)==null?void 0:E.w)??e.terminal.fontSize*.6,g=((A=h.current)==null?void 0:A.h)??e.terminal.fontSize*1.2;v({cols:Math.max(1,Math.floor(T/w)),rows:Math.max(1,Math.floor(x/g))})}});return y.observe(n.current),()=>y.disconnect()},[e.mode,e.fit,e.terminal.fontSize]),b.useEffect(()=>{if(e.mode!=="terminal"||!m||!o.current)return;let y=!1;const _=o.current,T=m,x=w=>{var g;i(w),(g=e.onStatusChange)==null||g.call(e,w)},E=w=>{var g;x("error"),u(w instanceof Error?w.message:String(w)),(g=e.onError)==null||g.call(e,w)};x("loading"),u("");async function A(){try{const w=await te();if(y)return;_.innerHTML="";const g=new w.Terminal({cols:T.cols,rows:T.rows,fontSize:e.terminal.fontSize,fontFamily:e.terminal.fontFamily,theme:e.terminal.theme,disableStdin:!e.interactive,cursorBlink:e.terminal.cursorBlink,convertEol:e.terminal.convertEol});a.current=g,g.open(_);let U=g.cols,R=g.rows;if(e.fit==="container"){const S=new w.FitAddon;g.loadAddon(S),S.fit(),U=g.cols,R=g.rows,n.current&&U>0&&R>0&&(h.current={w:n.current.clientWidth/U,h:n.current.clientHeight/R})}const D=e.resolveArgv({cols:U,rows:R}),B=new TextDecoder,C=new N({args:[e.wasm.toString(),...D],env:e.env,stdout:S=>g.write(B.decode(S)),stderr:S=>g.write(B.decode(S)),onExit:S=>{var q;y||(x("exited"),(q=e.onExit)==null||q.call(e,S))}});e.interactive&&g.onData(S=>C.pushInput(S));const $=await O(e.wasm,C);if(y)return;x("running"),queueMicrotask(()=>{y||$.run().catch(S=>{y||E(S)})})}catch(w){y||E(w)}}return A(),()=>{var w;y=!0,(w=a.current)==null||w.dispose(),a.current=null}},[e.mode,m,e.wasm,e.resolveArgv,e.env,e.fit,e.interactive,e.onExit,e.onError,e.onStatusChange,e.terminal.fontSize,e.terminal.fontFamily,e.terminal.theme,e.terminal.cursorBlink,e.terminal.convertEol]),b.useEffect(()=>{if(e.mode!=="static")return;let y=!1;const _=x=>{var E;i(x),(E=e.onStatusChange)==null||E.call(e,x)};_("loading"),u(""),s(null);async function T(){var x;try{const E=new TextDecoder,A=[],w=new N({args:[e.wasm.toString(),...e.resolveArgv(e.size)],env:e.env,stdout:U=>A.push(new Uint8Array(U)),stderr:()=>{},onExit:U=>{var R;if(!y){const D=A.reduce(($,S)=>$+S.length,0),B=new Uint8Array(D);let C=0;for(const $ of A)B.set($,C),C+=$.length;s(ee(E.decode(B))),_("exited"),(R=e.onExit)==null||R.call(e,U)}}}),g=await O(e.wasm,w);if(y)return;_("running"),await g.run()}catch(E){y||(_("error"),u(E instanceof Error?E.message:String(E)),(x=e.onError)==null||x.call(e,E))}}return T(),()=>{y=!0}},[e.mode,e.wasm,e.resolveArgv,e.env,e.size.cols,e.size.rows,e.onExit,e.onError,e.onStatusChange]);const f=((F=e.terminal.theme)==null?void 0:F.background)??"#1a1b26",l=((I=e.terminal.theme)==null?void 0:I.foreground)??"#a9b1d6";return e.mode==="static"?M.jsxs("div",{className:t.className,style:{position:"relative",background:f,borderRadius:6,overflow:"hidden",...t.style},children:[r==="loading"&&M.jsx("div",{style:L,children:"Loading…"}),r==="error"&&M.jsxs("div",{style:{...L,color:"#f7768e"},children:["Error: ",c]}),d!==null&&M.jsx("pre",{style:{margin:0,padding:"0.5em",fontFamily:e.terminal.fontFamily,fontSize:e.terminal.fontSize,color:l,lineHeight:1.2,background:"transparent",overflow:"auto"},dangerouslySetInnerHTML:{__html:d}})]}):M.jsxs("div",{ref:n,className:t.className,style:{position:"relative",display:"inline-block",background:f,borderRadius:6,overflow:"hidden",...t.style},children:[M.jsx("div",{ref:o,style:{display:r==="error"?"none":void 0}}),r==="loading"&&M.jsx("div",{style:L,children:"Loading…"}),r==="error"&&M.jsxs("div",{style:{...L,color:"#f7768e"},children:["Error: ",c]})]})}const L={padding:"1rem",fontFamily:"monospace",fontSize:14,color:"#a9b1d6"};exports.TuiPreview=ue;exports.WasiBridge=N;exports.WasiExitError=H;exports.instantiateApp=O;
|
|
1
|
+
"use strict";var V=Object.defineProperty;var G=(e,t,n)=>t in e?V(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var R=(e,t,n)=>G(e,typeof t!="symbol"?t+"":t,n);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const T=require("react/jsx-runtime"),v=require("react");let k=null;function H(){return k||(k=Promise.resolve().then(()=>require("./ghostty-web-DkOZu5AZ.cjs")).then(async e=>(await e.init(),e))),k}const _={cols:80,rows:24},W={},$=[];function Y(e){return"wasm"in e}function C(e){const t=e??$;return typeof t=="function"?t:()=>t}function Z(e){return e.cols!==void 0||e.rows!==void 0?{fit:"none",size:{cols:Math.max(1,e.cols??_.cols),rows:Math.max(1,e.rows??_.rows)}}:{fit:"container",size:_}}let D=!1;function J(e){!e||D||(D=!0,console.warn("[tui-preview] Legacy props (`app`, `args`, `cols`, `rows`, `fontSize`, `fontFamily`, `theme`) are deprecated. Use `wasm`, `argv`, `fit`, `size`, and `terminal`."))}function K(e){var i,o,r,s,c,u,a,h,m;if(Y(e)){const y=e.fit??(e.size?"none":"container"),d=y==="none"?{cols:Math.max(1,((i=e.size)==null?void 0:i.cols)??_.cols),rows:Math.max(1,((o=e.size)==null?void 0:o.rows)??_.rows)}:{cols:Math.max(1,((r=e.size)==null?void 0:r.cols)??_.cols),rows:Math.max(1,((s=e.size)==null?void 0:s.rows)??_.rows)},E=e.mode??"terminal";return{wasm:e.wasm,env:e.env??W,interactive:E==="static"?!1:e.interactive??!0,mode:E,fit:y,size:d,terminal:{fontSize:((c=e.terminal)==null?void 0:c.fontSize)??14,fontFamily:((u=e.terminal)==null?void 0:u.fontFamily)??"monospace",cursorBlink:((a=e.terminal)==null?void 0:a.cursorBlink)??!0,convertEol:((h=e.terminal)==null?void 0:h.convertEol)??!0,theme:(m=e.terminal)==null?void 0:m.theme},resolveArgv:C(e.argv),onExit:e.onExit,onError:e.onError,onStatusChange:e.onStatusChange,usedLegacyProps:!1}}const{fit:t,size:n}=Z(e);return{wasm:e.app,env:e.env??W,interactive:e.interactive??!0,mode:"terminal",fit:t,size:n,terminal:{fontSize:e.fontSize??14,fontFamily:e.fontFamily??"monospace",cursorBlink:!0,convertEol:!0,theme:e.theme},resolveArgv:C(e.args),onExit:e.onExit,onError:e.onError,onStatusChange:e.onStatusChange,usedLegacyProps:!0}}const w=0,X=6,b=8,tt=0,L=1,et=2;class j{constructor(t){R(this,"inputQueue",[]);R(this,"memory");this.opts=t}pushInput(t){const n=typeof t=="string"?new TextEncoder().encode(t):t;this.inputQueue.push(n)}attachMemory(t){this.memory=t}view(){return new DataView(this.memory.buffer)}u8(){return new Uint8Array(this.memory.buffer)}get imports(){return{args_sizes_get:(t,n)=>{const{args:i}=this.opts,o=new TextEncoder,r=i.reduce((s,c)=>s+o.encode(c).length+1,0);return this.view().setUint32(t,i.length,!0),this.view().setUint32(n,r,!0),w},args_get:(t,n)=>{const i=new TextEncoder,o=this.u8(),r=this.view();let s=n;return this.opts.args.forEach((c,u)=>{const a=i.encode(c);o.set(a,s),o[s+a.length]=0,r.setUint32(t+u*4,s,!0),s+=a.length+1}),w},environ_sizes_get:(t,n)=>{const i=this.envEntries(),o=new TextEncoder,r=i.reduce((s,c)=>s+o.encode(c).length+1,0);return this.view().setUint32(t,i.length,!0),this.view().setUint32(n,r,!0),w},environ_get:(t,n)=>{const i=new TextEncoder,o=this.u8(),r=this.view();let s=n;return this.envEntries().forEach((c,u)=>{const a=i.encode(c);o.set(a,s),o[s+a.length]=0,r.setUint32(t+u*4,s,!0),s+=a.length+1}),w},fd_write:(t,n,i,o)=>{if(t!==L&&t!==et)return b;const r=this.view(),s=this.u8();let c=0;const u=[];for(let m=0;m<i;m++){const y=r.getUint32(n+m*8,!0),d=r.getUint32(n+m*8+4,!0);u.push(s.slice(y,y+d)),c+=d}const a=new Uint8Array(c);let h=0;for(const m of u)a.set(m,h),h+=m.length;return t===L?this.opts.stdout(a):this.opts.stderr(a),r.setUint32(o,c,!0),w},fd_read:(t,n,i,o)=>{if(t!==tt)return b;const r=this.inputQueue.shift();if(!r)return X;const s=this.view(),c=this.u8();let u=0;for(let a=0;a<i&&u<r.length;a++){const h=s.getUint32(n+a*8,!0),m=s.getUint32(n+a*8+4,!0),y=Math.min(m,r.length-u);c.set(r.subarray(u,u+y),h),u+=y}return s.setUint32(o,u,!0),w},poll_oneoff:(t,n,i,o)=>{const r=this.view();let s=0;for(let c=0;c<i;c++){const u=t+c*48,a=r.getUint8(u+8);if(a===0&&this.inputQueue.length>0){const h=n+s*32;r.setBigUint64(h,r.getBigUint64(u,!0),!0),r.setUint16(h+8,0,!0),r.setUint8(h+10,a),s++}}return r.setUint32(o,s,!0),w},proc_exit:t=>{throw this.opts.onExit(t),new p(t)},random_get:(t,n)=>(crypto.getRandomValues(new Uint8Array(this.memory.buffer,t,n)),w),fd_close:()=>w,fd_seek:()=>w,fd_fdstat_get:(t,n)=>(this.view().setUint8(n,t<=2?2:0),w),fd_prestat_get:()=>b,fd_prestat_dir_name:()=>b,path_open:()=>b,sched_yield:()=>w,clock_time_get:(t,n,i)=>{const o=BigInt(Date.now())*1000000n;return this.view().setBigUint64(i,o,!0),w}}}envEntries(){const t={TERM:"xterm-256color",COLORTERM:"truecolor",...this.opts.env};return Object.entries(t).map(([n,i])=>`${n}=${i}`)}}class p extends Error{constructor(t){super(`WASI exit: ${t}`),this.code=t}}const I=new Map;async function N(e,t){const n=e.toString();let i=I.get(n);if(!i){const u=await(await fetch(e)).arrayBuffer();i=await WebAssembly.compile(u),I.set(n,i)}const o={wasi_snapshot_preview1:t.imports},r=await WebAssembly.instantiate(i,o);t.attachMemory(r.exports.memory);const s=r.exports._start;if(!s)throw new Error("WASM module has no _start export");return{run:async()=>{try{s()}catch(c){if(!(c instanceof p))throw c}}}}function nt(e){var y;const t=v.useMemo(()=>K(e),[e]),n=v.useRef(null),i=v.useRef(null),o=v.useRef(null),[r,s]=v.useState("loading"),[c,u]=v.useState(""),a=v.useRef(null),[h,m]=v.useState(t.size);return v.useEffect(()=>{J(t.usedLegacyProps)},[t.usedLegacyProps]),v.useEffect(()=>{m(t.size)},[t.fit,t.size.cols,t.size.rows]),v.useEffect(()=>{if(t.fit!=="container"||!n.current)return;const d=new ResizeObserver(([E])=>{var z,A;const{width:x,height:S}=E.contentRect;if(x>0&&S>0){const f=((z=a.current)==null?void 0:z.w)??t.terminal.fontSize*.6,l=((A=a.current)==null?void 0:A.h)??t.terminal.fontSize*1.2;m({cols:Math.max(1,Math.floor(x/f)),rows:Math.max(1,Math.floor(S/l))})}});return d.observe(n.current),()=>d.disconnect()},[t.fit,t.terminal.fontSize]),v.useEffect(()=>{if(!h||!i.current)return;let d=!1;const E=i.current,x=h,S=f=>{var l;s(f),(l=t.onStatusChange)==null||l.call(t,f)},z=f=>{var l;S("error"),u(f instanceof Error?f.message:String(f)),(l=t.onError)==null||l.call(t,f)};S("loading"),u("");async function A(){try{const f=await H();if(d)return;E.innerHTML="";const l=new f.Terminal({cols:x.cols,rows:x.rows,fontSize:t.terminal.fontSize,fontFamily:t.terminal.fontFamily,theme:t.terminal.theme,disableStdin:!t.interactive,cursorBlink:t.terminal.cursorBlink,convertEol:t.terminal.convertEol});o.current=l,l.open(E),t.mode==="static"&&l.write("\x1B[?25l");let U=l.cols,M=l.rows;if(t.fit==="container"){const g=new f.FitAddon;l.loadAddon(g),g.fit(),U=l.cols,M=l.rows,n.current&&U>0&&M>0&&(a.current={w:n.current.clientWidth/U,h:n.current.clientHeight/M})}const q=t.resolveArgv({cols:U,rows:M}),B=new TextDecoder,F=new j({args:[t.wasm.toString(),...q],env:t.env,stdout:g=>l.write(B.decode(g)),stderr:g=>l.write(B.decode(g)),onExit:g=>{var P;d||(S("exited"),(P=t.onExit)==null||P.call(t,g))}});t.interactive&&l.onData(g=>F.pushInput(g));const Q=await N(t.wasm,F);if(d)return;S("running"),queueMicrotask(()=>{d||Q.run().catch(g=>{d||z(g)})})}catch(f){d||z(f)}}return A(),()=>{var f;d=!0,(f=o.current)==null||f.dispose(),o.current=null}},[t.mode,h,t.wasm,t.resolveArgv,t.env,t.fit,t.interactive,t.onExit,t.onError,t.onStatusChange,t.terminal.fontSize,t.terminal.fontFamily,t.terminal.theme,t.terminal.cursorBlink,t.terminal.convertEol]),T.jsxs("div",{ref:n,className:e.className,style:{position:"relative",display:"inline-block",background:((y=t.terminal.theme)==null?void 0:y.background)??"#1a1b26",borderRadius:6,overflow:"hidden",...e.style},children:[T.jsx("div",{ref:i,style:{display:r==="error"?"none":void 0}}),r==="loading"&&T.jsx("div",{style:O,children:"Loading…"}),r==="error"&&T.jsxs("div",{style:{...O,color:"#f7768e"},children:["Error: ",c]})]})}const O={padding:"1rem",fontFamily:"monospace",fontSize:14,color:"#a9b1d6"};exports.TuiPreview=nt;exports.WasiBridge=j;exports.WasiExitError=p;exports.instantiateApp=N;
|
package/dist/index.js
CHANGED
|
@@ -1,178 +1,103 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
import { jsxs as D, jsx as
|
|
5
|
-
import { useMemo as
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
"
|
|
9
|
-
"#00cd00",
|
|
10
|
-
"#cdcd00",
|
|
11
|
-
"#0000ee",
|
|
12
|
-
"#cd00cd",
|
|
13
|
-
"#00cdcd",
|
|
14
|
-
"#e5e5e5",
|
|
15
|
-
"#7f7f7f",
|
|
16
|
-
"#ff0000",
|
|
17
|
-
"#00ff00",
|
|
18
|
-
"#ffff00",
|
|
19
|
-
"#5c5cff",
|
|
20
|
-
"#ff00ff",
|
|
21
|
-
"#00ffff",
|
|
22
|
-
"#ffffff"
|
|
23
|
-
];
|
|
24
|
-
function V(t) {
|
|
25
|
-
if (t < 16) return I[t];
|
|
26
|
-
if (t < 232) {
|
|
27
|
-
const n = t - 16, s = Math.floor(n / 36), a = Math.floor(n % 36 / 6), r = n % 6, i = (c) => c === 0 ? 0 : c * 40 + 55;
|
|
28
|
-
return `rgb(${i(s)},${i(a)},${i(r)})`;
|
|
29
|
-
}
|
|
30
|
-
const e = (t - 232) * 10 + 8;
|
|
31
|
-
return `rgb(${e},${e},${e})`;
|
|
32
|
-
}
|
|
33
|
-
function q(t) {
|
|
34
|
-
return t.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
1
|
+
var H = Object.defineProperty;
|
|
2
|
+
var $ = (e, t, n) => t in e ? H(e, t, { enumerable: !0, configurable: !0, writable: !0, value: n }) : e[t] = n;
|
|
3
|
+
var k = (e, t, n) => $(e, typeof t != "symbol" ? t + "" : t, n);
|
|
4
|
+
import { jsxs as D, jsx as L } from "react/jsx-runtime";
|
|
5
|
+
import { useMemo as Y, useRef as M, useState as R, useEffect as T } from "react";
|
|
6
|
+
let p = null;
|
|
7
|
+
function q() {
|
|
8
|
+
return p || (p = import("./ghostty-web-BfBVpf8G.js").then(async (e) => (await e.init(), e))), p;
|
|
35
9
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
let c = "", u = "";
|
|
40
|
-
function h() {
|
|
41
|
-
const o = [];
|
|
42
|
-
return e && o.push(`color:${e}`), n && o.push(`background-color:${n}`), s && o.push("font-weight:bold"), a && o.push("font-style:italic"), r && o.push("text-decoration:underline"), o.join(";");
|
|
43
|
-
}
|
|
44
|
-
function m() {
|
|
45
|
-
c && (i.push(u ? `<span style="${u}">${q(c)}</span>` : q(c)), c = "");
|
|
46
|
-
}
|
|
47
|
-
function v(o) {
|
|
48
|
-
m();
|
|
49
|
-
let f = 0;
|
|
50
|
-
for (; f < o.length; ) {
|
|
51
|
-
const l = o[f];
|
|
52
|
-
l === 0 ? (e = null, n = null, s = !1, a = !1, r = !1) : l === 1 ? s = !0 : l === 22 ? s = !1 : l === 3 ? a = !0 : l === 23 ? a = !1 : l === 4 ? r = !0 : l === 24 ? r = !1 : l >= 30 && l <= 37 ? e = I[l - 30] : l === 38 ? o[f + 1] === 2 && f + 4 < o.length ? (e = `rgb(${o[f + 2]},${o[f + 3]},${o[f + 4]})`, f += 4) : o[f + 1] === 5 && f + 2 < o.length && (e = V(o[f + 2]), f += 2) : l === 39 ? e = null : l >= 40 && l <= 47 ? n = I[l - 40] : l === 48 ? o[f + 1] === 2 && f + 4 < o.length ? (n = `rgb(${o[f + 2]},${o[f + 3]},${o[f + 4]})`, f += 4) : o[f + 1] === 5 && f + 2 < o.length && (n = V(o[f + 2]), f += 2) : l === 49 ? n = null : l >= 90 && l <= 97 ? e = I[l - 82] : l >= 100 && l <= 107 && (n = I[l - 92]), f++;
|
|
53
|
-
}
|
|
54
|
-
u = h();
|
|
55
|
-
}
|
|
56
|
-
let d = 0;
|
|
57
|
-
for (; d < t.length; ) {
|
|
58
|
-
const o = t[d];
|
|
59
|
-
if (o === "\x1B" && d + 1 < t.length && t[d + 1] === "[") {
|
|
60
|
-
const f = d + 2;
|
|
61
|
-
let l = f;
|
|
62
|
-
for (; l < t.length && (t.charCodeAt(l) < 64 || t.charCodeAt(l) > 126); )
|
|
63
|
-
l++;
|
|
64
|
-
if (l < t.length) {
|
|
65
|
-
if (t[l] === "m") {
|
|
66
|
-
const $ = t.slice(f, l), L = $ ? $.split(";").map((y) => parseInt(y, 10) || 0) : [0];
|
|
67
|
-
v(L);
|
|
68
|
-
}
|
|
69
|
-
d = l + 1;
|
|
70
|
-
} else
|
|
71
|
-
d++;
|
|
72
|
-
} else if (o === "\r")
|
|
73
|
-
d++;
|
|
74
|
-
else {
|
|
75
|
-
const f = h();
|
|
76
|
-
f !== u && (m(), u = f), c += o, d++;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
return m(), i.join("");
|
|
10
|
+
const S = { cols: 80, rows: 24 }, P = {}, Z = [];
|
|
11
|
+
function J(e) {
|
|
12
|
+
return "wasm" in e;
|
|
80
13
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
return
|
|
14
|
+
function I(e) {
|
|
15
|
+
const t = e ?? Z;
|
|
16
|
+
return typeof t == "function" ? t : () => t;
|
|
84
17
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
return "wasm" in t;
|
|
88
|
-
}
|
|
89
|
-
function Y(t) {
|
|
90
|
-
const e = t ?? se;
|
|
91
|
-
return typeof e == "function" ? e : () => e;
|
|
92
|
-
}
|
|
93
|
-
function le(t) {
|
|
94
|
-
return t.cols !== void 0 || t.rows !== void 0 ? {
|
|
18
|
+
function K(e) {
|
|
19
|
+
return e.cols !== void 0 || e.rows !== void 0 ? {
|
|
95
20
|
fit: "none",
|
|
96
21
|
size: {
|
|
97
|
-
cols: Math.max(1,
|
|
98
|
-
rows: Math.max(1,
|
|
22
|
+
cols: Math.max(1, e.cols ?? S.cols),
|
|
23
|
+
rows: Math.max(1, e.rows ?? S.rows)
|
|
99
24
|
}
|
|
100
|
-
} : { fit: "container", size:
|
|
25
|
+
} : { fit: "container", size: S };
|
|
101
26
|
}
|
|
102
|
-
let
|
|
103
|
-
function
|
|
104
|
-
!
|
|
27
|
+
let W = !1;
|
|
28
|
+
function X(e) {
|
|
29
|
+
!e || W || (W = !0, console.warn(
|
|
105
30
|
"[tui-preview] Legacy props (`app`, `args`, `cols`, `rows`, `fontSize`, `fontFamily`, `theme`) are deprecated. Use `wasm`, `argv`, `fit`, `size`, and `terminal`."
|
|
106
31
|
));
|
|
107
32
|
}
|
|
108
|
-
function
|
|
109
|
-
var
|
|
110
|
-
if (
|
|
111
|
-
const
|
|
112
|
-
cols: Math.max(1, ((
|
|
113
|
-
rows: Math.max(1, ((
|
|
33
|
+
function tt(e) {
|
|
34
|
+
var i, s, r, o, c, u, a, h, m;
|
|
35
|
+
if (J(e)) {
|
|
36
|
+
const v = e.fit ?? (e.size ? "none" : "container"), w = v === "none" ? {
|
|
37
|
+
cols: Math.max(1, ((i = e.size) == null ? void 0 : i.cols) ?? S.cols),
|
|
38
|
+
rows: Math.max(1, ((s = e.size) == null ? void 0 : s.rows) ?? S.rows)
|
|
114
39
|
} : {
|
|
115
|
-
cols: Math.max(1, ((r =
|
|
116
|
-
rows: Math.max(1, ((
|
|
117
|
-
};
|
|
40
|
+
cols: Math.max(1, ((r = e.size) == null ? void 0 : r.cols) ?? S.cols),
|
|
41
|
+
rows: Math.max(1, ((o = e.size) == null ? void 0 : o.rows) ?? S.rows)
|
|
42
|
+
}, y = e.mode ?? "terminal";
|
|
118
43
|
return {
|
|
119
|
-
wasm:
|
|
120
|
-
env:
|
|
121
|
-
interactive:
|
|
122
|
-
mode:
|
|
123
|
-
fit:
|
|
124
|
-
size:
|
|
44
|
+
wasm: e.wasm,
|
|
45
|
+
env: e.env ?? P,
|
|
46
|
+
interactive: y === "static" ? !1 : e.interactive ?? !0,
|
|
47
|
+
mode: y,
|
|
48
|
+
fit: v,
|
|
49
|
+
size: w,
|
|
125
50
|
terminal: {
|
|
126
|
-
fontSize: ((c =
|
|
127
|
-
fontFamily: ((u =
|
|
128
|
-
cursorBlink: ((
|
|
129
|
-
convertEol: ((
|
|
130
|
-
theme: (
|
|
51
|
+
fontSize: ((c = e.terminal) == null ? void 0 : c.fontSize) ?? 14,
|
|
52
|
+
fontFamily: ((u = e.terminal) == null ? void 0 : u.fontFamily) ?? "monospace",
|
|
53
|
+
cursorBlink: ((a = e.terminal) == null ? void 0 : a.cursorBlink) ?? !0,
|
|
54
|
+
convertEol: ((h = e.terminal) == null ? void 0 : h.convertEol) ?? !0,
|
|
55
|
+
theme: (m = e.terminal) == null ? void 0 : m.theme
|
|
131
56
|
},
|
|
132
|
-
resolveArgv:
|
|
133
|
-
onExit:
|
|
134
|
-
onError:
|
|
135
|
-
onStatusChange:
|
|
57
|
+
resolveArgv: I(e.argv),
|
|
58
|
+
onExit: e.onExit,
|
|
59
|
+
onError: e.onError,
|
|
60
|
+
onStatusChange: e.onStatusChange,
|
|
136
61
|
usedLegacyProps: !1
|
|
137
62
|
};
|
|
138
63
|
}
|
|
139
|
-
const { fit:
|
|
64
|
+
const { fit: t, size: n } = K(e);
|
|
140
65
|
return {
|
|
141
|
-
wasm:
|
|
142
|
-
env:
|
|
143
|
-
interactive:
|
|
66
|
+
wasm: e.app,
|
|
67
|
+
env: e.env ?? P,
|
|
68
|
+
interactive: e.interactive ?? !0,
|
|
144
69
|
mode: "terminal",
|
|
145
|
-
fit:
|
|
70
|
+
fit: t,
|
|
146
71
|
size: n,
|
|
147
72
|
terminal: {
|
|
148
|
-
fontSize:
|
|
149
|
-
fontFamily:
|
|
73
|
+
fontSize: e.fontSize ?? 14,
|
|
74
|
+
fontFamily: e.fontFamily ?? "monospace",
|
|
150
75
|
cursorBlink: !0,
|
|
151
76
|
convertEol: !0,
|
|
152
|
-
theme:
|
|
77
|
+
theme: e.theme
|
|
153
78
|
},
|
|
154
|
-
resolveArgv:
|
|
155
|
-
onExit:
|
|
156
|
-
onError:
|
|
157
|
-
onStatusChange:
|
|
79
|
+
resolveArgv: I(e.args),
|
|
80
|
+
onExit: e.onExit,
|
|
81
|
+
onError: e.onError,
|
|
82
|
+
onStatusChange: e.onStatusChange,
|
|
158
83
|
usedLegacyProps: !0
|
|
159
84
|
};
|
|
160
85
|
}
|
|
161
|
-
const
|
|
162
|
-
class
|
|
163
|
-
constructor(
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
this.opts =
|
|
86
|
+
const d = 0, et = 6, x = 8, nt = 0, O = 1, rt = 2;
|
|
87
|
+
class it {
|
|
88
|
+
constructor(t) {
|
|
89
|
+
k(this, "inputQueue", []);
|
|
90
|
+
k(this, "memory");
|
|
91
|
+
this.opts = t;
|
|
167
92
|
}
|
|
168
93
|
/** Push keyboard data from the terminal into the app's stdin */
|
|
169
|
-
pushInput(
|
|
170
|
-
const n = typeof
|
|
94
|
+
pushInput(t) {
|
|
95
|
+
const n = typeof t == "string" ? new TextEncoder().encode(t) : t;
|
|
171
96
|
this.inputQueue.push(n);
|
|
172
97
|
}
|
|
173
98
|
/** Attach the WASM instance's memory after instantiation */
|
|
174
|
-
attachMemory(
|
|
175
|
-
this.memory =
|
|
99
|
+
attachMemory(t) {
|
|
100
|
+
this.memory = t;
|
|
176
101
|
}
|
|
177
102
|
view() {
|
|
178
103
|
return new DataView(this.memory.buffer);
|
|
@@ -183,317 +108,240 @@ class K {
|
|
|
183
108
|
// ── WASI imports object ────────────────────────────────────────────────
|
|
184
109
|
get imports() {
|
|
185
110
|
return {
|
|
186
|
-
args_sizes_get: (
|
|
187
|
-
const { args:
|
|
188
|
-
return this.view().setUint32(
|
|
111
|
+
args_sizes_get: (t, n) => {
|
|
112
|
+
const { args: i } = this.opts, s = new TextEncoder(), r = i.reduce((o, c) => o + s.encode(c).length + 1, 0);
|
|
113
|
+
return this.view().setUint32(t, i.length, !0), this.view().setUint32(n, r, !0), d;
|
|
189
114
|
},
|
|
190
|
-
args_get: (
|
|
191
|
-
const
|
|
192
|
-
let
|
|
115
|
+
args_get: (t, n) => {
|
|
116
|
+
const i = new TextEncoder(), s = this.u8(), r = this.view();
|
|
117
|
+
let o = n;
|
|
193
118
|
return this.opts.args.forEach((c, u) => {
|
|
194
|
-
const
|
|
195
|
-
|
|
196
|
-
}),
|
|
119
|
+
const a = i.encode(c);
|
|
120
|
+
s.set(a, o), s[o + a.length] = 0, r.setUint32(t + u * 4, o, !0), o += a.length + 1;
|
|
121
|
+
}), d;
|
|
197
122
|
},
|
|
198
|
-
environ_sizes_get: (
|
|
199
|
-
const
|
|
200
|
-
return this.view().setUint32(
|
|
123
|
+
environ_sizes_get: (t, n) => {
|
|
124
|
+
const i = this.envEntries(), s = new TextEncoder(), r = i.reduce((o, c) => o + s.encode(c).length + 1, 0);
|
|
125
|
+
return this.view().setUint32(t, i.length, !0), this.view().setUint32(n, r, !0), d;
|
|
201
126
|
},
|
|
202
|
-
environ_get: (
|
|
203
|
-
const
|
|
204
|
-
let
|
|
127
|
+
environ_get: (t, n) => {
|
|
128
|
+
const i = new TextEncoder(), s = this.u8(), r = this.view();
|
|
129
|
+
let o = n;
|
|
205
130
|
return this.envEntries().forEach((c, u) => {
|
|
206
|
-
const
|
|
207
|
-
|
|
208
|
-
}),
|
|
131
|
+
const a = i.encode(c);
|
|
132
|
+
s.set(a, o), s[o + a.length] = 0, r.setUint32(t + u * 4, o, !0), o += a.length + 1;
|
|
133
|
+
}), d;
|
|
209
134
|
},
|
|
210
|
-
fd_write: (
|
|
211
|
-
if (
|
|
212
|
-
const r = this.view(),
|
|
135
|
+
fd_write: (t, n, i, s) => {
|
|
136
|
+
if (t !== O && t !== rt) return x;
|
|
137
|
+
const r = this.view(), o = this.u8();
|
|
213
138
|
let c = 0;
|
|
214
139
|
const u = [];
|
|
215
|
-
for (let
|
|
216
|
-
const
|
|
217
|
-
u.push(
|
|
140
|
+
for (let m = 0; m < i; m++) {
|
|
141
|
+
const v = r.getUint32(n + m * 8, !0), w = r.getUint32(n + m * 8 + 4, !0);
|
|
142
|
+
u.push(o.slice(v, v + w)), c += w;
|
|
218
143
|
}
|
|
219
|
-
const
|
|
220
|
-
let
|
|
221
|
-
for (const
|
|
222
|
-
|
|
223
|
-
return
|
|
144
|
+
const a = new Uint8Array(c);
|
|
145
|
+
let h = 0;
|
|
146
|
+
for (const m of u)
|
|
147
|
+
a.set(m, h), h += m.length;
|
|
148
|
+
return t === O ? this.opts.stdout(a) : this.opts.stderr(a), r.setUint32(s, c, !0), d;
|
|
224
149
|
},
|
|
225
|
-
fd_read: (
|
|
226
|
-
if (
|
|
150
|
+
fd_read: (t, n, i, s) => {
|
|
151
|
+
if (t !== nt) return x;
|
|
227
152
|
const r = this.inputQueue.shift();
|
|
228
|
-
if (!r) return
|
|
229
|
-
const
|
|
153
|
+
if (!r) return et;
|
|
154
|
+
const o = this.view(), c = this.u8();
|
|
230
155
|
let u = 0;
|
|
231
|
-
for (let
|
|
232
|
-
const
|
|
233
|
-
c.set(r.subarray(u, u +
|
|
156
|
+
for (let a = 0; a < i && u < r.length; a++) {
|
|
157
|
+
const h = o.getUint32(n + a * 8, !0), m = o.getUint32(n + a * 8 + 4, !0), v = Math.min(m, r.length - u);
|
|
158
|
+
c.set(r.subarray(u, u + v), h), u += v;
|
|
234
159
|
}
|
|
235
|
-
return
|
|
160
|
+
return o.setUint32(s, u, !0), d;
|
|
236
161
|
},
|
|
237
|
-
poll_oneoff: (
|
|
162
|
+
poll_oneoff: (t, n, i, s) => {
|
|
238
163
|
const r = this.view();
|
|
239
|
-
let
|
|
240
|
-
for (let c = 0; c <
|
|
241
|
-
const u =
|
|
242
|
-
if (
|
|
243
|
-
const
|
|
244
|
-
r.setBigUint64(
|
|
164
|
+
let o = 0;
|
|
165
|
+
for (let c = 0; c < i; c++) {
|
|
166
|
+
const u = t + c * 48, a = r.getUint8(u + 8);
|
|
167
|
+
if (a === 0 && this.inputQueue.length > 0) {
|
|
168
|
+
const h = n + o * 32;
|
|
169
|
+
r.setBigUint64(h, r.getBigUint64(u, !0), !0), r.setUint16(h + 8, 0, !0), r.setUint8(h + 10, a), o++;
|
|
245
170
|
}
|
|
246
171
|
}
|
|
247
|
-
return r.setUint32(
|
|
172
|
+
return r.setUint32(s, o, !0), d;
|
|
248
173
|
},
|
|
249
|
-
proc_exit: (
|
|
250
|
-
throw this.opts.onExit(
|
|
174
|
+
proc_exit: (t) => {
|
|
175
|
+
throw this.opts.onExit(t), new Q(t);
|
|
251
176
|
},
|
|
252
|
-
random_get: (
|
|
177
|
+
random_get: (t, n) => (crypto.getRandomValues(new Uint8Array(this.memory.buffer, t, n)), d),
|
|
253
178
|
// Stubs for calls TUI apps may make but we don't need to implement.
|
|
254
|
-
fd_close: () =>
|
|
255
|
-
fd_seek: () =>
|
|
256
|
-
fd_fdstat_get: (
|
|
257
|
-
fd_prestat_get: () =>
|
|
258
|
-
fd_prestat_dir_name: () =>
|
|
259
|
-
path_open: () =>
|
|
260
|
-
sched_yield: () =>
|
|
261
|
-
clock_time_get: (
|
|
262
|
-
const
|
|
263
|
-
return this.view().setBigUint64(
|
|
179
|
+
fd_close: () => d,
|
|
180
|
+
fd_seek: () => d,
|
|
181
|
+
fd_fdstat_get: (t, n) => (this.view().setUint8(n, t <= 2 ? 2 : 0), d),
|
|
182
|
+
fd_prestat_get: () => x,
|
|
183
|
+
fd_prestat_dir_name: () => x,
|
|
184
|
+
path_open: () => x,
|
|
185
|
+
sched_yield: () => d,
|
|
186
|
+
clock_time_get: (t, n, i) => {
|
|
187
|
+
const s = BigInt(Date.now()) * 1000000n;
|
|
188
|
+
return this.view().setBigUint64(i, s, !0), d;
|
|
264
189
|
}
|
|
265
190
|
};
|
|
266
191
|
}
|
|
267
192
|
envEntries() {
|
|
268
|
-
const
|
|
193
|
+
const t = {
|
|
269
194
|
TERM: "xterm-256color",
|
|
270
195
|
COLORTERM: "truecolor",
|
|
271
196
|
...this.opts.env
|
|
272
197
|
};
|
|
273
|
-
return Object.entries(
|
|
198
|
+
return Object.entries(t).map(([n, i]) => `${n}=${i}`);
|
|
274
199
|
}
|
|
275
200
|
}
|
|
276
|
-
class
|
|
277
|
-
constructor(
|
|
278
|
-
super(`WASI exit: ${
|
|
201
|
+
class Q extends Error {
|
|
202
|
+
constructor(t) {
|
|
203
|
+
super(`WASI exit: ${t}`), this.code = t;
|
|
279
204
|
}
|
|
280
205
|
}
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
206
|
+
const N = /* @__PURE__ */ new Map();
|
|
207
|
+
async function ot(e, t) {
|
|
208
|
+
const n = e.toString();
|
|
209
|
+
let i = N.get(n);
|
|
210
|
+
if (!i) {
|
|
211
|
+
const u = await (await fetch(e)).arrayBuffer();
|
|
212
|
+
i = await WebAssembly.compile(u), N.set(n, i);
|
|
213
|
+
}
|
|
214
|
+
const s = {
|
|
215
|
+
wasi_snapshot_preview1: t.imports
|
|
216
|
+
}, r = await WebAssembly.instantiate(i, s);
|
|
217
|
+
t.attachMemory(r.exports.memory);
|
|
218
|
+
const o = r.exports._start;
|
|
219
|
+
if (!o) throw new Error("WASM module has no _start export");
|
|
288
220
|
return {
|
|
289
221
|
run: async () => {
|
|
290
222
|
try {
|
|
291
|
-
|
|
292
|
-
} catch (
|
|
293
|
-
if (!(
|
|
223
|
+
o();
|
|
224
|
+
} catch (c) {
|
|
225
|
+
if (!(c instanceof Q)) throw c;
|
|
294
226
|
}
|
|
295
227
|
}
|
|
296
228
|
};
|
|
297
229
|
}
|
|
298
|
-
function
|
|
299
|
-
var
|
|
300
|
-
const
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
}, [
|
|
304
|
-
|
|
305
|
-
}, [
|
|
306
|
-
if (
|
|
307
|
-
const
|
|
308
|
-
var
|
|
309
|
-
const { width:
|
|
310
|
-
if (
|
|
311
|
-
const
|
|
312
|
-
|
|
313
|
-
cols: Math.max(1, Math.floor(
|
|
314
|
-
rows: Math.max(1, Math.floor(
|
|
230
|
+
function ut(e) {
|
|
231
|
+
var v;
|
|
232
|
+
const t = Y(() => tt(e), [e]), n = M(null), i = M(null), s = M(null), [r, o] = R("loading"), [c, u] = R(""), a = M(null), [h, m] = R(t.size);
|
|
233
|
+
return T(() => {
|
|
234
|
+
X(t.usedLegacyProps);
|
|
235
|
+
}, [t.usedLegacyProps]), T(() => {
|
|
236
|
+
m(t.size);
|
|
237
|
+
}, [t.fit, t.size.cols, t.size.rows]), T(() => {
|
|
238
|
+
if (t.fit !== "container" || !n.current) return;
|
|
239
|
+
const w = new ResizeObserver(([y]) => {
|
|
240
|
+
var z, b;
|
|
241
|
+
const { width: _, height: E } = y.contentRect;
|
|
242
|
+
if (_ > 0 && E > 0) {
|
|
243
|
+
const f = ((z = a.current) == null ? void 0 : z.w) ?? t.terminal.fontSize * 0.6, l = ((b = a.current) == null ? void 0 : b.h) ?? t.terminal.fontSize * 1.2;
|
|
244
|
+
m({
|
|
245
|
+
cols: Math.max(1, Math.floor(_ / f)),
|
|
246
|
+
rows: Math.max(1, Math.floor(E / l))
|
|
315
247
|
});
|
|
316
248
|
}
|
|
317
249
|
});
|
|
318
|
-
return
|
|
319
|
-
}, [
|
|
320
|
-
if (
|
|
321
|
-
let
|
|
322
|
-
const
|
|
323
|
-
var
|
|
324
|
-
|
|
325
|
-
},
|
|
326
|
-
var
|
|
327
|
-
|
|
250
|
+
return w.observe(n.current), () => w.disconnect();
|
|
251
|
+
}, [t.fit, t.terminal.fontSize]), T(() => {
|
|
252
|
+
if (!h || !i.current) return;
|
|
253
|
+
let w = !1;
|
|
254
|
+
const y = i.current, _ = h, E = (f) => {
|
|
255
|
+
var l;
|
|
256
|
+
o(f), (l = t.onStatusChange) == null || l.call(t, f);
|
|
257
|
+
}, z = (f) => {
|
|
258
|
+
var l;
|
|
259
|
+
E("error"), u(f instanceof Error ? f.message : String(f)), (l = t.onError) == null || l.call(t, f);
|
|
328
260
|
};
|
|
329
|
-
|
|
330
|
-
async function
|
|
261
|
+
E("loading"), u("");
|
|
262
|
+
async function b() {
|
|
331
263
|
try {
|
|
332
|
-
const
|
|
333
|
-
if (
|
|
334
|
-
|
|
335
|
-
const
|
|
336
|
-
cols:
|
|
337
|
-
rows:
|
|
338
|
-
fontSize:
|
|
339
|
-
fontFamily:
|
|
340
|
-
theme:
|
|
341
|
-
disableStdin: !
|
|
342
|
-
cursorBlink:
|
|
343
|
-
convertEol:
|
|
264
|
+
const f = await q();
|
|
265
|
+
if (w) return;
|
|
266
|
+
y.innerHTML = "";
|
|
267
|
+
const l = new f.Terminal({
|
|
268
|
+
cols: _.cols,
|
|
269
|
+
rows: _.rows,
|
|
270
|
+
fontSize: t.terminal.fontSize,
|
|
271
|
+
fontFamily: t.terminal.fontFamily,
|
|
272
|
+
theme: t.terminal.theme,
|
|
273
|
+
disableStdin: !t.interactive,
|
|
274
|
+
cursorBlink: t.terminal.cursorBlink,
|
|
275
|
+
convertEol: t.terminal.convertEol
|
|
344
276
|
});
|
|
345
|
-
|
|
346
|
-
let A =
|
|
347
|
-
if (
|
|
348
|
-
const
|
|
349
|
-
|
|
277
|
+
s.current = l, l.open(y), t.mode === "static" && l.write("\x1B[?25l");
|
|
278
|
+
let A = l.cols, U = l.rows;
|
|
279
|
+
if (t.fit === "container") {
|
|
280
|
+
const g = new f.FitAddon();
|
|
281
|
+
l.loadAddon(g), g.fit(), A = l.cols, U = l.rows, n.current && A > 0 && U > 0 && (a.current = {
|
|
350
282
|
w: n.current.clientWidth / A,
|
|
351
|
-
h: n.current.clientHeight /
|
|
283
|
+
h: n.current.clientHeight / U
|
|
352
284
|
});
|
|
353
285
|
}
|
|
354
|
-
const
|
|
355
|
-
args: [
|
|
356
|
-
env:
|
|
357
|
-
stdout: (
|
|
358
|
-
stderr: (
|
|
359
|
-
onExit: (
|
|
360
|
-
var
|
|
361
|
-
|
|
286
|
+
const V = t.resolveArgv({ cols: A, rows: U }), F = new TextDecoder(), B = new it({
|
|
287
|
+
args: [t.wasm.toString(), ...V],
|
|
288
|
+
env: t.env,
|
|
289
|
+
stdout: (g) => l.write(F.decode(g)),
|
|
290
|
+
stderr: (g) => l.write(F.decode(g)),
|
|
291
|
+
onExit: (g) => {
|
|
292
|
+
var C;
|
|
293
|
+
w || (E("exited"), (C = t.onExit) == null || C.call(t, g));
|
|
362
294
|
}
|
|
363
295
|
});
|
|
364
|
-
|
|
365
|
-
const
|
|
366
|
-
if (
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
296
|
+
t.interactive && l.onData((g) => B.pushInput(g));
|
|
297
|
+
const G = await ot(t.wasm, B);
|
|
298
|
+
if (w) return;
|
|
299
|
+
E("running"), queueMicrotask(() => {
|
|
300
|
+
w || G.run().catch((g) => {
|
|
301
|
+
w || z(g);
|
|
370
302
|
});
|
|
371
303
|
});
|
|
372
|
-
} catch (
|
|
373
|
-
|
|
304
|
+
} catch (f) {
|
|
305
|
+
w || z(f);
|
|
374
306
|
}
|
|
375
307
|
}
|
|
376
|
-
return
|
|
377
|
-
var
|
|
378
|
-
|
|
308
|
+
return b(), () => {
|
|
309
|
+
var f;
|
|
310
|
+
w = !0, (f = s.current) == null || f.dispose(), s.current = null;
|
|
379
311
|
};
|
|
380
312
|
}, [
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
]),
|
|
397
|
-
if (e.mode !== "static") return;
|
|
398
|
-
let y = !1;
|
|
399
|
-
const _ = (b) => {
|
|
400
|
-
var E;
|
|
401
|
-
i(b), (E = e.onStatusChange) == null || E.call(e, b);
|
|
402
|
-
};
|
|
403
|
-
_("loading"), u(""), o(null);
|
|
404
|
-
async function U() {
|
|
405
|
-
var b;
|
|
406
|
-
try {
|
|
407
|
-
const E = new TextDecoder(), x = [], w = new K({
|
|
408
|
-
args: [e.wasm.toString(), ...e.resolveArgv(e.size)],
|
|
409
|
-
env: e.env,
|
|
410
|
-
stdout: (A) => x.push(new Uint8Array(A)),
|
|
411
|
-
stderr: () => {
|
|
412
|
-
},
|
|
413
|
-
onExit: (A) => {
|
|
414
|
-
var M;
|
|
415
|
-
if (!y) {
|
|
416
|
-
const H = x.reduce((k, S) => k + S.length, 0), R = new Uint8Array(H);
|
|
417
|
-
let F = 0;
|
|
418
|
-
for (const k of x)
|
|
419
|
-
R.set(k, F), F += k.length;
|
|
420
|
-
o(ie(E.decode(R))), _("exited"), (M = e.onExit) == null || M.call(e, A);
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
}), g = await X(e.wasm, w);
|
|
424
|
-
if (y) return;
|
|
425
|
-
_("running"), await g.run();
|
|
426
|
-
} catch (E) {
|
|
427
|
-
y || (_("error"), u(E instanceof Error ? E.message : String(E)), (b = e.onError) == null || b.call(e, E));
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
return U(), () => {
|
|
431
|
-
y = !0;
|
|
432
|
-
};
|
|
433
|
-
}, [
|
|
434
|
-
e.mode,
|
|
435
|
-
e.wasm,
|
|
436
|
-
e.resolveArgv,
|
|
437
|
-
e.env,
|
|
438
|
-
e.size.cols,
|
|
439
|
-
e.size.rows,
|
|
440
|
-
e.onExit,
|
|
441
|
-
e.onError,
|
|
442
|
-
e.onStatusChange
|
|
443
|
-
]);
|
|
444
|
-
const f = (($ = e.terminal.theme) == null ? void 0 : $.background) ?? "#1a1b26", l = ((L = e.terminal.theme) == null ? void 0 : L.foreground) ?? "#a9b1d6";
|
|
445
|
-
return e.mode === "static" ? /* @__PURE__ */ D(
|
|
446
|
-
"div",
|
|
447
|
-
{
|
|
448
|
-
className: t.className,
|
|
449
|
-
style: {
|
|
450
|
-
position: "relative",
|
|
451
|
-
background: f,
|
|
452
|
-
borderRadius: 6,
|
|
453
|
-
overflow: "hidden",
|
|
454
|
-
...t.style
|
|
455
|
-
},
|
|
456
|
-
children: [
|
|
457
|
-
r === "loading" && /* @__PURE__ */ p("div", { style: N, children: "Loading…" }),
|
|
458
|
-
r === "error" && /* @__PURE__ */ D("div", { style: { ...N, color: "#f7768e" }, children: [
|
|
459
|
-
"Error: ",
|
|
460
|
-
c
|
|
461
|
-
] }),
|
|
462
|
-
d !== null && /* @__PURE__ */ p(
|
|
463
|
-
"pre",
|
|
464
|
-
{
|
|
465
|
-
style: {
|
|
466
|
-
margin: 0,
|
|
467
|
-
padding: "0.5em",
|
|
468
|
-
fontFamily: e.terminal.fontFamily,
|
|
469
|
-
fontSize: e.terminal.fontSize,
|
|
470
|
-
color: l,
|
|
471
|
-
lineHeight: 1.2,
|
|
472
|
-
background: "transparent",
|
|
473
|
-
overflow: "auto"
|
|
474
|
-
},
|
|
475
|
-
dangerouslySetInnerHTML: { __html: d }
|
|
476
|
-
}
|
|
477
|
-
)
|
|
478
|
-
]
|
|
479
|
-
}
|
|
480
|
-
) : /* @__PURE__ */ D(
|
|
313
|
+
t.mode,
|
|
314
|
+
h,
|
|
315
|
+
t.wasm,
|
|
316
|
+
t.resolveArgv,
|
|
317
|
+
t.env,
|
|
318
|
+
t.fit,
|
|
319
|
+
t.interactive,
|
|
320
|
+
t.onExit,
|
|
321
|
+
t.onError,
|
|
322
|
+
t.onStatusChange,
|
|
323
|
+
t.terminal.fontSize,
|
|
324
|
+
t.terminal.fontFamily,
|
|
325
|
+
t.terminal.theme,
|
|
326
|
+
t.terminal.cursorBlink,
|
|
327
|
+
t.terminal.convertEol
|
|
328
|
+
]), /* @__PURE__ */ D(
|
|
481
329
|
"div",
|
|
482
330
|
{
|
|
483
331
|
ref: n,
|
|
484
|
-
className:
|
|
332
|
+
className: e.className,
|
|
485
333
|
style: {
|
|
486
334
|
position: "relative",
|
|
487
335
|
display: "inline-block",
|
|
488
|
-
background:
|
|
336
|
+
background: ((v = t.terminal.theme) == null ? void 0 : v.background) ?? "#1a1b26",
|
|
489
337
|
borderRadius: 6,
|
|
490
338
|
overflow: "hidden",
|
|
491
|
-
...
|
|
339
|
+
...e.style
|
|
492
340
|
},
|
|
493
341
|
children: [
|
|
494
|
-
/* @__PURE__ */
|
|
495
|
-
r === "loading" && /* @__PURE__ */
|
|
496
|
-
r === "error" && /* @__PURE__ */ D("div", { style: { ...
|
|
342
|
+
/* @__PURE__ */ L("div", { ref: i, style: { display: r === "error" ? "none" : void 0 } }),
|
|
343
|
+
r === "loading" && /* @__PURE__ */ L("div", { style: j, children: "Loading…" }),
|
|
344
|
+
r === "error" && /* @__PURE__ */ D("div", { style: { ...j, color: "#f7768e" }, children: [
|
|
497
345
|
"Error: ",
|
|
498
346
|
c
|
|
499
347
|
] })
|
|
@@ -501,15 +349,15 @@ function ve(t) {
|
|
|
501
349
|
}
|
|
502
350
|
);
|
|
503
351
|
}
|
|
504
|
-
const
|
|
352
|
+
const j = {
|
|
505
353
|
padding: "1rem",
|
|
506
354
|
fontFamily: "monospace",
|
|
507
355
|
fontSize: 14,
|
|
508
356
|
color: "#a9b1d6"
|
|
509
357
|
};
|
|
510
358
|
export {
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
359
|
+
ut as TuiPreview,
|
|
360
|
+
it as WasiBridge,
|
|
361
|
+
Q as WasiExitError,
|
|
362
|
+
ot as instantiateApp
|
|
515
363
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dkkoval/tui-preview",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "React component for embedding interactive TUI apps via ghostty-web",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/dmk/tui-preview"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://github.com/dmk/tui-preview#readme",
|
|
10
|
+
"bugs": {
|
|
11
|
+
"url": "https://github.com/dmk/tui-preview/issues"
|
|
12
|
+
},
|
|
5
13
|
"type": "module",
|
|
6
14
|
"license": "MIT",
|
|
7
15
|
"sideEffects": false,
|
package/dist/core/ansi.d.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Minimal ANSI SGR → HTML converter.
|
|
3
|
-
*
|
|
4
|
-
* Handles the subset used by typical wasm32-wasi TUI apps:
|
|
5
|
-
* - Reset (0)
|
|
6
|
-
* - Bold, italic, underline (1/3/4 and their off codes)
|
|
7
|
-
* - Standard 16-color fg/bg (30–37, 39, 40–47, 49, 90–97, 100–107)
|
|
8
|
-
* - 256-color fg/bg (38;5;N / 48;5;N)
|
|
9
|
-
* - 24-bit truecolor fg/bg (38;2;R;G;B / 48;2;R;G;B)
|
|
10
|
-
*
|
|
11
|
-
* Non-SGR CSI sequences (cursor movement etc.) are silently dropped,
|
|
12
|
-
* which is correct for static capture where only the final text matters.
|
|
13
|
-
*/
|
|
14
|
-
/** Convert ANSI escape codes to an HTML string of styled `<span>` elements. */
|
|
15
|
-
export declare function ansiToHtml(input: string): string;
|
package/dist/core/ansi.js
DELETED
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Minimal ANSI SGR → HTML converter.
|
|
3
|
-
*
|
|
4
|
-
* Handles the subset used by typical wasm32-wasi TUI apps:
|
|
5
|
-
* - Reset (0)
|
|
6
|
-
* - Bold, italic, underline (1/3/4 and their off codes)
|
|
7
|
-
* - Standard 16-color fg/bg (30–37, 39, 40–47, 49, 90–97, 100–107)
|
|
8
|
-
* - 256-color fg/bg (38;5;N / 48;5;N)
|
|
9
|
-
* - 24-bit truecolor fg/bg (38;2;R;G;B / 48;2;R;G;B)
|
|
10
|
-
*
|
|
11
|
-
* Non-SGR CSI sequences (cursor movement etc.) are silently dropped,
|
|
12
|
-
* which is correct for static capture where only the final text matters.
|
|
13
|
-
*/
|
|
14
|
-
// Standard xterm 16-color palette
|
|
15
|
-
const ANSI16 = [
|
|
16
|
-
"#000000", "#cd0000", "#00cd00", "#cdcd00",
|
|
17
|
-
"#0000ee", "#cd00cd", "#00cdcd", "#e5e5e5",
|
|
18
|
-
"#7f7f7f", "#ff0000", "#00ff00", "#ffff00",
|
|
19
|
-
"#5c5cff", "#ff00ff", "#00ffff", "#ffffff",
|
|
20
|
-
];
|
|
21
|
-
function color256(n) {
|
|
22
|
-
if (n < 16)
|
|
23
|
-
return ANSI16[n];
|
|
24
|
-
if (n < 232) {
|
|
25
|
-
const i = n - 16;
|
|
26
|
-
const r = Math.floor(i / 36);
|
|
27
|
-
const g = Math.floor((i % 36) / 6);
|
|
28
|
-
const b = i % 6;
|
|
29
|
-
const v = (x) => (x === 0 ? 0 : x * 40 + 55);
|
|
30
|
-
return `rgb(${v(r)},${v(g)},${v(b)})`;
|
|
31
|
-
}
|
|
32
|
-
const grey = (n - 232) * 10 + 8;
|
|
33
|
-
return `rgb(${grey},${grey},${grey})`;
|
|
34
|
-
}
|
|
35
|
-
function escHtml(s) {
|
|
36
|
-
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
37
|
-
}
|
|
38
|
-
/** Convert ANSI escape codes to an HTML string of styled `<span>` elements. */
|
|
39
|
-
export function ansiToHtml(input) {
|
|
40
|
-
// Current SGR state
|
|
41
|
-
let fg = null;
|
|
42
|
-
let bg = null;
|
|
43
|
-
let bold = false;
|
|
44
|
-
let italic = false;
|
|
45
|
-
let underline = false;
|
|
46
|
-
const result = [];
|
|
47
|
-
let buf = "";
|
|
48
|
-
let bufStyle = "";
|
|
49
|
-
function buildStyle() {
|
|
50
|
-
const parts = [];
|
|
51
|
-
if (fg)
|
|
52
|
-
parts.push(`color:${fg}`);
|
|
53
|
-
if (bg)
|
|
54
|
-
parts.push(`background-color:${bg}`);
|
|
55
|
-
if (bold)
|
|
56
|
-
parts.push("font-weight:bold");
|
|
57
|
-
if (italic)
|
|
58
|
-
parts.push("font-style:italic");
|
|
59
|
-
if (underline)
|
|
60
|
-
parts.push("text-decoration:underline");
|
|
61
|
-
return parts.join(";");
|
|
62
|
-
}
|
|
63
|
-
function flush() {
|
|
64
|
-
if (!buf)
|
|
65
|
-
return;
|
|
66
|
-
result.push(bufStyle ? `<span style="${bufStyle}">${escHtml(buf)}</span>` : escHtml(buf));
|
|
67
|
-
buf = "";
|
|
68
|
-
}
|
|
69
|
-
function applySgr(params) {
|
|
70
|
-
flush();
|
|
71
|
-
let i = 0;
|
|
72
|
-
while (i < params.length) {
|
|
73
|
-
const p = params[i];
|
|
74
|
-
if (p === 0) {
|
|
75
|
-
fg = null;
|
|
76
|
-
bg = null;
|
|
77
|
-
bold = false;
|
|
78
|
-
italic = false;
|
|
79
|
-
underline = false;
|
|
80
|
-
}
|
|
81
|
-
else if (p === 1) {
|
|
82
|
-
bold = true;
|
|
83
|
-
}
|
|
84
|
-
else if (p === 22) {
|
|
85
|
-
bold = false;
|
|
86
|
-
}
|
|
87
|
-
else if (p === 3) {
|
|
88
|
-
italic = true;
|
|
89
|
-
}
|
|
90
|
-
else if (p === 23) {
|
|
91
|
-
italic = false;
|
|
92
|
-
}
|
|
93
|
-
else if (p === 4) {
|
|
94
|
-
underline = true;
|
|
95
|
-
}
|
|
96
|
-
else if (p === 24) {
|
|
97
|
-
underline = false;
|
|
98
|
-
}
|
|
99
|
-
else if (p >= 30 && p <= 37) {
|
|
100
|
-
fg = ANSI16[p - 30];
|
|
101
|
-
}
|
|
102
|
-
else if (p === 38) {
|
|
103
|
-
if (params[i + 1] === 2 && i + 4 < params.length) {
|
|
104
|
-
fg = `rgb(${params[i + 2]},${params[i + 3]},${params[i + 4]})`;
|
|
105
|
-
i += 4;
|
|
106
|
-
}
|
|
107
|
-
else if (params[i + 1] === 5 && i + 2 < params.length) {
|
|
108
|
-
fg = color256(params[i + 2]);
|
|
109
|
-
i += 2;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
else if (p === 39) {
|
|
113
|
-
fg = null;
|
|
114
|
-
}
|
|
115
|
-
else if (p >= 40 && p <= 47) {
|
|
116
|
-
bg = ANSI16[p - 40];
|
|
117
|
-
}
|
|
118
|
-
else if (p === 48) {
|
|
119
|
-
if (params[i + 1] === 2 && i + 4 < params.length) {
|
|
120
|
-
bg = `rgb(${params[i + 2]},${params[i + 3]},${params[i + 4]})`;
|
|
121
|
-
i += 4;
|
|
122
|
-
}
|
|
123
|
-
else if (params[i + 1] === 5 && i + 2 < params.length) {
|
|
124
|
-
bg = color256(params[i + 2]);
|
|
125
|
-
i += 2;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
else if (p === 49) {
|
|
129
|
-
bg = null;
|
|
130
|
-
}
|
|
131
|
-
else if (p >= 90 && p <= 97) {
|
|
132
|
-
fg = ANSI16[p - 82];
|
|
133
|
-
}
|
|
134
|
-
else if (p >= 100 && p <= 107) {
|
|
135
|
-
bg = ANSI16[p - 92];
|
|
136
|
-
}
|
|
137
|
-
i++;
|
|
138
|
-
}
|
|
139
|
-
bufStyle = buildStyle();
|
|
140
|
-
}
|
|
141
|
-
let i = 0;
|
|
142
|
-
while (i < input.length) {
|
|
143
|
-
const ch = input[i];
|
|
144
|
-
if (ch === "\x1b" && i + 1 < input.length && input[i + 1] === "[") {
|
|
145
|
-
// CSI sequence: find the final byte (0x40–0x7e)
|
|
146
|
-
const seqStart = i + 2;
|
|
147
|
-
let end = seqStart;
|
|
148
|
-
while (end < input.length && (input.charCodeAt(end) < 0x40 || input.charCodeAt(end) > 0x7e)) {
|
|
149
|
-
end++;
|
|
150
|
-
}
|
|
151
|
-
if (end < input.length) {
|
|
152
|
-
if (input[end] === "m") {
|
|
153
|
-
const seq = input.slice(seqStart, end);
|
|
154
|
-
const params = seq ? seq.split(";").map((s) => parseInt(s, 10) || 0) : [0];
|
|
155
|
-
applySgr(params);
|
|
156
|
-
}
|
|
157
|
-
// Non-SGR CSI (cursor movement etc.) — silently skip
|
|
158
|
-
i = end + 1;
|
|
159
|
-
}
|
|
160
|
-
else {
|
|
161
|
-
// Incomplete sequence at end of input — skip escape char
|
|
162
|
-
i++;
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
else if (ch === "\r") {
|
|
166
|
-
i++;
|
|
167
|
-
}
|
|
168
|
-
else {
|
|
169
|
-
// Regular character — append, flushing if style changed
|
|
170
|
-
const style = buildStyle();
|
|
171
|
-
if (style !== bufStyle) {
|
|
172
|
-
flush();
|
|
173
|
-
bufStyle = style;
|
|
174
|
-
}
|
|
175
|
-
buf += ch;
|
|
176
|
-
i++;
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
flush();
|
|
180
|
-
return result.join("");
|
|
181
|
-
}
|