feat(filter): Support filter tag

This commit is contained in:
Kyle Fuller
2016-11-30 18:44:44 +00:00
parent 2ebb79df8b
commit 2be672c6a5
6 changed files with 91 additions and 0 deletions

View File

@@ -13,6 +13,15 @@
path. Any template names that try to escape the base path will raise a
`SuspiciousFileOperation` error.
- New `{% filter %}` tag allowing you to perform a filter across the contents
of a block.
```html+django
{% filter lowercase %}
This Text Will Be Lowercased.
{% endfilter %}
```
## 0.7.1

35
Sources/FilterTag.swift Normal file
View File

@@ -0,0 +1,35 @@
class FilterNode : NodeType {
let resolvable: Resolvable
let nodes: [NodeType]
class func parse(_ parser: TokenParser, token: Token) throws -> NodeType {
let bits = token.components()
guard bits.count == 2 else {
throw TemplateSyntaxError("'filter' tag takes one argument, the filter expression")
}
let blocks = try parser.parse(until(["endfilter"]))
guard let token = parser.nextToken() else {
throw TemplateSyntaxError("`endfilter` was not found.")
}
let resolvable = try parser.compileFilter("filter_value|\(bits[1])")
return FilterNode(nodes: blocks, resolvable: resolvable)
}
init(nodes: [NodeType], resolvable: Resolvable) {
self.nodes = nodes
self.resolvable = resolvable
}
func render(_ context: Context) throws -> String {
let value = try renderNodes(nodes, context)
return try context.push(dictionary: ["filter_value": value]) {
return try VariableNode(variable: resolvable).render(context)
}
}
}

View File

@@ -42,6 +42,7 @@ public class Namespace {
registerTag("include", parser: IncludeNode.parse)
registerTag("extends", parser: ExtendsNode.parse)
registerTag("block", parser: BlockNode.parse)
registerTag("filter", parser: FilterNode.parse)
}
fileprivate func registerDefaultFilters() {

View File

@@ -0,0 +1,25 @@
import Spectre
import Stencil
func testFilterTag() {
describe("Filter Tag") {
$0.it("allows you to use a filter") {
let template = Template(templateString: "{% filter uppercase %}Test{% endfilter %}")
let result = try template.render()
try expect(result) == "TEST"
}
$0.it("allows you to chain filters") {
let template = Template(templateString: "{% filter lowercase|capitalize %}TEST{% endfilter %}")
let result = try template.render()
try expect(result) == "Test"
}
$0.it("errors without a filter") {
let template = Template(templateString: "{% filter %}Test{% endfilter %}")
try expect(try template.render()).toThrow()
}
}
}

View File

@@ -17,6 +17,7 @@ public func stencilTests() {
testNowNode()
testInclude()
testInheritence()
testFilterTag()
testStencil()
}

View File

@@ -177,6 +177,26 @@ Will be treated as:
``now``
~~~~~~~
``filter``
~~~~~~~~~~
Filters the contents of the block.
.. code-block:: html+django
{% filter lowercase %}
This Text Will Be Lowercased.
{% endfilter %}
You can chain multiple filters with a pipe (`|`).
.. code-block:: html+django
{% filter lowercase|capitalize %}
This Text Will First Be Lowercased, Then The First Character Will BE
Capitalised.
{% endfilter %}
``include``
~~~~~~~~~~~