@hex1b/web-terminal 0.1.0 → 0.167.0-alpha.1512.1.d6b2173

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 CHANGED
@@ -172,6 +172,20 @@ actions reject if selection/input/focus changes before their asynchronous work
172
172
  can be applied safely. Errors are surfaced rather than silently reported as
173
173
  successful copies or pastes.
174
174
 
175
+ ### Hyperlinks
176
+
177
+ Hold Ctrl or Cmd and click an OSC 8 hyperlink to open its destination in a new
178
+ tab. Hovering shows the destination and activation hint; holding the modifier
179
+ also shows a pointer cursor. Links work in live output, scrollback, and read-only
180
+ views. Plain clicks and drags retain their existing selection/application
181
+ behavior, and explicit input-policy routes or actions take precedence.
182
+ Shift and Alt/Option continue to reserve selection gestures.
183
+
184
+ Only absolute `http:`, `https:`, and `mailto:` destinations are activated
185
+ (`mailto:` handling depends on the browser). New tabs use `noopener,noreferrer`.
186
+ Script, data, file, relative, and custom-scheme URLs are not activated.
187
+ Plain URL text is not automatically detected; the workload must emit OSC 8.
188
+
175
189
  ## Selection UI hooks
176
190
 
177
191
  `onSelectionUI` receives a typed `SelectionUIEvent`, also dispatched as the
@@ -0,0 +1,10 @@
1
+ import type { TerminalPoint } from "./types.js";
2
+ import type { HyperlinkRange } from "./wire-types.js";
3
+ /** OSC 8 destinations are untrusted output, not page-relative navigation. */
4
+ export declare function hyperlinkUri(uri: string): string | null;
5
+ export declare class Hyperlinks {
6
+ #private;
7
+ update(ranges: readonly HyperlinkRange[]): void;
8
+ at(point: TerminalPoint): string | null;
9
+ }
10
+ //# sourceMappingURL=hyperlinks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hyperlinks.d.ts","sourceRoot":"","sources":["../src/hyperlinks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtD,6EAA6E;AAC7E,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAIvD;AAED,qBAAa,UAAU;;IAGrB,MAAM,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,GAAG,IAAI;IAa/C,EAAE,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI;CAIxC"}
@@ -0,0 +1,28 @@
1
+ /** OSC 8 destinations are untrusted output, not page-relative navigation. */
2
+ export function hyperlinkUri(uri) {
3
+ if (/[\u0000-\u0020\u007f]/u.test(uri) || !URL.canParse(uri))
4
+ return null;
5
+ const url = new URL(uri);
6
+ return ["https:", "http:", "mailto:"].includes(url.protocol) ? url.href : null;
7
+ }
8
+ export class Hyperlinks {
9
+ #rows = new Map();
10
+ update(ranges) {
11
+ this.#rows.clear();
12
+ const destinations = new Map();
13
+ for (const range of ranges) {
14
+ if (!destinations.has(range.uri))
15
+ destinations.set(range.uri, hyperlinkUri(range.uri));
16
+ const uri = destinations.get(range.uri);
17
+ if (!uri)
18
+ continue;
19
+ const row = this.#rows.get(range.row) ?? [];
20
+ row.push({ ...range, uri });
21
+ this.#rows.set(range.row, row);
22
+ }
23
+ }
24
+ at(point) {
25
+ return this.#rows.get(point.y)?.find(range => point.x >= range.startColumn && point.x < range.endColumn)?.uri ?? null;
26
+ }
27
+ }
28
+ //# sourceMappingURL=hyperlinks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hyperlinks.js","sourceRoot":"","sources":["../src/hyperlinks.ts"],"names":[],"mappings":"AAGA,6EAA6E;AAC7E,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,IAAI,wBAAwB,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1E,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IACzB,OAAO,CAAC,QAAQ,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AACjF,CAAC;AAED,MAAM,OAAO,UAAU;IACrB,KAAK,GAAG,IAAI,GAAG,EAA4B,CAAC;IAE5C,MAAM,CAAC,MAAiC;QACtC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACnB,MAAM,YAAY,GAAG,IAAI,GAAG,EAAyB,CAAC;QACtD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC;gBAAE,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;YACvF,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACxC,IAAI,CAAC,GAAG;gBAAE,SAAS;YACnB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;YAC5C,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;YAC5B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IAED,EAAE,CAAC,KAAoB;QACrB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,CAC3C,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,SAAS,CAAC,EAAE,GAAG,IAAI,IAAI,CAAC;IAC5E,CAAC;CACF","sourcesContent":["import type { TerminalPoint } from \"./types.js\";\nimport type { HyperlinkRange } from \"./wire-types.js\";\n\n/** OSC 8 destinations are untrusted output, not page-relative navigation. */\nexport function hyperlinkUri(uri: string): string | null {\n if (/[\\u0000-\\u0020\\u007f]/u.test(uri) || !URL.canParse(uri)) return null;\n const url = new URL(uri);\n return [\"https:\", \"http:\", \"mailto:\"].includes(url.protocol) ? url.href : null;\n}\n\nexport class Hyperlinks {\n #rows = new Map<number, HyperlinkRange[]>();\n\n update(ranges: readonly HyperlinkRange[]): void {\n this.#rows.clear();\n const destinations = new Map<string, string | null>();\n for (const range of ranges) {\n if (!destinations.has(range.uri)) destinations.set(range.uri, hyperlinkUri(range.uri));\n const uri = destinations.get(range.uri);\n if (!uri) continue;\n const row = this.#rows.get(range.row) ?? [];\n row.push({ ...range, uri });\n this.#rows.set(range.row, row);\n }\n }\n\n at(point: TerminalPoint): string | null {\n return this.#rows.get(point.y)?.find(range =>\n point.x >= range.startColumn && point.x < range.endColumn)?.uri ?? null;\n }\n}\n"]}
@@ -14,9 +14,12 @@ interface MouseInspection {
14
14
  execute?: (decision: Extract<InputDecision, {
15
15
  action: unknown;
16
16
  }>, input: TerminalInput) => void;
17
+ hyperlink?: (point: TerminalPoint) => string | null;
18
+ openHyperlink?: (uri: string) => void;
17
19
  }
18
20
  export interface MouseCapture {
19
21
  update(columns: number, rows: number, tracking: MouseTrackingMode): void;
22
+ refresh(): void;
20
23
  cancel(): void;
21
24
  dispose(): void;
22
25
  }
