about summary refs log tree commit diff stats
path: root/cmd/build/template.go
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/build/template.go')
-rw-r--r--cmd/build/template.go359
1 files changed, 0 insertions, 359 deletions
diff --git a/cmd/build/template.go b/cmd/build/template.go
deleted file mode 100644
index 84cf57c..0000000
--- a/cmd/build/template.go
+++ /dev/null
@@ -1,359 +0,0 @@
-package main
-
-import (
-	"encoding/xml"
-	"fmt"
-	"io"
-	"log/slog"
-	"net/url"
-	"os"
-	"strings"
-	"sync"
-	"time"
-	"website/internal/atom"
-	"website/internal/config"
-
-	"github.com/PuerkitoBio/goquery"
-	"github.com/a-h/htmlformat"
-	"github.com/antchfx/xmlquery"
-	"github.com/antchfx/xpath"
-	mapset "github.com/deckarep/golang-set/v2"
-	"golang.org/x/net/html"
-)
-
-var (
-	assetsOnce sync.Once
-	css        string
-	countHTML  *goquery.Document
-	templates  map[string]*os.File = make(map[string]*os.File)
-)
-
-func loadTemplate(path string) (file *os.File, err error) {
-	if templates[path] == nil {
-		file, err = os.OpenFile(path, os.O_RDONLY, 0)
-		if err != nil {
-			return nil, err
-		}
-		templates[path] = file
-	}
-	file = templates[path]
-	return
-}
-
-var (
-	imgOnce     sync.Once
-	img         *goquery.Selection
-	urlTemplate *url.URL
-)
-
-type QuerySelection struct {
-	*goquery.Selection
-}
-
-type QueryDocument struct {
-	*goquery.Document
-}
-
-func NewDocumentFromReader(r io.Reader) (*QueryDocument, error) {
-	doc, err := goquery.NewDocumentFromReader(r)
-	return &QueryDocument{doc}, err
-}
-
-func (q *QueryDocument) Find(selector string) *QuerySelection {
-	return &QuerySelection{q.Document.Find(selector)}
-}
-
-func NewDocumentNoScript(r io.Reader) (*goquery.Document, error) {
-	root, err := html.ParseWithOptions(r, html.ParseOptionEnableScripting(false))
-	return goquery.NewDocumentFromNode(root), err
-}
-
-func (root QuerySelection) setImgURL(pageURL string, pageTitle string) QuerySelection {
-	clone := countHTML.Clone()
-	imgOnce.Do(func() {
-		var err error
-		img = clone.Find("img")
-		attr, _ := img.Attr("src")
-		if attr == "" {
-			panic("<img> does not have src attribute")
-		}
-		urlTemplate, err = url.Parse(attr)
-		if err != nil {
-			panic(err.Error())
-		}
-	})
-	q := urlTemplate.Query()
-	urlTemplate.RawQuery = ""
-	q.Set("p", pageURL)
-	q.Set("t", pageTitle)
-	output := urlTemplate.String() + "?" + q.Encode()
-	clone.Find("img").SetAttr("src", output)
-	root.AppendSelection(clone.Find("body").Children())
-	return root
-}
-
-func layout(filename string, config config.Config, pageTitle string, pageURL string) (*goquery.Document, error) {
-	html, err := loadTemplate(filename)
-	if err != nil {
-		return nil, err
-	}
-	defer html.Seek(0, io.SeekStart)
-	assetsOnce.Do(func() {
-		var bytes []byte
-		bytes, err = os.ReadFile("templates/style.css")
-		if err != nil {
-			return
-		}
-		css = string(bytes)
-		countFile, err := os.OpenFile("templates/count.html", os.O_RDONLY, 0)
-		if err != nil {
-			return
-		}
-		defer countFile.Close()
-		countHTML, err = NewDocumentNoScript(countFile)
-	})
-	if err != nil {
-		return nil, err
-	}
-
-	doc, err := NewDocumentFromReader(html)
-	if err != nil {
-		return nil, err
-	}
-	doc.Find("html").SetAttr("lang", config.DefaultLanguage)
-	doc.Find("head > link[rel=alternate]").SetAttr("title", config.Title)
-	doc.Find("head > link[rel=canonical]").SetAttr("href", pageURL)
-	doc.Find(".title").SetText(config.Title)
-	doc.Find("title").Add(".p-name").SetText(pageTitle)
-	doc.Find("head > style").SetHtml(css)
-	doc.Find("body").setImgURL(pageURL, pageTitle)
-	nav := doc.Find("nav")
-	navLink := doc.Find("nav a")
-	nav.Empty()
-	for _, link := range config.Menus["main"] {
-		nav.AppendSelection(navLink.Clone().SetAttr("href", link.URL).SetText(link.Name))
-	}
-	return doc.Document, nil
-}
-
-func renderPost(post Post, config config.Config) (r io.Reader, err error) {
-	doc, err := layout("templates/post.html", config, post.PostMatter.Title, post.URL)
-	if err != nil {
-		return nil, err
-	}
-	doc.Find(".title").AddClass("p-author h-card").SetAttr("rel", "author")
-	doc.Find(".h-entry .dt-published").
-		SetAttr("datetime", post.PostMatter.Date.UTC().Format(time.RFC3339)).
-		SetText(
-			post.PostMatter.Date.Format("2006-01-02"),
-		)
-	doc.Find(".h-entry .e-content").SetHtml(post.Content)
-	categories := doc.Find(".h-entry .p-categories")
-	tpl := categories.Find(".p-category").ParentsUntilSelection(categories)
-	tpl.Remove()
-	for _, tag := range post.Taxonomies.Tags {
-		cat := tpl.Clone()
-		cat.Find(".p-category").SetAttr("href", fmt.Sprintf("/tags/%s/", tag)).SetText("#" + tag)
-		categories.AppendSelection(cat)
-	}
-
-	return renderHTML(doc), nil
-}
-
-func renderTags(tags Tags, config config.Config, url string) (io.Reader, error) {
-	doc, err := layout("templates/tags.html", config, config.Title, url)
-	if err != nil {
-		return nil, err
-	}
-	tagList := doc.Find(".tags")
-	tpl := doc.Find(".h-feed")
-	tpl.Remove()
-	for _, tag := range mapset.Sorted(tags) {
-		li := tpl.Clone()
-		li.Find("a").SetAttr("href", fmt.Sprintf("/tags/%s/", tag)).SetText("#" + tag)
-		tagList.AppendSelection(li)
-	}
-	return renderHTML(doc), nil
-}
-
-func renderListPage(tag string, config config.Config, posts []Post, url string) (io.Reader, error) {
-	var title string
-	if len(tag) > 0 {
-		title = tag
-	} else {
-		title = config.Title
-	}
-	doc, err := layout("templates/list.html", config, title, url)
-	if err != nil {
-		return nil, err
-	}
-	feed := doc.Find(".h-feed")
-	tpl := feed.Find(".h-entry")
-	tpl.Remove()
-
-	doc.Find(".title").AddClass("p-author h-card").SetAttr("rel", "author")
-	if tag == "" {
-		doc.Find(".filter").Remove()
-	} else {
-		doc.Find(".filter").Find("h3").SetText("#" + tag)
-	}
-
-	for _, post := range posts {
-		entry := tpl.Clone()
-		entry.Find(".p-name").SetText(post.Title).SetAttr("href", post.URL)
-		entry.Find(".dt-published").
-			SetAttr("datetime", post.PostMatter.Date.UTC().Format(time.RFC3339)).
-			SetText(post.PostMatter.Date.Format("2006-01-02"))
-		feed.AppendSelection(entry)
-	}
-
-	return renderHTML(doc), nil
-}
-
-func renderHomepage(config config.Config, posts []Post, url string) (io.Reader, error) {
-	_, index, err := getPost("content/_index.md")
-	if err != nil {
-		return nil, err
-	}
-	doc, err := layout("templates/homepage.html", config, config.Title, url)
-	if err != nil {
-		return nil, err
-	}
-	doc.Find("body").AddClass("h-card")
-	doc.Find(".title").AddClass("p-name u-url")
-
-	html, err := renderMarkdown(index)
-	doc.Find("#content").SetHtml(html)
-
-	feed := doc.Find(".h-feed")
-	tpl := feed.Find(".h-entry")
-	tpl.Remove()
-
-	for _, post := range posts[0:3] {
-		entry := tpl.Clone()
-		entry.Find(".p-name").SetText(post.Title)
-		entry.Find(".u-url").SetAttr("href", post.URL)
-		entry.
-			Find(".dt-published").
-			SetAttr("datetime", post.PostMatter.Date.UTC().Format(time.RFC3339)).
-			SetText(post.PostMatter.Date.Format("2006-01-02"))
-
-		feed.AppendSelection(entry)
-	}
-	doc.Find(".u-email").
-		SetAttr("href", fmt.Sprintf("mailto:%s", config.Email)).
-		SetText(config.Email)
-
-	elsewhere := doc.Find(".elsewhere")
-	linkRelMe := elsewhere.Find(".u-url[rel=me]").ParentsUntil("ul")
-	linkRelMe.Remove()
-
-	for _, link := range config.Menus["me"] {
-		el := linkRelMe.Clone()
-		el.Find("a").SetAttr("href", link.URL).SetText(link.Name)
-		elsewhere.AppendSelection(el)
-	}
-
-	return renderHTML(doc), nil
-}
-
-func render404(config config.Config, url string) (io.Reader, error) {
-	doc, err := layout("templates/404.html", config, "404 Not Found", url)
-	if err != nil {
-		return nil, err
-	}
-	return renderHTML(doc), nil
-}
-
-func renderFeed(title string, config config.Config, posts []Post, specific string) (io.Reader, error) {
-	reader, err := loadTemplate("templates/feed.xml")
-	if err != nil {
-		return nil, err
-	}
-	defer reader.Seek(0, io.SeekStart)
-	doc, err := xmlquery.Parse(reader)
-	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()
-	feed.SelectElement("updated").FirstChild.Data = string(datetime)
-	tpl := feed.SelectElement("entry")
-	xmlquery.RemoveFromTree(tpl)
-
-	for _, post := range posts {
-		fullURL, err := url.JoinPath(config.BaseURL.String(), post.URL)
-		if err != nil {
-			return nil, err
-		}
-		text, err := xml.MarshalIndent(&atom.FeedEntry{
-			Title:   post.Title,
-			Link:    atom.MakeLink(fullURL),
-			Id:      atom.MakeTagURI(config, post.Basename),
-			Updated: post.Date.UTC(),
-			Summary: post.Description,
-			Author:  config.Title,
-			Content: atom.FeedContent{
-				Content: post.Content,
-				Type:    "html",
-			},
-		}, "  ", "    ")
-		if err != nil {
-			return nil, err
-		}
-		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, err
-		}
-		xmlquery.AddChild(feed, entry.SelectElement("entry"))
-	}
-
-	return strings.NewReader(doc.OutputXML(true)), nil
-}
-
-func renderFeedStyles() (io.Reader, error) {
-	reader, err := loadTemplate("templates/feed-styles.xsl")
-	if err != nil {
-		return nil, err
-	}
-	defer reader.Seek(0, io.SeekStart)
-	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",
-	}
-	doc, err := xmlquery.Parse(reader)
-	expr, err := xpath.CompileWithNS("//xhtml:style", nsMap)
-	if err != nil {
-		return nil, err
-	}
-	style := xmlquery.QuerySelector(doc, expr)
-	xmlquery.AddChild(style, &xmlquery.Node{
-		Type: xmlquery.TextNode,
-		Data: string(css),
-	})
-	return strings.NewReader(doc.OutputXML(true)), nil
-}
-
-func renderHTML(doc *goquery.Document) io.Reader {
-	r, w := io.Pipe()
-
-	// TODO: return errors to main thread
-	go func() {
-		w.Write([]byte("<!doctype html>\n"))
-		err := htmlformat.Nodes(w, []*html.Node{doc.Children().Get(0)})
-		if err != nil {
-			slog.Error("error rendering html", "error", err)
-			w.CloseWithError(err)
-			return
-		}
-		defer w.Close()
-	}()
-	return r
-}