from pathlib import Path
import re
import flask
from src import constants as const
def get_unique_elements(_list: list) -> list:
"""
Get unique elements of list without changing order.
"""
return list(dict.fromkeys(_list))
def get_theme_names() -> list[str]:
with open("./static/css/themes.css") as file:
css_file = file.read()
themes = re.findall(r"\n\.([a-z\-]+-theme)", css_file)
return get_unique_elements(themes)
def get_code_style_names() -> list[str]:
styles = const.PYGMENTS_BUILTIN_STYLES.copy()
styles.extend(path.stem for path in const.CODE_STYLES_DIR.iterdir())
return get_unique_elements(styles)
def to_bool_str(value: str) -> str:
return BOOL_SET[not bool(value)] # True -> "1", False -> ""
def set_cookie_value_after_this_request(name: str, value: str):
@flask.after_this_request
def _set_cookie_value(response):
response.set_cookie(name, value, samesite='Lax', expires=1 << 32 - 1)
return response
def get_cookie_value(name: str, possible_values: list[str]) -> str:
"""
Get cookie value by name.
First possible value - default.
"""
value = flask.request.values.get(name) # try to get value from args/form
if value in possible_values: # valid value was found
set_cookie_value_after_this_request(name, value)
return value
value = flask.request.cookies.get(name)
if value in possible_values: # valid value present in cookies
return value
set_cookie_value_after_this_request(name, possible_values[0])
return possible_values[0] # default value
def process_cookies():
"""
Set parsed cookie values into `flask.g`.
"""
flask.g.theme = get_cookie_value("theme", THEME_NAMES)
flask.g.code_style = get_cookie_value("code_style", CODE_STYLES)
flask.g.body_width = get_cookie_value("body_width", BODY_WIDTHS)
for cookie_name in BOOL_COOKIE_LIST:
flask.g.setdefault(
cookie_name,
get_cookie_value(cookie_name, BOOL_SET),
)
flask.g.mode = THEME_MODES[bool(flask.g.dark_mode)]
THEME_NAMES = get_theme_names()
CODE_STYLES = get_code_style_names()
THEME_MODES = ("light-mode", "dark-mode")
BODY_WIDTHS = get_unique_elements(["40", *map(str, range(20, 101, 5))])
BOOL_SET = ["1", ""] # [True, False]
BOOL_COOKIE_LIST = ("dark_mode", "use_js", "use_hl", "fonts", "extra_css")
def init(app: flask.Flask):
app.before_request(process_cookies)
app.jinja_env.globals.update(
to_bool_str=to_bool_str,
THEME_NAMES=THEME_NAMES,
THEME_MODES=THEME_MODES,
)