diff options
author | Dmitry Ilvokhin <d@ilvokhin.com> | 2025-04-19 21:43:53 +0100 |
---|---|---|
committer | Dmitry Ilvokhin <d@ilvokhin.com> | 2025-04-19 21:43:53 +0100 |
commit | 96d437baab4a622eb540719feb90ea810fb01756 (patch) | |
tree | 8757d41e9e2c673965483b2466ae306c9a7b8368 /blog | |
parent | ea523d411689338876abd7b87d85164009e7ec73 (diff) | |
download | blog-master.tar.gz blog-master.tar.bz2 blog-master.zip |
Date format was changed to support `updated` in ISO format. Now every
post will require date and time, which might be a usability regression,
but we'll see. Also, `updated` field was introduced in metadata. If
there is no such field, them date field will be used instead.
Diffstat (limited to 'blog')
-rw-r--r-- | blog/atom.py | 34 | ||||
-rw-r--r-- | blog/blog.py | 4 | ||||
-rw-r--r-- | blog/feed.py | 9 | ||||
-rw-r--r-- | blog/post.py | 50 |
4 files changed, 70 insertions, 27 deletions
diff --git a/blog/atom.py b/blog/atom.py new file mode 100644 index 0000000..e6d836c --- /dev/null +++ b/blog/atom.py @@ -0,0 +1,34 @@ +import os +import datetime +import functools +from typing import List + +from jinja2 import Template + +import render +from post import Post, remove_drafts + + +class Atom(object): + template: Template + posts: List[Post] + + def __init__(self, template: Template, posts: List[Post]) -> None: + self.template = template + self.posts = remove_drafts(posts) + + @staticmethod + def _now() -> datetime.datetime: + now = datetime.datetime.now(datetime.timezone.utc) + return now.replace(microsecond=0) + + @functools.cached_property + def updated(self) -> datetime.datetime: + if not self.posts: + return self._now() + return self.posts[0].metadata.updated + + def generate(self, basedir: str) -> None: + atom = os.path.join(basedir, "atom.xml") + rendered = self.template.render(updated=self.updated, posts=self.posts) + render.write_file_content(atom, rendered) diff --git a/blog/blog.py b/blog/blog.py index 27845bc..4b9a345 100644 --- a/blog/blog.py +++ b/blog/blog.py @@ -10,6 +10,7 @@ from jinja2 import Template, Environment, FileSystemLoader, select_autoescape from post import Post from feed import Feed +from atom import Atom def recreate_workdir(basedir: str) -> None: @@ -49,6 +50,9 @@ def generate_blog() -> None: feed = Feed(env.get_template("feed.html"), posts) feed.generate(workdir) + atom = Atom(env.get_template("atom.xml"), posts) + atom.generate(workdir) + copy_share(workdir) diff --git a/blog/feed.py b/blog/feed.py index 3e5b2e0..381aab6 100644 --- a/blog/feed.py +++ b/blog/feed.py @@ -1,10 +1,11 @@ import os +import datetime from typing import List from jinja2 import Template import render -from post import Post +from post import Post, remove_drafts class Feed(object): @@ -13,11 +14,7 @@ class Feed(object): def __init__(self, template: Template, posts: List[Post]) -> None: self.template = template - self.posts = Feed._remove_drafts(posts) - - @staticmethod - def _remove_drafts(posts: List[Post]) -> List[Post]: - return list(filter(lambda x: x.metadata.status != "draft", posts)) + self.posts = remove_drafts(posts) def generate(self, basedir: str) -> None: index = os.path.join(basedir, "index.html") diff --git a/blog/post.py b/blog/post.py index 8a7c880..955724a 100644 --- a/blog/post.py +++ b/blog/post.py @@ -2,27 +2,23 @@ import os import shutil import datetime import functools -from typing import Dict +from typing import Dict, List from jinja2 import Template +from dataclasses import dataclass + import render +@dataclass(slots=True) class Metadata(object): - __slots__ = ("title", "author", "date", "status") title: str author: str - date: str + date: datetime.datetime + updated: datetime.datetime status: str - def __init__(self, title: str, author: str, - date: str, status: str) -> None: - self.title = title - self.author = author - self.date = date - self.status = status - class Post(object): template: Template @@ -52,33 +48,45 @@ class Post(object): title = raw["Title"] author = raw["Author"] - date = raw.get("Date", datetime.date.today().strftime("%Y-%m-%d")) + date = raw["Date"] + updated = raw.get("Updated", date) status = raw.get("Status", "draft") - return Metadata(title, author, date, status) + return Metadata( + title, + author, + datetime.datetime.fromisoformat(date), + datetime.datetime.fromisoformat(updated), + status + ) + + @functools.cached_property + def content(self) -> str: + md = None + for filename in os.listdir(self.directory): + if filename.endswith(".md"): + return render.to_html(os.path.join(self.directory, filename)) + assert False, f"There is no markdown file in `{self.directory}`" def generate(self, basedir: str) -> None: postdir = os.path.basename(self.directory) workdir = os.path.join(basedir, postdir) os.makedirs(workdir) - md = None for filename in os.listdir(self.directory): source = os.path.join(self.directory, filename) destination = os.path.join(workdir, filename) - shutil.copy(source, destination) - if filename.endswith(".md"): - md = source - - assert md, f"There is no markdown file in `{self.directory}`" - - content = render.to_html(md) rendered = self.template.render(title=self.metadata.title, author=self.metadata.author, date=self.metadata.date, + updated=self.metadata.updated, status=self.metadata.status, - content=content) + content=self.content) render.write_file_content(os.path.join(workdir, "index.html"), rendered) + + +def remove_drafts(posts: List[Post]) -> List[Post]: + return list(filter(lambda x: x.metadata.status != "draft", posts)) |