| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586 |
- package main
- import (
- "bytes"
- "embed"
- "html/template"
- "log"
- "net/http"
- "time"
- "github.com/yuin/goldmark"
- "github.com/yuin/goldmark/extension"
- "github.com/yuin/goldmark/parser"
- )
- var (
- //go:embed templates/*.html
- templateFS embed.FS
- //go:embed static
- staticFS embed.FS
- //go:embed about.md
- aboutMarkdown []byte
- )
- // newMarkdown returns a CommonMark renderer with GitHub-style extensions.
- // Raw HTML in posts is omitted (goldmark's default).
- func newMarkdown() goldmark.Markdown {
- return goldmark.New(
- goldmark.WithExtensions(extension.GFM),
- goldmark.WithParserOptions(parser.WithAutoHeadingID()),
- )
- }
- // pageData is passed to every template.
- type pageData struct {
- Site string
- Config siteConfig
- Posts []*Post
- Post *Post
- Newer, Older *Post
- Status int
- Message string
- // About page only.
- Version, Commit string
- About template.HTML
- }
- // loadTemplates parses each page template together with the shared layout.
- func loadTemplates() (map[string]*template.Template, error) {
- funcs := template.FuncMap{
- "date": func(t time.Time) string { return t.Format("2 January 2006") },
- "isodate": func(t time.Time) string { return t.Format(time.DateOnly) },
- }
- base, err := template.New("layout.html").Funcs(funcs).ParseFS(templateFS, "templates/layout.html")
- if err != nil {
- return nil, err
- }
- pages := map[string]*template.Template{}
- for _, name := range []string{"index", "post", "about", "error"} {
- t, err := base.Clone()
- if err != nil {
- return nil, err
- }
- if pages[name], err = t.ParseFS(templateFS, "templates/"+name+".html"); err != nil {
- return nil, err
- }
- }
- return pages, nil
- }
- // render executes a page into a buffer first so a template error becomes a
- // clean 500 instead of a half-written page.
- func (a *app) render(w http.ResponseWriter, status int, page string, data pageData) {
- data.Site = a.siteName
- data.Config = a.config.Get()
- var buf bytes.Buffer
- if err := a.pages[page].ExecuteTemplate(&buf, "layout.html", data); err != nil {
- log.Printf("render %s: %v", page, err)
- http.Error(w, "internal server error", http.StatusInternalServerError)
- return
- }
- w.Header().Set("Content-Type", "text/html; charset=utf-8")
- w.WriteHeader(status)
- buf.WriteTo(w)
- }
|