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)