// 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" "os" "path/filepath" "github.com/lukaszkasprzak/lectio/internal/calendar" "github.com/lukaszkasprzak/lectio/internal/ini" ) //go:embed roman-calendar.ini var romanCalendar []byte //go:embed tridentine-calendar.ini var tridentineCalendar []byte //go:embed tridentine-lectionary.ini var tridentineLectionary []byte // efTempReadings maps an EF temporal-day slug to its readings (parsed once). var efTempReadings = parseLectionary(tridentineLectionary) func parseLectionary(data []byte) map[string][]calendar.Reading { l, err := ParseLayer(data) if err != nil { panic(fmt.Sprintf("caldata: tridentine-lectionary.ini invalid: %v", err)) } out := map[string][]calendar.Reading{} for slug, rc := range l.Cels { var rs []calendar.Reading for _, part := range []string{"first", "psalm", "second", "gospel"} { if c := rc.Fields[part]; c != "" { rs = append(rs, calendar.Reading{Part: part, Citation: c}) } } out[slug] = rs } return out } // TemporalReadings returns the temporal-cycle readings for a computed day slug, // or nil. Only the EF ("old") temporal lectionary exists so far. func TemporalReadings(form, slug string) []calendar.Reading { if form == "old" { return efTempReadings[slug] } return nil } // Universal parses the embedded Ordinary Form universal calendar. It panics on a // malformed embedded file (a build-time bug caught by tests). func Universal() calendar.Layer { l, err := ParseLayer(romanCalendar) if err != nil { panic(fmt.Sprintf("caldata: embedded roman-calendar.ini invalid: %v", err)) } return l } // Tridentine parses the embedded Extraordinary Form (1962) universal calendar. func Tridentine() calendar.Layer { l, err := ParseLayer(tridentineCalendar) if err != nil { panic(fmt.Sprintf("caldata: embedded tridentine-calendar.ini invalid: %v", err)) } return l } // Base returns the universal base layer for a form: the 1962 calendar for // "old" (EF), the General Roman Calendar otherwise (OF). func Base(form string) calendar.Layer { if form == "old" { return Tridentine() } return Universal() } // LoadLayer reads and parses a user calendar layer file. id (the filename stem) // is used as the layer's ID when the file's [layer] header omits one. func LoadLayer(path, id string) (calendar.Layer, error) { data, err := os.ReadFile(path) if err != nil { return calendar.Layer{}, err } l, err := ParseLayer(data) if err != nil { return calendar.Layer{}, fmt.Errorf("%s: %w", path, err) } if l.ID == "" { l.ID = id } return l, nil } // Stack returns the ordered layer stack for the engine: the form's universal // base first, then each user layer named in use (matched to "