diff options
Diffstat (limited to 'blog')
| -rw-r--r-- | blog/__init__.py | 0 | ||||
| -rw-r--r-- | blog/blog.py | 53 | ||||
| -rw-r--r-- | blog/feed.py | 14 | ||||
| -rw-r--r-- | blog/post.py | 71 | ||||
| -rw-r--r-- | blog/render.py | 16 | 
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"]) |