From c9f3bf46f0de09edb796e35f3dcff349febf75c9 Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Fri, 24 Jul 2026 10:32:28 +0200 Subject: dayinfo: show feast/day name + colour (modern niedziela + traditional missalemeum) in cli/tui/web; v0.5.0 --- internal/liturgy/parse.go | 53 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) (limited to 'internal/liturgy/parse.go') diff --git a/internal/liturgy/parse.go b/internal/liturgy/parse.go index 64e6928..4c1a935 100644 --- a/internal/liturgy/parse.go +++ b/internal/liturgy/parse.go @@ -23,8 +23,32 @@ var ( h4Re = regexp.MustCompile(`(?s)

(.*?)

`) pRe = regexp.MustCompile(`(?s)

(.*?)

`) citationRe = regexp.MustCompile(`\((.+)\)\s*$`) + + // dayNamePRe matches every classed

...

on the page; only + // the one whose class carries both "fw-bold" and a "color-" role (see + // dayNameParaMatches) is the day's celebration name -- the page also + // carries a plain fw-bold (no color-) lookalike higher up that must not + // win instead. + dayNamePRe = regexp.MustCompile(`(?s)

\s*(.*?)\s*

`) + + // dayColourRe matches niedziela.pl's "Kolor szat: " vestment-colour + // line, tolerating the / markup wrapped around the colour + // word on the page (see internal/liturgy/testdata/2026-07-22.html). + dayColourRe = regexp.MustCompile(`Kolor szat:\s*(?:<[^>]+>\s*)*([\p{L}]+)`) ) +// modernColours maps niedziela.pl's Polish vestment-colour words to +// DayInfo's normalized colour names; anything not listed here (including a +// multi-option line like "zielony albo biały albo czerwony", which matches +// only its first word) is left for the caller to treat as "" if absent. +var modernColours = map[string]string{ + "biały": "white", + "zielony": "green", + "fioletowy": "violet", + "czerwony": "red", + "różowy": "rose", +} + // panePattern matches the opening tag of the tab-pane div carrying the given // tab id, e.g. `
`. func panePattern(tab string) *regexp.Regexp { @@ -122,6 +146,35 @@ func Parse(pageHTML string) ([]Section, error) { return sections, nil } +// ParseDayInfo extracts the day's celebration name and liturgical colour +// from a niedziela.pl page: Name is the inner text of the

NAME

paragraph (there is also an earlier, +// plain fw-bold-but-no-color- lookalike on the page -- see dayNamePRe -- +// which must not match instead), and Colour comes from the page's "Kolor +// szat: " line, mapped via modernColours (case-insensitive; unknown +// word -> ""). Season is always "" -- the modern lectionary folds its +// temporal context into Name on temporal days rather than carrying it +// separately. A page whose markup doesn't match either pattern (a layout +// change, or a fixture with neither) yields a zero DayInfo, never an error: +// the readings are the load-bearing content, the header is a nice-to-have. +func ParseDayInfo(pageHTML string) DayInfo { + var info DayInfo + + for _, m := range dayNamePRe.FindAllStringSubmatch(pageHTML, -1) { + class := m[1] + if strings.Contains(class, "fw-bold") && strings.Contains(class, "color-") { + info.Name = strings.Join(htmlToLines(m[2]), " ") + break + } + } + + if m := dayColourRe.FindStringSubmatch(pageHTML); m != nil { + info.Colour = modernColours[strings.ToLower(m[1])] + } + + return info +} + // partID assigns the stable liturgical-part identifier for a section heading. // A second "1. czytanie" heading on the same day (a split feast offering two // alternative first readings) becomes "drugie_czytanie" instead of colliding -- cgit v1.3