Shiki (Highlight)
The comark/plugins/shiki plugin provides syntax highlighting for code blocks using Shiki. It supports multiple themes, line highlighting, and dual light/dark palettes.
comark/plugins/highlight is a deprecated alias of comark/plugins/shiki and will be removed in the next major version. Prefer import shiki from 'comark/plugins/shiki'.For a lighter alternative (no TextMate grammars), see comark/plugins/rangi.
Installation
shiki is a peer dependency — install it alongside Comark:
npm install shikiFor explicit theme/language imports (recommended for tree-shaking and the core entry), also install the standalone packages:
npm install @shikijs/themes @shikijs/langs| Package | When you need it |
|---|---|
shiki | Always — peer dependency of the plugin |
@shikijs/themes | Importing themes like @shikijs/themes/github-dark |
@shikijs/langs | Importing languages like @shikijs/langs/typescript |
shiki() with no options after installing only shiki. Install @shikijs/themes / @shikijs/langs when you pass custom themes / languages, or when you use comark/plugins/shiki/core.Usage
Standard entry
Zero-config — defaults cover Material light/dark and common languages (vue, tsx, svelte, astro, typescript, javascript, bash, json, yaml, plus Comark/mdc):
import { parseMarkdown } from 'comark'
import shiki from 'comark/plugins/shiki'
const result = await parseMarkdown(content, {
plugins: [shiki()]
})Override themes (import from @shikijs/themes):
import { parseMarkdown } from 'comark'
import shiki from 'comark/plugins/shiki'
import githubLight from '@shikijs/themes/github-light'
import githubDark from '@shikijs/themes/github-dark'
const result = await parseMarkdown(content, {
plugins: [
shiki({
themes: {
light: githubLight,
dark: githubDark
}
})
]
})Core entry (minimal bundle)
To keep default theme/language chunks out of the bundle entirely, use core. themes and languages are required (ShikiCoreOptions) — there are no registerDefault* flags:
import shiki from 'comark/plugins/shiki/core'
import javascript from '@shikijs/langs/javascript'
import typescript from '@shikijs/langs/typescript'
import githubLight from '@shikijs/themes/github-light'
import githubDark from '@shikijs/themes/github-dark'
const plugins = [
shiki({
languages: [javascript, typescript],
themes: { light: githubLight, dark: githubDark },
})
]Framework packages expose the same nested entry, for example @comark/vue/plugins/shiki/core and @comark/react/plugins/shiki/core.
The Comark TextMate grammar can also be imported independently from the plugin-owned language entry:
import comarkLanguages, { comarkLanguage } from 'comark/plugins/shiki/language-comark'The default export includes the Comark grammar and its Markdown, YAML, and HTML dependencies, ready to pass to Shiki. This entry does not import rangi.
With framework components:
<script setup lang="ts">
import { Markdown } from '@comark/vue'
import shiki from '@comark/vue/plugins/shiki'
import githubLight from '@shikijs/themes/github-light'
import githubDark from '@shikijs/themes/github-dark'
const plugins = [
shiki({
themes: { light: githubLight, dark: githubDark }
})
]
</script>
<template>
<Suspense>
<Markdown :plugins="plugins">{{ content }}</Markdown>
</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 { Markdown } from '@comark/react'
import shiki from '@comark/react/plugins/shiki'
import githubLight from '@shikijs/themes/github-light'
import githubDark from '@shikijs/themes/github-dark'
<Markdown
plugins={[shiki({ themes: { light: githubLight, dark: githubDark } })]}
>
{content}
</Markdown>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 →
shiki({
themes: {
light: githubLight,
dark: githubDark
}
})Language Detection
Comark reads the language from the code fence info string and highlights accordingly. On the standard entry, the default language set is pre-registered; pass extra grammars via languages (from @shikijs/langs). On core, only the languages you pass are available. 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
Install @shikijs/langs and import grammars to register extra languages (or all languages on core):
npm install @shikijs/langsimport javascript from '@shikijs/langs/javascript'
import typescript from '@shikijs/langs/typescript'
import python from '@shikijs/langs/python'
shiki({
languages: [javascript, typescript, python]
})languages merges on top. Use registerDefaultLanguages: false to replace the set entirely.
Core: no defaults — languages is required and is the full set (plus the built-in Comark/mdc grammar).Transformers
Pass any Shiki transformer via transformers to add diff annotations, focus lines, or custom classes:
import { transformerNotationDiff } from '@shikijs/transformers'
shiki({
themes: { light: githubLight, dark: githubDark },
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
shiki(options?) — standard entry
import shiki from 'comark/plugins/shiki'
// shiki(options?: ShikiOptions): ComarkPluginReturns a ComarkPlugin with bundled Material themes and the default language set. Options are optional.
shiki(options) — core entry
import shiki from 'comark/plugins/shiki/core'
// shiki(options: ShikiCoreOptions): ComarkPluginReturns a ComarkPlugin with no bundled themes or languages. themes and languages are required. Import them from @shikijs/themes and @shikijs/langs.
Options
Two option types, one per entry:
ShikiOptions—comark/plugins/shiki(standard). Themes/languages optional; includesregisterDefaultThemes/registerDefaultLanguages.ShikiCoreOptions—comark/plugins/shiki/core.themesandlanguagesare required; noregisterDefault*options (nothing is bundled by default).
Standard (ShikiOptions)
| Option | Type | Default | Description |
|---|---|---|---|
themes | object | Material themes | Light and dark theme registrations |
languages | LanguageRegistration[] | undefined | Extra languages (merged onto the default set) |
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 |
Core (ShikiCoreOptions)
| Option | Type | Default | Description |
|---|---|---|---|
themes | object | required | Light and/or dark theme registrations |
languages | LanguageRegistration[] | required | Languages to register |
transformers | ShikiTransformer[] | undefined | Shiki transformers applied to every block |
preStyles | boolean | false | Add inline background/foreground styles to <pre> |
themes
Theme configuration for light and dark modes. Install @shikijs/themes and import from there:
npm install @shikijs/themesimport githubLight from '@shikijs/themes/github-light'
import githubDark from '@shikijs/themes/github-dark'
shiki({
themes: {
light: githubLight,
dark: githubDark
}
})Standard default: { light: materialThemeLighter, dark: materialThemePalenight } (when registerDefaultThemes is true). Core: required (at least one of light / dark).
languages
Languages to register. Install @shikijs/langs and import from there. On the standard entry, values are merged on top of the default set when registerDefaultLanguages is true.
npm install @shikijs/langsimport javascript from '@shikijs/langs/javascript'
import typescript from '@shikijs/langs/typescript'
shiki({
languages: [javascript, typescript]
})Standard default: undefined (default set still registered via registerDefaultLanguages). Core: required.
transformers
An array of Shiki transformers applied to every highlighted block.
import { transformerNotationDiff, transformerNotationHighlight } from '@shikijs/transformers'
shiki({
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.
shiki({ preStyles: true })Default: false
registerDefaultLanguages
Standard entry only. When true, these languages are pre-registered: vue, tsx, svelte, astro, typescript, javascript, bash, json, yaml (plus the built-in Comark/mdc grammar). Set to false to control the language set entirely via languages.
shiki({
registerDefaultLanguages: false,
languages: [javascript, typescript]
})Default: true
registerDefaultThemes
Standard entry only. When true, registers material-theme-lighter (light) and material-theme-palenight (dark). Set it to false to skip loading those themes at runtime. To keep their import chunks out of a consumer bundle entirely, use comark/plugins/shiki/core instead.
shiki({
registerDefaultThemes: false,
themes: { light: githubLight, dark: githubDark }
})Default: true
Examples
GitHub Theme
import { parseMarkdown } from 'comark'
import shiki from 'comark/plugins/shiki'
import githubLight from '@shikijs/themes/github-light'
import githubDark from '@shikijs/themes/github-dark'
const result = await parseMarkdown(content, {
plugins: [shiki({ themes: { light: githubLight, dark: githubDark } })]
})Minimal Bundle
Install the standalone Shiki packages, use the core entry (ShikiCoreOptions), and import only what you need — languages and themes are required, and no defaults are bundled:
npm install shiki @shikijs/langs @shikijs/themesimport shiki from 'comark/plugins/shiki/core'
import javascript from '@shikijs/langs/javascript'
import typescript from '@shikijs/langs/typescript'
import githubDark from '@shikijs/themes/github-dark'
shiki({
languages: [javascript, typescript],
themes: { dark: githubDark }
})With Transformers
import {
transformerNotationDiff,
transformerNotationHighlight,
transformerNotationFocus,
} from '@shikijs/transformers'
shiki({
themes: { light: githubLight, dark: githubDark },
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.
ProsePre? After highlighting there is no code prop — reconstruct the source with __node and textContent().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>