munin/internal/store/links.go
2026-09-15 20:36:26 +02:00

55 lines
1.7 KiB
Go

package store
import (
"regexp"
"sort"
"strings"
)
// linkPattern findet Verweise der Form [[slug]] im Inhalt eines Eintrags.
//
// Die Schreibweise stammt aus Wiki-Systemen und ist Menschen wie KI-Werkzeugen
// vertraut. Sie hat einen praktischen Vorzug gegenüber Markdown-Links: Sie
// enthält nur den Bezeichner, keine URL — die Verweise bleiben also gültig,
// wenn sich Adressen ändern, und sie sind ohne Kontextwissen erkennbar.
//
// Erlaubt ist derselbe Zeichenvorrat wie bei Slugs (siehe ValidSlug). Damit wird
// aus "[[siehe hier]]" kein Verweis — das ist gewollt, sonst würde jede eckige
// Klammer im Text zu einem Falschtreffer.
var linkPattern = regexp.MustCompile(`\[\[([a-z0-9][a-z0-9_-]{0,63})\]\]`)
// ExtractLinks liest alle [[slug]]-Verweise aus einem Text.
// Das Ergebnis ist sortiert und ohne Dubletten — ein zweiter Verweis auf dasselbe
// Ziel ist keine zusätzliche Information.
func ExtractLinks(content string) []string {
treffer := linkPattern.FindAllStringSubmatch(content, -1)
if len(treffer) == 0 {
return nil
}
gesehen := make(map[string]bool, len(treffer))
var ziele []string
for _, t := range treffer {
ziel := t[1]
if gesehen[ziel] {
continue
}
gesehen[ziel] = true
ziele = append(ziele, ziel)
}
sort.Strings(ziele)
return ziele
}
// ReplaceLinks ersetzt jeden [[slug]]-Verweis durch das Ergebnis von fn.
//
// Wird beim Rendern verwendet, um aus den Verweisen echte Links zu machen. Die
// Ersetzungsfunktion bekommt den Slug und liefert den Ersatztext.
func ReplaceLinks(content string, fn func(slug string) string) string {
return linkPattern.ReplaceAllStringFunc(content, func(treffer string) string {
slug := strings.TrimSuffix(strings.TrimPrefix(treffer, "[["), "]]")
return fn(slug)
})
}