import {Link} from 'react-router-dom'; // **bold** and [text](url) only. No nesting: the link text is plain. const TOKEN = /\*\*([^*\n]+)\*\*|\[([^\]\n]+)\]\(([^)\s]+)\)/g; // An app path (not //host, and no backslash: browsers read /\host as //host), or https. Case-sensitive on purpose. const APP_PATH = /^\/(?![/\\])[^\s\\]*$/; const HTTPS = /^https:\/\/[^\s\\]+$/; /** * @returns {{to: string} | {href: string} | null} null: the url is not safe, so the link stays plain text */ export const safeLink = (url) => { if (APP_PATH.test(url)) return {to: url}; if (HTTPS.test(url)) return {href: url}; return null; }; /** * Hint and news text with **bold** and [text](url). Only React elements, never HTML: React escapes every string. */ export default function HintText({text}) { const parts = []; let last = 0; for (const match of text.matchAll(TOKEN)) { const [whole, bold, label, url] = match; if (match.index > last) parts.push(text.slice(last, match.index)); last = match.index + whole.length; const link = url && safeLink(url); if (bold !== undefined) { parts.push({bold}); } else if (link?.to) { parts.push({label}); } else if (link) { parts.push({label}); } else { parts.push(whole); } } parts.push(text.slice(last)); return <>{parts}; }