package template
import (
"bytes"
"encoding/xml"
"io"
"text/template"
"github.com/PuerkitoBio/goquery"
"github.com/Southclaws/fault"
"github.com/Southclaws/fault/fmsg"
"github.com/antchfx/xmlquery"
"github.com/antchfx/xpath"
"alin.ovh/homestead/domain/content"
"alin.ovh/homestead/domain/indieweb/atom"
"alin.ovh/homestead/domain/web/templates"
"alin.ovh/homestead/shared/config"
)
var 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 RenderRobotsTXT(baseURL config.URL, w io.Writer) error {
tpl, err := template.ParseFS(templates.Files, "robots.tmpl")
if err != nil {
return fault.Wrap(err)
}
err = tpl.Execute(w, map[string]any{
"BaseURL": baseURL,
})
if err != nil {
return fault.Wrap(err)
}
return nil
}
func RenderFeed(
title string,
config *config.Config,
posts []*content.Post,
specific string,
) (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
}
feed := &atom.Feed{
Title: title,
Link: atom.MakeLink(config.BaseURL.URL),
ID: atom.MakeTagURI(config, specific),
Updated: datetime,
Entries: make([]*atom.FeedEntry, len(posts)),
}
for i, post := range posts {
html, err := post.RenderString()
if err != nil {
return nil, fault.Wrap(err, fmsg.With("could not render post"))
}
feed.Entries[i] = &atom.FeedEntry{
Title: post.Title,
Link: atom.MakeLink(config.BaseURL.JoinPath(post.URL)),
ID: atom.MakeTagURI(config, post.Basename),
Updated: post.Date.UTC(),
Summary: post.Description,
Author: config.Title,
Content: atom.FeedContent{
Content: html,
Type: "html",
},
}
}
enc := xml.NewEncoder(buf)
if err := enc.Encode(feed); err != nil {
return nil, fault.Wrap(err)
}
return buf, nil
}
func CopyFile(filename string, w io.Writer) error {
f, err := templates.Files.Open(filename)
if err != nil {
return fault.Wrap(err)
}
defer f.Close()
if _, err := io.Copy(w, f); err != nil {
return fault.Wrap(err)
}
return nil
}
func GetFeedStyleHash(r io.Reader) (string, error) {
doc, err := xmlquery.Parse(r)
if err != nil {
return "", fault.Wrap(err)
}
expr, err := xpath.CompileWithNS("//xhtml:style", nsMap)
if err != nil {
return "", fault.Wrap(err, fmsg.With("could not parse XPath"))
}
style := xmlquery.QuerySelector(doc, expr)
return Hash(style.InnerText()), nil
}
func GetHTMLStyleHash(r io.Reader) (string, error) {
doc, err := goquery.NewDocumentFromReader(r)
if err != nil {
return "", fault.Wrap(err)
}
html := doc.Find("head > style").Text()
return Hash(html), nil
}
domain/content/builder/template/template.go (view raw)