From 7b220084cf3951c8cde0582efdfcf628afc64336 Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Tue, 28 Jul 2026 12:50:31 +0200 Subject: refactor: remove the niedziela/missalemeum scrapers, bt, traditional_lang The daily view now computes entirely offline (previous commit), so retire the network path and everything that served it: - Delete internal/tradlit (missalemeum) and the niedziela scraper from internal/liturgy (fetch/store/parse + fixtures); keep Section, DayInfo and ExtractCitation. - Remove the "bt" version everywhere (render gatherBT + branches, config, i18n, web form, TUI) and bible.ToEnglishRef (Polish citation converter). A legacy config carrying "bt" migrates to "wuj" on load (config.migrateBT). - Remove the traditional_lang config field and the -g/--lang flag from all three binaries. - Drop the now-dead flags -R/--refresh, -o/--offline, -u/--update, -C/--clean and the harvest/clean commands. - New defaults: versions = wuj,vul,grb,drb; default_version = vul. Update the README (offline-by-design, no harvest/update), help text, and stale niedziela/bt doc comments. Tests updated for the offline reality; go test ./... and go vet ./... are clean, all three binaries build and run offline (OF + EF, compare, web). --- internal/liturgy/citation.go | 21 + internal/liturgy/clean_test.go | 75 - internal/liturgy/fetch.go | 259 --- internal/liturgy/fetch_test.go | 68 - internal/liturgy/parse.go | 209 --- internal/liturgy/parse_test.go | 176 -- internal/liturgy/section.go | 21 +- internal/liturgy/store.go | 215 --- internal/liturgy/store_test.go | 100 - internal/liturgy/testdata/2026-06-22.html | 2713 --------------------------- internal/liturgy/testdata/2026-07-22.html | 2831 ----------------------------- 11 files changed, 31 insertions(+), 6657 deletions(-) create mode 100644 internal/liturgy/citation.go delete mode 100644 internal/liturgy/clean_test.go delete mode 100644 internal/liturgy/fetch.go delete mode 100644 internal/liturgy/fetch_test.go delete mode 100644 internal/liturgy/parse.go delete mode 100644 internal/liturgy/parse_test.go delete mode 100644 internal/liturgy/store.go delete mode 100644 internal/liturgy/store_test.go delete mode 100644 internal/liturgy/testdata/2026-06-22.html delete mode 100644 internal/liturgy/testdata/2026-07-22.html (limited to 'internal/liturgy') 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..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": "old", - "2020-01-01.json": `[{"Heading":"old"}]`, - "2020-01-01.trad.pl.json": `[{"info":{},"sections":[]}]`, - recent + ".html": "recent", - 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(): ".html", ".json", and -// ".trad..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: -// ".html", ".json", or the traditional lectionary's -// ".trad..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)`) - tagRe = regexp.MustCompile(`<[^>]+>`) - wsRe = regexp.MustCompile(`[ \t]+`) - h2Re = regexp.MustCompile(`(?s)

(.*?)

`) - h4Re = regexp.MustCompile(`(?s)

(.*?)

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

(.*?)

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

...

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

\s*(.*?)\s*

`) - - // dayColourRe matches niedziela.pl's "Kolor szat: " vestment-colour - // line, tolerating the / markup wrapped around the colour - // word on the page (see internal/liturgy/testdata/2026-07-22.html). - dayColourRe = regexp.MustCompile(`Kolor szat:\s*(?:<[^>]+>\s*)*([\p{L}]+)`) -) - -// modernColours maps niedziela.pl's Polish vestment-colour words to -// DayInfo's normalized colour names; anything not listed here (including a -// multi-option line like "zielony albo biały albo czerwony", which matches -// only its first word) is left for the caller to treat as "" if absent. -var modernColours = map[string]string{ - "biały": "white", - "zielony": "green", - "fioletowy": "violet", - "czerwony": "red", - "różowy": "rose", -} - -// panePattern matches the opening tag of the tab-pane div carrying the given -// tab id, e.g. `
`. -func panePattern(tab string) *regexp.Regexp { - return regexp.MustCompile(`
`) -} - -// htmlToLines turns an HTML fragment into a list of non-empty text lines. -//
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, `
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

