@aurigax-ai/ghostty-web 0.3.6 → 0.3.7
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/lib/renderer.ts +3 -30
- package/lib/terminal.ts +1 -49
- package/lib/webgl-renderer.ts +1 -1
- package/package.json +1 -1
package/lib/renderer.ts
CHANGED
|
@@ -268,8 +268,6 @@ export abstract class TerminalRenderer {
|
|
|
268
268
|
private readonly highlightRows = new Set<number>();
|
|
269
269
|
protected highlightColors: SearchHighlightColors = { match: '#5c6266', active: '#538bb5' };
|
|
270
270
|
|
|
271
|
-
protected hoveredHyperlinkId = 0;
|
|
272
|
-
private previousHoveredHyperlinkId = 0;
|
|
273
271
|
protected hoveredLinkRange: LinkRange | null = null;
|
|
274
272
|
private previousHoveredLinkRange: LinkRange | null = null;
|
|
275
273
|
|
|
@@ -385,22 +383,6 @@ export abstract class TerminalRenderer {
|
|
|
385
383
|
};
|
|
386
384
|
|
|
387
385
|
const hyperlinkRows = new Set<number>();
|
|
388
|
-
if (this.hoveredHyperlinkId !== this.previousHoveredHyperlinkId) {
|
|
389
|
-
for (let y = 0; y < dims.rows; y++) {
|
|
390
|
-
const line = lineAt(y);
|
|
391
|
-
if (!line) continue;
|
|
392
|
-
for (const cell of line) {
|
|
393
|
-
if (
|
|
394
|
-
cell.hyperlink_id === this.hoveredHyperlinkId ||
|
|
395
|
-
cell.hyperlink_id === this.previousHoveredHyperlinkId
|
|
396
|
-
) {
|
|
397
|
-
hyperlinkRows.add(y);
|
|
398
|
-
break;
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
this.previousHoveredHyperlinkId = this.hoveredHyperlinkId;
|
|
403
|
-
}
|
|
404
386
|
if (!sameRange(this.hoveredLinkRange, this.previousHoveredLinkRange)) {
|
|
405
387
|
for (const range of [this.previousHoveredLinkRange, this.hoveredLinkRange]) {
|
|
406
388
|
if (!range) continue;
|
|
@@ -511,9 +493,8 @@ export abstract class TerminalRenderer {
|
|
|
511
493
|
/** Called when the search highlight colors change. */
|
|
512
494
|
protected searchColorsChanged(): void {}
|
|
513
495
|
|
|
514
|
-
/** Whether the cell has a hovered link under it (OSC 8
|
|
515
|
-
protected linkHovered(
|
|
516
|
-
if (cell.hyperlink_id > 0 && cell.hyperlink_id === this.hoveredHyperlinkId) return true;
|
|
496
|
+
/** Whether the cell has a hovered link under it (OSC 8 or detected URL range). */
|
|
497
|
+
protected linkHovered(x: number, y: number): boolean {
|
|
517
498
|
const range = this.hoveredLinkRange;
|
|
518
499
|
if (!range) return false;
|
|
519
500
|
return (
|
|
@@ -676,14 +657,6 @@ export abstract class TerminalRenderer {
|
|
|
676
657
|
this.selectionManager = manager;
|
|
677
658
|
}
|
|
678
659
|
|
|
679
|
-
public setHoveredHyperlinkId(hyperlinkId: number): void {
|
|
680
|
-
this.hoveredHyperlinkId = hyperlinkId;
|
|
681
|
-
}
|
|
682
|
-
|
|
683
|
-
public getHoveredHyperlinkId(): number {
|
|
684
|
-
return this.hoveredHyperlinkId;
|
|
685
|
-
}
|
|
686
|
-
|
|
687
660
|
/** Set the hovered range of a detected URL, or null to clear it. */
|
|
688
661
|
public setHoveredLinkRange(range: LinkRange | null): void {
|
|
689
662
|
this.hoveredLinkRange = range;
|
|
@@ -1006,7 +979,7 @@ export class CanvasRenderer extends TerminalRenderer {
|
|
|
1006
979
|
private renderDecorations(cell: GhosttyCell, x: number, y: number, color: string): void {
|
|
1007
980
|
const underline = cell.flags & CellFlags.UNDERLINE;
|
|
1008
981
|
const strike = cell.flags & CellFlags.STRIKETHROUGH;
|
|
1009
|
-
const link =
|
|
982
|
+
const link = this.hoveredLinkRange && this.linkHovered(x, y);
|
|
1010
983
|
if (!underline && !strike && !link) return;
|
|
1011
984
|
const cellX = x * this.metrics.width;
|
|
1012
985
|
const cellY = y * this.metrics.height;
|
package/lib/terminal.ts
CHANGED
|
@@ -660,10 +660,8 @@ export class Terminal implements ITerminalCore {
|
|
|
660
660
|
/** Disposes the current renderer and draws with `renderer` from now on, in its state. */
|
|
661
661
|
private installRenderer(renderer: TerminalRenderer): void {
|
|
662
662
|
const old = this.renderer!;
|
|
663
|
-
const hoveredLink = old.getHoveredHyperlinkId();
|
|
664
663
|
old.dispose();
|
|
665
664
|
renderer.onNeedsFrame = () => this.requestFrame();
|
|
666
|
-
renderer.setHoveredHyperlinkId(hoveredLink);
|
|
667
665
|
renderer.setFocused(this.focused);
|
|
668
666
|
renderer.setSearchHighlights(this.searchHighlights.list, this.searchHighlights.colors);
|
|
669
667
|
if (this.selectionManager) {
|
|
@@ -1545,47 +1543,7 @@ export class Terminal implements ITerminalCore {
|
|
|
1545
1543
|
const x = Math.floor((e.clientX - rect.left) / this.renderer.charWidth);
|
|
1546
1544
|
const y = Math.floor((e.clientY - rect.top) / this.renderer.charHeight);
|
|
1547
1545
|
|
|
1548
|
-
|
|
1549
|
-
// Must account for viewportY (scrollback position)
|
|
1550
|
-
const viewportRow = y; // Row in the viewport (0 to rows-1)
|
|
1551
|
-
let hyperlinkId = 0;
|
|
1552
|
-
|
|
1553
|
-
// When scrolled, fetch from scrollback or screen based on position
|
|
1554
|
-
// NOTE: viewportY may be fractional during smooth scrolling. The renderer
|
|
1555
|
-
// uses Math.floor(viewportY) when mapping viewport rows to scrollback vs
|
|
1556
|
-
// screen; we mirror that logic here so link hit-testing matches what the
|
|
1557
|
-
// user sees on screen.
|
|
1558
|
-
let line: GhosttyCell[] | null = null;
|
|
1559
|
-
const rawViewportY = this.getViewportY();
|
|
1560
|
-
const viewportY = Math.max(0, Math.floor(rawViewportY));
|
|
1561
|
-
if (viewportY > 0) {
|
|
1562
|
-
const scrollbackLength = this.wasmTerm.getScrollbackLength();
|
|
1563
|
-
if (viewportRow < viewportY) {
|
|
1564
|
-
// Mouse is over scrollback content
|
|
1565
|
-
const scrollbackOffset = scrollbackLength - viewportY + viewportRow;
|
|
1566
|
-
line = this.wasmTerm.getScrollbackLine(scrollbackOffset);
|
|
1567
|
-
} else {
|
|
1568
|
-
// Mouse is over screen content (bottom part of viewport)
|
|
1569
|
-
const screenRow = viewportRow - viewportY;
|
|
1570
|
-
line = this.wasmTerm.getLine(screenRow);
|
|
1571
|
-
}
|
|
1572
|
-
} else {
|
|
1573
|
-
// At bottom - just use screen buffer
|
|
1574
|
-
line = this.wasmTerm.getLine(viewportRow);
|
|
1575
|
-
}
|
|
1576
|
-
|
|
1577
|
-
if (line && x >= 0 && x < line.length) {
|
|
1578
|
-
hyperlinkId = line[x].hyperlink_id;
|
|
1579
|
-
}
|
|
1580
|
-
|
|
1581
|
-
// Update renderer for underline rendering
|
|
1582
|
-
const previousHyperlinkId = (this.renderer as any).hoveredHyperlinkId || 0;
|
|
1583
|
-
if (hyperlinkId !== previousHyperlinkId) {
|
|
1584
|
-
this.renderer.setHoveredHyperlinkId(hyperlinkId);
|
|
1585
|
-
|
|
1586
|
-
// The 60fps render loop will pick up the change automatically
|
|
1587
|
-
// No need to force a render - this keeps performance smooth
|
|
1588
|
-
}
|
|
1546
|
+
const viewportRow = y;
|
|
1589
1547
|
|
|
1590
1548
|
// Check if there's a link at this position (for click handling and cursor)
|
|
1591
1549
|
// Buffer API expects absolute buffer coordinates (including scrollback)
|
|
@@ -1678,12 +1636,6 @@ export class Terminal implements ITerminalCore {
|
|
|
1678
1636
|
this.wake();
|
|
1679
1637
|
// Clear hyperlink underline
|
|
1680
1638
|
if (this.renderer && this.wasmTerm) {
|
|
1681
|
-
const previousHyperlinkId = (this.renderer as any).hoveredHyperlinkId || 0;
|
|
1682
|
-
if (previousHyperlinkId > 0) {
|
|
1683
|
-
this.renderer.setHoveredHyperlinkId(0);
|
|
1684
|
-
|
|
1685
|
-
// The 60fps render loop will pick up the change automatically
|
|
1686
|
-
}
|
|
1687
1639
|
// Clear regex link underline
|
|
1688
1640
|
this.renderer.setHoveredLinkRange(null);
|
|
1689
1641
|
}
|
package/lib/webgl-renderer.ts
CHANGED
|
@@ -610,7 +610,7 @@ export class WebglRenderer extends TerminalRenderer {
|
|
|
610
610
|
}
|
|
611
611
|
}
|
|
612
612
|
|
|
613
|
-
const link =
|
|
613
|
+
const link = this.hoveredLinkRange && this.linkHovered(x, y);
|
|
614
614
|
if (link || cell.flags & CellFlags.UNDERLINE) {
|
|
615
615
|
rects[deco1] = left;
|
|
616
616
|
rects[deco1 + 1] = underlineY;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aurigax-ai/ghostty-web",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.7",
|
|
4
4
|
"description": "Ghostty's terminal engine (libghostty-vt) in the browser: WebAssembly build, an xterm.js-shaped API and WebGL and canvas renderers. A hard fork of coder/ghostty-web.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.ts",
|