Know-how

Unser Seitenbereich “Know-how” enthält alle Downloads mit technischem Inhalt und auch wiki-Seiten. Die wiki-Seiten stammen noch aus der alten ftc-Seite, aktuell gibt es keine Möglichkeit wiki-Seiten neu anzulegen oder vorhandene Seiten zu bearbeiten. Für eine Veröffentlichung Deines Wissens ist die ft:pedia die geeignetere Plattform.

Hier werfen wir einen Blick auf die ‘Technik’ der Seite im Hintergrund.

Inhalt

Download-Datei

Begleitdaten zum Download (.md)

Download Seitenansicht steuern (file.html)

Wiki-Inhalt

Wiki-Artikel (.md)

Wiki Seitenansicht steuern (wiki.html)

Verfügbare Inhalte auflisten (list.html)


Download-Datei

Wie im Bilderpool gibt es die Zweiteilung in die Datei zum Download und eine zugehörige Markdown-Datei mit Beschreibung und Info zur Darstellung.

Das Dateiformat der Download-Datei kann alles sein, auch ein Bild (wobei ein Bild eher in den Bilderpool-Bereich gehört). In der alten ftc sind im Download-Bereich tatsächlich ein paar Bilder versteckt. Aber zurück zum Thema.

Aus organisatorischen Gründen sind die Download-Datei und die Datei mit der Beschreibung namensgleich. Das muss allerdings nicht zwingend so sein. Ein Admin freut sich allerdings über sofort sichtbare Bezüge. Aktuell unterscheidet sich die Beschreibung vom Download nur in der Datei-Endung. Die Beschreibung ist immer in einer .md-Datei untergebracht. [Das geht genau so lange gut, bis jemand mal eine Markdowndatei mit der Endung .md hochlädt.] Auf der Platte sieht das dann etwa so aus:

$ ls
grundbaustein.md
grundbaustein.pdf
flipflop.md
flipflop.pdf

grundbaustein.md enthält die Beschreibung zum Download grundbaustein.pdf und flipflop.md enthält die Beschreibung zum Download flipflop.pdf.

Zurück zur Inhaltsübersicht

Download-Datei Beschreibung (.md)

Strukturell gibt es keinen großen Unterschied zum Bilderpool. Zuerst haben wir den “Frontmatter”-Abschnitt. Er enthält diese Felder (die Reihenfolge ist nicht so wichtig, aber eine einheitliche Anordnung macht es den Admins leichter):

Frontmatter Angabe Comment
--- Leitet den Frontmatter-Block ein
layout: "file" Pflicht Das Layout für einen Download-Eintrag heißt "file".
title: "Flip Flop Baustein" Pflicht Der Titel, der als Überschrift oben erscheint
date: 2005-06-06T00:00:00+0200 Pflicht Das Datum des uploads - wird automatisch erzeugt.
Codierung: yyyy-mm-ddThh:mm:ss+hhmm
Beim manuellem Erstellen neuer Seiten bitte die Zeitzone (`+0100` MEZ bzw. `+0200` MESZ nicht vergessen)! Es wird empfohlen vorhandene Archetypes zu nutzen. Hugo kümmert sich dann um das korrekte Datum mitsamt der Zeitzone. Für legacy Dateien die älter als 2 h sind, ist die Angabe der Zeitzone unerheblich und kann entfallen. Für alles Aktuelle soll sie rein sonst wird die Seite von hugo nicht (zur richtigen Zeit) gebaut.
file: "flipflop.pdf" Pflicht Das zugehörige Download-File. Vorzugsweise heißen Download-File und Markdownfile gleich. Das hilft den menschlichen Admins sehr zu erkennen was zusammen gehört. Beispiel: flipflop.pdf <=> flipflop.md
konstrukteure:
- "Michael Becker"
Option 'Autoren' wäre hier von der Wortwahl geschickter, 'konstrukteure' ist technisch aber das gleiche. Also nennen wir es genau so wie es auch im Bilderpool benannt ist. Für den Fall der Fälle (wir haben tatsächlich welche) ist das als Liste mit mehreren Einträgen vorbereitet. Je Autor eine Zeile und bitte das "-" davor! Mittlerweile ist die zugehörige Steuerdatei für die Darstellung in der Lage auch mit leeren Listen umzugehen. Trotzdem bitte bei manuellen Pflegearbeiten darauf achten, hier entweder den Eintrag mit wenigstens einem Autor zu machen oder die Zeile komplett weg zu lassen.
uploadBy:
- "Michael Becker"
Pflicht Logisch macht es keinen Sinn hier eine Liste zu führen, denn der upload erfolgt natürlich nur von einem Nutzer. Nun gibt es da aber eine kleine Kosmetik für eine angenehme Formulierung der Angaben auf der Seite. Und diese Kosmetik funktioniert (derzeit) nur mit gleichen Datentypen. Deswegen: Liste mit nur einem Eintrag. Mittlerweile ist das zugehörige Kontrollfile für die Darstellung in der Lage auch mit leeren Listen umzugehen. Trotzdem bitte bei manuellen Pflegearbeiten darauf achten hier entweder den Eintrag mit exakt einem Eintrag zu machen oder die Zeile komplett weg zu lassen.
license: "unknown" Option Die Angabe der Lizenz zur Veröffentlichung. Gab es in der alten ftc nicht, ist neu hier. Wir (also Admins) müssen uns noch überlegen wie eine "default"-Lizenz sein müsste, mit der die Inhalte auch aus der alten ftc abgedeckt werden.
legacy_id:
- /data/downloads/ebausteine/schaltplne/flipflop.pdf
Option Das ist gedacht für Seiten, die aus der alten ftc übernommen wurden. Ebenso nützlich aber auch, wenn mal was verschoben wurde. Dann bleiben die Links darauf alle wirksam. 'https://www.ftcommunity.de' wird rausgeworfen, der Rest kommt so wie in der url-Zeile vom Browser. Original hieß das mal
https://www.ftcommunity.de/data/downloads/ebausteine/schaltplne/flipflop.pdf
Falls ein imported tag vergeben ist, muss auch eine legacy_id vorhanden sein!
imported:
- "2019"
Option Wird dieser Eintrag gemacht, ist die Datei aus einer vorherigen ftc-Version übernommen worden. "2019" steht dann für das Jahr, in dem der Import gemacht wurde.
Stammt der Download aus der aktuellen Version der ftc, wird dieser Eintrag nicht gemacht!
Die Idee ist, hier bei Bedarf einen Automaten drauf loszulassen der die Einträge vornimmt / ergänzt (z. B.: - "2019" -> - "2019" - "2033"). Vorläufig wird das Feld nicht ausgewertet, hilft uns aber eines Tages herauszufinden was schon vorher da war. legacy_id ist dafür ungeeignet, da dort jede ehemalige ID reinkommt - also auch wenn innerhalb der aktuellen ftc-Seite was verschoben wird. Zukunftssicher ist eine Liste besser geeignet als ein einzelner String.
--- Schließt den Frontmatter-Block ab.