NAME

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

...

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 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("redesigned") - if info != (DayInfo{}) { - t.Errorf("ParseDayInfo(unrecognised) = %+v, want zero value", info) - } -} - -func TestParseLayoutChange(t *testing.T) { - if _, err := Parse("redesigned"); 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("Przykro nam")) // 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 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - Niezbędnik katolika - czytania na 2026-06-22 - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- -
- - - - -
- - - -
-
- - - - - - - - -

- Czytania liturgiczne na dziś; - Rok A, II

-
- -
- - - -
- -
- - - - -

Dzień Powszedni albo wspomnienie św. Paulina z Noli, biskupa albo wspomnienie świętych męczenników -Jana Fishera, biskupa, i Tomasza More'a

- -

Kolor szat: zielony albo biały albo czerwony

- - - - - - - - - - - -
-
- - - - -
- -
- - -

1. czytanie (2 Krl 17, 5-8. 13-15a. 18)

Zdobycie Samarii przez Asyryjczyków

Czytanie z Drugiej Księgi Królewskiej

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.

-

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.

-

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ł.

-

Wtedy Pan zapłonął gwałtownym gniewem przeciw Izraelowi i odrzucił go sprzed swego oblicza. Pozostało tylko samo pokolenie Judy.

- -

Psalm (Ps 60 (59), 3-4. 5 i 12. 13-14 (R.: por. 7b))

Usłysz nas, Panie, wspomóż Twą prawicą

Odrzuciłeś nas i złamałeś, Boże, * -
rozgniewałeś się, lecz powróć do nas! -
Wstrząsnąłeś i rozdarłeś ziemię, * -
ulecz jej rozdarcia, albowiem się chwieje.

Usłysz nas, Panie, wspomóż Twą prawicą

- -

Ludowi Twemu zgotowałeś los twardy, * -
napoiłeś nas winem, które moc odbiera. -
Czyż nie Ty, Boże, który nas odrzuciłeś * -
i już nie wychodzisz z naszymi wojskami?

Usłysz nas, Panie, wspomóż Twą prawicą

- -

Daj nam pomoc przeciw nieprzyjacielowi, * -
bo ludzkie wsparcie jest zawodne. -
Dokonamy w Bogu czynów pełnych mocy, * -
a On podepcze naszych nieprzyjaciół.

Usłysz nas, Panie, wspomóż Twą prawicą

- -

Aklamacja (Por. Hbr 4, 12)

Alleluja, alleluja, alleluja

Żywe jest słowo Boże i skuteczne, -
zdolne osądzić pragnienia i myśli serca.

Alleluja, alleluja, alleluja

- - -

Ewangelia (Mt 7, 1-5)

Usuń najpierw belkę ze swego oka

Słowa Ewangelii według Świętego Mateusza

Jezus powiedział do swoich uczniów:

-

«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ą.

-

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».

-
- - -
- -

1. czytanie (2 Krl 17, 5-8. 13-15a. 18)

Zdobycie Samarii przez Asyryjczyków

Czytanie z Drugiej Księgi Królewskiej

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.

-

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.

-

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ł.

-

Wtedy Pan zapłonął gwałtownym gniewem przeciw Izraelowi i odrzucił go sprzed swego oblicza. Pozostało tylko samo pokolenie Judy.

-
- -
- -

Psalm (Ps 60 (59), 3-4. 5 i 12. 13-14 (R.: por. 7b))

Usłysz nas, Panie, wspomóż Twą prawicą

Odrzuciłeś nas i złamałeś, Boże, * -
rozgniewałeś się, lecz powróć do nas! -
Wstrząsnąłeś i rozdarłeś ziemię, * -
ulecz jej rozdarcia, albowiem się chwieje.

Usłysz nas, Panie, wspomóż Twą prawicą

- -

