---
title: "Syntax Highlighting"
description: "Syntax Highlighting in this system is powered by Shiki, leveraging its high-performance tokenization capabilities to provide semantic code highlighting within MDX and React components. The system i..."
last_updated: "2026-07-02T09:46:39.363642+00:00"
canonical_url: "https://www.doc0.dev/docs/e8872a72-1909-479c-b585-dc74c6e26726/technical/rendering-ui/syntax-highlighting"
---

<details>
<summary>Relevant source files</summary>

The following files were used as context for generating this wiki page:

- [packages/mdx/src/loaders/mdx/index.ts](https://github.com/blade47/fumadocs/blob/main/packages/mdx/src/loaders/mdx/index.ts)
- [packages/core/src/mdx-plugins/transformer-icon.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/mdx-plugins/transformer-icon.ts)
- [packages/mdx/src/loaders/mdx/remark-include.ts](https://github.com/blade47/fumadocs/blob/main/packages/mdx/src/loaders/mdx/remark-include.ts)
- [packages/mdx/src/node/_loader.ts](https://github.com/blade47/fumadocs/blob/main/packages/mdx/src/node/_loader.ts)
- [packages/core/src/mdx-plugins/rehype-code.core.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/mdx-plugins/rehype-code.core.ts)
- [packages/core/src/highlight/client.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/highlight/client.ts)
- [packages/obsidian/src/mdx/index.ts](https://github.com/blade47/fumadocs/blob/main/packages/obsidian/src/mdx/index.ts)
- [packages/core/src/mdx-plugins/rehype-code/shiki.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/mdx-plugins/rehype-code/shiki.ts)
- [packages/core/src/highlight/shiki/react.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/highlight/shiki/react.ts)
- [packages/mdx/src/webpack/meta.ts](https://github.com/blade47/fumadocs/blob/main/packages/mdx/src/webpack/meta.ts)
- [packages/base-ui/src/components/dynamic-codeblock.core.tsx](https://github.com/blade47/fumadocs/blob/main/packages/base-ui/src/components/dynamic-codeblock.core.tsx)
- [packages/radix-ui/src/components/dynamic-codeblock.core.tsx](https://github.com/blade47/fumadocs/blob/main/packages/radix-ui/src/components/dynamic-codeblock.core.tsx)
- [packages/core/src/highlight/index.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/highlight/index.ts)
- [packages/mdx/src/loaders/meta.ts](https://github.com/blade47/fumadocs/blob/main/packages/mdx/src/loaders/meta.ts)
- [packages/core/src/highlight/shiki/index.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/highlight/shiki/index.ts)
- [packages/core/src/mdx-plugins/remark-mdx-files.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/mdx-plugins/remark-mdx-files.ts)
- [packages/base-ui/src/components/codeblock.rsc.tsx](https://github.com/blade47/fumadocs/blob/main/packages/base-ui/src/components/codeblock.rsc.tsx)
- [packages/radix-ui/src/components/codeblock.rsc.tsx](https://github.com/blade47/fumadocs/blob/main/packages/radix-ui/src/components/codeblock.rsc.tsx)
- [packages/asyncapi/src/ui/components/codeblock.tsx](https://github.com/blade47/fumadocs/blob/main/packages/asyncapi/src/ui/components/codeblock.tsx)
- [packages/openapi/src/ui/components/codeblock.tsx](https://github.com/blade47/fumadocs/blob/main/packages/openapi/src/ui/components/codeblock.tsx)
- [packages/twoslash/src/index.ts](https://github.com/blade47/fumadocs/blob/main/packages/twoslash/src/index.ts)
- [packages/core/src/highlight/shiki/full.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/highlight/shiki/full.ts)
- [packages/core/src/mdx-plugins/rehype-code/parsers.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/mdx-plugins/rehype-code/parsers.ts)
- [packages/base-ui/src/components/codeblock.tsx](https://github.com/blade47/fumadocs/blob/main/packages/base-ui/src/components/codeblock.tsx)
- [packages/radix-ui/src/components/codeblock.tsx](https://github.com/blade47/fumadocs/blob/main/packages/radix-ui/src/components/codeblock.tsx)
- [packages/base-ui/css/lib/shiki.css](https://github.com/blade47/fumadocs/blob/main/packages/base-ui/css/lib/shiki.css)
- [packages/radix-ui/css/lib/shiki.css](https://github.com/blade47/fumadocs/blob/main/packages/radix-ui/css/lib/shiki.css)
- [packages/core/src/mdx-plugins/rehype-code.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/mdx-plugins/rehype-code.ts)
- [packages/mdx/src/loaders/config.ts](https://github.com/blade47/fumadocs/blob/main/packages/mdx/src/loaders/config.ts)
- [packages/core/src/highlight/utils.ts](https://github.com/blade47/fumadocs/blob/main/packages/core/src/highlight/utils.ts)
</details>

Syntax Highlighting in this system is powered by [Shiki](https://shiki.style), leveraging its high-performance tokenization capabilities to provide semantic code highlighting within MDX and React components. The system is designed to operate both as a static build-time transformation—converting code blocks into HTML structures during MDX compilation—and as a dynamic runtime client-side service for specialized components.

By decoupling the highlighter instance from the UI, the architecture allows for flexible theme management and on-demand language loading. The system handles the complexities of metadata parsing, line numbering, and icon injection through a pipeline of `rehype` plugins, ensuring that code blocks are rendered with proper styling, accessibility, and interactivity.

The system addresses the challenge of large bundle sizes by employing lazy-loading for languages and themes. When an unknown language or theme is requested, the system attempts to resolve and load it asynchronously. This ensures the initial bundle remains small while keeping the documentation flexible enough to support a vast array of programming languages and design tokens.

## Architecture and Pipeline Execution

The syntax highlighting system operates as a multi-stage pipeline, primarily integrated through `rehype`. During the build, the `rehype-code` plugin detects code nodes, parses meta-strings for configuration, and transforms them into syntax-highlighted HAST (HTML Abstract Syntax Tree) structures.

```mermaid
flowchart TD
    A["Raw MDX Code Block"] --> B["Rehype Plugin Pipeline"]
    B --> C["Parse Meta String"]
    C --> D["Identify Language"]
    D --> E["Load Theme/Language<br>(On-demand)"]
    E --> F["Apply Transformers<br>(Icon, Tab, Twoslash)"]
    F --> G["Render to HAST"]
    G --> H["Inject to UI"]
```
Sources: [packages/core/src/mdx-plugins/rehype-code.ts:19-34](https://github.com/blade47/fumadocs/blob/main/packages/core/src/mdx-plugins/rehype-code.ts#L19-L34), [packages/core/src/mdx-plugins/rehype-code.core.ts:82-142](https://github.com/blade47/fumadocs/blob/main/packages/core/src/mdx-plugins/rehype-code.core.ts#L82-L142)

## Shiki Instance Factory and Lifecycle

The `ShikiFactory` provides a mechanism for initializing and accessing the highlighter instance. It ensures that expensive initialization only occurs once, supporting lazy-loading of engines (either `js` or `oniguruma` via WASM).

> [!TIP]
> The `getOrInit` method ensures that the highlighter instance is reused across the entire application lifecycle, preventing redundant loading of the heavy tokenization engine.

Sources: [packages/core/src/highlight/shiki/index.ts:20-36](https://github.com/blade47/fumadocs/blob/main/packages/core/src/highlight/shiki/index.ts#L20-L36)

## Meta String Parsing and Configuration

Meta strings inside code blocks (e.g., `ts {1,3} title="example.ts"`) are processed by custom parsers. The core logic extracts data attributes like titles, line numbers, and custom metadata, transforming them into a structured data object used by the Shiki pipeline.

The `parseMetaString` function allows users to define custom transformations. For example, `lineNumbers=5` is stripped from the meta string and converted into the `data-line-numbers-start` attribute.

Sources: [packages/core/src/mdx-plugins/rehype-code.core.ts:37-56](https://github.com/blade47/fumadocs/blob/main/packages/core/src/mdx-plugins/rehype-code.core.ts#L37-L56)

## Dynamic Code Execution Flow

For interactive or documentation-heavy UI components (like API Docs or OpenApi), the system uses dynamic highlighting at runtime. This avoids shipping large bundles to the browser while maintaining high-fidelity code display.

```mermaid
sequenceDiagram
    participant UI as DynamicCodeBlock
    participant SH as Shiki Instance
    participant Hook as useShikiDynamic
    
    UI->>Hook: Request highlight(lang, code)
    Hook->>SH: Ensure language/theme loaded
    SH-->>Hook: Instance Ready
    Hook->>SH: codeToHast(code, options)
    SH-->>Hook: HAST Fragments
    Hook->>UI: Render HAST to React Components
```
Sources: [packages/core/src/highlight/shiki/react.ts:27-59](https://github.com/blade47/fumadocs/blob/main/packages/core/src/highlight/shiki/react.ts#L27-L59), [packages/base-ui/src/components/dynamic-codeblock.core.tsx:45-67](https://github.com/blade47/fumadocs/blob/main/packages/base-ui/src/components/dynamic-codeblock.core.tsx#L45-L67)

## Language and Theme Resolution

To keep the system performant, `utils.ts` contains logic to check if languages and themes are already registered in the current `HighlighterCore` instance. If a language or theme is requested but not present, the `loadMissingLanguage` and `loadMissingTheme` helpers are triggered to fetch them asynchronously before execution.

| Function | Purpose |
| :--- | :--- |
| `loadMissingTheme` | Dynamically loads a theme registration if not in `bundledThemes`. |
| `loadMissingLanguage` | Dynamically loads a language registration if not in `bundledLanguages`. |
| `getRequiredThemes` | Resolves standard theme sets from the configuration. |

Sources: [packages/core/src/highlight/utils.ts:9-55](https://github.com/blade47/fumadocs/blob/main/packages/core/src/highlight/utils.ts#L9-L55)

## Transformer Extension Points

Shiki transformers are used to manipulate the AST before serialization. The system includes pre-defined transformers for notation diffing, focus, and word highlighting, along with custom extensions like icon injection.

> [!WARNING]
> Transformers are executed sequentially. The order in which they are added to the `transformers` array is critical, especially when modifying node structures.

Sources: [packages/core/src/mdx-plugins/rehype-code.core.ts:107-115](https://github.com/blade47/fumadocs/blob/main/packages/core/src/mdx-plugins/rehype-code.core.ts#L107-L115)

## Practical Implementation Example

To implement a syntax-highlighted code block in a React component, use the `DynamicCodeBlock` provided by the base UI package:

```tsx
import { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock.core';
import { getHighlighter } from 'fumadocs-core/highlight';

export default function MyPage() {
  return (
    <DynamicCodeBlock
      highlighter={() => getHighlighter('js')}
      lang="typescript"
      code="const greeting: string = 'Hello World';"
      options={{ theme: { light: 'github-light', dark: 'github-dark' } }}
    />
  );
}
```
Sources: [packages/base-ui/src/components/dynamic-codeblock.core.tsx:45-67](https://github.com/blade47/fumadocs/blob/main/packages/base-ui/src/components/dynamic-codeblock.core.tsx#L45-L67)

## Related

- [Twoslash Highlight](https://www.doc0.dev/docs/e8872a72-1909-479c-b585-dc74c6e26726/technical/rendering-ui/twoslash-highlight)
- [Base Components](https://www.doc0.dev/docs/e8872a72-1909-479c-b585-dc74c6e26726/technical/rendering-ui/base-components)


## Sitemap

See the full [sitemap](https://www.doc0.dev/docs/e8872a72-1909-479c-b585-dc74c6e26726/llms.txt) for all pages in this wiki.
