bible-passage-reference-parser
Version:
Identifies and parses Bible references (like John 3:16) in over 40 languages.
1,362 lines (1,297 loc) • 255 kB
JavaScript
(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