Code Blocks
Syntax highlighting, line highlighting, titles, copy button, and advanced code block features in HolyDocs.
Overview
Code blocks are the backbone of technical documentation. HolyDocs renders fenced code blocks with syntax highlighting powered by Shiki, supporting 100+ programming languages out of the box. Every code block includes a copy button, optional line numbers, line highlighting, and a filename header.
Basic Usage
Create a code block by wrapping your code in triple backticks with a language identifier:
mdx```javascriptconst holydocs = require('@holydocs/cli');holydocs.deploy({ projectId: 'my-project' });```
The language identifier determines syntax highlighting. If omitted, the block renders as plain text.
Supported Languages
HolyDocs supports all major programming languages and configuration formats. Here are the most commonly used identifiers:
| Language | Identifier(s) | Language | Identifier(s) |
|---|---|---|---|
| JavaScript | javascript, js | TypeScript | typescript, ts |
| Python | python, py | Go | go |
| Rust | rust, rs | Java | java |
| Ruby | ruby, rb | PHP | php |
| C# | csharp, cs | C / C++ | c, cpp |
| Swift | swift | Kotlin | kotlin, kt |
| Shell / Bash | bash, shell, sh | PowerShell | powershell, ps1 |
| SQL | sql | GraphQL | graphql, gql |
| JSON | json | YAML | yaml, yml |
| TOML | toml | XML | xml |
| HTML | html | CSS | css |
| SCSS | scss | Markdown | markdown, md |
| MDX | mdx | Diff | diff |
| Docker | dockerfile | Nginx | nginx |
| Prisma | prisma | Protocol Buffers | protobuf |
If your language is not listed here, it is likely still supported. HolyDocs uses the full Shiki grammar library. Try using the standard file extension as the identifier.
Code Block Titles
Add a filename or descriptive title after the language identifier to display a header above the code block:
mdx```typescript docs.json{ "name": "My Docs", "theme": "holy"}```
mdx```python app/main.pyfrom fastapi import FastAPIapp = FastAPI()@app.get("/")async def root(): return {"message": "Hello World"}```
Titles are particularly useful when showing file contents, configuration examples, or when multiple code blocks on a page need to be distinguishable at a glance.
Line Highlighting
Highlight specific lines to draw attention to important code. Add line numbers in curly braces after the language identifier:
mdx```javascript {3,5-7}const express = require('express');const app = express();const port = 3000; // highlightedapp.get('/', (req, res) => { // highlighted res.send('Hello World'); // highlighted}); // highlightedapp.listen(port);```
Highlight Syntax
| Syntax | Description | Example |
|---|---|---|
{3} | Single line | Highlights line 3 |
{3,5} | Multiple lines | Highlights lines 3 and 5 |
{3-7} | Line range | Highlights lines 3 through 7 |
{1,3-5,8} | Mixed | Highlights line 1, lines 3-5, and line 8 |
Highlighted lines receive a subtle background tint that works in both light and dark modes.
Line Numbers
Enable line numbers on a code block by adding showLineNumbers after the language identifier:
mdx```typescript showLineNumbersinterface User { id: string; name: string; email: string; role: 'admin' | 'member' | 'viewer';}function getUser(id: string): Promise<User> { return fetch(`/api/users/${id}`).then(r => r.json());}```
Line numbers are useful for longer code blocks or when you need to reference specific lines in your prose.
Line numbers and line highlighting can be combined. Use {3,5} with showLineNumbers to highlight numbered lines.
Copy Button
Every code block includes a copy-to-clipboard button in the top-right corner. When clicked, the full contents of the block are copied and the button displays a checkmark confirmation for 2 seconds.
The copy button is automatic and requires no configuration. It copies only the raw code content, excluding line numbers and any decorative elements.
CodeGroup
The CodeGroup component renders multiple code blocks as a tabbed interface. This is ideal for showing the same concept in multiple languages or the same command for different package managers.
mdx<CodeGroup>```bash npmnpm install @holydocs/cli``````bash pnpmpnpm add @holydocs/cli``````bash yarnyarn add @holydocs/cli``````bash bunbun add @holydocs/cli```</CodeGroup>
Each code block's tab label is derived from the text after the language identifier. If no custom title is provided, the language name is used.
Multi-Language API Examples
mdx<CodeGroup>```javascript JavaScriptconst res = await fetch('https://api.example.com/users', { headers: { 'Authorization': 'Bearer YOUR_API_KEY' },});const users = await res.json();``````python Pythonimport requestsresponse = requests.get( 'https://api.example.com/users', headers={'Authorization': 'Bearer YOUR_API_KEY'},)users = response.json()``````go Goreq, _ := http.NewRequest("GET", "https://api.example.com/users", nil)req.Header.Set("Authorization", "Bearer YOUR_API_KEY")resp, _ := http.DefaultClient.Do(req)```</CodeGroup>
The reader's tab selection is persisted across CodeGroups on the same page. If a reader selects "Python" in one CodeGroup, all other CodeGroups on that page switch to "Python" too (when available).
Diff Highlighting
Use the diff language identifier to show additions and removals:
diff- const API_URL = 'http://localhost:3000';+ const API_URL = process.env.API_URL || 'http://localhost:3000'; async function fetchUsers() {- const res = await fetch(API_URL + '/users');+ const res = await fetch(`${API_URL}/users`, {+ headers: { 'Authorization': `Bearer ${getToken()}` },+ }); return res.json(); }
Lines prefixed with + are highlighted green, lines with - are highlighted red, and unchanged lines (prefixed with a space) render normally.
Diff in Typed Code Blocks
You can also show diffs within a syntax-highlighted code block by combining the language with diff markers. Use // [!code ++] and // [!code --] annotations at the end of lines:
mdx```typescriptconst config = { name: 'My Docs', theme: 'mint', // [!code --] theme: 'holy', // [!code ++] colors: { primary: '#007AFF', // [!code --] primary: '#FBBF24', // [!code ++] },};```
This approach preserves full TypeScript syntax highlighting while showing the diff.
Word Highlighting
Highlight specific words or phrases within a code block using the // [!code word:xxx] annotation:
mdx```typescript// [!code word:apiKey]const apiKey = process.env.API_KEY;const client = new Client({ apiKey });```
Every occurrence of apiKey in the block is highlighted with a subtle background, making it easy for readers to track a variable or concept through a longer code example.
Code Block Themes
HolyDocs supports two code block theme modes, configured in docs.json:
json{ "styling": { "codeblocks": "system" }}
| Value | Behavior |
|---|---|
system | Code blocks use a light theme in light mode and a dark theme in dark mode |
dark | Code blocks always use a dark background, regardless of the site theme |
Most documentation sites use "dark" because dark code blocks provide better contrast for syntax highlighting and remain visually consistent across both appearance modes.
Long Lines
By default, code blocks scroll horizontally when lines exceed the block width. This preserves the original formatting and prevents awkward line breaks in the middle of expressions.
If you prefer wrapping, you can enable it globally through custom CSS:
css.code-block pre { white-space: pre-wrap; word-break: break-all;}
Line wrapping can make code harder to read, especially for languages where indentation is significant (Python, YAML). Use horizontal scrolling unless you have a specific reason to wrap.
Inline Code
Use single backticks for inline code within paragraphs:
mdxRun `npm install` to install dependencies. The config file is `docs.json`.
Inline code is styled with a subtle background and monospace font. It does not receive syntax highlighting.
Best Practices
Without a language identifier, code blocks render as plain text with no highlighting. Even for simple shell commands, use bash or shell to provide visual structure.
When showing the contents of a specific file, always include the filename as a title. This gives readers immediate context about where the code lives in their project.
Show the minimum code needed to illustrate the concept. Avoid boilerplate that distracts from the point. When a full file is necessary, use line highlighting to focus on the relevant lines.
Whenever you show the same operation in multiple languages or tools (e.g., npm vs pnpm vs yarn), wrap them in a CodeGroup rather than listing them sequentially. This saves vertical space and lets readers pick their preference.
Instead of generic placeholders like YOUR_VALUE_HERE, use realistic example values that help readers understand the expected format. For sensitive values like API keys, use clearly fake values like sk_test_abc123.