diff --git a/argparser.py b/argparser.py
new file mode 100644
index 0000000..2d9dd4f
--- /dev/null
+++ b/argparser.py
@@ -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')
\ No newline at end of file
diff --git a/classes.py b/classes.py
new file mode 100644
index 0000000..f5f7f11
--- /dev/null
+++ b/classes.py
@@ -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] + "... read more"
+ 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'
\ No newline at end of file
diff --git a/config.py b/config.py
index 5b7ace6..888b62e 100644
--- a/config.py
+++ b/config.py
@@ -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'
\ No newline at end of file
diff --git a/functions.py b/functions.py
new file mode 100644
index 0000000..f8e1d43
--- /dev/null
+++ b/functions.py
@@ -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")
+
+
\ No newline at end of file
diff --git a/hydrogen.py b/hydrogen.py
index 9dd9040..76019a4 100644
--- a/hydrogen.py
+++ b/hydrogen.py
@@ -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] + "... read more"
- 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.")
\ No newline at end of file
+ # 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()
\ No newline at end of file
diff --git a/logger.py b/logger.py
index a3a59b7..c413738 100644
--- a/logger.py
+++ b/logger.py
@@ -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)
diff --git a/requirements.txt b/requirements.txt
index d822853..d0d8a2c 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,3 +1,4 @@
+argparse
python-frontmatter
jinja2
markdown