An awesome Swift HTML DSL library using result builders.

Overview

SwiftHtml

An awesome Swift HTML DSL library using result builders.

let doc = Document(.html5) {
    Html {
        Head {
            Meta()
                .name("og:title")
                .content("My website")
            Link()
                .rel("stylesheet")
                .href("./css/style.css")
                
        }
        Body {
            Div {
                H1("Lorem ipsum")
                P("Dolor sit amet")
                A("Hello Swift HTML DSL!").href("https://swift.org")
            }
        }
    }
}
print(doc.html)

Credits & references

Comments
  • Attribute Value + Manipulate Children

    Attribute Value + Manipulate Children

    Get attribute value with key

    func value(_ key: String) -> String?
    

    This would make finding an attribute value very compact and convenient

    Add [Tag] to children with TagBuilder parameter

    public func insert(at i: Int? = nil, if condition: Bool = true, @TagBuilder children: () -> [Tag]) -> Self
    public func append(_ condition: Bool = true, @TagBuilder children: () -> [Tag]) -> Self
    

    One more option when declaring a Tag. Right now it's either Tag(...) or Tag {...} This way is both Tag(...).insert{...}

    Also, it would allow you to write func() calls on a Tag before declaring children. For example, instead of...

    Div {
         // ... a huge hierarchy making me lose track of parent's closing bracket
    }
    .func()
    .anotherFunc()
    .anotherFunc()
    

    You could put the func() calls next to the tag declaration. And then attributes are listed closer to the parent.

    Div()
         .func()
         .anotherFunc()
         .anotherFunc()
         .append {
              // ... a huge hierarchy that seems better placed in code
         }
    

    • Remove children at index

    public func remove(at i: Int, if condition: Bool = true) -> Self
    

    If children can be added, it seems only natural to also remove

    opened by bgisme 8
  • AttributeKey enum

    AttributeKey enum

    Add type safety for making Attributes with...

    enum AttributeKey: String {...}
    

    Also, I added a function to the previous pull request for getting values with AttributeKey. Since it relies on that one being approved.

    func value(_ key: AttributeKey) -> String? {
        self.value(key.rawValue)
    }
    
    opened by bgisme 4
  • Update Tag.swift

    Update Tag.swift

    Just a thought...

    I tried using Tag with generics.

    Got this compiler error...

    Constructing an object of class type ’T’ with a metatype value must use a ‘required’ initializer

    Example:

    public class MyClass<T: Tag> {

    let props: MyProps
    let children: [Tag]
    
    init(_ props: MyProps, @TagBuilder _ children: () -> [Tag]) {
        self.props = props
        self.children = children()
    }
    
    public func build() -> Tag {
        T(children)
            .doSomething(props)
            .anotherThing(props)
    }
    

    }

    opened by bgisme 4
  • Treat class attribute value like Set<String>

    Treat class attribute value like Set

    This proposal is predicated on the idea that space separated values inside the class attribute should be unique.

    <p class='valueA valueB valueC'>...<\p>
    

    I have been running into situations where I build complex objects on top of simpler ones. And many times I can't be sure if the simple object has certain values already set. So there are two choices—check the simple object for that value before adding, or just add the one I need.

    Checking takes extra time and code for every string, like an unnecessary two-step process.

    And blindly adding introduces the possibility of duplicate values, which, depending on the number of them, can lead to very messy html.

    And just fundamentally, if class values should be unique, they should be managed that way.

    Instead of...

    func `class`(add value: String?, _ condition: Bool = true) -> Self
    

    How about...

    func `class`(insert value: String?, _ condition: Bool = true) -> Self
    

    And then treat the underlying String like a Set while manipulating it.

    So when you want to add a value, you don't have to worry about whether it exists or not. And no duplications. Changing the parameter label to insert reinforces that notion.

    Also, I added a version that takes variadic Optionals.

    func `class`(insert values: String?..., if condition: Bool = true) -> Self
    

    I use it in my own code and find it extremely flexible. You can write...

    tag.class(insert: v)
    tag.class(insert: optionalV)
    
    tag.class(insert: v, if: condition)
    tag.class(insert: optionalV, if: condition)
    
    tag.class(insert: v, optionalV)
    
    tag.class(insert: v, optionalV, if: condition)
    
    tag.class(insert: v, optionalV, "anything", if: condition)
    

    The only rub is having to put a parameter label where there was none. I chose if to indicate the logic.

    I won't take it personally if this seems a bit too far out on a limb. But it's really flexible and terse when you need to constantly add a few values here or there without the [ ]. And it keeps with the theme of every other function that accepts an optional value and a Bool condition.

    I also changed...

    func `class`(insert values: [String], _ condition: Bool = true) -> Self
    

    ...to take an optional array. Again more flexibility and keeps with the theme of every other func. But I understand if it's a bridge too far.

    func `class`(insert values: [String]?, _ condition: Bool = true) -> Self
    

    Lastly, I added a guard condition in...

    func `class`(remove values: [String], _ condition: Bool = true) -> Self
    

    I could be wrong, but I think the class attribute can be deleted even if the condition is false

    I commented on my lines of code as well. Hopefully that makes things more clear.

    opened by bgisme 2
  • Update Tag.swift

    Update Tag.swift

    Is there a reason the required init can't take both contents: String? and children: [Tag]?

    So typography tags can be more readable?

    For example:

    <H4>Some text before a <span>styled text</span> and more after</H4>

    Could be written...

    H4("Some text before a") { Span("styled text") Text("and more after") }

    opened by bgisme 2
  • Update Button.swift

    Update Button.swift

    When using libraries like Bootstrap, I often need to put child elements inside buttons. But the init() only takes contents.

    Not sure if it was intentional. To only allow users to create Buttons with String contents. But I would think all Tags should have a designated init() that allows for children with a builder parameter, whether or not it produces well written HTML. And then the convenience inits would implement preferred or common usage. Like in A.swift where the convenience init() just takes contents.

    opened by bgisme 2
  • Update Textarea.swift

    Update Textarea.swift

    Textarea bug: attribute value for disabled should be "disabled" and not "autofocus"

    Tibor, this is the first time ever that I make a code change in Github. I hope, I do it correctly. Please check. Thx

    opened by m-y-n-o-n-a 1
  • Treat class attribute like Set<String> instead of Array<String>

    Treat class attribute like Set instead of Array

    These changes are primarily about trying to guarantee the format of the class attribute value is always consistent. And without empty or duplicate substrings. Regardless of whether it is set as a string literal in .attribute(...) or via the class(...) functions. And the best way to accomplish this is by treating the underlying attribute value like a Set rather than an Array

    As an added benefit, the class attribute can handle .union(...), .subtraction(...) and .intersection(...) This is especially helpful when trying to eliminate lots of possible classes without having to interrogate for each one. It takes very little code to create a large Set and just subtract it.

    opened by bgisme 0
  • Td colspan

    Td colspan

    <td> also has a colspan attribute.
    reference: https://www.w3schools.com/tags/att_td_colspan.asp
    I copied the function from <th>
    and added a test for table with attributes.

    opened by atacan 0
  • Attribute Value + Manipulate Children

    Attribute Value + Manipulate Children

    • Get attribute value with key func value(_ key: String) -> String?

     This would make finding an attribute value very compact and convenient
    

    • Add [Tag] to children with TagBuilder parameter public func insert(at i: Int? = nil, if condition: Bool = true, @TagBuilder children: () -> [Tag]) -> Self

     One more option when declaring a Tag. Right now it's either Tag(...) or Tag {...} This way is both Tag(...).insert{...}
    
     Also, it would allow you to write func() calls on a Tag before declaring children. For example, instead of...
          `Div {
                ... a huge hierarchy making me lose track of parent's closing bracket
           }
           .func()
           .anotherFunc()
           .anotherFunc()`
    
     You could put the func() calls next to the tag declaration. And then attributes are listed closer to the parent.
          `Div()
           .func()
           .anotherFunc()
           .anotherFunc()
           .insert {
                   ... a huge hierarchy that seems better placed in code
           }`
    

    • Remove children at index public func remove(at i: Int, if condition: Bool = true) -> Self

     If children can be added, it seems only natural to also remove
    
    opened by bgisme 0
  • Update Global.swift

    Update Global.swift

    Eliminate empty strings from array before joining. Otherwise the final value may contain extra spaces.

    let strings = ["1", "", "2", "3", ""]

    let str = strings.joined(separator: " ") // => "1 23 "

    let str2 = strings.filter{$0.count > 0}.joined(separator: " ") // => "123"

    opened by bgisme 0
