[PR #736] [MERGED] fix(renderer): add OSC 8 hyperlink id parameter and onChunks hook for link detection #747

Closed
opened 2026-03-02 23:47:57 +03:00 by kerem · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/anomalyco/opentui/pull/736
Author: @mugnimaestra
Created: 2/24/2026
Status: Merged
Merged: 3/1/2026
Merged by: @kommander

Base: mainHead: fix/osc8-hyperlink-id


📝 Commits (3)

  • 8dd41d7 fix(renderer): add id parameter to OSC 8 hyperlink sequences
  • 71e8d29 feat(code): add onChunks hook and detectLinks helper for link detection
  • 875db41 Merge branch 'main' into fix/osc8-hyperlink-id

📊 Changes

6 files changed (+247 additions, -5 deletions)

View changed files

packages/core/src/lib/detect-links.test.ts (+98 -0)
packages/core/src/lib/detect-links.ts (+56 -0)
📝 packages/core/src/lib/index.ts (+1 -0)
📝 packages/core/src/renderables/Code.ts (+34 -1)
📝 packages/core/src/zig/renderer.zig (+2 -2)
📝 packages/core/src/zig/tests/renderer_test.zig (+56 -2)

📄 Description

Summary

Fixes hyperlinks not working correctly when they wrap across terminal lines, and adds opt-in link detection for tree-sitter rendered code blocks.

Closes #735

Changes

The renderer emitted OSC 8 without the id parameter, so terminals could not identify wrapped link segments as the same hyperlink. Now emits:

\x1b]8;id={linkId};{url}\x1b\\

Links stay open across row boundaries and close naturally when a different link (or no link) is encountered.

The tree-sitter path (CodeRenderable) never set link on TextChunk objects, so OSC 8 was never emitted for code blocks.

Following maintainer feedback, this uses hooks instead of hardcoded scope names:

  • onChunks callback on CodeRenderable — runs after treeSitterToTextChunks, before setStyledText
  • detectLinks() exported helper — scans highlights for URL scopes, sets chunk.link = { url } on matches

Uses content.indexOf() to find chunk positions in original content, handling concealed markdown syntax where visible text length differs from source byte positions.

import { detectLinks } from "@opentui/core"

<code filetype="markdown" onChunks={detectLinks}>
  {content}
</code>

Tests

  • 3334 TS tests pass, 1480 native tests pass
  • Added renderer test for wrapped hyperlinks
  • Added 5 unit tests for detectLinks including concealed text edge case

Known Limitation

Visual hover highlighting covers one row at a time for wrapped links. The OSC 8 spec defines id-based cross-row grouping, but no terminal has been verified to implement it. Cmd/Ctrl+Click works correctly across all rows.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/anomalyco/opentui/pull/736 **Author:** [@mugnimaestra](https://github.com/mugnimaestra) **Created:** 2/24/2026 **Status:** ✅ Merged **Merged:** 3/1/2026 **Merged by:** [@kommander](https://github.com/kommander) **Base:** `main` ← **Head:** `fix/osc8-hyperlink-id` --- ### 📝 Commits (3) - [`8dd41d7`](https://github.com/anomalyco/opentui/commit/8dd41d78e0b92e9220585bc6785d3a457cf25c8d) fix(renderer): add id parameter to OSC 8 hyperlink sequences - [`71e8d29`](https://github.com/anomalyco/opentui/commit/71e8d29a9c74f40330d83ed117d5bcb384317d80) feat(code): add onChunks hook and detectLinks helper for link detection - [`875db41`](https://github.com/anomalyco/opentui/commit/875db412e940d985845376b3bd7775a3a27499e6) Merge branch 'main' into fix/osc8-hyperlink-id ### 📊 Changes **6 files changed** (+247 additions, -5 deletions) <details> <summary>View changed files</summary> ➕ `packages/core/src/lib/detect-links.test.ts` (+98 -0) ➕ `packages/core/src/lib/detect-links.ts` (+56 -0) 📝 `packages/core/src/lib/index.ts` (+1 -0) 📝 `packages/core/src/renderables/Code.ts` (+34 -1) 📝 `packages/core/src/zig/renderer.zig` (+2 -2) 📝 `packages/core/src/zig/tests/renderer_test.zig` (+56 -2) </details> ### 📄 Description ## Summary Fixes hyperlinks not working correctly when they wrap across terminal lines, and adds opt-in link detection for tree-sitter rendered code blocks. Closes #735 ## Changes ### 1. `fix(renderer): add id parameter to OSC 8 hyperlink sequences` The renderer emitted OSC 8 without the `id` parameter, so terminals could not identify wrapped link segments as the same hyperlink. Now emits: ``` \x1b]8;id={linkId};{url}\x1b\\ ``` Links stay open across row boundaries and close naturally when a different link (or no link) is encountered. ### 2. `feat(code): add onChunks hook and detectLinks helper` The tree-sitter path (`CodeRenderable`) never set `link` on `TextChunk` objects, so OSC 8 was never emitted for code blocks. Following [maintainer feedback](https://github.com/anomalyco/opentui/pull/736#issuecomment-3955277832), this uses hooks instead of hardcoded scope names: - **`onChunks`** callback on `CodeRenderable` — runs after `treeSitterToTextChunks`, before `setStyledText` - **`detectLinks()`** exported helper — scans highlights for URL scopes, sets `chunk.link = { url }` on matches Uses `content.indexOf()` to find chunk positions in original content, handling concealed markdown syntax where visible text length differs from source byte positions. ```tsx import { detectLinks } from "@opentui/core" <code filetype="markdown" onChunks={detectLinks}> {content} </code> ``` ## Tests - 3334 TS tests pass, 1480 native tests pass - Added renderer test for wrapped hyperlinks - Added 5 unit tests for `detectLinks` including concealed text edge case ## Known Limitation Visual hover highlighting covers one row at a time for wrapped links. The [OSC 8 spec](https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda) defines `id`-based cross-row grouping, but no terminal has been verified to implement it. Cmd/Ctrl+Click works correctly across all rows. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
kerem 2026-03-02 23:47:57 +03:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/opentui#747
No description provided.