render-engine 2025.10.1a1__tar.gz → 2025.10.1a2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/PKG-INFO +1 -1
  2. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/docs/docs/page.md +14 -13
  3. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine/page.py +32 -11
  4. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine.egg-info/PKG-INFO +1 -1
  5. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/tests/test_page.py +69 -0
  6. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/.all-contributorsrc +0 -0
  7. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/.devcontainer/Dockerfile +0 -0
  8. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/.devcontainer/devcontainer.json +0 -0
  9. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/.devcontainer/setup.sh +0 -0
  10. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/.github/FUNDING.yml +0 -0
  11. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/.github/ISSUE_TEMPLATE/config.yaml +0 -0
  12. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/.github/ISSUE_TEMPLATE/form_issue_template.yml +0 -0
  13. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  14. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/.github/dependabot-bot.yml +0 -0
  15. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/.github/dependabot.yml +0 -0
  16. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/.github/labeler.yml +0 -0
  17. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/.github/release.yml +0 -0
  18. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/.github/workflows/devcontainer-ci.yml +0 -0
  19. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/.github/workflows/labeler.yml +0 -0
  20. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/.github/workflows/lint.yml +0 -0
  21. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/.github/workflows/publish.yml +0 -0
  22. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/.github/workflows/scorecard.yml +0 -0
  23. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/.github/workflows/test.yml +0 -0
  24. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/.gitignore +0 -0
  25. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/.markdownlint.json +0 -0
  26. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/.pre-commit-config.yaml +0 -0
  27. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/.readthedocs.yml +0 -0
  28. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/.vscode/tasks.json +0 -0
  29. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/CONTRIBUTING.md +0 -0
  30. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/README.md +0 -0
  31. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/SECURITY.md +0 -0
  32. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/docs/.markdownlint.json +0 -0
  33. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/docs/docs/archive.md +0 -0
  34. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/docs/docs/assets/create environment vs code.gif +0 -0
  35. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/docs/docs/assets/create-app-help.png +0 -0
  36. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/docs/docs/assets/create-codespace.gif +0 -0
  37. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/docs/docs/assets/launching a dev container.gif +0 -0
  38. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/docs/docs/assets/render-engine-init-help.png +0 -0
  39. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/docs/docs/assets/render-engine-init.png +0 -0
  40. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/docs/docs/cli.md +0 -0
  41. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/docs/docs/collection.md +0 -0
  42. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/docs/docs/contributing/CODE_OF_CONDUCT.md +0 -0
  43. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/docs/docs/contributing/CONTRIBUTING.md +0 -0
  44. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/docs/docs/contributing/environment_setup.md +0 -0
  45. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/docs/docs/custom_collections.md +0 -0
  46. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/docs/docs/feeds.md +0 -0
  47. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/docs/docs/getting-started/building-your-site.md +0 -0
  48. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/docs/docs/getting-started/creating-a-collection.md +0 -0
  49. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/docs/docs/getting-started/creating-a-page.md +0 -0
  50. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/docs/docs/getting-started/creating-your-app.md +0 -0
  51. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/docs/docs/getting-started/getting-started.md +0 -0
  52. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/docs/docs/getting-started/installation.md +0 -0
  53. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/docs/docs/getting-started/layout.md +0 -0
  54. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/docs/docs/index.md +0 -0
  55. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/docs/docs/parsers.md +0 -0
  56. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/docs/docs/plugins.md +0 -0
  57. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/docs/docs/site.md +0 -0
  58. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/docs/docs/site_map.md +0 -0
  59. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/docs/docs/templates.md +0 -0
  60. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/docs/docs/theme_management.md +0 -0
  61. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/docs/mkdocs.yml +0 -0
  62. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/docs/requirements.txt +0 -0
  63. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/noxfile.py +0 -0
  64. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/pyproject.toml +0 -0
  65. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/requirements.txt +0 -0
  66. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/setup.cfg +0 -0
  67. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine/.gitignore +0 -0
  68. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine/__init__.py +0 -0
  69. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine/__main__.py +0 -0
  70. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine/_base_object.py +0 -0
  71. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine/archive.py +0 -0
  72. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine/blog.py +0 -0
  73. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine/collection.py +0 -0
  74. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine/engine.py +0 -0
  75. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine/extras/__init__.py +0 -0
  76. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine/feeds.py +0 -0
  77. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine/hookspecs.py +0 -0
  78. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine/links.py +0 -0
  79. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine/parsers/markdown.py +0 -0
  80. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine/plugins.py +0 -0
  81. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine/py.typed +0 -0
  82. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine/render_engine_templates/__init__.py +0 -0
  83. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine/render_engine_templates/archive.html +0 -0
  84. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine/render_engine_templates/base.html +0 -0
  85. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine/render_engine_templates/base_collection_path.md +0 -0
  86. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine/render_engine_templates/base_templates/_archive.html +0 -0
  87. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine/render_engine_templates/base_templates/_base.html +0 -0
  88. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine/render_engine_templates/base_templates/_page.html +0 -0
  89. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine/render_engine_templates/components/footer.html +0 -0
  90. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine/render_engine_templates/components/page_title.html +0 -0
  91. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine/render_engine_templates/page.html +0 -0
  92. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine/render_engine_templates/rss2.0.xml +0 -0
  93. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine/render_engine_templates/rss2.0_items.xml +0 -0
  94. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine/render_engine_templates/sitemap.xml +0 -0
  95. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine/render_engine_templates/sitemap_item.xml +0 -0
  96. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine/site.py +0 -0
  97. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine/site_map.py +0 -0
  98. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine/themes.py +0 -0
  99. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine/utils/__init__.py +0 -0
  100. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine.egg-info/SOURCES.txt +0 -0
  101. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine.egg-info/dependency_links.txt +0 -0
  102. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine.egg-info/requires.txt +0 -0
  103. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/src/render_engine.egg-info/top_level.txt +0 -0
  104. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/tests/conftest.py +0 -0
  105. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/tests/test_archive.py +0 -0
  106. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/tests/test_base_object.py +0 -0
  107. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/tests/test_blog.py +0 -0
  108. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/tests/test_collections.py +0 -0
  109. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/tests/test_engine.py +0 -0
  110. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/tests/test_feeds/conftest_feed.py +0 -0
  111. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/tests/test_feeds/test_feeds.py +0 -0
  112. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/tests/test_parsers_remove_2024_3_1.py +0 -0
  113. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/tests/test_plugins.py +0 -0
  114. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/tests/test_site.py +0 -0
  115. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/tests/test_site_map.py +0 -0
  116. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/tests/test_templates/test_base_html.py +0 -0
  117. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/tests/test_theme_manager.py +0 -0
  118. {render_engine-2025.10.1a1 → render_engine-2025.10.1a2}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: render_engine
