render-engine 2026.6.2a4__tar.gz → 2026.7.1a3__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 (141) hide show
  1. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/.github/workflows/lint.yml +13 -8
  2. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/.github/workflows/publish-prerelease.yml +1 -1
  3. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/.github/workflows/publish.yml +4 -3
  4. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/.github/workflows/scorecard.yml +4 -4
  5. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/.github/workflows/test.yml +25 -12
  6. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/.github/workflows/ty.yml +8 -3
  7. render_engine-2026.7.1a3/.github/workflows/zizmor.yml +28 -0
  8. render_engine-2026.7.1a3/.pre-commit-config.yaml +47 -0
  9. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/PKG-INFO +1 -1
  10. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/docs/docs/contributing/CONTRIBUTING.md +11 -18
  11. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/docs/docs/contributing/github-actions-file-patterns.md +0 -21
  12. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/docs/docs/site.md +10 -0
  13. render_engine-2026.7.1a3/docs/docs/site_map.md +151 -0
  14. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/justfile +12 -3
  15. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/pyproject.toml +10 -7
  16. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/__version__.py +3 -3
  17. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/site.py +38 -3
  18. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/site_map.py +84 -1
  19. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine.egg-info/PKG-INFO +1 -1
  20. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine.egg-info/SOURCES.txt +1 -4
  21. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine.egg-info/scm_file_list.json +1 -4
  22. render_engine-2026.7.1a3/src/render_engine.egg-info/scm_version.json +8 -0
  23. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/tests/test_site.py +65 -0
  24. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/tests/test_site_map.py +169 -1
  25. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/uv.lock +31 -31
  26. render_engine-2026.6.2a4/.github/labeler.yml +0 -43
  27. render_engine-2026.6.2a4/.github/workflows/devcontainer-ci.yml +0 -28
  28. render_engine-2026.6.2a4/.github/workflows/labeler.yml +0 -16
  29. render_engine-2026.6.2a4/.github/workflows/todos.yml +0 -89
  30. render_engine-2026.6.2a4/.pre-commit-config.yaml +0 -41
  31. render_engine-2026.6.2a4/docs/docs/site_map.md +0 -76
  32. render_engine-2026.6.2a4/src/render_engine.egg-info/scm_version.json +0 -8
  33. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/.all-contributorsrc +0 -0
  34. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/.devcontainer/Dockerfile +0 -0
  35. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/.devcontainer/devcontainer.json +0 -0
  36. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/.devcontainer/setup.sh +0 -0
  37. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/.github/FUNDING.yml +0 -0
  38. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/.github/ISSUE_TEMPLATE/config.yaml +0 -0
  39. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/.github/ISSUE_TEMPLATE/form_issue_template.yml +0 -0
  40. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  41. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/.github/dependabot-bot.yml +0 -0
  42. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/.github/dependabot.yml +0 -0
  43. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/.github/release.yml +0 -0
  44. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/.github/scripts/publish_prerelease.py +0 -0
  45. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/.gitignore +0 -0
  46. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/.markdownlint.json +0 -0
  47. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/.readthedocs.yml +0 -0
  48. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/.vscode/tasks.json +0 -0
  49. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/README.md +0 -0
  50. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/SECURITY.md +0 -0
  51. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/coverage-badge.svg +0 -0
  52. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/docs/docs/archive.md +0 -0
  53. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/docs/docs/assets/create environment vs code.gif +0 -0
  54. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/docs/docs/assets/create-app-help.png +0 -0
  55. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/docs/docs/assets/create-codespace.gif +0 -0
  56. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/docs/docs/assets/launching a dev container.gif +0 -0
  57. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/docs/docs/assets/render-engine-init-help.png +0 -0
  58. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/docs/docs/assets/render-engine-init.png +0 -0
  59. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/docs/docs/collection.md +0 -0
  60. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/docs/docs/content_manager.md +0 -0
  61. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/docs/docs/contributing/CODE_OF_CONDUCT.md +0 -0
  62. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/docs/docs/contributing/SECURITY.md +0 -0
  63. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/docs/docs/contributing/environment_setup.md +0 -0
  64. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/docs/docs/contributing/gen_badge.md +0 -0
  65. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/docs/docs/contributing/style-guide.md +0 -0
  66. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/docs/docs/contributing/testing.md +0 -0
  67. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/docs/docs/contributing/typechecking.md +0 -0
  68. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/docs/docs/custom_collections.md +0 -0
  69. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/docs/docs/data_object.md +0 -0
  70. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/docs/docs/feeds.md +0 -0
  71. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/docs/docs/getting-started/building-your-site.md +0 -0
  72. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/docs/docs/getting-started/creating-a-collection.md +0 -0
  73. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/docs/docs/getting-started/creating-a-page.md +0 -0
  74. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/docs/docs/getting-started/creating-your-app.md +0 -0
  75. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/docs/docs/getting-started/extending-render-engine.md +0 -0
  76. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/docs/docs/getting-started/getting-started.md +0 -0
  77. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/docs/docs/getting-started/installation.md +0 -0
  78. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/docs/docs/getting-started/layout.md +0 -0
  79. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/docs/docs/index.md +0 -0
  80. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/docs/docs/page.md +0 -0
  81. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/docs/docs/parsers.md +0 -0
  82. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/docs/docs/plugins.md +0 -0
  83. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/docs/docs/templates.md +0 -0
  84. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/docs/docs/theme_management.md +0 -0
  85. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/docs/mkdocs.yml +0 -0
  86. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/noxfile.py +0 -0
  87. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/setup.cfg +0 -0
  88. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/.gitignore +0 -0
  89. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/__init__.py +0 -0
  90. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/_base_object.py +0 -0
  91. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/archive.py +0 -0
  92. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/blog.py +0 -0
  93. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/collection.py +0 -0
  94. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/content_managers/__init__.py +0 -0
  95. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/content_managers/base_content_manager.py +0 -0
  96. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/content_managers/file_content_manager.py +0 -0
  97. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/data_object.py +0 -0
  98. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/engine.py +0 -0
  99. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/feeds.py +0 -0
  100. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/hookspecs.py +0 -0
  101. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/links.py +0 -0
  102. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/page.py +0 -0
  103. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/parsers/__init__.py +0 -0
  104. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/parsers/base_parsers.py +0 -0
  105. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/parsers/markdown.py +0 -0
  106. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/plugins.py +0 -0
  107. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/py.typed +0 -0
  108. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/render_engine_templates/__init__.py +0 -0
  109. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/render_engine_templates/archive.html +0 -0
  110. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/render_engine_templates/base.html +0 -0
  111. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/render_engine_templates/base_collection_path.md +0 -0
  112. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/render_engine_templates/base_templates/_archive.html +0 -0
  113. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/render_engine_templates/base_templates/_base.html +0 -0
  114. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/render_engine_templates/base_templates/_page.html +0 -0
  115. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/render_engine_templates/components/footer.html +0 -0
  116. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/render_engine_templates/components/page_title.html +0 -0
  117. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/render_engine_templates/page.html +0 -0
  118. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/render_engine_templates/redirect.html +0 -0
  119. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/render_engine_templates/rss2.0.xml +0 -0
  120. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/render_engine_templates/rss2.0_items.xml +0 -0
  121. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/render_engine_templates/sitemap.xml +0 -0
  122. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/render_engine_templates/sitemap_item.xml +0 -0
  123. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/themes.py +0 -0
  124. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine/utils/__init__.py +0 -0
  125. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine.egg-info/dependency_links.txt +0 -0
  126. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine.egg-info/requires.txt +0 -0
  127. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/src/render_engine.egg-info/top_level.txt +0 -0
  128. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/tests/conftest.py +0 -0
  129. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/tests/test_archive.py +0 -0
  130. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/tests/test_base_object.py +0 -0
  131. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/tests/test_blog.py +0 -0
  132. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/tests/test_collections.py +0 -0
  133. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/tests/test_engine.py +0 -0
  134. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/tests/test_feeds/conftest_feed.py +0 -0
  135. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/tests/test_feeds/test_feeds.py +0 -0
  136. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/tests/test_file_content_manager.py +0 -0
  137. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/tests/test_page.py +0 -0
  138. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/tests/test_parsers_remove_2024_3_1.py +0 -0
  139. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/tests/test_plugins.py +0 -0
  140. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/tests/test_templates/test_base_html.py +0 -0
  141. {render_engine-2026.6.2a4 → render_engine-2026.7.1a3}/tests/test_theme_manager.py +0 -0
