diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2994156..1e578a1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,6 +17,9 @@
### Enhancements
+- Variable lookup now supports introspection of Swift types. You can now lookup
+ values of Swift structures and classes inside a Context.
+
- If tags can now use prefix and infix operators such as `not`, `and` and `or`.
```html+django
diff --git a/README.md b/README.md
index d33858f..1a40c72 100644
--- a/README.md
+++ b/README.md
@@ -11,21 +11,28 @@ feel right at home with Stencil.
```html+django
There are {{ articles.count }} articles.
-{% for article in articles %}
- - {{ article.title }} by {{ article.author }}.
-{% endfor %}
+
+ {% for article in articles %}
+ - {{ article.title }} by {{ article.author }}
+ {% endfor %}
+
```
```swift
+struct Article {
+ let title: String
+ let author: String
+}
+
let context = Context(dictionary: [
"articles": [
- [ "title": "Migrating from OCUnit to XCTest", "author": "Kyle Fuller" ],
- [ "title": "Memory Management with ARC", "author": "Kyle Fuller" ],
+ Article(title: "Migrating from OCUnit to XCTest", author: "Kyle Fuller"),
+ Article(title: "Memory Management with ARC", author: "Kyle Fuller"),
]
])
do {
- let template = try Template(named: "template.stencil")
+ let template = try Template(named: "template.html")
let rendered = try template.render(context)
print(rendered)
} catch {
diff --git a/Sources/Variable.swift b/Sources/Variable.swift
index dcd462a..3c29bf6 100644
--- a/Sources/Variable.swift
+++ b/Sources/Variable.swift
@@ -87,6 +87,13 @@ public struct Variable : Equatable, Resolvable {
#else
current = object.value(forKey: bit)
#endif
+ } else if let value = current {
+ let mirror = Mirror(reflecting: value)
+ current = mirror.descendant(bit)
+
+ if current == nil {
+ return nil
+ }
} else {
return nil
}
diff --git a/Tests/StencilTests/StencilSpec.swift b/Tests/StencilTests/StencilSpec.swift
index c7521e5..fa0cff2 100644
--- a/Tests/StencilTests/StencilSpec.swift
+++ b/Tests/StencilTests/StencilSpec.swift
@@ -2,16 +2,23 @@ import Spectre
import Stencil
-class CustomNode : NodeType {
+fileprivate class CustomNode : NodeType {
func render(_ context:Context) throws -> String {
return "Hello World"
}
}
+fileprivate struct Article {
+ let title: String
+ let author: String
+}
+
+
func testStencil() {
describe("Stencil") {
$0.it("can render the README example") {
+
let templateString = "There are {{ articles.count }} articles.\n" +
"\n" +
"{% for article in articles %}" +
@@ -20,8 +27,8 @@ func testStencil() {
let context = Context(dictionary: [
"articles": [
- [ "title": "Migrating from OCUnit to XCTest", "author": "Kyle Fuller" ],
- [ "title": "Memory Management with ARC", "author": "Kyle Fuller" ],
+ Article(title: "Migrating from OCUnit to XCTest", author: "Kyle Fuller"),
+ Article(title: "Memory Management with ARC", author: "Kyle Fuller"),
]
])
diff --git a/Tests/StencilTests/VariableSpec.swift b/Tests/StencilTests/VariableSpec.swift
index 2713626..19123d6 100644
--- a/Tests/StencilTests/VariableSpec.swift
+++ b/Tests/StencilTests/VariableSpec.swift
@@ -9,6 +9,14 @@ import Stencil
}
#endif
+fileprivate struct Person {
+ let name: String
+}
+
+fileprivate struct Article {
+ let author: Person
+}
+
func testVariable() {
describe("Variable") {
@@ -18,6 +26,7 @@ func testVariable() {
"profiles": [
"github": "kylef",
],
+ "article": Article(author: Person(name: "Kyle"))
])
#if os(OSX)
@@ -80,6 +89,12 @@ func testVariable() {
try expect(result) == "Carlton"
}
+ $0.it("can resolve a property with reflection") {
+ let variable = Variable("article.author.name")
+ let result = try variable.resolve(context) as? String
+ try expect(result) == "Kyle"
+ }
+
#if os(OSX)
$0.it("can resolve a value via KVO") {
let variable = Variable("object.title")
diff --git a/docs/index.rst b/docs/index.rst
index a2c0c5b..10fbb37 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -17,15 +17,20 @@ feel right at home with Stencil.
.. code-block:: swift
+ struct Article {
+ let title: String
+ let author: String
+ }
+
let context = Context(dictionary: [
"articles": [
- [ "title": "Migrating from OCUnit to XCTest", "author": "Kyle Fuller" ],
- [ "title": "Memory Management with ARC", "author": "Kyle Fuller" ],
+ Article(title: "Migrating from OCUnit to XCTest", author: "Kyle Fuller"),
+ Article(title: "Memory Management with ARC", author: "Kyle Fuller"),
]
])
do {
- let template = try Template(named: "template.stencil")
+ let template = try Template(named: "template.html")
let rendered = try template.render(context)
print(rendered)
} catch {
diff --git a/docs/templates.rst b/docs/templates.rst
index d112936..6db5e4b 100644
--- a/docs/templates.rst
+++ b/docs/templates.rst
@@ -22,6 +22,7 @@ following lookup:
- Dictionary lookup
- Array lookup (first, last, count, index)
- Key value coding lookup
+- Type introspection
For example, if `people` was an array: