import React from "react"; import { Box, Link, Typography } from "@mui/material"; // Tiny, dependency-free markdown renderer for AI suggestions. Handles the subset the prompts emit: // #/##/### headings, **bold**, *italic*, [text](url), and - / * bullet lists. Everything is rendered // as React elements (no dangerouslySetInnerHTML), so there is no HTML-injection surface. export default function Markdown({ text }: { text: string }) { const blocks: React.ReactNode[] = []; const lines = (text ?? "").replace(/\r\n/g, "\n").split("\n"); let list: string[] = []; const flushList = (key: string) => { if (list.length === 0) return; blocks.push( {list.map((li, i) =>
  • {inline(li)}
  • )}
    , ); list = []; }; lines.forEach((raw, i) => { const line = raw.trimEnd(); const bullet = line.match(/^\s*[-*]\s+(.*)$/); if (bullet) { list.push(bullet[1]); return; } flushList(`ul-${i}`); if (!line.trim()) return; const heading = line.match(/^(#{1,3})\s+(.*)$/); if (heading) { const level = heading[1].length; blocks.push( {inline(heading[2])} , ); return; } // A line that is only **bold** reads as a section heading in these prompts. const boldOnly = line.match(/^\*\*(.+)\*\*:?$/); if (boldOnly) { blocks.push({boldOnly[1]}); return; } blocks.push({inline(line)}); }); flushList("ul-end"); return {blocks}; } // Inline **bold**, *italic*, [text](url) → React nodes. function inline(text: string): React.ReactNode[] { const tokens: React.ReactNode[] = []; const rx = /\*\*(.+?)\*\*|\*(.+?)\*|\[([^\]]+)\]\((https?:\/\/[^\s)]+)\)/g; let last = 0; let m: RegExpExecArray | null; let k = 0; while ((m = rx.exec(text)) !== null) { if (m.index > last) tokens.push(text.slice(last, m.index)); if (m[1] !== undefined) tokens.push({m[1]}); else if (m[2] !== undefined) tokens.push({m[2]}); else if (m[3] !== undefined) tokens.push({m[3]}); last = rx.lastIndex; } if (last < text.length) tokens.push(text.slice(last)); return tokens; }