Less HTML
HTML is a Text Markup Language
HTML stands for HyperText Markup Language. As the name suggests, HTML is used to mark up text, not to describe user interfaces. Although it has been extended over time, it still doesn't excel at expressing user interfaces due to compatibility with its original design.
Of course, JavaScript was originally intended to decorate pages, for creating some sparkly little widgets. But regardless, JavaScript is still a general-purpose programming language, and JavaScript updates at a much faster pace than HTML. So when choosing between two evils, we'd rather write JavaScript than HTML.
In fact, frameworks that use pure HTML are not common.
Because HTML is too unwieldy, frameworks that use HTML usually need to add some extras,
such as *ng
(Angular) and v-
(Vue) attributes, or JSX (React).
Otherwise, they create a template language similar to HTML.
Actually, this patching approach is not as straightforward as directly writing JavaScript.
The Kotlin and Ceylon Approach
Some newer languages directly use native structures to express HTML.
For example, in Kotlin, HTML is written like this:
fun result(args: Array<String>) =
html {
head {
title {+"XML encoding with Kotlin"}
}
body {
h1 {+"XML encoding with Kotlin"}
a(href = "http://kotlinlang.org") {+"Kotlin"}
p {
for (arg in args)
+arg
}
}
}
This is not some template language. This is Kotlin, native Kotlin.
Kotlin provides this syntactic sugar:
f({ "an anonymous function" })
can be written as
f { "an anonymous function" }
So html { ... }
is a Kotlin function call,
and the other HTML elements inside {}
work the same way.
The html
function is defined roughly like this:
fun html(init: HTML.() -> Unit): HTML {
val html = HTML()
html.init()
return html
}
Essentially, it initializes an HTML instance.
The corresponding HTML class definition:
class HTML : TagWithText("html") {
fun head(init: Head.() -> Unit) = initTag(Head(), init)
fun body(init: Body.() -> Unit) = initTag(Body(), init)
}
Using native Kotlin language to express HTML means we can use all of Kotlin's native language features, and no longer need to worry about the limited expressiveness or strange syntax of HTML template languages. At the same time, this naturally ensures type safety for HTML templates.
Similarly, in Ceylon, HTML is written like this:
Html {
doctype = html5;
Head {
title = "Ceylon: home page";
};
Body {
H1 { "Hello `` req.queryParameter("name") else "World" `` !" }
};
}
This uses Ceylon's syntactic sugar for named parameters, equivalent to:
Html(doctype = html5, Head(...), Body(...))
Html
is a class provided by the standard library, Html { ... }
is initialization,
(Ceylon directly constructs class instances through C()
, no need for new
)
This is also native Ceylon.
The approach is similar to Kotlin's.