Ludowi Twemu zgotowałeś los twardy, * -
napoiłeś nas winem, które moc odbiera. -
Czyż nie Ty, Boże, który nas odrzuciłeś * -
i już nie wychodzisz z naszymi wojskami?

Usłysz nas, Panie, wspomóż Twą prawicą

- -

Daj nam pomoc przeciw nieprzyjacielowi, * -
bo ludzkie wsparcie jest zawodne. -
Dokonamy w Bogu czynów pełnych mocy, * -
a On podepcze naszych nieprzyjaciół.

Usłysz nas, Panie, wspomóż Twą prawicą

-
- -
- -

Aklamacja (Por. Hbr 4, 12)

Alleluja, alleluja, alleluja

Żywe jest słowo Boże i skuteczne, -
zdolne osądzić pragnienia i myśli serca.

Alleluja, alleluja, alleluja

- -
- - - -
- - - - -

Ewangelia (Mt 7, 1-5)

Usuń najpierw belkę ze swego oka

Słowa Ewangelii według Świętego Mateusza

Jezus powiedział do swoich uczniów:

-

«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ą.

-

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».

- -
- -
- -
- - - - - - -
-
- -
- - - - -
- -
- -

1. czytanie (2 Krl 17, 5-8. 13-15a. 18)

Zdobycie Samarii przez Asyryjczyków

Czytanie z Drugiej Księgi Królewskiej

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.

- -

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.

- -

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ł.

- -

Wtedy Pan zapłonął gwałtownym gniewem przeciw Izraelowi i odrzucił go od swego oblicza. Pozostało tylko samo pokolenie Judy.

- -

Psalm (Ps 60, 3-4. 5 i 12. 13-14)

Usłysz nas, Panie, wspomóż Twą prawicą

Odrzuciłeś nas i złamałeś, Boże, -
rozgniewałeś się, lecz powróć do nas. -
Wstrząsnąłeś i rozdarłeś ziemię, -
ulecz jej rozdarcia, albowiem się chwieje.

Usłysz nas, Panie, wspomóż Twą prawicą

- -

Ludowi Twemu zgotowałeś los twardy, -
napoiłeś nas winem, które moc odbiera. -
Czyż nie Ty, o Boże, nas odrzuciłeś -
i już nie wychodzisz, Boże, z naszymi wojskami?

Usłysz nas, Panie, wspomóż Twą prawicą

- -

Daj nam pomoc przeciw nieprzyjacielowi, -
bo ludzkie wsparcie jest zawodne. -
Dokonamy w Bogu czynów pełnych mocy, -
a On podepcze naszych nieprzyjaciół.

Usłysz nas, Panie, wspomóż Twą prawicą

- -

Aklamacja (Hbr 4, 12)

Alleluja, alleluja, alleluja

Żywe jest słowo Boże i skuteczne, -
zdolne osądzić pragnienia i myśli serca.

Alleluja, alleluja, alleluja

- - -

Ewangelia (Mt 7, 1-5)

Drzazga i belka

Słowa Ewangelii według świętego Mateusza

Jezus powiedział do swoich uczniów:

-

„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ą.

- -

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”.

-
- - -
- -

1. czytanie (2 Krl 17, 5-8. 13-15a. 18)

Zdobycie Samarii przez Asyryjczyków

Czytanie z Drugiej Księgi Królewskiej

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.

- -

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.

- -

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ł.

- -

Wtedy Pan zapłonął gwałtownym gniewem przeciw Izraelowi i odrzucił go od swego oblicza. Pozostało tylko samo pokolenie Judy.

-
- -
- -

Psalm (Ps 60, 3-4. 5 i 12. 13-14)

Usłysz nas, Panie, wspomóż Twą prawicą

Odrzuciłeś nas i złamałeś, Boże, -
rozgniewałeś się, lecz powróć do nas. -
Wstrząsnąłeś i rozdarłeś ziemię, -
ulecz jej rozdarcia, albowiem się chwieje.

Usłysz nas, Panie, wspomóż Twą prawicą

- -

