Spaces:
Build error
Build error
| "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<SyntaxHighlighterProps>; | |
| 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<Props> = 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 ( | |
| <div className="codeblock relative w-full bg-zinc-950 font-sans"> | |
| <div className="flex w-full items-center justify-between bg-zinc-800 px-6 py-2 pr-4 text-zinc-100"> | |
| <span className="text-xs lowercase">{language}</span> | |
| <div className="flex items-center space-x-1"> | |
| <Button variant="ghost" onClick={downloadAsFile} size="icon"> | |
| <Download /> | |
| <span className="sr-only">Download</span> | |
| </Button> | |
| <Button variant="ghost" size="icon" onClick={onCopy}> | |
| {isCopied ? ( | |
| <Check className="h-4 w-4" /> | |
| ) : ( | |
| <Copy className="h-4 w-4" /> | |
| )} | |
| <span className="sr-only">Copy code</span> | |
| </Button> | |
| </div> | |
| </div> | |
| <SyntaxHighlighter | |
| language={language} | |
| style={coldarkDark} | |
| PreTag="div" | |
| showLineNumbers | |
| customStyle={{ | |
| width: "100%", | |
| background: "transparent", | |
| padding: "1.5rem 1rem", | |
| borderRadius: "0.5rem", | |
| }} | |
| codeTagProps={{ | |
| style: { | |
| fontSize: "0.9rem", | |
| fontFamily: "var(--font-mono)", | |
| }, | |
| }} | |
| > | |
| {value} | |
| </SyntaxHighlighter> | |
| </div> | |
| ); | |
| }); | |
| CodeBlock.displayName = "CodeBlock"; | |
| export { CodeBlock }; | |