codexparser 0.1.42 → 0.1.43
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 +110 -79
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codexparser",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.43",
|
|
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
|
@@ -147,16 +147,19 @@ class CodexParser {
|
|
|
147
147
|
|
|
148
148
|
references.forEach((ref) => {
|
|
149
149
|
let type
|
|
150
|
-
|
|
151
150
|
if (ref.includes(":")) {
|
|
152
151
|
if (ref.includes("-")) {
|
|
153
152
|
const [start, end] = ref.split("-")
|
|
154
153
|
const startParts = start.split(":")
|
|
155
154
|
const endParts = end.split(":")
|
|
155
|
+
|
|
156
|
+
// Determine type based on the chapter (startParts[0] and endParts[0])
|
|
156
157
|
type =
|
|
158
|
+
startParts.length > 1 &&
|
|
159
|
+
endParts.length > 1 &&
|
|
157
160
|
startParts[0].trim() !== endParts[0].trim()
|
|
158
|
-
? "multi_chapter_verse_range"
|
|
159
|
-
: "chapter_verse_range"
|
|
161
|
+
? "multi_chapter_verse_range" // Chapters differ
|
|
162
|
+
: "chapter_verse_range" // Same chapter
|
|
160
163
|
} else if (ref.includes(",")) {
|
|
161
164
|
type = "comma_separated_verses"
|
|
162
165
|
} else {
|
|
@@ -242,12 +245,14 @@ class CodexParser {
|
|
|
242
245
|
// Checks to see if we are in a multi chapter verse range, if so, include only relevant verses from the this.chapterVerse to
|
|
243
246
|
// the end of the chapter.
|
|
244
247
|
if (start.includes(separator) && end.includes(separator)) {
|
|
248
|
+
// TODO: Need to update versification and version here.
|
|
249
|
+
this._setVersion(book, startChapter, passage.version)
|
|
245
250
|
parsedPassage.verses = this.chapterVerses[book][startChapter].slice(
|
|
246
251
|
this.chapterVerses[book][startChapter].indexOf(Number(startVerse))
|
|
247
252
|
)
|
|
248
253
|
}
|
|
249
254
|
|
|
250
|
-
// Handle
|
|
255
|
+
// Handle chapter ranges (e.g., "27:27-29") and multi-chapter ranges (e.g., "Ex 2:1-3:4")
|
|
251
256
|
if (end.includes(separator)) {
|
|
252
257
|
let [endChapter, endVerse] = end.split(separator)
|
|
253
258
|
if (Number(endChapter) !== Number(startChapter)) {
|
|
@@ -256,11 +261,14 @@ class CodexParser {
|
|
|
256
261
|
book: book,
|
|
257
262
|
chapter: Number(endChapter), // End chapter
|
|
258
263
|
}
|
|
264
|
+
|
|
259
265
|
if (endVerse > 1) {
|
|
260
266
|
parsedPassage.to.verses = this.chapterVerses[book][Number(endChapter)].slice(
|
|
261
267
|
0,
|
|
262
268
|
this.chapterVerses[book][Number(endChapter)].indexOf(Number(endVerse)) + 1
|
|
263
269
|
)
|
|
270
|
+
} else {
|
|
271
|
+
parsedPassage.to.verses = [endVerse]
|
|
264
272
|
}
|
|
265
273
|
parsedPassage.type =
|
|
266
274
|
endChapter !== startChapter ? "multi_chapter_verse_range" : "chapter_verse_range" // Set type to chapter range
|
|
@@ -350,18 +358,17 @@ class CodexParser {
|
|
|
350
358
|
return range
|
|
351
359
|
}
|
|
352
360
|
|
|
353
|
-
_searchVersificationDifferences(
|
|
354
|
-
|
|
361
|
+
_searchVersificationDifferences(book, chapter, version) {
|
|
362
|
+
version = version.toLowerCase()
|
|
355
363
|
if (!this.chapterVerses[book][chapter]) return
|
|
356
|
-
|
|
357
364
|
// Loop through each key-value pair in the dictionary
|
|
358
365
|
for (const [key, value] of Object.entries(this.versificationDifferences[book])) {
|
|
359
366
|
// Check if the key starts with the desired chapter
|
|
360
|
-
if (value[version
|
|
367
|
+
if (value[version].startsWith(`${chapter}:`)) {
|
|
361
368
|
// Ensure the version exists in the value object
|
|
362
|
-
if (value[version
|
|
369
|
+
if (value[version]) {
|
|
363
370
|
// Extract the verse number from the value
|
|
364
|
-
const verse = value[version
|
|
371
|
+
const verse = value[version].split(":")[1]
|
|
365
372
|
this.chapterVerses[book][chapter].push(Number(verse))
|
|
366
373
|
}
|
|
367
374
|
}
|
|
@@ -370,11 +377,11 @@ class CodexParser {
|
|
|
370
377
|
return this.chapterVerses // Return the array of verses
|
|
371
378
|
}
|
|
372
379
|
|
|
373
|
-
_setVersion(
|
|
374
|
-
this.version =
|
|
380
|
+
_setVersion(book, chapter, version) {
|
|
381
|
+
this.version = version ? version : "eng"
|
|
375
382
|
|
|
376
383
|
if (this.version !== "eng") {
|
|
377
|
-
this._searchVersificationDifferences(
|
|
384
|
+
this._searchVersificationDifferences(book, chapter, version)
|
|
378
385
|
}
|
|
379
386
|
}
|
|
380
387
|
|
|
@@ -432,8 +439,8 @@ class CodexParser {
|
|
|
432
439
|
populate(parsedPassage) {
|
|
433
440
|
const passages = []
|
|
434
441
|
const { book, chapter, verses, type, to } = parsedPassage
|
|
435
|
-
|
|
436
|
-
this._setVersion(
|
|
442
|
+
const version = parsedPassage.version ? parsedPassage.version.abbreviation : "eng"
|
|
443
|
+
this._setVersion(book, chapter, version) // Set version data if needed
|
|
437
444
|
|
|
438
445
|
if (type === "single_chapter") {
|
|
439
446
|
// Handle entire chapter references
|
|
@@ -460,7 +467,6 @@ class CodexParser {
|
|
|
460
467
|
}
|
|
461
468
|
} else if (type === "multi_chapter_verse_range") {
|
|
462
469
|
// Handle multi-chapter verse ranges (e.g., 3:1-5:6)
|
|
463
|
-
|
|
464
470
|
const startChapter = chapter
|
|
465
471
|
const startVerse = verses[0]
|
|
466
472
|
const endChapter = to.chapter
|
|
@@ -648,7 +654,6 @@ class CodexParser {
|
|
|
648
654
|
const noDuplicates2 = [...new Set(newPassages)]
|
|
649
655
|
|
|
650
656
|
const parsed = this.parse(noDuplicates2.join(" // ")).getPassages()
|
|
651
|
-
|
|
652
657
|
return this.join(parsed)
|
|
653
658
|
}
|
|
654
659
|
|
|
@@ -660,86 +665,100 @@ class CodexParser {
|
|
|
660
665
|
* @return {object} The combined passage object.
|
|
661
666
|
*/
|
|
662
667
|
join(passages) {
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
const uniquePassages = new Set() // Track unique passages to prevent duplicates
|
|
667
|
-
// Add initial passages to the unique set to avoid duplication
|
|
668
|
-
newObject.passages.forEach((p) => {
|
|
669
|
-
const passageKey = `${p.book}-${p.chapter}-${p.verse}`
|
|
670
|
-
uniquePassages.add(passageKey)
|
|
671
|
-
})
|
|
668
|
+
if (!passages || passages.length === 0) {
|
|
669
|
+
throw new Error("No passages provided to join.")
|
|
670
|
+
}
|
|
672
671
|
|
|
673
|
-
//
|
|
674
|
-
passages.
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
672
|
+
// Ensure all passages are from the same book
|
|
673
|
+
const uniqueBooks = [...new Set(passages.map((p) => p.book))]
|
|
674
|
+
if (uniqueBooks.length > 1) {
|
|
675
|
+
throw new Error("Passages must be from the same book to join.")
|
|
676
|
+
}
|
|
678
677
|
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
678
|
+
// Start with the base object
|
|
679
|
+
const combined = {
|
|
680
|
+
...passages[0],
|
|
681
|
+
verses: [],
|
|
682
|
+
passages: [],
|
|
683
|
+
to: null,
|
|
684
|
+
scripture: {},
|
|
685
|
+
type: null,
|
|
686
|
+
}
|
|
682
687
|
|
|
683
|
-
|
|
684
|
-
|
|
688
|
+
const chapterVerses = {}
|
|
689
|
+
let firstChapter = null
|
|
690
|
+
let lastChapter = null
|
|
685
691
|
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
692
|
+
// Collect all verses and passages, grouped by chapter
|
|
693
|
+
passages.forEach((passage) => {
|
|
694
|
+
passage.passages.forEach((p) => {
|
|
695
|
+
if (!chapterVerses[p.chapter]) {
|
|
696
|
+
chapterVerses[p.chapter] = new Set()
|
|
690
697
|
}
|
|
698
|
+
chapterVerses[p.chapter].add(p.verse)
|
|
699
|
+
combined.passages.push(p) // Add individual passage
|
|
691
700
|
})
|
|
692
|
-
})
|
|
693
701
|
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
if (
|
|
697
|
-
|
|
702
|
+
// Track first and last chapters
|
|
703
|
+
const chapters = passage.passages.map((p) => p.chapter)
|
|
704
|
+
if (!firstChapter || Math.min(...chapters) < firstChapter) {
|
|
705
|
+
firstChapter = Math.min(...chapters)
|
|
706
|
+
}
|
|
707
|
+
if (!lastChapter || Math.max(...chapters) > lastChapter) {
|
|
708
|
+
lastChapter = Math.max(...chapters)
|
|
698
709
|
}
|
|
699
|
-
return a.verse - b.verse // Sort by verse within the same chapter
|
|
700
710
|
})
|
|
701
711
|
|
|
702
|
-
//
|
|
712
|
+
// Ensure unique and sorted passages
|
|
713
|
+
combined.passages = Array.from(new Set(combined.passages.map(JSON.stringify))).map(JSON.parse)
|
|
714
|
+
|
|
715
|
+
// Process chapter and verse data
|
|
703
716
|
const chapterStrings = []
|
|
704
|
-
|
|
705
|
-
|
|
717
|
+
const sortedChapters = Object.keys(chapterVerses)
|
|
718
|
+
.map(Number)
|
|
719
|
+
.sort((a, b) => a - b)
|
|
706
720
|
|
|
707
|
-
|
|
708
|
-
const verses = Array.from(
|
|
709
|
-
const mergedVerses = this.mergeRanges(verses)
|
|
721
|
+
sortedChapters.forEach((chapter) => {
|
|
722
|
+
const verses = Array.from(chapterVerses[chapter]).sort((a, b) => a - b)
|
|
723
|
+
const mergedVerses = this.mergeRanges(verses)
|
|
710
724
|
chapterStrings.push(`${chapter}:${mergedVerses.join(",")}`)
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
if (!firstChapter) firstChapter = Number(chapter) // Ensure chapter is a number
|
|
714
|
-
lastChapter = Number(chapter) // Always update to the current chapter as a number
|
|
715
|
-
|
|
716
|
-
// Update the newObject.verses with the merged ranges for the current chapter
|
|
717
|
-
if (Number(chapter) === firstChapter) {
|
|
718
|
-
newObject.verses = mergedVerses
|
|
725
|
+
if (chapter === firstChapter) {
|
|
726
|
+
combined.verses = mergedVerses // First chapter's verses
|
|
719
727
|
}
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
// Build the final combined object with `to` key for multi-chapter passages
|
|
723
|
-
newObject.original = `${newObject.book} ${firstChapter}:${newObject.verses.join(",")}`
|
|
728
|
+
})
|
|
724
729
|
|
|
730
|
+
// Handle multi-chapter ranges
|
|
725
731
|
if (firstChapter !== lastChapter) {
|
|
726
|
-
|
|
727
|
-
|
|
732
|
+
combined.type = "multi_chapter_verse_range"
|
|
733
|
+
combined.to = {
|
|
734
|
+
book: combined.book,
|
|
728
735
|
chapter: lastChapter,
|
|
729
|
-
verses: this.mergeRanges(Array.from(
|
|
736
|
+
verses: this.mergeRanges(Array.from(chapterVerses[lastChapter])),
|
|
737
|
+
}
|
|
738
|
+
combined.original = `${combined.book} ${firstChapter}:${combined.verses.join(
|
|
739
|
+
","
|
|
740
|
+
)}-${lastChapter}:${combined.to.verses.join(",")}`
|
|
741
|
+
} else {
|
|
742
|
+
// Single-chapter range or comma-separated
|
|
743
|
+
if (combined.verses.length > 1) {
|
|
744
|
+
combined.type = "chapter_verse_range"
|
|
745
|
+
} else {
|
|
746
|
+
combined.type = "chapter_verse"
|
|
730
747
|
}
|
|
748
|
+
combined.original = `${combined.book} ${firstChapter}:${combined.verses.join(",")}`
|
|
731
749
|
}
|
|
732
750
|
|
|
733
|
-
// Build the scripture
|
|
734
|
-
const chapterString = chapterStrings.join(",")
|
|
735
|
-
|
|
736
|
-
passage: `${
|
|
751
|
+
// Build the scripture property
|
|
752
|
+
const chapterString = chapterStrings.join(",")
|
|
753
|
+
combined.scripture = {
|
|
754
|
+
passage: `${combined.book} ${chapterString}`,
|
|
737
755
|
cv: chapterString,
|
|
738
|
-
hash: `${
|
|
756
|
+
hash: `${combined.book.toLowerCase()}_${chapterString.replace(/:/g, ".").replace(/,/g, ".")}`,
|
|
739
757
|
}
|
|
740
758
|
|
|
741
|
-
return
|
|
759
|
+
return combined
|
|
742
760
|
}
|
|
761
|
+
|
|
743
762
|
mergeRanges(verses) {
|
|
744
763
|
const sortedVerses = [...new Set(verses)].sort((a, b) => a - b)
|
|
745
764
|
const merged = []
|
|
@@ -750,11 +769,9 @@ class CodexParser {
|
|
|
750
769
|
if (sortedVerses[i] === end + 1) {
|
|
751
770
|
end = sortedVerses[i]
|
|
752
771
|
} else {
|
|
753
|
-
// Push
|
|
772
|
+
// Push range or single verse
|
|
754
773
|
if (start === end) {
|
|
755
774
|
merged.push(`${start}`)
|
|
756
|
-
} else if (end === start + 1) {
|
|
757
|
-
merged.push(`${start},${end}`)
|
|
758
775
|
} else {
|
|
759
776
|
merged.push(`${start}-${end}`)
|
|
760
777
|
}
|
|
@@ -763,11 +780,9 @@ class CodexParser {
|
|
|
763
780
|
}
|
|
764
781
|
}
|
|
765
782
|
|
|
766
|
-
// Push the final range or
|
|
783
|
+
// Push the final range or single verse
|
|
767
784
|
if (start === end) {
|
|
768
785
|
merged.push(`${start}`)
|
|
769
|
-
} else if (end === start + 1) {
|
|
770
|
-
merged.push(`${start},${end}`)
|
|
771
786
|
} else {
|
|
772
787
|
merged.push(`${start}-${end}`)
|
|
773
788
|
}
|
|
@@ -849,6 +864,22 @@ class CodexParser {
|
|
|
849
864
|
}
|
|
850
865
|
}
|
|
851
866
|
}
|
|
867
|
+
for (let i = 0; i < passage.verses.length; i++) {
|
|
868
|
+
let verse = passage.verses[i]
|
|
869
|
+
const searchForVerse = this.chapterVerses[passage.book][passage.chapter].find(
|
|
870
|
+
(v) => Number(v) === Number(verse)
|
|
871
|
+
)
|
|
872
|
+
if (!searchForVerse) {
|
|
873
|
+
return {
|
|
874
|
+
error: true,
|
|
875
|
+
code: 104,
|
|
876
|
+
message: {
|
|
877
|
+
verse_exists: false,
|
|
878
|
+
content: `Verse number ${verse} does not exist in ${passage.book} ${passage.chapter}`,
|
|
879
|
+
},
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
}
|
|
852
883
|
return true
|
|
853
884
|
}
|
|
854
885
|
_handleVersion(version, testament) {
|