parent
84c1322c44
commit
7878db5c95
@ -0,0 +1,134 @@ |
||||
package gmi |
||||
|
||||
import ( |
||||
"bytes" |
||||
"context" |
||||
"embed" |
||||
"fmt" |
||||
"io" |
||||
"io/fs" |
||||
"net/url" |
||||
"strconv" |
||||
"strings" |
||||
"text/template" |
||||
|
||||
"git.sr.ht/~adnano/go-gemini" |
||||
"github.com/mediocregopher/blog.mediocregopher.com/srv/post" |
||||
"github.com/mediocregopher/mediocre-go-lib/v2/mctx" |
||||
) |
||||
|
||||
//go:embed tpl
|
||||
var tplFS embed.FS |
||||
|
||||
type rendererGetPostsRes struct { |
||||
Posts []post.StoredPost |
||||
HasMore bool |
||||
} |
||||
|
||||
type renderer struct { |
||||
url *url.URL |
||||
postStore post.Store |
||||
} |
||||
|
||||
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) 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) |
||||
} |
||||
|
||||
func (r renderer) Add(a, b int) int { return a + b } |
||||
|
||||
func (a *api) tplHandler() (gemini.Handler, error) { |
||||
|
||||
allTpls := template.New("") |
||||
|
||||
err := fs.WalkDir(tplFS, "tpl", func(path string, d fs.DirEntry, err error) error { |
||||
|
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
if d.IsDir() { |
||||
return nil |
||||
} |
||||
|
||||
body, err := fs.ReadFile(tplFS, path) |
||||
if err != nil { |
||||
panic(err) |
||||
} |
||||
|
||||
name := strings.TrimPrefix(path, "tpl/") |
||||
|
||||
allTpls, err = allTpls.New(name).Parse(string(body)) |
||||
if err != nil { |
||||
return fmt.Errorf("parsing %q as template: %w", path, err) |
||||
} |
||||
|
||||
return nil |
||||
}) |
||||
|
||||
if err != nil { |
||||
return nil, fmt.Errorf("parsing templates: %w", err) |
||||
} |
||||
|
||||
return gemini.HandlerFunc(func( |
||||
ctx context.Context, |
||||
rw gemini.ResponseWriter, |
||||
r *gemini.Request, |
||||
) { |
||||
|
||||
if strings.HasSuffix(r.URL.Path, "/") { |
||||
r.URL.Path += "index.gmi" |
||||
} |
||||
|
||||
tplPath := strings.TrimPrefix(r.URL.Path, "/") |
||||
|
||||
ctx = mctx.Annotate(ctx, |
||||
"url", r.URL, |
||||
"tplPath", tplPath, |
||||
) |
||||
|
||||
tpl := allTpls.Lookup(tplPath) |
||||
|
||||
if tpl == nil { |
||||
a.params.Logger.WarnString(ctx, "page not found") |
||||
rw.WriteHeader(gemini.StatusNotFound, "Page not found, sorry!") |
||||
return |
||||
} |
||||
|
||||
buf := new(bytes.Buffer) |
||||
|
||||
err := tpl.Execute(buf, renderer{ |
||||
url: r.URL, |
||||
postStore: a.params.PostStore, |
||||
}) |
||||
|
||||
if err != nil { |
||||
a.params.Logger.Error(ctx, "rendering error", err) |
||||
rw.WriteHeader(gemini.StatusTemporaryFailure, err.Error()) |
||||
return |
||||
} |
||||
|
||||
io.Copy(rw, buf) |
||||
}), nil |
||||
} |
@ -0,0 +1,3 @@ |
||||
# Index |
||||
|
||||
=> /posts/index.gmi See all posts |
@ -0,0 +1,18 @@ |
||||
# mediocregopher's Posts |
||||
|
||||
{{ $page := .GetQueryIntValue "page" 0 -}} |
||||
{{ $getPostsRes := .GetPosts $page 20 -}} |
||||
|
||||
{{ if gt $page 0 -}} |
||||
=> /posts.gmi?page={{ .Add $page -1 }} Previous Page |
||||
|
||||
{{ end -}} |
||||
|
||||
{{ range $getPostsRes.Posts -}} |
||||
=> /posts/{{ .ID }}.gmi {{ .PublishedAt.Format "2006-01-02" }} - {{ .Title }} |
||||
|
||||
{{ end -}} |
||||
|
||||
{{ if $getPostsRes.HasMore -}} |
||||
=> /posts.gmi?page={{ .Add $page 1 }} Next page |
||||
{{ end -}} |
@ -0,0 +1,9 @@ |
||||
{{ $post := .GetPostByID (.GetQueryValue "id" "") -}} |
||||
|
||||
# {{ $post.Title }} |
||||
|
||||
{{ if ne $post.Description "" -}} |
||||
> {{ $post.Description }} |
||||
{{ end -}} |
||||
|
||||
{{ $post.Body }} |
Loading…
Reference in new issue