Skip to content

Commit 896165e

Browse files
authored
Merge pull request #111 from cacheplane/fix/code-syntax-highlighting
feat(website): Shiki syntax highlighting on landing page code blocks
2 parents 525c832 + 2a4e2d8 commit 896165e

4 files changed

Lines changed: 60 additions & 78 deletions

File tree

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { codeToHtml } from 'shiki';
2+
3+
interface HighlightedCodeProps {
4+
code: string;
5+
lang?: string;
6+
}
7+
8+
export async function HighlightedCode({ code, lang = 'typescript' }: HighlightedCodeProps) {
9+
const html = await codeToHtml(code.trim(), {
10+
lang,
11+
theme: 'tokyo-night',
12+
});
13+
14+
return (
15+
<div
16+
className="shiki"
17+
style={{ margin: 0, borderRadius: 0 }}
18+
dangerouslySetInnerHTML={{ __html: html }}
19+
/>
20+
);
21+
}

apps/website/src/components/landing/angular/AngularCodeShowcase.tsx

Lines changed: 13 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
// apps/website/src/components/landing/angular/AngularCodeShowcase.tsx
2-
'use client';
3-
import { motion } from 'framer-motion';
41
import { tokens } from '@cacheplane/design-tokens';
2+
import { HighlightedCode } from '../HighlightedCode';
53

64
const SNIPPET_1 = `import { agent } from '@cacheplane/angular';
75
@@ -27,16 +25,15 @@ provideAgent({
2725
: new FetchStreamTransport(),
2826
});`;
2927

