UNPKG

@gracious.tech/bible-references

Version:

Bible reference detection, parsing, and rendering that supports any language.

818 lines (817 loc) 31.4 kB
import { describe, it } from "vitest"; import { PassageReference, _detect_book, _verses_str_to_obj } from "./passage.js"; import { book_names_english, book_abbrev_english, english_abbrev_include } from "./data.js"; function simple(start_chapter, start_verse, end_chapter, end_verse) { return { start_chapter, start_verse, end_chapter: end_chapter != null ? end_chapter : start_chapter, end_verse: end_verse != null ? end_verse : start_verse }; } describe("_verses_str_to_obj", () => { it("Parses a single chapter", ({ expect }) => { expect(_verses_str_to_obj("1")).toEqual({ start_chapter: 1, start_verse: void 0, end_chapter: void 0, end_verse: void 0 }); }); it("Parses multiple chapters", ({ expect }) => { expect(_verses_str_to_obj("1-2")).toEqual({ start_chapter: 1, start_verse: void 0, end_chapter: 2, end_verse: void 0 }); }); it("Parses a single verse", ({ expect }) => { expect(_verses_str_to_obj("1:1")).toEqual({ start_chapter: 1, start_verse: 1, end_chapter: void 0, end_verse: void 0 }); }); it("Parses multiple verses", ({ expect }) => { expect(_verses_str_to_obj("1:1-2")).toEqual({ start_chapter: 1, start_verse: 1, end_chapter: void 0, end_verse: 2 }); }); it("Parses verses across chapters", ({ expect }) => { expect(_verses_str_to_obj("1:1-2:2")).toEqual({ start_chapter: 1, start_verse: 1, end_chapter: 2, end_verse: 2 }); }); it("Salvages what it can from invalid references", ({ expect }) => { expect(_verses_str_to_obj("x")).toEqual({ start_chapter: void 0, start_verse: void 0, end_chapter: void 0, end_verse: void 0 }); expect(_verses_str_to_obj("1:x")).toEqual({ start_chapter: 1, start_verse: void 0, end_chapter: void 0, end_verse: void 0 }); expect(_verses_str_to_obj("1:1-x")).toEqual({ start_chapter: 1, start_verse: 1, end_chapter: void 0, end_verse: void 0 }); expect(_verses_str_to_obj("1:1-1:x")).toEqual({ start_chapter: 1, start_verse: 1, end_chapter: 1, end_verse: void 0 }); expect(_verses_str_to_obj("1-2:1")).toEqual({ start_chapter: 1, start_verse: void 0, end_chapter: 2, end_verse: 1 }); }); }); describe("_detect_book", () => { const book_names = [...Object.entries(book_names_english), ...english_abbrev_include]; for (const [code, name] of book_names) { it(`Identifies "${name}" as '${code}'`, ({ expect }) => { expect(_detect_book(name, book_names)).toEqual(code); }); } for (const [code, abbrevs] of Object.entries(book_name_abbreviations)) { for (const abbrev of abbrevs) { it(`Identifies "${abbrev}" as '${code}'`, ({ expect }) => { expect(_detect_book(abbrev, book_names)).toEqual(code); }); } } it("Returns null if can't match", ({ expect }) => { expect(_detect_book("nothing", book_names)).toEqual(null); }); it("Returns null if multiple matches", ({ expect }) => { expect(_detect_book("j", book_names)).toEqual(null); }); it("Requires second char at start if first char is number", ({ expect }) => { expect(_detect_book("1am", book_names)).toEqual(null); expect(_detect_book("1sam", book_names)).toEqual("1sa"); }); it("Still parses some kinds of ambiguous references", ({ expect }) => { expect(_detect_book("Phil", book_names)).toEqual("php"); }); it("Detects abbreviations within words for languages that require it", ({ expect }) => { expect(_detect_book("\u4F2F", [["job", "\u7D04\u4F2F\u8A18"]], void 0, false)).toBe("job"); }); }); describe("get_prev_verse", () => { it("Accounts for chapters", ({ expect }) => { expect(new PassageReference("2th", 1, 1).get_prev_verse()).toBe(null); expect(new PassageReference("2th", 1, 2).get_prev_verse()).toMatchObject(simple(1, 1)); expect(new PassageReference("2th", 2, 1).get_prev_verse()).toMatchObject(simple(1, 12)); }); it("Gets previous from end when arg passed", ({ expect }) => { expect(new PassageReference({ book: "2th", start_chapter: 1, start_verse: 1, end_chapter: 2, end_verse: 1 }).get_prev_verse(true)).toMatchObject(simple(1, 12)); }); it("Expands book/chapter type to actual end when prev_to_end=true", ({ expect }) => { expect(new PassageReference("2th").get_prev_verse(true)).toMatchObject(simple(3, 17)); expect(new PassageReference("2th", 1).get_prev_verse(true)).toMatchObject(simple(1, 11)); }); }); describe("get_next_verse", () => { it("Accounts for chapters", ({ expect }) => { expect(new PassageReference("2th", 1, 1).get_next_verse()).toMatchObject(simple(1, 2)); expect(new PassageReference("2th", 1, 12).get_next_verse()).toMatchObject(simple(2, 1)); expect(new PassageReference("2th", 3, 18).get_next_verse()).toBe(null); }); it("Gets next from end when arg passed", ({ expect }) => { expect(new PassageReference({ book: "2th", start_chapter: 1, start_verse: 1, end_chapter: 2, end_verse: 1 }).get_next_verse(true)).toMatchObject(simple(2, 2)); }); it("Expands book/chapter type to actual end when after_end=true", ({ expect }) => { expect(new PassageReference("2th").get_next_verse(true)).toBe(null); expect(new PassageReference("2th", 1).get_next_verse(true)).toMatchObject(simple(2, 1)); }); }); describe("constructor", () => { it("Interprets basic args", ({ expect }) => { expect(new PassageReference("2th")).toMatchObject({ type: "book", range: false, book: "2th", start_chapter: 1, start_verse: 1, end_chapter: 1, end_verse: 1 }); expect(new PassageReference("2th", 1)).toMatchObject({ type: "chapter", range: false, book: "2th", start_chapter: 1, start_verse: 1, end_chapter: 1, end_verse: 1 }); expect(new PassageReference("2th", 1, 1)).toMatchObject({ type: "verse", range: false, book: "2th", start_chapter: 1, start_verse: 1, end_chapter: 1, end_verse: 1 }); }); it("Interprets invalid basic args", ({ expect }) => { expect(new PassageReference("invalid")).toMatchObject({ type: "book", range: false, book: "gen", start_chapter: 1, start_verse: 1, end_chapter: 1, end_verse: 1 }); expect(new PassageReference("2th", -1)).toMatchObject({ type: "chapter", range: false, book: "2th", start_chapter: 1, start_verse: 1, end_chapter: 1, end_verse: 1 }); expect(new PassageReference("2th", 99)).toMatchObject({ type: "chapter", range: false, book: "2th", start_chapter: 3, start_verse: 18, end_chapter: 3, end_verse: 18 }); expect(new PassageReference("2th", 2, -1)).toMatchObject({ type: "verse", range: false, book: "2th", start_chapter: 2, start_verse: 1, end_chapter: 2, end_verse: 1 }); expect(new PassageReference("2th", 2, 99)).toMatchObject({ type: "verse", range: false, book: "2th", start_chapter: 2, start_verse: 17, end_chapter: 2, end_verse: 17 }); }); it("Interprets range args", ({ expect }) => { expect(new PassageReference( { book: "2th", start_chapter: 2, end_chapter: 3 } )).toMatchObject({ type: "range_chapters", range: true, book: "2th", start_chapter: 2, start_verse: 1, end_chapter: 3, end_verse: 18 }); expect(new PassageReference( { book: "2th", start_chapter: 2, start_verse: 1, end_verse: 2 } )).toMatchObject({ type: "range_verses", range: true, book: "2th", start_chapter: 2, start_verse: 1, end_chapter: 2, end_verse: 2 }); expect(new PassageReference( { book: "2th", start_chapter: 1, start_verse: 1, end_chapter: 2, end_verse: 1 } )).toMatchObject({ type: "range_multi", range: true, book: "2th", start_chapter: 1, start_verse: 1, end_chapter: 2, end_verse: 1 }); }); it("Interprets invalid range args", ({ expect }) => { expect(new PassageReference( { book: "2th", start_chapter: 2, end_chapter: 1 } )).toMatchObject({ type: "chapter", range: false, book: "2th", start_chapter: 2, start_verse: 1, end_chapter: 2, end_verse: 1 }); expect(new PassageReference( { book: "2th", start_chapter: 2, start_verse: 1, end_chapter: 2, end_verse: 99 } )).toMatchObject({ type: "range_verses", range: true, book: "2th", start_chapter: 2, start_verse: 1, end_chapter: 2, end_verse: 17 }); }); it("Interprets non-sensical args", ({ expect }) => { expect(new PassageReference( { book: "2th", start_verse: 1 } )).toMatchObject({ type: "book", range: false, book: "2th", start_chapter: 1, start_verse: 1, end_chapter: 1, end_verse: 1 }); expect(new PassageReference({ book: "2th", start_chapter: 2, end_verse: 5 })).toMatchObject({ type: "range_verses", range: true, book: "2th", start_chapter: 2, start_verse: 1, end_chapter: 2, end_verse: 5 }); expect(new PassageReference({ book: "2th", start_chapter: 1, start_verse: 1, end_chapter: 2 })).toMatchObject({ type: "range_chapters", range: true, book: "2th", start_chapter: 1, start_verse: 1, end_chapter: 2, end_verse: 17 }); }); it("Produces consistent results for single chapter books", ({ expect }) => { expect(new PassageReference({ book: "jud" })).toMatchObject({ type: "book" }); expect(new PassageReference({ book: "jud", start_chapter: 1 })).toMatchObject({ type: "book" }); expect(new PassageReference({ book: "jud", start_chapter: 1, start_verse: 1 })).toMatchObject({ type: "verse" }); expect(new PassageReference({ book: "jud", start_chapter: 1, start_verse: 1, end_verse: 2 })).toMatchObject({ type: "range_verses" }); expect(new PassageReference({ book: "jud", start_chapter: 1, end_chapter: 2 })).toMatchObject({ type: "range_verses" }); expect(new PassageReference({ book: "jud", start_chapter: 1, start_verse: 2, end_chapter: 2, end_verse: 2 })).toMatchObject({ type: "range_verses" }); }); }); describe("ranges", () => { it("Interprets ranges reliably", ({ expect }) => { const tests = [ // Each type ["Titus", "book", 1, 1, 1, 1], ["Titus 1", "chapter", 1, 1, 1, 1], ["Titus 1:1", "verse", 1, 1, 1, 1], ["Titus 1:1-2", "range_verses", 1, 1, 1, 2], ["Titus 1-2", "range_chapters", 1, 1, 2, 15], ["Titus 1:1-2:2", "range_multi", 1, 1, 2, 2], // Ranges that should be simplified to a range of chapters ["Titus 1:1-2:15", "range_chapters", 1, 1, 2, 15, "Titus 1-2"], // Range of entire chapters ["Titus 1:1-3:15", "range_chapters", 1, 1, 3, 15, "Titus 1-3"], // Range of entire book // Ranges that should NOT be simplified // as would then cause ambiguity as to whether they represent a range or an identifier ["Titus 1:1-16", "range_verses", 1, 1, 1, 16], // Whole chapter ["Titus 1-3", "range_chapters", 1, 1, 3, 15], // Whole book // Each type ["Jude", "book", 1, 1, 1, 1], ["Jude 1", "verse", 1, 1, 1, 1, "Jude 1:1"], ["Jude 1:1", "verse", 1, 1, 1, 1], ["Jude 1:1-2", "range_verses", 1, 1, 1, 2], ["Jude 1-2", "range_verses", 1, 1, 1, 2, "Jude 1:1-2"], ["Jude 1:1-2:2", "range_verses", 1, 1, 1, 25, "Jude 1:1-25"], // Actually invalid but still test // Ranges that should NOT be simplified // as would then cause ambiguity as to whether they represent a range or an identifier ["Jude 1:1-25", "range_verses", 1, 1, 1, 25] // Whole chapter ]; for (const [string, type, start_chapter, start_verse, end_chapter, end_verse, new_string] of tests) { const ref_obj = PassageReference.from_string(string); expect(ref_obj).toMatchObject( { type, start_chapter, start_verse, end_chapter, end_verse } ); expect(ref_obj.toString()).toBe(new_string != null ? new_string : string); } }); }); describe("from_string", () => { it("Interprets single digits as verses for single chapter books", ({ expect }) => { expect(PassageReference.from_string("1 John 1").type).toBe("chapter"); expect(PassageReference.from_string("1 John 2-3")).toMatchObject({ start_chapter: 2, start_verse: 1, end_chapter: 3, end_verse: 24 }); expect(PassageReference.from_string("Obadiah 1").type).toBe("verse"); expect(PassageReference.from_string("Philemon 1").type).toBe("verse"); expect(PassageReference.from_string("2 John 1").type).toBe("verse"); expect(PassageReference.from_string("3 John 1").type).toBe("verse"); expect(PassageReference.from_string("Jude 1").type).toBe("verse"); expect(PassageReference.from_string("Obadiah 2-3")).toMatchObject({ start_chapter: 1, start_verse: 2, end_chapter: 1, end_verse: 3 }); expect(PassageReference.from_string("Philemon 2-3")).toMatchObject({ start_chapter: 1, start_verse: 2, end_chapter: 1, end_verse: 3 }); expect(PassageReference.from_string("2 John 2-3")).toMatchObject({ start_chapter: 1, start_verse: 2, end_chapter: 1, end_verse: 3 }); expect(PassageReference.from_string("3 John 2-3")).toMatchObject({ start_chapter: 1, start_verse: 2, end_chapter: 1, end_verse: 3 }); expect(PassageReference.from_string("Jude 2-3")).toMatchObject({ start_chapter: 1, start_verse: 2, end_chapter: 1, end_verse: 3 }); }); it("Does not detect single letter English names", ({ expect }) => { var _a; expect(PassageReference.from_string("O 1")).toBe(null); expect((_a = PassageReference.from_string("O. 1")) == null ? void 0 : _a.book).toBe("oba"); }); }); describe("toString", () => { it("Renders when coercing to a string", ({ expect }) => { expect(`${new PassageReference("tit")}`).toBe("Titus"); }); it("Renders passage types correctly", ({ expect }) => { expect(new PassageReference("tit").toString()).toBe("Titus"); expect(new PassageReference("tit", 1).toString()).toBe("Titus 1"); expect(new PassageReference("tit", 1, 1).toString()).toBe("Titus 1:1"); expect(new PassageReference({ book: "tit", start_chapter: 1, start_verse: 1, end_verse: 2 }).toString()).toBe("Titus 1:1-2"); expect(new PassageReference({ book: "tit", start_chapter: 1, end_chapter: 2 }).toString()).toBe("Titus 1-2"); expect(new PassageReference({ book: "tit", start_chapter: 1, start_verse: 1, end_chapter: 2, end_verse: 1 }).toString()).toBe("Titus 1:1-2:1"); }); it("Uses abbreviation when passed the hardcoded data", ({ expect }) => { expect(new PassageReference("ezk").toString(book_abbrev_english)).toBe("Ezek"); }); it("Restores original valid string", ({ expect }) => { expect(PassageReference.from_string("Titus").toString()).toBe("Titus"); expect(PassageReference.from_string("Titus 1").toString()).toBe("Titus 1"); expect(PassageReference.from_string("Titus 1:1").toString()).toBe("Titus 1:1"); expect(PassageReference.from_string("Titus 1:1-2").toString()).toBe("Titus 1:1-2"); expect(PassageReference.from_string("Titus 1:1-2:2").toString()).toBe("Titus 1:1-2:2"); expect(PassageReference.from_string("Titus 1-2").toString()).toBe("Titus 1-2"); expect(PassageReference.from_string("Jude").toString()).toBe("Jude"); }); }); describe("serialized", () => { it("Is deterministic", ({ expect }) => { const props_tit = [ ["tit", { book: "tit", type: "book", start_chapter: 1, start_verse: 1, end_chapter: 1, end_verse: 1 }], ["tit2", { book: "tit", type: "chapter", start_chapter: 2, start_verse: 1, end_chapter: 2, end_verse: 1 }], ["tit2:2", { book: "tit", type: "verse", start_chapter: 2, start_verse: 2, end_chapter: 2, end_verse: 2 }], ["tit2:2-3", { book: "tit", type: "range_verses", start_chapter: 2, start_verse: 2, end_chapter: 2, end_verse: 3 }], ["tit2-3", { book: "tit", type: "range_chapters", start_chapter: 2, start_verse: 1, end_chapter: 3, end_verse: 15 }], ["tit2:2-3:3", { book: "tit", type: "range_multi", start_chapter: 2, start_verse: 2, end_chapter: 3, end_verse: 3 }] ]; const props_jud = [ ["jud", { book: "jud", type: "book", start_chapter: 1, start_verse: 1, end_chapter: 1, end_verse: 1 }], // NOTE 'chapter' is not possible ["jud1:2", { book: "jud", type: "verse", start_chapter: 1, start_verse: 2, end_chapter: 1, end_verse: 2 }], ["jud1:2-3", { book: "jud", type: "range_verses", start_chapter: 1, start_verse: 2, end_chapter: 1, end_verse: 3 }] // NOTE 'range_chapters' is not possible // NOTE 'range_multi' is not possible ]; for (const test_props of [props_tit, props_jud]) { for (const [code, props] of test_props) { const ref_produced = PassageReference.from_serialized(code); expect(ref_produced).toMatchObject(props); const code_produced = ref_produced.to_serialized(); expect(code_produced).toBe(code); } } }); }); describe("total_verses", () => { it("Sums for each verse type", ({ expect }) => { expect(PassageReference.from_string("2 Tim").total_verses()).toBe(18 + 26 + 17 + 22); expect(PassageReference.from_string("2 Tim 2").total_verses()).toBe(26); expect(PassageReference.from_string("2 Tim 2:4").total_verses()).toBe(1); expect(PassageReference.from_string("2 Tim 2:4-5").total_verses()).toBe(2); expect(PassageReference.from_string("2 Tim 2-3").total_verses()).toBe(26 + 17); expect(PassageReference.from_string("2 Tim 2:2-3:3").total_verses()).toBe(25 + 3); expect(PassageReference.from_string("2 Tim 1:2-4:3").total_verses()).toBe(17 + 26 + 17 + 3); }); }); describe("is_before", () => { it("Returns true when ref ends before the given chapter/verse", ({ expect }) => { expect(new PassageReference("gen", 1, 5).is_before(1, 6)).toBe(true); expect(new PassageReference("gen", 1, 5).is_before(1, 5)).toBe(false); expect(new PassageReference("gen", 1, 6).is_before(1, 5)).toBe(false); }); it("Returns true when ref ends before the given ref starts", ({ expect }) => { const a = new PassageReference("gen", 1, 5); const b = new PassageReference("gen", 1, 6); expect(a.is_before(b)).toBe(true); expect(b.is_before(a)).toBe(false); expect(a.is_before(a)).toBe(false); }); it("Expands book/chapter type to actual end for ref", ({ expect }) => { expect(new PassageReference("gen", 1).is_before(1, 31)).toBe(false); expect(new PassageReference("gen", 1).is_before(1, 15)).toBe(false); expect(new PassageReference("gen", 1).is_before(2, 1)).toBe(true); }); it("Uses canonical book order for cross-book comparison", ({ expect }) => { expect(new PassageReference("gen").is_before(new PassageReference("mat"))).toBe(true); expect(new PassageReference("mat").is_before(new PassageReference("gen"))).toBe(false); }); }); describe("is_after", () => { it("Returns true when ref starts after the given chapter/verse", ({ expect }) => { expect(new PassageReference("gen", 1, 6).is_after(1, 5)).toBe(true); expect(new PassageReference("gen", 1, 5).is_after(1, 5)).toBe(false); expect(new PassageReference("gen", 1, 5).is_after(1, 6)).toBe(false); }); it("Returns true when ref starts after the given ref ends", ({ expect }) => { const a = new PassageReference("gen", 1, 5); const b = new PassageReference("gen", 1, 6); expect(b.is_after(a)).toBe(true); expect(a.is_after(b)).toBe(false); expect(a.is_after(a)).toBe(false); }); it("Expands book/chapter type to actual end for ref arg", ({ expect }) => { expect(new PassageReference("gen", 1, 15).is_after(new PassageReference("gen", 1))).toBe(false); expect(new PassageReference("gen", 1, 31).is_after(new PassageReference("gen", 1))).toBe(false); expect(new PassageReference("gen", 2, 1).is_after(new PassageReference("gen", 1))).toBe(true); }); it("Uses canonical book order for cross-book comparison", ({ expect }) => { expect(new PassageReference("mat").is_after(new PassageReference("gen"))).toBe(true); expect(new PassageReference("gen").is_after(new PassageReference("mat"))).toBe(false); }); }); describe("includes", () => { it("Returns true when the given chapter/verse is within ref", ({ expect }) => { const ref = new PassageReference({ book: "gen", start_chapter: 1, start_verse: 5, end_chapter: 2, end_verse: 10 }); expect(ref.includes(1, 5)).toBe(true); expect(ref.includes(2, 10)).toBe(true); expect(ref.includes(1, 10)).toBe(true); expect(ref.includes(1, 4)).toBe(false); expect(ref.includes(2, 11)).toBe(false); }); it("Returns true when the argument ref is fully within the calling ref", ({ expect }) => { const outer = new PassageReference({ book: "gen", start_chapter: 1, start_verse: 1, end_chapter: 5, end_verse: 32 }); const inner = new PassageReference({ book: "gen", start_chapter: 1, start_verse: 5, end_chapter: 2, end_verse: 10 }); expect(outer.includes(inner)).toBe(true); expect(inner.includes(outer)).toBe(false); }); it("Returns true when refs are identical", ({ expect }) => { const ref = new PassageReference({ book: "gen", start_chapter: 1, start_verse: 5, end_chapter: 2, end_verse: 10 }); expect(ref.includes(ref)).toBe(true); }); it("Returns false when ref only partially overlaps", ({ expect }) => { const ref = new PassageReference({ book: "gen", start_chapter: 2, start_verse: 5, end_chapter: 3, end_verse: 10 }); expect(ref.includes(new PassageReference({ book: "gen", start_chapter: 1, start_verse: 1, end_chapter: 2, end_verse: 10 }))).toBe(false); expect(ref.includes(new PassageReference({ book: "gen", start_chapter: 3, start_verse: 5, end_chapter: 4, end_verse: 1 }))).toBe(false); }); it("Expands book/chapter type to full range for the calling ref", ({ expect }) => { expect(new PassageReference("gen").includes(new PassageReference("gen", 5, 1))).toBe(true); expect(new PassageReference("gen", 1).includes(new PassageReference("gen", 1, 15))).toBe(true); expect(new PassageReference("gen", 1).includes(new PassageReference("gen", 2, 1))).toBe(false); }); it("Returns false for different books", ({ expect }) => { expect(new PassageReference("gen").includes(new PassageReference("mat", 1, 1))).toBe(false); }); }); describe("overlaps", () => { it("Returns true when ranges share verses", ({ expect }) => { const ref = new PassageReference({ book: "gen", start_chapter: 2, start_verse: 5, end_chapter: 3, end_verse: 10 }); expect(ref.overlaps(new PassageReference({ book: "gen", start_chapter: 1, start_verse: 1, end_chapter: 2, end_verse: 10 }))).toBe(true); expect(ref.overlaps(new PassageReference({ book: "gen", start_chapter: 3, start_verse: 5, end_chapter: 4, end_verse: 1 }))).toBe(true); expect(ref.overlaps(new PassageReference({ book: "gen", start_chapter: 1, start_verse: 1, end_chapter: 5, end_verse: 32 }))).toBe(true); expect(ref.overlaps(ref)).toBe(true); }); it("Returns false when ranges do not share verses", ({ expect }) => { const ref = new PassageReference({ book: "gen", start_chapter: 2, start_verse: 5, end_chapter: 3, end_verse: 10 }); expect(ref.overlaps(new PassageReference({ book: "gen", start_chapter: 1, start_verse: 1, end_chapter: 2, end_verse: 4 }))).toBe(false); expect(ref.overlaps(new PassageReference({ book: "gen", start_chapter: 3, start_verse: 11, end_chapter: 4, end_verse: 1 }))).toBe(false); }); it("Returns false for different books", ({ expect }) => { expect(new PassageReference("gen").overlaps(new PassageReference("mat"))).toBe(false); }); it("Expands book/chapter types to full range", ({ expect }) => { expect(new PassageReference("gen").overlaps(new PassageReference("gen", 5, 1))).toBe(true); expect(new PassageReference("gen", 1).overlaps(new PassageReference("gen", 1, 15))).toBe(true); expect(new PassageReference("gen", 1).overlaps(new PassageReference("gen", 2, 1))).toBe(false); }); }); describe("simplify", () => { it("Collapses a whole-chapter range_verses to a chapter identifier", ({ expect }) => { const ref = PassageReference.from_string("Gen 1:1-31"); expect(ref.type).toBe("range_verses"); const simplified = ref.simplify(); expect(simplified.type).toBe("chapter"); expect(simplified.to_serialized()).toBe("gen1"); }); it("Collapses a whole-book range_chapters to a book identifier", ({ expect }) => { const ref = PassageReference.from_string("Gen 1-50"); expect(ref.type).toBe("range_chapters"); const simplified = ref.simplify(); expect(simplified.type).toBe("book"); expect(simplified.to_serialized()).toBe("gen"); }); it("Leaves a partial chapter range unchanged", ({ expect }) => { const ref = PassageReference.from_string("Gen 1:1-30"); expect(ref.simplify()).toBe(ref); }); it("Leaves a partial book range unchanged", ({ expect }) => { const ref = PassageReference.from_string("Gen 1-49"); expect(ref.simplify()).toBe(ref); }); it("Returns the same reference when already an identifier", ({ expect }) => { expect(PassageReference.from_string("Gen 1").simplify().type).toBe("chapter"); expect(PassageReference.from_string("Gen").simplify().type).toBe("book"); expect(PassageReference.from_string("Gen 1:1").simplify().type).toBe("verse"); }); }); const book_name_abbreviations = { "gen": ["Gen.", "Ge.", "Gn."], "exo": ["Ex.", "Exod.", "Exo."], "lev": ["Lev.", "Le.", "Lv."], "num": ["Num.", "Nu.", "Nm.", "Nb."], "deu": ["Deut.", "De.", "Dt."], "jos": ["Josh.", "Jos.", "Jsh."], "jdg": ["Judg.", "Jdg.", "Jg.", "Jdgs."], "rut": ["Ruth", "Rth.", "Ru."], "1sa": ["1 Sam.", "1 Sm.", "1 Sa.", "1 S.", "I Sam.", "I Sa.", "1Sam.", "1Sa.", "1S.", "1st Samuel", "1st Sam.", "First Samuel", "First Sam."], "2sa": ["2 Sam.", "2 Sm.", "2 Sa.", "2 S.", "II Sam.", "II Sa.", "2Sam.", "2Sa.", "2S.", "2nd Samuel", "2nd Sam.", "Second Samuel", "Second Sam."], "1ki": ["1 Kings", "1 Kgs", "1 Ki", "1Kgs", "1Kin", "1Ki", "1K", "I Kgs", "I Ki", "1st Kings", "1st Kgs", "First Kings", "First Kgs"], "2ki": ["2 Kings", "2 Kgs.", "2 Ki.", "2Kgs.", "2Kin.", "2Ki.", "2K.", "II Kgs.", "II Ki.", "2nd Kings", "2nd Kgs.", "Second Kings", "Second Kgs."], "1ch": ["1 Chron.", "1 Chr.", "1 Ch.", "1Chron.", "1Chr.", "1Ch.", "I Chron.", "I Chr.", "I Ch.", "1st Chronicles", "1st Chron.", "First Chronicles", "First Chron."], "2ch": ["2 Chron.", "2 Chr.", "2 Ch.", "2Chron.", "2Chr.", "2Ch.", "II Chron.", "II Chr.", "II Ch.", "2nd Chronicles", "2nd Chron.", "Second Chronicles", "Second Chron."], "ezr": ["Ezra", "Ezr.", "Ez."], "neh": ["Neh.", "Ne."], "est": ["Est.", "Esth.", "Es."], "job": ["Job", "Jb."], "psa": ["Ps.", "Psalm", "Pslm.", "Psa.", "Psm.", "Pss."], "pro": ["Prov", "Pro.", "Prv.", "Pr."], "ecc": ["Eccles.", "Eccle.", "Ecc.", "Ec."], "sng": ["Song", "Song of Songs", "SOS.", "So."], "isa": ["Isa.", "Is."], "jer": ["Jer.", "Je.", "Jr."], "lam": ["Lam.", "La."], "ezk": ["Ezek.", "Eze.", "Ezk."], "dan": ["Dan.", "Da.", "Dn."], "hos": ["Hos.", "Ho."], "jol": ["Joel", "Jl."], "amo": ["Amos", "Am."], "oba": ["Obad.", "Ob."], "jon": ["Jonah", "Jnh.", "Jon."], "mic": ["Mic.", "Mc."], "nam": ["Nah.", "Na."], "hab": ["Hab.", "Hb."], "zep": ["Zeph.", "Zep.", "Zp."], "hag": ["Hag.", "Hg."], "zec": ["Zech.", "Zec.", "Zc."], "mal": ["Mal.", "Ml."], "mat": ["Matt.", "Mt."], "mrk": ["Mark", "Mrk", "Mar", "Mk", "Mr"], "luk": ["Luke", "Luk", "Lk"], "jhn": ["John", "Joh", "Jhn", "Jn"], "act": ["Acts", "Act", "Ac"], "rom": ["Rom.", "Ro.", "Rm."], "1co": ["1 Cor.", "1 Co.", "I Cor.", "I Co.", "1Cor.", "1Co.", "I Corinthians", "1Corinthians", "1st Corinthians", "First Corinthians"], "2co": ["2 Cor.", "2 Co.", "II Cor.", "II Co.", "2Cor.", "2Co.", "II Corinthians", "2Corinthians", "2nd Corinthians", "Second Corinthians"], "gal": ["Gal.", "Ga."], "eph": ["Eph.", "Ephes."], "php": ["Phil.", "Php.", "Pp."], "col": ["Col.", "Co."], "1th": ["1 Thess.", "1 Thes.", "1 Th.", "I Thessalonians", "I Thess.", "I Thes.", "I Th.", "1Thessalonians", "1Thess.", "1Thes.", "1Th.", "1st Thessalonians", "1st Thess.", "First Thessalonians", "First Thess."], "2th": ["2 Thess.", "2 Thes.", "2 Th.", "II Thessalonians", "II Thess.", "II Thes.", "II Th.", "2Thessalonians", "2Thess.", "2Thes.", "2Th.", "2nd Thessalonians", "2nd Thess.", "Second Thessalonians", "Second Thess."], "1ti": ["1 Tim.", "1 Ti.", "I Timothy", "I Tim.", "I Ti.", "1Timothy", "1Tim.", "1Ti.", "1st Timothy", "1st Tim.", "First Timothy", "First Tim."], "2ti": ["2 Tim.", "2 Ti.", "II Timothy", "II Tim.", "II Ti.", "2Timothy", "2Tim.", "2Ti.", "2nd Timothy", "2nd Tim.", "Second Timothy", "Second Tim."], "tit": ["Titus", "Tit", "ti"], "phm": ["Philem.", "Phm.", "Pm."], "heb": ["Heb."], "jas": ["James", "Jas", "Jm"], "1pe": ["1 Pet.", "1 Pe.", "1 Pt.", "1 P.", "I Pet.", "I Pt.", "I Pe.", "1Peter", "1Pet.", "1Pe.", "1Pt.", "1P.", "I Peter", "1st Peter", "First Peter"], "2pe": ["2 Pet.", "2 Pe.", "2 Pt.", "2 P.", "II Peter", "II Pet.", "II Pt.", "II Pe.", "2Peter", "2Pet.", "2Pe.", "2Pt.", "2P.", "2nd Peter", "Second Peter"], "1jn": ["1 John", "1 Jhn.", "1 Jn.", "1 J.", "1John", "1Jhn.", "1Joh.", "1Jn.", "1Jo.", "1J.", "I John", "I Jhn.", "I Joh.", "I Jn.", "I Jo.", "1st John", "First John"], "2jn": ["2 John", "2 Jhn.", "2 Jn.", "2 J.", "2John", "2Jhn.", "2Joh.", "2Jn.", "2Jo.", "2J.", "II John", "II Jhn.", "II Joh.", "II Jn.", "II Jo.", "2nd John", "Second John"], "3jn": ["3 John", "3 Jhn.", "3 Jn.", "3 J.", "3John", "3Jhn.", "3Joh.", "3Jn.", "3Jo.", "3J.", "III John", "III Jhn.", "III Joh.", "III Jn.", "III Jo.", "3rd John", "Third John"], "jud": ["Jude", "Jud.", "Jd."], "rev": ["Rev", "Re"] }; //# sourceMappingURL=passage.test.js.map