Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed block inheritance with several levels #154

Merged
merged 2 commits into from
Nov 30, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Stencil Changelog

## Master

- Fixed rendering `{{ block.super }}` with several levels of inheritance

## 0.10.1

### Enhancements
Expand Down
35 changes: 28 additions & 7 deletions Sources/Inheritence.swift
Original file line number Diff line number Diff line change
@@ -1,14 +1,33 @@
class BlockContext {
class var contextKey: String { return "block_context" }

var blocks: [String: BlockNode]
var blocks: [String: [BlockNode]]

init(blocks: [String: BlockNode]) {
self.blocks = blocks
self.blocks = blocks.mapValues({ [$0] })
}

func push(_ block: BlockNode, forKey blockName: String) {
if var blocks = blocks[blockName] {
blocks.append(block)
self.blocks[blockName] = blocks
} else {
self.blocks[blockName] = [block]
}
}

func pop(_ blockName: String) -> BlockNode? {
return blocks.removeValue(forKey: blockName)
if var blocks = blocks[blockName] {
let block = blocks.removeFirst()
if blocks.isEmpty {
self.blocks.removeValue(forKey: blockName)
} else {
self.blocks[blockName] = blocks
}
return block
} else {
return nil
}
}
}

Expand Down Expand Up @@ -70,9 +89,7 @@ class ExtendsNode : NodeType {
blockContext = context

for (key, value) in blocks {
if !blockContext.blocks.keys.contains(key) {
blockContext.blocks[key] = value
}
blockContext.push(value, forKey: key)
}
} else {
blockContext = BlockContext(blocks: blocks)
Expand Down Expand Up @@ -109,7 +126,11 @@ class BlockNode : NodeType {

func render(_ context: Context) throws -> String {
if let blockContext = context[BlockContext.contextKey] as? BlockContext, let node = blockContext.pop(name) {
return try context.push(dictionary: ["block": ["super": self]]) {
let newContext: [String: Any] = [
BlockContext.contextKey: blockContext,
"block": ["super": try self.render(context)]
]
return try context.push(dictionary: newContext) {
return try node.render(context)
}
}
Expand Down
6 changes: 3 additions & 3 deletions Tests/StencilTests/InheritenceSpec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,17 @@ func testInheritence() {

$0.it("can inherit from another template") {
let template = try environment.loadTemplate(name: "child.html")
try expect(try template.render()) == "Header\nChild"
try expect(try template.render()) == "Super_Header Child_Header\nChild_Body"
}

$0.it("can inherit from another template inheriting from another template") {
let template = try environment.loadTemplate(name: "child-child.html")
try expect(try template.render()) == "Child Child Header\nChild"
try expect(try template.render()) == "Super_Header Child_Header Child_Child_Header\nChild_Body"
}

$0.it("can inherit from a template that calls a super block") {
let template = try environment.loadTemplate(name: "child-super.html")
try expect(try template.render()) == "Header\nChild Body"
try expect(try template.render()) == "Header\nChild_Body"
}
}
}
2 changes: 1 addition & 1 deletion Tests/StencilTests/fixtures/child-child.html
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
{% extends "child.html" %}
{% block header %}Child Child Header{% endblock %}
{% block header %}{{ block.super }} Child_Child_Header{% endblock %}
2 changes: 1 addition & 1 deletion Tests/StencilTests/fixtures/child-super.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{% extends "base.html" %}
{% block body %}Child {{ block.super }}{% endblock %}
{% block body %}Child_{{ block.super }}{% endblock %}

3 changes: 2 additions & 1 deletion Tests/StencilTests/fixtures/child.html
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
{% extends "base.html" %}
{% block body %}Child{% endblock %}
{% block header %}Super_{{ block.super }} Child_Header{% endblock %}
{% block body %}Child_Body{% endblock %}