codexparser 0.1.89 → 0.1.91
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 +260 -22
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codexparser",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.91",
|
|
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
|
@@ -352,8 +352,10 @@ class CodexParser {
|
|
|
352
352
|
const { value, abbr } = sblEntry[1]
|
|
353
353
|
const ref = passage.reference.replace(/\s*(LXX|MT)$/i, "").trim()
|
|
354
354
|
parsedPassage.abbr = abbr
|
|
355
|
-
? `${value}. ${ref}${
|
|
356
|
-
|
|
355
|
+
? `${value}. ${ref}${
|
|
356
|
+
parsedPassage.version.value !== "ENG" ? " " + parsedPassage.version.value : ""
|
|
357
|
+
}`
|
|
358
|
+
: `${value} ${ref}${parsedPassage.version.value !== "ENG" ? " " + parsedPassage.version.value : ""}`
|
|
357
359
|
} else {
|
|
358
360
|
parsedPassage.abbr = parsedPassage.original
|
|
359
361
|
}
|
|
@@ -803,6 +805,7 @@ class CodexParser {
|
|
|
803
805
|
*/
|
|
804
806
|
getPassages() {
|
|
805
807
|
const passagesArray = [...this.passages]
|
|
808
|
+
const self = this
|
|
806
809
|
|
|
807
810
|
passagesArray.first = function () {
|
|
808
811
|
return this.length > 0 ? this[0] : null
|
|
@@ -823,7 +826,6 @@ class CodexParser {
|
|
|
823
826
|
return [...this]
|
|
824
827
|
}
|
|
825
828
|
|
|
826
|
-
const parser = new CodexParser()
|
|
827
829
|
const groupedByBook = new Map()
|
|
828
830
|
|
|
829
831
|
this.forEach((passage) => {
|
|
@@ -851,12 +853,12 @@ class CodexParser {
|
|
|
851
853
|
if (passages.length === 1) {
|
|
852
854
|
combinedPassages.push({ ...passages[0] })
|
|
853
855
|
} else {
|
|
854
|
-
const combined =
|
|
856
|
+
const combined = self.combine(passages)
|
|
855
857
|
combinedPassages.push(combined)
|
|
856
858
|
}
|
|
857
859
|
}
|
|
858
860
|
} else {
|
|
859
|
-
const combined =
|
|
861
|
+
const combined = self.combine(bookPassages)
|
|
860
862
|
combinedPassages.push(combined)
|
|
861
863
|
}
|
|
862
864
|
}
|
|
@@ -864,6 +866,207 @@ class CodexParser {
|
|
|
864
866
|
return combinedPassages
|
|
865
867
|
}
|
|
866
868
|
|
|
869
|
+
passagesArray.getVersion = function (targetVersion) {
|
|
870
|
+
const targetAbbr = targetVersion.toLowerCase() === "bhs" ? "mt" : targetVersion.toLowerCase()
|
|
871
|
+
let versionObj
|
|
872
|
+
if (targetAbbr === "eng") {
|
|
873
|
+
versionObj = { name: "English", value: "ENG", abbreviation: "eng" }
|
|
874
|
+
} else if (targetAbbr === "mt") {
|
|
875
|
+
versionObj = { name: "Masoretic Text", value: "MT", abbreviation: "mt" }
|
|
876
|
+
} else if (targetAbbr === "lxx") {
|
|
877
|
+
versionObj = { name: "Septuagint", value: "LXX", abbreviation: "lxx" }
|
|
878
|
+
} else {
|
|
879
|
+
throw new Error("Invalid version: must be one of 'eng', 'mt', 'bhs', 'lxx'")
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
const converted = this.map((passage) => {
|
|
883
|
+
const cloned = JSON.parse(JSON.stringify(passage))
|
|
884
|
+
cloned.version = versionObj
|
|
885
|
+
|
|
886
|
+
cloned.passages.forEach((sub) => {
|
|
887
|
+
if (sub.versification && sub.versification[targetAbbr]) {
|
|
888
|
+
const [ch, v] = sub.versification[targetAbbr].split(":").map(Number)
|
|
889
|
+
sub.chapter = ch
|
|
890
|
+
sub.verse = v
|
|
891
|
+
}
|
|
892
|
+
// else remain unchanged
|
|
893
|
+
})
|
|
894
|
+
|
|
895
|
+
// Recompute summary fields
|
|
896
|
+
cloned.passages.sort((a, b) => a.chapter - b.chapter || a.verse - b.verse)
|
|
897
|
+
|
|
898
|
+
if (cloned.passages.length > 0) {
|
|
899
|
+
cloned.start = {
|
|
900
|
+
book: cloned.book,
|
|
901
|
+
chapter: cloned.passages[0].chapter,
|
|
902
|
+
verse: cloned.passages[0].verse,
|
|
903
|
+
}
|
|
904
|
+
cloned.end = {
|
|
905
|
+
book: cloned.book,
|
|
906
|
+
chapter: cloned.passages[cloned.passages.length - 1].chapter,
|
|
907
|
+
verse: cloned.passages[cloned.passages.length - 1].verse,
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
const chapterVersesMap = {}
|
|
912
|
+
cloned.passages.forEach((p) => {
|
|
913
|
+
if (!chapterVersesMap[p.chapter]) chapterVersesMap[p.chapter] = new Set()
|
|
914
|
+
chapterVersesMap[p.chapter].add(p.verse)
|
|
915
|
+
})
|
|
916
|
+
|
|
917
|
+
const sortedChs = Object.keys(chapterVersesMap)
|
|
918
|
+
.map(Number)
|
|
919
|
+
.sort((a, b) => a - b)
|
|
920
|
+
const chapterStrs = []
|
|
921
|
+
|
|
922
|
+
const mergeFunc = (verses) => {
|
|
923
|
+
const sorted = [...verses].sort((a, b) => a - b)
|
|
924
|
+
const merged = []
|
|
925
|
+
if (sorted.length === 0) return merged
|
|
926
|
+
let start = sorted[0]
|
|
927
|
+
let end = sorted[0]
|
|
928
|
+
for (let i = 1; i < sorted.length; i++) {
|
|
929
|
+
if (sorted[i] === end + 1) {
|
|
930
|
+
end = sorted[i]
|
|
931
|
+
} else {
|
|
932
|
+
merged.push(start === end ? `${start}` : `${start}-${end}`)
|
|
933
|
+
start = end = sorted[i]
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
merged.push(start === end ? `${start}` : `${start}-${end}`)
|
|
937
|
+
return merged
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
sortedChs.forEach((ch) => {
|
|
941
|
+
const vs = Array.from(chapterVersesMap[ch])
|
|
942
|
+
.filter((v) => v > 0)
|
|
943
|
+
.sort((a, b) => a - b)
|
|
944
|
+
if (vs.length > 0) {
|
|
945
|
+
const merged = mergeFunc(vs)
|
|
946
|
+
chapterStrs.push(`${ch}:${merged.join(",")}`)
|
|
947
|
+
}
|
|
948
|
+
})
|
|
949
|
+
|
|
950
|
+
if (chapterStrs.length === 0) {
|
|
951
|
+
return cloned // no verses, perhaps error but return as is
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
const firstCh = sortedChs[0]
|
|
955
|
+
const lastCh = sortedChs[sortedChs.length - 1]
|
|
956
|
+
cloned.chapter = firstCh
|
|
957
|
+
|
|
958
|
+
const mergedFirst = mergeFunc(chapterVersesMap[firstCh] || new Set())
|
|
959
|
+
cloned.verses = mergedFirst
|
|
960
|
+
|
|
961
|
+
if (firstCh !== lastCh) {
|
|
962
|
+
cloned.type = this.MULTI_CHAPTER_RANGE
|
|
963
|
+
cloned.to = {
|
|
964
|
+
book: cloned.book,
|
|
965
|
+
chapter: lastCh,
|
|
966
|
+
verses: mergeFunc(chapterVersesMap[lastCh] || new Set()),
|
|
967
|
+
}
|
|
968
|
+
cloned.original = `${cloned.book} ${chapterStrs.join("; ")}`
|
|
969
|
+
} else {
|
|
970
|
+
const hasRangeOrMultiple =
|
|
971
|
+
mergedFirst.length > 1 || (mergedFirst.length === 1 && mergedFirst[0].includes("-"))
|
|
972
|
+
cloned.type = hasRangeOrMultiple ? this.CHAPTER_VERSE_RANGE : this.CHAPTER_VERSE
|
|
973
|
+
if (cloned.to) delete cloned.to
|
|
974
|
+
cloned.original = `${cloned.book} ${chapterStrs[0]}`
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
const chString = chapterStrs.join("; ")
|
|
978
|
+
cloned.scripture = {
|
|
979
|
+
passage: `${cloned.book} ${chString}`,
|
|
980
|
+
cv: chString,
|
|
981
|
+
hash: `${cloned.book.toLowerCase()}_${chString
|
|
982
|
+
.replace(/:/g, ".")
|
|
983
|
+
.replace(/-/g, ".")
|
|
984
|
+
.replace(/[,; ]/g, ".")}`,
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
// Set abbr
|
|
988
|
+
const sblEntry = Object.entries(self.sblAbbreviations).find(
|
|
989
|
+
([key]) => key.toLowerCase() === cloned.book.toLowerCase()
|
|
990
|
+
)
|
|
991
|
+
const suffix = versionObj.abbreviation === "eng" ? "" : ` ${versionObj.value}`
|
|
992
|
+
if (sblEntry) {
|
|
993
|
+
const { value, abbr } = sblEntry[1]
|
|
994
|
+
cloned.abbr = abbr
|
|
995
|
+
? `${value}. ${cloned.scripture.cv}${suffix}`
|
|
996
|
+
: `${value} ${cloned.scripture.cv}${suffix}`
|
|
997
|
+
} else {
|
|
998
|
+
cloned.abbr = `${cloned.book} ${cloned.scripture.cv}${suffix}`
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
return cloned
|
|
1002
|
+
})
|
|
1003
|
+
|
|
1004
|
+
const newArray = [...converted]
|
|
1005
|
+
|
|
1006
|
+
newArray.first = function () {
|
|
1007
|
+
return this.length > 0 ? this[0] : null
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
newArray.oldTestament = function () {
|
|
1011
|
+
return this.filter((passage) => passage.testament === "old")
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
newArray.newTestament = function () {
|
|
1015
|
+
return this.filter((passage) => passage.testament === "new")
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
newArray.combine = function (options = {}) {
|
|
1019
|
+
const { book = true, chapter = true } = options
|
|
1020
|
+
|
|
1021
|
+
if (!book) {
|
|
1022
|
+
return [...this]
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
const groupedByBook = new Map()
|
|
1026
|
+
|
|
1027
|
+
this.forEach((passage) => {
|
|
1028
|
+
const bookKey = passage.book
|
|
1029
|
+
if (!groupedByBook.has(bookKey)) {
|
|
1030
|
+
groupedByBook.set(bookKey, [])
|
|
1031
|
+
}
|
|
1032
|
+
groupedByBook.get(bookKey).push(passage)
|
|
1033
|
+
})
|
|
1034
|
+
|
|
1035
|
+
const combinedPassages = []
|
|
1036
|
+
|
|
1037
|
+
for (const [book, bookPassages] of groupedByBook) {
|
|
1038
|
+
if (chapter) {
|
|
1039
|
+
const groupedByChapter = new Map()
|
|
1040
|
+
bookPassages.forEach((passage) => {
|
|
1041
|
+
const chapterKey = `${passage.book}-${passage.chapter}`
|
|
1042
|
+
if (!groupedByChapter.has(chapterKey)) {
|
|
1043
|
+
groupedByChapter.set(chapterKey, [])
|
|
1044
|
+
}
|
|
1045
|
+
groupedByChapter.get(chapterKey).push(passage)
|
|
1046
|
+
})
|
|
1047
|
+
|
|
1048
|
+
for (const passages of groupedByChapter.values()) {
|
|
1049
|
+
if (passages.length === 1) {
|
|
1050
|
+
combinedPassages.push({ ...passages[0] })
|
|
1051
|
+
} else {
|
|
1052
|
+
const combined = self.combine(passages)
|
|
1053
|
+
combinedPassages.push(combined)
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
} else {
|
|
1057
|
+
const combined = self.combine(bookPassages)
|
|
1058
|
+
combinedPassages.push(combined)
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
return combinedPassages
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
newArray.getVersion = passagesArray.getVersion
|
|
1066
|
+
|
|
1067
|
+
return newArray
|
|
1068
|
+
}
|
|
1069
|
+
|
|
867
1070
|
return passagesArray
|
|
868
1071
|
}
|
|
869
1072
|
|
|
@@ -957,23 +1160,35 @@ class CodexParser {
|
|
|
957
1160
|
|
|
958
1161
|
passages.forEach((passage) => {
|
|
959
1162
|
passage.passages.forEach((p) => {
|
|
960
|
-
|
|
961
|
-
|
|
1163
|
+
let normChapter = p.chapter
|
|
1164
|
+
let normVerse = p.verse
|
|
1165
|
+
if (p.versification && p.versification.eng) {
|
|
1166
|
+
const [c, v] = p.versification.eng.split(":").map(Number)
|
|
1167
|
+
normChapter = c
|
|
1168
|
+
normVerse = v
|
|
962
1169
|
}
|
|
963
|
-
chapterVerses[
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
if (firstChapter === null || p.chapter < firstChapter) {
|
|
967
|
-
firstChapter = p.chapter
|
|
968
|
-
firstVerse = p.verse
|
|
969
|
-
} else if (p.chapter === firstChapter && (firstVerse === null || p.verse < firstVerse)) {
|
|
970
|
-
firstVerse = p.verse
|
|
1170
|
+
if (!chapterVerses[normChapter]) {
|
|
1171
|
+
chapterVerses[normChapter] = new Set()
|
|
971
1172
|
}
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
1173
|
+
chapterVerses[normChapter].add(normVerse)
|
|
1174
|
+
combined.passages.push({
|
|
1175
|
+
book: p.book,
|
|
1176
|
+
chapter: normChapter,
|
|
1177
|
+
verse: normVerse,
|
|
1178
|
+
versification: p.versification,
|
|
1179
|
+
})
|
|
1180
|
+
|
|
1181
|
+
if (firstChapter === null || normChapter < firstChapter) {
|
|
1182
|
+
firstChapter = normChapter
|
|
1183
|
+
firstVerse = normVerse
|
|
1184
|
+
} else if (normChapter === firstChapter && (firstVerse === null || normVerse < firstVerse)) {
|
|
1185
|
+
firstVerse = normVerse
|
|
1186
|
+
}
|
|
1187
|
+
if (lastChapter === null || normChapter > lastChapter) {
|
|
1188
|
+
lastChapter = normChapter
|
|
1189
|
+
lastVerse = normVerse
|
|
1190
|
+
} else if (normChapter === lastChapter && (lastVerse === null || normVerse > lastVerse)) {
|
|
1191
|
+
lastVerse = normVerse
|
|
977
1192
|
}
|
|
978
1193
|
})
|
|
979
1194
|
})
|
|
@@ -1003,12 +1218,18 @@ class CodexParser {
|
|
|
1003
1218
|
throw new Error("No valid verses found in passages.")
|
|
1004
1219
|
}
|
|
1005
1220
|
|
|
1221
|
+
combined.chapter = firstChapter
|
|
1222
|
+
|
|
1006
1223
|
if (firstChapter !== lastChapter) {
|
|
1007
1224
|
combined.type = this.MULTI_CHAPTER_RANGE
|
|
1008
1225
|
combined.to = {
|
|
1009
1226
|
book: combined.book,
|
|
1010
1227
|
chapter: lastChapter,
|
|
1011
|
-
verses: this.mergeRanges(
|
|
1228
|
+
verses: this.mergeRanges(
|
|
1229
|
+
Array.from(chapterVerses[lastChapter])
|
|
1230
|
+
.filter((verse) => verse > 0)
|
|
1231
|
+
.sort((a, b) => a - b)
|
|
1232
|
+
),
|
|
1012
1233
|
}
|
|
1013
1234
|
combined.original = `${combined.book} ${chapterStrings.join("; ")}`
|
|
1014
1235
|
} else {
|
|
@@ -1020,7 +1241,10 @@ class CodexParser {
|
|
|
1020
1241
|
combined.scripture = {
|
|
1021
1242
|
passage: `${combined.book} ${chapterString}`,
|
|
1022
1243
|
cv: chapterString,
|
|
1023
|
-
hash: `${combined.book.toLowerCase()}_${chapterString
|
|
1244
|
+
hash: `${combined.book.toLowerCase()}_${chapterString
|
|
1245
|
+
.replace(/:/g, ".")
|
|
1246
|
+
.replace(/-/g, ".")
|
|
1247
|
+
.replace(/[,;]/g, ".")}`,
|
|
1024
1248
|
}
|
|
1025
1249
|
|
|
1026
1250
|
combined.start = {
|
|
@@ -1048,6 +1272,20 @@ class CodexParser {
|
|
|
1048
1272
|
delete combined.to
|
|
1049
1273
|
}
|
|
1050
1274
|
|
|
1275
|
+
// Prefer English version
|
|
1276
|
+
combined.version = { name: "English", value: "ENG", abbreviation: "eng" }
|
|
1277
|
+
|
|
1278
|
+
// Set abbr without version suffix
|
|
1279
|
+
const sblEntry = Object.entries(this.sblAbbreviations).find(
|
|
1280
|
+
([key]) => key.toLowerCase() === combined.book.toLowerCase()
|
|
1281
|
+
)
|
|
1282
|
+
if (sblEntry) {
|
|
1283
|
+
const { value, abbr } = sblEntry[1]
|
|
1284
|
+
combined.abbr = abbr ? `${value}. ${combined.scripture.cv}` : `${value} ${combined.scripture.cv}`
|
|
1285
|
+
} else {
|
|
1286
|
+
combined.abbr = `${combined.book} ${combined.scripture.cv}`
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1051
1289
|
return combined
|
|
1052
1290
|
}
|
|
1053
1291
|
|