codexparser 0.1.52 → 0.1.53

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/CodexParser.js +81 -140
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codexparser",
3
- "version": "0.1.52",
3
+ "version": "0.1.53",
4
4
  "description": "This is a Javascript Bible parser and text scanner. It will search through texts and collate all scripture references into an array and parse them into objects, and it will parse passages into objects by book, chapter, verse, and testament. ",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -186,148 +186,88 @@ class CodexParser {
186
186
  * @returns {object} An object with the parsed passage.
187
187
  */
188
188
  parse(reference) {
189
- this.scan(reference) // Call scan to populate this.found
189
+ this.scan(reference) // Populate this.found
190
190
 
191
191
  this.passages = this.found.map((passage) => {
192
192
  const book = this.bookify(passage.book)
193
- const testament = this.bible.old.find((bible) => bible === book) ? "old" : "new"
194
-
195
- // Initialize the parsed passage object
193
+ const testament = this.bible.old.includes(book) ? "old" : "new"
196
194
  const parsedPassage = {
197
195
  original: passage.book + " " + passage.reference,
198
196
  book: book,
199
197
  chapter: null,
200
- verses: [], // Verses stored as an array
201
- type: passage.type, // Set type based on reference
198
+ verses: [],
199
+ type: passage.type,
202
200
  testament: testament,
203
201
  index: passage.index,
204
202
  version: this._handleVersion(passage.version, testament),
205
203
  }
206
204
 
207
- // Split reference by commas to handle multiple ranges or verses (e.g., "Isaiah 8:22-9:1,5")
208
- let parts = passage.reference.split(",")
209
-
210
- // Check for single-chapter books
211
- const singleChapterBook = this.singleChapterBook.find((bible) => bible[book])
205
+ // Split reference into parts (e.g., "40:3-5,8-9" -> ["40:3-5", "8-9"])
206
+ const parts = passage.reference.split(",")
212
207
 
213
208
  parts.forEach((part, partIndex) => {
214
- part = part.trim() // Clean up spaces
215
- const separator = part.includes(":") ? ":" : "."
216
-
217
- if (part.includes("-")) {
218
- // Handle ranges (e.g., "8:22-9:1")
219
- let [start, end] = part.split("-")
220
-
221
- // Handle the starting part
222
- let [startChapter, startVerse] = start.includes(separator)
223
- ? start.split(separator)
224
- : [parsedPassage.chapter, start] // Default to same chapter if no chapter is provided
225
-
226
- parsedPassage.chapter = Number(startChapter) // Set the chapter
227
-
228
- // Multi-chapter verse range logic
229
- if (start.includes(separator) && end.includes(separator)) {
230
- let [endChapter, endVerse] = end.split(separator)
231
-
232
- parsedPassage.verses = this.chapterVerses[book][startChapter].slice(
233
- this.chapterVerses[book][startChapter].indexOf(Number(startVerse))
234
- )
235
-
236
- if (Number(endChapter) !== Number(startChapter)) {
237
- const endVerses = this.chapterVerses[book][endChapter].slice(
238
- 0,
239
- this.chapterVerses[book][endChapter].indexOf(Number(endVerse)) + 1
240
- )
241
- // Construct ranges for the `to` object
242
- parsedPassage.to = {
243
- book: book,
244
- chapter: Number(endChapter),
245
- verses: [endVerse],
246
- }
209
+ part = part.trim()
247
210
 
248
- parsedPassage.type = "multi_chapter_verse_range"
249
- } else {
250
- parsedPassage.verses.push(`${startVerse}-${endVerse}`)
251
- }
211
+ if (part.includes(":")) {
212
+ // Explicit chapter:verse (e.g., "40:3-5")
213
+ const [chapterPart, versePart] = part.split(":")
214
+ if (partIndex === 0) {
215
+ parsedPassage.chapter = Number(chapterPart) // Set chapter only on first part
216
+ }
217
+
218
+ if (versePart.includes("-")) {
219
+ // Verse range (e.g., "3-5")
220
+ parsedPassage.verses.push(versePart)
252
221
  } else {
253
- if (separator !== ":") {
254
- // then this is a chapter_range
255
- let [startChapter, endChapter] = part.split("-")
256
- parsedPassage.chapter = Number(startChapter)
257
- parsedPassage.verses = [
258
- `${this.chapterVerses[book][parsedPassage.chapter][0]}-${
259
- this.chapterVerses[book][parsedPassage.chapter][
260
- this.chapterVerses[book][parsedPassage.chapter].length - 1
261
- ]
262
- }`,
263
- ]
264
- parsedPassage.to = {
265
- book: book,
266
- chapter: Number(endChapter),
267
- verses: [
268
- `${this.chapterVerses[book][endChapter][0]}-${
269
- this.chapterVerses[book][endChapter][
270
- this.chapterVerses[book][endChapter].length - 1
271
- ]
272
- }`,
273
- ],
274
- }
275
- } else {
276
- // Handles when verses are present.
277
- parsedPassage.verses = [part.split(separator)[1]]
278
- }
222
+ parsedPassage.verses.push(Number(versePart))
223
+ }
224
+ } else if (part.includes("-")) {
225
+ // Verse range without chapter (e.g., "8-9")
226
+ if (parsedPassage.chapter === null) {
227
+ // Assume chapter 1 for single-chapter books if no chapter yet
228
+ const singleChapterBook = this.singleChapterBook.find((b) => b[book])
229
+ parsedPassage.chapter = singleChapterBook ? 1 : Number(part.split("-")[0])
230
+ parsedPassage.verses.push(part)
231
+ } else {
232
+ parsedPassage.verses.push(part) // Add as verse range in current chapter
279
233
  }
280
234
  } else {
281
- // Handle individual chapter:verse references (e.g., "9:5" in "8:22-9:1,5")
282
-
283
- let [chapterPart, versePart] = part.includes(separator)
284
- ? part.split(separator)
285
- : [parsedPassage.chapter, part]
286
-
287
- if (separator.trim() !== ":" && !parsedPassage.chapter) {
288
- if (singleChapterBook) {
289
- parsedPassage.chapter = 1
290
- parsedPassage.verses.push(versePart) // Add single verse to array
291
- } else {
292
- parsedPassage.chapter = Number(part)
293
- parsedPassage.verses = [
294
- `${this.chapterVerses[book][parsedPassage.chapter][0]}-${
295
- this.chapterVerses[book][parsedPassage.chapter][
296
- this.chapterVerses[book][parsedPassage.chapter].length - 1
297
- ]
298
- }`,
299
- ]
300
- }
235
+ // Single verse without chapter (e.g., "8")
236
+ if (parsedPassage.chapter === null) {
237
+ const singleChapterBook = this.singleChapterBook.find((b) => b[book])
238
+ parsedPassage.chapter = singleChapterBook ? 1 : Number(part)
301
239
  } else {
302
- if (chapterPart) {
303
- if (partIndex === parts.length - 1 && parsedPassage.to) {
304
- // Add additional verses to the last chapter in multi-chapter range
305
- if (!parsedPassage.to.verses) parsedPassage.to.verses = []
306
- parsedPassage.to.verses.push(Number(versePart))
307
- } else {
308
- parsedPassage.chapter = Number(chapterPart)
309
- parsedPassage.verses.push(Number(versePart))
310
- }
311
- }
240
+ parsedPassage.verses.push(Number(part))
312
241
  }
313
242
  }
314
-
315
- parsedPassage.passages = this.populate(parsedPassage)
316
- parsedPassage.scripture = this.scripturize(parsedPassage)
317
243
  })
318
244
 
319
- // Handle range merging in `to` object
320
- if (parsedPassage.to && Array.isArray(parsedPassage.to.verses)) {
321
- parsedPassage.to.verses = this.mergeRanges(parsedPassage.to.verses)
322
- }
323
-
245
+ // Populate passages and scripture after processing all parts
246
+ parsedPassage.passages = this.populate(parsedPassage)
247
+ parsedPassage.scripture = this.scripturize(parsedPassage)
324
248
  parsedPassage.valid = this._isValid(parsedPassage, passage.reference)
325
249
 
250
+ // Handle multi-chapter range if applicable
251
+ if (
252
+ parsedPassage.type === "multi_chapter_verse_range" &&
253
+ parts.some((p) => p.includes(":") && p.split(":")[0] !== String(parsedPassage.chapter))
254
+ ) {
255
+ const lastPart = parts[parts.length - 1]
256
+ const [endChapter, endVerse] = lastPart.split(":")
257
+ parsedPassage.to = {
258
+ book: book,
259
+ chapter: Number(endChapter),
260
+ verses: endVerse.includes("-") ? [endVerse] : [Number(endVerse)],
261
+ }
262
+ } else {
263
+ delete parsedPassage.to // Ensure no erroneous 'to' property
264
+ }
265
+
326
266
  return parsedPassage
327
267
  })
328
268
 
329
269
  this.versification()
330
- return this // Return this instance
270
+ return this
331
271
  }
332
272
  /**
333
273
  * Generates an array of numbers representing a range from start to end, inclusive.
@@ -419,28 +359,39 @@ class CodexParser {
419
359
  * @param {Object} parsedPassage - The parsed passage object containing book, chapter, and verses information.
420
360
  * @return {Array} An array of passage objects with individual verses.
421
361
  */
362
+ /**
363
+ * Populate all verses from a parsed passage, including all verses in ranges or chapters.
364
+ *
365
+ * @param {Object} parsedPassage - The parsed passage object containing book, chapter, and verses information.
366
+ * @return {Array} An array of passage objects with individual verses.
367
+ */
422
368
  populate(parsedPassage) {
423
369
  const passages = []
424
-
425
370
  const { book, chapter, verses, type, to } = parsedPassage
426
371
  const version = parsedPassage.version ? parsedPassage.version.abbreviation : "eng"
427
372
  this._setVersion(book, chapter, version) // Set version data if needed
428
373
 
429
374
  if (type === "single_chapter") {
430
- // Handle entire chapter references
375
+ // Handle entire chapter references (e.g., "Isaiah 40")
431
376
  if (this.chapterVerses[book] && this.chapterVerses[book][chapter]) {
432
377
  this.chapterVerses[book][chapter].forEach((verse) => {
433
378
  passages.push({ book, chapter: Number(chapter), verse: Number(verse) })
434
379
  })
435
380
  }
436
- } else if (type === "comma_separated_verses") {
437
- // Handle explicitly mentioned verses (e.g., 3:1,3,6)
438
-
381
+ } else if (type === "comma_separated_verses" || type === "chapter_verse_range") {
382
+ // Handle comma-separated verses or single-chapter verse ranges (e.g., "Isaiah 40:3-5,8-9" or "Isaiah 40:3-5")
439
383
  verses.forEach((verse) => {
440
- passages.push({ book, chapter: Number(chapter), verse: Number(verse) })
384
+ if (typeof verse === "string" && verse.includes("-")) {
385
+ const [start, end] = verse.split("-").map(Number)
386
+ for (let i = start; i <= end; i++) {
387
+ passages.push({ book, chapter: Number(chapter), verse: i })
388
+ }
389
+ } else {
390
+ passages.push({ book, chapter: Number(chapter), verse: Number(verse) })
391
+ }
441
392
  })
442
393
  } else if (type === "chapter_range") {
443
- // Handle ranges of chapters (e.g., 3-5)
394
+ // Handle ranges of chapters (e.g., "Isaiah 3-5")
444
395
  for (let currentChapter = chapter; currentChapter <= to.chapter; currentChapter++) {
445
396
  if (this.chapterVerses[book] && this.chapterVerses[book][currentChapter]) {
446
397
  this.chapterVerses[book][currentChapter].forEach((verse) => {
@@ -449,18 +400,17 @@ class CodexParser {
449
400
  }
450
401
  }
451
402
  } else if (type === "multi_chapter_verse_range") {
452
- // Handle multi-chapter verse ranges (e.g., 3:1-5:6)
403
+ // Handle multi-chapter verse ranges (e.g., "Isaiah 3:1-5:6")
453
404
  const startChapter = chapter
454
- const startVerse = verses[0]
405
+ const startVerse = verses[0].includes("-") ? Number(verses[0].split("-")[0]) : Number(verses[0])
455
406
  const endChapter = to.chapter
456
- const endVerse = to.verses[to.verses.length - 1]
407
+ const endVerse = to.verses[0].includes("-") ? Number(to.verses[0].split("-")[1]) : Number(to.verses[0])
457
408
 
458
409
  for (let currentChapter = startChapter; currentChapter <= endChapter; currentChapter++) {
459
410
  const chapterVerses = this.chapterVerses[book][currentChapter]
460
411
  if (!chapterVerses) continue
461
412
 
462
- // Determine start and end verses for each chapter
463
- const chapterStartVerse = currentChapter === startChapter ? startVerse : 1
413
+ const chapterStartVerse = currentChapter === startChapter ? startVerse : chapterVerses[0]
464
414
  const chapterEndVerse =
465
415
  currentChapter === endChapter ? endVerse : chapterVerses[chapterVerses.length - 1]
466
416
 
@@ -468,22 +418,13 @@ class CodexParser {
468
418
  passages.push({ book, chapter: currentChapter, verse })
469
419
  }
470
420
  }
471
- } else if (type === "chapter_verse" || type === "chapter_verse_range") {
472
- // Handle single chapter:verse or chapter:verse ranges (e.g., 3:1 or 3:1-5)
473
- if (this.chapterVerses[book] && this.chapterVerses[book][chapter]) {
474
- verses.forEach((verse) => {
475
- if (typeof verse === "string" && verse.includes("-")) {
476
- const [start, end] = verse.split("-").map(Number)
477
- for (let i = start; i <= end; i++) {
478
- passages.push({ book, chapter: Number(chapter), verse: i })
479
- }
480
- } else {
481
- passages.push({ book, chapter: Number(chapter), verse: Number(verse) })
482
- }
483
- })
484
- }
421
+ } else if (type === "chapter_verse") {
422
+ // Handle single chapter:verse references (e.g., "Isaiah 40:3")
423
+ verses.forEach((verse) => {
424
+ passages.push({ book, chapter: Number(chapter), verse: Number(verse) })
425
+ })
485
426
  } else if (type === "single_chapter_book_verse_range") {
486
- // Handle ranges in single-chapter books (e.g., Jude 5-7)
427
+ // Handle ranges in single-chapter books (e.g., "Jude 5-7")
487
428
  const [startVerse, endVerse] = verses[0].split("-").map(Number)
488
429
  for (let i = startVerse; i <= endVerse; i++) {
489
430
  passages.push({ book, chapter: 1, verse: i })