From c9d28a108d6df59a895dd10f47e834ceba20f98a Mon Sep 17 00:00:00 2001 From: Brian Picciano Date: Thu, 4 Jul 2024 18:25:17 +0200 Subject: Add gateway_url parameter in gemtext template --- README.md | 43 +++++++++++++++++++++----- example/Caddyfile | 4 ++- http/handlers/templates/functions/gemtext.go | 46 ++++++++++++++++++++++++++-- 3 files changed, 81 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index a914f51..30a3285 100644 --- a/README.md +++ b/README.md @@ -20,11 +20,45 @@ function][mdfunc] in its usage. It can be enabled by being included in the ```text templates { extensions { - gemtext + gemtext { + # All parameters are optional + gateway_url "https://some.gateway/x/" + } } } ``` +See the `template.localhost` virtual host in `example/Caddyfile`, and the +associated `example/tpl/render_gemtext.html` template file, for an example of +how to use this directive. + +[gemtext]: https://geminiprotocol.net/docs/gemtext.gmi +[mdfunc]: https://caddyserver.com/docs/modules/http.handlers.templates#markdown + +#### Parameters + +Optional parameters to the gemtext extension include: + +**gateway_url** + +If given then any `gemini://` URLs encountered as links within +the document will be appended to this URL, having their `gemini://` scheme +stripped off first. + +e.g. if `gateway_url` is `https://some.gateway/x/` then the following line: + +```text +=> gemini://geminiprotocol.net Check it out! +``` + +becomes + +```html +Check it out! +``` + +#### Template function + Within a template being rendered the `gemtext` function will be available and can be passed any string. The function will return a struct with the following fields: @@ -36,13 +70,6 @@ fields: * `Title`: A suggested title, based on the first `# Header` line found in the gemtext input. -See the `template.localhost` virtual host in `example/Caddyfile`, and the -associated `example/tpl/render_gemtext.html` template file, for an example of -how to use the template function. - -[gemtext]: https://geminiprotocol.net/docs/gemtext.gmi -[mdfunc]: https://caddyserver.com/docs/modules/http.handlers.templates#markdown - ## Development A nix-based development environment is provided with the correct versions of all diff --git a/example/Caddyfile b/example/Caddyfile index 8d9dd50..05ad0ba 100644 --- a/example/Caddyfile +++ b/example/Caddyfile @@ -26,7 +26,9 @@ http://template.localhost { # Include the gemtext extention to make the gemtext function # available within the template. extensions { - gemtext + gemtext { + gateway_url "https://gemini.tildeverse.org/?gemini://" + } } } diff --git a/http/handlers/templates/functions/gemtext.go b/http/handlers/templates/functions/gemtext.go index 57ea751..179d558 100644 --- a/http/handlers/templates/functions/gemtext.go +++ b/http/handlers/templates/functions/gemtext.go @@ -7,6 +7,7 @@ import ( "fmt" "html" "io" + "net/url" "strings" "text/template" @@ -30,7 +31,22 @@ func init() { ) } -type Gemtext struct{} +type Gemtext struct { + + // If given then any `gemini://` URLs encountered as links within the + // document will be appended to this URL, having their `gemini://` scheme + // stripped off first. + // + // e.g. if `gateway_url` is `https://some.gateway/x/` then the following + // line: + // + // => gemini://geminiprotocol.net Check it out! + // + // becomes + // + // Check it out! + GatewayURL string `json:"gateway_url,omitempty"` +} var _ templates.CustomFunctions = (*Gemtext)(nil) @@ -56,7 +72,7 @@ type gemtextResult struct { Body string } -func (*Gemtext) funcGemtext(input any) (gemtextResult, error) { +func (g *Gemtext) funcGemtext(input any) (gemtextResult, error) { var ( r = bufio.NewReader(strings.NewReader(caddy.ToString(input))) w = new(bytes.Buffer) @@ -126,9 +142,17 @@ loop: urlStr = line label = urlStr ) + if i := strings.IndexAny(urlStr, " \t"); i > -1 { urlStr, label = urlStr[:i], sanitizeText(urlStr[i:]) } + + if g.GatewayURL != "" { + if u, err := url.Parse(urlStr); err == nil && u.Scheme == "gemini" { + urlStr = g.GatewayURL + u.Host + u.Path + } + } + write("

%s

\n", urlStr, label) case strings.HasPrefix(line, "###"): @@ -160,7 +184,23 @@ loop: } // UnmarshalCaddyfile implements caddyfile.Unmarshaler. -func (*Gemtext) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { +func (g *Gemtext) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { d.Next() // consume directive name + + for nesting := d.Nesting(); d.NextBlock(nesting); { + v := d.Val() + switch v { + case "gateway_url": + if !d.Args(&g.GatewayURL) { + return d.ArgErr() + } else if _, err := url.Parse(g.GatewayURL); err != nil { + return fmt.Errorf("invalid gateway url: %w", err) + } + + default: + return fmt.Errorf("unknown directive %q", v) + } + } + return nil } -- cgit v1.2.3