14 type Renderer interface {
15 RenderErrorPage(ctx context.Context, writer io.Writer, err error)
16 RenderHomePage(ctx context.Context, writer io.Writer) (err error)
17 RenderSigninPage(ctx context.Context, writer io.Writer) (err error)
18 RenderTimelinePage(ctx context.Context, writer io.Writer, data *TimelinePageTemplateData) (err error)
19 RenderThreadPage(ctx context.Context, writer io.Writer, data *ThreadPageTemplateData) (err error)
20 RenderNotificationPage(ctx context.Context, writer io.Writer, data *NotificationPageTemplateData) (err error)
21 RenderUserPage(ctx context.Context, writer io.Writer, data *UserPageTemplateData) (err error)
24 type renderer struct {
25 template *template.Template
28 func NewRenderer(templateGlobPattern string) (r *renderer, err error) {
29 t := template.New("default")
30 t, err = t.Funcs(template.FuncMap{
31 "EmojiFilter": EmojiFilter,
32 "StatusContentFilter": StatusContentFilter,
33 "DisplayInteractionCount": DisplayInteractionCount,
34 "TimeSince": TimeSince,
35 "FormatTimeRFC3339": FormatTimeRFC3339,
36 }).ParseGlob(templateGlobPattern)
45 func (r *renderer) RenderErrorPage(ctx context.Context, writer io.Writer, err error) {
46 r.template.ExecuteTemplate(writer, "error.tmpl", err)
50 func (r *renderer) RenderHomePage(ctx context.Context, writer io.Writer) (err error) {
51 return r.template.ExecuteTemplate(writer, "homepage.tmpl", nil)
54 func (r *renderer) RenderSigninPage(ctx context.Context, writer io.Writer) (err error) {
55 return r.template.ExecuteTemplate(writer, "signin.tmpl", nil)
58 func (r *renderer) RenderTimelinePage(ctx context.Context, writer io.Writer, data *TimelinePageTemplateData) (err error) {
59 return r.template.ExecuteTemplate(writer, "timeline.tmpl", data)
62 func (r *renderer) RenderThreadPage(ctx context.Context, writer io.Writer, data *ThreadPageTemplateData) (err error) {
63 return r.template.ExecuteTemplate(writer, "thread.tmpl", data)
66 func (r *renderer) RenderNotificationPage(ctx context.Context, writer io.Writer, data *NotificationPageTemplateData) (err error) {
67 return r.template.ExecuteTemplate(writer, "notification.tmpl", data)
70 func (r *renderer) RenderUserPage(ctx context.Context, writer io.Writer, data *UserPageTemplateData) (err error) {
71 return r.template.ExecuteTemplate(writer, "user.tmpl", data)
75 func EmojiFilter(content string, emojis []mastodon.Emoji) string {
76 var replacements []string
77 for _, e := range emojis {
78 replacements = append(replacements, ":"+e.ShortCode+":", "<img class=\"status-emoji\" src=\""+e.URL+"\" alt=\""+e.ShortCode+"\" />")
80 return strings.NewReplacer(replacements...).Replace(content)
83 func StatusContentFilter(content string, emojis []mastodon.Emoji, mentions []mastodon.Mention) string {
84 var replacements []string
85 for _, e := range emojis {
86 replacements = append(replacements, ":"+e.ShortCode+":", "<img class=\"status-emoji\" src=\""+e.URL+"\" alt=\""+e.ShortCode+"\" />")
88 for _, m := range mentions {
89 replacements = append(replacements, "\""+m.URL+"\"", "\"/user/"+m.ID+"\"")
91 return strings.NewReplacer(replacements...).Replace(content)
94 func DisplayInteractionCount(c int64) string {
96 return strconv.Itoa(int(c))
101 func TimeSince(t time.Time) string {
106 return strconv.Itoa(int(s)) + "s"
111 return strconv.Itoa(int(m)) + "m"
116 return strconv.Itoa(int(h)) + "h"
121 return strconv.Itoa(int(d)) + "d"
126 return strconv.Itoa(int(mo)) + "mo"
130 return strconv.Itoa(int(y)) + "y"
133 func FormatTimeRFC3339(t time.Time) string {
134 return t.Format(time.RFC3339)