The comark/plugins/rangi plugin highlights code blocks with rangi — a tiny, zero-dependency, fully synchronous highlighter (~13kB with all languages, or ~1.5kB core). Prefer this when bundle size and cold-start matter more than TextMate grammar depth.
rangi is a peer dependency:
npm install rangicomark/plugins/shiki when you need transformers, Twoslash, or the full VS Code grammar set. Use rangi for a faster, smaller highlighter with built-in light/dark themes.Usage
import { parseMarkdown } from 'comark'
import rangi from 'comark/plugins/rangi'
const result = await parseMarkdown(content, {
plugins: [rangi()]
})With framework components:
<script setup lang="ts">
import { Markdown } from '@comark/vue'
import rangi from '@comark/vue/plugins/rangi'
import { github } from 'rangi/themes'
</script>
<template>
<Suspense>
<Markdown :plugins="[rangi({ theme: github })]">{{ content }}</Markdown>
</Suspense>
</template>import { Markdown } from '@comark/react'
import rangi from '@comark/react/plugins/rangi'
import { github } from 'rangi/themes'
<Markdown plugins={[rangi({ theme: github })]}>
{content}
</Markdown><script>
import { Markdown } from '@comark/svelte'
import rangi from '@comark/svelte/plugins/rangi'
import { github } from 'rangi/themes'
let { content } = $props()
</script>
<Markdown value={content} plugins={[rangi({ theme: github })]} />Features
Inline theme colors
Tokens get inline colors — no stylesheet required. Pass a single theme or a { light, dark } pair from rangi/themes (defaults to rangi's built-in light/dark pair):
import { githubDark, githubLight, github } from 'rangi/themes'
// single theme
rangi({ theme: githubDark })
// light/dark pair (ready-made)
rangi({ theme: github })
// or explicit pair — also emits --shiki-dark* vars for class-based dark toggles
rangi({ theme: { light: githubLight, dark: githubDark } })Comark language
Comark ships its own rangi grammar, registered automatically for the comark, mdc, md and markdown fence languages. It is built on rangi's official markdown grammar and adds the Comark syntax on top:
---
title: Frontmatter is highlighted as YAML
---
# Heading{#slug .lead}
::alert{type="warning" .rounded}
A :icon{name="lucide:check"} inline component, a [span]{.accent},
and a {{ user.name || Anonymous }} binding.
#footer
Named slot body
::Language aliases
Rangi ships aliases built-in (javascript→js, typescript→ts, python→py, yml→yaml, …). Comark passes the fence info string straight through. Unknown languages fall back to plain text (no throw).
Line highlighting
Fence info {2-3,5} marks lines with the .highlight class — same as the Shiki plugin.
Pre Styles
Set preStyles: true to add inline background and foreground colors to <pre> elements based on the active theme.
API
rangi(options?)
Returns a ComarkPlugin that enables rangi syntax highlighting.
Options
| Option | Type | Default | Description |
|---|---|---|---|
theme | ShjTheme | { light, dark } | rangi default pair | Inline colors |
lineNumbers | boolean | false | Wrap each line in <span class="line"> |
classPrefix | string | 'shj' | Class prefix on the highlighted <pre> |
languages | Record<string, grammar> | — | Extra custom grammars, merged over the Comark ones |
preStyles | boolean | false | Add inline background/foreground styles to <pre> |
theme
import { github, atomDark, geist } from 'rangi/themes'
rangi({ theme: github })
rangi({ theme: atomDark })
rangi({ theme: geist }) // light/dark pairOr a plain object:
rangi({
theme: {
name: 'mine',
scheme: 'dark',
bg: '#0d1117',
fg: '#e6edf3',
tokens: {
kwd: '#ff7b72',
str: '#a5d6ff',
cmnt: '#8b949e',
num: '#79c0ff',
func: '#d2a8ff',
},
},
})lineNumbers
When true, each source line is wrapped in <span class="line"> so {1,3-5} highlights can target lines and CSS gutters can number them:
rangi({ lineNumbers: true })Default: false
classPrefix
rangi({ classPrefix: 'code' })
// → class="code shj-lang-js"languages
Pass custom grammars through to rangi (see rangi docs). They are merged over the built-in Comark grammar, so a key such as md overrides it:
rangi({ languages: { mine: myGrammar } })preStyles
Add inline background and foreground color styles to <pre> elements based on the active theme.
rangi({ preStyles: true })Default: false
Examples
Minimal
import { parseMarkdown } from 'comark'
import rangi from 'comark/plugins/rangi'
const result = await parseMarkdown(content, {
plugins: [rangi()]
})GitHub dual theme
import { github } from 'rangi/themes'
rangi({ theme: github })With HTML renderer
import { createHtmlRenderer } from '@comark/html'
import rangi from '@comark/html/plugins/rangi'
import { githubDark } from 'rangi/themes'
const renderHtml = createHtmlRenderer({
plugins: [rangi({ theme: githubDark })],
})Live Example
Styling
Colors are inlined on tokens. For dual themes with a class-based dark toggle:
html.dark .shj span {
color: var(--shiki-dark) !important;
}
html.dark pre.shj {
background-color: var(--shiki-dark-bg) !important;
color: var(--shiki-dark) !important;
}Line highlight
.shj span.line.highlight {
background-color: rgba(255, 255, 0, 0.1);
display: inline-block;
width: calc(100% + 2rem);
margin: 0 -1rem;
padding: 0 1rem;
}Supported languages
46 languages including js/javascript, ts/typescript, tsx, jsx, py/python, rs/rust, go, vue, svelte, astro, css, html, json, yaml/yml, bash/sh/shell, and more — plus Comark itself under comark/mdc/md/markdown.
Full list: rangi languages.