The comark/plugins/highlight plugin provides syntax highlighting for code blocks using Shiki. It supports multiple themes, line highlighting, and on-demand language loading.
shiki is a peer dependency, install it alongside Comark:
npm install shikiUsage
Pass bundled theme names as strings — no extra imports needed:
import { parse } from 'comark'
import highlight from 'comark/plugins/highlight'
const result = await parse(content, {
plugins: [
highlight({
themes: {
light: 'github-light',
dark: 'github-dark'
}
})
]
})With framework components:
<script setup lang="ts">
import { Comark } from '@comark/vue'
import highlight from '@comark/vue/plugins/highlight'
const plugins = [
highlight({
themes: { light: 'github-light', dark: 'github-dark' }
})
]
</script>
<template>
<Suspense>
<Comark :plugins="plugins">{{ content }}</Comark>
</Suspense>
</template>
<style scoped>
html.dark .shiki :deep(span) {
color: var(--shiki-dark) !important;
background-color: var(--shiki-dark-bg) !important;
font-style: var(--shiki-dark-font-style) !important;
font-weight: var(--shiki-dark-font-weight) !important;
text-decoration: var(--shiki-dark-text-decoration) !important;
}
</style>import { Comark } from '@comark/react'
import highlight from '@comark/react/plugins/highlight'
<Comark
plugins={[highlight({ themes: { light: 'github-light', dark: 'github-dark' } })]}
>
{content}
</Comark>Features
Dual-Theme Support
Highlight code with different themes for light and dark modes. Both palettes are embedded as CSS custom properties, so there is no flash on theme switch. See all available themes →
highlight({
themes: {
light: 'github-light',
dark: 'github-dark'
}
})You can also pass theme registration objects (for example from @shikijs/themes) when you want explicit control over what gets bundled:
import githubLight from '@shikijs/themes/github-light'
import githubDark from '@shikijs/themes/github-dark'
highlight({
themes: {
light: githubLight,
dark: githubDark
}
})Language Detection
Comark reads the language from the code fence info string and highlights accordingly. Languages are loaded on demand by default. See all 180+ supported languages →
```typescript
const x: number = 42
```Line Highlighting
Highlight specific lines using {line-numbers} syntax:
```javascript {2-3,5}
function example() {
const a = 1 // highlighted
const b = 2 // highlighted
const c = 3
return a + b + c // highlighted
}
```Lines receive the .highlight class; see Styling for the required CSS.
Filename Metadata
Display a filename label above the code block:
```javascript [server.js]
const app = express()
```Language Loading
Import languages from @shikijs/langs to preload them and gain type safety:
import javascript from '@shikijs/langs/javascript'
import typescript from '@shikijs/langs/typescript'
import python from '@shikijs/langs/python'
highlight({
languages: [javascript, typescript, python]
})languages, unregistered languages are loaded on demand. Use registerDefaultLanguages: false with an explicit languages array for the smallest bundle.Transformers
Pass any Shiki transformer via transformers to add diff annotations, focus lines, or custom classes:
import { transformerNotationDiff } from '@shikijs/transformers'
highlight({
themes: { light: 'github-light', dark: 'github-dark' },
transformers: [transformerNotationDiff()]
})The most powerful transformer is @shikijs/twoslash: it runs the TypeScript compiler on your code blocks to add inline type tooltips and error annotations.
Pre Styles
Set preStyles: true to add inline background and foreground colors to <pre> elements based on the active theme.
API
highlight(options?)
Returns a ComarkPlugin that enables Shiki syntax highlighting.
Parameters:
options?- Optional configuration, see Options
Returns: ComarkPlugin
Options
| Option | Type | Default | Description |
|---|---|---|---|
themes | object | Material themes | Light and dark theme names or registrations |
languages | LanguageRegistration[] | undefined | Languages to preload |
transformers | ShikiTransformer[] | undefined | Shiki transformers applied to every block |
preStyles | boolean | false | Add inline background/foreground styles to <pre> |
registerDefaultLanguages | boolean | true | Register the built-in default language set |
registerDefaultThemes | boolean | true | Register the built-in Material themes |
themes
Theme configuration for light and dark modes. Each value can be a bundled theme name string (resolved from shiki) or a theme registration object.
highlight({
themes: {
light: 'github-light',
dark: 'github-dark'
}
})Default: { light: 'material-theme-lighter', dark: 'material-theme-palenight' }
languages
Languages to preload. Import from @shikijs/langs. Without this option, languages are loaded on demand.
import javascript from '@shikijs/langs/javascript'
import typescript from '@shikijs/langs/typescript'
highlight({
languages: [javascript, typescript]
})Default: undefined
transformers
An array of Shiki transformers applied to every highlighted block.
import { transformerNotationDiff, transformerNotationHighlight } from '@shikijs/transformers'
highlight({
transformers: [
transformerNotationDiff(), // [!code ++] / [!code --]
transformerNotationHighlight(), // [!code highlight]
]
})Default: undefined
preStyles
Add inline background and foreground color styles to <pre> elements based on the active theme.
highlight({ preStyles: true })Default: false
registerDefaultLanguages
When true, these languages are pre-registered: vue, tsx, svelte, astro, typescript, javascript, mdc, bash, json, yaml. Set to false to control the language set entirely via languages.
highlight({
registerDefaultLanguages: false,
languages: [javascript, typescript]
})Default: true
registerDefaultThemes
When true, material-theme-lighter (light) and material-theme-palenight (dark) are pre-registered. Set to false when using only custom themes.
highlight({
registerDefaultThemes: false,
themes: { light: 'github-light', dark: 'github-dark' }
})Default: true
Examples
GitHub Theme
import { parse } from 'comark'
import highlight from 'comark/plugins/highlight'
const result = await parse(content, {
plugins: [highlight({ themes: { light: 'github-light', dark: 'github-dark' } })]
})Minimal Bundle
Disable defaults and import only what you need. Prefer theme registration objects here so unused bundled themes are tree-shaken:
import javascript from '@shikijs/langs/javascript'
import typescript from '@shikijs/langs/typescript'
import githubDark from '@shikijs/themes/github-dark'
highlight({
registerDefaultLanguages: false,
registerDefaultThemes: false,
languages: [javascript, typescript],
themes: { dark: githubDark }
})With Transformers
import {
transformerNotationDiff,
transformerNotationHighlight,
transformerNotationFocus,
} from '@shikijs/transformers'
highlight({
themes: { light: 'github-light', dark: 'github-dark' },
transformers: [
transformerNotationDiff(), // [!code ++] / [!code --]
transformerNotationHighlight(), // [!code highlight]
transformerNotationFocus(), // [!code focus]
]
})See the Twoslash guide for TypeScript-powered type tooltips and error annotations in code blocks.
Live Examples
Vue + Vite Highlight
Vue + Vite Twoslash
Styling
Shiki outputs tokens as <span class="line"> elements inside a <pre class="shiki"> block.
Line Highlight
Lines set with {1,3-5} syntax receive the .highlight class:
.shiki span.line.highlight {
background-color: rgba(255, 255, 0, 0.1);
display: inline-block;
width: calc(100% + 2rem);
margin: 0 -1rem;
padding: 0 1rem;
}Dark Mode
When both light and dark themes are provided, Shiki embeds both palettes as CSS custom properties on every <span>. Activate the dark palette based on your project's dark-mode class:
html.dark .shiki span {
color: var(--shiki-dark) !important;
background-color: var(--shiki-dark-bg) !important;
font-style: var(--shiki-dark-font-style) !important;
font-weight: var(--shiki-dark-font-weight) !important;
text-decoration: var(--shiki-dark-text-decoration) !important;
}In Vue scoped styles, use :deep() to reach Shiki spans:
<style scoped>
html.dark .shiki :deep(span) {
color: var(--shiki-dark) !important;
background-color: var(--shiki-dark-bg) !important;
font-style: var(--shiki-dark-font-style) !important;
font-weight: var(--shiki-dark-font-weight) !important;
text-decoration: var(--shiki-dark-text-decoration) !important;
}
</style>