@@ -1 +1 @@
|
|||||||
3.0.1
|
3.1
|
||||||
|
|||||||
@@ -17,6 +17,14 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- `for` block now allows you to iterate over array of tuples or dictionaries.
|
||||||
|
|
||||||
|
```html+django
|
||||||
|
{% for key, value in thing %}
|
||||||
|
<li>{{ key }}: {{ value }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
```
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
- You can now use literal filter arguments which contain quotes.
|
- You can now use literal filter arguments which contain quotes.
|
||||||
|
|||||||
@@ -53,13 +53,41 @@ class ForNode : NodeType {
|
|||||||
self.where = `where`
|
self.where = `where`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func push<Result>(value: Any, context: Context, closure: () throws -> (Result)) rethrows -> Result {
|
||||||
|
if loopVariables.isEmpty {
|
||||||
|
return try context.push() {
|
||||||
|
return try closure()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let value = value as? (Any, Any) {
|
||||||
|
let first = loopVariables[0]
|
||||||
|
|
||||||
|
if loopVariables.count == 2 {
|
||||||
|
let second = loopVariables[1]
|
||||||
|
|
||||||
|
return try context.push(dictionary: [first: value.0, second: value.1]) {
|
||||||
|
return try closure()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return try context.push(dictionary: [first: value.0]) {
|
||||||
|
return try closure()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return try context.push(dictionary: [loopVariables.first!: value]) {
|
||||||
|
return try closure()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func render(_ context: Context) throws -> String {
|
func render(_ context: Context) throws -> String {
|
||||||
let resolved = try resolvable.resolve(context)
|
let resolved = try resolvable.resolve(context)
|
||||||
|
|
||||||
var values: [Any]
|
var values: [Any]
|
||||||
|
|
||||||
if let dictionary = resolved as? [String: Any], !dictionary.isEmpty {
|
if let dictionary = resolved as? [String: Any], !dictionary.isEmpty {
|
||||||
values = Array(dictionary.keys)
|
values = dictionary.map { ($0.key, $0.value) }
|
||||||
} else if let array = resolved as? [Any] {
|
} else if let array = resolved as? [Any] {
|
||||||
values = array
|
values = array
|
||||||
} else {
|
} else {
|
||||||
@@ -68,7 +96,7 @@ class ForNode : NodeType {
|
|||||||
|
|
||||||
if let `where` = self.where {
|
if let `where` = self.where {
|
||||||
values = try values.filter({ item -> Bool in
|
values = try values.filter({ item -> Bool in
|
||||||
return try context.push(dictionary: [loopVariables.first!: item]) { () -> Bool in
|
return try push(value: item, context: context) {
|
||||||
try `where`.evaluate(context: context)
|
try `where`.evaluate(context: context)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -84,9 +112,11 @@ class ForNode : NodeType {
|
|||||||
"counter": index + 1,
|
"counter": index + 1,
|
||||||
]
|
]
|
||||||
|
|
||||||
return try context.push(dictionary: [loopVariables.first!: item, "forloop": forContext]) {
|
return try context.push(dictionary: ["forloop": forContext]) {
|
||||||
|
return try push(value: item, context: context) {
|
||||||
try renderNodes(nodes, context)
|
try renderNodes(nodes, context)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}.joined(separator: "")
|
}.joined(separator: "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -111,6 +111,13 @@ func testForNode() {
|
|||||||
let node = ForNode(resolvable: Variable("dict"), loopVariables: ["key"], nodes: nodes, emptyNodes: emptyNodes, where: nil)
|
let node = ForNode(resolvable: Variable("dict"), loopVariables: ["key"], nodes: nodes, emptyNodes: emptyNodes, where: nil)
|
||||||
try expect(try node.render(context)) == "onetwo"
|
try expect(try node.render(context)) == "onetwo"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$0.it("renders supports iterating over dictionary") {
|
||||||
|
let nodes: [NodeType] = [VariableNode(variable: "key"), VariableNode(variable: "value")]
|
||||||
|
let emptyNodes: [NodeType] = [TextNode(text: "empty")]
|
||||||
|
let node = ForNode(resolvable: Variable("dict"), loopVariables: ["key", "value"], nodes: nodes, emptyNodes: emptyNodes, where: nil)
|
||||||
|
try expect(try node.render(context)) == "oneItwoII"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,16 @@ A for loop allows you to iterate over an array found by variable lookup.
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
The ``for`` tag can iterate over dictionaries.
|
||||||
|
|
||||||
|
.. code-block:: html+django
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
{% for key, value in dict %}
|
||||||
|
<li>{{ key }}: {{ value }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
|
||||||
The ``for`` tag can contain optional ``where`` expression to filter out
|
The ``for`` tag can contain optional ``where`` expression to filter out
|
||||||
elements on which this expression evaluates to false.
|
elements on which this expression evaluates to false.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user