From ca1b378a1455b1fae6248037318b971aa39dc622 Mon Sep 17 00:00:00 2001 From: Walter Oggioni Date: Fri, 1 Mar 2024 06:10:54 +0800 Subject: [PATCH] use khtml library --- gradle.properties | 4 +- jpacrepo-frontend/build.gradle | 1 + .../net/woggioni/jpacrepo/DocumentWalk.kt | 182 ------------------ .../kotlin/net/woggioni/jpacrepo/Main.kt | 43 ++--- 4 files changed, 23 insertions(+), 207 deletions(-) delete mode 100644 jpacrepo-frontend/src/jsMain/kotlin/net/woggioni/jpacrepo/DocumentWalk.kt diff --git a/gradle.properties b/gradle.properties index d65171e..8b029bf 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ org.gradle.parallel=true org.gradle.caching=true -jpacrepo.version=2024.02.24 +jpacrepo.version=2024.03.01 -lys.version=2024.02.24 +lys.version=2024.03.01 diff --git a/jpacrepo-frontend/build.gradle b/jpacrepo-frontend/build.gradle index bf708cd..6489823 100644 --- a/jpacrepo-frontend/build.gradle +++ b/jpacrepo-frontend/build.gradle @@ -18,6 +18,7 @@ kotlin { jsMain { dependencies { implementation catalog.klevtree + implementation catalog.khtml implementation group: 'org.jetbrains.kotlinx', name: 'kotlinx-serialization-json', version: '1.6.2' implementation(npm("bootstrap", "5.3.2")) diff --git a/jpacrepo-frontend/src/jsMain/kotlin/net/woggioni/jpacrepo/DocumentWalk.kt b/jpacrepo-frontend/src/jsMain/kotlin/net/woggioni/jpacrepo/DocumentWalk.kt deleted file mode 100644 index 14eb999..0000000 --- a/jpacrepo-frontend/src/jsMain/kotlin/net/woggioni/jpacrepo/DocumentWalk.kt +++ /dev/null @@ -1,182 +0,0 @@ -package net.woggioni.jpacrepo - -import kotlin.coroutines.Continuation -import kotlin.coroutines.CoroutineContext -import kotlin.coroutines.EmptyCoroutineContext -import kotlin.coroutines.resume -import kotlin.coroutines.resumeWithException -import kotlin.coroutines.startCoroutine -import kotlin.coroutines.suspendCoroutine -import kotlin.js.Promise -import org.w3c.dom.Document -import org.w3c.dom.Element -import org.w3c.dom.events.Event - -object HtmlUtils { - fun Element.removeChildren() { - while (true) { - removeChild(firstChild ?: break) - } - } - - fun Element.on(eventName : String, eventListener : (Event) -> Unit) { - addEventListener(eventName, eventListener) - } - - fun launch(block: suspend () -> Unit) { - block.startCoroutine(object : Continuation { - override val context: CoroutineContext get() = EmptyCoroutineContext - override fun resumeWith(result: Result) {} - }) - } - - suspend fun Promise.await(): T = suspendCoroutine { cont -> - then({ cont.resume(it) }, { cont.resumeWithException(it) }) - } -} - -class HtmlBuilder private constructor(private val doc : Document, val el: Element) { - - companion object { - fun of(doc : Document, el: Element, cb : HtmlBuilder.(el : Element) -> T) : T { - return HtmlBuilder(doc, el).cb(el) - } - } - - private inline fun dfd( - name : String, - attrs : Map, - cb : HtmlBuilder.(el : Element) -> T) : T { - val child = doc.createElement(name) - for((key, value) in attrs) { - child.setAttribute(key, value) - } - el.appendChild(child) - return HtmlBuilder(doc, child).cb(child) - } - - fun html(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("html", attrs, cb) - fun head(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("head", attrs, cb) - fun body(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("body", attrs, cb) - - fun use(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("use", attrs, cb) - fun svg(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("svg", attrs, cb) - fun div(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("div", attrs, cb) - fun header(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("header", attrs, cb) - fun main(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("main", attrs, cb) - fun footer(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("footer", attrs, cb) - fun a(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("a", attrs, cb) - fun meta(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("meta", attrs, cb) - fun script(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("script", attrs, cb) - fun link(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("link", attrs, cb) - fun title(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("title", attrs, cb) - fun p(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("p", attrs, cb) - fun span(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("span", attrs, cb) - fun i(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("i", attrs, cb) - fun del(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("del", attrs, cb) - fun s(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("s", attrs, cb) - fun ins(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("ins", attrs, cb) - fun u(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("u", attrs, cb) - fun b(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("b", attrs, cb) - fun small(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("small", attrs, cb) - fun strong(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("strong", attrs, cb) - fun em(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("em", attrs, cb) - fun mark(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("mark", attrs, cb) - fun obj(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("object", attrs, cb) - fun h1(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("h1", attrs, cb) - fun h2(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("h2", attrs, cb) - fun h3(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("h3", attrs, cb) - fun h4(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("h4", attrs, cb) - fun h5(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("h5", attrs, cb) - fun h6(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("h6", attrs, cb) - fun table(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("table", attrs, cb) - fun thead(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("thead", attrs, cb) - fun tbody(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("tbody", attrs, cb) - fun tfoot(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("tfoot", attrs, cb) - fun tr(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("tr", attrs, cb) - fun th(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("th", attrs, cb) - fun td(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("td", attrs, cb) - fun ol(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("ol", attrs, cb) - fun ul(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("ul", attrs, cb) - fun li(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("li", attrs, cb) - fun img(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("img", attrs, cb) - fun form(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("form", attrs, cb) - fun label(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("label", attrs, cb) - fun button(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("button", attrs, cb) - fun input(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("input", attrs, cb) - fun select(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("select", attrs, cb) - fun option(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("option", attrs, cb) - fun meter(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("meter", attrs, cb) - fun nav(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("nav", attrs, cb) - fun menu(attrs : Map = emptyMap(), - cb : HtmlBuilder.(el : Element) -> T) : T = dfd("menu", attrs, cb) - - - fun classes(vararg classes : String) { - for(cls in classes) el.classList.add(cls) - } - - fun attr(key: String, value : String) { - el.setAttribute(key, value) - } - - fun text(txt : String) { - el.appendChild(doc.createTextNode(txt)) - } - - fun on(eventName : String, cb: (Event) -> Unit) { - el.addEventListener(eventName, cb) - } -} diff --git a/jpacrepo-frontend/src/jsMain/kotlin/net/woggioni/jpacrepo/Main.kt b/jpacrepo-frontend/src/jsMain/kotlin/net/woggioni/jpacrepo/Main.kt index aeff694..7f79ec4 100644 --- a/jpacrepo-frontend/src/jsMain/kotlin/net/woggioni/jpacrepo/Main.kt +++ b/jpacrepo-frontend/src/jsMain/kotlin/net/woggioni/jpacrepo/Main.kt @@ -6,11 +6,12 @@ import kotlinx.browser.document import kotlinx.browser.window import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json -import net.woggioni.jpacrepo.HtmlUtils.await -import net.woggioni.jpacrepo.HtmlUtils.launch -import net.woggioni.jpacrepo.HtmlUtils.on -import net.woggioni.jpacrepo.HtmlUtils.removeChildren import net.woggioni.jpacrepo.common.JpacrepoCommons.toHexString +import net.woggioni.khtml.Khtml +import net.woggioni.khtml.Khtml.Companion.await +import net.woggioni.khtml.Khtml.Companion.launch +import net.woggioni.khtml.Khtml.Companion.on +import net.woggioni.khtml.Khtml.Companion.removeChildren import net.woggioni.klevtree.LevTrie import org.w3c.dom.CustomEvent import org.w3c.dom.Element @@ -132,7 +133,7 @@ suspend fun buildTable(root: Element, searchTerm: String, commonElement: Element while (children.length > 0) { children[0]!!.remove() } - HtmlBuilder.of(document, root) { + Khtml.of(document, root) { table { classes("table", "table-striped", "pkgtable") thead { @@ -209,9 +210,9 @@ suspend fun buildTable(root: Element, searchTerm: String, commonElement: Element ?.let { it[selectedVersion] } availablePackages?.keys?.first() } - var selectedCompressionFormat = getFirstAvailableCompressionFormat() + var selectedCompressionFormat: CompressionFormat? - fun HtmlBuilder.createCompressionFormatDropdown() { + fun Khtml.createCompressionFormatDropdown() { val availablePackages = packages ?.let { it[selectedVersion] } availablePackages?.keys?.let { compressionFormats -> @@ -236,24 +237,21 @@ suspend fun buildTable(root: Element, searchTerm: String, commonElement: Element val compressionFormatCell = td { createCompressionFormatDropdown() - el } val fileNameCell = td { selectedPackage?.let { text(it.second.fileName) } - el } val sizeCell = td { selectedPackage?.let { text(it.second.size.toHumanReadableByteSize()) } - el } - on(REFRESH_TABLE_ROW_EVENT_NAME) { evt -> + on(REFRESH_TABLE_ROW_EVENT_NAME) { selectedCompressionFormat = getFirstAvailableCompressionFormat() compressionFormatCell.removeChildren() - HtmlBuilder.of(document, compressionFormatCell) { + Khtml.of(document, compressionFormatCell) { createCompressionFormatDropdown() } selectedPackage = archive.pkgMap[arch]?.let { @@ -278,9 +276,9 @@ suspend fun buildTable(root: Element, searchTerm: String, commonElement: Element } } -private fun HtmlBuilder.buildPackageSearchSection(commonElement: Element) { - val root = el +private fun Khtml.buildPackageSearchSection(commonElement: Element) { var selectedPackageName: String? = null + val root = element div { classes("row", "g-5") div { @@ -354,7 +352,7 @@ private fun HtmlBuilder.buildPackageSearchSection(commonElement: Element) { } div { table -> classes("row", "align-items-md-stretch") - root.on(REFRESH_TABLE_EVENT_NAME) { evt -> + root.on(REFRESH_TABLE_EVENT_NAME) { evt : Event -> launch { (evt as? CustomEvent)?.let { pnuv -> table.let { t -> @@ -371,7 +369,7 @@ private fun HtmlBuilder.buildPackageSearchSection(commonElement: Element) { fun main(vararg args: String) { js("require ('./scss/styles.scss');") - HtmlBuilder.of(document, document.body as HTMLElement) { + Khtml.of(document, document.body as HTMLElement) { main { main -> div { classes("container", "py-4") @@ -392,7 +390,7 @@ fun main(vararg args: String) { div { classes("container") div { - val commonElement = el + val commonElement = element classes("row", "align-items-start") div { classes("col-3") @@ -405,7 +403,7 @@ fun main(vararg args: String) { text("Package Cart") } } - fun HtmlBuilder.createSelectedPackageList() { + fun Khtml.createSelectedPackageList() { if (selectedPackages.isNotEmpty()) { div { classes("card-body") @@ -433,7 +431,7 @@ fun main(vararg args: String) { } button { classes("btn", "btn-primary", "w-100") - el.asDynamic().style.marginTop = "10px" + element.asDynamic().style.marginTop = "10px" val totalSize = selectedPackages .asSequence() .map(PkgTuple::size) @@ -453,9 +451,9 @@ fun main(vararg args: String) { .map(PkgTuple::fileName) .joinToString(" ") temporaryForm.appendChild(textField) - el.appendChild(temporaryForm) + element.appendChild(temporaryForm) temporaryForm.submit() - el.removeChild(temporaryForm) + element.removeChild(temporaryForm) } } } @@ -464,7 +462,7 @@ fun main(vararg args: String) { div { createSelectedPackageList() commonElement.on(REFRESH_SELECTED_PACKAGES_EVENT_NAME) { - el.removeChildren() + element.removeChildren() createSelectedPackageList() } } @@ -474,7 +472,6 @@ fun main(vararg args: String) { classes("col-9") buildPackageSearchSection(commonElement) } - el } } footer {