• Stars
    star
    297
  • Rank 140,075 (Top 3 %)
  • Language
    Swift
  • License
    MIT License
  • Created over 3 years ago
  • Updated 9 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

An awesome Swift HTML DSL library using result builders.

SwiftHtml

An awesome Swift HTML DSL library using result builders.

import SwiftHtml 

let 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:

.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:

.product(name: "SwiftHtml", package: "swift-html"),

Import the framework:

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.

open class Div: Tag {

}

// <div></div> - standard tag

open class Br: EmptyTag {
    
}
// <br> - 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.

open class LastBuildDate: Tag {

    open override class func createNode() -> Node {
        Node(type: .standard, name: "lastBuildDate")
    }
}

// <lastBuildDate></lastBuildDate> - standard tag with custom name

It is also possible to create tags with altered content or default attributes.

open class Description: Tag {
    
    public init(_ contents: String) {
        super.init()
        setContents("<![CDATA[" + contents + "]]>")
    }
}
// <description><![CDATA[lorem ipsum]]></description> - content wrapped in CDATA

open class Rss: Tag {
    
    public init(@TagBuilder _ builder: () -> Tag) {
        super.init(builder())
        setAttributes([
            .init(key: "version", value: "2.0"),
        ])
    }
}
// <rss version="2.0">...</rss> - tag with a default attribute

Attribute management

You can set, add or delete the attributes of a given tag.

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")
    
// <leaf a="foo" c="baz" foo="example" bar></leaf>

You can also manage the class atrribute through helper methods.

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)

// <span class="a f"></span>

You can create your own attribute modifier via an extension.

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.

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.

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.

let tag = WebIndexTemplate(ctx) {
    ListComponent(["a", "b", "c"])
        .render(req)
}
.render(req)

If you want to create a lightweight template engine for the Vapor web framework using SwiftHtml, you can see a working example inside the Feather CMS core repository.

Credits & references

More Repositories

1

swift-http

An awesome Swift HTTP library to rapidly create communication layers with API endpoints.
Swift
81
star
2

swift-css

An awesome Swift CSS DSL library using result builders.
Swift
66
star
3

swift-template

A template based module generator for Swift projects.
Swift
47
star
4

vapor-spec

Unit testing Vapor applications through declarative specifications.
Swift
37
star
5

liquid

Abstract file storage component made for Vapor 4.
Swift
37
star
6

Sunlight

Calculate dawn, dusk, golden and blue hour times by using various algorithms.
Swift
27
star
7

Testify

Testify converts XCTest output into a proper structure (JSON, JUNIT, MD, GFM), or it'll miserably fail. πŸ˜‰
Swift
22
star
8

view-kit

A generic, reusable view layer for building (not just) admin interfaces using Vapor 4.
Swift
21
star
9

git-kit

GitKit is a Swift wrapper around the git command line interface.
Swift
20
star
10

Toucan

Toucan is a static site generator written in Swift.
Swift
19
star
11

CI

Swift + Continuous Integration service (task runner proof of concept)
Swift
18
star
12

content-api

Generic, reusable, content focused API component for Vapor.
Swift
14
star
13

shell-kit

Shell is a simple package that gives you the ability to call shell commands through Swift.
Swift
13
star
14

swift-macros

🚧 A collection of useful macro definitions for Swift. (WIP)
Swift
11
star
15

liquid-aws-s3-driver

AWS S3 driver implementation for the LiquidKit file storage solution, based on the Soto for AWS project.
Swift
9
star
16

viper-kit

VIPER module protocols for Vapor applications
Swift
9
star
17

peacock-css

A modern, responsive CSS boilerplate library to kickstart any web-based project.
HTML
8
star
18

liquid-local-driver

A local driver implementation for the LiquidKit file storage solution.
Swift
7
star
19

liquid-kit

An abstract FileStorage solution, based on the SwiftNIO framework.
Swift
7
star
20

tau

A template engine for Vapor 4 based on TauKit.
Swift
6
star
21

env-kit

EnvKit is a Swift package for transmitting environment variables between shell processes.
Swift
6
star
22

vapor-hooks

Hook functions for Vapor.
Swift
5
star
23

tau-kit

A generic purpose template engine
Swift
5
star
24

tau-foundation

Reusable entities and extensions for the Tau template engine.
Swift
4
star
25

path-kit

Working with files and directories in a nice way using Swift.
Swift
3
star
26

swift-mime

A MIME type library written for Swift
Swift
3
star
27

swagger-petstore

This is a sample Pet Store Server based on the OpenAPI 3.0 specification generated using Swift & OpenAPIKit.
Swift
2
star
28

hook-kit

Generic event hook functions and invocation for Swift.
Swift
2
star
29

TimeZones

Strong typed, autocompleted time zones with locations for Swift.
Swift
2
star
30

site

Source code of the binarybirds.com site.
Mustache
2
star
31

json-server

Swift
2
star
32

file-manager-kit

Swift
1
star
33

swift-libman

Swift
1
star
34

swift-format-template

Makefile
1
star
35

plural-kit

Swift
1
star
36

request-processing

1
star
37

swift-plugins

Plugins for Swift
Swift
1
star
38

swift-log-env

Create custom loggers using a subsystem identifier and a log level.
Shell
1
star
39

swift-nanoid

Swift
1
star