@@ -4,20 +4,23 @@ on:
4
4
  branches: [main]
5
5
  workflow_dispatch:
6
6
 
7
- permissions:
8
- contents: write
9
- pull-requests: write
7
+ permissions: {}
8
+
9
+ concurrency:
10
+ group: ${{ github.workflow }}-${{ github.ref }}
11
+ cancel-in-progress: true
12
+
10
13
 
11
14
  jobs:
12
15
  lint-python:
13
16
  name: Format and Lint Python
14
17
  runs-on: ubuntu-latest
15
18
  steps:
16
- - uses: actions/checkout@v6.0.1
19
+ - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
17
20
  with:
18
- fetch-depth: 0
21
+ persist-credentials: false
19
22
  - name: Install uv
20
- uses: astral-sh/setup-uv@v7
23
+ uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
21
24
  with:
22
25
  python-version: 3.14
23
26
  - name: Install dependencies
@@ -29,8 +32,10 @@ jobs:
29
32
  name: Lint Markdown
30
33
  runs-on: ubuntu-latest
31
34
  steps:
32
- - uses: actions/checkout@v6.0.1
35
+ - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
36
+ with:
37
+ persist-credentials: false
33
38
  - name: lint-test
34
- uses: DavidAnson/markdownlint-cli2-action@v23
39
+ uses: DavidAnson/markdownlint-cli2-action@ded1f9488f68a970bc66ea5619e13e9b52e601cd # v23.2.0
35
40
  with:
