This commit is contained in:
SG
2025-06-17 16:22:47 +03:00
parent 4ea54eaa91
commit 326e5c5edd
7 changed files with 77 additions and 51 deletions

View File

@@ -1,10 +1,10 @@
import argparse import argparse
from config import Config from config import config
argparser = argparse.ArgumentParser( argparser = argparse.ArgumentParser(
prog = Config.APP_NAME, prog = config.app_name,
description = Config.APP_DESCRIPTION, description = config.app_description,
epilog = f"See {Config.APP_SRC_URL} for more info.") epilog = f"See {config.app_src_url} for more info.")
subparsers = argparser.add_subparsers(dest='command', required=True) subparsers = argparser.add_subparsers(dest='command', required=True)

View File

@@ -5,16 +5,15 @@ import shutil
from collections import defaultdict from collections import defaultdict
import markdown import markdown
import frontmatter import frontmatter
from bs4 import BeautifulSoup
from pathlib import Path from pathlib import Path
from logger import logger from logger import logger
from config import Config from config import config
#from jinja_env import env, content_item_template, index_template #from jinja_env import env, content_item_template, index_template
from jinja2 import Environment, FileSystemLoader from jinja2 import Environment, FileSystemLoader
# get the scrip directory # Get the script base_dir and check for templates dir
if Path(f'themes/{config.theme}/templates').exists():
if Path(f'themes/{Config.THEME}/templates').exists():
base_dir = "." base_dir = "."
elif getattr(sys, 'frozen', False): elif getattr(sys, 'frozen', False):
# Running fron Pyinstaller-packed binary # Running fron Pyinstaller-packed binary
@@ -24,9 +23,9 @@ else:
base_dir = Path(__file__).resolve().parent base_dir = Path(__file__).resolve().parent
# Prepare template rendering engine # Prepare template rendering engine
if Path(f"themes/{Config.THEME}/templates").exists(): if Path(f"themes/{config.theme}/templates").exists():
# Use the templates from the initialized site instance and the installed theme # Use the templates from the initialized site instance and the installed theme
jinja_env_dir = f"themes/{Config.THEME}/templates" jinja_env_dir = f"themes/{config.theme}/templates"
print("USING LOCALLY INITIALIZED THEMES") print("USING LOCALLY INITIALIZED THEMES")
else: else:
# Use default templates from the default theme shipped with the app # Use default templates from the default theme shipped with the app
@@ -34,7 +33,7 @@ else:
print("USING DEFAULT THEMES") print("USING DEFAULT THEMES")
jinja_env_dir = f"{base_dir}/themes/default/templates" jinja_env_dir = f"{base_dir}/themes/default/templates"
env = Environment(loader=FileSystemLoader(f"{jinja_env_dir}")) env = Environment(loader=FileSystemLoader(f"{jinja_env_dir}"))
env.globals['header_image'] = f"{base_dir}/themes/{Config.THEME}/static/images/header.jpg" env.globals['header_image'] = f"{base_dir}/themes/{config.theme}/static/images/header.jpg"
index_template = env.get_template("index.html") index_template = env.get_template("index.html")
content_item_template = env.get_template("content_item.html") content_item_template = env.get_template("content_item.html")
print(env.loader.searchpath) print(env.loader.searchpath)
@@ -46,20 +45,20 @@ class ContentItem:
logger.debug(f"Rendering {self.source_file} to {self.target_file}") logger.debug(f"Rendering {self.source_file} to {self.target_file}")
try: try:
if self.image_file and self.image_file.exists(): if self.image_file and self.image_file.exists():
image_targetfile = Path(f"{Config.OUTPUT_DIR}/{Config.STATIC_DIR}/images/{self.image_file.name}") image_targetfile = Path(f"{config.output_dir}/{config.static_dir}/images/{self.image_file.name}")
logger.debug(f"Copying {self.image_file} to {image_targetfile}") logger.debug(f"Copying {self.image_file} to {image_targetfile}")
shutil.copyfile(self.image_file, image_targetfile) shutil.copyfile(self.image_file, image_targetfile)
self.image_file = f"{self.image_file.stem}.jpg" self.image_file = f"{self.image_file.stem}.jpg"
if self.css_file and self.css_file.exists(): if self.css_file and self.css_file.exists():
css_targetfile = Path(f"{Config.OUTPUT_DIR}/{Config.STATIC_DIR}/css/{self.css_file.name}") css_targetfile = Path(f"{config.output_dir}/{config.static_dir}/css/{self.css_file.name}")
logger.debug(f"Copying {self.css_file} to {css_targetfile}") logger.debug(f"Copying {self.css_file} to {css_targetfile}")
shutil.copyfile(self.css_file, css_targetfile) shutil.copyfile(self.css_file, css_targetfile)
if self.js_file and self.js_file.exists(): if self.js_file and self.js_file.exists():
js_targetfile = Path(f"{Config.OUTPUT_DIR}/{Config.STATIC_DIR}/js/{self.js_file.name}") js_targetfile = Path(f"{config.output_dir}/{config.static_dir}/js/{self.js_file.name}")
logger.debug(f"Copying {self.js_file} to {js_targetfile}") logger.debug(f"Copying {self.js_file} to {js_targetfile}")
shutil.copyfile(self.js_file, js_targetfile) shutil.copyfile(self.js_file, js_targetfile)
with self.target_file.open("w", encoding="utf-8") as f: with self.target_file.open("w", encoding="utf-8") as f:
f.write(content_item_template.render(content_item = self, page_title = f"{Config.MAIN_PAGE_TITLE}: {self.title}", parent_path = '../', categories = categories)) f.write(content_item_template.render(content_item = self, page_title = f"{config.site_name}: {self.title}", parent_path = '../', categories = categories))
except Exception as e: except Exception as e:
logger.error(f"Renderer: {e}") logger.error(f"Renderer: {e}")
@@ -69,7 +68,7 @@ class ContentItem:
self.source_file = Path(self.source_file) self.source_file = Path(self.source_file)
self.parent_dir = self.source_file.parent self.parent_dir = self.source_file.parent
self.slug = self.source_file.stem self.slug = self.source_file.stem
self.target_file = Path(f"{Config.OUTPUT_DIR}/{self.source_file.parent}/{self.source_file.stem}.html") self.target_file = Path(f"{config.output_dir}/{self.source_file.parent}/{self.source_file.stem}.html")
self.data = frontmatter.load(self.source_file) self.data = frontmatter.load(self.source_file)
self.preview = self.data.content.replace('\n', '<br>')[:300] self.preview = self.data.content.replace('\n', '<br>')[:300]
self.title = self.data.get("title", self.slug) self.title = self.data.get("title", self.slug)
@@ -109,14 +108,14 @@ class ContentItem:
class Site: class Site:
def __init__(self): def __init__(self):
self.output_dir = Path(Config.OUTPUT_DIR) self.output_dir = Path(config.output_dir)
self.content_dir = Path(Config.CONTENT_DIR) self.content_dir = Path(config.content_dir)
self.static_dir = Path(Config.STATIC_DIR) self.static_dir = Path(config.static_dir)
self.templates_dir = Path(Config.TEMPLATES_DIR) self.templates_dir = Path(config.templates_dir)
self.images_dir = Path(f"{Config.STATIC_DIR}/images") self.images_dir = Path(f"{config.static_dir}/images")
self.css_dir = Path(f"{Config.STATIC_DIR}/css") self.css_dir = Path(f"{config.static_dir}/css")
self.js_dir = Path(f"{Config.STATIC_DIR}/js") self.js_dir = Path(f"{config.static_dir}/js")
self.output_dir = Path(Config.OUTPUT_DIR) self.output_dir = Path(config.output_dir)
self.content_items = [] self.content_items = []
self.categories = defaultdict(list) self.categories = defaultdict(list)
@@ -132,8 +131,8 @@ class Site:
def get_content_items(self): def get_content_items(self):
logger.debug("Getting content items") logger.debug("Getting content items")
self.get_content_items = [] self.get_content_items = []
logger.debug(f"Scanning {Path(Config.CONTENT_DIR)}") logger.debug(f"Scanning {Path(config.content_dir)}")
for md_file in Path(Config.CONTENT_DIR).glob("*.md"): for md_file in Path(config.content_dir).glob("*.md"):
content_item = ContentItem(md_file) content_item = ContentItem(md_file)
content_item.parse_content() content_item.parse_content()
self.content_items.append(content_item) self.content_items.append(content_item)
@@ -159,7 +158,7 @@ class Site:
subdir.mkdir(parents=True, exist_ok=True) subdir.mkdir(parents=True, exist_ok=True)
# Copy theme's static dir to 'public/static # Copy theme's static dir to 'public/static
shutil.copytree(f"{base_dir}/themes/{Config.THEME}/static", f"{self.output_dir}/static", dirs_exist_ok=True) shutil.copytree(f"{base_dir}/themes/{config.theme}/static", f"{self.output_dir}/static", dirs_exist_ok=True)
# Get content items # Get content items
self.get_content_items() self.get_content_items()
@@ -172,14 +171,14 @@ class Site:
content_item.render_content(categories = self.categories) content_item.render_content(categories = self.categories)
# Render the about file # Render the about file
about_content = ContentItem(Path(f'themes/{Config.THEME}/content/about.md')) about_content = ContentItem(Path(f'themes/{config.theme}/content/about.md'))
about_content.parse_content() about_content.parse_content()
about_content.render_content(categories = self.categories, target_file='public/static/about.html') about_content.render_content(categories = self.categories, target_file='public/static/about.html')
# Render the index file # Render the index file
visible_content_items = [c for c in self.content_items if c.data.get("hidden") != True] visible_content_items = [c for c in self.content_items if c.data.get("hidden") != True]
with (self.output_dir / "index.html").open("w", encoding="utf-8") as f: with (self.output_dir / "index.html").open("w", encoding="utf-8") as f:
f.write(index_template.render(page_title = Config.MAIN_PAGE_TITLE, content_items=visible_content_items, categories = self.categories)) f.write(index_template.render(page_title = config.site_name, content_items=visible_content_items, categories = self.categories))
# Render the categories indices # Render the categories indices
visible_content_items = [c for c in self.content_items if c.data.get("hidden") != True] visible_content_items = [c for c in self.content_items if c.data.get("hidden") != True]
@@ -187,7 +186,7 @@ class Site:
category_index = Path(f"{self.output_dir}/categories/{category}.html") category_index = Path(f"{self.output_dir}/categories/{category}.html")
category_items = [i for i in visible_content_items if category in i.data.get("categories")] category_items = [i for i in visible_content_items if category in i.data.get("categories")]
with (category_index).open(mode="w", encoding="utf-8") as f: with (category_index).open(mode="w", encoding="utf-8") as f:
f.write(index_template.render(page_title=f"{Config.MAIN_PAGE_TITLE}: {category}", content_items=category_items, categories = self.categories, parent_path = '../')) f.write(index_template.render(page_title=f"{config.site_name}: {category}", content_items=category_items, categories = self.categories, parent_path = '../'))
logger.info(f"Created {len(self.content_items)} content items.") logger.info(f"Created {len(self.content_items)} content items.")

