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,82 +18,69 @@ 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'
logger.info(f"Building the '{Config.MAIN_PAGE_TITLE}' site.")
# Recreate the output dir if needed
if output_dir.exists():
shutil.rmtree(output_dir)
output_dir.mkdir()
# Create public subdirs
subdirs = [img_dir, assets_css_dir, assets_js_dir]
for subdir in subdirs:
subdir.mkdir(parents=True, exist_ok=True)
# Copy static files if exist
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"):
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,
})
def build_site():
logger.info(f"Building the '{Config.MAIN_PAGE_TITLE}' site.")
# 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))
# Recreate the output dir if needed
if output_dir.exists():
shutil.rmtree(output_dir)
output_dir.mkdir()
# Render the about file
about_content = ContentItemPrototype(Path('static/about.md'))
about_content.render_content()
# Create public subdirs
subdirs = [img_dir, assets_css_dir, assets_js_dir]
for subdir in subdirs:
subdir.mkdir(parents=True, exist_ok=True)
# Move 'robots.txt' into output_dir
shutil.copyfile(static_dir / 'robots.txt', output_dir / 'robots.txt')
# Copy static files if exist
if static_dir.exists():
shutil.copytree(static_dir, output_dir / "static", dirs_exist_ok=True)
logger.info(f"Created {len(content_items)} content items.")
# 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 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