@@ -78,12 +78,76 @@ func getCellHeightFromFd(fd int) int {
7878 return 0
7979}
8080
81- // hyperlink formats a string as a terminal-clickable hyperlink.
81+ // hyperlinkSupported checks if the terminal supports OSC 8 hyperlinks.
82+ func hyperlinkSupported () bool {
83+ term := strings .ToLower (os .Getenv ("TERM" ))
84+
85+ // Terminals known to support OSC 8 hyperlinks
86+ supportedTerms := []string {
87+ "kitty" ,
88+ "ghostty" ,
89+ "wezterm" ,
90+ "alacritty" ,
91+ "foot" ,
92+ "tmux" ,
93+ "screen" ,
94+ }
95+
96+ for _ , supported := range supportedTerms {
97+ if strings .Contains (term , supported ) {
98+ return true
99+ }
100+ }
101+
102+ // Check for specific terminal programs
103+ termProgram := strings .ToLower (os .Getenv ("TERM_PROGRAM" ))
104+ supportedPrograms := []string {
105+ "iterm.app" ,
106+ "hyper" ,
107+ "vscode" ,
108+ "ghostty" ,
109+ "wezterm" ,
110+ }
111+
112+ for _ , supported := range supportedPrograms {
113+ if strings .Contains (termProgram , supported ) {
114+ return true
115+ }
116+ }
117+
118+ // Check for VTE-based terminals (GNOME Terminal, etc.)
119+ if os .Getenv ("VTE_VERSION" ) != "" {
120+ return true
121+ }
122+
123+ // Check for specific environment variables that indicate hyperlink support
124+ if os .Getenv ("KITTY_WINDOW_ID" ) != "" ||
125+ os .Getenv ("GHOSTTY_RESOURCES_DIR" ) != "" ||
126+ os .Getenv ("WEZTERM_EXECUTABLE" ) != "" {
127+ return true
128+ }
129+
130+ return false
131+ }
132+
133+ // hyperlink formats a string as either a terminal-clickable hyperlink or plain text with URL.
82134func hyperlink (url , text string ) string {
83135 if text == "" {
84136 text = url
85137 }
86- return fmt .Sprintf ("\x1b ]8;;%s\x07 %s\x1b ]8;;\x07 " , url , text )
138+
139+ supported := hyperlinkSupported ()
140+
141+ if supported {
142+ // Use OSC 8 hyperlink sequence for supported terminals
143+ return fmt .Sprintf ("\x1b ]8;;%s\x07 %s\x1b ]8;;\x07 " , url , text )
144+ } else {
145+ // Fallback to plain text format for unsupported terminals
146+ if text == url {
147+ return fmt .Sprintf ("<%s>" , url )
148+ }
149+ return fmt .Sprintf ("%s <%s>" , text , url )
150+ }
87151}
88152
89153func decodeQuotedPrintable (s string ) (string , error ) {
@@ -362,8 +426,11 @@ func processBody(rawBody string, inline map[string]string, h1Style, h2Style, bod
362426 } else {
363427 debugKitty ("kitty not detected for src=%s" , src )
364428 }
365-
366- s .ReplaceWithHtml (hyperlink (src , fmt .Sprintf ("\n [Click here to view image: %s] \n " , alt )))
429+ if hyperlinkSupported () {
430+ s .ReplaceWithHtml (hyperlink (src , fmt .Sprintf ("\n [Click here to view image: %s] \n " , alt )))
431+ } else {
432+ s .ReplaceWithHtml (fmt .Sprintf ("\n [Image: %s, %s] \n " , alt , src ))
433+ }
367434 })
368435
369436 text := doc .Text ()
0 commit comments