36
41
  globs: '**/*.md'
@@ -27,7 +27,7 @@ jobs:
27
27
  contains(github.event.pull_request.labels.*.name, 'release'))
28
28
  runs-on: ubuntu-latest
29
29
  steps:
30
- - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
30
+ - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
31
31
  with:
32
32
  persist-credentials: false # checkout only fetches the publish script
33
33
  - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
@@ -12,6 +12,7 @@ jobs:
12
12
  uses: ./.github/workflows/test.yml
13
13
  permissions:
14
14
  contents: read
15
+ pull-requests: write # This is needed for the coverage badge. Will fail on startup without it.
15
16
 
16
17
  build:
17
18
  needs: test
@@ -21,7 +22,7 @@ jobs:
21
22
  runs-on: ubuntu-latest
22
23
  steps:
23
24
  - name: Checkout source
24
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0
25
+ uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
25
26
  with:
26
27
  persist-credentials: false
27
28
 
@@ -34,7 +35,7 @@ jobs:
34
35
  - name: Build distributions
35
36
  run: uv build
36
37
  - name: Upload artifact
37
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
38
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
38
39
  with:
39
40
  path: ./dist
40
41
  name: render-engine
@@ -52,4 +53,4 @@ jobs:
52
53
  path: ./dist
53
54
  name: render-engine
54
55
  - name: Push to PyPI
55
- uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b
56
+ uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
@@ -32,12 +32,12 @@ jobs:
32
32
 
33
33
  steps:
34
34
  - name: "Checkout code"
35
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4.1.1
35
+ uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
36
36
  with:
37
37
  persist-credentials: false
38
38
 
39
39
  - name: "Run analysis"
40
- uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2
40
+ uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
41
41
  with:
42
42
  results_file: results.sarif
43
43
  results_format: sarif
@@ -59,7 +59,7 @@ jobs:
59
59
  # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
60
60
  # format to the repository Actions tab.
61
61
  - name: "Upload artifact"
62
- uses: actions/upload-artifact@v7
62
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
63
63
  with:
64
64
  name: SARIF
65
65
  path: results.sarif
@@ -68,6 +68,6 @@ jobs:
68
68
  # Upload the results to GitHub's code scanning dashboard (optional).
69
69
  # Commenting out will disable upload of results to your repo's Code Scanning dashboard
70
70
  - name: "Upload to code-scanning"
71
- uses: github/codeql-action/upload-sarif@v4
71
+ uses: github/codeql-action/upload-sarif@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4.36.3
72
72
  with:
73
73
  sarif_file: results.sarif
@@ -13,12 +13,20 @@ on:
13
13
  - "pyproject.toml"
14
14
  - "requirements.txt"
15
15
 
16
+ permissions:
17
+ contents: read
18
+
16
19
  jobs:
17
20
  gen-coverage-badge:
21
+ name: Generate Coverage Badge
18
22
  runs-on: ubuntu-latest
23
+ permissions:
24
+ pull-requests: write
19
25
  steps:
20
- - uses: actions/checkout@v6
21
- - uses: astral-sh/setup-uv@v7
26
+ - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
27
+ with:
28
+ persist-credentials: false
29
+ - uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0
22
30
  with:
23
31
  python-version: "3.14"
24
32
  enable-cache: true
@@ -30,32 +38,35 @@ jobs:
30
38
  run: |
31
39
  uvx --with "genbadge[coverage]" genbadge coverage -i coverage.xml
32
40
  - name: Commit Badge
33
- uses: stefanzweifel/git-auto-commit-action@v7
41
+ uses: stefanzweifel/git-auto-commit-action@4a55954c782fc1ea30b9056cd3e7a2b40ca8887d # v7.2.0
34
42
  with:
35
43
  commit_message: Update coverage badge [skip ci]
36
44
  file_pattern: coverage.svg
37
45
 
38
46
  test-against-python-matrix:
