-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathcode-block.tsx
More file actions
110 lines (103 loc) · 2.26 KB
/
code-block.tsx
File metadata and controls
110 lines (103 loc) · 2.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
"use client"
import { useCallback, useRef, type ReactNode } from "react"
import { CopyButton } from "./copy-button"
import { cn } from "@/lib/utils"
const languageLabels: Record<string, string> = {
sh: "Shell",
bash: "Shell",
zsh: "Shell",
shell: "Shell",
yaml: "YAML",
yml: "YAML",
json: "JSON",
js: "JavaScript",
javascript: "JavaScript",
ts: "TypeScript",
typescript: "TypeScript",
tsx: "TSX",
jsx: "JSX",
py: "Python",
python: "Python",
rb: "Ruby",
ruby: "Ruby",
go: "Go",
rust: "Rust",
rs: "Rust",
php: "PHP",
sql: "SQL",
css: "CSS",
scss: "SCSS",
html: "HTML",
xml: "XML",
md: "Markdown",
markdown: "Markdown",
dockerfile: "Dockerfile",
docker: "Docker",
nginx: "Nginx",
apache: "Apache",
ini: "INI",
toml: "TOML",
env: "ENV",
dotenv: ".env",
txt: "Text",
text: "Text",
plaintext: "Text",
diff: "Diff",
graphql: "GraphQL",
vue: "Vue",
svelte: "Svelte",
swift: "Swift",
kotlin: "Kotlin",
java: "Java",
c: "C",
cpp: "C++",
csharp: "C#",
lua: "Lua",
}
export function CodeBlock({
children,
language,
...props
}: {
children: ReactNode
language?: string
[key: string]: unknown
}) {
const preRef = useRef<HTMLPreElement>(null)
const label = language
? languageLabels[language] || language.toUpperCase()
: null
const getCodeText = useCallback(() => {
if (!preRef.current) return ""
const code = preRef.current.querySelector("code")
return code?.textContent || ""
}, [])
return (
<div className="group/code relative my-5">
{/* Header bar with language label and copy button */}
<div
className={cn(
"flex items-center justify-between rounded-t-lg border border-b-0 px-3 py-1",
"bg-zinc-50 dark:bg-zinc-900/80"
)}
>
<span className="text-xs font-medium text-muted-foreground/70 select-none">
{label || "Code"}
</span>
<CopyButton getText={getCodeText} />
</div>
{/* Code content */}
<pre
ref={preRef}
className={cn(
"overflow-x-auto rounded-b-lg border py-4",
"bg-white dark:bg-zinc-950",
"text-[0.8125rem] leading-relaxed"
)}
{...props}
>
{children}
</pre>
</div>
)
}