codexparser 0.1.22 → 0.1.24

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 +159 -9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codexparser",
3
- "version": "0.1.22",
3
+ "version": "0.1.24",
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": {
@@ -366,18 +366,41 @@ class CodexParser {
366
366
  }
367
367
 
368
368
  versification() {
369
- for (let i = 0; i < this.passages.length; i++) {
370
- const passage = this.passages[i]
369
+ this.passages.forEach((passage) => {
371
370
  const hasVersification = this.versificationDifferences[passage.book]
372
- for (let j = 0; j < passage.passages.length; j++) {
373
- const subPassage = passage.passages[j]
371
+
372
+ passage.passages.forEach((subPassage) => {
373
+ // Apply general versification differences
374
374
  if (hasVersification) {
375
- if (this.versificationDifferences[passage.book][subPassage.chapter + ":" + subPassage.verse])
376
- subPassage.versification =
377
- this.versificationDifferences[passage.book][subPassage.chapter + ":" + subPassage.verse]
375
+ const key = `${subPassage.chapter}:${subPassage.verse}`
376
+ if (this.versificationDifferences[passage.book][key]) {
377
+ subPassage.versification = this.versificationDifferences[passage.book][key]
378
+ }
378
379
  }
379
- }
380
- }
380
+
381
+ // Handle specific version adjustments for "lxx" or "mt"
382
+ if (passage.version) {
383
+ const versionAbbreviation = passage.version.abbreviation
384
+ const versionType =
385
+ versionAbbreviation === "lxx" ? "lxx" : versionAbbreviation === "mt" ? "mt" : null
386
+
387
+ if (versionType) {
388
+ const versionReference = `${subPassage.chapter}:${subPassage.verse}`
389
+
390
+ // Look for matching versification based on the version type (lxx or mt)
391
+ for (const versification in this.versificationDifferences[passage.book]) {
392
+ if (
393
+ this.versificationDifferences[passage.book][versification][versionType] ===
394
+ versionReference
395
+ ) {
396
+ subPassage.versification = this.versificationDifferences[passage.book][versification]
397
+ break // Break once a match is found
398
+ }
399
+ }
400
+ }
401
+ }
402
+ })
403
+ })
381
404
  }
382
405
 
