Skip to content
This repository has been archived by the owner on Aug 4, 2022. It is now read-only.

Commit

Permalink
Merge pull request #11 from g-Off/t-filter
Browse files Browse the repository at this point in the history
Implemented t filter
  • Loading branch information
katbutler authored Nov 20, 2019
2 parents 139ae54 + 70ebbcd commit 954bc7a
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 6 deletions.
4 changes: 3 additions & 1 deletion Sources/Liquid/Context.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,19 @@ public final class Context {
private var registers: [String: Any] = [:]

public let filters: [String: FilterFunc]
public let translations: [String: String]?
public let tags: [String: TagBuilder]
public let environment: Environment
public let encoder: Encoder
public let fileSystem: FileSystem

init(fileSystem: FileSystem, values: [String: Value] = [:], environment: Environment = Environment(), tags: [String: TagBuilder], filters: [String: FilterFunc] = [:], encoder: Encoder) {
init(fileSystem: FileSystem, values: [String: Value] = [:], environment: Environment = Environment(), tags: [String: TagBuilder], filters: [String: FilterFunc] = [:], translations: [String: String]? = nil, encoder: Encoder) {
self.fileSystem = fileSystem
self.scopes = [Scope(values: values)]
self.environment = environment
self.tags = tags
self.filters = filters
self.translations = translations
self.encoder = encoder
}

Expand Down
45 changes: 45 additions & 0 deletions Sources/Liquid/Filter+Standard.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ enum Filters {
template.registerFilter(name: "sort", filter: sortFilter)
template.registerFilter(name: "sort_natural", filter: sortNaturalFilter)
template.registerFilter(name: "date", filter: dateFilter)
template.registerFilter(name: "t", filter: tFilter)
}

static func appendFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value {
Expand Down Expand Up @@ -512,6 +513,25 @@ enum Filters {
}
return Value(formatter.string(from: date))
}

static func tFilter(value: Value, args: [Value], kwargs: [String: Value], context: FilterContext) throws -> Value {
guard let translations = context.translations else {
throw RuntimeError.reason("No translations dictionary available")
}

guard let val = translations[value.toString()] else {
throw RuntimeError.reason("Invalid translation key")
}

if kwargs.isEmpty && args.isEmpty {
return Value(val)
}
if !kwargs.isEmpty {
return Value(val.replaceWithValues(kwargs))
}

throw RuntimeError.unimplemented
}

private static func convertValueToDate(_ value: Value, context: FilterContext) -> Date? {
if value.isInteger {
Expand All @@ -530,3 +550,28 @@ enum Filters {
return context.encoder.dateEncodingStrategry.date(from: string)
}
}

private extension String {
func replaceWithValues(_ values: [String: Value]) -> String {
let scanner = Scanner(string: self)
scanner.charactersToBeSkipped = CharacterSet.newlines

var result: String = ""
var temp: NSString?

while !scanner.isAtEnd {
scanner.scanUpTo("%{", into: &temp)
scanner.scanCharacters(from: CharacterSet.init(charactersIn: "%{"), into: nil)

result = "\(result)\(temp ?? "")"

scanner.scanUpTo("}", into: &temp)
scanner.scanCharacters(from: CharacterSet.init(charactersIn: "}"), into: nil)

let resultValue = values[String(temp ?? "")]?.toString() ?? ""
result = "\(result)\(resultValue)"
}

return result
}
}
6 changes: 4 additions & 2 deletions Sources/Liquid/FilterContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ import Foundation

public struct FilterContext {
public let encoder: Encoder
public let translations: [String: String]?

init(context: Context) {
self.init(encoder: context.encoder)
self.init(encoder: context.encoder, translations: context.translations)
}

init(encoder: Encoder) {
init(encoder: Encoder, translations: [String: String]? = nil) {
self.encoder = encoder
self.translations = translations
}
}
10 changes: 7 additions & 3 deletions Sources/Liquid/Template.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ public final class Template {

private let fileSystem: FileSystem

public convenience init(sourceURL: URL, encoder: Encoder = Encoder(), environment: Environment = Environment()) throws {
private let translations: [String: String]?

public convenience init(sourceURL: URL, encoder: Encoder = Encoder(), environment: Environment = Environment(), translations: [String: String]? = nil) throws {
let source = try String(contentsOf: sourceURL)
let fileSystem = LocalFileSystem(baseURL: sourceURL.deletingLastPathComponent())
self.init(source: source, fileSystem: fileSystem, encoder: encoder, environment: environment)
Expand All @@ -43,13 +45,15 @@ public final class Template {
self.environment = context.environment
self.fileSystem = context.fileSystem
self.filters = context.filters
self.translations = context.translations
self.tags = context.tags
}

private init(source: String, fileSystem: FileSystem, encoder: Encoder, environment: Environment) {
private init(source: String, fileSystem: FileSystem, encoder: Encoder, environment: Environment, translations: [String: String]? = nil) {
self.source = source
self.fileSystem = fileSystem
self.environment = environment
self.translations = translations
self.encoder = encoder

tags["assign"] = Assign.init
Expand Down Expand Up @@ -88,7 +92,7 @@ public final class Template {
}

public func render(values: [String: Value] = [:]) throws -> String {
let context = Context(fileSystem: fileSystem, values: values, environment: environment, tags: tags, filters: filters, encoder: encoder)
let context = Context(fileSystem: fileSystem, values: values, environment: environment, tags: tags, filters: filters, translations: translations, encoder: encoder)
return try render(context: context)
}

Expand Down
15 changes: 15 additions & 0 deletions Tests/LiquidTests/FilterTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,21 @@ final class FilterTests: XCTestCase {
XCTAssertEqual(try Filters.dateFilter(value: Value("1152098955"), args: [Value("%m/%d/%Y")], kwargs: [:], context: FilterContext(encoder: encoder)), Value("07/05/2006"))
}

func testTranslate() {
var encoder = Encoder()
encoder.locale = Locale(identifier: "en_US")

let sampleTranslationDict: [String: String] = [
"x.files.main.characters": "%{argA} and %{argB}",
"x.files.title": "The X-Files",
]

let filterContext = FilterContext(encoder: encoder, translations: sampleTranslationDict)

XCTAssertEqual(try Filters.tFilter(value: Value("x.files.title"), args: [], kwargs: [:], context: filterContext), Value("The X-Files"))
XCTAssertEqual(try Filters.tFilter(value: Value("x.files.main.characters"), args: [], kwargs: ["argA": Value("Fox Mulder"), "argB": Value("Dana Scully")], context: filterContext), Value("Fox Mulder and Dana Scully"))
}

func testFilterArgs() {
let echoFilter: FilterFunc = { (value, args, kwargs, encoder) -> Value in
let strArgs = args.map { "\($0)" }.sorted()
Expand Down

0 comments on commit 954bc7a

Please sign in to comment.