Dieses Template erzeugt für eine Datei mit dem Layout layout: file
die Seite,
die am Ende im Browser zu sehen ist.
Solche Dateien gibt es im Know-How-Bereich und im ft:pedia-Bereich.
Das Format einer solchen Datei ist hier beschrieben.
Dieses Template liegt daher unter layouts/_default/file.html
.
Fangen wir vorne an.
{{ define "main" }}
{{ $date_format_string := "2.1.2006" }}
{{ $wir_email := .Site.Params.email_uns }}
{{ define "main" }}
definiert einen Block für den eigentlichen Seiteninhalt.
Als nächstes geben wir das Muster vor, mit dem die Datumsangaben formatiert werden. Eine Erklärung, warum das Muster genau so aussieht, gibt es bei Hugo.
Aus der globalen Angabe, die für die ganze Website gilt,
.Site.Params.email_uns
, holen wir uns unsere Mail-Adresse und
speichern sie in der Variablen $wir_email
.
Wir überprüfen nun, ob die Pflichtangaben alle anwesend sind! Falls nicht, gibt es sehr deutlich “Mecker”!
{{/* --- Überprüfe ob die Pflichtangaben alle vorhanden sind --- */}}
{{/* --- Check all mandatory field entries are available --- */}}
{{ if not .Params.title }}
{{ errorf "Oh oh, der Seitentitel 'title' fehlt oder ist leer in Seite %q" .Path }}
{{ end }}
Da kommt auch schon der erste Kniff, die Abfrage ob der Titel ‘title’ im
Frontmatter definiert ist (z. B. title: "Flip Flop Baustein"
), leer blieb
(title:
) oder aber das title:
gar komplett fehlt.
Die etwas eigenwillige Hugo-Syntax if not .Params.title
könnte in anderer
Schreibweise if !defined("title:") || (title == "")
lauten.
Wenn die Bedingung zutrifft, wird die Zeile
errorf "Oh oh, der Seitentitel 'title' fehlt oder ist leer in Seite %q" .Path
ausgeführt.
Hugo erzeugt dann eine Fehlermeldung, stoppt unmittelbar und produziert keine
Seite.
Das %q
zusammen mit .Path
gibt die fehlerhafte Datei mitsamt Zugriffspfad
preis; ein Service, den der Admin sehr schätzt.
Außer dem Titel title
gehören auch noch Dateiname file
, Datum des Uploads
date
, und Name des hochladenden Nutzers uploadBy
zu den Pflichtfeldern.
{{ $fname := .Params.file }}
{{ if not $fname }}
{{ errorf "Oh oh, der Dateiname 'file' fehlt oder ist leer in Seite %q" .Path }}
{{ end }}
$fname := .Params.file
weist den Namen der Datei an eine eigene Variable zu.
Das macht den Code später etwas übersichtlicher.
Der Rest der Prüfung erfolgt baugleich zum Code für den Titel, also
Fehlermeldung mit exakter Angabe der fehlerhaften Datei, falls der Dateiname
fehlt.
{{ $uploadDate := .Params.Date }}
{{ if not $uploadDate }}
{{ errorf "Oh oh, das Hochladedatum 'date' fehlt oder ist leer in Seite %q" .Path }}
{{ end }}
Das Datum ´date` sollte sich jetzt schon selbst erklären.
{{ $uploader := .Params.uploadBy }}
{{ if not $uploader }}
{{ errorf "Oh oh, der Nutzername 'uploadBy' fehlt oder ist leer in Seite %q" .Path }}
{{ end }}
Für den verantwortlichen Nutzer, also denjenigen, der den Upload gemacht hat,
ist im Frontmatter der Eintrag uploadBy
vorgesehen.
Noch Fragen?
Damit ist die grundsätzlich “Anwesenheitskontrolle” erledigt. Allerdings gibt es noch einen weiteren notwendigen Test. Wie im Abschnitt über das Frontmatter erklärt, ist der Nutzername als Liste angelegt. Theoretisch kann die Liste auch mehrere Namen umfassen, das ist hier aber nicht sinnvoll. Die korrekte Angabe enthält exakt einen Namen!
{{ $uploaderCount := 0 }}
{{ $uploaderCount = len $uploader }}
{{ if gt $uploaderCount 1 }}
{{ errorf "Oh oh, zu viele 'uploadBy' in Seite %q. Nur ein Nutzername erlaubt!" .Path }}
{{ end }}
Zunächst wird die Anzahl der Nutzer angelegt und auf ‘0’ gesetzt
($uploaderCount := 0
), anschließend die Länge des Eintrags (die Zahl der
Listeneinträge!) abgeholt ($uploaderCount = len $uploader
).
Nun erfolgt eine Abfrage, ob die Anzahl der Nutzer größer als ‘1’ ist
(if gt $uploaderCount 1
).
Falls ja, erfolgt die bewährte Fehlermeldung und Hugo beendet seinen Dienst.
Der Wert ‘0’ kann hier nicht auftreten, da ansonsten bereits die vorherige
Kontrolle ihren eigenen Fehler produziert hätte.
Faktisch käme if ne $uploaderCount 1
(if $uploaderCount != 1
) zum exakt
gleichen Ergebnis.
Für den Fall, dass es sich um eine aus der alten ftc importierte Seite handelt,
wird abgefragt ob es außer dem imported
-Eintrag auch eine gefüllte
legacy_id
gibt.
Falls nicht, gibt es sehr deutlich eine Fehlermeldung.
{{ if .Params.imported }}
{{ if not .Params.legacy_id }}
{{ errorf "'legacy_id' fehlt für Seite %q. Wenn der Eintrag importiert wurde, muss auch eine Legacy-ID vorhanden sein!" .Path }}
{{ end }}
{{ end }}
Auf diese Art stellen wir hoffentlich sicher, dass die Importe komplett sind.
Nun kommt die Liste mit den Autoren an die Reihe. Die Autoren sind wahlfrei, die Liste darf leer sein. Daher entfällt die Abfrage, ob sie definiert ist.
{{/* --- Lies ein was sonst noch benötigt wird --- */}}
{{/* --- Read additional data --- */}}
{{ $authorsCount := 0 }}
{{ $authors := .Params.konstrukteure }}
{{ if $authors }}
{{ $authorsCount = len $authors }}
{{ end }}
$authorsCount := 0
initialisiert die neue Variable auf ‘0’,
$authors := .Params.konstrukteure
weist die Liste an eine Variable zu.
Das erspart Tiparbeit und macht den Code später etwas übersichtlicher.
Falls wenigstens ein Autor definiert ist (if $authors
), wird die Anzahl der
Autoren passend eingestellt ($authorsCount = len $authors
).
Ansonsten bleibt $authorsCount
auf ‘0’ stehen.
Damit wäre der erste Teil der Vorbereitung auch schon erledigt - wenn es da nicht ein paar Altlasten aus der alten ftc gäbe. Es existieren tatsächlich Uploads ohne Angabe von Autor oder Nutzer! Würden diese Einträge ins Frontmatter übersetzt, könnte Hugo wegen des fehlenden Nutzers die Seite nicht bauen (Stichwort: Fehlermeldung an den Admin). Also wird mit einem kleinen Kniff und einer Ausnahmebehandlung einerseits die “Anwesenheitskontrolle” von eben befriedigt, aber die korrekte Information dann doch noch erzeugt.
{{/* --- Spezialbehandlung für Altlasten aus den Anfängen der ftc --- */}}
{{/* --- Special handling of legacy ftc problem sites --- */}}
{{ if eq $uploader (slice "-LegacyAdmin-") }}
{{ $uploaderCount = 0 }}
{{ end }}
Zuerst wird geschaut, ob der ‘magische’ Nutzer -LegacyAdmin-
angegeben ist.
Im Frontmatter steht dafür
uploadBy:
- "-LegacyAdmin-"
Dieser Nutzername kann (und darf!) regulär sonst nicht erzeugt werden.
Falls nun ‘-Legacy-Admin-’ eintragen ist, wird die Anzahl der Nutzer auf ‘0’
zurückgestellt.
In dem if-Konstrukt wird ein bisschen getrickst, um Hugo auf die richtige Fährte
zu bringen.
Normalerweise ist hier ein Vergleich zweier Strings fällig
(if $uploader == "-LegacyAdmin-"
).
Nun ist Hugo aber etwas anders drauf und bietet hier gleich den Vergleich
zweier Listen an. $uploader
ist nämlich bereits eine Liste (mit genau einem
Eintrag), also wird per slice "-LegacyAdmin-"
schnell eine zweite Liste mit
genau einem Eintrag angefertigt.
‘slice’ ist hier das Zauberwort.
Nun kann das mit dem if
auch klappen.
Für die Autoren gibt es das auch.
{{ if eq $authors (slice "-?-") }}
{{ $authorsCount = 0 }}
{{ end }}
Wie hier eine absichtlich leere Autorenliste ermittelt und die Anzahl der Autoren im Bedarfsfall auf ‘0’ zurückgestellt wird, sollte jetzt ohne neue Erklärung klar sein. Die aus alten Zeiten fehlende Angabe zum Autor ist per
konstrukteure:
- "-?-"
im Frontmatter definiert.
Kommen wir nun zu ein bisschen ‘Vorgeplänkel’. Das müsste hier nicht stehen, macht jedoch den späteren Code deutlich übersichtlicher. Ihr werdet schon sehen warum. Aber der Reihe nach.
Auf der fertigen Seite gibt es einen “Haftungsausschluss”. Ein Bestandteil dabei ist die Möglichkeit per e-mail auf einen inhaltlichen Fehler der dargestellten Seite aufmerksam zu machen. Als puren Luxus für den Nutzer, und zur Unterstützung der Admins, gibt es einen vordefinierten Text, der den Link zur bemängelten Seite bereits enthält. Dieser Text ist im Zusammenbau nicht ganz trivial und erfolgt daher bereits vorab.
{{/* --- Vorgeplänkel --- */}}
{{/* --- Prologue --- */}}
{{ $email_subject := "Da stimmt was nicht!" }}
{{ $scratch2 := newScratch }}
{{ printf "Hallo ihr Lieben,\n\n" | $scratch2.Set "email_body" }}
{{ printf "ich möchte Euch auf ein Problem mit der ftc-Seite hinweisen:\n" | $scratch2.Add "email_body" }}
{{ printf "%s%s\n" .Site.BaseURL (path.Join .File.Dir (split (lower $fname) "." | first 1)) | $scratch2.Add "email_body" }}
{{/* printf "%s\n" (path.Join .File.Dir $fname) | $scratch2.Add "email_body" */}}
{{/* printf "%s\n" .Path | $scratch2.Add "email_body" */}}
{{/* printf "(Bitte diese Referenzen nicht löschen!)\n" | $scratch2.Add "email_body" */}}
{{ printf "\n<Problembeschreibung>" | $scratch2.Add "email_body" }}
Drei Zeilen sind derzeit auskommentiert, können aber zugeschaltet werden, um außer dem URL der Seite auch noch die Dateipositionen mitzugeben. Die Dateipfade ergeben sich jedoch aus dem URL und so muss die E-Mail nicht mit dieser Information überfrachtet werden.
Für den Text wird zunächst ein “Notizzettel” angelegt:
$scratch2 := newScratch
.
Die erste Zeile wird per $scratch2.Set
zugewiesen, die folgenden Textbausteine
fügt $scratch2.Add
jeweils hinten an.
printf "%s%s\n"
baut aus dem Seitennamen (https://www.ftcommunity.de oder
wo auch immer sie gerade liegt und per .Site.BaseURL
zu erfragen) und ein
bisschen Stringbastelei
(path.Join .File.Dir (split (lower $fname) "." | first 1)
)
den kompletten Namen der Unterseite zusammen.
Dabei sorgt lower $fname
für eine konsequente Kleinschreibung der URL,
so wie sie im Browser auch angezeigt wird.
Ein Klick auf den späteren Link öffnet das E-Mail-Programm des Besuchers und
bietet die Vorbelegung in einer neu zu schreibenden E-Mail an.
Das sieht dann so aus (ungefähr, der Link variiert mit dem Seitennamen):
Hallo ihr Lieben,
ich möchte Euch auf ein Problem mit der ftc-Seite hinweisen:
https://www.ftcommunity.de/knowhow/elektronik/silberlinge/flipflop/
<Problembeschreibung>
Mit diesen Zeilen endet das Vorgeplänkel und der produktive Teil, also der HTML-Code, der vom Browser dargestellt wird, tritt auf den Plan.
{{/* --- HTML-Seite zusammenbauen --- */}}
{{/* --- Assemble the HTML site --- */}}
<div class="padding highlightable">
{{ partial "topbar.html" . }}
<div id="body-inner">
<h2>{{.Title}}</h2>
Zunächst gibt es den Start der Seite und die einheitliche Kopfzeile.
Für die Kopfzeile gibt es so eine Art “Unterprogramm”, das im Framework
an anderer Stelle vordefiniert ist.
Das ist die Zeile {{ partial "topbar.html" . }}
.
Danach kommt sofort der Seitentitel in Form von <h1>{{.Title}}</h1>
.
Das HTML-tag <h2>
startet die Überschrift, </h2>
beendet sie.
Wie sie genau aussieht, ist irgendwo im Framework ‘versteckt’ - global für
alle Seiten. Das Stichwort dazu heisst “Stylesheet” und hat eine
eigene Beschreibung.
In einem eigenen Absatz wird der Inhaltsbereich aus der jeweiligen .md-Datei unterhalb des Frontmatter eingefügt.
<p>
{{ .Content }}
</p>
<p>
und </p>
definieren den Absatz, .Content
füllt ihn.
Nach dieser Beschreibung zum Downloadfile - die vom Nutzer erstellt wurde - soll das anklickbare Icon für den Download folgen.
<br />
<p>
<a href="../{{ $fname }}" style = "float: left; margin: 1em 1.5em 1em 0;">
{{ partial "download-icon.html" . }}
</a>
Für ein etwas weniger gedrängtes Aussehen gibt es zuerst noch einen
Zeilenvorschub (<br />
) und ein neuer Absatz startet mit <p>
.
Der Hyperlink wird ganz klassisch mittels <a href="../{{ $fname }}">
eingeleitet. Dabei ist die Sequenz ../
vor dem Dateinamen ($fname
)
essentiell. Ohne diese Angabe würde der Link falsch umgesetzt und die Datei
nicht gefunden! Das ist wohl eine Eigenheit von Hugo, man muss sie halt kennen.
Per Default erscheint das Icon mittig auf der Seite, Text wird
nur oberhalb und unterhalb zugelassen.
Hier soll das Icon allerdings linksbündig angeordnet sein und der weitere
Text auf der rechten Seite um das Icon herumfliessen.
Die Angabe style=
zusammen mit css
-Syntax ermöglicht den gewünschten
Effekt. Dabei bewirkt float: left;
die Anordnung des Icons links im
umlaufenden Text.
Danach sorgt margin:
für eine Feinplatzierung des
Icons durch Angabe der Randbreiten (in dieser Reihenfolge!):
1em
(Abstand zur Textzeile obendrüber - hier Absatzbeginn)1.5em
(Abstand zum rechts umlaufenden Text)1em
(Abstand zur Textzeile untendrunter - hier Absatzende)0
(Abstand zum linken Rand des Absatzes)Die Einheit em
steht kurz für “die Breite des Buchstaben ‘m’ im Font”.
Damit skaliert die Größe des Icons mit der Größe der Schriftzeichen und die
Gestaltung bleibt beim Verändern der Zoomstufe unverändert.
Mehr Doku:
float
: https://www.w3schools.com/cssref/pr_class_float.aspmargin
: https://www.w3schools.com/cssref/pr_margin.aspem
: https://www.w3schools.com/css/css_units.aspDiese Angaben zur Größe und Position des Icons sind feinstsäuberlich auf die drei weiter unten beschriebenen Textzeilen abgestimmt!
Anstelle eines Textes zum Anklicken soll hier ein kleines Bild, ein Icon, stehen. Die Zeilen zum Bild haben es nun allerdings “in sich”:
{{ partial "download-icon.html" . }}
partial "download-icon.html" .
ist eine Art “Unterprogramm” oder auch “Makro”.
Diese Art der Auslagerung gestattet es. die Funktion “Generisches Icon passend
zur Dateiendung eines Files” auch von anderen Stellen aus zu nutzen;
und so wird der Code deutlich besser lesbar. Das partial ‘download-icon’
hat seine eigene Doku. Siehe auch
https://gohugo.io/templates/partials/
</a>
schließt den Hyperlink ab.
Dieses Stück Code erzeugt also ein anklickbares Bild und der Browser fragt üblicherweise, wohin die referenzierte Datei gespeichert werden darf.
Im gleichen Absatz (sozusagen rechts oben vom Bild) kommt zunächst der Name der Downloaddatei mit einer Angabe zur Dateigröße.
{{ $fname }}
( {{- partial "download-size.html" . -}} )
Der Dateiname wird als Text angezeigt.
Eine ‘(’ kommt dahinter, partial "download-size.html" .
liefert die Größe
mit Einheit und eine ‘)’ schließt die Zeile ab.
Nun kommt die Information über den / die Autor(en).
<small>
<br />
Diese Angabe (und auch noch die nachfolgende) ist vom Dateinamen durch
eine kleinere Schriftgröße abgesetzt (<small
>) und der Text beginnt
in einer neuen Zeile (<br />
).
Der Code für den Satzbau ist ziemlich unschön zu lesen, weil die diversen Textbausteine in Abhängigkeit von diversen Angaben ausgewählt werden. Hugo-Code, HTML und Text scheinen wirr miteinander verwoben.
{{- if gt $authorsCount 0 -}}
Erstellt
{{- if eq $authors $uploader }}
und hochgeladen
{{- end }}
von
{{ range $index, $name := $authors -}}
{{- if and (gt $index 0) (sub $authorsCount 1 | lt $index) -}}
,
{{- else if gt $index 0 }}
und
{{- end }}
{{ if eq $authors $uploader -}}
<a href = "{{ $.Site.BaseURL }}konstrukteure/{{ $name|urlize }}">{{ $name }}</a>
{{- else -}}
<i>{{ $name -}}</i>
{{- end -}}
{{- end -}}
.
{{- else -}}
Leider ist kein Autor angegeben.
{{- end -}}
Als erste “Amtshandlung” wird per if gt $authorsCount 0
festgestellt, ob es
einen Autor gibt.
Falls dem nicht so ist, erledigt der else
Zweig die nötige Angabe:
“Leider ist kein Autor angegeben.”
Der übriggebliebene Rest bei Zutreffen der Bedingung $authorsCount > 0
erledigt den Zusammenbau eines lesbaren Satzes.
Erstellt
{{- if eq $authors $uploader }}
und hochgeladen
{{- end }}
von
Lässt den Satz je nach Übereinstimmung von Autor und Nutzer unterschiedlich beginnen.
Bedingung | Satzanfang |
---|---|
$authors == $uploader | Erstellt und hochgeladen von |
$authors != $uploader | Erstellt von |
Es folgt die Auflistung der Autoren, mit Komma, ‘und’ und allem, was so dazugehört.
{{ range $index, $name := $authors -}}
{{- if and (gt $index 0) (sub $authorsCount 1 | lt $index) -}}
,
{{- else if gt $index 0 }}
und
{{- end }}
{{ if eq $authors $uploader -}}
<a href = "{{ $.Site.BaseURL }}konstrukteure/{{ $name|urlize }}">{{ $name }}</a>
{{- else -}}
{{ $name -}}
{{- end -}}
{{- end -}}
.
Das Schleifenkonstrukt range $index, $name := $authors
arbeitet sich durch
alle vorhandenen Einträge.
Dabei zählt $index von ‘0’ aus hoch - der erste Autor hat dabei den Index ‘0’,
der letzte Autor den Index ‘$authorsCount - 1’ (oder wie Hugo es ausdrückt:
sub $authorsCount 1
).
Der Ausdruck if and (gt $index 0) (sub $authorsCount 1 | lt $index)
wäre als
if ($index > 0) && ($index < ($authorsCount - 1))
wohl gewohnter.
Er sorgt dafür, dass das ‘,’ nur nur vom ersten bis zum vorletzten Autor der
Liste eingefügt wird.
Besteht die Liste aus weniger als drei Autoren, kommt kein ‘,'.
Trifft die “Kommaregel” nicht zu, kommt else
zum Zuge.
Das ist entweder der erste Autor ($index = 0) oder der letzte Autor der Liste
($index > 0) und insgesamt erteilt else if gt $index
nur im letzten Fall
die Erlaubnis das ‘und’ einzufügen.
Nun kommt noch eine Unterscheidung ob Autor und Nutzer identisch sind
(if eq $authors $uploader
).
Falls ja, gibt es den Autorennamen mit Hyperlink hinterlegt (<a href = ...
).
Falls nein, kann es ein nicht registrierter Mensch sein und so gibt es
pauschal keinen Hyperlink dazu ($name
).
Eine besondere Eigenschaft dieses Konstrukts ist: Nur wenn beide Listen exakt
einen und den gleichen Eintrag haben, wird der Hyperlink gegeben, sonst nie.
Jetzt folgt noch der ‘.’ und der Satz ist fertig gebaut.
Die seltsamen {{-
und -}}
bewirken eine Unterdrückung sämtlicher
‘Whitespace’-Leerzeichen entweder vor oder hinter dem Hugo-Code.
Ohne die wäre beispielsweise zwischen Wort und Satzzeichen eine unerwünschte
Lücke.
Frontmatter | Satzende |
---|---|
konstrukteure: - "Hinz & Kunz" |
Hinz & Kunz. |
konstrukteure: - "Hinz & Kunz" - "Miez & Maunz" |
Hinz & Kunz und Miez & Maunz. |
konstrukteure: - "Hinz & Kunz" - "Miez & Maunz" - "Alter Sack" |
Hinz & Kunz, Miez & Maunz und Alter Sack. |
konstrukteure: - "Hinz & Kunz" - "Miez & Maunz" - "Alter Sack" - "Niemand Sonst" |
Hinz & Kunz, Miez & Maunz, Alter Sack und Niemand Sonst. |
Das war ein dicker Brocken.
{{ if not (eq .Params.license "unknown") }}
Lizenz: {{- partial "download-license.html" . -}}
{{ end }}
Wenn der Autor der Download-Datei eine Lizenz angegeben hat,
die anderen die Nutzung erlaubt, wird hier ein Partial aufgerufen,
das diese Lizenz darstellt.
Für alle aus der alten Seite importierten Dateien gilt:
license: unknown
.
Vergleichsweise entspannt ist die Darstellung, wann die Datei hochgeladen wurde und von wem.
<br />
Hochgeladen
{{ if eq $uploaderCount 1 -}}
{{ if not (eq $authors $uploader) -}}
von
<a href = "{{ $.Site.BaseURL -}} uploadBy/ {{- delimit $uploader ", " | urlize -}}">{{- delimit $uploader ", " -}}</a>
{{ end -}}
{{ end -}}
am
{{ dateFormat $date_format_string $uploadDate -}}
.
Die Auskunft, wer den Upload wann gemacht hat, kommt in eine neue Zeile.
<br />
kennen wir ja jetzt schon.
Der Satz beginnt grundsätzlich mit ‘Hochgeladen’.
Gibt es genau einen Nutzer in der Liste (if eq $uploaderCount 1
), wird
mittels if not (eq $authors $uploader)
untersucht, ob Autor und Nutzer
nicht identisch sind.
In dem Fall wird der Satzteil ‘von >Nutzer<’ eingefügt.
Der Nutzername wird außerdem mit einem Hyperlink hinterlegt.
In allen anderen Fällen entfällt dieser Teil.
delimit
wird normalerweise benutzt, um eine Liste mit Trennzeichen zu
versehen und in einen zusammengesetzten String umzuwandeln.
Hier wird es ‘missbraucht’ um den einen Listeneintrag in einen String
umzuwandeln.
Die Angabe ‘am’ ergänzt durch das formatierte Datum beendet den Satz.
Bedingung | Satz |
---|---|
$uploaderCount != 1 | Hochgeladen am 5.1.1900. |
$uploaderCount == 1 UND$authors == $uploadBy |
Hochgeladen am 5.1.1900. |
$uploaderCount == 1 UND$authors != $uploadBy |
Hochgeladen von Alter Sack am 5.1.1900. |
</small>
</p>
Der Bereich mit der Kleinschrift endet hier (</small>
) wie auch der Absatz
(</p
).
Es folgt nun ein weiterer Absatz in kleiner Schrift.
<p>
<small>
Zweck der Übung ist ein Hinweistext, der mit einem fett gesetzten ‘Hinweis:’ beginnt.
<b>Hinweis:</b>
Das Herunterladen, Öffnen und Ausführen von Dateien geschieht auf
eigene Gefahr.
Wir können keine Verantwortung für eventuelle Fehler oder gar Schäden
übernehmen.
Falls Du einen Fehler findest, kontaktiere bitte
Ein ‘uns’ beendet den Satz. Das ‘uns’ ist mit einem Hyperlink hinterlegt. Eine Verlinkung zu dem oder den Autoren bzw. dem User, der den Upload gemacht hat, ist nicht vorgesehen, weil wir hier keine Kontaktdaten dieses Users haben. Hier wird der Versand einer E-Mail an das Betreuungsteam vorbereitet.
<a href="mailto:{{$wir_email}}?subject={{$email_subject}}&body={{$scratch2.Get "email_body"}}">uns</a>.
$wir_email
gibt den Adressaten an, $email_subject
liefert den Betreff und
$scratch2.Get "email_body"
enthält dann die Nachricht.
Das ist der lange Text aus dem Vorgeplänkel oben “Hallo ihr Lieben, …".
Der Absatz mit dem Hinweistext wird beendet (Kleinschrift aus und Absatzende).
</small>
</p>
Der spezielle Inhalt einer Downloadseite ist damit beendet, jetzt folgt noch die Navigation.
<div id="navigation">
Die Navigation wird per <div id="navigation">
eingeleitet. Das hilft, den
Abschnitt per Texteditor schnell aufzuspüren.
{{ $prev := slice }}
{{ $next := slice }}
{{ $node := . }}
{{ $match := 0 }}
Zunächst werden einige Variablen definiert, die wir weiter unten noch brauchen.
{{ $neighbours := slice }}
{{ range .Parent.Pages.ByTitle }}
{{ if gt .Parent.Pages 1 }}
{{ $neighbours = append . $neighbours }}
{{ end }}
{{ end }}
{{ $neighbours = append .Parent.Sections.ByTitle $neighbours }}
Jetzt suchen wir alle Nachbarn. Das sind andere Seiten,
die das gleiche Elternverzeichnis haben,
sowie Unterverzeichnisse (.Sections
) im gleichen Verzeichnis.
Diese Liste der Nachbarn ist nach dem Titel alphabetisch sortiert.
{{ with $neighbours }}
{{ $i := 0 }}
{{ range . }}
{{ if eq . $node }}
{{ $match = $i }}
{{ end }}
{{ $i = add $i 1 }}
{{ end }}
{{ end }}
{{ $prev = index $neighbours (sub $match 1) }}
{{ $next = index $neighbours (add $match 1) }}
Jetzt finden wir heraus, wo in dieser Liste der Nachbarn die aktuelle Datei liegt.
Ihren Index ordnen wir der Variablen $match
zu.
Der vorige Eintrag in der Liste ist der Vorgänger ($prev
),
der nächste der Nachfolger ($next
).
{{ with $prev }}
<a class="nav nav-prev" href="{{.RelPermalink}}" title="{{.Title}}"> <i class="fa fa-chevron-left"></i></a>
{{else}}
{{with .Parent}}
<a class="nav nav-prev" href="{{.RelPermalink}}" title="{{.Title}}"> <i class="fas fa-arrow-up"></i></a>
{{end}}
{{end}}
{{with $next}}
<a class="nav nav-next" href="{{.RelPermalink}}" title="{{.Title}}"> <i class="fa fa-chevron-right"></i></a>
{{else}}
{{with .Parent}}
<a class="nav nav-next" href="{{.RelPermalink}}" title="{{.Title}}"> <i class="fas fa-arrow-up"></i></a>
{{end}}
{{end}}
</div>
Die Navigation ist in zwei Hälften aufgeteilt. Eine Hälfte behandelt die horizontale Navigation “nach links”, die andere, baugleiche, Hälfte bedient die Navigation “nach rechts”.
Die linke Hälfte startet mit {{with $prev }}
. Auf die Art schaltet
man Hugo in den Kontext des nächsten Eintrags aus der Sammlung
der Seiten.
Mit der Info aus dem Kontext des vorigen Nachbarn wird nun ein Hyperlink gebaut:
<a class="nav nav-prev" href="{{.RelPermalink}}" title="{{.Title}}"> <i class="fa fa-chevron-left"></i></a>
<a
leitet die Hyperlink-Sequenz ein. Mittels der
CSS-Klasse nav nav-prev
bekommt der Hyperlink seinen Platz, seine Gestaltung
und sein Verhalten zugewiesen (derzeit links, vor dem Seiteninhalt und mit
Animationseffekten wenn die Maus drüberläuft). Es folgt der unvermeidliche
Link selbst href="{{.RelPermalink}}"
, bei dem die URL der betreffenden
Seite von Hugo erzeugt wird ({{.RelPermalink}}
) - gemäß Kontext vom Nachbarn.
title="{{.Title}}">
gibt dann noch den Namen der Zielseite aus deren
Frontmatter in den Tooltip ({{.Title}}
). So sieht man, wohin die Reise gehen
wird, wenn die Maus über den Link gezogen wird. Jetzt fehlt noch der Text, der
als klickbarer Link angezeigt wird. Hier ist es ein ‘<’, das aus einem
speziellen Font ausgewählt wurde: <i class="fa fa-chevron-left"></i>
.
Ordnungsgemäß schließt ein </a>
den Hyperlink ab. Puh, geschafft.
Was passiert nun wenn es keinen älteren (linken) Nachbarn gibt?
Dann wirkt das with
wie ein if
und wir betreten den {{else}}
Zweig.
{{with .Parent}}
versucht nun den Kontext der übergeordneten Ebene zu
erreichen. Der Pfad soll diesmal eine Ebene nach oben führen. Der Hyperlink
kann nun aus dem Kontext des Parent gebaut werden, siehe oben. Der einzige
Unterschied ist hier das Symbol in der Navigation. Diesmal wird die
Richtung durch einen Pfeil nach oben angezeigt: <i class="fas fa-arrow-up"></i>
.
Und was ist wenn es auch keinen Parent gibt?
In unserem Fall gibt es immer einen Parent. Der fehlt lediglich
auf der Homepage, die ja die Wurzel darstellt. Trotzdem wirkt auch hier wieder
das with
wie ein if
und baut keinen Hyperlink nach oben, wenn es keinen
Parent gibt.
Das {{end}}
schließt den Bau der linksseitigen Navigation ab.
Die Navigation auf der rechten Seite ist
nav nav-next
) und{{with $next }}
) bzw. “nach oben” ({{with .Parent}}
).Gibt es weder einen linken noch einen rechten Nachbarn, so führen halt beide Navigationen nach oben.
Der Abschnitt der Navigation wird durch </div>
geschlossen.