Theme fest ins Repo uebernehmen statt als Submodule

Ein normaler git clone holt Submodules nicht mit - geprueft: nach dem
Klonen des Repos war themes/gokarna leer. Portainer klont ebenso, der
Build im Container waere also an dem fehlenden Theme gescheitert.

Gokarna liegt jetzt direkt im Repo, festgeschrieben auf Commit 8306042,
den Stand, mit dem die Seite bisher gebaut wurde. .gitmodules entfaellt.

Nachteil: Theme-Updates muessen kuenftig von Hand eingespielt werden.
Dafuer baut das Repo aus jedem beliebigen Klon heraus, ohne
Sonderbehandlung.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-03 01:25:39 +02:00
parent fbab2dc2cd
commit 1f354130bb
109 changed files with 4966 additions and 4 deletions

View File

@@ -0,0 +1,19 @@
{{ define "main"}}
<div class="text-404">
<h1 class="error-emoji"></h1>
<h2>
404 ... {{ i18n "error404" . }} <a href="{{ .Site.BaseURL }}">{{ i18n "home" }}</a>
</h2>
</div>
<script>
const errorEmojiContainer = document.getElementsByClassName('error-emoji')[0];
const emojiArray = [
'\\(o_o)/', '(o^^)o', '(˚Δ˚)b', '(^-^*)', '(≥o≤)', '(^_^)b', '(·_·)',
'(=\'X\'=)', '(>_<)', '(;-;)', '\\(^Д^)/',
];
const errorEmoji = emojiArray[Math.floor(Math.random() * emojiArray.length)];
errorEmojiContainer.appendChild(document.createTextNode(errorEmoji));
</script>
{{ end }}

View File

@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html lang="en">
{{- $avatarImgSrc := .Site.Params.AvatarURL -}}
{{- if and (isset .Site.Params "avatarURL") (not (hasPrefix $avatarImgSrc "http")) -}}
{{- $avatarImgSrc = (urls.JoinPath $.Site.BaseURL ($.Site.Params.AvatarURL | default "")) -}}
{{- end -}}
{{- .Scratch.Set "avatarImgSrc" $avatarImgSrc -}}
{{- partial "head.html" . -}}
<body>
<script>
// Immediately set theme on page load
setThemeByUserPref();
</script>
{{- partial "header.html" . -}}
<main id="content">
{{- block "main" . }}{{- end }}
</main>
{{- partial "footer.html" . -}}
</body>
</html>

View File

@@ -0,0 +1,7 @@
{{ define "main" }}
{{ if eq .Type "page" }}
{{- partial "page.html" . -}}
{{ else }}
{{- partial "list.html" . -}}
{{ end }}
{{ end }}

View File

@@ -0,0 +1,11 @@
{{ define "main" }}
{{ if eq .Type "post" }}
{{- partial "post.html" . -}}
{{- partial "toc.html" . -}}
{{ end }}
{{ if eq .Type "page" }}
{{- partial "page.html" . -}}
{{- partial "toc.html" . -}}
{{ end }}
{{ end }}

View File

@@ -0,0 +1,21 @@
{{ define "main" }}
<div class="container tags-list">
<h1 class="list-title">{{ i18n "tags" }}</h1>
{{if eq (len $.Site.Taxonomies.tags) 0}}
{{ i18n "nothing" }}
{{else}}
<ul class="post-tags">
{{ range $.Site.Taxonomies.tags.ByCount }}
<li class="post-tag">
<a href="{{ .Page.RelPermalink }}">
<div class="tag-name">{{ .Name }}</div>
<div class="tag-posts-count">{{ .Count }}</div>
</a>
</li>
{{ end }}
</ul>
{{ end }}
</div>
{{ end }}

View File

