Generate anchor links for headings
This will generate `id` attributes for all heading levels. The labels are generated using steps 1-4 of the gitlab flavored markdown algorithm which seems to be pretty standard for generating anchors: https://docs.gitlab.com/ee/user/markdown.html#header-ids-and-links A unique ID isn't appended to avoid having to store a list of previous headers to compare against.
This commit is contained in:
parent
a8c54c1a32
commit
857f8c97eb
1 changed files with 23 additions and 6 deletions
29
main.go
29
main.go
|
@ -13,6 +13,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
"unicode"
|
||||||
|
|
||||||
"git.sr.ht/~adnano/go-gemini"
|
"git.sr.ht/~adnano/go-gemini"
|
||||||
"git.sr.ht/~sircmpwn/getopt"
|
"git.sr.ht/~sircmpwn/getopt"
|
||||||
|
@ -24,11 +25,11 @@ var gemtextPage = template.Must(template.
|
||||||
"heading": func(line gemini.Line) *GemtextHeading {
|
"heading": func(line gemini.Line) *GemtextHeading {
|
||||||
switch l := line.(type) {
|
switch l := line.(type) {
|
||||||
case gemini.LineHeading1:
|
case gemini.LineHeading1:
|
||||||
return &GemtextHeading{1, string(l)}
|
return &GemtextHeading{1, string(l), createAnchor(string(l))}
|
||||||
case gemini.LineHeading2:
|
case gemini.LineHeading2:
|
||||||
return &GemtextHeading{2, string(l)}
|
return &GemtextHeading{2, string(l), createAnchor(string(l))}
|
||||||
case gemini.LineHeading3:
|
case gemini.LineHeading3:
|
||||||
return &GemtextHeading{3, string(l)}
|
return &GemtextHeading{3, string(l), createAnchor(string(l))}
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -147,7 +148,7 @@ var gemtextPage = template.Must(template.
|
||||||
|
|
||||||
{{- with . | heading }}
|
{{- with . | heading }}
|
||||||
{{- $isList = false -}}
|
{{- $isList = false -}}
|
||||||
<h{{.Level}}>{{.Text}}</h{{.Level}}>
|
<h{{.Level}} id="{{.Anchor}}">{{.Text}}</h{{.Level}}>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|
||||||
{{- with . | link }}
|
{{- with . | link }}
|
||||||
|
@ -388,8 +389,24 @@ type InputContext struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type GemtextHeading struct {
|
type GemtextHeading struct {
|
||||||
Level int
|
Level int
|
||||||
Text string
|
Text string
|
||||||
|
Anchor string
|
||||||
|
}
|
||||||
|
|
||||||
|
func createAnchor(heading string) string {
|
||||||
|
var anchor strings.Builder
|
||||||
|
prev := '-'
|
||||||
|
for _, c := range heading {
|
||||||
|
if unicode.IsLetter(c) || unicode.IsDigit(c) {
|
||||||
|
anchor.WriteRune(unicode.ToLower(c))
|
||||||
|
prev = c
|
||||||
|
} else if (unicode.IsSpace(c) || c == '-') && prev != '-' {
|
||||||
|
anchor.WriteRune('-')
|
||||||
|
prev = '-'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return strings.ToLower(anchor.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func proxyGemini(req gemini.Request, external bool, root *url.URL,
|
func proxyGemini(req gemini.Request, external bool, root *url.URL,
|
||||||
|
|
Loading…
Reference in a new issue