aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--LICENSE2
-rw-r--r--cmd/server/feed.go216
-rw-r--r--cmd/server/handlers.go13
-rw-r--r--cmd/server/main.go42
-rw-r--r--go.mod10
-rw-r--r--go.sum40
-rw-r--r--page/index.go3
-rw-r--r--page/page.go18
-rw-r--r--page/pagelist.go16
-rw-r--r--page/render.go2
-rw-r--r--page/time.go5
12 files changed, 299 insertions, 70 deletions
diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index d050e4c..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-*site*
-server
diff --git a/LICENSE b/LICENSE
index f92dbaa..b10b656 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright 2020 Mitchell Riedstra
+Copyright 2021 Mitchell Riedstra
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
diff --git a/cmd/server/feed.go b/cmd/server/feed.go
new file mode 100644
index 0000000..2d4a75b
--- /dev/null
+++ b/cmd/server/feed.go
@@ -0,0 +1,216 @@
+package main
+
+import (
+ "bytes"
+ "encoding/xml"
+ "errors"
+ "fmt"
+ "log"
+ "net/http"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/gorilla/mux"
+ "riedstra.dev/mitch/go-website/page"
+)
+
+type Author struct {
+ Name string `xml:"name"` // Required
+ Uri string `xml:"uri,omitempty"`
+ Email string `xml:"email,omitempty"`
+}
+
+type Link struct {
+ Href string `xml:"href,attr,omitempty"`
+ Rel string `xml:"rel,attr,omitempty"`
+ Type string `xml:"type,attr,omitempty"`
+ Title string `xml:"Title,attr,omitempty"`
+ Length string `xml:"Length,attr,omitempty"`
+}
+
+type Content struct {
+ Type string `xml:"type,attr"`
+ Data string `xml:",chardata"`
+}
+
+type Entry struct {
+ // Spec requires this, autogenerated from Title and updated if otherwise
+ // left empty
+ Id string `xml:"id"`
+
+ Title string `xml:"title"` // Required
+ Updated *time.Time `xml:"updated"` // Required
+ Author *Author `xml:"author,omitempty"`
+ Published *time.Time `xml:"published,omitempty"`
+ Links []Link `xml:"link,omitempty"`
+ Content *Content `xml:"content,omitempty"`
+}
+
+func (i Entry) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
+ type Alias Entry
+
+ errs := []string{}
+ if i.Title == "" {
+ errs = append(errs, "Title Cannot be empty")
+ }
+ if i.Updated == nil {
+ errs = append(errs, "Updated cannot be nil")
+ }
+
+ if len(errs) > 0 {
+ return errors.New(strings.Join(errs, ","))
+ }
+
+ if i.Id == "" {
+ i.Id = fmt.Sprintf("%s::%d", i.Title, i.Updated.Unix())
+ }
+
+ i2 := (*Alias)(&i)
+
+ return e.EncodeElement(i2, start)
+}
+
+type Atom struct {
+ Ns string `xml:"xmlns,attr"`
+ Title string `xml:"title"` // Required
+ Id string `xml:"id"` // Required
+ Author Author `xml:"author,omitempty"` // Required
+ Updated *time.Time `xml:"updated"` // Required
+ Published *time.Time `xml:"published,omitempty"`
+ Subtitle string `xml:"subtitle,omitempty"`
+ Entries []Entry `xml:"entry"`
+}
+
+func (a Atom) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
+ type Alias Atom
+
+ a.Ns = "http://www.w3.org/2005/Atom"
+ errs := []string{}
+ if a.Id == "" {
+ errs = append(errs, "ID Cannot be empty")
+ }
+ if a.Author.Name == "" {
+ errs = append(errs, "Author Name cannot be empty")
+ }
+ if a.Updated == nil {
+ errs = append(errs, "Updated cannot be empty")
+ }
+
+ if len(errs) > 0 {
+ return errors.New(strings.Join(errs, ","))
+ }
+
+ start.Name = xml.Name{Local: "feed"}
+
+ a2 := (*Alias)(&a)
+
+ return e.EncodeElement(a2, start)
+}
+
+// FeedHandler takes care of pulling from the index all of the relevant posts
+// and dumping them into an Atom feed.
+//
+// Relevant query parameters are:
+//
+// "content" if unset, or set to false content is omitted from the feed
+// "limit=n" stop at "n" and return the feed
+//
+func (a *App) FeedHandler(w http.ResponseWriter, r *http.Request) {
+ vars := mux.Vars(r)
+ var addContent bool
+ var limit int
+
+ if _, ok := r.URL.Query()["content"]; ok {
+ if r.URL.Query().Get("content") != "false" {
+ addContent = true
+ }
+ }
+
+ if l := r.URL.Query().Get("limit"); l != "" {
+ i, err := strconv.Atoi(l)
+ if err == nil {
+ limit = i
+ }
+ }
+
+ tag, ok := vars["tag"]
+ if !ok {
+ http.Error(w, "Tag not found or supplied", http.StatusNotFound)
+ return
+ }
+
+ p := page.NewPage("index")
+ index, err := p.Index()
+ if err != nil {
+ log.Println(err)
+ http.Error(w, "Internal server error", http.StatusInternalServerError)
+ return
+ }
+
+ pages, ok := index[tag]
+ if !ok {
+ http.Error(w, "Invalid tag", http.StatusNotFound)
+ return
+ }
+
+ pages, dateless := pages.RemoveDateless()
+ for _, p := range dateless {
+ log.Printf("Warning, page %s has no Date field. Skipping inclusion on feed", p)
+ }
+ pages.SortDate()
+
+ feed := &Atom{
+ Author: a.Author,
+ Title: a.Title,
+ Id: a.FeedId,
+ Updated: &a.Updated.Time,
+ Subtitle: a.Description,
+ }
+
+ entries := []Entry{}
+
+ for n, p := range pages {
+ if limit != 0 && n >= limit {
+ break
+ }
+
+ content := &bytes.Buffer{}
+ err := p.Render(content)
+ if err != nil {
+ log.Println(err)
+ http.Error(w, "Internal server error", http.StatusInternalServerError)
+ return
+ }
+
+ entry := Entry{
+ Title: p.Title,
+ Updated: &p.Date.Time,
+ Links: []Link{Link{Href: strings.Join([]string{a.SiteURL, p.Path()}, "/")}},
+ }
+
+ if addContent {
+ entry.Content = &Content{Type: "html", Data: content.String()}
+ }
+
+ entries = append(entries, entry)
+
+ }
+
+ feed.Entries = entries
+
+ w.Header().Add("Content-type", "application/xml")
+ w.Write([]byte(xml.Header))
+
+ enc := xml.NewEncoder(w)
+ enc.Indent("", " ")
+
+ err = enc.Encode(feed)
+ if err != nil {
+ log.Println(err)
+ // Headers probably already sent, but we'll try anyway
+ http.Error(w, "Internal server error", http.StatusInternalServerError)
+ }
+
+ return
+}
diff --git a/cmd/server/handlers.go b/cmd/server/handlers.go
index 60e0a35..5ea89cd 100644
--- a/cmd/server/handlers.go
+++ b/cmd/server/handlers.go
@@ -1,6 +1,7 @@
package main
import (
+ "fmt"
"net/http"
"path/filepath"
@@ -8,9 +9,20 @@ import (
"riedstra.dev/mitch/go-website/page"
)
+var FeedPrefixDefault = ".feeds"
+
type App struct {
ReIndexPath string
StaticDirectory string
+
+ // Related to the Atom feed
+ Title string
+ Description string // aka, "subtitle"
+ Author Author
+ SiteURL string
+ FeedId string
+ Updated page.PageTime
+ FeedPrefix string
}
func (a *App) PageHandler(w http.ResponseWriter, r *http.Request) {
@@ -48,6 +60,7 @@ func (a *App) ServeHTTP(w http.ResponseWriter, r *http.Request) {
rtr := mux.NewRouter()
rtr.HandleFunc(a.ReIndexPath, a.RebuildIndexHandler)
rtr.PathPrefix("/static/").Handler(a.StaticHandler())
+ rtr.PathPrefix(fmt.Sprintf("/%s/{tag}", a.FeedPrefix)).HandlerFunc(a.FeedHandler)
rtr.PathPrefix("/").HandlerFunc(a.PageHandler)
rtr.ServeHTTP(w, r)
}
diff --git a/cmd/server/main.go b/cmd/server/main.go
index 9ec96da..4b2c1ad 100644
--- a/cmd/server/main.go
+++ b/cmd/server/main.go
@@ -3,6 +3,7 @@ package main
import (
"flag"
"fmt"
+ "gopkg.in/yaml.v3"
"log"
"net/http"
"os"
@@ -18,13 +19,28 @@ func VersionPrint() {
os.Exit(0)
}
+func loadConf(fn string) (*App, error) {
+ fh, err := os.Open(fn)
+ if err != nil {
+ return nil, err
+ }
+ dec := yaml.NewDecoder(fh)
+
+ app := &App{}
+ err = dec.Decode(app)
+ return app, err
+}
+
func main() {
fl := flag.NewFlagSet("Website", flag.ExitOnError)
listen := fl.String("l", "0.0.0.0:8001", "Listening address")
directory := fl.String("d", ".", "Directory to serve.")
version := fl.Bool("v", false, "Print the version then exit")
- fl.StringVar(&page.TimeFormat, "T", page.TimeFormat, "Print the version then exit")
- indexPath := fl.String("i", "/reIndex",
+ confFn := fl.String("c", "conf.yml", "Location for the config file")
+ verbose := fl.Bool("V", false, "Be more verbose ( dump config, etc ) ")
+ fl.StringVar(&page.TimeFormat, "T", page.TimeFormat, "Set the page time format, be careful with this")
+ defaultIndexPath := "/reIndex"
+ indexPath := fl.String("i", defaultIndexPath,
"Path in which, when called will rebuild the index and clear the cache")
_ = fl.Parse(os.Args[1:])
@@ -36,9 +52,25 @@ func main() {
log.Fatal(err)
}
- app := &App{
- ReIndexPath: *indexPath,
- StaticDirectory: "static",
+ app, err := loadConf(*confFn)
+ if err != nil {
+ log.Println(err)
+ app = &App{}
+ }
+
+ if app.ReIndexPath == "" || *indexPath != defaultIndexPath {
+ app.ReIndexPath = *indexPath
+ }
+ if app.StaticDirectory == "" {
+ app.StaticDirectory = "static"
+ }
+ if app.FeedPrefix == "" {
+ app.FeedPrefix = FeedPrefixDefault
+ }
+
+ if *verbose {
+ b, _ := yaml.Marshal(app)
+ os.Stderr.Write(b)
}
srv := &http.Server{
diff --git a/go.mod b/go.mod
index efa317a..0843585 100644
--- a/go.mod
+++ b/go.mod
@@ -3,20 +3,10 @@ module riedstra.dev/mitch/go-website
go 1.13
require (
- github.com/flimzy/diff v0.1.7 // indirect
- github.com/flimzy/testy v0.1.17 // indirect
- github.com/go-kivik/couchdb v2.0.0+incompatible
- github.com/go-kivik/kivik v2.0.0+incompatible
- github.com/go-kivik/kiviktest v2.0.0+incompatible // indirect
- github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 // indirect
github.com/gorilla/mux v1.8.0
github.com/kr/pretty v0.1.0 // indirect
- github.com/pkg/errors v0.9.1 // indirect
github.com/russross/blackfriday v2.0.0+incompatible
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
- gitlab.com/flimzy/testy v0.3.0 // indirect
- golang.org/x/net v0.0.0-20200925080053-05aa5d4ee321 // indirect
- golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776
)
diff --git a/go.sum b/go.sum
index 72f0eb6..5d34e9c 100644
--- a/go.sum
+++ b/go.sum
@@ -1,17 +1,3 @@
-github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
-github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/flimzy/diff v0.1.7 h1:DRbd+lN3lY1xVuQrfqvDNsqBwA6RMbClMs6tS5sqWWk=
-github.com/flimzy/diff v0.1.7/go.mod h1:lFJtC7SPsK0EroDmGTSrdtWKAxOk3rO+q+e04LL05Hs=
-github.com/flimzy/testy v0.1.17 h1:Y+TUugY6s4B/vrOEPo6SUKafc41W5aiX3qUWvhAPMdI=
-github.com/flimzy/testy v0.1.17/go.mod h1:3szguN8NXqgq9bt9Gu8TQVj698PJWmyx/VY1frwwKrM=
-github.com/go-kivik/couchdb v2.0.0+incompatible h1:DsXVuGJTng04Guz8tg7jGVQ53RlByEhk+gPB/1yo3Oo=
-github.com/go-kivik/couchdb v2.0.0+incompatible/go.mod h1:5XJRkAMpBlEVA4q0ktIZjUPYBjoBmRoiWvwUBzP3BOQ=
-github.com/go-kivik/kivik v2.0.0+incompatible h1:/7hgr29DKv/vlaJsUoyRlOFq0K+3ikz0wTbu+cIs7QY=
-github.com/go-kivik/kivik v2.0.0+incompatible/go.mod h1:nIuJ8z4ikBrVUSk3Ua8NoDqYKULPNjuddjqRvlSUyyQ=
-github.com/go-kivik/kiviktest v2.0.0+incompatible h1:y1RyPHqWQr+eFlevD30Tr3ipiPCxK78vRoD3o9YysjI=
-github.com/go-kivik/kiviktest v2.0.0+incompatible/go.mod h1:JdhVyzixoYhoIDUt6hRf1yAfYyaDa5/u9SDOindDkfQ=
-github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 h1:l5lAOZEym3oK3SQ2HBHWsJUfbNBiTXJDeW2QDxw9AQ0=
-github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
@@ -19,36 +5,10 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
-github.com/otiai10/copy v1.0.2 h1:DDNipYy6RkIkjMwy+AWzgKiNTyj2RUI9yEMeETEpVyc=
-github.com/otiai10/copy v1.0.2/go.mod h1:c7RpqBkwMom4bYTSkLSym4VSJz/XtncWRAj/J4PEIMY=
-github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95 h1:+OLn68pqasWca0z5ryit9KGfp3sUsW4Lqg32iRMJyzs=
-github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
-github.com/otiai10/mint v1.3.0 h1:Ady6MKVezQwHBkGzLFbrsywyp09Ah7rkmfjV3Bcr5uc=
-github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo=
-github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
-github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
-github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday v2.0.0+incompatible h1:cBXrhZNUf9C+La9/YpS+UHpUT8YD6Td9ZMSU9APFcsk=
github.com/russross/blackfriday v2.0.0+incompatible/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
-gitlab.com/flimzy/testy v0.3.0 h1:HbY+NAJjXWxRqX8X4yZ0Blr5t6Yxc2n5RYREGVkwFDw=
-gitlab.com/flimzy/testy v0.3.0/go.mod h1:YObF4cq711ubd/3U0ydRQQVz7Cnq/ChgJpVwNr/AJac=
-golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20200925080053-05aa5d4ee321 h1:lleNcKRbcaC8MqgLwghIkzZ2JBQAb7QQ9MiwRt1BisA=
-golang.org/x/net v0.0.0-20200925080053-05aa5d4ee321/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
-golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
-golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
diff --git a/page/index.go b/page/index.go
index a453335..f9f2df5 100644
--- a/page/index.go
+++ b/page/index.go
@@ -1,7 +1,6 @@
package page
import (
- "fmt"
"os"
"path/filepath"
"strings"
@@ -49,7 +48,7 @@ func (p *Page) Index() (map[string]PageList, error) {
err = p2.Read()
if err != nil {
- fmt.Fprintln(os.Stderr, "Error encountered: ", err)
+ Logger.Println("Error encountered: ", err)
return err
}
diff --git a/page/page.go b/page/page.go
index 82f46f2..8b84099 100644
--- a/page/page.go
+++ b/page/page.go
@@ -25,6 +25,7 @@ package page
import (
"bufio"
"bytes"
+ "encoding/json"
"fmt"
"io"
"log"
@@ -45,6 +46,8 @@ type Page struct {
Title string
Head string
Description string
+ AuthorName string
+ AuthorEmail string
// Tags to apply to the page in question. Useful for Index()
Tags map[string]interface{}
Date *PageTime
@@ -58,10 +61,6 @@ type Page struct {
// .Global care must be taken when utilizing this functionality
var Global interface{}
-// CachePages determines whether or not the rendered page will be stored in
-// memory
-var CachePages = true
-
// CacheIndex determines whether or not the index will be cached in memory
// or rebuilt on each call
var CacheIndex = true
@@ -102,11 +101,6 @@ func (p *Page) Global() interface{} {
return Global
}
-// SetVars Will set to `nil` if provided
-func (p *Page) SetVars(vars map[string]interface{}) {
- p.Vars = vars
-}
-
// Renders a page
func (p *Page) Render(wr io.Writer) error {
if err := p.Read(); err != nil {
@@ -209,3 +203,9 @@ func (p *Page) RenderBody() (string, error) {
func (p Page) String() string {
return fmt.Sprintf("Page: %s", p.path)
}
+
+// StringDetail prints a detailed string of the page
+func (p Page) StringDetail() string {
+ b, _ := json.MarshalIndent(p, "", " ")
+ return fmt.Sprintf("Page: %s\n%s\n", p.path, b)
+}
diff --git a/page/pagelist.go b/page/pagelist.go
index a5cf844..f2140f9 100644
--- a/page/pagelist.go
+++ b/page/pagelist.go
@@ -8,6 +8,22 @@ import (
// by the date, or date reversed
type PageList []*Page
+// RemoveDateless returns two PageLists, the first with valid dates,
+// and the second without. This is useful if you need a PageList which
+// will run SortDate and SortDateReverse without issue
+func (p PageList) RemoveDateless() (PageList, PageList) {
+ with := PageList{}
+ without := PageList{}
+ for _, p := range p {
+ if p.Date != nil {
+ with = append(with, p)
+ } else {
+ without = append(without, p)
+ }
+ }
+ return with, without
+}
+
func (p PageList) SortDate() PageList {
sort.Slice(p, func(i, j int) bool {
return p[i].Time().After(p[j].Time())
diff --git a/page/render.go b/page/render.go
index 4378675..07b1b88 100644
--- a/page/render.go
+++ b/page/render.go
@@ -21,7 +21,7 @@ func Render(w http.ResponseWriter, r *http.Request,
p := NewPage(path)
if vars != nil {
- p.SetVars(vars)
+ p.Vars = vars
}
err := p.Render(w)
diff --git a/page/time.go b/page/time.go
index 958dc38..0374490 100644
--- a/page/time.go
+++ b/page/time.go
@@ -21,3 +21,8 @@ func (pt *PageTime) UnmarshalYAML(n *yaml.Node) error {
pt.Time = t
return nil
}
+
+func (pt PageTime) MarshalYAML() (interface{}, error) {
+ s := pt.Time.Format(TimeFormat)
+ return s, nil
+}