-
Notifications
You must be signed in to change notification settings - Fork 0
/
generate.py
89 lines (73 loc) · 2.86 KB
/
generate.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import os
from jinja2 import Environment, FileSystemLoader
import markdown
from datetime import datetime
class Post:
def __init__(self, title, date, content, url):
self.title = title
self.date = date
self.content = content
self.url = url
class PostLoader:
def __init__(self, posts_dir):
self.posts_dir = posts_dir
def load_posts(self):
posts = []
for filename in os.listdir(self.posts_dir):
if filename.endswith(".md"):
post = self._parse_markdown_file(
os.path.join(self.posts_dir, filename)
)
posts.append(post)
return sorted(posts, key=lambda x: x.date, reverse=True)
def _parse_markdown_file(self, filepath):
with open(filepath, "r") as file:
content = file.read()
md = markdown.Markdown(
extensions=[
"meta",
"extra",
"nl2br",
"tables",
"markdown_checklist.extension",
]
)
html_content = md.convert(content)
title = md.Meta["title"][0]
date = datetime.strptime(md.Meta["date"][0], "%Y-%m-%d")
url = f"{os.path.basename(filepath)[:-3]}.html"
return Post(title, date, html_content, url)
class Renderer:
def __init__(self, template_dir, output_dir):
self.env = Environment(loader=FileSystemLoader(template_dir))
self.output_dir = output_dir
def render_index(self, posts):
template = self.env.get_template("index.html")
output_path = os.path.join(self.output_dir, "index.html")
self._render_template(template, output_path, posts=posts)
def render_post(self, post):
template = self.env.get_template("post.html")
output_path = os.path.join(self.output_dir, post.url)
self._render_template(template, output_path, post=post)
def _render_template(self, template, output_path, **context):
os.makedirs(os.path.dirname(output_path), exist_ok=True)
with open(output_path, "w") as f:
f.write(template.render(**context))
class SiteGenerator:
def __init__(self, posts_dir, template_dir, output_dir):
self.posts_dir = posts_dir
self.template_dir = template_dir
self.output_dir = output_dir
self.post_loader = PostLoader(posts_dir)
self.renderer = Renderer(template_dir, output_dir)
def generate_site(self):
posts = self.post_loader.load_posts()
self.renderer.render_index(posts)
for post in posts:
self.renderer.render_post(post)
if __name__ == "__main__":
posts_dir = "posts"
template_dir = "templates"
output_dir = "output"
generator = SiteGenerator(posts_dir, template_dir, output_dir)
generator.generate_site()