Implemented binary propagation
This commit is contained in:
parent
941da6fab7
commit
e6bee125d3
@ -12,7 +12,7 @@ allprojects {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val dataforgeVersion by extra("0.6.1-dev-4")
|
val dataforgeVersion by extra("0.6.1-dev-6")
|
||||||
|
|
||||||
ksciencePublish {
|
ksciencePublish {
|
||||||
github("SciProgCentre", "snark")
|
github("SciProgCentre", "snark")
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
kotlin.code.style=official
|
kotlin.code.style=official
|
||||||
|
|
||||||
toolsVersion=0.14.2-kotlin-1.8.10
|
toolsVersion=0.14.5-kotlin-1.8.20-RC
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,5 +1,5 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
rootProject.name = "snark"
|
rootProject.name = "snark"
|
||||||
|
|
||||||
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
|
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
|
||||||
enableFeaturePreview("VERSION_CATALOGS")
|
//enableFeaturePreview("VERSION_CATALOGS")
|
||||||
|
|
||||||
pluginManagement {
|
pluginManagement {
|
||||||
|
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
package space.kscience.snark
|
||||||
|
|
||||||
|
@DslMarker
|
||||||
|
public annotation class SnarkBuilder
|
@ -3,4 +3,5 @@ package space.kscience.snark
|
|||||||
/**
|
/**
|
||||||
* A marker interface for Snark Page and Site builders
|
* A marker interface for Snark Page and Site builders
|
||||||
*/
|
*/
|
||||||
|
@SnarkBuilder
|
||||||
public interface SnarkContext
|
public interface SnarkContext
|
@ -1,40 +0,0 @@
|
|||||||
package space.kscience.snark
|
|
||||||
|
|
||||||
import space.kscience.dataforge.context.Context
|
|
||||||
import space.kscience.dataforge.context.Global
|
|
||||||
import space.kscience.dataforge.context.Plugin
|
|
||||||
import space.kscience.dataforge.data.DataSourceBuilder
|
|
||||||
import space.kscience.dataforge.data.DataTree
|
|
||||||
import space.kscience.dataforge.data.DataTreeBuilder
|
|
||||||
import space.kscience.dataforge.meta.MutableMeta
|
|
||||||
import kotlin.reflect.typeOf
|
|
||||||
|
|
||||||
public class SnarkEnvironment(public val parentContext: Context) {
|
|
||||||
private var _data: DataTree<*>? = null
|
|
||||||
public val data: DataTree<Any> get() = _data ?: DataTree.empty()
|
|
||||||
|
|
||||||
public fun data(builder: DataSourceBuilder<Any>.() -> Unit) {
|
|
||||||
_data = DataTreeBuilder<Any>(typeOf<Any>(), parentContext.coroutineContext).apply(builder)
|
|
||||||
//TODO use node meta
|
|
||||||
}
|
|
||||||
|
|
||||||
public val meta: MutableMeta = MutableMeta()
|
|
||||||
|
|
||||||
public fun meta(block: MutableMeta.() -> Unit) {
|
|
||||||
meta.apply(block)
|
|
||||||
}
|
|
||||||
|
|
||||||
private val _plugins = HashSet<Plugin>()
|
|
||||||
public val plugins: Set<Plugin> get() = _plugins
|
|
||||||
|
|
||||||
public fun registerPlugin(plugin: Plugin) {
|
|
||||||
_plugins.add(plugin)
|
|
||||||
}
|
|
||||||
|
|
||||||
public companion object{
|
|
||||||
public val default: SnarkEnvironment = SnarkEnvironment(Global)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun SnarkEnvironment(parentContext: Context = Global, block: SnarkEnvironment.() -> Unit): SnarkEnvironment =
|
|
||||||
SnarkEnvironment(parentContext).apply(block)
|
|
@ -0,0 +1,15 @@
|
|||||||
|
package space.kscience.snark.html
|
||||||
|
|
||||||
|
import io.ktor.util.asStream
|
||||||
|
import io.ktor.utils.io.core.Input
|
||||||
|
import space.kscience.dataforge.io.IOReader
|
||||||
|
import java.awt.image.BufferedImage
|
||||||
|
import javax.imageio.ImageIO
|
||||||
|
import kotlin.reflect.KType
|
||||||
|
import kotlin.reflect.typeOf
|
||||||
|
|
||||||
|
internal object ImageIOReader : IOReader<BufferedImage> {
|
||||||
|
override val type: KType get() = typeOf<BufferedImage>()
|
||||||
|
|
||||||
|
override fun readObject(input: Input): BufferedImage = ImageIO.read(input.asStream())
|
||||||
|
}
|
@ -3,6 +3,7 @@ package space.kscience.snark.html
|
|||||||
import space.kscience.dataforge.data.getItem
|
import space.kscience.dataforge.data.getItem
|
||||||
import space.kscience.dataforge.meta.*
|
import space.kscience.dataforge.meta.*
|
||||||
import space.kscience.dataforge.names.*
|
import space.kscience.dataforge.names.*
|
||||||
|
import space.kscience.snark.SnarkBuilder
|
||||||
import space.kscience.snark.html.Language.Companion.SITE_LANGUAGES_KEY
|
import space.kscience.snark.html.Language.Companion.SITE_LANGUAGES_KEY
|
||||||
import space.kscience.snark.html.Language.Companion.SITE_LANGUAGE_KEY
|
import space.kscience.snark.html.Language.Companion.SITE_LANGUAGE_KEY
|
||||||
|
|
||||||
@ -46,7 +47,7 @@ public class Language : Scheme() {
|
|||||||
context(SiteBuilder)
|
context(SiteBuilder)
|
||||||
public fun forName(name: Name): Meta = Meta {
|
public fun forName(name: Name): Meta = Meta {
|
||||||
val currentLanguagePrefix = languages[language]?.get(Language::prefix.name)?.string ?: language
|
val currentLanguagePrefix = languages[language]?.get(Language::prefix.name)?.string ?: language
|
||||||
val fullName = (route.removeHeadOrNull(currentLanguagePrefix.asName()) ?: route) + name
|
val fullName = (route.removeFirstOrNull(currentLanguagePrefix.asName()) ?: route) + name
|
||||||
languages.forEach { (key, meta) ->
|
languages.forEach { (key, meta) ->
|
||||||
val languagePrefix: String = meta[Language::prefix.name].string ?: key
|
val languagePrefix: String = meta[Language::prefix.name].string ?: key
|
||||||
val nameWithLanguage: Name = if (languagePrefix.isBlank()) {
|
val nameWithLanguage: Name = if (languagePrefix.isBlank()) {
|
||||||
@ -90,6 +91,7 @@ public fun SiteBuilder.withLanguages(languageMap: Map<String, Meta>, block: Site
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SnarkBuilder
|
||||||
public fun SiteBuilder.withLanguages(
|
public fun SiteBuilder.withLanguages(
|
||||||
vararg language: Pair<String, String>,
|
vararg language: Pair<String, String>,
|
||||||
block: SiteBuilder.(language: String) -> Unit,
|
block: SiteBuilder.(language: String) -> Unit,
|
||||||
|
@ -5,6 +5,7 @@ import space.kscience.dataforge.context.Context
|
|||||||
import space.kscience.dataforge.context.ContextAware
|
import space.kscience.dataforge.context.ContextAware
|
||||||
import space.kscience.dataforge.data.DataTree
|
import space.kscience.dataforge.data.DataTree
|
||||||
import space.kscience.dataforge.data.DataTreeItem
|
import space.kscience.dataforge.data.DataTreeItem
|
||||||
|
import space.kscience.dataforge.data.branch
|
||||||
import space.kscience.dataforge.data.getItem
|
import space.kscience.dataforge.data.getItem
|
||||||
import space.kscience.dataforge.meta.Meta
|
import space.kscience.dataforge.meta.Meta
|
||||||
import space.kscience.dataforge.meta.get
|
import space.kscience.dataforge.meta.get
|
||||||
@ -14,6 +15,7 @@ import space.kscience.dataforge.names.Name
|
|||||||
import space.kscience.dataforge.names.NameToken
|
import space.kscience.dataforge.names.NameToken
|
||||||
import space.kscience.dataforge.names.asName
|
import space.kscience.dataforge.names.asName
|
||||||
import space.kscience.dataforge.names.parseAsName
|
import space.kscience.dataforge.names.parseAsName
|
||||||
|
import space.kscience.snark.SnarkBuilder
|
||||||
import space.kscience.snark.SnarkContext
|
import space.kscience.snark.SnarkContext
|
||||||
import space.kscience.snark.html.SiteLayout.Companion.LAYOUT_KEY
|
import space.kscience.snark.html.SiteLayout.Companion.LAYOUT_KEY
|
||||||
|
|
||||||
@ -21,6 +23,7 @@ import space.kscience.snark.html.SiteLayout.Companion.LAYOUT_KEY
|
|||||||
/**
|
/**
|
||||||
* An abstraction, which is used to render sites to the different rendering engines
|
* An abstraction, which is used to render sites to the different rendering engines
|
||||||
*/
|
*/
|
||||||
|
@SnarkBuilder
|
||||||
public interface SiteBuilder : ContextAware, SnarkContext {
|
public interface SiteBuilder : ContextAware, SnarkContext {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -48,29 +51,16 @@ public interface SiteBuilder : ContextAware, SnarkContext {
|
|||||||
/**
|
/**
|
||||||
* Serve a static data as a file from [data] with given [dataName] at given [routeName].
|
* Serve a static data as a file from [data] with given [dataName] at given [routeName].
|
||||||
*/
|
*/
|
||||||
public fun file(dataName: Name, routeName: Name = dataName)
|
public fun static(dataName: Name, routeName: Name = dataName)
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Add a static file or directory to this site/route at [webPath]
|
|
||||||
// */
|
|
||||||
// public fun file(file: Path, webPath: String = file.fileName.toString())
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Add a static file (single) from resources
|
|
||||||
// */
|
|
||||||
// public fun resourceFile(resourcesPath: String, webPath: String = resourcesPath)
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Add a resource directory to route
|
|
||||||
// */
|
|
||||||
// public fun resourceDirectory(resourcesPath: String)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a single page at given [route]. If route is empty, create an index page at current route.
|
* Create a single page at given [route]. If route is empty, create an index page at current route.
|
||||||
*
|
*
|
||||||
* @param pageMeta additional page meta. [WebPage] will use both it and [siteMeta]
|
* @param pageMeta additional page meta. [WebPage] will use both it and [siteMeta]
|
||||||
*/
|
*/
|
||||||
public fun page(route: Name = Name.EMPTY, pageMeta: Meta = Meta.EMPTY, content: context(WebPage, HTML) () -> Unit)
|
@SnarkBuilder
|
||||||
|
public fun page(route: Name = Name.EMPTY, pageMeta: Meta = Meta.EMPTY, content: context(HTML, WebPage) () -> Unit)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a route with optional data tree override. For example one could use a subtree of the initial tree.
|
* Create a route with optional data tree override. For example one could use a subtree of the initial tree.
|
||||||
@ -100,9 +90,10 @@ public interface SiteBuilder : ContextAware, SnarkContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
context(SiteBuilder)
|
context(SiteBuilder)
|
||||||
public val siteBuilder: SiteBuilder
|
public val site: SiteBuilder
|
||||||
get() = this@SiteBuilder
|
get() = this@SiteBuilder
|
||||||
|
|
||||||
|
@SnarkBuilder
|
||||||
public inline fun SiteBuilder.route(
|
public inline fun SiteBuilder.route(
|
||||||
route: Name,
|
route: Name,
|
||||||
dataOverride: DataTree<*>? = null,
|
dataOverride: DataTree<*>? = null,
|
||||||
@ -112,6 +103,7 @@ public inline fun SiteBuilder.route(
|
|||||||
route(route, dataOverride, routeMeta).apply(block)
|
route(route, dataOverride, routeMeta).apply(block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SnarkBuilder
|
||||||
public inline fun SiteBuilder.route(
|
public inline fun SiteBuilder.route(
|
||||||
route: String,
|
route: String,
|
||||||
dataOverride: DataTree<*>? = null,
|
dataOverride: DataTree<*>? = null,
|
||||||
@ -121,6 +113,7 @@ public inline fun SiteBuilder.route(
|
|||||||
route(route.parseAsName(), dataOverride, routeMeta).apply(block)
|
route(route.parseAsName(), dataOverride, routeMeta).apply(block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SnarkBuilder
|
||||||
public inline fun SiteBuilder.site(
|
public inline fun SiteBuilder.site(
|
||||||
route: Name,
|
route: Name,
|
||||||
dataOverride: DataTree<*>? = null,
|
dataOverride: DataTree<*>? = null,
|
||||||
@ -130,6 +123,7 @@ public inline fun SiteBuilder.site(
|
|||||||
site(route, dataOverride, routeMeta).apply(block)
|
site(route, dataOverride, routeMeta).apply(block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SnarkBuilder
|
||||||
public inline fun SiteBuilder.site(
|
public inline fun SiteBuilder.site(
|
||||||
route: String,
|
route: String,
|
||||||
dataOverride: DataTree<*>? = null,
|
dataOverride: DataTree<*>? = null,
|
||||||
@ -139,6 +133,26 @@ public inline fun SiteBuilder.site(
|
|||||||
site(route.parseAsName(), dataOverride, routeMeta).apply(block)
|
site(route.parseAsName(), dataOverride, routeMeta).apply(block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public inline fun SiteBuilder.withData(
|
||||||
|
data: DataTree<*>,
|
||||||
|
block: SiteBuilder.() -> Unit
|
||||||
|
){
|
||||||
|
route(Name.EMPTY, data).apply(block)
|
||||||
|
}
|
||||||
|
|
||||||
|
public inline fun SiteBuilder.withDataBranch(
|
||||||
|
name: Name,
|
||||||
|
block: SiteBuilder.() -> Unit
|
||||||
|
){
|
||||||
|
route(Name.EMPTY, data.branch(name)).apply(block)
|
||||||
|
}
|
||||||
|
|
||||||
|
public inline fun SiteBuilder.withDataBranch(
|
||||||
|
name: String,
|
||||||
|
block: SiteBuilder.() -> Unit
|
||||||
|
){
|
||||||
|
route(Name.EMPTY, data.branch(name)).apply(block)
|
||||||
|
}
|
||||||
|
|
||||||
///**
|
///**
|
||||||
// * Create a stand-alone site at a given node
|
// * Create a stand-alone site at a given node
|
||||||
@ -154,14 +168,19 @@ public inline fun SiteBuilder.site(
|
|||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
public fun SiteBuilder.static(dataName: String): Unit = static(dataName.parseAsName())
|
||||||
|
|
||||||
|
public fun SiteBuilder.static(dataName: String, routeName: String): Unit = static(
|
||||||
|
dataName.parseAsName(),
|
||||||
|
routeName.parseAsName()
|
||||||
|
)
|
||||||
|
|
||||||
internal fun SiteBuilder.assetsFrom(rootMeta: Meta) {
|
internal fun SiteBuilder.assetsFrom(rootMeta: Meta) {
|
||||||
rootMeta.getIndexed("file".asName()).forEach { (_, meta) ->
|
rootMeta.getIndexed("file".asName()).forEach { (_, meta) ->
|
||||||
val webName: String? by meta.string()
|
val webName: String? by meta.string()
|
||||||
val name by meta.string { error("File path is not provided") }
|
val name by meta.string { error("File path is not provided") }
|
||||||
val fileName = name.parseAsName()
|
val fileName = name.parseAsName()
|
||||||
file(fileName, webName?.parseAsName() ?: fileName)
|
static(fileName, webName?.parseAsName() ?: fileName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ package space.kscience.snark.html
|
|||||||
import io.ktor.utils.io.core.readBytes
|
import io.ktor.utils.io.core.readBytes
|
||||||
import space.kscience.dataforge.context.*
|
import space.kscience.dataforge.context.*
|
||||||
import space.kscience.dataforge.data.DataTree
|
import space.kscience.dataforge.data.DataTree
|
||||||
|
import space.kscience.dataforge.io.IOFormat
|
||||||
import space.kscience.dataforge.io.IOPlugin
|
import space.kscience.dataforge.io.IOPlugin
|
||||||
import space.kscience.dataforge.io.IOReader
|
import space.kscience.dataforge.io.IOReader
|
||||||
import space.kscience.dataforge.io.JsonMetaFormat
|
import space.kscience.dataforge.io.JsonMetaFormat
|
||||||
@ -17,7 +18,6 @@ import space.kscience.dataforge.names.asName
|
|||||||
import space.kscience.dataforge.names.parseAsName
|
import space.kscience.dataforge.names.parseAsName
|
||||||
import space.kscience.dataforge.workspace.FileData
|
import space.kscience.dataforge.workspace.FileData
|
||||||
import space.kscience.dataforge.workspace.readDataDirectory
|
import space.kscience.dataforge.workspace.readDataDirectory
|
||||||
import space.kscience.snark.SnarkEnvironment
|
|
||||||
import space.kscience.snark.SnarkParser
|
import space.kscience.snark.SnarkParser
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import kotlin.io.path.extension
|
import kotlin.io.path.extension
|
||||||
@ -66,16 +66,19 @@ public class SnarkHtmlPlugin : AbstractPlugin() {
|
|||||||
"png".asName() to SnarkParser(ImageIOReader, "png"),
|
"png".asName() to SnarkParser(ImageIOReader, "png"),
|
||||||
"jpg".asName() to SnarkParser(ImageIOReader, "jpg", "jpeg"),
|
"jpg".asName() to SnarkParser(ImageIOReader, "jpg", "jpeg"),
|
||||||
"gif".asName() to SnarkParser(ImageIOReader, "gif"),
|
"gif".asName() to SnarkParser(ImageIOReader, "gif"),
|
||||||
|
"svg".asName() to SnarkParser(IOReader.binary, "svg"),
|
||||||
|
"raw".asName() to SnarkParser(IOReader.binary, "css", "js", "scss", "woff", "woff2", "ttf", "eot")
|
||||||
)
|
)
|
||||||
|
|
||||||
TextProcessor.TYPE -> mapOf(
|
TextProcessor.TYPE -> mapOf(
|
||||||
"basic".asName() to BasicTextProcessor
|
"basic".asName() to BasicTextProcessor
|
||||||
)
|
)
|
||||||
|
|
||||||
else -> super.content(target)
|
else -> super.content(target)
|
||||||
}
|
}
|
||||||
|
|
||||||
public companion object : PluginFactory<SnarkHtmlPlugin> {
|
public companion object : PluginFactory<SnarkHtmlPlugin> {
|
||||||
override val tag: PluginTag = PluginTag("snark")
|
override val tag: PluginTag = PluginTag("snark")
|
||||||
override val type: KClass<out SnarkHtmlPlugin> = SnarkHtmlPlugin::class
|
|
||||||
|
|
||||||
override fun build(context: Context, meta: Meta): SnarkHtmlPlugin = SnarkHtmlPlugin()
|
override fun build(context: Context, meta: Meta): SnarkHtmlPlugin = SnarkHtmlPlugin()
|
||||||
|
|
||||||
@ -87,30 +90,28 @@ public class SnarkHtmlPlugin : AbstractPlugin() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Load necessary dependencies and return a [SnarkHtmlPlugin] in a finalized context
|
|
||||||
*/
|
|
||||||
public fun SnarkEnvironment.buildHtmlPlugin(): SnarkHtmlPlugin {
|
|
||||||
val context = parentContext.buildContext("snark".asName()) {
|
|
||||||
plugin(SnarkHtmlPlugin)
|
|
||||||
plugins.forEach {
|
|
||||||
plugin(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return context.request(SnarkHtmlPlugin)
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(DFExperimental::class)
|
@OptIn(DFExperimental::class)
|
||||||
public fun SnarkHtmlPlugin.readDirectory(path: Path): DataTree<Any> = io.readDataDirectory(path) { dataPath, meta ->
|
public fun SnarkHtmlPlugin.readDirectory(path: Path): DataTree<Any> = io.readDataDirectory(path, setOf("md","html")) { dataPath, meta ->
|
||||||
val fileExtension = meta[FileData.FILE_EXTENSION_KEY].string ?: dataPath.extension
|
val fileExtension = meta[FileData.FILE_EXTENSION_KEY].string ?: dataPath.extension
|
||||||
val parser: SnarkParser<Any> = parsers.values.filter { parser ->
|
val parser: SnarkParser<Any> = parsers.values.filter { parser ->
|
||||||
fileExtension in parser.fileExtensions
|
fileExtension in parser.fileExtensions
|
||||||
}.maxByOrNull {
|
}.maxByOrNull {
|
||||||
it.priority
|
it.priority
|
||||||
} ?: run {
|
} ?: run {
|
||||||
logger.warn { "The parser is not found for file $dataPath with meta $meta" }
|
logger.debug { "The parser is not found for file $dataPath with meta $meta" }
|
||||||
SnarkHtmlPlugin.byteArraySnarkParser
|
SnarkHtmlPlugin.byteArraySnarkParser
|
||||||
}
|
}
|
||||||
|
|
||||||
parser.asReader(context, meta)
|
parser.asReader(context, meta)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public fun SnarkHtmlPlugin.readResourceDirectory(
|
||||||
|
resource: String = "",
|
||||||
|
classLoader: ClassLoader = SnarkHtmlPlugin::class.java.classLoader,
|
||||||
|
): DataTree<Any> = readDirectory(
|
||||||
|
Path.of(
|
||||||
|
classLoader.getResource(resource)?.toURI() ?: error(
|
||||||
|
"Resource with name $resource is not resolved"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
@ -1,19 +1,14 @@
|
|||||||
package space.kscience.snark.html
|
package space.kscience.snark.html
|
||||||
|
|
||||||
import io.ktor.util.asStream
|
|
||||||
import io.ktor.utils.io.core.Input
|
|
||||||
import kotlinx.html.div
|
import kotlinx.html.div
|
||||||
import kotlinx.html.unsafe
|
import kotlinx.html.unsafe
|
||||||
import org.intellij.markdown.flavours.commonmark.CommonMarkFlavourDescriptor
|
import org.intellij.markdown.flavours.commonmark.CommonMarkFlavourDescriptor
|
||||||
import org.intellij.markdown.html.HtmlGenerator
|
import org.intellij.markdown.html.HtmlGenerator
|
||||||
import org.intellij.markdown.parser.MarkdownParser
|
import org.intellij.markdown.parser.MarkdownParser
|
||||||
import space.kscience.dataforge.context.Context
|
import space.kscience.dataforge.context.Context
|
||||||
import space.kscience.dataforge.io.IOReader
|
|
||||||
import space.kscience.dataforge.meta.Meta
|
import space.kscience.dataforge.meta.Meta
|
||||||
import space.kscience.dataforge.meta.get
|
import space.kscience.dataforge.meta.get
|
||||||
import space.kscience.snark.SnarkParser
|
import space.kscience.snark.SnarkParser
|
||||||
import java.awt.image.BufferedImage
|
|
||||||
import javax.imageio.ImageIO
|
|
||||||
import kotlin.reflect.KType
|
import kotlin.reflect.KType
|
||||||
import kotlin.reflect.typeOf
|
import kotlin.reflect.typeOf
|
||||||
|
|
||||||
@ -61,8 +56,3 @@ internal object SnarkMarkdownParser : SnarkTextParser<HtmlFragment>() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal object ImageIOReader : IOReader<BufferedImage> {
|
|
||||||
override val type: KType get() = typeOf<BufferedImage>()
|
|
||||||
|
|
||||||
override fun readObject(input: Input): BufferedImage = ImageIO.read(input.asStream())
|
|
||||||
}
|
|
||||||
|
@ -10,7 +10,6 @@ import space.kscience.dataforge.meta.toMutableMeta
|
|||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
import space.kscience.dataforge.names.isEmpty
|
import space.kscience.dataforge.names.isEmpty
|
||||||
import space.kscience.dataforge.names.plus
|
import space.kscience.dataforge.names.plus
|
||||||
import space.kscience.snark.SnarkEnvironment
|
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import kotlin.contracts.InvocationKind
|
import kotlin.contracts.InvocationKind
|
||||||
@ -30,7 +29,7 @@ internal class StaticSiteBuilder(
|
|||||||
private val outputPath: Path,
|
private val outputPath: Path,
|
||||||
) : SiteBuilder {
|
) : SiteBuilder {
|
||||||
|
|
||||||
override fun file(dataName: Name, routeName: Name) {
|
override fun static(dataName: Name, routeName: Name) {
|
||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,15 +81,16 @@ internal class StaticSiteBuilder(
|
|||||||
override val snark: SnarkHtmlPlugin get() = this@StaticSiteBuilder.snark
|
override val snark: SnarkHtmlPlugin get() = this@StaticSiteBuilder.snark
|
||||||
|
|
||||||
|
|
||||||
override fun resolveRef(ref: String): String = resolveRef(baseUrl, ref)
|
override fun resolveRef(ref: String): String =
|
||||||
|
this@StaticSiteBuilder.resolveRef(this@StaticSiteBuilder.baseUrl, ref)
|
||||||
|
|
||||||
override fun resolvePageRef(pageName: Name, relative: Boolean): String = resolveRef(
|
override fun resolvePageRef(pageName: Name, relative: Boolean): String = resolveRef(
|
||||||
(if (relative) route + pageName else pageName).toWebPath() + ".html"
|
(if (relative) this@StaticSiteBuilder.route + pageName else pageName).toWebPath() + ".html"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun page(route: Name, pageMeta: Meta, content: context(WebPage, HTML) () -> Unit) {
|
override fun page(route: Name, pageMeta: Meta, content: context(HTML) WebPage.() -> Unit) {
|
||||||
val htmlBuilder = createHTML()
|
val htmlBuilder = createHTML()
|
||||||
|
|
||||||
val modifiedPageMeta = pageMeta.toMutableMeta().apply {
|
val modifiedPageMeta = pageMeta.toMutableMeta().apply {
|
||||||
@ -98,7 +98,7 @@ internal class StaticSiteBuilder(
|
|||||||
}
|
}
|
||||||
|
|
||||||
htmlBuilder.html {
|
htmlBuilder.html {
|
||||||
content(StaticWebPage(Laminate(modifiedPageMeta, siteMeta)), this)
|
content(this, StaticWebPage(Laminate(modifiedPageMeta, siteMeta)))
|
||||||
}
|
}
|
||||||
|
|
||||||
val newPath = if (route.isEmpty()) {
|
val newPath = if (route.isEmpty()) {
|
||||||
@ -132,7 +132,7 @@ internal class StaticSiteBuilder(
|
|||||||
snark = snark,
|
snark = snark,
|
||||||
data = dataOverride ?: data,
|
data = dataOverride ?: data,
|
||||||
siteMeta = Laminate(routeMeta, siteMeta),
|
siteMeta = Laminate(routeMeta, siteMeta),
|
||||||
baseUrl = if(baseUrl == "") "" else resolveRef(baseUrl, routeName.toWebPath()),
|
baseUrl = if (baseUrl == "") "" else resolveRef(baseUrl, routeName.toWebPath()),
|
||||||
route = Name.EMPTY,
|
route = Name.EMPTY,
|
||||||
outputPath = outputPath.resolve(routeName.toWebPath())
|
outputPath = outputPath.resolve(routeName.toWebPath())
|
||||||
)
|
)
|
||||||
@ -143,14 +143,15 @@ internal class StaticSiteBuilder(
|
|||||||
* Use [siteUrl] as a base for all resolved URLs. By default, use [outputPath] absolute path as a base.
|
* Use [siteUrl] as a base for all resolved URLs. By default, use [outputPath] absolute path as a base.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public fun SnarkEnvironment.static(
|
public fun SnarkHtmlPlugin.static(
|
||||||
|
data: DataTree<*>,
|
||||||
outputPath: Path,
|
outputPath: Path,
|
||||||
siteUrl: String = outputPath.absolutePathString().replace("\\", "/"),
|
siteUrl: String = outputPath.absolutePathString().replace("\\", "/"),
|
||||||
|
siteMeta: Meta = data.meta,
|
||||||
block: SiteBuilder.() -> Unit,
|
block: SiteBuilder.() -> Unit,
|
||||||
) {
|
) {
|
||||||
contract {
|
contract {
|
||||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||||
}
|
}
|
||||||
val plugin = buildHtmlPlugin()
|
StaticSiteBuilder(this, data, siteMeta, siteUrl, Name.EMPTY, outputPath).block()
|
||||||
StaticSiteBuilder(plugin, data, meta, siteUrl, Name.EMPTY, outputPath).block()
|
|
||||||
}
|
}
|
@ -7,6 +7,7 @@ import space.kscience.dataforge.meta.Meta
|
|||||||
import space.kscience.dataforge.meta.get
|
import space.kscience.dataforge.meta.get
|
||||||
import space.kscience.dataforge.meta.string
|
import space.kscience.dataforge.meta.string
|
||||||
import space.kscience.dataforge.names.*
|
import space.kscience.dataforge.names.*
|
||||||
|
import space.kscience.snark.SnarkBuilder
|
||||||
import space.kscience.snark.SnarkContext
|
import space.kscience.snark.SnarkContext
|
||||||
|
|
||||||
context(SnarkContext)
|
context(SnarkContext)
|
||||||
@ -21,6 +22,7 @@ public fun Name.toWebPath(): String = tokens.joinToString(separator = "/") {
|
|||||||
/**
|
/**
|
||||||
* A context for building a single page
|
* A context for building a single page
|
||||||
*/
|
*/
|
||||||
|
@SnarkBuilder
|
||||||
public interface WebPage : ContextAware, SnarkContext {
|
public interface WebPage : ContextAware, SnarkContext {
|
||||||
|
|
||||||
public val snark: SnarkHtmlPlugin
|
public val snark: SnarkHtmlPlugin
|
||||||
@ -62,7 +64,7 @@ public val WebPage.name: Name? get() = pageMeta["name"].string?.parseAsName()
|
|||||||
* Resolve a Html builder by its full name
|
* Resolve a Html builder by its full name
|
||||||
*/
|
*/
|
||||||
context(SnarkContext)
|
context(SnarkContext)
|
||||||
public fun DataTree<*>.resolveHtml(name: Name): HtmlData? {
|
public fun DataTree<*>.resolveHtmlOrNull(name: Name): HtmlData? {
|
||||||
val resolved = (getByType<HtmlFragment>(name) ?: getByType<HtmlFragment>(name + SiteBuilder.INDEX_PAGE_TOKEN))
|
val resolved = (getByType<HtmlFragment>(name) ?: getByType<HtmlFragment>(name + SiteBuilder.INDEX_PAGE_TOKEN))
|
||||||
|
|
||||||
return resolved?.takeIf {
|
return resolved?.takeIf {
|
||||||
@ -71,7 +73,11 @@ public fun DataTree<*>.resolveHtml(name: Name): HtmlData? {
|
|||||||
}
|
}
|
||||||
|
|
||||||
context(SnarkContext)
|
context(SnarkContext)
|
||||||
public fun DataTree<*>.resolveHtml(name: String): HtmlData? = resolveHtml(name.parseAsName())
|
public fun DataTree<*>.resolveHtmlOrNull(name: String): HtmlData? = resolveHtmlOrNull(name.parseAsName())
|
||||||
|
|
||||||
|
context(SnarkContext)
|
||||||
|
public fun DataTree<*>.resolveHtml(name: String): HtmlData = resolveHtmlOrNull(name)
|
||||||
|
?: error("Html fragment with name $name is not resolved")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find all Html blocks using given name/meta filter
|
* Find all Html blocks using given name/meta filter
|
||||||
|
@ -1,42 +1,37 @@
|
|||||||
package space.kscience.snark.html
|
package space.kscience.snark.html
|
||||||
|
|
||||||
import space.kscience.dataforge.context.AbstractPlugin
|
|
||||||
import space.kscience.dataforge.context.PluginTag
|
|
||||||
import space.kscience.dataforge.data.DataTreeItem
|
import space.kscience.dataforge.data.DataTreeItem
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
import space.kscience.dataforge.names.parseAsName
|
import space.kscience.dataforge.names.parseAsName
|
||||||
import space.kscience.snark.SnarkEnvironment
|
|
||||||
import kotlin.contracts.InvocationKind
|
|
||||||
import kotlin.contracts.contract
|
|
||||||
|
|
||||||
public class SnarkHtmlEnvironmentBuilder {
|
public class SnarkHtmlEnvironmentBuilder {
|
||||||
public val layouts: HashMap<Name, SiteLayout> = HashMap()
|
public val layouts: HashMap<Name, SiteLayout> = HashMap()
|
||||||
|
|
||||||
public fun layout(name: String, body: context(SiteBuilder) (DataTreeItem<*>) -> Unit) {
|
public fun layout(name: String, body: context(SiteBuilder) (DataTreeItem<*>) -> Unit) {
|
||||||
layouts[name.parseAsName()] = object : SiteLayout {
|
layouts[name.parseAsName()] = object : SiteLayout {
|
||||||
context(SiteBuilder) override fun render(item: DataTreeItem<*>) = body(siteBuilder, item)
|
context(SiteBuilder) override fun render(item: DataTreeItem<*>) = body(site, item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public fun SnarkEnvironment.html(block: SnarkHtmlEnvironmentBuilder.() -> Unit) {
|
//public fun SnarkEnvironment.html(block: SnarkHtmlEnvironmentBuilder.() -> Unit) {
|
||||||
contract {
|
// contract {
|
||||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
// callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
val envBuilder = SnarkHtmlEnvironmentBuilder().apply(block)
|
// val envBuilder = SnarkHtmlEnvironmentBuilder().apply(block)
|
||||||
|
//
|
||||||
val plugin = object : AbstractPlugin() {
|
// val plugin = object : AbstractPlugin() {
|
||||||
val snark by require(SnarkHtmlPlugin)
|
// val snark by require(SnarkHtmlPlugin)
|
||||||
|
//
|
||||||
override val tag: PluginTag = PluginTag("@extension[${hashCode()}]")
|
// override val tag: PluginTag = PluginTag("@extension[${hashCode()}]")
|
||||||
|
//
|
||||||
|
//
|
||||||
override fun content(target: String): Map<Name, Any> = when (target) {
|
// override fun content(target: String): Map<Name, Any> = when (target) {
|
||||||
SiteLayout.TYPE -> envBuilder.layouts
|
// SiteLayout.TYPE -> envBuilder.layouts
|
||||||
else -> super.content(target)
|
// else -> super.content(target)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
registerPlugin(plugin)
|
// registerPlugin(plugin)
|
||||||
}
|
//}
|
@ -20,6 +20,8 @@ import kotlinx.css.CssBuilder
|
|||||||
import kotlinx.html.CommonAttributeGroupFacade
|
import kotlinx.html.CommonAttributeGroupFacade
|
||||||
import kotlinx.html.HTML
|
import kotlinx.html.HTML
|
||||||
import kotlinx.html.style
|
import kotlinx.html.style
|
||||||
|
import space.kscience.dataforge.context.error
|
||||||
|
import space.kscience.dataforge.context.logger
|
||||||
import space.kscience.dataforge.data.DataTree
|
import space.kscience.dataforge.data.DataTree
|
||||||
import space.kscience.dataforge.data.DataTreeItem
|
import space.kscience.dataforge.data.DataTreeItem
|
||||||
import space.kscience.dataforge.data.await
|
import space.kscience.dataforge.data.await
|
||||||
@ -32,8 +34,10 @@ import space.kscience.dataforge.names.cutLast
|
|||||||
import space.kscience.dataforge.names.endsWith
|
import space.kscience.dataforge.names.endsWith
|
||||||
import space.kscience.dataforge.names.plus
|
import space.kscience.dataforge.names.plus
|
||||||
import space.kscience.dataforge.workspace.FileData
|
import space.kscience.dataforge.workspace.FileData
|
||||||
import space.kscience.snark.SnarkEnvironment
|
import space.kscience.snark.html.SiteBuilder
|
||||||
import space.kscience.snark.html.*
|
import space.kscience.snark.html.SnarkHtmlPlugin
|
||||||
|
import space.kscience.snark.html.WebPage
|
||||||
|
import space.kscience.snark.html.toWebPath
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import kotlin.contracts.InvocationKind
|
import kotlin.contracts.InvocationKind
|
||||||
import kotlin.contracts.contract
|
import kotlin.contracts.contract
|
||||||
@ -52,34 +56,35 @@ public class KtorSiteBuilder(
|
|||||||
private val ktorRoute: Route,
|
private val ktorRoute: Route,
|
||||||
) : SiteBuilder {
|
) : SiteBuilder {
|
||||||
|
|
||||||
private fun file(item: DataTreeItem<Any>, routeName: Name) {
|
private fun files(item: DataTreeItem<Any>, routeName: Name) {
|
||||||
val extension = item.meta[FileData.FILE_EXTENSION_KEY]?.string?.let { ".$it" } ?: ""
|
|
||||||
|
|
||||||
//try using direct file rendering
|
//try using direct file rendering
|
||||||
item.meta[FileData.FILE_PATH_KEY]?.string?.let {
|
item.meta[FileData.FILE_PATH_KEY]?.string?.let {
|
||||||
try {
|
val file = try {
|
||||||
val file = Path.of(it).toFile()
|
Path.of(it).toFile()
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
//failure,
|
||||||
|
logger.error { "File $it could not be converted to java.io.File"}
|
||||||
|
return@let
|
||||||
|
}
|
||||||
|
|
||||||
if (file.isDirectory) {
|
if (file.isDirectory) {
|
||||||
ktorRoute.static(routeName.toWebPath()) {
|
ktorRoute.static(routeName.toWebPath()) {
|
||||||
files(file)
|
files(file)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val fileName = routeName.toWebPath() + extension //TODO add extension
|
val fileName = routeName.toWebPath()
|
||||||
ktorRoute.file(fileName, file)
|
ktorRoute.file(fileName, file)
|
||||||
}
|
}
|
||||||
//success, don't do anything else
|
//success, don't do anything else
|
||||||
return@file
|
return@files
|
||||||
} catch (ex: Exception) {
|
|
||||||
//failure,
|
|
||||||
return@let
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
when (item) {
|
when (item) {
|
||||||
is DataTreeItem.Leaf -> {
|
is DataTreeItem.Leaf -> {
|
||||||
val datum = item.data
|
val datum = item.data
|
||||||
if (datum.type != typeOf<Binary>()) error("Can't directly serve file of type ${item.data.type}")
|
if (datum.type != typeOf<Binary>()) error("Can't directly serve file of type ${item.data.type}")
|
||||||
ktorRoute.get(routeName.toWebPath() + extension) {
|
ktorRoute.get(routeName.toWebPath()) {
|
||||||
val binary = datum.await() as Binary
|
val binary = datum.await() as Binary
|
||||||
|
val extension = item.meta[FileData.FILE_EXTENSION_KEY]?.string?.let { ".$it" } ?: ""
|
||||||
val contentType: ContentType = extension
|
val contentType: ContentType = extension
|
||||||
.let(ContentType::fromFileExtension)
|
.let(ContentType::fromFileExtension)
|
||||||
.firstOrNull()
|
.firstOrNull()
|
||||||
@ -93,15 +98,15 @@ public class KtorSiteBuilder(
|
|||||||
|
|
||||||
is DataTreeItem.Node -> {
|
is DataTreeItem.Node -> {
|
||||||
item.tree.items.forEach { (token, childItem) ->
|
item.tree.items.forEach { (token, childItem) ->
|
||||||
file(childItem, routeName + token)
|
files(childItem, routeName + token)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun file(dataName: Name, routeName: Name) {
|
override fun static(dataName: Name, routeName: Name) {
|
||||||
val item: DataTreeItem<Any> = data.getItem(dataName) ?: error("Data with name is not resolved")
|
val item: DataTreeItem<Any> = data.getItem(dataName) ?: error("Data with name $dataName is not resolved")
|
||||||
file(item, routeName)
|
files(item, routeName)
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// override fun file(file: Path, webPath: String) {
|
// override fun file(file: Path, webPath: String) {
|
||||||
@ -140,13 +145,13 @@ public class KtorSiteBuilder(
|
|||||||
override val snark: SnarkHtmlPlugin get() = this@KtorSiteBuilder.snark
|
override val snark: SnarkHtmlPlugin get() = this@KtorSiteBuilder.snark
|
||||||
override val data: DataTree<*> get() = this@KtorSiteBuilder.data
|
override val data: DataTree<*> get() = this@KtorSiteBuilder.data
|
||||||
|
|
||||||
override fun resolveRef(ref: String): String = resolveRef(pageBaseUrl, ref)
|
override fun resolveRef(ref: String): String = this@KtorSiteBuilder.resolveRef(pageBaseUrl, ref)
|
||||||
|
|
||||||
override fun resolvePageRef(
|
override fun resolvePageRef(
|
||||||
pageName: Name,
|
pageName: Name,
|
||||||
relative: Boolean,
|
relative: Boolean,
|
||||||
): String {
|
): String {
|
||||||
val fullPageName = if (relative) route + pageName else pageName
|
val fullPageName = if (relative) this@KtorSiteBuilder.route + pageName else pageName
|
||||||
return if (fullPageName.endsWith(SiteBuilder.INDEX_PAGE_TOKEN)) {
|
return if (fullPageName.endsWith(SiteBuilder.INDEX_PAGE_TOKEN)) {
|
||||||
resolveRef(fullPageName.cutLast().toWebPath())
|
resolveRef(fullPageName.cutLast().toWebPath())
|
||||||
} else {
|
} else {
|
||||||
@ -155,7 +160,7 @@ public class KtorSiteBuilder(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun page(route: Name, pageMeta: Meta, content: context(WebPage, HTML)() -> Unit) {
|
override fun page(route: Name, pageMeta: Meta, content: context(HTML, WebPage) () -> Unit) {
|
||||||
ktorRoute.get(route.toWebPath()) {
|
ktorRoute.get(route.toWebPath()) {
|
||||||
call.respondHtml {
|
call.respondHtml {
|
||||||
val request = call.request
|
val request = call.request
|
||||||
@ -172,7 +177,7 @@ public class KtorSiteBuilder(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val pageBuilder = KtorWebPage(url.buildString(), Laminate(modifiedPageMeta, siteMeta))
|
val pageBuilder = KtorWebPage(url.buildString(), Laminate(modifiedPageMeta, siteMeta))
|
||||||
content(pageBuilder, this)
|
content(this, pageBuilder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -213,26 +218,30 @@ public class KtorSiteBuilder(
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
context(Route, SnarkEnvironment)
|
private fun Route.site(
|
||||||
private fun siteInRoute(
|
snarkHtmlPlugin: SnarkHtmlPlugin,
|
||||||
|
data: DataTree<*>,
|
||||||
baseUrl: String = "",
|
baseUrl: String = "",
|
||||||
|
siteMeta: Meta = data.meta,
|
||||||
block: KtorSiteBuilder.() -> Unit,
|
block: KtorSiteBuilder.() -> Unit,
|
||||||
) {
|
) {
|
||||||
contract {
|
contract {
|
||||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||||
}
|
}
|
||||||
block(KtorSiteBuilder(buildHtmlPlugin(), data, meta, baseUrl, route = Name.EMPTY, this@Route))
|
block(KtorSiteBuilder(snarkHtmlPlugin, data, siteMeta, baseUrl, route = Name.EMPTY, this@Route))
|
||||||
}
|
}
|
||||||
|
|
||||||
context(Application)
|
public fun Application.site(
|
||||||
public fun SnarkEnvironment.site(
|
snark: SnarkHtmlPlugin,
|
||||||
|
data: DataTree<*>,
|
||||||
baseUrl: String = "",
|
baseUrl: String = "",
|
||||||
block: KtorSiteBuilder.() -> Unit,
|
siteMeta: Meta = data.meta,
|
||||||
|
block: SiteBuilder.() -> Unit,
|
||||||
) {
|
) {
|
||||||
contract {
|
contract {
|
||||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||||
}
|
}
|
||||||
routing {
|
routing {
|
||||||
siteInRoute(baseUrl, block)
|
site(snark, data, baseUrl, siteMeta, block)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,30 +12,30 @@ import java.time.LocalDateTime
|
|||||||
import kotlin.io.path.*
|
import kotlin.io.path.*
|
||||||
|
|
||||||
|
|
||||||
public fun KtorSiteBuilder.extractResources(uri: URI, targetPath: Path): Path {
|
//public fun KtorSiteBuilder.extractResources(uri: URI, targetPath: Path): Path {
|
||||||
if (Files.isDirectory(targetPath)) {
|
// if (Files.isDirectory(targetPath)) {
|
||||||
logger.info { "Using existing data directory at $targetPath." }
|
// logger.info { "Using existing data directory at $targetPath." }
|
||||||
} else {
|
// } else {
|
||||||
logger.info { "Copying data from $uri into $targetPath." }
|
// logger.info { "Copying data from $uri into $targetPath." }
|
||||||
targetPath.createDirectories()
|
// targetPath.createDirectories()
|
||||||
//Copy everything into a temporary directory
|
// //Copy everything into a temporary directory
|
||||||
FileSystems.newFileSystem(uri, emptyMap<String, Any>()).use { fs ->
|
// FileSystems.newFileSystem(uri, emptyMap<String, Any>()).use { fs ->
|
||||||
val rootPath: Path = fs.provider().getPath(uri)
|
// val rootPath: Path = fs.provider().getPath(uri)
|
||||||
Files.walk(rootPath).forEach { source: Path ->
|
// Files.walk(rootPath).forEach { source: Path ->
|
||||||
if (source.isRegularFile()) {
|
// if (source.isRegularFile()) {
|
||||||
val relative = source.relativeTo(rootPath).toString()
|
// val relative = source.relativeTo(rootPath).toString()
|
||||||
val destination: Path = targetPath.resolve(relative)
|
// val destination: Path = targetPath.resolve(relative)
|
||||||
destination.parent.createDirectories()
|
// destination.parent.createDirectories()
|
||||||
Files.copy(source, destination)
|
// Files.copy(source, destination)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
return targetPath
|
// return targetPath
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
public fun KtorSiteBuilder.extractResources(resource: String, targetPath: Path): Path =
|
//public fun KtorSiteBuilder.extractResources(resource: String, targetPath: Path): Path =
|
||||||
extractResources(javaClass.getResource(resource)!!.toURI(), targetPath)
|
// extractResources(javaClass.getResource(resource)!!.toURI(), targetPath)
|
||||||
|
|
||||||
private const val DEPLOY_DATE_FILE = "deployDate"
|
private const val DEPLOY_DATE_FILE = "deployDate"
|
||||||
private const val BUILD_DATE_FILE = "/buildDate"
|
private const val BUILD_DATE_FILE = "/buildDate"
|
||||||
|
Loading…
Reference in New Issue
Block a user