From: Lanius Trolling Date: Wed, 2 Aug 2023 16:27:22 +0000 (-0400) Subject: Add OpenGraph data X-Git-Url: https://gitweb.starshipfights.net/?a=commitdiff_plain;h=aa004fbcb7c1979359881df3a603a9a22d6e5177;p=factbooks Add OpenGraph data --- diff --git a/graphics/icon.svg b/graphics/icon.svg deleted file mode 100644 index a2889bf..0000000 --- a/graphics/icon.svg +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - diff --git a/src/main/kotlin/info/mechyrdia/lore/parser_tags.kt b/src/main/kotlin/info/mechyrdia/lore/parser_tags.kt index 4b61fb6..87039f1 100644 --- a/src/main/kotlin/info/mechyrdia/lore/parser_tags.kt +++ b/src/main/kotlin/info/mechyrdia/lore/parser_tags.kt @@ -141,6 +141,17 @@ enum class TextParserFormattingTag(val type: TextParserTagType) { ) ), + // Metadata + DESC( + TextParserTagType.Direct( + { _, _ -> "" }, + { "" }, + ) + ), + THUMB( + TextParserTagType.Indirect { _, _, _ -> "" } + ), + // Resource showing IMAGE( TextParserTagType.Indirect { tagParam, content, _ -> @@ -379,3 +390,6 @@ val INSIDE_TAG_TEXT = Regex("\\[.*?]") fun headerContentToLabel(content: String) = TextParserState.uncensorText(content.replace(INSIDE_TAG_TEXT, "")) fun headerContentToAnchor(content: String) = headerContentToLabel(content).replace(NON_ANCHOR_CHAR, "-") + +fun imagePathToOpenGraphValue(path: String) = "https://mechyrdia.info/assets/images/${sanitizeLink(path)}" +fun descriptionContentToPlainText(content: String) = TextParserState.uncensorText(content.replace(INSIDE_TAG_TEXT, "")) diff --git a/src/main/kotlin/info/mechyrdia/lore/parser_toc.kt b/src/main/kotlin/info/mechyrdia/lore/parser_toc.kt index c1e837c..8918065 100644 --- a/src/main/kotlin/info/mechyrdia/lore/parser_toc.kt +++ b/src/main/kotlin/info/mechyrdia/lore/parser_toc.kt @@ -5,7 +5,7 @@ class TableOfContentsBuilder { private val levels = mutableListOf() private val links = mutableListOf() - fun add(text: String, level: Int, toAnchor: String) { + fun addHeader(text: String, level: Int, toAnchor: String) { if (level == 0) { if (title == null) title = text @@ -25,8 +25,28 @@ class TableOfContentsBuilder { links.plusAssign(NavLink("#$toAnchor", "$number. $text", aClasses = "left")) } + private var description: String? = null + private var image: String? = null + + fun addDescription(plainText: String) { + description = description.orEmpty() + plainText + } + + fun addImage(path: String, overWrite: Boolean = false) { + if (overWrite || image == null) + image = path + } + fun toPageTitle() = title ?: MISSING_TITLE + fun toOpenGraph() = title?.let { title -> + description?.let { desc -> + image?.let { image -> + OpenGraphData(title, desc, image) + } + } + } + fun toNavBar(): List = listOf(NavLink("#page-top", title ?: MISSING_TITLE, aClasses = "left")) + links.toList() companion object { @@ -37,39 +57,57 @@ class TableOfContentsBuilder { enum class TextParserToCBuilderTag(val type: TextParserTagType) { H1( TextParserTagType.Indirect { _, content, builder -> - builder.add(headerContentToLabel(content), 0, headerContentToAnchor(content)) + builder.addHeader(headerContentToLabel(content), 0, headerContentToAnchor(content)) "[h1]$content[/h1]" } ), H2( TextParserTagType.Indirect { _, content, builder -> - builder.add(headerContentToLabel(content), 1, headerContentToAnchor(content)) + builder.addHeader(headerContentToLabel(content), 1, headerContentToAnchor(content)) "[h2]$content[/h2]" } ), H3( TextParserTagType.Indirect { _, content, builder -> - builder.add(headerContentToLabel(content), 2, headerContentToAnchor(content)) + builder.addHeader(headerContentToLabel(content), 2, headerContentToAnchor(content)) "[h3]$content[/h3]" } ), H4( TextParserTagType.Indirect { _, content, builder -> - builder.add(headerContentToLabel(content), 3, headerContentToAnchor(content)) + builder.addHeader(headerContentToLabel(content), 3, headerContentToAnchor(content)) "[h4]$content[/h4]" } ), H5( TextParserTagType.Indirect { _, content, builder -> - builder.add(headerContentToLabel(content), 4, headerContentToAnchor(content)) + builder.addHeader(headerContentToLabel(content), 4, headerContentToAnchor(content)) "[h5]$content[/h5]" } ), H6( TextParserTagType.Indirect { _, content, builder -> - builder.add(headerContentToLabel(content), 5, headerContentToAnchor(content)) + builder.addHeader(headerContentToLabel(content), 5, headerContentToAnchor(content)) "[h6]$content[/h6]" } + ), + DESC( + TextParserTagType.Indirect { _, content, builder -> + builder.addDescription(descriptionContentToPlainText(content)) + content + } + ), + IMAGE( + TextParserTagType.Indirect { param, content, builder -> + builder.addImage(imagePathToOpenGraphValue(content)) + "[image=$param]$content[/image]" + } + ), + THUMB( + TextParserTagType.Indirect { _, content, builder -> + builder.addImage(imagePathToOpenGraphValue(content), true) + "" + } ); companion object { diff --git a/src/main/kotlin/info/mechyrdia/lore/view_og.kt b/src/main/kotlin/info/mechyrdia/lore/view_og.kt new file mode 100644 index 0000000..e6c745c --- /dev/null +++ b/src/main/kotlin/info/mechyrdia/lore/view_og.kt @@ -0,0 +1,30 @@ +package info.mechyrdia.lore + +import io.ktor.server.application.* +import io.ktor.server.request.* +import kotlinx.html.HEAD +import kotlinx.html.meta +import kotlinx.serialization.Serializable + +@Serializable +data class OpenGraphData( + val title: String, + val desc: String, + val image: String +) + +fun HEAD.ogProperty(property: String, content: String) { + meta { + attributes["property"] = "og:$property" + attributes["content"] = content + } +} + +context(ApplicationCall) +fun HEAD.renderOgData(data: OpenGraphData) { + ogProperty("title", data.title) + ogProperty("type", "website") + ogProperty("description", data.desc) + ogProperty("image", data.image) + ogProperty("url", "https://mechyrdia.info/${request.path().removePrefix("/")}") +} diff --git a/src/main/kotlin/info/mechyrdia/lore/view_tpl.kt b/src/main/kotlin/info/mechyrdia/lore/view_tpl.kt index c1e5809..d42afc8 100644 --- a/src/main/kotlin/info/mechyrdia/lore/view_tpl.kt +++ b/src/main/kotlin/info/mechyrdia/lore/view_tpl.kt @@ -36,7 +36,7 @@ private val images = listOf( "panel.png", ) -fun ApplicationCall.page(pageTitle: String, navBar: List? = null, sidebar: Sidebar? = null, content: SECTIONS.() -> Unit): HTML.() -> Unit { +fun ApplicationCall.page(pageTitle: String, navBar: List? = null, sidebar: Sidebar? = null, ogData: OpenGraphData? = null, content: SECTIONS.() -> Unit): HTML.() -> Unit { val theme = request.cookies["FACTBOOK_THEME"] return { @@ -50,6 +50,10 @@ fun ApplicationCall.page(pageTitle: String, navBar: List? = null, sideb meta(charset = "utf-8") meta(name = "viewport", content = "width=device-width, initial-scale=1.0") + ogData?.let { data -> + renderOgData(data) + } + script(src = "/static/obj-viewer/three.js") {} script(src = "/static/obj-viewer/three-examples.js") {} script(src = "/static/obj-viewer/OrbitControls.js") {} diff --git a/src/main/kotlin/info/mechyrdia/lore/views_lore.kt b/src/main/kotlin/info/mechyrdia/lore/views_lore.kt index 5458a42..f92dcf7 100644 --- a/src/main/kotlin/info/mechyrdia/lore/views_lore.kt +++ b/src/main/kotlin/info/mechyrdia/lore/views_lore.kt @@ -1,6 +1,7 @@ package info.mechyrdia.lore import info.mechyrdia.Configuration +import info.mechyrdia.JsonFileCodec import info.mechyrdia.data.* import io.ktor.server.application.* import io.ktor.util.* @@ -11,10 +12,13 @@ import kotlinx.html.* import java.io.File suspend fun ApplicationCall.loreIntroPage(): HTML.() -> Unit { + val metaJsonFile = File(Configuration.CurrentConfiguration.articleDir).parentFile.combineSafe("introMeta.json") + val metaData = JsonFileCodec.decodeFromString(OpenGraphData.serializer(), metaJsonFile.readText()) + val htmlFile = File(Configuration.CurrentConfiguration.articleDir).parentFile.combineSafe("intro.html") val fileHtml = htmlFile.readText() - return page("Welcome to Mechyrdia", standardNavBar(), null) { + return page(metaData.title, standardNavBar(), null, metaData) { section { a { id = "page-top" } unsafe { raw(fileHtml) } @@ -75,7 +79,7 @@ suspend fun ApplicationCall.loreArticlePage(): HTML.() -> Unit { val navbar = standardNavBar(pagePathParts) val sidebar = PageNavSidebar(pageNav) - return page(pageToC.toPageTitle(), navbar, sidebar) { + return page(pageToC.toPageTitle(), navbar, sidebar, pageToC.toOpenGraph()) { section { a { id = "page-top" } unsafe { raw(pageHtml) } diff --git a/src/main/resources/static/images/icon.png b/src/main/resources/static/images/icon.png index a51c89e..6e083e7 100644 Binary files a/src/main/resources/static/images/icon.png and b/src/main/resources/static/images/icon.png differ