Releases(1.6.11)
Owner
Binary Birds
Binary Birds
SwiftSoup: Pure Swift HTML Parser, with best of DOM, CSS, and jquery (Supports Linux, iOS, Mac, tvOS, watchOS)

SwiftSoup is a pure Swift library, cross-platform (macOS, iOS, tvOS, watchOS and Linux!), for working with real-world HTML. It provides a very conveni

Nabil Chatbi 3.7k Dec 28, 2022
Kanna(鉋) is an XML/HTML parser for Swift.

Kanna(鉋) Kanna(鉋) is an XML/HTML parser for cross-platform(macOS, iOS, tvOS, watchOS and Linux!). It was inspired by Nokogiri(鋸). ℹ️ Documentation Fea

Atsushi Kiwaki 2.3k Dec 31, 2022
Ji (戟) is an XML/HTML parser for Swift

Ji 戟 Ji (戟) is a Swift wrapper on libxml2 for parsing XML/HTML. Features Build XML/HTML Tree and Navigate. XPath Query Supported. Comprehensive Unit T

HongHao Zhang 824 Dec 15, 2022
Frank is a DSL for quickly writing web applications in Swift

Frank Frank is a DSL for quickly writing web applications in Swift with type-safe path routing. Sources/main.swift import Frank // Handle GET request

