feat: refactored the overview
This commit is contained in:
		
							
								
								
									
										219
									
								
								stsg/build.py
									
									
									
									
									
								
							
							
						
						
									
										219
									
								
								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'<ul><a href="{self.relative_url}"><bold>{self.flag} {self.native_name}</bold></a></ul>' | ||||
|  | ||||
|  | ||||
| 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 "<content/>" | ||||
|  | ||||
|     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""" | ||||
|     <li> | ||||
|         {''.join(l.html_code for l in language_codes_found)} | ||||
|     </li> | ||||
|     """ | ||||
|     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())) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user