render-engine 2026.3.4a2__tar.gz → 2026.3.4a3__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 (134) hide show
  1. render_engine-2026.3.4a3/.github/workflows/todos.yml +89 -0
  2. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/.gitignore +1 -0
  3. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/.pre-commit-config.yaml +4 -0
  4. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/PKG-INFO +17 -17
  5. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/README.md +6 -6
  6. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/docs/docs/contributing/CONTRIBUTING.md +11 -3
  7. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/docs/docs/contributing/testing.md +9 -0
  8. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/docs/docs/getting-started/building-your-site.md +1 -2
  9. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/docs/docs/getting-started/creating-your-app.md +1 -1
  10. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/docs/docs/getting-started/installation.md +3 -3
  11. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/docs/docs/index.md +3 -3
  12. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/docs/mkdocs.yml +8 -1
  13. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/justfile +12 -0
  14. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/pyproject.toml +25 -22
  15. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine/__init__.py +2 -1
  16. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine/__version__.py +3 -3
  17. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine/collection.py +1 -1
  18. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine/feeds.py +1 -2
  19. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine/page.py +9 -4
  20. render_engine-2026.3.4a3/src/render_engine/parsers/__init__.py +3 -0
  21. render_engine-2026.3.4a3/src/render_engine/parsers/base_parsers.py +76 -0
  22. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine.egg-info/PKG-INFO +17 -17
  23. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine.egg-info/SOURCES.txt +2 -1
  24. render_engine-2026.3.4a3/src/render_engine.egg-info/requires.txt +14 -0
  25. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/uv.lock +80 -32
  26. render_engine-2026.3.4a2/.github/workflows/todos.yml +0 -31
  27. render_engine-2026.3.4a2/docs/docs/cli.md +0 -230
  28. render_engine-2026.3.4a2/src/render_engine.egg-info/requires.txt +0 -14
  29. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/.all-contributorsrc +0 -0
  30. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/.devcontainer/Dockerfile +0 -0
  31. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/.devcontainer/devcontainer.json +0 -0
  32. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/.devcontainer/setup.sh +0 -0
  33. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/.github/FUNDING.yml +0 -0
  34. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/.github/ISSUE_TEMPLATE/config.yaml +0 -0
  35. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/.github/ISSUE_TEMPLATE/form_issue_template.yml +0 -0
  36. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  37. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/.github/dependabot-bot.yml +0 -0
  38. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/.github/dependabot.yml +0 -0
  39. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/.github/labeler.yml +0 -0
  40. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/.github/release.yml +0 -0
  41. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/.github/workflows/devcontainer-ci.yml +0 -0
  42. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/.github/workflows/labeler.yml +0 -0
  43. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/.github/workflows/lint.yml +0 -0
  44. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/.github/workflows/publish.yml +0 -0
  45. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/.github/workflows/scorecard.yml +0 -0
  46. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/.github/workflows/test.yml +0 -0
  47. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/.github/workflows/ty.yml +0 -0
  48. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/.markdownlint.json +0 -0
  49. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/.readthedocs.yml +0 -0
  50. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/.vscode/tasks.json +0 -0
  51. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/SECURITY.md +0 -0
  52. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/coverage-badge.svg +0 -0
  53. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/docs/docs/archive.md +0 -0
  54. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/docs/docs/assets/create environment vs code.gif +0 -0
  55. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/docs/docs/assets/create-app-help.png +0 -0
  56. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/docs/docs/assets/create-codespace.gif +0 -0
  57. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/docs/docs/assets/launching a dev container.gif +0 -0
  58. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/docs/docs/assets/render-engine-init-help.png +0 -0
  59. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/docs/docs/assets/render-engine-init.png +0 -0
  60. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/docs/docs/collection.md +0 -0
  61. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/docs/docs/content_manager.md +0 -0
  62. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/docs/docs/contributing/CODE_OF_CONDUCT.md +0 -0
  63. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/docs/docs/contributing/SECURITY.md +0 -0
  64. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/docs/docs/contributing/environment_setup.md +0 -0
  65. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/docs/docs/contributing/gen_badge.md +0 -0
  66. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/docs/docs/contributing/github-actions-file-patterns.md +0 -0
  67. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/docs/docs/contributing/style-guide.md +0 -0
  68. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/docs/docs/contributing/typechecking.md +0 -0
  69. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/docs/docs/custom_collections.md +0 -0
  70. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/docs/docs/data_object.md +0 -0
  71. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/docs/docs/feeds.md +0 -0
  72. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/docs/docs/getting-started/creating-a-collection.md +0 -0
  73. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/docs/docs/getting-started/creating-a-page.md +0 -0
  74. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/docs/docs/getting-started/getting-started.md +0 -0
  75. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/docs/docs/getting-started/layout.md +0 -0
  76. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/docs/docs/page.md +0 -0
  77. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/docs/docs/parsers.md +0 -0
  78. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/docs/docs/plugins.md +0 -0
  79. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/docs/docs/site.md +0 -0
  80. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/docs/docs/site_map.md +0 -0
  81. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/docs/docs/templates.md +0 -0
  82. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/docs/docs/theme_management.md +0 -0
  83. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/noxfile.py +0 -0
  84. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/setup.cfg +0 -0
  85. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine/.gitignore +0 -0
  86. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine/_base_object.py +0 -0
  87. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine/archive.py +0 -0
  88. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine/blog.py +0 -0
  89. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine/content_managers/__init__.py +0 -0
  90. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine/content_managers/base_content_manager.py +0 -0
  91. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine/content_managers/file_content_manager.py +0 -0
  92. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine/data_object.py +0 -0
  93. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine/engine.py +0 -0
  94. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine/hookspecs.py +0 -0
  95. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine/links.py +0 -0
  96. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine/parsers/markdown.py +0 -0
  97. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine/plugins.py +0 -0
  98. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine/py.typed +0 -0
  99. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine/render_engine_templates/__init__.py +0 -0
  100. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine/render_engine_templates/archive.html +0 -0
  101. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine/render_engine_templates/base.html +0 -0
  102. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine/render_engine_templates/base_collection_path.md +0 -0
  103. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine/render_engine_templates/base_templates/_archive.html +0 -0
  104. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine/render_engine_templates/base_templates/_base.html +0 -0
  105. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine/render_engine_templates/base_templates/_page.html +0 -0
  106. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine/render_engine_templates/components/footer.html +0 -0
  107. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine/render_engine_templates/components/page_title.html +0 -0
  108. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine/render_engine_templates/page.html +0 -0
  109. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine/render_engine_templates/rss2.0.xml +0 -0
  110. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine/render_engine_templates/rss2.0_items.xml +0 -0
  111. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine/render_engine_templates/sitemap.xml +0 -0
  112. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine/render_engine_templates/sitemap_item.xml +0 -0
  113. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine/site.py +0 -0
  114. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine/site_map.py +0 -0
  115. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine/themes.py +0 -0
  116. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine/utils/__init__.py +0 -0
  117. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine.egg-info/dependency_links.txt +0 -0
  118. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/src/render_engine.egg-info/top_level.txt +0 -0
  119. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/tests/conftest.py +0 -0
  120. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/tests/test_archive.py +0 -0
  121. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/tests/test_base_object.py +0 -0
  122. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/tests/test_blog.py +0 -0
  123. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/tests/test_collections.py +0 -0
  124. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/tests/test_engine.py +0 -0
  125. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/tests/test_feeds/conftest_feed.py +0 -0
  126. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/tests/test_feeds/test_feeds.py +0 -0
  127. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/tests/test_file_content_manager.py +0 -0
  128. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/tests/test_page.py +0 -0
  129. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/tests/test_parsers_remove_2024_3_1.py +0 -0
  130. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/tests/test_plugins.py +0 -0
  131. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/tests/test_site.py +0 -0
  132. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/tests/test_site_map.py +0 -0
  133. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/tests/test_templates/test_base_html.py +0 -0
  134. {render_engine-2026.3.4a2 → render_engine-2026.3.4a3}/tests/test_theme_manager.py +0 -0
