From ee26af8b351d49e5a4097d14c8269fb173ec2464 Mon Sep 17 00:00:00 2001 From: Lars Noack Date: Mon, 14 Apr 2025 15:12:56 +0200 Subject: [PATCH] feat: refactored the overview --- src/index.html | 41 --------- stsg/build.py | 219 ++++++++++++++++++++++++++++++------------------- 2 files changed, 136 insertions(+), 124 deletions(-) delete mode 100644 src/index.html diff --git a/src/index.html b/src/index.html deleted file mode 100644 index b1b2986..0000000 --- a/src/index.html +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - STSG - - - - - - - -
-
- Go Back -
-
- - -
-
- - - - - diff --git a/stsg/build.py b/stsg/build.py index 65425df..0ebd7d3 100644 --- a/stsg/build.py +++ b/stsg/build.py @@ -1,9 +1,10 @@ +from __future__ import annotations import logging import shutil from pathlib import Path import os import markdown -from typing import Optional +from typing import Optional, Union, Dict, Generator from .config import SOURCE_DIRECTORY, DIST_DIRECTORY, LANGUAGE_INFORMATION @@ -11,87 +12,112 @@ from .config import SOURCE_DIRECTORY, DIST_DIRECTORY, LANGUAGE_INFORMATION logger = logging.getLogger("stsg.build") -def copy_static(src, dst): - if not os.path.exists(src): - logger.warn("The static folder '%s' wasn't defined.", src) +class CustomPath: + def __init__(self, path: Path): + self.path = path + + def __repr__(self) -> str: + return str(self.path) + + @property + def source_path(self) -> Path: + return Path(SOURCE_DIRECTORY, self.path) + + @property + def dist_path(self) -> Path: + return Path(DIST_DIRECTORY, self.path) + + @property + def name(self) -> str: + return Path(self.path).name + + @property + def parent(self) -> CustomPath: + return CustomPath(Path(self.path).parent) + + @property + def stem(self) -> str: + return Path(self.path).stem + + def iterdir(self) -> Generator[CustomPath, None, None]: + for p in self.source_path.iterdir(): + yield CustomPath(Path(self.path, p.name)) + + def get_child(self, name: str, force_directory: bool = False, force_file: bool = False) -> Optional[CustomPath]: + child = Path(self.source_path, name) + + if not child.exists(): + return None + + if force_directory and not child.is_dir(): + return None + + if force_file and not child.is_file(): + return None + + return CustomPath(Path(self.path, name)) + + def read_text(self) -> str: + return self.source_path.read_text() + +def copy_static(path: CustomPath): + src = path.source_path + dst = path.dist_path + + if not src.exists(): + logger.warning("The static folder '%s' wasn't defined.", src) return - logger.info("copying static files from '%s' to '%r'", src, dst) + logger.info("Copying static files from '%s' to '%s'", src, dst) - os.makedirs(dst, exist_ok=True) + dst.mkdir(parents=True, exist_ok=True) for root, dirs, files in os.walk(src): - if any(p.startswith(".") for p in Path(root).parts): - continue + root_path = Path(root) - # Compute relative path from the source root - rel_path = os.path.relpath(root, src) - dest_dir = os.path.join(dst, rel_path) + if any(part.startswith(".") for part in root_path.parts): + continue - os.makedirs(dest_dir, exist_ok=True) + rel_path = root_path.relative_to(src) + dest_dir = dst / rel_path + dest_dir.mkdir(parents=True, exist_ok=True) for file in files: if file.startswith("."): continue - src_file = os.path.join(root, file) - dest_file = os.path.join(dest_dir, file) - shutil.copy2(src_file, dest_file) + src_file = root_path / file + dest_file = dest_dir / file + shutil.copy2(src_file, dest_file) + -class Context: - def __init__(self, root: str = SOURCE_DIRECTORY): - self.file = None +class Article(CustomPath): + def __init__(self, path: CustomPath): + super().__init__(path.path) - current_root = Path(root) - while current_root.parts and self.file is None: - current_file = Path(current_root, "index.html") - if current_file.exists() and current_file.is_file: - self.file = current_file + def get_content(self) -> str: + if self.name.endswith(".md"): + return markdown.markdown(self.read_text()) - current_root = current_root.parent + return self.read_text() - if self.file is None: - logger.error("couldn't find context for %s", root) - exit(1) - logger.info("%s found context %r", root, str(self.file)) - - def get_text(self, **placeholder_values: dict): - text = self.file.read_text() - - for key, value in placeholder_values.items(): - text = text.replace(f"<{key}/>", value) - text = text.replace(f"<{key} />", value) - - return text - - -def convert_md(src: Path, dst: Path, context: Optional[Context] = None): - logger.info("converting %s", src) - - html_content = markdown.markdown(src.read_text()) - context = context or Context(str(src.parent)) - full_page = context.get_text(content=html_content) - - folder_dst = dst.parent / dst.name.replace(".md", "") - folder_dst.mkdir(parents=True, exist_ok=True) - - - with Path(folder_dst, "index.html").open("w") as f: - f.write(full_page) + @property + def article_directory(self) -> Path: + return self.dist_path.parent / self.stem class CustomLanguageCode: - def __init__(self, file: Path): - self.file: Path = file + def __init__(self, file: CustomPath): + self.file = file @property def language_code(self) -> str: - return self.file.name.replace(".md", "") + return self.file.stem @property def relative_url(self) -> str: - return "/" + str(Path(self.file.parent, self.language_code)) + return "/" + str(self) def __repr__(self) -> str: return f"{self.language_code}" @@ -120,40 +146,67 @@ class CustomLanguageCode: return f'' -def walk_directory(root): - src_path = Path(SOURCE_DIRECTORY, root) - dst_path = Path(DIST_DIRECTORY, root) +class Template: + def __init__(self, root: CustomPath): + self.root = root - context = Context(src_path) - language_codes_found = [] + self.articles = [] - for current_full_path in src_path.iterdir(): - current_name = Path(current_full_path).name - current_dst = Path(dst_path, current_name) - current_src = Path(src_path, current_name) + def copy(self): + return Template(root=self.root) - if current_name == "static": - copy_static(current_src, current_dst) - continue - - if current_name.endswith(".md"): - convert_md(current_src, current_dst, context=context) - - language_codes_found.append(CustomLanguageCode(Path(root, current_name))) + def _replace_keywords(self, text: str, **placeholder_values: str) -> str: + for key, value in placeholder_values.items(): + text = text.replace(f"<{key}/>", value) + text = text.replace(f"<{key} />", value) + + return text + + @property + def article_template(self) -> str: + article = self.root.get_child("article.html", force_file=True) + return article.source_path.read_text() if article else "" + + def convert_article(self, path: Article): + logger.info("converting %s", path) + + article_text = self._replace_keywords( + self.article_template, + content = path.get_content(), + ) + + path.article_directory.mkdir(parents=True, exist_ok=True) + with Path(path.article_directory, "index.html").open("w") as f: + f.write(article_text) + + +def walk_directory(root: CustomPath, template: Optional[Template] = None): + template_dir = root.get_child("_templates", force_directory=True) + if template_dir is not None: + template = Template(template_dir) + + if template is None: + logger.error("Didn't find template for %d", root) + return + + for current_path in root.iterdir(): + if current_path.name.startswith("_") or current_path.name == "static": continue - if current_src.is_dir(): - walk_directory(Path(root, current_full_path.name)) + if current_path.source_path.is_file(): + template.convert_article(Article(current_path)) + continue - content = f""" -
  • - {''.join(l.html_code for l in language_codes_found)} -
  • - """ - with Path(dst_path, "index.html").open("w") as f: - f.write(context.get_text(content=content)) + if current_path.source_path.is_dir(): + walk_directory(current_path, template=template.copy()) + + + + static_dir = root.get_child("static", force_directory=True) + if static_dir: + copy_static(static_dir) def build(): logger.info("building static page") - walk_directory("") + walk_directory(CustomPath(Path()))