summaryrefslogtreecommitdiff
path: root/src/gmi
diff options
context:
space:
mode:
Diffstat (limited to 'src/gmi')
-rw-r--r--src/gmi/gemtext/gemtext.go (renamed from src/gmi/gemtext.go)8
-rw-r--r--src/gmi/gemtext/gemtext_test.go (renamed from src/gmi/gemtext_test.go)6
-rw-r--r--src/gmi/gmi.go14
-rw-r--r--src/gmi/tpl.go150
-rw-r--r--src/gmi/tpl/posts/post.gmi4
5 files changed, 45 insertions, 137 deletions
diff --git a/src/gmi/gemtext.go b/src/gmi/gemtext/gemtext.go
index 884635c..5c8f594 100644
--- a/src/gmi/gemtext.go
+++ b/src/gmi/gemtext/gemtext.go
@@ -1,4 +1,6 @@
-package gmi
+// Package gemtext contains code related to processing and producing gemtext
+// documents.
+package gemtext
import (
"bufio"
@@ -23,12 +25,12 @@ func hasImgExt(p string) bool {
// matches `=> dstURL [optional description]`
var linkRegexp = regexp.MustCompile(`^=>\s+(\S+)\s*(.*?)\s*$`)
-// GemtextToMarkdown reads a gemtext formatted body from the Reader and writes
+// ToMarkdown reads a gemtext formatted body from the Reader and writes
// the markdown version of that body to the Writer.
//
// gmiGateway, if given, is used for all `gemini://` links. The `gemini://`
// prefix will be stripped, and replaced with the given URL.
-func GemtextToMarkdown(dst io.Writer, src io.Reader, gmiGateway *url.URL) error {
+func ToMarkdown(dst io.Writer, src io.Reader, gmiGateway *url.URL) error {
bufSrc := bufio.NewReader(src)
diff --git a/src/gmi/gemtext_test.go b/src/gmi/gemtext/gemtext_test.go
index 75da9df..fe58a64 100644
--- a/src/gmi/gemtext_test.go
+++ b/src/gmi/gemtext/gemtext_test.go
@@ -1,4 +1,4 @@
-package gmi
+package gemtext
import (
"bytes"
@@ -9,7 +9,7 @@ import (
"github.com/stretchr/testify/assert"
)
-func TestGemtextToMarkdown(t *testing.T) {
+func TestToMarkdown(t *testing.T) {
gmiGateway, _ := url.Parse("https://gateway.com/x/")
@@ -58,7 +58,7 @@ func TestGemtextToMarkdown(t *testing.T) {
t.Run(strconv.Itoa(i), func(t *testing.T) {
got := new(bytes.Buffer)
- err := GemtextToMarkdown(got, bytes.NewBufferString(test.in), gmiGateway)
+ err := ToMarkdown(got, bytes.NewBufferString(test.in), gmiGateway)
assert.NoError(t, err)
assert.Equal(t, test.exp, got.String())
})
diff --git a/src/gmi/gmi.go b/src/gmi/gmi.go
index 467ab5a..e37ca74 100644
--- a/src/gmi/gmi.go
+++ b/src/gmi/gmi.go
@@ -14,14 +14,14 @@ import (
"path/filepath"
"strings"
- "git.sr.ht/~adnano/go-gemini"
- "git.sr.ht/~adnano/go-gemini/certificate"
"dev.mediocregopher.com/mediocre-blog.git/src/cache"
"dev.mediocregopher.com/mediocre-blog.git/src/cfg"
"dev.mediocregopher.com/mediocre-blog.git/src/post"
"dev.mediocregopher.com/mediocre-blog.git/src/post/asset"
"dev.mediocregopher.com/mediocre-go-lib.git/mctx"
"dev.mediocregopher.com/mediocre-go-lib.git/mlog"
+ "git.sr.ht/~adnano/go-gemini"
+ "git.sr.ht/~adnano/go-gemini/certificate"
)
// Params are used to instantiate a new API instance. All fields are required
@@ -37,7 +37,8 @@ type Params struct {
ListenAddr string
CertificatesPath string
- HTTPPublicURL *url.URL
+ HTTPPublicURL *url.URL
+ HTTPGeminiGatewayURL *url.URL
}
// SetupCfg implement the cfg.Cfger interface.
@@ -193,12 +194,7 @@ func postsMiddleware(tplHandler gemini.Handler) gemini.Handler {
return
}
- query := r.URL.Query()
- query.Set("id", id)
- r.URL.RawQuery = query.Encode()
-
- r.URL.Path = "/posts/post.gmi"
-
+ ctx = withTplPath(ctx, "/posts/post.gmi")
tplHandler.ServeGemini(ctx, rw, r)
})
}
diff --git a/src/gmi/tpl.go b/src/gmi/tpl.go
index 03d9819..8ffa6bc 100644
--- a/src/gmi/tpl.go
+++ b/src/gmi/tpl.go
@@ -4,6 +4,7 @@ import (
"bytes"
"context"
"embed"
+ "errors"
"fmt"
"io"
"io/fs"
@@ -11,126 +12,27 @@ import (
"net/url"
"path"
"path/filepath"
- "strconv"
"strings"
"text/template"
- "git.sr.ht/~adnano/go-gemini"
"dev.mediocregopher.com/mediocre-blog.git/src/post"
+ "dev.mediocregopher.com/mediocre-blog.git/src/render"
"dev.mediocregopher.com/mediocre-go-lib.git/mctx"
- gmnhg "github.com/tdemin/gmnhg"
+ "git.sr.ht/~adnano/go-gemini"
)
-//go:embed tpl
-var tplFS embed.FS
-
-type rendererGetPostsRes struct {
- Posts []post.StoredPost
- HasMore bool
-}
-
-type rendererGetPostSeriesNextPreviousRes struct {
- Next *post.StoredPost
- Previous *post.StoredPost
-}
-
-type renderer struct {
- url *url.URL
- publicURL *url.URL
- postStore post.Store
- preprocessFuncs post.PreprocessFunctions
-}
-
-func (r renderer) GetPosts(page, count int) (rendererGetPostsRes, error) {
- posts, hasMore, err := r.postStore.Get(page, count)
- return rendererGetPostsRes{posts, hasMore}, err
-}
-
-func (r renderer) GetPostByID(id string) (post.StoredPost, error) {
- p, err := r.postStore.GetByID(id)
- if err != nil {
- return post.StoredPost{}, fmt.Errorf("fetching post %q: %w", id, err)
- }
- return p, nil
-}
-
-func (r renderer) GetPostSeriesNextPrevious(p post.StoredPost) (rendererGetPostSeriesNextPreviousRes, error) {
-
- seriesPosts, err := r.postStore.GetBySeries(p.Series)
- if err != nil {
- return rendererGetPostSeriesNextPreviousRes{}, fmt.Errorf(
- "fetching posts for series %q: %w", p.Series, err,
- )
- }
-
- var (
- res rendererGetPostSeriesNextPreviousRes
- foundThis bool
- )
-
- for i := range seriesPosts {
-
- seriesPost := seriesPosts[i]
-
- if seriesPost.ID == p.ID {
- foundThis = true
- continue
- }
-
- if !foundThis {
- res.Next = &seriesPost
- continue
- }
-
- res.Previous = &seriesPost
- break
- }
-
- return res, nil
-}
-
-func (r renderer) PostBody(p post.StoredPost) (string, error) {
-
- buf := new(bytes.Buffer)
-
- if err := p.PreprocessBody(buf, r.preprocessFuncs); err != nil {
- return "", fmt.Errorf("preprocessing post body: %w", err)
- }
-
- bodyBytes := buf.Bytes()
-
- if p.Format == post.FormatMarkdown {
-
- gemtextBodyBytes, err := gmnhg.RenderMarkdown(bodyBytes, 0)
- if err != nil {
- return "", fmt.Errorf("converting from markdown: %w", err)
- }
-
- bodyBytes = gemtextBodyBytes
- }
-
- return string(bodyBytes), nil
-}
+type ctxKey string
-func (r renderer) GetQueryValue(key, def string) string {
- v := r.url.Query().Get(key)
- if v == "" {
- v = def
- }
- return v
-}
-
-func (r renderer) GetQueryIntValue(key string, def int) (int, error) {
- vStr := r.GetQueryValue(key, strconv.Itoa(def))
- return strconv.Atoi(vStr)
-}
+const (
+ ctxKeyTplPath ctxKey = "tplPath"
+)
-func (r renderer) GetPath() (string, error) {
- basePath := filepath.Join("/", r.publicURL.Path) // in case it's empty
- return filepath.Rel(basePath, r.url.Path)
+func withTplPath(ctx context.Context, path string) context.Context {
+ return context.WithValue(ctx, ctxKeyTplPath, path)
}
-func (r renderer) Add(a, b int) int { return a + b }
+//go:embed tpl
+var tplFS embed.FS
func (a *api) tplHandler() (gemini.Handler, error) {
@@ -177,7 +79,6 @@ func (a *api) tplHandler() (gemini.Handler, error) {
return blogURL(a.params.HTTPPublicURL, path, true)
},
Image: func(args ...string) (string, error) {
-
var (
id = args[0]
descr = "Image"
@@ -243,9 +144,13 @@ func (a *api) tplHandler() (gemini.Handler, error) {
rw gemini.ResponseWriter,
r *gemini.Request,
) {
+ tplPath, _ := ctx.Value(ctxKeyTplPath).(string)
+ if tplPath == "" {
+ tplPath = r.URL.Path
+ }
+ tplPath = strings.TrimPrefix(tplPath, "/")
- tplPath := strings.TrimPrefix(r.URL.Path, "/")
- mimeType := mime.TypeByExtension(path.Ext(r.URL.Path))
+ mimeType := mime.TypeByExtension(path.Ext(tplPath))
ctx = mctx.Annotate(ctx,
"url", r.URL,
@@ -266,14 +171,19 @@ func (a *api) tplHandler() (gemini.Handler, error) {
buf := new(bytes.Buffer)
- err := tpl.Execute(buf, renderer{
- url: r.URL,
- publicURL: a.params.PublicURL,
- postStore: a.params.PostStore,
- preprocessFuncs: preprocessFuncs,
- })
-
- if err != nil {
+ err := tpl.Execute(buf, render.NewMethods(
+ ctx,
+ r.URL,
+ a.params.PublicURL,
+ a.params.HTTPGeminiGatewayURL,
+ a.params.PostStore,
+ preprocessFuncs,
+ ))
+
+ if errors.Is(err, post.ErrPostNotFound) {
+ a.params.Logger.Warn(ctx, "post not found", err)
+ rw.WriteHeader(gemini.StatusNotFound, "Post not found")
+ } else if err != nil {
a.params.Logger.Error(ctx, "rendering error", err)
rw.WriteHeader(gemini.StatusTemporaryFailure, err.Error())
return
diff --git a/src/gmi/tpl/posts/post.gmi b/src/gmi/tpl/posts/post.gmi
index 0234395..b568044 100644
--- a/src/gmi/tpl/posts/post.gmi
+++ b/src/gmi/tpl/posts/post.gmi
@@ -1,4 +1,4 @@
-{{ $post := .GetPostByID (.GetQueryValue "id" "") -}}
+{{ $post := .GetThisPost -}}
{{ if eq $post.Format "md" -}}
This post has been translated from it's original markdown format, if it seems busted it might appear better over HTTP:
@@ -14,7 +14,7 @@ This post has been translated from it's original markdown format, if it seems bu
{{ end -}}
-{{ .PostBody $post }}
+{{ .PostGemtextBody $post }}
========================================