diff --git a/CHANGELOG.md b/CHANGELOG.md index 02fb49b..9ce06c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,9 @@ - You can now use parentheses in boolean expressions to change operator precedence. [Ilya Puchka](https://github.com/ilyapuchka) [#165](https://github.com/stencilproject/Stencil/pull/165) +- Added method to add boolean filters with their negative counterparts. + [Ilya Puchka](https://github.com/ilyapuchka) + [#160](https://github.com/stencilproject/Stencil/pull/160) ### New Features diff --git a/Sources/Extension.swift b/Sources/Extension.swift index 1203378..d2ee907 100644 --- a/Sources/Extension.swift +++ b/Sources/Extension.swift @@ -18,6 +18,15 @@ open class Extension { return SimpleNode(token: token, handler: handler) }) } + + /// Registers boolean filter with it's negative counterpart + public func registerFilter(name: String, negativeFilterName: String, filter: @escaping (Any?) throws -> Bool?) { + filters[name] = .simple(filter) + filters[negativeFilterName] = .simple { + guard let result = try filter($0) else { return nil } + return !result + } + } /// Registers a template filter with the given name public func registerFilter(_ name: String, filter: @escaping (Any?) throws -> Any?) { diff --git a/Tests/StencilTests/FilterSpec.swift b/Tests/StencilTests/FilterSpec.swift index 9e4a58a..35f20e5 100644 --- a/Tests/StencilTests/FilterSpec.swift +++ b/Tests/StencilTests/FilterSpec.swift @@ -22,6 +22,24 @@ class FilterTests: XCTestCase { let result = try template.render(Context(dictionary: context, environment: Environment(extensions: [repeatExtension]))) try expect(result) == "Kyle Kyle" } + + $0.it("allows you to register boolean filters") { + let repeatExtension = Extension() + repeatExtension.registerFilter(name: "isPositive", negativeFilterName: "isNotPositive") { (value: Any?) in + if let value = value as? Int { + return value > 0 + } + return nil + } + + let result = try Template(templateString: "{{ value|isPositive }}") + .render(Context(dictionary: ["value": 1], environment: Environment(extensions: [repeatExtension]))) + try expect(result) == "true" + + let negativeResult = try Template(templateString: "{{ value|isNotPositive }}") + .render(Context(dictionary: ["value": -1], environment: Environment(extensions: [repeatExtension]))) + try expect(negativeResult) == "true" + } $0.it("allows you to register a custom filter which accepts single argument") { let template = Template(templateString: """ diff --git a/docs/custom-template-tags-and-filters.rst b/docs/custom-template-tags-and-filters.rst index 2ec7e5a..7ce4756 100644 --- a/docs/custom-template-tags-and-filters.rst +++ b/docs/custom-template-tags-and-filters.rst @@ -48,6 +48,17 @@ Registering custom filters with arguments: return value } +Registering custom boolean filters: + +.. code-block:: swift + + ext.registerFilter("ordinary", negativeFilterName: "odd") { (value: Any?) in + if let value = value as? Int { + return myInt % 2 == 0 + } + return nil + } + Custom Tags -----------