Compare commits

...

5 Commits

Author SHA1 Message Date
Hazel Noack
632f47e017 refactored article translations with cached properties 2025-05-22 12:24:38 +02:00
Hazel Noack
2a7ebaa298 some refactoring 2025-05-22 12:06:53 +02:00
Hazel Noack
d43d6505b1 defined name 2025-05-22 12:02:42 +02:00
Hazel Noack
e7558d996b refactored some attributes as cached properties 2025-05-22 11:56:06 +02:00
Hazel Noack
15707ada59 feat: english documentation up to date 2025-05-22 11:18:09 +02:00
4 changed files with 141 additions and 53 deletions

View File

@ -10,7 +10,7 @@ dependencies = [
dynamic = []
authors = []
readme = "README.md"
requires-python = ">=3.10"
requires-python = ">=3.8"
classifiers = []
version = "0.0.0"

View File

@ -4,3 +4,23 @@ Here you will learn how to get started making your own website.
1. fork the project and clone the fork
2. {{installation.link}}
## File structure
The files that define the content can be found in `src`. There are 3 subfolders. The style and functionality is defined in `templates`. If you can't code, or you don't know what your doing, leave it alone. The static files like stylesheets or pictures exist in `static`. This folder is simply copied on build. The interesting part starts with `articles`. Here are (like the name implies) all articles.
If something remains unclear, then the code of this documentation (should be found in your fork) could be helpful.
## Write articles
The text for the articles follows the following naming scheme `<language_code>.md`. In this case it would be `en.md` then you can write the article normally using [markdown](https://www.markdownguide.org/) for formatting.
If there should be subarticles, just create a new folder in the parent article folder. The folder name will be used as slug. That means it will appear in the url, and you can use it to link to other articles.
If you want to define the metadata for the article (the name, creation date, or author), then you can do so in `index.toml`. If none exists you can just create one. Here an example of such a file.
```toml
name="stsg"
datetime="2024-04-15 13:45:12.123456"
author="Hazel"
```

View File

@ -8,6 +8,9 @@ class config:
fallback_language = "en"
preview_length = 400
preview_header_shift = 2
markdown_extras = [
"fenced-code-blocks"
]
languages = {
"af": {

View File

@ -10,9 +10,12 @@ from collections import defaultdict
import toml
from datetime import datetime
import jinja2
from functools import cached_property
from . import config
def get_first_header_content(content, fallback: str = ""):
soup = BeautifulSoup(content, 'html.parser')
for level in range(1, 7):
@ -76,20 +79,7 @@ def shift_headings(html_string, header_shift=config.formatting.preview_header_sh
def get_preview_text(html_string: str):
return shift_headings(shorten_text_and_clean(html_string))
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 TemplateDict(dict):
@ -137,28 +127,66 @@ def compile_cross_article_context(cross_article_context):
cross_article_context["link"] = f'<a href="{url}">{title}</a>'
class ArticleTranslationContext(TypedDict):
slug: str
name: str
datetime: str
author: str
url: str
class ArticleTranslation:
article: Article
file: Path
@cached_property
def html_content(self) -> str:
html_content = self.file.read_text()
if self.file.suffix == ".md":
return markdown(html_content, extras=config.formatting.markdown_extras)
return html_content
@cached_property
def language_code(self) -> str:
language_code = self.file.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)
@cached_property
def priority(self) -> int:
return LANGUAGES[self.language_code]["priority"]
@cached_property
def slug_path(self) -> List[str]:
return [self.language_code, *self.article.slug_path]
@cached_property
def url(self) -> str:
return "/" + "/".join(self.slug_path)
@cached_property
def dist_path(self) -> Path:
return Path(config.setup.dist_directory, *self.slug_path)
context: ArticleTranslationContext
cross_article_context: Dict[str, Any]
def __init__(self, file: Path, article: Article):
self.file = file
self.article = article
self.file = file
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.context = {}
self.cross_article_context = TRANSLATED_CROSS_ARTICLE_CONTEXT[self.language_code][self.article.slug] = {}
self.priority = LANGUAGES[self.language_code]["priority"]
self.real_language_code = LANGUAGES[self.language_code]["code"]
self.html_content = self.file.read_text()
if self.file.suffix == ".md":
self.html_content = markdown(self.html_content, extras=["fenced-code-blocks"])
def __init_context__(self):
self.context["meta"] = self.article.context_shared
self.context["url"] = self.url
@ -211,33 +239,70 @@ class ArticleTranslation:
f.write(TEMPLATE["article_translation"].render(self.context))
class ArticleConfig(TypedDict):
slug: str
name: str
datetime: str
author: str
class ArticleContext(TypedDict):
slug: str
name: str
datetime: str
author: str
url: str
class Article:
def __init__(self, directory: Path, location_in_tree: Optional[List[str]] = None, is_root: bool = False, parent: Optional[Article] = None):
directory: Path
@cached_property
def config(self) -> ArticleConfig:
config_file = self.directory / "index.toml"
return toml.load(config_file) if config_file.exists() else {}
@cached_property
def slug(self) -> str:
slug = self.config.get("name", self.directory.name)
if slug in ARTICLE_LAKE:
logger.error("two articles have the same name at %s and %r", ARTICLE_LAKE[slug].directory, self.directory)
exit(1)
return slug
@cached_property
def name(self) -> str:
return self.config.get("name", self.slug)
article_path: List[Article]
@cached_property
def slug_path(self) -> List[str]:
return [a.slug for a in self.article_path[1:]]
@cached_property
def url(self) -> str:
return "/" + "/".join(self.slug_path)
@cached_property
def dist_path(self) -> Path:
return Path(config.setup.dist_directory, *self.slug_path)
context: ArticleContext
context_shared: Dict[str, Any]
cross_article_context: Dict[str, Any]
def __init__(self, directory: Path, article_path: Optional[List[str]] = None, is_root: bool = False, parent: Optional[Article] = None):
self.directory = directory
self.context: Dict[str, Any] = {}
self.context_shared: Dict[str, Any] = {}
if parent is not None:
self.context["parent"] = parent.context_shared
self.article_path: List[Article] = article_path or []
self.article_path.append(self)
# initializing the config values of the article
config_file = self.directory / "index.toml"
self.config = toml.load(config_file) if config_file.exists() else {}
# 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)
self.context: ArticleContext = {}
self.context_shared = {}
self.cross_article_context = CROSS_ARTICLE_CONTEXT[self.slug] = {}
ARTICLE_LAKE[self.slug] = self
self.location_in_tree: List[str] = location_in_tree or []
if not is_root:
self.location_in_tree.append(self.slug)
self.url = "/" + "/".join(self.location_in_tree)
self.dist_path = Path(config.setup.dist_directory, *self.location_in_tree)
# build the tree
self.child_articles: List[Article] = []
self.article_translations_list: List[ArticleTranslation] = []
@ -254,13 +319,13 @@ class Article:
elif c.is_dir():
self.child_articles.append(Article(
directory=c,
location_in_tree=self.location_in_tree.copy(),
article_path=self.article_path.copy(),
parent=self,
))
self.article_translations_list.sort(key=lambda a: a.priority, reverse=True)
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.slug_path)), ",".join(self.article_translations_map.keys()))
def __init_context__(self):
self.context_shared["url"] = self.url
@ -282,7 +347,7 @@ class Article:
child_article_list = self.context["children"] = []
for article_translation in self.article_translations_list:
self.context[article_translation.real_language_code] = article_translation.context
self.context[article_translation.language_code] = article_translation.context
translation_list.append(article_translation.context)
for child_article in self.child_articles: