From 1c95e07c1ee8af740f786064bce425da1ab7ff12 Mon Sep 17 00:00:00 2001 From: Geoffrey Foster Date: Mon, 18 Nov 2019 11:24:19 -0500 Subject: [PATCH] introduce the initial FilterContext type that is passed into a FilterFunc --- Sources/Liquid/Expression.swift | 6 +- Sources/Liquid/Filter+Standard.swift | 103 ++++++++++++++------------- Sources/Liquid/Filter.swift | 2 +- Sources/Liquid/FilterContext.swift | 20 ++++++ Sources/Liquid/Variable.swift | 2 +- Tests/LiquidTests/FilterTests.swift | 40 +++++------ 6 files changed, 97 insertions(+), 76 deletions(-) create mode 100644 Sources/Liquid/FilterContext.swift diff --git a/Sources/Liquid/Expression.swift b/Sources/Liquid/Expression.swift index ab8edc1..9b888e1 100644 --- a/Sources/Liquid/Expression.swift +++ b/Sources/Liquid/Expression.swift @@ -99,11 +99,11 @@ struct Expression: CustomStringConvertible { } else { switch filter { case .size: - result = try? Filters.sizeFilter(value: data, args: [], kwargs: [:], encoder: context.encoder) + result = try? Filters.sizeFilter(value: data, args: [], kwargs: [:], context: FilterContext(context: context)) case .first: - result = try? Filters.firstFilter(value: data, args: [], kwargs: [:], encoder: context.encoder) + result = try? Filters.firstFilter(value: data, args: [], kwargs: [:], context: FilterContext(context: context)) case .last: - result = try? Filters.lastFilter(value: data, args: [], kwargs: [:], encoder: context.encoder) + result = try? Filters.lastFilter(value: data, args: [], kwargs: [:], context: FilterContext(context: context)) } } } else { diff --git a/Sources/Liquid/Filter+Standard.swift b/Sources/Liquid/Filter+Standard.swift index 3de6c87..365963a 100644 --- a/Sources/Liquid/Filter+Standard.swift +++ b/Sources/Liquid/Filter+Standard.swift @@ -56,7 +56,7 @@ enum Filters { template.registerFilter(name: "date", filter: dateFilter) } - static func appendFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func appendFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { var result = value.toString() args.forEach { result += $0.toString() @@ -64,28 +64,28 @@ enum Filters { return Value(result) } - static func prependFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func prependFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard let first = args.first, args.count == 1 else { throw RuntimeError.invalidArgCount(expected: 1, received: args.count, tag: tagName()) } return Value(first.toString() + value.toString()) } - static func downcaseFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func downcaseFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard args.isEmpty else { throw RuntimeError.invalidArgCount(expected: 0, received: args.count, tag: tagName()) } return Value(value.toString().lowercased()) } - static func upcaseFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func upcaseFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard args.isEmpty else { throw RuntimeError.invalidArgCount(expected: 0, received: args.count, tag: tagName()) } return Value(value.toString().uppercased()) } - static func capitalizeFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func capitalizeFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard args.isEmpty else { throw RuntimeError.invalidArgCount(expected: 0, received: args.count, tag: tagName()) } @@ -93,56 +93,56 @@ enum Filters { return Value(string.prefix(1).capitalized + string.dropFirst()) } - static func stripFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func stripFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard args.isEmpty else { throw RuntimeError.invalidArgCount(expected: 0, received: args.count, tag: tagName()) } return Value(value.toString().strip()) } - static func rstripFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func rstripFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard args.isEmpty else { throw RuntimeError.invalidArgCount(expected: 0, received: args.count, tag: tagName()) } return Value(value.toString().rstrip()) } - static func lstripFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func lstripFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard args.isEmpty else { throw RuntimeError.invalidArgCount(expected: 0, received: args.count, tag: tagName()) } return Value(value.toString().lstrip()) } - static func stripNewlinesFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func stripNewlinesFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard args.isEmpty else { throw RuntimeError.invalidArgCount(expected: 0, received: args.count, tag: tagName()) } return Value(value.toString().replacingOccurrences(of: "\\s", with: "", options: [.regularExpression])) } - static func newlineToBRFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func newlineToBRFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard args.isEmpty else { throw RuntimeError.invalidArgCount(expected: 0, received: args.count, tag: tagName()) } return Value(value.toString().replacingOccurrences(of: "\n", with: "
\n")) } - static func escapeFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func escapeFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard args.isEmpty else { throw RuntimeError.invalidArgCount(expected: 0, received: args.count, tag: tagName()) } return Value(value.toString().htmlEscape(decimal: true, useNamedReferences: true)) } - static func escapeOnceFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func escapeOnceFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard args.isEmpty else { throw RuntimeError.invalidArgCount(expected: 0, received: args.count, tag: tagName()) } return Value(value.toString().htmlUnescape().htmlEscape(decimal: true, useNamedReferences: true)) } - static func urlEncodeFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func urlEncodeFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard args.isEmpty else { throw RuntimeError.invalidArgCount(expected: 0, received: args.count, tag: tagName()) } @@ -152,7 +152,7 @@ enum Filters { return Value(inputString.addingPercentEncoding(withAllowedCharacters: allowedCharset) ?? inputString) } - static func urlDecodeFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func urlDecodeFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard args.isEmpty else { throw RuntimeError.invalidArgCount(expected: 0, received: args.count, tag: tagName()) } @@ -160,14 +160,14 @@ enum Filters { return Value(string.removingPercentEncoding ?? string) } - static func stripHTMLFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func stripHTMLFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard args.isEmpty else { throw RuntimeError.invalidArgCount(expected: 0, received: args.count, tag: tagName()) } return Value(value.toString().replacingOccurrences(of: "<[^>]+>", with: "", options: .regularExpression)) } - static func truncateFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func truncateFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard !args.isEmpty, let firstArg = args.first else { throw RuntimeError.invalidArgCount(expected: 1, received: args.count, tag: tagName()) } @@ -179,7 +179,7 @@ enum Filters { return Value(String((string[string.startIndex.. Value { + static func truncateWordsFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard !args.isEmpty, let firstArg = args.first else { throw RuntimeError.invalidArgCount(expected: 1, received: args.count, tag: tagName()) } @@ -206,7 +206,7 @@ enum Filters { return Value(words.joined(separator: " ").appending(suffix)) } - static func plusFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func plusFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard args.count == 1, let arg = args.first else { throw RuntimeError.invalidArgCount(expected: 1, received: args.count, tag: tagName()) } @@ -216,7 +216,7 @@ enum Filters { return Value(value.toDecimal() + arg.toDecimal()) } - static func minusFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func minusFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard args.count == 1, let arg = args.first else { throw RuntimeError.invalidArgCount(expected: 1, received: args.count, tag: tagName()) } @@ -226,7 +226,7 @@ enum Filters { return Value(value.toDecimal() - arg.toDecimal()) } - static func multipliedByFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func multipliedByFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard args.count == 1, let arg = args.first else { throw RuntimeError.invalidArgCount(expected: 1, received: args.count, tag: tagName()) } @@ -236,7 +236,7 @@ enum Filters { return Value(value.toDecimal() * arg.toDecimal()) } - static func dividedByFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func dividedByFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard args.count == 1, let arg = args.first else { throw RuntimeError.invalidArgCount(expected: 1, received: args.count, tag: tagName()) } @@ -246,7 +246,7 @@ enum Filters { return Value(value.toDecimal() / arg.toDecimal()) } - static func absFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func absFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard args.isEmpty else { throw RuntimeError.invalidArgCount(expected: 0, received: args.count, tag: tagName()) } @@ -256,7 +256,7 @@ enum Filters { return Value(abs(value.toDecimal())) } - static func ceilFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func ceilFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard args.isEmpty else { throw RuntimeError.invalidArgCount(expected: 0, received: args.count, tag: tagName()) } @@ -266,7 +266,7 @@ enum Filters { return Value(ceil(value.toDecimal().doubleValue)) } - static func floorFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func floorFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard args.isEmpty else { throw RuntimeError.invalidArgCount(expected: 0, received: args.count, tag: tagName()) } @@ -276,7 +276,7 @@ enum Filters { return Value(floor(value.toDecimal().doubleValue)) } - static func roundFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func roundFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard args.count <= 1 else { throw RuntimeError.invalidArgCount(expected: 1, received: args.count, tag: tagName()) } @@ -285,7 +285,7 @@ enum Filters { return Value(result) } - static func moduloFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func moduloFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard args.count == 1, let arg = args.first else { throw RuntimeError.invalidArgCount(expected: 1, received: args.count, tag: tagName()) } @@ -296,7 +296,7 @@ enum Filters { return Value(value.toDecimal().doubleValue.truncatingRemainder(dividingBy: arg.toDecimal().doubleValue)) } - static func splitFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func splitFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard let separator = args.first?.toString() else { throw RuntimeError.invalidArgCount(expected: 0, received: args.count, tag: tagName()) } @@ -304,14 +304,14 @@ enum Filters { return Value(components.map { Value($0) }) } - static func joinFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func joinFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard let separator = args.first?.toString() else { throw RuntimeError.invalidArgCount(expected: 0, received: args.count, tag: tagName()) } return Value(value.toArray().map { $0.toString() }.joined(separator: separator)) } - static func uniqueFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func uniqueFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard args.isEmpty else { throw RuntimeError.invalidArgCount(expected: 0, received: args.count, tag: tagName()) } @@ -325,26 +325,26 @@ enum Filters { return Value(unique) } - static func sizeFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func sizeFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard args.isEmpty else { throw RuntimeError.invalidArgCount(expected: 0, received: args.count, tag: tagName()) } return Value(value.size) } - static func firstFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func firstFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard args.isEmpty else { throw RuntimeError.invalidArgCount(expected: 0, received: args.count, tag: tagName()) } return value.toArray().first ?? Value() } - static func lastFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func lastFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard args.isEmpty else { throw RuntimeError.invalidArgCount(expected: 0, received: args.count, tag: tagName()) } return value.toArray().last ?? Value() } - static func defaultFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func defaultFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard args.count == 1, let arg = args.first else { throw RuntimeError.invalidArgCount(expected: 1, received: args.count, tag: tagName()) } @@ -354,7 +354,7 @@ enum Filters { return value } } - static func replaceFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func replaceFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard args.count == 2 else { throw RuntimeError.invalidArgCount(expected: 2, received: args.count, tag: tagName()) } @@ -363,7 +363,7 @@ enum Filters { return Value(value.toString().replacingOccurrences(of: target, with: replacement)) } - static func replaceFirstFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func replaceFirstFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard args.count == 2 else { throw RuntimeError.invalidArgCount(expected: 2, received: args.count, tag: tagName()) } @@ -376,7 +376,7 @@ enum Filters { return Value(string.replacingCharacters(in: range, with: replacement)) } - static func removeFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func removeFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard args.count == 1 else { throw RuntimeError.invalidArgCount(expected: 1, received: args.count, tag: tagName()) } @@ -384,7 +384,7 @@ enum Filters { return Value(value.toString().replacingOccurrences(of: target, with: "")) } - static func removeFirstFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func removeFirstFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard args.count == 1 else { throw RuntimeError.invalidArgCount(expected: 1, received: args.count, tag: tagName()) } @@ -396,7 +396,7 @@ enum Filters { return Value(string.replacingCharacters(in: range, with: "")) } - static func sliceFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func sliceFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard !args.isEmpty else { throw RuntimeError.invalidArgCount(expected: 1, received: args.count, tag: tagName()) } @@ -424,31 +424,31 @@ enum Filters { return Value(String(string[sliceStartIndex.. Value { + static func reverseFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard args.isEmpty else { throw RuntimeError.invalidArgCount(expected: 0, received: args.count, tag: tagName()) } return Value(value.toArray().reversed()) } - static func compactFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func compactFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard args.isEmpty else { throw RuntimeError.invalidArgCount(expected: 0, received: args.count, tag: tagName()) } return Value(value.toArray().filter { !$0.isNil }) } - static func mapFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func mapFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard args.count == 1 else { throw RuntimeError.invalidArgCount(expected: 1, received: args.count, tag: tagName()) } let property = args[0] - let results = value.toArray().map { $0.lookup(property, encoder: encoder) } + let results = value.toArray().map { $0.lookup(property, encoder: context.encoder) } return Value(results) } - static func concatFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func concatFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard args.count == 1 else { throw RuntimeError.invalidArgCount(expected: 1, received: args.count, tag: tagName()) } @@ -461,28 +461,28 @@ enum Filters { return Value(array) } - static func sortFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func sortFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard args.count <= 1 else { throw RuntimeError.invalidArgCount(expected: 1, received: args.count, tag: tagName()) } if let property = args.first { return Value(value.toArray().sorted(by: { (lhs, rhs) -> Bool in - return lhs.lookup(property, encoder: encoder) < rhs.lookup(property, encoder: encoder) + return lhs.lookup(property, encoder: context.encoder) < rhs.lookup(property, encoder: context.encoder) })) } else { return Value(value.toArray().sorted()) } } - static func sortNaturalFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func sortNaturalFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard args.count <= 1 else { throw RuntimeError.invalidArgCount(expected: 1, received: args.count, tag: tagName()) } if let property = args.first { return Value(value.toArray().sorted(by: { (lhs, rhs) -> Bool in - return lhs.lookup(property, encoder: encoder).toString().caseInsensitiveCompare(rhs.lookup(property, encoder: encoder).toString()) == .orderedAscending + return lhs.lookup(property, encoder: context.encoder).toString().caseInsensitiveCompare(rhs.lookup(property, encoder: context.encoder).toString()) == .orderedAscending })) } else { return Value(value.toArray().sorted(by: { (lhs, rhs) -> Bool in @@ -491,12 +491,12 @@ enum Filters { } } - static func dateFilter(value: Value, args: [Value], kwargs: [String: Value], encoder: Encoder) throws -> Value { + static func dateFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value { guard args.count == 1 else { throw RuntimeError.invalidArgCount(expected: 1, received: args.count, tag: tagName()) } - guard let date = convertValueToDate(value, encoder: encoder) else { + guard let date = convertValueToDate(value, context: context) else { throw RuntimeError.wrongType("Could not convert to date") } @@ -504,6 +504,7 @@ enum Filters { let formatter: DateFormatter if format.isEmpty { formatter = DateFormatter() + formatter.locale = context.encoder.locale formatter.dateStyle = .short formatter.timeStyle = .medium } else { @@ -512,7 +513,7 @@ enum Filters { return Value(formatter.string(from: date)) } - private static func convertValueToDate(_ value: Value, encoder: Encoder) -> Date? { + private static func convertValueToDate(_ value: Value, context: FilterContext) -> Date? { if value.isInteger { return Date(timeIntervalSince1970: Double(value.toInteger())) } @@ -526,6 +527,6 @@ enum Filters { if ["now", "today"].contains(string.lowercased()) { return Date() } - return encoder.dateEncodingStrategry.date(from: string) + return context.encoder.dateEncodingStrategry.date(from: string) } } diff --git a/Sources/Liquid/Filter.swift b/Sources/Liquid/Filter.swift index f54153b..127f26b 100644 --- a/Sources/Liquid/Filter.swift +++ b/Sources/Liquid/Filter.swift @@ -19,4 +19,4 @@ struct Filter { } } -public typealias FilterFunc = (_ value: Value, _ args: [Value], _ kwargs: [String: Value], _ encoder: Encoder) throws -> Value +public typealias FilterFunc = (_ value: Value, _ args: [Value], _ kwargs: [String: Value], _ context: FilterContext) throws -> Value diff --git a/Sources/Liquid/FilterContext.swift b/Sources/Liquid/FilterContext.swift new file mode 100644 index 0000000..93c6c79 --- /dev/null +++ b/Sources/Liquid/FilterContext.swift @@ -0,0 +1,20 @@ +// +// FilterContext.swift +// +// +// Created by Geoffrey Foster on 2019-11-18. +// + +import Foundation + +public struct FilterContext { + public let encoder: Encoder + + init(context: Context) { + self.init(encoder: context.encoder) + } + + init(encoder: Encoder) { + self.encoder = encoder + } +} diff --git a/Sources/Liquid/Variable.swift b/Sources/Liquid/Variable.swift index d58fa53..c8d2a11 100644 --- a/Sources/Liquid/Variable.swift +++ b/Sources/Liquid/Variable.swift @@ -65,7 +65,7 @@ struct Variable { guard let filterFunc = context.filter(named: filter.name) else { throw RuntimeError.unknownFilter(filter.name) } - value = try filterFunc(value, filter.args.map { $0.evaluate(context: context) }, filter.kwargs.mapValues { $0.evaluate(context: context) }, context.encoder) + value = try filterFunc(value, filter.args.map { $0.evaluate(context: context) }, filter.kwargs.mapValues { $0.evaluate(context: context) }, FilterContext(context: context)) } return value } diff --git a/Tests/LiquidTests/FilterTests.swift b/Tests/LiquidTests/FilterTests.swift index feb5f2f..66c5446 100644 --- a/Tests/LiquidTests/FilterTests.swift +++ b/Tests/LiquidTests/FilterTests.swift @@ -54,25 +54,25 @@ final class FilterTests: XCTestCase { } func testEscape() { - XCTAssertEqual(try Filters.escapeFilter(value: Value(""), args: [], kwargs: [:], encoder: Encoder()).toString(), "<strong>") + XCTAssertEqual(try Filters.escapeFilter(value: Value(""), args: [], kwargs: [:], context: FilterContext(encoder: Encoder())).toString(), "<strong>") } func testEscapeOnce() throws { - XCTAssertEqual(try Filters.escapeOnceFilter(value: Value("<strong>Hulk"), args: [], kwargs: [:], encoder: Encoder()).toString(), "<strong>Hulk</strong>") + XCTAssertEqual(try Filters.escapeOnceFilter(value: Value("<strong>Hulk"), args: [], kwargs: [:], context: FilterContext(encoder: Encoder())).toString(), "<strong>Hulk</strong>") } func testUrlEncode() { - XCTAssertEqual(try Filters.urlEncodeFilter(value: Value("foo+1@example.com"), args: [], kwargs: [:], encoder: Encoder()).toString(), "foo%2B1%40example.com") + XCTAssertEqual(try Filters.urlEncodeFilter(value: Value("foo+1@example.com"), args: [], kwargs: [:], context: FilterContext(encoder: Encoder())).toString(), "foo%2B1%40example.com") } func testUrlDecode() { - XCTAssertEqual(try Filters.urlDecodeFilter(value: Value("foo+bar"), args: [], kwargs: [:], encoder: Encoder()).toString(), "foo bar") - XCTAssertEqual(try Filters.urlDecodeFilter(value: Value("foo%20bar"), args: [], kwargs: [:], encoder: Encoder()).toString(), "foo bar") - XCTAssertEqual(try Filters.urlDecodeFilter(value: Value("foo%2B1%40example.com"), args: [], kwargs: [:], encoder: Encoder()).toString(), "foo+1@example.com") + XCTAssertEqual(try Filters.urlDecodeFilter(value: Value("foo+bar"), args: [], kwargs: [:], context: FilterContext(encoder: Encoder())).toString(), "foo bar") + XCTAssertEqual(try Filters.urlDecodeFilter(value: Value("foo%20bar"), args: [], kwargs: [:], context: FilterContext(encoder: Encoder())).toString(), "foo bar") + XCTAssertEqual(try Filters.urlDecodeFilter(value: Value("foo%2B1%40example.com"), args: [], kwargs: [:], context: FilterContext(encoder: Encoder())).toString(), "foo+1@example.com") - XCTAssertEqual(try Filters.urlDecodeFilter(value: Value("%20"), args: [], kwargs: [:], encoder: Encoder()).toString(), " ") - XCTAssertEqual(try Filters.urlDecodeFilter(value: Value("%2"), args: [], kwargs: [:], encoder: Encoder()).toString(), "%2") - XCTAssertEqual(try Filters.urlDecodeFilter(value: Value("%"), args: [], kwargs: [:], encoder: Encoder()).toString(), "%") + XCTAssertEqual(try Filters.urlDecodeFilter(value: Value("%20"), args: [], kwargs: [:], context: FilterContext(encoder: Encoder())).toString(), " ") + XCTAssertEqual(try Filters.urlDecodeFilter(value: Value("%2"), args: [], kwargs: [:], context: FilterContext(encoder: Encoder())).toString(), "%2") + XCTAssertEqual(try Filters.urlDecodeFilter(value: Value("%"), args: [], kwargs: [:], context: FilterContext(encoder: Encoder())).toString(), "%") } func testStripHtml() { @@ -254,21 +254,21 @@ final class FilterTests: XCTestCase { var encoder = Encoder() encoder.locale = Locale(identifier: "en_US") - XCTAssertEqual(try Filters.dateFilter(value: Value("2006-05-05T10:00:00Z"), args: [Value("%B")], kwargs: [:], encoder: encoder), Value("May")) - XCTAssertEqual(try Filters.dateFilter(value: Value("2006-06-05T10:00:00Z"), args: [Value("%B")], kwargs: [:], encoder: encoder), Value("June")) - XCTAssertEqual(try Filters.dateFilter(value: Value("2006-07-05T10:00:00Z"), args: [Value("%B")], kwargs: [:], encoder: encoder), Value("July")) + XCTAssertEqual(try Filters.dateFilter(value: Value("2006-05-05T10:00:00Z"), args: [Value("%B")], kwargs: [:], context: FilterContext(encoder: encoder)), Value("May")) + XCTAssertEqual(try Filters.dateFilter(value: Value("2006-06-05T10:00:00Z"), args: [Value("%B")], kwargs: [:], context: FilterContext(encoder: encoder)), Value("June")) + XCTAssertEqual(try Filters.dateFilter(value: Value("2006-07-05T10:00:00Z"), args: [Value("%B")], kwargs: [:], context: FilterContext(encoder: encoder)), Value("July")) - XCTAssertEqual(try Filters.dateFilter(value: Value("2006-07-05T10:00:00Z"), args: [Value("")], kwargs: [:], encoder: encoder), Value("7/5/06, 10:00:00 AM")) - XCTAssertEqual(try Filters.dateFilter(value: Value("2006-07-05T10:00:00Z"), args: [Value()], kwargs: [:], encoder: encoder), Value("7/5/06, 10:00:00 AM")) + XCTAssertEqual(try Filters.dateFilter(value: Value("2006-07-05T10:00:00Z"), args: [Value("")], kwargs: [:], context: FilterContext(encoder: encoder)), Value("7/5/06, 10:00:00 AM")) + XCTAssertEqual(try Filters.dateFilter(value: Value("2006-07-05T10:00:00Z"), args: [Value()], kwargs: [:], context: FilterContext(encoder: encoder)), Value("7/5/06, 10:00:00 AM")) let yearString = "\(Calendar.autoupdatingCurrent.component(.year, from: Date()))" - XCTAssertEqual(try Filters.dateFilter(value: Value("2004-07-16T01:00:00Z"), args: [Value("%m/%d/%Y")], kwargs: [:], encoder: encoder), Value("07/16/2004")) - XCTAssertEqual(try Filters.dateFilter(value: Value("now"), args: [Value("%Y")], kwargs: [:], encoder: encoder), Value(yearString)) - XCTAssertEqual(try Filters.dateFilter(value: Value("today"), args: [Value("%Y")], kwargs: [:], encoder: encoder), Value(yearString)) - XCTAssertEqual(try Filters.dateFilter(value: Value("Today"), args: [Value("%Y")], kwargs: [:], encoder: encoder), Value(yearString)) + XCTAssertEqual(try Filters.dateFilter(value: Value("2004-07-16T01:00:00Z"), args: [Value("%m/%d/%Y")], kwargs: [:], context: FilterContext(encoder: encoder)), Value("07/16/2004")) + XCTAssertEqual(try Filters.dateFilter(value: Value("now"), args: [Value("%Y")], kwargs: [:], context: FilterContext(encoder: encoder)), Value(yearString)) + XCTAssertEqual(try Filters.dateFilter(value: Value("today"), args: [Value("%Y")], kwargs: [:], context: FilterContext(encoder: encoder)), Value(yearString)) + XCTAssertEqual(try Filters.dateFilter(value: Value("Today"), args: [Value("%Y")], kwargs: [:], context: FilterContext(encoder: encoder)), Value(yearString)) - XCTAssertEqual(try Filters.dateFilter(value: Value(1152098955), args: [Value("%m/%d/%Y")], kwargs: [:], encoder: encoder), Value("07/05/2006")) - XCTAssertEqual(try Filters.dateFilter(value: Value("1152098955"), args: [Value("%m/%d/%Y")], kwargs: [:], encoder: encoder), Value("07/05/2006")) + XCTAssertEqual(try Filters.dateFilter(value: Value(1152098955), args: [Value("%m/%d/%Y")], kwargs: [:], context: FilterContext(encoder: encoder)), Value("07/05/2006")) + XCTAssertEqual(try Filters.dateFilter(value: Value("1152098955"), args: [Value("%m/%d/%Y")], kwargs: [:], context: FilterContext(encoder: encoder)), Value("07/05/2006")) } func testFilterArgs() {