import { Button } from "@/components/ui/button" import { useCopyToClipboard } from "@/lib/hooks/use-copy-to-clipboard" import { IconCheck, IconCopy, IconDownload } from "@tabler/icons-react" import { FC, memo } from "react" import { Prism as SyntaxHighlighter } from "react-syntax-highlighter" import { oneDark } from "react-syntax-highlighter/dist/cjs/styles/prism" interface MessageCodeBlockProps { language: string value: string } interface languageMap { [key: string]: string | undefined } export const programmingLanguages: languageMap = { javascript: ".js", python: ".py", java: ".java", c: ".c", cpp: ".cpp", "c++": ".cpp", "c#": ".cs", ruby: ".rb", php: ".php", swift: ".swift", "objective-c": ".m", kotlin: ".kt", typescript: ".ts", go: ".go", perl: ".pl", rust: ".rs", scala: ".scala", haskell: ".hs", lua: ".lua", shell: ".sh", sql: ".sql", html: ".html", css: ".css" } export const generateRandomString = (length: number, lowercase = false) => { const chars = "ABCDEFGHJKLMNPQRSTUVWXY3456789" // excluding similar looking characters like Z, 2, I, 1, O, 0 let result = "" for (let i = 0; i < length; i++) { result += chars.charAt(Math.floor(Math.random() * chars.length)) } return lowercase ? result.toLowerCase() : result } export const MessageCodeBlock: FC = memo( ({ language, value }) => { const { isCopied, copyToClipboard } = useCopyToClipboard({ timeout: 2000 }) const downloadAsFile = () => { if (typeof window === "undefined") { return } const fileExtension = programmingLanguages[language] || ".file" const suggestedFileName = `file-${generateRandomString( 3, true )}${fileExtension}` const fileName = window.prompt("Enter file name" || "", suggestedFileName) if (!fileName) { return } const blob = new Blob([value], { type: "text/plain" }) const url = URL.createObjectURL(blob) const link = document.createElement("a") link.download = fileName link.href = url link.style.display = "none" document.body.appendChild(link) link.click() document.body.removeChild(link) URL.revokeObjectURL(url) } const onCopy = () => { if (isCopied) return copyToClipboard(value) } return (
{language}
{value}
) } ) MessageCodeBlock.displayName = "MessageCodeBlock"