from datetime import datetime import os import shutil import markdown import frontmatter from pathlib import Path from logger import logger from config import Config from jinja_env import env, content_item_template, index_template class ContentItem: def render_content(self): logger.debug(f"Rendering {self.source_filename} to {Config.OUTPUT_DIR}/{self.target_filename}") if self.image_file.exists(): shutil.copyfile(self.image_src_file, Path(Config.OUTPUT_DIR) / self.image) if self.css_file.exists(): shutil.copyfile(self.custom_css_src_file,Path(Config.OUTPUT_DIR) / self.custom_css) if self.js_file.exists(): shutil.copyfile(self.custom_js_src_file, Path(Config.OUTPUT_DIR) / self.custom_js) with self.target_filename.open("w", encoding="utf-8") as f: f.write(content_item_template.render(content_item = self, page_title = self.title)) def parse_content(self): try: self.source_filename = Path(self.source_filename) logger.debug(f"Parsing item {self.source_filename}") self.subdir = self.source_filename.parent self.slug = self.source_filename.stem self.target_filename = Path(f"{Config.OUTPUT_DIR}/{self.source_filename.parent}/{self.source_filename.stem}.html") self.data = frontmatter.load(self.source_filename) self.html = markdown.markdown(self.data.content.replace('\n', ' \n')) self.url = " ...read more" self.preview = self.html[:300] + self.url self.title = self.data.get("title", self.slug) self.omit_second_title = self.data.get("omit_second_title", False) self.date = self.data.get("date", "2000-01-01T00:00:00+03:00") self.categories = self.data.get("categories", str([])) self.hidden = self.data.get("hidden", str(False)) self.image_file = Path(self.source_filename.stem + ".jpg") self.css_file = Path(self.source_filename.stem + ".css") self.js_file = Path(self.source_filename.stem + ".js") except Exception as e: logger.error(e) def create_content(self): with open(self.source_filename, mode="w", encoding="utf-8") as f: f.writelines([ "---\n", f"title: {self.source_filename.stem}\n", f"date: '{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}'\n", "description: ''\n", "author: ''\n", "categories: ['default']\n", "hidden: 'False'\n", "omit_second_title: 'False'\n", "---\n", "\n\n\n" ]) def __init__(self, filename): self.source_filename = filename class Site: def init_site(): logger.info("Initializing new site") content_dir = Path(Config.CONTENT_DIR) static_dir = Path(Config.STATIC_DIR) templates_dir = Path(Config.TEMPLATES_DIR) images_dir = Path(f"{Config.STATIC_DIR}/images") css_dir = Path(f"{Config.STATIC_DIR}/css") js_dir = Path(f"{Config.STATIC_DIR}/js") # Create directories for subdir in [content_dir, static_dir, templates_dir, images_dir, css_dir, js_dir]: os.makedirs(subdir, exist_ok=True) # Create templates from literals import templates template_names = [t for t in dir(templates) if not t.startswith('_')] for template_name in template_names: template_content = getattr(templates, template_name) with open(templates_dir / f"{template_name}.html", "w", encoding="utf8") as f: f.write(template_content) # Create static/about.md def build_site(self): # Recreate the output dir if needed if output_dir.exists(): shutil.rmtree(output_dir) output_dir.mkdir() # Create public subdirs subdirs = [img_dir, css_dir, js_dir] for subdir in subdirs: subdir.mkdir(arents=True, exist_ok=True) # Copy static files if exist if static_dir.exists(): shutil.copytree(static_dir, output_dir / "static", dirs_exist_ok=True) # Parse the content files content_items = [] for md_file in content_dir.glob("*.md"): current_content_item = ContentItemPrototype(md_file) current_content_item.render_content() content_items.append({ "slug": current_content_item.slug, "title": current_content_item.title, "date": current_content_item.date, # "preview": markdown.markdown(current_content_item.preview), "image": current_content_item.image, }) # Render the index file with (output_dir / "index.html").open("w", encoding="utf-8") as f: f.write(index_template.render(page_title = Config.MAIN_PAGE_TITLE, content_items=content_items)) # Render the about file about_content = ContentItemPrototype(Path('static/about.md')) about_content.render_content() # Move 'robots.txt' into output_dir shutil.copyfile(static_dir / 'robots.txt', output_dir / 'robots.txt') logger.info(f"Created {len(content_items)} content items.") def __init__(self): self.output_dir = Path(Config.OUTPUT_DIR)