Code Blocks

Fern uses Shiki for syntax highlighting in code blocks. It’s reliable and performant. Below are examples of how you can configure syntax highlighting in code snippets.

Basic

To create a code snippet, you need to wrap your code in three backticks. You can also specify the language for syntax highlighting after the opening backticks.

1console.log("hello world")

Titles

You can add a title to your code snippet by adding a title after the language identifier.

Hello World Snippet
1console.log("hello world")

Line highlighting

You can highlight specific lines in your code snippet by placing a numeric range inside {} after the language identifier.

1console.log("Line 1");
2console.log("Line 2");
3console.log("Line 3");
4console.log("Line 4");
5console.log("Line 5");

Line focusing

Instead of highlighting lines, you can focus on specific lines by adding a comment [!code focus] or by adding a focus attribute after the language identifier. The focus attribute works the same way as the highlight attribute.

1console.log("Line 1");
2console.log("Line 2");
3console.log("Line 3");
4console.log("Line 4");
5console.log("Line 5");

Start line

You can control which line appears first in your code block by adding a startLine attribute after the language identifier. This is particularly useful for longer code snippets where you want to highlight the main logic while still providing the complete context.

1console.log("Line 1");
2console.log("Line 2");
3console.log("Line 3");
4console.log("Line 4");
5console.log("Line 5");
6console.log("Line 6");
7console.log("Line 7");
8console.log("Line 8");
9console.log("Line 9");
10console.log("Line 10");
11console.log("Line 11");
12console.log("Line 12");
13console.log("Line 13");
14console.log("Line 14");
15console.log("Line 15");
16console.log("Line 16");
17console.log("Line 17");
18console.log("Line 18");
19console.log("Line 19");
20console.log("Line 20");
21console.log("Line 21");
22console.log("Line 22");
23console.log("Line 23");
24console.log("Line 24");
25console.log("Line 25");
26console.log("Line 26");
27console.log("Line 27");
28console.log("Line 28")

Max height

You can control the max height of the code block by adding a maxLines attribute after the language identifier. The maxLines attribute should be a number representing the maximum number of lines to display. By default, the code block will display up to 20 lines.

When you use maxLines, an expand button automatically appears on hover in the top-right corner, allowing users to view the full code content in an expanded overlay that displays over the page.

1def is_prime(num):
2 """Check if a number is prime."""
3 if num <= 1:
4 return False
5 for i in range(2, num):
6 if num % i == 0:
7 return False
8 return True
9
10start = 10
11end = 50
12
13print(f"Prime numbers between {start} and {end} are:")
14
15prime_numbers = []
16
17for num in range(start, end+1):
18 if is_prime(num):
19 prime_numbers.append(num)
20
21for prime in prime_numbers:
22 print(prime)

To hide the expand button or add custom styling, target the .fern-expand-button selector:

1/* Hide the expand button */
2.fern-expand-button {
3 display: none;
4}

Wrap overflow

By default, long lines that exceed the width of the code block become scrollable:

Without wordWrap
A very very very long line of text that may cause the code block to overflow and scroll as a result.

To disable scrolling and wrap overflow onto the next line, use the wordWrap prop:

With wordWrap
A very very very long line of text that may cause the code block to overflow and scroll as a result.

Deep linking

You can make specific text within code blocks clickable by defining a links map. This is useful for linking to documentation, API references, or related resources directly from your code examples.

The links property accepts a map where keys are matching patterns (exact strings or regex) and values are the URLs to link to.

Exact string matching

1import { PlantClient } from "@plantstore/sdk";
2
3const client = new PlantClient({ apiKey: "YOUR_API_KEY" });
4const plant = await client.createPlant({
5 name: "Monstera",
6 species: "Monstera deliciosa"
7});

The links property uses JSON format. Each key in the map is matched exactly against text in the Code Block, and matching text becomes a clickable link to the corresponding URL.

Regex pattern matching

You can use regex patterns for more flexible matching. This is useful when you want to link multiple variations or patterns of text.

In the example below, the pattern /get\\w+/ matches both getPlant and getGarden, while /Plant(Store|Client)/ matches both PlantStore and PlantClient.

1from plantstore import PlantStore, PlantClientfrom plantstore import PlantStore, PlantClient
2
3store = PlantStore(api_key="YOUR_API_KEY")
4client = PlantClient(store)
5
6plant = store.getPlant(plant_id="123")
7garden = store.getGarden(garden_id="456")

When using regex patterns, remember to escape special characters with double backslashes (e.g., \\w+, \\d+) in the JSON string.

Combining props

You can combine the title, highlight, focus, startLine, maxLines, wordWrap, and links props to create a code block with a title, highlighted lines, specific starting line, a maximum height, and clickable links.

Hello, World!
1console.log("Line 1");
2console.log("Line 2");
3console.log("Line 3");
4console.log("Line 4");
5console.log("Line 5");
6console.log("Line 6");
7console.log("Line 7");
8console.log("Line 8");
9console.log("Line 9");
10console.log("Line 10");

Code Blocks with Tabs

The CodeBlocks component allows you to display multiple code blocks in a tabbed interface.

1puts "Hello World"

Language synchronization

Multiple CodeBlocks on a documentation site automatically synchronize. This means when a user selects a CodeBlock with a specific language, all other CodeBlocks across your documentation site with the same language will automatically sync and switch to match. Language preferences are stored in client-side local storage and persist across browser sessions.

The example below demonstrates language sync in action – choosing a language in either set of CodeBlocks will automatically update both sets to match:

1print("First code block!")
1print("Second code block - syncs with the one above!")
Tabs and CodeBlocks integration

CodeBlocks automatically synchronize with <Tab> components that have a language property.

Linking to language-specific content

You can link directly to content in a specific language by adding ?language=<some-language> to the end of a URL. This sets which language tab wil be displayed by default when users visit the page.

For example, the following link opens with Java tabs displayed: https://buildwithfern.com/learn/docs/writing-content/components/tabs?language=java

This works with both CodeBlocks and Tab components that have a language property.

Override synchronization

You can override the synchronization of code blocks by setting the for prop.

$npm install plantstore
$npm uninstall plantstore

Embed local code files

Option A

1console.log("I love Fern!");

Option B

example-code.js
1console.log("I love Fern!");