39
- # Only test all the supported versions when a pull request is made or the workflow is called
40
- if: ${{github.event_name == 'workflow_call'}} || ${{github.event_name == 'pull_request'}}
47
+ name: Test on all supported Python versions
41
48
  runs-on: ubuntu-latest
42
49
  strategy:
43
50
  matrix:
44
- python-version: ["3.10", "3.11", "3.12", "3.13"]
51
+ # 3.14 is not run here because it is for the latest OK check so it would be redundant.
52
+ python-version: ["3.10", "3.11", "3.12", "3.13", "3.15"]
45
53
  fail-fast: true
46
54
  steps:
47
- - uses: actions/checkout@v6.0.1
55
+ - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
56
+ with:
57
+ persist-credentials: false
48
58
  - name: Install uv
49
- uses: astral-sh/setup-uv@v7
59
+ uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0
50
60
  with:
51
61
  python-version: ${{ matrix.python-version }}
52
62
  enable-cache: true # caching dependencies
53
63
  - name: Run tests
54
64
  run: |
55
- uv run --dev pytest tests
65
+ uv run --dev --python ${{ matrix.python-version }} pytest tests
56
66
 
57
67
  test-against-latest-os:
58
68
  # Always run against the latest version on both Windows, Linux, MacOS
69
+ name: Test against latest OS
59
70
  if: github.event.pull_request.user.login != 'dependabot[bot]'
60
71
  strategy:
61
72
  matrix:
@@ -63,11 +74,13 @@ jobs:
63
74
  fail-fast: true
64
75
  runs-on: ${{ matrix.os }}
65
76
  steps:
66
- - uses: actions/checkout@v6.0.1
77
+ - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
78
+ with:
79
+ persist-credentials: false
67
80
  - name: Install uv
68
- uses: astral-sh/setup-uv@v7
81
+ uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0
69
82
  with:
70
83
  python-version: "3.14"
71
84
  enable-cache: true # caching dependencies
72
85
  - name: run tests
73
- run: uv run --dev pytest tests
86
+ run: uv run --dev --python 3.14 pytest tests
@@ -1,12 +1,15 @@
1
1
  name: Type Check
2
2
 
3
+ permissions:
4
+ contents: read
5
+
3
6
  on:
4
7
  push:
5
8
  branches:
6
9
  - main
7
10
  pull_request:
8
11
  branches:
9
- - main
12
+ - main
10
13
  paths:
11
14
  - "src/**"
12
15
  - "pyproject.toml"
@@ -16,7 +19,9 @@ jobs:
16
19
  ty_check:
17
20
  runs-on: ubuntu-latest
18
21
  steps:
19
- - uses: actions/checkout@v6.0.1
20
- - uses: astral-sh/setup-uv@v7
22
+ - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
23
+ with:
24
+ persist-credentials: false
25
+ - uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
21
26
  - name: Run type (ty) check
22
27
  run: uv run ty check src
@@ -0,0 +1,28 @@
1
+ name: GitHub Actions Security Analysis with zizmor 🌈
2
+
3
+ on:
4
+ push:
5
+ branches: ["main"]
6
+ pull_request:
7
+ branches: ["**"]
8
+
9
+ concurrency:
10
+ group: ${{ github.workflow }}-${{ github.ref }}
11
+ cancel-in-progress: true
12
+
13
+ permissions: {}
14
+
15
+ jobs:
16
+ zizmor:
17
+ name: Zizmor Check
18
+ runs-on: ubuntu-latest
19
+ permissions:
20
+ security-events: write # required for advanced security policy
21
+ steps:
22
+ - name: Checkout repository
23
+ uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
24
+ with:
25
+ persist-credentials: false
26
+
27
+ - name: Run zizmor 🌈
28
+ uses: zizmorcore/zizmor-action@192e21d79ab29983730a13d1382995c2307fbcaa # v0.5.7
@@ -0,0 +1,47 @@
1
+ repos:
2
+ - repo: https://github.com/pre-commit/pre-commit-hooks
3
+ rev: v2.3.0
4
+ hooks:
5
+ - id: check-yaml
6
+ - id: end-of-file-fixer
7
+ - id: trailing-whitespace
8
+ - repo: https://github.com/astral-sh/ruff-pre-commit
9
+ # Ruff version.
10
+ rev: v0.15.1
11
+ hooks:
12
+ # Run the linter.
13
+ - id: ruff-check
14
+ args: [--fix]
15
+ # Run the formatter.
16
+ - id: ruff-format
17
+ - repo: local
18
+ hooks:
19
+ - id: ty-check
20
+ name: ty
21
+ entry: uv run ty check src/render_engine
22
+ language: system
23
+ types: [python]
24
+ pass_filenames: false
25
+ - repo: https://github.com/DavidAnson/markdownlint-cli2
26
+ rev: v0.6.0
27
+ hooks:
28
+ - id: markdownlint-cli2
29
+ args: ["*.md", "docs/**/*.md"]
30
+ - repo: https://github.com/kjaymiller/pin-versions
31
+ rev: 2026.3.6
32
+ hooks:
33
+ - id: pin-versions
34
+ - repo: https://github.com/zizmorcore/zizmor-pre-commit
35
+ # Zizmor version.
36
+ rev: v1.26.1
37
+ hooks:
38
+ # Run the linter.
39
+ - id: zizmor
40
+ - repo: local
41
+ hooks:
42
+ - id: deptry
43
+ name: deptry
44
+ entry: uv run deptry src
45
+ language: system
46
+ always_run: true
47
+ pass_filenames: false
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: render_engine
3
- Version: 2026.6.2a4
3
+ Version: 2026.7.1a3
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/
@@ -78,7 +78,7 @@ Once you've been [assigned an issue][being-assigned], you can begin working on a
78
78
  ### Dockerfile