Ludowi Twemu zgotowałeś los twardy, -
napoiłeś nas winem, które moc odbiera. -
Czyż nie Ty, o Boże, nas odrzuciłeś -
i już nie wychodzisz, Boże, z naszymi wojskami?

Usłysz nas, Panie, wspomóż Twą prawicą

- -

Daj nam pomoc przeciw nieprzyjacielowi, -
bo ludzkie wsparcie jest zawodne. -
Dokonamy w Bogu czynów pełnych mocy, -
a On podepcze naszych nieprzyjaciół.

Usłysz nas, Panie, wspomóż Twą prawicą

-
- -
- -

Aklamacja (Hbr 4, 12)

Alleluja, alleluja, alleluja

Żywe jest słowo Boże i skuteczne, -
zdolne osądzić pragnienia i myśli serca.

Alleluja, alleluja, alleluja

- -
- - - -
- - - - -

Ewangelia (Mt 7, 1-5)

Drzazga i belka

Słowa Ewangelii według świętego Mateusza

Jezus powiedział do swoich uczniów:

-

„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ą.

- -

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”.

- -
- -
- -
- - - - - - - -
-
- -
- - - - -
-
-

Polecamy

-
- -
- - -

Czytania Liturgiczne pochodzą z Lekcjonarza wydanego przez:
Wydawnictwo Pallottinum - -

- -
-
-
-
- -
-
- -

Pomóż w rozwoju serwisu

-
-
- - -

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.
Zostań naszym patronem i ofiaruj nam wsparcie finansowe.

- -
-

Na funkcjonowanie serwisu do końca II kwartału: 144 000 zł

-
-
62%
-
-

Uzbieraliśmy: 89 471 zł

- - -
- - -
-
- -
- -
-
-
- -
-
- -

Nowości w Rafaelu

-
-
- - - -
-
- -
-
-

Odkrywanie wieczności - Peter Seewald -
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.
ZOBACZ -

-
- -
- - -
- -
-
-
-
-
- -

Polecamy

-
-
- - - - - -
-
- -
-
-

Credo krok po kroku -
- -
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ć.

-

- - Zobacz - -

-
-
- - -
- -
-
-
- -
- - - -
-
- -

22 czerwca, poniedziałek

-
-
- - - -
-
-

XII Tydzień zwykły

-

Dzień Powszedni albo wspomnienie św. Paulina z Noli, biskupa albo wspomnienie świętych męczenników -Jana Fishera, biskupa, i Tomasza More'a

- -

- Rok A, II
Kolor szat: zielony albo biały albo czerwony
Liturgia dnia - - -

-

- - - 173. dzień roku - -
- - 04:12 - 21:03 - - - -

-

- Imieniny: Paulina, Jana, Tomasza -

-
-
-

Ważne

- -

Patron dnia

-

Wydarzyło się...

-
  • św. Kamil de Lellis został ogłoszony przez papieża Leona XIII patronem wszystkich chorych i szpitali (1886 r.)
  • • odbyła się 9-godzinna podróż apostolska Jana Pawła II do Bośni i Hercegowiny (2003 r.)
- - -
- -
-
- -
- -
-
-
- - - - - - - - -
-
-
-
- - -

-
- - - - -
- -
-
- -
-
- -
-
- -
-

- - - - Kalendarz na rok 2026 -

- - - -
- -
-
-
- -
- - - - - - - -
- -
-
-
- -
-

W NOWYM NUMERZE NIEDZIELI

-
-
- -
-
-

Jasna Góra to mój drugi dom -
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ń.

-

- - - Zobacz - - Zamów e-wydanie - -

-
-
-
-
-

Księgarnia Niedziela

-
-
- -
-
-

Nasz Benedykt czyli kwiatki Josepha Ratzingera -
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ą.

-

- - Zobacz - -

-
-
-
- -
-
-
- -
- -
-
- -

Liturgia na Twojej stronie WWW

-
-
- - -

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.

Zobacz

- -
-
- -
- -
-
-
- - - -
-
- - - - - - - - - - -
-
-

