UNPKG

bible-passage-reference-parser

Version:

Identifies and parses Bible references (like John 3:16) in over 40 languages.

1,362 lines (1,297 loc) 258 kB
(function() { var bcv_parser, bcv_passage, bcv_utils, root, hasProp = {}.hasOwnProperty; root = this; bcv_parser = (function() { bcv_parser.prototype.s = ""; bcv_parser.prototype.entities = []; bcv_parser.prototype.passage = null; bcv_parser.prototype.regexps = {}; bcv_parser.prototype.options = { consecutive_combination_strategy: "combine", osis_compaction_strategy: "b", book_sequence_strategy: "ignore", invalid_sequence_strategy: "ignore", sequence_combination_strategy: "combine", punctuation_strategy: "us", invalid_passage_strategy: "ignore", non_latin_digits_strategy: "ignore", passage_existence_strategy: "bcv", zero_chapter_strategy: "error", zero_verse_strategy: "error", single_chapter_1_strategy: "chapter", book_alone_strategy: "ignore", book_range_strategy: "ignore", captive_end_digits_strategy: "delete", end_range_digits_strategy: "verse", include_apocrypha: false, ps151_strategy: "c", versification_system: "default", case_sensitive: "none" }; function bcv_parser() { var key, ref, val; this.options = {}; ref = bcv_parser.prototype.options; for (key in ref) { if (!hasProp.call(ref, key)) continue; val = ref[key]; this.options[key] = val; } this.versification_system(this.options.versification_system); } bcv_parser.prototype.parse = function(s) { var ref; this.reset(); this.s = s; s = this.replace_control_characters(s); ref = this.match_books(s), s = ref[0], this.passage.books = ref[1]; this.entities = this.match_passages(s)[0]; return this; }; bcv_parser.prototype.parse_with_context = function(s, context) { var entities, ref, ref1, ref2; this.reset(); ref = this.match_books(this.replace_control_characters(context)), context = ref[0], this.passage.books = ref[1]; ref1 = this.match_passages(context), entities = ref1[0], context = ref1[1]; this.reset(); this.s = s; s = this.replace_control_characters(s); ref2 = this.match_books(s), s = ref2[0], this.passage.books = ref2[1]; this.passage.books.push({ value: "", parsed: [], start_index: 0, type: "context", context: context }); s = "\x1f" + (this.passage.books.length - 1) + "/9\x1f" + s; this.entities = this.match_passages(s)[0]; return this; }; bcv_parser.prototype.reset = function() { this.s = ""; this.entities = []; if (this.passage) { this.passage.books = []; return this.passage.indices = {}; } else { this.passage = new bcv_passage; this.passage.options = this.options; return this.passage.translations = this.translations; } }; bcv_parser.prototype.set_options = function(options) { var key, val; for (key in options) { if (!hasProp.call(options, key)) continue; val = options[key]; if (key === "include_apocrypha" || key === "versification_system" || key === "case_sensitive") { this[key](val); } else { this.options[key] = val; } } return this; }; bcv_parser.prototype.include_apocrypha = function(arg) { var base, base1, ref, translation, verse_count; if (!((arg != null) && (arg === true || arg === false))) { return this; } this.options.include_apocrypha = arg; this.regexps.books = this.regexps.get_books(arg, this.options.case_sensitive); ref = this.translations; for (translation in ref) { if (!hasProp.call(ref, translation)) continue; if (translation === "aliases" || translation === "alternates") { continue; } if ((base = this.translations[translation]).chapters == null) { base.chapters = {}; } if ((base1 = this.translations[translation].chapters)["Ps"] == null) { base1["Ps"] = bcv_utils.shallow_clone_array(this.translations["default"].chapters["Ps"]); } if (arg === true) { if (this.translations[translation].chapters["Ps151"] != null) { verse_count = this.translations[translation].chapters["Ps151"][0]; } else { verse_count = this.translations["default"].chapters["Ps151"][0]; } this.translations[translation].chapters["Ps"][150] = verse_count; } else { if (this.translations[translation].chapters["Ps"].length === 151) { this.translations[translation].chapters["Ps"].pop(); } } } return this; }; bcv_parser.prototype.versification_system = function(system) { var base, base1, base2, book, chapter_list, ref, ref1; if (!((system != null) && (this.translations[system] != null))) { return this; } if (this.translations.alternates["default"] != null) { if (system === "default") { if (this.translations.alternates["default"].order != null) { this.translations["default"].order = bcv_utils.shallow_clone(this.translations.alternates["default"].order); } ref = this.translations.alternates["default"].chapters; for (book in ref) { if (!hasProp.call(ref, book)) continue; chapter_list = ref[book]; this.translations["default"].chapters[book] = bcv_utils.shallow_clone_array(chapter_list); } } else { this.versification_system("default"); } } if ((base = this.translations.alternates)["default"] == null) { base["default"] = { order: null, chapters: {} }; } if (system !== "default" && (this.translations[system].order != null)) { if ((base1 = this.translations.alternates["default"]).order == null) { base1.order = bcv_utils.shallow_clone(this.translations["default"].order); } this.translations["default"].order = bcv_utils.shallow_clone(this.translations[system].order); } if (system !== "default" && (this.translations[system].chapters != null)) { ref1 = this.translations[system].chapters; for (book in ref1) { if (!hasProp.call(ref1, book)) continue; chapter_list = ref1[book]; if ((base2 = this.translations.alternates["default"].chapters)[book] == null) { base2[book] = bcv_utils.shallow_clone_array(this.translations["default"].chapters[book]); } this.translations["default"].chapters[book] = bcv_utils.shallow_clone_array(chapter_list); } } this.options.versification_system = system; this.include_apocrypha(this.options.include_apocrypha); return this; }; bcv_parser.prototype.case_sensitive = function(arg) { if (!((arg != null) && (arg === "none" || arg === "books"))) { return this; } if (arg === this.options.case_sensitive) { return this; } this.options.case_sensitive = arg; this.regexps.books = this.regexps.get_books(this.options.include_apocrypha, arg); return this; }; bcv_parser.prototype.translation_info = function(new_translation) { var book, chapter_list, id, old_translation, out, ref, ref1, ref2; if (new_translation == null) { new_translation = "default"; } if ((new_translation != null) && (((ref = this.translations.aliases[new_translation]) != null ? ref.alias : void 0) != null)) { new_translation = this.translations.aliases[new_translation].alias; } if (!((new_translation != null) && (this.translations[new_translation] != null))) { new_translation = "default"; } old_translation = this.options.versification_system; if (new_translation !== old_translation) { this.versification_system(new_translation); } out = { alias: new_translation, books: [], chapters: {}, order: bcv_utils.shallow_clone(this.translations["default"].order) }; ref1 = this.translations["default"].chapters; for (book in ref1) { if (!hasProp.call(ref1, book)) continue; chapter_list = ref1[book]; out.chapters[book] = bcv_utils.shallow_clone_array(chapter_list); } ref2 = out.order; for (book in ref2) { if (!hasProp.call(ref2, book)) continue; id = ref2[book]; out.books[id - 1] = book; } if (new_translation !== old_translation) { this.versification_system(old_translation); } return out; }; bcv_parser.prototype.replace_control_characters = function(s) { s = s.replace(this.regexps.control, " "); if (this.options.non_latin_digits_strategy === "replace") { s = s.replace(/[٠۰߀०০੦૦୦0౦೦൦๐໐༠၀႐០᠐᥆᧐᪀᪐᭐᮰᱀᱐꘠꣐꤀꧐꩐꯰0]/g, "0"); s = s.replace(/[١۱߁१১੧૧୧௧౧೧൧๑໑༡၁႑១᠑᥇᧑᪁᪑᭑᮱᱁᱑꘡꣑꤁꧑꩑꯱1]/g, "1"); s = s.replace(/[٢۲߂२২੨૨୨௨౨೨൨๒໒༢၂႒២᠒᥈᧒᪂᪒᭒᮲᱂᱒꘢꣒꤂꧒꩒꯲2]/g, "2"); s = s.replace(/[٣۳߃३৩੩૩୩௩౩೩൩๓໓༣၃႓៣᠓᥉᧓᪃᪓᭓᮳᱃᱓꘣꣓꤃꧓꩓꯳3]/g, "3"); s = s.replace(/[٤۴߄४৪੪૪୪௪౪೪൪๔໔༤၄႔៤᠔᥊᧔᪄᪔᭔᮴᱄᱔꘤꣔꤄꧔꩔꯴4]/g, "4"); s = s.replace(/[٥۵߅५৫੫૫୫௫౫೫൫๕໕༥၅႕៥᠕᥋᧕᪅᪕᭕᮵᱅᱕꘥꣕꤅꧕꩕꯵5]/g, "5"); s = s.replace(/[٦۶߆६৬੬૬୬௬౬೬൬๖໖༦၆႖៦᠖᥌᧖᪆᪖᭖᮶᱆᱖꘦꣖꤆꧖꩖꯶6]/g, "6"); s = s.replace(/[٧۷߇७৭੭૭୭௭౭೭൭๗໗༧၇႗៧᠗᥍᧗᪇᪗᭗᮷᱇᱗꘧꣗꤇꧗꩗꯷7]/g, "7"); s = s.replace(/[٨۸߈८৮੮૮୮௮౮೮൮๘໘༨၈႘៨᠘᥎᧘᪈᪘᭘᮸᱈᱘꘨꣘꤈꧘꩘꯸8]/g, "8"); s = s.replace(/[٩۹߉९৯੯૯୯௯౯೯൯๙໙༩၉႙៩᠙᥏᧙᪉᪙᭙᮹᱉᱙꘩꣙꤉꧙꩙꯹9]/g, "9"); } return s; }; bcv_parser.prototype.match_books = function(s) { var book, books, has_replacement, k, len, ref; books = []; ref = this.regexps.books; for (k = 0, len = ref.length; k < len; k++) { book = ref[k]; has_replacement = false; s = s.replace(book.regexp, function(full, prev, bk) { var extra; has_replacement = true; books.push({ value: bk, parsed: book.osis, type: "book" }); extra = book.extra != null ? "/" + book.extra : ""; return prev + "\x1f" + (books.length - 1) + extra + "\x1f"; }); if (has_replacement === true && /^[\s\x1f\d:.,;\-\u2013\u2014]+$/.test(s)) { break; } } s = s.replace(this.regexps.translations, function(match) { books.push({ value: match, parsed: match.toLowerCase(), type: "translation" }); return "\x1e" + (books.length - 1) + "\x1e"; }); return [s, this.get_book_indices(books, s)]; }; bcv_parser.prototype.get_book_indices = function(books, s) { var add_index, match, re; add_index = 0; re = /([\x1f\x1e])(\d+)(?:\/\d+)?\1/g; while (match = re.exec(s)) { books[match[2]].start_index = match.index + add_index; add_index += books[match[2]].value.length - match[0].length; } return books; }; bcv_parser.prototype.match_passages = function(s) { var accum, book_id, entities, full, match, next_char, original_part_length, part, passage, post_context, ref, regexp_index_adjust, start_index_adjust; entities = []; post_context = {}; while (match = this.regexps.escaped_passage.exec(s)) { full = match[0], part = match[1], book_id = match[2]; original_part_length = part.length; match.index += full.length - original_part_length; if (/\s[2-9]\d\d\s*$|\s\d{4,}\s*$/.test(part)) { part = part.replace(/\s+\d+\s*$/, ""); } if (!/[\d\x1f\x1e)]$/.test(part)) { part = this.replace_match_end(part); } if (this.options.captive_end_digits_strategy === "delete") { next_char = match.index + part.length; if (s.length > next_char && /^\w/.test(s.substr(next_char, 1))) { part = part.replace(/[\s*]+\d+$/, ""); } part = part.replace(/(\x1e[)\]]?)[\s*]*\d+$/, "$1"); } part = part.replace(/[A-Z]+/g, function(capitals) { return capitals.toLowerCase(); }); start_index_adjust = part.substr(0, 1) === "\x1f" ? 0 : part.split("\x1f")[0].length; passage = { value: grammar.parse(part, { punctuation_strategy: this.options.punctuation_strategy }), type: "base", start_index: this.passage.books[book_id].start_index - start_index_adjust, match: part }; if (this.options.book_alone_strategy === "full" && this.options.book_range_strategy === "include" && passage.value[0].type === "b" && (passage.value.length === 1 || (passage.value.length > 1 && passage.value[1].type === "translation_sequence")) && start_index_adjust === 0 && (this.passage.books[book_id].parsed.length === 1 || (this.passage.books[book_id].parsed.length > 1 && this.passage.books[book_id].parsed[1].type === "translation")) && /^[234]/.test(this.passage.books[book_id].parsed[0])) { this.create_book_range(s, passage, book_id); } ref = this.passage.handle_obj(passage), accum = ref[0], post_context = ref[1]; entities = entities.concat(accum); regexp_index_adjust = this.adjust_regexp_end(accum, original_part_length, part.length); if (regexp_index_adjust > 0) { this.regexps.escaped_passage.lastIndex -= regexp_index_adjust; } } return [entities, post_context]; }; bcv_parser.prototype.adjust_regexp_end = function(accum, old_length, new_length) { var regexp_index_adjust; regexp_index_adjust = 0; if (accum.length > 0) { regexp_index_adjust = old_length - accum[accum.length - 1].indices[1] - 1; } else if (old_length !== new_length) { regexp_index_adjust = old_length - new_length; } return regexp_index_adjust; }; bcv_parser.prototype.replace_match_end = function(part) { var match, remove; remove = part.length; while (match = this.regexps.match_end_split.exec(part)) { remove = match.index + match[0].length; } if (remove < part.length) { part = part.substr(0, remove); } return part; }; bcv_parser.prototype.create_book_range = function(s, passage, book_id) { var cases, i, k, limit, prev, range_regexp, ref; cases = [bcv_parser.prototype.regexps.first, bcv_parser.prototype.regexps.second, bcv_parser.prototype.regexps.third]; limit = parseInt(this.passage.books[book_id].parsed[0].substr(0, 1), 10); for (i = k = 1, ref = limit; 1 <= ref ? k < ref : k > ref; i = 1 <= ref ? ++k : --k) { range_regexp = i === limit - 1 ? bcv_parser.prototype.regexps.range_and : bcv_parser.prototype.regexps.range_only; prev = s.match(RegExp("(?:^|\\W)(" + cases[i - 1] + "\\s*" + range_regexp + "\\s*)\\x1f" + book_id + "\\x1f", "i")); if (prev != null) { return this.add_book_range_object(passage, prev, i); } } return false; }; bcv_parser.prototype.add_book_range_object = function(passage, prev, start_book_number) { var i, k, length, ref, ref1, results; length = prev[1].length; passage.value[0] = { type: "b_range_pre", value: [ { type: "b_pre", value: start_book_number.toString(), indices: [prev.index, prev.index + length] }, passage.value[0] ], indices: [0, passage.value[0].indices[1] + length] }; passage.value[0].value[1].indices[0] += length; passage.value[0].value[1].indices[1] += length; passage.start_index -= length; passage.match = prev[1] + passage.match; if (passage.value.length === 1) { return; } results = []; for (i = k = 1, ref = passage.value.length; 1 <= ref ? k < ref : k > ref; i = 1 <= ref ? ++k : --k) { if (passage.value[i].value == null) { continue; } if (((ref1 = passage.value[i].value[0]) != null ? ref1.indices : void 0) != null) { passage.value[i].value[0].indices[0] += length; passage.value[i].value[0].indices[1] += length; } passage.value[i].indices[0] += length; results.push(passage.value[i].indices[1] += length); } return results; }; bcv_parser.prototype.osis = function() { var k, len, osis, out, ref; out = []; ref = this.parsed_entities(); for (k = 0, len = ref.length; k < len; k++) { osis = ref[k]; if (osis.osis.length > 0) { out.push(osis.osis); } } return out.join(","); }; bcv_parser.prototype.osis_and_translations = function() { var k, len, osis, out, ref; out = []; ref = this.parsed_entities(); for (k = 0, len = ref.length; k < len; k++) { osis = ref[k]; if (osis.osis.length > 0) { out.push([osis.osis, osis.translations.join(",")]); } } return out; }; bcv_parser.prototype.osis_and_indices = function() { var k, len, osis, out, ref; out = []; ref = this.parsed_entities(); for (k = 0, len = ref.length; k < len; k++) { osis = ref[k]; if (osis.osis.length > 0) { out.push({ osis: osis.osis, translations: osis.translations, indices: osis.indices }); } } return out; }; bcv_parser.prototype.parsed_entities = function() { var entity, entity_id, i, k, l, last_i, len, len1, length, m, n, osis, osises, out, passage, ref, ref1, ref2, ref3, strings, translation, translation_alias, translation_osis, translations; out = []; for (entity_id = k = 0, ref = this.entities.length; 0 <= ref ? k < ref : k > ref; entity_id = 0 <= ref ? ++k : --k) { entity = this.entities[entity_id]; if (entity.type && entity.type === "translation_sequence" && out.length > 0 && entity_id === out[out.length - 1].entity_id + 1) { out[out.length - 1].indices[1] = entity.absolute_indices[1]; } if (entity.passages == null) { continue; } if ((entity.type === "b" && this.options.book_alone_strategy === "ignore") || (entity.type === "b_range" && this.options.book_range_strategy === "ignore") || entity.type === "context") { continue; } translations = []; translation_alias = null; if (entity.passages[0].translations != null) { ref1 = entity.passages[0].translations; for (l = 0, len = ref1.length; l < len; l++) { translation = ref1[l]; translation_osis = ((ref2 = translation.osis) != null ? ref2.length : void 0) > 0 ? translation.osis : ""; if (translation_alias == null) { translation_alias = translation.alias; } translations.push(translation_osis); } } else { translations = [""]; translation_alias = "default"; } osises = []; length = entity.passages.length; for (i = m = 0, ref3 = length; 0 <= ref3 ? m < ref3 : m > ref3; i = 0 <= ref3 ? ++m : --m) { passage = entity.passages[i]; if (passage.type == null) { passage.type = entity.type; } if (passage.valid.valid === false) { if (this.options.invalid_sequence_strategy === "ignore" && entity.type === "sequence") { this.snap_sequence("ignore", entity, osises, i, length); } if (this.options.invalid_passage_strategy === "ignore") { continue; } } if ((passage.type === "b" || passage.type === "b_range") && this.options.book_sequence_strategy === "ignore" && entity.type === "sequence") { this.snap_sequence("book", entity, osises, i, length); continue; } if ((passage.type === "b_range_start" || passage.type === "range_end_b") && this.options.book_range_strategy === "ignore") { this.snap_range(entity, i); } if (passage.absolute_indices == null) { passage.absolute_indices = entity.absolute_indices; } osises.push({ osis: passage.valid.valid ? this.to_osis(passage.start, passage.end, translation_alias) : "", type: passage.type, indices: passage.absolute_indices, translations: translations, start: passage.start, end: passage.end, enclosed_indices: passage.enclosed_absolute_indices, entity_id: entity_id, entities: [passage] }); } if (osises.length === 0) { continue; } if (osises.length > 1 && this.options.consecutive_combination_strategy === "combine") { osises = this.combine_consecutive_passages(osises, translation_alias); } if (this.options.sequence_combination_strategy === "separate") { out = out.concat(osises); } else { strings = []; last_i = osises.length - 1; if ((osises[last_i].enclosed_indices != null) && osises[last_i].enclosed_indices[1] >= 0) { entity.absolute_indices[1] = osises[last_i].enclosed_indices[1]; } for (n = 0, len1 = osises.length; n < len1; n++) { osis = osises[n]; if (osis.osis.length > 0) { strings.push(osis.osis); } } out.push({ osis: strings.join(","), indices: entity.absolute_indices, translations: translations, entity_id: entity_id, entities: osises }); } } return out; }; bcv_parser.prototype.to_osis = function(start, end, translation) { var osis, out; if ((end.c == null) && (end.v == null) && start.b === end.b && (start.c == null) && (start.v == null) && this.options.book_alone_strategy === "first_chapter") { end.c = 1; } osis = { start: "", end: "" }; if (start.c == null) { start.c = 1; } if (start.v == null) { start.v = 1; } if (end.c == null) { if (this.options.passage_existence_strategy.indexOf("c") >= 0 || ((this.passage.translations[translation].chapters[end.b] != null) && this.passage.translations[translation].chapters[end.b].length === 1)) { end.c = this.passage.translations[translation].chapters[end.b].length; } else { end.c = 999; } } if (end.v == null) { if ((this.passage.translations[translation].chapters[end.b][end.c - 1] != null) && this.options.passage_existence_strategy.indexOf("v") >= 0) { end.v = this.passage.translations[translation].chapters[end.b][end.c - 1]; } else { end.v = 999; } } if (this.options.include_apocrypha && this.options.ps151_strategy === "b" && ((start.c === 151 && start.b === "Ps") || (end.c === 151 && end.b === "Ps"))) { this.fix_ps151(start, end, translation); } if (this.options.osis_compaction_strategy === "b" && start.c === 1 && start.v === 1 && ((end.c === 999 && end.v === 999) || (end.c === this.passage.translations[translation].chapters[end.b].length && this.options.passage_existence_strategy.indexOf("c") >= 0 && (end.v === 999 || (end.v === this.passage.translations[translation].chapters[end.b][end.c - 1] && this.options.passage_existence_strategy.indexOf("v") >= 0))))) { osis.start = start.b; osis.end = end.b; } else if (this.options.osis_compaction_strategy.length <= 2 && start.v === 1 && (end.v === 999 || (end.v === this.passage.translations[translation].chapters[end.b][end.c - 1] && this.options.passage_existence_strategy.indexOf("v") >= 0))) { osis.start = start.b + "." + start.c.toString(); osis.end = end.b + "." + end.c.toString(); } else { osis.start = start.b + "." + start.c.toString() + "." + start.v.toString(); osis.end = end.b + "." + end.c.toString() + "." + end.v.toString(); } if (osis.start === osis.end) { out = osis.start; } else { out = osis.start + "-" + osis.end; } if (start.extra != null) { out = start.extra + "," + out; } if (end.extra != null) { out += "," + end.extra; } return out; }; bcv_parser.prototype.fix_ps151 = function(start, end, translation) { var ref; if (translation !== "default" && (((ref = this.translations[translation]) != null ? ref.chapters["Ps151"] : void 0) == null)) { this.passage.promote_book_to_translation("Ps151", translation); } if (start.c === 151 && start.b === "Ps") { if (end.c === 151 && end.b === "Ps") { start.b = "Ps151"; start.c = 1; end.b = "Ps151"; return end.c = 1; } else { start.extra = this.to_osis({ b: "Ps151", c: 1, v: start.v }, { b: "Ps151", c: 1, v: this.passage.translations[translation].chapters["Ps151"][0] }, translation); start.b = "Prov"; start.c = 1; return start.v = 1; } } else { end.extra = this.to_osis({ b: "Ps151", c: 1, v: 1 }, { b: "Ps151", c: 1, v: end.v }, translation); end.c = 150; return end.v = this.passage.translations[translation].chapters["Ps"][149]; } }; bcv_parser.prototype.combine_consecutive_passages = function(osises, translation) { var enclosed_sequence_start, has_enclosed, i, is_enclosed_last, k, last_i, osis, out, prev, prev_i, ref; out = []; prev = {}; last_i = osises.length - 1; enclosed_sequence_start = -1; has_enclosed = false; for (i = k = 0, ref = last_i; 0 <= ref ? k <= ref : k >= ref; i = 0 <= ref ? ++k : --k) { osis = osises[i]; if (osis.osis.length > 0) { prev_i = out.length - 1; is_enclosed_last = false; if (osis.enclosed_indices[0] !== enclosed_sequence_start) { enclosed_sequence_start = osis.enclosed_indices[0]; } if (enclosed_sequence_start >= 0 && (i === last_i || osises[i + 1].enclosed_indices[0] !== osis.enclosed_indices[0])) { is_enclosed_last = true; has_enclosed = true; } if (this.is_verse_consecutive(prev, osis.start, translation)) { out[prev_i].end = osis.end; out[prev_i].is_enclosed_last = is_enclosed_last; out[prev_i].indices[1] = osis.indices[1]; out[prev_i].enclosed_indices[1] = osis.enclosed_indices[1]; out[prev_i].osis = this.to_osis(out[prev_i].start, osis.end, translation); } else { out.push(osis); } prev = { b: osis.end.b, c: osis.end.c, v: osis.end.v }; } else { out.push(osis); prev = {}; } } if (has_enclosed) { this.snap_enclosed_indices(out); } return out; }; bcv_parser.prototype.snap_enclosed_indices = function(osises) { var k, len, osis; for (k = 0, len = osises.length; k < len; k++) { osis = osises[k]; if (osis.is_enclosed_last != null) { if (osis.enclosed_indices[0] < 0 && osis.is_enclosed_last) { osis.indices[1] = osis.enclosed_indices[1]; } delete osis.is_enclosed_last; } } return osises; }; bcv_parser.prototype.is_verse_consecutive = function(prev, check, translation) { var translation_order; if (prev.b == null) { return false; } translation_order = this.passage.translations[translation].order != null ? this.passage.translations[translation].order : this.passage.translations["default"].order; if (prev.b === check.b) { if (prev.c === check.c) { if (prev.v === check.v - 1) { return true; } } else if (check.v === 1 && prev.c === check.c - 1) { if (prev.v === this.passage.translations[translation].chapters[prev.b][prev.c - 1]) { return true; } } } else if (check.c === 1 && check.v === 1 && translation_order[prev.b] === translation_order[check.b] - 1) { if (prev.c === this.passage.translations[translation].chapters[prev.b].length && prev.v === this.passage.translations[translation].chapters[prev.b][prev.c - 1]) { return true; } } return false; }; bcv_parser.prototype.snap_range = function(entity, passage_i) { var entity_i, key, pluck, ref, source_entity, target_entity, temp, type; if (entity.type === "b_range_start" || (entity.type === "sequence" && entity.passages[passage_i].type === "b_range_start")) { entity_i = 1; source_entity = "end"; type = "b_range_start"; } else { entity_i = 0; source_entity = "start"; type = "range_end_b"; } target_entity = source_entity === "end" ? "start" : "end"; ref = entity.passages[passage_i][target_entity]; for (key in ref) { if (!hasProp.call(ref, key)) continue; entity.passages[passage_i][target_entity][key] = entity.passages[passage_i][source_entity][key]; } if (entity.type === "sequence") { if (passage_i >= entity.value.length) { passage_i = entity.value.length - 1; } pluck = this.passage.pluck(type, entity.value[passage_i]); if (pluck != null) { temp = this.snap_range(pluck, 0); if (passage_i === 0) { entity.absolute_indices[0] = temp.absolute_indices[0]; } else { entity.absolute_indices[1] = temp.absolute_indices[1]; } } } else { entity.original_type = entity.type; entity.type = entity.value[entity_i].type; entity.absolute_indices = [entity.value[entity_i].absolute_indices[0], entity.value[entity_i].absolute_indices[1]]; } return entity; }; bcv_parser.prototype.snap_sequence = function(type, entity, osises, i, length) { var passage; passage = entity.passages[i]; if (passage.absolute_indices[0] === entity.absolute_indices[0] && i < length - 1 && this.get_snap_sequence_i(entity.passages, i, length) !== i) { entity.absolute_indices[0] = entity.passages[i + 1].absolute_indices[0]; this.remove_absolute_indices(entity.passages, i + 1); } else if (passage.absolute_indices[1] === entity.absolute_indices[1] && i > 0) { entity.absolute_indices[1] = osises.length > 0 ? osises[osises.length - 1].indices[1] : entity.passages[i - 1].absolute_indices[1]; } else if (type === "book" && i < length - 1 && !this.starts_with_book(entity.passages[i + 1])) { entity.passages[i + 1].absolute_indices[0] = passage.absolute_indices[0]; } return entity; }; bcv_parser.prototype.get_snap_sequence_i = function(passages, i, length) { var j, k, ref, ref1; for (j = k = ref = i + 1, ref1 = length; ref <= ref1 ? k < ref1 : k > ref1; j = ref <= ref1 ? ++k : --k) { if (this.starts_with_book(passages[j])) { return j; } if (passages[j].valid.valid) { return i; } } return i; }; bcv_parser.prototype.starts_with_book = function(passage) { if (passage.type.substr(0, 1) === "b") { return true; } if ((passage.type === "range" || passage.type === "ff") && passage.start.type.substr(0, 1) === "b") { return true; } return false; }; bcv_parser.prototype.remove_absolute_indices = function(passages, i) { var end, k, len, passage, ref, ref1, start; if (passages[i].enclosed_absolute_indices[0] < 0) { return false; } ref = passages[i].enclosed_absolute_indices, start = ref[0], end = ref[1]; ref1 = passages.slice(i); for (k = 0, len = ref1.length; k < len; k++) { passage = ref1[k]; if (passage.enclosed_absolute_indices[0] === start && passage.enclosed_absolute_indices[1] === end) { passage.enclosed_absolute_indices = [-1, -1]; } else { break; } } return true; }; return bcv_parser; })(); root.bcv_parser = bcv_parser; bcv_passage = (function() { function bcv_passage() {} bcv_passage.prototype.books = []; bcv_passage.prototype.indices = {}; bcv_passage.prototype.options = {}; bcv_passage.prototype.translations = {}; bcv_passage.prototype.handle_array = function(passages, accum, context) { var k, len, passage, ref; if (accum == null) { accum = []; } if (context == null) { context = {}; } for (k = 0, len = passages.length; k < len; k++) { passage = passages[k]; if (passage == null) { continue; } if (passage.type === "stop") { break; } ref = this.handle_obj(passage, accum, context), accum = ref[0], context = ref[1]; } return [accum, context]; }; bcv_passage.prototype.handle_obj = function(passage, accum, context) { if ((passage.type != null) && (this[passage.type] != null)) { return this[passage.type](passage, accum, context); } else { return [accum, context]; } }; bcv_passage.prototype.b = function(passage, accum, context) { var alternates, b, k, len, obj, ref, valid; passage.start_context = bcv_utils.shallow_clone(context); passage.passages = []; alternates = []; ref = this.books[passage.value].parsed; for (k = 0, len = ref.length; k < len; k++) { b = ref[k]; valid = this.validate_ref(passage.start_context.translations, { b: b }); obj = { start: { b: b }, end: { b: b }, valid: valid }; if (passage.passages.length === 0 && valid.valid) { passage.passages.push(obj); } else { alternates.push(obj); } } if (passage.passages.length === 0) { passage.passages.push(alternates.shift()); } if (alternates.length > 0) { passage.passages[0].alternates = alternates; } if (passage.start_context.translations != null) { passage.passages[0].translations = passage.start_context.translations; } if (passage.absolute_indices == null) { passage.absolute_indices = this.get_absolute_indices(passage.indices); } accum.push(passage); context = { b: passage.passages[0].start.b }; if (passage.start_context.translations != null) { context.translations = passage.start_context.translations; } return [accum, context]; }; bcv_passage.prototype.b_range = function(passage, accum, context) { return this.range(passage, accum, context); }; bcv_passage.prototype.b_range_pre = function(passage, accum, context) { var book, end, ref, ref1, start_obj; passage.start_context = bcv_utils.shallow_clone(context); passage.passages = []; book = this.pluck("b", passage.value); ref = this.b(book, [], context), (ref1 = ref[0], end = ref1[0]), context = ref[1]; if (passage.absolute_indices == null) { passage.absolute_indices = this.get_absolute_indices(passage.indices); } start_obj = { b: passage.value[0].value + end.passages[0].start.b.substr(1), type: "b" }; passage.passages = [ { start: start_obj, end: end.passages[0].end, valid: end.passages[0].valid } ]; if (passage.start_context.translations != null) { passage.passages[0].translations = passage.start_context.translations; } accum.push(passage); return [accum, context]; }; bcv_passage.prototype.b_range_start = function(passage, accum, context) { return this.range(passage, accum, context); }; bcv_passage.prototype.base = function(passage, accum, context) { this.indices = this.calculate_indices(passage.match, passage.start_index); return this.handle_array(passage.value, accum, context); }; bcv_passage.prototype.bc = function(passage, accum, context) { var alternates, b, c, context_key, k, len, obj, ref, ref1, valid; passage.start_context = bcv_utils.shallow_clone(context); passage.passages = []; this.reset_context(context, ["b", "c", "v"]); c = this.pluck("c", passage.value).value; alternates = []; ref = this.books[this.pluck("b", passage.value).value].parsed; for (k = 0, len = ref.length; k < len; k++) { b = ref[k]; context_key = "c"; valid = this.validate_ref(passage.start_context.translations, { b: b, c: c }); obj = { start: { b: b }, end: { b: b }, valid: valid }; if (valid.messages.start_chapter_not_exist_in_single_chapter_book || valid.messages.start_chapter_1) { obj.valid = this.validate_ref(passage.start_context.translations, { b: b, v: c }); if (valid.messages.start_chapter_not_exist_in_single_chapter_book) { obj.valid.messages.start_chapter_not_exist_in_single_chapter_book = 1; } obj.start.c = 1; obj.end.c = 1; context_key = "v"; } obj.start[context_key] = c; ref1 = this.fix_start_zeroes(obj.valid, obj.start.c, obj.start.v), obj.start.c = ref1[0], obj.start.v = ref1[1]; if (obj.start.v == null) { delete obj.start.v; } obj.end[context_key] = obj.start[context_key]; if (passage.passages.length === 0 && obj.valid.valid) { passage.passages.push(obj); } else { alternates.push(obj); } } if (passage.passages.length === 0) { passage.passages.push(alternates.shift()); } if (alternates.length > 0) { passage.passages[0].alternates = alternates; } if (passage.start_context.translations != null) { passage.passages[0].translations = passage.start_context.translations; } if (passage.absolute_indices == null) { passage.absolute_indices = this.get_absolute_indices(passage.indices); } this.set_context_from_object(context, ["b", "c", "v"], passage.passages[0].start); accum.push(passage); return [accum, context]; }; bcv_passage.prototype.bc_title = function(passage, accum, context) { var bc, i, k, ref, ref1, ref2, title; passage.start_context = bcv_utils.shallow_clone(context); ref = this.bc(this.pluck("bc", passage.value), [], context), (ref1 = ref[0], bc = ref1[0]), context = ref[1]; if (bc.passages[0].start.b.substr(0, 2) !== "Ps" && (bc.passages[0].alternates != null)) { for (i = k = 0, ref2 = bc.passages[0].alternates.length; 0 <= ref2 ? k < ref2 : k > ref2; i = 0 <= ref2 ? ++k : --k) { if (bc.passages[0].alternates[i].start.b.substr(0, 2) !== "Ps") { continue; } bc.passages[0] = bc.passages[0].alternates[i]; break; } } if (bc.passages[0].start.b.substr(0, 2) !== "Ps") { accum.push(bc); return [accum, context]; } this.books[this.pluck("b", bc.value).value].parsed = ["Ps"]; title = this.pluck("title", passage.value); if (title == null) { title = this.pluck("v", passage.value); } passage.value[1] = { type: "v", value: [ { type: "integer", value: 1, indices: title.indices } ], indices: title.indices }; passage.type = "bcv"; return this.bcv(passage, accum, passage.start_context); }; bcv_passage.prototype.bcv = function(passage, accum, context) { var alternates, b, bc, c, k, len, obj, ref, ref1, v, valid; passage.start_context = bcv_utils.shallow_clone(context); passage.passages = []; this.reset_context(context, ["b", "c", "v"]); bc = this.pluck("bc", passage.value); c = this.pluck("c", bc.value).value; v = this.pluck("v", passage.value).value; alternates = []; ref = this.books[this.pluck("b", bc.value).value].parsed; for (k = 0, len = ref.length; k < len; k++) { b = ref[k]; valid = this.validate_ref(passage.start_context.translations, { b: b, c: c, v: v }); ref1 = this.fix_start_zeroes(valid, c, v), c = ref1[0], v = ref1[1]; obj = { start: { b: b, c: c, v: v }, end: { b: b, c: c, v: v }, valid: valid }; if (passage.passages.length === 0 && valid.valid) { passage.passages.push(obj); } else { alternates.push(obj); } } if (passage.passages.length === 0) { passage.passages.push(alternates.shift()); } if (alternates.length > 0) { passage.passages[0].alternates = alternates; } if (passage.start_context.translations != null) { passage.passages[0].translations = passage.start_context.translations; } if (passage.absolute_indices == null) { passage.absolute_indices = this.get_absolute_indices(passage.indices); } this.set_context_from_object(context, ["b", "c", "v"], passage.passages[0].start); accum.push(passage); return [accum, context]; }; bcv_passage.prototype.bv = function(passage, accum, context) { var b, bcv, ref, ref1, ref2, v; passage.start_context = bcv_utils.shallow_clone(context); ref = passage.value, b = ref[0], v = ref[1]; bcv = { indices: passage.indices, value: [ { type: "bc", value: [ b, { type: "c", value: [ { type: "integer", value: 1 } ] } ] }, v ] }; ref1 = this.bcv(bcv, [], context), (ref2 = ref1[0], bcv = ref2[0]), context = ref1[1]; passage.passages = bcv.passages; if (passage.absolute_indices == null) { passage.absolute_indices = this.get_absolute_indices(passage.indices); } accum.push(passage); return [accum, context]; }; bcv_passage.prototype.c = function(passage, accum, context) { var c, valid; passage.start_context = bcv_utils.shallow_clone(context); c = passage.type === "integer" ? passage.value : this.pluck("integer", passage.value).value; valid = this.validate_ref(passage.start_context.translations, { b: context.b, c: c }); if (!valid.valid && valid.messages.start_chapter_not_exist_in_single_chapter_book) { return this.v(passage, accum, context); } c = this.fix_start_zeroes(valid, c)[0]; passage.passages = [ { start: { b: context.b, c: c }, end: { b: context.b, c: c }, valid: valid } ]; if (passage.start_context.translations != null) { passage.passages[0].translations = passage.start_context.translations; } accum.push(passage); context.c = c; this.reset_context(context, ["v"]); if (passage.absolute_indices == null) { passage.absolute_indices = this.get_absolute_indices(passage.indices); } return [accum, context]; }; bcv_passage.prototype.c_psalm = function(passage, accum, context) { var c; passage.type = "bc"; c = parseInt(this.books[passage.value].value.match(/^\d+/)[0], 10); passage.value = [ { type: "b", value: passage.value, indices: passage.indices }, { type: "c", value: [ { type: "integer", value: c, indices: passage.indices } ], indices: passage.indices } ]; return this.bc(passage, accum, context); }; bcv_passage.prototype.c_title = function(passage, accum, context) { var title; passage.start_context = bcv_utils.shallow_clone(context); if (context.b !== "Ps") { return this.c(passage.value[0], accum, context); } title = this.pluck("title", passage.value); passage.value[1] = { type: "v", value: [ { type: "integer", value: 1, indices: title.indices } ], indices: title.indices }; passage.type = "cv"; return this.cv(passage, accum, passage.start_context); }; bcv_passage.prototype.cv = function(passage, accum, context) { var c, ref, v, valid; passage.start_context = bcv_utils.shallow_clone(context); c = this.pluck("c", passage.value).value; v = this.pluck("v", passage.value).value; valid = this.validate_ref(passage.start_context.translations, { b: context.b, c: c, v: v }); ref = this.fix_start_zeroes(valid, c, v), c = ref[0], v = ref[1]; passage.passages = [ { start: { b: context.b, c: c, v: v }, end: { b: context.b, c: c, v: v }, valid: valid } ]; if (passage.start_context.translations != null) { passage.passages[0].translations = passage.start_context.translations; } accum.push(passage); context.c = c; context.v = v; if (passage.absolute_indices == null) { passage.absolute_indices = this.get_absolute_indices(passage.indices); } return [accum, context]; }; bcv_passage.prototype.cb_range = function(passage, accum, context) { var b, end_c, ref, start_c; passage.type = "range"; ref = passage.value, b = ref[0], start_c = ref[1], end_c = ref[2]; passage.value = [ { type: "bc", value: [b, start_c], indices: passage.indices }, end_c ]; end_c.indices[1] = passage.indices[1]; return this.range(passage, accum, context); }; bcv_passage.prototype.context = function(passage, accum, context) { var key, ref; passage.start_context = bcv_utils.shallow_clone(context); passage.passages = []; ref = this.books[passage.value].context; for (key in ref) { if (!hasProp.call(ref, key)) continue; context[key] = this.books[passage.value].context[key]; } accum.push(passage); return [accum, context]; }; bcv_passage.prototype.cv_psalm = function(passage, accum, context) { var bc, c_psalm, ref, v; passage.start_context = bcv_utils.shallow_clone(context); passage.type = "bcv"; ref = passage.value, c_psalm = ref[0], v = ref[1]; bc = this.c_psalm(c_psalm, [], passage.start_context)[0][0]; passage.value = [bc, v]; return this.bcv(passage, accum, context); }; bcv_passage.prototype.ff = function(passage, accum, context) { var ref, ref1; passage.start_context = bcv_utils.shallow_clone(context); passage.value.push({ type: "integer", indices: passage.indices, value: 999 }); ref = this.range(passage, [], passage.start_context), (ref1 = ref[0], passage = ref1[0]), context = ref[1]; passage.value[0].indices = passage.value[1].indices; passage.value[0].absolute_indices = passage.value[1].absolute_indices; passage.value.pop(); if (passage.passages[0].valid.messages.end_verse_not_exist != null) { delete passage.passages[0].valid.messages.end_verse_not_exist; } if (passage.passages[0].valid.messages.end_chapter_not_exist != null) { delete passage.passages[0].valid.messages.end_chapter_not_exist; } if (passage.passages[0].end.original_c != null) { delete passage.passages[0].end.original_c; } accum.push(passage); return [accum, context]; }; bcv_passage.prototype.integer_title = function(passage, accum, context) { passage.start_context = bcv_utils.shallow_clone(context); if (context.b !== "Ps") { return this.integer(passage.value[0], accum, context); } passage.value[0] = { type: "c", value: [passage.value[0]], indices: [passage.value[0].indices[0], passage.value[0].indices[1]] }; passage.value[1].type = "v"; passage.value[1].original_type = "title"; passage.value[1].value = [ { type: "integer", value: 1, indices: passage.value[1].value.indices } ]; passage.type = "cv"; return this.cv(passage, accum, passage.start_c