Koreander
Kotlin HTML Template Engine
Install / Use
/learn @lukasjapan/KoreanderREADME
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

