Skip to content

Commit 44fa629

Browse files
committed
del codeblock
1 parent ed6fd23 commit 44fa629

File tree

3 files changed

+145
-832
lines changed

3 files changed

+145
-832
lines changed
Lines changed: 145 additions & 145 deletions
Original file line numberDiff line numberDiff line change
@@ -1,178 +1,178 @@
11
"use client";
22

3-
import { Button } from "@/components/ui/button";
4-
import { cn } from "@/lib/utils";
53
import { CheckIcon, CopyIcon } from "lucide-react";
64
import {
7-
type ComponentProps,
8-
createContext,
9-
type HTMLAttributes,
10-
useContext,
11-
useEffect,
12-
useRef,
13-
useState,
5+
type ComponentProps,
6+
createContext,
7+
type HTMLAttributes,
8+
useContext,
9+
useEffect,
10+
useRef,
11+
useState,
1412
} from "react";
1513
import { type BundledLanguage, codeToHtml, type ShikiTransformer } from "shiki";
14+
import { Button } from "@/components/ui/button";
15+
import { cn } from "@/lib/utils";
1616

1717
type CodeBlockProps = HTMLAttributes<HTMLDivElement> & {
18-
code: string;
19-
language: BundledLanguage;
20-
showLineNumbers?: boolean;
18+
code: string;
19+
language: BundledLanguage;
20+
showLineNumbers?: boolean;
2121
};
2222

2323
type CodeBlockContextType = {
24-
code: string;
24+
code: string;
2525
};
2626

2727
const CodeBlockContext = createContext<CodeBlockContextType>({
28-
code: "",
28+
code: "",
2929
});
3030

3131
const lineNumberTransformer: ShikiTransformer = {
32-
name: "line-numbers",
33-
line(node, line) {
34-
node.children.unshift({
35-
type: "element",
36-
tagName: "span",
37-
properties: {
38-
className: [
39-
"inline-block",
40-
"min-w-10",
41-
"mr-4",
42-
"text-right",
43-
"select-none",
44-
"text-muted-foreground",
45-
],
46-
},
47-
children: [{ type: "text", value: String(line) }],
48-
});
49-
},
32+
name: "line-numbers",
33+
line(node, line) {
34+
node.children.unshift({
35+
type: "element",
36+
tagName: "span",
37+
properties: {
38+
className: [
39+
"inline-block",
40+
"min-w-10",
41+
"mr-4",
42+
"text-right",
43+
"select-none",
44+
"text-muted-foreground",
45+
],
46+
},
47+
children: [{ type: "text", value: String(line) }],
48+
});
49+
},
5050
};
5151

5252
export async function highlightCode(
53-
code: string,
54-
language: BundledLanguage,
55-
showLineNumbers = false
53+
code: string,
54+
language: BundledLanguage,
55+
showLineNumbers = false
5656
) {
57-
const transformers: ShikiTransformer[] = showLineNumbers
58-
? [lineNumberTransformer]
59-
: [];
60-
61-
return await Promise.all([
62-
codeToHtml(code, {
63-
lang: language,
64-
theme: "one-light",
65-
transformers,
66-
}),
67-
codeToHtml(code, {
68-
lang: language,
69-
theme: "one-dark-pro",
70-
transformers,
71-
}),
72-
]);
57+
const transformers: ShikiTransformer[] = showLineNumbers
58+
? [lineNumberTransformer]
59+
: [];
60+
61+
return await Promise.all([
62+
codeToHtml(code, {
63+
lang: language,
64+
theme: "one-light",
65+
transformers,
66+
}),
67+
codeToHtml(code, {
68+
lang: language,
69+
theme: "one-dark-pro",
70+
transformers,
71+
}),
72+
]);
7373
}
7474

