aboutsummaryrefslogtreecommitdiff
path: root/internal/web/server.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/web/server.go')
-rw-r--r--internal/web/server.go110
1 files changed, 72 insertions, 38 deletions
diff --git a/internal/web/server.go b/internal/web/server.go
index b1a483f..d484b69 100644
--- a/internal/web/server.go
+++ b/internal/web/server.go
@@ -6,6 +6,7 @@
package web
import (
+ "bytes"
"fmt"
"html/template"
"io"
@@ -101,6 +102,33 @@ func requestLectionary(cfg config.Config, r *http.Request) string {
return cfg.Lectionary
}
+// requestDisplay returns the ?display= override (normalized the same way
+// config.Load normalizes cfg.WebDisplay, so a bad/unknown value falls back
+// to "horizontal" rather than reaching RenderReadings unchecked), falling
+// back to cfg.WebDisplay when the param is absent.
+func requestDisplay(cfg config.Config, r *http.Request) string {
+ if d := r.URL.Query().Get("display"); d != "" {
+ return config.NormalizeDisplay(d)
+ }
+ return cfg.WebDisplay
+}
+
+// resolveQuery resolves the date/lectionary/all/versions/display controls
+// shared by indexHandler and readingsHandler from cfg (the defaults) and
+// r's query params (the overrides) -- one place for both handlers so they
+// can't drift.
+func resolveQuery(cfg config.Config, r *http.Request) (date, lectionary string, all bool, versions []string, display string) {
+ date = r.URL.Query().Get("date")
+ if date == "" {
+ date = today()
+ }
+ lectionary = requestLectionary(cfg, r)
+ all = queryBool(r, "all", cfg.All)
+ versions = requestVersions(cfg, r)
+ display = requestDisplay(cfg, r)
+ return date, lectionary, all, versions, display
+}
+
// loadSections runs the readings router for one request: date/lectionary
// override cfg, all controls part filtering, and (when cfg.Offline)
// versions is swapped via render.OfflineVersions before being handed back
@@ -127,6 +155,7 @@ type indexData struct {
All bool
ThemeOpts []themeOpt
Theme string
+ Display string
Ref string
Lookup template.HTML
Reading template.HTML
@@ -147,20 +176,14 @@ type themeOpt struct {
// same query, so a plain (JS-less) GET / already shows today's gospel.
func indexHandler(cfg config.Config) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
- date := r.URL.Query().Get("date")
- if date == "" {
- date = today()
- }
- lectionary := requestLectionary(cfg, r)
- all := queryBool(r, "all", cfg.All)
- versions := requestVersions(cfg, r)
+ date, lectionary, all, versions, display := resolveQuery(cfg, r)
theme := r.URL.Query().Get("theme")
if theme == "" {
theme = cfg.WebTheme
}
secs, loadVersions, err := loadSections(cfg, lectionary, date, all, versions)
- reading := renderOrError(secs, loadVersions, lectionary, err)
+ reading := renderOrError(secs, loadVersions, lectionary, display, err)
selected := map[string]bool{}
for _, v := range versions {
@@ -177,6 +200,12 @@ func indexHandler(cfg config.Config) http.HandlerFunc {
themeOpts = append(themeOpts, themeOpt{Name: name, Selected: name == theme})
}
+ ref := r.URL.Query().Get("ref") // echoed into the lookup box on a shared/bookmarked link
+ var lookup template.HTML
+ if ref != "" {
+ lookup = renderLookup(ref, versions)
+ }
+
data := indexData{
Date: date,
PrevDate: shiftDate(date, -1),
@@ -186,7 +215,9 @@ func indexHandler(cfg config.Config) http.HandlerFunc {
All: all,
ThemeOpts: themeOpts,
Theme: theme,
- Ref: r.URL.Query().Get("ref"), // echoed into the lookup box on a shared/bookmarked link
+ Display: display,
+ Ref: ref,
+ Lookup: lookup,
Reading: reading,
}
@@ -201,16 +232,10 @@ func indexHandler(cfg config.Config) http.HandlerFunc {
// produced entirely by RenderReadings (never re-implemented here).
func readingsHandler(cfg config.Config) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
- date := r.URL.Query().Get("date")
- if date == "" {
- date = today()
- }
- lectionary := requestLectionary(cfg, r)
- all := queryBool(r, "all", cfg.All)
- versions := requestVersions(cfg, r)
+ date, lectionary, all, versions, display := resolveQuery(cfg, r)
secs, loadVersions, err := loadSections(cfg, lectionary, date, all, versions)
- reading := renderOrError(secs, loadVersions, lectionary, err)
+ reading := renderOrError(secs, loadVersions, lectionary, display, err)
w.Header().Set("Content-Type", "text/html; charset=utf-8")
io.WriteString(w, string(reading))
@@ -221,14 +246,14 @@ func readingsHandler(cfg config.Config) http.HandlerFunc {
// error) a small escaped error paragraph -- readings.Load errors are
// expected in normal operation (an unpublished date, no network while
// online, ...) so the pane should show them, not 500.
-func renderOrError(secs []liturgy.Section, versions []string, lectionary string, err error) template.HTML {
+func renderOrError(secs []liturgy.Section, versions []string, lectionary, display string, err error) template.HTML {
if err != nil {
return template.HTML(`<p class="error">` + template.HTMLEscapeString(err.Error()) + `</p>`)
}
if len(secs) == 0 {
return template.HTML(`<p class="error">brak czytań na ten dzień</p>`)
}
- return RenderReadings(secs, versions, lectionary)
+ return RenderReadings(secs, versions, lectionary, display)
}
// lookupColumn is what templates/lookup.html ranges over: one per requested
@@ -239,29 +264,38 @@ type lookupColumn struct {
Missing []string
}
-// lookupHandler serves the passage-lookup fragment: ref is looked up as-is
-// (already English/kjv-style, e.g. "J 20:1") against each requested version
-// via bible.Lookup directly -- no Polish->English conversion, that only
-// applies to a section's own citation (render.GatherVersion), not a
-// free-typed lookup.
+// renderLookup renders the passage-lookup fragment for ref (looked up as-is
+// -- already English/kjv-style, e.g. "J 20:1" -- against each of versions
+// via bible.Lookup directly; no Polish->English conversion, that only
+// applies to a section's own citation via render.GatherVersion, not a
+// free-typed lookup) against each requested version. Shared by lookupHandler
+// (the HTMX partial) and indexHandler (so a bookmarked/shared "/?ref=..."
+// link shows the same result instead of an empty pane). An empty ref
+// renders nothing, matching lookupHandler's previous no-op behavior.
+func renderLookup(ref string, versions []string) template.HTML {
+ if ref == "" {
+ return ""
+ }
+ cols := make([]lookupColumn, 0, len(versions))
+ for _, v := range versions {
+ verses, missing := bible.Lookup(v, ref)
+ cols = append(cols, lookupColumn{Version: v, Verses: verses, Missing: missing})
+ }
+
+ var buf bytes.Buffer
+ if err := tmpl.ExecuteTemplate(&buf, "lookup.html", cols); err != nil {
+ return template.HTML(`<p class="error">` + template.HTMLEscapeString(err.Error()) + `</p>`)
+ }
+ return template.HTML(buf.String())
+}
+
+// lookupHandler serves the passage-lookup fragment via renderLookup (see
+// its doc comment for the lookup semantics).
func lookupHandler(cfg config.Config) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ref := strings.TrimSpace(r.URL.Query().Get("ref"))
w.Header().Set("Content-Type", "text/html; charset=utf-8")
- if ref == "" {
- return
- }
-
- versions := requestVersions(cfg, r)
- cols := make([]lookupColumn, 0, len(versions))
- for _, v := range versions {
- verses, missing := bible.Lookup(v, ref)
- cols = append(cols, lookupColumn{Version: v, Verses: verses, Missing: missing})
- }
-
- if err := tmpl.ExecuteTemplate(w, "lookup.html", cols); err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
- }
+ io.WriteString(w, string(renderLookup(ref, requestVersions(cfg, r))))
}
}