Merge pull request #182 from stencilproject/blocks-cache

Caching rendered blocks content to reuse them in further calls
This commit is contained in:
David Jennes
2022-07-28 19:07:15 +02:00
committed by GitHub
7 changed files with 51 additions and 2 deletions

View File

@@ -26,6 +26,10 @@
- Added support for adding default whitespace trimming behaviour to an environment. - Added support for adding default whitespace trimming behaviour to an environment.
[Yonas Kolb](https://github.com/yonaskolb) [Yonas Kolb](https://github.com/yonaskolb)
[#287](https://github.com/stencilproject/Stencil/pull/287) [#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 ### Deprecations

View File

@@ -85,4 +85,19 @@ public class Context {
return accumulator 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)
}
}
} }

View File

@@ -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
} }
} }

View File

@@ -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
"""
}
}
} }

View File

@@ -0,0 +1,5 @@
{% block header %}Header{% endblock %}
{% block body %}Body{% endblock %}
Repeat
{{ block.header }}
{{ block.body }}

View File

@@ -0,0 +1,3 @@
{% extends "base-repeat.html" %}
{% block header %}Super_{{ block.super }} Child_Header{% endblock %}
{% block body %}Child_Body{% endblock %}

View File

@@ -141,7 +141,7 @@ Let's take a look at an example. Here is our base template (``base.html``):
</html> </html>
This example declares three blocks, ``title``, ``sidebar`` and ``content``. We 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. and then use ``{% block %}`` to override any blocks from our base template.
A child template might look like the following: 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. extend ``base.html`` and include section-specific styles/design.
* Create individual templates for each type of page, such as a news article or * Create individual templates for each type of page, such as a news article or
blog entry. These templates extend the appropriate section template. 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.