Merge pull request #182 from stencilproject/blocks-cache
Caching rendered blocks content to reuse them in further calls
This commit is contained in:
@@ -26,6 +26,10 @@
|
||||
- Added support for adding default whitespace trimming behaviour to an environment.
|
||||
[Yonas Kolb](https://github.com/yonaskolb)
|
||||
[#287](https://github.com/stencilproject/Stencil/pull/287)
|
||||
- Blocks now can be used repeatedly in the template. When block is rendered for the first time its content will be cached and it can be rendered again later using `{{ block.block_name }}`.
|
||||
[Ilya Puchka](https://github.com/ilyapuchka)
|
||||
[#158](https://github.com/stencilproject/Stencil/issues/158)
|
||||
[#182](https://github.com/stencilproject/Stencil/pull/182)
|
||||
|
||||
### Deprecations
|
||||
|
||||
|
||||
@@ -85,4 +85,19 @@ public class Context {
|
||||
|
||||
return accumulator
|
||||
}
|
||||
|
||||
/// Cache result of block by its name in the context top-level, so that it can be later rendered
|
||||
/// via `{{ block.name }}`
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - name: The name of the stored block
|
||||
/// - content: The block's rendered content
|
||||
public func cacheBlock(_ name: String, content: String) {
|
||||
if var block = dictionaries.first?["block"] as? [String: String] {
|
||||
block[name] = content
|
||||
dictionaries[0]["block"] = block
|
||||
} else {
|
||||
dictionaries.insert(["block": [name: content]], at: 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,6 +151,8 @@ class BlockNode: NodeType {
|
||||
}
|
||||
}
|
||||
|
||||
return try renderNodes(nodes, context)
|
||||
let result = try renderNodes(nodes, context)
|
||||
context.cacheBlock(name, content: result)
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,4 +52,22 @@ final class InheritanceTests: XCTestCase {
|
||||
"""
|
||||
}
|
||||
}
|
||||
|
||||
func testInheritanceCache() {
|
||||
it("can call block twice") {
|
||||
let template: Template = "{% block repeat %}Block{% endblock %}{{ block.repeat }}"
|
||||
try expect(try template.render()) == "BlockBlock"
|
||||
}
|
||||
|
||||
it("renders child content when calling block twice in base template") {
|
||||
let template = try self.environment.loadTemplate(name: "child-repeat.html")
|
||||
try expect(try template.render()) == """
|
||||
Super_Header Child_Header
|
||||
Child_Body
|
||||
Repeat
|
||||
Super_Header Child_Header
|
||||
Child_Body
|
||||
"""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
5
Tests/StencilTests/fixtures/base-repeat.html
Normal file
5
Tests/StencilTests/fixtures/base-repeat.html
Normal file
@@ -0,0 +1,5 @@
|
||||
{% block header %}Header{% endblock %}
|
||||
{% block body %}Body{% endblock %}
|
||||
Repeat
|
||||
{{ block.header }}
|
||||
{{ block.body }}
|
||||
3
Tests/StencilTests/fixtures/child-repeat.html
Normal file
3
Tests/StencilTests/fixtures/child-repeat.html
Normal file
@@ -0,0 +1,3 @@
|
||||
{% extends "base-repeat.html" %}
|
||||
{% block header %}Super_{{ block.super }} Child_Header{% endblock %}
|
||||
{% block body %}Child_Body{% endblock %}
|
||||
@@ -141,7 +141,7 @@ Let's take a look at an example. Here is our base template (``base.html``):
|
||||
</html>
|
||||
|
||||
This example declares three blocks, ``title``, ``sidebar`` and ``content``. We
|
||||
can use the ``{% extends %}`` template tag to inherit from out base template
|
||||
can use the ``{% extends %}`` template tag to inherit from our base template
|
||||
and then use ``{% block %}`` to override any blocks from our base template.
|
||||
|
||||
A child template might look like the following:
|
||||
@@ -195,3 +195,5 @@ inheritance is the following three-level approach:
|
||||
extend ``base.html`` and include section-specific styles/design.
|
||||
* Create individual templates for each type of page, such as a news article or
|
||||
blog entry. These templates extend the appropriate section template.
|
||||
|
||||
You can render block's content more than once by using ``{{ block.name }}`` **after** a block is defined.
|
||||
|
||||
Reference in New Issue
Block a user