Bump version to 1.2.10, simplify attribute and event handling in ElementExtensions, and remove deprecated logic in HtmlBuilder.
Some checks failed
Gradle CI / build (push) Has been cancelled
Some checks failed
Gradle CI / build (push) Has been cancelled
This commit is contained in:
@@ -11,7 +11,7 @@ plugins {
|
||||
}
|
||||
|
||||
group = "nl.astraeus"
|
||||
version = "1.2.9"
|
||||
version = "1.2.10"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
|
||||
@@ -40,14 +40,6 @@ fun Element.printTree(indent: Int = 0): String {
|
||||
}
|
||||
result.append(") {")
|
||||
result.append("\n")
|
||||
for ((name, event) in getKompEvents()) {
|
||||
result.append(indent.asSpaces())
|
||||
result.append("on")
|
||||
result.append(name)
|
||||
result.append(" -> ")
|
||||
result.append(event)
|
||||
result.append("\n")
|
||||
}
|
||||
for (index in 0 until childNodes.length) {
|
||||
childNodes[index]?.let {
|
||||
if (it is Element) {
|
||||
@@ -65,55 +57,52 @@ fun Element.printTree(indent: Int = 0): String {
|
||||
return result.toString()
|
||||
}
|
||||
|
||||
internal fun Element.setKompAttribute(attributeName: String, value: String?) {
|
||||
//val attributeName = name.lowercase()
|
||||
if (value == null || value.isBlank()) {
|
||||
if (this is HTMLInputElement) {
|
||||
when (attributeName) {
|
||||
"checked" -> {
|
||||
checked = false
|
||||
}
|
||||
"class" -> {
|
||||
className = ""
|
||||
}
|
||||
"value" -> {
|
||||
this.value = ""
|
||||
}
|
||||
else -> {
|
||||
removeAttribute(attributeName)
|
||||
}
|
||||
internal fun Element.setKompAttribute(attributeName: String, value: String) {
|
||||
if (this is HTMLInputElement) {
|
||||
when (attributeName) {
|
||||
"checked" -> {
|
||||
checked = "checked" == value
|
||||
}
|
||||
} else {
|
||||
removeAttribute(attributeName)
|
||||
}
|
||||
} else {
|
||||
if (this is HTMLInputElement) {
|
||||
when (attributeName) {
|
||||
"checked" -> {
|
||||
checked = "checked" == value
|
||||
}
|
||||
"class" -> {
|
||||
className = value
|
||||
}
|
||||
"value" -> {
|
||||
this.value = value
|
||||
}
|
||||
else -> {
|
||||
setAttribute(attributeName, value)
|
||||
}
|
||||
|
||||
"class" -> {
|
||||
className = value
|
||||
}
|
||||
|
||||
"value" -> {
|
||||
this.value = value
|
||||
}
|
||||
|
||||
else -> {
|
||||
setAttribute(attributeName, value)
|
||||
}
|
||||
} else if (this.getAttribute(attributeName) != value) {
|
||||
setAttribute(attributeName, value)
|
||||
}
|
||||
} else if (this.getAttribute(attributeName) != value) {
|
||||
setAttribute(attributeName, value)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Element.clearKompEvents() {
|
||||
val events = getKompEvents()
|
||||
for ((name, event) in getKompEvents()) {
|
||||
removeEventListener(name, event)
|
||||
internal fun Element.clearKompAttribute(attributeName: String) {
|
||||
if (this is HTMLInputElement) {
|
||||
when (attributeName) {
|
||||
"checked" -> {
|
||||
checked = false
|
||||
}
|
||||
|
||||
"class" -> {
|
||||
className = ""
|
||||
}
|
||||
|
||||
"value" -> {
|
||||
this.value = ""
|
||||
}
|
||||
|
||||
else -> {
|
||||
removeAttribute(attributeName)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
removeAttribute(attributeName)
|
||||
}
|
||||
events.clear()
|
||||
}
|
||||
|
||||
internal fun Element.setKompEvent(name: String, event: (Event) -> Unit) {
|
||||
@@ -123,22 +112,9 @@ internal fun Element.setKompEvent(name: String, event: (Event) -> Unit) {
|
||||
name
|
||||
}
|
||||
|
||||
getKompEvents()[eventName] = event
|
||||
|
||||
this.addEventListener(eventName, event)
|
||||
}
|
||||
|
||||
internal fun Element.getKompEvents(): MutableMap<String, (Event) -> Unit> {
|
||||
var map = this.asDynamic()["komp-events"] as? MutableMap<String, (Event) -> Unit>
|
||||
|
||||
if (map == null) {
|
||||
map = mutableMapOf()
|
||||
this.asDynamic()["komp-events"] = map
|
||||
}
|
||||
|
||||
return map
|
||||
}
|
||||
|
||||
internal fun Element.findElementIndex(): Int {
|
||||
val childNodes = parentElement?.children
|
||||
if (childNodes != null) {
|
||||
|
||||
@@ -6,7 +6,6 @@ import org.w3c.dom.get
|
||||
data class ElementIndex(
|
||||
val parent: Node,
|
||||
var childIndex: Int,
|
||||
var setAttr: MutableSet<String> = mutableSetOf()
|
||||
) {
|
||||
override fun toString(): String {
|
||||
return "${parent.nodeName}[$childIndex]"
|
||||
@@ -39,7 +38,6 @@ fun ArrayList<ElementIndex>.currentPosition(): ElementIndex? {
|
||||
|
||||
fun ArrayList<ElementIndex>.nextElement() {
|
||||
this.lastOrNull()?.let {
|
||||
it.setAttr.clear()
|
||||
it.childIndex++
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,12 +57,6 @@ class HtmlBuilder(
|
||||
}
|
||||
} else {
|
||||
// current element should become parent
|
||||
/*
|
||||
val ce = komponent.element
|
||||
if (ce != null) {
|
||||
append(ce as Element)
|
||||
}
|
||||
*/
|
||||
komponent.create(
|
||||
currentPosition.last().parent as Element,
|
||||
currentPosition.last().childIndex
|
||||
@@ -100,39 +94,26 @@ class HtmlBuilder(
|
||||
"onTagStart, [${tag.tagName}, ${tag.namespace ?: ""}], currentPosition: $currentPosition"
|
||||
}
|
||||
|
||||
currentNode = currentPosition.currentElement()
|
||||
currentNode = if (tag.namespace != null) {
|
||||
document.createElementNS(tag.namespace, tag.tagName)
|
||||
} else {
|
||||
document.createElement(tag.tagName)
|
||||
}
|
||||
|
||||
if (currentNode == null) {
|
||||
logReplace { "onTagStart, currentNode1: $currentNode" }
|
||||
currentNode = if (tag.namespace != null) {
|
||||
document.createElementNS(tag.namespace, tag.tagName)
|
||||
} else {
|
||||
document.createElement(tag.tagName)
|
||||
}
|
||||
|
||||
logReplace { "onTagStart, currentElement1.1: $currentNode" }
|
||||
currentPosition.currentParent().appendChild(currentNode!!)
|
||||
} else if (
|
||||
!currentNode?.asElement()?.tagName.equals(tag.tagName, true) ||
|
||||
(
|
||||
tag.namespace != null &&
|
||||
!currentNode?.asElement()?.namespaceURI.equals(tag.namespace, true)
|
||||
)
|
||||
) {
|
||||
logReplace {
|
||||
"onTagStart, currentElement, namespace: ${currentNode?.asElement()?.namespaceURI} -> ${tag.namespace}"
|
||||
}
|
||||
logReplace {
|
||||
"onTagStart, currentElement, replace: ${currentNode?.asElement()?.tagName} -> ${tag.tagName}"
|
||||
}
|
||||
} else {
|
||||
logReplace {
|
||||
"onTagStart, currentElement, namespace: ${currentNode?.asElement()?.namespaceURI} -> ${tag.namespace}"
|
||||
}
|
||||
logReplace {
|
||||
"onTagStart, currentElement, replace: ${currentNode?.asElement()?.tagName} -> ${tag.tagName}"
|
||||
}
|
||||
|
||||
currentNode = if (tag.namespace != null) {
|
||||
document.createElementNS(tag.namespace, tag.tagName)
|
||||
} else {
|
||||
document.createElement(tag.tagName)
|
||||
}
|
||||
|
||||
currentPosition.replace(currentNode!!)
|
||||
currentPosition.replace(currentNode!!)
|
||||
}
|
||||
|
||||
currentElement = currentNode as? Element ?: currentElement
|
||||
@@ -144,15 +125,8 @@ class HtmlBuilder(
|
||||
firstTag = false
|
||||
}
|
||||
|
||||
currentElement?.clearKompEvents()
|
||||
|
||||
// if currentElement = checkbox make sure it's cleared
|
||||
(currentElement as? HTMLInputElement)?.checked = false
|
||||
|
||||
currentPosition.lastOrNull()?.setAttr?.clear()
|
||||
for (entry in tag.attributesEntries) {
|
||||
currentElement!!.setKompAttribute(entry.key, entry.value)
|
||||
currentPosition.lastOrNull()?.setAttr?.add(entry.key)
|
||||
currentElement?.setKompAttribute(entry.key, entry.value)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,11 +155,10 @@ class HtmlBuilder(
|
||||
checkTag("onTagAttributeChange", tag)
|
||||
}
|
||||
|
||||
currentElement?.setKompAttribute(attribute, value)
|
||||
if (value == null || value.isEmpty()) {
|
||||
currentPosition.currentPosition()?.setAttr?.remove(attribute)
|
||||
currentElement?.clearKompAttribute(attribute)
|
||||
} else {
|
||||
currentPosition.currentPosition()?.setAttr?.add(attribute)
|
||||
currentElement?.setKompAttribute(attribute, value)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,25 +195,6 @@ class HtmlBuilder(
|
||||
checkTag("onTagEnd", tag)
|
||||
}
|
||||
|
||||
if (currentElement != null) {
|
||||
val setAttrs: Set<String> = currentPosition.currentPosition()?.setAttr ?: setOf()
|
||||
|
||||
// remove attributes that where not set
|
||||
val element = currentElement
|
||||
if (element?.hasAttributes() == true) {
|
||||
for (index in 0 until element.attributes.length) {
|
||||
val attribute = element.attributes[index]
|
||||
if (attribute?.name != null) {
|
||||
val attr = attribute.name
|
||||
|
||||
if (!setAttrs.contains(attr)) {
|
||||
element.setKompAttribute(attr, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
currentPosition.pop()
|
||||
|
||||
currentNode = currentPosition.currentElement()
|
||||
|
||||
@@ -38,7 +38,7 @@ class TestClassUpdate {
|
||||
Komponent.create(div, classComponent)
|
||||
|
||||
// Verify initial state - should have the class
|
||||
val contentDiv = div.querySelector("div")
|
||||
var contentDiv = div.querySelector("div")
|
||||
println("[DEBUG_LOG] Initial DOM: ${div.printTree()}")
|
||||
assertTrue(contentDiv?.classList?.contains("test-class") ?: false, "Div should have the class initially")
|
||||
|
||||
@@ -47,6 +47,7 @@ class TestClassUpdate {
|
||||
classComponent.requestImmediateUpdate()
|
||||
|
||||
// Verify the class was removed
|
||||
contentDiv = div.querySelector("div")
|
||||
println("[DEBUG_LOG] After class removal: ${div.printTree()}")
|
||||
assertFalse(contentDiv?.classList?.contains("test-class") ?: true, "Class should be removed after update")
|
||||
|
||||
@@ -55,6 +56,7 @@ class TestClassUpdate {
|
||||
classComponent.requestImmediateUpdate()
|
||||
|
||||
// Verify the class was added back
|
||||
contentDiv = div.querySelector("div")
|
||||
println("[DEBUG_LOG] After class added back: ${div.printTree()}")
|
||||
assertTrue(contentDiv?.classList?.contains("test-class") ?: false, "Class should be added back")
|
||||
|
||||
@@ -63,6 +65,7 @@ class TestClassUpdate {
|
||||
classComponent.requestImmediateUpdate()
|
||||
|
||||
// Verify the class was changed
|
||||
contentDiv = div.querySelector("div")
|
||||
println("[DEBUG_LOG] After class name change: ${div.printTree()}")
|
||||
assertFalse(contentDiv?.classList?.contains("test-class") ?: true, "Old class should be removed")
|
||||
assertTrue(contentDiv?.classList?.contains("new-class") ?: false, "New class should be added")
|
||||
|
||||
@@ -77,9 +77,9 @@ class TestInsert {
|
||||
tableComponent.addRow("First Row")
|
||||
|
||||
// Verify the row was added
|
||||
val rowsAfterFirstInsert = table.querySelectorAll("tr")
|
||||
assertEquals(1, rowsAfterFirstInsert.length, "Table should have one row after insertion")
|
||||
val firstRowCell = table.querySelector("tr td")
|
||||
val rowsAfterFirstInsert = div.querySelector("table")?.querySelectorAll("tr")
|
||||
assertEquals(1, rowsAfterFirstInsert?.length, "Table should have one row after insertion")
|
||||
val firstRowCell = div.querySelector("table")?.querySelector("tr td")
|
||||
assertNotNull(firstRowCell, "First row cell should exist")
|
||||
assertEquals("First Row", firstRowCell.textContent, "Row content should match")
|
||||
|
||||
@@ -87,12 +87,12 @@ class TestInsert {
|
||||
tableComponent.addRow("Second Row")
|
||||
|
||||
// Verify both rows are present
|
||||
val rowsAfterSecondInsert = table.querySelectorAll("tr")
|
||||
assertEquals(2, rowsAfterSecondInsert.length, "Table should have two rows after second insertion")
|
||||
val allCells = table.querySelectorAll("tr td")
|
||||
assertEquals(2, allCells.length, "Table should have two cells")
|
||||
assertEquals("First Row", allCells.item(0)?.textContent, "First row content should match")
|
||||
assertEquals("Second Row", allCells.item(1)?.textContent, "Second row content should match")
|
||||
val rowsAfterSecondInsert = div.querySelector("table")?.querySelectorAll("tr")
|
||||
assertEquals(2, rowsAfterSecondInsert?.length, "Table should have two rows after second insertion")
|
||||
val allCells = div.querySelector("table")?.querySelectorAll("tr td")
|
||||
assertEquals(2, allCells?.length, "Table should have two cells")
|
||||
assertEquals("First Row", allCells?.item(0)?.textContent, "First row content should match")
|
||||
assertEquals("Second Row", allCells?.item(1)?.textContent, "Second row content should match")
|
||||
|
||||
// Print the DOM tree for debugging
|
||||
println("Table DOM: ${div.printTree()}")
|
||||
|
||||
@@ -12,57 +12,68 @@ import kotlin.test.assertNull
|
||||
* Test class for verifying style attribute updates and removals
|
||||
*/
|
||||
class StyleKomponent : Komponent() {
|
||||
var includeStyle = true
|
||||
var styleValue = "color: red;"
|
||||
var includeStyle = true
|
||||
var styleValue = "color: red;"
|
||||
|
||||
override fun HtmlBuilder.render() {
|
||||
div {
|
||||
if (includeStyle) {
|
||||
style = styleValue
|
||||
}
|
||||
+"Content"
|
||||
}
|
||||
override fun HtmlBuilder.render() {
|
||||
div {
|
||||
if (includeStyle) {
|
||||
style = styleValue
|
||||
}
|
||||
+"Content"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TestStyleUpdate {
|
||||
|
||||
@Test
|
||||
fun testStyleRemoval() {
|
||||
// Create a test component
|
||||
val styleComponent = StyleKomponent()
|
||||
val div = document.createElement("div") as HTMLDivElement
|
||||
@Test
|
||||
fun testStyleRemoval() {
|
||||
// Create a test component
|
||||
val styleComponent = StyleKomponent()
|
||||
val div = document.createElement("div") as HTMLDivElement
|
||||
|
||||
// Render it
|
||||
Komponent.create(div, styleComponent)
|
||||
// Render it
|
||||
Komponent.create(div, styleComponent)
|
||||
|
||||
// Verify initial state - should have the style
|
||||
val contentDiv = div.querySelector("div")
|
||||
println("[DEBUG_LOG] Initial DOM: ${div.printTree()}")
|
||||
assertEquals("color: red;", contentDiv?.getAttribute("style"), "Div should have the style initially")
|
||||
// Verify initial state - should have the style
|
||||
var contentDiv = div.querySelector("div")
|
||||
println("[DEBUG_LOG] Initial DOM: ${div.printTree()}")
|
||||
assertEquals(
|
||||
"color: red;",
|
||||
contentDiv?.getAttribute("style"),
|
||||
"Div should have the style initially"
|
||||
)
|
||||
|
||||
// Update to remove the style
|
||||
styleComponent.includeStyle = false
|
||||
styleComponent.requestImmediateUpdate()
|
||||
// Update to remove the style
|
||||
styleComponent.includeStyle = false
|
||||
styleComponent.requestImmediateUpdate()
|
||||
|
||||
// Verify the style was removed
|
||||
println("[DEBUG_LOG] After style removal: ${div.printTree()}")
|
||||
assertNull(contentDiv?.getAttribute("style"), "Style should be removed after update")
|
||||
// Verify the style was removed
|
||||
contentDiv = div.querySelector("div")
|
||||
println("[DEBUG_LOG] After style removal: ${div.printTree()}")
|
||||
assertNull(contentDiv?.getAttribute("style"), "Style should be removed after update")
|
||||
|
||||
// Add the style back
|
||||
styleComponent.includeStyle = true
|
||||
styleComponent.requestImmediateUpdate()
|
||||
// Add the style back
|
||||
styleComponent.includeStyle = true
|
||||
styleComponent.requestImmediateUpdate()
|
||||
|
||||
// Verify the style was added back
|
||||
println("[DEBUG_LOG] After style added back: ${div.printTree()}")
|
||||
assertEquals("color: red;", contentDiv?.getAttribute("style"), "Style should be added back")
|
||||
// Verify the style was added back
|
||||
contentDiv = div.querySelector("div")
|
||||
println("[DEBUG_LOG] After style added back: ${div.printTree()}")
|
||||
assertEquals("color: red;", contentDiv?.getAttribute("style"), "Style should be added back")
|
||||
|
||||
// Change the style value
|
||||
styleComponent.styleValue = "color: blue;"
|
||||
styleComponent.requestImmediateUpdate()
|
||||
// Change the style value
|
||||
styleComponent.styleValue = "color: blue;"
|
||||
styleComponent.requestImmediateUpdate()
|
||||
|
||||
// Verify the style was changed
|
||||
println("[DEBUG_LOG] After style value change: ${div.printTree()}")
|
||||
assertEquals("color: blue;", contentDiv?.getAttribute("style"), "Style should be updated to new value")
|
||||
}
|
||||
// Verify the style was changed
|
||||
contentDiv = div.querySelector("div")
|
||||
println("[DEBUG_LOG] After style value change: ${div.printTree()}")
|
||||
assertEquals(
|
||||
"color: blue;",
|
||||
contentDiv?.getAttribute("style"),
|
||||
"Style should be updated to new value"
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user