Nach dem Frontmatter kommt nun die Beschreibung der Download-Datei.

Für das gewählte Beispiel (flipflop.md) haben wir diesen Dateiinhalt:

---
layout: "file"
title: "Flip Flop Baustein"
date: 2005-06-06T00:00:00
file: "flipflop.pdf"
konstrukteure: 
- "Michael Becker"
uploadBy:
- "Michael Becker"
license: "unknown"
legacy_id:
- /data/downloads/ebausteine/schaltplne/flipflop.pdf
imported:
- "2019"
---
<!-- https://www.ftcommunity.de/data/downloads/ebausteine/schaltplne/flipflop.pdf -->
Schaltplan "Flip Flop Baustein" (36479)

In der Beschreibung steht der vollständige Link zur alten ftc als html-Kommentar, um notfalls die volle Info über die Herkunft zur Verfügung zu haben. Der Link selbst erscheint nirgends. Der alte Link ist natürlich nur für Seiten aus der alten ftc sinnvoll.

Die Beschreibung darf, mit allem was Markdown bietet, formatiert werden.
Da wäre dann die Frage wie das der geneigte Benutzer ohne entsprechende Kenntnisse im Upload hinbekommt? Zumindest für Admins aber zumindest schon mal wichtig.

Das Beispiel stammt von einem der Silberlinge:
/website-root/knowhow/elektronik/silberlinge/flipflop/

Wie das in der Darstellung genau aussieht, bestimmt die zugehörige “Beschreibung” in der Datei
/website-root/layouts/knowhow/file.html
die die Angaben für das layout: “file” liest und für eine schöne Browseransicht umsetzt. Diese Datei schauen wir uns als nächstes an.

Zurück zum Kapitelanfang

Zurück zur Inhaltsübersicht

Download-Datei Seitenansicht (file.html)

Bevor es an die Beschreibung des Codes geht, sind noch zwei oder drei Sätze zum eigentlichen Framework im Hintergrund angebracht. Dieses Framework sorgt für einheitliche Definitionen, die gleichmässige Optik und stellt grundlegende sowie gemeinsame Dinge bereit. Da wäre zum Beispiel Textfarbe, Hintergrundfarbe, Überschriftsstil, Kopfzeile, Fußzeile, Navigationsfunktionen und vieles mehr. Das Alles wird automatisch übernommen und gestaltet die angezeigte Seite grundsätzlich.

Der besondere Teil hier beschäftigt sich nun mit den Elementen, die speziell für die Ansicht eines Download-Elements mit dem Layout file benötigt werden. Das Framework weiß nämlich eigentlich gar nichts über unsere speziellen Seiteninhalte und auch nicht was ein Download ist. Es hat aber eine Struktur, die ebenso wie die Inhalte aufgebaut ist. Es gibt unter anderem /content für die Seiteninhalte (also in diesem Fall /content/knowhow für die Downloads) sowie /layout wo die Information zur Seitendarstellung selbst abgelegt ist (hier: layout/knowhow). Genau diese gleiche Struktur ermöglicht es dem Framework den Grundzusammenhang zu erkennen und den richtigen Code für die Darstellung anzuwählen.

Ist im Frontmatter des Seiteninhalts layout: “file” angegeben, so ‘weiß’ das Framework, dass die Datei file.html aus dem layout-Bereich die passende Darstellung erzeugt. Der genaue Zugriffspfad ist layout/knowhow/file.html. Weiterhin ist noch (im Framework) festgelegt, dass alle Dateien im Bereich Know-how (/content/knowhow) die das Layout file benutzen, dieses eine file.html für die Darstellung benutzen. Das gilt auch für weitere Unterabteilungen des Bereiches (z. B.: _content/knowhow/elektronik …). Deswegen sehen alle Einträge zu einer Download-Datei einheitlich aus.

Nun soll das hier kein komplettes hugo-Handbuch werden. Auch was HTML ist und wie es in allen Details funktioniert, wird hier nicht beschrieben. Außerdem sind die globalen Teile, also die, die überall vorkommen, schon woanders dokumentiert. Daher geht es hier um die besonderen Teile des Codes der schlussendlich die Seite erzeugt, die am Ende im Browser zu sehen ist.

Fangen wir also mal vorne an.

