Syntax Highlighting
eziwiki uses Shiki for beautiful, accurate syntax highlighting.
Why Shiki?#
- Accurate β uses the same TextMate grammars as VS Code
- Beautiful β the highlighting you already know from your editor
- Zero client cost β code is highlighted during the build, so no highlighter is sent to the browser
- Both themes at once β light and dark are emitted as CSS variables, so switching theme never flashes or re-highlights
Supported Languages#
Shiki bundles grammars for over a hundred languages β JavaScript, TypeScript, Python, Go, Rust, C, C++, C#, Java, Ruby, PHP, SQL, GraphQL, HTML, CSS, YAML, TOML, Bash, and so on.
Only what you use is loaded#
Loading all of them costs about twenty seconds before the first page renders, so eziwiki scans your content for the languages it actually contains and loads only those, plus a handful of common defaults. This site loads sixteen grammars and initialises in well under a second.
The practical effect: write a fence in any supported language and it just works β the next build picks it up. A fence whose language Shiki does not recognise renders as plain text rather than failing the build.
Usage#
Basic Code Block#
Use triple backticks with a language identifier:
```javascript
function greet(name) {
return `Hello, ${name}!`;
}
```Result:
function greet(name) {
return `Hello, ${name}!`;
}TypeScript Example#
```typescript
interface User {
id: string;
name: string;
email: string;
}
async function fetchUser(id: string): Promise<User> {
const response = await fetch(`/api/users/${id}`);
return response.json();
}
```interface User {
id: string;
name: string;
email: string;
}
async function fetchUser(id: string): Promise<User> {
const response = await fetch(`/api/users/${id}`);
return response.json();
}Python Example#
```python
def calculate_fibonacci(n: int) -> list[int]:
"""Generate Fibonacci sequence."""
if n <= 0:
return []
fib = [0, 1]
for i in range(2, n):
fib.append(fib[i-1] + fib[i-2])
return fib
```def calculate_fibonacci(n: int) -> list[int]:
"""Generate Fibonacci sequence."""
if n <= 0:
return []
fib = [0, 1]
for i in range(2, n):
fib.append(fib[i-1] + fib[i-2])
return fibConfiguration#
Change Theme#
Edit lib/markdown/highlighter.ts:
import { getHighlighter } from 'shiki';
const highlighter = await getHighlighter({
themes: ['github-light', 'github-dark'], // Change themes here
langs: ['javascript', 'typescript', ...],
});Available Themes#
Popular themes:
github-light,github-dark(default)norddraculamonokaione-dark-promaterial-themesolarized-light,solarized-dark
See all themes.
Add Languages#
Add more languages to support:
const highlighter = await getHighlighter({
themes: ['github-light', 'github-dark'],
langs: [
'javascript',
'typescript',
'python',
'rust', // Add Rust
'kotlin', // Add Kotlin
'swift', // Add Swift
],
});Dark Mode Support#
Code blocks automatically adapt to the theme:
// Light mode: github-light theme
// Dark mode: github-dark theme
const html = highlighter.codeToHtml(code, {
lang: 'javascript',
theme: isDark ? 'github-dark' : 'github-light',
});Inline Code#
Inline code uses a simple monospace style:
Use `const` instead of `var` in JavaScript.Use const instead of var in JavaScript.
Line Numbers#
To add line numbers, modify the highlighter configuration:
const html = highlighter.codeToHtml(code, {
lang: 'javascript',
theme: 'github-light',
lineNumbers: true, // Enable line numbers
});Line Highlighting#
Highlight specific lines:
const html = highlighter.codeToHtml(code, {
lang: 'javascript',
theme: 'github-light',
lineOptions: [
{ line: 3, classes: ['highlighted'] },
{ line: 5, classes: ['highlighted'] },
],
});Copy Button#
Add a copy button to code blocks:
'use client';
import { useState } from 'react';
import { Copy, Check } from 'lucide-react';
export function CodeBlock({ code, lang }: { code: string; lang: string }) {
const [copied, setCopied] = useState(false);
const copyCode = async () => {
await navigator.clipboard.writeText(code);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
};
return (
<div className="relative">
<button
onClick={copyCode}
className="absolute top-2 right-2 p-2 rounded bg-gray-700 hover:bg-gray-600"
>
{copied ? <Check size={16} /> : <Copy size={16} />}
</button>
<pre>
<code>{code}</code>
</pre>
</div>
);
}Language Detection#
If no language is specified, Shiki tries to detect it:
```
function hello() {
console.log('Hello!');
}
```But it's better to always specify the language:
```javascript
function hello() {
console.log('Hello!');
}
```Performance#
Build-Time Rendering#
Code blocks are highlighted at build time, not runtime:
// During build
const html = highlighter.codeToHtml(code, { lang, theme });
// Served as static HTML
<div dangerouslySetInnerHTML={{ __html: html }} />This means:
- Fast loading - No client-side processing
- Small bundle - No syntax highlighting library in browser
- SEO friendly - Fully rendered HTML
Bundle Size#
Shiki only runs at build time, so it doesn't increase your client bundle size.
Best Practices#
Always Specify Language#
β
Good:
```javascript
const x = 10;
```
β Bad:
```
const x = 10;
```Use Proper Indentation#
β
Good:
```javascript
function example() {
if (true) {
console.log('Properly indented');
}
}
```
β Bad:
```javascript
function example() {
if (true) {
console.log('Bad indentation');
}
}
```Add Comments#
```javascript
// Initialize user data
const user = {
name: 'Alice',
email: 'alice@example.com',
};
// Send welcome email
sendEmail(user.email, 'Welcome!');
```Keep Examples Focused#
β
Good - focused example:
```javascript
// Calculate total
const total = items.reduce((sum, item) => sum + item.price, 0);
```
β Bad - too much code:
```javascript
// 100 lines of unrelated code...
```Troubleshooting#
Language Not Recognized#
If a language isn't highlighted:
- Check the language name is correct
- Add it to
langsarray in highlighter config - See supported languages
Theme Not Working#
If theme doesn't apply:
- Check theme name is correct
- Add it to
themesarray in highlighter config - Rebuild the site:
npm run build
Code Not Highlighting#
If code blocks aren't highlighted:
- Check triple backticks are correct
- Verify language identifier is specified
- Check for syntax errors in code
- Rebuild the site
Examples#
Diff Highlighting#
Show code changes:
```diff
- const oldValue = 10;
+ const newValue = 20;
```Shell Commands#
```bash
# Install dependencies
npm install
# Start dev server
npm run dev
```Configuration Files#
```json
{
"name": "my-project",
"version": "1.0.0",
"scripts": {
"dev": "next dev",
"build": "next build"
}
}
```