@@ -0,0 +1,89 @@
1
+ name: "TODO to Issue"
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened, synchronize, labeled]
6
+ branches: [main]
7
+
8
+ jobs:
9
+ detect-todos:
10
+ if: github.event.action == 'opened' || github.event.action == 'synchronize'
11
+ runs-on: ubuntu-latest
12
+ permissions:
13
+ pull-requests: write
14
+ steps:
15
+ - uses: actions/checkout@v6
16
+ with:
17
+ fetch-depth: 0
18
+
19
+ - name: Check diff for TODOs
20
+ id: check
21
+ run: |
22
+ if git diff origin/main...HEAD | grep -q '^\+.*# *TODO'; then
23
+ echo "found=true" >> "$GITHUB_OUTPUT"
24
+ else
25
+ echo "found=false" >> "$GITHUB_OUTPUT"
26
+ fi
27
+
28
+ - name: Comment on PR
29
+ if: steps.check.outputs.found == 'true'
30
+ uses: actions/github-script@v7
31
+ with:
32
+ script: |
33
+ const { data: comments } = await github.rest.issues.listComments({
34
+ owner: context.repo.owner,
35
+ repo: context.repo.repo,
36
+ issue_number: context.payload.pull_request.number,
37
+ });
38
+ const marker = '<!-- todo-to-issue-bot -->';
39
+ if (comments.some(c => c.body.includes(marker))) return;
40
+
41
+ await github.rest.issues.createComment({
42
+ owner: context.repo.owner,
43
+ repo: context.repo.repo,
44
+ issue_number: context.payload.pull_request.number,
45
+ body: `${marker}\nThis PR contains \`TODO\` comments. A maintainer can add the **todo-to-issue** label to automatically create GitHub issues and link them in the code.`
46
+ });
47
+
48
+ create-issues:
49
+ if: github.event.action == 'labeled' && github.event.label.name == 'todo-to-issue'
50
+ runs-on: ubuntu-latest
51
+ permissions:
52
+ contents: write
53
+ issues: write
54
+ pull-requests: write
55
+ steps:
56
+ - uses: actions/checkout@v6
57
+ with:
58
+ ref: ${{ github.head_ref }}
59
+ fetch-depth: 0
60
+
61
+ - name: TODO to Issue
62
+ uses: alstr/todo-to-issue-action@v5
63
+ with:
64
+ INSERT_ISSUE_URLS: "true"
65
+ CLOSES_ISSUE: "true"
66
+
67
+ - name: Commit and push issue URLs
68
+ run: |
69
+ git config user.name "github-actions[bot]"
70
+ git config user.email "github-actions[bot]@users.noreply.github.com"
71
+ git add -A
72
+ if [[ `git status --porcelain` ]]; then
73
+ git commit -m "Automatically added GitHub issue links to TODOs"
74
+ git push origin HEAD:${{ github.head_ref }}
75
+ else
76
+ echo "No changes to commit"
77
+ fi
78
+
79
+ - name: Remove label
80
+ if: always()
81
+ uses: actions/github-script@v7
82
+ with:
83
+ script: |
84
+ await github.rest.issues.removeLabel({
85
+ owner: context.repo.owner,
86
+ repo: context.repo.repo,
87
+ issue_number: context.payload.pull_request.number,
88
+ name: 'todo-to-issue'
89
+ });
@@ -168,3 +168,4 @@ untitled-site/
168
168
  .python-version
