@gracious.tech/bible-references
Version:
Bible reference detection, parsing, and rendering that supports any language.
204 lines (203 loc) • 9.12 kB
JavaScript
import { describe, it } from "vitest";
import { detect_references } from "./detect.js";
import { english_abbrev_exclude } from "./data.js";
describe("detect_references", () => {
it("Detects a single reference", ({ expect }) => {
var _a;
expect((_a = detect_references("Titus 2:3").next().value) == null ? void 0 : _a.text).toBe("Titus 2:3");
});
it("Detects all reference types (except book)", ({ expect }) => {
var _a;
for (const ref of ["Tit 2", "Tit 2:3", "Tit 2-3", "Tit 2:2-3", "Tit 2:2-3:3"]) {
expect((_a = detect_references(ref).next().value) == null ? void 0 : _a.text).toBe(ref);
}
});
it("Does not detect whole books", ({ expect }) => {
expect(detect_references("Titus").next().value).toBe(null);
});
it("Does not detect invalid references", ({ expect }) => {
expect(detect_references("Titus 9").next().value).toBe(null);
});
it("Detects a reference deep in text", ({ expect }) => {
var _a, _b;
expect((_a = detect_references("About Titus 2:3 and more").next().value) == null ? void 0 : _a.text).toBe("Titus 2:3");
expect((_b = detect_references("About (Titus 2:3) and more").next().value) == null ? void 0 : _b.text).toBe("Titus 2:3");
});
it("Detects multiple references", ({ expect }) => {
var _a, _b, _c;
const text = "Multiple Gen 2:3 refs like John 3:16 and Matt 10:8";
const detector = detect_references(text);
expect((_a = detector.next().value) == null ? void 0 : _a.text).toBe("Gen 2:3");
expect((_b = detector.next().value) == null ? void 0 : _b.text).toBe("John 3:16");
expect((_c = detector.next().value) == null ? void 0 : _c.text).toBe("Matt 10:8");
});
it("Loops through multiple references", ({ expect }) => {
const text = "Multiple Gen 2:3 refs like John 3:16 and Matt 10:8";
const results = ["Gen 2:3", "John 3:16", "Matt 10:8"];
for (const ref of detect_references(text)) {
expect(ref.text).toBe(results.shift());
}
});
it("Provides accurate indexing from last match", ({ expect }) => {
let text = "Multiple Gen 2:3 refs like John 3:16 and Matt 10:8.";
let result = "";
const detector = detect_references(text);
const ref1 = detector.next().value;
expect(ref1.text).toBe("Gen 2:3");
expect(ref1.index_from_prev_match).toBe(9);
result += text.slice(0, ref1.index_from_prev_match) + "X";
text = text.slice(ref1.index_from_prev_match + ref1.text.length);
const ref2 = detector.next().value;
expect(ref2.text).toBe("John 3:16");
expect(ref2.index_from_prev_match).toBe(11);
result += text.slice(0, ref2.index_from_prev_match) + "X";
text = text.slice(ref2.index_from_prev_match + ref2.text.length);
const ref3 = detector.next().value;
expect(ref3.text).toBe("Matt 10:8");
expect(ref3.index_from_prev_match).toBe(5);
result += text.slice(0, ref3.index_from_prev_match) + "X";
text = text.slice(ref3.index_from_prev_match + ref3.text.length);
expect(detector.next().value).toBe(null);
result += text;
expect(result).toBe("Multiple X refs like X and X.");
});
it("Provides accurate indexing from last match #2", ({ expect }) => {
let text = "Examples (1 Cor 9:18, 2 Cor 2:17, 2 Cor 11:7)";
let result = "";
const detector = detect_references(text);
const ref1 = detector.next().value;
expect(ref1.text).toBe("1 Cor 9:18");
expect(ref1.index_from_prev_match).toBe(10);
result += text.slice(0, ref1.index_from_prev_match) + "X";
text = text.slice(ref1.index_from_prev_match + ref1.text.length);
const ref2 = detector.next().value;
expect(ref2.text).toBe("2 Cor 2:17");
expect(ref2.index_from_prev_match).toBe(2);
result += text.slice(0, ref2.index_from_prev_match) + "X";
text = text.slice(ref2.index_from_prev_match + ref2.text.length);
const ref3 = detector.next().value;
expect(ref3.text).toBe("2 Cor 11:7");
expect(ref3.index_from_prev_match).toBe(2);
result += text.slice(0, ref3.index_from_prev_match) + "X";
text = text.slice(ref3.index_from_prev_match + ref3.text.length);
expect(detector.next().value).toBe(null);
result += text;
expect(result).toBe("Examples (X, X, X)");
});
it("Provides accurate indexing from last match #3", ({ expect }) => {
let text = "John 10:3-4, 11, 14-15; End";
let result = "";
const detector = detect_references(text);
const ref1 = detector.next().value;
expect(ref1.text).toBe("John 10:3-4");
expect(ref1.index_from_prev_match).toBe(0);
result += text.slice(0, ref1.index_from_prev_match) + "X";
text = text.slice(ref1.index_from_prev_match + ref1.text.length);
const ref2 = detector.next().value;
expect(ref2.text).toBe("11");
expect(ref2.index_from_prev_match).toBe(2);
result += text.slice(0, ref2.index_from_prev_match) + "X";
text = text.slice(ref2.index_from_prev_match + ref2.text.length);
const ref3 = detector.next().value;
expect(ref3.text).toBe("14-15");
expect(ref3.index_from_prev_match).toBe(2);
result += text.slice(0, ref3.index_from_prev_match) + "X";
text = text.slice(ref3.index_from_prev_match + ref3.text.length);
expect(detector.next().value).toBe(null);
result += text;
expect(result).toBe("X, X, X; End");
});
it("Detects relative references", ({ expect }) => {
const relative = (text, type, start_chapter, start_verse) => {
const detector = detect_references(text);
detector.next();
const match = detector.next().value;
expect(match.ref).toMatchObject({ type, start_chapter, start_verse });
};
relative("Gen 1,6", "chapter", 6, 1);
relative("Gen 1-2,6", "chapter", 6, 1);
relative("Gen 1:1,6", "verse", 1, 6);
relative("Gen 1:1-2,6", "verse", 1, 6);
relative("Gen 1:1-2:2,6", "verse", 2, 6);
relative("Gen 1,6:1", "verse", 6, 1);
relative("Gen 1-2,6:1", "verse", 6, 1);
relative("Gen 1:1,6:1", "verse", 6, 1);
relative("Gen 1:1-2,6:1", "verse", 6, 1);
relative("Gen 1:1-2:2,6:1", "verse", 6, 1);
});
it("Interprets relative verse after two previous references", ({ expect }) => {
const detector = detect_references("2 Cor 2:17; 11:7,12");
let match = detector.next().value;
expect(match.ref).toMatchObject({ type: "verse", start_chapter: 2, start_verse: 17 });
match = detector.next().value;
expect(match.ref).toMatchObject({ type: "verse", start_chapter: 11, start_verse: 7 });
match = detector.next().value;
expect(match.ref).toMatchObject({ type: "verse", start_chapter: 11, start_verse: 12 });
});
it("Doesn't steal numbers from subsequent refs", ({ expect }) => {
const detector = detect_references("1 Cor 9:18,2 Cor 2:17 and 2 Cor 11:7,9 cor");
expect([...detector].map((m) => m.text)).toEqual(["1 Cor 9:18", "2 Cor 2:17", "2 Cor 11:7", "9"]);
const detector2 = detect_references("John 1:1, 3, 3 John 1");
expect([...detector2].map((m) => m.ref)).toMatchObject([
{ book: "jhn", start_chapter: 1, start_verse: 1, end_verse: 1 },
{ book: "jhn", start_chapter: 1, start_verse: 3, end_verse: 3 },
{ book: "3jn", start_chapter: 1, start_verse: 1, end_verse: 1 }
]);
});
it("Allows 0-2 spaces between segments", ({ expect }) => {
var _a, _b;
expect((_a = detect_references("Tit1:1-2:2").next().value) == null ? void 0 : _a.ref.toString()).toBe("Titus 1:1-2:2");
expect((_b = detect_references("Tit 1 : 1 - 2 : 2").next().value) == null ? void 0 : _b.ref.toString()).toBe("Titus 1:1-2:2");
expect(detect_references("Tit 1:1-2:2").next().value).toBe(null);
});
const common_2letter_words = [
"to",
"of",
"in",
"is",
"it",
"no",
"on",
"so",
"as",
"at",
"we",
"if",
"be",
"by",
"or",
"up",
"an",
"am",
"do",
"my",
"me",
"us",
"to",
"he",
"hi",
"of",
"oh",
"on",
"at",
"by"
];
for (const word of common_2letter_words) {
it(`Doesn't match two letter word "${word}"`, ({ expect }) => {
var _a;
expect((_a = detect_references(`${word} 1 Cor 9`).next().value) == null ? void 0 : _a.text).toBe("1 Cor 9");
});
}
for (const word of english_abbrev_exclude) {
it(`Does match "${word}."`, ({ expect }) => {
var _a;
expect((_a = detect_references(`${word}. 1`).next().value) == null ? void 0 : _a.text).not.toBe(null);
});
}
it("Detects Chinese references", ({ expect }) => {
var _a, _b;
expect((_a = detect_references("\u6709\u6301\u7EED\u7684\u6743\u5A01\uFF08\u7F57\u9A6C\u4E665\uFF1A14\uFF09\u3002\u6240\u6709\u4EBA\u7C7B", { rom: "\u7F57\u9A6C\u4E66" }).next().value) == null ? void 0 : _a.ref).toMatchObject({ book: "rom", start_chapter: 5, start_verse: 14 });
expect((_b = detect_references("\u6709\u6301\u7EED\u7684\u6743\u5A01\uFF08\u4F2F5\uFF1A14\uFF09\u3002\u6240\u6709\u4EBA\u7C7B", { job: "\u7D04\u4F2F\u8A18" }, [], 1, false).next().value) == null ? void 0 : _b.ref).toMatchObject({ book: "job", start_chapter: 5, start_verse: 14 });
});
});
//# sourceMappingURL=detect.test.js.map