@@ -0,0 +1,59 @@
{{ define "main" }}
<section class="home-about">
<div class="avatar">
{{ if isset .Site.Params "avatarurl" }}
<img class={{ .Site.Params.AvatarSize | default "size-m" }} src='{{ .Scratch.Get "avatarImgSrc" }}' alt="{{ .Site.Params.AvatarAltText|default "avatar" }}">
{{ end }}
</div>
<h1>{{ .Site.Title }}</h1>
{{ if isset .Site.Params "description" }}
<h2>{{ .Site.Params.Description }}</h2>
{{ end }}
</section>
<div class="flex-break"></div>
{{ if isset .Site.Params "socialicons" }}
<div class="gk-social-icons">
<ul class="gk-social-icons-list">
{{ range .Site.Params.SocialIcons }}
<li class="gk-social-icon">
<a href="{{ .url }}" target="_blank" rel="{{ if .rel }}{{ .rel }} {{ end }}noopener noreferrer" aria-label="Learn more on {{ .name }}">
<img class="svg-inject" src="{{ relURL "svg/icons/" }}{{ .name | lower }}.svg" alt="">
</a>
</li>
{{ end }}
</ul>
</div>
{{ end }}
{{ if (or
(and (fileExists "content/_index.md") .Content)
(fileExists "content/index-about.md")) }}
<section class="home-content">
{{ or .Content (readFile "index-about.md" | markdownify) }}
</section>
{{ end }}
{{ if isset .Site.Params "showpostsonhomepage" }}
<div class="home-posts list-posts">
<h2>{{ i18n (.Site.Params.ShowPostsOnHomePage | humanize) }}</h2>
{{ $posts := where .Site.Pages "Params.type" "post" }}
{{ if eq .Site.Params.ShowPostsOnHomePage "popular" }}
{{ range $posts.ByWeight | first (or .Site.Params.NumberPostsOnHomePage 4) }}
{{- partial "list-posts.html" . -}}
{{ end }}
{{ else if eq .Site.Params.ShowPostsOnHomePage "recent" }}
{{ range $posts.ByDate.Reverse | first (or .Site.Params.NumberPostsOnHomePage 4) }}
{{- partial "list-posts.html" . -}}
{{ end }}
{{ end }}
</div>
{{ end }}
{{ end }}

View File

@@ -0,0 +1,23 @@
<svg id="btt-button" class="arrow-logo" xmlns="http://www.w3.org/2000/svg" height="1em" viewBox="0 0 384 512" onclick="scrollToTop()" title="Go to top">
<!-- Your arrow SVG path or elements go here -->
<path d="M177 159.7l136 136c9.4 9.4 9.4 24.6 0 33.9l-22.6 22.6c-9.4 9.4-24.6 9.4-33.9 0L160 255.9l-96.4 96.4c-9.4 9.4-24.6 9.4-33.9 0L7 329.7c-9.4-9.4-9.4-24.6 0-33.9l136-136c9.4-9.5 24.6-9.5 34-.1z"/>
</svg>
<script>
let backToTopButton = document.getElementById("btt-button");
window.onscroll = function() {
scrollFunction()
};
function scrollFunction() {
if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) {
backToTopButton.style.display = "block";
} else {
backToTopButton.style.display = "none";
}
}
function scrollToTop() {
window.scrollTo(0, 0);
}
</script>

After

Width:  |  Height:  |  Size: 896 B

View File

@@ -0,0 +1,39 @@
<footer class="footer">
<!-- Option for user to inject custom html -->
{{ if .Site.Params.CustomFooterHTML }}
{{ .Site.Params.CustomFooterHTML | safeHTML }}
{{ end }}
{{ .Scratch.Set "footerText" "" }}
{{ if (.Site.Params.Footer) }}
{{ if and (eq .Kind "page") (.Date) }}
{{ .Scratch.Add "footerText" (.Date | time.Format "2006") }}
{{ else }}
{{ .Scratch.Add "footerText" (time.Now | time.Format "2006") }}
{{ end }}
{{ if and (eq .Kind "page") (.Lastmod) (gt (time.Format "2006" .Lastmod) (time.Format "2006" .Date)) }}
{{ .Scratch.Add "footerText" "-" }}
{{ .Scratch.Add "footerText" (.Lastmod | time.Format "2006") }}
{{ end }}
{{ .Scratch.Add "footerText" " " }}
{{ .Scratch.Add "footerText" .Site.Params.Footer }}
{{ if and (eq .Kind "page") (.Site.Copyright) }}
{{ .Scratch.Add "footerText" " " }}
{{ .Scratch.Add "footerText" .Site.Copyright }}
{{ end }}
{{ end }}
{{ if (gt (.Scratch.Get "footerText" | len) 0) }}
<span>&copy; {{ .Scratch.Get "footerText" | markdownify }}</span>
{{ end }}
<span>
Made with &#10084;&#65039; using <a target="_blank" href="https://github.com/gokarna-theme/gokarna-hugo">Gokarna</a>
</span>
</footer>

View File