169
169
 
170
170
  __version__.py
171
+ .worktress
@@ -26,6 +26,10 @@ repos:
26
26
  rev: v0.6.0
27
27
  hooks:
28
28
  - id: markdownlint-cli2
29
+ - repo: https://github.com/kjaymiller/pin-versions
30
+ rev: 2026.3.6
31
+ hooks:
32
+ - id: pin-versions
29
33
  - repo: local
30
34
  hooks:
31
35
  - id: deptry
@@ -1,24 +1,24 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: render_engine
3
- Version: 2026.3.4a2
3
+ Version: 2026.3.4a3
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/
7
7
  Project-URL: documentation, https://render-engine.readthedocs.io/en/latest/
8
8
  Requires-Python: >=3.10
9
9
  Description-Content-Type: text/markdown
10
- Requires-Dist: jinja2
11
- Requires-Dist: more-itertools
12
- Requires-Dist: pluggy
13
- Requires-Dist: python-dateutil
14
- Requires-Dist: python-slugify
15
- Requires-Dist: render-engine-parser
16
- Requires-Dist: render-engine-markdown
17
- Requires-Dist: rich
10
+ Requires-Dist: jinja2==3.1.6
11
+ Requires-Dist: more-itertools==10.8.0
12
+ Requires-Dist: pluggy==1.6.0
13
+ Requires-Dist: python-dateutil==2.9.0.post0
14
+ Requires-Dist: python-frontmatter==1.1.0
15
+ Requires-Dist: python-slugify==8.0.4
16
+ Requires-Dist: render-engine-markdown==2023.12.1
17
+ Requires-Dist: rich==14.3.1
18
18
  Provides-Extra: cli
