Skip to content

Commit 01ce7d5

Browse files
committed
feat: add updated SurahMeta
1 parent 21303f7 commit 01ce7d5

17 files changed

+171
-44
lines changed

examples/data-check/checkQuranApi.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*/
66

77

8-
import { findPagebyAyahId, findAyahIdBySurah, findJuz, findRubAlHizb, getAyahMeta, getRubAlHizbMetaByAyahId, HizbQuarterList, Juz, JuzList, ManzilList, meta, PageList, RukuList, SajdaList, Surah, SurahList, SurahInfo, getJuzMeta, getRubAlHizbMeta, getRukuMeta, getPageMeta, getManzilMeta, getSurahInfo } from "../../src"
8+
import { findPagebyAyahId, findAyahIdBySurah, findJuz, findRubAlHizb, getAyahMeta, getRubAlHizbMetaByAyahId, HizbQuarterList, Juz, JuzList, ManzilList, meta, PageList, RukuList, SajdaList, Surah, SurahList, SurahInfo, getJuzMeta, getRubAlHizbMeta, getRukuMeta, getPageMeta, getManzilMeta, getSurahInfo, getSurahMeta } from "../../src"
99
import { AyahNo, AyahId, Manzil, Page, Ruku, RubAlHizbId } from "../../src/types"
1010

1111
import quranApi from "./data/quran-api.json"
@@ -29,19 +29,18 @@ export function checkQuranApi() {
2929
}
3030

3131
for (let surahNo: Surah = 1; surahNo <= meta.numSurahs; surahNo++) {
32-
const [
33-
startAyahId,
32+
const {
33+
firstAyahId,
3434
ayahCount,
3535
surahOrder,
3636
rukuCount,
3737
name,
38-
isMeccan,
39-
page
40-
]: SurahInfo = getSurahInfo(surahNo as Surah)
38+
isMeccan
39+
} = getSurahMeta(surahNo as Surah)
4140
const { chapter, name: oName, englishname, arabicname, revelation, verses } = quranApi.chapters[surahNo - 1]
4241

4342
if (surahNo !== chapter) console.warn("error QuranApi surah: ", surahNo, chapter)
44-
if (startAyahId !== verses[0].line) console.warn("error QuranApi surah: ", startAyahId, verses[0].line)
43+
if (firstAyahId !== verses[0].line) console.warn("error QuranApi surah: ", firstAyahId, verses[0].line)
4544
if (ayahCount !== verses.length) console.warn("error QuranApi surah: ", ayahCount, verses.length)
4645
}
4746

