Add library and support for partials
This commit is contained in:
17
Sources/HummingbirdMustache/Library.swift
Normal file
17
Sources/HummingbirdMustache/Library.swift
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
public class HBMustacheLibrary {
|
||||
init() {
|
||||
self.templates = [:]
|
||||
}
|
||||
|
||||
public func register(_ template: HBMustacheTemplate, named name: String) {
|
||||
templates[name] = template
|
||||
}
|
||||
|
||||
public func render(_ object: Any, withTemplateNamed name: String) -> String? {
|
||||
guard let template = templates[name] else { return nil }
|
||||
return template.render(object, library: self)
|
||||
}
|
||||
|
||||
var templates: [String: HBMustacheTemplate]
|
||||
}
|
||||
@@ -13,39 +13,22 @@ extension Dictionary: HBMustacheParent where Key == String {
|
||||
}
|
||||
|
||||
protocol HBSequence {
|
||||
func renderSection(with template: HBMustacheTemplate) -> String
|
||||
func renderInvertedSection(with template: HBMustacheTemplate) -> String
|
||||
func renderSection(with template: HBMustacheTemplate, library: HBMustacheLibrary?) -> String
|
||||
func renderInvertedSection(with template: HBMustacheTemplate, library: HBMustacheLibrary?) -> String
|
||||
}
|
||||
|
||||
extension Array: HBSequence {
|
||||
func renderSection(with template: HBMustacheTemplate) -> String {
|
||||
func renderSection(with template: HBMustacheTemplate, library: HBMustacheLibrary?) -> String {
|
||||
var string = ""
|
||||
for obj in self {
|
||||
string += template.render(obj)
|
||||
string += template.render(obj, library: library)
|
||||
}
|
||||
return string
|
||||
}
|
||||
|
||||
func renderInvertedSection(with template: HBMustacheTemplate) -> String {
|
||||
func renderInvertedSection(with template: HBMustacheTemplate, library: HBMustacheLibrary?) -> String {
|
||||
if count == 0 {
|
||||
return template.render(self)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
extension Dictionary: HBSequence {
|
||||
func renderSection(with template: HBMustacheTemplate) -> String {
|
||||
var string = ""
|
||||
for obj in self {
|
||||
string += template.render(obj)
|
||||
}
|
||||
return string
|
||||
}
|
||||
|
||||
func renderInvertedSection(with template: HBMustacheTemplate) -> String {
|
||||
if count == 0 {
|
||||
return template.render(self)
|
||||
return template.render(self, library: library)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -53,6 +53,11 @@ extension HBMustacheTemplate {
|
||||
parser.unsafeAdvance()
|
||||
_ = try parseSection(&parser)
|
||||
|
||||
case ">":
|
||||
parser.unsafeAdvance()
|
||||
let name = try parseSectionName(&parser)
|
||||
tokens.append(.partial(name))
|
||||
|
||||
default:
|
||||
let name = try parseSectionName(&parser)
|
||||
tokens.append(.variable(name))
|
||||
@@ -66,7 +71,9 @@ extension HBMustacheTemplate {
|
||||
}
|
||||
|
||||
static func parseSectionName(_ parser: inout HBParser) throws -> String {
|
||||
parser.read(while: \.isWhitespace)
|
||||
let text = parser.read(while: sectionNameChars )
|
||||
parser.read(while: \.isWhitespace)
|
||||
guard try parser.read("}"), try parser.read("}") else { throw HBMustacheError.unfinishedSectionName }
|
||||
return text.string
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
extension HBMustacheTemplate {
|
||||
public func render(_ object: Any) -> String {
|
||||
public func render(_ object: Any, library: HBMustacheLibrary? = nil) -> String {
|
||||
var string = ""
|
||||
for token in tokens {
|
||||
switch token {
|
||||
@@ -16,40 +16,44 @@ extension HBMustacheTemplate {
|
||||
}
|
||||
case .section(let variable, let template):
|
||||
let child = getChild(named: variable, from: object)
|
||||
string += renderSection(child, parent: object, with: template)
|
||||
string += renderSection(child, parent: object, with: template, library: library)
|
||||
|
||||
case .invertedSection(let variable, let template):
|
||||
let child = getChild(named: variable, from: object)
|
||||
string += renderInvertedSection(child, parent: object, with: template)
|
||||
string += renderInvertedSection(child, parent: object, with: template, library: library)
|
||||
|
||||
case .partial(let name):
|
||||
if let text = library?.render(object, withTemplateNamed: name) {
|
||||
string += text
|
||||
}
|
||||
}
|
||||
}
|
||||
return string
|
||||
}
|
||||
|
||||
func renderSection(_ child: Any?, parent: Any, with template: HBMustacheTemplate) -> String {
|
||||
func renderSection(_ child: Any?, parent: Any, with template: HBMustacheTemplate, library: HBMustacheLibrary?) -> String {
|
||||
switch child {
|
||||
case let array as HBSequence:
|
||||
return array.renderSection(with: template)
|
||||
return array.renderSection(with: template, library: library)
|
||||
case let bool as Bool:
|
||||
return bool ? template.render(parent) : ""
|
||||
return bool ? template.render(parent, library: library) : ""
|
||||
case .some(let value):
|
||||
return template.render(value)
|
||||
return template.render(value, library: library)
|
||||
case .none:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func renderInvertedSection(_ child: Any?, parent: Any, with template: HBMustacheTemplate) -> String {
|
||||
func renderInvertedSection(_ child: Any?, parent: Any, with template: HBMustacheTemplate, library: HBMustacheLibrary?) -> String {
|
||||
switch child {
|
||||
case let array as HBSequence:
|
||||
return array.renderInvertedSection(with: template)
|
||||
return array.renderInvertedSection(with: template, library: library)
|
||||
case let bool as Bool:
|
||||
return bool ? "" : template.render(parent)
|
||||
return bool ? "" : template.render(parent, library: library)
|
||||
case .some:
|
||||
return ""
|
||||
case .none:
|
||||
return template.render(parent)
|
||||
return template.render(parent, library: library)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ public class HBMustacheTemplate {
|
||||
case unescapedVariable(String)
|
||||
case section(String, HBMustacheTemplate)
|
||||
case invertedSection(String, HBMustacheTemplate)
|
||||
case partial(String)
|
||||
}
|
||||
|
||||
let tokens: [Token]
|
||||
|
||||
Reference in New Issue
Block a user