SkillAgentSearch skills...

Koreander

Kotlin HTML Template Engine

Install / Use

/learn @lukasjapan/Koreander
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Version Build Status Coverage Status

Koreander

Koreander is a HTML template engine for Kotlin with a clean elegant haml inspired syntax.

Quick Example

Code

data class ViewModel(val name: String)

val viewModel = ViewModel("world")
val input = File("input.kor")
val output = Koreander().render(input, viewModel)

input.kor

%html
    %body
        .content Hello ${name.capitalized()}!

->

<html>
    <body>
        <div class="content">Hello World!</div>
    </body>
</html>

Introduction

Koreander is a HTML template engine for Kotlin. Html tags are defined by an indent based syntax that is similar to pug (JavaScript), jade4j (Java) or slim/haml (Ruby). Templates are executed in the context of a view model class from where the properties and methods can be accessed in pure Kotlin code.

By combining the simplicity of Kotlin and HAML, the Koreander template syntax is simply beautiful. Koreander templates are also type-safe!! and have excellent performance due to JVM compilation.

Installation

Using Koreander is as simple as adding a few lines to your packaging tool. For Spring integration see below.

Gradle

repositories {
    maven {
        url  "https://dl.bintray.com/lukasjapan/de.cvguy.kotlin"
    }
}

dependencies {
    implementation 'de.cvguy.kotlin:koreander:0.1.0'
}

Maven

TBA

Usage

An introduction of how to use the Koreander template engine.

Code

Just create the view model (instance) and pass it to the render function of a Koreander instance along with the template. The template can be passed as String, File, URL or Input Stream.

import de.cvguy.kotlin.koreander.Koreander

data class Beer(
        val name: String,
        val manufacturer: String,
        val alc: Double
)

data class ViewModel(
        val title: String,
        val beers: List<Beer>
)

fun main(args: Array<String>) {
    val koreander = Koreander()

    val input = File("input.kor").readText()

    val viewModel = ViewModel(
            "Japanese Beers",
            listOf(
                    Beer("Asahi Super Dry", "Asahi Breweries Ltd ", 0.05),
                    Beer("Kirin Ichiban Shibori", "Kirin Brewery Company, Limited", 0.05),
                    Beer("Yebisu", "Sapporo Breweries Ltd.", 0.05),
                    Beer("Sapporo Black Label", "Sapporo Breweries Ltd.", 0.05),
                    Beer("The Premium Malts", "Suntory", 0.055),
                    Beer("Kirin Lager", "Kirin Brewery Company, Limited", 0.049)
            )
    )

    val output = koreander.render(input, viewModel)

    println(output)
}

Template Syntax Summarization

Explanation in detail about the Koreander template syntax can be found below.

Here are the main points summarized to get you started:

  • HTML tags are expressed by a % and are closed automatically
    • %tag<tag></tag>
    • %tag content<tag>content</tag>
  • Lines with deeper indent are included inside the next less deep tag
%outertag
    %innertag content

<outertag>
    <innertag>content</innertag>
