diff options
Diffstat (limited to 'internal/builder/template.go')
-rw-r--r-- | internal/builder/template.go | 108 |
1 files changed, 38 insertions, 70 deletions
diff --git a/internal/builder/template.go b/internal/builder/template.go index d46844d..9f019df 100644 --- a/internal/builder/template.go +++ b/internal/builder/template.go @@ -1,53 +1,41 @@ package builder import ( + "bytes" "encoding/xml" "io" "os" "path/filepath" "strings" "text/template" - "website/internal/atom" - "website/internal/config" - "website/internal/content" + + "go.alanpearce.eu/website/internal/atom" + "go.alanpearce.eu/website/internal/config" + "go.alanpearce.eu/website/internal/content" "github.com/PuerkitoBio/goquery" "github.com/antchfx/xmlquery" "github.com/antchfx/xpath" - "github.com/pkg/errors" + "gitlab.com/tozd/go/errors" ) var ( - css string - templateFiles = make(map[string]*os.File) - nsMap = map[string]string{ + css string + nsMap = map[string]string{ "xsl": "http://www.w3.org/1999/XSL/Transform", "atom": "http://www.w3.org/2005/Atom", "xhtml": "http://www.w3.org/1999/xhtml", } ) -func loadCSS() { - bytes, err := os.ReadFile("templates/style.css") +func loadCSS(source string) { + bytes, err := os.ReadFile(filepath.Join(source, "templates/style.css")) if err != nil { panic(err) } css = string(bytes) } -func loadTemplate(path string) (file *os.File, err error) { - if templateFiles[path] == nil { - file, err = os.OpenFile(path, os.O_RDONLY, 0) - if err != nil { - return nil, errors.Wrapf(err, "could not load template at path %s", path) - } - templateFiles[path] = file - } - file = templateFiles[path] - - return -} - type QuerySelection struct { *goquery.Selection } @@ -66,9 +54,9 @@ func (q *QueryDocument) Find(selector string) *QuerySelection { return &QuerySelection{q.Document.Find(selector)} } -func renderRobotsTXT(config *config.Config) (io.Reader, error) { +func renderRobotsTXT(source string, config *config.Config) (io.Reader, error) { r, w := io.Pipe() - tpl, err := template.ParseFiles("templates/robots.tmpl") + tpl, err := template.ParseFiles(filepath.Join(source, "templates/robots.tmpl")) if err != nil { return nil, err } @@ -90,38 +78,27 @@ func renderFeed( config *config.Config, posts []content.Post, specific string, -) (io.Reader, error) { - reader, err := loadTemplate("templates/feed.xml") +) (io.WriterTo, error) { + buf := &bytes.Buffer{} + datetime := posts[0].Date.UTC() + + buf.WriteString(xml.Header) + err := atom.LinkXSL(buf, "/feed-styles.xsl") if err != nil { return nil, err } - defer func() { - _, err := reader.Seek(0, io.SeekStart) - if err != nil { - panic("could not reset reader: " + err.Error()) - } - }() - doc, err := xmlquery.Parse(reader) - if err != nil { - return nil, errors.Wrap(err, "could not parse XML") - } - feed := doc.SelectElement("feed") - feed.SelectElement("title").FirstChild.Data = title - feed.SelectElement("link").SetAttr("href", config.BaseURL.String()) - feed.SelectElement("id").FirstChild.Data = atom.MakeTagURI(config, specific) - datetime, err := posts[0].Date.UTC().MarshalText() - if err != nil { - return nil, errors.Wrap(err, "could not convert post date to text") + feed := &atom.Feed{ + Title: title, + Link: atom.MakeLink(config.BaseURL.URL), + ID: atom.MakeTagURI(config, specific), + Updated: datetime, + Entries: make([]*atom.FeedEntry, len(posts)), } - feed.SelectElement("updated").FirstChild.Data = string(datetime) - tpl := feed.SelectElement("entry") - xmlquery.RemoveFromTree(tpl) - for _, post := range posts { - fullURL := config.BaseURL.JoinPath(post.URL).String() - text, err := xml.MarshalIndent(&atom.FeedEntry{ + for i, post := range posts { + feed.Entries[i] = &atom.FeedEntry{ Title: post.Title, - Link: atom.MakeLink(fullURL), + Link: atom.MakeLink(config.BaseURL.JoinPath(post.URL)), ID: atom.MakeTagURI(config, post.Basename), Updated: post.Date.UTC(), Summary: post.Description, @@ -130,31 +107,19 @@ func renderFeed( Content: post.Content, Type: "html", }, - }, " ", " ") - if err != nil { - return nil, errors.Wrap(err, "could not marshal xml") - } - entry, err := xmlquery.ParseWithOptions( - strings.NewReader(string(text)), - xmlquery.ParserOptions{ - Decoder: &xmlquery.DecoderOptions{ - Strict: false, - AutoClose: xml.HTMLAutoClose, - Entity: xml.HTMLEntity, - }, - }, - ) - if err != nil { - return nil, errors.Wrap(err, "could not parse XML") } - xmlquery.AddChild(feed, entry.SelectElement("entry")) + } + enc := xml.NewEncoder(buf) + err = enc.Encode(feed) + if err != nil { + return nil, err } - return strings.NewReader(doc.OutputXML(true)), nil + return buf, nil } -func renderFeedStyles() (*strings.Reader, error) { - tpl, err := template.ParseFiles("templates/feed-styles.xsl") +func renderFeedStyles(source string) (*strings.Reader, error) { + tpl, err := template.ParseFiles(filepath.Join(source, "templates/feed-styles.xsl")) if err != nil { return nil, err } @@ -169,6 +134,9 @@ func renderFeedStyles() (*strings.Reader, error) { err = tpl.Execute(w, map[string]interface{}{ "css": esc.String(), }) + if err != nil { + return nil, err + } return strings.NewReader(w.String()), nil } |