json-bible 1.1.5 → 1.1.7
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/lib/search.ts +56 -30
- package/package.json +1 -1
package/lib/search.ts
CHANGED
|
@@ -90,9 +90,12 @@ export function _bookSearch(bible: Bible, searchValue: string) {
|
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
// remove books with numbers if no number at search start (John)
|
|
93
|
+
// remove books with numbers if no number at search start (John) - when there are matches
|
|
94
94
|
const hasNum = (str: string) => /\d/.test(str)
|
|
95
|
-
if (!hasNum(name[0])
|
|
95
|
+
if (!hasNum(name[0]) && name.length > 1) {
|
|
96
|
+
const noNumberMatches = matches.filter((book) => !hasNum(book.name))
|
|
97
|
+
if (noNumberMatches.length) matches = noNumberMatches
|
|
98
|
+
}
|
|
96
99
|
|
|
97
100
|
return matches
|
|
98
101
|
}
|
|
@@ -108,52 +111,75 @@ export function _bookSearch(bible: Bible, searchValue: string) {
|
|
|
108
111
|
|
|
109
112
|
// TEXT SEARCH //
|
|
110
113
|
|
|
111
|
-
|
|
114
|
+
const formattedTextCache = new Map<string, string>()
|
|
115
|
+
function getFormattedVerse(text: string) {
|
|
116
|
+
const cached = formattedTextCache.get(text)
|
|
117
|
+
if (cached !== undefined) return cached
|
|
118
|
+
|
|
119
|
+
const formatted = formatText(text)
|
|
120
|
+
formattedTextCache.set(text, formatted)
|
|
121
|
+
|
|
122
|
+
return formatted
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const textSearchCache = new Map<string, VerseReference[]>()
|
|
112
126
|
export function _textSearch(bible: Bible, searchValue: string, limit: number, bookNumber?: number) {
|
|
113
127
|
searchValue = formatText(searchValue).trim()
|
|
114
|
-
if (!searchValue
|
|
115
|
-
|
|
116
|
-
const cacheId = searchValue + limit + (bookNumber ?? "")
|
|
117
|
-
if (textSearchCache[cacheId]) return JSON.parse(textSearchCache[cacheId]) as VerseReference[]
|
|
128
|
+
if (!searchValue) return []
|
|
118
129
|
|
|
119
|
-
|
|
130
|
+
// cache results for identical searches
|
|
131
|
+
const cacheId = `${bible.name}|${searchValue}|${limit}|${bookNumber ?? ""}`
|
|
132
|
+
const cached = textSearchCache.get(cacheId)
|
|
133
|
+
if (cached) return cached
|
|
120
134
|
|
|
121
|
-
|
|
122
|
-
|
|
135
|
+
// split into individual words so we can match verses containing all words even if the exact phrase is absent
|
|
136
|
+
const searchWords = searchValue.split(/\s+/)
|
|
123
137
|
|
|
124
|
-
|
|
138
|
+
// search in a specific book or all books
|
|
139
|
+
const books = bookNumber === undefined ? bible.books : [bible.books[getBookIndex(bible, bookNumber)]]
|
|
125
140
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
const
|
|
141
|
+
const matches: VerseReference[] = []
|
|
142
|
+
for (const book of books) {
|
|
143
|
+
for (const chapter of book.chapters) {
|
|
144
|
+
const verses: number[] = []
|
|
129
145
|
|
|
130
|
-
|
|
146
|
+
for (const verse of chapter.verses) {
|
|
147
|
+
const verseValue = getFormattedVerse(verse.text ?? "")
|
|
131
148
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
let verses: number[] = []
|
|
149
|
+
// check if the full phrase exists in the verse
|
|
150
|
+
let isMatch = verseValue.includes(searchValue)
|
|
135
151
|
|
|
136
|
-
|
|
137
|
-
|
|
152
|
+
// or check whether every search word exists somewhere in the verse
|
|
153
|
+
if (!isMatch) {
|
|
154
|
+
isMatch = true
|
|
138
155
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
156
|
+
for (const word of searchWords) {
|
|
157
|
+
if (!verseValue.includes(word)) {
|
|
158
|
+
isMatch = false
|
|
159
|
+
break
|
|
160
|
+
}
|
|
142
161
|
}
|
|
143
162
|
}
|
|
144
163
|
|
|
145
|
-
if (verses.
|
|
146
|
-
|
|
147
|
-
|
|
164
|
+
if (isMatch) verses.push(verse.number)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (verses.length) {
|
|
168
|
+
const reference = getVerseReferences(bible, { book: book.number, chapter: chapter.number, verses })
|
|
169
|
+
matches.push(...reference)
|
|
148
170
|
|
|
149
|
-
|
|
150
|
-
|
|
171
|
+
// return early once we have enough results
|
|
172
|
+
if (matches.length >= limit) {
|
|
173
|
+
const result = matches.slice(0, limit)
|
|
174
|
+
textSearchCache.set(cacheId, result)
|
|
175
|
+
return result
|
|
151
176
|
}
|
|
152
177
|
}
|
|
153
178
|
}
|
|
154
|
-
|
|
155
|
-
return matches
|
|
156
179
|
}
|
|
180
|
+
|
|
181
|
+
textSearchCache.set(cacheId, matches)
|
|
182
|
+
return matches
|
|
157
183
|
}
|
|
158
184
|
|
|
159
185
|
// HELPERS //
|