W związku z tym, iż od dnia 25 maja 2018 roku obowiązuje 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 oraz uchylenia Dyrektywy 95/46/WE (ogólne rozporządzenie o ochronie danych) 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. -
Więcej o polityce prywatności czytaj TUTAJ. -

-

Akceptuję

-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - 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 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - Niezbędnik katolika - czytania na 2026-07-22 - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - -
- -
- - - - -
- - - -
-
- - - - - - - - -

- Czytania liturgiczne na dziś; - Rok A, II

-
- -
- - - -
- -
- - - - -

Święto św. Marii Magdaleny

- -

Kolor szat: biały

- - - - - - - - - - - -
-
- - - - -
- -
- - -

1. czytanie (Pnp 8, 6-7)

Jak śmierć potężna jest miłość

Czytanie z Księgi Pieśni nad pieśniami

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.

- -

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ą.

- -

Albo:

- - -

1. czytanie (2 Kor 5, 14-17)

Miłość Chrystusa przynagla nas

Czytanie z Drugiego listu świętego Pawła Apostoła do Koryntian

Bracia:

- -

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ł.

- -

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.

- -

W kościołach, które obchodzą uroczystość, powyższe czytanie czyta się jako drugie.

- - -

Psalm (Ps 63 (62), 2. 3-4. 5-6. 8-9 (R.: por. 2ab))

Ciebie, mój Boże, pragnie moja dusza

Boże, mój Boże, szukam Ciebie * -
i pragnie Ciebie moja dusza. -
Ciało moje tęskni za Tobą * -
jak zeschła ziemia łaknąca wody.

Ciebie, mój Boże, pragnie moja dusza

- -

Oto wpatruję się w Ciebie w świątyni, * -
by ujrzeć Twą potęgę i chwałę. -
Twoja łaska jest cenniejsza od życia, * -
więc sławić Cię będą moje wargi.

Ciebie, mój Boże, pragnie moja dusza

- -

Będę Cię wielbił przez całe me życie * -
i wzniosę ręce w imię Twoje. -
Moja dusza syci się obficie, * -
a usta Cię wielbią radosnymi wargami.

Ciebie, mój Boże, pragnie moja dusza

- -

Bo stałeś się dla mnie pomocą * -
i w cieniu Twych skrzydeł wołam radośnie: -
Do Ciebie lgnie moja dusza, * -
prawica Twoja mnie wspiera.

Ciebie, mój Boże, pragnie moja dusza

- -

Aklamacja (por. J 20, 11)

Alleluja, alleluja, alleluja

Mario, Ty powiedz, coś w drodze widziała? -
Jam zmartwychwstałego blask chwały ujrzała. -
Żywego już Pana widziałam grób pusty -
i świadków anielskich, i odzież, i chusty.

Alleluja, alleluja, alleluja

- - -

Ewangelia (J 20, 1. 11-18)

Niewiasto, czemu płaczesz? Kogo szukasz?

Słowa Ewangelii według świętego Jana

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.

- -

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.

- -

I rzekli do niej: «Niewiasto, czemu płaczesz?».

- -

Odpowiedziała im: «Zabrano Pana mego i nie wiem, gdzie Go położono».

- -

Gdy to powiedziała, odwróciła się i ujrzała stojącego Jezusa, ale nie wiedziała, że to Jezus.

- -

Rzekł do niej Jezus: «Niewiasto, czemu płaczesz? Kogo szukasz?».

- -

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ę».

- -

Jezus rzekł do niej: «Mario!». A ona, obróciwszy się, powiedziała do Niego po hebrajsku: «Rabbuni», to znaczy: Mój Nauczycielu!

- -

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”».

- -

Poszła Maria Magdalena oznajmiając uczniom: «Widziałam Pana», i co jej powiedział.

- -
- - -
- -

1. czytanie (Pnp 8, 6-7)

Jak śmierć potężna jest miłość

Czytanie z Księgi Pieśni nad pieśniami

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.

- -

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ą.

- -

Albo:

- -
- -
- -

