Ich bin schon seit ein paar Tagen dabei, das neue Wiki einzurichten und die Inhalte umzuziehen und anzupassen. Das neue Wiki ist zwar bereits online, aber bis zur Fertigstellung noch mit einem Passwort geschützt.

Hier erkläre ich, was ich alles gemacht habe, um mein neues Wiki so einzurichten, wie man es in ein paar Tagen online sehen wird.

Neue Website mit Hugo erstellen

hugo new site wiki.natenom.com

cd wiki.natenom.com
git init .

cd themes
git submodule add https://github.com/google/docsy.git

cd docsy
git submodule sync && git submodule update --init --recursive

Installation von PostCSS

npm install -D autoprefixer
npm install -D postcss-cli
npm install -D postcss

Dokumentation

Eigenes CSS

Eigenes CSS kommt in die Datei assets/scss/_styles_project.scss.

Dokumentation.

Shortcodes

Ich verwende einige meiner Shortcods aus meinem Blog.

Das Theme Docsy liefert viele Shortcodes bereits mit, siehe hier.

Alte Bilddateien

Alte Bilddateien habe ich erst einmal nach static/_media/ kopiert damit sie noch eine Zeit lang unter der selben URL zu erreichen sind wie bisher auch, wenn auch auf einer neuen Domain, zum Beispiel https://wiki.natenom.de/_media/minimalismus.jpg.

Keine externen Ressourcen

Per Voreinstellung bindet das Theme leider ein paar externe Ressourcen ein. Diese werden in den Dateien theme/docsy/layouts/partials/scripts.html und theme/docsy/layouts/partials/head.html referenziert.

JavaScript und CSS

Doch man kann die referenzierten Dateien auch herunterladen und selbst in Hugo vorhalten. 1

Dazu kopiert man die eben genannte Datei nach hugo/layouts/partials/. Somit werden unsere eigenen Version verwendet statt der im Theme mitgelieferten.

Dann erstellt man in hugo/static ein Verzeichnis externals und lädt dorthin alle eingebundenen Dateien herunter und ändert anschließend die URLs der eingebundenen Dateien. Aus https://... wird /externals/....

Ursprüngliche Datei scripts.html:

[…]
<script
  defer
  src="https://cdn.jsdelivr.net/npm/katex@0.15.1/dist/katex.min.js"
  integrity="sha512-5ufNcHqOYgilGEHPfuRIQ5B/vDS1M8+UC+DESZ5CwVgGTg+b2Ol/15rYL/GiCWJ/Sx8oVo0FPFok1dPk8U9INQ=="
  crossorigin="anonymous"
></script>
[…]

Veränderte Datei scripts.html:

[…]
<script defer src="/externals/katex.min.js" crossorigin="anonymous"></script>
[…]

Das sind die Dateien, die von extern eingebunden werden:

  • auto-render.min.js
  • bootstrap.min.js
  • katex.min.css
  • markmap-autoloader
  • mermaid.min.js
  • mhchem.min.js
  • popper.min.js

Schriften

Dann werden auch noch Fonts eingebunden in:

  • docsy/assets/scss/rtl/_main.scss
    • Hierfür erstellt man die neue Datei assets/scss/rtl/_main.scss ohne Inhalt. Damit wird die Originaldatei vom Theme überlagert. Auch das habe ich bei OpenBikeSensor gefunden, siehe hier.
  • docsy/assets/scss/_variables.scss.
    • Hierfür erstellt man die neue Datei assets/scss/_variables_project.scss mit folgendem Inhalt:
      $td-enable-google-fonts: false;

Schriften selbst hosten

Da mir die im Original-Theme verwendete Schriftart gefällt, binde ich sie lokal ein. Wie das geht, habe ich auf der Projektseite von OpenBikeSensor gefunden, siehe hier.

Hier eine Anleitung, wie man an die Schriftdateien kommt.

Dazu kommt zusätzlich in die Datei assets/scss/_variables_project.scss:

$font-family-sans-serif:
  "Open Sans",
  -apple-system,
  BlinkMacSystemFont,
  "Segoe UI",
  Roboto,
  "Helvetica Neue",
  Arial,
  sans-serif,
  "Apple Color Emoji",
  "Segoe UI Emoji",
  "Segoe UI Symbol";

