feat(variable): Allow Swift type introspection
This commit is contained in:
@@ -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
|
||||
|
||||
19
README.md
19
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 %}
|
||||
<ul>
|
||||
{% for article in articles %}
|
||||
<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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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"),
|
||||
]
|
||||
])
|
||||
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user