feat(filter): Support filter tag
This commit is contained in:
@@ -13,6 +13,15 @@
|
|||||||
path. Any template names that try to escape the base path will raise a
|
path. Any template names that try to escape the base path will raise a
|
||||||
`SuspiciousFileOperation` error.
|
`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
|
## 0.7.1
|
||||||
|
|
||||||
|
|||||||
35
Sources/FilterTag.swift
Normal file
35
Sources/FilterTag.swift
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -42,6 +42,7 @@ public class Namespace {
|
|||||||
registerTag("include", parser: IncludeNode.parse)
|
registerTag("include", parser: IncludeNode.parse)
|
||||||
registerTag("extends", parser: ExtendsNode.parse)
|
registerTag("extends", parser: ExtendsNode.parse)
|
||||||
registerTag("block", parser: BlockNode.parse)
|
registerTag("block", parser: BlockNode.parse)
|
||||||
|
registerTag("filter", parser: FilterNode.parse)
|
||||||
}
|
}
|
||||||
|
|
||||||
fileprivate func registerDefaultFilters() {
|
fileprivate func registerDefaultFilters() {
|
||||||
|
|||||||
25
Tests/StencilTests/FilterTagSpec.swift
Normal file
25
Tests/StencilTests/FilterTagSpec.swift
Normal 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()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,6 +17,7 @@ public func stencilTests() {
|
|||||||
testNowNode()
|
testNowNode()
|
||||||
testInclude()
|
testInclude()
|
||||||
testInheritence()
|
testInheritence()
|
||||||
|
testFilterTag()
|
||||||
testStencil()
|
testStencil()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -177,6 +177,26 @@ Will be treated as:
|
|||||||
``now``
|
``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``
|
``include``
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user