1. czytanie (2 Kor 5, 14-17)

Miłość Chrystusa przynagla nas

Czytanie z Drugiego listu świętego Pawła Apostoła do Koryntian

Bracia:

- -

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ł.

- -

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.

- -

W kościołach, które obchodzą uroczystość, powyższe czytanie czyta się jako drugie.

- -
- -
- -

Psalm (Ps 63 (62), 2. 3-4. 5-6. 8-9 (R.: por. 2ab))

Ciebie, mój Boże, pragnie moja dusza

Boże, mój Boże, szukam Ciebie * -
i pragnie Ciebie moja dusza. -
Ciało moje tęskni za Tobą * -
jak zeschła ziemia łaknąca wody.

Ciebie, mój Boże, pragnie moja dusza

- -

Oto wpatruję się w Ciebie w świątyni, * -
by ujrzeć Twą potęgę i chwałę. -
Twoja łaska jest cenniejsza od życia, * -
więc sławić Cię będą moje wargi.

Ciebie, mój Boże, pragnie moja dusza

- -

Będę Cię wielbił przez całe me życie * -
i wzniosę ręce w imię Twoje. -
Moja dusza syci się obficie, * -
a usta Cię wielbią radosnymi wargami.

Ciebie, mój Boże, pragnie moja dusza

- -

Bo stałeś się dla mnie pomocą * -
i w cieniu Twych skrzydeł wołam radośnie: -
Do Ciebie lgnie moja dusza, * -
prawica Twoja mnie wspiera.

Ciebie, mój Boże, pragnie moja dusza

-
- -
- -

Aklamacja (por. J 20, 11)

Alleluja, alleluja, alleluja

Mario, Ty powiedz, coś w drodze widziała? -
Jam zmartwychwstałego blask chwały ujrzała. -
Żywego już Pana widziałam grób pusty -
i świadków anielskich, i odzież, i chusty.

Alleluja, alleluja, alleluja

- -
- - - -
- - - - - -

Ewangelia (J 20, 1. 11-18)

Niewiasto, czemu płaczesz? Kogo szukasz?

Słowa Ewangelii według świętego Jana

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.

- -

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.

- -

I rzekli do niej: «Niewiasto, czemu płaczesz?».

- -

Odpowiedziała im: «Zabrano Pana mego i nie wiem, gdzie Go położono».

- -

Gdy to powiedziała, odwróciła się i ujrzała stojącego Jezusa, ale nie wiedziała, że to Jezus.

- -

Rzekł do niej Jezus: «Niewiasto, czemu płaczesz? Kogo szukasz?».

- -

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ę».

- -

Jezus rzekł do niej: «Mario!». A ona, obróciwszy się, powiedziała do Niego po hebrajsku: «Rabbuni», to znaczy: Mój Nauczycielu!

- -

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”».

- -

Poszła Maria Magdalena oznajmiając uczniom: «Widziałam Pana», i co jej powiedział.

- - -
- -
- -
- - - - - - -
-
- -
- - - - -
- -
- -

1. czytanie (Pnp 8, 6-7)

Jak śmierć potężna jest miłość

Czytanie z Księgi Pieśni nad pieśniami

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.

-

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.

- -

Albo:

1. czytanie (2 Kor 5, 14-17)

Miłość Chrystusa przynagla nas

Czytanie z Drugiego listu świętego Pawła Apostoła -do Koryntian

Bracia:

-

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ł.

-

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.

- -

W kościołach, które obchodzą uroczystość, powyższe czytanie czyta się jako drugie.

Psalm (Ps 63, 2. 3-4. 5-6. 8-9 (R.: por. 2))

Ciebie, mój Boże, pragnie moja dusza

Boże mój, Boże, szukam Ciebie * -
i pragnie Ciebie moja dusza. -
Ciało moje tęskni za Tobą, * -
jak ziemia zeschła i łaknąca wody.

Ciebie, mój Boże, pragnie moja dusza

- -

