<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="KotlinJpsPluginSettings">
- <option name="version" value="1.8.10" />
+ <option name="version" value="1.8.22" />
</component>
</project>
\ No newline at end of file
plugins {
java
- kotlin("jvm") version "1.8.10"
- kotlin("plugin.serialization") version "1.8.10"
+ kotlin("jvm") version "1.8.22"
+ kotlin("plugin.serialization") version "1.8.22"
id("com.github.johnrengelman.shadow") version "7.1.2"
application
}
}
dependencies {
- implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.6.4")
- implementation("org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.6.4")
- implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactive:1.6.4")
- implementation("org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:1.5.0")
- implementation("org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:1.5.0")
+ 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("io.ktor:ktor-server-core-jvm:2.3.1")
- implementation("io.ktor:ktor-server-netty-jvm:2.3.1")
+ implementation("io.ktor:ktor-server-core-jvm:2.3.2")
+ implementation("io.ktor:ktor-server-netty-jvm:2.3.2")
- implementation("io.ktor:ktor-server-call-id:2.3.1")
- implementation("io.ktor:ktor-server-call-logging:2.3.1")
- implementation("io.ktor:ktor-server-forwarded-header:2.3.1")
- implementation("io.ktor:ktor-server-html-builder:2.3.1")
- implementation("io.ktor:ktor-server-sessions-jvm:2.3.1")
- implementation("io.ktor:ktor-server-status-pages:2.3.1")
+ implementation("io.ktor:ktor-server-call-id:2.3.2")
+ implementation("io.ktor:ktor-server-call-logging:2.3.2")
+ implementation("io.ktor:ktor-server-forwarded-header:2.3.2")
+ implementation("io.ktor:ktor-server-html-builder:2.3.2")
+ implementation("io.ktor:ktor-server-sessions-jvm:2.3.2")
+ implementation("io.ktor:ktor-server-status-pages:2.3.2")
- implementation("org.jetbrains.kotlinx:kotlinx-html-jvm:0.8.1")
+ implementation("org.jetbrains.kotlinx:kotlinx-html-jvm:0.9.0")
implementation("com.samskivert:jmustache:1.15")
implementation("org.apache.groovy:groovy-jsr223:4.0.10")
),
H1(
TextParserTagType.Indirect { _, content, _ ->
- "<h1>$content</h1><script>window.checkRedirectTarget();</script>"
+ "<h1>$content</h1><script>window.checkRedirectTarget('');</script>"
}
),
H2(
TextParserTagType.Indirect { _, content, _ ->
val anchor = headerContentToAnchor(content)
- "</section><section><h2><a id='$anchor'></a>$content</h2>"
+ "</section><section><h2><a id='$anchor'></a>$content</h2><script>window.checkRedirectTarget('#$anchor');</script>"
}
),
H3(
TextParserTagType.Indirect { _, content, _ ->
val anchor = headerContentToAnchor(content)
- "<h3><a id='$anchor'></a>$content</h3>"
+ "<h3><a id='$anchor'></a>$content</h3><script>window.checkRedirectTarget('#$anchor');</script>"
}
),
H4(
TextParserTagType.Indirect { _, content, _ ->
val anchor = headerContentToAnchor(content)
- "<h4><a id='$anchor'></a>$content</h4>"
+ "<h4><a id='$anchor'></a>$content</h4><script>window.checkRedirectTarget('#$anchor');</script>"
}
),
H5(
TextParserTagType.Indirect { _, content, _ ->
val anchor = headerContentToAnchor(content)
- "<h5><a id='$anchor'></a>$content</h5>"
+ "<h5><a id='$anchor'></a>$content</h5><script>window.checkRedirectTarget('#$anchor');</script>"
}
),
H6(
TextParserTagType.Indirect { _, content, _ ->
val anchor = headerContentToAnchor(content)
- "<h6><a id='$anchor'></a>$content</h6>"
+ "<h6><a id='$anchor'></a>$content</h6><script>window.checkRedirectTarget('#$anchor');</script>"
}
),
ALIGN(
val imageUrl = sanitizeLink(content)
val (width, height) = getSizeParam(tagParam)
- val sizeAttrs = getImageSizeAttributes(width, height)
- if (imageUrl.endsWith(".svg")) {
- val imageFile = File(Configuration.CurrentConfiguration.assetDir, "images/$imageUrl")
- val imageSvg = imageFile.readText().replace("<svg", "<svg$sizeAttrs")
-
- imageSvg
- } else
- "<a class=\"thumb\" href=\"/assets/images/$imageUrl\" title=\"Click to view full size\"><img src=\"/assets/images/$imageUrl\"$sizeAttrs/></a>"
+ if (imageUrl.endsWith(".svg"))
+ File(Configuration.CurrentConfiguration.assetDir, "images/$imageUrl")
+ .readText()
+ .replace("<svg", "<svg${getImageSizeAttributes(width, height)}")
+ else
+ "<script>window.appendImageThumb('/assets/images/$imageUrl', '${getImageSizeStyleValue(width, height)}');</script>"
}
),
MODEL(
} ?: (null to null)
fun getTableSizeAttributes(width: Int?, height: Int?) = (width?.let { " colspan=\"$it\"" } ?: "") + (height?.let { " rowspan=\"$it\"" } ?: "")
-fun getImageSizeAttributes(width: Int?, height: Int?) = " style=\"" + (width?.let { "width: calc(var(--media-size-unit) * $it);" } ?: "") + (height?.let { "height: calc(var(--media-size-unit) * $it);" } ?: "") + "\""
+fun getImageSizeStyleValue(width: Int?, height: Int?) = (width?.let { "width: calc(var(--media-size-unit) * $it);" } ?: "") + (height?.let { "height: calc(var(--media-size-unit) * $it);" } ?: "")
+fun getImageSizeAttributes(width: Int?, height: Int?) = " style=\"${getImageSizeStyleValue(width, height)}\""
val NON_ANCHOR_CHAR = Regex("[^a-zA-Z\\d\\-]")
val INSIDE_TAG_TEXT = Regex("\\[.*?]")
enum class TextParserToCBuilderTag(val type: TextParserTagType<TableOfContentsBuilder>) {
H1(
- TextParserTagType.Indirect<TableOfContentsBuilder> { _, content, builder ->
+ TextParserTagType.Indirect { _, content, builder ->
builder.add(headerContentToLabel(content), 0, headerContentToAnchor(content))
"[h1]$content[/h1]"
}
),
H2(
- TextParserTagType.Indirect<TableOfContentsBuilder> { _, content, builder ->
+ TextParserTagType.Indirect { _, content, builder ->
builder.add(headerContentToLabel(content), 1, headerContentToAnchor(content))
"[h2]$content[/h2]"
}
),
H3(
- TextParserTagType.Indirect<TableOfContentsBuilder> { _, content, builder ->
+ TextParserTagType.Indirect { _, content, builder ->
builder.add(headerContentToLabel(content), 2, headerContentToAnchor(content))
"[h3]$content[/h3]"
}
),
H4(
- TextParserTagType.Indirect<TableOfContentsBuilder> { _, content, builder ->
+ TextParserTagType.Indirect { _, content, builder ->
builder.add(headerContentToLabel(content), 3, headerContentToAnchor(content))
"[h4]$content[/h4]"
}
),
H5(
- TextParserTagType.Indirect<TableOfContentsBuilder> { _, content, builder ->
+ TextParserTagType.Indirect { _, content, builder ->
builder.add(headerContentToLabel(content), 4, headerContentToAnchor(content))
"[h5]$content[/h5]"
}
),
H6(
- TextParserTagType.Indirect<TableOfContentsBuilder> { _, content, builder ->
+ TextParserTagType.Indirect { _, content, builder ->
builder.add(headerContentToLabel(content), 5, headerContentToAnchor(content))
"[h6]$content[/h6]"
}
}
});
+ window.appendImageThumb = function (src, sizeStyle) {
+ // Image previewing (1)
+ const imgElement = document.createElement("img");
+ imgElement.src = src;
+ imgElement.setAttribute("title", "Click to view full size");
+ imgElement.setAttribute("style", sizeStyle);
+
+ imgElement.onclick = e => {
+ e.preventDefault();
+
+ const thumbView = document.getElementById("thumb-view");
+ const thumbViewImg = thumbView.getElementsByTagName("img")[0];
+ thumbViewImg.src = e.currentTarget.src;
+ thumbView.classList.add("visible");
+ }
+
+ document.currentScript.after(imgElement);
+ };
+
window.addEventListener("load", function () {
- // Image previewing
+ // Image previewing (2)
document.getElementById("thumb-view").addEventListener("click", e => {
e.preventDefault();
e.currentTarget.classList.remove("visible");
e.currentTarget.getElementsByTagName("img")[0].src = "";
});
-
- const thumbs = document.querySelectorAll("a.thumb");
- for (const thumb of thumbs) {
- thumb.onclick = e => {
- e.preventDefault();
-
- const thumbView = document.getElementById("thumb-view");
- const thumbViewImg = thumbView.getElementsByTagName("img")[0];
- thumbViewImg.src = e.currentTarget.getAttribute("href");
- thumbView.classList.add("visible");
- };
- }
});
window.addEventListener("load", function () {
pElement.append(aElement);
document.currentScript.after(pElement);
} else {
- document.cookie = "REDIRECTED_FROM=" + window.location.pathname + "; SameSite=Lax; Secure";
+ window.localStorage.setItem("redirectedFrom", window.location.pathname);
window.location = redirectTo;
}
};
- window.checkRedirectTarget = function () {
- const redirectSourceValues = document.cookie.split(';').filter(value => value.trim().startsWith("REDIRECTED_FROM="));
- if (redirectSourceValues.length > 0) {
- const redirectSource = new URL(redirectSourceValues[0].trim().substring("REDIRECTED_FROM=".length), window.location.origin);
+ window.checkRedirectTarget = function (anchorHash) {
+ const redirectTargetValue = window.location.hash;
+ if (redirectTargetValue !== anchorHash) return;
+
+ const redirectSourceValue = window.localStorage.getItem("redirectedFrom");
+ if (redirectSourceValue != null) {
+ const redirectSource = new URL(redirectSourceValue, window.location.origin);
if (redirectSource.search.length > 0) {
redirectSource.search += "&redirect=no";
} else {
document.currentScript.after(pElement);
}
- document.cookie = "REDIRECTED_FROM=; Expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=Lax; Secure";
+ window.localStorage.removeItem("redirectedFrom");
};
})();