Skip to content

Code Component

In addition to rendering fenced code blocks in markdown & MDX documents, the Expressive Code Astro & Starlight integrations also provide a <Code> component that can be used in .mdx and .astro files.

In contrast to static fenced code blocks, the <Code> component allows you to dynamically define a code block’s contents using props. This makes it possible to render code blocks from variables or data coming from external sources like files, databases or APIs.

To use the <Code> component, you must first import it into your file. The location and syntax of the import statement depend on the file type and integration you’re using:

To get started, add an import statement to the content section of your .mdx file (the part below the frontmatter block). You can then use the component anywhere in the content.

src/content/docs/example.mdx
---
title: My example page
---
import { Code } from 'astro-expressive-code/components'
<Code code="console.log('Hello world!')" lang="js" />

The code above generates the following on the page:

console.log('Hello world!')

The <Code> component enables you to render code blocks in .astro files. This allows you to use all features of Expressive Code in your pages, and even creating custom components that wrap the <Code> component to provide additional functionality.

Using the component in .astro files works just like in .mdx files, except that you need to place the import statement inside the frontmatter block:

src/pages/index.astro
---
import MainLayout from '../layouts/MainLayout.astro'
import { Code } from 'astro-expressive-code/components'
---
<MainLayout>
<h1>My example page</h1>
<p>Here is some interesting code:</p>
<Code code="console.log('Hello world!')" lang="js" />
</MainLayout>

The true power of the <Code> component lies in its ability to render code blocks from variables or data coming from external sources like files, databases or APIs.

To do this, set the component’s props like code, lang, title etc. to variables instead of static values.

src/content/docs/example.mdx
---
title: My example page
---
import { Code } from 'astro-expressive-code/components'
export const exampleCode = `console.log('This could come from a file or CMS!');`
export const fileName = 'example.js'
export const highlights = ['file', 'CMS']
<Code code={exampleCode} lang="js" title={fileName} mark={highlights} />

The code above generates the following on the page:

example.js
console.log('This could come from a file or CMS!');

Use Vite’s ?raw import suffix to import any code file as a string. You can then pass this imported string to the <Code> component to include it on your page.

This is especially useful when documenting a project, as your code examples will always be up-to-date with the actual code.

You can also use this feature to create reusable snippets and include them in multiple code blocks on your site.

src/content/docs/example.mdx
import { Code } from 'astro-expressive-code/components';
import importedCode from '/src/env.d.ts?raw';
<Code code={importedCode} lang="ts" title="src/env.d.ts" />

The code above generates the following on the page:

src/env.d.ts
/* eslint-disable @typescript-eslint/triple-slash-reference */
/// <reference path="../.astro/types.d.ts" />
/// <reference types="astro/client" />

The <Code> component is designed to automatically pick up the Expressive Code configuration options from your project’s Astro config file without requiring any additional setup.

Due to the way Astro works, the Expressive Code integration can only share its configuration with the component by serializing it to JSON. In some situations, this is not possible, e.g. when your configuration includes custom plugins or functions that are not serializable to JSON.

In these cases, you will receive the following error message when trying to use the <Code> component:

[ERROR] Failed to render a <Code> component on page […]:

Your Astro config file contains Expressive Code options that are not serializable to JSON. To use the <Code> component, please create a separate config file called ec.config.mjs in your project root, move your Expressive Code options object into the config file, and export it as the default export.

As instructed by the error message, you can fix this issue by creating a separate ec.config.mjs file in your project root and moving your Expressive Code options object into the config file. Here is an example of how this file could look like if you’re using the collapsible sections plugin:

ec.config.mjs
import { defineEcConfig } from 'astro-expressive-code'
import { pluginCollapsibleSections } from '@expressive-code/plugin-collapsible-sections'
export default defineEcConfig({
// Example: Using a custom plugin (which makes this `ec.config.mjs` file necessary)
plugins: [pluginCollapsibleSections()],
// ... any other options you want to configure
})

You can find a list of all default props that can be used with the <Code> component below.

Type: string

The plaintext contents of the code block. This property is required and must be set to a non-empty string.

Type: string | undefined Default: undefined

The code block’s language.

Please use a valid language identifier to ensure proper syntax highlighting.

Type: string | undefined Default: undefined

An optional meta string. In markdown or MDX documents, this is the part of the code block’s opening fence that comes after the language name.

Type: string | undefined Default: undefined

The code block’s locale (e.g. en-US or de-DE). This is used by plugins to display localized strings depending on the language of the containing page.

If no locale is defined here, most Expressive Code integrations will attempt to auto-detect the block locale using the configured getBlockLocale function, and finally fall back to the configured defaultLocale.

Type: string | undefined Default: undefined

The code block’s title.

Depending on the frame type (code or terminal), this title is displayed by the frames plugin either as an open file tab label or as a terminal window title.

Type: 'auto' | 'code' | 'terminal' | 'none' | undefined Default: 'auto'

The code block’s frame type.

Type: MarkerDefinition | MarkerDefinition[] Default: undefined

Defines the code block’s text & line markers.

You can either pass a single marker definition or an array of them.

Type: string | undefined Default: undefined

The CSS class name(s) to apply to the code block’s container element.

Type: boolean Default: false

If true, word wrapping will be enabled for the code block, causing lines that exceed the available width to wrap to the next line. You can use the preserveIndent option to control how wrapped lines are indented.

If false, lines that exceed the available width will cause a horizontal scrollbar to appear.

Type: boolean Default: true

If true, wrapped parts of long lines will be aligned with their line’s indentation level, making the wrapped code appear to start at the same column. This increases readability of the wrapped code and can be especially useful for languages where indentation is significant, e.g. Python.

If false, wrapped parts of long lines will always start at column 1. This can be useful to reproduce terminal output.

Type: number Default: 0

Defines the number of columns by which all wrapped lines are indented.

This option only has an effect if wrap is true.

If preserveIndent is true, this value is added to the indentation of the original line. If preserveIndent is false, this value is used as the indentation for all wrapped lines.