4 Commits

14 changed files with 859 additions and 1019 deletions

2
.gitignore vendored
View File

@@ -1,6 +1,4 @@
# Created by .ignore support plugin (hsz.mobi) # Created by .ignore support plugin (hsz.mobi)
build
.gradle
web/js/generated web/js/generated
gradle.properties gradle.properties
local.properties local.properties

View File

@@ -1,23 +1,27 @@
plugins { plugins {
kotlin("multiplatform") version "1.5.21" kotlin("multiplatform") version "1.4.30"
`maven-publish` `maven-publish`
} }
group = "nl.astraeus" group = "nl.astraeus"
version = "0.5.7-SNAPSHOT" version = "0.2.5-SNAPSHOT"
repositories { repositories {
mavenCentral() mavenCentral()
jcenter()
} }
kotlin { 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(BOTH) { js(BOTH) {
browser { browser {
//produceKotlinLibrary()
testTask { testTask {
useKarma { useKarma {
useChromiumHeadless() useChromeHeadless()
//useChromeHeadless()
} }
} }
} }
@@ -28,7 +32,7 @@ kotlin {
dependencies { dependencies {
implementation(kotlin("stdlib-common")) implementation(kotlin("stdlib-common"))
api("org.jetbrains.kotlinx:kotlinx-html-js:0.7.3") api("org.jetbrains.kotlinx:kotlinx-html-js:0.7.2")
} }
} }
val jsMain by getting { val jsMain by getting {
@@ -46,34 +50,34 @@ kotlin {
publishing { publishing {
repositories { repositories {
if (project.properties["nexusUsername"] != null) { maven {
maven { name = "releases"
name = "releases" // change to point to your repo, e.g. http://my.org/repo
url = uri("https://nexus.astraeus.nl/nexus/content/repositories/releases") url = uri("http://nexus.astraeus.nl/nexus/content/repositories/releases")
credentials { credentials {
val nexusUsername: String by project val nexusUsername: String by project
val nexusPassword: String by project val nexusPassword: String by project
username = nexusUsername username = nexusUsername
password = nexusPassword password = nexusPassword
}
} }
maven { }
name = "snapshots" maven {
url = uri("https://nexus.astraeus.nl/nexus/content/repositories/snapshots") name = "snapshots"
credentials { // change to point to your repo, e.g. http://my.org/repo
val nexusUsername: String by project url = uri("http://nexus.astraeus.nl/nexus/content/repositories/snapshots")
val nexusPassword: String by project credentials {
val nexusUsername: String by project
val nexusPassword: String by project
username = nexusUsername username = nexusUsername
password = nexusPassword password = nexusPassword
}
} }
} else {
println("Publishing disabled properties not found.")
} }
} }
publications { publications {
val kotlinMultiplatform by getting {} val kotlinMultiplatform by getting {
//artifactId = "kotlin-css-generator"
}
} }
} }

View File

@@ -1,5 +1,5 @@
#Wed Mar 04 13:29:12 CET 2020 #Wed Mar 04 13:29:12 CET 2020
distributionUrl=https\://services.gradle.org/distributions/gradle-7.1-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-6.2-all.zip
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

View File

@@ -1,25 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id="komp:commonMain" 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.type="sourceSet" external.system.module.version="0.5.6-SNAPSHOT" type="JAVA_MODULE" version="4"> <module external.linked.project.id="komp:commonMain" 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.type="sourceSet" external.system.module.version="0.2.4-SNAPSHOT" type="JAVA_MODULE" version="4">
<component name="FacetManager"> <component name="FacetManager">
<facet type="kotlin-language" name="Kotlin"> <facet type="kotlin-language" name="Kotlin">
<configuration version="3" platform="Common (experimental) " allPlatforms="JS []/JVM [1.8]/Native []/Native [general]" useProjectSettings="false" isTestModule="false" externalProjectId="komp" pureKotlinSourceFolders="$MODULE_DIR$/src/jsMain/kotlin;/home/rnentjes/Development/komp/komp/build/externals/komp-js-legacy/src;/home/rnentjes/Development/komp/komp/build/externals/komp-js-ir/src;/home/rnentjes/Development/komp/komp/src/jsTest/kotlin"> <configuration version="3" platform="Common (experimental) " allPlatforms="JS []/JVM [1.6]/Native []/Native [general]" useProjectSettings="false" isTestModule="false" externalProjectId="komp" pureKotlinSourceFolders="$MODULE_DIR$/src/jsMain/kotlin;/home/rnentjes/Development/komp/komp/build/externals/komp-jsLegacy/src;/home/rnentjes/Development/komp/komp/build/externals/komp-jsIr/src;/home/rnentjes/Development/komp/komp/src/jsTest/kotlin;/home/rnentjes/Development/komp/komp/src/commonMain/kotlin">
<newMppModelJpsModuleKind>SOURCE_SET_HOLDER</newMppModelJpsModuleKind> <newMppModelJpsModuleKind>SOURCE_SET_HOLDER</newMppModelJpsModuleKind>
<compilerSettings /> <compilerSettings />
<compilerArguments> <compilerArguments>
<option name="languageVersion" value="1.5" /> <option name="languageVersion" value="1.4" />
<option name="apiVersion" value="1.5" /> <option name="apiVersion" value="1.4" />
<option name="pluginOptions"> <option name="pluginOptions">
<array /> <array />
</option> </option>
<option name="pluginClasspaths"> <option name="pluginClasspaths">
<array> <array>
<option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-scripting-jvm/1.5.21/8143908a15163e634fecb87013ed4a139170b032/kotlin-scripting-jvm-1.5.21.jar" /> <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-scripting-jvm/1.4.30/7d0085e5781847da84580d16239c1c4e0980bdb0/kotlin-scripting-jvm-1.4.30.jar" />
<option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-scripting-common/1.5.21/5d271f9e7e7191902f8c0d45c600f5b57a284036/kotlin-scripting-common-1.5.21.jar" /> <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-scripting-common/1.4.30/c7896c5c6b504f44e7cf9f5719d4393e20680666/kotlin-scripting-common-1.4.30.jar" />
<option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlinx/kotlinx-coroutines-core/1.3.8/f62be6d4cbf27781c2969867b4ed952f38378492/kotlinx-coroutines-core-1.3.8.jar" /> <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlinx/kotlinx-coroutines-core/1.3.8/f62be6d4cbf27781c2969867b4ed952f38378492/kotlinx-coroutines-core-1.3.8.jar" />
<option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib/1.5.21/2f537cad7e9eeb9da73738c8812e1e4cf9b62e4e/kotlin-stdlib-1.5.21.jar" /> <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib/1.4.30/d10d1e10f47006ee08162dde039e38ac487de4ac/kotlin-stdlib-1.4.30.jar" />
<option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-common/1.4.30/bb9a3173350f55732416ee27956ea8f9b81f4dbb/kotlin-stdlib-common-1.4.30.jar" />
<option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains/annotations/13.0/919f0dfe192fb4e063e7dacadee7f8bb9a2672a9/annotations-13.0.jar" /> <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains/annotations/13.0/919f0dfe192fb4e063e7dacadee7f8bb9a2672a9/annotations-13.0.jar" />
<option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-common/1.5.21/cc8bf3586fd2ebcf234058b9440bb406e62dfacb/kotlin-stdlib-common-1.5.21.jar" /> <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-script-runtime/1.4.30/b9c2a1fab9217623fc0fbadf6190e77eed6f054d/kotlin-script-runtime-1.4.30.jar" />
<option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-script-runtime/1.5.21/96d49e89873fde985750af354b6eabb60cfa999b/kotlin-script-runtime-1.5.21.jar" />
</array> </array>
</option> </option>
<option name="multiPlatform" value="true" /> <option name="multiPlatform" value="true" />
@@ -32,7 +32,7 @@
<content url="file://$MODULE_DIR$/src/commonMain" /> <content url="file://$MODULE_DIR$/src/commonMain" />
<orderEntry type="jdk" jdkName="Kotlin SDK" jdkType="KotlinSDK" /> <orderEntry type="jdk" jdkName="Kotlin SDK" jdkType="KotlinSDK" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Gradle: org.jetbrains.kotlin:kotlin-stdlib-common:1.5.21" level="project" /> <orderEntry type="library" name="Gradle: org.jetbrains.kotlin:kotlin-stdlib-common:1.4.30" level="project" />
<orderEntry type="library" name="Gradle: org.jetbrains.kotlinx:kotlinx-html-common:0.7.3" level="project" /> <orderEntry type="library" name="Gradle: org.jetbrains.kotlinx:kotlinx-html-common:0.7.2" level="project" />
</component> </component>
</module> </module>

View File

@@ -1,28 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id="komp:commonTest" 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.type="sourceSet" external.system.module.version="0.5.6-SNAPSHOT" type="JAVA_MODULE" version="4"> <module external.linked.project.id="komp:commonTest" 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.type="sourceSet" external.system.module.version="0.2.4-SNAPSHOT" type="JAVA_MODULE" version="4">
<component name="FacetManager"> <component name="FacetManager">
<facet type="kotlin-language" name="Kotlin"> <facet type="kotlin-language" name="Kotlin">
<configuration version="3" platform="Common (experimental) " allPlatforms="JS []/JVM [1.8]/Native []/Native [general]" useProjectSettings="false" isTestModule="true" externalProjectId="komp" pureKotlinSourceFolders="$MODULE_DIR$/src/jsMain/kotlin;/home/rnentjes/Development/komp/komp/build/externals/komp-js-legacy/src;/home/rnentjes/Development/komp/komp/build/externals/komp-js-ir/src;/home/rnentjes/Development/komp/komp/src/jsTest/kotlin"> <configuration version="3" platform="Common (experimental) " allPlatforms="JS []/JVM [1.6]/Native []/Native [general]" useProjectSettings="false" isTestModule="true" externalProjectId="komp" pureKotlinSourceFolders="$MODULE_DIR$/src/jsMain/kotlin;/home/rnentjes/Development/komp/komp/build/externals/komp-jsLegacy/src;/home/rnentjes/Development/komp/komp/build/externals/komp-jsIr/src;/home/rnentjes/Development/komp/komp/src/jsTest/kotlin;/home/rnentjes/Development/komp/komp/src/commonMain/kotlin">
<newMppModelJpsModuleKind>SOURCE_SET_HOLDER</newMppModelJpsModuleKind> <newMppModelJpsModuleKind>SOURCE_SET_HOLDER</newMppModelJpsModuleKind>
<externalSystemTestTasks> <externalSystemTestTasks>
<externalSystemTestTask>jsLegacyBrowserTest|komp:jsTest|jsLegacy</externalSystemTestTask> <externalSystemTestTask>jsLegacyBrowserTest|komp:jsTest|jsLegacy</externalSystemTestTask>
</externalSystemTestTasks> </externalSystemTestTasks>
<compilerSettings /> <compilerSettings />
<compilerArguments> <compilerArguments>
<option name="languageVersion" value="1.5" /> <option name="languageVersion" value="1.4" />
<option name="apiVersion" value="1.5" /> <option name="apiVersion" value="1.4" />
<option name="pluginOptions"> <option name="pluginOptions">
<array /> <array />
</option> </option>
<option name="pluginClasspaths"> <option name="pluginClasspaths">
<array> <array>
<option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-scripting-jvm/1.5.21/8143908a15163e634fecb87013ed4a139170b032/kotlin-scripting-jvm-1.5.21.jar" /> <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-scripting-jvm/1.4.30/7d0085e5781847da84580d16239c1c4e0980bdb0/kotlin-scripting-jvm-1.4.30.jar" />
<option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-scripting-common/1.5.21/5d271f9e7e7191902f8c0d45c600f5b57a284036/kotlin-scripting-common-1.5.21.jar" /> <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-scripting-common/1.4.30/c7896c5c6b504f44e7cf9f5719d4393e20680666/kotlin-scripting-common-1.4.30.jar" />
<option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlinx/kotlinx-coroutines-core/1.3.8/f62be6d4cbf27781c2969867b4ed952f38378492/kotlinx-coroutines-core-1.3.8.jar" /> <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlinx/kotlinx-coroutines-core/1.3.8/f62be6d4cbf27781c2969867b4ed952f38378492/kotlinx-coroutines-core-1.3.8.jar" />
<option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib/1.5.21/2f537cad7e9eeb9da73738c8812e1e4cf9b62e4e/kotlin-stdlib-1.5.21.jar" /> <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib/1.4.30/d10d1e10f47006ee08162dde039e38ac487de4ac/kotlin-stdlib-1.4.30.jar" />
<option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-common/1.4.30/bb9a3173350f55732416ee27956ea8f9b81f4dbb/kotlin-stdlib-common-1.4.30.jar" />
<option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains/annotations/13.0/919f0dfe192fb4e063e7dacadee7f8bb9a2672a9/annotations-13.0.jar" /> <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains/annotations/13.0/919f0dfe192fb4e063e7dacadee7f8bb9a2672a9/annotations-13.0.jar" />
<option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-common/1.5.21/cc8bf3586fd2ebcf234058b9440bb406e62dfacb/kotlin-stdlib-common-1.5.21.jar" /> <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-script-runtime/1.4.30/b9c2a1fab9217623fc0fbadf6190e77eed6f054d/kotlin-script-runtime-1.4.30.jar" />
<option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-script-runtime/1.5.21/96d49e89873fde985750af354b6eabb60cfa999b/kotlin-script-runtime-1.5.21.jar" />
</array> </array>
</option> </option>
<option name="multiPlatform" value="true" /> <option name="multiPlatform" value="true" />
@@ -36,9 +36,9 @@
<orderEntry type="jdk" jdkName="Kotlin SDK" jdkType="KotlinSDK" /> <orderEntry type="jdk" jdkName="Kotlin SDK" jdkType="KotlinSDK" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="komp.commonMain" scope="TEST" /> <orderEntry type="module" module-name="komp.commonMain" scope="TEST" />
<orderEntry type="library" scope="TEST" name="Gradle: org.jetbrains.kotlin:kotlin-stdlib-common:1.5.21" level="project" /> <orderEntry type="library" scope="TEST" name="Gradle: org.jetbrains.kotlin:kotlin-stdlib-js:1.4.30" level="project" />
<orderEntry type="library" scope="TEST" name="Gradle: org.jetbrains.kotlin:kotlin-stdlib-js:1.5.21" level="project" /> <orderEntry type="library" scope="TEST" name="Gradle: org.jetbrains.kotlinx:kotlinx-html-common:0.7.2" level="project" />
<orderEntry type="library" scope="TEST" name="Gradle: org.jetbrains.kotlinx:kotlinx-html-common:0.7.3" level="project" /> <orderEntry type="library" scope="TEST" name="Gradle: org.jetbrains.kotlin:kotlin-stdlib-common:1.4.30" level="project" />
</component> </component>
<component name="TestModuleProperties" production-module="komp.commonMain" /> <component name="TestModuleProperties" production-module="komp.commonMain" />
</module> </module>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?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.5.6-SNAPSHOT" type="JAVA_MODULE" version="4"> <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.2.4-SNAPSHOT" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true"> <component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output /> <exclude-output />
<content url="file://$MODULE_DIR$"> <content url="file://$MODULE_DIR$">

200
komp.ipr
View File

@@ -49,60 +49,6 @@
<element id="module-output" name="komp.jsMain" /> <element id="module-output" name="komp.jsMain" />
</root> </root>
</artifact> </artifact>
<artifact type="jar" name="komp-jslegacy-0.2.5-SNAPSHOT">
<output-path>$PROJECT_DIR$/build/libs</output-path>
<root id="archive" name="komp-jslegacy-0.2.5-SNAPSHOT.jar">
<element id="module-output" name="komp.jsMain" />
</root>
</artifact>
<artifact type="jar" name="komp-jslegacy-0.3.0-SNAPSHOT">
<output-path>$PROJECT_DIR$/build/libs</output-path>
<root id="archive" name="komp-jslegacy-0.3.0-SNAPSHOT.jar">
<element id="module-output" name="komp.jsMain" />
</root>
</artifact>
<artifact type="jar" name="komp-jslegacy-0.4.0-SNAPSHOT">
<output-path>$PROJECT_DIR$/build/libs</output-path>
<root id="archive" name="komp-jslegacy-0.4.0-SNAPSHOT.jar">
<element id="module-output" name="komp.jsMain" />
</root>
</artifact>
<artifact type="jar" name="komp-jslegacy-0.4.1">
<output-path>$PROJECT_DIR$/build/libs</output-path>
<root id="archive" name="komp-jslegacy-0.4.1.jar">
<element id="module-output" name="komp.jsMain" />
</root>
</artifact>
<artifact type="jar" name="komp-jslegacy-0.5.1">
<output-path>$PROJECT_DIR$/build/libs</output-path>
<root id="archive" name="komp-jslegacy-0.5.1.jar">
<element id="module-output" name="komp.jsMain" />
</root>
</artifact>
<artifact type="jar" name="komp-jslegacy-0.5.2">
<output-path>$PROJECT_DIR$/build/libs</output-path>
<root id="archive" name="komp-jslegacy-0.5.2.jar">
<element id="module-output" name="komp.jsMain" />
</root>
</artifact>
<artifact type="jar" name="komp-jslegacy-0.5.3">
<output-path>$PROJECT_DIR$/build/libs</output-path>
<root id="archive" name="komp-jslegacy-0.5.3.jar">
<element id="module-output" name="komp.jsMain" />
</root>
</artifact>
<artifact type="jar" name="komp-jslegacy-0.5.4">
<output-path>$PROJECT_DIR$/build/libs</output-path>
<root id="archive" name="komp-jslegacy-0.5.4.jar">
<element id="module-output" name="komp.jsMain" />
</root>
</artifact>
<artifact type="jar" name="komp-jslegacy-0.5.6-SNAPSHOT">
<output-path>$PROJECT_DIR$/build/libs</output-path>
<root id="archive" name="komp-jslegacy-0.5.6-SNAPSHOT.jar">
<element id="module-output" name="komp.jsMain" />
</root>
</artifact>
</component> </component>
<component name="CheckStyle-IDEA"> <component name="CheckStyle-IDEA">
<option name="configuration"> <option name="configuration">
@@ -302,80 +248,6 @@
</group> </group>
</component> </component>
<component name="PhpWorkspaceProjectConfiguration" backward_compatibility_performed="true" /> <component name="PhpWorkspaceProjectConfiguration" backward_compatibility_performed="true" />
<component name="ProjectCodeStyleConfiguration">
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
<code_scheme name="Project" version="173">
<option name="LINE_SEPARATOR" value="&#10;" />
<option name="RIGHT_MARGIN" value="140" />
<H2CodeStyleSettings version="6">
<option name="USE_GENERAL_STYLE" value="false" />
</H2CodeStyleSettings>
<H2CodeStyleSettings version="6">
<option name="USE_GENERAL_STYLE" value="false" />
</H2CodeStyleSettings>
<JavaCodeStyleSettings>
<option name="ANNOTATION_PARAMETER_WRAP" value="5" />
<option name="ALIGN_MULTILINE_ANNOTATION_PARAMETERS" value="true" />
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="50" />
</JavaCodeStyleSettings>
<JetCodeStyleSettings>
<option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="99" />
<option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="99" />
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</JetCodeStyleSettings>
<codeStyleSettings language="JAVA">
<option name="KEEP_FIRST_COLUMN_COMMENT" value="false" />
<option name="ALIGN_MULTILINE_CHAINED_METHODS" value="true" />
<option name="ALIGN_MULTILINE_PARAMETERS_IN_CALLS" value="true" />
<option name="ALIGN_MULTILINE_BINARY_OPERATION" value="true" />
<option name="ALIGN_MULTILINE_TERNARY_OPERATION" value="true" />
<option name="ALIGN_MULTILINE_EXTENDS_LIST" value="true" />
<option name="ALIGN_MULTILINE_ARRAY_INITIALIZER_EXPRESSION" value="true" />
<option name="ALIGN_GROUP_FIELD_DECLARATIONS" value="true" />
<option name="ALIGN_CONSECUTIVE_VARIABLE_DECLARATIONS" value="true" />
<option name="ALIGN_CONSECUTIVE_ASSIGNMENTS" value="true" />
<option name="ALIGN_SUBSEQUENT_SIMPLE_METHODS" value="true" />
<option name="CALL_PARAMETERS_WRAP" value="5" />
<option name="CALL_PARAMETERS_LPAREN_ON_NEXT_LINE" value="true" />
<option name="CALL_PARAMETERS_RPAREN_ON_NEXT_LINE" value="true" />
<option name="METHOD_PARAMETERS_WRAP" value="5" />
<option name="METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE" value="true" />
<option name="METHOD_PARAMETERS_RPAREN_ON_NEXT_LINE" value="true" />
<option name="RESOURCE_LIST_WRAP" value="5" />
<option name="RESOURCE_LIST_LPAREN_ON_NEXT_LINE" value="true" />
<option name="RESOURCE_LIST_RPAREN_ON_NEXT_LINE" value="true" />
<option name="EXTENDS_LIST_WRAP" value="5" />
<option name="THROWS_LIST_WRAP" value="5" />
<option name="THROWS_KEYWORD_WRAP" value="1" />
<option name="METHOD_CALL_CHAIN_WRAP" value="5" />
<option name="PARENTHESES_EXPRESSION_LPAREN_WRAP" value="true" />
<option name="PARENTHESES_EXPRESSION_RPAREN_WRAP" value="true" />
<option name="BINARY_OPERATION_WRAP" value="5" />
<option name="TERNARY_OPERATION_WRAP" value="5" />
<option name="FOR_STATEMENT_WRAP" value="5" />
<option name="FOR_STATEMENT_LPAREN_ON_NEXT_LINE" value="true" />
<option name="FOR_STATEMENT_RPAREN_ON_NEXT_LINE" value="true" />
<option name="ARRAY_INITIALIZER_WRAP" value="5" />
<option name="ARRAY_INITIALIZER_LBRACE_ON_NEXT_LINE" value="true" />
<option name="ARRAY_INITIALIZER_RBRACE_ON_NEXT_LINE" value="true" />
<option name="ASSERT_STATEMENT_WRAP" value="5" />
<option name="IF_BRACE_FORCE" value="3" />
<option name="DOWHILE_BRACE_FORCE" value="3" />
<option name="WHILE_BRACE_FORCE" value="3" />
<option name="FOR_BRACE_FORCE" value="3" />
<option name="ENUM_CONSTANTS_WRAP" value="5" />
</codeStyleSettings>
<codeStyleSettings language="kotlin">
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
<indentOptions>
<option name="INDENT_SIZE" value="2" />
<option name="CONTINUATION_INDENT_SIZE" value="4" />
<option name="TAB_SIZE" value="2" />
</indentOptions>
</codeStyleSettings>
</code_scheme>
</component>
<component name="ProjectModuleManager"> <component name="ProjectModuleManager">
<modules> <modules>
<module fileurl="file://$PROJECT_DIR$/komp.iml" filepath="$PROJECT_DIR$/komp.iml" /> <module fileurl="file://$PROJECT_DIR$/komp.iml" filepath="$PROJECT_DIR$/komp.iml" />
@@ -383,8 +255,6 @@
<module fileurl="file://$PROJECT_DIR$/komp.commonTest.iml" filepath="$PROJECT_DIR$/komp.commonTest.iml" /> <module fileurl="file://$PROJECT_DIR$/komp.commonTest.iml" filepath="$PROJECT_DIR$/komp.commonTest.iml" />
<module fileurl="file://$PROJECT_DIR$/komp.jsMain.iml" filepath="$PROJECT_DIR$/komp.jsMain.iml" /> <module fileurl="file://$PROJECT_DIR$/komp.jsMain.iml" filepath="$PROJECT_DIR$/komp.jsMain.iml" />
<module fileurl="file://$PROJECT_DIR$/komp.jsTest.iml" filepath="$PROJECT_DIR$/komp.jsTest.iml" /> <module fileurl="file://$PROJECT_DIR$/komp.jsTest.iml" filepath="$PROJECT_DIR$/komp.jsTest.iml" />
<module fileurl="file://$PROJECT_DIR$/komp_main.iml" filepath="$PROJECT_DIR$/komp_main.iml" group="komp" />
<module fileurl="file://$PROJECT_DIR$/komp_test.iml" filepath="$PROJECT_DIR$/komp_test.iml" group="komp" />
</modules> </modules>
</component> </component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" 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">
@@ -426,13 +296,6 @@
<option name="url" value="https://jcenter.bintray.com/" /> <option name="url" value="https://jcenter.bintray.com/" />
</remote-repository> </remote-repository>
</component> </component>
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="com.android.tools.idea.compose.preview.runconfiguration.ComposePreviewRunConfigurationProducer" />
</set>
</option>
</component>
<component name="RunManager"> <component name="RunManager">
<configuration default="true" type="Applet" factoryName="Applet"> <configuration default="true" type="Applet" factoryName="Applet">
<option name="WIDTH" value="400" /> <option name="WIDTH" value="400" />
@@ -496,6 +359,7 @@
<mapping directory="" vcs="Git" /> <mapping directory="" vcs="Git" />
</component> </component>
<component name="accountSettings"> <component name="accountSettings">
<option name="activeRegion" value="us-east-1" />
<option name="recentlyUsedRegions"> <option name="recentlyUsedRegions">
<list> <list>
<option value="us-east-1" /> <option value="us-east-1" />
@@ -503,51 +367,67 @@
</option> </option>
</component> </component>
<component name="libraryTable"> <component name="libraryTable">
<library name="Gradle: org.jetbrains.kotlin:kotlin-stdlib-common:1.5.21" type="kotlin.common"> <library name="Gradle: org.jetbrains.kotlin:kotlin-stdlib-common:1.4.30" type="kotlin.common">
<CLASSES> <CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-common/1.5.21/cc8bf3586fd2ebcf234058b9440bb406e62dfacb/kotlin-stdlib-common-1.5.21.jar!/" /> <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-common/1.4.30/bb9a3173350f55732416ee27956ea8f9b81f4dbb/kotlin-stdlib-common-1.4.30.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-common/1.5.21/5b8f86fea035328fc9e8c660773037a3401ce25f/kotlin-stdlib-common-1.5.21-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-common/1.5.21/64f0dd5eac2d479a65bc077185d9a8f661c948fe/kotlin-stdlib-common-1.5.21-sources.jar!/" />
</SOURCES>
</library>
<library name="Gradle: org.jetbrains.kotlin:kotlin-stdlib-js:1.5.21" type="kotlin.js">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-js/1.5.21/9b22e0c2e0dcf2ba9f27e45a48944d05b0384bc3/kotlin-stdlib-js-1.5.21.jar!/" />
</CLASSES> </CLASSES>
<JAVADOC /> <JAVADOC />
<SOURCES> <SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-js/1.5.21/dcd3e87dab1d7ecc7f2952d5d213e20f977bbddc/kotlin-stdlib-js-1.5.21-sources.jar!/" /> <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-common/1.4.30/9427471650876e86fdb0dd878f147ff15c57eac0/kotlin-stdlib-common-1.4.30-sources.jar!/" />
</SOURCES> </SOURCES>
</library> </library>
<library name="Gradle: org.jetbrains.kotlin:kotlin-test-js:1.5.21" type="kotlin.js"> <library name="Gradle: org.jetbrains.kotlin:kotlin-stdlib-js:1.4.30" type="kotlin.js">
<CLASSES> <CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-test-js/1.5.21/db9c8e994715fb1edd5bef91db179b60347cbfc9/kotlin-test-js-1.5.21.jar!/" /> <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-js/1.4.30/6c66d1db9c724b087c3a6f37aecffd24d0b14f26/kotlin-stdlib-js-1.4.30.jar!/" />
</CLASSES> </CLASSES>
<JAVADOC /> <JAVADOC />
<SOURCES> <SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-test-js/1.5.21/8e70170db077d3f421c3fb6d24468b3938990f4a/kotlin-test-js-1.5.21-sources.jar!/" /> <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-js/1.4.30/5729944dc91bf28689461fe44b9e401fd41a84a7/kotlin-stdlib-js-1.4.30-sources.jar!/" />
</SOURCES> </SOURCES>
</library> </library>
<library name="Gradle: org.jetbrains.kotlinx:kotlinx-html-common:0.7.3" type="kotlin.common"> <library name="Gradle: org.jetbrains.kotlin:kotlin-test-annotations-common:1.4.30" type="kotlin.common">
<CLASSES> <CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlinx/kotlinx-html-common/0.7.3/4f3df7b2096bce6fef3e532ca1ccff13bd15a6bc/kotlinx-html-metadata-0.7.3.jar!/" /> <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-test-annotations-common/1.4.30/e77a76b23fc3007baf57a9d3354fdd318fe1fa88/kotlin-test-annotations-common-1.4.30.jar!/" />
</CLASSES> </CLASSES>
<JAVADOC /> <JAVADOC />
<SOURCES> <SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlinx/kotlinx-html-common/0.7.3/f4eb48699d893b863f142a3c30e1ddddd13b876/kotlinx-html-common-0.7.3-sources.jar!/" /> <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-test-annotations-common/1.4.30/57512e29ee20defe37d54ce19507d599b0f2113/kotlin-test-annotations-common-1.4.30-sources.jar!/" />
</SOURCES> </SOURCES>
</library> </library>
<library name="Gradle: org.jetbrains.kotlinx:kotlinx-html-js:0.7.3" type="kotlin.js"> <library name="Gradle: org.jetbrains.kotlin:kotlin-test-common:1.4.30" type="kotlin.common">
<CLASSES> <CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlinx/kotlinx-html-js/0.7.3/93a1ab4269d3a567e05088d1237eedbc2efd03c9/kotlinx-html-jslegacy-0.7.3.jar!/" /> <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-test-common/1.4.30/823ed87441680d1334a1f0d23781c0089e16c0a6/kotlin-test-common-1.4.30.jar!/" />
</CLASSES> </CLASSES>
<JAVADOC /> <JAVADOC />
<SOURCES> <SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlinx/kotlinx-html-js/0.7.3/fc3bc71d1c037b715689112c95c44b96bb2409ea/kotlinx-html-js-0.7.3-sources.jar!/" /> <root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-test-common/1.4.30/d1818d1bdc457b51289f006884a260b56a55cb77/kotlin-test-common-1.4.30-sources.jar!/" />
</SOURCES>
</library>
<library name="Gradle: org.jetbrains.kotlin:kotlin-test-js:1.4.30" type="kotlin.js">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-test-js/1.4.30/5b1cb1ec31a344f6aa1047d6cae3a268825cb724/kotlin-test-js-1.4.30.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-test-js/1.4.30/8e70170db077d3f421c3fb6d24468b3938990f4a/kotlin-test-js-1.4.30-sources.jar!/" />
</SOURCES>
</library>
<library name="Gradle: org.jetbrains.kotlinx:kotlinx-html-common:0.7.2" type="kotlin.common">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlinx/kotlinx-html-common/0.7.2/7da838083337896b558cab2884c4118709a58769/kotlinx-html-metadata-0.7.2.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlinx/kotlinx-html-common/0.7.2/866bbbfe0a81d49cdf19fd149adafbb938b35be4/kotlinx-html-common-0.7.2-sources.jar!/" />
</SOURCES>
</library>
<library name="Gradle: org.jetbrains.kotlinx:kotlinx-html-js:0.7.2" type="kotlin.js">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlinx/kotlinx-html-js/0.7.2/baf7e494e549776d0ae3e0ee225804a513f5dc26/kotlinx-html-jslegacy-0.7.2.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlinx/kotlinx-html-js/0.7.2/b09bfd3565058174afa3fd0888743f8b8dca5406/kotlinx-html-js-0.7.2-sources.jar!/" />
</SOURCES> </SOURCES>
</library> </library>
</component> </component>

View File

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id="komp:jsMain" 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.type="sourceSet" external.system.module.version="0.5.6-SNAPSHOT" type="JAVA_MODULE" version="4"> <module external.linked.project.id="komp:jsMain" 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.type="sourceSet" external.system.module.version="0.2.4-SNAPSHOT" type="JAVA_MODULE" version="4">
<component name="FacetManager"> <component name="FacetManager">
<facet type="kotlin-language" name="Kotlin"> <facet type="kotlin-language" name="Kotlin">
<configuration version="3" platform="JavaScript " allPlatforms="JS []" useProjectSettings="false" isTestModule="false" externalProjectId="komp" pureKotlinSourceFolders="$MODULE_DIR$/src/jsMain/kotlin;/home/rnentjes/Development/komp/komp/build/externals/komp-js-legacy/src;/home/rnentjes/Development/komp/komp/build/externals/komp-js-ir/src;/home/rnentjes/Development/komp/komp/src/jsTest/kotlin"> <configuration version="3" platform="JavaScript " allPlatforms="JS []" useProjectSettings="false" isTestModule="false" externalProjectId="komp" pureKotlinSourceFolders="$MODULE_DIR$/src/jsMain/kotlin;/home/rnentjes/Development/komp/komp/build/externals/komp-jsLegacy/src;/home/rnentjes/Development/komp/komp/build/externals/komp-jsIr/src;/home/rnentjes/Development/komp/komp/src/jsTest/kotlin;/home/rnentjes/Development/komp/komp/src/commonMain/kotlin">
<dependsOnModuleNames>komp:commonMain</dependsOnModuleNames> <dependsOnModuleNames>komp:commonMain</dependsOnModuleNames>
<sourceSets> <sourceSets>
<sourceSet>komp.commonMain</sourceSet> <sourceSet>komp.commonMain</sourceSet>
@@ -10,25 +10,25 @@
<newMppModelJpsModuleKind>COMPILATION_AND_SOURCE_SET_HOLDER</newMppModelJpsModuleKind> <newMppModelJpsModuleKind>COMPILATION_AND_SOURCE_SET_HOLDER</newMppModelJpsModuleKind>
<compilerSettings /> <compilerSettings />
<compilerArguments> <compilerArguments>
<option name="outputFile" value="$MODULE_DIR$/build/js/packages/komp-js-legacy/kotlin/komp-js-legacy.js" /> <option name="outputFile" value="$MODULE_DIR$/build/js/packages/komp-jsLegacy/kotlin/komp-jsLegacy.js" />
<option name="noStdlib" value="true" /> <option name="noStdlib" value="true" />
<option name="sourceMap" value="true" /> <option name="sourceMap" value="true" />
<option name="metaInfo" value="true" /> <option name="metaInfo" value="true" />
<option name="target" value="v5" /> <option name="target" value="v5" />
<option name="moduleKind" value="umd" /> <option name="moduleKind" value="umd" />
<option name="main" value="call" /> <option name="main" value="call" />
<option name="languageVersion" value="1.5" /> <option name="languageVersion" value="1.4" />
<option name="apiVersion" value="1.5" /> <option name="apiVersion" value="1.4" />
<option name="pluginOptions"> <option name="pluginOptions">
<array /> <array />
</option> </option>
<option name="pluginClasspaths"> <option name="pluginClasspaths">
<array> <array>
<option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-script-runtime/1.5.21/96d49e89873fde985750af354b6eabb60cfa999b/kotlin-script-runtime-1.5.21.jar" /> <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-script-runtime/1.4.30/b9c2a1fab9217623fc0fbadf6190e77eed6f054d/kotlin-script-runtime-1.4.30.jar" />
<option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-scripting-common/1.5.21/5d271f9e7e7191902f8c0d45c600f5b57a284036/kotlin-scripting-common-1.5.21.jar" /> <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-scripting-common/1.4.30/c7896c5c6b504f44e7cf9f5719d4393e20680666/kotlin-scripting-common-1.4.30.jar" />
<option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-scripting-jvm/1.5.21/8143908a15163e634fecb87013ed4a139170b032/kotlin-scripting-jvm-1.5.21.jar" /> <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-scripting-jvm/1.4.30/7d0085e5781847da84580d16239c1c4e0980bdb0/kotlin-scripting-jvm-1.4.30.jar" />
<option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-common/1.5.21/cc8bf3586fd2ebcf234058b9440bb406e62dfacb/kotlin-stdlib-common-1.5.21.jar" /> <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-common/1.4.30/bb9a3173350f55732416ee27956ea8f9b81f4dbb/kotlin-stdlib-common-1.4.30.jar" />
<option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib/1.5.21/2f537cad7e9eeb9da73738c8812e1e4cf9b62e4e/kotlin-stdlib-1.5.21.jar" /> <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib/1.4.30/d10d1e10f47006ee08162dde039e38ac487de4ac/kotlin-stdlib-1.4.30.jar" />
<option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlinx/kotlinx-coroutines-core/1.3.8/f62be6d4cbf27781c2969867b4ed952f38378492/kotlinx-coroutines-core-1.3.8.jar" /> <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlinx/kotlinx-coroutines-core/1.3.8/f62be6d4cbf27781c2969867b4ed952f38378492/kotlinx-coroutines-core-1.3.8.jar" />
<option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains/annotations/13.0/919f0dfe192fb4e063e7dacadee7f8bb9a2672a9/annotations-13.0.jar" /> <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains/annotations/13.0/919f0dfe192fb4e063e7dacadee7f8bb9a2672a9/annotations-13.0.jar" />
</array> </array>
@@ -42,18 +42,18 @@
</facet> </facet>
</component> </component>
<component name="NewModuleRootManager"> <component name="NewModuleRootManager">
<output url="file://$MODULE_DIR$/build/js/packages/komp-js-legacy/kotlin" /> <output url="file://$MODULE_DIR$/build/js/packages/komp-jsLegacy/kotlin" />
<exclude-output /> <exclude-output />
<content url="file://$MODULE_DIR$/build/externals/komp-js-ir/src" /> <content url="file://$MODULE_DIR$/build/externals/komp-jsIr/src" />
<content url="file://$MODULE_DIR$/build/externals/komp-js-legacy/src" /> <content url="file://$MODULE_DIR$/build/externals/komp-jsLegacy/src" />
<content url="file://$MODULE_DIR$/src/jsMain"> <content url="file://$MODULE_DIR$/src/jsMain">
<sourceFolder url="file://$MODULE_DIR$/src/jsMain/kotlin" type="kotlin-source" /> <sourceFolder url="file://$MODULE_DIR$/src/jsMain/kotlin" type="kotlin-source" />
</content> </content>
<orderEntry type="jdk" jdkName="Kotlin SDK" jdkType="KotlinSDK" /> <orderEntry type="jdk" jdkName="Kotlin SDK" jdkType="KotlinSDK" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="komp.commonMain" /> <orderEntry type="module" module-name="komp.commonMain" />
<orderEntry type="library" name="Gradle: org.jetbrains.kotlinx:kotlinx-html-js:0.7.3" level="project" /> <orderEntry type="library" name="Gradle: org.jetbrains.kotlinx:kotlinx-html-js:0.7.2" level="project" />
<orderEntry type="library" name="Gradle: org.jetbrains.kotlin:kotlin-stdlib-js:1.5.21" level="project" /> <orderEntry type="library" name="Gradle: org.jetbrains.kotlin:kotlin-stdlib-js:1.4.30" level="project" />
<orderEntry type="library" name="Gradle: org.jetbrains.kotlin:kotlin-stdlib-common:1.5.21" level="project" /> <orderEntry type="library" name="Gradle: org.jetbrains.kotlin:kotlin-stdlib-common:1.4.30" level="project" />
</component> </component>
</module> </module>

View File

@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id="komp:jsTest" 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.type="sourceSet" external.system.module.version="0.5.6-SNAPSHOT" type="JAVA_MODULE" version="4"> <module external.linked.project.id="komp:jsTest" 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.type="sourceSet" external.system.module.version="0.2.4-SNAPSHOT" type="JAVA_MODULE" version="4">
<component name="FacetManager"> <component name="FacetManager">
<facet type="kotlin-language" name="Kotlin"> <facet type="kotlin-language" name="Kotlin">
<configuration version="3" platform="JavaScript " allPlatforms="JS []" useProjectSettings="false" isTestModule="true" externalProjectId="komp" pureKotlinSourceFolders="$MODULE_DIR$/src/jsMain/kotlin;/home/rnentjes/Development/komp/komp/build/externals/komp-js-legacy/src;/home/rnentjes/Development/komp/komp/build/externals/komp-js-ir/src;/home/rnentjes/Development/komp/komp/src/jsTest/kotlin"> <configuration version="3" platform="JavaScript " allPlatforms="JS []" useProjectSettings="false" isTestModule="true" externalProjectId="komp" pureKotlinSourceFolders="$MODULE_DIR$/src/jsMain/kotlin;/home/rnentjes/Development/komp/komp/build/externals/komp-jsLegacy/src;/home/rnentjes/Development/komp/komp/build/externals/komp-jsIr/src;/home/rnentjes/Development/komp/komp/src/jsTest/kotlin;/home/rnentjes/Development/komp/komp/src/commonMain/kotlin">
<dependsOnModuleNames>komp:commonTest</dependsOnModuleNames> <dependsOnModuleNames>komp:commonTest</dependsOnModuleNames>
<sourceSets> <sourceSets>
<sourceSet>komp.commonTest</sourceSet>
<sourceSet>komp.jsMain</sourceSet> <sourceSet>komp.jsMain</sourceSet>
<sourceSet>komp.commonTest</sourceSet>
<sourceSet>komp.commonMain</sourceSet> <sourceSet>komp.commonMain</sourceSet>
</sourceSets> </sourceSets>
<newMppModelJpsModuleKind>COMPILATION_AND_SOURCE_SET_HOLDER</newMppModelJpsModuleKind> <newMppModelJpsModuleKind>COMPILATION_AND_SOURCE_SET_HOLDER</newMppModelJpsModuleKind>
@@ -15,25 +15,25 @@
</externalSystemTestTasks> </externalSystemTestTasks>
<compilerSettings /> <compilerSettings />
<compilerArguments> <compilerArguments>
<option name="outputFile" value="$MODULE_DIR$/build/js/packages/komp-js-legacy-test/kotlin/komp-js-legacy-test.js" /> <option name="outputFile" value="$MODULE_DIR$/build/js/packages/komp-jsLegacy-test/kotlin/komp-jsLegacy-test.js" />
<option name="noStdlib" value="true" /> <option name="noStdlib" value="true" />
<option name="sourceMap" value="true" /> <option name="sourceMap" value="true" />
<option name="metaInfo" value="true" /> <option name="metaInfo" value="true" />
<option name="target" value="v5" /> <option name="target" value="v5" />
<option name="moduleKind" value="umd" /> <option name="moduleKind" value="umd" />
<option name="main" value="call" /> <option name="main" value="call" />
<option name="languageVersion" value="1.5" /> <option name="languageVersion" value="1.4" />
<option name="apiVersion" value="1.5" /> <option name="apiVersion" value="1.4" />
<option name="pluginOptions"> <option name="pluginOptions">
<array /> <array />
</option> </option>
<option name="pluginClasspaths"> <option name="pluginClasspaths">
<array> <array>
<option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-script-runtime/1.5.21/96d49e89873fde985750af354b6eabb60cfa999b/kotlin-script-runtime-1.5.21.jar" /> <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-script-runtime/1.4.30/b9c2a1fab9217623fc0fbadf6190e77eed6f054d/kotlin-script-runtime-1.4.30.jar" />
<option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-scripting-common/1.5.21/5d271f9e7e7191902f8c0d45c600f5b57a284036/kotlin-scripting-common-1.5.21.jar" /> <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-scripting-common/1.4.30/c7896c5c6b504f44e7cf9f5719d4393e20680666/kotlin-scripting-common-1.4.30.jar" />
<option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-scripting-jvm/1.5.21/8143908a15163e634fecb87013ed4a139170b032/kotlin-scripting-jvm-1.5.21.jar" /> <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-scripting-jvm/1.4.30/7d0085e5781847da84580d16239c1c4e0980bdb0/kotlin-scripting-jvm-1.4.30.jar" />
<option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-common/1.5.21/cc8bf3586fd2ebcf234058b9440bb406e62dfacb/kotlin-stdlib-common-1.5.21.jar" /> <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-common/1.4.30/bb9a3173350f55732416ee27956ea8f9b81f4dbb/kotlin-stdlib-common-1.4.30.jar" />
<option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib/1.5.21/2f537cad7e9eeb9da73738c8812e1e4cf9b62e4e/kotlin-stdlib-1.5.21.jar" /> <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib/1.4.30/d10d1e10f47006ee08162dde039e38ac487de4ac/kotlin-stdlib-1.4.30.jar" />
<option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlinx/kotlinx-coroutines-core/1.3.8/f62be6d4cbf27781c2969867b4ed952f38378492/kotlinx-coroutines-core-1.3.8.jar" /> <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlinx/kotlinx-coroutines-core/1.3.8/f62be6d4cbf27781c2969867b4ed952f38378492/kotlinx-coroutines-core-1.3.8.jar" />
<option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains/annotations/13.0/919f0dfe192fb4e063e7dacadee7f8bb9a2672a9/annotations-13.0.jar" /> <option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.jetbrains/annotations/13.0/919f0dfe192fb4e063e7dacadee7f8bb9a2672a9/annotations-13.0.jar" />
</array> </array>
@@ -47,7 +47,7 @@
</facet> </facet>
</component> </component>
<component name="NewModuleRootManager"> <component name="NewModuleRootManager">
<output-test url="file://$MODULE_DIR$/build/js/packages/komp-js-legacy-test/kotlin" /> <output-test url="file://$MODULE_DIR$/build/js/packages/komp-jsLegacy-test/kotlin" />
<exclude-output /> <exclude-output />
<content url="file://$MODULE_DIR$/src/jsTest"> <content url="file://$MODULE_DIR$/src/jsTest">
<sourceFolder url="file://$MODULE_DIR$/src/jsTest/kotlin" type="kotlin-test" /> <sourceFolder url="file://$MODULE_DIR$/src/jsTest/kotlin" type="kotlin-test" />
@@ -58,29 +58,13 @@
<orderEntry type="module" module-name="komp.commonTest" scope="TEST" production-on-test="" /> <orderEntry type="module" module-name="komp.commonTest" scope="TEST" production-on-test="" />
<orderEntry type="module" module-name="komp.jsMain" scope="TEST" /> <orderEntry type="module" module-name="komp.jsMain" scope="TEST" />
<orderEntry type="module" module-name="komp.jsMain" scope="RUNTIME" /> <orderEntry type="module" module-name="komp.jsMain" scope="RUNTIME" />
<orderEntry type="module-library" scope="PROVIDED"> <orderEntry type="library" scope="TEST" name="Gradle: org.jetbrains.kotlinx:kotlinx-html-js:0.7.2" level="project" />
<library name="Gradle: nl.astraeus:komp"> <orderEntry type="library" scope="TEST" name="Gradle: org.jetbrains.kotlin:kotlin-test-js:1.4.30" level="project" />
<CLASSES> <orderEntry type="library" scope="TEST" name="Gradle: org.jetbrains.kotlin:kotlin-stdlib-js:1.4.30" level="project" />
<root url="file://$MODULE_DIR$/build/classes/kotlin/jsIr/main" /> <orderEntry type="library" scope="TEST" name="Gradle: org.jetbrains.kotlinx:kotlinx-html-common:0.7.2" level="project" />
</CLASSES> <orderEntry type="library" scope="TEST" name="Gradle: org.jetbrains.kotlin:kotlin-stdlib-common:1.4.30" level="project" />
<JAVADOC /> <orderEntry type="library" scope="TEST" name="Gradle: org.jetbrains.kotlin:kotlin-test-common:1.4.30" level="project" />
<SOURCES /> <orderEntry type="library" scope="TEST" name="Gradle: org.jetbrains.kotlin:kotlin-test-annotations-common:1.4.30" level="project" />
</library>
</orderEntry>
<orderEntry type="module-library" scope="RUNTIME">
<library>
<CLASSES>
<root url="file://$MODULE_DIR$/build/processedResources/jsIr/main" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
<orderEntry type="library" scope="TEST" name="Gradle: org.jetbrains.kotlinx:kotlinx-html-js:0.7.3" level="project" />
<orderEntry type="library" scope="TEST" name="Gradle: org.jetbrains.kotlin:kotlin-test-js:1.5.21" level="project" />
<orderEntry type="library" scope="TEST" name="Gradle: org.jetbrains.kotlinx:kotlinx-html-common:0.7.3" level="project" />
<orderEntry type="library" scope="TEST" name="Gradle: org.jetbrains.kotlin:kotlin-stdlib-js:1.5.21" level="project" />
<orderEntry type="library" scope="TEST" name="Gradle: org.jetbrains.kotlin:kotlin-stdlib-common:1.5.21" level="project" />
</component> </component>
<component name="TestModuleProperties" production-module="komp.jsMain" /> <component name="TestModuleProperties" production-module="komp.jsMain" />
</module> </module>

View File

@@ -12,3 +12,5 @@ pluginManagement {
} }
rootProject.name = "komp" rootProject.name = "komp"
enableFeaturePreview("GRADLE_METADATA")

View File

@@ -0,0 +1,368 @@
package nl.astraeus.komp
import org.w3c.dom.HTMLElement
import org.w3c.dom.HTMLInputElement
import org.w3c.dom.Node
import org.w3c.dom.NodeList
import org.w3c.dom.events.Event
import org.w3c.dom.get
const val HASH_VALUE = "komp-hash-value"
//const val HASH_ATTRIBUTE = "data-komp-hash"
const val EVENT_ATTRIBUTE = "data-komp-events"
fun Node.getKompHash(): Int = this.asDynamic()[HASH_VALUE] as? Int? ?: -1
fun Node.setKompHash(hash: Int) {
this.asDynamic()[HASH_VALUE] = hash
}
private fun NodeList.findNodeHashIndex(hash: Int): Int {
for (index in 0..this.length) {
val node = this[index]
if (node is HTMLElement && node.getKompHash() == hash) {
return index
}
}
return -1
}
object DiffPatch {
fun hashesMatch(oldNode: Node, newNode: Node): Boolean {
return (
oldNode is HTMLElement &&
newNode is HTMLElement &&
oldNode.nodeName == newNode.nodeName &&
oldNode.getKompHash() == newNode.getKompHash()
)
}
private fun updateKomponentOnNode(oldNode: Node, newNode: Node) {
val komponent = newNode.asDynamic()[KOMP_KOMPONENT] as? Komponent
if (komponent != null) {
if (Komponent.logReplaceEvent) {
console.log("Keeping oldNode, set oldNode element on Komponent", oldNode, komponent)
}
komponent.element = oldNode
}
}
fun updateNode(oldNode: Node, newNode: Node): Node {
if (hashesMatch(oldNode, newNode)) {
if (Komponent.logReplaceEvent) {
console.log("Hashes match", oldNode, newNode, oldNode.getKompHash(), newNode.getKompHash())
}
updateKomponentOnNode(oldNode, newNode)
return oldNode
}
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
}
updateKomponentOnNode(oldNode, newNode)
return oldNode
}
if (oldNode is HTMLElement && newNode is HTMLElement) {
if (oldNode.nodeName == newNode.nodeName) {
if (Komponent.logReplaceEvent) {
console.log("Update attributes", oldNode.nodeName, newNode.nodeName)
}
updateAttributes(oldNode, newNode);
if (Komponent.logReplaceEvent) {
console.log("Update events", oldNode.nodeName, newNode.nodeName)
}
updateEvents(oldNode, newNode)
if (Komponent.logReplaceEvent) {
console.log("Update children", oldNode.nodeName, newNode.nodeName)
}
updateChildren(oldNode, newNode)
oldNode.setKompHash(newNode.getKompHash())
updateKomponentOnNode(oldNode, newNode)
return oldNode
}
}
if (Komponent.logReplaceEvent) {
console.log("Replace node (type)", oldNode.nodeType, oldNode, newNode)
}
oldNode.parentNode?.replaceChild(newNode, oldNode)
//replaceNode(oldNode, newNode)
return newNode
}
private fun updateAttributes(oldNode: HTMLElement, newNode: HTMLElement) {
// removed attributes
for (name in oldNode.getAttributeNames()) {
val attr = oldNode.attributes[name]
if (attr != null && newNode.getAttribute(name) == null) {
oldNode.removeAttribute(name)
}
}
for (name in newNode.getAttributeNames()) {
val value = newNode.getAttribute(name)
val oldValue = oldNode.getAttribute(name)
if (value != oldValue) {
if (value != null) {
oldNode.setAttribute(name, value)
}else {
oldNode.removeAttribute(name)
}
}
}
if (newNode is HTMLInputElement && oldNode is HTMLInputElement) {
oldNode.value = newNode.value
}
/*
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) {
var oldIndex = 0
var newIndex = 0
if (Komponent.logReplaceEvent) {
console.log(
"updateChildren HTML old(${oldNode.childNodes.length})",
oldNode.innerHTML
)
console.log(
"updateChildren HTML new(${newNode.childNodes.length})",
newNode.innerHTML
)
}
while (newIndex < newNode.childNodes.length) {
if (Komponent.logReplaceEvent) {
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(">>> updateChildren old/new", oldChildNode, newChildNode)
}
*/
if (Komponent.logReplaceEvent) {
console.log("Update node Old/new", oldChildNode, newChildNode)
}
if (!hashesMatch(oldChildNode, newChildNode) && newChildNode is HTMLElement && oldChildNode is HTMLElement) {
if (Komponent.logReplaceEvent) {
console.log("Hashes don't match")
}
val oldHash = oldChildNode.getKompHash()
val newHash = newChildNode.getKompHash()
if (newHash >= 0) {
val oldNodeWithNewHashIndex = oldNode.childNodes.findNodeHashIndex(newHash)
if (Komponent.logReplaceEvent) {
console.log("oldNodeWithNewHashIndex", newHash, oldNodeWithNewHashIndex)
}
if (oldNodeWithNewHashIndex > oldIndex) {
if (oldHash >= 0) {
val newNodeWithOldHashIndex = newNode.childNodes.findNodeHashIndex(oldHash)
// remove i.o. swap
if (newNodeWithOldHashIndex == -1) {
if (Komponent.logReplaceEvent) {
console.log("Old node missing in new tree, remove node", oldChildNode)
}
oldNode.removeChild(oldChildNode)
continue
}
}
val nodeWithHash = oldNode.childNodes[oldNodeWithNewHashIndex]
if (Komponent.logReplaceEvent) {
console.log("nodeWithHash", nodeWithHash)
}
if (nodeWithHash != null) {
if (Komponent.logReplaceEvent) {
console.log(">-> swap nodes", oldNode)
}
oldNode.insertBefore(nodeWithHash, oldNode.childNodes[oldIndex])
if (Komponent.logReplaceEvent) {
console.log(">-> swapped nodes", oldNode)
}
newIndex++
oldIndex++
continue
}
} else if (oldHash >= 0 && newNode.childNodes.findNodeHashIndex(oldHash) > newIndex) {
if (Komponent.logReplaceEvent) {
console.log("newNodeWithOldHashIndex", oldHash, newNode.childNodes.findNodeHashIndex(oldHash))
}
oldNode.insertBefore(newChildNode, oldChildNode)
oldIndex++
continue
}
}
}
val updatedNode = updateNode(oldChildNode, newChildNode)
if (updatedNode == newChildNode) {
if (oldChildNode is HTMLElement && newChildNode is HTMLElement) {
updateEvents(oldChildNode, newChildNode)
}
oldIndex++
continue
}
} else {
if (Komponent.logReplaceEvent) {
console.log("Null node", oldChildNode, newChildNode)
}
}
oldIndex++
newIndex++
} else {
if (Komponent.logReplaceEvent) {
console.log("Append Old/new/node", oldIndex, newIndex, newChildNode)
}
oldNode.append(newChildNode)
oldIndex++
}
/*
if (Komponent.logReplaceEvent) {
console.log("<<< Updated Old/new", oldNode.innerHTML, newNode.innerHTML)
}
*/
}
while (oldIndex < oldNode.childNodes.length) {
oldNode.childNodes[oldIndex]?.also {
if (Komponent.logReplaceEvent) {
console.log("Remove old node", it)
}
oldNode.removeChild(it)
}
}
}
private fun updateEvents(oldNode: HTMLElement, newNode: HTMLElement) {
val oldEvents = mutableListOf<String>()
oldEvents.addAll((oldNode.getAttribute(EVENT_ATTRIBUTE) ?: "").split(","))
val newEvents = (newNode.getAttribute(EVENT_ATTRIBUTE) ?: "").split(",")
if (Komponent.logReplaceEvent) {
console.log("Update events", oldNode.getAttribute(EVENT_ATTRIBUTE), newNode.getAttribute(EVENT_ATTRIBUTE))
}
for (event in newEvents) {
if (event.isNotBlank()) {
val oldNodeEvent = oldNode.asDynamic()["event-$event"]
val newNodeEvent = newNode.asDynamic()["event-$event"]
if (oldNodeEvent != null) {
if (Komponent.logReplaceEvent) {
console.log("Remove old event $event")
}
oldNode.removeEventListener(event, oldNodeEvent as ((Event) -> Unit), null)
}
if (newNodeEvent != null) {
if (Komponent.logReplaceEvent) {
console.log("Set event $event on", oldNode)
}
oldNode.setEvent(event, newNodeEvent as ((Event) -> Unit))
}
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(EVENT_ATTRIBUTE)?.also {
oldNode.setAttribute(EVENT_ATTRIBUTE, it)
}
}
private fun replaceNode(oldNode: Node, newNode: Node) {
oldNode.parentNode?.also { parent ->
val clone = newNode.cloneNode(true)
cloneEvents(clone, newNode)
parent.replaceChild(clone, oldNode)
}
}
private fun cloneEvents(destination: Node, source: Node) {
if (source is HTMLElement && destination is HTMLElement) {
val events = (source.getAttribute(EVENT_ATTRIBUTE) ?: "").split(",")
for (event in events) {
if (event.isNotBlank()) {
if (Komponent.logReplaceEvent) {
console.log("Clone event $event on", source)
}
val foundEvent = source.asDynamic()["event-$event"]
if (foundEvent != null) {
if (Komponent.logReplaceEvent) {
console.log("Clone add eventlistener", foundEvent)
}
destination.setEvent(event, foundEvent as ((Event) -> Unit))
} else {
if (Komponent.logReplaceEvent) {
console.log("Event not found $event", source)
}
}
}
}
}
for (index in 0 until source.childNodes.length) {
destination.childNodes[index]?.also { destinationChild ->
source.childNodes[index]?.also { sourceChild ->
cloneEvents(destinationChild, sourceChild)
}
}
}
}
}

View File

@@ -1,521 +1,229 @@
package nl.astraeus.komp package nl.astraeus.komp
import kotlinx.browser.document import org.w3c.dom.*
import kotlinx.html.DefaultUnsafe import org.w3c.dom.css.CSSStyleDeclaration
import kotlinx.html.Entities
import kotlinx.html.FlowOrMetaDataOrPhrasingContent
import kotlinx.html.Tag
import kotlinx.html.TagConsumer
import kotlinx.html.Unsafe
import org.w3c.dom.Element
import org.w3c.dom.HTMLElement
import org.w3c.dom.HTMLInputElement
import org.w3c.dom.HTMLSpanElement
import org.w3c.dom.Node
import org.w3c.dom.asList
import org.w3c.dom.events.Event import org.w3c.dom.events.Event
import org.w3c.dom.get import kotlinx.browser.document
import kotlinx.html.*
private var currentElement: Element? = null @Suppress("NOTHING_TO_INLINE")
inline fun HTMLElement.setEvent(name: String, noinline callback: (Event) -> Unit) {
interface HtmlConsumer : TagConsumer<Element> { val eventName = if (name.startsWith("on")) {
fun append(node: Element)
fun include(komponent: Komponent)
fun debug(block: HtmlConsumer.() -> Unit)
}
fun Int.asSpaces(): String {
val result = StringBuilder()
repeat(this) {
result.append(" ")
}
return result.toString()
}
fun FlowOrMetaDataOrPhrasingContent.currentElement(): Element =
currentElement ?: error("No current element defined!")
fun Element.printTree(indent: Int = 0): String {
val result = StringBuilder()
result.append(indent.asSpaces())
result.append(tagName)
if (this.namespaceURI != "http://www.w3.org/1999/xhtml") {
result.append(" [")
result.append(namespaceURI)
result.append("]")
}
result.append(" (")
var first = true
if (hasAttributes()) {
for (index in 0 until attributes.length) {
if (!first) {
result.append(", ")
} else {
first = false
}
result.append(attributes[index]?.localName)
result.append("=")
result.append(attributes[index]?.value)
}
}
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) {
result.append(it.printTree(indent + 2))
} else {
result.append((indent + 2).asSpaces())
result.append(it.textContent)
result.append("\n")
}
}
}
result.append(indent.asSpaces())
result.append("}\n")
return result.toString()
}
private fun Element.clearKompAttributes() {
val attributes = this.asDynamic()["komp-attributes"] as MutableSet<String>?
if (attributes == null) {
this.asDynamic()["komp-attributes"] = mutableSetOf<String>()
} else {
attributes.clear()
}
if (this is HTMLInputElement) {
this.checked = false
}
}
private fun Element.getKompAttributes(): MutableSet<String> {
var result: MutableSet<String>? = this.asDynamic()["komp-attributes"] as MutableSet<String>?
if (result == null) {
result = mutableSetOf()
this.asDynamic()["komp-attributes"] = result
}
return result
}
private fun Element.setKompAttribute(name: String, value: String) {
val setAttrs: MutableSet<String> = getKompAttributes()
setAttrs.add(name)
if (this is HTMLInputElement) {
when (name) {
"checked" -> {
this.checked = value == "checked"
}
"value" -> {
this.value = value
}
else -> {
setAttribute(name, value)
}
}
} else if (this.getAttribute(name) != value) {
setAttribute(name, value)
}
}
private fun Element.clearKompEvents() {
for ((name, event) in getKompEvents()) {
currentElement?.removeEventListener(name, event)
}
val events = this.asDynamic()["komp-events"] as MutableMap<String, (Event) -> Unit>?
if (events == null) {
this.asDynamic()["komp-events"] = mutableMapOf<String, (Event) -> Unit>()
} else {
events.clear()
}
}
private fun Element.setKompEvent(name: String, event: (Event) -> Unit) {
val eventName: String = if (name.startsWith("on")) {
name.substring(2) name.substring(2)
} else { } else {
name name
} }
addEventListener(eventName, callback, null)
if (Komponent.updateStrategy == UpdateStrategy.DOM_DIFF) {
//asDynamic()[name] = callback
val events = getAttribute(EVENT_ATTRIBUTE) ?: ""
val events: MutableMap<String, (Event) -> Unit> = getKompEvents() setAttribute(
EVENT_ATTRIBUTE,
events[eventName]?.let { if (events.isBlank()) {
println("Warn event already defined!") eventName
currentElement?.removeEventListener(eventName, it) } else {
} "$events,$eventName"
}
events[eventName] = event )
asDynamic()["event-$eventName"] = callback
this.asDynamic()["komp-events"] = events
this.addEventListener(eventName, event)
}
private fun Element.getKompEvents(): MutableMap<String, (Event) -> Unit> {
return this.asDynamic()["komp-events"] ?: mutableMapOf()
}
private data class ElementIndex(
val parent: Node,
var childIndex: Int
)
private fun ArrayList<ElementIndex>.currentParent(): Node {
this.lastOrNull()?.let {
return it.parent
}
throw IllegalStateException("currentParent should never be null!")
}
private fun ArrayList<ElementIndex>.currentElement(): Node? {
this.lastOrNull()?.let {
return it.parent.childNodes[it.childIndex]
}
return null
}
private fun ArrayList<ElementIndex>.nextElement() {
this.lastOrNull()?.let {
it.childIndex++
} }
} }
private fun ArrayList<ElementIndex>.pop() { interface HtmlConsumer : TagConsumer<HTMLElement> {
this.removeLast() fun append(node: Node)
} }
private fun ArrayList<ElementIndex>.push(element: Node) { fun HTMLElement.setStyles(cssStyle: CSSStyleDeclaration) {
this.add(ElementIndex(element, 0)) for (index in 0 until cssStyle.length) {
} val propertyName = cssStyle.item(index)
private fun ArrayList<ElementIndex>.replace(new: Node) { style.setProperty(propertyName, cssStyle.getPropertyValue(propertyName))
if (this.currentElement() != null) {
this.currentElement()?.parentElement?.replaceChild(new, this.currentElement()!!)
} else {
this.last().parent.appendChild(new)
} }
} }
private fun Node.asElement() = this as? HTMLElement
class HtmlBuilder( class HtmlBuilder(
val parent: Element, val komponent: Komponent,
var childIndex: Int = 0 val document: Document
) : HtmlConsumer { ) : HtmlConsumer {
private var currentPosition = arrayListOf<ElementIndex>() private val path = arrayListOf<HTMLElement>()
private var inDebug = false private var lastLeaved: HTMLElement? = null
var currentNode: Node? = null
var root: Element? = null
val currentAttributes: MutableMap<String, String> = mutableMapOf()
init {
currentPosition.add(ElementIndex(parent, childIndex))
}
override fun include(komponent: Komponent) {
if (
komponent.element != null &&
!komponent.memoizeChanged()
) {
currentPosition.replace(komponent.element!!)
if (Komponent.logRenderEvent) {
console.log("Skipped include $komponent, memoize hasn't changed")
}
} else {
komponent.create(
currentPosition.last().parent as Element,
currentPosition.last().childIndex
)
}
currentPosition.nextElement()
}
override fun append(node: Element) {
currentPosition.replace(node)
currentPosition.nextElement()
}
override fun debug(block: HtmlConsumer.() -> Unit) {
inDebug = true
try {
block.invoke(this)
} finally {
inDebug = false
}
}
fun logReplace(msg: String) {
if (Komponent.logReplaceEvent && inDebug) {
console.log(msg)
}
}
override fun onTagStart(tag: Tag) { override fun onTagStart(tag: Tag) {
//logReplace"onTagStart, [${tag.tagName}, ${tag.namespace}], currentPosition: $currentPosition") val element: HTMLElement = when {
currentNode = currentPosition.currentElement() tag.namespace != null -> document.createElementNS(tag.namespace!!, tag.tagName).asDynamic()
else -> document.createElement(tag.tagName) as HTMLElement
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}")
currentNode = if (tag.namespace != null) {
document.createElementNS(tag.namespace, tag.tagName)
} else {
document.createElement(tag.tagName)
}
currentPosition.replace(currentNode!!)
} else {
//logReplace"onTagStart, same node type")
} }
currentElement = currentNode as? Element ?: currentElement if (path.isNotEmpty()) {
path.last().appendChild(element)
if (currentNode is Element) {
if (root == null) {
//logReplace"Setting root: $currentNode")
root = currentNode as Element
}
currentElement?.clearKompAttributes()
currentElement?.clearKompEvents()
for (entry in tag.attributesEntries) {
currentElement!!.setKompAttribute(entry.key.lowercase(), entry.value)
}
if (tag.namespace != null) {
//logReplace"onTagStart, same node type")
(currentNode as? Element)?.innerHTML = ""
}
} }
//logReplace"onTagStart, currentElement2: $currentNode") path.add(element)
currentPosition.push(currentNode!!)
}
private fun checkTag(tag: Tag) {
check(currentElement != null) {
js("debugger")
"No current tag"
}
check(currentElement?.tagName.equals(tag.tagName, ignoreCase = true)) {
js("debugger")
"Wrong current tag"
}
} }
override fun onTagAttributeChange(tag: Tag, attribute: String, value: String?) { override fun onTagAttributeChange(tag: Tag, attribute: String, value: String?) {
logReplace("onTagAttributeChange, ${tag.tagName} [$attribute, $value]") when {
path.isEmpty() -> throw IllegalStateException("No current tag")
checkTag(tag) path.last().tagName.toLowerCase() != tag.tagName.toLowerCase() -> throw IllegalStateException("Wrong current tag")
else -> path.last().let { node ->
if (value == null) { if (value == null) {
currentElement?.removeAttribute(attribute.lowercase()) node.removeAttribute(attribute)
} else { } else {
currentElement?.setKompAttribute(attribute.lowercase(), value) node.setAttribute(attribute, value)
}
}
} }
} }
override fun onTagEvent(tag: Tag, event: String, value: (Event) -> Unit) { override fun onTagEvent(tag: Tag, event: String, value: (Event) -> Unit) {
//logReplace"onTagEvent, ${tag.tagName} [$event, $value]") when {
path.isEmpty() -> throw IllegalStateException("No current tag")
checkTag(tag) path.last().tagName.toLowerCase() != tag.tagName.toLowerCase() -> throw IllegalStateException("Wrong current tag")
else -> path.last().setEvent(event, value)
currentElement?.setKompEvent(event.lowercase(), value) }
} }
override fun onTagEnd(tag: Tag) { override fun onTagEnd(tag: Tag) {
while (currentPosition.currentElement() != null) { var hash = 0
currentPosition.currentElement()?.let { if (path.isEmpty() || path.last().tagName.toLowerCase() != tag.tagName.toLowerCase()) {
it.parentElement?.removeChild(it) throw IllegalStateException("We haven't entered tag ${tag.tagName} but trying to leave")
}
} }
checkTag(tag) val element = path.last()
currentPosition.pop() if (Komponent.updateStrategy == UpdateStrategy.DOM_DIFF) {
for (index in 0 until element.childNodes.length) {
val setAttrs: List<String> = currentElement.asDynamic()["komp-attributes"] ?: listOf() val child = element.childNodes[index]
if (child is HTMLElement) {
// remove attributes that where not set hash = hash * 37 + child.getKompHash()
val element = currentElement } else {
if (element?.hasAttributes() == true) { hash = hash * 37 + (child?.textContent?.hashCode() ?: 0)
for (index in 0 until element.attributes.length) {
val attr = element.attributes[index]
if (attr != null) {
if (element is HTMLElement && attr.name == "data-has-focus" && "true" == attr.value) {
element.focus()
}
if (!setAttrs.contains(attr.name)) {
if (element is HTMLInputElement) {
if (attr.name == "checkbox") {
element.checked = false
} else if (attr.name == "value") {
element.value = ""
}
} else {
if (Komponent.logReplaceEvent) {
console.log("Clear attribute [${attr.name}] on $element)")
}
element.removeAttribute(attr.name)
}
}
} }
} }
} }
currentPosition.nextElement() for ((key, value) in tag.attributesEntries) {
if (key == "class") {
val classes = value.split(Regex("\\s+"))
val classNames = StringBuilder()
currentElement = currentElement?.parentElement as? HTMLElement for (cls in classes) {
val cssStyle = komponent.declaredStyles[cls]
//logReplace"onTagEnd, popped: $currentElement") if (cssStyle != null) {
if (Komponent.updateStrategy == UpdateStrategy.DOM_DIFF) {
hash = hash * 37 + cssStyle.hashCode()
}
if (cls.endsWith(":hover")) {
val oldOnMouseOver = element.onmouseover
val oldOnMouseOut = element.onmouseout
element.onmouseover = {
element.setStyles(cssStyle)
oldOnMouseOver?.invoke(it)
}
element.onmouseout = {
cls.split(':').firstOrNull()?.let {
komponent.declaredStyles[it]?.let { cssStyle ->
element.setStyles(cssStyle)
}
}
oldOnMouseOut?.invoke(it)
}
} else {
element.setStyles(cssStyle)
}
} else {
if (Komponent.updateStrategy == UpdateStrategy.DOM_DIFF) {
hash = hash * 37 + cls.hashCode()
}
classNames.append(cls)
classNames.append(" ")
}
}
element.className = classNames.toString()
if (Komponent.updateStrategy == UpdateStrategy.DOM_DIFF) {
val key_value = "${key}-${classNames}"
hash = hash * 37 + key_value.hashCode()
}
} else {
element.setAttribute(key, value)
if (Komponent.updateStrategy == UpdateStrategy.DOM_DIFF) {
val key_value = "${key}-${value}"
hash = hash * 37 + key_value.hashCode()
}
}
}
if (Komponent.updateStrategy == UpdateStrategy.DOM_DIFF) {
element.setKompHash(hash)
//element.setAttribute(DiffPatch.HASH_ATTRIBUTE, hash.toString(16))
}
lastLeaved = path.removeAt(path.lastIndex)
} }
override fun onTagContent(content: CharSequence) { override fun onTagContent(content: CharSequence) {
//logReplace"onTagContent, [$content]") if (path.isEmpty()) {
throw IllegalStateException("No current DOM node")
check(currentElement != null) {
"No current DOM node"
} }
//logReplace"Tag content: $content") path.last().appendChild(document.createTextNode(content.toString()))
if (
currentElement?.nodeType != Node.TEXT_NODE ||
currentElement?.textContent != content.toString()
) {
currentElement?.textContent = content.toString()
}
currentPosition.nextElement()
} }
override fun onTagContentEntity(entity: Entities) { override fun onTagContentEntity(entity: Entities) {
//logReplace"onTagContentEntity, [${entity.text}]") if (path.isEmpty()) {
throw IllegalStateException("No current DOM node")
check(currentElement != null) {
"No current DOM node"
} }
val s = document.createElement("span") as HTMLSpanElement // stupid hack as browsers don't support createEntityReference
val s = document.createElement("span") as HTMLElement
s.innerHTML = entity.text s.innerHTML = entity.text
currentPosition.replace( path.last().appendChild(s.childNodes.asList().first { it.nodeType == Node.TEXT_NODE })
s.childNodes.asList().firstOrNull() ?: document.createTextNode(entity.text)
) // other solution would be
currentPosition.nextElement() // pathLast().innerHTML += entity.text
}
override fun append(node: Node) {
path.last().appendChild(node)
} }
override fun onTagContentUnsafe(block: Unsafe.() -> Unit) { override fun onTagContentUnsafe(block: Unsafe.() -> Unit) {
with(DefaultUnsafe()) { with(DefaultUnsafe()) {
block() block()
val textContent = toString() path.last().innerHTML += toString()
//logReplace"onTagContentUnsafe, [$textContent]")
var namespace: String? = null
if (currentPosition.currentParent().nodeType == 1.toShort()) {
val element = currentPosition.currentParent() as Element
namespace = when (Komponent.unsafeMode) {
UnsafeMode.UNSAFE_ALLOWED -> {
element.namespaceURI
}
UnsafeMode.UNSAFE_SVG_ONLY -> {
if (element.namespaceURI == "http://www.w3.org/2000/svg") {
element.namespaceURI
} else {
null
}
}
else -> {
null
}
}
}
//logReplace"onTagContentUnsafe, namespace: [$namespace]")
if (Komponent.unsafeMode == UnsafeMode.UNSAFE_ALLOWED ||
(Komponent.unsafeMode == UnsafeMode.UNSAFE_SVG_ONLY && namespace == "http://www.w3.org/2000/svg")
) {
if (currentElement?.innerHTML != textContent) {
currentElement?.innerHTML += textContent
}
} else if (currentElement?.textContent != textContent) {
currentElement?.textContent = textContent
}
currentPosition.nextElement()
} }
} }
override fun onTagComment(content: CharSequence) { override fun onTagComment(content: CharSequence) {
//logReplace"onTagComment, [$content]") if (path.isEmpty()) {
throw IllegalStateException("No current DOM node")
check(currentElement != null) {
"No current DOM node"
} }
currentElement?.appendChild(
document.createComment(content.toString())
)
currentPosition.nextElement() path.last().appendChild(document.createComment(content.toString()))
} }
override fun finalize(): Element { override fun finalize(): HTMLElement = lastLeaved?.asR() ?: throw IllegalStateException("We can't finalize as there was no tags")
//logReplace"finalize, currentPosition: $currentPosition")
return root ?: throw IllegalStateException("We can't finalize as there was no tags") @Suppress("UNCHECKED_CAST")
} private fun HTMLElement.asR(): HTMLElement = this.asDynamic()
companion object { companion object {
fun create(content: HtmlBuilder.() -> Unit): Element { fun create(content: HtmlBuilder.() -> Unit): HTMLElement {
val container = document.createElement("div") as HTMLElement val consumer = HtmlBuilder(DummyKomponent(), document)
val consumer = HtmlBuilder(container, 0)
content.invoke(consumer) content.invoke(consumer)
return consumer.root ?: error("error") return consumer.finalize()
} }
} }
} }

