Resolving paths for static sites.

This commit is contained in:
Alexander Nozik 2022-06-22 23:35:16 +03:00
parent bafc75086a
commit d657282a33
No known key found for this signature in database
GPG Key ID: F7FCF2DD25C71357
7 changed files with 102 additions and 64 deletions

View File

@ -8,7 +8,7 @@ import kotlinx.html.style
import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.fetch import space.kscience.dataforge.context.fetch
import space.kscience.snark.SnarkPlugin import space.kscience.snark.SnarkPlugin
import space.kscience.snark.mountSnark import space.kscience.snark.site
import java.net.URI import java.net.URI
import java.nio.file.FileSystems import java.nio.file.FileSystems
import java.nio.file.Files import java.nio.file.Files
@ -50,7 +50,7 @@ fun Application.spcModule() {
val context = Context("spc-site") { val context = Context("spc-site") {
plugin(SnarkPlugin) plugin(SnarkPlugin)
} }
val snarkPlugin = context.fetch(SnarkPlugin) val snark = context.fetch(SnarkPlugin)
val dataPath = Path.of("data") val dataPath = Path.of("data")
@ -86,16 +86,16 @@ fun Application.spcModule() {
dataPath.resolve(DEPLOY_DATE_FILE).writeText(date) dataPath.resolve(DEPLOY_DATE_FILE).writeText(date)
} }
mountSnark(snarkPlugin) { snark.site {
val homeDataPath = resolveData( val homeDataPath = resolveData(
javaClass.getResource("/home")!!.toURI(), this@spcModule.javaClass.getResource("/home")!!.toURI(),
dataPath / "home" dataPath / "home"
) )
spcHome(rootPath = homeDataPath) spcHome(rootPath = homeDataPath)
val mastersDataPath = resolveData( val mastersDataPath = resolveData(
javaClass.getResource("/magprog")!!.toURI(), this@spcModule.javaClass.getResource("/magprog")!!.toURI(),
dataPath / "magprog" dataPath / "magprog"
) )

View File

@ -221,7 +221,7 @@ context(SiteData) internal fun HTML.magProgHead(title: String) {
} }
link { link {
rel = "stylesheet" rel = "stylesheet"
href = resolveRef("css/main.css") href = resolveRef("assets/css/main.css")
} }
link { link {
rel = "shortcut icon" rel = "shortcut icon"
@ -230,7 +230,7 @@ context(SiteData) internal fun HTML.magProgHead(title: String) {
noScript { noScript {
link { link {
rel = "stylesheet" rel = "stylesheet"
href = resolveRef("css/noscript.css") href = resolveRef("assets/css/noscript.css")
} }
} }
} }
@ -253,25 +253,25 @@ context(SiteData) internal fun BODY.magProgFooter() {
} }
} }
script { script {
src = resolveRef("js/jquery.min.js") src = resolveRef("assets/js/jquery.min.js")
} }
script { script {
src = resolveRef("js/jquery.scrollex.min.js") src = resolveRef("assets/js/jquery.scrollex.min.js")
} }
script { script {
src = resolveRef("js/jquery.scrolly.min.js") src = resolveRef("assets/js/jquery.scrolly.min.js")
} }
script { script {
src = resolveRef("js/browser.min.js") src = resolveRef("assets/js/browser.min.js")
} }
script { script {
src = resolveRef("js/breakpoints.min.js") src = resolveRef("assets/js/breakpoints.min.js")
} }
script { script {
src = resolveRef("js/util.js") src = resolveRef("assets/js/util.js")
} }
script { script {
src = resolveRef("js/main.js") src = resolveRef("assets/js/main.js")
} }
} }
@ -282,7 +282,7 @@ internal fun SiteBuilder.spcMaster(dataPath: Path, prefix: Name = "magprog".asNa
val magProgSiteContext = snark.readDirectory(dataPath.resolve("content")) val magProgSiteContext = snark.readDirectory(dataPath.resolve("content"))
mountSite(prefix, magProgSiteContext) { mountSite(prefix, magProgSiteContext) {
assetDirectory("", dataPath.resolve("assets")) assetDirectory("assets", dataPath.resolve("assets"))
assetDirectory("images", dataPath.resolve("images")) assetDirectory("images", dataPath.resolve("images"))
page { page {

View File

@ -0,0 +1,15 @@
package ru.mipt.spc
import space.kscience.dataforge.context.Global
import space.kscience.dataforge.context.fetch
import space.kscience.snark.SnarkPlugin
import space.kscience.snark.static
import java.nio.file.Path
import kotlin.io.path.toPath
fun main() {
Global.fetch(SnarkPlugin).static(Path.of("build/out")) {
spcHome(rootPath = javaClass.getResource("/home")!!.toURI().toPath())
spcMaster(dataPath = javaClass.getResource("/magprog")!!.toURI().toPath())
}
}

View File

@ -1,11 +1,19 @@
package space.kscience.snark package space.kscience.snark
import io.ktor.http.URLBuilder
import io.ktor.http.URLProtocol
import io.ktor.server.application.Application
import io.ktor.server.application.call import io.ktor.server.application.call
import io.ktor.server.html.respondHtml import io.ktor.server.html.respondHtml
import io.ktor.server.http.content.* import io.ktor.server.http.content.*
import io.ktor.server.plugins.origin
import io.ktor.server.request.ApplicationRequest
import io.ktor.server.request.host
import io.ktor.server.request.port
import io.ktor.server.routing.Route import io.ktor.server.routing.Route
import io.ktor.server.routing.createRouteFromPath import io.ktor.server.routing.createRouteFromPath
import io.ktor.server.routing.get import io.ktor.server.routing.get
import io.ktor.server.routing.routing
import kotlinx.html.HTML import kotlinx.html.HTML
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import java.nio.file.Path import java.nio.file.Path
@ -43,4 +51,37 @@ class KtorSiteBuilder(override val data: SiteData, private val ktorRoute: Route)
} }
override fun withData(newData: SiteData): SiteBuilder = KtorSiteBuilder(newData, ktorRoute) override fun withData(newData: SiteData): SiteBuilder = KtorSiteBuilder(newData, ktorRoute)
}
@PublishedApi
internal fun SiteData.copyWithRequestHost(request: ApplicationRequest): SiteData {
val uri = URLBuilder(
protocol = URLProtocol.createOrDefault(request.origin.scheme),
host = request.host(),
port = request.port(),
pathSegments = baseUrlPath.split("/"),
)
return copy(baseUrlPath = uri.buildString())
}
inline fun Route.snarkSite(
data: SiteData,
block: SiteBuilder.() -> Unit,
) {
block(KtorSiteBuilder(data, this@snarkSite))
}
fun Application.snarkSite(
data: SiteData,
block: SiteBuilder.() -> Unit,
) {
routing {
snarkSite(data, block)
}
}
context (Application) fun SnarkPlugin.site(
block: SiteBuilder.() -> Unit,
) {
snarkSite(SiteData.empty(this), block)
} }

View File

@ -1,8 +1,5 @@
package space.kscience.snark package space.kscience.snark
import io.ktor.server.application.Application
import io.ktor.server.routing.Route
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
import space.kscience.dataforge.context.ContextAware import space.kscience.dataforge.context.ContextAware
@ -66,27 +63,3 @@ public fun SiteBuilder.mountSite(route: Name, dataRoot: DataTree<*>, block: Site
withData(mountedData).block() withData(mountedData).block()
} }
} }
inline fun Route.mountSnark(
data: SiteData,
block: context(SiteData, SiteBuilder)() -> Unit,
) {
block(data, KtorSiteBuilder(data, this@mountSnark))
}
fun Application.mountSnark(
data: SiteData,
block: context(SiteData, SiteBuilder)() -> Unit,
) {
routing {
mountSnark(data, block)
}
}
fun Application.mountSnark(
snarkPlugin: SnarkPlugin,
block: context(SiteData, SiteBuilder)() -> Unit,
) {
mountSnark(SiteData.empty(snarkPlugin), block)
}

