Plugin Hooks
Available plugin hooks
The engine calls the following hook functions in the order listed here:
preprocessLanguage
Allows preprocessing the code block’s language identifier before loading language-specific defaults into 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
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
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
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
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
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
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
Allows editing the AST of a single line of code after all annotations were rendered.
postprocessRenderedBlock
Allows editing the AST of the entire code block after all annotations were rendered and all lines were postprocessed.
postprocessRenderedBlockGroup
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
ExpressiveCodeHook
context) => void | Promise<void> Type parameters
| Parameter | Value |
|---|---|
ContextType | ExpressiveCodeHookContext |
The base type of all hooks. It is a function that gets called by the engine and receives a context object. The context type defaults to ExpressiveCodeHookContext, but can vary by hook, so see the list of available hooks for the correct type.
Arguments
| Parameter | Type |
|---|---|
context | ContextType |
ExpressiveCodeHookContext
A context object that the engine passes to most hook functions.
It provides access to theme-dependent CSS variables, all resolved style variants based on the configured themes and settings, and the config-dependent wrapper class name.
Properties
addGutterElement
element) => void Registers a gutter element for the current code block.
The engine calls the renderLine function of the gutter elements registered by all plugins for every line of the code block. The returned elements are then added as children to the line’s gutter container.
Arguments
| Parameter | Type |
|---|---|
element | GutterElement |
addStyles
css) => void Adds CSS styles to the document that contains the rendered code.
All styles are scoped to Expressive Code by default, so they will not affect the rest of the page. SASS-like nesting is supported. If you want to add global styles, you can use the @at-root rule or target :root, html or body in your selectors.
The engine’s render function returns all added styles in a string array along with the rendered group and block ASTs. The calling code must take care of actually adding these styles to the page. For example, it could insert them into a <style> element before the rendered code block.
Note for integration authors: If you are rendering multiple code block groups on the same HTML page, you should deduplicate the returned styles at the page level. Expressive Code deduplicates styles added to the same group before returning them, but is not aware which styles are already present on the page.
Note for plugin authors: If you are adding the same styles to every block, consider using the baseStyles property of the plugin instead. This allows integrations to optionally extract these styles into a separate CSS file.
Arguments
| Parameter | Type |
|---|---|
css | string |
codeBlock
ExpressiveCodeBlock config
ResolvedExpressiveCodeEngineConfig The Expressive Code engine configuration, with all optional properties resolved to their default values.
cssVar
styleSetting, fallbackValue?) => string Returns a CSS variable reference for the given style setting. The CSS variable name is automatically generated based on the setting path.
You can optionally pass a fallback value that will be added to the CSS var() function call (e.g. var(--ec-xyz, fallbackValue)) in case the referenced variable is not defined or unsupported. However, this should rarely be the case as the engine automatically generates CSS variables for all style settings if the plugin’s styleSettings property is set.
Arguments
| Parameter | Type |
|---|---|
styleSetting | StyleSettingPath |
fallbackValue? | string |
Example
cssVar('frames.fontSize')// ↓↓↓'var(--ec-frames-fontSize)'
cssVar('frames.fontSize', '2rem')// ↓↓↓'var(--ec-frames-fontSize, 2rem)'cssVarName
styleSetting) => string Returns the CSS variable name for the given style setting. The CSS variable name is automatically generated based on the setting path.
Arguments
| Parameter | Type |
|---|---|
styleSetting | StyleSettingPath |
Example
cssVarName('frames.fontSize')// ↓↓↓'--ec-frames-fontSize'groupContents
codeBlock: ExpressiveCodeBlock }[] locale
string styleVariants
StyleVariant[] PostprocessRenderedLineContext
A context object that the engine passes to the postprocessRenderedLine hook function.
In addition to the properties made available by ExpressiveCodeHookContext, it provides access to information about the line currently being rendered, and allows modifying the rendered output.
Additional properties
line
ExpressiveCodeLine A reference to the line that is currently being rendered. It is read-only at this point, but you can access all line properties, including its source code and annotations.
lineIndex
number The 0-based index of the line inside the code block.
renderData
Object Allows modifying the line’s rendered output. The lineAst property of this object contains the Hypertext Abstract Syntax Tree (HAST) node representing the rendered line.
You have full control over the lineAst property to modify the rendered output. For example, you could add a class name to the line’s root element, or you could wrap the entire line in a custom element.
There is a wide range of existing utility packages that you can use to manipulate HAST elements. For more information, see the list of utilities in the HAST documentation.
Object properties
- lineAst
- Type:
Element
renderEmptyLine
RenderEmptyLineFn Allows rendering an empty line that is not part of the original code.
Some plugins may need to render lines that are not part of the original code, e.g. to display the expected output of a call right inside the code block. To align such lines with the original code, plugins can request an empty line from the engine using this function.
PostprocessRenderedBlockContext
A context object that the engine passes to the postprocessRenderedBlock hook function.
In addition to the properties made available by ExpressiveCodeHookContext, it provides access to render data of the code block currently being rendered, and allows modifying the rendered output.
Additional properties
renderData
Object Allows modifying the block’s rendered output. The blockAst property of this object contains the Hypertext Abstract Syntax Tree (HAST) node representing the rendered block.
You have full control over the blockAst property to modify the rendered output. For example, you could add a class name to the block’s root element, wrap the entire block in a custom element, or traverse its children to find specific elements and modify them.
There is a wide range of existing utility packages that you can use to manipulate HAST elements. For more information, see the list of utilities in the HAST documentation.
Object properties
- blockAst
- Type:
Element
renderEmptyLine
RenderEmptyLineFn Allows rendering an empty line that is not part of the original code.
Some plugins may need to render lines that are not part of the original code, e.g. to display the expected output of a call right inside the code block. To align such lines with the original code, plugins can request an empty line from the engine using this function.
PostprocessRenderedBlockGroupContext
A context object that the engine passes to the postprocessRenderedBlockGroup hook function.
It provides access to information about the code block group currently being rendered, and allows modifying the rendered output.
Properties
addStyles
css) => void See ExpressiveCodeHookContext.addStyles.
Arguments
| Parameter | Type |
|---|---|
css | string |
pluginStyles
pluginName: string; styles: string }[] A list of styles that plugins added to the current code block group using the addStyles hook context function. Each item contains the plugin name and the styles it added. You have full control over the styles at this point and can add, modify or remove them as needed.
renderData
Object Allows modifying the rendered output of a group of code blocks. The groupAst property of this object contains the Hypertext Abstract Syntax Tree (HAST) parent node surrounding all rendered blocks.
This is the only property that allows you to modify the wrapper element of the entire group. You have full control over it to modify the rendered output. For example, you could add a class name to the group’s root element, or you could wrap the entire group in a custom element.
Object properties
- groupAst
- Type:
Element
renderedGroupContents
codeBlock: ExpressiveCodeBlock; renderedBlockAst: Element }[] An array of objects, each containing a reference to the code block, and its rendered HAST output. This is the same HAST element per block that is also available in the renderData property of the postprocessRenderedBlock hook context.