From 22bfec8fc13a20a8d95a4609b4a02bb48acede5a Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Fri, 24 Jul 2026 13:35:24 +0200 Subject: citation: render --citation/--week gospel ref in the configured sigla dialect (bible.FormatRef); v0.11.0 --- internal/bible/booktable.go | 32 ++++++++++++++++++++++++++++++++ internal/bible/booktable_test.go | 31 +++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) (limited to 'internal/bible') diff --git a/internal/bible/booktable.go b/internal/bible/booktable.go index eb3b4e4..007e75e 100644 --- a/internal/bible/booktable.go +++ b/internal/bible/booktable.go @@ -141,6 +141,38 @@ func (t *BookTable) ParseRef(dialect, input string) (string, bool) { return "", false } +// shortcut returns the dialect's primary abbreviation (the first form) for a +// canonical book, or "" when the dialect has no entry for it. +func (t *BookTable) shortcut(dialect, canonical string) string { + if forms := t.forms[dialect][canonical]; len(forms) > 0 { + return forms[0] + } + return "" +} + +// FormatRef renders a canonical English reference ("John 20:1,11-18") in the +// dialect's sigla: the dialect's book shortcut plus its number style -- English +// "Jn 20:1,11-18" (colon chapter:verse, comma groups); Polish "J 20, 1. 11-18" +// (comma chapter, verse; period groups). It is the inverse of ParseRef's +// normalizeSigla. If canonicalRef can't be parsed or the book is not in the +// dialect, it is returned unchanged (a safe, still-readable fallback). +func (t *BookTable) FormatRef(dialect, canonicalRef string) string { + m := refRe.FindStringSubmatch(strings.TrimSpace(canonicalRef)) + if m == nil { + return canonicalRef + } + canon, chap, verses := m[1], m[2], m[3] + abbrev := t.shortcut(dialect, canon) + if abbrev == "" { + return canonicalRef + } + if dialect == "pl" { + verses = strings.ReplaceAll(verses, ",", ". ") // disjoint groups + return abbrev + " " + chap + ", " + verses + } + return abbrev + " " + chap + ":" + verses +} + // normalizeSigla rewrites a dialect's verse-reference tail into the colon/comma // form bible.Lookup expects: ":", groups comma-separated, ranges // with "-". Polish uses a comma (with or without a space) as the chapter/verse diff --git a/internal/bible/booktable_test.go b/internal/bible/booktable_test.go index ededad3..2a57d80 100644 --- a/internal/bible/booktable_test.go +++ b/internal/bible/booktable_test.go @@ -64,6 +64,37 @@ func TestParseRefDialects(t *testing.T) { } } +func TestFormatRef(t *testing.T) { + tbl, _ := LoadBookTable(nil) + cases := []struct { + dialect, canonical, want string + }{ + {"en", "John 20:1,11-18", "Jn 20:1,11-18"}, + {"pl", "John 20:1,11-18", "J 20, 1. 11-18"}, + {"en", "Matthew 13:18-23", "Matt 13:18-23"}, + {"pl", "Matthew 13:18-23", "Mt 13, 18-23"}, + {"en", "Luke 16:1-9", "Lk 16:1-9"}, + // Round-trip: ParseRef then FormatRef in the same dialect is stable. + } + for _, c := range cases { + if got := tbl.FormatRef(c.dialect, c.canonical); got != c.want { + t.Errorf("FormatRef(%q,%q)=%q want %q", c.dialect, c.canonical, got, c.want) + } + } + // Unparseable / unknown book -> unchanged (safe fallback). + if got := tbl.FormatRef("en", "not a ref"); got != "not a ref" { + t.Errorf("unparseable ref should be unchanged, got %q", got) + } + // Round-trip through both dialects. + canon, ok := tbl.ParseRef("pl", "J 20, 1. 11-18") + if !ok || canon != "John 20:1,11-18" { + t.Fatalf("ParseRef round-trip canon=%q ok=%v", canon, ok) + } + if got := tbl.FormatRef("pl", canon); got != "J 20, 1. 11-18" { + t.Errorf("pl round-trip = %q", got) + } +} + func TestBookTableMergeAndMalformed(t *testing.T) { // User adds an alias "Jhn" to English John; other books stay default. user := []byte("[en]\nJohn = [\"Jn\", \"Jhn\", \"John\"]\n") -- cgit v1.3