UNPKG

@sahabaplus/mushaf-engine

Version:

TypeScript implementation of a Quran Mushaf navigation engine

237 lines (236 loc) 9.14 kB
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; }