This commit is contained in:
fenris 2025-09-26 12:00:23 +02:00
parent 0a21755862
commit f1694dc42e
5 changed files with 375 additions and 11 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/build/

View file

@ -1,14 +1,6 @@
# Espe
# Espe | Documentation
Espe ist eine schlichte Nutzerverwaltung, welche als Daten-Quelle für Identitätsanbieter-Dienste verwendet werden kann.
## Beschreibung
Es können damit als Personen begreifbare Entitäten erfasst werden, die folgende Eigenschaft umfassen:
- Identifikations-Name
- Anzeige-Name
- E-Mail-Adresse
- ob aktiv
- Passwort-Daten
- Gruppen-Zugehörigkeiten
Bei Änderungen am Datenbestand können Ausgabe-Operationen ausgelöst werden, welche dazu dienen sollen evtl. angeschlossene Identitätanbieter-Dienste zu aktualisieren.
- enthält Konzept und Dokumentation für "Espe" (Erweiterte Sächsische Partei-Eingliederung)

153
source/logo.svg Normal file
View file

@ -0,0 +1,153 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="190.000000pt" height="190.000000pt" viewBox="0 0 190.000000 190.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.16, written by Peter Selinger 2001-2019
</metadata>
<g transform="translate(0.000000,190.000000) scale(0.100000,-0.100000)"
fill="#FF0000" stroke="none">
<!--
<path d="M0 950 l0 -950 950 0 950 0 0 950 0 950 -950 0 -950 0 0 -950z m1181
862 c275 -73 514 -285 608 -542 45 -123 55 -181 55 -320 0 -198 -42 -339 -144
-493 -174 -259 -435 -400 -745 -400 -416 0 -760 268 -871 680 -15 53 -19 101
-18 218 1 132 4 160 27 238 49 161 124 283 243 398 137 130 272 199 457 235
98 19 289 11 388 -14z"/>
-->
<path d="M850 1734 c-18 -37 -20 -50 -11 -70 18 -41 71 -25 71 22 0 21 -26 94
-34 94 -2 0 -14 -21 -26 -46z"/>
<path d="M1012 1741 c-16 -51 -15 -76 2 -90 11 -10 15 -8 19 6 4 17 5 17 6 0
1 -24 22 -17 32 9 7 20 -26 114 -41 114 -4 0 -12 -17 -18 -39z"/>
<path d="M701 1670 c-25 -54 -26 -73 -6 -90 12 -10 15 -10 16 1 0 8 4 5 8 -6
7 -18 9 -18 26 8 17 26 17 29 -3 80 l-20 52 -21 -45z"/>
<path d="M1167 1671 c-21 -51 -21 -75 -2 -91 18 -15 45 -10 59 12 8 13 5 29
-15 69 l-25 52 -17 -42z"/>
<path d="M956 1580 c-26 -64 -17 -100 26 -100 41 0 44 64 5 121 -14 19 -15 18
-31 -21z"/>
<path d="M537 1557 c-21 -66 -21 -86 -1 -115 22 -32 34 -27 35 16 1 39 3 37
14 -13 6 -29 7 -29 21 -11 22 31 17 68 -19 124 l-33 53 -17 -54z"/>
<path d="M802 1582 c-34 -32 -35 -62 -1 -62 21 0 42 41 37 73 -3 18 -6 17 -36
-11z"/>
<path d="M1070 1583 c0 -37 14 -58 40 -59 32 -2 26 40 -10 66 l-30 21 0 -28z"/>
<path d="M1321 1561 c-36 -55 -42 -104 -18 -128 14 -14 16 -12 26 28 l10 44
-2 -42 c-3 -44 0 -48 19 -35 30 20 35 52 19 114 -8 34 -17 63 -19 65 -2 2 -18
-19 -35 -46z"/>
<path d="M671 1462 c-16 -38 -11 -66 11 -70 24 -5 33 39 15 73 l-14 27 -12
-30z"/>
<path d="M1211 1467 c-6 -16 -11 -37 -11 -47 0 -23 16 -35 23 -18 4 10 6 10 6
0 1 -7 6 -10 11 -7 14 9 12 45 -5 75 l-13 25 -11 -28z"/>
<path d="M438 1431 c4 -57 28 -87 61 -76 34 11 26 48 -19 89 -22 20 -41 36
-43 36 -1 0 0 -22 1 -49z m60 -66 c-3 -3 -9 2 -12 12 -6 14 -5 15 5 6 7 -7 10
-15 7 -18z"/>
<path d="M773 1463 c-15 -10 -23 -25 -22 -42 0 -14 3 -20 6 -12 5 11 7 11 14
0 11 -19 25 -3 34 39 7 35 1 39 -32 15z"/>
<path d="M830 1441 c0 -50 14 -86 35 -95 14 -5 16 -2 11 21 -6 27 -6 28 7 5
15 -26 27 -19 27 15 0 21 -57 93 -74 93 -3 0 -6 -18 -6 -39z"/>
<path d="M1032 1446 c-35 -41 -43 -90 -16 -100 38 -14 72 51 56 108 l-8 28
-32 -36z m-1 -77 c-5 -13 -10 -19 -10 -12 -1 15 10 45 15 40 3 -2 0 -15 -5
-28z"/>
<path d="M1100 1456 c0 -24 39 -82 40 -58 0 7 5 10 10 7 20 -13 9 32 -13 53
-30 28 -37 28 -37 -2z"/>
<path d="M1427 1446 c-43 -40 -50 -80 -15 -92 32 -10 58 27 58 82 0 24 -1 44
-3 44 -2 0 -20 -15 -40 -34z m1 -61 c-6 -14 -13 -23 -15 -21 -5 5 15 46 22 46
3 0 -1 -11 -7 -25z"/>
<path d="M1186 1385 c40 -115 46 -255 14 -359 -12 -36 -24 -66 -28 -66 -4 0
-17 15 -29 33 -12 17 -43 52 -69 77 l-47 45 50 -65 c57 -74 73 -101 73 -125 0
-9 -29 -47 -64 -83 -36 -37 -80 -92 -98 -123 l-34 -57 -29 51 c-15 27 -59 82
-96 121 -38 39 -69 79 -69 89 0 26 24 69 76 134 l46 58 -59 -60 c-32 -33 -65
-71 -74 -84 -15 -24 -16 -24 -38 47 -29 90 -32 220 -7 306 9 32 15 60 13 62
-9 9 -50 -123 -62 -199 l-6 -38 -30 26 c-37 31 -104 37 -176 15 -18 -5 -5 -6
38 -3 111 9 158 -31 178 -151 7 -38 18 -84 26 -102 7 -18 11 -35 7 -38 -12
-12 -60 -5 -141 23 -47 16 -76 22 -66 15 30 -22 126 -56 178 -63 44 -6 51 -10
102 -76 l54 -70 -37 -7 c-66 -12 -166 -8 -215 10 -26 9 -66 35 -89 57 -22 22
-36 31 -30 20 19 -36 76 -84 127 -106 39 -18 75 -24 162 -27 l112 -4 15 -46
c16 -45 21 -147 10 -187 -4 -16 -19 -23 -62 -32 -31 -6 -86 -25 -122 -42 -36
-17 -54 -29 -40 -26 150 33 180 38 187 32 4 -4 -3 -14 -14 -22 -23 -16 -38
-55 -47 -120 l-5 -40 15 35 c27 64 42 85 73 97 l30 13 -5 -88 c-2 -48 -2 -82
0 -77 2 6 14 43 26 83 12 39 26 72 29 72 4 0 13 -26 19 -57 8 -37 24 -71 42
-93 35 -40 37 -38 10 15 -17 34 -30 145 -16 145 21 0 90 -40 125 -73 l44 -42
-23 40 c-12 22 -36 52 -53 68 -30 26 -31 27 -8 27 13 0 39 -9 57 -21 35 -21
154 -71 154 -63 0 2 -17 12 -38 23 -20 10 -62 37 -92 60 -30 22 -69 44 -86 47
-22 4 -34 13 -38 27 -12 44 -6 167 10 206 l15 39 112 4 c87 3 123 9 162 27 51
23 109 71 127 106 6 11 -9 1 -33 -22 -25 -23 -65 -48 -92 -57 -49 -17 -143
-20 -211 -8 l-39 7 45 55 c24 30 52 68 61 83 10 15 41 39 70 53 29 14 68 39
87 56 32 29 32 30 5 13 -89 -56 -145 -72 -126 -36 6 10 15 49 21 86 19 118 69
162 174 152 46 -4 55 -3 37 4 -42 17 -126 13 -160 -7 -17 -10 -31 -22 -31 -26
0 -4 -4 -8 -8 -8 -4 0 -9 18 -10 40 -3 47 -36 154 -58 190 -10 17 -13 18 -8 5z"/>
<path d="M747 1339 c-43 -35 -50 -74 -16 -84 30 -10 55 20 63 73 3 23 3 42 -2
42 -4 0 -24 -14 -45 -31z m-4 -64 c-3 -9 -8 -14 -10 -11 -3 3 -2 9 2 15 9 16
15 13 8 -4z"/>
<path d="M1114 1329 c8 -52 22 -79 41 -79 18 0 18 4 5 33 -10 22 -10 22 6 0
21 -29 34 -29 34 -2 0 22 -62 89 -82 89 -7 0 -8 -15 -4 -41z"/>
<path d="M376 1313 c18 -74 31 -88 70 -79 44 11 21 62 -43 95 -31 16 -34 14
-27 -16z m72 -68 c-3 -3 -13 7 -23 22 l-17 28 23 -22 c12 -12 20 -25 17 -28z"/>
<path d="M1495 1324 c-37 -20 -55 -42 -55 -68 0 -18 2 -18 26 5 l27 24 -18
-27 c-17 -27 -17 -28 3 -28 23 0 41 26 53 77 8 37 6 38 -36 17z"/>
<path d="M581 1311 c-16 -29 -10 -65 11 -69 23 -4 32 32 15 64 l-14 28 -12
-23z"/>
<path d="M1301 1312 c-13 -25 -14 -59 -2 -66 5 -4 12 0 14 6 4 10 6 10 6 0 1
-7 6 -10 11 -7 14 9 12 48 -4 70 -13 18 -14 18 -25 -3z"/>
<path d="M935 1248 c-13 -36 -14 -50 -6 -67 14 -26 31 -27 32 -3 0 15 1 15 8
-1 6 -17 8 -17 20 -3 16 19 7 62 -18 95 l-18 24 -18 -45z"/>
<path d="M300 1247 c0 -38 17 -58 30 -37 6 10 9 9 13 -1 4 -8 5 -1 4 15 -1 17
-11 35 -24 44 -22 14 -23 13 -23 -21z"/>
<path d="M817 1258 c-29 -29 -36 -54 -13 -45 10 4 13 1 9 -9 -4 -10 0 -12 11
-8 18 7 30 42 24 71 -3 16 -6 15 -31 -9z"/>
<path d="M1055 1248 c8 -39 25 -59 32 -39 5 11 7 11 14 0 6 -10 9 -6 9 12 0
17 -9 32 -25 43 -34 22 -38 20 -30 -16z"/>
<path d="M1571 1254 c-25 -31 -26 -38 -7 -53 20 -17 46 12 46 50 0 36 -12 37
-39 3z"/>
<path d="M755 1150 c-20 -29 -26 -46 -21 -65 8 -31 23 -33 29 -2 l4 22 2 -22
c1 -28 17 -30 31 -3 11 20 3 97 -10 105 -4 3 -20 -13 -35 -35z"/>
<path d="M1106 1145 c-7 -44 5 -85 24 -85 6 0 10 8 11 18 0 14 2 14 8 -3 8
-19 8 -19 20 3 12 22 3 50 -32 95 -20 25 -24 22 -31 -28z"/>
<path d="M430 1145 c0 -2 7 -23 16 -45 11 -27 24 -42 40 -46 31 -8 54 11 47
37 -7 25 -103 76 -103 54z m70 -60 c13 -14 21 -25 18 -25 -2 0 -15 11 -28 25
-13 14 -21 25 -18 25 2 0 15 -11 28 -25z"/>
<path d="M1421 1133 c-40 -20 -62 -60 -40 -74 35 -22 67 -1 87 59 13 38 5 40
-47 15z m9 -36 c0 -2 -10 -12 -22 -23 l-23 -19 19 23 c18 21 26 27 26 19z"/>
<path d="M1570 1123 c-47 -20 -70 -42 -70 -66 0 -19 3 -18 32 9 31 29 30 17
-1 -20 -15 -17 -14 -18 9 -15 18 3 31 17 49 52 13 26 22 49 20 51 -2 2 -20 -3
-39 -11z"/>
<path d="M300 1125 c0 -11 25 -62 38 -77 9 -10 24 -18 35 -18 20 0 19 1 -4 27
l-24 27 28 -18 c34 -21 43 -16 27 14 -14 26 -100 65 -100 45z"/>
<path d="M274 1005 c7 -66 18 -90 47 -106 31 -16 33 -6 9 41 -28 54 -20 62 9
10 26 -47 41 -51 41 -11 0 34 -33 78 -81 105 l-32 19 7 -58z"/>
<path d="M1582 1023 c-49 -41 -65 -73 -53 -105 7 -20 10 -18 35 25 37 62 43
60 11 -3 -21 -41 -23 -50 -10 -50 27 0 65 47 65 78 0 16 3 44 6 61 8 40 -1 39
-54 -6z"/>
<path d="M560 1042 c0 -17 41 -62 57 -62 14 0 13 3 -3 22 -16 19 -16 20 -1 9
22 -17 36 -6 16 14 -18 17 -69 31 -69 17z"/>
<path d="M1006 1000 c-46 -49 -56 -79 -36 -110 10 -16 10 -17 33 30 10 19 15
27 12 17 -21 -73 -14 -86 25 -47 16 16 20 33 20 90 0 39 -2 70 -4 70 -2 0 -24
-22 -50 -50z"/>
<path d="M1304 1040 c-24 -10 -39 -28 -30 -37 3 -3 14 0 23 8 14 10 13 8 -2
-10 -20 -23 -20 -23 -1 -20 24 5 66 69 44 68 -7 0 -23 -4 -34 -9z"/>
<path d="M828 973 c-5 -62 7 -110 33 -124 29 -15 31 -8 14 41 -21 58 -12 63
10 6 20 -52 30 -57 39 -21 8 31 -11 69 -57 113 l-35 34 -4 -49z"/>
<path d="M468 868 c4 -42 25 -78 45 -78 5 0 6 8 2 18 -17 41 -16 45 3 19 21
-31 38 -22 27 13 -6 19 -60 70 -74 70 -3 0 -5 -19 -3 -42z"/>
<path d="M1395 879 c-41 -36 -47 -74 -13 -85 30 -9 58 27 58 77 0 21 -2 39 -5
39 -2 0 -20 -14 -40 -31z m3 -54 c-6 -14 -13 -23 -15 -21 -5 5 15 46 22 46 3
0 -1 -11 -7 -25z"/>
<path d="M617 813 c7 -46 28 -83 48 -83 14 0 14 4 -1 33 l-16 32 26 -30 25
-30 1 26 c0 26 -27 57 -67 78 -21 11 -22 9 -16 -26z"/>
<path d="M1247 819 c-26 -21 -37 -38 -37 -57 l0 -27 26 30 c25 29 25 29 10 3
-9 -15 -16 -30 -16 -33 0 -10 28 -5 39 9 13 15 32 106 22 106 -4 0 -23 -14
-44 -31z"/>
<path d="M243 793 c57 -78 123 -111 166 -84 11 7 0 17 -42 41 -32 18 -57 34
-57 36 0 5 42 -12 80 -31 37 -19 40 -19 40 3 0 46 -75 81 -173 82 l-49 0 35
-47z"/>
<path d="M1559 831 c-47 -15 -67 -30 -78 -61 -10 -29 -9 -31 12 -24 12 3 39
15 60 26 22 11 41 17 44 14 3 -2 -15 -14 -39 -27 -62 -31 -72 -40 -56 -50 42
-27 101 1 157 75 l42 56 -58 -1 c-32 0 -70 -4 -84 -8z"/>
<path d="M463 669 c-29 -11 -53 -24 -53 -28 0 -11 93 -51 118 -51 11 0 30 9
43 20 l24 19 -50 1 c-37 1 -45 4 -30 10 11 5 34 9 50 10 l30 1 -24 19 c-29 25
-42 24 -108 -1z"/>
<path d="M1339 670 l-24 -19 30 -1 c17 -1 39 -5 50 -10 15 -6 7 -9 -30 -10
l-50 -1 24 -19 c13 -11 32 -20 43 -20 22 0 118 39 118 49 0 7 -105 51 -124 51
-8 0 -24 -9 -37 -20z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.9 KiB

