fix(extends): Support multiple extends

Fixes #60
This commit is contained in:
Kyle Fuller
2016-11-27 04:22:37 +00:00
parent a014fecd23
commit 393dc88a10
4 changed files with 30 additions and 8 deletions

View File

@@ -19,6 +19,9 @@
index will now resolve to `nil` instead of causing a crash. index will now resolve to `nil` instead of causing a crash.
[#72](https://github.com/kylef/Stencil/issues/72) [#72](https://github.com/kylef/Stencil/issues/72)
- Templates can now extend templates that extend other templates.
[#60](https://github.com/kylef/Stencil/issues/60)
## 0.6.0 ## 0.6.0

View File

@@ -42,10 +42,9 @@ class ExtendsNode : NodeType {
throw TemplateSyntaxError("'extends' cannot appear more than once in the same template") throw TemplateSyntaxError("'extends' cannot appear more than once in the same template")
} }
let blockNodes = parsedNodes.filter { node in node is BlockNode } let blockNodes = parsedNodes.flatMap { $0 as? BlockNode }
let nodes = blockNodes.reduce([String:BlockNode]()) { (accumulator, node:NodeType) -> [String:BlockNode] in let nodes = blockNodes.reduce([String: BlockNode]()) { (accumulator, node) -> [String: BlockNode] in
let node = (node as! BlockNode)
var dict = accumulator var dict = accumulator
dict[node.name] = node dict[node.name] = node
return dict return dict
@@ -73,7 +72,19 @@ class ExtendsNode : NodeType {
throw TemplateSyntaxError("'\(templateName)' template not found in \(paths)") throw TemplateSyntaxError("'\(templateName)' template not found in \(paths)")
} }
let blockContext = BlockContext(blocks: blocks) let blockContext: BlockContext
if let context = context[BlockContext.contextKey] as? BlockContext {
blockContext = context
for (key, value) in blocks {
if !blockContext.blocks.keys.contains(key) {
blockContext.blocks[key] = value
}
}
} else {
blockContext = BlockContext(blocks: blocks)
}
return try context.push(dictionary: [BlockContext.contextKey: blockContext]) { return try context.push(dictionary: [BlockContext.contextKey: blockContext]) {
return try template.render(context) return try template.render(context)
} }
@@ -89,7 +100,7 @@ class BlockNode : NodeType {
let bits = token.components() let bits = token.components()
guard bits.count == 2 else { guard bits.count == 2 else {
throw TemplateSyntaxError("'block' tag takes one argument, the template file to be included") throw TemplateSyntaxError("'block' tag takes one argument, the block name")
} }
let blockName = bits[1] let blockName = bits[1]

View File

@@ -13,5 +13,11 @@ func testInheritence() {
let template = loader.loadTemplate("child.html") let template = loader.loadTemplate("child.html")
try expect(try template?.render(context)) == "Header\nChild" try expect(try template?.render(context)) == "Header\nChild"
} }
$0.it("can inherit from another template inheriting from another template") {
let context = Context(dictionary: ["loader": loader])
let template = loader.loadTemplate("child-child.html")
try expect(try template?.render(context)) == "Child Child Header\nChild"
}
} }
} }

View File

@@ -0,0 +1,2 @@
{% extends "child.html" %}
{% block header %}Child Child Header{% endblock %}