mirror of
https://github.com/siteboon/claudecodeui.git
synced 2026-03-11 08:57:38 +00:00
73 lines
2.3 KiB
TypeScript
73 lines
2.3 KiB
TypeScript
import { useState } from 'react';
|
|
import type { ComponentProps } from 'react';
|
|
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
|
|
import { oneDark as prismOneDark } from 'react-syntax-highlighter/dist/esm/styles/prism';
|
|
import { copyTextToClipboard } from '../../../../../utils/clipboard';
|
|
|
|
type MarkdownCodeBlockProps = {
|
|
inline?: boolean;
|
|
node?: unknown;
|
|
} & ComponentProps<'code'>;
|
|
|
|
export default function MarkdownCodeBlock({
|
|
inline,
|
|
className,
|
|
children,
|
|
node: _node,
|
|
...props
|
|
}: MarkdownCodeBlockProps) {
|
|
const [copied, setCopied] = useState(false);
|
|
const rawContent = Array.isArray(children) ? children.join('') : String(children ?? '');
|
|
const looksMultiline = /[\r\n]/.test(rawContent);
|
|
const shouldRenderInline = inline || !looksMultiline;
|
|
|
|
if (shouldRenderInline) {
|
|
return (
|
|
<code
|
|
className={`font-mono text-[0.9em] px-1.5 py-0.5 rounded-md bg-gray-100 text-gray-900 border border-gray-200 dark:bg-gray-800/60 dark:text-gray-100 dark:border-gray-700 whitespace-pre-wrap break-words ${className || ''}`}
|
|
{...props}
|
|
>
|
|
{children}
|
|
</code>
|
|
);
|
|
}
|
|
|
|
const languageMatch = /language-(\w+)/.exec(className || '');
|
|
const language = languageMatch ? languageMatch[1] : 'text';
|
|
|
|
return (
|
|
<div className="relative group my-2">
|
|
{language !== 'text' && (
|
|
<div className="absolute top-2 left-3 z-10 text-xs text-gray-400 font-medium uppercase">{language}</div>
|
|
)}
|
|
|
|
<button
|
|
type="button"
|
|
onClick={() =>
|
|
copyTextToClipboard(rawContent).then((success) => {
|
|
if (success) {
|
|
setCopied(true);
|
|
setTimeout(() => setCopied(false), 2000);
|
|
}
|
|
})}
|
|
className="absolute top-2 right-2 z-10 opacity-0 group-hover:opacity-100 transition-opacity text-xs px-2 py-1 rounded-md bg-gray-700/80 hover:bg-gray-700 text-white border border-gray-600"
|
|
>
|
|
{copied ? 'Copied!' : 'Copy'}
|
|
</button>
|
|
|
|
<SyntaxHighlighter
|
|
language={language}
|
|
style={prismOneDark}
|
|
customStyle={{
|
|
margin: 0,
|
|
borderRadius: '0.5rem',
|
|
fontSize: '0.875rem',
|
|
padding: language !== 'text' ? '2rem 1rem 1rem 1rem' : '1rem',
|
|
}}
|
|
>
|
|
{rawContent}
|
|
</SyntaxHighlighter>
|
|
</div>
|
|
);
|
|
}
|