Replacing Leaf with a Swift DSL

When Apple revealed SwiftUI last week during WWDC 2019, we also saw a new feature in Swift proposed as a draft on Swift Evolution (Function builders). Together with the Property wrappers proposal and some other recent Swift features, in Swift 5.1 it will be now possible to define DSLs that will enable code like this (screenshot from this WWDC session):

Yes, this is Swift code!

As you can see, it will soon be possible to natively support HTML by implementing a DSL for it in Swift (like Vaux does) with all the advantages that come along with it: Great compiler errors as feedback, autocompletion, more readable and flexible functions, Swift-native control flow etc.

While Leaf is a good template engine, I think it would make sense to introduce an alternative to Leaf based on such a DSL for HTML, CSS and the likes of it. What do you guys think?


As a heavy user of templating languages, I'd be all for this. However, I do hope this will become a SSWG effort, so we don't end up with multiple incompatible DSLs.

FYI: There's also I believe pointfree uses this for their website.


I know of swift-html, but it doesn't use the new features in Swift (cause they weren't announced at that time) and the dot syntax they're using is much less powerful then what will be possible with Swift 5.1 onwards. Note that with the new DSL you won't even need commas between statements!

1 Like

I think GitHub - vapor-community/HTMLKit: A type-safe DSL that renders dynamic HTML templates in Swift would be a great place to implement function builder support.

Depending on how the HTMLKit package is received, the core team would consider making it an official package (moving it to vapor/*) and offering it during vapor new project initialization.

1 Like

:wave: Hi! One of the swift-html developers here.

Point-Free's swift-html library offers a DSL vision from before the era of "function builders". Because of this it doesn't (and couldn't) take advantage of the new, implicit syntax that function builders offers, but it's definitely not "less" powerful! If anything it's "differently" (and sometimes more) powerful. We want to explore what the Swift DSL syntax has to offer, and we plan on updating our libraries accordingly, but please understand that function builders introduce limited sugar on top of existing means of building DSLs in Swift.

The swift-html library lets you build HTML as first-class Swift values, which means arrays of non-HTML values can be mapped to arrays of li elements using the map that comes with Sequence. Function builders can't take advantage of these operations and instead requires custom ForEach operators to be defined per DSL.

In the end, function builders are an early work in progress, and even though they read very nicely, they are much less composable right now. A few folks have pointed this out in evolution, so if this kind of flexibility is important to you, now's a good time to weigh in!


Something like SwiftWebUI?


I really like the idea of moving to a DSL. I have wondered how one would integrate some basic Javascript functionality for things like disabling buttons when all the required fields are not full, or client-side validation. There are many cases were a bit of interactivity would be all that was needed, not a full single page application.

@MajorTom have you tried using something like HTMLKit? That's a fairly straight-forward thing to support right now.

Leaf falls apart if you try to do anything with in-page HTML script blocks.

I looked briefly at both HTMLKit and Swift-HTML (with the Vapor version), and was not really clear how I would add the JavaScript. It is probably easy, but I did not see how I would do it. :slight_smile:

I can't check right now but as far as I know, HTMLKit has a Builder that would allow you to do something like:

Script {
// Write your JS here.

I did not find script as one of the tags they generate, but I may have missed it.

FWIW this now exists too


I don’t think Sundell’s repo uses the DSL @Builder or @functionBuilder though.

Terms of Service

Privacy Policy

Cookie Policy