codexparser 0.1.53 → 0.1.54
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 +146 -56
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codexparser",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.54",
|
|
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
|
@@ -191,6 +191,7 @@ class CodexParser {
|
|
|
191
191
|
this.passages = this.found.map((passage) => {
|
|
192
192
|
const book = this.bookify(passage.book)
|
|
193
193
|
const testament = this.bible.old.includes(book) ? "old" : "new"
|
|
194
|
+
const singleChapterBook = this.singleChapterBook.find((b) => Object.keys(b)[0] === book)
|
|
194
195
|
const parsedPassage = {
|
|
195
196
|
original: passage.book + " " + passage.reference,
|
|
196
197
|
book: book,
|
|
@@ -202,42 +203,72 @@ class CodexParser {
|
|
|
202
203
|
version: this._handleVersion(passage.version, testament),
|
|
203
204
|
}
|
|
204
205
|
|
|
205
|
-
// Split reference into parts (e.g., "
|
|
206
|
+
// Split reference into parts (e.g., "2 John 1", "2 John 2", "2 John 1:1-3,5")
|
|
206
207
|
const parts = passage.reference.split(",")
|
|
207
208
|
|
|
208
209
|
parts.forEach((part, partIndex) => {
|
|
209
210
|
part = part.trim()
|
|
210
211
|
|
|
211
212
|
if (part.includes(":")) {
|
|
212
|
-
// Explicit chapter:verse (e.g., "
|
|
213
|
+
// Explicit chapter:verse (e.g., "1:1-3")
|
|
213
214
|
const [chapterPart, versePart] = part.split(":")
|
|
214
215
|
if (partIndex === 0) {
|
|
215
216
|
parsedPassage.chapter = Number(chapterPart) // Set chapter only on first part
|
|
216
217
|
}
|
|
217
218
|
|
|
218
219
|
if (versePart.includes("-")) {
|
|
219
|
-
//
|
|
220
|
-
parsedPassage.verses.push(versePart)
|
|
220
|
+
parsedPassage.verses.push(versePart) // Add range (e.g., "1-3")
|
|
221
221
|
} else {
|
|
222
|
-
parsedPassage.verses.push(Number(versePart))
|
|
222
|
+
parsedPassage.verses.push(Number(versePart)) // Add single verse
|
|
223
223
|
}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
parsedPassage.
|
|
224
|
+
parsedPassage.type = versePart.includes("-") ? "chapter_verse_range" : "chapter_verse"
|
|
225
|
+
} else if (singleChapterBook) {
|
|
226
|
+
// Handle single-chapter books
|
|
227
|
+
const verseCount = singleChapterBook[book][1].length
|
|
228
|
+
if (part === "1" && parts.length === 1 && partIndex === 0) {
|
|
229
|
+
// "2 John 1" means the whole chapter
|
|
230
|
+
parsedPassage.chapter = 1
|
|
231
|
+
parsedPassage.type = "single_chapter"
|
|
232
|
+
parsedPassage.verses = [`1-${verseCount}`] // e.g., "1-13"
|
|
233
|
+
} else if (part.includes("-")) {
|
|
234
|
+
// "2 John 3-5" → "2 John 1:3-5"
|
|
235
|
+
parsedPassage.chapter = 1
|
|
236
|
+
parsedPassage.verses.push(part) // e.g., "3-5"
|
|
237
|
+
parsedPassage.type = "chapter_verse_range"
|
|
231
238
|
} else {
|
|
232
|
-
|
|
239
|
+
// "2 John 2" → "2 John 1:2"
|
|
240
|
+
const num = Number(part)
|
|
241
|
+
if (num > 1 || (num === 1 && parts.length > 1)) {
|
|
242
|
+
parsedPassage.chapter = 1
|
|
243
|
+
parsedPassage.verses.push(num) // Treat as verse number
|
|
244
|
+
parsedPassage.type = "chapter_verse"
|
|
245
|
+
}
|
|
233
246
|
}
|
|
247
|
+
} else if (part.includes("-") && !parsedPassage.chapter) {
|
|
248
|
+
// Range without chapter for multi-chapter books (e.g., "Isaiah 3-5")
|
|
249
|
+
const [start, end] = part.split("-").map(Number)
|
|
250
|
+
parsedPassage.chapter = start
|
|
251
|
+
parsedPassage.verses = [
|
|
252
|
+
`${this.chapterVerses[book][start][0]}-${this.chapterVerses[book][start].slice(-1)[0]}`,
|
|
253
|
+
]
|
|
254
|
+
parsedPassage.to = {
|
|
255
|
+
book,
|
|
256
|
+
chapter: end,
|
|
257
|
+
verses: [`${this.chapterVerses[book][end][0]}-${this.chapterVerses[book][end].slice(-1)[0]}`],
|
|
258
|
+
}
|
|
259
|
+
parsedPassage.type = "chapter_range"
|
|
260
|
+
} else if (part.includes("-")) {
|
|
261
|
+
// Verse range in current chapter (e.g., "8-9" after "40:3-5")
|
|
262
|
+
parsedPassage.verses.push(part)
|
|
263
|
+
parsedPassage.type = "chapter_verse_range"
|
|
234
264
|
} else {
|
|
235
|
-
// Single verse
|
|
236
|
-
if (parsedPassage.chapter
|
|
237
|
-
|
|
238
|
-
parsedPassage.
|
|
265
|
+
// Single number (chapter or verse) for multi-chapter books
|
|
266
|
+
if (partIndex === 0 && !parsedPassage.chapter) {
|
|
267
|
+
parsedPassage.chapter = Number(part)
|
|
268
|
+
parsedPassage.type = "single_chapter"
|
|
239
269
|
} else {
|
|
240
270
|
parsedPassage.verses.push(Number(part))
|
|
271
|
+
parsedPassage.type = "comma_separated_verses"
|
|
241
272
|
}
|
|
242
273
|
}
|
|
243
274
|
})
|
|
@@ -260,7 +291,7 @@ class CodexParser {
|
|
|
260
291
|
verses: endVerse.includes("-") ? [endVerse] : [Number(endVerse)],
|
|
261
292
|
}
|
|
262
293
|
} else {
|
|
263
|
-
delete parsedPassage.to //
|
|
294
|
+
delete parsedPassage.to // Remove erroneous 'to' property
|
|
264
295
|
}
|
|
265
296
|
|
|
266
297
|
return parsedPassage
|
|
@@ -345,20 +376,6 @@ class CodexParser {
|
|
|
345
376
|
})
|
|
346
377
|
}
|
|
347
378
|
|
|
348
|
-
/**
|
|
349
|
-
* Populate a Set of passages from entities.start.v to entities.end.v,
|
|
350
|
-
* and then add any additional verses from the verses array.
|
|
351
|
-
*
|
|
352
|
-
* @param {Object} entities - Entities object from the bible-passage-reference-parser
|
|
353
|
-
* @param {Array} verses - Array of verse numbers to add to the set of passages
|
|
354
|
-
* @return {Array} Array of passage objects
|
|
355
|
-
*/
|
|
356
|
-
/**
|
|
357
|
-
* Populate all verses from a parsed passage, including all verses in ranges or chapters.
|
|
358
|
-
*
|
|
359
|
-
* @param {Object} parsedPassage - The parsed passage object containing book, chapter, and verses information.
|
|
360
|
-
* @return {Array} An array of passage objects with individual verses.
|
|
361
|
-
*/
|
|
362
379
|
/**
|
|
363
380
|
* Populate all verses from a parsed passage, including all verses in ranges or chapters.
|
|
364
381
|
*
|
|
@@ -371,15 +388,24 @@ class CodexParser {
|
|
|
371
388
|
const version = parsedPassage.version ? parsedPassage.version.abbreviation : "eng"
|
|
372
389
|
this._setVersion(book, chapter, version) // Set version data if needed
|
|
373
390
|
|
|
391
|
+
const singleChapterBook = this.singleChapterBook.find((b) => Object.keys(b)[0] === book)
|
|
392
|
+
|
|
374
393
|
if (type === "single_chapter") {
|
|
375
|
-
// Handle entire chapter references (e.g., "Isaiah 40")
|
|
376
|
-
if (
|
|
394
|
+
// Handle entire chapter references (e.g., "Isaiah 40" or "2 John 1")
|
|
395
|
+
if (singleChapterBook) {
|
|
396
|
+
// Single-chapter book: populate all verses from singleChapterBook
|
|
397
|
+
const verseCount = singleChapterBook[book][1].length
|
|
398
|
+
for (let verse = 1; verse <= verseCount; verse++) {
|
|
399
|
+
passages.push({ book, chapter: 1, verse })
|
|
400
|
+
}
|
|
401
|
+
} else if (this.chapterVerses[book] && this.chapterVerses[book][chapter]) {
|
|
402
|
+
// Multi-chapter book: populate all verses in the chapter
|
|
377
403
|
this.chapterVerses[book][chapter].forEach((verse) => {
|
|
378
404
|
passages.push({ book, chapter: Number(chapter), verse: Number(verse) })
|
|
379
405
|
})
|
|
380
406
|
}
|
|
381
407
|
} 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 "
|
|
408
|
+
// Handle comma-separated verses or single-chapter verse ranges (e.g., "Isaiah 40:3-5,8-9" or "2 John 1:1-3")
|
|
383
409
|
verses.forEach((verse) => {
|
|
384
410
|
if (typeof verse === "string" && verse.includes("-")) {
|
|
385
411
|
const [start, end] = verse.split("-").map(Number)
|
|
@@ -419,7 +445,7 @@ class CodexParser {
|
|
|
419
445
|
}
|
|
420
446
|
}
|
|
421
447
|
} else if (type === "chapter_verse") {
|
|
422
|
-
// Handle single chapter:verse references (e.g., "
|
|
448
|
+
// Handle single chapter:verse references (e.g., "2 John 1:1")
|
|
423
449
|
verses.forEach((verse) => {
|
|
424
450
|
passages.push({ book, chapter: Number(chapter), verse: Number(verse) })
|
|
425
451
|
})
|
|
@@ -727,31 +753,35 @@ class CodexParser {
|
|
|
727
753
|
return orderedToc
|
|
728
754
|
}
|
|
729
755
|
|
|
756
|
+
/**
|
|
757
|
+
* Validates a parsed passage to ensure the chapter and verses exist.
|
|
758
|
+
*
|
|
759
|
+
* @param {Object} passage - The parsed passage object to validate.
|
|
760
|
+
* @param {string} reference - The original reference string for error messaging.
|
|
761
|
+
* @return {boolean|Object} True if valid, or an error object if invalid.
|
|
762
|
+
*/
|
|
730
763
|
_isValid(passage, reference) {
|
|
731
|
-
const singleChapterBook = this.singleChapterBook.find((
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
message: {
|
|
737
|
-
chapter_exists: false,
|
|
738
|
-
content: "Possible invalid chapter: " + reference,
|
|
739
|
-
},
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
if (!singleChapterBook) {
|
|
743
|
-
if (!this.chapterVerses[passage.book][passage.chapter]) {
|
|
764
|
+
const singleChapterBook = this.singleChapterBook.find((b) => Object.keys(b)[0] === passage.book)
|
|
765
|
+
|
|
766
|
+
// Check if verses exist at all
|
|
767
|
+
if (!passage.verses || passage.verses.length === 0) {
|
|
768
|
+
if (passage.type !== "single_chapter") {
|
|
744
769
|
return {
|
|
745
770
|
error: true,
|
|
746
|
-
code:
|
|
771
|
+
code: 101,
|
|
747
772
|
message: {
|
|
748
773
|
chapter_exists: false,
|
|
749
|
-
content:
|
|
774
|
+
content: "Possible invalid chapter: " + reference,
|
|
750
775
|
},
|
|
751
776
|
}
|
|
752
777
|
}
|
|
753
|
-
}
|
|
754
|
-
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
// Handle single-chapter books
|
|
781
|
+
if (singleChapterBook) {
|
|
782
|
+
const verseCount = singleChapterBook[passage.book][1].length
|
|
783
|
+
|
|
784
|
+
if (passage.chapter !== 1) {
|
|
755
785
|
return {
|
|
756
786
|
error: true,
|
|
757
787
|
code: 103,
|
|
@@ -761,19 +791,78 @@ class CodexParser {
|
|
|
761
791
|
},
|
|
762
792
|
}
|
|
763
793
|
}
|
|
794
|
+
|
|
795
|
+
if (passage.type === "single_chapter") {
|
|
796
|
+
// For "2 John 1", validate the full range
|
|
797
|
+
const [range] = passage.verses // e.g., "1-13"
|
|
798
|
+
if (range) {
|
|
799
|
+
const [start, end] = range.split("-").map(Number)
|
|
800
|
+
if (start < 1 || end > verseCount) {
|
|
801
|
+
return {
|
|
802
|
+
error: true,
|
|
803
|
+
code: 104,
|
|
804
|
+
message: {
|
|
805
|
+
verse_exists: false,
|
|
806
|
+
content: `Verse range ${start}-${end} exceeds available verses (1-${verseCount}) in ${passage.book} 1`,
|
|
807
|
+
},
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
return true // If no specific verses or range matches, it’s valid
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
// For specific verses in single-chapter books (e.g., "2 John 1:1-3")
|
|
815
|
+
for (let i = 0; i < passage.verses.length; i++) {
|
|
816
|
+
const verseRange = String(passage.verses[i])
|
|
817
|
+
let versesToCheck = verseRange.includes("-") ? verseRange.split("-").map(Number) : [Number(verseRange)]
|
|
818
|
+
|
|
819
|
+
if (versesToCheck.length === 2) {
|
|
820
|
+
const [start, end] = versesToCheck
|
|
821
|
+
versesToCheck = Array.from({ length: end - start + 1 }, (_, idx) => start + idx)
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
for (const verse of versesToCheck) {
|
|
825
|
+
if (verse < 1 || verse > verseCount) {
|
|
826
|
+
return {
|
|
827
|
+
error: true,
|
|
828
|
+
code: 104,
|
|
829
|
+
message: {
|
|
830
|
+
verse_exists: false,
|
|
831
|
+
content: `Verse number ${verse} does not exist in ${passage.book} 1`,
|
|
832
|
+
},
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
return true
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
// Handle multi-chapter books
|
|
841
|
+
if (!this.chapterVerses[passage.book] || !this.chapterVerses[passage.book][passage.chapter]) {
|
|
842
|
+
return {
|
|
843
|
+
error: true,
|
|
844
|
+
code: 102,
|
|
845
|
+
message: {
|
|
846
|
+
chapter_exists: false,
|
|
847
|
+
content: `Chapter ${passage.chapter} does not exist in ${passage.book}`,
|
|
848
|
+
},
|
|
849
|
+
}
|
|
764
850
|
}
|
|
851
|
+
|
|
852
|
+
if (passage.type === "single_chapter") {
|
|
853
|
+
return true // For multi-chapter books, whole chapter is valid if it exists
|
|
854
|
+
}
|
|
855
|
+
|
|
765
856
|
for (let i = 0; i < passage.verses.length; i++) {
|
|
766
857
|
const passageVerses = String(passage.verses[i])
|
|
767
|
-
let verses = passageVerses.split("-").map(Number)
|
|
858
|
+
let verses = passageVerses.includes("-") ? passageVerses.split("-").map(Number) : [Number(passageVerses)]
|
|
768
859
|
|
|
769
860
|
if (verses.length === 2) {
|
|
770
861
|
// Expand the range if there are two numbers
|
|
771
862
|
verses = Array.from({ length: verses[1] - verses[0] + 1 }, (_, index) => verses[0] + index)
|
|
772
863
|
}
|
|
773
864
|
|
|
774
|
-
// The verses array now contains all values between the range or remains as a single value
|
|
775
865
|
for (const verse of verses) {
|
|
776
|
-
// Check if the verse exists in the chapterVerses structure
|
|
777
866
|
const isValidVerse =
|
|
778
867
|
this.chapterVerses[passage.book] &&
|
|
779
868
|
this.chapterVerses[passage.book][passage.chapter] &&
|
|
@@ -791,6 +880,7 @@ class CodexParser {
|
|
|
791
880
|
}
|
|
792
881
|
}
|
|
793
882
|
}
|
|
883
|
+
|
|
794
884
|
return true
|
|
795
885
|
}
|
|
796
886
|
_handleVersion(version, testament) {
|