Skip to content

Instantly share code, notes, and snippets.

@chriseidhof
Created August 3, 2018 08:30
Show Gist options
  • Select an option

  • Save chriseidhof/a9ce356ea840223622a79144c72f2fd5 to your computer and use it in GitHub Desktop.

Select an option

Save chriseidhof/a9ce356ea840223622a79144c72f2fd5 to your computer and use it in GitHub Desktop.
//
// main.swift
// DynamicMemberLookupXML
//
// Created by Chris Eidhof on 03.08.18.
// Copyright © 2018 objc.io. All rights reserved.
//
import Foundation
enum Node {
case tag(Tag)
case text(String)
var pretty: String {
switch self {
case let .tag(t): return t.pretty
case let .text(t): return t
}
}
}
@dynamicMemberLookup
class Tag {
var tag: String
var children: [Node] = []
var attributes: [String:String]
init(_ name: String) {
self.tag = name
self.children = []
self.attributes = [:]
}
subscript(dynamicMember member: String) -> (Any...) -> () {
let new = Tag(member)
children.append(.tag(new))
return { (args: Any...) in
for x in args {
if let attr = x as? Attr {
new.attributes[attr.key] = attr.value
} else if let s = x as? String {
new.children.append(.text(s))
} else {
fatalError()
}
}
}
}
var pretty: String {
let atts = attributes.map { "\($0.0)=\"\($0.1)\"" }.joined(separator: " ")
let c = children.map { $0.pretty }.joined(separator: "\n")
return "<\(tag) \(atts)>\n\(c)\n</\(tag)>"
}
}
infix operator .=
struct Attr { let key: String; let value: String }
func .=(lhs: String, rhs: String) -> Attr { return Attr(key: lhs, value: rhs)}
let p = Tag("person")
p.span("class" .= "wide", "Test")
p.h1("Hello")
print("done")
print(p.pretty)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment