Source code for nefelibata.builders.categories
import logging
from collections import defaultdict
from pathlib import Path
from typing import Optional
from jinja2 import Environment
from jinja2 import FileSystemLoader
from nefelibata import __version__
from nefelibata.builders import Builder
from nefelibata.builders import Scope
from nefelibata.builders.utils import hash_n
from nefelibata.builders.utils import random_color
from nefelibata.post import get_posts
_logger = logging.getLogger(__name__)
[docs]class CategoriesBuilder(Builder):
scopes = [Scope.SITE]
[docs] def process_site(self, force: bool = False) -> None:
"""Generate pages for each category.
"""
_logger.info("Creating categories pages")
env = Environment(
loader=FileSystemLoader(
str(self.root / "templates" / self.config["theme"]),
),
)
template = env.get_template("index.html")
posts = get_posts(self.root)
categories = defaultdict(list)
for post in posts:
for category in post.parsed.get("keywords", "").split(","):
categories[category.strip()].append(post)
for category, posts in categories.items():
posts.sort(key=lambda x: x.date, reverse=True)
last_modified = max(post.file_path.stat().st_mtime for post in posts)
show = self.config.get("posts-to-show", 10)
# first page; these will be updated
page = 1
name: Optional[str] = f"{category}.html"
previous: Optional[str] = None
while name:
page_posts, posts = posts[:show], posts[show:]
file_path = self.root / "build" / name
# only update if there are changes to files in this category
if (
not force
and file_path.exists()
and file_path.stat().st_mtime > last_modified
):
break
# link to next page
next = f"{category}{page}.html" if posts else None
html = template.render(
__version__=__version__,
config=self.config,
language=self.config["language"],
posts=page_posts,
breadcrumbs=[
("Home", "/index.html"),
(f'Posts about "{category}"', None),
],
previous=previous,
next=next,
hash_n=hash_n,
random_color=random_color,
)
with open(file_path, "w") as fp:
fp.write(html)
page += 1
previous, name = name, next