KorTE Extending
It is possible to extend KorTE with new tags, functions and filters.
Table of contents:
Extending
By registering new extensions via TemplateConfig.register
you can have more functionality in your templates.
val config = TemplateConfig()
config.register(Filter("length") { subject.dynamicLength() })
val template = Template("mytemplate", config)
Filters
Filters have an injected this with the execution context
, the subject
,and optionally the args
of the filter call.
config.register(Filter("length") { subject.dynamicLength() })
config.register(Filter("chunked") {
subject.toDynamicList().chunked(args[0].toDynamicInt())
})
Functions
Functions have an args argument that receives a list of parameters already evaluated:
config.register(TeFunction("cycle") { args ->
val list = args.getOrNull(0).toDynamicList()
val index = args.getOrNull(1).toDynamicInt()
list[index umod list.size]
})
Tags
A tag has an associated name, several internal tag names, and a tag that ends this tag or null if it is not a block.
config.register(Tag("capture", setOf(), null) {
data class BlockCapture(val varname: String, val content: Block) : Block {
override suspend fun eval(context: Template.EvalContext) {
val result = context.capture {
content.eval(context)
}
context.scope.set(varname, RawString(result))
}
}
val main = chunks[0]
val tr = ExprNode.Token.tokenize(main.tag.content)
val varname = ExprNode.parseId(tr)
DefaultBlocks.BlockCapture(varname, main.body)
})
config.register(Tag("switch", setOf("case", "default"), setOf("endswitch")) {
var subject: ExprNode? = null
val cases = arrayListOf<Pair<ExprNode, Block>>()
var defaultCase: Block? = null
for (part in this.chunks) {
val tagContent = part.tag.content
val body = part.body
when (part.tag.name) {
"switch" -> {
subject = ExprNode.parse(tagContent)
}
"case" -> {
cases += ExprNode.parse(tagContent) to body
}
"default" -> {
defaultCase = body
}
}
}
if (subject == null) error("No subject set in switch")
//println(this.chunks)
object : Block {
override suspend fun eval(context: Template.EvalContext) {
val subjectValue = subject.eval(context)
for ((case, block) in cases) {
if (subjectValue == case.eval(context)) {
block.eval(context)
return
}
}
defaultCase?.eval(context)
return
}
}
})