@@ -1 +1 @@
1
- {"version":3,"file":"mouse-input.d.ts","sourceRoot":"","sources":["../src/mouse-input.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAmB,iBAAiB,EAAiB,aAAa,EAC3F,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,KAAK,EAA6B,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAK/E,UAAU,eAAe;IACvB,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;IAC7C,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE;QAAE,IAAI,EAAE,aAAa,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC;IAC5F,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IACxC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,aAAa,KAAK,IAAI,CAAC;IAC3D,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,aAAa,CAAC;IAClD,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC,aAAa,EAAE;QAAE,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC,EAAE,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;CACjG;AACD,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACzE,MAAM,IAAI,IAAI,CAAC;IACf,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,oFAAoF;AACpF,wBAAgB,YAAY,CAAC,MAAM,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,EAC3F,KAAK,EAAE,MAAM,IAAI,EAAE,UAAU,GAAE,eAAoB,GAAG,YAAY,CA+SnE"}
1
+ {"version":3,"file":"mouse-input.d.ts","sourceRoot":"","sources":["../src/mouse-input.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAmB,iBAAiB,EAAiB,aAAa,EAC3F,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,KAAK,EAA6B,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAM/E,UAAU,eAAe;IACvB,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;IAC7C,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE;QAAE,IAAI,EAAE,aAAa,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC;IAC5F,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IACxC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,aAAa,KAAK,IAAI,CAAC;IAC3D,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,aAAa,CAAC;IAClD,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC,aAAa,EAAE;QAAE,MAAM,EAAE,OAAO,CAAA;KAAE,CAAC,EAAE,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAChG,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,MAAM,GAAG,IAAI,CAAC;IACpD,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CACvC;AACD,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACzE,OAAO,IAAI,IAAI,CAAC;IAChB,MAAM,IAAI,IAAI,CAAC;IACf,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,oFAAoF;AACpF,wBAAgB,YAAY,CAAC,MAAM,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,EAC3F,KAAK,EAAE,MAAM,IAAI,EAAE,UAAU,GAAE,eAAoB,GAAG,YAAY,CA2WnE"}
@@ -24,10 +24,27 @@ export function captureMouse(canvas, send, focus, inspection = {}) {
24
24
  let completedClick;
25
25
  let routedGesture;
26
26
  let contextMenuRoute;
27
+ let hyperlinkClick;
28
+ let hoverEvent;
29
+ let hoverModifiers;
30
+ const originalTitle = canvas.title;
31
+ const originalCursor = canvas.style.cursor;
27
32
  const state = () => ({ tracking, ...inspection.state?.() });
28
33
  function point(event, clamp = false) {
29
34
  return cellPoint(event, canvas.getBoundingClientRect(), columns, rows, clamp);
30
35
  }
36
+ function refreshHover(modifiers = hoverModifiers) {
37
+ if (!inspection.hyperlink)
38
+ return;
39
+ hoverModifiers = modifiers;
40
+ const position = hoverEvent && point(hoverEvent);
41
+ const uri = position ? inspection.hyperlink(position) : null;
42
+ canvas.title = uri ? `${uri}\nCtrl/Cmd+click to open link` : originalTitle;
43
+ canvas.style.cursor = uri && modifiers && (modifiers.ctrlKey || modifiers.metaKey) &&
44
+ !modifiers.altKey && !modifiers.shiftKey ? "pointer" : originalCursor;
45
+ if (hyperlinkClick && hyperlinkClick.uri !== uri)
46
+ hyperlinkClick.dragged = true;
47
+ }
31
48
  function updateAutoScroll() {
32
49
  clearTimeout(autoScroll);
33
50
  autoScroll = undefined;
@@ -83,6 +100,7 @@ export function captureMouse(canvas, send, focus, inspection = {}) {
83
100
  pointerEvent = undefined;
84
101
  selectionClick = undefined;
85
102
  completedClick = undefined;
103
+ hyperlinkClick = undefined;
86
104
  gesture.end();
87
105
  routedGesture = undefined;
88
106
  if (report)
@@ -115,6 +133,8 @@ export function captureMouse(canvas, send, focus, inspection = {}) {
115
133
  if (!position)
116
134
  return;
117
135
  if (pointerId !== null) {
136
+ if (hyperlinkClick)
137
+ hyperlinkClick.dragged = true;
118
138
  if (routedGesture !== InputRoute.Browser)
119
139
  event.preventDefault();
120
140
  if ((gesture.owner === "app" || routedGesture === InputRoute.Application) && pointerId === event.pointerId)
@@ -125,8 +145,20 @@ export function captureMouse(canvas, send, focus, inspection = {}) {
125
145
  const input = { type: "pointer", button: pointerButtons[event.button],
126
146
  point: Object.freeze({ ...position }), ...inputModifiers(event) };
127
147
  const decision = inspection.resolve?.(input) ?? { route: InputRoute.Continue };
128
- const route = decision.action !== undefined ? InputRoute.Consume : decision.route;
148
+ let route = decision.action !== undefined ? InputRoute.Consume : decision.route;
149
+ if (route === InputRoute.Continue && event.button === 0 && (event.ctrlKey || event.metaKey) &&
150
+ !event.altKey && !event.shiftKey) {
151
+ const uri = inspection.hyperlink?.(position);
152
+ if (uri) {
153
+ hyperlinkClick = { uri, x: event.clientX, y: event.clientY, dragged: false };
154
+ route = InputRoute.Consume;
155
+ }
156
+ }
129
157
  contextMenuRoute = event.button === 2 ? route : undefined;
158
+ if (hyperlinkClick)
159
+ contextMenuRoute = InputRoute.Consume;
160
+ hoverEvent = event;
161
+ refreshHover(event);
130
162
  if (route !== InputRoute.Continue) {
131
163
  completedClick = selectionClick = undefined;
132
164
  click.count = 0;
@@ -186,6 +218,10 @@ export function captureMouse(canvas, send, focus, inspection = {}) {
186
218
  return;
187
219
  if (pointerId !== null && pointerId !== event.pointerId)
188
220
  return;
221
+ hoverEvent = event;
222
+ refreshHover(event);
223
+ if (hyperlinkClick && Math.hypot(event.clientX - hyperlinkClick.x, event.clientY - hyperlinkClick.y) >= 4)
224
+ hyperlinkClick.dragged = true;
189
225
  const position = point(event, pointerId !== null);
190
226
  if (!position)
191
227
  return;
@@ -224,6 +260,21 @@ export function captureMouse(canvas, send, focus, inspection = {}) {
224
260
  canvas.addEventListener("pointerup", event => {
225
261
  if (pointerId !== event.pointerId)
226
262
  return;
263
+ if (hyperlinkClick) {
264
+ event.preventDefault();
265
+ const link = hyperlinkClick;
266
+ const position = point(event);
267
+ const activate = event.button === 0 && event.buttons === 0 && !link.dragged &&
268
+ Math.hypot(event.clientX - link.x, event.clientY - link.y) < 4 &&
269
+ position && inspection.hyperlink?.(position) === link.uri;
270
+ if (event.buttons === 0)
271
+ cancel(false, false);
272
+ else
273
+ link.dragged = true;
274
+ if (activate)
275
+ inspection.openHyperlink?.(link.uri);
276
+ return;
277
+ }
227
278
  const position = point(event, true) ?? lastPoint;
228
279
  if (routedGesture) {
229
280
  if (routedGesture === InputRoute.Application && position)
@@ -262,11 +313,21 @@ export function captureMouse(canvas, send, focus, inspection = {}) {
262
313
  inspection.begin?.(completed.point, { mode, extend: false });
263
314
  }, options);
264
315
  canvas.addEventListener("pointercancel", () => cancel(), options);
316
+ canvas.addEventListener("pointerleave", () => {
317
+ hoverEvent = undefined;
318
+ refreshHover();
319
+ }, options);
265
320
  canvas.addEventListener("lostpointercapture", () => {
266
321
  if (pointerId !== null)
267
322
  cancel();
268
323
  }, options);
269
- window.addEventListener("blur", () => cancel(), options);
324
+ window.addEventListener("blur", () => {
325
+ cancel();
326
+ hoverEvent = undefined;
327
+ refreshHover();
328
+ }, options);
329
+ window.addEventListener("keydown", event => refreshHover(event), { ...options, capture: true });
330
+ window.addEventListener("keyup", event => refreshHover(event), { ...options, capture: true });
270
331
  canvas.addEventListener("contextmenu", event => {
271
332
  if (contextMenuRoute !== undefined && contextMenuRoute !== InputRoute.Continue) {
272
333
  const route = contextMenuRoute;
@@ -279,6 +340,8 @@ export function captureMouse(canvas, send, focus, inspection = {}) {
279
340
  event.preventDefault();
280
341
  }, options);
281
342
  canvas.addEventListener("wheel", event => {
343
+ if (hyperlinkClick)
344
+ hyperlinkClick.dragged = true;
282
345
  const input = { type: "wheel", deltaX: event.deltaX, deltaY: event.deltaY,
283
346
  deltaMode: event.deltaMode, point: point(event), ...inputModifiers(event) };
284
347
  const decision = pointerId === null
@@ -345,11 +408,15 @@ export function captureMouse(canvas, send, focus, inspection = {}) {
345
408
  rows = nextRows;
346
409
  tracking = nextTracking;
347
410
  }
411
+ refreshHover();
348
412
  },
413
+ refresh() { refreshHover(); },
349
414
  cancel() { cancel(); },
350
415
  dispose() {
351
416
  cancel(false);
352
417
  listeners.abort();
418
+ canvas.title = originalTitle;
419
+ canvas.style.cursor = originalCursor;
353
420
  }
354
421
  };
355
422
  }
@@ -1 +1 @@
1
- {"version":3,"file":"mouse-input.js","sourceRoot":"","sources":["../src/mouse-input.ts"],"names":[],"mappings":"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","sourcesContent":["import { cellPoint, WheelAccumulator, SelectionGesture } from \"./selection-input.js\";\nimport { InputRoute, inputModifiers } from \"./input-policy.js\";\nimport type { GestureState } from \"./selection-input.js\";\nimport type { InputDecision, InputRouteValue, MouseTrackingMode, PointerButton, SelectionMode,\n TerminalInput, TerminalPoint } from \"./types.js\";\nimport type { CellPosition, MouseButton, MouseCommand } from \"./wire-types.js\";\n\nconst buttons: readonly (readonly [PointerButton, number])[] = [[\"left\", 1], [\"middle\", 4], [\"right\", 2]];\nconst pointerButtons: readonly PointerButton[] = [\"left\", \"middle\", \"right\"];\ninterface SelectionClick { point: TerminalPoint; mode: SelectionMode; extend: boolean; dragged: boolean }\ninterface MouseInspection {\n state?: () => Omit<GestureState, \"tracking\">;\n begin?: (point: TerminalPoint, selection: { mode: SelectionMode; extend: boolean }) => void;\n extend?: (point: TerminalPoint) => void;\n scroll?: (delta: number, endpoint?: TerminalPoint) => void;\n end?: (cancelled: boolean) => void;\n resolve?: (input: TerminalInput) => InputDecision;\n execute?: (decision: Extract<InputDecision, { action: unknown }>, input: TerminalInput) => void;\n}\nexport interface MouseCapture {\n update(columns: number, rows: number, tracking: MouseTrackingMode): void;\n cancel(): void;\n dispose(): void;\n}\n\n/** Capture input intent only; the server chooses and encodes the mouse protocol. */\nexport function captureMouse(canvas: HTMLCanvasElement, send: (command: MouseCommand) => void,\n focus: () => void, inspection: MouseInspection = {}): MouseCapture {\n const listeners = new AbortController();\n const options = { signal: listeners.signal };\n let columns = 1, rows = 1;\n let tracking: MouseTrackingMode = 0;\n let pointerId: number | null = null;\n const pressed = new Set<PointerButton>();\n let lastPoint: CellPosition | undefined;\n let pendingMove: MouseCommand | undefined;\n let lastMove: string | undefined;\n let scheduled: number | undefined;\n const wheel = new WheelAccumulator();\n const gesture = new SelectionGesture();\n let wheelOwner: \"local\" | \"app\" | undefined;\n let pointerEvent: PointerEvent | undefined;\n let autoScroll: ReturnType<typeof setTimeout> | undefined;\n let click = { count: 0, time: 0, x: -1, y: -1 };\n let selectionClick: SelectionClick | undefined;\n let completedClick: SelectionClick | undefined;\n let routedGesture: InputRouteValue | undefined;\n let contextMenuRoute: InputRouteValue | undefined;\n const state = () => ({ tracking, ...inspection.state?.() });\n\n function point(event: MouseEvent, clamp = false): CellPosition | null {\n return cellPoint(event, canvas.getBoundingClientRect(), columns, rows, clamp);\n }\n\n function updateAutoScroll() {\n clearTimeout(autoScroll);\n autoScroll = undefined;\n if (gesture.owner !== \"local\" || !pointerEvent) return;\n const bounds = canvas.getBoundingClientRect();\n const distance = pointerEvent.clientY < bounds.top ? pointerEvent.clientY - bounds.top\n : pointerEvent.clientY >= bounds.bottom ? pointerEvent.clientY - bounds.bottom + 1 : 0;\n if (!distance) return;\n autoScroll = setTimeout(() => {\n autoScroll = undefined;\n if (!pointerEvent) return;\n const position = point(pointerEvent, true);\n if (gesture.owner === \"local\" && position) {\n if (selectionClick) selectionClick.dragged = true;\n click.count = 0;\n const lines = Math.sign(distance) * Math.min(8, Math.max(1, Math.ceil(Math.abs(distance) / (bounds.height / rows))));\n inspection.scroll?.(lines, gesture.scrollPoint(position));\n updateAutoScroll();\n }\n }, 60);\n }\n\n function flushMove() {\n if (scheduled !== undefined) cancelAnimationFrame(scheduled);\n scheduled = undefined;\n if (pendingMove) send(pendingMove);\n pendingMove = undefined;\n }\n\n function changeButtons(event: PointerEvent, position: CellPosition): void {\n for (const [button, mask] of buttons) {\n const down = (event.buttons & mask) !== 0;\n if (down === pressed.has(button)) continue;\n flushMove();\n if (down) pressed.add(button);\n else pressed.delete(button);\n if (down || tracking !== 9)\n send({ type: \"mouse\", action: down ? \"down\" : \"up\", button, ...position });\n lastMove = undefined;\n }\n }\n\n function cancel(report = true, cancelled = true) {\n inspection.end?.(cancelled);\n clearTimeout(autoScroll);\n autoScroll = undefined;\n pointerEvent = undefined;\n selectionClick = undefined;\n completedClick = undefined;\n gesture.end();\n routedGesture = undefined;\n if (report) flushMove();\n else {\n if (scheduled !== undefined) cancelAnimationFrame(scheduled);\n scheduled = undefined;\n pendingMove = undefined;\n }\n if (report && tracking !== 9 && lastPoint) {\n for (const button of pressed)\n send({ type: \"mouse\", action: \"up\", button, ...lastPoint });\n }\n pressed.clear();\n const captured = pointerId;\n pointerId = null;\n if (captured !== null && canvas.hasPointerCapture(captured))\n canvas.releasePointerCapture(captured);\n lastMove = undefined;\n wheel.reset();\n wheelOwner = undefined;\n }\n\n canvas.addEventListener(\"pointerdown\", event => {\n if (event.defaultPrevented && pointerId === null) return;\n if (event.pointerType !== \"mouse\" || ![0, 1, 2].includes(event.button)) return;\n const position = point(event);\n if (!position) return;\n if (pointerId !== null) {\n if (routedGesture !== InputRoute.Browser) event.preventDefault();\n if ((gesture.owner === \"app\" || routedGesture === InputRoute.Application) && pointerId === event.pointerId)\n changeButtons(event, position);\n return;\n }\n focus();\n const input: TerminalInput = { type: \"pointer\", button: pointerButtons[event.button],\n point: Object.freeze({ ...position }), ...inputModifiers(event) };\n const decision = inspection.resolve?.(input) ?? { route: InputRoute.Continue };\n const route = decision.action !== undefined ? InputRoute.Consume : decision.route;\n contextMenuRoute = event.button === 2 ? route : undefined;\n if (route !== InputRoute.Continue) {\n completedClick = selectionClick = undefined;\n click.count = 0;\n routedGesture = route;\n pointerId = event.pointerId;\n lastPoint = position;\n canvas.setPointerCapture(pointerId);\n if (route !== InputRoute.Browser) event.preventDefault();\n if (route === InputRoute.Application) flushMove();\n else {\n if (scheduled !== undefined) cancelAnimationFrame(scheduled);\n scheduled = undefined;\n pendingMove = undefined;\n }\n if (route === InputRoute.Application) changeButtons(event, position);\n if (decision.action !== undefined) inspection.execute?.(decision, input);\n return;\n }\n // Keep focus on the hidden keyboard input instead of the canvas.\n event.preventDefault();\n if (event.metaKey) return;\n const now = performance.now();\n click.count = now - click.time < 500 && position.x === click.x && position.y === click.y\n ? click.count % 3 + 1 : 1;\n click = { count: click.count, time: now, x: position.x, y: position.y };\n const start = gesture.begin({ button: event.button, shiftKey: event.shiftKey, altKey: event.altKey,\n detail: event.detail || click.count }, position, state());\n if (!start) return;\n pointerId = event.pointerId;\n pointerEvent = event;\n lastPoint = position;\n completedClick = undefined;\n canvas.setPointerCapture(pointerId);\n if (start.owner === \"local\") {\n if (scheduled !== undefined) cancelAnimationFrame(scheduled);\n scheduled = undefined;\n pendingMove = undefined;\n lastMove = undefined;\n selectionClick = { point: position, mode: start.mode, extend: start.extend, dragged: false };\n inspection.begin?.(position, start);\n }\n else changeButtons(event, position);\n }, options);\n\n canvas.addEventListener(\"pointermove\", event => {\n if (event.pointerType !== \"mouse\") return;\n if (pointerId === null && event.buttons) return;\n if (pointerId !== null && pointerId !== event.pointerId) return;\n const position = point(event, pointerId !== null);\n if (!position) return;\n lastPoint = position;\n if (routedGesture && routedGesture !== InputRoute.Application) return;\n if (gesture.owner === \"local\") {\n pointerEvent = event;\n const previous = gesture.endpoint;\n const endpoint = gesture.move(position);\n if (endpoint && previous && (endpoint.x !== previous.x || endpoint.y !== previous.y)) {\n click.count = 0;\n if (selectionClick) selectionClick.dragged = true;\n inspection.extend?.(endpoint);\n }\n updateAutoScroll();\n return;\n }\n if (!tracking || (!routedGesture && gesture.owner === null && (state().historical || state().readOnly || event.shiftKey))) return;\n if (pointerId === event.pointerId) changeButtons(event, position);\n if (event.metaKey || (tracking !== 1003 && !(tracking === 1002 && pressed.size))) return;\n const button = buttons.find(([name]) => pressed.has(name))?.[0] ?? \"none\";\n const move: MouseCommand = { type: \"mouse\", action: \"move\", button, ...position };\n const key = JSON.stringify(move);\n if (key === lastMove) return;\n lastMove = key;\n pendingMove = move;\n if (scheduled === undefined) scheduled = requestAnimationFrame(flushMove);\n }, options);\n\n canvas.addEventListener(\"pointerup\", event => {\n if (pointerId !== event.pointerId) return;\n const position = point(event, true) ?? lastPoint;\n if (routedGesture) {\n if (routedGesture === InputRoute.Application && position) changeButtons(event, position);\n if (event.buttons === 0) cancel(routedGesture === InputRoute.Application);\n return;\n }\n if (gesture.owner === \"local\") {\n if (position && gesture.endpoint && (position.x !== gesture.endpoint.x || position.y !== gesture.endpoint.y)) {\n if (selectionClick) selectionClick.dragged = true;\n const endpoint = gesture.move(position);\n if (endpoint) inspection.extend?.(endpoint);\n }\n const completed = selectionClick;\n cancel(false, false);\n completedClick = completed;\n return;\n }\n if (position) changeButtons(event, position);\n if (!pressed.size) cancel();\n }, options);\n canvas.addEventListener(\"click\", event => {\n const completed = completedClick;\n completedClick = undefined;\n if (!completed || completed.dragged || !Number.isInteger(event.detail) || event.detail < 1) return;\n click.count = event.detail;\n // Some browsers expose native multiclick counts only on click, not pointerdown.\n const mode = event.detail >= 3 ? \"line\" : event.detail === 2 ? \"word\" : \"character\";\n if (!completed.extend && completed.mode !== \"rectangle\" && mode !== completed.mode)\n inspection.begin?.(completed.point, { mode, extend: false });\n }, options);\n canvas.addEventListener(\"pointercancel\", () => cancel(), options);\n canvas.addEventListener(\"lostpointercapture\", () => {\n if (pointerId !== null) cancel();\n }, options);\n window.addEventListener(\"blur\", () => cancel(), options);\n canvas.addEventListener(\"contextmenu\", event => {\n if (contextMenuRoute !== undefined && contextMenuRoute !== InputRoute.Continue) {\n const route = contextMenuRoute;\n contextMenuRoute = undefined;\n if (route !== InputRoute.Browser) event.preventDefault();\n return;\n }\n if (tracking || gesture.owner === \"local\") event.preventDefault();\n }, options);\n canvas.addEventListener(\"wheel\", event => {\n const input: TerminalInput = { type: \"wheel\", deltaX: event.deltaX, deltaY: event.deltaY,\n deltaMode: event.deltaMode, point: point(event), ...inputModifiers(event) };\n const decision: InputDecision = pointerId === null\n ? inspection.resolve?.(input) ?? { route: InputRoute.Continue }\n : { route: routedGesture ?? InputRoute.Continue };\n if (decision.route === InputRoute.Browser) return;\n if (decision.action !== undefined || decision.route === InputRoute.Consume) {\n event.preventDefault();\n if (decision.action !== undefined) inspection.execute?.(decision, input);\n return;\n }\n // Ctrl+wheel (including trackpad pinch) remains browser zoom.\n if (decision.route !== InputRoute.Application && (event.ctrlKey || event.metaKey)) return;\n const owner = decision.route === InputRoute.Application ? \"app\" : gesture.wheelOwner(event, state());\n if (owner === \"app\" && tracking === 9) return;\n const position = point(gesture.owner === \"local\" && pointerEvent ? pointerEvent : event, gesture.owner === \"local\");\n if (!position) return;\n event.preventDefault();\n flushMove();\n const bounds = canvas.getBoundingClientRect();\n if (wheelOwner !== owner) wheel.reset();\n wheelOwner = owner;\n const { x: horizontal, y: vertical } = wheel.take(event, bounds, rows);\n if (owner === \"local\") {\n if (vertical) {\n if (selectionClick) selectionClick.dragged = true;\n click.count = 0;\n inspection.scroll?.(vertical, gesture.scrollPoint(position));\n }\n return;\n }\n const wheelDirections: [number, MouseButton, MouseButton][] = [\n [vertical, \"wheelUp\", \"wheelDown\"],\n [horizontal, \"wheelLeft\", \"wheelRight\"]\n ];\n for (const [steps, negative, positive] of wheelDirections) {\n if (steps) send({\n type: \"mouse\", action: \"wheel\", button: steps < 0 ? negative : positive,\n count: Math.min(32, Math.abs(steps)), ...position\n });\n }\n }, { ...options, passive: false });\n\n return {\n update(nextColumns, nextRows, nextTracking) {\n if (columns !== nextColumns || rows !== nextRows || tracking !== nextTracking) {\n if (lastPoint) {\n lastPoint = { ...lastPoint,\n x: Math.min(lastPoint.x, nextColumns - 1),\n y: Math.min(lastPoint.y, nextRows - 1)\n };\n }\n // Application mode changes do not transfer ownership mid-gesture.\n if (columns !== nextColumns || rows !== nextRows) cancel(nextTracking !== 0);\n columns = nextColumns;\n rows = nextRows;\n tracking = nextTracking;\n }\n },\n cancel() { cancel(); },\n dispose() {\n cancel(false);\n listeners.abort();\n }\n };\n}\n"]}
1
+ {"version":3,"file":"mouse-input.js","sourceRoot":"","sources":["../src/mouse-input.ts"],"names":[],"mappings":"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","sourcesContent":["import { cellPoint, WheelAccumulator, SelectionGesture } from \"./selection-input.js\";\nimport { InputRoute, inputModifiers } from \"./input-policy.js\";\nimport type { GestureState } from \"./selection-input.js\";\nimport type { InputDecision, InputRouteValue, MouseTrackingMode, PointerButton, SelectionMode,\n TerminalInput, TerminalPoint } from \"./types.js\";\nimport type { CellPosition, MouseButton, MouseCommand } from \"./wire-types.js\";\n\nconst buttons: readonly (readonly [PointerButton, number])[] = [[\"left\", 1], [\"middle\", 4], [\"right\", 2]];\nconst pointerButtons: readonly PointerButton[] = [\"left\", \"middle\", \"right\"];\ninterface SelectionClick { point: TerminalPoint; mode: SelectionMode; extend: boolean; dragged: boolean }\ninterface HyperlinkClick { uri: string; x: number; y: number; dragged: boolean }\ninterface MouseInspection {\n state?: () => Omit<GestureState, \"tracking\">;\n begin?: (point: TerminalPoint, selection: { mode: SelectionMode; extend: boolean }) => void;\n extend?: (point: TerminalPoint) => void;\n scroll?: (delta: number, endpoint?: TerminalPoint) => void;\n end?: (cancelled: boolean) => void;\n resolve?: (input: TerminalInput) => InputDecision;\n execute?: (decision: Extract<InputDecision, { action: unknown }>, input: TerminalInput) => void;\n hyperlink?: (point: TerminalPoint) => string | null;\n openHyperlink?: (uri: string) => void;\n}\nexport interface MouseCapture {\n update(columns: number, rows: number, tracking: MouseTrackingMode): void;\n refresh(): void;\n cancel(): void;\n dispose(): void;\n}\n\n/** Capture input intent only; the server chooses and encodes the mouse protocol. */\nexport function captureMouse(canvas: HTMLCanvasElement, send: (command: MouseCommand) => void,\n focus: () => void, inspection: MouseInspection = {}): MouseCapture {\n const listeners = new AbortController();\n const options = { signal: listeners.signal };\n let columns = 1, rows = 1;\n let tracking: MouseTrackingMode = 0;\n let pointerId: number | null = null;\n const pressed = new Set<PointerButton>();\n let lastPoint: CellPosition | undefined;\n let pendingMove: MouseCommand | undefined;\n let lastMove: string | undefined;\n let scheduled: number | undefined;\n const wheel = new WheelAccumulator();\n const gesture = new SelectionGesture();\n let wheelOwner: \"local\" | \"app\" | undefined;\n let pointerEvent: PointerEvent | undefined;\n let autoScroll: ReturnType<typeof setTimeout> | undefined;\n let click = { count: 0, time: 0, x: -1, y: -1 };\n let selectionClick: SelectionClick | undefined;\n let completedClick: SelectionClick | undefined;\n let routedGesture: InputRouteValue | undefined;\n let contextMenuRoute: InputRouteValue | undefined;\n let hyperlinkClick: HyperlinkClick | undefined;\n let hoverEvent: PointerEvent | undefined;\n let hoverModifiers: Pick<MouseEvent, \"ctrlKey\" | \"metaKey\" | \"altKey\" | \"shiftKey\"> | undefined;\n const originalTitle = canvas.title;\n const originalCursor = canvas.style.cursor;\n const state = () => ({ tracking, ...inspection.state?.() });\n\n function point(event: MouseEvent, clamp = false): CellPosition | null {\n return cellPoint(event, canvas.getBoundingClientRect(), columns, rows, clamp);\n }\n\n function refreshHover(modifiers = hoverModifiers) {\n if (!inspection.hyperlink) return;\n hoverModifiers = modifiers;\n const position = hoverEvent && point(hoverEvent);\n const uri = position ? inspection.hyperlink(position) : null;\n canvas.title = uri ? `${uri}\\nCtrl/Cmd+click to open link` : originalTitle;\n canvas.style.cursor = uri && modifiers && (modifiers.ctrlKey || modifiers.metaKey) &&\n !modifiers.altKey && !modifiers.shiftKey ? \"pointer\" : originalCursor;\n if (hyperlinkClick && hyperlinkClick.uri !== uri) hyperlinkClick.dragged = true;\n }\n\n function updateAutoScroll() {\n clearTimeout(autoScroll);\n autoScroll = undefined;\n if (gesture.owner !== \"local\" || !pointerEvent) return;\n const bounds = canvas.getBoundingClientRect();\n const distance = pointerEvent.clientY < bounds.top ? pointerEvent.clientY - bounds.top\n : pointerEvent.clientY >= bounds.bottom ? pointerEvent.clientY - bounds.bottom + 1 : 0;\n if (!distance) return;\n autoScroll = setTimeout(() => {\n autoScroll = undefined;\n if (!pointerEvent) return;\n const position = point(pointerEvent, true);\n if (gesture.owner === \"local\" && position) {\n if (selectionClick) selectionClick.dragged = true;\n click.count = 0;\n const lines = Math.sign(distance) * Math.min(8, Math.max(1, Math.ceil(Math.abs(distance) / (bounds.height / rows))));\n inspection.scroll?.(lines, gesture.scrollPoint(position));\n updateAutoScroll();\n }\n }, 60);\n }\n\n function flushMove() {\n if (scheduled !== undefined) cancelAnimationFrame(scheduled);\n scheduled = undefined;\n if (pendingMove) send(pendingMove);\n pendingMove = undefined;\n }\n\n function changeButtons(event: PointerEvent, position: CellPosition): void {\n for (const [button, mask] of buttons) {\n const down = (event.buttons & mask) !== 0;\n if (down === pressed.has(button)) continue;\n flushMove();\n if (down) pressed.add(button);\n else pressed.delete(button);\n if (down || tracking !== 9)\n send({ type: \"mouse\", action: down ? \"down\" : \"up\", button, ...position });\n lastMove = undefined;\n }\n }\n\n function cancel(report = true, cancelled = true) {\n inspection.end?.(cancelled);\n clearTimeout(autoScroll);\n autoScroll = undefined;\n pointerEvent = undefined;\n selectionClick = undefined;\n completedClick = undefined;\n hyperlinkClick = undefined;\n gesture.end();\n routedGesture = undefined;\n if (report) flushMove();\n else {\n if (scheduled !== undefined) cancelAnimationFrame(scheduled);\n scheduled = undefined;\n pendingMove = undefined;\n }\n if (report && tracking !== 9 && lastPoint) {\n for (const button of pressed)\n send({ type: \"mouse\", action: \"up\", button, ...lastPoint });\n }\n pressed.clear();\n const captured = pointerId;\n pointerId = null;\n if (captured !== null && canvas.hasPointerCapture(captured))\n canvas.releasePointerCapture(captured);\n lastMove = undefined;\n wheel.reset();\n wheelOwner = undefined;\n }\n\n canvas.addEventListener(\"pointerdown\", event => {\n if (event.defaultPrevented && pointerId === null) return;\n if (event.pointerType !== \"mouse\" || ![0, 1, 2].includes(event.button)) return;\n const position = point(event);\n if (!position) return;\n if (pointerId !== null) {\n if (hyperlinkClick) hyperlinkClick.dragged = true;\n if (routedGesture !== InputRoute.Browser) event.preventDefault();\n if ((gesture.owner === \"app\" || routedGesture === InputRoute.Application) && pointerId === event.pointerId)\n changeButtons(event, position);\n return;\n }\n focus();\n const input: TerminalInput = { type: \"pointer\", button: pointerButtons[event.button],\n point: Object.freeze({ ...position }), ...inputModifiers(event) };\n const decision = inspection.resolve?.(input) ?? { route: InputRoute.Continue };\n let route = decision.action !== undefined ? InputRoute.Consume : decision.route;\n if (route === InputRoute.Continue && event.button === 0 && (event.ctrlKey || event.metaKey) &&\n !event.altKey && !event.shiftKey) {\n const uri = inspection.hyperlink?.(position);\n if (uri) {\n hyperlinkClick = { uri, x: event.clientX, y: event.clientY, dragged: false };\n route = InputRoute.Consume;\n }\n }\n contextMenuRoute = event.button === 2 ? route : undefined;\n if (hyperlinkClick) contextMenuRoute = InputRoute.Consume;\n hoverEvent = event;\n refreshHover(event);\n if (route !== InputRoute.Continue) {\n completedClick = selectionClick = undefined;\n click.count = 0;\n routedGesture = route;\n pointerId = event.pointerId;\n lastPoint = position;\n canvas.setPointerCapture(pointerId);\n if (route !== InputRoute.Browser) event.preventDefault();\n if (route === InputRoute.Application) flushMove();\n else {\n if (scheduled !== undefined) cancelAnimationFrame(scheduled);\n scheduled = undefined;\n pendingMove = undefined;\n }\n if (route === InputRoute.Application) changeButtons(event, position);\n if (decision.action !== undefined) inspection.execute?.(decision, input);\n return;\n }\n // Keep focus on the hidden keyboard input instead of the canvas.\n event.preventDefault();\n if (event.metaKey) return;\n const now = performance.now();\n click.count = now - click.time < 500 && position.x === click.x && position.y === click.y\n ? click.count % 3 + 1 : 1;\n click = { count: click.count, time: now, x: position.x, y: position.y };\n const start = gesture.begin({ button: event.button, shiftKey: event.shiftKey, altKey: event.altKey,\n detail: event.detail || click.count }, position, state());\n if (!start) return;\n pointerId = event.pointerId;\n pointerEvent = event;\n lastPoint = position;\n completedClick = undefined;\n canvas.setPointerCapture(pointerId);\n if (start.owner === \"local\") {\n if (scheduled !== undefined) cancelAnimationFrame(scheduled);\n scheduled = undefined;\n pendingMove = undefined;\n lastMove = undefined;\n selectionClick = { point: position, mode: start.mode, extend: start.extend, dragged: false };\n inspection.begin?.(position, start);\n }\n else changeButtons(event, position);\n }, options);\n\n canvas.addEventListener(\"pointermove\", event => {\n if (event.pointerType !== \"mouse\") return;\n if (pointerId === null && event.buttons) return;\n if (pointerId !== null && pointerId !== event.pointerId) return;\n hoverEvent = event;\n refreshHover(event);\n if (hyperlinkClick && Math.hypot(event.clientX - hyperlinkClick.x, event.clientY - hyperlinkClick.y) >= 4)\n hyperlinkClick.dragged = true;\n const position = point(event, pointerId !== null);\n if (!position) return;\n lastPoint = position;\n if (routedGesture && routedGesture !== InputRoute.Application) return;\n if (gesture.owner === \"local\") {\n pointerEvent = event;\n const previous = gesture.endpoint;\n const endpoint = gesture.move(position);\n if (endpoint && previous && (endpoint.x !== previous.x || endpoint.y !== previous.y)) {\n click.count = 0;\n if (selectionClick) selectionClick.dragged = true;\n inspection.extend?.(endpoint);\n }\n updateAutoScroll();\n return;\n }\n if (!tracking || (!routedGesture && gesture.owner === null && (state().historical || state().readOnly || event.shiftKey))) return;\n if (pointerId === event.pointerId) changeButtons(event, position);\n if (event.metaKey || (tracking !== 1003 && !(tracking === 1002 && pressed.size))) return;\n const button = buttons.find(([name]) => pressed.has(name))?.[0] ?? \"none\";\n const move: MouseCommand = { type: \"mouse\", action: \"move\", button, ...position };\n const key = JSON.stringify(move);\n if (key === lastMove) return;\n lastMove = key;\n pendingMove = move;\n if (scheduled === undefined) scheduled = requestAnimationFrame(flushMove);\n }, options);\n\n canvas.addEventListener(\"pointerup\", event => {\n if (pointerId !== event.pointerId) return;\n if (hyperlinkClick) {\n event.preventDefault();\n const link = hyperlinkClick;\n const position = point(event);\n const activate = event.button === 0 && event.buttons === 0 && !link.dragged &&\n Math.hypot(event.clientX - link.x, event.clientY - link.y) < 4 &&\n position && inspection.hyperlink?.(position) === link.uri;\n if (event.buttons === 0) cancel(false, false);\n else link.dragged = true;\n if (activate) inspection.openHyperlink?.(link.uri);\n return;\n }\n const position = point(event, true) ?? lastPoint;\n if (routedGesture) {\n if (routedGesture === InputRoute.Application && position) changeButtons(event, position);\n if (event.buttons === 0) cancel(routedGesture === InputRoute.Application);\n return;\n }\n if (gesture.owner === \"local\") {\n if (position && gesture.endpoint && (position.x !== gesture.endpoint.x || position.y !== gesture.endpoint.y)) {\n if (selectionClick) selectionClick.dragged = true;\n const endpoint = gesture.move(position);\n if (endpoint) inspection.extend?.(endpoint);\n }\n const completed = selectionClick;\n cancel(false, false);\n completedClick = completed;\n return;\n }\n if (position) changeButtons(event, position);\n if (!pressed.size) cancel();\n }, options);\n canvas.addEventListener(\"click\", event => {\n const completed = completedClick;\n completedClick = undefined;\n if (!completed || completed.dragged || !Number.isInteger(event.detail) || event.detail < 1) return;\n click.count = event.detail;\n // Some browsers expose native multiclick counts only on click, not pointerdown.\n const mode = event.detail >= 3 ? \"line\" : event.detail === 2 ? \"word\" : \"character\";\n if (!completed.extend && completed.mode !== \"rectangle\" && mode !== completed.mode)\n inspection.begin?.(completed.point, { mode, extend: false });\n }, options);\n canvas.addEventListener(\"pointercancel\", () => cancel(), options);\n canvas.addEventListener(\"pointerleave\", () => {\n hoverEvent = undefined;\n refreshHover();\n }, options);\n canvas.addEventListener(\"lostpointercapture\", () => {\n if (pointerId !== null) cancel();\n }, options);\n window.addEventListener(\"blur\", () => {\n cancel();\n hoverEvent = undefined;\n refreshHover();\n }, options);\n window.addEventListener(\"keydown\", event => refreshHover(event), { ...options, capture: true });\n window.addEventListener(\"keyup\", event => refreshHover(event), { ...options, capture: true });\n canvas.addEventListener(\"contextmenu\", event => {\n if (contextMenuRoute !== undefined && contextMenuRoute !== InputRoute.Continue) {\n const route = contextMenuRoute;\n contextMenuRoute = undefined;\n if (route !== InputRoute.Browser) event.preventDefault();\n return;\n }\n if (tracking || gesture.owner === \"local\") event.preventDefault();\n }, options);\n canvas.addEventListener(\"wheel\", event => {\n if (hyperlinkClick) hyperlinkClick.dragged = true;\n const input: TerminalInput = { type: \"wheel\", deltaX: event.deltaX, deltaY: event.deltaY,\n deltaMode: event.deltaMode, point: point(event), ...inputModifiers(event) };\n const decision: InputDecision = pointerId === null\n ? inspection.resolve?.(input) ?? { route: InputRoute.Continue }\n : { route: routedGesture ?? InputRoute.Continue };\n if (decision.route === InputRoute.Browser) return;\n if (decision.action !== undefined || decision.route === InputRoute.Consume) {\n event.preventDefault();\n if (decision.action !== undefined) inspection.execute?.(decision, input);\n return;\n }\n // Ctrl+wheel (including trackpad pinch) remains browser zoom.\n if (decision.route !== InputRoute.Application && (event.ctrlKey || event.metaKey)) return;\n const owner = decision.route === InputRoute.Application ? \"app\" : gesture.wheelOwner(event, state());\n if (owner === \"app\" && tracking === 9) return;\n const position = point(gesture.owner === \"local\" && pointerEvent ? pointerEvent : event, gesture.owner === \"local\");\n if (!position) return;\n event.preventDefault();\n flushMove();\n const bounds = canvas.getBoundingClientRect();\n if (wheelOwner !== owner) wheel.reset();\n wheelOwner = owner;\n const { x: horizontal, y: vertical } = wheel.take(event, bounds, rows);\n if (owner === \"local\") {\n if (vertical) {\n if (selectionClick) selectionClick.dragged = true;\n click.count = 0;\n inspection.scroll?.(vertical, gesture.scrollPoint(position));\n }\n return;\n }\n const wheelDirections: [number, MouseButton, MouseButton][] = [\n [vertical, \"wheelUp\", \"wheelDown\"],\n [horizontal, \"wheelLeft\", \"wheelRight\"]\n ];\n for (const [steps, negative, positive] of wheelDirections) {\n if (steps) send({\n type: \"mouse\", action: \"wheel\", button: steps < 0 ? negative : positive,\n count: Math.min(32, Math.abs(steps)), ...position\n });\n }\n }, { ...options, passive: false });\n\n return {\n update(nextColumns, nextRows, nextTracking) {\n if (columns !== nextColumns || rows !== nextRows || tracking !== nextTracking) {\n if (lastPoint) {\n lastPoint = { ...lastPoint,\n x: Math.min(lastPoint.x, nextColumns - 1),\n y: Math.min(lastPoint.y, nextRows - 1)\n };\n }\n // Application mode changes do not transfer ownership mid-gesture.\n if (columns !== nextColumns || rows !== nextRows) cancel(nextTracking !== 0);\n columns = nextColumns;\n rows = nextRows;\n tracking = nextTracking;\n }\n refreshHover();\n },\n refresh() { refreshHover(); },\n cancel() { cancel(); },\n dispose() {\n cancel(false);\n listeners.abort();\n canvas.title = originalTitle;\n canvas.style.cursor = originalCursor;\n }\n };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,eAAe,EAAiB,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAIlH,eAAO,MAAM,MAAM;;;;;;;;EAQjB,CAAC;AAKH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAGxD;AAyBD,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,IAAI,eAAe,GAAG,IAAI,CAqC1H;AAmGD,8FAA8F;AAC9F,wBAAgB,WAAW,CAAC,MAAM,EAAE,OAAO,GAAG,aAAa,CAiD1D;AAED,6FAA6F;AAC7F,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,CAAC,YAAY,GAAG,SAAS,CAAC,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAY9G"}
1
+ {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,eAAe,EAAiB,YAAY,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAIlH,eAAO,MAAM,MAAM;;;;;;;;EAQjB,CAAC;AAKH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAGxD;AAyBD,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,IAAI,eAAe,GAAG,IAAI,CAqC1H;AA+GD,8FAA8F;AAC9F,wBAAgB,WAAW,CAAC,MAAM,EAAE,OAAO,GAAG,aAAa,CAiD1D;AAED,6FAA6F;AAC7F,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,CAAC,YAAY,GAAG,SAAS,CAAC,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAY9G"}
package/dist/protocol.js CHANGED
@@ -116,6 +116,20 @@ function validateMetadata(metadata) {
116
116
  }
117
117
  integer(columns * rows, "cell count", 1, LIMITS.cells);
118
118
  validateHistory(metadata.history, columns, rows);
119
+ array(metadata.hyperlinks, "hyperlinks", columns * rows);
120
+ let previousLinkEnd = 0;
121
+ for (const link of metadata.hyperlinks) {
122
+ if (!isRecord(link))
123
+ throw new Error("Invalid hyperlink");
124
+ const row = integer(link.row, "hyperlink row", 0, rows - 1);
125
+ const start = integer(link.startColumn, "hyperlink start column", 0, columns - 1);
126
+ const end = integer(link.endColumn, "hyperlink end column", start + 1, columns);
127
+ if (row * columns + start < previousLinkEnd)
128
+ throw new Error("Unordered or overlapping hyperlinks");
129
+ previousLinkEnd = row * columns + end;
130
+ if (typeof link.uri !== "string" || !link.uri.length || link.uri.length > LIMITS.metadataBytes)
131
+ throw new Error("Invalid hyperlink URI");
132
+ }
119
133
  if (metadata.cellWidth !== 10 || metadata.cellHeight !== 20) {
120
134
  throw new Error("This spike requires server geometry of 10 × 20 logical pixels");
121
135
  }
@@ -1 +1 @@
1
- {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"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","sourcesContent":["import type { FrameMetadata, HistoryMetadata, SelectionText, TerminalCell, TerminalFrame } from \"./wire-types.js\";\nimport { isRecord } from \"./validation.js\";\n\n// Binary validation is deliberately independent of the GPU and the transport.\nexport const LIMITS = Object.freeze({\n commandBytes: 64 * 1024,\n frameBytes: 96 * 1024 * 1024,\n metadataBytes: 8 * 1024 * 1024,\n cells: 262144,\n images: 4096,\n placements: 16384,\n textureBytes: 256 * 1024 * 1024,\n});\n\nconst utf8 = new TextDecoder(\"utf-8\", { fatal: true });\nconst utf8Encoder = new TextEncoder();\n\nexport function assertCommandSize(command: unknown): void {\n if (utf8Encoder.encode(JSON.stringify(command)).byteLength > LIMITS.commandBytes)\n throw new RangeError(\"Terminal input exceeds the 64 KiB message limit. Send a smaller amount of text.\");\n}\n\nfunction integer(value: unknown, name: string, min = 0, max = Number.MAX_SAFE_INTEGER): number {\n if (typeof value !== \"number\" || !Number.isSafeInteger(value) || value < min || value > max) {\n throw new Error(`Invalid ${name}: ${String(value)}`);\n }\n return value;\n}\n\nfunction array(value: unknown, name: string, limit: number): asserts value is unknown[] {\n if (!Array.isArray(value) || value.length > limit) throw new Error(`Invalid ${name}`);\n}\n\nfunction key(value: unknown): asserts value is string {\n if (typeof value !== \"string\" || !value.length || value.length > 1024) {\n throw new Error(\"Invalid image key\");\n }\n}\n\nfunction rowId(value: unknown, name: string): asserts value is string {\n if (typeof value !== \"string\" || !/^[1-9][0-9]{0,18}$/u.test(value) || BigInt(value) > 9223372036854775807n) {\n throw new Error(`Invalid ${name}`);\n }\n}\n\nexport function validateHistory(history: unknown, columns: number, rows: number): asserts history is HistoryMetadata | null {\n if (history === null) return;\n if (!isRecord(history)) throw new Error(\"Missing history metadata\");\n rowId(history.generation, \"history generation\");\n if (history.buffer !== \"main\" && history.buffer !== \"alternate\") throw new Error(\"Invalid history buffer\");\n const totalRows = integer(history.totalRows, \"history total rows\", rows, 2147483647);\n const liveTop = integer(history.liveTop, \"history live top\", 0, totalRows - rows);\n if (liveTop !== totalRows - rows) throw new Error(\"Inconsistent history extent\");\n integer(history.top, \"history top\", 0, liveTop);\n if (typeof history.following !== \"boolean\" || (history.following && history.top !== history.liveTop)) {\n throw new Error(\"Invalid history following state\");\n }\n integer(history.requestId, \"viewport request id\");\n array(history.rowIds, \"viewport row ids\", rows);\n if (history.rowIds.length !== rows || new Set(history.rowIds).size !== rows) throw new Error(\"Invalid viewport row ids\");\n for (const id of history.rowIds) rowId(id, \"viewport row id\");\n const selection = history.selection;\n if (!isRecord(selection) || typeof selection.status !== \"string\" ||\n ![\"none\", \"valid\", \"invalidated\"].includes(selection.status)) throw new Error(\"Invalid selection status\");\n integer(selection.requestId, \"selection request id\");\n if (typeof selection.mode !== \"string\" || ![\"character\", \"word\", \"line\", \"rectangle\"].includes(selection.mode)) throw new Error(\"Invalid selection mode\");\n array(selection.ranges, \"selection ranges\", rows);\n let previousRow = -1;\n for (const range of selection.ranges) {\n if (!isRecord(range)) throw new Error(\"Invalid selection range\");\n const row = integer(range.row, \"selection range row\", previousRow + 1, rows - 1);\n const startColumn = integer(range.startColumn, \"selection start column\", 0, columns - 1);\n integer(range.endColumn, \"selection end column\", startColumn + 1, columns);\n previousRow = row;\n }\n validateSelectionText(selection);\n if (selection.status !== \"valid\" && selection.ranges.length) throw new Error(\"Inactive selection has highlight ranges\");\n if (history.copy !== null) {\n if (!isRecord(history.copy)) throw new Error(\"Missing copy metadata\");\n integer(history.copy.requestId, \"copy request id\", 1);\n validateSelectionText(history.copy);\n }\n}\n\nfunction validateSelectionText(selection: Record<string, unknown>): asserts selection is Record<string, unknown> & SelectionText {\n if (typeof selection.status !== \"string\" || ![\"none\", \"valid\", \"invalidated\"].includes(selection.status) ||\n (selection.status === \"valid\"\n ? typeof selection.text !== \"string\" || selection.text.length > LIMITS.metadataBytes\n : selection.text !== null)) {\n throw new Error(\"Invalid selection text\");\n }\n}\n\nfunction validateMetadata(metadata: unknown): asserts metadata is FrameMetadata {\n if (!isRecord(metadata) || metadata.version !== 1 || typeof metadata.full !== \"boolean\") {\n throw new Error(\"Unsupported frame metadata version\");\n }\n integer(metadata.revision, \"revision\", 1);\n integer(metadata.baseRevision, \"base revision\");\n const columns = integer(metadata.columns, \"columns\", 1, 1024);\n const rows = integer(metadata.rows, \"rows\", 1, 512);\n if (typeof metadata.mouseTracking !== \"number\" || ![0, 9, 1000, 1002, 1003].includes(metadata.mouseTracking)) {\n throw new Error(\"Unsupported mouse tracking mode\");\n }\n if (!isRecord(metadata.peer) || typeof metadata.peer.isPrimary !== \"boolean\") throw new Error(\"Invalid peer state\");\n for (const field of [\"id\", \"primaryId\"]) {\n const id = metadata.peer[field];\n if (id !== null && (typeof id !== \"string\" || !id.length || id.length > 256)) {\n throw new Error(`Invalid peer ${field}`);\n }\n }\n if (metadata.peer.id !== null && metadata.peer.isPrimary !== (metadata.peer.id === metadata.peer.primaryId)) {\n throw new Error(\"Inconsistent primary peer state\");\n }\n integer(columns * rows, \"cell count\", 1, LIMITS.cells);\n validateHistory(metadata.history, columns, rows);\n if (metadata.cellWidth !== 10 || metadata.cellHeight !== 20) {\n throw new Error(\"This spike requires server geometry of 10 × 20 logical pixels\");\n }\n for (const field of [\"defaultBackground\", \"defaultForeground\"]) {\n if (metadata[field] !== undefined) integer(metadata[field], field, 0, 0xffffffff);\n }\n if (!isRecord(metadata.cursor) || typeof metadata.cursor.visible !== \"boolean\") throw new Error(\"Invalid cursor\");\n integer(metadata.cursor.x, \"cursor x\", -1, 1024);\n integer(metadata.cursor.y, \"cursor y\", -1, 512);\n const shapes = [\"Default\", \"BlinkingBlock\", \"SteadyBlock\", \"BlinkingUnderline\", \"SteadyUnderline\", \"BlinkingBar\", \"SteadyBar\"];\n if (typeof metadata.cursor.shape === \"string\") metadata.cursor.shape = shapes.indexOf(metadata.cursor.shape);\n integer(metadata.cursor.shape, \"cursor shape\", 0, 6);\n array(metadata.images, \"images\", LIMITS.images);\n array(metadata.retainedImages, \"retained image keys\", LIMITS.images);\n array(metadata.placements, \"placements\", LIMITS.placements);\n array(metadata.warnings, \"warnings\", 256);\n if (metadata.warnings.some(w => typeof w !== \"string\")) throw new Error(\"Invalid warning\");\n if (!isRecord(metadata.stats)) throw new Error(\"Invalid server metrics\");\n for (const field of [\"workloadBytes\", \"outputBatches\", \"captureMs\", \"elapsedMs\"]) {\n const metric = metadata.stats[field];\n if (typeof metric !== \"number\" || !Number.isFinite(metric) || metric < 0) {\n throw new Error(`Invalid server metric ${field}`);\n }\n }\n const retained = new Set<string>();\n for (const imageKey of metadata.retainedImages) {\n key(imageKey);\n if (retained.has(imageKey)) throw new Error(\"Duplicate retained image key\");\n retained.add(imageKey);\n }\n const imageKeys = new Set<string>();\n let decodedImageBytes = 0;\n for (const image of metadata.images) {\n if (!isRecord(image)) throw new Error(\"Invalid image\");\n key(image.key);\n if (imageKeys.has(image.key) || !retained.has(image.key)) throw new Error(\"Inconsistent new image keys\");\n imageKeys.add(image.key);\n const width = integer(image.width, \"image width\", 1, 16384);\n const height = integer(image.height, \"image height\", 1, 16384);\n const byteLength = integer(image.byteLength, \"image byte length\", 1, LIMITS.frameBytes);\n if (image.format !== \"rgba\" && image.format !== \"png\") throw new Error(\"Unsupported image format\");\n if (image.format === \"rgba\" && byteLength !== width * height * 4) {\n throw new Error(\"RGBA image size mismatch\");\n }\n decodedImageBytes += width * height * 4;\n if (decodedImageBytes > LIMITS.textureBytes) throw new Error(\"New images exceed decoded texture budget\");\n }\n for (const placement of metadata.placements) {\n if (!isRecord(placement)) throw new Error(\"Invalid placement\");\n key(placement.key);\n if (!retained.has(placement.key)) throw new Error(\"Placement references an unretained image\");\n if (placement.kind !== \"kgp\" && placement.kind !== \"sixel\") throw new Error(\"Invalid placement kind\");\n for (const field of [\"x\", \"y\", \"width\", \"height\", \"sourceX\", \"sourceY\", \"sourceWidth\", \"sourceHeight\", \"clipX\", \"clipY\", \"clipWidth\", \"clipHeight\", \"z\"]) {\n const coordinate = placement[field];\n if (typeof coordinate !== \"number\" || !Number.isFinite(coordinate) || Math.abs(coordinate) > 2147483648) {\n throw new Error(`Invalid placement ${field}`);\n }\n }\n for (const field of [\"width\", \"height\", \"sourceWidth\", \"sourceHeight\", \"clipWidth\", \"clipHeight\"]) {\n const coordinate = placement[field];\n if (typeof coordinate !== \"number\" || coordinate < 0) throw new Error(`Negative placement ${field}`);\n }\n }\n}\n\n/** Decode one complete, experimental HWT1 message, checking every boundary before reading. */\nexport function decodeFrame(buffer: unknown): TerminalFrame {\n if (!(buffer instanceof ArrayBuffer) || buffer.byteLength > LIMITS.frameBytes) {\n throw new Error(\"Invalid or oversized binary frame\");\n }\n const view = new DataView(buffer);\n let offset = 0;\n const requireBytes = (count: number) => {\n if (count < 0 || count > view.byteLength - offset) throw new Error(\"Truncated HWT1 frame\");\n };\n const u32 = () => { requireBytes(4); const n = view.getUint32(offset, true); offset += 4; return n; };\n if (u32() !== 0x31545748) throw new Error(\"Unsupported frame magic (expected HWT1)\");\n const metadataLength = integer(u32(), \"metadata length\", 2, LIMITS.metadataBytes);\n requireBytes(metadataLength);\n const metadata: unknown = JSON.parse(utf8.decode(new Uint8Array(buffer, offset, metadataLength)));\n offset += metadataLength;\n validateMetadata(metadata);\n const cellCount = metadata.columns * metadata.rows;\n const changedCount = integer(u32(), \"changed cell count\", 0, cellCount);\n if (changedCount > Math.floor((view.byteLength - offset) / 22)) throw new Error(\"Truncated cell records\");\n if (metadata.full && changedCount !== cellCount) throw new Error(\"Incomplete full frame\");\n const cells = [];\n const seen = new Set();\n for (let i = 0; i < changedCount; i++) {\n requireBytes(22);\n const index = u32();\n if (index >= cellCount || seen.has(index)) throw new Error(\"Invalid or duplicate cell index\");\n seen.add(index);\n const foreground = u32();\n const background = u32();\n const underlineColor = u32();\n const attributes = view.getUint16(offset, true);\n const width = view.getUint8(offset + 2);\n const underlineStyle = view.getUint8(offset + 3);\n const textLength = view.getUint16(offset + 4, true);\n offset += 6;\n if (underlineStyle > 5) throw new Error(\"Unsupported underline style\");\n requireBytes(textLength);\n const text = utf8.decode(new Uint8Array(buffer, offset, textLength));\n offset += textLength;\n cells.push({ index, foreground, background, underlineColor, attributes, width, underlineStyle, text });\n }\n const imageBytes = metadata.images.reduce((total, image) => total + image.byteLength, 0);\n if (imageBytes !== view.byteLength - offset) throw new Error(\"Image payload length mismatch\");\n const images = metadata.images.map(image => {\n const bytes = new Uint8Array(buffer, offset, image.byteLength);\n offset += image.byteLength;\n return { ...image, bytes };\n });\n return { metadata, cells, images };\n}\n\n/** Mirror text, not ANSI; continuation cells are already represented by their lead glyph. */\nexport function screenText(cells: readonly (TerminalCell | undefined)[], columns: number, rows: number): string {\n const lines = [];\n for (let y = 0; y < rows; y++) {\n let line = \"\";\n for (let x = 0; x < columns; x++) {\n const cell = cells[y * columns + x];\n if (!cell || cell.width === 0) continue;\n line += cell.attributes & 64 ? \" \".repeat(cell.width) : (cell.text || \" \");\n }\n lines.push(line.replace(/ +$/u, \"\"));\n }\n return lines.join(\"\\n\");\n}\n"]}
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE3C,8EAA8E;AAC9E,MAAM,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IAClC,YAAY,EAAE,EAAE,GAAG,IAAI;IACvB,UAAU,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI;IAC5B,aAAa,EAAE,CAAC,GAAG,IAAI,GAAG,IAAI;IAC9B,KAAK,EAAE,MAAM;IACb,MAAM,EAAE,IAAI;IACZ,UAAU,EAAE,KAAK;IACjB,YAAY,EAAE,GAAG,GAAG,IAAI,GAAG,IAAI;CAChC,CAAC,CAAC;AAEH,MAAM,IAAI,GAAG,IAAI,WAAW,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AACvD,MAAM,WAAW,GAAG,IAAI,WAAW,EAAE,CAAC;AAEtC,MAAM,UAAU,iBAAiB,CAAC,OAAgB;IAChD,IAAI,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,GAAG,MAAM,CAAC,YAAY;QAC9E,MAAM,IAAI,UAAU,CAAC,iFAAiF,CAAC,CAAC;AAC5G,CAAC;AAED,SAAS,OAAO,CAAC,KAAc,EAAE,IAAY,EAAE,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,MAAM,CAAC,gBAAgB;IACnF,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,GAAG,IAAI,KAAK,GAAG,GAAG,EAAE,CAAC;QAC5F,MAAM,IAAI,KAAK,CAAC,WAAW,IAAI,KAAK,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACvD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,KAAK,CAAC,KAAc,EAAE,IAAY,EAAE,KAAa;IACxD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;AACxF,CAAC;AAED,SAAS,GAAG,CAAC,KAAc;IACzB,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC;QACtE,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;IACvC,CAAC;AACH,CAAC;AAED,SAAS,KAAK,CAAC,KAAc,EAAE,IAAY;IACzC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,GAAG,oBAAoB,EAAE,CAAC;QAC5G,MAAM,IAAI,KAAK,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;IACrC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAgB,EAAE,OAAe,EAAE,IAAY;IAC7E,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO;IAC7B,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;IACpE,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,oBAAoB,CAAC,CAAC;IAChD,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM,IAAI,OAAO,CAAC,MAAM,KAAK,WAAW;QAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAC3G,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,oBAAoB,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;IACrF,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,kBAAkB,EAAE,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC,CAAC;IAClF,IAAI,OAAO,KAAK,SAAS,GAAG,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACjF,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,aAAa,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;IAChD,IAAI,OAAO,OAAO,CAAC,SAAS,KAAK,SAAS,IAAI,CAAC,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,GAAG,KAAK,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACrG,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,qBAAqB,CAAC,CAAC;IAClD,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,kBAAkB,EAAE,IAAI,CAAC,CAAC;IAChD,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,KAAK,IAAI,IAAI,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,KAAK,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;IACzH,KAAK,MAAM,EAAE,IAAI,OAAO,CAAC,MAAM;QAAE,KAAK,CAAC,EAAE,EAAE,iBAAiB,CAAC,CAAC;IAC9D,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;IACpC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,OAAO,SAAS,CAAC,MAAM,KAAK,QAAQ;QAC5D,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;IAC9G,OAAO,CAAC,SAAS,CAAC,SAAS,EAAE,sBAAsB,CAAC,CAAC;IACrD,IAAI,OAAO,SAAS,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAC1J,KAAK,CAAC,SAAS,CAAC,MAAM,EAAE,kBAAkB,EAAE,IAAI,CAAC,CAAC;IAClD,IAAI,WAAW,GAAG,CAAC,CAAC,CAAC;IACrB,KAAK,MAAM,KAAK,IAAI,SAAS,CAAC,MAAM,EAAE,CAAC;QACrC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QACjE,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,qBAAqB,EAAE,WAAW,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC;QACjF,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,wBAAwB,EAAE,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC;QACzF,OAAO,CAAC,KAAK,CAAC,SAAS,EAAE,sBAAsB,EAAE,WAAW,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;QAC3E,WAAW,GAAG,GAAG,CAAC;IACpB,CAAC;IACD,qBAAqB,CAAC,SAAS,CAAC,CAAC;IACjC,IAAI,SAAS,CAAC,MAAM,KAAK,OAAO,IAAI,SAAS,CAAC,MAAM,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;IACxH,IAAI,OAAO,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;QAC1B,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;QACtE,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,EAAE,CAAC,CAAC,CAAC;QACtD,qBAAqB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC;AACH,CAAC;AAED,SAAS,qBAAqB,CAAC,SAAkC;IAC/D,IAAI,OAAO,SAAS,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC;QACpG,CAAC,SAAS,CAAC,MAAM,KAAK,OAAO;YAC3B,CAAC,CAAC,OAAO,SAAS,CAAC,IAAI,KAAK,QAAQ,IAAI,SAAS,CAAC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,aAAa;YACpF,CAAC,CAAC,SAAS,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAC5C,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,QAAiB;IACzC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,OAAO,KAAK,CAAC,IAAI,OAAO,QAAQ,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QACxF,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,CAAC,QAAQ,CAAC,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC;IAC1C,OAAO,CAAC,QAAQ,CAAC,YAAY,EAAE,eAAe,CAAC,CAAC;IAChD,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;IAC9D,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC;IACpD,IAAI,OAAO,QAAQ,CAAC,aAAa,KAAK,QAAQ,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;QAC7G,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;IACrD,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,OAAO,QAAQ,CAAC,IAAI,CAAC,SAAS,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;IACpH,KAAK,MAAM,KAAK,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,EAAE,CAAC;QACxC,MAAM,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAChC,IAAI,EAAE,KAAK,IAAI,IAAI,CAAC,OAAO,EAAE,KAAK,QAAQ,IAAI,CAAC,EAAE,CAAC,MAAM,IAAI,EAAE,CAAC,MAAM,GAAG,GAAG,CAAC,EAAE,CAAC;YAC7E,MAAM,IAAI,KAAK,CAAC,gBAAgB,KAAK,EAAE,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC;IACD,IAAI,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,IAAI,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QAC5G,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,CAAC,OAAO,GAAG,IAAI,EAAE,YAAY,EAAE,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IACvD,eAAe,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IACjD,KAAK,CAAC,QAAQ,CAAC,UAAU,EAAE,YAAY,EAAE,OAAO,GAAG,IAAI,CAAC,CAAC;IACzD,IAAI,eAAe,GAAG,CAAC,CAAC;IACxB,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;QACvC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;QAC1D,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,EAAE,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC;QAC5D,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,wBAAwB,EAAE,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC;QAClF,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,sBAAsB,EAAE,KAAK,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;QAChF,IAAI,GAAG,GAAG,OAAO,GAAG,KAAK,GAAG,eAAe;YAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;QACpG,eAAe,GAAG,GAAG,GAAG,OAAO,GAAG,GAAG,CAAC;QACtC,IAAI,OAAO,IAAI,CAAC,GAAG,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,aAAa;YAC5F,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC7C,CAAC;IACD,IAAI,QAAQ,CAAC,SAAS,KAAK,EAAE,IAAI,QAAQ,CAAC,UAAU,KAAK,EAAE,EAAE,CAAC;QAC5D,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;IACnF,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,CAAC,mBAAmB,EAAE,mBAAmB,CAAC,EAAE,CAAC;QAC/D,IAAI,QAAQ,CAAC,KAAK,CAAC,KAAK,SAAS;YAAE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC;IACpF,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,OAAO,QAAQ,CAAC,MAAM,CAAC,OAAO,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;IAClH,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IACjD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAChD,MAAM,MAAM,GAAG,CAAC,SAAS,EAAE,eAAe,EAAE,aAAa,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC;IAC/H,IAAI,OAAO,QAAQ,CAAC,MAAM,CAAC,KAAK,KAAK,QAAQ;QAAE,QAAQ,CAAC,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7G,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,cAAc,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACrD,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAChD,KAAK,CAAC,QAAQ,CAAC,cAAc,EAAE,qBAAqB,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACrE,KAAK,CAAC,QAAQ,CAAC,UAAU,EAAE,YAAY,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;IAC5D,KAAK,CAAC,QAAQ,CAAC,QAAQ,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;IAC1C,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;IAC3F,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;IACzE,KAAK,MAAM,KAAK,IAAI,CAAC,eAAe,EAAE,eAAe,EAAE,WAAW,EAAE,WAAW,CAAC,EAAE,CAAC;QACjF,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACrC,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;YACzE,MAAM,IAAI,KAAK,CAAC,yBAAyB,KAAK,EAAE,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;IACnC,KAAK,MAAM,QAAQ,IAAI,QAAQ,CAAC,cAAc,EAAE,CAAC;QAC/C,GAAG,CAAC,QAAQ,CAAC,CAAC;QACd,IAAI,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAC5E,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACzB,CAAC;IACD,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;IACpC,IAAI,iBAAiB,GAAG,CAAC,CAAC;IAC1B,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;QACpC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;QACvD,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACf,IAAI,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;QACzG,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACzB,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,aAAa,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;QAC5D,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;QAC/D,MAAM,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,UAAU,EAAE,mBAAmB,EAAE,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;QACxF,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,IAAI,KAAK,CAAC,MAAM,KAAK,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;QACnG,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,IAAI,UAAU,KAAK,KAAK,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC;YACjE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAC9C,CAAC;QACD,iBAAiB,IAAI,KAAK,GAAG,MAAM,GAAG,CAAC,CAAC;QACxC,IAAI,iBAAiB,GAAG,MAAM,CAAC,YAAY;YAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAC3G,CAAC;IACD,KAAK,MAAM,SAAS,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;QAC5C,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;QAC/D,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QACnB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAC9F,IAAI,SAAS,CAAC,IAAI,KAAK,KAAK,IAAI,SAAS,CAAC,IAAI,KAAK,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;QACtG,KAAK,MAAM,KAAK,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,GAAG,CAAC,EAAE,CAAC;YACzJ,MAAM,UAAU,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;YACpC,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,UAAU,EAAE,CAAC;gBACxG,MAAM,IAAI,KAAK,CAAC,qBAAqB,KAAK,EAAE,CAAC,CAAC;YAChD,CAAC;QACH,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,cAAc,EAAE,WAAW,EAAE,YAAY,CAAC,EAAE,CAAC;YAClG,MAAM,UAAU,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;YACpC,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,GAAG,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,KAAK,EAAE,CAAC,CAAC;QACvG,CAAC;IACH,CAAC;AACH,CAAC;AAED,8FAA8F;AAC9F,MAAM,UAAU,WAAW,CAAC,MAAe;IACzC,IAAI,CAAC,CAAC,MAAM,YAAY,WAAW,CAAC,IAAI,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;QAC9E,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACvD,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC;IAClC,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,MAAM,YAAY,GAAG,CAAC,KAAa,EAAE,EAAE;QACrC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,IAAI,CAAC,UAAU,GAAG,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;IAC7F,CAAC,CAAC;IACF,MAAM,GAAG,GAAG,GAAG,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IACtG,IAAI,GAAG,EAAE,KAAK,UAAU;QAAE,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;IACrF,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,EAAE,EAAE,iBAAiB,EAAE,CAAC,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC;IAClF,YAAY,CAAC,cAAc,CAAC,CAAC;IAC7B,MAAM,QAAQ,GAAY,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC;IAClG,MAAM,IAAI,cAAc,CAAC;IACzB,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAC3B,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC;IACnD,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,EAAE,EAAE,oBAAoB,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC;IACxE,IAAI,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,GAAG,EAAE,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAC1G,IAAI,QAAQ,CAAC,IAAI,IAAI,YAAY,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC1F,MAAM,KAAK,GAAG,EAAE,CAAC;IACjB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAE,CAAC;IACvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,YAAY,CAAC,EAAE,CAAC,CAAC;QACjB,MAAM,KAAK,GAAG,GAAG,EAAE,CAAC;QACpB,IAAI,KAAK,IAAI,SAAS,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;QAC9F,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAChB,MAAM,UAAU,GAAG,GAAG,EAAE,CAAC;QACzB,MAAM,UAAU,GAAG,GAAG,EAAE,CAAC;QACzB,MAAM,cAAc,GAAG,GAAG,EAAE,CAAC;QAC7B,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAChD,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACxC,MAAM,cAAc,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACjD,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;QACpD,MAAM,IAAI,CAAC,CAAC;QACZ,IAAI,cAAc,GAAG,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;QACvE,YAAY,CAAC,UAAU,CAAC,CAAC;QACzB,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;QACrE,MAAM,IAAI,UAAU,CAAC;QACrB,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,cAAc,EAAE,UAAU,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC;IACzG,CAAC;IACD,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,GAAG,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;IACzF,IAAI,UAAU,KAAK,IAAI,CAAC,UAAU,GAAG,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IAC9F,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE;QACzC,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;QAC/D,MAAM,IAAI,KAAK,CAAC,UAAU,CAAC;QAC3B,OAAO,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,CAAC;IAC7B,CAAC,CAAC,CAAC;IACH,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;AACrC,CAAC;AAED,6FAA6F;AAC7F,MAAM,UAAU,UAAU,CAAC,KAA4C,EAAE,OAAe,EAAE,IAAY;IACpG,MAAM,KAAK,GAAG,EAAE,CAAC;IACjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;QAC9B,IAAI,IAAI,GAAG,EAAE,CAAC;QACd,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,EAAE,CAAC,EAAE,EAAE,CAAC;YACjC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,GAAG,OAAO,GAAG,CAAC,CAAC,CAAC;YACpC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,KAAK,CAAC;gBAAE,SAAS;YACxC,IAAI,IAAI,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC;QAC7E,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC","sourcesContent":["import type { FrameMetadata, HistoryMetadata, SelectionText, TerminalCell, TerminalFrame } from \"./wire-types.js\";\nimport { isRecord } from \"./validation.js\";\n\n// Binary validation is deliberately independent of the GPU and the transport.\nexport const LIMITS = Object.freeze({\n commandBytes: 64 * 1024,\n frameBytes: 96 * 1024 * 1024,\n metadataBytes: 8 * 1024 * 1024,\n cells: 262144,\n images: 4096,\n placements: 16384,\n textureBytes: 256 * 1024 * 1024,\n});\n\nconst utf8 = new TextDecoder(\"utf-8\", { fatal: true });\nconst utf8Encoder = new TextEncoder();\n\nexport function assertCommandSize(command: unknown): void {\n if (utf8Encoder.encode(JSON.stringify(command)).byteLength > LIMITS.commandBytes)\n throw new RangeError(\"Terminal input exceeds the 64 KiB message limit. Send a smaller amount of text.\");\n}\n\nfunction integer(value: unknown, name: string, min = 0, max = Number.MAX_SAFE_INTEGER): number {\n if (typeof value !== \"number\" || !Number.isSafeInteger(value) || value < min || value > max) {\n throw new Error(`Invalid ${name}: ${String(value)}`);\n }\n return value;\n}\n\nfunction array(value: unknown, name: string, limit: number): asserts value is unknown[] {\n if (!Array.isArray(value) || value.length > limit) throw new Error(`Invalid ${name}`);\n}\n\nfunction key(value: unknown): asserts value is string {\n if (typeof value !== \"string\" || !value.length || value.length > 1024) {\n throw new Error(\"Invalid image key\");\n }\n}\n\nfunction rowId(value: unknown, name: string): asserts value is string {\n if (typeof value !== \"string\" || !/^[1-9][0-9]{0,18}$/u.test(value) || BigInt(value) > 9223372036854775807n) {\n throw new Error(`Invalid ${name}`);\n }\n}\n\nexport function validateHistory(history: unknown, columns: number, rows: number): asserts history is HistoryMetadata | null {\n if (history === null) return;\n if (!isRecord(history)) throw new Error(\"Missing history metadata\");\n rowId(history.generation, \"history generation\");\n if (history.buffer !== \"main\" && history.buffer !== \"alternate\") throw new Error(\"Invalid history buffer\");\n const totalRows = integer(history.totalRows, \"history total rows\", rows, 2147483647);\n const liveTop = integer(history.liveTop, \"history live top\", 0, totalRows - rows);\n if (liveTop !== totalRows - rows) throw new Error(\"Inconsistent history extent\");\n integer(history.top, \"history top\", 0, liveTop);\n if (typeof history.following !== \"boolean\" || (history.following && history.top !== history.liveTop)) {\n throw new Error(\"Invalid history following state\");\n }\n integer(history.requestId, \"viewport request id\");\n array(history.rowIds, \"viewport row ids\", rows);\n if (history.rowIds.length !== rows || new Set(history.rowIds).size !== rows) throw new Error(\"Invalid viewport row ids\");\n for (const id of history.rowIds) rowId(id, \"viewport row id\");\n const selection = history.selection;\n if (!isRecord(selection) || typeof selection.status !== \"string\" ||\n ![\"none\", \"valid\", \"invalidated\"].includes(selection.status)) throw new Error(\"Invalid selection status\");\n integer(selection.requestId, \"selection request id\");\n if (typeof selection.mode !== \"string\" || ![\"character\", \"word\", \"line\", \"rectangle\"].includes(selection.mode)) throw new Error(\"Invalid selection mode\");\n array(selection.ranges, \"selection ranges\", rows);\n let previousRow = -1;\n for (const range of selection.ranges) {\n if (!isRecord(range)) throw new Error(\"Invalid selection range\");\n const row = integer(range.row, \"selection range row\", previousRow + 1, rows - 1);\n const startColumn = integer(range.startColumn, \"selection start column\", 0, columns - 1);\n integer(range.endColumn, \"selection end column\", startColumn + 1, columns);\n previousRow = row;\n }\n validateSelectionText(selection);\n if (selection.status !== \"valid\" && selection.ranges.length) throw new Error(\"Inactive selection has highlight ranges\");\n if (history.copy !== null) {\n if (!isRecord(history.copy)) throw new Error(\"Missing copy metadata\");\n integer(history.copy.requestId, \"copy request id\", 1);\n validateSelectionText(history.copy);\n }\n}\n\nfunction validateSelectionText(selection: Record<string, unknown>): asserts selection is Record<string, unknown> & SelectionText {\n if (typeof selection.status !== \"string\" || ![\"none\", \"valid\", \"invalidated\"].includes(selection.status) ||\n (selection.status === \"valid\"\n ? typeof selection.text !== \"string\" || selection.text.length > LIMITS.metadataBytes\n : selection.text !== null)) {\n throw new Error(\"Invalid selection text\");\n }\n}\n\nfunction validateMetadata(metadata: unknown): asserts metadata is FrameMetadata {\n if (!isRecord(metadata) || metadata.version !== 1 || typeof metadata.full !== \"boolean\") {\n throw new Error(\"Unsupported frame metadata version\");\n }\n integer(metadata.revision, \"revision\", 1);\n integer(metadata.baseRevision, \"base revision\");\n const columns = integer(metadata.columns, \"columns\", 1, 1024);\n const rows = integer(metadata.rows, \"rows\", 1, 512);\n if (typeof metadata.mouseTracking !== \"number\" || ![0, 9, 1000, 1002, 1003].includes(metadata.mouseTracking)) {\n throw new Error(\"Unsupported mouse tracking mode\");\n }\n if (!isRecord(metadata.peer) || typeof metadata.peer.isPrimary !== \"boolean\") throw new Error(\"Invalid peer state\");\n for (const field of [\"id\", \"primaryId\"]) {\n const id = metadata.peer[field];\n if (id !== null && (typeof id !== \"string\" || !id.length || id.length > 256)) {\n throw new Error(`Invalid peer ${field}`);\n }\n }\n if (metadata.peer.id !== null && metadata.peer.isPrimary !== (metadata.peer.id === metadata.peer.primaryId)) {\n throw new Error(\"Inconsistent primary peer state\");\n }\n integer(columns * rows, \"cell count\", 1, LIMITS.cells);\n validateHistory(metadata.history, columns, rows);\n array(metadata.hyperlinks, \"hyperlinks\", columns * rows);\n let previousLinkEnd = 0;\n for (const link of metadata.hyperlinks) {\n if (!isRecord(link)) throw new Error(\"Invalid hyperlink\");\n const row = integer(link.row, \"hyperlink row\", 0, rows - 1);\n const start = integer(link.startColumn, \"hyperlink start column\", 0, columns - 1);\n const end = integer(link.endColumn, \"hyperlink end column\", start + 1, columns);\n if (row * columns + start < previousLinkEnd) throw new Error(\"Unordered or overlapping hyperlinks\");\n previousLinkEnd = row * columns + end;\n if (typeof link.uri !== \"string\" || !link.uri.length || link.uri.length > LIMITS.metadataBytes)\n throw new Error(\"Invalid hyperlink URI\");\n }\n if (metadata.cellWidth !== 10 || metadata.cellHeight !== 20) {\n throw new Error(\"This spike requires server geometry of 10 × 20 logical pixels\");\n }\n for (const field of [\"defaultBackground\", \"defaultForeground\"]) {\n if (metadata[field] !== undefined) integer(metadata[field], field, 0, 0xffffffff);\n }\n if (!isRecord(metadata.cursor) || typeof metadata.cursor.visible !== \"boolean\") throw new Error(\"Invalid cursor\");\n integer(metadata.cursor.x, \"cursor x\", -1, 1024);\n integer(metadata.cursor.y, \"cursor y\", -1, 512);\n const shapes = [\"Default\", \"BlinkingBlock\", \"SteadyBlock\", \"BlinkingUnderline\", \"SteadyUnderline\", \"BlinkingBar\", \"SteadyBar\"];\n if (typeof metadata.cursor.shape === \"string\") metadata.cursor.shape = shapes.indexOf(metadata.cursor.shape);\n integer(metadata.cursor.shape, \"cursor shape\", 0, 6);\n array(metadata.images, \"images\", LIMITS.images);\n array(metadata.retainedImages, \"retained image keys\", LIMITS.images);\n array(metadata.placements, \"placements\", LIMITS.placements);\n array(metadata.warnings, \"warnings\", 256);\n if (metadata.warnings.some(w => typeof w !== \"string\")) throw new Error(\"Invalid warning\");\n if (!isRecord(metadata.stats)) throw new Error(\"Invalid server metrics\");\n for (const field of [\"workloadBytes\", \"outputBatches\", \"captureMs\", \"elapsedMs\"]) {\n const metric = metadata.stats[field];\n if (typeof metric !== \"number\" || !Number.isFinite(metric) || metric < 0) {\n throw new Error(`Invalid server metric ${field}`);\n }\n }\n const retained = new Set<string>();\n for (const imageKey of metadata.retainedImages) {\n key(imageKey);\n if (retained.has(imageKey)) throw new Error(\"Duplicate retained image key\");\n retained.add(imageKey);\n }\n const imageKeys = new Set<string>();\n let decodedImageBytes = 0;\n for (const image of metadata.images) {\n if (!isRecord(image)) throw new Error(\"Invalid image\");\n key(image.key);\n if (imageKeys.has(image.key) || !retained.has(image.key)) throw new Error(\"Inconsistent new image keys\");\n imageKeys.add(image.key);\n const width = integer(image.width, \"image width\", 1, 16384);\n const height = integer(image.height, \"image height\", 1, 16384);\n const byteLength = integer(image.byteLength, \"image byte length\", 1, LIMITS.frameBytes);\n if (image.format !== \"rgba\" && image.format !== \"png\") throw new Error(\"Unsupported image format\");\n if (image.format === \"rgba\" && byteLength !== width * height * 4) {\n throw new Error(\"RGBA image size mismatch\");\n }\n decodedImageBytes += width * height * 4;\n if (decodedImageBytes > LIMITS.textureBytes) throw new Error(\"New images exceed decoded texture budget\");\n }\n for (const placement of metadata.placements) {\n if (!isRecord(placement)) throw new Error(\"Invalid placement\");\n key(placement.key);\n if (!retained.has(placement.key)) throw new Error(\"Placement references an unretained image\");\n if (placement.kind !== \"kgp\" && placement.kind !== \"sixel\") throw new Error(\"Invalid placement kind\");\n for (const field of [\"x\", \"y\", \"width\", \"height\", \"sourceX\", \"sourceY\", \"sourceWidth\", \"sourceHeight\", \"clipX\", \"clipY\", \"clipWidth\", \"clipHeight\", \"z\"]) {\n const coordinate = placement[field];\n if (typeof coordinate !== \"number\" || !Number.isFinite(coordinate) || Math.abs(coordinate) > 2147483648) {\n throw new Error(`Invalid placement ${field}`);\n }\n }\n for (const field of [\"width\", \"height\", \"sourceWidth\", \"sourceHeight\", \"clipWidth\", \"clipHeight\"]) {\n const coordinate = placement[field];\n if (typeof coordinate !== \"number\" || coordinate < 0) throw new Error(`Negative placement ${field}`);\n }\n }\n}\n\n/** Decode one complete, experimental HWT1 message, checking every boundary before reading. */\nexport function decodeFrame(buffer: unknown): TerminalFrame {\n if (!(buffer instanceof ArrayBuffer) || buffer.byteLength > LIMITS.frameBytes) {\n throw new Error(\"Invalid or oversized binary frame\");\n }\n const view = new DataView(buffer);\n let offset = 0;\n const requireBytes = (count: number) => {\n if (count < 0 || count > view.byteLength - offset) throw new Error(\"Truncated HWT1 frame\");\n };\n const u32 = () => { requireBytes(4); const n = view.getUint32(offset, true); offset += 4; return n; };\n if (u32() !== 0x31545748) throw new Error(\"Unsupported frame magic (expected HWT1)\");\n const metadataLength = integer(u32(), \"metadata length\", 2, LIMITS.metadataBytes);\n requireBytes(metadataLength);\n const metadata: unknown = JSON.parse(utf8.decode(new Uint8Array(buffer, offset, metadataLength)));\n offset += metadataLength;\n validateMetadata(metadata);\n const cellCount = metadata.columns * metadata.rows;\n const changedCount = integer(u32(), \"changed cell count\", 0, cellCount);\n if (changedCount > Math.floor((view.byteLength - offset) / 22)) throw new Error(\"Truncated cell records\");\n if (metadata.full && changedCount !== cellCount) throw new Error(\"Incomplete full frame\");\n const cells = [];\n const seen = new Set();\n for (let i = 0; i < changedCount; i++) {\n requireBytes(22);\n const index = u32();\n if (index >= cellCount || seen.has(index)) throw new Error(\"Invalid or duplicate cell index\");\n seen.add(index);\n const foreground = u32();\n const background = u32();\n const underlineColor = u32();\n const attributes = view.getUint16(offset, true);\n const width = view.getUint8(offset + 2);\n const underlineStyle = view.getUint8(offset + 3);\n const textLength = view.getUint16(offset + 4, true);\n offset += 6;\n if (underlineStyle > 5) throw new Error(\"Unsupported underline style\");\n requireBytes(textLength);\n const text = utf8.decode(new Uint8Array(buffer, offset, textLength));\n offset += textLength;\n cells.push({ index, foreground, background, underlineColor, attributes, width, underlineStyle, text });\n }\n const imageBytes = metadata.images.reduce((total, image) => total + image.byteLength, 0);\n if (imageBytes !== view.byteLength - offset) throw new Error(\"Image payload length mismatch\");\n const images = metadata.images.map(image => {\n const bytes = new Uint8Array(buffer, offset, image.byteLength);\n offset += image.byteLength;\n return { ...image, bytes };\n });\n return { metadata, cells, images };\n}\n\n/** Mirror text, not ANSI; continuation cells are already represented by their lead glyph. */\nexport function screenText(cells: readonly (TerminalCell | undefined)[], columns: number, rows: number): string {\n const lines = [];\n for (let y = 0; y < rows; y++) {\n let line = \"\";\n for (let x = 0; x < columns; x++) {\n const cell = cells[y * columns + x];\n if (!cell || cell.width === 0) continue;\n line += cell.attributes & 64 ? \" \".repeat(cell.width) : (cell.text || \" \");\n }\n lines.push(line.replace(/ +$/u, \"\"));\n }\n return lines.join(\"\\n\");\n}\n"]}
@@ -123,7 +123,7 @@ async function drawFrame() {
123
123
  type: "geometry", columns: metadata.columns, rows: metadata.rows,
124
124
  cellWidth: metadata.cellWidth, cellHeight: metadata.cellHeight,
125
125
  mouseTracking: metadata.mouseTracking, peer: metadata.peer,
126
- history: metadata.history, revision: frame.revision, text
126
+ history: metadata.history, revision: frame.revision, text, hyperlinks: metadata.hyperlinks
127
127
  });
128
128
  send({ type: "ack", revision: frame.revision });
129
129
  emitStats(text);