MarkdownRenderer.tsx (3110B)
1 import ReactMarkdown from "react-markdown"; 2 import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"; 3 import { oneDark } from "react-syntax-highlighter/dist/esm/styles/prism"; 4 5 interface MarkdownRendererProps { 6 content: string; 7 } 8 9 function CodeBlock({ language, children }: { language: string; children: string }) { 10 return ( 11 <SyntaxHighlighter 12 style={oneDark} 13 language={language} 14 PreTag="div" 15 className="rounded-lg text-sm" 16 > 17 {children} 18 </SyntaxHighlighter> 19 ); 20 } 21 22 export function MarkdownRenderer({ content }: MarkdownRendererProps) { 23 return ( 24 <div className="prose prose-invert max-w-none text-gray-100"> 25 <ReactMarkdown 26 components={{ 27 code({ className, children, ...rest }) { 28 const match = /language-(\w+)/.exec(className ?? ""); 29 const codeString = String(children).replace(/\n$/, ""); 30 if (match) { 31 return <CodeBlock language={match[1]}>{codeString}</CodeBlock>; 32 } 33 return ( 34 <code 35 className="rounded bg-gray-800 px-1.5 py-0.5 text-sm text-gray-200" 36 {...rest} 37 > 38 {children} 39 </code> 40 ); 41 }, 42 a({ href, children }) { 43 return ( 44 <a 45 href={href} 46 target="_blank" 47 rel="noopener noreferrer" 48 className="text-blue-400 underline hover:text-blue-300" 49 > 50 {children} 51 </a> 52 ); 53 }, 54 table({ children }) { 55 return ( 56 <div className="overflow-x-auto"> 57 <table className="min-w-full border-collapse border border-gray-700"> 58 {children} 59 </table> 60 </div> 61 ); 62 }, 63 th({ children }) { 64 return ( 65 <th className="border border-gray-700 bg-gray-800 px-3 py-2 text-left text-sm font-semibold"> 66 {children} 67 </th> 68 ); 69 }, 70 td({ children }) { 71 return ( 72 <td className="border border-gray-700 px-3 py-2 text-sm"> 73 {children} 74 </td> 75 ); 76 }, 77 ul({ children }) { 78 return <ul className="list-disc pl-5 space-y-1">{children}</ul>; 79 }, 80 ol({ children }) { 81 return <ol className="list-decimal pl-5 space-y-1">{children}</ol>; 82 }, 83 p({ children }) { 84 return <p className="mb-3 last:mb-0">{children}</p>; 85 }, 86 h1({ children }) { 87 return <h1 className="text-2xl font-bold mb-4 mt-6">{children}</h1>; 88 }, 89 h2({ children }) { 90 return <h2 className="text-xl font-bold mb-3 mt-5">{children}</h2>; 91 }, 92 h3({ children }) { 93 return <h3 className="text-lg font-bold mb-2 mt-4">{children}</h3>; 94 }, 95 }} 96 > 97 {content} 98 </ReactMarkdown> 99 </div> 100 ); 101 }