1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
package handlers
import (
"bytes"
"fmt"
"html/template"
"strings"
"time"
"github.com/SayaAndy/saya-today-web/internal/b2"
"github.com/SayaAndy/saya-today-web/internal/frontmatter"
"github.com/SayaAndy/saya-today-web/internal/router"
"github.com/gofiber/fiber/v2"
"github.com/yuin/goldmark"
)
func init() {
router.Routes = append(router.Routes, &BlogPageHandler{})
}
type BlogPageHandler struct {
router.BasicHandler
}
func (r *BlogPageHandler) Filter() (method string, path string) {
return "GET", "/:lang/blog/:title"
}
func (r *BlogPageHandler) IsTemplated() bool {
return true
}
func (r *BlogPageHandler) TemplatesToInject() []string {
return []string{"views/pages/blog-page.html"}
}
func (r *BlogPageHandler) ToCache() router.CacheSetting {
return router.ByUrlOnly
}
func (r *BlogPageHandler) CacheDuration() time.Duration {
return 15 * time.Minute
}
func (r *BlogPageHandler) ToValidateLang() router.LangSetting {
return router.InPath
}
func (r *BlogPageHandler) RenderBody(c *fiber.Ctx, supplements *router.Supplements, lang string, templateMap fiber.Map) (statusCode int, err error) {
_, pathParts, _, err := router.GetPathFromReferer(c)
if err != nil {
return fiber.StatusBadRequest, fmt.Errorf("failed to get path from referer: %w", err)
}
metadata, parsedMarkdown, err := readBlogPost(supplements.MarkdownRenderer, supplements.B2Client, lang+"/"+pathParts[2])
if err != nil {
return fiber.StatusNotFound, fmt.Errorf("failed to find '%s' post: %w", pathParts[2], err)
}
geolocationParts := strings.Split(metadata.Geolocation, " ")
var x, y, areaError string
if len(geolocationParts) >= 2 {
x = geolocationParts[0]
y = geolocationParts[1]
}
if len(geolocationParts) >= 3 {
areaError = geolocationParts[2]
}
templateMap["MapLocationX"] = x
templateMap["MapLocationY"] = y
templateMap["MapLocationAreaMeters"] = areaError
templateMap["Title"] = metadata.Title
templateMap["ParsedMarkdown"] = template.HTML(parsedMarkdown)
templateMap["PublishedDate"] = metadata.PublishedTime.Format("2006-01-02 15:04:05 -07:00")
templateMap["ActionDate"] = metadata.ActionDate
templateMap["ShortDescription"] = metadata.ShortDescription
go supplements.ClientCache.View(c.IP(), pathParts[2])
return fiber.StatusOK, nil
}
func (r *BlogPageHandler) RenderHeader(c *fiber.Ctx, supplements *router.Supplements, lang string, templateMap fiber.Map) (statusCode int, err error) {
path, pathParts, _, err := router.GetPathFromReferer(c)
if err != nil {
return fiber.StatusBadRequest, fmt.Errorf("failed to get path from referer: %w", err)
}
metadata, _, err := supplements.B2Client.ReadFrontmatter(lang + "/" + pathParts[2] + ".md")
if err != nil {
return fiber.StatusNotFound, fmt.Errorf("could not read '%s' for metadata: %w", path, err)
}
templateMap["Title"] = metadata.Title
return fiber.StatusOK, nil
}
func readBlogPost(md goldmark.Markdown, b2Client *b2.B2Client, sourceName string) (metadata *frontmatter.Metadata, html string, err error) {
metadata, markdown, err := b2Client.ReadFrontmatter(sourceName + ".md")
if err != nil {
return nil, "", fmt.Errorf("failed to read a frontmatter file: %w", err)
}
var buf bytes.Buffer
if err := md.Convert(markdown, &buf); err != nil {
return nil, "", fmt.Errorf("convert source context from md to html: %w", err)
}
return metadata, buf.String(), nil
}
|