some reworking

This commit is contained in:
SG
2025-06-07 13:17:51 +03:00
parent fc1ee27146
commit 1854366a9d
7 changed files with 183 additions and 74 deletions

11
argparser.py Normal file
View File

@@ -0,0 +1,11 @@
import argparse
from config import Config
argparser = argparse.ArgumentParser(
prog = Config.APP_NAME,
description = Config.APP_DESCRIPTION,
epilog = f"See {Config.APP_SRC_URL} for more info.")
argparser.add_argument('--init', action='store_true', help = 'Initialize new site')
argparser.add_argument('--content', '--edit', type = str, help = 'Create new content')
argparser.add_argument('--build', action='store_true', help = 'Build the site')

58
classes.py Normal file
View File

@@ -0,0 +1,58 @@
from datetime import datetime
import shutil
import markdown
import frontmatter
from jinja2 import Environment, FileSystemLoader
from pathlib import Path
from logger import logger
from config import Config
# Prepare template rendering engine
env = Environment(loader=FileSystemLoader(Config.TEMPLATE_DIR))
env.globals['header_image'] = Config.HEADER_IMAGE
index_template = env.get_template("index.html")
content_item_template = env.get_template("content_item.html")
class DefaultFrontmatterHeader:
def __init__(self, title):
self.title = f"title: '{title}'\n"
self.date = f"date: '{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}'\n"
self.omit_second_title = f"omit_second_title: '{str(False)}'\n"
self.description = "description: \n"
self.author = "author: \n"
class ContentItemPrototype:
def render_content(self):
logger.debug(f"Rendering {self.source_filename} to {Config.OUTPUT_DIR}/{self.target_filename}")
if self.image_src_file.exists():
shutil.copyfile(self.image_src_file, Path(Config.OUTPUT_DIR) / self.image)
if self.custom_css_src_file.exists():
shutil.copyfile(self.custom_css_src_file,Path(Config.OUTPUT_DIR) / self.custom_css)
if self.custom_js_src_file.exists():
shutil.copyfile(self.custom_js_src_file, Path(Config.OUTPUT_DIR) / self.custom_js)
with self.content_output_path.open("w", encoding="utf-8") as f:
f.write(content_item_template.render(content_item = self, page_title = self.title))
def __init__(self, md_file):
logger.debug(f"Parsing {md_file}")
self.source_filename = md_file
self.slug = md_file.stem
self.target_filename = self.slug + ".html"
self.data = frontmatter.load(md_file)
self.html = markdown.markdown(self.data.content)
self.preview = self.html[:300] + "<a href=" + f"{self.slug}.html" + ">... read more</a>"
self.title = self.data.get("title", self.slug)
self.omit_second_title = self.data.get("omit_second_title", False)
self.date = self.data.get("data", "2000-01-01T00:00:00+03:00")
self.content_output_path = Path(Config.OUTPUT_DIR) / f"{self.slug}.html"
self.image_src_file = Path(f"{Config.CONTENT_DIR}/{md_file.stem}.jpg")
self.image = f"images/{md_file.stem}.jpg" if self.image_src_file.exists() else None
self.custom_css_src_file = Path(f"{Config.CONTENT_DIR}/{md_file.stem}.css")
self.custom_css = f"static/css/{md_file.stem}.css" if self.custom_css_src_file.exists() else None
logger.debug(f"Custom CSS: {self.slug}: {self.custom_css}")
self.custom_js_src_file = Path(f"{Config.CONTENT_DIR}/{md_file.stem}.js")
self.custom_js = f"static/js/{md_file.stem}.js" if self.custom_js_src_file.exists() else None
logger.debug(f"Custom JS: {self.slug}: {self.custom_js}")
# Special handling for the 'about' item
if self.slug == 'about':
self.image = 'static/about.jpg'

View File

@@ -1,7 +1,16 @@
import os
# Main config section
class Config:
MAIN_PAGE_TITLE = "hydrogen site"
APP_NAME = "hydrogen"
MAIN_PAGE_TITLE = "Selected poems"
OUTPUT_DIR = os.environ.get('OUTPUT_DIR') or 'public'
APP_DESCRIPTION = "Simplistic static site generator"
APP_SRC_URL = f"https://git.exocortex.ru/Exocortex/{APP_NAME}"
OUTPUT_DIR = 'public'
OUTPUT_IMG_DIR = f"{OUTPUT_DIR}/images"
OUTPUT_CSS_DIR = f"{OUTPUT_DIR}/css"
OUTPUT_JS_DIR = f"{OUTPUT_DIR}/js"
TEMPLATE_DIR = 'templates'
CONTENT_DIR = 'content'
STATIC_DIR = 'static'
HEADER_IMAGE = 'static/header.jpg'

42
functions.py Normal file
View File

