feat(variable): Allow Swift type introspection

This commit is contained in:
Kyle Fuller
2016-11-28 06:13:46 +00:00
parent 9af9cf4005
commit 38d7ec87f6
7 changed files with 57 additions and 12 deletions

View File

@@ -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

View File

@@ -11,21 +11,28 @@ feel right at home with Stencil.
```html+django
There are {{ articles.count }} articles.
<ul>
{% for article in articles %}
- {{ article.title }} by {{ article.author }}.
<li>{{ article.title }} by {{ article.author }}</li>
{% endfor %}
</ul>
```
```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 {

View File

@@ -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
}

View File

@@ -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"),
]
])

View File

@@ -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")

View File

@@ -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 {

View File

@@ -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: