<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="KotlinJpsPluginSettings">
- <option name="version" value="1.8.22" />
+ <option name="version" value="1.9.0" />
</component>
</project>
\ No newline at end of file
+<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="FrameworkDetectionExcludesConfiguration">
<textMaps />
</LinkMapSettings>
</component>
+ <component name="PWA">
+ <option name="wasEnabledAtLeastOnce" value="true" />
+ </component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_14" default="true" project-jdk-name="14" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
plugins {
java
- kotlin("jvm") version "1.8.22"
- kotlin("plugin.serialization") version "1.8.22"
+ kotlin("jvm") version "1.9.0"
+ kotlin("plugin.serialization") version "1.9.0"
id("com.github.johnrengelman.shadow") version "7.1.2"
application
}
}
dependencies {
- implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.7.2")
- implementation("org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.7.2")
- implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactive:1.7.2")
- implementation("org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.5.1")
- implementation("org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:1.5.1")
+ implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.7.3")
+ implementation("org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.7.3")
+ implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactive:1.7.3")
+ implementation("org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.6.0")
+ implementation("org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:1.6.0")
- implementation("io.ktor:ktor-server-core-jvm:2.3.3")
- implementation("io.ktor:ktor-server-netty-jvm:2.3.3")
+ implementation("io.ktor:ktor-server-core-jvm:2.3.4")
+ implementation("io.ktor:ktor-server-netty-jvm:2.3.4")
- implementation("io.ktor:ktor-server-caching-headers:2.3.3")
- implementation("io.ktor:ktor-server-call-id:2.3.3")
- implementation("io.ktor:ktor-server-call-logging:2.3.3")
- implementation("io.ktor:ktor-server-conditional-headers:2.3.3")
- implementation("io.ktor:ktor-server-forwarded-header:2.3.3")
- implementation("io.ktor:ktor-server-html-builder:2.3.3")
- implementation("io.ktor:ktor-server-sessions-jvm:2.3.3")
- implementation("io.ktor:ktor-server-status-pages:2.3.3")
+ implementation("io.ktor:ktor-server-caching-headers:2.3.4")
+ implementation("io.ktor:ktor-server-call-id:2.3.4")
+ implementation("io.ktor:ktor-server-call-logging:2.3.4")
+ implementation("io.ktor:ktor-server-conditional-headers:2.3.4")
+ implementation("io.ktor:ktor-server-forwarded-header:2.3.4")
+ implementation("io.ktor:ktor-server-html-builder:2.3.4")
+ implementation("io.ktor:ktor-server-sessions-jvm:2.3.4")
+ implementation("io.ktor:ktor-server-status-pages:2.3.4")
implementation("org.jetbrains.kotlinx:kotlinx-html-jvm:0.9.0")
package info.mechyrdia.lore
-import info.mechyrdia.OWNER_NATION
+import info.mechyrdia.Configuration
+import info.mechyrdia.JsonFileCodec
import info.mechyrdia.auth.createCsrfToken
import info.mechyrdia.data.currentNation
import io.ktor.server.application.*
-import kotlinx.html.DIV
-import kotlinx.html.a
-import kotlinx.html.span
-import kotlinx.html.style
+import io.ktor.util.*
+import kotlinx.html.*
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.builtins.ListSerializer
+import java.io.File
import kotlin.collections.component1
import kotlin.collections.component2
import kotlin.collections.set
+@Serializable
+private data class ExternalLink(
+ val url: String,
+ val text: String
+)
+
+fun loadExternalLinks(): List<NavItem> {
+ val extraLinksFile = File(Configuration.CurrentConfiguration.articleDir).parentFile.combineSafe("externalLinks.json")
+ val extraLinks = JsonFileCodec.decodeFromString(ListSerializer(ExternalLink.serializer()), extraLinksFile.readText())
+ return if (extraLinks.isEmpty())
+ emptyList()
+ else (listOf(NavHead("See Also")) + extraLinks.map { NavLink(it.url, it.text, textIsHtml = true) })
+}
+
suspend fun ApplicationCall.standardNavBar(path: List<String>? = null) = listOf(
NavLink("/", "Lore Intro"),
NavLink("/lore", "Table of Contents")
NavHead("Useful Links"),
NavLink("/comment/help", "Commenting Help"),
NavLink("/comment/recent", "Recent Comments"),
- NavHead("See Also"),
- NavLink("https://nationstates.net/$OWNER_NATION", "Mechyrdia on NationStates"),
- NavLink("https://discord.gg/cvUZMVQsqD", "Forum 7 Discord Server"),
- NavLink("https://laniustrolling.dev/", "The Man Behind Mechyrdia"),
-)
+) + loadExternalLinks()
sealed class NavItem {
protected abstract fun DIV.display()
}
}
-data class NavLink(val to: String, val text: String, val aClasses: String? = null, val linkAttributes: Map<String, String> = emptyMap()) : NavItem() {
+data class NavLink(
+ val to: String,
+ val text: String,
+ val textIsHtml: Boolean = false,
+ val aClasses: String? = null,
+ val linkAttributes: Map<String, String> = emptyMap()
+) : NavItem() {
override fun DIV.display() {
a(href = to, classes = aClasses) {
for ((attrName, attrValue) in linkAttributes)
attributes[attrName] = attrValue
- +text
+ if (textIsHtml)
+ unsafe { raw(text) }
+ else
+ +text
}
}
}