summaryrefslogtreecommitdiff
path: root/blog
diff options
context:
space:
mode:
authorDmitry Ilvokhin <d@ilvokhin.com>2022-12-24 18:10:17 +0000
committerDmitry Ilvokhin <d@ilvokhin.com>2022-12-24 18:10:17 +0000
commit54ac714da7175a8a08239e500a4e75a48b97d97e (patch)
tree8fa4bb4e7d37f2b6eff7068d47a58ca2ad93f18d /blog
downloadblog-54ac714da7175a8a08239e500a4e75a48b97d97e.tar.gz
blog-54ac714da7175a8a08239e500a4e75a48b97d97e.tar.bz2
blog-54ac714da7175a8a08239e500a4e75a48b97d97e.zip
Initial version of generator
Generation of feed page and post pages are supported. Markdown to html conversion seems working. At least there is nothing strange with hello-world example.
Diffstat (limited to 'blog')
-rw-r--r--blog/__init__.py0
-rw-r--r--blog/blog.py53
-rw-r--r--blog/feed.py14
-rw-r--r--blog/post.py71
-rw-r--r--blog/render.py16
5 files changed, 154 insertions, 0 deletions
diff --git a/blog/__init__.py b/blog/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/blog/__init__.py
diff --git a/blog/blog.py b/blog/blog.py
new file mode 100644
index 0000000..cb6ab1e
--- /dev/null
+++ b/blog/blog.py
@@ -0,0 +1,53 @@
+#! /usr/bin/env python3
+# -*- coding: utf-8 -*
+
+import os
+import shutil
+
+from jinja2 import Environment, FileSystemLoader, select_autoescape
+
+from post import Post
+from feed import Feed
+
+
+def recreate_workdir(basedir):
+ if os.path.exists(basedir):
+ shutil.rmtree(basedir)
+ os.makedirs(basedir)
+
+
+def find_posts(template, basedir):
+ posts = []
+ for subdir in os.listdir(basedir):
+ posts.append(Post(template, os.path.join(basedir, subdir)))
+ return posts
+
+
+def generate_blog(include_drafts=False):
+ env = Environment(loader=FileSystemLoader(searchpath="templates"),
+ autoescape=select_autoescape())
+
+ posts = find_posts(env.get_template("post.html"),
+ os.path.join("posts", "public"))
+
+ if include_drafts:
+ drafts = find_posts(env.get_template("post.html"),
+ os.path.join("posts", "drafts"))
+ posts.extend(drafts)
+
+ workdir = "remote"
+ recreate_workdir(workdir)
+
+ for post in posts:
+ post.generate(workdir)
+
+ feed = Feed(env.get_template("feed.html"), posts)
+ feed.generate(workdir)
+
+
+def main():
+ generate_blog(include_drafts=True)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/blog/feed.py b/blog/feed.py
new file mode 100644
index 0000000..d8ffc8c
--- /dev/null
+++ b/blog/feed.py
@@ -0,0 +1,14 @@
+import os
+
+import render
+
+
+class Feed(object):
+ def __init__(self, template, posts):
+ self.template = template
+ self.posts = posts
+
+ def generate(self, basedir):
+ index = os.path.join(basedir, "index.html")
+ rendered = self.template.render(posts=self.posts)
+ render.write_file_content(index, rendered)
diff --git a/blog/post.py b/blog/post.py
new file mode 100644
index 0000000..1d35b6c
--- /dev/null
+++ b/blog/post.py
@@ -0,0 +1,71 @@
+import os
+import shutil
+import datetime
+import functools
+
+import render
+
+
+class Metadata(object):
+ __slots__ = ("title", "date", "status")
+
+ def __init__(self, title, date, status):
+ self.title = title
+ self.date = date
+ self.status = status
+
+
+class Post(object):
+ def __init__(self, template, directory):
+ self.template = template
+ self.directory = directory
+ self.name = os.path.basename(directory)
+
+ @staticmethod
+ def _load_raw_metadata(filename):
+ data = {}
+
+ with open(filename) as f:
+ for line in f:
+ k, v = line.strip().split(": ")
+ data[k] = v
+
+ return data
+
+ @functools.cached_property
+ def metadata(self):
+ raw = Post._load_raw_metadata(os.path.join(self.directory,
+ "metadata.txt"))
+
+ title = raw["Title"]
+ date = raw.get("Date", datetime.date.today().strftime("%Y-%m-%d"))
+ status = raw.get("Status", "draft")
+
+ return Metadata(title, date, status)
+
+ def is_draft(self):
+ return self.metadata.status == "draft"
+
+ def generate(self, basedir):
+ 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}`"
+
+ body = render.to_html(md)
+ rendered = self.template.render(title=self.metadata.title,
+ date=self.metadata.date,
+ body=body)
+ render.write_file_content(os.path.join(workdir, "index.html"),
+ rendered)
diff --git a/blog/render.py b/blog/render.py
new file mode 100644
index 0000000..4e26318
--- /dev/null
+++ b/blog/render.py
@@ -0,0 +1,16 @@
+import markdown
+
+
+def read_file_content(filename):
+ with open(filename) as f:
+ return f.read()
+
+
+def write_file_content(filename, data):
+ with open(filename, mode='w') as f:
+ f.write(data)
+
+
+def to_html(filename):
+ text = read_file_content(filename)
+ return markdown.markdown(text, extensions=["fenced_code", "footnotes"])