Allow template filters to throw errors

This commit is contained in:
Kyle Fuller
2015-10-24 14:41:37 -07:00
parent f35be4b701
commit 8ac6e26876
5 changed files with 29 additions and 20 deletions

View File

@@ -47,7 +47,7 @@ public class TextNode : NodeType {
} }
public protocol Resolvable { public protocol Resolvable {
func resolve(context: Context) -> Any? func resolve(context: Context) throws -> Any?
} }
public class VariableNode : NodeType { public class VariableNode : NodeType {
@@ -62,7 +62,7 @@ public class VariableNode : NodeType {
} }
public func render(context: Context) throws -> String { public func render(context: Context) throws -> String {
let result = variable.resolve(context) let result = try variable.resolve(context)
if let result = result as? String { if let result = result as? String {
return result return result
@@ -99,7 +99,7 @@ public class NowNode : NodeType {
public func render(context: Context) throws -> String { public func render(context: Context) throws -> String {
let date = NSDate() let date = NSDate()
let format = self.format.resolve(context) let format = try self.format.resolve(context)
var formatter:NSDateFormatter? var formatter:NSDateFormatter?
if let format = format as? NSDateFormatter { if let format = format as? NSDateFormatter {
@@ -154,7 +154,7 @@ public class ForNode : NodeType {
} }
public func render(context: Context) throws -> String { public func render(context: Context) throws -> String {
let values = variable.resolve(context) let values = try variable.resolve(context)
if let values = values as? NSArray { if let values = values as? NSArray {
return try values.map { item in return try values.map { item in
context.push() context.push()
@@ -227,7 +227,7 @@ public class IfNode : NodeType {
} }
public func render(context: Context) throws -> String { public func render(context: Context) throws -> String {
let result = variable.resolve(context) let result = try variable.resolve(context)
var truthy = false var truthy = false
if let result = result as? [AnyObject] { if let result = result as? [AnyObject] {

View File

@@ -10,7 +10,7 @@ public func until(tags:[String])(parser:TokenParser, token:Token) -> Bool {
return false return false
} }
public typealias Filter = Any? -> Any? public typealias Filter = Any? throws -> Any?
/// A class for parsing an array of tokens and converts them into a collection of Node's /// A class for parsing an array of tokens and converts them into a collection of Node's
public class TokenParser { public class TokenParser {

View File

@@ -24,11 +24,11 @@ class FilterExpression : Resolvable {
} }
} }
func resolve(context: Context) -> Any? { func resolve(context: Context) throws -> Any? {
let result = variable.resolve(context) let result = try variable.resolve(context)
return filters.reduce(result) { x, y in return try filters.reduce(result) { x, y in
return y(x) return try y(x)
} }
} }
} }
@@ -47,7 +47,7 @@ public struct Variable : Equatable, Resolvable {
} }
/// Resolve the variable in the given context /// Resolve the variable in the given context
public func resolve(context:Context) -> Any? { public func resolve(context:Context) throws -> Any? {
var current: Any? = context var current: Any? = context
if (variable.hasPrefix("'") && variable.hasSuffix("'")) || (variable.hasPrefix("\"") && variable.hasSuffix("\"")) { if (variable.hasPrefix("'") && variable.hasSuffix("'")) || (variable.hasPrefix("\"") && variable.hasSuffix("\"")) {

View File

@@ -4,9 +4,9 @@ import Stencil
describe("template filters") { describe("template filters") {
let context = Context(dictionary: ["name": "Kyle"]) let context = Context(dictionary: ["name": "Kyle"])
let template = Template(templateString: "{{ name|repeat }}")
$0.it("allows you to register a custom filter") { $0.it("allows you to register a custom filter") {
let template = Template(templateString: "{{ name|repeat }}")
template.parser.registerFilter("repeat") { value in template.parser.registerFilter("repeat") { value in
if let value = value as? String { if let value = value as? String {
return "\(value) \(value)" return "\(value) \(value)"
@@ -18,6 +18,15 @@ describe("template filters") {
let result = try template.render(context) let result = try template.render(context)
try expect(result) == "Kyle Kyle" try expect(result) == "Kyle Kyle"
} }
$0.it("allows you to register a custom filter") {
let template = Template(templateString: "{{ name|repeat }}")
template.parser.registerFilter("repeat") { value in
throw TemplateSyntaxError("No Repeat")
}
try expect(try template.render(context)).toThrow(TemplateSyntaxError("No Repeat"))
}
} }

View File

@@ -20,49 +20,49 @@ describe("Variable") {
$0.it("can resolve a string literal with double quotes") { $0.it("can resolve a string literal with double quotes") {
let variable = Variable("\"name\"") let variable = Variable("\"name\"")
let result = variable.resolve(context) as? String let result = try variable.resolve(context) as? String
try expect(result) == "name" try expect(result) == "name"
} }
$0.it("can resolve a string literal with single quotes") { $0.it("can resolve a string literal with single quotes") {
let variable = Variable("'name'") let variable = Variable("'name'")
let result = variable.resolve(context) as? String let result = try variable.resolve(context) as? String
try expect(result) == "name" try expect(result) == "name"
} }
$0.it("can resolve a string variable") { $0.it("can resolve a string variable") {
let variable = Variable("name") let variable = Variable("name")
let result = variable.resolve(context) as? String let result = try variable.resolve(context) as? String
try expect(result) == "Kyle" try expect(result) == "Kyle"
} }
$0.it("can resolve an item from a dictionary") { $0.it("can resolve an item from a dictionary") {
let variable = Variable("profiles.github") let variable = Variable("profiles.github")
let result = variable.resolve(context) as? String let result = try variable.resolve(context) as? String
try expect(result) == "kylef" try expect(result) == "kylef"
} }
$0.it("can resolve an item from an array via it's index") { $0.it("can resolve an item from an array via it's index") {
let variable = Variable("contacts.0") let variable = Variable("contacts.0")
let result = variable.resolve(context) as? String let result = try variable.resolve(context) as? String
try expect(result) == "Katie" try expect(result) == "Katie"
} }
$0.it("can resolve the first item from an array") { $0.it("can resolve the first item from an array") {
let variable = Variable("contacts.first") let variable = Variable("contacts.first")
let result = variable.resolve(context) as? String let result = try variable.resolve(context) as? String
try expect(result) == "Katie" try expect(result) == "Katie"
} }
$0.it("can resolve the last item from an array") { $0.it("can resolve the last item from an array") {
let variable = Variable("contacts.last") let variable = Variable("contacts.last")
let result = variable.resolve(context) as? String let result = try variable.resolve(context) as? String
try expect(result) == "Carlton" try expect(result) == "Carlton"
} }
$0.it("can resolve a value via KVO") { $0.it("can resolve a value via KVO") {
let variable = Variable("object.title") let variable = Variable("object.title")
let result = variable.resolve(context) as? String let result = try variable.resolve(context) as? String
try expect(result) == "Hello World" try expect(result) == "Hello World"
} }
} }