79
79
 
80
80
  Our DevContainer is built primarily from a dockerfile. You can build from our Dockerfile directly which would
81
- ensure the manual configuration is ran (You will still need to fork and clone).
81
+ ensure the manual configuration is run (You will still need to fork and clone).
82
82
 
83
83
  ## Verify Before Submitting
84
84
 
@@ -92,21 +92,14 @@ all supported versions.
92
92
 
93
93
  ## TODOs
94
94
 
95
- Todos are not encouraged all the time but if necessary please indicate any todos with the `# TODO` prefix.
96
- We use [todo-to-issue] as a GitHub Action to create issues from TODOs.
97
-
98
- When a PR containing `# TODO` comments is opened, a bot will comment suggesting a maintainer
99
- add the **todo-to-issue** label. Once a maintainer adds the label, the action will:
100
-
101
- 1. Create GitHub issues for each TODO
102
- 2. Update the TODO comments in your code with the issue number and link
103
- 3. Commit the changes back to your PR branch
104
-
105
- The label is removed automatically afterward and can be re-applied if new TODOs are added.
95
+ To-dos are not encouraged all the time but if necessary please indicate any todos with the `# TODO` prefix.
96
+ Before submitting a PR with a `# TODO` please make sure to open the corresponding [issue in GitHub] and include
97
+ the link as part of the `# TODO` comment. PRs opened that include a `# TODO` comment without a corresponding
98
+ GitHub issue will be requested to create the issue and update the comment prior to merge.
106
99
 
107
100
  ## Contributing to Documentation
108
101
 
