Compare commits

...

5 Commits

View File

@ -4,7 +4,7 @@ import shutil
from pathlib import Path from pathlib import Path
import os import os
import markdown 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 bs4 import BeautifulSoup
from collections import defaultdict from collections import defaultdict
import toml import toml
@ -30,6 +30,37 @@ def get_first_header_content(content, fallback: str = ""):
return fallback 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: class Template:
def __init__(self, folder: Path): def __init__(self, folder: Path):
self.folder = folder self.folder = folder
@ -40,50 +71,33 @@ class Template:
self.article_card: str = (self.folder / "article_card.html").read_text() self.article_card: str = (self.folder / "article_card.html").read_text()
class ArticleTranslation: class ArticleTranslation:
def __init__(self, file: Path, article_overview: ArticleOverview): def __init__(self, file: Path, article: Article):
self.file = file self.file = file
self.article_overview = article_overview self.article = article
self.language_code = self.file.stem
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_content = self.file.read_text()
self.article_preview = self.article_content[:config.formatting.article_preview_length] + "..." self.article_preview = self.article_content[:config.formatting.article_preview_length] + "..."
if self.file.suffix == ".md": if self.file.suffix == ".md":
self.article_content = markdown.markdown(self.article_content) self.article_content = markdown.markdown(self.article_content)
self.article_preview = markdown.markdown(self.article_preview) self.article_preview = markdown.markdown(self.article_preview)
self.location_in_tree = [self.language_code, *self.article_overview.location_in_tree] self.title = get_first_header_content(self.article_content, fallback="")
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.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): def build(self):
self.dist_path.mkdir(parents=True, exist_ok=True) self.dist_path.mkdir(parents=True, exist_ok=True)
@ -96,15 +110,11 @@ class ArticleTranslation:
"article_content": self.article_content, "article_content": self.article_content,
"article_preview": self.article_preview, "article_preview": self.article_preview,
"article_url": self.url, "article_url": self.url,
"article_overview_url": self.article_overview.url, "article_overview_url": self.article.url,
"article_slug": self.article_overview.slug, "article_slug": self.article.slug,
"article_title": self.title, "article_title": self.title,
"article_datetime": self.article_overview.article_written.strftime(config.formatting.datetime_format), "article_datetime": self.article.article_written.strftime(config.formatting.datetime_format),
"article_datetime_iso": self.article_overview.article_written.isoformat(), "article_datetime_iso": self.article.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,
} }
if return_foreign_articles: if return_foreign_articles:
@ -115,7 +125,7 @@ class ArticleTranslation:
def get_article_values(self) -> Dict[str, str]: def get_article_values(self) -> Dict[str, str]:
res = {} res = {}
for key, value in self._get_values(return_foreign_articles=False).items(): 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 return res
@ -129,17 +139,23 @@ class ArticleTranslation:
return replace_values(TEMPLATE.article_card, self._get_values()) 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): def __init__(self, directory: Path, location_in_tree: Optional[List[str]] = None, is_root: bool = False):
self.directory = directory self.directory = directory
article_config = {} self.context: Dict[str, Any] = {}
if (self.directory / "index.toml").exists(): self.context_meta = self.context["meta"] = {}
article_config = toml.load(self.directory / "index.toml")
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 [] self.location_in_tree: List[str] = location_in_tree or []
if not is_root: if not is_root:
@ -147,12 +163,12 @@ class ArticleOverview:
self.url = "/" + "/".join(self.location_in_tree) self.url = "/" + "/".join(self.location_in_tree)
self.dist_path = Path(config.setup.dist_directory, *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: List[ArticleTranslation] = []
self.article_translations_map: Dict[str, ArticleTranslation] = {} self.article_translations_map: Dict[str, ArticleTranslation] = {}
@ -165,7 +181,7 @@ class ArticleOverview:
self.article_translations.append(at) self.article_translations.append(at)
self.article_translations_map[at.language_code] = at self.article_translations_map[at.language_code] = at
elif c.is_dir(): elif c.is_dir():
self.child_articles.append(ArticleOverview( self.child_articles.append(Article(
directory=c, directory=c,
location_in_tree=self.location_in_tree.copy(), 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) self.article_cards = "\n".join(c.get_article_card() for c in self.child_articles)
for at in self.article_translations: 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())) 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 # GLOBALS
logger = logging.getLogger("stsg.build") logger = logging.getLogger("stsg.build")
TEMPLATE = Template(Path(config.setup.source_directory, "templates")) 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) ARTICLE_REFERENCE_VALUES: DefaultDict[str, Dict[str, str]] = defaultdict(dict)
def build(): 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) shutil.copytree(Path(config.setup.source_directory, "static"), Path(config.setup.dist_directory, "static"), dirs_exist_ok=True)
logger.info("reading page tree...") 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 # build article reverence values
for article_overview in ARTICLE_LAKE.values(): for article_overview in ARTICLE_LAKE.values():