From bafc75086ad4ff8dc892b792f7d7f5578e4a6082 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 22 Jun 2022 22:14:19 +0300 Subject: [PATCH] Implementation for static site generator --- src/main/kotlin/ru/mipt/spc/spcCollection.kt | 2 +- src/main/kotlin/ru/mipt/spc/spcHome.kt | 2 +- .../space/kscience/snark/KtorSiteBuilder.kt | 46 +++++++++++++++++++ .../space/kscience/snark/SiteBuilder.kt | 42 +---------------- .../kotlin/space/kscience/snark/SiteData.kt | 1 - .../space/kscience/snark/StaticSiteBuilder.kt | 46 +++++++++++++++++++ 6 files changed, 95 insertions(+), 44 deletions(-) create mode 100644 src/main/kotlin/space/kscience/snark/KtorSiteBuilder.kt create mode 100644 src/main/kotlin/space/kscience/snark/StaticSiteBuilder.kt diff --git a/src/main/kotlin/ru/mipt/spc/spcCollection.kt b/src/main/kotlin/ru/mipt/spc/spcCollection.kt index 0a36e5f..5b7c3da 100644 --- a/src/main/kotlin/ru/mipt/spc/spcCollection.kt +++ b/src/main/kotlin/ru/mipt/spc/spcCollection.kt @@ -21,7 +21,7 @@ context(SiteData, FlowContent) private fun spcSpotlightContent( ) { // Banner // Note: The "styleN" class below should match that of the header element. - section("style2") { + section("style1") { id = "banner" div("inner") { span("image") { diff --git a/src/main/kotlin/ru/mipt/spc/spcHome.kt b/src/main/kotlin/ru/mipt/spc/spcHome.kt index 54e4f28..373721a 100644 --- a/src/main/kotlin/ru/mipt/spc/spcHome.kt +++ b/src/main/kotlin/ru/mipt/spc/spcHome.kt @@ -65,7 +65,7 @@ internal val FortyDataRenderer: SiteBuilder.(Data<*>) -> Unit = { data -> } -context(SiteData, HTML) private fun HTML.spcHome() { +context(SiteData, HTML) private fun spcHome() { spcHead() body("is-preload") { wrapper { diff --git a/src/main/kotlin/space/kscience/snark/KtorSiteBuilder.kt b/src/main/kotlin/space/kscience/snark/KtorSiteBuilder.kt new file mode 100644 index 0000000..c3ad1cc --- /dev/null +++ b/src/main/kotlin/space/kscience/snark/KtorSiteBuilder.kt @@ -0,0 +1,46 @@ +package space.kscience.snark + +import io.ktor.server.application.call +import io.ktor.server.html.respondHtml +import io.ktor.server.http.content.* +import io.ktor.server.routing.Route +import io.ktor.server.routing.createRouteFromPath +import io.ktor.server.routing.get +import kotlinx.html.HTML +import space.kscience.dataforge.names.Name +import java.nio.file.Path + +class KtorSiteBuilder(override val data: SiteData, private val ktorRoute: Route) : SiteBuilder { + + override fun assetFile(remotePath: String, file: Path) { + ktorRoute.file(remotePath, file.toFile()) + } + + override fun assetDirectory(remotePath: String, directory: Path) { + ktorRoute.static(remotePath) { + files(directory.toFile()) + } + } + + override fun page(route: Name, content: context(SiteData, HTML)() -> Unit) { + ktorRoute.get(route.toWebPath()) { + call.respondHtml { + val dataWithUrl = data.copyWithRequestHost(call.request) + content(dataWithUrl, this) + } + } + } + + override fun route(subRoute: Name): SiteBuilder = + KtorSiteBuilder(data, ktorRoute.createRouteFromPath(subRoute.toWebPath())) + + override fun assetResourceFile(remotePath: String, resourcesPath: String) { + ktorRoute.resource(resourcesPath, resourcesPath) + } + + override fun assetResourceDirectory(resourcesPath: String) { + ktorRoute.resources(resourcesPath) + } + + override fun withData(newData: SiteData): SiteBuilder = KtorSiteBuilder(newData, ktorRoute) +} \ No newline at end of file diff --git a/src/main/kotlin/space/kscience/snark/SiteBuilder.kt b/src/main/kotlin/space/kscience/snark/SiteBuilder.kt index dccd6d5..0b58e09 100644 --- a/src/main/kotlin/space/kscience/snark/SiteBuilder.kt +++ b/src/main/kotlin/space/kscience/snark/SiteBuilder.kt @@ -1,12 +1,7 @@ package space.kscience.snark import io.ktor.server.application.Application -import io.ktor.server.application.call -import io.ktor.server.html.respondHtml -import io.ktor.server.http.content.* import io.ktor.server.routing.Route -import io.ktor.server.routing.createRouteFromPath -import io.ktor.server.routing.get import io.ktor.server.routing.routing import kotlinx.html.HTML import space.kscience.dataforge.context.Context @@ -72,46 +67,11 @@ public fun SiteBuilder.mountSite(route: Name, dataRoot: DataTree<*>, block: Site } } -class KtorSiteRoute(override val data: SiteData, private val ktorRoute: Route) : SiteBuilder { - - override fun assetFile(remotePath: String, file: Path) { - ktorRoute.file(remotePath, file.toFile()) - } - - override fun assetDirectory(remotePath: String, directory: Path) { - ktorRoute.static(remotePath) { - files(directory.toFile()) - } - } - - override fun page(route: Name, content: context(SiteData, HTML)() -> Unit) { - ktorRoute.get(route.toWebPath()) { - call.respondHtml { - val dataWithUrl = data.copyWithRequestHost(call.request) - content(dataWithUrl, this) - } - } - } - - override fun route(subRoute: Name): SiteBuilder = - KtorSiteRoute(data, ktorRoute.createRouteFromPath(subRoute.toWebPath())) - - override fun assetResourceFile(remotePath: String, resourcesPath: String) { - ktorRoute.resource(resourcesPath, resourcesPath) - } - - override fun assetResourceDirectory(resourcesPath: String) { - ktorRoute.resources(resourcesPath) - } - - override fun withData(newData: SiteData): SiteBuilder = KtorSiteRoute(newData, ktorRoute) -} - inline fun Route.mountSnark( data: SiteData, block: context(SiteData, SiteBuilder)() -> Unit, ) { - block(data, KtorSiteRoute(data, this@mountSnark)) + block(data, KtorSiteBuilder(data, this@mountSnark)) } fun Application.mountSnark( diff --git a/src/main/kotlin/space/kscience/snark/SiteData.kt b/src/main/kotlin/space/kscience/snark/SiteData.kt index becdcd5..33b6e0f 100644 --- a/src/main/kotlin/space/kscience/snark/SiteData.kt +++ b/src/main/kotlin/space/kscience/snark/SiteData.kt @@ -79,7 +79,6 @@ fun DataTree<*>.resolveAllHtml(predicate: (name: Name, meta: Meta) -> Boolean): val SiteData.homeRef get() = resolveRef("").removeSuffix("/") - fun SiteData.findByType(contentType: String, baseName: Name = Name.EMPTY) = resolveAllHtml { name, meta -> name.startsWith(baseName) && meta["content_type"].string == contentType } diff --git a/src/main/kotlin/space/kscience/snark/StaticSiteBuilder.kt b/src/main/kotlin/space/kscience/snark/StaticSiteBuilder.kt new file mode 100644 index 0000000..a823076 --- /dev/null +++ b/src/main/kotlin/space/kscience/snark/StaticSiteBuilder.kt @@ -0,0 +1,46 @@ +package space.kscience.snark + +import kotlinx.html.HTML +import kotlinx.html.html +import kotlinx.html.stream.createHTML +import space.kscience.dataforge.names.Name +import java.nio.file.Path +import kotlin.io.path.copyTo +import kotlin.io.path.createDirectories +import kotlin.io.path.writeText + +class StaticSiteBuilder(override val data: SiteData, private val path: Path) : SiteBuilder { + override fun assetFile(remotePath: String, file: Path) { + file.copyTo(path.resolve(remotePath)) + } + + override fun assetDirectory(remotePath: String, directory: Path) { + directory.copyTo(path.resolve(remotePath)) + } + + override fun assetResourceFile(remotePath: String, resourcesPath: String) { + javaClass.getResource(resourcesPath)?.let { Path.of(it.toURI()) }?.copyTo(path.resolve(remotePath)) + } + + override fun assetResourceDirectory(resourcesPath: String) { + javaClass.getResource(resourcesPath)?.let { Path.of(it.toURI()) }?.copyTo(path) + } + + override fun page(route: Name, content: context(SiteData, HTML) () -> Unit) { + val htmlBuilder = createHTML() + + htmlBuilder.html { + content(data, this) + } + + val newPath = path.resolve(route.toWebPath() + ".html") + + newPath.parent.createDirectories() + newPath.writeText(htmlBuilder.finalize()) + } + + override fun route(subRoute: Name): SiteBuilder = StaticSiteBuilder(data, path.resolve(subRoute.toWebPath())) + + override fun withData(newData: SiteData): SiteBuilder = StaticSiteBuilder(newData, path) + +} \ No newline at end of file