personal garden & website
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

223 lines
8.4 KiB

6 months ago
import os
5 months ago
import random
6 months ago
import markdown
import re
from jinja2 import Environment, FileSystemLoader
import yaml
import time
6 months ago
import json
2 months ago
from datetime import datetime
6 months ago
class Website:
def __init__(self, template_dir, public_dir):
self.template_dir_root = template_dir
self.public_dir = public_dir
self.output_dir_root = 'public/articles'
self.env = Environment(loader=FileSystemLoader(self.template_dir_root))
self.pages = []
self.tags = []
self.all_images = []
self.about_meta, self.about_content, self.about_modified_time = self.fetch_page('content', 'about.md')
6 months ago
def build(self):
self.fetch_pages()
2 months ago
self.sort_pages_by_date()
6 months ago
self.process_page()
self.fetch_tags()
self.create_list()
self.build_about()
self.build_campfire()
6 months ago
self.fetch_all_images()
self.create_json('public/json/articles.json')
def fetch_pages(self):
for page in os.listdir('content/posts'):
if page.endswith('.md'):
with open(os.path.join('content/posts', page), 'r', encoding="utf8") as f:
content = f.read()
file_desc = f.fileno()
file_status = os.fstat(file_desc)
6 months ago
parts = content.split('---')
metadata = yaml.safe_load(parts[1])
md_content = ''.join(parts[2:])
md_content = re.sub(r'\(([^)]+)\)\[([^\]]+)\]', r'<a href="\2">\1</a>', md_content)
md_content = self.format_content(md_content)
html_content = markdown.markdown(md_content)
output_filename = os.path.splitext(page)[0] + '.html'
new_page = Page(metadata, html_content, output_filename, file_status)
6 months ago
self.pages.append(new_page)
def process_page(self):
template = self.env.get_template('article.html')
self.check_output_dir()
for page in self.pages:
metadata = page.get_metadata()
filename = page.get_filename()
html_content = page.get_content()
html_output = template.render(
title=metadata.get('title', ''),
year=metadata.get('year', ''), # Assuming year is a string
date=metadata.get('date', ''), # Assuming date is a string
tags=metadata.get('tags', []),
image=metadata.get('image', ''), # Assuming image is a string
showcase=metadata.get('showcase', []),
credits=metadata.get('credits', []), # Assuming credits is a string
modified_time=page.get_modified_time_readable(),
6 months ago
content=html_content)
with open(os.path.join(self.output_dir_root, filename), 'w', encoding='utf8') as output_file:
output_file.write(html_output)
def check_output_dir(self):
if not os.path.exists(self.output_dir_root):
os.makedirs(self.output_dir_root)
def fetch_page(self, dir, page):
for about in os.listdir(dir):
if about == page:
with open(os.path.join(dir, about), 'r', encoding='utf8') as f:
content = f.read()
parts = content.split('---')
metadata = yaml.safe_load(parts[1])
md_content = ''.join(parts[2:])
6 months ago
md_content = re.sub(r'\(([^)]+)\)\[([^\]]+)\]', r'<a href="\2" target="_blank">\1</a>', md_content)
6 months ago
html_content = markdown.markdown(md_content)
about_modified_time = time.ctime(os.fstat(f.fileno()).st_mtime)
return metadata, html_content, about_modified_time
6 months ago
def create_list(self):
template = self.env.get_template('list.html')
self.check_output_dir()
html_output = template.render(
tags=self.tags,
pages=self.pages
)
with open(os.path.join('public', 'list.html'), 'w', encoding='utf8') as output_file:
output_file.write(html_output)
def fetch_tags(self):
for page in self.pages:
page_tags = page.get_tags()
for tag in page_tags:
if tag not in self.tags:
self.tags.append(tag)
def build_about(self):
template = self.env.get_template('about.html')
html_output = template.render(
content=self.about_content,
socials=self.about_meta,
modified_time = self.about_modified_time
6 months ago
)
with open(os.path.join('public', 'about.html'), 'w', encoding='utf8') as output_file:
output_file.write(html_output)
def build_campfire(self):
template = self.env.get_template('campfire.html')
html_output = template.render(
content=None
)
6 months ago
def format_content(self, content):
# convert all (link)(src) to <a> tags
6 months ago
content = re.sub(r'\(([^)]+)\)\[([^\]]+)\]', r'<a href="\2" target="_blank">\1</a>', content)
# convert all video links to embedded code
6 months ago
return content
def fetch_all_images(self):
dir = 'public/images'
template = self.env.get_template('gallery.html')
image_extensions = ('.png', '.jpg', '.jpeg', '.gif', '.webp')
for dirpath, _, filename in os.walk(dir):
for filename in filename:
if filename.lower().endswith(image_extensions):
relative_path = os.path.relpath(dirpath, dir).replace("\\", "/")
image_path = os.path.join('/images', relative_path, filename).replace("\\", "/")
if image_path.startswith("/images/."):
image_path = image_path.replace("/images/.", "/images")
self.all_images.append(image_path)
5 months ago
random.shuffle(self.all_images)
6 months ago
html_output = template.render(
images=self.all_images
)
with open(os.path.join('public', 'gallery.html'), 'w', encoding='utf8') as output_file:
output_file.write(html_output)
def create_json(self, json_file):
page_info_list = []
for page in self.pages:
page_info = {
'name': page.get_title(),
'filename': '/articles/' + page.get_filename(),
'image': page.get_image()
}
page_info_list.append(page_info)
with open(json_file, 'w', encoding='utf8') as f:
json.dump(page_info_list, f, ensure_ascii=False, indent=4)
2 months ago
def sort_pages_by_date(self):
# Sort pages by date in descending order (newest first)
self.pages.sort(key=lambda x: x.date, reverse=True)
6 months ago
class Page:
def __init__(self, metadata, md_content, filename, last_updated):
6 months ago
self.metadata = metadata
self.content = md_content
self.filename = filename
self.last_updated = last_updated
6 months ago
self.title = self.metadata['title']
self.type = self.metadata['type']
self.year = self.metadata['year']
self.image_src = self.metadata['image']
self.tags = self.metadata['tags']
self.date = self.metadata['date']
self.showcase = self.metadata.get('showcase', {})
6 months ago
self.credits = self.metadata.get('credits', {})
self.references = self.metadata.get('references', [])
self.isDraft = self.metadata['draft']
def get_metadata(self):
return self.metadata
def get_content(self):
return self.content
def get_filename(self):
return self.filename
def get_title(self):
return self.title
def get_tags(self):
return self.tags
def get_year(self):
return self.year
def get_image(self):
return self.image_src
def get_references(self):
return self.references
def get_src(self):
return os.path.splitext(self.filename)[0]
def display_metadata(self):
output = f"Title: {self.title}\nYear: {self.year}\nDate: {self.date}\nTags: {self.tags}\nType: {self.type}"
print(output)
def get_modified_time_readable(self):
if self.last_updated is not None:
last_modified_time = self.last_updated.st_mtime
last_modified_time_readable = time.ctime(last_modified_time)
return last_modified_time_readable
return None
6 months ago
def main():
inst = Website('templates', 'public')
inst.build()
if __name__ == "__main__":
main()