import React, { useRef, useState, RefObject, memo, useEffect } from 'react'; import copy from 'copy-to-clipboard'; import rehypeKatex from 'rehype-katex'; import ReactMarkdown from 'react-markdown'; import type { PluggableList } from 'unified'; import rehypeHighlight from 'rehype-highlight'; import { useDebounceCodeBlock } from './useDebounceCodeBlock'; import { handleDoubleClick, cn, langSubset } from '~/utils'; import Clipboard from '~/components/svg/Clipboard'; import CheckMark from '~/components/svg/CheckMark'; import useLocalize from '~/hooks/useLocalize'; import CodePreview from './CodePreview'; type CodeBarProps = { lang: string; codeRef: RefObject; }; interface CodeBlockArtifactProps { lang: string; codeString: string; artifactId: string; } type CodeBlockProps = Pick & { codeChildren: React.ReactNode; classProp?: string; }; const CodeBar: React.FC = React.memo(({ lang, codeRef }) => { const localize = useLocalize(); const [isCopied, setIsCopied] = useState(false); return (
{lang}
); }); const CodeBlock: React.FC = ({ lang, codeChildren, classProp = '' }) => { const codeRef = useRef(null); return (
{codeChildren}
); }; type TCodeProps = { inline: boolean; className?: string; children: React.ReactNode; }; export const code: React.ElementType = memo(({ inline, className, children }: TCodeProps) => { const match = /language-(\w+)/.exec(className ?? ''); const lang = match && match[1]; if (inline) { return ( {children} ); } return ; }); const cursor = ' '; export const CodeMarkdown = memo( ({ content = '', showCursor, isLatestMessage, }: { content: string; showCursor?: boolean; isLatestMessage: boolean; }) => { const currentContent = content; const rehypePlugins: PluggableList = [ [rehypeKatex, { output: 'mathml' }], [ rehypeHighlight, { detect: true, ignoreMissing: true, subset: langSubset, }, ], ]; return ( {isLatestMessage && showCursor === true ? currentContent + cursor : currentContent} ); }, );