import csv import os import pathlib import shutil import http.server import socketserver from jinja2 import Environment, FileSystemLoader, select_autoescape import yaml import frontmatter import markdown import fire translations = {} def copy_file(src, dst): os.makedirs(os.path.dirname(dst), exist_ok=True) shutil.copy2(src, dst) def load_translations(file_path, _dict): with open(file_path) as f: reader = csv.DictReader(f, delimiter='|') for row in reader: _dict[row['id']] = row del row['id'] def translate(id, language): global translations return translations[id][language] def develop(): PORT = 8000 os.chdir('public') handler = http.server.SimpleHTTPRequestHandler server = socketserver.TCPServer(("", PORT), handler) print("Server started at port 8000. Press CTRL+C to close the server.") try: server.serve_forever() except KeyboardInterrupt: server.server_close() print("Server Closed") def site_creator(prod=False): global translations # Read config of site with open('config.yaml', 'r') as file: config = yaml.safe_load(file) # Load theme's jinja templates templates = Environment(loader=FileSystemLoader( f"themes/{config['theme']}/templates/"), autoescape=select_autoescape()) # Load base jinja template base = templates.get_template("base.j2") # Load translations load_translations(f"themes/{config['theme']}/i18n.csv", translations) load_translations("i18n.csv", translations) # Add functions to base template base.globals.update({"translate": translate}) # Remove public folder if exists before generating new content shutil.rmtree('public', ignore_errors=True) posts = {} # Create new public folder for language in config['languages']: path = f"content/{language}" content_dir = pathlib.Path(path) content_files = content_dir.rglob("*.md") posts[language] = {} # Create posts dict for item in list(content_files): with open(item, 'r') as f: data = frontmatter.loads(f.read()) post_path = str(item).replace( "content", "public").rstrip(".md") os.makedirs(post_path, exist_ok=True) content = "{% import 'shortcodes.j2' as shortcodes %}" + \ markdown.markdown(data.content) content = templates.from_string(content).render() description = content.partition('')[0] url = post_path.replace(f"public/{language}", "") section = url.split('/')[1] if not os.path.dirname(url) == "/": posts[language].setdefault(section, {}) posts[language][section][url] = { 'title': data['title'], 'description': description, 'date': data['date'], 'content': content } image = data.get('image', None) if image: posts[language][section][url]['image'] = image copy_file(f'assets{image}', f'public{image}') for section, urls in posts[language].items(): html = base.render(config=config, section=section, language=language, posts=posts) with open(f"public/{language}/{section}/index.html", 'w') as f: f.write(html) for url, post in urls.items(): html = base.render(config=config, post=post, language=language, url=url, posts=posts) with open(f"public/{language}{url}/index.html", 'w') as f: f.write(html) html = base.render(config=config, posts=posts, language=language, home=True) with open(f"public/{language}/index.html", 'w') as f: f.write(html) shutil.copytree('static', 'public', dirs_exist_ok=True) shutil.copytree( f"themes/{config['theme']}/static", 'public', dirs_exist_ok=True) if not prod: develop() if __name__ == '__main__': fire.Fire(site_creator)