diff --git a/ui-tui/src/components/markdown.tsx b/ui-tui/src/components/markdown.tsx index d43357b691..5e1063837b 100644 --- a/ui-tui/src/components/markdown.tsx +++ b/ui-tui/src/components/markdown.tsx @@ -1,4 +1,4 @@ -import { Box, Text } from '@hermes/ink' +import { Box, Link, Text } from '@hermes/ink' import { memo, type ReactNode, useMemo } from 'react' import { highlightLine, isHighlightable } from '../lib/syntax.js' @@ -23,10 +23,12 @@ type Fence = { len: number } -const renderLink = (key: number, t: Theme, label: string) => ( - - {label} - +const renderLink = (key: number, t: Theme, label: string, url: string) => ( + + + {label} + + ) const trimBareUrl = (value: string) => { @@ -38,11 +40,17 @@ const trimBareUrl = (value: string) => { } } -const renderAutolink = (key: number, t: Theme, raw: string) => ( - - {raw.replace(/^mailto:/, '')} - -) +const renderAutolink = (key: number, t: Theme, raw: string) => { + const url = raw.startsWith('mailto:') ? raw : raw.includes('@') && !raw.startsWith('http') ? `mailto:${raw}` : raw + + return ( + + + {raw.replace(/^mailto:/, '')} + + + ) +} const indentDepth = (indent: string) => Math.floor(indent.replace(/\t/g, ' ').length / 2) @@ -142,7 +150,7 @@ function MdInline({ t, text }: { t: Theme; text: string }) { ) } else if (m[4] && m[5]) { - parts.push(renderLink(parts.length, t, m[4])) + parts.push(renderLink(parts.length, t, m[4], m[5])) } else if (m[6]) { parts.push(renderAutolink(parts.length, t, m[6])) } else if (m[7]) { diff --git a/ui-tui/src/types/hermes-ink.d.ts b/ui-tui/src/types/hermes-ink.d.ts index 9b2deec35f..051451d419 100644 --- a/ui-tui/src/types/hermes-ink.d.ts +++ b/ui-tui/src/types/hermes-ink.d.ts @@ -63,6 +63,11 @@ declare module '@hermes/ink' { export const Box: React.ComponentType export const AlternateScreen: React.ComponentType export const Ansi: React.ComponentType + export const Link: React.ComponentType<{ + readonly children?: React.ReactNode + readonly fallback?: React.ReactNode + readonly url: string + }> export const NoSelect: React.ComponentType export const ScrollBox: React.ComponentType export const Text: React.ComponentType