Implementation for static site generator

This commit is contained in:
Alexander Nozik 2022-06-22 22:14:19 +03:00
parent d74c8be135
commit bafc75086a
No known key found for this signature in database
GPG Key ID: F7FCF2DD25C71357
6 changed files with 95 additions and 44 deletions

View File

@ -21,7 +21,7 @@ context(SiteData, FlowContent) private fun spcSpotlightContent(
) { ) {
// Banner // Banner
// Note: The "styleN" class below should match that of the header element. // Note: The "styleN" class below should match that of the header element.
section("style2") { section("style1") {
id = "banner" id = "banner"
div("inner") { div("inner") {
span("image") { span("image") {

View File

@ -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() spcHead()
body("is-preload") { body("is-preload") {
wrapper { wrapper {

View File

@ -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)
}

View File

@ -1,12 +1,7 @@
package space.kscience.snark package space.kscience.snark
import io.ktor.server.application.Application 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.Route
import io.ktor.server.routing.createRouteFromPath
import io.ktor.server.routing.get
import io.ktor.server.routing.routing import io.ktor.server.routing.routing
import kotlinx.html.HTML import kotlinx.html.HTML
import space.kscience.dataforge.context.Context 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( inline fun Route.mountSnark(
data: SiteData, data: SiteData,
block: context(SiteData, SiteBuilder)() -> Unit, block: context(SiteData, SiteBuilder)() -> Unit,
) { ) {
block(data, KtorSiteRoute(data, this@mountSnark)) block(data, KtorSiteBuilder(data, this@mountSnark))
} }
fun Application.mountSnark( fun Application.mountSnark(

View File

@ -79,7 +79,6 @@ fun DataTree<*>.resolveAllHtml(predicate: (name: Name, meta: Meta) -> Boolean):
val SiteData.homeRef get() = resolveRef("").removeSuffix("/") val SiteData.homeRef get() = resolveRef("").removeSuffix("/")
fun SiteData.findByType(contentType: String, baseName: Name = Name.EMPTY) = resolveAllHtml { name, meta -> fun SiteData.findByType(contentType: String, baseName: Name = Name.EMPTY) = resolveAllHtml { name, meta ->
name.startsWith(baseName) && meta["content_type"].string == contentType name.startsWith(baseName) && meta["content_type"].string == contentType
} }

View File

@ -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)
}