Oto wpatruję się w Ciebie w świątyni, * -
by ujrzeć Twą potęgę i chwałę. -
Twoja łaska jest cenniejsza od życia, * -
więc sławić Cię będą moje wargi.

Ciebie, mój Boże, pragnie moja dusza

- -

Będę Cię wielbił przez całe me życie * -
i wzniosę ręce w imię Twoje. -
Moja dusza syci się obficie, * -
a usta Cię wielbią radosnymi wargami.

Ciebie, mój Boże, pragnie moja dusza

- -

Bo stałeś się dla mnie pomocą * -
i w cieniu Twych skrzydeł wołam radośnie: -
Do Ciebie lgnie moja dusza, * -
prawica Twoja mnie wspiera.

Ciebie, mój Boże, pragnie moja dusza

- -

Aklamacja (por. J 20, 11)

Alleluja, alleluja, alleluja

Maryjo, Ty powiedz, coś w drodze widziała? -
Jam zmartwychwstałego blask chwały ujrzała. -
Żywego już Pana widziałam grób pusty -
I świadków anielskich, i odzież, i chusty.

Alleluja, alleluja, alleluja

- - -

Ewangelia (J 20, 1. 11-18)

Zmartwychwstały Chrystus ukazuje się Magdalenie

Słowa Ewangelii według świętego Jana

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.

-

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.

-

I rzekli do niej: «Niewiasto, czemu płaczesz?».

-

Odpowiedziała im: «Zabrano Pana mego i nie wiem, gdzie Go położono».

-

Gdy to powiedziała, odwróciła się i ujrzała stojącego Jezusa, ale nie wiedziała, że to Jezus.

-

Rzekł do niej Jezus: «Niewiasto, czemu płaczesz? Kogo szukasz?».

-

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ę».

-

Jezus rzekł do niej: «Mario!».

-

A ona obróciwszy się powiedziała do Niego po hebrajsku: «Rabbuni», to znaczy: «Nauczycielu».

-

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”».

-

Poszła Maria Magdalena oznajmiając uczniom: «Widziałam Pana i to mi powiedział».

-
- - -
- -

1. czytanie (Pnp 8, 6-7)

Jak śmierć potężna jest miłość

Czytanie z Księgi Pieśni nad pieśniami

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.

-

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.

-
- -
- -

Albo:

1. czytanie (2 Kor 5, 14-17)

Miłość Chrystusa przynagla nas

Czytanie z Drugiego listu świętego Pawła Apostoła -do Koryntian

Bracia:

-

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ł.

-

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.

-
- -
- -

W kościołach, które obchodzą uroczystość, powyższe czytanie czyta się jako drugie.

Psalm (Ps 63, 2. 3-4. 5-6. 8-9 (R.: por. 2))

Ciebie, mój Boże, pragnie moja dusza

Boże mój, Boże, szukam Ciebie * -
i pragnie Ciebie moja dusza. -
Ciało moje tęskni za Tobą, * -
jak ziemia zeschła i łaknąca wody.

Ciebie, mój Boże, pragnie moja dusza

- -

Oto wpatruję się w Ciebie w świątyni, * -
by ujrzeć Twą potęgę i chwałę. -
Twoja łaska jest cenniejsza od życia, * -
więc sławić Cię będą moje wargi.

Ciebie, mój Boże, pragnie moja dusza

- -

Będę Cię wielbił przez całe me życie * -
i wzniosę ręce w imię Twoje. -
Moja dusza syci się obficie, * -
a usta Cię wielbią radosnymi wargami.

Ciebie, mój Boże, pragnie moja dusza

- -

Bo stałeś się dla mnie pomocą * -
i w cieniu Twych skrzydeł wołam radośnie: -
Do Ciebie lgnie moja dusza, * -
prawica Twoja mnie wspiera.

Ciebie, mój Boże, pragnie moja dusza

-
- -
- -

Aklamacja (por. J 20, 11)

Alleluja, alleluja, alleluja

Maryjo, Ty powiedz, coś w drodze widziała? -
Jam zmartwychwstałego blask chwały ujrzała. -
Żywego już Pana widziałam grób pusty -
I świadków anielskich, i odzież, i chusty.

