website/generator/util.py
2024-02-11 00:55:23 +00:00

95 lines
2.5 KiB
Python

import datetime
import os
from pathlib import Path
import yaml
import mistune
import threading
ERROR_LEADER = "[[red bold]FAIL[/bold red]] "
WARN_LEADER = "[[yellow bold]WARN[/bold yellow]] "
INFO_LEADER = "[[turquoise2 bold]info[/turquoise2 bold]] "
def load_yaml(data: str) -> any:
return yaml.load(data, Loader=yaml.CFullLoader)
def is_directory_empty(path: str | Path) -> bool:
return len(os.listdir(path)) == 0
_counts: dict[str, int] = {}
def reset_counts():
_counts = {}
def update_counts(key: str, delta: int):
_counts[key] = _counts.get(key, 0) + delta
def get_counts() -> dict[str, int]:
return _counts
def extract_frontmatter(instr: str) -> tuple[any, str]:
first = instr.find("---")
second = instr.find("---", first + 1)
if first != 0 or second == -1:
raise ValueError("no valid frontmatter found")
end = second + 3
raw_frontmatter = instr[:end]
trailer = instr[end:]
if trailer.startswith("\n"):
trailer = trailer[1:]
frontmatter = load_yaml(raw_frontmatter.strip("-\n"))
return frontmatter, trailer
def get_absolute_url(site_config: any, path: str):
bu = site_config["baseURL"]
return bu.rstrip("/") + "/" + path.lstrip("/")
def date_to_datetime(d: datetime.date) -> datetime.datetime:
return datetime.datetime(d.year, d.month, d.day)
def render_markdown(raw_content: str, escape: bool = True) -> str:
markdown = mistune.create_markdown(
escape=escape, plugins=["strikethrough", "table", "footnotes"]
)
return markdown(raw_content)
def debounce(wait_time):
"""
https://stackoverflow.com/a/66907107
Decorator that will debounce a function so that it is called after wait_time seconds
If it is called multiple times, will wait for the last call to be debounced and run only this one.
"""
def decorator(function):
def debounced(*args, **kwargs):
def call_function():
debounced._timer = None
return function(*args, **kwargs)
# if we already have a call to the function currently waiting to be executed, reset the timer
if debounced._timer is not None:
debounced._timer.cancel()
# after wait_time, call the function provided to the decorator with its arguments
debounced._timer = threading.Timer(wait_time, call_function)
debounced._timer.start()
debounced._timer = None
return debounced
return decorator