mikepenz / multiplatform-markdown-renderer

Markdown renderer for Kotlin Multiplatform Projects (Android, iOS, Desktop), using Compose.
https://mikepenz.github.io/multiplatform-markdown-renderer/
Apache License 2.0
380 stars 25 forks source link

Customize header element with MarkdownComponent #200

Closed gs-ts closed 2 weeks ago

gs-ts commented 2 weeks ago

About this issue

Here I am again with another simple issue which I have been stuck all day...

I am trying to style a heading2 with text align in center and a different color. So let's say we have the following markdown example:

val markdownExample = """
                      ## What's included

                      - Super simple setup
                      - Cross-platform ready
                      - Lightweight
                      """.trimIndent()

val customHeading2: MarkdownComponent = {
    val styledText = buildAnnotatedString {
        pushStyle(LocalMarkdownTypography.current.h2.toSpanStyle().copy(color = Color.Red))
        buildMarkdownAnnotatedString(it.content, it.node)
        pop()
    }

    Text(
        styledText,
        modifier = Modifier.fillMaxSize(),
        textAlign = TextAlign.Center
    )
}

Markdown(
    content = markdownExample.trimIndent(),
    colors = markdownColor(),
    typography = markdownTypography(),
    components = markdownComponents(heading2 = customHeading2)
)

However, this disappears completely the heading from the content. Isn't the LocalMarkdownTypography.current.h2 the one that we need to customize?

Details

Checklist

gs-ts commented 2 weeks ago

I am also trying with markdownAnnotator but doesn't work either 😕

 markdownAnnotator { content, child ->
     if (child.type == GFMElementTypes.HEADER) {
          ....
     }
gs-ts commented 2 weeks ago

@mikepenz I would highly appreciate it if you could help me with this 🙂

mikepenz commented 2 weeks ago

@gs-ts you are already pretty close, however the code on how to retrieve the content is not yet correct.

The library exposes the same structure as the markdown library parses, as such the correct node needs to be used. You can see how a default header is implemented here: https://github.com/mikepenz/multiplatform-markdown-renderer/blob/develop/multiplatform-markdown-renderer/src/commonMain/kotlin/com/mikepenz/markdown/compose/elements/MarkdownHeader.kt#L20-L28

Putting this in action in your case will look like:

val customHeading2: MarkdownComponent = {
    val content = it.content
    it.node.findChildOfType(MarkdownTokenTypes.ATX_CONTENT)?.let {
        val styledText = buildAnnotatedString {
            pushStyle(LocalMarkdownTypography.current.h2.toSpanStyle().copy(color = Color.Red))
            buildMarkdownAnnotatedString(content, it)
            pop()
        }
        Text(
            styledText,
            modifier = Modifier.fillMaxSize(),
            textAlign = TextAlign.Center
        )
    }
}
Screenshot 2024-08-30 at 09 26 02