@@ -0,0 +1,42 @@
import os, subprocess
import shutil
from pathlib import Path
from classes import DefaultFrontmatterHeader
from config import Config
from logger import logger
def create_content(filename):
filename += '.md'
filename = Path(f"{Config.CONTENT_DIR}/{filename}")
if not filename.exists():
fh = DefaultFrontmatterHeader(filename.stem)
logger.debug(f"Creating new content {filename}")
with filename.open("w", encoding="utf-8") as f:
f.writelines(['---\n', fh.title, fh.date, fh.description, fh.author, fh.omit_second_title, '---\n', '\n', '\n'])
def edit_content(filename):
logger.debug(f"Editing content {filename}")
editor = os.environ.get('EDITOR', 'vim')
subprocess.call([editor, filename])
def init_site():
logger.debug(f"Initializing new site")
# Recreate output directory if necessary
output_dir = Path(Config.OUTPUT_DIR)
if output_dir.exists():
shutil.rmtree(output_dir)
output_dir.mkdir()
# Create output directory subtree
for dir in [ Path(Config.CONTENT_DIR), Path(Config.STATIC_DIR), Path(Config.TEMPLATE_DIR),
Path(Config.OUTPUT_IMG_DIR), Path(Config.OUTPUT_CSS_DIR), Path(Config.OUTPUT_JS_DIR)]:
dir.mkdir(exist_ok=True)
# Create "About.md" content item
create_content("about")
def build_site():
logger.debug(f"Starting build")

View File

@@ -1,12 +1,13 @@
#!/usr/bin/env python3
from pathlib import Path
import frontmatter
import markdown
from jinja2 import Environment, FileSystemLoader
import shutil
from config import Config
from logger import logger
from argparser import argparser
from classes import *
from functions import *
content_dir = Path('content')
template_dir = Path('templates')
@@ -17,38 +18,14 @@ assets_js_dir = Path(output_dir / 'static/js')
static_dir = Path('static')
header_image = Config.HEADER_IMAGE or '/static/header.jpg'
class ContentItemPrototype:
def render_content(self):
if self.image_src_file.exists():
shutil.copyfile(self.image_src_file, output_dir / self.image)
if self.custom_css_src_file.exists():
shutil.copyfile(self.custom_css_src_file,output_dir / self.custom_css)
if self.custom_js_src_file.exists():
shutil.copyfile(self.custom_js_src_file, output_dir / self.custom_js)
with self.content_output_path.open("w", encoding="utf-8") as f:
f.write(content_item_template.render(content_item = self, page_title = self.title))
def __init__(self, md_file):
self.slug = md_file.stem
self.data = frontmatter.load(md_file)
self.html = markdown.markdown(self.data.content)
self.preview = self.html[:300] + "<a href=" + f"{self.slug}.html" + ">... read more</a>"
self.title = self.data.get("title", self.slug)
self.omit_second_title = self.data.get("omit_second_title", False)
self.date = self.data.get("data", "2000-01-01T00:00:00+03:00")
self.content_output_path = output_dir / f"{self.slug}.html"
self.image_src_file = Path(f"{content_dir}/{md_file.stem}.jpg")
self.image = f"images/{md_file.stem}.jpg" if self.image_src_file.exists() else None
self.custom_css_src_file = Path(f"{content_dir}/{md_file.stem}.css")
self.custom_css = f"static/css/{md_file.stem}.css" if self.custom_css_src_file.exists() else None
logger.debug(f"Custom CSS: {self.slug}: {self.custom_css}")
self.custom_js_src_file = Path(f"{content_dir}/{md_file.stem}.js")
self.custom_js = f"static/js/{md_file.stem}.js" if self.custom_js_src_file.exists() else None
logger.debug(f"Custom JS: {self.slug}: {self.custom_js}")
# Special handling for the 'about' item
if self.slug == 'about':
self.image = 'static/about.jpg'
def build_site():
logger.info(f"Building the '{Config.MAIN_PAGE_TITLE}' site.")
# Recreate the output dir if needed
@@ -65,12 +42,6 @@ for subdir in subdirs:
if static_dir.exists():
shutil.copytree(static_dir, output_dir / "static", dirs_exist_ok=True)
# Prepare template rendering engine
env = Environment(loader=FileSystemLoader(str(template_dir)))
env.globals['header_image'] = header_image
index_template = env.get_template("index.html")
content_item_template = env.get_template("content_item.html")
# Parse the content files
content_items = []
for md_file in content_dir.glob("*.md"):
@@ -80,7 +51,7 @@ for md_file in content_dir.glob("*.md"):
"slug": current_content_item.slug,
"title": current_content_item.title,
"date": current_content_item.date,
"preview": markdown.markdown(current_content_item.preview),
# "preview": markdown.markdown(current_content_item.preview),
"image": current_content_item.image,
})
@@ -96,3 +67,20 @@ about_content.render_content()
shutil.copyfile(static_dir / 'robots.txt', output_dir / 'robots.txt')
logger.info(f"Created {len(content_items)} content items.")
def main():
args = argparser.parse_args()
if args.content:
content = args.content or args.edit
create_content(content)
edit_content(content)
if args.build:
build_site()
if args.init:
init_site()
if __name__ == '__main__':
main()

View File

@@ -4,7 +4,7 @@ from config import Config
# Logging config section
LOG_TO = sys.stdout
LOG_LEVEL = logging.INFO
LOG_LEVEL = logging.DEBUG
logger = logging.getLogger(Config.APP_NAME)
logger.setLevel(LOG_LEVEL)

View File

@@ -1,3 +1,4 @@
argparse
python-frontmatter
jinja2
markdown