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
-
-
-
-
-
-
-
-
-
-
-
-
-
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()))