@bud.sh/app 0.5.0 → 0.6.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.
Files changed (115) hide show
  1. package/README.md +41 -31
  2. package/dist/client/assets/bud/design.js +1 -1
  3. package/dist/client/assets/canvas-Bih9EdKJ.js +1 -0
  4. package/dist/client/assets/difference-worker-Bzg-rizy.js +8 -0
  5. package/dist/client/assets/dist-CdE5wBkg.js +5 -0
  6. package/dist/client/assets/files-1dLuoM2f.js +1 -0
  7. package/dist/client/assets/i18n-CkO6VFI0.js +1 -0
  8. package/dist/client/assets/index-Cn2mxroU.css +2 -0
  9. package/dist/client/assets/{index-ChANGtl-.js → index-DtISWZp9.js} +2 -2
  10. package/dist/client/assets/pages-BJ-tNJ4J.js +1 -0
  11. package/dist/client/assets/{project-branches-DO897zM6.js → project-branches-Ce3rXrkc.js} +1 -1
  12. package/dist/client/assets/project-comments-CPUONfs8.js +1 -0
  13. package/dist/client/assets/project-thread-links-C-TGkq59.js +1 -0
  14. package/dist/client/assets/{project-threads-Lay351p4.js → project-threads-Bv7IDBgi.js} +105 -105
  15. package/dist/client/assets/project-work-DAE9-olg.js +1 -0
  16. package/dist/client/assets/{task-design-Avb2RO4w.js → task-design-CwySIAOl.js} +3 -3
  17. package/dist/client/assets/tasks-KWsCLi_h.js +3 -0
  18. package/dist/client/assets/wasm-inline-DSUyFn1L.js +1 -0
  19. package/dist/client/assets/workspace-CVdcfaaB.js +2 -0
  20. package/dist/client/index.html +3 -3
  21. package/dist/hosted/assets/{canvas-V36732ER.js → canvas-AII16n9i.js} +97 -6
  22. package/dist/hosted/assets/{comment-data-CF2ZV_3k.js → comment-data-BXfMElfx.js} +2004 -402
  23. package/dist/hosted/assets/dist-BCSTeNf4.js +4785 -0
  24. package/dist/hosted/assets/{files-DjSCjfU7.js → files-D_1yeAVO.js} +10 -5
  25. package/dist/hosted/assets/{pages-BzjzeuPu.js → pages-CN_SbKWA.js} +3 -3
  26. package/dist/hosted/assets/{project-branches-BT97J9i7.js → project-branches-Bxp0DCwg.js} +1 -1
  27. package/dist/hosted/assets/{project-thread-links-BRLgByEe.js → project-thread-links-KqQoKBLE.js} +76 -4
  28. package/dist/{node-host/assets/screen-CZXWJEds.js → hosted/assets/screen-DpAcDUKR.js} +29 -1
  29. package/dist/hosted/assets/tasks-D66LlwxM.js +1423 -0
  30. package/dist/hosted/assets/wasm-inline-Dl9tqabx.js +4 -0
  31. package/dist/hosted/hosted.js +7885 -6219
  32. package/dist/node/assets/Stream-CAm1eJ2n.js +16604 -0
  33. package/dist/{server/assets/bridge-B_Blt55E.js → node/assets/bridge-DQSBYHmw.js} +124 -290
  34. package/dist/node/assets/config-9_jWwNBh.js +1067 -0
  35. package/dist/node/assets/load-config.server-CMVtRVmO.js +261 -0
  36. package/dist/node/assets/module-3GgtT4Xs.js +308 -0
  37. package/dist/node/assets/server-DTQFuoX2.js +846 -0
  38. package/dist/node/assets/src-D-kG1GxB.js +2 -0
  39. package/dist/node/assets/{src-CerrKjID.js → src-Dwe9APUx.js} +93 -3
  40. package/dist/node/assets/src-DysjfbM8.js +8592 -0
  41. package/dist/node/bridge.js +1 -845
  42. package/dist/node/cli.js +206 -0
  43. package/dist/node/design.js +811 -13
  44. package/dist/node/index.js +2 -739
  45. package/dist/node/plugins.js +5711 -0
  46. package/dist/node/server.js +1 -6746
  47. package/dist/node/vite.js +121 -0
  48. package/dist/{server/assets/canvas-Dc1mYCwQ.js → node-host/assets/canvas-BeDoufy1.js} +97 -7
  49. package/dist/node-host/assets/{comment-data-DyIZNpfG.js → comment-data-DE2T9yTj.js} +1980 -376
  50. package/dist/node-host/assets/dist-BCSTeNf4.js +4785 -0
  51. package/dist/node-host/assets/{files-Dh2TiQZq.js → files-Dl-PTS09.js} +11 -6
  52. package/dist/node-host/assets/{pages-BxpjbYhs.js → pages-DL2sk6_U.js} +3 -3
  53. package/dist/node-host/assets/{project-branches-B7HUGiVK.js → project-branches-DGp5ELct.js} +1 -1
  54. package/dist/{server/assets/project-thread-links-CBOpf6zk.js → node-host/assets/project-thread-links-CgBV3Jcm.js} +76 -5
  55. package/dist/{hosted/assets/screen-CKp2C7kx.js → node-host/assets/screen-B55yyVfb.js} +29 -1
  56. package/dist/node-host/assets/tasks-DZRNkoxe.js +1425 -0
  57. package/dist/node-host/assets/wasm-inline-Dl9tqabx.js +4 -0
  58. package/dist/node-host/node-host.js +6127 -4438
  59. package/dist/server/assets/{branch-previews-ClkoJ0lM.js → branch-previews-DedrpnVR.js} +1555 -673
  60. package/dist/{node-host/assets/canvas-TRUfxfL5.js → server/assets/canvas-CJWQ-jjv.js} +98 -6
  61. package/dist/server/assets/{comment-data-CsjukwAW.js → comment-data-Rg42ToTW.js} +1666 -47
  62. package/dist/server/assets/dist-BCSTeNf4.js +4785 -0
  63. package/dist/server/assets/{events-iHpLGr3k.js → events-BH_rAu7O.js} +155 -20
  64. package/dist/server/assets/{files-E9mSFeoc.js → files-CPJqKeMo.js} +12 -7
  65. package/dist/server/assets/{listener-DN5TyOjJ.js → listener-D61O6PzF.js} +708 -12
  66. package/dist/server/assets/{pages-BBBXyJWV.js → pages-KJY_Ba92.js} +4 -4
  67. package/dist/server/assets/{project-branches-B0YIK6Ur.js → project-branches-qG9ACZvo.js} +2 -2
  68. package/dist/{node-host/assets/project-thread-links-CauJF0Cz.js → server/assets/project-thread-links-CqK0lqCF.js} +77 -4
  69. package/dist/{node-host/assets/tasks-request-ZWmbc8fE.js → server/assets/project-work-DoIwxWMm.js} +87 -2
  70. package/dist/server/assets/run-BJ8r5jSh.js +572 -0
  71. package/dist/server/assets/{screen-BIQA2mr4.js → screen-CBrHPFug.js} +30 -2
  72. package/dist/server/assets/{server-DxK-UB_Z.js → server-Dkbp5stG.js} +1521 -793
  73. package/dist/server/assets/{services-BRrgXYlT.js → services-BTfig8A8.js} +234 -997
  74. package/dist/server/assets/tasks-Bgu5Lg9Y.js +1427 -0
  75. package/dist/server/assets/wasm-inline-Dl9tqabx.js +4 -0
  76. package/dist/server/capture.js +1 -2
  77. package/dist/server/migration.js +569 -12
  78. package/dist/server/runtime.js +7 -5
  79. package/dist/server/server.js +3 -3
  80. package/dist/types/assets/{config-DIC2cf_S.d.ts → config-CvcYmE2s.d.ts} +188 -50
  81. package/dist/types/assets/{contract-CAT-XFNq.d.ts → contract-B7yuuqSn.d.ts} +44 -2
  82. package/dist/types/assets/{items-CaVkByHk.d.ts → items-BQdaVksf.d.ts} +12 -1
  83. package/dist/types/assets/memory-state-BBW-FAVA.d.ts +236 -0
  84. package/dist/types/assets/picker-Be5Gx4WR.d.ts +9 -0
  85. package/dist/types/assets/{task-design-xJOhRNWh.d.ts → task-design-BDHKFHpp.d.ts} +3 -1
  86. package/dist/types/bridge.d.ts +1 -1
  87. package/dist/types/companion.d.ts +3 -3
  88. package/dist/types/design.d.ts +2 -2
  89. package/dist/types/hosted.d.ts +3 -3
  90. package/dist/types/index.d.ts +2 -2
  91. package/dist/types/node-host.d.ts +2 -2
  92. package/dist/types/plugins.d.ts +445 -0
  93. package/dist/types/screen.d.ts +2 -2
  94. package/dist/types/server.d.ts +2 -228
  95. package/dist/types/vite.d.ts +16 -0
  96. package/package.json +19 -3
  97. package/dist/client/assets/canvas-Cu6R6xxT.js +0 -1
  98. package/dist/client/assets/difference-worker-jfTSn-Tw.js +0 -8
  99. package/dist/client/assets/files-js6ElfkU.js +0 -1
  100. package/dist/client/assets/i18n-DxqFr2mi.js +0 -1
  101. package/dist/client/assets/index-CFFxP0gS.css +0 -2
  102. package/dist/client/assets/pages-6_lhiQmz.js +0 -1
  103. package/dist/client/assets/project-comments-DFFKVpia.js +0 -1
  104. package/dist/client/assets/project-thread-links-NLFWQRD2.js +0 -1
  105. package/dist/client/assets/project-work-du0Y-L5Y.js +0 -1
  106. package/dist/client/assets/tasks-CA-E8bbK.js +0 -1
  107. package/dist/client/assets/tasks-request-C55IeuiP.js +0 -1
  108. package/dist/client/assets/workspace-Cw5HvX5d.js +0 -2
  109. package/dist/hosted/assets/tasks-Dj7AyBJB.js +0 -649
  110. package/dist/hosted/assets/tasks-request-DZob623r.js +0 -113
  111. package/dist/node-host/assets/tasks-Bs1IOpeU.js +0 -651
  112. package/dist/server/assets/project-work-qSKFO5yj.js +0 -88
  113. package/dist/server/assets/tasks-CiXodsLN.js +0 -652
  114. package/dist/server/assets/tasks-request-DhwCzpRi.js +0 -115
  115. package/dist/types/assets/picker-D1Bw3ndx.d.ts +0 -14
