@@ -40,6 +40,14 @@
|
|||||||
{{ value|join:", " }}
|
{{ value|join:", " }}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- `{% for %}` tag now supports filters.
|
||||||
|
|
||||||
|
```html+django
|
||||||
|
{% for user in non_admins|default:admins %}
|
||||||
|
{{ user }}
|
||||||
|
{% endfor %}
|
||||||
|
```
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
- Variables (`{{ variable.5 }}`) that reference an array index at an unknown
|
- Variables (`{{ variable.5 }}`) that reference an array index at an unknown
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
class ForNode : NodeType {
|
class ForNode : NodeType {
|
||||||
let variable:Variable
|
let resolvable: Resolvable
|
||||||
let loopVariable:String
|
let loopVariable:String
|
||||||
let nodes:[NodeType]
|
let nodes:[NodeType]
|
||||||
let emptyNodes: [NodeType]
|
let emptyNodes: [NodeType]
|
||||||
@@ -27,18 +27,19 @@ class ForNode : NodeType {
|
|||||||
_ = parser.nextToken()
|
_ = parser.nextToken()
|
||||||
}
|
}
|
||||||
|
|
||||||
return ForNode(variable: variable, loopVariable: loopVariable, nodes: forNodes, emptyNodes:emptyNodes)
|
let filter = try parser.compileFilter(variable)
|
||||||
|
return ForNode(resolvable: filter, loopVariable: loopVariable, nodes: forNodes, emptyNodes:emptyNodes)
|
||||||
}
|
}
|
||||||
|
|
||||||
init(variable:String, loopVariable:String, nodes:[NodeType], emptyNodes:[NodeType]) {
|
init(resolvable: Resolvable, loopVariable:String, nodes:[NodeType], emptyNodes:[NodeType]) {
|
||||||
self.variable = Variable(variable)
|
self.resolvable = resolvable
|
||||||
self.loopVariable = loopVariable
|
self.loopVariable = loopVariable
|
||||||
self.nodes = nodes
|
self.nodes = nodes
|
||||||
self.emptyNodes = emptyNodes
|
self.emptyNodes = emptyNodes
|
||||||
}
|
}
|
||||||
|
|
||||||
func render(_ context: Context) throws -> String {
|
func render(_ context: Context) throws -> String {
|
||||||
let values = try variable.resolve(context)
|
let values = try resolvable.resolve(context)
|
||||||
|
|
||||||
if let values = values as? [Any] , values.count > 0 {
|
if let values = values as? [Any] , values.count > 0 {
|
||||||
let count = values.count
|
let count = values.count
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ public class TokenParser {
|
|||||||
throw TemplateSyntaxError("Invalid filter '\(name)'")
|
throw TemplateSyntaxError("Invalid filter '\(name)'")
|
||||||
}
|
}
|
||||||
|
|
||||||
func compileFilter(_ token: String) throws -> Resolvable {
|
public func compileFilter(_ token: String) throws -> Resolvable {
|
||||||
return try FilterExpression(token: token, parser: self)
|
return try FilterExpression(token: token, parser: self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,14 +12,14 @@ func testForNode() {
|
|||||||
|
|
||||||
$0.it("renders the given nodes for each item") {
|
$0.it("renders the given nodes for each item") {
|
||||||
let nodes: [NodeType] = [VariableNode(variable: "item")]
|
let nodes: [NodeType] = [VariableNode(variable: "item")]
|
||||||
let node = ForNode(variable: "items", loopVariable: "item", nodes: nodes, emptyNodes: [])
|
let node = ForNode(resolvable: Variable("items"), loopVariable: "item", nodes: nodes, emptyNodes: [])
|
||||||
try expect(try node.render(context)) == "123"
|
try expect(try node.render(context)) == "123"
|
||||||
}
|
}
|
||||||
|
|
||||||
$0.it("renders the given empty nodes when no items found item") {
|
$0.it("renders the given empty nodes when no items found item") {
|
||||||
let nodes: [NodeType] = [VariableNode(variable: "item")]
|
let nodes: [NodeType] = [VariableNode(variable: "item")]
|
||||||
let emptyNodes: [NodeType] = [TextNode(text: "empty")]
|
let emptyNodes: [NodeType] = [TextNode(text: "empty")]
|
||||||
let node = ForNode(variable: "emptyItems", loopVariable: "item", nodes: nodes, emptyNodes: emptyNodes)
|
let node = ForNode(resolvable: Variable("emptyItems"), loopVariable: "item", nodes: nodes, emptyNodes: emptyNodes)
|
||||||
try expect(try node.render(context)) == "empty"
|
try expect(try node.render(context)) == "empty"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ func testForNode() {
|
|||||||
])
|
])
|
||||||
|
|
||||||
let nodes: [NodeType] = [VariableNode(variable: "item")]
|
let nodes: [NodeType] = [VariableNode(variable: "item")]
|
||||||
let node = ForNode(variable: "items", loopVariable: "item", nodes: nodes, emptyNodes: [])
|
let node = ForNode(resolvable: Variable("items"), loopVariable: "item", nodes: nodes, emptyNodes: [])
|
||||||
try expect(try node.render(any_context)) == "123"
|
try expect(try node.render(any_context)) == "123"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,27 +40,56 @@ func testForNode() {
|
|||||||
])
|
])
|
||||||
|
|
||||||
let nodes: [NodeType] = [VariableNode(variable: "item")]
|
let nodes: [NodeType] = [VariableNode(variable: "item")]
|
||||||
let node = ForNode(variable: "items", loopVariable: "item", nodes: nodes, emptyNodes: [])
|
let node = ForNode(resolvable: Variable("items"), loopVariable: "item", nodes: nodes, emptyNodes: [])
|
||||||
try expect(try node.render(nsarray_context)) == "123"
|
try expect(try node.render(nsarray_context)) == "123"
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
$0.it("renders the given nodes while providing if the item is first in the context") {
|
$0.it("renders the given nodes while providing if the item is first in the context") {
|
||||||
let nodes: [NodeType] = [VariableNode(variable: "item"), VariableNode(variable: "forloop.first")]
|
let nodes: [NodeType] = [VariableNode(variable: "item"), VariableNode(variable: "forloop.first")]
|
||||||
let node = ForNode(variable: "items", loopVariable: "item", nodes: nodes, emptyNodes: [])
|
let node = ForNode(resolvable: Variable("items"), loopVariable: "item", nodes: nodes, emptyNodes: [])
|
||||||
try expect(try node.render(context)) == "1true2false3false"
|
try expect(try node.render(context)) == "1true2false3false"
|
||||||
}
|
}
|
||||||
|
|
||||||
$0.it("renders the given nodes while providing if the item is last in the context") {
|
$0.it("renders the given nodes while providing if the item is last in the context") {
|
||||||
let nodes: [NodeType] = [VariableNode(variable: "item"), VariableNode(variable: "forloop.last")]
|
let nodes: [NodeType] = [VariableNode(variable: "item"), VariableNode(variable: "forloop.last")]
|
||||||
let node = ForNode(variable: "items", loopVariable: "item", nodes: nodes, emptyNodes: [])
|
let node = ForNode(resolvable: Variable("items"), loopVariable: "item", nodes: nodes, emptyNodes: [])
|
||||||
try expect(try node.render(context)) == "1false2false3true"
|
try expect(try node.render(context)) == "1false2false3true"
|
||||||
}
|
}
|
||||||
|
|
||||||
$0.it("renders the given nodes while providing item counter") {
|
$0.it("renders the given nodes while providing item counter") {
|
||||||
let nodes: [NodeType] = [VariableNode(variable: "item"), VariableNode(variable: "forloop.counter")]
|
let nodes: [NodeType] = [VariableNode(variable: "item"), VariableNode(variable: "forloop.counter")]
|
||||||
let node = ForNode(variable: "items", loopVariable: "item", nodes: nodes, emptyNodes: [])
|
let node = ForNode(resolvable: Variable("items"), loopVariable: "item", nodes: nodes, emptyNodes: [])
|
||||||
try expect(try node.render(context)) == "112233"
|
try expect(try node.render(context)) == "112233"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$0.it("can render a filter") {
|
||||||
|
let templateString = "{% for article in ars|default:articles %}" +
|
||||||
|
"- {{ article.title }} by {{ article.author }}.\n" +
|
||||||
|
"{% endfor %}\n"
|
||||||
|
|
||||||
|
let context = Context(dictionary: [
|
||||||
|
"articles": [
|
||||||
|
Article(title: "Migrating from OCUnit to XCTest", author: "Kyle Fuller"),
|
||||||
|
Article(title: "Memory Management with ARC", author: "Kyle Fuller"),
|
||||||
|
]
|
||||||
|
])
|
||||||
|
|
||||||
|
let template = Template(templateString: templateString)
|
||||||
|
let result = try template.render(context)
|
||||||
|
|
||||||
|
let fixture = "" +
|
||||||
|
"- Migrating from OCUnit to XCTest by Kyle Fuller.\n" +
|
||||||
|
"- Memory Management with ARC by Kyle Fuller.\n" +
|
||||||
|
"\n"
|
||||||
|
|
||||||
|
try expect(result) == fixture
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fileprivate struct Article {
|
||||||
|
let title: String
|
||||||
|
let author: String
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user