- commit
- 160f932
- parent
- e52ab6f
- author
- Eric Bower
- date
- 2022-08-28 04:24:17 +0000 UTC
feat(prose): support for og images on blog and posts
5 files changed,
+73,
-17
+31,
-12
1@@ -66,17 +66,19 @@ type PostPageData struct {
2 PageTitle string
3 URL template.URL
4 BlogURL template.URL
5+ BlogName string
6 Slug string
7 Title string
8 Description string
9 Username string
10- BlogName string
11 Contents template.HTML
12 PublishAtISO string
13 PublishAt string
14 HasCSS bool
15 CssURL template.URL
16 Tags []string
17+ Image template.URL
18+ ImageCard string
19 }
20
21 type TransparencyPageData struct {
22@@ -85,11 +87,13 @@ type TransparencyPageData struct {
23 }
24
25 type HeaderTxt struct {
26- Title string
27- Bio string
28- Nav []shared.Link
29- HasLinks bool
30- Layout string
31+ Title string
32+ Bio string
33+ Nav []shared.Link
34+ HasLinks bool
35+ Layout string
36+ Image template.URL
37+ ImageCard string
38 }
39
40 type ReadmeTxt struct {
41@@ -190,9 +194,10 @@ func blogHandler(w http.ResponseWriter, r *http.Request) {
42 }
43
44 headerTxt := &HeaderTxt{
45- Title: GetBlogName(username),
46- Bio: "",
47- Layout: "default",
48+ Title: GetBlogName(username),
49+ Bio: "",
50+ Layout: "default",
51+ ImageCard: "summary",
52 }
53 readmeTxt := &ReadmeTxt{}
54
55@@ -203,12 +208,12 @@ func blogHandler(w http.ResponseWriter, r *http.Request) {
56 logger.Error(err)
57 }
58 headerTxt.Bio = parsedText.Description
59+ headerTxt.Layout = parsedText.Layout
60+ headerTxt.Image = template.URL(parsedText.Image)
61+ headerTxt.ImageCard = parsedText.ImageCard
62 if parsedText.Title != "" {
63 headerTxt.Title = parsedText.Title
64 }
65- if parsedText.Layout != "" {
66- headerTxt.Layout = parsedText.Layout
67- }
68
69 headerTxt.Nav = []shared.Link{}
70 for _, nav := range parsedText.Nav {
71@@ -342,6 +347,8 @@ func postHandler(w http.ResponseWriter, r *http.Request) {
72 onSubdomain := cfg.IsSubdomains() && strings.Contains(hostDomain, appDomain)
73 withUserName := (!onSubdomain && hostDomain == appDomain) || !cfg.IsCustomdomains()
74
75+ ogImage := ""
76+ ogImageCard := ""
77 hasCSS := false
78 var data PostPageData
79 post, err := dbpool.FindPostWithSlug(slug, user.ID, cfg.Space)
80@@ -361,6 +368,16 @@ func postHandler(w http.ResponseWriter, r *http.Request) {
81 if readmeParsed.MetaData.Title != "" {
82 blogName = readmeParsed.MetaData.Title
83 }
84+ ogImage = readmeParsed.Image
85+ ogImageCard = readmeParsed.ImageCard
86+ }
87+
88+ if parsedText.Image != "" {
89+ ogImage = parsedText.Image
90+ }
91+
92+ if parsedText.ImageCard != "" {
93+ ogImageCard = parsedText.ImageCard
94 }
95
96 // we need the blog name from the readme unfortunately
97@@ -395,6 +412,8 @@ func postHandler(w http.ResponseWriter, r *http.Request) {
98 HasCSS: hasCSS,
99 CssURL: template.URL(cfg.CssURL(username)),
100 Tags: parsedText.Tags,
101+ Image: template.URL(ogImage),
102+ ImageCard: ogImageCard,
103 }
104 } else {
105 data = PostPageData{
+14,
-2
1@@ -10,17 +10,29 @@
2 <meta property="og:url" content="{{.URL}}">
3 <meta property="og:title" content="{{.Header.Title}}">
4 {{if .Header.Bio}}<meta property="og:description" content="{{.Header.Bio}}">{{end}}
5+
6+{{if .Header.Image}}
7+<meta itemprop="image" content="{{.Header.Image}}" />
8+<meta property="og:image" content="{{.Header.Image}}" />
9+
10+<meta name="twitter:image" content="{{.Header.Image}}" />
11+{{else}}
12 <meta property="og:image:width" content="300" />
13 <meta property="og:image:height" content="300" />
14 <meta itemprop="image" content="https://{{.Site.Domain}}/card.png" />
15 <meta property="og:image" content="https://{{.Site.Domain}}/card.png" />
16
17+<meta name="twitter:image" content="https://{{.Site.Domain}}/card.png" />
18+{{end}}
19+
20+{{if .Header.ImageCard}}
21+<meta property="twitter:card" content="{{.Header.ImageCard}}">
22+{{else}}
23 <meta property="twitter:card" content="summary">
24+{{end}}
25 <meta property="twitter:url" content="{{.URL}}">
26 <meta property="twitter:title" content="{{.Header.Title}}">
27 {{if .Header.Bio}}<meta property="twitter:description" content="{{.Header.Bio}}">{{end}}
28-<meta name="twitter:image" content="https://{{.Site.Domain}}/card.png" />
29-<meta name="twitter:image:src" content="https://{{.Site.Domain}}/card.png" />
30
31 <link rel="stylesheet" href="/syntax.css" />
32 {{if .HasCSS}}<link rel="stylesheet" href="{{.CssURL}}" />{{end}}
+5,
-1
1@@ -100,8 +100,10 @@ date: 2022-06-28
2 <ul>
3 <li>title (custom title not dependent on filename)</li>
4 <li>description (what is the purpose of this post? It's also added to meta tag)</li>
5- <li>date (format must be YYYY-MM-DD, if set in future post wil be unlisted)</li>
6+ <li>date (suggested format YYYY-MM-DD, if set in future post wil be unlisted)</li>
7 <li>tags (<code>[feature, announcement]</code>)</li>
8+ <li>image (og image)</li>
9+ <li>card (og image twitter card: summary, summary_large_image, etc.)</li>
10 </ul>
11 </p>
12 </section>
13@@ -182,6 +184,8 @@ This will show up on the blog landing page.
14 <li>title (name of the blog, default: "X's blog")</li>
15 <li>description (description of blog)</li>
16 <li>nav (key=value pair that corresponds to text=href in html)</li>
17+ <li>image (og image)</li>
18+ <li>card (og image twitter card: summary, summary_large_image, etc.)</li>
19 </ul>
20 </p>
21 </section>
+14,
-2
1@@ -10,17 +10,29 @@
2 <meta property="og:url" content="{{.URL}}">
3 <meta property="og:title" content="{{.Title}}">
4 {{if .Description}}<meta property="og:description" content="{{.Description}}">{{end}}
5+
6+{{if .Image}}
7+<meta itemprop="image" content="{{.Image}}" />
8+<meta property="og:image" content="{{.Image}}" />
9+
10+<meta name="twitter:image" content="{{.Image}}" />
11+{{else}}
12 <meta property="og:image:width" content="300" />
13 <meta property="og:image:height" content="300" />
14 <meta itemprop="image" content="https://{{.Site.Domain}}/card.png" />
15 <meta property="og:image" content="https://{{.Site.Domain}}/card.png" />
16
17+<meta name="twitter:image" content="https://{{.Site.Domain}}/card.png" />
18+{{end}}
19+
20+{{if .ImageCard}}
21+<meta property="twitter:card" content="{{.ImageCard}}">
22+{{else}}
23 <meta property="twitter:card" content="summary">
24+{{end}}
25 <meta property="twitter:url" content="{{.URL}}">
26 <meta property="twitter:title" content="{{.Title}}">
27 {{if .Description}}<meta property="twitter:description" content="{{.Description}}">{{end}}
28-<meta name="twitter:image" content="https://{{.Site.Domain}}/card.png" />
29-<meta name="twitter:image:src" content="https://{{.Site.Domain}}/card.png" />
30
31 <link rel="stylesheet" href="/syntax.css" />
32 {{if .HasCSS}}<link rel="stylesheet" href="{{.CssURL}}" />{{end}}
1@@ -32,6 +32,8 @@ type MetaData struct {
2 Nav []Link
3 Tags []string
4 Layout string
5+ Image string
6+ ImageCard string
7 }
8
9 type ParsedText struct {
10@@ -210,6 +212,13 @@ func ParseText(text string, absURL string) (*ParsedText, error) {
11 parsed.MetaData.Title = toString(metaData["title"])
12 parsed.MetaData.Description = toString(metaData["description"])
13 parsed.MetaData.Layout = toString(metaData["layout"])
14+ parsed.MetaData.Image = toString(metaData["image"])
15+ if strings.HasPrefix(parsed.Image, "/") {
16+ parsed.MetaData.Image = fmt.Sprintf("%s%s", absURL, parsed.Image)
17+ } else if strings.HasPrefix(parsed.Image, "./") {
18+ parsed.MetaData.Image = fmt.Sprintf("%s%s", absURL, parsed.Image[1:])
19+ }
20+ parsed.MetaData.ImageCard = toString(metaData["card"])
21
22 var publishAt *time.Time = nil
23 var err error