// This code was written by Jeremy and Jason Wall. // Feel free to use, and if you can, include a link back to www.walljm.com // Jason@walljm.com // www.walljm.com // Jeremy@marzhillstudios.com // jeremy.marzhillstudios.com /// class StringUtils { public static trim(str: string): string { return str.replace(/^\s+|\s+$/g, ""); } public static ltrim(str: string): string { return str.replace(/^\s+/, ""); } public static rtrim(str: string): string { return str.replace(/\s+$/, ""); } } export class Reference { private ref: string; public Section: Section; public errAcc: string; constructor(reference: string) { this.Section = { start: { book: -1, bookname: "", longbookname: "", lastchapter: -1, chapter: "", verse: "" }, end: { book: -1, bookname: "", longbookname: "", lastchapter: -1, chapter: "", verse: "" } }; this.ref = reference.toLowerCase().trim(); this.parseReference(); if (this.Section.end.book == -1) { this.Section.end.book = this.Section.start.book; this.Section.end.bookname = this.Section.start.bookname; this.Section.end.longbookname = this.Section.start.longbookname; this.Section.end.lastchapter = this.Section.start.lastchapter; } if (this.Section.end.chapter == "") this.Section.end.chapter = this.Section.start.chapter; if ( Number(this.Section.start.verse) > Number(this.Section.end.verse) && this.Section.start.chapter == this.Section.end.chapter && this.Section.start.book == this.Section.end.book ) this.Section.end.verse = this.Section.start.verse; if (this.Section.start.verse == "") this.Section.start.verse = "1"; if (this.Section.end.verse == "") this.Section.end.verse = "*"; } private parseReference() { this.parseBook(false); this.parseFirstNum(false); let foundFirstVerse = this.ref.search(/:.*-/) != -1; this.maybeParseSecondNum(false); this.maybeParseRangeSep(); let foundSecondBook = this.ref.search(/\w\s+\d/i) != -1; this.maybeParseBook(true); this.maybeParseFirstNumOrVerse(foundSecondBook, foundFirstVerse, true); this.maybeParseSecondNum(true); }; private parseBook(isEnd?: boolean) { this.ref = this.ref.toLowerCase().trim(); let thing = this.Section.start; if (isEnd) thing = this.Section.end; let fbook = this.ref.substring(0, this.ref.search(/\w\s+\d/i) + 1); if (!fbook) fbook = this.ref; this.ref = this.ref.slice(this.ref.search(/\w\s+\d/i) + 1); if (fbook.search(/\b(genesis|gen|ge|gn)\b/i) != -1) { thing.book = 1; thing.bookname = "Genesis"; thing.longbookname = "Genesis"; thing.lastchapter = 50; } if (fbook.search(/\b(exodus|ex|exo|exod|exd)\b/i) != -1) { thing.book = 2; thing.bookname = "Exodus"; thing.longbookname = "Exodus"; thing.lastchapter = 40; } if (fbook.search(/\b(leviticus|lev|le|levi|lv)\b/i) != -1) { thing.book = 3; thing.bookname = "Leviticus"; thing.longbookname = "Leviticus"; thing.lastchapter = 27; } if (fbook.search(/\b(numbers|num|nu|numb|number)\b/i) != -1) { thing.book = 4; thing.bookname = "Numbers"; thing.longbookname = "Book_of_Numbers"; thing.lastchapter = 36; } if (fbook.search(/\b(deuteronomy|deut|de|dt|deu)\b/i) != -1) { thing.book = 5; thing.bookname = "Deuteronomy"; thing.longbookname = "Deuteronomy"; thing.lastchapter = 34; } if (fbook.search(/\b(joshua|josh|jos)\b/i) != -1) { thing.book = 6; thing.bookname = "Joshua"; thing.longbookname = "Book_of_Joshua"; thing.lastchapter = 24; } if (fbook.search(/\b(judges|jud|ju|jdg|judg)\b/i) != -1) { thing.book = 7; thing.bookname = "Judges"; thing.longbookname = "Book_of_Judges"; thing.lastchapter = 21; } if (fbook.search(/\b(ruth|ru)\b/i) != -1) { thing.book = 8; thing.bookname = "Ruth"; thing.longbookname = "Book_of_Ruth"; thing.lastchapter = 4; } if (fbook.search(/\b(1|i|1st|first)\s*(samuel|sa|sam|sml)\b/i) != -1) { thing.book = 9; thing.bookname = "1 Samuel"; thing.longbookname = "First_Samuel"; thing.lastchapter = 31; } if (fbook.search(/\b(2|ii|2nd|second|sec)\s*(samuel|sa|sam|sml)\b/i) != -1) { thing.book = 10; thing.bookname = "2 Samuel"; thing.longbookname = "Second_Samuel"; thing.lastchapter = 24; } if (fbook.search(/\b(1|i|1st|first)\s*(kings|king|kgs|kn|k|ki)\b/i) != -1) { thing.book = 11; thing.bookname = "1 Kings"; thing.longbookname = "First_Kings"; thing.lastchapter = 22; } if (fbook.search(/\b(2|ii|2nd|second|sec)\s*(kings|king|kgs|kn|k|ki)\b/i) != -1) { thing.book = 12; thing.bookname = "2 Kings"; thing.longbookname = "Second_Kings"; thing.lastchapter = 25; } if (fbook.search(/\b(1|i|1st|first)\s*(chronicles|chron|ch|chr)\b/i) != -1) { thing.book = 13; thing.bookname = "1 Chronicles"; thing.longbookname = "First_Chronicles"; thing.lastchapter = 29; } if (fbook.search(/\b(2|ii|2nd|second|sec)\s*(chronicles|chron|ch|chr)\b/i) != -1) { thing.book = 14; thing.bookname = "2 Chronicles"; thing.longbookname = "Second_Chronicles"; thing.lastchapter = 36; } if (fbook.search(/\b(ezra|ez|ezr)\b/i) != -1) { thing.book = 15; thing.bookname = "Ezra"; thing.longbookname = "Book_of_Ezra"; thing.lastchapter = 10; } if (fbook.search(/\b(nehemiah|neh|ne|nehamiah)\b/i) != -1) { thing.book = 16; thing.bookname = "Nehemiah"; thing.longbookname = "Book_of_Nehemiah"; thing.lastchapter = 13; } if (fbook.search(/\b(esther|est|es|esth)\b/i) != -1) { thing.book = 17; thing.bookname = "Esther"; thing.longbookname = "Book_of_Esther"; thing.lastchapter = 10; } if (fbook.search(/\b(job|jo|jb)\b/i) != -1) { thing.book = 18; thing.bookname = "Job"; thing.longbookname = "Book_of_Job"; thing.lastchapter = 42; } if (fbook.search(/\b(psalms|ps|psa|psalm|psm)\b/i) != -1) { thing.book = 19; thing.bookname = "Psalm"; thing.longbookname = "Psalm"; thing.lastchapter = 150; } if (fbook.search(/\b(proverbs|prov|pr|pro|proverb|prv|prvbs)\b/i) != -1) { thing.book = 20; thing.bookname = "Proverbs"; thing.longbookname = "Book_of_Proverbs"; thing.lastchapter = 31; } if (fbook.search(/\b(ecclesiastes|eccl|ecc|eccles|ec|ecl|ecclesiaste)\b/i) != -1) { thing.book = 21; thing.bookname = "Ecclesiastes"; thing.longbookname = "Ecclesiastes"; thing.lastchapter = 12; } if (fbook.search(/\b(song\sof\ssolomon|song\sof\ssongs|sos|ss|son|so|song|songs)\b/i) != -1) { thing.book = 22; thing.bookname = "Song of Solomon"; thing.longbookname = "Song_of_Solomon"; thing.lastchapter = 8; } if (fbook.search(/\b(isaiah|is|is|isah|isai|ia)\b/i) != -1) { thing.book = 23; thing.bookname = "Isaiah"; thing.longbookname = "Book_of_Isaiah"; thing.lastchapter = 66; } if (fbook.search(/\b(jerimiah|jeremiah|jer|je|jere)\b/i) != -1) { thing.book = 24; thing.bookname = "Jeremiah"; thing.longbookname = "Book_of_Jeremiah"; thing.lastchapter = 52; } if (fbook.search(/\b(lamentations|lam|la|lamentation)\b/i) != -1) { thing.book = 25; thing.bookname = "Lamentations"; thing.longbookname = "Book_of_Lamentations"; thing.lastchapter = 5; } if (fbook.search(/\b(ezekiel|eze|ez|ezk|ezek)\b/i) != -1) { thing.book = 26; thing.bookname = "Ezekiel"; thing.longbookname = "Book_of_Ezekiel"; thing.lastchapter = 48; } if (fbook.search(/\b(daniel|dan|dn|dl|da)\b/i) != -1) { thing.book = 27; thing.bookname = "Daniel"; thing.longbookname = "Book_of_Daniel"; thing.lastchapter = 12; } if (fbook.search(/\b(hosea|hos|ho)\b/i) != -1) { thing.book = 28; thing.bookname = "Hosea"; thing.longbookname = "Book_of_Hosea"; thing.lastchapter = 14; } if (fbook.search(/\b(joel|joe|jl)\b/i) != -1) { thing.book = 29; thing.bookname = "Joel"; thing.longbookname = "Book_of_Joel"; thing.lastchapter = 3; } if (fbook.search(/\b(amos|am|amo)\b/i) != -1) { thing.book = 30; thing.bookname = "Amos"; thing.longbookname = "Book_of_Amos"; thing.lastchapter = 9; } if (fbook.search(/\b(obadiah|oba|ob|obad)\b/i) != -1) { thing.book = 31; thing.bookname = "Obadiah"; thing.longbookname = "Book_of_Obadiah"; thing.lastchapter = 1; } if (fbook.search(/\b(jonah|jnh|jon)\b/i) != -1) { thing.book = 32; thing.bookname = "Jonah"; thing.longbookname = "Book_of_Jonah"; thing.lastchapter = 4; } if (fbook.search(/\b(micah|mic|mi)\b/i) != -1) { thing.book = 33; thing.bookname = "Micah"; thing.longbookname = "Book_of_Micah"; thing.lastchapter = 7; } if (fbook.search(/\b(nahum|nah|na)\b/i) != -1) { thing.book = 34; thing.bookname = "Nahum"; thing.longbookname = "Book_of_Nahum"; thing.lastchapter = 3; } if (fbook.search(/\b(habakkuk|hab|ha|habakuk)\b/i) != -1) { thing.book = 35; thing.bookname = "Habakkuk"; thing.longbookname = "Book_of_Habakkuk"; thing.lastchapter = 3; } if (fbook.search(/\b(zephaniah|zeph|zep)\b/i) != -1) { thing.book = 36; thing.bookname = "Zephaniah"; thing.longbookname = "Book_of_Zephaniah"; thing.lastchapter = 3; } if (fbook.search(/\b(haggia|hag|hg|haggai)\b/i) != -1) { thing.book = 37; thing.bookname = "Haggai"; thing.longbookname = "Book_of_Haggai"; thing.lastchapter = 2; } if (fbook.search(/\b(zechariah|zech|zch|zec)\b/i) != -1) { thing.book = 38; thing.bookname = "Zechariah"; thing.longbookname = "Book_of_Zechariah"; thing.lastchapter = 14; } if (fbook.search(/\b(malachi|mal)\b/i) != -1) { thing.book = 39; thing.bookname = "Malachi"; thing.longbookname = "Book_of_Malachi"; thing.lastchapter = 4; } if (fbook.search(/\b(matthew|mt|matt|mat)\b/i) != -1) { thing.book = 40; thing.bookname = "Matthew"; thing.longbookname = "Gospel_of_Matthew"; thing.lastchapter = 28; } if (fbook.search(/\b(mark|mrk|mk|mr)\b/i) != -1) { thing.book = 41; thing.bookname = "Mark"; thing.longbookname = "Gospel_of_Mark"; thing.lastchapter = 16; } if (fbook.search(/\b(luke|lu|lke|luk|lk)\b/i) != -1) { thing.book = 42; thing.bookname = "Luke"; thing.longbookname = "Gospel_of_Luke"; thing.lastchapter = 24; } if (fbook.search(/\b(john|jn|jhn)\b/i) != -1) { thing.book = 43; thing.bookname = "John"; thing.longbookname = "Gospel_of_John"; thing.lastchapter = 21; } if (fbook.search(/\b(acts|ac|act)\b/i) != -1) { thing.book = 44; thing.bookname = "Acts"; thing.longbookname = "Acts_of_the_Apostles"; thing.lastchapter = 28; } if (fbook.search(/\b(romans|rom|ro|rm|roman)\b/i) != -1) { thing.book = 45; thing.bookname = "Romans"; thing.longbookname = "Epistle_to_the_Romans"; thing.lastchapter = 16; } if (fbook.search(/\b(1|i|1st|first)\s*(corinthian|cor|corinthians|corinth|corin|corth|corint)\b/i) != -1) { thing.book = 46; thing.bookname = "1 Corinthians"; thing.longbookname = "First_Epistle_to_the_Corinthians"; thing.lastchapter = 16; } if (fbook.search(/\b(2|ii|2nd|second|sec)\s*(corinthian|cor|corinthians|corinth|corin|corth|corint)\b/i) != -1) { thing.book = 47; thing.bookname = "2 Corinthians"; thing.longbookname = "Second_Epistle_to_the_Corinthians"; thing.lastchapter = 13; } if (fbook.search(/\b(galatians|galatian|galations|gal|ga|gala|galation|galat)\b/i) != -1) { thing.book = 48; thing.bookname = "Galatians"; thing.longbookname = "Epistle_to_the_Galatians"; thing.lastchapter = 6; } if (fbook.search(/\b(ephesians|eph|ep|ephes|ephe|ephs)\b/i) != -1) { thing.book = 49; thing.bookname = "Ephesians"; thing.longbookname = "Epistle_to_the_Ephesians"; thing.lastchapter = 6; } if (fbook.search(/\b(philippians|phi|phil|ph|philip)\b/i) != -1) { thing.book = 50; thing.bookname = "Philippians"; thing.longbookname = "Epistle_to_the_Philippians"; thing.lastchapter = 4; } if (fbook.search(/\b(colossians|col|co|colossian|colos|coloss)\b/i) != -1) { thing.book = 51; thing.bookname = "Colossians"; thing.longbookname = "Epistle_to_the_Colossians"; thing.lastchapter = 4; } if (fbook.search(/\b(1|i|1st|first)\s*(thessalonians|the|thessa|thessalonian|thes|thess|th)\b/i) != -1) { thing.book = 52; thing.bookname = "1 Thessalonians"; thing.longbookname = "First_Epistle_to_the_Thessalonians"; thing.lastchapter = 5; } if (fbook.search(/\b(2|ii|2nd|second|sec)\s*(thessalonians|the|thessa|thessalonian|thes|thess|th)\b/i) != -1) { thing.book = 53; thing.bookname = "2 Thessalonians"; thing.longbookname = "Second_Epistle_to_the_Thessalonians"; thing.lastchapter = 3; } if (fbook.search(/\b(1|i|1st|first)\s*(timothy|tim|ti|timoth|tm)\b/i) != -1) { thing.book = 54; thing.bookname = "1 Timothy"; thing.longbookname = "First_Epistle_to_Timothy"; thing.lastchapter = 6; } if (fbook.search(/\b(2|ii|2nd|second|sec)\s*(timothy|tim|timoth|tm)\b/i) != -1) { thing.book = 55; thing.bookname = "2 Timothy"; thing.longbookname = "Second_Epistle_to_Timothy"; thing.lastchapter = 4; } if (fbook.search(/\b(titus|tit)\b/i) != -1) { thing.book = 56; thing.bookname = "Titus"; thing.longbookname = "Epistle_to_Titus"; thing.lastchapter = 3; } if (fbook.search(/\b(philemon|phlmn|phl|phm|phile|philem)\b/i) != -1) { thing.book = 57; thing.bookname = "Philemon"; thing.longbookname = "Epistle_to_Philemon"; thing.lastchapter = 1; } if (fbook.search(/\b(hebrews|heb|he|hebrew)\b/i) != -1) { thing.book = 58; thing.bookname = "Hebrews"; thing.longbookname = "Epistle_to_the_Hebrews"; thing.lastchapter = 13; } if (fbook.search(/\b(james|jam|ja|jas|jms|jame|jm)\b/i) != -1) { thing.book = 59; thing.bookname = "James"; thing.longbookname = "Epistle_of_James"; thing.lastchapter = 5; } if (fbook.search(/\b(1|i|1st|first)\s*(peter|pe|pet|pete|pt|p)\b/i) != -1) { thing.book = 60; thing.bookname = "1 Peter"; thing.longbookname = "First_Epistle_of_Peter"; thing.lastchapter = 5; } if (fbook.search(/\b(2|ii|2nd|second|sec)\s*(peter|pe|pet|pete|pt|p)\b/i) != -1) { thing.book = 61; thing.bookname = "2 Peter"; thing.longbookname = "Second_Epistle_of_Peter"; thing.lastchapter = 3; } if (fbook.search(/\b(1|i|1st|first)\s*(john|jn|jo)\b/i) != -1) { thing.book = 62; thing.bookname = "1 John"; thing.longbookname = "First_Epistle_of_John"; thing.lastchapter = 5; } if (fbook.search(/\b(2|ii|2nd|second|sec)\s*(john|jn|jo)\b/i) != -1) { thing.book = 63; thing.bookname = "2 John"; thing.longbookname = "Second_Epistle_of_John"; thing.lastchapter = 1; } if (fbook.search(/\b(3|iii|3rd|third)\s*(john|jn|jo)\b/i) != -1) { thing.book = 64; thing.bookname = "3 John"; thing.longbookname = "Third_Epistle_of_John"; thing.lastchapter = 1; } if (fbook.search(/\b(jude|jud|ju)\b/i) != -1) { thing.book = 65; thing.bookname = "Jude"; thing.longbookname = "Epistle_of_Jude"; thing.lastchapter = 1; } if (fbook.search(/\b(revelation|rev|re|revelations|rv)\b/i) != -1) { thing.book = 66; thing.bookname = "Revelation"; thing.longbookname = "Book_of_Revelations"; thing.lastchapter = 22; } } private parseFirstNum(isEnd: boolean) { let thing = this.Section.start; if (isEnd) thing = this.Section.end; this.ref = StringUtils.ltrim(this.ref); let found = false; for (let i = 0; i <= this.ref.length; i++) { let c = this.ref.charAt(i); // Grab characters until we hit a non digit. if ("0".charAt(0) <= c && c <= "9".charAt(0)) { found = true; thing.chapter = thing.chapter.concat(c); } else { // if the chapter is longer than 3 digits it's an error if (thing.chapter.length > 3) { this.errAcc = "Chapter too long\"" + thing.chapter + "\"."; return; } else if (!found) { this.errAcc = "No chapter found" + this.ref; } this.ref = this.ref.slice(i); return; } } } private parseSecondNum(skipColon?: boolean, isEnd?: boolean) { let thing = this.Section.start; if (isEnd) thing = this.Section.end; this.ref = StringUtils.ltrim(this.ref.toLowerCase()); if (!skipColon) { if (this.ref[0] != ":") { return; } this.ref = this.ref.slice(1); } this.ref = StringUtils.ltrim(this.ref.toLowerCase()); if (this.ref[0] == "*") { thing.verse = "*"; this.ref = this.ref.slice(1); return; } for (var i = 0; i <= this.ref.length; i++) { let c = this.ref.charAt(i); if ("0".charAt(0) <= c && c <= "9".charAt(0)) { thing.verse = thing.verse.concat(c); } else { if (thing.verse.length > 3) { this.errAcc = "Verse too long \"" + thing.verse + "\"."; return ""; } this.ref = this.ref.slice(i); return; } } } private maybeParseBook(isEnd: boolean) { return this.maybeDo(() => { if (this.ref.search(/\w\s+\d/i) == -1) { this.Section.end.book = this.Section.start.book; this.Section.end.bookname = this.Section.start.bookname; this.Section.end.longbookname = this.Section.start.longbookname; this.Section.end.lastchapter = this.Section.start.lastchapter; } else { this.parseBook(isEnd) } }); }; private maybeParseSecondNum(isEnd?: boolean) { return this.maybeDo(() => { this.parseSecondNum(false, isEnd); }); }; private maybeParseFirstNumOrVerse(foundSecondBook: boolean, foundFirstVerse: boolean, isEnd: boolean) { let self = this; return this.maybeDo(() => { if (self.Section.end.book == self.Section.start.book) { if (self.ref.search(/:/) != -1 || foundSecondBook || !foundFirstVerse) { self.parseFirstNum(isEnd); } self.parseSecondNum(true, isEnd); } }); }; private maybeParseRangeSep() { let self = this; return this.maybeDo(() => { if (self.ref[0] == "-") { self.ref = StringUtils.ltrim(self.ref.slice(1)); } }); }; private maybeDo(f) { let func = f; this.ref = StringUtils.ltrim(this.ref.toLowerCase()); if (this.ref != "") { func(); } }; public toString() { // get the starting book, chapter, verse let ref = this.Section.start.bookname.concat(" "). concat(this.Section.start.chapter).concat(":"). concat(this.Section.start.verse); if (this.Section.start.chapter == this.Section.end.chapter && this.Section.start.verse == this.Section.end.verse && this.Section.start.book == this.Section.end.book) { return ref; } if (this.Section.start.chapter == this.Section.end.chapter && this.Section.start.verse != this.Section.end.verse && this.Section.start.book == this.Section.end.book) { return ref.concat(" - ").concat(this.Section.end.verse); } if (this.Section.start.book != this.Section.end.book) { ref = ref.concat(" - ").concat(this.Section.end.bookname).concat(" "); } else { ref = ref.concat(" - "); } ref = ref.concat(this.Section.end.chapter).concat(":"); return ref.concat(this.Section.end.verse); }; public static bookName(booknum: number): string { let book = new Array(); book[0] = ""; book[1] = "Genesis"; book[2] = "Exodus"; book[3] = "Leviticus"; book[4] = "Numbers"; book[5] = "Deuteronomy"; book[6] = "Joshua"; book[7] = "Judges"; book[8] = "Ruth"; book[9] = "1 Samuel"; book[10] = "2 Samuel"; book[11] = "1 Kings"; book[12] = "2 Kings"; book[13] = "1 Chronicles"; book[14] = "2 Chronicles"; book[15] = "Ezra"; book[16] = "Nehemiah"; book[17] = "Esther"; book[18] = "Job"; book[19] = "Psalm"; book[20] = "Proverbs"; book[21] = "Ecclesiastes"; book[22] = "Song of Songs"; book[23] = "Isaiah"; book[24] = "Jeremiah"; book[25] = "Lamentations"; book[26] = "Ezekiel"; book[27] = "Daniel"; book[28] = "Hosea"; book[29] = "Joel"; book[30] = "Amos"; book[31] = "Obadiah"; book[32] = "Jonah"; book[33] = "Micah"; book[34] = "Nahum"; book[35] = "Habakkuk"; book[36] = "Zephaniah"; book[37] = "Haggai"; book[38] = "Zechariah"; book[39] = "Malachi"; book[40] = "Matthew"; book[41] = "Mark"; book[42] = "Luke"; book[43] = "John"; book[44] = "Acts"; book[45] = "Romans"; book[46] = "1 Corinthians"; book[47] = "2 Corinthians"; book[48] = "Galatians"; book[49] = "Ephesians"; book[50] = "Philippians"; book[51] = "Colossians"; book[52] = "1 Thessalonians"; book[53] = "2 Thessalonians"; book[54] = "1 Timothy"; book[55] = "2 Timothy"; book[56] = "Titus"; book[57] = "Philemon"; book[58] = "Hebrews"; book[59] = "James"; book[60] = "1 Peter"; book[61] = "2 Peter"; book[62] = "1 John"; book[63] = "2 John"; book[64] = "3 John"; book[65] = "Jude"; book[66] = "Revelation"; return book[booknum]; } }