UNPKG

@allemandi/bible-validate

Version:

Fast, type-safe utilities for parsing, validating, and normalizing Bible references.

1 lines 29.6 kB
{"version":3,"file":"index.cjs","sources":["../src/utils/normalizer.js","../src/utils/lookup.js","../src/utils/validator.js","../src/utils/formatter.js"],"sourcesContent":["\n\n/**\n * Normalizes a Bible book name or alias by trimming spaces, removing common prefixes, \n * converting ordinal prefixes to digits, and stripping non-alphanumeric characters.\n * @public\n * @param {string} name - The raw book name or alias to normalize, possibly with prefixes, punctuation, and mixed case.\n * @returns {string|null} - A cleaned lowercase alphanumeric string with numeric prefixes for ordinals, or null if input is null or undefined.\n * @example\n * // Converts ordinal prefix to digit and removes punctuation\n * normalizeBookName('1st John'); // '1john'\n * // Removes unified prefixes and lowercases the name\n * normalizeBookName('The Epistle to the Romans'); // 'romans'\n * // Strips non-alphanumeric characters and trims spaces\n * normalizeBookName(' Book of *EX* '); // 'ex'\n * // Returns null if input is null or undefined\n * normalizeBookName(null); // null\n */\nfunction normalizeBookName(name) {\n if (!name) return null;\n /** @type {Record<string, string>} */\n const prefixMap = {\n '1st': '1', 'first': '1',\n '2nd': '2', 'second': '2',\n '3rd': '3', 'third': '3',\n 'iii': '3', 'ii': '2', 'i': '1',\n };\n let cleaned = name.trim().toLowerCase().replace(/\\s+/g, ' ');\n cleaned = cleaned.replace(\n /^(?:the\\s+)?(?:(book|epistle|gospel|letter)\\s+(?:according\\s+)?(?:to|for|of)(?:\\s+the)?\\s*)?/,\n ''\n );\n const prefixMatch = cleaned.match(/^(first|1st|second|2nd|third|3rd|iii|ii|i)\\b/);\n if (prefixMatch) {\n const key = prefixMatch[0];\n if (key in prefixMap) {\n const prefix = prefixMap[key];\n cleaned = prefix + ' ' + cleaned.slice(key.length).trim();\n }\n }\n return cleaned.replace(/[^a-z0-9]/g, '');\n}\n\n/**\n * Parses a string representing a chapter and optional verse or verse range\n * into an object with numeric values.\n * @public\n * @param {string} str - The string containing chapter and verse references, which may include words, punctuation, and ranges.\n * @returns {{chapter: number, verseStart: number|null, verseEnd: number|null}|null} - An object with the chapter number and optional verse start and end numbers, or null if no valid numbers are found.\n * @example\n * // Parses chapter only reference\n * parseChapterVerse('12'); // { chapter: 12, verseStart: null, verseEnd: null }\n * // Parses chapter and single verse reference\n * parseChapterVerse('5:3'); // { chapter: 5, verseStart: 3, verseEnd: null }\n * // Parses chapter with verse range including words and punctuation\n * parseChapterVerse('Chapter 13 Verses 4–7'); // { chapter: 13, verseStart: 4, verseEnd: 7 }\n * // Parses chapter with verse range using \"to\" as a separator\n * parseChapterVerse('chap. 13, v3 to 8'); // { chapter: 13, verseStart: 3, verseEnd: 8 }\n * // Returns null if no numeric chapter is present\n * parseChapterVerse('nonsense'); // null\n * // Parses chapter and verse range with extra whitespace and punctuation\n * parseChapterVerse(' 10 : 2 - 6 '); // { chapter: 10, verseStart: 2, verseEnd: 6 }\n * // Handles pure whitespace and number combination\n * parseChapterVerse(' 11 1 2 '); // { chapter: 11, verseStart: 1, verseEnd: 2 }\n */\nfunction parseChapterVerse(str) {\n if (!str) return null;\n\n const cleaned = str.toLowerCase()\n .replace(/[–—]/g, '-')\n .replace(/\\bto\\b/g, '-')\n .replace(/[a-z.,]/g, '')\n .replace(/\\s+/g, ' ')\n .trim();\n\n const tokens = cleaned.split(/[\\s\\-:]+/).filter(Boolean);\n const nums = tokens.map(t => parseInt(t, 10)).filter(n => !isNaN(n));\n if (nums.length === 0) return null;\n switch (nums.length) {\n case 1:\n return { chapter: nums[0], verseStart: null, verseEnd: null };\n case 2:\n return { chapter: nums[0], verseStart: nums[1], verseEnd: null };\n default:\n return { chapter: nums[0], verseStart: nums[1], verseEnd: nums[2] };\n }\n}\n\n/**\n * Splits a Bible reference string into the book name and chapter/verse range parts,\n * trimming empty space. No further normalization.\n * @public\n * @param {string} ref - The Bible reference string containing a book name optionally followed by a chapter/verse range.\n * @returns {[string|null, string|null]} - A tuple where the first element is the extracted book name and the second is the range; returns [null, null] if input is invalid or empty.\n * @example\n * // Extracts book and range from a standard reference\n * extractBookAndRange('1st John 3:16'); // ['1st John', '3:16']\n * // Extracts book name with punctuation and range\n * extractBookAndRange(\"The Revelation 4:5\"); // [\"The Revelation\", '4:5']\n * // Returns book name with empty range when no range is given\n * extractBookAndRange('Genesis'); // ['Genesis', '']\n * // Returns [null, null] for empty or invalid input\n * extractBookAndRange(''); // [null, null]\n * // Handles leading spaces and complex ranges with simple chapter abbreviations\n * extractBookAndRange(' Exodus 12. 1 to 3'); // ['Exodus', '12. 1 to 3']\n * extractBookAndRange('Exodus Chapter 12:1-3'); // ['Exodus', 'Chapter 12:1-3']\n * extractBookAndRange(' Exodus Ch. 12. 1 to 3'); // ['Exodus', 'Ch. 12. 1 to 3']\n * extractBookAndRange('second Kings Chape 1 to 3'); // ['second Kings Chape', '1 to 3']\n */\nfunction extractBookAndRange(ref) {\n if (!ref || typeof ref !== 'string') return [null, null];\n const cleaned = ref.trim().replace(/\\s+/g, ' ');\n const pattern = /^([\\d\\w\\s.']+?)\\s*(?=\\b(ch(?:apter)?|chap\\.?)\\b|\\d)/i;\n const match = cleaned.match(pattern);\n if (match) {\n const book = match[1].trim();\n const range = cleaned.slice(match[0].length).trim();\n return [book, range];\n }\n return [cleaned, ''];\n}\n\n/**\n * @import { ParsedReference } from './types.js'\n */\n\n/**\n * Parses a Bible reference string into its book, chapter, and verse components, supporting various formats and spacing.\n * @public\n * @param { string } ref - The Bible reference string to parse, which may include ordinal prefixes, varying case, punctuation, and verse ranges.\n * @returns {ParsedReference|null} - An object with normalized book name, chapter, verseStart, and verseEnd fields, or null if the input is not a string.\n * @example\n * // Parses ordinal prefix and returns structured reference\n * parseBibleReference('2nd Kings 4:2'); \n * // { book: '2kings', chapter: 4, verseStart: 2, verseEnd: null }\n * // Handles mixed casing, chapter/verse labels, and verse range\n * parseBibleReference(' Iii JohN Chap. 1 verses 9 to 11'); \n * // { book: '3john', chapter: 1, verseStart: 9, verseEnd: 11 }\n * // Returns null fields when chapter and verse are omitted\n * parseBibleReference('Genesis'); \n * // { book: 'genesis', chapter: null, verseStart: null, verseEnd: null }\n * // Cleans and parses input with excessive spacing\n * parseBibleReference(' 1st Samuel 17 : 4-9 '); \n * // { book: '1samuel', chapter: 17, verseStart: 4, verseEnd: 9 }\n * // Returns null for invalid or non-string input\n * parseBibleReference('!!!'); \n * // { book: null, chapter: null, verseStart: null, verseEnd: null }\n * parseBibleReference(42); // null\n */\nfunction parseBibleReference(ref) {\n if (!ref || typeof ref !== 'string') return null;\n const cleanedRef = ref.trim().replace(/\\s+/g, ' ');\n const [bookRaw, chapterVerseRaw] = extractBookAndRange(cleanedRef);\n const book = bookRaw && normalizeBookName(bookRaw);\n if (!book) {\n return {\n book: null,\n chapter: null,\n verseStart: null,\n verseEnd: null,\n };\n };\n const chapVerse = chapterVerseRaw ? parseChapterVerse(chapterVerseRaw) : null;\n return {\n book,\n chapter: chapVerse?.chapter ?? null,\n verseStart: chapVerse?.verseStart ?? null,\n verseEnd: chapVerse?.verseEnd ?? null,\n };\n}\n\nexport {\n normalizeBookName,\n parseChapterVerse,\n extractBookAndRange,\n parseBibleReference,\n};","/**\n * @import { BibleBook } from './types.js'\n */\nimport bibleCounts from '../data/bibleCounts.json';\nimport { normalizeBookName } from './normalizer';\n\n// Build a Map at load time for fast lookup by normalized book name or alias\nconst bookCache = new Map();\n\n/**\n * Retrieves a book object from the Bible collection matching the given book name or its aliases, ignoring case and special characters.\n * @public\n * @param {string} book - The name or alias of the book to lookup, which will be normalized internally.\n * @returns {BibleBook|null} - The matched book object containing book name, aliases, and chapters, or null if no match is found.\n * @example\n * // Returns the Genesis book object with its aliases and 50 chapters\n * getBook('Genesis'); // { book: 'Genesis', aliases: ['Gen', 'Ge', 'Gn'], chapters: [...] }\n * // Returns the Song of Solomon book object when queried with a normalized alias ignoring punctuation and case\n * getBook('The CANticle of CantiClEs !!?*'); // { book: 'Song of Solomon', aliases: [...], chapters: [...] }\n * // Returns null for an unknown or invalid book name\n * getBook('Judas'); // null\n */\nfunction getBook(book) {\n if (!book) return null;\n\n const normalized = normalizeBookName(book);\n if (bookCache.has(normalized)) {\n return bookCache.get(normalized);\n }\n\n const found = bibleCounts.find(b => {\n const normalizedBook = normalizeBookName(b.book);\n if (normalizedBook === normalized) return true;\n\n const normalizedAliases = b.aliases.map(normalizeBookName);\n return normalizedAliases.includes(normalized);\n }) || null;\n\n bookCache.set(normalized, found);\n return found;\n}\n\n/**\n * Returns the number of chapters for a given Bible book name or alias, or null if the book is not found.\n * @public\n * @param {string} name - The name or alias of the book to lookup, which will be normalized internally.\n * @returns {number|null} - The total number of chapters in the matched book, or null if no book is found.\n * @example\n * // Returns 50 chapters for Genesis\n * getChapterCount('Genesis'); // 50\n * // Returns null for an unknown or invalid book name\n * getChapterCount('Judas');\n */\nfunction getChapterCount(name) {\n const book = getBook(name);\n return book ? book.chapters.length : null;\n}\n\n/**\n * Returns the number of verses in a specified chapter of a given Bible book, or null if the book or chapter is invalid.\n * @public\n * @param {string} name - The name or alias of the book to lookup, which will be normalized internally.\n * @param {number} chapter - The chapter number to retrieve the verse count for; must be within valid range.\n * @returns {number|null} - The count of verses in the specified chapter, or null if the book is unknown or chapter is out of bounds.\n * @example\n * // Returns 25, the number of verses in Genesis chapter 2\n * getVerseCount('GeN. ', 2); // 25\n * // Returns null for an invalid book name\n * getVerseCount('Judas', 1);\n * // Returns null for a chapter number that is too high\n * getVerseCount('Genesis', 999);\n * // Returns null for a chapter number less than 1\n * getVerseCount('Genesis', 0);\n */\nfunction getVerseCount(name, chapter) {\n const book = getBook(name);\n if (!book || chapter < 1 || chapter > book.chapters.length) return null;\n return book.chapters[chapter - 1];\n}\n\n/**\n * Returns an array of all Bible book names in their canonical order.\n * @public\n * @returns {string[]} - An array containing 66 book names starting with Genesis and ending with Revelation.\n * @example\n * // Returns an array of 66 Bible books\n * listBibleBooks();\n * // The first and last elements are Genesis and Revelation respectively\n * const books = listBibleBooks();\n * console.log(books[0]); // \"Genesis\"\n * console.log(books[books.length - 1]); // \"Revelation\"\n */\nfunction listBibleBooks() {\n return bibleCounts.map(b => b.book);\n}\n\n/**\n * Returns all aliases for a given book name, including the official book title, optionally normalized.\n * @public\n * @param {string} bookName - The name or alias of the book to lookup, which will be normalized internally.\n * @param {Object} [options] - Optional settings.\n * @param {boolean} [options.normalized=false] - If true, returns all aliases normalized (lowercased and stripped of special characters).\n * @returns {string[]|null} - An array of aliases including the official book name, either normalized or in original form, or null if no matching book is found.\n * @example\n * // Returns non-normalized aliases for \"Second Corinthians\"\n * listAliases('Second Corinthians');\n * // Expected output: [\"2 Corinthians\", \"2 Co\", ...other aliases]\n * // Returns normalized aliases for \"Song\" with normalization enabled\n * listAliases('Song', { normalized: true });\n * // Expected output: [\"songofsolomon\", \"canticleofcanticles\", \"sos\", ...]\n * // Returns null for unrecognized or empty book names\n * listAliases('UnknownBook'); // null\n * listAliases(null); // null\n * listAliases(''); // null\n */\nfunction listAliases(bookName, { normalized = false } = {}) {\n const book = getBook(bookName);\n if (!book) return null;\n if (normalized) {\n return [book.book, ...book.aliases]\n .map(normalizeBookName)\n .filter(s => s != null);\n }\n return [book.book, ...book.aliases];\n}\n\n/**\n * Returns an array of chapter numbers for a given Bible book, starting from 1 up to the total chapter count.\n * @public\n * @param {string} bookName - The name or alias of the book to lookup, which will be normalized internally.\n * @returns {number[]|null} - An array of chapter numbers from 1 to the book's chapter count, or null if the book is invalid or not found.\n * @example\n * // Returns an array [1, 2, ..., 40] for Exodus, which has 40 chapters\n * listChapters('Exodus'); // [1, 2, 3, ..., 40]\n * // Returns null for an invalid or unknown book\n * listChapters('UnknownBook'); // null\n */\nfunction listChapters(bookName) {\n const count = getChapterCount(bookName);\n if (count == null) return null;\n return Array.from({ length: count }, (_, i) => i + 1);\n}\n\n\n/**\n * Lists all verse numbers for a given book and chapter as a sequential array starting from 1.\n * @public\n * @param {string} bookName - The name or alias of the book to lookup, which will be normalized internally.\n * @param {number} chapter - The chapter number within the book.\n * @returns {number[]|null} - An array of verse numbers from 1 up to the chapter's verse count, or null if the book or chapter is invalid or out of range.\n * @example\n * // Returns an array of verses [1, 2, ..., 31] for Genesis chapter 1\n * listVerses('Genesis', 1); // [1, 2, 3, ..., 31]\n * // Returns null for a missing chapter parameter\n * listVerses('Genesis'); // null\n * // Returns null for an invalid chapter number or unknown book\n * listVerses('Genesis', 0); // null\n * listVerses('Genesis', 999); // null\n * listVerses('UnknownBook', 1); // null\n */\nfunction listVerses(bookName, chapter) {\n const verseCount = getVerseCount(bookName, chapter);\n if (verseCount == null) return null;\n return Array.from({ length: verseCount }, (_, i) => i + 1);\n}\n\nexport {\n getBook,\n getChapterCount,\n getVerseCount,\n listBibleBooks,\n listAliases,\n listChapters,\n listVerses\n};","import { getBook } from './lookup.js';\n\n/**\n * Checks if a given book name or alias corresponds to a valid Bible book.\n * @public\n * @param {string|null|undefined} book - The name or alias of the book to lookup, which will be normalized internally.\n * @returns {boolean} - True if the book exists in the Bible collection, false otherwise.\n * @example\n * // Valid full book name returns true\n * isValidBook('Genesis'); // true\n * // Valid alias, case-insensitive, returns true\n * isValidBook('gEn'); // true\n * // Unknown book returns false\n * isValidBook('Judas'); // false\n * // Empty string returns false\n * isValidBook(''); // false\n * // Null or undefined input returns false\n * isValidBook(null); // false\n * isValidBook(undefined); // false\n */\nfunction isValidBook(book) {\n if (typeof book !== 'string' || book.trim() === '') return false;\n return getBook(book) !== null;\n}\n\n/**\n * Checks if the given chapter number is valid for the specified Bible book.\n * @public\n * @param {string} book - The name or alias of the book to lookup, which will be normalized internally.\n * @param {number} chapter - The chapter number to check, expected to be a positive integer.\n * @returns {boolean} - True if the chapter is within the valid range for the book; otherwise, false.\n * @example\n * // Valid chapters for Genesis include 1 and 50\n * isValidChapter('Genesis', 1); // true\n * isValidChapter('Genesis', 50); // true\n * // Invalid chapters are below 1 or above the book's chapter count\n * isValidChapter('Genesis', 0); // false\n * isValidChapter('Genesis', 51); // false\n * isValidChapter('Genesis', -1); // false\n * // Returns false if the book is unknown or input is null/undefined\n * isValidChapter('Judas', 1); // false\n * isValidChapter(null, 1); // false\n * isValidChapter('Genesis', null); // false\n */\nfunction isValidChapter(book, chapter) {\n const bookObj = getBook(book);\n if (!bookObj) return false;\n return chapter >= 1 && chapter <= bookObj.chapters.length;\n}\n\n/**\n * Validates whether a given Bible reference consisting of book, chapter, and verse(s) is valid.\n * @public\n * @param {string} book - The name or alias of the book to lookup, which will be normalized internally.\n * @param {number} chapter - The chapter number, must be a positive integer within the book's chapter count.\n * @param {number} verseStart - The starting verse number, must be a positive integer within the chapter's verse count.\n * @param {number|null} [verseEnd=null] - Optional ending verse number, must be greater than or equal to verseStart and within the chapter's verse count if provided.\n * @returns {boolean} True if the reference is valid within the book's chapter and verse bounds, otherwise false.\n * @example\n * // Valid single verse in Genesis chapter 1\n * isValidReference('Genesis', 1, 1); // true\n * // Valid last verse in Genesis chapter 1\n * isValidReference('Genesis', 1, 31); // true\n * // Invalid verse number exceeding the number of verses in chapter 1 of Genesis\n * isValidReference('Genesis', 1, 32); // false\n * // Invalid chapter number (0) in Genesis\n * isValidReference('Genesis', 0, 1); // false\n * // Invalid verse number (0) in Genesis chapter 1\n * isValidReference('Genesis', 1, 0); // false\n * // Invalid unknown book name returns false\n * isValidReference('Blah', 1, 1); // false\n * // Reference with a verse range, valid only if verseEnd >= verseStart and within chapter verse count\n * isValidReference('Genesis', 1, 1, 5); // true\n * // Case-insensitive book name input is accepted\n * isValidReference('gEnEsIs', 1, 1); // true\n */\nfunction isValidReference(book, chapter, verseStart, verseEnd = null) {\n const bookObj = getBook(book);\n if (!bookObj || !isValidChapter(book, chapter)) return false;\n const maxVerses = bookObj.chapters[chapter - 1];\n if (verseStart < 1 || verseStart > maxVerses) return false;\n if (verseEnd !== null) {\n if (verseEnd < verseStart || verseEnd > maxVerses) return false;\n }\n return true;\n}\n\nexport {\n isValidBook,\n isValidChapter,\n isValidReference\n};","/**\n * @import { ParseReferenceOptions, ParsedReference, SimpleResult, StructuredResult } from './types.js'\n */\nimport { parseBibleReference } from './normalizer.js';\nimport { getBook } from './lookup.js';\nimport { isValidReference } from './validator.js';\n\n/**\n * Formats a scripture reference string based on the provided input. Input is not normalized.\n * @public\n * @param {Object} reference - The reference object.\n * @param {string} reference.book - The name of the book (e.g., \"Genesis\").\n * @param {number} [reference.chapter] - The chapter number.\n * @param {number} [reference.verseStart] - The starting verse number.\n * @param {number|null} [reference.verseEnd] - The ending verse number (optional, used for ranges).\n * @returns {string} - A formatted Bible reference (e.g., \"Genesis 1:1-5\"). Returns an empty string if no input is provided.\n * @example\n * formatReference({}); // ''\n * formatReference({ book: 'Genesis' }); // 'Genesis'\n * formatReference({ book: 'Genesis', chapter: 1 }); // 'Genesis 1'\n * formatReference({ book: 'Genesis', chapter: 1, verseStart: 1 }); // 'Genesis 1:1'\n * formatReference({ book: 'Genesis', chapter: 1, verseStart: 1, verseEnd: 5 }); // 'Genesis 1:1-5'\n * formatReference({ book: 'Genesis', chapter: 1, verseStart: 3, verseEnd: 3 }); // 'Genesis 1:3'\n */\nfunction formatReference({ book, chapter, verseStart, verseEnd }) {\n if (!book || !chapter) return book || '';\n if (verseStart == null) return `${book} ${chapter}`;\n if (verseEnd == null || verseEnd === verseStart) return `${book} ${chapter}:${verseStart}`;\n return `${book} ${chapter}:${verseStart}-${verseEnd}`;\n}\n\n/**\n * Parses and validates a Bible reference string.\n * @public\n * @param {string} reference - The raw Bible reference string to be parsed, normalized, and formatted (e.g., \"Genesis 1:1\", \"Letter to the Romans. Ch 2 , 1 to 3\").\n * @param {ParseReferenceOptions} [options] - Optional configuration, return structured object or just the formatted result.\n * @returns {SimpleResult|StructuredResult} - Result object depending on options.structured.\n * @example\n * parseAndValidateReference(' GN. Ch 1 , 1 to 3');\n * // → { isValid: true, formatted: 'Genesis 1:1-3', error: null, original: ' GN. Ch 1 , 1 to 3' }\n * parseAndValidateReference('gEnEsIs 1 verse 1', { structured: true });\n * // → {\n * // isValid: true,\n * // book: 'Genesis',\n * // chapter: 1,\n * // verseStart: 1,\n * // verseEnd: null,\n * // formatted: 'Genesis 1:1',\n * // error: null,\n * // original: 'gEnEsIs 1 verse 1'\n * // }\n * parseAndValidateReference('Book of Judas 1:1');\n * // → { isValid: false, error: 'Invalid book name', original: 'Book of Judas 1:1' }\n */\nfunction parseAndValidateReference(reference, { structured = false } = {}) {\n /**\n * @private\n * @param {string} msg\n * @returns {{ isValid: false, error: string, original: string }}\n */\n const fail = (msg) => ({ isValid: false, error: msg, original: reference });\n\n if (typeof reference !== 'string' || !reference.trim()) {\n return fail('Empty or invalid input');\n }\n\n /**\n * @private\n * @type {ParsedReference|null}\n */\n const parsed = parseBibleReference(reference);\n if (!parsed?.book) return fail('Could not parse reference');\n const bookObj = getBook(parsed.book);\n if (!bookObj) return fail('Invalid book name');\n const chapter = parsed.chapter ?? null;\n const verseStart = parsed.verseStart ?? null;\n const verseEnd = parsed.verseEnd ?? null;\n if (chapter === null || verseStart === null) {\n return fail('Missing chapter or verse');\n }\n if (!isValidReference(bookObj.book, chapter, verseStart, verseEnd)) {\n return fail('Invalid chapter or verse');\n }\n const formatted = formatReference({ book: bookObj.book, chapter, verseStart, verseEnd });\n const base = {\n isValid: true,\n formatted,\n error: null,\n original: reference,\n };\n return structured\n ? {\n ...base,\n book: bookObj.book,\n chapter,\n verseStart,\n verseEnd,\n }\n : base;\n}\n\nexport {\n parseAndValidateReference,\n formatReference,\n}"],"names":["normalizeBookName","name","prefixMap","first","second","third","iii","ii","i","cleaned","trim","toLowerCase","replace","prefixMatch","match","key","slice","length","parseChapterVerse","str","nums","split","filter","Boolean","map","t","parseInt","n","isNaN","chapter","verseStart","verseEnd","extractBookAndRange","ref","parseBibleReference","_chapVerse$chapter","_chapVerse$verseStart","_chapVerse$verseEnd","_extractBookAndRange","bookRaw","chapterVerseRaw","book","chapVerse","bookCache","Map","getBook","normalized","has","get","found","bibleCounts","find","b","aliases","includes","set","getChapterCount","chapters","getVerseCount","isValidChapter","bookObj","isValidReference","maxVerses","formatReference","_ref","bookName","_temp","_ref$normalized","concat","s","count","Array","from","_","verseCount","reference","_parsed$chapter","_parsed$verseStart","_parsed$verseEnd","_ref2$structured","structured","fail","msg","isValid","error","original","parsed","base","formatted","_extends"],"mappings":"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"}