Compare commits
5 Commits
54d1f0292e
...
632f47e017
Author | SHA1 | Date | |
---|---|---|---|
|
632f47e017 | ||
|
2a7ebaa298 | ||
|
d43d6505b1 | ||
|
e7558d996b | ||
|
15707ada59 |
@ -10,7 +10,7 @@ dependencies = [
|
||||
dynamic = []
|
||||
authors = []
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.10"
|
||||
requires-python = ">=3.8"
|
||||
classifiers = []
|
||||
version = "0.0.0"
|
||||
|
||||
|
@ -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"
|
||||
```
|
||||
|
@ -8,6 +8,9 @@ class config:
|
||||
fallback_language = "en"
|
||||
preview_length = 400
|
||||
preview_header_shift = 2
|
||||
markdown_extras = [
|
||||
"fenced-code-blocks"
|
||||
]
|
||||
|
||||
languages = {
|
||||
"af": {
|
||||
|
169
stsg/build.py
169
stsg/build.py
@ -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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user