Change Tylan numerals
authorLanius Trolling <lanius@laniustrolling.dev>
Wed, 14 Dec 2022 22:31:55 +0000 (17:31 -0500)
committerLanius Trolling <lanius@laniustrolling.dev>
Wed, 14 Dec 2022 22:31:55 +0000 (17:31 -0500)
build.gradle.kts
src/main/kotlin/info/mechyrdia/Factbooks.kt
src/main/kotlin/info/mechyrdia/lore/tylan_language.kt
src/main/resources/static/font/tylan-language-alphabet-3.woff
src/main/resources/static/style.css

index a8ce5c10bcfb019ea41fa739833ac8655070ab1c..ea7c65e9611ebc8a896c17f09888c2fe5aa94d69 100644 (file)
@@ -22,13 +22,14 @@ dependencies {
        implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.4.1")
        implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.1")
        
-       implementation("io.ktor:ktor-server-netty:2.1.3")
-       implementation("io.ktor:ktor-server-html-builder:2.1.3")
+       implementation("io.ktor:ktor-server-netty:2.2.1")
+       implementation("io.ktor:ktor-server-html-builder:2.2.1")
        
-       implementation("io.ktor:ktor-server-call-id:2.1.3")
-       implementation("io.ktor:ktor-server-call-logging:2.1.3")
-       implementation("io.ktor:ktor-server-forwarded-header:2.1.3")
-       implementation("io.ktor:ktor-server-status-pages:2.1.3")
+       implementation("io.ktor:ktor-server-call-id:2.2.1")
+       implementation("io.ktor:ktor-server-call-logging:2.2.1")
+       implementation("io.ktor:ktor-server-forwarded-header:2.2.1")
+       implementation("io.ktor:ktor-server-sessions-jvm:2.2.1")
+       implementation("io.ktor:ktor-server-status-pages:2.2.1")
        
        implementation("org.jetbrains.kotlinx:kotlinx-html-jvm:0.8.0")
        
index 8f6db51643520e9f3072c831fe5ba18aaec3c89f..19dff0e130f84085c5515d1fac5076dde85a8ea2 100644 (file)
@@ -1,3 +1,5 @@
+@file:JvmName("Factbooks")
+
 package info.mechyrdia
 
 import info.mechyrdia.lore.*
@@ -15,100 +17,112 @@ import io.ktor.server.plugins.statuspages.*
 import io.ktor.server.request.*
 import io.ktor.server.response.*
 import io.ktor.server.routing.*
+import io.ktor.server.sessions.*
+import io.ktor.util.*
 import org.slf4j.event.Level
 import java.io.File
 import java.io.IOException
 import java.util.concurrent.atomic.AtomicLong
 
-object Factbooks {
-       @JvmStatic
-       fun main(args: Array<String>) {
-               System.setProperty("logback.statusListenerClass", "ch.qos.logback.core.status.NopStatusListener")
+fun main() {
+       System.setProperty("logback.statusListenerClass", "ch.qos.logback.core.status.NopStatusListener")
+       
+       System.setProperty("io.ktor.development", "false")
+       
+       embeddedServer(Netty, port = Configuration.CurrentConfiguration.port, host = Configuration.CurrentConfiguration.host, module = Application::factbooks).start(wait = true)
+}
+
+fun Application.factbooks() {
+       install(IgnoreTrailingSlash)
+       install(XForwardedHeaders)
+       
+       install(CallId) {
+               val counter = AtomicLong(0)
+               generate {
+                       "call-${counter.incrementAndGet().toULong()}-${System.currentTimeMillis()}"
+               }
+       }
+       
+       install(CallLogging) {
+               level = Level.INFO
                
-               System.setProperty("io.ktor.development", "false")
+               callIdMdc("ktor-call-id")
                
-               embeddedServer(Netty, port = Configuration.CurrentConfiguration.port, host = Configuration.CurrentConfiguration.host) {
-                       install(IgnoreTrailingSlash)
-                       install(XForwardedHeaders)
-                       
-                       install(CallId) {
-                               val counter = AtomicLong(0)
-                               generate {
-                                       "call-${counter.incrementAndGet().toULong()}-${System.currentTimeMillis()}"
-                               }
-                       }
-                       
-                       install(CallLogging) {
-                               level = Level.INFO
-                               
-                               callIdMdc("ktor-call-id")
-                               
-                               format { call ->
-                                       "Call #${call.callId} Client ${call.request.origin.remoteHost} `${call.request.userAgent()}` Request ${call.request.httpMethod.value} ${call.request.uri} Response ${call.response.status()}"
-                               }
-                       }
+               format { call ->
+                       "Call #${call.callId} Client ${call.request.origin.remoteHost} `${call.request.userAgent()}` Request ${call.request.httpMethod.value} ${call.request.uri} Response ${call.response.status()}"
+               }
+       }
+       
+       /*
+       install(Sessions) {
+               cookie<UserSession>("USER_SESSION", SessionStorageMongoDB()) {
+                       identity { Id<UserSession>().id }
                        
-                       install(StatusPages) {
-                               status(HttpStatusCode.NotFound) { call, _ ->
-                                       call.respondHtml(HttpStatusCode.NotFound, call.error404())
-                               }
-                               
-                               exception<HttpRedirectException> { call, (url, permanent) ->
-                                       call.respondRedirect(url, permanent)
-                               }
-                               exception<MissingRequestParameterException> { call, _ ->
-                                       call.respondHtml(HttpStatusCode.BadRequest, call.error400())
-                               }
-                               exception<NullPointerException> { call, _ ->
-                                       call.respondHtml(HttpStatusCode.NotFound, call.error404())
-                               }
-                               exception<IOException> { call, _ ->
-                                       call.respondHtml(HttpStatusCode.NotFound, call.error404())
-                               }
-                               
-                               exception<Throwable> { call, ex ->
-                                       call.application.log.error("Got uncaught exception from serving call ${call.callId}", ex)
-                                       
-                                       call.respondHtml(HttpStatusCode.InternalServerError, call.error500())
-                                       throw ex
-                               }
-                       }
+                       cookie.extensions["SameSite"] = "lax"
+                       cookie.extensions["Secure"] = null
+               }
+       }
+       */
+       
+       install(StatusPages) {
+               status(HttpStatusCode.NotFound) { call, _ ->
+                       call.respondHtml(HttpStatusCode.NotFound, call.error404())
+               }
+               
+               exception<HttpRedirectException> { call, (url, permanent) ->
+                       call.respondRedirect(url, permanent)
+               }
+               exception<MissingRequestParameterException> { call, _ ->
+                       call.respondHtml(HttpStatusCode.BadRequest, call.error400())
+               }
+               exception<NullPointerException> { call, _ ->
+                       call.respondHtml(HttpStatusCode.NotFound, call.error404())
+               }
+               exception<IOException> { call, _ ->
+                       call.respondHtml(HttpStatusCode.NotFound, call.error404())
+               }
+               
+               exception<Throwable> { call, ex ->
+                       call.application.log.error("Got uncaught exception from serving call ${call.callId}", ex)
                        
-                       routing {
-                               get("/") {
-                                       redirect("/lore")
-                               }
-                               
-                               static("/static") {
-                                       resources("static")
-                               }
-                               
-                               get("/lore/{path...}") {
-                                       call.respondHtml(HttpStatusCode.OK, call.loreArticlePage())
-                               }
-                               
-                               static("/assets") {
-                                       files(File(Configuration.CurrentConfiguration.assetDir))
-                               }
-                               
-                               get("/change-theme") {
-                                       call.respondHtml(HttpStatusCode.OK, call.changeThemePage())
-                               }
-                               
-                               post("/change-theme") {
-                                       val newTheme = when (call.receiveParameters()["theme"]) {
-                                               "light" -> "light"
-                                               "dark" -> "dark"
-                                               else -> "system"
-                                       }
-                                       call.response.cookies.append("factbook-theme", newTheme, maxAge = Int.MAX_VALUE.toLong())
-                                       redirect("/lore")
-                               }
-                               
-                               post("/tylan-lang") {
-                                       call.respondText(TylanAlphabet.tylanToFontAlphabet(call.receiveText()))
-                               }
+                       call.respondHtml(HttpStatusCode.InternalServerError, call.error500())
+                       throw ex
+               }
+       }
+       
+       routing {
+               get("/") {
+                       redirect("/lore")
+               }
+               
+               static("/static") {
+                       resources("static")
+               }
+               
+               get("/lore/{path...}") {
+                       call.respondHtml(HttpStatusCode.OK, call.loreArticlePage())
+               }
+               
+               static("/assets") {
+                       files(File(Configuration.CurrentConfiguration.assetDir))
+               }
+               
+               get("/change-theme") {
+                       call.respondHtml(HttpStatusCode.OK, call.changeThemePage())
+               }
+               
+               post("/change-theme") {
+                       val newTheme = when (call.receiveParameters()["theme"]) {
+                               "light" -> "light"
+                               "dark" -> "dark"
+                               else -> "system"
                        }
-               }.start(wait = true)
+                       call.response.cookies.append("factbook-theme", newTheme, maxAge = Int.MAX_VALUE.toLong())
+                       redirect("/lore")
+               }
+               
+               post("/tylan-lang") {
+                       call.respondText(TylanAlphabet.tylanToFontAlphabet(call.receiveText()))
+               }
        }
 }
index 2d0bb12524bd00874db0e4ccb3987cc8f48dcafc..1a88a51037b3d0e41b3cb8e2fe0ba56894874638 100644 (file)
@@ -11,6 +11,9 @@ object TylanAlphabet {
        )
        
        private val replacements = listOf(
+               Regex("([0-9xy]+)(?!\\s)") to "$1 ",
+               Regex("(?<!\\s)([0-9xy]+)") to " $1",
+               
                Regex("([a-pr-v'])m(?![\\w'])") to "$1A",
                Regex("([a-pr-v'])n(?![\\w'])") to "$1E",
                Regex("([a-ps-v'])r(?![\\w'])") to "$1H",
index b0ce07cac86bceddc2c9c1de158648296d94152a..313bb3f7368d8b934a464fc799c08210cc4d198c 100644 (file)
Binary files a/src/main/resources/static/font/tylan-language-alphabet-3.woff and b/src/main/resources/static/font/tylan-language-alphabet-3.woff differ
index d8b731a9168aa09d2b86df415031baacb2e73b6c..023c30798c0ffa9ac215d69c18dc5cd30c845748 100644 (file)
@@ -601,7 +601,7 @@ textarea:invalid {
        border-bottom-color: var(--err-ul);
 }
 
-input[type=submit] {
+button, input[type=submit] {
        background-color: var(--btn-bg);
        border: none;
        border-radius: 0.3em;
@@ -614,15 +614,15 @@ input[type=submit] {
        padding: 0.85em 1.15em;
 }
 
-input[type=submit]:hover {
+button:hover, input[type=submit]:hover {
        background-color: var(--btn-h-bg);
 }
 
-input[type=submit]:active {
+button:active, input[type=submit]:active {
        background-color: var(--btn-a-bg);
 }
 
-input[type=submit].evil {
+button.evil, input[type=submit].evil {
        background-color: var(--evil-btn-bg);
        border: none;
        border-radius: 0.3em;
@@ -635,14 +635,16 @@ input[type=submit].evil {
        padding: 0.85em 1.15em;
 }
 
-input[type=submit].evil:hover {
+button.evil:hover, input[type=submit].evil:hover {
        background-color: var(--evil-btn-h-bg);
 }
 
-input[type=submit].evil:active {
+button.evil:active, input[type=submit].evil:active {
        background-color: var(--evil-btn-a-bg);
 }
 
+button:disabled,
+button.evil:disabled,
 input[type=submit]:disabled,
 input[type=submit].evil:disabled {
        background-color: var(--btn-na-bg);