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
417 stars 27 forks source link

Customize header element with MarkdownComponent #200

Closed gs-ts closed 2 months ago

gs-ts commented 2 months 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 months ago

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

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

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

mikepenz commented 2 months 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