remember Highlighted Code
Pre-highlights code and remembers the resulting AnnotatedString.
Returns null while highlighting is in progress or if highlighting failed.
In preview / inspection mode, returns a plain-text AnnotatedString(code) immediately so @Preview composables can render without creating the WebView-backed engine.
Re-runs automatically when code, language, or theme changes.
Usage
@Composable
fun CodeSnippet(code: String, language: String) {
val highlighted by rememberHighlightedCode(code, language)
// highlighted is null while loading or if highlighting failed;
// fall back to plain text in that case
Text(
text = highlighted ?: AnnotatedString(code),
style = TextStyle(fontFamily = FontFamily.Monospace),
)
}Theme creation
Built-in themes are precompiled and need no android.content.Context:
val theme = remember { HighlightTheme.tomorrow() }
val highlighted by rememberHighlightedCode(code, "kotlin", theme)For custom CSS-backed themes, wrap creation in remember so CSS parsing does not repeat on every recomposition. Or use the built-in convenience functions which handle this internally:
val highlighted by rememberHighlightedCode(code, "kotlin", rememberTomorrowTheme())For light/dark toggling without re-highlighting, prefer rememberHighlightedCodeBothThemes.
Return
A State holding the highlighted AnnotatedString, or null while loading / on error. In inspection mode, the state is initialized to plain text immediately.
Parameters
The source code to highlight.
The Highlight.js language identifier (e.g. "python", "kotlin").
The theme to apply. Defaults to LocalHighlightTheme.
Optional callback invoked with a HighlightResult when highlighting succeeds. Fires after the State is updated. Not called on failure.
Optional callback invoked with the HighlightException when highlighting fails. Use this to log failures, show a snackbar, or record analytics. The plain-text fallback is always displayed regardless of whether this callback is set - it is purely observational. Use rememberUpdatedState semantics: the latest lambda is always called without restarting the effect. The HighlightException subtypes give you typed error info:
HighlightException.Timeout - JS call did not complete in time
HighlightException.JsExecutionFailed - JavaScript error
HighlightException.WebViewInitFailed - WebView could not be created
HighlightException.HtmlParseFailed - the HTML parser could not parse the highlight output
val highlighted by rememberHighlightedCode(
code = myCode,
language = userInput,
onError = { error ->
Log.w("Highlight", "Failed to highlight: ${error.message}")
},
)