Last active
July 22, 2023 12:06
-
-
Save joost-klitsie/8959187d61cd5d1a388a2937c318dc13 to your computer and use it in GitHub Desktop.
Kotlin HTML Builder
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
fun HtmlTag.Builder.addAttribute(attribute: Pair<String, String>) { | |
attributes = attributes.plus(attribute) | |
} | |
fun HtmlTag.Builder.addChild(child: HtmlElement) { | |
children = children.plus(child) | |
} |
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
fun interface HtmlElement { | |
fun render(indent: String): String | |
} |
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
fun HtmlTag.Builder.a( | |
href: String, | |
configure: HtmlTag.Builder.() -> Unit | |
) = tag("a") { | |
addAttribute("href" to href) | |
configure() | |
} | |
fun HtmlTag.Builder.div( | |
configure: HtmlTag.Builder.() -> Unit | |
) = tag("div", configure) | |
fun HtmlTag.Builder.br() = tag("br") {} | |
fun HtmlTag.Builder.p( | |
configure: HtmlTag.Builder.() -> Unit | |
) = tag("p", configure) | |
fun HtmlTag.Builder.classes( | |
classNames: String | |
) = addAttribute("class" to classNames) |
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
<html> | |
Hello people! | |
<div> | |
<a href="http://adnovum.com"> | |
Go to Adnovum! | |
</a> | |
</div> | |
<div> | |
<p class="my-class"> | |
I am a paragraph | |
</p> | |
<br/> | |
<div class="other-class"> | |
<p> | |
I am also a paragraph | |
</p> | |
</div> | |
</div> | |
<div> | |
number 0 | |
</div> | |
<div> | |
number 1 | |
</div> | |
<div> | |
number 2 | |
</div> | |
<div> | |
number 3 | |
</div> | |
<div> | |
number 4 | |
</div> | |
</html> |
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
val html = html { | |
text("Hello people!") | |
div { | |
a("http://adnovum.com") { | |
text("Go to Adnovum!") | |
} | |
} | |
div { | |
p { | |
classes("my-class") | |
text("I am a paragraph") | |
} | |
br() | |
div { | |
classes("other-class") | |
p { | |
text("I am also a paragraph") | |
} | |
} | |
} | |
repeat(5) { index -> | |
div { | |
text("number $index") | |
} | |
} | |
} | |
println(html.render("")) |
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
class HtmlTag private constructor( | |
val name: String, | |
val attributes: Map<String, String>, | |
val children: List<HtmlElement>, | |
) : HtmlElement { | |
override fun render(indent: String): String { | |
val attributeString = | |
attributes.entries.joinToString(separator = " ") { (key, value) -> | |
"$key=\"$value\"" | |
} | |
return if (children.isEmpty()) { | |
"$indent<$name $attributeString/>" | |
} else { | |
val childrenString = children.joinToString("\n") { | |
it.render("$indent ") | |
} | |
""" | |
|$indent<$name $attributeString> | |
|$childrenString | |
|$indent</$name> | |
""".trimMargin() | |
} | |
} | |
class Builder( | |
var name: String, | |
var attributes: Map<String, String> = emptyMap(), | |
var children: List<HtmlElement> = emptyList(), | |
) { | |
fun build() = HtmlTag(name, attributes, children) | |
} | |
} |
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
fun html(configure: HtmlTag.Builder.() -> Unit): HtmlElement { | |
val builder = HtmlTag.Builder("html") | |
builder.configure() | |
return builder.build() | |
} |
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
val html = html { } | |
println(html.render("")) // prints: <html /> |
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
fun HtmlTag.Builder.tag( | |
name: String, | |
configure: HtmlTag.Builder.() -> Unit | |
) = addChild(HtmlTag.Builder(name).apply(configure).build()) |
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
val html = html { | |
tag("p") { | |
text("Hello, world!") | |
} | |
} | |
println(html.render("")) | |
/* Output: | |
<html> | |
<p> | |
Hello, world! | |
</p> | |
</html> | |
*/ |
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
val html = html { | |
text("Hello, world!") | |
} | |
println(html.render("")) | |
/* Output: | |
<html> | |
Hello, world! | |
</html> | |
*/ |
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
<TagName attribute="value">children</TagName> |
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
fun HtmlTag.Builder.text(text: String) = addChild { indent -> "$indent$text" } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment