From 4a35093c4358be17da6f0f374197caed743bda26 Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Mon, 27 Jul 2026 23:27:07 +0200 Subject: feat(caldata): OF Sunday/solemnity readings by slug+cycle (seed table) --- internal/caldata/caldata.go | 10 ++++++++-- internal/caldata/of-lectionary.ini | 15 +++++++++++++++ internal/caldata/of_test.go | 38 ++++++++++++++++++++++++++++++++++++++ internal/caldata/readings.go | 7 ++++++- 4 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 internal/caldata/of-lectionary.ini create mode 100644 internal/caldata/of_test.go diff --git a/internal/caldata/caldata.go b/internal/caldata/caldata.go index 92f9327..9c17035 100644 --- a/internal/caldata/caldata.go +++ b/internal/caldata/caldata.go @@ -25,6 +25,12 @@ var tridentineLectionary []byte // efTempReadings maps an EF temporal-day slug to its readings (parsed once). var efTempReadings = parseLectionary(tridentineLectionary) +//go:embed of-lectionary.ini +var ofLectionary []byte + +// ofTempReadings maps an OF - key to its readings (parsed once). +var ofTempReadings = parseLectionary(ofLectionary) + func parseLectionary(data []byte) map[string][]calendar.Reading { l, err := ParseLayer(data) if err != nil { @@ -44,12 +50,12 @@ func parseLectionary(data []byte) map[string][]calendar.Reading { } // TemporalReadings returns the temporal-cycle readings for a computed day slug, -// or nil. Only the EF ("old") temporal lectionary exists so far. +// or nil. EF ("old") looks up efTempReadings; OF looks up ofTempReadings. func TemporalReadings(form, slug string) []calendar.Reading { if form == "old" { return efTempReadings[slug] } - return nil + return ofTempReadings[slug] } // Universal parses the embedded Ordinary Form universal calendar. It panics on a diff --git a/internal/caldata/of-lectionary.ini b/internal/caldata/of-lectionary.ini new file mode 100644 index 0000000..b9f4772 --- /dev/null +++ b/internal/caldata/of-lectionary.ini @@ -0,0 +1,15 @@ +; OF (Ordinary Form) Sunday & solemnity lectionary, keyed by +; -. Citations English-canonical. +; SEED — replaced by scripts/genlect-of.go (niedziela, 2025-2027). + +[easter-sunday-A] +first = Acts 10:34,37-43 +psalm = Ps 118:1-2,16-17,22-23 +second = Col 3:1-4 +gospel = John 20:1-9 + +[christ-the-king-A] +first = Ezek 34:11-12,15-17 +psalm = Ps 23:1-2,2-3,5-6 +second = 1 Cor 15:20-26,28 +gospel = Matt 25:31-46 diff --git a/internal/caldata/of_test.go b/internal/caldata/of_test.go new file mode 100644 index 0000000..7bc2ce1 --- /dev/null +++ b/internal/caldata/of_test.go @@ -0,0 +1,38 @@ +package caldata + +import ( + "testing" + "time" + + "github.com/lukaszkasprzak/lectio/internal/calendar" +) + +func TestOFReadingsByCycle(t *testing.T) { + // A synthetic OF day keyed christ-the-king-A must resolve to Matt 25. + day := calendar.LiturgicalDay{ + Observed: calendar.Celebration{Slug: "christ-the-king", Layer: "temporal"}, + SundayCycle: "A", + Weekday: time.Sunday, + } + sel := calendar.Selection{Form: "new"} + rs := Readings(sel, nil, time.Date(2026, 11, 22, 0, 0, 0, 0, time.UTC), day) + var gospel string + for _, r := range rs { + if r.Part == "gospel" { + gospel = r.Citation + } + } + if gospel == "" || gospel[:4] != "Matt" { + t.Fatalf("christ-the-king-A gospel = %q, want Matt…", gospel) + } +} + +func TestOFWeekdayEmpty(t *testing.T) { + day := calendar.LiturgicalDay{ + Observed: calendar.Celebration{Slug: "ordinary-weekday", Layer: "temporal"}, + Weekday: time.Wednesday, // no SundayCycle key -> deferred phase -> empty + } + if rs := Readings(calendar.Selection{Form: "new"}, nil, time.Now().UTC(), day); len(rs) != 0 { + t.Fatalf("weekday should be empty, got %v", rs) + } +} diff --git a/internal/caldata/readings.go b/internal/caldata/readings.go index a11235d..2810026 100644 --- a/internal/caldata/readings.go +++ b/internal/caldata/readings.go @@ -19,7 +19,12 @@ func Readings(sel calendar.Selection, layers []calendar.Layer, date time.Time, d if len(rs) > 0 { return rs } - if r := TemporalReadings(sel.Form, day.Observed.Slug); len(r) > 0 { + // temporal table: EF by slug, OF by slug+cycle. + key := day.Observed.Slug + if sel.Form != "old" && day.SundayCycle != "" { + key = day.Observed.Slug + "-" + day.SundayCycle + } + if r := TemporalReadings(sel.Form, key); len(r) > 0 { return r } if sel.Form == "old" && day.Observed.Layer == "temporal" && date.Weekday() != time.Sunday { -- cgit v1.3