From 55245e960fa0b42618290772f6cbdbcbb9736b4e Mon Sep 17 00:00:00 2001 From: Adam Fowler Date: Thu, 11 Mar 2021 17:14:12 +0000 Subject: [PATCH] Add support for member variables --- .../HummingbirdMustache/Template+Render.swift | 23 ++++++++++++++----- .../TemplateRendererTests.swift | 18 +++++++++++++++ 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/Sources/HummingbirdMustache/Template+Render.swift b/Sources/HummingbirdMustache/Template+Render.swift index fa1099f..796f96e 100644 --- a/Sources/HummingbirdMustache/Template+Render.swift +++ b/Sources/HummingbirdMustache/Template+Render.swift @@ -89,13 +89,24 @@ extension HBTemplate { } } - func getChild(named name: String, from: Any) -> Any? { - if name == "." { return from } - if let customBox = from as? HBMustacheParent { - return customBox.child(named: name) + func getChild(named name: String, from object: Any) -> Any? { + func _getChild(named names: ArraySlice, from object: Any) -> Any? { + guard let name = names.first else { return object } + let childObject: Any? + if let customBox = object as? HBMustacheParent { + childObject = customBox.child(named: name) + } else { + let mirror = Mirror(reflecting: object) + childObject = mirror.getAttribute(forKey: name) + } + guard childObject != nil else { return nil } + let names2 = names.dropFirst() + return _getChild(named: names2, from: childObject!) } - let mirror = Mirror(reflecting: from) - return mirror.getAttribute(forKey: name) + + if name == "." { return object } + let nameSplit = name.split(separator: ".").map { String($0) } + return _getChild(named: nameSplit[...], from: object) } } diff --git a/Tests/HummingbirdMustacheTests/TemplateRendererTests.swift b/Tests/HummingbirdMustacheTests/TemplateRendererTests.swift index f8d8aab..7ea600e 100644 --- a/Tests/HummingbirdMustacheTests/TemplateRendererTests.swift +++ b/Tests/HummingbirdMustacheTests/TemplateRendererTests.swift @@ -79,4 +79,22 @@ final class TemplateRendererTests: XCTestCase { XCTAssertEqual(template2.render(Test(string: "string")), "test ") XCTAssertEqual(template2.render(Test(string: nil)), "test *") } + + func testDictionarySequence() throws { + let template = try HBTemplate("test {{#.}}{{value}}{{/.}}") + XCTAssert(template.render(["one": 1, "two": 2]) == "test 12" || + template.render(["one": 1, "two": 2]) == "test 21") + } + + func testStructureInStructure() throws { + struct SubTest { + let string: String? + } + struct Test { + let test: SubTest + } + + let template = try HBTemplate("test {{test.string}}") + XCTAssertEqual(template.render(Test(test: .init(string: "sub"))), "test sub") + } }