Skip to content

Commit

Permalink
support for iterating array of tuples with more than two values
Browse files Browse the repository at this point in the history
  • Loading branch information
ilyapuchka committed Dec 28, 2017
1 parent 74e79d4 commit 0f28367
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 12 deletions.
23 changes: 12 additions & 11 deletions Sources/ForTag.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,25 +53,26 @@ class ForNode : NodeType {
self.where = `where`
}

func push<Result>(value: Any, context: Context, closure: () throws -> (Result)) rethrows -> Result {
func push<Result>(value: Any, context: Context, closure: () throws -> (Result)) throws -> 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()
}
let valueMirror = Mirror(reflecting: value)
if case .tuple? = valueMirror.displayStyle {
if loopVariables.count > valueMirror.children.count {
throw TemplateSyntaxError("Tuple '\(value)' has less values than loop variables")
}
var variablesContext = [String: Any]()
valueMirror.children.prefix(loopVariables.count).enumerated().forEach({ (offset, element) in
if loopVariables[offset] != "_" {
variablesContext[loopVariables[offset]] = element.value
}
})

return try context.push(dictionary: [first: value.0]) {
return try context.push(dictionary: variablesContext) {
return try closure()
}
}
Expand Down
50 changes: 49 additions & 1 deletion Tests/StencilTests/ForNodeSpec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ func testForNode() {
"dict": [
"one": "I",
"two": "II",
]
],
"tuples": [(1, 2, 3), (4, 5, 6)]
])

$0.it("renders the given nodes for each item") {
Expand Down Expand Up @@ -127,6 +128,53 @@ func testForNode() {
try expect(result) == fixture
}

$0.context("given array of tuples") {
$0.it("can iterate over all tuple values") {
let templateString = "{% for first,second,third in tuples %}" +
"{{ first }}, {{ second }}, {{ third }}\n" +
"{% endfor %}\n"

let template = Template(templateString: templateString)
let result = try template.render(context)

let fixture = "1, 2, 3\n4, 5, 6\n\n"
try expect(result) == fixture
}

$0.it("can iterate with less number of variables") {
let templateString = "{% for first,second in tuples %}" +
"{{ first }}, {{ second }}\n" +
"{% endfor %}\n"

let template = Template(templateString: templateString)
let result = try template.render(context)

let fixture = "1, 2\n4, 5\n\n"
try expect(result) == fixture
}

$0.it("can use _ to skip variables") {
let templateString = "{% for first,_,third in tuples %}" +
"{{ first }}, {{ third }}\n" +
"{% endfor %}\n"

let template = Template(templateString: templateString)
let result = try template.render(context)

let fixture = "1, 3\n4, 6\n\n"
try expect(result) == fixture
}

$0.it("throws when number of variables is more than number of tuple values") {
let templateString = "{% for key,value,smth in dict %}" +
"{% endfor %}\n"

let template = Template(templateString: templateString)
try expect(template.render(context)).toThrow()
}

}

$0.it("can iterate over dictionary") {
let templateString = "{% for key,value in dict %}" +
"{{ key }}: {{ value }}\n" +
Expand Down

0 comments on commit 0f28367

Please sign in to comment.