152 lines
3.9 KiB
TypeScript
152 lines
3.9 KiB
TypeScript
import ReactMarkdown from 'react-markdown'
|
|
import remarkGfm from 'remark-gfm'
|
|
import type { Components } from 'react-markdown'
|
|
|
|
interface DocContentProps {
|
|
content: string
|
|
onReferenceClick: (ref: string) => void
|
|
}
|
|
|
|
export const DocContent = ({ content, onReferenceClick }: DocContentProps) => {
|
|
if (!content) {
|
|
return (
|
|
<div className="flex items-center justify-center h-full text-zinc-500">
|
|
<p className="text-base">选择左侧文档</p>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
const components: Components = {
|
|
a: ({ href, children }) => {
|
|
if (href && (href.startsWith('./') || href.startsWith('../'))) {
|
|
return (
|
|
<button
|
|
onClick={() => onReferenceClick(href)}
|
|
className="text-blue-500 hover:text-blue-400 transition-colors"
|
|
>
|
|
{children}
|
|
</button>
|
|
)
|
|
}
|
|
return (
|
|
<a href={href} className="text-blue-500 hover:text-blue-400 transition-colors">
|
|
{children}
|
|
</a>
|
|
)
|
|
},
|
|
code: ({ className, children, ...props }) => {
|
|
const match = /language-(\w+)/.exec(className || '')
|
|
if (match) {
|
|
return (
|
|
<code className={className} {...props}>
|
|
{children}
|
|
</code>
|
|
)
|
|
}
|
|
return (
|
|
<code className="text-zinc-300 font-mono text-lg" {...props}>
|
|
{children}
|
|
</code>
|
|
)
|
|
},
|
|
pre: ({ children }) => (
|
|
<pre className="bg-zinc-900 rounded-lg p-5 overflow-x-auto my-6 text-lg leading-relaxed">
|
|
{children}
|
|
</pre>
|
|
),
|
|
table: ({ children }) => (
|
|
<div className="overflow-x-auto my-6">
|
|
<table className="w-full text-lg">
|
|
{children}
|
|
</table>
|
|
</div>
|
|
),
|
|
thead: ({ children }) => (
|
|
<thead className="border-b border-zinc-700">
|
|
{children}
|
|
</thead>
|
|
),
|
|
th: ({ children }) => (
|
|
<th className="text-left py-4 pr-4 font-medium text-zinc-300 whitespace-nowrap">
|
|
{children}
|
|
</th>
|
|
),
|
|
td: ({ children }) => (
|
|
<td className="py-4 pr-4 text-zinc-400">
|
|
{children}
|
|
</td>
|
|
),
|
|
tr: ({ children }) => (
|
|
<tr className="border-b border-zinc-800">
|
|
{children}
|
|
</tr>
|
|
),
|
|
h1: ({ children }) => (
|
|
<h1 className="text-4xl font-bold text-white mt-0 mb-8">
|
|
{children}
|
|
</h1>
|
|
),
|
|
h2: ({ children }) => (
|
|
<h2 className="text-2xl font-semibold text-white mt-10 mb-4">
|
|
{children}
|
|
</h2>
|
|
),
|
|
h3: ({ children }) => (
|
|
<h3 className="text-xl font-medium text-zinc-200 mt-8 mb-3">
|
|
{children}
|
|
</h3>
|
|
),
|
|
h4: ({ children }) => (
|
|
<h4 className="text-lg font-medium text-zinc-300 mt-6 mb-2">
|
|
{children}
|
|
</h4>
|
|
),
|
|
p: ({ children }) => (
|
|
<p className="text-lg text-zinc-400 leading-relaxed my-4">
|
|
{children}
|
|
</p>
|
|
),
|
|
ul: ({ children }) => (
|
|
<ul className="list-disc list-inside text-zinc-400 my-4 space-y-1">
|
|
{children}
|
|
</ul>
|
|
),
|
|
ol: ({ children }) => (
|
|
<ol className="list-decimal list-inside text-zinc-400 my-4 space-y-1">
|
|
{children}
|
|
</ol>
|
|
),
|
|
li: ({ children }) => (
|
|
<li className="text-zinc-400">
|
|
{children}
|
|
</li>
|
|
),
|
|
blockquote: ({ children }) => (
|
|
<blockquote className="border-l-2 border-zinc-700 pl-4 my-4 text-zinc-400 italic">
|
|
{children}
|
|
</blockquote>
|
|
),
|
|
hr: () => (
|
|
<hr className="border-zinc-800 my-8" />
|
|
),
|
|
strong: ({ children }) => (
|
|
<strong className="font-semibold text-zinc-200">
|
|
{children}
|
|
</strong>
|
|
),
|
|
}
|
|
|
|
return (
|
|
<div className="h-full overflow-auto px-12 py-10">
|
|
<article className="max-w-3xl mx-auto">
|
|
<ReactMarkdown
|
|
remarkPlugins={[remarkGfm]}
|
|
components={components}
|
|
>
|
|
{content}
|
|
</ReactMarkdown>
|
|
</article>
|
|
</div>
|
|
)
|
|
}
|