@@ -7,28 +7,39 @@ import org.jetbrains.kotlinx.jupyter.api.MimeTypedResultEx
77import org.jetbrains.kotlinx.jupyter.api.MimeTypes
88import org.jetbrains.letsPlot.Figure
99import org.jetbrains.letsPlot.awt.plot.PlotSvgExport
10+ import org.jetbrains.letsPlot.core.plot.export.PlotImageExport
1011import org.jetbrains.letsPlot.frontend.NotebookFrontendContext
1112import org.jetbrains.letsPlot.intern.toSpec
12- import org.jetbrains.letsPlot.toolkit.jupyter.json.extendedByJson
1313import org.jetbrains.letsPlot.toolkit.json.serializeJsonMap
14+ import org.jetbrains.letsPlot.toolkit.jupyter.json.extendedByJson
1415import java.util.*
1516
1617internal class NotebookRenderingContext (
1718 private val config : JupyterConfig ,
1819 private val frontendContext : NotebookFrontendContext ,
19- private val webOnly : Boolean
20+ private val outputOptions : OutputOptions
2021) {
22+
23+ data class OutputOptions (
24+ val addWebOutput : Boolean ,
25+ val addKTNBOutput : Boolean ,
26+ val addStaticSvg : Boolean ,
27+ val addStaticPng : Boolean ,
28+ )
29+
2130 /* *
2231 * Creates Mime JSON with two output options - HTML and application/plot.
2332 * The HTML output is used in Jupyter Notebooks and Datalore (the other one is ignored).
2433 * The application/plot is used in Kotlin Notebook when native rendering via Swing is enabled.
2534 */
2635 private fun figureToMimeJson (figure : Figure ): JsonObject {
2736 val spec = figure.toSpec()
28- val html = frontendContext.getDisplayHtml(figure.toSpec())
2937 return buildJsonObject {
30- put(MimeTypes .HTML , JsonPrimitive (html))
31- if (! webOnly) {
38+ if (outputOptions.addWebOutput) {
39+ val plotHtml = frontendContext.getDisplayHtml(spec)
40+ put(MimeTypes .HTML , JsonPrimitive (plotHtml))
41+ }
42+ if (outputOptions.addKTNBOutput) {
3243 put(" application/plot+json" , buildJsonObject {
3344 put(" output_type" , JsonPrimitive (" lets_plot_spec" ))
3445 put(" output" , serializeJsonMap(spec))
@@ -66,19 +77,38 @@ internal class NotebookRenderingContext(
6677 val svgSplit = split(' \n ' )
6778 (listOf (updateSvg(svgSplit.first(), id)) + svgSplit.drop(1 )).joinToString(" \n " )
6879 }
69- val extraHTML = """
80+ val htmlWithSvg = """
7081 $svgWithID
7182 <script>document.getElementById("$id ").style.display = "none";</script>
7283 """ .trimIndent()
7384
74- return mapOf (MimeTypes .HTML to JsonPrimitive (extraHTML))
85+ return mapOf (MimeTypes .HTML to JsonPrimitive (htmlWithSvg))
86+ }
87+
88+ private fun figureToHiddenPng (figure : Figure ): Map <String , JsonPrimitive > {
89+ val base64 = Base64 .getEncoder().encodeToString(
90+ PlotImageExport .buildImageFromRawSpecs(
91+ figure.toSpec(), PlotImageExport .Format .PNG
92+ ).bytes
93+ )
94+ val id = UUID .randomUUID().toString()
95+ val htmlWithPng = """
96+ <img id="$id " src="data:image/png;base64,$base64 " alt="image">
97+ <script>document.getElementById("$id ").style.display = "none";</script>
98+ """ .trimIndent()
99+
100+ return mapOf (MimeTypes .HTML to JsonPrimitive (htmlWithPng))
75101 }
76102
77103 fun figureToMimeResult (figure : Figure ): MimeTypedResultEx {
78- val basicResult = figureToMimeJson(figure)
79- val extraSvg = figureToHiddenSvg(figure)
104+ val mimeJson = figureToMimeJson(figure)
105+ .let {
106+ if (outputOptions.addStaticSvg) it.extendedByJson(figureToHiddenSvg(figure)) else it
107+ }.let {
108+ if (outputOptions.addStaticPng) it.extendedByJson(figureToHiddenPng(figure)) else it
109+ }
80110 return MimeTypedResultEx (
81- basicResult extendedByJson extraSvg ,
111+ mimeJson ,
82112 id = null ,
83113 metadataModifiers = emptyList()
84114 )
0 commit comments