View File

@ -1,11 +1,5 @@
package space.kscience.snark package space.kscience.snark
import io.ktor.http.URLBuilder
import io.ktor.http.URLProtocol
import io.ktor.server.plugins.origin
import io.ktor.server.request.ApplicationRequest
import io.ktor.server.request.host
import io.ktor.server.request.port
import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.ContextAware import space.kscience.dataforge.context.ContextAware
import space.kscience.dataforge.data.* import space.kscience.dataforge.data.*
@ -93,14 +87,3 @@ internal val Data<*>.published: Boolean get() = meta["published"].string != "fal
// //
// return readData(parsedData, rootUrl) // return readData(parsedData, rootUrl)
//} //}
@PublishedApi
internal fun SiteData.copyWithRequestHost(request: ApplicationRequest): SiteData {
val uri = URLBuilder(
protocol = URLProtocol.createOrDefault(request.origin.scheme),
host = request.host(),
port = request.port(),
pathSegments = baseUrlPath.split("/"),
)
return copy(baseUrlPath = uri.buildString())
}

View File

@ -4,26 +4,44 @@ import kotlinx.html.HTML
import kotlinx.html.html import kotlinx.html.html
import kotlinx.html.stream.createHTML import kotlinx.html.stream.createHTML
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.isEmpty
import java.nio.file.Files
import java.nio.file.Path import java.nio.file.Path
import kotlin.io.path.copyTo import kotlin.io.path.copyTo
import kotlin.io.path.createDirectories import kotlin.io.path.createDirectories
import kotlin.io.path.relativeTo
import kotlin.io.path.writeText import kotlin.io.path.writeText
class StaticSiteBuilder(override val data: SiteData, private val path: Path) : SiteBuilder { class StaticSiteBuilder(override val data: SiteData, private val path: Path) : SiteBuilder {
private fun Path.copyRecursively(target: Path) {
Files.walk(this).forEach { source: Path ->
val destination: Path = target.resolve(source.relativeTo(this))
source.copyTo(destination,true)
}
}
override fun assetFile(remotePath: String, file: Path) { override fun assetFile(remotePath: String, file: Path) {
file.copyTo(path.resolve(remotePath)) val targetPath = path.resolve(remotePath)
targetPath.parent.createDirectories()
file.copyTo(targetPath, true)
} }
override fun assetDirectory(remotePath: String, directory: Path) { override fun assetDirectory(remotePath: String, directory: Path) {
directory.copyTo(path.resolve(remotePath)) val targetPath = path.resolve(remotePath)
targetPath.parent.createDirectories()
directory.copyRecursively(targetPath)
} }
override fun assetResourceFile(remotePath: String, resourcesPath: String) { override fun assetResourceFile(remotePath: String, resourcesPath: String) {
javaClass.getResource(resourcesPath)?.let { Path.of(it.toURI()) }?.copyTo(path.resolve(remotePath)) val targetPath = path.resolve(remotePath)
targetPath.parent.createDirectories()
javaClass.getResource(resourcesPath)?.let { Path.of(it.toURI()) }?.copyTo(targetPath,true)
} }
override fun assetResourceDirectory(resourcesPath: String) { override fun assetResourceDirectory(resourcesPath: String) {
javaClass.getResource(resourcesPath)?.let { Path.of(it.toURI()) }?.copyTo(path) path.parent.createDirectories()
javaClass.getResource(resourcesPath)?.let { Path.of(it.toURI()) }?.copyRecursively(path)
} }
override fun page(route: Name, content: context(SiteData, HTML) () -> Unit) { override fun page(route: Name, content: context(SiteData, HTML) () -> Unit) {
@ -33,7 +51,11 @@ class StaticSiteBuilder(override val data: SiteData, private val path: Path) : S
content(data, this) content(data, this)
} }
val newPath = path.resolve(route.toWebPath() + ".html") val newPath = if (route.isEmpty()) {
path.resolve("index.html")
} else {
path.resolve(route.toWebPath() + ".html")
}
newPath.parent.createDirectories() newPath.parent.createDirectories()
newPath.writeText(htmlBuilder.finalize()) newPath.writeText(htmlBuilder.finalize())
@ -43,4 +65,8 @@ class StaticSiteBuilder(override val data: SiteData, private val path: Path) : S
override fun withData(newData: SiteData): SiteBuilder = StaticSiteBuilder(newData, path) override fun withData(newData: SiteData): SiteBuilder = StaticSiteBuilder(newData, path)
}
fun SnarkPlugin.static(path: Path, block: SiteBuilder.() -> Unit) {
StaticSiteBuilder(SiteData.empty(this), path).block()
} }