A lightweight Android library to convert Markdown text into a Jetpack Compose AnnotatedString. Use com.sumup.markdown:annotatedstring-generator to produce one AnnotatedString for a Compose Text on Android (minSdk 24).
This library is built on top of JetBrains intellij-markdown, a multiplatform Markdown processor written in Kotlin.
This library supports common Markdown syntax, including:
- Bold and Italic text
- Headers
- Block quotes
- Ordered and unordered lists
- Links
- Code blocks and inline code
- Horizontal rules
- Images (rendered as text placeholder)
- Android
minSdk24 - Jetpack Compose. Compose Foundation is brought in by this library.
Use this library when Markdown should become one styled string inside a Compose Text. The parser is CommonMark through JetBrains intellij-markdown. Links are a "URL" string annotation. Images are text placeholders. A TextView/Spannable library, or a renderer that emits a column of Compose nodes, fits a different layout.
Add the dependency to your module's build.gradle.kts. The Maven Central badge above shows the latest published version. This snippet uses 0.1.1.
dependencies {
implementation("com.sumup.markdown:annotatedstring-generator:0.1.1")
}Groovy (build.gradle)
dependencies {
implementation 'com.sumup.markdown:annotatedstring-generator:0.1.1'
}Snapshot versions
Stable releases are published to Maven Central. To try an unpublished snapshot (for example 0.1.2-SNAPSHOT), add the Maven Central snapshots repository in your settings.gradle.kts:
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven("https://central.sonatype.com/repository/maven-snapshots/")
}
}Then use the snapshot version in your dependency:
dependencies {
implementation("com.sumup.markdown:annotatedstring-generator:0.1.2-SNAPSHOT")
}Imports:
import com.sumup.markdown.annotatedstring.AnnotatedStringGenerator
import com.sumup.markdown.annotatedstring.CommonMarkFlavourDescriptor
import org.intellij.markdown.parser.MarkdownParserParse your markdown and generate an AnnotatedString:
val markdown = "Hello **world**! This is *italic* and `code`."
val flavour = CommonMarkFlavourDescriptor()
val parser = MarkdownParser(flavour)
val root = parser.buildMarkdownTreeFromString(markdown)
val annotatedString = AnnotatedStringGenerator(markdown, root, flavour).generateAnnotatedString()Use the generated AnnotatedString directly in a Compose Text or ClickableText:
@Composable
fun MarkdownText(markdown: String, modifier: Modifier = Modifier) {
val flavour = remember { CommonMarkFlavourDescriptor() }
val annotatedString = remember(markdown) {
val parser = MarkdownParser(flavour)
val root = parser.buildMarkdownTreeFromString(markdown)
AnnotatedStringGenerator(markdown, root, flavour).generateAnnotatedString()
}
Text(
text = annotatedString,
modifier = modifier,
)
}Links are annotated with a "URL" string annotation. Use ClickableText to handle taps:
@Composable
fun ClickableMarkdownText(markdown: String, modifier: Modifier = Modifier) {
val flavour = remember { CommonMarkFlavourDescriptor() }
val annotatedString = remember(markdown) {
val parser = MarkdownParser(flavour)
val root = parser.buildMarkdownTreeFromString(markdown)
AnnotatedStringGenerator(markdown, root, flavour).generateAnnotatedString()
}
val uriHandler = LocalUriHandler.current
ClickableText(
text = annotatedString,
modifier = modifier,
onClick = { offset ->
annotatedString.getStringAnnotations(tag = "URL", start = offset, end = offset)
.firstOrNull()?.let { annotation ->
uriHandler.openUri(annotation.item)
}
}
)
}The sample module is a small Compose playground for the same API.
To build the library from source, clone the repository and run the following command:
./gradlew :annotatedstring-generator:assembleReleaseThis project uses JUnit and Paparazzi for testing.
To run the unit tests:
./gradlew :annotatedstring-generator:testDebugUnitTestTo run the Paparazzi snapshot tests:
./gradlew :annotatedstring-generator:verifyPaparazziDebugCopyright 2026 SumUp
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.