diff --git a/CHANGELOG.md b/CHANGELOG.md index c72ae37b..b8b3e309 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,38 +1,75 @@ # Changelog -All notable changes to this project will be documented in this file. +All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## Unreleased ### Added + +### Changed + +### Deprecated + +### Removed + +### Fixed + +### Security + +## 0.7.1.1 - 2024-12-11 + +### Added + - Compose demo ### Changed + - Migrated to DF 0.8 -### Deprecated +### Removed + +- Grid view + +### Fixed + +- Wrong script reference for static file generation +- Fixed rendering for Jupyter lab + +## 0.7.1 - 2024-02-22 + +### Added + +- Compose demo + +### Changed + +- Migrated to DF 0.8 ### Removed + - Grid view ### Fixed -### Security +- Fixed rendering for Jupyter lab ## 0.6.0 - 2023-07-29 ### Added + - Add experimental support for events on JS ### Changed + - DataForge 0.6.2 - Use a self-made Plotly-js bundle instead of one from CDN ## 0.5.3 - 2023-04-01 ### Added + - API for background images (https://github.com/SciProgCentre/plotly.kt/issues/49) - API for multiple Y axis (https://github.com/SciProgCentre/plotly.kt/issues/92) - Native support @@ -40,6 +77,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - DataSourceHost/DataSourcePost to configure custom networks ### Changed + - Kotlin 1.8.20 - Moved renderers to JVM to avoid confusion with JS direct element rendering. - DataForge 0.6 @@ -49,12 +87,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Moved to Ktor 2.0 ### Deprecated + - Page layout. Use VisionForge for that. ### Removed + - Moved CORS to `Plotly.serve` ### Fixed + - Added a protective copy on reading doubleArray from TraceValues - #85 - Rendering in JS that used backend HTML generation @@ -62,70 +103,84 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## 0.5.0 ### Changed + - Switch to DataForge 0.5 - ## 0.4.4 ### Added + - Candlestick support - Range builders for axis ### Changed + - build tools 0.10.0 - demo projects moved to examples ### Deprecated + - Direct usage of `range` in axis ### Fixed + - #80 - Plotly coordinate array wrap is moved to the server side ## 0.4.3 ### Fixed + - Proper deserialization of single plot. - A bug in jupyter lab visualization ## 0.4.2 ### Added + - `automargin` property to `Axis` according to https://plotly.com/python/reference/layout/xaxis/#layout-xaxis-automargin ### Fixed + - Remove unnecessary `kotlinx-css` dependency. - Added compatibility mode for legacy notebooks. Use `Plotly.jupyter.notebook()` call to enable legacy mode. ## 0.4.0 ### Added + - Jupyter integration plugin for server - Separate static plot integration module in `plotlykt-jupyter` - Expanded JS demo - Jupyter support goes beta ### Changed + - Package change (again) to `space.kscience` - Build tools `0.9.5` - Kotlin `1.5.0` - HtmlFragment renamed to PlotlyHtmlFragment ### Removed + - Local bootstrap ### Fixed + - Incomplete coverage in JS (#70) ## 0.3.1 ### Added + - Table widget implementation by @ArtificialPB - Mathjax header promoted to stable - Tabbed plots layout (experimental) - Trace value builders for functions and ranges (experimental) ### Changed + - **Breaking API change!** Trace `text` replaced by `TraceValues` - Moved to DataForge 0.3 API - Kotlin 1.4.30 @@ -134,23 +189,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Replaced direct color accessor by a delegate ### Fixed + - https://github.com/mipt-npm/plotly.kt/issues/53 - Add JQuery to Bootstrap headers ## 0.3.0 ### Changed + - Serialization API is encapsulated (not longer exposed) in order to provide compatibility with new serialization. - Migration to Kotlin 1.4 - Minor breaking change in Plot to encapsulate serialization usage - JS supports IR. LEGACY is not supported anymore. ### Fixed + - https://github.com/mipt-npm/plotly.kt/issues/51 ## 0.2.0 ### Added + - Experimental scripting support - Static export via Orca - Experimental Jupyter support @@ -168,6 +227,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - TraceValues extension for krangl columns ### Changed + - Migrated from `scientifik` to `kscience` - Refactored packages to better suit star import style - Removed bootstrap dependency diff --git a/README.md b/README.md index 05cbea51..8ff2c6ae 100644 --- a/README.md +++ b/README.md @@ -44,8 +44,6 @@ See [simpleServer](./examples/src/main/kotlin/simpleServer.kt) and ## Kotlin-JS Plotly is a JavaScript library, yet it is convenient to have a type-safe API when using in with Kotlin-JS. The sample application is available in [js-demo](./examples/js-demo) module. One should node that Plotly.kt for JS is not a zero-cost wrapper like TypeScript definitions, it maintains its own object structure, could generate stand-alone models and some internal optimizations. -**Plotly-kt does not support `LEGACY` JS target. Be sure to use [IR compiler](https://kotlinlang.org/docs/js-ir-compiler.html)** - ## JavaFX browser Plotly.kt could be run in a JavaFX browser. An example project is presented in [fx-demo](./fx-demo). @@ -60,9 +58,9 @@ The examples of the notebooks are shown in [notebooks](./examples/notebooks) dir //@file:DependsOn("space.kscience:plotlykt-server:$version") // Use this one for sever integration. ``` -The module `plotly` allows rendering static plots in Jupyter. Jupyter lab is currently supported. Jupyter notebook (classic) is able to render only `PlotlyPage` objects, so one must convert plots to pages to be able to use notebook (see [demo notebook](./examples/notebooks/plotlykt-demo.ipynb)). +The module `plotly` allows rendering static plots in Jupyter. Jupyter lab is currently supported. Jupyter notebook (classic) is able to render only `PlotlyPage` objects, so one must convert plots to pages to be able to use notebook (see [demo notebook](./notebooks/plotlykt-demo-classic.ipynb)). -The module `plotly-server` adds server capabilities and allows to render dynamic plots in notebooks (see [demo notebook](./examples/notebooks/plotlykt-server-demo.ipynb)). One must note that for dynamic pages, one must pass `renderer` parameter explicitly to plot like it is done in examples. +The module `plotly-server` adds server capabilities and allows to render dynamic plots in notebooks (see [demo notebook](./notebooks/plotlykt-server-demo.ipynb)). One must note that for dynamic pages, one must pass `renderer` parameter explicitly to plot like it is done in examples. **IMPORTANT:** By default, Plotly-kt jupyter integration is configured to work with Jupyter Lab frontend, which renders all cells in the same page. Jupyter classic notebook and DataLore use cell isolation with iframes, so you will see blanks instead of plots. It could be fixed by switching into a notebook mode by running `Plotly.jupyter.notebook()` in a cell after plotly library is loaded. diff --git a/build.gradle.kts b/build.gradle.kts index 6b08110b..2c439c7f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -10,7 +10,7 @@ val plotlyVersion by extra("2.29.0") allprojects { group = "space.kscience" - version = "0.7.0" + version = "0.7.1.1" } apiValidation { diff --git a/examples/compose-demo/build.gradle.kts b/examples/compose-demo/build.gradle.kts index d1d6f55a..5344b79e 100644 --- a/examples/compose-demo/build.gradle.kts +++ b/examples/compose-demo/build.gradle.kts @@ -11,11 +11,11 @@ repositories { maven("https://jogamp.org/deployment/maven") } -kotlin{ +kotlin { jvm() jvmToolchain(17) - sourceSets{ - jvmMain{ + sourceSets { + jvmMain { dependencies { implementation(compose.runtime) implementation(compose.foundation) diff --git a/examples/notebooks/plotlykt-demo.ipynb b/examples/notebooks/plotlykt-demo.ipynb index 0ce976d2..c2c502bf 100644 --- a/examples/notebooks/plotlykt-demo.ipynb +++ b/examples/notebooks/plotlykt-demo.ipynb @@ -14,6 +14,17 @@ "//%use plotly" ] }, + { + "cell_type": "code", + "outputs": [], + "source": [ + "Plotly.jupyter.notebook()" + ], + "metadata": { + "collapsed": false + }, + "execution_count": null + }, { "cell_type": "code", "execution_count": null, diff --git a/examples/notebooks/plotlykt-server-demo.ipynb b/examples/notebooks/plotlykt-server-demo.ipynb index 73ecae7e..190e35a6 100644 --- a/examples/notebooks/plotlykt-server-demo.ipynb +++ b/examples/notebooks/plotlykt-server-demo.ipynb @@ -2,35 +2,30 @@ "cells": [ { "cell_type": "code", - "execution_count": null, - "outputs": [], "source": [ "import space.kscience.plotly.server.PlotlyServerIntegration\n", "import space.kscience.plotly.server.jupyter\n", "\n", - "val integration = PlotlyServerIntegration()\n", - "integration.getDefinitions(notebook).forEach {\n", - " USE(it)\n", - "}" + "USE(PlotlyServerIntegration())" ], "metadata": { "collapsed": false - } + }, + "outputs": [], + "execution_count": null }, { "cell_type": "code", - "execution_count": null, "metadata": {}, - "outputs": [], "source": [ "import kotlin.math.*" - ] + ], + "outputs": [], + "execution_count": null }, { "cell_type": "code", - "execution_count": null, "metadata": {}, - "outputs": [], "source": [ "val x1 = (0..100).map { it.toDouble() / 100.0 }\n", "val y1 = x1.map { sin(2.0 * PI * it) }\n", @@ -67,13 +62,13 @@ " }\n", "}\n", "fragment" - ] + ], + "outputs": [], + "execution_count": null }, { "cell_type": "code", - "execution_count": null, "metadata": {}, - "outputs": [], "source": [ "Plotly.plot {\n", " traces(trace1, trace2)\n", @@ -83,13 +78,13 @@ " yaxis.title = \"y axis name\"\n", " }\n", "}" - ] + ], + "outputs": [], + "execution_count": null }, { "cell_type": "code", - "execution_count": null, "metadata": {}, - "outputs": [], "source": [ "val x = (0..100).map { it.toDouble() / 100.0 }\n", "val y = x.map { sin(2.0 * PI * it) }\n", @@ -107,13 +102,13 @@ "}\n", "\n", "dynamicPlot" - ] + ], + "outputs": [], + "execution_count": null }, { "cell_type": "code", - "execution_count": null, "metadata": {}, - "outputs": [], "source": [ "import kotlinx.coroutines.*\n", "\n", @@ -126,52 +121,54 @@ " trace.y.set(dynamicY)\n", " }\n", "}" - ] + ], + "outputs": [], + "execution_count": null }, { "cell_type": "code", - "execution_count": null, "metadata": {}, - "outputs": [], "source": [ "job.cancel()" - ] + ], + "outputs": [], + "execution_count": null }, { "cell_type": "code", - "execution_count": null, "metadata": {}, - "outputs": [], "source": [ "dynamicPlot.layout.xaxis.title = \"крокозябра\"" - ] + ], + "outputs": [], + "execution_count": null }, { "cell_type": "code", - "execution_count": null, "metadata": {}, - "outputs": [], "source": [ "Plotly.jupyter.port = 8884" - ] + ], + "outputs": [], + "execution_count": null }, { "cell_type": "code", - "execution_count": null, "metadata": {}, - "outputs": [], "source": [ "Plotly.jupyter.port" - ] + ], + "outputs": [], + "execution_count": null }, { "cell_type": "code", - "execution_count": null, - "outputs": [], "source": [], "metadata": { "collapsed": false - } + }, + "outputs": [], + "execution_count": null } ], "metadata": { @@ -208,7 +205,7 @@ "toc_window_display": false }, "ktnbPluginMetadata": { - "isBuildProject": true + "projectDependencies": true } }, "nbformat": 4, diff --git a/plotlykt-core/README.md b/plotlykt-core/README.md index 75ce6442..da4cddad 100644 --- a/plotlykt-core/README.md +++ b/plotlykt-core/README.md @@ -6,19 +6,8 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:plotlykt-core:0.6.0`. +The Maven coordinates of this project are `space.kscience:plotlykt-core:0.7.1`. -**Gradle Groovy:** -```groovy -repositories { - maven { url 'https://repo.kotlin.link' } - mavenCentral() -} - -dependencies { - implementation 'space.kscience:plotlykt-core:0.6.0' -} -``` **Gradle Kotlin DSL:** ```kotlin repositories { @@ -27,6 +16,6 @@ repositories { } dependencies { - implementation("space.kscience:plotlykt-core:0.6.0") + implementation("space.kscience:plotlykt-core:0.7.1") } ``` diff --git a/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/dfExt.kt b/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/dfExt.kt index 8fcd5234..fffde72e 100644 --- a/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/dfExt.kt +++ b/plotlykt-core/src/commonMain/kotlin/space/kscience/plotly/dfExt.kt @@ -12,21 +12,6 @@ import kotlin.time.toDuration //extensions for DataForge -private fun MutableMeta.getIndexedProviders(name: Name): Map { - val parent = get(name.cutLast()) ?: return emptyMap() - return parent.items.keys.filter { - it.body == name.lastOrNull()?.body - }.map { - it.index - }.associate { index -> - if (index == null) { - "" to getOrCreate(name) - } else { - index to getOrCreate(name.withIndex(index)) - } - } -} - /** * List of values delegate */ @@ -201,35 +186,6 @@ internal fun Scheme.duration( } } -///** -// * Infer type of value and set -// */ -//public operator fun MutableMeta.set(name: String, value: Any?) { -// when (value) { -// null -> this[name] = null -// is Meta -> this[name] = value -// is Value -> set(Name.parse(name), value) -// is String -> this[name] = value.asValue() -// is Number -> this[name] = value.asValue() -// is Boolean -> this[name] = value.asValue() -// is Iterable<*> -> { -// if (value.all { it is Meta }) { -// this.setIndexed(Name.parse(name), value.map { it as Meta }) -// } else { -// this[name] = value.map { Value.of(it) }.asValue() -// } -// } -// } -//} - -///** -// * A patch to cover API no longer existing in DataForge -// */ -//@Deprecated("Use specialized meta methods instead") -//public operator fun Scheme.set(name: String, value: Any?) { -// meta[name] = value -//} - /** * Append the observable note to same-name-siblings and observe its changes. */ diff --git a/plotlykt-core/src/jsMain/kotlin/space/kscience/plotly/PlotlyConnect.kt b/plotlykt-core/src/jsMain/kotlin/space/kscience/plotly/PlotlyConnect.kt index 5e526e54..cf2d6832 100644 --- a/plotlykt-core/src/jsMain/kotlin/space/kscience/plotly/PlotlyConnect.kt +++ b/plotlykt-core/src/jsMain/kotlin/space/kscience/plotly/PlotlyConnect.kt @@ -25,7 +25,7 @@ public object PlotlyConnect { console.warn("Plotly not defined. Loading the script from CDN") window.asDynamic().promiseOfPlotly = Promise { resolve, reject -> val plotlyLoaderScript = document.createElement("script") as HTMLScriptElement - plotlyLoaderScript.src = "https://cdn.plot.ly/plotly-2.24.1.min.js" + plotlyLoaderScript.src = "https://cdn.plot.ly/plotly-2.29.0.min.js" plotlyLoaderScript.type = "text/javascript" plotlyLoaderScript.onload = { resolve(PlotlyJs) @@ -163,4 +163,5 @@ public object PlotlyConnect { public fun main() { window.asDynamic().plotlyConnect = PlotlyConnect + window.asDynamic().Plotly = PlotlyJs } \ No newline at end of file diff --git a/plotlykt-core/src/jvmMain/kotlin/space/kscience/plotly/plotlyHeaders.kt b/plotlykt-core/src/jvmMain/kotlin/space/kscience/plotly/plotlyHeaders.kt index 73abd52f..0bedfde8 100644 --- a/plotlykt-core/src/jvmMain/kotlin/space/kscience/plotly/plotlyHeaders.kt +++ b/plotlykt-core/src/jvmMain/kotlin/space/kscience/plotly/plotlyHeaders.kt @@ -8,7 +8,7 @@ import java.nio.file.Path import java.nio.file.StandardOpenOption -internal const val PLOTLY_SCRIPT_PATH = "/js/plotly.min.js" +internal const val PLOTLY_SCRIPT_PATH = "/js/plotly-kt.js" //const val PLOTLY_PROMISE_NAME = "promiseOfPlotly" /** * Check if the asset exists in given local location and put it there if it does not diff --git a/plotlykt-geo/README.md b/plotlykt-geo/README.md index 8d6ff85e..f15f5f2a 100644 --- a/plotlykt-geo/README.md +++ b/plotlykt-geo/README.md @@ -6,19 +6,8 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:plotlykt-geo:0.6.0`. +The Maven coordinates of this project are `space.kscience:plotlykt-geo:0.7.1`. -**Gradle Groovy:** -```groovy -repositories { - maven { url 'https://repo.kotlin.link' } - mavenCentral() -} - -dependencies { - implementation 'space.kscience:plotlykt-geo:0.6.0' -} -``` **Gradle Kotlin DSL:** ```kotlin repositories { @@ -27,6 +16,6 @@ repositories { } dependencies { - implementation("space.kscience:plotlykt-geo:0.6.0") + implementation("space.kscience:plotlykt-geo:0.7.1") } ``` diff --git a/plotlykt-geo/build.gradle.kts b/plotlykt-geo/build.gradle.kts index 788c4c15..341adac0 100644 --- a/plotlykt-geo/build.gradle.kts +++ b/plotlykt-geo/build.gradle.kts @@ -9,7 +9,7 @@ kscience{ native() wasm() dependencies { - api(project(":plotlykt-core")) + api(projects.plotlyktCore) } } diff --git a/plotlykt-jupyter/README.md b/plotlykt-jupyter/README.md index 1d293945..d27b29a7 100644 --- a/plotlykt-jupyter/README.md +++ b/plotlykt-jupyter/README.md @@ -6,19 +6,8 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:plotlykt-jupyter:0.6.0`. +The Maven coordinates of this project are `space.kscience:plotlykt-jupyter:0.7.1`. -**Gradle Groovy:** -```groovy -repositories { - maven { url 'https://repo.kotlin.link' } - mavenCentral() -} - -dependencies { - implementation 'space.kscience:plotlykt-jupyter:0.6.0' -} -``` **Gradle Kotlin DSL:** ```kotlin repositories { @@ -27,6 +16,6 @@ repositories { } dependencies { - implementation("space.kscience:plotlykt-jupyter:0.6.0") + implementation("space.kscience:plotlykt-jupyter:0.7.1") } ``` diff --git a/plotlykt-jupyter/src/jvmMain/kotlin/space/kscience/plotly/PlotlyIntegration.kt b/plotlykt-jupyter/src/jvmMain/kotlin/space/kscience/plotly/PlotlyIntegration.kt index 7c93bc9f..dc0d197b 100644 --- a/plotlykt-jupyter/src/jvmMain/kotlin/space/kscience/plotly/PlotlyIntegration.kt +++ b/plotlykt-jupyter/src/jvmMain/kotlin/space/kscience/plotly/PlotlyIntegration.kt @@ -17,7 +17,7 @@ public object PlotlyJupyterConfiguration { return PlotlyHtmlFragment { div { style = "color: blue;" - +"Plotly notebook integration switched into the legacy mode." + +"Plotly notebook integration switched into the notebook mode." } } } @@ -82,6 +82,7 @@ public class PlotlyIntegration : JupyterIntegration(), PlotlyRenderer { resources { js("plotly-kt") { + url("https://cdn.plot.ly/plotly-2.29.1.min.js") classPath("js/plotly-kt.js") } } diff --git a/plotlykt-script/README.md b/plotlykt-script/README.md index 1a6424da..692a74a4 100644 --- a/plotlykt-script/README.md +++ b/plotlykt-script/README.md @@ -6,19 +6,8 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:plotlykt-script:0.6.0`. +The Maven coordinates of this project are `space.kscience:plotlykt-script:0.7.1`. -**Gradle Groovy:** -```groovy -repositories { - maven { url 'https://repo.kotlin.link' } - mavenCentral() -} - -dependencies { - implementation 'space.kscience:plotlykt-script:0.6.0' -} -``` **Gradle Kotlin DSL:** ```kotlin repositories { @@ -27,6 +16,6 @@ repositories { } dependencies { - implementation("space.kscience:plotlykt-script:0.6.0") + implementation("space.kscience:plotlykt-script:0.7.1") } ``` diff --git a/plotlykt-script/src/jvmTest/kotlin/space/kscience/plotly/script/BuilderTest.kt b/plotlykt-script/src/jvmTest/kotlin/space/kscience/plotly/script/BuilderTest.kt index 5eccfc8b..3271253d 100644 --- a/plotlykt-script/src/jvmTest/kotlin/space/kscience/plotly/script/BuilderTest.kt +++ b/plotlykt-script/src/jvmTest/kotlin/space/kscience/plotly/script/BuilderTest.kt @@ -8,6 +8,6 @@ internal class BuilderTest { fun testBuilderFromString() { val string = javaClass.getResource("/customPage.plotly.kts").readText() val page = Plotly.page(string) - page.render() + println(page.render()) } } \ No newline at end of file diff --git a/plotlykt-server/README.md b/plotlykt-server/README.md index 691ead64..59e5a1ac 100644 --- a/plotlykt-server/README.md +++ b/plotlykt-server/README.md @@ -6,19 +6,8 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:plotlykt-server:0.6.0`. +The Maven coordinates of this project are `space.kscience:plotlykt-server:0.7.1`. -**Gradle Groovy:** -```groovy -repositories { - maven { url 'https://repo.kotlin.link' } - mavenCentral() -} - -dependencies { - implementation 'space.kscience:plotlykt-server:0.6.0' -} -``` **Gradle Kotlin DSL:** ```kotlin repositories { @@ -27,6 +16,6 @@ repositories { } dependencies { - implementation("space.kscience:plotlykt-server:0.6.0") + implementation("space.kscience:plotlykt-server:0.7.1") } ``` diff --git a/plotlykt-server/build.gradle.kts b/plotlykt-server/build.gradle.kts index 57063afd..ec7d9cc9 100644 --- a/plotlykt-server/build.gradle.kts +++ b/plotlykt-server/build.gradle.kts @@ -11,6 +11,7 @@ val ktorVersion = KScienceVersions.ktorVersion kscience{ jvm() + useCoroutines() commonMain{ api(projects.plotlyktCore) api("io.ktor:ktor-server-cio:$ktorVersion") diff --git a/plotlykt-server/src/jvmMain/kotlin/space/kscience/plotly/server/PlotlyServerIntegration.kt b/plotlykt-server/src/jvmMain/kotlin/space/kscience/plotly/server/PlotlyServerIntegration.kt index 9be4229c..2ea82a3a 100644 --- a/plotlykt-server/src/jvmMain/kotlin/space/kscience/plotly/server/PlotlyServerIntegration.kt +++ b/plotlykt-server/src/jvmMain/kotlin/space/kscience/plotly/server/PlotlyServerIntegration.kt @@ -115,8 +115,6 @@ public class PlotlyServerIntegration : JupyterIntegration() { } } - private fun renderPage(page: PlotlyPage): String = page.copy(renderer = renderer).render() - override fun Builder.onLoaded() { resources { @@ -131,7 +129,8 @@ public class PlotlyServerIntegration : JupyterIntegration() { "space.kscience.plotly.*", "space.kscience.plotly.models.*", "space.kscience.dataforge.meta.*", - "kotlinx.html.*" + "kotlinx.html.*", + "kotlinx.coroutines.*" ) import("space.kscience.plotly.server.jupyter")