Syntax Highlighting
BunPress provides beautiful code syntax highlighting powered by ts-syntax-highlighter, a blazing-fast, zero-dependency syntax highlighter built specifically for Bun.
Overview
Code blocks in your markdown are automatically highlighted with proper syntax coloring for better readability. The highlighter supports multiple languages and includes features like line highlighting, line numbers, and diff indicators.
Supported Languages
BunPress supports syntax highlighting for the following languages:
- JavaScript (
js,javascript,jsx) - TypeScript (
ts,typescript,tsx) - HTML (
html,htm) - CSS (
css) - JSON (
json) - STX (
stx) - Blade-like templating
Important
Shell/Bash commands (bash, sh, shell) are not currently supported for syntax highlighting. Code will be displayed in a monospace font with HTML entities properly escaped for security.
Tip
For shell commands, you can omit the language identifier or use text for plain formatting.
Basic Usage
Simply use standard markdown code fences with a language identifier:
const greeting = 'Hello World'
console.log(greeting)
Result:
const greeting ='Hello World' 'Hello World'
console.log(greeting)
Language Examples
JavaScript
function fibonacci(n) {
if (n <= 1) return n
return fibonacci(n - 1) + fibonacci(n - 2)
}
const result = fibonacci(10)
console.log(result)
TypeScript
interface User {
name: string
age: number
email?: string
}
function greetUser(user: User): string {
return Hello, ${user.name}!
}
const user: User = { name: 'Alice', age: 30 }
console.log(greetUser(user))
HTML
Welcome
CSS
.container {
display: flex;
flex-direction: column;
gap: 1rem;
padding: 2rem;
background: linear-gradient(to right, #667eea, #764ba2);
}
@media (prefers-color-scheme: dark) {
.container {
background: #1a1a1a;
}
}
JSON
{
"name": "bunpress",
"version": "1.0.0",
"description": "Modern documentation engine",
"dependencies": {
"ts-syntax-highlighter": "^0.1.0"
}
}
Advanced Features
Line Highlighting
Highlight specific lines to draw attention to important code:
function fibonacci(n) {
if (n <= 1) return n // This line is highlighted
let a = 0 // These lines
let b = 1 // are also
let temp // highlighted
for (let i = 2; i <= n; i++) {
temp = a + b
a = b
b = temp
}
return b
}
Note
Use {line-numbers} syntax where line-numbers can be a single number, a range (1-5), or a comma-separated list (1,3,5-7).
Line Numbers
Enable line numbers for easier reference:
function add(a: number, b: number): number {
return a + b
}
function multiply(a: number, b: number): number {
return a * b
}
Inline Code Markers
Use special comments to add visual indicators to your code:
Focus Lines
function example() {
const important = true // [!code focus]
const other = false
return important
}
Tip
Focused lines remain clear while unfocused lines are dimmed.
Diff Highlighting
function greet(name) {
console.log('Hi') // [!code --]
console.log(Hello, ${name}!) // [!code ++]
}
Error and Warning Indicators
function divide(a, b) {
return a / b // [!code error]
// Should check for division by zero!
}
function calculate(x) {
const result = x * 2 // [!code warning]
// Consider using a more descriptive variable name
return result
}
Code in Multiple Languages
Use code groups to show examples in different languages:
npm install bunpress
yarn add bunpress
bun add bunpress
See Code Groups for more details.
Themes
BunPress uses a light theme by default with automatic dark mode support:
- Light theme: Clean, GitHub-inspired colors
- Dark theme: Automatically applied based on system preferences
The theme switching uses CSS media queries:
@media (prefers-color-scheme: dark) {
/* Dark theme styles applied here */
}
Note
Custom theme support is planned for future versions.
Performance
The syntax highlighter is designed for speed:
- Async tokenization: Non-blocking, efficient parsing
- Built-in caching: Repeated highlights are faster
- Zero dependencies: No heavy grammar files to load
- Bun-optimized: Built specifically for the Bun runtime
Typical Performance
| Code Size | Highlight Time |
|---|---|
| Small (10-20 lines) | < 50ms |
| Medium (50 lines) | < 100ms |
| Large (100+ lines) | < 500ms |
Styling
The syntax highlighter provides comprehensive CSS classes for customization:
/* Basic code block styling */
pre {
overflow-x: auto;
padding: 1rem;
border-radius: 0.5rem;
}
/* Line highlighting */
.line.highlighted {
background-color: rgba(255, 255, 0, 0.1);
border-left: 3px solid #fbbf24;
}
/* Focus mode */
.line.focused {
filter: none;
}
.line.dimmed {
opacity: 0.5;
}
/* Diff highlighting */
.line.diff-add {
background-color: rgba(16, 185, 129, 0.1);
border-left: 3px solid #10b981;
}
.line.diff-remove {
background-color: rgba(239, 68, 68, 0.1);
border-left: 3px solid #ef4444;
}
Comparison with Shiki
BunPress previously used Shiki but switched to ts-syntax-highlighter for several reasons:
| Feature | ts-syntax-highlighter | Shiki |
|---|---|---|
| Bundle Size | ~50KB | ~6MB |
| Dependencies | Zero | Many |
| Performance | Async, cached | Slower initialization |
| Bun Native | ✅ Yes | ❌ No |
| Grammar Files | Built-in | External |
| Language Support | 6 core languages | 200+ languages |
Tip
If you need support for languages beyond the core 6, ts-syntax-highlighter supports custom language definitions.
Troubleshooting
Code not highlighting
If your code isn't being highlighted:
1. Check the language identifier - Make sure you're using a supported language
2. Verify the syntax - Ensure the code fence uses triple backticks
3. Check for typos - Language identifiers are case-insensitive but must be spelled correctly
✅ Correct:
const x = 42
❌ Incorrect:
const x = 42
\`\`\`
<div class="github-alert github-alert-note">
<p class="github-alert-title">
<svg class="github-alert-icon" viewBox="0 0 16 16" width="16" height="16" aria-hidden="true"><path d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5 7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"></path></svg>
Note
</p>
<div class="github-alert-content">
<p>Common unsupported languages include: <code>bash</code>, <code>sh</code>, <code>shell</code>, <code>python</code>, <code>ruby</code>, <code>go</code>, <code>rust</code>, <code>java</code>, <code>php</code>, and others. These will display as plain monospace text.</p>
</div>
</div>
### Styling issues
If the highlighting doesn't look right:
<div class="github-alert github-alert-important">
<p class="github-alert-title">
<svg class="github-alert-icon" viewBox="0 0 16 16" width="16" height="16" aria-hidden="true"><path d="M0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v9.5A1.75 1.75 0 0 1 14.25 13H8.06l-2.573 2.573A1.458 1.458 0 0 1 3 14.543V13H1.75A1.75 1.75 0 0 1 0 11.25Zm1.75-.25a.25.25 0 0 0-.25.25v9.5c0 .138.112.25.25.25h2a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h6.5a.25.25 0 0 0 .25-.25v-9.5a.25.25 0 0 0-.25-.25Zm7 2.25v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 9a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path></svg>
Important
</p>
<div class="github-alert-content">
<p>Make sure your custom CSS isn't overriding the syntax highlighting styles.</p>
</div>
</div>
Check for CSS conflicts in your browser's developer tools.
### Performance issues
For very large code blocks:
<div class="github-alert github-alert-tip">
<p class="github-alert-title">
<svg class="github-alert-icon" viewBox="0 0 16 16" width="16" height="16" aria-hidden="true"><path d="M8 1.5c-2.363 0-4 1.69-4 3.75 0 .984.424 1.625.984 2.304l.214.253c.223.264.47.556.673.848.284.411.537.896.621 1.49a.75.75 0 0 1-1.484.211c-.04-.282-.163-.547-.37-.847a8.456 8.456 0 0 0-.542-.68c-.084-.1-.173-.205-.268-.32C3.201 7.75 2.5 6.766 2.5 5.25 2.5 2.31 4.863 0 8 0s5.5 2.31 5.5 5.25c0 1.516-.701 2.5-1.328 3.259-.095.115-.184.22-.268.319-.207.245-.383.453-.541.681-.208.3-.33.565-.37.847a.751.751 0 0 1-1.485-.212c.084-.593.337-1.078.621-1.489.203-.292.45-.584.673-.848.075-.088.147-.173.213-.253.561-.679.985-1.32.985-2.304 0-2.06-1.637-3.75-4-3.75ZM5.75 12h4.5a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1 0-1.5ZM6 15.25a.75.75 0 0 1 .75-.75h2.5a.75.75 0 0 1 0 1.5h-2.5a.75.75 0 0 1-.75-.75Z"></path></svg>
Tip
</p>
<div class="github-alert-content">
<p>Consider splitting large code examples into smaller, focused examples.</p>
</div>
</div>
Smaller code blocks are easier to read and highlight faster.
## Best Practices
### Choose the Right Language
Always specify the language for better highlighting:
✅ Good:
const greeting: string ='Hello' 'Hello'
❌ Avoid:
const greeting = 'Hello'
\\\`
Keep Code Examples Focused
Tip
Show only relevant code. Use comments or line highlighting to guide attention.
// ✅ Good: Focused example
interface User {
name: string
age: number
}
// ❌ Avoid: Too much code
// (showing entire file with hundreds of lines)
Use Inline Code for Single Values
For short snippets, use inline code instead of code blocks:
Use the `console.log()` function to debug.
Set `DEBUG=true` in your environment.
Combine with Other Features
Syntax highlighting works great with other BunPress features:
- Code groups for multi-language examples
- GitHub alerts for important notes
- Code imports to sync with actual source files
- Containers for expandable code examples
API Reference
For programmatic use, BunPress exports the following functions:
import {
highlightCode,
normalizeLanguage,
isLanguageSupported,
getSyntaxHighlightingStyles
} from'@stacksjs/bunpress' '@stacksjs/bunpress'
// Highlight code (async)
const html = await highlightCode('const x = 42''const x = 42','javascript' 'javascript')
// Check if language is supported
if (isLanguageSupported('python''python')) {
// Language is supported
}
// Normalize language alias
const lang = normalizeLanguage('js''js')// Returns 'javascript' // Returns 'javascript'
// Get CSS styles
const styles = getSyntaxHighlightingStyles()
Note
These functions are primarily for advanced usage and plugin development. Most users won't need to use them directly.
Working with Shell Commands
Since bash/sh is not currently supported, here are some alternatives for displaying shell commands:
Option 1: Use Plain Text
Omit the language identifier or use text:
npm install bunpress
bun add bunpress
Option 2: Use Code Groups
For package manager commands, use code groups without highlighting:
<div class="code-group" id="code-group-1p7wi11us">
<div class="code-group-tabs">
<button class="code-group-tab active" onclick="switchCodeTab('code-group-1p7wi11us', 0)">npm</button><button class="code-group-tab " onclick="switchCodeTab('code-group-1p7wi11us', 1)">yarn</button><button class="code-group-tab " onclick="switchCodeTab('code-group-1p7wi11us', 2)">bun</button>
</div>
<div class="code-group-panels">
<div class="code-group-panel active" data-panel="0">
<pre data-lang="text"><code class="language-text"><span class="line">npm install bunpress</span>
<span class="line"></span></code></pre>
</div>
<div class="code-group-panel " data-panel="1">
<pre data-lang="text"><code class="language-text"><span class="line">yarn add bunpress</span>
<span class="line"></span></code></pre>
</div>
<div class="code-group-panel " data-panel="2">
<pre data-lang="text"><code class="language-text"><span class="line">bun add bunpress</span>
<span class="line"></span></code></pre>
</div>
</div>
</div>
Option 3: Inline Code
For short commands, use inline code:
Run `npm install bunpress` to install.
Use `bun dev` to start the development server.
Note
Shell/Bash highlighting support is planned for a future release through custom language definitions.
Future Enhancements
Planned improvements for syntax highlighting:
- [ ] Shell/Bash language support
- [ ] Additional language support (Python, Ruby, Go, Rust, etc.)
- [ ] Custom theme creation
- [ ] Copy-to-clipboard buttons
- [ ] Code playground integration
- [ ] Syntax highlighting in search results
See Also
- Code Groups - Tabbed code examples
- Code Imports - Import code from files
- Markdown Extensions - All markdown features
- Examples - More real-world examples