"use client"; import { Check, Copy, Download } from "lucide-react"; import { FC, memo } from "react"; import { Prism, SyntaxHighlighterProps } from "react-syntax-highlighter"; import { coldarkDark } from "react-syntax-highlighter/dist/cjs/styles/prism"; import { Button } from "../button"; import { useCopyToClipboard } from "./use-copy-to-clipboard"; // TODO: Remove this when @type/react-syntax-highlighter is updated const SyntaxHighlighter = Prism as unknown as FC; interface Props { 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", // add more file extensions here, make sure the key is same as language prop in CodeBlock.tsx component }; 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; }; const CodeBlock: 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) { // User pressed cancel on prompt. 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}
); }); CodeBlock.displayName = "CodeBlock"; export { CodeBlock };