Write HTML using Swift Macros.
- Swift Macros are powerful, efficient and essentially removes any runtime overhead
- Alternative libraries may not fit all situations and may restrict how the html is generated, manipulated, prone to human error, or cost a constant performance overhead (middleware, rendering, result builders, etc)
- HTML macros enforce safety, can be used anywhere, and compile directly to strings
- The output is minified at no performance cost
How do I use this library?
Syntax: #<html element>(attributes: [], <element specific attributes>: V?, _ innerHTML: [ExpressibleByStringLiteral])
// <div class="dark"><p>Macros are beautiful</p></div>
#div(attributes: [.class(["dark"])], [
#p(["Macros are beautiful"])
])
// <a href="/RandomHashTags/litleagues" target="_blank"></a>
#a(href: "https://github.com/RandomHashTags/litleagues", target: ._blank)
// <input id="funny-number" max="420" min="69" name="funny_number" step="1" type="number" value="69">
#input(
attributes: [.id("funny-number")],
max: 420,
min: 69,
name: "funny_number",
step: 1,
type: .number,
value: "69"
)
// html example
let test:String = #html([
#body([
#div(
attributes: [
.class(["dark-mode", "row"]),
.draggable(.false),
.hidden(.true),
.inputmode(.email),
.title("Hey, you're pretty cool")
],
[
"Random text",
#div(),
#a([
#div([
#abbr()
]),
#address()
]),
#div(),
#button(disabled: true),
#video(autoplay: true, controls: false, preload: .auto, src: "https://github.com/RandomHashTags/litleagues", width: .centimeters(1)),
]
)
])
])
How do I encode variables?
Using String Interpolation.let string:String = "any string value", integer:Int = -69, float:Float = 3.14159
// ✅ DO
let _:String = #p(["\(string); \(integer); \(float)"])
// ❌ DON'T
let _:String = #p([string, "; ", String(describing: integer), "; ", float.description])
I need a custom element!
Use the #custom(tag:isVoid:attributes:innerHTML:)
macro.
We want to show the Apple Pay button:
#custom(tag: "apple-pay-button", isVoid: false, attributes: [.custom("buttonstyle", "black"), .custom("type", "buy"), .custom("locale", "el-GR")])
becomes
<apple-pay-button buttonstyle="black" type="buy" locale="el-GR"></apple-pay-button>
I need a custom attribute!
Use HTMLElementAttribute.custom(id:value:)
We want to show the Apple Pay button:
#custom(tag: "apple-pay-button", isVoid: false, attributes: [.custom("buttonstyle", "black"), .custom("type", "buy"), .custom("locale", "el-GR")])
becomes
<apple-pay-button buttonstyle="black" type="buy" locale="el-GR"></apple-pay-button>
I need to listen for events!
WARNING
Inline event handlers are an outdated way to handle events.
General consensus considers this "bad practice" and you shouldn't mix your HTML and JavaScript.
This remains deprecated to encourage use of other techniques.
Learn more at https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#inline_event_handlers_—_dont_use_these.
Use the HTMLElementAttribute.event(<type>, "<value>")
.
#div(attributes: [.event(.click, "doThing()"), .event(.change, "doAnotherThing()")])
- Libraries tested
- BinaryBuilds/swift-html v1.7.0 (patched version here; custom renderer here)
- sliemeobn/elementary v0.3.4
- JohnSundell/Plot v0.14.0
- RandomHashTags/swift-htmlkit v0.5.0 (this library)
- pointfreeco/swift-html v0.4.1
- robb/Swim v0.4.0 (patched version here)
- vapor-community/HTMLKit v2.8.1
- dokun1/Vaux v0.2.0 (patched version here; custom renderer here)
Test machine: iMac (i9 9900k, 72GB RAM, 2TB) running macOS 15.0 with the Swift 6 compiler.
Executed command: swift package -c release --allow-writing-to-package-directory benchmark --metric throughput --format jmh
This library is the clear leader in performance & efficiency. Static webpages offer the best performance, while dynamic pages still tops the charts (I am actively researching and testing improvements for dynamic pages).
Create a PR.
Love this library? Consider supporting this project by sponsoring the developers.