@@ -0,0 +1,61 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
:root {
--accent-color: {{ .Site.Params.AccentColor | default "#FF4D4D" }};
--font-size: {{ .Site.Params.FontSize | default "1.1rem" }};
}
</style>
{{ $title := .Title | markdownify | default .Site.Title }}
{{ $description := ((.Description | default (.Summary | default .Content) | default .Site.Params.Description) | plainify | truncate 160) }}
{{ $image := .Params.image | default (.Scratch.Get "avatarImgSrc") }}
{{ $siteKeywords := .Site.Params.MetaKeywords | default (slice) }}
{{ $postKeywords := .Params.tags | default (slice) }}
{{ $keywords := union $siteKeywords $postKeywords }}
<!-- SEO titles & descriptions -->
<title>{{ $title }}</title>
<meta name="description" content="{{ $description }}">
<meta name="keywords" content='{{ delimit $keywords ", "}}'>
<meta property="og:url" content="{{ .Permalink }}">
<meta property="og:type" content="website">
<meta property="og:title" content="{{ $title }}">
<meta property="og:description" content="{{ $description }}">
<meta property="og:image" content="{{ absURL $image }}">
<meta property="og:image:secure_url" content="{{ absURL $image }}">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="{{ $title }}">
<meta name="twitter:description" content="{{ $description }}">
<meta property="twitter:domain" content="{{ .Permalink }}">
<meta property="twitter:url" content="{{ .Permalink }}">
<meta name="twitter:image" content="{{ absURL $image }}">
<!-- SEO canonicals: helps Google understand your site better when using marketing campaign tagging etc -->
<link rel="canonical" href="{{ .Permalink }}">
{{ $cssNormalize := resources.Get "css/normalize.min.css" }}
<link rel="stylesheet" type="text/css" href="{{ $cssNormalize.RelPermalink }}" media="print">
{{ $cssMain := resources.Get "css/main.css" | minify }}
<link rel="stylesheet" type="text/css" href="{{ $cssMain.RelPermalink }}">
{{ $cssDark := resources.Get "css/dark.css" | minify }}
<link id="dark-theme" rel="stylesheet" href="{{ $cssDark.RelPermalink }}">
{{ $jsBundle := resources.Match "js/**.js" | resources.Concat "js/bundle.js" | minify | resources.Fingerprint "sha256" }}
<script src="{{ $jsBundle.RelPermalink }}" integrity="{{ $jsBundle.Data.Integrity }}"></script>
{{ range .AlternativeOutputFormats }}
{{ printf "<link rel=%q type=%q href=%q title=%q>" .Rel .MediaType.Type .Permalink $.Site.Title | safeHTML }}
{{ end }}
<!-- Option for user to inject custom html -->
{{ if .Site.Params.CustomHeadHTML }}
{{ .Site.Params.CustomHeadHTML | safeHTML }}
{{ end }}
</head>

View File

@@ -0,0 +1,59 @@
<header class="header">
<nav class="header-nav">
{{ if isset .Site.Params "avatarurl" }}
<div class="avatar">
<a href="{{ .Site.BaseURL }}">
<img src='{{ .Scratch.Get "avatarImgSrc" }}' alt="{{ .Site.Params.AvatarAltText|default "avatar" }}">
</a>
</div>
{{ end }}
<div class="nav-title">
<a class="nav-brand" href="{{ .Site.BaseURL }}">{{ .Site.Title }}</a>
</div>
<div class="nav-links">
{{ range .Site.Menus.main }}
<div class="nav-link">
<a href="{{ .URL | absURL }}" aria-label="{{ .Identifier }}" {{ if .Params.NewPage -}}target="_blank" {{- end -}}>
{{- .Pre | safeHTML }} {{ .Name }} {{ .Post | safeHTML -}}
</a>
</div>
{{ end }}
<span class="nav-icons-divider"></span>
<div class="nav-link dark-theme-toggle">
<span class="sr-only dark-theme-toggle-screen-reader-target">theme</span>
<a aria-hidden="true" role="switch">
<span class="theme-toggle-icon" data-feather="moon"></span>
</a>
</div>
<div class="nav-link" id="hamburger-menu-toggle">
<span class="sr-only hamburger-menu-toggle-screen-reader-target">menu</span>
<a aria-checked="false" aria-labelledby="hamburger-menu-toggle" id="hamburger-menu-toggle-target" role="switch">
<span data-feather="menu"></span>
</a>
</div>
<!-- For mobile -->
<ul class="nav-hamburger-list visibility-hidden">
{{ range .Site.Menus.main }}
<li class="nav-item">
<a href="{{ .URL | absURL }}" {{ if .Params.NewPage -}} target="_blank"{{- end -}}>
{{- .Pre | safeHTML }} {{ .Name }} {{ .Post | safeHTML -}}
</a>
</li>
{{ end }}
<li class="nav-item dark-theme-toggle">
<span class="sr-only dark-theme-toggle-screen-reader-target">theme</span>
<a role="switch">
<span class="theme-toggle-icon" data-feather="moon"></span>
</a>
</li>
</ul>
</div>
</nav>
</header>

View File

@@ -0,0 +1,16 @@
<div class="post-title">
<a href="{{ .Permalink }}" class="post-link">{{ .Title | markdownify }}</a>
{{/* Decide to display the date based on the tags */}}
{{ $displayDate := true }}
{{ $tagsHidePostDate := or .Site.Params.Hidden.TagsPostDate slice }}
{{ $postTags := or .Params.Tags slice }}
{{ if gt ($tagsHidePostDate | intersect $postTags | len) 0 }}
{{ $displayDate = false }}
{{ end }}
{{ if eq $displayDate true }}
<div class="flex-break"></div>
<span class="post-date">{{ dateFormat (or .Site.Params.dateFormat "January 2, 2006") .Date}}</span>
{{ end }}
</div>

