Egne temaer i innholdsrepoet, temavalg i innstillinger

Temaer slås opp i content/themes/<navn>/ før de innebygde, slik at et
eget tema følger med i git, backup og ved flytting – uten ny container.
Et tema kan være delvis: manglende maler/filer arves fra green (Jinja
ChoiceLoader, static kopieres lagvis). Valget lagres i site.toml;
SOAPBOX_THEME er bare standardverdi.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JcEy43fNYpwg6K6oTKakWR
This commit is contained in:
Ole-Morten Duesund 2026-08-26 13:45:04 +02:00
commit 9eb375e339
7 changed files with 112 additions and 15 deletions

View file

@ -190,3 +190,37 @@ def test_post_history(client, cfg):
client.post("/admin/logout", data={"csrf": token})
login(client, "gjest1")
assert client.get(f"/admin/history/{pid}").status_code == 403
def test_user_theme_in_content_repo(client, cfg):
"""Eget tema i content/themes/ overstyrer delvis og velges via innstillinger."""
theme = cfg.content_dir / "themes" / "skog"
(theme / "static").mkdir(parents=True)
(theme / "static" / "style.css").write_text(":root{--bg:#000}")
(theme / "templates").mkdir()
(theme / "templates" / "index.html").write_text("SKOG {{ rel('theme/style.css') }}")
assert cfg.available_themes() == ["green", "skog"]
login(client)
token = csrf(client)
assert (
client.post(
"/admin/settings", data={"csrf": token, "title": "T", "theme": "../etc"}
).status_code
== 400
)
r = client.post("/admin/settings", data={"csrf": token, "title": "T", "theme": "skog"})
assert r.status_code == 302
assert 'theme = "skog"' in (cfg.content_dir / "site.toml").read_text()
assert cfg.theme == "skog"
assert client.get("/").text.startswith("SKOG theme/style.css")
assert client.get("/theme/style.css").text == ":root{--bg:#000}"
assert client.get("/theme/favicon.svg").status_code == 200 # arvet fra green
# post.html finnes ikke i skog → arves fra green
r = client.post("/admin/new", data={"csrf": token})
pid = r.headers["Location"].split("/admin/edit/")[1]
client.post(
f"/admin/edit/{pid}", data={"csrf": token, "title": "P", "body": "x", "action": "publish"}
)
assert '<article class="post">' in client.get("/p/").text