diff options
Diffstat (limited to 'internal')
40 files changed, 390 insertions, 7887 deletions
diff --git a/internal/bible/convert.go b/internal/bible/convert.go index e7d5944..6b9a663 100644 --- a/internal/bible/convert.go +++ b/internal/bible/convert.go @@ -1,128 +1,15 @@ package bible -import ( - "fmt" - "regexp" - "sort" - "strconv" - "strings" - - "github.com/lukaszkasprzak/lectio/internal/psalter" -) - -// polishToEn maps Polish Biblical abbreviations to the book name accepted by -// the kjv-family tools. Gospels use the short forms (Mat/Mark/Luke/John); -// other books use full names that the tools resolve by unique prefix. -// Ported verbatim from ewangelia.py POLISH_TO_EN. -var polishToEn = map[string]string{ - // Old Testament - "Rdz": "Genesis", "Wj": "Exodus", "Kpł": "Leviticus", "Lb": "Numbers", - "Pwt": "Deuteronomy", "Joz": "Joshua", "Sdz": "Judges", "Rt": "Ruth", - "1 Sm": "1 Samuel", "2 Sm": "2 Samuel", "1 Krl": "1 Kings", "2 Krl": "2 Kings", - "1 Krn": "1 Chronicles", "2 Krn": "2 Chronicles", "Ezd": "Ezra", - "Ne": "Nehemiah", "Tb": "Tobit", "Jdt": "Judith", "Est": "Esther", - "1 Mch": "1 Maccabees", "2 Mch": "2 Maccabees", "Hi": "Job", "Ps": "Psalms", - "Prz": "Proverbs", "Koh": "Ecclesiastes", "Pnp": "Song of Solomon", - "Mdr": "Wisdom", "Syr": "Sirach", "Iz": "Isaiah", "Jr": "Jeremiah", - "Lm": "Lamentations", "Ba": "Baruch", "Ez": "Ezekiel", "Dn": "Daniel", - "Oz": "Hosea", "Jl": "Joel", "Am": "Amos", "Ab": "Obadiah", "Jon": "Jonah", - "Mi": "Micah", "Na": "Nahum", "Ha": "Habakkuk", "So": "Zephaniah", - "Ag": "Haggai", "Za": "Zechariah", "Ml": "Malachi", - // New Testament - "Mt": "Mat", "Mk": "Mark", "Łk": "Luke", "J": "John", "Dz": "Acts", - "Rz": "Romans", "1 Kor": "1 Corinthians", "2 Kor": "2 Corinthians", - "Ga": "Galatians", "Ef": "Ephesians", "Flp": "Philippians", - "Kol": "Colossians", "1 Tes": "1 Thessalonians", "2 Tes": "2 Thessalonians", - "1 Tm": "1 Timothy", "2 Tm": "2 Timothy", "Tt": "Titus", "Flm": "Philemon", - "Hbr": "Hebrews", "Jk": "James", "1 P": "1 Peter", "2 P": "2 Peter", - "1 J": "1 John", "2 J": "2 John", "3 J": "3 John", "Jud": "Jude", - "Ap": "Revelation", -} +import "regexp" +// Shared citation-normalisation regexes used by the book table (normalizeSigla) +// and the Ordinary Form reference renumbering (OFRef). The niedziela.pl Polish +// citation converter that once lived here (ToEnglishRef) was removed with the +// scraper: readings are now authored in English-canonical form. var ( - porRe = regexp.MustCompile(`(?i)^\s*por\.\s*`) - refrainRe = regexp.MustCompile(`\s*\(R\.:.*$`) - wsRe = regexp.MustCompile(`\s+`) iRe = regexp.MustCompile(`\s+i\s+`) dashRe = regexp.MustCompile(`\s*[-–—]\s*`) verseLetterRe = regexp.MustCompile(`(\d)[a-c]\b`) bookDotRe = regexp.MustCompile(`(\p{L})\.`) // abbreviation dot after a letter ("Cor." -> "Cor") - psalmRestRe = regexp.MustCompile(`(\d+)(?:\s*\((\d+)\))?(.*)$`) digitsRe = regexp.MustCompile(`\d+`) ) - -// polishBookKeys holds the POLISH_TO_EN keys sorted longest-first, matching -// the Python `sorted(POLISH_TO_EN, key=len, reverse=True)` traversal order. -var polishBookKeys = sortedPolishBookKeys() - -func sortedPolishBookKeys() []string { - keys := make([]string, 0, len(polishToEn)) - for k := range polishToEn { - keys = append(keys, k) - } - sort.SliceStable(keys, func(i, j int) bool { return len(keys[i]) > len(keys[j]) }) - return keys -} - -// psalmRef maps the psalm citation body ("63 (62), 2. 3-4. ...") to the target Psalter. -func psalmRef(rest, system string) string { - m := psalmRestRe.FindStringSubmatch(rest) - if m == nil { - return rest - } - heb, _ := strconv.Atoi(m[1]) - tail := m[3] - if system == "vulgate" { - ch := m[1] - if m[2] != "" { - ch = m[2] - } - return ch + tail - } - if system == "drb" { - tail = digitsRe.ReplaceAllStringFunc(tail, func(s string) string { - n, _ := strconv.Atoi(s) - return strconv.Itoa(psalter.DrbVerse(heb, n)) - }) - } - return strconv.Itoa(heb) + tail -} - -// ToEnglishRef converts a Polish citation to kjv-tool style: "Mt 7, 1-5" -> "Mat 7:1-5". -// -// Handles the extra apparatus of non-gospel readings: a leading "por." (compare) -// marker, a trailing "(R.: ...)" responsorial refrain, and psalm versification. -// system selects the target Psalter: "vulgate" (vul/grb/wuj) uses the citation's -// Vulgate chapter (62 of "63 (62)"); "drb" uses the Hebrew chapter (63) with the -// DRB title-fold verse shift; other values use the Hebrew chapter unshifted. -func ToEnglishRef(plRef, system string) (string, error) { - plRef = porRe.ReplaceAllString(plRef, "") // 'compare' marker - plRef = refrainRe.ReplaceAllString(plRef, "") // responsorial refrain - plRef = wsRe.ReplaceAllString(strings.TrimSpace(plRef), " ") - - var book string - found := false - for _, k := range polishBookKeys { - if plRef == k || strings.HasPrefix(plRef, k+" ") { - book = k - found = true - break - } - } - if !found { - return "", fmt.Errorf("unknown book in reference: %q", plRef) - } - - rest := strings.TrimSpace(plRef[len(book):]) - if polishToEn[book] == "Psalms" { - rest = psalmRef(rest, system) - } - rest = strings.ReplaceAll(rest, ", ", ":") // chapter/verse separator - rest = strings.ReplaceAll(rest, ". ", ",") // disjoint verse groups - rest = iRe.ReplaceAllString(rest, ",") // Polish 'and' - rest = dashRe.ReplaceAllString(rest, "-") // normalise ranges - rest = verseLetterRe.ReplaceAllString(rest, "$1") // drop verse-part letters (15a -> 15) - rest = strings.ReplaceAll(rest, " ", "") - - return strings.TrimSpace(fmt.Sprintf("%s %s", polishToEn[book], rest)), nil -} diff --git a/internal/bible/convert_test.go b/internal/bible/convert_test.go deleted file mode 100644 index 6f16c89..0000000 --- a/internal/bible/convert_test.go +++ /dev/null @@ -1,19 +0,0 @@ -package bible - -import "testing" - -func TestToEnglishRef(t *testing.T) { - cases := []struct{ in, system, want string }{ - {"Mt 7, 1-5", "vulgate", "Mat 7:1-5"}, - {"J 20, 1. 11-18", "vulgate", "John 20:1,11-18"}, - {"por. J 20, 11", "vulgate", "John 20:11"}, - {"Ps 63 (62), 2. 3-4. 5-6. 8-9 (R.: por. 2ab)", "vulgate", "Psalms 62:2,3-4,5-6,8-9"}, - {"Ps 63 (62), 2. 3-4. 5-6. 8-9 (R.: por. 2ab)", "drb", "Psalms 63:1,2-3,4-5,7-8"}, - } - for _, c := range cases { - got, err := ToEnglishRef(c.in, c.system) - if err != nil || got != c.want { - t.Errorf("ToEnglishRef(%q,%q)=%q,%v want %q", c.in, c.system, got, err, c.want) - } - } -} diff --git a/internal/bible/ofref_test.go b/internal/bible/ofref_test.go index fae593a..4b9cb1e 100644 --- a/internal/bible/ofref_test.go +++ b/internal/bible/ofref_test.go @@ -20,10 +20,10 @@ func TestOFRef(t *testing.T) { {"ps27-hebrew", "Psalms 27:1,4,13-14", "hebrew", "Psalms 27:1,4,13-14"}, // Boundary cases of HebrewToVulgateChapter. - {"ps8-vulgate", "Psalms 8:2", "vulgate", "Psalms 8:2"}, // <=8 unchanged - {"ps9-vulgate", "Psalms 9:2", "vulgate", "Psalms 9:2"}, // 9,10 -> 9 - {"ps10-vulgate", "Psalms 10:1", "vulgate", "Psalms 9:1"}, // 10 -> 9 - {"ps11-vulgate", "Psalms 11:1", "vulgate", "Psalms 10:1"}, // 11..113 -> h-1 + {"ps8-vulgate", "Psalms 8:2", "vulgate", "Psalms 8:2"}, // <=8 unchanged + {"ps9-vulgate", "Psalms 9:2", "vulgate", "Psalms 9:2"}, // 9,10 -> 9 + {"ps10-vulgate", "Psalms 10:1", "vulgate", "Psalms 9:1"}, // 10 -> 9 + {"ps11-vulgate", "Psalms 11:1", "vulgate", "Psalms 10:1"}, // 11..113 -> h-1 {"ps116-vulgate", "Psalms 116:12", "vulgate", "Psalms 114:12"}, {"ps147-vulgate", "Psalms 147:12", "vulgate", "Psalms 146:12"}, {"ps148-vulgate", "Psalms 148:1", "vulgate", "Psalms 148:1"}, // >=148 unchanged diff --git a/internal/cli/cli.go b/internal/cli/cli.go index d671c91..c4f063d 100644 --- a/internal/cli/cli.go +++ b/internal/cli/cli.go @@ -1,6 +1,6 @@ // Package cli is lectio's flag-driven command dispatcher: it wires config, -// the readings router, liturgy.Harvest and render together into the -// `lectio` binary's Run entry point. +// the offline readings engine and render together into the `lectio` binary's +// Run entry point. package cli import ( @@ -21,7 +21,6 @@ import ( "github.com/lukaszkasprzak/lectio/internal/liturgy" "github.com/lukaszkasprzak/lectio/internal/readings" "github.com/lukaszkasprzak/lectio/internal/render" - "github.com/lukaszkasprzak/lectio/internal/tradlit" ) const helpText = `lectio — daily Catholic liturgy readings (Polish + 4 versions) @@ -31,18 +30,13 @@ Usage: Flags: -a, --all all readings, not just the gospel - -b, --bible VER one version's text: bt,wuj,vul,grb,drb + -b, --bible VER one version's text: wuj,vul,grb,drb -c, --compare LIST versions side by side (comma-separated) -p, --ref REF look up a passage (e.g. "J 3:16") with -b/-c -r, --raw text only, no banner/headings (for piping) -w, --width N wrap width; 0 = detect terminal - -R, --refresh ignore cache, re-download - -o, --offline cache/sigla only, no network -l, --lectionary WHICH new|trad (trad -> traditional) - -g, --lang LANG traditional lectionary language: pl|en --ui-lang LANG override interface/export language: pl|en - -u, --update harvest sigla maximally to the horizon (idempotent) - -C, --clean prune cached readings older than a year -P, --pager page reading output (like git); default from config --no-pager never page, even if config sets one --list list all books + abbreviations (dialect from sigla_style) @@ -54,8 +48,7 @@ Flags: --corpus-check X validate a bible corpus (code, e.g. drb, or a path to a <code>.tsv) and exit; errors fail, coverage gaps warn --json with --corpus-check, print the report as JSON - --rand, --rand-v print a random verse and exit (uses default_version or -b VER; - bt has no corpus, so it falls back to a corpus version) + --rand, --rand-v print a random verse and exit (uses default_version or -b VER) --rand-ch print a random chapter and exit --md export the readings as Markdown (to --out or stdout) --pdf export the readings as PDF (to --out or stdout) @@ -69,16 +62,14 @@ Flags: -v, --version print the version and exit -h, --help this help -Versions: bt (Biblia Tysiąclecia) wuj (Wujek) vul (Wulgata) grb (Grecki) - drb (Douay-Rheims) +Versions: wuj (Wujek) vul (Wulgata) grb (Grecki) drb (Douay-Rheims) Examples: lectio today's gospel lectio 2026-07-22 -a all readings for a date - lectio -c bt,wuj 2026-07-22 compare two versions for a date + lectio -c wuj,drb 2026-07-22 compare two versions for a date lectio -b vul -a Vulgate text, all readings lectio -l trad -a traditional lectionary, all readings - lectio -u harvest sigla to the horizon lectio -p "Jn 3:16" -b vul look up a passage (English sigla) lectio -p "J 3,16" -c wuj,drb Polish sigla when sigla_style=polish/auto+pl UI lectio --list list every book + abbreviations @@ -86,8 +77,8 @@ Examples: lectio --week 2026-07-22 a week of gospel references from a date lectio --rand-v a random verse (for cron/prompt) -Flags override config. Exit codes: 0 ok, 1 runtime error (fetch/parse), -2 usage error (bad flag, bad date, bad version, bad --lectionary/--lang). +Flags override config. Exit codes: 0 ok, 1 runtime error, 2 usage error +(bad flag, bad date, bad version, bad --lectionary). ` const ( @@ -122,11 +113,11 @@ func Run(args []string, stdin io.Reader, stdout, stderr io.Writer) int { return 2 } - var all, raw, refresh, offline, update, clean, pagerFlag, noPager, citation, week bool + var all, raw, pagerFlag, noPager, citation, week bool var randV, randCh bool var expMD, expPDF bool var output, calendar, uiLang string - var bibleVer, compareList, lectionary, lang string + var bibleVer, compareList, lectionary string var width int var list bool var ref string @@ -142,27 +133,17 @@ func Run(args []string, stdin io.Reader, stdout, stderr io.Writer) int { fs.BoolVar(&all, "a", false, "all readings, not just the gospel") fs.BoolVar(&all, "all", false, "all readings, not just the gospel") - fs.StringVar(&bibleVer, "b", "", "one version's text: bt,wuj,vul,grb,drb") - fs.StringVar(&bibleVer, "bible", "", "one version's text: bt,wuj,vul,grb,drb") + fs.StringVar(&bibleVer, "b", "", "one version's text: wuj,vul,grb,drb") + fs.StringVar(&bibleVer, "bible", "", "one version's text: wuj,vul,grb,drb") fs.StringVar(&compareList, "c", "", "versions side by side (comma list)") fs.StringVar(&compareList, "compare", "", "versions side by side (comma list)") fs.BoolVar(&raw, "r", false, "text only, no banner/headings") fs.BoolVar(&raw, "raw", false, "text only, no banner/headings") fs.IntVar(&width, "w", 0, "wrap width (0 = detect terminal)") fs.IntVar(&width, "width", 0, "wrap width (0 = detect terminal)") - fs.BoolVar(&refresh, "R", false, "ignore cache, re-download") - fs.BoolVar(&refresh, "refresh", false, "ignore cache, re-download") - fs.BoolVar(&offline, "o", false, "cache/sigla only, no network") - fs.BoolVar(&offline, "offline", false, "cache/sigla only, no network") fs.StringVar(&lectionary, "l", "", "new|trad") fs.StringVar(&lectionary, "lectionary", "", "new|trad") - fs.StringVar(&lang, "g", "", "pl|en") - fs.StringVar(&lang, "lang", "", "pl|en") fs.StringVar(&uiLang, "ui-lang", "", "override interface/export language: pl|en") - fs.BoolVar(&update, "u", false, "harvest sigla maximally to the horizon") - fs.BoolVar(&update, "update", false, "harvest sigla maximally to the horizon") - fs.BoolVar(&clean, "C", false, "prune cached readings older than a year") - fs.BoolVar(&clean, "clean", false, "prune cached readings older than a year") fs.BoolVar(&pagerFlag, "P", false, "page reading output (like git)") fs.BoolVar(&pagerFlag, "pager", false, "page reading output (like git)") fs.BoolVar(&noPager, "no-pager", false, "never page, even if config sets one") @@ -204,17 +185,6 @@ func Run(args []string, stdin io.Reader, stdout, stderr io.Writer) int { fmt.Fprintln(stderr, "lectio:", err) return 2 } - if lang != "" && lang != "pl" && lang != "en" { - fmt.Fprintf(stderr, "lectio: invalid --lang %q (want pl|en)\n", lang) - return 2 - } - - if clean { - return runClean(stdout, stderr) - } - if update { - return runHarvest(date, stdout, stderr) - } if calNew != "" { return runCalNew(calNew, stdout, stderr) } @@ -233,15 +203,9 @@ func Run(args []string, stdin io.Reader, stdout, stderr io.Writer) int { if dir, err := config.CorporaDir(); err == nil { bible.SetUserCorporaDir(dir) } - if offline { - cfg.Offline = true - } if lectionary != "" { cfg.Lectionary = lectionary } - if lang != "" { - cfg.TraditionalLang = lang - } if uiLang != "" { cfg.UILanguage = config.NormalizeUILanguage(uiLang) } @@ -265,9 +229,9 @@ func Run(args []string, stdin io.Reader, stdout, stderr io.Writer) int { } return runRand(cfg, tbl, ver, randCh, raw, width, stdout, stderr) case citation: - return runCitation(cfg, tbl, date, refresh, stdout, stderr) + return runCitation(cfg, tbl, date, stdout, stderr) default: - return runWeek(cfg, tbl, date, refresh, stdout, stderr) + return runWeek(cfg, tbl, date, stdout, stderr) } } @@ -279,10 +243,10 @@ func Run(args []string, stdin io.Reader, stdout, stderr io.Writer) int { ver = cfg.DefaultVersion } if !config.ValidVersion(ver) { - fmt.Fprintf(stderr, "lectio: unknown version %q (want one of bt, wuj, vul, grb, drb)\n", ver) + fmt.Fprintf(stderr, "lectio: unknown version %q (want one of wuj, vul, grb, drb)\n", ver) return 2 } - return runExport(cfg, date, ver, effAll, refresh, expPDF, output, stdout, stderr) + return runExport(cfg, date, ver, effAll, expPDF, output, stdout, stderr) } if calendar != "" { return runCalendar(cfg, calendar, output, stdout, stderr) @@ -313,13 +277,13 @@ func Run(args []string, stdin io.Reader, stdout, stderr io.Writer) int { // Day-reading paths: bt is a valid version here (compareList wins over // bibleVer, as before, so bibleVer is left unvalidated when a list is given). if bibleVer != "" && compareList == "" && !config.ValidVersion(bibleVer) { - fmt.Fprintf(stderr, "lectio: unknown version %q (want one of bt, wuj, vul, grb, drb)\n", bibleVer) + fmt.Fprintf(stderr, "lectio: unknown version %q (want one of wuj, vul, grb, drb)\n", bibleVer) return 2 } if compareList != "" { for _, v := range strings.Split(compareList, ",") { if v = strings.TrimSpace(v); v != "" && !config.ValidVersion(v) { - fmt.Fprintf(stderr, "lectio: unknown version %q (want one of bt, wuj, vul, grb, drb)\n", v) + fmt.Fprintf(stderr, "lectio: unknown version %q (want one of wuj, vul, grb, drb)\n", v) return 2 } } @@ -351,11 +315,11 @@ func Run(args []string, stdin io.Reader, stdout, stderr io.Writer) int { case ref != "": code = lookupRef(cfg, bookTbl, ref, refVersions, raw, effWidth, out, stderr) case compareList != "": - code = renderCompare(cfg, compareList, date, effAll, raw, effWidth, refresh, out, stderr) + code = renderCompare(cfg, compareList, date, effAll, raw, effWidth, out, stderr) case bibleVer != "": - code = fetchAndPrint(cfg, bibleVer, date, effAll, raw, effWidth, refresh, out, stderr) + code = fetchAndPrint(cfg, bibleVer, date, effAll, raw, effWidth, out, stderr) default: - code = fetchAndPrint(cfg, cfg.DefaultVersion, date, effAll, raw, effWidth, refresh, out, stderr) + code = fetchAndPrint(cfg, cfg.DefaultVersion, date, effAll, raw, effWidth, out, stderr) } finish() return code @@ -389,24 +353,19 @@ func gospelCitation(sec liturgy.Section) string { return "" } -// dialectCitation renders a gospel section's reference in the configured sigla -// dialect (cfg.SiglaLang(): sigla_style, or -- "auto" -- ui_language). The -// source citation's language is the lectionary's: Polish for the modern -// (niedziela) lectionary, cfg.TraditionalLang for the traditional one. The ref -// is parsed to canonical and re-rendered in the target dialect; a citation -// whose book can't be parsed comes back in its source form unchanged. +// dialectCitation returns a gospel section's reference for display. The offline +// loader already renders Section.Citation in the reader's configured sigla +// dialect (see readings.citationForms), so this just returns it (cfg and tbl are +// kept for signature compatibility with the callers). func dialectCitation(cfg config.Config, tbl *bible.BookTable, sec liturgy.Section) string { - // The offline loader already rendered Citation in the reader's sigla dialect - // (see readings.citationForms), so the gospel reference is shown as-is. return gospelCitation(sec) } -// runExport handles --md/--pdf: load the day's readings and write them as -// Markdown or PDF to --out FILE (or stdout). Honors date/lectionary/all/offline -// and the version (bt is fine -- it is the niedziela text -- but is swapped for -// traditional/offline via EffectiveVersions). -func runExport(cfg config.Config, date, version string, all, refresh, asPDF bool, output string, stdout, stderr io.Writer) int { - secs, info, err := readings.Load(cfg, readings.Options{Date: date, Refresh: refresh, Offline: cfg.Offline, All: all}) +// runExport handles --md/--pdf: compute the day's readings offline and write +// them as Markdown or PDF to --out FILE (or stdout). Honors date/lectionary/all +// and the version. +func runExport(cfg config.Config, date, version string, all, asPDF bool, output string, stdout, stderr io.Writer) int { + secs, info, err := readings.Load(cfg, readings.Options{Date: date, All: all}) if err != nil { fmt.Fprintln(stderr, "lectio:", err) return 1 @@ -456,7 +415,7 @@ func runCalendar(cfg config.Config, ym, output string, stdout, stderr io.Writer) var days []export.CalendarDay for d := first; int(d.Month()) == month; d = d.AddDate(0, 0, 1) { cd := export.CalendarDay{Day: d.Day()} - if secs, info, lerr := readings.Load(cfg, readings.Options{Date: d.Format("2006-01-02"), Offline: cfg.Offline, All: false}); lerr == nil { + if secs, info, lerr := readings.Load(cfg, readings.Options{Date: d.Format("2006-01-02"), All: false}); lerr == nil { cd.Name = info.Name cd.Colour = info.Colour cd.Citation = readings.GospelCitation(secs) @@ -485,8 +444,8 @@ func runCalendar(cfg config.Config, ym, output string, stdout, stderr io.Writer) // dialectCitation), for scripts/cron/prompt use. Honors the resolved cfg // (lectionary/lang/offline) and date. Exit 1 if the day has no gospel // reference (unpublished date, no network while offline, ...). -func runCitation(cfg config.Config, tbl *bible.BookTable, date string, refresh bool, stdout, stderr io.Writer) int { - secs, _, err := readings.Load(cfg, readings.Options{Date: date, Refresh: refresh, Offline: cfg.Offline, All: false}) +func runCitation(cfg config.Config, tbl *bible.BookTable, date string, stdout, stderr io.Writer) int { + secs, _, err := readings.Load(cfg, readings.Options{Date: date, All: false}) if err != nil { fmt.Fprintln(stderr, "lectio:", err) return 1 @@ -510,7 +469,7 @@ func runCitation(cfg config.Config, tbl *bible.BookTable, date string, refresh b // can't be loaded (unpublished, offline gap, no gospel) shows "—" rather than // aborting the run, so the list is always seven lines. Honors cfg // (lectionary/lang/offline). -func runWeek(cfg config.Config, tbl *bible.BookTable, date string, refresh bool, stdout, stderr io.Writer) int { +func runWeek(cfg config.Config, tbl *bible.BookTable, date string, stdout, stderr io.Writer) int { start, err := time.Parse("2006-01-02", date) if err != nil { fmt.Fprintln(stderr, "lectio:", err) @@ -519,7 +478,7 @@ func runWeek(cfg config.Config, tbl *bible.BookTable, date string, refresh bool, for i := 0; i < 7; i++ { d := start.AddDate(0, 0, i).Format("2006-01-02") cit := "—" - secs, _, err := readings.Load(cfg, readings.Options{Date: d, Refresh: refresh, Offline: cfg.Offline, All: false}) + secs, _, err := readings.Load(cfg, readings.Options{Date: d, All: false}) if err == nil { if sec, ok := gospelSection(secs); ok { if c := dialectCitation(cfg, tbl, sec); c != "" { @@ -618,116 +577,11 @@ func normalizeLectionary(lectionary string) (string, error) { return v, nil } -// runHarvest handles -u/--update: harvest sigla maximally (to the -// unpublished horizon) from date for the modern lectionary, printing the -// outcome or -- on a genuine interruption (see liturgy.Harvest) -- the -// error. On a successful harvest it also best-effort pre-caches the -// traditional lectionary's propers (internal/tradlit) for every date in -// that same [date, furthest] window, so 'lectio update' prepares both -// lectionaries for offline use in one run. The 1962 calendar has no -// "unpublished horizon" (every date has propers), so this is a plain -// date-range fetch; a per-date failure is not fatal here -- it never -// prevented the traditional lectionary from working live before, and the -// modern-harvest outcome is still reported either way. -func runHarvest(date string, stdout, stderr io.Writer) int { - added, furthest, err := liturgy.Harvest(date, 0) - if err != nil { - fmt.Fprintln(stderr, "lectio:", err) - return 1 - } - - lang := config.Default().TraditionalLang - cachedTrad := 0 - if furthest != "" { - if cfg, cfgErr := config.Load(); cfgErr == nil { - lang = cfg.TraditionalLang - cachedTrad = cacheTraditionalRange(date, furthest, lang) - } - } - - fmt.Fprintf(stdout, "harvested %d day(s), furthest %s; cached traditional propers (%s) for %d day(s)\n", - added, furthest, lang, cachedTrad) - return 0 -} - -// cacheTraditionalRange best-effort pre-caches tradlit's traditional propers -// for lang for every date in [from, to] inclusive (walking forward a day at -// a time), returning how many dates succeeded. A per-date failure (e.g. a -// transient network hiccup) is ignored -- the traditional 1962 calendar has -// propers for every date, so there is no "unpublished horizon" to stop at -// the way liturgy.Harvest has for the modern lectionary. -func cacheTraditionalRange(from, to, lang string) int { - start, err := time.Parse("2006-01-02", from) - if err != nil { - return 0 - } - end, err := time.Parse("2006-01-02", to) - if err != nil { - return 0 - } - - cached := 0 - for d := start; !d.After(end); d = d.AddDate(0, 0, 1) { - if _, _, err := tradlit.Load(d.Format("2006-01-02"), lang, false); err == nil { - cached++ - } - } - return cached -} - -// runClean handles -C/--clean: prune cached readings older than one year -// (relative to today()) and print a human-readable summary of what was -// removed. Like -u/--update, this is a maintenance mode -- it ignores DATE -// and every render flag, and is dispatched before the render paths. If both -// --clean and -u/--update are given, --clean takes precedence (see Run). -func runClean(stdout, stderr io.Writer) int { - now, err := time.Parse("2006-01-02", today()) - if err != nil { - fmt.Fprintln(stderr, "lectio:", err) - return 1 - } - before := now.AddDate(-1, 0, 0) - - removed, freed, err := liturgy.CleanCache(before) - if err != nil { - fmt.Fprintln(stderr, "lectio:", err) - return 1 - } - - cutoff := before.Format("2006-01-02") - if removed == 0 { - fmt.Fprintf(stdout, "cache already clean (nothing older than %s)\n", cutoff) - return 0 - } - entries := "entries" - if removed == 1 { - entries = "entry" - } - fmt.Fprintf(stdout, "cleaned %d cache %s older than %s (freed %s)\n", removed, entries, cutoff, formatFreed(freed)) - return 0 -} - -// formatFreed renders a byte count the way -C/--clean's summary line wants -// it: megabytes with one decimal once it's a meaningful size, kilobytes -// (also one decimal) for anything smaller. -func formatFreed(bytes int64) string { - const mb = 1024 * 1024 - if bytes >= mb { - return fmt.Sprintf("%.1f MB", float64(bytes)/mb) - } - return fmt.Sprintf("%.1f KB", float64(bytes)/1024) -} - // fetchAndPrint is the shared single-version render path (default version or -// -b/--bible): fetch via the readings router, apply the offline version -// swap, then render each section's heading and render.GatherVersion blocks. -func fetchAndPrint(cfg config.Config, version, date string, all, raw bool, width int, refresh bool, stdout, stderr io.Writer) int { - secs, dayInfo, err := readings.Load(cfg, readings.Options{ - Date: date, - Refresh: refresh, - Offline: cfg.Offline, - All: all, - }) +// -b/--bible): compute the day's readings offline, resolve the reading corpus, +// then render each section's heading and render.GatherVersion blocks. +func fetchAndPrint(cfg config.Config, version, date string, all, raw bool, width int, stdout, stderr io.Writer) int { + secs, dayInfo, err := readings.Load(cfg, readings.Options{Date: date, All: all}) if err != nil { fmt.Fprintln(stderr, "lectio:", err) return 1 @@ -823,7 +677,7 @@ func renderSection(sec liturgy.Section, version, lectionary, lang string, width // renderCompare handles -c/--compare LIST: LIST is a comma-separated list of // version codes (falling back to cfg.Versions when empty), rendered side by // side via render.Compare. -func renderCompare(cfg config.Config, list, date string, all, raw bool, width int, refresh bool, stdout, stderr io.Writer) int { +func renderCompare(cfg config.Config, list, date string, all, raw bool, width int, stdout, stderr io.Writer) int { var versions []string if list == "" { versions = append(versions, cfg.Versions...) @@ -838,18 +692,13 @@ func renderCompare(cfg config.Config, list, date string, all, raw bool, width in } for _, v := range versions { if !config.ValidVersion(v) { - fmt.Fprintf(stderr, "lectio: unknown version %q (want one of bt, wuj, vul, grb, drb)\n", v) + fmt.Fprintf(stderr, "lectio: unknown version %q (want one of wuj, vul, grb, drb)\n", v) return 2 } } versions = render.EffectiveVersions(versions, cfg.Lectionary, cfg.Offline) - secs, dayInfo, err := readings.Load(cfg, readings.Options{ - Date: date, - Refresh: refresh, - Offline: cfg.Offline, - All: all, - }) + secs, dayInfo, err := readings.Load(cfg, readings.Options{Date: date, All: all}) if err != nil { fmt.Fprintln(stderr, "lectio:", err) return 1 @@ -873,18 +722,17 @@ func renderCompare(cfg config.Config, list, date string, all, raw bool, width in } // randVersion picks the corpus version for --rand: an explicit -b VER (any of -// the five is accepted), else the configured default_version. "bt" is allowed -// but has no embedded corpus (it is the niedziela.pl scrape), so it -- like an -// unset default -- transparently falls back to the first corpus version in -// cfg.Versions (else "wuj"), so --rand always yields a passage. Only an unknown -// version code is an error. +// the four is accepted), else the configured default_version. An unset default +// transparently falls back to the first corpus version in cfg.Versions (else +// "wuj"), so --rand always yields a passage. Only an unknown version code is an +// error. func randVersion(cfg config.Config, bibleVer string) (string, error) { v := bibleVer if v == "" { v = cfg.DefaultVersion } if v != "" && !config.ValidVersion(v) { - return "", fmt.Errorf("unknown version %q (want one of bt, wuj, vul, grb, drb)", v) + return "", fmt.Errorf("unknown version %q (want one of wuj, vul, grb, drb)", v) } if isCorpusVersion(v) { return v, nil @@ -953,14 +801,14 @@ func runRand(cfg config.Config, tbl *bible.BookTable, version string, chapter, r } // isCorpusVersion reports whether v is a scripture-text version with an -// embedded corpus (wuj/vul/grb/drb) -- i.e. a valid version that is not "bt" -// (the niedziela.pl scrape, which has no full text to look a passage up in). +// embedded corpus (wuj/vul/grb/drb) a passage can be looked up in. Every valid +// version now has a corpus, so this is exactly config.ValidVersion. func isCorpusVersion(v string) bool { - return config.ValidVersion(v) && v != "bt" + return config.ValidVersion(v) } // refLookupVersions resolves which corpus version(s) `--ref` should look a -// passage up in, rejecting "bt" (no corpus). Precedence: an explicit -c LIST, +// passage up in. Precedence: an explicit -c LIST, // then a single -b VER, then a sensible default (the configured default_version // if it has a corpus, else the first corpus version in cfg.Versions). It errors // (exit 2 in the caller) on any non-corpus version or if nothing usable is @@ -1003,10 +851,10 @@ func refLookupVersions(cfg config.Config, bibleVer, compareList string) ([]strin // in the resolved sigla dialect (bookTbl.ParseRef -- dialect-scoped book names // and number syntax) into an English colon-style reference, then reuses the // same render path as the readings with lectionary="traditional" (the ref is -// already in target form, looked up literally per version -- no niedziela -// conversion, no cross-version psalm renumbering). versions is the validated -// corpus set (never "bt"). raw omits the header. Exit 2 on an unparseable ref, -// exit 1 if no requested version has the passage. +// already in target form, looked up literally per version -- no cross-version +// psalm renumbering). versions is the validated corpus set. raw omits the +// header. Exit 2 on an unparseable ref, exit 1 if no requested version has the +// passage. func lookupRef(cfg config.Config, tbl *bible.BookTable, ref string, versions []string, raw bool, width int, stdout, stderr io.Writer) int { ref = strings.TrimSpace(ref) engRef, ok := tbl.ParseRef(cfg.SiglaLang(), ref) diff --git a/internal/cli/cli_test.go b/internal/cli/cli_test.go index 0e90a04..a244885 100644 --- a/internal/cli/cli_test.go +++ b/internal/cli/cli_test.go @@ -2,10 +2,6 @@ package cli import ( "bytes" - "net/http" - "net/http/httptest" - "os" - "path/filepath" "strings" "testing" @@ -65,8 +61,8 @@ func TestTwoDatesIsAmbiguous(t *testing.T) { } // TestUnknownVersion exercises -b/--bible's version-validation usage-error -// path without touching the network: the version code is checked against -// the five known codes before any fetch is attempted. +// path: the version code is checked against the known corpus codes before +// any reading is resolved. func TestUnknownVersion(t *testing.T) { t.Setenv("XDG_CONFIG_HOME", t.TempDir()) var out, errb bytes.Buffer @@ -104,14 +100,6 @@ func TestLectionaryBogus(t *testing.T) { } } -func TestLangBogus(t *testing.T) { - t.Setenv("XDG_CONFIG_HOME", t.TempDir()) - var out, errb bytes.Buffer - if code := Run([]string{"-g", "de"}, nil, &out, &errb); code != 2 { - t.Errorf("bogus lang code=%d want 2 (stderr=%q)", code, errb.String()) - } -} - // TestBannerForLang checks bannerFor's wording follows lang: pl reproduces // the pre-i18n Polish banner exactly ("Ewangelia na D" / "Czytania na D"), // en gives "Gospel for D" / "Readings for D". @@ -133,71 +121,9 @@ func TestBannerForLang(t *testing.T) { } } -// TestCleanEmptyCache exercises -C/--clean's dispatch as a maintenance mode: -// it must be handled before any render path (and before the network-hitting -// -u/--update path) is reached. Pointing XDG_CACHE_HOME at an empty temp dir -// keeps liturgy.CleanCache's directory-read hermetic (no network), and an -// empty dir exercises the "nothing to remove" branch of the summary line. -func TestCleanEmptyCache(t *testing.T) { - t.Setenv("XDG_CACHE_HOME", t.TempDir()) - var out, errb bytes.Buffer - code := Run([]string{"-C"}, nil, &out, &errb) - if code != 0 { - t.Fatalf("--clean code=%d want 0 (stderr=%q)", code, errb.String()) - } - if !strings.Contains(out.String(), "clean") { - t.Errorf("--clean stdout=%q, want a clean/nothing message", out.String()) - } -} - -// TestCleanRemovesOldEntries exercises the non-empty summary branch: a stale -// cache pair sitting in XDG_CACHE_HOME must be reported as removed, entirely -// via the filesystem (no network involved). -func TestCleanRemovesOldEntries(t *testing.T) { - dir := t.TempDir() - t.Setenv("XDG_CACHE_HOME", dir) - cacheDir := filepath.Join(dir, "lectio") - if err := os.MkdirAll(cacheDir, 0o755); err != nil { - t.Fatal(err) - } - if err := os.WriteFile(filepath.Join(cacheDir, "2020-01-01.html"), []byte("<html>old</html>"), 0o644); err != nil { - t.Fatal(err) - } - - var out, errb bytes.Buffer - code := Run([]string{"--clean"}, nil, &out, &errb) - if code != 0 { - t.Fatalf("--clean code=%d want 0 (stderr=%q)", code, errb.String()) - } - if !strings.Contains(out.String(), "cleaned 1 cache entry") { - t.Errorf("--clean stdout=%q, want a \"cleaned 1 cache entry\" message", out.String()) - } - if _, err := os.Stat(filepath.Join(cacheDir, "2020-01-01.html")); !os.IsNotExist(err) { - t.Errorf("2020-01-01.html still exists after --clean") - } -} - -// TestCleanPreferredOverUpdate exercises Run's stated precedence: when both -// --clean and -u/--update are given, --clean wins and -u's network-hitting -// harvest path is never reached (proven here by the empty-cache dir plus a -// zero exit code -- a network attempt against no test server would either -// hang or return an error/non-zero code). -func TestCleanPreferredOverUpdate(t *testing.T) { - t.Setenv("XDG_CACHE_HOME", t.TempDir()) - var out, errb bytes.Buffer - code := Run([]string{"--clean", "-u"}, nil, &out, &errb) - if code != 0 { - t.Fatalf("--clean -u code=%d want 0 (stderr=%q)", code, errb.String()) - } - if !strings.Contains(out.String(), "clean") { - t.Errorf("--clean -u stdout=%q, want a clean/nothing message", out.String()) - } -} - // TestDayInfoHeaderShown exercises fetchAndPrint's day-info header end to -// end (via Run against a fixture server, matching internal/readings' -// TestLoadModernRoutes): the day's celebration name appears above the -// banner for the default (non-raw) render, and is entirely absent from +// end (via Run, computed offline): the day's celebration name appears above +// the banner for the default (non-raw) render, and is entirely absent from // --raw output, which stays text-only for piping. func TestDayInfoHeaderShown(t *testing.T) { t.Setenv("XDG_CONFIG_HOME", t.TempDir()) @@ -381,15 +307,12 @@ func TestRandChapter(t *testing.T) { } } -func TestRandBTFallsBack(t *testing.T) { - // bt has no corpus but is accepted: --rand falls back to a corpus version - // and still prints a passage (exit 0), rather than erroring. +func TestRandRejectsBT(t *testing.T) { + // bt is no longer a valid version (its niedziela.pl corpus was retired), so + // --rand -b bt is a usage error, same as -p -b bt (see TestRefRejectsBT). var out, errb bytes.Buffer - if code := Run([]string{"--rand-v", "-b", "bt"}, nil, &out, &errb); code != 0 { - t.Errorf("rand -b bt code=%d want 0 (stderr=%q)", code, errb.String()) - } - if strings.TrimSpace(out.String()) == "" { - t.Errorf("rand -b bt produced no output") + if code := Run([]string{"--rand-v", "-b", "bt"}, nil, &out, &errb); code != 2 { + t.Errorf("rand -b bt code=%d want 2 (stderr=%q)", code, errb.String()) } } @@ -423,15 +346,10 @@ func TestGospelCitationHelpers(t *testing.T) { } } +// TestCitation exercises --citation end to end offline: the daily-readings +// engine computes the day's gospel with no network/cache, and the reference is +// printed in the configured sigla dialect. func TestCitation(t *testing.T) { - html, err := os.ReadFile("../liturgy/testdata/2026-07-22.html") - if err != nil { - t.Fatal(err) - } - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write(html) })) - defer srv.Close() - liturgy.SetBaseURL(srv.URL + "/liturgia/%s/Ewangelia") - t.Setenv("XDG_CACHE_HOME", t.TempDir()) t.Setenv("XDG_CONFIG_HOME", t.TempDir()) var out, errb bytes.Buffer @@ -439,22 +357,16 @@ func TestCitation(t *testing.T) { t.Fatalf("citation code=%d stderr=%q", code, errb.String()) } // Default config resolves to the English dialect (sigla_style auto + - // ui_language en), so the Polish source "J 20, 1. 11-18" is rendered as the - // English sigla "Jn 20:1,11-18". + // ui_language en); 2026-07-22 is St Mary Magdalene, gospel John 20:1-2,11-18, + // rendered as the English sigla "Jn 20:...". if s := strings.TrimSpace(out.String()); !strings.Contains(s, "Jn 20:") { t.Errorf("citation = %q, want English-dialect gospel ref 'Jn 20:...'", s) } } +// TestWeek exercises --week offline: seven days of gospel references starting +// at the given date, one line each, computed by the offline engine. func TestWeek(t *testing.T) { - html, err := os.ReadFile("../liturgy/testdata/2026-07-22.html") - if err != nil { - t.Fatal(err) - } - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write(html) })) - defer srv.Close() - liturgy.SetBaseURL(srv.URL + "/liturgia/%s/Ewangelia") - t.Setenv("XDG_CACHE_HOME", t.TempDir()) t.Setenv("XDG_CONFIG_HOME", t.TempDir()) var out, errb bytes.Buffer diff --git a/internal/cli/liturgy.go b/internal/cli/liturgy.go index aa3f97e..07a87bc 100644 --- a/internal/cli/liturgy.go +++ b/internal/cli/liturgy.go @@ -15,8 +15,9 @@ import ( ) // runLiturgy prints the computed liturgical day for date (default today) using -// the offline calendar engine, and exits. It is the engine's demo/validation -// surface; the daily-readings paths still use the scraper. +// the offline calendar engine, and exits. It shows the day's identity and +// resolved reading citations; the daily-readings paths render the same offline +// engine's readings as full text. func runLiturgy(cfg config.Config, date string, stdout, stderr io.Writer) int { if date == "" { date = today() diff --git a/internal/cli/pager_test.go b/internal/cli/pager_test.go index 3882162..4850e5e 100644 --- a/internal/cli/pager_test.go +++ b/internal/cli/pager_test.go @@ -97,7 +97,8 @@ func TestIsTerminalWriterBuffer(t *testing.T) { func TestPagerFlagDoesNotBreakBufferOutput(t *testing.T) { t.Setenv("XDG_CONFIG_HOME", t.TempDir()) var out, errb bytes.Buffer - code := Run([]string{"-P", "-o", "-l", "trad"}, nil, &out, &errb) + // (The former -o/--offline flag is gone: the daily view is always offline.) + code := Run([]string{"-P", "-l", "trad", "2026-07-22"}, nil, &out, &errb) if code != 0 && code != 1 { t.Fatalf("-P run code=%d (stderr=%q)", code, errb.String()) } diff --git a/internal/config/config.go b/internal/config/config.go index a9e00d1..31e9078 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -32,9 +32,8 @@ const configHeader = `# lectio configuration (INI). Full-line comments only (# o # # Allowed values: # lectionary new | traditional (new = modern OF; traditional = 1962 EF) -# traditional_lang pl | en (vernacular for traditional propers) -# versions any of: bt, wuj, vul, grb, drb (comma list; bt = Biblia Tysiąclecia) -# default_version bt | wuj | vul | grb | drb +# versions any of: wuj, vul, grb, drb (comma list) +# default_version wuj | vul | grb | drb # width integer; 0 = detect terminal width # all true | false (all readings, or just the gospel) # offline true | false (never fetch; cache/sigla only) @@ -46,7 +45,7 @@ const configHeader = `# lectio configuration (INI). Full-line comments only (# o # web_port integer; 0 = try 1099, then any free port # web_display horizontal | vertical | interlinear # web_mono true | false (monospace reading face in the web UI) -# web_versions any of: bt, wuj, vul, grb, drb (comma list); empty = just default_version +# web_versions any of: wuj, vul, grb, drb (comma list); empty = just default_version # pager shell command, e.g. less -R; empty = off # use calendar layers to stack over the universal calendar: names of # ~/.config/lectio/calendars/<name>.ini files (comma list, order = precedence) @@ -65,17 +64,18 @@ const configHeader = `# lectio configuration (INI). Full-line comments only (# o // -v/--version output (lectio, lectio-ui, lectio-web). const Version = "0.44.0" -// validVersions are the five scripture versions lectio understands. +// validVersions are the scripture versions lectio understands. All are +// embedded corpora; the former "bt" (the niedziela.pl modern scrape) is gone +// and a legacy config carrying it is migrated to "wuj" on load (see Load). var validVersions = map[string]bool{ - "bt": true, "wuj": true, "vul": true, "grb": true, "drb": true, } -// ValidVersion reports whether v is one of the five scripture versions -// lectio understands (bt, wuj, vul, grb, drb). +// ValidVersion reports whether v is one of the scripture versions lectio +// understands (wuj, vul, grb, drb). func ValidVersion(v string) bool { return validVersions[v] } @@ -150,25 +150,24 @@ func NormalizeSiglaStyle(s string) string { // Config holds lectio's user-configurable settings. The toml tags are used only // by the one-shot config.toml -> config.ini migration; the live format is INI. type Config struct { - SchemaVersion int `toml:"schema_version"` - Lectionary string `toml:"lectionary"` - TraditionalLang string `toml:"traditional_lang"` - Versions []string `toml:"versions"` - DefaultVersion string `toml:"default_version"` - Width int `toml:"width"` - All bool `toml:"all"` - Offline bool `toml:"offline"` - UILanguage string `toml:"ui_language"` - ReadingLang string `toml:"reading_lang"` - ReadingVersion string `toml:"reading_version"` - SiglaStyle string `toml:"sigla_style"` - WebTheme string `toml:"web_theme"` - WebPort int `toml:"web_port"` - WebDisplay string `toml:"web_display"` - WebMono bool `toml:"web_mono"` - WebVersions []string `toml:"web_versions"` - Pager string `toml:"pager"` - Parts map[string]map[string]bool `toml:"parts"` + SchemaVersion int `toml:"schema_version"` + Lectionary string `toml:"lectionary"` + Versions []string `toml:"versions"` + DefaultVersion string `toml:"default_version"` + Width int `toml:"width"` + All bool `toml:"all"` + Offline bool `toml:"offline"` + UILanguage string `toml:"ui_language"` + ReadingLang string `toml:"reading_lang"` + ReadingVersion string `toml:"reading_version"` + SiglaStyle string `toml:"sigla_style"` + WebTheme string `toml:"web_theme"` + WebPort int `toml:"web_port"` + WebDisplay string `toml:"web_display"` + WebMono bool `toml:"web_mono"` + WebVersions []string `toml:"web_versions"` + Pager string `toml:"pager"` + Parts map[string]map[string]bool `toml:"parts"` // Computed-calendar placement options (INI [calendar] section; INI-only). CalEpiphany string `toml:"-"` @@ -257,23 +256,22 @@ func (c Config) Selection() calendar.Selection { // is found and as the base that a partial config file overrides. func Default() Config { return Config{ - SchemaVersion: 1, - Lectionary: "new", - TraditionalLang: "pl", - Versions: []string{"bt", "wuj", "vul", "grb", "drb"}, - DefaultVersion: "bt", - Width: 0, - All: false, - Offline: false, - UILanguage: "en", - SiglaStyle: "auto", - WebTheme: "transfiguration", - WebPort: 0, - WebDisplay: "horizontal", - WebMono: false, - WebVersions: nil, - Pager: "", - Parts: nil, + SchemaVersion: 1, + Lectionary: "new", + Versions: []string{"wuj", "vul", "grb", "drb"}, + DefaultVersion: "vul", + Width: 0, + All: false, + Offline: false, + UILanguage: "en", + SiglaStyle: "auto", + WebTheme: "transfiguration", + WebPort: 0, + WebDisplay: "horizontal", + WebMono: false, + WebVersions: nil, + Pager: "", + Parts: nil, } } @@ -471,6 +469,45 @@ func normalize(cfg *Config) { cfg.WebDisplay = NormalizeDisplay(cfg.WebDisplay) cfg.UILanguage = NormalizeUILanguage(cfg.UILanguage) cfg.SiglaStyle = NormalizeSiglaStyle(cfg.SiglaStyle) + migrateBT(cfg) +} + +// migrateBT rewrites a legacy "bt" version (the retired niedziela.pl scrape, +// which had no embedded corpus) to "wuj" wherever a saved config still carries +// it, so an existing config keeps loading after bt was removed. In a version +// list "bt" becomes "wuj" only when "wuj" is not already present; otherwise it +// is dropped, so no list gains a duplicate column. +func migrateBT(cfg *Config) { + if cfg.DefaultVersion == "bt" { + cfg.DefaultVersion = "wuj" + } + cfg.Versions = migrateBTList(cfg.Versions) + cfg.WebVersions = migrateBTList(cfg.WebVersions) +} + +func migrateBTList(versions []string) []string { + if len(versions) == 0 { + return versions + } + hasWuj := false + for _, v := range versions { + if v == "wuj" { + hasWuj = true + break + } + } + out := make([]string, 0, len(versions)) + for _, v := range versions { + if v != "bt" { + out = append(out, v) + continue + } + if !hasWuj { + out = append(out, "wuj") + hasWuj = true + } + } + return out } // readINI parses INI bytes into a Config over Default(). Absent keys keep the @@ -520,8 +557,6 @@ func applyScalar(cfg *Config, key, val string) { cfg.SchemaVersion = atoiOr(val, cfg.SchemaVersion) case "lectionary": cfg.Lectionary = val - case "traditional_lang": - cfg.TraditionalLang = val case "versions": cfg.Versions = ini.List(val) case "default_version": @@ -569,20 +604,17 @@ func validate(cfg Config) error { if cfg.Lectionary != "new" && cfg.Lectionary != "traditional" { return fmt.Errorf("config: invalid lectionary %q (must be \"new\" or \"traditional\")", cfg.Lectionary) } - if cfg.TraditionalLang != "pl" && cfg.TraditionalLang != "en" { - return fmt.Errorf("config: invalid traditional_lang %q (must be \"pl\" or \"en\")", cfg.TraditionalLang) - } for _, v := range cfg.Versions { if !validVersions[v] { - return fmt.Errorf("config: invalid version %q in versions (must be one of bt, wuj, vul, grb, drb)", v) + return fmt.Errorf("config: invalid version %q in versions (must be one of wuj, vul, grb, drb)", v) } } if !validVersions[cfg.DefaultVersion] { - return fmt.Errorf("config: invalid default_version %q (must be one of bt, wuj, vul, grb, drb)", cfg.DefaultVersion) + return fmt.Errorf("config: invalid default_version %q (must be one of wuj, vul, grb, drb)", cfg.DefaultVersion) } for _, v := range cfg.WebVersions { if !validVersions[v] { - return fmt.Errorf("config: invalid version %q in web_versions (must be one of bt, wuj, vul, grb, drb)", v) + return fmt.Errorf("config: invalid version %q in web_versions (must be one of wuj, vul, grb, drb)", v) } } return nil @@ -613,7 +645,6 @@ func renderConfigINI(cfg Config) []byte { b.WriteString("\n") fmt.Fprintf(&b, "schema_version = %d\n", cfg.SchemaVersion) fmt.Fprintf(&b, "lectionary = %s\n", cfg.Lectionary) - fmt.Fprintf(&b, "traditional_lang = %s\n", cfg.TraditionalLang) fmt.Fprintf(&b, "versions = %s\n", strings.Join(cfg.Versions, ", ")) fmt.Fprintf(&b, "default_version = %s\n", cfg.DefaultVersion) fmt.Fprintf(&b, "width = %d\n", cfg.Width) diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 3830cb6..14823b8 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -13,9 +13,20 @@ func TestLoadSeeds(t *testing.T) { if err != nil { t.Fatal(err) } - if cfg.DefaultVersion != "bt" || cfg.Offline { + if cfg.DefaultVersion != "vul" || cfg.Offline { t.Errorf("defaults wrong: %+v", cfg) } + wantVersions := []string{"wuj", "vul", "grb", "drb"} + if len(cfg.Versions) != len(wantVersions) { + t.Errorf("versions default = %v, want %v", cfg.Versions, wantVersions) + } else { + for i, v := range wantVersions { + if cfg.Versions[i] != v { + t.Errorf("versions default = %v, want %v", cfg.Versions, wantVersions) + break + } + } + } if cfg.Lectionary != "new" { t.Errorf("lectionary default wrong: %+v", cfg) } @@ -24,6 +35,32 @@ func TestLoadSeeds(t *testing.T) { } } +// TestLoadMigratesBT checks a legacy config still carrying the retired "bt" +// version (both as default_version and in the versions list) loads and is +// migrated to wuj: bt is dropped from the list when wuj is already present +// (no duplicate column) and default_version bt becomes wuj. +func TestLoadMigratesBT(t *testing.T) { + dir := t.TempDir() + t.Setenv("LECTIO_CONFIG", filepath.Join(dir, "config.ini")) + os.WriteFile(filepath.Join(dir, "config.ini"), + []byte("default_version = bt\nversions = bt, wuj, vul\n"), 0o644) + cfg, err := Load() + if err != nil { + t.Fatal(err) + } + if cfg.DefaultVersion != "wuj" { + t.Errorf("default_version bt not migrated: %q", cfg.DefaultVersion) + } + for _, v := range cfg.Versions { + if v == "bt" { + t.Errorf("versions still carries bt: %v", cfg.Versions) + } + } + if len(cfg.Versions) != 2 || cfg.Versions[0] != "wuj" || cfg.Versions[1] != "vul" { + t.Errorf("versions after migration = %v, want [wuj vul]", cfg.Versions) + } +} + func TestLoadOverride(t *testing.T) { dir := t.TempDir() t.Setenv("XDG_CONFIG_HOME", dir) diff --git a/internal/export/export_test.go b/internal/export/export_test.go index 7f1c68d..5adf7d4 100644 --- a/internal/export/export_test.go +++ b/internal/export/export_test.go @@ -8,30 +8,37 @@ import ( "github.com/lukaszkasprzak/lectio/internal/liturgy" ) +// sampleSecs builds a reading section the offline way: the English-canonical +// lookup reference lives in Ref, the display citation stays in the reader's +// sigla dialect. render.GatherVersion resolves Ref against a real embedded +// corpus, so the exported document carries actual verse text. func sampleSecs() []liturgy.Section { return []liturgy.Section{{ - Heading: "Ewangelia (Mt 13, 1-9)", - Citation: "Mt 13, 1-9", - PartID: "ewangelia", - Paragraphs: [][]string{{"Owego dnia Jezus wyszedł z domu i usiadł nad jeziorem."}}, + Heading: "Ewangelia", + Citation: "J 20, 1. 11-18", + Ref: "John 20:1,11-18", + PartID: "ewangelia", }} } func TestMarkdownAndText(t *testing.T) { info := liturgy.DayInfo{Name: "Środa XV tygodnia", Colour: "green"} - md := Markdown("2026-07-22", info, sampleSecs(), "bt", "new", "en") - if !strings.Contains(md, "# Środa") || !strings.Contains(md, "## Gospel") || !strings.Contains(md, "Jezus wyszedł") { + // vul -> Vulgate Latin verse text, versified ("20:1 Una autem sabbati, + // Maria Magdalene ..."). + md := Markdown("2026-07-22", info, sampleSecs(), "vul", "new", "en") + if !strings.Contains(md, "# Środa") || !strings.Contains(md, "## Gospel") || + !strings.Contains(md, "20:1") || !strings.Contains(md, "Maria Magdalene") { t.Errorf("markdown:\n%s", md) } - txt := Text("2026-07-22", info, sampleSecs(), "bt", "new", "en") - if !strings.Contains(txt, "Jezus wyszedł") || !strings.Contains(txt, "Gospel") { + txt := Text("2026-07-22", info, sampleSecs(), "vul", "new", "en") + if !strings.Contains(txt, "Maria Magdalene") || !strings.Contains(txt, "Gospel") { t.Errorf("text:\n%s", txt) } } func TestReadingsPDF(t *testing.T) { info := liturgy.DayInfo{Name: "Środa XV tygodnia"} - pdf, err := ReadingsPDF("2026-07-22", info, sampleSecs(), "bt", "new", "en") + pdf, err := ReadingsPDF("2026-07-22", info, sampleSecs(), "vul", "new", "en") if err != nil { t.Fatal(err) } diff --git a/internal/i18n/i18n.go b/internal/i18n/i18n.go index 36aa288..f2221b6 100644 --- a/internal/i18n/i18n.go +++ b/internal/i18n/i18n.go @@ -8,7 +8,7 @@ package i18n // UI is one language's complete set of chrome strings. type UI struct { // Version names each bible version for column headers / prose, keyed by - // version code (bt, wuj, vul, grb, drb). + // version code (wuj, vul, grb, drb). Version map[string]string // PartLabel names each modern-lectionary section's heading label word, @@ -74,7 +74,7 @@ type UI struct { // Web /settings page labels (the ones without an existing shared field): // the saved confirmation, the config-field labels, and the save button. - WebSaved, WebTradLang, WebUILang, WebSiglaStyle, WebDefaultVersion string + WebSaved, WebUILang, WebSiglaStyle, WebDefaultVersion string WebVersions, WebWebVersions, WebOffline, WebWidth, WebPort, WebPager string WebSave string @@ -106,7 +106,6 @@ func Get(lang string) UI { var enUI = UI{ Version: map[string]string{ - "bt": "Biblia Tysiąclecia (niedziela.pl)", "wuj": "Wujek (Polish)", "vul": "Vulgate (Latin)", "grb": "Greek", @@ -119,11 +118,11 @@ var enUI = UI{ "aklamacja": "Acclamation", "ewangelia": "Gospel", }, - FooterKeys: "tab/⇧tab version ←/→ day d date j/k scroll space/b page g/G top/bottom r refresh q quit", + FooterKeys: "tab/⇧tab version ←/→ day d date j/k scroll space/b page g/G top/bottom q quit", Loading: "loading…", NoReadingsFor: "no readings for ", ErrorPrefix: "error: ", - ErrorHint: "change date (←/→) or refresh (r)", + ErrorHint: "change date (←/→)", JumpPrompt: "go to date (YYYY-MM-DD)", ReaderTitle: "reader — pick a book", ReaderPickKeys: "type to filter ↑/↓ move enter open esc quit", @@ -172,7 +171,6 @@ var enUI = UI{ WebNoBookmarks: "No bookmarks yet.", WebDelete: "delete", WebSaved: "Saved.", - WebTradLang: "traditional language", WebUILang: "UI language", WebSiglaStyle: "sigla style", WebDefaultVersion: "default version", @@ -194,7 +192,6 @@ var enUI = UI{ var plUI = UI{ Version: map[string]string{ - "bt": "Biblia Tysiąclecia (niedziela.pl)", "wuj": "Wujek (pol.)", "vul": "Wulgata (lac.)", "grb": "Grecki", @@ -207,11 +204,11 @@ var plUI = UI{ "aklamacja": "Aklamacja", "ewangelia": "Ewangelia", }, - FooterKeys: "tab/⇧tab wersja ←/→ dzień d data j/k przewiń spacja/b strona g/G góra/dół r odśwież q wyjście", + FooterKeys: "tab/⇧tab wersja ←/→ dzień d data j/k przewiń spacja/b strona g/G góra/dół q wyjście", Loading: "ładowanie…", NoReadingsFor: "brak czytań na ", ErrorPrefix: "błąd: ", - ErrorHint: "zmień datę (←/→) lub odśwież (r)", + ErrorHint: "zmień datę (←/→)", JumpPrompt: "przejdź do daty (RRRR-MM-DD)", ReaderTitle: "czytnik — wybierz księgę", ReaderPickKeys: "wpisz, by filtrować ↑/↓ ruch enter otwórz esc wyjście", @@ -260,7 +257,6 @@ var plUI = UI{ WebNoBookmarks: "Brak zakładek.", WebDelete: "usuń", WebSaved: "Zapisano.", - WebTradLang: "język tradycyjny", WebUILang: "język interfejsu", WebSiglaStyle: "styl sigli", WebDefaultVersion: "wersja domyślna", diff --git a/internal/i18n/i18n_test.go b/internal/i18n/i18n_test.go index 79479e8..79f3009 100644 --- a/internal/i18n/i18n_test.go +++ b/internal/i18n/i18n_test.go @@ -28,8 +28,6 @@ func TestVersionLabels(t *testing.T) { cases := []struct { lang, code, want string }{ - {"en", "bt", "Biblia Tysiąclecia (niedziela.pl)"}, - {"pl", "bt", "Biblia Tysiąclecia (niedziela.pl)"}, {"en", "wuj", "Wujek (Polish)"}, {"pl", "wuj", "Wujek (pol.)"}, {"en", "vul", "Vulgate (Latin)"}, @@ -50,10 +48,10 @@ func TestTUIStrings(t *testing.T) { en := Get("en") pl := Get("pl") - if en.FooterKeys != "tab/⇧tab version ←/→ day d date j/k scroll space/b page g/G top/bottom r refresh q quit" { + if en.FooterKeys != "tab/⇧tab version ←/→ day d date j/k scroll space/b page g/G top/bottom q quit" { t.Errorf("en.FooterKeys = %q", en.FooterKeys) } - if pl.FooterKeys != "tab/⇧tab wersja ←/→ dzień d data j/k przewiń spacja/b strona g/G góra/dół r odśwież q wyjście" { + if pl.FooterKeys != "tab/⇧tab wersja ←/→ dzień d data j/k przewiń spacja/b strona g/G góra/dół q wyjście" { t.Errorf("pl.FooterKeys = %q", pl.FooterKeys) } if en.Loading != "loading…" || pl.Loading != "ładowanie…" { @@ -74,7 +72,7 @@ func TestTUIStrings(t *testing.T) { if strings.HasSuffix(en.ErrorPrefix, " ") || strings.HasSuffix(pl.ErrorPrefix, " ") { t.Errorf("ErrorPrefix has 2+ trailing spaces: en=%q pl=%q", en.ErrorPrefix, pl.ErrorPrefix) } - if en.ErrorHint != "change date (←/→) or refresh (r)" || pl.ErrorHint != "zmień datę (←/→) lub odśwież (r)" { + if en.ErrorHint != "change date (←/→)" || pl.ErrorHint != "zmień datę (←/→)" { t.Errorf("ErrorHint en=%q pl=%q", en.ErrorHint, pl.ErrorHint) } } diff --git a/internal/liturgy/citation.go b/internal/liturgy/citation.go new file mode 100644 index 0000000..2c545c2 --- /dev/null +++ b/internal/liturgy/citation.go @@ -0,0 +1,21 @@ +package liturgy + +import ( + "fmt" + "regexp" + "strings" +) + +// citationRe captures a scripture reference in a trailing "(...)" of a section +// heading, e.g. "Ewangelia (J 20, 1. 11-18)" -> "J 20, 1. 11-18". +var citationRe = regexp.MustCompile(`\((.+)\)\s*$`) + +// ExtractCitation returns the scripture reference carried in a section +// heading's trailing parentheses, or an error when the heading has none. +func ExtractCitation(heading string) (string, error) { + m := citationRe.FindStringSubmatch(heading) + if m == nil { + return "", fmt.Errorf("no reference found in heading: %q", heading) + } + return strings.TrimSpace(m[1]), nil +} diff --git a/internal/liturgy/clean_test.go b/internal/liturgy/clean_test.go deleted file mode 100644 index d9ab4fc..0000000 --- a/internal/liturgy/clean_test.go +++ /dev/null @@ -1,75 +0,0 @@ -package liturgy - -import ( - "os" - "path/filepath" - "testing" - "time" -) - -// TestCleanCache exercises CleanCache's file-selection rules: date-prefixed -// cache files (modern ".html"/".json" and traditional ".trad.<lang>.json") -// older than the cutoff are removed; recent files and a non-matching file -// are left untouched. The cutoff is a fixed literal (not time.Now-derived) -// so the test is deterministic; only the "recent" fixtures are anchored to -// today, and only to make sure they land safely on the "keep" side of that -// fixed cutoff. -func TestCleanCache(t *testing.T) { - dir := t.TempDir() - t.Setenv("XDG_CACHE_HOME", dir) - cacheDir := filepath.Join(dir, "lectio") - if err := os.MkdirAll(cacheDir, 0o755); err != nil { - t.Fatal(err) - } - - recent := time.Now().Format("2006-01-02") - files := map[string]string{ - "2020-01-01.html": "<html>old</html>", - "2020-01-01.json": `[{"Heading":"old"}]`, - "2020-01-01.trad.pl.json": `[{"info":{},"sections":[]}]`, - recent + ".html": "<html>recent</html>", - recent + ".trad.pl.json": `[{"info":{},"sections":[]}]`, - "notes.txt": "not a cache file", - } - for name, content := range files { - if err := os.WriteFile(filepath.Join(cacheDir, name), []byte(content), 0o644); err != nil { - t.Fatal(err) - } - } - - cutoff := time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC) - removed, freed, err := CleanCache(cutoff) - if err != nil { - t.Fatalf("CleanCache: %v", err) - } - if removed != 3 { - t.Errorf("removed = %d, want 3", removed) - } - if freed <= 0 { - t.Errorf("freed = %d, want > 0", freed) - } - - for _, gone := range []string{"2020-01-01.html", "2020-01-01.json", "2020-01-01.trad.pl.json"} { - if _, err := os.Stat(filepath.Join(cacheDir, gone)); !os.IsNotExist(err) { - t.Errorf("%s still exists after CleanCache, want removed", gone) - } - } - for _, kept := range []string{recent + ".html", recent + ".trad.pl.json", "notes.txt"} { - if _, err := os.Stat(filepath.Join(cacheDir, kept)); err != nil { - t.Errorf("%s missing after CleanCache, want kept: %v", kept, err) - } - } -} - -// TestCleanCacheMissingDir checks the documented no-op: a cache dir that -// does not exist yet is not an error. -func TestCleanCacheMissingDir(t *testing.T) { - t.Setenv("XDG_CACHE_HOME", t.TempDir()) - removed, freed, err := CleanCache(time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC)) - if err != nil { - t.Fatalf("CleanCache on missing dir: %v", err) - } - if removed != 0 || freed != 0 { - t.Errorf("CleanCache on missing dir = (%d, %d), want (0, 0)", removed, freed) - } -} diff --git a/internal/liturgy/fetch.go b/internal/liturgy/fetch.go deleted file mode 100644 index e66b77f..0000000 --- a/internal/liturgy/fetch.go +++ /dev/null @@ -1,259 +0,0 @@ -package liturgy - -import ( - "encoding/json" - "fmt" - "io" - "net/http" - "os" - "path/filepath" - "regexp" - "time" -) - -// baseURL is the niedziela.pl URL template ("%s" is the date, YYYY-MM-DD). -// It is a package var so tests can point it at an httptest server. -var baseURL = "https://niezbednik.niedziela.pl/liturgia/%s/Ewangelia" - -// SetBaseURL overrides the fetch URL template used by Load. It exists so -// tests in other packages (e.g. internal/readings) can point Load at an -// httptest server; production code must never call it. -func SetBaseURL(url string) { - baseURL = url -} - -// userAgent is sent on every fetch; the site serves a different (broken) -// page to non-browser clients without it. -const userAgent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 " + - "(KHTML, like Gecko) Chrome/124.0 Safari/537.36" - -// publishedRe matches the tab-pane id niedziela.pl gives a fully published -// day's page (e.g. "tabnowy0all"). Its absence -- together with a "Przykro -// nam" placeholder -- marks a date that has not been published yet; see -// ewangelia.py's fetch() for the original behaviour this mirrors. -var publishedRe = regexp.MustCompile(`id="\w*0all"`) - -// dateRe is the same YYYY-MM-DD shape internal/cli's dateRe validates -// against. Load checks opts.Date against it before building any filesystem -// path (jsonPath/htmlPath below are built by string concatenation, so an -// unvalidated Date is a path-traversal vector) -- defense-in-depth so every -// caller (web, cli, tui) is protected even if a future caller forgets to -// validate its own input first. -var dateRe = regexp.MustCompile(`^\d{4}-\d{2}-\d{2}$`) - -// cacheFileRe matches the date-prefixed cache file names Load/Harvest/tradlit -// write into CacheDir(): "<YYYY-MM-DD>.html", "<YYYY-MM-DD>.json", and -// "<YYYY-MM-DD>.trad.<lang>.json" (the traditional-lectionary cache; see -// internal/tradlit). CleanCache uses it to tell cache entries apart from -// anything else that might be sitting in the directory, and to recover the -// date (group 1) for the age check regardless of which cache file it is. -var cacheFileRe = regexp.MustCompile(`^(\d{4}-\d{2}-\d{2})\.[a-z0-9.]+$`) - -// Options controls how Load resolves a day's readings. -type Options struct { - // Date is the day to load, formatted YYYY-MM-DD. - Date string - // Refresh bypasses both cache layers and re-fetches from the network. - Refresh bool - // Offline restricts Load to previously cached/harvested data (see - // LoadOffline), never hitting the network. - Offline bool -} - -// CacheDir is where the HTML/JSON cache layers live: -// ${XDG_CACHE_HOME:-~/.cache}/lectio/ -// Exported so internal/tradlit shares the same cache root for the -// traditional lectionary's propers. -func CacheDir() string { - base := os.Getenv("XDG_CACHE_HOME") - if base == "" { - home, err := os.UserHomeDir() - if err != nil { - home = "." - } - base = filepath.Join(home, ".cache") - } - return filepath.Join(base, "lectio") -} - -// Load returns the day's reading sections and DayInfo, from the modern -// (niedziela.pl) source, preferring cache over network: -// -// 0. If Offline, skip straight to LoadOffline (the harvested sigla TSV) -- -// that store carries citations only, so DayInfo comes back zero. -// 1. Unless Refresh, the parsed JSON cache ({date}.json), which round-trips -// DayInfo alongside the sections (see cachedDay/loadCache). -// 2. Unless Refresh, the raw HTML cache ({date}.html) -- parsed (both -// sections and DayInfo re-derived from the same HTML via Parse/ -// ParseDayInfo), and the result written to the JSON cache for next time. -// 3. Otherwise, fetch the page over the network, parse it, and -- only if -// the page is fully published -- write both cache layers. A fetch error -// here (e.g. no network) falls back to LoadOffline for this date if it -// has been harvested, and only surfaces the original fetch error if -// that fallback also fails. -func Load(opts Options) ([]Section, DayInfo, error) { - if !dateRe.MatchString(opts.Date) { - return nil, DayInfo{}, fmt.Errorf("invalid date %q: want YYYY-MM-DD", opts.Date) - } - - if opts.Offline { - secs, err := LoadOffline(opts.Date) - return secs, DayInfo{}, err - } - - dir := CacheDir() - jsonPath := filepath.Join(dir, opts.Date+".json") - htmlPath := filepath.Join(dir, opts.Date+".html") - - if !opts.Refresh { - if secs, info, err := loadCache(jsonPath); err == nil { - return secs, info, nil - } - if page, err := os.ReadFile(htmlPath); err == nil { - pageStr := string(page) - secs, err := Parse(pageStr) - if err != nil { - return nil, DayInfo{}, err - } - info := ParseDayInfo(pageStr) - writeCache(jsonPath, secs, info) - return secs, info, nil - } - } - - page, err := fetch(opts.Date) - if err != nil { - // Network is unreachable: fall back to a prior harvest of this date - // if there is one, rather than failing outright. The sigla store - // carries no DayInfo, so this path always reports it zero. - if secs, offErr := LoadOffline(opts.Date); offErr == nil { - return secs, DayInfo{}, nil - } - return nil, DayInfo{}, err - } - - // Parse itself reports an unpublished date as "no reading published for - // this date yet" (via the "Przykro nam" placeholder), so an unpublished - // page is neither cached nor returned as sections here. - secs, err := Parse(page) - if err != nil { - return nil, DayInfo{}, err - } - info := ParseDayInfo(page) - - // Cache only fully-published pages, so an as-yet-unpublished future date - // keeps being retried instead of caching a "no reading" placeholder. - if publishedRe.MatchString(page) { - if err := os.MkdirAll(dir, 0o755); err == nil { - _ = os.WriteFile(htmlPath, []byte(page), 0o644) - writeCache(jsonPath, secs, info) - } - } - - return secs, info, nil -} - -// CleanCache removes cached readings whose date is before `before` from -// CacheDir(). It matches only date-prefixed cache files (see cacheFileRe: -// "<YYYY-MM-DD>.html", ".json", or the traditional lectionary's -// ".trad.<lang>.json"); anything else in the directory (e.g. a stray -// notes.txt, or the sigla store, which lives elsewhere entirely) is left -// alone. A missing cache dir is not an error -- it just means there is -// nothing to clean yet. -func CleanCache(before time.Time) (removed int, freed int64, err error) { - dir := CacheDir() - entries, err := os.ReadDir(dir) - if err != nil { - if os.IsNotExist(err) { - return 0, 0, nil - } - return 0, 0, err - } - - for _, entry := range entries { - if entry.IsDir() { - continue - } - m := cacheFileRe.FindStringSubmatch(entry.Name()) - if m == nil { - continue - } - date, perr := time.Parse("2006-01-02", m[1]) - if perr != nil || !date.Before(before) { - continue - } - - path := filepath.Join(dir, entry.Name()) - info, serr := os.Stat(path) - if serr != nil { - return removed, freed, serr - } - if rerr := os.Remove(path); rerr != nil { - return removed, freed, rerr - } - removed++ - freed += info.Size() - } - return removed, freed, nil -} - -// cachedDay is the on-disk shape of the parsed-sections JSON cache -// ({date}.json): the sections plus the day's liturgical identity, so a -// cache hit round-trips DayInfo without re-parsing the HTML cache. (An -// older cache file written before DayInfo existed was a bare JSON array, -// not an object -- json.Unmarshal into cachedDay then fails, which -// loadCache treats as an ordinary cache miss, falling through to the HTML -// cache or the network like any other stale/missing cache entry.) -type cachedDay struct { - Sections []Section - DayInfo DayInfo -} - -// loadCache reads and unmarshals the parsed-sections + DayInfo cache file. -func loadCache(path string) ([]Section, DayInfo, error) { - data, err := os.ReadFile(path) - if err != nil { - return nil, DayInfo{}, err - } - var cd cachedDay - if err := json.Unmarshal(data, &cd); err != nil { - return nil, DayInfo{}, err - } - return cd.Sections, cd.DayInfo, nil -} - -// writeCache best-effort writes the parsed sections + DayInfo cache; a -// failure to cache should never fail the load itself. -func writeCache(path string, secs []Section, info DayInfo) { - data, err := json.Marshal(cachedDay{Sections: secs, DayInfo: info}) - if err != nil { - return - } - _ = os.WriteFile(path, data, 0o644) -} - -// fetch GETs the day's page from baseURL with the browser User-Agent. -// Whether the page is actually published is left to the caller (Parse -// detects an unpublished date; Load re-checks the tab id to decide whether -// the result is cache-worthy). -func fetch(dateStr string) (string, error) { - url := fmt.Sprintf(baseURL, dateStr) - req, err := http.NewRequest(http.MethodGet, url, nil) - if err != nil { - return "", err - } - req.Header.Set("User-Agent", userAgent) - - client := &http.Client{Timeout: 20 * time.Second} - resp, err := client.Do(req) - if err != nil { - return "", fmt.Errorf("failed to fetch %s: %w", url, err) - } - defer resp.Body.Close() - - body, err := io.ReadAll(resp.Body) - if err != nil { - return "", fmt.Errorf("failed to read response from %s: %w", url, err) - } - return string(body), nil -} diff --git a/internal/liturgy/fetch_test.go b/internal/liturgy/fetch_test.go deleted file mode 100644 index c06f0f8..0000000 --- a/internal/liturgy/fetch_test.go +++ /dev/null @@ -1,68 +0,0 @@ -package liturgy - -import ( - "net/http" - "net/http/httptest" - "os" - "path/filepath" - "testing" -) - -func TestLoadCaches(t *testing.T) { - html, _ := os.ReadFile("testdata/2026-06-22.html") - hits := 0 - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - hits++ - w.Write(html) - })) - defer srv.Close() - t.Setenv("XDG_CACHE_HOME", t.TempDir()) - baseURL = srv.URL + "/liturgia/%s/Ewangelia" // test hook - - secs1, info1, err := Load(Options{Date: "2026-06-22"}) - if err != nil || len(secs1) == 0 { - t.Fatalf("load1: %v", err) - } - if info1.Name == "" { - t.Error("load1: DayInfo.Name empty, want it populated from the freshly-parsed HTML") - } - secs2, info2, _ := Load(Options{Date: "2026-06-22"}) // should hit JSON cache - if hits != 1 { - t.Errorf("server hit %d times, want 1 (cache miss on repeat)", hits) - } - if len(secs2) != len(secs1) { - t.Error("cache returned different section count") - } - // The JSON cache round-trips DayInfo (see cachedDay/loadCache), so a - // cache-hit repeat load must not lose it. - if info2 != info1 { - t.Errorf("cache-hit DayInfo = %+v, want it to match the first load's %+v", info2, info1) - } -} - -// TestLoadRejectsInvalidDate is the liturgy-layer defense-in-depth check for -// the ?date= path-traversal finding: Load must reject a non-YYYY-MM-DD date -// before it ever builds a filesystem path from it, so every caller (web, -// cli, tui) is protected even if a future caller forgets to validate. -// -// The planted "passwd.json" sits one level *above* CacheDir() -- reachable -// only via a "../" date -- so if Load ever built jsonPath from the raw date -// unchecked, loadCache would read it back and return its section instead -// of an error. -func TestLoadRejectsInvalidDate(t *testing.T) { - dir := t.TempDir() - t.Setenv("XDG_CACHE_HOME", dir) - - evilPath := filepath.Join(dir, "passwd.json") - if err := os.WriteFile(evilPath, []byte(`[{"Heading":"SHOULD-NEVER-BE-READ"}]`), 0o644); err != nil { - t.Fatal(err) - } - - secs, _, err := Load(Options{Date: "../passwd"}) - if err == nil { - t.Fatalf("Load(Date=%q) = (%v, nil), want a non-nil error", "../passwd", secs) - } - if secs != nil { - t.Errorf("Load(Date=%q) sections = %v, want nil", "../passwd", secs) - } -} diff --git a/internal/liturgy/parse.go b/internal/liturgy/parse.go deleted file mode 100644 index 4c1a935..0000000 --- a/internal/liturgy/parse.go +++ /dev/null @@ -1,209 +0,0 @@ -package liturgy - -import ( - "fmt" - "html" - "regexp" - "strings" -) - -// lectionaryTabs lists the two reading sets carried on the page: the -// lectionary in force since Advent 2015 ("nowy") and the one it replaced -// ("stary"). They are not interchangeable -- the acclamation can cite a -// different book entirely, and the older set contains malformed citations. -// Pick by id, never by position in the markup, or a reordering silently -// switches edition. -var lectionaryTabs = []string{"tabnowy0all", "tabstary0all"} - -var ( - brRe = regexp.MustCompile(`(?i)<br\s*/?>`) - tagRe = regexp.MustCompile(`<[^>]+>`) - wsRe = regexp.MustCompile(`[ \t]+`) - h2Re = regexp.MustCompile(`(?s)<h2>(.*?)</h2>`) - h4Re = regexp.MustCompile(`(?s)<h4>(.*?)</h4>`) - pRe = regexp.MustCompile(`(?s)<p>(.*?)</p>`) - citationRe = regexp.MustCompile(`\((.+)\)\s*$`) - - // dayNamePRe matches every classed <p><em>...</em></p> 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)<p class="([^"]*)">\s*<em>(.*?)</em>\s*</p>`) - - // dayColourRe matches niedziela.pl's "Kolor szat: <word>" vestment-colour - // line, tolerating the <span>/<strong> 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. `<div class="tab-pane fade " id="tabnowy0all">`. -func panePattern(tab string) *regexp.Regexp { - return regexp.MustCompile(`<div class="tab-pane[^"]*"\s+id="` + regexp.QuoteMeta(tab) + `">`) -} - -// htmlToLines turns an HTML fragment into a list of non-empty text lines. -// <br> marks a verse line break (used in psalms/acclamations); other tags -// are dropped, entities decoded, and intra-line whitespace collapsed. -func htmlToLines(fragment string) []string { - fragment = brRe.ReplaceAllString(fragment, "\n") - fragment = tagRe.ReplaceAllString(fragment, "") - text := html.UnescapeString(fragment) - var lines []string - for _, ln := range strings.Split(text, "\n") { - ln = strings.TrimSpace(wsRe.ReplaceAllString(ln, " ")) - if ln != "" { - lines = append(lines, ln) - } - } - return lines -} - -// Parse extracts every reading section from the page's preferred lectionary -// tab (falling back to the superseded one), erroring loudly if neither tab is -// present on the page, or the tab is found but carries no sections -- a -// layout change should never be mistaken for a quiet day with no readings. -func Parse(pageHTML string) ([]Section, error) { - var loc []int - for _, tab := range lectionaryTabs { - if m := panePattern(tab).FindStringIndex(pageHTML); m != nil { - loc = m - break - } - } - if loc == nil { - if strings.Contains(pageHTML, "Przykro nam") { - return nil, fmt.Errorf("no reading published for this date yet") - } - return nil, fmt.Errorf( - "no reading tab (%s) found on page -- the site layout may have changed", - strings.Join(lectionaryTabs, "/"), - ) - } - - rest := pageHTML[loc[1]:] - block := rest - if nxt := strings.Index(rest, `<div class="tab-pane`); nxt != -1 { - block = rest[:nxt] - } - - heads := h2Re.FindAllStringSubmatchIndex(block, -1) - var sections []Section - czytanieCount := 0 - for i, h := range heads { - bodyEnd := len(block) - if i+1 < len(heads) { - bodyEnd = heads[i+1][0] - } - body := block[h[1]:bodyEnd] - - heading := strings.Join(htmlToLines(block[h[2]:h[3]]), " ") - - subtitle := "" - if sub := h4Re.FindStringSubmatch(body); sub != nil { - subtitle = strings.Join(htmlToLines(sub[1]), " ") - } - - var paragraphs [][]string - for _, p := range pRe.FindAllStringSubmatch(body, -1) { - if lines := htmlToLines(p[1]); len(lines) > 0 { - paragraphs = append(paragraphs, lines) - } - } - - // A heading is expected to always carry a parenthetical citation; - // if one is somehow missing, leave Citation empty rather than - // failing the whole parse over one section. - citation, _ := ExtractCitation(heading) - - sections = append(sections, Section{ - Heading: heading, - Subtitle: subtitle, - Citation: citation, - PartID: partID(heading, &czytanieCount), - Paragraphs: paragraphs, - }) - } - - // A layout change can leave the tab findable but empty; say so rather - // than returning nothing and looking like a quiet day. - if len(sections) == 0 { - return nil, fmt.Errorf("reading tab found but no sections in it -- the site layout may have changed") - } - 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 <p class="... -// fw-bold color-XXX"><em>NAME</em></p> 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: <word>" 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 -// with the first ("pierwsze_czytanie"). Anything unrecognised is "". -func partID(heading string, czytanieCount *int) string { - switch { - case strings.HasPrefix(heading, "1. czytanie"): - *czytanieCount++ - if *czytanieCount == 1 { - return "pierwsze_czytanie" - } - return "drugie_czytanie" - case strings.HasPrefix(heading, "Psalm"): - return "psalm" - case strings.HasPrefix(heading, "Aklamacja"): - return "aklamacja" - case strings.HasPrefix(heading, "Ewangelia"): - return "ewangelia" - default: - return "" - } -} - -// ExtractCitation pulls the citation from a section heading: -// "Ewangelia (Mt 7, 1-5)" -> "Mt 7, 1-5". -func ExtractCitation(heading string) (string, error) { - m := citationRe.FindStringSubmatch(heading) - if m == nil { - return "", fmt.Errorf("no reference found in heading: %q", heading) - } - return strings.TrimSpace(m[1]), nil -} diff --git a/internal/liturgy/parse_test.go b/internal/liturgy/parse_test.go deleted file mode 100644 index 8fe2eb0..0000000 --- a/internal/liturgy/parse_test.go +++ /dev/null @@ -1,176 +0,0 @@ -package liturgy - -import ( - "os" - "strings" - "testing" -) - -func TestParse(t *testing.T) { - html, _ := os.ReadFile("testdata/2026-07-22.html") - secs, err := Parse(string(html)) - if err != nil { - t.Fatal(err) - } - var gospel *Section - var firstCzytanie *Section - var secondCzytanie *Section - for i := range secs { - if strings.HasPrefix(secs[i].Heading, "Ewangelia") { - gospel = &secs[i] - } - if strings.HasPrefix(secs[i].Heading, "1. czytanie") { - if firstCzytanie == nil { - firstCzytanie = &secs[i] - } else if secondCzytanie == nil { - secondCzytanie = &secs[i] - } - } - } - if gospel == nil { - t.Fatal("no gospel section") - } - if gospel.Citation != "J 20, 1. 11-18" { - t.Errorf("gospel citation = %q", gospel.Citation) - } - if len(gospel.Paragraphs) == 0 { - t.Error("gospel has no paragraphs") - } - if gospel.PartID != "ewangelia" { - t.Errorf("gospel PartID = %q, want %q", gospel.PartID, "ewangelia") - } - - if firstCzytanie == nil { - t.Fatal("no '1. czytanie' section") - } - if firstCzytanie.PartID != "pierwsze_czytanie" { - t.Errorf("first '1. czytanie' PartID = %q, want %q", firstCzytanie.PartID, "pierwsze_czytanie") - } - // 2026-07-22 is a split-feast day with two "1. czytanie" sections in the - // same tab; the second one must not collide with the first. - if secondCzytanie == nil { - t.Fatal("expected a second '1. czytanie' section (split feast fixture)") - } - if secondCzytanie.PartID != "drugie_czytanie" { - t.Errorf("second '1. czytanie' PartID = %q, want %q", secondCzytanie.PartID, "drugie_czytanie") - } -} - -// TestParseDayInfo checks the modern (niedziela.pl) day-info extraction -// against the split-feast fixture: Name comes from the color-classed, -// fw-bold <p><em>...</em></p> near id="dzien" (not the earlier, plain -// fw-bold lookalike higher up the page), and Colour from "Kolor szat: -// biały" -> "white". Season is always "" for the modern lectionary. -func TestParseDayInfo(t *testing.T) { - html, err := os.ReadFile("testdata/2026-07-22.html") - if err != nil { - t.Fatal(err) - } - info := ParseDayInfo(string(html)) - if !strings.Contains(info.Name, "Marii Magdaleny") { - t.Errorf("Name = %q, want it to contain %q", info.Name, "Marii Magdaleny") - } - if info.Colour != "white" { - t.Errorf("Colour = %q, want %q", info.Colour, "white") - } - if info.Season != "" { - t.Errorf("Season = %q, want empty for the modern lectionary", info.Season) - } -} - -// TestParseDayInfoMultilineName checks the day name is cleanly joined when -// the source <em> body itself carries an embedded line break (a long -// commemoration name wrapped across lines in the page's own markup), and -// that a multi-option colour line ("zielony albo biały albo czerwony") -// maps by its first word. -func TestParseDayInfoMultilineName(t *testing.T) { - html, err := os.ReadFile("testdata/2026-06-22.html") - if err != nil { - t.Fatal(err) - } - info := ParseDayInfo(string(html)) - if !strings.Contains(info.Name, "Dzień Powszedni") || !strings.Contains(info.Name, "Jana Fishera") { - t.Errorf("Name = %q, want it to contain both wrapped-line fragments", info.Name) - } - if strings.Contains(info.Name, "\n") { - t.Errorf("Name = %q, should not contain a raw newline", info.Name) - } - if info.Colour != "green" { - t.Errorf("Colour = %q, want %q (first of \"zielony albo...\")", info.Colour, "green") - } -} - -// TestParseDayInfoNoMatch checks an unrecognised page shape yields a zero -// DayInfo rather than an error -- the header is simply omitted by callers. -func TestParseDayInfoNoMatch(t *testing.T) { - info := ParseDayInfo("<html><body>redesigned</body></html>") - if info != (DayInfo{}) { - t.Errorf("ParseDayInfo(unrecognised) = %+v, want zero value", info) - } -} - -func TestParseLayoutChange(t *testing.T) { - if _, err := Parse("<html><body>redesigned</body></html>"); err == nil { - t.Error("expected error on missing reading tab") - } -} - -func TestParseNormalDay(t *testing.T) { - html, err := os.ReadFile("testdata/2026-06-22.html") - if err != nil { - t.Fatal(err) - } - secs, err := Parse(string(html)) - if err != nil { - t.Fatal(err) - } - if len(secs) != 4 { - t.Fatalf("len(secs) = %d, want 4", len(secs)) - } - want := map[string]string{ - "1. czytanie": "pierwsze_czytanie", - "Psalm": "psalm", - "Aklamacja": "aklamacja", - "Ewangelia": "ewangelia", - } - for _, s := range secs { - for prefix, partID := range want { - if strings.HasPrefix(s.Heading, prefix) { - if s.PartID != partID { - t.Errorf("heading %q: PartID = %q, want %q", s.Heading, s.PartID, partID) - } - } - } - if s.Subtitle == "" { - t.Errorf("heading %q: empty subtitle", s.Heading) - } - if len(s.Paragraphs) == 0 { - t.Errorf("heading %q: no paragraphs", s.Heading) - } - } -} - -func TestExtractCitation(t *testing.T) { - cases := []struct { - heading string - want string - }{ - {"Ewangelia (Mt 7, 1-5)", "Mt 7, 1-5"}, - {"1. czytanie (Pnp 8, 6-7)", "Pnp 8, 6-7"}, - {"Psalm (Ps 63 (62), 2. 3-4. 5-6. 8-9 (R.: por. 2ab))", "Ps 63 (62), 2. 3-4. 5-6. 8-9 (R.: por. 2ab)"}, - } - for _, c := range cases { - got, err := ExtractCitation(c.heading) - if err != nil { - t.Errorf("ExtractCitation(%q) error: %v", c.heading, err) - continue - } - if got != c.want { - t.Errorf("ExtractCitation(%q) = %q, want %q", c.heading, got, c.want) - } - } - - if _, err := ExtractCitation("no parens here"); err == nil { - t.Error("expected error for heading with no parenthetical") - } -} diff --git a/internal/liturgy/section.go b/internal/liturgy/section.go index 1e446a1..dcca7b5 100644 --- a/internal/liturgy/section.go +++ b/internal/liturgy/section.go @@ -17,19 +17,18 @@ type Section struct { Paragraphs [][]string } -// DayInfo is the day's liturgical identity, source-language (Polish for the -// modern niedziela.pl lectionary, English/Latin for the traditional -// missalemeum) -- never translated, like Section's own Heading/Citation. -// A source that carries no such data (or an unrecognised page/response -// shape) yields a zero DayInfo; callers must treat that as "omit the -// header", never as an error. +// DayInfo is the day's liturgical identity from the offline calendar engine. +// Name follows the UI language where the calendar data has a localized name +// (else English); Colour is normalized. A day that carries no celebration name +// yields a zero DayInfo; callers must treat that as "omit the header", never as +// an error. type DayInfo struct { - // Name is the celebration, e.g. "Święto św. Marii Magdaleny" (modern) or - // "St. Mary Magdalene" (traditional). + // Name is the celebration, e.g. "św. Marii Magdaleny" (pl UI, where the + // calendar data has a Polish name) or "Saint Mary Magdalene" (en). Name string - // Season is the temporal context, e.g. "Feria IV after VIII Sunday - // after Pentecost" (traditional); always "" for the modern lectionary, - // whose temporal is folded into Name on temporal days. + // Season is the temporal context; currently left empty by the offline + // loader, since the celebration name already carries the temporal identity + // on temporal days. Season string // Colour is the normalized liturgical colour: "white", "green", // "violet", "red", "rose", or "" when unknown/unmapped. diff --git a/internal/liturgy/store.go b/internal/liturgy/store.go deleted file mode 100644 index 5bf7ef0..0000000 --- a/internal/liturgy/store.go +++ /dev/null @@ -1,215 +0,0 @@ -package liturgy - -import ( - "fmt" - "os" - "path/filepath" - "sort" - "strings" - "time" -) - -// harvestRetries is how many times Harvest attempts a single date's fetch -// before treating it as a genuine network failure rather than transient -// hiccup; harvestRetryDelay is the backoff slept between attempts. Both are -// package vars so tests can shrink the delay instead of waiting on it. -var ( - harvestRetries = 3 - harvestRetryDelay = 2 * time.Second -) - -// siglaRow is one line of the sigla TSV: a date's section label and the -// scripture citation extracted from its heading. -type siglaRow struct { - label, citation string -} - -// siglaPath is the persistent sigla store written by Harvest and read by -// LoadOffline: ${XDG_DATA_HOME:-~/.local/share}/lectio/sigla.tsv -func siglaPath() string { - base := os.Getenv("XDG_DATA_HOME") - if base == "" { - home, err := os.UserHomeDir() - if err != nil { - home = "." - } - base = filepath.Join(home, ".local", "share") - } - return filepath.Join(base, "lectio", "sigla.tsv") -} - -// sectionLabel derives the short label Harvest stores alongside a citation -// from a section's full heading, e.g. "Ewangelia (J 20, 1. 11-18)" -> -// "Ewangelia". It strips the same trailing "(...)" citation ExtractCitation -// reads, so the two stay in sync. -func sectionLabel(heading string) string { - loc := citationRe.FindStringIndex(heading) - if loc == nil { - return strings.TrimSpace(heading) - } - return strings.TrimSpace(heading[:loc[0]]) -} - -// readSigla loads the sigla TSV into date -> rows. A missing file is not an -// error -- it just means nothing has been harvested yet. -func readSigla(path string) (map[string][]siglaRow, error) { - data, err := os.ReadFile(path) - if err != nil { - if os.IsNotExist(err) { - return map[string][]siglaRow{}, nil - } - return nil, err - } - rows := map[string][]siglaRow{} - for _, line := range strings.Split(string(data), "\n") { - if line == "" { - continue - } - fields := strings.SplitN(line, "\t", 3) - if len(fields) != 3 { - continue - } - date := fields[0] - rows[date] = append(rows[date], siglaRow{label: fields[1], citation: fields[2]}) - } - return rows, nil -} - -// writeSigla writes date -> rows back out as the sigla TSV, sorted by date -// for a deterministic, diffable file. -func writeSigla(path string, byDate map[string][]siglaRow) error { - if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { - return err - } - dates := make([]string, 0, len(byDate)) - for d := range byDate { - dates = append(dates, d) - } - sort.Strings(dates) - - var b strings.Builder - for _, date := range dates { - for _, r := range byDate[date] { - fmt.Fprintf(&b, "%s\t%s\t%s\n", date, r.label, r.citation) - } - } - return os.WriteFile(path, []byte(b.String()), 0o644) -} - -// Harvest walks dates forward from fromDate, fetching and parsing each day's -// page and recording every section's citation to the sigla TSV, for up to -// maxDays days (0 = walk until the unpublished horizon). It stops cleanly -// (nil error) the first time a date fails to PARSE -- niedziela.pl's -// "Przykro nam" placeholder (or any other parse failure) marks the horizon -// the site hasn't published past yet, not an error to report. A date that -// fails to FETCH, by contrast, is a transient network problem, not the -// horizon: Harvest retries it a few times (harvestRetries, backing off -// harvestRetryDelay between attempts) and, if it still fails, stops and -// returns an error -- but only after saving whatever was harvested up to -// that point, so the caller never loses progress to a blip. -// -// Re-harvesting a date replaces its rows in the TSV rather than duplicating -// them, so running Harvest again over an already-harvested range is safe. -// It also warms the HTML/JSON cache for every date it successfully harvests. -// -// It returns how many days were harvested and the furthest (most recent) -// date reached, alongside any fetch error (nil on a clean parse-horizon -// stop or on reaching maxDays). -func Harvest(fromDate string, maxDays int) (added int, furthest string, err error) { - start, err := time.Parse("2006-01-02", fromDate) - if err != nil { - return 0, "", fmt.Errorf("invalid date %q: %w", fromDate, err) - } - - path := siglaPath() - byDate, err := readSigla(path) - if err != nil { - return 0, "", err - } - - dir := CacheDir() - day := start - var harvestErr error - for i := 0; maxDays == 0 || i < maxDays; i++ { - dateStr := day.Format("2006-01-02") - - var page string - var ferr error - for attempt := 1; attempt <= harvestRetries; attempt++ { - page, ferr = fetch(dateStr) - if ferr == nil { - break - } - if attempt < harvestRetries { - time.Sleep(harvestRetryDelay) - } - } - if ferr != nil { - // A genuine network/transport error, not the horizon: don't - // silently stop as if the site simply hadn't published this - // date yet. Record it and stop walking, but writeSigla below - // still runs so progress made so far isn't lost. - harvestErr = fmt.Errorf("harvest interrupted at %s: %w", dateStr, ferr) - break - } - secs, perr := Parse(page) - if perr != nil { - break // unpublished horizon (or unparsable page): stop walking, cleanly - } - - var rows []siglaRow - for _, s := range secs { - citation, cerr := ExtractCitation(s.Heading) - if cerr != nil { - continue - } - rows = append(rows, siglaRow{label: sectionLabel(s.Heading), citation: citation}) - } - byDate[dateStr] = rows - - if publishedRe.MatchString(page) { - if mkErr := os.MkdirAll(dir, 0o755); mkErr == nil { - _ = os.WriteFile(filepath.Join(dir, dateStr+".html"), []byte(page), 0o644) - writeCache(filepath.Join(dir, dateStr+".json"), secs, ParseDayInfo(page)) - } - } - - added++ - furthest = dateStr - day = day.AddDate(0, 0, 1) - } - - werr := writeSigla(path, byDate) - if harvestErr != nil { - return added, furthest, harvestErr - } - if werr != nil { - return added, furthest, werr - } - return added, furthest, nil -} - -// LoadOffline builds a day's sections purely from the harvested sigla TSV: -// Heading is the stored section label, Citation the stored citation, and -// Paragraphs empty (no reading text is harvested, only the scripture -// reference). It errors clearly if the date has not been harvested. -func LoadOffline(date string) ([]Section, error) { - byDate, err := readSigla(siglaPath()) - if err != nil { - return nil, err - } - rows, ok := byDate[date] - if !ok || len(rows) == 0 { - return nil, fmt.Errorf("%s not harvested; run 'lectio update' while online first", date) - } - secs := make([]Section, 0, len(rows)) - czytanieCount := 0 - for _, r := range rows { - secs = append(secs, Section{ - Heading: r.label, - Citation: r.citation, - PartID: partID(r.label, &czytanieCount), - }) - } - return secs, nil -} diff --git a/internal/liturgy/store_test.go b/internal/liturgy/store_test.go deleted file mode 100644 index 1bf8343..0000000 --- a/internal/liturgy/store_test.go +++ /dev/null @@ -1,100 +0,0 @@ -package liturgy - -import ( - "net/http" - "net/http/httptest" - "os" - "strings" - "testing" - "time" -) - -func TestHarvestAndOffline(t *testing.T) { - html, _ := os.ReadFile("testdata/2026-07-22.html") - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if strings.Contains(r.URL.Path, "2026-07-22") { - w.Write(html) - } else { - w.Write([]byte("<html>Przykro nam</html>")) // horizon - } - })) - defer srv.Close() - t.Setenv("XDG_CACHE_HOME", t.TempDir()) - t.Setenv("XDG_DATA_HOME", t.TempDir()) - baseURL = srv.URL + "/liturgia/%s/Ewangelia" - - added, _, err := Harvest("2026-07-22", 3) - if err != nil || added < 1 { - t.Fatalf("harvest: added=%d err=%v", added, err) - } - secs, err := LoadOffline("2026-07-22") - if err != nil { - t.Fatal(err) - } - var haveGospel bool - var haveFirstCzytanie bool - for _, s := range secs { - if s.Citation == "J 20, 1. 11-18" && s.PartID == "ewangelia" { - haveGospel = true - } - if strings.HasPrefix(s.Heading, "1. czytanie") && s.PartID == "pierwsze_czytanie" { - haveFirstCzytanie = true - } - } - if !haveGospel { - t.Error("offline gospel citation or PartID missing") - } - if !haveFirstCzytanie { - t.Error("offline first czytanie PartID missing") - } -} - -// TestHarvestFetchErrorSavesPartialProgress exercises the transient-error -// path: a genuine network/transport failure on a date must NOT be mistaken -// for the unpublished horizon (that is Parse's job, on a "Przykro nam" page -// -- see TestHarvestAndOffline above, which stays nil-error). It must -// instead surface as a returned error, after writeSigla has still saved -// whatever was harvested before the failing date. -func TestHarvestFetchErrorSavesPartialProgress(t *testing.T) { - html, _ := os.ReadFile("testdata/2026-07-22.html") - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if strings.Contains(r.URL.Path, "2026-07-22") { - w.Write(html) - return - } - // Simulate a network/transport error (not a "Przykro nam" horizon - // page) by hijacking the connection and closing it without a - // response, so the client sees a read/EOF error. - hj, ok := w.(http.Hijacker) - if !ok { - t.Fatal("test server ResponseWriter does not support hijacking") - } - conn, _, err := hj.Hijack() - if err != nil { - t.Fatal(err) - } - conn.Close() - })) - defer srv.Close() - t.Setenv("XDG_CACHE_HOME", t.TempDir()) - t.Setenv("XDG_DATA_HOME", t.TempDir()) - baseURL = srv.URL + "/liturgia/%s/Ewangelia" - - origRetries, origDelay := harvestRetries, harvestRetryDelay - harvestRetries, harvestRetryDelay = 2, time.Millisecond - defer func() { harvestRetries, harvestRetryDelay = origRetries, origDelay }() - - added, furthest, err := Harvest("2026-07-22", 0) - if err == nil { - t.Fatal("harvest: want error on a fetch failure, got nil") - } - if added != 1 || furthest != "2026-07-22" { - t.Errorf("harvest: added=%d furthest=%q, want added=1 furthest=2026-07-22 (only the one date fetched before the network error)", added, furthest) - } - - // Progress made before the failing date must still be on disk. - secs, offErr := LoadOffline("2026-07-22") - if offErr != nil || len(secs) == 0 { - t.Errorf("harvest: partial progress not saved: offErr=%v secs=%v", offErr, secs) - } -} diff --git a/internal/liturgy/testdata/2026-06-22.html b/internal/liturgy/testdata/2026-06-22.html deleted file mode 100644 index a6c3f93..0000000 --- a/internal/liturgy/testdata/2026-06-22.html +++ /dev/null @@ -1,2713 +0,0 @@ -
-<!DOCTYPE html> -<html lang="pl-PL"> - -<head> - <meta charset="UTF-8"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <meta name="keywords" content="liturgia, czytania na dziś, lirturgis na dzis, czytanie na niedzielę, psalm na dziś, kalendarz liturgiczny, brewiarz, liturgia godzin, biblia, patron, święty, błogosławiony, rozważania, ewangelia, różanieć, tajmenice rózańcowe"> - <meta name="news_keywords" content="liturgia, czytania na dziś, kalendarz liturgiczny, brewiarz, liturgia godzin, biblia, patron, święty, błogosławiony, rozważania, ewangelia, różanieć, tajmenice rózańcowe"> - <meta name="description" content="Niezbędnik katolika - czytanie na dziś, rozważanie do Ewangelii, czytania liturgiczne, kalendarz liturgiczny, brewiarz, o czym warto pamiętać, czytania na każdy dzień, Slowo Boże na każdy dzień"> - <link rel="apple-touch-icon" sizes="57x57" href="https://niezbednik.niedziela.pl/apple-icon-57x57.png"> - <link rel="apple-touch-icon" sizes="60x60" href="https://niezbednik.niedziela.pl/apple-icon-60x60.png"> - <link rel="apple-touch-icon" sizes="72x72" href="https://niezbednik.niedziela.pl/apple-icon-72x72.png"> - <link rel="apple-touch-icon" sizes="76x76" href="https://niezbednik.niedziela.pl/apple-icon-76x76.png"> - <link rel="apple-touch-icon" sizes="114x114" href="https://niezbednik.niedziela.pl/apple-icon-114x114.png"> - <link rel="apple-touch-icon" sizes="120x120" href="https://niezbednik.niedziela.pl/apple-icon-120x120.png"> - <link rel="apple-touch-icon" sizes="144x144" href="https://niezbednik.niedziela.pl/apple-icon-144x144.png"> - <link rel="apple-touch-icon" sizes="152x152" href="https://niezbednik.niedziela.pl/apple-icon-152x152.png"> - <link rel="apple-touch-icon" sizes="180x180" href="https://niezbednik.niedziela.pl/apple-icon-180x180.png"> - <link rel="icon" type="image/png" sizes="192x192" href="https://niezbednik.niedziela.pl/android-icon-192x192.png"> - <link rel="icon" type="image/png" sizes="32x32" href="https://niezbednik.niedziela.pl/favicon-32x32.png"> - <link rel="icon" type="image/png" sizes="96x96" href="https://niezbednik.niedziela.pl/favicon-96x96.png"> - <link rel="icon" type="image/png" sizes="16x16" href="https://niezbednik.niedziela.pl/favicon-16x16.png"> - <link rel="manifest" href="https://niezbednik.niedziela.pl/manifest.json"> - <meta name="msapplication-TileColor" content="#ffffff"> - <meta name="msapplication-TileImage" content="https://niezbednik.niedziela.pl/ms-icon-144x144.png"> - <meta name="theme-color" content="#ffffff"> - <title>Niezbędnik katolika - czytania na 2026-06-22</title> - <link rel="canonical" href="https://niezbednik.niedziela.pl/liturgia/2026-06-22"> - - - <link rel="preconnect" href="https://fonts.googleapis.com"> - <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> - <link href="https://fonts.googleapis.com/css2?family=Work+Sans:ital,wght@0,400;0,500;0,700;1,400;1,700&family=PT+Serif:ital,wght@0,400;0,700;1,400;1,700&display=swap" rel="stylesheet"> - - - <link href="/assets/7ca11ba7/dist/css/bootstrap.min.css?v=1680299989" rel="stylesheet"> -<link href="/font-awesome/css/font-awesome.min.css?v=1488459453" rel="stylesheet"> -<link href="/css/animate.css?v=1663049856" rel="stylesheet"> -<link href="/css/swiper/swiper.min.css?v=1573878192" rel="stylesheet"> -<link href="/css/cookie-consent.css?v=1726132740" rel="stylesheet"> -<link href="/css/main.css?v=1774598783" rel="stylesheet"> - - - - <!-- Google tag (gtag.js) --> - <script async src="https://www.googletagmanager.com/gtag/js?id=G-3E6YN6ZC9K"></script> - <script> - window.dataLayer = window.dataLayer || []; - - function gtag() { - dataLayer.push(arguments); - } - gtag('js', new Date()); - - gtag('config', 'G-3E6YN6ZC9K'); - </script> - </head> - -<body class=""> - - - <!-- Progress scroll totop --> - <div class="progress-wrap cursor-pointer d-none"> - <svg class="progress-circle svg-content" width="100%" height="100%" viewBox="-1 -1 102 102"> - <path d="M50,1 a49,49 0 0,1 0,98 a49,49 0 0,1 0,-98" /> - </svg> - </div> - - <div id="theme-page"> - -
-
-<aside id="theme-aside-dark" class="background-primary lh-sm">
- <div class="menu-close lh-1 d-md-none"><a href="#" class="js-theme-nav-toggle">
- <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-x" viewBox="0 0 16 16">
- <path d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z" />
- </svg></a></div>
- <div class="position-relative h-100">
-
- <nav class="navbar navbar-accessibility mb-1 d-md-block d-none">
-
- <div class="d-inline-flex w-100">
- <ul class="nav list-inline mx-auto color-light">
- <li class="list-inline-item pt-0 pr-1 pb-0 pl-0">
- <a href="#" class="btn-font-size color-light" accesskey="b">
- <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-font-increase" viewBox="0 0 16 16">
- <path d="M8.59,12.033H3.815l-0.907,2.715H0.014L4.931,1.53h2.526l4.946,13.218H9.508L8.59,12.033z M14.248,4.976v1.739h-1.705V4.976
- h-1.74V3.269h1.74V1.53h1.705v1.739h1.738v1.707H14.248z M4.55,9.82h3.306L6.195,4.87L4.55,9.82L4.55,9.82z" />
- </svg><span class="visually-hidden">Wielkość czcionki</span>
- </a>
- </li>
- <li class="list-inline-item py-0 px-1 link-contrast">
- <a href="/site/contrast" accesskey="c" class="btn-contrast">A<span class="visually-hidden">Wersja graficzna</span></a>
- </li>
- </ul>
- </div>
-
- </nav>
-
- <!-- Logo -->
- <div id="theme-logo" style="margin-bottom: 1em;"> <a href="https://niezbednik.niedziela.pl">
- <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi color-white" style="font-size: 4.5em" viewBox="0 0 16 16">
-
- <path d="M4.286,9.063c1.004,0.876,2.082,1.274,3.208,1.185c1.078-0.087,2.059-0.609,2.836-1.185
- C9.553,8.488,8.571,7.968,7.494,7.879C6.368,7.789,5.29,8.188,4.286,9.063z" />
- <path d="M13.989,4.023H13.33V3.931c0-0.222-0.18-0.401-0.402-0.401H12.37c-0.222,0-0.401,0.18-0.401,0.401v0.093h-0.788V3.136
- c0-1.008-0.822-1.829-1.831-1.829h-2.7c-1.009,0-1.83,0.821-1.83,1.829v0.888H4.031V3.931c0-0.222-0.179-0.401-0.401-0.401H3.071
- c-0.222,0-0.401,0.18-0.401,0.401v0.093H2.011c-0.92,0-1.666,0.745-1.666,1.666v7.338c0,0.92,0.746,1.666,1.666,1.666h11.979
- c0.921,0,1.666-0.746,1.666-1.666V5.689C15.655,4.769,14.91,4.023,13.989,4.023z M5.866,3.136c0-0.432,0.352-0.784,0.784-0.784h2.7
- c0.433,0,0.785,0.353,0.785,0.784v0.888H5.866V3.136z M12.578,10.402l-0.48,0.362c-0.01-0.013-0.492-0.642-1.275-1.313
- c-1.082,0.827-2.207,1.308-3.277,1.396c-0.124,0.01-0.247,0.016-0.37,0.016c-1.258,0-2.449-0.531-3.546-1.583L3.421,9.063
- l0.208-0.217c1.204-1.153,2.52-1.679,3.916-1.566c1.07,0.087,2.195,0.568,3.277,1.396c0.783-0.67,1.266-1.3,1.275-1.313l0.48,0.362
- c-0.021,0.028-0.492,0.653-1.281,1.34C12.086,9.75,12.557,10.377,12.578,10.402z" />
- </svg>
- <p class="lh-sm pt-1" style="font-size: 1em;"><span>Niezbędnik<br>katolika</span></p>
- </a>
- </div>
- <!-- Menu -->
- <nav id="theme-main-menu">
- <ul class="mb-5">
- <li><a href="https://niezbednik.niedziela.pl">Strona główna</a></li>
- <li><a href="https://niezbednik.niedziela.pl/biblia">Biblia</a></li>
- <li><a href="https://niezbednik.niedziela.pl/liturgia#20260622">Kalendarz liturgiczny</a></li>
- <li><a href="/dzial/5/Modlitewnik">Modlitewnik</a></li>
- <li><a href="https://niezbednik.niedziela.pl/spiewnik">Śpiewnik</a></li>
- <li><a href="https://www.niedziela.pl/dzial/6/Wiara">Wiara</a></li>
- </ul>
-
- - -<div class="text-center mb-3 mx-auto p-3 border background-red-dark"> - <p class="m-0 mb-2 text-danger text-center font-sans text-white" style="line-height: 1"><small>Na funkcjonowanie serwisu do końca II kwartału: </small><span class="fw-bold">144 000 zł</span></p> - <div class="progress border " style="height: 2rem;"> - <div class="progress-bar progress-bar-striped bg-danger" role="progressbar" aria-valuenow="75" aria-valuemin="0" aria-valuemax="100" style="width: 62%"><span class="fw-bold fs-5 mx-2" style="">62%</span></div> - </div> - <p class="m-0 mt-1 text-start font-sans text-white"><small>Uzbieraliśmy: </small><span class="fw-bold">89 471 zł</span></p> - - <div class="text-center mt-3"> - <a href="/wsparcie" class="btn btn-red m-0" data-clicksmap="liturgia-AsideBtnDonation-Desktop">Wesprzyj nas <svg xmlns="http://www.w3.org/2000/svg" - width="40" height="40" viewBox="0 0 40 40" fill="currentColor" class="bi"> - <path d="M20,2.796c-7.297,0-13.233,5.937-13.233,13.233S12.704,29.263,20,29.263c7.296,0,13.234-5.937,13.234-13.233 - S27.297,2.796,20,2.796z M20,5.442c5.837,0,10.587,4.75,10.587,10.587S25.838,26.617,20,26.617S9.414,21.867,9.414,16.03 - S14.163,5.442,20,5.442z M1.474,26.617v10.586H4.12v-7.94h7.121c-1.126-0.748-2.144-1.644-3.045-2.646H1.474z M31.804,26.617 - c-0.9,1.003-1.917,1.899-3.044,2.646h7.12v7.94h2.647V26.617H31.804z M6.767,31.91v2.647h26.467V31.91H6.767z" /> - <g> - <path d="M20.992,22.001h-6.898v-1.406l4.047-5.508h-3.805v-1.82h6.516v1.547l-3.938,5.367h4.078V22.001z" /> - <path d="M25.289,14.736l0.547-0.336l0.914,1.539l-1.461,0.875v5.188h-2.383v-3.727l-0.555,0.336l-0.883-1.539l1.438-0.875V9.845 - h2.383V14.736z" /> - </g> - </svg></a> - </div> - </div> -
-
- <div class="d-flex justify-content-center w-100 mt-4 mx-auto" style="bottom: 0;">
-
- <!-- Sidebar Footer -->
- <div class="text-center mx-2">
- <small class="color-white">Tworzony przez</small>
- <br><a href="//niedziela.pl"><img src="https://www.niedziela.pl/img/logo.jpg" class="img-fluid mb-2" style="height: 2em;"></a>
- </div>
- </div>
- </div>
- </nav>
-
-</aside> - <div id="theme-main"> - - - - <div class="pt-3 px-3" style="clear: both" id="content">
- <article> - - - - - - - - - <h1 class="mb-4 lh-1 text-uppercase"> - Czytania liturgiczne na dziś; - Rok A, II </h1> - <div class="row"> - - <div class="col-xs-12"> - - <div class="social-btn" style="margin: 0 0 0.5em 0" data-ayoshare="https://niezbednik.niedziela.pl/liturgia/2026-06-22"></div> - - </div> - -</div> - - - - - <p class="font-serif fw-bold"><em>Dzień Powszedni albo wspomnienie św. Paulina z Noli, biskupa albo wspomnienie świętych męczenników -Jana Fishera, biskupa, i Tomasza More'a</em></p> - - <p class="font-sans">Kolor szat: <span class="fw-bold">zielony albo biały albo czerwony</span></p> - - - - - - - - - - <ul class="nav nav-tabs" role="tablist"> - <li class="nav-item" role="presentation"> - <button class="nav-link active" id="tabnowy0-tab" data-bs-toggle="tab" data-bs-target="#tabnowy0" type="button" role="tab" aria-controls="tabnowy0" aria-selected="true">Nowy lekcjonarz</button> - </li> - - <li class="nav-item" role="presentation"> - <button class="nav-link " id="tabstary0-tab" data-bs-toggle="tab" data-bs-target="#tabstary0" type="button" role="tab" aria-controls="tabstary0" aria-selected="true">Stary lekcjonarz</button> - </li> - </ul> - - <div id="lekcjonarzTabContent0" class="tab-content m-2"> - <div class="tab-elementy tab-pane fade active show" id="tabnowy0"> - - <ul class="nav nav-tabs" role="tablist"> - <li class="nav-item" role="presentation"> - <button class="nav-link " id="tabnowy0all-tab" data-bs-toggle="tab" data-bs-target="#tabnowy0all" type="button" role="tab" aria-controls="tabnowy0all" aria-selected="true">Całość</button> - </li> - - <li class="nav-item" role="presentation"> - <button class="nav-link " id="tabnowy00-tab" data-bs-toggle="tab" data-bs-target="#tabnowy00" type="button" role="tab" aria-controls="tabnowy00" aria-selected="true">1. czytanie</button> - </li> - - <li class="nav-item" role="presentation"> - <button class="nav-link " id="tabnowy01-tab" data-bs-toggle="tab" data-bs-target="#tabnowy01" type="button" role="tab" aria-controls="tabnowy01" aria-selected="true">Psalm</button> - </li> - - <li class="nav-item" role="presentation"> - <button class="nav-link " id="tabnowy02-tab" data-bs-toggle="tab" data-bs-target="#tabnowy02" type="button" role="tab" aria-controls="tabnowy02" aria-selected="true">Aklamacja</button> - </li> - - <li class="nav-item" role="presentation"> - <button class="nav-link active" id="tabnowy03-tab" data-bs-toggle="tab" data-bs-target="#tabnowy03" type="button" role="tab" aria-controls="tabnowy03" aria-selected="true">Ewangelia</button> - </li> - - </ul> - - - <div id="elementyTabContent0" class="tab-content liturgia-content py-2 px-4 background-white"> - - <div class="tab-pane fade " id="tabnowy0all"> - - - <h2>1. czytanie (<a href="/biblia/druga-ksiega-krolewska/17" class="">2 Krl 17</a>, 5-8. 13-15a. 18)</h2><h4><em>Zdobycie Samarii przez Asyryjczyków</em></h4><p><strong>Czytanie z Drugiej Księgi Królewskiej</strong></p><p>Król asyryjski Salmanassar najechał cały kraj, dotarł do Samarii i oblegał ją przez trzy lata. W dziewiątym roku panowania Ozeasza król asyryjski zdobył Samarię i uprowadził Izraelitów na wygnanie do Asyrii. Osiedlił ich w Chalach, nad Chabor, rzeką Gozanu, i w miastach Medii.</p>
-<p>Stało się tak, bo Izraelici zgrzeszyli przeciwko Panu, Bogu swemu, który ich wyprowadził z Egiptu, spod ręki faraona, króla egipskiego. Czcili oni cudzych bogów i naśladowali obyczaje ludów, które Pan wypędził przed Izraelitami, oraz królów izraelskich, których wybrali.</p>
-<p>Pan jednak ciągle ostrzegał Izraela i Judę przez wszystkich swoich proroków i wszystkich „widzących”, mówiąc: «Zawróćcie z waszych dróg grzesznych i przestrzegajcie moich przykazań i postanowień moich, według całego Prawa, które nadałem waszym przodkom i które przekazałem wam przez sługi moje, proroków». Lecz oni nie słuchali i twardym uczynili swój kark, jak ich przodkowie, którzy nie zawierzyli Panu, Bogu swojemu. Odrzucili przykazania Jego i przymierze, które zawarł z przodkami, oraz prawa, które im nadał.</p>
-<p>Wtedy Pan zapłonął gwałtownym gniewem przeciw Izraelowi i odrzucił go sprzed swego oblicza. Pozostało tylko samo pokolenie Judy.</p> - - <h2>Psalm (<a href="/biblia/ksiega-psalmow/60" class="">Ps 60 (59)</a>, 3-4. 5 i 12. 13-14 (R.: por. 7b))</h2><h4><em>Usłysz nas, Panie, wspomóż Twą prawicą</em></h4><p><strong></strong></p><p>Odrzuciłeś nas i złamałeś, Boże, *
-<br>rozgniewałeś się, lecz powróć do nas!
-<br>Wstrząsnąłeś i rozdarłeś ziemię, *
-<br>ulecz jej rozdarcia, albowiem się chwieje.</p><p><strong>Usłysz nas, Panie, wspomóż Twą prawicą</strong></p>
-
-<p>Ludowi Twemu zgotowałeś los twardy, *
-<br>napoiłeś nas winem, które moc odbiera.
-<br>Czyż nie Ty, Boże, który nas odrzuciłeś *
-<br>i już nie wychodzisz z naszymi wojskami?</p><p><strong>Usłysz nas, Panie, wspomóż Twą prawicą</strong></p>
-
-<p>Daj nam pomoc przeciw nieprzyjacielowi, *
-<br>bo ludzkie wsparcie jest zawodne.
-<br>Dokonamy w Bogu czynów pełnych mocy, *
-<br>a On podepcze naszych nieprzyjaciół.</p><p><strong>Usłysz nas, Panie, wspomóż Twą prawicą</strong></p> - - <h2>Aklamacja (Por. Hbr 4, 12)</h2><h4><em>Alleluja, alleluja, alleluja</em></h4><p><strong></strong></p><p>Żywe jest słowo Boże i skuteczne,
-<br>zdolne osądzić pragnienia i myśli serca.</p><p><strong>Alleluja, alleluja, alleluja</strong></p>
- - - <h2>Ewangelia (<a href="/biblia/ewangelia-wg-sw-mateusza/7" class="">Mt 7</a>, 1-5)</h2><h4><em>Usuń najpierw belkę ze swego oka</em></h4><p><strong>Słowa Ewangelii według Świętego Mateusza</strong></p><p>Jezus powiedział do swoich uczniów:</p>
-<p>«Nie sądźcie, abyście nie byli sądzeni. Bo takim sądem, jakim sądzicie, i was osądzą; i taką miarą, jaką wy mierzycie, wam odmierzą.</p>
-<p>Czemu to widzisz drzazgę w oku swego brata, a nie dostrzegasz belki we własnym oku? Albo jak możesz mówić swemu bratu: Pozwól, że usunę drzazgę z twego oka, podczas gdy belka tkwi w twoim oku? Obłudniku, usuń najpierw belkę ze swego oka, a wtedy przejrzysz, ażeby usunąć drzazgę z oka twego brata».</p> - </div> - - - <div class="tab-pane fade " id="tabnowy00"> - - <h2>1. czytanie (<a href="/biblia/druga-ksiega-krolewska/17" class="">2 Krl 17</a>, 5-8. 13-15a. 18)</h2><h4><em>Zdobycie Samarii przez Asyryjczyków</em></h4><p><strong>Czytanie z Drugiej Księgi Królewskiej</strong></p><p>Król asyryjski Salmanassar najechał cały kraj, dotarł do Samarii i oblegał ją przez trzy lata. W dziewiątym roku panowania Ozeasza król asyryjski zdobył Samarię i uprowadził Izraelitów na wygnanie do Asyrii. Osiedlił ich w Chalach, nad Chabor, rzeką Gozanu, i w miastach Medii.</p>
-<p>Stało się tak, bo Izraelici zgrzeszyli przeciwko Panu, Bogu swemu, który ich wyprowadził z Egiptu, spod ręki faraona, króla egipskiego. Czcili oni cudzych bogów i naśladowali obyczaje ludów, które Pan wypędził przed Izraelitami, oraz królów izraelskich, których wybrali.</p>
-<p>Pan jednak ciągle ostrzegał Izraela i Judę przez wszystkich swoich proroków i wszystkich „widzących”, mówiąc: «Zawróćcie z waszych dróg grzesznych i przestrzegajcie moich przykazań i postanowień moich, według całego Prawa, które nadałem waszym przodkom i które przekazałem wam przez sługi moje, proroków». Lecz oni nie słuchali i twardym uczynili swój kark, jak ich przodkowie, którzy nie zawierzyli Panu, Bogu swojemu. Odrzucili przykazania Jego i przymierze, które zawarł z przodkami, oraz prawa, które im nadał.</p>
-<p>Wtedy Pan zapłonął gwałtownym gniewem przeciw Izraelowi i odrzucił go sprzed swego oblicza. Pozostało tylko samo pokolenie Judy.</p> - </div> - - <div class="tab-pane fade " id="tabnowy01"> - - <h2>Psalm (<a href="/biblia/ksiega-psalmow/60" class="">Ps 60 (59)</a>, 3-4. 5 i 12. 13-14 (R.: por. 7b))</h2><h4><em>Usłysz nas, Panie, wspomóż Twą prawicą</em></h4><p><strong></strong></p><p>Odrzuciłeś nas i złamałeś, Boże, *
-<br>rozgniewałeś się, lecz powróć do nas!
-<br>Wstrząsnąłeś i rozdarłeś ziemię, *
-<br>ulecz jej rozdarcia, albowiem się chwieje.</p><p><strong>Usłysz nas, Panie, wspomóż Twą prawicą</strong></p>
-
-<p>Ludowi Twemu zgotowałeś los twardy, *
-<br>napoiłeś nas winem, które moc odbiera.
-<br>Czyż nie Ty, Boże, który nas odrzuciłeś *
-<br>i już nie wychodzisz z naszymi wojskami?</p><p><strong>Usłysz nas, Panie, wspomóż Twą prawicą</strong></p>
-
-<p>Daj nam pomoc przeciw nieprzyjacielowi, *
-<br>bo ludzkie wsparcie jest zawodne.
-<br>Dokonamy w Bogu czynów pełnych mocy, *
-<br>a On podepcze naszych nieprzyjaciół.</p><p><strong>Usłysz nas, Panie, wspomóż Twą prawicą</strong></p> - </div> - - <div class="tab-pane fade " id="tabnowy02"> - - <h2>Aklamacja (Por. Hbr 4, 12)</h2><h4><em>Alleluja, alleluja, alleluja</em></h4><p><strong></strong></p><p>Żywe jest słowo Boże i skuteczne,
-<br>zdolne osądzić pragnienia i myśli serca.</p><p><strong>Alleluja, alleluja, alleluja</strong></p>
- - </div> - - - - <div class="tab-pane fade active show" id="tabnowy03"> - - - - - <h2>Ewangelia (<a href="/biblia/ewangelia-wg-sw-mateusza/7" class="">Mt 7</a>, 1-5)</h2><h4><em>Usuń najpierw belkę ze swego oka</em></h4><p><strong>Słowa Ewangelii według Świętego Mateusza</strong></p><p>Jezus powiedział do swoich uczniów:</p>
-<p>«Nie sądźcie, abyście nie byli sądzeni. Bo takim sądem, jakim sądzicie, i was osądzą; i taką miarą, jaką wy mierzycie, wam odmierzą.</p>
-<p>Czemu to widzisz drzazgę w oku swego brata, a nie dostrzegasz belki we własnym oku? Albo jak możesz mówić swemu bratu: Pozwól, że usunę drzazgę z twego oka, podczas gdy belka tkwi w twoim oku? Obłudniku, usuń najpierw belkę ze swego oka, a wtedy przejrzysz, ażeby usunąć drzazgę z oka twego brata».</p> - - </div> - - </div> - - <div class="prev-next text-center"> - <a href="#" class="btn btn-default disabled prev-tab fs-4"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-left" viewBox="0 0 16 16"> - <path fill-rule="evenodd" d="M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z"/> -</svg></a> - <a href="#" class="btn btn-default next-tab fs-4"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-right" viewBox="0 0 16 16"> - <path fill-rule="evenodd" d="M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z"/> -</svg></a> - </div> - </div> - - <div class="tab-elementy tab-pane fade " id="tabstary0"> - - <ul class="nav nav-tabs"> - <li class="nav-item" role="presentation"> - <button class="nav-link " id="tabstary0all-tab" data-bs-toggle="tab" data-bs-target="#tabstary0all" type="button" role="tab" aria-controls="tabstary0all" aria-selected="true">Całość</button> - </li> - <li class="nav-item" role="presentation"> - <button class="nav-link " id="tabstary00-tab" data-bs-toggle="tab" data-bs-target="#tabstary00" type="button" role="tab" aria-controls="tabstary00" aria-selected="true">1. czytanie</button> - </li> - - <li class="nav-item" role="presentation"> - <button class="nav-link " id="tabstary01-tab" data-bs-toggle="tab" data-bs-target="#tabstary01" type="button" role="tab" aria-controls="tabstary01" aria-selected="true">Psalm</button> - </li> - - <li class="nav-item" role="presentation"> - <button class="nav-link " id="tabstary02-tab" data-bs-toggle="tab" data-bs-target="#tabstary02" type="button" role="tab" aria-controls="tabstary02" aria-selected="true">Aklamacja</button> - </li> - - <li class="nav-item" role="presentation"> - <button class="nav-link active" id="tabstary03-tab" data-bs-toggle="tab" data-bs-target="#tabstary03" type="button" role="tab" aria-controls="tabstary03" aria-selected="true">Ewangelia</button> - </li> - - </ul> - - - <div id="elementyStaryTabContent0" class="tab-content liturgia-content py-2 px-4 background-white"> - - <div class="tab-pane fade " id="tabstary0all"> - - <h2>1. czytanie (<a href="/biblia/druga-ksiega-krolewska/17" class="">2 Krl 17</a>, 5-8. 13-15a. 18)</h2><h4><em>Zdobycie Samarii przez Asyryjczyków</em></h4><p><strong>Czytanie z Drugiej Księgi Królewskiej</strong></p><p>Król asyryjski Salmanassar najechał cały kraj, przyszedł pod Samarię i oblegał ją przez trzy lata. W dziewiątym roku Ozeasza król asyryjski zdobył Samarię i zabrał Izraelitów w niewolę do Asyrii, i przesiedlił ich do Chałach, nad Chabor - rzekę Gozanu, i do miast Medów.</p>
-
-<p>Stało się tak, bo Izraelici zgrzeszyli przeciwko Panu Bogu swemu, który ich wyprowadził z Egiptu, spod ręki faraona, króla egipskiego. Czcili oni bogów obcych i naśladowali obyczaje ludów, które Pan wypędził przed Izraelitami, oraz królów izraelskich, których wybrali.</p>
-
-<p>Pan jednak ciągle ostrzegał Izraela i Judę przez wszystkich swoich proroków i wszystkich „Widzących”, mówiąc: „Zawróćcie z waszych dróg grzesznych i przestrzegajcie poleceń moich i postanowień moich, według całego Prawa, które nadałem waszym przodkom i które przekazałem wam przez sługi moje, proroków”. Lecz oni nie słuchali i twardym uczynili swój kark, jak kark ich przodków, którzy nie zawierzyli Panu Bogu swojemu. Odrzucili przykazania Jego i przymierze, które zawarł z przodkami, oraz rozkazy, które im wydał.</p>
-
-<p>Wtedy Pan zapłonął gwałtownym gniewem przeciw Izraelowi i odrzucił go od swego oblicza. Pozostało tylko samo pokolenie Judy.</p> - - <h2>Psalm (<a href="/biblia/ksiega-psalmow/60" class="">Ps 60</a>, 3-4. 5 i 12. 13-14)</h2><h4><em>Usłysz nas, Panie, wspomóż Twą prawicą</em></h4><p><strong></strong></p><p>Odrzuciłeś nas i złamałeś, Boże,
-<br>rozgniewałeś się, lecz powróć do nas.
-<br>Wstrząsnąłeś i rozdarłeś ziemię,
-<br>ulecz jej rozdarcia, albowiem się chwieje.</p><p><strong>Usłysz nas, Panie, wspomóż Twą prawicą</strong></p>
-
-<p>Ludowi Twemu zgotowałeś los twardy,
-<br>napoiłeś nas winem, które moc odbiera.
-<br>Czyż nie Ty, o Boże, nas odrzuciłeś
-<br>i już nie wychodzisz, Boże, z naszymi wojskami?</p><p><strong>Usłysz nas, Panie, wspomóż Twą prawicą</strong></p>
-
-<p>Daj nam pomoc przeciw nieprzyjacielowi,
-<br>bo ludzkie wsparcie jest zawodne.
-<br>Dokonamy w Bogu czynów pełnych mocy,
-<br>a On podepcze naszych nieprzyjaciół.</p><p><strong>Usłysz nas, Panie, wspomóż Twą prawicą</strong></p> - - <h2>Aklamacja (<a href="/biblia/list-do-hebrajczykow/4" class="">Hbr 4</a>, 12)</h2><h4><em>Alleluja, alleluja, alleluja</em></h4><p><strong></strong></p><p>Żywe jest słowo Boże i skuteczne,
-<br>zdolne osądzić pragnienia i myśli serca.</p><p><strong>Alleluja, alleluja, alleluja</strong></p>
- - - <h2>Ewangelia (<a href="/biblia/ewangelia-wg-sw-mateusza/7" class="">Mt 7</a>, 1-5)</h2><h4><em>Drzazga i belka</em></h4><p><strong>Słowa Ewangelii według świętego Mateusza</strong></p><p>Jezus powiedział do swoich uczniów:</p>
-<p>„Nie sądźcie, abyście nie byli sądzeni. Bo takim sądem, jakim wy sądzicie, i was osądzą; i taką miarą, jaką wy mierzycie, wam odmierzą.</p>
-
-<p>Czemu to widzisz drzazgę w oku swego brata, a belki we własnym oku nie dostrzegasz? Albo jak możesz mówić swemu bratu: «Pozwól, że usunę drzazgę z twego oka», gdy belka tkwi w twoim oku? Obłudniku, wyrzuć najpierw belkę ze swego oka, a wtedy przejrzysz, ażeby usunąć drzazgę z oka twego brata”.</p> - </div> - - - <div class="tab-pane fade " id="tabstary00"> - - <h2>1. czytanie (<a href="/biblia/druga-ksiega-krolewska/17" class="">2 Krl 17</a>, 5-8. 13-15a. 18)</h2><h4><em>Zdobycie Samarii przez Asyryjczyków</em></h4><p><strong>Czytanie z Drugiej Księgi Królewskiej</strong></p><p>Król asyryjski Salmanassar najechał cały kraj, przyszedł pod Samarię i oblegał ją przez trzy lata. W dziewiątym roku Ozeasza król asyryjski zdobył Samarię i zabrał Izraelitów w niewolę do Asyrii, i przesiedlił ich do Chałach, nad Chabor - rzekę Gozanu, i do miast Medów.</p>
-
-<p>Stało się tak, bo Izraelici zgrzeszyli przeciwko Panu Bogu swemu, który ich wyprowadził z Egiptu, spod ręki faraona, króla egipskiego. Czcili oni bogów obcych i naśladowali obyczaje ludów, które Pan wypędził przed Izraelitami, oraz królów izraelskich, których wybrali.</p>
-
-<p>Pan jednak ciągle ostrzegał Izraela i Judę przez wszystkich swoich proroków i wszystkich „Widzących”, mówiąc: „Zawróćcie z waszych dróg grzesznych i przestrzegajcie poleceń moich i postanowień moich, według całego Prawa, które nadałem waszym przodkom i które przekazałem wam przez sługi moje, proroków”. Lecz oni nie słuchali i twardym uczynili swój kark, jak kark ich przodków, którzy nie zawierzyli Panu Bogu swojemu. Odrzucili przykazania Jego i przymierze, które zawarł z przodkami, oraz rozkazy, które im wydał.</p>
-
-<p>Wtedy Pan zapłonął gwałtownym gniewem przeciw Izraelowi i odrzucił go od swego oblicza. Pozostało tylko samo pokolenie Judy.</p> - </div> - - <div class="tab-pane fade " id="tabstary01"> - - <h2>Psalm (<a href="/biblia/ksiega-psalmow/60" class="">Ps 60</a>, 3-4. 5 i 12. 13-14)</h2><h4><em>Usłysz nas, Panie, wspomóż Twą prawicą</em></h4><p><strong></strong></p><p>Odrzuciłeś nas i złamałeś, Boże,
-<br>rozgniewałeś się, lecz powróć do nas.
-<br>Wstrząsnąłeś i rozdarłeś ziemię,
-<br>ulecz jej rozdarcia, albowiem się chwieje.</p><p><strong>Usłysz nas, Panie, wspomóż Twą prawicą</strong></p>
-
-<p>Ludowi Twemu zgotowałeś los twardy,
-<br>napoiłeś nas winem, które moc odbiera.
-<br>Czyż nie Ty, o Boże, nas odrzuciłeś
-<br>i już nie wychodzisz, Boże, z naszymi wojskami?</p><p><strong>Usłysz nas, Panie, wspomóż Twą prawicą</strong></p>
-
-<p>Daj nam pomoc przeciw nieprzyjacielowi,
-<br>bo ludzkie wsparcie jest zawodne.
-<br>Dokonamy w Bogu czynów pełnych mocy,
-<br>a On podepcze naszych nieprzyjaciół.</p><p><strong>Usłysz nas, Panie, wspomóż Twą prawicą</strong></p> - </div> - - <div class="tab-pane fade " id="tabstary02"> - - <h2>Aklamacja (<a href="/biblia/list-do-hebrajczykow/4" class="">Hbr 4</a>, 12)</h2><h4><em>Alleluja, alleluja, alleluja</em></h4><p><strong></strong></p><p>Żywe jest słowo Boże i skuteczne,
-<br>zdolne osądzić pragnienia i myśli serca.</p><p><strong>Alleluja, alleluja, alleluja</strong></p>
- - </div> - - - - <div class="tab-pane fade active show" id="tabstary03"> - - - - - <h2>Ewangelia (<a href="/biblia/ewangelia-wg-sw-mateusza/7" class="">Mt 7</a>, 1-5)</h2><h4><em>Drzazga i belka</em></h4><p><strong>Słowa Ewangelii według świętego Mateusza</strong></p><p>Jezus powiedział do swoich uczniów:</p>
-<p>„Nie sądźcie, abyście nie byli sądzeni. Bo takim sądem, jakim wy sądzicie, i was osądzą; i taką miarą, jaką wy mierzycie, wam odmierzą.</p>
-
-<p>Czemu to widzisz drzazgę w oku swego brata, a belki we własnym oku nie dostrzegasz? Albo jak możesz mówić swemu bratu: «Pozwól, że usunę drzazgę z twego oka», gdy belka tkwi w twoim oku? Obłudniku, wyrzuć najpierw belkę ze swego oka, a wtedy przejrzysz, ażeby usunąć drzazgę z oka twego brata”.</p> - - </div> - - </div> - - <div class="prev-next text-center mb-3"> - <a href="#" class="btn btn-default disabled prev-tab fs-4"> - <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-left" viewBox="0 0 16 16"> - <path fill-rule="evenodd" d="M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z"/> -</svg></a> - <a href="#" class="btn btn-default next-tab fs-4"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-right" viewBox="0 0 16 16"> - <path fill-rule="evenodd" d="M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z"/> -</svg></a> - </div> - </div> - - </div> - - - - -<div class="card border-0 px-lg-4 px-1 py-1 my-1 flat-alizarin"> - <div class="card-body text-md-left"> - <h2 class="mb-4 lh-1 text-uppercase">Polecamy</h2> - <div class="row align-items-start"> - - <div class="col-12"> - - - <p>Czytania Liturgiczne pochodzą z Lekcjonarza wydanego przez:<br><a href="http://www.pallottinum.pl/" data-clicksmap="liturgia-PanelZTLekcjonarzZrodlo-Desktop"><strong>Wydawnictwo Pallottinum</strong> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-right " viewBox="0 0 16 16">
- <path fill-rule="evenodd" d="M1 8a.5.5 0 0 1 .5-.5h11.793l-3.147-3.146a.5.5 0 0 1 .708-.708l4 4a.5.5 0 0 1 0 .708l-4 4a.5.5 0 0 1-.708-.708L13.293 8.5H1.5A.5.5 0 0 1 1 8z"/>
- </svg></a></p> - - </div> - </div> - </div> -</div> - -<div class="card border-0 px-lg-3 px-1 py-1 my-4 background-primary" > - <div class="card-body text-md-left"> - - <h2 class="mb-4 lh-1 text-uppercase" style="letter-spacing:2px">Pomóż w rozwoju serwisu </h2> - <div class="row align-items-start"> - <div class="col-md-9"> - - - <p>Aby nasz serwis mógł się rozwijać i trwać potrzebujemy regularnego wsparcia finansowego. Nie publikujemy komercyjnych reklam, jedynym źródłem finansowania jest Państwa wsparcie.<br>Zostań naszym patronem i ofiaruj nam wsparcie finansowe.</p> - -<div class="text-center mb-3 mx-auto p-3 border background-red-dark"> - <p class="m-0 mb-2 text-danger text-center font-sans text-white" style="line-height: 1"><small>Na funkcjonowanie serwisu do końca II kwartału: </small><span class="fw-bold">144 000 zł</span></p> - <div class="progress border " style="height: 2rem;"> - <div class="progress-bar progress-bar-striped bg-danger" role="progressbar" aria-valuenow="75" aria-valuemin="0" aria-valuemax="100" style="width: 62%"><span class="fw-bold fs-5 mx-2" style="">62%</span></div> - </div> - <p class="m-0 mt-1 text-start font-sans text-white"><small>Uzbieraliśmy: </small><span class="fw-bold">89 471 zł</span></p> - - <div class="text-center mt-3"> - <a href="/wsparcie" class="btn btn-red m-0" data-clicksmap="liturgia-AsideBtnDonation-Desktop">Wesprzyj nas <svg xmlns="http://www.w3.org/2000/svg" - width="40" height="40" viewBox="0 0 40 40" fill="currentColor" class="bi"> - <path d="M20,2.796c-7.297,0-13.233,5.937-13.233,13.233S12.704,29.263,20,29.263c7.296,0,13.234-5.937,13.234-13.233 - S27.297,2.796,20,2.796z M20,5.442c5.837,0,10.587,4.75,10.587,10.587S25.838,26.617,20,26.617S9.414,21.867,9.414,16.03 - S14.163,5.442,20,5.442z M1.474,26.617v10.586H4.12v-7.94h7.121c-1.126-0.748-2.144-1.644-3.045-2.646H1.474z M31.804,26.617 - c-0.9,1.003-1.917,1.899-3.044,2.646h7.12v7.94h2.647V26.617H31.804z M6.767,31.91v2.647h26.467V31.91H6.767z" /> - <g> - <path d="M20.992,22.001h-6.898v-1.406l4.047-5.508h-3.805v-1.82h6.516v1.547l-3.938,5.367h4.078V22.001z" /> - <path d="M25.289,14.736l0.547-0.336l0.914,1.539l-1.461,0.875v5.188h-2.383v-3.727l-0.555,0.336l-0.883-1.539l1.438-0.875V9.845 - h2.383V14.736z" /> - </g> - </svg></a> - </div> - </div> - - - </div> - <div class="col-12 col-md-3 mt-4 mt-md-0"> - <img src="https://niezbednik.niedziela.pl/images/dotacja.png" alt="" class="img-fluid w-75 mx-auto d-block"> - </div> - - </div> - </div> -</div> - -<div class="card border-0 px-lg-3 px-1 py-1 my-4 background-primary-01" > - <div class="card-body text-md-left"> - - <h2 class="mb-4 lh-1 text-uppercase" style="letter-spacing:2px">Nowości w Rafaelu </h2> - <div class="row align-items-start"> - <div class="col-12"> - - - -<div class="row"> - <div class="col-md-2"> - <img src="//niezbednik.niedziela.pl/images/ksiazki/rafael-seewald.png" class="img-fluid"> - </div> - <div class="col-md-10"> - <p><strong>Odkrywanie wieczności - Peter Seewald</strong> - <br>To głęboko duchowa i inspirująca książka o sensie życia, która pomaga zatrzymać się i spojrzeć na codzienność z nowej perspektywy. Autor proponuje rewolucyjny sposób patrzenia na życie „od końca”, który pozwala lepiej zrozumieć, co jest naprawdę ważne. <br><a href="https://rafael.pl/odkrywanie-wiecznosci?utm_source=niedziela&utm_medium=cpc&utm_id=odkrywaniewiecznosci_niedziela" class="btn fw-bold" data-clicksmap="liturgia-RafaelSeewaldOferta-Desktop">ZOBACZ</a> - </p> - </div> - -</div> - - - </div> - - </div> - </div> -</div> -<div class="card border-0 px-lg-3 px-1 py-1 my-4 background-primary-01" > - <div class="card-body text-md-left"> - - <h2 class="mb-4 lh-1 text-uppercase" style="letter-spacing:2px">Polecamy </h2> - <div class="row align-items-start"> - <div class="col-12"> - - - - - - <div class="row"> - <div class="col-lg-2 mb-2 text-center"> - <img src="//niezbednik.niedziela.pl/images/ksiazki/ksiazka-credo.jpg" class="img-fluid"> - </div> - <div class="col-lg-10"> - <p class="pe-2 font-sans"><strong>Credo krok po kroku</strong> - <br><small><strong></strong></small> - - <br>Modlitwa "Wierzę w Boga" jest drogowskazem na drodze duchowego wzrastania. Dzięki książce "Credo" krok po kroku możemy to jeszcze pełniej zrozumieć. </p> - <p class=""> - - <a href="https://www.niedziela.pl/artykul/113896/Credo-Krok-po-kroku-%E2%80%93-ks-prof-Janusz-Lekan?utm_source=niezbednikKatolika&utm_medium=AdsArticleBtnDesktop&utm_campaign=AdsArticleBtnDesktop" class="btn btn-primary" data-clicksmap="liturgia-AdsArticleCredoBtn-Desktop">Zobacz</a> - - </p> - </div> - </div> - - - </div> - - </div> - </div> -</div> - <div class="row"> - <div class="col-6"> - <a class="btn btn-default d-block" href="/liturgia/2026-06-21" data-clicksmap="site:liturgia - liturgiaTopPrevDay - /liturgia/2026-06-21"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-left" viewBox="0 0 16 16"> - <path fill-rule="evenodd" d="M15 8a.5.5 0 0 0-.5-.5H2.707l3.147-3.146a.5.5 0 1 0-.708-.708l-4 4a.5.5 0 0 0 0 .708l4 4a.5.5 0 0 0 .708-.708L2.707 8.5H14.5A.5.5 0 0 0 15 8z"/> -</svg> Czytania na 21 czerwca</a> - </div> - <div class="col-6"> - <a class="btn btn-default d-block me-0" href="/liturgia/2026-06-23" data-clicksmap="site:liturgia - liturgiaTopNextDay - /liturgia/2026-06-23">Czytania na 23 czerwca <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-right" viewBox="0 0 16 16"> - <path fill-rule="evenodd" d="M1 8a.5.5 0 0 1 .5-.5h11.793l-3.147-3.146a.5.5 0 0 1 .708-.708l4 4a.5.5 0 0 1 0 .708l-4 4a.5.5 0 0 1-.708-.708L13.293 8.5H1.5A.5.5 0 0 1 1 8z"/> -</svg></a> - </div> - </div> - </article> - - -<div class="card border-0 px-lg-3 px-1 py-1 my-4 " id="rozwazania"> - <div class="card-body text-md-left"> - - <h2 class="mb-4 lh-1 text-uppercase" style="letter-spacing:2px">Rozważania na dziś </h2> - <div class="row align-items-start"> - <div class="col-12"> - - - - - - -<div class="swiper-container swiper-rozwazania swiper-with-scroll"> - <!-- Additional required wrapper --> - <div class="swiper-wrapper mb-2"> - <!-- Slides --> - - - - - - - - <div class="swiper-slide mb-2 swiper-slide-equal-height"> - <a href="/artykul/7527/Kilka-slow-o-Slowie-22-VI-2026" data-clicksmap="liturgia-PanelRozwazania:/artykul/7527/Kilka-slow-o-Slowie-22-VI-2026-Desktop"> - <div class="card h-100 shadow-sm"> - - - <div class="text-center"> - - - <div class="img-hover-zoom img-hover-zoom--colorize position-relative"> - <!--<div class="card-icon"> - <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-caret-right-fill" viewBox="0 0 16 16"> - <path d="m12.14 8.753-5.482 4.796c-.646.566-1.658.106-1.658-.753V3.204a1 1 0 0 1 1.659-.753l5.48 4.796a1 1 0 0 1 0 1.506z"/> -</svg> - </div>--> - <div class="card-icon1"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-youtube" viewBox="0 0 16 16"> - <path d="M8.051 1.999h.089c.822.003 4.987.033 6.11.335a2.01 2.01 0 0 1 1.415 1.42c.101.38.172.883.22 1.402l.01.104.022.26.008.104c.065.914.073 1.77.074 1.957v.075c-.001.194-.01 1.108-.082 2.06l-.008.105-.009.104c-.05.572-.124 1.14-.235 1.558a2.007 2.007 0 0 1-1.415 1.42c-1.16.312-5.569.334-6.18.335h-.142c-.309 0-1.587-.006-2.927-.052l-.17-.006-.087-.004-.171-.007-.171-.007c-1.11-.049-2.167-.128-2.654-.26a2.007 2.007 0 0 1-1.415-1.419c-.111-.417-.185-.986-.235-1.558L.09 9.82l-.008-.104A31.4 31.4 0 0 1 0 7.68v-.123c.002-.215.01-.958.064-1.778l.007-.103.003-.052.008-.104.022-.26.01-.104c.048-.519.119-1.023.22-1.402a2.007 2.007 0 0 1 1.415-1.42c.487-.13 1.544-.21 2.654-.26l.17-.007.172-.006.086-.003.171-.007A99.788 99.788 0 0 1 7.858 2h.193zM6.4 5.209v4.818l4.157-2.408L6.4 5.209z"/> -</svg> - - </div> - <img class="shadow" src="https://niezbednik.niedziela.pl/images/legan.jpg" - alt=""> - </div> - - </div> - - <div class="card-body"> - <div class="clearfix mb-3"> - - - - - </div> - - - <div class="my-2 text-center"> - - <h3 class="lh-sm"> - O. Michał Legan OSPPE - <br><small><i>Kilka słów o Słowie</i></small> - </h3> - - </div> - <div class="mb-3"> - - <p class="text-uppercase text-center role"></p> - - </div> - - - </div> - </a> - </div> - - <!--<div class="card"> - <a class="panel-link" href="/artykul/7527/Kilka-slow-o-Slowie-22-VI-2026" data-clicksmap="site:liturgia - PanelRozwazanie - /artykul/7527/Kilka-slow-o-Slowie-22-VI-2026">O. Michał Legan OSPPE <i class="fa fa-arrow-circle-right"></i></a> - </div>--> - </div> - - - - - <div class="swiper-slide mb-2 swiper-slide-equal-height"> - <a href="https://www.niedziela.pl/artykul/124912" data-clicksmap="liturgia-PanelRozwazania:https://www.niedziela.pl/artykul/124912-Desktop"> - <div class="card h-100 shadow-sm"> - - - <div class="text-center"> - - - <div class="img-hover-zoom img-hover-zoom--colorize position-relative"> - <img class="shadow" src="https://niezbednik.niedziela.pl/images/wydpomoc.jpg" - alt=""> - </div> - - </div> - - <div class="card-body"> - <div class="clearfix mb-3"> - - - - - </div> - - - <div class="my-2 text-center"> - - <h3 class="lh-sm"> - Wydawnictwo „Pomoc”<br><small><i>Żyć Ewangelią</i></small> </h3> - - </div> - <div class="mb-3"> - - <p class="text-uppercase text-center role"></p> - - </div> - - - </div> - </a> - </div> - - <!--<div class="card"> - <a class="panel-link" href="https://www.niedziela.pl/artykul/124912" data-clicksmap="site:liturgia - PanelRozwazanie - https://www.niedziela.pl/artykul/124912">"Żyć Ewangelią" (wyd. Pomoc) <i class="fa fa-arrow-circle-right"></i></a> - </div>--> - </div> - - - - - <div class="swiper-slide mb-2 swiper-slide-equal-height"> - <a href="https://www.niedziela.pl/artykul/124945" data-clicksmap="liturgia-PanelRozwazania:https://www.niedziela.pl/artykul/124945-Desktop"> - <div class="card h-100 shadow-sm"> - - - <div class="text-center"> - - - <div class="img-hover-zoom img-hover-zoom--colorize position-relative"> - <img class="shadow" src="https://niezbednik.niedziela.pl/images/mlotek.jpg" - alt=""> - </div> - - </div> - - <div class="card-body"> - <div class="clearfix mb-3"> - - - - - </div> - - - <div class="my-2 text-center"> - - <h3 class="lh-sm"> - Ks. Krzysztof Młotek - <br><small><i>Glossa marginalia</i></small> - </h3> - - </div> - <div class="mb-3"> - - <p class="text-uppercase text-center role"></p> - - </div> - - - </div> - </a> - </div> - - <!--<div class="card"> - <a class="panel-link" href="https://www.niedziela.pl/artykul/124945" data-clicksmap="site:liturgia - PanelRozwazanie - https://www.niedziela.pl/artykul/124945">Ks. Krzysztof Młotek <i class="fa fa-arrow-circle-right"></i></a> - </div>--> - </div> - - - - - <div class="swiper-slide mb-2 swiper-slide-equal-height"> - <a href="/artykul/1362/O-co-prosze-O-ludzka-zyczliwosc-i-dobroc" data-clicksmap="liturgia-PanelRozwazania:/artykul/1362/O-co-prosze-O-ludzka-zyczliwosc-i-dobroc-Desktop"> - <div class="card h-100 shadow-sm"> - - - <div class="text-center"> - - - <div class="img-hover-zoom img-hover-zoom--colorize position-relative"> - <img class="shadow" src="https://niezbednik.niedziela.pl/images/wons.jpg" - alt=""> - </div> - - </div> - - <div class="card-body"> - <div class="clearfix mb-3"> - - - - - </div> - - - <div class="my-2 text-center"> - - <h3 class="lh-sm"> - Krzysztof Wons SDS/Salwator - <br><small><i>O co proszę?</i></small> </h3> - - </div> - <div class="mb-3"> - - <p class="text-uppercase text-center role"></p> - - </div> - - - </div> - </a> - </div> - - <!--<div class="card"> - <a class="panel-link" href="/artykul/1362/O-co-prosze-O-ludzka-zyczliwosc-i-dobroc" data-clicksmap="site:liturgia - PanelRozwazanie - /artykul/1362/O-co-prosze-O-ludzka-zyczliwosc-i-dobroc">Krzysztof Wons SDS/Salwator <i class="fa fa-arrow-circle-right"></i></a> - </div>--> - </div> - - - - - <div class="swiper-slide mb-2 swiper-slide-equal-height"> - <a href="/artykul/7525/Gospel-dla-zabieganych-22-VI-2026" data-clicksmap="liturgia-PanelRozwazania:/artykul/7525/Gospel-dla-zabieganych-22-VI-2026-Desktop"> - <div class="card h-100 shadow-sm"> - - - <div class="text-center"> - - - <div class="img-hover-zoom img-hover-zoom--colorize position-relative"> - <!--<div class="card-icon"> - <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-caret-right-fill" viewBox="0 0 16 16"> - <path d="m12.14 8.753-5.482 4.796c-.646.566-1.658.106-1.658-.753V3.204a1 1 0 0 1 1.659-.753l5.48 4.796a1 1 0 0 1 0 1.506z"/> -</svg> - </div>--> - <div class="card-icon1"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-youtube" viewBox="0 0 16 16"> - <path d="M8.051 1.999h.089c.822.003 4.987.033 6.11.335a2.01 2.01 0 0 1 1.415 1.42c.101.38.172.883.22 1.402l.01.104.022.26.008.104c.065.914.073 1.77.074 1.957v.075c-.001.194-.01 1.108-.082 2.06l-.008.105-.009.104c-.05.572-.124 1.14-.235 1.558a2.007 2.007 0 0 1-1.415 1.42c-1.16.312-5.569.334-6.18.335h-.142c-.309 0-1.587-.006-2.927-.052l-.17-.006-.087-.004-.171-.007-.171-.007c-1.11-.049-2.167-.128-2.654-.26a2.007 2.007 0 0 1-1.415-1.419c-.111-.417-.185-.986-.235-1.558L.09 9.82l-.008-.104A31.4 31.4 0 0 1 0 7.68v-.123c.002-.215.01-.958.064-1.778l.007-.103.003-.052.008-.104.022-.26.01-.104c.048-.519.119-1.023.22-1.402a2.007 2.007 0 0 1 1.415-1.42c.487-.13 1.544-.21 2.654-.26l.17-.007.172-.006.086-.003.171-.007A99.788 99.788 0 0 1 7.858 2h.193zM6.4 5.209v4.818l4.157-2.408L6.4 5.209z"/> -</svg> - - </div> - <img class="shadow" src="https://niezbednik.niedziela.pl/images/gospel-dla-zabieganych.jpg" - alt=""> - </div> - - </div> - - <div class="card-body"> - <div class="clearfix mb-3"> - - - - - </div> - - - <div class="my-2 text-center"> - - <h3 class="lh-sm"> - Ks. Piotr Szeląg - <br><small><i>Gospel dla zabieganych</i></small> - </h3> - - </div> - <div class="mb-3"> - - <p class="text-uppercase text-center role"></p> - - </div> - - - </div> - </a> - </div> - - <!--<div class="card"> - <a class="panel-link" href="/artykul/7525/Gospel-dla-zabieganych-22-VI-2026" data-clicksmap="site:liturgia - PanelRozwazanie - /artykul/7525/Gospel-dla-zabieganych-22-VI-2026">Ks. Piotr Szeląg <i class="fa fa-arrow-circle-right"></i></a> - </div>--> - </div> - - - - - <div class="swiper-slide mb-2 swiper-slide-equal-height"> - <a href="/artykul/7526/DrogaDoJezusacom-22-VI-2026" data-clicksmap="liturgia-PanelRozwazania:/artykul/7526/DrogaDoJezusacom-22-VI-2026-Desktop"> - <div class="card h-100 shadow-sm"> - - - <div class="text-center"> - - - <div class="img-hover-zoom img-hover-zoom--colorize position-relative"> - <!--<div class="card-icon"> - <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-caret-right-fill" viewBox="0 0 16 16"> - <path d="m12.14 8.753-5.482 4.796c-.646.566-1.658.106-1.658-.753V3.204a1 1 0 0 1 1.659-.753l5.48 4.796a1 1 0 0 1 0 1.506z"/> -</svg> - </div>--> - <div class="card-icon1"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-youtube" viewBox="0 0 16 16"> - <path d="M8.051 1.999h.089c.822.003 4.987.033 6.11.335a2.01 2.01 0 0 1 1.415 1.42c.101.38.172.883.22 1.402l.01.104.022.26.008.104c.065.914.073 1.77.074 1.957v.075c-.001.194-.01 1.108-.082 2.06l-.008.105-.009.104c-.05.572-.124 1.14-.235 1.558a2.007 2.007 0 0 1-1.415 1.42c-1.16.312-5.569.334-6.18.335h-.142c-.309 0-1.587-.006-2.927-.052l-.17-.006-.087-.004-.171-.007-.171-.007c-1.11-.049-2.167-.128-2.654-.26a2.007 2.007 0 0 1-1.415-1.419c-.111-.417-.185-.986-.235-1.558L.09 9.82l-.008-.104A31.4 31.4 0 0 1 0 7.68v-.123c.002-.215.01-.958.064-1.778l.007-.103.003-.052.008-.104.022-.26.01-.104c.048-.519.119-1.023.22-1.402a2.007 2.007 0 0 1 1.415-1.42c.487-.13 1.544-.21 2.654-.26l.17-.007.172-.006.086-.003.171-.007A99.788 99.788 0 0 1 7.858 2h.193zM6.4 5.209v4.818l4.157-2.408L6.4 5.209z"/> -</svg> - - </div> - <img class="shadow" src="https://niezbednik.niedziela.pl/images/drogadojezusa.jpg" - alt=""> - </div> - - </div> - - <div class="card-body"> - <div class="clearfix mb-3"> - - - - - </div> - - - <div class="my-2 text-center"> - - <h3 class="lh-sm"> - DrogaDoJezusa.com <br><small>(dla dzieci i rodziców)</small> </h3> - - </div> - <div class="mb-3"> - - <p class="text-uppercase text-center role"></p> - - </div> - - - </div> - </a> - </div> - - <!--<div class="card"> - <a class="panel-link" href="/artykul/7526/DrogaDoJezusacom-22-VI-2026" data-clicksmap="site:liturgia - PanelRozwazanie - /artykul/7526/DrogaDoJezusacom-22-VI-2026">DrogaDoJezusa.com <i class="fa fa-arrow-circle-right"></i></a> - </div>--> - </div> - - - - - <div class="swiper-slide mb-2 swiper-slide-equal-height"> - <a href="/artykul/7524/Damy-z-Bogiem-rade-22-VI-2026" data-clicksmap="liturgia-PanelRozwazania:/artykul/7524/Damy-z-Bogiem-rade-22-VI-2026-Desktop"> - <div class="card h-100 shadow-sm"> - - - <div class="text-center"> - - - <div class="img-hover-zoom img-hover-zoom--colorize position-relative"> - <!--<div class="card-icon"> - <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-caret-right-fill" viewBox="0 0 16 16"> - <path d="m12.14 8.753-5.482 4.796c-.646.566-1.658.106-1.658-.753V3.204a1 1 0 0 1 1.659-.753l5.48 4.796a1 1 0 0 1 0 1.506z"/> -</svg> - </div>--> - <div class="card-icon1"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-youtube" viewBox="0 0 16 16"> - <path d="M8.051 1.999h.089c.822.003 4.987.033 6.11.335a2.01 2.01 0 0 1 1.415 1.42c.101.38.172.883.22 1.402l.01.104.022.26.008.104c.065.914.073 1.77.074 1.957v.075c-.001.194-.01 1.108-.082 2.06l-.008.105-.009.104c-.05.572-.124 1.14-.235 1.558a2.007 2.007 0 0 1-1.415 1.42c-1.16.312-5.569.334-6.18.335h-.142c-.309 0-1.587-.006-2.927-.052l-.17-.006-.087-.004-.171-.007-.171-.007c-1.11-.049-2.167-.128-2.654-.26a2.007 2.007 0 0 1-1.415-1.419c-.111-.417-.185-.986-.235-1.558L.09 9.82l-.008-.104A31.4 31.4 0 0 1 0 7.68v-.123c.002-.215.01-.958.064-1.778l.007-.103.003-.052.008-.104.022-.26.01-.104c.048-.519.119-1.023.22-1.402a2.007 2.007 0 0 1 1.415-1.42c.487-.13 1.544-.21 2.654-.26l.17-.007.172-.006.086-.003.171-.007A99.788 99.788 0 0 1 7.858 2h.193zM6.4 5.209v4.818l4.157-2.408L6.4 5.209z"/> -</svg> - - </div> - <img class="shadow" src="https://niezbednik.niedziela.pl/images/wegrzyniak.jpg" - alt=""> - </div> - - </div> - - <div class="card-body"> - <div class="clearfix mb-3"> - - - - - </div> - - - <div class="my-2 text-center"> - - <h3 class="lh-sm"> - Ks. Wojciech Węgrzyniak - <br><small><i>Damy z Bogiem radę</i></small> - </h3> - - </div> - <div class="mb-3"> - - <p class="text-uppercase text-center role"></p> - - </div> - - - </div> - </a> - </div> - - <!--<div class="card"> - <a class="panel-link" href="/artykul/7524/Damy-z-Bogiem-rade-22-VI-2026" data-clicksmap="site:liturgia - PanelRozwazanie - /artykul/7524/Damy-z-Bogiem-rade-22-VI-2026">Ks. Wojciech Węgrzyniak <i class="fa fa-arrow-circle-right"></i></a> - </div>--> - </div> - - - -</div> - - - <!-- If we need scrollbar --> - <div class=" swiper-scrollbar-all swiper-rozwazania-scrollbar"></div> - <!-- If we need navigation buttons --> - <div class="swiper-button-nav d-none d-md-block"> - <div class="btn btn-default swiper-rozwazania-button-prev "><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-left" viewBox="0 0 16 16"> - <path fill-rule="evenodd" d="M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z"/> -</svg></div> - <div class="btn btn-default swiper-rozwazania-button-next "><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-right" viewBox="0 0 16 16"> - <path fill-rule="evenodd" d="M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z"/> -</svg></div> - </div> - </div> - - - - - - </div> - - </div> - </div> -</div> -<div class="card border-0 px-lg-3 px-1 py-1 my-4 " id="dzien"> - <div class="card-body text-md-left"> - - <h2 class="mb-4 lh-1 text-uppercase" style="letter-spacing:2px">22 czerwca, poniedziałek </h2> - <div class="row align-items-start"> - <div class="col-md-9"> - - - -<div class="row"> - <div class="col-12 col-lg-5"> - <p class="lh-sm background-zwykly px-2 py-1 mb-0 text-center badge fw-normal fs-6">XII Tydzień zwykły</p> - <p class="font-serif mb-2 lh-sm fs-4 fw-bold color-powszedni"><em>Dzień Powszedni albo wspomnienie św. Paulina z Noli, biskupa albo wspomnienie świętych męczenników -Jana Fishera, biskupa, i Tomasza More'a</em></p> - - <p class="lh-sm"> - Rok A, II <br>Kolor szat: <strong>zielony albo biały albo czerwony</strong> <br><a href="/liturgia/2026-06-22" class="fw-bold" data-clicksmap="liturgia-PanelDayLiturgiaLink-Mobile">Liturgia dnia <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-right " viewBox="0 0 16 16">
- <path fill-rule="evenodd" d="M1 8a.5.5 0 0 1 .5-.5h11.793l-3.147-3.146a.5.5 0 0 1 .708-.708l4 4a.5.5 0 0 1 0 .708l-4 4a.5.5 0 0 1-.708-.708L13.293 8.5H1.5A.5.5 0 0 1 1 8z"/>
- </svg></a> - </p> - <p class="lh-sm"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-calendar3" viewBox="0 0 16 16"> - <path d="M14 0H2a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2zM1 3.857C1 3.384 1.448 3 2 3h12c.552 0 1 .384 1 .857v10.286c0 .473-.448.857-1 .857H2c-.552 0-1-.384-1-.857V3.857z"/> - <path d="M6.5 7a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm3 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm3 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm-9 3a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm3 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm3 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm3 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm-9 3a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm3 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm3 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/> -</svg> 173. dzień roku - - <br><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-sunrise fs-3" style="vertical-align: -.25em" viewBox="0 0 16 16"> - <path d="M7.646 1.146a.5.5 0 0 1 .708 0l1.5 1.5a.5.5 0 0 1-.708.708L8.5 2.707V4.5a.5.5 0 0 1-1 0V2.707l-.646.647a.5.5 0 1 1-.708-.708l1.5-1.5zM2.343 4.343a.5.5 0 0 1 .707 0l1.414 1.414a.5.5 0 0 1-.707.707L2.343 5.05a.5.5 0 0 1 0-.707zm11.314 0a.5.5 0 0 1 0 .707l-1.414 1.414a.5.5 0 1 1-.707-.707l1.414-1.414a.5.5 0 0 1 .707 0zM8 7a3 3 0 0 1 2.599 4.5H5.4A3 3 0 0 1 8 7zm3.71 4.5a4 4 0 1 0-7.418 0H.499a.5.5 0 0 0 0 1h15a.5.5 0 0 0 0-1h-3.79zM0 10a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2A.5.5 0 0 1 0 10zm13 0a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1-.5-.5z"/> -</svg> 04:12 - 21:03 <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-sunset fs-3" style="vertical-align: -.25em" viewBox="0 0 16 16"> - <path d="M7.646 4.854a.5.5 0 0 0 .708 0l1.5-1.5a.5.5 0 0 0-.708-.708l-.646.647V1.5a.5.5 0 0 0-1 0v1.793l-.646-.647a.5.5 0 1 0-.708.708l1.5 1.5zm-5.303-.51a.5.5 0 0 1 .707 0l1.414 1.413a.5.5 0 0 1-.707.707L2.343 5.05a.5.5 0 0 1 0-.707zm11.314 0a.5.5 0 0 1 0 .706l-1.414 1.414a.5.5 0 1 1-.707-.707l1.414-1.414a.5.5 0 0 1 .707 0zM8 7a3 3 0 0 1 2.599 4.5H5.4A3 3 0 0 1 8 7zm3.71 4.5a4 4 0 1 0-7.418 0H.499a.5.5 0 0 0 0 1h15a.5.5 0 0 0 0-1h-3.79zM0 10a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2A.5.5 0 0 1 0 10zm13 0a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1-.5-.5z"/> -</svg> - - </p> - <p class="lh-sm"> - <strong>Imieniny:</strong> <em>Paulina, Jana, Tomasza</em> - </p> - </div> - <div class="col-12 col-lg-7"> - <h4 class="text-uppercase mb-1 "><span class="background-primary badge fs-5 fw-normal color-white py-1 px-2">Ważne</span></h4> - <div class="mb-2"> <p class="lh-sm p-0 m-0 pb-1"><a href="https://niezbednik.niedziela.pl/artykul/284/Litania-do-Najswietszego-Serca-Pana?utm_source=niezbednikKatolika&utm_medium=PanelPamietajMobile&utm_campaign=PanelPamietajMobile" data-clicksmap="site:liturgia - PanelPamietaj - czerwcowe"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-youtube" viewBox="0 0 16 16"> - <path d="M8.051 1.999h.089c.822.003 4.987.033 6.11.335a2.01 2.01 0 0 1 1.415 1.42c.101.38.172.883.22 1.402l.01.104.022.26.008.104c.065.914.073 1.77.074 1.957v.075c-.001.194-.01 1.108-.082 2.06l-.008.105-.009.104c-.05.572-.124 1.14-.235 1.558a2.007 2.007 0 0 1-1.415 1.42c-1.16.312-5.569.334-6.18.335h-.142c-.309 0-1.587-.006-2.927-.052l-.17-.006-.087-.004-.171-.007-.171-.007c-1.11-.049-2.167-.128-2.654-.26a2.007 2.007 0 0 1-1.415-1.419c-.111-.417-.185-.986-.235-1.558L.09 9.82l-.008-.104A31.4 31.4 0 0 1 0 7.68v-.123c.002-.215.01-.958.064-1.778l.007-.103.003-.052.008-.104.022-.26.01-.104c.048-.519.119-1.023.22-1.402a2.007 2.007 0 0 1 1.415-1.42c.487-.13 1.544-.21 2.654-.26l.17-.007.172-.006.086-.003.171-.007A99.788 99.788 0 0 1 7.858 2h.193zM6.4 5.209v4.818l4.157-2.408L6.4 5.209z"/> -</svg> Litania do Najświętszego Serca Pana Jezusa</a></p> <p class="lh-sm p-0 m-0 pb-1"><a href="https://www.niedziela.pl/artykul/81264/LudzkieSerceBoga-Poznaj-Serce-Jezusa-tak-bliskie-kazdemu-z-nas---rozwazania?utm_source=niezbednikKatolika&utm_medium=PanelPamietajMobile&utm_campaign=PanelPamietajMobile" data-clicksmap="site:liturgia - PanelPamietaj - czerwcowe">#LudzkieSerceBoga - rozważania czerwcowe</a></p> <p class="lh-sm p-0 m-0 pb-1"><a href="/artykul/7316/Codzienna-modlitwa-maj-czerwiec-2026" data-clicksmap="site:liturgia - PanelPamietaj - /artykul/7316/Codzienna-modlitwa-maj-czerwiec-2026"">Codzienna modlitwa (maj-czerwiec 2026)</a></p> <p class="lh-sm p-0 m-0 pb-1"><a href="https://www.niedziela.pl/artykul/102453/Nowenna-do-Przenajdrozszej-Krwi-Chrystusa?utm_source=niezbednikKatolika&utm_medium=PanelPamietajMobile&utm_campaign=PanelPamietajMobile" data-clicksmap="site:liturgia - PanelPamietaj - niedziela.pl/artykul/102453/Nowenna-do-Przenajdrozszej-Krwi-Chrystusa">Nowenna do Przenajdroższej Krwi Chrystusa (1. dzień)</a></p> <p class="lh-sm p-0 m-0 pb-1"><a href="https://www.niedziela.pl/artykul/77464/Modlitwa-sw-Jana-Pawla-II-o-pokoj?utm_source=niezbednikKatolika&utm_medium=PanelPamietajMobile&utm_campaign=PanelPamietajMobile" data-clicksmap="site:liturgia - PanelPamietaj - https://www.niedziela.pl/artykul/77464/" target="_blank"><strong>Modlitwa św. Jana Pawła II o pokój</strong></a></p> <p class="lh-sm p-0 m-0 pb-1"><a href="https://www.niedziela.pl/artykul/121618/Modlitwa-do-Maryi-Krolowej-Pokoju?utm_source=niezbednikKatolika&utm_medium=PanelPamietajMobile&utm_campaign=PanelPamietajMobile" data-clicksmap="site:liturgia - PanelPamietaj - https://www.niedziela.pl/artykul/121618/" target="_blank"><strong>Modlitwa do Maryi, Królowej Pokoju</strong></a></p> <p class="lh-sm p-0 m-0 pb-1"><a href="https://niezbednik.niedziela.pl/biblia" data-clicksmap="site:liturgia - PanelPamietaj - Biblia" target="_blank"><strong>Biblia Tysiąclecia - pełny tekst</strong></a></p></div> - <h4 class="fs-5 text-uppercase mb-1"><span class="background-primary badge fs-5 fw-normal py-1 px-2">Patron dnia</span></h4> - <ul class="list-unstyled mt-1"><li class="mb-1"><h3 class="pb-0 mb-0 lh-sm"><a class="" href="https://www.niedziela.pl/artykul/84204/nd/Sw-Paulin-z-Noli?utm_source=niezbednikKatolika&utm_medium=PanelDzienMobile&utm_campaign=PanelDzienMobile" data-clicksmap="site:liturgia - PanelPatron - https://www.niedziela.pl/artykul/84204/nd/Sw-Paulin-z-Noli"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-bookmark" viewBox="0 0 16 16"> - <path d="M2 2a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v13.5a.5.5 0 0 1-.777.416L8 13.101l-5.223 2.815A.5.5 0 0 1 2 15.5V2zm2-1a1 1 0 0 0-1 1v12.566l4.723-2.482a.5.5 0 0 1 .554 0L13 14.566V2a1 1 0 0 0-1-1H4z"/> - </svg> Św. Paulin z Noli</a></h3></a></li><li class="mb-1"><h3 class="pb-0 mb-0 lh-sm"><a class="" href="https://www.niedziela.pl/artykul/716/Sw-Jan-Fisher-biskup?utm_source=niezbednikKatolika&utm_medium=PanelDzienMobile&utm_campaign=PanelDzienMobile" data-clicksmap="site:liturgia - PanelPatron - https://www.niedziela.pl/artykul/716/Sw-Jan-Fisher-biskup"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-bookmark" viewBox="0 0 16 16"> - <path d="M2 2a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v13.5a.5.5 0 0 1-.777.416L8 13.101l-5.223 2.815A.5.5 0 0 1 2 15.5V2zm2-1a1 1 0 0 0-1 1v12.566l4.723-2.482a.5.5 0 0 1 .554 0L13 14.566V2a1 1 0 0 0-1-1H4z"/> - </svg> Św. Jan Fisher, biskup</a></h3></a></li></ul> <h4 class="fs-5 text-uppercase mb-1"><span class="background-primary badge fs-5 fw-normal py-1 px-2">Wydarzyło się...</span></h4> - <ul class="list-unstyled"><li>• <a href="http://www.niedziela.pl/artykul/18925/nd/Sw-Kamil-de-Lellis" data-clicksmap="site:liturgia - PanelWydarzenia - http://www.niedziela.pl/artykul/18925/nd/Sw-Kamil-de-Lellis"><strong>św. Kamil de Lellis</strong> <i class="fa fa-external-link"></i></a> został ogłoszony przez papieża Leona XIII patronem wszystkich chorych i szpitali (1886 r.)</li><li>• odbyła się 9-godzinna podróż apostolska Jana Pawła II do Bośni i Hercegowiny (2003 r.)</li></ul> </div> - <div class="col-12"> - <a class="btn btn-primary ms-0" href="/dzien/2026-06-21" data-clicksmap="liturgia-PanelDayBtnPrev-Mobile"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-left" viewBox="0 0 16 16"> - <path fill-rule="evenodd" d="M15 8a.5.5 0 0 0-.5-.5H2.707l3.147-3.146a.5.5 0 1 0-.708-.708l-4 4a.5.5 0 0 0 0 .708l4 4a.5.5 0 0 0 .708-.708L2.707 8.5H14.5A.5.5 0 0 0 15 8z"/> -</svg> Wczoraj</a> - <a class="btn btn-primary pull-right me-0" href="/dzien/2026-06-23" data-clicksmap="liturgia-PanelDayBtnNext-Mobile">Jutro <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-right" viewBox="0 0 16 16"> - <path fill-rule="evenodd" d="M1 8a.5.5 0 0 1 .5-.5h11.793l-3.147-3.146a.5.5 0 0 1 .708-.708l4 4a.5.5 0 0 1 0 .708l-4 4a.5.5 0 0 1-.708-.708L13.293 8.5H1.5A.5.5 0 0 1 1 8z"/> -</svg></a> - </div> - -</div> - - </div> - <div class="col-12 col-md-3 mt-4 mt-md-0"> - <img src="https://niezbednik.niedziela.pl/images/dzien2.png" alt="" class="img-fluid w-75 mx-auto d-block"> - </div> - - </div> - </div> -</div> - - - - - - - - -<div class="card border-0 px-lg-3 px-1 py-1 my-4 " > - <div class="card-body text-md-left"> - <div class="row align-items-start"> - <div class="col-12"> - - - <h2 id="panelCalendarTitle"></h2>
- <div class="swiper-container swiper-kalendarz swiper-with-scroll my-main">
- <!-- Additional required wrapper -->
- <ul class="swiper-wrapper mb-4 list-unstyled">
- <!-- Slides -->
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XI Tydzień zwykły">
-
-
- <a href="/dzien/2026-06-14" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide0-Desktop">
-
-
-<div class="panel-calendar niedziela h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">czerwiec</p>
- <p class="panel-calendar-day px-4"><span>14</span></p>
- <p class="mb-2">
- niedziela
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Jedenasta Niedziela zwykła</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XI Tydzień zwykły">
-
-
- <a href="/dzien/2026-06-15" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide1-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">czerwiec</p>
- <p class="panel-calendar-day px-4"><span>15</span></p>
- <p class="mb-2">
- poniedziałek
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Dzień Powszedni</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XI Tydzień zwykły">
-
-
- <a href="/dzien/2026-06-16" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide2-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">czerwiec</p>
- <p class="panel-calendar-day px-4"><span>16</span></p>
- <p class="mb-2">
- wtorek
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Dzień Powszedni</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XI Tydzień zwykły">
-
-
- <a href="/dzien/2026-06-17" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide3-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">czerwiec</p>
- <p class="panel-calendar-day px-4"><span>17</span></p>
- <p class="mb-2">
- środa
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Wspomnienie św. brata Alberta Chmielowskiego, zakonnika</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XI Tydzień zwykły">
-
-
- <a href="/dzien/2026-06-18" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide4-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">czerwiec</p>
- <p class="panel-calendar-day px-4"><span>18</span></p>
- <p class="mb-2">
- czwartek
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Dzień Powszedni</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XI Tydzień zwykły">
-
-
- <a href="/dzien/2026-06-19" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide5-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">czerwiec</p>
- <p class="panel-calendar-day px-4"><span>19</span></p>
- <p class="mb-2">
- piątek
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Dzień Powszedni albo wspomnienie św. Romualda, opata</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XI Tydzień zwykły">
-
-
- <a href="/dzien/2026-06-20" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide6-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">czerwiec</p>
- <p class="panel-calendar-day px-4"><span>20</span></p>
- <p class="mb-2">
- sobota
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Dzień Powszedni albo wspomnienie Najświętszej Maryi Panny w sobotę</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XII Tydzień zwykły">
-
-
- <a href="/dzien/2026-06-21" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide7-Desktop">
-
-
-<div class="panel-calendar niedziela h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">czerwiec</p>
- <p class="panel-calendar-day px-4"><span>21</span></p>
- <p class="mb-2">
- niedziela
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Dwunasta Niedziela zwykła</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XII Tydzień zwykły">
-
-
- <a href="/dzien/2026-06-22" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide8-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 today">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">czerwiec</p>
- <p class="panel-calendar-day px-4"><span>22</span></p>
- <p class="mb-2">
- <span class="fw-bold">DZISIAJ</span>
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Dzień Powszedni albo wspomnienie św. Paulina z Noli, biskupa albo wspomnienie świętych męczenników -Jana Fishera, biskupa, i Tomasza More'a</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XII Tydzień zwykły">
-
-
- <a href="/dzien/2026-06-23" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide9-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">czerwiec</p>
- <p class="panel-calendar-day px-4"><span>23</span></p>
- <p class="mb-2">
- wtorek
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Dzień Powszedni</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XII Tydzień zwykły">
-
-
- <a href="/dzien/2026-06-24" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide10-Desktop">
-
-
-<div class="panel-calendar niedziela h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">czerwiec</p>
- <p class="panel-calendar-day px-4"><span>24</span></p>
- <p class="mb-2">
- środa
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Uroczystość narodzenia św. Jana Chrzciciela</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XII Tydzień zwykły">
-
-
- <a href="/dzien/2026-06-25" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide11-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">czerwiec</p>
- <p class="panel-calendar-day px-4"><span>25</span></p>
- <p class="mb-2">
- czwartek
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Dzień Powszedni</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XII Tydzień zwykły">
-
-
- <a href="/dzien/2026-06-26" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide12-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">czerwiec</p>
- <p class="panel-calendar-day px-4"><span>26</span></p>
- <p class="mb-2">
- piątek
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Dzień Powszedni albo wspomnienie św. Zygmunta Gorazdowskiego, prezbitera</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XII Tydzień zwykły">
-
-
- <a href="/dzien/2026-06-27" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide13-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">czerwiec</p>
- <p class="panel-calendar-day px-4"><span>27</span></p>
- <p class="mb-2">
- sobota
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Dzień Powszedni albo wspomnienie Najświętszej Maryi Panny w sobotę albo wspomnienie św. Cyryla Aleksandryjskiego, -biskupa i doktora Kościoła</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XIII Tydzień zwykły">
-
-
- <a href="/dzien/2026-06-28" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide14-Desktop">
-
-
-<div class="panel-calendar niedziela h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">czerwiec</p>
- <p class="panel-calendar-day px-4"><span>28</span></p>
- <p class="mb-2">
- niedziela
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Trzynasta Niedziela zwykła</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XIII Tydzień zwykły">
-
-
- <a href="/dzien/2026-06-29" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide15-Desktop">
-
-
-<div class="panel-calendar niedziela h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">czerwiec</p>
- <p class="panel-calendar-day px-4"><span>29</span></p>
- <p class="mb-2">
- poniedziałek
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Uroczystość świętych Apostołów Piotra i Pawła</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XIII Tydzień zwykły">
-
-
- <a href="/dzien/2026-06-30" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide16-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">czerwiec</p>
- <p class="panel-calendar-day px-4"><span>30</span></p>
- <p class="mb-2">
- wtorek
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Wspomnienie Świętych Pierwszych Męczenników Kościoła Rzymskiego</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XIII Tydzień zwykły">
-
-
- <a href="/dzien/2026-07-01" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide17-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">lipiec</p>
- <p class="panel-calendar-day px-4"><span>1</span></p>
- <p class="mb-2">
- środa
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Dzień Powszedni albo wspomnienie św. Ottona, biskupa</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XIII Tydzień zwykły">
-
-
- <a href="/dzien/2026-07-02" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide18-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">lipiec</p>
- <p class="panel-calendar-day px-4"><span>2</span></p>
- <p class="mb-2">
- <span class="fw-bold font-sans">pierwszy czwartek</span>
-
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Dzień Powszedni</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XIII Tydzień zwykły">
-
-
- <a href="/dzien/2026-07-03" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide19-Desktop">
-
-
-<div class="panel-calendar swieto h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">lipiec</p>
- <p class="panel-calendar-day px-4"><span>3</span></p>
- <p class="mb-2">
- <span class="fw-bold font-sans">pierwszy piątek</span>
-
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Święto św. Tomasza, apostoła</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XIII Tydzień zwykły">
-
-
- <a href="/dzien/2026-07-04" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide20-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">lipiec</p>
- <p class="panel-calendar-day px-4"><span>4</span></p>
- <p class="mb-2">
- <span class="fw-bold font-sans">pierwsza sobota</span>
-
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Dzień Powszedni albo wspomnienie Najświętszej Maryi Panny w sobotę albo wspomnienie św. Elżbiety Portugalskiej</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XIV Tydzień zwykły">
-
-
- <a href="/dzien/2026-07-05" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide21-Desktop">
-
-
-<div class="panel-calendar niedziela h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">lipiec</p>
- <p class="panel-calendar-day px-4"><span>5</span></p>
- <p class="mb-2">
- niedziela
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Czternasta Niedziela zwykła</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XIV Tydzień zwykły">
-
-
- <a href="/dzien/2026-07-06" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide22-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">lipiec</p>
- <p class="panel-calendar-day px-4"><span>6</span></p>
- <p class="mb-2">
- poniedziałek
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Wspomnienie bł. Marii Teresy Ledóchowskiej, dziewicy</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XIV Tydzień zwykły">
-
-
- <a href="/dzien/2026-07-07" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide23-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">lipiec</p>
- <p class="panel-calendar-day px-4"><span>7</span></p>
- <p class="mb-2">
- wtorek
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Dzień Powszedni</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XIV Tydzień zwykły">
-
-
- <a href="/dzien/2026-07-08" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide24-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">lipiec</p>
- <p class="panel-calendar-day px-4"><span>8</span></p>
- <p class="mb-2">
- środa
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Wspomnienie św. Jana z Dukli, prezbitera</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XIV Tydzień zwykły">
-
-
- <a href="/dzien/2026-07-09" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide25-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">lipiec</p>
- <p class="panel-calendar-day px-4"><span>9</span></p>
- <p class="mb-2">
- czwartek
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Dzień Powszedni albo wspomnienie świętych męczenników -Augustyna Zhao Rong, prezbitera, i Towarzyszy</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XIV Tydzień zwykły">
-
-
- <a href="/dzien/2026-07-10" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide26-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">lipiec</p>
- <p class="panel-calendar-day px-4"><span>10</span></p>
- <p class="mb-2">
- piątek
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Dzień Powszedni</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XIV Tydzień zwykły">
-
-
- <a href="/dzien/2026-07-11" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide27-Desktop">
-
-
-<div class="panel-calendar swieto h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">lipiec</p>
- <p class="panel-calendar-day px-4"><span>11</span></p>
- <p class="mb-2">
- sobota
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Święto św. Benedykta, opata, patrona Europy</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XV Tydzień zwykły">
-
-
- <a href="/dzien/2026-07-12" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide28-Desktop">
-
-
-<div class="panel-calendar niedziela h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">lipiec</p>
- <p class="panel-calendar-day px-4"><span>12</span></p>
- <p class="mb-2">
- niedziela
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Piętnasta Niedziela zwykła</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XV Tydzień zwykły">
-
-
- <a href="/dzien/2026-07-13" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide29-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">lipiec</p>
- <p class="panel-calendar-day px-4"><span>13</span></p>
- <p class="mb-2">
- poniedziałek
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Wspomnienie świętych pustelników Andrzeja Świerada i Benedykta</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XV Tydzień zwykły">
-
-
- <a href="/dzien/2026-07-14" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide30-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">lipiec</p>
- <p class="panel-calendar-day px-4"><span>14</span></p>
- <p class="mb-2">
- wtorek
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Dzień Powszedni albo wspomnienie św. Kamila de Lellis, prezbitera albo wspomnienie św. Henryka</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XV Tydzień zwykły">
-
-
- <a href="/dzien/2026-07-15" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide31-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">lipiec</p>
- <p class="panel-calendar-day px-4"><span>15</span></p>
- <p class="mb-2">
- środa
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Wspomnienie św. Bonawentury, biskupa i doktora Kościoła</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XV Tydzień zwykły">
-
-
- <a href="/dzien/2026-07-16" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide32-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">lipiec</p>
- <p class="panel-calendar-day px-4"><span>16</span></p>
- <p class="mb-2">
- czwartek
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Wspomnienie Najświętszej Maryi Panny z Góry Karmel</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XV Tydzień zwykły">
-
-
- <a href="/dzien/2026-07-17" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide33-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">lipiec</p>
- <p class="panel-calendar-day px-4"><span>17</span></p>
- <p class="mb-2">
- piątek
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Dzień Powszedni</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XV Tydzień zwykły">
-
-
- <a href="/dzien/2026-07-18" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide34-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">lipiec</p>
- <p class="panel-calendar-day px-4"><span>18</span></p>
- <p class="mb-2">
- sobota
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Dzień Powszedni albo wspomnienie Najświętszej Maryi Panny w sobotę albo wspomnienie św. Szymona z Lipnicy, prezbitera</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
-
-
-
- </ul>
-
- <!-- If we need scrollbar -->
-<div class=" swiper-scrollbar-all swiper-kalendarz-scrollbar"></div>
- <!-- If we need navigation buttons -->
- <div class="swiper-button-nav d-none d-md-block">
- <div class="btn btn-default swiper-kalendarz-button-prev "><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-left" viewBox="0 0 16 16">
- <path fill-rule="evenodd" d="M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z"/>
-</svg></div>
- <div class="btn btn-default swiper-kalendarz-button-next "><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-right" viewBox="0 0 16 16">
- <path fill-rule="evenodd" d="M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z"/>
-</svg></div>
- </div>
-
- </div>
- <p class="text-center">
- <a class="btn btn-primary ms-0" href="/site/liturgia#20260622" data-clicksmap="liturgia-PanelDayBtnCalendar-Desktop"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-calendar3" viewBox="0 0 16 16">
- <path d="M14 0H2a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2zM1 3.857C1 3.384 1.448 3 2 3h12c.552 0 1 .384 1 .857v10.286c0 .473-.448.857-1 .857H2c-.552 0-1-.384-1-.857V3.857z"/>
- <path d="M6.5 7a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm3 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm3 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm-9 3a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm3 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm3 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm3 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm-9 3a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm3 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm3 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/>
-</svg> Kalendarz na rok 2026</a>
- </p>
-
- - - </div> - - </div> - </div> -</div> -<div class="card border-0 px-lg-3 px-1 py-1 my-4 " > - <div class="card-body text-md-left"> - - <h2 class="mb-4 lh-1 text-uppercase" style="letter-spacing:2px">Z życia Kościoła </h2> - <div class="row align-items-start"> - <div class="col-12"> - - -
-
-
-
-<div class="swiper-container swiper-wiadomosci swiper-with-scroll">
- <!-- Additional required wrapper -->
- <div class="swiper-wrapper mb-2">
- <!-- Slides -->
-
-
-
- <div class="swiper-slide mb-2 swiper-slide-equal-height">
- <a href="//www.niedziela.pl/artykul/125309/" data-clicksmap="liturgia-PanWiad-0-125309-Desktop">
- <div class="card h-100 shadow-sm">
- <div class="text-center">
- <div class="img-hover-zoom img-hover-zoom--colorize">
- <img class="shadow" src="https://www.niedziela.pl/gifs/portaln/150x150/1780997021.jpg" alt="">
- </div>
- </div>
-
- <div class="card-body">
-
- <div class="my-2 text-center">
-
- <h3 class="lh-sm truncate-multiline-3">Ksiądz Padre Guilherme o hejcie na swój temat: Gdy pojawia się coś nietypowego, wiele osób mówi, że ksiądz nie powinien tego robić</h3>
-
- </div>
-
- </div>
- </div>
- </a>
- </div>
-
-
- <div class="swiper-slide mb-2 swiper-slide-equal-height">
- <a href="//www.niedziela.pl/artykul/125302/" data-clicksmap="liturgia-PanWiad-1-125302-Desktop">
- <div class="card h-100 shadow-sm">
- <div class="text-center">
- <div class="img-hover-zoom img-hover-zoom--colorize">
- <img class="shadow" src="https://www.niedziela.pl/gifs/portaln/150x150/1782128362.jpg" alt="">
- </div>
- </div>
-
- <div class="card-body">
-
- <div class="my-2 text-center">
-
- <h3 class="lh-sm truncate-multiline-3">Papież wręczy paliusze trzem polski metropolitom</h3>
-
- </div>
-
- </div>
- </div>
- </a>
- </div>
-
-
- <div class="swiper-slide mb-2 swiper-slide-equal-height">
- <a href="//www.niedziela.pl/artykul/125297/" data-clicksmap="liturgia-PanWiad-2-125297-Desktop">
- <div class="card h-100 shadow-sm">
- <div class="text-center">
- <div class="img-hover-zoom img-hover-zoom--colorize">
- <img class="shadow" src="https://www.niedziela.pl/gifs/portaln/150x150/1724163599.jpg" alt="">
- </div>
- </div>
-
- <div class="card-body">
-
- <div class="my-2 text-center">
-
- <h3 class="lh-sm truncate-multiline-3">Bp Ważny o relacjach polsko-ukraińskich: bez prawdy o przeszłości nie będzie zaufania</h3>
-
- </div>
-
- </div>
- </div>
- </a>
- </div>
-
-
- <div class="swiper-slide mb-2 swiper-slide-equal-height">
- <a href="//www.niedziela.pl/artykul/125291/" data-clicksmap="liturgia-PanWiad-3-125291-Desktop">
- <div class="card h-100 shadow-sm">
- <div class="text-center">
- <div class="img-hover-zoom img-hover-zoom--colorize">
- <img class="shadow" src="https://www.niedziela.pl/gifs/portaln/150x150/1781002382.jpg" alt="">
- </div>
- </div>
-
- <div class="card-body">
-
- <div class="my-2 text-center">
-
- <h3 class="lh-sm truncate-multiline-3">Francja: z kościoła ukradziono konsekrowane hostie i Najświętszy Sakrament</h3>
-
- </div>
-
- </div>
- </div>
- </a>
- </div>
-
-
- <div class="swiper-slide mb-2 swiper-slide-equal-height">
- <a href="//www.niedziela.pl/artykul/125280/" data-clicksmap="liturgia-PanWiad-4-125280-Desktop">
- <div class="card h-100 shadow-sm">
- <div class="text-center">
- <div class="img-hover-zoom img-hover-zoom--colorize">
- <img class="shadow" src="https://www.niedziela.pl/gifs/portaln/150x150/1743583648.jpg" alt="">
- </div>
- </div>
-
- <div class="card-body">
-
- <div class="my-2 text-center">
-
- <h3 class="lh-sm truncate-multiline-3">Jan Paweł II patronem Europy i doktorem Kościoła?</h3>
-
- </div>
-
- </div>
- </div>
- </a>
- </div>
-
-
- <div class="swiper-slide mb-2 swiper-slide-equal-height">
- <a href="//www.niedziela.pl/artykul/125277/" data-clicksmap="liturgia-PanWiad-5-125277-Desktop">
- <div class="card h-100 shadow-sm">
- <div class="text-center">
- <div class="img-hover-zoom img-hover-zoom--colorize">
- <img class="shadow" src="https://www.niedziela.pl/gifs/portaln/150x150/1782060892.jpg" alt="">
- </div>
- </div>
-
- <div class="card-body">
-
- <div class="my-2 text-center">
-
- <h3 class="lh-sm truncate-multiline-3">Krótka historia o tym, jak... strażacy uratowali niedzielną Mszę św.</h3>
-
- </div>
-
- </div>
- </div>
- </a>
- </div>
-
-
- <div class="swiper-slide mb-2 swiper-slide-equal-height">
- <a href="//www.niedziela.pl/artykul/125275/" data-clicksmap="liturgia-PanWiad-6-125275-Desktop">
- <div class="card h-100 shadow-sm">
- <div class="text-center">
- <div class="img-hover-zoom img-hover-zoom--colorize">
- <img class="shadow" src="https://www.niedziela.pl/gifs/portaln/150x150/1782054783.jpg" alt="">
- </div>
- </div>
-
- <div class="card-body">
-
- <div class="my-2 text-center">
-
- <h3 class="lh-sm truncate-multiline-3">Francuscy biskupi ogłosili nowennę w intencji życia</h3>
-
- </div>
-
- </div>
- </div>
- </a>
- </div>
-
-
- <div class="swiper-slide mb-2 swiper-slide-equal-height">
- <a href="//www.niedziela.pl/artykul/125274/" data-clicksmap="liturgia-PanWiad-7-125274-Desktop">
- <div class="card h-100 shadow-sm">
- <div class="text-center">
- <div class="img-hover-zoom img-hover-zoom--colorize">
- <img class="shadow" src="https://www.niedziela.pl/gifs/portaln/150x150/1782054502.jpg" alt="">
- </div>
- </div>
-
- <div class="card-body">
-
- <div class="my-2 text-center">
-
- <h3 class="lh-sm truncate-multiline-3">Jasna Góra: Pielgrzymka Podwórkowych Kółek Różańcowych</h3>
-
- </div>
-
- </div>
- </div>
- </a>
- </div>
-
-
- <div class="swiper-slide mb-2 swiper-slide-equal-height">
- <a href="//www.niedziela.pl/artykul/125273/" data-clicksmap="liturgia-PanWiad-8-125273-Desktop">
- <div class="card h-100 shadow-sm">
- <div class="text-center">
- <div class="img-hover-zoom img-hover-zoom--colorize">
- <img class="shadow" src="https://www.niedziela.pl/gifs/portaln/150x150/1779449003.jpg" alt="">
- </div>
- </div>
-
- <div class="card-body">
-
- <div class="my-2 text-center">
-
- <h3 class="lh-sm truncate-multiline-3">Opole: Fałszywy ksiądz krąży po mieście. Oszukuje seniorów oferując spowiedź, wyłudza pieniądze</h3>
-
- </div>
-
- </div>
- </div>
- </a>
- </div>
-
-
- <div class="swiper-slide mb-2 swiper-slide-equal-height">
- <a href="//www.niedziela.pl/artykul/125272/" data-clicksmap="liturgia-PanWiad-9-125272-Desktop">
- <div class="card h-100 shadow-sm">
- <div class="text-center">
- <div class="img-hover-zoom img-hover-zoom--colorize">
- <img class="shadow" src="https://www.niedziela.pl/gifs/portaln/150x150/1782044578.jpg" alt="">
- </div>
- </div>
-
- <div class="card-body">
-
- <div class="my-2 text-center">
-
- <h3 class="lh-sm truncate-multiline-3">Papież: Świat bardzo potrzebuje orędzia nadziei, miłości i pokoju Chrystusa</h3>
-
- </div>
-
- </div>
- </div>
- </a>
- </div>
-
- </div>
-
-<!-- If we need scrollbar -->
-<div class=" swiper-scrollbar-all swiper-wiadomosci-scrollbar"></div>
- <!-- If we need navigation buttons -->
- <div class="swiper-button-nav d-none d-md-block">
- <div class="btn btn-default swiper-wiadomosci-button-prev "><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-left" viewBox="0 0 16 16">
- <path fill-rule="evenodd" d="M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z"/>
-</svg></div>
- <div class="btn btn-default swiper-wiadomosci-button-next "><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-right" viewBox="0 0 16 16">
- <path fill-rule="evenodd" d="M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z"/>
-</svg></div>
- </div>
-</div>
-
-
-
-
- - - </div> - - </div> - </div> -</div>
-</div>
-
-
-
- - - - - <div class="px-3"> - -<div class="card border-0 px-lg-4 px-1 py-1 h-100" style="background-color: rgba(29,76,176,.1);"> - <div class="card-body text-md-left"> - <div class="row"> - - <div class="col-12 col-xl-6"> - <h2 class="mb-3 lh-1 color-primary text-uppercase">W NOWYM NUMERZE <strong><i>NIEDZIELI</i></strong></h2> - <div class="row"> - <div class="col-lg-4 mb-2 text-center"> - <img src="https://www.niedziela.pl/images/okladki/ewydanie/202625.png" class="img-fluid"> - </div> - <div class="col-lg-8"> - <p class="pe-2"><strong>Jasna Góra to mój drugi dom</strong> - <br>Chociaż większość dzieciństwa spędziła na Śląsku, a teraz mieszka w Warszawie, to jej korzenie są w Częstochowie. Dziennikarka, autorka książek… Magdalena Szefernaker. „Rola” mamy nie przeszkadza jej w realizacji zawodowych działań. </p> - <p> - - - <a href="https://www.niedziela.pl/prezentacja?utm_source=niezbednikKatolika&utm_medium=NiedzielaBottom0Btn0Desktop&utm_campaign=NiedzielaBottom0Btn0Desktop" class="btn btn-primary" data-clicksmap="liturgia-NiedzielaBottom0Btn0-Desktop">Zobacz</a> - - <a href="https://e.niedziela.pl/?utm_source=niezbednikKatolika&utm_medium=NiedzielaEwydanieBottom0Btn1Desktop&utm_campaign=NiedzielaEwydanieBottom0Btn1Desktop" class="btn btn-primary" data-clicksmap="liturgia-NiedzielaEwydanieBottom0Btn1-Desktop">Zamów e-wydanie</a> - - </p> - </div> - </div> - </div> - <div class="col-12 col-xl-6"> - <h2 class="mb-3 lh-1 color-primary text-uppercase">Księgarnia Niedziela</h2> - <div class="row"> - <div class="col-lg-4 mb-2 text-center"> - <img src="https://niezbednik.niedziela.pl/images/ksiazki/ksiazka-nasz-benedykt.jpg" class="img-fluid"> - </div> - <div class="col-lg-8"> - <p class="pe-2"><strong>Nasz Benedykt czyli kwiatki Josepha Ratzingera</strong> - <br>Podobno już jako czterolatek ogłosił, że zostanie kardynałem. Złościł się, gdy wołano na niego "Józio". Był marnym sportowcem i plastykiem, ale grywał w kości, i to z samym Gunterem Grassem! A przynajmniej tak twierdził ten ostatni.
-Benedykt XVI - Joseph Ratzinger. Złośliwi nazywali go "pancernym". A ile było w tym prawdy? Pewnie niewiele, bo do końca życia miał przy sobie dziecięcego misia Tediego, dokarmiał rzymskie koty, a sam żywił się głównie bawarską kiełbasą. </p> - <p> - - <a href="https://ksiegarnia.niedziela.pl/religia/194812-nasz-benedykt-czyli-kwiatki-josepha-ratzingera-9788327731876.html?utm_source=niezbednikKatolika&utm_medium=AdsBottom1BtnDesktop&utm_campaign=AdsBottom1BtnDesktop" class="btn btn-primary" data-clicksmap="liturgia-AdsBottom1Btn-Desktop">Zobacz</a> - - </p> - </div> - </div> - </div> - - </div> - </div> -</div> </div> - - <div class="px-3"> - -<div class="card border-0 px-lg-3 px-1 py-1 my-4 " > - <div class="card-body text-md-left"> - - <h2 class="mb-4 lh-1 text-uppercase" style="letter-spacing:2px">Liturgia na Twojej stronie WWW </h2> - <div class="row align-items-start"> - <div class="col-md-9"> - - - <p>Masz własną stronę i chcesz umieścić na niej liturgię dnia? Skorzystaj z naszej propozycji. Oferujemy wstawki z tekstami liturgii, które w bardzo prosty sposób dostosujesz do szaty graficznej na swojej witrynie.</p><p><a class="btn" href="https://www.niedziela.pl/webmaster/liturgia" data-clicksmap="liturgia-LiturgiaWidgetBtn-Desktop">Zobacz</a></p> - - </div> - <div class="col-12 col-md-3 mt-4 mt-md-0"> - <img src="https://niezbednik.niedziela.pl/images/widget.png" alt="" class="img-fluid w-75 mx-auto d-block"> - </div> - - </div> - </div> -</div> </div> - - <footer class="footer"> - - - - - <div class="row my-3"> - <div class="col-12"> - <div class="background-gold color-light text-center m-3 p-2 card border-0 px-lg-3 px-1 py-1 my-4 "> - <a class="color-light" href="https://www.niedziela.pl/artykul/117159/Nasz-portal-niedzielapl-i-serwis-Niezbednik-Katolika-nagrodzone-Malym-Feniksem?utm_source=niezbednikKatolika&utm_medium=BtnPanelDesktop&utm_campaign=BtnPanelDesktop" data-clicksmap="liturgia-Feniks2025-Desktop">LAUREAT NAGRODY: <strong>MAŁY FENIKS 2025</strong></a> - </div> - </div> - - <div class="col-xs-12"> - <p class="text-center napisz" style="margin: 0;"> - - </p> - </div> - </div> - - - - <div class="row"> - <div class="col-12 text-center mt-2"> - <a href="https://www.niedziela.pl/prezentacja" class="m-2"><img src="https://ksiazkinawielkipost.niedziela.pl/img/layout/tygodnik-niedziela.jpg" alt="Tygodnik Niedziela" class="img-fluid my-2"></a> - <a href="https://blizejzycia.pl" class="m-2"><img src="https://ksiazkinawielkipost.niedziela.pl/img/layout/logo-blizej-zycia-z-wiara.jpg" alt="Tygodnik Bliżej Życia z Wiarą" class="img-fluid my-2"></a> - <a href="https://magazyn.niedziela.pl" class="m-2"><img src="https://magazyn.niedziela.pl/img/logo-magazyn.jpg" alt="Niedziela. Magazyn" class="img-fluid my-2"></a> - <a href="https://www.niedziela.pl" class="m-2"><img src="https://www.niedziela.pl/img/logo.jpg" alt="Portal Niedziela" class="img-fluid my-2"></a> - <a href="https://ksiegarnia.niedziela.pl" class="mx-2"><img src="https://ksiazkinawielkipost.niedziela.pl/img/layout/logo.jpg" alt="Księgarnia Niedziela" class="img-fluid"></a> - </div> - - </div> - - <div class="row py-3"> - - - <div class="col-xs-12 text-center"> - <a href="https://www.niedziela.pl/polityka_prywatnosci">Polityka prywatności</a> - <br>Copyright © 2026 - Instytut NIEDZIELA - </div> - </div> - - </footer> - - </div> - </div> - -
-
-<div class="modal fade" tabindex="-1" data-bs-backdrop="static" id="entranceModal">
- <div class="modal-dialog modal-dialog-centered">
- <div class="modal-content background-red-dark">
- <div class="modal-body">
- <p class="text-end mb-2"><button type="button" class="btn btn-light py-0 px-2 m-0 rounded" data-bs-dismiss="modal" aria-label="Zamknij">Zamknij X</button></p>
- <a href="//niezbednik.niedziela.pl/wsparcie?utm_source=niezbednikKatolika&utm_medium=EntranceModalDesktop&utm_campaign=EntranceModalDesktop" data-clicksmap="EntranceModal - Donation - Desktop">
- <!-- 16:9 aspect ratio -->
- <img class="img-fluid" alt="Wsparcie Niezbędnika" src="//niezbednik.niedziela.pl/images/wsparcieNiezbednik-entrance.jpg" >
-
- </a>
-
- </div>
- </div>
- </div>
-</div>
-
-
- - - - - <div class="cookies"> - <div class="text-center p-main border-solid"> - <p>W związku z tym, iż od dnia 25 maja 2018 roku obowiązuje <i>Rozporządzenie Parlamentu Europejskiego i Rady (UE) 2016/679 z dnia 27 kwietnia 2016r. w sprawie ochrony osób fizycznych w związku z przetwarzaniem danych osobowych i w sprawie swobodnego przepływu takich danych</i> oraz <i>uchylenia Dyrektywy 95/46/WE (ogólne rozporządzenie o ochronie danych)</i> uprzejmie Państwa informujemy, iż nasza organizacja, mając szczególnie na względzie bezpieczeństwo danych osobowych, które przetwarza, wdrożyła System Zarządzania Bezpieczeństwem Informacji w rozumieniu odpowiednich polityk ochrony danych (zgodnie z art. 24 ust. 2 przedmiotowego rozporządzenia ogólnego). W celu dochowania należytej staranności w kontekście ochrony danych osobowych, Zarząd Instytutu NIEDZIELA wyznaczył w organizacji Inspektora Ochrony Danych. - <br><a target="_prywatnosc" class="" href="https://niedziela.pl/polityka_prywatnosci">Więcej o polityce prywatności czytaj TUTAJ</a>. - </p> - <p class="text-center pt-half"><a class="closecookies btn btn-default btn-sm" href="#"><strong>Akceptuję</strong></a></p> - </div> - </div> - - - - <script src="/assets/a2538e11/jquery.min.js?v=1680299989"></script> -<script src="/assets/2f582ad1/yii.js?v=1680299989"></script> -<script src="/assets/7ca11ba7/dist/js/bootstrap.bundle.min.js?v=1680299989"></script> -<script src="/js/modernizr-2.6.2.min.js?v=1663058799"></script> -<script src="/js/cookie.js?v=1615876568"></script> -<script src="/js/jquery.fitvids.js?v=1480508397"></script> -<script src="/js/aos.js?v=1659426147"></script> -<script src="/js/jquery.easing.1.3.js?v=1663056769"></script> -<script src="/js/jquery.waypoint.min.js?v=1663048957"></script> -<script src="/js/animated.headline.js?v=1663058587"></script> -<script src="/js/sticky-kit.min.js?v=1663058674"></script> -<script src="/js/swiper/swiper.min.js?v=1680301166"></script> -<script src="/js/cookie-consent.js?v=1726132310"></script> -<script src="/js/script.js?v=1765368704"></script> -<script src="/js/main.js?v=1681205062"></script> -<script>jQuery(function ($) { -var magazineSwiper = new Swiper ('.swiper-rozwazania', { - // Optional parameters - //direction: 'vertical', - - //slidesPerView: 'auto', - spaceBetween: 10, - //loop: true, - navigation: { - nextEl: '.swiper-rozwazania-button-next', - prevEl: '.swiper-rozwazania-button-prev' - }, - - mousewheel: false, - - - // And if we need scrollbar - scrollbar: { - el: '.swiper-rozwazania-scrollbar' - }, - breakpoints: { - 0: { - slidesPerView: 1.6 - }, - 768: { - slidesPerView: 2.6, - slidesPerGroup: 2 - }, - 1200: { - slidesPerView: 3.6, - slidesPerGroup: 3 - } - } - }); -
-var kalendarzSwiper = new Swiper ('.swiper-kalendarz', {
- // Optional parameters
- //direction: 'vertical',
- //slidesPerView: 'auto',
- //slidesPerView: 'auto',
- spaceBetween: 10,
- initialSlide: 8,
- //loop: true,
- navigation: {
- nextEl: '.swiper-kalendarz-button-next',
- prevEl: '.swiper-kalendarz-button-prev'
- },
-
- mousewheel: false,
-
-
- // And if we need scrollbar
- scrollbar: {
- el: '.swiper-kalendarz-scrollbar'
- },
- breakpoints: {
- 0: {
- slidesPerView: 1.6,
- centeredSlides: true,
- },
- 768: {
- slidesPerView: 2.6,
- centeredSlides: false,
- },
- 1200: {
- slidesPerView: 7,
- slidesPerGroup: 7,
- centeredSlides: false,
- }
- },
- on: {
- slideChange: function () {
- $('#panelCalendarTitle').text($('.swiper-kalendarz > .swiper-wrapper > .swiper-slide').eq(kalendarzSwiper.activeIndex).data('week'));
- },
- },
- });
- $('#panelCalendarTitle').text($('.swiper-kalendarz > .swiper-wrapper > .swiper-slide').eq(7).data('week')); -var wiadomosciSwiper = new Swiper ('.swiper-wiadomosci', {
- // Optional parameters
- //direction: 'vertical',
-
- //slidesPerView: 'auto',
- spaceBetween: 10,
- //loop: true,
- navigation: {
- nextEl: '.swiper-wiadomosci-button-next',
- prevEl: '.swiper-wiadomosci-button-prev'
- },
-
- mousewheel: false,
-
-
- // And if we need scrollbar
- scrollbar: {
- el: '.swiper-wiadomosci-scrollbar'
- },
- breakpoints: {
- 0: {
- slidesPerView: 1.6
- },
- 768: {
- slidesPerView: 2.6,
- slidesPerGroup: 2
- },
- 1200: {
- slidesPerView: 3.6,
- slidesPerGroup: 3
- }
- }
- }); -
-$('#entranceModal').on('show.bs.modal', function (e) {
- if (typeof gtag === "function") {
- //ga("send", "event", "Entrance Modal", "Show", window.location.href, 1, {"nonInteraction": true });
- gtag("event", "EntranceModal - Donation (Show)", {"eventCategory": "Entrance Modal", "eventLabel": window.location.href});
- }
-
-});
-
-
-
- setTimeout(function(){
-
- const myModal = new bootstrap.Modal('#entranceModal');
-
- myModal.show({backdrop: 'static'});
-
- }, 10000);
-
-
-
-
-
- - - $(".closecookies").click(function() { - Cookies.set("prywatnoscaccept", "1", { expires: 1000 }); - //$.cookie("prywatnoscaccept", 1, {path: "/", expires: 1000}); - $(".cookies").hide(); - return false; - }); - -});</script> -</body> - -</html> -
-
-
-
-
diff --git a/internal/liturgy/testdata/2026-07-22.html b/internal/liturgy/testdata/2026-07-22.html deleted file mode 100644 index 6573210..0000000 --- a/internal/liturgy/testdata/2026-07-22.html +++ /dev/null @@ -1,2831 +0,0 @@ -
-<!DOCTYPE html> -<html lang="pl-PL"> - -<head> - <meta charset="UTF-8"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <meta name="keywords" content="liturgia, czytania na dziś, lirturgis na dzis, czytanie na niedzielę, psalm na dziś, kalendarz liturgiczny, brewiarz, liturgia godzin, biblia, patron, święty, błogosławiony, rozważania, ewangelia, różanieć, tajmenice rózańcowe"> - <meta name="news_keywords" content="liturgia, czytania na dziś, kalendarz liturgiczny, brewiarz, liturgia godzin, biblia, patron, święty, błogosławiony, rozważania, ewangelia, różanieć, tajmenice rózańcowe"> - <meta name="description" content="Niezbędnik katolika - czytanie na dziś, rozważanie do Ewangelii, czytania liturgiczne, kalendarz liturgiczny, brewiarz, o czym warto pamiętać, czytania na każdy dzień, Slowo Boże na każdy dzień"> - <link rel="apple-touch-icon" sizes="57x57" href="https://niezbednik.niedziela.pl/apple-icon-57x57.png"> - <link rel="apple-touch-icon" sizes="60x60" href="https://niezbednik.niedziela.pl/apple-icon-60x60.png"> - <link rel="apple-touch-icon" sizes="72x72" href="https://niezbednik.niedziela.pl/apple-icon-72x72.png"> - <link rel="apple-touch-icon" sizes="76x76" href="https://niezbednik.niedziela.pl/apple-icon-76x76.png"> - <link rel="apple-touch-icon" sizes="114x114" href="https://niezbednik.niedziela.pl/apple-icon-114x114.png"> - <link rel="apple-touch-icon" sizes="120x120" href="https://niezbednik.niedziela.pl/apple-icon-120x120.png"> - <link rel="apple-touch-icon" sizes="144x144" href="https://niezbednik.niedziela.pl/apple-icon-144x144.png"> - <link rel="apple-touch-icon" sizes="152x152" href="https://niezbednik.niedziela.pl/apple-icon-152x152.png"> - <link rel="apple-touch-icon" sizes="180x180" href="https://niezbednik.niedziela.pl/apple-icon-180x180.png"> - <link rel="icon" type="image/png" sizes="192x192" href="https://niezbednik.niedziela.pl/android-icon-192x192.png"> - <link rel="icon" type="image/png" sizes="32x32" href="https://niezbednik.niedziela.pl/favicon-32x32.png"> - <link rel="icon" type="image/png" sizes="96x96" href="https://niezbednik.niedziela.pl/favicon-96x96.png"> - <link rel="icon" type="image/png" sizes="16x16" href="https://niezbednik.niedziela.pl/favicon-16x16.png"> - <link rel="manifest" href="https://niezbednik.niedziela.pl/manifest.json"> - <meta name="msapplication-TileColor" content="#ffffff"> - <meta name="msapplication-TileImage" content="https://niezbednik.niedziela.pl/ms-icon-144x144.png"> - <meta name="theme-color" content="#ffffff"> - <title>Niezbędnik katolika - czytania na 2026-07-22</title> - <link rel="canonical" href="https://niezbednik.niedziela.pl/liturgia/2026-07-22"> - - - <link rel="preconnect" href="https://fonts.googleapis.com"> - <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> - <link href="https://fonts.googleapis.com/css2?family=Work+Sans:ital,wght@0,400;0,500;0,700;1,400;1,700&family=PT+Serif:ital,wght@0,400;0,700;1,400;1,700&display=swap" rel="stylesheet"> - - - <link href="/assets/7ca11ba7/dist/css/bootstrap.min.css?v=1680299989" rel="stylesheet"> -<link href="/font-awesome/css/font-awesome.min.css?v=1488459453" rel="stylesheet"> -<link href="/css/animate.css?v=1663049856" rel="stylesheet"> -<link href="/css/swiper/swiper.min.css?v=1573878192" rel="stylesheet"> -<link href="/css/cookie-consent.css?v=1726132740" rel="stylesheet"> -<link href="/css/main.css?v=1774598783" rel="stylesheet"> - - - - <!-- Google tag (gtag.js) --> - <script async src="https://www.googletagmanager.com/gtag/js?id=G-3E6YN6ZC9K"></script> - <script> - window.dataLayer = window.dataLayer || []; - - function gtag() { - dataLayer.push(arguments); - } - gtag('js', new Date()); - - gtag('config', 'G-3E6YN6ZC9K'); - </script> - </head> - -<body class=""> - - - <!-- Progress scroll totop --> - <div class="progress-wrap cursor-pointer d-none"> - <svg class="progress-circle svg-content" width="100%" height="100%" viewBox="-1 -1 102 102"> - <path d="M50,1 a49,49 0 0,1 0,98 a49,49 0 0,1 0,-98" /> - </svg> - </div> - - <div id="theme-page"> - -
-
-<aside id="theme-aside-dark" class="background-primary lh-sm">
- <div class="menu-close lh-1 d-md-none"><a href="#" class="js-theme-nav-toggle">
- <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-x" viewBox="0 0 16 16">
- <path d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z" />
- </svg></a></div>
- <div class="position-relative h-100">
-
- <nav class="navbar navbar-accessibility mb-1 d-md-block d-none">
-
- <div class="d-inline-flex w-100">
- <ul class="nav list-inline mx-auto color-light">
- <li class="list-inline-item pt-0 pr-1 pb-0 pl-0">
- <a href="#" class="btn-font-size color-light" accesskey="b">
- <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-font-increase" viewBox="0 0 16 16">
- <path d="M8.59,12.033H3.815l-0.907,2.715H0.014L4.931,1.53h2.526l4.946,13.218H9.508L8.59,12.033z M14.248,4.976v1.739h-1.705V4.976
- h-1.74V3.269h1.74V1.53h1.705v1.739h1.738v1.707H14.248z M4.55,9.82h3.306L6.195,4.87L4.55,9.82L4.55,9.82z" />
- </svg><span class="visually-hidden">Wielkość czcionki</span>
- </a>
- </li>
- <li class="list-inline-item py-0 px-1 link-contrast">
- <a href="/site/contrast" accesskey="c" class="btn-contrast">A<span class="visually-hidden">Wersja graficzna</span></a>
- </li>
- </ul>
- </div>
-
- </nav>
-
- <!-- Logo -->
- <div id="theme-logo" style="margin-bottom: 1em;"> <a href="https://niezbednik.niedziela.pl">
- <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi color-white" style="font-size: 4.5em" viewBox="0 0 16 16">
-
- <path d="M4.286,9.063c1.004,0.876,2.082,1.274,3.208,1.185c1.078-0.087,2.059-0.609,2.836-1.185
- C9.553,8.488,8.571,7.968,7.494,7.879C6.368,7.789,5.29,8.188,4.286,9.063z" />
- <path d="M13.989,4.023H13.33V3.931c0-0.222-0.18-0.401-0.402-0.401H12.37c-0.222,0-0.401,0.18-0.401,0.401v0.093h-0.788V3.136
- c0-1.008-0.822-1.829-1.831-1.829h-2.7c-1.009,0-1.83,0.821-1.83,1.829v0.888H4.031V3.931c0-0.222-0.179-0.401-0.401-0.401H3.071
- c-0.222,0-0.401,0.18-0.401,0.401v0.093H2.011c-0.92,0-1.666,0.745-1.666,1.666v7.338c0,0.92,0.746,1.666,1.666,1.666h11.979
- c0.921,0,1.666-0.746,1.666-1.666V5.689C15.655,4.769,14.91,4.023,13.989,4.023z M5.866,3.136c0-0.432,0.352-0.784,0.784-0.784h2.7
- c0.433,0,0.785,0.353,0.785,0.784v0.888H5.866V3.136z M12.578,10.402l-0.48,0.362c-0.01-0.013-0.492-0.642-1.275-1.313
- c-1.082,0.827-2.207,1.308-3.277,1.396c-0.124,0.01-0.247,0.016-0.37,0.016c-1.258,0-2.449-0.531-3.546-1.583L3.421,9.063
- l0.208-0.217c1.204-1.153,2.52-1.679,3.916-1.566c1.07,0.087,2.195,0.568,3.277,1.396c0.783-0.67,1.266-1.3,1.275-1.313l0.48,0.362
- c-0.021,0.028-0.492,0.653-1.281,1.34C12.086,9.75,12.557,10.377,12.578,10.402z" />
- </svg>
- <p class="lh-sm pt-1" style="font-size: 1em;"><span>Niezbędnik<br>katolika</span></p>
- </a>
- </div>
- <!-- Menu -->
- <nav id="theme-main-menu">
- <ul class="mb-5">
- <li><a href="https://niezbednik.niedziela.pl">Strona główna</a></li>
- <li><a href="https://niezbednik.niedziela.pl/biblia">Biblia</a></li>
- <li><a href="https://niezbednik.niedziela.pl/liturgia#20260722">Kalendarz liturgiczny</a></li>
- <li><a href="/dzial/5/Modlitewnik">Modlitewnik</a></li>
- <li><a href="https://niezbednik.niedziela.pl/spiewnik">Śpiewnik</a></li>
- <li><a href="https://www.niedziela.pl/dzial/6/Wiara">Wiara</a></li>
- </ul>
-
- - -<div class="text-center mb-3 mx-auto p-3 border background-red-dark"> - <p class="m-0 mb-2 text-danger text-center font-sans text-white" style="line-height: 1"><small>Na funkcjonowanie serwisu do końca II kwartału: </small><span class="fw-bold">144 000 zł</span></p> - <div class="progress border " style="height: 2rem;"> - <div class="progress-bar progress-bar-striped bg-danger" role="progressbar" aria-valuenow="75" aria-valuemin="0" aria-valuemax="100" style="width: 93%"><span class="fw-bold fs-5 mx-2" style="">93%</span></div> - </div> - <p class="m-0 mt-1 text-start font-sans text-white"><small>Uzbieraliśmy: </small><span class="fw-bold">133 211 zł</span></p> - - <div class="text-center mt-3"> - <a href="/wsparcie" class="btn btn-red m-0" data-clicksmap="liturgia-AsideBtnDonation-Desktop">Wesprzyj nas <svg xmlns="http://www.w3.org/2000/svg" - width="40" height="40" viewBox="0 0 40 40" fill="currentColor" class="bi"> - <path d="M20,2.796c-7.297,0-13.233,5.937-13.233,13.233S12.704,29.263,20,29.263c7.296,0,13.234-5.937,13.234-13.233 - S27.297,2.796,20,2.796z M20,5.442c5.837,0,10.587,4.75,10.587,10.587S25.838,26.617,20,26.617S9.414,21.867,9.414,16.03 - S14.163,5.442,20,5.442z M1.474,26.617v10.586H4.12v-7.94h7.121c-1.126-0.748-2.144-1.644-3.045-2.646H1.474z M31.804,26.617 - c-0.9,1.003-1.917,1.899-3.044,2.646h7.12v7.94h2.647V26.617H31.804z M6.767,31.91v2.647h26.467V31.91H6.767z" /> - <g> - <path d="M20.992,22.001h-6.898v-1.406l4.047-5.508h-3.805v-1.82h6.516v1.547l-3.938,5.367h4.078V22.001z" /> - <path d="M25.289,14.736l0.547-0.336l0.914,1.539l-1.461,0.875v5.188h-2.383v-3.727l-0.555,0.336l-0.883-1.539l1.438-0.875V9.845 - h2.383V14.736z" /> - </g> - </svg></a> - </div> - </div> -
-
- <div class="d-flex justify-content-center w-100 mt-4 mx-auto" style="bottom: 0;">
-
- <!-- Sidebar Footer -->
- <div class="text-center mx-2">
- <small class="color-white">Tworzony przez</small>
- <br><a href="//niedziela.pl"><img src="https://www.niedziela.pl/img/logo.jpg" class="img-fluid mb-2" style="height: 2em;"></a>
- </div>
- </div>
- </div>
- </nav>
-
-</aside> - <div id="theme-main"> - - - - <div class="pt-3 px-3" style="clear: both" id="content">
- <article> - - - - - - - - - <h1 class="mb-4 lh-1 text-uppercase"> - Czytania liturgiczne na dziś; - Rok A, II </h1> - <div class="row"> - - <div class="col-xs-12"> - - <div class="social-btn" style="margin: 0 0 0.5em 0" data-ayoshare="https://niezbednik.niedziela.pl/liturgia/2026-07-22"></div> - - </div> - -</div> - - - - - <p class="font-serif fw-bold"><em>Święto św. Marii Magdaleny</em></p> - - <p class="font-sans">Kolor szat: <span class="fw-bold">biały</span></p> - - - - - - - - - - <ul class="nav nav-tabs" role="tablist"> - <li class="nav-item" role="presentation"> - <button class="nav-link active" id="tabnowy0-tab" data-bs-toggle="tab" data-bs-target="#tabnowy0" type="button" role="tab" aria-controls="tabnowy0" aria-selected="true">Nowy lekcjonarz</button> - </li> - - <li class="nav-item" role="presentation"> - <button class="nav-link " id="tabstary0-tab" data-bs-toggle="tab" data-bs-target="#tabstary0" type="button" role="tab" aria-controls="tabstary0" aria-selected="true">Stary lekcjonarz</button> - </li> - </ul> - - <div id="lekcjonarzTabContent0" class="tab-content m-2"> - <div class="tab-elementy tab-pane fade active show" id="tabnowy0"> - - <ul class="nav nav-tabs" role="tablist"> - <li class="nav-item" role="presentation"> - <button class="nav-link " id="tabnowy0all-tab" data-bs-toggle="tab" data-bs-target="#tabnowy0all" type="button" role="tab" aria-controls="tabnowy0all" aria-selected="true">Całość</button> - </li> - - <li class="nav-item" role="presentation"> - <button class="nav-link " id="tabnowy00-tab" data-bs-toggle="tab" data-bs-target="#tabnowy00" type="button" role="tab" aria-controls="tabnowy00" aria-selected="true">1. czytanie</button> - </li> - - <li class="nav-item" role="presentation"> - <button class="nav-link " id="tabnowy01-tab" data-bs-toggle="tab" data-bs-target="#tabnowy01" type="button" role="tab" aria-controls="tabnowy01" aria-selected="true">1. czytanie</button> - </li> - - <li class="nav-item" role="presentation"> - <button class="nav-link " id="tabnowy02-tab" data-bs-toggle="tab" data-bs-target="#tabnowy02" type="button" role="tab" aria-controls="tabnowy02" aria-selected="true">Psalm</button> - </li> - - <li class="nav-item" role="presentation"> - <button class="nav-link " id="tabnowy03-tab" data-bs-toggle="tab" data-bs-target="#tabnowy03" type="button" role="tab" aria-controls="tabnowy03" aria-selected="true">Aklamacja</button> - </li> - - <li class="nav-item" role="presentation"> - <button class="nav-link active" id="tabnowy04-tab" data-bs-toggle="tab" data-bs-target="#tabnowy04" type="button" role="tab" aria-controls="tabnowy04" aria-selected="true">Ewangelia</button> - </li> - - </ul> - - - <div id="elementyTabContent0" class="tab-content liturgia-content py-2 px-4 background-white"> - - <div class="tab-pane fade " id="tabnowy0all"> - - - <h2>1. czytanie (<a href="/biblia/piesn-nad-piesniami/8" class="">Pnp 8</a>, 6-7)</h2><h4><em>Jak śmierć potężna jest miłość</em></h4><p><strong>Czytanie z Księgi Pieśni nad pieśniami</strong></p><p>Połóż mnie jak pieczęć na twoim sercu, jak pieczęć na twoim ramieniu, bo jak śmierć potężna jest miłość, a zazdrość jej nieprzejednana jak Szeol; żar jej to żar ognia, uderzenie boskiego gromu.</p>
-
-<p>Wody wielkie nie zdołają ugasić miłości, nie zatopią jej rzeki. Jeśliby kto oddał za miłość całe bogactwo swego domu, z pewnością nim pogardzą.</p>
-
-<p><B>Albo:</p></b>
- - - <h2>1. czytanie (<a href="/biblia/drugi-list-do-koryntian/5" class="">2 Kor 5</a>, 14-17)</h2><h4><em>Miłość Chrystusa przynagla nas</em></h4><p><strong>Czytanie z Drugiego listu świętego Pawła Apostoła do Koryntian</strong></p><p>Bracia:</p>
-
-<p>Miłość Chrystusa przynagla nas, pomnych na to, że skoro Jeden umarł za wszystkich, to wszyscy pomarli. A właśnie za wszystkich umarł Chrystus po to, aby ci, co żyją, już nie żyli dla siebie, lecz dla Tego, który za nich umarł i zmartwychwstał.</p>
-
-<p>Tak więc i my odtąd już nikogo nie znamy według ciała; a jeśli nawet według ciała poznaliśmy Chrystusa, to już więcej nie znamy Go w ten sposób. Jeżeli więc ktoś pozostaje w Chrystusie, jest nowym stworzeniem. To, co dawne, minęło, a oto wszystko stało się nowe.</p>
-
-<p><B>W kościołach, które obchodzą uroczystość, powyższe czytanie czyta się jako drugie.</p></B>
- - - <h2>Psalm (<a href="/biblia/ksiega-psalmow/63" class="">Ps 63 (62)</a>, 2. 3-4. 5-6. 8-9 (R.: por. 2ab))</h2><h4><em>Ciebie, mój Boże, pragnie moja dusza</em></h4><p><strong></strong></p><p>Boże, mój Boże, szukam Ciebie *
-<br>i pragnie Ciebie moja dusza.
-<br>Ciało moje tęskni za Tobą *
-<br>jak zeschła ziemia łaknąca wody.</p><p><strong>Ciebie, mój Boże, pragnie moja dusza</strong></p>
-
-<p>Oto wpatruję się w Ciebie w świątyni, *
-<br>by ujrzeć Twą potęgę i chwałę.
-<br>Twoja łaska jest cenniejsza od życia, *
-<br>więc sławić Cię będą moje wargi.</p><p><strong>Ciebie, mój Boże, pragnie moja dusza</strong></p>
-
-<p>Będę Cię wielbił przez całe me życie *
-<br>i wzniosę ręce w imię Twoje.
-<br>Moja dusza syci się obficie, *
-<br>a usta Cię wielbią radosnymi wargami.</p><p><strong>Ciebie, mój Boże, pragnie moja dusza</strong></p>
-
-<p>Bo stałeś się dla mnie pomocą *
-<br>i w cieniu Twych skrzydeł wołam radośnie:
-<br>Do Ciebie lgnie moja dusza, *
-<br>prawica Twoja mnie wspiera.</p><p><strong>Ciebie, mój Boże, pragnie moja dusza</strong></p> - - <h2>Aklamacja (por. J 20, 11)</h2><h4><em>Alleluja, alleluja, alleluja</em></h4><p><strong></strong></p><p>Mario, Ty powiedz, coś w drodze widziała?
-<br>Jam zmartwychwstałego blask chwały ujrzała.
-<br>Żywego już Pana widziałam grób pusty
-<br>i świadków anielskich, i odzież, i chusty.</p><p><strong>Alleluja, alleluja, alleluja</strong></p>
- - - <h2>Ewangelia (<a href="/biblia/ewangelia-wg-sw-jana/20" class="">J 20</a>, 1. 11-18)</h2><h4><em>Niewiasto, czemu płaczesz? Kogo szukasz?</em></h4><p><strong>Słowa Ewangelii według świętego Jana</strong></p><p>Pierwszego dnia po szabacie, wczesnym rankiem, gdy jeszcze było ciemno, Maria Magdalena udała się do grobu i zobaczyła kamień odsunięty od grobu.</p>
-
-<p>Stała ona przed grobem, płacząc. A kiedy tak płakała, nachyliła się do grobu i ujrzała dwóch aniołów w bieli, siedzących tam, gdzie leżało ciało Jezusa - jednego w miejscu głowy, drugiego w miejscu nóg.</p>
-
-<p>I rzekli do niej: «Niewiasto, czemu płaczesz?».</p>
-
-<p>Odpowiedziała im: «Zabrano Pana mego i nie wiem, gdzie Go położono».</p>
-
-<p>Gdy to powiedziała, odwróciła się i ujrzała stojącego Jezusa, ale nie wiedziała, że to Jezus.</p>
-
-<p>Rzekł do niej Jezus: «Niewiasto, czemu płaczesz? Kogo szukasz?».</p>
-
-<p>Ona zaś sądząc, że to jest ogrodnik, powiedziała do Niego: «Panie, jeśli ty Go przeniosłeś, powiedz mi, gdzie Go położyłeś, a ja Go zabiorę».</p>
-
-<p>Jezus rzekł do niej: «Mario!». A ona, obróciwszy się, powiedziała do Niego po hebrajsku: «Rabbuni», to znaczy: Mój Nauczycielu!</p>
-
-<p>Rzekł do niej Jezus: «Nie zatrzymuj Mnie, jeszcze bowiem nie wstąpiłem do Ojca. Natomiast udaj się do moich braci i powiedz im: „Wstępuję do Ojca mego i Ojca waszego oraz do Boga mego i Boga waszego”».</p>
-
-<p>Poszła Maria Magdalena oznajmiając uczniom: «Widziałam Pana», i co jej powiedział.</p>
- - </div> - - - <div class="tab-pane fade " id="tabnowy00"> - - <h2>1. czytanie (<a href="/biblia/piesn-nad-piesniami/8" class="">Pnp 8</a>, 6-7)</h2><h4><em>Jak śmierć potężna jest miłość</em></h4><p><strong>Czytanie z Księgi Pieśni nad pieśniami</strong></p><p>Połóż mnie jak pieczęć na twoim sercu, jak pieczęć na twoim ramieniu, bo jak śmierć potężna jest miłość, a zazdrość jej nieprzejednana jak Szeol; żar jej to żar ognia, uderzenie boskiego gromu.</p>
-
-<p>Wody wielkie nie zdołają ugasić miłości, nie zatopią jej rzeki. Jeśliby kto oddał za miłość całe bogactwo swego domu, z pewnością nim pogardzą.</p>
-
-<p><B>Albo:</p></b>
- - </div> - - <div class="tab-pane fade " id="tabnowy01"> - - <h2>1. czytanie (<a href="/biblia/drugi-list-do-koryntian/5" class="">2 Kor 5</a>, 14-17)</h2><h4><em>Miłość Chrystusa przynagla nas</em></h4><p><strong>Czytanie z Drugiego listu świętego Pawła Apostoła do Koryntian</strong></p><p>Bracia:</p>
-
-<p>Miłość Chrystusa przynagla nas, pomnych na to, że skoro Jeden umarł za wszystkich, to wszyscy pomarli. A właśnie za wszystkich umarł Chrystus po to, aby ci, co żyją, już nie żyli dla siebie, lecz dla Tego, który za nich umarł i zmartwychwstał.</p>
-
-<p>Tak więc i my odtąd już nikogo nie znamy według ciała; a jeśli nawet według ciała poznaliśmy Chrystusa, to już więcej nie znamy Go w ten sposób. Jeżeli więc ktoś pozostaje w Chrystusie, jest nowym stworzeniem. To, co dawne, minęło, a oto wszystko stało się nowe.</p>
-
-<p><B>W kościołach, które obchodzą uroczystość, powyższe czytanie czyta się jako drugie.</p></B>
- - </div> - - <div class="tab-pane fade " id="tabnowy02"> - - <h2>Psalm (<a href="/biblia/ksiega-psalmow/63" class="">Ps 63 (62)</a>, 2. 3-4. 5-6. 8-9 (R.: por. 2ab))</h2><h4><em>Ciebie, mój Boże, pragnie moja dusza</em></h4><p><strong></strong></p><p>Boże, mój Boże, szukam Ciebie *
-<br>i pragnie Ciebie moja dusza.
-<br>Ciało moje tęskni za Tobą *
-<br>jak zeschła ziemia łaknąca wody.</p><p><strong>Ciebie, mój Boże, pragnie moja dusza</strong></p>
-
-<p>Oto wpatruję się w Ciebie w świątyni, *
-<br>by ujrzeć Twą potęgę i chwałę.
-<br>Twoja łaska jest cenniejsza od życia, *
-<br>więc sławić Cię będą moje wargi.</p><p><strong>Ciebie, mój Boże, pragnie moja dusza</strong></p>
-
-<p>Będę Cię wielbił przez całe me życie *
-<br>i wzniosę ręce w imię Twoje.
-<br>Moja dusza syci się obficie, *
-<br>a usta Cię wielbią radosnymi wargami.</p><p><strong>Ciebie, mój Boże, pragnie moja dusza</strong></p>
-
-<p>Bo stałeś się dla mnie pomocą *
-<br>i w cieniu Twych skrzydeł wołam radośnie:
-<br>Do Ciebie lgnie moja dusza, *
-<br>prawica Twoja mnie wspiera.</p><p><strong>Ciebie, mój Boże, pragnie moja dusza</strong></p> - </div> - - <div class="tab-pane fade " id="tabnowy03"> - - <h2>Aklamacja (por. J 20, 11)</h2><h4><em>Alleluja, alleluja, alleluja</em></h4><p><strong></strong></p><p>Mario, Ty powiedz, coś w drodze widziała?
-<br>Jam zmartwychwstałego blask chwały ujrzała.
-<br>Żywego już Pana widziałam grób pusty
-<br>i świadków anielskich, i odzież, i chusty.</p><p><strong>Alleluja, alleluja, alleluja</strong></p>
- - </div> - - - - <div class="tab-pane fade active show" id="tabnowy04"> - - - - - - <h2>Ewangelia (<a href="/biblia/ewangelia-wg-sw-jana/20" class="">J 20</a>, 1. 11-18)</h2><h4><em>Niewiasto, czemu płaczesz? Kogo szukasz?</em></h4><p><strong>Słowa Ewangelii według świętego Jana</strong></p><p>Pierwszego dnia po szabacie, wczesnym rankiem, gdy jeszcze było ciemno, Maria Magdalena udała się do grobu i zobaczyła kamień odsunięty od grobu.</p>
-
-<p>Stała ona przed grobem, płacząc. A kiedy tak płakała, nachyliła się do grobu i ujrzała dwóch aniołów w bieli, siedzących tam, gdzie leżało ciało Jezusa - jednego w miejscu głowy, drugiego w miejscu nóg.</p>
-
-<p>I rzekli do niej: «Niewiasto, czemu płaczesz?».</p>
-
-<p>Odpowiedziała im: «Zabrano Pana mego i nie wiem, gdzie Go położono».</p>
-
-<p>Gdy to powiedziała, odwróciła się i ujrzała stojącego Jezusa, ale nie wiedziała, że to Jezus.</p>
-
-<p>Rzekł do niej Jezus: «Niewiasto, czemu płaczesz? Kogo szukasz?».</p>
-
-<p>Ona zaś sądząc, że to jest ogrodnik, powiedziała do Niego: «Panie, jeśli ty Go przeniosłeś, powiedz mi, gdzie Go położyłeś, a ja Go zabiorę».</p>
-
-<p>Jezus rzekł do niej: «Mario!». A ona, obróciwszy się, powiedziała do Niego po hebrajsku: «Rabbuni», to znaczy: Mój Nauczycielu!</p>
-
-<p>Rzekł do niej Jezus: «Nie zatrzymuj Mnie, jeszcze bowiem nie wstąpiłem do Ojca. Natomiast udaj się do moich braci i powiedz im: „Wstępuję do Ojca mego i Ojca waszego oraz do Boga mego i Boga waszego”».</p>
-
-<p>Poszła Maria Magdalena oznajmiając uczniom: «Widziałam Pana», i co jej powiedział.</p>
- - - </div> - - </div> - - <div class="prev-next text-center"> - <a href="#" class="btn btn-default disabled prev-tab fs-4"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-left" viewBox="0 0 16 16"> - <path fill-rule="evenodd" d="M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z"/> -</svg></a> - <a href="#" class="btn btn-default next-tab fs-4"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-right" viewBox="0 0 16 16"> - <path fill-rule="evenodd" d="M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z"/> -</svg></a> - </div> - </div> - - <div class="tab-elementy tab-pane fade " id="tabstary0"> - - <ul class="nav nav-tabs"> - <li class="nav-item" role="presentation"> - <button class="nav-link " id="tabstary0all-tab" data-bs-toggle="tab" data-bs-target="#tabstary0all" type="button" role="tab" aria-controls="tabstary0all" aria-selected="true">Całość</button> - </li> - <li class="nav-item" role="presentation"> - <button class="nav-link " id="tabstary00-tab" data-bs-toggle="tab" data-bs-target="#tabstary00" type="button" role="tab" aria-controls="tabstary00" aria-selected="true">1. czytanie</button> - </li> - - <li class="nav-item" role="presentation"> - <button class="nav-link " id="tabstary01-tab" data-bs-toggle="tab" data-bs-target="#tabstary01" type="button" role="tab" aria-controls="tabstary01" aria-selected="true">1. czytanie</button> - </li> - - <li class="nav-item" role="presentation"> - <button class="nav-link " id="tabstary02-tab" data-bs-toggle="tab" data-bs-target="#tabstary02" type="button" role="tab" aria-controls="tabstary02" aria-selected="true">Psalm</button> - </li> - - <li class="nav-item" role="presentation"> - <button class="nav-link " id="tabstary03-tab" data-bs-toggle="tab" data-bs-target="#tabstary03" type="button" role="tab" aria-controls="tabstary03" aria-selected="true">Aklamacja</button> - </li> - - <li class="nav-item" role="presentation"> - <button class="nav-link active" id="tabstary04-tab" data-bs-toggle="tab" data-bs-target="#tabstary04" type="button" role="tab" aria-controls="tabstary04" aria-selected="true">Ewangelia</button> - </li> - - </ul> - - - <div id="elementyStaryTabContent0" class="tab-content liturgia-content py-2 px-4 background-white"> - - <div class="tab-pane fade " id="tabstary0all"> - - <h2>1. czytanie (<a href="/biblia/piesn-nad-piesniami/8" class="">Pnp 8</a>, 6-7)</h2><h4><em>Jak śmierć potężna jest miłość</em></h4><p><strong>Czytanie z Księgi Pieśni nad pieśniami</strong></p><p>Połóż mnie jak pieczęć na twoim sercu, jak pieczęć na twoim ramieniu, bo jak śmierć potężna jest miłość, a zazdrość jej nieprzejednana jak otchłań; żar jej to żar ognia, płomień Pana.</p>
-<p>Wody wielkie nie zdołają ugasić miłości, nie zatopią jej rzeki. Jeśliby kto oddał za miłość całe bogactwo swego domu, pogardzą nim tylko.</p> - - <p>Albo:</p><h2>1. czytanie (<a href="/biblia/drugi-list-do-koryntian/5" class="">2 Kor 5</a>, 14-17)</h2><h4><em>Miłość Chrystusa przynagla nas</em></h4><p><strong>Czytanie z Drugiego listu świętego Pawła Apostoła -do Koryntian</strong></p><p>Bracia:</p>
-<p>Miłość Chrystusa przynagla nas, pomnych na to, że skoro Jeden umarł za wszystkich, to wszyscy pomarli. A właśnie za wszystkich umarł Chrystus, aby ci, co żyją, już nie żyli dla siebie, lecz dla Tego, który za nich umarł i zmartwychwstał.</p>
-<p>Tak więc i my odtąd już nikogo nie znamy według ciała; a jeśli nawet według ciała poznaliśmy Chrystusa, to już więcej nie znamy Go w ten sposób. Jeżeli więc kto pozostaje w Chrystusie, jest nowym stworzeniem. To, co dawne, minęło, a oto wszystko stało się nowe.</p> - - <p>W kościołach, które obchodzą uroczystość, powyższe czytanie czyta się jako drugie.</p><h2>Psalm (<a href="/biblia/ksiega-psalmow/63" class="">Ps 63</a>, 2. 3-4. 5-6. 8-9 (R.: por. 2))</h2><h4><em>Ciebie, mój Boże, pragnie moja dusza</em></h4><p><strong></strong></p><p>Boże mój, Boże, szukam Ciebie *
-<br>i pragnie Ciebie moja dusza.
-<br>Ciało moje tęskni za Tobą, *
-<br>jak ziemia zeschła i łaknąca wody.</p><p><strong>Ciebie, mój Boże, pragnie moja dusza</strong></p>
-
-<p>Oto wpatruję się w Ciebie w świątyni, *
-<br>by ujrzeć Twą potęgę i chwałę.
-<br>Twoja łaska jest cenniejsza od życia, *
-<br>więc sławić Cię będą moje wargi.</p><p><strong>Ciebie, mój Boże, pragnie moja dusza</strong></p>
-
-<p>Będę Cię wielbił przez całe me życie *
-<br>i wzniosę ręce w imię Twoje.
-<br>Moja dusza syci się obficie, *
-<br>a usta Cię wielbią radosnymi wargami.</p><p><strong>Ciebie, mój Boże, pragnie moja dusza</strong></p>
-
-<p>Bo stałeś się dla mnie pomocą *
-<br>i w cieniu Twych skrzydeł wołam radośnie:
-<br>Do Ciebie lgnie moja dusza, *
-<br>prawica Twoja mnie wspiera.</p><p><strong>Ciebie, mój Boże, pragnie moja dusza</strong></p> - - <h2>Aklamacja (por. J 20, 11)</h2><h4><em>Alleluja, alleluja, alleluja</em></h4><p><strong></strong></p><p>Maryjo, Ty powiedz, coś w drodze widziała?
-<br>Jam zmartwychwstałego blask chwały ujrzała.
-<br>Żywego już Pana widziałam grób pusty
-<br>I świadków anielskich, i odzież, i chusty.</p><p><strong>Alleluja, alleluja, alleluja</strong></p>
- - - <h2>Ewangelia (<a href="/biblia/ewangelia-wg-sw-jana/20" class="">J 20</a>, 1. 11-18)</h2><h4><em>Zmartwychwstały Chrystus ukazuje się Magdalenie</em></h4><p><strong>Słowa Ewangelii według świętego Jana</strong></p><p>Pierwszego dnia po szabacie, wczesnym rankiem, gdy jeszcze było ciemno, Maria Magdalena udała się do grobu i zobaczyła kamień od niego odsunięty.</p>
-<p>Maria stała przed grobem płacząc. A kiedy tak płakała, nachyliła się do grobu i ujrzała dwóch aniołów w bieli, siedzących tam, gdzie leżało ciało Jezusa: jednego w miejscu głowy, a drugiego w miejscu nóg.</p>
-<p>I rzekli do niej: «Niewiasto, czemu płaczesz?».</p>
-<p>Odpowiedziała im: «Zabrano Pana mego i nie wiem, gdzie Go położono».</p>
-<p>Gdy to powiedziała, odwróciła się i ujrzała stojącego Jezusa, ale nie wiedziała, że to Jezus.</p>
-<p>Rzekł do niej Jezus: «Niewiasto, czemu płaczesz? Kogo szukasz?».</p>
-<p>Ona zaś sądząc, że to jest ogrodnik, powiedziała do Niego: «Panie, jeśli ty Go przeniosłeś, powiedz mi, gdzie Go położyłeś, a ja Go wezmę».</p>
-<p>Jezus rzekł do niej: «Mario!».</p>
-<p>A ona obróciwszy się powiedziała do Niego po hebrajsku: «Rabbuni», to znaczy: «Nauczycielu».</p>
-<p>Rzekł do niej Jezus: «Nie zatrzymuj Mnie; jeszcze bowiem nie wstąpiłem do Ojca. Natomiast udaj się do moich braci i powiedz im: „Wstępuję do Ojca mego i Ojca waszego oraz do Boga mego i Boga waszego”».</p>
-<p>Poszła Maria Magdalena oznajmiając uczniom: «Widziałam Pana i to mi powiedział».</p> - </div> - - - <div class="tab-pane fade " id="tabstary00"> - - <h2>1. czytanie (<a href="/biblia/piesn-nad-piesniami/8" class="">Pnp 8</a>, 6-7)</h2><h4><em>Jak śmierć potężna jest miłość</em></h4><p><strong>Czytanie z Księgi Pieśni nad pieśniami</strong></p><p>Połóż mnie jak pieczęć na twoim sercu, jak pieczęć na twoim ramieniu, bo jak śmierć potężna jest miłość, a zazdrość jej nieprzejednana jak otchłań; żar jej to żar ognia, płomień Pana.</p>
-<p>Wody wielkie nie zdołają ugasić miłości, nie zatopią jej rzeki. Jeśliby kto oddał za miłość całe bogactwo swego domu, pogardzą nim tylko.</p> - </div> - - <div class="tab-pane fade " id="tabstary01"> - - <p>Albo:</p><h2>1. czytanie (<a href="/biblia/drugi-list-do-koryntian/5" class="">2 Kor 5</a>, 14-17)</h2><h4><em>Miłość Chrystusa przynagla nas</em></h4><p><strong>Czytanie z Drugiego listu świętego Pawła Apostoła -do Koryntian</strong></p><p>Bracia:</p>
-<p>Miłość Chrystusa przynagla nas, pomnych na to, że skoro Jeden umarł za wszystkich, to wszyscy pomarli. A właśnie za wszystkich umarł Chrystus, aby ci, co żyją, już nie żyli dla siebie, lecz dla Tego, który za nich umarł i zmartwychwstał.</p>
-<p>Tak więc i my odtąd już nikogo nie znamy według ciała; a jeśli nawet według ciała poznaliśmy Chrystusa, to już więcej nie znamy Go w ten sposób. Jeżeli więc kto pozostaje w Chrystusie, jest nowym stworzeniem. To, co dawne, minęło, a oto wszystko stało się nowe.</p> - </div> - - <div class="tab-pane fade " id="tabstary02"> - - <p>W kościołach, które obchodzą uroczystość, powyższe czytanie czyta się jako drugie.</p><h2>Psalm (<a href="/biblia/ksiega-psalmow/63" class="">Ps 63</a>, 2. 3-4. 5-6. 8-9 (R.: por. 2))</h2><h4><em>Ciebie, mój Boże, pragnie moja dusza</em></h4><p><strong></strong></p><p>Boże mój, Boże, szukam Ciebie *
-<br>i pragnie Ciebie moja dusza.
-<br>Ciało moje tęskni za Tobą, *
-<br>jak ziemia zeschła i łaknąca wody.</p><p><strong>Ciebie, mój Boże, pragnie moja dusza</strong></p>
-
-<p>Oto wpatruję się w Ciebie w świątyni, *
-<br>by ujrzeć Twą potęgę i chwałę.
-<br>Twoja łaska jest cenniejsza od życia, *
-<br>więc sławić Cię będą moje wargi.</p><p><strong>Ciebie, mój Boże, pragnie moja dusza</strong></p>
-
-<p>Będę Cię wielbił przez całe me życie *
-<br>i wzniosę ręce w imię Twoje.
-<br>Moja dusza syci się obficie, *
-<br>a usta Cię wielbią radosnymi wargami.</p><p><strong>Ciebie, mój Boże, pragnie moja dusza</strong></p>
-
-<p>Bo stałeś się dla mnie pomocą *
-<br>i w cieniu Twych skrzydeł wołam radośnie:
-<br>Do Ciebie lgnie moja dusza, *
-<br>prawica Twoja mnie wspiera.</p><p><strong>Ciebie, mój Boże, pragnie moja dusza</strong></p> - </div> - - <div class="tab-pane fade " id="tabstary03"> - - <h2>Aklamacja (por. J 20, 11)</h2><h4><em>Alleluja, alleluja, alleluja</em></h4><p><strong></strong></p><p>Maryjo, Ty powiedz, coś w drodze widziała?
-<br>Jam zmartwychwstałego blask chwały ujrzała.
-<br>Żywego już Pana widziałam grób pusty
-<br>I świadków anielskich, i odzież, i chusty.</p><p><strong>Alleluja, alleluja, alleluja</strong></p>
- - </div> - - - - <div class="tab-pane fade active show" id="tabstary04"> - - - - - - <h2>Ewangelia (<a href="/biblia/ewangelia-wg-sw-jana/20" class="">J 20</a>, 1. 11-18)</h2><h4><em>Zmartwychwstały Chrystus ukazuje się Magdalenie</em></h4><p><strong>Słowa Ewangelii według świętego Jana</strong></p><p>Pierwszego dnia po szabacie, wczesnym rankiem, gdy jeszcze było ciemno, Maria Magdalena udała się do grobu i zobaczyła kamień od niego odsunięty.</p>
-<p>Maria stała przed grobem płacząc. A kiedy tak płakała, nachyliła się do grobu i ujrzała dwóch aniołów w bieli, siedzących tam, gdzie leżało ciało Jezusa: jednego w miejscu głowy, a drugiego w miejscu nóg.</p>
-<p>I rzekli do niej: «Niewiasto, czemu płaczesz?».</p>
-<p>Odpowiedziała im: «Zabrano Pana mego i nie wiem, gdzie Go położono».</p>
-<p>Gdy to powiedziała, odwróciła się i ujrzała stojącego Jezusa, ale nie wiedziała, że to Jezus.</p>
-<p>Rzekł do niej Jezus: «Niewiasto, czemu płaczesz? Kogo szukasz?».</p>
-<p>Ona zaś sądząc, że to jest ogrodnik, powiedziała do Niego: «Panie, jeśli ty Go przeniosłeś, powiedz mi, gdzie Go położyłeś, a ja Go wezmę».</p>
-<p>Jezus rzekł do niej: «Mario!».</p>
-<p>A ona obróciwszy się powiedziała do Niego po hebrajsku: «Rabbuni», to znaczy: «Nauczycielu».</p>
-<p>Rzekł do niej Jezus: «Nie zatrzymuj Mnie; jeszcze bowiem nie wstąpiłem do Ojca. Natomiast udaj się do moich braci i powiedz im: „Wstępuję do Ojca mego i Ojca waszego oraz do Boga mego i Boga waszego”».</p>
-<p>Poszła Maria Magdalena oznajmiając uczniom: «Widziałam Pana i to mi powiedział».</p> - - </div> - - </div> - - <div class="prev-next text-center mb-3"> - <a href="#" class="btn btn-default disabled prev-tab fs-4"> - <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-left" viewBox="0 0 16 16"> - <path fill-rule="evenodd" d="M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z"/> -</svg></a> - <a href="#" class="btn btn-default next-tab fs-4"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-right" viewBox="0 0 16 16"> - <path fill-rule="evenodd" d="M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z"/> -</svg></a> - </div> - </div> - - </div> - - - - -<div class="card border-0 px-lg-4 px-1 py-1 my-1 flat-alizarin"> - <div class="card-body text-md-left"> - <h2 class="mb-4 lh-1 text-uppercase">Polecamy</h2> - <div class="row align-items-start"> - - <div class="col-12"> - - - <p>Czytania Liturgiczne pochodzą z Lekcjonarza wydanego przez:<br><a href="http://www.pallottinum.pl/" data-clicksmap="liturgia-PanelZTLekcjonarzZrodlo-Desktop"><strong>Wydawnictwo Pallottinum</strong> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-right " viewBox="0 0 16 16">
- <path fill-rule="evenodd" d="M1 8a.5.5 0 0 1 .5-.5h11.793l-3.147-3.146a.5.5 0 0 1 .708-.708l4 4a.5.5 0 0 1 0 .708l-4 4a.5.5 0 0 1-.708-.708L13.293 8.5H1.5A.5.5 0 0 1 1 8z"/>
- </svg></a></p> - - </div> - </div> - </div> -</div> - -<div class="card border-0 px-lg-3 px-1 py-1 my-4 background-primary" > - <div class="card-body text-md-left"> - - <h2 class="mb-4 lh-1 text-uppercase" style="letter-spacing:2px">Pomóż w rozwoju serwisu </h2> - <div class="row align-items-start"> - <div class="col-md-9"> - - - <p>Aby nasz serwis mógł się rozwijać i trwać potrzebujemy regularnego wsparcia finansowego. Nie publikujemy komercyjnych reklam, jedynym źródłem finansowania jest Państwa wsparcie.<br>Zostań naszym patronem i ofiaruj nam wsparcie finansowe.</p> - -<div class="text-center mb-3 mx-auto p-3 border background-red-dark"> - <p class="m-0 mb-2 text-danger text-center font-sans text-white" style="line-height: 1"><small>Na funkcjonowanie serwisu do końca II kwartału: </small><span class="fw-bold">144 000 zł</span></p> - <div class="progress border " style="height: 2rem;"> - <div class="progress-bar progress-bar-striped bg-danger" role="progressbar" aria-valuenow="75" aria-valuemin="0" aria-valuemax="100" style="width: 93%"><span class="fw-bold fs-5 mx-2" style="">93%</span></div> - </div> - <p class="m-0 mt-1 text-start font-sans text-white"><small>Uzbieraliśmy: </small><span class="fw-bold">133 211 zł</span></p> - - <div class="text-center mt-3"> - <a href="/wsparcie" class="btn btn-red m-0" data-clicksmap="liturgia-AsideBtnDonation-Desktop">Wesprzyj nas <svg xmlns="http://www.w3.org/2000/svg" - width="40" height="40" viewBox="0 0 40 40" fill="currentColor" class="bi"> - <path d="M20,2.796c-7.297,0-13.233,5.937-13.233,13.233S12.704,29.263,20,29.263c7.296,0,13.234-5.937,13.234-13.233 - S27.297,2.796,20,2.796z M20,5.442c5.837,0,10.587,4.75,10.587,10.587S25.838,26.617,20,26.617S9.414,21.867,9.414,16.03 - S14.163,5.442,20,5.442z M1.474,26.617v10.586H4.12v-7.94h7.121c-1.126-0.748-2.144-1.644-3.045-2.646H1.474z M31.804,26.617 - c-0.9,1.003-1.917,1.899-3.044,2.646h7.12v7.94h2.647V26.617H31.804z M6.767,31.91v2.647h26.467V31.91H6.767z" /> - <g> - <path d="M20.992,22.001h-6.898v-1.406l4.047-5.508h-3.805v-1.82h6.516v1.547l-3.938,5.367h4.078V22.001z" /> - <path d="M25.289,14.736l0.547-0.336l0.914,1.539l-1.461,0.875v5.188h-2.383v-3.727l-0.555,0.336l-0.883-1.539l1.438-0.875V9.845 - h2.383V14.736z" /> - </g> - </svg></a> - </div> - </div> - - - </div> - <div class="col-12 col-md-3 mt-4 mt-md-0"> - <img src="https://niezbednik.niedziela.pl/images/dotacja.png" alt="" class="img-fluid w-75 mx-auto d-block"> - </div> - - </div> - </div> -</div> - -<div class="card border-0 px-lg-3 px-1 py-1 my-4 background-primary-01" > - <div class="card-body text-md-left"> - - <h2 class="mb-4 lh-1 text-uppercase" style="letter-spacing:2px">Nowości w Rafaelu </h2> - <div class="row align-items-start"> - <div class="col-12"> - - - -<div class="row"> - <div class="col-md-2"> - <img src="//niezbednik.niedziela.pl/images/ksiazki/rafael-ryta.png" class="img-fluid"> - </div> - <div class="col-md-10"> - <p><strong>Żywot Świętej Ryty. Patronka rzeczy nadzwyczajnych</strong> - <br>Kolejne wydanie historycznej biografii jednej z najbardziej znanych świętych - Ryty z Cascii. Pierwsze wydanie ukazało się w 1900 roku jako „Pamiątka Jubileuszowa” z okazji kanonizacji świętej. Obecna publikacja stanowi wierne, precyzyjne odtworzenie oryginalnego wydania, zachowujące jego treść i charakter. <br><a href="https://rafael.pl/zywot-swietej-ryty?utm_source=niedziela&utm_medium=cpc&utm_id=zywotswietejryty_niedziela" class="btn fw-bold" data-clicksmap="liturgia-RafaelRytaOferta-Desktop">ZOBACZ</a> - </p> - </div> - -</div> - - - </div> - - </div> - </div> -</div> -<div class="card border-0 px-lg-3 px-1 py-1 my-4 background-primary-01" > - <div class="card-body text-md-left"> - - <h2 class="mb-4 lh-1 text-uppercase" style="letter-spacing:2px">Polecamy </h2> - <div class="row align-items-start"> - <div class="col-12"> - - - - - - <div class="row"> - <div class="col-lg-2 mb-2 text-center"> - <img src="//niezbednik.niedziela.pl/images/ksiazki/ksiazka-credo.jpg" class="img-fluid"> - </div> - <div class="col-lg-10"> - <p class="pe-2 font-sans"><strong>Credo krok po kroku</strong> - <br><small><strong></strong></small> - - <br>Modlitwa "Wierzę w Boga" jest drogowskazem na drodze duchowego wzrastania. Dzięki książce "Credo" krok po kroku możemy to jeszcze pełniej zrozumieć. </p> - <p class=""> - - <a href="https://www.niedziela.pl/artykul/113896/Credo-Krok-po-kroku-%E2%80%93-ks-prof-Janusz-Lekan?utm_source=niezbednikKatolika&utm_medium=AdsArticleBtnDesktop&utm_campaign=AdsArticleBtnDesktop" class="btn btn-primary" data-clicksmap="liturgia-AdsArticleCredoBtn-Desktop">Zobacz</a> - - </p> - </div> - </div> - - - </div> - - </div> - </div> -</div> - <div class="row"> - <div class="col-6"> - <a class="btn btn-default d-block" href="/liturgia/2026-07-21" data-clicksmap="site:liturgia - liturgiaTopPrevDay - /liturgia/2026-07-21"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-left" viewBox="0 0 16 16"> - <path fill-rule="evenodd" d="M15 8a.5.5 0 0 0-.5-.5H2.707l3.147-3.146a.5.5 0 1 0-.708-.708l-4 4a.5.5 0 0 0 0 .708l4 4a.5.5 0 0 0 .708-.708L2.707 8.5H14.5A.5.5 0 0 0 15 8z"/> -</svg> Czytania na 21 lipca</a> - </div> - <div class="col-6"> - <a class="btn btn-default d-block me-0" href="/liturgia/2026-07-23" data-clicksmap="site:liturgia - liturgiaTopNextDay - /liturgia/2026-07-23">Czytania na 23 lipca <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-right" viewBox="0 0 16 16"> - <path fill-rule="evenodd" d="M1 8a.5.5 0 0 1 .5-.5h11.793l-3.147-3.146a.5.5 0 0 1 .708-.708l4 4a.5.5 0 0 1 0 .708l-4 4a.5.5 0 0 1-.708-.708L13.293 8.5H1.5A.5.5 0 0 1 1 8z"/> -</svg></a> - </div> - </div> - </article> - - -<div class="card border-0 px-lg-3 px-1 py-1 my-4 " id="rozwazania"> - <div class="card-body text-md-left"> - - <h2 class="mb-4 lh-1 text-uppercase" style="letter-spacing:2px">Rozważania na dziś </h2> - <div class="row align-items-start"> - <div class="col-12"> - - - - - - -<div class="swiper-container swiper-rozwazania swiper-with-scroll"> - <!-- Additional required wrapper --> - <div class="swiper-wrapper mb-2"> - <!-- Slides --> - - - - - - - - <div class="swiper-slide mb-2 swiper-slide-equal-height"> - <a href="/artykul/7646/Kilka-slow-o-Slowie-22-VII-2026" data-clicksmap="liturgia-PanelRozwazania:/artykul/7646/Kilka-slow-o-Slowie-22-VII-2026-Desktop"> - <div class="card h-100 shadow-sm"> - - - <div class="text-center"> - - - <div class="img-hover-zoom img-hover-zoom--colorize position-relative"> - <!--<div class="card-icon"> - <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-caret-right-fill" viewBox="0 0 16 16"> - <path d="m12.14 8.753-5.482 4.796c-.646.566-1.658.106-1.658-.753V3.204a1 1 0 0 1 1.659-.753l5.48 4.796a1 1 0 0 1 0 1.506z"/> -</svg> - </div>--> - <div class="card-icon1"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-youtube" viewBox="0 0 16 16"> - <path d="M8.051 1.999h.089c.822.003 4.987.033 6.11.335a2.01 2.01 0 0 1 1.415 1.42c.101.38.172.883.22 1.402l.01.104.022.26.008.104c.065.914.073 1.77.074 1.957v.075c-.001.194-.01 1.108-.082 2.06l-.008.105-.009.104c-.05.572-.124 1.14-.235 1.558a2.007 2.007 0 0 1-1.415 1.42c-1.16.312-5.569.334-6.18.335h-.142c-.309 0-1.587-.006-2.927-.052l-.17-.006-.087-.004-.171-.007-.171-.007c-1.11-.049-2.167-.128-2.654-.26a2.007 2.007 0 0 1-1.415-1.419c-.111-.417-.185-.986-.235-1.558L.09 9.82l-.008-.104A31.4 31.4 0 0 1 0 7.68v-.123c.002-.215.01-.958.064-1.778l.007-.103.003-.052.008-.104.022-.26.01-.104c.048-.519.119-1.023.22-1.402a2.007 2.007 0 0 1 1.415-1.42c.487-.13 1.544-.21 2.654-.26l.17-.007.172-.006.086-.003.171-.007A99.788 99.788 0 0 1 7.858 2h.193zM6.4 5.209v4.818l4.157-2.408L6.4 5.209z"/> -</svg> - - </div> - <img class="shadow" src="https://niezbednik.niedziela.pl/images/legan.jpg" - alt=""> - </div> - - </div> - - <div class="card-body"> - <div class="clearfix mb-3"> - - - - - </div> - - - <div class="my-2 text-center"> - - <h3 class="lh-sm"> - O. Michał Legan OSPPE - <br><small><i>Kilka słów o Słowie</i></small> - </h3> - - </div> - <div class="mb-3"> - - <p class="text-uppercase text-center role"></p> - - </div> - - - </div> - </a> - </div> - - <!--<div class="card"> - <a class="panel-link" href="/artykul/7646/Kilka-slow-o-Slowie-22-VII-2026" data-clicksmap="site:liturgia - PanelRozwazanie - /artykul/7646/Kilka-slow-o-Slowie-22-VII-2026">O. Michał Legan OSPPE <i class="fa fa-arrow-circle-right"></i></a> - </div>--> - </div> - - - - - <div class="swiper-slide mb-2 swiper-slide-equal-height"> - <a href="/artykul/1442/O-co-prosze-O-gleboka-tesknote-serca-za" data-clicksmap="liturgia-PanelRozwazania:/artykul/1442/O-co-prosze-O-gleboka-tesknote-serca-za-Desktop"> - <div class="card h-100 shadow-sm"> - - - <div class="text-center"> - - - <div class="img-hover-zoom img-hover-zoom--colorize position-relative"> - <img class="shadow" src="https://niezbednik.niedziela.pl/images/wons.jpg" - alt=""> - </div> - - </div> - - <div class="card-body"> - <div class="clearfix mb-3"> - - - - - </div> - - - <div class="my-2 text-center"> - - <h3 class="lh-sm"> - Krzysztof Wons SDS/Salwator - <br><small><i>O co proszę?</i></small> </h3> - - </div> - <div class="mb-3"> - - <p class="text-uppercase text-center role"></p> - - </div> - - - </div> - </a> - </div> - - <!--<div class="card"> - <a class="panel-link" href="/artykul/1442/O-co-prosze-O-gleboka-tesknote-serca-za" data-clicksmap="site:liturgia - PanelRozwazanie - /artykul/1442/O-co-prosze-O-gleboka-tesknote-serca-za">Krzysztof Wons SDS/Salwator <i class="fa fa-arrow-circle-right"></i></a> - </div>--> - </div> - - - - - <div class="swiper-slide mb-2 swiper-slide-equal-height"> - <a href="/artykul/7644/Damy-z-Bogiem-rade-22-VII-2026" data-clicksmap="liturgia-PanelRozwazania:/artykul/7644/Damy-z-Bogiem-rade-22-VII-2026-Desktop"> - <div class="card h-100 shadow-sm"> - - - <div class="text-center"> - - - <div class="img-hover-zoom img-hover-zoom--colorize position-relative"> - <!--<div class="card-icon"> - <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-caret-right-fill" viewBox="0 0 16 16"> - <path d="m12.14 8.753-5.482 4.796c-.646.566-1.658.106-1.658-.753V3.204a1 1 0 0 1 1.659-.753l5.48 4.796a1 1 0 0 1 0 1.506z"/> -</svg> - </div>--> - <div class="card-icon1"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-youtube" viewBox="0 0 16 16"> - <path d="M8.051 1.999h.089c.822.003 4.987.033 6.11.335a2.01 2.01 0 0 1 1.415 1.42c.101.38.172.883.22 1.402l.01.104.022.26.008.104c.065.914.073 1.77.074 1.957v.075c-.001.194-.01 1.108-.082 2.06l-.008.105-.009.104c-.05.572-.124 1.14-.235 1.558a2.007 2.007 0 0 1-1.415 1.42c-1.16.312-5.569.334-6.18.335h-.142c-.309 0-1.587-.006-2.927-.052l-.17-.006-.087-.004-.171-.007-.171-.007c-1.11-.049-2.167-.128-2.654-.26a2.007 2.007 0 0 1-1.415-1.419c-.111-.417-.185-.986-.235-1.558L.09 9.82l-.008-.104A31.4 31.4 0 0 1 0 7.68v-.123c.002-.215.01-.958.064-1.778l.007-.103.003-.052.008-.104.022-.26.01-.104c.048-.519.119-1.023.22-1.402a2.007 2.007 0 0 1 1.415-1.42c.487-.13 1.544-.21 2.654-.26l.17-.007.172-.006.086-.003.171-.007A99.788 99.788 0 0 1 7.858 2h.193zM6.4 5.209v4.818l4.157-2.408L6.4 5.209z"/> -</svg> - - </div> - <img class="shadow" src="https://niezbednik.niedziela.pl/images/wegrzyniak.jpg" - alt=""> - </div> - - </div> - - <div class="card-body"> - <div class="clearfix mb-3"> - - - - - </div> - - - <div class="my-2 text-center"> - - <h3 class="lh-sm"> - Ks. Wojciech Węgrzyniak - <br><small><i>Damy z Bogiem radę</i></small> - </h3> - - </div> - <div class="mb-3"> - - <p class="text-uppercase text-center role"></p> - - </div> - - - </div> - </a> - </div> - - <!--<div class="card"> - <a class="panel-link" href="/artykul/7644/Damy-z-Bogiem-rade-22-VII-2026" data-clicksmap="site:liturgia - PanelRozwazanie - /artykul/7644/Damy-z-Bogiem-rade-22-VII-2026">Ks. Wojciech Węgrzyniak <i class="fa fa-arrow-circle-right"></i></a> - </div>--> - </div> - - - - - <div class="swiper-slide mb-2 swiper-slide-equal-height"> - <a href="/artykul/7643/Gospel-dla-zabieganych-22-VII-2026" data-clicksmap="liturgia-PanelRozwazania:/artykul/7643/Gospel-dla-zabieganych-22-VII-2026-Desktop"> - <div class="card h-100 shadow-sm"> - - - <div class="text-center"> - - - <div class="img-hover-zoom img-hover-zoom--colorize position-relative"> - <!--<div class="card-icon"> - <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-caret-right-fill" viewBox="0 0 16 16"> - <path d="m12.14 8.753-5.482 4.796c-.646.566-1.658.106-1.658-.753V3.204a1 1 0 0 1 1.659-.753l5.48 4.796a1 1 0 0 1 0 1.506z"/> -</svg> - </div>--> - <div class="card-icon1"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-youtube" viewBox="0 0 16 16"> - <path d="M8.051 1.999h.089c.822.003 4.987.033 6.11.335a2.01 2.01 0 0 1 1.415 1.42c.101.38.172.883.22 1.402l.01.104.022.26.008.104c.065.914.073 1.77.074 1.957v.075c-.001.194-.01 1.108-.082 2.06l-.008.105-.009.104c-.05.572-.124 1.14-.235 1.558a2.007 2.007 0 0 1-1.415 1.42c-1.16.312-5.569.334-6.18.335h-.142c-.309 0-1.587-.006-2.927-.052l-.17-.006-.087-.004-.171-.007-.171-.007c-1.11-.049-2.167-.128-2.654-.26a2.007 2.007 0 0 1-1.415-1.419c-.111-.417-.185-.986-.235-1.558L.09 9.82l-.008-.104A31.4 31.4 0 0 1 0 7.68v-.123c.002-.215.01-.958.064-1.778l.007-.103.003-.052.008-.104.022-.26.01-.104c.048-.519.119-1.023.22-1.402a2.007 2.007 0 0 1 1.415-1.42c.487-.13 1.544-.21 2.654-.26l.17-.007.172-.006.086-.003.171-.007A99.788 99.788 0 0 1 7.858 2h.193zM6.4 5.209v4.818l4.157-2.408L6.4 5.209z"/> -</svg> - - </div> - <img class="shadow" src="https://niezbednik.niedziela.pl/images/gospel-dla-zabieganych.jpg" - alt=""> - </div> - - </div> - - <div class="card-body"> - <div class="clearfix mb-3"> - - - - - </div> - - - <div class="my-2 text-center"> - - <h3 class="lh-sm"> - Ks. Paweł Wróbel - <br><small><i>Gospel dla zabieganych</i></small> - </h3> - - </div> - <div class="mb-3"> - - <p class="text-uppercase text-center role"></p> - - </div> - - - </div> - </a> - </div> - - <!--<div class="card"> - <a class="panel-link" href="/artykul/7643/Gospel-dla-zabieganych-22-VII-2026" data-clicksmap="site:liturgia - PanelRozwazanie - /artykul/7643/Gospel-dla-zabieganych-22-VII-2026">Ks. Paweł Wróbel <i class="fa fa-arrow-circle-right"></i></a> - </div>--> - </div> - - - - - <div class="swiper-slide mb-2 swiper-slide-equal-height"> - <a href="https://www.niedziela.pl/artykul/126009" data-clicksmap="liturgia-PanelRozwazania:https://www.niedziela.pl/artykul/126009-Desktop"> - <div class="card h-100 shadow-sm"> - - - <div class="text-center"> - - - <div class="img-hover-zoom img-hover-zoom--colorize position-relative"> - <img class="shadow" src="https://niezbednik.niedziela.pl/images/wydpomoc.jpg" - alt=""> - </div> - - </div> - - <div class="card-body"> - <div class="clearfix mb-3"> - - - - - </div> - - - <div class="my-2 text-center"> - - <h3 class="lh-sm"> - Wydawnictwo „Pomoc”<br><small><i>Żyć Ewangelią</i></small> </h3> - - </div> - <div class="mb-3"> - - <p class="text-uppercase text-center role"></p> - - </div> - - - </div> - </a> - </div> - - <!--<div class="card"> - <a class="panel-link" href="https://www.niedziela.pl/artykul/126009" data-clicksmap="site:liturgia - PanelRozwazanie - https://www.niedziela.pl/artykul/126009">"Żyć Ewangelią" (wyd. Pomoc) <i class="fa fa-arrow-circle-right"></i></a> - </div>--> - </div> - - - - - <div class="swiper-slide mb-2 swiper-slide-equal-height"> - <a href="/artykul/7645/DrogaDoJezusacom-22-VII-2026" data-clicksmap="liturgia-PanelRozwazania:/artykul/7645/DrogaDoJezusacom-22-VII-2026-Desktop"> - <div class="card h-100 shadow-sm"> - - - <div class="text-center"> - - - <div class="img-hover-zoom img-hover-zoom--colorize position-relative"> - <!--<div class="card-icon"> - <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-caret-right-fill" viewBox="0 0 16 16"> - <path d="m12.14 8.753-5.482 4.796c-.646.566-1.658.106-1.658-.753V3.204a1 1 0 0 1 1.659-.753l5.48 4.796a1 1 0 0 1 0 1.506z"/> -</svg> - </div>--> - <div class="card-icon1"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-youtube" viewBox="0 0 16 16"> - <path d="M8.051 1.999h.089c.822.003 4.987.033 6.11.335a2.01 2.01 0 0 1 1.415 1.42c.101.38.172.883.22 1.402l.01.104.022.26.008.104c.065.914.073 1.77.074 1.957v.075c-.001.194-.01 1.108-.082 2.06l-.008.105-.009.104c-.05.572-.124 1.14-.235 1.558a2.007 2.007 0 0 1-1.415 1.42c-1.16.312-5.569.334-6.18.335h-.142c-.309 0-1.587-.006-2.927-.052l-.17-.006-.087-.004-.171-.007-.171-.007c-1.11-.049-2.167-.128-2.654-.26a2.007 2.007 0 0 1-1.415-1.419c-.111-.417-.185-.986-.235-1.558L.09 9.82l-.008-.104A31.4 31.4 0 0 1 0 7.68v-.123c.002-.215.01-.958.064-1.778l.007-.103.003-.052.008-.104.022-.26.01-.104c.048-.519.119-1.023.22-1.402a2.007 2.007 0 0 1 1.415-1.42c.487-.13 1.544-.21 2.654-.26l.17-.007.172-.006.086-.003.171-.007A99.788 99.788 0 0 1 7.858 2h.193zM6.4 5.209v4.818l4.157-2.408L6.4 5.209z"/> -</svg> - - </div> - <img class="shadow" src="https://niezbednik.niedziela.pl/images/drogadojezusa.jpg" - alt=""> - </div> - - </div> - - <div class="card-body"> - <div class="clearfix mb-3"> - - - - - </div> - - - <div class="my-2 text-center"> - - <h3 class="lh-sm"> - DrogaDoJezusa.com <br><small>(dla dzieci i rodziców)</small> </h3> - - </div> - <div class="mb-3"> - - <p class="text-uppercase text-center role"></p> - - </div> - - - </div> - </a> - </div> - - <!--<div class="card"> - <a class="panel-link" href="/artykul/7645/DrogaDoJezusacom-22-VII-2026" data-clicksmap="site:liturgia - PanelRozwazanie - /artykul/7645/DrogaDoJezusacom-22-VII-2026">DrogaDoJezusa.com <i class="fa fa-arrow-circle-right"></i></a> - </div>--> - </div> - - - - - <div class="swiper-slide mb-2 swiper-slide-equal-height"> - <a href="https://www.niedziela.pl/artykul/126051" data-clicksmap="liturgia-PanelRozwazania:https://www.niedziela.pl/artykul/126051-Desktop"> - <div class="card h-100 shadow-sm"> - - - <div class="text-center"> - - - <div class="img-hover-zoom img-hover-zoom--colorize position-relative"> - <img class="shadow" src="https://niezbednik.niedziela.pl/images/mlotek.jpg" - alt=""> - </div> - - </div> - - <div class="card-body"> - <div class="clearfix mb-3"> - - - - - </div> - - - <div class="my-2 text-center"> - - <h3 class="lh-sm"> - Ks. Krzysztof Młotek - <br><small><i>Glossa marginalia</i></small> - </h3> - - </div> - <div class="mb-3"> - - <p class="text-uppercase text-center role"></p> - - </div> - - - </div> - </a> - </div> - - <!--<div class="card"> - <a class="panel-link" href="https://www.niedziela.pl/artykul/126051" data-clicksmap="site:liturgia - PanelRozwazanie - https://www.niedziela.pl/artykul/126051">Ks. Krzysztof Młotek <i class="fa fa-arrow-circle-right"></i></a> - </div>--> - </div> - - - -</div> - - - <!-- If we need scrollbar --> - <div class=" swiper-scrollbar-all swiper-rozwazania-scrollbar"></div> - <!-- If we need navigation buttons --> - <div class="swiper-button-nav d-none d-md-block"> - <div class="btn btn-default swiper-rozwazania-button-prev "><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-left" viewBox="0 0 16 16"> - <path fill-rule="evenodd" d="M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z"/> -</svg></div> - <div class="btn btn-default swiper-rozwazania-button-next "><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-right" viewBox="0 0 16 16"> - <path fill-rule="evenodd" d="M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z"/> -</svg></div> - </div> - </div> - - - - - - </div> - - </div> - </div> -</div> -<div class="card border-0 px-lg-3 px-1 py-1 my-4 " id="dzien"> - <div class="card-body text-md-left"> - - <h2 class="mb-4 lh-1 text-uppercase" style="letter-spacing:2px">22 lipca, środa </h2> - <div class="row align-items-start"> - <div class="col-md-9"> - - - -<div class="row"> - <div class="col-12 col-lg-5"> - <p class="lh-sm background-zwykly px-2 py-1 mb-0 text-center badge fw-normal fs-6">XVI Tydzień zwykły</p> - <p class="font-serif mb-2 lh-sm fs-4 fw-bold color-swieto"><em>Święto św. Marii Magdaleny</em></p> - - <p class="lh-sm"> - Rok A, II <br>Kolor szat: <strong>biały</strong> <br><a href="/liturgia/2026-07-22" class="fw-bold" data-clicksmap="index-PanelDayLiturgiaLink-Mobile">Liturgia dnia <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-right " viewBox="0 0 16 16">
- <path fill-rule="evenodd" d="M1 8a.5.5 0 0 1 .5-.5h11.793l-3.147-3.146a.5.5 0 0 1 .708-.708l4 4a.5.5 0 0 1 0 .708l-4 4a.5.5 0 0 1-.708-.708L13.293 8.5H1.5A.5.5 0 0 1 1 8z"/>
- </svg></a> - </p> - <p class="lh-sm"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-calendar3" viewBox="0 0 16 16"> - <path d="M14 0H2a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2zM1 3.857C1 3.384 1.448 3 2 3h12c.552 0 1 .384 1 .857v10.286c0 .473-.448.857-1 .857H2c-.552 0-1-.384-1-.857V3.857z"/> - <path d="M6.5 7a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm3 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm3 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm-9 3a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm3 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm3 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm3 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm-9 3a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm3 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm3 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/> -</svg> 203. dzień roku - - <br><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-sunrise fs-3" style="vertical-align: -.25em" viewBox="0 0 16 16"> - <path d="M7.646 1.146a.5.5 0 0 1 .708 0l1.5 1.5a.5.5 0 0 1-.708.708L8.5 2.707V4.5a.5.5 0 0 1-1 0V2.707l-.646.647a.5.5 0 1 1-.708-.708l1.5-1.5zM2.343 4.343a.5.5 0 0 1 .707 0l1.414 1.414a.5.5 0 0 1-.707.707L2.343 5.05a.5.5 0 0 1 0-.707zm11.314 0a.5.5 0 0 1 0 .707l-1.414 1.414a.5.5 0 1 1-.707-.707l1.414-1.414a.5.5 0 0 1 .707 0zM8 7a3 3 0 0 1 2.599 4.5H5.4A3 3 0 0 1 8 7zm3.71 4.5a4 4 0 1 0-7.418 0H.499a.5.5 0 0 0 0 1h15a.5.5 0 0 0 0-1h-3.79zM0 10a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2A.5.5 0 0 1 0 10zm13 0a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1-.5-.5z"/> -</svg> 04:40 - 20:44 <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-sunset fs-3" style="vertical-align: -.25em" viewBox="0 0 16 16"> - <path d="M7.646 4.854a.5.5 0 0 0 .708 0l1.5-1.5a.5.5 0 0 0-.708-.708l-.646.647V1.5a.5.5 0 0 0-1 0v1.793l-.646-.647a.5.5 0 1 0-.708.708l1.5 1.5zm-5.303-.51a.5.5 0 0 1 .707 0l1.414 1.413a.5.5 0 0 1-.707.707L2.343 5.05a.5.5 0 0 1 0-.707zm11.314 0a.5.5 0 0 1 0 .706l-1.414 1.414a.5.5 0 1 1-.707-.707l1.414-1.414a.5.5 0 0 1 .707 0zM8 7a3 3 0 0 1 2.599 4.5H5.4A3 3 0 0 1 8 7zm3.71 4.5a4 4 0 1 0-7.418 0H.499a.5.5 0 0 0 0 1h15a.5.5 0 0 0 0-1h-3.79zM0 10a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2A.5.5 0 0 1 0 10zm13 0a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1-.5-.5z"/> -</svg> - - </p> - <p class="lh-sm"> - <strong>Imieniny:</strong> <em>Marii, Magdaleny, Laurentego</em> - </p> - </div> - <div class="col-12 col-lg-7"> - <h4 class="text-uppercase mb-1 "><span class="background-primary badge fs-5 fw-normal color-white py-1 px-2">Ważne</span></h4> - <div class="mb-2"> <p class="lh-sm p-0 m-0 pb-1"><a href="https://niezbednik.niedziela.pl/artykul/283/Litania-do-Najdrozszej-Krwi-Pana-Jezusa?utm_source=niezbednikKatolika&utm_medium=PanelPamietajMobile&utm_campaign=PanelPamietajMobile" data-clicksmap="site:index - PanelPamietaj - czerwcowe"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-youtube" viewBox="0 0 16 16"> - <path d="M8.051 1.999h.089c.822.003 4.987.033 6.11.335a2.01 2.01 0 0 1 1.415 1.42c.101.38.172.883.22 1.402l.01.104.022.26.008.104c.065.914.073 1.77.074 1.957v.075c-.001.194-.01 1.108-.082 2.06l-.008.105-.009.104c-.05.572-.124 1.14-.235 1.558a2.007 2.007 0 0 1-1.415 1.42c-1.16.312-5.569.334-6.18.335h-.142c-.309 0-1.587-.006-2.927-.052l-.17-.006-.087-.004-.171-.007-.171-.007c-1.11-.049-2.167-.128-2.654-.26a2.007 2.007 0 0 1-1.415-1.419c-.111-.417-.185-.986-.235-1.558L.09 9.82l-.008-.104A31.4 31.4 0 0 1 0 7.68v-.123c.002-.215.01-.958.064-1.778l.007-.103.003-.052.008-.104.022-.26.01-.104c.048-.519.119-1.023.22-1.402a2.007 2.007 0 0 1 1.415-1.42c.487-.13 1.544-.21 2.654-.26l.17-.007.172-.006.086-.003.171-.007A99.788 99.788 0 0 1 7.858 2h.193zM6.4 5.209v4.818l4.157-2.408L6.4 5.209z"/> -</svg> Litania do Najdroższej Krwi Pana Jezusa</a></p> <p class="lh-sm p-0 m-0 pb-1"><a href="/artykul/7536/Codzienna-modlitwa-lipiec-sierpien-2026" data-clicksmap="site:index - PanelPamietaj - /artykul/7536/Codzienna-modlitwa-lipiec-sierpien-2026"">Codzienna modlitwa (lipiec-sierpień 2026)</a></p> <p class="lh-sm p-0 m-0 pb-1"><a href="https://www.niedziela.pl/artykul/113997/Nowenna-do-sw-Krzysztofa?utm_source=niezbednikKatolika&utm_medium=PanelPamietajMobile&utm_campaign=PanelPamietajMobile" data-clicksmap="site:index - PanelPamietaj - niedziela.pl/artykul/113997/Nowenna-do-sw-Krzysztofa">Nowenna do św. Krzysztofa (7. dzień)</a></p> <p class="lh-sm p-0 m-0 pb-1"><a href="https://www.niedziela.pl/artykul/125162/Nowenna-do-sw-Marty-o-pomoc-w-sprawach-trudnych?utm_source=niezbednikKatolika&utm_medium=PanelPamietajMobile&utm_campaign=PanelPamietajMobile" data-clicksmap="site:index - PanelPamietaj - niedziela.pl/artykul/125162/Nowenna-do-sw-Marty-o-pomoc-w-sprawach-trudnych">Nowenna do św. Marty o pomoc w sprawach trudnych (3. dzień)</a></p> <p class="lh-sm p-0 m-0 pb-1"><a href="https://www.niedziela.pl/artykul/125060/Nowenna-do-sw-Ignacego-Loyoli?utm_source=niezbednikKatolika&utm_medium=PanelPamietajMobile&utm_campaign=PanelPamietajMobile" data-clicksmap="site:index - PanelPamietaj - niedziela.pl/artykul/125060/Nowenna-do-sw-Ignacego-Loyoli">Nowenna do św. Ignacego Loyoli (1. dzień)</a></p> <p class="lh-sm p-0 m-0 pb-1"><a href="https://www.niedziela.pl/artykul/91265/Nowenna-do-sw-Szarbela?utm_source=niezbednikKatolika&utm_medium=PanelPamietajMobile&utm_campaign=PanelPamietajMobile" data-clicksmap="site:index - PanelPamietaj - niedziela.pl/artykul/91265/Nowenna-do-sw-Szarbela">Nowenna do św. Szarbela (4. dzień)</a></p> <p class="lh-sm p-0 m-0 pb-1"><a href="https://www.niedziela.pl/artykul/77464/Modlitwa-sw-Jana-Pawla-II-o-pokoj?utm_source=niezbednikKatolika&utm_medium=PanelPamietajMobile&utm_campaign=PanelPamietajMobile" data-clicksmap="site:index - PanelPamietaj - https://www.niedziela.pl/artykul/77464/" target="_blank"><strong>Modlitwa św. Jana Pawła II o pokój</strong></a></p> <p class="lh-sm p-0 m-0 pb-1"><a href="https://www.niedziela.pl/artykul/121618/Modlitwa-do-Maryi-Krolowej-Pokoju?utm_source=niezbednikKatolika&utm_medium=PanelPamietajMobile&utm_campaign=PanelPamietajMobile" data-clicksmap="site:index - PanelPamietaj - https://www.niedziela.pl/artykul/121618/" target="_blank"><strong>Modlitwa do Maryi, Królowej Pokoju</strong></a></p> <p class="lh-sm p-0 m-0 pb-1"><a href="https://niezbednik.niedziela.pl/biblia" data-clicksmap="site:index - PanelPamietaj - Biblia" target="_blank"><strong>Biblia Tysiąclecia - pełny tekst</strong></a></p></div> - <h4 class="fs-5 text-uppercase mb-1"><span class="background-primary badge fs-5 fw-normal py-1 px-2">Warto przeczytać</span></h4> - <ul class="list-unstyled"><li><h3 class="pb-0 mb-0 lh-sm"><a class="" href="http://niedziela.pl/artykul/28929/?utm_source=niezbednikKatolika&utm_medium=PanelPamietajMobile&utm_campaign=PanelPamietajMobile" data-clicksmap="site:index - PanelPolecane - http://niedziela.pl/artykul/28929/"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-bookmark" viewBox="0 0 16 16"> - <path d="M2 2a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v13.5a.5.5 0 0 1-.777.416L8 13.101l-5.223 2.815A.5.5 0 0 1 2 15.5V2zm2-1a1 1 0 0 0-1 1v12.566l4.723-2.482a.5.5 0 0 1 .554 0L13 14.566V2a1 1 0 0 0-1-1H4z"/> - </svg> Maria Magdalena apostołką nadziei</a></h3></a></li><li><h3 class="pb-0 mb-0 lh-sm"><a class="" href="https://www.niedziela.pl/artykul/152947/nd/Maria-Magdalena-%E2%80%93-swiadek?utm_source=niezbednikKatolika&utm_medium=PanelPamietajMobile&utm_campaign=PanelPamietajMobile" data-clicksmap="site:index - PanelPolecane - https://www.niedziela.pl/artykul/152947/nd/Maria-Magdalena-%E2%80%93-swiadek"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-bookmark" viewBox="0 0 16 16"> - <path d="M2 2a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v13.5a.5.5 0 0 1-.777.416L8 13.101l-5.223 2.815A.5.5 0 0 1 2 15.5V2zm2-1a1 1 0 0 0-1 1v12.566l4.723-2.482a.5.5 0 0 1 .554 0L13 14.566V2a1 1 0 0 0-1-1H4z"/> - </svg> Maria Magdalena – świadek Zmartwychwstania</a></h3></a></li><li><h3 class="pb-0 mb-0 lh-sm"><a class="" href="https://www.niedziela.pl/artykul/154640/nd/Sladem-swietej-z-Magdali?utm_source=niezbednikKatolika&utm_medium=PanelPamietajMobile&utm_campaign=PanelPamietajMobile" data-clicksmap="site:index - PanelPolecane - https://www.niedziela.pl/artykul/154640/nd/Sladem-swietej-z-Magdali"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-bookmark" viewBox="0 0 16 16"> - <path d="M2 2a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v13.5a.5.5 0 0 1-.777.416L8 13.101l-5.223 2.815A.5.5 0 0 1 2 15.5V2zm2-1a1 1 0 0 0-1 1v12.566l4.723-2.482a.5.5 0 0 1 .554 0L13 14.566V2a1 1 0 0 0-1-1H4z"/> - </svg> Śladem świętej z Magdali</a></h3></a></li><li><h3 class="pb-0 mb-0 lh-sm"><a class="" href="https://niezbednik.niedziela.pl/audio/kod" data-clicksmap="site:index - PanelPolecane - Codzienna modlitwa - wersja AUDIO"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-bookmark" viewBox="0 0 16 16"> - <path d="M2 2a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v13.5a.5.5 0 0 1-.777.416L8 13.101l-5.223 2.815A.5.5 0 0 1 2 15.5V2zm2-1a1 1 0 0 0-1 1v12.566l4.723-2.482a.5.5 0 0 1 .554 0L13 14.566V2a1 1 0 0 0-1-1H4z"/> - </svg> Codzienna modlitwa - wersja AUDIO</a></h3></a></li></ul> <h4 class="fs-5 text-uppercase mb-1"><span class="background-primary badge fs-5 fw-normal py-1 px-2">Wydarzyło się...</span></h4> - <ul class="list-unstyled"><li>• Paweł VI zawiesił działanie Bractwa Kapłańskiego Świętego Piusa X, a jego założyciela <a href="http://www.niedziela.pl/artykul/88161/nd/Sprawa-schizmy-lefebrystow" data-clicksmap="site:index - PanelWydarzenia - http://www.niedziela.pl/artykul/88161/nd/Sprawa-schizmy-lefebrystow"><strong>Marcela Lefebvre’a</strong> <i class="fa fa-external-link"></i></a> ukarał suspensą (1976 r.)</li></ul> </div> - <div class="col-12"> - <a class="btn btn-primary ms-0" href="/dzien/2026-07-21" data-clicksmap="index-PanelDayBtnPrev-Mobile"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-left" viewBox="0 0 16 16"> - <path fill-rule="evenodd" d="M15 8a.5.5 0 0 0-.5-.5H2.707l3.147-3.146a.5.5 0 1 0-.708-.708l-4 4a.5.5 0 0 0 0 .708l4 4a.5.5 0 0 0 .708-.708L2.707 8.5H14.5A.5.5 0 0 0 15 8z"/> -</svg> Wczoraj</a> - <a class="btn btn-primary pull-right me-0" href="/dzien/2026-07-23" data-clicksmap="index-PanelDayBtnNext-Mobile">Jutro <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-right" viewBox="0 0 16 16"> - <path fill-rule="evenodd" d="M1 8a.5.5 0 0 1 .5-.5h11.793l-3.147-3.146a.5.5 0 0 1 .708-.708l4 4a.5.5 0 0 1 0 .708l-4 4a.5.5 0 0 1-.708-.708L13.293 8.5H1.5A.5.5 0 0 1 1 8z"/> -</svg></a> - </div> - -</div> - - </div> - <div class="col-12 col-md-3 mt-4 mt-md-0"> - <img src="https://niezbednik.niedziela.pl/images/dzien2.png" alt="" class="img-fluid w-75 mx-auto d-block"> - </div> - - </div> - </div> -</div> - - - - - - - - -<div class="card border-0 px-lg-3 px-1 py-1 my-4 " > - <div class="card-body text-md-left"> - <div class="row align-items-start"> - <div class="col-12"> - - - <h2 id="panelCalendarTitle"></h2>
- <div class="swiper-container swiper-kalendarz swiper-with-scroll my-main">
- <!-- Additional required wrapper -->
- <ul class="swiper-wrapper mb-4 list-unstyled">
- <!-- Slides -->
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XV Tydzień zwykły">
-
-
- <a href="/dzien/2026-07-12" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide0-Desktop">
-
-
-<div class="panel-calendar niedziela h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">lipiec</p>
- <p class="panel-calendar-day px-4"><span>12</span></p>
- <p class="mb-2">
- niedziela
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Piętnasta Niedziela zwykła</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XV Tydzień zwykły">
-
-
- <a href="/dzien/2026-07-13" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide1-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">lipiec</p>
- <p class="panel-calendar-day px-4"><span>13</span></p>
- <p class="mb-2">
- poniedziałek
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Wspomnienie świętych pustelników Andrzeja Świerada i Benedykta</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XV Tydzień zwykły">
-
-
- <a href="/dzien/2026-07-14" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide2-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">lipiec</p>
- <p class="panel-calendar-day px-4"><span>14</span></p>
- <p class="mb-2">
- wtorek
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Dzień Powszedni albo wspomnienie św. Kamila de Lellis, prezbitera albo wspomnienie św. Henryka</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XV Tydzień zwykły">
-
-
- <a href="/dzien/2026-07-15" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide3-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">lipiec</p>
- <p class="panel-calendar-day px-4"><span>15</span></p>
- <p class="mb-2">
- środa
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Wspomnienie św. Bonawentury, biskupa i doktora Kościoła</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XV Tydzień zwykły">
-
-
- <a href="/dzien/2026-07-16" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide4-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">lipiec</p>
- <p class="panel-calendar-day px-4"><span>16</span></p>
- <p class="mb-2">
- czwartek
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Wspomnienie Najświętszej Maryi Panny z Góry Karmel</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XV Tydzień zwykły">
-
-
- <a href="/dzien/2026-07-17" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide5-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">lipiec</p>
- <p class="panel-calendar-day px-4"><span>17</span></p>
- <p class="mb-2">
- piątek
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Dzień Powszedni</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XV Tydzień zwykły">
-
-
- <a href="/dzien/2026-07-18" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide6-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">lipiec</p>
- <p class="panel-calendar-day px-4"><span>18</span></p>
- <p class="mb-2">
- sobota
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Dzień Powszedni albo wspomnienie Najświętszej Maryi Panny w sobotę albo wspomnienie św. Szymona z Lipnicy, prezbitera</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XVI Tydzień zwykły">
-
-
- <a href="/dzien/2026-07-19" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide7-Desktop">
-
-
-<div class="panel-calendar niedziela h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">lipiec</p>
- <p class="panel-calendar-day px-4"><span>19</span></p>
- <p class="mb-2">
- niedziela
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Szesnasta Niedziela zwykła</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XVI Tydzień zwykły">
-
-
- <a href="/dzien/2026-07-20" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide8-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">lipiec</p>
- <p class="panel-calendar-day px-4"><span>20</span></p>
- <p class="mb-2">
- poniedziałek
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Dzień Powszedni albo wspomnienie bł. Czesława, prezbitera</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XVI Tydzień zwykły">
-
-
- <a href="/dzien/2026-07-21" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide9-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">lipiec</p>
- <p class="panel-calendar-day px-4"><span>21</span></p>
- <p class="mb-2">
- wtorek
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Dzień Powszedni albo wspomnienie św. Wawrzyńca z Brindisi, prezbitera i doktora Kościoła albo wspomnienie św. Apolinarego, biskupa i męczennika</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XVI Tydzień zwykły">
-
-
- <a href="/dzien/2026-07-22" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide10-Desktop">
-
-
-<div class="panel-calendar swieto h-100 today">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">lipiec</p>
- <p class="panel-calendar-day px-4"><span>22</span></p>
- <p class="mb-2">
- <span class="fw-bold">DZISIAJ</span>
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Święto św. Marii Magdaleny</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XVI Tydzień zwykły">
-
-
- <a href="/dzien/2026-07-23" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide11-Desktop">
-
-
-<div class="panel-calendar swieto h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">lipiec</p>
- <p class="panel-calendar-day px-4"><span>23</span></p>
- <p class="mb-2">
- czwartek
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Święto św. Brygidy, zakonnicy, Patronki Europy</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XVI Tydzień zwykły">
-
-
- <a href="/dzien/2026-07-24" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide12-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">lipiec</p>
- <p class="panel-calendar-day px-4"><span>24</span></p>
- <p class="mb-2">
- piątek
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Wspomnienie św. Kingi, dziewicy</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XVI Tydzień zwykły">
-
-
- <a href="/dzien/2026-07-25" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide13-Desktop">
-
-
-<div class="panel-calendar swieto h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">lipiec</p>
- <p class="panel-calendar-day px-4"><span>25</span></p>
- <p class="mb-2">
- sobota
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Święto św. Jakuba, apostoła</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XVII Tydzień zwykły">
-
-
- <a href="/dzien/2026-07-26" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide14-Desktop">
-
-
-<div class="panel-calendar niedziela h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">lipiec</p>
- <p class="panel-calendar-day px-4"><span>26</span></p>
- <p class="mb-2">
- niedziela
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Siedemnasta Niedziela zwykła</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XVII Tydzień zwykły">
-
-
- <a href="/dzien/2026-07-27" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide15-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">lipiec</p>
- <p class="panel-calendar-day px-4"><span>27</span></p>
- <p class="mb-2">
- poniedziałek
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Dzień Powszedni</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XVII Tydzień zwykły">
-
-
- <a href="/dzien/2026-07-28" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide16-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">lipiec</p>
- <p class="panel-calendar-day px-4"><span>28</span></p>
- <p class="mb-2">
- wtorek
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Dzień Powszedni albo wspomnienie św. Sarbeliusza Makhluf, prezbitera</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XVII Tydzień zwykły">
-
-
- <a href="/dzien/2026-07-29" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide17-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">lipiec</p>
- <p class="panel-calendar-day px-4"><span>29</span></p>
- <p class="mb-2">
- środa
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Wspomnienie św. Marty, Marii i Łazarza</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XVII Tydzień zwykły">
-
-
- <a href="/dzien/2026-07-30" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide18-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">lipiec</p>
- <p class="panel-calendar-day px-4"><span>30</span></p>
- <p class="mb-2">
- czwartek
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Dzień Powszedni albo wspomnienie św. Piotra Chryzologa, -biskupa i doktora Kościoła</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XVII Tydzień zwykły">
-
-
- <a href="/dzien/2026-07-31" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide19-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">lipiec</p>
- <p class="panel-calendar-day px-4"><span>31</span></p>
- <p class="mb-2">
- piątek
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Wspomnienie św. Ignacego z Loyoli, prezbitera</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XVII Tydzień zwykły">
-
-
- <a href="/dzien/2026-08-01" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide20-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">sierpień</p>
- <p class="panel-calendar-day px-4"><span>1</span></p>
- <p class="mb-2">
- <span class="fw-bold font-sans">pierwsza sobota</span>
-
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Wspomnienie św. Alfonsa Marii Liguoriego, -biskupa i doktora Kościoła</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XVIII Tydzień zwykły">
-
-
- <a href="/dzien/2026-08-02" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide21-Desktop">
-
-
-<div class="panel-calendar niedziela h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">sierpień</p>
- <p class="panel-calendar-day px-4"><span>2</span></p>
- <p class="mb-2">
- niedziela
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Osiemnasta Niedziela zwykła</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XVIII Tydzień zwykły">
-
-
- <a href="/dzien/2026-08-03" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide22-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">sierpień</p>
- <p class="panel-calendar-day px-4"><span>3</span></p>
- <p class="mb-2">
- poniedziałek
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Dzień Powszedni</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XVIII Tydzień zwykły">
-
-
- <a href="/dzien/2026-08-04" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide23-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">sierpień</p>
- <p class="panel-calendar-day px-4"><span>4</span></p>
- <p class="mb-2">
- wtorek
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Wspomnienie św. Jana Marii Vianneya, prezbitera</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XVIII Tydzień zwykły">
-
-
- <a href="/dzien/2026-08-05" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide24-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">sierpień</p>
- <p class="panel-calendar-day px-4"><span>5</span></p>
- <p class="mb-2">
- środa
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Dzień Powszedni albo wspomnienie rocznicy poświęcenia rzymskiej Bazyliki - Najświętszej Maryi Panny</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XVIII Tydzień zwykły">
-
-
- <a href="/dzien/2026-08-06" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide25-Desktop">
-
-
-<div class="panel-calendar swieto h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">sierpień</p>
- <p class="panel-calendar-day px-4"><span>6</span></p>
- <p class="mb-2">
- <span class="fw-bold font-sans">pierwszy czwartek</span>
-
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Święto Przemienienia Pańskiego</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XVIII Tydzień zwykły">
-
-
- <a href="/dzien/2026-08-07" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide26-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">sierpień</p>
- <p class="panel-calendar-day px-4"><span>7</span></p>
- <p class="mb-2">
- <span class="fw-bold font-sans">pierwszy piątek</span>
-
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Dzień Powszedni albo wspomnienie świętych męczenników -Sykstusa II, papieża, i Towarzyszy albo wspomnienie św. Kajetana, prezbitera</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XVIII Tydzień zwykły">
-
-
- <a href="/dzien/2026-08-08" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide27-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">sierpień</p>
- <p class="panel-calendar-day px-4"><span>8</span></p>
- <p class="mb-2">
- sobota
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Wspomnienie św. Dominika, prezbitera</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XIX Tydzień zwykły">
-
-
- <a href="/dzien/2026-08-09" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide28-Desktop">
-
-
-<div class="panel-calendar niedziela h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">sierpień</p>
- <p class="panel-calendar-day px-4"><span>9</span></p>
- <p class="mb-2">
- niedziela
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Dziewiętnasta Niedziela zwykła</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XIX Tydzień zwykły">
-
-
- <a href="/dzien/2026-08-10" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide29-Desktop">
-
-
-<div class="panel-calendar swieto h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">sierpień</p>
- <p class="panel-calendar-day px-4"><span>10</span></p>
- <p class="mb-2">
- poniedziałek
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Święto św. Wawrzyńca, diakona i męczennika</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XIX Tydzień zwykły">
-
-
- <a href="/dzien/2026-08-11" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide30-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">sierpień</p>
- <p class="panel-calendar-day px-4"><span>11</span></p>
- <p class="mb-2">
- wtorek
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Wspomnienie św. Klary, dziewicy</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XIX Tydzień zwykły">
-
-
- <a href="/dzien/2026-08-12" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide31-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">sierpień</p>
- <p class="panel-calendar-day px-4"><span>12</span></p>
- <p class="mb-2">
- środa
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Dzień Powszedni albo wspomnienie św. Joanny Franciszki de Chantal, -zakonnicy</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XIX Tydzień zwykły">
-
-
- <a href="/dzien/2026-08-13" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide32-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">sierpień</p>
- <p class="panel-calendar-day px-4"><span>13</span></p>
- <p class="mb-2">
- czwartek
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Dzień Powszedni albo wspomnienie świętych męczenników -Poncjana, papieża, i Hipolita, prezbitera</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XIX Tydzień zwykły">
-
-
- <a href="/dzien/2026-08-14" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide33-Desktop">
-
-
-<div class="panel-calendar powszedni h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">sierpień</p>
- <p class="panel-calendar-day px-4"><span>14</span></p>
- <p class="mb-2">
- piątek
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Wspomnienie św. Maksymiliana Marii Kolbego, prezbitera i męczennika</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
- <li class="swiper-slide mb-2 swiper-slide-equal-height" data-week="XIX Tydzień zwykły">
-
-
- <a href="/dzien/2026-08-15" class="panel-calendar-link" data-clicksmap="liturgia-PanelKalendarzSlide34-Desktop">
-
-
-<div class="panel-calendar niedziela h-100 ">
- <div class="panel-calendar-week background-zwykly " style="height: 1.5em;"></div>
- <div class="panel-calendar-content px-2 text-center">
- <p class="lh-1 text-uppercase pt-3 mb-0">sierpień</p>
- <p class="panel-calendar-day px-4"><span>15</span></p>
- <p class="mb-2">
- sobota
-
- </p>
- <p class="mb-3 fs-6 font-serif lh-sm ">
- <i>Uroczystość Wniebowzięcia Najświętszej Maryi Panny</i>
-
-
-</p>
- </div>
-</div>
-
-
- </a>
- </li>
-
-
-
-
- </ul>
-
- <!-- If we need scrollbar -->
-<div class=" swiper-scrollbar-all swiper-kalendarz-scrollbar"></div>
- <!-- If we need navigation buttons -->
- <div class="swiper-button-nav d-none d-md-block">
- <div class="btn btn-default swiper-kalendarz-button-prev "><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-left" viewBox="0 0 16 16">
- <path fill-rule="evenodd" d="M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z"/>
-</svg></div>
- <div class="btn btn-default swiper-kalendarz-button-next "><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-right" viewBox="0 0 16 16">
- <path fill-rule="evenodd" d="M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z"/>
-</svg></div>
- </div>
-
- </div>
- <p class="text-center">
- <a class="btn btn-primary ms-0" href="/site/liturgia#20260722" data-clicksmap="liturgia-PanelDayBtnCalendar-Desktop"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-calendar3" viewBox="0 0 16 16">
- <path d="M14 0H2a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2zM1 3.857C1 3.384 1.448 3 2 3h12c.552 0 1 .384 1 .857v10.286c0 .473-.448.857-1 .857H2c-.552 0-1-.384-1-.857V3.857z"/>
- <path d="M6.5 7a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm3 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm3 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm-9 3a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm3 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm3 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm3 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm-9 3a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm3 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm3 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/>
-</svg> Kalendarz na rok 2026</a>
- </p>
-
- - - </div> - - </div> - </div> -</div> -<div class="card border-0 px-lg-3 px-1 py-1 my-4 " > - <div class="card-body text-md-left"> - - <h2 class="mb-4 lh-1 text-uppercase" style="letter-spacing:2px">Z życia Kościoła </h2> - <div class="row align-items-start"> - <div class="col-12"> - - -
-
-
-
-<div class="swiper-container swiper-wiadomosci swiper-with-scroll">
- <!-- Additional required wrapper -->
- <div class="swiper-wrapper mb-2">
- <!-- Slides -->
-
-
-
- <div class="swiper-slide mb-2 swiper-slide-equal-height">
- <a href="//www.niedziela.pl/artykul/126205/" data-clicksmap="liturgia-PanWiad-0-126205-Desktop">
- <div class="card h-100 shadow-sm">
- <div class="text-center">
- <div class="img-hover-zoom img-hover-zoom--colorize">
- <img class="shadow" src="https://www.niedziela.pl/gifs/portaln/150x150/1754215986.jpg" alt="">
- </div>
- </div>
-
- <div class="card-body">
-
- <div class="my-2 text-center">
-
- <h3 class="lh-sm truncate-multiline-3">Kłodzko: 80 lat nieprzerwanej adoracji Najświętszego Sakramentu</h3>
-
- </div>
-
- </div>
- </div>
- </a>
- </div>
-
-
- <div class="swiper-slide mb-2 swiper-slide-equal-height">
- <a href="//www.niedziela.pl/artykul/126204/" data-clicksmap="liturgia-PanWiad-1-126204-Desktop">
- <div class="card h-100 shadow-sm">
- <div class="text-center">
- <div class="img-hover-zoom img-hover-zoom--colorize">
- <img class="shadow" src="https://www.niedziela.pl/gifs/portaln/150x150/1784746880.jpg" alt="">
- </div>
- </div>
-
- <div class="card-body">
-
- <div class="my-2 text-center">
-
- <h3 class="lh-sm truncate-multiline-3">Słowo metropolity gdańskiego nt. korzystania z posługi duszpasterzy Kościoła Polskokatolickiego</h3>
-
- </div>
-
- </div>
- </div>
- </a>
- </div>
-
-
- <div class="swiper-slide mb-2 swiper-slide-equal-height">
- <a href="//www.niedziela.pl/artykul/126202/" data-clicksmap="liturgia-PanWiad-2-126202-Desktop">
- <div class="card h-100 shadow-sm">
- <div class="text-center">
- <div class="img-hover-zoom img-hover-zoom--colorize">
- <img class="shadow" src="https://www.niedziela.pl/gifs/portaln/150x150/1784742198.jpg" alt="">
- </div>
- </div>
-
- <div class="card-body">
-
- <div class="my-2 text-center">
-
- <h3 class="lh-sm truncate-multiline-3">Leon XIV odwiedził Subiaco – duchowe serce benedyktynów</h3>
-
- </div>
-
- </div>
- </div>
- </a>
- </div>
-
-
- <div class="swiper-slide mb-2 swiper-slide-equal-height">
- <a href="//www.niedziela.pl/artykul/126199/" data-clicksmap="liturgia-PanWiad-3-126199-Desktop">
- <div class="card h-100 shadow-sm">
- <div class="text-center">
- <div class="img-hover-zoom img-hover-zoom--colorize">
- <img class="shadow" src="https://www.niedziela.pl/gifs/portaln/150x150/1780483663.jpg" alt="">
- </div>
- </div>
-
- <div class="card-body">
-
- <div class="my-2 text-center">
-
- <h3 class="lh-sm truncate-multiline-3">Watykan: nie ma jeszcze decyzji w sprawie ks. Marka Rupnika</h3>
-
- </div>
-
- </div>
- </div>
- </a>
- </div>
-
-
- <div class="swiper-slide mb-2 swiper-slide-equal-height">
- <a href="//www.niedziela.pl/artykul/126197/" data-clicksmap="liturgia-PanWiad-4-126197-Desktop">
- <div class="card h-100 shadow-sm">
- <div class="text-center">
- <div class="img-hover-zoom img-hover-zoom--colorize">
- <img class="shadow" src="https://www.niedziela.pl/gifs/portaln/150x150/1784733167.jpg" alt="">
- </div>
- </div>
-
- <div class="card-body">
-
- <div class="my-2 text-center">
-
- <h3 class="lh-sm truncate-multiline-3">Leon XIV: nie zostawiajmy ubogich i osób starszych samych</h3>
-
- </div>
-
- </div>
- </div>
- </a>
- </div>
-
-
- <div class="swiper-slide mb-2 swiper-slide-equal-height">
- <a href="//www.niedziela.pl/artykul/126196/" data-clicksmap="liturgia-PanWiad-5-126196-Desktop">
- <div class="card h-100 shadow-sm">
- <div class="text-center">
- <div class="img-hover-zoom img-hover-zoom--colorize">
- <img class="shadow" src="https://www.niedziela.pl/gifs/portaln/150x150/1784727420.jpg" alt="">
- </div>
- </div>
-
- <div class="card-body">
-
- <div class="my-2 text-center">
-
- <h3 class="lh-sm truncate-multiline-3">Leon XIV modlił się w sanktuarium Trójcy Świętej w Vallepietra</h3>
-
- </div>
-
- </div>
- </div>
- </a>
- </div>
-
-
- <div class="swiper-slide mb-2 swiper-slide-equal-height">
- <a href="//www.niedziela.pl/artykul/126193/" data-clicksmap="liturgia-PanWiad-6-126193-Desktop">
- <div class="card h-100 shadow-sm">
- <div class="text-center">
- <div class="img-hover-zoom img-hover-zoom--colorize">
- <img class="shadow" src="https://www.niedziela.pl/gifs/portaln/150x150/1784724981.jpg" alt="">
- </div>
- </div>
-
- <div class="card-body">
-
- <div class="my-2 text-center">
-
- <h3 class="lh-sm truncate-multiline-3">Oświadczenie KEP: przesłane przez nas propozycje dot. przedmiotu edukacja zdrowotna nie zostały uwzględnione</h3>
-
- </div>
-
- </div>
- </div>
- </a>
- </div>
-
-
- <div class="swiper-slide mb-2 swiper-slide-equal-height">
- <a href="//www.niedziela.pl/artykul/126191/" data-clicksmap="liturgia-PanWiad-7-126191-Desktop">
- <div class="card h-100 shadow-sm">
- <div class="text-center">
- <div class="img-hover-zoom img-hover-zoom--colorize">
- <img class="shadow" src="https://www.niedziela.pl/gifs/portaln/150x150/1723648348.jpg" alt="">
- </div>
- </div>
-
- <div class="card-body">
-
- <div class="my-2 text-center">
-
- <h3 class="lh-sm truncate-multiline-3">Chrześcijanie są pielgrzymami do celu. Są ciągle w drodze</h3>
-
- </div>
-
- </div>
- </div>
- </a>
- </div>
-
-
- <div class="swiper-slide mb-2 swiper-slide-equal-height">
- <a href="//www.niedziela.pl/artykul/126165/" data-clicksmap="liturgia-PanWiad-8-126165-Desktop">
- <div class="card h-100 shadow-sm">
- <div class="text-center">
- <div class="img-hover-zoom img-hover-zoom--colorize">
- <img class="shadow" src="https://www.niedziela.pl/gifs/portaln/150x150/1784631693.jpg" alt="">
- </div>
- </div>
-
- <div class="card-body">
-
- <div class="my-2 text-center">
-
- <h3 class="lh-sm truncate-multiline-3">Piła: "Jezus uratowany". Nauczyciele i uczniowie odnowili kompletnie zniszczoną figurę Chrystusa</h3>
-
- </div>
-
- </div>
- </div>
- </a>
- </div>
-
-
- <div class="swiper-slide mb-2 swiper-slide-equal-height">
- <a href="//www.niedziela.pl/artykul/126163/" data-clicksmap="liturgia-PanWiad-9-126163-Desktop">
- <div class="card h-100 shadow-sm">
- <div class="text-center">
- <div class="img-hover-zoom img-hover-zoom--colorize">
- <img class="shadow" src="https://www.niedziela.pl/gifs/portaln/150x150/1784628392.jpg" alt="">
- </div>
- </div>
-
- <div class="card-body">
-
- <div class="my-2 text-center">
-
- <h3 class="lh-sm truncate-multiline-3">"Soli Deo Gloria": Uczniowie oddają cześć Chrystusowi poprzez niesamowitą sztukę z nakrętek od butelek</h3>
-
- </div>
-
- </div>
- </div>
- </a>
- </div>
-
- </div>
-
-<!-- If we need scrollbar -->
-<div class=" swiper-scrollbar-all swiper-wiadomosci-scrollbar"></div>
- <!-- If we need navigation buttons -->
- <div class="swiper-button-nav d-none d-md-block">
- <div class="btn btn-default swiper-wiadomosci-button-prev "><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-left" viewBox="0 0 16 16">
- <path fill-rule="evenodd" d="M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z"/>
-</svg></div>
- <div class="btn btn-default swiper-wiadomosci-button-next "><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-right" viewBox="0 0 16 16">
- <path fill-rule="evenodd" d="M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z"/>
-</svg></div>
- </div>
-</div>
-
-
-
-
- - - </div> - - </div> - </div> -</div>
-</div>
-
-
-
- - - - - <div class="px-3"> - -<div class="card border-0 px-lg-4 px-1 py-1 h-100" style="background-color: rgba(29,76,176,.1);"> - <div class="card-body text-md-left"> - <div class="row"> - - <div class="col-12 col-xl-6"> - <h2 class="mb-3 lh-1 color-primary text-uppercase">W NOWYM NUMERZE <strong><i>BLIŻEJ ŻYCIA Z WIARĄ</i></strong></h2> - <div class="row"> - <div class="col-lg-4 mb-2 text-center"> - <img src="https://www.niedziela.pl/images/okladki/ewydanie_bz/202630.png" class="img-fluid"> - </div> - <div class="col-lg-8"> - <p class="pe-2"><strong>Pasja nie zna wieku</strong> - <br>Jeszcze kilkanaście lat temu nie podejrzewał, że drzemie w nim rzeźbiarz. Dziś jego figury zdobią domy rodziny i przyjaciół. </p> - <p> - - - <a href="https://blizejzycia.pl?utm_source=niezbednikKatolika&utm_medium=BlizejZyciaBottom0Btn0Desktop&utm_campaign=BlizejZyciaBottom0Btn0Desktop" class="btn btn-primary" data-clicksmap="liturgia-BlizejZyciaBottom0Btn0-Desktop">Zobacz</a> - - <a href="https://e.niedziela.pl/?utm_source=niezbednikKatolika&utm_medium=BlizejZyciaEwydanieBottom0Btn1Desktop&utm_campaign=BlizejZyciaEwydanieBottom0Btn1Desktop" class="btn btn-primary" data-clicksmap="liturgia-BlizejZyciaEwydanieBottom0Btn1-Desktop">Zamów e-wydanie</a> - - </p> - </div> - </div> - </div> - <div class="col-12 col-xl-6"> - <h2 class="mb-3 lh-1 color-primary text-uppercase">Księgarnia Niedziela</h2> - <div class="row"> - <div class="col-lg-4 mb-2 text-center"> - <img src="https://niezbednik.niedziela.pl/images/ksiazki/ksiazka-psychoterapia-ewangelia3.jpg" class="img-fluid"> - </div> - <div class="col-lg-8"> - <p class="pe-2"><strong>Psychoterapia Ewangelią 3. Reaktywacja</strong> - <br>Od dzieciństwa każdy z nas zostaje obarczony dawką traumatycznych przeżyć obniżających samoocenę, podmywających nadzieję na przyszłość. Z takim trudnym depozytem wchodzimy w młodość i dorosłość. Krzywdzące myśli o nas samych nieraz zapadają w nas tak głęboko, że są niedostępne naszej jaźni, gdzieś tam zostały wyparte i przysypane, ale działają nadal. </p> - <p> - - <a href="https://ksiegarnia.niedziela.pl/religia/201087-psychoterapia-ewangelia-t3-9788380799134.html?utm_source=niezbednikKatolika&utm_medium=AdsBottom1BtnDesktop&utm_campaign=AdsBottom1BtnDesktop" class="btn btn-primary" data-clicksmap="liturgia-AdsBottom1Btn-Desktop">Zobacz</a> - - </p> - </div> - </div> - </div> - - </div> - </div> -</div> </div> - - <div class="px-3"> - -<div class="card border-0 px-lg-3 px-1 py-1 my-4 " > - <div class="card-body text-md-left"> - - <h2 class="mb-4 lh-1 text-uppercase" style="letter-spacing:2px">Liturgia na Twojej stronie WWW </h2> - <div class="row align-items-start"> - <div class="col-md-9"> - - - <p>Masz własną stronę i chcesz umieścić na niej liturgię dnia? Skorzystaj z naszej propozycji. Oferujemy wstawki z tekstami liturgii, które w bardzo prosty sposób dostosujesz do szaty graficznej na swojej witrynie.</p><p><a class="btn" href="https://www.niedziela.pl/webmaster/liturgia" data-clicksmap="liturgia-LiturgiaWidgetBtn-Desktop">Zobacz</a></p> - - </div> - <div class="col-12 col-md-3 mt-4 mt-md-0"> - <img src="https://niezbednik.niedziela.pl/images/widget.png" alt="" class="img-fluid w-75 mx-auto d-block"> - </div> - - </div> - </div> -</div> </div> - - <footer class="footer"> - - - - - <div class="row my-3"> - <div class="col-12"> - <div class="background-gold color-light text-center m-3 p-2 card border-0 px-lg-3 px-1 py-1 my-4 "> - <a class="color-light" href="https://www.niedziela.pl/artykul/117159/Nasz-portal-niedzielapl-i-serwis-Niezbednik-Katolika-nagrodzone-Malym-Feniksem?utm_source=niezbednikKatolika&utm_medium=BtnPanelDesktop&utm_campaign=BtnPanelDesktop" data-clicksmap="liturgia-Feniks2025-Desktop">LAUREAT NAGRODY: <strong>MAŁY FENIKS 2025</strong></a> - </div> - </div> - - <div class="col-xs-12"> - <p class="text-center napisz" style="margin: 0;"> - - </p> - </div> - </div> - - - - <div class="row"> - <div class="col-12 text-center mt-2"> - <a href="https://www.niedziela.pl/prezentacja" class="m-2"><img src="https://ksiazkinawielkipost.niedziela.pl/img/layout/tygodnik-niedziela.jpg" alt="Tygodnik Niedziela" class="img-fluid my-2"></a> - <a href="https://blizejzycia.pl" class="m-2"><img src="https://ksiazkinawielkipost.niedziela.pl/img/layout/logo-blizej-zycia-z-wiara.jpg" alt="Tygodnik Bliżej Życia z Wiarą" class="img-fluid my-2"></a> - <a href="https://magazyn.niedziela.pl" class="m-2"><img src="https://magazyn.niedziela.pl/img/logo-magazyn.jpg" alt="Niedziela. Magazyn" class="img-fluid my-2"></a> - <a href="https://www.niedziela.pl" class="m-2"><img src="https://www.niedziela.pl/img/logo.jpg" alt="Portal Niedziela" class="img-fluid my-2"></a> - <a href="https://ksiegarnia.niedziela.pl" class="mx-2"><img src="https://ksiazkinawielkipost.niedziela.pl/img/layout/logo.jpg" alt="Księgarnia Niedziela" class="img-fluid"></a> - </div> - - </div> - - <div class="row py-3"> - - - <div class="col-xs-12 text-center"> - <a href="https://www.niedziela.pl/polityka_prywatnosci">Polityka prywatności</a> - <br>Copyright © 2026 - Instytut NIEDZIELA - </div> - </div> - - </footer> - - </div> - </div> - -
-
-<div class="modal fade" tabindex="-1" data-bs-backdrop="static" id="entranceModal">
- <div class="modal-dialog modal-dialog-centered">
- <div class="modal-content background-primary">
- <div class="modal-body">
- <p class="text-end mb-2"><button type="button" class="btn btn-light py-0 px-2 m-0 rounded" data-bs-dismiss="modal" aria-label="Zamknij">Zamknij X</button></p>
- <a href="https://e.niedziela.pl?utm_source=niezbednikKatolika&utm_medium=EntranceModalDesktop&utm_campaign=EntranceModalDesktop" data-clicksmap="EntranceModal - E-wydanie - Desktop" target="_blank" >
- <!-- 16:9 aspect ratio -->
- <img class="img-fluid" alt="E-wydanie Tygodnika Niedziela" src="https://www.niedziela.pl/img/niedzielaMobile-entrance-202630.jpg" >
-
- </a>
-
- </div>
- </div>
- </div>
-</div>
-
-
- - - - - <div class="cookies"> - <div class="text-center p-main border-solid"> - <p>W związku z tym, iż od dnia 25 maja 2018 roku obowiązuje <i>Rozporządzenie Parlamentu Europejskiego i Rady (UE) 2016/679 z dnia 27 kwietnia 2016r. w sprawie ochrony osób fizycznych w związku z przetwarzaniem danych osobowych i w sprawie swobodnego przepływu takich danych</i> oraz <i>uchylenia Dyrektywy 95/46/WE (ogólne rozporządzenie o ochronie danych)</i> uprzejmie Państwa informujemy, iż nasza organizacja, mając szczególnie na względzie bezpieczeństwo danych osobowych, które przetwarza, wdrożyła System Zarządzania Bezpieczeństwem Informacji w rozumieniu odpowiednich polityk ochrony danych (zgodnie z art. 24 ust. 2 przedmiotowego rozporządzenia ogólnego). W celu dochowania należytej staranności w kontekście ochrony danych osobowych, Zarząd Instytutu NIEDZIELA wyznaczył w organizacji Inspektora Ochrony Danych. - <br><a target="_prywatnosc" class="" href="https://niedziela.pl/polityka_prywatnosci">Więcej o polityce prywatności czytaj TUTAJ</a>. - </p> - <p class="text-center pt-half"><a class="closecookies btn btn-default btn-sm" href="#"><strong>Akceptuję</strong></a></p> - </div> - </div> - - - - <script src="/assets/a2538e11/jquery.min.js?v=1680299989"></script> -<script src="/assets/2f582ad1/yii.js?v=1680299989"></script> -<script src="/assets/7ca11ba7/dist/js/bootstrap.bundle.min.js?v=1680299989"></script> -<script src="/js/modernizr-2.6.2.min.js?v=1663058799"></script> -<script src="/js/cookie.js?v=1615876568"></script> -<script src="/js/jquery.fitvids.js?v=1480508397"></script> -<script src="/js/aos.js?v=1659426147"></script> -<script src="/js/jquery.easing.1.3.js?v=1663056769"></script> -<script src="/js/jquery.waypoint.min.js?v=1663048957"></script> -<script src="/js/animated.headline.js?v=1663058587"></script> -<script src="/js/sticky-kit.min.js?v=1663058674"></script> -<script src="/js/swiper/swiper.min.js?v=1680301166"></script> -<script src="/js/cookie-consent.js?v=1726132310"></script> -<script src="/js/script.js?v=1765368704"></script> -<script src="/js/main.js?v=1681205062"></script> -<script>jQuery(function ($) { -var magazineSwiper = new Swiper ('.swiper-rozwazania', { - // Optional parameters - //direction: 'vertical', - - //slidesPerView: 'auto', - spaceBetween: 10, - //loop: true, - navigation: { - nextEl: '.swiper-rozwazania-button-next', - prevEl: '.swiper-rozwazania-button-prev' - }, - - mousewheel: false, - - - // And if we need scrollbar - scrollbar: { - el: '.swiper-rozwazania-scrollbar' - }, - breakpoints: { - 0: { - slidesPerView: 1.6 - }, - 768: { - slidesPerView: 2.6, - slidesPerGroup: 2 - }, - 1200: { - slidesPerView: 3.6, - slidesPerGroup: 3 - } - } - }); -
-var kalendarzSwiper = new Swiper ('.swiper-kalendarz', {
- // Optional parameters
- //direction: 'vertical',
- //slidesPerView: 'auto',
- //slidesPerView: 'auto',
- spaceBetween: 10,
- initialSlide: 10,
- //loop: true,
- navigation: {
- nextEl: '.swiper-kalendarz-button-next',
- prevEl: '.swiper-kalendarz-button-prev'
- },
-
- mousewheel: false,
-
-
- // And if we need scrollbar
- scrollbar: {
- el: '.swiper-kalendarz-scrollbar'
- },
- breakpoints: {
- 0: {
- slidesPerView: 1.6,
- centeredSlides: true,
- },
- 768: {
- slidesPerView: 2.6,
- centeredSlides: false,
- },
- 1200: {
- slidesPerView: 7,
- slidesPerGroup: 7,
- centeredSlides: false,
- }
- },
- on: {
- slideChange: function () {
- $('#panelCalendarTitle').text($('.swiper-kalendarz > .swiper-wrapper > .swiper-slide').eq(kalendarzSwiper.activeIndex).data('week'));
- },
- },
- });
- $('#panelCalendarTitle').text($('.swiper-kalendarz > .swiper-wrapper > .swiper-slide').eq(7).data('week')); -var wiadomosciSwiper = new Swiper ('.swiper-wiadomosci', {
- // Optional parameters
- //direction: 'vertical',
-
- //slidesPerView: 'auto',
- spaceBetween: 10,
- //loop: true,
- navigation: {
- nextEl: '.swiper-wiadomosci-button-next',
- prevEl: '.swiper-wiadomosci-button-prev'
- },
-
- mousewheel: false,
-
-
- // And if we need scrollbar
- scrollbar: {
- el: '.swiper-wiadomosci-scrollbar'
- },
- breakpoints: {
- 0: {
- slidesPerView: 1.6
- },
- 768: {
- slidesPerView: 2.6,
- slidesPerGroup: 2
- },
- 1200: {
- slidesPerView: 3.6,
- slidesPerGroup: 3
- }
- }
- }); -
-$('#entranceModal').on('show.bs.modal', function (e) {
- if (typeof gtag === "function") {
- //ga("send", "event", "Entrance Modal", "Show", window.location.href, 1, {"nonInteraction": true });
- gtag("event", "EntranceModal - E-wydanie (Show)", {"eventCategory": "Entrance Modal", "eventLabel": window.location.href});
- }
-
-});
-
-
-
- setTimeout(function(){
-
- const myModal = new bootstrap.Modal('#entranceModal');
-
- myModal.show({backdrop: 'static'});
-
- }, 10000);
-
-
-
-
-
- - - $(".closecookies").click(function() { - Cookies.set("prywatnoscaccept", "1", { expires: 1000 }); - //$.cookie("prywatnoscaccept", 1, {path: "/", expires: 1000}); - $(".cookies").hide(); - return false; - }); - -});</script> -</body> - -</html> -
-
-
-
-
diff --git a/internal/readings/readings.go b/internal/readings/readings.go index b6fae51..d0d7bf9 100644 --- a/internal/readings/readings.go +++ b/internal/readings/readings.go @@ -16,10 +16,6 @@ import ( type Options struct { // Date is the day to load, formatted YYYY-MM-DD. Date string - // Refresh and Offline are retained for caller compatibility but no longer - // have any effect: readings are always computed offline from embedded data. - Refresh bool - Offline bool // All, when true, keeps every part the config doesn't explicitly hide; // when false, only the gospel is kept. All bool diff --git a/internal/readings/readings_test.go b/internal/readings/readings_test.go index f3375f6..143b43e 100644 --- a/internal/readings/readings_test.go +++ b/internal/readings/readings_test.go @@ -103,7 +103,7 @@ func TestLoadModern(t *testing.T) { // needs the network, and yields the EF epistle+gospel with a header name. func TestLoadTraditional(t *testing.T) { cfg := config.Config{Lectionary: "traditional"} - secs, info, err := Load(cfg, Options{Date: "2026-07-22", Offline: true, All: true}) + secs, info, err := Load(cfg, Options{Date: "2026-07-22", All: true}) if err != nil { t.Fatalf("Load: %v", err) } diff --git a/internal/render/render.go b/internal/render/render.go index 3d685d2..c744aac 100644 --- a/internal/render/render.go +++ b/internal/render/render.go @@ -99,22 +99,17 @@ func system(version string) string { return "vulgate" } -const incipit = "Słowa Ewangelii" - // GatherVersion returns (label, blocks) for one version of one reading -// section. Each block is a paragraph (Polish) or a verse line (bible -// versions); on any failure the blocks hold a single short note instead. +// section. Each block is a verse line; on any failure the blocks hold a single +// short note instead. // -// lectionary selects how sec.Citation is read: "new" (modern/niedziela.pl) -// citations are Polish and go through bible.ToEnglishRef; "traditional" -// (missalemeum) citations are already English kjv-style and are used as-is. -// lang selects the UI chrome language the label comes from (see -// internal/i18n); it never affects the verse text/citation itself. +// lectionary selects how sec.Ref is renumbered: "new" (Ordinary Form) refs are +// modern-numbered and go through bible.OFRef for the target Psalter; +// "traditional" (1962) refs are already Vulgate-numbered and used as-is. lang +// selects the UI chrome language the label comes from (see internal/i18n); it +// never affects the verse text/citation itself. func GatherVersion(version string, sec liturgy.Section, lectionary, lang string) (label string, blocks []string) { label = versionLabel(version, lang) - if version == "bt" { - return label, gatherBT(sec) - } ref, err := resolveRef(version, sec, lectionary, lang) if err != nil { @@ -170,15 +165,12 @@ func resolveRef(version string, sec liturgy.Section, lectionary, lang string) (s } // GatherVerses returns one version's verses for a section as raw bible.Verse -// structs (for column/interlinear alignment). versified is false for "bt" -// (paragraph text, no verse numbers) and on any resolution/lookup failure -- -// callers fall back to GatherVersion's string blocks for those. lang selects -// the UI chrome language the label comes from, same as GatherVersion. +// structs (for column/interlinear alignment). versified is false on any +// resolution/lookup failure -- callers fall back to GatherVersion's string +// blocks for those. lang selects the UI chrome language the label comes from, +// same as GatherVersion. func GatherVerses(version string, sec liturgy.Section, lectionary, lang string) (label string, verses []bible.Verse, versified bool) { label = versionLabel(version, lang) - if version == "bt" { - return label, nil, false - } ref, err := resolveRef(version, sec, lectionary, lang) if err != nil { @@ -192,35 +184,10 @@ func GatherVerses(version string, sec liturgy.Section, lectionary, lang string) return label, verses, true } -// gatherBT returns the section's paragraphs, one block per paragraph, with -// the liturgical incipit ("Słowa Ewangelii według ...") dropped and repeated -// blocks (a responsorial psalm's refrain) deduped to their first occurrence. -func gatherBT(sec liturgy.Section) []string { - var blocks []string - for _, p := range sec.Paragraphs { - b := strings.Join(p, " ") - if strings.HasPrefix(b, incipit) { - continue - } - blocks = append(blocks, b) - } - - seen := map[string]bool{} - deduped := make([]string, 0, len(blocks)) - for _, b := range blocks { - if seen[b] { - continue - } - seen[b] = true - deduped = append(deduped, b) - } - return deduped -} - -// OfflineVersions drops "bt" (which needs the network fetch of the liturgy -// page) from versions. If "bt" was present but "wuj" (the Polish-language -// bible version) was not, "wuj" takes bt's place, so the offline set still -// carries a Polish column. +// OfflineVersions maps a legacy "bt" version (the retired niedziela.pl scrape, +// which has no embedded corpus) to "wuj", or drops it when "wuj" is already +// present so the set keeps a single Polish column. Config load migrates bt out +// (see config.migrateBT), so this only guards versions passed in directly. func OfflineVersions(versions []string) []string { hadWuj := false for _, v := range versions { diff --git a/internal/render/render_test.go b/internal/render/render_test.go index 00c8a85..dd177bb 100644 --- a/internal/render/render_test.go +++ b/internal/render/render_test.go @@ -7,23 +7,6 @@ import ( "github.com/lukaszkasprzak/lectio/internal/liturgy" ) -func TestGatherBTDedup(t *testing.T) { - sec := liturgy.Section{ - Heading: "Psalm (Ps 1)", - Paragraphs: [][]string{{"stanza one"}, {"refrain"}, {"stanza two"}, {"refrain"}}, - } - _, blocks := GatherVersion("bt", sec, "new", "pl") - n := 0 - for _, b := range blocks { - if b == "refrain" { - n++ - } - } - if n != 1 { - t.Errorf("refrain appears %d times, want 1 (deduped)", n) - } -} - func TestGatherBible(t *testing.T) { // Offline sections carry the English-canonical lookup reference in Ref; the // display citation stays in the reader's sigla dialect. diff --git a/internal/tradlit/parse_test.go b/internal/tradlit/parse_test.go deleted file mode 100644 index 58cc66f..0000000 --- a/internal/tradlit/parse_test.go +++ /dev/null @@ -1,86 +0,0 @@ -package tradlit - -import ( - "os" - "strings" - "testing" - - "github.com/lukaszkasprzak/lectio/internal/liturgy" -) - -func TestParse(t *testing.T) { - body, err := os.ReadFile("testdata/2026-07-22.json") - if err != nil { - t.Fatal(err) - } - secs, _, err := Parse(body) - if err != nil { - t.Fatal(err) - } - var gospel, epistle bool - for _, s := range secs { - if s.PartID == "evangelium" { - gospel = true - if s.Citation != "Luke 7:36-50" { - t.Errorf("gospel citation = %q", s.Citation) - } - if len(s.Paragraphs) == 0 { - t.Error("gospel has no vernacular text") - } - } - if s.PartID == "lectio" { - epistle = true - } - } - if !gospel || !epistle { - t.Errorf("missing parts: gospel=%v epistle=%v", gospel, epistle) - } -} - -// TestParseDayInfo checks the traditional (missalemeum) day-info -// extraction against the fixture's "info" object: Name from info.title, -// Season from info.tempora, Colour from info.colors[0] ("w" -> "white"). -func TestParseDayInfo(t *testing.T) { - body, err := os.ReadFile("testdata/2026-07-22.json") - if err != nil { - t.Fatal(err) - } - _, info, err := Parse(body) - if err != nil { - t.Fatal(err) - } - if info.Name != "St. Mary Magdalene" { - t.Errorf("Name = %q, want %q", info.Name, "St. Mary Magdalene") - } - if !strings.Contains(info.Season, "Pentecost") { - t.Errorf("Season = %q, want it to contain %q", info.Season, "Pentecost") - } - if info.Colour != "white" { - t.Errorf("Colour = %q, want %q", info.Colour, "white") - } -} - -// TestParseDayInfoMissingInfo checks that a response with no (or empty) -// info object yields a zero DayInfo rather than an error. -func TestParseDayInfoMissingInfo(t *testing.T) { - _, info, err := Parse([]byte(`[{"sections":[]}]`)) - if err != nil { - t.Fatal(err) - } - if info != (liturgy.DayInfo{}) { - t.Errorf("info = %+v, want zero value for a response with no info object", info) - } -} - -// TestParseDayInfoUnknownColourCode checks an unrecognised colour code maps -// to "" rather than passing the raw code through. -func TestParseDayInfoUnknownColourCode(t *testing.T) { - body := []byte(`[{"info":{"title":"Test","tempora":"","colors":["z"]},"sections":[]}]`) - _, info, err := Parse(body) - if err != nil { - t.Fatal(err) - } - if info.Colour != "" { - t.Errorf("Colour = %q, want empty for unknown code %q", info.Colour, "z") - } -} diff --git a/internal/tradlit/testdata/2026-07-22.json b/internal/tradlit/testdata/2026-07-22.json deleted file mode 100644 index 32b366f..0000000 --- a/internal/tradlit/testdata/2026-07-22.json +++ /dev/null @@ -1 +0,0 @@ -[{"info":{"id":"sancti:07-22:3:w","title":"St. Mary Magdalene","tags":[],"colors":["w"],"date":"2026-07-22","description":"","rank":3,"supplements":[],"tempora":"Feria IV after VIII Sunday after Pentecost","commemorations":[],"displaced":[]},"sections":[{"id":"Introitus","label":"Introit","body":[["*Ps 118:95-96.*\nSinners wait to destroy me, but I pay heed to Your decrees, O Lord. I see that all fulfillment has its limits; broad indeed is Your command. (Alleluja, alleluja.)\n*Ps 118:1*\nHappy are they whose way is blameless, who walk in the law of the Lord.\nGlory Be to the Father…\nSinners wait to destroy me, but I pay heed to Your decrees, O Lord. I see that all fulfillment has its limits; broad indeed is Your command. (Allelúja, allelúja.)","*Ps 118:95-96*\nMe exspectavérunt peccatóres, ut pérderent me: testimónia tua, Dómine, intelléxi: omnis consummatiónis vidi finem: latum mandátum tuum nimis. (Allelúja, allelúja.)\n*Ps 118:1*\nBeáti immaculáti in via: qui ámbulant in lege Dómini.\nGlória Patri…\nMe exspectavérunt peccatóres, ut pérderent me: testimónia tua, Dómine, intelléxi: omnis consummatiónis vidi finem: latum mandátum tuum nimis. (Allelúja, allelúja.)"]]},{"id":"Oratio","label":"Collect","body":[["May the prayers of blessed Mary Magdalen help us, O Lord, Who were moved by her prayers and brought back alive from the grave her brother Lazarus, dead for four days.\nThrough our Lord…","Beátæ Maríæ Magdalénæ, quǽsumus, Dómine, suffrágiis adjuvémur: cujus précibus exorátus, quatriduánum fratrem Lázarum vivum ab ínferis resuscitásti:\nQui vivis…"]]},{"id":"Lectio","label":"Epistle","body":[["Lesson from the book of Canticles\n*Song 3:2-5; 8:6-7*\nI will rise and go about the city; in the streets and crossings I will seek Him Whom my heart loves. I sought Him but I did not find Him. The watchmen came upon me as they made their rounds of the city: Have you seen Him Whom my heart loves? I had hardly left them when I found Him Whom my heart loves. I took hold of Him and would not let Him go till I should bring Him to the home of my mother, to the room of my parent, I adjure you, daughters of Jerusalem, by the gazelles and hinds of the field, do not arouse, do not stir up love before its own time. Set me as a seal on Your heart, as a seal on Your arm; for stern as death is love, relentless as the nether world is devotion; its flames are a blazing fire. Deep waters cannot quench love, nor floods sweep it away. Were one to offer all he owns to purchase love, he would despise it as nothing.","Léctio libri Sapiéntiæ\n*Cant 3:2-5; 8:6-7*\nSurgam, et circuíbo civitátem: per vicos et pláteas quæram, quem díligit ánima mea: quæsívi illum, et non invéni. Invenérunt me vígiles, qui custódiunt civitátem. Num quem díligit ánima mea, vidístis? Páululum cum pertransíssem eos, invéni, quem díligit ánima mea: ténui eum, nec dimíttam, donec introdúcam illum in domum matris meæ et in cubículum genetrícis meæ. Adjúro vos, fíliæ Jerúsalem, per cápreas cervósque campórum, ne suscitétis neque evigiláre faciátis diléctam, donec ipsa velit. Pone me ut signáculum super cor tuum, ut signáculum super bráchium tuum: quia fortis est ut mors diléctio, dura sicut inférnus æmulátio: lámpades ejus lámpades ignis atque flammárum. Aquæ multæ non potuérunt exstínguere caritátem, nec flúmina óbruent illam: si déderit homo omnem substántiam domus suæ pro dilectióne, quasi nihil despíciet eam."]]},{"id":"Graduale","label":"Gradual","body":[["*Ps 44:8*\nYou love justice and hate wickedness.\n℣. Therefore God, your God, has anointed you with the oil of gladness.\nAlleluia, alleluia.\n*Ps 44:3*\nGrace is poured out upon your lips; thus God has blessed you forever. Alleluia.","*Ps 44:8*\nDilexísti justítiam, et odísti iniquitátem.\n℣. Proptérea unxit te Deus, Deus tuus, óleo lætítiæ.\nAllelúja, allelúja.\n*Ps 44:3*\nDiffúsa est grátia in lábiis tuis: proptérea benedíxit te Deus in ætérnum. Allelúja."]]},{"id":"Evangelium","label":"Gospel","body":[["Continuation ☩ of the Holy Gospel according to Luke\n*Luke 7:36-50*\nAt that time, one of the Pharisees asked Jesus to dine with him; so He went into the house of the Pharisee and reclined at table. And behold, a woman in the town who was a sinner, upon learning that He was at table in the Pharisee's house, brought an alabaster jar of ointment; and standing behind Him at His feet, she began to bathe His feet with her tears, and wiped them with the hair of her head, and kissed His feet, and anointed them with ointment. Now when the Pharisee, who had invited Him, saw it, he said to himself, “This man, were He a prophet, would surely know who and what manner of woman this is who is touching Him, for she is a sinner.” And Jesus answered and said to him, “Simon, I have something to say to you.” And he said, “Master, speak.” “A certain money-lender had two debtors; the one owed five hundred denarii, the other fifty. As they had no means of paying, he forgave them both. Which of them, therefore, will love him more?” Simon answered and said, “He, I suppose, to whom he forgave more.” And He said to him, “You have judged rightly.” And turning to the woman, He said to Simon, “Do you see this woman? I came into your house; you gave Me no water for My feet; but she has bathed My feet with her tears, and has wiped them with her hair. You gave Me no kiss; but she, from the moment she entered, has not ceased to kiss My feet. You did not anoint My head with oil; but she has anointed My feet with ointment. Wherefore I say to you, her sins, many as they are, shall be forgiven her, because she has loved much. But he to whom little is forgiven, loves little.” And He said to her, “Your sins are forgiven.” And they who were at table with Him began to say within themselves, “Who is this man, who even forgives sins?” But He said to the woman, “Your faith has saved you; go in peace.”","Sequéntia ☩ sancti Evangélii secúndum Lucam\n*Luc 7:36-50*\nIn illo témpore: Rogábat Jesum quidam de pharisǽis, ut manducáret cum illo. Et ingréssus domum pharisǽi, discúbuit. Et ecce múlier, quæ erat in civitáte peccátrix, ut cognóvit, quod accubuísset in domo pharisǽi, áttulit alabástrum unguénti: et stans retro secus pedes ejus, lácrimis cœpit rigáre pedes ejus, et capíllis cápitis sui tergébat, et osculabátur pedes ejus, et unguénto ungébat. Videns autem pharisǽus, qui vocáverat eum, ait intra se, dicens: Hic si esset Prophéta, sciret útique, quæ et qualis est múlier, quæ tangit eum: quia peccátrix est. Et respóndens Jesus, dixit ad illum: Simon, hábeo tibi áliquid dícere. At ille ait: Magíster, dic. Duo debitóres erant cuidam fœneratóri: unus debébat denários quingéntos, et álius quinquagínta. Non habéntibus illis, unde rédderent, donávit utrísque. Quis ergo eum plus díligit? Respóndens Simon, dixit: Æstimo, quia is, cui plus donávit. At ille dixit ei: Recte judicásti. Et convérsus ad mulíerem, dixit Simóni: Vides hanc mulíerem? Intrávi in domum tuam, aquam pédibus meis non dedísti: hæc autem lácrimis rigávit pedes meos et capíllis suis tersit. Osculum mihi non dedísti: hæc autem, ex quo intrávit, non cessávit osculári pedes meos. Oleo caput meum non unxísti: hæc autem unguénto unxit pedes meos. Propter quod dico tibi: Remittúntur ei peccáta multa, quóniam diléxit multum. Cui autem minus dimíttitur, minus díligit. Dixit autem ad illam: Remittúntur tibi peccáta. Et cœpérunt, qui simul accumbébant, dícere intra se: Quis est hic, qui étiam peccáta dimíttit? Dixit autem ad mulíerem: Fides tua te salvam fecit: vade in pace."]]},{"id":"Offertorium","label":"Offertory","body":[["*Ps 44:10*\nThe daughters of kings have delighted thee in thy glory. The queen stood on thy right hand, in gilded clothing; surrounded with variety. (Allelúja.)","*Ps 44:10*\nFíliæ regum in honóre tuo, ástitit regína a dextris tuis in vestítu deauráto, circúmdata varietáte. (Allelúja.)"]]},{"id":"Secreta","label":"Secret","body":[["O Lord, may our gifts be acceptable to You through the glorious merits of blessed Mary Magdalen, whose offering of homage Your only-begotten Son did mercifully accept.\nWho livest and reignest with God the Father…","Múnera nostra, quǽsumus. Dómine, beátæ Maríæ Magdalénæ gloriósa mérita tibi reddant accépta: cujus oblatiónis obséquium unigénitus Fílius tuus cleménter suscépit impénsum:\nQui tecum…"]]},{"id":"Prefatio","label":"Preface","body":[["*Common*\nIt is truly meet and just, and profitable unto salvation, that we should at all times, and in all places, give thanks to Thee, O Holy Lord, Father Almighty, eternal God, through Christ, our Lord. Through whom the Angels praise Thy Majesty, the Dominions adore it, the Powers are in awe. Which the heavens and the hosts of heaven together with the blessed Seraphim joyfully do magnify. And do Thou command that it be permitted us to join with them in confessing Thee, while we say with lowly praise:","*Communis*\nVere dignum et justum est, æquum et salutáre, nos tibi semper et ubíque grátias ágere: Dómine sancte, Pater omnípotens, ætérne Deus: per Christum, Dóminum nostrum. Per quem majestátem tuam laudant Angeli, adórant Dominatiónes, tremunt Potestátes. Cæli cælorúmque Virtútes ac beáta Séraphim sócia exsultatióne concélebrant. Cum quibus et nostras voces ut admítti jubeas, deprecámur, súpplici confessione dicéntes:"]]},{"id":"Communio","label":"Communion","body":[["*Ps 118:121-122; 118:128*\nI have fulfilled just ordinances, O Lord; let not the proud oppress me. For in all Your precepts I go forward; every false way I hate. (Alleluja.)","*Ps 118:121; 118:122; 118:128*\nFeci judícium et justítiam, Dómine, non calumniéntur mihi supérbi: ad ómnia mandáta tua dirigébar, omnem viam iniquitátis ódio hábui. (Allelúja.)"]]},{"id":"Postcommunio","label":"Postcommunion","body":[["After receiving Your Body and precious Blood, the one and only saving remedy, we beseech You, O Lord, that, under the protection of blessed Mary Magdalen, we may be freed from all evils.\nWho livest…","Sumpto, quǽsumus, Dómine, único ac salutári remédio, Córpore et Sánguine tuo pretióso: ab ómnibus malis, sanctæ Maríæ Magdalénæ patrocíniis, eruámur:\nQui vivis…"]]}]}]
\ No newline at end of file diff --git a/internal/tradlit/tradlit.go b/internal/tradlit/tradlit.go deleted file mode 100644 index b464e56..0000000 --- a/internal/tradlit/tradlit.go +++ /dev/null @@ -1,216 +0,0 @@ -// Package tradlit fetches and parses the Traditional (1962 Missal) Latin -// propers from the missalemeum JSON API into the shared liturgy.Section -// type, so the rest of the app can treat the traditional and modern -// (niedziela.pl) lectionaries interchangeably. -package tradlit - -import ( - "encoding/json" - "fmt" - "io" - "net/http" - "os" - "path/filepath" - "regexp" - "strings" - - "github.com/lukaszkasprzak/lectio/internal/liturgy" -) - -// baseURL is the missalemeum proper-of-the-day API template ("%s" is lang, -// then date, YYYY-MM-DD). It is a package var so tests can point it at an -// httptest server. -var baseURL = "https://www.missalemeum.com/%s/api/v5/proper/%s" - -// userAgent is sent on every fetch; matches the browser UA used elsewhere -// in this project (see the plan's Global Constraints). -const userAgent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 " + - "(KHTML, like Gecko) Chrome/124.0 Safari/537.36" - -// citationRe matches the first *...* marker in a section's body text, e.g. -// "*Luke 7:36-50*" or "*Ps 44:2*". -var citationRe = regexp.MustCompile(`\*([^*\n]+)\*`) - -// apiResponse mirrors the shape of the missalemeum proper-of-the-day API: -// a single-element list of { info, sections }. -type apiResponse struct { - Info apiInfo `json:"info"` - Sections []apiSection `json:"sections"` -} - -// apiInfo mirrors the missalemeum API's "info" object: the day's celebration -// title, its temporal context ("tempora"), and its liturgical colour code(s) -// -- see dayInfoFromAPI, which turns it into a liturgy.DayInfo. -type apiInfo struct { - Title string `json:"title"` - Tempora string `json:"tempora"` - Colors []string `json:"colors"` -} - -type apiSection struct { - ID string `json:"id"` - Label string `json:"label"` - Body [][]string `json:"body"` -} - -// tradColours maps missalemeum's single-letter liturgical colour codes to -// DayInfo's normalized colour names; a code not listed here (or an empty -// Colors list) leaves DayInfo.Colour "". -var tradColours = map[string]string{ - "w": "white", - "r": "red", - "v": "violet", - "g": "green", - "p": "rose", -} - -// dayInfoFromAPI turns a response's info object into a liturgy.DayInfo: -// Title -> Name, Tempora -> Season, and the first Colors code -> Colour via -// tradColours (unknown/missing -> ""). A zero-value apiInfo (no "info" key -// in the response) yields a zero DayInfo. -func dayInfoFromAPI(info apiInfo) liturgy.DayInfo { - colour := "" - if len(info.Colors) > 0 { - colour = tradColours[strings.ToLower(info.Colors[0])] - } - return liturgy.DayInfo{ - Name: info.Title, - Season: info.Tempora, - Colour: colour, - } -} - -// Parse decodes a missalemeum proper-of-the-day API response body into -// liturgy.Sections plus the day's liturgical identity (its "info" object, -// see dayInfoFromAPI). Sections with an empty id or empty body are skipped. -func Parse(jsonBody []byte) ([]liturgy.Section, liturgy.DayInfo, error) { - var resp []apiResponse - if err := json.Unmarshal(jsonBody, &resp); err != nil { - return nil, liturgy.DayInfo{}, fmt.Errorf("tradlit: parse: %w", err) - } - if len(resp) == 0 { - return nil, liturgy.DayInfo{}, fmt.Errorf("tradlit: parse: empty response") - } - - info := dayInfoFromAPI(resp[0].Info) - - var out []liturgy.Section - for _, sec := range resp[0].Sections { - if sec.ID == "" || len(sec.Body) == 0 || len(sec.Body[0]) == 0 { - continue - } - - text := strings.Join(sec.Body[0], "\n") - - var lines []string - for _, line := range strings.Split(text, "\n") { - line = strings.TrimSpace(line) - if line != "" { - lines = append(lines, line) - } - } - - citation := "" - if m := citationRe.FindStringSubmatch(text); m != nil { - citation = strings.TrimSpace(m[1]) - } - - out = append(out, liturgy.Section{ - Heading: sec.Label, - Citation: citation, - PartID: strings.ToLower(sec.ID), - Paragraphs: [][]string{lines}, - }) - } - return out, info, nil -} - -// cachePath returns where Load caches a (date, lang) day's raw API response: -// <CacheDir>/<date>.trad.<lang>.json -- date-prefixed (like the modern -// lectionary's own cache files) so liturgy.CleanCache can prune it by date. -func cachePath(date, lang string) string { - return filepath.Join(liturgy.CacheDir(), date+".trad."+lang+".json") -} - -// Load returns a day's traditional propers for lang, either read from the -// on-disk cache (offline) or fetched live from missalemeum and cached for -// next time (online). Both paths share Parse, so cached and live results -// are identical. -// -// - offline: reads the cache file written by a prior online Load (see -// cachePath); if it doesn't exist, returns a clear error telling the -// caller to go online or run 'lectio update' first. -// - online: fetches https://www.missalemeum.com/{lang}/api/v5/proper/{date} -// as before. On a successful 200, the raw response body is written to -// the cache path (best-effort -- a cache-write failure never fails the -// request) before being parsed. On HTTP 404 (no propers published for -// that date) it returns a clear error and writes nothing to the cache. -func Load(date, lang string, offline bool) ([]liturgy.Section, liturgy.DayInfo, error) { - if offline { - return loadCached(date, lang) - } - return loadLive(date, lang) -} - -// loadCached implements Load's offline path. -func loadCached(date, lang string) ([]liturgy.Section, liturgy.DayInfo, error) { - body, err := os.ReadFile(cachePath(date, lang)) - if err != nil { - return nil, liturgy.DayInfo{}, fmt.Errorf("tradlit: no cached traditional propers for %s (%s); view it online or run 'lectio update' first", date, lang) - } - return Parse(body) -} - -// loadLive implements Load's online path: fetch, best-effort cache the raw -// body, then parse. -func loadLive(date, lang string) ([]liturgy.Section, liturgy.DayInfo, error) { - body, err := fetch(date, lang) - if err != nil { - return nil, liturgy.DayInfo{}, err - } - writeCache(date, lang, body) - return Parse(body) -} - -// fetch GETs the day's proper-of-the-day JSON from missalemeum and returns -// the raw response body. On HTTP 404 (no propers published for that date) -// it returns a clear error rather than the raw 404 body. -func fetch(date, lang string) ([]byte, error) { - url := fmt.Sprintf(baseURL, lang, date) - - req, err := http.NewRequest(http.MethodGet, url, nil) - if err != nil { - return nil, fmt.Errorf("tradlit: load: %w", err) - } - req.Header.Set("User-Agent", userAgent) - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return nil, fmt.Errorf("tradlit: load %s: %w", date, err) - } - defer resp.Body.Close() - - if resp.StatusCode == http.StatusNotFound { - return nil, fmt.Errorf("tradlit: no propers published for %s", date) - } - if resp.StatusCode != http.StatusOK { - return nil, fmt.Errorf("tradlit: load %s: unexpected status %s", date, resp.Status) - } - - body, err := io.ReadAll(resp.Body) - if err != nil { - return nil, fmt.Errorf("tradlit: load %s: %w", date, err) - } - return body, nil -} - -// writeCache best-effort writes a day's raw API response body to its cache -// path; a failure to cache (e.g. an unwritable cache dir) must never fail -// the live request that produced body. -func writeCache(date, lang string, body []byte) { - path := cachePath(date, lang) - if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { - return - } - _ = os.WriteFile(path, body, 0o644) -} diff --git a/internal/tradlit/tradlit_test.go b/internal/tradlit/tradlit_test.go deleted file mode 100644 index 8aa46eb..0000000 --- a/internal/tradlit/tradlit_test.go +++ /dev/null @@ -1,127 +0,0 @@ -package tradlit - -import ( - "net/http" - "net/http/httptest" - "os" - "path/filepath" - "strings" - "testing" - - "github.com/lukaszkasprzak/lectio/internal/liturgy" -) - -// TestLoadOnlineCachesRawBody exercises Load's online path: a successful -// fetch is cached verbatim (the raw response body, not the parsed -// sections) at tradlit's cache path, and parses the same way a cached read -// would. -func TestLoadOnlineCachesRawBody(t *testing.T) { - body, err := os.ReadFile("testdata/2026-07-22.json") - if err != nil { - t.Fatal(err) - } - hits := 0 - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - hits++ - w.Write(body) - })) - defer srv.Close() - - orig := baseURL - baseURL = srv.URL + "/%s/api/v5/proper/%s" - defer func() { baseURL = orig }() - t.Setenv("XDG_CACHE_HOME", t.TempDir()) - - secs, info, err := Load("2026-07-22", "en", false) - if err != nil { - t.Fatalf("Load: %v", err) - } - if len(secs) == 0 { - t.Fatal("Load returned no sections") - } - if info.Name != "St. Mary Magdalene" { - t.Errorf("Load DayInfo.Name = %q, want %q", info.Name, "St. Mary Magdalene") - } - if hits != 1 { - t.Errorf("server hit %d times, want 1", hits) - } - - cached, err := os.ReadFile(filepath.Join(liturgy.CacheDir(), "2026-07-22.trad.en.json")) - if err != nil { - t.Fatalf("cache file not written: %v", err) - } - if string(cached) != string(body) { - t.Error("cached content does not match the raw response body") - } -} - -// TestLoadOnline404WritesNoCache checks the documented invariant: a 404 (no -// propers published for that date) returns an error and leaves the cache -// directory untouched. -func TestLoadOnline404WritesNoCache(t *testing.T) { - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusNotFound) - })) - defer srv.Close() - - orig := baseURL - baseURL = srv.URL + "/%s/api/v5/proper/%s" - defer func() { baseURL = orig }() - t.Setenv("XDG_CACHE_HOME", t.TempDir()) - - _, _, err := Load("2026-07-22", "en", false) - if err == nil { - t.Fatal("expected error on 404, got nil") - } - - cachePath := filepath.Join(liturgy.CacheDir(), "2026-07-22.trad.en.json") - if _, statErr := os.Stat(cachePath); !os.IsNotExist(statErr) { - t.Errorf("cache file should not exist after a 404 (stat err = %v)", statErr) - } -} - -// TestLoadOfflineReadsCache exercises Load's offline path against a -// pre-written cache file (as an earlier online Load, or 'lectio update', -// would have left behind) -- no network access at all. -func TestLoadOfflineReadsCache(t *testing.T) { - body, err := os.ReadFile("testdata/2026-07-22.json") - if err != nil { - t.Fatal(err) - } - dir := t.TempDir() - t.Setenv("XDG_CACHE_HOME", dir) - cacheDir := filepath.Join(dir, "lectio") - if err := os.MkdirAll(cacheDir, 0o755); err != nil { - t.Fatal(err) - } - if err := os.WriteFile(filepath.Join(cacheDir, "2026-07-22.trad.pl.json"), body, 0o644); err != nil { - t.Fatal(err) - } - - secs, info, err := Load("2026-07-22", "pl", true) - if err != nil { - t.Fatalf("Load offline: %v", err) - } - if len(secs) == 0 { - t.Fatal("Load offline returned no sections") - } - if info.Name != "St. Mary Magdalene" { - t.Errorf("Load offline DayInfo.Name = %q, want %q", info.Name, "St. Mary Magdalene") - } -} - -// TestLoadOfflineMissingCacheErrors checks Load's offline path errors -// clearly (mentioning the missing cache) rather than trying the network, -// when nothing has been cached yet for that (date, lang). -func TestLoadOfflineMissingCacheErrors(t *testing.T) { - t.Setenv("XDG_CACHE_HOME", t.TempDir()) - - _, _, err := Load("2026-07-22", "pl", true) - if err == nil { - t.Fatal("expected error for missing cache, got nil") - } - msg := strings.ToLower(err.Error()) - if !strings.Contains(msg, "no cached") { - t.Errorf("error %q should mention no cached propers", err.Error()) - } -} diff --git a/internal/tui/reader.go b/internal/tui/reader.go index 7f23f66..dc9141a 100644 --- a/internal/tui/reader.go +++ b/internal/tui/reader.go @@ -138,7 +138,7 @@ func (m ReaderModel) bookIndex(canonical string) int { func corpusVersions(cfg config.Config) []string { var out []string for _, v := range cfg.Versions { - if config.ValidVersion(v) && v != "bt" { + if config.ValidVersion(v) { out = append(out, v) } } diff --git a/internal/tui/tui.go b/internal/tui/tui.go index 96d82c1..374537f 100644 --- a/internal/tui/tui.go +++ b/internal/tui/tui.go @@ -134,20 +134,14 @@ func shiftDate(date string, days int) string { return t.AddDate(0, 0, days).Format("2006-01-02") } -// fetchCmd issues the readings.Load fetch for the model's current date as a -// tea.Cmd, resolving to readingsMsg or errMsg. All follows cfg.All (config's -// gospel-only vs every-part choice); Offline follows cfg.Offline; refresh -// bypasses the cache (the "r" key), matching the CLI's --refresh. -func (m Model) fetchCmd(refresh bool) tea.Cmd { +// fetchCmd resolves the readings.Load for the model's current date as a +// tea.Cmd, yielding readingsMsg or errMsg. All follows cfg.All (config's +// gospel-only vs every-part choice); readings are always computed offline. +func (m Model) fetchCmd() tea.Cmd { cfg := m.cfg date := m.date return func() tea.Msg { - secs, info, err := readings.Load(cfg, readings.Options{ - Date: date, - Refresh: refresh, - Offline: cfg.Offline, - All: cfg.All, - }) + secs, info, err := readings.Load(cfg, readings.Options{Date: date, All: cfg.All}) if err != nil { return errMsg{err} } @@ -157,7 +151,7 @@ func (m Model) fetchCmd(refresh bool) tea.Cmd { // Init issues the first load. func (m Model) Init() tea.Cmd { - return m.fetchCmd(false) + return m.fetchCmd() } // Update handles key input and fetch results. @@ -196,16 +190,12 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.date = shiftDate(m.date, -1) m.loading = true m.err = nil - return m, m.fetchCmd(false) + return m, m.fetchCmd() case "right": m.date = shiftDate(m.date, +1) m.loading = true m.err = nil - return m, m.fetchCmd(false) - case "r": - m.loading = true - m.err = nil - return m, m.fetchCmd(true) + return m, m.fetchCmd() case "d": m.jumping = true m.jumpBuf = "" @@ -253,7 +243,7 @@ func (m Model) updateJump(msg tea.KeyMsg) (tea.Model, tea.Cmd) { m.date = t.Format("2006-01-02") m.loading = true m.err = nil - return m, m.fetchCmd(false) + return m, m.fetchCmd() } return m, nil case tea.KeyBackspace: @@ -423,12 +413,8 @@ func (m Model) bodyLines(w int) []string { _, blocks := render.GatherVersion(ver, sec, m.cfg.Lectionary, m.cfg.UILanguage) numW := maxNumWidth(blocks) - // The refrain-italic only applies to the bt responsorial-psalm block - // (its first, deduped paragraph); bible versions have no refrain block. - isPsalm := sec.PartID == "psalm" && ver == "bt" - for bi, b := range blocks { - refrain := isPsalm && bi == 0 - lines = append(lines, styleBlock(b, refrain, w, numW)...) + for _, b := range blocks { + lines = append(lines, styleBlock(b, false, w, numW)...) lines = append(lines, "") } } diff --git a/internal/tui/tui_test.go b/internal/tui/tui_test.go index d4aa855..68e09b5 100644 --- a/internal/tui/tui_test.go +++ b/internal/tui/tui_test.go @@ -153,12 +153,14 @@ func TestDayInfoLineOmittedWhenEmpty(t *testing.T) { // TestFooterKeysLocalised checks the footer keybar text follows // cfg.UILanguage. func TestFooterKeysLocalised(t *testing.T) { - en := Model{cfg: config.Config{UILanguage: "en"}, date: "2026-07-22"} + // Give the model a real terminal width so the one-line keybar is not wrapped + // across lines (the 80-col View() fallback would split "q quit"). + en := Model{cfg: config.Config{UILanguage: "en"}, date: "2026-07-22", width: 120} if out := en.View(); !strings.Contains(out, "q quit") { t.Errorf("en View() footer missing %q: %q", "q quit", out) } - pl := Model{cfg: config.Config{UILanguage: "pl"}, date: "2026-07-22"} + pl := Model{cfg: config.Config{UILanguage: "pl"}, date: "2026-07-22", width: 120} if out := pl.View(); !strings.Contains(out, "q wyjście") { t.Errorf("pl View() footer missing %q: %q", "q wyjście", out) } diff --git a/internal/web/render.go b/internal/web/render.go index 2cbf331..3ea52e3 100644 --- a/internal/web/render.go +++ b/internal/web/render.go @@ -191,12 +191,9 @@ func buildColumnViews(secs []liturgy.Section, versions []string, lectionary, lan return views } -// interlinearVersions maps versions through the same bt->wuj substitution -// render.OfflineVersions performs for offline mode: "bt" (niedziela.pl -// paragraph text) carries no verse numbers and cannot interleave, so it is -// dropped, substituting "wuj" (the Polish-language bible version) in its -// place unless "wuj" was already selected. Reuses render.OfflineVersions -// rather than duplicating its two-line transform. +// interlinearVersions maps versions through render.OfflineVersions, which +// substitutes a legacy "bt" with "wuj" (unless "wuj" is already selected). +// Every remaining version is a versified corpus that interleaves cleanly. func interlinearVersions(versions []string) []string { return render.OfflineVersions(versions) } @@ -288,9 +285,8 @@ func webVersionLabel(v, lang string) string { return v } -// readerCorpusVersions are the versions the /reader offers: the four with an -// embedded full-text corpus. "bt" (the niedziela.pl scrape) has no corpus and -// cannot be read chapter-by-chapter. +// readerCorpusVersions are the versions the /reader offers: the four embedded +// full-text corpora. var readerCorpusVersions = []string{"wuj", "vul", "grb", "drb"} // UnionChapters returns the sorted union of chapter numbers a book has across diff --git a/internal/web/render_test.go b/internal/web/render_test.go index c05a83c..39bcc58 100644 --- a/internal/web/render_test.go +++ b/internal/web/render_test.go @@ -80,13 +80,19 @@ func TestThemeCSSGuardRejectsInvalidNames(t *testing.T) { } func TestRenderReadingsEscapesScriptText(t *testing.T) { + // An attacker-controlled version code (?v=... reaches RenderReadings + // unfiltered) flows to render.GatherVersion as both the column label and the + // "(not in %s)" note. RenderReadings must HTML-escape it: it renders through + // html/template, never wrapping untrusted text in template.HTML. + const evil = "<script>alert(1)</script>" secs := []liturgy.Section{{ - Heading: "Test", - PartID: "pierwsze_czytanie", - Paragraphs: [][]string{{"<script>alert(1)</script>"}}, + Heading: "Ewangelia", + Citation: "J 20, 1. 11-18", + Ref: "John 20:1,11-18", + PartID: "pierwsze_czytanie", }} - html := string(RenderReadings(secs, []string{"bt"}, "new", "horizontal", "pl", liturgy.DayInfo{})) - if strings.Contains(html, "<script>alert(1)</script>") { + html := string(RenderReadings(secs, []string{evil}, "new", "horizontal", "pl", liturgy.DayInfo{})) + if strings.Contains(html, evil) { t.Errorf("raw <script> leaked into rendered output: %q", html) } if !strings.Contains(html, "<script>alert(1)</script>") { diff --git a/internal/web/server.go b/internal/web/server.go index fce0f22..6e76d3f 100644 --- a/internal/web/server.go +++ b/internal/web/server.go @@ -35,7 +35,7 @@ import ( // bibleVersions is the fixed, Themes-independent list of scripture versions // the web UI's checkboxes offer -- independent of any one cfg.Versions, so // every visitor sees the same five choices regardless of their config file. -var bibleVersions = []string{"bt", "wuj", "vul", "grb", "drb"} +var bibleVersions = []string{"wuj", "vul", "grb", "drb"} // server holds the live, mutable config + book table so /settings can apply // changes to the running process. All handlers read a snapshot via get()/table(). @@ -142,17 +142,6 @@ func requestVersions(cfg config.Config, r *http.Request) []string { return []string{cfg.DefaultVersion} } -// withoutVersion returns versions with every occurrence of drop removed. -func withoutVersion(versions []string, drop string) []string { - kept := make([]string, 0, len(versions)) - for _, v := range versions { - if v != drop { - kept = append(kept, v) - } - } - return kept -} - // queryBool reads a truthy/falsy query param ("1"/"true"/"on"/"yes" vs. // "0"/"false"/"off"/"no"), falling back to def when the param is absent or // unrecognized. @@ -202,35 +191,19 @@ func resolveQuery(cfg config.Config, r *http.Request) (date, lectionary string, lectionary = requestLectionary(cfg, r) all = queryBool(r, "all", cfg.All) versions = requestVersions(cfg, r) - // "bt" (the niedziela modern scrape) is invalid for the traditional - // lectionary and is hidden in the form -- but a box hidden by CSS stays - // checked, so switching modern->traditional carries a phantom v=bt that - // EffectiveVersions would substitute to wuj, defeating "no version selected - // -> nothing". On an explicit form submit (vset) drop that phantom bt; a - // fresh visit (no vset) keeps bt so its bt->wuj default still shows. - if lectionary == "traditional" && r.URL.Query().Has("vset") { - versions = withoutVersion(versions, "bt") - } display = requestDisplay(cfg, r) return date, lectionary, all, versions, display } -// loadSections runs the readings router for one request: date/lectionary -// 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. dayInfo is the day's celebration -// identity (see liturgy.DayInfo), zero when the source carried none. +// loadSections computes one request's readings offline: date/lectionary +// override cfg, all controls part filtering, and versions is passed through +// render.EffectiveVersions (which maps any legacy "bt" to "wuj") so the +// caller's column labels always match what was actually loadable. dayInfo is +// the day's celebration identity (see liturgy.DayInfo), zero when none. func loadSections(cfg config.Config, lectionary, date string, all bool, versions []string) (secs []liturgy.Section, dayInfo liturgy.DayInfo, effVersions []string, err error) { cfg.Lectionary = lectionary effVersions = render.EffectiveVersions(versions, lectionary, cfg.Offline) - secs, dayInfo, err = readings.Load(cfg, readings.Options{ - Date: date, - Offline: cfg.Offline, - All: all, - }) + secs, dayInfo, err = readings.Load(cfg, readings.Options{Date: date, All: all}) return secs, dayInfo, effVersions, err } @@ -406,7 +379,7 @@ func calendarHandler(cfg config.Config) http.HandlerFunc { var days []export.CalendarDay for d := first; int(d.Month()) == month; d = d.AddDate(0, 0, 1) { cd := export.CalendarDay{Day: d.Day()} - if secs, info, lerr := readings.Load(cfg, readings.Options{Date: d.Format("2006-01-02"), Offline: cfg.Offline, All: false}); lerr == nil { + if secs, info, lerr := readings.Load(cfg, readings.Options{Date: d.Format("2006-01-02"), All: false}); lerr == nil { cd.Name = info.Name cd.Colour = info.Colour cd.Citation = readings.GospelCitation(secs) @@ -799,7 +772,6 @@ func settingsPost(s *server) http.HandlerFunc { cfg := s.get() // start from live cfg so Parts/SchemaVersion are preserved cfg.Lectionary = normLect(r.PostForm.Get("lectionary"), cfg.Lectionary) - cfg.TraditionalLang = pickLang(r.PostForm.Get("traditional_lang"), cfg.TraditionalLang) cfg.UILanguage = config.NormalizeUILanguage(r.PostForm.Get("ui_language")) cfg.SiglaStyle = config.NormalizeSiglaStyle(r.PostForm.Get("sigla_style")) cfg.WebDisplay = config.NormalizeDisplay(r.PostForm.Get("web_display")) @@ -865,14 +837,6 @@ func normLect(v, def string) string { return def } -// pickLang returns v if it is "pl"/"en", else def. -func pickLang(v, def string) string { - if v == "pl" || v == "en" { - return v - } - return def -} - func atoiOr(s string, def int) int { if n, err := strconv.Atoi(strings.TrimSpace(s)); err == nil { return n diff --git a/internal/web/server_test.go b/internal/web/server_test.go index 12542e5..57286d5 100644 --- a/internal/web/server_test.go +++ b/internal/web/server_test.go @@ -15,22 +15,9 @@ import ( "github.com/lukaszkasprzak/lectio/internal/liturgy" ) -// TestServer exercises NewServer's handler tree end to end via httptest, -// against the same fixture HTML/hook internal/readings uses (see -// readings_test.go TestLoadModernRoutes): no real network, no real browser. +// TestServer exercises NewServer's handler tree end to end via httptest. Every +// reading is computed offline (no network, no cache, no fixture server). func TestServer(t *testing.T) { - html, err := os.ReadFile("../liturgy/testdata/2026-07-22.html") - if err != nil { - t.Fatal(err) - } - fixtureServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Write(html) - })) - defer fixtureServer.Close() - liturgy.SetBaseURL(fixtureServer.URL + "/liturgia/%s/Ewangelia") - cacheHome := t.TempDir() - t.Setenv("XDG_CACHE_HOME", cacheHome) - srv := NewServer(config.Default()) t.Run("index page", func(t *testing.T) { @@ -41,20 +28,24 @@ func TestServer(t *testing.T) { } body := rec.Body.String() // config.Default() -> UILanguage "en", so the gospel heading's part - // label is localised to "Gospel" (render.LocalizeHeading); the - // citation stays exactly as scraped. + // label is localised to "Gospel" (render.LocalizeHeading). if !strings.Contains(body, "Gospel") { t.Errorf("body missing reading heading: %q", body) } + // ?v=wuj -> the gospel is rendered from the Wujek corpus ("grobu" is + // distinctly Polish Wujek verse text, not Latin/English). + if !strings.Contains(body, "grobu") { + t.Errorf("body missing Wujek verse text: %q", body) + } if !strings.Contains(body, "htmx") { t.Errorf("body missing htmx reference") } if !strings.Contains(body, `id="theme"`) { t.Errorf("body missing theme <link>") } - // Name is source-language (Polish), never translated, even - // though the surrounding chrome is English -- see RenderReadings. - if !strings.Contains(body, `class="dayinfo"`) || !strings.Contains(body, "Święto św. Marii Magdaleny") { + // The offline engine localises the celebration name to the UI language + // (en): 2026-07-22 is Saint Mary Magdalene. + if !strings.Contains(body, `class="dayinfo"`) || !strings.Contains(body, "Saint Mary Magdalene") { t.Errorf("body missing day-info header: %q", body) } }) @@ -187,18 +178,7 @@ func TestServer(t *testing.T) { // Regression coverage for the ?date= path-traversal finding: resolveQuery // must reject anything that isn't YYYY-MM-DD and fall back to today(), // the same "normalize, don't trust" pattern requestDisplay already uses. - t.Run("date path traversal does not read a planted cache file", func(t *testing.T) { - // cacheDir() == filepath.Join(cacheHome, "lectio"), so - // filepath.Join(cacheDir(), "../evil"+".json") resolves to - // cacheHome/evil.json -- one level *above* the real cache dir, and - // only reachable via an unvalidated "../" date. If the marker below - // ever appears in a response, liturgy.Load read this planted file. - evilPath := filepath.Join(cacheHome, "evil.json") - evilJSON := `[{"Heading":"LEAKED-VIA-TRAVERSAL","PartID":"ewangelia","Paragraphs":[["s"]]}]` - if err := os.WriteFile(evilPath, []byte(evilJSON), 0o644); err != nil { - t.Fatal(err) - } - + t.Run("date path traversal falls back to today, same as omitting date", func(t *testing.T) { baseline := httptest.NewRecorder() srv.ServeHTTP(baseline, httptest.NewRequest("GET", "/readings?v=wuj", nil)) // no date -> today() if baseline.Code != http.StatusOK { @@ -210,12 +190,8 @@ func TestServer(t *testing.T) { if rec.Code != http.StatusOK { t.Fatalf("status = %d, want 200", rec.Code) } - body := rec.Body.String() - if strings.Contains(body, "LEAKED-VIA-TRAVERSAL") { - t.Fatalf("traversal date reached the planted cache file outside the cache dir: %q", body) - } - if body != baseline.Body.String() { - t.Errorf("traversal date did not fall back to today() identically to omitting date\n got: %q\nwant: %q", body, baseline.Body.String()) + if rec.Body.String() != baseline.Body.String() { + t.Errorf("traversal date did not fall back to today() identically to omitting date\n got: %q\nwant: %q", rec.Body.String(), baseline.Body.String()) } }) @@ -234,23 +210,21 @@ func TestServer(t *testing.T) { }) } -// TestBTHiddenForTraditional checks index.html's server-side initial-hidden -// state for the "bt" version checkbox: hidden (inline style) when the -// lectionary is traditional (bt is meaningless for missalemeum -- see -// render.EffectiveVersions), present and visible otherwise. This is -// presentation-only: it does not touch which versions actually load. -func TestBTHiddenForTraditional(t *testing.T) { +// TestBTCheckboxRemoved checks index.html no longer renders a "bt" version +// checkbox (the niedziela.pl corpus was retired; bibleVersions is now +// wuj,vul,grb,drb) for either lectionary, while the real version boxes remain. +func TestBTCheckboxRemoved(t *testing.T) { srv := NewServer(config.Default()) - trad := httptest.NewRecorder() - srv.ServeHTTP(trad, httptest.NewRequest("GET", "/?lectionary=traditional", nil)) - if !strings.Contains(trad.Body.String(), `id="ver-bt" style="display:none"`) { - t.Errorf("bt checkbox not hidden for traditional") - } - modern := httptest.NewRecorder() - srv.ServeHTTP(modern, httptest.NewRequest("GET", "/?lectionary=new", nil)) - b := modern.Body.String() - if !strings.Contains(b, `id="ver-bt">`) || strings.Contains(b, `id="ver-bt" style="display:none"`) { - t.Errorf("bt checkbox should be visible for modern") + for _, lect := range []string{"traditional", "new"} { + rec := httptest.NewRecorder() + srv.ServeHTTP(rec, httptest.NewRequest("GET", "/?lectionary="+lect, nil)) + b := rec.Body.String() + if strings.Contains(b, `id="ver-bt"`) { + t.Errorf("%s: bt checkbox should no longer be rendered", lect) + } + if !strings.Contains(b, `id="ver-wuj"`) { + t.Errorf("%s: wuj checkbox missing", lect) + } } } @@ -325,17 +299,6 @@ func TestRenderOrErrorNoSectionsLang(t *testing.T) { // TestIndexHTMLLangAttribute checks index.html's <html lang="..."> follows // cfg.UILanguage (finding §6) instead of being hardcoded "pl". func TestIndexHTMLLangAttribute(t *testing.T) { - html, err := os.ReadFile("../liturgy/testdata/2026-07-22.html") - if err != nil { - t.Fatal(err) - } - fixtureServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Write(html) - })) - defer fixtureServer.Close() - liturgy.SetBaseURL(fixtureServer.URL + "/liturgia/%s/Ewangelia") - t.Setenv("XDG_CACHE_HOME", t.TempDir()) - cfg := config.Default() cfg.UILanguage = "en" rec := httptest.NewRecorder() @@ -422,11 +385,11 @@ func TestVsetEmptyShowsNothing(t *testing.T) { t.Errorf("readings with vset and no v should be empty, got %q", b) } - // Fresh visit (no vset): config default (bt for modern) box is checked. + // Fresh visit (no vset): the config default (vul) box is checked. fresh := httptest.NewRecorder() srv.ServeHTTP(fresh, httptest.NewRequest("GET", "/", nil)) - if !strings.Contains(fresh.Body.String(), `value="bt" checked`) { - t.Errorf("fresh visit should check the config default (bt) version box") + if !strings.Contains(fresh.Body.String(), `value="vul" checked`) { + t.Errorf("fresh visit should check the config default (vul) version box") } // Full page with vset and no v: no VERSION box checked (mono may be). @@ -439,32 +402,31 @@ func TestVsetEmptyShowsNothing(t *testing.T) { } } -// TestTraditionalDropsPhantomBT guards the traditional case of "no version -> -// nothing": a phantom checked-but-hidden bt (carried over from modern) must not -// substitute to wuj on an explicit form submit, but a fresh visit keeps the -// bt->wuj default. -func TestTraditionalDropsPhantomBT(t *testing.T) { +// TestBTSubstitutesToWuj: the legacy "bt" version has no corpus, so an explicit +// ?v=bt now renders the Wujek column instead (render.EffectiveVersions maps +// bt->wuj unconditionally, offline) for both lectionaries -- there is no longer +// a traditional-only "drop bt" special case. A fresh visit checks the config +// default (vul), never bt. +func TestBTSubstitutesToWuj(t *testing.T) { srv := NewServer(config.Default()) - // Explicit submit, only the phantom bt "checked": empty pane. - phantom := httptest.NewRecorder() - srv.ServeHTTP(phantom, httptest.NewRequest("GET", "/readings?vset=1&lectionary=traditional&v=bt", nil)) - if b := strings.TrimSpace(phantom.Body.String()); b != "" { - t.Errorf("traditional vset+v=bt should be empty, got %d bytes", len(b)) - } - - // Explicit submit, bt phantom + a real corpus version: still renders it. - withWuj := httptest.NewRecorder() - srv.ServeHTTP(withWuj, httptest.NewRequest("GET", "/readings?vset=1&lectionary=traditional&v=bt&v=wuj", nil)) - if !strings.Contains(withWuj.Body.String(), "block") { - t.Errorf("traditional vset+v=bt+v=wuj should still render wuj") + for _, lect := range []string{"new", "traditional"} { + rec := httptest.NewRecorder() + srv.ServeHTTP(rec, httptest.NewRequest("GET", "/readings?vset=1&date=2026-07-22&lectionary="+lect+"&v=bt", nil)) + b := rec.Body.String() + if strings.TrimSpace(b) == "" { + t.Errorf("%s: vset+v=bt should substitute wuj and render, got empty", lect) + } + if !strings.Contains(b, "Wujek") { + t.Errorf("%s: vset+v=bt should render the Wujek column: %q", lect, b) + } } - // Fresh visit (no vset): the bt->wuj default is kept and wuj is checked. + // Fresh traditional visit (no vset): the config default (vul) is checked. fresh := httptest.NewRecorder() srv.ServeHTTP(fresh, httptest.NewRequest("GET", "/?lectionary=traditional", nil)) - if !strings.Contains(fresh.Body.String(), `value="wuj" checked`) { - t.Errorf("fresh traditional visit should default to wuj (checked)") + if !strings.Contains(fresh.Body.String(), `value="vul" checked`) { + t.Errorf("fresh traditional visit should default to vul (checked)") } } @@ -521,13 +483,12 @@ func TestSettingsPostAppliesLive(t *testing.T) { form := url.Values{} form.Set("lectionary", "new") - form.Set("traditional_lang", "pl") form.Set("ui_language", "pl") // change it form.Set("sigla_style", "auto") form.Set("web_display", "vertical") form.Set("web_theme", "transfiguration") - form.Set("default_version", "bt") - form["versions"] = []string{"bt", "wuj", "vul", "grb", "drb"} + form.Set("default_version", "vul") + form["versions"] = []string{"wuj", "vul", "grb", "drb"} form.Set("books", string(bibleDefaultBooks())) post := httptest.NewRequest("POST", "/settings", strings.NewReader(form.Encode())) @@ -554,8 +515,8 @@ func TestSettingsPostInvalidBooks(t *testing.T) { form.Set("ui_language", "en") form.Set("web_display", "vertical") form.Set("web_theme", "transfiguration") - form.Set("default_version", "bt") - form["versions"] = []string{"bt"} + form.Set("default_version", "vul") + form["versions"] = []string{"wuj"} form.Set("books", "this is not [valid toml") post := httptest.NewRequest("POST", "/settings", strings.NewReader(form.Encode())) post.Header.Set("Content-Type", "application/x-www-form-urlencoded") @@ -584,8 +545,8 @@ func TestSettingsPostEmptyBooksPreservesFile(t *testing.T) { form.Set("ui_language", "en") form.Set("web_display", "vertical") form.Set("web_theme", "transfiguration") - form.Set("default_version", "bt") - form["versions"] = []string{"bt"} // no "books" field + form.Set("default_version", "vul") + form["versions"] = []string{"wuj"} // no "books" field post := httptest.NewRequest("POST", "/settings", strings.NewReader(form.Encode())) post.Header.Set("Content-Type", "application/x-www-form-urlencoded") rec := httptest.NewRecorder() @@ -634,15 +595,21 @@ func TestBookmarksFlow(t *testing.T) { } } -func TestExportNoReadings(t *testing.T) { - t.Setenv("XDG_CACHE_HOME", t.TempDir()) - cfg := config.Default() - cfg.Offline = true // no network; uncached date -> no readings - srv := NewServer(cfg) +// TestExportSucceeds: the offline engine computes readings for any valid date, +// so /export always has content to render (there is no "no readings" 404/500 +// path for a normal date anymore). Even a far-future date exports successfully. +func TestExportSucceeds(t *testing.T) { + srv := NewServer(config.Default()) rec := httptest.NewRecorder() srv.ServeHTTP(rec, httptest.NewRequest("GET", "/export?fmt=md&date=2099-01-01", nil)) - if rec.Code != http.StatusNotFound && rec.Code != http.StatusInternalServerError { - t.Errorf("export with no readings status=%d (want 404/500)", rec.Code) + if rec.Code != http.StatusOK { + t.Fatalf("export status=%d (want 200), body=%q", rec.Code, rec.Body.String()) + } + if ct := rec.Header().Get("Content-Type"); !strings.Contains(ct, "markdown") { + t.Errorf("Content-Type = %q, want markdown", ct) + } + if !strings.Contains(rec.Body.String(), "## Gospel") { + t.Errorf("export body missing a gospel section:\n%s", rec.Body.String()) } } diff --git a/internal/web/templates/index.html b/internal/web/templates/index.html index c8a48ed..762ed7b 100644 --- a/internal/web/templates/index.html +++ b/internal/web/templates/index.html @@ -36,14 +36,14 @@ </span> <label>{{.L.Lectionary}} - <select name="lectionary" onchange="var b=document.getElementById('ver-bt');if(b)b.style.display=this.value==='traditional'?'none':'';"> + <select name="lectionary"> <option value="new" {{if eq .Lectionary "new"}}selected{{end}}>{{.L.OptModern}}</option> <option value="traditional" {{if eq .Lectionary "traditional"}}selected{{end}}>{{.L.OptTraditional}}</option> </select> </label> {{range .VersionOpts}} - <label id="ver-{{.Code}}"{{if and (eq .Code "bt") (eq $.Lectionary "traditional")}} style="display:none"{{end}}><input type="checkbox" name="v" value="{{.Code}}" {{if .Checked}}checked{{end}}> {{.Code}}</label> + <label id="ver-{{.Code}}"><input type="checkbox" name="v" value="{{.Code}}" {{if .Checked}}checked{{end}}> {{.Code}}</label> {{end}} <label>{{.L.Parts}} diff --git a/internal/web/templates/settings.html b/internal/web/templates/settings.html index e2ee39e..f4fae47 100644 --- a/internal/web/templates/settings.html +++ b/internal/web/templates/settings.html @@ -30,13 +30,6 @@ </select> </label> - <label>{{.L.WebTradLang}} - <select name="traditional_lang"> - <option value="pl" {{if eq .Cfg.TraditionalLang "pl"}}selected{{end}}>pl</option> - <option value="en" {{if eq .Cfg.TraditionalLang "en"}}selected{{end}}>en</option> - </select> - </label> - <label>{{.L.WebUILang}} <select name="ui_language"> <option value="en" {{if eq .Cfg.UILanguage "en"}}selected{{end}}>en</option> |