7575
export const CodeBlock = ({
76-
code,
77-
language,
78-
showLineNumbers = false,
79-
className,
80-
children,
81-
...props
76+
code,
77+
language,
78+
showLineNumbers = false,
79+
className,
80+
children,
81+
...props
8282
}: CodeBlockProps) => {
83-
const [html, setHtml] = useState<string>("");
84-
const [darkHtml, setDarkHtml] = useState<string>("");
85-
const mounted = useRef(false);
86-
87-
useEffect(() => {
88-
highlightCode(code, language, showLineNumbers).then(([light, dark]) => {
89-
if (!mounted.current) {
90-
setHtml(light);
91-
setDarkHtml(dark);
92-
mounted.current = true;
93-
}
94-
});
95-
96-
return () => {
97-
mounted.current = false;
98-
};
99-
}, [code, language, showLineNumbers]);
100-
101-
return (
102-
<CodeBlockContext.Provider value={{ code }}>
103-
<div
104-
className={cn(
105-
"group relative w-full overflow-hidden rounded-md border bg-background text-foreground",
106-
className
107-
)}
108-
{...props}
109-
>
110-
<div className="relative">
111-
<div
112-
className="overflow-hidden dark:hidden [&>pre]:m-0 [&>pre]:bg-background! [&>pre]:p-4 [&>pre]:text-foreground! [&>pre]:text-sm [&_code]:font-mono [&_code]:text-sm"
113-
// biome-ignore lint/security/noDangerouslySetInnerHtml: "this is needed."
114-
dangerouslySetInnerHTML={{ __html: html }}
115-
/>
116-
<div
117-
className="hidden overflow-hidden dark:block [&>pre]:m-0 [&>pre]:bg-background! [&>pre]:p-4 [&>pre]:text-foreground! [&>pre]:text-sm [&_code]:font-mono [&_code]:text-sm"
118-
// biome-ignore lint/security/noDangerouslySetInnerHtml: "this is needed."
119-
dangerouslySetInnerHTML={{ __html: darkHtml }}
120-
/>
121-
{children && (
122-
<div className="absolute top-2 right-2 flex items-center gap-2">
123-
{children}
124-
</div>
125-
)}
126-
</div>
127-
</div>
128-
</CodeBlockContext.Provider>
129-
);
83+
const [html, setHtml] = useState<string>("");
84+
const [darkHtml, setDarkHtml] = useState<string>("");
85+
const mounted = useRef(false);
86+
87+
useEffect(() => {
88+
highlightCode(code, language, showLineNumbers).then(([light, dark]) => {
89+
if (!mounted.current) {
90+
setHtml(light);
91+
setDarkHtml(dark);
92+
mounted.current = true;
93+
}
94+
});
95+
96+
return () => {
97+
mounted.current = false;
98+
};
99+
}, [code, language, showLineNumbers]);
100+
101+
return (
102+
<CodeBlockContext.Provider value={{ code }}>
103+
<div
104+
className={cn(
105+
"group relative w-full overflow-hidden rounded-md border bg-background text-foreground",
106+
className
107+
)}
108+
{...props}
109+
>
110+
<div className="relative">
111+
<div
112+
className="overflow-hidden dark:hidden [&>pre]:m-0 [&>pre]:bg-background! [&>pre]:p-4 [&>pre]:text-foreground! [&>pre]:text-sm [&_code]:font-mono [&_code]:text-sm"
113+
// biome-ignore lint/security/noDangerouslySetInnerHtml: "this is needed."
114+
dangerouslySetInnerHTML={{ __html: html }}
115+
/>
116+
<div
117+
className="hidden overflow-hidden dark:block [&>pre]:m-0 [&>pre]:bg-background! [&>pre]:p-4 [&>pre]:text-foreground! [&>pre]:text-sm [&_code]:font-mono [&_code]:text-sm"
118+
// biome-ignore lint/security/noDangerouslySetInnerHtml: "this is needed."
119+
dangerouslySetInnerHTML={{ __html: darkHtml }}
120+
/>
121+
{children && (
122+
<div className="absolute top-2 right-2 flex items-center gap-2">
123+
{children}
124+
</div>
125+
)}
126+
</div>
127+
</div>
128+
</CodeBlockContext.Provider>
129+
);
130130
};
131131

132132
export type CodeBlockCopyButtonProps = ComponentProps<typeof Button> & {
133-
onCopy?: () => void;
134-
onError?: (error: Error) => void;
135-
timeout?: number;
133+
onCopy?: () => void;
134+
onError?: (error: Error) => void;
135+
timeout?: number;
136136
};
137137

138138
export const CodeBlockCopyButton = ({
139-
onCopy,
140-
onError,
141-
timeout = 2000,
142-
children,
143-
className,
144-
...props
139+
onCopy,
140+
onError,
141+
timeout = 2000,
142+
children,
143+
className,
144+
...props
145145
}: CodeBlockCopyButtonProps) => {
146-
const [isCopied, setIsCopied] = useState(false);
147-
const { code } = useContext(CodeBlockContext);
148-
149-
const copyToClipboard = async () => {
150-
if (typeof window === "undefined" || !navigator?.clipboard?.writeText) {
151-
onError?.(new Error("Clipboard API not available"));
152-
return;
153-
}
154-
155-
try {
156-
await navigator.clipboard.writeText(code);
157-
setIsCopied(true);
158-
onCopy?.();
159-
setTimeout(() => setIsCopied(false), timeout);
160-
} catch (error) {
161-
onError?.(error as Error);
162-
}
163-
};
164-
165-
const Icon = isCopied ? CheckIcon : CopyIcon;
166-
167-
return (
168-
<Button
169-
className={cn("shrink-0", className)}
170-
onClick={copyToClipboard}
171-
size="icon"
172-
variant="ghost"
173-
{...props}
174-
>
175-
{children ?? <Icon size={14} />}
176-
</Button>
177-
);
146+
const [isCopied, setIsCopied] = useState(false);
147+
const { code } = useContext(CodeBlockContext);
148+
149+
const copyToClipboard = async () => {
150+
if (typeof window === "undefined" || !navigator?.clipboard?.writeText) {
151+
onError?.(new Error("Clipboard API not available"));
152+
return;
153+
}
154+
155+
try {
156+
await navigator.clipboard.writeText(code);
157+
setIsCopied(true);
158+
onCopy?.();
159+
setTimeout(() => setIsCopied(false), timeout);
160+
} catch (error) {
161+
onError?.(error as Error);
162+
}
163+
};
164+
165+
const Icon = isCopied ? CheckIcon : CopyIcon;
166+
167+
return (
168+
<Button
169+
className={cn("shrink-0", className)}
170+
onClick={copyToClipboard}
171+
size="icon"
172+
variant="ghost"
173+
{...props}
174+
>
175+
{children ?? <Icon size={14} />}
176+
</Button>
177+
);
178178
};

0 commit comments

Comments
 (0)