30-
export function AngularCodeShowcase() {
28+
const SNIPPETS = [
29+
{ title: 'Minimal Setup', code: SNIPPET_1, lang: 'typescript' },
30+
{ title: 'Full Configuration', code: SNIPPET_2, lang: 'typescript' },
31+
];
32+
33+
export async function AngularCodeShowcase() {
3134
return (
3235
<section style={{ padding: '80px 32px' }}>
33-
<motion.div
34-
initial={{ opacity: 0, y: 16 }}
35-
whileInView={{ opacity: 1, y: 0 }}
36-
viewport={{ once: true }}
37-
transition={{ duration: 0.5 }}
38-
style={{ textAlign: 'center', marginBottom: 48 }}
39-
>
36+
<div style={{ textAlign: 'center', marginBottom: 48 }}>
4037
<p style={{
4138
fontFamily: 'var(--font-mono,"JetBrains Mono",monospace)',
4239
fontSize: '0.7rem', textTransform: 'uppercase', letterSpacing: '0.12em',
@@ -51,19 +48,15 @@ export function AngularCodeShowcase() {
5148
}}>
5249
Production streaming in a few lines
5350
</h2>
54-
</motion.div>
51+
</div>
5552

5653
<div style={{
5754
maxWidth: 900, margin: '0 auto',
5855
display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(min(380px, 100%), 1fr))', gap: 24,
5956
}}>
60-
{[{ title: 'Minimal Setup', code: SNIPPET_1 }, { title: 'Full Configuration', code: SNIPPET_2 }].map((s, i) => (
61-
<motion.div
57+
{SNIPPETS.map((s) => (
58+
<div
6259
key={s.title}
63-
initial={{ opacity: 0, y: 20 }}
64-
whileInView={{ opacity: 1, y: 0 }}
65-
viewport={{ once: true }}
66-
transition={{ duration: 0.45, delay: i * 0.1 }}
6760
style={{ borderRadius: 14, overflow: 'hidden', border: `1px solid ${tokens.glass.border}` }}
6861
>
6962
<div style={{
@@ -77,14 +70,8 @@ export function AngularCodeShowcase() {
7770
{s.title}
7871
</span>
7972
</div>
80-
<pre style={{
81-
background: '#1a1b26', color: '#c8ccee', padding: '20px 24px',
82-
fontSize: '0.78rem', lineHeight: 1.65, margin: 0, overflowX: 'auto',
83-
fontFamily: "'JetBrains Mono', monospace",
84-
}}>
85-
<code>{s.code}</code>
86-
</pre>
87-
</motion.div>
73+
<HighlightedCode code={s.code} lang={s.lang} />
74+
</div>
8875
))}
8976
</div>
9077
</section>

apps/website/src/components/landing/chat-landing/ChatLandingCodeShowcase.tsx

Lines changed: 13 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
// apps/website/src/components/landing/chat-landing/ChatLandingCodeShowcase.tsx
2-
'use client';
3-
import { motion } from 'framer-motion';
41
import { tokens } from '@cacheplane/design-tokens';
2+
import { HighlightedCode } from '../HighlightedCode';
53

64
const SNIPPET_1 = `import { ChatComponent } from '@cacheplane/chat';
75
@@ -28,16 +26,15 @@ const SNIPPET_2 = `chat {
2826
--chat-input-border: 1px solid #e4e4e7;
2927
}`;
3028

31-
export function ChatLandingCodeShowcase() {
29+
const SNIPPETS = [
30+
{ title: 'Prebuilt Chat', code: SNIPPET_1, lang: 'typescript' },
31+
{ title: 'Custom Theming', code: SNIPPET_2, lang: 'css' },
32+
];
33+
34+
export async function ChatLandingCodeShowcase() {
3235
return (
3336
<section style={{ padding: '80px 32px' }}>
34-
<motion.div
35-
initial={{ opacity: 0, y: 16 }}
36-
whileInView={{ opacity: 1, y: 0 }}
37-
viewport={{ once: true }}
38-
transition={{ duration: 0.5 }}
39-
style={{ textAlign: 'center', marginBottom: 48 }}
40-
>
37+
<div style={{ textAlign: 'center', marginBottom: 48 }}>
4138
<p style={{
4239
fontFamily: 'var(--font-mono,"JetBrains Mono",monospace)',
4340
fontSize: '0.7rem', textTransform: 'uppercase', letterSpacing: '0.12em',
@@ -52,19 +49,15 @@ export function ChatLandingCodeShowcase() {
5249
}}>
5350
Full-featured chat in a few lines
5451
</h2>
55-
</motion.div>
52+
</div>
5653

5754
<div style={{
5855
maxWidth: 900, margin: '0 auto',
5956
display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(min(380px, 100%), 1fr))', gap: 24,
6057
}}>
61-
{[{ title: 'Prebuilt Chat', code: SNIPPET_1 }, { title: 'Custom Theming', code: SNIPPET_2 }].map((s, i) => (
62-
<motion.div
58+
{SNIPPETS.map((s) => (
59+
<div
6360
key={s.title}
64-
initial={{ opacity: 0, y: 20 }}
65-
whileInView={{ opacity: 1, y: 0 }}
66-
viewport={{ once: true }}
67-
transition={{ duration: 0.45, delay: i * 0.1 }}
6861
style={{ borderRadius: 14, overflow: 'hidden', border: `1px solid ${tokens.glass.border}` }}
6962
>
7063
<div style={{
@@ -78,14 +71,8 @@ export function ChatLandingCodeShowcase() {
7871
{s.title}
7972
</span>
8073
</div>
81-
<pre style={{
82-
background: '#1a1b26', color: '#c8ccee', padding: '20px 24px',
83-
fontSize: '0.78rem', lineHeight: 1.65, margin: 0, overflowX: 'auto',
84-
fontFamily: "'JetBrains Mono', monospace",
85-
}}>
86-
<code>{s.code}</code>
87-
</pre>
88-
</motion.div>
74+
<HighlightedCode code={s.code} lang={s.lang} />
75+
</div>
8976
))}
9077
</div>
9178
</section>

apps/website/src/components/landing/render/RenderCodeShowcase.tsx

Lines changed: 13 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
// apps/website/src/components/landing/render/RenderCodeShowcase.tsx
2-
'use client';
3-
import { motion } from 'framer-motion';
41
import { tokens } from '@cacheplane/design-tokens';
2+
import { HighlightedCode } from '../HighlightedCode';
53

64
const SNIPPET_1 = `import { defineAngularRegistry } from '@cacheplane/render';
75
import { TableComponent } from './table.component';
@@ -19,16 +17,15 @@ const SNIPPET_2 = `<render-spec
1917
[state]="stateStore"
2018
/>`;
2119

22-
export function RenderCodeShowcase() {
20+
const SNIPPETS = [
21+
{ title: 'Registry Setup', code: SNIPPET_1, lang: 'typescript' },
22+
{ title: 'Template Binding', code: SNIPPET_2, lang: 'html' },
23+
];
24+
25+
export async function RenderCodeShowcase() {
2326
return (
2427
<section style={{ padding: '80px 32px' }}>
25-
<motion.div
26-
initial={{ opacity: 0, y: 16 }}
27-
whileInView={{ opacity: 1, y: 0 }}
28-
viewport={{ once: true }}
29-
transition={{ duration: 0.5 }}
30-
style={{ textAlign: 'center', marginBottom: 48 }}
31-
>
28+
<div style={{ textAlign: 'center', marginBottom: 48 }}>
3229
<p style={{
3330
fontFamily: 'var(--font-mono,"JetBrains Mono",monospace)',
3431
fontSize: '0.7rem', textTransform: 'uppercase', letterSpacing: '0.12em',
@@ -43,19 +40,15 @@ export function RenderCodeShowcase() {
4340
}}>
4441
Generative UI in a few lines
4542
</h2>
46-
</motion.div>
43+
</div>
4744

4845
<div style={{
4946
maxWidth: 900, margin: '0 auto',
5047
display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(min(380px, 100%), 1fr))', gap: 24,
5148
}}>
52-
{[{ title: 'Registry Setup', code: SNIPPET_1 }, { title: 'Template Binding', code: SNIPPET_2 }].map((s, i) => (
53-
<motion.div
49+
{SNIPPETS.map((s) => (
50+
<div
5451
key={s.title}
55-
initial={{ opacity: 0, y: 20 }}
56-
whileInView={{ opacity: 1, y: 0 }}
57-
viewport={{ once: true }}
58-
transition={{ duration: 0.45, delay: i * 0.1 }}
5952
style={{ borderRadius: 14, overflow: 'hidden', border: `1px solid ${tokens.glass.border}` }}
6053
>
6154
<div style={{
@@ -69,14 +62,8 @@ export function RenderCodeShowcase() {
6962
{s.title}
7063
</span>
7164
</div>
72-
<pre style={{
73-
background: '#1a1b26', color: '#c8ccee', padding: '20px 24px',
74-
fontSize: '0.78rem', lineHeight: 1.65, margin: 0, overflowX: 'auto',
75-
fontFamily: "'JetBrains Mono', monospace",
76-
}}>
77-
<code>{s.code}</code>
78-
</pre>
79-
</motion.div>
65+
<HighlightedCode code={s.code} lang={s.lang} />
66+
</div>
8067
))}
8168
</div>
8269
</section>

0 commit comments

Comments
 (0)