Kyle Fuller Archive 377 Jun 29, 2022
An awesome Swift HTTP library to rapidly create communication layers with API endpoints

An awesome Swift HTTP library to rapidly create communication layers with API endpoints

Binary Birds 69 Nov 28, 2022
Simple iOS app in Swift to show AQI for some cities using websocket using Combine + MVVM

AQI Simple iOS app in Swift to show AQI for some cities using websocket using Combine + MVVM This app follows MVVM This app uses combine framework The

Amey Vikkram Tiwari 2 Nov 6, 2022
WebSocket(RFC-6455) library written using Swift

DNWebSocket Object-Oriented, Swift-style WebSocket Library (RFC 6455) for Swift-compatible Platforms. Tests Installation Requirements Usage Tests Conf

Gleb Radchenko 36 Jan 29, 2022
Plugin and runtime library for using protobuf with Swift

Swift Protobuf Welcome to Swift Protobuf! Apple's Swift programming language is a perfect complement to Google's Protocol Buffer ("protobuf") serializ

Apple 4.1k Jan 6, 2023
AsyncHTTP - Generic networking library written using Swift async/await

Generic networking library written using Swift async/await

Laszlo Teveli 7 Aug 3, 2022
NWReachability - a pure Swift library for monitoring the network connection of iOS devices using Apple's Network framework.

NWReachability is a pure Swift library for monitoring the network connection of iOS devices using Apple's Network framework.

null 4 Dec 2, 2022
A reactive library for using URLSession

Reactive wrapper for URLSession using Combine. At its core, the library consist of the NetworkServiceClient protocol along with a minimal implementation NetworkService.

MFB Technologies, Inc. 2 Nov 20, 2022
SwiftCANLib is a library used to process Controller Area Network (CAN) frames utilizing the Linux kernel open source library SOCKETCAN.

SwiftCANLib SwiftCANLib is a library used to process Controller Area Network (CAN) frames utilizing the Linux kernel open source library SOCKETCAN. Th

Tim Wise 4 Oct 25, 2021
Socket framework for Swift using the Swift Package Manager. Works on iOS, macOS, and Linux.

BlueSocket Socket framework for Swift using the Swift Package Manager. Works on iOS, macOS, and Linux. Prerequisites Swift Swift Open Source swift-5.1

Kitura 1.3k Dec 26, 2022
Approov Integration Examples 0 Jan 26, 2022
Swift HTTP server using the pre-fork worker model

Curassow Curassow is a Swift Nest HTTP Server. It uses the pre-fork worker model and it's similar to Python's Gunicorn and Ruby's Unicorn. It exposes

Kyle Fuller Archive 397 Oct 30, 2022
Generic Network Layer created using Swift.

Generic-Network-Layer_iOS Generic Network Layer created using URLSession. Networking is an essential element in app development, and you'll need API c

Shubham Kr. Singh 41 Dec 31, 2022
❌📱 A little swift Internet error status indicator using ReachabilitySwift

EFInternetIndicator Requirements Xcode 8.0+ iOS 8.3+ WARNING : It's not work on simulator. #1 Installation CocoaPods You can use CocoaPods to install

Ezequiel França 131 Dec 14, 2022
A web API client in Swift built using Async/Await

Get A modern web API client in Swift built using Async/Await and Actors. let cli

Alexander Grebenyuk 745 Jan 3, 2023
Approov-service-ios-swift-grpc - Approov service layer for iOS clients using GRPC

Approov Service for GRPC A wrapper for the Approov SDK to enable easy integratio

Approov Integration Examples 0 Jan 21, 2022