From 00f27f0cbe29cd720dd212c2e5fd9ea385e4b1b3 Mon Sep 17 00:00:00 2001 From: Naman Sood Date: Mon, 15 Mar 2021 19:20:25 -0400 Subject: [PATCH] markdown hotplugging Signed-off-by: Naman Sood --- page.go | 49 ++++++++++++++++++++++++++++++++++++++++- server.go | 45 +++++++++++++++++++++++++++++++++++-- templates/fullpost.html | 2 +- templates/summary.html | 2 +- 4 files changed, 93 insertions(+), 5 deletions(-) diff --git a/page.go b/page.go index 6fd634c..d155ca3 100644 --- a/page.go +++ b/page.go @@ -4,6 +4,7 @@ import ( "bytes" "fmt" "os" + "sort" "github.com/aymerick/raymond" "github.com/mitchellh/mapstructure" @@ -20,7 +21,7 @@ import ( type Metadata struct { Title string Summary string - Date string // TODO: better representation? time.Time might cause timezone issues... + Time int64 // unix timestamp } // Page stores the contents of a blog post. @@ -76,3 +77,49 @@ func newPage(slug string) (*Page, error) { func (p *Page) render(tpl *raymond.Template) (string, error) { return tpl.Exec(p) } + +func (p *Page) String() string { + return p.Slug +} + +type pages []*Page + +func insertOrUpdate(ps pages, p *Page) pages { + defer sort.Sort(ps) + for i, pg := range ps { + if pg.Slug == p.Slug { + ps[i] = p + return ps + } + } + ps = append(ps, p) + return ps +} + +func remove(ps pages, slug string) pages { + for i, pg := range ps { + if pg.Slug == slug { + ps = append(ps[:i], ps[i+1:]...) + break + } + } + fmt.Println(ps) + return ps +} + +// Len implements sort.Interface +func (ps pages) Len() int { + return len(ps) +} + +// Less implements sort.Interface +func (ps pages) Less(i, j int) bool { + return ps[i].Metadata.Time > ps[j].Metadata.Time +} + +// Swap implements sort.Interface +func (ps pages) Swap(i, j int) { + temp := ps[i] + ps[i] = ps[j] + ps[j] = temp +} diff --git a/server.go b/server.go index cc23424..133e2b9 100644 --- a/server.go +++ b/server.go @@ -7,8 +7,11 @@ import ( "net/http" "os" "runtime" + "sort" + "strconv" "strings" "sync" + "time" "github.com/aymerick/raymond" "github.com/rjeczalik/notify" @@ -16,11 +19,13 @@ import ( ) type server struct { - pages []*Page staticHandler http.Handler tplMutex sync.RWMutex templates map[string]*raymond.Template + + pgMutex sync.RWMutex + pages } func newServer() (*server, error) { @@ -43,6 +48,27 @@ func newServer() (*server, error) { return nil, err } + pagesLn := &listener{ + folder: "posts/", + update: func(file string) error { + s.pgMutex.Lock() + defer s.pgMutex.Unlock() + page, err := newPage(strings.TrimSuffix(file, ".md")) + if err != nil { + return err + } + s.pages = insertOrUpdate(s.pages, page) + return nil + }, + clean: func(file string) error { + s.pgMutex.Lock() + defer s.pgMutex.Unlock() + s.pages = remove(s.pages, strings.TrimSuffix(file, ".md")) + return nil + }, + } + go pagesLn.listen() + templatesLn := &listener{ folder: "templates/", update: func(file string) error { @@ -99,7 +125,9 @@ func (s *server) refreshPages() error { return err } - s.pages = make([]*Page, 0, len(files)) + s.pgMutex.Lock() + defer s.pgMutex.Unlock() + s.pages = make(pages, 0, len(files)) for _, f := range files { filename := f.Name() @@ -112,6 +140,7 @@ func (s *server) refreshPages() error { log.Printf("Loaded page %s", filename) } } + sort.Sort(s.pages) return nil } @@ -121,6 +150,14 @@ func loadTemplate(file string) (*raymond.Template, error) { if err != nil { return nil, fmt.Errorf("Could not parse %s template: %w", file, err) } + tpl.RegisterHelper("datetime", func(timeStr string) string { + timestamp, err := strconv.ParseInt(timeStr, 10, 64) + if err != nil { + log.Printf("Could not parse timestamp '%v', falling back to current time", timeStr) + timestamp = time.Now().Unix() + } + return time.Unix(timestamp, 0).Format("Jan 2 2006, 3:04 PM") + }) log.Printf("Loaded template: %s", file) return tpl, nil } @@ -303,6 +340,8 @@ func (s *server) router(res http.ResponseWriter, req *http.Request) { return } + s.pgMutex.RLock() + defer s.pgMutex.RUnlock() for _, p := range s.pages { if p.Slug == slug { s.renderPage(p, res, req) @@ -345,6 +384,8 @@ func (s *server) homePage(res http.ResponseWriter, req *http.Request) { var posts string + s.pgMutex.RLock() + defer s.pgMutex.RUnlock() for _, p := range s.pages { summary, err := p.render(s.templates["summary"]) if err != nil { diff --git a/templates/fullpost.html b/templates/fullpost.html index ec14f9f..6605caa 100644 --- a/templates/fullpost.html +++ b/templates/fullpost.html @@ -1,5 +1,5 @@
- {{metadata.date}} + {{datetime metadata.time}}

{{metadata.title}}

{{metadata.summary}}

diff --git a/templates/summary.html b/templates/summary.html index 9bd0031..f7e3518 100644 --- a/templates/summary.html +++ b/templates/summary.html @@ -1,5 +1,5 @@
- {{metadata.date}} + {{datetime metadata.time}}

{{metadata.title}}

{{metadata.summary}}

Read more →