109
- Render Engine uses [readthedocs][readthedocs] in combination with [MkDocs][uv[Material for MkDocs][material],
102
+ Render Engine uses [readthedocs][readthedocs] in combination with [MkDocs], [Material for MkDocs],
110
103
  and [mkdocsstrings][mkdocsstrings] to generate documentation.
111
104
 
112
105
  - 📝 update docstrings for functions, methods, and classes.
@@ -119,7 +112,7 @@ Test your docs changes by running the command **FROM THE PROJECT ROOT**.
119
112
  You can start the documentation server on the default port (8000):
120
113
 
121
114
  ```sh
122
- just docs
115
+ just docs
123
116
  ```
124
117
 
125
118
  Or, you can specify a custom port:
@@ -149,7 +142,7 @@ This attestation should mean that the AI model is included as a co-Author of the
149
142
 
150
143
  The AI assistant is your copilot. You are still responsible for code changes submitted.
151
144
  Low quality contributions or code that cannot be defended by the USER (not their AI model)
152
- will result in issues/prs being immediately closed.
145
+ will result in issues/PRs being immediately closed.
153
146
  Multiple low quality contributions will result in your user account being banned from contribution.
154
147
 
155
148
  [AI attestation]: #ai-attestation
@@ -161,11 +154,11 @@ Multiple low quality contributions will result in your user account being banned
161
154
  [dev-container]: https://render-engine.readthedocs.io/en/latest/contributing/environment_setup#developing-locally
162
155
  [codespaces]: https://render-engine.readthedocs.io/en/latest/contributing/environment_setup#using-codespaces
163
156
  [readthedocs]: https://readthedocs.org
164
- [mkdocs]: https://www.mkdocs.org
165
- [material]: https://squidfunk.github.io/mkdocs-material/
157
+ [MkDocs]: https://www.mkdocs.org
158
+ [Material for MkDocs]: https://squidfunk.github.io/mkdocs-material/
166
159
  [mkdocsstrings]: https://mkdocsstrings.readthedocs.io/en/latest/
167
160
  [code of conduct]: https://github.com/render-engine/render-engine/blob/main/.github/CODE_OF_CONDUCT.md
168
161
  [docs-contributing]: https://render-engine.readthedocs.io/en/latest/contributing/CONTRIBUTING/#instead-of-making-a-change-in-render-engines-code-consider
169
- [todo-to-issue]: https://github.com/marketplace/actions/todo-to-issue
170
162
  [Wait to be assigned an issue]: #wait-to-be-assigned-issues
171
163
  [Formatting your PR]: #formatting-your-pr
164
+ [issue in GitHub]: https://github.com/render-engine/render-engine/issues/new/choose
@@ -201,27 +201,6 @@ paths:
201
201
  - "requirements.txt"
202
202
  ```
203
203
 
204
- ### Documentation Labels
205
-
206
- From `.github/labeler.yml`:
207
-
208
- ```yaml
209
- documentation:
210
- - changed-files:
211
- - any-glob-to-any-file: ['docs/**', 'guides/**']
212
- - any-glob-to-any-file: '**/*.md'
213
- ```
214
-
215
- ### Source Code Labels
216
-
217
- ```yaml
218
- source:
219
- - all:
220
- - changed-files:
221
- - any-glob-to-any-file: 'src/**/*'
222
- - all-globs-to-all-files: '!src/docs/*'
223
- ```
224
-
225
204
  ## Troubleshooting
226
205
 
227
206
  ### Workflow Not Running When Expected
@@ -40,6 +40,11 @@ Site(
40
40
  render_xml_site_map: bool = False,
41
41
  slug_only_urls: bool = False,
42
42
  site_vars: object | dict = SENTINEL,
43
+ static_include_patterns: set[str] | None = None,
44
+ static_exclude_patterns: set[str] | None = None,
45
+ static_exclude_dirs: set[str] | None = None,
46
+ static_include_dirs: set[str] | None = None,
47
+ include_static_in_site_map: bool = False,
43
48
  ) -> None:
44
49
  pass
45
50
  ```
@@ -58,6 +63,11 @@ The `Site` constructor takes the following keyword arguments:
58
63
  | `render_xml_site_map` | `bool` | When True render the site map as an XML file. Default: False. |
59
64
  | `slug_only_urls` | `bool` | Default value for Page objects rendering slub only URLS. Default: False |
60
65
  | `site_vars` | `dict` | The site_vars dictionary containing data to be passed to all templates during rendering. |
66
+ | `static_include_patterns` | `set[str] \| None` | Glob patterns a static file must match to be included. Default: `None` (no filtering). |
67
+ | `static_exclude_patterns` | `set[str] \| None` | Glob patterns that exclude a static file even if it matched an include pattern. Default: `None`. |
68
+ | `static_exclude_dirs` | `set[str] \| None` | Directory names to skip entirely under any static path. Default: `None`. |
69
+ | `static_include_dirs` | `set[str] \| None` | Subdirectory paths that override `static_exclude_dirs` for matching subdirectories. Default: `None`. |
70
+ | `include_static_in_site_map` | `bool` | When True, static files are added to the site map. Default: `False`. |
61
71
  <!-- markdownlint-enable MD056 -->
62
72
  <!-- markdownlint-enable MD060 -->
63
73
 
@@ -0,0 +1,151 @@
1
+ ---
2
+ title: "SiteMap Objects"
3
+ description: "Overview of the SiteMap"
4
+ date: September 27, 2025
5
+ tags: ["site-map"]
6
+ ---
7
+ Prior to rendering the `Site` Render Engine will create a `SiteMap` containing searchable information
8
+ about all of the `Collection` and `Page` objects it has.
9
+
10
+ ## Searching the `SiteMap`
11
+
12
+ To search the `SiteMap` use the `find` method.
13
+
14
+ ```python
15
+ def find(
16
+ self,
17
+ value: str,
18
+ attr: str = "slug",
19
+ collection: str = None,
20
+ full_search: bool = False,
21
+ ) -> SiteMapEntry | None:
22
+ ```
23
+
24
+ ### Parameters
25
+
26
+ - `value`: The value to search for
27
+ - `attr`: Optional attribute to search by. Options are `slug`, `title`, `path_name`. Defaults to `slug`.
28
+ - `collection`: Limit the search to a single `Collection`. Defaults to `None`.
29
+ - `full_search`: Search all `Page` and `Collection` objects. Defaults to `False`.
30
+
31
+ Notes:
32
+
33
+ 1. If `collection` is set the search will be limited to that `Collection` object regardless of whether
34
+ `full_search` is set.
35
+ 2. If `full_search` is set it will return the first match found. If you have 3 pages with the same `slug`,
36
+ 1 not in a `Collection` and 2 others in different `Collection` objects, the first one defined will be the
37
+ one found.
38
+
39
+ ## Generating an HTML site map
40
+
41
+ The `SiteMap` object has an `html` property that will return an HTML sitemap with _absolute_ URLs with the
42
+ `Site`'s `SITE_URL`.
43
+
44
+ As a convenience, Render Engine will generate a site map page if the `Site` property of `render_html_site_map`
45
+ is `True` (it defaults to `False`.) Please note that this will not be templated. Should you wish the generated
46
+ site map to be on a template you can add the following to your app:
47
+
48
+ ```python
49
+ @app.page
50
+ class SiteMapPage(Page):
51
+ template = "site_map_template.html"
52
+ content = "{{ site_map.html }}"
53
+ skip_site_map = True
54
+ ```
55
+
56
+ Please note the `skip_site_map = True` to avoid having a self-referential link to the site map.
57
+
58
+ ## Generating an XML site map
59
+
60
+ To have your site generate an XML site map set the `render_xml_site_map` property of your `Site` object
61
+ to `True` (defaults to `False`.) This will create the `site_map.xml` file in the root output directory
62
+ of your site.
63
+
64
+ ## Including Static Files in the Site Map
65
+
66
+ By default, the `SiteMap` also includes an entry for every static file found in
67
+ the `Site`'s `static_paths` (e.g. images, CSS, JS, and any other files copied
68
+ from your static directories). This means static assets show up in both the
69
+ generated HTML site map and the XML site map alongside your `Page` and
70
+ `Collection` entries.
71
+
72
+ Static file entries use the URL they are ultimately served at, based on where
73
+ `static_paths` are copied to in the output directory. For example, a file at
74
+ `static/images/logo.png` will appear in the site map with the URL
75
+ `/static/images/logo.png`.
76
+
77
+ If you want to add static files to a `SiteMap` manually — for example, when
78
+ working with the `SiteMap` object directly rather than through `Site.render()`
79
+ — use the `add_static_files` method:
80
+
81
+ ```python
82
+ def add_static_files(
83
+ self,
84
+ static_paths: Iterable[str | Path],
85
+ include_patterns: Iterable[str] | None = None,
86
+ exclude_patterns: Iterable[str] | None = None,
87
+ exclude_dirs: Iterable[str] | None = None,
88
+ include_dirs: Iterable[str] | None = None,
89
+ ) -> None:
90
+ ```
91
+
92
+ <!-- markdownlint-disable-next-line MD024 -->
93
+ ### Parameters
94
+
95
+ - `static_paths`: An iterable of directories (as `str` or `Path`) to walk for
96
+ static files. This is normally `Site.static_paths`, the same set of
97
+ directories copied to the output folder.
98
+ - `include_patterns`: An iterable of glob patterns a file must match to be
99
+ included in the site map. Defaults to `None`, meaning no filtering — every
100
+ file is included.
101
+ - `exclude_patterns`: An iterable of glob patterns that exclude a file even
102
+ if it matched an `include_patterns` entry. Defaults to `None`, excluding
103
+ nothing.
104
+ - `exclude_dirs`: An iterable of directory names to skip entirely, matched
105
+ against any path segment relative to the static directory. Defaults to
106
+ `None`, excluding nothing.
107
+ - `include_dirs`: An iterable of subdirectory paths that override
108
+ `exclude_dirs`, forcing inclusion for matching subdirectories even if a
109
+ parent directory was excluded. Defaults to `None`, meaning no override.
110
+
111
+ Note: `SiteMap.update()` will automatically call `add_static_files` for you
112
+ if the `SiteMap` has `static_paths` set and `include_static_in_site_map` is
113
+ `True`, using `Site.static_include_patterns`, `Site.static_exclude_patterns`,
114
+ `Site.static_exclude_dirs`, and `Site.static_include_dirs` — so in most cases
115
+ you won't need to call this directly, or configure filtering anywhere except
116
+ on your `Site` object. Setting `include_static_in_site_map=False` on `Site`
117
+ excludes static files from the site map entirely, without affecting whether
118
+ they are copied to the output directory. For example:
119
+
120
+ ```python
121
+ site = Site(
122
+ static_paths={"static"},
123
+ static_include_patterns=("*.css", "*.js", "*.png"),
124
+ static_exclude_dirs=("drafts",),
125
+ static_include_dirs=("drafts/public",),
126
+ include_static_in_site_map=True,
127
+ )
128
+ ```
129
+
130
+ ## The `SiteMapEntry` object
131
+
132
+ The `SiteMap` is a collection of `SiteMapEntry` objects. Each `SiteMapEntry` has the following attributes
133
+ and properties:
134
+
135
+ ### Attributes and Properties
136
+
137
+ - `slug` - The `slug` for the referenced `Page` or `Collection`.
138
+ - `title` - The `title` for the referenced `Page` or `Collection`.
139
+ - `path_name` - The `path_name` for the referenced `Page` or `Collection`.
140
+ - `entries` - A list of `SiteMapEntry` objects representing the `Page` objects in a given `Collection`.
141
+ for a `Page` this will be an empty `list`.
142
+ - `url_for` - This property will provide the _relative_ URL for the given entry.
143
+
144
+ ## The `StaticSiteMapEntry` object
145
+
146
+ `StaticSiteMapEntry` is a subclass of `SiteMapEntry` used to represent static
147
+ files (images, CSS, JS, etc.) in the site map, rather than `Page` or
148
+ `Collection` objects. It shares the same `url_for` property and `__str__`
149
+ behavior as `SiteMapEntry`, so it can be used interchangeably anywhere a
150
+ `SiteMapEntry` is expected — for example, when iterating over a `SiteMap` or
151
+ using `SiteMap.find()`.
@@ -2,8 +2,10 @@
2
2
  # Requires: just, uv