383
406
  /**
@@ -481,6 +504,133 @@ class CodexParser {
481
504
  }
482
505
  }
483
506
 
507
+ /**
508
+ * Combine multiple passages into one. The method checks for duplicates, merges overlapping or adjacent ranges,
509
+ * and builds the original and scripture properties.
510
+ * **This method will always combine based on English versification. LXX and MT versifications will be reflected in the combined passage.passages.versification.**
511
+ * This method will fail if the passages are not to the same book and chapter.
512
+ * @param {array} passages - An array of passage objects to combine.
513
+ * @return {object} The combined passage object.
514
+ */
515
+ combine(passages) {
516
+ const noDuplicates = [...new Set(passages.map((p) => p.book + " " + p.chapter))]
517
+ if (noDuplicates.length > 1) {
518
+ throw new Error("Passages are not from the same book and chapter.")
519
+ }
520
+ const newPassages = []
521
+ passages.forEach((passageSet) => {
522
+ passageSet.passages.forEach((passage) => {
523
+ if (passage.versification) {
524
+ newPassages.push(passage.book + " " + passage.versification.eng)
525
+ } else {
526
+ newPassages.push(passage.book + " " + passage.chapter + ":" + passage.verse)
527
+ }
528
+ })
529
+ })
530
+ const noDuplicates2 = [...new Set(newPassages)]
531
+ const parsed = this.parse(noDuplicates2.join(" // ")).getPassages()
532
+ return this.join(parsed)
533
+ }
534
+
535
+ /**
536
+ * Combine multiple passages into one. The method checks for duplicates, merges overlapping or adjacent ranges,
537
+ * and builds the original and scripture properties.
538
+ *
539
+ * @param {array} passages - An array of passage objects to combine.
540
+ * @return {object} The combined passage object.
541
+ */
542
+ join(passages) {
543
+ const newObject = { ...passages[0] }
544
+
545
+ for (let i = 1; i < passages.length; i++) {
546
+ // Combine passages, but check for duplicates
547
+ passages[i].passages.forEach((passage) => {
548
+ // Add passage only if it's not already in newObject.passages
549
+ const isDuplicate = newObject.passages.some(
550
+ (p) => p.book === passage.book && p.chapter === passage.chapter && p.verse === passage.verse
551
+ )
552
+ if (!isDuplicate) {
553
+ newObject.passages = newObject.passages.concat(passage)
554
+ }
555
+ })
556
+ const verses = passages[i].verses
557
+ for (let j = 0; j < verses.length; j++) {
558
+ const verse = verses[j]
559
+ newObject.verses = newObject.verses.concat(verse)
560
+ }
561
+ }
562
+
563
+ // Remove lone numbers that are part of a range
564
+ newObject.verses = newObject.verses.filter((v, i, arr) => {
565
+ if (!v.includes("-")) {
566
+ const num = parseInt(v, 10)
567
+ return !arr.some((item) => {
568
+ if (item.includes("-")) {
569
+ const [start, end] = item.split("-").map(Number)
570
+ return num >= start && num <= end
571
+ }
572
+ return false
573
+ })
574
+ }
575
+ return true // Keep ranges
576
+ })
577
+
578
+ // Convert to a Set to remove duplicates
579
+ newObject.verses = [...new Set(newObject.verses)]
580
+
581
+ // Helper function to merge overlapping or adjacent ranges
582
+ const mergeRanges = (verses) => {
583
+ const rangeObjects = verses.map((v) => {
584
+ if (v.includes("-")) {
585
+ const [start, end] = v.split("-").map(Number)
586
+ return { start, end }
587
+ } else {
588
+ const num = Number(v)
589
+ return { start: num, end: num }
590
+ }
591
+ })
592
+
593
+ // Sort the ranges by starting number
594
+ rangeObjects.sort((a, b) => a.start - b.start)
595
+
596
+ const merged = []
597
+ let currentRange = rangeObjects[0]
598
+
599
+ for (let i = 1; i < rangeObjects.length; i++) {
600
+ const nextRange = rangeObjects[i]
601
+
602
+ if (currentRange.end >= nextRange.start - 1) {
603
+ // Overlapping or adjacent, merge the ranges
604
+ currentRange.end = Math.max(currentRange.end, nextRange.end)
605
+ } else {
606
+ // No overlap, push the current range and start a new one
607
+ merged.push(currentRange)
608
+ currentRange = nextRange
609
+ }
610
+ }
611
+
612
+ // Push the last range
613
+ merged.push(currentRange)
614
+
615
+ // Convert merged ranges back to strings
616
+ return merged.map(({ start, end }) => (start === end ? `${start}` : `${start}-${end}`))
617
+ }
618
+
619
+ // Merge and sort the ranges
620
+ newObject.verses = mergeRanges(newObject.verses)
621
+
622
+ // Build the original and scripture properties
623
+ newObject.original = newObject.book + " " + newObject.chapter + ":" + newObject.verses.join(",")
624
+ newObject.scripture = {
625
+ passage: newObject.book + " " + newObject.chapter + ":" + newObject.verses.join(","),
626
+ cv: newObject.chapter + ":" + newObject.verses.join(","),
627
+ hash: newObject.book + "_" + newObject.chapter + "." + newObject.verses.join("."),
628
+ }
629
+ newObject.scripture.hash = newObject.scripture.hash.toLowerCase()
630
+
631
+ return newObject
632
+ }
633
+
484
634
  _isValid(passage, reference) {
485
635
  const singleChapterBook = this.singleChapterBook.find((bible) => bible[passage.book])
486
636
  if (!passage.verses) {