Skip to content

Commit 3ee238f

Browse files
committed
Change toHTML rendering to allow custom HTML content inside cells and not just text
fixes #319
1 parent c7b1004 commit 3ee238f

File tree

4 files changed

+41
-3
lines changed

4 files changed

+41
-3
lines changed

core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/dataTypes/IMG.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,6 @@ public data class IMG(
2323
if (height != null) style.append("height:${height}px;")
2424
if (maxWidth != null) style.append("max-width:${maxWidth}px;")
2525
if (maxHeight != null) style.append("max-height:${maxHeight}px;")
26-
return """<img src="$src" style="$style"}/>"""
26+
return """<img src="$src" style="$style"/>"""
2727
}
2828
}

core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/html.kt

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import org.jetbrains.kotlinx.dataframe.columns.BaseColumn
2020
import org.jetbrains.kotlinx.dataframe.columns.ColumnGroup
2121
import org.jetbrains.kotlinx.dataframe.columns.ColumnWithPath
2222
import org.jetbrains.kotlinx.dataframe.columns.FrameColumn
23+
import org.jetbrains.kotlinx.dataframe.dataTypes.IFRAME
24+
import org.jetbrains.kotlinx.dataframe.dataTypes.IMG
2325
import org.jetbrains.kotlinx.dataframe.impl.DataFrameSize
2426
import org.jetbrains.kotlinx.dataframe.impl.columns.addPath
2527
import org.jetbrains.kotlinx.dataframe.impl.io.resizeKeepingAspectRatio
@@ -514,6 +516,8 @@ private fun AnyFrame.getColumnsHeaderGrid(): List<List<ColumnWithPathWithBorder<
514516
internal fun DataFrameHtmlData.print() = println(this)
515517

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

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

837-
val result = when (value) {
843+
val result: RenderedContent? = when (value) {
838844
null -> "null".addCss(nullClass)
839845

840846
is AnyRow -> {
@@ -899,6 +905,12 @@ internal class DataFrameFormatter(
899905

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

908+
is IMG -> RenderedContent.media(value.toString())
909+
910+
is IFRAME -> RenderedContent.media(value.toString())
911+
912+
is RenderedContent -> value
913+
902914
else -> renderer.content(value, configuration)
903915
}
904916
if (result != null && result.textLength > configuration.cellContentLimit) return null

core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/jupyter/CellRenderer.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.jetbrains.kotlinx.dataframe.jupyter
22

3+
import org.intellij.lang.annotations.Language
34
import org.jetbrains.kotlinx.dataframe.io.DisplayConfiguration
45
import org.jetbrains.kotlinx.dataframe.io.renderValueForHtml
56
import org.jetbrains.kotlinx.dataframe.io.tooltipLimit
@@ -12,7 +13,9 @@ public data class RenderedContent(
1213
) {
1314
public companion object {
1415

15-
public fun media(html: String): RenderedContent = RenderedContent(html, 0, null, false)
16+
public fun media(
17+
@Language("HTML") html: String,
18+
): RenderedContent = RenderedContent(html, 0, null, false)
1619

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

core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/rendering/RenderingTests.kt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import org.jetbrains.kotlinx.dataframe.api.parse
2020
import org.jetbrains.kotlinx.dataframe.api.schema
2121
import org.jetbrains.kotlinx.dataframe.api.toDataFrame
2222
import org.jetbrains.kotlinx.dataframe.api.with
23+
import org.jetbrains.kotlinx.dataframe.dataTypes.IFRAME
24+
import org.jetbrains.kotlinx.dataframe.dataTypes.IMG
2325
import org.jetbrains.kotlinx.dataframe.io.DisplayConfiguration
2426
import org.jetbrains.kotlinx.dataframe.io.escapeHTML
2527
import org.jetbrains.kotlinx.dataframe.io.formatter
@@ -227,4 +229,25 @@ class RenderingTests : TestBase() {
227229
val html = df.toStandaloneHTML()
228230
html.toString() shouldInclude "style: \"background-color"
229231
}
232+
233+
@Test
234+
fun `render img`() {
235+
val src = "https://github.com/Kotlin/dataframe/blob/master/docs/StardustDocs/images/gettingStarted.png?raw=true"
236+
val df = dataFrameOf("img")(IMG(src))
237+
df.toStandaloneHTML().toString() shouldInclude
238+
"""values: ["<img src=\"https://github.com/Kotlin/dataframe/blob/master/docs/StardustDocs/images/gettingStarted.png?raw=true\" style=\"\"/>"]"""
239+
}
240+
241+
@Test
242+
fun `render custom content`() {
243+
val df = dataFrameOf("customUrl")(RenderedContent.media("""<a href="http://example.com">Click me!</a>"""))
244+
df.toStandaloneHTML().openInBrowser()
245+
}
246+
247+
@Test
248+
fun `render iframe content`() {
249+
val df = dataFrameOf("customUrl")(IFRAME("http://example.com"))
250+
df.toStandaloneHTML().toString() shouldInclude
251+
"""values: ["<iframe src=\"http://example.com\"""
252+
}
230253
}

0 commit comments

Comments
 (0)