diff options
| author | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-07-27 12:25:46 +0200 |
|---|---|---|
| committer | Lukasz Kasprzak <lukas@labunix.xyz> | 2026-07-27 12:25:46 +0200 |
| commit | 56f3b8161f73c33fe6e25f6461d3f061af427e9e (patch) | |
| tree | 7abe54aa45b3b4d9e3db0a75564d75c0d44b06ce /internal/caldata | |
| parent | a8232892b0ec94f8d077e3730143a09efcac452d (diff) | |
| download | lectio-56f3b8161f73c33fe6e25f6461d3f061af427e9e.tar.gz lectio-56f3b8161f73c33fe6e25f6461d3f061af427e9e.zip | |
feat(caldata): embed + parse the owned universal Roman calendar (initial coverage)
Diffstat (limited to 'internal/caldata')
| -rw-r--r-- | internal/caldata/caldata.go | 69 | ||||
| -rw-r--r-- | internal/caldata/caldata_test.go | 25 | ||||
| -rw-r--r-- | internal/caldata/roman-calendar.ini | 231 |
3 files changed, 325 insertions, 0 deletions
diff --git a/internal/caldata/caldata.go b/internal/caldata/caldata.go new file mode 100644 index 0000000..5deb895 --- /dev/null +++ b/internal/caldata/caldata.go @@ -0,0 +1,69 @@ +// Package caldata embeds and parses lectio's owned universal General Roman +// Calendar data into a calendar.Layer. It imports only internal/ini and +// internal/calendar (types). +package caldata + +import ( + _ "embed" + "fmt" + + "github.com/lukaszkasprzak/lectio/internal/calendar" + "github.com/lukaszkasprzak/lectio/internal/ini" +) + +//go:embed roman-calendar.ini +var romanCalendar []byte + +// Universal parses the embedded universal calendar. It panics on a malformed +// embedded file (a build-time bug caught by tests), never at the request layer. +func Universal() calendar.Layer { + l, err := parse(romanCalendar) + if err != nil { + panic(fmt.Sprintf("caldata: embedded roman-calendar.ini invalid: %v", err)) + } + return l +} + +func parse(data []byte) (calendar.Layer, error) { + secs, err := ini.Parse(data) + if err != nil { + return calendar.Layer{}, err + } + layer := calendar.Layer{Cels: map[string]calendar.RawCelebration{}} + for _, s := range secs { + fields := map[string]string{} + for _, p := range s.Pairs { + fields[p.Key] = p.Val + } + switch { + case s.Name == "" && len(fields) == 0: + continue + case s.Name == "layer": + layer.ID, layer.Name, layer.Type = fields["id"], fields["name"], fields["type"] + default: + base, variant, isVariant := cutVariant(s.Name) + rc := layer.Cels[base] + if rc.Fields == nil { + rc = calendar.RawCelebration{Fields: map[string]string{}, Variants: map[string]map[string]string{}} + } + if isVariant { + rc.Variants[variant] = fields + } else { + for k, v := range fields { + rc.Fields[k] = v + } + } + layer.Cels[base] = rc + } + } + return layer, nil +} + +func cutVariant(name string) (base, variant string, ok bool) { + for i := 0; i < len(name); i++ { + if name[i] == '/' { + return name[:i], name[i+1:], true + } + } + return name, "", false +} diff --git a/internal/caldata/caldata_test.go b/internal/caldata/caldata_test.go new file mode 100644 index 0000000..ab7a314 --- /dev/null +++ b/internal/caldata/caldata_test.go @@ -0,0 +1,25 @@ +package caldata + +import ( + "testing" + + "github.com/lukaszkasprzak/lectio/internal/calendar" +) + +func TestUniversalLoads(t *testing.T) { + l := Universal() + if l.ID != "universal" { + t.Fatalf("layer id = %q", l.ID) + } + rc, ok := l.Cels["assumption"] + if !ok || rc.Fields["rank"] != "solemnity" || rc.Fields["date"] != "08-15" { + t.Fatalf("assumption = %+v ok=%v", rc, ok) + } + // every entry must build into a typed Celebration whose rank parsed. + for slug, rc := range l.Cels { + c := calendar.BuildCelebrationForTest(slug, rc) + if c.Rank == calendar.RankFerial && rc.Fields["rank"] != "" { + t.Errorf("%s: rank did not parse (%q)", slug, rc.Fields["rank"]) + } + } +} diff --git a/internal/caldata/roman-calendar.ini b/internal/caldata/roman-calendar.ini new file mode 100644 index 0000000..dfaeb96 --- /dev/null +++ b/internal/caldata/roman-calendar.ini @@ -0,0 +1,231 @@ +; General Roman Calendar (Ordinary Form) — universal sanctoral. +; The temporal cycle (Sundays, seasons, Easter, Christmas, Epiphany, Ascension, +; Pentecost, Trinity, Corpus Christi, Sacred Heart, Christ the King, Baptism, +; Holy Family) is computed by internal/calendar and is NOT listed here. +; Initial coverage; expanded and verified against the oracle (see the plan). +; Bootstrapped with reference to romcal (MIT) — see NOTICE. + +[layer] +id = universal +name = General Roman Calendar +type = universal + +; --- Solemnities --- + +[mary-mother-of-god] +date = 01-01 +rank = solemnity +class = bvm +colour = white +name.en = Mary, the Holy Mother of God +name.pl = Świętej Bożej Rodzicielki Maryi +name.la = Sanctae Dei Genetricis Mariae + +[st-joseph] +date = 03-19 +rank = solemnity +class = saint +colour = white +name.en = Saint Joseph, Spouse of the Blessed Virgin Mary +name.pl = Świętego Józefa, Oblubieńca Najświętszej Maryi Panny + +[annunciation] +date = 03-25 +rank = solemnity +class = lord +colour = white +name.en = The Annunciation of the Lord +name.pl = Zwiastowanie Pańskie + +[nativity-john-baptist] +date = 06-24 +rank = solemnity +class = saint +colour = white +name.en = The Nativity of Saint John the Baptist +name.pl = Narodzenie świętego Jana Chrzciciela + +[peter-and-paul] +date = 06-29 +rank = solemnity +class = saint +colour = red +name.en = Saints Peter and Paul, Apostles +name.pl = Świętych Apostołów Piotra i Pawła + +[assumption] +date = 08-15 +rank = solemnity +class = bvm +colour = white +name.en = The Assumption of the Blessed Virgin Mary +name.pl = Wniebowzięcie Najświętszej Maryi Panny +name.la = In Assumptione Beatae Mariae Virginis + +[all-saints] +date = 11-01 +rank = solemnity +class = saint +colour = white +name.en = All Saints +name.pl = Wszystkich Świętych + +[all-souls] +date = 11-02 +rank = solemnity +class = saint +colour = violet +name.en = The Commemoration of All the Faithful Departed (All Souls) +name.pl = Wspomnienie wszystkich wiernych zmarłych + +[immaculate-conception] +date = 12-08 +rank = solemnity +class = bvm +colour = white +name.en = The Immaculate Conception of the Blessed Virgin Mary +name.pl = Niepokalane Poczęcie Najświętszej Maryi Panny + +; --- Feasts of the Lord (class lord → replace Ordinary Sundays) --- + +[presentation-of-the-lord] +date = 02-02 +rank = feast +class = lord +colour = white +name.en = The Presentation of the Lord +name.pl = Ofiarowanie Pańskie + +[transfiguration] +date = 08-06 +rank = feast +class = lord +colour = white +name.en = The Transfiguration of the Lord +name.pl = Przemienienie Pańskie + +[exaltation-of-the-cross] +date = 09-14 +rank = feast +class = lord +colour = red +name.en = The Exaltation of the Holy Cross +name.pl = Podwyższenie Krzyża Świętego + +[dedication-of-the-lateran] +date = 11-09 +rank = feast +class = lord +colour = white +name.en = The Dedication of the Lateran Basilica + +; --- Feasts (saints) --- + +[conversion-of-paul] +date = 01-25 +rank = feast +class = saint +colour = white +name.en = The Conversion of Saint Paul the Apostle + +[st-mark] +date = 04-25 +rank = feast +class = saint +colour = red +name.en = Saint Mark, Evangelist + +[st-james] +date = 07-25 +rank = feast +class = saint +colour = red +name.en = Saint James, Apostle + +[archangels] +date = 09-29 +rank = feast +class = saint +colour = white +name.en = Saints Michael, Gabriel and Raphael, Archangels + +[st-luke] +date = 10-18 +rank = feast +class = saint +colour = red +name.en = Saint Luke, Evangelist + +[st-andrew] +date = 11-30 +rank = feast +class = saint +colour = red +name.en = Saint Andrew, Apostle + +[st-stephen] +date = 12-26 +rank = feast +class = saint +colour = red +name.en = Saint Stephen, the First Martyr + +[st-john-evangelist] +date = 12-27 +rank = feast +class = saint +colour = white +name.en = Saint John, Apostle and Evangelist + +[holy-innocents] +date = 12-28 +rank = feast +class = saint +colour = red +name.en = The Holy Innocents, Martyrs + +; --- Memorials --- + +[st-thomas-aquinas] +date = 01-28 +rank = memorial +class = saint +colour = white +name.en = Saint Thomas Aquinas, Priest and Doctor + +[st-benedict] +date = 07-11 +rank = memorial +class = saint +colour = white +name.en = Saint Benedict, Abbot + +[st-anthony-padua] +date = 06-13 +rank = memorial +class = saint +colour = white +name.en = Saint Anthony of Padua, Priest and Doctor + +[st-augustine] +date = 08-28 +rank = memorial +class = saint +colour = white +name.en = Saint Augustine, Bishop and Doctor + +[st-therese-lisieux] +date = 10-01 +rank = memorial +class = saint +colour = white +name.en = Saint Thérèse of the Child Jesus, Virgin and Doctor + +; --- Optional memorials --- + +[st-nicholas] +date = 12-06 +rank = optional +class = saint +colour = white +name.en = Saint Nicholas, Bishop |
