diff options
Diffstat (limited to 'internal/web/server.go')
| -rw-r--r-- | internal/web/server.go | 110 |
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)))) } } |