19
- Requires-Dist: render-engine-cli; extra == "cli"
19
+ Requires-Dist: render-engine-cli==2025.11.1; extra == "cli"
20
20
  Provides-Extra: extras
21
- Requires-Dist: render-engine-sitemap; extra == "extras"
21
+ Requires-Dist: render-engine-sitemap==2024.1.1a1; extra == "extras"
22
22
 
23
23
  <!-- markdownlint-disable -->
24
24
  <!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
@@ -51,10 +51,10 @@ Requires-Dist: render-engine-sitemap; extra == "extras"
51
51
 
52
52
  ## Installing Render Engine
53
53
 
54
- To use the render engine, you must have Python 3.10 or greater installed. You can download Python from [python.org][python].
54
+ To use the render engine, you must have Python 3.10 or greater installed. You can download Python from [python.org].
55
55
 
56
- - Linux/MacOS: [python.org][python]
57
- - Windows: [Microsoft Store][ms-store]
56
+ - Linux/MacOS: [python.org]
57
+ - Windows: Install Python using [pymanager on Microsoft Store][ms-store], which manages Python installations.
58
58
 
59
59
  Render Engine is available in PyPI and can be installed using pip:
60
60
 
@@ -131,13 +131,13 @@ Thank you to them and all of those who continue to support this project!
131
131
 
132
132
  [pytest-badge]: https://github.com/kjaymiller/render_engine/actions/workflows/test.yml/badge.svg
133
133
  [pytest-action]: https://github.com/kjaymiller/render_engine/actions/workflows/test.yml
134
- [coverage-badge]: ./coverage-badge.svg
134
+ [coverage-badge]: https://raw.githubusercontent.com/render-engine/render-engine/refs/heads/main/coverage-badge.svg
135
135
  [discord-badge]: https://img.shields.io/discord/1174377880118104156?label=Discord&color=purple
136
136
  [discord-link]: https://discord.gg/2xMQ4j4d8m
137
137
  [docs]: https://render-engine.readthedocs.io/en/latest/
138
138
  [wiki]: https://github.com/render-engine/render-engine/wiki
139
- [python]: https://python.org
140
- [ms-store]: https://apps.microsoft.com/store/detail/python-311/9NRWMJP3717K
139
+ [python.org]: https://python.org
140
+ [ms-store]: https://apps.microsoft.com/detail/9NQ7512CXL7T
141
141
  [getting-started]: https://render-engine.readthedocs.io/en/latest/page/
142
142
  [bdougie]: https://github.com/bdougie
143
143
  [contributing]: https://render-engine.readthedocs.io/en/latest/contributing/CONTRIBUTING/
@@ -29,10 +29,10 @@
29
29
 
30
30
  ## Installing Render Engine
31
31
 
32
- To use the render engine, you must have Python 3.10 or greater installed. You can download Python from [python.org][python].
32
+ To use the render engine, you must have Python 3.10 or greater installed. You can download Python from [python.org].
33
33
 
34
- - Linux/MacOS: [python.org][python]
35
- - Windows: [Microsoft Store][ms-store]
34
+ - Linux/MacOS: [python.org]
35
+ - Windows: Install Python using [pymanager on Microsoft Store][ms-store], which manages Python installations.
36
36
 
37
37
  Render Engine is available in PyPI and can be installed using pip:
38
38
 
@@ -109,13 +109,13 @@ Thank you to them and all of those who continue to support this project!
109
109
 