3
- Version: 2025.10.1a1
3
+ Version: 2025.10.1a2
4
4
  Summary: A Flexible Static Site Generator for Python
5
5
  Project-URL: homepage, https://github.com/render-engine/render-engine/
6
6
  Project-URL: repository, https://github.com/render-engine/render-engine/
@@ -63,17 +63,18 @@ When you create a page, you specify variables passed into rendering template.
63
63
 
64
64
  **Attributes:**
65
65
 
66
- | Name | Type | Description |
67
- | --- | --- | --- |
68
- | `content_path` | `str | None` |The path to the file that will be used to generate the Page's `content`. |
69
- | `extension` | `str | None` |The suffix to use for the page. Defaults to `.html`. |
70
- | `engine` | `str | None` | If present, the engine to use for rendering the page. **This is normally not set and the `Site` 's engine will be used.** |
71
- | `reference` | `str | None` |Used to determine how to reference the page in the `Site`'s route_list. Defaults to `slug`. |
72
- | `routes` | `str | None` |The routes to use for the page. Defaults to `["./"]`. |
73
- | `template` | `str | None` |The template used to render the page. If not provided, the `Site`'s `content`will be used. |
74
- | `Parser` | `type[BasePageParser]` |The parser to generate the page's `raw_content`. Defaults to `BasePageParser`. |
75
- | `title` | `str` |The title of the page. Defaults to the class name. |
76
- | `skip_site_map` | `False` | When set to `True` the `Page` will not be included in the generated `SiteMap` |
66
+ | Name | Type | Description |
67
+ | --- |--------------------------|----------------------------------------------------------------------------------------------------------------------------------------------|
68
+ | `content_path` | `str \| None` | The path to the file that will be used to generate the Page's `content`. |
69
+ | `extension` | `str \| None` | The suffix to use for the page. Defaults to `.html`. |
70
+ | `engine` | `str \| None` | If present, the engine to use for rendering the page. **This is normally not set and the `Site` 's engine will be used.** |
71
+ | `reference` | `str \| None` | Used to determine how to reference the page in the `Site`'s route_list. Defaults to `slug`. |
72
+ | `routes` | `str \| None` | The routes to use for the page. Defaults to `["./"]`. |
73
+ | `template` | `str \| None` | The template used to render the page. If not provided, the `Site`'s `content`will be used. |
74
+ | `Parser` | `type[BasePageParser]` | The parser to generate the page's `raw_content`. Defaults to `BasePageParser`. |
75
+ | `title` | `str` | The title of the page. Defaults to the class name. |
76
+ | `skip_site_map` | `bool` | When set to `True` the `Page` will not be included in the generated `SiteMap`. Defaults to `False`. |
77
+ | `no_prerender` | `bool` | When set to `True` the `Page`'s `content` will not be pre-rendered as a `Template` even if `{{ site_map }}` is present. Defaults to `False`. |
77
78
 