View File

@@ -1,14 +1,41 @@
import os import os, yaml
# Main config section # Main config section
#class Config:
# MAIN_PAGE_TITLE = "microgen library"
# APP_NAME = "hydrogen"
# APP_DESCRIPTION = "Simplistic static site generator"
# APP_SRC_URL = f"https://git.exocortex.ru/Exocortex/{APP_NAME}"
# OUTPUT_DIR = 'public'
# TEMPLATES_DIR = 'templates'
# CONTENT_DIR = 'content'
# STATIC_DIR = 'static'
# HEADER_IMAGE = 'static/header.jpg'
# THEME = "default"
class Config: class Config:
MAIN_PAGE_TITLE = "microgen library" def __init__(self, config_path="config.yml"):
APP_NAME = "hydrogen" self.app_name = "microgen"
APP_DESCRIPTION = "Simplistic static site generator" self.app_description = "Simplistic static site generator"
APP_SRC_URL = f"https://git.exocortex.ru/Exocortex/{APP_NAME}" self.app_src_url = f"https://git.exocortex.ru/Exocortex/{self.app_name}"
OUTPUT_DIR = 'public' self.content_dir = 'content'
TEMPLATES_DIR = 'templates' self.templates_dir = 'templates'
CONTENT_DIR = 'content' self.static_dir = 'static'
STATIC_DIR = 'static' self.output_dir = 'public'
HEADER_IMAGE = 'static/header.jpg' self.header_image = 'static/header.jpg'
THEME = "default" self.site_name = "microgen library"
self.theme = "default"
if os.path.isfile (config_path):
with open(config_path, "r") as f:
config = yaml.safe_load(f)
if config:
self.update_from_dict(config)
def update_from_dict(self, config_dict):
for key, value in config_dict.items():
setattr(self, key, value)
def __repr__(self):
return f"{self.__dict__}"
config = Config()