/* open-sans-300 - latin */
@font-face {
  font-family: "Open Sans";
  font-style: normal;
  font-weight: 300;
  src:
    local(""),
    url("/fonts/open-sans-v27-latin-300.woff2") format("woff2"),
    /* Chrome 26+, Opera 23+, Firefox 39+ */
      url("/fonts/open-sans-v27-latin-300.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
}

/* open-sans-500 - latin */
@font-face {
  font-family: "Open Sans";
  font-style: normal;
  font-weight: 500;
  src:
    local(""),
    url("/fonts/open-sans-v27-latin-500.woff2") format("woff2"),
    /* Chrome 26+, Opera 23+, Firefox 39+ */
      url("/fonts/open-sans-v27-latin-500.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
}

/* open-sans-regular - latin */
@font-face {
  font-family: "Open Sans";
  font-style: normal;
  font-weight: 400;
  src:
    local(""),
    url("/fonts/open-sans-v27-latin-regular.woff2") format("woff2"),
    /* Chrome 26+, Opera 23+, Firefox 39+ */
      url("/fonts/open-sans-v27-latin-regular.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
}

/* open-sans-700 - latin */
@font-face {
  font-family: "Open Sans";
  font-style: normal;
  font-weight: 700;
  src:
    local(""),
    url("/fonts/open-sans-v27-latin-700.woff2") format("woff2"),
    /* Chrome 26+, Opera 23+, Firefox 39+ */
      url("/fonts/open-sans-v27-latin-700.woff") format("woff"); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
}

Die acht heruntergeladenen woff- und woff2-Dateien kommen dann nach static/fonts/.

  • open-sans-v27-latin-300.woff
  • open-sans-v27-latin-300.woff2
  • open-sans-v27-latin-500.woff
  • open-sans-v27-latin-500.woff2
  • open-sans-v27-latin-700.woff
  • open-sans-v27-latin-700.woff2
  • open-sans-v27-latin-regular.woff
  • open-sans-v27-latin-regular.woff2

Die Dokumentation zu Fonts in Docsy gibt es hier.

Lokale Suche aktivieren

In die config.toml eintragen:

[params]
offlineSearch = true
algolia_docsearch = false

Dokumentation

Kaskadierung – “/docs/abc” vs “/abc”

Hinweis
Ich habe mich später dazu entschieden, keine Kaskadierung zu verwenden, um in Zukunft die Möglichkeit zu haben, einfach auf ein anderes Theme wechseln zu können, ohne viele Anpassungen machen zu müssen. Auch könnte ich in Zukunft, passendes Theme vorausgesetzt, Blog und Wiki zusammenführen. Dazu will ich aber ein Theme nutzen, das von Haus aus sowohl für /blogs/ als auch für /docs/ gut aussieht.

Per Voreinstellung des Themes sollen alle Dokumentationsinhalt im Unterverzeichnis content/<sprache>/docs/ eingefügt werden und /docs/ ist dann überall in der URL zu sehen. Man landet auch immer auf einer Startseite, die per Voreinstellung leer ist und muss dann für mein Wiki erst einmal rechts oben auf den Eintrag Wiki klicken. Das liegt daran, dass für das Theme docs nur ein Inhaltstyp von mehreren ist. Daneben gibt es z. B. noch blog.

Da ich schon hier einen Blog betreibe und neben der Dokumentation keine weiteren Inhaltstypen im Wiki benötige, habe ich das Theme so umgestellt, dass content/<sprache>/docs/ nicht benötigt wird. Stattdessen liegen alle Inhalte direkt im Hauptverzeichnis content/<sprache>/.

Zuerst werden alle Dateien und Verzeichnisse aus content/<sprache>/docs/ nach content/<sprache>/ verschoben.

Dann erstellt man die Datei content/<sprache>/_index.md mit folgendem Inhalt: 2

---
title: "Wiki"
linkTitle: "Wiki"
type: "docs"
weight: 20
menu:
  main:
    weight: 20
cascade:
- _target:
    path: "/blog/**"
  type: "blog"
  # set to false to include a blog section in the section nav along with docs
  toc_root: true
- _target:
    path: "/**"
    kind: "page"
  type: "docs"
- _target:
    path: "/**"
    kind: "section"
  type: "docs"
- _target:
    path: "/**"
    kind: "section"
  type: "home"
---

Natenoms neues Wiki. Mein altes Wiki unter https://wiki.natenom.de wird weiterhin bestehen bleiben. Jedoch werde ich neue Inhalte nur noch hier erstellen und die alten Inhalte langsam nach hierher umziehen. Die ganz alten Sachen werden dauerhaft im alten Wiki verbleiben.

Dokumentation zu cascade auf docsy.dev und auf gohugo.io.

Verzeichnisstruktur

Die von DokuWiki exporierte Verzeichnisstruktur muss noch angepasst werden, damit sie in Hugo richtig angezeigt wird. Hier am Beispiel des Namensraums “Orte”.

Zuerst die Struktur, wie sie exportiert wurde (und wie sie auch in DokuWiki war):

.
├── orte
│   ├── enzkreis.md
│   ├── landkreis_calw.md
│   ├── neuhausen_enzkreis.md
│   └── pforzheim.md
├── orte.md

Und die angepasste Struktur:

.
├── orte
│   ├── enzkreis.md
│   ├── _index.md
│   ├── landkreis_calw.md
│   ├── neuhausen_enzkreis.md
│   └── pforzheim.md

Die Änderungen haben meinem Verständnis nach vor allem mit Page Bundles zu tun.

Während z. B. in DokuWiki der Hauptbereich orte aus dem Verzeichnis orte und einer auf gleicher Ebene liegenden Datei orte.txt besteht, so benötigt Hugo eine Struktur in der Form, dass es ein Verzeichnis orte gibt, in dem die Datei _index.md liegt, die der Datei orte.txt (bzw. orte.md im exportierten Verzeichnis) von DokuWiki entspricht.

Bilder zusammen mit Markdown-Dateien

In DokuWiki liegen Dateien in dokuwiki/media/ und Seiten in dokuwiki/pages/. In Hugo liegen Bilder, Videos, usw. in den selben Verzeichnissen wie auch die Markdown-Dateien. Würden sie in einer eigenen Verzeichnisstruktur liegen, wäre es z. B. nicht möglich, automatisiert kleinere Varianten dieser Bilder zu erstellen. Das hat was mit Page Bundles zu tun.

Ich glaube ich habe das Konzept von Page Bundles einigermaßen verstanden, so, dass ich es nutzen kann. Erklären kann ich es aber nicht. Bitte selbst die Dokumentation lesen.

Entwurfsmodus für ganze Namensräume

Fügt man in das Front Matter einer _index.md-Datei das Tag draft mit dem Wert true ein, dann befindet sich der gesamte Namensraum im Entwurfsmodus. D. h. er wird nur gerendert, wenn man hugo mit dem Parameter -D aufruft.

D. h. ich stelle die Namensräume, die noch nicht fertig sind, auf Entwurf um.

Man muss allerdings bedenken, dass es eine Fehlermeldung gibt, wenn man den Shortcode ref (Dokumentation) verwendet, um auf URL innerhalb der Website zu verlinken, die dann in der gerenderten Website gar nicht existieren wird.

Eine Liste aller im Entwurfsmodus befindlichen Seiten erhält man z. B. mit grep, wenn man nach draft: … sucht oder noch einfacher mit:

hugo list drafts

Das Kommando muss dabei im Basisverzeichnis der Hugo-Website ausgeführt werden.

Teilweiser Umzug

Sobald ein Namensraum der Hauptebene fertig ist, stelle ich draft: false ein, lasse die Website rendern und lade das Ergebnis hoch.

In der Nginx-Konfiguration richte ich dann Weiterleitungen für diesen Namensraum ein. Entweder einen Eintrag für den gesamten Namensraum, wenn sich an dessen URL-Struktur nichts verändert hat oder einzeln je Seite, wenn ich die Struktur verändert habe.

About-Seite

Wenn es eine Seite mit dem Namen about gibt, so wird diese automatisch unten im Footer aufgelistet.

Dies kann man in der config.toml abschalten mit:

    [params.ui]
    footer_about_disable = true

Impressum/Datenschutz

Ganz wichtig im Land, in dem Kennzeichen schützenswerter sind als Menschen: Man benötigt Links zu Impressum und zu Datenschutz.

Dazu habe ich das Verzeichnis content/de/ueber/ erstellt. Hier landen alle Inhalte, in denen es über mein neues Wiki geht.

Optional kann man die Seite im Seitenverzeichnis verstecken, in dem man ins Front Matter toc_hide: true einträgt. 3

Aus der Suche ausschließen

Mit dem Eintrag exclude_search: true im Front Matter kann man die Inhalte einzelner Seite von der Indexierung der Suchfunktion ausschließen.

Dokumentation

Liste aller Tags aus der Sidebar entfernen

Mir gefällt es gar nicht, dass im verwendeten Theme rechts immer alle vorhandenen Tags des gesamten Wikis angezeigt werden. Das ist meiner Ansicht nach unnötig und sehr störend, da es in meinem Wiki (noch) hunderte Tags gibt.

Um das zu entfernen habe ich die Datei hugo/themes/docsy/layouts/partials/taxonomy_terms_clouds.html aus dem Theme-Verzeichnis nach hugo/layouts/partials/ kopiert und den Inhalt gelöscht.

404 Fehlerseite

Es wird automatisch eine 404-Fehlerseite erzeugt. Diese kann man z. B. in der Nginx-Konfiguration aktivieren mit:

error_page 404 /404.html;

Ich kann im neuen Wiki die Interwiki-Links nutzen, die ich gerade erst implementiert habe. Siehe hier.

Die Datei hugo/themes/docsy/layouts/partials/footer.html nach hugo/layouts/partials/footer.html kopieren und in Zeile unten einfügen:

<p class="mt-2">
  <small>
    <a href="/impressum/">Impressum</a>
    <a href="/docs/ueber/datenschutz/">Datenschutz</a></small
  >
</p>

Das Theme bietet die Möglichkeit, dass man links unten (und rechts unten) verschiedene Icons einfügt, die auf verschiedene andere Webseiten wie z. B. auf ein Maston-Profil verlinken.

In die config.toml eintragen:

[params.links]
[[params.links.user]]
        name = "Über Natenom"
        url = "/about/"
        icon = "fas fa-user-circle"
        desc = "Über Natenom"
[[params.links.user]]
        name = "Mumble"
        url = "https://wikiarchiv.natenom.de/ueber/natemologie-zentrum"
        icon = "fa fa-mobile"
        desc = "Mumble"
[[params.links.user]]
        name = "E-Mail"
        url = "mailto:user@tld.org"
        icon = "fa fa-envelope"
        desc = "E-Mail"
[[params.links.user]]
        name = "Github"
        url = "https://github.com/natenom"
        icon = "fab fa-github"
        desc = "Github"
[[params.links.user]]
        name = "Twitter"
        url = "https://twitter.com/natenom"
        icon = "fab fa-twitter"
        desc = "Github"
[[params.links.user]]
        name = "Mastodon"
        url = "https://social.anoxinon.de/users/natenom"
        icon = "fab fa-mastodon"
        desc = "Mastodon"

So sieht es aus:

Damit die Icons rechts landen, nutzt man statt params.links.user die Zeichenkette params.links.developer.

Videos (extern) hosten

Im alten Wiki sind einige Videos enthalten. Diese werde ich in Zukunft auf f.natenom.de hosten, damit das Git-Repo des Wikis nicht unnötig groß wird. Außerdem will ich nicht, dass die Videos für immer im Repo verbleiben.

Dauer fürs Rendern

Das neue Wiki braucht aktuell circa 10 Sekunden, um komplett gerendert zu werden:

                |  DE
-------------------+-------
Pages            | 1289
Paginator pages  |    0
Non-page files   |  143
Static files     |  105
Processed images |  102
Aliases          |    0
Sitemaps         |    1
Cleaned          |    0

Built in 9771 ms

Ergebnis

Und so sieht derzeit mein neues Wiki aus:

Mein neues Wiki

Todo

Was mir noch fehlt:

  • Nummerierung der Überschriften (Inhalt und Inhaltsverzeichnis).
  • Favicons einrichten (Dokumentation)

  1. Es gibt dazu seit 2021 einen offenen Issue, siehe hier↩︎

  2. Das Beispiel habe ich von hier↩︎

  3. Dokumentation ↩︎