Compare commits

...

5 Commits

View File

@ -4,7 +4,7 @@ import shutil
from pathlib import Path
import os
import markdown
from typing import Optional, Union, Dict, Generator, List, DefaultDict
from typing import Optional, Union, Dict, Generator, List, DefaultDict, Any
from bs4 import BeautifulSoup
from collections import defaultdict
import toml
@ -30,6 +30,37 @@ def get_first_header_content(content, fallback: str = ""):
return fallback
def stem_to_language_code(stem: str) -> str:
language_code = stem.lower().replace("-", "_")
if language_code in config.languages:
return language_code
language_code = language_code.split("_")[0]
if language_code in config.languages:
return language_code
logger.error("Didn't recognize %s as a valid language code, add it to the config, or fix your structure.", stem)
exit(1)
class LanguageDict(dict):
def __missing__(self, key: str):
if key not in config.languages:
raise KeyError(key)
lang_dict = config.languages[key]
lang_dict["priority"] = lang_dict.get("priority", 0)
elements = key.split("_")
if len(elements) > 1:
elements[-1] = elements[-1].upper()
lang_dict["code"] = "-".join(elements)
return lang_dict
LANGUAGES = LanguageDict()
class Template:
def __init__(self, folder: Path):
self.folder = folder
@ -40,50 +71,33 @@ class Template:
self.article_card: str = (self.folder / "article_card.html").read_text()
class ArticleTranslation:
def __init__(self, file: Path, article_overview: ArticleOverview):
def __init__(self, file: Path, article: Article):
self.file = file
self.article_overview = article_overview
self.language_code = self.file.stem
self.article = article
self.context: Dict[str, Any] = {}
# initializing the location of the article translation
self.language_code = stem_to_language_code(self.file.stem)
self.location_in_tree = [self.language_code, *self.article.location_in_tree]
self.url = "/" + "/".join(self.location_in_tree)
self.dist_path = Path(config.setup.dist_directory, *self.location_in_tree)
self.priority = LANGUAGES[self.language_code]["priority"]
# TODO remove
self.article_content = self.file.read_text()
self.article_preview = self.article_content[:config.formatting.article_preview_length] + "..."
if self.file.suffix == ".md":
self.article_content = markdown.markdown(self.article_content)
self.article_preview = markdown.markdown(self.article_preview)
self.location_in_tree = [self.language_code, *self.article_overview.location_in_tree]
self.url = "/" + "/".join(self.location_in_tree)
self.dist_path = Path(config.setup.dist_directory, *self.location_in_tree)
_language_info = config.languages[config.formatting.fallback_language]
parsed_language_code = self.language_code.lower().replace("-", "_")
if parsed_language_code in config.languages:
_language_info = config.languages[parsed_language_code]
elif parsed_language_code.split("_")[0] in config.languages:
_language_info = config.languages[parsed_language_code.split("_")[0]]
self.language_name: str = _language_info["native_name"]
self.language_flag: str = _language_info["flag"]
self.priority: int = _language_info.get("priority", 0)
self.title = get_first_header_content(self.article_content, fallback=self.language_name)
self.title = get_first_header_content(self.article_content, fallback="")
self.article_cards = ""
def post_init(self):
"""
the initializing that takes place after the creation of the tree
"""
article_card_strings = []
for child in self.article_overview.child_articles:
if self.language_code in child.article_translations_map:
article_card_strings.append(child.article_translations_map[self.language_code].get_article_card())
self.article_cards = "\n".join(article_card_strings)
def __init_context__(self):
self.context["meta"] = self.article.context_meta
self.context["language"] = LANGUAGES[self.language_code]
def build(self):
self.dist_path.mkdir(parents=True, exist_ok=True)
@ -96,15 +110,11 @@ class ArticleTranslation:
"article_content": self.article_content,
"article_preview": self.article_preview,
"article_url": self.url,
"article_overview_url": self.article_overview.url,
"article_slug": self.article_overview.slug,
"article_overview_url": self.article.url,
"article_slug": self.article.slug,
"article_title": self.title,
"article_datetime": self.article_overview.article_written.strftime(config.formatting.datetime_format),
"article_datetime_iso": self.article_overview.article_written.isoformat(),
"article_language_name": self.language_name,
"article_language_code": self.language_code,
"article_language_flag": self.language_flag,
"article_children_cards": self.article_cards,
"article_datetime": self.article.article_written.strftime(config.formatting.datetime_format),
"article_datetime_iso": self.article.article_written.isoformat(),
}
if return_foreign_articles:
@ -115,7 +125,7 @@ class ArticleTranslation:
def get_article_values(self) -> Dict[str, str]:
res = {}
for key, value in self._get_values(return_foreign_articles=False).items():
res[key + ":" + self.article_overview.slug] = value
res[key + ":" + self.article.slug] = value
return res
@ -129,17 +139,23 @@ class ArticleTranslation:
return replace_values(TEMPLATE.article_card, self._get_values())
class ArticleOverview:
class Article:
def __init__(self, directory: Path, location_in_tree: Optional[List[str]] = None, is_root: bool = False):
self.directory = directory
article_config = {}
if (self.directory / "index.toml").exists():
article_config = toml.load(self.directory / "index.toml")
self.context: Dict[str, Any] = {}
self.context_meta = self.context["meta"] = {}
self.slug = article_config.get("name", self.directory.name)
# initializing the config values of the article
config_file = self.directory / "index.toml"
self.config = toml.load(config_file) if config_file.exists() else {}
self.article_written = datetime.datetime.fromisoformat(article_config["datetime"]) if "datetime" in article_config else datetime.datetime.fromtimestamp(self.directory.stat().st_mtime)
# initializing the location and slug of the article
self.slug = self.config.get("name", self.directory.name)
if self.slug in ARTICLE_LAKE:
logger.error("two articles have the same name at %s and %r", ARTICLE_LAKE[self.slug].directory, self.directory)
exit(1)
ARTICLE_LAKE[self.slug] = self
self.location_in_tree: List[str] = location_in_tree or []
if not is_root:
@ -147,12 +163,12 @@ class ArticleOverview:
self.url = "/" + "/".join(self.location_in_tree)
self.dist_path = Path(config.setup.dist_directory, *self.location_in_tree)
if self.slug in ARTICLE_LAKE:
logger.error("two articles have the same name at %s and %r", ARTICLE_LAKE[self.slug].directory, self.directory)
exit(1)
ARTICLE_LAKE[self.slug] = self
self.child_articles: List[ArticleOverview] = []
self.article_written = datetime.datetime.fromisoformat(article_config["datetime"]) if "datetime" in article_config else datetime.datetime.fromtimestamp(self.directory.stat().st_mtime)
self.child_articles: List[Article] = []
self.article_translations: List[ArticleTranslation] = []
self.article_translations_map: Dict[str, ArticleTranslation] = {}
@ -165,7 +181,7 @@ class ArticleOverview:
self.article_translations.append(at)
self.article_translations_map[at.language_code] = at
elif c.is_dir():
self.child_articles.append(ArticleOverview(
self.child_articles.append(Article(
directory=c,
location_in_tree=self.location_in_tree.copy(),
))
@ -176,7 +192,7 @@ class ArticleOverview:
self.article_cards = "\n".join(c.get_article_card() for c in self.child_articles)
for at in self.article_translations:
at.post_init()
at.__init_context__()
logger.info("found %s at %s with the translations %s", self.slug, ".".join(list(self.location_in_tree)), ",".join(self.article_translations_map.keys()))
@ -227,7 +243,7 @@ class ArticleOverview:
# GLOBALS
logger = logging.getLogger("stsg.build")
TEMPLATE = Template(Path(config.setup.source_directory, "templates"))
ARTICLE_LAKE: Dict[str, ArticleOverview] = {}
ARTICLE_LAKE: Dict[str, Article] = {}
ARTICLE_REFERENCE_VALUES: DefaultDict[str, Dict[str, str]] = defaultdict(dict)
def build():
@ -237,7 +253,7 @@ def build():
shutil.copytree(Path(config.setup.source_directory, "static"), Path(config.setup.dist_directory, "static"), dirs_exist_ok=True)
logger.info("reading page tree...")
tree = ArticleOverview(directory=Path(config.setup.source_directory, "articles"), is_root=True)
tree = Article(directory=Path(config.setup.source_directory, "articles"), is_root=True)
# build article reverence values
for article_overview in ARTICLE_LAKE.values():