190 lines
9.2 KiB
Markdown
190 lines
9.2 KiB
Markdown
# Autorenwebseite tobias-radloff.de
|
||
|
||
Eine moderne statische Autorenwebseite mit Werksseiten, Neuigkeiten, Terminkalender, Newsletterabonnentenverwaltung und Kontaktformular auf Basis von [Pelican](https://getpelican.com).
|
||
|
||
## Dependencies
|
||
|
||
### Pelican
|
||
|
||
Ich verwende Pelican v4.11.0 mit Markdown-Support (`pip install pelican[markdown]`) in einer eigenen `venv`-Umgebung. Pelican setzt `python3` voraus.
|
||
|
||
Außerdem nutze ich folgende Pelican-Plugins:
|
||
|
||
* `pelican-yaml-metadata` – ermöglicht das Einlesen von Metadaten im YAML-Format
|
||
* `pelican-image-process` – erlaubt das Bearbeiten von Bildern beim Erzeugen der Seite
|
||
* `pelican-alias` – damit kann ich Alias-URLs definieren, von denen aus auf die betreffende Page/Post umgeleitet wird
|
||
|
||
### CSS und Schriften
|
||
|
||
* [Pico CSS](https://picocss.com/) – tatsächlich verwende ich einen [Fork](https://github.com/Yohn/PicoCSS), der zusätzlich Hamburger-Menüs unterstützt
|
||
* [Libertinus Sans](https://github.com/alerque/libertinus) – im Development Mode greife ich auf lokale Dateien zurück, im Production Mode lade ich sie von einem [CDN](https://www.cdnfonts.com/libertinus-sans.font) herunter
|
||
|
||
### Werke und Texte
|
||
|
||
* TODO: alle Sourcefiles für meine Werke und Texte direkt aus der `the_works`-Datenbank erzeugen
|
||
|
||
### Termine
|
||
|
||
Das Script `utils/refresh-events.py` benötigt folgende Python-Packages (alle via `pip` installierbar):
|
||
|
||
* `caldav`
|
||
* `vobject`
|
||
* `pyyaml` (bereits mit Pelican mitinstalliert)
|
||
|
||
### Bildverarbeitung
|
||
|
||
@TODO: benutze ich das Script überhaupt noch?
|
||
|
||
Das Script `utils/crop_image_to_bbox.py` benötigt folgende Python-Packages:
|
||
|
||
* `PIL`
|
||
|
||
### Favicon
|
||
|
||
Um aus einer einzelnen SVG-Datei Favicons in allen nötigen Größen zu erzeugen, nutze ich das Shellscript `utils/favicon-from-svg.sh`. Es benötigt die folgenden Linux-Packages:
|
||
|
||
* `inkscape`
|
||
* `pngquant`
|
||
* `image-magick`
|
||
|
||
### Deployment Tool
|
||
|
||
* `lftp` – FTP-Client
|
||
|
||
### Auf dem Produktionsserver
|
||
|
||
* `php` (aktuell v8.1)
|
||
* PHP-Datenbanktreiber (aktuell `pdo_sqlite`)
|
||
* PHP-Package `PHPMailer` (im Repository enthalten)
|
||
|
||
## Konfiguration
|
||
|
||
Das Projekt wird in diesen Dateien konfiguriert:
|
||
|
||
* `pelicanconf.py` und `publishconf.py` – enthalten die Pelican-Konfiguration für Development bzw. Production Mode
|
||
* `config.ini` – enthält die Zugangsdaten für Datenbank und SMTP-Server sowie einige Einträge für die Newsletteran-/-abmeldung und das Kontaktformular; üblicherweise ist diese Datei ein Symlink zu einer Development- bzw. Production-spezifischen Datei
|
||
* `deploy.ini` – Zugangsdaten für den Upload auf den Produktionsserver
|
||
* `events.ini` – Zugangsdaten für den CalDAV-Server
|
||
|
||
## Ausführen
|
||
|
||
### Seite im Development Mode (neu) erzeugen
|
||
|
||
* `make clean` – Output-Verzeichnis leeren
|
||
* `make html` – alle HTML-Seiten neu erzeugen, die nicht im Output-Verzeichnis vorhanden sind oder deren Sourcefiles sich seit dem letzten Erzeugen verändert haben
|
||
* `make regenerate` – auf Änderungen in Sourcefiles lauschen und entsprechende Seiten neu erzeugen
|
||
* `sudo lighttpd -f lighttpd.conf` – Test-Webserver starten (Kontaktformular und Newsletteran-/-abmeldung erzeugen POST-Requests, doch der mit Pelican mitgelieferte Webserver verarbeitet nur GET-Requests; ich teste die Seite daher mit [lighttpd](https://www.lighttpd.net/))
|
||
* `utils/refresh-events.py` – CalDAV-Termine neu einlesen
|
||
|
||
### Seite im Production Mode (neu) erzeugen
|
||
|
||
* `make clean` – Output-Verzeichnis leeren
|
||
* `make publish` – Seite mit Produktionsparametern neu erzeugen (liest automatisch Termine neu ein)
|
||
|
||
### Deployment
|
||
|
||
* `deploy-via-ftp.sh` – Seite auf den Produktionsserver hochladen
|
||
|
||
## Dokumentation
|
||
|
||
### Aufbau der Webseite
|
||
|
||
Pelican kennt Artikel und Seiten. Ich verwende diese wie folgt:
|
||
|
||
* meine einzelnen Werke und News-Posts sind Artikel; alle Sourcefiles liegen in Unterverzeichnissen von `content/posts/`
|
||
* die Kategorie entspricht der Werksart (Romane, Kurzprosa, Lyrik, Weitere, News); alle Sourcefiles einer Kategorie liegen im gleichnamigen Unterverzeichnis (zB `content/posts/romane/`)
|
||
* Schlagworte entsprechen (größtenteils) Genres; ich habe aber zB auch englischsprachige Texte per Schlagwort markiert
|
||
* alles andere sind Seiten; die Sourcefiles liegen in `content/pages/`
|
||
* Seiten haben keine Schlagworte auf und üblicherweise auch keine Kategorie
|
||
* nur die Übersichtsseiten der jeweiligen Kategorie gehört ebendieser Kategorie an (so enthält zB `content/pages/romane.md` die Metadatenzeile `category: Romane`)
|
||
|
||
### Templates
|
||
|
||
Alle Templates liegen im Verzeichnis `theme/templates/`.
|
||
|
||
#### Basis
|
||
|
||
Das Basis-Template ist `base.html`, so wie es für Pelican üblich ist. Darin werden der grundsätzliche Seitenaufbau festgelegt, HTML-Metadaten gesetzt und Teil-Templates aus dem Unterverzeichnis `includes/` eingebunden, in denen wiederkehrenden Seitenelemente definiert sind:
|
||
|
||
* `favicon.html` – inklusive HTML-Metadaten
|
||
* `jumbotron.html` – Seitenheader
|
||
* `navbar.html` – NavigationsmMenü
|
||
* `footer.html` – Seitenfooter
|
||
|
||
Sämtliche First-Level-Templates binden das Basis-Template ein.
|
||
|
||
#### Seiten und Artikel
|
||
|
||
Das Template `page.html` definiert den Aufbau einer Einzelseite mit statischem Fließtext und wenigen Bildern. Auf diesem Template beruhen zB die Seiten Impressum, Übermich, Datenschutzerklärung oder die Seiten für die Newsletteran- bzw. -abmeldung.
|
||
|
||
Alle Werke und Texte hingegen verwenden das Template `article.html`.
|
||
|
||
|
||
#### Übersichtsseiten
|
||
|
||
* `wide-cards.html` – Template der Übersichtsseite über alle Werkskategorien (`werke.md`)
|
||
* `cards.html` – Template der Übersichtsseiten über alle Werke einer einzelnen Kategorien
|
||
|
||
#### Spezielle Seiten
|
||
|
||
* `index.html` – Startseitentemplate
|
||
* `news.html` – Template für den Neuigkeiten-Bereich
|
||
* `tag.html` – Template für Schlagwortseiten, auf denen alle Werke aufgelistet sind, die mit dem jeweiligen Begriff verschlagwortet sind
|
||
* `termine.html` – Template für den Terminkalender
|
||
|
||
|
||
### Termine neu einlesen
|
||
|
||
Um die Termine automatisch einzulesen und dem Pelican-Template `theme/templates/termine.html` zur Verfügung zu stellen, gibt es das Python-Script `utils/refresh_events.py`. Dieses Script
|
||
|
||
1. öffnet die Config-Datei `events.ini` – diese muss im Hauptverzeichnis des Projekts liegen –,
|
||
2. öffnet den in der Config-Datei definierten CalDAV-Kalender und liest daraus alle Events ein, die der Kategorie "Veranstaltung" angehören,
|
||
3. bereitet die Event-Daten für die Weiterverarbeitung auf
|
||
4. und speichert sie im YAML-Format in der Datei `content/pages/termine.md`.
|
||
|
||
Im Development-Modus muss `refresh_events.py` per Hand aufgerufen werden; im Publication-Modus geschieht dies automatisch.
|
||
|
||
Damit eine Lesung aus dem Kalender auf die Termine-Seite übernommen wird, muss sie folgende Voraussetzungen erfüllen:
|
||
|
||
1. im richtigen Kalender eingetragen sein (duh)
|
||
2. der Kategorie "Veranstaltung" angehören
|
||
3. in der Zukunft liegen
|
||
|
||
Standardmäßig werden alle Properties des "icalender"-Standards eingelesen und als Metadaten abgespeichert; ausgenommen davon sind nur die Properties "action", "repeat" und "trigger". Konkret werden vom Template die folgenden Properties ausgewertet:
|
||
|
||
* "dtstart": wird vom Script in "startdate" und ggf. "starttime" aufgespalten
|
||
* "dtend": wird vom Script zu "enddate" umgewandelt, wenn es vom Startdatum abweicht
|
||
* "summary": der Titel der Veranstaltung
|
||
* "location": Veranstaltungsort
|
||
* "description": zusäzliche Informationen zur Veranstaltung
|
||
* bestimmte Einträge in "categories":
|
||
* "Moderation": hängt "(Moderation)" an die Summary an
|
||
* "Babelsberger Lesesalon", "Andere Welten": gibt dem Datumsfeld des Termins die der entsprechenden Veranstaltungsreihe zugeordnete Hintergrundfarbe
|
||
* "attach": das Script geht die dem Event angehängten Links durch und stellt dem Template zur Verfügung:
|
||
* max. einen Link zu einer Webseite (als "link")
|
||
* max. einen Link zu einer Bilddatei (als "image")
|
||
|
||
Zu den Attachments ist Folgendes zu beachten:
|
||
|
||
* Alle Links, die zu einer Bilddatei verweisen (bei denen der "Pfad"-Teil der URL auf eine Datei mit einer Bilddatei-Suffix, z.B. "jpg", verweist), gelten als Bild-Links. Alle akzeptierten Suffixe sind in der Script-Variable "image_suffixes" definiert.
|
||
* Alle Links, die nicht als Bild-Links eingestugt werden, gelten als reguläre Links.
|
||
* Wenn mehrere Bild- oder reguläre Links existieren, wird der jeweils letzte verwendet.
|
||
* Soll auf eine lokale Bilddatei verwiesen werden, muss der Hostname des "attach"-Eintrags `localhost`, und eine gleićhnamige Datei muss im Verzeichnis `content/images/termine/` vorhanden sein. URL-Schema, -Pfad und Query-Parameter werden nicht ausgewertet. Attachments, die auf Webseiten oder auf Bilddateien auf externen Servern verweisen, bleiben unverändert.
|
||
|
||
Beispiele:
|
||
|
||
| Attachment URL | URL-Typ | aufbereitete URL |
|
||
| -------------- | ---------------- | ------- |
|
||
| `http://localhost/spam/eggs/image.jpg` | Bild | `../images/termine/image.jpg` |
|
||
| `ftp://localhost/image2.png` | Bild | `../images/termine/image2.jpg` |
|
||
| `https://example.com/path/to/image3.png` | Bild | (unverändert) |
|
||
| `http://veranstaltungsort.de/kalender/coole-lesung-mit-tobi.html` | Link | (unverändert) |
|
||
| `https://127.0.0.1/foo/bar/image4.webp?size=400&height=260` | Bild | `../images/termine/image4.webp` |
|
||
|
||
|
||
|
||
|
||
## TODOs
|
||
|
||
* Seite schneller laden (lazy loading?)
|
||
* the_works anbinden, sodass die Werk-Seiten aus der DB automatisch übernommen werden |