SciSiteForge/scisiteforge/themes.py

106 lines
3.5 KiB
Python

from __future__ import annotations
from dataclasses import dataclass, field
from pathlib import Path
import shutil
REPO_ROOT = Path(__file__).resolve().parents[1]
@dataclass(frozen=True)
class ThemeSpec:
name: str
display_name: str
template_path: Path
stylesheet_path: Path
extra_assets: tuple[Path, ...] = field(default_factory=tuple)
body_class: str = ""
shell_class: str = ""
page_class: str = ""
description: str = ""
def _theme_path(*parts: str) -> Path:
return REPO_ROOT.joinpath(*parts)
_THEMES: dict[str, ThemeSpec] = {
"evo-edu": ThemeSpec(
name="evo-edu",
display_name="Evo-Edu",
template_path=_theme_path("theme", "themes", "evo-edu", "base.html"),
stylesheet_path=_theme_path("theme", "themes", "evo-edu", "style.css"),
body_class="theme-evo-edu",
shell_class="site-shell",
page_class="evo-edu-page",
description="Warm learning-focused theme derived from the evo-edu.org home page.",
),
"talkorigins-modern": ThemeSpec(
name="talkorigins-modern",
display_name="TalkOrigins Modern",
template_path=_theme_path("theme", "themes", "talkorigins-modern", "base.html"),
stylesheet_path=_theme_path("theme", "themes", "talkorigins-modern", "style.css"),
extra_assets=(
_theme_path("theme", "themes", "talkorigins-modern", "assets", "toa.ico"),
_theme_path("theme", "themes", "talkorigins-modern", "assets", "toa_logo_001_edit_001.png"),
),
body_class="theme-talkorigins-modern",
shell_class="site-shell",
page_class="talkorigins-preview",
description="Archive-forward theme derived from the www2.talkorigins.org modernization proof-of-concept.",
),
"pandasthumb": ThemeSpec(
name="pandasthumb",
display_name="Panda's Thumb",
template_path=_theme_path("theme", "themes", "pandasthumb", "base.html"),
stylesheet_path=_theme_path("theme", "themes", "pandasthumb", "style.css"),
body_class="theme-pandasthumb",
shell_class="site-shell",
page_class="pandasthumb-page",
description="Legacy-archive theme derived from pandasthumb.net.",
),
}
def available_themes() -> list[ThemeSpec]:
return [_THEMES[name] for name in sorted(_THEMES)]
def get_theme(name: str | None) -> ThemeSpec:
theme_name = name or "evo-edu"
try:
return _THEMES[theme_name]
except KeyError as exc:
raise KeyError(f"Unknown SciSiteForge theme: {theme_name}") from exc
def materialize_theme(theme: ThemeSpec, output_dir: str | Path) -> dict[str, str]:
out = Path(output_dir)
theme_root = out / "theme"
assets_root = theme_root / "assets"
assets_root.mkdir(parents=True, exist_ok=True)
style_target = theme_root / "style.css"
shutil.copyfile(theme.stylesheet_path, style_target)
copied_assets: list[str] = []
for asset in theme.extra_assets:
target = assets_root / asset.name
shutil.copyfile(asset, target)
copied_assets.append(target.relative_to(out).as_posix())
shared_js = _theme_path("theme", "main.js")
if shared_js.exists():
shutil.copyfile(shared_js, theme_root / "main.js")
return {
"theme_name": theme.name,
"theme_display_name": theme.display_name,
"theme_description": theme.description,
"theme_stylesheet_href": "/theme/style.css",
"theme_script_href": "/theme/main.js",
"theme_asset_prefix": "/theme/assets",
"theme_assets": copied_assets,
}