server, post: add about images for social media
Signed-off-by: Naman Sood <mail@nsood.in>
This commit is contained in:
parent
4fd8925116
commit
4c39700474
36 changed files with 216 additions and 3 deletions
108
server.go
108
server.go
|
@ -1,12 +1,22 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"log"
|
||||
"math"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/aymerick/raymond"
|
||||
"github.com/fogleman/gg"
|
||||
)
|
||||
|
||||
const (
|
||||
blogTitle = "Prose"
|
||||
blogURL = "https://prose.nsood.in"
|
||||
blogSummary = "Where I infodump in Markdown and nobody can stop me."
|
||||
)
|
||||
|
||||
type server struct {
|
||||
|
@ -15,7 +25,8 @@ type server struct {
|
|||
mu sync.RWMutex
|
||||
templates map[string]*raymond.Template
|
||||
postList
|
||||
styles map[string]string
|
||||
styles map[string]string
|
||||
homeImage bytes.Buffer
|
||||
}
|
||||
|
||||
func newServer() (*server, error) {
|
||||
|
@ -23,6 +34,11 @@ func newServer() (*server, error) {
|
|||
staticHandler: http.FileServer(http.Dir("static/")),
|
||||
}
|
||||
|
||||
err := createImage(blogTitle, blogSummary, blogURL, &s.homeImage)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
posts, err := newPostList()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -92,11 +108,18 @@ func (s *server) router(res http.ResponseWriter, req *http.Request) {
|
|||
s.homePage(res, req)
|
||||
return
|
||||
}
|
||||
if slug == "about.png" {
|
||||
s.renderImage(res, req, &s.homeImage)
|
||||
return
|
||||
}
|
||||
|
||||
for _, p := range s.postList {
|
||||
if p.Slug == slug {
|
||||
if slug == p.Slug {
|
||||
s.postPage(p, res, req)
|
||||
return
|
||||
} else if slug == p.Slug+"/about.png" {
|
||||
s.renderImage(res, req, &p.Image)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -152,7 +175,7 @@ func (s *server) homePage(res http.ResponseWriter, req *http.Request) {
|
|||
posts = posts + summary
|
||||
}
|
||||
|
||||
page, err := s.createWebPage("Home", "Where I infodump in Markdown and nobody can stop me.", posts)
|
||||
page, err := s.createWebPage("Home", blogSummary, posts)
|
||||
|
||||
if err != nil {
|
||||
s.errorInRequest(res, req, err)
|
||||
|
@ -161,6 +184,14 @@ func (s *server) homePage(res http.ResponseWriter, req *http.Request) {
|
|||
res.Write([]byte(page))
|
||||
}
|
||||
|
||||
func (s *server) renderImage(res http.ResponseWriter, req *http.Request, img io.Reader) {
|
||||
res.Header().Add("content-type", "image/png")
|
||||
_, err := io.Copy(res, img)
|
||||
if err != nil {
|
||||
s.errorInRequest(res, req, err)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *server) loadStylesheet(res http.ResponseWriter, req *http.Request, filename string) (ok bool) {
|
||||
contents, ok := s.styles[filename]
|
||||
if !ok {
|
||||
|
@ -170,3 +201,74 @@ func (s *server) loadStylesheet(res http.ResponseWriter, req *http.Request, file
|
|||
res.Write([]byte(contents))
|
||||
return ok
|
||||
}
|
||||
|
||||
func createImage(title, summary, url string, out io.Writer) error {
|
||||
imgWidth, imgPaddingX, imgPaddingY := 800, 30, 60
|
||||
titleSize, summarySize, urlSize := 42.0, 28.0, 18.0
|
||||
lineHeight := 1.5
|
||||
textWidth := float64(imgWidth - 2*imgPaddingX)
|
||||
|
||||
// temporarily set height = 0 for context only used to generate
|
||||
// wrapped strings
|
||||
draw := gg.NewContext(imgWidth, 0)
|
||||
|
||||
titleFont, err := gg.LoadFontFace("fonts/Nunito-Bold.ttf", titleSize)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
summaryFont, err := gg.LoadFontFace("fonts/Nunito-LightItalic.ttf", summarySize)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
urlFont, err := gg.LoadFontFace("fonts/JetBrainsMono-ExtraLight.ttf", urlSize)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
draw.SetFontFace(titleFont)
|
||||
wrappedTitle := draw.WordWrap(title, textWidth)
|
||||
draw.SetFontFace(summaryFont)
|
||||
wrappedSummary := draw.WordWrap(summary, textWidth)
|
||||
|
||||
imgHeight := 2 * imgPaddingY
|
||||
for range wrappedTitle {
|
||||
imgHeight += int(math.Ceil(lineHeight * titleSize))
|
||||
}
|
||||
for range wrappedSummary {
|
||||
imgHeight += int(math.Ceil(lineHeight * summarySize))
|
||||
}
|
||||
imgHeight += int(math.Ceil(lineHeight * urlSize))
|
||||
|
||||
// actual context with actual height
|
||||
draw = gg.NewContext(imgWidth, imgHeight)
|
||||
draw.SetHexColor("#fff")
|
||||
draw.DrawRectangle(0, 0, float64(imgWidth), float64(imgHeight))
|
||||
draw.Fill()
|
||||
draw.SetHexColor("#3498db")
|
||||
accentHeight := 5.0
|
||||
draw.DrawRectangle(0, float64(imgHeight)-accentHeight, float64(imgWidth), accentHeight)
|
||||
draw.Fill()
|
||||
|
||||
offset := float64(imgPaddingY)
|
||||
|
||||
draw.SetFontFace(titleFont)
|
||||
draw.SetHexColor("#333")
|
||||
for _, line := range wrappedTitle {
|
||||
draw.DrawString(line, float64(imgPaddingX), offset)
|
||||
offset += lineHeight * titleSize
|
||||
}
|
||||
|
||||
draw.SetFontFace(summaryFont)
|
||||
draw.SetHexColor("#999")
|
||||
for _, line := range wrappedSummary {
|
||||
draw.DrawString(line, float64(imgPaddingX), offset)
|
||||
offset += lineHeight * summarySize
|
||||
}
|
||||
|
||||
draw.SetHexColor("#333")
|
||||
draw.SetFontFace(urlFont)
|
||||
urlY := float64(imgHeight - imgPaddingY)
|
||||
draw.DrawStringWrapped(url, float64(imgPaddingX), urlY, 0, 0, textWidth, lineHeight, gg.AlignRight)
|
||||
|
||||
return draw.EncodePNG(out)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue