Created
December 6, 2019 18:12
-
-
Save toefel18/711eeb65e74b476df293708c2a3aed14 to your computer and use it in GitHub Desktop.
kotlin-html-dsl-tryout
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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