feat: Add tagging support for blog posts
All checks were successful
Build and Deploy Static Site / build (push) Successful in 7m54s
All checks were successful
Build and Deploy Static Site / build (push) Successful in 7m54s
Introduces tagging system that organizes posts by tags and generates dedicated tag index pages. Updates templates to display tags and streamlines tag page rendering.
This commit is contained in:
parent
020c916651
commit
c037d1d918
3 changed files with 77 additions and 18 deletions
|
@ -6,6 +6,8 @@ author: Kumi
|
||||||
author_url: https://kumi.website
|
author_url: https://kumi.website
|
||||||
license: CC BY-SA 4.0
|
license: CC BY-SA 4.0
|
||||||
license_url: https://creativecommons.org/licenses/by-sa/4.0/
|
license_url: https://creativecommons.org/licenses/by-sa/4.0/
|
||||||
|
tags: test
|
||||||
|
excerpt: This is the excerpt of a test post. It is displayed on the index pages.
|
||||||
---
|
---
|
||||||
This is a test post.
|
This is a test post.
|
||||||
|
|
||||||
|
|
85
main.py
85
main.py
|
@ -117,6 +117,8 @@ def generate_blog_html(template_kwargs={}, posts_per_page=5):
|
||||||
blog_dir = pathlib.Path("blog")
|
blog_dir = pathlib.Path("blog")
|
||||||
blog_posts = []
|
blog_posts = []
|
||||||
|
|
||||||
|
blog_tags = {}
|
||||||
|
|
||||||
for post_dir in blog_dir.iterdir():
|
for post_dir in blog_dir.iterdir():
|
||||||
if post_dir.is_dir():
|
if post_dir.is_dir():
|
||||||
md_path = post_dir / "index.md"
|
md_path = post_dir / "index.md"
|
||||||
|
@ -133,6 +135,7 @@ def generate_blog_html(template_kwargs={}, posts_per_page=5):
|
||||||
else:
|
else:
|
||||||
post_date = front_matter["date"]
|
post_date = front_matter["date"]
|
||||||
front_matter["date"] = post_date.strftime("%Y-%m-%d %H:%M:%S")
|
front_matter["date"] = post_date.strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
|
||||||
if post_date > datetime.datetime.now():
|
if post_date > datetime.datetime.now():
|
||||||
if not args.dev:
|
if not args.dev:
|
||||||
logging.info(f"Skipping future post: {post_dir.name}")
|
logging.info(f"Skipping future post: {post_dir.name}")
|
||||||
|
@ -143,6 +146,16 @@ def generate_blog_html(template_kwargs={}, posts_per_page=5):
|
||||||
front_matter["content"] = html_content
|
front_matter["content"] = html_content
|
||||||
front_matter["slug"] = post_dir.name
|
front_matter["slug"] = post_dir.name
|
||||||
|
|
||||||
|
# Add post to relevant tag lists
|
||||||
|
if "tags" in front_matter:
|
||||||
|
for tag in front_matter["tags"].split(","):
|
||||||
|
tag = tag.strip()
|
||||||
|
|
||||||
|
if tag not in blog_tags:
|
||||||
|
blog_tags[tag] = []
|
||||||
|
|
||||||
|
blog_tags[tag].append(front_matter)
|
||||||
|
|
||||||
# Create excerpt if not present
|
# Create excerpt if not present
|
||||||
if "excerpt" not in front_matter:
|
if "excerpt" not in front_matter:
|
||||||
excerpt = html_content.split("</p>")[0]
|
excerpt = html_content.split("</p>")[0]
|
||||||
|
@ -171,11 +184,32 @@ def generate_blog_html(template_kwargs={}, posts_per_page=5):
|
||||||
# Sort posts by date, descending
|
# Sort posts by date, descending
|
||||||
blog_posts.sort(key=lambda x: x.get("date", ""), reverse=True)
|
blog_posts.sort(key=lambda x: x.get("date", ""), reverse=True)
|
||||||
|
|
||||||
# Calculate total pages
|
# Render each individual post
|
||||||
|
for post in blog_posts:
|
||||||
|
post.setdefault("license", "CC BY-SA 4.0")
|
||||||
|
post.setdefault(
|
||||||
|
"license-url", "https://creativecommons.org/licenses/by-sa/4.0/"
|
||||||
|
)
|
||||||
|
post.setdefault("author", "Private.coffee Team")
|
||||||
|
post.setdefault("author-url", "https://private.coffee")
|
||||||
|
|
||||||
|
post["tags"] = [tag.strip() for tag in post.get("tags", "").split(",") if tag]
|
||||||
|
|
||||||
|
post_slug = post["slug"]
|
||||||
|
render_template_to_file(
|
||||||
|
"blog/post.html",
|
||||||
|
f"blog/{post_slug}/index.html",
|
||||||
|
**{**post, "relative_path": calculate_relative_path(2)},
|
||||||
|
**template_kwargs,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add tags to template kwargs
|
||||||
|
template_kwargs["tags"] = blog_tags.keys()
|
||||||
|
|
||||||
|
# Generate each index page
|
||||||
total_posts = len(blog_posts)
|
total_posts = len(blog_posts)
|
||||||
total_pages = math.ceil(total_posts / posts_per_page)
|
total_pages = math.ceil(total_posts / posts_per_page)
|
||||||
|
|
||||||
# Generate each index page
|
|
||||||
for page in range(total_pages):
|
for page in range(total_pages):
|
||||||
start = page * posts_per_page
|
start = page * posts_per_page
|
||||||
end = start + posts_per_page
|
end = start + posts_per_page
|
||||||
|
@ -199,22 +233,39 @@ def generate_blog_html(template_kwargs={}, posts_per_page=5):
|
||||||
"blog/index.html", "blog/page/1/index.html", **context
|
"blog/index.html", "blog/page/1/index.html", **context
|
||||||
)
|
)
|
||||||
|
|
||||||
# Render each individual post
|
# Generate tag pages
|
||||||
for post in blog_posts:
|
for tag, posts in blog_tags.items():
|
||||||
post.setdefault("license", "CC BY-SA 4.0")
|
tag_posts = sorted(posts, key=lambda x: x.get("date", ""), reverse=True)
|
||||||
post.setdefault(
|
total_tag_posts = len(tag_posts)
|
||||||
"license-url", "https://creativecommons.org/licenses/by-sa/4.0/"
|
total_tag_pages = math.ceil(total_tag_posts / posts_per_page)
|
||||||
)
|
|
||||||
post.setdefault("author", "Private.coffee Team")
|
|
||||||
post.setdefault("author-url", "https://private.coffee")
|
|
||||||
|
|
||||||
post_slug = post["slug"]
|
for page in range(total_tag_pages):
|
||||||
render_template_to_file(
|
start = page * posts_per_page
|
||||||
"blog/post.html",
|
end = start + posts_per_page
|
||||||
f"blog/{post_slug}/index.html",
|
paginated_posts = tag_posts[start:end]
|
||||||
**{**post, "relative_path": calculate_relative_path(2)},
|
context = {
|
||||||
**template_kwargs,
|
"posts": paginated_posts,
|
||||||
)
|
"current_page": page + 1,
|
||||||
|
"total_pages": total_tag_pages,
|
||||||
|
"tag": tag,
|
||||||
|
"relative_path": calculate_relative_path(3),
|
||||||
|
**template_kwargs,
|
||||||
|
}
|
||||||
|
output_path = (
|
||||||
|
f"blog/tag/{tag}/index.html"
|
||||||
|
if page == 0
|
||||||
|
else f"blog/tag/{tag}/page/{page + 1}/index.html"
|
||||||
|
)
|
||||||
|
render_template_to_file("blog/index.html", output_path, **context)
|
||||||
|
|
||||||
|
if page == 0:
|
||||||
|
pathlib.Path(f"build/blog/tag/{tag}/page/1").mkdir(
|
||||||
|
parents=True, exist_ok=True
|
||||||
|
)
|
||||||
|
context["relative_path"] = calculate_relative_path(5)
|
||||||
|
render_template_to_file(
|
||||||
|
"blog/index.html", f"blog/tag/{tag}/page/1/index.html", **context
|
||||||
|
)
|
||||||
|
|
||||||
logging.info("Blog section generated successfully.")
|
logging.info("Blog section generated successfully.")
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
{% endblock title %}
|
{% endblock title %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="container my-5">
|
<div class="container my-5">
|
||||||
<h1>Blog</h1>
|
<h1>Blog{% if tag %} index for tag {{ tag }}{% endif %}</h1>
|
||||||
<ul class="list-unstyled">
|
<ul class="list-unstyled">
|
||||||
{% for post in posts %}
|
{% for post in posts %}
|
||||||
<li class="d-flex align-items-center mb-4 p-3 border-bottom">
|
<li class="d-flex align-items-center mb-4 p-3 border-bottom">
|
||||||
|
@ -20,6 +20,12 @@
|
||||||
<a href="{{ relative_path }}blog/{{ post.slug }}/index.html">{{ post.title }}</a>
|
<a href="{{ relative_path }}blog/{{ post.slug }}/index.html">{{ post.title }}</a>
|
||||||
</h2>
|
</h2>
|
||||||
<small class="text-muted">by {{ post.author }}, published {{ post.date }}</small>
|
<small class="text-muted">by {{ post.author }}, published {{ post.date }}</small>
|
||||||
|
{% if post.tags %}
|
||||||
|
<br>
|
||||||
|
<small class="text-muted">tags:
|
||||||
|
{% for tag in post.tags %}<a href="{{ relative_path }}blog/tag/{{ tag }}">{{ tag }}</a>{% endfor %}
|
||||||
|
</small>
|
||||||
|
{% endif %}
|
||||||
<p>
|
<p>
|
||||||
{{ post.excerpt }} <a href="{{ relative_path }}blog/{{ post.slug }}/index.html">[read more]</a>
|
{{ post.excerpt }} <a href="{{ relative_path }}blog/{{ post.slug }}/index.html">[read more]</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue