Eigenes HUGO-Theme für Blogdown erstellen

Ich habe für mein Blog ein eigenes Theme erstellt.
Blogdown
Autor:in

Joe Slam

Veröffentlichungsdatum

19. Februar 2022

Ich habe für mein Blog ein eigenes HUGO-Theme erstellt. Dabei lernt man eine Menge über CSS, HUGO und Blogdown.

Ich bin einfach der sehr guten Anleitung auf https://pakstech.com/blog/introduction-to-hugo-basics/ gefolgt und habe alles 1 zu 1 umgesetzt. Anschließend habe ich noch einmal komplett von vorne begonnen, und die Seite so gestaltet, wie sie nun aussieht. Folgende Punkte waren für mich zunächst schwer bzw. unverständlich.

pre, code, .highlight und .sourceCode können die divs sprengen

Wenn man langzeiligen Quellcode in die Seite einbindet, können die Container die Größe des <div> sprengen. Das wird dann vor allem am Handy schnell unleserlich. Ich musste explizit in meiner .css-Datei angeben, dass die Codeblöcke nur maximal 95% der Bildschirmbreite einnehmen dürfen:

pre, code, .highlight, .sourceCode {
  max-width: 95vw;
}

HUGO vs. Blogdown

Mein Theme habe ich mit dem HUGO-Testserver gebaut und getestet. Darum waren alle Dateien reine .md-Files. Blogdown verwendet aber .Rmd und/oder .Rmarkdown als Suffix, und die Formate unterscheiden sich:

  • .md kann keinen r-Code ausführen und ist damit für Blogdown relativ uninteressant.
  • .Rmarkdown verwendet Blackfriday und HUGO zum rendern der Seite, es ist quasi ein r-verstehendes .md-File.
  • .Rmd verwendet Pandoc und R zum rendern der Seite.

Auf weitere Unterschiede gehe ich im Verlauf immer wieder ein.

Mathe mit KaTeX

Ich möchte meine -Matheformeln im Blog verwenden. Hierfür kann entweder MathJax oder KaTeX verwendet werden. Letzteres läuft schneller als MathJax, und darum binde ich es (wie von Mert Bakir hier beschrieben) wie folgt ein:

In meinem Themeordner erstelle ich die Datei /MEINTHEME/layouts/partials/katex.html und gebe ihr folgenden Inhalt:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.15.2/dist/katex.min.css" integrity="sha384-MlJdn/WNKDGXveldHDdyRP1R4CTHr3FeuDNfhsLPYrq2t0UBkUdK2jyTnXPEK1NQ" crossorigin="anonymous">

<!-- The loading of KaTeX is deferred to speed up page rendering -->
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.15.2/dist/katex.min.js" integrity="sha384-VQ8d8WVFw0yHhCk5E8I86oOhv48xLpnDZx5T9GogA/Y84DcCKWXDmSDfn13bzFZY" crossorigin="anonymous"></script>

<!-- To automatically render math in text elements, include the auto-render extension: -->
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.15.2/dist/contrib/auto-render.min.js" integrity="sha384-+XBljXPPiv+OzfbB3cVmLHf4hdUFHlWNZN5spNQ7rmHTXpd7WvJum6fIACpNNfIR" crossorigin="anonymous" onload="renderMathInElement(document.body);"></script>

<script>
    document.addEventListener("DOMContentLoaded", function() {
        renderMathInElement(document.body, {
            delimiters: [
                {left: "$$", right: "$$", display: true},
                {left: "$", right: "$", display: false}
            ]
        });
    });
</script>

In der Datei /MEINTHEME/layouts/partials/head.html ergänze ich:

    {{ if .Params.math }}{{ partial "katex.html" . }}{{ end }}

Wenn ich später in Blogdown bei einem Post im Meta-Kopf folgenden Paramter setze:

 math: true

…dann wird $$ geladen und kann verwendet werden.

Gleichungen stehen zwischen $$-Blöcken, z.B.

$$
x - 1 \cdot \frac{x^2}{\sqrt{y_1}}
$$