src/ayahStringSplitter.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@ import { checkValidAyahId, checkValidSurahAyah } from "./validation"
77
* @param str - The string to parse, expected format: "surah:ayah" or "surah:ayahStart-ayahEnd"
88
* @param isStrict - If true, enforces strict format checking. Defaults to true. If false, allows for additional characters in the string
99
* @returns A tuple containing surah number and either a single ayah number or a range [start, end]
10-
* @throws {Error} If the string format is invalid
11-
* @throws {Error} If surah number is invalid
12-
* @throws {Error} If ayah number(s) are invalid
13-
* @throws {Error} If ayah range is invalid (start > end)
10+
* @throws {@link Error} If the string format is invalid
11+
* @throws {@link Error} If surah number is invalid
12+
* @throws {@link Error} If ayah number(s) are invalid
13+
* @throws {@link sError} If ayah range is invalid (start > end)
1414
* @example
15+
* ```ts
1516
* ayahStringSplitter("2:255") // returns [2, 255]
1617
* ayahStringSplitter("1:1-7") // returns [1, [1, 7]]
18+
* ```
1719
*/
1820
export function ayahStringSplitter(str: string, isStrict = true): SurahAyahSegment {
1921
const result = isStrict ? string2NumberSplitterStrict(str) : string2NumberSplitter(str)
@@ -82,7 +84,7 @@ export function string2NumberSplitter(str: string): { ayah?: number, ayahTo?: nu
8284
* - surahOrAyah: The surah number
8385
* - ayah: The first or only ayah number
8486
* - ayahTo: The ending ayah number (if range specified)
85-
* @throws {Error} When the input string format is invalid or contains non-numeric values
87+
* @throws {@link Error} When the input string format is invalid or contains non-numeric values
8688
*
8789
* @example
8890
* string2NumberSplitterStrict("2:255") // returns { surahOrAyah: 2, ayah: 255, ayahTo: NaN }

src/findManzilByAyahId.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { checkValidAyahId } from "./validation"
99
*
1010
* @param ayahId - The ID of the Ayah to find the Manzil for
1111
* @returns The Manzil number (1-7) containing the specified Ayah
12-
* @throws {Error} If the provided Ayah ID is invalid
12+
* @throws {@link Error} If the provided Ayah ID is invalid
1313
*
1414
* @example
1515
* ```typescript

src/findRukuByAyahId.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ import { checkValidAyahId } from "./validation"
88
*
99
* @param ayahId - The unique identifier of an Ayah in format: surah:ayah (e.g., "2:255")
1010
* @returns The Ruku number corresponding to the given Ayah ID
11-
* @throws {Error} If the provided Ayah ID is invalid
11+
* @throws {@link Error} If the provided Ayah ID is invalid
1212
*
1313
* @example
14-
* ```typescript
14+
* ```ts
1515
* const ruku = findRukuByAyahId("2:255");
1616
* // Returns the Ruku number containing Ayah 255 of Surah 2
1717
* ```

src/getPageMeta.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ import { checkValidPage } from "./validation"
77
* Retrieves metadata for a specific page of the Quran.
88
*
99
* @param pageNum - The page number to retrieve metadata for (1-604)
10-
* @returns An object containing the page number, first ayah, and last ayah on the page
11-
* @throws RangeError If the page number is not between 1 and 604
10+
* @returns {@link PageMeta} An object containing the page number, first ayah, and last ayah on the page
11+
* @throws {@link RangeError} If the page number is not between 1 and 604
1212
*/
1313
export function getPageMeta(pageNum: Page): PageMeta {
1414
checkValidPage(pageNum)

src/getRukuMeta.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { checkValidRuku } from "./validation"
66
/**
77
* Retrieves metadata for a specific Ruku (section) of the Quran.
88
* @param rukuNum - The number of the Ruku to retrieve metadata for
9-
* @returns {RukuMeta} An object containing metadata about the Ruku including:
9+
* @returns {@link RukuMeta} An object containing metadata about the Ruku including:
1010
* - rukuNum: The Ruku number
1111
* - firstAyahId: The global Ayah ID of the first verse in this Ruku
1212
* - lastAyahId: The global Ayah ID of the last verse in this Ruku

src/getSurahMeta.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { getSurahInfo } from "./getSurahInfo"
2+
import { Surah, SurahMeta } from "./types"
3+
4+
/**
5+
* Gets the metadata for the specified Surah.
6+
*
7+
* @param surah - The Surah to get the metadata for.
8+
* @returns The metadata for the specified Surah.
9+
*/
10+
export function getSurahMeta(surahNum: Surah): SurahMeta {
11+
const [
12+
firstAyahId,
13+
ayahCount,
14+
surahOrder,
15+
rukuCount,
16+
name,
17+
isMeccan
18+
] = getSurahInfo(surahNum)
19+
20+
const lastAyahId = firstAyahId + ayahCount - 1
21+
return {
22+
surahNum,
23+
ayahCount,
24+
surahOrder,
25+
rukuCount,
26+
name,
27+
isMeccan,
28+
firstAyahId,
29+
lastAyahId,
30+
first: [surahNum, 1],
31+
last: [surahNum, ayahCount]
32+
}
33+
}

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export { getRubAlHizb } from "./getRubAlHizb"
3434
export { getRubAlHizbMeta } from "./getRubAlHizbMeta"
3535
export { getRubAlHizbMetaByAyahId } from "./getRubAlHizbMetaByAyahId"
3636
export { getRubAlHizbByAyahId } from "./getRubAlHizbByAyahId"
37-
export { getSurahInfo as getSurahInfo } from "./getSurahInfo"
37+
export { getSurahMeta } from "./getSurahMeta"
3838
export { isAyahJuzFirst } from "./isAyahJuzFirst"
3939
export { isAyahPageFirst } from "./isAyahPageFirst"
4040
export { isSurahAyahJuzFirst } from "./isSurahAyahJuzFirst"

src/surahStringParser.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { Surah } from "./types"
55
* Parses a string representation of a Surah number and converts it to a valid Surah type
66
* @param str - The string containing the Surah number to parse
77
* @returns The parsed Surah number as a Surah type
8-
* @throws {Error} If the string cannot be parsed as a number or if the number is not a valid Surah number
8+
* @throws {@link Error} If the string cannot be parsed as a number or if the number is not a valid Surah number
99
*/
1010
export function surahStringParser(str: string, isStrict = false): Surah {
1111
const surahX = isStrict ? Number(str.trim()) : Number.parseInt(str.trim(), 10)

src/typeGuards.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,11 @@ export function isValidRuku(x: unknown): x is Ruku {
112112
* @returns True if the value is an integer between 1 and the total number of Manzils
113113
*
114114
* @example
115+
* ```ts
115116
* if (isValidManzil(3)) {
116117
* // value is a valid Manzil number
117118
* }
119+
* ```
118120
*/
119121
export function isValidManzil(x: unknown): x is Manzil {
120122
return Number.isInteger(x) && 1 <= (x as number) && x as number <= meta.numManzils

src/types.ts

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,17 @@ export type Juz = NumericRange<0, typeof meta.numJuzs>
8383
*/
8484
export type JuzPart = NumericRange<1, typeof meta.numRubsInJuz>
8585

86+
// [start, ayas, order, rukus, name, isMeccan, page ]
87+
export type SurahInfo = [
88+
startAyahId: AyahId,
89+
ayahCount: AyahNo,
90+
surahOrder: Surah,
91+
rukuCount: Ruku,
92+
name: string,
93+
isMeccan: boolean
94+
]
95+
export type SurahName = [name: string, translitName: string]
96+
8697
export type RangeMeta = {
8798
firstAyahId: AyahId
8899
lastAyahId: AyahId
@@ -106,6 +117,15 @@ export type SurahAyah = [Surah, AyahNo]
106117
export type AyahRange = [AyahId, AyahId]
107118
export type SurahAyahSegment = [Surah, AyahNo | [AyahNo, AyahNo]]
108119

120+
export type SurahMeta = {
121+
name: string
122+
surahNum: Surah
123+
ayahCount: AyahNo
124+
surahOrder: Surah
125+
rukuCount: Ruku
126+
isMeccan: boolean
127+
} & RangeMeta
128+
109129
export type PageMeta = {
110130
pageNum: Page
111131
} & RangeMeta
@@ -134,16 +154,6 @@ export type SurahJuzMeta = {
134154
}
135155
export type SajdaType = "recommended" | "obligatory"
136156
export type Sajda = [AyahId, SajdaType]
137-
// [start, ayas, order, rukus, name, isMeccan, page ]
138-
export type SurahInfo = [
139-
startAyahId: AyahId,
140-
ayahCount: AyahNo,
141-
surahOrder: Surah,
142-
rukuCount: Ruku,
143-
name: string,
144-
isMeccan: boolean
145-
]
146-
export type SurahName = [name: string, translitName: string]
147157

148158
export type RangeMode = "juz" | "surah" | "ayah" | "page" | "ruku" | "all"
149159

src/validation.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ export function checkValidAyahId(ayahId: unknown | number | AyahId): asserts aya
7171
/**
7272
* Checks if a value is a valid Page number.
7373
* @param x - The value to check
74-
* @throws {TypeError} When the value is not an integer
75-
* @throws {RangeError} When the value is not within valid page range (1 to numPages)
74+
* @throws {@link TypeError} When the value is not an integer
75+
* @throws {@link RangeError} When the value is not within valid page range (1 to numPages)
7676
* @remarks This is a type assertion function that ensures a value is a valid Page number
7777
*/
7878
export function checkValidPage(x: unknown | number | Page): asserts x is Page {
@@ -90,8 +90,8 @@ export function checkValidPage(x: unknown | number | Page): asserts x is Page {
9090
* Throws RangeError if value is outside valid Juz range.
9191
*
9292
* @param x - Value to check
93-
* @throws {TypeError} If value is not an integer
94-
* @throws {RangeError} If value is not between 1 and the total number of Juz
93+
* @throws {@link TypeError} If value is not an integer
94+
* @throws {@link RangeError} If value is not between 1 and the total number of Juz
9595
*/
9696
export function checkValidJuz(x: unknown | number | Juz): asserts x is Juz {
9797
if (typeof x !== "number" || !Number.isInteger(x)) {
@@ -104,11 +104,11 @@ export function checkValidJuz(x: unknown | number | Juz): asserts x is Juz {
104104

105105
/**
106106
* Type guard that checks if a value is a valid Ruku number.
107-
* @param x The value to check
108-
* @throws {TypeError} If the value is not an integer number
109-
* @throws {RangeError} If the number is not within valid Ruku range
107+
* @param x - The value to check
108+
* @throws {@link TypeError} If the value is not an integer number
109+
* @throws {@link RangeError} If the number is not within valid Ruku range
110110
* @example
111-
* ```typescript
111+
* ```ts
112112
* checkValidRuku(5); // OK
113113
* checkValidRuku("5"); // Throws TypeError
114114
* checkValidRuku(999); // Throws RangeError
@@ -126,8 +126,8 @@ export function checkValidRuku(x: unknown | number | Ruku): asserts x is Ruku {
126126
/**
127127
* Type guard that checks if a value is a valid Manzil number.
128128
* @param x - The value to check
129-
* @throws {TypeError} If the value is not an integer
130-
* @throws {RangeError} If the value is not within valid Manzil range (1 to max manzils)
129+
* @throws {@link TypeError} If the value is not an integer
130+
* @throws {@link RangeError} If the value is not within valid Manzil range (1 to max manzils)
131131
* @remarks This is an assertion function that ensures the input is a valid Manzil type
132132
*/
133133
export function checkValidManzil(x: unknown | number | Manzil): asserts x is Manzil {

tests/getManzilMeta.spec.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { describe, it, expect } from "vitest"
2+
import { getManzilMeta } from "../src/getManzilMeta"
3+
4+
describe("getManzilMeta", () => {
5+
it("should return correct metadata for Manzil 1", () => {
6+
const result = getManzilMeta(1)
7+
expect(result).toEqual({
8+
manzilNum: 1,
9+
firstAyahId: 1,
10+
lastAyahId: 669,
11+
first: [1, 1],
12+
last: [4, 176]
13+
})
14+
})
15+
16+
it("should return correct metadata for Manzil 4", () => {
17+
const result = getManzilMeta(4)
18+
expect(result).toEqual({
19+
manzilNum: 4,
20+
firstAyahId: 2030,
21+
lastAyahId: 2932,
22+
first: [17, 1],
23+
last: [25, 77]
24+
})
25+
})
26+
27+
it("should return correct metadata for Manzil 8", () => {
28+
const result = getManzilMeta(7)
29+
expect(result).toEqual({
30+
manzilNum: 7,
31+
firstAyahId: 4631,
32+
lastAyahId: 6236,
33+
first: [50, 1],
34+
last: [114, 6]
35+
})
36+
})
37+
38+
it("should throw error for invalid Manzil number 0", () => {
39+
expect(() => getManzilMeta(0)).toThrow()
40+
})
41+
42+
it("should throw error for invalid Manzil number 8", () => {
43+
expect(() => getManzilMeta(8)).toThrow()
44+
})
45+
})

tests/getSurahInfo.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { findPage, getSurahInfo, meta, Surah, SurahList } from "../src"
1+
import { SurahList } from "../src"
2+
import { getSurahInfo } from "../src/getSurahInfo"
23

34
describe("getSurahInfo", () => {
45
it("should return correct metadata for first surah", () => {
@@ -11,7 +12,6 @@ describe("getSurahInfo", () => {
1112
expect(result).toEqual(SurahList[114])
1213
})
1314

14-
1515
it("should return correct metadata for a middle surah", () => {
1616
const result = getSurahInfo(57)
1717
expect(result).toEqual(SurahList[57])

tests/getSurahMeta.spec.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { getSurahMeta } from "../src/getSurahMeta"
2+
3+
describe("getSurahMeta", () => {
4+
it("returns correct metadata for Surah Al-Fatihah (1)", () => {
5+
const meta = getSurahMeta(1)
6+
expect(meta).toEqual({
7+
surahNum: 1,
8+
ayahCount: 7,
9+
surahOrder: 5,
10+
rukuCount: 1,
11+
name: "الفاتحة",
12+
isMeccan: true,
13+
firstAyahId: 1,
14+
lastAyahId: 7,
15+
first: [1, 1],
16+
last: [1, 7]
17+
})
18+
})
19+
20+
it("returns correct metadata for Surah Al-Baqarah (2)", () => {
21+
const meta = getSurahMeta(2)
22+
expect(meta).toEqual({
23+
surahNum: 2,
24+
ayahCount: 286,
25+
surahOrder: 87,
26+
rukuCount: 40,
27+
name: "البقرة",
28+
isMeccan: false,
29+
firstAyahId: 8,
30+
lastAyahId: 293,
31+
first: [2, 1],
32+
last: [2, 286]
33+
})
34+
})
35+
})

tests/meta.spec.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import { meta, getList, getSurahInfo, HizbQuarterList, JuzList, ManzilList, PageList, RukuList, SajdaList, SurahList } from "../src"
1+
import { meta, getList, HizbQuarterList, JuzList, ManzilList, PageList, RukuList, SajdaList, SurahList } from "../src"
22
import { maxAyahsInSurah } from "../src/const"
3+
import { getSurahInfo } from "../src/getSurahInfo"
34

45
describe("Meta constants", () => {
56
it("should return correct numSurahs", () => {

tests/quran-data.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ import {
55
findSurahAyahByAyahId,
66
findSurahByAyahId,
77
getPageMeta,
8-
getSurahInfo,
98
isAyahJuzFirst,
109
JuzList,
1110
meta
1211
} from "../src"
12+
import { getSurahInfo } from "../src/getSurahInfo"
1313
import { AyahId, AyahNo, Surah } from "../src/types"
1414

1515
console.log("STARING")

0 commit comments

Comments
 (0)