---
title: "Expressive Code plugins"
description: "The Expressive Code plugins that the package exports, for sites that configure Expressive Code themselves."
url: "https://ewels.github.io/starlight-codeblocks/reference/expressive-code-plugins/"
markdown: "https://ewels.github.io/starlight-codeblocks/reference/expressive-code-plugins.md"
section: "Reference"
site: "starlight-codeblocks documentation"
context: "This page is from the documentation of starlight-codeblocks. A Starlight plugin that adds focus, line states, annotations, API auto-linking and 22 more features to the code blocks of a site."
index: "https://ewels.github.io/starlight-codeblocks/llms.txt"
---

# Expressive Code plugins

> The Expressive Code plugins that the package exports, for sites that configure Expressive Code themselves.

`codeblocks()` adds every feature to Starlight for you. Behind it, each feature is an Expressive Code plugin. The `starlight-codeblocks/expressive-code` subpath exports these plugins, and a preset that returns all of them. A site that uses Expressive Code without Starlight, or with its own `plugins` list in `ec.config.mjs`, uses them there.

## The preset

`pluginCodeblocks(options)` returns every plugin, in the correct order, with the options of [`codeblocks()`](https://ewels.github.io/starlight-codeblocks/reference/options/). Use the preset unless you have a reason to add plugins one by one. To leave a feature out, set its option to `false`:

```js title="ec.config.mjs"
import { pluginCodeblocks } from 'starlight-codeblocks/expressive-code';

export default {
  plugins: [pluginCodeblocks({ annotations: false, runnable: false })],
};
```

On a Starlight site with `codeblocks()`, call `pluginCodeblocks()` with no argument. It then reads the options that you gave to `codeblocks()`.

On a site without `codeblocks()`, give the preset Astro's `base` as the second argument, if the site has one. Links in code that start with `/` then get it in front:

```js title="ec.config.mjs"
plugins: [pluginCodeblocks({}, { base: '/docs' })],
```

## Plugins

Each plugin takes the settings of its option, as the [options reference](https://ewels.github.io/starlight-codeblocks/reference/options/) lists them. The table gives the plugins in the order that the preset adds them.

| Plugin | Option | Feature |
|---|---|---|
| `pluginCore()` | none | Shared style settings and styles |
| `pluginNotation(settings)` | `notation` | [Comment notation](https://ewels.github.io/starlight-codeblocks/comment-notation/) |
| `pluginFocus(settings)` | `focus` | [Focus](https://ewels.github.io/starlight-codeblocks/features/focus/) |
| `pluginLineStates(settings)` | `lineStates` | [Line states](https://ewels.github.io/starlight-codeblocks/features/line-states/) |
| `pluginWordDiff(settings)` | `wordDiff` | [Word-level diff](https://ewels.github.io/starlight-codeblocks/features/word-level-diff/) |
| `pluginWhitespace()` | `whitespace` | [Visible whitespace](https://ewels.github.io/starlight-codeblocks/features/visible-whitespace/) |
| `pluginBrackets(settings)` | `brackets` | [Colourised brackets](https://ewels.github.io/starlight-codeblocks/features/colourised-brackets/) |
| `pluginSwatches(settings)` | `swatches` | [Colour swatches](https://ewels.github.io/starlight-codeblocks/features/colour-swatches/) |
| `pluginShellCopy(settings)` | `shellCopy` | [Smart shell copy](https://ewels.github.io/starlight-codeblocks/features/smart-shell-copy/) |
| `pluginCodeLinks({ base })` | `codeLinks` | [Code links](https://ewels.github.io/starlight-codeblocks/features/code-links/) |
| `pluginApiLinks({ adapters, base })` | `apiLinks` | [API auto-linking](https://ewels.github.io/starlight-codeblocks/features/api-auto-linking/) |
| `pluginPlaceholders(settings)` | `placeholders` | [Fill-in placeholders](https://ewels.github.io/starlight-codeblocks/features/fill-in-placeholders/) |
| `pluginMentions()` | `mentions` | [Code mentions](https://ewels.github.io/starlight-codeblocks/features/code-mentions/) |
| `pluginPermalinks()` | `permalinks` | [Line permalinks](https://ewels.github.io/starlight-codeblocks/features/line-permalinks/) |
| `pluginHiddenLines()` | `hiddenLines` | [Hidden lines](https://ewels.github.io/starlight-codeblocks/features/hidden-lines/) |
| `pluginExpandable(settings)` | `expandable` | [Expandable blocks](https://ewels.github.io/starlight-codeblocks/features/expandable-blocks/) |
| `pluginPlayground(playgrounds)` | `playgrounds` | [Open in playground](https://ewels.github.io/starlight-codeblocks/features/open-in-playground/) |
| `pluginRunnable(settings)` | `runnable` | [Run code](https://ewels.github.io/starlight-codeblocks/features/run-code/) |
| `pluginFileIcons(settings)` | `fileIcons` | [File icons](https://ewels.github.io/starlight-codeblocks/features/file-icons/) |
| `pluginCodeTabs(fileIcons)` | `codeTabs` | [Code tabs](https://ewels.github.io/starlight-codeblocks/features/code-tabs/) |
| `pluginWalkthrough()` | `walkthrough` | [Code walkthrough](https://ewels.github.io/starlight-codeblocks/features/code-walkthrough/) |
| `pluginCallouts()` | `callouts` | [Inline callouts](https://ewels.github.io/starlight-codeblocks/features/inline-callouts/) |
| `pluginAnnotations()` | `annotations` | [Annotations](https://ewels.github.io/starlight-codeblocks/features/annotations/) and [side annotations](https://ewels.github.io/starlight-codeblocks/features/side-annotations/) |
| `pluginFootnotes(settings)` | `footnotes` | [Footnotes](https://ewels.github.io/starlight-codeblocks/features/footnotes/) |

`pluginCodeLinks()` and `pluginApiLinks()` take the `base` of the Astro site, for links that start with `/`. With `codeblocks()`, they read it from Astro. `pluginApiLinks()` has no default adapters. Give it the adapters from `starlight-codeblocks/adapters/python` and `starlight-codeblocks/adapters/nextflow`, or your own.

## Rules for single plugins

If you add plugins one by one, follow these rules:

1. Add `pluginCore()` first. Every other plugin uses its style settings.
2. Add `pluginNotation()` second, if any plugin after it reads directives.
3. Add the other plugins in the order of the table.

The order matters. For example, `pluginPlayground()` sends the copied text, so it must come after `pluginShellCopy()` and `pluginPlaceholders()`, which change that text. `pluginCallouts()` must come after `pluginHiddenLines()`, which rebuilds the lines of the block.

## Without Starlight

Some features need more than an Expressive Code plugin. Without `codeblocks()`, these parts are not there:

- The `:::code-tabs` directive and [inline code highlighting](https://ewels.github.io/starlight-codeblocks/features/inline-code-highlighting/) need the Markdown plugin that `codeblocks()` adds.
- The `<CodeWalkthrough>` and `<Scrollycoding>` components need Starlight.
- `runnable.runtimes` values are URLs that the browser imports as they are, because `codeblocks()` is not there to bundle the runtime modules. There are no built-in runtimes. Map each language to the URL of its runtime module, such as `https://cdn.jsdelivr.net/npm/starlight-codeblocks/dist/runtimes/pyodide.mjs`. The JavaScript and TypeScript runtimes are `javascript.mjs` and `typescript.mjs` in the same folder.
- Expressive Code turns each tab into spaces, because `codeblocks()` is not there to set `tabWidth: 0`. Set `tabWidth: 0` in `ec.config.mjs`, so that tabs reach the code blocks unchanged.

The client scripts of interactive features load inline on each page that needs them, so the features work without a change to the build.
