@simon_he/vue-tui 1.1.6 → 1.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/TAgentTerminalGraphic-B8-YZfuP.js +1198 -0
- package/dist/{TSelect-CMBOOFwK.js → TSelect-CCsjjCOr.js} +41 -12
- package/dist/{TTree-kk8ntrpg.js → TTree-3W5A2_EH.js} +4 -3
- package/dist/TVideo-D9AOiyq2.js +948 -0
- package/dist/agent.cjs +4926 -4364
- package/dist/agent.js +11 -9
- package/dist/{block-source-DByORvKG.js → block-source-BhvdZomx.js} +3 -3
- package/dist/cli.cjs +1 -1
- package/dist/cli.js +8 -1
- package/dist/core.js +2 -2
- package/dist/experimental/browser.cjs +3705 -0
- package/dist/experimental/browser.d.cts +3 -0
- package/dist/experimental/browser.d.ts +3 -0
- package/dist/experimental/browser.js +413 -0
- package/dist/experimental.cjs +1 -1
- package/dist/experimental.js +9 -947
- package/dist/{linkify-CL9wwnZN.js → frame-mailbox-DaTrfyaF.js} +2 -297
- package/dist/index.cjs +25 -8
- package/dist/index.js +6 -5
- package/dist/linkify-CklfA1vp.js +298 -0
- package/dist/markdown.cjs +4907 -4362
- package/dist/markdown.js +4 -4
- package/dist/{mermaid-CWy4wtCL.js → mermaid-D0ov4_A1.js} +3 -3
- package/dist/mermaid.cjs +1 -1
- package/dist/mermaid.js +4 -4
- package/dist/{path-suggest-Dndu4dTi.js → path-suggest-fPzRsgPv.js} +1 -1
- package/dist/renderer/terminal-graphics.d.ts +1 -1
- package/dist/{terminal-graphics-D6KErRBY.js → terminal-graphics-DpSL29OQ.js} +1 -1
- package/dist/{tlog-theme-DIrlCw6m.js → tlog-theme-BnILsD3n.js} +10 -1203
- package/dist/vue/browser/types.d.ts +52 -0
- package/dist/vue/components/TBrowser.d.ts +231 -0
- package/dist/vue/components/input/plugins/promptMentionPlugin.d.ts +3 -0
- package/dist/vue.cjs +25 -8
- package/dist/vue.js +8 -7
- package/package.json +16 -2
- /package/dist/{TMermaidText-wLnMMvVS.js → TMermaidText-C1akgJPU.js} +0 -0
- /package/dist/{math-image-BZhmfUeu.js → math-image-CcUpBnW0.js} +0 -0
- /package/dist/{path-mnSgEpCm.js → path-BI9W15Zt.js} +0 -0
- /package/dist/{wheel-scroll-DASkEZr-.js → wheel-scroll-CQ22Hcyj.js} +0 -0
|
@@ -0,0 +1,3705 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: !0 });
|
|
9
|
+
}, __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from == "object" || typeof from == "function")
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
!__hasOwnProp.call(to, key) && key !== except && __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
13
|
+
return to;
|
|
14
|
+
};
|
|
15
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: !0 }), mod);
|
|
16
|
+
|
|
17
|
+
// src/experimental/browser.ts
|
|
18
|
+
var browser_exports = {};
|
|
19
|
+
__export(browser_exports, {
|
|
20
|
+
TBrowser: () => TBrowser
|
|
21
|
+
});
|
|
22
|
+
module.exports = __toCommonJS(browser_exports);
|
|
23
|
+
|
|
24
|
+
// src/vue/components/TBrowser.ts
|
|
25
|
+
var import_vue12 = require("vue");
|
|
26
|
+
|
|
27
|
+
// src/vue/composables/use-layout.ts
|
|
28
|
+
var import_vue2 = require("vue");
|
|
29
|
+
|
|
30
|
+
// src/vue/context.ts
|
|
31
|
+
var import_vue = require("vue");
|
|
32
|
+
|
|
33
|
+
// src/renderer/terminal-graphics-trace.ts
|
|
34
|
+
var metrics = {
|
|
35
|
+
requests: 0,
|
|
36
|
+
skippedHidden: 0,
|
|
37
|
+
skippedScrolling: 0,
|
|
38
|
+
cacheHits: 0,
|
|
39
|
+
cacheMisses: 0,
|
|
40
|
+
cacheStores: 0,
|
|
41
|
+
rendererRuns: 0,
|
|
42
|
+
rendererAborts: 0,
|
|
43
|
+
rendererErrors: 0,
|
|
44
|
+
queued: 0,
|
|
45
|
+
queueWaits: 0,
|
|
46
|
+
queueDeduped: 0,
|
|
47
|
+
cleared: 0,
|
|
48
|
+
bytesQueued: 0,
|
|
49
|
+
totalRendererMs: 0,
|
|
50
|
+
totalValidateMs: 0,
|
|
51
|
+
totalQueueWaitMs: 0,
|
|
52
|
+
maxQueueWaitMs: 0,
|
|
53
|
+
maxActiveRenders: 0,
|
|
54
|
+
maxWaitingRenders: 0,
|
|
55
|
+
maxCacheEntries: 0,
|
|
56
|
+
maxCacheBytes: 0,
|
|
57
|
+
scrollStarts: 0,
|
|
58
|
+
scrollMarks: 0,
|
|
59
|
+
scrollIdles: 0,
|
|
60
|
+
totalScrollMs: 0,
|
|
61
|
+
maxScrollMs: 0
|
|
62
|
+
}, subscribers = /* @__PURE__ */ new Set();
|
|
63
|
+
function nowTerminalGraphicTraceTime() {
|
|
64
|
+
return typeof performance < "u" && typeof performance.now == "function" ? performance.now() : Date.now();
|
|
65
|
+
}
|
|
66
|
+
function recordTerminalGraphicTrace(event) {
|
|
67
|
+
let normalized = {
|
|
68
|
+
...event,
|
|
69
|
+
timestamp: event.timestamp ?? nowTerminalGraphicTraceTime()
|
|
70
|
+
};
|
|
71
|
+
switch (normalized.type) {
|
|
72
|
+
case "request":
|
|
73
|
+
metrics.requests++;
|
|
74
|
+
break;
|
|
75
|
+
case "skip-hidden":
|
|
76
|
+
metrics.skippedHidden++;
|
|
77
|
+
break;
|
|
78
|
+
case "skip-scrolling":
|
|
79
|
+
metrics.skippedScrolling++;
|
|
80
|
+
break;
|
|
81
|
+
case "cache-hit":
|
|
82
|
+
metrics.cacheHits++;
|
|
83
|
+
break;
|
|
84
|
+
case "cache-miss":
|
|
85
|
+
metrics.cacheMisses++;
|
|
86
|
+
break;
|
|
87
|
+
case "cache-store":
|
|
88
|
+
metrics.cacheStores++;
|
|
89
|
+
break;
|
|
90
|
+
case "renderer-start":
|
|
91
|
+
metrics.rendererRuns++;
|
|
92
|
+
break;
|
|
93
|
+
case "renderer-end":
|
|
94
|
+
metrics.totalRendererMs += normalized.durationMs ?? 0;
|
|
95
|
+
break;
|
|
96
|
+
case "renderer-abort":
|
|
97
|
+
metrics.rendererAborts++;
|
|
98
|
+
break;
|
|
99
|
+
case "renderer-error":
|
|
100
|
+
metrics.rendererErrors++;
|
|
101
|
+
break;
|
|
102
|
+
case "validate-end":
|
|
103
|
+
metrics.totalValidateMs += normalized.durationMs ?? 0;
|
|
104
|
+
break;
|
|
105
|
+
case "queue":
|
|
106
|
+
metrics.queued++, metrics.bytesQueued += normalized.bytes ?? 0;
|
|
107
|
+
break;
|
|
108
|
+
case "queue-wait": {
|
|
109
|
+
let durationMs = normalized.durationMs ?? 0;
|
|
110
|
+
metrics.queueWaits++, metrics.totalQueueWaitMs += durationMs, metrics.maxQueueWaitMs = Math.max(metrics.maxQueueWaitMs, durationMs);
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
case "queue-dedupe":
|
|
114
|
+
metrics.queueDeduped++;
|
|
115
|
+
break;
|
|
116
|
+
case "clear":
|
|
117
|
+
metrics.cleared++;
|
|
118
|
+
break;
|
|
119
|
+
case "scroll-start":
|
|
120
|
+
metrics.scrollStarts++;
|
|
121
|
+
break;
|
|
122
|
+
case "scroll-mark":
|
|
123
|
+
metrics.scrollMarks++;
|
|
124
|
+
break;
|
|
125
|
+
case "scroll-idle": {
|
|
126
|
+
let durationMs = normalized.durationMs ?? 0;
|
|
127
|
+
metrics.scrollIdles++, metrics.totalScrollMs += durationMs, metrics.maxScrollMs = Math.max(metrics.maxScrollMs, durationMs);
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
normalized.active != null && Number.isFinite(normalized.active) && (metrics.maxActiveRenders = Math.max(metrics.maxActiveRenders, Math.max(0, normalized.active))), normalized.waiting != null && Number.isFinite(normalized.waiting) && (metrics.maxWaitingRenders = Math.max(
|
|
132
|
+
metrics.maxWaitingRenders,
|
|
133
|
+
Math.max(0, normalized.waiting)
|
|
134
|
+
)), normalized.cacheEntries != null && Number.isFinite(normalized.cacheEntries) && (metrics.maxCacheEntries = Math.max(
|
|
135
|
+
metrics.maxCacheEntries,
|
|
136
|
+
Math.max(0, normalized.cacheEntries)
|
|
137
|
+
)), normalized.cacheBytes != null && Number.isFinite(normalized.cacheBytes) && (metrics.maxCacheBytes = Math.max(metrics.maxCacheBytes, Math.max(0, normalized.cacheBytes)));
|
|
138
|
+
for (let subscriber of subscribers)
|
|
139
|
+
try {
|
|
140
|
+
subscriber(normalized);
|
|
141
|
+
} catch {
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// src/vue/injection-key.ts
|
|
146
|
+
var VUE_TUI_INJECTION_PROTOCOL = "v1";
|
|
147
|
+
function injectionKey(name) {
|
|
148
|
+
return Symbol.for(`@simon_he/vue-tui:${VUE_TUI_INJECTION_PROTOCOL}:${name}`);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// src/vue/context.ts
|
|
152
|
+
var TerminalContextKey = injectionKey("TerminalContext"), LayoutContextKey = injectionKey("LayoutContext"), VisibilityContextKey = injectionKey("VisibilityContext"), EventZIndexContextKey = injectionKey("EventZIndex"), RenderPlaneContextKey = injectionKey("RenderPlane"), ImeAnchorContextKey = injectionKey("ImeAnchor"), TInputPluginsContextKey = injectionKey("TInputPlugins"), TPathPickerProviderContextKey = injectionKey("TPathPickerProvider"), TerminalGraphicsActivityKey = injectionKey(
|
|
153
|
+
"TerminalGraphicsActivity"
|
|
154
|
+
), DialogContextKey = injectionKey("DialogContext");
|
|
155
|
+
|
|
156
|
+
// src/vue/composables/use-layout.ts
|
|
157
|
+
function useLayout() {
|
|
158
|
+
let ctx = (0, import_vue2.inject)(LayoutContextKey, null);
|
|
159
|
+
if (!ctx)
|
|
160
|
+
throw new Error("LayoutContext is missing (TerminalProvider/TView)");
|
|
161
|
+
return ctx;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// src/vue/composables/use-terminal-node.ts
|
|
165
|
+
var import_vue4 = require("vue");
|
|
166
|
+
|
|
167
|
+
// src/vue/composables/use-terminal.ts
|
|
168
|
+
var import_vue3 = require("vue");
|
|
169
|
+
function useTerminal() {
|
|
170
|
+
let ctx = (0, import_vue3.inject)(TerminalContextKey, null);
|
|
171
|
+
if (!ctx)
|
|
172
|
+
throw new Error("TerminalProvider is missing");
|
|
173
|
+
return ctx;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// src/core/buffer/eaw-ranges-unicode-17.ts
|
|
177
|
+
var fullWidthRanges = [
|
|
178
|
+
[4352, 4447],
|
|
179
|
+
[8986, 8987],
|
|
180
|
+
[9001, 9002],
|
|
181
|
+
[9193, 9196],
|
|
182
|
+
[9200, 9200],
|
|
183
|
+
[9203, 9203],
|
|
184
|
+
[9725, 9726],
|
|
185
|
+
[9748, 9749],
|
|
186
|
+
[9776, 9783],
|
|
187
|
+
[9800, 9811],
|
|
188
|
+
[9855, 9855],
|
|
189
|
+
[9866, 9871],
|
|
190
|
+
[9875, 9875],
|
|
191
|
+
[9889, 9889],
|
|
192
|
+
[9898, 9899],
|
|
193
|
+
[9917, 9918],
|
|
194
|
+
[9924, 9925],
|
|
195
|
+
[9934, 9934],
|
|
196
|
+
[9940, 9940],
|
|
197
|
+
[9962, 9962],
|
|
198
|
+
[9970, 9971],
|
|
199
|
+
[9973, 9973],
|
|
200
|
+
[9978, 9978],
|
|
201
|
+
[9981, 9981],
|
|
202
|
+
[9989, 9989],
|
|
203
|
+
[9994, 9995],
|
|
204
|
+
[10024, 10024],
|
|
205
|
+
[10060, 10060],
|
|
206
|
+
[10062, 10062],
|
|
207
|
+
[10067, 10069],
|
|
208
|
+
[10071, 10071],
|
|
209
|
+
[10133, 10135],
|
|
210
|
+
[10160, 10160],
|
|
211
|
+
[10175, 10175],
|
|
212
|
+
[11035, 11036],
|
|
213
|
+
[11088, 11088],
|
|
214
|
+
[11093, 11093],
|
|
215
|
+
[11904, 11929],
|
|
216
|
+
[11931, 12019],
|
|
217
|
+
[12032, 12245],
|
|
218
|
+
[12272, 12350],
|
|
219
|
+
[12353, 12438],
|
|
220
|
+
[12441, 12543],
|
|
221
|
+
[12549, 12591],
|
|
222
|
+
[12593, 12686],
|
|
223
|
+
[12688, 12773],
|
|
224
|
+
[12783, 12830],
|
|
225
|
+
[12832, 12871],
|
|
226
|
+
[12880, 42124],
|
|
227
|
+
[42128, 42182],
|
|
228
|
+
[43360, 43388],
|
|
229
|
+
[44032, 55203],
|
|
230
|
+
[63744, 64255],
|
|
231
|
+
[65040, 65049],
|
|
232
|
+
[65072, 65106],
|
|
233
|
+
[65108, 65126],
|
|
234
|
+
[65128, 65131],
|
|
235
|
+
[65281, 65376],
|
|
236
|
+
[65504, 65510],
|
|
237
|
+
[94176, 94180],
|
|
238
|
+
[94192, 94198],
|
|
239
|
+
[94208, 101589],
|
|
240
|
+
[101631, 101662],
|
|
241
|
+
[101760, 101874],
|
|
242
|
+
[110576, 110579],
|
|
243
|
+
[110581, 110587],
|
|
244
|
+
[110589, 110590],
|
|
245
|
+
[110592, 110882],
|
|
246
|
+
[110898, 110898],
|
|
247
|
+
[110928, 110930],
|
|
248
|
+
[110933, 110933],
|
|
249
|
+
[110948, 110951],
|
|
250
|
+
[110960, 111355],
|
|
251
|
+
[119552, 119638],
|
|
252
|
+
[119648, 119670],
|
|
253
|
+
[126980, 126980],
|
|
254
|
+
[127183, 127183],
|
|
255
|
+
[127374, 127374],
|
|
256
|
+
[127377, 127386],
|
|
257
|
+
[127488, 127490],
|
|
258
|
+
[127504, 127547],
|
|
259
|
+
[127552, 127560],
|
|
260
|
+
[127568, 127569],
|
|
261
|
+
[127584, 127589],
|
|
262
|
+
[127744, 127776],
|
|
263
|
+
[127789, 127797],
|
|
264
|
+
[127799, 127868],
|
|
265
|
+
[127870, 127891],
|
|
266
|
+
[127904, 127946],
|
|
267
|
+
[127951, 127955],
|
|
268
|
+
[127968, 127984],
|
|
269
|
+
[127988, 127988],
|
|
270
|
+
[127992, 128062],
|
|
271
|
+
[128064, 128064],
|
|
272
|
+
[128066, 128252],
|
|
273
|
+
[128255, 128317],
|
|
274
|
+
[128331, 128334],
|
|
275
|
+
[128336, 128359],
|
|
276
|
+
[128378, 128378],
|
|
277
|
+
[128405, 128406],
|
|
278
|
+
[128420, 128420],
|
|
279
|
+
[128507, 128591],
|
|
280
|
+
[128640, 128709],
|
|
281
|
+
[128716, 128716],
|
|
282
|
+
[128720, 128722],
|
|
283
|
+
[128725, 128728],
|
|
284
|
+
[128732, 128735],
|
|
285
|
+
[128747, 128748],
|
|
286
|
+
[128756, 128764],
|
|
287
|
+
[128992, 129003],
|
|
288
|
+
[129008, 129008],
|
|
289
|
+
[129292, 129338],
|
|
290
|
+
[129340, 129349],
|
|
291
|
+
[129351, 129535],
|
|
292
|
+
[129648, 129660],
|
|
293
|
+
[129664, 129674],
|
|
294
|
+
[129678, 129734],
|
|
295
|
+
[129736, 129736],
|
|
296
|
+
[129741, 129756],
|
|
297
|
+
[129759, 129770],
|
|
298
|
+
[129775, 129784],
|
|
299
|
+
[131072, 196605],
|
|
300
|
+
[196608, 262141]
|
|
301
|
+
], ambiguousWidthRanges = [
|
|
302
|
+
[161, 161],
|
|
303
|
+
[164, 164],
|
|
304
|
+
[167, 168],
|
|
305
|
+
[170, 170],
|
|
306
|
+
[173, 174],
|
|
307
|
+
[176, 180],
|
|
308
|
+
[182, 186],
|
|
309
|
+
[188, 191],
|
|
310
|
+
[198, 198],
|
|
311
|
+
[208, 208],
|
|
312
|
+
[215, 216],
|
|
313
|
+
[222, 225],
|
|
314
|
+
[230, 230],
|
|
315
|
+
[232, 234],
|
|
316
|
+
[236, 237],
|
|
317
|
+
[240, 240],
|
|
318
|
+
[242, 243],
|
|
319
|
+
[247, 250],
|
|
320
|
+
[252, 252],
|
|
321
|
+
[254, 254],
|
|
322
|
+
[257, 257],
|
|
323
|
+
[273, 273],
|
|
324
|
+
[275, 275],
|
|
325
|
+
[283, 283],
|
|
326
|
+
[294, 295],
|
|
327
|
+
[299, 299],
|
|
328
|
+
[305, 307],
|
|
329
|
+
[312, 312],
|
|
330
|
+
[319, 322],
|
|
331
|
+
[324, 324],
|
|
332
|
+
[328, 331],
|
|
333
|
+
[333, 333],
|
|
334
|
+
[338, 339],
|
|
335
|
+
[358, 359],
|
|
336
|
+
[363, 363],
|
|
337
|
+
[462, 462],
|
|
338
|
+
[464, 464],
|
|
339
|
+
[466, 466],
|
|
340
|
+
[468, 468],
|
|
341
|
+
[470, 470],
|
|
342
|
+
[472, 472],
|
|
343
|
+
[474, 474],
|
|
344
|
+
[476, 476],
|
|
345
|
+
[593, 593],
|
|
346
|
+
[609, 609],
|
|
347
|
+
[708, 708],
|
|
348
|
+
[711, 711],
|
|
349
|
+
[713, 715],
|
|
350
|
+
[717, 717],
|
|
351
|
+
[720, 720],
|
|
352
|
+
[728, 731],
|
|
353
|
+
[733, 733],
|
|
354
|
+
[735, 735],
|
|
355
|
+
[768, 879],
|
|
356
|
+
[913, 929],
|
|
357
|
+
[931, 937],
|
|
358
|
+
[945, 961],
|
|
359
|
+
[963, 969],
|
|
360
|
+
[1025, 1025],
|
|
361
|
+
[1040, 1103],
|
|
362
|
+
[1105, 1105],
|
|
363
|
+
[8208, 8208],
|
|
364
|
+
[8211, 8214],
|
|
365
|
+
[8216, 8217],
|
|
366
|
+
[8220, 8221],
|
|
367
|
+
[8224, 8226],
|
|
368
|
+
[8228, 8231],
|
|
369
|
+
[8240, 8240],
|
|
370
|
+
[8242, 8243],
|
|
371
|
+
[8245, 8245],
|
|
372
|
+
[8251, 8251],
|
|
373
|
+
[8254, 8254],
|
|
374
|
+
[8308, 8308],
|
|
375
|
+
[8319, 8319],
|
|
376
|
+
[8321, 8324],
|
|
377
|
+
[8364, 8364],
|
|
378
|
+
[8451, 8451],
|
|
379
|
+
[8453, 8453],
|
|
380
|
+
[8457, 8457],
|
|
381
|
+
[8467, 8467],
|
|
382
|
+
[8470, 8470],
|
|
383
|
+
[8481, 8482],
|
|
384
|
+
[8486, 8486],
|
|
385
|
+
[8491, 8491],
|
|
386
|
+
[8531, 8532],
|
|
387
|
+
[8539, 8542],
|
|
388
|
+
[8544, 8555],
|
|
389
|
+
[8560, 8569],
|
|
390
|
+
[8585, 8585],
|
|
391
|
+
[8592, 8601],
|
|
392
|
+
[8632, 8633],
|
|
393
|
+
[8658, 8658],
|
|
394
|
+
[8660, 8660],
|
|
395
|
+
[8679, 8679],
|
|
396
|
+
[8704, 8704],
|
|
397
|
+
[8706, 8707],
|
|
398
|
+
[8711, 8712],
|
|
399
|
+
[8715, 8715],
|
|
400
|
+
[8719, 8719],
|
|
401
|
+
[8721, 8721],
|
|
402
|
+
[8725, 8725],
|
|
403
|
+
[8730, 8730],
|
|
404
|
+
[8733, 8736],
|
|
405
|
+
[8739, 8739],
|
|
406
|
+
[8741, 8741],
|
|
407
|
+
[8743, 8748],
|
|
408
|
+
[8750, 8750],
|
|
409
|
+
[8756, 8759],
|
|
410
|
+
[8764, 8765],
|
|
411
|
+
[8776, 8776],
|
|
412
|
+
[8780, 8780],
|
|
413
|
+
[8786, 8786],
|
|
414
|
+
[8800, 8801],
|
|
415
|
+
[8804, 8807],
|
|
416
|
+
[8810, 8811],
|
|
417
|
+
[8814, 8815],
|
|
418
|
+
[8834, 8835],
|
|
419
|
+
[8838, 8839],
|
|
420
|
+
[8853, 8853],
|
|
421
|
+
[8857, 8857],
|
|
422
|
+
[8869, 8869],
|
|
423
|
+
[8895, 8895],
|
|
424
|
+
[8978, 8978],
|
|
425
|
+
[9312, 9449],
|
|
426
|
+
[9451, 9547],
|
|
427
|
+
[9552, 9587],
|
|
428
|
+
[9600, 9615],
|
|
429
|
+
[9618, 9621],
|
|
430
|
+
[9632, 9633],
|
|
431
|
+
[9635, 9641],
|
|
432
|
+
[9650, 9651],
|
|
433
|
+
[9654, 9655],
|
|
434
|
+
[9660, 9661],
|
|
435
|
+
[9664, 9665],
|
|
436
|
+
[9670, 9672],
|
|
437
|
+
[9675, 9675],
|
|
438
|
+
[9678, 9681],
|
|
439
|
+
[9698, 9701],
|
|
440
|
+
[9711, 9711],
|
|
441
|
+
[9733, 9734],
|
|
442
|
+
[9737, 9737],
|
|
443
|
+
[9742, 9743],
|
|
444
|
+
[9756, 9756],
|
|
445
|
+
[9758, 9758],
|
|
446
|
+
[9792, 9792],
|
|
447
|
+
[9794, 9794],
|
|
448
|
+
[9824, 9825],
|
|
449
|
+
[9827, 9829],
|
|
450
|
+
[9831, 9834],
|
|
451
|
+
[9836, 9837],
|
|
452
|
+
[9839, 9839],
|
|
453
|
+
[9886, 9887],
|
|
454
|
+
[9919, 9919],
|
|
455
|
+
[9926, 9933],
|
|
456
|
+
[9935, 9939],
|
|
457
|
+
[9941, 9953],
|
|
458
|
+
[9955, 9955],
|
|
459
|
+
[9960, 9961],
|
|
460
|
+
[9963, 9969],
|
|
461
|
+
[9972, 9972],
|
|
462
|
+
[9974, 9977],
|
|
463
|
+
[9979, 9980],
|
|
464
|
+
[9982, 9983],
|
|
465
|
+
[10045, 10045],
|
|
466
|
+
[10102, 10111],
|
|
467
|
+
[11094, 11097],
|
|
468
|
+
[12872, 12879],
|
|
469
|
+
[57344, 63743],
|
|
470
|
+
[65024, 65039],
|
|
471
|
+
[65533, 65533],
|
|
472
|
+
[127232, 127242],
|
|
473
|
+
[127248, 127277],
|
|
474
|
+
[127280, 127337],
|
|
475
|
+
[127344, 127373],
|
|
476
|
+
[127375, 127376],
|
|
477
|
+
[127387, 127404],
|
|
478
|
+
[917760, 917999],
|
|
479
|
+
[983040, 1048573],
|
|
480
|
+
[1048576, 1114109]
|
|
481
|
+
];
|
|
482
|
+
|
|
483
|
+
// src/core/buffer/width.ts
|
|
484
|
+
function isFullWidthCodePoint(codePoint) {
|
|
485
|
+
if (codePoint < 4352)
|
|
486
|
+
return !1;
|
|
487
|
+
for (let [start, end] of fullWidthRanges) {
|
|
488
|
+
if (codePoint < start)
|
|
489
|
+
return !1;
|
|
490
|
+
if (codePoint <= end)
|
|
491
|
+
return !0;
|
|
492
|
+
}
|
|
493
|
+
return !1;
|
|
494
|
+
}
|
|
495
|
+
function isAmbiguousWidthCodePoint(codePoint) {
|
|
496
|
+
let first = ambiguousWidthRanges[0], last = ambiguousWidthRanges[ambiguousWidthRanges.length - 1];
|
|
497
|
+
if (!first || !last || codePoint < first[0] || codePoint > last[1])
|
|
498
|
+
return !1;
|
|
499
|
+
for (let [start, end] of ambiguousWidthRanges) {
|
|
500
|
+
if (codePoint < start)
|
|
501
|
+
return !1;
|
|
502
|
+
if (codePoint <= end)
|
|
503
|
+
return !0;
|
|
504
|
+
}
|
|
505
|
+
return !1;
|
|
506
|
+
}
|
|
507
|
+
function isVariationSelectorCodePoint(codePoint) {
|
|
508
|
+
return codePoint >= 65024 && codePoint <= 65039 || codePoint >= 917760 && codePoint <= 917999;
|
|
509
|
+
}
|
|
510
|
+
function isCombiningMarkCodePoint(codePoint) {
|
|
511
|
+
return codePoint >= 768 && codePoint <= 879 || // Combining Diacritical Marks
|
|
512
|
+
codePoint >= 6832 && codePoint <= 6911 || // Combining Diacritical Marks Extended
|
|
513
|
+
codePoint >= 7616 && codePoint <= 7679 || // Combining Diacritical Marks Supplement
|
|
514
|
+
codePoint >= 8400 && codePoint <= 8447 || // Combining Diacritical Marks for Symbols
|
|
515
|
+
codePoint >= 65056 && codePoint <= 65071 || // Combining Half Marks
|
|
516
|
+
codePoint >= 12330 && codePoint <= 12335 || // EAW=W: Ideographic level tone marks
|
|
517
|
+
codePoint >= 12441 && codePoint <= 12442 || // EAW=W: Combining Katakana-Hiragana marks
|
|
518
|
+
codePoint === 94180;
|
|
519
|
+
}
|
|
520
|
+
function isEmojiLike(codePoint) {
|
|
521
|
+
return codePoint >= 127744 && codePoint <= 129791 || codePoint >= 127462 && codePoint <= 127487;
|
|
522
|
+
}
|
|
523
|
+
var extendedPictographicRe = null;
|
|
524
|
+
try {
|
|
525
|
+
extendedPictographicRe = new RegExp("\\p{Extended_Pictographic}", "u");
|
|
526
|
+
} catch {
|
|
527
|
+
extendedPictographicRe = null;
|
|
528
|
+
}
|
|
529
|
+
var emojiPresentationRe = null;
|
|
530
|
+
try {
|
|
531
|
+
emojiPresentationRe = new RegExp("\\p{Emoji_Presentation}", "u");
|
|
532
|
+
} catch {
|
|
533
|
+
emojiPresentationRe = null;
|
|
534
|
+
}
|
|
535
|
+
var emojiRe = null;
|
|
536
|
+
try {
|
|
537
|
+
emojiRe = new RegExp("\\p{Emoji}", "u");
|
|
538
|
+
} catch {
|
|
539
|
+
emojiRe = null;
|
|
540
|
+
}
|
|
541
|
+
function normalizeCustomWidth(width) {
|
|
542
|
+
return width === 2 ? 2 : 1;
|
|
543
|
+
}
|
|
544
|
+
function charCellWidth(text, provider = "default") {
|
|
545
|
+
if (!text)
|
|
546
|
+
return 1;
|
|
547
|
+
if (typeof provider == "function")
|
|
548
|
+
return normalizeCustomWidth(provider(text));
|
|
549
|
+
if (provider !== "cjk" && text.length === 1 && text.charCodeAt(0) < 4352)
|
|
550
|
+
return 1;
|
|
551
|
+
let codePoint = text.codePointAt(0);
|
|
552
|
+
if (codePoint == null)
|
|
553
|
+
return 1;
|
|
554
|
+
let hasVs16 = text.includes("\uFE0F");
|
|
555
|
+
return isVariationSelectorCodePoint(codePoint) || isCombiningMarkCodePoint(codePoint) || codePoint >= 9472 && codePoint <= 9599 ? 1 : isFullWidthCodePoint(codePoint) || provider === "cjk" && isAmbiguousWidthCodePoint(codePoint) || isEmojiLike(codePoint) || emojiPresentationRe?.test(text) || text.includes("\u20E3") || hasVs16 && emojiRe?.test(text) ? 2 : extendedPictographicRe?.test(text) ? codePoint <= 65535 ? hasVs16 ? 2 : 1 : 2 : 1;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
// src/utils/grapheme.ts
|
|
559
|
+
var graphemeSegmenter = null;
|
|
560
|
+
try {
|
|
561
|
+
let Segmenter = typeof Intl < "u" ? Intl.Segmenter : void 0;
|
|
562
|
+
graphemeSegmenter = Segmenter ? new Segmenter(void 0, { granularity: "grapheme" }) : null;
|
|
563
|
+
} catch {
|
|
564
|
+
graphemeSegmenter = null;
|
|
565
|
+
}
|
|
566
|
+
var unicodeMarkRe = null;
|
|
567
|
+
try {
|
|
568
|
+
unicodeMarkRe = new RegExp("\\p{Mark}", "u");
|
|
569
|
+
} catch {
|
|
570
|
+
unicodeMarkRe = null;
|
|
571
|
+
}
|
|
572
|
+
function needsGraphemeSegmentation(text) {
|
|
573
|
+
for (let ch of text) {
|
|
574
|
+
let cp = ch.codePointAt(0);
|
|
575
|
+
if (cp === 8205 || cp >= 65024 && cp <= 65039 || cp >= 917760 && cp <= 917999 || isCombiningMark(cp) || cp >= 127995 && cp <= 127999 || cp >= 127462 && cp <= 127487 || cp >= 917504 && cp <= 917631)
|
|
576
|
+
return !0;
|
|
577
|
+
}
|
|
578
|
+
return !1;
|
|
579
|
+
}
|
|
580
|
+
function isVariationSelector(codePoint) {
|
|
581
|
+
return codePoint >= 65024 && codePoint <= 65039 || codePoint >= 917760 && codePoint <= 917999;
|
|
582
|
+
}
|
|
583
|
+
function isCombiningMark(codePoint) {
|
|
584
|
+
return codePoint >= 768 && codePoint <= 879 || codePoint >= 6832 && codePoint <= 6911 || codePoint >= 7616 && codePoint <= 7679 || codePoint >= 8400 && codePoint <= 8447 || codePoint >= 65056 && codePoint <= 65071 || isDevanagariMark(codePoint) || unicodeMarkRe?.test(String.fromCodePoint(codePoint)) === !0;
|
|
585
|
+
}
|
|
586
|
+
function isDevanagariMark(codePoint) {
|
|
587
|
+
return codePoint >= 2304 && codePoint <= 2307 || codePoint >= 2362 && codePoint <= 2364 || codePoint >= 2366 && codePoint <= 2383 || codePoint >= 2385 && codePoint <= 2391 || codePoint >= 2402 && codePoint <= 2403;
|
|
588
|
+
}
|
|
589
|
+
function isVirama(codePoint) {
|
|
590
|
+
return codePoint === 2381;
|
|
591
|
+
}
|
|
592
|
+
function isEmojiModifier(codePoint) {
|
|
593
|
+
return codePoint >= 127995 && codePoint <= 127999;
|
|
594
|
+
}
|
|
595
|
+
function isRegionalIndicator(codePoint) {
|
|
596
|
+
return codePoint >= 127462 && codePoint <= 127487;
|
|
597
|
+
}
|
|
598
|
+
function isEmojiTag(codePoint) {
|
|
599
|
+
return codePoint >= 917504 && codePoint <= 917631;
|
|
600
|
+
}
|
|
601
|
+
function fallbackGraphemeSegments(text) {
|
|
602
|
+
let out = [], segment = "", segmentStart = 0, pos = 0, regionalIndicators = 0, joinNext = !1, pushSegment = () => {
|
|
603
|
+
segment && out.push({ segment, index: segmentStart });
|
|
604
|
+
};
|
|
605
|
+
for (let ch of text) {
|
|
606
|
+
let codePoint = ch.codePointAt(0), chStart = pos;
|
|
607
|
+
pos += ch.length, segment !== "" && (joinNext || codePoint === 8205 || isVariationSelector(codePoint) || isCombiningMark(codePoint) || isEmojiModifier(codePoint) || isEmojiTag(codePoint) || isRegionalIndicator(codePoint) && regionalIndicators === 1) ? (segment += ch, isRegionalIndicator(codePoint) ? regionalIndicators++ : !isVariationSelector(codePoint) && !isCombiningMark(codePoint) && (regionalIndicators = 0)) : (pushSegment(), segment = ch, segmentStart = chStart, regionalIndicators = isRegionalIndicator(codePoint) ? 1 : 0), codePoint === 8205 || isVirama(codePoint) ? joinNext = !0 : joinNext && !isVariationSelector(codePoint) && !isCombiningMark(codePoint) && (joinNext = !1);
|
|
608
|
+
}
|
|
609
|
+
return pushSegment(), out;
|
|
610
|
+
}
|
|
611
|
+
function segmentedGraphemes(text) {
|
|
612
|
+
return needsGraphemeSegmentation(text) ? graphemeSegmenter ? graphemeSegmenter.segment(text) : fallbackGraphemeSegments(text) : null;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
// src/vue/utils/text.ts
|
|
616
|
+
var renderPassDepth = 0, renderPassTextWidthCache = /* @__PURE__ */ new Map(), textWidthProviderStack = [];
|
|
617
|
+
function currentTextWidthProvider() {
|
|
618
|
+
return textWidthProviderStack[textWidthProviderStack.length - 1] ?? "default";
|
|
619
|
+
}
|
|
620
|
+
function hasAsciiFastPath(provider) {
|
|
621
|
+
return typeof provider != "function";
|
|
622
|
+
}
|
|
623
|
+
function canUseDefaultTextCache(provider) {
|
|
624
|
+
return provider === "default" || provider === "narrow-ambiguous";
|
|
625
|
+
}
|
|
626
|
+
function withTextWidthProvider(provider, fn) {
|
|
627
|
+
textWidthProviderStack.push(provider ?? "default");
|
|
628
|
+
try {
|
|
629
|
+
return fn();
|
|
630
|
+
} finally {
|
|
631
|
+
textWidthProviderStack.pop();
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
function isAscii(text) {
|
|
635
|
+
for (let i = 0; i < text.length; i++)
|
|
636
|
+
if (text.charCodeAt(i) > 127)
|
|
637
|
+
return !1;
|
|
638
|
+
return !0;
|
|
639
|
+
}
|
|
640
|
+
var UNSAFE_FORMAT_CONTROL_RE = /[\u061C\u00AD\u180E\u200B\u200C\u200E\u200F\u202A-\u202E\u2060-\u206F\uFEFF]/u;
|
|
641
|
+
function isUnsafeFormatControl(codePoint) {
|
|
642
|
+
return codePoint === 1564 || codePoint === 173 || codePoint === 6158 || codePoint === 8203 || codePoint === 8204 || codePoint === 8206 || codePoint === 8207 || codePoint >= 8234 && codePoint <= 8238 || codePoint >= 8288 && codePoint <= 8303 || codePoint === 65279;
|
|
643
|
+
}
|
|
644
|
+
function hasInlineAsciiControl(text) {
|
|
645
|
+
for (let i = 0; i < text.length; i++) {
|
|
646
|
+
let code = text.charCodeAt(i);
|
|
647
|
+
if (code === 10 || code === 13 || code === 9)
|
|
648
|
+
return !0;
|
|
649
|
+
}
|
|
650
|
+
return !1;
|
|
651
|
+
}
|
|
652
|
+
function hasTextBlockAsciiControl(text) {
|
|
653
|
+
for (let i = 0; i < text.length; i++) {
|
|
654
|
+
let code = text.charCodeAt(i);
|
|
655
|
+
if (code === 9 || code <= 31 && code !== 10 || code === 127)
|
|
656
|
+
return !0;
|
|
657
|
+
}
|
|
658
|
+
return !1;
|
|
659
|
+
}
|
|
660
|
+
function forEachGrapheme(text, cb) {
|
|
661
|
+
if (!text)
|
|
662
|
+
return;
|
|
663
|
+
let segments = segmentedGraphemes(text);
|
|
664
|
+
if (!segments) {
|
|
665
|
+
for (let ch of text)
|
|
666
|
+
if (cb(ch) === !1)
|
|
667
|
+
return;
|
|
668
|
+
return;
|
|
669
|
+
}
|
|
670
|
+
for (let part of segments)
|
|
671
|
+
if (cb(part.segment) === !1)
|
|
672
|
+
return;
|
|
673
|
+
}
|
|
674
|
+
function sanitizeInlineText(text) {
|
|
675
|
+
if (!text)
|
|
676
|
+
return "";
|
|
677
|
+
if (!UNSAFE_FORMAT_CONTROL_RE.test(text) && !hasInlineAsciiControl(text))
|
|
678
|
+
return text;
|
|
679
|
+
let out = [];
|
|
680
|
+
for (let ch of text) {
|
|
681
|
+
let cp = ch.codePointAt(0);
|
|
682
|
+
if (cp === 10 || cp === 13 || cp === 9) {
|
|
683
|
+
out.push(" ");
|
|
684
|
+
continue;
|
|
685
|
+
}
|
|
686
|
+
isUnsafeFormatControl(cp) || out.push(ch);
|
|
687
|
+
}
|
|
688
|
+
return out.join("");
|
|
689
|
+
}
|
|
690
|
+
function sanitizeTextBlock(text) {
|
|
691
|
+
if (!text)
|
|
692
|
+
return "";
|
|
693
|
+
if (!UNSAFE_FORMAT_CONTROL_RE.test(text) && !hasTextBlockAsciiControl(text))
|
|
694
|
+
return text;
|
|
695
|
+
let out = [];
|
|
696
|
+
out.length = 0;
|
|
697
|
+
for (let ch of text) {
|
|
698
|
+
let cp = ch.codePointAt(0);
|
|
699
|
+
if (cp !== 13) {
|
|
700
|
+
if (cp === 9) {
|
|
701
|
+
out.push(" ");
|
|
702
|
+
continue;
|
|
703
|
+
}
|
|
704
|
+
cp <= 31 && cp !== 10 || cp === 127 || isUnsafeFormatControl(cp) || out.push(ch);
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
return out.join("");
|
|
708
|
+
}
|
|
709
|
+
function textCellWidth(text, provider = currentTextWidthProvider()) {
|
|
710
|
+
if (!text)
|
|
711
|
+
return 0;
|
|
712
|
+
if (hasAsciiFastPath(provider) && isAscii(text))
|
|
713
|
+
return text.length;
|
|
714
|
+
let useCache = canUseDefaultTextCache(provider);
|
|
715
|
+
if (useCache && renderPassDepth > 0) {
|
|
716
|
+
let cached = renderPassTextWidthCache.get(text);
|
|
717
|
+
if (cached != null)
|
|
718
|
+
return cached;
|
|
719
|
+
}
|
|
720
|
+
if (useCache) {
|
|
721
|
+
let cached = textWidthCacheGet(text);
|
|
722
|
+
if (cached != null)
|
|
723
|
+
return cached;
|
|
724
|
+
}
|
|
725
|
+
let cells = 0;
|
|
726
|
+
return forEachGrapheme(text, (g) => {
|
|
727
|
+
cells += charCellWidth(g, provider);
|
|
728
|
+
}), useCache && renderPassDepth > 0 && renderPassTextWidthCache.set(text, cells), useCache && textWidthCacheSet(text, cells), cells;
|
|
729
|
+
}
|
|
730
|
+
var spaceCache = /* @__PURE__ */ new Map(), MAX_CACHED_SPACES = 256;
|
|
731
|
+
function spaces(count) {
|
|
732
|
+
if (count = Math.max(0, Math.floor(count)), count === 0)
|
|
733
|
+
return "";
|
|
734
|
+
let cached = spaceCache.get(count);
|
|
735
|
+
if (cached)
|
|
736
|
+
return cached;
|
|
737
|
+
let v = " ".repeat(count);
|
|
738
|
+
return spaceCache.size >= MAX_CACHED_SPACES && spaceCache.clear(), spaceCache.set(count, v), v;
|
|
739
|
+
}
|
|
740
|
+
function sliceByCells(text, maxCells, provider = currentTextWidthProvider()) {
|
|
741
|
+
if (maxCells = Math.max(0, Math.floor(maxCells)), maxCells <= 0)
|
|
742
|
+
return "";
|
|
743
|
+
if (text && hasAsciiFastPath(provider) && isAscii(text))
|
|
744
|
+
return text.slice(0, maxCells);
|
|
745
|
+
let out = [], cells = 0;
|
|
746
|
+
return forEachGrapheme(text, (g) => {
|
|
747
|
+
let w = charCellWidth(g, provider);
|
|
748
|
+
if (cells + w > maxCells)
|
|
749
|
+
return !1;
|
|
750
|
+
out.push(g), cells += w;
|
|
751
|
+
}), out.length ? out.join("") : "";
|
|
752
|
+
}
|
|
753
|
+
function sliceByCellsRange(text, startCells, endCells, provider = currentTextWidthProvider()) {
|
|
754
|
+
if (startCells = Math.max(0, Math.floor(startCells)), endCells = Math.max(0, Math.floor(endCells)), endCells <= startCells || !text)
|
|
755
|
+
return "";
|
|
756
|
+
if (hasAsciiFastPath(provider) && isAscii(text))
|
|
757
|
+
return text.slice(startCells, endCells);
|
|
758
|
+
let out = [], cells = 0;
|
|
759
|
+
return forEachGrapheme(text, (g) => {
|
|
760
|
+
let w = charCellWidth(g, provider), next = cells + w;
|
|
761
|
+
if (cells >= endCells)
|
|
762
|
+
return !1;
|
|
763
|
+
if (next <= startCells) {
|
|
764
|
+
cells = next;
|
|
765
|
+
return;
|
|
766
|
+
}
|
|
767
|
+
if (cells < startCells && next > startCells) {
|
|
768
|
+
out.push(spaces(Math.min(next, endCells) - startCells)), cells = next;
|
|
769
|
+
return;
|
|
770
|
+
}
|
|
771
|
+
if (next > endCells)
|
|
772
|
+
return out.push(spaces(endCells - cells)), !1;
|
|
773
|
+
out.push(g), cells = next;
|
|
774
|
+
}), out.length ? out.join("") : "";
|
|
775
|
+
}
|
|
776
|
+
function padEndByCells(text, width, provider = currentTextWidthProvider()) {
|
|
777
|
+
width = Math.max(0, Math.floor(width));
|
|
778
|
+
let cells = text && hasAsciiFastPath(provider) && isAscii(text) ? text.length : textCellWidth(text, provider);
|
|
779
|
+
return cells >= width ? text : `${text}${spaces(width - cells)}`;
|
|
780
|
+
}
|
|
781
|
+
var wrapCacheByWidth = /* @__PURE__ */ new Map(), MAX_WRAP_CACHE_BUCKETS = 32, MAX_WRAP_CACHE_PER_WIDTH = 256;
|
|
782
|
+
function getWrapBucket(width) {
|
|
783
|
+
let bucket = wrapCacheByWidth.get(width);
|
|
784
|
+
return bucket || (wrapCacheByWidth.size >= MAX_WRAP_CACHE_BUCKETS && wrapCacheByWidth.clear(), bucket = /* @__PURE__ */ new Map(), wrapCacheByWidth.set(width, bucket), bucket);
|
|
785
|
+
}
|
|
786
|
+
var textWidthCache = /* @__PURE__ */ new Map(), MAX_TEXT_WIDTH_CACHE = 1024;
|
|
787
|
+
function textWidthCacheGet(text) {
|
|
788
|
+
let cached = textWidthCache.get(text);
|
|
789
|
+
return cached == null ? null : (textWidthCache.delete(text), textWidthCache.set(text, cached), cached);
|
|
790
|
+
}
|
|
791
|
+
function textWidthCacheSet(text, cells) {
|
|
792
|
+
if (textWidthCache.set(text, cells), textWidthCache.size > MAX_TEXT_WIDTH_CACHE) {
|
|
793
|
+
let firstKey = textWidthCache.keys().next().value;
|
|
794
|
+
firstKey != null && textWidthCache.delete(firstKey);
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
function wrapByCells(text, width, provider = currentTextWidthProvider()) {
|
|
798
|
+
width = Math.max(1, Math.floor(width));
|
|
799
|
+
let bucket = canUseDefaultTextCache(provider) ? getWrapBucket(width) : null;
|
|
800
|
+
if (text && hasAsciiFastPath(provider) && isAscii(text)) {
|
|
801
|
+
if (bucket) {
|
|
802
|
+
let cached = bucket.get(text);
|
|
803
|
+
if (cached)
|
|
804
|
+
return cached;
|
|
805
|
+
}
|
|
806
|
+
let out2 = [];
|
|
807
|
+
for (let rawLine of text.replace(/\r/g, "").split(`
|
|
808
|
+
`)) {
|
|
809
|
+
if (rawLine.length === 0) {
|
|
810
|
+
out2.push("");
|
|
811
|
+
continue;
|
|
812
|
+
}
|
|
813
|
+
for (let i = 0; i < rawLine.length; i += width)
|
|
814
|
+
out2.push(rawLine.slice(i, i + width));
|
|
815
|
+
}
|
|
816
|
+
return bucket && (bucket.size >= MAX_WRAP_CACHE_PER_WIDTH && bucket.clear(), bucket.set(text, out2)), out2;
|
|
817
|
+
}
|
|
818
|
+
if (bucket) {
|
|
819
|
+
let cached = bucket.get(text);
|
|
820
|
+
if (cached)
|
|
821
|
+
return cached;
|
|
822
|
+
}
|
|
823
|
+
let out = [];
|
|
824
|
+
for (let rawLine of text.replace(/\r/g, "").split(`
|
|
825
|
+
`)) {
|
|
826
|
+
if (rawLine.length === 0) {
|
|
827
|
+
out.push("");
|
|
828
|
+
continue;
|
|
829
|
+
}
|
|
830
|
+
let segments = segmentedGraphemes(rawLine);
|
|
831
|
+
if (segments) {
|
|
832
|
+
let lineStart = 0, cells = 0;
|
|
833
|
+
for (let part of segments) {
|
|
834
|
+
let g = part.segment, gIdx = part.index, w = charCellWidth(g, provider);
|
|
835
|
+
if (cells > 0 && cells + w > width && (out.push(rawLine.slice(lineStart, gIdx)), lineStart = gIdx, cells = 0), cells += w, cells >= width) {
|
|
836
|
+
let end = gIdx + g.length;
|
|
837
|
+
out.push(rawLine.slice(lineStart, end)), lineStart = end, cells = 0;
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
lineStart < rawLine.length && out.push(rawLine.slice(lineStart));
|
|
841
|
+
} else {
|
|
842
|
+
let lineStart = 0, pos = 0, cells = 0;
|
|
843
|
+
for (let ch of rawLine) {
|
|
844
|
+
let w = charCellWidth(ch, provider);
|
|
845
|
+
cells > 0 && cells + w > width && (out.push(rawLine.slice(lineStart, pos)), lineStart = pos, cells = 0), pos += ch.length, cells += w, cells >= width && (out.push(rawLine.slice(lineStart, pos)), lineStart = pos, cells = 0);
|
|
846
|
+
}
|
|
847
|
+
lineStart < rawLine.length && out.push(rawLine.slice(lineStart));
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
let res = out.length ? out : [""];
|
|
851
|
+
return bucket && (bucket.size >= MAX_WRAP_CACHE_PER_WIDTH && bucket.clear(), bucket.set(text, res)), res;
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
// src/vue/composables/use-terminal-node.ts
|
|
855
|
+
function wrapHandlers(handlers, widthProvider) {
|
|
856
|
+
if (!handlers)
|
|
857
|
+
return {};
|
|
858
|
+
let out = {};
|
|
859
|
+
for (let key of Object.keys(handlers)) {
|
|
860
|
+
let handler = handlers[key];
|
|
861
|
+
handler && (out[key] = (event) => withTextWidthProvider(widthProvider, () => handler(event)));
|
|
862
|
+
}
|
|
863
|
+
return out;
|
|
864
|
+
}
|
|
865
|
+
function useTerminalNode(getOptions) {
|
|
866
|
+
let { events, widthProvider } = useTerminal(), id = (0, import_vue4.ref)(null), options = (0, import_vue4.computed)(() => withTextWidthProvider(widthProvider, getOptions)), stop = (0, import_vue4.watchEffect)(() => {
|
|
867
|
+
let manager = events.value;
|
|
868
|
+
if (!manager)
|
|
869
|
+
return;
|
|
870
|
+
let opt = options.value;
|
|
871
|
+
if (!id.value) {
|
|
872
|
+
let node = manager.register({
|
|
873
|
+
rect: opt.rect,
|
|
874
|
+
zIndex: opt.zIndex ?? 0,
|
|
875
|
+
visible: opt.visible,
|
|
876
|
+
focusable: opt.focusable,
|
|
877
|
+
selectable: opt.selectable,
|
|
878
|
+
selectionScrollBy: opt.selectionScrollBy,
|
|
879
|
+
handlers: wrapHandlers(opt.handlers, widthProvider)
|
|
880
|
+
});
|
|
881
|
+
id.value = node.id;
|
|
882
|
+
return;
|
|
883
|
+
}
|
|
884
|
+
manager.update(id.value, {
|
|
885
|
+
rect: opt.rect,
|
|
886
|
+
zIndex: opt.zIndex ?? 0,
|
|
887
|
+
visible: opt.visible,
|
|
888
|
+
focusable: opt.focusable,
|
|
889
|
+
selectable: opt.selectable,
|
|
890
|
+
selectionScrollBy: opt.selectionScrollBy,
|
|
891
|
+
handlers: wrapHandlers(opt.handlers, widthProvider)
|
|
892
|
+
});
|
|
893
|
+
});
|
|
894
|
+
return (0, import_vue4.onBeforeUnmount)(() => {
|
|
895
|
+
stop();
|
|
896
|
+
let manager = events.value;
|
|
897
|
+
manager && id.value && manager.unregister(id.value);
|
|
898
|
+
}), { id };
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
// src/vue/composables/use-visibility.ts
|
|
902
|
+
var import_vue5 = require("vue");
|
|
903
|
+
var VUE_TERMINAL_SHOW_CB = "__vueTerminalOnShow", vShowPatched = !1;
|
|
904
|
+
function patchVShow() {
|
|
905
|
+
if (vShowPatched)
|
|
906
|
+
return;
|
|
907
|
+
vShowPatched = !0;
|
|
908
|
+
let dir = import_vue5.vShow, origBeforeMount = dir.beforeMount, origUpdated = dir.updated, origBeforeUnmount = dir.beforeUnmount, notify = (el, value) => {
|
|
909
|
+
if (!el || typeof el != "object")
|
|
910
|
+
return;
|
|
911
|
+
let cb = el[VUE_TERMINAL_SHOW_CB];
|
|
912
|
+
cb?.(!!value);
|
|
913
|
+
};
|
|
914
|
+
typeof origBeforeMount == "function" && (dir.beforeMount = (el, binding, vnode) => {
|
|
915
|
+
origBeforeMount(el, binding, vnode), notify(el, binding?.value);
|
|
916
|
+
}), typeof origUpdated == "function" && (dir.updated = (el, binding, vnode) => {
|
|
917
|
+
origUpdated(el, binding, vnode), notify(el, binding?.value);
|
|
918
|
+
}), typeof origBeforeUnmount == "function" && (dir.beforeUnmount = (el, binding, vnode) => {
|
|
919
|
+
origBeforeUnmount(el, binding, vnode), notify(el, binding?.value);
|
|
920
|
+
});
|
|
921
|
+
}
|
|
922
|
+
var PLACEHOLDER_STYLE = Object.freeze({
|
|
923
|
+
position: "absolute",
|
|
924
|
+
left: "-9999px",
|
|
925
|
+
top: "0",
|
|
926
|
+
width: "0",
|
|
927
|
+
height: "0",
|
|
928
|
+
overflow: "hidden"
|
|
929
|
+
});
|
|
930
|
+
function useVisibility(options) {
|
|
931
|
+
patchVShow();
|
|
932
|
+
let { scheduler } = useTerminal(), parentVisible = (0, import_vue5.inject)(VisibilityContextKey, (0, import_vue5.ref)(!0)), localVisible = (0, import_vue5.ref)(!0), visible = (0, import_vue5.computed)(() => parentVisible.value && localVisible.value);
|
|
933
|
+
options?.provide && (0, import_vue5.provide)(VisibilityContextKey, visible);
|
|
934
|
+
let onShow = (value) => {
|
|
935
|
+
localVisible.value = value, scheduler.invalidate();
|
|
936
|
+
};
|
|
937
|
+
return { visible, rootProps: {
|
|
938
|
+
style: PLACEHOLDER_STYLE,
|
|
939
|
+
onVnodeBeforeMount: (vnode) => {
|
|
940
|
+
let el = vnode.el;
|
|
941
|
+
el && typeof el == "object" && (el[VUE_TERMINAL_SHOW_CB] = onShow);
|
|
942
|
+
},
|
|
943
|
+
onVnodeBeforeUnmount: (vnode) => {
|
|
944
|
+
let el = vnode.el;
|
|
945
|
+
el && typeof el == "object" && el[VUE_TERMINAL_SHOW_CB] === onShow && delete el[VUE_TERMINAL_SHOW_CB];
|
|
946
|
+
}
|
|
947
|
+
} };
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
// src/vue/utils/rect.ts
|
|
951
|
+
function intersectRect(a, b) {
|
|
952
|
+
let x0 = Math.max(a.x, b.x), y0 = Math.max(a.y, b.y), x1 = Math.min(a.x + a.w, b.x + b.w), y1 = Math.min(a.y + a.h, b.y + b.h);
|
|
953
|
+
return x1 <= x0 || y1 <= y0 ? null : { x: x0, y: y0, w: x1 - x0, h: y1 - y0 };
|
|
954
|
+
}
|
|
955
|
+
function translateRect(rect, dx, dy) {
|
|
956
|
+
return { x: rect.x + dx, y: rect.y + dy, w: rect.w, h: rect.h };
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
// src/vue/components/TVideo.ts
|
|
960
|
+
var import_vue11 = require("vue");
|
|
961
|
+
|
|
962
|
+
// src/core/terminal/create-terminal.ts
|
|
963
|
+
var TERMINAL_PLANE_INTERNALS = Symbol.for("@simon_he/vue-tui:v1:terminal-plane-internals"), TERMINAL_ROOT = Symbol.for("@simon_he/vue-tui:v1:terminal-root");
|
|
964
|
+
function getRootTerminal(terminal) {
|
|
965
|
+
return terminal[TERMINAL_ROOT] ?? terminal;
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
// src/renderer/terminal-graphics.ts
|
|
969
|
+
var ESC = "\x1B", BEL = "\x07", ST = `${ESC}\\`, ESC_RE = "\\u001B", BEL_RE = "\\u0007", CSI_RE = new RegExp(`${ESC_RE}\\[[0-?]*[ -/]*[@-~]`, "g"), OSC_RE = new RegExp(`${ESC_RE}\\][\\s\\S]*?(?:${BEL_RE}|${ESC_RE}\\\\)`, "g"), DCS_RE = new RegExp(`${ESC_RE}P[\\s\\S]*?${ESC_RE}\\\\`, "g"), APC_RE = new RegExp(`${ESC_RE}_[\\s\\S]*?${ESC_RE}\\\\`, "g"), C1_CSI_RE = new RegExp("\\u009B[0-?]*[ -/]*[@-~]", "g"), C1_OSC_RE = new RegExp(`\\u009D[\\s\\S]*?(?:${BEL_RE}|\\u009C)`, "g"), C1_DCS_RE = new RegExp("\\u0090[\\s\\S]*?\\u009C", "g"), C1_APC_RE = new RegExp("\\u009F[\\s\\S]*?\\u009C", "g"), MAX_TERMINAL_GRAPHICS_SEQUENCE_CHARS = 16 * 1024 * 1024, MAX_TERMINAL_GRAPHICS_FALLBACK_CHARS = 16384, MAX_TERMINAL_GRAPHIC_CELLS = 1e5, TERMINAL_GRAPHICS_REGISTRY = Symbol.for("@simon_he/vue-tui:v1:terminal-graphics"), terminalGraphicsGlobal = globalThis, terminalGraphicsRegistry = terminalGraphicsGlobal[TERMINAL_GRAPHICS_REGISTRY] ?? {
|
|
970
|
+
outputs: /* @__PURE__ */ new WeakMap(),
|
|
971
|
+
outputVersions: /* @__PURE__ */ new WeakMap(),
|
|
972
|
+
outputListeners: /* @__PURE__ */ new WeakMap()
|
|
973
|
+
};
|
|
974
|
+
terminalGraphicsGlobal[TERMINAL_GRAPHICS_REGISTRY] = terminalGraphicsRegistry;
|
|
975
|
+
var terminalGraphicsOutputs = terminalGraphicsRegistry.outputs, terminalGraphicsOutputVersions = terminalGraphicsRegistry.outputVersions, terminalGraphicsOutputListeners = terminalGraphicsRegistry.outputListeners;
|
|
976
|
+
function getTerminalGraphicsOutput(terminal) {
|
|
977
|
+
return terminalGraphicsOutputs.get(getRootTerminal(terminal)) ?? null;
|
|
978
|
+
}
|
|
979
|
+
function getTerminalGraphicsOutputVersion(terminal) {
|
|
980
|
+
return terminalGraphicsOutputVersions.get(getRootTerminal(terminal)) ?? 0;
|
|
981
|
+
}
|
|
982
|
+
function subscribeTerminalGraphicsOutput(terminal, listener) {
|
|
983
|
+
let rootTerminal = getRootTerminal(terminal), listeners = terminalGraphicsOutputListeners.get(rootTerminal);
|
|
984
|
+
return listeners || (listeners = /* @__PURE__ */ new Set(), terminalGraphicsOutputListeners.set(rootTerminal, listeners)), listeners.add(listener), () => {
|
|
985
|
+
listeners.delete(listener), listeners.size === 0 && terminalGraphicsOutputListeners.delete(rootTerminal);
|
|
986
|
+
};
|
|
987
|
+
}
|
|
988
|
+
function isTerminalGraphicsProtocol(value) {
|
|
989
|
+
return value === "kitty" || value === "iterm2" || value === "sixel";
|
|
990
|
+
}
|
|
991
|
+
function stableTerminalGraphicNumericId(input, options = {}) {
|
|
992
|
+
let min = Math.floor(options.min ?? 1), max = Math.floor(options.max ?? 2147483647), span = Math.max(1, max - min + 1), hash = 2166136261;
|
|
993
|
+
for (let index = 0; index < input.length; index += 1)
|
|
994
|
+
hash ^= input.charCodeAt(index), hash = Math.imul(hash, 16777619);
|
|
995
|
+
return min + (hash >>> 0) % span;
|
|
996
|
+
}
|
|
997
|
+
function positiveGraphicInt(value, max) {
|
|
998
|
+
let n = Math.trunc(Number(value));
|
|
999
|
+
return !Number.isFinite(n) || n <= 0 ? null : Math.min(max, n);
|
|
1000
|
+
}
|
|
1001
|
+
function normalizeTerminalGraphicSize(width, height) {
|
|
1002
|
+
let w = positiveGraphicInt(width, MAX_TERMINAL_GRAPHIC_CELLS), h6 = positiveGraphicInt(height, MAX_TERMINAL_GRAPHIC_CELLS);
|
|
1003
|
+
return w == null || h6 == null || w * h6 > MAX_TERMINAL_GRAPHIC_CELLS ? null : { width: w, height: h6 };
|
|
1004
|
+
}
|
|
1005
|
+
function canDrawTerminalGraphicRect(rect, size) {
|
|
1006
|
+
let x = Math.floor(rect.x), y = Math.floor(rect.y), graphicSize = normalizeTerminalGraphicSize(rect.w, rect.h), cols = Math.max(0, Math.floor(size.cols)), rows = Math.max(0, Math.floor(size.rows));
|
|
1007
|
+
return graphicSize != null && cols > 0 && rows > 0 && Number.isFinite(x) && Number.isFinite(y) && x >= 0 && y >= 0 && x < cols && y < rows;
|
|
1008
|
+
}
|
|
1009
|
+
function withoutNestedEscapes(body) {
|
|
1010
|
+
return !body.includes(ESC) && !body.includes(BEL);
|
|
1011
|
+
}
|
|
1012
|
+
function isBase64ish(value) {
|
|
1013
|
+
return /^[A-Za-z0-9+/=]*$/.test(value);
|
|
1014
|
+
}
|
|
1015
|
+
function parseKittyControls(raw) {
|
|
1016
|
+
let out = /* @__PURE__ */ new Map();
|
|
1017
|
+
if (!/^[A-Za-z0-9_,=+.\-:]*$/.test(raw))
|
|
1018
|
+
return null;
|
|
1019
|
+
for (let part of raw.split(",")) {
|
|
1020
|
+
if (!part)
|
|
1021
|
+
continue;
|
|
1022
|
+
let eq = part.indexOf("=");
|
|
1023
|
+
if (eq <= 0)
|
|
1024
|
+
return null;
|
|
1025
|
+
let key = part.slice(0, eq), value = part.slice(eq + 1);
|
|
1026
|
+
if (!/^[A-Za-z]$/.test(key) || !/^[A-Za-z0-9+.\-:]*$/.test(value))
|
|
1027
|
+
return null;
|
|
1028
|
+
out.set(key, value);
|
|
1029
|
+
}
|
|
1030
|
+
return out;
|
|
1031
|
+
}
|
|
1032
|
+
function parseKittyPackets(sequence) {
|
|
1033
|
+
let packets = [], index = 0;
|
|
1034
|
+
for (; index < sequence.length; ) {
|
|
1035
|
+
if (!sequence.startsWith(`${ESC}_G`, index))
|
|
1036
|
+
return null;
|
|
1037
|
+
let end = sequence.indexOf(ST, index + 3);
|
|
1038
|
+
if (end < 0)
|
|
1039
|
+
return null;
|
|
1040
|
+
let body = sequence.slice(index + 3, end);
|
|
1041
|
+
if (!withoutNestedEscapes(body))
|
|
1042
|
+
return null;
|
|
1043
|
+
let semicolon = body.indexOf(";"), rawControls = semicolon >= 0 ? body.slice(0, semicolon) : body, payload = semicolon >= 0 ? body.slice(semicolon + 1) : "", controls = parseKittyControls(rawControls);
|
|
1044
|
+
if (!controls || payload && !isBase64ish(payload))
|
|
1045
|
+
return null;
|
|
1046
|
+
packets.push({ controls, payload }), index = end + ST.length;
|
|
1047
|
+
}
|
|
1048
|
+
return packets.length ? packets : null;
|
|
1049
|
+
}
|
|
1050
|
+
var KITTY_DRAW_FIRST_CONTROL_KEYS = /* @__PURE__ */ new Set([
|
|
1051
|
+
"a",
|
|
1052
|
+
"f",
|
|
1053
|
+
"q",
|
|
1054
|
+
"C",
|
|
1055
|
+
"i",
|
|
1056
|
+
"I",
|
|
1057
|
+
"p",
|
|
1058
|
+
"c",
|
|
1059
|
+
"r",
|
|
1060
|
+
"x",
|
|
1061
|
+
"y",
|
|
1062
|
+
"w",
|
|
1063
|
+
"h",
|
|
1064
|
+
"z",
|
|
1065
|
+
"m",
|
|
1066
|
+
"t"
|
|
1067
|
+
]), KITTY_DRAW_CONTINUATION_CONTROL_KEYS = /* @__PURE__ */ new Set(["a", "q", "m"]), KITTY_CLEAR_CONTROL_KEYS = /* @__PURE__ */ new Set(["a", "d", "i", "I", "p", "q"]);
|
|
1068
|
+
function kittyControlsUseOnly(controls, allowed) {
|
|
1069
|
+
for (let key of controls.keys())
|
|
1070
|
+
if (!allowed.has(key))
|
|
1071
|
+
return !1;
|
|
1072
|
+
return !0;
|
|
1073
|
+
}
|
|
1074
|
+
var KITTY_UINT32_MAX = 4294967295, KITTY_INT32_MIN = -2147483648, KITTY_INT32_MAX = 2147483647;
|
|
1075
|
+
function kittyControlIsUint32(controls, key, min = 0) {
|
|
1076
|
+
let value = controls.get(key);
|
|
1077
|
+
if (value == null)
|
|
1078
|
+
return !0;
|
|
1079
|
+
if (!/^\d+$/.test(value))
|
|
1080
|
+
return !1;
|
|
1081
|
+
let n = Number(value);
|
|
1082
|
+
return Number.isSafeInteger(n) && n >= min && n <= KITTY_UINT32_MAX;
|
|
1083
|
+
}
|
|
1084
|
+
function kittyControlIsInt32(controls, key) {
|
|
1085
|
+
let value = controls.get(key);
|
|
1086
|
+
if (value == null)
|
|
1087
|
+
return !0;
|
|
1088
|
+
if (!/^-?\d+$/.test(value))
|
|
1089
|
+
return !1;
|
|
1090
|
+
let n = Number(value);
|
|
1091
|
+
return Number.isSafeInteger(n) && n >= KITTY_INT32_MIN && n <= KITTY_INT32_MAX;
|
|
1092
|
+
}
|
|
1093
|
+
function kittyControlPositiveInt(controls, key, fallback) {
|
|
1094
|
+
let value = controls.get(key);
|
|
1095
|
+
if (value == null)
|
|
1096
|
+
return fallback;
|
|
1097
|
+
if (!/^\d+$/.test(value))
|
|
1098
|
+
return null;
|
|
1099
|
+
let n = Number(value);
|
|
1100
|
+
return Number.isSafeInteger(n) && n >= 1 ? n : null;
|
|
1101
|
+
}
|
|
1102
|
+
function kittyControlIsTerminalGraphicCellsBounded(controls) {
|
|
1103
|
+
let columns = kittyControlPositiveInt(controls, "c", 1), rows = kittyControlPositiveInt(controls, "r", 1);
|
|
1104
|
+
return columns != null && rows != null && columns * rows <= MAX_TERMINAL_GRAPHIC_CELLS;
|
|
1105
|
+
}
|
|
1106
|
+
function validateKittySharedSafeControls(controls) {
|
|
1107
|
+
let q = controls.get("q");
|
|
1108
|
+
if (q != null && !/^[0-2]$/.test(q))
|
|
1109
|
+
return !1;
|
|
1110
|
+
let cursorMove = controls.get("C");
|
|
1111
|
+
if (cursorMove != null && !/^[01]$/.test(cursorMove))
|
|
1112
|
+
return !1;
|
|
1113
|
+
for (let key of ["i", "I", "p"])
|
|
1114
|
+
if (!kittyControlIsUint32(controls, key))
|
|
1115
|
+
return !1;
|
|
1116
|
+
for (let key of ["c", "r"])
|
|
1117
|
+
if (!kittyControlIsUint32(controls, key, 1))
|
|
1118
|
+
return !1;
|
|
1119
|
+
if (!kittyControlIsTerminalGraphicCellsBounded(controls))
|
|
1120
|
+
return !1;
|
|
1121
|
+
for (let key of ["x", "y"])
|
|
1122
|
+
if (!kittyControlIsUint32(controls, key))
|
|
1123
|
+
return !1;
|
|
1124
|
+
for (let key of ["w", "h"])
|
|
1125
|
+
if (!kittyControlIsUint32(controls, key, 1))
|
|
1126
|
+
return !1;
|
|
1127
|
+
if (!kittyControlIsInt32(controls, "z"))
|
|
1128
|
+
return !1;
|
|
1129
|
+
let transmissionMedium = controls.get("t");
|
|
1130
|
+
return !(transmissionMedium != null && transmissionMedium !== "d");
|
|
1131
|
+
}
|
|
1132
|
+
function validateKittySequence(sequence, op = "draw") {
|
|
1133
|
+
let packets = parseKittyPackets(sequence);
|
|
1134
|
+
if (!packets)
|
|
1135
|
+
return !1;
|
|
1136
|
+
if (op === "clear") {
|
|
1137
|
+
if (packets.length !== 1)
|
|
1138
|
+
return !1;
|
|
1139
|
+
let packet = packets[0];
|
|
1140
|
+
if (!kittyControlsUseOnly(packet.controls, KITTY_CLEAR_CONTROL_KEYS) || !validateKittySharedSafeControls(packet.controls) || packet.payload || packet.controls.get("a") !== "d")
|
|
1141
|
+
return !1;
|
|
1142
|
+
let d = packet.controls.get("d");
|
|
1143
|
+
return d == null || /^[aAcCiI]$/.test(d);
|
|
1144
|
+
}
|
|
1145
|
+
let first = packets[0];
|
|
1146
|
+
if (!kittyControlsUseOnly(first.controls, KITTY_DRAW_FIRST_CONTROL_KEYS) || !validateKittySharedSafeControls(first.controls))
|
|
1147
|
+
return !1;
|
|
1148
|
+
if (first.controls.get("a") === "p")
|
|
1149
|
+
return !(packets.length !== 1 || first.payload || !first.controls.has("i") && !first.controls.has("I"));
|
|
1150
|
+
if (first.controls.get("a") !== "T" || !first.payload)
|
|
1151
|
+
return !1;
|
|
1152
|
+
let f = first.controls.get("f");
|
|
1153
|
+
if (f != null && f !== "24" && f !== "32" && f !== "100")
|
|
1154
|
+
return !1;
|
|
1155
|
+
let firstMore = first.controls.get("m");
|
|
1156
|
+
if (firstMore != null && firstMore !== "0" && firstMore !== "1" || packets.length > 1 && firstMore !== "1")
|
|
1157
|
+
return !1;
|
|
1158
|
+
for (let i = 1; i < packets.length; i++) {
|
|
1159
|
+
let packet = packets[i];
|
|
1160
|
+
if (!kittyControlsUseOnly(packet.controls, KITTY_DRAW_CONTINUATION_CONTROL_KEYS) || !validateKittySharedSafeControls(packet.controls))
|
|
1161
|
+
return !1;
|
|
1162
|
+
let action = packet.controls.get("a");
|
|
1163
|
+
if (action != null && action !== "T")
|
|
1164
|
+
return !1;
|
|
1165
|
+
let m = packet.controls.get("m");
|
|
1166
|
+
if (m !== "0" && m !== "1" || !packet.payload && !(i === packets.length - 1 && m === "0"))
|
|
1167
|
+
return !1;
|
|
1168
|
+
}
|
|
1169
|
+
return !(packets.length > 1 && packets[packets.length - 1].controls.get("m") === "1");
|
|
1170
|
+
}
|
|
1171
|
+
function validateIterm2Dimension(value) {
|
|
1172
|
+
return /^auto$/i.test(value) || /^(?:[1-9]\d{0,4})(?:px|%)?$/.test(value);
|
|
1173
|
+
}
|
|
1174
|
+
function validateIterm2Params(params) {
|
|
1175
|
+
let seen = /* @__PURE__ */ new Set(), inline = !1;
|
|
1176
|
+
for (let part of params.split(";").filter(Boolean)) {
|
|
1177
|
+
let eq = part.indexOf("=");
|
|
1178
|
+
if (eq <= 0)
|
|
1179
|
+
return !1;
|
|
1180
|
+
let key = part.slice(0, eq), value = part.slice(eq + 1);
|
|
1181
|
+
if (seen.has(key))
|
|
1182
|
+
return !1;
|
|
1183
|
+
switch (seen.add(key), key) {
|
|
1184
|
+
case "inline":
|
|
1185
|
+
if (value !== "1")
|
|
1186
|
+
return !1;
|
|
1187
|
+
inline = !0;
|
|
1188
|
+
break;
|
|
1189
|
+
case "width":
|
|
1190
|
+
case "height":
|
|
1191
|
+
if (!validateIterm2Dimension(value))
|
|
1192
|
+
return !1;
|
|
1193
|
+
break;
|
|
1194
|
+
case "preserveAspectRatio":
|
|
1195
|
+
case "doNotMoveCursor":
|
|
1196
|
+
if (!/^[01]$/.test(value))
|
|
1197
|
+
return !1;
|
|
1198
|
+
break;
|
|
1199
|
+
default:
|
|
1200
|
+
return !1;
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
return inline;
|
|
1204
|
+
}
|
|
1205
|
+
function validateIterm2Sequence(sequence, op = "draw") {
|
|
1206
|
+
if (op === "clear")
|
|
1207
|
+
return !1;
|
|
1208
|
+
let index = 0;
|
|
1209
|
+
for (; index < sequence.length; ) {
|
|
1210
|
+
let prefix = `${ESC}]1337;File=`;
|
|
1211
|
+
if (!sequence.startsWith(prefix, index))
|
|
1212
|
+
return !1;
|
|
1213
|
+
let belEnd = sequence.indexOf(BEL, index + prefix.length), stEnd = sequence.indexOf(ST, index + prefix.length), end = belEnd >= 0 && stEnd >= 0 ? Math.min(belEnd, stEnd) : belEnd >= 0 ? belEnd : stEnd;
|
|
1214
|
+
if (end < 0)
|
|
1215
|
+
return !1;
|
|
1216
|
+
let body = sequence.slice(index + `${ESC}]1337;`.length, end);
|
|
1217
|
+
if (!body.startsWith("File=") || !withoutNestedEscapes(body))
|
|
1218
|
+
return !1;
|
|
1219
|
+
let colon = body.indexOf(":");
|
|
1220
|
+
if (colon < 0)
|
|
1221
|
+
return !1;
|
|
1222
|
+
let params = body.slice(5, colon), payload = body.slice(colon + 1);
|
|
1223
|
+
if (!/^[A-Za-z0-9_=;,.%+\-:]*$/.test(params) || !payload || !isBase64ish(payload) || !validateIterm2Params(params))
|
|
1224
|
+
return !1;
|
|
1225
|
+
index = end + (end === stEnd ? ST.length : BEL.length);
|
|
1226
|
+
}
|
|
1227
|
+
return sequence.length > 0;
|
|
1228
|
+
}
|
|
1229
|
+
function validateSixelSequence(sequence, op = "draw") {
|
|
1230
|
+
if (op === "clear")
|
|
1231
|
+
return !1;
|
|
1232
|
+
let index = 0;
|
|
1233
|
+
for (; index < sequence.length; ) {
|
|
1234
|
+
if (!sequence.startsWith(`${ESC}P`, index))
|
|
1235
|
+
return !1;
|
|
1236
|
+
let end = sequence.indexOf(ST, index + 2);
|
|
1237
|
+
if (end < 0)
|
|
1238
|
+
return !1;
|
|
1239
|
+
let body = sequence.slice(index + 2, end);
|
|
1240
|
+
if (!withoutNestedEscapes(body))
|
|
1241
|
+
return !1;
|
|
1242
|
+
for (let i = 0; i < body.length; i++) {
|
|
1243
|
+
let code = body.charCodeAt(i);
|
|
1244
|
+
if (code < 32 || code > 126)
|
|
1245
|
+
return !1;
|
|
1246
|
+
}
|
|
1247
|
+
let q = body.indexOf("q");
|
|
1248
|
+
if (q < 0 || q > 32)
|
|
1249
|
+
return !1;
|
|
1250
|
+
let introducer = body.slice(0, q);
|
|
1251
|
+
if (!/^[0-9;?]*$/.test(introducer) || !body.slice(q + 1).length)
|
|
1252
|
+
return !1;
|
|
1253
|
+
index = end + ST.length;
|
|
1254
|
+
}
|
|
1255
|
+
return sequence.length > 0;
|
|
1256
|
+
}
|
|
1257
|
+
function stripTerminalControlChars(value) {
|
|
1258
|
+
let out = "";
|
|
1259
|
+
for (let index = 0; index < value.length; index++) {
|
|
1260
|
+
let code = value.charCodeAt(index);
|
|
1261
|
+
code <= 8 || code === 11 || code === 12 || code >= 14 && code <= 31 || code === 127 || code >= 128 && code <= 159 || (out += value[index]);
|
|
1262
|
+
}
|
|
1263
|
+
return out;
|
|
1264
|
+
}
|
|
1265
|
+
function sanitizeTerminalFallbackText(text) {
|
|
1266
|
+
return stripTerminalControlChars(
|
|
1267
|
+
String(text ?? "").replace(OSC_RE, "").replace(CSI_RE, "").replace(DCS_RE, "").replace(APC_RE, "").replace(C1_OSC_RE, "").replace(C1_CSI_RE, "").replace(C1_DCS_RE, "").replace(C1_APC_RE, "")
|
|
1268
|
+
).slice(0, MAX_TERMINAL_GRAPHICS_FALLBACK_CHARS);
|
|
1269
|
+
}
|
|
1270
|
+
function isSafeTerminalGraphicsSequence(sequence, protocol, op = "draw") {
|
|
1271
|
+
return !isTerminalGraphicsProtocol(protocol) || !sequence || sequence.length > MAX_TERMINAL_GRAPHICS_SEQUENCE_CHARS ? !1 : protocol === "kitty" ? validateKittySequence(sequence, op) : protocol === "iterm2" ? validateIterm2Sequence(sequence, op) : validateSixelSequence(sequence, op);
|
|
1272
|
+
}
|
|
1273
|
+
function uint32Control(key, value, min = 0) {
|
|
1274
|
+
if (value == null)
|
|
1275
|
+
return "";
|
|
1276
|
+
let n = Math.floor(value);
|
|
1277
|
+
return Number.isSafeInteger(n) && n >= min && n <= KITTY_UINT32_MAX ? `${key}=${n}` : "";
|
|
1278
|
+
}
|
|
1279
|
+
function int32Control(key, value) {
|
|
1280
|
+
if (value == null)
|
|
1281
|
+
return "";
|
|
1282
|
+
let n = Math.floor(value);
|
|
1283
|
+
return Number.isSafeInteger(n) && n >= KITTY_INT32_MIN && n <= KITTY_INT32_MAX ? `${key}=${n}` : "";
|
|
1284
|
+
}
|
|
1285
|
+
function sanitizeBase64(value) {
|
|
1286
|
+
let data = String(value ?? "").replace(/\s+/g, "");
|
|
1287
|
+
return isBase64ish(data) ? data : "";
|
|
1288
|
+
}
|
|
1289
|
+
function kittyGraphicCellControls(columns, rows) {
|
|
1290
|
+
if (columns == null && rows == null)
|
|
1291
|
+
return [];
|
|
1292
|
+
let size = normalizeTerminalGraphicSize(columns ?? 1, rows ?? 1);
|
|
1293
|
+
return size ? [columns == null ? "" : `c=${size.width}`, rows == null ? "" : `r=${size.height}`] : [];
|
|
1294
|
+
}
|
|
1295
|
+
function kittyGraphicSourceControls(sourceX, sourceY, sourceWidth, sourceHeight) {
|
|
1296
|
+
return [
|
|
1297
|
+
uint32Control("x", sourceX),
|
|
1298
|
+
uint32Control("y", sourceY),
|
|
1299
|
+
uint32Control("w", sourceWidth, 1),
|
|
1300
|
+
uint32Control("h", sourceHeight, 1)
|
|
1301
|
+
];
|
|
1302
|
+
}
|
|
1303
|
+
function chunkBase64(value, chunkSize) {
|
|
1304
|
+
let normalizedSize = Math.max(4, Math.floor(chunkSize / 4) * 4), chunks = [];
|
|
1305
|
+
for (let index = 0; index < value.length; index += normalizedSize)
|
|
1306
|
+
chunks.push(value.slice(index, index + normalizedSize));
|
|
1307
|
+
return chunks.length ? chunks : [""];
|
|
1308
|
+
}
|
|
1309
|
+
function createKittyPlacementSequence(options) {
|
|
1310
|
+
let imageId = uint32Control("i", options.imageId), imageNumber = uint32Control("I", options.imageNumber);
|
|
1311
|
+
if (!imageId && !imageNumber)
|
|
1312
|
+
return "";
|
|
1313
|
+
let controls = [
|
|
1314
|
+
"a=p",
|
|
1315
|
+
options.quiet === !1 ? "" : "q=2",
|
|
1316
|
+
options.noCursorMove === !1 ? "" : "C=1",
|
|
1317
|
+
imageId,
|
|
1318
|
+
imageNumber,
|
|
1319
|
+
uint32Control("p", options.placementId),
|
|
1320
|
+
...kittyGraphicCellControls(options.columns, options.rows),
|
|
1321
|
+
...kittyGraphicSourceControls(
|
|
1322
|
+
options.sourceX,
|
|
1323
|
+
options.sourceY,
|
|
1324
|
+
options.sourceWidth,
|
|
1325
|
+
options.sourceHeight
|
|
1326
|
+
),
|
|
1327
|
+
int32Control("z", options.zIndex)
|
|
1328
|
+
].filter(Boolean);
|
|
1329
|
+
return `${ESC}_G${controls.join(",")}${ST}`;
|
|
1330
|
+
}
|
|
1331
|
+
function createKittyGraphicsSequence(base64Png, options = {}) {
|
|
1332
|
+
let data = sanitizeBase64(base64Png);
|
|
1333
|
+
if (!data)
|
|
1334
|
+
return "";
|
|
1335
|
+
let chunks = chunkBase64(data, options.chunkSize ?? 4096), baseControls = [
|
|
1336
|
+
"a=T",
|
|
1337
|
+
"f=100",
|
|
1338
|
+
options.quiet === !1 ? "" : "q=2",
|
|
1339
|
+
options.noCursorMove === !1 ? "" : "C=1",
|
|
1340
|
+
uint32Control("i", options.imageId),
|
|
1341
|
+
uint32Control("I", options.imageNumber),
|
|
1342
|
+
uint32Control("p", options.placementId),
|
|
1343
|
+
...kittyGraphicCellControls(options.columns, options.rows),
|
|
1344
|
+
...kittyGraphicSourceControls(
|
|
1345
|
+
options.sourceX,
|
|
1346
|
+
options.sourceY,
|
|
1347
|
+
options.sourceWidth,
|
|
1348
|
+
options.sourceHeight
|
|
1349
|
+
),
|
|
1350
|
+
int32Control("z", options.zIndex)
|
|
1351
|
+
].filter(Boolean);
|
|
1352
|
+
return chunks.map((chunk, index) => {
|
|
1353
|
+
let last = index === chunks.length - 1, controls = index === 0 ? [...baseControls, chunks.length > 1 ? `m=${last ? 0 : 1}` : ""] : [options.quiet === !1 ? "" : "q=2", `m=${last ? 0 : 1}`].filter(Boolean);
|
|
1354
|
+
return `${ESC}_G${controls.filter(Boolean).join(",")};${chunk}${ST}`;
|
|
1355
|
+
}).join("");
|
|
1356
|
+
}
|
|
1357
|
+
function createKittyDeleteGraphicsSequence(options = {}) {
|
|
1358
|
+
let controls = ["a=d"];
|
|
1359
|
+
if (options.allVisible)
|
|
1360
|
+
controls.push(`d=${options.freeImageData ? "A" : "a"}`);
|
|
1361
|
+
else if (options.imageId != null) {
|
|
1362
|
+
let imageId = uint32Control("i", options.imageId), placementId = uint32Control("p", options.placementId);
|
|
1363
|
+
if (!imageId || options.placementId != null && !placementId)
|
|
1364
|
+
return "";
|
|
1365
|
+
controls.push(`d=${options.freeImageData ? "I" : "i"}`), controls.push(imageId), controls.push(placementId);
|
|
1366
|
+
} else if (options.currentCell)
|
|
1367
|
+
controls.push(`d=${options.freeImageData ? "C" : "c"}`);
|
|
1368
|
+
else
|
|
1369
|
+
return "";
|
|
1370
|
+
return options.quiet !== !1 && controls.push("q=2"), `${ESC}_G${controls.filter(Boolean).join(",")}${ST}`;
|
|
1371
|
+
}
|
|
1372
|
+
function createIterm2InlineImageSequence(base64Data, options = {}) {
|
|
1373
|
+
let data = sanitizeBase64(base64Data);
|
|
1374
|
+
if (!data)
|
|
1375
|
+
return "";
|
|
1376
|
+
let params = [
|
|
1377
|
+
"inline=1",
|
|
1378
|
+
options.width != null ? `width=${formatItermDimension(options.width)}` : "",
|
|
1379
|
+
options.height != null ? `height=${formatItermDimension(options.height)}` : "",
|
|
1380
|
+
`preserveAspectRatio=${options.preserveAspectRatio === !1 ? 0 : 1}`,
|
|
1381
|
+
options.doNotMoveCursor === !1 ? "" : "doNotMoveCursor=1"
|
|
1382
|
+
].filter(Boolean);
|
|
1383
|
+
return `${ESC}]1337;File=${params.join(";")}:${data}${BEL}`;
|
|
1384
|
+
}
|
|
1385
|
+
function formatItermDimension(value) {
|
|
1386
|
+
if (typeof value == "number") {
|
|
1387
|
+
let n = Math.floor(value);
|
|
1388
|
+
return Number.isFinite(n) ? String(Math.min(99999, Math.max(1, n))) : "auto";
|
|
1389
|
+
}
|
|
1390
|
+
let raw = String(value ?? "").trim();
|
|
1391
|
+
return validateIterm2Dimension(raw) ? raw : "auto";
|
|
1392
|
+
}
|
|
1393
|
+
function resolveKittyPngSourceCrop(rect, fullRect, sourceWidth, sourceHeight) {
|
|
1394
|
+
if (fullRect.w <= 0 || fullRect.h <= 0)
|
|
1395
|
+
return null;
|
|
1396
|
+
let offsetX = Math.max(0, rect.x - fullRect.x), offsetY = Math.max(0, rect.y - fullRect.y), visibleW = Math.max(0, Math.min(rect.w, fullRect.w - offsetX)), visibleH = Math.max(0, Math.min(rect.h, fullRect.h - offsetY));
|
|
1397
|
+
if (offsetX <= 0 && offsetY <= 0 && visibleW >= fullRect.w && visibleH >= fullRect.h)
|
|
1398
|
+
return null;
|
|
1399
|
+
let sourceX = Math.max(
|
|
1400
|
+
0,
|
|
1401
|
+
Math.min(sourceWidth - 1, Math.floor(offsetX * sourceWidth / fullRect.w))
|
|
1402
|
+
), sourceY = Math.max(
|
|
1403
|
+
0,
|
|
1404
|
+
Math.min(sourceHeight - 1, Math.floor(offsetY * sourceHeight / fullRect.h))
|
|
1405
|
+
), sourceRight = Math.max(
|
|
1406
|
+
sourceX + 1,
|
|
1407
|
+
Math.min(sourceWidth, Math.ceil((offsetX + visibleW) * sourceWidth / fullRect.w))
|
|
1408
|
+
), sourceBottom = Math.max(
|
|
1409
|
+
sourceY + 1,
|
|
1410
|
+
Math.min(sourceHeight, Math.ceil((offsetY + visibleH) * sourceHeight / fullRect.h))
|
|
1411
|
+
);
|
|
1412
|
+
return {
|
|
1413
|
+
sourceX,
|
|
1414
|
+
sourceY,
|
|
1415
|
+
sourceWidth: sourceRight - sourceX,
|
|
1416
|
+
sourceHeight: sourceBottom - sourceY
|
|
1417
|
+
};
|
|
1418
|
+
}
|
|
1419
|
+
function createTerminalGraphicPngSequence(options) {
|
|
1420
|
+
if (options.protocol === "kitty") {
|
|
1421
|
+
let placement = {
|
|
1422
|
+
columns: options.placementColumns,
|
|
1423
|
+
rows: options.placementRows
|
|
1424
|
+
};
|
|
1425
|
+
if (options.rect && options.fullRect && options.sourceWidth && options.sourceHeight) {
|
|
1426
|
+
let crop = resolveKittyPngSourceCrop(
|
|
1427
|
+
options.rect,
|
|
1428
|
+
options.fullRect,
|
|
1429
|
+
options.sourceWidth,
|
|
1430
|
+
options.sourceHeight
|
|
1431
|
+
);
|
|
1432
|
+
crop && (placement = { ...placement, ...crop });
|
|
1433
|
+
}
|
|
1434
|
+
let transmissionPlacement = options.cropTransmission !== !1 ? placement : {
|
|
1435
|
+
columns: options.transmissionColumns ?? options.placementColumns,
|
|
1436
|
+
rows: options.transmissionRows ?? options.placementRows
|
|
1437
|
+
};
|
|
1438
|
+
return {
|
|
1439
|
+
type: "sequence",
|
|
1440
|
+
protocol: "kitty",
|
|
1441
|
+
sequence: createKittyGraphicsSequence(options.base64, {
|
|
1442
|
+
imageId: options.imageId,
|
|
1443
|
+
placementId: options.placementId,
|
|
1444
|
+
zIndex: options.zIndex,
|
|
1445
|
+
...transmissionPlacement
|
|
1446
|
+
}),
|
|
1447
|
+
resizeSequence: createKittyPlacementSequence({
|
|
1448
|
+
imageId: options.imageId,
|
|
1449
|
+
placementId: options.placementId,
|
|
1450
|
+
zIndex: options.zIndex,
|
|
1451
|
+
...placement
|
|
1452
|
+
}),
|
|
1453
|
+
clearSequence: createKittyDeleteGraphicsSequence({
|
|
1454
|
+
imageId: options.imageId,
|
|
1455
|
+
placementId: options.placementId,
|
|
1456
|
+
freeImageData: options.freeImageData
|
|
1457
|
+
}),
|
|
1458
|
+
...options.fallback != null ? { fallback: options.fallback } : {},
|
|
1459
|
+
...options.cols != null ? { cols: options.cols } : {},
|
|
1460
|
+
...options.rows != null ? { rows: options.rows } : {},
|
|
1461
|
+
...options.sourceWidth != null ? { sourceWidth: options.sourceWidth } : {},
|
|
1462
|
+
...options.sourceHeight != null ? { sourceHeight: options.sourceHeight } : {},
|
|
1463
|
+
...options.zIndex != null ? { zIndex: options.zIndex } : {}
|
|
1464
|
+
};
|
|
1465
|
+
}
|
|
1466
|
+
return options.protocol === "iterm2" ? {
|
|
1467
|
+
type: "sequence",
|
|
1468
|
+
protocol: "iterm2",
|
|
1469
|
+
sequence: createIterm2InlineImageSequence(options.base64, {
|
|
1470
|
+
width: options.cols,
|
|
1471
|
+
height: options.rows,
|
|
1472
|
+
preserveAspectRatio: !0,
|
|
1473
|
+
doNotMoveCursor: !0
|
|
1474
|
+
}),
|
|
1475
|
+
...options.fallback != null ? { fallback: options.fallback } : {},
|
|
1476
|
+
...options.cols != null ? { cols: options.cols } : {},
|
|
1477
|
+
...options.rows != null ? { rows: options.rows } : {},
|
|
1478
|
+
...options.sourceWidth != null ? { sourceWidth: options.sourceWidth } : {},
|
|
1479
|
+
...options.sourceHeight != null ? { sourceHeight: options.sourceHeight } : {}
|
|
1480
|
+
} : null;
|
|
1481
|
+
}
|
|
1482
|
+
|
|
1483
|
+
// src/vue/scheduler/frame-mailbox.ts
|
|
1484
|
+
var EMPTY = Symbol("frame-mailbox-empty");
|
|
1485
|
+
function createFrameMailbox(options) {
|
|
1486
|
+
let disposed = !1, hasPending = !1, pending = EMPTY, queued = 0, pendingTaskId = null;
|
|
1487
|
+
function clearPending() {
|
|
1488
|
+
hasPending = !1, pending = EMPTY, queued = 0, pendingTaskId = null;
|
|
1489
|
+
}
|
|
1490
|
+
function currentTaskId() {
|
|
1491
|
+
if (pendingTaskId)
|
|
1492
|
+
return pendingTaskId;
|
|
1493
|
+
let id = typeof options.id == "function" ? options.id() : options.id;
|
|
1494
|
+
if (!id)
|
|
1495
|
+
throw new Error("createFrameMailbox requires a non-empty task id");
|
|
1496
|
+
return pendingTaskId = id, pendingTaskId;
|
|
1497
|
+
}
|
|
1498
|
+
function queue(value) {
|
|
1499
|
+
if (disposed)
|
|
1500
|
+
return !1;
|
|
1501
|
+
let wasPending = hasPending, taskId = wasPending ? pendingTaskId : currentTaskId(), nextPending;
|
|
1502
|
+
try {
|
|
1503
|
+
nextPending = hasPending && options.merge ? options.merge(pending, value) : value;
|
|
1504
|
+
} catch (error) {
|
|
1505
|
+
throw clearPending(), wasPending && options.scheduler.cancelFrameTask?.(taskId), error;
|
|
1506
|
+
}
|
|
1507
|
+
if (pending = nextPending, hasPending = !0, queued++, wasPending)
|
|
1508
|
+
return !0;
|
|
1509
|
+
let accepted;
|
|
1510
|
+
try {
|
|
1511
|
+
accepted = options.scheduler.queueFrameTask({
|
|
1512
|
+
id: taskId,
|
|
1513
|
+
reason: options.reason,
|
|
1514
|
+
priority: options.priority,
|
|
1515
|
+
sync: options.sync,
|
|
1516
|
+
run(ctx) {
|
|
1517
|
+
if (disposed || !hasPending)
|
|
1518
|
+
return;
|
|
1519
|
+
let value2 = pending, count = queued, dropped = Math.max(0, count - 1);
|
|
1520
|
+
clearPending(), ctx.reportMailboxDeliveryAttempt?.({
|
|
1521
|
+
id: taskId,
|
|
1522
|
+
queued: count,
|
|
1523
|
+
dropped
|
|
1524
|
+
}), options.apply(value2, ctx, {
|
|
1525
|
+
queued: count,
|
|
1526
|
+
dropped
|
|
1527
|
+
}), ctx.reportDroppedUpdates?.(dropped);
|
|
1528
|
+
}
|
|
1529
|
+
});
|
|
1530
|
+
} catch (error) {
|
|
1531
|
+
throw clearPending(), error;
|
|
1532
|
+
}
|
|
1533
|
+
return accepted === !1 ? (clearPending(), !1) : !0;
|
|
1534
|
+
}
|
|
1535
|
+
function replacePending(value) {
|
|
1536
|
+
return disposed ? !1 : hasPending ? (pending = value, !0) : queue(value);
|
|
1537
|
+
}
|
|
1538
|
+
function cancel() {
|
|
1539
|
+
let taskId = pendingTaskId;
|
|
1540
|
+
clearPending(), taskId && options.scheduler.cancelFrameTask?.(taskId);
|
|
1541
|
+
}
|
|
1542
|
+
function dispose() {
|
|
1543
|
+
cancel(), disposed = !0;
|
|
1544
|
+
}
|
|
1545
|
+
return {
|
|
1546
|
+
queue,
|
|
1547
|
+
replacePending,
|
|
1548
|
+
cancel,
|
|
1549
|
+
dispose,
|
|
1550
|
+
hasPending: () => hasPending,
|
|
1551
|
+
// Ambiguous when T includes undefined. Pair with hasPending() to
|
|
1552
|
+
// distinguish "pending undefined" from "no pending value".
|
|
1553
|
+
peek: () => hasPending ? pending : void 0
|
|
1554
|
+
};
|
|
1555
|
+
}
|
|
1556
|
+
|
|
1557
|
+
// src/vue/components/TAgentTerminalGraphic.ts
|
|
1558
|
+
var import_vue8 = require("vue");
|
|
1559
|
+
|
|
1560
|
+
// src/vue/composables/use-render-node.ts
|
|
1561
|
+
var import_vue7 = require("vue");
|
|
1562
|
+
|
|
1563
|
+
// src/vue/composables/use-render-stack.ts
|
|
1564
|
+
var import_vue6 = require("vue");
|
|
1565
|
+
|
|
1566
|
+
// src/vue/render/context.ts
|
|
1567
|
+
var RenderStackKey = injectionKey("RenderStack");
|
|
1568
|
+
|
|
1569
|
+
// src/vue/composables/use-render-stack.ts
|
|
1570
|
+
function useRenderStack() {
|
|
1571
|
+
let stack = (0, import_vue6.inject)(RenderStackKey, null);
|
|
1572
|
+
if (!stack)
|
|
1573
|
+
throw new Error("RenderStack is missing");
|
|
1574
|
+
return stack;
|
|
1575
|
+
}
|
|
1576
|
+
|
|
1577
|
+
// src/vue/composables/use-render-node.ts
|
|
1578
|
+
var pendingInvalidateByScheduler = /* @__PURE__ */ new WeakMap();
|
|
1579
|
+
function mergePriority(prev, next) {
|
|
1580
|
+
return prev === "high" || next === "high" ? "high" : prev === "normal" || next === "normal" ? "normal" : "low";
|
|
1581
|
+
}
|
|
1582
|
+
function requestBatchedInvalidate(scheduler, plane, priority) {
|
|
1583
|
+
let state = pendingInvalidateByScheduler.get(scheduler);
|
|
1584
|
+
if (state || (state = { queued: !1, plane: null, priority: "low" }, pendingInvalidateByScheduler.set(scheduler, state)), state.queued) {
|
|
1585
|
+
state.plane !== null && state.plane !== plane && (state.plane = null), state.priority = mergePriority(state.priority, priority);
|
|
1586
|
+
return;
|
|
1587
|
+
}
|
|
1588
|
+
state.plane = plane, state.priority = priority, state.queued = !0, queueMicrotask(() => {
|
|
1589
|
+
state.queued = !1;
|
|
1590
|
+
let queuedPlane = state.plane, queuedPriority = state.priority;
|
|
1591
|
+
state.plane = null, state.priority = "low", scheduler.invalidate({
|
|
1592
|
+
plane: queuedPlane ?? void 0,
|
|
1593
|
+
priority: queuedPriority
|
|
1594
|
+
});
|
|
1595
|
+
});
|
|
1596
|
+
}
|
|
1597
|
+
function sameRenderRect(a, b) {
|
|
1598
|
+
return a === b ? !0 : !a || !b ? !1 : a.x === b.x && a.y === b.y && a.w === b.w && a.h === b.h;
|
|
1599
|
+
}
|
|
1600
|
+
function sameDeps(a, b) {
|
|
1601
|
+
if (Object.is(a, b))
|
|
1602
|
+
return !0;
|
|
1603
|
+
if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length)
|
|
1604
|
+
return !1;
|
|
1605
|
+
for (let i = 0; i < a.length; i++)
|
|
1606
|
+
if (!Object.is(a[i], b[i]))
|
|
1607
|
+
return !1;
|
|
1608
|
+
return !0;
|
|
1609
|
+
}
|
|
1610
|
+
function useRenderNode(getOptions) {
|
|
1611
|
+
let { scheduler, render, widthProvider } = useTerminal(), parentStack = useRenderStack(), plane = (0, import_vue7.inject)(RenderPlaneContextKey, (0, import_vue7.ref)("default")), id = (0, import_vue7.ref)(null), lastPlane = (0, import_vue7.ref)(plane.value), lastStack = null, lastZIndex = 0, lastHasRect = !1, lastRect = null, lastDeps, lastHasDeps = !1, options = (0, import_vue7.computed)(() => withTextWidthProvider(widthProvider, getOptions)), stop = (0, import_vue7.watchEffect)(
|
|
1612
|
+
() => {
|
|
1613
|
+
let opt = options.value;
|
|
1614
|
+
opt.deps;
|
|
1615
|
+
let stack = opt.stack ?? parentStack.value, nextPlane = plane.value, hasRect = Object.prototype.hasOwnProperty.call(opt, "rect"), nextRect = hasRect ? opt.rect ?? null : null, nextZIndex = opt.zIndex ?? 0, hasDeps = Object.prototype.hasOwnProperty.call(opt, "deps");
|
|
1616
|
+
if (!stack)
|
|
1617
|
+
return;
|
|
1618
|
+
if (!id.value) {
|
|
1619
|
+
let node = render.register({
|
|
1620
|
+
stack,
|
|
1621
|
+
zIndex: nextZIndex,
|
|
1622
|
+
rect: hasRect ? nextRect : void 0,
|
|
1623
|
+
plane: nextPlane,
|
|
1624
|
+
paint: opt.paint
|
|
1625
|
+
});
|
|
1626
|
+
id.value = node.id, lastPlane.value = nextPlane, lastStack = stack, lastZIndex = nextZIndex, lastHasRect = hasRect, lastRect = nextRect, lastHasDeps = hasDeps, lastDeps = opt.deps, requestBatchedInvalidate(scheduler, nextPlane, opt.priority ?? "normal");
|
|
1627
|
+
return;
|
|
1628
|
+
}
|
|
1629
|
+
let prevPlane = lastPlane.value;
|
|
1630
|
+
if (hasDeps && lastHasDeps && !opt.dirtyRowsHint?.length && lastStack === stack && lastZIndex === nextZIndex && prevPlane === nextPlane && lastHasRect === hasRect && (!hasRect || sameRenderRect(lastRect, nextRect)) && sameDeps(lastDeps, opt.deps))
|
|
1631
|
+
return;
|
|
1632
|
+
let updatePayload = {
|
|
1633
|
+
stack,
|
|
1634
|
+
zIndex: nextZIndex,
|
|
1635
|
+
dirtyRowsHint: opt.dirtyRowsHint,
|
|
1636
|
+
plane: nextPlane,
|
|
1637
|
+
paint: opt.paint
|
|
1638
|
+
};
|
|
1639
|
+
hasRect && (updatePayload.rect = nextRect), render.update(id.value, updatePayload), lastPlane.value = nextPlane, lastStack = stack, lastZIndex = nextZIndex, lastHasRect = hasRect, lastRect = nextRect, lastHasDeps = hasDeps, lastDeps = opt.deps;
|
|
1640
|
+
let priority = opt.priority ?? "normal";
|
|
1641
|
+
requestBatchedInvalidate(scheduler, prevPlane, priority), prevPlane !== nextPlane && requestBatchedInvalidate(scheduler, nextPlane, priority);
|
|
1642
|
+
},
|
|
1643
|
+
{ flush: "sync" }
|
|
1644
|
+
);
|
|
1645
|
+
return (0, import_vue7.onBeforeUnmount)(() => {
|
|
1646
|
+
stop(), id.value && (render.unregister(id.value), requestBatchedInvalidate(scheduler, lastPlane.value, "normal"));
|
|
1647
|
+
}), { id };
|
|
1648
|
+
}
|
|
1649
|
+
|
|
1650
|
+
// src/vue/components/TAgentTerminalGraphic.ts
|
|
1651
|
+
var NO_GRAPHICS_CAPABILITIES = Object.freeze({
|
|
1652
|
+
supported: !1,
|
|
1653
|
+
kitty: !1,
|
|
1654
|
+
iterm2: !1,
|
|
1655
|
+
sixel: !1,
|
|
1656
|
+
preferredProtocol: null,
|
|
1657
|
+
protocol: "unicode",
|
|
1658
|
+
candidates: [],
|
|
1659
|
+
stdoutIsTTY: !1,
|
|
1660
|
+
insideTmux: !1,
|
|
1661
|
+
insideScreen: !1,
|
|
1662
|
+
insideZellij: !1,
|
|
1663
|
+
multiplexer: null,
|
|
1664
|
+
passthrough: !1,
|
|
1665
|
+
forced: !1,
|
|
1666
|
+
reason: "no-terminal-graphics-output"
|
|
1667
|
+
});
|
|
1668
|
+
function splitTextOutput(value) {
|
|
1669
|
+
let lines = sanitizeTextBlock(sanitizeTerminalFallbackText(value).replace(/\r\n?/g, `
|
|
1670
|
+
`)).split(`
|
|
1671
|
+
`);
|
|
1672
|
+
return lines.length ? lines : [""];
|
|
1673
|
+
}
|
|
1674
|
+
function hasVisibleOutput(value) {
|
|
1675
|
+
return value.some((line) => line.trim().length > 0);
|
|
1676
|
+
}
|
|
1677
|
+
function errorMessage(error) {
|
|
1678
|
+
return error instanceof Error ? error.message : String(error);
|
|
1679
|
+
}
|
|
1680
|
+
function positiveInt(value) {
|
|
1681
|
+
let n = Math.floor(Number(value));
|
|
1682
|
+
return Number.isFinite(n) && n > 0 ? n : void 0;
|
|
1683
|
+
}
|
|
1684
|
+
function finiteInt(value) {
|
|
1685
|
+
let n = Math.floor(Number(value));
|
|
1686
|
+
return Number.isFinite(n) ? n : void 0;
|
|
1687
|
+
}
|
|
1688
|
+
function clampNumber(value, min, max) {
|
|
1689
|
+
return Math.max(min, Math.min(max, value));
|
|
1690
|
+
}
|
|
1691
|
+
function rectArea(rect) {
|
|
1692
|
+
return Math.max(0, rect.w) * Math.max(0, rect.h);
|
|
1693
|
+
}
|
|
1694
|
+
function sameRect(a, b) {
|
|
1695
|
+
return a.x === b.x && a.y === b.y && a.w === b.w && a.h === b.h;
|
|
1696
|
+
}
|
|
1697
|
+
function subtractRect(rect, cover) {
|
|
1698
|
+
let hit = intersectRect(rect, cover);
|
|
1699
|
+
if (!hit)
|
|
1700
|
+
return [rect];
|
|
1701
|
+
let out = [], rectRight = rect.x + rect.w, rectBottom = rect.y + rect.h, hitRight = hit.x + hit.w, hitBottom = hit.y + hit.h;
|
|
1702
|
+
return hit.y > rect.y && out.push({ x: rect.x, y: rect.y, w: rect.w, h: hit.y - rect.y }), hitBottom < rectBottom && out.push({ x: rect.x, y: hitBottom, w: rect.w, h: rectBottom - hitBottom }), hit.x > rect.x && out.push({ x: rect.x, y: hit.y, w: hit.x - rect.x, h: hit.h }), hitRight < rectRight && out.push({ x: hitRight, y: hit.y, w: rectRight - hitRight, h: hit.h }), out.filter((part) => part.w > 0 && part.h > 0);
|
|
1703
|
+
}
|
|
1704
|
+
function largestUncoveredRect(rect, covers) {
|
|
1705
|
+
let parts = [rect];
|
|
1706
|
+
for (let cover of covers)
|
|
1707
|
+
if (parts = parts.flatMap((part) => subtractRect(part, cover)), !parts.length)
|
|
1708
|
+
return null;
|
|
1709
|
+
return parts.sort((a, b) => rectArea(b) - rectArea(a) || a.y - b.y || a.x - b.x), parts[0] ?? null;
|
|
1710
|
+
}
|
|
1711
|
+
function parseKittyClearControls(sequence) {
|
|
1712
|
+
let prefix = "\x1B_G", terminator = "\x1B\\";
|
|
1713
|
+
if (!sequence.startsWith(prefix) || !sequence.endsWith(terminator))
|
|
1714
|
+
return null;
|
|
1715
|
+
let body = sequence.slice(prefix.length, -terminator.length);
|
|
1716
|
+
if (body.includes(terminator) || body.includes("\x1B") || body.includes("\x07"))
|
|
1717
|
+
return null;
|
|
1718
|
+
let semicolon = body.indexOf(";"), rawControls = semicolon >= 0 ? body.slice(0, semicolon) : body, controls = /* @__PURE__ */ new Map();
|
|
1719
|
+
for (let part of rawControls.split(",")) {
|
|
1720
|
+
let eq = part.indexOf("=");
|
|
1721
|
+
if (eq <= 0)
|
|
1722
|
+
return null;
|
|
1723
|
+
controls.set(part.slice(0, eq), part.slice(eq + 1));
|
|
1724
|
+
}
|
|
1725
|
+
return controls;
|
|
1726
|
+
}
|
|
1727
|
+
function kittyClearTargetsComponent(sequence, imageId, placementId) {
|
|
1728
|
+
let controls = parseKittyClearControls(sequence);
|
|
1729
|
+
if (!controls)
|
|
1730
|
+
return !1;
|
|
1731
|
+
let mode = controls.get("d");
|
|
1732
|
+
return mode !== "i" && mode !== "I" ? !1 : controls.get("i") === String(imageId) && controls.get("p") === String(placementId);
|
|
1733
|
+
}
|
|
1734
|
+
function isSafeComponentClearSequence(sequence, protocol, imageId, placementId) {
|
|
1735
|
+
return isSafeTerminalGraphicsSequence(sequence, protocol, "clear") ? protocol !== "kitty" || kittyClearTargetsComponent(sequence, imageId, placementId) : !1;
|
|
1736
|
+
}
|
|
1737
|
+
var textEncoder = null;
|
|
1738
|
+
function stringByteLength(value) {
|
|
1739
|
+
if (typeof TextEncoder < "u")
|
|
1740
|
+
return textEncoder ?? (textEncoder = new TextEncoder()), textEncoder.encode(value).length;
|
|
1741
|
+
let bytes = 0;
|
|
1742
|
+
for (let index = 0; index < value.length; index++) {
|
|
1743
|
+
let code = value.charCodeAt(index);
|
|
1744
|
+
code <= 127 ? bytes += 1 : code <= 2047 ? bytes += 2 : code >= 55296 && code <= 56319 && index + 1 < value.length ? (bytes += 4, index++) : bytes += 3;
|
|
1745
|
+
}
|
|
1746
|
+
return bytes;
|
|
1747
|
+
}
|
|
1748
|
+
function smallHash(input) {
|
|
1749
|
+
let hash = 2166136261;
|
|
1750
|
+
for (let i = 0; i < input.length; i++)
|
|
1751
|
+
hash ^= input.charCodeAt(i), hash = Math.imul(hash, 16777619);
|
|
1752
|
+
return (hash >>> 0).toString(36);
|
|
1753
|
+
}
|
|
1754
|
+
var tAgentTerminalGraphicProps = {
|
|
1755
|
+
x: { type: Number, required: !0 },
|
|
1756
|
+
y: { type: Number, required: !0 },
|
|
1757
|
+
w: { type: Number, required: !0 },
|
|
1758
|
+
h: { type: Number, default: void 0 },
|
|
1759
|
+
zIndex: { type: Number, default: 0 },
|
|
1760
|
+
content: { type: String, required: !0 },
|
|
1761
|
+
kind: {
|
|
1762
|
+
type: String,
|
|
1763
|
+
default: "image"
|
|
1764
|
+
},
|
|
1765
|
+
fallback: { type: String, default: void 0 },
|
|
1766
|
+
style: { type: Object, default: void 0 },
|
|
1767
|
+
loadingStyle: { type: Object, default: void 0 },
|
|
1768
|
+
errorStyle: { type: Object, default: void 0 },
|
|
1769
|
+
clear: { type: Boolean, default: !0 },
|
|
1770
|
+
final: { type: Boolean, default: !0 },
|
|
1771
|
+
streaming: { type: Boolean, default: !1 },
|
|
1772
|
+
renderer: {
|
|
1773
|
+
type: Function,
|
|
1774
|
+
default: void 0
|
|
1775
|
+
},
|
|
1776
|
+
loadingText: {
|
|
1777
|
+
type: String,
|
|
1778
|
+
default: "Rendering terminal graphic..."
|
|
1779
|
+
},
|
|
1780
|
+
deferRenderUntilVisible: { type: Boolean, default: !0 },
|
|
1781
|
+
suspendRawWhileScrolling: { type: Boolean, default: !0 },
|
|
1782
|
+
suspendRenderWhileScrolling: { type: Boolean, default: !0 },
|
|
1783
|
+
scrolling: { type: Boolean, default: !1 },
|
|
1784
|
+
scrollVersion: { type: Number, default: 0 },
|
|
1785
|
+
/** Advanced Kitty-only opt-in for moving an unchanged image via a reusable placement sequence. */
|
|
1786
|
+
placementMoveWithoutClear: { type: Boolean, default: !1 },
|
|
1787
|
+
preserveRawWhileRendering: { type: Boolean, default: !1 },
|
|
1788
|
+
suspended: { type: Boolean, default: !1 },
|
|
1789
|
+
retainRawWhileCovered: { type: Boolean, default: !1 },
|
|
1790
|
+
ignoreRawCoverage: { type: Boolean, default: !1 },
|
|
1791
|
+
ignoreSamePlaneRawCoverage: { type: Boolean, default: !1 },
|
|
1792
|
+
cacheKey: { type: String, default: void 0 },
|
|
1793
|
+
placementKey: { type: String, default: void 0 },
|
|
1794
|
+
trace: {
|
|
1795
|
+
type: Function,
|
|
1796
|
+
default: void 0
|
|
1797
|
+
}
|
|
1798
|
+
};
|
|
1799
|
+
function terminalDrawKey(current, rect, clearSequence, resizeSequence) {
|
|
1800
|
+
return [
|
|
1801
|
+
current.protocol,
|
|
1802
|
+
rect.x,
|
|
1803
|
+
rect.y,
|
|
1804
|
+
rect.w,
|
|
1805
|
+
rect.h,
|
|
1806
|
+
current.sequenceHash,
|
|
1807
|
+
clearSequence === current.clearSequence ? current.clearSequenceHash ?? "" : smallHash(clearSequence ?? ""),
|
|
1808
|
+
resizeSequence === current.resizeSequence ? current.resizeSequenceHash ?? "" : smallHash(resizeSequence ?? "")
|
|
1809
|
+
].join(":");
|
|
1810
|
+
}
|
|
1811
|
+
var TAgentTerminalGraphic = (0, import_vue8.defineComponent)({
|
|
1812
|
+
name: "TAgentTerminalGraphic",
|
|
1813
|
+
props: tAgentTerminalGraphicProps,
|
|
1814
|
+
setup(props) {
|
|
1815
|
+
let instance = (0, import_vue8.getCurrentInstance)(), { terminal, defaultStyle, scheduler, widthProvider, render } = useTerminal(), layout = useLayout(), { visible, rootProps } = useVisibility(), graphicsActivity = (0, import_vue8.inject)(TerminalGraphicsActivityKey, null), status = (0, import_vue8.shallowRef)("idle"), error = (0, import_vue8.shallowRef)(""), graphic = (0, import_vue8.shallowRef)(null), documentVersion = (0, import_vue8.shallowRef)(0), builtOnce = !1, renderVersion = 0, renderAbort = null, alive = !0, lastRenderedContent = "", lastRenderRawVisible = !1, lastRenderProtocol = null, lastRenderGraphicsOutputVersion = 0, rawIdSeed = props.placementKey ? `placement:${props.placementKey}` : props.cacheKey ? `cache:${props.cacheKey}` : `instance:${instance?.uid ?? "unknown"}`, rawId = `TAgentTerminalGraphic:${smallHash(rawIdSeed)}`, frameTaskId = `${rawId}:render`, lastDrawnGraphic = (0, import_vue8.shallowRef)(null), rawClearPendingRepaint = (0, import_vue8.shallowRef)(null), rawDrawRejectedKey = (0, import_vue8.shallowRef)(null), reservedTerminalGraphicSize = (0, import_vue8.shallowRef)(null), terminalSizeVersion = (0, import_vue8.shallowRef)(0), renderNodeId = (0, import_vue8.shallowRef)(null), lastRawSkipScrollKey = "", lastDeferTraceKey = "", isParentScrolling = (0, import_vue8.computed)(
|
|
1816
|
+
() => props.scrolling || !!graphicsActivity?.scrolling.value
|
|
1817
|
+
), graphicsActivityVersion = (0, import_vue8.computed)(
|
|
1818
|
+
() => (graphicsActivity?.version.value ?? 0) + Math.floor(Number(props.scrollVersion ?? 0))
|
|
1819
|
+
), graphicsOutput = () => getTerminalGraphicsOutput(terminal), graphicsOutputVersion = (0, import_vue8.shallowRef)(getTerminalGraphicsOutputVersion(terminal)), unsubscribeGraphicsOutput = subscribeTerminalGraphicsOutput(terminal, () => {
|
|
1820
|
+
graphicsOutputVersion.value = getTerminalGraphicsOutputVersion(terminal);
|
|
1821
|
+
}), unsubscribeTerminalResize = terminal.on("resize", () => {
|
|
1822
|
+
terminalSizeVersion.value++;
|
|
1823
|
+
}), fallbackText = () => props.fallback ?? (props.kind === "math" ? props.content : ""), contentIdentity = (0, import_vue8.computed)(() => `${props.content.length}:${smallHash(props.content)}`), stableGraphicKey = (0, import_vue8.computed)(
|
|
1824
|
+
() => [
|
|
1825
|
+
rawIdSeed,
|
|
1826
|
+
props.cacheKey ?? "",
|
|
1827
|
+
props.kind,
|
|
1828
|
+
contentIdentity.value,
|
|
1829
|
+
props.w,
|
|
1830
|
+
props.h ?? "",
|
|
1831
|
+
props.final ? "final" : "draft"
|
|
1832
|
+
].join("")
|
|
1833
|
+
), imageId = (0, import_vue8.computed)(
|
|
1834
|
+
() => stableTerminalGraphicNumericId(`image:${stableGraphicKey.value}`)
|
|
1835
|
+
), placementId = (0, import_vue8.computed)(
|
|
1836
|
+
() => stableTerminalGraphicNumericId(`placement:${stableGraphicKey.value}`)
|
|
1837
|
+
);
|
|
1838
|
+
function rememberTerminalGraphicSize(current) {
|
|
1839
|
+
if (current.type !== "terminal")
|
|
1840
|
+
return;
|
|
1841
|
+
let rows = positiveInt(current.rows);
|
|
1842
|
+
rows && (reservedTerminalGraphicSize.value = {
|
|
1843
|
+
key: stableGraphicKey.value,
|
|
1844
|
+
rows
|
|
1845
|
+
});
|
|
1846
|
+
}
|
|
1847
|
+
function bump() {
|
|
1848
|
+
documentVersion.value++;
|
|
1849
|
+
}
|
|
1850
|
+
function currentCapabilities() {
|
|
1851
|
+
return graphicsOutput()?.capabilities ?? NO_GRAPHICS_CAPABILITIES;
|
|
1852
|
+
}
|
|
1853
|
+
function trace(type, extra = {}) {
|
|
1854
|
+
let capabilities = currentCapabilities();
|
|
1855
|
+
try {
|
|
1856
|
+
props.trace?.({
|
|
1857
|
+
type,
|
|
1858
|
+
id: rawId,
|
|
1859
|
+
kind: props.kind,
|
|
1860
|
+
protocol: capabilities.protocol,
|
|
1861
|
+
contentHash: smallHash(props.content),
|
|
1862
|
+
...extra
|
|
1863
|
+
});
|
|
1864
|
+
} catch {
|
|
1865
|
+
}
|
|
1866
|
+
let protocol = isTerminalGraphicsProtocol(capabilities.protocol) ? capabilities.protocol : void 0, key = props.cacheKey ?? smallHash(props.content);
|
|
1867
|
+
type === "render-start" ? recordTerminalGraphicTrace({ type: "renderer-start", id: rawId, key, protocol }) : type === "render-end" ? recordTerminalGraphicTrace({
|
|
1868
|
+
type: extra.reason ? "renderer-error" : "renderer-end",
|
|
1869
|
+
id: rawId,
|
|
1870
|
+
key,
|
|
1871
|
+
protocol,
|
|
1872
|
+
durationMs: extra.durationMs,
|
|
1873
|
+
bytes: extra.sequenceBytes,
|
|
1874
|
+
error: extra.reason
|
|
1875
|
+
}) : type === "defer" ? recordTerminalGraphicTrace({
|
|
1876
|
+
type: extra.reason === "scrolling" ? "skip-scrolling" : "skip-hidden",
|
|
1877
|
+
id: rawId,
|
|
1878
|
+
key,
|
|
1879
|
+
protocol,
|
|
1880
|
+
reason: extra.reason
|
|
1881
|
+
}) : type === "raw-draw" || (type === "render-abort" ? recordTerminalGraphicTrace({
|
|
1882
|
+
type: "renderer-abort",
|
|
1883
|
+
id: rawId,
|
|
1884
|
+
key,
|
|
1885
|
+
protocol,
|
|
1886
|
+
reason: extra.reason
|
|
1887
|
+
}) : type === "raw-clear" ? recordTerminalGraphicTrace({ type: "clear", id: rawId, key, protocol }) : type === "raw-skip-scroll" && recordTerminalGraphicTrace({
|
|
1888
|
+
type: "skip-scrolling",
|
|
1889
|
+
id: rawId,
|
|
1890
|
+
key,
|
|
1891
|
+
protocol,
|
|
1892
|
+
reason: extra.reason
|
|
1893
|
+
}));
|
|
1894
|
+
}
|
|
1895
|
+
function traceDeferOnce(reason) {
|
|
1896
|
+
let key = [reason, graphicsActivityVersion.value, stableGraphicKey.value].join(":");
|
|
1897
|
+
lastDeferTraceKey !== key && (lastDeferTraceKey = key, trace("defer", { reason }));
|
|
1898
|
+
}
|
|
1899
|
+
function abortCurrentRender(reason) {
|
|
1900
|
+
renderAbort && (renderAbort.abort(), renderAbort = null, trace("render-abort", { reason }));
|
|
1901
|
+
}
|
|
1902
|
+
function normalizeResult(result) {
|
|
1903
|
+
if (result == null)
|
|
1904
|
+
return {
|
|
1905
|
+
type: "text",
|
|
1906
|
+
text: fallbackText()
|
|
1907
|
+
};
|
|
1908
|
+
if (typeof result == "string")
|
|
1909
|
+
return {
|
|
1910
|
+
type: "text",
|
|
1911
|
+
text: result
|
|
1912
|
+
};
|
|
1913
|
+
if (typeof result != "object")
|
|
1914
|
+
return {
|
|
1915
|
+
type: "text",
|
|
1916
|
+
text: fallbackText()
|
|
1917
|
+
};
|
|
1918
|
+
if ("type" in result && result.type === "text")
|
|
1919
|
+
return {
|
|
1920
|
+
type: "text",
|
|
1921
|
+
text: result.text
|
|
1922
|
+
};
|
|
1923
|
+
let maybeRaw = result;
|
|
1924
|
+
if (!(maybeRaw.type === "sequence" || "sequence" in result || "protocol" in result) && "text" in result)
|
|
1925
|
+
return {
|
|
1926
|
+
type: "text",
|
|
1927
|
+
text: result.text
|
|
1928
|
+
};
|
|
1929
|
+
let sequence = typeof maybeRaw.sequence == "string" ? maybeRaw.sequence : "", protocol = isTerminalGraphicsProtocol(maybeRaw.protocol) ? maybeRaw.protocol : null, fallback = typeof maybeRaw.fallback == "string" ? sanitizeTerminalFallbackText(maybeRaw.fallback) : fallbackText(), fallbackFromProps = typeof maybeRaw.fallback != "string";
|
|
1930
|
+
if (!sequence || !protocol || !isSafeTerminalGraphicsSequence(sequence, protocol, "draw"))
|
|
1931
|
+
return {
|
|
1932
|
+
type: "text",
|
|
1933
|
+
text: fallback
|
|
1934
|
+
};
|
|
1935
|
+
let rawClear = typeof maybeRaw.clearSequence == "string" ? maybeRaw.clearSequence : void 0, clearSequence = rawClear && isSafeComponentClearSequence(rawClear, protocol, imageId.value, placementId.value) ? rawClear : void 0, rawResize = typeof maybeRaw.resizeSequence == "string" ? maybeRaw.resizeSequence : void 0, resizeSequence = rawResize && isSafeTerminalGraphicsSequence(rawResize, protocol, "draw") ? rawResize : void 0, declaredRows = positiveInt(maybeRaw.rows), declaredCols = positiveInt(maybeRaw.cols), sourceWidth = positiveInt(maybeRaw.sourceWidth), sourceHeight = positiveInt(maybeRaw.sourceHeight), zIndex = finiteInt(maybeRaw.zIndex), declaredSize = declaredRows == null ? null : normalizeTerminalGraphicSize(declaredCols ?? props.w, declaredRows);
|
|
1936
|
+
return {
|
|
1937
|
+
type: "terminal",
|
|
1938
|
+
protocol,
|
|
1939
|
+
sequence,
|
|
1940
|
+
sequenceHash: smallHash(sequence),
|
|
1941
|
+
sequenceBytes: stringByteLength(sequence),
|
|
1942
|
+
fallback,
|
|
1943
|
+
fallbackFromProps,
|
|
1944
|
+
clearSequence,
|
|
1945
|
+
clearSequenceHash: clearSequence ? smallHash(clearSequence) : void 0,
|
|
1946
|
+
resizeSequence,
|
|
1947
|
+
resizeSequenceHash: resizeSequence ? smallHash(resizeSequence) : void 0,
|
|
1948
|
+
cols: declaredRows == null ? declaredCols : declaredSize?.width,
|
|
1949
|
+
rows: declaredSize?.height,
|
|
1950
|
+
sourceWidth,
|
|
1951
|
+
sourceHeight,
|
|
1952
|
+
zIndex
|
|
1953
|
+
};
|
|
1954
|
+
}
|
|
1955
|
+
function defaultClearSequence(protocol) {
|
|
1956
|
+
return protocol === "kitty" ? createKittyDeleteGraphicsSequence({
|
|
1957
|
+
imageId: imageId.value,
|
|
1958
|
+
placementId: placementId.value
|
|
1959
|
+
}) : "";
|
|
1960
|
+
}
|
|
1961
|
+
function resolveClearSequence(current) {
|
|
1962
|
+
if (current.clearSequence)
|
|
1963
|
+
return current.clearSequence;
|
|
1964
|
+
let candidate = defaultClearSequence(current.protocol);
|
|
1965
|
+
if (candidate)
|
|
1966
|
+
return isSafeComponentClearSequence(
|
|
1967
|
+
candidate,
|
|
1968
|
+
current.protocol,
|
|
1969
|
+
imageId.value,
|
|
1970
|
+
placementId.value
|
|
1971
|
+
) ? candidate : void 0;
|
|
1972
|
+
}
|
|
1973
|
+
function resolveResizeSequence(current, rect, full) {
|
|
1974
|
+
if (current.protocol !== "kitty")
|
|
1975
|
+
return current.resizeSequence;
|
|
1976
|
+
let sourceWidth = positiveInt(current.sourceWidth), sourceHeight = positiveInt(current.sourceHeight);
|
|
1977
|
+
if (!sourceWidth || !sourceHeight || full.w <= 0 || full.h <= 0)
|
|
1978
|
+
return current.resizeSequence;
|
|
1979
|
+
let offsetX = Math.max(0, rect.x - full.x), offsetY = Math.max(0, rect.y - full.y), visibleW = Math.max(0, Math.min(rect.w, full.w - offsetX)), visibleH = Math.max(0, Math.min(rect.h, full.h - offsetY)), x0 = clampNumber(Math.floor(offsetX * sourceWidth / full.w), 0, sourceWidth - 1), y0 = clampNumber(Math.floor(offsetY * sourceHeight / full.h), 0, sourceHeight - 1), x1 = Math.max(
|
|
1980
|
+
x0 + 1,
|
|
1981
|
+
clampNumber(Math.ceil((offsetX + visibleW) * sourceWidth / full.w), 1, sourceWidth)
|
|
1982
|
+
), y1 = Math.max(
|
|
1983
|
+
y0 + 1,
|
|
1984
|
+
clampNumber(Math.ceil((offsetY + visibleH) * sourceHeight / full.h), 1, sourceHeight)
|
|
1985
|
+
);
|
|
1986
|
+
return createKittyPlacementSequence({
|
|
1987
|
+
imageId: imageId.value,
|
|
1988
|
+
placementId: placementId.value,
|
|
1989
|
+
columns: rect.w,
|
|
1990
|
+
rows: rect.h,
|
|
1991
|
+
sourceX: x0,
|
|
1992
|
+
sourceY: y0,
|
|
1993
|
+
sourceWidth: x1 - x0,
|
|
1994
|
+
sourceHeight: y1 - y0,
|
|
1995
|
+
zIndex: current.zIndex
|
|
1996
|
+
});
|
|
1997
|
+
}
|
|
1998
|
+
function queueClearLastGraphic(options = {}) {
|
|
1999
|
+
let previous = lastDrawnGraphic.value;
|
|
2000
|
+
if (!previous)
|
|
2001
|
+
return !1;
|
|
2002
|
+
let output = graphicsOutput(), accepted = !1;
|
|
2003
|
+
if (output?.clear && !previous.retainOnClear)
|
|
2004
|
+
try {
|
|
2005
|
+
accepted = !!output.clear(previous.id);
|
|
2006
|
+
} catch {
|
|
2007
|
+
accepted = !1;
|
|
2008
|
+
}
|
|
2009
|
+
if (!accepted && output && previous.clearSequence)
|
|
2010
|
+
try {
|
|
2011
|
+
accepted = output.queue({
|
|
2012
|
+
id: previous.id,
|
|
2013
|
+
x: previous.x,
|
|
2014
|
+
y: previous.y,
|
|
2015
|
+
w: previous.w,
|
|
2016
|
+
h: previous.h,
|
|
2017
|
+
protocol: previous.protocol,
|
|
2018
|
+
sequence: previous.clearSequence,
|
|
2019
|
+
deferFlush: !0,
|
|
2020
|
+
retainOnClear: previous.retainOnClear,
|
|
2021
|
+
op: "clear"
|
|
2022
|
+
});
|
|
2023
|
+
} catch {
|
|
2024
|
+
accepted = !1;
|
|
2025
|
+
}
|
|
2026
|
+
return accepted && ((options.markPendingRepaint ?? !0) && (rawClearPendingRepaint.value = previous), lastDrawnGraphic.value = null, trace("raw-clear", {
|
|
2027
|
+
x: previous.x,
|
|
2028
|
+
y: previous.y,
|
|
2029
|
+
w: previous.w,
|
|
2030
|
+
h: previous.h
|
|
2031
|
+
})), accepted;
|
|
2032
|
+
}
|
|
2033
|
+
function queueDrawGraphic(output, current, rect, full = rect, options = {}) {
|
|
2034
|
+
let clearSequence = resolveClearSequence(current), resizeSequence = resolveResizeSequence(current, rect, full), drawKey = terminalDrawKey(current, rect, clearSequence, resizeSequence), activePrevious = lastDrawnGraphic.value, retainedPrevious = rawClearPendingRepaint.value, previous = activePrevious ?? retainedPrevious, previousIsRetained = activePrevious == null && retainedPrevious != null, previousStillActive = previous ? typeof output.isActive == "function" ? output.isActive(previous.id) : !0 : !1, preservePreviousForAtomicReplace = props.preserveRawWhileRendering && activePrevious != null && !previousIsRetained && previousStillActive;
|
|
2035
|
+
if (!previousIsRetained && !options.force && previous?.drawKey === drawKey && previousStillActive)
|
|
2036
|
+
return !1;
|
|
2037
|
+
let canReusePlacementSequence = previousStillActive && previous?.protocol === current.protocol && previous.sequenceHash === current.sequenceHash && current.protocol === "kitty" && !!resizeSequence, scrollVersion = Math.floor(Number(props.scrollVersion ?? 0)), canMoveWithoutClear = canReusePlacementSequence && !!options.placementMoveWithoutClear;
|
|
2038
|
+
if (!previousIsRetained && previousStillActive && !resizeSequence && previous?.protocol === current.protocol && previous.sequenceHash === current.sequenceHash && previous.x === rect.x && previous.y === rect.y && rect.w <= previous.w && rect.h <= previous.h && (options.force || !sameRect(rect, full)))
|
|
2039
|
+
return lastDrawnGraphic.value = {
|
|
2040
|
+
...previous,
|
|
2041
|
+
w: rect.w,
|
|
2042
|
+
h: rect.h,
|
|
2043
|
+
clearSequence,
|
|
2044
|
+
resizeSequence,
|
|
2045
|
+
drawKey,
|
|
2046
|
+
activityVersion: graphicsActivityVersion.value,
|
|
2047
|
+
scrollVersion
|
|
2048
|
+
}, lastRawSkipScrollKey = "", !1;
|
|
2049
|
+
if (previousStillActive && !previousIsRetained && !canReusePlacementSequence && !preservePreviousForAtomicReplace) {
|
|
2050
|
+
if (!queueClearLastGraphic({ markPendingRepaint: !1 }))
|
|
2051
|
+
return !1;
|
|
2052
|
+
} else
|
|
2053
|
+
previous && (previousStillActive || (lastDrawnGraphic.value = null, rawClearPendingRepaint.value = null));
|
|
2054
|
+
let accepted = !1;
|
|
2055
|
+
try {
|
|
2056
|
+
accepted = output.queue({
|
|
2057
|
+
id: rawId,
|
|
2058
|
+
x: rect.x,
|
|
2059
|
+
y: rect.y,
|
|
2060
|
+
w: rect.w,
|
|
2061
|
+
h: rect.h,
|
|
2062
|
+
protocol: current.protocol,
|
|
2063
|
+
sequence: canReusePlacementSequence && resizeSequence ? resizeSequence : current.sequence,
|
|
2064
|
+
resizeSequence,
|
|
2065
|
+
clearSequence,
|
|
2066
|
+
retainOnClear: !!(props.cacheKey && resizeSequence),
|
|
2067
|
+
resizeRedraw: canReusePlacementSequence,
|
|
2068
|
+
placementMoveWithoutClear: canMoveWithoutClear,
|
|
2069
|
+
allowTextOverlay: options.allowTextOverlay,
|
|
2070
|
+
forceDraw: options.force,
|
|
2071
|
+
deferFlush: options.deferFlush ?? !0,
|
|
2072
|
+
fallbackText: current.fallback
|
|
2073
|
+
});
|
|
2074
|
+
} catch {
|
|
2075
|
+
accepted = !1;
|
|
2076
|
+
}
|
|
2077
|
+
return accepted ? (rawDrawRejectedKey.value = null, rawClearPendingRepaint.value = null, lastDrawnGraphic.value = {
|
|
2078
|
+
id: rawId,
|
|
2079
|
+
x: rect.x,
|
|
2080
|
+
y: rect.y,
|
|
2081
|
+
w: rect.w,
|
|
2082
|
+
h: rect.h,
|
|
2083
|
+
protocol: current.protocol,
|
|
2084
|
+
sequenceHash: current.sequenceHash,
|
|
2085
|
+
clearSequence,
|
|
2086
|
+
resizeSequence,
|
|
2087
|
+
retainOnClear: !!(props.cacheKey && resizeSequence),
|
|
2088
|
+
allowTextOverlay: !!options.allowTextOverlay,
|
|
2089
|
+
drawKey,
|
|
2090
|
+
activityVersion: graphicsActivityVersion.value,
|
|
2091
|
+
scrollVersion
|
|
2092
|
+
}, lastRawSkipScrollKey = "", !0) : (preservePreviousForAtomicReplace ? (lastDrawnGraphic.value = activePrevious, queueClearLastGraphic({ markPendingRepaint: !1 })) : lastDrawnGraphic.value = null, rawDrawRejectedKey.value !== drawKey && (rawDrawRejectedKey.value = drawKey, scheduler.invalidate({ priority: "low", reason: "data" })), !1);
|
|
2093
|
+
}
|
|
2094
|
+
function hasRetainedActiveRawGraphic() {
|
|
2095
|
+
let output = graphicsOutput();
|
|
2096
|
+
return !!(status.value === "loading" && !graphic.value && output && typeof output.isActive == "function" && output.isActive(rawId));
|
|
2097
|
+
}
|
|
2098
|
+
let showingInitialLoadingText = (0, import_vue8.computed)(
|
|
2099
|
+
() => status.value === "loading" && !graphic.value && !hasRetainedActiveRawGraphic()
|
|
2100
|
+
), fullRect = (0, import_vue8.computed)(() => {
|
|
2101
|
+
let current = graphic.value, reserved = reservedTerminalGraphicSize.value, reservedRows = current?.type === "terminal" ? void 0 : status.value === "idle" && reserved?.key === stableGraphicKey.value ? reserved.rows : void 0, textLines = current?.type === "text" ? splitTextOutput(current.text) : splitTextOutput(fallbackText()), height = props.h ?? (current?.type === "terminal" ? current.rows : void 0) ?? reservedRows ?? Math.max(1, textLines.length);
|
|
2102
|
+
return translateRect(
|
|
2103
|
+
{ x: props.x, y: props.y, w: props.w, h: height },
|
|
2104
|
+
layout.originX,
|
|
2105
|
+
layout.originY
|
|
2106
|
+
);
|
|
2107
|
+
}), absRect = (0, import_vue8.computed)(() => {
|
|
2108
|
+
terminalSizeVersion.value;
|
|
2109
|
+
let translated = fullRect.value, size = terminal.size(), terminalClip = {
|
|
2110
|
+
x: 0,
|
|
2111
|
+
y: 0,
|
|
2112
|
+
w: Math.max(0, Math.floor(size.cols)),
|
|
2113
|
+
h: Math.max(0, Math.floor(size.rows))
|
|
2114
|
+
}, clip = layout.clipRect ? intersectRect(layout.clipRect, terminalClip) : terminalClip;
|
|
2115
|
+
return clip ? intersectRect(translated, clip) ?? { x: 0, y: 0, w: 0, h: 0 } : { x: 0, y: 0, w: 0, h: 0 };
|
|
2116
|
+
}), renderRect = (0, import_vue8.computed)(() => absRect.value);
|
|
2117
|
+
function rawRectFitsTerminalViewport(rect) {
|
|
2118
|
+
return canDrawTerminalGraphicRect(rect, terminal.size());
|
|
2119
|
+
}
|
|
2120
|
+
function rawCoveredByHigherRenderNode(rect = fullRect.value) {
|
|
2121
|
+
if (props.retainRawWhileCovered)
|
|
2122
|
+
return !1;
|
|
2123
|
+
let id = renderNodeId.value;
|
|
2124
|
+
return !props.ignoreRawCoverage && id != null && render.isRectCoveredByHigherNode(id, rect, {
|
|
2125
|
+
ignoreSamePlane: props.ignoreSamePlaneRawCoverage
|
|
2126
|
+
});
|
|
2127
|
+
}
|
|
2128
|
+
function retainedRawCoveredByHigherRenderNode(rect) {
|
|
2129
|
+
if (!props.retainRawWhileCovered)
|
|
2130
|
+
return !1;
|
|
2131
|
+
let id = renderNodeId.value;
|
|
2132
|
+
return !!(id != null && render.isRectCoveredByHigherNode(id, rect, {
|
|
2133
|
+
ignoreSamePlane: props.ignoreSamePlaneRawCoverage
|
|
2134
|
+
}));
|
|
2135
|
+
}
|
|
2136
|
+
function rawUncoveredRenderRect(rect) {
|
|
2137
|
+
if (props.retainRawWhileCovered)
|
|
2138
|
+
return rect;
|
|
2139
|
+
let id = renderNodeId.value;
|
|
2140
|
+
if (id == null)
|
|
2141
|
+
return rect;
|
|
2142
|
+
let covers = render.higherNodeCoverageRects(id, rect, {
|
|
2143
|
+
ignoreSamePlane: props.ignoreSamePlaneRawCoverage
|
|
2144
|
+
});
|
|
2145
|
+
return covers.length ? props.ignoreRawCoverage ? largestUncoveredRect(rect, covers) : null : rect;
|
|
2146
|
+
}
|
|
2147
|
+
let rawCanRender = (0, import_vue8.computed)(() => {
|
|
2148
|
+
graphicsOutputVersion.value, terminalSizeVersion.value;
|
|
2149
|
+
let current = graphic.value, output = graphicsOutput(), rect = absRect.value;
|
|
2150
|
+
return current?.type === "terminal" && rawRectFitsTerminalViewport(rect) && !!output?.capabilities.supported && output?.capabilities.preferredProtocol === current.protocol;
|
|
2151
|
+
}), rawOutputCanRenderValue = (0, import_vue8.computed)(() => (graphicsOutputVersion.value, terminalSizeVersion.value, rawOutputCanRender())), rawSuppressedByScroll = (0, import_vue8.computed)(
|
|
2152
|
+
() => props.suspended || props.suspendRawWhileScrolling && isParentScrolling.value
|
|
2153
|
+
), rawCanQueue = (0, import_vue8.computed)(() => rawCanRender.value && !rawSuppressedByScroll.value);
|
|
2154
|
+
function traceRawSkipScrollOnce(reason) {
|
|
2155
|
+
let r = absRect.value, key = [
|
|
2156
|
+
reason,
|
|
2157
|
+
graphicsActivityVersion.value,
|
|
2158
|
+
stableGraphicKey.value,
|
|
2159
|
+
r.x,
|
|
2160
|
+
r.y,
|
|
2161
|
+
r.w,
|
|
2162
|
+
r.h
|
|
2163
|
+
].join(":");
|
|
2164
|
+
lastRawSkipScrollKey !== key && (lastRawSkipScrollKey = key, trace("raw-skip-scroll", { reason }));
|
|
2165
|
+
}
|
|
2166
|
+
function hasPaintableRect() {
|
|
2167
|
+
let r = absRect.value;
|
|
2168
|
+
return visible.value && r.w > 0 && r.h > 0;
|
|
2169
|
+
}
|
|
2170
|
+
function rawOutputCanRender() {
|
|
2171
|
+
let output = graphicsOutput(), rect = absRect.value;
|
|
2172
|
+
return rawRectFitsTerminalViewport(rect) && !!output?.capabilities.supported;
|
|
2173
|
+
}
|
|
2174
|
+
function renderDeferReason() {
|
|
2175
|
+
return props.suspended ? "suspended" : props.deferRenderUntilVisible && !hasPaintableRect() ? "not-visible" : props.suspendRenderWhileScrolling && isParentScrolling.value ? "scrolling" : null;
|
|
2176
|
+
}
|
|
2177
|
+
function shouldDeferRender() {
|
|
2178
|
+
return renderDeferReason() != null;
|
|
2179
|
+
}
|
|
2180
|
+
function shouldRerenderForGraphicsOutputChange() {
|
|
2181
|
+
if (!props.renderer || !props.content.trim() || shouldDeferRender() || rawSuppressedByScroll.value)
|
|
2182
|
+
return !1;
|
|
2183
|
+
let protocol = currentCapabilities().protocol;
|
|
2184
|
+
return lastRenderProtocol != null && (lastRenderProtocol !== protocol || lastRenderGraphicsOutputVersion !== graphicsOutputVersion.value);
|
|
2185
|
+
}
|
|
2186
|
+
function shouldRetryTemporaryRawFallback(rawCovered = rawCoveredByHigherRenderNode()) {
|
|
2187
|
+
return !!props.renderer && props.content.trim().length > 0 && graphic.value?.type === "text" && status.value !== "loading" && !lastRenderRawVisible && rawOutputCanRenderValue.value && !rawSuppressedByScroll.value && !rawCovered;
|
|
2188
|
+
}
|
|
2189
|
+
function setDeferredFallback(content) {
|
|
2190
|
+
graphic.value = { type: "text", text: content.trim() ? fallbackText() : "" }, lastRenderedContent = content, status.value = "idle", error.value = "", bump();
|
|
2191
|
+
}
|
|
2192
|
+
function resolveRendererContext(signal) {
|
|
2193
|
+
let capabilities = currentCapabilities(), visibleNow = hasPaintableRect(), rawVisible = rawOutputCanRenderValue.value && !rawSuppressedByScroll.value && !rawCoveredByHigherRenderNode();
|
|
2194
|
+
return {
|
|
2195
|
+
kind: props.kind,
|
|
2196
|
+
width: props.w,
|
|
2197
|
+
height: props.h,
|
|
2198
|
+
final: props.final,
|
|
2199
|
+
streaming: props.streaming,
|
|
2200
|
+
protocol: capabilities.protocol,
|
|
2201
|
+
capabilities,
|
|
2202
|
+
signal,
|
|
2203
|
+
imageId: imageId.value,
|
|
2204
|
+
placementId: placementId.value,
|
|
2205
|
+
visible: visibleNow,
|
|
2206
|
+
rawVisible,
|
|
2207
|
+
scrolling: isParentScrolling.value,
|
|
2208
|
+
cacheKey: props.cacheKey,
|
|
2209
|
+
viewport: {
|
|
2210
|
+
visible: visibleNow,
|
|
2211
|
+
rawVisible,
|
|
2212
|
+
scrolling: isParentScrolling.value,
|
|
2213
|
+
rect: absRect.value,
|
|
2214
|
+
fullRect: fullRect.value
|
|
2215
|
+
}
|
|
2216
|
+
};
|
|
2217
|
+
}
|
|
2218
|
+
async function renderNow(version) {
|
|
2219
|
+
let protocol = currentCapabilities().protocol;
|
|
2220
|
+
recordTerminalGraphicTrace({
|
|
2221
|
+
type: "request",
|
|
2222
|
+
id: rawId,
|
|
2223
|
+
key: props.cacheKey ?? smallHash(props.content),
|
|
2224
|
+
protocol: isTerminalGraphicsProtocol(protocol) ? protocol : void 0
|
|
2225
|
+
});
|
|
2226
|
+
let content = props.content;
|
|
2227
|
+
if (!content.trim()) {
|
|
2228
|
+
if (abortCurrentRender("superseded"), !alive || version !== renderVersion)
|
|
2229
|
+
return;
|
|
2230
|
+
graphic.value = { type: "text", text: "" }, lastRenderedContent = content, status.value = "ready", error.value = "", bump();
|
|
2231
|
+
return;
|
|
2232
|
+
}
|
|
2233
|
+
let renderer = props.renderer;
|
|
2234
|
+
if (!renderer) {
|
|
2235
|
+
if (abortCurrentRender("superseded"), !alive || version !== renderVersion)
|
|
2236
|
+
return;
|
|
2237
|
+
graphic.value = { type: "text", text: fallbackText() }, lastRenderedContent = content, status.value = "ready", error.value = "", bump();
|
|
2238
|
+
return;
|
|
2239
|
+
}
|
|
2240
|
+
let deferred = renderDeferReason();
|
|
2241
|
+
if (deferred) {
|
|
2242
|
+
if (abortCurrentRender(deferred), !alive || version !== renderVersion)
|
|
2243
|
+
return;
|
|
2244
|
+
setDeferredFallback(content), traceDeferOnce(deferred);
|
|
2245
|
+
return;
|
|
2246
|
+
}
|
|
2247
|
+
abortCurrentRender("superseded"), lastDeferTraceKey = "";
|
|
2248
|
+
let abort = new AbortController();
|
|
2249
|
+
renderAbort = abort;
|
|
2250
|
+
let startedAt = nowTerminalGraphicTraceTime();
|
|
2251
|
+
status.value = "loading", error.value = "", trace("render-start"), bump();
|
|
2252
|
+
try {
|
|
2253
|
+
let contextGraphicsOutputVersion = graphicsOutputVersion.value, context = resolveRendererContext(abort.signal);
|
|
2254
|
+
lastRenderRawVisible = context.rawVisible, lastRenderProtocol = context.protocol, lastRenderGraphicsOutputVersion = contextGraphicsOutputVersion;
|
|
2255
|
+
let result = await renderer(content, context);
|
|
2256
|
+
if (abort.signal.aborted || !alive || version !== renderVersion)
|
|
2257
|
+
return;
|
|
2258
|
+
let normalized = normalizeResult(result);
|
|
2259
|
+
rememberTerminalGraphicSize(normalized), graphic.value = normalized, lastRenderedContent = content, status.value = "ready", error.value = "", trace("render-end", {
|
|
2260
|
+
durationMs: nowTerminalGraphicTraceTime() - startedAt,
|
|
2261
|
+
sequenceChars: normalized.type === "terminal" ? normalized.sequence.length : 0,
|
|
2262
|
+
sequenceBytes: normalized.type === "terminal" ? normalized.sequenceBytes : 0
|
|
2263
|
+
}), bump(), normalized.type === "terminal" && scheduler.invalidate({ priority: "low", reason: "data" });
|
|
2264
|
+
} catch (err) {
|
|
2265
|
+
if (abort.signal.aborted || !alive || version !== renderVersion)
|
|
2266
|
+
return;
|
|
2267
|
+
graphic.value = { type: "text", text: fallbackText() }, lastRenderedContent = content, status.value = "ready", error.value = errorMessage(err), trace("render-end", {
|
|
2268
|
+
durationMs: nowTerminalGraphicTraceTime() - startedAt,
|
|
2269
|
+
reason: error.value
|
|
2270
|
+
}), bump();
|
|
2271
|
+
} finally {
|
|
2272
|
+
renderAbort === abort && (renderAbort = null);
|
|
2273
|
+
}
|
|
2274
|
+
}
|
|
2275
|
+
function scheduleRender(options = {}) {
|
|
2276
|
+
let version = ++renderVersion;
|
|
2277
|
+
if ((options.clearLastGraphic ?? !props.preserveRawWhileRendering) && queueClearLastGraphic(), !builtOnce || !props.streaming) {
|
|
2278
|
+
builtOnce = !0, renderNow(version);
|
|
2279
|
+
return;
|
|
2280
|
+
}
|
|
2281
|
+
scheduler.queueFrameTask({
|
|
2282
|
+
id: frameTaskId,
|
|
2283
|
+
reason: "stream",
|
|
2284
|
+
priority: "low",
|
|
2285
|
+
sync: !1,
|
|
2286
|
+
run: () => {
|
|
2287
|
+
alive && version === renderVersion && renderNow(version);
|
|
2288
|
+
}
|
|
2289
|
+
}) === !1 && renderNow(version);
|
|
2290
|
+
}
|
|
2291
|
+
(0, import_vue8.watch)(
|
|
2292
|
+
[
|
|
2293
|
+
() => props.content,
|
|
2294
|
+
() => props.kind,
|
|
2295
|
+
() => props.renderer,
|
|
2296
|
+
() => props.w,
|
|
2297
|
+
() => props.h,
|
|
2298
|
+
() => props.streaming,
|
|
2299
|
+
() => props.final,
|
|
2300
|
+
() => props.deferRenderUntilVisible,
|
|
2301
|
+
() => props.suspendRawWhileScrolling,
|
|
2302
|
+
() => props.suspendRenderWhileScrolling,
|
|
2303
|
+
() => props.scrolling,
|
|
2304
|
+
() => props.preserveRawWhileRendering,
|
|
2305
|
+
() => props.suspended,
|
|
2306
|
+
() => props.retainRawWhileCovered,
|
|
2307
|
+
() => props.ignoreRawCoverage,
|
|
2308
|
+
() => props.ignoreSamePlaneRawCoverage,
|
|
2309
|
+
() => props.cacheKey,
|
|
2310
|
+
() => props.placementKey
|
|
2311
|
+
],
|
|
2312
|
+
() => {
|
|
2313
|
+
scheduleRender();
|
|
2314
|
+
},
|
|
2315
|
+
{ immediate: !0 }
|
|
2316
|
+
), (0, import_vue8.watch)(
|
|
2317
|
+
() => props.fallback,
|
|
2318
|
+
() => {
|
|
2319
|
+
let current = graphic.value;
|
|
2320
|
+
if (current?.type === "terminal") {
|
|
2321
|
+
if (current.fallbackFromProps) {
|
|
2322
|
+
graphic.value = { ...current, fallback: fallbackText() }, bump(), scheduler.invalidate({ priority: "low", reason: "data" });
|
|
2323
|
+
return;
|
|
2324
|
+
}
|
|
2325
|
+
scheduleRender({ clearLastGraphic: !1 });
|
|
2326
|
+
return;
|
|
2327
|
+
}
|
|
2328
|
+
scheduleRender();
|
|
2329
|
+
}
|
|
2330
|
+
), (0, import_vue8.watch)(
|
|
2331
|
+
() => [graphicsOutputVersion.value, rawOutputCanRenderValue.value],
|
|
2332
|
+
() => {
|
|
2333
|
+
!props.renderer || !props.content.trim() || graphic.value?.type !== "terminal" && (!rawOutputCanRenderValue.value || shouldDeferRender() || scheduleRender({ clearLastGraphic: !1 }));
|
|
2334
|
+
}
|
|
2335
|
+
), (0, import_vue8.watch)(
|
|
2336
|
+
() => [props.x, props.y, props.w, props.h, props.scrollVersion],
|
|
2337
|
+
() => {
|
|
2338
|
+
if (graphic.value?.type === "terminal") {
|
|
2339
|
+
scheduler.invalidate({ priority: "low", reason: "data" });
|
|
2340
|
+
return;
|
|
2341
|
+
}
|
|
2342
|
+
props.kind !== "image" || status.value !== "loading" || !props.renderer || scheduleRender({ clearLastGraphic: !1 });
|
|
2343
|
+
},
|
|
2344
|
+
{ flush: "sync" }
|
|
2345
|
+
), (0, import_vue8.onBeforeUnmount)(() => {
|
|
2346
|
+
alive = !1, renderVersion++, unsubscribeTerminalResize(), unsubscribeGraphicsOutput(), abortCurrentRender("unmount"), scheduler.cancelFrameTask?.(frameTaskId), queueClearLastGraphic();
|
|
2347
|
+
});
|
|
2348
|
+
function resolveDisplayLines(rawPlaceholderAllowed) {
|
|
2349
|
+
if (showingInitialLoadingText.value)
|
|
2350
|
+
return splitTextOutput(props.loadingText);
|
|
2351
|
+
let current = graphic.value;
|
|
2352
|
+
if (!current)
|
|
2353
|
+
return splitTextOutput(fallbackText());
|
|
2354
|
+
if (current.type === "terminal" && rawPlaceholderAllowed) {
|
|
2355
|
+
let clearSequence = resolveClearSequence(current), drawKey = terminalDrawKey(
|
|
2356
|
+
current,
|
|
2357
|
+
absRect.value,
|
|
2358
|
+
clearSequence,
|
|
2359
|
+
resolveResizeSequence(current, absRect.value, fullRect.value)
|
|
2360
|
+
);
|
|
2361
|
+
if (rawDrawRejectedKey.value !== drawKey)
|
|
2362
|
+
return (0, import_vue8.markRaw)([""]);
|
|
2363
|
+
}
|
|
2364
|
+
let text = current.type === "terminal" ? current.fallback : current.text, lines = splitTextOutput(text);
|
|
2365
|
+
return text.trim().length > 0 && !hasVisibleOutput(lines) ? splitTextOutput(fallbackText()) : lines;
|
|
2366
|
+
}
|
|
2367
|
+
let displayLines = (0, import_vue8.computed)(() => resolveDisplayLines(rawCanQueue.value)), currentStyle = (0, import_vue8.computed)(() => error.value ? props.errorStyle ?? props.style ?? defaultStyle.value : showingInitialLoadingText.value ? props.loadingStyle ?? props.style ?? defaultStyle.value : props.style ?? defaultStyle.value), renderNode = useRenderNode(() => ({
|
|
2368
|
+
zIndex: props.zIndex,
|
|
2369
|
+
rect: visible.value ? renderRect.value : { x: 0, y: 0, w: 0, h: 0 },
|
|
2370
|
+
deps: [
|
|
2371
|
+
visible.value,
|
|
2372
|
+
renderRect.value,
|
|
2373
|
+
fullRect.value,
|
|
2374
|
+
displayLines.value,
|
|
2375
|
+
currentStyle.value,
|
|
2376
|
+
props.clear,
|
|
2377
|
+
status.value,
|
|
2378
|
+
error.value,
|
|
2379
|
+
documentVersion.value,
|
|
2380
|
+
rawOutputCanRenderValue.value,
|
|
2381
|
+
rawCanRender.value,
|
|
2382
|
+
rawCanQueue.value,
|
|
2383
|
+
rawClearPendingRepaint.value,
|
|
2384
|
+
rawDrawRejectedKey.value,
|
|
2385
|
+
rawSuppressedByScroll.value,
|
|
2386
|
+
props.placementMoveWithoutClear,
|
|
2387
|
+
props.retainRawWhileCovered,
|
|
2388
|
+
isParentScrolling.value,
|
|
2389
|
+
graphicsActivityVersion.value,
|
|
2390
|
+
graphicsOutputVersion.value
|
|
2391
|
+
],
|
|
2392
|
+
paint: (dirtyRows) => {
|
|
2393
|
+
withTextWidthProvider(widthProvider, () => {
|
|
2394
|
+
if (!visible.value) {
|
|
2395
|
+
queueClearLastGraphic();
|
|
2396
|
+
return;
|
|
2397
|
+
}
|
|
2398
|
+
let r = absRect.value, full = fullRect.value;
|
|
2399
|
+
if (r.w <= 0 || r.h <= 0) {
|
|
2400
|
+
queueClearLastGraphic();
|
|
2401
|
+
return;
|
|
2402
|
+
}
|
|
2403
|
+
let style = currentStyle.value, dx = Math.max(0, Math.floor(r.x - full.x)), fullY = Math.floor(full.y), current = graphic.value, output = graphicsOutput(), retainedActiveRawGraphic = hasRetainedActiveRawGraphic(), rawRectForPaint = rawUncoveredRenderRect(r), rawCoverageClipped = rawRectForPaint != null && props.ignoreRawCoverage && !sameRect(rawRectForPaint, r), rawCoveredForPaint = rawRectForPaint == null && rawCoveredByHigherRenderNode(r), rawCanQueueForPaint = current?.type === "terminal" && rawCanQueue.value && rawRectForPaint != null, preserveActiveRawGraphic = !1, forceActiveRawRedraw = !1, allowTextOverlay = !1;
|
|
2404
|
+
if (rawCanQueueForPaint && output) {
|
|
2405
|
+
let previous = lastDrawnGraphic.value;
|
|
2406
|
+
if ((previous ? typeof output.isActive == "function" ? output.isActive(previous.id) : !0 : !1) && previous) {
|
|
2407
|
+
let clearSequence = resolveClearSequence(current), resizeSequence = resolveResizeSequence(current, rawRectForPaint, full);
|
|
2408
|
+
preserveActiveRawGraphic = rawClearPendingRepaint.value == null && previous.drawKey === terminalDrawKey(current, rawRectForPaint, clearSequence, resizeSequence), allowTextOverlay = retainedRawCoveredByHigherRenderNode(r), forceActiveRawRedraw = preserveActiveRawGraphic && (previous.activityVersion !== graphicsActivityVersion.value || previous.allowTextOverlay !== allowTextOverlay);
|
|
2409
|
+
}
|
|
2410
|
+
}
|
|
2411
|
+
let preserveActiveRawGraphicForPaint = preserveActiveRawGraphic, out = rawCanQueueForPaint ? displayLines.value : resolveDisplayLines(!1), clearingRawGraphic = rawClearPendingRepaint.value != null || lastDrawnGraphic.value != null && !preserveActiveRawGraphicForPaint, clearOwnedRegion = preserveActiveRawGraphicForPaint || retainedActiveRawGraphic ? !1 : props.clear || clearingRawGraphic || !!rawCanQueueForPaint, blank = clearOwnedRegion ? spaces(r.w) : "", paintRow = (y) => {
|
|
2412
|
+
if (y < r.y || y >= r.y + r.h)
|
|
2413
|
+
return;
|
|
2414
|
+
let rowIndex = y - fullY;
|
|
2415
|
+
if (rowIndex < 0 || rowIndex >= out.length) {
|
|
2416
|
+
clearOwnedRegion && terminal.write(blank, { x: r.x, y, style });
|
|
2417
|
+
return;
|
|
2418
|
+
}
|
|
2419
|
+
let src = out[rowIndex] ?? "", clipped = dx > 0 ? sliceByCellsRange(src, dx, dx + r.w) : sliceByCells(src, r.w), value = clearOwnedRegion ? padEndByCells(clipped, r.w) : clipped;
|
|
2420
|
+
(value || clearOwnedRegion) && terminal.write(value, { x: r.x, y, style });
|
|
2421
|
+
}, paintRows = () => {
|
|
2422
|
+
if (dirtyRows?.length)
|
|
2423
|
+
for (let y of dirtyRows)
|
|
2424
|
+
paintRow(y);
|
|
2425
|
+
else
|
|
2426
|
+
for (let y = r.y; y < r.y + r.h; y++)
|
|
2427
|
+
paintRow(y);
|
|
2428
|
+
};
|
|
2429
|
+
if (paintRows(), current?.type === "terminal" && output?.capabilities.supported && output.capabilities.preferredProtocol === current.protocol && rawCanQueueForPaint) {
|
|
2430
|
+
let drawKey = terminalDrawKey(
|
|
2431
|
+
current,
|
|
2432
|
+
rawRectForPaint,
|
|
2433
|
+
resolveClearSequence(current),
|
|
2434
|
+
resolveResizeSequence(current, rawRectForPaint, full)
|
|
2435
|
+
);
|
|
2436
|
+
queueDrawGraphic(output, current, rawRectForPaint, full, {
|
|
2437
|
+
force: forceActiveRawRedraw,
|
|
2438
|
+
deferFlush: preserveActiveRawGraphicForPaint,
|
|
2439
|
+
placementMoveWithoutClear: props.placementMoveWithoutClear || rawCoverageClipped,
|
|
2440
|
+
allowTextOverlay
|
|
2441
|
+
}) ? trace("raw-draw", {
|
|
2442
|
+
sequenceChars: current.sequence.length,
|
|
2443
|
+
sequenceBytes: current.sequenceBytes,
|
|
2444
|
+
x: rawRectForPaint.x,
|
|
2445
|
+
y: rawRectForPaint.y,
|
|
2446
|
+
w: rawRectForPaint.w,
|
|
2447
|
+
h: rawRectForPaint.h
|
|
2448
|
+
}) : rawDrawRejectedKey.value === drawKey && (out = resolveDisplayLines(!1), paintRows());
|
|
2449
|
+
} else
|
|
2450
|
+
current?.type === "terminal" && rawSuppressedByScroll.value && traceRawSkipScrollOnce(isParentScrolling.value ? "scrolling" : "suspended"), queueClearLastGraphic({ markPendingRepaint: !1 }), !shouldDeferRender() && shouldRetryTemporaryRawFallback(rawCoveredForPaint) && scheduleRender({ clearLastGraphic: !1 });
|
|
2451
|
+
clearingRawGraphic && (rawClearPendingRepaint.value = null);
|
|
2452
|
+
});
|
|
2453
|
+
}
|
|
2454
|
+
}));
|
|
2455
|
+
return (0, import_vue8.watch)(
|
|
2456
|
+
renderNode.id,
|
|
2457
|
+
(id) => {
|
|
2458
|
+
renderNodeId.value = id;
|
|
2459
|
+
},
|
|
2460
|
+
{ immediate: !0 }
|
|
2461
|
+
), (0, import_vue8.watch)(
|
|
2462
|
+
[
|
|
2463
|
+
visible,
|
|
2464
|
+
rawOutputCanRenderValue,
|
|
2465
|
+
rawCanRender,
|
|
2466
|
+
rawCanQueue,
|
|
2467
|
+
rawSuppressedByScroll,
|
|
2468
|
+
isParentScrolling,
|
|
2469
|
+
graphicsActivityVersion,
|
|
2470
|
+
graphicsOutputVersion,
|
|
2471
|
+
() => renderRect.value.x,
|
|
2472
|
+
() => renderRect.value.y,
|
|
2473
|
+
() => renderRect.value.w,
|
|
2474
|
+
() => renderRect.value.h,
|
|
2475
|
+
() => fullRect.value.x,
|
|
2476
|
+
() => fullRect.value.y,
|
|
2477
|
+
() => fullRect.value.w,
|
|
2478
|
+
() => fullRect.value.h
|
|
2479
|
+
],
|
|
2480
|
+
() => {
|
|
2481
|
+
if (!alive)
|
|
2482
|
+
return;
|
|
2483
|
+
let deferred = renderDeferReason();
|
|
2484
|
+
deferred && (abortCurrentRender(deferred), (status.value === "loading" || !graphic.value || lastRenderedContent !== props.content) && setDeferredFallback(props.content), traceDeferOnce(deferred)), (!visible.value || !rawCanQueue.value) && queueClearLastGraphic();
|
|
2485
|
+
let shouldRetryTemporaryFallback = shouldRetryTemporaryRawFallback(), shouldRerenderForOutputChange = shouldRerenderForGraphicsOutputChange();
|
|
2486
|
+
if (!shouldDeferRender() && (!graphic.value || status.value === "idle" || shouldRetryTemporaryFallback || shouldRerenderForOutputChange)) {
|
|
2487
|
+
scheduleRender();
|
|
2488
|
+
return;
|
|
2489
|
+
}
|
|
2490
|
+
scheduler.invalidate({ priority: "low", reason: "data" });
|
|
2491
|
+
},
|
|
2492
|
+
{ flush: "post" }
|
|
2493
|
+
), () => (0, import_vue8.h)("span", rootProps);
|
|
2494
|
+
}
|
|
2495
|
+
});
|
|
2496
|
+
|
|
2497
|
+
// src/vue/components/TText.ts
|
|
2498
|
+
var import_vue9 = require("vue");
|
|
2499
|
+
function fitText(text, max) {
|
|
2500
|
+
return max <= 0 ? "" : (text = sanitizeInlineText(text), sliceByCells(text, max));
|
|
2501
|
+
}
|
|
2502
|
+
function splitLines(text) {
|
|
2503
|
+
return sanitizeTextBlock(text).split(`
|
|
2504
|
+
`);
|
|
2505
|
+
}
|
|
2506
|
+
function computeDefaultWidth(text) {
|
|
2507
|
+
let lines = splitLines(text), max = 0;
|
|
2508
|
+
for (let line of lines)
|
|
2509
|
+
max = Math.max(max, textCellWidth(line));
|
|
2510
|
+
return max;
|
|
2511
|
+
}
|
|
2512
|
+
var TText = (0, import_vue9.defineComponent)({
|
|
2513
|
+
name: "TText",
|
|
2514
|
+
props: {
|
|
2515
|
+
x: { type: Number, required: !0 },
|
|
2516
|
+
y: { type: Number, required: !0 },
|
|
2517
|
+
zIndex: { type: Number, default: 0 },
|
|
2518
|
+
value: { type: String, required: !0 },
|
|
2519
|
+
w: { type: Number, default: void 0 },
|
|
2520
|
+
h: { type: Number, default: void 0 },
|
|
2521
|
+
style: { type: Object, default: void 0 },
|
|
2522
|
+
clear: { type: Boolean, default: !0 },
|
|
2523
|
+
wrap: { type: Boolean, default: !1 },
|
|
2524
|
+
/**
|
|
2525
|
+
* Optional key that participates in render-node dependency tracking.
|
|
2526
|
+
* Useful for forcing a repaint when the rendered output might change
|
|
2527
|
+
* even if `value`, `style`, and geometry are unchanged (e.g. external
|
|
2528
|
+
* terminal writes or higher-level virtualized row reuse).
|
|
2529
|
+
*/
|
|
2530
|
+
depsKey: { type: null, default: void 0 }
|
|
2531
|
+
},
|
|
2532
|
+
setup(props) {
|
|
2533
|
+
let { terminal, defaultStyle } = useTerminal(), layout = useLayout(), { visible, rootProps } = useVisibility(), defaultWidth = (0, import_vue9.computed)(() => computeDefaultWidth(props.value)), lines = (0, import_vue9.computed)(() => {
|
|
2534
|
+
let w = props.w ?? defaultWidth.value;
|
|
2535
|
+
if (w <= 0)
|
|
2536
|
+
return [""];
|
|
2537
|
+
if (!props.wrap)
|
|
2538
|
+
return splitLines(props.value).map((l) => fitText(l, w));
|
|
2539
|
+
let safe = sanitizeTextBlock(props.value);
|
|
2540
|
+
return wrapByCells(safe, w).map((l) => fitText(l, w));
|
|
2541
|
+
}), absRect = (0, import_vue9.computed)(() => {
|
|
2542
|
+
let width = props.w ?? defaultWidth.value, height = props.h ?? (props.wrap, lines.value.length || 1), raw = { x: props.x, y: props.y, w: width, h: height }, translated = translateRect(raw, layout.originX, layout.originY);
|
|
2543
|
+
return layout.clipRect ? intersectRect(translated, layout.clipRect) ?? { x: 0, y: 0, w: 0, h: 0 } : translated;
|
|
2544
|
+
}), fullRect = (0, import_vue9.computed)(() => {
|
|
2545
|
+
let width = props.w ?? defaultWidth.value, height = props.h ?? (props.wrap, lines.value.length || 1);
|
|
2546
|
+
return translateRect(
|
|
2547
|
+
{ x: props.x, y: props.y, w: width, h: height },
|
|
2548
|
+
layout.originX,
|
|
2549
|
+
layout.originY
|
|
2550
|
+
);
|
|
2551
|
+
});
|
|
2552
|
+
return useRenderNode(() => ({
|
|
2553
|
+
zIndex: props.zIndex,
|
|
2554
|
+
rect: visible.value ? absRect.value : { x: 0, y: 0, w: 0, h: 0 },
|
|
2555
|
+
deps: [
|
|
2556
|
+
visible.value,
|
|
2557
|
+
absRect.value,
|
|
2558
|
+
fullRect.value,
|
|
2559
|
+
props.value,
|
|
2560
|
+
props.w,
|
|
2561
|
+
props.h,
|
|
2562
|
+
props.wrap,
|
|
2563
|
+
props.style,
|
|
2564
|
+
defaultStyle.value,
|
|
2565
|
+
props.depsKey
|
|
2566
|
+
],
|
|
2567
|
+
paint: (dirtyRows) => {
|
|
2568
|
+
if (!visible.value)
|
|
2569
|
+
return;
|
|
2570
|
+
let r = absRect.value;
|
|
2571
|
+
if (r.w <= 0 || r.h <= 0)
|
|
2572
|
+
return;
|
|
2573
|
+
let full = fullRect.value, style = props.style ?? defaultStyle.value, blank = props.clear ? spaces(r.w) : "", out = lines.value, dx = Math.max(0, Math.floor(r.x - full.x)), fullY = Math.floor(full.y), paintRow = (y) => {
|
|
2574
|
+
let relY = y - r.y;
|
|
2575
|
+
if (relY < 0 || relY >= r.h)
|
|
2576
|
+
return;
|
|
2577
|
+
let i = y - fullY;
|
|
2578
|
+
if (i < 0 || i >= out.length) {
|
|
2579
|
+
props.clear && terminal.write(blank, { x: r.x, y, style });
|
|
2580
|
+
return;
|
|
2581
|
+
}
|
|
2582
|
+
let src = out[i] ?? "", clipped = dx > 0 ? sliceByCellsRange(src, dx, dx + r.w) : sliceByCells(src, r.w);
|
|
2583
|
+
terminal.write(padEndByCells(clipped, r.w), { x: r.x, y, style });
|
|
2584
|
+
};
|
|
2585
|
+
if (!dirtyRows) {
|
|
2586
|
+
for (let i = 0; i < r.h; i++)
|
|
2587
|
+
paintRow(r.y + i);
|
|
2588
|
+
return;
|
|
2589
|
+
}
|
|
2590
|
+
for (let y of dirtyRows)
|
|
2591
|
+
paintRow(y);
|
|
2592
|
+
}
|
|
2593
|
+
})), () => (0, import_vue9.h)("span", rootProps);
|
|
2594
|
+
}
|
|
2595
|
+
});
|
|
2596
|
+
|
|
2597
|
+
// src/vue/components/TView.ts
|
|
2598
|
+
var import_vue10 = require("vue");
|
|
2599
|
+
var EMPTY_RECT = Object.freeze({ x: 0, y: 0, w: 0, h: 0 }), TView = (0, import_vue10.defineComponent)({
|
|
2600
|
+
name: "TView",
|
|
2601
|
+
props: {
|
|
2602
|
+
x: { type: Number, required: !0 },
|
|
2603
|
+
y: { type: Number, required: !0 },
|
|
2604
|
+
w: { type: Number, required: !0 },
|
|
2605
|
+
h: { type: Number, required: !0 },
|
|
2606
|
+
zIndex: { type: Number, default: 0 },
|
|
2607
|
+
scrollX: { type: Number, default: 0 },
|
|
2608
|
+
scrollY: { type: Number, default: 0 },
|
|
2609
|
+
focusable: { type: Boolean, default: !1 },
|
|
2610
|
+
selectable: { type: Boolean, default: void 0 },
|
|
2611
|
+
selectionScrollBy: {
|
|
2612
|
+
type: Function,
|
|
2613
|
+
default: void 0
|
|
2614
|
+
},
|
|
2615
|
+
autoFocus: { type: Boolean, default: !1 }
|
|
2616
|
+
},
|
|
2617
|
+
emits: [
|
|
2618
|
+
"clickCapture",
|
|
2619
|
+
"click",
|
|
2620
|
+
"dblclickCapture",
|
|
2621
|
+
"dblclick",
|
|
2622
|
+
"pointerdownCapture",
|
|
2623
|
+
"pointerdown",
|
|
2624
|
+
"pointerupCapture",
|
|
2625
|
+
"pointerup",
|
|
2626
|
+
"pointermoveCapture",
|
|
2627
|
+
"pointermove",
|
|
2628
|
+
"pointerenterCapture",
|
|
2629
|
+
"pointerenter",
|
|
2630
|
+
"pointerleaveCapture",
|
|
2631
|
+
"pointerleave",
|
|
2632
|
+
"wheelCapture",
|
|
2633
|
+
"wheel",
|
|
2634
|
+
"keydownCapture",
|
|
2635
|
+
"keydown",
|
|
2636
|
+
"keyupCapture",
|
|
2637
|
+
"keyup",
|
|
2638
|
+
"focusCapture",
|
|
2639
|
+
"focus",
|
|
2640
|
+
"blurCapture",
|
|
2641
|
+
"blur"
|
|
2642
|
+
],
|
|
2643
|
+
setup(props, { emit, slots }) {
|
|
2644
|
+
let parent = useLayout(), { render, events } = useTerminal(), parentStack = useRenderStack(), { visible, rootProps } = useVisibility({ provide: !0 }), parentEventZ = (0, import_vue10.inject)(EventZIndexContextKey, (0, import_vue10.computed)(() => 0)), eventZ = (0, import_vue10.computed)(() => (parentEventZ.value ?? 0) + (props.zIndex ?? 0)), rawRect = (0, import_vue10.computed)(
|
|
2645
|
+
() => translateRect(
|
|
2646
|
+
{ x: props.x, y: props.y, w: props.w, h: props.h },
|
|
2647
|
+
parent.originX,
|
|
2648
|
+
parent.originY
|
|
2649
|
+
)
|
|
2650
|
+
), rect = (0, import_vue10.computed)(() => {
|
|
2651
|
+
let translated = rawRect.value;
|
|
2652
|
+
return parent.clipRect ? intersectRect(translated, parent.clipRect) ?? EMPTY_RECT : translated;
|
|
2653
|
+
}), { id } = useTerminalNode(() => ({
|
|
2654
|
+
rect: rect.value,
|
|
2655
|
+
zIndex: eventZ.value,
|
|
2656
|
+
visible: visible.value,
|
|
2657
|
+
focusable: props.focusable,
|
|
2658
|
+
selectable: props.selectable,
|
|
2659
|
+
selectionScrollBy: props.selectionScrollBy,
|
|
2660
|
+
handlers: {
|
|
2661
|
+
clickCapture: (e) => emit("clickCapture", e),
|
|
2662
|
+
click: (e) => emit("click", e),
|
|
2663
|
+
dblclickCapture: (e) => emit("dblclickCapture", e),
|
|
2664
|
+
dblclick: (e) => emit("dblclick", e),
|
|
2665
|
+
pointerdownCapture: (e) => emit("pointerdownCapture", e),
|
|
2666
|
+
pointerdown: (e) => emit("pointerdown", e),
|
|
2667
|
+
pointerupCapture: (e) => emit("pointerupCapture", e),
|
|
2668
|
+
pointerup: (e) => emit("pointerup", e),
|
|
2669
|
+
pointermoveCapture: (e) => emit("pointermoveCapture", e),
|
|
2670
|
+
pointermove: (e) => emit("pointermove", e),
|
|
2671
|
+
pointerenterCapture: (e) => emit("pointerenterCapture", e),
|
|
2672
|
+
pointerenter: (e) => emit("pointerenter", e),
|
|
2673
|
+
pointerleaveCapture: (e) => emit("pointerleaveCapture", e),
|
|
2674
|
+
pointerleave: (e) => emit("pointerleave", e),
|
|
2675
|
+
wheelCapture: (e) => emit("wheelCapture", e),
|
|
2676
|
+
wheel: (e) => emit("wheel", e),
|
|
2677
|
+
keydownCapture: (e) => emit("keydownCapture", e),
|
|
2678
|
+
keydown: (e) => emit("keydown", e),
|
|
2679
|
+
keyupCapture: (e) => emit("keyupCapture", e),
|
|
2680
|
+
keyup: (e) => emit("keyup", e),
|
|
2681
|
+
focusCapture: (e) => emit("focusCapture", e),
|
|
2682
|
+
focus: (e) => emit("focus", e),
|
|
2683
|
+
blurCapture: (e) => emit("blurCapture", e),
|
|
2684
|
+
blur: (e) => emit("blur", e)
|
|
2685
|
+
}
|
|
2686
|
+
}));
|
|
2687
|
+
(0, import_vue10.watchEffect)(() => {
|
|
2688
|
+
if (!props.autoFocus || !visible.value)
|
|
2689
|
+
return;
|
|
2690
|
+
let manager = events.value, nodeId = id.value;
|
|
2691
|
+
!manager || !nodeId || manager.getFocused() !== nodeId && manager.focus(nodeId);
|
|
2692
|
+
});
|
|
2693
|
+
let childLayout = (0, import_vue10.shallowReactive)({
|
|
2694
|
+
originX: 0,
|
|
2695
|
+
originY: 0,
|
|
2696
|
+
clipRect: null
|
|
2697
|
+
}), childStack = (0, import_vue10.computed)(() => render.createStack(parentStack.value, props.zIndex));
|
|
2698
|
+
return (0, import_vue10.watchEffect)(() => {
|
|
2699
|
+
let translated = rawRect.value;
|
|
2700
|
+
childLayout.originX = translated.x - Math.floor(props.scrollX), childLayout.originY = translated.y - Math.floor(props.scrollY), childLayout.clipRect = rect.value;
|
|
2701
|
+
}), (0, import_vue10.provide)(LayoutContextKey, childLayout), (0, import_vue10.provide)(RenderStackKey, childStack), (0, import_vue10.provide)(EventZIndexContextKey, eventZ), () => (0, import_vue10.h)("div", rootProps, slots.default?.());
|
|
2702
|
+
}
|
|
2703
|
+
});
|
|
2704
|
+
|
|
2705
|
+
// src/vue/components/TVideo.ts
|
|
2706
|
+
var DEFAULT_MAX_FPS = 12, DEFAULT_MAX_PIXEL_WIDTH = 640, DEFAULT_MAX_PIXEL_HEIGHT = 360, MAX_PIXEL_DIMENSION = 4096, MAX_FRAME_BYTES = 8 * 1024 * 1024, MAX_GRAY8_FPS = 10, MAX_GRAY8_WIDTH = 512, MAX_GRAY8_HEIGHT = 256, ASCII_RAMP = " .:-=+*#%@", CONTROL_REFRESH_MS = 250, PLAYBACK_RATES = [1, 2, 3];
|
|
2707
|
+
function positiveInt2(value, fallback, max) {
|
|
2708
|
+
let parsed = Math.floor(Number(value));
|
|
2709
|
+
return !Number.isFinite(parsed) || parsed <= 0 ? Math.min(max, fallback) : Math.min(max, parsed);
|
|
2710
|
+
}
|
|
2711
|
+
function positiveNumber(value, fallback, max) {
|
|
2712
|
+
let parsed = Number(value);
|
|
2713
|
+
return !Number.isFinite(parsed) || parsed <= 0 ? fallback : Math.min(max, parsed);
|
|
2714
|
+
}
|
|
2715
|
+
function playbackRate(value) {
|
|
2716
|
+
return value === 2 || value === 3 ? value : 1;
|
|
2717
|
+
}
|
|
2718
|
+
function optionalDuration(value) {
|
|
2719
|
+
let parsed = Number(value);
|
|
2720
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : void 0;
|
|
2721
|
+
}
|
|
2722
|
+
function formatPlaybackTime(valueMs, hourDigits = 0) {
|
|
2723
|
+
if (valueMs == null)
|
|
2724
|
+
return "--:--";
|
|
2725
|
+
let seconds = Math.max(0, Math.floor(valueMs / 1e3)), hours = Math.floor(seconds / 3600), minutes = Math.floor(seconds % 3600 / 60), remainder = seconds % 60;
|
|
2726
|
+
return hours > 0 || hourDigits > 0 ? `${String(hours).padStart(Math.max(1, hourDigits), "0")}:${String(minutes).padStart(2, "0")}:${String(remainder).padStart(2, "0")}` : `${String(minutes).padStart(2, "0")}:${String(remainder).padStart(2, "0")}`;
|
|
2727
|
+
}
|
|
2728
|
+
function readUint32(bytes, offset) {
|
|
2729
|
+
return bytes[offset] * 16777216 + (bytes[offset + 1] << 16) + (bytes[offset + 2] << 8) + bytes[offset + 3] >>> 0;
|
|
2730
|
+
}
|
|
2731
|
+
function normalizeFrame(frame) {
|
|
2732
|
+
if (frame.format === "gray8") {
|
|
2733
|
+
let pixelWidth2 = Math.floor(Number(frame.pixelWidth)), pixelHeight2 = Math.floor(Number(frame.pixelHeight)), pixels = frame.pixels;
|
|
2734
|
+
if (!Number.isFinite(pixelWidth2) || !Number.isFinite(pixelHeight2) || pixelWidth2 <= 0 || pixelHeight2 <= 0 || pixelWidth2 > MAX_GRAY8_WIDTH || pixelHeight2 > MAX_GRAY8_HEIGHT || !(pixels instanceof Uint8Array) || pixels.length !== pixelWidth2 * pixelHeight2 || pixels.length > MAX_FRAME_BYTES)
|
|
2735
|
+
throw new Error("TVideo gray8 frame must match its bounded pixel dimensions");
|
|
2736
|
+
return {
|
|
2737
|
+
format: "gray8",
|
|
2738
|
+
pixels,
|
|
2739
|
+
timestampMs: Math.max(0, Number(frame.timestampMs) || 0),
|
|
2740
|
+
pixelWidth: pixelWidth2,
|
|
2741
|
+
pixelHeight: pixelHeight2,
|
|
2742
|
+
fingerprint: frame.fingerprint,
|
|
2743
|
+
durationMs: optionalDuration(frame.durationMs)
|
|
2744
|
+
};
|
|
2745
|
+
}
|
|
2746
|
+
let png = frame.png;
|
|
2747
|
+
if (!(png instanceof Uint8Array) || png.length < 24 || png.length > MAX_FRAME_BYTES)
|
|
2748
|
+
throw new Error("TVideo frame must contain a bounded PNG Uint8Array");
|
|
2749
|
+
if (png[0] !== 137 || png[1] !== 80 || png[2] !== 78 || png[3] !== 71 || png[4] !== 13 || png[5] !== 10 || png[6] !== 26 || png[7] !== 10)
|
|
2750
|
+
throw new Error("TVideo frame source emitted invalid PNG data");
|
|
2751
|
+
let pixelWidth = readUint32(png, 16), pixelHeight = readUint32(png, 20);
|
|
2752
|
+
if (pixelWidth <= 0 || pixelHeight <= 0 || pixelWidth > MAX_PIXEL_DIMENSION || pixelHeight > MAX_PIXEL_DIMENSION)
|
|
2753
|
+
throw new Error(`TVideo frame has an unsupported size: ${pixelWidth}x${pixelHeight}`);
|
|
2754
|
+
return {
|
|
2755
|
+
format: "png",
|
|
2756
|
+
png,
|
|
2757
|
+
timestampMs: Math.max(0, Number(frame.timestampMs) || 0),
|
|
2758
|
+
pixelWidth,
|
|
2759
|
+
pixelHeight,
|
|
2760
|
+
fingerprint: frame.fingerprint,
|
|
2761
|
+
durationMs: optionalDuration(frame.durationMs)
|
|
2762
|
+
};
|
|
2763
|
+
}
|
|
2764
|
+
function frameBytes(frame) {
|
|
2765
|
+
return frame.format === "gray8" ? frame.pixels : frame.png;
|
|
2766
|
+
}
|
|
2767
|
+
function gray8ToAscii(frame, cellWidth) {
|
|
2768
|
+
let lines = [], width = Math.max(1, Math.floor(cellWidth));
|
|
2769
|
+
for (let y = 0; y < frame.pixelHeight; y++) {
|
|
2770
|
+
let line = "", rowStart = y * frame.pixelWidth;
|
|
2771
|
+
for (let x = 0; x < frame.pixelWidth; x++) {
|
|
2772
|
+
let value = frame.pixels[rowStart + x], glyph = ASCII_RAMP[Math.min(ASCII_RAMP.length - 1, value * ASCII_RAMP.length >> 8)];
|
|
2773
|
+
line += `${glyph}${glyph}`;
|
|
2774
|
+
}
|
|
2775
|
+
lines.push(line.slice(0, width));
|
|
2776
|
+
}
|
|
2777
|
+
return lines.join(`
|
|
2778
|
+
`);
|
|
2779
|
+
}
|
|
2780
|
+
function sameBytes(left, right) {
|
|
2781
|
+
if (left.length !== right.length)
|
|
2782
|
+
return !1;
|
|
2783
|
+
for (let index = 0; index < left.length; index++)
|
|
2784
|
+
if (left[index] !== right[index])
|
|
2785
|
+
return !1;
|
|
2786
|
+
return !0;
|
|
2787
|
+
}
|
|
2788
|
+
function bytesToBase64(bytes) {
|
|
2789
|
+
let alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", chunks = [], chunk = "";
|
|
2790
|
+
for (let index = 0; index < bytes.length; index += 3) {
|
|
2791
|
+
let a = bytes[index], hasB = index + 1 < bytes.length, hasC = index + 2 < bytes.length, b = hasB ? bytes[index + 1] : 0, c = hasC ? bytes[index + 2] : 0;
|
|
2792
|
+
chunk += alphabet[a >> 2] + alphabet[(a & 3) << 4 | b >> 4] + (hasB ? alphabet[(b & 15) << 2 | c >> 6] : "=") + (hasC ? alphabet[c & 63] : "="), chunk.length >= 16384 && (chunks.push(chunk), chunk = "");
|
|
2793
|
+
}
|
|
2794
|
+
return chunk && chunks.push(chunk), chunks.join("");
|
|
2795
|
+
}
|
|
2796
|
+
function createFrameRenderer(frame, cellWidth) {
|
|
2797
|
+
if (frame.format === "gray8") {
|
|
2798
|
+
let text = gray8ToAscii(frame, cellWidth);
|
|
2799
|
+
return () => ({ type: "text", text });
|
|
2800
|
+
}
|
|
2801
|
+
let base64;
|
|
2802
|
+
return (_content, context) => {
|
|
2803
|
+
if (!context.visible || !context.rawVisible)
|
|
2804
|
+
return null;
|
|
2805
|
+
base64 ?? (base64 = bytesToBase64(frame.png));
|
|
2806
|
+
let protocol = context.protocol;
|
|
2807
|
+
return protocol !== "kitty" && protocol !== "iterm2" ? null : createTerminalGraphicPngSequence({
|
|
2808
|
+
protocol,
|
|
2809
|
+
base64,
|
|
2810
|
+
imageId: context.imageId,
|
|
2811
|
+
placementId: context.placementId,
|
|
2812
|
+
cols: context.width,
|
|
2813
|
+
rows: context.height,
|
|
2814
|
+
sourceWidth: frame.pixelWidth,
|
|
2815
|
+
sourceHeight: frame.pixelHeight,
|
|
2816
|
+
placementColumns: Math.max(1, Math.floor(context.viewport.rect.w)),
|
|
2817
|
+
placementRows: Math.max(1, Math.floor(context.viewport.rect.h)),
|
|
2818
|
+
rect: context.viewport.rect,
|
|
2819
|
+
fullRect: context.viewport.fullRect,
|
|
2820
|
+
freeImageData: !0
|
|
2821
|
+
});
|
|
2822
|
+
};
|
|
2823
|
+
}
|
|
2824
|
+
function errorMessage2(error) {
|
|
2825
|
+
return error instanceof Error ? error.message : String(error);
|
|
2826
|
+
}
|
|
2827
|
+
var tVideoProps = {
|
|
2828
|
+
x: { type: Number, required: !0 },
|
|
2829
|
+
y: { type: Number, required: !0 },
|
|
2830
|
+
w: { type: Number, required: !0 },
|
|
2831
|
+
h: { type: Number, required: !0 },
|
|
2832
|
+
zIndex: { type: Number, default: 0 },
|
|
2833
|
+
src: { type: String, required: !0 },
|
|
2834
|
+
frameSource: {
|
|
2835
|
+
type: Function,
|
|
2836
|
+
required: !0
|
|
2837
|
+
},
|
|
2838
|
+
paused: { type: Boolean, default: void 0 },
|
|
2839
|
+
playbackRate: { type: Number, default: void 0 },
|
|
2840
|
+
controls: { type: Boolean, default: !1 },
|
|
2841
|
+
controlsLayout: {
|
|
2842
|
+
type: String,
|
|
2843
|
+
default: "compact"
|
|
2844
|
+
},
|
|
2845
|
+
durationMs: { type: Number, default: void 0 },
|
|
2846
|
+
loop: { type: Boolean, default: !1 },
|
|
2847
|
+
maxFps: { type: Number, default: DEFAULT_MAX_FPS },
|
|
2848
|
+
pixelWidth: { type: Number, default: void 0 },
|
|
2849
|
+
pixelHeight: { type: Number, default: void 0 },
|
|
2850
|
+
fallback: { type: String, default: "[video]" },
|
|
2851
|
+
style: { type: Object, default: void 0 },
|
|
2852
|
+
clear: { type: Boolean, default: !0 }
|
|
2853
|
+
}, TVideo = (0, import_vue11.defineComponent)({
|
|
2854
|
+
name: "TVideo",
|
|
2855
|
+
props: tVideoProps,
|
|
2856
|
+
emits: {
|
|
2857
|
+
frame: (_event) => !0,
|
|
2858
|
+
ended: () => !0,
|
|
2859
|
+
error: (_error) => !0,
|
|
2860
|
+
seek: (_event) => !0,
|
|
2861
|
+
"update:paused": (_paused) => !0,
|
|
2862
|
+
"update:playbackRate": (_rate) => !0
|
|
2863
|
+
},
|
|
2864
|
+
setup(props, { emit }) {
|
|
2865
|
+
let instance = (0, import_vue11.getCurrentInstance)(), { terminal, scheduler } = useTerminal(), layout = useLayout(), { visible, rootProps } = useVisibility({ provide: !0 }), graphicsActivity = (0, import_vue11.inject)(TerminalGraphicsActivityKey, null), frameRenderer = (0, import_vue11.shallowRef)(), playbackError = (0, import_vue11.shallowRef)(""), internalPaused = (0, import_vue11.shallowRef)(props.paused ?? !1), internalPlaybackRate = (0, import_vue11.shallowRef)(playbackRate(props.playbackRate)), discoveredDurationMs = (0, import_vue11.shallowRef)(), displayedTimestampMs = (0, import_vue11.shallowRef)(0), seekPreviewMs = (0, import_vue11.shallowRef)(), seeking = (0, import_vue11.shallowRef)(!1), terminalSizeVersion = (0, import_vue11.shallowRef)(0), graphicsOutputVersion = (0, import_vue11.shallowRef)(getTerminalGraphicsOutputVersion(terminal)), placementKey = `TVideo:${instance?.uid ?? "unknown"}`, mailboxId = `${placementKey}:frame`, alive = !0, generation = 0, activeAbort = null, lastSourceBytes = null, lastQueuedBytes = null, lastQueuedFormat = null, lastQueuedFingerprint, lastTimestampMs = 0, droppedFrames = 0, pendingEndedGeneration = null, suppressNextVideoClick = !1, controlPointerCapture = null, unsubscribeTerminalResize = terminal.on("resize", () => {
|
|
2866
|
+
terminalSizeVersion.value++;
|
|
2867
|
+
}), unsubscribeGraphicsOutput = subscribeTerminalGraphicsOutput(terminal, () => {
|
|
2868
|
+
graphicsOutputVersion.value = getTerminalGraphicsOutputVersion(terminal);
|
|
2869
|
+
}), showControls = (0, import_vue11.computed)(
|
|
2870
|
+
() => props.controls && Math.floor(props.w) >= 14 && Math.floor(props.h) >= 2
|
|
2871
|
+
), resolvedControlsLayout = (0, import_vue11.computed)(
|
|
2872
|
+
() => props.controlsLayout === "cinema" && Math.floor(props.h) >= 3 ? "cinema" : "compact"
|
|
2873
|
+
), controlRows = (0, import_vue11.computed)(
|
|
2874
|
+
() => showControls.value ? resolvedControlsLayout.value === "cinema" ? 2 : 1 : 0
|
|
2875
|
+
), videoHeight = (0, import_vue11.computed)(() => Math.max(1, Math.floor(props.h) - controlRows.value)), resolvedMaxFps = (0, import_vue11.computed)(() => positiveNumber(props.maxFps, DEFAULT_MAX_FPS, 60)), resolvedPixelSize = (0, import_vue11.computed)(() => {
|
|
2876
|
+
let desiredWidth = Math.max(2, Math.floor(props.w) * 8), desiredHeight = Math.max(2, videoHeight.value * 16);
|
|
2877
|
+
if (props.pixelWidth == null && props.pixelHeight == null) {
|
|
2878
|
+
let scale = Math.min(
|
|
2879
|
+
1,
|
|
2880
|
+
DEFAULT_MAX_PIXEL_WIDTH / desiredWidth,
|
|
2881
|
+
DEFAULT_MAX_PIXEL_HEIGHT / desiredHeight
|
|
2882
|
+
);
|
|
2883
|
+
return {
|
|
2884
|
+
width: Math.max(2, Math.floor(desiredWidth * scale)),
|
|
2885
|
+
height: Math.max(2, Math.floor(desiredHeight * scale))
|
|
2886
|
+
};
|
|
2887
|
+
}
|
|
2888
|
+
if (props.pixelWidth != null && props.pixelHeight == null) {
|
|
2889
|
+
let width = positiveInt2(props.pixelWidth, desiredWidth, MAX_PIXEL_DIMENSION), inferredHeight = width * desiredHeight / desiredWidth, scale = Math.min(1, MAX_PIXEL_DIMENSION / inferredHeight);
|
|
2890
|
+
return {
|
|
2891
|
+
width: Math.max(2, Math.floor(width * scale)),
|
|
2892
|
+
height: Math.max(2, Math.floor(inferredHeight * scale))
|
|
2893
|
+
};
|
|
2894
|
+
}
|
|
2895
|
+
if (props.pixelWidth == null && props.pixelHeight != null) {
|
|
2896
|
+
let height = positiveInt2(props.pixelHeight, desiredHeight, MAX_PIXEL_DIMENSION), inferredWidth = height * desiredWidth / desiredHeight, scale = Math.min(1, MAX_PIXEL_DIMENSION / inferredWidth);
|
|
2897
|
+
return {
|
|
2898
|
+
width: Math.max(2, Math.floor(inferredWidth * scale)),
|
|
2899
|
+
height: Math.max(2, Math.floor(height * scale))
|
|
2900
|
+
};
|
|
2901
|
+
}
|
|
2902
|
+
return {
|
|
2903
|
+
width: positiveInt2(props.pixelWidth, desiredWidth, MAX_PIXEL_DIMENSION),
|
|
2904
|
+
height: positiveInt2(props.pixelHeight, desiredHeight, MAX_PIXEL_DIMENSION)
|
|
2905
|
+
};
|
|
2906
|
+
}), resolvedPixelWidth = (0, import_vue11.computed)(() => resolvedPixelSize.value.width), resolvedPixelHeight = (0, import_vue11.computed)(() => resolvedPixelSize.value.height), paintable = (0, import_vue11.computed)(() => {
|
|
2907
|
+
if (terminalSizeVersion.value, !visible.value)
|
|
2908
|
+
return !1;
|
|
2909
|
+
let size = terminal.size(), terminalRect = {
|
|
2910
|
+
x: 0,
|
|
2911
|
+
y: 0,
|
|
2912
|
+
w: Math.max(0, Math.floor(size.cols)),
|
|
2913
|
+
h: Math.max(0, Math.floor(size.rows))
|
|
2914
|
+
}, clip = layout.clipRect ? intersectRect(layout.clipRect, terminalRect) : terminalRect;
|
|
2915
|
+
if (!clip)
|
|
2916
|
+
return !1;
|
|
2917
|
+
let rect = translateRect(
|
|
2918
|
+
{ x: props.x, y: props.y, w: props.w, h: videoHeight.value },
|
|
2919
|
+
layout.originX,
|
|
2920
|
+
layout.originY
|
|
2921
|
+
), visibleRect = intersectRect(rect, clip);
|
|
2922
|
+
return !!(visibleRect && visibleRect.w > 0 && visibleRect.h > 0);
|
|
2923
|
+
}), graphicsProtocol = (0, import_vue11.computed)(() => (graphicsOutputVersion.value, getTerminalGraphicsOutput(terminal)?.capabilities.preferredProtocol ?? null)), preferredFormat = (0, import_vue11.computed)(
|
|
2924
|
+
() => graphicsProtocol.value === "kitty" || graphicsProtocol.value === "iterm2" ? "png" : "gray8"
|
|
2925
|
+
), resolvedDecodeFps = (0, import_vue11.computed)(
|
|
2926
|
+
() => preferredFormat.value === "gray8" ? Math.min(MAX_GRAY8_FPS, resolvedMaxFps.value) : resolvedMaxFps.value
|
|
2927
|
+
), resolvedDecodeWidth = (0, import_vue11.computed)(
|
|
2928
|
+
() => preferredFormat.value === "gray8" ? positiveInt2(Math.ceil(props.w / 2), 1, MAX_GRAY8_WIDTH) : resolvedPixelWidth.value
|
|
2929
|
+
), resolvedDecodeHeight = (0, import_vue11.computed)(
|
|
2930
|
+
() => preferredFormat.value === "gray8" ? positiveInt2(videoHeight.value, 1, MAX_GRAY8_HEIGHT) : resolvedPixelHeight.value
|
|
2931
|
+
), resolvedDurationMs = (0, import_vue11.computed)(
|
|
2932
|
+
() => optionalDuration(props.durationMs) ?? discoveredDurationMs.value
|
|
2933
|
+
), effectivePaused = (0, import_vue11.computed)(() => props.paused ?? internalPaused.value), effectivePlaybackRate = (0, import_vue11.computed)(
|
|
2934
|
+
() => props.playbackRate == null ? internalPlaybackRate.value : playbackRate(props.playbackRate)
|
|
2935
|
+
), controlTimestampMs = (0, import_vue11.computed)(() => seekPreviewMs.value ?? displayedTimestampMs.value), timeHourDigits = (0, import_vue11.computed)(() => {
|
|
2936
|
+
let duration = resolvedDurationMs.value;
|
|
2937
|
+
return !duration || duration < 36e5 ? 0 : String(Math.floor(duration / 36e5)).length;
|
|
2938
|
+
}), currentTimeText = (0, import_vue11.computed)(
|
|
2939
|
+
() => formatPlaybackTime(controlTimestampMs.value, timeHourDigits.value)
|
|
2940
|
+
), durationTimeText = (0, import_vue11.computed)(
|
|
2941
|
+
() => formatPlaybackTime(resolvedDurationMs.value, timeHourDigits.value)
|
|
2942
|
+
), controlLayout = (0, import_vue11.computed)(() => {
|
|
2943
|
+
let width = Math.max(1, Math.floor(props.w)), progressY = videoHeight.value, current = currentTimeText.value, duration = durationTimeText.value, timeWidth = Math.max(textCellWidth(current), textCellWidth(duration)), ratesWidth = 8;
|
|
2944
|
+
if (resolvedControlsLayout.value === "cinema") {
|
|
2945
|
+
let ratesX2 = Math.max(3, width - ratesWidth), timeText = `${current} / ${duration}`;
|
|
2946
|
+
return {
|
|
2947
|
+
width,
|
|
2948
|
+
kind: "cinema",
|
|
2949
|
+
progressX: 0,
|
|
2950
|
+
progressY,
|
|
2951
|
+
progressWidth: width,
|
|
2952
|
+
actionY: progressY + 1,
|
|
2953
|
+
ratesX: ratesX2,
|
|
2954
|
+
showAllRates: !0,
|
|
2955
|
+
showTimes: 3 + textCellWidth(timeText) < ratesX2,
|
|
2956
|
+
current,
|
|
2957
|
+
duration,
|
|
2958
|
+
timeText,
|
|
2959
|
+
timeWidth,
|
|
2960
|
+
currentX: 3,
|
|
2961
|
+
totalX: 0
|
|
2962
|
+
};
|
|
2963
|
+
}
|
|
2964
|
+
let ratesX = width - ratesWidth, progressX = timeWidth + 4, totalX = ratesX - timeWidth - 1, progressWidth = totalX - progressX - 1;
|
|
2965
|
+
if (progressWidth >= 4)
|
|
2966
|
+
return {
|
|
2967
|
+
width,
|
|
2968
|
+
kind: "compact",
|
|
2969
|
+
progressX,
|
|
2970
|
+
progressY,
|
|
2971
|
+
progressWidth,
|
|
2972
|
+
actionY: progressY,
|
|
2973
|
+
ratesX,
|
|
2974
|
+
showAllRates: !0,
|
|
2975
|
+
showTimes: !0,
|
|
2976
|
+
current,
|
|
2977
|
+
duration,
|
|
2978
|
+
timeText: "",
|
|
2979
|
+
timeWidth,
|
|
2980
|
+
currentX: 3,
|
|
2981
|
+
totalX
|
|
2982
|
+
};
|
|
2983
|
+
let compactRatesX = Math.max(4, width - 2);
|
|
2984
|
+
return {
|
|
2985
|
+
width,
|
|
2986
|
+
kind: "compact",
|
|
2987
|
+
progressX: 3,
|
|
2988
|
+
progressY,
|
|
2989
|
+
progressWidth: Math.max(1, compactRatesX - 4),
|
|
2990
|
+
actionY: progressY,
|
|
2991
|
+
ratesX: compactRatesX,
|
|
2992
|
+
showAllRates: !1,
|
|
2993
|
+
showTimes: !1,
|
|
2994
|
+
current,
|
|
2995
|
+
duration,
|
|
2996
|
+
timeText: "",
|
|
2997
|
+
timeWidth,
|
|
2998
|
+
currentX: 0,
|
|
2999
|
+
totalX: 0
|
|
3000
|
+
};
|
|
3001
|
+
}), rateStyles = (0, import_vue11.computed)(
|
|
3002
|
+
() => PLAYBACK_RATES.map(
|
|
3003
|
+
(rate) => rate === effectivePlaybackRate.value ? { ...props.style, inverse: !0 } : props.style
|
|
3004
|
+
)
|
|
3005
|
+
), remainingProgressStyle = (0, import_vue11.computed)(() => ({ ...props.style, dim: !0 })), progressThumbStyle = (0, import_vue11.computed)(() => ({ ...props.style, inverse: !0 })), progressSegments = (0, import_vue11.computed)(() => {
|
|
3006
|
+
let { progressWidth } = controlLayout.value, duration = resolvedDurationMs.value;
|
|
3007
|
+
if (!duration)
|
|
3008
|
+
return { playedWidth: 0, thumbWidth: 0, remainingWidth: progressWidth };
|
|
3009
|
+
let ratio = Math.max(0, Math.min(1, controlTimestampMs.value / duration)), marker = Math.round(ratio * Math.max(0, progressWidth - 1));
|
|
3010
|
+
return {
|
|
3011
|
+
playedWidth: marker,
|
|
3012
|
+
thumbWidth: 1,
|
|
3013
|
+
remainingWidth: progressWidth - marker - 1
|
|
3014
|
+
};
|
|
3015
|
+
}), controlFill = (0, import_vue11.computed)(() => " ".repeat(controlLayout.value.width)), progressGlyphs = (0, import_vue11.computed)(() => ({
|
|
3016
|
+
played: "\u2501".repeat(progressSegments.value.playedWidth),
|
|
3017
|
+
remaining: "\u2500".repeat(progressSegments.value.remainingWidth)
|
|
3018
|
+
})), playbackEnabled = (0, import_vue11.computed)(
|
|
3019
|
+
() => alive && !effectivePaused.value && !graphicsActivity?.scrolling.value && props.src.trim().length > 0 && paintable.value
|
|
3020
|
+
), shouldPlay = (0, import_vue11.computed)(() => playbackEnabled.value && !seeking.value), visibleFallback = (0, import_vue11.computed)(
|
|
3021
|
+
() => playbackError.value ? `${props.fallback}: ${playbackError.value}` : props.fallback
|
|
3022
|
+
);
|
|
3023
|
+
function timelineTimestamp(timestampMs) {
|
|
3024
|
+
let duration = resolvedDurationMs.value;
|
|
3025
|
+
return duration ? props.loop ? Math.max(0, timestampMs) % duration : Math.max(0, Math.min(duration, timestampMs)) : Math.max(0, timestampMs);
|
|
3026
|
+
}
|
|
3027
|
+
function seekTimestamp(timestampMs) {
|
|
3028
|
+
let duration = resolvedDurationMs.value;
|
|
3029
|
+
if (!duration)
|
|
3030
|
+
return Math.max(0, timestampMs);
|
|
3031
|
+
let end = props.loop ? Math.max(0, duration - 1) : duration;
|
|
3032
|
+
return Math.max(0, Math.min(end, timestampMs));
|
|
3033
|
+
}
|
|
3034
|
+
function updateTimestamp(timestampMs, force = !1) {
|
|
3035
|
+
let next = timelineTimestamp(timestampMs);
|
|
3036
|
+
if (lastTimestampMs = next, !showControls.value)
|
|
3037
|
+
return;
|
|
3038
|
+
let threshold = CONTROL_REFRESH_MS * effectivePlaybackRate.value;
|
|
3039
|
+
(force || next < displayedTimestampMs.value || Math.abs(next - displayedTimestampMs.value) >= threshold) && (displayedTimestampMs.value = next);
|
|
3040
|
+
}
|
|
3041
|
+
function commitFrame(frame, dropped) {
|
|
3042
|
+
if (!alive)
|
|
3043
|
+
return;
|
|
3044
|
+
droppedFrames += dropped, frameRenderer.value = (0, import_vue11.markRaw)(createFrameRenderer(frame, props.w)), updateTimestamp(frame.timestampMs);
|
|
3045
|
+
let durationMs = resolvedDurationMs.value;
|
|
3046
|
+
emit("frame", {
|
|
3047
|
+
timestampMs: frame.timestampMs,
|
|
3048
|
+
pixelWidth: frame.pixelWidth,
|
|
3049
|
+
pixelHeight: frame.pixelHeight,
|
|
3050
|
+
droppedFrames,
|
|
3051
|
+
...durationMs ? { durationMs } : {},
|
|
3052
|
+
playbackRate: effectivePlaybackRate.value
|
|
3053
|
+
});
|
|
3054
|
+
}
|
|
3055
|
+
let mailbox = createFrameMailbox({
|
|
3056
|
+
scheduler,
|
|
3057
|
+
id: mailboxId,
|
|
3058
|
+
reason: "stream",
|
|
3059
|
+
priority: "low",
|
|
3060
|
+
apply(frame, _context, meta) {
|
|
3061
|
+
commitFrame(frame, meta.dropped), pendingEndedGeneration === generation && (pendingEndedGeneration = null, emit("ended"));
|
|
3062
|
+
}
|
|
3063
|
+
});
|
|
3064
|
+
function stopPlayback() {
|
|
3065
|
+
generation++, pendingEndedGeneration = null;
|
|
3066
|
+
let discardedPendingFrame = mailbox.hasPending();
|
|
3067
|
+
mailbox.cancel(), discardedPendingFrame && (lastQueuedBytes = null, lastQueuedFormat = null, lastQueuedFingerprint = void 0), activeAbort?.abort(), activeAbort = null;
|
|
3068
|
+
}
|
|
3069
|
+
function resetQueuedFrameIdentity() {
|
|
3070
|
+
lastSourceBytes = null, lastQueuedBytes = null, lastQueuedFormat = null, lastQueuedFingerprint = void 0;
|
|
3071
|
+
}
|
|
3072
|
+
function setPaused(paused) {
|
|
3073
|
+
effectivePaused.value !== paused && (props.paused == null && (internalPaused.value = paused), emit("update:paused", paused));
|
|
3074
|
+
}
|
|
3075
|
+
function setPlaybackRate(rate) {
|
|
3076
|
+
let next = playbackRate(rate);
|
|
3077
|
+
effectivePlaybackRate.value !== next && (props.playbackRate == null && (internalPlaybackRate.value = next), emit("update:playbackRate", next));
|
|
3078
|
+
}
|
|
3079
|
+
function applySeek(timestampMs, restart) {
|
|
3080
|
+
let parsed = Number(timestampMs);
|
|
3081
|
+
if (!Number.isFinite(parsed))
|
|
3082
|
+
return;
|
|
3083
|
+
stopPlayback(), resetQueuedFrameIdentity();
|
|
3084
|
+
let next = seekTimestamp(parsed);
|
|
3085
|
+
updateTimestamp(next, !0), seekPreviewMs.value = void 0;
|
|
3086
|
+
let durationMs = resolvedDurationMs.value;
|
|
3087
|
+
emit("seek", {
|
|
3088
|
+
timestampMs: next,
|
|
3089
|
+
...durationMs ? { durationMs } : {}
|
|
3090
|
+
}), restart && startPlayback(effectivePaused.value);
|
|
3091
|
+
}
|
|
3092
|
+
function controlCell(event) {
|
|
3093
|
+
return {
|
|
3094
|
+
x: Math.floor(event.cellX - layout.originX - props.x),
|
|
3095
|
+
y: Math.floor(event.cellY - layout.originY - props.y)
|
|
3096
|
+
};
|
|
3097
|
+
}
|
|
3098
|
+
function previewSeekAt(cellX) {
|
|
3099
|
+
let duration = resolvedDurationMs.value;
|
|
3100
|
+
if (!duration)
|
|
3101
|
+
return;
|
|
3102
|
+
let { progressX, progressWidth } = controlLayout.value, offset = Math.max(0, Math.min(progressWidth - 1, cellX - progressX));
|
|
3103
|
+
seekPreviewMs.value = progressWidth <= 1 ? 0 : offset / Math.max(1, progressWidth - 1) * duration;
|
|
3104
|
+
}
|
|
3105
|
+
function captureControlPointer(event) {
|
|
3106
|
+
let native = event.nativeEvent, pointerId = native?.pointerId, target = native?.target;
|
|
3107
|
+
pointerId == null || !target?.setPointerCapture || (target.setPointerCapture(pointerId), controlPointerCapture = { pointerId, target });
|
|
3108
|
+
}
|
|
3109
|
+
function releaseControlPointer() {
|
|
3110
|
+
controlPointerCapture && (controlPointerCapture.target.releasePointerCapture?.(controlPointerCapture.pointerId), controlPointerCapture = null);
|
|
3111
|
+
}
|
|
3112
|
+
function rateAt(cellX) {
|
|
3113
|
+
let { ratesX, showAllRates } = controlLayout.value, offset = cellX - ratesX;
|
|
3114
|
+
if (!showAllRates) {
|
|
3115
|
+
if (offset < 0 || offset >= 2)
|
|
3116
|
+
return;
|
|
3117
|
+
let index = PLAYBACK_RATES.indexOf(effectivePlaybackRate.value);
|
|
3118
|
+
return PLAYBACK_RATES[(index + 1) % PLAYBACK_RATES.length];
|
|
3119
|
+
}
|
|
3120
|
+
if (!(offset < 0 || offset % 3 >= 2))
|
|
3121
|
+
return PLAYBACK_RATES[Math.floor(offset / 3)];
|
|
3122
|
+
}
|
|
3123
|
+
function onInteractivePointerDown(event) {
|
|
3124
|
+
if (event.button != null && event.button !== 0)
|
|
3125
|
+
return;
|
|
3126
|
+
let { x: cellX, y: cellY } = controlCell(event);
|
|
3127
|
+
if (cellY < videoHeight.value) {
|
|
3128
|
+
suppressNextVideoClick = !1;
|
|
3129
|
+
return;
|
|
3130
|
+
}
|
|
3131
|
+
if (!showControls.value)
|
|
3132
|
+
return;
|
|
3133
|
+
let { actionY, progressY, progressX, progressWidth } = controlLayout.value, rate = rateAt(cellX);
|
|
3134
|
+
if (cellY === actionY && cellX <= 1) {
|
|
3135
|
+
event.preventDefault(), event.stopPropagation(), suppressNextVideoClick = !0, setPaused(!effectivePaused.value);
|
|
3136
|
+
return;
|
|
3137
|
+
}
|
|
3138
|
+
if (cellY === actionY && rate) {
|
|
3139
|
+
event.preventDefault(), event.stopPropagation(), suppressNextVideoClick = !0, setPlaybackRate(rate);
|
|
3140
|
+
return;
|
|
3141
|
+
}
|
|
3142
|
+
cellY !== progressY || !resolvedDurationMs.value || cellX < progressX || cellX >= progressX + progressWidth || (event.preventDefault(), event.stopPropagation(), suppressNextVideoClick = !0, seeking.value = !0, stopPlayback(), previewSeekAt(cellX), captureControlPointer(event));
|
|
3143
|
+
}
|
|
3144
|
+
function onInteractivePointerMove(event) {
|
|
3145
|
+
if (seeking.value) {
|
|
3146
|
+
if (event.buttons === 0) {
|
|
3147
|
+
onInteractivePointerUp(event);
|
|
3148
|
+
return;
|
|
3149
|
+
}
|
|
3150
|
+
event.preventDefault(), event.stopPropagation(), previewSeekAt(controlCell(event).x);
|
|
3151
|
+
}
|
|
3152
|
+
}
|
|
3153
|
+
function onInteractivePointerUp(event) {
|
|
3154
|
+
if (!seeking.value)
|
|
3155
|
+
return;
|
|
3156
|
+
event.preventDefault(), event.stopPropagation(), previewSeekAt(controlCell(event).x);
|
|
3157
|
+
let timestampMs = seekPreviewMs.value ?? lastTimestampMs;
|
|
3158
|
+
applySeek(timestampMs, !1), seeking.value = !1, releaseControlPointer(), startPlayback(effectivePaused.value);
|
|
3159
|
+
}
|
|
3160
|
+
function onVideoClick(event) {
|
|
3161
|
+
if (!(event.button != null && event.button !== 0)) {
|
|
3162
|
+
if (suppressNextVideoClick) {
|
|
3163
|
+
suppressNextVideoClick = !1, event.preventDefault(), event.stopPropagation();
|
|
3164
|
+
return;
|
|
3165
|
+
}
|
|
3166
|
+
controlCell(event).y >= videoHeight.value || (event.preventDefault(), event.stopPropagation(), setPaused(!effectivePaused.value));
|
|
3167
|
+
}
|
|
3168
|
+
}
|
|
3169
|
+
function finishControlSeek() {
|
|
3170
|
+
if (!seeking.value)
|
|
3171
|
+
return;
|
|
3172
|
+
let timestampMs = seekPreviewMs.value ?? lastTimestampMs;
|
|
3173
|
+
applySeek(timestampMs, !1), seeking.value = !1, releaseControlPointer(), startPlayback(effectivePaused.value);
|
|
3174
|
+
}
|
|
3175
|
+
function onControlKeydown(event) {
|
|
3176
|
+
if (event.key === "Enter" || event.key === " " || event.key === "Spacebar") {
|
|
3177
|
+
event.preventDefault(), event.stopPropagation(), setPaused(!effectivePaused.value);
|
|
3178
|
+
return;
|
|
3179
|
+
}
|
|
3180
|
+
if (event.key === "ArrowUp" || event.key === "ArrowDown") {
|
|
3181
|
+
event.preventDefault(), event.stopPropagation();
|
|
3182
|
+
let index = PLAYBACK_RATES.indexOf(effectivePlaybackRate.value), offset = event.key === "ArrowUp" ? 1 : -1;
|
|
3183
|
+
setPlaybackRate(PLAYBACK_RATES[Math.max(0, Math.min(2, index + offset))]);
|
|
3184
|
+
return;
|
|
3185
|
+
}
|
|
3186
|
+
if (!event.repeat && (event.key === "Home" || event.key === "End") && resolvedDurationMs.value) {
|
|
3187
|
+
event.preventDefault(), event.stopPropagation(), applySeek(event.key === "Home" ? 0 : resolvedDurationMs.value, !0);
|
|
3188
|
+
return;
|
|
3189
|
+
}
|
|
3190
|
+
(event.key === "1" || event.key === "2" || event.key === "3") && (event.preventDefault(), event.stopPropagation(), setPlaybackRate(Number(event.key)));
|
|
3191
|
+
}
|
|
3192
|
+
function queueFrame(frame, expectedFormat) {
|
|
3193
|
+
let normalized = normalizeFrame(frame);
|
|
3194
|
+
if (normalized.format !== expectedFormat)
|
|
3195
|
+
throw new Error(`TVideo frame source did not provide requested ${expectedFormat} frames`);
|
|
3196
|
+
normalized.durationMs != null && normalized.durationMs !== discoveredDurationMs.value && (discoveredDurationMs.value = normalized.durationMs), normalized = { ...normalized, timestampMs: timelineTimestamp(normalized.timestampMs) };
|
|
3197
|
+
let sourceBytes = frameBytes(normalized), reusesSourceBuffer = sourceBytes === lastSourceBytes;
|
|
3198
|
+
lastSourceBytes = sourceBytes;
|
|
3199
|
+
let stableFrame = reusesSourceBuffer ? normalized.format === "gray8" ? { ...normalized, pixels: new Uint8Array(normalized.pixels) } : { ...normalized, png: new Uint8Array(normalized.png) } : normalized, bytes = frameBytes(stableFrame), sameFingerprint = normalized.format === lastQueuedFormat && normalized.fingerprint != null && lastQueuedFingerprint != null && normalized.fingerprint === lastQueuedFingerprint, canCompareBytes = normalized.fingerprint == null && lastQueuedFingerprint == null && !reusesSourceBuffer;
|
|
3200
|
+
if (sameFingerprint || canCompareBytes && normalized.format === lastQueuedFormat && lastQueuedBytes && sameBytes(lastQueuedBytes, sourceBytes)) {
|
|
3201
|
+
lastQueuedBytes = bytes, lastQueuedFormat = normalized.format, lastQueuedFingerprint = normalized.fingerprint, updateTimestamp(normalized.timestampMs), mailbox.hasPending() && mailbox.replacePending(stableFrame);
|
|
3202
|
+
return;
|
|
3203
|
+
}
|
|
3204
|
+
lastQueuedBytes = bytes, lastQueuedFormat = normalized.format, lastQueuedFingerprint = normalized.fingerprint, mailbox.queue(stableFrame) || (commitFrame(stableFrame, 0), scheduler.invalidate({ priority: "low", reason: "stream" }));
|
|
3205
|
+
}
|
|
3206
|
+
function startPlayback(oneFrame = !1) {
|
|
3207
|
+
if (stopPlayback(), !shouldPlay.value && !(oneFrame && alive && props.src.trim().length > 0 && paintable.value && !graphicsActivity?.scrolling.value))
|
|
3208
|
+
return;
|
|
3209
|
+
let currentGeneration = generation, abort = new AbortController();
|
|
3210
|
+
activeAbort = abort, playbackError.value = "";
|
|
3211
|
+
let source = props.frameSource, format = preferredFormat.value, context = {
|
|
3212
|
+
src: props.src,
|
|
3213
|
+
signal: abort.signal,
|
|
3214
|
+
maxFps: resolvedDecodeFps.value,
|
|
3215
|
+
pixelWidth: resolvedDecodeWidth.value,
|
|
3216
|
+
pixelHeight: resolvedDecodeHeight.value,
|
|
3217
|
+
startAtMs: lastTimestampMs,
|
|
3218
|
+
preferredFormat: format,
|
|
3219
|
+
playbackRate: effectivePlaybackRate.value,
|
|
3220
|
+
loop: props.loop
|
|
3221
|
+
};
|
|
3222
|
+
(async () => {
|
|
3223
|
+
try {
|
|
3224
|
+
let frames = await source(context);
|
|
3225
|
+
for await (let frame of frames)
|
|
3226
|
+
if (!alive || abort.signal.aborted || currentGeneration !== generation || (queueFrame(frame, format), oneFrame))
|
|
3227
|
+
return;
|
|
3228
|
+
if (!alive || abort.signal.aborted || currentGeneration !== generation)
|
|
3229
|
+
return;
|
|
3230
|
+
mailbox.hasPending() ? pendingEndedGeneration = currentGeneration : emit("ended");
|
|
3231
|
+
} catch (error) {
|
|
3232
|
+
if (!alive || abort.signal.aborted || currentGeneration !== generation)
|
|
3233
|
+
return;
|
|
3234
|
+
playbackError.value = errorMessage2(error), emit("error", error), scheduler.invalidate({ priority: "low", reason: "data" });
|
|
3235
|
+
} finally {
|
|
3236
|
+
activeAbort === abort && (activeAbort = null);
|
|
3237
|
+
}
|
|
3238
|
+
})();
|
|
3239
|
+
}
|
|
3240
|
+
return (0, import_vue11.watch)(
|
|
3241
|
+
() => props.paused,
|
|
3242
|
+
(paused) => {
|
|
3243
|
+
paused != null && (internalPaused.value = paused);
|
|
3244
|
+
}
|
|
3245
|
+
), (0, import_vue11.watch)(
|
|
3246
|
+
() => props.playbackRate,
|
|
3247
|
+
(rate) => {
|
|
3248
|
+
rate != null && (internalPlaybackRate.value = playbackRate(rate));
|
|
3249
|
+
}
|
|
3250
|
+
), (0, import_vue11.watch)(
|
|
3251
|
+
[
|
|
3252
|
+
() => props.src,
|
|
3253
|
+
() => props.frameSource,
|
|
3254
|
+
playbackEnabled,
|
|
3255
|
+
resolvedDecodeFps,
|
|
3256
|
+
resolvedDecodeWidth,
|
|
3257
|
+
resolvedDecodeHeight,
|
|
3258
|
+
preferredFormat,
|
|
3259
|
+
effectivePlaybackRate,
|
|
3260
|
+
() => props.loop
|
|
3261
|
+
],
|
|
3262
|
+
(next, previous) => {
|
|
3263
|
+
let sourceChanged = !previous || next[0] !== previous[0] || next[1] !== previous[1], formatChanged = !previous || next[6] !== previous[6];
|
|
3264
|
+
(sourceChanged || formatChanged) && (resetQueuedFrameIdentity(), sourceChanged && (lastTimestampMs = 0, displayedTimestampMs.value = 0, discoveredDurationMs.value = void 0, seekPreviewMs.value = void 0, seeking.value = !1, suppressNextVideoClick = !1, releaseControlPointer(), droppedFrames = 0), playbackError.value = "", frameRenderer.value = void 0), startPlayback();
|
|
3265
|
+
},
|
|
3266
|
+
{ immediate: !0, flush: "post" }
|
|
3267
|
+
), (0, import_vue11.onBeforeUnmount)(() => {
|
|
3268
|
+
alive = !1, stopPlayback(), releaseControlPointer(), mailbox.dispose(), unsubscribeTerminalResize(), unsubscribeGraphicsOutput();
|
|
3269
|
+
}), () => {
|
|
3270
|
+
let children = [
|
|
3271
|
+
(0, import_vue11.h)(TAgentTerminalGraphic, {
|
|
3272
|
+
x: props.x,
|
|
3273
|
+
y: props.y,
|
|
3274
|
+
w: props.w,
|
|
3275
|
+
h: videoHeight.value,
|
|
3276
|
+
zIndex: props.zIndex,
|
|
3277
|
+
content: props.src.trim() ? props.src : "video",
|
|
3278
|
+
fallback: visibleFallback.value,
|
|
3279
|
+
style: props.style,
|
|
3280
|
+
clear: props.clear,
|
|
3281
|
+
final: !1,
|
|
3282
|
+
streaming: !0,
|
|
3283
|
+
renderer: frameRenderer.value,
|
|
3284
|
+
placementKey,
|
|
3285
|
+
preserveRawWhileRendering: !0,
|
|
3286
|
+
ignoreSamePlaneRawCoverage: !0,
|
|
3287
|
+
suspended: !paintable.value
|
|
3288
|
+
})
|
|
3289
|
+
];
|
|
3290
|
+
return props.controls && children.push(
|
|
3291
|
+
(0, import_vue11.h)(
|
|
3292
|
+
TView,
|
|
3293
|
+
{
|
|
3294
|
+
x: props.x,
|
|
3295
|
+
y: props.y,
|
|
3296
|
+
w: Math.max(0, Math.floor(props.w)),
|
|
3297
|
+
h: Math.max(0, Math.floor(props.h)),
|
|
3298
|
+
zIndex: props.zIndex,
|
|
3299
|
+
focusable: !0,
|
|
3300
|
+
selectable: !1,
|
|
3301
|
+
onClick: onVideoClick,
|
|
3302
|
+
onPointerdown: onInteractivePointerDown,
|
|
3303
|
+
onPointermove: onInteractivePointerMove,
|
|
3304
|
+
onPointerup: onInteractivePointerUp,
|
|
3305
|
+
onKeydown: onControlKeydown,
|
|
3306
|
+
onBlur: finishControlSeek
|
|
3307
|
+
},
|
|
3308
|
+
() => {
|
|
3309
|
+
if (!showControls.value)
|
|
3310
|
+
return [];
|
|
3311
|
+
let layout2 = controlLayout.value, segments = progressSegments.value, controls = Array.from(
|
|
3312
|
+
{ length: controlRows.value },
|
|
3313
|
+
(_, index) => (0, import_vue11.h)(TText, {
|
|
3314
|
+
x: 0,
|
|
3315
|
+
y: videoHeight.value + index,
|
|
3316
|
+
w: layout2.width,
|
|
3317
|
+
value: controlFill.value,
|
|
3318
|
+
style: props.style
|
|
3319
|
+
})
|
|
3320
|
+
);
|
|
3321
|
+
return controls.push(
|
|
3322
|
+
(0, import_vue11.h)(TText, {
|
|
3323
|
+
x: 0,
|
|
3324
|
+
y: layout2.actionY,
|
|
3325
|
+
w: 2,
|
|
3326
|
+
value: effectivePaused.value ? "> " : "||",
|
|
3327
|
+
style: props.style
|
|
3328
|
+
})
|
|
3329
|
+
), layout2.showTimes && (layout2.kind === "cinema" ? controls.push(
|
|
3330
|
+
(0, import_vue11.h)(TText, {
|
|
3331
|
+
x: layout2.currentX,
|
|
3332
|
+
y: layout2.actionY,
|
|
3333
|
+
w: textCellWidth(layout2.timeText),
|
|
3334
|
+
value: layout2.timeText,
|
|
3335
|
+
style: props.style
|
|
3336
|
+
})
|
|
3337
|
+
) : controls.push(
|
|
3338
|
+
(0, import_vue11.h)(TText, {
|
|
3339
|
+
x: layout2.currentX,
|
|
3340
|
+
y: layout2.actionY,
|
|
3341
|
+
w: layout2.timeWidth,
|
|
3342
|
+
value: layout2.current,
|
|
3343
|
+
style: props.style
|
|
3344
|
+
}),
|
|
3345
|
+
(0, import_vue11.h)(TText, {
|
|
3346
|
+
x: layout2.totalX,
|
|
3347
|
+
y: layout2.actionY,
|
|
3348
|
+
w: layout2.timeWidth,
|
|
3349
|
+
value: layout2.duration,
|
|
3350
|
+
style: props.style
|
|
3351
|
+
})
|
|
3352
|
+
)), segments.playedWidth > 0 && controls.push(
|
|
3353
|
+
(0, import_vue11.h)(TText, {
|
|
3354
|
+
x: layout2.progressX,
|
|
3355
|
+
y: layout2.progressY,
|
|
3356
|
+
w: segments.playedWidth,
|
|
3357
|
+
value: progressGlyphs.value.played,
|
|
3358
|
+
style: props.style
|
|
3359
|
+
})
|
|
3360
|
+
), segments.thumbWidth > 0 && controls.push(
|
|
3361
|
+
(0, import_vue11.h)(TText, {
|
|
3362
|
+
x: layout2.progressX + segments.playedWidth,
|
|
3363
|
+
y: layout2.progressY,
|
|
3364
|
+
w: 1,
|
|
3365
|
+
value: "\u254B",
|
|
3366
|
+
style: progressThumbStyle.value
|
|
3367
|
+
})
|
|
3368
|
+
), segments.remainingWidth > 0 && controls.push(
|
|
3369
|
+
(0, import_vue11.h)(TText, {
|
|
3370
|
+
x: layout2.progressX + segments.playedWidth + segments.thumbWidth,
|
|
3371
|
+
y: layout2.progressY,
|
|
3372
|
+
w: segments.remainingWidth,
|
|
3373
|
+
value: progressGlyphs.value.remaining,
|
|
3374
|
+
style: remainingProgressStyle.value
|
|
3375
|
+
})
|
|
3376
|
+
), layout2.showAllRates ? controls.push(
|
|
3377
|
+
...PLAYBACK_RATES.map(
|
|
3378
|
+
(rate, index) => (0, import_vue11.h)(TText, {
|
|
3379
|
+
x: layout2.ratesX + index * 3,
|
|
3380
|
+
y: layout2.actionY,
|
|
3381
|
+
w: 2,
|
|
3382
|
+
value: `${rate}x`,
|
|
3383
|
+
style: rateStyles.value[index]
|
|
3384
|
+
})
|
|
3385
|
+
)
|
|
3386
|
+
) : controls.push(
|
|
3387
|
+
(0, import_vue11.h)(TText, {
|
|
3388
|
+
x: layout2.ratesX,
|
|
3389
|
+
y: layout2.actionY,
|
|
3390
|
+
w: 2,
|
|
3391
|
+
value: `${effectivePlaybackRate.value}x`,
|
|
3392
|
+
style: rateStyles.value[PLAYBACK_RATES.indexOf(effectivePlaybackRate.value)]
|
|
3393
|
+
})
|
|
3394
|
+
), controls;
|
|
3395
|
+
}
|
|
3396
|
+
)
|
|
3397
|
+
), (0, import_vue11.h)("span", rootProps, children);
|
|
3398
|
+
};
|
|
3399
|
+
}
|
|
3400
|
+
});
|
|
3401
|
+
|
|
3402
|
+
// src/vue/components/TBrowser.ts
|
|
3403
|
+
var EMPTY_RECT2 = Object.freeze({ x: 0, y: 0, w: 0, h: 0 }), tBrowserProps = {
|
|
3404
|
+
x: { type: Number, required: !0 },
|
|
3405
|
+
y: { type: Number, required: !0 },
|
|
3406
|
+
w: { type: Number, required: !0 },
|
|
3407
|
+
h: { type: Number, required: !0 },
|
|
3408
|
+
zIndex: { type: Number, default: 0 },
|
|
3409
|
+
url: { type: String, required: !0 },
|
|
3410
|
+
sessionFactory: {
|
|
3411
|
+
type: Function,
|
|
3412
|
+
required: !0
|
|
3413
|
+
},
|
|
3414
|
+
autoFocus: { type: Boolean, default: !1 },
|
|
3415
|
+
maxFps: { type: Number, default: 60 },
|
|
3416
|
+
pixelWidth: { type: Number, default: void 0 },
|
|
3417
|
+
pixelHeight: { type: Number, default: void 0 },
|
|
3418
|
+
fallback: { type: String, default: "[browser requires terminal graphics]" },
|
|
3419
|
+
style: { type: Object, default: void 0 },
|
|
3420
|
+
clear: { type: Boolean, default: !0 }
|
|
3421
|
+
};
|
|
3422
|
+
function modifiers(event) {
|
|
3423
|
+
return {
|
|
3424
|
+
ctrl: !!event.ctrlKey,
|
|
3425
|
+
shift: !!event.shiftKey,
|
|
3426
|
+
alt: !!event.altKey,
|
|
3427
|
+
meta: !!event.metaKey
|
|
3428
|
+
};
|
|
3429
|
+
}
|
|
3430
|
+
function eventText(event) {
|
|
3431
|
+
return String(event.text ?? event.data ?? "");
|
|
3432
|
+
}
|
|
3433
|
+
function isBrowserShortcut(event) {
|
|
3434
|
+
let key = event.key.toLowerCase();
|
|
3435
|
+
return (event.ctrlKey || event.metaKey) && ["l", "r", "t", "w"].includes(key) || !!event.altKey && (event.key === "ArrowLeft" || event.key === "ArrowRight") || !!event.ctrlKey && (key === "c" || key === "q");
|
|
3436
|
+
}
|
|
3437
|
+
var TBrowser = (0, import_vue12.defineComponent)({
|
|
3438
|
+
name: "TBrowser",
|
|
3439
|
+
props: tBrowserProps,
|
|
3440
|
+
emits: {
|
|
3441
|
+
ready: (_session) => !0,
|
|
3442
|
+
frame: (_event) => !0,
|
|
3443
|
+
navigate: (_url) => !0,
|
|
3444
|
+
titleChange: (_title) => !0,
|
|
3445
|
+
requestAddress: () => !0,
|
|
3446
|
+
close: () => !0,
|
|
3447
|
+
error: (_error) => !0
|
|
3448
|
+
},
|
|
3449
|
+
setup(props, { emit }) {
|
|
3450
|
+
let layout = useLayout(), { events } = useTerminal(), { visible } = useVisibility(), activeSession = null, activePixelWidth = Math.max(1, Math.floor(props.pixelWidth ?? props.w * 8)), activePixelHeight = Math.max(1, Math.floor(props.pixelHeight ?? props.h * 16)), alive = !0, skipNextInput = !1, requestedUrl = props.url, sessionQueue = Promise.resolve(), continuousInputScheduled = !1, continuousInputGeneration = 0, pendingContinuousInput = [], initialUrl = props.url, initialPixelWidth = Math.max(2, Math.floor(props.pixelWidth ?? props.w * 8)), initialPixelHeight = Math.max(2, Math.floor(props.pixelHeight ?? props.h * 16)), rawRect = (0, import_vue12.computed)(
|
|
3451
|
+
() => translateRect(
|
|
3452
|
+
{
|
|
3453
|
+
x: Math.floor(props.x),
|
|
3454
|
+
y: Math.floor(props.y),
|
|
3455
|
+
w: Math.max(0, Math.floor(props.w)),
|
|
3456
|
+
h: Math.max(0, Math.floor(props.h))
|
|
3457
|
+
},
|
|
3458
|
+
layout.originX,
|
|
3459
|
+
layout.originY
|
|
3460
|
+
)
|
|
3461
|
+
), rect = (0, import_vue12.computed)(() => {
|
|
3462
|
+
let value = rawRect.value;
|
|
3463
|
+
return layout.clipRect ? intersectRect(value, layout.clipRect) ?? EMPTY_RECT2 : value;
|
|
3464
|
+
}), frameSource = async function* (context) {
|
|
3465
|
+
activePixelWidth = context.pixelWidth, activePixelHeight = context.pixelHeight;
|
|
3466
|
+
let session = await props.sessionFactory({
|
|
3467
|
+
url: context.src,
|
|
3468
|
+
signal: context.signal,
|
|
3469
|
+
maxFps: context.maxFps,
|
|
3470
|
+
pixelWidth: context.pixelWidth,
|
|
3471
|
+
pixelHeight: context.pixelHeight,
|
|
3472
|
+
preferredFormat: context.preferredFormat,
|
|
3473
|
+
onNavigate: (url) => emit("navigate", url),
|
|
3474
|
+
onTitleChange: (title) => emit("titleChange", title)
|
|
3475
|
+
});
|
|
3476
|
+
if (context.signal.aborted || !alive) {
|
|
3477
|
+
await session.close();
|
|
3478
|
+
return;
|
|
3479
|
+
}
|
|
3480
|
+
clearContinuousInput(), sessionQueue = Promise.resolve(), activeSession = session;
|
|
3481
|
+
try {
|
|
3482
|
+
if (requestedUrl !== context.src && session.navigate && await session.navigate(requestedUrl), context.signal.aborted || !alive)
|
|
3483
|
+
return;
|
|
3484
|
+
emit("ready", session);
|
|
3485
|
+
for await (let frame of session.frames) {
|
|
3486
|
+
if (context.signal.aborted || !alive)
|
|
3487
|
+
return;
|
|
3488
|
+
yield frame;
|
|
3489
|
+
}
|
|
3490
|
+
} finally {
|
|
3491
|
+
activeSession === session && (activeSession = null, clearContinuousInput()), await session.close();
|
|
3492
|
+
}
|
|
3493
|
+
};
|
|
3494
|
+
function reportError(error) {
|
|
3495
|
+
alive && emit("error", error);
|
|
3496
|
+
}
|
|
3497
|
+
function clearContinuousInput() {
|
|
3498
|
+
pendingContinuousInput.length = 0, continuousInputGeneration++, continuousInputScheduled = !1;
|
|
3499
|
+
}
|
|
3500
|
+
function scheduleContinuousInput(session) {
|
|
3501
|
+
if (continuousInputScheduled || pendingContinuousInput.length === 0)
|
|
3502
|
+
return;
|
|
3503
|
+
let event = pendingContinuousInput.shift(), generation = continuousInputGeneration;
|
|
3504
|
+
continuousInputScheduled = !0;
|
|
3505
|
+
let pending = sessionQueue.then(() => {
|
|
3506
|
+
if (!(generation !== continuousInputGeneration || activeSession !== session))
|
|
3507
|
+
return session.dispatch(event);
|
|
3508
|
+
});
|
|
3509
|
+
sessionQueue = pending.catch((error) => {
|
|
3510
|
+
activeSession === session && reportError(error);
|
|
3511
|
+
});
|
|
3512
|
+
let finish = () => {
|
|
3513
|
+
generation === continuousInputGeneration && (continuousInputScheduled = !1, activeSession === session && scheduleContinuousInput(session));
|
|
3514
|
+
};
|
|
3515
|
+
pending.then(finish, finish);
|
|
3516
|
+
}
|
|
3517
|
+
function queueContinuousInput(session, event) {
|
|
3518
|
+
let index = pendingContinuousInput.findIndex((pending) => pending.type === event.type);
|
|
3519
|
+
if (index < 0)
|
|
3520
|
+
pendingContinuousInput.push(event);
|
|
3521
|
+
else if (event.type === "wheel") {
|
|
3522
|
+
let previous = pendingContinuousInput[index], deltaY = (previous?.type === "wheel" ? previous.deltaY : 0) + event.deltaY;
|
|
3523
|
+
deltaY === 0 ? pendingContinuousInput.splice(index, 1) : pendingContinuousInput[index] = { ...event, deltaY };
|
|
3524
|
+
} else
|
|
3525
|
+
pendingContinuousInput[index] = event;
|
|
3526
|
+
scheduleContinuousInput(session);
|
|
3527
|
+
}
|
|
3528
|
+
function dispatch(event) {
|
|
3529
|
+
let session = activeSession;
|
|
3530
|
+
if (!session)
|
|
3531
|
+
return;
|
|
3532
|
+
if (event.type === "wheel" || event.type === "pointermove") {
|
|
3533
|
+
queueContinuousInput(session, event);
|
|
3534
|
+
return;
|
|
3535
|
+
}
|
|
3536
|
+
clearContinuousInput(), sessionQueue = sessionQueue.then(() => {
|
|
3537
|
+
if (activeSession === session)
|
|
3538
|
+
return session.dispatch(event);
|
|
3539
|
+
}).catch((error) => {
|
|
3540
|
+
activeSession === session && reportError(error);
|
|
3541
|
+
});
|
|
3542
|
+
}
|
|
3543
|
+
function invoke(action) {
|
|
3544
|
+
let session = activeSession;
|
|
3545
|
+
if (!session)
|
|
3546
|
+
return;
|
|
3547
|
+
clearContinuousInput(), sessionQueue = sessionQueue.then(() => {
|
|
3548
|
+
if (activeSession === session)
|
|
3549
|
+
return action(session);
|
|
3550
|
+
}).catch((error) => {
|
|
3551
|
+
activeSession === session && reportError(error);
|
|
3552
|
+
});
|
|
3553
|
+
}
|
|
3554
|
+
function closeCurrentPage() {
|
|
3555
|
+
let session = activeSession;
|
|
3556
|
+
if (!session?.closePage) {
|
|
3557
|
+
emit("close");
|
|
3558
|
+
return;
|
|
3559
|
+
}
|
|
3560
|
+
clearContinuousInput(), sessionQueue = sessionQueue.then(() => {
|
|
3561
|
+
if (activeSession === session)
|
|
3562
|
+
return session.closePage?.();
|
|
3563
|
+
}).then((closed) => {
|
|
3564
|
+
closed === !1 && activeSession === session && emit("close");
|
|
3565
|
+
}).catch((error) => {
|
|
3566
|
+
activeSession === session && reportError(error);
|
|
3567
|
+
});
|
|
3568
|
+
}
|
|
3569
|
+
function point(event) {
|
|
3570
|
+
let bounds = rawRect.value, cellX = Math.max(0, Math.min(bounds.w - 1, Math.floor(event.cellX - bounds.x))), cellY = Math.max(0, Math.min(bounds.h - 1, Math.floor(event.cellY - bounds.y)));
|
|
3571
|
+
return {
|
|
3572
|
+
x: Math.max(
|
|
3573
|
+
0,
|
|
3574
|
+
Math.min(activePixelWidth - 1, (cellX + 0.5) / bounds.w * activePixelWidth)
|
|
3575
|
+
),
|
|
3576
|
+
y: Math.max(
|
|
3577
|
+
0,
|
|
3578
|
+
Math.min(activePixelHeight - 1, (cellY + 0.5) / bounds.h * activePixelHeight)
|
|
3579
|
+
)
|
|
3580
|
+
};
|
|
3581
|
+
}
|
|
3582
|
+
function capture(event) {
|
|
3583
|
+
event.preventDefault(), event.stopPropagation();
|
|
3584
|
+
}
|
|
3585
|
+
function pointer(type, event) {
|
|
3586
|
+
type === "pointerdown" && id.value && events.value?.focus(id.value), capture(event), dispatch({
|
|
3587
|
+
type,
|
|
3588
|
+
...point(event),
|
|
3589
|
+
button: event.button,
|
|
3590
|
+
buttons: event.buttons,
|
|
3591
|
+
modifiers: modifiers(event)
|
|
3592
|
+
});
|
|
3593
|
+
}
|
|
3594
|
+
let { id } = useTerminalNode(() => ({
|
|
3595
|
+
rect: rect.value,
|
|
3596
|
+
zIndex: props.zIndex,
|
|
3597
|
+
visible: visible.value,
|
|
3598
|
+
focusable: !0,
|
|
3599
|
+
selectable: !1,
|
|
3600
|
+
handlers: {
|
|
3601
|
+
pointerdown: (event) => pointer("pointerdown", event),
|
|
3602
|
+
pointerup: (event) => pointer("pointerup", event),
|
|
3603
|
+
pointermove: (event) => pointer("pointermove", event),
|
|
3604
|
+
wheel: (event) => {
|
|
3605
|
+
capture(event), dispatch({
|
|
3606
|
+
type: "wheel",
|
|
3607
|
+
...point(event),
|
|
3608
|
+
deltaY: Number(event.deltaY ?? 0),
|
|
3609
|
+
modifiers: modifiers(event)
|
|
3610
|
+
});
|
|
3611
|
+
},
|
|
3612
|
+
keydown: (event) => {
|
|
3613
|
+
if (capture(event), (event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "l") {
|
|
3614
|
+
emit("requestAddress");
|
|
3615
|
+
return;
|
|
3616
|
+
}
|
|
3617
|
+
if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "r") {
|
|
3618
|
+
invoke((session) => session.reload?.());
|
|
3619
|
+
return;
|
|
3620
|
+
}
|
|
3621
|
+
if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "t") {
|
|
3622
|
+
invoke((session) => session.newPage?.()), emit("requestAddress");
|
|
3623
|
+
return;
|
|
3624
|
+
}
|
|
3625
|
+
if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "w") {
|
|
3626
|
+
closeCurrentPage();
|
|
3627
|
+
return;
|
|
3628
|
+
}
|
|
3629
|
+
if (event.altKey && event.key === "ArrowLeft") {
|
|
3630
|
+
invoke((session) => session.back?.());
|
|
3631
|
+
return;
|
|
3632
|
+
}
|
|
3633
|
+
if (event.altKey && event.key === "ArrowRight") {
|
|
3634
|
+
invoke((session) => session.forward?.());
|
|
3635
|
+
return;
|
|
3636
|
+
}
|
|
3637
|
+
if (event.ctrlKey && ["c", "q"].includes(event.key.toLowerCase())) {
|
|
3638
|
+
emit("close");
|
|
3639
|
+
return;
|
|
3640
|
+
}
|
|
3641
|
+
dispatch({
|
|
3642
|
+
type: "keydown",
|
|
3643
|
+
key: event.key,
|
|
3644
|
+
code: event.code,
|
|
3645
|
+
repeat: !!event.repeat,
|
|
3646
|
+
modifiers: modifiers(event)
|
|
3647
|
+
});
|
|
3648
|
+
},
|
|
3649
|
+
keyup: (event) => {
|
|
3650
|
+
capture(event), !isBrowserShortcut(event) && dispatch({
|
|
3651
|
+
type: "keyup",
|
|
3652
|
+
key: event.key,
|
|
3653
|
+
code: event.code,
|
|
3654
|
+
repeat: !!event.repeat,
|
|
3655
|
+
modifiers: modifiers(event)
|
|
3656
|
+
});
|
|
3657
|
+
},
|
|
3658
|
+
paste: (event) => {
|
|
3659
|
+
capture(event);
|
|
3660
|
+
let text = eventText(event);
|
|
3661
|
+
text && dispatch({ type: "paste", text });
|
|
3662
|
+
},
|
|
3663
|
+
compositionend: (event) => {
|
|
3664
|
+
capture(event);
|
|
3665
|
+
let text = eventText(event);
|
|
3666
|
+
text && dispatch({ type: "text", text }), skipNextInput = !0, queueMicrotask(() => {
|
|
3667
|
+
skipNextInput = !1;
|
|
3668
|
+
});
|
|
3669
|
+
},
|
|
3670
|
+
input: (event) => {
|
|
3671
|
+
if (capture(event), skipNextInput)
|
|
3672
|
+
return;
|
|
3673
|
+
let text = eventText(event);
|
|
3674
|
+
text && dispatch({ type: "text", text });
|
|
3675
|
+
}
|
|
3676
|
+
}
|
|
3677
|
+
}));
|
|
3678
|
+
return (0, import_vue12.watchEffect)(() => {
|
|
3679
|
+
!props.autoFocus || !visible.value || !id.value || events.value?.getFocused() !== id.value && events.value?.focus(id.value);
|
|
3680
|
+
}), (0, import_vue12.watch)(
|
|
3681
|
+
() => props.url,
|
|
3682
|
+
(url) => {
|
|
3683
|
+
requestedUrl = url, activeSession?.navigate && invoke((session) => session.navigate?.(url));
|
|
3684
|
+
}
|
|
3685
|
+
), (0, import_vue12.onBeforeUnmount)(() => {
|
|
3686
|
+
alive = !1, activeSession = null, clearContinuousInput();
|
|
3687
|
+
}), () => (0, import_vue12.h)(TVideo, {
|
|
3688
|
+
x: props.x,
|
|
3689
|
+
y: props.y,
|
|
3690
|
+
w: props.w,
|
|
3691
|
+
h: props.h,
|
|
3692
|
+
zIndex: props.zIndex,
|
|
3693
|
+
src: initialUrl,
|
|
3694
|
+
frameSource,
|
|
3695
|
+
maxFps: props.maxFps,
|
|
3696
|
+
pixelWidth: props.pixelWidth ?? initialPixelWidth,
|
|
3697
|
+
pixelHeight: props.pixelHeight ?? initialPixelHeight,
|
|
3698
|
+
fallback: props.fallback,
|
|
3699
|
+
style: props.style,
|
|
3700
|
+
clear: props.clear,
|
|
3701
|
+
onFrame: (event) => emit("frame", event),
|
|
3702
|
+
onError: (error) => emit("error", error)
|
|
3703
|
+
});
|
|
3704
|
+
}
|
|
3705
|
+
});
|