Dim diff option
This commit is contained in:
82
build.gradle
82
build.gradle
@@ -1,82 +0,0 @@
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.3.70'
|
||||
repositories {
|
||||
maven {
|
||||
url "http://nexus.astraeus.nl/nexus/content/groups/public"
|
||||
}
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id("org.jetbrains.kotlin.js") version "1.3.70"
|
||||
}
|
||||
|
||||
apply plugin: 'idea'
|
||||
apply plugin: 'maven'
|
||||
apply plugin: 'maven-publish'
|
||||
|
||||
group 'nl.astraeus'
|
||||
version '0.1.17-SNAPSHOT'
|
||||
/*
|
||||
|
||||
kotlin {
|
||||
target {
|
||||
browser {
|
||||
webpackTask {
|
||||
output.libraryTarget = "umd"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
compileKotlinJs.kotlinOptions.moduleKind = "umd"
|
||||
*/
|
||||
|
||||
idea {
|
||||
module {
|
||||
name = "komp"
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
url "http://nexus.astraeus.nl/nexus/content/groups/public"
|
||||
}
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
ext {
|
||||
kotlin_version = '1.3.70'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlin_version"
|
||||
compile 'org.jetbrains.kotlinx:kotlinx-html-js:0.7.1'
|
||||
}
|
||||
|
||||
uploadArchives {
|
||||
//println 'user: ' + nexusUsername
|
||||
repositories {
|
||||
mavenDeployer {
|
||||
repository(url: "http://nexus.astraeus.nl/nexus/content/repositories/releases") {
|
||||
authentication(userName: nexusUsername, password: nexusPassword)
|
||||
}
|
||||
snapshotRepository(url: "http://nexus.astraeus.nl/nexus/content/repositories/snapshots") {
|
||||
authentication(userName: nexusUsername, password: nexusPassword)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
compileKotlin2Js {
|
||||
kotlinOptions.sourceMap = true
|
||||
kotlinOptions.sourceMapEmbedSources = "always"
|
||||
|
||||
// remaining configuration options
|
||||
}
|
||||
*/
|
||||
77
build.gradle.kts
Normal file
77
build.gradle.kts
Normal file
@@ -0,0 +1,77 @@
|
||||
plugins {
|
||||
kotlin("multiplatform") version "1.4-M2-eap-68"
|
||||
`maven-publish`
|
||||
}
|
||||
|
||||
group = "nl.astraeus"
|
||||
version = "0.1.20-SNAPSHOT"
|
||||
|
||||
repositories {
|
||||
maven { setUrl("https://dl.bintray.com/kotlin/kotlin-eap") }
|
||||
mavenCentral()
|
||||
maven {
|
||||
url = uri("https://dl.bintray.com/kotlin/kotlin-dev")
|
||||
}
|
||||
}
|
||||
|
||||
kotlin {
|
||||
/* Targets configuration omitted.
|
||||
* To find out how to configure the targets, please follow the link:
|
||||
* https://kotlinlang.org/docs/reference/building-mpp-with-gradle.html#setting-up-targets */
|
||||
js {
|
||||
browser {
|
||||
//produceKotlinLibrary()
|
||||
}
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
val commonMain by getting {
|
||||
dependencies {
|
||||
implementation(kotlin("stdlib-common"))
|
||||
|
||||
//implementation("org.jetbrains.kotlinx:kotlinx-html:0.7.2-build-1711")
|
||||
}
|
||||
}
|
||||
val jsMain by getting {
|
||||
dependencies {
|
||||
implementation(kotlin("stdlib-js"))
|
||||
|
||||
api("org.jetbrains.kotlinx:kotlinx-html-js:0.7.2-build-1716")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
publishing {
|
||||
repositories {
|
||||
maven {
|
||||
name = "releases"
|
||||
// change to point to your repo, e.g. http://my.org/repo
|
||||
url = uri("http://nexus.astraeus.nl/nexus/content/repositories/releases")
|
||||
credentials {
|
||||
val nexusUsername: String by project
|
||||
val nexusPassword: String by project
|
||||
|
||||
username = nexusUsername
|
||||
password = nexusPassword
|
||||
}
|
||||
}
|
||||
maven {
|
||||
name = "snapshots"
|
||||
// change to point to your repo, e.g. http://my.org/repo
|
||||
url = uri("http://nexus.astraeus.nl/nexus/content/repositories/snapshots")
|
||||
credentials {
|
||||
val nexusUsername: String by project
|
||||
val nexusPassword: String by project
|
||||
|
||||
username = nexusUsername
|
||||
password = nexusPassword
|
||||
}
|
||||
}
|
||||
}
|
||||
publications {
|
||||
val kotlinMultiplatform by getting {
|
||||
//artifactId = "kotlin-css-generator"
|
||||
}
|
||||
}
|
||||
}
|
||||
33
komp.iml
33
komp.iml
@@ -1,41 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module external.linked.project.id="komp" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="nl.astraeus" external.system.module.version="0.1.17-SNAPSHOT" type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="kotlin-language" name="Kotlin">
|
||||
<configuration version="3" platform="JavaScript " allPlatforms="JS []" useProjectSettings="false">
|
||||
<testOutputPath>$MODULE_DIR$/build/classes/kotlin/test/komp_test.js</testOutputPath>
|
||||
<compilerSettings />
|
||||
<compilerArguments>
|
||||
<option name="outputFile" value="$MODULE_DIR$/build/classes/kotlin/main/komp.js" />
|
||||
<option name="noStdlib" value="true" />
|
||||
<option name="sourceMap" value="true" />
|
||||
<option name="sourceMapEmbedSources" value="always" />
|
||||
<option name="metaInfo" value="true" />
|
||||
<option name="target" value="v5" />
|
||||
<option name="main" value="call" />
|
||||
<option name="languageVersion" value="1.3" />
|
||||
<option name="apiVersion" value="1.3" />
|
||||
<option name="pluginOptions">
|
||||
<array />
|
||||
</option>
|
||||
<option name="pluginClasspaths">
|
||||
<array />
|
||||
</option>
|
||||
<option name="errors">
|
||||
<ArgumentParseErrors />
|
||||
</option>
|
||||
</compilerArguments>
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<module external.linked.project.id="komp" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="nl.astraeus" external.system.module.version="0.1.20-SNAPSHOT" type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/out" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="Kotlin SDK" jdkType="KotlinSDK" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
5
komp.ipr
5
komp.ipr
@@ -27,6 +27,9 @@
|
||||
</map>
|
||||
</option>
|
||||
</component>
|
||||
<component name="CompilerConfiguration">
|
||||
<bytecodeTargetLevel target="1.8" />
|
||||
</component>
|
||||
<component name="Encoding">
|
||||
<file url="PROJECT" charset="UTF-8" />
|
||||
</component>
|
||||
@@ -218,7 +221,7 @@
|
||||
<module fileurl="file://$PROJECT_DIR$/komp_test.iml" filepath="$PROJECT_DIR$/komp_test.iml" group="komp" />
|
||||
</modules>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/classes" />
|
||||
</component>
|
||||
<component name="PropertiesComponent">
|
||||
|
||||
@@ -39,6 +39,17 @@
|
||||
<content url="file://$MODULE_DIR$/src/test/resources" />
|
||||
<orderEntry type="jdk" jdkName="Kotlin SDK" jdkType="KotlinSDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="komp_main" scope="TEST" />
|
||||
<orderEntry type="module-library" scope="TEST">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="file://$MODULE_DIR$/build/classes/kotlin/main" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="library" scope="TEST" name="Gradle: org.jetbrains.kotlin:kotlin-stdlib-js:1.3.70" level="project" />
|
||||
<orderEntry type="module-library" scope="RUNTIME">
|
||||
<library>
|
||||
<CLASSES>
|
||||
@@ -48,45 +59,9 @@
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="library" scope="TEST" name="Gradle: org.jetbrains.kotlinx:kotlinx-html-common:0.7.1" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Gradle: org.jetbrains.kotlin:kotlin-stdlib-common:1.3.70" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Gradle: org.jetbrains.kotlinx:kotlinx-html-js:0.7.1" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Gradle: org.jetbrains.kotlin:kotlin-stdlib-js:1.3.70" level="project" />
|
||||
<orderEntry type="module-library" scope="TEST">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="file://$MODULE_DIR$/build/classes/kotlin/main" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="module-library" scope="TEST">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="file://$MODULE_DIR$/build/classes/kotlin/main" />
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-js/1.3.70/41513becdc85a89799b74028a81c39c364ba3465/kotlin-stdlib-js-1.3.70.jar!/" />
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlinx/kotlinx-html-js/0.7.1/f3a744916effcbe728d38e4bfd732f9694d18fa9/kotlinx-html-js-0.7.1.jar!/" />
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-common/1.3.70/3fa8dd6c896d635e78201e5e811545f3846dec04/kotlin-stdlib-common-1.3.70.jar!/" />
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlinx/kotlinx-html-common/0.7.1/26651a49fdc0e6abf8a61182b01d6bb0a6bb427e/kotlinx-html-common-0.7.1.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="module" module-name="komp_main" scope="TEST" />
|
||||
<orderEntry type="module-library" scope="RUNTIME">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlinx/kotlinx-html-js/0.7.1/f3a744916effcbe728d38e4bfd732f9694d18fa9/kotlinx-html-js-0.7.1.jar!/" />
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-js/1.3.70/41513becdc85a89799b74028a81c39c364ba3465/kotlin-stdlib-js-1.3.70.jar!/" />
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-common/1.3.70/3fa8dd6c896d635e78201e5e811545f3846dec04/kotlin-stdlib-common-1.3.70.jar!/" />
|
||||
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlinx/kotlinx-html-common/0.7.1/26651a49fdc0e6abf8a61182b01d6bb0a6bb427e/kotlinx-html-common-0.7.1.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="library" scope="TEST" name="Gradle: org.jetbrains.kotlin:kotlin-stdlib-common:1.3.70" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Gradle: org.jetbrains.kotlinx:kotlinx-html-common:0.7.1" level="project" />
|
||||
</component>
|
||||
<component name="TestModuleProperties" production-module="komp_main" />
|
||||
</module>
|
||||
@@ -1,3 +0,0 @@
|
||||
rootProject.name = 'komp'
|
||||
|
||||
enableFeaturePreview('GRADLE_METADATA')
|
||||
16
settings.gradle.kts
Normal file
16
settings.gradle.kts
Normal file
@@ -0,0 +1,16 @@
|
||||
pluginManagement {
|
||||
repositories {
|
||||
|
||||
maven { setUrl("https://dl.bintray.com/kotlin/kotlin-dev") }
|
||||
|
||||
maven { setUrl("https://dl.bintray.com/kotlin/kotlin-eap") }
|
||||
|
||||
mavenCentral()
|
||||
|
||||
maven { setUrl("https://plugins.gradle.org/m2/") }
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.name = "komp"
|
||||
|
||||
enableFeaturePreview("GRADLE_METADATA")
|
||||
195
src/jsMain/kotlin/nl/astraeus/komp/DiffPatch.kt
Normal file
195
src/jsMain/kotlin/nl/astraeus/komp/DiffPatch.kt
Normal file
@@ -0,0 +1,195 @@
|
||||
package nl.astraeus.komp
|
||||
|
||||
import org.w3c.dom.HTMLElement
|
||||
import org.w3c.dom.Node
|
||||
import org.w3c.dom.events.Event
|
||||
import org.w3c.dom.get
|
||||
|
||||
object DiffPatch {
|
||||
|
||||
fun updateNode(oldNode: Node, newNode: Node): Node {
|
||||
if (oldNode is HTMLElement && newNode is HTMLElement) {
|
||||
if (oldNode.nodeName == newNode.nodeName) {
|
||||
if (oldNode.getAttribute("data-komp-hash") != null &&
|
||||
oldNode.getAttribute("data-komp-hash") == newNode.getAttribute("data-komp-hash")) {
|
||||
|
||||
if (Komponent.logReplaceEvent) {
|
||||
console.log("Skip node, hash equals", oldNode, newNode)
|
||||
}
|
||||
|
||||
return oldNode
|
||||
} else {
|
||||
if (Komponent.logReplaceEvent) {
|
||||
console.log("Update attributes", oldNode.innerHTML, newNode.innerHTML)
|
||||
}
|
||||
updateAttributes(oldNode, newNode);
|
||||
if (Komponent.logReplaceEvent) {
|
||||
console.log("Update children", oldNode.innerHTML, newNode.innerHTML)
|
||||
}
|
||||
updateChildren(oldNode, newNode)
|
||||
updateEvents(oldNode, newNode)
|
||||
return oldNode
|
||||
}
|
||||
} else {
|
||||
if (Komponent.logReplaceEvent) {
|
||||
console.log("Replace node ee", oldNode.innerHTML, newNode.innerHTML)
|
||||
}
|
||||
replaceNode(oldNode, newNode)
|
||||
return newNode
|
||||
}
|
||||
} else {
|
||||
if (oldNode.nodeType == newNode.nodeType && oldNode.nodeType == 3.toShort()) {
|
||||
if (oldNode.textContent != newNode.textContent) {
|
||||
if (Komponent.logReplaceEvent) {
|
||||
console.log("Updating text content", oldNode, newNode)
|
||||
}
|
||||
oldNode.textContent = newNode.textContent
|
||||
return oldNode
|
||||
}
|
||||
}
|
||||
|
||||
if (Komponent.logReplaceEvent) {
|
||||
console.log("Replace node", oldNode, newNode)
|
||||
}
|
||||
replaceNode(oldNode, newNode)
|
||||
return newNode
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateAttributes(oldNode: HTMLElement, newNode: HTMLElement) {
|
||||
// removed attributes
|
||||
for (index in 0 until oldNode.attributes.length) {
|
||||
val attr = oldNode.attributes[index]
|
||||
|
||||
if (attr != null && newNode.attributes[attr.name] == null) {
|
||||
oldNode.removeAttribute(attr.name)
|
||||
}
|
||||
}
|
||||
|
||||
for (index in 0 until newNode.attributes.length) {
|
||||
val attr = newNode.attributes[index]
|
||||
|
||||
if (attr != null) {
|
||||
val oldAttr = oldNode.attributes[attr.name]
|
||||
|
||||
if (oldAttr == null || oldAttr.value != attr.value) {
|
||||
oldNode.setAttribute(attr.name, attr.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateChildren(oldNode: HTMLElement, newNode: HTMLElement) {
|
||||
// todo: add 1 look ahead/back
|
||||
var oldIndex = 0
|
||||
var newIndex = 0
|
||||
|
||||
if (Komponent.logReplaceEvent) {
|
||||
console.log("updateChildren old/new count", oldNode.childNodes.length, newNode.childNodes.length)
|
||||
}
|
||||
|
||||
while(newIndex < newNode.childNodes.length) {
|
||||
if (Komponent.logReplaceEvent) {
|
||||
console.log(">>> updateChildren old/new count", oldNode.childNodes, newNode.childNodes)
|
||||
console.log("Update Old/new", oldIndex, newIndex)
|
||||
}
|
||||
val newChildNode = newNode.childNodes[newIndex]
|
||||
|
||||
if (oldIndex < oldNode.childNodes.length) {
|
||||
val oldChildNode = oldNode.childNodes[oldIndex]
|
||||
|
||||
if (oldChildNode != null && newChildNode != null) {
|
||||
if (Komponent.logReplaceEvent) {
|
||||
console.log("Update node Old/new", oldChildNode, newChildNode)
|
||||
}
|
||||
|
||||
updateNode(oldChildNode, newChildNode)
|
||||
|
||||
if (Komponent.logReplaceEvent) {
|
||||
console.log("--- Updated Old/new", oldNode.children, newNode.children)
|
||||
}
|
||||
} else {
|
||||
if (Komponent.logReplaceEvent) {
|
||||
console.log("Null node", oldChildNode, newChildNode)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (Komponent.logReplaceEvent) {
|
||||
console.log("Append Old/new/node", oldIndex, newIndex, newChildNode)
|
||||
}
|
||||
oldNode.append(newChildNode)
|
||||
}
|
||||
|
||||
if (Komponent.logReplaceEvent) {
|
||||
console.log("<<< Updated Old/new", oldNode.children, newNode.children)
|
||||
}
|
||||
|
||||
oldIndex++
|
||||
newIndex++
|
||||
}
|
||||
|
||||
while(oldIndex < oldNode.childNodes.length) {
|
||||
oldNode.childNodes[oldIndex]?.also {
|
||||
if (Komponent.logReplaceEvent) {
|
||||
console.log("Remove old node", it)
|
||||
}
|
||||
|
||||
oldNode.removeChild(it)
|
||||
}
|
||||
oldIndex++
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateEvents(oldNode: HTMLElement, newNode: HTMLElement) {
|
||||
val oldEvents = mutableListOf<String>()
|
||||
oldEvents.addAll((oldNode.getAttribute("data-komp-events") ?: "").split(","))
|
||||
|
||||
val newEvents = (newNode.getAttribute("data-komp-events") ?: "").split(",")
|
||||
|
||||
for (event in newEvents) {
|
||||
if (event.isNotBlank()) {
|
||||
val oldNodeEvent = oldNode.asDynamic()["event-$event"]
|
||||
val newNodeEvent = newNode.asDynamic()["event-$event"]
|
||||
if (oldNodeEvent != null) {
|
||||
oldNode.removeEventListener(event, oldNodeEvent as ((Event) -> Unit), null)
|
||||
}
|
||||
if (newNodeEvent != null) {
|
||||
oldNode.addEventListener(event, newNodeEvent as ((Event) -> Unit), null)
|
||||
oldNode.asDynamic()["event-$event"] = newNodeEvent
|
||||
}
|
||||
oldEvents.remove(event)
|
||||
}
|
||||
}
|
||||
|
||||
for (event in oldEvents) {
|
||||
if (event.isNotBlank()) {
|
||||
val oldNodeEvent = oldNode.asDynamic()["event-$event"]
|
||||
if (oldNodeEvent != null) {
|
||||
oldNode.removeEventListener(event, oldNodeEvent as ((Event) -> Unit), null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
newNode.getAttribute("data-komp-events")?.also {
|
||||
oldNode.setAttribute("data-komp-events", it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun replaceNode(oldNode: Node, newNode: Node) {
|
||||
oldNode.parentNode?.also { parent ->
|
||||
val clone = newNode.cloneNode(true)
|
||||
if (newNode is HTMLElement) {
|
||||
val events = (newNode.getAttribute("data-komp-events") ?: "").split(",")
|
||||
for (event in events) {
|
||||
val foundEvent = newNode.asDynamic()["event-$event"]
|
||||
if (foundEvent != null) {
|
||||
clone.addEventListener(event, foundEvent as ((Event) -> Unit), null)
|
||||
}
|
||||
}
|
||||
}
|
||||
parent.replaceChild(clone, oldNode)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,21 +1,20 @@
|
||||
package nl.astraeus.komp
|
||||
|
||||
import kotlinx.html.DefaultUnsafe
|
||||
import kotlinx.html.Entities
|
||||
import kotlinx.html.Tag
|
||||
import kotlinx.html.TagConsumer
|
||||
import kotlinx.html.Unsafe
|
||||
import org.w3c.dom.Document
|
||||
import org.w3c.dom.HTMLElement
|
||||
import org.w3c.dom.Node
|
||||
import org.w3c.dom.asList
|
||||
import kotlinx.html.*
|
||||
import org.w3c.dom.*
|
||||
import org.w3c.dom.css.CSSStyleDeclaration
|
||||
import org.w3c.dom.events.Event
|
||||
import kotlin.browser.document
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
private inline fun HTMLElement.setEvent(name: String, noinline callback : (Event) -> Unit) : Unit {
|
||||
asDynamic()[name] = callback
|
||||
val eventName = if (name.startsWith("on")) { name.substring(2) } else { name }
|
||||
addEventListener(eventName, callback, null)
|
||||
//asDynamic()[name] = callback
|
||||
val events = getAttribute("data-komp-events") ?: ""
|
||||
|
||||
setAttribute("data-komp-events", if (events.isBlank()) { eventName } else { "$events,$eventName" })
|
||||
asDynamic()["event-$eventName"] = callback
|
||||
}
|
||||
|
||||
interface HtmlConsumer : TagConsumer<HTMLElement> {
|
||||
@@ -73,13 +72,27 @@ class HtmlBuilder(
|
||||
}
|
||||
|
||||
override fun onTagEnd(tag: Tag) {
|
||||
var hash = 0
|
||||
if (path.isEmpty() || path.last().tagName.toLowerCase() != tag.tagName.toLowerCase()) {
|
||||
throw IllegalStateException("We haven't entered tag ${tag.tagName} but trying to leave")
|
||||
}
|
||||
|
||||
val element = path.last()
|
||||
|
||||
for (index in 0 until element.childNodes.length) {
|
||||
val child = element.childNodes[index]
|
||||
if (child is HTMLElement) {
|
||||
|
||||
hash = hash * 37 + (child.getAttribute("data-komp-hash")?.toInt() ?: 0)
|
||||
} else {
|
||||
hash = hash * 37 + (child?.textContent?.hashCode() ?: 0)
|
||||
}
|
||||
}
|
||||
|
||||
tag.attributesEntries.forEach {
|
||||
hash = hash * 37 + it.key.hashCode()
|
||||
hash = hash * 37 + it.value.hashCode()
|
||||
|
||||
if (it.key == "class") {
|
||||
val classes = it.value.split(Regex("\\s+"))
|
||||
val classNames = StringBuilder()
|
||||
@@ -121,6 +134,8 @@ class HtmlBuilder(
|
||||
}
|
||||
}
|
||||
|
||||
element.setAttribute("data-komp-hash", hash.toString())
|
||||
|
||||
lastLeaved = path.removeAt(path.lastIndex)
|
||||
}
|
||||
|
||||
@@ -33,6 +33,11 @@ class DummyKomponent: Komponent() {
|
||||
}
|
||||
}
|
||||
|
||||
enum class UpdateStrategy {
|
||||
REPLACE,
|
||||
DOM_DIFF
|
||||
}
|
||||
|
||||
abstract class Komponent {
|
||||
var element: Node? = null
|
||||
val declaredStyles: MutableMap<String, CSSStyleDeclaration> = HashMap()
|
||||
@@ -68,10 +73,18 @@ abstract class Komponent {
|
||||
val newElement = create()
|
||||
|
||||
if (oldElement != null) {
|
||||
if (updateStrategy == UpdateStrategy.REPLACE) {
|
||||
if (logReplaceEvent) {
|
||||
console.log("Replacing", oldElement, newElement)
|
||||
}
|
||||
oldElement.parentNode?.replaceChild(newElement, oldElement)
|
||||
element = newElement
|
||||
} else {
|
||||
if (logReplaceEvent) {
|
||||
console.log("DomDiffing", oldElement, newElement)
|
||||
}
|
||||
element = DiffPatch.updateNode(oldElement, newElement)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,6 +104,7 @@ abstract class Komponent {
|
||||
companion object {
|
||||
var logRenderEvent = false
|
||||
var logReplaceEvent = false
|
||||
var updateStrategy = UpdateStrategy.DOM_DIFF
|
||||
|
||||
fun create(parent: HTMLElement, component: Komponent, insertAsFirst: Boolean = false) {
|
||||
val element = component.create()
|
||||
@@ -102,4 +116,5 @@ abstract class Komponent {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Bla</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<script src="../../kotlin-js-min/main/kotlin.js"></script>
|
||||
<script src="../../kotlin-js-min/main/kotlinx-html-js.js"></script>
|
||||
<script src="../../kotlin-js-min/main/komp.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user