Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/randomhashtags/swift-htmlkit
Write HTML using Swift Macros.
https://github.com/randomhashtags/swift-htmlkit
dsl html server-side-swift swift swift-library swift-macro swift-macros
Last synced: 2 months ago
JSON representation
Write HTML using Swift Macros.
- Host: GitHub
- URL: https://github.com/randomhashtags/swift-htmlkit
- Owner: RandomHashTags
- License: apache-2.0
- Created: 2024-09-16T18:21:00.000Z (3 months ago)
- Default Branch: main
- Last Pushed: 2024-10-10T03:42:41.000Z (2 months ago)
- Last Synced: 2024-10-10T08:13:00.553Z (2 months ago)
- Topics: dsl, html, server-side-swift, swift, swift-library, swift-macro, swift-macros
- Language: Swift
- Homepage:
- Size: 616 KB
- Stars: 7
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
Write HTML using Swift Macros.
- [Why](#why)
- [Examples](#examples)
- [Basic](#basic)
- [Advanced](#advanced)
- [Benchmarks](#benchmarks)
- [Static](#static)
- [Dynamic](#dynamic)
- [Conclusion](#conclusion)
- [Contributing](#contributing)
- [Funding](#funding)## Why
- 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
## Examples
### BasicHow do I use this library?
Syntax: `#(attributes: [], : V?, _ innerHTML: ExpressibleByStringLiteral...)`
#### Examples```swift
//Macros are beautiful
#div(attributes: [.class(["dark"])],
#p("Macros are beautiful")
)//
#a(href: "https://github.com/RandomHashTags/litleagues", target: ._blank)//
#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 escape HTML?
The output automatically escapes html characters **known only at compile time**.
If you know the data **at compile time** (and not working with HTML macros):
- `#escapeHTML()` macroIf you're working with **runtime** data:
- `.escapeHTML(escapeAttributes:)`
- mutates `self` escaping HTML and, optionally, attribute characters
- `.escapeHTMLAttributes()`
- mutates `self` escaping only attribute characters
- `.escapingHTML(escapeAttributes:)`
- creates a copy of `self` escaping HTML and, optionally, attribute characters
- `.escapingHTMLAttributes()`
- creates a copy of `self` escaping only attribute charactersHow do I encode variables?
Using String Interpolation.
> You will get a compiler warning saying *interpolation may introduce raw HTML*.
>
> Its up to you whether or not to suppress this warning or escape the HTML at runtime using an method described above.#### Example
```swift
let string:String = "any string value", integer:Int = -69, float:Float = 3.14159// ✅ DO
let _:String = #p("\(string); \(integer); \(float)")
let _:String = #p("\(string)", "; ", String(describing: integer), "; ", float.description)// ❌ DON'T; compiler error: String Interpolation required
let integer_string:String = String(describing: integer), float_string:String = String(describing: float)
let _:String = #p(string, "; ", integer_string, "; ", float_string)```
### Advanced
I need a custom element!
Use the `#custom(tag:isVoid:attributes:innerHTML:)` macro.
#### Example
We want to show the [Apple Pay button](https://developer.apple.com/documentation/apple_pay_on_the_web/displaying_apple_pay_buttons_using_javascript#3783424):
```swift
#custom(tag: "apple-pay-button", isVoid: false, attributes: [.custom("buttonstyle", "black"), .custom("type", "buy"), .custom("locale", "el-GR")])
```
becomes
```html```
I need a custom attribute!
Use `HTMLElementAttribute.custom(id:value:)`
#### Example
We want to show the [Apple Pay button](https://developer.apple.com/documentation/apple_pay_on_the_web/displaying_apple_pay_buttons_using_javascript#3783424):
```swift
#custom(tag: "apple-pay-button", isVoid: false, attributes: [.custom("buttonstyle", "black"), .custom("type", "buy"), .custom("locale", "el-GR")])
```
becomes
```html```
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(, "")`.
#### Example
```swift
#div(attributes: [.event(.click, "doThing()"), .event(.change, "doAnotherThing()")])
```## Benchmarks
- Libraries tested
- [BinaryBuilds/swift-html](https://github.com/BinaryBirds/swift-html) v1.7.0 (patched version [here](https://github.com/RandomHashTags/fork-bb-swift-html))
- [sliemeobn/elementary](https://github.com/sliemeobn/elementary) v0.3.4
- [JohnSundell/Plot](https://github.com/JohnSundell/Plot) v0.14.0
- [RandomHashTags/swift-htmlkit](https://github.com/RandomHashTags/swift-htmlkit) v0.6.0 (this library)
- [pointfreeco/swift-html](https://github.com/pointfreeco/swift-html) v0.4.1
- [robb/Swim](https://github.com/robb/Swim) v0.4.0 (patched version [here](https://github.com/RandomHashTags/fork-Swim); custom renderer [here](https://github.com/RandomHashTags/swift-htmlkit/blob/main/Benchmarks/Benchmarks/Swim/Swim.swift))
- [vapor-community/HTMLKit](https://github.com/vapor-community/HTMLKit) v2.8.1
- [dokun1/Vaux](https://github.com/dokun1/Vaux) v0.2.0 (patched version [here](https://github.com/RandomHashTags/fork-Vaux); custom renderer [here](https://github.com/RandomHashTags/swift-htmlkit/blob/main/Benchmarks/Benchmarks/Vaux/Vaux.swift))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 --target Benchmarks --metric throughput --format jmh`
### Static
### Dynamic
### Conclusion
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).## Contributing
Create a PR.## Funding
Love this library? Consider supporting this project by sponsoring the developers.
- [RandomHashTags](https://github.com/sponsors/RandomHashTags)