惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
WordPress大学
WordPress大学
Google DeepMind News
Google DeepMind News
T
The Exploit Database - CXSecurity.com
阮一峰的网络日志
阮一峰的网络日志
F
Fox-IT International blog
The GitHub Blog
The GitHub Blog
Engineering at Meta
Engineering at Meta
I
Intezer
P
Privacy & Cybersecurity Law Blog
B
Blog RSS Feed
Latest news
Latest news
小众软件
小众软件
A
Arctic Wolf
Attack and Defense Labs
Attack and Defense Labs
L
LINUX DO - 热门话题
博客园 - 聂微东
B
Blog
T
Troy Hunt's Blog
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
Malwarebytes
Malwarebytes
爱范儿
爱范儿
Recorded Future
Recorded Future
Apple Machine Learning Research
Apple Machine Learning Research
人人都是产品经理
人人都是产品经理
D
Docker
T
Threat Research - Cisco Blogs
MyScale Blog
MyScale Blog
Martin Fowler
Martin Fowler
E
Exploit-DB.com RSS Feed
F
Fortinet All Blogs
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
PCI Perspectives
PCI Perspectives
Scott Helme
Scott Helme
N
Netflix TechBlog - Medium
博客园 - 三生石上(FineUI控件)
T
True Tiger Recordings
C
Check Point Blog
Microsoft Azure Blog
Microsoft Azure Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
K
Kaspersky official blog
Security Latest
Security Latest
The Hacker News
The Hacker News
Microsoft Security Blog
Microsoft Security Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
Stack Overflow Blog
Stack Overflow Blog
S
Security @ Cisco Blogs
C
CXSECURITY Database RSS Feed - CXSecurity.com
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
M
Microsoft Research Blog - Microsoft Research

Streamdown Documentation

Migrate from react-markdown Custom renderers @streamdown/mermaid @streamdown/math Built-in Plugins @streamdown/code @streamdown/cjk Usage Typography Unterminated Block Parsing Styling Security Animation Memoization Link Safety Internationalization Interactivity Introduction GitHub Flavored Markdown Getting Started FAQ Configuration Components Carets
Code Blocks
Vercel · 2026-04-11 · via Streamdown Documentation

Beautiful syntax highlighting and interactive code blocks powered by Shiki.

Streamdown provides beautiful, interactive code blocks with syntax highlighting powered by Shiki. Every code block includes a copy button and supports a wide range of programming languages.

Create code blocks using triple backticks with an optional language identifier:

```javascript
function greet(name) {
  return `Hello, ${name}!`;
}
```

Streamdown will automatically apply syntax highlighting based on the specified language.

Syntax highlighting requires the code plugin. Install it:

Then import and pass the plugin to Streamdown:

import { Streamdown } from "streamdown";
import { code } from "@streamdown/code";

export default function Page() {
  return (
    <Streamdown plugins={{ code: code }}>
      {markdown}
    </Streamdown>
  );
}

Without the code plugin, code blocks render as plain text with no highlighting.

Streamdown supports 200+ programming languages through Shiki. All languages are lazy-loaded on demand, so only the grammars you use are downloaded.

Common Languages

  • Web: JavaScript, TypeScript, JSX, TSX, HTML, CSS
  • Data: JSON, YAML, TOML
  • Shell: Bash, Shell Script, PowerShell
  • Backend: Python, Go, Java, Rust, C, C++, C#, PHP, Ruby
  • Functional: Haskell, Elixir, Clojure, F#, OCaml
  • Markup: Markdown, LaTeX, MDX, XML
  • And 180+ more languages

Language Examples

TypeScript

```typescript
interface User {
  id: number;
  name: string;
  email: string;
}

async function fetchUser(id: number): Promise<User> {
  const response = await fetch(`/api/users/${id}`);
  return response.json();
}
```

Python

```python
def fibonacci(n: int) -> list[int]:
    """Generate Fibonacci sequence up to n terms."""
    fib = [0, 1]
    for i in range(2, n):
        fib.append(fib[i-1] + fib[i-2])
    return fib

print(fibonacci(10))
```

Rust

```rust
fn main() {
    let numbers = vec![1, 2, 3, 4, 5];
    let sum: i32 = numbers.iter().sum();
    println!("Sum: {}", sum);
}
```

Streamdown uses dual themes for light and dark modes. You can customize the themes using the shikiTheme prop:

import { Streamdown } from "streamdown";
import { code } from "@streamdown/code";

export default function Page() {
  return (
    <Streamdown
      plugins={{ code: code }}
      shikiTheme={["dracula", "dracula"]}
    >
      {markdown}
    </Streamdown>
  );
}

