/** Render plain text with http(s) URLs as clickable links. */ const URL_RE = /https?:\/\/[^\s<>"']+/g function cleanUrl(raw: string): string { return raw.replace(/[!.,;:)]+$/g, '') } export function LinkifiedText({ text, className, linkClassName = 'text-teal-700 underline decoration-teal-400/60 hover:text-teal-900 break-all', }: { text: string className?: string linkClassName?: string }) { if (!text) return null const parts: { key: number; type: 'text' | 'url'; value: string }[] = [] let last = 0 let key = 0 for (const match of text.matchAll(URL_RE)) { const idx = match.index ?? 0 if (idx > last) { parts.push({ key: key++, type: 'text', value: text.slice(last, idx) }) } parts.push({ key: key++, type: 'url', value: match[0] }) last = idx + match[0].length } if (last < text.length) { parts.push({ key: key++, type: 'text', value: text.slice(last) }) } if (parts.length === 0) { return {text} } return ( {parts.map((part) => part.type === 'url' ? ( {part.value} ) : ( {part.value} ), )} ) }