🗺 swift-html
Overview
swift-html is a Swift Domain Specific Language (DSL) that allows developers to create HTML documents in a type-safe, extensible, and transformable manner. Instead of relying on traditional templating languages, which often expose applications to runtime errors and invalid HTML, swift-html embeds HTML directly into Swift’s type system, ensuring compile-time safety.
Motivation
Many developers traditionally use templating languages for rendering HTML in Swift, but these can lead to runtime errors and invalid HTML since they operate with stringly-typed APIs. swift-html addresses these issues by using Swift’s type system to ensure that HTML documents are correctly structured at compile time, reducing bugs and ensuring the validity of the HTML.
Examples
Creating HTML documents with swift-html is similar to constructing a tree-like JSON document. For example, a simple HTML document can be written as:
import Html
let document: Node = .document(
.html(
.body(
.h1("Welcome!"),
.p("You’ve found our site!")
)
)
)
This code builds a nested structure using Swift enums, making it easy to create and manipulate HTML. For instance, if there's a need to transform the document by removing all exclamation marks, one can define a transformation function:
func unexclaim(_ node: Node) -> Node {
switch node {
case .comment, .doctype:
return node
case let .element(tag, attrs, children):
return .element(tag, attrs, unexclaim(children))
case let .fragment(children):
return .fragment(children.map(unexclaim))
case let .raw(string), let .text(string):
return .raw(string.replacingOccurrences(of: "!", with: "."))
}
}
unexclaim(document)
The rendered HTML output is then consistent, both before and after transformations.
Safety
An advantage of swift-html is its ability to leverage Swift's advanced features for safer HTML document construction. For instance, attributes can force their true types rather than using plain strings, which reduces the chance of errors:
let imgTag = Node.img(attributes: [.src("cat.jpg"), .width(400), .height(300)])
Additionally, it enforces the correct nesting of HTML elements, preventing compile-time errors that occur when invalid structures are attempted.
Design
swift-html revolves around a central Node
enum with six cases: comment
, doctype
, element
, fragment
, raw
, and text
. These cases offer a comprehensive model for representing any HTML document. Helper functions are provided for constructing HTML elements and attributes, ensuring a type-safe syntax that remains close to native HTML.
FAQ
Using with Web Frameworks:
swift-html can integrate with existing Swift web frameworks like Kitura and Vapor. It has specific plugins to ease this integration.
Templating Languages vs. swift-html:
swift-html offers enhanced safety and flexibility over traditional templating languages, which often lack the type safety and transformation capabilities that swift-html provides. Nevertheless, templating languages may be more suitable in scenarios where simplicity and non-HTML document rendering are needed.
Installation
To incorporate swift-html into an Xcode project, it must be added as a package dependency:
dependencies: [
.package(url: "https://github.com/pointfreeco/swift-html", from: "0.4.0")
]
Learning More
To dive deeper, one can explore these concepts through episodes on Point-Free, a series dedicated to functional programming and Swift, hosted by Brandon Williams and Stephen Celis. Key episodes include introductions to Domain Specific Languages and comparisons between DSLs and templating languages.
License
swift-html is distributed under the MIT license, making it an open-source resource available for modification and distribution by anyone interested.