Available Themes

Streamdown supports all Shiki themes including:

  • github-light (default light theme)
  • github-dark (default dark theme)
  • dracula, nord, one-dark-pro, monokai
  • catppuccin-latte, catppuccin-mocha
  • vitesse-light, vitesse-dark
  • tokyo-night, slack-dark, slack-ochin
  • And many more

Custom theme objects

The shikiTheme prop accepts [ThemeInput, ThemeInput] where ThemeInput is either a bundled theme name (BundledTheme) or a custom theme object (ThemeRegistrationAny). You can mix and match:

import { Streamdown } from "streamdown";
import { code } from "@streamdown/code";
import myCustomDarkTheme from "./my-dark-theme.json";

export default function Page() {
  return (
    <Streamdown
      plugins={{ code: code }}
      shikiTheme={["github-light", myCustomDarkTheme]}
    >
      {markdown}
    </Streamdown>
  );
}

Bundled theme names (strings) load from Shiki's built-in registry. Custom theme objects follow the ThemeRegistrationAny format from Shiki — any VS Code .tmTheme or JSON theme file works.

Set the starting line number for a code block using startLine=N in the code fence meta:

```typescript startLine=10
const user = await getUser(id);
const profile = await getProfile(user);
```

Line numbers begin at the value you specify instead of 1. The value must be a positive integer (>= 1).

Copy Button

Every code block includes a copy button that appears on hover. Users can click to copy the entire code block content to their clipboard.

The copy button:

  • Appears on hover (desktop) or is always visible (mobile)
  • Provides visual feedback on successful copy
  • Is automatically disabled during streaming (when isAnimating={true})

Disable Controls

Disable individual code block buttons using the controls prop:

// Hide the download button, keep copy
<Streamdown controls={{ code: { download: false } }}>{markdown}</Streamdown>

// Hide the copy button, keep download
<Streamdown controls={{ code: { copy: false } }}>{markdown}</Streamdown>

// Hide all code block controls
<Streamdown controls={{ code: false }}>{markdown}</Streamdown>

// Hide all controls across all block types
<Streamdown controls={false}>{markdown}</Streamdown>

Inline code uses backticks and receives subtle styling:

Use the `useState` hook to manage state in React.

Inline code is styled with:

  • Monospace font family
  • Subtle background color
  • Rounded corners
  • Appropriate padding

Code blocks include:

  • Line Numbers - Optional line numbers for reference
  • Rounded Corners - Modern, polished appearance
  • Proper Padding - Comfortable spacing
  • Scrolling - Horizontal scroll for long lines
  • Responsive Design - Adapts to container width

Code blocks work seamlessly with streaming content:

Incomplete Code Blocks

When a code block is streaming in, Streamdown handles the incomplete state gracefully:

```javascript
function example() {
  // Streaming in progress...
```

The unterminated block parser ensures the code block renders properly even without the closing backticks.

Loading Behavior

Code block shells render immediately with plain text content, then syntax colors are applied when highlighting resolves.

This keeps code readable on first paint and improves visual stability during lazy highlight loading.

Disabling Interactions During Streaming

Use the isAnimating prop to disable copy buttons while streaming:

<Streamdown isAnimating={isStreaming}>{markdown}</Streamdown>

This prevents users from copying incomplete code.

The Code plugin implements the CodeHighlighterPlugin interface:

interface CodeHighlighterPlugin {
  name: "shiki";
  type: "code-highlighter";
  highlight: (options: HighlightOptions, callback?: (result: HighlightResult) => void) => HighlightResult | null;
  supportsLanguage: (language: BundledLanguage) => boolean;
  getSupportedLanguages: () => BundledLanguage[];
  getThemes: () => [BundledTheme, BundledTheme];
}

Exported Types

import type {
  CodeHighlighterPlugin,
  HighlightOptions,
  HighlightResult,
} from '@streamdown/code';

// HighlightOptions - parameters for highlighting
interface HighlightOptions {
  code: string;
  language: BundledLanguage;
  themes: [string, string];
}

// HighlightResult - Shiki's TokensResult type
type HighlightResult = TokensResult;

Programmatic Highlighting

Use the plugin directly for custom highlighting:

import { code } from '@streamdown/code';

// Check language support
if (code.supportsLanguage('typescript')) {
  code.highlight(
    { code: 'const x = 1;', language: 'typescript', themes: ['github-light', 'github-dark'] },
    (result) => {
      // Handle highlighted tokens
      console.log(result.tokens);
    }
  );
}