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
31 lines
883 B
Python
31 lines
883 B
Python
"""Lager URL-vennlige slugs fra titler.
|
|
|
|
Norske tegn translittereres eksplisitt (æ→ae, ø→oe, å→aa) fordi generisk
|
|
unicode-normalisering ville mistet dem helt ("blåbær" → "blbr").
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
import unicodedata
|
|
|
|
_NORDIC = str.maketrans(
|
|
{"æ": "ae", "ø": "oe", "å": "aa", "ä": "ae", "ö": "oe", "ü": "ue", "ß": "ss"}
|
|
)
|
|
|
|
|
|
def slugify(text: str) -> str:
|
|
text = text.lower().translate(_NORDIC)
|
|
text = unicodedata.normalize("NFKD", text).encode("ascii", "ignore").decode()
|
|
text = re.sub(r"[^a-z0-9]+", "-", text).strip("-")
|
|
return text or "post"
|
|
|
|
|
|
def unique_slug(base: str, taken: set[str]) -> str:
|
|
"""Returnerer ``base`` eller ``base-2``, ``base-3`` … til den er ledig."""
|
|
if base not in taken:
|
|
return base
|
|
n = 2
|
|
while f"{base}-{n}" in taken:
|
|
n += 1
|
|
return f"{base}-{n}"
|