90
source/notizen.md Normal file
View file

@ -0,0 +1,90 @@
## Beschreibung
Espe soll dazu dienen die Mitglieder einer Partei-Orgranisations-Struktur (z.B. Landesverband) zu erfassen.
Damit ist es eine Zusatz bzw. eine Alternative zum MGL des Bundesverbandes.
Das Haupt-Ziel dabei ist den Mitgliedern die Nutzung verschiedener Dienste im Netz zu ermöglichen, vorrangig E-Mail abseits von privaten Adressen.
Darüber hinaus sollen mittels Espe relevante Mitglieder-Angaben erfasst und berechtigten Stellen zur Verfügung gestellt werden, welche nicht durch das MGL abgedeckt werden bzw. darüber schlecht oder gar nicht abrufbar sind.
Der Name ist einerseits ein Bezug zum gleichnamigen Pionier-Baum, welcher auch als "Zitter-Pappel" bekannt ist, zum anderen kann man ihn lesen als Abkürzung für "Erweiterte Sächsische Partei-Eingliederung".
## Anwendungsfälle
### Partei-Eintritt
- Bundespartei erfasst und stellt bereit (z.B. mittels Meldung an Mitglieder-Beauftragen der Organisations-Struktur)
- Mitgliedsnummer (z.B. "123456")
- Klarname (z.B. "Karl Liebknecht")
- private E-Mail-Adresse (optional)
- der zuständige Betreuer des Espe-Instanz legt einen Datensatz für das Mitglied mit diesen Angaben an
- folgende Werte leiten sich aus dem Klarname des Mitglieds ab:
- Anzeigename für Netz-Dienste (im einfachsten Fall entspricht dieser Wert genau dem Klarname)
- Anmeldename für Netz-Dienste (z.B. `karl.liebknecht`) (muss eindeutig sein; bei Namens-Dopplung wird ein Index angehangen)
- dem Mitglied wird eine E-Mail an die private Adresse geschickt mit einem Willkommens-Gruß und einem Link zu einem Registrierungs-Formular in Espe, welches folgende Angaben erfasst:
- soll eine pseudonymisierte E-Mail-Adresse (z.B. "mitglied-1234567@dielinke-sachsen.de") bei der Organisations-Struktur angelegt werden?
- soll eine namentliche E-Mail-Adresse (z.B. "karl.liebknecht@dielinke-sachsen.de") bei der Organisations-Struktur angelegt werden?
- sollen eingehende E-Mails an die private Adresse geleitet werden? (empfohlen)
- welches Passwort soll für die Nutzung der Netz-Dienste verwendet werden? (optional; falls nicht ausgefüllt, kein Zugang zu Netz-Diensten)
- durch Absenden des Formulars werden die Daten zur Espe-Instanz übertragen und dort hinterlegt
- der zuständige Betreuer des Espe-Instanz erhält Benachrichtigung über erfolgte Registrierung des Mitglieds
- der zuständige Betreuer des Espe-Instanz veranlasst die Einrichtung der gewünschten E-Mail-Adresse(n) und schaltet das Mitglieder-Konto frei
- Benachrichtigung des Mitglieds
- ggf. über erfolgte Einrichtung der E-Mail-Adresse(n)
- ggf. Zugangsdaten für Dienste (ohne Passwort)
- fehlschlagenden Prüfungen werden nicht immer an das Frontend kommuniziert um potenziellen Angreifern keine Informationen zu liefern
### Änderung des Namens
__\[TODO\]__
### Änderung der privaten E-Mail-Adresse
__\[TODO\]__
### Änderung des Passwortes
- Mitglied gibt Anmelde-Namen oder private E-Mail-Adresse an
- Espe ermittelt das dazu passenden Mitglied-Konten
- Espe prüft:
- ob der letzte Änderungs-Gesuch lang genug zurück liegt (Durchsatzratenbegrenzung)
- ob das Mitglied registriert ist
- ob das Mitglied aktiviert ist
- Espe erzeugt einen Schlüssel und hinterlegt ihn für das Mitglied
- Espe setzt den aktuellen Zeitpunkt als Zeitpunkt des letzten Änderungs-Gesuch des Mitglieds
- Espe sendet eine E-Mail an die private E-Mail-Adresse des Mitglieds mit einem Link zum nächsten Schritt, welcher die ID des Mitglieds sowie den erzeugten Schlüssel transportiert
- Mitglied erhält E-Mail
- Mitglied öffnet Link
- Mitglied gibt das neue Passwort ein und sendet das Formular ab, wobei der mit transportierte Schlüssel ebenfalls übermittelt wird
- Espe prüft ob der Schlüssel korrekt ist
- Espe prüft ob die Passwort-Kriterien erfüllt sind
- Espe speichert das neue Passwort und löscht den hinterlegten Schlüssel
- Espe sendet Benachrichtigung über Passwort-Änderung an private E-Mail-Adresse des Mitglieds
### Partei-Austritt
- Mitglied meldet Austritt
- Meldung an zuständigen Betreuer des Espe-Instanz geht ein
- zuständiger Betreuer des Espe-Instanz löscht Datensatz des betreffenden Mitglieds zum Inkrafttreten des Austritts
## Technische Eckpunkte
- Drei-Teilung in Datenbank, Backend und Frontend
- falls Datenbank und Backend auf verschiedenen Systemen laufen, soll die Übertragung auf einem verschlüsselten Kanal geschehen
- die Übertragung zwischen Clients und Backend- sowie Frontend-Server soll zwingend verschlüsselt sein (z.B. [HSTS](https://de.wikipedia.org/wiki/HTTP_Strict_Transport_Security))
- Sicherheits-Anforderungen
- müssen hoch sein, da es sich um sensible Daten handelt und potentiell ein hohes Interesse am Abgreifen der Daten durch Dritte besteht
- vor Verwendung soll das ganze System ausgiebig durchleuchtet und auf Schwachstellen abgeklopft werden
- Passwörter werden nicht im Klartext gespeichert
- ["mobile first"](https://www.itportal24.de/ratgeber/mobile-first)-Ansatz für Frontend verfolgen
## Logik
__\[TODO\]__

128
tools/build Executable file
View file

@ -0,0 +1,128 @@
#!/usr/bin/env python3
import sys as _sys
import os as _os
import argparse as _argparse
def string_coin(
template,
arguments
):
result = template
for (key, value, ) in arguments.items():
result = result.replace("{{%s}}" % key, value)
return result
def file_read(path):
handle = open(path, "r")
content = handle.read()
handle.close()
return content
def file_write(path, content):
handle = open(path, "w")
handle.write(content)
handle.close()
def main():
## consts
conf = {
"title": "Espe",
"source_directory": "source"
}
## args
argument_parser = _argparse.ArgumentParser()
argument_parser.add_argument(
"-t",
"--target-directory",
type = str,
default = "build",
)
argument_parser.add_argument(
"-f",
"--format",
type = str,
action = "append",
choices = ["markdown", "html", "pdf"],
default = [],
)
args = argument_parser.parse_args()
## vars
target_directory = _os.path.abspath(args.target_directory)
formats = (["html"] if (len(args.format) <= 0) else args.format)
## exec
_os.makedirs(args.target_directory, exist_ok = True)
for format_ in formats:
if (format_ == "markdown"):
target_path = string_coin(
"{{target_directory}}/espe.md",
{
"target_directory": target_directory,
}
)
file_write(
target_path,
string_coin(
"# {{title}}\n\n{{content}}",
{
"title": conf["title"],
"content": file_read(
string_coin(
"{{source_directory}}/notizen.md",
{
"source_directory": conf["source_directory"],
}
)
),
}
)
)
_sys.stdout.write("%s\n" % target_path)
elif (format_ == "html"):
target_path = string_coin(
"{{target_directory}}/espe.html",
{
"target_directory": target_directory,
}
)
_os.system(
string_coin(
"pandoc {{source_directory}}/notizen.md --to=html --title={{title}} --metadata='title:{{title}}' --output={{target_path}}",
{
"source_directory": conf["source_directory"],
"target_path": target_path,
"title": conf["title"],
}
)
)
_sys.stdout.write("%s\n" % target_path)
elif (format_ == "pdf"):
target_path = string_coin(
"{{target_directory}}/espe.pdf",
{
"target_directory": target_directory,
}
)
_os.system(
string_coin(
"pandoc {{source_directory}}/notizen.md --to=pdf --title={{title}} --metadata='title:{{title}}' --output={{target_path}}",
{
"source_directory": conf["source_directory"],
"target_path": target_path,
"title": conf["title"],
}
)
)
_sys.stdout.write("%s\n" % target_path)
else:
raise ValueError("invalid format: %s" % format_)
main()