diff --git a/CHANGELOG.md b/CHANGELOG.md index c023f215..5e3ec328 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ their stored properties. - Allow default string filters to be applied to arrays - Similar filters are suggested when unknown filter is used -- Added `indent`, `split`, `map`, `compact` and `filter` filters +- Added `indent`, `split`, `map`, `compact`, `filterEach` and `filter` filters ### Bug Fixes diff --git a/Sources/Extension.swift b/Sources/Extension.swift index 711d50f1..7d5626b6 100644 --- a/Sources/Extension.swift +++ b/Sources/Extension.swift @@ -65,6 +65,7 @@ class DefaultExtension: Extension { registerFilter("indent", filter: indentFilter) registerFilter("map", filter: mapFilter) registerFilter("compact", filter: compactFilter) + registerFilter("filterEach", filter: filterEachFilter) registerFilter("filter", filter: filterFilter) } } diff --git a/Sources/Filters.swift b/Sources/Filters.swift index 7ff33f41..59541909 100644 --- a/Sources/Filters.swift +++ b/Sources/Filters.swift @@ -156,9 +156,9 @@ func compactFilter(value: Any?, arguments: [Any?], context: Context) throws -> A }) } -func filterFilter(value: Any?, arguments: [Any?], context: Context) throws -> Any? { +func filterEachFilter(value: Any?, arguments: [Any?], context: Context) throws -> Any? { guard arguments.count == 1 else { - throw TemplateSyntaxError("'filter' filter takes one argument") + throw TemplateSyntaxError("'filterEach' filter takes one argument") } let attribute = stringify(arguments[0]) @@ -176,3 +176,18 @@ func filterFilter(value: Any?, arguments: [Any?], context: Context) throws -> An return value } +func filterFilter(value: Any?, arguments: [Any?], context: Context) throws -> Any? { + guard let value = value else { return nil } + guard arguments.count == 1 else { + throw TemplateSyntaxError("'filter' filter takes one argument") + } + + let attribute = stringify(arguments[0]) + let parser = TokenParser(tokens: [], environment: context.environment) + + let expr = try parser.compileFilter("$0|\(attribute)") + return try context.push(dictionary: ["$0": value]) { + try expr.resolve(context) + } +} + diff --git a/Tests/StencilTests/FilterSpec.swift b/Tests/StencilTests/FilterSpec.swift index 4156ded9..59e3f607 100644 --- a/Tests/StencilTests/FilterSpec.swift +++ b/Tests/StencilTests/FilterSpec.swift @@ -316,7 +316,7 @@ func testFilter() { } - describe("filter filter") { + describe("filterEach filter") { $0.it("can filter using filter") { let env = environmentWithFilter("isPositive") { (value) -> Any? in @@ -324,16 +324,32 @@ func testFilter() { else { return nil } } - let template = Template(templateString: "{{ array|filter:'$0|isPositive' }}") + let template = Template(templateString: "{{ array|filterEach:'$0|isPositive' }}") let result = try template.render(Context(dictionary: ["array": [1, -1, 2, -2, 3, -3]], environment: env)) try expect(result) == "[1, 2, 3]" } $0.it("can filter using boolean expression") { - let template = Template(templateString: "{{ array|filter:'$0 > 0' }}") + let template = Template(templateString: "{{ array|filterEach:'$0 > 0' }}") let result = try template.render(Context(dictionary: ["array": [1, -1, 2, -2, 3, -3]])) try expect(result) == "[1, 2, 3]" } } + + describe("filter filter") { + + $0.it("can apply dynamic filter") { + let template = Template(templateString: "{{ name|filter:somefilter }}") + let result = try template.render(Context(dictionary: ["name": "Jhon", "somefilter": "uppercase"])) + try expect(result) == "JHON" + } + + $0.it("can apply dynamic filter on array") { + let template = Template(templateString: "{{ values|filter:joinfilter }}") + let result = try template.render(Context(dictionary: ["values": [1, 2, 3], "joinfilter": "join:\", \""])) + try expect(result) == "1, 2, 3" + } + + } }