Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/binarybirds/swift-html
An awesome Swift HTML DSL library using result builders.
https://github.com/binarybirds/swift-html
dsl html result-builder swift swift-5 swift-html swift-package-manager
Last synced: 4 days ago
JSON representation
An awesome Swift HTML DSL library using result builders.
- Host: GitHub
- URL: https://github.com/binarybirds/swift-html
- Owner: BinaryBirds
- License: mit
- Created: 2021-07-19T13:36:40.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2024-02-25T00:02:05.000Z (10 months ago)
- Last Synced: 2024-12-18T05:05:15.355Z (11 days ago)
- Topics: dsl, html, result-builder, swift, swift-5, swift-html, swift-package-manager
- Language: Swift
- Homepage:
- Size: 338 KB
- Stars: 301
- Watchers: 12
- Forks: 26
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# SwiftHtml
An awesome Swift HTML DSL library using result builders.
```swift
import SwiftHtmllet doc = Document(.html) {
Html {
Head {
Title("Hello Swift HTML DSL")
Meta().charset("utf-8")
Meta().name(.viewport).content("width=device-width, initial-scale=1")Link(rel: .stylesheet).href("./css/style.css")
}
Body {
Main {
Div {
Section {
Img(src: "./images/swift.png", alt: "Swift Logo")
.title("Picture of the Swift Logo")
H1("Lorem ipsum")
.class("red")
P("Lorem ipsum dolor sit amet, consectetur adipiscing elit.")
.class(["green", "blue"])
.spellcheck(false)
}A("Download SwiftHtml now!")
.href("https://github.com/binarybirds/swift-html/")
.target(.blank)
.download()
Abbr("WTFPL")
.title("Do What The Fuck You Want To Public License")
}
}
.class("container")Script().src("./js/main.js").async()
}
}
}let html = DocumentRenderer(minify: false, indent: 2).render(doc)
print(html)
```## Install
You can simply use `SwiftHtml` as a dependency via the Swift Package Manager:
```swift
.package(url: "https://github.com/binarybirds/swift-html", from: "1.6.0"),
```Add the `SwiftHtml` product from the `swift-html` package as a dependency to your target:
```swift
.product(name: "SwiftHtml", package: "swift-html"),
```Import the framework:
```swift
import SwiftHtml
```That's it.
## Creating custom tags
You can define your own custom tags by subclassing the `Tag` or `EmptyTag` class.
You can follow the same pattern if you take a look at the core tags.
```swift
open class Div: Tag {}
//
- standard tagopen class Br: EmptyTag {
}
//
- no closing tag```
By default the name of the tag is automatically derived from the class name (lowercased), but you can also create your own tag type & name by overriding the `createNode()` class function.
```swift
open class LastBuildDate: Tag {open override class func createNode() -> Node {
Node(type: .standard, name: "lastBuildDate")
}
}// - standard tag with custom name
```It is also possible to create tags with altered content or default attributes.
```swift
open class Description: Tag {
public init(_ contents: String) {
super.init()
setContents("")
}
}
// - content wrapped in CDATAopen class Rss: Tag {
public init(@TagBuilder _ builder: () -> Tag) {
super.init(builder())
setAttributes([
.init(key: "version", value: "2.0"),
])
}
}
// ... - tag with a default attribute
```## Attribute management
You can set, add or delete the attributes of a given tag.
```swift
Leaf("example")
// set (override) the current attributes
.setAttributes([
.init(key: "a", value: "foo"),
.init(key: "b", value: "bar"),
.init(key: "c", value: "baz"),
])
// add a new attribute using a key & value
.attribute("foo", "example")
// add a new flag attribute (without a value)
.flagAttribute("bar")
// delete an attribute by using a key
.deleteAttribute("b")
//
```You can also manage the class atrribute through helper methods.
```swift
Span("foo")
// set (override) class values
.class("a", "b", "c")
// add new class values
.class(add: ["d", "e", "f"])
// add new class value if the condition is true
.class(add: "b", true)
/// remove multiple class values
.class(remove: ["b", "c", "d"])
/// remove a class value if the condition is true
.class(remove: "e", true)//
```You can create your own attribute modifier via an extension.
```swift
public extension Guid {
func isPermalink(_ value: Bool = true) -> Self {
attribute("isPermalink", String(value))
}
}
```There are other built-in type-safe attribute modifiers available on tags.
## Composing tags
You can come up with your own `Tag` composition system by introducing a new protocol.
```swift
protocol TagRepresentable {@TagBuilder
func build() -> Tag
}struct ListComponent: TagRepresentable {
let items: [String]
init(_ items: [String]) {
self.items = items
}func build() -> Tag {
Ul {
for item in items {
Li(item)
}
}
}
}let tag = ListComponent(["a", "b", "c"]).build()
```This way it is also possible to extend the `TagBuilder` to support the new protocol.
```swift
extension TagBuilder {static func buildExpression(_ expression: Tag) -> Tag {
expression
}
static func buildExpression(_ expression: TagRepresentable) -> Tag {
expression.build()
}
}
```Sometimes you'll need extra parameters for the build function, so you have to call the build method by hand.
In those cases it is recommended to introduce a `render` function instead of using build.
```swift
let tag = WebIndexTemplate(ctx) {
ListComponent(["a", "b", "c"])
.render(req)
}
.render(req)
```If you want to create a lightweight template engine for the [Vapor](https://vapor.codes/) web framework using SwiftHtml, you can see a working example inside the [Feather CMS core](https://github.com/FeatherCMS/feather-core) repository.
## Credits & references
- [HTML Reference](https://www.w3schools.com/tags/default.asp)