~sircmpwn/gmni-devel

kineto: Generate anchor links for headings v1 APPLIED

nytpu: 1
 Generate anchor links for headings

 1 files changed, 23 insertions(+), 6 deletions(-)
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~sircmpwn/gmni-devel/patches/26214/mbox | git am -3
Learn more about email & git
View this thread in the archives

[PATCH kineto] Generate anchor links for headings Export this patch

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 has been tested locally and on my capsule's public kineto proxy.

Would it be good to also add a link enclosing the header to allow for
clicking on the header to get the full url with the fragment?  Or do
something like the Sourcehut markdown converter does and add an icon
next to the headers that'll link to the header?  I could send a
follow-up patch.

 main.go | 29 +++++++++++++++++++++++------
 1 file changed, 23 insertions(+), 6 deletions(-)

diff --git a/main.go b/main.go
index 535ce75..483b01b 100644
--- a/main.go
+++ b/main.go
@@ -13,6 +13,7 @@ import (
	"os"
	"strings"
	"time"
	"unicode"

	"git.sr.ht/~adnano/go-gemini"
	"git.sr.ht/~sircmpwn/getopt"
@@ -24,11 +25,11 @@ var gemtextPage = template.Must(template.
		"heading": func(line gemini.Line) *GemtextHeading {
			switch l := line.(type) {
			case gemini.LineHeading1:
				return &GemtextHeading{1, string(l)}
				return &GemtextHeading{1, string(l), createAnchor(string(l))}
			case gemini.LineHeading2:
				return &GemtextHeading{2, string(l)}
				return &GemtextHeading{2, string(l), createAnchor(string(l))}
			case gemini.LineHeading3:
				return &GemtextHeading{3, string(l)}
				return &GemtextHeading{3, string(l), createAnchor(string(l))}
			default:
				return nil
			}
@@ -153,7 +154,7 @@ var gemtextPage = template.Must(template.

	{{- with . | heading }}
	{{- $isList = false -}}
	<h{{.Level}}>{{.Text}}</h{{.Level}}>
	<h{{.Level}} id="{{.Anchor}}">{{.Text}}</h{{.Level}}>
	{{- end -}}

	{{- with . | link }}
@@ -395,8 +396,24 @@ type InputContext struct {
}

type GemtextHeading struct {
	Level int
	Text  string
	Level  int
	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,
-- 
2.33.1
Thanks!

To git@git.sr.ht:~sircmpwn/kineto
   a8c54c1..857f8c9  master -> master