All Projects → BinaryBirds → swift-html

BinaryBirds / swift-html

Licence: MIT license
An awesome Swift HTML DSL library using result builders.

Programming Languages

swift
15916 projects
Makefile
30231 projects

Projects that are alternatives of or similar to swift-html

xcbeautify
A little beautifier tool for xcodebuild
Stars: ✭ 687 (+267.38%)
Mutual labels:  swift-package-manager, swift-5
Hippolyte
HTTP Stubbing in Swift
Stars: ✭ 109 (-41.71%)
Mutual labels:  swift-package-manager, swift-5
WXKDarkSky
A pure-Swift Codable layer over the Dark Sky API.
Stars: ✭ 21 (-88.77%)
Mutual labels:  swift-package-manager, swift-5
Table
CLI tables in Swift
Stars: ✭ 53 (-71.66%)
Mutual labels:  swift-package-manager, swift-5
PiedPiper
A small set of classes and functions to make easy use of Futures, Promises and async computation in general. All written in Swift for iOS 10+, WatchOS 3, tvOS and Mac OS X apps.
Stars: ✭ 44 (-76.47%)
Mutual labels:  swift-package-manager
PerfectLearnGuide
Are you eager to get programming with Swift and Perfect? This PerfectLearnGuide will help you.
Stars: ✭ 19 (-89.84%)
Mutual labels:  swift-package-manager
GoogleCloudLogging
Swift (Darwin) library for logging application events in Google Cloud.
Stars: ✭ 24 (-87.17%)
Mutual labels:  swift-package-manager
ResponderChain
Cross-platform first responder handling without subclassing views or making custom ViewRepresentables in SwiftUI. Similar to FocusState but for iOS 13+
Stars: ✭ 69 (-63.1%)
Mutual labels:  swift-package-manager
SwiftFCXRefresh
Pull to refresh in Swift.
Stars: ✭ 29 (-84.49%)
Mutual labels:  swift-package-manager
SwiftNES
Cross-platform NES Emulator written in Swift
Stars: ✭ 29 (-84.49%)
Mutual labels:  swift-package-manager
YMFF
Feature management made easy.
Stars: ✭ 26 (-86.1%)
Mutual labels:  swift-package-manager
AirPlay
Small framework that lets users track iOS AirPlay availability and extra features.
Stars: ✭ 46 (-75.4%)
Mutual labels:  swift-package-manager
geofeatures2
A lightweight, high performance geometry library in Swift.
Stars: ✭ 18 (-90.37%)
Mutual labels:  swift-package-manager
SwiLex
A universal lexer library in Swift.
Stars: ✭ 29 (-84.49%)
Mutual labels:  swift-package-manager
Dots
Lightweight Concurrent Networking Framework
Stars: ✭ 35 (-81.28%)
Mutual labels:  swift-package-manager
TeadsSDK-iOS
Teads SDK iOS Sample App - Check out an open-source sample of the Teads iOS SDK implementation
Stars: ✭ 22 (-88.24%)
Mutual labels:  swift-package-manager
swift-package-manager-ios
Example of how to use SPM v4 to manage iOS dependencies
Stars: ✭ 136 (-27.27%)
Mutual labels:  swift-package-manager
danger-swift-xcodesummary
A Danger-Swift plugin that adds build errors, warnings and unit tests results generated from xcodebuild to your Danger report
Stars: ✭ 72 (-61.5%)
Mutual labels:  swift-package-manager
tracelog
TraceLog is a highly configurable, flexible, portable, and simple to use debug logging system for Swift and Objective-C applications running on Linux, macOS, iOS, watchOS, and tvOS.
Stars: ✭ 52 (-72.19%)
Mutual labels:  swift-package-manager
Sqlable
Swift library for making storing data in a SQLite database simple and magic-free
Stars: ✭ 83 (-55.61%)
Mutual labels:  swift-package-manager

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 {

    func build() -> Tag
}

struct ListComponent: TagRepresentable {

    let items: [String]
    
    init(_ items: [String]) {
        self.items = items
    }

    @TagBuilder
    func build() -> Tag {
        Ul {
            items.map { Li($0) }
        }
    }
}

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: TagRepresentable) -> Tag {
        expression.build()
    }
    
    static func buildExpression(_ expression: TagRepresentable) -> [Tag] {
        [expression.build()]
    }

    static func buildExpression(_ expression: [TagRepresentable]) -> [Tag] {
        expression.map { $0.build() }
    }

    static func buildExpression(_ expression: [TagRepresentable]) -> Tag {
        GroupTag {
            expression.map { $0.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

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].