---
title: Plugin Hooks
---

## Available plugin hooks

The engine calls the following hook functions in the order listed here:

### preprocessLanguage

<PropertySignature>
- Type: [`ExpressiveCodeHook`](/api/expressive-code/core/type-aliases/ExpressiveCodeHook/)\<[`ExpressiveCodeHookContext`](/api/expressive-code/core/interfaces/ExpressiveCodeHookContext/)\>
</PropertySignature>

Allows preprocessing the code block's [language](/api/expressive-code/core/classes/ExpressiveCodeBlock/#language) identifier before loading language-specific defaults into
[props](/api/expressive-code/core/classes/ExpressiveCodeBlock/#props).

The Text Markers plugin uses this hook to override the `diff` language identifier with the language specified in the `lang` meta option (if given) to allow using diff syntax to mark inserted and deleted lines while using another language for syntax highlighting.

### preprocessMetadata

<PropertySignature>
- Type: [`ExpressiveCodeHook`](/api/expressive-code/core/type-aliases/ExpressiveCodeHook/)\<[`ExpressiveCodeHookContext`](/api/expressive-code/core/interfaces/ExpressiveCodeHookContext/)\>
</PropertySignature>

Allows preprocessing the meta string and the language before any plugins can modify the code.

Plugins are expected to use this hook to remove any of their syntax from the meta string. Removed information can either be stored internally or used to create annotations.

As the code still matches the plaintext in the containing Markdown/MDX document at this point, this hook can be used to apply annotations by line numbers.

### preprocessCode

<PropertySignature>
- Type: [`ExpressiveCodeHook`](/api/expressive-code/core/type-aliases/ExpressiveCodeHook/)\<[`ExpressiveCodeHookContext`](/api/expressive-code/core/interfaces/ExpressiveCodeHookContext/)\>
</PropertySignature>

Allows preprocessing the code before any language-specific hooks are run.

Plugins are expected to use this hook to remove any of their syntax that could disturb annotation plugins like syntax highlighters. Removed information can either be stored internally or used to create annotations.

Plugins can also use this hook to insert new code, e.g. to add type information for syntax highlighters, or to provide functionality to include external files into the code block.

### performSyntaxAnalysis

<PropertySignature>
- Type: [`ExpressiveCodeHook`](/api/expressive-code/core/type-aliases/ExpressiveCodeHook/)\<[`ExpressiveCodeHookContext`](/api/expressive-code/core/interfaces/ExpressiveCodeHookContext/)\>
</PropertySignature>

Allows analyzing the preprocessed code and collecting language-specific syntax annotations.

This hook is used by the syntax highlighting plugin to run the code through `Shiki` and to create annotations from the returned syntax tokens.

These annotations are then available to the following hooks and will be used during rendering.

### postprocessAnalyzedCode

<PropertySignature>
- Type: [`ExpressiveCodeHook`](/api/expressive-code/core/type-aliases/ExpressiveCodeHook/)\<[`ExpressiveCodeHookContext`](/api/expressive-code/core/interfaces/ExpressiveCodeHookContext/)\>
</PropertySignature>

Allows postprocessing the code plaintext after collecting syntax annotations.

Plugins are expected to use this hook to remove any parts from the code that should not be contained in the output. For example, if a plugin added declarations or type information during the `preprocessCode` hook to provide information to the syntax highlighter, the declarations could now be removed again.

After this hook has finished processing, the plaintext of all code lines becomes read-only.

### annotateCode

<PropertySignature>
- Type: [`ExpressiveCodeHook`](/api/expressive-code/core/type-aliases/ExpressiveCodeHook/)\<[`ExpressiveCodeHookContext`](/api/expressive-code/core/interfaces/ExpressiveCodeHookContext/)\>
</PropertySignature>

Allows annotating the final code plaintext.

As the code is read-only at this point, plugins can use this hook to create annotations on lines or inline ranges matching a specific search term.

### postprocessAnnotations

<PropertySignature>
- Type: [`ExpressiveCodeHook`](/api/expressive-code/core/type-aliases/ExpressiveCodeHook/)\<[`ExpressiveCodeHookContext`](/api/expressive-code/core/interfaces/ExpressiveCodeHookContext/)\>
</PropertySignature>

Allows applying final changes to annotations before rendering.

After this hook has finished processing, all annotations become read-only and the engine starts rendering the code blocks line by line.

### postprocessRenderedLine

<PropertySignature>
- Type: [`ExpressiveCodeHook`](/api/expressive-code/core/type-aliases/ExpressiveCodeHook/)\<[`PostprocessRenderedLineContext`](/api/expressive-code/core/interfaces/PostprocessRenderedLineContext/)\>
</PropertySignature>

Allows editing the AST of a single line of code after all annotations were rendered.

### postprocessRenderedBlock

<PropertySignature>
- Type: [`ExpressiveCodeHook`](/api/expressive-code/core/type-aliases/ExpressiveCodeHook/)\<[`PostprocessRenderedBlockContext`](/api/expressive-code/core/interfaces/PostprocessRenderedBlockContext/)\>
</PropertySignature>

Allows editing the AST of the entire code block after all annotations were rendered and all lines were postprocessed.

### postprocessRenderedBlockGroup

<PropertySignature>
- Type: [`ExpressiveCodeHook`](/api/expressive-code/core/type-aliases/ExpressiveCodeHook/)\<[`PostprocessRenderedBlockGroupContext`](/api/expressive-code/core/interfaces/PostprocessRenderedBlockGroupContext/)\>
</PropertySignature>

Allows editing the ASTs of all code blocks that were rendered as part of the same group, as well as the AST of the group root element that contains all group blocks.

Groups are defined by the calling code. For example, a rehype plugin using Expressive Code to render code blocks could provide authors with a way to group related code blocks together.

This hook is used by the frames plugin to display multiple code blocks as editor file tabs.

Note: Even if a code block is not part of any group, this hook will still be called. Standalone code blocks are treated like a group containing only a single block.

## Referenced types

````yml include
name: "ExpressiveCodeHook"
headingLevel: 3
````

````yml include
name: "ExpressiveCodeHookContext"
headingLevel: 3
replacements:
- search: '\[`GroupContents`\]\(.*?\)'
  replace: 'readonly \{ `codeBlock`: `ExpressiveCodeBlock` \}[]'
````

````yml include
name: "PostprocessRenderedLineContext"
headingLevel: 3
removeSections:
- "Properties/(addStyles|codeBlock|config|cssVar|cssVarName|groupContents|locale|styleVariants)"
editSections:
- path: "Properties"
  replaceHeading: "Additional properties"
````

````yml include
name: "PostprocessRenderedBlockContext"
headingLevel: 3
removeSections:
- "Properties/(addStyles|codeBlock|config|cssVar|cssVarName|groupContents|locale|styleVariants)"
editSections:
- path: "Properties"
  replaceHeading: "Additional properties"
````

````yml include
name: "PostprocessRenderedBlockGroupContext"
headingLevel: 3
replacements:
- search: '\[`PluginStyles`\]\(.*?\)'
  replace: '\{ `pluginName`: `string`; `styles`: `string` \}'
- search: '\[`RenderedGroupContents`\]\(.*?\)'
  replace: 'readonly \{ `codeBlock`: `ExpressiveCodeBlock`; `renderedBlockAst`: `Element` \}[]'
````
