summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
Diffstat (limited to 'internal')
-rw-r--r--internal/readings/readings.go26
-rw-r--r--internal/readings/readings_test.go23
-rw-r--r--internal/web/server.go84
-rw-r--r--internal/web/server_test.go27
-rw-r--r--internal/web/static/base.css2
-rw-r--r--internal/web/templates/index.html9
-rw-r--r--internal/web/templates/lookup.html20
7 files changed, 66 insertions, 125 deletions
diff --git a/internal/readings/readings.go b/internal/readings/readings.go
index 886c1eb..82d2fb9 100644
--- a/internal/readings/readings.go
+++ b/internal/readings/readings.go
@@ -6,6 +6,7 @@ package readings
import (
"fmt"
+ "strings"
"github.com/lukaszkasprzak/lectio/internal/config"
"github.com/lukaszkasprzak/lectio/internal/liturgy"
@@ -56,8 +57,12 @@ func Load(cfg config.Config, opts Options) ([]liturgy.Section, error) {
}
// filterParts keeps only the gospel when !all (PartID "ewangelia" modern or
-// "evangelium" traditional), otherwise keeps sections cfg.PartShown allows
-// (a section with an empty PartID is always kept). Pure and network-free.
+// "evangelium" traditional). When all and the lectionary is traditional, it
+// keeps only the scripture readings (isTraditionalReading) -- dropping
+// Introit/Kolekta/Graduale/Offertorium/Sekreta/Prefacja/Komunia/Pokomunia
+// and any commemoration, none of which are readings; the "new" lectionary
+// path is unchanged, keeping sections cfg.PartShown allows (a section with
+// an empty PartID is always kept). Pure and network-free.
func filterParts(secs []liturgy.Section, cfg config.Config, all bool) []liturgy.Section {
var out []liturgy.Section
for _, s := range secs {
@@ -67,9 +72,26 @@ func filterParts(secs []liturgy.Section, cfg config.Config, all bool) []liturgy.
}
continue
}
+ if cfg.Lectionary == "traditional" {
+ if isTraditionalReading(s.PartID) {
+ out = append(out, s)
+ }
+ continue
+ }
if s.PartID == "" || cfg.PartShown(cfg.Lectionary, s.PartID) {
out = append(out, s)
}
}
return out
}
+
+// isTraditionalReading reports whether partID (a lowercased missalemeum
+// section id) is a scripture reading -- the gospel, or an epistle/lesson --
+// rather than Introit/Kolekta/Graduale/Offertorium/Sekreta/Prefacja/
+// Komunia/Pokomunia or a commemoration.
+func isTraditionalReading(partID string) bool {
+ return partID == "evangelium" ||
+ strings.HasPrefix(partID, "lectio") ||
+ strings.HasPrefix(partID, "epistola") ||
+ strings.HasPrefix(partID, "prophetia")
+}
diff --git a/internal/readings/readings_test.go b/internal/readings/readings_test.go
index fd355ff..20df5e0 100644
--- a/internal/readings/readings_test.go
+++ b/internal/readings/readings_test.go
@@ -55,6 +55,29 @@ func TestFilterPartsAll(t *testing.T) {
}
}
+func TestFilterPartsTraditionalAllReadingsOnly(t *testing.T) {
+ secs := []liturgy.Section{
+ {PartID: "introitus", Heading: "Introit"},
+ {PartID: "oratio", Heading: "Kolekta"},
+ {PartID: "lectio", Heading: "Lekcja"},
+ {PartID: "graduale", Heading: "GraduaƂ"},
+ {PartID: "evangelium", Heading: "Ewangelia"},
+ {PartID: "offertorium", Heading: "Ofiarowanie"},
+ {PartID: "secreta", Heading: "Sekreta"},
+ {PartID: "communio", Heading: "Komunia"},
+ {PartID: "postcommunio", Heading: "Pokomunia"},
+ }
+ cfg := config.Config{Lectionary: "traditional"}
+ got := filterParts(secs, cfg, true)
+
+ if len(got) != 2 {
+ t.Fatalf("got %d sections, want 2: %+v", len(got), got)
+ }
+ if got[0].PartID != "lectio" || got[1].PartID != "evangelium" {
+ t.Errorf("got %+v, want [lectio evangelium] in order", got)
+ }
+}
+
func TestLoadModernRoutes(t *testing.T) {
html, err := os.ReadFile("../liturgy/testdata/2026-07-22.html")
if err != nil {
diff --git a/internal/web/server.go b/internal/web/server.go
index c7e645d..76a5d3b 100644
--- a/internal/web/server.go
+++ b/internal/web/server.go
@@ -1,12 +1,11 @@
// This file wires the package's render helpers (RenderReadings, Themes,
// themeCSS, the embedded static/templates FS) into an HTTP server: the full
-// page (GET /), the HTMX reading-pane partial (GET /readings), a passage
-// lookup partial (GET /lookup), a theme stylesheet endpoint (GET
-// /theme.css) and the embedded static assets (GET /static/...).
+// page (GET /), the HTMX reading-pane partial (GET /readings), a theme
+// stylesheet endpoint (GET /theme.css) and the embedded static assets (GET
+// /static/...).
package web
import (
- "bytes"
"fmt"
"html/template"
"io"
@@ -19,7 +18,6 @@ import (
"strings"
"time"
- "github.com/lukaszkasprzak/lectio/internal/bible"
"github.com/lukaszkasprzak/lectio/internal/config"
"github.com/lukaszkasprzak/lectio/internal/liturgy"
"github.com/lukaszkasprzak/lectio/internal/readings"
@@ -39,7 +37,6 @@ func NewServer(cfg config.Config) http.Handler {
mux.HandleFunc("GET /{$}", indexHandler(cfg))
mux.HandleFunc("GET /readings", readingsHandler(cfg))
- mux.HandleFunc("GET /lookup", lookupHandler(cfg))
mux.HandleFunc("GET /theme.css", themeCSSHandler(cfg))
staticSub, err := fs.Sub(staticFS, "static")
@@ -76,12 +73,14 @@ func shiftDate(date string, days int) string {
}
// requestVersions returns the versions requested via one or more repeated
-// ?v= query params, falling back to cfg.Versions when none were given.
+// ?v= query params, falling back to a single cfg.DefaultVersion (not the
+// full cfg.Versions set) when none were given, so a plain visit checks
+// exactly one version box.
func requestVersions(cfg config.Config, r *http.Request) []string {
if vs, ok := r.URL.Query()["v"]; ok && len(vs) > 0 {
return vs
}
- return append([]string(nil), cfg.Versions...)
+ return []string{cfg.DefaultVersion}
}
// queryBool reads a truthy/falsy query param ("1"/"true"/"on"/"yes" vs.
@@ -138,15 +137,20 @@ func resolveQuery(cfg config.Config, r *http.Request) (date, lectionary string,
}
// 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
-// to the caller for rendering -- so the caller's column labels always match
-// what was actually loadable.
+// override cfg, all controls part filtering, and versions is swapped via
+// render.OfflineVersions -- when cfg.Offline (any lectionary needs the
+// network-free set), or when lectionary is "traditional" (pl is the
+// niedziela.pl modern scrape, meaningless for missalemeum) -- before being
+// handed back to the caller for rendering, so the caller's column labels
+// always match what was actually loadable.
func loadSections(cfg config.Config, lectionary, date string, all bool, versions []string) ([]liturgy.Section, []string, error) {
cfg.Lectionary = lectionary
if cfg.Offline {
versions = render.OfflineVersions(versions)
}
+ if lectionary == "traditional" {
+ versions = render.OfflineVersions(versions)
+ }
secs, err := readings.Load(cfg, readings.Options{
Date: date,
Offline: cfg.Offline,
@@ -165,8 +169,6 @@ type indexData struct {
Theme string
Display string
Mono bool
- Ref string
- Lookup template.HTML
Reading template.HTML
}
@@ -209,12 +211,6 @@ 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),
@@ -226,8 +222,6 @@ func indexHandler(cfg config.Config) http.HandlerFunc {
Theme: theme,
Display: display,
Mono: queryBool(r, "mono", cfg.WebMono),
- Ref: ref,
- Lookup: lookup,
Reading: reading,
}
@@ -266,52 +260,6 @@ func renderOrError(secs []liturgy.Section, versions []string, lectionary, displa
return RenderReadings(secs, versions, lectionary, display)
}
-// lookupColumn is what templates/lookup.html ranges over: one per requested
-// version.
-type lookupColumn struct {
- Version string
- Verses []bible.Verse
- Missing []string
-}
-
-// 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). ref is trimmed of
-// surrounding whitespace here so both routes treat a whitespace-only ref
-// identically; an empty (or now-empty) ref renders nothing, matching
-// lookupHandler's previous no-op behavior.
-func renderLookup(ref string, versions []string) template.HTML {
- ref = strings.TrimSpace(ref)
- 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 := r.URL.Query().Get("ref") // renderLookup trims whitespace
- w.Header().Set("Content-Type", "text/html; charset=utf-8")
- io.WriteString(w, string(renderLookup(ref, requestVersions(cfg, r))))
- }
-}
-
// themeCSSHandler serves one theme's stylesheet: the requested name, or
// (unknown/invalid) cfg.WebTheme, or (that also unknown) the built-in
// default -- so an unrecognized ?name= degrades to a working theme instead
diff --git a/internal/web/server_test.go b/internal/web/server_test.go
index 30c8fbf..47c38e9 100644
--- a/internal/web/server_test.go
+++ b/internal/web/server_test.go
@@ -64,17 +64,6 @@ func TestServer(t *testing.T) {
}
})
- t.Run("lookup", func(t *testing.T) {
- rec := httptest.NewRecorder()
- srv.ServeHTTP(rec, httptest.NewRequest("GET", "/lookup?ref=J+20:1&v=wuj", nil))
- if rec.Code != http.StatusOK {
- t.Fatalf("status = %d, want 200", rec.Code)
- }
- if !strings.Contains(rec.Body.String(), "20:1") {
- t.Errorf("lookup result missing verse: %q", rec.Body.String())
- }
- })
-
t.Run("theme.css", func(t *testing.T) {
rec := httptest.NewRecorder()
srv.ServeHTTP(rec, httptest.NewRequest("GET", "/theme.css?name=benedictines", nil))
@@ -172,22 +161,6 @@ func TestServer(t *testing.T) {
}
})
- t.Run("index page seeds lookup results from ?ref=", func(t *testing.T) {
- rec := httptest.NewRecorder()
- srv.ServeHTTP(rec, httptest.NewRequest("GET", "/?ref=J+20:1&v=wuj", nil))
- if rec.Code != http.StatusOK {
- t.Fatalf("status = %d, want 200", rec.Code)
- }
- body := rec.Body.String()
- if !strings.Contains(body, `id="lookup-results"`) {
- t.Fatalf("body missing lookup-results container: %q", body)
- }
- i := strings.Index(body, `id="lookup-results"`)
- if !strings.Contains(body[i:], "20:1") {
- t.Errorf("lookup-results not populated from ?ref=: %q", body[i:min(i+400, len(body))])
- }
- })
-
t.Run("index page seeds display select from cfg", func(t *testing.T) {
rec := httptest.NewRecorder()
srv.ServeHTTP(rec, httptest.NewRequest("GET", "/?date=2026-07-22&v=wuj", nil))
diff --git a/internal/web/static/base.css b/internal/web/static/base.css
index 59c67aa..f31dc64 100644
--- a/internal/web/static/base.css
+++ b/internal/web/static/base.css
@@ -82,6 +82,8 @@ body.mono {
border-width: 1px;
border-style: solid;
border-radius: 0; /* no rounded chrome */
+ background: var(--bg);
+ color: var(--fg);
}
/* Reading pane */
diff --git a/internal/web/templates/index.html b/internal/web/templates/index.html
index 8c88779..cc56a09 100644
--- a/internal/web/templates/index.html
+++ b/internal/web/templates/index.html
@@ -1,7 +1,6 @@
{{/* index.html renders the full lectio-web page: top-bar controls (date,
lectionary, version checkboxes, all/gospel toggle, display select,
- theme select), a passage-lookup form, and the pre-rendered reading pane
- (#pane).
+ theme select) and the pre-rendered reading pane (#pane).
The controls form (#controls) carries hx-get="/readings" and fires on
any "change" bubbling up from its fields (htmx auto-includes an
@@ -72,12 +71,6 @@
<label class="mono-toggle"><input type="checkbox" {{if .Mono}}checked{{end}}
onchange="document.body.classList.toggle('mono', this.checked)"> mono</label>
- <form id="lookup-form" class="controls" hx-get="/lookup" hx-target="#lookup-results" hx-include="#controls">
- <input type="text" name="ref" placeholder="np. J 20:1" value="{{.Ref}}">
- <button type="submit">szukaj</button>
- </form>
- <div id="lookup-results">{{.Lookup}}</div>
-
<div id="pane">{{.Reading}}</div>
</div>
diff --git a/internal/web/templates/lookup.html b/internal/web/templates/lookup.html
deleted file mode 100644
index c8bc2a7..0000000
--- a/internal/web/templates/lookup.html
+++ /dev/null
@@ -1,20 +0,0 @@
-{{/* lookup.html renders the passage-lookup fragment: one .column per
- requested version, each version's matched bible.Verse rows plus any
- sub-refs the corpus had no entry for. Structurally mirrors
- readings.html's .columns/.column/.block classes so theme CSS restyles
- both panes the same way. */}}
-{{if .}}
-<div class="columns">
- {{range .}}
- <div class="column">
- <h3 class="version-label">{{.Version}}</h3>
- {{range .Verses}}
- <p class="block verse"><span class="vnum">{{.Chapter}}:{{.Verse}}</span> {{.Text}}</p>
- {{end}}
- {{if .Missing}}
- <p class="block error">brak: {{range $i, $m := .Missing}}{{if $i}}, {{end}}{{$m}}{{end}}</p>
- {{end}}
- </div>
- {{end}}
-</div>
-{{end}}