3
3
 
4
4
  DEFAULT_PYTHON_VERSION := "3.14"
5
+ WORKFLOW_DIRECTORY := ".github/workflows/"
5
6
 
6
7
  # Default recipe to display available commands
8
+ [private]
7
9
  default:
8
10
  @just --list
9
11
 
@@ -12,11 +14,10 @@ sync:
12
14
  uv sync --dev --group docs
13
15
 
14
16
  # Run pytest
15
- test *FLAGS='':
16
- pytest {{ DEFAULT_PYTHON_VERSION }} {{ FLAGS }}
17
+ test *FLAGS='': (pytest DEFAULT_PYTHON_VERSION FLAGS)
17
18
 
18
19
  # Run tests in arbitrary Python version.
19
- pytest VERSION *FLAGS='':
20
+ pytest VERSION=DEFAULT_PYTHON_VERSION *FLAGS='':
20
21
  uv run -p {{ VERSION }} --dev pytest {{ FLAGS }}
21
22
 
22
23
  # Run pytest with coverage report (defaults to XML)
@@ -79,3 +80,11 @@ badge: (test-cov-report 'xml')
79
80
 
80
81
  # Run full CI workflow (sync, lint, test, badge)
81
82
  ci: sync nox ruff ty badge
83
+
84
+ # Update and pin actions with pinact
85
+ pinact WORKFLOW='*.yml' *FLAGS='':
86
+ pinact run -u {{ FLAGS }} {{ WORKFLOW_DIRECTORY }}{{ WORKFLOW }}
87
+
88
+ # Audit with zizmor
89
+ zizmor WORKFLOW='*.yml' *FLAGS='':
90
+ uvx zizmor {{ WORKFLOW_DIRECTORY }}{{ WORKFLOW }} {{ FLAGS }}
@@ -25,13 +25,11 @@ extras = []
25
25
  [dependency-groups]
