@sahabaplus/mushaf-engine
Version:
TypeScript implementation of a Quran Mushaf navigation engine
237 lines (236 loc) • 9.14 kB
TypeScript
import { Mushaf, QuranMetadata, Verse } from "../mushaf";
import { Direction } from "./direction";
import { NavigationSettings } from "./navigationSettings";
import { VersePosition } from "./versePosition";
/**
* A navigator for moving through verses in the Mushaf with bounded iteration support.
*
* `VersesNavigator` provides controlled navigation through Quranic verses with support
* for bounded ranges and iteration limits. It automatically handles direction changes
* and maintains iteration state for cycling through defined ranges.
*
* # Key Features
*
* ## Bounded Navigation
* - Navigate within specific verse ranges using `NavigationBounds`
* - Control iteration limits to cycle through ranges multiple times
* - Automatic bounds reversal when changing direction
*
* ## Iteration Behavior
* The navigator tracks iteration count and manages cycling behavior:
* - When reaching `lowerBound` with remaining iterations: resets to `upperBound`
* - When reaching `lowerBound` with no remaining iterations: returns `undefined`
* - Iteration count is incremented each time a cycle completes
*
* ## Direction Support
* - **Downwards**: Navigate from lower sura numbers to higher (1→114)
* - **Upwards**: Navigate from higher sura numbers to lower (114→1)
* - Bounds are automatically reversed when direction changes
*/
export declare class VersesNavigator {
private mushaf;
private quranMetadata;
private currentPageIdx;
private currentVerseIdx;
private settings;
private direction;
private iterationCount;
/**
* Set to `true` when `nextVerse()` or `previousVerse()` wraps from
* end_bound back to start_bound (or vice-versa). Reset to `false`
* on the next call. Callers can read this after each call to detect
* that a boundary wrap just occurred.
*/
crossedBoundaries: boolean;
/**
* Creates a new `VersesNavigator` with specified settings and direction.
*
* @param mushaf - The Mushaf containing verse data
* @param metadata - Quran metadata for sura information
* @param settings - Navigation settings including bounds and iteration limits
* @param direction - Navigation direction (automatically adjusts bounds)
*/
constructor(mushaf: Mushaf, metadata: QuranMetadata, settings: NavigationSettings, direction: Direction);
/**
* Creates a builder for `VersesNavigator` with default settings.
*
* Default settings:
* - `direction`: `Direction.Downwards`
* - `iterationLimit`: 0 (no cycling)
* - `upperBound`: (1, 1) - beginning of Al-Fatiha
* - `lowerBound`: (114, 6) - end of An-Nas
* - `ignoreSuraHeader`: false (include headers)
*/
static builder(mushaf: Mushaf, metadata: QuranMetadata): VersesNavigator;
/**
* Check if navigation direction is wrong for given start and end positions
*/
static isWrongDirection(start: VersePosition | {
sura: number;
verse: number;
}, end: VersePosition | {
sura: number;
verse: number;
}, direction: Direction): boolean;
/**
* Get the start bound based on current direction
*/
getStartBound(): VersePosition;
/**
* Get the end bound based on current direction
*/
getEndBound(): VersePosition;
/**
* Reset the navigator to a specific verse position
*
* @param verse - Verse position to reset to
* @returns The current verse after reset, or undefined if not found or out of bounds
*/
resetPosition(verse: VersePosition): Verse | undefined;
/**
* Check if a verse position is out of bounds
*/
isOutOfBounds(verse: VersePosition): boolean;
/**
* Resets the iteration counter to a specific value.
*
* This method allows you to manually control the iteration count, which is useful
* for scenarios where you want to start from a specific iteration state or
* reset the counter after modifying bounds.
*
* @param iterations - New iteration count value
*/
resetIterations(iterations: number): void;
/**
* Get the current verse
*
* @returns The current verse
*/
currentVerse(): Verse;
/**
* Get the current navigation settings
*
* @returns The current navigation settings
*/
getSettings(): NavigationSettings;
/**
* Moves to the next verse based on direction and iteration bounds.
*
* This is the core navigation method that handles iteration limits and bounded navigation.
* It automatically manages cycling through bounded ranges and respects iteration limits.
*
* # Iteration Behavior
*
* The method implements the following iteration logic:
* 1. Check if current position equals the `endBound`
* 2. If at end position and iterations remain: increment count and reset to `startBound`
* 3. If at end position and no iterations remain: return `undefined` (stop navigation)
* 4. Otherwise: move to next verse in the specified direction
* 5. In excluding mode: skip over excluded verses
*
* @returns The next verse, or undefined if reached end of bounds with no remaining iterations
*/
nextVerse(): Verse | undefined;
/**
* Moves to the previous verse based on direction and iteration bounds.
*
* This is the inverse of `nextVerse()`. It handles iteration limits and bounded
* navigation when moving backward. When at the start bound with remaining
* iterations, it resets to the end bound; otherwise returns undefined.
*
* @returns The previous verse, or undefined if at start of bounds with no remaining iterations
*/
previousVerse(): Verse | undefined;
/**
* Attempts to retreat to the previous verse within the current sura.
*
* This method tries to move backward by one verse while ensuring the navigator
* stays within the same sura. If the backward movement would cross into a
* different sura, the operation is rolled back and returns false.
*
* @returns True if successfully moved to previous verse in the same sura, false otherwise
*/
private tryRetreatWithinCurrentSura;
/**
* Move to the previous verse in downward direction
*
* @returns True if successfully moved, false otherwise
*/
private prevVerseDownward;
/**
* Move to the next sura (in upward navigation, "previous" verse means higher sura number)
*
* When at sura 114, wraps to sura 1. Goes to the last verse of the target sura.
*
* @param currentSura - Current sura number
* @returns The last verse of the next sura, or undefined if not found
*/
private moveNextSura;
/**
* Move to the previous verse in upward direction
*
* @returns True if successfully moved, false otherwise
*/
private prevVerseUpward;
/**
* Attempts to advance to the next verse within the current sura.
*
* This method tries to move forward by one verse while ensuring the navigator
* stays within the same sura. If the forward movement would cross into a
* different sura, the operation is rolled back and returns `false`.
*
* @returns True if successfully moved to next verse in the same sura, false otherwise
*/
private tryAdvanceWithinCurrentSura;
/**
* Move to the next verse in downward direction
*
* @returns True if successfully moved, false otherwise
*/
private nextVerseDownward;
/**
* Move to the previous sura
*
* @param currentSura - Current sura number
* @returns The first verse of the previous sura, or undefined if not found
*/
private movePreSura;
/**
* Move to the next verse in upward direction
*
* @returns True if successfully moved, false otherwise
*/
private nextVerseUpward;
/**
* Find a verse in the mushaf and return its location (Verse, page, index_of_verse)
*
* @param verse - Verse position to find
* @returns The verse and its location, or undefined if not found
*/
findVerse(verse: VersePosition): [Verse, number, number] | 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 (rounded to 1 decimal place)
*/
calculateVerseLines(verse: Verse): number;
/**
* Index navigation - move by a specific number of verses
*/
private moveByIndex;
/**
* Move forward by a specific number of verses
*
* @param index - Number of verses to move forward
* @returns The verse at the new position, or undefined if out of bounds
*/
forwardIndex(index: number): Verse | undefined;
/**
* Move backward by a specific number of verses
*
* @param index - Number of verses to move backward
* @returns The verse at the new position, or undefined if out of bounds
*/
backwardIndex(index: number): Verse | undefined;
}