Refactor
This commit is contained in:
parent
5fd1b91eba
commit
c5d7d48492
144
crater.py
144
crater.py
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue