Skip to content

fix(vt): keep OSC 8 hyperlinks when the URL contains semicolons - #950

Open
youdie006 wants to merge 1 commit into
charmbracelet:mainfrom
youdie006:fix/937-osc8-hyperlink-semicolon-url
Open

fix(vt): keep OSC 8 hyperlinks when the URL contains semicolons#950
youdie006 wants to merge 1 commit into
charmbracelet:mainfrom
youdie006:fix/937-osc8-hyperlink-semicolon-url

Conversation

@youdie006

Copy link
Copy Markdown

Summary

Fixes #937.

An OSC 8 hyperlink is silently dropped when its URI contains a semicolon (for example https://example.com/f?a=1;b=2). The link text still renders, but the cells are never given the hyperlink, so it is not clickable.

Root cause

handleHyperlink in vt/osc.go split the payload on every semicolon:

parts := bytes.Split(data, []byte{';'})
if len(parts) != 3 || cmd != 8 { return }

The OSC 8 wire format is 8 ; params ; uri, where only the first two semicolons are field separators -- any later semicolon belongs to the URI. A URI with a semicolon produces four or more parts, so the len(parts) != 3 guard rejects the whole command and the link is discarded.

Fix

Split on only the first two semicolons with bytes.SplitN(data, ';', 3), so the remainder (the URI) keeps its own semicolons. The len(parts) != 3 guard still rejects malformed payloads with fewer than two semicolons, and the reset sequence (8;;) and ordinary links are unaffected.

This is orthogonal to #868: that PR corrects which slot the params and URI are stored in (they are currently exchanged), while this PR fixes the parser dropping semicolon URIs entirely. The two changes compose -- the field mapping is left to #868. The added test asserts the URI survives in either Link.URL or Link.Params, so it passes independently of #868's merge order.

Test

TestHyperlinkURLWithSemicolon drives Emulator.Write with the issue's reproduction and asserts the semicolon URI reaches the cells' link.

  • RED (before fix): link dropped, Link.URL/Link.Params both empty -- FAIL.
  • GREEN (after fix): URI present -- PASS.

Full vt suite passes; gofmt and go vet clean.


AI-assisted: this change was prepared with the help of an AI coding assistant and reviewed by me.

An OSC 8 hyperlink was silently dropped when its URI contained a semicolon
(e.g. https://example.com/f?a=1;b=2). handleHyperlink split the payload on every
semicolon with bytes.Split, but the OSC 8 wire format is '8;params;uri' where
only the first two semicolons are field separators; a URI with a semicolon
produced four or more parts, so the len(parts) != 3 guard rejected the whole
command.

Split on only the first two semicolons with bytes.SplitN(data, ';', 3) so the
URI keeps its own semicolons. The guard still rejects malformed payloads, and
the reset sequence (8;;) and ordinary links are unaffected. Orthogonal to charmbracelet#868
(the params/uri field mapping); the added test is swap-agnostic.

Fixes charmbracelet#937
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

vt: keep OSC 8 links when the URL contains semicolons

1 participant