@@ -0,0 +1,4785 @@
1
+ //#region ../../node_modules/.pnpm/@wterm+core@0.5.4/node_modules/@wterm/core/dist/wasm-loading.js
2
+ var embedded;
3
+ var modules = /* @__PURE__ */ new Map();
4
+ var MAX_CACHED_MODULES = 4;
5
+ function decodeBase64(base64) {
6
+ const binary = atob(base64);
7
+ const bytes = new Uint8Array(binary.length);
8
+ for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
9
+ return bytes.buffer;
10
+ }
11
+ async function compileUrl(url) {
12
+ const response = await fetch(url);
13
+ if (!response.ok) throw new Error(`[wterm] Failed to load WASM from ${url}: ${response.status} ${response.statusText}`);
14
+ if (typeof WebAssembly.compileStreaming === "function" && response.headers.get("Content-Type")?.trim().toLowerCase() === "application/wasm") try {
15
+ return await WebAssembly.compileStreaming(response.clone());
16
+ } catch {}
17
+ return WebAssembly.compile(await response.arrayBuffer());
18
+ }
19
+ /** Share compiled code, including pending work; callers create fresh instances. */
20
+ function loadWasmModule(url) {
21
+ if (!url) {
22
+ embedded ?? (embedded = import("./wasm-inline-Dl9tqabx.js").then(({ WASM_BASE64 }) => WebAssembly.compile(decodeBase64(WASM_BASE64))).catch((error) => {
23
+ embedded = void 0;
24
+ throw error;
25
+ }));
26
+ return embedded;
27
+ }
28
+ if (typeof document !== "undefined") url = new URL(url, document.baseURI).href;
29
+ else if (typeof location !== "undefined") url = new URL(url, location.href).href;
30
+ const key = url;
31
+ const cached = modules.get(key);
32
+ if (cached) {
33
+ modules.delete(key);
34
+ modules.set(key, cached);
35
+ return cached;
36
+ }
37
+ const pending = compileUrl(key).catch((error) => {
38
+ if (modules.get(key) === pending) modules.delete(key);
39
+ throw error;
40
+ });
41
+ modules.set(key, pending);
42
+ if (modules.size > MAX_CACHED_MODULES) modules.delete(modules.keys().next().value);
43
+ return pending;
44
+ }
45
+ //#endregion
46
+ //#region ../../node_modules/.pnpm/@wterm+core@0.5.4/node_modules/@wterm/core/dist/wasm-bridge.js
47
+ var WasmBridge = class WasmBridge {
48
+ get dv() {
49
+ if (this._dvBuffer !== this.memory.buffer) {
50
+ this._dvBuffer = this.memory.buffer;
51
+ this._dv = new DataView(this.memory.buffer);
52
+ }
53
+ return this._dv;
54
+ }
55
+ constructor(instance) {
56
+ this.gridPtr = 0;
57
+ this.dirtyPtr = 0;
58
+ this.writeBufferPtr = 0;
59
+ this.cellSize = 12;
60
+ this.gridStride = 0;
61
+ this.encoder = new TextEncoder();
62
+ this.decoder = new TextDecoder();
63
+ this._dvBuffer = null;
64
+ this.linkCache = /* @__PURE__ */ new Map();
65
+ this.exports = instance.exports;
66
+ this.memory = this.exports.memory;
67
+ }
68
+ static async load(url) {
69
+ const module = await loadWasmModule(url);
70
+ const instance = await WebAssembly.instantiate(module);
71
+ return new WasmBridge(instance);
72
+ }
73
+ init(cols, rows) {
74
+ this.exports.init(cols, rows);
75
+ this.linkCache.clear();
76
+ this._updatePointers();
77
+ }
78
+ _updatePointers() {
79
+ this.gridPtr = this.exports.getGridPtr();
80
+ this.dirtyPtr = this.exports.getDirtyPtr();
81
+ this.writeBufferPtr = this.exports.getWriteBuffer();
82
+ this.cellSize = this.exports.getCellSize();
83
+ this.gridStride = this.exports.getGridStride();
84
+ }
85
+ writeString(str, afterChunk) {
86
+ const encoded = this.encoder.encode(str);
87
+ this.writeRaw(encoded, afterChunk);
88
+ }
89
+ writeRaw(data, afterChunk) {
90
+ let offset = 0;
91
+ while (offset < data.length) {
92
+ const chunk = Math.min(data.length - offset, 8192);
93
+ new Uint8Array(this.memory.buffer, this.writeBufferPtr, 8192).set(data.subarray(offset, offset + chunk));
94
+ this.exports.writeBytes(chunk);
95
+ this._updatePointers();
96
+ offset += chunk;
97
+ afterChunk?.();
98
+ }
99
+ }
100
+ getCell(row, col) {
101
+ const offset = this.gridPtr + (row * this.gridStride + col) * this.cellSize;
102
+ const dv = this.dv;
103
+ const result = {
104
+ char: dv.getUint32(offset, true),
105
+ fg: dv.getUint16(offset + 4, true),
106
+ bg: dv.getUint16(offset + 6, true),
107
+ flags: dv.getUint8(offset + 8),
108
+ width: dv.getUint8(offset + 9)
109
+ };
110
+ Object.assign(result, this._readLink(dv.getUint16(offset + 10, true)));
111
+ return result;
112
+ }
113
+ isDirtyRow(row) {
114
+ return new Uint8Array(this.memory.buffer, this.dirtyPtr, this.getRows())[row] !== 0;
115
+ }
116
+ clearDirty() {
117
+ this.exports.clearDirty();
118
+ }
119
+ getCursor() {
120
+ const shape = this.exports.getCursorShape?.() ?? 0;
121
+ return {
122
+ row: this.exports.getCursorRow(),
123
+ col: this.exports.getCursorCol(),
124
+ visible: this.exports.getCursorVisible() !== 0,
125
+ shape: shape === 1 ? "underline" : shape === 2 ? "bar" : "block",
126
+ blinking: (this.exports.getCursorBlinking?.() ?? 0) !== 0
127
+ };
128
+ }
129
+ getCols() {
130
+ return this.exports.getCols();
131
+ }
132
+ getRows() {
133
+ return this.exports.getRows();
134
+ }
135
+ cursorKeysApp() {
136
+ return this.exports.getCursorKeysApp() !== 0;
137
+ }
138
+ bracketedPaste() {
139
+ return this.exports.getBracketedPaste() !== 0;
140
+ }
141
+ usingAltScreen() {
142
+ return this.exports.getUsingAltScreen() !== 0;
143
+ }
144
+ mouseTracking() {
145
+ const mode = this.exports.getMouseTracking();
146
+ return mode === 1e3 || mode === 1002 || mode === 1003 ? mode : 0;
147
+ }
148
+ mouseSgr() {
149
+ return this.exports.getMouseSgr() !== 0;
150
+ }
151
+ mouseEncoding() {
152
+ switch (this.exports.getMouseEncoding?.()) {
153
+ case 0: return "x10";
154
+ case 1: return "utf8";
155
+ case 2: return "sgr";
156
+ case 3: return "urxvt";
157
+ case 4: return "sgr-pixels";
158
+ case void 0: return this.mouseSgr() ? "sgr" : "x10";
159
+ default: return null;
160
+ }
161
+ }
162
+ focusEvents() {
163
+ return this.exports.getFocusEvents() !== 0;
164
+ }
165
+ synchronizedOutput() {
166
+ return this.exports.getSynchronizedOutput() !== 0;
167
+ }
168
+ synchronizedOutputGeneration() {
169
+ return this.exports.getSynchronizedOutputGeneration();
170
+ }
171
+ kittyKeyboardFlags() {
172
+ return this.exports.getKittyKeyboardFlags?.() ?? 0;
173
+ }
174
+ getTitle() {
175
+ if (this.exports.getTitleChanged() === 0) return null;
176
+ const ptr = this.exports.getTitlePtr();
177
+ const len = this.exports.getTitleLen();
178
+ const bytes = new Uint8Array(this.memory.buffer, ptr, len);
179
+ return this.decoder.decode(bytes);
180
+ }
181
+ getBellCount() {
182
+ return this.exports.getBellCount?.() ?? 0;
183
+ }
184
+ getResponse() {
185
+ const len = this.exports.getResponseLen();
186
+ if (len === 0) return null;
187
+ const ptr = this.exports.getResponsePtr();
188
+ const bytes = new Uint8Array(this.memory.buffer, ptr, len);
189
+ const str = this.decoder.decode(bytes);
190
+ this.exports.clearResponse();
191
+ return str;
192
+ }
193
+ getResourceState() {
194
+ const capacity = this.exports.getHyperlinkCapacity?.();
195
+ const used = this.exports.getHyperlinkCount?.();
196
+ const rejected = this.exports.getHyperlinkRejectedCount?.();
197
+ if (capacity === void 0 || used === void 0 || rejected === void 0) return {};
198
+ return { hyperlinks: {
199
+ capacity,
200
+ used,
201
+ rejected,
202
+ saturated: used >= capacity
203
+ } };
204
+ }
205
+ getScrollbackCount() {
206
+ return this.exports.getScrollbackCount();
207
+ }
208
+ getScrollbackDiscardedCount() {
209
+ return this.exports.getScrollbackDiscardedCount();
210
+ }
211
+ getScrollbackCell(offset, col) {
212
+ const off = this.exports.getScrollbackLine(offset) + col * this.cellSize;
213
+ const dv = this.dv;
214
+ const result = {
215
+ char: dv.getUint32(off, true),
216
+ fg: dv.getUint16(off + 4, true),
217
+ bg: dv.getUint16(off + 6, true),
218
+ flags: dv.getUint8(off + 8),
219
+ width: dv.getUint8(off + 9)
220
+ };
221
+ Object.assign(result, this._readLink(dv.getUint16(off + 10, true)));
222
+ return result;
223
+ }
224
+ getScrollbackLineLen(offset) {
225
+ return this.exports.getScrollbackLineLen(offset);
226
+ }
227
+ getUnhandledSequences() {
228
+ const count = this.exports.getDebugLogCount();
229
+ if (count === 0) return [];
230
+ const ptr = this.exports.getDebugLogPtr();
231
+ const entrySize = this.exports.getDebugLogEntrySize();
232
+ const maxEntries = this.exports.getDebugLogMax();
233
+ const total = Math.min(count, maxEntries);
234
+ const dv = new DataView(this.memory.buffer);
235
+ const entries = [];
236
+ const startIdx = count >= maxEntries ? count % maxEntries : 0;
237
+ for (let i = 0; i < total; i++) {
238
+ const off = ptr + (startIdx + i) % maxEntries * entrySize;
239
+ const finalByte = dv.getUint8(off);
240
+ if (finalByte === 0) continue;
241
+ const privateByte = dv.getUint8(off + 1);
242
+ const paramCount = dv.getUint8(off + 2);
243
+ const params = [];
244
+ for (let p = 0; p < Math.min(paramCount, 4); p++) params.push(dv.getUint16(off + 4 + p * 2, true));
245
+ entries.push({
246
+ final: String.fromCharCode(finalByte),
247
+ private: privateByte ? String.fromCharCode(privateByte) : "",
248
+ paramCount,
249
+ params
250
+ });
251
+ }
252
+ return entries;
253
+ }
254
+ resize(cols, rows) {
255
+ this.exports.resizeTerminal(cols, rows);
256
+ this._updatePointers();
257
+ }
258
+ _readLink(index) {
259
+ if (index === 0) return void 0;
260
+ const cached = this.linkCache.get(index);
261
+ if (cached) return cached;
262
+ const uriLen = this.exports.getLinkUriLen(index);
263
+ if (uriLen === 0) return void 0;
264
+ const uri = this.decoder.decode(new Uint8Array(this.memory.buffer, this.exports.getLinkUriPtr(index), uriLen));
265
+ const idLen = this.exports.getLinkIdLen(index);
266
+ const linkId = idLen === 0 ? void 0 : this.decoder.decode(new Uint8Array(this.memory.buffer, this.exports.getLinkIdPtr(index), idLen));
267
+ const value = {
268
+ linkUri: uri,
269
+ linkId,
270
+ linkKey: linkId ? `e\0${linkId}\0${uri}` : `b\0${index}`
271
+ };
272
+ this.linkCache.set(index, value);
273
+ return value;
274
+ }
275
+ };
276
+ //#endregion
277
+ //#region ../../node_modules/.pnpm/@wterm+dom@0.5.4/node_modules/@wterm/dom/dist/graphics-layer.js
278
+ /**
279
+ * Keep browser-owned image backing stores bounded independently of the core's
280
+ * decoded image budget. This is deliberately a fixed layer limit: placement
281
+ * geometry is terminal output and must not be allowed to choose an arbitrary
282
+ * amount of browser memory.
283
+ */
284
+ var GRAPHICS_CANVAS_BUDGET_BYTES = 33554432;
285
+ var MAX_CANVAS_DIMENSION = 32768;
286
+ function finitePositive(value) {
287
+ return value !== void 0 && Number.isFinite(value) && value > 0;
288
+ }
289
+ function safeNonNegativeInteger(value) {
290
+ return Number.isSafeInteger(value) && value >= 0;
291
+ }
292
+ function safeProduct(...values) {
293
+ let result = 1;
294
+ for (const value of values) {
295
+ if (!safeNonNegativeInteger(value)) return null;
296
+ result *= value;
297
+ if (!Number.isSafeInteger(result)) return null;
298
+ }
299
+ return result;
300
+ }
301
+ function placementKey(placement) {
302
+ return `${placement.placementKey}:${placement.imageId}:${placement.imageVersion}`;
303
+ }
304
+ /** Browser-owned canvas overlay for cores that expose normalized terminal images. */
305
+ var GraphicsLayer = class {
306
+ constructor(container, options = {}) {
307
+ this.layer = null;
308
+ this.flowSpacer = null;
309
+ this.canvases = /* @__PURE__ */ new Map();
310
+ this.canvasAllocations = /* @__PURE__ */ new Map();
311
+ this.canvasBytes = 0;
312
+ this.cache = /* @__PURE__ */ new Map();
313
+ this.generation = -1;
314
+ this.flowRows = /* @__PURE__ */ new Map();
315
+ this.container = container;
316
+ this.maxImageWidth = finitePositive(options.maxImageWidth) ? options.maxImageWidth : void 0;
317
+ this.maxImageHeight = finitePositive(options.maxImageHeight) ? options.maxImageHeight : void 0;
318
+ }
319
+ setup() {
320
+ this.destroy();
321
+ const flowSpacer = document.createElement("div");
322
+ flowSpacer.className = "term-image-flow-spacer";
323
+ flowSpacer.setAttribute("aria-hidden", "true");
324
+ this.container.appendChild(flowSpacer);
325
+ this.flowSpacer = flowSpacer;
326
+ const layer = document.createElement("div");
327
+ layer.className = "term-images";
328
+ layer.setAttribute("aria-hidden", "true");
329
+ layer.setAttribute("role", "presentation");
330
+ this.container.appendChild(layer);
331
+ this.layer = layer;
332
+ this.generation = -1;
333
+ }
334
+ reconcile(core, viewport) {
335
+ const getState = core.getGraphicsState;
336
+ const getImage = core.getGraphicsImage;
337
+ if (!getState || !getImage || !this.layer) {
338
+ this.clearCanvases();
339
+ this.clearFlowReservations();
340
+ return;
341
+ }
342
+ let state;
343
+ try {
344
+ state = getState.call(core);
345
+ } catch {
346
+ this.clearCanvases();
347
+ this.clearFlowReservations();
348
+ return;
349
+ }
350
+ if (!state || !Number.isSafeInteger(state.generation) || !Array.isArray(state.images) || !Array.isArray(state.placements)) {
351
+ this.clearCanvases();
352
+ this.clearFlowReservations();
353
+ return;
354
+ }
355
+ const descriptors = /* @__PURE__ */ new Map();
356
+ for (const image of state.images) if (Number.isSafeInteger(image.imageId) && image.imageId > 0 && Number.isSafeInteger(image.version) && image.version > 0 && Number.isSafeInteger(image.width) && Number.isSafeInteger(image.height) && image.width > 0 && image.height > 0) descriptors.set(`${image.imageId}:${image.version}`, image);
357
+ const bounds = this.visiblePixelArea(core, viewport);
358
+ const flowOffsets = bounds ? this.reconcileFlowReservations(core, state, viewport, descriptors, bounds) : /* @__PURE__ */ new Map();
359
+ if (!bounds) this.clearFlowReservations();
360
+ const visible = bounds ? this.visiblePlacements(core, state, viewport, descriptors, bounds, flowOffsets) : [];
361
+ const wanted = /* @__PURE__ */ new Set();
362
+ const refs = /* @__PURE__ */ new Map();
363
+ for (const placement of visible) {
364
+ const key = placementKey(placement);
365
+ const imageKey = `${placement.imageId}:${placement.imageVersion}`;
366
+ if (!descriptors.has(imageKey)) continue;
367
+ wanted.add(key);
368
+ refs.set(imageKey, (refs.get(imageKey) ?? 0) + 1);
369
+ }
370
+ const changed = state.generation !== this.generation;
371
+ this.generation = state.generation;
372
+ for (const [key, canvas] of this.canvases) if (!wanted.has(key)) this.removeCanvas(key);
373
+ for (const [key, cached] of this.cache) if (!refs.has(key)) this.cache.delete(key);
374
+ else cached.refs = refs.get(key);
375
+ for (const placement of visible) {
376
+ const key = placementKey(placement);
377
+ const imageKey = `${placement.imageId}:${placement.imageVersion}`;
378
+ if (!wanted.has(key)) continue;
379
+ const descriptor = descriptors.get(imageKey);
380
+ if (!descriptor) continue;
381
+ let cached = this.cache.get(imageKey);
382
+ if (!cached) {
383
+ let data;
384
+ try {
385
+ data = getImage.call(core, placement.imageId, placement.imageVersion);
386
+ } catch {
387
+ data = null;
388
+ }
389
+ if (!data || !this.validImage(data, descriptor.width, descriptor.height)) continue;
390
+ cached = {
391
+ data,
392
+ refs: refs.get(imageKey) ?? 0
393
+ };
394
+ this.cache.set(imageKey, cached);
395
+ }
396
+ const existingCanvas = this.canvases.get(key);
397
+ const canvas = existingCanvas ?? this.createCanvas(key);
398
+ if (!canvas) continue;
399
+ if (changed || !existingCanvas) {
400
+ let painted = false;
401
+ try {
402
+ painted = this.paint(canvas, key, cached.data, placement, viewport, bounds, flowOffsets.get(placement.row) ?? 0);
403
+ } catch {
404
+ painted = false;
405
+ }
406
+ if (!painted) this.removeCanvas(key);
407
+ } else this.position(canvas, placement, viewport, flowOffsets.get(placement.row) ?? 0);
408
+ }
409
+ }
410
+ destroy() {
411
+ this.clearCanvases();
412
+ this.layer?.remove();
413
+ this.flowSpacer?.remove();
414
+ this.layer = null;
415
+ this.flowSpacer = null;
416
+ this.cache.clear();
417
+ this.generation = -1;
418
+ this.clearFlowReservations();
419
+ }
420
+ createCanvas(key) {
421
+ if (!this.layer) return null;
422
+ const canvas = document.createElement("canvas");
423
+ canvas.className = "term-image";
424
+ canvas.setAttribute("aria-hidden", "true");
425
+ canvas.tabIndex = -1;
426
+ canvas.draggable = false;
427
+ this.layer.appendChild(canvas);
428
+ this.canvases.set(key, canvas);
429
+ return canvas;
430
+ }
431
+ clearCanvases() {
432
+ for (const key of this.canvases.keys()) this.removeCanvas(key);
433
+ this.canvasAllocations.clear();
434
+ this.canvasBytes = 0;
435
+ this.cache.clear();
436
+ }
437
+ removeCanvas(key) {
438
+ this.canvases.get(key)?.remove();
439
+ this.canvases.delete(key);
440
+ const bytes = this.canvasAllocations.get(key) ?? 0;
441
+ this.canvasAllocations.delete(key);
442
+ this.canvasBytes = Math.max(0, this.canvasBytes - bytes);
443
+ }
444
+ /**
445
+ * An implicit Kitty placement has zero cell rows in its metadata. The
446
+ * terminal core still advances the shell cursor independently, so an
447
+ * absolute canvas alone would let the next prompt paint underneath it.
448
+ * Move the placement's row below the image while keeping the image itself
449
+ * anchored at the row where Kitty placed it. Transforms preserve the
450
+ * terminal screen's existing scroll geometry while changing the visual
451
+ * flow of rows after the image.
452
+ */
453
+ reconcileFlowReservations(core, state, viewport, descriptors, bounds) {
454
+ let totalRows;
455
+ let screenRows;
456
+ try {
457
+ screenRows = core.getRows();
458
+ totalRows = viewport.scrollbackCount + screenRows;
459
+ } catch {
460
+ if (this.flowRows.size > 0) this.clearFlowReservations();
461
+ return /* @__PURE__ */ new Map();
462
+ }
463
+ if (!Number.isSafeInteger(screenRows) || screenRows < 0 || !Number.isSafeInteger(totalRows) || totalRows < 0) {
464
+ if (this.flowRows.size > 0) this.clearFlowReservations();
465
+ return /* @__PURE__ */ new Map();
466
+ }
467
+ const reservations = /* @__PURE__ */ new Map();
468
+ for (const placement of state.placements) {
469
+ if (!this.validPlacement(placement, totalRows)) continue;
470
+ if (placement.rows !== 0) continue;
471
+ if (placement.row < viewport.scrollbackCount) continue;
472
+ const image = descriptors.get(`${placement.imageId}:${placement.imageVersion}`);
473
+ if (!image) continue;
474
+ const size = this.destinationSize(placement, placement.sourceWidth || image.width, placement.sourceHeight || image.height, viewport, bounds);
475
+ if (!size) continue;
476
+ const reserve = placement.offsetY + size.height;
477
+ if (!finitePositive(reserve)) continue;
478
+ reservations.set(placement.row, Math.max(reservations.get(placement.row) ?? 0, reserve));
479
+ }
480
+ if (reservations.size === 0) {
481
+ if (this.flowRows.size > 0) this.clearFlowReservations();
482
+ return /* @__PURE__ */ new Map();
483
+ }
484
+ this.clearFlowReservations();
485
+ const rows = this.container.querySelectorAll(".term-row:not(.term-scrollback-row)");
486
+ for (const row of rows) row.style.transform = "";
487
+ const flowOffsets = /* @__PURE__ */ new Map();
488
+ let offset = 0;
489
+ const scrollbackCount = viewport.scrollbackCount;
490
+ for (let viewportRow = 0; viewportRow < screenRows; viewportRow++) {
491
+ const row = scrollbackCount + viewportRow;
492
+ if (offset > 0) flowOffsets.set(row, offset);
493
+ const reserve = reservations.get(row) ?? 0;
494
+ const rowElement = rows[viewportRow];
495
+ const rowOffset = offset + reserve;
496
+ if (rowElement && rowOffset > 0) rowElement.style.transform = `translateY(${rowOffset}px)`;
497
+ offset += reserve;
498
+ }
499
+ if (this.flowSpacer) this.flowSpacer.style.height = `${offset}px`;
500
+ this.container.parentElement?.classList.toggle("has-image-flow", offset > 0);
501
+ this.flowRows = reservations;
502
+ return flowOffsets;
503
+ }
504
+ clearFlowReservations() {
505
+ if (this.flowRows.size === 0) {
506
+ this.flowSpacer?.style.setProperty("height", "0px");
507
+ this.container.parentElement?.classList.remove("has-image-flow");
508
+ return;
509
+ }
510
+ const rows = this.container.querySelectorAll(".term-row:not(.term-scrollback-row)");
511
+ for (const row of rows) row.style.transform = "";
512
+ if (this.flowSpacer) this.flowSpacer.style.height = "0px";
513
+ this.container.parentElement?.classList.remove("has-image-flow");
514
+ this.flowRows.clear();
515
+ }
516
+ validImage(data, expectedWidth, expectedHeight) {
517
+ const byteLength = safeProduct(data.width, data.height, 4);
518
+ return Number.isSafeInteger(data.width) && Number.isSafeInteger(data.height) && data.width > 0 && data.height > 0 && data.width === expectedWidth && data.height === expectedHeight && data.rgba instanceof Uint8Array && byteLength !== null && data.rgba.byteLength === byteLength;
519
+ }
520
+ visiblePlacements(core, state, viewport, descriptors, bounds, flowOffsets) {
521
+ if (!finitePositive(viewport.rowHeight) || !finitePositive(viewport.charWidth) || !Number.isFinite(viewport.scrollTop)) return [];
522
+ let totalRows;
523
+ try {
524
+ totalRows = viewport.scrollbackCount + core.getRows();
525
+ } catch {
526
+ return [];
527
+ }
528
+ if (!Number.isSafeInteger(totalRows) || totalRows < 0) return [];
529
+ const viewportStart = viewport.scrollTop - viewport.overscanRows * viewport.rowHeight;
530
+ const viewportEnd = viewport.scrollTop + Math.max(viewport.clientHeight, viewport.rowHeight) + viewport.overscanRows * viewport.rowHeight;
531
+ return state.placements.filter((placement) => {
532
+ if (!this.validPlacement(placement, totalRows)) return false;
533
+ const image = descriptors.get(`${placement.imageId}:${placement.imageVersion}`);
534
+ if (!image) return false;
535
+ const size = this.destinationSize(placement, placement.sourceWidth || image.width, placement.sourceHeight || image.height, viewport, bounds);
536
+ if (!size) return false;
537
+ const placementTop = placement.row * viewport.rowHeight + placement.offsetY + (flowOffsets.get(placement.row) ?? 0);
538
+ const placementEnd = placementTop + size.height;
539
+ return Number.isFinite(placementTop) && Number.isFinite(placementEnd) && placementTop < viewportEnd && placementEnd > viewportStart;
540
+ });
541
+ }
542
+ validPlacement(placement, totalRows) {
543
+ return typeof placement.placementKey === "string" && placement.placementKey.length > 0 && safeNonNegativeInteger(placement.imageId) && placement.imageId > 0 && safeNonNegativeInteger(placement.imageVersion) && placement.imageVersion > 0 && safeNonNegativeInteger(placement.row) && placement.row < totalRows && safeNonNegativeInteger(placement.col) && safeNonNegativeInteger(placement.offsetX) && safeNonNegativeInteger(placement.offsetY) && safeNonNegativeInteger(placement.sourceX) && safeNonNegativeInteger(placement.sourceY) && safeNonNegativeInteger(placement.sourceWidth) && safeNonNegativeInteger(placement.sourceHeight) && safeNonNegativeInteger(placement.columns) && safeNonNegativeInteger(placement.rows) && Number.isSafeInteger(placement.z) && Number.isSafeInteger(placement.row + (placement.rows || 1));
544
+ }
545
+ position(canvas, placement, viewport, flowOffset = 0) {
546
+ const left = placement.rows === 0 ? placement.offsetX : placement.col * viewport.charWidth + placement.offsetX;
547
+ const top = placement.row * viewport.rowHeight + placement.offsetY + flowOffset;
548
+ if (Number.isFinite(left)) canvas.style.left = `${left}px`;
549
+ if (Number.isFinite(top)) canvas.style.top = `${top}px`;
550
+ }
551
+ paint(canvas, key, image, placement, viewport, bounds, flowOffset = 0) {
552
+ if (!this.validPlacement(placement, Number.MAX_SAFE_INTEGER)) return false;
553
+ const sourceX = placement.sourceX;
554
+ const sourceY = placement.sourceY;
555
+ const sourceWidth = placement.sourceWidth || image.width;
556
+ const sourceHeight = placement.sourceHeight || image.height;
557
+ if (!Number.isSafeInteger(sourceX) || !Number.isSafeInteger(sourceY) || !Number.isSafeInteger(sourceWidth) || !Number.isSafeInteger(sourceHeight) || sourceX < 0 || sourceY < 0 || sourceWidth <= 0 || sourceHeight <= 0 || sourceX + sourceWidth > image.width || sourceY + sourceHeight > image.height) return false;
558
+ const destination = this.destinationSize(placement, sourceWidth, sourceHeight, viewport, bounds);
559
+ if (!destination) return false;
560
+ const { width: destinationWidth, height: destinationHeight } = destination;
561
+ const pixelWidth = Math.max(1, Math.ceil(destinationWidth));
562
+ const pixelHeight = Math.max(1, Math.ceil(destinationHeight));
563
+ if (!Number.isSafeInteger(pixelWidth) || !Number.isSafeInteger(pixelHeight) || pixelWidth > MAX_CANVAS_DIMENSION || pixelHeight > MAX_CANVAS_DIMENSION) return false;
564
+ const allocationBytes = safeProduct(pixelWidth, pixelHeight, 4);
565
+ if (allocationBytes === null || !this.resizeCanvas(canvas, key, pixelWidth, pixelHeight, allocationBytes)) return false;
566
+ this.position(canvas, placement, viewport, flowOffset);
567
+ canvas.style.width = `${destinationWidth}px`;
568
+ canvas.style.height = `${destinationHeight}px`;
569
+ canvas.style.zIndex = String(placement.z);
570
+ canvas.style.pointerEvents = "none";
571
+ const context = canvas.getContext("2d");
572
+ if (!context) return false;
573
+ const source = document.createElement("canvas");
574
+ source.width = image.width;
575
+ source.height = image.height;
576
+ const sourceContext = source.getContext("2d");
577
+ if (!sourceContext) return false;
578
+ const rgba = new Uint8ClampedArray(image.rgba);
579
+ const imageData = typeof ImageData !== "undefined" ? new ImageData(rgba, image.width, image.height) : sourceContext.createImageData?.(image.width, image.height) ?? {
580
+ data: rgba,
581
+ width: image.width,
582
+ height: image.height
583
+ };
584
+ if ("data" in imageData && imageData.data !== rgba) imageData.data.set(rgba);
585
+ sourceContext.putImageData(imageData, 0, 0);
586
+ context.clearRect(0, 0, pixelWidth, pixelHeight);
587
+ context.drawImage(source, sourceX, sourceY, sourceWidth, sourceHeight, 0, 0, pixelWidth, pixelHeight);
588
+ return true;
589
+ }
590
+ destinationSize(placement, sourceWidth, sourceHeight, viewport, bounds) {
591
+ if (!safeNonNegativeInteger(sourceWidth) || !safeNonNegativeInteger(sourceHeight) || sourceWidth <= 0 || sourceHeight <= 0) return null;
592
+ const width = placement.columns * viewport.charWidth;
593
+ const height = placement.rows * viewport.rowHeight;
594
+ const destinationWidth = finitePositive(width) && placement.columns > 0 ? width : finitePositive(height) && placement.rows > 0 ? height * (sourceWidth / sourceHeight) : sourceWidth;
595
+ const destinationHeight = finitePositive(height) && placement.rows > 0 ? height : finitePositive(width) && placement.columns > 0 ? width * (sourceHeight / sourceWidth) : sourceHeight;
596
+ if (!finitePositive(destinationWidth) || !finitePositive(destinationHeight) || !Number.isFinite(placement.offsetY + destinationHeight)) return null;
597
+ if (!bounds) return null;
598
+ const scale = Math.min(1, bounds.width / destinationWidth, bounds.height / destinationHeight, this.maxImageWidth === void 0 ? 1 : this.maxImageWidth / destinationWidth, this.maxImageHeight === void 0 ? 1 : this.maxImageHeight / destinationHeight);
599
+ if (!finitePositive(scale)) return null;
600
+ return {
601
+ width: destinationWidth * scale,
602
+ height: destinationHeight * scale
603
+ };
604
+ }
605
+ visiblePixelArea(core, viewport) {
606
+ let cols;
607
+ let rows;
608
+ try {
609
+ cols = core.getCols();
610
+ rows = core.getRows();
611
+ } catch {
612
+ return null;
613
+ }
614
+ if (!safeNonNegativeInteger(cols) || !safeNonNegativeInteger(rows) || cols <= 0 || rows <= 0 || !finitePositive(viewport.charWidth) || !finitePositive(viewport.rowHeight)) return null;
615
+ const width = cols * viewport.charWidth;
616
+ const height = rows * viewport.rowHeight;
617
+ if (!finitePositive(width) || !finitePositive(height) || !Number.isSafeInteger(Math.ceil(width)) || !Number.isSafeInteger(Math.ceil(height))) return null;
618
+ return {
619
+ width: Math.min(width, MAX_CANVAS_DIMENSION),
620
+ height: Math.min(height, MAX_CANVAS_DIMENSION)
621
+ };
622
+ }
623
+ resizeCanvas(canvas, key, width, height, bytes) {
624
+ const previousBytes = this.canvasAllocations.get(key) ?? 0;
625
+ if (bytes > GRAPHICS_CANVAS_BUDGET_BYTES - this.canvasBytes + previousBytes) return false;
626
+ try {
627
+ canvas.width = width;
628
+ canvas.height = height;
629
+ } catch {
630
+ return false;
631
+ }
632
+ this.canvasBytes = this.canvasBytes - previousBytes + bytes;
633
+ this.canvasAllocations.set(key, bytes);
634
+ return true;
635
+ }
636
+ };
637
+ //#endregion
638
+ //#region ../../node_modules/.pnpm/@wterm+dom@0.5.4/node_modules/@wterm/dom/dist/selection.js
639
+ /** Expand partial graphemes and remove layout-only wide-glyph spacer heads. */
640
+ function selectedText(content, start, end) {
641
+ const parts = [];
642
+ let cursor = start;
643
+ for (const cell of content.specialCells) {
644
+ if (cell.end <= start) continue;
645
+ if (cell.start >= end) break;
646
+ if (cursor < cell.start) parts.push(content.text.slice(cursor, cell.start));
647
+ if (!cell.omit) parts.push(content.text.slice(cell.start, cell.end));
648
+ cursor = cell.end;
649
+ }
650
+ if (cursor < end) parts.push(content.text.slice(cursor, end));
651
+ return parts.join("");
652
+ }
653
+ /**
654
+ * Extract only a selection wholly owned by this terminal. Work against the
655
+ * painted snapshot: core state can already be ahead of the visible frame.
656
+ * Unknown/missing rows, multiple ranges, and selections outside the terminal
657
+ * stay with the browser rather than silently exporting incomplete history.
658
+ */
659
+ function getSelectionText(terminal, rows) {
660
+ return readSelection(terminal, rows)?.text ?? null;
661
+ }
662
+ function readSelection(terminal, rows) {
663
+ const selection = terminal.ownerDocument.getSelection();
664
+ if (!selection || selection.isCollapsed || selection.rangeCount !== 1) return null;
665
+ const range = selection.getRangeAt(0);
666
+ if (!terminal.contains(range.startContainer) || !terminal.contains(range.endContainer)) return null;
667
+ const active = terminal.ownerDocument.activeElement;
668
+ if (active && (active.tagName === "INPUT" || active.tagName === "TEXTAREA")) {
669
+ const input = active;
670
+ if (input.selectionStart !== input.selectionEnd) return null;
671
+ }
672
+ const parts = [];
673
+ let first;
674
+ let last;
675
+ let previous;
676
+ for (const current of rows) {
677
+ const { element, content } = current;
678
+ if (!range.intersectsNode(element)) continue;
679
+ const selected = terminal.ownerDocument.createRange();
680
+ selected.selectNodeContents(element);
681
+ if (element.contains(range.startContainer)) selected.setStart(range.startContainer, range.startOffset);
682
+ if (element.contains(range.endContainer)) selected.setEnd(range.endContainer, range.endOffset);
683
+ const before = terminal.ownerDocument.createRange();
684
+ before.selectNodeContents(element);
685
+ before.setEnd(selected.startContainer, selected.startOffset);
686
+ const start = before.toString().length;
687
+ const end = start + selected.toString().length;
688
+ if (element.textContent !== content.text) return null;
689
+ first ?? (first = {
690
+ row: current,
691
+ offset: start
692
+ });
693
+ last = {
694
+ row: current,
695
+ offset: end === content.text.length && !content.metadata?.wrapsToNext ? Math.max(start, content.text.replace(/ +$/, "").length) : end
696
+ };
697
+ if (previous) {
698
+ if (current.row !== previous.row + 1) return null;
699
+ if (!(previous.content.metadata?.wrapsToNext && content.metadata?.continuesPrevious)) parts.push("\n");
700
+ }
701
+ let text = start === end ? "" : selectedText(content, start, end);
702
+ if (end === content.text.length && !content.metadata?.wrapsToNext) text = text.replace(/ +$/, "");
703
+ parts.push(text);
704
+ previous = current;
705
+ }
706
+ return first && last ? {
707
+ text: parts.join(""),
708
+ first,
709
+ last,
710
+ backward: selection.anchorNode !== range.startContainer || selection.anchorOffset !== range.startOffset
711
+ } : null;
712
+ }
713
+ /** Anchor an edge to an included cell, so an end at a wrap follows that cell. */
714
+ function cellAtOffset(content, offset, end) {
715
+ let delta = 0;
716
+ for (const cell of content.specialCells) {
717
+ if (offset >= cell.start && offset < cell.end && !end || offset > cell.start && offset <= cell.end && end) return {
718
+ col: cell.col,
719
+ after: end
720
+ };
721
+ if (cell.end <= offset) delta += cell.width - (cell.end - cell.start);
722
+ }
723
+ const after = offset > 0 && (end || offset === content.text.length);
724
+ return {
725
+ col: offset + delta - (after ? 1 : 0),
726
+ after
727
+ };
728
+ }
729
+ function offsetAtCell(content, col, after) {
730
+ let delta = 0;
731
+ for (const cell of content.specialCells) {
732
+ if (col >= cell.col && col < cell.col + cell.width) return after ? cell.end : cell.start;
733
+ if (cell.col < col) delta += cell.end - cell.start - cell.width;
734
+ }
735
+ return col + delta + (after ? 1 : 0);
736
+ }
737
+ function textPoint(element, offset) {
738
+ const walker = element.ownerDocument.createTreeWalker(element, 4);
739
+ let node;
740
+ while (node = walker.nextNode()) {
741
+ const length = node.textContent?.length ?? 0;
742
+ if (offset <= length) return [node, offset];
743
+ offset -= length;
744
+ }
745
+ return null;
746
+ }
747
+ //#endregion
748
+ //#region ../../node_modules/.pnpm/@wterm+dom@0.5.4/node_modules/@wterm/dom/dist/selection-range.js
749
+ var MAX_SELECTION_ROWS = 1e3;
750
+ var MAX_SELECTION_TEXT = 1048576;
751
+ var WORD_BOUNDARIES = /* @__PURE__ */ new Set(" '\"│`|:;,()[]{}<>$");
752
+ /** Expand in retained-buffer coordinates without joining hard/unknown breaks. */
753
+ function selectionRange(core, position, unit) {
754
+ const history = core.getScrollbackCount();
755
+ const total = history + core.getRows();
756
+ const cols = core.getCols();
757
+ const blank = {
758
+ char: 0,
759
+ fg: 256,
760
+ bg: 256,
761
+ flags: 0
762
+ };
763
+ if (!Number.isInteger(position.row) || !Number.isInteger(position.col) || position.row < 0 || position.row >= total || position.col < 0 || position.col >= cols) return null;
764
+ const cell = (p) => p.row < history ? p.col < core.getScrollbackLineLen(history - p.row - 1) ? core.getScrollbackCell(history - p.row - 1, p.col) : blank : core.getCell(p.row - history, p.col);
765
+ const metadata = (row) => row < history ? core.getScrollbackLineLen(history - row - 1) <= cols ? core.getScrollbackRowMetadata?.(history - row - 1) : null : core.getRowMetadata?.(row - history);
766
+ const wraps = (row) => row >= 0 && row + 1 < total && metadata(row)?.wrapsToNext && metadata(row + 1)?.continuesPrevious;
767
+ const advance = (p, direction) => {
768
+ const col = p.col + direction;
769
+ if (col >= 0 && col < cols) return {
770
+ row: p.row,
771
+ col
772
+ };
773
+ const row = p.row + direction;
774
+ if (!wraps(Math.min(row, p.row))) return null;
775
+ return {
776
+ row,
777
+ col: direction === 1 ? 0 : cols - 1
778
+ };
779
+ };
780
+ let origin = { ...position };
781
+ if (cell(origin).spacerHead) return null;
782
+ if (cell(origin).width === 0 && origin.col > 0) origin.col--;
783
+ const text = (p) => {
784
+ const value = cell(p);
785
+ return value.chars ?? String.fromCodePoint(value.char || 32);
786
+ };
787
+ const boundary = (text) => WORD_BOUNDARIES.has(String.fromCodePoint(text.codePointAt(0) ?? 32));
788
+ const expected = boundary(text(origin));
789
+ let length = text(origin).length;
790
+ let reads = 1;
791
+ let exceeded = length > MAX_SELECTION_TEXT;
792
+ let start = origin, end = origin;
793
+ const expand = (direction) => {
794
+ let current = origin;
795
+ let included = origin;
796
+ while (true) {
797
+ const next = advance(current, direction);
798
+ if (!next) return included;
799
+ if (++reads > 2097152) {
800
+ exceeded = true;
801
+ return included;
802
+ }
803
+ const value = cell(next);
804
+ if (value.width !== 0 && !value.spacerHead) {
805
+ const chars = value.chars ?? String.fromCodePoint(value.char || 32);
806
+ if (unit === "word" && boundary(chars) !== expected) return included;
807
+ length += chars.length;
808
+ included = next;
809
+ }
810
+ const first = direction === -1 ? next.row : start.row;
811
+ if ((direction === 1 ? next.row : origin.row) - first >= 1e3 || length > 1048576) {
812
+ exceeded = true;
813
+ return included;
814
+ }
815
+ current = next;
816
+ }
817
+ };
818
+ start = expand(-1);
819
+ if (!exceeded) end = expand(1);
820
+ return exceeded ? null : {
821
+ start,
822
+ end
823
+ };
824
+ }
825
+ //#endregion
826
+ //#region ../../node_modules/.pnpm/@wterm+dom@0.5.4/node_modules/@wterm/dom/dist/rectangle-selection.js
827
+ var MAX_RECTANGLE_CELLS = 65536;
828
+ /** Inclusive corners in physical rows; wide glyphs at either edge stay whole. */
829
+ function rectangleSelection(core, start, end) {
830
+ const history = core.getScrollbackCount();
831
+ const total = history + core.getRows();
832
+ const cols = core.getCols();
833
+ for (const point of [start, end]) if (!Number.isInteger(point.row) || !Number.isInteger(point.col) || point.row < 0 || point.row >= total || point.col < 0 || point.col >= cols) return null;
834
+ const top = Math.min(start.row, end.row), bottom = Math.max(start.row, end.row);
835
+ const left = Math.min(start.col, end.col), right = Math.max(start.col, end.col);
836
+ const count = bottom - top + 1;
837
+ if (count > 1e3 || count * (right - left + 2) > MAX_RECTANGLE_CELLS) return null;
838
+ const rows = [];
839
+ const text = [];
840
+ let length = count - 1;
841
+ for (let row = top; row <= bottom; row++) {
842
+ const offset = history - row - 1;
843
+ const width = row < history ? core.getScrollbackLineLen(offset) : cols;
844
+ const cell = (col) => col >= width ? null : row < history ? core.getScrollbackCell(offset, col) : core.getCell(row - history, col);
845
+ let first = left;
846
+ if (first > 0 && cell(first)?.width === 0 && cell(first - 1)?.width === 2) first--;
847
+ let last = right + 1;
848
+ let line = "";
849
+ for (let col = first; col <= right; col++) {
850
+ const value = cell(col);
851
+ if (value?.width === 0 || value?.spacerHead) continue;
852
+ const chars = value?.chars ?? String.fromCodePoint(value?.char || 32);
853
+ length += chars.length;
854
+ if (length > 1048576) return null;
855
+ line += chars;
856
+ last = Math.max(last, Math.min(cols, col + (value?.width ?? 1)));
857
+ }
858
+ rows.push({
859
+ row,
860
+ left: first,
861
+ right: last
862
+ });
863
+ text.push(line);
864
+ }
865
+ return {
866
+ rows,
867
+ text: text.join("\n")
868
+ };
869
+ }
870
+ //#endregion
871
+ //#region ../../node_modules/.pnpm/@wterm+dom@0.5.4/node_modules/@wterm/dom/dist/tracked-selection.js
872
+ var MAX_TRACKED_SELECTION_ROWS = MAX_SELECTION_ROWS;
873
+ var TrackedSelection = class {
874
+ constructor(terminal) {
875
+ this.terminal = terminal;
876
+ this.current = null;
877
+ this.painted = true;
878
+ }
879
+ matches() {
880
+ const selection = this.terminal.ownerDocument.getSelection();
881
+ const native = this.current?.native;
882
+ return !!selection && !!native && selection.anchorNode === native.anchorNode && selection.anchorOffset === native.anchorOffset && selection.focusNode === native.focusNode && selection.focusOffset === native.focusOffset;
883
+ }
884
+ capture(core, rows) {
885
+ const active = this.terminal.ownerDocument.activeElement;
886
+ if (active && (active.tagName === "INPUT" || active.tagName === "TEXTAREA")) {
887
+ const input = active;
888
+ if (input.selectionStart !== input.selectionEnd) {
889
+ this.dispose();
890
+ return;
891
+ }
892
+ }
893
+ if (this.current && this.matches()) return;
894
+ this.dispose();
895
+ if (!this.painted || !core.trackPosition) return;
896
+ const value = readSelection(this.terminal, rows);
897
+ if (!value || !value.text.length || value.last.row.row - value.first.row.row >= MAX_TRACKED_SELECTION_ROWS || value.text.length > 1048576) return;
898
+ const start = cellAtOffset(value.first.row.content, value.first.offset, false);
899
+ const end = cellAtOffset(value.last.row.content, value.last.offset, true);
900
+ const a = core.trackPosition({
901
+ row: value.first.row.row,
902
+ col: start.col
903
+ });
904
+ if (!a) return;
905
+ const b = core.trackPosition({
906
+ row: value.last.row.row,
907
+ col: end.col
908
+ });
909
+ if (!b) {
910
+ a.dispose();
911
+ return;
912
+ }
913
+ const selection = this.terminal.ownerDocument.getSelection();
914
+ this.current = {
915
+ start: {
916
+ pin: a,
917
+ after: start.after
918
+ },
919
+ end: {
920
+ pin: b,
921
+ after: end.after
922
+ },
923
+ text: value.text,
924
+ backward: value.backward,
925
+ native: this.snapshot(selection)
926
+ };
927
+ }
928
+ beforeMutation(core, rows) {
929
+ this.capture(core, rows);
930
+ this.painted = false;
931
+ }
932
+ beforeRender(core, rows) {
933
+ this.capture(core, rows);
934
+ const start = this.current?.start.pin.resolve();
935
+ const end = this.current?.end.pin.resolve();
936
+ if (!start || !end || end.row < start.row || end.row === start.row && end.col < start.col || end.row - start.row >= MAX_TRACKED_SELECTION_ROWS) {
937
+ this.clear();
938
+ return null;
939
+ }
940
+ return {
941
+ start,
942
+ end
943
+ };
944
+ }
945
+ afterRender(rows, positions) {
946
+ this.painted = true;
947
+ const current = this.current;
948
+ if (!current || !positions) return;
949
+ const mounted = Array.from(rows);
950
+ const edge = (position, after) => {
951
+ const row = mounted.find((row) => row.row === position.row);
952
+ return row && textPoint(row.element, offsetAtCell(row.content, position.col, after));
953
+ };
954
+ const start = edge(positions.start, current.start.after);
955
+ const end = edge(positions.end, current.end.after);
956
+ const selection = this.terminal.ownerDocument.getSelection();
957
+ if (!start || !end || !selection) {
958
+ this.clear();
959
+ return;
960
+ }
961
+ const anchor = current.backward ? end : start;
962
+ const focus = current.backward ? start : end;
963
+ if (selection.anchorNode !== anchor[0] || selection.anchorOffset !== anchor[1] || selection.focusNode !== focus[0] || selection.focusOffset !== focus[1]) selection.setBaseAndExtent(...anchor, ...focus);
964
+ current.native = this.snapshot(selection);
965
+ if (readSelection(this.terminal, mounted)?.text !== current.text) this.clear();
966
+ }
967
+ snapshot(selection) {
968
+ return {
969
+ anchorNode: selection.anchorNode,
970
+ anchorOffset: selection.anchorOffset,
971
+ focusNode: selection.focusNode,
972
+ focusOffset: selection.focusOffset
973
+ };
974
+ }
975
+ clear() {
976
+ if (this.current && this.matches()) this.terminal.ownerDocument.getSelection()?.removeAllRanges();
977
+ this.dispose();
978
+ }
979
+ dispose() {
980
+ this.current?.start.pin.dispose();
981
+ this.current?.end.pin.dispose();
982
+ this.current = null;
983
+ }
984
+ };
985
+ //#endregion
986
+ //#region ../../node_modules/.pnpm/@wterm+dom@0.5.4/node_modules/@wterm/dom/dist/renderer.js
987
+ var DEFAULT_COLOR = 256;
988
+ var DEFAULT_FG_CSS = "var(--term-app-fg, var(--term-fg))";
989
+ var DEFAULT_BG_CSS = "var(--term-app-bg, var(--term-bg))";
990
+ var FLAG_BOLD = 1;
991
+ var FLAG_DIM = 2;
992
+ var FLAG_ITALIC = 4;
993
+ var FLAG_UNDERLINE = 8;
994
+ var FLAG_REVERSE = 32;
995
+ var FLAG_INVISIBLE = 64;
996
+ var FLAG_STRIKETHROUGH = 128;
997
+ var DEFAULT_SCROLLBACK_OVERSCAN_ROWS = 10;
998
+ function rgbToCSS(packed) {
999
+ return `rgb(${packed >> 16 & 255},${packed >> 8 & 255},${packed & 255})`;
1000
+ }
1001
+ function colorToCSS(index) {
1002
+ if (index === DEFAULT_COLOR) return null;
1003
+ if (index < 16) return `var(--term-color-${index})`;
1004
+ if (index < 232) {
1005
+ const n = index - 16;
1006
+ return `rgb(${Math.floor(n / 36) * 51},${Math.floor(n / 6) % 6 * 51},${n % 6 * 51})`;
1007
+ }
1008
+ const level = (index - 232) * 10 + 8;
1009
+ return `rgb(${level},${level},${level})`;
1010
+ }
1011
+ function cellFgCSS(fg, fgRgb) {
1012
+ if (fgRgb !== void 0) return rgbToCSS(fgRgb);
1013
+ return colorToCSS(fg);
1014
+ }
1015
+ function cellBgCSS(bg, bgRgb) {
1016
+ if (bgRgb !== void 0) return rgbToCSS(bgRgb);
1017
+ return colorToCSS(bg);
1018
+ }
1019
+ function buildCellStyle({ fg, bg, flags, fgRgb, bgRgb, underlineStyle, underlineRgb }) {
1020
+ let fgCSS = cellFgCSS(fg, fgRgb);
1021
+ let bgCSS = cellBgCSS(bg, bgRgb);
1022
+ if (flags & FLAG_REVERSE) [fgCSS, bgCSS] = [bgCSS ?? DEFAULT_BG_CSS, fgCSS ?? DEFAULT_FG_CSS];
1023
+ let style = "";
1024
+ if (fgCSS) style += `color:${fgCSS};`;
1025
+ if (bgCSS) style += `background:${bgCSS};`;
1026
+ if (flags & FLAG_BOLD) style += "font-weight:bold;";
1027
+ if (flags & FLAG_DIM) style += "opacity:0.5;";
1028
+ if (flags & FLAG_ITALIC) style += "font-style:italic;";
1029
+ const decorations = [];
1030
+ const underline = underlineStyle ?? (flags & FLAG_UNDERLINE ? "single" : "none");
1031
+ if (underline !== "none") decorations.push("underline");
1032
+ if (flags & FLAG_STRIKETHROUGH) decorations.push("line-through");
1033
+ if (decorations.length) style += `text-decoration:${decorations.join(" ")};`;
1034
+ if (underline !== "none") {
1035
+ style += `text-decoration-style:${underline === "curly" ? "wavy" : underline === "double" || underline === "dotted" || underline === "dashed" ? underline : "solid"};text-decoration-skip-ink:none;`;
1036
+ if (underlineRgb !== void 0) style += `text-decoration-color:${rgbToCSS(underlineRgb)};`;
1037
+ }
1038
+ if (flags & FLAG_INVISIBLE) style += "visibility:hidden;";
1039
+ return style;
1040
+ }
1041
+ function cursorCellStyle(style) {
1042
+ return style.replace(/(^|;)color:/g, "$1--term-cell-fg:").replace(/(^|;)background:/g, "$1--term-cell-bg:");
1043
+ }
1044
+ function columnStyle(columns) {
1045
+ return columns === 1 ? "" : `--term-span-cols:${columns};`;
1046
+ }
1047
+ function escapeHTML(text) {
1048
+ return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
1049
+ }
1050
+ function cellSpanPart(className, style, text) {
1051
+ let content = escapeHTML(text);
1052
+ const flat = !style.includes("text-decoration:underline line-through;");
1053
+ if (!flat) {
1054
+ style = style.replace("text-decoration:underline line-through;", "text-decoration:underline;");
1055
+ content = `<span style="text-decoration:line-through solid currentColor;">${content}</span>`;
1056
+ }
1057
+ const opening = `<span${className ? ` class="${className}"` : ""}${style ? ` style="${style}"` : ""}>`;
1058
+ return {
1059
+ html: `${opening}${content}</span>`,
1060
+ opening: flat ? opening : void 0,
1061
+ text: flat ? text : void 0
1062
+ };
1063
+ }
1064
+ function safeLinkHref(uri) {
1065
+ if (!uri) return void 0;
1066
+ try {
1067
+ const url = new URL(uri);
1068
+ return url.protocol === "http:" || url.protocol === "https:" ? url.href : void 0;
1069
+ } catch {
1070
+ return;
1071
+ }
1072
+ }
1073
+ function linkIdentity(cell) {
1074
+ if (!cell.linkUri) return "";
1075
+ return cell.linkKey ?? `fallback\0${cell.linkId ?? ""}\0${cell.linkUri}`;
1076
+ }
1077
+ function resolveColors(fg, bg, flags, fgRgb, bgRgb) {
1078
+ const foreground = cellFgCSS(fg, fgRgb) || DEFAULT_FG_CSS;
1079
+ const background = cellBgCSS(bg, bgRgb) || DEFAULT_BG_CSS;
1080
+ return flags & FLAG_REVERSE ? {
1081
+ fg: background,
1082
+ bg: foreground
1083
+ } : {
1084
+ fg: foreground,
1085
+ bg: background
1086
+ };
1087
+ }
1088
+ var SNAP_1_8 = "round(calc(var(--term-row-height) * 0.125), 1px)";
1089
+ var SNAP_2_8 = "round(calc(var(--term-row-height) * 0.25), 1px)";
1090
+ var SNAP_3_8 = "round(calc(var(--term-row-height) * 0.375), 1px)";
1091
+ var SNAP_4_8 = "round(calc(var(--term-row-height) * 0.5), 1px)";
1092
+ var SNAP_5_8 = "round(calc(var(--term-row-height) * 0.625), 1px)";
1093
+ var SNAP_6_8 = "round(calc(var(--term-row-height) * 0.75), 1px)";
1094
+ var SNAP_7_8 = "round(calc(var(--term-row-height) * 0.875), 1px)";
1095
+ function getBlockBackground(cp, fg, bg) {
1096
+ switch (cp) {
1097
+ case 9600: return `linear-gradient(${fg} ${SNAP_4_8},${bg} ${SNAP_4_8})`;
1098
+ case 9601: return `linear-gradient(${bg} ${SNAP_7_8},${fg} ${SNAP_7_8})`;
1099
+ case 9602: return `linear-gradient(${bg} ${SNAP_6_8},${fg} ${SNAP_6_8})`;
1100
+ case 9603: return `linear-gradient(${bg} ${SNAP_5_8},${fg} ${SNAP_5_8})`;
1101
+ case 9604: return `linear-gradient(${bg} ${SNAP_4_8},${fg} ${SNAP_4_8})`;
1102
+ case 9605: return `linear-gradient(${bg} ${SNAP_3_8},${fg} ${SNAP_3_8})`;
1103
+ case 9606: return `linear-gradient(${bg} ${SNAP_2_8},${fg} ${SNAP_2_8})`;
1104
+ case 9607: return `linear-gradient(${bg} ${SNAP_1_8},${fg} ${SNAP_1_8})`;
1105
+ case 9608: return fg;
1106
+ case 9609: return `linear-gradient(to right,${fg} 87.5%,${bg} 87.5%)`;
1107
+ case 9610: return `linear-gradient(to right,${fg} 75%,${bg} 75%)`;
1108
+ case 9611: return `linear-gradient(to right,${fg} 62.5%,${bg} 62.5%)`;
1109
+ case 9612: return `linear-gradient(to right,${fg} 50%,${bg} 50%)`;
1110
+ case 9613: return `linear-gradient(to right,${fg} 37.5%,${bg} 37.5%)`;
1111
+ case 9614: return `linear-gradient(to right,${fg} 25%,${bg} 25%)`;
1112
+ case 9615: return `linear-gradient(to right,${fg} 12.5%,${bg} 12.5%)`;
1113
+ case 9616: return `linear-gradient(to right,${bg} 50%,${fg} 50%)`;
1114
+ case 9617: return `color-mix(in srgb,${fg} 25%,${bg})`;
1115
+ case 9618: return `color-mix(in srgb,${fg} 50%,${bg})`;
1116
+ case 9619: return `color-mix(in srgb,${fg} 75%,${bg})`;
1117
+ case 9620: return `linear-gradient(${fg} ${SNAP_1_8},${bg} ${SNAP_1_8})`;
1118
+ case 9621: return `linear-gradient(to right,${bg} 87.5%,${fg} 87.5%)`;
1119
+ default: {
1120
+ const q = {
1121
+ 9622: [
1122
+ false,
1123
+ false,
1124
+ true,
1125
+ false
1126
+ ],
1127
+ 9623: [
1128
+ false,
1129
+ false,
1130
+ false,
1131
+ true
1132
+ ],
1133
+ 9624: [
1134
+ true,
1135
+ false,
1136
+ false,
1137
+ false
1138
+ ],
1139
+ 9625: [
1140
+ true,
1141
+ false,
1142
+ true,
1143
+ true
1144
+ ],
1145
+ 9626: [
1146
+ true,
1147
+ false,
1148
+ false,
1149
+ true
1150
+ ],
1151
+ 9627: [
1152
+ true,
1153
+ true,
1154
+ true,
1155
+ false
1156
+ ],
1157
+ 9628: [
1158
+ true,
1159
+ true,
1160
+ false,
1161
+ true
1162
+ ],
1163
+ 9629: [
1164
+ false,
1165
+ true,
1166
+ false,
1167
+ false
1168
+ ],
1169
+ 9630: [
1170
+ false,
1171
+ true,
1172
+ true,
1173
+ false
1174
+ ],
1175
+ 9631: [
1176
+ false,
1177
+ true,
1178
+ true,
1179
+ true
1180
+ ]
1181
+ }[cp];
1182
+ if (!q) return fg;
1183
+ const [tl, tr, bl, br] = q;
1184
+ if (tl && tr && bl && br) return fg;
1185
+ const layers = [];
1186
+ const POS = [
1187
+ "0 0",
1188
+ "100% 0",
1189
+ "0 100%",
1190
+ "100% 100%"
1191
+ ];
1192
+ q.forEach((filled, i) => {
1193
+ if (filled) layers.push(`linear-gradient(${fg},${fg}) ${POS[i]}/50% 50% no-repeat`);
1194
+ });
1195
+ layers.push(bg);
1196
+ return layers.join(",");
1197
+ }
1198
+ }
1199
+ }
1200
+ var LIGHT_BOX_ARMS = {
1201
+ 9472: "lr",
1202
+ 9474: "ud",
1203
+ 9484: "dr",
1204
+ 9488: "dl",
1205
+ 9492: "ur",
1206
+ 9496: "ul",
1207
+ 9500: "udr",
1208
+ 9508: "udl",
1209
+ 9516: "dlr",
1210
+ 9524: "ulr",
1211
+ 9532: "udlr",
1212
+ 9588: "l",
1213
+ 9589: "u",
1214
+ 9590: "r",
1215
+ 9591: "d"
1216
+ };
1217
+ var HEAVY_BOX_ARMS = {
1218
+ 9473: "lr",
1219
+ 9475: "ud",
1220
+ 9487: "dr",
1221
+ 9491: "dl",
1222
+ 9495: "ur",
1223
+ 9499: "ul",
1224
+ 9507: "udr",
1225
+ 9515: "udl",
1226
+ 9523: "dlr",
1227
+ 9531: "ulr",
1228
+ 9547: "udlr",
1229
+ 9592: "l",
1230
+ 9593: "u",
1231
+ 9594: "r",
1232
+ 9595: "d"
1233
+ };
1234
+ var ROUNDED_BOX_CORNERS = {
1235
+ 9581: "tl",
1236
+ 9582: "tr",
1237
+ 9583: "br",
1238
+ 9584: "bl"
1239
+ };
1240
+ var BOX_STYLES = {};
1241
+ function addBoxStyles(characters, className) {
1242
+ const stroke = "var(--term-box-stroke)";
1243
+ const verticalLength = `calc(50% + ${stroke})`;
1244
+ const horizontalLength = `calc(50% + ${stroke})`;
1245
+ for (const [codepoint, arms] of Object.entries(characters)) {
1246
+ const selected = [];
1247
+ if (arms.includes("u") && arms.includes("d")) selected.push(["center center", `${stroke} 100%`]);
1248
+ else {
1249
+ if (arms.includes("u")) selected.push(["center top", `${stroke} ${verticalLength}`]);
1250
+ if (arms.includes("d")) selected.push(["center bottom", `${stroke} ${verticalLength}`]);
1251
+ }
1252
+ if (arms.includes("l") && arms.includes("r")) selected.push(["center center", `100% ${stroke}`]);
1253
+ else {
1254
+ if (arms.includes("l")) selected.push(["left center", `${horizontalLength} ${stroke}`]);
1255
+ if (arms.includes("r")) selected.push(["right center", `${horizontalLength} ${stroke}`]);
1256
+ }
1257
+ BOX_STYLES[Number(codepoint)] = {
1258
+ className,
1259
+ style: `background-image:${selected.map(() => "linear-gradient(currentColor,currentColor)").join(",")};background-position:${selected.map(([position]) => position).join(",")};background-size:${selected.map(([, size]) => size).join(",")};background-repeat:no-repeat;`
1260
+ };
1261
+ }
1262
+ }
1263
+ addBoxStyles(LIGHT_BOX_ARMS, "term-box");
1264
+ addBoxStyles(HEAVY_BOX_ARMS, "term-box term-box-heavy");
1265
+ for (const [codepoint, corner] of Object.entries(ROUNDED_BOX_CORNERS)) BOX_STYLES[Number(codepoint)] = {
1266
+ className: `term-box term-box-round term-box-round-${corner}`,
1267
+ style: ""
1268
+ };
1269
+ var Renderer = class {
1270
+ get hasImageFlow() {
1271
+ return this.container.parentElement?.classList.contains("has-image-flow") ?? false;
1272
+ }
1273
+ constructor(container, options = {}) {
1274
+ this.rows = 0;
1275
+ this.cols = 0;
1276
+ this.rowEls = [];
1277
+ this.prevCursorRow = -1;
1278
+ this.prevCursorCol = -1;
1279
+ this.prevCursorVisible = false;
1280
+ this.prevRowBg = [];
1281
+ this._scrollbackRowEls = [];
1282
+ this._scrollbackKeys = [];
1283
+ this._scrollbackRowHeight = 0;
1284
+ this._scrollbackGapSpacers = [];
1285
+ this._renderedScrollbackCount = -1;
1286
+ this._renderedDiscardedCount = -1;
1287
+ this._scrollbackTopSpacer = null;
1288
+ this._scrollbackBottomSpacer = null;
1289
+ this.rowText = /* @__PURE__ */ new WeakMap();
1290
+ this.rowParts = /* @__PURE__ */ new WeakMap();
1291
+ this.rowBackground = /* @__PURE__ */ new WeakMap();
1292
+ this.selection = null;
1293
+ this.needsSetup = false;
1294
+ this.colorsChanged = false;
1295
+ this.painted = false;
1296
+ this.container = container;
1297
+ this.colorHost = options.colorHost ?? container;
1298
+ this.graphics = new GraphicsLayer(container, options);
1299
+ this.searchLayer = document.createElement("div");
1300
+ this.searchLayer.className = "term-search-layer";
1301
+ this.searchLayer.setAttribute("aria-hidden", "true");
1302
+ }
1303
+ setup(cols, rows) {
1304
+ this.cols = cols;
1305
+ this.rows = rows;
1306
+ this.container.innerHTML = "";
1307
+ this.rowText = /* @__PURE__ */ new WeakMap();
1308
+ this.rowParts = /* @__PURE__ */ new WeakMap();
1309
+ this.rowBackground = /* @__PURE__ */ new WeakMap();
1310
+ this.rowEls = [];
1311
+ this.prevRowBg = [];
1312
+ this._scrollbackRowEls = [];
1313
+ this._scrollbackKeys = [];
1314
+ this._scrollbackGapSpacers = [];
1315
+ this._renderedScrollbackCount = -1;
1316
+ this._renderedDiscardedCount = -1;
1317
+ const fragment = document.createDocumentFragment();
1318
+ this._scrollbackTopSpacer = document.createElement("div");
1319
+ this._scrollbackTopSpacer.className = "term-scrollback-spacer";
1320
+ fragment.appendChild(this._scrollbackTopSpacer);
1321
+ this._scrollbackBottomSpacer = document.createElement("div");
1322
+ this._scrollbackBottomSpacer.className = "term-scrollback-spacer";
1323
+ fragment.appendChild(this._scrollbackBottomSpacer);
1324
+ for (let r = 0; r < rows; r++) {
1325
+ const rowEl = document.createElement("div");
1326
+ rowEl.className = "term-row";
1327
+ fragment.appendChild(rowEl);
1328
+ this.rowEls.push(rowEl);
1329
+ }
1330
+ this.container.appendChild(fragment);
1331
+ this.searchLayer.replaceChildren();
1332
+ this.container.appendChild(this.searchLayer);
1333
+ this.graphics.setup();
1334
+ this.prevCursorRow = -1;
1335
+ this.prevCursorCol = -1;
1336
+ }
1337
+ _buildRowContent(rowEl, getCell, lineLen, cursorCol, rowIndex) {
1338
+ const parts = [];
1339
+ let linkHtml = "";
1340
+ const content = {
1341
+ text: "",
1342
+ specialCells: [],
1343
+ metadata: null
1344
+ };
1345
+ const recordText = (text, col, width = 1, omit = false) => {
1346
+ const start = content.text.length;
1347
+ content.text += text;
1348
+ if (text.length !== width || width > 1 || omit) content.specialCells.push({
1349
+ start,
1350
+ end: content.text.length,
1351
+ col,
1352
+ width,
1353
+ omit
1354
+ });
1355
+ };
1356
+ let runStyle = "";
1357
+ let runText = "";
1358
+ let runCells = [];
1359
+ let runStart = 0;
1360
+ let runLinkKey = "";
1361
+ let runLinkUri;
1362
+ let outputLinkKey = "";
1363
+ let rowBackground;
1364
+ let uniformBackground = lineLen >= this.cols;
1365
+ const appendContent = (content, linkKey, uri) => {
1366
+ const href = safeLinkHref(uri);
1367
+ const nextLinkKey = href ? linkKey : "";
1368
+ if (nextLinkKey !== outputLinkKey) {
1369
+ if (outputLinkKey) parts.push({ html: linkHtml + "</a>" });
1370
+ if (nextLinkKey) linkHtml = `<a class="term-link" href="${escapeHTML(href)}" target="_blank" rel="noopener noreferrer">`;
1371
+ outputLinkKey = nextLinkKey;
1372
+ }
1373
+ if (outputLinkKey) linkHtml += content.html;
1374
+ else parts.push(content);
1375
+ };
1376
+ const flushRun = (endCol) => {
1377
+ if (!runText) return;
1378
+ const append = (className, style, text) => appendContent(cellSpanPart(className, style, text), runLinkKey, runLinkUri);
1379
+ if (cursorCol >= runStart && cursorCol < endCol) {
1380
+ const offset = cursorCol - runStart;
1381
+ const before = runCells.slice(0, offset).join("");
1382
+ const cursorChar = runCells[offset] || " ";
1383
+ const after = runCells.slice(offset + 1).join("");
1384
+ if (before) append("", columnStyle(offset) + runStyle, before);
1385
+ append("term-cursor", cursorCellStyle(runStyle), cursorChar);
1386
+ if (after) append("", columnStyle(runCells.length - offset - 1) + runStyle, after);
1387
+ } else append("", columnStyle(runCells.length) + runStyle, runText);
1388
+ runText = "";
1389
+ runCells = [];
1390
+ };
1391
+ const appendStyledSpan = (className, style, text, linkKey, linkUri) => {
1392
+ appendContent(cellSpanPart(className, style, text), linkKey, linkUri);
1393
+ };
1394
+ for (let col = 0; col < this.cols; col++) {
1395
+ const cell = getCell(col);
1396
+ const inBounds = col < lineLen;
1397
+ const cp = inBounds ? cell.char : 0;
1398
+ const width = inBounds ? cell.width ?? 1 : 1;
1399
+ const cellLinkKey = inBounds ? linkIdentity(cell) : "";
1400
+ const cellLinkUri = inBounds ? cell.linkUri : void 0;
1401
+ const continuesWide = inBounds && width === 0 && col > 0 && (getCell(col - 1).width ?? 1) === 2;
1402
+ if (uniformBackground && !continuesWide) {
1403
+ const bg = resolveColors(cell.fg, cell.bg, cell.flags, cell.fgRgb, cell.bgRgb).bg;
1404
+ if (cell.flags & 66 || rowBackground !== void 0 && rowBackground !== bg) uniformBackground = false;
1405
+ else rowBackground = bg;
1406
+ }
1407
+ if (inBounds && width === 0) {
1408
+ flushRun(col);
1409
+ if (!continuesWide) {
1410
+ recordText(" ", col);
1411
+ const style = buildCellStyle(cell);
1412
+ const cursor = col === cursorCol;
1413
+ appendStyledSpan(cursor ? "term-cursor" : "", cursor ? cursorCellStyle(style) : style, " ", cellLinkKey, cellLinkUri);
1414
+ }
1415
+ runStyle = "";
1416
+ runLinkKey = "";
1417
+ runLinkUri = void 0;
1418
+ runText = "";
1419
+ runCells = [];
1420
+ runStart = col + 1;
1421
+ continue;
1422
+ }
1423
+ if (inBounds && width === 2) {
1424
+ flushRun(col);
1425
+ if (col + 1 >= this.cols) {
1426
+ recordText(" ", col);
1427
+ const style = buildCellStyle(cell);
1428
+ const cursor = col === cursorCol;
1429
+ appendStyledSpan(cursor ? "term-cursor" : "", cursor ? cursorCellStyle(style) : style, " ", cellLinkKey, cellLinkUri);
1430
+ runStyle = "";
1431
+ runLinkKey = "";
1432
+ runLinkUri = void 0;
1433
+ runText = "";
1434
+ runCells = [];
1435
+ runStart = col + 1;
1436
+ continue;
1437
+ }
1438
+ const ch = cell.chars ?? (cp >= 32 ? String.fromCodePoint(cp) : " ");
1439
+ recordText(ch, col, 2);
1440
+ const style = buildCellStyle(cell);
1441
+ const cursor = cursorCol >= col && cursorCol < col + 2;
1442
+ appendStyledSpan(cursor ? "term-wide term-cursor" : "term-wide", cursor ? cursorCellStyle(style) : style, ch, cellLinkKey, cellLinkUri);
1443
+ runStyle = "";
1444
+ runLinkKey = "";
1445
+ runLinkUri = void 0;
1446
+ runText = "";
1447
+ runCells = [];
1448
+ runStart = col + 2;
1449
+ continue;
1450
+ }
1451
+ if (inBounds && cp >= 9600 && cp <= 9631) {
1452
+ flushRun(col);
1453
+ const ch = cell.chars ?? String.fromCodePoint(cp);
1454
+ recordText(ch, col);
1455
+ const colors = resolveColors(cell.fg, cell.bg, cell.flags, cell.fgRgb, cell.bgRgb);
1456
+ const cls = col === cursorCol ? "term-block term-cursor" : "term-block";
1457
+ const bg = getBlockBackground(cp, colors.fg, colors.bg);
1458
+ const style = buildCellStyle(cell) + `color:${colors.fg};background:${bg};`;
1459
+ appendStyledSpan(cls, col === cursorCol ? cursorCellStyle(style) : style, ch, cellLinkKey, cellLinkUri);
1460
+ runStyle = "";
1461
+ runLinkKey = "";
1462
+ runLinkUri = void 0;
1463
+ runText = "";
1464
+ runCells = [];
1465
+ runStart = col + 1;
1466
+ } else {
1467
+ const ch = cell.chars ?? (inBounds && cp >= 32 ? String.fromCodePoint(cp) : " ");
1468
+ recordText(ch, col, 1, cell.spacerHead === true);
1469
+ const style = inBounds ? buildCellStyle(cell) : "";
1470
+ if (ch.length !== 1 || ch.charCodeAt(0) > 126) {
1471
+ flushRun(col);
1472
+ const cursor = col === cursorCol;
1473
+ const box = BOX_STYLES[cp];
1474
+ const boxStyle = box && ch === String.fromCodePoint(cp) ? box : null;
1475
+ let className = boxStyle?.className ?? "";
1476
+ if (boxStyle && cell.flags & FLAG_BOLD) className += " term-box-bold";
1477
+ if (cursor) className += className ? " term-cursor" : "term-cursor";
1478
+ appendStyledSpan(className, (cursor ? cursorCellStyle(style) : style) + (boxStyle?.style ?? ""), ch, cellLinkKey, cellLinkUri);
1479
+ runStyle = "";
1480
+ runLinkKey = "";
1481
+ runLinkUri = void 0;
1482
+ runStart = col + 1;
1483
+ continue;
1484
+ }
1485
+ if (style !== runStyle || cellLinkKey !== runLinkKey) {
1486
+ flushRun(col);
1487
+ runStyle = style;
1488
+ runLinkKey = cellLinkKey;
1489
+ runLinkUri = cellLinkUri;
1490
+ runText = ch;
1491
+ runCells = [ch];
1492
+ runStart = col;
1493
+ } else {
1494
+ runText += ch;
1495
+ runCells.push(ch);
1496
+ }
1497
+ }
1498
+ }
1499
+ flushRun(this.cols);
1500
+ if (outputLinkKey) parts.push({ html: linkHtml + "</a>" });
1501
+ this.updateRowParts(rowEl, parts);
1502
+ this.rowText.set(rowEl, content);
1503
+ const bgCss = uniformBackground && rowBackground !== DEFAULT_BG_CSS ? rowBackground ?? "" : "";
1504
+ if (rowIndex >= 0) {
1505
+ if (bgCss !== (this.prevRowBg[rowIndex] ?? "")) {
1506
+ rowEl.style.background = bgCss;
1507
+ this.prevRowBg[rowIndex] = bgCss;
1508
+ }
1509
+ } else if (this.rowBackground.get(rowEl) !== bgCss) {
1510
+ rowEl.style.background = bgCss;
1511
+ this.rowBackground.set(rowEl, bgCss);
1512
+ }
1513
+ }
1514
+ updateRowParts(row, parts) {
1515
+ const previous = this.rowParts.get(row);
1516
+ let start = 0;
1517
+ let oldEnd = previous?.length ?? 0;
1518
+ let newEnd = parts.length;
1519
+ if (previous) {
1520
+ while (start < oldEnd && start < newEnd && previous[start].html === parts[start].html) start++;
1521
+ while (oldEnd > start && newEnd > start && previous[oldEnd - 1].html === parts[newEnd - 1].html) {
1522
+ oldEnd--;
1523
+ newEnd--;
1524
+ }
1525
+ }
1526
+ if (start === oldEnd && start === newEnd) return;
1527
+ let textOnly = previous !== void 0 && oldEnd === newEnd;
1528
+ for (let i = start; textOnly && i < newEnd; i++) {
1529
+ const child = row.childNodes[i];
1530
+ textOnly = parts[i].opening !== void 0 && parts[i].opening === previous[i].opening && child?.childNodes.length === 1 && child.firstChild?.nodeType === 3;
1531
+ }
1532
+ if (textOnly) {
1533
+ for (let i = start; i < newEnd; i++) if (parts[i].html !== previous[i].html) row.childNodes[i].firstChild.nodeValue = parts[i].text;
1534
+ this.rowParts.set(row, parts);
1535
+ return;
1536
+ }
1537
+ if (start + parts.length - newEnd < Math.max(oldEnd - start, newEnd - start)) row.innerHTML = parts.map((part) => part.html).join("");
1538
+ else {
1539
+ const range = row.ownerDocument.createRange();
1540
+ range.setStart(row, start);
1541
+ range.setEnd(row, oldEnd);
1542
+ range.deleteContents();
1543
+ const html = parts.slice(start, newEnd).map((part) => part.html).join("");
1544
+ if (html) range.insertNode(range.createContextualFragment(html));
1545
+ }
1546
+ this.rowParts.set(row, parts);
1547
+ }
1548
+ _updateScrollbackRow(core, sbOffset, rowEl) {
1549
+ const lineLen = core.getScrollbackLineLen(sbOffset);
1550
+ this._buildRowContent(rowEl, (col) => core.getScrollbackCell(sbOffset, col), lineLen, -1, -1);
1551
+ const content = this.rowText.get(rowEl);
1552
+ const metadata = core.getScrollbackRowMetadata?.(sbOffset);
1553
+ content.metadata = metadata && lineLen <= this.cols ? { ...metadata } : null;
1554
+ }
1555
+ syncScrollback(core, viewport) {
1556
+ const scrollbackCount = core.getScrollbackCount();
1557
+ const rowHeight = viewport?.rowHeight ?? 0;
1558
+ const virtual = viewport !== void 0 && rowHeight > 0;
1559
+ const overscan = viewport?.overscanRows ?? DEFAULT_SCROLLBACK_OVERSCAN_ROWS;
1560
+ const hasDiscardedCount = viewport?.scrollbackDiscardedCount !== void 0;
1561
+ const discardedCount = viewport?.scrollbackDiscardedCount ?? 0;
1562
+ const viewportHeight = viewport && viewport.clientHeight > 0 ? viewport.clientHeight : this.rows * rowHeight;
1563
+ const firstVisible = virtual ? Math.floor(viewport.scrollTop / rowHeight) : 0;
1564
+ const visibleRows = virtual ? Math.ceil(viewportHeight / rowHeight) : scrollbackCount;
1565
+ const start = virtual ? Math.max(0, Math.min(scrollbackCount, firstVisible - overscan)) : 0;
1566
+ const end = virtual ? Math.max(start, Math.min(scrollbackCount, firstVisible + visibleRows + overscan)) : scrollbackCount;
1567
+ const selection = this.container.ownerDocument.getSelection();
1568
+ const selectionInContainer = selection !== null && !selection.isCollapsed && (this.container.contains(selection.anchorNode) || this.container.contains(selection.focusNode));
1569
+ const contentUnchanged = this.painted && !this.colorsChanged && hasDiscardedCount && scrollbackCount === this._renderedScrollbackCount && discardedCount === this._renderedDiscardedCount;
1570
+ const first = (this._scrollbackKeys[0] ?? Infinity) - discardedCount;
1571
+ const last = (this._scrollbackKeys[this._scrollbackKeys.length - 1] ?? -Infinity) - discardedCount + 1;
1572
+ const margin = Math.ceil(overscan / 2);
1573
+ if (virtual && contentUnchanged && !selectionInContainer && !viewport?.selectedRows && rowHeight === this._scrollbackRowHeight && this._scrollbackKeys.length === last - first && this._scrollbackKeys.length <= visibleRows + 2 * overscan && first <= Math.max(0, Math.min(scrollbackCount, firstVisible - margin)) && last >= Math.min(scrollbackCount, firstVisible + visibleRows + margin)) return;
1574
+ const indices = /* @__PURE__ */ new Set();
1575
+ for (let index = start; index < end; index++) indices.add(index);
1576
+ if (!viewport?.selectedRows && selectionInContainer && selection.rangeCount === 1) {
1577
+ const range = selection.getRangeAt(0);
1578
+ const selected = this._scrollbackRowEls.flatMap((row, i) => range.intersectsNode(row) ? [this._scrollbackKeys[i] - discardedCount] : []);
1579
+ if (selected.length <= MAX_TRACKED_SELECTION_ROWS) {
1580
+ for (const index of selected) if (index >= 0 && index < scrollbackCount) indices.add(index);
1581
+ }
1582
+ }
1583
+ if (viewport?.selectedRows) for (let index = Math.max(0, viewport.selectedRows.start); index <= Math.min(scrollbackCount - 1, viewport.selectedRows.end); index++) indices.add(index);
1584
+ const ordered = Array.from(indices).sort((a, b) => a - b);
1585
+ const keys = ordered.map((index) => discardedCount + index);
1586
+ if (contentUnchanged && rowHeight === this._scrollbackRowHeight && keys.length === this._scrollbackKeys.length && keys.every((key, index) => key === this._scrollbackKeys[index])) return;
1587
+ const previous = /* @__PURE__ */ new Map();
1588
+ for (let i = 0; i < this._scrollbackRowEls.length; i++) previous.set(this._scrollbackKeys[i], this._scrollbackRowEls[i]);
1589
+ const retained = new Set(keys);
1590
+ for (const [key, rowEl] of previous) if (!retained.has(key)) rowEl.remove();
1591
+ for (const spacer of this._scrollbackGapSpacers) spacer.remove();
1592
+ this._scrollbackGapSpacers = [];
1593
+ const nextRows = [];
1594
+ let nextSibling = this._scrollbackTopSpacer?.nextSibling ?? null;
1595
+ let previousIndex = (ordered[0] ?? scrollbackCount) - 1;
1596
+ for (const index of ordered) {
1597
+ if (index > previousIndex + 1) {
1598
+ const spacer = document.createElement("div");
1599
+ spacer.className = "term-scrollback-spacer";
1600
+ spacer.style.height = `${(index - previousIndex - 1) * rowHeight}px`;
1601
+ this.container.insertBefore(spacer, nextSibling ?? this._scrollbackBottomSpacer);
1602
+ this._scrollbackGapSpacers.push(spacer);
1603
+ }
1604
+ previousIndex = index;
1605
+ const key = discardedCount + index;
1606
+ const offset = scrollbackCount - 1 - index;
1607
+ let rowEl = previous.get(key);
1608
+ if (!rowEl) {
1609
+ rowEl = document.createElement("div");
1610
+ rowEl.className = "term-row term-scrollback-row";
1611
+ this._updateScrollbackRow(core, offset, rowEl);
1612
+ } else if (!contentUnchanged) this._updateScrollbackRow(core, offset, rowEl);
1613
+ if (rowEl !== nextSibling) this.container.insertBefore(rowEl, nextSibling ?? this._scrollbackBottomSpacer);
1614
+ nextSibling = rowEl.nextSibling;
1615
+ nextRows.push(rowEl);
1616
+ }
1617
+ this._scrollbackRowEls = nextRows;
1618
+ this._scrollbackKeys = keys;
1619
+ this._renderedScrollbackCount = scrollbackCount;
1620
+ this._renderedDiscardedCount = discardedCount;
1621
+ this._scrollbackRowHeight = rowHeight;
1622
+ if (this._scrollbackTopSpacer) this._scrollbackTopSpacer.style.height = `${(ordered[0] ?? scrollbackCount) * rowHeight}px`;
1623
+ if (this._scrollbackBottomSpacer) this._scrollbackBottomSpacer.style.height = `${ordered.length ? (scrollbackCount - ordered[ordered.length - 1] - 1) * rowHeight : 0}px`;
1624
+ }
1625
+ syncColorOverrides(colors = {}) {
1626
+ for (const [key, property] of [
1627
+ ["foreground", "--term-app-fg"],
1628
+ ["background", "--term-app-bg"],
1629
+ ["cursor", "--term-app-cursor"]
1630
+ ]) {
1631
+ const value = colors[key];
1632
+ const css = value === void 0 ? "" : rgbToCSS(value);
1633
+ if (this.colorHost.style.getPropertyValue(property) === css) continue;
1634
+ if (css) this.colorHost.style.setProperty(property, css);
1635
+ else this.colorHost.style.removeProperty(property);
1636
+ }
1637
+ }
1638
+ render(core, viewport) {
1639
+ this.syncColorOverrides(core.getColorOverrides?.());
1640
+ this.viewport = viewport;
1641
+ this.selection ?? (this.selection = new TrackedSelection(this.container.parentElement ?? this.container));
1642
+ const positions = this.selection.beforeRender(core, this.selectionRows());
1643
+ const rows = core.getRows();
1644
+ const cols = core.getCols();
1645
+ let resized = false;
1646
+ if (this.needsSetup || rows !== this.rows || cols !== this.cols) {
1647
+ this.setup(cols, rows);
1648
+ this.needsSetup = false;
1649
+ resized = true;
1650
+ }
1651
+ this.syncScrollback(core, viewport && {
1652
+ ...viewport,
1653
+ selectedRows: positions ? {
1654
+ start: positions.start.row,
1655
+ end: positions.end.row
1656
+ } : void 0
1657
+ });
1658
+ const cursor = core.getCursor();
1659
+ const cursorVisible = cursor.visible;
1660
+ const shape = cursor.shape ?? "block";
1661
+ const blink = String(cursor.blinking ?? false);
1662
+ if (this.container.dataset.cursorShape !== shape) this.container.dataset.cursorShape = shape;
1663
+ if (this.container.dataset.cursorBlink !== blink) this.container.dataset.cursorBlink = blink;
1664
+ const needsCursorUpdate = cursor.row !== this.prevCursorRow || cursor.col !== this.prevCursorCol || cursorVisible !== this.prevCursorVisible;
1665
+ for (let r = 0; r < this.rows; r++) {
1666
+ const isDirty = this.colorsChanged || resized || core.isDirtyRow(r);
1667
+ const hadCursor = r === this.prevCursorRow && needsCursorUpdate;
1668
+ const hasCursor = r === cursor.row;
1669
+ if (isDirty || hadCursor || hasCursor && needsCursorUpdate) {
1670
+ const cCol = hasCursor && cursorVisible ? cursor.col : -1;
1671
+ this._buildRowContent(this.rowEls[r], (col) => core.getCell(r, col), this.cols, cCol, r);
1672
+ }
1673
+ const content = this.rowText.get(this.rowEls[r]);
1674
+ if (content) {
1675
+ const metadata = core.getRowMetadata?.(r);
1676
+ content.metadata = metadata ? { ...metadata } : null;
1677
+ }
1678
+ }
1679
+ this.prevCursorRow = cursor.row;
1680
+ this.prevCursorCol = cursor.col;
1681
+ this.prevCursorVisible = cursorVisible;
1682
+ core.clearDirty();
1683
+ this.colorsChanged = false;
1684
+ this.selection.afterRender(this.selectionRows(), positions);
1685
+ this.painted = true;
1686
+ this.graphics.reconcile(core, {
1687
+ scrollTop: viewport?.scrollTop ?? 0,
1688
+ clientHeight: viewport?.clientHeight ?? 0,
1689
+ rowHeight: viewport?.rowHeight ?? 0,
1690
+ charWidth: viewport?.charWidth ?? 0,
1691
+ overscanRows: viewport?.overscanRows ?? DEFAULT_SCROLLBACK_OVERSCAN_ROWS,
1692
+ scrollbackCount: core.getScrollbackCount()
1693
+ });
1694
+ }
1695
+ /** Mounted rows in chronological, retained-buffer coordinates. */
1696
+ *searchRows() {
1697
+ for (let i = 0; i < this._scrollbackRowEls.length; i++) yield {
1698
+ row: this._scrollbackKeys[i] - Math.max(0, this._renderedDiscardedCount),
1699
+ element: this._scrollbackRowEls[i]
1700
+ };
1701
+ for (let i = 0; i < this.rowEls.length; i++) yield {
1702
+ row: Math.max(0, this._renderedScrollbackCount) + i,
1703
+ element: this.rowEls[i]
1704
+ };
1705
+ }
1706
+ /** Plain text for the native selection, or null when this terminal does not own it. */
1707
+ getSelectionText() {
1708
+ const terminal = this.container.parentElement;
1709
+ if (!terminal) return null;
1710
+ return getSelectionText(terminal, this.selectionRows());
1711
+ }
1712
+ *selectionRows() {
1713
+ for (const row of this.searchRows()) {
1714
+ const content = this.rowText.get(row.element);
1715
+ if (content) yield {
1716
+ ...row,
1717
+ content
1718
+ };
1719
+ }
1720
+ }
1721
+ beforeMutation(core) {
1722
+ this.selection?.beforeMutation(core, this.selectionRows());
1723
+ this.painted = false;
1724
+ }
1725
+ /** Resolve a mounted row hit using cell geometry, including wide glyphs. */
1726
+ positionAt(target, clientX, charWidth) {
1727
+ if (!this.painted || this.needsSetup || charWidth <= 0) return null;
1728
+ const element = target.closest(".term-row");
1729
+ const mounted = Array.from(this.searchRows()).find((row) => row.element === element);
1730
+ if (!mounted) return null;
1731
+ const col = Math.floor((clientX - mounted.element.getBoundingClientRect().left) / charWidth);
1732
+ return col >= 0 && col < this.cols ? {
1733
+ row: mounted.row,
1734
+ col
1735
+ } : null;
1736
+ }
1737
+ select(core, position, unit, beforeSelect) {
1738
+ if (!this.painted || this.needsSetup) return false;
1739
+ const range = selectionRange(core, position, unit);
1740
+ if (!range) return false;
1741
+ beforeSelect();
1742
+ if (!this.painted || this.needsSetup) return false;
1743
+ this.syncScrollback(core, {
1744
+ ...this.viewport ?? {
1745
+ scrollTop: 0,
1746
+ clientHeight: 0,
1747
+ rowHeight: 0
1748
+ },
1749
+ selectedRows: {
1750
+ start: range.start.row,
1751
+ end: range.end.row
1752
+ }
1753
+ });
1754
+ const mounted = Array.from(this.selectionRows());
1755
+ const edge = (position, after) => {
1756
+ const row = mounted.find((row) => row.row === position.row);
1757
+ return row && textPoint(row.element, offsetAtCell(row.content, position.col, after));
1758
+ };
1759
+ const start = edge(range.start, false), end = edge(range.end, true);
1760
+ const native = this.container.ownerDocument.getSelection();
1761
+ if (!start || !end || !native) return false;
1762
+ native.setBaseAndExtent(...start, ...end);
1763
+ this.selection?.capture(core, this.selectionRows());
1764
+ return true;
1765
+ }
1766
+ rectangle(core, start, end, beforeSelect) {
1767
+ if (!this.painted || this.needsSetup) return null;
1768
+ const rectangle = rectangleSelection(core, start, end);
1769
+ if (!rectangle) return null;
1770
+ beforeSelect();
1771
+ return this.painted && !this.needsSetup ? rectangle : null;
1772
+ }
1773
+ /** Clamp a drag to the nearest mounted row without mounting extra history. */
1774
+ dragPositionAt(clientX, clientY, charWidth) {
1775
+ if (!this.painted || this.needsSetup || charWidth <= 0) return null;
1776
+ let nearest = null;
1777
+ for (const { row, element } of this.searchRows()) {
1778
+ const rect = element.getBoundingClientRect();
1779
+ const distance = Math.max(rect.top - clientY, clientY - rect.bottom, 0);
1780
+ if (!nearest || distance < nearest.distance) nearest = {
1781
+ row,
1782
+ distance,
1783
+ col: Math.max(0, Math.min(this.cols - 1, Math.floor((clientX - rect.left) / charWidth)))
1784
+ };
1785
+ }
1786
+ return nearest && {
1787
+ row: nearest.row,
1788
+ col: nearest.col
1789
+ };
1790
+ }
1791
+ requestSetup() {
1792
+ this.needsSetup = true;
1793
+ }
1794
+ /** Re-read indexed colors in live and retained rows without rebuilding the grid. */
1795
+ invalidateColors() {
1796
+ this.colorsChanged = true;
1797
+ }
1798
+ /** Replaces decorations only, preserving native text selection. */
1799
+ setSearchDecorations(decorations) {
1800
+ if (!decorations.firstChild && !this.searchLayer.firstChild) return;
1801
+ this.searchLayer.replaceChildren(decorations);
1802
+ }
1803
+ destroy() {
1804
+ this.syncColorOverrides();
1805
+ this.painted = false;
1806
+ this.selection?.dispose();
1807
+ this.graphics.destroy();
1808
+ this.container.innerHTML = "";
1809
+ this.rowEls = [];
1810
+ this._scrollbackRowEls = [];
1811
+ }
1812
+ };
1813
+ //#endregion
1814
+ //#region ../../node_modules/.pnpm/@wterm+dom@0.5.4/node_modules/@wterm/dom/dist/input-accessibility.js
1815
+ var LABEL_ATTRIBUTES = [
1816
+ "aria-label",
1817
+ "aria-labelledby",
1818
+ "aria-describedby",
1819
+ "aria-description"
1820
+ ];
1821
+ var KEYBOARD_EXIT_HINT = "Press Escape, then Tab to move focus out of the terminal, or Shift+Tab to move focus backward.";
1822
+ var nextHintId = 0;
1823
+ /** Keep host-provided names and tab order on the element receiving input. */
1824
+ var InputAccessibility = class {
1825
+ constructor(host, input) {
1826
+ this.host = host;
1827
+ this.input = input;
1828
+ this.destroyed = false;
1829
+ this.hint = host.ownerDocument.createElement("span");
1830
+ do
1831
+ this.hint.id = `wterm-input-help-${++nextHintId}`;
1832
+ while (host.getRootNode().querySelector(`#${this.hint.id}`));
1833
+ this.hint.hidden = true;
1834
+ this.hint.textContent = KEYBOARD_EXIT_HINT;
1835
+ host.append(this.hint);
1836
+ this.tabIndex = host.getAttribute("tabindex");
1837
+ this.defaultRole = !host.hasAttribute("role");
1838
+ if (this.defaultRole) host.setAttribute("role", "group");
1839
+ this.observer = new MutationObserver((records) => this.sync(records));
1840
+ this.sync();
1841
+ }
1842
+ sync(records = []) {
1843
+ if (records.some((record) => record.attributeName === "tabindex")) this.tabIndex = this.host.getAttribute("tabindex");
1844
+ for (const attribute of LABEL_ATTRIBUTES) {
1845
+ const value = this.host.getAttribute(attribute);
1846
+ if (value?.trim()) this.input.setAttribute(attribute, value);
1847
+ else this.input.removeAttribute(attribute);
1848
+ }
1849
+ if (!this.input.hasAttribute("aria-label")) this.input.setAttribute("aria-label", "Terminal");
1850
+ const describedBy = this.input.getAttribute("aria-describedby");
1851
+ if (describedBy) this.input.setAttribute("aria-describedby", `${describedBy} ${this.hint.id}`);
1852
+ this.input.setAttribute("aria-description", [this.input.getAttribute("aria-description"), KEYBOARD_EXIT_HINT].filter(Boolean).join(" "));
1853
+ this.input.setAttribute("tabindex", this.tabIndex ?? "0");
1854
+ this.observer.disconnect();
1855
+ if (this.tabIndex !== null) this.host.setAttribute("tabindex", "-1");
1856
+ this.observer.observe(this.host, {
1857
+ attributes: true,
1858
+ attributeFilter: [...LABEL_ATTRIBUTES, "tabindex"]
1859
+ });
1860
+ }
1861
+ destroy() {
1862
+ if (this.destroyed) return;
1863
+ this.destroyed = true;
1864
+ if (this.observer.takeRecords().some((record) => record.attributeName === "tabindex")) this.tabIndex = this.host.getAttribute("tabindex");
1865
+ this.observer.disconnect();
1866
+ this.hint.remove();
1867
+ if (this.tabIndex === null) this.host.removeAttribute("tabindex");
1868
+ else this.host.setAttribute("tabindex", this.tabIndex);
1869
+ if (this.defaultRole && this.host.getAttribute("role") === "group") this.host.removeAttribute("role");
1870
+ }
1871
+ };
1872
+ //#endregion
1873
+ //#region ../../node_modules/.pnpm/@wterm+dom@0.5.4/node_modules/@wterm/dom/dist/hyperlink.js
1874
+ function isLinkActivationModifier(event, navigator) {
1875
+ return navigator.platform.startsWith("Mac") ? event.metaKey : event.ctrlKey;
1876
+ }
1877
+ var FUNCTIONAL_KEYS = {
1878
+ Escape: {
1879
+ code: 27,
1880
+ final: "u"
1881
+ },
1882
+ Enter: {
1883
+ code: 13,
1884
+ final: "u"
1885
+ },
1886
+ Tab: {
1887
+ code: 9,
1888
+ final: "u"
1889
+ },
1890
+ Backspace: {
1891
+ code: 127,
1892
+ final: "u"
1893
+ },
1894
+ Insert: {
1895
+ code: 2,
1896
+ final: "~"
1897
+ },
1898
+ Delete: {
1899
+ code: 3,
1900
+ final: "~"
1901
+ },
1902
+ ArrowLeft: {
1903
+ code: 1,
1904
+ final: "D"
1905
+ },
1906
+ ArrowRight: {
1907
+ code: 1,
1908
+ final: "C"
1909
+ },
1910
+ ArrowUp: {
1911
+ code: 1,
1912
+ final: "A"
1913
+ },
1914
+ ArrowDown: {
1915
+ code: 1,
1916
+ final: "B"
1917
+ },
1918
+ PageUp: {
1919
+ code: 5,
1920
+ final: "~"
1921
+ },
1922
+ PageDown: {
1923
+ code: 6,
1924
+ final: "~"
1925
+ },
1926
+ Home: {
1927
+ code: 1,
1928
+ final: "H"
1929
+ },
1930
+ End: {
1931
+ code: 1,
1932
+ final: "F"
1933
+ },
1934
+ CapsLock: {
1935
+ code: 57358,
1936
+ final: "u",
1937
+ modifier: true
1938
+ },
1939
+ ScrollLock: {
1940
+ code: 57359,
1941
+ final: "u"
1942
+ },
1943
+ NumLock: {
1944
+ code: 57360,
1945
+ final: "u",
1946
+ modifier: true
1947
+ },
1948
+ PrintScreen: {
1949
+ code: 57361,
1950
+ final: "u"
1951
+ },
1952
+ Pause: {
1953
+ code: 57362,
1954
+ final: "u"
1955
+ },
1956
+ F1: {
1957
+ code: 1,
1958
+ final: "P"
1959
+ },
1960
+ F2: {
1961
+ code: 1,
1962
+ final: "Q"
1963
+ },
1964
+ F3: {
1965
+ code: 13,
1966
+ final: "~"
1967
+ },
1968
+ F4: {
1969
+ code: 1,
1970
+ final: "S"
1971
+ },
1972
+ F5: {
1973
+ code: 15,
1974
+ final: "~"
1975
+ },
1976
+ F6: {
1977
+ code: 17,
1978
+ final: "~"
1979
+ },
1980
+ F7: {
1981
+ code: 18,
1982
+ final: "~"
1983
+ },
1984
+ F8: {
1985
+ code: 19,
1986
+ final: "~"
1987
+ },
1988
+ F9: {
1989
+ code: 20,
1990
+ final: "~"
1991
+ },
1992
+ F10: {
1993
+ code: 21,
1994
+ final: "~"
1995
+ },
1996
+ F11: {
1997
+ code: 23,
1998
+ final: "~"
1999
+ },
2000
+ F12: {
2001
+ code: 24,
2002
+ final: "~"
2003
+ },
2004
+ ShiftLeft: {
2005
+ code: 57441,
2006
+ final: "u",
2007
+ modifier: true
2008
+ },
2009
+ ControlLeft: {
2010
+ code: 57442,
2011
+ final: "u",
2012
+ modifier: true
2013
+ },
2014
+ AltLeft: {
2015
+ code: 57443,
2016
+ final: "u",
2017
+ modifier: true
2018
+ },
2019
+ MetaLeft: {
2020
+ code: 57444,
2021
+ final: "u",
2022
+ modifier: true
2023
+ },
2024
+ ShiftRight: {
2025
+ code: 57447,
2026
+ final: "u",
2027
+ modifier: true
2028
+ },
2029
+ ControlRight: {
2030
+ code: 57448,
2031
+ final: "u",
2032
+ modifier: true
2033
+ },
2034
+ AltRight: {
2035
+ code: 57449,
2036
+ final: "u",
2037
+ modifier: true
2038
+ },
2039
+ MetaRight: {
2040
+ code: 57450,
2041
+ final: "u",
2042
+ modifier: true
2043
+ },
2044
+ Numpad0: {
2045
+ code: 57399,
2046
+ final: "u"
2047
+ },
2048
+ Numpad1: {
2049
+ code: 57400,
2050
+ final: "u"
2051
+ },
2052
+ Numpad2: {
2053
+ code: 57401,
2054
+ final: "u"
2055
+ },
2056
+ Numpad3: {
2057
+ code: 57402,
2058
+ final: "u"
2059
+ },
2060
+ Numpad4: {
2061
+ code: 57403,
2062
+ final: "u"
2063
+ },
2064
+ Numpad5: {
2065
+ code: 57404,
2066
+ final: "u"
2067
+ },
2068
+ Numpad6: {
2069
+ code: 57405,
2070
+ final: "u"
2071
+ },
2072
+ Numpad7: {
2073
+ code: 57406,
2074
+ final: "u"
2075
+ },
2076
+ Numpad8: {
2077
+ code: 57407,
2078
+ final: "u"
2079
+ },
2080
+ Numpad9: {
2081
+ code: 57408,
2082
+ final: "u"
2083
+ },
2084
+ NumpadDecimal: {
2085
+ code: 57409,
2086
+ final: "u"
2087
+ },
2088
+ NumpadDivide: {
2089
+ code: 57410,
2090
+ final: "u"
2091
+ },
2092
+ NumpadMultiply: {
2093
+ code: 57411,
2094
+ final: "u"
2095
+ },
2096
+ NumpadSubtract: {
2097
+ code: 57412,
2098
+ final: "u"
2099
+ },
2100
+ NumpadAdd: {
2101
+ code: 57413,
2102
+ final: "u"
2103
+ },
2104
+ NumpadEnter: {
2105
+ code: 57414,
2106
+ final: "u"
2107
+ },
2108
+ NumpadEqual: {
2109
+ code: 57415,
2110
+ final: "u"
2111
+ },
2112
+ NumpadComma: {
2113
+ code: 57416,
2114
+ final: "u"
2115
+ }
2116
+ };
2117
+ var KEYPAD_BEGIN = {
2118
+ code: 1,
2119
+ final: "E"
2120
+ };
2121
+ for (let index = 13; index <= 25; index++) FUNCTIONAL_KEYS[`F${index}`] = {
2122
+ code: 57363 + index,
2123
+ final: "u"
2124
+ };
2125
+ function codePoint(value) {
2126
+ const chars = Array.from(value);
2127
+ return chars.length === 1 ? chars[0].codePointAt(0) : null;
2128
+ }
2129
+ function printableEntry(event) {
2130
+ const current = codePoint(event.key);
2131
+ if (current === null || current < 32 || current === 127) return null;
2132
+ return {
2133
+ code: codePoint(event.key.toLowerCase()) ?? current,
2134
+ final: "u"
2135
+ };
2136
+ }
2137
+ function resolveKey(event, normalizeKeypad) {
2138
+ if (normalizeKeypad && event.code.startsWith("Numpad")) {
2139
+ if (event.code === "Numpad5" && event.key === "Clear") return {
2140
+ entry: KEYPAD_BEGIN,
2141
+ functionalKey: "Begin"
2142
+ };
2143
+ if (event.key.length === 1) {
2144
+ const entry = printableEntry(event);
2145
+ return entry ? {
2146
+ entry,
2147
+ functionalKey: null
2148
+ } : null;
2149
+ }
2150
+ const entry = FUNCTIONAL_KEYS[event.key];
2151
+ return entry ? {
2152
+ entry,
2153
+ functionalKey: event.key
2154
+ } : null;
2155
+ }
2156
+ const keypadNavigation = keypadNavigationEntry(event);
2157
+ if (keypadNavigation) return {
2158
+ entry: keypadNavigation,
2159
+ functionalKey: event.code
2160
+ };
2161
+ const byCode = FUNCTIONAL_KEYS[event.code];
2162
+ if (byCode) return {
2163
+ entry: byCode,
2164
+ functionalKey: event.code
2165
+ };
2166
+ const byKey = FUNCTIONAL_KEYS[event.key];
2167
+ if (byKey) return {
2168
+ entry: byKey,
2169
+ functionalKey: event.key
2170
+ };
2171
+ const printable = printableEntry(event);
2172
+ return printable ? {
2173
+ entry: printable,
2174
+ functionalKey: null
2175
+ } : null;
2176
+ }
2177
+ function keypadNavigationEntry(event) {
2178
+ const code = {
2179
+ "Numpad4:ArrowLeft": 57417,
2180
+ "Numpad6:ArrowRight": 57418,
2181
+ "Numpad8:ArrowUp": 57419,
2182
+ "Numpad2:ArrowDown": 57420,
2183
+ "Numpad9:PageUp": 57421,
2184
+ "Numpad3:PageDown": 57422,
2185
+ "Numpad7:Home": 57423,
2186
+ "Numpad1:End": 57424,
2187
+ "Numpad0:Insert": 57425,
2188
+ "NumpadDecimal:Delete": 57426,
2189
+ "Numpad5:Clear": 57427
2190
+ }[`${event.code}:${event.key}`];
2191
+ return code === void 0 ? null : {
2192
+ code,
2193
+ final: "u"
2194
+ };
2195
+ }
2196
+ function hasModifier(prefix, pressedModifiers) {
2197
+ for (const code of pressedModifiers ?? []) if (code.startsWith(prefix)) return true;
2198
+ return false;
2199
+ }
2200
+ function modifierValue(event, action, pressedModifiers) {
2201
+ let value = 1;
2202
+ const includeCurrent = action !== "release";
2203
+ if (event.shiftKey || hasModifier("Shift", pressedModifiers) || includeCurrent && event.code.startsWith("Shift")) value += 1;
2204
+ if (event.altKey || hasModifier("Alt", pressedModifiers) || includeCurrent && event.code.startsWith("Alt")) value += 2;
2205
+ if (event.ctrlKey || hasModifier("Control", pressedModifiers) || includeCurrent && event.code.startsWith("Control")) value += 4;
2206
+ if (event.metaKey || hasModifier("Meta", pressedModifiers) || includeCurrent && event.code.startsWith("Meta")) value += 8;
2207
+ if (event.getModifierState("CapsLock")) value += 64;
2208
+ if (event.getModifierState("NumLock")) value += 128;
2209
+ return value;
2210
+ }
2211
+ function associatedText(event) {
2212
+ if (event.ctrlKey || event.metaKey || event.altKey) return [];
2213
+ return Array.from(event.key).map((char) => char.codePointAt(0)).filter((point) => point >= 32 && point !== 127);
2214
+ }
2215
+ /** ASCII control byte for a browser key, or null when no legacy mapping exists. */
2216
+ function legacyControlByte(key) {
2217
+ if (key.length !== 1) return null;
2218
+ const code = key.toLowerCase().charCodeAt(0);
2219
+ if (code >= 97 && code <= 122) return String.fromCharCode(code - 96);
2220
+ switch (key) {
2221
+ case " ":
2222
+ case "2":
2223
+ case "@": return "\0";
2224
+ case "3":
2225
+ case "[": return "\x1B";
2226
+ case "4":
2227
+ case "\\": return "";
2228
+ case "5":
2229
+ case "]": return "";
2230
+ case "6":
2231
+ case "^":
2232
+ case "~": return "";
2233
+ case "7":
2234
+ case "/":
2235
+ case "_": return "";
2236
+ case "8":
2237
+ case "?": return "";
2238
+ default: return null;
2239
+ }
2240
+ }
2241
+ function legacyModifiedText(event) {
2242
+ if (event.metaKey) return null;
2243
+ const chars = Array.from(event.key);
2244
+ if (chars.length !== 1 || chars[0].codePointAt(0) < 32 || chars[0].codePointAt(0) > 126) return null;
2245
+ if (event.shiftKey && event.ctrlKey && /^[a-z]$/i.test(event.key)) return null;
2246
+ if (event.ctrlKey) {
2247
+ const key = event.key.toLowerCase();
2248
+ const control = legacyControlByte(key) ?? key;
2249
+ return event.altKey ? `\x1b${control}` : control;
2250
+ }
2251
+ return event.altKey ? `\x1b${event.key}` : null;
2252
+ }
2253
+ function legacyFunctionalSequence(functionalKey, flags, action, modifierBits, cursorKeysApp) {
2254
+ const disambiguate = Boolean(flags & 1);
2255
+ const reportEvents = Boolean(flags & 2);
2256
+ const reportAll = Boolean(flags & 8);
2257
+ const legacyMode = !disambiguate && !reportEvents && !reportAll;
2258
+ const nonLockModifiers = modifierBits & -193;
2259
+ if (cursorKeysApp && legacyMode && nonLockModifiers === 0) {
2260
+ const appSequence = {
2261
+ ArrowUp: "\x1BOA",
2262
+ ArrowDown: "\x1BOB",
2263
+ ArrowRight: "\x1BOC",
2264
+ ArrowLeft: "\x1BOD",
2265
+ Begin: "\x1BOE",
2266
+ End: "\x1BOF",
2267
+ Home: "\x1BOH"
2268
+ }[functionalKey];
2269
+ if (appSequence) return {
2270
+ handled: true,
2271
+ sequence: appSequence
2272
+ };
2273
+ }
2274
+ if (nonLockModifiers === 0) {
2275
+ if (!disambiguate && !reportAll && functionalKey === "Escape") return {
2276
+ handled: true,
2277
+ sequence: "\x1B"
2278
+ };
2279
+ if (legacyMode) {
2280
+ const functionSequence = {
2281
+ F1: "\x1BOP",
2282
+ F2: "\x1BOQ",
2283
+ F3: "\x1BOR",
2284
+ F4: "\x1BOS"
2285
+ }[functionalKey];
2286
+ if (functionSequence) return {
2287
+ handled: true,
2288
+ sequence: functionSequence
2289
+ };
2290
+ }
2291
+ }
2292
+ if (legacyMode && modifierBits !== 0) {
2293
+ const prefix = modifierBits & 2 ? "\x1B" : "";
2294
+ if (functionalKey === "Enter") return {
2295
+ handled: true,
2296
+ sequence: `${prefix}\r`
2297
+ };
2298
+ if (functionalKey === "Escape") return {
2299
+ handled: true,
2300
+ sequence: `${prefix}\x1b`
2301
+ };
2302
+ if (functionalKey === "Backspace") return {
2303
+ handled: true,
2304
+ sequence: `${prefix}${modifierBits & 4 ? "\b" : ""}`
2305
+ };
2306
+ if (functionalKey === "Tab") {
2307
+ if (modifierBits & 1) return {
2308
+ handled: true,
2309
+ sequence: `${modifierBits & 2 ? "\x1B\x1B" : "\x1B"}[Z`
2310
+ };
2311
+ return {
2312
+ handled: true,
2313
+ sequence: `${prefix}\t`
2314
+ };
2315
+ }
2316
+ }
2317
+ if (nonLockModifiers === 0 && !reportAll && (functionalKey === "Enter" || functionalKey === "Backspace" || functionalKey === "Tab")) return {
2318
+ handled: true,
2319
+ sequence: action === "release" ? null : functionalKey === "Enter" ? "\r" : functionalKey === "Backspace" ? "" : " "
2320
+ };
2321
+ return {
2322
+ handled: false,
2323
+ sequence: null
2324
+ };
2325
+ }
2326
+ function encodeKittyKey(event, flags, action, pressedModifiers, cursorKeysApp = false) {
2327
+ if (flags === 0) return null;
2328
+ if (action === "release" && !(flags & 2)) return null;
2329
+ const normalizeKeypad = !(flags & 1) && !(flags & 8);
2330
+ const resolved = resolveKey(event, normalizeKeypad);
2331
+ const entry = resolved?.entry ?? null;
2332
+ const textEntry = printableEntry(event);
2333
+ const legacyText = !(flags & 8) && textEntry !== null && !event.altKey && !event.ctrlKey && !event.metaKey;
2334
+ const legacyModified = !(flags & 1) && !(flags & 8) && (action === "press" || !(flags & 2)) && (event.ctrlKey || event.altKey) ? legacyModifiedText(event) : null;
2335
+ if (action === "release" && !(flags & 8) && legacyText) return null;
2336
+ if (action !== "release" && !(flags & 8) && !event.altKey && !event.ctrlKey && !event.metaKey) {
2337
+ if (!event.shiftKey) {
2338
+ if (event.key === "Enter" && (event.code !== "NumpadEnter" || normalizeKeypad)) return "\r";
2339
+ if (event.key === "Tab") return " ";
2340
+ if (event.key === "Backspace") return "";
2341
+ }
2342
+ if (legacyText) return event.key;
2343
+ }
2344
+ if (legacyModified !== null) return legacyModified;
2345
+ if (!entry) return null;
2346
+ if (entry.modifier && !(flags & 8)) return null;
2347
+ const modifiers = modifierValue(event, action, pressedModifiers);
2348
+ if (resolved?.functionalKey) {
2349
+ const legacy = legacyFunctionalSequence(resolved.functionalKey, flags, action, modifiers - 1, cursorKeysApp);
2350
+ if (legacy.handled) return legacy.sequence;
2351
+ }
2352
+ const eventType = flags & 2 ? action === "repeat" ? 2 : action === "release" ? 3 : 0 : 0;
2353
+ if (entry.final !== "u" && entry.final !== "~") {
2354
+ if (eventType !== 0) return `\x1b[1;${modifiers}:${eventType}${entry.final}`;
2355
+ if (modifiers > 1) return `\x1b[1;${modifiers}${entry.final}`;
2356
+ return `\x1b[${entry.final}`;
2357
+ }
2358
+ let sequence = `\x1b[${entry.code}`;
2359
+ if (textEntry && flags & 4 && event.shiftKey) {
2360
+ const shifted = codePoint(event.key);
2361
+ if (shifted !== null && shifted !== entry.code) sequence += `:${shifted}`;
2362
+ }
2363
+ let emittedModifiers = false;
2364
+ if (eventType === 2 || eventType === 3) {
2365
+ sequence += `;${modifiers}:${eventType}`;
2366
+ emittedModifiers = true;
2367
+ } else if (modifiers > 1) {
2368
+ sequence += `;${modifiers}`;
2369
+ emittedModifiers = true;
2370
+ }
2371
+ if (textEntry && flags & 16 && action !== "release") {
2372
+ const text = associatedText(event);
2373
+ if (text.length > 0) {
2374
+ sequence += emittedModifiers ? ";" : ";;";
2375
+ sequence += text.join(":");
2376
+ }
2377
+ }
2378
+ return sequence + entry.final;
2379
+ }
2380
+ //#endregion
2381
+ //#region ../../node_modules/.pnpm/@wterm+dom@0.5.4/node_modules/@wterm/dom/dist/input.js
2382
+ var NORMAL_KEYS = {
2383
+ ArrowUp: "\x1B[A",
2384
+ ArrowDown: "\x1B[B",
2385
+ ArrowRight: "\x1B[C",
2386
+ ArrowLeft: "\x1B[D",
2387
+ Home: "\x1B[H",
2388
+ End: "\x1B[F"
2389
+ };
2390
+ var APP_KEYS = {
2391
+ ArrowUp: "\x1BOA",
2392
+ ArrowDown: "\x1BOB",
2393
+ ArrowRight: "\x1BOC",
2394
+ ArrowLeft: "\x1BOD",
2395
+ Home: "\x1BOH",
2396
+ End: "\x1BOF"
2397
+ };
2398
+ var MODIFIED_CSI_KEYS = {
2399
+ ArrowUp: "A",
2400
+ ArrowDown: "B",
2401
+ ArrowRight: "C",
2402
+ ArrowLeft: "D",
2403
+ Home: "H",
2404
+ End: "F",
2405
+ F1: "P",
2406
+ F2: "Q",
2407
+ F3: "R",
2408
+ F4: "S"
2409
+ };
2410
+ var MODIFIED_TILDE_KEYS = {
2411
+ Insert: 2,
2412
+ Delete: 3,
2413
+ PageUp: 5,
2414
+ PageDown: 6,
2415
+ F5: 15,
2416
+ F6: 17,
2417
+ F7: 18,
2418
+ F8: 19,
2419
+ F9: 20,
2420
+ F10: 21,
2421
+ F11: 23,
2422
+ F12: 24
2423
+ };
2424
+ var FIXED_KEYS = {
2425
+ Enter: "\r",
2426
+ Backspace: "",
2427
+ Tab: " ",
2428
+ Escape: "\x1B",
2429
+ Insert: "\x1B[2~",
2430
+ Delete: "\x1B[3~",
2431
+ PageUp: "\x1B[5~",
2432
+ PageDown: "\x1B[6~",
2433
+ F1: "\x1BOP",
2434
+ F2: "\x1BOQ",
2435
+ F3: "\x1BOR",
2436
+ F4: "\x1BOS",
2437
+ F5: "\x1B[15~",
2438
+ F6: "\x1B[17~",
2439
+ F7: "\x1B[18~",
2440
+ F8: "\x1B[19~",
2441
+ F9: "\x1B[20~",
2442
+ F10: "\x1B[21~",
2443
+ F11: "\x1B[23~",
2444
+ F12: "\x1B[24~"
2445
+ };
2446
+ var COMPOSITION_INPUT_DEDUP_MS = 250;
2447
+ var SCROLLBACK_BOTTOM_TOLERANCE = 5;
2448
+ var TOUCH_INPUT_PLACEHOLDER = "​";
2449
+ function isAltGraphTextInput(event, pressedModifiers) {
2450
+ if (event.metaKey || !(event.getModifierState("AltGraph") || event.ctrlKey && event.altKey && pressedModifiers.has("AltRight"))) return false;
2451
+ const chars = Array.from(event.key);
2452
+ return chars.length === 1 && chars[0].codePointAt(0) >= 32 && chars[0] !== "";
2453
+ }
2454
+ var InputHandler = class {
2455
+ constructor(element, onData, getBridge, getCellSize = () => null, prepareComposition = () => {}, onBinary, selectionActions) {
2456
+ this.selectionActions = selectionActions;
2457
+ this.composing = false;
2458
+ this.compositionWidth = 0;
2459
+ this.recentCompositionCommit = null;
2460
+ this.suppressNextTouchDeleteInput = false;
2461
+ this.mouseButtons = 0;
2462
+ this.lastMouseMotion = null;
2463
+ this.focused = false;
2464
+ this.suppressedKeyUps = /* @__PURE__ */ new Set();
2465
+ this.pressedModifiers = /* @__PURE__ */ new Set();
2466
+ this.deliveredKeys = /* @__PURE__ */ new Set();
2467
+ this.tabExitArmed = false;
2468
+ this.element = element;
2469
+ this.onData = onData;
2470
+ this.onBinary = onBinary;
2471
+ this.getBridge = getBridge;
2472
+ this.getCellSize = getCellSize;
2473
+ this.prepareComposition = prepareComposition;
2474
+ this.touchPrimary = element.ownerDocument.defaultView?.matchMedia?.("(pointer: coarse)").matches ?? false;
2475
+ this.textarea = document.createElement("textarea");
2476
+ this.textarea.setAttribute("autocapitalize", "off");
2477
+ this.textarea.setAttribute("autocomplete", "off");
2478
+ this.textarea.setAttribute("autocorrect", "off");
2479
+ this.textarea.setAttribute("spellcheck", "false");
2480
+ this.textarea.setAttribute("enterkeyhint", "send");
2481
+ this.textarea.wrap = "off";
2482
+ const s = this.textarea.style;
2483
+ s.position = "absolute";
2484
+ s.left = "-9999px";
2485
+ s.top = "0";
2486
+ s.width = this.touchPrimary ? "var(--term-cell-width, 1ch)" : "1px";
2487
+ s.height = this.touchPrimary ? "var(--term-row-height)" : "1px";
2488
+ s.boxSizing = "border-box";
2489
+ s.font = "inherit";
2490
+ s.lineHeight = "var(--term-row-height)";
2491
+ s.fontKerning = "none";
2492
+ s.fontVariantLigatures = "none";
2493
+ s.whiteSpace = "pre";
2494
+ s.zIndex = "2";
2495
+ s.opacity = this.touchPrimary ? "1" : "0";
2496
+ s.overflow = "hidden";
2497
+ s.border = "0";
2498
+ s.padding = "0";
2499
+ s.margin = "0";
2500
+ s.outline = "none";
2501
+ s.resize = "none";
2502
+ s.pointerEvents = this.touchPrimary ? "auto" : "none";
2503
+ s.caretColor = "transparent";
2504
+ s.color = "transparent";
2505
+ s.background = "transparent";
2506
+ element.appendChild(this.textarea);
2507
+ this.accessibility = new InputAccessibility(element, this.textarea);
2508
+ this._onKeyDown = this.handleKeyDown.bind(this);
2509
+ this._onKeyUp = this.handleKeyUp.bind(this);
2510
+ this._onPaste = this.handlePaste.bind(this);
2511
+ this._onCompositionStart = this.handleCompositionStart.bind(this);
2512
+ this._onCompositionEnd = this.handleCompositionEnd.bind(this);
2513
+ this._onInput = this.handleInput.bind(this);
2514
+ this._onFocus = () => {
2515
+ if (this.focused) return;
2516
+ this.focused = true;
2517
+ if (this.touchPrimary && !this.textarea.value) this.resetInputValue();
2518
+ this.positionTextarea();
2519
+ this.element.classList.add("focused");
2520
+ if (this.getBridge()?.focusEvents?.()) this.onData("\x1B[I");
2521
+ };
2522
+ this._onBlur = () => {
2523
+ this.tabExitArmed = false;
2524
+ this.focused = false;
2525
+ this.composing = false;
2526
+ this.recentCompositionCommit = null;
2527
+ this.suppressNextTouchDeleteInput = false;
2528
+ this.hideComposition();
2529
+ this.textarea.value = "";
2530
+ this.element.classList.remove("focused");
2531
+ this.stopMouseCapture();
2532
+ this.lastMouseMotion = null;
2533
+ this.pressedModifiers.clear();
2534
+ this.deliveredKeys.clear();
2535
+ if (this.getBridge()?.focusEvents?.()) this.onData("\x1B[O");
2536
+ };
2537
+ this._onMouseDown = (event) => {
2538
+ this.tabExitArmed = false;
2539
+ this.handleMouse(event, "press");
2540
+ };
2541
+ this._onHoverMove = (event) => {
2542
+ if (this.mouseButtons !== 0) return;
2543
+ if (event.buttons !== 0 || event.shiftKey) {
2544
+ this.lastMouseMotion = null;
2545
+ return;
2546
+ }
2547
+ this.handleMouse(event, "move");
2548
+ };
2549
+ this._onMouseMove = (event) => {
2550
+ if (this.mouseButtons !== 0) this.handleMouse(event, "move");
2551
+ };
2552
+ this._onMouseUp = (event) => {
2553
+ if (this.mouseButtons === 0) return;
2554
+ this.handleMouse(event, "release");
2555
+ this.mouseButtons = event.buttons & 7;
2556
+ if (this.mouseButtons === 0) this.stopMouseCapture();
2557
+ };
2558
+ this._onMouseLeave = () => {
2559
+ if (this.mouseButtons === 0) this.lastMouseMotion = null;
2560
+ };
2561
+ this._onWheel = (event) => this.handleMouse(event, "wheel");
2562
+ this.textarea.addEventListener("keydown", this._onKeyDown);
2563
+ this.textarea.addEventListener("keyup", this._onKeyUp);
2564
+ this.textarea.addEventListener("paste", this._onPaste);
2565
+ this.textarea.addEventListener("compositionstart", this._onCompositionStart);
2566
+ this.textarea.addEventListener("compositionend", this._onCompositionEnd);
2567
+ this.textarea.addEventListener("input", this._onInput);
2568
+ this.textarea.addEventListener("focus", this._onFocus);
2569
+ this.textarea.addEventListener("blur", this._onBlur);
2570
+ this.element.addEventListener("mousedown", this._onMouseDown);
2571
+ this.element.addEventListener("mousemove", this._onHoverMove);
2572
+ this.element.addEventListener("mouseleave", this._onMouseLeave);
2573
+ this.element.addEventListener("wheel", this._onWheel, { passive: false });
2574
+ }
2575
+ focus() {
2576
+ if (this.touchPrimary) this.prepareComposition();
2577
+ if (this.touchPrimary && !this.composing && !this.textarea.value) this.resetInputValue();
2578
+ this.positionTextarea();
2579
+ this.textarea.focus({ preventScroll: true });
2580
+ }
2581
+ syncInputPosition() {
2582
+ if (this.composing || this.touchPrimary) this.positionTextarea();
2583
+ }
2584
+ destroy() {
2585
+ this.accessibility.destroy();
2586
+ this.textarea.removeEventListener("keydown", this._onKeyDown);
2587
+ this.textarea.removeEventListener("keyup", this._onKeyUp);
2588
+ this.textarea.removeEventListener("paste", this._onPaste);
2589
+ this.textarea.removeEventListener("compositionstart", this._onCompositionStart);
2590
+ this.textarea.removeEventListener("compositionend", this._onCompositionEnd);
2591
+ this.textarea.removeEventListener("input", this._onInput);
2592
+ this.textarea.removeEventListener("focus", this._onFocus);
2593
+ this.textarea.removeEventListener("blur", this._onBlur);
2594
+ this.element.removeEventListener("mousedown", this._onMouseDown);
2595
+ this.element.removeEventListener("mousemove", this._onHoverMove);
2596
+ this.element.removeEventListener("mouseleave", this._onMouseLeave);
2597
+ this.stopMouseCapture();
2598
+ this.element.removeEventListener("wheel", this._onWheel);
2599
+ this.element.classList.remove("focused");
2600
+ this.textarea.remove();
2601
+ }
2602
+ handleKeyDown(e) {
2603
+ const keyId = e.code || e.key;
2604
+ if (e.key !== "Backspace") this.suppressNextTouchDeleteInput = false;
2605
+ const physicalModifier = /^(Shift|Control|Alt|Meta)(Left|Right)$/.test(e.code);
2606
+ if (physicalModifier) this.pressedModifiers.add(e.code);
2607
+ if (this.composing || e.isComposing || e.keyCode === 229) {
2608
+ this.tabExitArmed = false;
2609
+ this.positionTextarea();
2610
+ this.suppressedKeyUps.add(keyId);
2611
+ return;
2612
+ }
2613
+ this.recentCompositionCommit = null;
2614
+ const bridge = this.getBridge();
2615
+ const kittyFlags = bridge?.kittyKeyboardFlags?.() ?? 0;
2616
+ const kittyOwnsModifier = physicalModifier && Boolean(kittyFlags & 8);
2617
+ const delivered = this.deliveredKeys.has(keyId);
2618
+ if (this.tabExitArmed && e.key === "Tab" && !e.altKey && !e.ctrlKey && !e.metaKey && !e.repeat && !delivered) {
2619
+ this.tabExitArmed = false;
2620
+ this.suppressedKeyUps.add(keyId);
2621
+ return;
2622
+ }
2623
+ if (e.key !== "Shift" || e.altKey || e.ctrlKey || e.metaKey) this.tabExitArmed = e.key === "Escape" && !e.altKey && !e.ctrlKey && !e.metaKey && !e.shiftKey;
2624
+ if (isAltGraphTextInput(e, this.pressedModifiers)) {
2625
+ if (!delivered) this.suppressedKeyUps.add(keyId);
2626
+ return;
2627
+ }
2628
+ if (!delivered && this.selectionActions && !e.altKey && (e.metaKey && !e.ctrlKey && !e.shiftKey || e.ctrlKey && e.shiftKey && !e.metaKey) && e.key.toLowerCase() === "a") {
2629
+ e.preventDefault();
2630
+ e.stopPropagation();
2631
+ this.suppressedKeyUps.add(keyId);
2632
+ this.selectionActions.selectAll();
2633
+ return;
2634
+ }
2635
+ if (!delivered && e.key === "Escape" && !e.ctrlKey && !e.metaKey && !e.altKey && !e.shiftKey && this.selectionActions?.hasSelection()) {
2636
+ e.preventDefault();
2637
+ e.stopPropagation();
2638
+ this.suppressedKeyUps.add(keyId);
2639
+ this.selectionActions.clearSelection();
2640
+ return;
2641
+ }
2642
+ if (!delivered && (e.metaKey || e.ctrlKey) && !e.altKey && e.key.toLowerCase() === "c") {
2643
+ const sel = window.getSelection();
2644
+ if (this.selectionActions?.hasSelection() || sel && sel.toString().length > 0) {
2645
+ this.suppressedKeyUps.add(keyId);
2646
+ if (e.ctrlKey && e.shiftKey && !e.metaKey) {
2647
+ e.preventDefault();
2648
+ e.stopPropagation();
2649
+ this.element.ownerDocument.execCommand("copy");
2650
+ }
2651
+ return;
2652
+ }
2653
+ }
2654
+ if (!delivered && (e.metaKey || e.ctrlKey) && e.key === "v") {
2655
+ this.suppressedKeyUps.add(keyId);
2656
+ this.textarea.focus();
2657
+ return;
2658
+ }
2659
+ if (!delivered && !kittyOwnsModifier && e.metaKey && !e.ctrlKey) {
2660
+ this.suppressedKeyUps.add(keyId);
2661
+ if (e.key === "Backspace") {
2662
+ e.preventDefault();
2663
+ this.selectionActions?.clearSelection();
2664
+ this.onData("");
2665
+ } else if (e.key === "a") {
2666
+ e.preventDefault();
2667
+ const sel = window.getSelection();
2668
+ if (sel) {
2669
+ const range = document.createRange();
2670
+ range.selectNodeContents(this.element);
2671
+ sel.removeAllRanges();
2672
+ sel.addRange(range);
2673
+ }
2674
+ }
2675
+ return;
2676
+ }
2677
+ this.suppressedKeyUps.delete(keyId);
2678
+ const nativeTouchDelete = this.touchPrimary && e.key === "Backspace" && !e.altKey && !e.ctrlKey && !e.metaKey;
2679
+ if (kittyFlags !== 0) {
2680
+ const seq = encodeKittyKey(e, kittyFlags, e.repeat ? "repeat" : "press", this.pressedModifiers, bridge?.cursorKeysApp?.() ?? false);
2681
+ if (seq) {
2682
+ if (!physicalModifier) this.selectionActions?.clearSelection();
2683
+ if (nativeTouchDelete) this.suppressNextTouchDeleteInput = true;
2684
+ else e.preventDefault();
2685
+ e.stopPropagation();
2686
+ this.deliveredKeys.add(keyId);
2687
+ this.onData(seq, physicalModifier);
2688
+ }
2689
+ return;
2690
+ }
2691
+ const seq = this.keyToSequence(e);
2692
+ if (seq) {
2693
+ this.selectionActions?.clearSelection();
2694
+ if (nativeTouchDelete) this.suppressNextTouchDeleteInput = true;
2695
+ else e.preventDefault();
2696
+ e.stopPropagation();
2697
+ this.onData(seq);
2698
+ }
2699
+ }
2700
+ handleKeyUp(e) {
2701
+ const keyId = e.code || e.key;
2702
+ this.pressedModifiers.delete(e.code);
2703
+ const delivered = this.deliveredKeys.delete(keyId);
2704
+ if (this.suppressedKeyUps.delete(keyId)) return;
2705
+ if (!delivered) return;
2706
+ if (this.composing) return;
2707
+ const bridge = this.getBridge();
2708
+ const kittyFlags = bridge?.kittyKeyboardFlags?.() ?? 0;
2709
+ if (!(kittyFlags & 2)) return;
2710
+ const seq = encodeKittyKey(e, kittyFlags, "release", this.pressedModifiers, bridge?.cursorKeysApp?.() ?? false);
2711
+ if (!seq) return;
2712
+ e.preventDefault();
2713
+ this.onData(seq, true);
2714
+ }
2715
+ handlePaste(e) {
2716
+ this.tabExitArmed = false;
2717
+ this.recentCompositionCommit = null;
2718
+ this.suppressNextTouchDeleteInput = false;
2719
+ const text = e.clipboardData?.getData("text");
2720
+ if (!text) return;
2721
+ e.preventDefault();
2722
+ this.sendPaste(text);
2723
+ }
2724
+ sendPaste(text) {
2725
+ this.selectionActions?.clearSelection();
2726
+ const bridge = this.getBridge();
2727
+ if (bridge && bridge.bracketedPaste()) {
2728
+ const safe = text.replace(/\x1b/g, "");
2729
+ this.onData("\x1B[200~" + safe + "\x1B[201~");
2730
+ } else this.onData(text);
2731
+ }
2732
+ handleCompositionStart() {
2733
+ this.tabExitArmed = false;
2734
+ this.prepareComposition();
2735
+ this.composing = true;
2736
+ this.recentCompositionCommit = null;
2737
+ this.suppressNextTouchDeleteInput = false;
2738
+ if (this.touchPrimary && this.textarea.value === TOUCH_INPUT_PLACEHOLDER) this.textarea.value = "";
2739
+ this.positionTextarea();
2740
+ const s = this.textarea.style;
2741
+ s.opacity = "1";
2742
+ s.color = "var(--term-fg, currentColor)";
2743
+ s.background = "var(--term-bg, transparent)";
2744
+ s.caretColor = "var(--term-fg, currentColor)";
2745
+ }
2746
+ handleCompositionEnd(e) {
2747
+ this.composing = false;
2748
+ this.hideComposition();
2749
+ this.resetInputValue();
2750
+ if (e.data) {
2751
+ this.recentCompositionCommit = {
2752
+ text: e.data,
2753
+ at: performance.now()
2754
+ };
2755
+ this.onData(e.data);
2756
+ }
2757
+ }
2758
+ hideComposition() {
2759
+ this.compositionWidth = 0;
2760
+ const s = this.textarea.style;
2761
+ s.opacity = this.touchPrimary ? "1" : "0";
2762
+ s.width = this.touchPrimary ? "var(--term-cell-width, 1ch)" : "1px";
2763
+ s.height = this.touchPrimary ? "var(--term-row-height)" : "1px";
2764
+ s.color = "transparent";
2765
+ s.background = "transparent";
2766
+ s.caretColor = "transparent";
2767
+ }
2768
+ positionTextarea() {
2769
+ const bridge = this.getBridge();
2770
+ const cellSize = this.getCellSize();
2771
+ const firstRow = this.element.querySelector(".term-row:not(.term-scrollback-row)");
2772
+ if (!bridge || !cellSize || !firstRow || !bridge.getCursor) {
2773
+ this.textarea.style.left = "0px";
2774
+ this.textarea.style.top = "0px";
2775
+ if (this.composing) {
2776
+ this.textarea.style.width = `${Math.max(1, this.compositionWidth)}px`;
2777
+ this.textarea.style.height = `${cellSize?.rowHeight ?? 17}px`;
2778
+ }
2779
+ return;
2780
+ }
2781
+ const { charWidth, rowHeight } = cellSize;
2782
+ if (charWidth <= 0 || rowHeight <= 0) return;
2783
+ const cursor = bridge.getCursor();
2784
+ const col = Math.max(0, Math.min(cursor.col, bridge.getCols() - 1));
2785
+ const row = Math.max(0, Math.min(cursor.row, bridge.getRows() - 1));
2786
+ const hostRect = this.element.getBoundingClientRect();
2787
+ const rowRect = firstRow.getBoundingClientRect();
2788
+ const s = this.textarea.style;
2789
+ s.left = `${rowRect.left - hostRect.left - this.element.clientLeft + this.element.scrollLeft + col * charWidth}px`;
2790
+ s.top = `${rowRect.top - hostRect.top - this.element.clientTop + this.element.scrollTop + row * rowHeight}px`;
2791
+ if (this.composing) {
2792
+ s.width = `${Math.min((bridge.getCols() - col) * charWidth, Math.max(charWidth, this.compositionWidth))}px`;
2793
+ s.height = `${rowHeight}px`;
2794
+ }
2795
+ }
2796
+ sizeComposition() {
2797
+ const charWidth = this.getCellSize()?.charWidth;
2798
+ if (!charWidth || charWidth <= 0) return;
2799
+ this.textarea.style.width = "1px";
2800
+ this.compositionWidth = this.textarea.value ? Math.max(charWidth, this.textarea.scrollWidth + charWidth) : charWidth;
2801
+ this.positionTextarea();
2802
+ }
2803
+ resetInputValue() {
2804
+ this.textarea.value = this.touchPrimary ? TOUCH_INPUT_PLACEHOLDER : "";
2805
+ if (this.touchPrimary) this.textarea.setSelectionRange(1, 1);
2806
+ }
2807
+ sendTouchDelete() {
2808
+ this.selectionActions?.clearSelection();
2809
+ const bridge = this.getBridge();
2810
+ const flags = bridge?.kittyKeyboardFlags?.() ?? 0;
2811
+ const seq = flags ? encodeKittyKey(new KeyboardEvent("keydown", {
2812
+ key: "Backspace",
2813
+ code: "Backspace"
2814
+ }), flags, "press", void 0, bridge?.cursorKeysApp?.() ?? false) : "";
2815
+ if (seq) this.onData(seq);
2816
+ }
2817
+ handleInput(event) {
2818
+ this.tabExitArmed = false;
2819
+ if (this.composing) {
2820
+ this.sizeComposition();
2821
+ return;
2822
+ }
2823
+ const inputType = event.inputType;
2824
+ const rawValue = this.textarea.value;
2825
+ const value = this.touchPrimary && rawValue.startsWith(TOUCH_INPUT_PLACEHOLDER) ? rawValue.slice(1) : rawValue;
2826
+ this.resetInputValue();
2827
+ const recent = this.recentCompositionCommit;
2828
+ this.recentCompositionCommit = null;
2829
+ if (this.touchPrimary && inputType === "deleteContentBackward") {
2830
+ if (this.suppressNextTouchDeleteInput) this.suppressNextTouchDeleteInput = false;
2831
+ else this.sendTouchDelete();
2832
+ return;
2833
+ }
2834
+ this.suppressNextTouchDeleteInput = false;
2835
+ if (!value) return;
2836
+ if (recent && value === recent.text && performance.now() - recent.at < COMPOSITION_INPUT_DEDUP_MS) return;
2837
+ if (inputType === "insertFromPaste") this.sendPaste(value);
2838
+ else {
2839
+ this.selectionActions?.clearSelection();
2840
+ this.onData(value);
2841
+ }
2842
+ }
2843
+ handleMouse(event, kind) {
2844
+ const bridge = this.getBridge();
2845
+ const tracking = bridge?.mouseTracking?.() ?? 0;
2846
+ const encoding = bridge?.mouseEncoding?.() ?? (bridge?.mouseSgr?.() ? "sgr" : null);
2847
+ if (!bridge || tracking === 0 || encoding !== "sgr" && encoding !== "sgr-pixels" && encoding !== "x10" && encoding !== "utf8" && encoding !== "urxvt") {
2848
+ this.lastMouseMotion = null;
2849
+ return;
2850
+ }
2851
+ if (kind === "wheel") {
2852
+ const wheel = event;
2853
+ const maxScrollTop = this.element.scrollHeight - this.element.clientHeight;
2854
+ if (maxScrollTop > 0 && (wheel.shiftKey || maxScrollTop - this.element.scrollTop > SCROLLBACK_BOTTOM_TOLERANCE)) {
2855
+ this.lastMouseMotion = null;
2856
+ if (wheel.shiftKey) {
2857
+ const delta = Math.abs(wheel.deltaX) > Math.abs(wheel.deltaY) ? wheel.deltaX : wheel.deltaY;
2858
+ const scale = wheel.deltaMode === 1 ? this.getCellSize()?.rowHeight ?? 16 : wheel.deltaMode === 2 ? this.element.clientHeight : 1;
2859
+ if (delta !== 0) {
2860
+ this.element.scrollTop += delta * scale;
2861
+ wheel.preventDefault();
2862
+ }
2863
+ }
2864
+ return;
2865
+ }
2866
+ }
2867
+ if (kind === "press" && isLinkActivationModifier(event, this.element.ownerDocument.defaultView?.navigator ?? navigator) && event.target instanceof Element && event.target.closest(".term-link")) return;
2868
+ if (kind === "press" && (event.shiftKey || event.button > 2)) return;
2869
+ if (kind === "release" && event.button > 2) return;
2870
+ const supportedButtons = event.buttons & 7;
2871
+ if (kind === "move" && !(tracking === 1003 || tracking === 1002 && supportedButtons !== 0)) {
2872
+ this.lastMouseMotion = null;
2873
+ return;
2874
+ }
2875
+ const view = this.element.ownerDocument.defaultView;
2876
+ if (!view) return;
2877
+ const viewportRow = this.element.querySelector(".term-row:not(.term-scrollback-row)");
2878
+ const hostRect = this.element.getBoundingClientRect();
2879
+ const rowRect = viewportRow?.getBoundingClientRect();
2880
+ const cellSize = this.getCellSize();
2881
+ let left;
2882
+ let top;
2883
+ let charWidth;
2884
+ let rowHeight;
2885
+ if (rowRect && cellSize) {
2886
+ left = rowRect.left;
2887
+ top = rowRect.top;
2888
+ charWidth = cellSize.charWidth;
2889
+ rowHeight = cellSize.rowHeight;
2890
+ } else {
2891
+ const style = view.getComputedStyle(this.element);
2892
+ const borderLeft = parseFloat(style.borderLeftWidth) || 0;
2893
+ const borderRight = parseFloat(style.borderRightWidth) || 0;
2894
+ const borderTop = parseFloat(style.borderTopWidth) || 0;
2895
+ const borderBottom = parseFloat(style.borderBottomWidth) || 0;
2896
+ const paddingLeft = parseFloat(style.paddingLeft) || 0;
2897
+ const paddingRight = parseFloat(style.paddingRight) || 0;
2898
+ const paddingTop = parseFloat(style.paddingTop) || 0;
2899
+ const paddingBottom = parseFloat(style.paddingBottom) || 0;
2900
+ left = rowRect?.left ?? hostRect.left + borderLeft + paddingLeft;
2901
+ top = rowRect?.top ?? hostRect.top + borderTop + paddingTop;
2902
+ charWidth = (hostRect.width - borderLeft - borderRight - paddingLeft - paddingRight) / bridge.getCols();
2903
+ rowHeight = (hostRect.height - borderTop - borderBottom - paddingTop - paddingBottom) / bridge.getRows();
2904
+ }
2905
+ const cols = bridge.getCols();
2906
+ const rows = bridge.getRows();
2907
+ const gridWidth = charWidth * cols;
2908
+ const gridHeight = rowHeight * rows;
2909
+ if (!Number.isFinite(gridWidth) || !Number.isFinite(gridHeight) || gridWidth <= 0 || gridHeight <= 0) return;
2910
+ if ((event.clientX < left || event.clientX >= left + gridWidth || event.clientY < top || event.clientY >= top + gridHeight) && (kind === "press" || kind === "wheel" || kind === "move" && supportedButtons === 0)) {
2911
+ this.lastMouseMotion = null;
2912
+ return;
2913
+ }
2914
+ const pixels = encoding === "sgr-pixels";
2915
+ const x = Math.max(1, Math.min(pixels ? Math.ceil(gridWidth) : cols, Math.floor((event.clientX - left) / (pixels ? 1 : charWidth)) + 1));
2916
+ const y = Math.max(1, Math.min(pixels ? Math.ceil(gridHeight) : rows, Math.floor((event.clientY - top) / (pixels ? 1 : rowHeight)) + 1));
2917
+ const modifiers = (event.shiftKey ? 4 : 0) | (event.altKey ? 8 : 0) | (event.ctrlKey ? 16 : 0);
2918
+ let code;
2919
+ let final = "M";
2920
+ if (kind === "wheel") {
2921
+ const wheel = event;
2922
+ if (Math.abs(wheel.deltaX) > Math.abs(wheel.deltaY)) {
2923
+ if (wheel.deltaX === 0) return;
2924
+ code = (wheel.deltaX < 0 ? 66 : 67) | modifiers;
2925
+ } else {
2926
+ if (wheel.deltaY === 0) return;
2927
+ code = (wheel.deltaY < 0 ? 64 : 65) | modifiers;
2928
+ }
2929
+ } else {
2930
+ code = (kind === "release" && encoding !== "sgr" && !pixels ? 3 : kind === "move" ? supportedButtons === 0 ? 3 : supportedButtons & 4 ? 1 : supportedButtons & 2 ? 2 : 0 : event.button === 1 ? 1 : event.button === 2 ? 2 : 0) | modifiers | (kind === "move" ? 32 : 0);
2931
+ if (kind === "release") final = "m";
2932
+ }
2933
+ const legacy = encoding === "x10" ? Uint8Array.of(27, 91, 77, code + 32, x + 32, y + 32) : null;
2934
+ if (legacy && (x > 223 || y > 223 || !this.onBinary && (legacy[4] > 127 || legacy[5] > 127))) {
2935
+ this.lastMouseMotion = null;
2936
+ return;
2937
+ }
2938
+ if (encoding === "utf8" && (x > 2015 || y > 2015)) {
2939
+ this.lastMouseMotion = null;
2940
+ return;
2941
+ }
2942
+ if (kind === "move") {
2943
+ const previous = this.lastMouseMotion;
2944
+ if (previous?.mode === tracking && previous.encoding === encoding && previous.code === code && previous.x === x && previous.y === y) return;
2945
+ this.lastMouseMotion = {
2946
+ mode: tracking,
2947
+ encoding,
2948
+ code,
2949
+ x,
2950
+ y
2951
+ };
2952
+ } else this.lastMouseMotion = null;
2953
+ if (kind === "press") {
2954
+ this.textarea.focus({ preventScroll: true });
2955
+ if (!this.focused) this._onFocus();
2956
+ this.mouseButtons = supportedButtons || (event.button === 1 ? 4 : event.button === 2 ? 2 : 1);
2957
+ view.addEventListener("mousemove", this._onMouseMove);
2958
+ view.addEventListener("mouseup", this._onMouseUp);
2959
+ }
2960
+ event.preventDefault();
2961
+ if (legacy) {
2962
+ if (this.onBinary) this.onBinary(legacy);
2963
+ else this.onData(String.fromCharCode(...legacy));
2964
+ } else if (encoding === "utf8") this.onData(`\x1b[M${String.fromCodePoint(code + 32, x + 32, y + 32)}`);
2965
+ else if (encoding === "urxvt") this.onData(`\x1b[${code + 32};${x};${y}M`);
2966
+ else this.onData(`\x1b[<${code};${x};${y}${final}`);
2967
+ }
2968
+ stopMouseCapture() {
2969
+ this.mouseButtons = 0;
2970
+ const view = this.element.ownerDocument.defaultView;
2971
+ view?.removeEventListener("mousemove", this._onMouseMove);
2972
+ view?.removeEventListener("mouseup", this._onMouseUp);
2973
+ }
2974
+ keyToSequence(e) {
2975
+ if (e.ctrlKey && !e.altKey && !e.metaKey) {
2976
+ const control = legacyControlByte(e.key);
2977
+ if (control !== null) return control;
2978
+ if (e.key === "Backspace") return "\b";
2979
+ }
2980
+ if (e.key === "Enter" && e.shiftKey) return "\x1B[13;2u";
2981
+ if (e.key === "Tab" && e.shiftKey) return "\x1B[Z";
2982
+ if (!e.metaKey && (e.shiftKey || e.altKey || e.ctrlKey)) {
2983
+ const modifier = 1 + Number(e.shiftKey) + 2 * Number(e.altKey) + 4 * Number(e.ctrlKey);
2984
+ const final = MODIFIED_CSI_KEYS[e.key];
2985
+ if (final) return `\x1b[1;${modifier}${final}`;
2986
+ const tilde = MODIFIED_TILDE_KEYS[e.key];
2987
+ if (tilde) return `\x1b[${tilde};${modifier}~`;
2988
+ }
2989
+ const fixed = FIXED_KEYS[e.key];
2990
+ if (fixed) return e.altKey ? "\x1B" + fixed : fixed;
2991
+ const bridge = this.getBridge();
2992
+ const nav = (bridge && bridge.cursorKeysApp() ? APP_KEYS : NORMAL_KEYS)[e.key];
2993
+ if (nav) return e.altKey ? "\x1B" + nav : nav;
2994
+ if (e.key.length === 1 && !e.ctrlKey && !e.metaKey) return e.altKey ? "\x1B" + e.key : e.key;
2995
+ return null;
2996
+ }
2997
+ };
2998
+ //#endregion
2999
+ //#region ../../node_modules/.pnpm/@wterm+dom@0.5.4/node_modules/@wterm/dom/dist/text-capture.js
3000
+ var MAX_TEXT_LENGTH = 16777216;
3001
+ /** Copy cell text in small batches without mounting retained history. */
3002
+ function* scanText(core, limit = MAX_TEXT_LENGTH) {
3003
+ const history = core.getScrollbackCount();
3004
+ const parts = [];
3005
+ let chunk = "";
3006
+ let length = 0;
3007
+ let work = 0;
3008
+ let previousWrap = false;
3009
+ const append = (text) => {
3010
+ length += text.length;
3011
+ if (length > limit) throw new RangeError("Terminal text exceeds 16,777,216 UTF-16 code units");
3012
+ chunk += text;
3013
+ if (chunk.length >= 8192) {
3014
+ parts.push(chunk);
3015
+ chunk = "";
3016
+ }
3017
+ };
3018
+ for (let row = 0; row < history + core.getRows(); row++) {
3019
+ const offset = history - row - 1;
3020
+ const metadata = row < history ? core.getScrollbackRowMetadata?.(offset) : core.getRowMetadata?.(row - history);
3021
+ if (row > 0 && !(previousWrap && metadata?.continuesPrevious)) append("\n");
3022
+ previousWrap = metadata?.wrapsToNext ?? false;
3023
+ const cols = row < history ? core.getScrollbackLineLen(offset) : core.getCols();
3024
+ let spaces = 0;
3025
+ for (let col = 0; col < cols; col++) {
3026
+ if (++work >= 256) {
3027
+ work = 0;
3028
+ yield;
3029
+ }
3030
+ const cell = row < history ? core.getScrollbackCell(offset, col) : core.getCell(row - history, col);
3031
+ if (cell.width === 0 || cell.spacerHead) continue;
3032
+ const text = cell.chars ?? String.fromCodePoint(cell.char || 32);
3033
+ if (/^ +$/.test(text)) spaces += text.length;
3034
+ else {
3035
+ if (length + spaces + text.length > limit) throw new RangeError("Terminal text exceeds 16,777,216 UTF-16 code units");
3036
+ append(" ".repeat(spaces) + text);
3037
+ spaces = 0;
3038
+ }
3039
+ }
3040
+ if (previousWrap) {
3041
+ if (length + spaces > limit) throw new RangeError("Terminal text exceeds 16,777,216 UTF-16 code units");
3042
+ append(" ".repeat(spaces));
3043
+ }
3044
+ if (++work >= 256) {
3045
+ work = 0;
3046
+ yield;
3047
+ }
3048
+ }
3049
+ parts.push(chunk);
3050
+ return parts.join("");
3051
+ }
3052
+ function aborted(message) {
3053
+ return new DOMException(message, "AbortError");
3054
+ }
3055
+ /** One cancellable capture, resumed only after WTerm paints its current state. */
3056
+ var TextCapture = class {
3057
+ constructor() {
3058
+ this.request = null;
3059
+ this.timer = null;
3060
+ }
3061
+ read(signal) {
3062
+ this.cancel(aborted("Replaced by another text capture"));
3063
+ if (signal?.aborted) return Promise.reject(signal.reason);
3064
+ return new Promise((resolve, reject) => {
3065
+ const abort = () => this.cancel(signal?.reason);
3066
+ this.request = {
3067
+ resolve,
3068
+ reject,
3069
+ signal,
3070
+ abort,
3071
+ scan: null
3072
+ };
3073
+ signal?.addEventListener("abort", abort, { once: true });
3074
+ });
3075
+ }
3076
+ resume(core) {
3077
+ const request = this.request;
3078
+ if (!request || request.scan) return;
3079
+ const scan = request.scan = scanText(core);
3080
+ const tick = () => {
3081
+ if (this.request !== request) return;
3082
+ this.timer = null;
3083
+ const deadline = performance.now() + 4;
3084
+ try {
3085
+ for (let batch = 0; batch < 32; batch++) {
3086
+ const next = scan.next();
3087
+ if (next.done) {
3088
+ this.release();
3089
+ request.resolve(next.value);
3090
+ return;
3091
+ }
3092
+ if (performance.now() >= deadline) break;
3093
+ }
3094
+ this.timer = setTimeout(tick, 0);
3095
+ } catch (error) {
3096
+ this.cancel(error);
3097
+ }
3098
+ };
3099
+ this.timer = setTimeout(tick, 0);
3100
+ }
3101
+ cancel(error) {
3102
+ const request = this.request;
3103
+ if (!request) return;
3104
+ this.release();
3105
+ request.reject(error === void 0 ? aborted("Terminal changed during text capture") : error);
3106
+ }
3107
+ release() {
3108
+ if (this.timer !== null) clearTimeout(this.timer);
3109
+ this.timer = null;
3110
+ this.request?.signal?.removeEventListener("abort", this.request.abort);
3111
+ this.request?.scan?.return("");
3112
+ this.request = null;
3113
+ }
3114
+ };
3115
+ //#endregion
3116
+ //#region ../../node_modules/.pnpm/@wterm+dom@0.5.4/node_modules/@wterm/dom/dist/history-selection.js
3117
+ var owners = /* @__PURE__ */ new WeakMap();
3118
+ /** A complete, immutable selection; no partial text is exposed while scanning. */
3119
+ var HistorySelection = class {
3120
+ constructor(element) {
3121
+ this.element = element;
3122
+ this.text = null;
3123
+ this.scan = null;
3124
+ this.timer = null;
3125
+ this.resolve = null;
3126
+ this.rectangle = null;
3127
+ this.decorated = /* @__PURE__ */ new Set();
3128
+ this.onPointerDown = (event) => {
3129
+ if (event.button === 2 && this.element.contains(event.target)) return;
3130
+ this.clear();
3131
+ };
3132
+ this.onFocus = (event) => {
3133
+ if (!this.element.contains(event.target)) this.clear();
3134
+ };
3135
+ this.onSelectionChange = () => {
3136
+ if (!this.active) return;
3137
+ const doc = this.element.ownerDocument;
3138
+ const active = doc.activeElement;
3139
+ if (active && (active.tagName === "INPUT" || active.tagName === "TEXTAREA")) {
3140
+ const input = active;
3141
+ if (input.selectionStart !== input.selectionEnd) {
3142
+ this.clear();
3143
+ return;
3144
+ }
3145
+ }
3146
+ const selection = doc.getSelection();
3147
+ if (selection && !selection.isCollapsed) this.clear();
3148
+ };
3149
+ this.status = element.ownerDocument.createElement("div");
3150
+ this.status.className = "term-selection-status";
3151
+ this.status.setAttribute("role", "status");
3152
+ element.appendChild(this.status);
3153
+ const doc = element.ownerDocument;
3154
+ doc.addEventListener("pointerdown", this.onPointerDown, true);
3155
+ doc.addEventListener("focusin", this.onFocus);
3156
+ doc.addEventListener("selectionchange", this.onSelectionChange);
3157
+ }
3158
+ get pending() {
3159
+ return this.resolve !== null;
3160
+ }
3161
+ get active() {
3162
+ return this.pending || this.text !== null;
3163
+ }
3164
+ getText() {
3165
+ this.onSelectionChange();
3166
+ return this.text;
3167
+ }
3168
+ select() {
3169
+ this.claim();
3170
+ this.status.textContent = "Selecting terminal text…";
3171
+ return new Promise((resolve) => {
3172
+ this.resolve = resolve;
3173
+ });
3174
+ }
3175
+ selectRectangle(rectangle) {
3176
+ this.claim();
3177
+ this.rectangle = rectangle;
3178
+ this.text = rectangle.text;
3179
+ }
3180
+ paintRectangle(rows, charWidth) {
3181
+ this.clearDecorations();
3182
+ if (!this.rectangle || charWidth <= 0) return;
3183
+ const first = this.rectangle.rows[0].row;
3184
+ for (const { row, element } of rows) {
3185
+ const range = this.rectangle.rows[row - first];
3186
+ if (!range) continue;
3187
+ element.classList.add("term-rectangle-row");
3188
+ element.style.setProperty("--term-selection-left", `${range.left * charWidth}px`);
3189
+ element.style.setProperty("--term-selection-width", `${(range.right - range.left) * charWidth}px`);
3190
+ this.decorated.add(element);
3191
+ }
3192
+ }
3193
+ clearDecorations() {
3194
+ for (const element of this.decorated) {
3195
+ element.classList.remove("term-rectangle-row");
3196
+ element.style.removeProperty("--term-selection-left");
3197
+ element.style.removeProperty("--term-selection-width");
3198
+ }
3199
+ this.decorated.clear();
3200
+ }
3201
+ claim() {
3202
+ const doc = this.element.ownerDocument;
3203
+ owners.get(doc)?.clear();
3204
+ this.clear();
3205
+ owners.set(doc, this);
3206
+ const native = doc.getSelection();
3207
+ if (native && !native.isCollapsed) native.removeAllRanges();
3208
+ }
3209
+ /** WTerm calls this only once its current frame has painted. */
3210
+ resume(core) {
3211
+ if (!this.pending || this.scan) return;
3212
+ const scan = this.scan = scanText(core);
3213
+ const tick = () => {
3214
+ this.timer = null;
3215
+ const deadline = performance.now() + 4;
3216
+ try {
3217
+ for (let batch = 0; batch < 32; batch++) {
3218
+ const next = scan.next();
3219
+ if (next.done) {
3220
+ this.scan = null;
3221
+ this.text = next.value;
3222
+ this.element.classList.add("term-select-all");
3223
+ this.status.textContent = "";
3224
+ const resolve = this.resolve;
3225
+ this.resolve = null;
3226
+ resolve?.(true);
3227
+ return;
3228
+ }
3229
+ if (performance.now() >= deadline) break;
3230
+ }
3231
+ this.timer = setTimeout(tick, 0);
3232
+ } catch {
3233
+ this.clear();
3234
+ this.status.textContent = "Unable to select all text. Select a smaller range to copy.";
3235
+ }
3236
+ };
3237
+ this.timer = setTimeout(tick, 0);
3238
+ }
3239
+ clear(message = "") {
3240
+ if (!this.active && !this.status.textContent && !message) return;
3241
+ if (this.timer !== null) clearTimeout(this.timer);
3242
+ this.timer = null;
3243
+ this.scan?.return("");
3244
+ this.scan = null;
3245
+ this.text = null;
3246
+ this.rectangle = null;
3247
+ this.clearDecorations();
3248
+ this.element.classList.remove("term-select-all");
3249
+ this.status.textContent = message;
3250
+ if (owners.get(this.element.ownerDocument) === this) owners.delete(this.element.ownerDocument);
3251
+ const resolve = this.resolve;
3252
+ this.resolve = null;
3253
+ resolve?.(false);
3254
+ }
3255
+ invalidate() {
3256
+ if (!this.active) return;
3257
+ this.clear(this.pending ? "Terminal changed. Select all again to copy." : "");
3258
+ }
3259
+ destroy() {
3260
+ this.clear();
3261
+ const doc = this.element.ownerDocument;
3262
+ doc.removeEventListener("pointerdown", this.onPointerDown, true);
3263
+ doc.removeEventListener("focusin", this.onFocus);
3264
+ doc.removeEventListener("selectionchange", this.onSelectionChange);
3265
+ this.status.remove();
3266
+ }
3267
+ };
3268
+ //#endregion
3269
+ //#region ../../node_modules/.pnpm/@wterm+dom@0.5.4/node_modules/@wterm/dom/dist/rectangle-drag.js
3270
+ /** Own only an Alt+left drag accepted by the terminal's painted-grid checks. */
3271
+ var RectangleDrag = class {
3272
+ constructor(element, callbacks) {
3273
+ this.element = element;
3274
+ this.callbacks = callbacks;
3275
+ this.anchor = null;
3276
+ this.suppressClick = false;
3277
+ this.owned = false;
3278
+ this.lastEvent = null;
3279
+ this.frame = null;
3280
+ this.down = (event) => {
3281
+ this.cancel();
3282
+ this.owned = false;
3283
+ this.suppressClick = false;
3284
+ if (event.defaultPrevented || event.button !== 0 || !event.altKey || event.ctrlKey || event.metaKey) return;
3285
+ const anchor = this.callbacks.start(event);
3286
+ if (!anchor || !this.callbacks.select(anchor, anchor)) return;
3287
+ this.anchor = anchor;
3288
+ this.owned = true;
3289
+ event.preventDefault();
3290
+ event.stopImmediatePropagation();
3291
+ };
3292
+ this.move = (event) => {
3293
+ if (!this.owned) return;
3294
+ if (!(event.buttons & 1)) {
3295
+ this.blur();
3296
+ return;
3297
+ }
3298
+ event.preventDefault();
3299
+ event.stopImmediatePropagation();
3300
+ this.update(event);
3301
+ this.lastEvent = event;
3302
+ this.scheduleScroll();
3303
+ };
3304
+ this.up = (event) => {
3305
+ if (!this.owned || event.button !== 0) return;
3306
+ event.preventDefault();
3307
+ event.stopImmediatePropagation();
3308
+ this.update(event);
3309
+ this.cancel();
3310
+ this.owned = false;
3311
+ this.suppressClick = true;
3312
+ };
3313
+ this.click = (event) => {
3314
+ if (!this.suppressClick || event.detail === 0) return;
3315
+ this.suppressClick = false;
3316
+ event.preventDefault();
3317
+ event.stopImmediatePropagation();
3318
+ };
3319
+ this.key = (event) => {
3320
+ if (!this.anchor || event.key !== "Escape") return;
3321
+ event.preventDefault();
3322
+ event.stopImmediatePropagation();
3323
+ this.cancel();
3324
+ this.callbacks.clear();
3325
+ };
3326
+ this.cancel = () => {
3327
+ this.anchor = null;
3328
+ this.lastEvent = null;
3329
+ if (this.frame !== null) cancelAnimationFrame(this.frame);
3330
+ this.frame = null;
3331
+ };
3332
+ this.blur = () => {
3333
+ this.cancel();
3334
+ this.owned = false;
3335
+ };
3336
+ this.focus = (event) => {
3337
+ if (!this.element.contains(event.target)) this.cancel();
3338
+ };
3339
+ element.addEventListener("mousedown", this.down, true);
3340
+ element.addEventListener("click", this.click, true);
3341
+ const doc = element.ownerDocument;
3342
+ doc.addEventListener("mousemove", this.move, true);
3343
+ doc.addEventListener("mouseup", this.up, true);
3344
+ doc.addEventListener("keydown", this.key, true);
3345
+ doc.addEventListener("focusin", this.focus);
3346
+ doc.defaultView?.addEventListener("blur", this.blur);
3347
+ }
3348
+ update(event) {
3349
+ const point = this.callbacks.position(event);
3350
+ if (this.anchor && (!point || !this.callbacks.select(this.anchor, point))) this.callbacks.clear();
3351
+ }
3352
+ scheduleScroll() {
3353
+ if (this.frame !== null || !this.anchor || !this.lastEvent) return;
3354
+ this.frame = requestAnimationFrame(() => {
3355
+ this.frame = null;
3356
+ if (!this.anchor || !this.lastEvent) return;
3357
+ const rect = this.element.getBoundingClientRect();
3358
+ const y = this.lastEvent.clientY;
3359
+ const delta = y < rect.top ? Math.max(-24, y - rect.top) : y > rect.bottom ? Math.min(24, y - rect.bottom) : 0;
3360
+ const before = this.element.scrollTop;
3361
+ this.element.scrollTop += delta;
3362
+ this.update(this.lastEvent);
3363
+ if (this.element.scrollTop !== before) this.scheduleScroll();
3364
+ });
3365
+ }
3366
+ destroy() {
3367
+ this.cancel();
3368
+ this.element.removeEventListener("mousedown", this.down, true);
3369
+ this.element.removeEventListener("click", this.click, true);
3370
+ const doc = this.element.ownerDocument;
3371
+ doc.removeEventListener("mousemove", this.move, true);
3372
+ doc.removeEventListener("mouseup", this.up, true);
3373
+ doc.removeEventListener("keydown", this.key, true);
3374
+ doc.removeEventListener("focusin", this.focus);
3375
+ doc.defaultView?.removeEventListener("blur", this.blur);
3376
+ }
3377
+ };
3378
+ //#endregion
3379
+ //#region ../../node_modules/.pnpm/@wterm+dom@0.5.4/node_modules/@wterm/dom/dist/output-announcements.js
3380
+ var INTERVAL_MS = 500;
3381
+ var MAX_CELLS = 32768;
3382
+ var MAX_TEXT = 65536;
3383
+ var MAX_LINES = 20;
3384
+ var MAX_CHARACTERS = 4e3;
3385
+ var LIMIT_MESSAGE = "Output announcements paused because there is too much output. Type in the terminal or turn announcements off and on to resume.";
3386
+ /** Bounded, opt-in summaries of changes to painted terminal text. */
3387
+ var OutputAnnouncements = class {
3388
+ constructor(host, getCore, ready) {
3389
+ this.host = host;
3390
+ this.getCore = getCore;
3391
+ this.ready = ready;
3392
+ this.live = null;
3393
+ this.timer = null;
3394
+ this.previous = null;
3395
+ this.lines = 0;
3396
+ this.characters = 0;
3397
+ this.paused = false;
3398
+ /** Discard pending speech and baseline existing text after a user action. */
3399
+ this.reset = () => {
3400
+ this.invalidate();
3401
+ this.lines = 0;
3402
+ this.characters = 0;
3403
+ this.paused = false;
3404
+ const core = this.getCore();
3405
+ if (core && this.active()) {
3406
+ this.previous = this.snapshot(core);
3407
+ if (!this.previous) this.limit();
3408
+ }
3409
+ };
3410
+ host.addEventListener("focusin", this.reset);
3411
+ host.addEventListener("focusout", this.reset);
3412
+ host.ownerDocument.addEventListener("visibilitychange", this.reset);
3413
+ host.ownerDocument.defaultView?.addEventListener("blur", this.reset);
3414
+ host.ownerDocument.defaultView?.addEventListener("focus", this.reset);
3415
+ }
3416
+ setEnabled(enabled) {
3417
+ if (enabled === !!this.live) return;
3418
+ if (enabled) {
3419
+ this.live = this.host.ownerDocument.createElement("div");
3420
+ this.live.className = "term-announcements";
3421
+ this.live.setAttribute("role", "log");
3422
+ this.live.setAttribute("aria-label", "Terminal output");
3423
+ this.live.setAttribute("aria-live", "polite");
3424
+ this.live.setAttribute("aria-relevant", "additions");
3425
+ this.live.setAttribute("aria-atomic", "false");
3426
+ this.host.append(this.live);
3427
+ } else {
3428
+ this.live?.remove();
3429
+ this.live = null;
3430
+ }
3431
+ this.reset();
3432
+ }
3433
+ active() {
3434
+ return !!this.live && this.host.classList.contains("focused") && this.host.isConnected && this.host.ownerDocument.visibilityState !== "hidden" && this.host.ownerDocument.hasFocus();
3435
+ }
3436
+ input() {
3437
+ if (this.paused) this.reset();
3438
+ else {
3439
+ this.lines = 0;
3440
+ this.characters = 0;
3441
+ }
3442
+ }
3443
+ /** A resize changes coordinates, not terminal output. */
3444
+ invalidate() {
3445
+ if (this.timer !== null) clearTimeout(this.timer);
3446
+ this.timer = null;
3447
+ this.previous = null;
3448
+ this.live?.replaceChildren();
3449
+ }
3450
+ /** Called after painting. No cell reads or timers while disabled/unfocused. */
3451
+ rendered() {
3452
+ if (!this.active()) {
3453
+ this.invalidate();
3454
+ return;
3455
+ }
3456
+ if (this.paused || this.timer !== null) return;
3457
+ const core = this.getCore();
3458
+ if (!core) return;
3459
+ if (!this.previous) {
3460
+ this.previous = this.snapshot(core);
3461
+ if (!this.previous) this.limit();
3462
+ return;
3463
+ }
3464
+ this.timer = setTimeout(() => {
3465
+ this.timer = null;
3466
+ if (!this.active()) {
3467
+ this.invalidate();
3468
+ return;
3469
+ }
3470
+ if (!this.ready()) return;
3471
+ const current = this.getCore();
3472
+ if (current) this.announce(current);
3473
+ }, INTERVAL_MS);
3474
+ }
3475
+ snapshot(core, start) {
3476
+ const cols = core.getCols();
3477
+ const rows = core.getRows();
3478
+ const history = core.getScrollbackCount();
3479
+ const discarded = core.getScrollbackDiscardedCount?.() ?? 0;
3480
+ const base = history + discarded;
3481
+ const first = start ?? base;
3482
+ if (first < discarded || (base + rows - first) * cols > MAX_CELLS) return null;
3483
+ const lines = [];
3484
+ let length = 0;
3485
+ for (let row = first; row < base + rows; row++) {
3486
+ const offset = base - row - 1;
3487
+ const width = row < base ? core.getScrollbackLineLen(offset) : cols;
3488
+ if (width > cols) return null;
3489
+ let text = "";
3490
+ for (let col = 0; col < width; col++) {
3491
+ const cell = row < base ? core.getScrollbackCell(offset, col) : core.getCell(row - base, col);
3492
+ if (cell.width === 0 || cell.spacerHead) continue;
3493
+ const chars = cell.chars ?? String.fromCodePoint(cell.char || 32);
3494
+ length += chars.length;
3495
+ if (length > MAX_TEXT) return null;
3496
+ text += chars;
3497
+ }
3498
+ lines.push(text.replace(/ +$/, ""));
3499
+ }
3500
+ return {
3501
+ base: first,
3502
+ cols,
3503
+ rows,
3504
+ alternate: core.usingAltScreen(),
3505
+ lines
3506
+ };
3507
+ }
3508
+ announce(core) {
3509
+ const previous = this.previous;
3510
+ if (!previous) return;
3511
+ const base = core.getScrollbackCount() + (core.getScrollbackDiscardedCount?.() ?? 0);
3512
+ if (previous.cols !== core.getCols() || previous.rows !== core.getRows() || previous.alternate !== core.usingAltScreen() || base < previous.base) {
3513
+ this.previous = this.snapshot(core);
3514
+ return;
3515
+ }
3516
+ const current = this.snapshot(core, previous.base);
3517
+ if (!current) {
3518
+ this.limit();
3519
+ return;
3520
+ }
3521
+ const changed = current.lines.filter((line, index) => line.trim() && line !== previous.lines[index]);
3522
+ this.previous = {
3523
+ ...current,
3524
+ base,
3525
+ lines: current.lines.slice(base - current.base)
3526
+ };
3527
+ if (!changed.length) return;
3528
+ const text = changed.join("\n");
3529
+ if (this.lines + changed.length > MAX_LINES || this.characters + text.length > MAX_CHARACTERS) {
3530
+ this.limit();
3531
+ return;
3532
+ }
3533
+ this.lines += changed.length;
3534
+ this.characters += text.length;
3535
+ this.publish(text);
3536
+ }
3537
+ publish(text) {
3538
+ if (!this.live) return;
3539
+ const entry = this.host.ownerDocument.createElement("div");
3540
+ entry.textContent = text;
3541
+ this.live.replaceChildren(entry);
3542
+ }
3543
+ limit() {
3544
+ this.paused = true;
3545
+ this.previous = null;
3546
+ this.publish(LIMIT_MESSAGE);
3547
+ }
3548
+ destroy() {
3549
+ this.setEnabled(false);
3550
+ this.host.removeEventListener("focusin", this.reset);
3551
+ this.host.removeEventListener("focusout", this.reset);
3552
+ this.host.ownerDocument.removeEventListener("visibilitychange", this.reset);
3553
+ this.host.ownerDocument.defaultView?.removeEventListener("blur", this.reset);
3554
+ this.host.ownerDocument.defaultView?.removeEventListener("focus", this.reset);
3555
+ }
3556
+ };
3557
+ //#endregion
3558
+ //#region ../../node_modules/.pnpm/@wterm+dom@0.5.4/node_modules/@wterm/dom/dist/debug.js
3559
+ var FLAG_NAMES = {
3560
+ 1: "bold",
3561
+ 2: "dim",
3562
+ 4: "italic",
3563
+ 8: "underline",
3564
+ 16: "blink",
3565
+ 32: "reverse",
3566
+ 64: "invisible",
3567
+ 128: "strikethrough"
3568
+ };
3569
+ function flagsToNames(flags) {
3570
+ const names = [];
3571
+ for (const [bit, name] of Object.entries(FLAG_NAMES)) if (flags & Number(bit)) names.push(name);
3572
+ return names;
3573
+ }
3574
+ var ESC = 27;
3575
+ function scanSequences(data) {
3576
+ const entries = [];
3577
+ const ts = Date.now();
3578
+ let i = 0;
3579
+ let textStart = 0;
3580
+ const flushText = () => {
3581
+ if (i > textStart) {
3582
+ const raw = data.slice(textStart, i);
3583
+ if (raw.length > 0 && !/^[\x00-\x1f]+$/.test(raw)) entries.push({
3584
+ ts,
3585
+ type: "text",
3586
+ raw: raw.slice(0, 60)
3587
+ });
3588
+ }
3589
+ };
3590
+ while (i < data.length) {
3591
+ if (data.charCodeAt(i) !== ESC) {
3592
+ i++;
3593
+ continue;
3594
+ }
3595
+ flushText();
3596
+ const seqStart = i;
3597
+ i++;
3598
+ if (i >= data.length) break;
3599
+ const next = data[i];
3600
+ if (next === "[") {
3601
+ i++;
3602
+ let priv = "";
3603
+ if (i < data.length && (data[i] === "?" || data[i] === ">" || data[i] === "!")) {
3604
+ priv = data[i];
3605
+ i++;
3606
+ }
3607
+ let paramStr = "";
3608
+ while (i < data.length && (data.charCodeAt(i) >= 48 && data.charCodeAt(i) <= 59 || data[i] === ":")) {
3609
+ paramStr += data[i];
3610
+ i++;
3611
+ }
3612
+ while (i < data.length && data.charCodeAt(i) >= 32 && data.charCodeAt(i) <= 47) i++;
3613
+ let final = "";
3614
+ if (i < data.length && data.charCodeAt(i) >= 64 && data.charCodeAt(i) <= 126) {
3615
+ final = data[i];
3616
+ i++;
3617
+ }
3618
+ const raw = data.slice(seqStart, i);
3619
+ const params = paramStr ? paramStr.split(/[;:]/).map(Number).filter((n) => !isNaN(n)) : [];
3620
+ const type = final === "m" ? "sgr" : "csi";
3621
+ entries.push({
3622
+ ts,
3623
+ type,
3624
+ raw,
3625
+ params: params.length > 0 ? params : void 0,
3626
+ private: priv || void 0,
3627
+ final
3628
+ });
3629
+ } else if (next === "]") {
3630
+ i++;
3631
+ while (i < data.length && data.charCodeAt(i) !== 7 && !(data.charCodeAt(i) === ESC && i + 1 < data.length && data[i + 1] === "\\")) i++;
3632
+ if (i < data.length) {
3633
+ if (data.charCodeAt(i) === 7) i++;
3634
+ else if (data.charCodeAt(i) === ESC) i += 2;
3635
+ }
3636
+ const raw = data.slice(seqStart, i);
3637
+ entries.push({
3638
+ ts,
3639
+ type: "osc",
3640
+ raw: raw.slice(0, 80)
3641
+ });
3642
+ } else if (next >= " " && next <= "~") {
3643
+ i++;
3644
+ entries.push({
3645
+ ts,
3646
+ type: "esc",
3647
+ raw: data.slice(seqStart, i),
3648
+ final: next
3649
+ });
3650
+ } else i++;
3651
+ textStart = i;
3652
+ }
3653
+ flushText();
3654
+ return entries;
3655
+ }
3656
+ var MAX_TRACES = 500;
3657
+ var DebugAdapter = class {
3658
+ constructor() {
3659
+ this._traces = [];
3660
+ this._bridge = null;
3661
+ this._perf = {
3662
+ frameCount: 0,
3663
+ totalRenderMs: 0,
3664
+ avgRenderMs: 0,
3665
+ maxRenderMs: 0,
3666
+ lastDirtyRows: 0
3667
+ };
3668
+ }
3669
+ get traces() {
3670
+ return this._traces;
3671
+ }
3672
+ get perf() {
3673
+ return this._perf;
3674
+ }
3675
+ setBridge(bridge) {
3676
+ this._bridge = bridge;
3677
+ }
3678
+ traceWrite(data) {
3679
+ const entries = scanSequences(typeof data === "string" ? data : new TextDecoder().decode(data));
3680
+ for (const entry of entries) this._traces.push(entry);
3681
+ if (this._traces.length > MAX_TRACES) this._traces = this._traces.slice(-500);
3682
+ }
3683
+ recordRender(renderMs, dirtyRows) {
3684
+ this._perf.frameCount++;
3685
+ this._perf.totalRenderMs += renderMs;
3686
+ this._perf.avgRenderMs = this._perf.totalRenderMs / this._perf.frameCount;
3687
+ if (renderMs > this._perf.maxRenderMs) this._perf.maxRenderMs = renderMs;
3688
+ this._perf.lastDirtyRows = dirtyRows;
3689
+ }
3690
+ resetPerf() {
3691
+ this._perf = {
3692
+ frameCount: 0,
3693
+ totalRenderMs: 0,
3694
+ avgRenderMs: 0,
3695
+ maxRenderMs: 0,
3696
+ lastDirtyRows: 0
3697
+ };
3698
+ }
3699
+ cell(row, col) {
3700
+ if (!this._bridge) return null;
3701
+ const c = this._bridge.getCell(row, col);
3702
+ return {
3703
+ ...c,
3704
+ charStr: c.chars ?? (c.char >= 32 ? String.fromCodePoint(c.char) : ""),
3705
+ flagNames: flagsToNames(c.flags)
3706
+ };
3707
+ }
3708
+ row(row) {
3709
+ if (!this._bridge) return null;
3710
+ const cols = this._bridge.getCols();
3711
+ const cells = [];
3712
+ for (let c = 0; c < cols; c++) cells.push(this.cell(row, c));
3713
+ return cells;
3714
+ }
3715
+ grid() {
3716
+ if (!this._bridge) return null;
3717
+ const cursor = this._bridge.getCursor();
3718
+ return {
3719
+ rows: this._bridge.getRows(),
3720
+ cols: this._bridge.getCols(),
3721
+ cursor,
3722
+ altScreen: this._bridge.usingAltScreen(),
3723
+ scrollbackCount: this._bridge.getScrollbackCount()
3724
+ };
3725
+ }
3726
+ unhandled() {
3727
+ if (!this._bridge) return [];
3728
+ return this._bridge.getUnhandledSequences();
3729
+ }
3730
+ dump(count = 50) {
3731
+ const entries = this._traces.slice(-count);
3732
+ console.group(`%cwterm debug — last ${entries.length} traces`, "color: #569cd6; font-weight: bold");
3733
+ for (const e of entries) {
3734
+ const badge = e.type === "sgr" ? "%cSGR" : e.type === "csi" ? "%cCSI" : e.type === "osc" ? "%cOSC" : e.type === "esc" ? "%cESC" : "%cTXT";
3735
+ const color = 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";
3736
+ const detail = [
3737
+ e.private ? `private=${e.private}` : "",
3738
+ e.params ? `params=[${e.params}]` : "",
3739
+ e.final ? `final=${e.final}` : ""
3740
+ ].filter(Boolean).join(" ");
3741
+ console.log(`${badge} ${e.raw.slice(0, 40)}`, color, detail ? ` ${detail}` : "");
3742
+ }
3743
+ console.groupEnd();
3744
+ }
3745
+ dumpUnhandled() {
3746
+ const entries = this.unhandled();
3747
+ if (entries.length === 0) {
3748
+ console.log("%cwterm debug — no unhandled sequences", "color: #6a9955");
3749
+ return;
3750
+ }
3751
+ console.group(`%cwterm debug — ${entries.length} unhandled sequences`, "color: #d7ba7d; font-weight: bold");
3752
+ for (const e of entries) console.log(` final=${e.final} private=${e.private || "-"} params=[${e.params.slice(0, e.paramCount)}]`);
3753
+ console.groupEnd();
3754
+ }
3755
+ };
3756
+ //#endregion
3757
+ //#region ../../node_modules/.pnpm/@wterm+dom@0.5.4/node_modules/@wterm/dom/dist/search.js
3758
+ function fold(text, caseSensitive) {
3759
+ if (caseSensitive) return text;
3760
+ if (text.length <= 1) return text.toLowerCase();
3761
+ let folded = "";
3762
+ for (const char of text) folded += char.toLowerCase();
3763
+ return folded;
3764
+ }
3765
+ /** Streams cells without materializing history or an arbitrarily long line. */
3766
+ function* scanSearch(core, query, caseSensitive) {
3767
+ const needle = fold(query, caseSensitive);
3768
+ if (!needle) return;
3769
+ const prefix = new Uint32Array(needle.length);
3770
+ for (let i = 1, length = 0; i < needle.length; i++) {
3771
+ while (length > 0 && needle[i] !== needle[length]) length = prefix[length - 1];
3772
+ if (needle[i] === needle[length]) length++;
3773
+ prefix[i] = length;
3774
+ }
3775
+ const positions = new Array(needle.length);
3776
+ const history = core.getScrollbackCount();
3777
+ let matched = 0;
3778
+ let index = 0;
3779
+ let work = 0;
3780
+ let previousWrap = false;
3781
+ let previousMatch;
3782
+ for (let row = 0; row < history + core.getRows(); row++) {
3783
+ const offset = history - 1 - row;
3784
+ const metadata = row < history ? core.getScrollbackRowMetadata?.(offset) : core.getRowMetadata?.(row - history);
3785
+ if (!previousWrap || !metadata?.continuesPrevious) matched = 0;
3786
+ previousWrap = metadata?.wrapsToNext ?? false;
3787
+ const cols = row < history ? core.getScrollbackLineLen(offset) : core.getCols();
3788
+ for (let col = 0; col < cols; col++) {
3789
+ if (++work >= 256) {
3790
+ work = 0;
3791
+ yield null;
3792
+ }
3793
+ const cell = row < history ? core.getScrollbackCell(offset, col) : core.getCell(row - history, col);
3794
+ if (cell.width === 0 || cell.spacerHead) continue;
3795
+ const text = fold(cell.chars ?? String.fromCodePoint(cell.char || 32), caseSensitive);
3796
+ if (matched === 0 && text.length === 1 && text !== needle[0]) continue;
3797
+ const position = {
3798
+ row,
3799
+ col,
3800
+ endCol: Math.min(cols, col + (cell.width ?? 1))
3801
+ };
3802
+ for (let unit = 0; unit < text.length; unit++) {
3803
+ if (++work >= 256) {
3804
+ work = 0;
3805
+ yield null;
3806
+ }
3807
+ positions[index++ % needle.length] = position;
3808
+ while (matched > 0 && text[unit] !== needle[matched]) matched = prefix[matched - 1];
3809
+ if (text[unit] === needle[matched]) matched++;
3810
+ if (matched === needle.length) {
3811
+ const match = {
3812
+ start: positions[(index - needle.length) % needle.length],
3813
+ end: position
3814
+ };
3815
+ if (!previousMatch || previousMatch.start.row !== match.start.row || previousMatch.start.col !== match.start.col || previousMatch.end.row !== match.end.row || previousMatch.end.endCol !== match.end.endCol) {
3816
+ yield match;
3817
+ previousMatch = match;
3818
+ }
3819
+ matched = prefix[matched - 1];
3820
+ }
3821
+ }
3822
+ }
3823
+ if (++work >= 256) {
3824
+ work = 0;
3825
+ yield null;
3826
+ }
3827
+ }
3828
+ }
3829
+ /** Owns cancellation and small scan slices; WTerm resumes only after painting. */
3830
+ var SearchController = class {
3831
+ constructor(changed) {
3832
+ this.changed = changed;
3833
+ this.matches = [];
3834
+ this.state = {
3835
+ query: "",
3836
+ caseSensitive: false,
3837
+ count: 0,
3838
+ activeIndex: -1,
3839
+ searching: false,
3840
+ limited: false
3841
+ };
3842
+ this.timer = null;
3843
+ this.channel = null;
3844
+ this.scan = null;
3845
+ this.pending = false;
3846
+ this.revealFirst = false;
3847
+ }
3848
+ snapshot() {
3849
+ return { ...this.state };
3850
+ }
3851
+ search(query, options) {
3852
+ if (query.length > 1024) throw new RangeError("Search query exceeds 1,024 UTF-16 code units");
3853
+ this.state.query = query;
3854
+ this.state.caseSensitive = options.caseSensitive ?? false;
3855
+ this.revealFirst = true;
3856
+ this.invalidate();
3857
+ }
3858
+ invalidate() {
3859
+ this.cancel();
3860
+ this.matches = [];
3861
+ this.state.count = 0;
3862
+ this.state.activeIndex = -1;
3863
+ this.state.limited = false;
3864
+ this.pending = this.state.searching = this.state.query.length > 0;
3865
+ this.changed(false);
3866
+ }
3867
+ resume(core) {
3868
+ if (!this.pending) return;
3869
+ this.pending = false;
3870
+ const scan = this.scan = scanSearch(core, this.state.query, this.state.caseSensitive);
3871
+ const tick = () => {
3872
+ if (this.scan !== scan) return;
3873
+ this.timer = null;
3874
+ const deadline = performance.now() + 4;
3875
+ let done = false;
3876
+ do {
3877
+ const next = scan.next();
3878
+ if (next.done) {
3879
+ done = true;
3880
+ break;
3881
+ }
3882
+ if (next.value) {
3883
+ if (this.matches.length === 1e4) {
3884
+ this.state.limited = true;
3885
+ done = true;
3886
+ break;
3887
+ }
3888
+ this.matches.push(next.value);
3889
+ }
3890
+ } while (performance.now() < deadline);
3891
+ this.state.count = this.matches.length;
3892
+ const reveal = this.revealFirst && this.matches.length > 0;
3893
+ if (this.matches.length && this.state.activeIndex === -1) this.state.activeIndex = 0;
3894
+ if (reveal) this.revealFirst = false;
3895
+ this.state.searching = !done;
3896
+ if (done) {
3897
+ scan.return(void 0);
3898
+ this.scan = null;
3899
+ this.clearTask();
3900
+ }
3901
+ this.changed(reveal);
3902
+ if (this.scan === scan) this.schedule(tick);
3903
+ };
3904
+ this.schedule(tick);
3905
+ }
3906
+ schedule(tick) {
3907
+ if (typeof MessageChannel === "undefined") this.timer = setTimeout(tick, 0);
3908
+ else {
3909
+ const channel = this.channel ?? (this.channel = new MessageChannel());
3910
+ channel.port1.onmessage = tick;
3911
+ channel.port2.postMessage(null);
3912
+ }
3913
+ }
3914
+ clearTask() {
3915
+ if (this.timer !== null) clearTimeout(this.timer);
3916
+ this.timer = null;
3917
+ if (this.channel) {
3918
+ this.channel.port1.onmessage = null;
3919
+ this.channel.port1.close();
3920
+ this.channel.port2.close();
3921
+ this.channel = null;
3922
+ }
3923
+ }
3924
+ navigate(direction) {
3925
+ if (!this.matches.length) return false;
3926
+ this.state.activeIndex = (this.state.activeIndex + direction + this.matches.length) % this.matches.length;
3927
+ this.revealFirst = false;
3928
+ this.changed(true);
3929
+ return true;
3930
+ }
3931
+ cancel() {
3932
+ this.clearTask();
3933
+ this.scan?.return(void 0);
3934
+ this.scan = null;
3935
+ this.pending = false;
3936
+ this.matches = [];
3937
+ this.state.count = 0;
3938
+ this.state.activeIndex = -1;
3939
+ this.state.searching = false;
3940
+ this.state.limited = false;
3941
+ }
3942
+ };
3943
+ //#endregion
3944
+ //#region ../../node_modules/.pnpm/@wterm+dom@0.5.4/node_modules/@wterm/dom/dist/wterm.js
3945
+ var SYNCHRONIZED_OUTPUT_TIMEOUT_MS = 1e3;
3946
+ var PROGRAMMATIC_SCROLL_TOLERANCE = 1;
3947
+ var WTerm = class {
3948
+ constructor(element, options = {}) {
3949
+ this.bridge = null;
3950
+ this.debug = null;
3951
+ this._themeColors = null;
3952
+ this.renderer = null;
3953
+ this.input = null;
3954
+ this.rafId = null;
3955
+ this._synchronizedOutputTimer = null;
3956
+ this._synchronizedOutputState = "idle";
3957
+ this._synchronizedOutputGeneration = 0;
3958
+ this._rendererNeedsSetup = false;
3959
+ this.resizeObserver = null;
3960
+ this._destroyed = false;
3961
+ this._shouldScrollToBottom = false;
3962
+ this._scrollbackDiscardedCount = 0;
3963
+ this._programmaticScrollTop = null;
3964
+ this._pendingResizeScrollTop = null;
3965
+ this._rowHeight = 0;
3966
+ this._charWidth = 0;
3967
+ this._windowSizeQueryState = 0;
3968
+ this._textCapture = new TextCapture();
3969
+ this._searchReveal = false;
3970
+ this.element = element;
3971
+ this._coreOption = options.core;
3972
+ this._initialColsExplicit = options.cols !== void 0;
3973
+ this._initialRowsExplicit = options.rows !== void 0;
3974
+ this.wasmUrl = options.wasmUrl;
3975
+ this.maxImageWidth = options.maxImageWidth;
3976
+ this.maxImageHeight = options.maxImageHeight;
3977
+ this.cols = options.cols || 80;
3978
+ this.rows = options.rows || 24;
3979
+ this.autoResize = options.autoResize !== false;
3980
+ this._debugEnabled = options.debug ?? false;
3981
+ this._renderingPaused = options.renderingPaused ?? false;
3982
+ this.onData = options.onData || null;
3983
+ this.onBinary = options.onBinary || null;
3984
+ this.onTitle = options.onTitle || null;
3985
+ this.onWorkingDirectory = options.onWorkingDirectory || null;
3986
+ this.onBell = options.onBell || null;
3987
+ this.onShellIntegration = options.onShellIntegration || null;
3988
+ this.onClipboardWrite = options.onClipboardWrite || null;
3989
+ this.onResize = options.onResize || null;
3990
+ this.onSearchChange = options.onSearchChange || null;
3991
+ this._search = new SearchController((reveal) => {
3992
+ this._searchReveal || (this._searchReveal = reveal);
3993
+ if (reveal) {
3994
+ const match = this._search.matches[this.getSearchState().activeIndex];
3995
+ if (match) {
3996
+ this._shouldScrollToBottom = false;
3997
+ this._pendingResizeScrollTop = null;
3998
+ this._setScrollTop((match.start.row + .5) * this._rowHeight - this.element.clientHeight / 2);
3999
+ }
4000
+ }
4001
+ if (this._synchronizedOutputState !== "held") this._scheduleRender();
4002
+ this.onSearchChange?.(this.getSearchState());
4003
+ });
4004
+ this._container = document.createElement("div");
4005
+ this._container.className = "term-grid";
4006
+ this.element.appendChild(this._container);
4007
+ this.element.classList.add("wterm");
4008
+ this._historySelection = new HistorySelection(this.element);
4009
+ this._rectangleDrag = new RectangleDrag(this.element, {
4010
+ start: (event) => {
4011
+ if (!(event.target instanceof Element) || !this.bridge || !this._canRender()) return null;
4012
+ const point = this.renderer?.positionAt(event.target, event.clientX, this._charWidth);
4013
+ if (!point || !event.shiftKey && this.bridge.mouseTracking?.() && point.row >= this.bridge.getScrollbackCount()) return null;
4014
+ return point;
4015
+ },
4016
+ position: (event) => {
4017
+ const bounds = this.element.getBoundingClientRect();
4018
+ return this.renderer?.dragPositionAt(event.clientX, Math.max(bounds.top + 1, Math.min(bounds.bottom - 1, event.clientY)), this._charWidth) ?? null;
4019
+ },
4020
+ select: (start, end) => this.selectRectangle(start, end),
4021
+ clear: () => this._historySelection.clear()
4022
+ });
4023
+ this._outputAnnouncements = new OutputAnnouncements(this.element, () => this.bridge, () => this._canRender() && this.rafId === null && this._synchronizedOutputState !== "held");
4024
+ this._outputAnnouncements.setEnabled(options.announceOutput ?? false);
4025
+ this._onVisibilityChange = () => {
4026
+ if (this._canRender()) this._scheduleRender();
4027
+ else {
4028
+ this._rectangleDrag.cancel();
4029
+ this._cancelScheduledRender();
4030
+ this._outputAnnouncements.invalidate();
4031
+ }
4032
+ };
4033
+ this.element.ownerDocument.addEventListener("visibilitychange", this._onVisibilityChange);
4034
+ this.element.classList.toggle("cursor-blink", options.cursorBlink === true);
4035
+ this.element.classList.toggle("cursor-steady", options.cursorBlink === false);
4036
+ this._onClickFocus = (event) => {
4037
+ if (event.defaultPrevented || this._historySelection.active) return;
4038
+ const target = event.target;
4039
+ if (target instanceof Element && target.closest(".term-link")) {
4040
+ if (isLinkActivationModifier(event, this.element.ownerDocument.defaultView?.navigator ?? navigator) || event.detail === 0) return;
4041
+ event.preventDefault();
4042
+ }
4043
+ const sel = window.getSelection();
4044
+ if (!sel || sel.isCollapsed) this.input?.focus();
4045
+ };
4046
+ this._onMouseSelect = (event) => {
4047
+ if (event.defaultPrevented || event.button !== 0 || event.detail !== 2 && event.detail !== 3 || event.altKey || event.ctrlKey || event.metaKey || !(event.target instanceof Element)) return;
4048
+ const position = this.renderer?.positionAt(event.target, event.clientX, this._charWidth);
4049
+ if (!position || !this.bridge) return;
4050
+ if (!event.shiftKey && this.bridge.mouseTracking?.() && position.row >= this.bridge.getScrollbackCount()) return;
4051
+ if (event.detail === 2 ? this.selectWord(position) : this.selectLine(position.row)) event.preventDefault();
4052
+ };
4053
+ this.element.addEventListener("click", this._onMouseSelect);
4054
+ this.element.addEventListener("click", this._onClickFocus);
4055
+ this._onModifierChange = (event) => {
4056
+ this.element.classList.toggle("link-modifier-active", isLinkActivationModifier(event, this.element.ownerDocument.defaultView?.navigator ?? navigator));
4057
+ };
4058
+ this._onWindowBlur = () => {
4059
+ this.element.classList.remove("link-modifier-active");
4060
+ };
4061
+ this.element.ownerDocument.addEventListener("keydown", this._onModifierChange);
4062
+ this.element.ownerDocument.addEventListener("keyup", this._onModifierChange);
4063
+ this.element.ownerDocument.defaultView?.addEventListener("blur", this._onWindowBlur);
4064
+ this._onScroll = () => {
4065
+ if (this._pendingResizeScrollTop !== null) return;
4066
+ if (this._shouldScrollToBottom && this._isScrolledToBottom()) {
4067
+ this._programmaticScrollTop = null;
4068
+ return;
4069
+ }
4070
+ if (this._programmaticScrollTop !== null && Math.abs(this.element.scrollTop - this._programmaticScrollTop) <= PROGRAMMATIC_SCROLL_TOLERANCE) {
4071
+ this._programmaticScrollTop = null;
4072
+ return;
4073
+ }
4074
+ this._programmaticScrollTop = null;
4075
+ this._shouldScrollToBottom = false;
4076
+ this._scheduleRender();
4077
+ };
4078
+ this.element.addEventListener("scroll", this._onScroll, { passive: true });
4079
+ this._onCopy = (event) => {
4080
+ if (event.defaultPrevented || !event.clipboardData) return;
4081
+ const target = event.target;
4082
+ if (target instanceof Element && !this.element.contains(target) && (target.closest("input, textarea") || target.isContentEditable)) return;
4083
+ const text = this.getSelectionText();
4084
+ if (this._historySelection.pending) {
4085
+ event.preventDefault();
4086
+ return;
4087
+ }
4088
+ if (text === null) return;
4089
+ event.clipboardData.setData("text/plain", text);
4090
+ event.preventDefault();
4091
+ };
4092
+ this.element.ownerDocument.addEventListener("copy", this._onCopy);
4093
+ }
4094
+ async init() {
4095
+ try {
4096
+ if (this._coreOption) this.bridge = this._coreOption;
4097
+ else this.bridge = await WasmBridge.load(this.wasmUrl);
4098
+ if (this._destroyed) return this;
4099
+ const initialCols = this.cols;
4100
+ const initialRows = this.rows;
4101
+ this._setRowHeight();
4102
+ if (this.autoResize) {
4103
+ const size = this._measureGridSize();
4104
+ if (size) {
4105
+ if (!this._initialColsExplicit) this.cols = size.cols;
4106
+ if (!this._initialRowsExplicit) this.rows = size.rows;
4107
+ }
4108
+ }
4109
+ this.bridge.init(this.cols, this.rows);
4110
+ if (this._themeColors) this.bridge.setThemeColors?.(this._themeColors);
4111
+ this.cols = this.bridge.getCols();
4112
+ this.rows = this.bridge.getRows();
4113
+ if (this._debugEnabled) {
4114
+ this.debug = new DebugAdapter();
4115
+ this.debug.setBridge(this.bridge);
4116
+ globalThis.__wterm = this;
4117
+ }
4118
+ this._measureCharSize();
4119
+ this.renderer = new Renderer(this._container, {
4120
+ colorHost: this.element,
4121
+ maxImageWidth: this.maxImageWidth,
4122
+ maxImageHeight: this.maxImageHeight
4123
+ });
4124
+ this.renderer.setup(this.cols, this.rows);
4125
+ this.input = new InputHandler(this.element, (data, preserveScroll = false) => {
4126
+ if (!preserveScroll) {
4127
+ this._outputAnnouncements.input();
4128
+ this._scrollToBottom();
4129
+ }
4130
+ if (this.onData) this.onData(data);
4131
+ else this.write(data);
4132
+ }, () => this.bridge, () => this._charWidth > 0 && this._rowHeight > 0 ? {
4133
+ charWidth: this._charWidth,
4134
+ rowHeight: this._rowHeight
4135
+ } : null, () => {
4136
+ this._rectangleDrag.cancel();
4137
+ this._historySelection.clear();
4138
+ this._scrollToBottom();
4139
+ }, (data) => {
4140
+ this._outputAnnouncements.input();
4141
+ this._rectangleDrag.cancel();
4142
+ this._historySelection.clear();
4143
+ this._scrollToBottom();
4144
+ if (this.onBinary) this.onBinary(data);
4145
+ else if (!this.onData) this.write(data);
4146
+ else if (data.every((byte) => byte < 128)) this.onData(String.fromCharCode(...data));
4147
+ }, {
4148
+ selectAll: () => {
4149
+ this.selectAll();
4150
+ },
4151
+ hasSelection: () => this._historySelection.active,
4152
+ clearSelection: () => {
4153
+ this._rectangleDrag.cancel();
4154
+ this._historySelection.clear();
4155
+ }
4156
+ });
4157
+ this._setupResizeObserver();
4158
+ if (!this.autoResize) this._lockHeight();
4159
+ this.input.focus();
4160
+ this._initialRender();
4161
+ if (this.cols !== initialCols || this.rows !== initialRows) this.onResize?.(this.cols, this.rows);
4162
+ } catch (err) {
4163
+ this.destroy();
4164
+ throw new Error(`wterm: failed to initialize: ${err instanceof Error ? err.message : err}`);
4165
+ }
4166
+ return this;
4167
+ }
4168
+ _isScrolledToBottom() {
4169
+ const el = this.element;
4170
+ return el.scrollHeight - el.scrollTop - el.clientHeight < 5;
4171
+ }
4172
+ _scrollToBottom() {
4173
+ this._setScrollTop(this.element.scrollHeight);
4174
+ }
4175
+ _setScrollTop(value) {
4176
+ const before = this.element.scrollTop;
4177
+ this.element.scrollTop = value;
4178
+ const after = this.element.scrollTop;
4179
+ if (after === before) return;
4180
+ this._programmaticScrollTop = after;
4181
+ }
4182
+ /** Apply host colors without writing terminal input or restarting the session. */
4183
+ setThemeColors(colors) {
4184
+ const values = [
4185
+ colors.foreground,
4186
+ colors.background,
4187
+ colors.cursor,
4188
+ ...colors.palette
4189
+ ];
4190
+ if (colors.palette.length !== 16 || values.some((value) => !Number.isInteger(value) || value < 0 || value > 16777215)) throw new RangeError("Theme colors must be 24-bit RGB values with exactly 16 palette entries");
4191
+ if (this._destroyed) return;
4192
+ const copy = {
4193
+ ...colors,
4194
+ palette: [...colors.palette]
4195
+ };
4196
+ this.bridge?.setThemeColors?.(copy);
4197
+ this._themeColors = copy;
4198
+ const properties = [
4199
+ "--term-fg",
4200
+ "--term-bg",
4201
+ "--term-cursor",
4202
+ ...colors.palette.map((_, index) => `--term-color-${index}`)
4203
+ ];
4204
+ values.forEach((value, index) => this.element.style.setProperty(properties[index], `#${value.toString(16).padStart(6, "0")}`));
4205
+ this.renderer?.invalidateColors();
4206
+ this._scheduleRender();
4207
+ }
4208
+ write(data) {
4209
+ if (!this.bridge || this._destroyed) return;
4210
+ this._textCapture.cancel();
4211
+ this._rectangleDrag.cancel();
4212
+ this._historySelection.invalidate();
4213
+ this.renderer?.beforeMutation(this.bridge);
4214
+ if (this.debug) this.debug.traceWrite(data);
4215
+ this._shouldScrollToBottom = this._isScrolledToBottom();
4216
+ const windowSizeQueries = this._collectWindowSizeQueries(data);
4217
+ let deliveryError;
4218
+ let hasDeliveryError = false;
4219
+ const recordDeliveryError = (error) => {
4220
+ if (hasDeliveryError) return;
4221
+ hasDeliveryError = true;
4222
+ deliveryError = error;
4223
+ };
4224
+ const drain = () => {
4225
+ const result = this._drainResponses();
4226
+ if (result.hasError) recordDeliveryError(result.error);
4227
+ const bells = this.bridge?.getBellCount?.() ?? 0;
4228
+ if (bells > 0) try {
4229
+ this.onBell?.(bells);
4230
+ } catch (error) {
4231
+ recordDeliveryError(error);
4232
+ }
4233
+ try {
4234
+ this._deliverTitle();
4235
+ } catch (error) {
4236
+ recordDeliveryError(error);
4237
+ }
4238
+ try {
4239
+ const text = this.bridge?.getClipboardWrite?.() ?? null;
4240
+ if (text !== null && !this._destroyed) this.onClipboardWrite?.(text);
4241
+ } catch (error) {
4242
+ recordDeliveryError(error);
4243
+ }
4244
+ try {
4245
+ const state = this.bridge?.getShellIntegrationState?.() ?? null;
4246
+ if (state !== null && !this._destroyed) this.onShellIntegration?.(state);
4247
+ } catch (error) {
4248
+ recordDeliveryError(error);
4249
+ }
4250
+ try {
4251
+ const uri = this.bridge?.getWorkingDirectory?.() ?? null;
4252
+ if (uri !== null && !this._destroyed) this.onWorkingDirectory?.(uri);
4253
+ } catch (error) {
4254
+ recordDeliveryError(error);
4255
+ }
4256
+ };
4257
+ if (typeof data === "string") this.bridge.writeString(data, drain);
4258
+ else this.bridge.writeRaw(data, drain);
4259
+ const synchronized = this.bridge.synchronizedOutput?.() ?? false;
4260
+ const generation = this.bridge.synchronizedOutputGeneration?.() ?? 0;
4261
+ this._updateSynchronizedOutput(synchronized, generation);
4262
+ this._invalidateSearch();
4263
+ if (this._synchronizedOutputState !== "held") {
4264
+ this._setupRendererIfNeeded();
4265
+ this._scheduleRender();
4266
+ }
4267
+ drain();
4268
+ for (const query of windowSizeQueries) try {
4269
+ this.onData?.(this._windowSizeResponse(query));
4270
+ } catch (error) {
4271
+ recordDeliveryError(error);
4272
+ }
4273
+ if (hasDeliveryError) throw deliveryError;
4274
+ }
4275
+ /** Fit the grid to the current element and font metrics. */
4276
+ fit() {
4277
+ if (!this.bridge || this._destroyed) return;
4278
+ const size = this._measureGridSize();
4279
+ if (size && (size.cols !== this.cols || size.rows !== this.rows)) this.resize(size.cols, size.rows);
4280
+ }
4281
+ _measureGridSize() {
4282
+ const measured = this._measureCharSize();
4283
+ if (!measured) return null;
4284
+ const style = getComputedStyle(this.element);
4285
+ const rect = this.element.getBoundingClientRect();
4286
+ const pixels = (value) => parseFloat(value) || 0;
4287
+ const bordersX = pixels(style.borderLeftWidth) + pixels(style.borderRightWidth);
4288
+ const bordersY = pixels(style.borderTopWidth) + pixels(style.borderBottomWidth);
4289
+ const scrollbarWidth = Math.max(0, this.element.offsetWidth - this.element.clientWidth - bordersX);
4290
+ const scrollbarHeight = Math.max(0, this.element.offsetHeight - this.element.clientHeight - bordersY);
4291
+ const width = rect.width - pixels(style.paddingLeft) - pixels(style.paddingRight) - bordersX - scrollbarWidth;
4292
+ const height = rect.height - pixels(style.paddingTop) - pixels(style.paddingBottom) - bordersY - scrollbarHeight;
4293
+ if (width <= 0 || height <= 0) return null;
4294
+ return {
4295
+ cols: Math.max(1, Math.floor(width / measured.charWidth)),
4296
+ rows: Math.max(1, Math.floor(height / measured.rowHeight))
4297
+ };
4298
+ }
4299
+ resize(cols, rows) {
4300
+ if (!this.bridge || this._destroyed) return;
4301
+ this._textCapture.cancel();
4302
+ this._rectangleDrag.cancel();
4303
+ this._historySelection.invalidate();
4304
+ this.renderer?.beforeMutation(this.bridge);
4305
+ this._shouldScrollToBottom = this._pendingResizeScrollTop === null && this._isScrolledToBottom();
4306
+ this.bridge.resize(cols, rows);
4307
+ this._outputAnnouncements.invalidate();
4308
+ this.cols = this.bridge.getCols();
4309
+ this.rows = this.bridge.getRows();
4310
+ const synchronized = this.bridge.synchronizedOutput?.() ?? false;
4311
+ const generation = this.bridge.synchronizedOutputGeneration?.() ?? 0;
4312
+ if (this._updateSynchronizedOutput(synchronized, generation)) this._rendererNeedsSetup = true;
4313
+ else {
4314
+ this._setupRenderer();
4315
+ this._scheduleRender();
4316
+ }
4317
+ this._invalidateSearch();
4318
+ if (this.onResize) this.onResize(this.cols, this.rows);
4319
+ }
4320
+ /** Search retained history and the active screen, using plain text. */
4321
+ search(query, options = {}) {
4322
+ if (this._destroyed) return;
4323
+ this._search.search(query, options);
4324
+ this._paintSearch();
4325
+ }
4326
+ findNext() {
4327
+ return !this._destroyed && this._search.navigate(1);
4328
+ }
4329
+ findPrevious() {
4330
+ return !this._destroyed && this._search.navigate(-1);
4331
+ }
4332
+ clearSearch() {
4333
+ this.search("");
4334
+ }
4335
+ getSearchState() {
4336
+ return this._search.snapshot();
4337
+ }
4338
+ /** Scroll to the previous (-1) or next (1) shell prompt from the viewport top. */
4339
+ scrollToPrompt(direction) {
4340
+ if (!this._canRender() || !this.bridge?.findPrompt || !this.renderer || this._synchronizedOutputState === "held" || this.bridge.usingAltScreen() || direction !== -1 && direction !== 1) return false;
4341
+ this._cancelScheduledRender();
4342
+ this._doRender();
4343
+ if (direction === 1 && this._isScrolledToBottom()) return false;
4344
+ const bounds = this.element.getBoundingClientRect();
4345
+ const origin = this.renderer.dragPositionAt(bounds.left, bounds.top + this.element.clientTop + 1, this._charWidth);
4346
+ if (!origin) return false;
4347
+ const target = this.bridge.findPrompt(origin.row, direction);
4348
+ if (target === null || !Number.isInteger(target) || target < 0 || target >= this.bridge.getScrollbackCount() + this.rows || (direction < 0 ? target >= origin.row : target <= origin.row)) return false;
4349
+ const before = this.element.scrollTop;
4350
+ this._shouldScrollToBottom = false;
4351
+ this._searchReveal = false;
4352
+ this._pendingResizeScrollTop = target * this._rowHeight;
4353
+ this._doRender();
4354
+ const mounted = Array.from(this.renderer.searchRows()).find(({ row }) => row === target);
4355
+ if (mounted) this._setScrollTop(this.element.scrollTop + mounted.element.getBoundingClientRect().top - bounds.top - this.element.clientTop);
4356
+ this._scheduleRender();
4357
+ return Math.abs(this.element.scrollTop - before) > PROGRAMMATIC_SCROLL_TOLERANCE;
4358
+ }
4359
+ /** Enable or stop polite announcements without changing terminal focus. */
4360
+ setOutputAnnouncements(enabled) {
4361
+ if (!this._destroyed) this._outputAnnouncements.setEnabled(enabled);
4362
+ }
4363
+ /** Pause pane painting without buffering output or stopping terminal effects. */
4364
+ setRenderingPaused(paused) {
4365
+ if (this._destroyed || paused === this._renderingPaused) return;
4366
+ this._renderingPaused = paused;
4367
+ this._onVisibilityChange();
4368
+ }
4369
+ _canRender() {
4370
+ return !this._destroyed && !this._renderingPaused && this.element.ownerDocument.visibilityState !== "hidden";
4371
+ }
4372
+ /** Capture retained history and the active screen without changing selection. */
4373
+ readText(options = {}) {
4374
+ if (this._destroyed || !this.renderer || !this.bridge) return Promise.reject(/* @__PURE__ */ new Error("Terminal is not initialized"));
4375
+ const captured = this._textCapture.read(options.signal);
4376
+ this._scheduleRender();
4377
+ return captured;
4378
+ }
4379
+ /** Read the terminal selection with terminal line and cell semantics. */
4380
+ getSelectionText() {
4381
+ if (this._destroyed) return null;
4382
+ return this._historySelection.getText() ?? this.renderer?.getSelectionText() ?? null;
4383
+ }
4384
+ /** Select retained history and the active screen without mounting extra rows. */
4385
+ selectAll() {
4386
+ if (this._destroyed || !this.renderer || !this.bridge) return Promise.resolve(false);
4387
+ this._rectangleDrag.cancel();
4388
+ const selected = this._historySelection.select();
4389
+ this._scheduleRender();
4390
+ return selected;
4391
+ }
4392
+ /** Select a word at a cell, with row zero at the oldest retained row. */
4393
+ selectWord(position) {
4394
+ return this._selectUnit(position, "word");
4395
+ }
4396
+ /** Select the logical line containing a retained-buffer row. */
4397
+ selectLine(row) {
4398
+ return this._selectUnit({
4399
+ row,
4400
+ col: 0
4401
+ }, "line");
4402
+ }
4403
+ /** Select inclusive rectangle corners in retained physical-row coordinates. */
4404
+ selectRectangle(start, end) {
4405
+ if (this._destroyed || !this.bridge || !this.renderer || !this._canRender()) return false;
4406
+ const rectangle = this.renderer.rectangle(this.bridge, start, end, () => {
4407
+ this.input?.focus();
4408
+ });
4409
+ if (!rectangle) return false;
4410
+ this._historySelection.selectRectangle(rectangle);
4411
+ this._historySelection.paintRectangle(this.renderer.searchRows(), this._charWidth);
4412
+ return true;
4413
+ }
4414
+ _selectUnit(position, unit) {
4415
+ if (this._destroyed || !this.bridge || !this.renderer) return false;
4416
+ return this.renderer.select(this.bridge, position, unit, () => {
4417
+ this._rectangleDrag.cancel();
4418
+ this._historySelection.clear();
4419
+ const active = this.element.ownerDocument.activeElement;
4420
+ if (active instanceof HTMLElement && this.element.contains(active) && active.tagName === "TEXTAREA") active.blur();
4421
+ });
4422
+ }
4423
+ /** Clear custom selection and any native selection wholly owned by this terminal. */
4424
+ clearSelection() {
4425
+ this._rectangleDrag.cancel();
4426
+ this._historySelection.clear();
4427
+ const selection = this.element.ownerDocument.getSelection();
4428
+ if (!selection || selection.isCollapsed) return;
4429
+ for (let index = 0; index < selection.rangeCount; index++) {
4430
+ const range = selection.getRangeAt(index);
4431
+ if (!this.element.contains(range.startContainer) || !this.element.contains(range.endContainer)) return;
4432
+ }
4433
+ selection.removeAllRanges();
4434
+ }
4435
+ _invalidateSearch() {
4436
+ if (!this.getSearchState().query) return;
4437
+ this._searchReveal = false;
4438
+ this._search.invalidate();
4439
+ this._paintSearch();
4440
+ }
4441
+ _paintSearch() {
4442
+ if (!this.renderer || !this.bridge || !this._canRender()) return;
4443
+ const fragment = document.createDocumentFragment();
4444
+ const matches = this._search.matches;
4445
+ if (!matches.length) {
4446
+ this.renderer.setSearchDecorations(fragment);
4447
+ return;
4448
+ }
4449
+ const active = this.getSearchState().activeIndex;
4450
+ const viewport = this.element.getBoundingClientRect();
4451
+ for (const { row, element } of this.renderer.searchRows()) {
4452
+ const rect = element.getBoundingClientRect();
4453
+ if (rect.bottom <= viewport.top || rect.top >= viewport.bottom) continue;
4454
+ let low = 0, high = matches.length;
4455
+ while (low < high) {
4456
+ const mid = low + high >>> 1;
4457
+ if (matches[mid].end.row < row) low = mid + 1;
4458
+ else high = mid;
4459
+ }
4460
+ const history = this.bridge.getScrollbackCount();
4461
+ const offset = history - row - 1;
4462
+ let cols = row < history ? this.bridge.getScrollbackLineLen(offset) : this.cols;
4463
+ if (cols <= 0) continue;
4464
+ if ((row < history ? this.bridge.getScrollbackCell(offset, cols - 1) : this.bridge.getCell(row - history, cols - 1)).spacerHead) cols--;
4465
+ let rangeStart = -1, rangeEnd = -1;
4466
+ const draw = (start, end, selected) => {
4467
+ if (end <= start) return;
4468
+ const mark = document.createElement("div");
4469
+ mark.className = `term-search-match${selected ? " term-search-active" : ""}`;
4470
+ mark.style.cssText = `left:${start * this._charWidth}px;top:${element.offsetTop}px;width:${(end - start) * this._charWidth}px;height:${rect.height}px`;
4471
+ fragment.appendChild(mark);
4472
+ };
4473
+ for (let i = low; i < matches.length && matches[i].start.row <= row; i++) {
4474
+ const match = matches[i];
4475
+ const start = match.start.row === row ? match.start.col : 0;
4476
+ const end = Math.min(cols, match.end.row === row ? match.end.endCol : cols);
4477
+ if (rangeStart >= 0 && start > rangeEnd) {
4478
+ draw(rangeStart, rangeEnd, false);
4479
+ rangeStart = -1;
4480
+ }
4481
+ if (rangeStart < 0) rangeStart = start;
4482
+ rangeEnd = Math.max(rangeEnd, end);
4483
+ }
4484
+ if (rangeStart >= 0) draw(rangeStart, rangeEnd, false);
4485
+ const selected = matches[active];
4486
+ if (selected && selected.start.row <= row && selected.end.row >= row) draw(selected.start.row === row ? selected.start.col : 0, Math.min(cols, selected.end.row === row ? selected.end.endCol : cols), true);
4487
+ }
4488
+ this.renderer.setSearchDecorations(fragment);
4489
+ }
4490
+ focus() {
4491
+ if (this.input) this.input.focus();
4492
+ else this.element.focus();
4493
+ }
4494
+ _scheduleRender() {
4495
+ if (!this._canRender() || this._synchronizedOutputState === "held" || this.rafId != null) return;
4496
+ this.rafId = requestAnimationFrame(() => {
4497
+ this.rafId = null;
4498
+ this._doRender();
4499
+ });
4500
+ }
4501
+ _cancelScheduledRender() {
4502
+ if (this.rafId != null) {
4503
+ cancelAnimationFrame(this.rafId);
4504
+ this.rafId = null;
4505
+ }
4506
+ }
4507
+ _updateSynchronizedOutput(synchronized, generation) {
4508
+ if (!synchronized) {
4509
+ if (this._synchronizedOutputState === "held") this._cancelSynchronizedOutputFallback();
4510
+ this._synchronizedOutputState = "idle";
4511
+ return false;
4512
+ }
4513
+ if (this._synchronizedOutputState === "held" && generation !== this._synchronizedOutputGeneration) {
4514
+ this._armSynchronizedOutputFallback(generation);
4515
+ return true;
4516
+ } else if (this._synchronizedOutputState === "passthrough" && generation !== this._synchronizedOutputGeneration) this._synchronizedOutputState = "idle";
4517
+ if (this._synchronizedOutputState !== "idle") return this._synchronizedOutputState === "held";
4518
+ this._synchronizedOutputState = "held";
4519
+ this._cancelScheduledRender();
4520
+ this._armSynchronizedOutputFallback(generation);
4521
+ return true;
4522
+ }
4523
+ _armSynchronizedOutputFallback(generation) {
4524
+ this._cancelSynchronizedOutputFallback();
4525
+ this._synchronizedOutputGeneration = generation;
4526
+ this._synchronizedOutputTimer = setTimeout(() => {
4527
+ if (this._synchronizedOutputState !== "held" || this._synchronizedOutputGeneration !== generation) return;
4528
+ this._synchronizedOutputTimer = null;
4529
+ this._synchronizedOutputState = "passthrough";
4530
+ this._setupRendererIfNeeded();
4531
+ this._cancelScheduledRender();
4532
+ this._doRender();
4533
+ }, SYNCHRONIZED_OUTPUT_TIMEOUT_MS);
4534
+ }
4535
+ _cancelSynchronizedOutputFallback() {
4536
+ if (this._synchronizedOutputTimer == null) return;
4537
+ clearTimeout(this._synchronizedOutputTimer);
4538
+ this._synchronizedOutputTimer = null;
4539
+ }
4540
+ _setupRendererIfNeeded() {
4541
+ if (!this._rendererNeedsSetup) return;
4542
+ this._setupRenderer();
4543
+ this._rendererNeedsSetup = false;
4544
+ }
4545
+ _setupRenderer() {
4546
+ if (!this._shouldScrollToBottom && this._pendingResizeScrollTop === null) this._pendingResizeScrollTop = this.element.scrollTop;
4547
+ this.renderer?.requestSetup();
4548
+ }
4549
+ _initialRender() {
4550
+ this._doRender();
4551
+ }
4552
+ _doRender() {
4553
+ if (!this._canRender() || !this.bridge || !this.renderer || this._synchronizedOutputState === "held") return;
4554
+ let dirtyCount = 0;
4555
+ const t0 = this.debug ? performance.now() : 0;
4556
+ if (this.debug) {
4557
+ for (let r = 0; r < this.rows; r++) if (this.bridge.isDirtyRow(r)) dirtyCount++;
4558
+ }
4559
+ const rowHeight = this._rowHeight || 17;
4560
+ const scrollbackCount = this.bridge.getScrollbackCount();
4561
+ const discardedCount = this.bridge.getScrollbackDiscardedCount?.();
4562
+ const discardedDelta = discardedCount !== void 0 && discardedCount >= this._scrollbackDiscardedCount ? discardedCount - this._scrollbackDiscardedCount : 0;
4563
+ if (discardedCount !== void 0) this._scrollbackDiscardedCount = discardedCount;
4564
+ let scrollTop = this._pendingResizeScrollTop !== null ? this._pendingResizeScrollTop : this.element.scrollTop;
4565
+ if (!this._shouldScrollToBottom && discardedDelta > 0) {
4566
+ scrollTop = Math.max(0, scrollTop - discardedDelta * rowHeight);
4567
+ if (this._pendingResizeScrollTop !== null) this._pendingResizeScrollTop = scrollTop;
4568
+ else this._setScrollTop(scrollTop);
4569
+ }
4570
+ this.renderer.render(this.bridge, {
4571
+ scrollTop: this._shouldScrollToBottom ? Math.max(0, (scrollbackCount + this.rows) * rowHeight - this.element.clientHeight) : scrollTop,
4572
+ clientHeight: this.element.clientHeight,
4573
+ rowHeight,
4574
+ scrollbackDiscardedCount: discardedCount,
4575
+ charWidth: this._charWidth
4576
+ });
4577
+ if (this.debug) this.debug.recordRender(performance.now() - t0, dirtyCount);
4578
+ const hasScrollback = scrollbackCount > 0 || this.renderer.hasImageFlow;
4579
+ this.element.classList.toggle("has-scrollback", hasScrollback);
4580
+ if (this._shouldScrollToBottom) this._scrollToBottom();
4581
+ else if (this._pendingResizeScrollTop !== null) {
4582
+ const pendingScrollTop = this._pendingResizeScrollTop;
4583
+ this._pendingResizeScrollTop = null;
4584
+ this._setScrollTop(pendingScrollTop);
4585
+ } else if (!hasScrollback && this.element.scrollTop !== 0) this._setScrollTop(0);
4586
+ this.input?.syncInputPosition();
4587
+ if (this._searchReveal) {
4588
+ this._searchReveal = false;
4589
+ const match = this._search.matches[this.getSearchState().activeIndex];
4590
+ const target = match && Array.from(this.renderer.searchRows()).find(({ row }) => row === match.start.row);
4591
+ if (target) {
4592
+ const rect = target.element.getBoundingClientRect();
4593
+ const viewport = this.element.getBoundingClientRect();
4594
+ this._setScrollTop(this.element.scrollTop + rect.top - viewport.top - (this.element.clientHeight - rect.height) / 2);
4595
+ }
4596
+ }
4597
+ this._paintSearch();
4598
+ this._search.resume(this.bridge);
4599
+ this._historySelection.resume(this.bridge);
4600
+ this._historySelection.paintRectangle(this.renderer.searchRows(), this._charWidth);
4601
+ this._textCapture.resume(this.bridge);
4602
+ this._outputAnnouncements.rendered();
4603
+ this._deliverTitle();
4604
+ this._drainResponses();
4605
+ }
4606
+ _deliverTitle() {
4607
+ const title = this.bridge?.getTitle() ?? null;
4608
+ if (title !== null) this.onTitle?.(title);
4609
+ }
4610
+ _drainResponses() {
4611
+ if (!this.bridge) return { hasError: false };
4612
+ let response;
4613
+ let firstError;
4614
+ let hasError = false;
4615
+ while ((response = this.bridge.getResponse()) !== null) try {
4616
+ if (this.onData) this.onData(response);
4617
+ } catch (error) {
4618
+ if (!hasError) {
4619
+ hasError = true;
4620
+ firstError = error;
4621
+ }
4622
+ }
4623
+ return {
4624
+ hasError,
4625
+ error: firstError
4626
+ };
4627
+ }
4628
+ /**
4629
+ * Kitty uses xterm window reports to discover the pixel geometry needed for
4630
+ * image placement. The core intentionally does not know about the browser
4631
+ * viewport, so these two queries are answered at the DOM boundary.
4632
+ */
4633
+ _collectWindowSizeQueries(data) {
4634
+ const queries = [];
4635
+ let state = this._windowSizeQueryState;
4636
+ let index = 0;
4637
+ while (index < data.length) {
4638
+ if (state === 0) {
4639
+ index = typeof data === "string" ? data.indexOf("\x1B", index) : data.indexOf(27, index);
4640
+ if (index < 0) break;
4641
+ state = 1;
4642
+ index++;
4643
+ continue;
4644
+ }
4645
+ const code = typeof data === "string" ? data.charCodeAt(index) : data[index];
4646
+ index++;
4647
+ const restart = code === 27 ? 1 : 0;
4648
+ switch (state) {
4649
+ case 1:
4650
+ state = code === 91 ? 2 : restart;
4651
+ break;
4652
+ case 2:
4653
+ state = code === 49 ? 3 : restart;
4654
+ break;
4655
+ case 3:
4656
+ state = code === 52 ? 4 : code === 54 ? 6 : restart;
4657
+ break;
4658
+ case 4:
4659
+ case 6:
4660
+ if (code === 116) queries.push(state === 4 ? 14 : 16);
4661
+ state = restart;
4662
+ }
4663
+ }
4664
+ this._windowSizeQueryState = state;
4665
+ return queries;
4666
+ }
4667
+ _windowSizeResponse(query) {
4668
+ const { width, height } = this._pixelSize();
4669
+ if (query === 14) return `\x1b[4;${height};${width}t`;
4670
+ const cellWidth = Math.max(1, Math.round(this._charWidth));
4671
+ return `\x1b[6;${Math.max(1, Math.round(this._rowHeight))};${cellWidth}t`;
4672
+ }
4673
+ _pixelSize() {
4674
+ const style = getComputedStyle(this.element);
4675
+ const horizontalPadding = (parseFloat(style.paddingLeft) || 0) + (parseFloat(style.paddingRight) || 0);
4676
+ const verticalPadding = (parseFloat(style.paddingTop) || 0) + (parseFloat(style.paddingBottom) || 0);
4677
+ let width = this.element.clientWidth - horizontalPadding;
4678
+ let height = this.element.clientHeight - verticalPadding;
4679
+ if (width <= 0 || height <= 0) {
4680
+ const rect = this.element.getBoundingClientRect();
4681
+ width = rect.width - horizontalPadding;
4682
+ height = rect.height - verticalPadding;
4683
+ }
4684
+ if (width <= 0 && this._charWidth > 0) width = this.cols * this._charWidth;
4685
+ if (height <= 0 && this._rowHeight > 0) height = this.rows * this._rowHeight;
4686
+ return {
4687
+ width: Math.max(1, Math.round(width)),
4688
+ height: Math.max(1, Math.round(height))
4689
+ };
4690
+ }
4691
+ _lockHeight() {
4692
+ const rh = this._rowHeight || 17;
4693
+ const gridHeight = this.rows * rh;
4694
+ const cs = getComputedStyle(this.element);
4695
+ let extra = (parseFloat(cs.paddingTop) || 0) + (parseFloat(cs.paddingBottom) || 0);
4696
+ if (cs.boxSizing === "border-box") extra += (parseFloat(cs.borderTopWidth) || 0) + (parseFloat(cs.borderBottomWidth) || 0);
4697
+ this.element.style.height = `${gridHeight + extra}px`;
4698
+ }
4699
+ _setRowHeight() {
4700
+ const probe = document.createElement("div");
4701
+ probe.className = "term-row";
4702
+ probe.style.visibility = "hidden";
4703
+ probe.style.position = "absolute";
4704
+ probe.textContent = "W";
4705
+ this._container.appendChild(probe);
4706
+ const h = probe.getBoundingClientRect().height;
4707
+ probe.remove();
4708
+ if (h > 0) {
4709
+ this._rowHeight = h;
4710
+ this.element.style.setProperty("--term-row-height", `${h}px`);
4711
+ }
4712
+ }
4713
+ _measureCharSize() {
4714
+ const row = document.createElement("div");
4715
+ row.className = "term-row";
4716
+ row.style.visibility = "hidden";
4717
+ row.style.position = "absolute";
4718
+ const probe = document.createElement("span");
4719
+ probe.style.width = "auto";
4720
+ probe.textContent = "W";
4721
+ row.appendChild(probe);
4722
+ this._container.appendChild(row);
4723
+ const charWidth = probe.getBoundingClientRect().width;
4724
+ const rowHeight = row.getBoundingClientRect().height;
4725
+ row.remove();
4726
+ if (charWidth === 0 || rowHeight === 0) return null;
4727
+ this._charWidth = charWidth;
4728
+ this._rowHeight = rowHeight;
4729
+ this.element.style.setProperty("--term-cell-width", `${charWidth}px`);
4730
+ return {
4731
+ charWidth,
4732
+ rowHeight
4733
+ };
4734
+ }
4735
+ _setupResizeObserver() {
4736
+ const probe = document.createElement("span");
4737
+ probe.className = "term-size-probe";
4738
+ probe.setAttribute("aria-hidden", "true");
4739
+ probe.textContent = "W";
4740
+ this.element.appendChild(probe);
4741
+ let containerRect;
4742
+ this.resizeObserver = new ResizeObserver((entries) => {
4743
+ if (this._destroyed) return;
4744
+ for (const entry of entries) if (entry.target === this.element) containerRect = entry.contentRect;
4745
+ const measured = this._measureCharSize();
4746
+ if (!measured || !this.autoResize || !containerRect) return;
4747
+ const { charWidth, rowHeight } = measured;
4748
+ const newCols = Math.max(1, Math.floor(containerRect.width / charWidth));
4749
+ const newRows = Math.max(1, Math.floor(containerRect.height / rowHeight));
4750
+ if (newCols !== this.cols || newRows !== this.rows) this.resize(newCols, newRows);
4751
+ });
4752
+ this.resizeObserver.observe(probe);
4753
+ if (this.autoResize) this.resizeObserver.observe(this.element);
4754
+ }
4755
+ destroy() {
4756
+ this._destroyed = true;
4757
+ this._textCapture.cancel();
4758
+ this._historySelection.destroy();
4759
+ this._rectangleDrag.destroy();
4760
+ this._outputAnnouncements.destroy();
4761
+ this._search.cancel();
4762
+ this.onSearchChange = null;
4763
+ this._windowSizeQueryState = 0;
4764
+ this._cancelScheduledRender();
4765
+ this._cancelSynchronizedOutputFallback();
4766
+ if (this.resizeObserver) this.resizeObserver.disconnect();
4767
+ if (this.input) this.input.destroy();
4768
+ this.renderer?.destroy();
4769
+ this.renderer = null;
4770
+ this.element.removeEventListener("click", this._onClickFocus);
4771
+ this.element.removeEventListener("click", this._onMouseSelect);
4772
+ this.element.removeEventListener("scroll", this._onScroll);
4773
+ this.element.ownerDocument.removeEventListener("copy", this._onCopy);
4774
+ this.element.ownerDocument.removeEventListener("visibilitychange", this._onVisibilityChange);
4775
+ this.element.ownerDocument.removeEventListener("keydown", this._onModifierChange);
4776
+ this.element.ownerDocument.removeEventListener("keyup", this._onModifierChange);
4777
+ this.element.ownerDocument.defaultView?.removeEventListener("blur", this._onWindowBlur);
4778
+ this.element.classList.remove("link-modifier-active");
4779
+ this.element.innerHTML = "";
4780
+ if (this.debug && globalThis.__wterm === this) delete globalThis.__wterm;
4781
+ this.debug = null;
4782
+ }
4783
+ };
4784
+ //#endregion
4785
+ export { WTerm };