{{ define "main" }}

   {{ $date_format_string := "2.1.2006" }}

   {{ $wir_email := "vorstand@ftcommunity.de" }}

{{ define "main" }} ist der Startpunkt für hugo. Grundsätzlich gehört alles zwischen einem doppelt geschweiften Klammerpaar zu hugo. Alles Andere wird als HTML-tags oder Seiteninhalt verstanden und erscheint im Browser! Die geschweiften Klammern sind für das Verständnis des Codes nicht unbedingt wichtig und werden bei der weiteren Beschreibung einfach mal weggelassen.

{{/* leitet einen Kommentar ein, */}} beendet ihn. Was in diesem Kommentar steht, interessiert weder hugo noch landet das in in der fertigen HTML-Datei.

Wir überprüfen nun zunächst, 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 eine der beiden Bedingungen 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 ausser 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 bißchen 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 $scratch.Set zugewiesen, die folgenden Textbausteine fügt $scratch.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 bißchen 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">
         <h1>{{.Title}}</h1>

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 <h1> startet die Überschrift, </h1> 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 }}">
      <img
         src = "{{ $.Site.BaseURL }}images/{{ partial "download-icon.html" . }}"
         alt = "{{ partial "download-icon.html" . }}"
         style = "float: left; width: 3em; margin: 1em 1.5em 1em 0;"
      >
   </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.

Anstelle eines Textes zum Anklicken soll hier ein kleines Bild, ein Icon, stehen. Die Zeilen zum Bild haben es nun allerdings “in sich”:

   <img
      src = "{{ $.Site.BaseURL }}images/{{ partial "download-icon.html" . }}"
      alt = "{{ partial "download-icon.html" . }}"
      style = "float: left; width: 3em; margin: 1em 1.5em 1em 0;"
   >

