Just a follow up from my previous post: Swiccup.
Sidenote: Swiccup might be a bit of a dumb name… I was thinking about renaming it SwiftyML, but then I saw another project that is similar called SwifTML, so that might be too confusing…
As I mentioned previously, the first round was a bit of prototyping. I spent a bit more time on it today and have come up with a more flushed out implementation and a more streamlined approach, but it does make use of a couple of operators overloads, essentially creating a mini DSL (domain specific language).
Let’s compare, the original:
The new version:
There are a few differences:
- There are now two operators: |> and <|
- The signature of all of the tag constructs are now uniformed; this greatly reduces the codegen boilerplate and complexity of the system.
- String interpolation now works
The |> and <| operators
The |> operator is used to denote a child relationship between two different HtmlElement structs. The left hand side is the parent and the right hand side is the child. This can be a single entity or an array of children.
The <| operator is used to denote attributes that should be assigned to the HtmlElement to its left, hence the arrow pointing left. This allows either a dictionary to be merged into the attributes store for the element. Above is an example of both single entry dictionaries and multiple entry dictionaries being merged in.
Streamlined Method Signature
The signature for each tag is really nice now, it’s simply:
(_ attributes: [String:String] = [:]) -> HtmlElement
Before, I had a nasty mess of things as I was trying to figure out the best call site API feel. The other nice thing about this is that I only need a handful of operator overloads to handle all of the cases too.
So yeah, to get string conversion to work properly, you need to implement four different protocols:
Good times. Also, the ExpressibleByStringInterpolation one is a real doozy. It’s also marked as deprecated, but there is no alternative yet until Swift 4, so you’ll have to ignore the warning if you want to “build clean” (e.g. with no warnings). If you don’t implement that last one, you won’t be able to use string interpolation like:
I’m going to keep playing with it. Once I get pretty comfortable about the syntax, I’ll post it up to my github account.
Oh… and just to show the comparison of what the code looks like without the operator helpers:
You know, just the terrifying normal HTML element construction you see in pretty much every OOP language.
UPDATE @ 10:58PM
While the <| is “clever”, I think I like this API usage better:
h1("class", "welcome", "id", "title") |> "Welcome to Swiccup",
To each their own though and your mileage may vary.