Compose Markdown

repository·main·Indexed 21 days ago

https://github.com/jeziellago/compose-markdown

A Jetpack Compose library for rendering Markdown content using a TextView-based renderer. It supports rich text, HTML, images, tables, and task lists via the MarkdownText composable. The library includes customization options through TextStyle, MardownCorePlugin for syntax highlighting, and ImagesPlugin for Coil-integrated image and GIF support.

Tokens
2.4K
Snippets
7
Records
8
Agent score
73%

What's inside compose-markdown

  1. Use MarkdownText for basic markdown rendering

    main

    The primary entry point is the MarkdownText composable. Pass your markdown string to the markdown parameter to render it.

    import androidx.compose.runtime.Composable
    import dev.jeziellago.compose.markdowntext.MarkdownText
    
    @Composable
    fun ArticleBody() {
        val markdown = """
            # Compose Markdown
    
            Render **markdown**, [links](https://github.com/jeziellago/compose-markdown),
            images, tables, task lists, and even inline HTML.
    
            - [x] Markdown
            - [x] HTML
            - [x] Images
        """.trimIndent()
    
        MarkdownText(markdown = markdown)
    }
  2. Install Compose Markdown via JitPack

    main

    To use Compose Markdown in your Android project, you must first add the JitPack repository to your settings.gradle file, and then add the dependency to your build.gradle file.

    1. Add JitPack to settings.gradle

    Add maven { url 'https://jitpack.io' } to your dependencyResolutionManagement block:

    dependencyResolutionManagement {
        repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
        repositories {
            google()
            mavenCentral()
            maven { url 'https://jitpack.io' }
        }
    }

    2. Add the dependency

    Add the following line to your dependencies block, replacing VERSION with the desired version:

    dependencies {
        implementation 'com.github.jeziellago:compose-markdown:VERSION'
    }
  3. Handle clicks and link interactions in MarkdownText

    main

    You can intercept clicks on the entire composable using onClick or intercept specific markdown link clicks using onLinkClicked.

    Note: If you want the parent container to receive tap events instead of the internal link handler, set disableLinkMovementMethod = true.

    import android.widget.Toast
    import androidx.compose.runtime.Composable
    import androidx.compose.ui.platform.LocalContext
    import androidx.compose.ui.text.TextStyle
    import androidx.compose.ui.unit.sp
    import dev.jeziellago.compose.markdowntext.MarkdownText
    
    @Composable
    fun InteractiveMarkdown() {
        val context = LocalContext.current
    
        MarkdownText(
            markdown = """
                ## Interactive content
    
                Visit [GitHub](https://github.com/jeziellago/compose-markdown)
                or tap anywhere in this block.
            """.trimIndent(),
            style = TextStyle(fontSize = 18.sp),
            isTextSelectable = true,
            onClick = {
                Toast.makeText(context, "Block clicked", Toast.LENGTH_SHORT).show()
            },
            onLinkClicked = {\ url ->
                Toast.makeText(context, url, Toast.LENGTH_SHORT).show()
            },
        )
    }
    import android.widget.Toast
    import androidx.compose.runtime.Composable
    import androidx.compose.ui.platform.LocalContext
    import androidx.compose.ui.text.TextStyle
    import androidx.compose.ui.unit.sp
    import dev.jeziellago.compose.markdowntext.MarkdownText
    
    @Composable
    fun InteractiveMarkdown() {
        val context = LocalContext.current
    
        MarkdownText(
            markdown = """
                ## Interactive content
    
                Visit [GitHub](https://github.com/jeziellago/compose-markdown)
                or tap anywhere in this block.
            """.trimIndent(),
            style = TextStyle(fontSize = 18.sp),
            isTextSelectable = true,
            onClick = {
                Toast.makeText(context, "Block clicked", Toast.LENGTH_SHORT).show()
            },
            onLinkClicked = {
                Toast.makeText(context, url, Toast.LENGTH_SHORT).show()
            },
        )
    }
  4. Style MarkdownText with Compose TextStyles

    main

    You can customize the appearance of the rendered markdown using standard Compose Modifier and TextStyle objects. This allows you to control color, font size, line height, alignment, and line limits.

    import androidx.compose.foundation.layout.padding
    import androidx.compose.runtime.Composable
    import androidx.compose.ui.Modifier
    import androidx.compose.ui.graphics.Color
    import androidx.compose.ui.text.TextStyle
    import androidx.compose.ui.text.style.TextAlign
    import androidx.compose.ui.unit.dp
    import androidx.compose.ui.unit.sp
    import dev.jeziellago.compose.markdowntext.MarkdownText
    
    @Composable
    fun StyledMarkdown() {
        MarkdownText(
            modifier = Modifier.padding(16.dp),
            markdown = """
                ## Styled markdown
    
                This text uses a custom `TextStyle`, supports [links](https://example.com),
                and can be limited to a specific number of lines.
            """.trimIndent(),
            maxLines = 4,
            style = TextStyle(
                color = Color(0xFF1F3A5F),
                fontSize = 16.sp,
                lineHeight = 24.sp,
                textAlign = TextAlign.Justify,
            ),
        )
    }
  5. Reference: MarkdownText parameters

    main

    The MarkdownText composable exposes the following parameters for customization:

    ParameterDescription
    modifierApply Compose layout and interaction modifiers
    styleConfigure color, alignment, font size, line height, and more
    maxLinesLimit rendered lines
    truncateOnTextOverflowEnable ellipsizing
    fontResourceApply an Android font resource
    isTextSelectableEnable long-press text selection
    linkColorOverride link color
    disableLinkMovementMethodDisable internal link handling so parent click handlers can receive taps
    onClickHandle clicks on the whole composable
    onLinkClickedIntercept markdown link clicks
    imageLoaderProvide a custom Coil ImageLoader
    autoSizeConfigEnable auto-sizing on API 26+
    enableSoftBreakAddsNewLineTreat soft breaks as new lines
    headingBreakColorCustomize heading divider color
    enableUnderlineForLinkTurn link underlines on or off
    onTextLayoutObserve rendered line count
  6. Enable image and GIF support with ImagesPlugin

    main

    To render images and GIFs within your markdown text, use the ImagesPlugin. This plugin integrates with Coil to handle asynchronous image loading and supports animated content (like GIFs) by automatically starting the animation once the drawable is loaded.

    To use it, call ImagesPlugin.create(context, imageLoader) where context is your Android Context and imageLoader is an instance of a Coil ImageLoader.

    // Assuming you have a Coil ImageLoader instance
    val imageLoader = ImageLoader(context)
    
    // Create the plugin
    val imagesPlugin = ImagesPlugin.create(context, imageLoader)
    
    // Pass this plugin to your Markwon/Compose Markdown configuration
  7. Initialize MardownCorePlugin

    main

    The MardownCorePlugin is the primary plugin used to customize the markdown rendering behavior in Compose Markdown. It allows you to control syntax highlighting colors, link underlining, and intercept text addition events.

    To use it, instantiate it with the following parameters:

    • syntaxHighlightColor: An integer representing the background color for code blocks.
    • syntaxHighlightTextColor: An integer representing the text color for code blocks. If set to Color.Unspecified.toArgb(), the default text color is used.
    • enableUnderlineForLink: A boolean to determine if links should be underlined.
    • onTextAddedListeners: (Optional) A list of OnTextAddedListener instances to be notified when text is processed.
    val plugin = MardownCorePlugin(
        syntaxHighlightColor = Color.Black.toArgb(),
        syntaxHighlightTextColor = Color.White.toArgb(),
        enableUnderlineForLink = true
    )
  8. Register an OnTextAddedListener in MardownCorePlugin

    main

    You can intercept text as it is being added to the rendered output by using the addOnTextAddedListener method. This is useful for advanced text manipulation or tracking content during the rendering lifecycle.

    addOnTextAddedListener returns the plugin instance, allowing for a fluent API style.

    plugin.addOnTextAddedListener { visitor, literal, length ->
        // Handle text addition
    }