Die Definition startet wie von HTML gewohnt mit <img src = und wird durch den Dateipfad zum gewünschten Bild ergänzt. $.Site.BaseURL steuert die Seitenadresse bei (in unserem Fall https://www.ftcommunity/ oder halt die vom Testserver). images/ergänzt den Pfadnamen wo das Icon zu finden sein wird. partial "download-icon.html" . ist eine Art “Unterprogramm” oder auch “Makro” und gibt den Namen der passenden Icon-Datei an. Diese Art der Auslagerung gestattet es die Funktion “Icon-Datei passend zur Dateiendung eines Files” auch von anderen Stellen aus zu nutzen; und so wird der Code deutlich besser lesbar.

Die Beschreibung von download-icon.html wird demnächst nachgeliefert und hier mit einem Link verknüpft. Siehe auch https://gohugo.io/templates/partials/

Notiz: Im fertigen HTML steht http://localhost:1313/images/disk_pdf.png falls es sich um ein pdf Dokument handelt. Tatsächlich kommen die Icon-Dateien allerdings aus /static/images/disk_pdf.png wenn hugo die Seite zusammenbaut. Neue Icon-Dateien sind also dort einzupflegen (und oben in die Abfrageorgie einzuhängen).

alt = "..." liefert die ‘Pflichtangabe’ falls die angegebene Bilddatei nicht gefunden wird. Durch erneuten “Aufruf” von downlod-icon.html wird hier der Name der Icon- Datei eingesetzt. Er erscheint aber nur wenn es ein Problem mit der Datei selbst gibt.

Per Default erscheint das Icon so 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.

Mit width: 3em; wird die Größe des Icons festgelegt, die Originaldateien umfassen monstermässige 512x512 Pixel.

Zuletzt sorgt margin: für eine Feinplatzierung des Icons durch Angabe der Randbreiten (in dieser Reihenfolge!):

  • Oben: 1em (Abstand zur Textzeile obendrüber - hier Absatzbeginn)
  • Rechts:1.5em (Abstand zum rechts umlaufenden Text)
  • Unten: 1em (Abstand zur Textzeile untendrunter - hier Absatzende)
  • Links: 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.

Diese Angaben zur Größe und Position des Icons sind feinstsäuberlich auf die drei, im Folgenden beschriebenen, Textzeilen abgestimmt!

</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.

Es fehlt weiterhin 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 -}}
            {{ $name -}}
         {{- 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.

Ein paar Beispiele:
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. 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.

Ein paar Beispiele für den Nutzer 'Alter Sack' und Upload-Datum 5. Januar 1900:
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

Der angefangene Satz wird nun wieder in Abhängigkeit von diversen Bedingungen individuell gestaltet.

   {{ if ne $authors $uploader -}}
      {{- if gt $authorsCount 1 -}}
         einen der Autoren
      {{- else if gt $authorsCount 0 -}}
         den Autor
      {{- end -}}
      {{- if and (gt $authorsCount 0) (gt $uploaderCount 0) -}}
         ,
      {{ end -}}
   {{- end -}}

Sofern $authors nicht identisch mit $uploader ist, wird geprüft wieviele Autoren es gibt. Im Falle einer Anzahl ($authorsCount) größer 1 sorgt if gt $authorsCount 1 für den Textbaustein ‘einen der Autoren’. Gibt es genau einen Autor erscheint stattdessen ‘den Autor`. In den übrigen Fällen wird hier nichts eingefügt.

Dann folgt noch die “Kommaregel”: Das ‘,’ wird nur eingefügt, wenn sowohl wenigstens ein Autor und wenigstens ein Nutzer angegeben sind.

Die möglichen Fälle:
Bedingung Satz
$authors != $uploader
UND
$authorsCount > 1
UND
$uploaderCount == 0
einen der Autoren
$authors != $uploader
UND
$authorsCount > 1
UND
$uploaderCount > 0
einen der Autoren,
$authors != $uploader
UND
$authorsCount = 1
UND
$uploaderCount == 0
den Autor
$authors != $uploader
UND
$authorsCount = 1
UND
$uploaderCount > 0
den Autor,
$authors == $uploader
ODER
($authors != $uploader
UND
($authorsCount == 0 ODER $uploaderCount == 0))

Der Textbaustein zum verantwortlichen Nutzer wird nur eingefügt, wenn die Nutzeranzahl exakt auf ‘1’ steht. Der Nutzername ist (wie oben) mit einem Hyperlink hinterlegt.

   {{ if eq $uploaderCount 1 -}}
      <a href="{{ $.Site.BaseURL }}uploadBy/{{delimit $uploader ", "|urlize}}">{{delimit $uploader ", "}}</a>
   {{- end }}

Gibt es einen Textbautein für den/die Autor(en) oder einen Nutzer, dann wird der Satz mit ‘oder’ fortgeführt.

         {{ if or (gt $authorsCount 0) (gt $uploaderCount 0) -}}
            oder
         {{ end -}}

In jedem Falle beendet ein ‘uns’ den Satz. Das ‘uns’ ist auch mit einem Hyperlink hinterlegt. Hier wird allerdings 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 Fußzeile und Navigation. Beides sollte anderweitig beschrieben sein, da es sich um einheitliche Teile jeder Seitendfinition handelt.

Zurück zum Kapitelanfang

Zurück zur Inhaltsübersicht

Wiki-Inhalt

Ein Wiki-Artikel stammt aus der alten ftc-Seite. Oft sind nützliche Informationen enthalten und so haben wir versucht davon so viel zu bergen wie irgend möglich. Da ein Wiki-Artikel nicht viel mehr ist als eine Seite, kommen wir mit einer einzigen Datei aus.

Naja, das stimmt nicht ganz. In manchen Wiki-Artikeln sind Bilder eingebettet. Diese Bilder wurden früher sonstwo im www geparkt. Wir haben keinen Aufwand gescheut diese Bilder hierher zu holen und auf dem Server einzubetten.

Zurück zur Inhaltsübersicht

Wiki-Artikel (.md)

Für den Wiki-Artikel ist also nur eine Datei erforderlich. Selbstverständlich bietet sich auch hier das benutzte Markdown-Format zur Darstellung des Inhaltes an.

Und ebenso wie sonst auch ist hier zuerst ein Frontmatter enthalten, mit dem die nötigen Informationen zur Darstellung an hugo gegeben werden. Es unterscheidet sich ein klein wenig von dem des Downloads und des Bilderpools, da die Angabe über eine beigeordnete Datei entfällt.

Frontmatter Angabe Comment
--- Leitet den Frontmatter-Block ein
layout: "wiki" Pflicht Das Layout für einen Wiki-Artikel heißt "wiki".
title: "RC5 Codes für IR Contol Set 30344" Pflicht Der Titel, der als Überschrift oben erscheint
date: 2016-08-24T00:00:00+0200 Pflicht Das Datum des uploads - wird automatisch erzeugt.
Codierung: yyyy-mm-ddThh:mm:ss+hhmm
Beim manuellem Erstellen neuer Seiten bitte die Zeitzone (`+0100` MEZ bzw. `+0200` MESZ nicht vergessen)! Es wird empfohlen vorhandene Archetypes zu nutzen. Hugo kümmert sich dann um das korrekte Datum mitsamt der Zeitzone. Für legacy Dateien die älter als 2 h sind, ist die Angabe der Zeitzone unerheblich und kann entfallen. Für alles Aktuelle soll sie rein sonst wird die Seite von hugo nicht (zur richtigen Zeit) gebaut.
konstrukteure:
- "uffi"
Option 'Autor' (im Singular!) wär hier von der Wortwahl geschickter, konstrukteure nennen wir es sonst aber auch. Im Falle eines Wiki-Artikels ist der Autor und der Nutzer normalerweise identisch und konstrukteure könnte entfallen. Um die Darstellung ordentlich zu gestalten, achten wir darauf bei einem wiki-Frontmatter den Eintrag konstrukteure exakt so zu machen, wie auch den Eintrag für uploadBy.
uploadBy:
- "uffi"
Pflicht Logisch macht es keinen Sinn hier eine Liste zu führen, denn der upload erfolgt natürlich nur von einem Nutzer. Nun gibt es da aber eine kleine Kosmetik für eine angenehme Formulierung der Angaben auf der Seite. Und diese Kosmetik funktioniert (derzeit) nur mit gleichen Datentypen. Deswegen: Liste mit nur einem Eintrag. Und bitte darauf achten, dass hier beim Wiki-Inhalt konstrukteure mit uploadBy identisch eingestellt ist.
license: "unknown" Option Die Angabe der Lizenz zur Veröffentlichung. Gab es in der alten ftc nicht, ist neu hier. Wir (also Admins) müssen uns noch überlegen wie eine "default"-Lizenz sein müsste, mit der die Inhalte auch aus der alten ftc abgedeckt werden.
legacy_id:
- /wiki1b8f.html
Option Das ist gedacht für Seiten, die aus der alten ftc übernommen wurden. Ebenso nützlich aber auch wenn mal was verschoben wurde. Dann bleiben die Links darauf alle wirksam. 'https://www.ftcommunity.de' wird rausgeworfen, der Rest kommt so wie in der url-Zeile vom Browser bis zum ersten Sonderzeichen - meist ein '?'. Original hieß das mal
https://www.ftcommunity.de/wiki1b8f.html?action=show&topic_id=40
Falls ein imported tag vergeben ist, muss auch eine legacy_id vorhanden sein!
imported:
- "2019"
Option Wird dieser Eintrag gemacht, ist die Datei aus einer vorherigen ftc-Version übernommen worden. "2019" steht dann für das Jahr in dem der Import gemacht wurde.
Stammt der Download aus der aktuellen Version der ftc, wird dieser Eintrag nicht gemacht!
Die Idee ist, hier bei Bedarf einen Automaten drauf loszulassen der die Einträge vornimmt / ergänzt (z. B.: - "2019" -> - "2019" - "2033"). Vorläufig wird das Feld nicht ausgewertet, hilft uns aber eines Tages herauszufinden was schon vorher da war. legacy_id ist dafür ungeeignet, da dort jede ehemalige ID reinkommt - also auch wenn innerhalb der aktuellen ftc-Seite was verschoben wird. Zukunftssicher ist eine Liste besser geeignet als ein einzelner String.
--- Schließt den Frontmatter-Block ab.

Für das gewählte Beispiel (ex_wiki_RC5_Codes_fr_IR_Contol_Set_30344.md) haben wir dieses Frontmatter:

---
layout: "wiki"
title: "RC5 Codes für IR Contol Set 30344 (für den schwarzen Empfänger)"
date: 2016-08-24T00:00:00
konstrukteure: 
- "uffi"
uploadBy:
- "uffi"
license: "unknown"
legacy_id:
- /wiki1b8f.html
imported:
- "2019"
---
<!-- https://www.ftcommunity.de/wiki1b8f.html?action=show&topic_id=40 -->
<!--
   Wiki

   Thema: RC5 Codes für IR Contol Set 30344 (für den schwarzen Empfänger)

   Aktuelle Version

   von: uffi

   am: 24.08.2016, 19:04:16 Uhr

   Historie:
   Version 3 von uffi am 24.08.2016, 18:02:57 Uhr
   Version 2 von uffi am 24.08.2016, 15:23:26 Uhr
   Version 1 von uffi am 24.08.2016, 14:56:29 Uhr

Das hier wäre dann Version 4, die auf .md umgestellt und etwas aufgehübscht
wurde. Uffi wird es mir wohl verzeihen.
-->

Nach dem Frontmatter kommt nun noch ein wenig Antiquarisches.

In der Beschreibung steht zuerst der vollständige Link zur alten ftc als html-Kommentar, um notfalls die volle Info über die Herkunft zur Verfügung zu haben. Der Link selbst erscheint nirgends. Zusätzlich ist noch die Historie angegeben, so wie sie die alte Seite aufgelistet hat. Die wird auch nicht angezeigt (wohl aber dem Kundigen offenbart).

Nach diesem langen HTML-Kommentar kommt dann der eigentliche Inhalt der Seite. Die Beschreibung darf, mit allem was Markdown bietet, formatiert werden. Eventuell steht an der ein oder anderen Stelle ein HTML-tag dazwischen um dem Markdown etwas nachzuhelfen. Das ist derzeit allerdings nur für die Redakteure interessant, die die Inhalte aus der alten ftc übertragen.

Als Beispiel muss herhalten:
/knowhow/elektronik/selbstbau/ex_wiki_rc5_codes_fr_ir_contol_set_30344/

Wie das alles in der Darstellung genau aussieht, bestimmt die zugehörige “Beschreibung” in der Datei
/website-root/layouts/knowhow/wiki.html
die die Angaben für das layout: “wiki” liest und in eine angenehme Browseransicht umsetzt.

Von dieser Datei soll das nächste Kapitel handeln.

Zurück zum Kapitelanfang

Zurück zur Inhaltsübersicht

Wiki-Seitenansicht (wiki.html)

Wer bereits das Kapitel über file.html gelesen hat, wird hier sehr viele Teile wiedererkennen aber einige Unterschiede gibt es dann doch. Und für alle die, die jetzt nicht erst oben stöbern wollen, gibt es die Doku zum Code genauso ausführlich.

Los geht’s.

{{ define "main" }}

   {{ $date_format_string := "2.1.2006" }}

   {{ $wir_email := "vorstand@ftcommunity.de" }}

{{ define "main" }} ist der Startpunkt für hugo. Grundsätzlich gehört alles zwischen einem doppelt geschweiften Klammerpaar zu hugo. Alles Andere wird als HTML-tags oder Seiteninhalt verstanden und erscheint im Browser! Die geschweiften Klammern sind für das Verständnis des Codes nicht unbedingt wichtig und werden bei der weiteren Beschreibung einfach mal weggelassen.

{{/* leitet einen Kommentar ein, */}} beendet ihn. Was in diesem Kommentar steht, interessiert weder hugo noch landet das in in der fertigen HTML-Datei.

Wir überprüfen nun zunächst, 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 }}

if not .Params.title wird immer erfüllt, wenn im Frontmatter kein title: gefunden wird, oder der Eintrag leer ist. In diesem Fall wird hugo angehalten und für den Admin erscheint die Zeile mit der Angabe was wo fehlt. .Path liefet die Auskunft über die betroffene Datei, während das %q den Platz anweist.

Der Rest der Prüfung erfolgt für das Datum und den verantwortlichen Nutzer, baugleich zum Code für den Titel. Im Bedarfsfall gibt es die Fehlermeldung mit exakter Angabe der fehlerhaften Datei und dem genauen Grund dafür.

   {{ $uploadDate := .Params.Date }}
   {{ if not $uploadDate }}
      {{ errorf "Oh oh, das Hochladedatum 'date' fehlt oder ist leer in Seite %q" .Path }}
   {{ end }}

$uploadDate := .Params.Date weist das Datum an eine Variable zu. Die Prüfung erfolgt mit if not $uploadDate. Kein $date: führt zur Beschwerde.

   {{ $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 und wird erwartet.

Theoretisch kann die Liste uploadBy 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. Im wiki-Bereich der ftc war der Autor auch gleichzeitig der angemeldete Nutzer. Es ist also nicht zwingend erforderlich überhaupt einen Eintrag zu dem Autor zu machen. Da der Code aus dem Generator für die Downloadseite hervorgegangen ist, und es eventuell doch zu nötigen Unterscheidungen kommen kann, ist die Möglichkeit gleich von Anfang an vorgesehen. Die Autoren sind wahlfrei, die Liste darf leer sein. Daher entfällt die Abfrage, ob sie definiert ist.

Für den Fall, dass es sich um eine aus der alten ftc importierte Seite handelt, wird abgefragt, ob es ausser zum 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.

   {{/* --- 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.

Die Überprüfung auf Vollständigkeit und zumindest formal korrekte Angaben im Frontmatter ist damit erledigt.

Es gibt in der alten ftc allerdings auch Einträge ohne Nutzernamen. Beim wiki ist das eher unwahrscheinlich, jedoch ist der Code darauf ausgelegt auch mit solch exotischen Ausnahmen umzugehen.

Würden diese Einträge ins Frontmatter übersetzt, könnte hugo wegen des fehlenden Nutzers die Seite nicht bauen (Stichwort: Fehlermeldung an den Admin). Erreicht wird das durch spezielle Einträge für Nutzer und Autor.

   {{/* --- 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 bißchen getrickst, weil hugo für Listen optimiert ist. Normalerweise muss hier ein Vergleich zweier Strings stattfinden (if $uploader == "-LegacyAdmin-"). Für hugo werden allerdings zwei Listen verglichen und slice "-LegacyAdmin-" macht aus dem festgelegten String eine Liste (mit einem Eintrag).

Für die Autoren gibt es das, baugleich zu uploadBy, auch.

   {{ if eq $authors (slice "-?-") }}
      {{ $authorsCount = 0 }}
   {{ end }}

Die aus alten Zeiten fehlende Angabe zum Autor ist per

konstrukteure:
- "-?-"

im Frontmatter definiert.

Auf der fertigen Seite gibt es noch 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 enthält. Dieser Text ist im Zusammenbau nicht ganz trivial und wird daher bereits vorab erzeugt. Das macht den späteren Code für den Seitenaufbau übersichtlicher.

   {{/* --- Vorgeplänkel --- */}}
   {{/* --- Prologue --- */}}

   {{ $email_subject := "Da stimmt was nicht!" }}
   {{ $scratch := newScratch }}
   {{ printf "Hallo ihr Lieben,\n\n" | $scratch.Set "email_body" }}
   {{ printf "ich möchte Euch auf ein Problem mit der ftc-Seite hinweisen:\n" | $scratch.Add "email_body" }}
   {{ printf "%s%s%s/\n" (.Site.BaseURL) (replace .File.Dir "\\" "/") (lower .File) | $scratch.Add "email_body" }}
   {{/* printf "%s\n" .Path | $scratch.Add "email_body" */}}
   {{/* printf "(Bitte diese Referenzen nicht löschen!)\n" | $scratch.Add "email_body" */}}
   {{ printf "\n<Problembeschreibung>" | $scratch.Add "email_body" }}

Zwei Zeilen sind derzeit auskommentiert, können aber zugeschaltet werden um außer der URL der Seite auch noch die Dateiposition mitzugeben. Der Dateipfad ergibt sich jedoch aus der URL und so muss die e-mail nicht mit dieser Information überfrachtet werden.

Mittels $scratch := newScratch wird eine spezielle Variable für den späteren Text der eMail aufgemacht. $scratch.Set weist direkt den ersten Textteil zu, per $scratch.Add werden weitere Teile angehängt.

Das | ist eine Spezialität und eventuell dem Kenner der Unix-Kommandozeile schon geläufig. Das | heißt offiziell ‘pipe’ und leitet wie eine Rohrleitung die Ausgabe einer Anweisung (z. B. von printf) an die folgende Anweisung (z. B. $scratch.Add) weiter.

printf "%s%s%s\n" baut aus dem Seitennamen (‘https://www.ftcommunity.de' oder wo auch immer sie gerade liegt und per .Site.BaseURL zu erfragen) den kompletten Namen der Unterseite zusammen. Dabei sorgt lower .File für eine konsequente Kleinschreibung der URL, so wie sie im Browser auch angezeigt wird. Trotz anderslautender Beschreibung in der hugo Doku ist noch ein replace . File.Fir "\\" "/" fällig um Windows \ gegen den gewohnten / zu tauschen. Im Code hat der \ eine spezielle Bedeutung und so muss für \ "\\" hingetippt werden.

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/selbstbau/ex_wiki_rc5_codes_fr_ir_contol_set_30344

<Problembeschreibung>

Jetzt wird es produktiv. Es folgt Code der den Seitenaufbau im Browser steuert und sichtbare Inhalte erzeugt.

   {{/* --- HTML-Seite zusammenbauen --- */}}
   {{/* --- Assemble the HTML site --- */}}

   <div class="padding highlightable">
      {{ partial "topbar.html" . }}

      <div id="body-inner">
         <h1>{{.Title}}</h1>

         <p>
            {{ .Content }}
         </p>

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 <h1> startet die Überschrift, </h1> beendet sie. Wie sie genau aussieht, ist irgendwo im Framework ‘versteckt’ - global für alle Seiten. Der Inhalt der Seite (also der Text des Wiki-Eintrags) wird direkt aus der Datei geholt. Das erledigt .Content, eingerahmt von den zwei HTML-tags für einen eigenen Absatz (<p>und </p>). Dieser .Content ist der Markdownteil unterhalb des Frontmatters.

Als nächstes erfährt der Besucher wer den Inhalt erstellt und hochgeladen hat.

   <p>
      <small>
         <br />
         {{- 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 -}}
                  {{ $name -}}
               {{- end -}}
            {{- end -}}
            .
         {{- else -}}
            Leider ist kein Autor angegeben.
         {{- end -}}
         <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 -}}
         .
      </small>
   </p>

Die Angabe bekommt einen eigenen Absatz (<p> bis </p>) und einen kleineren Font (<small> bis </small>). Ein Zeilenvorschub <br /> gibt noch etwas zusätzlichen Abstand zum Inhalt.

Sofern kein Autor angegeben ist (eine der möglichen ftc Altlasten), ist $authorsCount = ‘0’ und somit liefert uns else “Leider ist kein Autor angegeben.” Im anderen Falle ist das Script bewusst so ausgelegt, dass es mit beliebig vielen Autoren arbeiten kann, auch wenn das per Definition hier nicht sinnvoll erscheinen mag. Der Code wurde einfach vom ‘file.html’ übernommen; ebenso wie die folgende Beschreibung.

Der übriggebliebene Rest bei Zutreffen der Bedingung $authorsCount > 0 erledigt den Zusammenbau eines lesbaren Satzes.

   Erstellt
   {{- if eq $authors $uploader }}
      und hochgeladen
   {{- end }}
   von

if eq $authors $uploader als hugo-Synonym für if $authors == $uploader lässt den Satz je nach Übereinstimmung von Autor und Nutzer unterschiedlich beginnen. Los geht es jedoch immer mit Erstellt.

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.

Ein paar Beispiele:
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.

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.

Ein paar Beispiele für den Nutzer 'Alter Sack' und Upload-Datum 5. Januar 1900:
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.

Der Bereich mit der Kleinschrift endet hier (</small>) und der Absatz auch (</p>).

      </small>
   </p>

Es folgt nun ein weiterer Absatz in kleiner Schrift.

   <p>
      <small>

Hier erscheint ein Text, der mit einem fett gesetzten ‘Hinweis:’ beginnt (das ist der Bereich zwischen den HTML-tags <b>und </b>).

   <b>Hinweis:</b>
   Wir vertrauen auf die Sachkunde und Sorgfalt unserer Nutzer.
   Trotzdem könnten sich Fehler eingeschlichen haben.
   Eine Haftung für die Richtigkeit der Inhalte können wir nicht
   übernehmen.
   Falls Du einen Fehler findest, kontaktiere bitte

Der angefangene Satz wird in Abhängigkeit von diversen Bedingungen individuell gestaltet.

   {{ if ne $authors $uploader -}}
      {{- if gt $authorsCount 1 -}}
         einen der Autoren
      {{- else if gt $authorsCount 0 -}}
         den Autor
      {{- end -}}
      {{- if and (gt $authorsCount 0) (gt $uploaderCount 0) -}}
         ,
      {{ end -}}
   {{- end -}}

Sofern $authors nicht identisch mit $uploader ist, wird geprüft wieviele Autoren es gibt. Im Falle einer Anzahl ($authorsCount) größer 1 sorgt if gt $authorsCount 1 für den Textbaustein ‘einen der Autoren’. Gibt es genau einen Autor erscheint stattdessen ‘den Autor`. In den übrigen Fällen wird hier nichts eingefügt.

Dann folgt noch die “Kommaregel”: Das ‘,’ wird nur eingefügt, wenn sowohl wenigstens ein Autor und wenigstens ein Nutzer angegeben sind.

Die möglichen Fälle:
Bedingung Satz
$authors != $uploader
UND
$authorsCount > 1
UND
$uploaderCount == 0
einen der Autoren
$authors != $uploader
UND
$authorsCount > 1
UND
$uploaderCount > 0
einen der Autoren,
$authors != $uploader
UND
$authorsCount = 1
UND
$uploaderCount == 0
den Autor
$authors != $uploader
UND
$authorsCount = 1
UND
$uploaderCount > 0
den Autor,
$authors == $uploader
ODER
($authors != $uploader
UND
($authorsCount == 0 ODER $uploaderCount == 0))

Der Textbaustein zum verantwortlichen Nutzer wird nur eingefügt, wenn die Nutzeranzahl exakt auf ‘1’ steht. Der Nutzername ist (wie oben) mit einem Hyperlink hinterlegt.

   {{ if eq $uploaderCount 1 -}}
      <a href="{{ $.Site.BaseURL }}uploadBy/{{delimit $uploader ", "|urlize}}">{{delimit $uploader ", "}}</a>
   {{- end }}

Gibt es einen Textbautein für den/die Autor(en) oder einen Nutzer, dann wird der Satz mit ‘oder’ fortgeführt.

         {{ if or (gt $authorsCount 0) (gt $uploaderCount 0) -}}
            oder
         {{ end -}}

In jedem Falle beendet ein ‘uns’ den Satz. Das ‘uns’ ist auch mit einem Hyperlink hinterlegt. Hier wird allerdings der Versand einer e-mail an das Betreuungsteam vorbereitet.

         <a href="mailto:{{$wir_email}}?subject={{$email_subject}}&body={{$scratch.Get "email_body"}}">uns</a>.

$wir_email gibt den Adressaten an, $email_subject liefert den Betreff und $scratch.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>

Speziell für die Wiki-Inhalte sollten Nutzername und Autorenname jeweils den gleichen Eintrag haben. Daher wird üblicherweise immer nur der entsprechende Satzbau zu finden sein. Es ist jedoch Absicht (und nicht nur Faulheit des Programmierers) die Flexibilität vom Download-Inhalt hier ebenfalls vorzuhalten.

Der spezielle Inhalt einer Wiki-Seite ist damit beendet, jetzt folgt noch Fußzeile und Navigation. Beides sollte anderweitig beschrieben sein, da es sich um einheitliche Teile jeder Seitendefinition handelt.

Zurück zum Kapitelanfang

Zurück zur Inhaltsübersicht

Inhalte auflisten (list.html)

Außer den vorgenannten Inhalten selbst, gibt es auch noch die jeweiligen Übersichtsseiten, mit dem Prädikat section. So eine Übersichtsseite wird in ihrem Ordner durch die Datei _index.md beschrieben. In der section “Know-how” kümmert sich das Script layouts/knowhow/list.html um die Darstellung dieser Inhalte.

Das Script beginnt mit dem üblichen “Überbau” für eine Seite und einer dazwischen eingefädelten Konstantendefinition ($maxChars).

{{ define "main" }}

  {{ $maxChars := 320 }}

  <div class="padding highlightable">
    {{ partial "topbar.html" . }}

    <div id="body-inner">

Direkt danach kommt auch schon der Titel und der Inhalt aus der jeweiligen _index.md-Datei.

      <h1>{{.Title}}</h1>

      {{ .Content }}

Nun arbeitet sich das Script durch alle weiteren Unterseiten (sections) um sie aufzulisten und mit einer kurzen Inhaltsangabe zu versehen.

      {{ range .Sections }}
         <hr>
         <h4>
            <a href = "{{ .RelPermalink }}"> <i class="far fa-folder-open"></i> </a>
            -
            <a href = "{{ .RelPermalink }}" style = "color: Black;"> {{ .Title }} </a>
         </h4>
         <p>{{ .Summary | markdownify | safeHTML | truncate $maxChars }}</p>
         <a href = "{{ .RelPermalink }}">Abschnitt öffnen</a>
      {{ end }}

Für jede section gibt es zuerst eine horizontale Trennlinie (<hr>), dann folgt der klickbare Eintrag als Überschrift (<h4>...</h4>) mit Icon aus Fontawesome davor. Dabei ist es Absicht nur das Icon in ‘Linkfarbe’ darzustellen, den Seitentitel jedoch stattdessen schwarz zu setzen. Der beschreibende Text der Untersection wird mittels .Summary geholt, durch den Markdown-Prozessor geschleust (markdownify), das entstandene HTML als ‘sicher, als solches weitergeben’ (safeHTML) erklärt und schließlich auf die eingangs definierte Länge $maxChars zurechtgestutzt. Dabei passt hugo auf, dass keine Worte mittendrin abgeschnitten werden. Dann gibt es nochmal einen Link zur section. Der ist für die Leute mit dem ganz kleinen Bildschirm gedacht - so muss man nach dem Lesen der Einleitung nicht wieder hochscrollen.

         <a href = "{{ .RelPermalink }}">Abschnitt öffnen</a>

Sind die sections alle aufgelistet, startet eine zweite Schleife, um die Liste durch alle Unterseiten des Typs page zu ergänzen. Dieses Konstrukt ist technisch identisch zur vorgenannten Schleife für die sections. Die Beschreibung wird daher kurzgefasst.

      {{ range .Pages }}
         {{ if eq .Layout "file" }}
            <hr>
            <h4>
               <a href = "{{ .RelPermalink }}"><i class="fas fa-download"></i></a>
               -
               <a href = "{{ .RelPermalink }}" style = "color: Black;"> {{ .Title }} </a>
            </h4>
            <p>{{ .Summary | markdownify | safeHTML | truncate $maxChars }}</p>
            <a href = "{{ .RelPermalink }}">Zum Download</a>
         {{ else if eq .Layout "wiki" }}
            <hr>
            <h4>
               <a href = "{{ .RelPermalink }}"><i class="fas fa-book-reader"></i></a>
               -
               <a href = "{{ .RelPermalink }}" style = "color: Black;"> {{ .Title }} </a>
            </h4>
            <p>{{ .Summary | markdownify | safeHTML | truncate $maxChars }}</p>
            <a href = "{{ .RelPermalink }}">Weiterlesen</a>
         {{ else }}
            {{ errorf "Oh oh, hier fehlt die Ansichtsdefinition für das Layout '%s' in Seite %q" .Layout .Path }}
         {{ end }}
      {{ end }}

Die Unterschiede:

  • range läuft hier nicht auf .Sections sondern auf .Pages.
  • Die Einträge werden nach .Layout Typ aus dem Frontmatter unterschieden. Ersatzweise ginge auch .Params.layout.
  • Je nachdem ob layout: "file" oder layout: "wiki" vorhanden ist, wird das Icon für den Eintrag ausgewählt.
  • Je nach Layout wird unterhalb der Summary ein passender Linktext verwendet.
  • Ist das Layout unbekannt, wird sich hugo weigern die Seite zu bauen. Das ist die Zeile mit dem errorf.

Das Script findet dann seinen Abschluss durch Fußzeile und die nötigen abschliessenden Tags / Befehle.

      <hr>
      <br />

      <footer class=" footline" >
        {{with .Params.LastModifierDisplayName}}
          <i class='fas fa-user'></i>
          <a href="mailto:{{ $.Params.LastModifierEmail }}">{{ . }}</a> 
          {{with $.Date}}
            <i class='fas fa-calendar'></i> {{ .Format "02/01/2006" }}
          {{end}}
   {{end}}
      </footer>

    </div> 
    {{ partial "custom-comments.html" . }}
  </div>
{{ end }}

Zurück zum Kapitelanfang

Zurück zur Inhaltsübersicht


Stand: 30. Juni 2019