Built-in

Syntax Highlighting

Plugin for syntax highlighting code blocks using Shiki with multi-theme support.

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 shiki

Usage

Import themes from @shikijs/themes for type safety and tree-shaking:

import { parse } from 'comark'
import highlight from 'comark/plugins/highlight'
import githubLight from '@shikijs/themes/github-light'
import githubDark from '@shikijs/themes/github-dark'

const result = await parse(content, {
  plugins: [
    highlight({
      themes: {
        light: githubLight,
        dark: githubDark
      }
    })
  ]
})

With framework components:

<script setup lang="ts">
import { Comark } from '@comark/vue'
import highlight from '@comark/vue/plugins/highlight'
import githubLight from '@shikijs/themes/github-light'
import githubDark from '@shikijs/themes/github-dark'

const plugins = [
  highlight({
    themes: { light: githubLight, dark: githubDark }
  })
]
</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>

Features

Dual-Theme Support

Highlight code with different themes for light and dark modes. Both palettes are embedded as CSS custom properties — no flash on theme switch. See all available themes →

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]
})
Without explicit 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: 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

highlight(options?)

Returns a ComarkPlugin that enables Shiki syntax highlighting.

Parameters:

  • options? - Optional configuration — see Options

Returns: ComarkPlugin


Options

OptionTypeDefaultDescription
themesobjectMaterial themesLight and dark theme registrations
languagesLanguageRegistration[]undefinedLanguages to preload
transformersShikiTransformer[]undefinedShiki transformers applied to every block
preStylesbooleanfalseAdd inline background/foreground styles to <pre>
registerDefaultLanguagesbooleantrueRegister the built-in default language set
registerDefaultThemesbooleantrueRegister the built-in Material themes

themes

Theme configuration for light and dark modes. Import from @shikijs/themes.

import githubLight from '@shikijs/themes/github-light'
import githubDark from '@shikijs/themes/github-dark'

highlight({
  themes: {
    light: githubLight,
    dark: githubDark
  }
})

Default: { light: materialThemeLighter, dark: materialThemePalenight }

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: githubLight, dark: githubDark }
})

Default: true


Examples

GitHub Theme

import { parse } from 'comark'
import highlight from 'comark/plugins/highlight'
import githubLight from '@shikijs/themes/github-light'
import githubDark from '@shikijs/themes/github-dark'

const result = await parse(content, {
  plugins: [highlight({ themes: { light: githubLight, dark: githubDark } })]
})

Minimal Bundle

Disable defaults and import only what you need:

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: 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.

Live Examples

Vue + Vite Highlight

Dual-theme support, 10+ languages, theme toggle. Includes JavaScript, TypeScript, Python, Rust, Go, SQL and more.

Vue + Vite Twoslash

Browser-side twoslash with CDN-fetched TypeScript types and interactive type popups.

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>