Merge pull request #40 from njdehoog/array_any

Cast ForNode values to Array<Any>
This commit is contained in:
Kyle Fuller
2015-11-23 11:02:29 +00:00
4 changed files with 92 additions and 21 deletions

View File

@@ -157,7 +157,7 @@ public class ForNode : NodeType {
public func render(context: Context) throws -> String { public func render(context: Context) throws -> String {
let values = try variable.resolve(context) let values = try variable.resolve(context)
if let values = values as? NSArray where values.count > 0 { if let values = values as? [Any] where values.count > 0 {
return try values.map { item in return try values.map { item in
try context.push([loopVariable: item]) { try context.push([loopVariable: item]) {
try renderNodes(nodes, context) try renderNodes(nodes, context)
@@ -232,10 +232,10 @@ public class IfNode : NodeType {
let result = try variable.resolve(context) let result = try variable.resolve(context)
var truthy = false var truthy = false
if let result = result as? NSArray { if let result = result as? [Any] {
if result.count > 0 { truthy = !result.isEmpty
truthy = true } else if let result = result as? [String:Any] {
} truthy = !result.isEmpty
} else if result != nil { } else if result != nil {
truthy = true truthy = true
} }

View File

@@ -58,11 +58,9 @@ public struct Variable : Equatable, Resolvable {
for bit in lookup() { for bit in lookup() {
if let context = current as? Context { if let context = current as? Context {
current = context[bit] current = context[bit]
} else if let dictionary = current as? [String: Any] { } else if let dictionary = resolveDictionary(current) {
current = dictionary[bit] current = dictionary[bit]
} else if let dictionary = current as? [String: AnyObject] { } else if let array = resolveArray(current) {
current = dictionary[bit]
} else if let array = current as? [Any] {
if let index = Int(bit) { if let index = Int(bit) {
current = array[index] current = array[index]
} else if bit == "first" { } else if bit == "first" {
@@ -72,27 +70,66 @@ public struct Variable : Equatable, Resolvable {
} else if bit == "count" { } else if bit == "count" {
current = array.count current = array.count
} }
} else if let array = current as? NSArray { } else if let object = current as? NSObject { // NSKeyValueCoding
if let index = Int(bit) {
current = array[index]
} else if bit == "first" {
current = array.firstObject
} else if bit == "last" {
current = array.lastObject
} else if bit == "count" {
current = array.count
}
} else if let object = current as? NSObject {
current = object.valueForKey(bit) current = object.valueForKey(bit)
} else { } else {
return nil return nil
} }
} }
return current return normalize(current)
} }
} }
public func ==(lhs: Variable, rhs: Variable) -> Bool { public func ==(lhs: Variable, rhs: Variable) -> Bool {
return lhs.variable == rhs.variable return lhs.variable == rhs.variable
} }
func resolveDictionary(current: Any?) -> [String: Any]? {
switch current {
case let dictionary as [String: Any]:
return dictionary
case let dictionary as [String: AnyObject]:
var result: [String: Any] = [:]
for (k, v) in dictionary {
result[k] = v as Any
}
return result
case let dictionary as NSDictionary:
var result: [String: Any] = [:]
for (k, v) in dictionary {
if let k = k as? String {
result[k] = v as Any
}
}
return result
default:
return nil
}
}
func resolveArray(current: Any?) -> [Any]? {
switch current {
case let array as [Any]:
return array
case let array as [AnyObject]:
return array.map { $0 as Any }
case let array as NSArray:
return array.map { $0 as Any }
default:
return nil
}
}
func normalize(current: Any?) -> Any? {
if let array = resolveArray(current) {
return array
}
if let dictionary = resolveDictionary(current) {
return dictionary
}
return current
}

View File

@@ -1,5 +1,6 @@
import Spectre import Spectre
import Stencil import Stencil
import Foundation
describe("ForNode") { describe("ForNode") {
@@ -20,4 +21,24 @@ describe("ForNode") {
let node = ForNode(variable: "emptyItems", loopVariable: "item", nodes: nodes, emptyNodes: emptyNodes) let node = ForNode(variable: "emptyItems", loopVariable: "item", nodes: nodes, emptyNodes: emptyNodes)
try expect(try node.render(context)) == "empty" try expect(try node.render(context)) == "empty"
} }
$0.it("renders a context variable of type Array<Any>") {
let any_context = Context(dictionary: [
"items": ([1, 2, 3] as [Any])
])
let nodes: [NodeType] = [VariableNode(variable: "item")]
let node = ForNode(variable: "items", loopVariable: "item", nodes: nodes, emptyNodes: [])
try expect(try node.render(any_context)) == "123"
}
$0.it("renders a context variable of type NSArray") {
let nsarray_context = Context(dictionary: [
"items": NSArray(array: [1, 2, 3])
])
let nodes: [NodeType] = [VariableNode(variable: "item")]
let node = ForNode(variable: "items", loopVariable: "item", nodes: nodes, emptyNodes: [])
try expect(try node.render(nsarray_context)) == "123"
}
} }

View File

@@ -96,5 +96,18 @@ describe("IfNode") {
let node = IfNode(variable: "items", trueNodes: [TextNode(text: "true")], falseNodes: [TextNode(text: "false")]) let node = IfNode(variable: "items", trueNodes: [TextNode(text: "true")], falseNodes: [TextNode(text: "false")])
try expect(try node.render(arrayContext)) == "false" try expect(try node.render(arrayContext)) == "false"
} }
$0.it("renders the false when dictionary expression is empty") {
let emptyItems = [String:AnyObject]()
let arrayContext = Context(dictionary: ["items": emptyItems])
let node = IfNode(variable: "items", trueNodes: [TextNode(text: "true")], falseNodes: [TextNode(text: "false")])
try expect(try node.render(arrayContext)) == "false"
}
$0.it("renders the false when Array<Any> variable is empty") {
let arrayContext = Context(dictionary: ["items": ([] as [Any])])
let node = IfNode(variable: "items", trueNodes: [TextNode(text: "true")], falseNodes: [TextNode(text: "false")])
try expect(try node.render(arrayContext)) == "false"
}
} }
} }