Skip to content

HighlightTheme

HighlightTheme maps hljs-* token classes to Compose SpanStyle values used by the highlight pipeline.

Full API in Dokka:

When to use each theme source

  • Built-in themes (tomorrow, tomorrowNight, atomOneDark, atomOneLight): fastest setup, precompiled maps, no CSS parsing at runtime.
  • fromAsset(...): best for shipping a highlight.js CSS file with your app.
  • fromCss(...): useful when CSS comes from network, config, or generated text.
  • fromColorMap(...): best when you want full programmatic control, for example Material 3 dynamic color integration.

Use remember*Theme() helpers inside composables so the theme instance stays stable across recompositions.

import dev.hossain.highlight.ui.HighlightThemeProvider
import dev.hossain.highlight.ui.rememberTomorrowNightTheme
import dev.hossain.highlight.ui.rememberTomorrowTheme

HighlightThemeProvider(
    lightHighlightTheme = rememberTomorrowTheme(),
    darkHighlightTheme  = rememberTomorrowNightTheme(),
) { ... }

Custom theme from asset CSS

import androidx.compose.ui.platform.LocalContext
import dev.hossain.highlight.engine.HighlightTheme
import dev.hossain.highlight.ui.HighlightThemeProvider

val appContext = LocalContext.current.applicationContext
val theme = HighlightTheme.fromAsset(
    context   = appContext,
    assetPath = "themes/github.css",
    name      = "github",
)

HighlightThemeProvider(lightHighlightTheme = theme) { ... }

Note

fromAsset() is lazy. CSS parsing happens on first theme usage, not at factory call time.

Custom theme from raw CSS

val theme = HighlightTheme.fromCss(
    cssText = css,
    name    = "my-runtime-theme",
)

Custom theme from a color map

val theme = HighlightTheme.fromColorMap(
    name             = "my-dynamic-theme",
    colorMap         = colorMap,
    backgroundColor  = Color(0xFFFFFFFF),
    defaultTextColor = Color(0xFF24292E),
)

Theme identity behavior

HighlightTheme equality is based on both name and content identity. This gives stable memoization while still triggering re-highlighting when CSS content changes.

  • Same name and same CSS content -> equal.
  • Same name and different CSS content -> not equal.
  • Different names -> not equal.
val light = HighlightTheme.fromCss(lightCss, "custom")
val dark  = HighlightTheme.fromCss(darkCss,  "custom")
light == dark  // false

val a = HighlightTheme.fromCss(css, "custom")
val b = HighlightTheme.fromCss(css, "custom")
a == b         // true

Common pitfalls

  • Passing activity context to long-lived themes in non-Compose layers.
  • Expecting fromAsset() parse failures at construction time rather than first use.
  • Recreating custom themes every recomposition instead of remembering stable instances.