Update web/templates/entry_edit.html

This commit is contained in:
Joshua Laymon 2025-09-02 02:16:47 +00:00
parent dc56c01d57
commit 72e14f6388

View File

@ -182,12 +182,15 @@
const el = document.getElementById("id_scripture_raw"); const el = document.getElementById("id_scripture_raw");
if (!el) return; if (!el) return;
// Exact WOL abbreviations
const WOL = new Set([ const WOL = new Set([
"Ge","Ex","Le","Nu","De","Jos","Jg","Ru","1Sa","2Sa","1Ki","2Ki","1Ch","2Ch","Ezr","Ne","Es","Job","Ps","Pr","Ec","Ca","Isa","Jer","La","Eze","Da","Ho","Joe","Am","Ob","Jon","Mic","Na","Hab","Zep","Hag","Zec","Mal", "Ge","Ex","Le","Nu","De","Jos","Jg","Ru","1Sa","2Sa","1Ki","2Ki","1Ch","2Ch","Ezr","Ne","Es","Job","Ps","Pr","Ec","Ca","Isa","Jer","La","Eze","Da","Ho","Joe","Am","Ob","Jon","Mic","Na","Hab","Zep","Hag","Zec","Mal",
"Mt","Mr","Lu","Joh","Ac","Ro","1Co","2Co","Ga","Eph","Php","Col","1Th","2Th","1Ti","2Ti","Tit","Phm","Heb","Jas","1Pe","2Pe","1Jo","2Jo","3Jo","Jude","Re" "Mt","Mr","Lu","Joh","Ac","Ro","1Co","2Co","Ga","Eph","Php","Col","1Th","2Th","1Ti","2Ti","Tit","Phm","Heb","Jas","1Pe","2Pe","1Jo","2Jo","3Jo","Jude","Re"
]); ]);
// Full names → WOL code (case-insensitive)
const FULL = new Map([ const FULL = new Map([
// OT
["genesis","Ge"],["exodus","Ex"],["leviticus","Le"],["numbers","Nu"],["deuteronomy","De"], ["genesis","Ge"],["exodus","Ex"],["leviticus","Le"],["numbers","Nu"],["deuteronomy","De"],
["joshua","Jos"],["judges","Jg"],["ruth","Ru"], ["joshua","Jos"],["judges","Jg"],["ruth","Ru"],
["1 samuel","1Sa"],["2 samuel","2Sa"],["1 kings","1Ki"],["2 kings","2Ki"], ["1 samuel","1Sa"],["2 samuel","2Sa"],["1 kings","1Ki"],["2 kings","2Ki"],
@ -197,6 +200,7 @@
["isaiah","Isa"],["jeremiah","Jer"],["lamentations","La"],["ezekiel","Eze"],["daniel","Da"], ["isaiah","Isa"],["jeremiah","Jer"],["lamentations","La"],["ezekiel","Eze"],["daniel","Da"],
["hosea","Ho"],["joel","Joe"],["amos","Am"],["obadiah","Ob"],["jonah","Jon"],["micah","Mic"], ["hosea","Ho"],["joel","Joe"],["amos","Am"],["obadiah","Ob"],["jonah","Jon"],["micah","Mic"],
["nahum","Na"],["habakkuk","Hab"],["zephaniah","Zep"],["haggai","Hag"],["zechariah","Zec"],["malachi","Mal"], ["nahum","Na"],["habakkuk","Hab"],["zephaniah","Zep"],["haggai","Hag"],["zechariah","Zec"],["malachi","Mal"],
// NT
["matthew","Mt"],["mark","Mr"],["luke","Lu"],["john","Joh"],["acts","Ac"],["romans","Ro"], ["matthew","Mt"],["mark","Mr"],["luke","Lu"],["john","Joh"],["acts","Ac"],["romans","Ro"],
["1 corinthians","1Co"],["2 corinthians","2Co"],["galatians","Ga"],["ephesians","Eph"], ["1 corinthians","1Co"],["2 corinthians","2Co"],["galatians","Ga"],["ephesians","Eph"],
["philippians","Php"],["colossians","Col"], ["philippians","Php"],["colossians","Col"],
@ -208,28 +212,58 @@
["jude","Jude"],["revelation","Re"] ["jude","Jude"],["revelation","Re"]
]); ]);
// Numbered-series acceptance (prose abbreviations like "2 Sam.", "1 Chron.", "2 Cor.", "1 Thes.", "2 Tim.", "1 Pet.", "1 Jn.")
const NUMBERED = [
{ prefixes: ["sam","samu","samuel"], codes: {1:"1Sa",2:"2Sa"} },
{ prefixes: ["ki","king","kings","kgs"], codes: {1:"1Ki",2:"2Ki"} },
{ prefixes: ["chron","chr","ch","chronicles"], codes: {1:"1Ch",2:"2Ch"} },
{ prefixes: ["cor","corin","corinth","corinthians","co","c"], codes: {1:"1Co",2:"2Co"} },
{ prefixes: ["thes","thess","thessalon","thessalonians","th"], codes: {1:"1Th",2:"2Th"} },
{ prefixes: ["tim","ti","timothy","t"], codes: {1:"1Ti",2:"2Ti"} },
{ prefixes: ["pet","pe","peter","pt","p"], codes: {1:"1Pe",2:"2Pe"} },
{ prefixes: ["jo","jn","joh","john","jno","jhn"], codes: {1:"1Jo",2:"2Jo",3:"3Jo"} },
];
// Split “book chapter[:verses…]”
function splitBookAndRest(s) { function splitBookAndRest(s) {
const m = s.match(/^(.+?)\s+(\d{1,3}(?:\s*:\s*.*)?)$/); const m = s.match(/^(.+?)\s+(\d{1,3}(?:\s*:\s*.*)?)$/);
return m ? {book: m[1], rest: m[2]} : null; return m ? {book: m[1], rest: m[2]} : null;
} }
function lookupBookCode(bookRaw) { function lookupBookCode(bookRaw) {
let b = bookRaw.trim(); // Trim and strip trailing period(s), collapse whitespace
let b = bookRaw.trim().replace(/\.+$/, "").replace(/\s+/g, " ");
// allow trailing period // 1) Full-name match (case-insensitive)
if (b.endsWith(".")) b = b.slice(0, -1); const fullKey = b.toLowerCase();
const fullKey = b.toLowerCase().replace(/\s+/g, " ");
if (FULL.has(fullKey)) return FULL.get(fullKey); if (FULL.has(fullKey)) return FULL.get(fullKey);
const maybeAbbr = b.replace(/^([1-3])\s+([A-Za-z]+)/, (_, n, letters) => n + letters); // 2) Numbered-series prose abbreviations: e.g., "2 Sam", "1 Chron", "2 Cor", "1 Thes", "2 Tim", "1 Pet", "1 Jn"
if (WOL.has(maybeAbbr)) return maybeAbbr; const m = b.toLowerCase().match(/^([1-3])\s*([a-z]+)$/);
if (m) {
const num = parseInt(m[1], 10);
const base = m[2];
for (const series of NUMBERED) {
if (series.prefixes.some(p => base.startsWith(p))) {
const code = series.codes[num];
if (code) return code;
}
}
}
// 3) WOL abbreviation (allow optional space after number and allow trailing period)
const abbr = b.replace(/^([1-3])\s+([A-Za-z]+)/, (_, n, letters) => n + letters);
if (WOL.has(abbr)) return abbr;
// Also try without spaces just in case
const abbrTight = b.replace(/\s+/g, "");
if (WOL.has(abbrTight)) return abbrTight;
if (WOL.has(b)) return b;
return null; return null;
} }
const versesRe = /^(\d{1,3})$|^(\d{1,3}):\s*(\d{1,3}(?:\s*-\s*(?:\d{1,3}|\d{1,3}:\d{1,3}))?(?:\s*,\s*\d{1,3}(?:\s*-\s*(?:\d{1,3}|\d{1,3}:\d{1,3}))?)*)$/; // Chapter only | chapter:verses | lists | ranges | cross-chapter range
const versesRe =
/^(\d{1,3})$|^(\d{1,3}):\s*(\d{1,3}(?:\s*-\s*(?:\d{1,3}|\d{1,3}:\d{1,3}))?(?:\s*,\s*\d{1,3}(?:\s*-\s*(?:\d{1,3}|\d{1,3}:\d{1,3}))?)*)$/;
function isValidSingleRef(ref) { function isValidSingleRef(ref) {
const s = ref.trim(); const s = ref.trim();