kotlinx.html
kotlinx.html copied to clipboard
JSDOMBuilder converts raw string contents to HTML tags
I want to display a Map<String, String>
in an HTML page.
import kotlinx.browser.document
import kotlinx.html.*
import kotlinx.html.dom.*
fun main() {
document.body!!.append.div {
pre {
code {
unsafe {
raw("""
val map: Map<String, String> = mapOf(
"key1" to "value1",
"key2" to "value2",
)
""".trimIndent())
}
}
}
}
The code is not display 'raw' though, and the generic parameters are converted into HTML tags <string, string="">
- very strange!
<div>
<pre>
<code>
val map: Map<string, string=""> = mapOf(
"key1" to "value1",
"key2" to "value2",
)
</string,>
</code>
</pre>
</div>
The code rendered in my browser does not match the raw string.

Expected result
If I don't use JSDOMBBuilder
, then the HTML matches the raw content:
import kotlinx.html.*
import kotlinx.html.dom.createHTMLDocument
import kotlinx.html.stream.createHTML
fun main() {
println(createHTML(prettyPrint = true).div {
pre {
code {
unsafe {
raw("""
val map: Map<String, String> = mapOf(
"key1" to "value1",
"key2" to "value2",
)
""".trimIndent())
}
}
}
})
}
<div>
<pre><code>val map: Map<String, String> = mapOf(
"key1" to "value1",
"key2" to "value2",
)</code></pre>
</div>
Compose Web
With Compose Web v1.2.2 I am also able to output raw content
import org.jetbrains.compose.web.*
import org.jetbrains.compose.web.css.*
import org.jetbrains.compose.web.dom.*
fun main() {
renderComposable(rootElementId = "root") {
Div {
Pre {
Code {
Text(
"""
val map: Map<String, String> = mapOf(
"key1" to "value1",
"key2" to "value2",
)
""".trimIndent()
)
}
}
}
}
}
However, Compose Web escapes the angled brackets.
<div><pre><code>
val map: Map<String, String> = mapOf(
"key1" to "value1",
"key2" to "value2",
)</code></pre></div>
The result matches the raw input:

Versions
- Kotlin/JS 1.7.20
- Kotlinx HTML 0.7.5
Because your code includes angled brackets, it actually should be escaped. The un-escaped code of
<div>
<pre><code>val map: Map<String, String> = mapOf(
"key1" to "value1",
"key2" to "value2",
)</code></pre>
</div>
will display like this in a browser:
val map: Map = mapOf(
"key1" to "value1",
"key2" to "value2",
)
i.e. the type declaration of the map does not render.
Instead, you should just use the normal text appending functionality in the library if you want to inject Kotlin code into a <code>
block, e.g.
fun main() {
document.body!!.append.div {
pre {
code {
+"""
val map: Map<String, String> = mapOf(
"key1" to "value1",
"key2" to "value2",
)
""".trimIndent()
}
}
}
}
Thanks for the suggestion @severn-everett. You are right, that technically the code should be escaped.
It's been a while since I looked at this. IIRC I was trying to use a JavaScript library for code syntax highlighting, which required the angled brackets were rendered as-is, because it needed to parse the code. It would then perform its own escaping.