Render Markdown in Compose Web (HTML)

399 Views Asked by At

I have a Compose Web app. How can I render Markdown on it?

1

There are 1 best solutions below

0
On

I found a fairly simple solution, by using the md-block library.

First we need to import the md-block script. We can either add it as an npm dependency, or simply load the module from url, like so.

<!-- Put this in your index.html -->
<script type="module" src="https://md-block.verou.me/md-block.js"></script>

And then in Kotlin:

// In your view html dsl:
var mdText: String? by mutableStateOf(null)

Button(attrs = {
    onClick {
        scope.launch {
            mdText = null // Reset value for md-block re-rendering
            mdText = viewModel.fetchContent()
        }
    }
}) {
    Text("Fetch data!")
}

mdText?.let {
    MarkDown(it)
}
// In some shared file:
@Composable
fun MarkDown(
    mdText: String,
    attrs: AttrBuilderContext<HTMLElement>? = null,
) {
    TagElement(
        elementBuilder = {
            document.createElement("md-block").cloneNode() as HTMLElement
        },
        applyAttrs = attrs,
    ) {     
        Text(mdText)
    }
}

Note that md-block is made so that it won't re-render on recomposition, even though the state value changes (see documentation for details). That is why we must nullify mdText before setting a new value, so that the <md-block> is completely removed and re-added.

Is there a better way?