ergibt

\[ x - 1 \cdot \frac{x^2}{\sqrt{y_1}} \]

Es gibt Unterschiede in der Notation, je nachdem, ob .Rmd, .Rmarkdown oder .md-Dateien verwendet werden. Ich hab in diesem Post beschrieben, was dabei zu beachten ist.

Syntax-Highlight

.md und .Rmarkdown machen das out-of-the-box

Für .md und .Rmarkdown-Files ist Syntax-Highlight quasi schon eingebaut, da sie mittels Blackfriday und HUGO gerendert werden. In der config.toml wird es wie folgt aktiviert:

 [markup.highlight]
    codeFences = true
    hl_Lines = ""
    lineNoStart = 1
    lineNos = true
    lineNumbersInTable = true
    noClasses = true
    style = "dracula"
    tabWidth = 4

Verwendet wird dabei die Chroma-Stylefamilie, hier im Beispiel ist “dracula” ausgewählt. Alle verfügbaren Styles findet man hier: https://xyproto.github.io/splash/docs/all.html

Codeschnipsel können mit dem HUGO-shortcode “highlight” eingerahmt werden…

{{< highlight latex "linenos=table,hl_lines=8 15-17,linenostart=199" >}}
// ... code
{{< / highlight >}}

oder als “normale” Codeblöcke gesetzt werden…

```latex {linenos=table,hl_lines=[2,"5-7"],linenostart=199}
// ... code
```

Das sieht dann z.B. so aus:

pre, code, .highlight, .sourceCode {
  max-width: 95vw;
}
.mysection {
  display: flex;
  justify-content: center;
  padding-top: 20px;
  padding-bottom: 20px;
  width: 99vw;
}

.Rmd benötigt highlight.js

Für .Rmd-Files, die über Pandoc gerendert werden, muss highlight.js eingebunden werden, damit Syntax-Highlight funktioniert.

In meinem Themeordner erstelle ich die Datei /MEINTHEME/layouts/partials/highlightjs.html und gebe ihr folgenden Inhalt:

    <link rel="stylesheet" href="//cdn.bootcss.com/highlight.js/10.2.0/styles/github.min.css" rel="stylesheet" id="theme-stylesheet">
    <link href="//cdn.bootcss.com/highlight.js/10.2.0/styles/default.min.css" rel="stylesheet">
    <script src="//cdn.bootcss.com/highlight.js/10.2.0/highlight.min.js"></script>
    <script src="//cdn.bootcss.com/highlight.js/10.2.0/languages/r.min.js"></script>
    <script src="//cdn.bootcss.com/highlight.js/10.2.0/languages/latex.min.js"></script>
    <script src="//cdn.bootcss.com/highlight.js/10.2.0/languages/yaml.min.js"></script>
    <script src="//cdn.bootcss.com/highlight.js/10.2.0/languages/bash.min.js"></script>
    <script>hljs.configure({languages: []});
    hljs.initHighlightingOnLoad();</script>

Ich verwende in meinem Theme die Version 10.2.0, weil mir hir die Farben am besten gefallen. Ihr müsst mal mit den Versionsnummern herumspielen und euch die Unterschiede anschauen.

Highlight.js “überschreibt” die HUGO-eigenen Highlights, so dass wir es nur in .Rmd-Files aktivieren wollen.

In der Datei /MEINTHEME/layouts/partials/head.html ergänze ich daher:

    {{ if .Params.highlightjs }}{{ partial "highlightjs.html" . }}{{ end }}

So kann highlight.js im Kopf der Posts eingeschaltet werden, indem highlightjs auf true gesetzt wird:

  highlightjs: true

Außerdem muss im Kopf noch angegeben werden:

  output:
    blogdown::html_page:
      highlight: espresso  

keine Plots mit .Rmarkdown

Standardmäßig werden keine Plots aus r-Code in .Rmarkdown-Files in den Post eingebunden. Auch dies muss erst in der config.toml aktiviert werden:

# enable plots being posted 
[markup.goldmark.renderer]
  unsafe= true