termcut 0.4.0 → 0.5.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.
- package/README.md +12 -0
- package/package.json +1 -1
- package/src/cast.ts +9 -3
- package/src/cli.ts +29 -9
- package/src/config.ts +11 -0
- package/src/recorder.ts +124 -7
- package/src/renderer/bundle.ts +8 -2
- package/src/renderer/generated/page.js +1 -1
- package/src/renderer/page-entry.ts +40 -0
- package/src/renderer/page.ts +54 -1
- package/src/renderer/webview.ts +42 -3
- package/src/screen.ts +15 -0
- package/src/types.ts +49 -1
- package/src/video.ts +27 -3
package/README.md
CHANGED
|
@@ -40,6 +40,17 @@ export default defineVideo({ output: "demo.gif" }, async (t) => {
|
|
|
40
40
|
tcut demo.video.ts
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
+
Record a real browser next to (or over) the terminal, for dev-server demos:
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
defineVideo({ output: "demo.mp4", browser: { position: "overlay" } }, async (t) => {
|
|
47
|
+
await t.run("bun run dev </dev/null >/tmp/dev.log 2>&1 &");
|
|
48
|
+
await t.browser.goto("http://localhost:5173");
|
|
49
|
+
await t.run("sed -i '' 's/Hello/Hi/' src/App.tsx"); // HMR updates the page
|
|
50
|
+
await t.focus("browser");
|
|
51
|
+
});
|
|
52
|
+
```
|
|
53
|
+
|
|
43
54
|
Re-render any recording without re-running it — ~600 themes ([Ghostty's collection](https://github.com/mbadolato/iTerm2-Color-Schemes)), `tcut themes` lists them:
|
|
44
55
|
|
|
45
56
|
```sh
|
|
@@ -57,6 +68,7 @@ tcut publish demo.gif # → https://…/3f9a1c2b7d4e/demo.gif
|
|
|
57
68
|
|
|
58
69
|
- [Examples](https://github.com/AmanVarshney01/tcut/tree/main/packages/tcut/examples) — driving an interactive TUI, recording Claude Code / Codex
|
|
59
70
|
- [Reference](https://github.com/AmanVarshney01/tcut/blob/main/packages/tcut/docs/REFERENCE.md) — every CLI flag and script option
|
|
71
|
+
- [llms.txt](https://tcut.amanv.dev/llms.txt) — the same, condensed for coding agents (`--json` gives machine-readable results)
|
|
60
72
|
- [tcut.amanv.dev](https://tcut.amanv.dev)
|
|
61
73
|
|
|
62
74
|
MIT
|
package/package.json
CHANGED
package/src/cast.ts
CHANGED
|
@@ -17,7 +17,9 @@ export function parseCast(text: string): Recording {
|
|
|
17
17
|
for (let i = 1; i < lines.length; i++) {
|
|
18
18
|
const parsed = JSON.parse(lines[i]!) as unknown;
|
|
19
19
|
if (!Array.isArray(parsed) || parsed.length < 3) throw new Error(`Malformed cast event on line ${i + 1}`);
|
|
20
|
-
|
|
20
|
+
const type = parsed[1] as CastEvent[1];
|
|
21
|
+
if (!["o", "i", "r", "m", "b"].includes(type)) continue; // tolerate unknown asciicast event types
|
|
22
|
+
events.push([Number(parsed[0]), type, String(parsed[2])]);
|
|
21
23
|
}
|
|
22
24
|
return { header, events };
|
|
23
25
|
}
|
|
@@ -27,14 +29,18 @@ export async function writeCast(file: string, rec: Recording): Promise<void> {
|
|
|
27
29
|
}
|
|
28
30
|
|
|
29
31
|
export async function readCast(file: string): Promise<Recording> {
|
|
30
|
-
const
|
|
32
|
+
const abs = path.resolve(file);
|
|
33
|
+
const f = Bun.file(abs);
|
|
31
34
|
if (!(await f.exists())) throw new Error(`Cast file not found: ${file}`);
|
|
32
|
-
|
|
35
|
+
const rec = parseCast(await f.text());
|
|
36
|
+
rec.source = abs;
|
|
37
|
+
return rec;
|
|
33
38
|
}
|
|
34
39
|
|
|
35
40
|
export const MARKER = {
|
|
36
41
|
hide: "hide",
|
|
37
42
|
show: "show",
|
|
38
43
|
screenshot: "screenshot:",
|
|
44
|
+
focus: "focus:",
|
|
39
45
|
end: "end",
|
|
40
46
|
} as const;
|
package/src/cli.ts
CHANGED
|
@@ -59,6 +59,7 @@ Options (override the script's config):
|
|
|
59
59
|
--name <file> publish: object name (default: the file's basename)
|
|
60
60
|
--endpoint --bucket --access-key --secret-key --public-url --region publish --setup values
|
|
61
61
|
--template <name> for init: basic | tour | test
|
|
62
|
+
--json machine-readable result (or { "error" }) on stdout, nothing else
|
|
62
63
|
-q, --quiet
|
|
63
64
|
-h, --help
|
|
64
65
|
`;
|
|
@@ -103,11 +104,17 @@ const { values, positionals } = parseArgs({
|
|
|
103
104
|
region: { type: "string" },
|
|
104
105
|
template: { type: "string" },
|
|
105
106
|
quiet: { type: "boolean", short: "q" },
|
|
107
|
+
json: { type: "boolean" },
|
|
106
108
|
help: { type: "boolean", short: "h" },
|
|
107
109
|
},
|
|
108
110
|
});
|
|
109
111
|
|
|
110
|
-
const
|
|
112
|
+
const json = values.json === true;
|
|
113
|
+
const quiet = values.quiet === true || json;
|
|
114
|
+
/** With --json, the only thing on stdout is one JSON document (results or { error }). */
|
|
115
|
+
const emit = (data: unknown) => {
|
|
116
|
+
if (json) process.stdout.write(JSON.stringify(data, null, 2) + "\n");
|
|
117
|
+
};
|
|
111
118
|
const useColor = process.stdout.isTTY === true && !process.env.NO_COLOR;
|
|
112
119
|
const paint = (code: string) => (s: string) => (useColor ? `\x1b[${code}m${s}\x1b[0m` : s);
|
|
113
120
|
const green = paint("32");
|
|
@@ -120,7 +127,8 @@ const log = (msg: string) => {
|
|
|
120
127
|
};
|
|
121
128
|
|
|
122
129
|
function fail(message: string): never {
|
|
123
|
-
|
|
130
|
+
if (json) process.stdout.write(JSON.stringify({ error: message }) + "\n");
|
|
131
|
+
else console.error(`${red("error:")} ${message}`);
|
|
124
132
|
process.exit(1);
|
|
125
133
|
}
|
|
126
134
|
|
|
@@ -211,9 +219,10 @@ async function fileSize(file: string): Promise<string> {
|
|
|
211
219
|
|
|
212
220
|
const ok = (what: string, detail = "") => log(`${green("✔")} ${what}${detail ? ` ${dim(detail)}` : ""}`);
|
|
213
221
|
|
|
214
|
-
async function reportOutputs(outputs: string[], screenshots: string[]): Promise<
|
|
222
|
+
async function reportOutputs(outputs: string[], screenshots: string[]): Promise<Array<{ path: string; bytes: number }>> {
|
|
215
223
|
for (const out of outputs) ok(`wrote ${out}`, await fileSize(out));
|
|
216
224
|
for (const shot of screenshots) ok(`screenshot ${shot}`);
|
|
225
|
+
return Promise.all([...outputs, ...screenshots].map(async (p) => ({ path: p, bytes: (await Bun.file(p).exists()) ? Bun.file(p).size : 0 })));
|
|
217
226
|
}
|
|
218
227
|
|
|
219
228
|
const TEMPLATES: Record<string, (name: string) => string> = {
|
|
@@ -344,6 +353,7 @@ async function main(): Promise<void> {
|
|
|
344
353
|
if (!cfg) fail("publish is not configured yet — run `tcut publish --setup` (or set TCUT_S3_ENDPOINT/BUCKET/ACCESS_KEY/SECRET_KEY)");
|
|
345
354
|
const published = await publishFiles(rest, cfg, { name: values.name, log });
|
|
346
355
|
for (const p of published) ok(p.url, dim(path.basename(p.file)));
|
|
356
|
+
emit({ published });
|
|
347
357
|
if (values.open && published[0]) {
|
|
348
358
|
const opener = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
349
359
|
Bun.spawn([opener, published[published.length - 1]!.url], { stdout: "ignore", stderr: "ignore" });
|
|
@@ -386,10 +396,14 @@ async function main(): Promise<void> {
|
|
|
386
396
|
await Bun.write(scriptPath, generateScript(recording, { output: outputs, cleanShell: !command, command, castPath: config.cast }));
|
|
387
397
|
ok(`wrote ${scriptPath}`, "editable script — tweak it, then `tcut " + scriptPath + "`");
|
|
388
398
|
}
|
|
389
|
-
if (values["record-only"])
|
|
399
|
+
if (values["record-only"]) {
|
|
400
|
+
emit({ cast: config.cast, script: values["no-script"] ? null : config.cast.replace(/\.cast$/, "") + ".video.ts", events: recording.events.length, durationSeconds: recording.header.duration ?? 0 });
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
390
403
|
const result = await renderOutputs(recording, config, progressReporter());
|
|
391
|
-
await reportOutputs(result.outputs, result.screenshots);
|
|
404
|
+
const files = await reportOutputs(result.outputs, result.screenshots);
|
|
392
405
|
log(dim(` ${result.frames} frames, ${result.durationSeconds.toFixed(1)}s of video in ${elapsed()}`));
|
|
406
|
+
emit({ cast: config.cast, script: values["no-script"] ? null : config.cast.replace(/\.cast$/, "") + ".video.ts", outputs: files, frames: result.frames, durationSeconds: result.durationSeconds });
|
|
393
407
|
return;
|
|
394
408
|
}
|
|
395
409
|
case "record": {
|
|
@@ -397,18 +411,21 @@ async function main(): Promise<void> {
|
|
|
397
411
|
const video = await loadVideo(rest[0]);
|
|
398
412
|
const rec = await video.record({ log, force: values.force });
|
|
399
413
|
ok(`${rec.cached ? "reused" : "wrote"} ${video.config.cast}`, `${rec.events.length} events, ${(rec.header.duration ?? 0).toFixed(1)}s, ${elapsed()}`);
|
|
414
|
+
emit({ cast: video.config.cast, cached: rec.cached === true, events: rec.events.length, durationSeconds: rec.header.duration ?? 0 });
|
|
400
415
|
return;
|
|
401
416
|
}
|
|
402
417
|
case "render": {
|
|
403
418
|
if (!rest[0]) fail("render needs a .cast file");
|
|
404
419
|
const result = await renderCast(rest[0], overridesFromFlags(), progressReporter());
|
|
405
|
-
await reportOutputs(result.outputs, result.screenshots);
|
|
420
|
+
const files = await reportOutputs(result.outputs, result.screenshots);
|
|
406
421
|
log(dim(` ${result.frames} frames, ${result.durationSeconds.toFixed(1)}s of video in ${elapsed()}`));
|
|
422
|
+
emit({ cast: rest[0], outputs: files, frames: result.frames, durationSeconds: result.durationSeconds });
|
|
407
423
|
return;
|
|
408
424
|
}
|
|
409
425
|
case "test": {
|
|
410
426
|
if (rest.length === 0) fail("test needs at least one script file or directory");
|
|
411
|
-
const summary = await runScriptTests(rest, (line) => console.log(line));
|
|
427
|
+
const summary = await runScriptTests(rest, json ? () => {} : (line) => console.log(line));
|
|
428
|
+
emit(summary);
|
|
412
429
|
process.exit(summary.failed > 0 ? 1 : 0);
|
|
413
430
|
}
|
|
414
431
|
// eslint-disable-next-line no-fallthrough -- process.exit above never returns
|
|
@@ -416,13 +433,16 @@ async function main(): Promise<void> {
|
|
|
416
433
|
const video = await loadVideo(first!);
|
|
417
434
|
const result = await video.run({ log, force: values.force, recordOnly: values["record-only"], onProgress: progressReporter() });
|
|
418
435
|
ok(`${result.cached ? "reused" : "wrote"} ${result.cast}`);
|
|
419
|
-
await reportOutputs(result.outputs, result.screenshots);
|
|
436
|
+
const files = await reportOutputs(result.outputs, result.screenshots);
|
|
420
437
|
if (!values["record-only"]) log(dim(` ${result.frames} frames, ${result.durationSeconds.toFixed(1)}s of video in ${elapsed()}`));
|
|
438
|
+
emit({ cast: result.cast, cached: result.cached, outputs: files, frames: result.frames, durationSeconds: result.durationSeconds });
|
|
421
439
|
}
|
|
422
440
|
}
|
|
423
441
|
}
|
|
424
442
|
|
|
425
443
|
main().catch((err: unknown) => {
|
|
426
|
-
|
|
444
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
445
|
+
if (json) process.stdout.write(JSON.stringify({ error: message, type: err instanceof Error ? err.name : "Error" }) + "\n");
|
|
446
|
+
else console.error(`\n${red("error:")} ${message}`);
|
|
427
447
|
process.exit(1);
|
|
428
448
|
});
|
package/src/config.ts
CHANGED
|
@@ -76,6 +76,17 @@ export function resolveConfig(config: VideoConfig): ResolvedConfig {
|
|
|
76
76
|
blink: config.cursor?.blink ?? true,
|
|
77
77
|
period: config.cursor?.period ?? 1000,
|
|
78
78
|
},
|
|
79
|
+
...(config.browser && {
|
|
80
|
+
browser: {
|
|
81
|
+
url: config.browser.url,
|
|
82
|
+
title: config.browser.title,
|
|
83
|
+
width: config.browser.width ?? 720,
|
|
84
|
+
height: config.browser.height ?? 0,
|
|
85
|
+
fps: config.browser.fps ?? 10,
|
|
86
|
+
position: config.browser.position ?? "right",
|
|
87
|
+
...(config.browser.offset && { offset: config.browser.offset }),
|
|
88
|
+
},
|
|
89
|
+
}),
|
|
79
90
|
padding,
|
|
80
91
|
margin,
|
|
81
92
|
marginFill: config.marginFill ?? theme.background,
|
package/src/recorder.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { MARKER } from "./cast";
|
|
2
|
+
import { WINDOW_BAR_HEIGHT, estimateCell } from "./config";
|
|
2
3
|
import { formatMs, toMs } from "./duration";
|
|
3
4
|
import { altSequence, ctrlSequence, keySequence, shiftSequence, wheelSequence } from "./keys";
|
|
4
5
|
import { Screen } from "./screen";
|
|
5
6
|
import type {
|
|
7
|
+
BrowserFrame,
|
|
8
|
+
BrowserSession,
|
|
6
9
|
CastEvent,
|
|
7
10
|
Duration,
|
|
8
11
|
KeyName,
|
|
@@ -150,6 +153,104 @@ export async function record(config: ResolvedConfig, script: Script, opts: Recor
|
|
|
150
153
|
if (!exited && !terminal.closed) terminal.write(response);
|
|
151
154
|
};
|
|
152
155
|
|
|
156
|
+
// Optional browser pane: a WebView sampled on the recording clock; only changed frames are kept.
|
|
157
|
+
let browserSession: (BrowserSession & { frames: BrowserFrame[]; stop(): Promise<void> }) | null = null;
|
|
158
|
+
if (config.browser) {
|
|
159
|
+
if (typeof Bun.WebView !== "function") throw new Error("The browser pane needs Bun.WebView (Bun >= 1.4).");
|
|
160
|
+
const bcfg = config.browser;
|
|
161
|
+
// Default pane height: what the terminal window will measure (estimated from the font metrics).
|
|
162
|
+
const est = estimateCell(config.font);
|
|
163
|
+
const termFrameH = Math.round(config.rows * est.h + config.padding * 2 + (config.windowBar === "none" ? 0 : WINDOW_BAR_HEIGHT));
|
|
164
|
+
const termFrameW = Math.round(config.cols * est.w + config.padding * 2);
|
|
165
|
+
const stacked = bcfg.position === "top" || bcfg.position === "bottom";
|
|
166
|
+
const paneW = stacked ? termFrameW : bcfg.width;
|
|
167
|
+
const paneH = bcfg.height || (stacked || bcfg.position === "overlay" ? 480 : termFrameH);
|
|
168
|
+
const view = new Bun.WebView({ width: paneW, height: paneH });
|
|
169
|
+
const frames: BrowserFrame[] = [];
|
|
170
|
+
// WebView calls can stall (page never fires load, evaluate on a navigating page); never let them hang a recording.
|
|
171
|
+
const within = <T,>(promise: Promise<T>, ms: number, label: string): Promise<T> =>
|
|
172
|
+
Promise.race([promise, Bun.sleep(ms).then(() => Promise.reject(new Error(`browser.${label} did not finish within ${ms}ms`)))]);
|
|
173
|
+
let currentUrl = bcfg.url ?? "about:blank";
|
|
174
|
+
let lastHash = "";
|
|
175
|
+
let running = true;
|
|
176
|
+
const sampler = (async () => {
|
|
177
|
+
while (running) {
|
|
178
|
+
try {
|
|
179
|
+
const png = (await within(view.screenshot({ encoding: "buffer" }), 5000, "screenshot")) as Uint8Array;
|
|
180
|
+
const hash = Bun.hash(png).toString(16);
|
|
181
|
+
if (hash !== lastHash) {
|
|
182
|
+
lastHash = hash;
|
|
183
|
+
frames.push({ time: stamp(), png });
|
|
184
|
+
}
|
|
185
|
+
} catch {
|
|
186
|
+
/* view busy or closed */
|
|
187
|
+
}
|
|
188
|
+
await Bun.sleep(1000 / bcfg.fps);
|
|
189
|
+
}
|
|
190
|
+
})();
|
|
191
|
+
/**
|
|
192
|
+
* Navigate and wait for the page to be there. Dev servers may still be starting (connection refused → retry)
|
|
193
|
+
* or may take a long first load (Vite pre-bundling, then a reload), so success is judged by the document's
|
|
194
|
+
* readyState at the target URL rather than by the navigate() promise alone.
|
|
195
|
+
*/
|
|
196
|
+
const goto = async (url: string): Promise<void> => {
|
|
197
|
+
const deadline = performance.now() + config.waitTimeout;
|
|
198
|
+
const target = url.replace(/\/$/, "");
|
|
199
|
+
let navigation: Promise<"ok" | "pending" | "failed"> | null = null;
|
|
200
|
+
for (;;) {
|
|
201
|
+
navigation ??= view.navigate(url).then(
|
|
202
|
+
() => "ok" as const,
|
|
203
|
+
(err: unknown) => (/pending/i.test(String(err)) ? ("pending" as const) : ("failed" as const)),
|
|
204
|
+
);
|
|
205
|
+
const outcome = await Promise.race([navigation, Bun.sleep(750).then(() => "tick" as const)]);
|
|
206
|
+
if (outcome === "ok") {
|
|
207
|
+
currentUrl = url;
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
if (outcome === "failed") navigation = null; // e.g. connection refused: the server isn't up yet
|
|
211
|
+
const state = await within(view.evaluate("document.readyState"), 3000, "goto").catch(() => "");
|
|
212
|
+
if (state === "complete" && (view.url ?? "").replace(/\/$/, "").startsWith(target)) {
|
|
213
|
+
currentUrl = url;
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
if (performance.now() > deadline) {
|
|
217
|
+
throw new WaitTimeoutError(`browser.goto(${url})`, config.waitTimeout, `current url: ${view.url ?? "(none)"}, readyState: ${state || "unknown"}`);
|
|
218
|
+
}
|
|
219
|
+
await Bun.sleep(250);
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
browserSession = {
|
|
223
|
+
frames,
|
|
224
|
+
get url() {
|
|
225
|
+
return currentUrl;
|
|
226
|
+
},
|
|
227
|
+
goto,
|
|
228
|
+
async waitFor(pattern, waitOpts = {}) {
|
|
229
|
+
const regex = toRegExp(pattern);
|
|
230
|
+
const deadline = performance.now() + toMs(waitOpts.timeout, config.waitTimeout);
|
|
231
|
+
for (;;) {
|
|
232
|
+
const text = String((await within(view.evaluate("document.body ? document.body.innerText : ''"), 5000, "waitFor").catch(() => "")) ?? "");
|
|
233
|
+
if (regex.test(text)) return;
|
|
234
|
+
if (performance.now() > deadline) throw new WaitTimeoutError(`${regex} in the browser page`, toMs(waitOpts.timeout, config.waitTimeout), text.slice(0, 2000));
|
|
235
|
+
await Bun.sleep(150);
|
|
236
|
+
}
|
|
237
|
+
},
|
|
238
|
+
click: (selector) => within(view.click(selector), 10000, "click"),
|
|
239
|
+
reload: () => within(view.reload(), 30000, "reload").catch((err) => (/pending/i.test(String(err)) ? undefined : Promise.reject(err))),
|
|
240
|
+
evaluate: (js) => within(view.evaluate(js), 10000, "evaluate"),
|
|
241
|
+
async stop() {
|
|
242
|
+
running = false;
|
|
243
|
+
await sampler;
|
|
244
|
+
try {
|
|
245
|
+
view.close();
|
|
246
|
+
} catch {
|
|
247
|
+
/* closed */
|
|
248
|
+
}
|
|
249
|
+
},
|
|
250
|
+
};
|
|
251
|
+
if (bcfg.url) await goto(bcfg.url).catch((err) => log(String(err)));
|
|
252
|
+
}
|
|
253
|
+
|
|
153
254
|
const sleep = async (duration: Duration): Promise<void> => {
|
|
154
255
|
const ms = toMs(duration);
|
|
155
256
|
if (fast) return;
|
|
@@ -230,18 +331,24 @@ export async function record(config: ResolvedConfig, script: Script, opts: Recor
|
|
|
230
331
|
}
|
|
231
332
|
};
|
|
232
333
|
|
|
334
|
+
// The prompt is whatever sits left of the cursor; text to the right may be residue from a TUI that exited.
|
|
335
|
+
const promptVisible = (): boolean => promptPattern.test(screen.lineToCursor());
|
|
336
|
+
|
|
233
337
|
const wait = async (pattern?: RegExp | string, waitOpts: WaitOptions = {}): Promise<void> => {
|
|
234
|
-
const
|
|
338
|
+
const timeout = toMs(waitOpts.timeout, config.waitTimeout);
|
|
339
|
+
if (pattern === undefined) {
|
|
340
|
+
await waitFor(`prompt ${promptPattern}`, promptVisible, timeout);
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
const regex = toRegExp(pattern);
|
|
235
344
|
const scope = waitOpts.scope ?? "line";
|
|
236
|
-
await waitFor(`${regex} on ${scope}`, () => matches(regex, scope),
|
|
345
|
+
await waitFor(`${regex} on ${scope}`, () => matches(regex, scope), timeout);
|
|
237
346
|
};
|
|
238
347
|
|
|
239
348
|
const waitForPrompt = async (afterLine: number, echoLine: string, timeoutMs: number): Promise<void> => {
|
|
240
349
|
await waitFor(
|
|
241
350
|
`prompt ${promptPattern}`,
|
|
242
|
-
() =>
|
|
243
|
-
promptPattern.test(screen.line()) &&
|
|
244
|
-
(screen.absoluteCursorLine() !== afterLine || screen.line() !== echoLine),
|
|
351
|
+
() => promptVisible() && (screen.absoluteCursorLine() !== afterLine || screen.lineToCursor() !== echoLine),
|
|
245
352
|
timeoutMs,
|
|
246
353
|
);
|
|
247
354
|
};
|
|
@@ -250,7 +357,7 @@ export async function record(config: ResolvedConfig, script: Script, opts: Recor
|
|
|
250
357
|
await type(command, runOpts);
|
|
251
358
|
await screen.settle();
|
|
252
359
|
const beforeLine = screen.absoluteCursorLine();
|
|
253
|
-
const echoLine = screen.
|
|
360
|
+
const echoLine = screen.lineToCursor();
|
|
254
361
|
await raw("\r");
|
|
255
362
|
const timeout = toMs(runOpts.timeout, config.waitTimeout);
|
|
256
363
|
if (runOpts.wait === false) return;
|
|
@@ -328,6 +435,14 @@ export async function record(config: ResolvedConfig, script: Script, opts: Recor
|
|
|
328
435
|
await screen.settle();
|
|
329
436
|
},
|
|
330
437
|
clear: () => run("clear"),
|
|
438
|
+
get browser(): BrowserSession {
|
|
439
|
+
if (!browserSession) throw new Error("t.browser needs `browser: { url }` in the video config.");
|
|
440
|
+
return browserSession;
|
|
441
|
+
},
|
|
442
|
+
focus: async (target) => {
|
|
443
|
+
await screen.settle();
|
|
444
|
+
push("m", `${MARKER.focus}${target}`);
|
|
445
|
+
},
|
|
331
446
|
screen: () => screen.screen(),
|
|
332
447
|
line: () => screen.line(),
|
|
333
448
|
cursor: () => screen.cursor(),
|
|
@@ -345,7 +460,7 @@ export async function record(config: ResolvedConfig, script: Script, opts: Recor
|
|
|
345
460
|
log(`starting ${Array.isArray(config.shell) ? config.shell.join(" ") : config.shell}`);
|
|
346
461
|
// Named shells get a known prompt; for an arbitrary command there is nothing to wait for — start at once.
|
|
347
462
|
if (!Array.isArray(config.shell)) {
|
|
348
|
-
await waitFor(`initial prompt ${promptPattern}`,
|
|
463
|
+
await waitFor(`initial prompt ${promptPattern}`, promptVisible, config.waitTimeout);
|
|
349
464
|
}
|
|
350
465
|
startedAt = performance.now();
|
|
351
466
|
log("recording");
|
|
@@ -355,6 +470,7 @@ export async function record(config: ResolvedConfig, script: Script, opts: Recor
|
|
|
355
470
|
if (config.endPause > 0 && !fast) await Bun.sleep(config.endPause);
|
|
356
471
|
push("m", MARKER.end);
|
|
357
472
|
} finally {
|
|
473
|
+
await browserSession?.stop();
|
|
358
474
|
try {
|
|
359
475
|
terminal.close();
|
|
360
476
|
} catch {
|
|
@@ -378,5 +494,6 @@ export async function record(config: ResolvedConfig, script: Script, opts: Recor
|
|
|
378
494
|
bunVideo: config,
|
|
379
495
|
},
|
|
380
496
|
events,
|
|
497
|
+
...(browserSession && { browserFrames: browserSession.frames }),
|
|
381
498
|
};
|
|
382
499
|
}
|
package/src/renderer/bundle.ts
CHANGED
|
@@ -43,9 +43,15 @@ async function embeddedAssets(): Promise<PageAssets | null> {
|
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
/**
|
|
46
|
+
/** True inside a `bun build --compile` binary, where sources live on the virtual /$bunfs filesystem. */
|
|
47
|
+
const isCompiled = import.meta.dir.startsWith("/$bunfs");
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Prebuilt assets in the compiled binary; otherwise built at runtime with Bun.build so edits to the page entries
|
|
51
|
+
* take effect immediately (prebuilt files in src/renderer/generated/ could be stale during development).
|
|
52
|
+
*/
|
|
47
53
|
async function loadAssets(): Promise<PageAssets> {
|
|
48
|
-
const embedded = await embeddedAssets();
|
|
54
|
+
const embedded = isCompiled ? await embeddedAssets() : null;
|
|
49
55
|
if (embedded) return embedded;
|
|
50
56
|
const [js, playerJs] = await Promise.all([bundle("page-entry.ts"), bundle("player-entry.ts")]);
|
|
51
57
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var j="AGFzbQEAAAABQAtgAAF/YAAAYAF/AX9gAX8AYAJ/fwBgBH9/f38AYAN/f38AYAJ/fwF/YAV/f39/fwBgBH9/f38Bf2ADf39/AX8DQUAAAAAAAAEAAAICAAAAAAACAgICAAAAAAAAAAAAAAAAAAAAAAEAAAMDBAQFBQUEBgcBCAkGAQEECgYGBAQDAAQEBAUBcAEBAQUDAQBkBgkBfwFBgIDAAAsH/gUsBm1lbW9yeQIACmdldE1heENvbHMAAAtnZXRDZWxsU2l6ZQABDmdldERlYnVnTG9nTWF4AAIUZ2V0RGVidWdMb2dFbnRyeVNpemUAARBnZXREZWJ1Z0xvZ0NvdW50AAMOZ2V0RGVidWdMb2dQdHIABA1jbGVhclJlc3BvbnNlAAUOZ2V0UmVzcG9uc2VMZW4ABg5nZXRSZXNwb25zZVB0cgAHFGdldFNjcm9sbGJhY2tMaW5lTGVuAAgRZ2V0U2Nyb2xsYmFja0xpbmUACRtnZXRTY3JvbGxiYWNrRGlzY2FyZGVkQ291bnQAChJnZXRTY3JvbGxiYWNrQ291bnQACxlnZXRIeXBlcmxpbmtSZWplY3RlZENvdW50AAwRZ2V0SHlwZXJsaW5rQ291bnQADRRnZXRIeXBlcmxpbmtDYXBhY2l0eQAODGdldExpbmtJZExlbgAPDGdldExpbmtJZFB0cgAQDWdldExpbmtVcmlMZW4AEQ1nZXRMaW5rVXJpUHRyABIPZ2V0VGl0bGVDaGFuZ2VkABMLZ2V0VGl0bGVMZW4AFAtnZXRUaXRsZVB0cgAVH2dldFN5bmNocm9uaXplZE91dHB1dEdlbmVyYXRpb24AFhVnZXRTeW5jaHJvbml6ZWRPdXRwdXQAFw5nZXRGb2N1c0V2ZW50cwAYC2dldE1vdXNlU2dyABkQZ2V0TW91c2VUcmFja2luZwAaEWdldFVzaW5nQWx0U2NyZWVuABsRZ2V0QnJhY2tldGVkUGFzdGUAHBBnZXRDdXJzb3JLZXlzQXBwAB0HZ2V0Um93cwAeB2dldENvbHMAHxBnZXRDdXJzb3JWaXNpYmxlACAMZ2V0Q3Vyc29yQ29sACEMZ2V0Q3Vyc29yUm93ACIKY2xlYXJEaXJ0eQAjC2dldERpcnR5UHRyACQKZ2V0R3JpZFB0cgAlCndyaXRlQnl0ZXMAJg5nZXRXcml0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AzsB9rGYgQAMAQtBACADOwH2sZiBAAsgAUECaiEBDAALC+YBAQJ/I4CAgIAAQRBrIgIkgICAgABBACEDIAJBADoACyACIAE6AAkgAiAAOgAIIAJCADcDACACQQAtAKCK8IAAIgE6AAogAUEEIAFBBEkbQQF0IQECQANAIAEgA0YNASACIANqIANB/InwgABqLwEAOwEAIANBAmohAwwACwtBAC0AlMSggQAiA0EMbCIBIAIpAwA3AeaumIEAIAFB7q6YgQBqIAJBCGooAgA2AQBBACADQQFqQR9xOgCUxKCBAEEAQQAoAsyumIEAQQFqIgNBfyADGzYCzK6YgQAgAkEQaiSAgICAAAt4AQJ/AkAgAEH//wNxIgJBAC8B9ofwgABPDQAgAkGAGGxB9IfAgABqIQBBACEDAkADQCADQQAvAfSH8IAATw0BIAAgASkCADcCACAAQQhqIAFBCGooAgA2AgAgAEEMaiEAIANBAWohAwwACwsgAkEBOgD4h/CAAAsLsAIBA38CQCAAQf//A3EiBEEALwH2h/CAAE8NACABQf//A3EiBUEALwH0h/CAACIAIAUgAEkbIQECQCAFIAJB//8DcSIGIAAgBiAASRsiBk8NACABIARBgBhsQfSHwIAAaiIFIAFBDGxqLQAJRSABQf//A3FBAEdxayEBIAJB//8DcSAATw0AAkAgBSAGQQxsai0ACQ0AIAZBAWohBgwBCyAGIAUgBkF/akH//wNxQQxsai0ACUECRmohBgtBACAGQf//A3EiACABQf//A3EiAmsiASABIABLGyEBIARBgBhsIAJBDGxqQfSHwIAAaiEAAkADQCABRQ0BIAAgAykCADcCACAAQQhqIANBCGooAgA2AgAgAEEMaiEAIAFBf2ohAQwACwsgBEEBOgD4h/CAAAsL4QEBBH8CQCACQf//A3FFDQAgAUH//wNxIABB//8DcU0NACABIABrIgQgAkH//wNxIgIgBEH//wNxIgQgAiAESRsiBWtB//8DcSEGQQAhAgNAAkAgBiACRw0AIAUgAGpB//8DcSECA0AgAEH//wNxIAJPDQMgACADEKmAgIAAIABBAWohAAwACwsgASACQX9zaiIHQf//A3EhBAJAQYAYRQ0AIARBgBhsQfSHwIAAaiAHIAVrQf//A3FBgBhsQfSHwIAAakGAGPwKAAALIARB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";function lA(A){let t=atob(A),e=new Uint8Array(t.length);for(let s=0;s<t.length;s++)e[s]=t.charCodeAt(s);return e.buffer}class L{get dv(){if(this._dvBuffer!==this.memory.buffer)this._dvBuffer=this.memory.buffer,this._dv=new DataView(this.memory.buffer);return this._dv}constructor(A){this.gridPtr=0,this.dirtyPtr=0,this.writeBufferPtr=0,this.cellSize=12,this.maxCols=256,this.encoder=new TextEncoder,this.decoder=new TextDecoder,this._dvBuffer=null,this.linkCache=new Map,this.exports=A.exports,this.memory=this.exports.memory}static async load(A){let t;if(A){let s=await fetch(A);if(!s.ok)throw Error(`[wterm] Failed to load WASM from ${A}: ${s.status} ${s.statusText}`);t=await s.arrayBuffer()}else t=lA(j);let{instance:e}=await WebAssembly.instantiate(t);return new L(e)}init(A,t){this.exports.init(A,t),this.linkCache.clear(),this._updatePointers()}_updatePointers(){this.gridPtr=this.exports.getGridPtr(),this.dirtyPtr=this.exports.getDirtyPtr(),this.writeBufferPtr=this.exports.getWriteBuffer(),this.cellSize=this.exports.getCellSize(),this.maxCols=this.exports.getMaxCols()}writeString(A,t){let e=this.encoder.encode(A);this.writeRaw(e,t)}writeRaw(A,t){let e=0;while(e<A.length){let s=Math.min(A.length-e,8192);new Uint8Array(this.memory.buffer,this.writeBufferPtr,8192).set(A.subarray(e,e+s)),this.exports.writeBytes(s),e+=s,t?.()}}getCell(A,t){let e=this.gridPtr+(A*this.maxCols+t)*this.cellSize,s=this.dv,i={char:s.getUint32(e,!0),fg:s.getUint16(e+4,!0),bg:s.getUint16(e+6,!0),flags:s.getUint8(e+8),width:s.getUint8(e+9)};return Object.assign(i,this._readLink(s.getUint16(e+10,!0))),i}isDirtyRow(A){return new Uint8Array(this.memory.buffer,this.dirtyPtr,256)[A]!==0}clearDirty(){this.exports.clearDirty()}getCursor(){return{row:this.exports.getCursorRow(),col:this.exports.getCursorCol(),visible:this.exports.getCursorVisible()!==0}}getCols(){return this.exports.getCols()}getRows(){return this.exports.getRows()}cursorKeysApp(){return this.exports.getCursorKeysApp()!==0}bracketedPaste(){return this.exports.getBracketedPaste()!==0}usingAltScreen(){return this.exports.getUsingAltScreen()!==0}mouseTracking(){let A=this.exports.getMouseTracking();return A===1000||A===1002?A:0}mouseSgr(){return this.exports.getMouseSgr()!==0}focusEvents(){return this.exports.getFocusEvents()!==0}synchronizedOutput(){return this.exports.getSynchronizedOutput()!==0}synchronizedOutputGeneration(){return this.exports.getSynchronizedOutputGeneration()}getTitle(){if(this.exports.getTitleChanged()===0)return null;let A=this.exports.getTitlePtr(),t=this.exports.getTitleLen(),e=new Uint8Array(this.memory.buffer,A,t);return this.decoder.decode(e)}getResponse(){let A=this.exports.getResponseLen();if(A===0)return null;let t=this.exports.getResponsePtr(),e=new Uint8Array(this.memory.buffer,t,A),s=this.decoder.decode(e);return this.exports.clearResponse(),s}getResourceState(){let A=this.exports.getHyperlinkCapacity?.(),t=this.exports.getHyperlinkCount?.(),e=this.exports.getHyperlinkRejectedCount?.();if(A===void 0||t===void 0||e===void 0)return{};return{hyperlinks:{capacity:A,used:t,rejected:e,saturated:t>=A}}}getScrollbackCount(){return this.exports.getScrollbackCount()}getScrollbackDiscardedCount(){return this.exports.getScrollbackDiscardedCount()}getScrollbackCell(A,t){let s=this.exports.getScrollbackLine(A)+t*this.cellSize,i=this.dv,r={char:i.getUint32(s,!0),fg:i.getUint16(s+4,!0),bg:i.getUint16(s+6,!0),flags:i.getUint8(s+8),width:i.getUint8(s+9)};return Object.assign(r,this._readLink(i.getUint16(s+10,!0))),r}getScrollbackLineLen(A){return this.exports.getScrollbackLineLen(A)}getUnhandledSequences(){let A=this.exports.getDebugLogCount();if(A===0)return[];let t=this.exports.getDebugLogPtr(),e=this.exports.getDebugLogEntrySize(),s=this.exports.getDebugLogMax(),i=Math.min(A,s),r=new DataView(this.memory.buffer),o=[],n=A>=s?A%s:0;for(let Q=0;Q<i;Q++){let g=(n+Q)%s,l=t+g*e,h=r.getUint8(l);if(h===0)continue;let E=r.getUint8(l+1),C=r.getUint8(l+2),d=[];for(let b=0;b<Math.min(C,4);b++)d.push(r.getUint16(l+4+b*2,!0));o.push({final:String.fromCharCode(h),private:E?String.fromCharCode(E):"",paramCount:C,params:d})}return o}resize(A,t){this.exports.resizeTerminal(A,t),this._updatePointers()}_readLink(A){if(A===0)return;let t=this.linkCache.get(A);if(t)return t;let e=this.exports.getLinkUriLen(A);if(e===0)return;let s=this.decoder.decode(new Uint8Array(this.memory.buffer,this.exports.getLinkUriPtr(A),e)),i=this.exports.getLinkIdLen(A),r=i===0?void 0:this.decoder.decode(new Uint8Array(this.memory.buffer,this.exports.getLinkIdPtr(A),i)),o={linkUri:s,linkId:r,linkKey:r?`e\x00${r}\x00${s}`:`b\x00${A}`};return this.linkCache.set(A,o),o}}function oA(A){let t=A>>16&255,e=A>>8&255,s=A&255;return`rgb(${t},${e},${s})`}function nA(A){if(A===256)return null;if(A<16)return`var(--term-color-${A})`;if(A<232){let e=A-16,s=Math.floor(e/36)*51,i=Math.floor(e/6)%6*51,r=e%6*51;return`rgb(${s},${i},${r})`}let t=(A-232)*10+8;return`rgb(${t},${t},${t})`}function BA(A,t){if(t!==void 0)return oA(t);return nA(A)}function J(A,t){if(t!==void 0)return oA(t);return nA(A)}function AA(A,t,e,s,i){let r=A,o=t,n=s,Q=i;if(e&32){let C=r;r=o,o=C;let d=n;if(n=Q,Q=d,n===void 0&&r===256)r=0;if(Q===void 0&&o===256)o=7}let g=BA(r,n),l=J(o,Q),h="";if(g)h+=`color:${g};`;if(l)h+=`background:${l};`;if(e&1)h+="font-weight:bold;";if(e&2)h+="opacity:0.5;";if(e&4)h+="font-style:italic;";let E=[];if(e&8)E.push("underline");if(e&128)E.push("line-through");if(E.length)h+=`text-decoration:${E.join(" ")};`;if(e&64)h+="visibility:hidden;";return h}function S(A){return A.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}function CA(A){if(!A)return;try{let t=new URL(A);return t.protocol==="http:"||t.protocol==="https:"?t.href:void 0}catch{return}}function IA(A){if(!A.linkUri)return"";return A.linkKey??`fallback\x00${A.linkId??""}\x00${A.linkUri}`}function uA(A,t,e,s,i){let r=A,o=t,n=s,Q=i;if(e&32){if([r,o]=[o,r],[n,Q]=[Q,n],n===void 0&&r===256)r=0;if(Q===void 0&&o===256)o=7}return{fg:BA(r,n)||"var(--term-fg)",bg:J(o,Q)||"var(--term-bg)"}}var v="round(calc(var(--term-row-height) * 0.125), 1px)",tA="round(calc(var(--term-row-height) * 0.25), 1px)",eA="round(calc(var(--term-row-height) * 0.375), 1px)",M="round(calc(var(--term-row-height) * 0.5), 1px)",sA="round(calc(var(--term-row-height) * 0.625), 1px)",iA="round(calc(var(--term-row-height) * 0.75), 1px)",rA="round(calc(var(--term-row-height) * 0.875), 1px)";function wA(A,t,e){switch(A){case 9600:return`linear-gradient(${t} ${M},${e} ${M})`;case 9601:return`linear-gradient(${e} ${rA},${t} ${rA})`;case 9602:return`linear-gradient(${e} ${iA},${t} ${iA})`;case 9603:return`linear-gradient(${e} ${sA},${t} ${sA})`;case 9604:return`linear-gradient(${e} ${M},${t} ${M})`;case 9605:return`linear-gradient(${e} ${eA},${t} ${eA})`;case 9606:return`linear-gradient(${e} ${tA},${t} ${tA})`;case 9607:return`linear-gradient(${e} ${v},${t} ${v})`;case 9608:return t;case 9609:return`linear-gradient(to right,${t} 87.5%,${e} 87.5%)`;case 9610:return`linear-gradient(to right,${t} 75%,${e} 75%)`;case 9611:return`linear-gradient(to right,${t} 62.5%,${e} 62.5%)`;case 9612:return`linear-gradient(to right,${t} 50%,${e} 50%)`;case 9613:return`linear-gradient(to right,${t} 37.5%,${e} 37.5%)`;case 9614:return`linear-gradient(to right,${t} 25%,${e} 25%)`;case 9615:return`linear-gradient(to right,${t} 12.5%,${e} 12.5%)`;case 9616:return`linear-gradient(to right,${e} 50%,${t} 50%)`;case 9617:return`color-mix(in srgb,${t} 25%,${e})`;case 9618:return`color-mix(in srgb,${t} 50%,${e})`;case 9619:return`color-mix(in srgb,${t} 75%,${e})`;case 9620:return`linear-gradient(${t} ${v},${e} ${v})`;case 9621:return`linear-gradient(to right,${e} 87.5%,${t} 87.5%)`;default:{let i={9622:[!1,!1,!0,!1],9623:[!1,!1,!1,!0],9624:[!0,!1,!1,!1],9625:[!0,!1,!0,!0],9626:[!0,!1,!1,!0],9627:[!0,!0,!0,!1],9628:[!0,!0,!1,!0],9629:[!1,!0,!1,!1],9630:[!1,!0,!0,!1],9631:[!1,!0,!0,!0]}[A];if(!i)return t;let[r,o,n,Q]=i;if(r&&o&&n&&Q)return t;let g=[],l=["0 0","100% 0","0 100%","100% 100%"];return i.forEach((h,E)=>{if(h)g.push(`linear-gradient(${t},${t}) ${l[E]}/50% 50% no-repeat`)}),g.push(e),g.join(",")}}}class Y{constructor(A){this.rows=0,this.cols=0,this.rowEls=[],this.prevCursorRow=-1,this.prevCursorCol=-1,this.prevContainerBg="",this.prevRowBg=[],this._scrollbackRowEls=[],this._scrollbackStartKey=0,this._renderedScrollbackCount=-1,this._renderedDiscardedCount=-1,this._scrollbackTopSpacer=null,this._scrollbackBottomSpacer=null,this.container=A}setup(A,t){this.cols=A,this.rows=t,this.container.innerHTML="",this.rowEls=[],this.prevRowBg=[],this._scrollbackRowEls=[],this._scrollbackStartKey=0,this._renderedScrollbackCount=-1,this._renderedDiscardedCount=-1;let e=document.createDocumentFragment();this._scrollbackTopSpacer=document.createElement("div"),this._scrollbackTopSpacer.className="term-scrollback-spacer",e.appendChild(this._scrollbackTopSpacer),this._scrollbackBottomSpacer=document.createElement("div"),this._scrollbackBottomSpacer.className="term-scrollback-spacer",e.appendChild(this._scrollbackBottomSpacer);for(let s=0;s<t;s++){let i=document.createElement("div");i.className="term-row",e.appendChild(i),this.rowEls.push(i)}this.container.appendChild(e),this.prevCursorRow=-1,this.prevCursorCol=-1}_buildRowContent(A,t,e,s,i){let r="",o="",n="",Q=[],g=0,l="",h,E="",C=(a,B,c)=>{let I=CA(c),p=I?B:"";if(p!==E){if(E)r+="</a>";if(p)r+=`<a class="term-link" href="${S(I)}" target="_blank" rel="noopener noreferrer">`;E=p}r+=a},d=(a)=>{if(!n)return;let B=S(n),c="";if(s>=g&&s<a){let I=s-g,p=Q.slice(0,I).join(""),w=Q[I]||" ",u=Q.slice(I+1).join("");if(p)c+=o?`<span style="${o}">${S(p)}</span>`:`<span>${S(p)}</span>`;if(c+=o?`<span class="term-cursor" style="${o}">${S(w)}</span>`:`<span class="term-cursor">${S(w)}</span>`,u)c+=o?`<span style="${o}">${S(u)}</span>`:`<span>${S(u)}</span>`}else c+=o?`<span style="${o}">${B}</span>`:`<span>${B}</span>`;C(c,l,h),n="",Q=[]},b=(a,B,c,I,p)=>{let w=a?` class="${a}"`:"",u=B?` style="${B}"`:"";C(`<span${w}${u}>${S(c)}</span>`,I,p)};for(let a=0;a<this.cols;a++){let B=t(a),c=a<e,I=c?B.char:0,p=c?B.width??1:1,w=c?IA(B):"",u=c?B.linkUri:void 0;if(c&&p===0){if(d(a),!(a>0&&(t(a-1).width??1)===2))b(a===s?"term-cursor":"",""," ",w,u);o="",l="",h=void 0,n="",Q=[],g=a+1;continue}if(c&&p===2){if(d(a),a+1>=this.cols){b(a===s?"term-cursor":"",""," ",w,u),o="",l="",h=void 0,n="",Q=[],g=a+1;continue}let f=B.chars??(I>=32?String.fromCodePoint(I):" "),x=AA(B.fg,B.bg,B.flags,B.fgRgb,B.bgRgb),U=s>=a&&s<a+2?"term-wide term-cursor":"term-wide";b(U,x,f,w,u),o="",l="",h=void 0,n="",Q=[],g=a+2;continue}if(c&&I>=9600&&I<=9631){d(a);let f=uA(B.fg,B.bg,B.flags,B.fgRgb,B.bgRgb),x=a===s?"term-block term-cursor":"term-block",U=wA(I,f.fg,f.bg),EA=B.flags&2?"opacity:0.5;":"";C(`<span class="${x}" style="background:${U};${EA}"></span>`,w,u),o="",l="",h=void 0,n="",Q=[],g=a+1}else{let f=B.chars??(c&&I>=32?String.fromCodePoint(I):" "),x=c?AA(B.fg,B.bg,B.flags,B.fgRgb,B.bgRgb):"";if(x!==o||w!==l)d(a),o=x,l=w,h=u,n=f,Q=[f],g=a;else n+=f,Q.push(f)}}if(d(this.cols),E)r+="</a>";A.innerHTML=r;let m="";if(e>=this.cols&&this.cols>0){let a=t(this.cols-1),B=a.bg,c=a.bgRgb;if(a.flags&32){if(B=a.fg,c=a.fgRgb,c===void 0&&B===256)B=7}m=J(B,c)||""}let _=m?`0 1px 0 ${m}`:"";if(i>=0){if(m!==(this.prevRowBg[i]??""))A.style.background=m,A.style.boxShadow=_,this.prevRowBg[i]=m}else A.style.background=m,A.style.boxShadow=_}_buildScrollbackRowEl(A,t){let e=document.createElement("div");e.className="term-row term-scrollback-row";let s=A.getScrollbackLineLen(t);return this._buildRowContent(e,(i)=>A.getScrollbackCell(t,i),s,-1,-1),e}syncScrollback(A,t){let e=A.getScrollbackCount(),s=t?.rowHeight??0,i=t!==void 0&&s>0,r=t?.overscanRows??10,o=t?.scrollbackDiscardedCount!==void 0,n=t?.scrollbackDiscardedCount??0,Q=t&&t.clientHeight>0?t.clientHeight:this.rows*s,g=i?Math.floor(t.scrollTop/s):0,l=i?Math.ceil(Q/s):e,h=i?Math.max(0,Math.min(e,g-r)):0,E=i?Math.max(h,Math.min(e,g+l+r)):e,C=this.container.ownerDocument.getSelection();if(C!==null&&!C.isCollapsed&&(this.container.contains(C.anchorNode)||this.container.contains(C.focusNode))&&this._scrollbackRowEls.length>0)h=Math.min(h,Math.max(0,this._scrollbackStartKey-n)),E=Math.max(E,Math.min(e,this._scrollbackStartKey-n+this._scrollbackRowEls.length));let b=n+h;if(o&&e===this._renderedScrollbackCount&&n===this._renderedDiscardedCount&&b===this._scrollbackStartKey&&E-h===this._scrollbackRowEls.length)return;let m=new Map;for(let c=0;c<this._scrollbackRowEls.length;c++)m.set(this._scrollbackStartKey+c,this._scrollbackRowEls[c]);let _=n+E;for(let[c,I]of m)if(c<b||c>=_)I.remove();let a=[],B=this._scrollbackTopSpacer?.nextSibling??null;for(let c=h;c<E;c++){let I=n+c,p=e-1-c,w=this._buildScrollbackRowEl(A,p),u=m.get(I),f=w,x=!1;if(u&&u.innerHTML===w.innerHTML&&u.style.cssText===w.style.cssText)f=u;else if(u)u.replaceWith(w),x=!0;if(!x&&f!==B)this.container.insertBefore(f,B??this._scrollbackBottomSpacer);B=f.nextSibling,a.push(f)}if(this._scrollbackRowEls=a,this._scrollbackStartKey=b,this._renderedScrollbackCount=e,this._renderedDiscardedCount=n,this._scrollbackTopSpacer)this._scrollbackTopSpacer.style.height=`${h*s}px`;if(this._scrollbackBottomSpacer)this._scrollbackBottomSpacer.style.height=`${(e-E)*s}px`}render(A,t){let e=A.getRows(),s=A.getCols(),i=!1;if(e!==this.rows||s!==this.cols)this.setup(s,e),i=!0;this.syncScrollback(A,t);let r=A.getCursor(),o=r.visible,n=r.row!==this.prevCursorRow||r.col!==this.prevCursorCol;for(let g=0;g<this.rows;g++){let l=i||A.isDirtyRow(g),h=g===this.prevCursorRow&&n,E=g===r.row;if(l||h||E&&n){let C=E&&o?r.col:-1;this._buildRowContent(this.rowEls[g],(d)=>A.getCell(g,d),this.cols,C,g)}}if(this.prevCursorRow=r.row,this.prevCursorCol=r.col,i||A.isDirtyRow(this.rows-1)){let g=A.getCell(this.rows-1,this.cols-1),l=g.bg,h=g.bgRgb;if(g.flags&32){if(l=g.fg,h=g.fgRgb,h===void 0&&l===256)l=7}let E=J(l,h)||"";if(E!==this.prevContainerBg)this.container.style.background=E,this.prevContainerBg=E}A.clearDirty()}}function G(A,t){return t.platform.startsWith("Mac")?A.metaKey:A.ctrlKey}var fA={ArrowUp:"\x1B[A",ArrowDown:"\x1B[B",ArrowRight:"\x1B[C",ArrowLeft:"\x1B[D",Home:"\x1B[H",End:"\x1B[F"},dA={ArrowUp:"\x1BOA",ArrowDown:"\x1BOB",ArrowRight:"\x1BOC",ArrowLeft:"\x1BOD",Home:"\x1BOH",End:"\x1BOF"},pA={Enter:"\r",Backspace:"",Tab:"\t",Escape:"\x1B",Insert:"\x1B[2~",Delete:"\x1B[3~",PageUp:"\x1B[5~",PageDown:"\x1B[6~",F1:"\x1BOP",F2:"\x1BOQ",F3:"\x1BOR",F4:"\x1BOS",F5:"\x1B[15~",F6:"\x1B[17~",F7:"\x1B[18~",F8:"\x1B[19~",F9:"\x1B[20~",F10:"\x1B[21~",F11:"\x1B[23~",F12:"\x1B[24~"};class N{constructor(A,t,e,s=()=>null){this.composing=!1,this.mouseButtons=0,this.focused=!1,this.element=A,this.onData=t,this.getBridge=e,this.getCellSize=s,this.textarea=document.createElement("textarea"),this.textarea.setAttribute("autocapitalize","off"),this.textarea.setAttribute("autocomplete","off"),this.textarea.setAttribute("autocorrect","off"),this.textarea.setAttribute("spellcheck","false"),this.textarea.setAttribute("enterkeyhint","send"),this.textarea.setAttribute("tabindex","0"),this.textarea.setAttribute("aria-hidden","true");let i=this.textarea.style;i.position="absolute",i.left="-9999px",i.top="0",i.width="1px",i.height="1px",i.opacity="0",i.overflow="hidden",i.border="0",i.padding="0",i.margin="0",i.outline="none",i.resize="none",i.pointerEvents="none",i.caretColor="transparent",i.color="transparent",i.background="transparent",A.appendChild(this.textarea),this._onKeyDown=this.handleKeyDown.bind(this),this._onPaste=this.handlePaste.bind(this),this._onCompositionStart=this.handleCompositionStart.bind(this),this._onCompositionEnd=this.handleCompositionEnd.bind(this),this._onInput=this.handleInput.bind(this),this._onFocus=()=>{if(this.focused)return;if(this.focused=!0,this.element.classList.add("focused"),this.getBridge()?.focusEvents?.())this.onData("\x1B[I")},this._onBlur=()=>{if(this.focused=!1,this.element.classList.remove("focused"),this.stopMouseCapture(),this.getBridge()?.focusEvents?.())this.onData("\x1B[O")},this._onMouseDown=(r)=>this.handleMouse(r,"press"),this._onMouseMove=(r)=>{if(this.mouseButtons!==0)this.handleMouse(r,"move")},this._onMouseUp=(r)=>{if(this.mouseButtons===0)return;if(this.handleMouse(r,"release"),this.mouseButtons=r.buttons&7,this.mouseButtons===0)this.stopMouseCapture()},this._onWheel=(r)=>this.handleMouse(r,"wheel"),this.textarea.addEventListener("keydown",this._onKeyDown),this.textarea.addEventListener("paste",this._onPaste),this.textarea.addEventListener("compositionstart",this._onCompositionStart),this.textarea.addEventListener("compositionend",this._onCompositionEnd),this.textarea.addEventListener("input",this._onInput),this.textarea.addEventListener("focus",this._onFocus),this.textarea.addEventListener("blur",this._onBlur),this.element.addEventListener("mousedown",this._onMouseDown),this.element.addEventListener("wheel",this._onWheel,{passive:!1})}focus(){this.textarea.focus({preventScroll:!0})}destroy(){this.textarea.removeEventListener("keydown",this._onKeyDown),this.textarea.removeEventListener("paste",this._onPaste),this.textarea.removeEventListener("compositionstart",this._onCompositionStart),this.textarea.removeEventListener("compositionend",this._onCompositionEnd),this.textarea.removeEventListener("input",this._onInput),this.textarea.removeEventListener("focus",this._onFocus),this.textarea.removeEventListener("blur",this._onBlur),this.element.removeEventListener("mousedown",this._onMouseDown),this.stopMouseCapture(),this.element.removeEventListener("wheel",this._onWheel),this.element.classList.remove("focused"),this.textarea.remove()}handleKeyDown(A){if(this.composing)return;if((A.metaKey||A.ctrlKey)&&A.key==="c"){let e=window.getSelection();if(e&&e.toString().length>0)return}if((A.metaKey||A.ctrlKey)&&A.key==="v"){this.textarea.focus();return}if(A.metaKey&&!A.ctrlKey){if(A.key==="Backspace")A.preventDefault(),this.onData("\x15");else if(A.key==="a"){A.preventDefault();let e=window.getSelection();if(e){let s=document.createRange();s.selectNodeContents(this.element),e.removeAllRanges(),e.addRange(s)}}return}A.preventDefault();let t=this.keyToSequence(A);if(t)this.onData(t)}handlePaste(A){A.preventDefault();let t=A.clipboardData?.getData("text");if(!t)return;let e=this.getBridge();if(e&&e.bracketedPaste()){let s=t.replace(/\x1b/g,"");this.onData("\x1B[200~"+s+"\x1B[201~")}else this.onData(t)}handleCompositionStart(){this.composing=!0}handleCompositionEnd(A){if(this.composing=!1,A.data)this.onData(A.data);this.textarea.value=""}handleInput(){if(this.composing)return;let A=this.textarea.value;if(A)this.onData(A),this.textarea.value=""}handleMouse(A,t){let e=this.getBridge(),s=e?.mouseTracking?.()??0;if(!e||s===0||!e.mouseSgr?.())return;if(t==="press"&&G(A,this.element.ownerDocument.defaultView?.navigator??navigator)&&A.target instanceof Element&&A.target.closest(".term-link"))return;if(t==="press"&&(A.shiftKey||A.button>2))return;if(t==="release"&&A.button>2)return;let i=A.buttons&7;if(t==="move"&&(s!==1002||i===0))return;let r=this.element.ownerDocument.defaultView;if(!r)return;let o=this.element.querySelector(".term-row:not(.term-scrollback-row)"),n=this.element.getBoundingClientRect(),Q=o?.getBoundingClientRect(),g=this.getCellSize(),l,h,E,C;if(Q&&g)l=Q.left,h=Q.top,E=g.charWidth,C=g.rowHeight;else{let B=r.getComputedStyle(this.element),c=parseFloat(B.borderLeftWidth)||0,I=parseFloat(B.borderRightWidth)||0,p=parseFloat(B.borderTopWidth)||0,w=parseFloat(B.borderBottomWidth)||0,u=parseFloat(B.paddingLeft)||0,f=parseFloat(B.paddingRight)||0,x=parseFloat(B.paddingTop)||0,U=parseFloat(B.paddingBottom)||0;l=Q?.left??n.left+c+u,h=Q?.top??n.top+p+x,E=(n.width-c-I-u-f)/e.getCols(),C=(n.height-p-w-x-U)/e.getRows()}if(E<=0||C<=0)return;if(t==="press"){if(this.textarea.focus({preventScroll:!0}),!this.focused)this._onFocus();this.mouseButtons=i||(A.button===1?4:A.button===2?2:1),r.addEventListener("mousemove",this._onMouseMove),r.addEventListener("mouseup",this._onMouseUp)}let d=Math.max(1,Math.min(e.getCols(),Math.floor((A.clientX-l)/E)+1)),b=Math.max(1,Math.min(e.getRows(),Math.floor((A.clientY-h)/C)+1)),m=(A.shiftKey?4:0)|(A.altKey?8:0)|(A.ctrlKey?16:0),_,a="M";if(t==="wheel"){let B=A;if(Math.abs(B.deltaX)>Math.abs(B.deltaY)){if(B.deltaX===0)return;_=(B.deltaX<0?66:67)|m}else{if(B.deltaY===0)return;_=(B.deltaY<0?64:65)|m}}else if(_=(t==="move"?i&4?1:i&2?2:0:A.button===1?1:A.button===2?2:0)|m|(t==="move"?32:0),t==="release")a="m";A.preventDefault(),this.onData(`\x1B[<${_};${d};${b}${a}`)}stopMouseCapture(){this.mouseButtons=0;let A=this.element.ownerDocument.defaultView;A?.removeEventListener("mousemove",this._onMouseMove),A?.removeEventListener("mouseup",this._onMouseUp)}keyToSequence(A){if(A.ctrlKey&&!A.altKey&&!A.metaKey){if(A.key.length===1){let o=A.key.toLowerCase().charCodeAt(0);if(o>=97&&o<=122)return String.fromCharCode(o-96)}if(A.key==="[")return"\x1B";if(A.key==="\\")return"\x1C";if(A.key==="]")return"\x1D";if(A.key==="^")return"\x1E";if(A.key==="_")return"\x1F"}if(A.key==="Enter"&&A.shiftKey)return"\x1B[13;2u";if(A.key==="Tab"&&A.shiftKey)return"\x1B[Z";let t=pA[A.key];if(t)return A.altKey?"\x1B"+t:t;let e=this.getBridge(),r=(e&&e.cursorKeysApp()?dA:fA)[A.key];if(r)return A.altKey?"\x1B"+r:r;if(A.key.length===1&&!A.ctrlKey&&!A.metaKey)return A.altKey?"\x1B"+A.key:A.key;return null}}var mA={1:"bold",2:"dim",4:"italic",8:"underline",16:"blink",32:"reverse",64:"invisible",128:"strikethrough"};function bA(A){let t=[];for(let[e,s]of Object.entries(mA))if(A&Number(e))t.push(s);return t}var q=27;function xA(A){let t=[],e=Date.now(),s=0,i=0,r=()=>{if(s>i){let o=A.slice(i,s);if(o.length>0&&!/^[\x00-\x1f]+$/.test(o))t.push({ts:e,type:"text",raw:o.slice(0,60)})}};while(s<A.length){if(A.charCodeAt(s)!==q){s++;continue}r();let o=s;if(s++,s>=A.length)break;let n=A[s];if(n==="["){s++;let Q="";if(s<A.length&&(A[s]==="?"||A[s]===">"||A[s]==="!"))Q=A[s],s++;let g="";while(s<A.length&&(A.charCodeAt(s)>=48&&A.charCodeAt(s)<=59||A[s]===":"))g+=A[s],s++;while(s<A.length&&A.charCodeAt(s)>=32&&A.charCodeAt(s)<=47)s++;let l="";if(s<A.length&&A.charCodeAt(s)>=64&&A.charCodeAt(s)<=126)l=A[s],s++;let h=A.slice(o,s),E=g?g.split(/[;:]/).map(Number).filter((d)=>!isNaN(d)):[],C=l==="m"?"sgr":"csi";t.push({ts:e,type:C,raw:h,params:E.length>0?E:void 0,private:Q||void 0,final:l})}else if(n==="]"){s++;while(s<A.length&&A.charCodeAt(s)!==7&&!(A.charCodeAt(s)===q&&s+1<A.length&&A[s+1]==="\\"))s++;if(s<A.length){if(A.charCodeAt(s)===7)s++;else if(A.charCodeAt(s)===q)s+=2}let Q=A.slice(o,s);t.push({ts:e,type:"osc",raw:Q.slice(0,80)})}else if(n>=" "&&n<="~")s++,t.push({ts:e,type:"esc",raw:A.slice(o,s),final:n});else s++;i=s}return r(),t}var gA=500;class K{constructor(){this._traces=[],this._bridge=null,this._perf={frameCount:0,totalRenderMs:0,avgRenderMs:0,maxRenderMs:0,lastDirtyRows:0}}get traces(){return this._traces}get perf(){return this._perf}setBridge(A){this._bridge=A}traceWrite(A){let t=typeof A==="string"?A:new TextDecoder().decode(A),e=xA(t);for(let s of e)this._traces.push(s);if(this._traces.length>gA)this._traces=this._traces.slice(-gA)}recordRender(A,t){if(this._perf.frameCount++,this._perf.totalRenderMs+=A,this._perf.avgRenderMs=this._perf.totalRenderMs/this._perf.frameCount,A>this._perf.maxRenderMs)this._perf.maxRenderMs=A;this._perf.lastDirtyRows=t}resetPerf(){this._perf={frameCount:0,totalRenderMs:0,avgRenderMs:0,maxRenderMs:0,lastDirtyRows:0}}cell(A,t){if(!this._bridge)return null;let e=this._bridge.getCell(A,t);return{...e,charStr:e.chars??(e.char>=32?String.fromCodePoint(e.char):""),flagNames:bA(e.flags)}}row(A){if(!this._bridge)return null;let t=this._bridge.getCols(),e=[];for(let s=0;s<t;s++)e.push(this.cell(A,s));return e}grid(){if(!this._bridge)return null;let A=this._bridge.getCursor();return{rows:this._bridge.getRows(),cols:this._bridge.getCols(),cursor:A,altScreen:this._bridge.usingAltScreen(),scrollbackCount:this._bridge.getScrollbackCount()}}unhandled(){if(!this._bridge)return[];return this._bridge.getUnhandledSequences()}dump(A=50){let t=this._traces.slice(-A);console.group(`%cwterm debug — last ${t.length} traces`,"color: #569cd6; font-weight: bold");for(let e of t){let s=e.type==="sgr"?"%cSGR":e.type==="csi"?"%cCSI":e.type==="osc"?"%cOSC":e.type==="esc"?"%cESC":"%cTXT",i=e.type==="sgr"?"background:#2d5a27;color:#fff;padding:1px 4px;border-radius:2px":e.type==="csi"?"background:#1e4a7a;color:#fff;padding:1px 4px;border-radius:2px":"background:#555;color:#fff;padding:1px 4px;border-radius:2px",r=[e.private?`private=${e.private}`:"",e.params?`params=[${e.params}]`:"",e.final?`final=${e.final}`:""].filter(Boolean).join(" ");console.log(`${s} ${e.raw.slice(0,40)}`,i,r?` ${r}`:"")}console.groupEnd()}dumpUnhandled(){let A=this.unhandled();if(A.length===0){console.log("%cwterm debug — no unhandled sequences","color: #6a9955");return}console.group(`%cwterm debug — ${A.length} unhandled sequences`,"color: #d7ba7d; font-weight: bold");for(let t of A)console.log(` final=${t.final} private=${t.private||"-"} params=[${t.params.slice(0,t.paramCount)}]`);console.groupEnd()}}var _A=1000;class T{constructor(A,t={}){if(this.bridge=null,this.debug=null,this.renderer=null,this.input=null,this.rafId=null,this._synchronizedOutputTimer=null,this._synchronizedOutputState="idle",this._synchronizedOutputGeneration=0,this._rendererNeedsSetup=!1,this.resizeObserver=null,this._destroyed=!1,this._shouldScrollToBottom=!1,this._scrollbackDiscardedCount=0,this._programmaticScrollTop=null,this._pendingResizeScrollTop=null,this._rowHeight=0,this._charWidth=0,this.element=A,this._coreOption=t.core,this.wasmUrl=t.wasmUrl,this.cols=t.cols||80,this.rows=t.rows||24,this.autoResize=t.autoResize!==!1,this._debugEnabled=t.debug??!1,this.onData=t.onData||null,this.onTitle=t.onTitle||null,this.onResize=t.onResize||null,this._container=document.createElement("div"),this._container.className="term-grid",this.element.appendChild(this._container),this.element.classList.add("wterm"),t.cursorBlink)this.element.classList.add("cursor-blink");this._onClickFocus=(e)=>{let s=e.target;if(s instanceof Element&&s.closest(".term-link")){if(G(e,this.element.ownerDocument.defaultView?.navigator??navigator)||e.detail===0)return;e.preventDefault()}let i=window.getSelection();if(!i||i.isCollapsed)this.input?.focus()},this.element.addEventListener("click",this._onClickFocus),this._onModifierChange=(e)=>{this.element.classList.toggle("link-modifier-active",G(e,this.element.ownerDocument.defaultView?.navigator??navigator))},this._onWindowBlur=()=>{this.element.classList.remove("link-modifier-active")},this.element.ownerDocument.addEventListener("keydown",this._onModifierChange),this.element.ownerDocument.addEventListener("keyup",this._onModifierChange),this.element.ownerDocument.defaultView?.addEventListener("blur",this._onWindowBlur),this._onScroll=()=>{if(this._pendingResizeScrollTop!==null)return;if(this._programmaticScrollTop!==null&&this.element.scrollTop===this._programmaticScrollTop){this._programmaticScrollTop=null;return}this._programmaticScrollTop=null,this._shouldScrollToBottom=!1,this._scheduleRender()},this.element.addEventListener("scroll",this._onScroll,{passive:!0})}async init(){try{if(this._coreOption)this.bridge=this._coreOption;else this.bridge=await L.load(this.wasmUrl);if(this._destroyed)return this;if(this.bridge.init(this.cols,this.rows),this._debugEnabled)this.debug=new K,this.debug.setBridge(this.bridge),globalThis.__wterm=this;if(this._setRowHeight(),this._measureCharSize(),this.renderer=new Y(this._container),this.renderer.setup(this.cols,this.rows),this.input=new N(this.element,(A)=>{if(this._scrollToBottom(),this.onData)this.onData(A);else this.write(A)},()=>this.bridge,()=>this._charWidth>0&&this._rowHeight>0?{charWidth:this._charWidth,rowHeight:this._rowHeight}:null),this.autoResize)this._setupResizeObserver();else this._lockHeight();this.input.focus(),this._initialRender()}catch(A){throw this.destroy(),Error(`wterm: failed to initialize: ${A instanceof Error?A.message:A}`)}return this}_isScrolledToBottom(){let A=this.element;return A.scrollHeight-A.scrollTop-A.clientHeight<5}_scrollToBottom(){let A=this.element,t=A.scrollHeight-A.clientHeight;if(t<=0){this._setScrollTop(0);return}this._setScrollTop(t)}_setScrollTop(A){if(this.element.scrollTop===A)return;this._programmaticScrollTop=A,this.element.scrollTop=A}write(A){if(!this.bridge)return;if(this.debug)this.debug.traceWrite(A);this._shouldScrollToBottom=this._isScrolledToBottom();let t,e=!1,s=()=>{let o=this._drainResponses();if(!e&&o.hasError)e=!0,t=o.error};if(typeof A==="string")this.bridge.writeString(A,s);else this.bridge.writeRaw(A,s);let i=this.bridge.synchronizedOutput?.()??!1,r=this.bridge.synchronizedOutputGeneration?.()??0;if(this._updateSynchronizedOutput(i,r),this._synchronizedOutputState!=="held")this._setupRendererIfNeeded(),this._scheduleRender();if(s(),e)throw t}resize(A,t){if(!this.bridge)return;this._shouldScrollToBottom=this._pendingResizeScrollTop===null&&this._isScrolledToBottom(),this.cols=A,this.rows=t,this.bridge.resize(A,t);let e=this.bridge.synchronizedOutput?.()??!1,s=this.bridge.synchronizedOutputGeneration?.()??0;if(this._updateSynchronizedOutput(e,s))this._rendererNeedsSetup=!0;else this._setupRenderer(A,t),this._scheduleRender();if(this.onResize)this.onResize(A,t)}focus(){if(this.input)this.input.focus();else this.element.focus()}_scheduleRender(){if(this.rafId!=null)return;this.rafId=requestAnimationFrame(()=>{this.rafId=null,this._doRender()})}_cancelScheduledRender(){if(this.rafId!=null)cancelAnimationFrame(this.rafId),this.rafId=null}_updateSynchronizedOutput(A,t){if(!A){if(this._synchronizedOutputState==="held")this._cancelSynchronizedOutputFallback();return this._synchronizedOutputState="idle",!1}if(this._synchronizedOutputState==="held"&&t!==this._synchronizedOutputGeneration)return this._armSynchronizedOutputFallback(t),!0;else if(this._synchronizedOutputState==="passthrough"&&t!==this._synchronizedOutputGeneration)this._synchronizedOutputState="idle";if(this._synchronizedOutputState!=="idle")return this._synchronizedOutputState==="held";return this._synchronizedOutputState="held",this._cancelScheduledRender(),this._armSynchronizedOutputFallback(t),!0}_armSynchronizedOutputFallback(A){this._cancelSynchronizedOutputFallback(),this._synchronizedOutputGeneration=A,this._synchronizedOutputTimer=setTimeout(()=>{if(this._synchronizedOutputState!=="held"||this._synchronizedOutputGeneration!==A)return;this._synchronizedOutputTimer=null,this._synchronizedOutputState="passthrough",this._setupRendererIfNeeded(),this._cancelScheduledRender(),this._doRender()},_A)}_cancelSynchronizedOutputFallback(){if(this._synchronizedOutputTimer==null)return;clearTimeout(this._synchronizedOutputTimer),this._synchronizedOutputTimer=null}_setupRendererIfNeeded(){if(!this._rendererNeedsSetup)return;this._setupRenderer(this.cols,this.rows),this._rendererNeedsSetup=!1}_setupRenderer(A,t){if(!this._shouldScrollToBottom&&this._pendingResizeScrollTop===null)this._pendingResizeScrollTop=this.element.scrollTop;this.renderer?.setup(A,t)}_initialRender(){this._doRender()}_doRender(){if(!this.bridge||!this.renderer)return;let A=0,t=this.debug?performance.now():0;if(this.debug){for(let g=0;g<this.rows;g++)if(this.bridge.isDirtyRow(g))A++}let e=this._rowHeight||17,s=this.bridge.getScrollbackCount(),i=this.bridge.getScrollbackDiscardedCount?.(),r=i!==void 0&&i>=this._scrollbackDiscardedCount?i-this._scrollbackDiscardedCount:0;if(i!==void 0)this._scrollbackDiscardedCount=i;let o=this._pendingResizeScrollTop!==null?this._pendingResizeScrollTop:this.element.scrollTop;if(!this._shouldScrollToBottom&&r>0)if(o=Math.max(0,o-r*e),this._pendingResizeScrollTop!==null)this._pendingResizeScrollTop=o;else this._setScrollTop(o);if(this.renderer.render(this.bridge,{scrollTop:this._shouldScrollToBottom?Math.max(0,(s+this.rows)*e-this.element.clientHeight):o,clientHeight:this.element.clientHeight,rowHeight:e,scrollbackDiscardedCount:i}),this.debug)this.debug.recordRender(performance.now()-t,A);let n=s>0;if(this.element.classList.toggle("has-scrollback",n),this._shouldScrollToBottom)this._scrollToBottom();else if(this._pendingResizeScrollTop!==null){let g=this._pendingResizeScrollTop;this._pendingResizeScrollTop=null,this._setScrollTop(g)}else if(!n&&this.element.scrollTop!==0)this.element.scrollTop=0;let Q=this.bridge.getTitle();if(Q!==null&&this.onTitle)this.onTitle(Q);this._drainResponses()}_drainResponses(){if(!this.bridge)return{hasError:!1};let A,t,e=!1;while((A=this.bridge.getResponse())!==null)try{if(this.onData)this.onData(A)}catch(s){if(!e)e=!0,t=s}return{hasError:e,error:t}}_lockHeight(){let A=this._rowHeight||17,t=this.rows*A,e=getComputedStyle(this.element),s=(parseFloat(e.paddingTop)||0)+(parseFloat(e.paddingBottom)||0);if(e.boxSizing==="border-box")s+=(parseFloat(e.borderTopWidth)||0)+(parseFloat(e.borderBottomWidth)||0);this.element.style.height=`${t+s}px`}_setRowHeight(){let A=document.createElement("div");A.className="term-row",A.style.visibility="hidden",A.style.position="absolute",A.textContent="W",this._container.appendChild(A);let t=A.getBoundingClientRect().height;if(A.remove(),t>0){let e=Math.ceil(t);this._rowHeight=e,this.element.style.setProperty("--term-row-height",`${e}px`)}}_measureCharSize(){let A=document.createElement("div");A.className="term-row",A.style.visibility="hidden",A.style.position="absolute";let t=document.createElement("span");t.textContent="W",A.appendChild(t),this._container.appendChild(A);let e=t.getBoundingClientRect().width,s=A.getBoundingClientRect().height;if(A.remove(),e===0||s===0)return null;return this._charWidth=e,this._rowHeight=s,{charWidth:e,rowHeight:s}}_setupResizeObserver(){let A=this._measureCharSize();if(!A)return;let{charWidth:t,rowHeight:e}=A;this.resizeObserver=new ResizeObserver((s)=>{let i=this._measureCharSize();if(i)t=i.charWidth,e=i.rowHeight;for(let r of s){let{width:o,height:n}=r.contentRect,Q=Math.max(1,Math.floor(o/t)),g=Math.max(1,Math.floor(n/e));if(Q!==this.cols||g!==this.rows)this.resize(Q,g)}}),this.resizeObserver.observe(this.element)}destroy(){if(this._destroyed=!0,this._cancelScheduledRender(),this._cancelSynchronizedOutputFallback(),this.resizeObserver)this.resizeObserver.disconnect();if(this.input)this.input.destroy();if(this.element.removeEventListener("click",this._onClickFocus),this.element.removeEventListener("scroll",this._onScroll),this.element.ownerDocument.removeEventListener("keydown",this._onModifierChange),this.element.ownerDocument.removeEventListener("keyup",this._onModifierChange),this.element.ownerDocument.defaultView?.removeEventListener("blur",this._onWindowBlur),this.element.classList.remove("link-modifier-active"),this.element.innerHTML="",this.debug&&globalThis.__wterm===this)delete globalThis.__wterm;this.debug=null}}var k=16,z='Serve the binary from your app and pass its URL: GhosttyCore.load({ wasmPath: "/ghostty-vt.wasm" }). The file ships with the package as @wterm/ghostty/ghostty-vt.wasm. See the Bundlers section of the @wterm/ghostty README.';function SA(){return new URL("../wasm/ghostty-vt.wasm",import.meta.url).href}function DA(A){if(A.byteLength<4)return!1;let t=new Uint8Array(A,0,4);return t[0]===0&&t[1]===97&&t[2]===115&&t[3]===109}async function QA(A){let t=A??SA();if(A===void 0&&t.startsWith("file:")&&typeof document<"u")throw Error(`@wterm/ghostty: your bundler resolved the WASM URL to ${t}, a path on the machine that built the bundle, so the browser cannot fetch it. ${z}`);let e=await fetch(t);if(!e.ok)throw Error(`@wterm/ghostty: fetching ${t} returned ${e.status} ${e.statusText}. ${z}`);let s=await e.arrayBuffer();if(!DA(s))throw Error(`@wterm/ghostty: ${t} did not return a WASM module. ${z}`);let i,{instance:r}=await WebAssembly.instantiate(s,{env:{log(n,Q){let g=new TextDecoder().decode(new Uint8Array(i.buffer,n,Q));console.log("[ghostty-vt]",g)}}});return i=r.exports.memory,{exports:r.exports,instance:r}}function W(A,t){return{codepoint:A.getUint32(t,!0),fgR:A.getUint8(t+4),fgG:A.getUint8(t+5),fgB:A.getUint8(t+6),bgR:A.getUint8(t+7),bgG:A.getUint8(t+8),bgB:A.getUint8(t+9),flags:A.getUint8(t+10),width:A.getUint8(t+11),colorFlags:A.getUint8(t+12),hasGrapheme:(A.getUint8(t+13)&1)!==0,hasHyperlink:(A.getUint8(t+13)&2)!==0}}function D(A,t){return A.exports.alloc_buffer(t)}function y(A,t,e){A.exports.free_buffer(t,e)}function hA(A,t,e){let s=new TextEncoder().encode(e);V(A,t,s)}function V(A,t,e){if(e.length===0)return;let s=D(A,e.length);if(s===0)return;new Uint8Array(A.exports.memory.buffer,s,e.length).set(e),A.exports.write(t,s,e.length),y(A,s,e.length)}var R=256,aA=256,Z=1024,yA="#d4d4d4",LA="#1e1e1e";function O(A,t,e){return A<<16|t<<8|e}var P={char:32,fg:R,bg:R,flags:0,width:1};function cA(A,t){if(!/^#[0-9a-f]{6}$/i.test(A))throw Error(`@wterm/ghostty: ${t} must be a #RRGGBB color`);return Number.parseInt(A.slice(1),16)}class H{constructor(A,t){this.termPtr=0,this._viewportBufPtr=0,this._viewportBufSize=0,this._viewportView=null,this._viewportStale=!0,this._cols=0,this._rows=0,this._scrollbackBufPtr=0,this._scrollbackBufSize=0,this._scrollbackView=null,this._scrollbackOffset=-1,this._scrollbackLen=0,this._graphemeBufPtr=0,this._graphemeBufSize=aA,this._hyperlinkBufPtr=0,this._hyperlinkBufSize=Z,this.wasm=A,this._options=t,this._foregroundRgb=cA(t.foregroundColor??yA,"foregroundColor"),this._backgroundRgb=cA(t.backgroundColor??LA,"backgroundColor")}static async load(A={}){let t=await QA(A.wasmPath);return new H(t,A)}init(A,t){this._cols=A,this._rows=t;let e=this._options.scrollbackLimit??1e4;if(this.termPtr=this.wasm.exports.init(A,t,e,this._foregroundRgb,this._backgroundRgb),this._graphemeBufPtr=D(this.wasm,aA),this._hyperlinkBufPtr!==0)y(this.wasm,this._hyperlinkBufPtr,this._hyperlinkBufSize);this._hyperlinkBufSize=Z,this._hyperlinkBufPtr=D(this.wasm,Z),this._allocViewportBuffer(),this._invalidate()}resize(A,t){this._cols=A,this._rows=t,this.wasm.exports.resize(this.termPtr,A,t),this._allocViewportBuffer(),this._invalidate()}writeString(A){hA(this.wasm,this.termPtr,A),this._invalidate()}writeRaw(A){V(this.wasm,this.termPtr,A),this._invalidate()}getCell(A,t){this._ensureViewport();let e=this._viewportView;if(!e)return P;let i=(A*this._cols+t)*k;if(i+k>this._viewportBufSize)return P;let r=W(e,i);if(r.codepoint===0&&r.flags===0&&r.colorFlags===0&&!r.hasHyperlink&&r.width!==0)return P;let o={char:r.codepoint||32,fg:R,bg:R,flags:r.flags,width:r.width};if(r.hasGrapheme)o.chars=this._readGrapheme(A,t);if(r.hasHyperlink)Object.assign(o,this._readHyperlink(A,t,!1));if(r.colorFlags&1)o.fgRgb=O(r.fgR,r.fgG,r.fgB);if(r.colorFlags&2)o.bgRgb=O(r.bgR,r.bgG,r.bgB);return o}isDirtyRow(A){return this._ensureViewport(),this.wasm.exports.is_dirty_row(this.termPtr,A)!==0}clearDirty(){this.wasm.exports.clear_dirty(this.termPtr),this._viewportStale=!0}getCols(){return this._cols}getRows(){return this._rows}getCursor(){return this._ensureViewport(),{row:this.wasm.exports.get_cursor_row(this.termPtr),col:this.wasm.exports.get_cursor_col(this.termPtr),visible:this.wasm.exports.get_cursor_visible(this.termPtr)!==0}}cursorKeysApp(){return this.wasm.exports.cursor_keys_app(this.termPtr)!==0}bracketedPaste(){return this.wasm.exports.bracketed_paste(this.termPtr)!==0}usingAltScreen(){return this.wasm.exports.using_alt_screen(this.termPtr)!==0}mouseTracking(){let A=this.wasm.exports.mouse_tracking(this.termPtr);return A===1000||A===1002?A:0}mouseSgr(){return this.wasm.exports.mouse_sgr(this.termPtr)!==0}focusEvents(){return this.wasm.exports.focus_events(this.termPtr)!==0}synchronizedOutput(){return this.wasm.exports.synchronized_output(this.termPtr)!==0}synchronizedOutputGeneration(){return this.wasm.exports.synchronized_output_generation(this.termPtr)}getTitle(){return null}getResponse(){let t=D(this.wasm,4096);if(t===0)return null;let e=this.wasm.exports.read_response(this.termPtr,t,4096);if(e===0)return y(this.wasm,t,4096),null;let s=new Uint8Array(this.wasm.exports.memory.buffer,t,e),i=new TextDecoder().decode(s);return y(this.wasm,t,4096),i}getScrollbackCount(){return this.wasm.exports.get_scrollback_count(this.termPtr)}getScrollbackDiscardedCount(){return this.wasm.exports.get_scrollback_discarded_count(this.termPtr)}getScrollbackCell(A,t){let e=this._ensureScrollbackLine(A),s=this._scrollbackView;if(!s||t>=e)return P;let i=W(s,t*k),r={char:i.codepoint||32,fg:R,bg:R,flags:i.flags,width:i.width};if(i.hasGrapheme)r.chars=this._readScrollbackGrapheme(A,t);if(i.hasHyperlink)Object.assign(r,this._readHyperlink(A,t,!0));if(i.colorFlags&1)r.fgRgb=O(i.fgR,i.fgG,i.fgB);if(i.colorFlags&2)r.bgRgb=O(i.bgR,i.bgG,i.bgB);return r}getScrollbackLineLen(A){return this._ensureScrollbackLine(A)}getUnhandledSequences(){return[]}_invalidate(){this._viewportStale=!0,this._scrollbackOffset=-1}_decodeGrapheme(A){if(A===0||this._graphemeBufPtr===0)return;return new TextDecoder().decode(new Uint8Array(this.wasm.exports.memory.buffer,this._graphemeBufPtr,A))}_ensureGraphemeBuffer(A){if(A<=this._graphemeBufSize)return;if(this._graphemeBufPtr!==0)y(this.wasm,this._graphemeBufPtr,this._graphemeBufSize);this._graphemeBufSize=A,this._graphemeBufPtr=D(this.wasm,A)}_ensureHyperlinkBuffer(A){if(A<=this._hyperlinkBufSize)return;if(this._hyperlinkBufPtr!==0)y(this.wasm,this._hyperlinkBufPtr,this._hyperlinkBufSize);this._hyperlinkBufSize=A,this._hyperlinkBufPtr=D(this.wasm,A)}_readHyperlink(A,t,e){if(this._hyperlinkBufPtr===0)return;let s=e?this.wasm.exports.get_scrollback_hyperlink:this.wasm.exports.get_viewport_hyperlink,i=s(this.termPtr,A,t,this._hyperlinkBufPtr,this._hyperlinkBufSize);if(i>this._hyperlinkBufSize){if(this._ensureHyperlinkBuffer(i),this._hyperlinkBufPtr===0)return;i=s(this.termPtr,A,t,this._hyperlinkBufPtr,this._hyperlinkBufSize)}if(i===0||i>this._hyperlinkBufSize)return;let r=new TextDecoder().decode(new Uint8Array(this.wasm.exports.memory.buffer,this._hyperlinkBufPtr,i)),[o,n="",Q=""]=r.split("\x00");if(!o)return;let g=n?`e\x00${n}\x00${o}`:`g\x00${Q}\x00${o}`;return{linkUri:o,linkId:n||void 0,linkKey:g}}_readGrapheme(A,t){if(this._graphemeBufPtr===0||!this.wasm.exports.get_viewport_grapheme)return;let e=this.wasm.exports.get_viewport_grapheme(this.termPtr,A,t,this._graphemeBufPtr,this._graphemeBufSize);if(e>this._graphemeBufSize)this._ensureGraphemeBuffer(e),e=this.wasm.exports.get_viewport_grapheme(this.termPtr,A,t,this._graphemeBufPtr,this._graphemeBufSize);return this._decodeGrapheme(e)}_readScrollbackGrapheme(A,t){if(this._graphemeBufPtr===0||!this.wasm.exports.get_scrollback_grapheme)return;let e=this.wasm.exports.get_scrollback_grapheme(this.termPtr,A,t,this._graphemeBufPtr,this._graphemeBufSize);if(e>this._graphemeBufSize)this._ensureGraphemeBuffer(e),e=this.wasm.exports.get_scrollback_grapheme(this.termPtr,A,t,this._graphemeBufPtr,this._graphemeBufSize);return this._decodeGrapheme(e)}_allocViewportBuffer(){if(this._viewportBufPtr!==0)y(this.wasm,this._viewportBufPtr,this._viewportBufSize);if(this._viewportBufSize=this._cols*this._rows*k,this._viewportBufPtr=D(this.wasm,this._viewportBufSize),this._viewportView=null,this._viewportStale=!0,this._scrollbackBufPtr!==0)y(this.wasm,this._scrollbackBufPtr,this._scrollbackBufSize);this._scrollbackBufSize=this._cols*k,this._scrollbackBufPtr=D(this.wasm,this._scrollbackBufSize),this._scrollbackView=null,this._scrollbackOffset=-1}_ensureScrollbackLine(A){if(this._scrollbackBufPtr===0)return 0;if(this._scrollbackOffset!==A)this._scrollbackLen=this.wasm.exports.get_scrollback_line(this.termPtr,A,this._scrollbackBufPtr,this._cols),this._scrollbackOffset=A;if(this._scrollbackView?.buffer!==this.wasm.exports.memory.buffer)this._scrollbackView=new DataView(this.wasm.exports.memory.buffer,this._scrollbackBufPtr,this._scrollbackBufSize);return this._scrollbackLen}_ensureViewport(){if(this._viewportStale)this.wasm.exports.update(this.termPtr),this.wasm.exports.get_viewport(this.termPtr,this._viewportBufPtr),this._viewportStale=!1;if(this._viewportView?.buffer!==this.wasm.exports.memory.buffer)this._viewportView=new DataView(this.wasm.exports.memory.buffer,this._viewportBufPtr,this._viewportBufSize)}}var F=null,X=()=>new Promise((A)=>requestAnimationFrame(()=>requestAnimationFrame(()=>A(!0)))),kA={async boot(A){let t=A.core==="lite"?await L.load():await H.load({wasmPath:A.wasmUrl,foregroundColor:A.foreground,backgroundColor:A.background}),e=document.getElementById("term");if(F=new T(e,{cols:A.cols,rows:A.rows,core:t,autoResize:!1,cursorBlink:!1,onData:()=>{}}),await F.init(),e.classList.add("focused"),document.fonts?.ready)await document.fonts.ready;return await X(),!0},measure(){let A=F;if(A&&A._charWidth&&A._rowHeight&&A._charWidth>0&&A._rowHeight>0)return{w:A._charWidth,h:A._rowHeight};let t=document.createElement("div");t.className="term-row",t.style.cssText="position:absolute;visibility:hidden";let e=document.createElement("span");e.textContent="W",t.appendChild(e),document.querySelector(".term-grid").appendChild(t);let s=e.getBoundingClientRect().width,i=t.getBoundingClientRect().height;return t.remove(),{w:s,h:i}},layout(A,t,e,s,i,r){let o=document.getElementById("frame");if(o.style.width=`${A}px`,o.style.height=`${t}px`,i!==void 0&&r!==void 0)o.style.padding=`${r}px ${i}px`;let n=document.getElementById("term");return n.style.width=`${e}px`,n.style.height=`${s}px`,!0},async applyUrl(A){let t=await(await fetch(A)).json();for(let e of t)if(e.type==="o")F.write(e.data);else if(e.type==="r"){let[s,i]=e.data.split("x").map(Number);if(s>0&&i>0)F.resize(s,i)}return await X(),!0},async writeUrl(A){return F.write(await(await fetch(A)).text()),await X(),!0},cursor(A){return document.getElementById("blink").textContent=A?"":".wterm.focused .term-cursor{background:transparent!important;color:inherit!important;outline:none!important}",!0}};window.__vt=kA;
|
|
1
|
+
var j="AGFzbQEAAAABQAtgAAF/YAAAYAF/AX9gAX8AYAJ/fwBgBH9/f38AYAN/f38AYAJ/fwF/YAV/f39/fwBgBH9/f38Bf2ADf39/AX8DQUAAAAAAAAEAAAICAAAAAAACAgICAAAAAAAAAAAAAAAAAAAAAAEAAAMDBAQFBQUEBgcBCAkGAQEECgYGBAQDAAQEBAUBcAEBAQUDAQBkBgkBfwFBgIDAAAsH/gUsBm1lbW9yeQIACmdldE1heENvbHMAAAtnZXRDZWxsU2l6ZQABDmdldERlYnVnTG9nTWF4AAIUZ2V0RGVidWdMb2dFbnRyeVNpemUAARBnZXREZWJ1Z0xvZ0NvdW50AAMOZ2V0RGVidWdMb2dQdHIABA1jbGVhclJlc3BvbnNlAAUOZ2V0UmVzcG9uc2VMZW4ABg5nZXRSZXNwb25zZVB0cgAHFGdldFNjcm9sbGJhY2tMaW5lTGVuAAgRZ2V0U2Nyb2xsYmFja0xpbmUACRtnZXRTY3JvbGxiYWNrRGlzY2FyZGVkQ291bnQAChJnZXRTY3JvbGxiYWNrQ291bnQACxlnZXRIeXBlcmxpbmtSZWplY3RlZENvdW50AAwRZ2V0SHlwZXJsaW5rQ291bnQADRRnZXRIeXBlcmxpbmtDYXBhY2l0eQAODGdldExpbmtJZExlbgAPDGdldExpbmtJZFB0cgAQDWdldExpbmtVcmlMZW4AEQ1nZXRMaW5rVXJpUHRyABIPZ2V0VGl0bGVDaGFuZ2VkABMLZ2V0VGl0bGVMZW4AFAtnZXRUaXRsZVB0cgAVH2dldFN5bmNocm9uaXplZE91dHB1dEdlbmVyYXRpb24AFhVnZXRTeW5jaHJvbml6ZWRPdXRwdXQAFw5nZXRGb2N1c0V2ZW50cwAYC2dldE1vdXNlU2dyABkQZ2V0TW91c2VUcmFja2luZwAaEWdldFVzaW5nQWx0U2NyZWVuABsRZ2V0QnJhY2tldGVkUGFzdGUAHBBnZXRDdXJzb3JLZXlzQXBwAB0HZ2V0Um93cwAeB2dldENvbHMAHxBnZXRDdXJzb3JWaXNpYmxlACAMZ2V0Q3Vyc29yQ29sACEMZ2V0Q3Vyc29yUm93ACIKY2xlYXJEaXJ0eQAjC2dldERpcnR5UHRyACQKZ2V0R3JpZFB0cgAlCndyaXRlQnl0ZXMAJg5nZXRXcml0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AzsB9rGYgQAMAQtBACADOwH2sZiBAAsgAUECaiEBDAALC+YBAQJ/I4CAgIAAQRBrIgIkgICAgABBACEDIAJBADoACyACIAE6AAkgAiAAOgAIIAJCADcDACACQQAtAKCK8IAAIgE6AAogAUEEIAFBBEkbQQF0IQECQANAIAEgA0YNASACIANqIANB/InwgABqLwEAOwEAIANBAmohAwwACwtBAC0AlMSggQAiA0EMbCIBIAIpAwA3AeaumIEAIAFB7q6YgQBqIAJBCGooAgA2AQBBACADQQFqQR9xOgCUxKCBAEEAQQAoAsyumIEAQQFqIgNBfyADGzYCzK6YgQAgAkEQaiSAgICAAAt4AQJ/AkAgAEH//wNxIgJBAC8B9ofwgABPDQAgAkGAGGxB9IfAgABqIQBBACEDAkADQCADQQAvAfSH8IAATw0BIAAgASkCADcCACAAQQhqIAFBCGooAgA2AgAgAEEMaiEAIANBAWohAwwACwsgAkEBOgD4h/CAAAsLsAIBA38CQCAAQf//A3EiBEEALwH2h/CAAE8NACABQf//A3EiBUEALwH0h/CAACIAIAUgAEkbIQECQCAFIAJB//8DcSIGIAAgBiAASRsiBk8NACABIARBgBhsQfSHwIAAaiIFIAFBDGxqLQAJRSABQf//A3FBAEdxayEBIAJB//8DcSAATw0AAkAgBSAGQQxsai0ACQ0AIAZBAWohBgwBCyAGIAUgBkF/akH//wNxQQxsai0ACUECRmohBgtBACAGQf//A3EiACABQf//A3EiAmsiASABIABLGyEBIARBgBhsIAJBDGxqQfSHwIAAaiEAAkADQCABRQ0BIAAgAykCADcCACAAQQhqIANBCGooAgA2AgAgAEEMaiEAIAFBf2ohAQwACwsgBEEBOgD4h/CAAAsL4QEBBH8CQCACQf//A3FFDQAgAUH//wNxIABB//8DcU0NACABIABrIgQgAkH//wNxIgIgBEH//wNxIgQgAiAESRsiBWtB//8DcSEGQQAhAgNAAkAgBiACRw0AIAUgAGpB//8DcSECA0AgAEH//wNxIAJPDQMgACADEKmAgIAAIABBAWohAAwACwsgASACQX9zaiIHQf//A3EhBAJAQYAYRQ0AIARBgBhsQfSHwIAAaiAHIAVrQf//A3FBgBhsQfSHwIAAakGAGPwKAAALIARBAToA+IfwgAAgAkEBaiECDAALCwvYAQEDfwJAIAJB//8DcUUNACABQf//A3EgAEH//wNxTQ0AIAJB//8DcSICIAEgAGtB//8DcSIEIAIgBEkbIgRBgBhsQfSHwIAAaiEFIAFB//8DcSEGIABB//8DcSIAQYAYbCECA0ACQCAEIABqIAZJDQADQCAAQf//A3EgAUH//wNxTw0DIAAgAxCpgICAACAAQQFqIQAMAAsLAkBBgBhFDQAgAkH0h8CAAGogBSACakGAGPwKAAALIABB+IfwgABqQQE6AAAgAkGAGGohAiAAQQFqIQAMAAsLCysAAkAgAEH//wNxQQAvAdqumIEATw0AIABBAC8B3K6YgQAgARC5gICAAAsLtQECA38BfiACQf//A3EhAyAAIAAoAqTfuwFBhBhsaiIEIQUCQANAIANFDQEgASkCACEGIAVBCGogAUEIaigCADYCACAFIAY3AgAgAUEMaiEBIAVBDGohBSADQX9qIQMMAAsLIAQgAjsBgBggACAAKAKk37sBQQFqQegHcDYCpN+7AQJAIAAoAqDfuwEiAUHoB0kNACAAIAAoAqjfuwFBAWo2AqjfuwEPCyAAIAFBAWo2AqDfuwEL3QIBA39BACECAkAgAEEBakH/AXEiA0EALQCgivCAACIETw0AAkACQAJAIANBAXQvAfyJ8IAAQX5qDgQBAwMAAwsgAEECakH/AXEiACAETw0CIABBAXQvAfyJ8IAAIQBBAiECDAELIABBBGpB/wFxIgMgBE8NASADQQF0LwH8ifCAACECAkAgAEECakH/AXFBAXQvAfyJ8IAAIgMgAEEDakH/AXFBAXQvAfyJ8IAAIgBHDQAgACACQf//A3FHDQBBBCECAkAgA0H/AXEiAEEITw0AQRAhAAwCCwJAIABB+AFNDQBB5wEhAAwCCyADQXhqQf8BcUEKbkHoAWoiAEH/ASAAQf8BSRshAAwBCyADQQVsQf8AakH//wNxQf8BbkEkbCAAQQVsQf8AakH//wNxQf8BbkEGbGogAkEFbEH/AGpB//8DcUH/AW5qQRBqIQBBBCECCyABIAA7AQALIAIL7QEBBH8jgICAgABBEGsiACSAgICAAAJAAkACQEEALwGCspiBAEEBaiIBQf//A3FBAC8B8LGYgQAiAkkNAEEALwHusZiBACEBQQAtAI2ymIEADQEgAUH//wNxDQFBACEBQQAoAsCO8IAAIgNFDQEgA0H0h8CAAEEALwHcrpiBABCugICAAEEALwHwsZiBACECQQAvAe6xmIEAIQEMAQtBACABOwGCspiBAAwBCyAAQYACNgIMIABBgAI7AQggAEEgNgIEIABBAC8B6LGYgQA7AQogASACQQEgAEEEahCsgICAAAsgAEEQaiSAgICAAAtYAAJAIAMgAkkNACAAQgA3AgAPCyAEQf8BcSEEAkADQCACIANGDQECQCABIANqLQAAIARHDQAgAEEBOgAEIAAgAzYCAA8LIANBAWohAwwACwsgAEIANwIAC/UCAQV/I4CAgIAAQRBrIgQkgICAgAACQAJAIAEgA0cNAEEBIQUgAUUNASAAQQEgARsiBiACQQEgAxsiB0YNAQJAIAFBEEsNAAJAIAFBBE8NACAALQAAIActAABGIAAgAUF/aiIDai0AACAHIANqLQAARnEgACABQQF2IgNqLQAAIAcgA2otAABGcSEFDAMLQQAhAyAEQQA2AgAgBCABQXxqIgU2AgQgBCABQQF2QQxxIgA2AgggBCAFIABrNgIMQQAhBQJAA0AgA0EQRg0BIAcgBCADaigCACIAaigAACAGIABqKAAAcyAFciEFIANBBGohAwwACwsgBUUhBQwCCyABQX9qQQJ2QQFqIQAgBiEDIAchBQJAA0AgAEF/aiIARQ0BIAUoAAAhAiADKAAAIQggA0EEaiEDIAVBBGohBSAIIAJHDQIMAAsLIAYgAUF8aiIDaigAACAHIANqKAAARiEFDAELQQAhBQsgBEEQaiSAgICAACAFC3UAAkAgAEH//wNxQQAvAfaH8IAATw0AIAFB//8DcUEALwH0h/CAAEH//wNxTw0AIABB//8DcSIAQYAYbCABQf//A3FBDGxqIgEgAikCADcC9IfAgAAgAUH8h8CAAGogAkEIaigCADYCACAAQQE6APiH8IAACwtKAEEAQQAvAYKymIEAOwHerpiBAEEAQQAvAfixmIEAOwHgrpiBAEEAQQAoAeaxmIEANgHirpiBAEEAQQAtAJLEoIEAOgCTxKCBAAtVAEEAQQAvAd6umIEAOwGCspiBAEEAQQAvAeCumIEAOwH4sZiBAEEAQQAoAeKumIEANgHmsZiBAEEAQQAtAJPEoIEAOgCSxKCBAEEAQQA6AJXEoIEAC8wDAQF/I4CAgIAAQYACayICJICAgIAAIAAgARC7gICAAAJAQcgERQ0AQfiJ8IAAQQBByAT8CwALQQAgATsB2q6YgQBBACAAOwHcrpiBAEEAQQE6AIiymIEAQQBCgICAgICggIABNwHerpiBAEEAQYCCgAg2AeaxmIEAQQBBAToAkcSggQBBACABOwHwsZiBAEEAQQA7AYKymIEAQQBBADoAlcSggQBBAEEAOwGSxKCBAEEAQQA2AuyxmIEAQQBBADoAkMSggQBBAEEAOgCLspiBAEEAQQA6AI60mIEAQQBBADoAirKYgQBBAEEANgH2sZiBAEEAQQA6AImymIEAQQBBADoAhrKYgQBBAEEAOgCHspiBAEEAQoCAgIiAIDcB+rGYgQBBAEEAOwGEspiBAEEAQQA6AIyymIEAQQBBADoAjbKYgQBBAEEAOwHYrpiBAEEAQQA6AI+0mIEAQQBBADYB8rGYgQBBAEEAOwHqsZiBAAJAQYACRQ0AIAJBAEGAAvwLAAtBCCEBAkADQCABQf8BSw0BIAIgAWpBAToAACABQQhqIQEMAAsLAkBBgAJFDQBBlsSggQAgAkGAAvwKAAALIAJBgAJqJICAgIAAC50BAQN/I4CAgIAAQRBrIgMkgICAgABBACEEA38CQCACQf//A3EiBQ0AIAFB/wFxIQIgA0ELakF/aiEFAkADQCAERQ0BIAAgAmogBSAEai0AADoAACACQQFqIQIgBEF/aiEEDAALCyADQRBqJICAgIAAIAIPCyADQQtqIARqIAIgBUEKbiIFQQpsa0EwcjoAACAEQQFqIQQgBSECDAALC5ICAQN/AkAgAEH//wNxQQAvAdqumIEATw0AIAFB//8DcUEALwHcrpiBAEH//wNxTw0AAkACQAJAAkAgAEH//wNxIgNBgBhsQfSHwIAAaiIEIAFB//8DcSIFQQxsaiIALQAJDgMABAEECyAFRQ0BIAQgAUF/akH//wNxQQxsaiIBLQAJQQJHDQEgASACKQIANwIAIAFBCGogAkEIaigCADYCAAwBCyAAIAIpAgA3AgAgAEEIaiACQQhqKAIANgIAIAFBAWoiAUH//wNxQQAvAdyumIEATw0BIAQgAUH//wNxQQxsaiIALQAJDQELIAAgAikCADcCACAAQQhqIAJBCGooAgA2AgALIANBAToA+IfwgAALC50CAQd/IABB//8DcSIDQYAYbEH0h8CAAGohBEEAIQBBACEFA0ACQAJAIABB//8DcSIGIAFB//8DcSIHTw0AAkACQAJAIAQgBkEMbGoiCC0ACQ4DAAQBAgsCQCAGRQ0AIAQgAEF/akH//wNxQQxsai0ACUECRg0ECyAIIAIpAgA3AgAgCEEIaiACQQhqKAIANgIAQQEhBQwDCwJAAkAgAEEBaiIJQf//A3EiBiAHTw0AIAQgBkEMbGotAAlFDQELIAggAikCADcCACAIQQhqIAJBCGooAgA2AgBBASEFIAkhAAwECyAAQQJqIQAMAwtBASEFIAhBAToACQwBCwJAIAVBAXFFDQAgA0EBOgD4h/CAAAsPCyAAQQFqIQAMAAsL0wMBAX8CQCAAQQFxQQAtAI2ymIEARg0AQQAoAtCumIEAIgJFDQACQAJAAkACQAJAAkAgAEEBcUUNAEEAQQAvAeyxmIEAOwHYrpiBAEEAQQA7AeyxmIEAIAFBAXENAQwECwJAQYSCMEUNAEH0h8CAACACQYSCMPwKAAALQQAhAEEAQQAvAdiumIEAOwHssZiBAEEAQQA6AI2ymIEAIAFBAXENAQwCC0EAQQAvAYKymIEAOwGEspiBAEEAQQAvAfixmIEAOwGAspiBAEEAQQAtAJLEoIEAOgCMspiBAEEAQQAoAeaxmIEAQRB3NgL8sZiBAAwCC0EAQQAvAYSymIEAOwGCspiBAEEAQQAvAYCymIEAOwH4sZiBAEEAQQAtAIyymIEAOgCSxKCBAEEAQQAoAvyxmIEAQRB3NgHmsZiBAEEAQQA6AJXEoIEAC0EALwHarpiBACEBA0AgASAARg0CIABB+IfwgABqQQE6AAAgAEEBaiEADAALCwJAQYSCMEUNACACQfSHwIAAQYSCMPwKAAALQQAvAdyumIEAQQAvAdqumIEAELuAgIAAQQBBAToAjbKYgQALQQBBAC8B2q6YgQA7AfCxmIEAQQBBADsB7rGYgQALC08AQQAgATsB9ofwgABBACAAOwH0h/CAAEEAIQACQANAIABB//8DcSABQf//A3FPDQEgABC8gICAACAAQQFqIQBBAC8B9ofwgAAhAQwACwsLEAAgAEGEgMCAABCpgICAAAsIAEHEvdyCAAvTCgENfyOAgICAAEEQayICJICAgIAAQYACIAFB//8DcSIDQQEgA0EBSxsiA0GAAiADQYACSRsgAUGAAksbIQRBAC8B2q6YgQAhBQJAAkBBgAIgAEH//wNxIgFBASABQQFLGyIBQYACIAFBgAJJGyAAQYACSxsiBkEALwHcrpiBACIDRw0AIAQgBUH//wNxRg0BCwJAIAYgA0kiB0UNACAEIAVB//8DcSIBIAQgAUkbIQggBkEMbEH0h8CAAGohCUEAIQoDQCAKIAhGDQEgCSEBIAYhAAJAA0AgAyAAQf//A3FGDQEgAUEIakEAKAKMgMCAADYCACABQQApAoSAwIAANwIAIAFBDGohASAAQQFqIQAMAAsLIAlBgBhqIQkgCkEBaiEKDAALCwJAIAQgBUH//wNxIghPDQBBAC8BgrKYgQAiASAESSIADQBBACABIARrQQFqIgEgABshCwJAQQAtAI2ymIEADQBBACgCwI7wgABFDQAgBiADIAcbIQogAUH//wNxIQlB9IfAgAAhAEEAIQEDQCAJIAFGDQEgASAKQYSAwIAAELmAgIAAQQAoAsCO8IAAIAAgChCugICAACAAQYAYaiEAIAFBAWohAQwACwtBACAFIAtBhIDAgAAQrICAgABBAEEAQQAvAYKymIEAIgEgC0H//wNxayIAIAAgAUsbOwGCspiBAAtBACEBQQAgBDsB2q6YgQBBACAGOwHcrpiBAEEAIAQ7AfaH8IAAQQAgBjsB9IfwgAACQCAEIAhNDQACQEEALQCNspiBAA0AQQAhAUEAKALAjvCAACIARQ0AIAAoAqDfuwEiACAEIAVrQf//A3EiCiAAIApJGyIMRQ0AQQAgBSAMaiAMQYSAwIAAEKuAgIAAIAxBf2ohC0EAIQcCQANAIAcgDEYNAUEAKALAjvCAACIKKAKg37sBIgFFDQEgC0H//wNxQYAYbEH0h8CAAGohACAKIAFBf2o2AqDfuwEgCiAKKAKk37sBQecHakHoB3AiCTYCpN+7ASAHQX9zIAxqIg1B//8DcSEOQQAhASAKIAlBhBhsaiIIIQkDQAJAAkAgBiABRg0AQYSAwIAAIQogASAILwGAGE8NASACQQhqIAlBCGooAgA2AgAgAiAJKQIANwMAIAIhCgwBCyANIAZBhIDAgAAQuYCAgAAgDkEBOgD4h/CAACALQX9qIQsgB0EBaiEHDAILIAAgCikCADcCACAAQQhqIApBCGooAgA2AgAgAEEMaiEAIAlBDGohCSABQQFqIQEMAAsLC0EAQQAvAYKymIEAIAxqOwGCspiBACAMIQELIAEgBWohAQNAIAFB//8DcSAETw0BIAEQvICAgAAgAUEBaiEBDAALCwJAIAYgA00NACAEIAVB//8DcSIBIAQgAUkbIQkgBiADayEIIANBDGxB9IfAgABqIQpBACEDA0AgAyAJRg0BIAghACAKIQECQANAIABFDQEgAUEIakEAKAKMgMCAADYCACABQQApAoSAwIAANwIAIABBf2ohACABQQxqIQEMAAsLIANBAToA+IfwgAAgCkGAGGohCiADQQFqIQMMAAsLQQAhAUEAIAQ7AfCxmIEAQQBBADsB7rGYgQACQANAIAFB//8DcSAETw0BIAFBhIDAgAAQrYCAgAAgAUEBaiEBDAALCwJAQQAvAfixmIEAIAZJDQBBACAGQX9qOwH4sZiBAAsCQEEALwGCspiBACAESQ0AQQAgBEF/ajsBgrKYgQALQQAhAQNAIAQgAUYNASABQfiH8IAAakEBOgAAIAFBAWohAQwACwsgAkEQaiSAgICAAAt0AEGAAiAAQQEgABsgAEGAAksbQYACIAFBASABGyABQYACSxsQtoCAgABBAEHE/dyCADYC0K6YgQBBAEGY3qCBADYCwI7wgABBAEIANwK4vdyCAEEAQQA2AsSO8IAAQQBBADsByK6YgQBBAEEANgLAvdyCAAsL/gcBAEGAgMAAC/QHaWQ9ACAAAAAAAQABAAEAAEUAAAAAAQABAAEAAAARAABfEQAAGiMAABsjAAApIwAAKiMAAOkjAADsIwAA8CMAAPAjAADzIwAA8yMAAP0lAAD+JQAAFCYAABUmAAAwJgAANyYAAEgmAABTJgAAfyYAAH8mAACKJgAAjyYAAJMmAACTJgAAoSYAAKEmAACqJgAAqyYAAL0mAAC+JgAAxCYAAMUmAADOJgAAziYAANQmAADUJgAA6iYAAOomAADyJgAA8yYAAPUmAAD1JgAA+iYAAPomAAD9JgAA/SYAAAUnAAAFJwAACicAAAsnAAAoJwAAKCcAAEwnAABMJwAATicAAE4nAABTJwAAVScAAFcnAABXJwAAlScAAJcnAACwJwAAsCcAAL8nAAC/JwAAGysAABwrAABQKwAAUCsAAFUrAABVKwAAgC4AAJkuAACbLgAA8y4AAAAvAADVLwAA8C8AAD4wAABBMAAAljAAAJkwAAD/MAAABTEAAC8xAAAxMQAAjjEAAJAxAADlMQAA7zEAAB4yAAAgMgAARzIAAFAyAACMpAAAkKQAAMakAABgqQAAfKkAAACsAACj1wAAAPkAAP/6AAAQ/gAAGf4AADD+AABS/gAAVP4AAGb+AABo/gAAa/4AAAH/AABg/wAA4P8AAOb/AADgbwEA5G8BAPBvAQD2bwEAAHABANWMAQD/jAEAHo0BAICNAQDyjQEA8K8BAPOvAQD1rwEA+68BAP2vAQD+rwEAALABACKxAQAysQEAMrEBAFCxAQBSsQEAVbEBAFWxAQBksQEAZ7EBAHCxAQD7sgEAANMBAFbTAQBg0wEAdtMBAATwAQAE8AEAz/ABAM/wAQCO8QEAjvEBAJHxAQCa8QEAAPIBAALyAQAQ8gEAO/IBAEDyAQBI8gEAUPIBAFHyAQBg8gEAZfIBAADzAQAg8wEALfMBADXzAQA38wEAfPMBAH7zAQCT8wEAoPMBAMrzAQDP8wEA0/MBAODzAQDw8wEA9PMBAPTzAQD48wEAPvQBAED0AQBA9AEAQvQBAPz0AQD/9AEAPfUBAEv1AQBO9QEAUPUBAGf1AQB69QEAevUBAJX1AQCW9QEApPUBAKT1AQD79QEAT/YBAID2AQDF9gEAzPYBAMz2AQDQ9gEA0vYBANX2AQDY9gEA3PYBAN/2AQDr9gEA7PYBAPT2AQD89gEA4PcBAOv3AQDw9wEA8PcBAAz5AQA6+QEAPPkBAEX5AQBH+QEA//kBAHD6AQB8+gEAgPoBAIr6AQCO+gEAxvoBAMj6AQDI+gEAzfoBANz6AQDf+gEA6voBAO/6AQD4+gEAAAACAP3/AgAAAAMA/f8DAA==";function EA(A){let t=atob(A),e=new Uint8Array(t.length);for(let s=0;s<t.length;s++)e[s]=t.charCodeAt(s);return e.buffer}class L{get dv(){if(this._dvBuffer!==this.memory.buffer)this._dvBuffer=this.memory.buffer,this._dv=new DataView(this.memory.buffer);return this._dv}constructor(A){this.gridPtr=0,this.dirtyPtr=0,this.writeBufferPtr=0,this.cellSize=12,this.maxCols=256,this.encoder=new TextEncoder,this.decoder=new TextDecoder,this._dvBuffer=null,this.linkCache=new Map,this.exports=A.exports,this.memory=this.exports.memory}static async load(A){let t;if(A){let s=await fetch(A);if(!s.ok)throw Error(`[wterm] Failed to load WASM from ${A}: ${s.status} ${s.statusText}`);t=await s.arrayBuffer()}else t=EA(j);let{instance:e}=await WebAssembly.instantiate(t);return new L(e)}init(A,t){this.exports.init(A,t),this.linkCache.clear(),this._updatePointers()}_updatePointers(){this.gridPtr=this.exports.getGridPtr(),this.dirtyPtr=this.exports.getDirtyPtr(),this.writeBufferPtr=this.exports.getWriteBuffer(),this.cellSize=this.exports.getCellSize(),this.maxCols=this.exports.getMaxCols()}writeString(A,t){let e=this.encoder.encode(A);this.writeRaw(e,t)}writeRaw(A,t){let e=0;while(e<A.length){let s=Math.min(A.length-e,8192);new Uint8Array(this.memory.buffer,this.writeBufferPtr,8192).set(A.subarray(e,e+s)),this.exports.writeBytes(s),e+=s,t?.()}}getCell(A,t){let e=this.gridPtr+(A*this.maxCols+t)*this.cellSize,s=this.dv,i={char:s.getUint32(e,!0),fg:s.getUint16(e+4,!0),bg:s.getUint16(e+6,!0),flags:s.getUint8(e+8),width:s.getUint8(e+9)};return Object.assign(i,this._readLink(s.getUint16(e+10,!0))),i}isDirtyRow(A){return new Uint8Array(this.memory.buffer,this.dirtyPtr,256)[A]!==0}clearDirty(){this.exports.clearDirty()}getCursor(){return{row:this.exports.getCursorRow(),col:this.exports.getCursorCol(),visible:this.exports.getCursorVisible()!==0}}getCols(){return this.exports.getCols()}getRows(){return this.exports.getRows()}cursorKeysApp(){return this.exports.getCursorKeysApp()!==0}bracketedPaste(){return this.exports.getBracketedPaste()!==0}usingAltScreen(){return this.exports.getUsingAltScreen()!==0}mouseTracking(){let A=this.exports.getMouseTracking();return A===1000||A===1002?A:0}mouseSgr(){return this.exports.getMouseSgr()!==0}focusEvents(){return this.exports.getFocusEvents()!==0}synchronizedOutput(){return this.exports.getSynchronizedOutput()!==0}synchronizedOutputGeneration(){return this.exports.getSynchronizedOutputGeneration()}getTitle(){if(this.exports.getTitleChanged()===0)return null;let A=this.exports.getTitlePtr(),t=this.exports.getTitleLen(),e=new Uint8Array(this.memory.buffer,A,t);return this.decoder.decode(e)}getResponse(){let A=this.exports.getResponseLen();if(A===0)return null;let t=this.exports.getResponsePtr(),e=new Uint8Array(this.memory.buffer,t,A),s=this.decoder.decode(e);return this.exports.clearResponse(),s}getResourceState(){let A=this.exports.getHyperlinkCapacity?.(),t=this.exports.getHyperlinkCount?.(),e=this.exports.getHyperlinkRejectedCount?.();if(A===void 0||t===void 0||e===void 0)return{};return{hyperlinks:{capacity:A,used:t,rejected:e,saturated:t>=A}}}getScrollbackCount(){return this.exports.getScrollbackCount()}getScrollbackDiscardedCount(){return this.exports.getScrollbackDiscardedCount()}getScrollbackCell(A,t){let s=this.exports.getScrollbackLine(A)+t*this.cellSize,i=this.dv,r={char:i.getUint32(s,!0),fg:i.getUint16(s+4,!0),bg:i.getUint16(s+6,!0),flags:i.getUint8(s+8),width:i.getUint8(s+9)};return Object.assign(r,this._readLink(i.getUint16(s+10,!0))),r}getScrollbackLineLen(A){return this.exports.getScrollbackLineLen(A)}getUnhandledSequences(){let A=this.exports.getDebugLogCount();if(A===0)return[];let t=this.exports.getDebugLogPtr(),e=this.exports.getDebugLogEntrySize(),s=this.exports.getDebugLogMax(),i=Math.min(A,s),r=new DataView(this.memory.buffer),o=[],n=A>=s?A%s:0;for(let Q=0;Q<i;Q++){let B=(n+Q)%s,l=t+B*e,h=r.getUint8(l);if(h===0)continue;let E=r.getUint8(l+1),C=r.getUint8(l+2),f=[];for(let b=0;b<Math.min(C,4);b++)f.push(r.getUint16(l+4+b*2,!0));o.push({final:String.fromCharCode(h),private:E?String.fromCharCode(E):"",paramCount:C,params:f})}return o}resize(A,t){this.exports.resizeTerminal(A,t),this._updatePointers()}_readLink(A){if(A===0)return;let t=this.linkCache.get(A);if(t)return t;let e=this.exports.getLinkUriLen(A);if(e===0)return;let s=this.decoder.decode(new Uint8Array(this.memory.buffer,this.exports.getLinkUriPtr(A),e)),i=this.exports.getLinkIdLen(A),r=i===0?void 0:this.decoder.decode(new Uint8Array(this.memory.buffer,this.exports.getLinkIdPtr(A),i)),o={linkUri:s,linkId:r,linkKey:r?`e\x00${r}\x00${s}`:`b\x00${A}`};return this.linkCache.set(A,o),o}}function oA(A){let t=A>>16&255,e=A>>8&255,s=A&255;return`rgb(${t},${e},${s})`}function nA(A){if(A===256)return null;if(A<16)return`var(--term-color-${A})`;if(A<232){let e=A-16,s=Math.floor(e/36)*51,i=Math.floor(e/6)%6*51,r=e%6*51;return`rgb(${s},${i},${r})`}let t=(A-232)*10+8;return`rgb(${t},${t},${t})`}function BA(A,t){if(t!==void 0)return oA(t);return nA(A)}function J(A,t){if(t!==void 0)return oA(t);return nA(A)}function AA(A,t,e,s,i){let r=A,o=t,n=s,Q=i;if(e&32){let C=r;r=o,o=C;let f=n;if(n=Q,Q=f,n===void 0&&r===256)r=0;if(Q===void 0&&o===256)o=7}let B=BA(r,n),l=J(o,Q),h="";if(B)h+=`color:${B};`;if(l)h+=`background:${l};`;if(e&1)h+="font-weight:bold;";if(e&2)h+="opacity:0.5;";if(e&4)h+="font-style:italic;";let E=[];if(e&8)E.push("underline");if(e&128)E.push("line-through");if(E.length)h+=`text-decoration:${E.join(" ")};`;if(e&64)h+="visibility:hidden;";return h}function S(A){return A.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}function CA(A){if(!A)return;try{let t=new URL(A);return t.protocol==="http:"||t.protocol==="https:"?t.href:void 0}catch{return}}function IA(A){if(!A.linkUri)return"";return A.linkKey??`fallback\x00${A.linkId??""}\x00${A.linkUri}`}function uA(A,t,e,s,i){let r=A,o=t,n=s,Q=i;if(e&32){if([r,o]=[o,r],[n,Q]=[Q,n],n===void 0&&r===256)r=0;if(Q===void 0&&o===256)o=7}return{fg:BA(r,n)||"var(--term-fg)",bg:J(o,Q)||"var(--term-bg)"}}var v="round(calc(var(--term-row-height) * 0.125), 1px)",tA="round(calc(var(--term-row-height) * 0.25), 1px)",eA="round(calc(var(--term-row-height) * 0.375), 1px)",M="round(calc(var(--term-row-height) * 0.5), 1px)",sA="round(calc(var(--term-row-height) * 0.625), 1px)",iA="round(calc(var(--term-row-height) * 0.75), 1px)",rA="round(calc(var(--term-row-height) * 0.875), 1px)";function wA(A,t,e){switch(A){case 9600:return`linear-gradient(${t} ${M},${e} ${M})`;case 9601:return`linear-gradient(${e} ${rA},${t} ${rA})`;case 9602:return`linear-gradient(${e} ${iA},${t} ${iA})`;case 9603:return`linear-gradient(${e} ${sA},${t} ${sA})`;case 9604:return`linear-gradient(${e} ${M},${t} ${M})`;case 9605:return`linear-gradient(${e} ${eA},${t} ${eA})`;case 9606:return`linear-gradient(${e} ${tA},${t} ${tA})`;case 9607:return`linear-gradient(${e} ${v},${t} ${v})`;case 9608:return t;case 9609:return`linear-gradient(to right,${t} 87.5%,${e} 87.5%)`;case 9610:return`linear-gradient(to right,${t} 75%,${e} 75%)`;case 9611:return`linear-gradient(to right,${t} 62.5%,${e} 62.5%)`;case 9612:return`linear-gradient(to right,${t} 50%,${e} 50%)`;case 9613:return`linear-gradient(to right,${t} 37.5%,${e} 37.5%)`;case 9614:return`linear-gradient(to right,${t} 25%,${e} 25%)`;case 9615:return`linear-gradient(to right,${t} 12.5%,${e} 12.5%)`;case 9616:return`linear-gradient(to right,${e} 50%,${t} 50%)`;case 9617:return`color-mix(in srgb,${t} 25%,${e})`;case 9618:return`color-mix(in srgb,${t} 50%,${e})`;case 9619:return`color-mix(in srgb,${t} 75%,${e})`;case 9620:return`linear-gradient(${t} ${v},${e} ${v})`;case 9621:return`linear-gradient(to right,${e} 87.5%,${t} 87.5%)`;default:{let i={9622:[!1,!1,!0,!1],9623:[!1,!1,!1,!0],9624:[!0,!1,!1,!1],9625:[!0,!1,!0,!0],9626:[!0,!1,!1,!0],9627:[!0,!0,!0,!1],9628:[!0,!0,!1,!0],9629:[!1,!0,!1,!1],9630:[!1,!0,!0,!1],9631:[!1,!0,!0,!0]}[A];if(!i)return t;let[r,o,n,Q]=i;if(r&&o&&n&&Q)return t;let B=[],l=["0 0","100% 0","0 100%","100% 100%"];return i.forEach((h,E)=>{if(h)B.push(`linear-gradient(${t},${t}) ${l[E]}/50% 50% no-repeat`)}),B.push(e),B.join(",")}}}class Y{constructor(A){this.rows=0,this.cols=0,this.rowEls=[],this.prevCursorRow=-1,this.prevCursorCol=-1,this.prevContainerBg="",this.prevRowBg=[],this._scrollbackRowEls=[],this._scrollbackStartKey=0,this._renderedScrollbackCount=-1,this._renderedDiscardedCount=-1,this._scrollbackTopSpacer=null,this._scrollbackBottomSpacer=null,this.container=A}setup(A,t){this.cols=A,this.rows=t,this.container.innerHTML="",this.rowEls=[],this.prevRowBg=[],this._scrollbackRowEls=[],this._scrollbackStartKey=0,this._renderedScrollbackCount=-1,this._renderedDiscardedCount=-1;let e=document.createDocumentFragment();this._scrollbackTopSpacer=document.createElement("div"),this._scrollbackTopSpacer.className="term-scrollback-spacer",e.appendChild(this._scrollbackTopSpacer),this._scrollbackBottomSpacer=document.createElement("div"),this._scrollbackBottomSpacer.className="term-scrollback-spacer",e.appendChild(this._scrollbackBottomSpacer);for(let s=0;s<t;s++){let i=document.createElement("div");i.className="term-row",e.appendChild(i),this.rowEls.push(i)}this.container.appendChild(e),this.prevCursorRow=-1,this.prevCursorCol=-1}_buildRowContent(A,t,e,s,i){let r="",o="",n="",Q=[],B=0,l="",h,E="",C=(a,g,c)=>{let I=CA(c),p=I?g:"";if(p!==E){if(E)r+="</a>";if(p)r+=`<a class="term-link" href="${S(I)}" target="_blank" rel="noopener noreferrer">`;E=p}r+=a},f=(a)=>{if(!n)return;let g=S(n),c="";if(s>=B&&s<a){let I=s-B,p=Q.slice(0,I).join(""),w=Q[I]||" ",u=Q.slice(I+1).join("");if(p)c+=o?`<span style="${o}">${S(p)}</span>`:`<span>${S(p)}</span>`;if(c+=o?`<span class="term-cursor" style="${o}">${S(w)}</span>`:`<span class="term-cursor">${S(w)}</span>`,u)c+=o?`<span style="${o}">${S(u)}</span>`:`<span>${S(u)}</span>`}else c+=o?`<span style="${o}">${g}</span>`:`<span>${g}</span>`;C(c,l,h),n="",Q=[]},b=(a,g,c,I,p)=>{let w=a?` class="${a}"`:"",u=g?` style="${g}"`:"";C(`<span${w}${u}>${S(c)}</span>`,I,p)};for(let a=0;a<this.cols;a++){let g=t(a),c=a<e,I=c?g.char:0,p=c?g.width??1:1,w=c?IA(g):"",u=c?g.linkUri:void 0;if(c&&p===0){if(f(a),!(a>0&&(t(a-1).width??1)===2))b(a===s?"term-cursor":"",""," ",w,u);o="",l="",h=void 0,n="",Q=[],B=a+1;continue}if(c&&p===2){if(f(a),a+1>=this.cols){b(a===s?"term-cursor":"",""," ",w,u),o="",l="",h=void 0,n="",Q=[],B=a+1;continue}let d=g.chars??(I>=32?String.fromCodePoint(I):" "),x=AA(g.fg,g.bg,g.flags,g.fgRgb,g.bgRgb),U=s>=a&&s<a+2?"term-wide term-cursor":"term-wide";b(U,x,d,w,u),o="",l="",h=void 0,n="",Q=[],B=a+2;continue}if(c&&I>=9600&&I<=9631){f(a);let d=uA(g.fg,g.bg,g.flags,g.fgRgb,g.bgRgb),x=a===s?"term-block term-cursor":"term-block",U=wA(I,d.fg,d.bg),lA=g.flags&2?"opacity:0.5;":"";C(`<span class="${x}" style="background:${U};${lA}"></span>`,w,u),o="",l="",h=void 0,n="",Q=[],B=a+1}else{let d=g.chars??(c&&I>=32?String.fromCodePoint(I):" "),x=c?AA(g.fg,g.bg,g.flags,g.fgRgb,g.bgRgb):"";if(x!==o||w!==l)f(a),o=x,l=w,h=u,n=d,Q=[d],B=a;else n+=d,Q.push(d)}}if(f(this.cols),E)r+="</a>";A.innerHTML=r;let m="";if(e>=this.cols&&this.cols>0){let a=t(this.cols-1),g=a.bg,c=a.bgRgb;if(a.flags&32){if(g=a.fg,c=a.fgRgb,c===void 0&&g===256)g=7}m=J(g,c)||""}let _=m?`0 1px 0 ${m}`:"";if(i>=0){if(m!==(this.prevRowBg[i]??""))A.style.background=m,A.style.boxShadow=_,this.prevRowBg[i]=m}else A.style.background=m,A.style.boxShadow=_}_buildScrollbackRowEl(A,t){let e=document.createElement("div");e.className="term-row term-scrollback-row";let s=A.getScrollbackLineLen(t);return this._buildRowContent(e,(i)=>A.getScrollbackCell(t,i),s,-1,-1),e}syncScrollback(A,t){let e=A.getScrollbackCount(),s=t?.rowHeight??0,i=t!==void 0&&s>0,r=t?.overscanRows??10,o=t?.scrollbackDiscardedCount!==void 0,n=t?.scrollbackDiscardedCount??0,Q=t&&t.clientHeight>0?t.clientHeight:this.rows*s,B=i?Math.floor(t.scrollTop/s):0,l=i?Math.ceil(Q/s):e,h=i?Math.max(0,Math.min(e,B-r)):0,E=i?Math.max(h,Math.min(e,B+l+r)):e,C=this.container.ownerDocument.getSelection();if(C!==null&&!C.isCollapsed&&(this.container.contains(C.anchorNode)||this.container.contains(C.focusNode))&&this._scrollbackRowEls.length>0)h=Math.min(h,Math.max(0,this._scrollbackStartKey-n)),E=Math.max(E,Math.min(e,this._scrollbackStartKey-n+this._scrollbackRowEls.length));let b=n+h;if(o&&e===this._renderedScrollbackCount&&n===this._renderedDiscardedCount&&b===this._scrollbackStartKey&&E-h===this._scrollbackRowEls.length)return;let m=new Map;for(let c=0;c<this._scrollbackRowEls.length;c++)m.set(this._scrollbackStartKey+c,this._scrollbackRowEls[c]);let _=n+E;for(let[c,I]of m)if(c<b||c>=_)I.remove();let a=[],g=this._scrollbackTopSpacer?.nextSibling??null;for(let c=h;c<E;c++){let I=n+c,p=e-1-c,w=this._buildScrollbackRowEl(A,p),u=m.get(I),d=w,x=!1;if(u&&u.innerHTML===w.innerHTML&&u.style.cssText===w.style.cssText)d=u;else if(u)u.replaceWith(w),x=!0;if(!x&&d!==g)this.container.insertBefore(d,g??this._scrollbackBottomSpacer);g=d.nextSibling,a.push(d)}if(this._scrollbackRowEls=a,this._scrollbackStartKey=b,this._renderedScrollbackCount=e,this._renderedDiscardedCount=n,this._scrollbackTopSpacer)this._scrollbackTopSpacer.style.height=`${h*s}px`;if(this._scrollbackBottomSpacer)this._scrollbackBottomSpacer.style.height=`${(e-E)*s}px`}render(A,t){let e=A.getRows(),s=A.getCols(),i=!1;if(e!==this.rows||s!==this.cols)this.setup(s,e),i=!0;this.syncScrollback(A,t);let r=A.getCursor(),o=r.visible,n=r.row!==this.prevCursorRow||r.col!==this.prevCursorCol;for(let B=0;B<this.rows;B++){let l=i||A.isDirtyRow(B),h=B===this.prevCursorRow&&n,E=B===r.row;if(l||h||E&&n){let C=E&&o?r.col:-1;this._buildRowContent(this.rowEls[B],(f)=>A.getCell(B,f),this.cols,C,B)}}if(this.prevCursorRow=r.row,this.prevCursorCol=r.col,i||A.isDirtyRow(this.rows-1)){let B=A.getCell(this.rows-1,this.cols-1),l=B.bg,h=B.bgRgb;if(B.flags&32){if(l=B.fg,h=B.fgRgb,h===void 0&&l===256)l=7}let E=J(l,h)||"";if(E!==this.prevContainerBg)this.container.style.background=E,this.prevContainerBg=E}A.clearDirty()}}function G(A,t){return t.platform.startsWith("Mac")?A.metaKey:A.ctrlKey}var dA={ArrowUp:"\x1B[A",ArrowDown:"\x1B[B",ArrowRight:"\x1B[C",ArrowLeft:"\x1B[D",Home:"\x1B[H",End:"\x1B[F"},fA={ArrowUp:"\x1BOA",ArrowDown:"\x1BOB",ArrowRight:"\x1BOC",ArrowLeft:"\x1BOD",Home:"\x1BOH",End:"\x1BOF"},pA={Enter:"\r",Backspace:"",Tab:"\t",Escape:"\x1B",Insert:"\x1B[2~",Delete:"\x1B[3~",PageUp:"\x1B[5~",PageDown:"\x1B[6~",F1:"\x1BOP",F2:"\x1BOQ",F3:"\x1BOR",F4:"\x1BOS",F5:"\x1B[15~",F6:"\x1B[17~",F7:"\x1B[18~",F8:"\x1B[19~",F9:"\x1B[20~",F10:"\x1B[21~",F11:"\x1B[23~",F12:"\x1B[24~"};class N{constructor(A,t,e,s=()=>null){this.composing=!1,this.mouseButtons=0,this.focused=!1,this.element=A,this.onData=t,this.getBridge=e,this.getCellSize=s,this.textarea=document.createElement("textarea"),this.textarea.setAttribute("autocapitalize","off"),this.textarea.setAttribute("autocomplete","off"),this.textarea.setAttribute("autocorrect","off"),this.textarea.setAttribute("spellcheck","false"),this.textarea.setAttribute("enterkeyhint","send"),this.textarea.setAttribute("tabindex","0"),this.textarea.setAttribute("aria-hidden","true");let i=this.textarea.style;i.position="absolute",i.left="-9999px",i.top="0",i.width="1px",i.height="1px",i.opacity="0",i.overflow="hidden",i.border="0",i.padding="0",i.margin="0",i.outline="none",i.resize="none",i.pointerEvents="none",i.caretColor="transparent",i.color="transparent",i.background="transparent",A.appendChild(this.textarea),this._onKeyDown=this.handleKeyDown.bind(this),this._onPaste=this.handlePaste.bind(this),this._onCompositionStart=this.handleCompositionStart.bind(this),this._onCompositionEnd=this.handleCompositionEnd.bind(this),this._onInput=this.handleInput.bind(this),this._onFocus=()=>{if(this.focused)return;if(this.focused=!0,this.element.classList.add("focused"),this.getBridge()?.focusEvents?.())this.onData("\x1B[I")},this._onBlur=()=>{if(this.focused=!1,this.element.classList.remove("focused"),this.stopMouseCapture(),this.getBridge()?.focusEvents?.())this.onData("\x1B[O")},this._onMouseDown=(r)=>this.handleMouse(r,"press"),this._onMouseMove=(r)=>{if(this.mouseButtons!==0)this.handleMouse(r,"move")},this._onMouseUp=(r)=>{if(this.mouseButtons===0)return;if(this.handleMouse(r,"release"),this.mouseButtons=r.buttons&7,this.mouseButtons===0)this.stopMouseCapture()},this._onWheel=(r)=>this.handleMouse(r,"wheel"),this.textarea.addEventListener("keydown",this._onKeyDown),this.textarea.addEventListener("paste",this._onPaste),this.textarea.addEventListener("compositionstart",this._onCompositionStart),this.textarea.addEventListener("compositionend",this._onCompositionEnd),this.textarea.addEventListener("input",this._onInput),this.textarea.addEventListener("focus",this._onFocus),this.textarea.addEventListener("blur",this._onBlur),this.element.addEventListener("mousedown",this._onMouseDown),this.element.addEventListener("wheel",this._onWheel,{passive:!1})}focus(){this.textarea.focus({preventScroll:!0})}destroy(){this.textarea.removeEventListener("keydown",this._onKeyDown),this.textarea.removeEventListener("paste",this._onPaste),this.textarea.removeEventListener("compositionstart",this._onCompositionStart),this.textarea.removeEventListener("compositionend",this._onCompositionEnd),this.textarea.removeEventListener("input",this._onInput),this.textarea.removeEventListener("focus",this._onFocus),this.textarea.removeEventListener("blur",this._onBlur),this.element.removeEventListener("mousedown",this._onMouseDown),this.stopMouseCapture(),this.element.removeEventListener("wheel",this._onWheel),this.element.classList.remove("focused"),this.textarea.remove()}handleKeyDown(A){if(this.composing)return;if((A.metaKey||A.ctrlKey)&&A.key==="c"){let e=window.getSelection();if(e&&e.toString().length>0)return}if((A.metaKey||A.ctrlKey)&&A.key==="v"){this.textarea.focus();return}if(A.metaKey&&!A.ctrlKey){if(A.key==="Backspace")A.preventDefault(),this.onData("\x15");else if(A.key==="a"){A.preventDefault();let e=window.getSelection();if(e){let s=document.createRange();s.selectNodeContents(this.element),e.removeAllRanges(),e.addRange(s)}}return}A.preventDefault();let t=this.keyToSequence(A);if(t)this.onData(t)}handlePaste(A){A.preventDefault();let t=A.clipboardData?.getData("text");if(!t)return;let e=this.getBridge();if(e&&e.bracketedPaste()){let s=t.replace(/\x1b/g,"");this.onData("\x1B[200~"+s+"\x1B[201~")}else this.onData(t)}handleCompositionStart(){this.composing=!0}handleCompositionEnd(A){if(this.composing=!1,A.data)this.onData(A.data);this.textarea.value=""}handleInput(){if(this.composing)return;let A=this.textarea.value;if(A)this.onData(A),this.textarea.value=""}handleMouse(A,t){let e=this.getBridge(),s=e?.mouseTracking?.()??0;if(!e||s===0||!e.mouseSgr?.())return;if(t==="press"&&G(A,this.element.ownerDocument.defaultView?.navigator??navigator)&&A.target instanceof Element&&A.target.closest(".term-link"))return;if(t==="press"&&(A.shiftKey||A.button>2))return;if(t==="release"&&A.button>2)return;let i=A.buttons&7;if(t==="move"&&(s!==1002||i===0))return;let r=this.element.ownerDocument.defaultView;if(!r)return;let o=this.element.querySelector(".term-row:not(.term-scrollback-row)"),n=this.element.getBoundingClientRect(),Q=o?.getBoundingClientRect(),B=this.getCellSize(),l,h,E,C;if(Q&&B)l=Q.left,h=Q.top,E=B.charWidth,C=B.rowHeight;else{let g=r.getComputedStyle(this.element),c=parseFloat(g.borderLeftWidth)||0,I=parseFloat(g.borderRightWidth)||0,p=parseFloat(g.borderTopWidth)||0,w=parseFloat(g.borderBottomWidth)||0,u=parseFloat(g.paddingLeft)||0,d=parseFloat(g.paddingRight)||0,x=parseFloat(g.paddingTop)||0,U=parseFloat(g.paddingBottom)||0;l=Q?.left??n.left+c+u,h=Q?.top??n.top+p+x,E=(n.width-c-I-u-d)/e.getCols(),C=(n.height-p-w-x-U)/e.getRows()}if(E<=0||C<=0)return;if(t==="press"){if(this.textarea.focus({preventScroll:!0}),!this.focused)this._onFocus();this.mouseButtons=i||(A.button===1?4:A.button===2?2:1),r.addEventListener("mousemove",this._onMouseMove),r.addEventListener("mouseup",this._onMouseUp)}let f=Math.max(1,Math.min(e.getCols(),Math.floor((A.clientX-l)/E)+1)),b=Math.max(1,Math.min(e.getRows(),Math.floor((A.clientY-h)/C)+1)),m=(A.shiftKey?4:0)|(A.altKey?8:0)|(A.ctrlKey?16:0),_,a="M";if(t==="wheel"){let g=A;if(Math.abs(g.deltaX)>Math.abs(g.deltaY)){if(g.deltaX===0)return;_=(g.deltaX<0?66:67)|m}else{if(g.deltaY===0)return;_=(g.deltaY<0?64:65)|m}}else if(_=(t==="move"?i&4?1:i&2?2:0:A.button===1?1:A.button===2?2:0)|m|(t==="move"?32:0),t==="release")a="m";A.preventDefault(),this.onData(`\x1B[<${_};${f};${b}${a}`)}stopMouseCapture(){this.mouseButtons=0;let A=this.element.ownerDocument.defaultView;A?.removeEventListener("mousemove",this._onMouseMove),A?.removeEventListener("mouseup",this._onMouseUp)}keyToSequence(A){if(A.ctrlKey&&!A.altKey&&!A.metaKey){if(A.key.length===1){let o=A.key.toLowerCase().charCodeAt(0);if(o>=97&&o<=122)return String.fromCharCode(o-96)}if(A.key==="[")return"\x1B";if(A.key==="\\")return"\x1C";if(A.key==="]")return"\x1D";if(A.key==="^")return"\x1E";if(A.key==="_")return"\x1F"}if(A.key==="Enter"&&A.shiftKey)return"\x1B[13;2u";if(A.key==="Tab"&&A.shiftKey)return"\x1B[Z";let t=pA[A.key];if(t)return A.altKey?"\x1B"+t:t;let e=this.getBridge(),r=(e&&e.cursorKeysApp()?fA:dA)[A.key];if(r)return A.altKey?"\x1B"+r:r;if(A.key.length===1&&!A.ctrlKey&&!A.metaKey)return A.altKey?"\x1B"+A.key:A.key;return null}}var mA={1:"bold",2:"dim",4:"italic",8:"underline",16:"blink",32:"reverse",64:"invisible",128:"strikethrough"};function bA(A){let t=[];for(let[e,s]of Object.entries(mA))if(A&Number(e))t.push(s);return t}var z=27;function xA(A){let t=[],e=Date.now(),s=0,i=0,r=()=>{if(s>i){let o=A.slice(i,s);if(o.length>0&&!/^[\x00-\x1f]+$/.test(o))t.push({ts:e,type:"text",raw:o.slice(0,60)})}};while(s<A.length){if(A.charCodeAt(s)!==z){s++;continue}r();let o=s;if(s++,s>=A.length)break;let n=A[s];if(n==="["){s++;let Q="";if(s<A.length&&(A[s]==="?"||A[s]===">"||A[s]==="!"))Q=A[s],s++;let B="";while(s<A.length&&(A.charCodeAt(s)>=48&&A.charCodeAt(s)<=59||A[s]===":"))B+=A[s],s++;while(s<A.length&&A.charCodeAt(s)>=32&&A.charCodeAt(s)<=47)s++;let l="";if(s<A.length&&A.charCodeAt(s)>=64&&A.charCodeAt(s)<=126)l=A[s],s++;let h=A.slice(o,s),E=B?B.split(/[;:]/).map(Number).filter((f)=>!isNaN(f)):[],C=l==="m"?"sgr":"csi";t.push({ts:e,type:C,raw:h,params:E.length>0?E:void 0,private:Q||void 0,final:l})}else if(n==="]"){s++;while(s<A.length&&A.charCodeAt(s)!==7&&!(A.charCodeAt(s)===z&&s+1<A.length&&A[s+1]==="\\"))s++;if(s<A.length){if(A.charCodeAt(s)===7)s++;else if(A.charCodeAt(s)===z)s+=2}let Q=A.slice(o,s);t.push({ts:e,type:"osc",raw:Q.slice(0,80)})}else if(n>=" "&&n<="~")s++,t.push({ts:e,type:"esc",raw:A.slice(o,s),final:n});else s++;i=s}return r(),t}var gA=500;class K{constructor(){this._traces=[],this._bridge=null,this._perf={frameCount:0,totalRenderMs:0,avgRenderMs:0,maxRenderMs:0,lastDirtyRows:0}}get traces(){return this._traces}get perf(){return this._perf}setBridge(A){this._bridge=A}traceWrite(A){let t=typeof A==="string"?A:new TextDecoder().decode(A),e=xA(t);for(let s of e)this._traces.push(s);if(this._traces.length>gA)this._traces=this._traces.slice(-gA)}recordRender(A,t){if(this._perf.frameCount++,this._perf.totalRenderMs+=A,this._perf.avgRenderMs=this._perf.totalRenderMs/this._perf.frameCount,A>this._perf.maxRenderMs)this._perf.maxRenderMs=A;this._perf.lastDirtyRows=t}resetPerf(){this._perf={frameCount:0,totalRenderMs:0,avgRenderMs:0,maxRenderMs:0,lastDirtyRows:0}}cell(A,t){if(!this._bridge)return null;let e=this._bridge.getCell(A,t);return{...e,charStr:e.chars??(e.char>=32?String.fromCodePoint(e.char):""),flagNames:bA(e.flags)}}row(A){if(!this._bridge)return null;let t=this._bridge.getCols(),e=[];for(let s=0;s<t;s++)e.push(this.cell(A,s));return e}grid(){if(!this._bridge)return null;let A=this._bridge.getCursor();return{rows:this._bridge.getRows(),cols:this._bridge.getCols(),cursor:A,altScreen:this._bridge.usingAltScreen(),scrollbackCount:this._bridge.getScrollbackCount()}}unhandled(){if(!this._bridge)return[];return this._bridge.getUnhandledSequences()}dump(A=50){let t=this._traces.slice(-A);console.group(`%cwterm debug — last ${t.length} traces`,"color: #569cd6; font-weight: bold");for(let e of t){let s=e.type==="sgr"?"%cSGR":e.type==="csi"?"%cCSI":e.type==="osc"?"%cOSC":e.type==="esc"?"%cESC":"%cTXT",i=e.type==="sgr"?"background:#2d5a27;color:#fff;padding:1px 4px;border-radius:2px":e.type==="csi"?"background:#1e4a7a;color:#fff;padding:1px 4px;border-radius:2px":"background:#555;color:#fff;padding:1px 4px;border-radius:2px",r=[e.private?`private=${e.private}`:"",e.params?`params=[${e.params}]`:"",e.final?`final=${e.final}`:""].filter(Boolean).join(" ");console.log(`${s} ${e.raw.slice(0,40)}`,i,r?` ${r}`:"")}console.groupEnd()}dumpUnhandled(){let A=this.unhandled();if(A.length===0){console.log("%cwterm debug — no unhandled sequences","color: #6a9955");return}console.group(`%cwterm debug — ${A.length} unhandled sequences`,"color: #d7ba7d; font-weight: bold");for(let t of A)console.log(` final=${t.final} private=${t.private||"-"} params=[${t.params.slice(0,t.paramCount)}]`);console.groupEnd()}}var _A=1000;class T{constructor(A,t={}){if(this.bridge=null,this.debug=null,this.renderer=null,this.input=null,this.rafId=null,this._synchronizedOutputTimer=null,this._synchronizedOutputState="idle",this._synchronizedOutputGeneration=0,this._rendererNeedsSetup=!1,this.resizeObserver=null,this._destroyed=!1,this._shouldScrollToBottom=!1,this._scrollbackDiscardedCount=0,this._programmaticScrollTop=null,this._pendingResizeScrollTop=null,this._rowHeight=0,this._charWidth=0,this.element=A,this._coreOption=t.core,this.wasmUrl=t.wasmUrl,this.cols=t.cols||80,this.rows=t.rows||24,this.autoResize=t.autoResize!==!1,this._debugEnabled=t.debug??!1,this.onData=t.onData||null,this.onTitle=t.onTitle||null,this.onResize=t.onResize||null,this._container=document.createElement("div"),this._container.className="term-grid",this.element.appendChild(this._container),this.element.classList.add("wterm"),t.cursorBlink)this.element.classList.add("cursor-blink");this._onClickFocus=(e)=>{let s=e.target;if(s instanceof Element&&s.closest(".term-link")){if(G(e,this.element.ownerDocument.defaultView?.navigator??navigator)||e.detail===0)return;e.preventDefault()}let i=window.getSelection();if(!i||i.isCollapsed)this.input?.focus()},this.element.addEventListener("click",this._onClickFocus),this._onModifierChange=(e)=>{this.element.classList.toggle("link-modifier-active",G(e,this.element.ownerDocument.defaultView?.navigator??navigator))},this._onWindowBlur=()=>{this.element.classList.remove("link-modifier-active")},this.element.ownerDocument.addEventListener("keydown",this._onModifierChange),this.element.ownerDocument.addEventListener("keyup",this._onModifierChange),this.element.ownerDocument.defaultView?.addEventListener("blur",this._onWindowBlur),this._onScroll=()=>{if(this._pendingResizeScrollTop!==null)return;if(this._programmaticScrollTop!==null&&this.element.scrollTop===this._programmaticScrollTop){this._programmaticScrollTop=null;return}this._programmaticScrollTop=null,this._shouldScrollToBottom=!1,this._scheduleRender()},this.element.addEventListener("scroll",this._onScroll,{passive:!0})}async init(){try{if(this._coreOption)this.bridge=this._coreOption;else this.bridge=await L.load(this.wasmUrl);if(this._destroyed)return this;if(this.bridge.init(this.cols,this.rows),this._debugEnabled)this.debug=new K,this.debug.setBridge(this.bridge),globalThis.__wterm=this;if(this._setRowHeight(),this._measureCharSize(),this.renderer=new Y(this._container),this.renderer.setup(this.cols,this.rows),this.input=new N(this.element,(A)=>{if(this._scrollToBottom(),this.onData)this.onData(A);else this.write(A)},()=>this.bridge,()=>this._charWidth>0&&this._rowHeight>0?{charWidth:this._charWidth,rowHeight:this._rowHeight}:null),this.autoResize)this._setupResizeObserver();else this._lockHeight();this.input.focus(),this._initialRender()}catch(A){throw this.destroy(),Error(`wterm: failed to initialize: ${A instanceof Error?A.message:A}`)}return this}_isScrolledToBottom(){let A=this.element;return A.scrollHeight-A.scrollTop-A.clientHeight<5}_scrollToBottom(){let A=this.element,t=A.scrollHeight-A.clientHeight;if(t<=0){this._setScrollTop(0);return}this._setScrollTop(t)}_setScrollTop(A){if(this.element.scrollTop===A)return;this._programmaticScrollTop=A,this.element.scrollTop=A}write(A){if(!this.bridge)return;if(this.debug)this.debug.traceWrite(A);this._shouldScrollToBottom=this._isScrolledToBottom();let t,e=!1,s=()=>{let o=this._drainResponses();if(!e&&o.hasError)e=!0,t=o.error};if(typeof A==="string")this.bridge.writeString(A,s);else this.bridge.writeRaw(A,s);let i=this.bridge.synchronizedOutput?.()??!1,r=this.bridge.synchronizedOutputGeneration?.()??0;if(this._updateSynchronizedOutput(i,r),this._synchronizedOutputState!=="held")this._setupRendererIfNeeded(),this._scheduleRender();if(s(),e)throw t}resize(A,t){if(!this.bridge)return;this._shouldScrollToBottom=this._pendingResizeScrollTop===null&&this._isScrolledToBottom(),this.cols=A,this.rows=t,this.bridge.resize(A,t);let e=this.bridge.synchronizedOutput?.()??!1,s=this.bridge.synchronizedOutputGeneration?.()??0;if(this._updateSynchronizedOutput(e,s))this._rendererNeedsSetup=!0;else this._setupRenderer(A,t),this._scheduleRender();if(this.onResize)this.onResize(A,t)}focus(){if(this.input)this.input.focus();else this.element.focus()}_scheduleRender(){if(this.rafId!=null)return;this.rafId=requestAnimationFrame(()=>{this.rafId=null,this._doRender()})}_cancelScheduledRender(){if(this.rafId!=null)cancelAnimationFrame(this.rafId),this.rafId=null}_updateSynchronizedOutput(A,t){if(!A){if(this._synchronizedOutputState==="held")this._cancelSynchronizedOutputFallback();return this._synchronizedOutputState="idle",!1}if(this._synchronizedOutputState==="held"&&t!==this._synchronizedOutputGeneration)return this._armSynchronizedOutputFallback(t),!0;else if(this._synchronizedOutputState==="passthrough"&&t!==this._synchronizedOutputGeneration)this._synchronizedOutputState="idle";if(this._synchronizedOutputState!=="idle")return this._synchronizedOutputState==="held";return this._synchronizedOutputState="held",this._cancelScheduledRender(),this._armSynchronizedOutputFallback(t),!0}_armSynchronizedOutputFallback(A){this._cancelSynchronizedOutputFallback(),this._synchronizedOutputGeneration=A,this._synchronizedOutputTimer=setTimeout(()=>{if(this._synchronizedOutputState!=="held"||this._synchronizedOutputGeneration!==A)return;this._synchronizedOutputTimer=null,this._synchronizedOutputState="passthrough",this._setupRendererIfNeeded(),this._cancelScheduledRender(),this._doRender()},_A)}_cancelSynchronizedOutputFallback(){if(this._synchronizedOutputTimer==null)return;clearTimeout(this._synchronizedOutputTimer),this._synchronizedOutputTimer=null}_setupRendererIfNeeded(){if(!this._rendererNeedsSetup)return;this._setupRenderer(this.cols,this.rows),this._rendererNeedsSetup=!1}_setupRenderer(A,t){if(!this._shouldScrollToBottom&&this._pendingResizeScrollTop===null)this._pendingResizeScrollTop=this.element.scrollTop;this.renderer?.setup(A,t)}_initialRender(){this._doRender()}_doRender(){if(!this.bridge||!this.renderer)return;let A=0,t=this.debug?performance.now():0;if(this.debug){for(let B=0;B<this.rows;B++)if(this.bridge.isDirtyRow(B))A++}let e=this._rowHeight||17,s=this.bridge.getScrollbackCount(),i=this.bridge.getScrollbackDiscardedCount?.(),r=i!==void 0&&i>=this._scrollbackDiscardedCount?i-this._scrollbackDiscardedCount:0;if(i!==void 0)this._scrollbackDiscardedCount=i;let o=this._pendingResizeScrollTop!==null?this._pendingResizeScrollTop:this.element.scrollTop;if(!this._shouldScrollToBottom&&r>0)if(o=Math.max(0,o-r*e),this._pendingResizeScrollTop!==null)this._pendingResizeScrollTop=o;else this._setScrollTop(o);if(this.renderer.render(this.bridge,{scrollTop:this._shouldScrollToBottom?Math.max(0,(s+this.rows)*e-this.element.clientHeight):o,clientHeight:this.element.clientHeight,rowHeight:e,scrollbackDiscardedCount:i}),this.debug)this.debug.recordRender(performance.now()-t,A);let n=s>0;if(this.element.classList.toggle("has-scrollback",n),this._shouldScrollToBottom)this._scrollToBottom();else if(this._pendingResizeScrollTop!==null){let B=this._pendingResizeScrollTop;this._pendingResizeScrollTop=null,this._setScrollTop(B)}else if(!n&&this.element.scrollTop!==0)this.element.scrollTop=0;let Q=this.bridge.getTitle();if(Q!==null&&this.onTitle)this.onTitle(Q);this._drainResponses()}_drainResponses(){if(!this.bridge)return{hasError:!1};let A,t,e=!1;while((A=this.bridge.getResponse())!==null)try{if(this.onData)this.onData(A)}catch(s){if(!e)e=!0,t=s}return{hasError:e,error:t}}_lockHeight(){let A=this._rowHeight||17,t=this.rows*A,e=getComputedStyle(this.element),s=(parseFloat(e.paddingTop)||0)+(parseFloat(e.paddingBottom)||0);if(e.boxSizing==="border-box")s+=(parseFloat(e.borderTopWidth)||0)+(parseFloat(e.borderBottomWidth)||0);this.element.style.height=`${t+s}px`}_setRowHeight(){let A=document.createElement("div");A.className="term-row",A.style.visibility="hidden",A.style.position="absolute",A.textContent="W",this._container.appendChild(A);let t=A.getBoundingClientRect().height;if(A.remove(),t>0){let e=Math.ceil(t);this._rowHeight=e,this.element.style.setProperty("--term-row-height",`${e}px`)}}_measureCharSize(){let A=document.createElement("div");A.className="term-row",A.style.visibility="hidden",A.style.position="absolute";let t=document.createElement("span");t.textContent="W",A.appendChild(t),this._container.appendChild(A);let e=t.getBoundingClientRect().width,s=A.getBoundingClientRect().height;if(A.remove(),e===0||s===0)return null;return this._charWidth=e,this._rowHeight=s,{charWidth:e,rowHeight:s}}_setupResizeObserver(){let A=this._measureCharSize();if(!A)return;let{charWidth:t,rowHeight:e}=A;this.resizeObserver=new ResizeObserver((s)=>{let i=this._measureCharSize();if(i)t=i.charWidth,e=i.rowHeight;for(let r of s){let{width:o,height:n}=r.contentRect,Q=Math.max(1,Math.floor(o/t)),B=Math.max(1,Math.floor(n/e));if(Q!==this.cols||B!==this.rows)this.resize(Q,B)}}),this.resizeObserver.observe(this.element)}destroy(){if(this._destroyed=!0,this._cancelScheduledRender(),this._cancelSynchronizedOutputFallback(),this.resizeObserver)this.resizeObserver.disconnect();if(this.input)this.input.destroy();if(this.element.removeEventListener("click",this._onClickFocus),this.element.removeEventListener("scroll",this._onScroll),this.element.ownerDocument.removeEventListener("keydown",this._onModifierChange),this.element.ownerDocument.removeEventListener("keyup",this._onModifierChange),this.element.ownerDocument.defaultView?.removeEventListener("blur",this._onWindowBlur),this.element.classList.remove("link-modifier-active"),this.element.innerHTML="",this.debug&&globalThis.__wterm===this)delete globalThis.__wterm;this.debug=null}}var k=16,W='Serve the binary from your app and pass its URL: GhosttyCore.load({ wasmPath: "/ghostty-vt.wasm" }). The file ships with the package as @wterm/ghostty/ghostty-vt.wasm. See the Bundlers section of the @wterm/ghostty README.';function SA(){return new URL("../wasm/ghostty-vt.wasm",import.meta.url).href}function DA(A){if(A.byteLength<4)return!1;let t=new Uint8Array(A,0,4);return t[0]===0&&t[1]===97&&t[2]===115&&t[3]===109}async function QA(A){let t=A??SA();if(A===void 0&&t.startsWith("file:")&&typeof document<"u")throw Error(`@wterm/ghostty: your bundler resolved the WASM URL to ${t}, a path on the machine that built the bundle, so the browser cannot fetch it. ${W}`);let e=await fetch(t);if(!e.ok)throw Error(`@wterm/ghostty: fetching ${t} returned ${e.status} ${e.statusText}. ${W}`);let s=await e.arrayBuffer();if(!DA(s))throw Error(`@wterm/ghostty: ${t} did not return a WASM module. ${W}`);let i,{instance:r}=await WebAssembly.instantiate(s,{env:{log(n,Q){let B=new TextDecoder().decode(new Uint8Array(i.buffer,n,Q));console.log("[ghostty-vt]",B)}}});return i=r.exports.memory,{exports:r.exports,instance:r}}function V(A,t){return{codepoint:A.getUint32(t,!0),fgR:A.getUint8(t+4),fgG:A.getUint8(t+5),fgB:A.getUint8(t+6),bgR:A.getUint8(t+7),bgG:A.getUint8(t+8),bgB:A.getUint8(t+9),flags:A.getUint8(t+10),width:A.getUint8(t+11),colorFlags:A.getUint8(t+12),hasGrapheme:(A.getUint8(t+13)&1)!==0,hasHyperlink:(A.getUint8(t+13)&2)!==0}}function D(A,t){return A.exports.alloc_buffer(t)}function y(A,t,e){A.exports.free_buffer(t,e)}function hA(A,t,e){let s=new TextEncoder().encode(e);Z(A,t,s)}function Z(A,t,e){if(e.length===0)return;let s=D(A,e.length);if(s===0)return;new Uint8Array(A.exports.memory.buffer,s,e.length).set(e),A.exports.write(t,s,e.length),y(A,s,e.length)}var R=256,aA=256,X=1024,yA="#d4d4d4",LA="#1e1e1e";function O(A,t,e){return A<<16|t<<8|e}var P={char:32,fg:R,bg:R,flags:0,width:1};function cA(A,t){if(!/^#[0-9a-f]{6}$/i.test(A))throw Error(`@wterm/ghostty: ${t} must be a #RRGGBB color`);return Number.parseInt(A.slice(1),16)}class H{constructor(A,t){this.termPtr=0,this._viewportBufPtr=0,this._viewportBufSize=0,this._viewportView=null,this._viewportStale=!0,this._cols=0,this._rows=0,this._scrollbackBufPtr=0,this._scrollbackBufSize=0,this._scrollbackView=null,this._scrollbackOffset=-1,this._scrollbackLen=0,this._graphemeBufPtr=0,this._graphemeBufSize=aA,this._hyperlinkBufPtr=0,this._hyperlinkBufSize=X,this.wasm=A,this._options=t,this._foregroundRgb=cA(t.foregroundColor??yA,"foregroundColor"),this._backgroundRgb=cA(t.backgroundColor??LA,"backgroundColor")}static async load(A={}){let t=await QA(A.wasmPath);return new H(t,A)}init(A,t){this._cols=A,this._rows=t;let e=this._options.scrollbackLimit??1e4;if(this.termPtr=this.wasm.exports.init(A,t,e,this._foregroundRgb,this._backgroundRgb),this._graphemeBufPtr=D(this.wasm,aA),this._hyperlinkBufPtr!==0)y(this.wasm,this._hyperlinkBufPtr,this._hyperlinkBufSize);this._hyperlinkBufSize=X,this._hyperlinkBufPtr=D(this.wasm,X),this._allocViewportBuffer(),this._invalidate()}resize(A,t){this._cols=A,this._rows=t,this.wasm.exports.resize(this.termPtr,A,t),this._allocViewportBuffer(),this._invalidate()}writeString(A){hA(this.wasm,this.termPtr,A),this._invalidate()}writeRaw(A){Z(this.wasm,this.termPtr,A),this._invalidate()}getCell(A,t){this._ensureViewport();let e=this._viewportView;if(!e)return P;let i=(A*this._cols+t)*k;if(i+k>this._viewportBufSize)return P;let r=V(e,i);if(r.codepoint===0&&r.flags===0&&r.colorFlags===0&&!r.hasHyperlink&&r.width!==0)return P;let o={char:r.codepoint||32,fg:R,bg:R,flags:r.flags,width:r.width};if(r.hasGrapheme)o.chars=this._readGrapheme(A,t);if(r.hasHyperlink)Object.assign(o,this._readHyperlink(A,t,!1));if(r.colorFlags&1)o.fgRgb=O(r.fgR,r.fgG,r.fgB);if(r.colorFlags&2)o.bgRgb=O(r.bgR,r.bgG,r.bgB);return o}isDirtyRow(A){return this._ensureViewport(),this.wasm.exports.is_dirty_row(this.termPtr,A)!==0}clearDirty(){this.wasm.exports.clear_dirty(this.termPtr),this._viewportStale=!0}getCols(){return this._cols}getRows(){return this._rows}getCursor(){return this._ensureViewport(),{row:this.wasm.exports.get_cursor_row(this.termPtr),col:this.wasm.exports.get_cursor_col(this.termPtr),visible:this.wasm.exports.get_cursor_visible(this.termPtr)!==0}}cursorKeysApp(){return this.wasm.exports.cursor_keys_app(this.termPtr)!==0}bracketedPaste(){return this.wasm.exports.bracketed_paste(this.termPtr)!==0}usingAltScreen(){return this.wasm.exports.using_alt_screen(this.termPtr)!==0}mouseTracking(){let A=this.wasm.exports.mouse_tracking(this.termPtr);return A===1000||A===1002?A:0}mouseSgr(){return this.wasm.exports.mouse_sgr(this.termPtr)!==0}focusEvents(){return this.wasm.exports.focus_events(this.termPtr)!==0}synchronizedOutput(){return this.wasm.exports.synchronized_output(this.termPtr)!==0}synchronizedOutputGeneration(){return this.wasm.exports.synchronized_output_generation(this.termPtr)}getTitle(){return null}getResponse(){let t=D(this.wasm,4096);if(t===0)return null;let e=this.wasm.exports.read_response(this.termPtr,t,4096);if(e===0)return y(this.wasm,t,4096),null;let s=new Uint8Array(this.wasm.exports.memory.buffer,t,e),i=new TextDecoder().decode(s);return y(this.wasm,t,4096),i}getScrollbackCount(){return this.wasm.exports.get_scrollback_count(this.termPtr)}getScrollbackDiscardedCount(){return this.wasm.exports.get_scrollback_discarded_count(this.termPtr)}getScrollbackCell(A,t){let e=this._ensureScrollbackLine(A),s=this._scrollbackView;if(!s||t>=e)return P;let i=V(s,t*k),r={char:i.codepoint||32,fg:R,bg:R,flags:i.flags,width:i.width};if(i.hasGrapheme)r.chars=this._readScrollbackGrapheme(A,t);if(i.hasHyperlink)Object.assign(r,this._readHyperlink(A,t,!0));if(i.colorFlags&1)r.fgRgb=O(i.fgR,i.fgG,i.fgB);if(i.colorFlags&2)r.bgRgb=O(i.bgR,i.bgG,i.bgB);return r}getScrollbackLineLen(A){return this._ensureScrollbackLine(A)}getUnhandledSequences(){return[]}_invalidate(){this._viewportStale=!0,this._scrollbackOffset=-1}_decodeGrapheme(A){if(A===0||this._graphemeBufPtr===0)return;return new TextDecoder().decode(new Uint8Array(this.wasm.exports.memory.buffer,this._graphemeBufPtr,A))}_ensureGraphemeBuffer(A){if(A<=this._graphemeBufSize)return;if(this._graphemeBufPtr!==0)y(this.wasm,this._graphemeBufPtr,this._graphemeBufSize);this._graphemeBufSize=A,this._graphemeBufPtr=D(this.wasm,A)}_ensureHyperlinkBuffer(A){if(A<=this._hyperlinkBufSize)return;if(this._hyperlinkBufPtr!==0)y(this.wasm,this._hyperlinkBufPtr,this._hyperlinkBufSize);this._hyperlinkBufSize=A,this._hyperlinkBufPtr=D(this.wasm,A)}_readHyperlink(A,t,e){if(this._hyperlinkBufPtr===0)return;let s=e?this.wasm.exports.get_scrollback_hyperlink:this.wasm.exports.get_viewport_hyperlink,i=s(this.termPtr,A,t,this._hyperlinkBufPtr,this._hyperlinkBufSize);if(i>this._hyperlinkBufSize){if(this._ensureHyperlinkBuffer(i),this._hyperlinkBufPtr===0)return;i=s(this.termPtr,A,t,this._hyperlinkBufPtr,this._hyperlinkBufSize)}if(i===0||i>this._hyperlinkBufSize)return;let r=new TextDecoder().decode(new Uint8Array(this.wasm.exports.memory.buffer,this._hyperlinkBufPtr,i)),[o,n="",Q=""]=r.split("\x00");if(!o)return;let B=n?`e\x00${n}\x00${o}`:`g\x00${Q}\x00${o}`;return{linkUri:o,linkId:n||void 0,linkKey:B}}_readGrapheme(A,t){if(this._graphemeBufPtr===0||!this.wasm.exports.get_viewport_grapheme)return;let e=this.wasm.exports.get_viewport_grapheme(this.termPtr,A,t,this._graphemeBufPtr,this._graphemeBufSize);if(e>this._graphemeBufSize)this._ensureGraphemeBuffer(e),e=this.wasm.exports.get_viewport_grapheme(this.termPtr,A,t,this._graphemeBufPtr,this._graphemeBufSize);return this._decodeGrapheme(e)}_readScrollbackGrapheme(A,t){if(this._graphemeBufPtr===0||!this.wasm.exports.get_scrollback_grapheme)return;let e=this.wasm.exports.get_scrollback_grapheme(this.termPtr,A,t,this._graphemeBufPtr,this._graphemeBufSize);if(e>this._graphemeBufSize)this._ensureGraphemeBuffer(e),e=this.wasm.exports.get_scrollback_grapheme(this.termPtr,A,t,this._graphemeBufPtr,this._graphemeBufSize);return this._decodeGrapheme(e)}_allocViewportBuffer(){if(this._viewportBufPtr!==0)y(this.wasm,this._viewportBufPtr,this._viewportBufSize);if(this._viewportBufSize=this._cols*this._rows*k,this._viewportBufPtr=D(this.wasm,this._viewportBufSize),this._viewportView=null,this._viewportStale=!0,this._scrollbackBufPtr!==0)y(this.wasm,this._scrollbackBufPtr,this._scrollbackBufSize);this._scrollbackBufSize=this._cols*k,this._scrollbackBufPtr=D(this.wasm,this._scrollbackBufSize),this._scrollbackView=null,this._scrollbackOffset=-1}_ensureScrollbackLine(A){if(this._scrollbackBufPtr===0)return 0;if(this._scrollbackOffset!==A)this._scrollbackLen=this.wasm.exports.get_scrollback_line(this.termPtr,A,this._scrollbackBufPtr,this._cols),this._scrollbackOffset=A;if(this._scrollbackView?.buffer!==this.wasm.exports.memory.buffer)this._scrollbackView=new DataView(this.wasm.exports.memory.buffer,this._scrollbackBufPtr,this._scrollbackBufSize);return this._scrollbackLen}_ensureViewport(){if(this._viewportStale)this.wasm.exports.update(this.termPtr),this.wasm.exports.get_viewport(this.termPtr,this._viewportBufPtr),this._viewportStale=!1;if(this._viewportView?.buffer!==this.wasm.exports.memory.buffer)this._viewportView=new DataView(this.wasm.exports.memory.buffer,this._viewportBufPtr,this._viewportBufSize)}}var F=null,q=()=>new Promise((A)=>requestAnimationFrame(()=>requestAnimationFrame(()=>A(!0)))),kA={async boot(A){let t=A.core==="lite"?await L.load():await H.load({wasmPath:A.wasmUrl,foregroundColor:A.foreground,backgroundColor:A.background}),e=document.getElementById("term");if(F=new T(e,{cols:A.cols,rows:A.rows,core:t,autoResize:!1,cursorBlink:!1,onData:()=>{}}),await F.init(),e.classList.add("focused"),document.fonts?.ready)await document.fonts.ready;return await q(),!0},measure(){let A=F;if(A&&A._charWidth&&A._rowHeight&&A._charWidth>0&&A._rowHeight>0)return{w:A._charWidth,h:A._rowHeight};let t=document.createElement("div");t.className="term-row",t.style.cssText="position:absolute;visibility:hidden";let e=document.createElement("span");e.textContent="W",t.appendChild(e),document.querySelector(".term-grid").appendChild(t);let s=e.getBoundingClientRect().width,i=t.getBoundingClientRect().height;return t.remove(),{w:s,h:i}},layout(A,t,e,s,i,r){let o=document.getElementById("frame");if(o.style.width=`${A}px`,o.style.height=`${t}px`,i!==void 0&&r!==void 0)o.style.padding=`${r}px ${i}px`;let n=document.getElementById("browser"),Q=document.getElementById("stage"),B=Q?/column/.test(getComputedStyle(Q).flexDirection):!1,l=getComputedStyle(o).position==="absolute";if(n&&!l)if(B)n.style.width=`${A}px`;else n.style.height=`${t}px`;let h=document.getElementById("term");return h.style.width=`${e}px`,h.style.height=`${s}px`,!0},browserOffset(A,t,e,s){let i=document.getElementById("browser");if(!i)return!1;return i.style.left=`${A}px`,i.style.top=`${t}px`,i.style.width=`${e}px`,i.style.height=`${s}px`,!0},focus(A){return document.getElementById("stage")?.classList.toggle("front-browser",A==="browser"),!0},browserFrame(A,t){let e=document.getElementById("bframe");if(!e)return Promise.resolve(!1);if(t!==void 0){let s=document.getElementById("browser-url");if(s)s.textContent=t}return new Promise((s)=>{e.onload=()=>q().then(()=>s(!0)),e.onerror=()=>s(!1),e.src=A})},async applyUrl(A){let t=await(await fetch(A)).json();for(let e of t)if(e.type==="o")F.write(e.data);else if(e.type==="r"){let[s,i]=e.data.split("x").map(Number);if(s>0&&i>0)F.resize(s,i)}return await q(),!0},async writeUrl(A){return F.write(await(await fetch(A)).text()),await q(),!0},cursor(A){return document.getElementById("blink").textContent=A?"":".wterm.focused .term-cursor{background:transparent!important;color:inherit!important;outline:none!important}",!0}};window.__vt=kA;
|
|
@@ -72,12 +72,52 @@ const api = {
|
|
|
72
72
|
frame.style.width = `${frameW}px`;
|
|
73
73
|
frame.style.height = `${frameH}px`;
|
|
74
74
|
if (padX !== undefined && padY !== undefined) frame.style.padding = `${padY}px ${padX}px`;
|
|
75
|
+
const browser = document.getElementById("browser");
|
|
76
|
+
const stage = document.getElementById("stage");
|
|
77
|
+
const stacked = stage ? /column/.test(getComputedStyle(stage).flexDirection) : false;
|
|
78
|
+
const overlay = getComputedStyle(frame).position === "absolute"; // overlay: size comes from browserOffset()
|
|
79
|
+
if (browser && !overlay) {
|
|
80
|
+
if (stacked) browser.style.width = `${frameW}px`;
|
|
81
|
+
else browser.style.height = `${frameH}px`;
|
|
82
|
+
}
|
|
75
83
|
const el = document.getElementById("term")!;
|
|
76
84
|
el.style.width = `${termW}px`;
|
|
77
85
|
el.style.height = `${termH}px`;
|
|
78
86
|
return true;
|
|
79
87
|
},
|
|
80
88
|
|
|
89
|
+
/** Overlay layout: place the browser window at an offset from the terminal window. */
|
|
90
|
+
browserOffset(x: number, y: number, w: number, h: number): boolean {
|
|
91
|
+
const browser = document.getElementById("browser");
|
|
92
|
+
if (!browser) return false;
|
|
93
|
+
browser.style.left = `${x}px`;
|
|
94
|
+
browser.style.top = `${y}px`;
|
|
95
|
+
browser.style.width = `${w}px`;
|
|
96
|
+
browser.style.height = `${h}px`;
|
|
97
|
+
return true;
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
/** Overlay layout: which window is in front. */
|
|
101
|
+
focus(target: "terminal" | "browser"): boolean {
|
|
102
|
+
document.getElementById("stage")?.classList.toggle("front-browser", target === "browser");
|
|
103
|
+
return true;
|
|
104
|
+
},
|
|
105
|
+
|
|
106
|
+
/** Show a captured browser frame (served by the renderer) and wait until it has loaded and painted. */
|
|
107
|
+
browserFrame(url: string, label?: string): Promise<boolean> {
|
|
108
|
+
const img = document.getElementById("bframe") as HTMLImageElement | null;
|
|
109
|
+
if (!img) return Promise.resolve(false);
|
|
110
|
+
if (label !== undefined) {
|
|
111
|
+
const bar = document.getElementById("browser-url");
|
|
112
|
+
if (bar) bar.textContent = label;
|
|
113
|
+
}
|
|
114
|
+
return new Promise((resolve) => {
|
|
115
|
+
img.onload = () => paint().then(() => resolve(true));
|
|
116
|
+
img.onerror = () => resolve(false);
|
|
117
|
+
img.src = url;
|
|
118
|
+
});
|
|
119
|
+
},
|
|
120
|
+
|
|
81
121
|
/** Fetch a JSON array of events from `url` and apply them, then wait for a paint. */
|
|
82
122
|
async applyUrl(url: string): Promise<boolean> {
|
|
83
123
|
const events = (await (await fetch(url)).json()) as BatchEvent[];
|
package/src/renderer/page.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type { ResolvedConfig, Theme } from "../types";
|
|
2
2
|
|
|
3
3
|
const BAR_HEIGHT = 36;
|
|
4
|
+
/** Gap between the terminal window and the browser window. */
|
|
5
|
+
export const BROWSER_GAP = 16;
|
|
6
|
+
/** Height of the browser window's chrome bar. */
|
|
7
|
+
export const BROWSER_BAR = 34;
|
|
4
8
|
|
|
5
9
|
export function barHeight(config: ResolvedConfig): number {
|
|
6
10
|
return config.windowBar === "none" ? 0 : BAR_HEIGHT;
|
|
@@ -69,9 +73,45 @@ export function renderHtml(config: ResolvedConfig): string {
|
|
|
69
73
|
<link rel="stylesheet" href="/wterm.css">
|
|
70
74
|
<style>
|
|
71
75
|
html, body { margin: 0; padding: 0; background: ${config.marginFill}; overflow: hidden; }
|
|
72
|
-
#
|
|
76
|
+
#stage {
|
|
73
77
|
position: absolute;
|
|
74
78
|
left: ${config.margin}px; top: ${config.margin}px;
|
|
79
|
+
display: flex; align-items: stretch; gap: ${BROWSER_GAP}px;
|
|
80
|
+
flex-direction: ${{ right: "row", left: "row-reverse", bottom: "column", top: "column-reverse", overlay: "row" }[config.browser?.position ?? "right"]};
|
|
81
|
+
}
|
|
82
|
+
${
|
|
83
|
+
config.browser?.position === "overlay"
|
|
84
|
+
? `#stage { display: block; }
|
|
85
|
+
#stage #frame { position: absolute; left: 0; top: 0; z-index: 2; box-shadow: 0 18px 50px rgba(0,0,0,0.45); }
|
|
86
|
+
#stage #browser { position: absolute; z-index: 1; box-shadow: 0 18px 50px rgba(0,0,0,0.45); }
|
|
87
|
+
#stage.front-browser #browser { z-index: 3; }
|
|
88
|
+
#stage.front-browser #frame { z-index: 1; }`
|
|
89
|
+
: ""
|
|
90
|
+
}
|
|
91
|
+
#browser {
|
|
92
|
+
width: ${config.browser && (config.browser.position === "top" || config.browser.position === "bottom") ? "auto" : `${config.browser?.width ?? 0}px`};
|
|
93
|
+
height: ${config.browser && (config.browser.position === "top" || config.browser.position === "bottom") ? `${config.browser.height || 480}px` : "auto"};
|
|
94
|
+
flex: none;
|
|
95
|
+
background: #ffffff;
|
|
96
|
+
border-radius: ${config.borderRadius}px;
|
|
97
|
+
overflow: hidden;
|
|
98
|
+
display: ${config.browser ? "flex" : "none"};
|
|
99
|
+
flex-direction: column;
|
|
100
|
+
box-sizing: border-box;
|
|
101
|
+
}
|
|
102
|
+
#browser-bar {
|
|
103
|
+
height: ${BROWSER_BAR}px; flex: none;
|
|
104
|
+
display: flex; align-items: center; gap: 8px; padding: 0 12px;
|
|
105
|
+
background: #e9e9ec; color: #444; font: 12px -apple-system, "Segoe UI", Helvetica, Arial, sans-serif;
|
|
106
|
+
}
|
|
107
|
+
#browser-bar .bdot { width: 11px; height: 11px; border-radius: 50%; display: inline-block; }
|
|
108
|
+
#browser-url {
|
|
109
|
+
flex: 1; margin-left: 8px; background: #fff; border-radius: 6px; padding: 3px 10px;
|
|
110
|
+
white-space: nowrap; overflow: hidden; text-overflow: ellipsis; text-align: center; color: #333;
|
|
111
|
+
}
|
|
112
|
+
#bframe { display: block; width: 100%; flex: 1; object-fit: cover; object-position: top; background: #fff; }
|
|
113
|
+
#frame {
|
|
114
|
+
position: relative;
|
|
75
115
|
background: ${theme.background};
|
|
76
116
|
border-radius: ${config.borderRadius}px;
|
|
77
117
|
padding: ${config.padding}px;
|
|
@@ -104,10 +144,23 @@ export function renderHtml(config: ResolvedConfig): string {
|
|
|
104
144
|
<style id="blink"></style>
|
|
105
145
|
</head>
|
|
106
146
|
<body>
|
|
147
|
+
<div id="stage">
|
|
107
148
|
<div id="frame">
|
|
108
149
|
${windowBarHtml(config)}
|
|
109
150
|
<div id="term"></div>
|
|
110
151
|
</div>
|
|
152
|
+
${
|
|
153
|
+
config.browser
|
|
154
|
+
? `<div id="browser">
|
|
155
|
+
<div id="browser-bar">
|
|
156
|
+
<span class="bdot" style="background:#ff5f57"></span><span class="bdot" style="background:#febc2e"></span><span class="bdot" style="background:#28c840"></span>
|
|
157
|
+
<span id="browser-url">${escapeHtml(config.browser.title ?? config.browser.url ?? "")}</span>
|
|
158
|
+
</div>
|
|
159
|
+
<img id="bframe" alt="" />
|
|
160
|
+
</div>`
|
|
161
|
+
: ""
|
|
162
|
+
}
|
|
163
|
+
</div>
|
|
111
164
|
<script type="module" src="/app.js"></script>
|
|
112
165
|
</body>
|
|
113
166
|
</html>`;
|
package/src/renderer/webview.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { fitFrame, loopOffsetFrames, rotateFrames } from "../loop";
|
|
|
6
6
|
import { buildTimeline, withReinjection, type TimedEvent } from "../timeline";
|
|
7
7
|
import { pageAssets } from "./bundle";
|
|
8
8
|
import { createSinks } from "./encoder";
|
|
9
|
-
import { barHeight, renderHtml, themeOsc } from "./page";
|
|
9
|
+
import { BROWSER_GAP, barHeight, renderHtml, themeOsc } from "./page";
|
|
10
10
|
|
|
11
11
|
export interface RenderResult {
|
|
12
12
|
outputs: string[];
|
|
@@ -27,6 +27,8 @@ export async function render(
|
|
|
27
27
|
const assets = await pageAssets();
|
|
28
28
|
const html = renderHtml(config);
|
|
29
29
|
const osc = themeOsc(config.theme);
|
|
30
|
+
const castDir = rec.source ? path.dirname(rec.source) : process.cwd();
|
|
31
|
+
const hasBrowser = Boolean(config.browser) && rec.events.some((e) => e[1] === "b");
|
|
30
32
|
const batches = new Map<number, string>();
|
|
31
33
|
let batchId = 0;
|
|
32
34
|
|
|
@@ -39,6 +41,11 @@ export async function render(
|
|
|
39
41
|
if (pathname === "/wterm.css") return new Response(assets.css, { headers: { "content-type": "text/css" } });
|
|
40
42
|
if (pathname === "/ghostty-vt.wasm") return new Response(Bun.file(assets.wasmPath), { headers: { "content-type": "application/wasm" } });
|
|
41
43
|
if (pathname === "/theme") return new Response(osc, { headers: { "content-type": "text/plain; charset=utf-8" } });
|
|
44
|
+
if (pathname.startsWith("/bframe/")) {
|
|
45
|
+
const rel = decodeURIComponent(pathname.slice("/bframe/".length));
|
|
46
|
+
if (rel.includes("..")) return new Response("forbidden", { status: 403 });
|
|
47
|
+
return new Response(Bun.file(path.join(castDir, rel)), { headers: { "content-type": "image/png" } });
|
|
48
|
+
}
|
|
42
49
|
if (pathname.startsWith("/batch/")) {
|
|
43
50
|
const id = Number(pathname.slice("/batch/".length));
|
|
44
51
|
const body = batches.get(id);
|
|
@@ -81,7 +88,7 @@ export async function render(
|
|
|
81
88
|
|
|
82
89
|
const termW = Math.ceil(rec.header.width * cell.w);
|
|
83
90
|
const termH = Math.ceil(rec.header.height * cell.h);
|
|
84
|
-
const
|
|
91
|
+
const fit = fitFrame({
|
|
85
92
|
termW,
|
|
86
93
|
termH,
|
|
87
94
|
padding: config.padding,
|
|
@@ -90,6 +97,29 @@ export async function render(
|
|
|
90
97
|
width: config.width,
|
|
91
98
|
height: config.height,
|
|
92
99
|
});
|
|
100
|
+
const { frameW, frameH, padX, padY } = fit;
|
|
101
|
+
// The browser pane extends the canvas sideways (left/right) or vertically (top/bottom).
|
|
102
|
+
const even = (n: number) => (n % 2 === 0 ? n : n + 1);
|
|
103
|
+
const position = config.browser?.position ?? "right";
|
|
104
|
+
const stacked = position === "top" || position === "bottom";
|
|
105
|
+
const overlay = position === "overlay";
|
|
106
|
+
let width = fit.width;
|
|
107
|
+
let height = fit.height;
|
|
108
|
+
if (hasBrowser && config.browser) {
|
|
109
|
+
if (overlay) {
|
|
110
|
+
const paneW = config.browser.width;
|
|
111
|
+
const paneH = config.browser.height || 480;
|
|
112
|
+
const ox = config.browser.offset?.x ?? Math.round(frameW * 0.42);
|
|
113
|
+
const oy = config.browser.offset?.y ?? Math.round(frameH * 0.18);
|
|
114
|
+
width = even(config.margin * 2 + Math.max(frameW, ox + paneW));
|
|
115
|
+
height = even(config.margin * 2 + Math.max(frameH, oy + paneH));
|
|
116
|
+
await view.evaluate(`window.__vt.browserOffset(${ox}, ${oy}, ${paneW}, ${paneH})`);
|
|
117
|
+
} else if (stacked) {
|
|
118
|
+
height = even(fit.height + BROWSER_GAP + (config.browser.height || 480));
|
|
119
|
+
} else {
|
|
120
|
+
width = even(fit.width + BROWSER_GAP + config.browser.width);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
93
123
|
await view.evaluate(`window.__vt.layout(${frameW}, ${frameH}, ${termW}, ${termH}, ${padX}, ${padY})`);
|
|
94
124
|
await view.resize(width, height);
|
|
95
125
|
await view.evaluate("new Promise(r => requestAnimationFrame(() => requestAnimationFrame(() => r(true))))");
|
|
@@ -114,13 +144,22 @@ export async function render(
|
|
|
114
144
|
const blinkOn = !config.cursor.blink || Math.floor((time / blinkPeriod) * 2) % 2 === 0;
|
|
115
145
|
const drawable = batch.filter((e) => e.type === "o" || e.type === "r");
|
|
116
146
|
const shots = batch.filter((e) => e.type === "m" && e.data.startsWith(MARKER.screenshot));
|
|
117
|
-
const
|
|
147
|
+
const browserFrame = hasBrowser ? batch.filter((e) => e.type === "b").at(-1) : undefined;
|
|
148
|
+
const focusChanged = hasBrowser && batch.some((e) => e.type === "m" && e.data.startsWith(MARKER.focus));
|
|
149
|
+
const dirty = lastPng === null || drawable.length > 0 || blinkOn !== lastBlink || browserFrame !== undefined || focusChanged;
|
|
118
150
|
|
|
119
151
|
if (drawable.length > 0) {
|
|
120
152
|
const id = ++batchId;
|
|
121
153
|
batches.set(id, JSON.stringify(drawable.map(({ type, data }) => ({ type, data }))));
|
|
122
154
|
await view.evaluate(`window.__vt.applyUrl('/batch/${id}')`);
|
|
123
155
|
}
|
|
156
|
+
if (browserFrame) {
|
|
157
|
+
await view.evaluate(`window.__vt.browserFrame(${JSON.stringify(`/bframe/${encodeURIComponent(browserFrame.data)}`)})`);
|
|
158
|
+
}
|
|
159
|
+
const focus = hasBrowser ? batch.filter((e) => e.type === "m" && e.data.startsWith(MARKER.focus)).at(-1) : undefined;
|
|
160
|
+
if (focus) {
|
|
161
|
+
await view.evaluate(`window.__vt.focus(${JSON.stringify(focus.data.slice(MARKER.focus.length))})`);
|
|
162
|
+
}
|
|
124
163
|
if (blinkOn !== lastBlink) {
|
|
125
164
|
await view.evaluate(`window.__vt.cursor(${blinkOn})`);
|
|
126
165
|
lastBlink = blinkOn;
|
package/src/screen.ts
CHANGED
|
@@ -114,6 +114,21 @@ export class Screen {
|
|
|
114
114
|
return this.rowText(this.core.getCursor().row);
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
+
/**
|
|
118
|
+
* The cursor line up to the cursor column. Prompt detection uses this rather than the whole line: after a
|
|
119
|
+
* full-screen program exits, the primary screen may still hold stale text to the right of the cursor.
|
|
120
|
+
*/
|
|
121
|
+
lineToCursor(): string {
|
|
122
|
+
const { row, col } = this.core.getCursor();
|
|
123
|
+
let text = "";
|
|
124
|
+
for (let x = 0; x < col; x++) {
|
|
125
|
+
const cell = this.core.getCell(row, x);
|
|
126
|
+
if (cell.width === 0) continue;
|
|
127
|
+
text += cell.chars ?? (cell.char === 0 ? " " : String.fromCodePoint(cell.char));
|
|
128
|
+
}
|
|
129
|
+
return text;
|
|
130
|
+
}
|
|
131
|
+
|
|
117
132
|
screen(): string {
|
|
118
133
|
const rows: string[] = [];
|
|
119
134
|
for (let y = 0; y < this.core.getRows(); y++) rows.push(this.rowText(y));
|
package/src/types.ts
CHANGED
|
@@ -48,6 +48,37 @@ export interface FontConfig {
|
|
|
48
48
|
letterSpacing?: number;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
/** A browser window recorded next to the terminal (Bun.WebView). */
|
|
52
|
+
export interface BrowserConfig {
|
|
53
|
+
/** Page to open when recording starts (may also be opened later with `t.browser.goto`). */
|
|
54
|
+
url?: string;
|
|
55
|
+
/** Pane size in px. Default 720 × the terminal frame height. */
|
|
56
|
+
width?: number;
|
|
57
|
+
height?: number;
|
|
58
|
+
/** How often the page is sampled while recording. Default 10. */
|
|
59
|
+
fps?: number;
|
|
60
|
+
/** Text shown in the browser window's address bar. Default: the current URL. */
|
|
61
|
+
title?: string;
|
|
62
|
+
/**
|
|
63
|
+
* Where the browser window sits: beside/above/below the terminal, or "overlay" — overlapping it like two desktop
|
|
64
|
+
* windows, with `t.focus()` deciding which one is in front. Default "right".
|
|
65
|
+
*/
|
|
66
|
+
position?: "right" | "left" | "top" | "bottom" | "overlay";
|
|
67
|
+
/** Overlay only: browser window offset from the terminal window's top-left corner, px. Default ~40%/18% of it. */
|
|
68
|
+
offset?: { x: number; y: number };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** Control of the recorded browser window. */
|
|
72
|
+
export interface BrowserSession {
|
|
73
|
+
goto(url: string): Promise<void>;
|
|
74
|
+
/** Wait until the page's visible text matches. */
|
|
75
|
+
waitFor(pattern: RegExp | string, opts?: { timeout?: Duration }): Promise<void>;
|
|
76
|
+
click(selector: string): Promise<void>;
|
|
77
|
+
reload(): Promise<void>;
|
|
78
|
+
evaluate(script: string): Promise<unknown>;
|
|
79
|
+
readonly url: string;
|
|
80
|
+
}
|
|
81
|
+
|
|
51
82
|
export interface CursorConfig {
|
|
52
83
|
/** Default true. Blink is driven by the render clock, so it is deterministic. */
|
|
53
84
|
blink?: boolean;
|
|
@@ -109,6 +140,8 @@ export interface VideoConfig {
|
|
|
109
140
|
font?: FontConfig;
|
|
110
141
|
theme?: ThemeName | Theme;
|
|
111
142
|
cursor?: CursorConfig;
|
|
143
|
+
/** Record a browser window beside the terminal. */
|
|
144
|
+
browser?: BrowserConfig;
|
|
112
145
|
/** Padding inside the window, px. Default 24. */
|
|
113
146
|
padding?: number;
|
|
114
147
|
/** Space around the window, px. Default 0. */
|
|
@@ -149,6 +182,7 @@ export interface ResolvedConfig {
|
|
|
149
182
|
font: Required<FontConfig>;
|
|
150
183
|
theme: Theme;
|
|
151
184
|
cursor: Required<CursorConfig>;
|
|
185
|
+
browser?: Required<Omit<BrowserConfig, "url" | "title" | "offset">> & Pick<BrowserConfig, "url" | "title" | "offset">;
|
|
152
186
|
padding: number;
|
|
153
187
|
margin: number;
|
|
154
188
|
marginFill: string;
|
|
@@ -244,6 +278,10 @@ export interface TerminalSession {
|
|
|
244
278
|
resize(cols: number, rows: number): Promise<void>;
|
|
245
279
|
/** Shorthand for `run("clear")`. */
|
|
246
280
|
clear(): Promise<void>;
|
|
281
|
+
/** The recorded browser window; throws if `browser` is not configured. */
|
|
282
|
+
readonly browser: BrowserSession;
|
|
283
|
+
/** Overlay layout: bring the terminal or the browser window to the front (recorded as a marker). */
|
|
284
|
+
focus(target: "terminal" | "browser"): Promise<void>;
|
|
247
285
|
|
|
248
286
|
/** Current visible screen as text (rows joined by "\n"). */
|
|
249
287
|
screen(): string;
|
|
@@ -257,7 +295,13 @@ export interface TerminalSession {
|
|
|
257
295
|
|
|
258
296
|
export type Script = (t: TerminalSession) => Promise<void> | void;
|
|
259
297
|
|
|
260
|
-
|
|
298
|
+
/** o = output, i = input, r = resize, m = marker, b = browser frame (path relative to the cast file). */
|
|
299
|
+
export type CastEventType = "o" | "i" | "r" | "m" | "b";
|
|
300
|
+
|
|
301
|
+
export interface BrowserFrame {
|
|
302
|
+
time: number;
|
|
303
|
+
png: Uint8Array;
|
|
304
|
+
}
|
|
261
305
|
export type CastEvent = [time: number, type: CastEventType, data: string];
|
|
262
306
|
|
|
263
307
|
export interface CastHeader {
|
|
@@ -276,6 +320,10 @@ export interface CastHeader {
|
|
|
276
320
|
export interface Recording {
|
|
277
321
|
header: CastHeader;
|
|
278
322
|
events: CastEvent[];
|
|
323
|
+
/** Absolute path of the cast file this recording was read from / written to; resolves `b` event paths. */
|
|
324
|
+
source?: string;
|
|
325
|
+
/** Browser frames captured during recording, before they are written beside the cast. */
|
|
326
|
+
browserFrames?: BrowserFrame[];
|
|
279
327
|
}
|
|
280
328
|
|
|
281
329
|
export interface RenderProgress {
|
package/src/video.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { mkdir } from "node:fs/promises";
|
|
1
|
+
import { mkdir, rm } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { readCast, writeCast } from "./cast";
|
|
4
4
|
import { applyOverrides, resolveConfig } from "./config";
|
|
5
5
|
import { record } from "./recorder";
|
|
6
6
|
import { renderOutputs, type RenderResult } from "./render";
|
|
7
|
-
import type { RecordOptions, Recording, RenderOptions, ResolvedConfig, Script, VideoConfig } from "./types";
|
|
7
|
+
import type { CastEvent, RecordOptions, Recording, RenderOptions, ResolvedConfig, Script, VideoConfig } from "./types";
|
|
8
8
|
|
|
9
9
|
export interface VideoRecordOptions extends RecordOptions {
|
|
10
10
|
/** Re-record even if a cached cast matches. */
|
|
@@ -29,6 +29,27 @@ const RECORD_KEYS: (keyof ResolvedConfig)[] = [
|
|
|
29
29
|
"typingSpeed", "typingJitter", "seed", "waitTimeout", "endPause", "quantize", "core",
|
|
30
30
|
];
|
|
31
31
|
|
|
32
|
+
/**
|
|
33
|
+
* Write captured browser frames beside the cast (`<name>.browser/0001.png`) and merge them into the event
|
|
34
|
+
* stream as `b` events whose data is the path relative to the cast file.
|
|
35
|
+
*/
|
|
36
|
+
export async function attachBrowserFrames(recording: Recording, castPath: string): Promise<void> {
|
|
37
|
+
const frames = recording.browserFrames;
|
|
38
|
+
if (!frames || frames.length === 0) return;
|
|
39
|
+
const dirName = `${path.basename(castPath).replace(/\.cast$/, "")}.browser`;
|
|
40
|
+
const dir = path.join(path.dirname(castPath), dirName);
|
|
41
|
+
await rm(dir, { recursive: true, force: true });
|
|
42
|
+
await mkdir(dir, { recursive: true });
|
|
43
|
+
const events: CastEvent[] = [];
|
|
44
|
+
for (const [i, frame] of frames.entries()) {
|
|
45
|
+
const name = `${String(i).padStart(4, "0")}.png`;
|
|
46
|
+
await Bun.write(path.join(dir, name), frame.png);
|
|
47
|
+
events.push([frame.time, "b", `${dirName}/${name}`]);
|
|
48
|
+
}
|
|
49
|
+
recording.events = [...recording.events, ...events].sort((a, b) => a[0] - b[0]);
|
|
50
|
+
delete recording.browserFrames;
|
|
51
|
+
}
|
|
52
|
+
|
|
32
53
|
export class Video {
|
|
33
54
|
readonly config: ResolvedConfig;
|
|
34
55
|
readonly script: Script;
|
|
@@ -80,8 +101,11 @@ export class Video {
|
|
|
80
101
|
}
|
|
81
102
|
const recording = await record(this.config, this.script, opts);
|
|
82
103
|
recording.header.scriptHash = await this.scriptHash();
|
|
83
|
-
|
|
104
|
+
const castPath = path.resolve(this.config.cast);
|
|
105
|
+
await mkdir(path.dirname(castPath), { recursive: true });
|
|
106
|
+
await attachBrowserFrames(recording, castPath);
|
|
84
107
|
await writeCast(this.config.cast, recording);
|
|
108
|
+
recording.source = castPath;
|
|
85
109
|
return recording;
|
|
86
110
|
}
|
|
87
111
|
|