</outertag>
  • No closing tags for Void Elements
    • %br something<br>something
  • Attributes can be written right after tags
    • %tag with=attribute content<tag with="attribute">content</tag>
  • There are shortcuts for id (#) and class (.) attribute
    • %tag#myid<tag id="myid"></tag>
    • %tag.myclass<tag class="myclass"></tag>
    • %tag#myid.myclass<tag id="myid" class="myclass"></tag>
  • If used, div tags may be omitted
    • #myid<div id="myid"></div>
    • .myclass<div class="myclass"></div>
    • #myid.myclass<div id="myid" class="myclass"></div>
  • Texts are evaluated as Kotlin string templates, therefore Kotlin code can be inserted (almost) anywhere
    • %tag one plus one is ${1 + 1}<tag>one plus one is 2</tag>
    • %tag oneplusone=is${1 + 1}<tag oneplusone="is2"></tag>
  • Code is executed as if it would be inside the view model class
    • %tag content ${functionOfViewModel()}<tag>content xxxxx</tag>
    • %tag content $propertyOfViewModel<tag>content xxxxx</tag>
  • Code only lines can be expressed by a leading -
    • - invokeFunctionOfViewModel()
  • Deeper indented lines after code are passed to the code as a block
%ul
    - $collectionPropertyOfViewModel.forEach
        %li This is ${it}!
    - $collectionPropertyOfViewModel.forEach -> item
        %li This is ${item}!

<ul>
        <li>This is xxxx</li>
        <li>This is xxxx</li>
        <li>This is xxxx</li>
        ...
</ul>
  • Filters can be used for non-html input
:js
    var name = "World"
    console.log("Hello " + name");

<script type="test/javascript">
var name = "World"
console.log("Hello " + name");
</script>

Example Template

Using the code above, a template saved as input.kor ...

!!! 5
%html
    %head
        %link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet"
    %body
        .container
            %h1 ${title}
            %table.table.table-striped
                %thead
                    %tr
                        %th Name
                        %th Manufacturer
                        %th Alc. percentage
                %tbody
                    - beers.forEach
                        %tr
                            %td ${it.name}
                            %td ${it.manufacturer}
                            %td ${"%.2f".format(it.alc * 100.0)}%

... will generate the following output:

<!DOCTYPE html>
<html>
    <head>
        <link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet">
    </head>
    <body>
        <div class="container">
            <h1>Japanese Beers</h1>
            <table class="table table-striped">
                <thead>
                    <tr>
                        <th>Name</th>
                        <th>Manufacturer</th>
                        <th>Alc. percentage</th>
                    </tr>
                </thead>
                <tbody>
                        <tr>
                            <td>Asahi Super Dry</td>
                            <td>Asahi Breweries Ltd </td>
                            <td>5.00%</td>
                        </tr>
                        <tr>
                            <td>Kirin Ichiban Shibori</td>
                            <td>Kirin Brewery Company, Limited</td>
                            <td>5.00%</td>
                        </tr>
                        <tr>
                            <td>Yebisu</td>
                            <td>Sapporo Breweries Ltd.</td>
                            <td>5.00%</td>
                        </tr>
                        <tr>
                            <td>Sapporo Black Label</td>
                            <td>Sapporo Breweries Ltd.</td>
                            <td>5.00%</td>
                        </tr>
                        <tr>
                            <td>The Premium Malts</td>
                            <td>Suntory</td>
                            <td>5.50%</td>
                        </tr>
                        <tr>
                            <td>Kirin Lager</td>
                            <td>Kirin Brewery Company, Limited</td>
                            <td>4.90%</td>
                        </tr>
                </tbody>
            </table>
        </div>
    </body>
</html>

Template Syntax

In depth explanation of the template syntax.

<!DOCTYPE> declaration

A doctype can be specified in the first line of the template. The following can be used:

| Identifier | Doctype | | --- | --- | | !!! | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> | | !!! Strict | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | | !!! Frameset | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"> | | !!! 5 | <!DOCTYPE html> | | !!! 1.1 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> | | !!! Basic | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd"> | | !!! Mobile | <!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd"> | | !!! RDFa | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN" "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd"> |

HTML Tags

TBA

Void Elements

Void elements are not allowed to have content and its closing tag is omitted. Currently, regardless of the doctype the alternate closing notations slash (<br/>) or space-slash (<br />) are not used.

List of void elements:

  • area
  • base
  • br
  • col
  • command
  • embed
  • hr
  • img
  • input
  • keygen
  • link
  • meta
  • param
  • source
  • track
  • wbr

Attributes

TBA

ID shortcut # and class shortcut .

TBA

Text content

TBA

Output =

TBA

Control code -

TBA

Comment /

TBA

Filters

Filters can process custom input and are expected

View on GitHub
GitHub Stars34
CategoryDevelopment
Updated1mo ago
Forks3

Languages

Kotlin

Security Score

75/100

Audited on Mar 7, 2026

No findings