Compare commits
8 Commits
2728bef5f2
...
87d3e7d133
| Author | SHA1 | Date | |
|---|---|---|---|
| 87d3e7d133 | |||
| 289e18e505 | |||
| 40ace39b0a | |||
| 1c36817daf | |||
| 02faf783f8 | |||
| e9d5a2c1a5 | |||
| cfaa5c27c4 | |||
| ada778e5a4 |
3
.gitignore
vendored
3
.gitignore
vendored
@ -8,4 +8,5 @@ config.ini
|
|||||||
config.dev.ini
|
config.dev.ini
|
||||||
config.prod.ini
|
config.prod.ini
|
||||||
events.ini
|
events.ini
|
||||||
deploy.conf
|
deploy.ini
|
||||||
|
venv/
|
||||||
109
README.md
Normal file
109
README.md
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
# Autorenwebseite tobias-radloff.de
|
||||||
|
|
||||||
|
Eine moderne statische Autorenwebseite mit Werksseiten, Neuigkeiten, Terminkalender, Newsletterabonnentenverwaltung und Kontaktformular auf Basis von [Pelican](https://getpelican.com).
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
### Pelican
|
||||||
|
|
||||||
|
In einer eigenen `venv`-Umgebung verwende ich Pelican (v4.11.0) mit Markdown-Support, installiert mittels `pip install pelican[markdown]`. Pelican setzt `python3` voraus.
|
||||||
|
|
||||||
|
Plugins für Pelican:
|
||||||
|
|
||||||
|
* `pelican-yaml-metadata` – ermöglicht das Einlesen von Metadaten im YAML-Format
|
||||||
|
* `pelican-image-process` – erlaubt das Bearbeiten von Bildern beim Erzeugen der Seite
|
||||||
|
|
||||||
|
### 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 stammen sie von einem [CDN](https://www.cdnfonts.com/libertinus-sans.font)
|
||||||
|
|
||||||
|
### Werke und Texte
|
||||||
|
|
||||||
|
* TODO: die Sourcefiles für meine Werke und Texte sollen direkt aus der `the_works`-Datenbank erzeugt werden
|
||||||
|
|
||||||
|
### Termine
|
||||||
|
|
||||||
|
Das Script `utils/refresh-events.py` benötigt folgende Python-Packages (beide via `pip` installierbar):
|
||||||
|
|
||||||
|
* `caldav`
|
||||||
|
* `vobject`
|
||||||
|
|
||||||
|
### Bildverarbeitung
|
||||||
|
|
||||||
|
@TODO: benutze ich das Script überhaupt noch?
|
||||||
|
|
||||||
|
Das Script `utils/crop_image_to_bbox.py` setzt die Python-Bibliothek `PIL` voraus.
|
||||||
|
|
||||||
|
### Favicon
|
||||||
|
|
||||||
|
Um aus einer einzelnen SVG-Datei Favicons in allen nötigen Größen zu erzeugen, nutze ich das Script `utils/favicon-from-svg.sh`. Es setzt voraus:
|
||||||
|
|
||||||
|
* `inkscape`
|
||||||
|
* `pngquant`
|
||||||
|
* `image-magick`
|
||||||
|
|
||||||
|
### Deployment Tool
|
||||||
|
|
||||||
|
* `lftp`
|
||||||
|
|
||||||
|
### Auf dem Produktionsserver
|
||||||
|
|
||||||
|
* `php` (aktuell 8.1)
|
||||||
|
* Datenbanktreiber, aktuell `pdo_sqlite`
|
||||||
|
* `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); üblicherweise ist diese Datei ein Symlink zu einer der folgenden Dateien
|
||||||
|
* `config.dev.ini` – Werte für den Development Mode
|
||||||
|
* `config.prod.ini` – Werte für den Production Mode
|
||||||
|
* und `config.example.ini` ist ein Beispieldatei mit Dummy-Werten
|
||||||
|
* `deploy.ini` – FTP-Zugangsdaten für 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 sowie News-Posts sind Artikel; die Sourcefiles liegen in `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 – weitgehend – den Genres, geben aber auch zB englischsprachige Texte an
|
||||||
|
* alles andere sind Seiten; die Sourcefiles liegen in `content/pages/`
|
||||||
|
|
||||||
|
### Templates
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Termine neu einlesen
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## TODOs
|
||||||
|
|
||||||
|
* Seite schneller laden (lazy loading?)
|
||||||
|
* the_works anbinden, sodass die Werk-Seiten aus der DB automatisch übernommen werden
|
||||||
@ -4,7 +4,7 @@
|
|||||||
; do not close with '/''
|
; do not close with '/''
|
||||||
site_url = https://www.example.com
|
site_url = https://www.example.com
|
||||||
notificationAddress = mail@example.com
|
notificationAddress = mail@example.com
|
||||||
; string concatenated with email address to create a non-recreatable md5 hash
|
; string that will be concatenated with email address to create a non-recreatable md5 hash
|
||||||
uniqueKey = "some string"
|
uniqueKey = "some string"
|
||||||
statusCode = "HTTP/1.1 303 See Other"
|
statusCode = "HTTP/1.1 303 See Other"
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
# -*- coding: utf8 -*-
|
# -*- coding: utf8 -*-
|
||||||
|
|
||||||
# source login credentials and paths
|
# source login credentials and paths
|
||||||
source ./deploy.conf
|
source ./deploy.ini
|
||||||
|
|
||||||
# get remote directory directly above target dir
|
# get remote directory directly above target dir
|
||||||
# parameter expansion with '%' (remove suffix): cut off the rightmost occurrence of what comes after the percent sign
|
# parameter expansion with '%' (remove suffix): cut off the rightmost occurrence of what comes after the percent sign
|
||||||
@ -17,4 +17,4 @@ mirror --reverse --continue --verbose $LOCAL_DIR $REMOTE_BASE_DIR/tmp;
|
|||||||
rm -rf $REMOTE_DIR-old;
|
rm -rf $REMOTE_DIR-old;
|
||||||
mv $REMOTE_DIR $REMOTE_DIR-old;
|
mv $REMOTE_DIR $REMOTE_DIR-old;
|
||||||
mv $REMOTE_BASE_DIR/tmp $REMOTE_DIR;
|
mv $REMOTE_BASE_DIR/tmp $REMOTE_DIR;
|
||||||
"
|
"
|
||||||
|
|||||||
@ -175,9 +175,6 @@ h1, h2, h3, h4, h5, h6 {
|
|||||||
|
|
||||||
/* Navbar */
|
/* Navbar */
|
||||||
#site-navbar {
|
#site-navbar {
|
||||||
a {
|
|
||||||
--pico-text-decoration: none;
|
|
||||||
}
|
|
||||||
ul {
|
ul {
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
@ -204,11 +201,17 @@ h1, h2, h3, h4, h5, h6 {
|
|||||||
details.dropdown {
|
details.dropdown {
|
||||||
margin-block-end: calc(var(--pico-spacing) * -1);
|
margin-block-end: calc(var(--pico-spacing) * -1);
|
||||||
|
|
||||||
>summary:not([role]) a,
|
>summary:not([role]) + ul li a,
|
||||||
li a {
|
a {
|
||||||
color: var(--pico-primary);
|
color: var(--pico-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
> summary + ul li a:hover,
|
||||||
|
a:hover {
|
||||||
|
color: var(--pico-primary-hover);
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
>summary:not([role]) {
|
>summary:not([role]) {
|
||||||
background-color: inherit;
|
background-color: inherit;
|
||||||
border: none;
|
border: none;
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<div class="container site-footer" >
|
<div class="container site-footer" >
|
||||||
{% set t = [ pages | map(attribute="modified") | list | max , articles | map(attribute="modified") | list | max ] | max %}
|
{% set t = [ pages | map(attribute="modified") | list | max , articles | map(attribute="modified") | list | max ] | max %}
|
||||||
<p>{{ t.strftime("%Y") }} erstellt mit <a href="https://www.getpelican.com/" target="_blank">Pelican</a> und viel <span class="heart">♥</span> von <a href="/ueber-mich/">Tobias Radloff</a></p>
|
<p>{{ t.strftime("%Y") }} | Erstellt mit <span class="heart">♥</span> von <a href="/ueber-mich/">Tobias Radloff</a></p>
|
||||||
</div>
|
</div>
|
||||||
Loading…
Reference in New Issue
Block a user