feat(variable): Allow Swift type introspection
This commit is contained in:
@@ -17,6 +17,9 @@
|
|||||||
|
|
||||||
### Enhancements
|
### 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`.
|
- If tags can now use prefix and infix operators such as `not`, `and` and `or`.
|
||||||
|
|
||||||
```html+django
|
```html+django
|
||||||
|
|||||||
19
README.md
19
README.md
@@ -11,21 +11,28 @@ feel right at home with Stencil.
|
|||||||
```html+django
|
```html+django
|
||||||
There are {{ articles.count }} articles.
|
There are {{ articles.count }} articles.
|
||||||
|
|
||||||
{% for article in articles %}
|
<ul>
|
||||||
- {{ article.title }} by {{ article.author }}.
|
{% for article in articles %}
|
||||||
{% endfor %}
|
<li>{{ article.title }} by {{ article.author }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
```
|
```
|
||||||
|
|
||||||
```swift
|
```swift
|
||||||
|
struct Article {
|
||||||
|
let title: String
|
||||||
|
let author: String
|
||||||
|
}
|
||||||
|
|
||||||
let context = Context(dictionary: [
|
let context = Context(dictionary: [
|
||||||
"articles": [
|
"articles": [
|
||||||
[ "title": "Migrating from OCUnit to XCTest", "author": "Kyle Fuller" ],
|
Article(title: "Migrating from OCUnit to XCTest", author: "Kyle Fuller"),
|
||||||
[ "title": "Memory Management with ARC", "author": "Kyle Fuller" ],
|
Article(title: "Memory Management with ARC", author: "Kyle Fuller"),
|
||||||
]
|
]
|
||||||
])
|
])
|
||||||
|
|
||||||
do {
|
do {
|
||||||
let template = try Template(named: "template.stencil")
|
let template = try Template(named: "template.html")
|
||||||
let rendered = try template.render(context)
|
let rendered = try template.render(context)
|
||||||
print(rendered)
|
print(rendered)
|
||||||
} catch {
|
} catch {
|
||||||
|
|||||||
@@ -87,6 +87,13 @@ public struct Variable : Equatable, Resolvable {
|
|||||||
#else
|
#else
|
||||||
current = object.value(forKey: bit)
|
current = object.value(forKey: bit)
|
||||||
#endif
|
#endif
|
||||||
|
} else if let value = current {
|
||||||
|
let mirror = Mirror(reflecting: value)
|
||||||
|
current = mirror.descendant(bit)
|
||||||
|
|
||||||
|
if current == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,16 +2,23 @@ import Spectre
|
|||||||
import Stencil
|
import Stencil
|
||||||
|
|
||||||
|
|
||||||
class CustomNode : NodeType {
|
fileprivate class CustomNode : NodeType {
|
||||||
func render(_ context:Context) throws -> String {
|
func render(_ context:Context) throws -> String {
|
||||||
return "Hello World"
|
return "Hello World"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fileprivate struct Article {
|
||||||
|
let title: String
|
||||||
|
let author: String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
func testStencil() {
|
func testStencil() {
|
||||||
describe("Stencil") {
|
describe("Stencil") {
|
||||||
$0.it("can render the README example") {
|
$0.it("can render the README example") {
|
||||||
|
|
||||||
let templateString = "There are {{ articles.count }} articles.\n" +
|
let templateString = "There are {{ articles.count }} articles.\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"{% for article in articles %}" +
|
"{% for article in articles %}" +
|
||||||
@@ -20,8 +27,8 @@ func testStencil() {
|
|||||||
|
|
||||||
let context = Context(dictionary: [
|
let context = Context(dictionary: [
|
||||||
"articles": [
|
"articles": [
|
||||||
[ "title": "Migrating from OCUnit to XCTest", "author": "Kyle Fuller" ],
|
Article(title: "Migrating from OCUnit to XCTest", author: "Kyle Fuller"),
|
||||||
[ "title": "Memory Management with ARC", "author": "Kyle Fuller" ],
|
Article(title: "Memory Management with ARC", author: "Kyle Fuller"),
|
||||||
]
|
]
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,14 @@ import Stencil
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
fileprivate struct Person {
|
||||||
|
let name: String
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate struct Article {
|
||||||
|
let author: Person
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
func testVariable() {
|
func testVariable() {
|
||||||
describe("Variable") {
|
describe("Variable") {
|
||||||
@@ -18,6 +26,7 @@ func testVariable() {
|
|||||||
"profiles": [
|
"profiles": [
|
||||||
"github": "kylef",
|
"github": "kylef",
|
||||||
],
|
],
|
||||||
|
"article": Article(author: Person(name: "Kyle"))
|
||||||
])
|
])
|
||||||
|
|
||||||
#if os(OSX)
|
#if os(OSX)
|
||||||
@@ -80,6 +89,12 @@ func testVariable() {
|
|||||||
try expect(result) == "Carlton"
|
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)
|
#if os(OSX)
|
||||||
$0.it("can resolve a value via KVO") {
|
$0.it("can resolve a value via KVO") {
|
||||||
let variable = Variable("object.title")
|
let variable = Variable("object.title")
|
||||||
|
|||||||
@@ -17,15 +17,20 @@ feel right at home with Stencil.
|
|||||||
|
|
||||||
.. code-block:: swift
|
.. code-block:: swift
|
||||||
|
|
||||||
|
struct Article {
|
||||||
|
let title: String
|
||||||
|
let author: String
|
||||||
|
}
|
||||||
|
|
||||||
let context = Context(dictionary: [
|
let context = Context(dictionary: [
|
||||||
"articles": [
|
"articles": [
|
||||||
[ "title": "Migrating from OCUnit to XCTest", "author": "Kyle Fuller" ],
|
Article(title: "Migrating from OCUnit to XCTest", author: "Kyle Fuller"),
|
||||||
[ "title": "Memory Management with ARC", "author": "Kyle Fuller" ],
|
Article(title: "Memory Management with ARC", author: "Kyle Fuller"),
|
||||||
]
|
]
|
||||||
])
|
])
|
||||||
|
|
||||||
do {
|
do {
|
||||||
let template = try Template(named: "template.stencil")
|
let template = try Template(named: "template.html")
|
||||||
let rendered = try template.render(context)
|
let rendered = try template.render(context)
|
||||||
print(rendered)
|
print(rendered)
|
||||||
} catch {
|
} catch {
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ following lookup:
|
|||||||
- Dictionary lookup
|
- Dictionary lookup
|
||||||
- Array lookup (first, last, count, index)
|
- Array lookup (first, last, count, index)
|
||||||
- Key value coding lookup
|
- Key value coding lookup
|
||||||
|
- Type introspection
|
||||||
|
|
||||||
For example, if `people` was an array:
|
For example, if `people` was an array:
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user