78
79
  ## About Page Attributes
79
80
 
@@ -109,8 +110,8 @@ By default Page._content will return the result of `Page.Parser.parse(Page.conte
109
110
  ### Accessing URLs for other pages in the site from within the page content
110
111
 
111
112
  In order to allow lookup of URLs for other pages within a Site the `content` of a page may be
112
- a template. If the `content` matches the pattern `{{.*?}}` we will render the `content` as a
113
- template prior to rendering the page itself.
113
+ a template. If the `content` matches the pattern `{{.*?site_map.*?}}` we will render the `content` as a
114
+ template prior to rendering the page itself unless the `no_prerender` attribute of the page is `True`.
114
115
 
115
116
  Example:
116
117
 
@@ -1,3 +1,4 @@
1
+ import logging
1
2
  import re
2
3
  from pathlib import Path
3
4
  from typing import Any
@@ -10,6 +11,8 @@ from render_engine.themes import ThemeManager
10
11
  from ._base_object import BaseObject
11
12
  from .plugins import PluginManager
12
13
 
14
+ logger = logging.getLogger("Page")
15
+
13
16
 
14
17
  class BasePage(BaseObject):
15
18
  """
@@ -28,6 +31,8 @@ class BasePage(BaseObject):
28
31
  extension (str): The file extension for the page. Defaults to ".html".
29
32
  routes (list[str] | Path): The list of routes for the page. Defaults to ["./"].
30
33
  template (str | Template | None): The template to use for rendering the page.
34
+ site: The Site object that owns the page.
35
+ no_prerender: Flag to not prerender the content
31
36
  """
32
37
 
33
38
  extension: str = ".html"
@@ -36,7 +41,8 @@ class BasePage(BaseObject):
36
41
  rendered_content: str | None
37
42
  _reference: str = "_slug"
38
43
  plugin_manager: PluginManager | None
39
- site = None
44
+ site = None # This is a Site but circular imports so we can't actually type hint it.
45
+ no_prerender: bool = False
40
46
 
41
47
  @property
42
48
  def _content(self) -> any:
@@ -69,20 +75,35 @@ class BasePage(BaseObject):
69
75
  return f"/{route}/{self.path_name}"
70
76
 
71
77
  def _render_from_template(self, template: Template, **kwargs) -> str:
72
- """Renders the page from a template."""
78
+ """
79
+ Renders the page from a template.
80
+
81
+ If the content looks like a template that
82
+
83
+ :param template: Template to render
84
+ :param **kwargs: Data to pass into the template for rendering.
85
+ :return: The rendered page
86
+ """
73
87
  template_data = {"data": self._data, "content": self._content}
74
88
  if site := getattr(self, "site", None):
75
89
  template_data["site_map"] = site.site_map
76
- if isinstance(self._content, str) and re.search(r"{{.*}}", self._content):
90
+ if not self.no_prerender and isinstance(self._content, str) and re.search(r"{{.*?site_map.*?}}", self._content):
77
91
  # If the content looks like a template, try to render it.
78
- content_template = Template(self._content)
79
- template_data["content"] = content_template.render(
80
- **{
81
- **self.to_dict(),
82
- **template_data,
83
- **kwargs,
84
- }
85
- )
92
+ try:
93
+ content_template = Template(self._content)
94
+ except Exception:
95
+ logger.info(f"Failed to parse {repr(self.path_name)} as a template.", exc_info=True)
96
+ else:
97
+ try:
98
+ template_data["content"] = content_template.render(
99
+ **{
100
+ **self.to_dict(),
101
+ **template_data,
102
+ **kwargs,
103
+ }
104
+ )
105
+ except Exception:
106
+ logger.info(f"Failed to pre-render {repr(self.path_name)}.", exc_info=True)
86
107
 
87
108
  return template.render(
88
109
  **{
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: render_engine
3
- Version: 2025.10.1a1
3
+ Version: 2025.10.1a2
4
4
  Summary: A Flexible Static Site Generator for Python
5
5
  Project-URL: homepage, https://github.com/render-engine/render-engine/
6
6
  Project-URL: repository, https://github.com/render-engine/render-engine/
@@ -1,3 +1,4 @@
1
+ import logging
1
2
  import pathlib
2
3
 
3
4
  import jinja2
@@ -96,3 +97,71 @@ def test_rendered_page_from_template_has_data():
96
97
  data = [1, 2, 3, 4]
97
98
 
98
99
  assert CustomPage()._render_from_template(template=CustomPage.template) == "1234"
100
+
101
+
102
+ def test_page_fails_to_render_content_as_template(caplog):
103
+ """Tests handling content that fails to render as a template"""
104
+ caplog.set_level(logging.INFO)
105
+
106
+ template = "{% for d in data %}{{d}}{% endfor %}\n{{content}}"
107
+
108
+ environment = jinja2.Environment(loader=jinja2.DictLoader({"test.html": template}))
109
+
110
+ class CustomPage(Page):
111
+ template = environment.get_template("test.html")
112
+ data = [1, 2, 3, 4]
113
+ content = "{{ site_map.find('test') }}"
114
+
115
+ assert CustomPage()._render_from_template(template=CustomPage.template) == "1234\n{{ site_map.find('test') }}"
116
+ assert "Failed to pre-render" in caplog.messages[0]
117
+
118
+
119
+ def test_braces_ignored_without_sitemap():
120
+ """Tests that braces in content are ignored without `site_map`"""
121
+ template = "{% for d in data %}{{d}}{% endfor %}\n{{content}}"
122
+
123
+ environment = jinja2.Environment(loader=jinja2.DictLoader({"test.html": template}))
124
+
125
+ class CustomPage(Page):
126
+ template = environment.get_template("test.html")
127
+ data = [1, 2, 3, 4]
128
+ content = "{{ example }}"
129
+
130
+ assert CustomPage()._render_from_template(template=CustomPage.template) == "1234\n{{ example }}"
131
+
132
+
133
+ def test_exception_in_parsing_content_as_template(monkeypatch, caplog):
134
+ """Test failing to parse content as template"""
135
+
136
+ def mock_template():
137
+ raise jinja2.exceptions.UndefinedError("Mocked error")
138
+
139
+ monkeypatch.setattr("render_engine.page.Template", mock_template)
140
+ caplog.set_level(logging.INFO)
141
+
142
+ template = "{% for d in data %}{{d}}{% endfor %}\n{{content}}"
143
+
144
+ environment = jinja2.Environment(loader=jinja2.DictLoader({"test.html": template}))
145
+
146
+ class CustomPage(Page):
147
+ template = environment.get_template("test.html")
148
+ data = [1, 2, 3, 4]
149
+ content = "{{ site_map.find('test') }}"
150
+
151
+ assert CustomPage()._render_from_template(template=CustomPage.template) == "1234\n{{ site_map.find('test') }}"
152
+ assert "Failed to parse" in caplog.messages[0]
153
+
154
+
155
+ def test_no_prerender():
156
+ """Test pre-rendering does not occur when no_prerender is True"""
157
+ template = "{% for d in data %}{{d}}{% endfor %}\n{{content}}"
158
+
159
+ environment = jinja2.Environment(loader=jinja2.DictLoader({"test.html": template}))
160
+
161
+ class CustomPage(Page):
162
+ template = environment.get_template("test.html")
163
+ data = [1, 2, 3, 4]
164
+ content = "{{ site_map.find('test') }}"
165
+ no_prerender = True
166
+
167
+ assert CustomPage()._render_from_template(template=CustomPage.template) == "1234\n{{ site_map.find('test') }}"