summaryrefslogtreecommitdiff
path: root/srv/src
diff options
context:
space:
mode:
Diffstat (limited to 'srv/src')
-rw-r--r--srv/src/api/api.go12
-rw-r--r--srv/src/api/apiutil/apiutil.go (renamed from srv/src/api/apiutils/apiutils.go)4
-rw-r--r--srv/src/api/chat.go36
-rw-r--r--srv/src/api/csrf.go14
-rw-r--r--srv/src/api/mailinglist.go24
-rw-r--r--srv/src/api/middleware.go6
-rw-r--r--srv/src/api/posts.go65
-rw-r--r--srv/src/api/pow.go10
-rw-r--r--srv/src/api/tpl/base.html (renamed from srv/src/tpl/html/base.html)0
-rw-r--r--srv/src/api/tpl/post.html (renamed from srv/src/tpl/html/post.html)0
-rw-r--r--srv/src/cmd/mediocre-blog/main.go1
-rw-r--r--srv/src/post/renderer.go96
-rw-r--r--srv/src/post/renderer_test.go92
-rw-r--r--srv/src/tpl/tpl.go12
14 files changed, 111 insertions, 261 deletions
diff --git a/srv/src/api/api.go b/srv/src/api/api.go
index 75147d5..92771a1 100644
--- a/srv/src/api/api.go
+++ b/srv/src/api/api.go
@@ -3,8 +3,10 @@ package api
import (
"context"
+ "embed"
"errors"
"fmt"
+ "html/template"
"net"
"net/http"
"net/http/httputil"
@@ -20,14 +22,18 @@ import (
"github.com/mediocregopher/mediocre-go-lib/v2/mlog"
)
+//go:embed tpl
+var fs embed.FS
+
+var tpls = template.Must(template.ParseFS(fs, "tpl/*"))
+
// Params are used to instantiate a new API instance. All fields are required
// unless otherwise noted.
type Params struct {
Logger *mlog.Logger
PowManager pow.Manager
- PostStore post.Store
- PostHTTPRenderer post.Renderer
+ PostStore post.Store
MailingList mailinglist.MailingList
@@ -190,7 +196,7 @@ func (a *api) handler() http.Handler {
mux.Handle("/api/", http.StripPrefix("/api", apiHandler))
- mux.Handle("/posts/", a.postHandler())
+ mux.Handle("/v2/posts/", a.postHandler())
return mux
}
diff --git a/srv/src/api/apiutils/apiutils.go b/srv/src/api/apiutil/apiutil.go
index 223c2b9..c9f8795 100644
--- a/srv/src/api/apiutils/apiutils.go
+++ b/srv/src/api/apiutil/apiutil.go
@@ -1,6 +1,6 @@
-// Package apiutils contains utilities which are useful for implementing api
+// Package apiutil contains utilities which are useful for implementing api
// endpoints.
-package apiutils
+package apiutil
import (
"context"
diff --git a/srv/src/api/chat.go b/srv/src/api/chat.go
index a1acc5a..f4b90ef 100644
--- a/srv/src/api/chat.go
+++ b/srv/src/api/chat.go
@@ -9,7 +9,7 @@ import (
"unicode"
"github.com/gorilla/websocket"
- "github.com/mediocregopher/blog.mediocregopher.com/srv/api/apiutils"
+ "github.com/mediocregopher/blog.mediocregopher.com/srv/api/apiutil"
"github.com/mediocregopher/blog.mediocregopher.com/srv/chat"
)
@@ -44,9 +44,9 @@ func newChatHandler(
func (c *chatHandler) historyHandler() http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
- limit, err := apiutils.StrToInt(r.PostFormValue("limit"), 0)
+ limit, err := apiutil.StrToInt(r.PostFormValue("limit"), 0)
if err != nil {
- apiutils.BadRequest(rw, r, fmt.Errorf("invalid limit parameter: %w", err))
+ apiutil.BadRequest(rw, r, fmt.Errorf("invalid limit parameter: %w", err))
return
}
@@ -58,13 +58,13 @@ func (c *chatHandler) historyHandler() http.Handler {
})
if argErr := (chat.ErrInvalidArg{}); errors.As(err, &argErr) {
- apiutils.BadRequest(rw, r, argErr.Err)
+ apiutil.BadRequest(rw, r, argErr.Err)
return
} else if err != nil {
- apiutils.InternalServerError(rw, r, err)
+ apiutil.InternalServerError(rw, r, err)
}
- apiutils.JSONResult(rw, r, struct {
+ apiutil.JSONResult(rw, r, struct {
Cursor string `json:"cursor"`
Messages []chat.Message `json:"messages"`
}{
@@ -107,11 +107,11 @@ func (c *chatHandler) userIDHandler() http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
userID, err := c.userID(r)
if err != nil {
- apiutils.BadRequest(rw, r, err)
+ apiutil.BadRequest(rw, r, err)
return
}
- apiutils.JSONResult(rw, r, struct {
+ apiutil.JSONResult(rw, r, struct {
UserID chat.UserID `json:"userID"`
}{
UserID: userID,
@@ -123,18 +123,18 @@ func (c *chatHandler) appendHandler() http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
userID, err := c.userID(r)
if err != nil {
- apiutils.BadRequest(rw, r, err)
+ apiutil.BadRequest(rw, r, err)
return
}
body := r.PostFormValue("body")
if l := len(body); l == 0 {
- apiutils.BadRequest(rw, r, errors.New("body is required"))
+ apiutil.BadRequest(rw, r, errors.New("body is required"))
return
} else if l > 300 {
- apiutils.BadRequest(rw, r, errors.New("body too long"))
+ apiutil.BadRequest(rw, r, errors.New("body too long"))
return
}
@@ -144,11 +144,11 @@ func (c *chatHandler) appendHandler() http.Handler {
})
if err != nil {
- apiutils.InternalServerError(rw, r, err)
+ apiutil.InternalServerError(rw, r, err)
return
}
- apiutils.JSONResult(rw, r, struct {
+ apiutil.JSONResult(rw, r, struct {
MessageID string `json:"messageID"`
}{
MessageID: msg.ID,
@@ -164,7 +164,7 @@ func (c *chatHandler) listenHandler() http.Handler {
conn, err := c.wsUpgrader.Upgrade(rw, r, nil)
if err != nil {
- apiutils.BadRequest(rw, r, err)
+ apiutil.BadRequest(rw, r, err)
return
}
defer conn.Close()
@@ -172,14 +172,14 @@ func (c *chatHandler) listenHandler() http.Handler {
it, err := c.room.Listen(ctx, sinceID)
if errors.As(err, new(chat.ErrInvalidArg)) {
- apiutils.BadRequest(rw, r, err)
+ apiutil.BadRequest(rw, r, err)
return
} else if errors.Is(err, context.Canceled) {
return
} else if err != nil {
- apiutils.InternalServerError(rw, r, err)
+ apiutil.InternalServerError(rw, r, err)
return
}
@@ -192,7 +192,7 @@ func (c *chatHandler) listenHandler() http.Handler {
return
} else if err != nil {
- apiutils.InternalServerError(rw, r, err)
+ apiutil.InternalServerError(rw, r, err)
return
}
@@ -203,7 +203,7 @@ func (c *chatHandler) listenHandler() http.Handler {
})
if err != nil {
- apiutils.GetRequestLogger(r).Error(ctx, "couldn't write message", err)
+ apiutil.GetRequestLogger(r).Error(ctx, "couldn't write message", err)
return
}
}
diff --git a/srv/src/api/csrf.go b/srv/src/api/csrf.go
index 13b6ec6..9717030 100644
--- a/srv/src/api/csrf.go
+++ b/srv/src/api/csrf.go
@@ -4,7 +4,7 @@ import (
"errors"
"net/http"
- "github.com/mediocregopher/blog.mediocregopher.com/srv/api/apiutils"
+ "github.com/mediocregopher/blog.mediocregopher.com/srv/api/apiutil"
)
const (
@@ -15,16 +15,16 @@ const (
func setCSRFMiddleware(h http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
- csrfTok, err := apiutils.GetCookie(r, csrfTokenCookieName, "")
+ csrfTok, err := apiutil.GetCookie(r, csrfTokenCookieName, "")
if err != nil {
- apiutils.InternalServerError(rw, r, err)
+ apiutil.InternalServerError(rw, r, err)
return
} else if csrfTok == "" {
http.SetCookie(rw, &http.Cookie{
Name: csrfTokenCookieName,
- Value: apiutils.RandStr(32),
+ Value: apiutil.RandStr(32),
Secure: true,
})
}
@@ -36,10 +36,10 @@ func setCSRFMiddleware(h http.Handler) http.Handler {
func checkCSRFMiddleware(h http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
- csrfTok, err := apiutils.GetCookie(r, csrfTokenCookieName, "")
+ csrfTok, err := apiutil.GetCookie(r, csrfTokenCookieName, "")
if err != nil {
- apiutils.InternalServerError(rw, r, err)
+ apiutil.InternalServerError(rw, r, err)
return
}
@@ -49,7 +49,7 @@ func checkCSRFMiddleware(h http.Handler) http.Handler {
}
if csrfTok == "" || givenCSRFTok != csrfTok {
- apiutils.BadRequest(rw, r, errors.New("invalid CSRF token"))
+ apiutil.BadRequest(rw, r, errors.New("invalid CSRF token"))
return
}
diff --git a/srv/src/api/mailinglist.go b/srv/src/api/mailinglist.go
index d89fe2a..c12e75d 100644
--- a/srv/src/api/mailinglist.go
+++ b/srv/src/api/mailinglist.go
@@ -5,7 +5,7 @@ import (
"net/http"
"strings"
- "github.com/mediocregopher/blog.mediocregopher.com/srv/api/apiutils"
+ "github.com/mediocregopher/blog.mediocregopher.com/srv/api/apiutil"
"github.com/mediocregopher/blog.mediocregopher.com/srv/mailinglist"
)
@@ -16,7 +16,7 @@ func (a *api) mailingListSubscribeHandler() http.Handler {
parts[0] == "" ||
parts[1] == "" ||
len(email) >= 512 {
- apiutils.BadRequest(rw, r, errors.New("invalid email"))
+ apiutil.BadRequest(rw, r, errors.New("invalid email"))
return
}
@@ -26,11 +26,11 @@ func (a *api) mailingListSubscribeHandler() http.Handler {
// just eat the error, make it look to the user like the
// verification email was sent.
} else if err != nil {
- apiutils.InternalServerError(rw, r, err)
+ apiutil.InternalServerError(rw, r, err)
return
}
- apiutils.JSONResult(rw, r, struct{}{})
+ apiutil.JSONResult(rw, r, struct{}{})
})
}
@@ -40,25 +40,25 @@ func (a *api) mailingListFinalizeHandler() http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
subToken := r.PostFormValue("subToken")
if l := len(subToken); l == 0 || l > 128 {
- apiutils.BadRequest(rw, r, errInvalidSubToken)
+ apiutil.BadRequest(rw, r, errInvalidSubToken)
return
}
err := a.params.MailingList.FinalizeSubscription(subToken)
if errors.Is(err, mailinglist.ErrNotFound) {
- apiutils.BadRequest(rw, r, errInvalidSubToken)
+ apiutil.BadRequest(rw, r, errInvalidSubToken)
return
} else if errors.Is(err, mailinglist.ErrAlreadyVerified) {
// no problem
} else if err != nil {
- apiutils.InternalServerError(rw, r, err)
+ apiutil.InternalServerError(rw, r, err)
return
}
- apiutils.JSONResult(rw, r, struct{}{})
+ apiutil.JSONResult(rw, r, struct{}{})
})
}
@@ -68,21 +68,21 @@ func (a *api) mailingListUnsubscribeHandler() http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
unsubToken := r.PostFormValue("unsubToken")
if l := len(unsubToken); l == 0 || l > 128 {
- apiutils.BadRequest(rw, r, errInvalidUnsubToken)
+ apiutil.BadRequest(rw, r, errInvalidUnsubToken)
return
}
err := a.params.MailingList.Unsubscribe(unsubToken)
if errors.Is(err, mailinglist.ErrNotFound) {
- apiutils.BadRequest(rw, r, errInvalidUnsubToken)
+ apiutil.BadRequest(rw, r, errInvalidUnsubToken)
return
} else if err != nil {
- apiutils.InternalServerError(rw, r, err)
+ apiutil.InternalServerError(rw, r, err)
return
}
- apiutils.JSONResult(rw, r, struct{}{})
+ apiutil.JSONResult(rw, r, struct{}{})
})
}
diff --git a/srv/src/api/middleware.go b/srv/src/api/middleware.go
index 6ea0d13..0b3eec7 100644
--- a/srv/src/api/middleware.go
+++ b/srv/src/api/middleware.go
@@ -5,7 +5,7 @@ import (
"net/http"
"time"
- "github.com/mediocregopher/blog.mediocregopher.com/srv/api/apiutils"
+ "github.com/mediocregopher/blog.mediocregopher.com/srv/api/apiutil"
"github.com/mediocregopher/mediocre-go-lib/v2/mctx"
"github.com/mediocregopher/mediocre-go-lib/v2/mlog"
)
@@ -61,7 +61,7 @@ func (lrw *logResponseWriter) WriteHeader(statusCode int) {
func logMiddleware(logger *mlog.Logger, h http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
- r = apiutils.SetRequestLogger(r, logger)
+ r = apiutil.SetRequestLogger(r, logger)
lrw := newLogResponseWriter(rw)
@@ -90,7 +90,7 @@ func postOnlyMiddleware(h http.Handler) http.Handler {
return
}
- apiutils.GetRequestLogger(r).WarnString(r.Context(), "method not allowed")
+ apiutil.GetRequestLogger(r).WarnString(r.Context(), "method not allowed")
rw.WriteHeader(405)
})
}
diff --git a/srv/src/api/posts.go b/srv/src/api/posts.go
index 995f2fb..cc7a176 100644
--- a/srv/src/api/posts.go
+++ b/srv/src/api/posts.go
@@ -3,11 +3,15 @@ package api
import (
"errors"
"fmt"
+ "html/template"
"net/http"
"path/filepath"
"strings"
- "github.com/mediocregopher/blog.mediocregopher.com/srv/api/apiutils"
+ "github.com/gomarkdown/markdown"
+ "github.com/gomarkdown/markdown/html"
+ "github.com/gomarkdown/markdown/parser"
+ "github.com/mediocregopher/blog.mediocregopher.com/srv/api/apiutil"
"github.com/mediocregopher/blog.mediocregopher.com/srv/post"
)
@@ -22,22 +26,63 @@ func (a *api) postHandler() http.Handler {
http.Error(rw, "Post not found", 404)
return
} else if err != nil {
- apiutils.InternalServerError(
+ apiutil.InternalServerError(
rw, r, fmt.Errorf("fetching post with id %q: %w", id, err),
)
return
}
- renderablePost, err := post.NewRenderablePost(a.params.PostStore, storedPost)
- if err != nil {
- apiutils.InternalServerError(
- rw, r, fmt.Errorf("constructing renderable post with id %q: %w", id, err),
- )
- return
+ parserExt := parser.CommonExtensions | parser.AutoHeadingIDs
+ parser := parser.NewWithExtensions(parserExt)
+
+ htmlFlags := html.CommonFlags | html.HrefTargetBlank
+ htmlRenderer := html.NewRenderer(html.RendererOptions{Flags: htmlFlags})
+
+ renderedBody := markdown.ToHTML([]byte(storedPost.Body), parser, htmlRenderer)
+
+ tplData := struct {
+ post.StoredPost
+ SeriesPrevious, SeriesNext *post.StoredPost
+ Body template.HTML
+ }{
+ StoredPost: storedPost,
+ Body: template.HTML(renderedBody),
+ }
+
+ if series := storedPost.Series; series != "" {
+
+ seriesPosts, err := a.params.PostStore.GetBySeries(series)
+ if err != nil {
+ apiutil.InternalServerError(
+ rw, r,
+ fmt.Errorf("fetching posts for series %q: %w", series, err),
+ )
+ return
+ }
+
+ var foundThis bool
+
+ for i := range seriesPosts {
+
+ seriesPost := seriesPosts[i]
+
+ if seriesPost.ID == storedPost.ID {
+ foundThis = true
+ continue
+ }
+
+ if !foundThis {
+ tplData.SeriesPrevious = &seriesPost
+ continue
+ }
+
+ tplData.SeriesNext = &seriesPost
+ break
+ }
}
- if err := a.params.PostHTTPRenderer.Render(rw, renderablePost); err != nil {
- apiutils.InternalServerError(
+ if err := tpls.ExecuteTemplate(rw, "post.html", tplData); err != nil {
+ apiutil.InternalServerError(
rw, r, fmt.Errorf("rendering post with id %q: %w", id, err),
)
return
diff --git a/srv/src/api/pow.go b/srv/src/api/pow.go
index 1b232b1..ae2d2f1 100644
--- a/srv/src/api/pow.go
+++ b/srv/src/api/pow.go
@@ -6,7 +6,7 @@ import (
"fmt"
"net/http"
- "github.com/mediocregopher/blog.mediocregopher.com/srv/api/apiutils"
+ "github.com/mediocregopher/blog.mediocregopher.com/srv/api/apiutil"
)
func (a *api) newPowChallengeHandler() http.Handler {
@@ -14,7 +14,7 @@ func (a *api) newPowChallengeHandler() http.Handler {
challenge := a.params.PowManager.NewChallenge()
- apiutils.JSONResult(rw, r, struct {
+ apiutil.JSONResult(rw, r, struct {
Seed string `json:"seed"`
Target uint32 `json:"target"`
}{
@@ -30,21 +30,21 @@ func (a *api) requirePowMiddleware(h http.Handler) http.Handler {
seedHex := r.FormValue("powSeed")
seed, err := hex.DecodeString(seedHex)
if err != nil || len(seed) == 0 {
- apiutils.BadRequest(rw, r, errors.New("invalid powSeed"))
+ apiutil.BadRequest(rw, r, errors.New("invalid powSeed"))
return
}
solutionHex := r.FormValue("powSolution")
solution, err := hex.DecodeString(solutionHex)
if err != nil || len(seed) == 0 {
- apiutils.BadRequest(rw, r, errors.New("invalid powSolution"))
+ apiutil.BadRequest(rw, r, errors.New("invalid powSolution"))
return
}
err = a.params.PowManager.CheckSolution(seed, solution)
if err != nil {
- apiutils.BadRequest(rw, r, fmt.Errorf("checking proof-of-work solution: %w", err))
+ apiutil.BadRequest(rw, r, fmt.Errorf("checking proof-of-work solution: %w", err))
return
}
diff --git a/srv/src/tpl/html/base.html b/srv/src/api/tpl/base.html
index bf81032..bf81032 100644
--- a/srv/src/tpl/html/base.html
+++ b/srv/src/api/tpl/base.html
diff --git a/srv/src/tpl/html/post.html b/srv/src/api/tpl/post.html
index 22a5b97..22a5b97 100644
--- a/srv/src/tpl/html/post.html
+++ b/srv/src/api/tpl/post.html
diff --git a/srv/src/cmd/mediocre-blog/main.go b/srv/src/cmd/mediocre-blog/main.go
index 28571a3..bdcd1b9 100644
--- a/srv/src/cmd/mediocre-blog/main.go
+++ b/srv/src/cmd/mediocre-blog/main.go
@@ -124,7 +124,6 @@ func main() {
apiParams.Logger = logger.WithNamespace("api")
apiParams.PowManager = powMgr
apiParams.PostStore = postStore
- apiParams.PostHTTPRenderer = post.NewMarkdownToHTMLRenderer()
apiParams.MailingList = ml
apiParams.GlobalRoom = chatGlobalRoom
apiParams.UserIDCalculator = chatUserIDCalc
diff --git a/srv/src/post/renderer.go b/srv/src/post/renderer.go
deleted file mode 100644
index 74acc25..0000000
--- a/srv/src/post/renderer.go
+++ /dev/null
@@ -1,96 +0,0 @@
-package post
-
-import (
- _ "embed"
- "fmt"
- "html/template"
- "io"
-
- "github.com/gomarkdown/markdown"
- "github.com/gomarkdown/markdown/html"
- "github.com/gomarkdown/markdown/parser"
- "github.com/mediocregopher/blog.mediocregopher.com/srv/tpl"
-)
-
-// RenderablePost is a Post wrapped with extra information necessary for
-// rendering.
-type RenderablePost struct {
- StoredPost
- SeriesPrevious, SeriesNext *StoredPost
-}
-
-// NewRenderablePost wraps an existing Post such that it can be rendered.
-func NewRenderablePost(store Store, post StoredPost) (RenderablePost, error) {
-
- renderablePost := RenderablePost{
- StoredPost: post,
- }
-
- if post.Series != "" {
-
- seriesPosts, err := store.GetBySeries(post.Series)
- if err != nil {
- return RenderablePost{}, fmt.Errorf(
- "fetching posts for series %q: %w",
- post.Series, err,
- )
- }
-
- var foundThis bool
-
- for i := range seriesPosts {
-
- seriesPost := seriesPosts[i]
-
- if seriesPost.ID == post.ID {
- foundThis = true
- continue
- }
-
- if !foundThis {
- renderablePost.SeriesPrevious = &seriesPost
- continue
- }
-
- renderablePost.SeriesNext = &seriesPost
- break
- }
- }
-
- return renderablePost, nil
-}
-
-// Renderer takes a Post and renders it to some encoding.
-type Renderer interface {
- Render(io.Writer, RenderablePost) error
-}
-
-func mdBodyToHTML(body []byte) []byte {
- parserExt := parser.CommonExtensions | parser.AutoHeadingIDs
- parser := parser.NewWithExtensions(parserExt)
-
- htmlFlags := html.CommonFlags | html.HrefTargetBlank
- htmlRenderer := html.NewRenderer(html.RendererOptions{Flags: htmlFlags})
-
- return markdown.ToHTML(body, parser, htmlRenderer)
-}
-
-type mdHTMLRenderer struct{}
-
-// NewMarkdownToHTMLRenderer renders Posts from markdown to HTML.
-func NewMarkdownToHTMLRenderer() Renderer {
- return mdHTMLRenderer{}
-}
-
-func (r mdHTMLRenderer) Render(into io.Writer, post RenderablePost) error {
-
- data := struct {
- RenderablePost
- Body template.HTML
- }{
- RenderablePost: post,
- Body: template.HTML(mdBodyToHTML([]byte(post.Body))),
- }
-
- return tpl.HTML.ExecuteTemplate(into, "post.html", data)
-}
diff --git a/srv/src/post/renderer_test.go b/srv/src/post/renderer_test.go
deleted file mode 100644
index 5c01cd2..0000000
--- a/srv/src/post/renderer_test.go
+++ /dev/null
@@ -1,92 +0,0 @@
-package post
-
-import (
- "bytes"
- "strconv"
- "strings"
- "testing"
- "time"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestMarkdownBodyToHTML(t *testing.T) {
-
- tests := []struct {
- body string
- exp string
- }{
- {
- body: `
-# Foo
-`,
- exp: `<h1 id="foo">Foo</h1>`,
- },
- {
- body: `
-this is a body
-
-this is another
-`,
- exp: `
-<p>this is a body</p>
-
-<p>this is another</p>`,
- },
- {
- body: `this is a [link](somewhere.html)`,
- exp: `<p>this is a <a href="somewhere.html" target="_blank">link</a></p>`,
- },
- }
-
- for i, test := range tests {
- t.Run(strconv.Itoa(i), func(t *testing.T) {
-
- outB := mdBodyToHTML([]byte(test.body))
- out := string(outB)
-
- // just to make the tests nicer
- out = strings.TrimSpace(out)
- test.exp = strings.TrimSpace(test.exp)
-
- assert.Equal(t, test.exp, out)
- })
- }
-}
-
-func TestMarkdownToHTMLRenderer(t *testing.T) {
-
- r := NewMarkdownToHTMLRenderer()
-
- post := RenderablePost{
- StoredPost: StoredPost{
- Post: Post{
- ID: "foo",
- Title: "Foo",
- Description: "Bar.",
- Body: "This is the body.",
- Series: "baz",
- },
- PublishedAt: time.Now(),
- },
-
- SeriesPrevious: &StoredPost{
- Post: Post{
- ID: "foo-prev",
- Title: "Foo Prev",
- },
- },
-
- SeriesNext: &StoredPost{
- Post: Post{
- ID: "foo-next",
- Title: "Foo Next",
- },
- },
- }
-
- buf := new(bytes.Buffer)
- err := r.Render(buf, post)
- assert.NoError(t, err)
- t.Log(buf.String())
-}
diff --git a/srv/src/tpl/tpl.go b/srv/src/tpl/tpl.go
deleted file mode 100644
index 1dd98ba..0000000
--- a/srv/src/tpl/tpl.go
+++ /dev/null
@@ -1,12 +0,0 @@
-// Package tpl contains template files which are used to render the blog.
-package tpl
-
-import (
- "embed"
- html_tpl "html/template"
-)
-
-//go:embed *
-var fs embed.FS
-
-var HTML = html_tpl.Must(html_tpl.ParseFS(fs, "html/*"))