From 1709dc093c39b2880cff7f83a1b166b5dc8661b4 Mon Sep 17 00:00:00 2001 From: karim Date: Sat, 6 Jun 2026 01:40:00 +0200 Subject: [PATCH] feature(library): Wiki-Links, Backlinks, Suche + A-Z-Index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit single.html: [[Begriff]]-Auflösung zu internen Links (.wikilink), fehlende Seiten als .wikilink-missing, „Siehe auch" (Gruppe+Tags) und „Erwähnt in" (Backlinks), Eintrags-Fuss mit Gruppe + bearbeiten. list.html: Suchfeld + A-Z-Index mit JS-Filter (Umlaute normalisiert), data-title auf
  • für clientseitiges Filtern. custom.css: .wikilink, .wikilink-missing, .entry-links, .entry-links-label, .lib-filter, .lib-search, .lib-az — alle via --section-color (ichigo/rose). Co-Authored-By: Claude Sonnet 4.6 --- assets/css/custom.css | 27 ++++++++++++++ layouts/library/list.html | 74 +++++++++++++++++++++++++++++++++---- layouts/library/single.html | 69 +++++++++++++++++++++++++++------- 3 files changed, 150 insertions(+), 20 deletions(-) diff --git a/assets/css/custom.css b/assets/css/custom.css index ee3b18b..6f73be7 100644 --- a/assets/css/custom.css +++ b/assets/css/custom.css @@ -729,6 +729,33 @@ a.byline-author:hover, a.journal-author:hover { color: var(--accent); } .entry-foot a { color: var(--color-text-muted); text-decoration: none; } .entry-foot a:hover { color: var(--accent); } +/* Wiki-Links in Library-Einträgen */ +.wikilink { color: var(--section-color, var(--accent)); text-decoration: underline; text-decoration-style: dotted; text-underline-offset: 0.2em; } +.wikilink:hover { text-decoration-style: solid; } +.wikilink-missing { color: var(--color-text-muted); border-bottom: 1px dashed currentColor; } + +/* Querverweise: „Siehe auch" + „Erwähnt in" */ +.entry-links { margin-top: var(--spacing-md); padding: 0.7em 1em; + background: color-mix(in oklab, var(--section-color, var(--accent)) 8%, transparent); + border-left: 3px solid var(--section-color, var(--accent)); border-radius: 0 8px 8px 0; } +.entry-links + .entry-links { margin-top: 0.5em; } +.entry-links ul { list-style: none; margin: 0.3em 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 0.25em 0.8em; } +.entry-links li { font-size: var(--font-size-small); } +.entry-links a { color: var(--section-color, var(--accent)); text-decoration: none; } +.entry-links a:hover { text-decoration: underline; text-underline-offset: 0.2em; } +.entry-links-label { font-size: var(--font-size-small); font-weight: 600; color: var(--color-text-muted); text-transform: uppercase; letter-spacing: 0.04em; } + +/* Library-Übersicht: Suchfeld + A-Z-Index */ +.lib-filter { margin-bottom: var(--spacing-md); display: flex; flex-direction: column; gap: 0.6em; } +.lib-search { width: 100%; padding: 0.45em 0.8em; border: 1px solid var(--color-border); border-radius: 6px; + background: var(--color-bg-secondary); color: var(--color-text-primary); font-size: var(--font-size-base); font-family: inherit; } +.lib-search:focus { outline: none; border-color: var(--section-color, var(--accent)); } +.lib-az { display: flex; flex-wrap: wrap; gap: 0.25em; } +.lib-az button { padding: 0.15em 0.45em; border: 1px solid var(--color-border); border-radius: 4px; + background: transparent; color: var(--color-text-muted); font-size: var(--font-size-small); cursor: pointer; font-family: inherit; line-height: 1.5; } +.lib-az button:hover { border-color: var(--section-color, var(--accent)); color: var(--color-text-primary); } +.lib-az button.active { background: var(--section-color, var(--accent)); border-color: var(--section-color, var(--accent)); color: white; } + /* ── Software-Landing: Werkzeuge getrennt von Texten ── */ .software-h { font-family: var(--font-family-serif); margin: var(--spacing-md) 0 var(--spacing-sm); } .software-tools { margin-bottom: var(--spacing-lg); } diff --git a/layouts/library/list.html b/layouts/library/list.html index 850e3f4..a15ee97 100644 --- a/layouts/library/list.html +++ b/layouts/library/list.html @@ -5,21 +5,47 @@ {{ .Content }} {{ $pages := where site.RegularPages "Section" "library" }} - {{ $groups := dict }} - {{ range $pages }} - {{ $g := .Params.group | default "Allgemein" }} - {{ $existing := index $groups $g | default slice }} - {{ $groups = merge $groups (dict $g ($existing | append .)) }} - {{ end }} {{ if $pages }} + {{/* A-Z Buchstaben aus vorhandenen Titeln */}} + {{ $letters := slice }} + {{ range $pages }} + {{ $first := substr (upper .Title) 0 1 }} + {{ $first = replace $first "Ä" "A" }} + {{ $first = replace $first "Ö" "O" }} + {{ $first = replace $first "Ü" "U" }} + {{ if not (in $letters $first) }}{{ $letters = $letters | append $first }}{{ end }} + {{ end }} + {{ $letters = sort $letters }} + +
    + +
    + + {{ range $letters }}{{ end }} +
    +
    + + {{/* Gruppen aufbauen */}} + {{ $groups := dict }} + {{ range $pages }} + {{ $g := .Params.group | default "Allgemein" }} + {{ $existing := index $groups $g | default slice }} + {{ $groups = merge $groups (dict $g ($existing | append .)) }} + {{ end }} +
    {{ range $g, $ps := $groups }}

    {{ $g }}

      {{ range sort $ps "Title" }} -
    • + {{ $norm := lower .Title }} + {{ $norm = replace $norm "ä" "a" }} + {{ $norm = replace $norm "ö" "o" }} + {{ $norm = replace $norm "ü" "u" }} + {{ $norm = replace $norm "ß" "ss" }} +
    • {{ .LinkTitle }} {{ with .Params.summary }} — {{ . }}{{ end }}
    • @@ -28,6 +54,40 @@
    {{ end }}
    + + {{ else }}

    Noch keine Einträge — der erste entsteht im Redaktions-Editor.

    {{ end }} diff --git a/layouts/library/single.html b/layouts/library/single.html index c4b3d52..8a8fa35 100644 --- a/layouts/library/single.html +++ b/layouts/library/single.html @@ -1,5 +1,5 @@ {{ define "main" }} -
    +

    {{ .Title }}

    {{ with .Params.summary }}

    {{ . }}

    {{ end }} @@ -14,20 +14,63 @@ {{ end }} -
    - {{ .Content }} -
    + {{/* Wiki-Links [[Titel]] / [[slug]] → Link auf die passende Library-Seite. */}} + {{ $html := .Content }} + {{ range (where site.RegularPages "Section" "library") }} + {{ $a := printf `%s` .RelPermalink .LinkTitle }} + {{ $html = replace $html (printf "[[%s]]" .LinkTitle) $a }} + {{ $html = replace $html (printf "[[%s]]" .File.ContentBaseName) $a }} + {{ end }} + {{/* Übrige (noch nicht angelegte) Verweise: ohne Klammern, dezent markiert. */}} + {{ $html = replaceRE `\[\[([^\]]+)\]\]` `$1` $html }} +
    {{ $html | safeHTML }}
    - {{/* Fuss: Gruppe + weitere Einträge derselben Gruppe + bearbeiten. */}} - {{ $g := .Params.group | default "Allgemein" }} - {{ $siblings := where (where site.RegularPages "Section" "library") "Params.group" (.Params.group) }} + {{/* ── Siehe auch: gleiche Gruppe + geteilte Tags ── */}} + {{ $cur := . }} + {{ $related := slice }} + {{ range where (where site.RegularPages "Section" "library") "Params.group" .Params.group }} + {{ if ne .RelPermalink $cur.RelPermalink }}{{ $related = $related | append . }}{{ end }} + {{ end }} + {{ with .Params.tags }} + {{ range $t := . }} + {{ range (where site.RegularPages "Section" "library") }} + {{ if and (ne .RelPermalink $cur.RelPermalink) (in (.Params.tags | default slice) $t) }} + {{ $related = $related | append . }} + {{ end }} + {{ end }} + {{ end }} + {{ end }} + {{ $related = $related | uniq }} + {{ with $related }} + + {{ end }} + + {{/* ── Erwähnt in (Backlinks): Seiten, die per Link oder [[…]] hierher zeigen ── */}} + {{ $back := slice }} + {{ $url := .RelPermalink }} + {{ $tok1 := printf "[[%s]]" .Title }} + {{ $tok2 := printf "[[%s]]" .File.ContentBaseName }} + {{ range site.RegularPages }} + {{ if ne .RelPermalink $url }} + {{ $raw := .RawContent }} + {{ if or (in $raw $url) (in $raw $tok1) (in $raw $tok2) }} + {{ $back = $back | append . }} + {{ end }} + {{ end }} + {{ end }} + {{ with $back }} + + {{ end }} + + {{/* Fuss: Gruppe + zuletzt bearbeitet + bearbeiten. */}}
    - - {{ $g }} - {{ $others := slice }} - {{ range $siblings }}{{ if ne .RelPermalink $.RelPermalink }}{{ $others = $others | append . }}{{ end }}{{ end }} - {{ with $others }} · {{ range $i, $p := . }}{{ if $i }} · {{ end }}{{ $p.LinkTitle }}{{ end }}{{ end }} - + {{ .Params.group | default "Allgemein" }} {{ if .Lastmod }}Zuletzt bearbeitet am {{ .Lastmod.Format "02.01.2006" }}{{ end }} {{ with .File }}bearbeiten ↗{{ end }}