From a4eb9ed3cd93cbac493a873991dd5817906aad56 Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Thu, 20 Aug 2026 14:54:01 +0200 Subject: fix(citation): survey all three citation-bearing files, not just the lectionary The book table was built against data/ef/lectionary.sexp alone. That undercounts: sanctoral.sexp carries more citations than the lectionary and, together with commons.sexp, cites 21 book tokens the table was missing entirely (62 distinct tokens across all three files, not 42), several of them common (2 Tim appears 8+ times). Add the missing spellings to existing ids (2 Cor, Col., Exod, Ezek, James, Sir, Eccli) and ten new ids for books not cited before (1-2 Timothy, 2 Peter, Apocalypse, Judith, Malachi, Proverbs, Song of Songs, Tobit, Wisdom). Sir and Rev are modern spellings sitting inside Vulgate data, so both resolve to their Vulgate ids (ecclesiasticus, apocalypse) rather than to the sirach/revelation tradition targets -- mapping them to a second id would double-map the same book. Add a duplicate-spelling invariant test (List.assoc_opt would silently prefer the first match on a collision) and a test that re-derives the token set from all three data files at test time and asserts every token resolves, rather than trusting a survey performed once by hand. --- lib/citation/book.ml | 47 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 11 deletions(-) (limited to 'lib/citation/book.ml') diff --git a/lib/citation/book.ml b/lib/citation/book.ml index a2f9678..545e324 100644 --- a/lib/citation/book.ml +++ b/lib/citation/book.ml @@ -4,25 +4,36 @@ type id = string let to_string t = t -(* Every book the shipped EF lectionary cites, with every spelling it uses. - The dotted/undotted pairs are inherited from lectio -- see book.mli. *) +(* Every book cited across the shipped EF data (lectionary, sanctoral + propers, and commons), with every spelling any of the three files uses. + The dotted/undotted and modern/Vulgate pairs are inherited from lectio -- + see book.mli. Surveyed directly against the data, all three files, not + the lectionary alone -- sanctoral.sexp alone carries more citations than + the lectionary and was the source of every token missed in the first + pass. *) let table = [ ("genesis", [ "Gen" ]); - ("exodus", [ "Ex" ]); + ("exodus", [ "Ex"; "Exod" ]); ("leviticus", [ "Lev" ]); ("numbers", [ "Num" ]); ("kings_3", [ "3 Kings"; "3 Kgs." ]); ("kings_4", [ "4 Kings" ]); ("esdras_2", [ "2 Esd." ]); + ("tobit", [ "Tob" ]); + ("judith", [ "Judith" ]); ("esther", [ "Esther" ]); - ("ecclesiasticus", [ "Ecclus" ]); + ("proverbs", [ "Prov" ]); + ("song_of_songs", [ "Song" ]); + ("wisdom", [ "Wis"; "Wis." ]); + ("ecclesiasticus", [ "Ecclus"; "Sir"; "Eccli" ]); ("isaiah", [ "Isa"; "Isa." ]); ("jeremiah", [ "Jer" ]); - ("ezekiel", [ "Ezech" ]); + ("ezekiel", [ "Ezech"; "Ezek" ]); ("daniel", [ "Dan" ]); ("osee", [ "Osee" ]); ("joel", [ "Joel" ]); ("jonas", [ "Jonas" ]); + ("malachi", [ "Mal" ]); ("matthew", [ "Matt"; "Matt." ]); ("mark", [ "Mark" ]); ("luke", [ "Luke" ]); @@ -30,23 +41,37 @@ let table = ("acts", [ "Acts" ]); ("romans", [ "Rom" ]); ("corinthians_1", [ "1 Cor"; "1 Cor." ]); - ("corinthians_2", [ "2 Cor." ]); + ("corinthians_2", [ "2 Cor"; "2 Cor." ]); ("galatians", [ "Gal" ]); ("ephesians", [ "Eph"; "Eph." ]); ("philippians", [ "Phil" ]); - ("colossians", [ "Col" ]); + ("colossians", [ "Col"; "Col." ]); ("thessalonians_1", [ "1 Thess"; "1 Thess." ]); ("thessalonians_2", [ "2 Thess" ]); + ("timothy_1", [ "1 Tim." ]); + ("timothy_2", [ "2 Tim"; "2 Tim." ]); ("titus", [ "Titus" ]); ("hebrews", [ "Heb" ]); - ("james", [ "Jas" ]); + ("james", [ "Jas"; "James" ]); ("peter_1", [ "1 Pet"; "1 Pet." ]); - ("john_1", [ "1 John" ]) ] + ("peter_2", [ "2 Pet." ]); + ("john_1", [ "1 John" ]); + (* "Apoc" is the Vulgate spelling and "Rev" its modern equivalent, but + BOTH sit inside Vulgate-tradition data, so both resolve to the same + Vulgate id here -- see book.mli's note by [apocalypse] never being an + [of_token] result under that name. Do not add "revelation" as a + spelling: it exists only as a tradition target (below), and giving it + an [of_token] entry would let one book carry two different ids. *) + ("apocalypse", [ "Apoc"; "Rev" ]) ] (* Targets a tradition can map ONTO that the Vulgate data never cites - directly. Present so [tradition_of_fields] can validate both sides. *) + directly. Present so [tradition_of_fields] can validate both sides. + [sirach] and [revelation] exist ONLY here, never as an [of_token] result: + "Sir" and "Rev" already resolve to the Vulgate ids [ecclesiasticus] and + [apocalypse] above, so a modern-numbering tradition maps ONTO these + targets rather than data ever citing them directly. *) let tradition_targets = - [ "kings_1"; "kings_2"; "nehemiah"; "sirach"; "hosea"; "jonah" ] + [ "kings_1"; "kings_2"; "nehemiah"; "sirach"; "hosea"; "jonah"; "revelation" ] let all = List.map fst table @ tradition_targets -- cgit v1.3