View File

@@ -1,13 +1,18 @@
package nl.astraeus.komp package nl.astraeus.komp
import kotlinx.browser.window import org.w3c.dom.HTMLDivElement
import org.w3c.dom.Element
import org.w3c.dom.HTMLElement import org.w3c.dom.HTMLElement
import org.w3c.dom.Node import org.w3c.dom.Node
import org.w3c.dom.css.CSSStyleDeclaration import org.w3c.dom.css.CSSStyleDeclaration
import org.w3c.dom.get import kotlinx.browser.document
import kotlinx.browser.window
import kotlinx.html.div
import kotlin.reflect.KProperty import kotlin.reflect.KProperty
const val KOMP_KOMPONENT = "komp-komponent"
typealias CssStyle = CSSStyleDeclaration.() -> Unit
class StateDelegate<T>( class StateDelegate<T>(
val komponent: Komponent, val komponent: Komponent,
initialValue: T initialValue: T
@@ -28,126 +33,138 @@ class StateDelegate<T>(
inline fun <reified T> Komponent.state(initialValue: T): StateDelegate<T> = StateDelegate(this, initialValue) inline fun <reified T> Komponent.state(initialValue: T): StateDelegate<T> = StateDelegate(this, initialValue)
enum class UnsafeMode { fun HtmlConsumer.include(component: Komponent) {
UNSAFE_ALLOWED, if (Komponent.updateStrategy == UpdateStrategy.REPLACE) {
UNSAFE_DISABLED, if (component.element != null) {
UNSAFE_SVG_ONLY component.update()
} else {
component.refresh()
}
component.element?.also {
append(it)
}
} else {
append(component.create())
}
}
class DummyKomponent: Komponent() {
override fun HtmlBuilder.render() {
div {
+ "dummy"
}
}
}
enum class UpdateStrategy {
REPLACE,
DOM_DIFF
} }
abstract class Komponent { abstract class Komponent {
val createIndex = getNextCreateIndex() private var createIndex = getNextCreateIndex()
private var dirty: Boolean = true private var dirty: Boolean = true
private var lastMemoizeHash: Int? = null
var element: Node? = null var element: Node? = null
val declaredStyles: MutableMap<String, CSSStyleDeclaration> = HashMap() val declaredStyles: MutableMap<String, CSSStyleDeclaration> = HashMap()
open fun create(parent: Element, childIndex: Int? = null) { open fun create(): HTMLElement {
onBeforeUpdate() val consumer = HtmlBuilder(this, document)
val builder = HtmlBuilder( consumer.render()
parent, val result = consumer.finalize()
childIndex ?: parent.childElementCount
)
builder.render() if (result.id.isBlank()) {
element = builder.root result.id = "komp_${createIndex}"
lastMemoizeHash = generateMemoizeHash() }
onAfterUpdate()
element = result
element.asDynamic()[KOMP_KOMPONENT] = this
dirty = false
return result
} }
fun memoizeChanged() = lastMemoizeHash != null && lastMemoizeHash != generateMemoizeHash()
abstract fun HtmlBuilder.render() abstract fun HtmlBuilder.render()
/**
* This method is called after the Komponent is updated
*
* note: it's also called at first render
*/
open fun onAfterUpdate() {}
/**
* This method is called before the Komponent is updated
* and before memoizeHash is checked
*
* note: it's also called at first render
*/
open fun onBeforeUpdate() {}
fun requestUpdate() { fun requestUpdate() {
dirty = true dirty = true
scheduleForUpdate(this) scheduleForUpdate(this)
} }
/** open fun style(className: String, vararg imports: CssStyle, block: CssStyle = {}) {
* Request an immediate update of this Komponent val style = (document.createElement("div") as HTMLDivElement).style
* for (imp in imports) {
* This will run immediately, make sure Komponents are not rendered multiple times imp(style)
* Any scheduled updates will be run as well }
*/ block(style)
fun requestImmediateUpdate() { declaredStyles[className] = style
dirty = true
runUpdateImmediately(this)
} }
/**
* This function can be overwritten if you know how to update the Komponent yourself
*
* HTMLBuilder.render() is called 1st time the component is rendered, after that this
* method will be called
*/
open fun update() { open fun update() {
refresh() refresh()
} }
/**
* If this function returns a value it will be stored and on the next render it will be compared.
*
* The render will only happen if the hash is not null and has changed
*/
open fun generateMemoizeHash(): Int? = null
internal fun refresh() { internal fun refresh() {
val currentElement = element val oldElement = element
check(currentElement != null) { if (logRenderEvent) {
error("element is null") console.log("Rendering", this)
} }
val newElement = create()
val parent = currentElement.parentElement as? HTMLElement ?: error("parent is null!?") if (oldElement != null) {
var childIndex = 0 element = if (updateStrategy == UpdateStrategy.REPLACE) {
for (index in 0 until parent.children.length) { if (logReplaceEvent) {
if (parent.children[index] == currentElement) { console.log("Replacing", oldElement, newElement)
childIndex = index }
oldElement.parentNode?.replaceChild(newElement, oldElement)
newElement
} else {
if (logReplaceEvent) {
console.log("DomDiffing", oldElement, newElement)
}
DiffPatch.updateNode(oldElement, newElement)
} }
} }
val consumer = HtmlBuilder(parent, childIndex)
consumer.root = null
consumer.render()
element = consumer.root
dirty = false dirty = false
} }
override fun toString(): String { @JsName("remove")
return "${this::class.simpleName}" fun remove() {
check(updateStrategy == UpdateStrategy.REPLACE) {
"remote only works with UpdateStrategy.REPLACE"
}
element?.let {
val parent = it.parentElement ?: throw IllegalArgumentException("Element has no parent!?")
if (logReplaceEvent) {
console.log("Remove", it)
}
parent.removeChild(it)
}
} }
companion object { companion object {
private var nextCreateIndex: Int = 1 private var nextCreateIndex: Int = 1
private var updateCallback: Int? = null private var updateCallback: Int? = null
private var scheduledForUpdate = mutableSetOf<Komponent>() private var scheduledForUpdate = mutableSetOf<Komponent>()
private var interceptor: (Komponent, () -> Unit) -> Unit = { _, block -> block() }
var logRenderEvent = false var logRenderEvent = false
var logReplaceEvent = false var logReplaceEvent = false
var unsafeMode = UnsafeMode.UNSAFE_DISABLED var updateStrategy = UpdateStrategy.DOM_DIFF
fun create(parent: HTMLElement, component: Komponent, insertAsFirst: Boolean = false) { fun create(parent: HTMLElement, component: Komponent, insertAsFirst: Boolean = false) {
component.create(parent) val element = component.create()
}
fun setUpdateInterceptor(block: (Komponent, () -> Unit) -> Unit) { if (insertAsFirst && parent.childElementCount > 0) {
interceptor = block parent.insertBefore(element, parent.firstChild)
} else {
parent.appendChild(element)
}
} }
private fun getNextCreateIndex() = nextCreateIndex++ private fun getNextCreateIndex() = nextCreateIndex++
@@ -162,11 +179,6 @@ abstract class Komponent {
} }
} }
private fun runUpdateImmediately(komponent: Komponent) {
scheduledForUpdate.add(komponent)
runUpdate()
}
private fun runUpdate() { private fun runUpdate() {
val todo = scheduledForUpdate.sortedBy { komponent -> komponent.createIndex } val todo = scheduledForUpdate.sortedBy { komponent -> komponent.createIndex }
@@ -175,31 +187,21 @@ abstract class Komponent {
} }
todo.forEach { next -> todo.forEach { next ->
interceptor(next) { val element = next.element
val element = next.element console.log("update element", element)
if (element is HTMLElement) {
if (element is HTMLElement) { console.log("by id", document.getElementById(element.id))
if (document.getElementById(element.id) != null) {
if (next.dirty) { if (next.dirty) {
if (logRenderEvent) { if (logRenderEvent) {
console.log("Update dirty ${next.createIndex}") console.log("Update dirty ${next.createIndex}")
} }
val memoizeHash = next.generateMemoizeHash() next.update()
if (memoizeHash == null || next.lastMemoizeHash != memoizeHash) {
next.onBeforeUpdate()
next.update()
next.lastMemoizeHash = memoizeHash
next.onAfterUpdate()
} else if (logRenderEvent) {
console.log("Skipped render, memoizeHash is equal $next-[$memoizeHash]")
}
} else { } else {
if (logRenderEvent) { if (logRenderEvent) {
console.log("Skip ${next.createIndex}") console.log("Skip ${next.createIndex}")
} }
} }
} else {
console.log("Komponent element is null", next, element)
} }
} }
} }

View File

@@ -1,238 +1,132 @@
package nl.astraeus.komp package nl.astraeus.komp
import kotlinx.browser.document import kotlinx.html.*
import kotlinx.html.div
import kotlinx.html.i
import kotlinx.html.id
import kotlinx.html.js.onClickFunction import kotlinx.html.js.onClickFunction
import kotlinx.html.p import org.w3c.dom.HTMLElement
import kotlinx.html.span import org.w3c.dom.Node
import kotlinx.html.svg import org.w3c.dom.get
import kotlinx.html.table
import kotlinx.html.td
import kotlinx.html.tr
import kotlinx.html.unsafe
import org.w3c.dom.Element
import org.w3c.dom.HTMLDivElement
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertTrue
class TestKomponent : Komponent() { fun nodesEqual(node1: Node, node2: Node): Boolean {
override fun HtmlBuilder.render() { if (node1.childNodes.length != node1.childNodes.length) {
div { return false
+"Test"
}
} }
} if (node1 is HTMLElement && node2 is HTMLElement) {
if (node1.attributes.length != node2.attributes.length) {
class Child1 : Komponent() { return false
override fun HtmlBuilder.render() {
div {
+"Child 1"
} }
} for (index in 0 until node1.attributes.length) {
} node1.attributes[index]?.also { attr1 ->
val attr2 = node2.getAttribute(attr1.name)
class Child2 : Komponent() { if (attr1.value != attr2) {
override fun HtmlBuilder.render() { return false
div {
+"Child 2"
}
}
}
class SimpleKomponent : Komponent() {
var hello = true
var append = HtmlBuilder.create {
p {
+"Appended"
}
}
override fun HtmlBuilder.render() {
div("div_class") {
span {
svg {
unsafe {
+"""
<p bla>
""".trimIndent()
}
} }
if (hello) { }
div { }
+"Hello" for (index in 0 until node1.childNodes.length) {
} node1.childNodes[index]?.also { child1 ->
} else { node2.childNodes[index]?.also { child2 ->
span { if (!nodesEqual(child1, child2)) {
+"Good bye" return false
} }
} }
} }
div {
if (hello) {
id = "123"
+"div text"
} else {
+"div text goodbye"
}
onClickFunction = if (hello) {
{
println("onClick")
}
} else {
{
println("onClick 2")
}
}
}
if (hello) {
span {
+"2nd span"
}
}
//append(append)
if (hello) {
include(Child1())
} else {
include(Child2())
}
//append(append)
}
}
}
class IncludeKomponent(
var text: String = "My Text"
) : Komponent() {
override fun generateMemoizeHash(): Int = text.hashCode()
override fun HtmlBuilder.render() {
span {
+text
}
}
}
class ReplaceKomponent : Komponent() {
val includeKomponent = IncludeKomponent()
var includeSpan = true
override fun generateMemoizeHash(): Int = includeSpan.hashCode() * 7 + includeKomponent.generateMemoizeHash()
override fun HtmlBuilder.render() {
div {
+"Child 2"
div {
if (includeSpan) {
span {
i("fas fa-eye") {
+"span1"
}
}
span {
i("fas fa-eye") {
+"span2"
}
}
span {
i("fas fa-eye") {
+"span3"
}
}
}
include(includeKomponent)
}
} }
} }
return true
} }
class TestUpdate { class TestUpdate {
@Test @Test
fun testUpdateWithEmpty() { fun testCompare1() {
val div = document.createElement("div") as HTMLDivElement val dom1 = HtmlBuilder.create {
val rk = ReplaceKomponent() div {
div(classes = "bla") {
Komponent.logRenderEvent = true span {
+" Some Text "
Komponent.create(div, rk) }
table {
println("ReplaceKomponent: ${div.printTree()}") tr {
td {
rk.requestImmediateUpdate() +"Table column"
}
println("ReplaceKomponent: ${div.printTree()}")
rk.requestImmediateUpdate()
println("ReplaceKomponent: ${div.printTree()}")
rk.includeSpan = false
rk.requestImmediateUpdate()
println("ReplaceKomponent: ${div.printTree()}")
rk.includeSpan = true
rk.includeKomponent.text = "New Text"
rk.requestImmediateUpdate()
println("ReplaceKomponent: ${div.printTree()}")
}
@Test
fun testSimpleKomponent() {
val sk = SimpleKomponent()
val div = document.createElement("div") as HTMLDivElement
Komponent.create(div, sk)
println("SimpleKomponent: ${div.printTree()}")
sk.hello = false
sk.requestImmediateUpdate()
println("SimpleKomponent updated: ${div.printTree()}")
}
@Test
fun testCreate() {
var elemTest: Element? = null
val element = HtmlBuilder.create {
div("div_class") {
id = "123"
+"Test"
span("span_class") {
+"Span"
elemTest = currentElement()
}
table {
tr {
td {
+"column 1"
}
td {
+"column 2"
} }
} }
} }
} }
} }
println("Element: ${element.printTree()}") val dom2 = HtmlBuilder.create {
println("divTst: ${elemTest?.printTree()}") div {
println("span class: ${ span {
elemTest?.getAttributeNames()?.joinToString id = "123"
{ "," }
}" +"New dom!"
) }
input {
value = "bla"
}
}
}
DiffPatch.updateNode(dom1, dom2)
assertTrue(nodesEqual(dom1, dom2), "Updated dom not equal to original")
}
@Test
fun testCompare2() {
val dom1 = HtmlBuilder.create {
div {
div(classes = "bla") {
span {
+" Some Text "
}
table {
tr {
th {
+ "Header"
}
}
tr {
td {
+"Table column"
}
}
}
}
}
}
val dom2 = HtmlBuilder.create {
div {
div {
span {
+ "Other text"
}
}
span {
id = "123"
+"New dom!"
}
input {
value = "bla"
onClickFunction = {
println("Clickerdyclick!")
}
}
}
}
Komponent.logReplaceEvent = true
DiffPatch.updateNode(dom1, dom2)
assertTrue(nodesEqual(dom1, dom2), "Updated dom not equal to original")
} }
} }