import os import markdown import re from jinja2 import Environment, FileSystemLoader import yaml import json 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.fetch_page('content', 'about.md') def build(self): self.fetch_pages() self.process_page() self.fetch_tags() self.create_list() self.build_about() 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() parts = content.split('---') metadata = yaml.safe_load(parts[1]) md_content = ''.join(parts[2:]) md_content = re.sub(r'\(([^)]+)\)\[([^\]]+)\]', r'\1', 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) 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['title'], year=metadata['year'], date=metadata['date'], tags=metadata.get('tags', []), image=metadata['image'], showcase=metadata['showcase'], credits=metadata['credits'], references=page.get_references(), 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:]) md_content = re.sub(r'\(([^)]+)\)\[([^\]]+)\]', r'\1', md_content) html_content = markdown.markdown(md_content) return metadata, html_content 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 ) with open(os.path.join('public', 'about.html'), 'w', encoding='utf8') as output_file: output_file.write(html_output) def format_content(self, content): # convert all (link)(src) to tags content = re.sub(r'\(([^)]+)\)\[([^\]]+)\]', r'\1', content) 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) 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) class Page: def __init__(self, metadata, md_content, filename): self.metadata = metadata self.content = md_content self.filename = filename 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', []) 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 main(): inst = Website('templates', 'public') inst.build() if __name__ == "__main__": main()