This commit is contained in:
Digital Studium 2023-07-23 11:30:22 +03:00
parent 5fd1b91eba
commit c5d7d48492
2 changed files with 81 additions and 64 deletions

144
crater.py
View File

@ -1,10 +1,12 @@
import csv
import os
import pathlib
import shutil
import http.server
import socketserver
from functools import partial
from http.server import HTTPServer, SimpleHTTPRequestHandler
from pathlib import Path
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
from jinja2 import Environment, FileSystemLoader, select_autoescape
import yaml
import frontmatter
@ -12,45 +14,65 @@ import markdown
import fire
translations = {}
def copy_file(src, dst):
os.makedirs(os.path.dirname(dst), exist_ok=True)
shutil.copy2(src, dst)
from common.functions import *
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']
reader = csv.DictReader(f, delimiter='|') #
for row in reader: # проходим по строкам csv, каждая из которых является словарём
_dict[row['id']] = row # добавляем ключ - значение ключа id, значение - словарь row
del row['id'] # удаляем ключ по названием "id" из словаря row, так как его значение уже является ключом в словаре _dict
# Функции, доступные в теме
def translate(id, language):
global translations
return translations[id][language]
translations = {} # здесь будут переводы от темы и от сайта
config = yaml.safe_load(read_file('config.yaml')) # Чиатем конфиг сайта
running = False # нужно для проверки
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")
# класс для watchdog.
# При обнаружении изменений в папках content и themes/{config['theme']}, перегенерировать папку public
class Develop(FileSystemEventHandler):
def on_modified(self, event):
print(f'event type: {event.event_type} path : {event.src_path}')
crater()
def on_created(self, event):
print(f'event type: {event.event_type} path : {event.src_path}')
crater()
def on_deleted(self, event):
print(f'event type: {event.event_type} path : {event.src_path}')
crater()
def site_creator(prod=False):
global translations
# Read config of site
with open('config.yaml', 'r') as file:
config = yaml.safe_load(file)
# Функция для запуска веб-сервера
def start_httpd(directory: Path, port: int = 8000):
print(f"Listen on port {port}, serving from {directory}...")
handler = partial(SimpleHTTPRequestHandler, directory=directory)
httpd = HTTPServer(('localhost', port), handler)
httpd.serve_forever()
# Функция для запуска разработки
def develop(prod):
global running
if not prod and not running:
event_handler = Develop()
observer = Observer()
observer.schedule(event_handler, path='content', recursive=True)
observer.schedule(event_handler, path=f"themes/{config['theme']}", recursive=True)
observer.start()
running = True
try:
start_httpd(directory='public')
except KeyboardInterrupt:
pass
# Функция для генерации сайта
def crater(prod=False):
# Load theme's jinja templates
templates = Environment(loader=FileSystemLoader(
f"themes/{config['theme']}/templates/"), autoescape=select_autoescape())
@ -59,6 +81,7 @@ def site_creator(prod=False):
base = templates.get_template("base.j2")
# Load translations
global translations
load_translations(f"themes/{config['theme']}/i18n.csv", translations)
load_translations("i18n.csv", translations)
@ -71,69 +94,62 @@ def site_creator(prod=False):
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")
content_dir = Path(f"content/{language}")
posts[language] = {}
# Create posts dict
for item in list(content_files):
with open(item, 'r') as f:
data = frontmatter.loads(f.read())
for item in list(content_dir.rglob("*.md")):
post_data = frontmatter.loads(read_file(item))
post_path = str(item).replace(
"content", "public").rstrip(".md")
os.makedirs(post_path, exist_ok=True)
description = post_data.content.partition('<!--more-->')[0]
content = "{% import 'shortcodes.j2' as shortcodes %}" + \
markdown.markdown(data.content)
markdown.markdown(post_data.content)
content = templates.from_string(content).render()
description = content.partition('<!--more-->')[0]
content = templates.from_string(content).render()
url = post_path.replace(f"public/{language}", "")
section = url.split('/')[1]
section = "/" if len(url.split('/')) == 2 else url.split('/')[1]
if not os.path.dirname(url) == "/":
posts[language].setdefault(section, {})
posts[language].setdefault(section, {})
posts[language][section][url] = {
'title': data['title'],
'description': description,
'date': data['date'],
'content': content
}
posts[language][section][url] = {
'title': post_data['title'],
'description': description,
'date': post_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}')
image = post_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)
if section != "/":
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)
write_file(f"public/{language}/{section}/index.html", 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)
write_file(f"public/{language}{url}/index.html", 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)
write_file(f"public/{language}/index.html", 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()
for source_folder in ('static', f"themes/{config['theme']}/static"):
shutil.copytree(source_folder, 'public', dirs_exist_ok=True)
develop(prod)
if __name__ == '__main__':
fire.Fire(site_creator)
fire.Fire(crater)

View File

@ -9,3 +9,4 @@ python-frontmatter==1.0.0
PyYAML==6.0.1
six==1.16.0
termcolor==2.3.0
watchdog==3.0.0