about summary refs log tree commit diff stats
path: root/internal/server
diff options
context:
space:
mode:
authorAlan Pearce2024-06-21 13:02:08 +0200
committerAlan Pearce2024-06-21 15:33:38 +0200
commitfc5fd2edd9b8282497e33a18300eab694d8a89c6 (patch)
tree18af097c037ef781cc8f6148d7c1ba37e10877c1 /internal/server
parentcac323d9ae70f55a43fd99b73e60cf614be11797 (diff)
downloadsearchix-fc5fd2edd9b8282497e33a18300eab694d8a89c6.tar.lz
searchix-fc5fd2edd9b8282497e33a18300eab694d8a89c6.tar.zst
searchix-fc5fd2edd9b8282497e33a18300eab694d8a89c6.zip
refactor: switch to templ for HTML templates
Diffstat (limited to 'internal/server')
-rw-r--r--internal/server/error.go10
-rw-r--r--internal/server/mux.go93
-rw-r--r--internal/server/templates.go25
3 files changed, 46 insertions, 82 deletions
diff --git a/internal/server/error.go b/internal/server/error.go
index e700d3b..4a8acbc 100644
--- a/internal/server/error.go
+++ b/internal/server/error.go
@@ -3,6 +3,8 @@ package server
 import (
 	"log/slog"
 	"net/http"
+
+	"searchix/internal/components"
 	"searchix/internal/config"
 )
 
