codexparser 0.1.28 → 0.1.30
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.
- package/package.json +1 -1
- package/src/CodexParser.js +107 -74
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codexparser",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.30",
|
|
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": {
|
package/src/CodexParser.js
CHANGED
|
@@ -223,7 +223,7 @@ class CodexParser {
|
|
|
223
223
|
i++
|
|
224
224
|
}
|
|
225
225
|
}
|
|
226
|
-
|
|
226
|
+
dump(this.found)
|
|
227
227
|
return this // Return this instance for method chaining
|
|
228
228
|
}
|
|
229
229
|
|
|
@@ -476,7 +476,20 @@ class CodexParser {
|
|
|
476
476
|
* @return {array} The passages stored in the object.
|
|
477
477
|
*/
|
|
478
478
|
getPassages() {
|
|
479
|
-
|
|
479
|
+
// Return the array of passages and add a custom first() method to it
|
|
480
|
+
const passagesArray = [...this.passages] // Clone the array to avoid mutation
|
|
481
|
+
|
|
482
|
+
// Add first() method directly to the array
|
|
483
|
+
passagesArray.first = function () {
|
|
484
|
+
return this.length > 0 ? this[0] : null
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
return passagesArray
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
// New first() method that can be chained after getPassages()
|
|
491
|
+
first() {
|
|
492
|
+
return this.passages.length > 0 ? this.passages[0] : null
|
|
480
493
|
}
|
|
481
494
|
|
|
482
495
|
/**
|
|
@@ -542,10 +555,12 @@ class CodexParser {
|
|
|
542
555
|
* @return {object} The combined passage object.
|
|
543
556
|
*/
|
|
544
557
|
combine(passages) {
|
|
545
|
-
|
|
558
|
+
// Only check if passages are from the same book
|
|
559
|
+
const noDuplicates = [...new Set(passages.map((p) => p.book))]
|
|
546
560
|
if (noDuplicates.length > 1) {
|
|
547
|
-
throw new Error("Passages are not from the same book
|
|
561
|
+
throw new Error("Passages are not from the same book.")
|
|
548
562
|
}
|
|
563
|
+
|
|
549
564
|
const newPassages = []
|
|
550
565
|
passages.forEach((passageSet) => {
|
|
551
566
|
passageSet.passages.forEach((passage) => {
|
|
@@ -556,6 +571,7 @@ class CodexParser {
|
|
|
556
571
|
}
|
|
557
572
|
})
|
|
558
573
|
})
|
|
574
|
+
|
|
559
575
|
const noDuplicates2 = [...new Set(newPassages)]
|
|
560
576
|
const parsed = this.parse(noDuplicates2.join(" // ")).getPassages()
|
|
561
577
|
return this.join(parsed)
|
|
@@ -569,96 +585,113 @@ class CodexParser {
|
|
|
569
585
|
* @return {object} The combined passage object.
|
|
570
586
|
*/
|
|
571
587
|
join(passages) {
|
|
572
|
-
const newObject = { ...passages[0] }
|
|
573
|
-
|
|
574
|
-
for (let i = 1; i < passages.length; i++) {
|
|
575
|
-
// Combine passages, but check for duplicates
|
|
576
|
-
passages[i].passages.forEach((passage) => {
|
|
577
|
-
// Add passage only if it's not already in newObject.passages
|
|
578
|
-
const isDuplicate = newObject.passages.some(
|
|
579
|
-
(p) => p.book === passage.book && p.chapter === passage.chapter && p.verse === passage.verse
|
|
580
|
-
)
|
|
581
|
-
if (!isDuplicate) {
|
|
582
|
-
newObject.passages = newObject.passages.concat(passage)
|
|
583
|
-
}
|
|
584
|
-
})
|
|
585
|
-
const verses = passages[i].verses
|
|
586
|
-
for (let j = 0; j < verses.length; j++) {
|
|
587
|
-
const verse = verses[j]
|
|
588
|
-
newObject.verses = newObject.verses.concat(verse)
|
|
589
|
-
}
|
|
590
|
-
}
|
|
588
|
+
const newObject = { ...passages[0] } // Start with the first passage
|
|
591
589
|
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
return num >= start && num <= end
|
|
600
|
-
}
|
|
601
|
-
return false
|
|
602
|
-
})
|
|
603
|
-
}
|
|
604
|
-
return true // Keep ranges
|
|
590
|
+
const chapters = {} // Store verses by chapters
|
|
591
|
+
const uniquePassages = new Set() // Track unique passages to prevent duplicates
|
|
592
|
+
|
|
593
|
+
// Add initial passages to the unique set to avoid duplication
|
|
594
|
+
newObject.passages.forEach((p) => {
|
|
595
|
+
const passageKey = `${p.book}-${p.chapter}-${p.verse}`
|
|
596
|
+
uniquePassages.add(passageKey)
|
|
605
597
|
})
|
|
606
598
|
|
|
607
|
-
//
|
|
608
|
-
|
|
599
|
+
// Iterate through all the passages and group verses by chapter
|
|
600
|
+
passages.forEach((passage) => {
|
|
601
|
+
if (!chapters[passage.chapter]) {
|
|
602
|
+
chapters[passage.chapter] = new Set() // Use Set to avoid duplicates
|
|
603
|
+
}
|
|
609
604
|
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
605
|
+
// Add verses to their corresponding chapter
|
|
606
|
+
passage.passages.forEach((p) => {
|
|
607
|
+
chapters[p.chapter].add(p.verse)
|
|
608
|
+
|
|
609
|
+
// Create a unique key for each passage (book-chapter-verse)
|
|
610
|
+
const passageKey = `${p.book}-${p.chapter}-${p.verse}`
|
|
611
|
+
|
|
612
|
+
// Add to the passages array if it hasn't been added yet
|
|
613
|
+
if (!uniquePassages.has(passageKey)) {
|
|
614
|
+
newObject.passages.push(p) // Add the passage
|
|
615
|
+
uniquePassages.add(passageKey) // Mark it as added
|
|
619
616
|
}
|
|
620
617
|
})
|
|
618
|
+
})
|
|
621
619
|
|
|
622
|
-
|
|
623
|
-
|
|
620
|
+
// Prepare to build the final result
|
|
621
|
+
const chapterStrings = []
|
|
622
|
+
let firstChapter = null
|
|
623
|
+
let lastChapter = null
|
|
624
624
|
|
|
625
|
-
|
|
626
|
-
|
|
625
|
+
for (const chapter in chapters) {
|
|
626
|
+
const verses = Array.from(chapters[chapter]).sort((a, b) => a - b)
|
|
627
|
+
const mergedVerses = this.mergeRanges(verses) // Merge adjacent verses into ranges
|
|
628
|
+
chapterStrings.push(`${chapter}:${mergedVerses.join(",")}`)
|
|
627
629
|
|
|
628
|
-
|
|
629
|
-
|
|
630
|
+
// Track the first and last chapters for the 'to' key
|
|
631
|
+
if (!firstChapter) firstChapter = Number(chapter) // Ensure chapter is a number
|
|
632
|
+
lastChapter = Number(chapter) // Always update to the current chapter as a number
|
|
630
633
|
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
} else {
|
|
635
|
-
// No overlap, push the current range and start a new one
|
|
636
|
-
merged.push(currentRange)
|
|
637
|
-
currentRange = nextRange
|
|
638
|
-
}
|
|
634
|
+
// Update the newObject.verses with the merged ranges for the current chapter
|
|
635
|
+
if (Number(chapter) === firstChapter) {
|
|
636
|
+
newObject.verses = mergedVerses
|
|
639
637
|
}
|
|
638
|
+
}
|
|
640
639
|
|
|
641
|
-
|
|
642
|
-
|
|
640
|
+
// Build the final combined object with `to` key for multi-chapter passages
|
|
641
|
+
newObject.original = `${newObject.book} ${firstChapter}:${newObject.verses.join(",")}`
|
|
643
642
|
|
|
644
|
-
|
|
645
|
-
|
|
643
|
+
if (firstChapter !== lastChapter) {
|
|
644
|
+
newObject.to = {
|
|
645
|
+
book: newObject.book,
|
|
646
|
+
chapter: lastChapter,
|
|
647
|
+
verses: this.mergeRanges(Array.from(chapters[lastChapter])), // Ensure merged range
|
|
648
|
+
}
|
|
646
649
|
}
|
|
647
650
|
|
|
648
|
-
//
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
// Build the original and scripture properties
|
|
652
|
-
newObject.original = newObject.book + " " + newObject.chapter + ":" + newObject.verses.join(",")
|
|
651
|
+
// Build the scripture string with combined chapters (without spaces after commas)
|
|
652
|
+
const chapterString = chapterStrings.join(",") // No space after comma
|
|
653
653
|
newObject.scripture = {
|
|
654
|
-
passage: newObject.book
|
|
655
|
-
cv:
|
|
656
|
-
hash: newObject.book
|
|
654
|
+
passage: `${newObject.book} ${chapterString}`,
|
|
655
|
+
cv: chapterString,
|
|
656
|
+
hash: `${newObject.book.toLowerCase()}_${chapterString.replace(/:/g, ".").replace(/,/g, ".")}`,
|
|
657
657
|
}
|
|
658
|
-
newObject.scripture.hash = newObject.scripture.hash.toLowerCase()
|
|
659
658
|
|
|
660
659
|
return newObject
|
|
661
660
|
}
|
|
661
|
+
mergeRanges(verses) {
|
|
662
|
+
const sortedVerses = [...new Set(verses)].sort((a, b) => a - b)
|
|
663
|
+
const merged = []
|
|
664
|
+
let start = sortedVerses[0]
|
|
665
|
+
let end = sortedVerses[0]
|
|
666
|
+
|
|
667
|
+
for (let i = 1; i < sortedVerses.length; i++) {
|
|
668
|
+
if (sortedVerses[i] === end + 1) {
|
|
669
|
+
end = sortedVerses[i]
|
|
670
|
+
} else {
|
|
671
|
+
// Push the current range if it's more than 2 consecutive numbers, otherwise separate by commas
|
|
672
|
+
if (start === end) {
|
|
673
|
+
merged.push(`${start}`)
|
|
674
|
+
} else if (end === start + 1) {
|
|
675
|
+
merged.push(`${start},${end}`)
|
|
676
|
+
} else {
|
|
677
|
+
merged.push(`${start}-${end}`)
|
|
678
|
+
}
|
|
679
|
+
start = sortedVerses[i]
|
|
680
|
+
end = sortedVerses[i]
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
// Push the final range or pair
|
|
685
|
+
if (start === end) {
|
|
686
|
+
merged.push(`${start}`)
|
|
687
|
+
} else if (end === start + 1) {
|
|
688
|
+
merged.push(`${start},${end}`)
|
|
689
|
+
} else {
|
|
690
|
+
merged.push(`${start}-${end}`)
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
return merged
|
|
694
|
+
}
|
|
662
695
|
|
|
663
696
|
_isValid(passage, reference) {
|
|
664
697
|
const singleChapterBook = this.singleChapterBook.find((bible) => bible[passage.book])
|