feat: docs

This commit is contained in:
David Carmichael
2024-08-16 15:09:07 +01:00
parent caaf17af12
commit bfcc49dd8d
95 changed files with 12960 additions and 0 deletions

3
docs/_ssg/__init__.py Normal file
View File

@@ -0,0 +1,3 @@
from .compiler import compiler
__all__ = ["compiler"]

132
docs/_ssg/compiler.py Normal file
View File

@@ -0,0 +1,132 @@
import re
import typing as t
from pathlib import Path
import mistune
from flask import render_template
from .exceptions import NoPostDefinition
from .helpers import get_relative_files_in_the_docs_folder, pytz_dt_now, post_date
from .render_engines import HighlightRenderer
def _raw_markdown_processor(raw_markdown: str) -> tuple[t.Optional[list], str, str]:
"""
:param raw_markdown: The raw markdown to process
:return: publish: bool, date: str, title: str, description: str, post: str
"""
if not raw_markdown.startswith("```"):
raise NoPostDefinition
split_md = raw_markdown.split("```")[1:]
raw_meta = split_md[0]
menu_ptn = re.compile(r"Menu =(.*?)\n", re.IGNORECASE)
title_ptn = re.compile(r"Title =(.*?)\n", re.IGNORECASE)
try:
menu = menu_ptn.findall(raw_meta)[0].strip().split("/")
except (ValueError, IndexError, TypeError) as _:
menu = None
try:
title = title_ptn.findall(raw_meta)[0].strip()
except (ValueError, IndexError, TypeError) as _:
title = "[Unable to find Title]"
try:
post = "```".join(split_md[1:])
except (IndexError, TypeError, ValueError) as _:
post = "[Unable to find Post]"
return menu, title, post
def compiler(docs_dir: Path, markdown_dir: Path):
docs_dir.mkdir(exist_ok=True)
markdown_dir.mkdir(exist_ok=True)
markdown_menu = markdown_dir / "__menu__.md"
markdown_index = markdown_dir / "__index__.md"
markdown_menu_dict = dict()
with open(markdown_menu, mode="r") as menu_file:
for line in menu_file.readlines():
if line.startswith("-"):
line_strip = line.strip()
markdown_menu_dict[line_strip.replace("- ", "").strip()] = {
"page": "",
"pages": [],
}
continue
if line.startswith(" ") or line.startswith("\t"):
line_strip = line.strip()
if line_strip.startswith("-"):
markdown_menu_dict[list(markdown_menu_dict.keys())[-1]][
"pages"
].append({line_strip.replace("- ", "").strip(): ""})
main_index_html = docs_dir.parent / "index.html"
index_html = docs_dir / "index.html"
docs_dir_files = get_relative_files_in_the_docs_folder(docs_dir)
markdown_dir_files = markdown_dir.glob("*.md")
html_engine = mistune.create_markdown(renderer=HighlightRenderer())
html_pages = dict()
dt_date = pytz_dt_now()
main_index_html.unlink(missing_ok=True)
main_index_html.write_text(
render_template("main_index.html", latest_version=docs_dir.name)
)
for file in docs_dir_files:
(docs_dir / f"{file}.html").unlink()
for file in markdown_dir_files:
if "__" in file.stem:
continue
raw_markdown = file.read_text()
menu, title, post = _raw_markdown_processor(raw_markdown)
html_filename = f'{file.stem.lower().replace(" ", "_")}.html'
html_pages[html_filename] = {
"menu": menu,
"title": title,
"content": html_engine(post),
}
if menu is not None:
if len(menu) == 1:
markdown_menu_dict[menu[0]]["page"] = html_filename
else:
for keys in markdown_menu_dict[menu[0]]["pages"]:
if menu[1] in keys.keys():
keys[menu[1]] = html_filename
# write html files
for page, meta in html_pages.items():
with open(docs_dir / page, mode="w") as html_file:
html_file.write(
render_template(
"__main__.html",
menu=markdown_menu_dict,
title=meta["title"],
date=post_date(dt_date),
content=meta["content"],
)
)
# write main index.html
index_html.write_text(
render_template(
"index.html",
menu=markdown_menu_dict,
date=post_date(dt_date),
index=html_engine(markdown_index.read_text()),
)
)

38
docs/_ssg/exceptions.py Normal file
View File

@@ -0,0 +1,38 @@
class NoPostDefinition(Exception):
builtin_msg = f"""\n
No post definition found!
{"_" * 10}TOP_OF_FILE{"_" * 10}
```
Publish = Bool
Date = 0000-00-00 00:00:00 +0100 or set-on-compile
Title = String
Description = String
```
Must be at the top of the file, and must be followed by a blank line.
"""
def __str__(self):
return self.builtin_msg
class ErrorInPostDefinition(Exception):
builtin_msg = f"""\n
There is an error in the post description!
{"_" * 10}TOP_OF_FILE{"_" * 10}
```
Publish = Bool
Date = 0000-00-00 00:00:00 +0100 or set-on-compile
Title = String
Description = String
```
Must be at the top of the file, and must be followed by a blank line.
"""
def __str__(self):
return self.builtin_msg

53
docs/_ssg/helpers.py Normal file
View File

@@ -0,0 +1,53 @@
import re
from datetime import datetime
from pathlib import Path
from pytz import timezone
local_tz = timezone("Europe/London")
def pytz_dt_now() -> datetime:
return datetime.now(local_tz)
def pytz_dt_epoch() -> float:
return pytz_dt_now().timestamp()
def pytz_dt_now_str(mask: str = "%Y-%m-%d %H:%M:%S %z") -> str:
return datetime.now(local_tz).strftime(mask)
def pytz_dt_to_str(pytz_dt: datetime, mask: str = "%Y-%m-%d %H:%M:%S %z") -> str:
return pytz_dt.strftime(mask)
def pytz_dt_str_to_dt(pytz_dt_str: str) -> datetime:
"""
:param pytz_dt_str: "2020-01-01 00:00:00 +0000"
"""
return datetime.strptime(pytz_dt_str, "%Y-%m-%d %H:%M:%S %z")
def post_date(pytz_dt: datetime) -> str:
return pytz_dt.strftime("%a, %d %b %Y")
def switch_date(content, new_date):
pattern = re.compile(r'date="(.*?)"', re.IGNORECASE)
return pattern.sub(f'date="{new_date}"', content)
def get_relative_files_in_the_docs_folder(docs_dir: Path) -> list:
_ = []
for f in docs_dir.glob("*.html"):
if f.stem == "index":
continue
_.append(f.stem)
return _
def excessive_br_cleanup(base_xml: str) -> str:
return base_xml.replace("</p><br/>", "</p>").replace("<ol><br/>", "<ol>")

View File

@@ -0,0 +1,18 @@
import mistune
from pygments import highlight
from pygments.formatters import HtmlFormatter
from pygments.lexers import get_lexer_by_name
from pygments.util import ClassNotFound
class HighlightRenderer(mistune.HTMLRenderer):
def block_code(self, code, info=None):
if info:
if info == "jinja2":
info = "jinja"
try:
lexer = get_lexer_by_name(info, stripall=True)
except ClassNotFound:
lexer = get_lexer_by_name("text", stripall=True)
return highlight(code, lexer, HtmlFormatter())
return "<pre><code>" + mistune.escape(code) + "</code></pre>"