Soapbox: statisk blogg med mobilvennlig markdown-editor
Flask-app som genererer statiske sider til public/ og serverer dem sammen med et admin-grensesnitt (/admin). Innhold ligger som markdown og bilder i et git-repo (data/content), brukere i sqlite. - Editor med toolbar, live server-side forhåndsvisning, bildeopplasting via knapp, dra-og-slipp og lim inn. Bilder nedskaleres og EXIF fjernes. - Hovedbruker publiserer under /<slug>/, gjester under /<bruker>/<slug>/. Slug lages fra tittelen og fryses ved publisering. - Alle interne lenker er relative, så siden kan flyttes mellom domener og sub-paths (SOAPBOX_BASE_PATH) uten rebuild. - Tema 'green' med CSS-variabler, mørk modus og WCAG-kontrast. - Containerfile (python:alpine + git), compose.yaml og Caddyfile-eksempel. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JcEy43fNYpwg6K6oTKakWR
This commit is contained in:
commit
7ab2320be6
35 changed files with 2726 additions and 0 deletions
46
tests/conftest.py
Normal file
46
tests/conftest.py
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
import io
|
||||
|
||||
import pytest
|
||||
from PIL import Image
|
||||
|
||||
from soapbox import db
|
||||
from soapbox.app import create_app
|
||||
from soapbox.config import load_config
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def cfg(tmp_path):
|
||||
return load_config(
|
||||
{"SOAPBOX_DATA_DIR": str(tmp_path / "data"), "SOAPBOX_SITE_URL": "https://blog.example.no"}
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def app(cfg):
|
||||
app = create_app(cfg)
|
||||
app.config["TESTING"] = True
|
||||
conn = db.connect(cfg.db_path)
|
||||
db.create_user(conn, "eier", "hemmelig123", db.ROLE_OWNER, "Ole")
|
||||
db.create_user(conn, "gjest1", "hemmelig123", db.ROLE_GUEST, "Gjest En")
|
||||
conn.close()
|
||||
return app
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def client(app):
|
||||
return app.test_client()
|
||||
|
||||
|
||||
def login(client, username="eier", password="hemmelig123", prefix=""):
|
||||
return client.post(f"{prefix}/admin/login", data={"username": username, "password": password})
|
||||
|
||||
|
||||
def csrf(client, prefix=""):
|
||||
with client.session_transaction(path=f"{prefix}/admin/") as s:
|
||||
return s["csrf"]
|
||||
|
||||
|
||||
def png_bytes(size=(3000, 1500)):
|
||||
buf = io.BytesIO()
|
||||
Image.new("RGB", size, "green").save(buf, "PNG")
|
||||
return buf.getvalue()
|
||||
Loading…
Add table
Add a link
Reference in a new issue