feat(if): Support elif tags

This commit is contained in:
Kyle Fuller
2017-03-03 09:56:41 +00:00
parent 233dcfc59a
commit dc8759ba34
4 changed files with 135 additions and 11 deletions

View File

@@ -1,5 +1,22 @@
# Stencil Changelog
## Master
### Enhancements
- `if` blocks may now contain else if (`elif`) conditions.
```html+django
{% if one or two and not three %}
one or two but not three
{% elif four %}
four
{% else %}
not one, two, or four
{% endif %}
```
## 0.8.0
### Breaking

View File

@@ -186,19 +186,30 @@ class IfNode : NodeType {
var components = token.components()
components.removeFirst()
var conditions: [IfCondition] = []
let expression = try parseExpression(components: components, tokenParser: parser)
let nodes = try parser.parse(until(["endif", "else"]))
conditions.append(IfCondition(expression: expression, nodes: nodes))
let nodes = try parser.parse(until(["endif", "elif", "else"]))
var conditions: [IfCondition] = [
IfCondition(expression: expression, nodes: nodes)
]
guard let token = parser.nextToken() else {
throw TemplateSyntaxError("`endif` was not found.")
var token = parser.nextToken()
while let current = token, current.contents.hasPrefix("elif") {
var components = current.components()
components.removeFirst()
let expression = try parseExpression(components: components, tokenParser: parser)
let nodes = try parser.parse(until(["endif", "elif", "else"]))
token = parser.nextToken()
conditions.append(IfCondition(expression: expression, nodes: nodes))
}
if token.contents == "else" {
if let current = token, current.contents == "else" {
conditions.append(IfCondition(expression: nil, nodes: try parser.parse(until(["endif"]))))
_ = parser.nextToken()
token = parser.nextToken()
}
guard let current = token, current.contents == "endif" else {
throw TemplateSyntaxError("`endif` was not found.")
}
return IfNode(conditions: conditions)

View File

@@ -48,6 +48,100 @@ func testIfNode() {
try expect(falseNode?.text) == "false"
}
$0.it("can parse an if with elif block") {
let tokens: [Token] = [
.block(value: "if value"),
.text(value: "true"),
.block(value: "elif something"),
.text(value: "some"),
.block(value: "else"),
.text(value: "false"),
.block(value: "endif")
]
let parser = TokenParser(tokens: tokens, environment: Environment())
let nodes = try parser.parse()
let node = nodes.first as? IfNode
let conditions = node?.conditions
try expect(conditions?.count) == 3
try expect(conditions?[0].nodes.count) == 1
let trueNode = conditions?[0].nodes.first as? TextNode
try expect(trueNode?.text) == "true"
try expect(conditions?[1].nodes.count) == 1
let elifNode = conditions?[1].nodes.first as? TextNode
try expect(elifNode?.text) == "some"
try expect(conditions?[2].nodes.count) == 1
let falseNode = conditions?[2].nodes.first as? TextNode
try expect(falseNode?.text) == "false"
}
$0.it("can parse an if with elif block without else") {
let tokens: [Token] = [
.block(value: "if value"),
.text(value: "true"),
.block(value: "elif something"),
.text(value: "some"),
.block(value: "endif")
]
let parser = TokenParser(tokens: tokens, environment: Environment())
let nodes = try parser.parse()
let node = nodes.first as? IfNode
let conditions = node?.conditions
try expect(conditions?.count) == 2
try expect(conditions?[0].nodes.count) == 1
let trueNode = conditions?[0].nodes.first as? TextNode
try expect(trueNode?.text) == "true"
try expect(conditions?[1].nodes.count) == 1
let elifNode = conditions?[1].nodes.first as? TextNode
try expect(elifNode?.text) == "some"
}
$0.it("can parse an if with multiple elif block") {
let tokens: [Token] = [
.block(value: "if value"),
.text(value: "true"),
.block(value: "elif something1"),
.text(value: "some1"),
.block(value: "elif something2"),
.text(value: "some2"),
.block(value: "else"),
.text(value: "false"),
.block(value: "endif")
]
let parser = TokenParser(tokens: tokens, environment: Environment())
let nodes = try parser.parse()
let node = nodes.first as? IfNode
let conditions = node?.conditions
try expect(conditions?.count) == 4
try expect(conditions?[0].nodes.count) == 1
let trueNode = conditions?[0].nodes.first as? TextNode
try expect(trueNode?.text) == "true"
try expect(conditions?[1].nodes.count) == 1
let elifNode = conditions?[1].nodes.first as? TextNode
try expect(elifNode?.text) == "some1"
try expect(conditions?[2].nodes.count) == 1
let elif2Node = conditions?[2].nodes.first as? TextNode
try expect(elif2Node?.text) == "some2"
try expect(conditions?[3].nodes.count) == 1
let falseNode = conditions?[3].nodes.first as? TextNode
try expect(falseNode?.text) == "false"
}
$0.it("can parse an if with complex expression") {
let tokens: [Token] = [
.block(value: "if value == \"test\" and not name"),

View File

@@ -52,10 +52,12 @@ true the contents of the block are processed. Being true is defined as:
.. code-block:: html+django
{% if variable %}
The variable was found in the current context.
{% if admin %}
The user is an administrator.
{% elif user %}
A user is logged in.
{% else %}
The variable was not found.
No user was found.
{% endif %}
Operators