Skip to content

Instantly share code, notes, and snippets.

@toefel18
Created December 6, 2019 18:12
Show Gist options
  • Save toefel18/711eeb65e74b476df293708c2a3aed14 to your computer and use it in GitHub Desktop.
Save toefel18/711eeb65e74b476df293708c2a3aed14 to your computer and use it in GitHub Desktop.
kotlin-html-dsl-tryout
package nl.toefel.kotlin.html.dsl
fun html(init: HTML.() -> Unit): HTML {
val html = HTML()
html.init()
return html
}
interface Element {
fun render(builder: StringBuilder, indent: String)
}
abstract class Tag(val name: String): Element {
val children = mutableListOf<Element>()
protected fun <T : Element> initTag(tag: T, init: T.() -> Unit): T {
tag.init()
children.add(tag)
return tag
}
operator fun String.unaryPlus() {
children.add(TextElement(this))
}
override fun render(builder: StringBuilder, indent: String) {
builder.append("$indent<$name>\n")
children.forEach {it.render(builder, "$indent ")}
builder.append("$indent</$name>\n")
}
override fun toString(): String {
val builder = StringBuilder()
render(builder, "")
return builder.toString()
}
}
class HTML : Tag("html") {
fun body(init: BODY.() -> Unit): BODY = initTag(BODY(), init)
}
class BODY: Tag("body") {
fun div(init: DIV.() -> Unit): DIV = initTag(DIV(), init)
fun a(init: Anchor.() -> Unit): Anchor = initTag(Anchor(), init)
fun span(init: SPAN.() -> Unit): SPAN = initTag(SPAN(), init)
}
class DIV : Tag("div") {
fun div(init: DIV.() -> Unit): DIV = initTag(DIV(), init)
fun a(init: Anchor.() -> Unit): Anchor = initTag(Anchor(), init)
fun span(init: SPAN.() -> Unit): SPAN = initTag(SPAN(), init)
}
class SPAN : Tag("span") {
fun div(init: DIV.() -> Unit): DIV = initTag(DIV(), init)
fun a(init: Anchor.() -> Unit): Anchor = initTag(Anchor(), init)
fun span(init: SPAN.() -> Unit): SPAN = initTag(SPAN(), init)
}
class Anchor : Tag("anchor") {
}
class TextElement(val text: String) : Element {
override fun render(builder: StringBuilder, indent: String) {
builder.append("$indent$text\n")
}
}
fun main(args: Array<String>) {
val doc = html {
body {
div {
+"hoi"
+"sua"
}
div {
a {
+"linkje"
}
}
span { +"inside span" }
}
}
println(doc.toString())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment