Make external links configurable
authorLanius Trolling <lanius@laniustrolling.dev>
Fri, 15 Sep 2023 14:45:16 +0000 (10:45 -0400)
committerLanius Trolling <lanius@laniustrolling.dev>
Fri, 15 Sep 2023 14:45:16 +0000 (10:45 -0400)
.idea/kotlinc.xml
.idea/misc.xml
build.gradle.kts
src/main/kotlin/info/mechyrdia/lore/view_nav.kt

index 9a55c2de1f41c0bb843e597ca7b85500604c46f7..fdf8d994a6599dd8b64a341af14c598069a10022 100644 (file)
@@ -1,6 +1,6 @@
 <?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
index 96c2c2762c535431958dc513422217a454668f0b..2e9b997f9958cfacb964a82260634c71283ecaf7 100644 (file)
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
 <project version="4">
   <component name="ExternalStorageConfigurationManager" enabled="true" />
   <component name="FrameworkDetectionExcludesConfiguration">
@@ -87,6 +88,9 @@
       <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>
index 84154dc81bb07fc304e6b3c1c3bb1d4a4c0eb030..071745ceb9b068eb75e1246252f4dad965f32401 100644 (file)
@@ -24,8 +24,8 @@ buildscript {
 
 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
 }
@@ -38,23 +38,23 @@ repositories {
 }
 
 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")
        
index 66241e5aa867f67c0a72b2c5c1e348a990a51b0c..30c0e04cb6649b7b85075c96af75d61eebb6d068 100644 (file)
@@ -1,17 +1,33 @@
 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")
@@ -37,11 +53,7 @@ suspend fun ApplicationCall.standardNavBar(path: List<String>? = null) = listOf(
        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()
@@ -57,13 +69,22 @@ data class NavHead(val label: String) : NavItem() {
        }
 }
 
-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
                }
        }
 }