110
110
  [pytest-badge]: https://github.com/kjaymiller/render_engine/actions/workflows/test.yml/badge.svg
111
111
  [pytest-action]: https://github.com/kjaymiller/render_engine/actions/workflows/test.yml
112
- [coverage-badge]: ./coverage-badge.svg
112
+ [coverage-badge]: https://raw.githubusercontent.com/render-engine/render-engine/refs/heads/main/coverage-badge.svg
113
113
  [discord-badge]: https://img.shields.io/discord/1174377880118104156?label=Discord&color=purple
114
114
  [discord-link]: https://discord.gg/2xMQ4j4d8m
115
115
  [docs]: https://render-engine.readthedocs.io/en/latest/
116
116
  [wiki]: https://github.com/render-engine/render-engine/wiki
117
- [python]: https://python.org
118
- [ms-store]: https://apps.microsoft.com/store/detail/python-311/9NRWMJP3717K
117
+ [python.org]: https://python.org
118
+ [ms-store]: https://apps.microsoft.com/detail/9NQ7512CXL7T
119
119
  [getting-started]: https://render-engine.readthedocs.io/en/latest/page/
120
120
  [bdougie]: https://github.com/bdougie
121
121
  [contributing]: https://render-engine.readthedocs.io/en/latest/contributing/CONTRIBUTING/
@@ -77,9 +77,17 @@ all supported versions.
77
77
 
78
78
  ## TODOs
79
79
 
80
- Todos are not encouraged all the time but if necessary please indicate any todos with the `# TODO Prefix`.
81
- We use [todo-to-issue] as a github action that will create issues for any TODOs that are created.
82
- This will modify your code with the issue number and link to the TODO in the comments.
80
+ Todos are not encouraged all the time but if necessary please indicate any todos with the `# TODO` prefix.
81
+ We use [todo-to-issue] as a GitHub Action to create issues from TODOs.
82
+
83
+ When a PR containing `# TODO` comments is opened, a bot will comment suggesting a maintainer
84
+ add the **todo-to-issue** label. Once a maintainer adds the label, the action will:
85
+
86
+ 1. Create GitHub issues for each TODO
87
+ 2. Update the TODO comments in your code with the issue number and link
88
+ 3. Commit the changes back to your PR branch
89
+
90
+ The label is removed automatically afterward and can be re-applied if new TODOs are added.
83
91
 
84
92
  ## Contributing to Documentation
85
93
 
@@ -60,6 +60,14 @@ To run the lint and format together:
60
60
  just ruff
61
61
  ```
62
62
 
63
+ #### Using just for linting Markdown
64
+
65
+ ```bash
66
+ just lint-md
67
+ ```
68
+
69
+ **NOTE** running the markdown lint requires [bun].
70
+
63
71
  #### Using uvx for linting and formatting
64
72
 
65
73
  ```bash
