KorTE

KorTE

KorTE is a asynchronous template engine for Multiplatform Kotlin 1.3.

It is a non-strict super set of twig / django / atpl.js / jinjava template engines and can support liquid templaet engine too with frontmatter.

It has out of the box support for ktor and vert.x.

It works on JVM and JS out of the box. But can also work on Native when using untyped model data or making models to implement the DynamicType interface.

It allows to call suspend methods from within templates.

https://github.com/korlibs/korte

Star

Build Status Maven Version

Live demo (editable) [source code]:

Table of contents:

Pages

{% include toc.html context=”/korte/” %}

Usage

Raw Usage

Manual usage:

import com.soywiz.korte.Template

val template = Template("hello {{ who }}")
val rendered = template(mapOf("who" to "world"))
assertEquals("hello world", rendered)

Managed with KorIO’s Vfs and optional cache:

import com.soywiz.korte.Templates

//val myvfs = resourcesVfs["templates"] // To read templates from a 'templates' folder in the application resources
val myvfs = MemoryVfsMix(
    "index.html" to "hello {{ who }}"
)

val templates = Templates(myvfs, cache = true)
val rendered = templates.render("index.html", mapOf("who" to "world"))
assertEquals("hello world", rendered)

Ktor

dependencies {
    jvmMainApi "com.soywiz:korte-ktor-jvm:$korteVersion"
}
fun Application.module() {
    install(Korte) {
        cache(true)
        root(
            // resourcesVfs
            MemoryVfsMix(
                "demo.tpl" to "Hello {{ hello }}"
            )
        )
    }
    routing {
        get("/") {
            call.respondKorte("demo.tpl", MyModel(hello = "world"))
        }
    }
    assertEquals("Hello world", handleRequest(HttpMethod.Get, "/") { }.response.content)
}

Vert.x

dependencies {
    jvmMainApi "com.soywiz:korte-vertx-jvm:$korteVersion"
}
val port = 0
val host = "127.0.0.1"
val vertx = Vertx.vertx()
val router = Router.router(vertx)
val template = TemplateHandler.create(
    KorteVertxTemplateEngine(
        coroutineContext, Templates(
            MemoryVfsMix(
                "index.html" to "hello world {{ 1 + 2 }}!",
                "hello.html" to "Nice :)!"
            )
        )
    )
)

router.get("/*").handler(template)

val server: HttpServer = run {
    val server = vertx.createHttpServer()
    server.requestHandler(router)
    vx { server.listen(port, host, it) }
}
val actualPort = server.actualPort()

try {
    val client = vertx.createHttpClient()
    assertEquals("hello world 3!", client.get(actualPort, "127.0.0.1", "/").readString())
    assertEquals("Nice :)!", client.get(actualPort, "127.0.0.1", "/hello").readString())
} finally {
    server.close()
}

Native

Since Kotlin/Native doesn’t provide any kind of reflective functionality yet (and kotlinx.serialization don’t allow to call methods), you have to help it a bit to understand your typed models to be able to call them.

data class Person(val name: String, val surname: String) :
    DynamicType<Person> by DynamicType({ register(Person::name, Person::surname) })
class TestMethods : DynamicType<TestMethods> by DynamicType({
        register("mytest123") { mytest123() }
        register("sum") { sum(it[0].toDynamicInt(), it[1].toDynamicInt()) }
    }), DynamicContext {
        var field = 1

        suspend fun mytest123(): Int {
            var r = withContext(Dispatchers.Unconfined) { field }
            return r + 7
        }

        @JsName("sum")
        suspend fun sum(a: Int, b: Int): Int {
            return a + b
        }
    }

Using with gradle

Requires Gradle 7.1.1 (JVM 8~13) for building and Kotlin >=1.5.20 for running:

build.gradle.kts

val korteVersion = "2.2.0"

repositories {
    maven { url("https://dl.bintray.com/korlibs/korlibs") }
    jcenter()
}

// For multiplatform projects
kotlin {
    sourceSets {
        commonMain {
            dependencies {
                implementation("com.soywiz.korlibs.korte:korte:$korteVersion") 
            }
        }
    }
}

dependencies {
    // For JVM only
    implementation("com.soywiz.korlibs.korte:korte-jvm:$korteVersion") 
    // For Android only
    implementation("com.soywiz.korlibs.korte:korte-android:$korteVersion") 
    // For JS only
    implementation("com.soywiz.korlibs.korte:korte-js:$korteVersion") 
}