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.
Files changed (2) hide show
  1. package/lib/search.ts +56 -30
  2. 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])) matches = matches.filter((book) => !hasNum(book.name))
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
- let textSearchCache: { [key: string]: string } = {}
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.length) return []
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
- const matches = bibleSearch().slice(0, limit)
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
- textSearchCache[cacheId] = JSON.stringify(matches)
122
- return matches
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
- function bibleSearch() {
127
- const searchWords = searchValue.split(" ")
128
- const books = bookNumber === undefined ? bible.books : [bible.books[getBookIndex(bible, bookNumber)]]
141
+ const matches: VerseReference[] = []
142
+ for (const book of books) {
143
+ for (const chapter of book.chapters) {
144
+ const verses: number[] = []
129
145
 
130
- let matches: VerseReference[] = []
146
+ for (const verse of chapter.verses) {
147
+ const verseValue = getFormattedVerse(verse.text ?? "")
131
148
 
132
- for (let book of books) {
133
- for (let chapter of book.chapters) {
134
- let verses: number[] = []
149
+ // check if the full phrase exists in the verse
150
+ let isMatch = verseValue.includes(searchValue)
135
151
 
136
- for (let verse of chapter.verses) {
137
- const verseValue = formatText(verse.text || "")
152
+ // or check whether every search word exists somewhere in the verse
153
+ if (!isMatch) {
154
+ isMatch = true
138
155
 
139
- // check if the full verse, or one of the words contains the search value
140
- if (verseValue.includes(searchValue) || searchWords.every((word) => verseValue.includes(word))) {
141
- verses.push(verse.number)
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.length) {
146
- const reference = getVerseReferences(bible, { book: book.number, chapter: chapter.number, verses })
147
- matches.push(...reference)
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
- // return early if we have reached the limit
150
- if (matches.length >= limit) return matches
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 //
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "json-bible",
3
3
  "description": "Universal JSON Bible Format",
4
- "version": "1.1.5",
4
+ "version": "1.1.7",
5
5
  "main": "index.js",
6
6
  "type": "module",
7
7
  "scripts": {