Building Your Own DSL with @resultBuilder in Swift: HTML Builder
๐ Ready to transform messy HTML string concatenation into beautiful, type-safe Swift code?
In Part 1 of this series, we demystified the magic behind SwiftUI's declarative syntax. Now it's time to build something real - a complete HTML DSL that you can actually use in production!
๐ฏ What We're Building
By the end of this tutorial, you'll transform this nightmare:
var html = "<html>"
html += "<head><title>" + title + "</title></head>"
html += "<body>"
html += "<div class=\"container\">"
html += "<h1>" + heading + "</h1>"
if showContent {
html += "<p>" + content + "</p>"
}
html += "</div></body></html>"
Into this beauty:
let webpage = html {
head {
title("My Awesome Site")
}
body {
div(class: "container") {
h1("Welcome!")
if showContent {
p("Amazing content here")
}
}
}
}
โจ What You'll Master
๐ ๏ธ Complete HTML DSL implementation - Every element you need, properly structured
๐ Automatic XSS protection - Built-in HTML escaping for security
๐ฏ Type-safe markup - Catch structural errors at compile time
๐งช Production testing strategies - Comprehensive test suites for DSLs
โก Modern Swift integration - Variables, loops, and conditionals that just work
๐๏ธ Why DSLs Matter Beyond SwiftUI
Every Swift developer knows SwiftUI uses @resultBuilder
, but the real power comes when you solve your own domain problems:
Server-side Swift developers โ Generate HTML responses without templating engines
Email automation โ Create dynamic email templates with type safety
Static site generation โ Build documentation sites with Swift
Configuration management โ Declare complex app settings declaratively
๐ป Core Architecture Revealed
The magic starts with a solid foundation:
protocol HTMLElement {
func render() -> String
}
struct Element: HTMLElement {
let tag: String
let attributes: [String: String]
let children: [HTMLElement]
let isSelfClosing: Bool
func render() -> String {
// Automatic HTML generation with proper escaping
}
}
Then we add the @resultBuilder
that makes the beautiful syntax possible:
@resultBuilder
struct HTMLBuilder {
static func buildBlock(_ components: HTMLElement...) -> HTMLElement {
ElementGroup(Array(components))
}
static func buildOptional(_ component: HTMLElement?) -> HTMLElement {
component ?? ElementGroup([])
}
// Automatic string-to-HTML conversion
static func buildExpression(_ expression: String) -> HTMLElement {
TextNode(expression) // With XSS protection built-in!
}
}
๐ง Production-Ready Patterns
Complete element support for all your HTML needs:
func div(class: String? = nil, @HTMLBuilder content: () -> HTMLElement) -> HTMLElement
func p(@HTMLBuilder content: () -> HTMLElement) -> HTMLElement
func img(src: String, alt: String) -> HTMLElement
// Plus 20+ more elements...
Smart conditional rendering that feels natural:
let userProfile = div {
h1(user.name)
if user.isVerified {
span(class: "verified") { "โ Verified" }
}
for skill in user.skills {
span(class: "skill") { skill }
}
}
Automatic security through HTML escaping:
p { "<script>alert('xss')</script>" }
// Safely renders: <p><script>alert('xss')</script></p>
๐งช Testing Like a Pro
DSLs need robust testing. Here's how we ensure reliability:
func testConditionalContent() {
let element = div {
p("Always visible")
if true {
span("Sometimes visible")
}
}
let html = element.render()
XCTAssertTrue(html.contains("Always visible"))
XCTAssertTrue(html.contains("Sometimes visible"))
}
๐ฏ Real-World Benefits
For teams:
- Reduced bugs - No more missing closing tags
- Better readability - Code that looks like what it produces
- Easier maintenance - Refactor HTML structure with Swift tools
For projects:
- Type safety - Catch errors at compile time
- Security - XSS protection built-in
- Performance - Efficient string generation
- Flexibility - Easy to extend and customize
๐ What's Next?
This complete tutorial covers:
- Foundation architecture and design decisions
- Complete
@resultBuilder
implementation - Full HTML element library
- Production testing strategies
- Integration with modern Swift features
- Real-world usage examples
Part 3 of this series will cover advanced patterns, performance optimization, and production deployment strategies.
๐ Read the Complete Guide
Ready to master DSL creation? The full tutorial includes complete working code, detailed explanations, and production-ready patterns:
Building Your Own DSL with @resultBuilder in Swift: HTML Builder
๐ฌ Join the Discussion
What would you build with a custom DSL? Share your ideas in the comments!
- Configuration management for complex apps?
- API response builders for server-side Swift?
- Test data generation for your test suites?
- Custom markup languages for your domain?
๐ Stay Connected
Follow me for more Swift deep dives and iOS development insights:
- Twitter: @swift_karan
- LinkedIn: karan-pal
- Medium: Subscribe for updates
Enjoyed this? Buy me a coffee โ to fuel more comprehensive Swift tutorials!
Top comments (0)