26
26
  dev = [
27
27
  "ephemeral-port-reserve==1.1.4",
28
- "deptry>=0.24.0",
28
+ "deptry==0.25.1",
29
29
  "httpx==0.28.1",
30
- # TODO: Update typing with new versions in 0.0.24
31
- # Issue URL: https://github.com/render-engine/render-engine/issues/1142
32
- "ty==0.0.40",
30
+ "ty==0.0.55",
33
31
  "pre-commit==4.6.0",
34
- "pytest==9.0.3",
32
+ "pytest==9.1.1",
35
33
  "pytest-cov==7.1.0",
36
34
  "pytest-mock==3.15.1",
37
35
  "toml==0.10.2",
@@ -41,7 +39,7 @@ docs = [
41
39
  "mkdocs-material==9.7.6",
42
40
  "mkdocs-multirepo-plugin==0.8.3",
43
41
  "mkdocstrings[python]==1.0.4",
44
- "pymdown-extensions==10.21.3",
42
+ "pymdown-extensions==11.0",
45
43
  ]
46
44
 
47
45
  [tool.setuptools_scm]
@@ -77,4 +75,9 @@ select = ["E", "F", "I", "UP"]
77
75
  unresolved-import = "warn"
78
76
 
79
77
  [tool.deptry]
80
- pep621_dev_dependency_groups = ["extras"]
78
+ optional_dependencies_dev_groups = ["extras"]
79
+
80
+ [tool.deptry.package_module_name_map]
81
+ python-dateutil = "dateutil"
82
+ python-slugify = "slugify"
83
+ python-frontmatter = "frontmatter"