@@ -14,9 +16,9 @@ func createErrorHandler(
 		if message == "" {
 			message = http.StatusText(code)
 		}
-		indexData := TemplateData{
+		indexData := components.TemplateData{
 			ExtraHeadHTML: config.Web.ExtraHeadHTML,
-			Sources:       config.Importer.Sources,
+			Sources:       sources,
 			Code:          code,
 			Message:       message,
 		}
@@ -24,9 +26,9 @@ func createErrorHandler(
 		w.Header().Del("Vary")
 		w.WriteHeader(code)
 		if r.Header.Get("Fetch") == "true" {
-			err = templates["error"].ExecuteTemplate(w, "main", indexData)
+			err = components.Error(indexData).Render(r.Context(), w)
 		} else {
-			err = templates["error"].Execute(w, indexData)
+			err = components.ErrorPage(indexData).Render(r.Context(), w)
 		}
 		if err != nil {
 			slog.Error(
diff --git a/internal/server/mux.go b/internal/server/mux.go
index 79e24cd..89ce952 100644
--- a/internal/server/mux.go
+++ b/internal/server/mux.go
@@ -3,7 +3,6 @@ package server
 import (
 	"context"
 	"fmt"
-	"html/template"
 	"io"
 	"log"
 	"log/slog"
@@ -16,11 +15,10 @@ import (
 	"time"
 
 	"searchix/frontend"
+	"searchix/internal/components"
 	"searchix/internal/config"
 	search "searchix/internal/index"
-	"searchix/internal/nix"
 
-	"github.com/blevesearch/bleve/v2"
 	sentryhttp "github.com/getsentry/sentry-go/http"
 	"github.com/osdevisnot/sorvor/pkg/livereload"
 	"github.com/pkg/errors"
@@ -33,36 +31,10 @@ type HTTPError struct {
 	Code    int
 }
 
-const jsSnippet = template.HTML(livereload.JsSnippet) // #nosec G203
-
-type TemplateData struct {
-	Sources       map[string]*config.Source
-	Source        config.Source
-	Query         string
-	Results       bool
-	SourceResult  *bleve.SearchResult
-	ExtraHeadHTML template.HTML
-	Code          int
-	Message       string
-	Assets        *frontend.AssetCollection
-}
-
-type ResultData struct {
-	TemplateData
-	Query          string
-	ResultsPerPage int
-	Results        *search.Result
-	Prev           string
-	Next           string
-}
-
-type DocumentData struct {
-	TemplateData
-	Document *nix.Importable
-	Children *search.Result
-}
-
-var templates TemplateCollection
+var (
+	templates TemplateCollection
+	sources   []*config.Source
+)
 
 func applyDevModeOverrides(cfg *config.Config) {
 	if len(cfg.Web.ContentSecurityPolicy.ScriptSrc) == 0 {
@@ -70,10 +42,18 @@ func applyDevModeOverrides(cfg *config.Config) {
 	}
 	cfg.Web.ContentSecurityPolicy.ScriptSrc = append(
 		cfg.Web.ContentSecurityPolicy.ScriptSrc,
+		"http://localhost:7331",
 		"'unsafe-inline'",
 	)
 }
 
+func sortSources(ss map[string]*config.Source) {
+	sources = make([]*config.Source, len(ss))
+	for _, v := range ss {
+		sources[v.Order] = v
+	}
+}
+
 func NewMux(
 	cfg *config.Config,
 	index *search.ReadIndex,
@@ -93,19 +73,20 @@ func NewMux(
 	if err != nil {
 		log.Panicf("could not load templates: %v", err)
 	}
+	sortSources(cfg.Importer.Sources)
 
 	errorHandler := createErrorHandler(cfg)
 
 	top := http.NewServeMux()
 	mux := http.NewServeMux()
 	mux.HandleFunc("/{$}", func(w http.ResponseWriter, r *http.Request) {
-		indexData := TemplateData{
+		indexData := components.TemplateData{
 			ExtraHeadHTML: cfg.Web.ExtraHeadHTML,
-			Sources:       cfg.Importer.Sources,
+			Sources:       sources,
 			Assets:        frontend.Assets,
 		}
 		w.Header().Add("Cache-Control", "max-age=86400")
-		err := templates["index"].Execute(w, indexData)
+		err := components.Homepage(indexData).Render(r.Context(), w)
 		if err != nil {
 			errorHandler(w, r, err.Error(), http.StatusInternalServerError)
 		}
@@ -146,12 +127,13 @@ func NewMux(
 					errorHandler(w, r, err.Error(), http.StatusInternalServerError)
 				}
 
-				tdata := ResultData{
-					TemplateData: TemplateData{
+				tdata := components.ResultData{
+					TemplateData: components.TemplateData{
 						ExtraHeadHTML: cfg.Web.ExtraHeadHTML,
 						Source:        *source,
-						Sources:       cfg.Importer.Sources,
+						Sources:       sources,
 						Assets:        frontend.Assets,
+						Query:         qs,
 					},
 					ResultsPerPage: search.ResultsPerPage,
 					Query:          qs,
@@ -193,9 +175,9 @@ func NewMux(
 				w.Header().Add("Vary", "Fetch")
 				if r.Header.Get("Fetch") == "true" {
 					w.Header().Add("Content-Type", "text/html; charset=utf-8")
-					err = templates[importerType.String()].ExecuteTemplate(w, "results", tdata)
+					err = components.Results(tdata).Render(r.Context(), w)
 				} else {
-					err = templates[importerType.String()].Execute(w, tdata)
+					err = components.ResultsPage(tdata).Render(r.Context(), w)
 				}
 				if err != nil {
 					slog.Error("template error", "template", importerType, "error", err)
@@ -210,13 +192,16 @@ func NewMux(
 				}
 
 				w.Header().Add("Cache-Control", "max-age=14400")
-				err = templates["search"].Execute(w, TemplateData{
-					ExtraHeadHTML: cfg.Web.ExtraHeadHTML,
-					Sources:       cfg.Importer.Sources,
-					Source:        *source,
-					SourceResult:  sourceResult,
-					Assets:        frontend.Assets,
-				})
+				err = components.SearchPage(
+					components.TemplateData{
+						ExtraHeadHTML: cfg.Web.ExtraHeadHTML,
+						Sources:       sources,
+						Source:        *source,
+						SourceResult:  sourceResult,
+						Assets:        frontend.Assets,
+					},
+					components.ResultData{},
+				).Render(r.Context(), w)
 				if err != nil {
 					errorHandler(w, r, err.Error(), http.StatusInternalServerError)
 
@@ -260,20 +245,20 @@ func NewMux(
 				return
 			}
 
-			tdata := DocumentData{
-				TemplateData: TemplateData{
+			tdata := components.DocumentData{
+				TemplateData: components.TemplateData{
 					ExtraHeadHTML: cfg.Web.ExtraHeadHTML,
 					Source:        *source,
-					Sources:       cfg.Importer.Sources,
+					Sources:       sources,
 					Assets:        frontend.Assets,
 				},
 				Document: doc,
 			}
 			if r.Header.Get("Fetch") == "true" {
 				w.Header().Add("Content-Type", "text/html; charset=utf-8")
-				err = templates[importerSingular].ExecuteTemplate(w, "main", tdata)
+				err = components.Detail(*doc).Render(r.Context(), w)
 			} else {
-				err = templates[importerSingular].Execute(w, tdata)
+				err = components.DetailPage(tdata.TemplateData, *doc).Render(r.Context(), w)
 			}
 			if err != nil {
 				slog.Error("template error", "template", importerSingular, "error", err)
@@ -337,7 +322,7 @@ func NewMux(
 
 	if liveReload {
 		applyDevModeOverrides(cfg)
-		cfg.Web.ExtraHeadHTML = jsSnippet
+		cfg.Web.ExtraHeadHTML = livereload.JsSnippet
 		liveReload := livereload.New()
 		liveReload.Start()
 		top.Handle("/livereload", liveReload)
diff --git a/internal/server/templates.go b/internal/server/templates.go
index 38ff5d4..fa95425 100644
--- a/internal/server/templates.go
+++ b/internal/server/templates.go
@@ -95,21 +95,13 @@ func loadTemplates() (TemplateCollection, error) {
 	templateDir := "templates"
 	templates := make(TemplateCollection, 0)
 
-	layoutFile := path.Join(templateDir, "index.gotmpl")
-
-	index, err := loadTemplate(layoutFile)
-	if err != nil {
-		return nil, err
-	}
-	templates["index"] = index
-
 	glob := path.Join(templateDir, "*.gotmpl")
 	templatePaths, err := fs.Glob(frontend.Files, glob)
 	if err != nil {
 		return nil, errors.WithMessage(err, "could not glob main templates")
 	}
 	for _, fullname := range templatePaths {
-		tpl, err := loadTemplate(layoutFile, fullname)
+		tpl, err := loadTemplate(fullname)
 		if err != nil {
 			return nil, err
 		}
@@ -117,20 +109,5 @@ func loadTemplates() (TemplateCollection, error) {
 		templates[name] = tpl
 	}
 
-	glob = path.Join(templateDir, "blocks", "*.gotmpl")
-	templatePaths, err = fs.Glob(frontend.Files, glob)
-	if err != nil {
-		return nil, errors.WithMessage(err, "could not glob block templates")
-	}
-	for _, fullname := range templatePaths {
-		tpl, err := loadTemplate(layoutFile, glob, fullname)
-		if err != nil {
-			return nil, err
-		}
-
-		name, _ := strings.CutSuffix(path.Base(fullname), ".gotmpl")
-		templates[name] = tpl
-	}
-
 	return templates, nil
 }