0
config.yml Normal file
View File

View File

@@ -1,11 +1,11 @@
import os, subprocess import os, subprocess
from pathlib import Path from pathlib import Path
from classes import * from classes import *
from config import Config from config import config
from logger import logger from logger import logger
def create_content(filename): def create_content(filename):
filename = Path(f"{Config.CONTENT_DIR}/{filename}.md") filename = Path(f"{config.content_dir}/{filename}.md")
if not filename.exists(): if not filename.exists():
logger.debug(f"Creating new content {filename}") logger.debug(f"Creating new content {filename}")
new_content_item = ContentItem(filename) new_content_item = ContentItem(filename)
@@ -15,9 +15,9 @@ def edit_content(filename):
logger.debug(f"Editing content {filename}") logger.debug(f"Editing content {filename}")
editor = os.environ.get('EDITOR', 'vim') editor = os.environ.get('EDITOR', 'vim')
# Create the content file if not exists # Create the content file if not exists
if not Path(f"{Config.CONTENT_DIR}/{filename}.md").exists(): if not Path(f"{config.content_dir}/{filename}.md").exists():
create_content(filename) create_content(filename)
filename = Path(f"{Config.CONTENT_DIR}/{filename}.md") filename = Path(f"{config.content_dir}/{filename}.md")
subprocess.call([editor, filename]) subprocess.call([editor, filename])
def init_site(): def init_site():