Alleluja, alleluja, alleluja

- -
- - - -
- - - - - -

Ewangelia (J 20, 1. 11-18)

Zmartwychwstały Chrystus ukazuje się Magdalenie

Słowa Ewangelii według świętego Jana

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.

-

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.

-

I rzekli do niej: «Niewiasto, czemu płaczesz?».

-

Odpowiedziała im: «Zabrano Pana mego i nie wiem, gdzie Go położono».

-

Gdy to powiedziała, odwróciła się i ujrzała stojącego Jezusa, ale nie wiedziała, że to Jezus.

-

Rzekł do niej Jezus: «Niewiasto, czemu płaczesz? Kogo szukasz?».

-

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ę».

-

Jezus rzekł do niej: «Mario!».

-

A ona obróciwszy się powiedziała do Niego po hebrajsku: «Rabbuni», to znaczy: «Nauczycielu».

-

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”».

-

Poszła Maria Magdalena oznajmiając uczniom: «Widziałam Pana i to mi powiedział».

- -
- -
- -
- - - - - - - -
-
- -
- - - - -
-
-

Polecamy

-
- -
- - -

Czytania Liturgiczne pochodzą z Lekcjonarza wydanego przez:
Wydawnictwo Pallottinum - -

- -
-
-
-
- -
-
- -

Pomóż w rozwoju serwisu

-
-
- - -

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.
Zostań naszym patronem i ofiaruj nam wsparcie finansowe.

- -
-

Na funkcjonowanie serwisu do końca II kwartału: 144 000 zł

-
-
93%
-
-

Uzbieraliśmy: 133 211 zł

- - -
- - -
-
- -
- -
-
-
- -
-
- -

Nowości w Rafaelu

-
-
- - - -
-
- -
-
-

Żywot Świętej Ryty. Patronka rzeczy nadzwyczajnych -
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.
ZOBACZ -

-
- -
- - -
- -
-
-
-
-
- -

Polecamy

-
-
- - - - - -
-
- -
-
-

Credo krok po kroku -
- -
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ć.

-

- - Zobacz - -

-
-
- - -
- -
-
-
- -
- - - -
-
- -

22 lipca, środa

-
-
- - - -
-
-

XVI Tydzień zwykły

-

Święto św. Marii Magdaleny

- -

- Rok A, II
Kolor szat: biały
Liturgia dnia - - -

-

- - - 203. dzień roku - -
- - 04:40 - 20:44 - - - -

-

- Imieniny: Marii, Magdaleny, Laurentego -

-
- - - -
- -
-
- -
- -
-
-
- - - - - - - - -
-
-
-
- - -

-
- - - - -
- -
-
- -
-
- -
-
- -
-

- - - - Kalendarz na rok 2026 -

- - - -
- -
-
-
- -
- - - - - - - -
- -
-
-
- -
-

W NOWYM NUMERZE BLIŻEJ ŻYCIA Z WIARĄ

-
-
- -
-
-

Pasja nie zna wieku -
Jeszcze kilkanaście lat temu nie podejrzewał, że drzemie w nim rzeźbiarz. Dziś jego figury zdobią domy rodziny i przyjaciół.

-

- - - Zobacz - - Zamów e-wydanie - -

-
-
-
-
-

Księgarnia Niedziela

-
-
- -
-
-

Psychoterapia Ewangelią 3. Reaktywacja -
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.

-

- - Zobacz - -

-
-
-
- -
-
-
- -
- -
-
- -

Liturgia na Twojej stronie WWW

-
-
- - -

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.

Zobacz

- -
-
- -
- -
-
-
- - - -
-
- - - - - - - - - - -
-
-

W związku z tym, iż od dnia 25 maja 2018 roku obowiązuje 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 oraz uchylenia Dyrektywy 95/46/WE (ogólne rozporządzenie o ochronie danych) 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. -
Więcej o polityce prywatności czytaj TUTAJ. -

-

Akceptuję

-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - -- cgit v1.3