Skip to content

Commit

Permalink
Change toHTML rendering to allow custom HTML content inside cells and…
Browse files Browse the repository at this point in the history
… not just text

fixes #319
  • Loading branch information
koperagen committed Nov 25, 2024
1 parent c7b1004 commit 8d59c97
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ public data class IMG(
if (height != null) style.append("height:${height}px;")
if (maxWidth != null) style.append("max-width:${maxWidth}px;")
if (maxHeight != null) style.append("max-height:${maxHeight}px;")
return """<img src="$src" style="$style"}/>"""
return """<img src="$src" style="$style"/>"""
}
}
14 changes: 13 additions & 1 deletion core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/html.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import org.jetbrains.kotlinx.dataframe.columns.BaseColumn
import org.jetbrains.kotlinx.dataframe.columns.ColumnGroup
import org.jetbrains.kotlinx.dataframe.columns.ColumnWithPath
import org.jetbrains.kotlinx.dataframe.columns.FrameColumn
import org.jetbrains.kotlinx.dataframe.dataTypes.IFRAME
import org.jetbrains.kotlinx.dataframe.dataTypes.IMG
import org.jetbrains.kotlinx.dataframe.impl.DataFrameSize
import org.jetbrains.kotlinx.dataframe.impl.columns.addPath
import org.jetbrains.kotlinx.dataframe.impl.io.resizeKeepingAspectRatio
Expand Down Expand Up @@ -514,6 +516,8 @@ private fun AnyFrame.getColumnsHeaderGrid(): List<List<ColumnWithPathWithBorder<
internal fun DataFrameHtmlData.print() = println(this)

/**
* By default, cell content is formatted as text
* Use [RenderedContent.media] or [IMG], [IFRAME] if you need custom HTML inside a cell.
* @return DataFrameHtmlData with table script and css definitions. Can be saved as an *.html file and displayed in the browser
*/
public fun <T> DataFrame<T>.toStandaloneHTML(
Expand All @@ -523,6 +527,8 @@ public fun <T> DataFrame<T>.toStandaloneHTML(
): DataFrameHtmlData = toHTML(configuration, cellRenderer, getFooter).withTableDefinitions()

/**
* By default, cell content is formatted as text
* Use [RenderedContent.media] or [IMG], [IFRAME] if you need custom HTML inside a cell.
* @return DataFrameHtmlData without additional definitions. Can be rendered in Jupyter kernel environments
*/
public fun <T> DataFrame<T>.toHTML(
Expand Down Expand Up @@ -834,7 +840,7 @@ internal class DataFrameFormatter(
return sb.result()
}

val result = when (value) {
val result: RenderedContent? = when (value) {
null -> "null".addCss(nullClass)

is AnyRow -> {
Expand Down Expand Up @@ -899,6 +905,12 @@ internal class DataFrameFormatter(

is DataFrameHtmlData -> RenderedContent.text(value.body)

is IMG -> RenderedContent.media(value.toString())

is IFRAME -> RenderedContent.media(value.toString())

is RenderedContent -> value

else -> renderer.content(value, configuration)
}
if (result != null && result.textLength > configuration.cellContentLimit) return null
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.jetbrains.kotlinx.dataframe.jupyter

import org.intellij.lang.annotations.Language
import org.jetbrains.kotlinx.dataframe.io.DisplayConfiguration
import org.jetbrains.kotlinx.dataframe.io.renderValueForHtml
import org.jetbrains.kotlinx.dataframe.io.tooltipLimit
Expand All @@ -12,7 +13,9 @@ public data class RenderedContent(
) {
public companion object {

public fun media(html: String): RenderedContent = RenderedContent(html, 0, null, false)
public fun media(
@Language("HTML") html: String,
): RenderedContent = RenderedContent(html, 0, null, false)

public fun textWithLength(str: String, len: Int): RenderedContent = RenderedContent(str, len, null, false)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import org.jetbrains.kotlinx.dataframe.api.parse
import org.jetbrains.kotlinx.dataframe.api.schema
import org.jetbrains.kotlinx.dataframe.api.toDataFrame
import org.jetbrains.kotlinx.dataframe.api.with
import org.jetbrains.kotlinx.dataframe.dataTypes.IFRAME
import org.jetbrains.kotlinx.dataframe.dataTypes.IMG
import org.jetbrains.kotlinx.dataframe.io.DisplayConfiguration
import org.jetbrains.kotlinx.dataframe.io.escapeHTML
import org.jetbrains.kotlinx.dataframe.io.formatter
Expand Down Expand Up @@ -227,4 +229,26 @@ class RenderingTests : TestBase() {
val html = df.toStandaloneHTML()
html.toString() shouldInclude "style: \"background-color"
}

@Test
fun `render img`() {
val src = "https://github.com/Kotlin/dataframe/blob/master/docs/StardustDocs/images/gettingStarted.png?raw=true"
val df = dataFrameOf("img")(IMG(src))
df.toStandaloneHTML().toString() shouldInclude
"""values: ["<img src=\"https://github.com/Kotlin/dataframe/blob/master/docs/StardustDocs/images/gettingStarted.png?raw=true\" style=\"\"/>"]"""
}

@Test
fun `render custom content`() {
val df = dataFrameOf("customUrl")(RenderedContent.media("""<a href="http://example.com">Click me!</a>"""))
df.toStandaloneHTML().toString() shouldInclude
"""values: ["<a href=\"http://example.com\">Click me!</a>"]"""
}

@Test
fun `render iframe content`() {
val df = dataFrameOf("iframe")(IFRAME("http://example.com"))
df.toStandaloneHTML().toString() shouldInclude
"""values: ["<iframe src=\"http://example.com\"""
}
}

0 comments on commit 8d59c97

Please sign in to comment.