View File

@@ -1,12 +1,12 @@
import logging, sys import logging, sys
from config import Config from config import config
# Logging config section # Logging config section
LOG_TO = sys.stdout LOG_TO = sys.stdout
LOG_LEVEL = logging.INFO LOG_LEVEL = logging.INFO
logger = logging.getLogger(Config.APP_NAME) logger = logging.getLogger(config.app_name)
logger.setLevel(LOG_LEVEL) logger.setLevel(LOG_LEVEL)
stdout_handler = logging.StreamHandler(LOG_TO) stdout_handler = logging.StreamHandler(LOG_TO)
stdout_handler.setLevel(LOG_LEVEL) stdout_handler.setLevel(LOG_LEVEL)

View File

@@ -13,7 +13,7 @@
</head> </head>
<body> <body>
<div id="content"> <div id="top_wrapper">
<div id= "top_header" class="row top_header"> <div id= "top_header" class="row top_header">
<img id="top_header_image" src="{{ parent_path }}static/images/header.jpg" class="img-fluid"> <img id="top_header_image" src="{{ parent_path }}static/images/header.jpg" class="img-fluid">
<div id="top_title" class="row"> <div id="top_title" class="row">
@@ -37,11 +37,11 @@
</div> </div>
</div> </div>
<div id="content" class="container-fluid mb-2"> <div id="content_wrapper" class="container-fluid mb-2">
{% block content %} {% block content %}
{% endblock %} {% endblock %}
</div> </div>
<div id="footer" class="container-fluid"> <div id="footer_wrapper" class="container-fluid">
<div id="footer-data" class="row my-1"> <div id="footer-data" class="row my-1">
{% block footer_includes %} {% block footer_includes %}
{% endblock %} {% endblock %}