diff --git a/dataforge-output/dataforge-output-html/build.gradle.kts b/dataforge-output/dataforge-output-html/build.gradle.kts new file mode 100644 index 00000000..3b5e24cb --- /dev/null +++ b/dataforge-output/dataforge-output-html/build.gradle.kts @@ -0,0 +1,28 @@ +plugins { + kotlin("multiplatform") +} + +val htmlVersion by rootProject.extra("0.6.12") + +kotlin { + jvm() + js() + sourceSets { + val commonMain by getting { + dependencies { + api(project(":dataforge-output")) + api("org.jetbrains.kotlinx:kotlinx-html-common:$htmlVersion") + } + } + val jsMain by getting { + dependencies { + api("org.jetbrains.kotlinx:kotlinx-html-js:$htmlVersion") + } + } + val jvmMain by getting{ + dependencies { + api("org.jetbrains.kotlinx:kotlinx-html-jvm:$htmlVersion") + } + } + } +} \ No newline at end of file diff --git a/dataforge-output/dataforge-output-html/src/jvmMain/kotlin/hep/dataforge/output/html/HtmlOutput.kt b/dataforge-output/dataforge-output-html/src/jvmMain/kotlin/hep/dataforge/output/html/HtmlOutput.kt new file mode 100644 index 00000000..4eb7ccff --- /dev/null +++ b/dataforge-output/dataforge-output-html/src/jvmMain/kotlin/hep/dataforge/output/html/HtmlOutput.kt @@ -0,0 +1,78 @@ +package hep.dataforge.output.html + +import hep.dataforge.context.Context +import hep.dataforge.meta.Meta +import hep.dataforge.output.Output +import hep.dataforge.output.TextRenderer +import hep.dataforge.output.TextRenderer.Companion.TEXT_RENDERER_TYPE +import hep.dataforge.output.html.HtmlBuilder.Companion.HTML_CONVERTER_TYPE +import hep.dataforge.provider.Type +import hep.dataforge.provider.provideAll +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.html.TagConsumer +import kotlinx.html.p +import kotlin.reflect.KClass + + +class HtmlOutput(override val context: Context, private val consumer: TagConsumer<*>) : Output { + private val cache = HashMap, HtmlBuilder<*>>() + + /** + * Find the first [TextRenderer] matching the given object type. + */ + override fun render(obj: T, meta: Meta) { + + val builder: HtmlBuilder<*> = if (obj is CharSequence) { + DefaultHtmlBuilder + } else { + val value = cache[obj::class] + if (value == null) { + val answer = context.provideAll(HTML_CONVERTER_TYPE).filterIsInstance>() + .filter { it.type.isInstance(obj) }.firstOrNull() + if (answer != null) { + cache[obj::class] = answer + answer + } else { + DefaultHtmlBuilder + } + } else { + value + } + } + context.launch(Dispatchers.Output) { + (builder as HtmlBuilder).run { consumer.render(obj) } + } + } +} + +/** + * A text or binary renderer based on [kotlinx.io.core.Output] + */ +@Type(HTML_CONVERTER_TYPE) +interface HtmlBuilder { + /** + * The priority of this renderer compared to other renderers + */ + val priority: Int + + /** + * The type of the content served by this renderer + */ + val type: KClass + + suspend fun TagConsumer<*>.render(obj: T) + + companion object { + const val HTML_CONVERTER_TYPE = "dataforge.htmlBuilder" + } +} + +object DefaultHtmlBuilder : HtmlBuilder { + override val priority: Int = Int.MAX_VALUE + override val type: KClass = Any::class + + override suspend fun TagConsumer<*>.render(obj: Any) { + p { +obj.toString() } + } +} \ No newline at end of file diff --git a/dataforge-output/src/commonMain/kotlin/hep/dataforge/io/Output.kt b/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/Output.kt similarity index 95% rename from dataforge-output/src/commonMain/kotlin/hep/dataforge/io/Output.kt rename to dataforge-output/src/commonMain/kotlin/hep/dataforge/output/Output.kt index e9d1800c..091cb999 100644 --- a/dataforge-output/src/commonMain/kotlin/hep/dataforge/io/Output.kt +++ b/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/Output.kt @@ -1,4 +1,4 @@ -package hep.dataforge.io +package hep.dataforge.output import hep.dataforge.context.ContextAware import hep.dataforge.meta.EmptyMeta diff --git a/dataforge-output/src/commonMain/kotlin/hep/dataforge/io/OutputManager.kt b/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/OutputManager.kt similarity index 96% rename from dataforge-output/src/commonMain/kotlin/hep/dataforge/io/OutputManager.kt rename to dataforge-output/src/commonMain/kotlin/hep/dataforge/output/OutputManager.kt index f3ed4b53..2a133f5d 100644 --- a/dataforge-output/src/commonMain/kotlin/hep/dataforge/io/OutputManager.kt +++ b/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/OutputManager.kt @@ -1,4 +1,4 @@ -package hep.dataforge.io +package hep.dataforge.output import hep.dataforge.context.AbstractPlugin import hep.dataforge.context.Context diff --git a/dataforge-output/src/commonMain/kotlin/hep/dataforge/io/TextOutput.kt b/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/TextOutput.kt similarity index 95% rename from dataforge-output/src/commonMain/kotlin/hep/dataforge/io/TextOutput.kt rename to dataforge-output/src/commonMain/kotlin/hep/dataforge/output/TextOutput.kt index 1e8d976a..673e8e07 100644 --- a/dataforge-output/src/commonMain/kotlin/hep/dataforge/io/TextOutput.kt +++ b/dataforge-output/src/commonMain/kotlin/hep/dataforge/output/TextOutput.kt @@ -1,7 +1,7 @@ -package hep.dataforge.io +package hep.dataforge.output import hep.dataforge.context.Context -import hep.dataforge.io.TextRenderer.Companion.TEXT_RENDERER_TYPE +import hep.dataforge.output.TextRenderer.Companion.TEXT_RENDERER_TYPE import hep.dataforge.meta.Meta import hep.dataforge.provider.Type import hep.dataforge.provider.provideAll diff --git a/dataforge-output/src/jsMain/kotlin/hep/dataforge/io/ConsoleOutput.kt b/dataforge-output/src/jsMain/kotlin/hep/dataforge/output/ConsoleOutput.kt similarity index 92% rename from dataforge-output/src/jsMain/kotlin/hep/dataforge/io/ConsoleOutput.kt rename to dataforge-output/src/jsMain/kotlin/hep/dataforge/output/ConsoleOutput.kt index ccd9ad5a..b927a386 100644 --- a/dataforge-output/src/jsMain/kotlin/hep/dataforge/io/ConsoleOutput.kt +++ b/dataforge-output/src/jsMain/kotlin/hep/dataforge/output/ConsoleOutput.kt @@ -1,4 +1,4 @@ -package hep.dataforge.io +package hep.dataforge.output import hep.dataforge.context.Context import hep.dataforge.context.Global diff --git a/dataforge-output/src/jvmMain/kotlin/hep/dataforge/io/ConsoleOutput.kt b/dataforge-output/src/jvmMain/kotlin/hep/dataforge/output/ConsoleOutput.kt similarity index 78% rename from dataforge-output/src/jvmMain/kotlin/hep/dataforge/io/ConsoleOutput.kt rename to dataforge-output/src/jvmMain/kotlin/hep/dataforge/output/ConsoleOutput.kt index ecb989a1..57ae4294 100644 --- a/dataforge-output/src/jvmMain/kotlin/hep/dataforge/io/ConsoleOutput.kt +++ b/dataforge-output/src/jvmMain/kotlin/hep/dataforge/output/ConsoleOutput.kt @@ -1,4 +1,4 @@ -package hep.dataforge.io +package hep.dataforge.output import hep.dataforge.context.Global import kotlinx.coroutines.Dispatchers diff --git a/settings.gradle.kts b/settings.gradle.kts index 49dbc374..a2705f26 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -25,6 +25,7 @@ include( ":dataforge-context", ":dataforge-data", ":dataforge-output", + ":dataforge-output:dataforge-output-html", ":dataforge-workspace", ":dataforge-scripting" ) \ No newline at end of file