Skip to content

Commit da1cfd9

Browse files
add shiki and code snippet
1 parent cc4b77a commit da1cfd9

File tree

4 files changed

+466
-3
lines changed

4 files changed

+466
-3
lines changed

apps/web/app/(base-org)/developers/onchainkit/page.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { InfoCards } from 'apps/web/src/components/Developers/Onchainkit/InfoCar
88
import { Templates } from 'apps/web/src/components/Developers/Onchainkit/Templates';
99
import { Testmonials } from 'apps/web/src/components/Developers/Onchainkit/Testimonials';
1010
import { CtaBanner } from 'apps/web/src/components/Developers/Shared/CtaBanner';
11-
import Image from 'next/image';
11+
import Image, { StaticImageData } from 'next/image';
1212
import onchainkit from 'apps/web/src/components/Developers/Onchainkit/onchainkit.svg';
1313

1414
export default async function OnchainKit() {
@@ -18,7 +18,13 @@ export default async function OnchainKit() {
1818
{/* Header */}
1919
<div className="flex flex-col items-center gap-1 pt-20">
2020
<div className="flex items-center gap-2 pb-6 text-[#C9A4FA]">
21-
<Image src={onchainkit} alt="onchainkit" width={32} height={32} className="h-5 w-5" />
21+
<Image
22+
src={onchainkit as StaticImageData}
23+
alt="onchainkit"
24+
width={32}
25+
height={32}
26+
className="h-5 w-5"
27+
/>
2228
<Title level={TitleLevel.Title3}>OnchainKit</Title>
2329
</div>
2430
<Title level={TitleLevel.Display3}>Full-stack onchain components</Title>

apps/web/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
"recharts": "^2.12.7",
7474
"satori": "^0.10.14",
7575
"sharp": "^0.33.4",
76+
"shiki": "^2.3.2",
7677
"three": "^0.168.0",
7778
"three-stdlib": "^2.33.0",
7879
"twemoji": "^14.0.2",
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
'use client';
2+
3+
import { useEffect, useMemo, useState } from 'react';
4+
import { createHighlighter } from 'shiki';
5+
6+
export default function CodeSnippet({ code }: { code: string }) {
7+
const [highlightedCode, setHighlightedCode] = useState('');
8+
9+
useEffect(() => {
10+
async function highlightCode() {
11+
const highlighter = await createHighlighter({
12+
themes: ['github-light', 'github-dark'],
13+
langs: ['typescript'],
14+
});
15+
16+
const formattedCode = highlighter.codeToHtml(code, {
17+
lang: 'typescript',
18+
themes: {
19+
light: 'github-light',
20+
dark: 'github-dark',
21+
},
22+
defaultColor: false,
23+
});
24+
25+
// Remove Shiki formatting
26+
const cleanedCode = formattedCode.replace(
27+
/<pre[^>]*class="([^"]*)"[^>]*>/,
28+
(_match: string, className: string) =>
29+
`<pre class="${className}" style="margin: 0; padding: 0; background: transparent">`,
30+
);
31+
32+
setHighlightedCode(cleanedCode);
33+
}
34+
35+
void highlightCode();
36+
}, [code]);
37+
38+
const dangerouslySetInnerHTML = useMemo(() => {
39+
return { __html: highlightedCode };
40+
}, [highlightedCode]);
41+
42+
if (!highlightedCode) {
43+
return (
44+
<div className="h-full overflow-auto rounded-lg transition-colors">
45+
<div className="text-neutral-400">Loading...</div>
46+
</div>
47+
);
48+
}
49+
50+
return (
51+
<div
52+
className="code-snippet h-full overflow-auto rounded-lg transition-colors"
53+
// eslint-disable-next-line react/no-danger
54+
dangerouslySetInnerHTML={dangerouslySetInnerHTML}
55+
/>
56+
);
57+
}

0 commit comments

Comments
 (0)