Files
superdesign/src/webview/components/MarkdownRenderer.tsx
2025-08-27 17:30:13 +08:00

66 lines
2.6 KiB
TypeScript

import React from 'react';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import rehypeHighlight from 'rehype-highlight';
import 'highlight.js/styles/vs2015.css'; // Dark theme that matches VS Code
interface MarkdownRendererProps {
content: string;
className?: string;
}
const MarkdownRenderer: React.FC<MarkdownRendererProps> = ({ content, className }) => {
return (
<div className={`markdown-content ${className || ''}`}>
<ReactMarkdown
remarkPlugins={[remarkGfm]}
rehypePlugins={[rehypeHighlight]}
components={{
// Custom rendering for code blocks
code: ({ node, className, children, ...props }: any) => {
const match = /language-(\w+)/.exec(className || '');
const inline = !className?.includes('language-');
return !inline && match ? (
<pre className={`language-${match[1]} hljs`}>
<code className={className} {...props}>
{children}
</code>
</pre>
) : (
<code className={`inline-code ${className || ''}`} {...props}>
{children}
</code>
);
},
// Custom rendering for links to open externally
a: ({ node, children, href, ...props }) => (
<a
href={href}
target="_blank"
rel="noopener noreferrer"
{...props}
>
{children}
</a>
),
// Custom rendering for tables
table: ({ node, children, ...props }) => (
<div className="table-wrapper">
<table {...props}>{children}</table>
</div>
),
// Custom rendering for blockquotes
blockquote: ({ node, children, ...props }) => (
<blockquote className="markdown-blockquote" {...props}>
{children}
</blockquote>
),
}}
>
{content}
</ReactMarkdown>
</div>
);
};
export default MarkdownRenderer;