UNPKG

versification

Version:

A library for parsing Paratext's vrs files.

200 lines (161 loc) 6.64 kB
import * as canon from './Canon' import Versification from './Versification' export default class VerseRef { private _bbbcccvvv: number; private _bbb: number; private _ccc: number; private _vvv: number; private _vvvEnd: number | undefined; private _segment: string | undefined; private _versification; public constructor(bbbcccvvv: number | string, rangeEnd?: number, segment?: string, versification?: Versification) { this._bbbcccvvv = typeof bbbcccvvv === 'string' ? parseInt(bbbcccvvv) : bbbcccvvv; this._bbb = VerseRef.toBook(this._bbbcccvvv); this._ccc = VerseRef.toChapter(this._bbbcccvvv); this._vvv = VerseRef.toVerse(this._bbbcccvvv); this._vvvEnd = rangeEnd; this._segment = segment; if (versification && !(versification instanceof Versification)) throw new TypeError(`versification : "${versification}" is wrong type.`) this._versification = versification; } public static toBook(bbbcccvvv: number) {return Math.round(bbbcccvvv / 1000000)} public static toChapter(bbbcccvvv: number) {return Math.round(bbbcccvvv / 1000) % 1000} public static toVerse(bbbcccvvv: number) {return bbbcccvvv % 1000} public static parse(verseRef: string, versification?: Versification): VerseRef | undefined { const [book, chapterVerse] = verseRef.split(' '); const bookNumber = canon.bookIdToNumber(book); const [chapter, verse] = chapterVerse.split(':'); if (bookNumber === undefined) return undefined; const verseNum = parseInt(verse); const verseNumLength = `${verseNum}`.length; if (verse.includes('-')) { const [startVerse, endVerse] = verse.split('-'); return this.fromBookChapterVerseWithRange(bookNumber, parseInt(chapter), parseInt(startVerse), parseInt(endVerse), versification); } else if (verseNumLength < verse.length) { const segment = verse.substring(verseNumLength); return this.fromBookChapterVerseWithSegment(bookNumber, parseInt(chapter), verseNum, segment, versification); } return this.fromBookChapterVerse(bookNumber, parseInt(chapter), verseNum, versification); } public static fromBookIdChapterVerse(bookId: string, chapter: number | string, verse: number | string, versification?: Versification): VerseRef | undefined { if (bookId === null || bookId === undefined || chapter === null || chapter === undefined || verse === null || verse === undefined) return undefined; return VerseRef.parse(`${bookId} ${chapter}:${verse}`, versification); } public static fromBookChapterVerse(book: number, chapter: number, verse: number, versification?: Versification): VerseRef { return this.frombcv(book * 1000000 + chapter * 1000 + verse, versification); } protected static fromBookChapterVerseWithRange(book: number, chapter: number, startVerse: number, endVerse: number, versification?: Versification) { return this.frombcvWithRange(book * 1000000 + chapter * 1000 + startVerse, endVerse, versification); } protected static fromBookChapterVerseWithSegment(book: number, chapter: number, verse: number, segment: string, versification?: Versification) { return this.frombcvWithSegment(book * 1000000 + chapter * 1000 + verse, segment, versification); } protected static frombcvWithRange(bbbcccvvv: number | string, vvvEnd: number, versification?: Versification) { return new VerseRef(bbbcccvvv, vvvEnd, undefined, versification); } protected static frombcvWithSegment(bbbcccvvv: number | string, segment: string, versification?: Versification) { return new VerseRef(bbbcccvvv, undefined, segment, versification); } protected copyFrom(verseRef: VerseRef) { this._bbbcccvvv = verseRef._bbbcccvvv; this._bbb = verseRef._bbb; this._ccc = verseRef._ccc; this._vvv = verseRef._vvv; this._vvvEnd = verseRef._vvvEnd; this._segment = verseRef._segment; this._versification = verseRef._versification; } public static frombcv(bbbcccvvv: number | string, versification?: Versification): VerseRef { return new VerseRef(bbbcccvvv, undefined, undefined, versification); } book() { return canon.bookNumberToId(this._bbb); } chapter() { return this._ccc.toString(); } verse() { const extra = (this._vvvEnd ? `-${this._vvvEnd}` : this._segment) || ''; return this._vvv.toString() + extra; } verseNum() { return this._vvv; } verseNumEnd() { return this._vvvEnd; } segment() { return this._segment; } versification() { return this._versification; } changeVersification(newVersification: Versification) { const newVerseRef = newVersification.changeVersification(this); this.copyFrom(newVerseRef) } bbbcccvvv(): number { return this._bbbcccvvv; } // compare two verseRef assuming same versification. static _equal(a: VerseRef, b: VerseRef) { return a.bbbcccvvv() === b.bbbcccvvv() && a.verseNumEnd() === b.verseNumEnd() && a.segment() === b.segment(); } equals(verseRef: VerseRef | undefined) { if (!verseRef) return false; if (this.versification() === verseRef.versification() || !this._versification) return VerseRef._equal(this, verseRef); const updatedVerseRef = this._versification.changeVersification(verseRef); return VerseRef._equal(this, updatedVerseRef); } isDefinedByVersification() : boolean { const versification = this.versification(); if (!versification) return true; const numberOfVerses = versification.books()?.[this._bbb]?.[this._ccc]; if (!numberOfVerses) return false; const inRange = numberOfVerses >= this._vvv; if (!inRange) return false; if (versification.excludedVerses().has(this._bbbcccvvv)) return false; return true; } toString() { return `${this.book()} ${this.chapter()}:${this.verse()}`; } }