Built-in

Rangi (Highlight)

Lightweight syntax highlighting for code blocks using rangi.

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:

terminal
npm install rangi
Use comark/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>

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 (javascriptjs, typescriptts, pythonpy, ymlyaml, …). 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

OptionTypeDefaultDescription
themeShjTheme | { light, dark }rangi default pairInline colors
lineNumbersbooleanfalseWrap each line in <span class="line">
classPrefixstring'shj'Class prefix on the highlighted <pre>
languagesRecord<string, grammar>Extra custom grammars, merged over the Comark ones
preStylesbooleanfalseAdd 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 pair

Or 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

Vue + Vite Rangi

Rangi dual themes as inline colors, line highlights, light/dark toggle.

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.