View File

@@ -0,0 +1,14 @@
<div class="container list-posts">
<h1 class="list-title">{{ i18n .Name }}</h1>
{{ range (where .Pages "Params.type" "post" ).GroupByDate "2006" }}
<h2 class="posts-year">{{ .Key }}</h2>
{{- range .Pages -}}
{{- partial "list-posts.html" . -}}
{{ end }}
{{ end }}
</div>

View File

@@ -0,0 +1,15 @@
<div class="post container">
<div class="post-header-section">
<h1>{{ or (.Params.H1 | markdownify) (.Title | markdownify) }}</h1>
</div>
<div class="post-content">
{{ .Content }}
</div>
<!-- Back to top button -->
{{ if .Site.Params.ShowBackToTopButton }}
{{ partial "back-to-top.html" . }}
{{ end }}
</div>

View File

@@ -0,0 +1,75 @@
<div class="post container">
<div class="post-header-section">
<h1>{{ or (.Params.H1 | markdownify) (.Title | markdownify) }}</h1>
{{/* Determine whether to display the date & description based on tags */}}
{{ $displayDate := true }}
{{ $displayDescription := true }}
{{ $postTags := or .Params.Tags slice }}
{{ $hiddenTags := or .Site.Params.Hidden.Tags slice }}
{{ $tagsHidePostDate := or .Site.Params.Hidden.TagsPostDate slice }}
{{ $tagsHidePostDescription := or .Site.Params.Hidden.TagsPostDescription slice }}
{{ if gt ($tagsHidePostDate | intersect $postTags | len) 0 }}
{{ $displayDate = false }}
{{ end }}
{{ if gt ($tagsHidePostDescription | intersect $postTags | len) 0 }}
{{ $displayDescription = false }}
{{ end }}
{{ if $displayDescription }}
<small role="doc-subtitle">{{ .Description }}</small>
{{ end }}
{{ if $displayDate }}
<p class="post-date">
{{ if (eq .Site.Params.DisplayReadingTime true) }}
{{ .ReadingTime }} min read |
{{ end }}
{{ dateFormat (or .Site.Params.dateFormat "January 2, 2006") .Date }}
{{ if lt .Date .Lastmod }}
| Updated {{ dateFormat (or .Site.Params.dateFormat "January 2, 2006") .Lastmod }}
{{ end }}
</p>
{{ end }}
<ul class="post-tags">
{{ range $tag := $postTags }}
{{ if not (in $hiddenTags $tag) }}
<li class="post-tag"><a href="{{ "tags/" | absLangURL }}{{ . | urlize }}">{{ . }}</a></li>
{{ end }}
{{ end }}
</ul>
</div>
<div class="post-content">
{{ .Content }}
{{ if .Site.Config.Services.Disqus.Shortname }}
<div class="post-comments">
{{ template "_internal/disqus.html" . }}
</div>
{{ end }}
</div>
<div class="prev-next">
{{ if (eq .Site.Params.TogglePreviousAndNextButtons true) }}
{{ if or .PrevInSection .NextInSection }}
{{ partial "prev-next.html" . }}
{{ end }}
{{ end }}
</div>
<!-- Back to top button -->
{{ if .Site.Params.ShowBackToTopButton }}
{{ partial "back-to-top.html" . }}
{{ end }}
{{ if .Site.Params.CustomCommentHTML }}
<div id="comments">
{{ .Site.Params.CustomCommentHTML | safeHTML }}
</div>
{{ end }}
</div>

View File

@@ -0,0 +1,31 @@
<nav aria-label="Post navigation" class="post-navigation">
{{ with .PrevInSection }}
<div class="prev-post">
<p>
<a href="{{ .RelPermalink }}">
&#8592;
{{ i18n "previous" }}:
{{ .Title | markdownify }}
</a>
</p>
<p class="prev-post-date">
{{ dateFormat (or .Site.Params.dateFormat "January 2, 2006") .Date}}
</p>
</div>
{{ end }}
{{ with .NextInSection }}
<div class="next-post">
<p>
<a href="{{ .RelPermalink }}">
{{ i18n "next" }}:
{{ .Title | markdownify }}
&#8594;
</a>
</p>
<p class="next-post-date">
{{ dateFormat (or .Site.Params.dateFormat "January 2, 2006") .Date}}
</p>
</div>
{{ end }}
</nav>

View File

@@ -0,0 +1,7 @@
{{ if .Params.ShowTableOfContents }}
<aside class="post-toc">
<nav id="toc">
{{ .TableOfContents }}
</nav>
</aside>
{{ end }}

View File

@@ -0,0 +1 @@
<br>