Add 'Namespace' a container for tags and filters
This commit is contained in:
@@ -96,7 +96,7 @@ When the `ForNode` is rendered in a context, it will look up the variable `artic
|
|||||||
|
|
||||||
There are two ways to register custom template tags. A simple way which allows you to map 1:1 a block token to a Node. You can also register a more advanced template tag which has it’s own block of code for handling parsing if you want to parse up until another token such as if you are trying to provide flow-control.
|
There are two ways to register custom template tags. A simple way which allows you to map 1:1 a block token to a Node. You can also register a more advanced template tag which has it’s own block of code for handling parsing if you want to parse up until another token such as if you are trying to provide flow-control.
|
||||||
|
|
||||||
The tags are registered onto the `TokenParser` which you can access from your `Template`.
|
The tags are registered with a `Namespace` passed when rendering your `Template`.
|
||||||
|
|
||||||
#### Simple Tags
|
#### Simple Tags
|
||||||
|
|
||||||
@@ -105,7 +105,7 @@ A simple tag is registered with a string for the tag name and a block of code wh
|
|||||||
Here’s an example. Registering a template tag called `custom` which just renders `Hello World` in the rendered template:
|
Here’s an example. Registering a template tag called `custom` which just renders `Hello World` in the rendered template:
|
||||||
|
|
||||||
```swift
|
```swift
|
||||||
parser.registerSimpleTag("custom") { context in
|
namespace.registerSimpleTag("custom") { context in
|
||||||
return "Hello World"
|
return "Hello World"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -120,7 +120,7 @@ You would use it as such in a template:
|
|||||||
|
|
||||||
If you need more control or functionality than the simple tag’s above, you can use the node based API where you can provide a block of code to deal with parsing. There are a few examples of this in use over at `Node.swift` inside Stencil. There is an implementation of `if` and `for` template tags.
|
If you need more control or functionality than the simple tag’s above, you can use the node based API where you can provide a block of code to deal with parsing. There are a few examples of this in use over at `Node.swift` inside Stencil. There is an implementation of `if` and `for` template tags.
|
||||||
|
|
||||||
You would register a template tag using the `registerTag` API inside a `TokenParser` which accepts a name for the tag and a block of code to handle parsing. The block of code is invoked with the parser and the current token as an argument. This allows you to use the API on `TokenParser` to parse node’s further in the token array.
|
You would register a template tag using the `registerTag` API inside a `Namespace` which accepts a name for the tag and a block of code to handle parsing. The block of code is invoked with the parser and the current token as an argument. This allows you to use the API on `TokenParser` to parse node’s further in the token array.
|
||||||
|
|
||||||
As an example, we’re going to create a template tag called `debug` which will optionally render nodes from `debug` up until `enddebug`. When rendering the `DebugNode`, it will only render the nodes inside if a variable called `debug` is set to `true` inside the template Context.
|
As an example, we’re going to create a template tag called `debug` which will optionally render nodes from `debug` up until `enddebug`. When rendering the `DebugNode`, it will only render the nodes inside if a variable called `debug` is set to `true` inside the template Context.
|
||||||
|
|
||||||
@@ -163,7 +163,7 @@ class DebugNode : Node {
|
|||||||
We will need to write a parser to parse up until the `enddebug` template block and create a `DebugNode` with the nodes in-between. If there was another error form another Node inside, then we will return that error.
|
We will need to write a parser to parse up until the `enddebug` template block and create a `DebugNode` with the nodes in-between. If there was another error form another Node inside, then we will return that error.
|
||||||
|
|
||||||
```swift
|
```swift
|
||||||
parser.registerTag("debug") { parser, token in
|
namespace.registerTag("debug") { parser, token in
|
||||||
// Use the parser to parse every token up until the `enddebug` block.
|
// Use the parser to parse every token up until the `enddebug` block.
|
||||||
let nodes = try until(["enddebug"]))
|
let nodes = try until(["enddebug"]))
|
||||||
return DebugNode(nodes)
|
return DebugNode(nodes)
|
||||||
|
|||||||
44
README.md
44
README.md
@@ -112,18 +112,6 @@ For example, `Stencil` to `stencil`.
|
|||||||
{{ "Stencil"|lowercase }}
|
{{ "Stencil"|lowercase }}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Registering custom filters
|
|
||||||
|
|
||||||
```swift
|
|
||||||
template.parser.registerFilter("double") { value in
|
|
||||||
if let value = value as? Int {
|
|
||||||
return value * 2
|
|
||||||
}
|
|
||||||
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Tags
|
### Tags
|
||||||
|
|
||||||
Tags are a mechanism to execute a piece of code, allowing you to have
|
Tags are a mechanism to execute a piece of code, allowing you to have
|
||||||
@@ -194,13 +182,37 @@ let context = Context(dictionary: [
|
|||||||
])
|
])
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Customisation
|
||||||
|
|
||||||
|
You can build your own custom filters and tags and pass them down while
|
||||||
|
rendering your template. Any custom filters or tags must be registered
|
||||||
|
with a namespace which contains all filters and tags available to the template.
|
||||||
|
|
||||||
|
```swift
|
||||||
|
let namespace = Namespace()
|
||||||
|
// Register your filters and tags with the namespace
|
||||||
|
let rendered = try template.render(context, namespace: namespace)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Registering custom filters
|
||||||
|
|
||||||
|
```swift
|
||||||
|
namespace.registerFilter("double") { value in
|
||||||
|
if let value = value as? Int {
|
||||||
|
return value * 2
|
||||||
|
}
|
||||||
|
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
#### Building custom tags
|
#### Building custom tags
|
||||||
|
|
||||||
You can build a custom template tag. There are a couple of APIs to allow
|
You can build a custom template tag. There are a couple of APIs to allow
|
||||||
you to write your own custom tags. The following is the simplest form:
|
you to write your own custom tags. The following is the simplest form:
|
||||||
|
|
||||||
```swift
|
```swift
|
||||||
template.parser.registerSimpleTag("custom") { context in
|
namespace.registerSimpleTag("custom") { context in
|
||||||
return "Hello World"
|
return "Hello World"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -214,9 +226,8 @@ of template tags. You will need to call the `registerTag` API which accepts a
|
|||||||
closure to handle the parsing. You can find examples of the `now`, `if` and
|
closure to handle the parsing. You can find examples of the `now`, `if` and
|
||||||
`for` tags found inside `Node.swift`.
|
`for` tags found inside `Node.swift`.
|
||||||
|
|
||||||
Custom template tags must be registered prior to calling `Template.render` the first time.
|
The architecture of Stencil along with how to build advanced plugins can be
|
||||||
|
found in the [architecture](ARCHITECTURE.md) document.
|
||||||
The architecture of Stencil along with how to build advanced plugins can be found in the [architecture](ARCHITECTURE.md) document.
|
|
||||||
|
|
||||||
### Comments
|
### Comments
|
||||||
|
|
||||||
@@ -230,4 +241,3 @@ To comment out part of your template, you can use the following syntax:
|
|||||||
|
|
||||||
Stencil is licensed under the BSD license. See [LICENSE](LICENSE) for more
|
Stencil is licensed under the BSD license. See [LICENSE](LICENSE) for more
|
||||||
info.
|
info.
|
||||||
|
|
||||||
|
|||||||
44
Stencil/Namespace.swift
Normal file
44
Stencil/Namespace.swift
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
public class Namespace {
|
||||||
|
public typealias TagParser = (TokenParser, Token) throws -> NodeType
|
||||||
|
|
||||||
|
var tags = [String: TagParser]()
|
||||||
|
var filters = [String: Filter]()
|
||||||
|
|
||||||
|
public init() {
|
||||||
|
registerDefaultTags()
|
||||||
|
registerDefaultFilters()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func registerDefaultTags() {
|
||||||
|
registerTag("for", parser: ForNode.parse)
|
||||||
|
registerTag("if", parser: IfNode.parse)
|
||||||
|
registerTag("ifnot", parser: IfNode.parse_ifnot)
|
||||||
|
registerTag("now", parser: NowNode.parse)
|
||||||
|
registerTag("include", parser: IncludeNode.parse)
|
||||||
|
registerTag("extends", parser: ExtendsNode.parse)
|
||||||
|
registerTag("block", parser: BlockNode.parse)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func registerDefaultFilters() {
|
||||||
|
registerFilter("capitalize", filter: capitalise)
|
||||||
|
registerFilter("uppercase", filter: uppercase)
|
||||||
|
registerFilter("lowercase", filter: lowercase)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Registers a new template tag
|
||||||
|
public func registerTag(name: String, parser: TagParser) {
|
||||||
|
tags[name] = parser
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Registers a simple template tag with a name and a handler
|
||||||
|
public func registerSimpleTag(name: String, handler: Context throws -> String) {
|
||||||
|
registerTag(name, parser: { parser, token in
|
||||||
|
return SimpleNode(handler: handler)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Registers a template filter with the given name
|
||||||
|
public func registerFilter(name: String, filter: Filter) {
|
||||||
|
filters[name] = filter
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,37 +17,11 @@ public class TokenParser {
|
|||||||
public typealias TagParser = (TokenParser, Token) throws -> NodeType
|
public typealias TagParser = (TokenParser, Token) throws -> NodeType
|
||||||
|
|
||||||
private var tokens: [Token]
|
private var tokens: [Token]
|
||||||
private var tags = [String:TagParser]()
|
private let namespace: Namespace
|
||||||
private var filters = [String: Filter]()
|
|
||||||
|
|
||||||
public init(tokens:[Token]) {
|
public init(tokens: [Token], namespace: Namespace) {
|
||||||
self.tokens = tokens
|
self.tokens = tokens
|
||||||
registerTag("for", parser: ForNode.parse)
|
self.namespace = namespace
|
||||||
registerTag("if", parser: IfNode.parse)
|
|
||||||
registerTag("ifnot", parser: IfNode.parse_ifnot)
|
|
||||||
registerTag("now", parser: NowNode.parse)
|
|
||||||
registerTag("include", parser: IncludeNode.parse)
|
|
||||||
registerTag("extends", parser: ExtendsNode.parse)
|
|
||||||
registerTag("block", parser: BlockNode.parse)
|
|
||||||
registerFilter("capitalize", filter: capitalise)
|
|
||||||
registerFilter("uppercase", filter: uppercase)
|
|
||||||
registerFilter("lowercase", filter: lowercase)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Registers a new template tag
|
|
||||||
public func registerTag(name:String, parser:TagParser) {
|
|
||||||
tags[name] = parser
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Registers a simple template tag with a name and a handler
|
|
||||||
public func registerSimpleTag(name:String, handler:(Context throws -> String)) {
|
|
||||||
registerTag(name, parser: { parser, token in
|
|
||||||
return SimpleNode(handler: handler)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
public func registerFilter(name: String, filter: Filter) {
|
|
||||||
filters[name] = filter
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse the given tokens into nodes
|
/// Parse the given tokens into nodes
|
||||||
@@ -75,7 +49,7 @@ public class TokenParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let tag = tag {
|
if let tag = tag {
|
||||||
if let parser = self.tags[tag] {
|
if let parser = namespace.tags[tag] {
|
||||||
nodes.append(try parser(self, token))
|
nodes.append(try parser(self, token))
|
||||||
} else {
|
} else {
|
||||||
throw TemplateSyntaxError("Unknown template tag '\(tag)'")
|
throw TemplateSyntaxError("Unknown template tag '\(tag)'")
|
||||||
@@ -102,7 +76,7 @@ public class TokenParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func findFilter(name: String) throws -> Filter {
|
public func findFilter(name: String) throws -> Filter {
|
||||||
if let filter = filters[name] {
|
if let filter = namespace.filters[name] {
|
||||||
return filter
|
return filter
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,7 @@ import PathKit
|
|||||||
|
|
||||||
/// A class representing a template
|
/// A class representing a template
|
||||||
public class Template {
|
public class Template {
|
||||||
public let parser:TokenParser
|
let tokens: [Token]
|
||||||
private var nodes:[NodeType]? = nil
|
|
||||||
|
|
||||||
/// Create a template with the given name inside the given bundle
|
/// Create a template with the given name inside the given bundle
|
||||||
public convenience init(named:String, inBundle bundle:NSBundle? = nil) throws {
|
public convenience init(named:String, inBundle bundle:NSBundle? = nil) throws {
|
||||||
@@ -29,16 +28,13 @@ public class Template {
|
|||||||
/// Create a template with a template string
|
/// Create a template with a template string
|
||||||
public init(templateString:String) {
|
public init(templateString:String) {
|
||||||
let lexer = Lexer(templateString: templateString)
|
let lexer = Lexer(templateString: templateString)
|
||||||
let tokens = lexer.tokenize()
|
tokens = lexer.tokenize()
|
||||||
parser = TokenParser(tokens: tokens)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Render the given template
|
/// Render the given template
|
||||||
public func render(context:Context? = nil) throws -> String {
|
public func render(context: Context? = nil, namespace: Namespace? = nil) throws -> String {
|
||||||
if nodes == nil {
|
let parser = TokenParser(tokens: tokens, namespace: namespace ?? Namespace())
|
||||||
nodes = try parser.parse()
|
let nodes = try parser.parse()
|
||||||
}
|
return try renderNodes(nodes, context ?? Context())
|
||||||
|
|
||||||
return try renderNodes(nodes!, context ?? Context())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,9 @@ describe("template filters") {
|
|||||||
|
|
||||||
$0.it("allows you to register a custom filter") {
|
$0.it("allows you to register a custom filter") {
|
||||||
let template = Template(templateString: "{{ name|repeat }}")
|
let template = Template(templateString: "{{ name|repeat }}")
|
||||||
template.parser.registerFilter("repeat") { value in
|
|
||||||
|
let namespace = Namespace()
|
||||||
|
namespace.registerFilter("repeat") { value in
|
||||||
if let value = value as? String {
|
if let value = value as? String {
|
||||||
return "\(value) \(value)"
|
return "\(value) \(value)"
|
||||||
}
|
}
|
||||||
@@ -15,17 +17,18 @@ describe("template filters") {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = try template.render(context)
|
let result = try template.render(context, namespace: namespace)
|
||||||
try expect(result) == "Kyle Kyle"
|
try expect(result) == "Kyle Kyle"
|
||||||
}
|
}
|
||||||
|
|
||||||
$0.it("allows you to register a custom filter") {
|
$0.it("allows you to register a custom filter") {
|
||||||
let template = Template(templateString: "{{ name|repeat }}")
|
let template = Template(templateString: "{{ name|repeat }}")
|
||||||
template.parser.registerFilter("repeat") { value in
|
let namespace = Namespace()
|
||||||
|
namespace.registerFilter("repeat") { value in
|
||||||
throw TemplateSyntaxError("No Repeat")
|
throw TemplateSyntaxError("No Repeat")
|
||||||
}
|
}
|
||||||
|
|
||||||
try expect(try template.render(context)).toThrow(TemplateSyntaxError("No Repeat"))
|
try expect(try template.render(context, namespace: namespace)).toThrow(TemplateSyntaxError("No Repeat"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ describe("IfNode") {
|
|||||||
Token.Block(value: "endif")
|
Token.Block(value: "endif")
|
||||||
]
|
]
|
||||||
|
|
||||||
let parser = TokenParser(tokens: tokens)
|
let parser = TokenParser(tokens: tokens, namespace: Namespace())
|
||||||
let nodes = try parser.parse()
|
let nodes = try parser.parse()
|
||||||
let node = nodes.first as? IfNode
|
let node = nodes.first as? IfNode
|
||||||
let trueNode = node?.trueNodes.first as? TextNode
|
let trueNode = node?.trueNodes.first as? TextNode
|
||||||
@@ -35,7 +35,7 @@ describe("IfNode") {
|
|||||||
Token.Block(value: "endif")
|
Token.Block(value: "endif")
|
||||||
]
|
]
|
||||||
|
|
||||||
let parser = TokenParser(tokens: tokens)
|
let parser = TokenParser(tokens: tokens, namespace: Namespace())
|
||||||
let nodes = try parser.parse()
|
let nodes = try parser.parse()
|
||||||
let node = nodes.first as? IfNode
|
let node = nodes.first as? IfNode
|
||||||
let trueNode = node?.trueNodes.first as? TextNode
|
let trueNode = node?.trueNodes.first as? TextNode
|
||||||
@@ -54,7 +54,7 @@ describe("IfNode") {
|
|||||||
Token.Block(value: "if value"),
|
Token.Block(value: "if value"),
|
||||||
]
|
]
|
||||||
|
|
||||||
let parser = TokenParser(tokens: tokens)
|
let parser = TokenParser(tokens: tokens, namespace: Namespace())
|
||||||
let error = TemplateSyntaxError("`endif` was not found.")
|
let error = TemplateSyntaxError("`endif` was not found.")
|
||||||
try expect(try parser.parse()).toThrow(error)
|
try expect(try parser.parse()).toThrow(error)
|
||||||
}
|
}
|
||||||
@@ -64,7 +64,7 @@ describe("IfNode") {
|
|||||||
Token.Block(value: "ifnot value"),
|
Token.Block(value: "ifnot value"),
|
||||||
]
|
]
|
||||||
|
|
||||||
let parser = TokenParser(tokens: tokens)
|
let parser = TokenParser(tokens: tokens, namespace: Namespace())
|
||||||
let error = TemplateSyntaxError("`endif` was not found.")
|
let error = TemplateSyntaxError("`endif` was not found.")
|
||||||
try expect(try parser.parse()).toThrow(error)
|
try expect(try parser.parse()).toThrow(error)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ describe("NowNode") {
|
|||||||
$0.describe("parsing") {
|
$0.describe("parsing") {
|
||||||
$0.it("parses default format without any now arguments") {
|
$0.it("parses default format without any now arguments") {
|
||||||
let tokens = [ Token.Block(value: "now") ]
|
let tokens = [ Token.Block(value: "now") ]
|
||||||
let parser = TokenParser(tokens: tokens)
|
let parser = TokenParser(tokens: tokens, namespace: Namespace())
|
||||||
|
|
||||||
let nodes = try parser.parse()
|
let nodes = try parser.parse()
|
||||||
let node = nodes.first as? NowNode
|
let node = nodes.first as? NowNode
|
||||||
@@ -17,7 +17,7 @@ describe("NowNode") {
|
|||||||
|
|
||||||
$0.it("parses now with a format") {
|
$0.it("parses now with a format") {
|
||||||
let tokens = [ Token.Block(value: "now \"HH:mm\"") ]
|
let tokens = [ Token.Block(value: "now \"HH:mm\"") ]
|
||||||
let parser = TokenParser(tokens: tokens)
|
let parser = TokenParser(tokens: tokens, namespace: Namespace())
|
||||||
let nodes = try parser.parse()
|
let nodes = try parser.parse()
|
||||||
let node = nodes.first as? NowNode
|
let node = nodes.first as? NowNode
|
||||||
try expect(nodes.count) == 1
|
try expect(nodes.count) == 1
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ describe("TokenParser") {
|
|||||||
$0.it("can parse a text token") {
|
$0.it("can parse a text token") {
|
||||||
let parser = TokenParser(tokens: [
|
let parser = TokenParser(tokens: [
|
||||||
Token.Text(value: "Hello World")
|
Token.Text(value: "Hello World")
|
||||||
])
|
], namespace: Namespace())
|
||||||
|
|
||||||
let nodes = try parser.parse()
|
let nodes = try parser.parse()
|
||||||
let node = nodes.first as? TextNode
|
let node = nodes.first as? TextNode
|
||||||
@@ -18,7 +18,7 @@ describe("TokenParser") {
|
|||||||
$0.it("can parse a variable token") {
|
$0.it("can parse a variable token") {
|
||||||
let parser = TokenParser(tokens: [
|
let parser = TokenParser(tokens: [
|
||||||
Token.Variable(value: "'name'")
|
Token.Variable(value: "'name'")
|
||||||
])
|
], namespace: Namespace())
|
||||||
|
|
||||||
let nodes = try parser.parse()
|
let nodes = try parser.parse()
|
||||||
let node = nodes.first as? VariableNode
|
let node = nodes.first as? VariableNode
|
||||||
@@ -30,7 +30,7 @@ describe("TokenParser") {
|
|||||||
$0.it("can parse a comment token") {
|
$0.it("can parse a comment token") {
|
||||||
let parser = TokenParser(tokens: [
|
let parser = TokenParser(tokens: [
|
||||||
Token.Comment(value: "Secret stuff!")
|
Token.Comment(value: "Secret stuff!")
|
||||||
])
|
], namespace: Namespace())
|
||||||
|
|
||||||
let nodes = try parser.parse()
|
let nodes = try parser.parse()
|
||||||
try expect(nodes.count) == 0
|
try expect(nodes.count) == 0
|
||||||
@@ -39,7 +39,7 @@ describe("TokenParser") {
|
|||||||
$0.it("can parse a tag token") {
|
$0.it("can parse a tag token") {
|
||||||
let parser = TokenParser(tokens: [
|
let parser = TokenParser(tokens: [
|
||||||
Token.Block(value: "now"),
|
Token.Block(value: "now"),
|
||||||
])
|
], namespace: Namespace())
|
||||||
|
|
||||||
let nodes = try parser.parse()
|
let nodes = try parser.parse()
|
||||||
try expect(nodes.count) == 1
|
try expect(nodes.count) == 1
|
||||||
@@ -48,7 +48,7 @@ describe("TokenParser") {
|
|||||||
$0.it("errors when parsing an unknown tag") {
|
$0.it("errors when parsing an unknown tag") {
|
||||||
let parser = TokenParser(tokens: [
|
let parser = TokenParser(tokens: [
|
||||||
Token.Block(value: "unknown"),
|
Token.Block(value: "unknown"),
|
||||||
])
|
], namespace: Namespace())
|
||||||
|
|
||||||
try expect(try parser.parse()).toThrow(TemplateSyntaxError("Unknown template tag 'unknown'"))
|
try expect(try parser.parse()).toThrow(TemplateSyntaxError("Unknown template tag 'unknown'"))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,11 +40,12 @@ describe("Stencil") {
|
|||||||
let templateString = "{% custom %}"
|
let templateString = "{% custom %}"
|
||||||
let template = Template(templateString: templateString)
|
let template = Template(templateString: templateString)
|
||||||
|
|
||||||
template.parser.registerTag("custom") { parser, token in
|
let namespace = Namespace()
|
||||||
|
namespace.registerTag("custom") { parser, token in
|
||||||
return CustomNode()
|
return CustomNode()
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = try template.render()
|
let result = try template.render(namespace: namespace)
|
||||||
try expect(result) == "Hello World"
|
try expect(result) == "Hello World"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,10 +53,11 @@ describe("Stencil") {
|
|||||||
let templateString = "{% custom %}"
|
let templateString = "{% custom %}"
|
||||||
let template = Template(templateString: templateString)
|
let template = Template(templateString: templateString)
|
||||||
|
|
||||||
template.parser.registerSimpleTag("custom") { context in
|
let namespace = Namespace()
|
||||||
|
namespace.registerSimpleTag("custom") { context in
|
||||||
return "Hello World"
|
return "Hello World"
|
||||||
}
|
}
|
||||||
|
|
||||||
try expect(try template.render()) == "Hello World"
|
try expect(try template.render(namespace: namespace)) == "Hello World"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ describe("Include") {
|
|||||||
$0.describe("parsing") {
|
$0.describe("parsing") {
|
||||||
$0.it("throws an error when no template is given") {
|
$0.it("throws an error when no template is given") {
|
||||||
let tokens = [ Token.Block(value: "include") ]
|
let tokens = [ Token.Block(value: "include") ]
|
||||||
let parser = TokenParser(tokens: tokens)
|
let parser = TokenParser(tokens: tokens, namespace: Namespace())
|
||||||
|
|
||||||
let error = TemplateSyntaxError("'include' tag takes one argument, the template file to be included")
|
let error = TemplateSyntaxError("'include' tag takes one argument, the template file to be included")
|
||||||
try expect(try parser.parse()).toThrow(error)
|
try expect(try parser.parse()).toThrow(error)
|
||||||
@@ -18,7 +18,7 @@ describe("Include") {
|
|||||||
|
|
||||||
$0.it("can parse a valid include block") {
|
$0.it("can parse a valid include block") {
|
||||||
let tokens = [ Token.Block(value: "include \"test.html\"") ]
|
let tokens = [ Token.Block(value: "include \"test.html\"") ]
|
||||||
let parser = TokenParser(tokens: tokens)
|
let parser = TokenParser(tokens: tokens, namespace: Namespace())
|
||||||
|
|
||||||
let nodes = try parser.parse()
|
let nodes = try parser.parse()
|
||||||
let node = nodes.first as? IncludeNode
|
let node = nodes.first as? IncludeNode
|
||||||
|
|||||||
Reference in New Issue
Block a user