Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -254,15 +254,17 @@ public fun <T> DataFrame<T>.html(): String = toStandaloneHTML().toString()
public fun <T> DataFrame<T>.toStandaloneHTML(
configuration: DisplayConfiguration = DisplayConfiguration.DEFAULT,
cellRenderer: CellRenderer = DefaultCellRenderer,
includeStatic: Boolean = true,
getFooter: (DataFrame<T>) -> String? = { "DataFrame [${it.size}]" },
): DataFrameHtmlData = toHTML(configuration, cellRenderer, getFooter).withTableDefinitions()
): DataFrameHtmlData = toHTML(configuration, cellRenderer, includeStatic, getFooter).withTableDefinitions()

/**
* @return DataFrameHtmlData without additional definitions. Can be rendered in Jupyter kernel environments
*/
public fun <T> DataFrame<T>.toHTML(
configuration: DisplayConfiguration = DisplayConfiguration.DEFAULT,
cellRenderer: CellRenderer = DefaultCellRenderer,
includeStatic: Boolean = true,
getFooter: (DataFrame<T>) -> String? = { "DataFrame [${it.size}]" },
): DataFrameHtmlData {
val limit = configuration.rowsLimit ?: Int.MAX_VALUE
Expand All @@ -283,7 +285,9 @@ public fun <T> DataFrame<T>.toHTML(

var tableHtml = toHtmlData(configuration, cellRenderer)

tableHtml += toStaticHtml(configuration, DefaultCellRenderer)
if (includeStatic) {
tableHtml += toStaticHtml(configuration, DefaultCellRenderer)
}

if (bodyFooter != null) {
tableHtml += DataFrameHtmlData("", bodyFooter, "")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import org.jetbrains.kotlinx.dataframe.io.DataFrameHtmlData
import org.jetbrains.kotlinx.dataframe.io.DisplayConfiguration
import org.jetbrains.kotlinx.dataframe.io.encodeFrame
import org.jetbrains.kotlinx.dataframe.io.toHTML
import org.jetbrains.kotlinx.dataframe.io.toStaticHtml
import org.jetbrains.kotlinx.dataframe.jupyter.KotlinNotebookPluginUtils.convertToDataFrame
import org.jetbrains.kotlinx.dataframe.nrow
import org.jetbrains.kotlinx.dataframe.size
Expand All @@ -30,7 +31,7 @@ internal class JupyterHtmlRenderer(
internal inline fun <reified T : Any> JupyterHtmlRenderer.render(
noinline getFooter: (T) -> String,
crossinline modifyConfig: T.(DisplayConfiguration) -> DisplayConfiguration = { it },
applyRowsLimit: Boolean = true
applyRowsLimit: Boolean = true,
) = builder.renderWithHost<T> { host, value ->
val contextRenderer = JupyterCellRenderer(this.notebook, host)
val reifiedDisplayConfiguration = value.modifyConfig(display)
Expand All @@ -44,36 +45,41 @@ internal inline fun <reified T : Any> JupyterHtmlRenderer.render(
df.nrow
}

val html = (
DataFrameHtmlData.tableDefinitions(
includeJs = reifiedDisplayConfiguration.isolatedOutputs,
includeCss = true
) + df.toHTML(
reifiedDisplayConfiguration,
contextRenderer
val html = DataFrameHtmlData.tableDefinitions(
includeJs = reifiedDisplayConfiguration.isolatedOutputs,
includeCss = true,
).plus(
df.toHTML(
configuration = reifiedDisplayConfiguration,
cellRenderer = contextRenderer,
includeStatic = false, // is added later to make sure it's put outside of potential iFrames
) { footer }
).toJupyterHtmlData()
).toJupyterHtmlData()

// Generates a static version of the table which can be displayed in GitHub previews etc.
val staticHtml = df.toStaticHtml(reifiedDisplayConfiguration, DefaultCellRenderer).toJupyterHtmlData()

if (notebook.kernelVersion >= KotlinKernelVersion.from(MIN_KERNEL_VERSION_FOR_NEW_TABLES_UI)!!) {
val jsonEncodedDf = json {
obj(
"nrow" to df.size.nrow,
"ncol" to df.size.ncol,
"columns" to df.columnNames(),
"kotlin_dataframe" to encodeFrame(df.rows().take(limit).toDataFrame())
"kotlin_dataframe" to encodeFrame(df.rows().take(limit).toDataFrame()),
)
}.toJsonString()
notebook.renderAsIFrameAsNeeded(html, jsonEncodedDf)
notebook.renderAsIFrameAsNeeded(html, staticHtml, jsonEncodedDf)
} else {
notebook.renderHtmlAsIFrameIfNeeded(html)
}
}

internal fun Notebook.renderAsIFrameAsNeeded(data: HtmlData, jsonEncodedDf: String): MimeTypedResult {
internal fun Notebook.renderAsIFrameAsNeeded(data: HtmlData, staticData: HtmlData, jsonEncodedDf: String): MimeTypedResult {
val textHtml = if (jupyterClientType == JupyterClientType.KOTLIN_NOTEBOOK) {
data.generateIframePlaneText(currentColorScheme)
data.generateIframePlaneText(currentColorScheme) +
staticData.toString(currentColorScheme)
} else {
data.toString(currentColorScheme)
(data + staticData).toString(currentColorScheme)
}

return mimeResult(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,15 +254,17 @@ public fun <T> DataFrame<T>.html(): String = toStandaloneHTML().toString()
public fun <T> DataFrame<T>.toStandaloneHTML(
configuration: DisplayConfiguration = DisplayConfiguration.DEFAULT,
cellRenderer: CellRenderer = DefaultCellRenderer,
includeStatic: Boolean = true,
getFooter: (DataFrame<T>) -> String? = { "DataFrame [${it.size}]" },
): DataFrameHtmlData = toHTML(configuration, cellRenderer, getFooter).withTableDefinitions()
): DataFrameHtmlData = toHTML(configuration, cellRenderer, includeStatic, getFooter).withTableDefinitions()

/**
* @return DataFrameHtmlData without additional definitions. Can be rendered in Jupyter kernel environments
*/
public fun <T> DataFrame<T>.toHTML(
configuration: DisplayConfiguration = DisplayConfiguration.DEFAULT,
cellRenderer: CellRenderer = DefaultCellRenderer,
includeStatic: Boolean = true,
getFooter: (DataFrame<T>) -> String? = { "DataFrame [${it.size}]" },
): DataFrameHtmlData {
val limit = configuration.rowsLimit ?: Int.MAX_VALUE
Expand All @@ -283,7 +285,9 @@ public fun <T> DataFrame<T>.toHTML(

var tableHtml = toHtmlData(configuration, cellRenderer)

tableHtml += toStaticHtml(configuration, DefaultCellRenderer)
if (includeStatic) {
tableHtml += toStaticHtml(configuration, DefaultCellRenderer)
}

if (bodyFooter != null) {
tableHtml += DataFrameHtmlData("", bodyFooter, "")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import org.jetbrains.kotlinx.dataframe.io.DataFrameHtmlData
import org.jetbrains.kotlinx.dataframe.io.DisplayConfiguration
import org.jetbrains.kotlinx.dataframe.io.encodeFrame
import org.jetbrains.kotlinx.dataframe.io.toHTML
import org.jetbrains.kotlinx.dataframe.io.toStaticHtml
import org.jetbrains.kotlinx.dataframe.jupyter.KotlinNotebookPluginUtils.convertToDataFrame
import org.jetbrains.kotlinx.dataframe.nrow
import org.jetbrains.kotlinx.dataframe.size
Expand All @@ -30,7 +31,7 @@ internal class JupyterHtmlRenderer(
internal inline fun <reified T : Any> JupyterHtmlRenderer.render(
noinline getFooter: (T) -> String,
crossinline modifyConfig: T.(DisplayConfiguration) -> DisplayConfiguration = { it },
applyRowsLimit: Boolean = true
applyRowsLimit: Boolean = true,
) = builder.renderWithHost<T> { host, value ->
val contextRenderer = JupyterCellRenderer(this.notebook, host)
val reifiedDisplayConfiguration = value.modifyConfig(display)
Expand All @@ -44,36 +45,41 @@ internal inline fun <reified T : Any> JupyterHtmlRenderer.render(
df.nrow
}

val html = (
DataFrameHtmlData.tableDefinitions(
includeJs = reifiedDisplayConfiguration.isolatedOutputs,
includeCss = true
) + df.toHTML(
reifiedDisplayConfiguration,
contextRenderer
val html = DataFrameHtmlData.tableDefinitions(
includeJs = reifiedDisplayConfiguration.isolatedOutputs,
includeCss = true,
).plus(
df.toHTML(
configuration = reifiedDisplayConfiguration,
cellRenderer = contextRenderer,
includeStatic = false, // is added later to make sure it's put outside of potential iFrames
) { footer }
).toJupyterHtmlData()
).toJupyterHtmlData()

// Generates a static version of the table which can be displayed in GitHub previews etc.
val staticHtml = df.toStaticHtml(reifiedDisplayConfiguration, DefaultCellRenderer).toJupyterHtmlData()

if (notebook.kernelVersion >= KotlinKernelVersion.from(MIN_KERNEL_VERSION_FOR_NEW_TABLES_UI)!!) {
val jsonEncodedDf = json {
obj(
"nrow" to df.size.nrow,
"ncol" to df.size.ncol,
"columns" to df.columnNames(),
"kotlin_dataframe" to encodeFrame(df.rows().take(limit).toDataFrame())
"kotlin_dataframe" to encodeFrame(df.rows().take(limit).toDataFrame()),
)
}.toJsonString()
notebook.renderAsIFrameAsNeeded(html, jsonEncodedDf)
notebook.renderAsIFrameAsNeeded(html, staticHtml, jsonEncodedDf)
} else {
notebook.renderHtmlAsIFrameIfNeeded(html)
}
}

internal fun Notebook.renderAsIFrameAsNeeded(data: HtmlData, jsonEncodedDf: String): MimeTypedResult {
internal fun Notebook.renderAsIFrameAsNeeded(data: HtmlData, staticData: HtmlData, jsonEncodedDf: String): MimeTypedResult {
val textHtml = if (jupyterClientType == JupyterClientType.KOTLIN_NOTEBOOK) {
data.generateIframePlaneText(currentColorScheme)
data.generateIframePlaneText(currentColorScheme) +
staticData.toString(currentColorScheme)
} else {
data.toString(currentColorScheme)
(data + staticData).toString(currentColorScheme)
}

return mimeResult(
Expand Down
Loading