@@ -69,3 +77,4 @@ uvx ruff check .
69
77
  ```
70
78
 
71
79
  [typechecking]: /contributing/typechecking/
80
+ [bun]: https://bun.com/docs
@@ -38,6 +38,5 @@ render-engine build app:app
38
38
 
39
39
  Your site will be generated in the `output` folder.
40
40
 
41
- [cli-build]: ../cli.md#building-your-site-with-render-engine-build
42
-
41
+ [cli-build]: ../cli/docs/cli.md#building-your-site-with-render-engine-build
43
42
  [layout]: layout.md
@@ -30,6 +30,6 @@ Visit the [CLI - init] page for more information.
30
30
 
31
31
  ### Continue to [Simple Site Layout]
32
32
 
33
- [cli - init]: ../cli.md
33
+ [cli - init]: ../cli/docs/cli.md
34
34
  [render-engine init --help]: ../assets/render-engine-init-help.png
35
35
  [simple site layout]: layout.md
@@ -5,10 +5,10 @@ date: August 22, 2024
5
5
  tags: ["installation", "render-engine"]
6
6
  ---
7
7
 
8
- In order to use render engine, you must have python 3.10 installed. You can download python from [python.org].
8
+ To use the render engine, you must have Python 3.10 or greater installed. You can download Python from [python.org].
9
9
 
10
10
  - Linux/MacOS: [python.org]
11
- - Windows: [Microsoft Store]
11
+ - Windows: Install Python using [pymanager on Microsoft Store][ms-store], which manages Python installations.
12
12
 
13
13
  Render Engine is available in PyPI and can be installed using pip:
14
14
 
@@ -35,5 +35,5 @@ pip install render-engine render-engine-rss
35
35
  [render-engine-rss]: https://pypi.org/project/render-engine-rss/
36
36
 
37
37
  [creating your app]: creating-your-app.md
38
- [microsoft store]: https://apps.microsoft.com/store/detail/python-311/9NRWMJP3717K
38
+ [ms-store]: https://apps.microsoft.com/detail/9NQ7512CXL7T
39
39
  [python.org]: https://python.org
@@ -16,10 +16,10 @@ tags:
16
16
 
17
17
  ### Installing Render Engine
18
18
 
19
- In order to use render engine, you must have python 3.10 installed. You can download python from [python.org].
19
+ To use the render engine, you must have Python 3.10 or greater installed. You can download Python from [python.org].
20
20
 
21
21
  - Linux/MacOS: [python.org]
22
- - Windows: [Microsoft Store]
22
+ - Windows: Install Python using [pymanager on Microsoft Store][ms-store], which manages Python installations.
23
23
 
24
24
  Render Engine is available in PyPI and can be installed using pip:
25
25
 
@@ -39,7 +39,7 @@ Check out the [Getting Started].
39
39
 
40
40
  [collection]: collection.md
41
41
  [getting started]: ./getting-started/getting-started.md
42
- [microsoft store]: https://apps.microsoft.com/store/detail/python-311/9NRWMJP3717K
42
+ [ms-store]: https://apps.microsoft.com/detail/9NQ7512CXL7T
43
43
  [page]: page.md
44
44
  [python.org]: https://python.org
45
45
  [site]: site.md
@@ -35,7 +35,7 @@ nav:
35
35
  - Plugins: plugins.md
36
36
  - Content Managers: content_manager.md
37
37
  - Parsers: parsers.md
38
- - CLI: cli.md
38
+ - CLI: cli/docs/cli.md
39
39
  - Templates and Themes:
40
40
  - Templates: templates.md
41
41
  - ThemeManager: theme_management.md
@@ -62,3 +62,10 @@ plugins:
62
62
  show_source: false
63
63
  show_root_full_path: false
64
64
  show_category_heading: true
65
+ - multirepo:
66
+ # (optional) tells multirepo to cleanup the temporary directory after site is built.
67
+ cleanup: true
68
+ nav_repos:
69
+ - name: CLI
70
+ import_url: https://github.com/render-engine/render-engine-cli?branch=main
71
+ imports: [/docs/cli.md]
@@ -27,6 +27,18 @@ test-cov-report REPORT='xml':
27
27
  nox:
28
28
  uvx nox
29
29
 
30
+ # Run markdown linter (requires bun or npm)
31
+ lint-md DIRECTORY=".":
32
+ #!/usr/bin/env sh
33
+ if command -v bun > /dev/null 2>&1; then
34
+ bunx markdownlint-cli2 {{ DIRECTORY }}
35
+ elif command -v npm > /dev/null 2>&1; then
36
+ npx markdownlint-cli2 {{ DIRECTORY }}
37
+ else
38
+ echo "Error: neither bun nor npm found. Install one of them to run markdown linting." >&2
39
+ exit 1
40
+ fi
41
+
30
42
  # Run ruff linter without fixing
31
43
  lint DIRECTORY='.':
32
44
  uvx ruff check {{ DIRECTORY }}
@@ -9,37 +9,40 @@ description = "A Flexible Static Site Generator for Python"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
11
11
  dependencies = [
12
- "jinja2",
13
- "more-itertools",
14
- "pluggy",
15
- "python-dateutil",
16
- "python-slugify",
17
- "render-engine-parser",
18
- "render-engine-markdown",
19
- "rich",
12
+ "jinja2==3.1.6",
13
+ "more-itertools==10.8.0",
14
+ "pluggy==1.6.0",
15
+ "python-dateutil==2.9.0.post0",
16
+ "python-frontmatter==1.1.0",
17
+ "python-slugify==8.0.4",
18
+ "render-engine-markdown==2023.12.1",
19
+ "rich==14.3.1",
20
20
  ]
21
21
 
22
22
  [project.optional-dependencies]
23
- cli = ["render-engine-cli"]
24
- extras = ["render-engine-sitemap"]
23
+ cli = ["render-engine-cli==2025.11.1"]
24
+ extras = ["render-engine-sitemap==2024.1.1a1"]
25
25
 
26
26
  [dependency-groups]
27
27
  dev = [
28
- "ephemeral-port-reserve",
28
+ "ephemeral-port-reserve==1.1.4",
29
29
  "deptry>=0.24.0",
30
- "httpx",
31
- "ty",
32
- "pre-commit",
33
- "pytest",
34
- "pytest-cov",
35
- "pytest-mock",
36
- "toml",
30
+ "httpx==0.28.1",
31
+ # TODO: Update typing with new versions in 0.0.24
32
+ # Issue URL: https://github.com/render-engine/render-engine/issues/1142
33
+ "ty==0.0.14",
34
+ "pre-commit==4.5.1",
35
+ "pytest==9.0.2",
36
+ "pytest-cov==7.0.0",
37
+ "pytest-mock==3.15.1",
38
+ "toml==0.10.2",
37
39
  ]
38
40
  docs = [
39
- "mkdocs",
40
- "mkdocs-material",
41
- "mkdocstrings[python]",
42
- "pymdown-extensions",
41
+ "mkdocs==1.6.1",
42
+ "mkdocs-material==9.7.6",
43
+ "mkdocs-multirepo-plugin==0.8.3",
44
+ "mkdocstrings[python]==1.0.3",
45
+ "pymdown-extensions==10.21",
43
46
  ]
44
47
 
45
48
  [tool.setuptools_scm]
@@ -2,6 +2,7 @@ from .blog import Blog
2
2
  from .collection import Collection
3
3
  from .data_object import DataObject
4
4
  from .page import Page
5
+ from .parsers import BasePageParser
5
6
  from .site import Site
6
7
 
7
- __all__ = ["Blog", "Collection", "Page", "Site", "DataObject"]
8
+ __all__ = ["Blog", "Collection", "Page", "Site", "DataObject", "BasePageParser"]
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '2026.3.4a2'
32
- __version_tuple__ = version_tuple = (2026, 3, 4, 'a2')
31
+ __version__ = version = '2026.3.4a3'
32
+ __version_tuple__ = version_tuple = (2026, 3, 4, 'a3')
33
33
 
34
- __commit_id__ = commit_id = 'g3cd8897ad'
34
+ __commit_id__ = commit_id = 'gbcfaed3c8'
@@ -9,7 +9,6 @@ from typing import Any, cast
9
9
 
10
10
  import dateutil.parser as dateparse
11
11
  from more_itertools import batched
12
- from render_engine_parser import BasePageParser
13
12
  from slugify import slugify
14
13
 
15
14
  from ._base_object import BaseObject
@@ -17,6 +16,7 @@ from .archive import Archive
17
16
  from .content_managers import ContentManager, FileContentManager
18
17
  from .feeds import RSSFeed
19
18
  from .page import Page
19
+ from .parsers import BasePageParser
20
20
  from .plugins import PluginManager
21
21
 
22
22
 
@@ -2,9 +2,8 @@
2
2
  Feed Objects for Generating RSS Feeds
3
3
  """
4
4
 
5
- from render_engine_parser import BasePageParser
6
-
7
5
  from .page import BasePage
6
+ from .parsers import BasePageParser
8
7
 
9
8
 
10
9
  class RSSFeed(BasePage):
@@ -4,11 +4,11 @@ from pathlib import Path
4
4
  from typing import Any, cast
5
5
 
6
6
  from jinja2 import Environment, Template
7
- from render_engine_parser.base_parsers import BasePageParser
8
7
 
9
8
  from render_engine.themes import ThemeManager
10
9
 
11
10
  from ._base_object import BaseObject
11
+ from .parsers import BasePageParser
12
12
  from .plugins import PluginManager
13
13
 
14
14
  logger = logging.getLogger("Page")
@@ -85,9 +85,11 @@ class BasePage(BaseObject):
85
85
  :param **kwargs: Data to pass into the template for rendering.
86
86
  :return: The rendered page
87
87
  """
88
+
88
89
  template_data = {"data": self._data, "content": self._content}
89
90
  if site := getattr(self, "site", None):
90
91
  template_data["site_map"] = site.site_map
92
+
91
93
  if not self.no_prerender and isinstance(self._content, str) and re.search(r"{{.*?site_map.*?}}", self._content):
92
94
  # If the content looks like a template, try to render it.
93
95
  try:
@@ -237,14 +239,14 @@ class Page(BasePage):
237
239
 
238
240
  # Parse Content from the Content Path or the Content
239
241
  if content_path := (content_path or getattr(self, "content_path", None)):
240
- self.metadata, self.content = self.Parser.parse_content_path(str(content_path))
242
+ self.metadata, self.content = self.Parser.parse_content_path(content_path)
241
243
 
242
244
  elif content := (content or getattr(self, "content", None)):
243
245
  self.metadata, self.content = self.Parser.parse_content(content)
244
246
 
245
247
  else:
246
248
  self.metadata = {}
247
- self.content = None
249
+ self.content = ""
248
250
 
249
251
  # Set the attributes
250
252
  for key, val in self.metadata.items():
@@ -260,4 +262,7 @@ class Page(BasePage):
260
262
  Returns:
261
263
  Any: The parsed content of the page.
262
264
  """
263
- return self.Parser.parse(self.content, extras=getattr(self, "parser_extras", {}))
265
+ content = getattr(self, "content", None)
266
+ if content:
267
+ return self.Parser.parse(content, extras=getattr(self, "parser_extras", {}))
268
+ return content
@@ -0,0 +1,3 @@
1
+ from .base_parsers import BasePageParser
2
+
3
+ __all__ = ["BasePageParser"]
@@ -0,0 +1,76 @@
1
+ import pathlib
2
+ from typing import Any
3
+
4
+ import frontmatter
5
+
6
+
7
+ def parse_content(content: str) -> tuple[dict, str]:
8
+ """Fetching content and atttributes from a content_path"""
9
+ p = frontmatter.parse(content)
10
+ return p
11
+
12
+
13
+ class BasePageParser:
14
+ """
15
+ The default Parser for Page objects.
16
+ This yields attributes and content using frontmatter.
17
+ The content is not modified.
18
+ """
19
+
20
+ @staticmethod
21
+ def parse_content_path(content_path: str | pathlib.Path) -> tuple[dict, str]:
22
+ """
23
+ Fetches content from `Page.content_path` and sets attributes.
24
+
25
+ This is a separate method so that it can be overridden by subclasses.
26
+
27
+ params:
28
+ content_path:
29
+ The path to the file that will be used to generate the Page's `content`.
30
+ Should be a valid path to a file or a url.
31
+ """
32
+ return parse_content(pathlib.Path(content_path).read_text())
33
+
34
+ @staticmethod
35
+ def parse_content(content: str) -> tuple[dict, str]:
36
+ """
37
+ Fetches content from `Page.content` and returns attributes and content.
38
+
39
+ This is a separate method so that it can be overridden by subclasses.
40
+
41
+ params:
42
+ content:
43
+ The path to the file that will be used to generate the Page's `content`.
44
+ Should be a valid path to a file or a url.
45
+ """
46
+
47
+ return parse_content(content)
48
+
49
+ @staticmethod
50
+ def parse(
51
+ content: str,
52
+ extras: dict[str, Any] | None = None,
53
+ ) -> str:
54
+ """
55
+ Parses content to be rendered into HTML
56
+
57
+ In the base parser, this returns the content as is.
58
+
59
+ params:
60
+ content: content to be rendered into HTML
61
+ extras: dictionary with extras to augment attributes
62
+ """
63
+ return content
64
+
65
+ @staticmethod
66
+ def create_entry(*, content: str = "Hello World", **kwargs) -> str:
67
+ """
68
+ Writes the content type that would be parsed to the content_path.
69
+ """
70
+
71
+ post = frontmatter.Post(content)
72
+
73
+ for key, val in kwargs.items():
74
+ post[key] = val
75
+
76
+ return frontmatter.dumps(post)