@sahabaplus/mushaf-engine
Version:
TypeScript implementation of a Quran Mushaf navigation engine
176 lines (175 loc) • 6.34 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.VersesNavigator = void 0;
const direction_1 = require("./direction");
/**
* A class responsible for navigating through verses in the Mushaf
*/
class VersesNavigator {
/**
* Create a new VersesNavigator
*
* @param mushaf - The Mushaf to navigate through
* @param metadata - Metadata about the Quran
*/
constructor(mushaf, metadata) {
this.mushaf = mushaf;
this.quranMetadata = metadata;
this.currentPageIdx = 0;
this.currentVerseIdx = 0;
}
/**
* Reset the navigator to a specific verse position
*
* @param suraNumber - Sura number (1-114)
* @param verseNumber - Verse number within the sura
* @returns The current verse after reset, or undefined if not found
*/
resetPosition(suraNumber, verseNumber) {
const versePos = this.findVerse(suraNumber, verseNumber);
if (versePos) {
const [_, page, idx] = versePos;
this.currentPageIdx = page - 1;
this.currentVerseIdx = idx;
return this.currentVerse();
}
return undefined;
}
/**
* Get the current verse
*
* @returns The current verse
*/
currentVerse() {
const currentPageVerses = this.mushaf.pages[this.currentPageIdx].verses();
return currentPageVerses[this.currentVerseIdx];
}
/**
* Move to the next verse based on direction
*
* @param direction - Direction to navigate
* @returns The next verse, or undefined if not found
*/
nextVerse(direction) {
switch (direction) {
case direction_1.Direction.Downwards:
return this.nextVerseDownward();
case direction_1.Direction.Upwards:
return this.nextVerseUpward();
}
}
/**
* Move to the next verse in downward direction
*
* @returns The next verse, or undefined if not found
*/
nextVerseDownward() {
const mushaf = this.mushaf.pages;
// Try to move to the next verse on the current page
this.currentVerseIdx += 1;
// If we've reached the end of current page, move to next page
if (this.currentVerseIdx >= mushaf[this.currentPageIdx].verses().length) {
this.currentPageIdx += 1;
this.currentVerseIdx = 0;
// Check if we've reached the end of the mushaf
if (this.currentPageIdx >= mushaf.length) {
// Select last verse of quran
this.currentPageIdx = mushaf.length - 1;
this.currentVerseIdx = mushaf[this.currentPageIdx].verses().length - 1;
}
}
return this.currentVerse();
}
/**
* Move to the previous sura
*
* @param currentSura - Current sura number
* @returns The first verse of the previous sura, or undefined if not found
*/
movePreSura(currentSura) {
const preSura = this.quranMetadata.getSuraInfo(currentSura - 1);
if (!preSura)
return undefined;
const firstPageIdx = preSura.startPage - 1;
const firstPage = this.mushaf.pages[firstPageIdx];
// Find first verse index
for (let idx = 0; idx < firstPage.verses().length; idx++) {
const verse = firstPage.verses()[idx];
if (verse.sura === preSura.number) {
this.currentPageIdx = firstPageIdx;
this.currentVerseIdx = idx;
return verse;
}
}
throw new Error("Unreachable code: Should have found a verse");
}
/**
* Move to the next verse in upward direction
*
* @returns The next verse, or undefined if not found
*/
nextVerseUpward() {
const pages = this.mushaf.pages;
const currentVerse = this.currentVerse(); // Reference current verse
let currentVerseIdx = this.currentVerseIdx + 1;
let currentPageIdx = this.currentPageIdx;
// Check if the next verse index is valid + in same sura
if (currentVerseIdx >= pages[currentPageIdx].verses().length) {
// Move to previous sura
currentPageIdx += 1;
currentVerseIdx = 0;
}
if (currentPageIdx >= pages.length ||
pages[currentPageIdx].verses()[currentVerseIdx].sura !== currentVerse.sura) {
return this.movePreSura(currentVerse.sura);
}
// Move next normally
this.currentVerseIdx = currentVerseIdx;
this.currentPageIdx = currentPageIdx;
return this.currentVerse();
}
/**
* Find a verse in the mushaf and return its location (Verse, page, index_of_verse)
*
* @param suraNumber - Sura number (1-114)
* @param verseNumber - Verse number within the sura
* @returns The verse and its location, or undefined if not found
*/
findVerse(suraNumber, verseNumber) {
const sura = this.quranMetadata.getSuraInfo(suraNumber);
if (sura) {
const pages = this.mushaf.pages;
for (let i = sura.startPage; i <= sura.endPage; i++) {
const page = pages[i - 1];
for (let j = 0; j < page.verses().length; j++) {
const verse = page.verses()[j];
if (verse.sura === suraNumber && verse.number === verseNumber) {
return [verse, page.number, j];
}
}
}
}
return undefined;
}
/**
* Calculate the lines taken by a verse including any sura headers
*
* @param verse - The verse to calculate lines for
* @returns The total number of lines taken by the verse
*/
calculateVerseLines(verse) {
let totalLines = verse.lines;
// Add lines for sura headers if this is the first verse of a sura
if (verse.number === 1) {
// All suras except At-Tawbah (9) have bismillah
if (verse.sura !== 9) {
totalLines += 2.0; // Sura title + bismillah
}
else {
totalLines += 1.0; // Only sura title for At-Tawbah
}
}
return totalLines;
}
}
exports.VersesNavigator = VersesNavigator;