@joewalker/scripture-ref 0.4.0 → 0.5.0
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/CHANGELOG.md +7 -0
- package/README.md +1 -1
- package/dist/book/books.d.ts +40 -17
- package/dist/book/books.js +147 -113
- package/dist/book/books.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/passage/bible-info.d.ts +21 -0
- package/dist/passage/bible-info.js +319 -421
- package/dist/passage/bible-info.js.map +1 -1
- package/dist/passage/verse.js +6 -2
- package/dist/passage/verse.js.map +1 -1
- package/package.json +1 -1
- /package/dist/book/{esv.json → data/ESV.json} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
# 0.5.0 (2026-05-11)
|
|
2
|
+
|
|
3
|
+
* Added a `Translation` class that loads a translation's text on demand via `Translation.create('ESV')` and exposes `getPassageText` and `search` as methods, paving the way for additional translations. The top-level `getPassageText` and `search` functions are retained as thin wrappers around an eagerly-loaded ESV translation and are now marked deprecated. The `BookName` and `VerseText` types are now exported from the public API, and the unused `Book` type has been removed.
|
|
4
|
+
* Expanded reference parsing to recognise a normalised registry of alternate book spellings and abbreviations (for example `Gen`, `1Cor`, `Song of Sol`), with case-insensitive and punctuation-insensitive lookup. Parsing now reports an explicit error when a name resolves to more than one book instead of silently picking the first match.
|
|
5
|
+
* Added a Damerau-Levenshtein fuzzy fallback when an exact book name lookup fails, so common typos such as `Genisis`, `Habakuk`, and `Revelaiton` now resolve to the intended book. The allowed edit distance scales with name length, and very short inputs stay unresolved to avoid colliding with the abbreviation table.
|
|
6
|
+
* Reduced the size of the published package by deriving verse ordinal lookup tables from the per-chapter verse counts at load time instead of shipping a pre-built prefix-sum table.
|
|
7
|
+
|
|
1
8
|
# 0.4.0 (2026-05-10)
|
|
2
9
|
|
|
3
10
|
* The package is now published to npm as `@joewalker/scripture-ref`, alongside the existing tagged releases on GitLab.
|
package/README.md
CHANGED
|
@@ -44,7 +44,7 @@ src/
|
|
|
44
44
|
__testutil__/index.ts test-only re-exports (parser internals)
|
|
45
45
|
book/
|
|
46
46
|
books.ts getPassageText, search
|
|
47
|
-
|
|
47
|
+
data/*.json Bible translations (about 10MB per file)
|
|
48
48
|
passage/
|
|
49
49
|
bible-info.ts structural helpers
|
|
50
50
|
verse.ts Verse and parser
|
package/dist/book/books.d.ts
CHANGED
|
@@ -1,15 +1,26 @@
|
|
|
1
1
|
import type { Passage } from '../passage/passage.js';
|
|
2
2
|
import type { Verse } from '../passage/verse.js';
|
|
3
|
-
type BookName = string;
|
|
4
|
-
type BibleText = Record<BookName, Chapters>;
|
|
5
|
-
type Chapters = ReadonlyArray<Verses>;
|
|
6
|
-
type Verses = ReadonlyArray<Words>;
|
|
7
|
-
type Words = ReadonlyArray<Word>;
|
|
8
|
-
type Word = [string, string] | [string];
|
|
9
3
|
/**
|
|
10
|
-
*
|
|
4
|
+
* VerseText returns the text for a verse in calls to `getPassageText(…)`
|
|
11
5
|
*/
|
|
12
|
-
export interface
|
|
6
|
+
export interface VerseText {
|
|
7
|
+
readonly verse: Verse;
|
|
8
|
+
readonly text: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Words might have Strong's numbers associated with them
|
|
12
|
+
*/
|
|
13
|
+
type WordData = [translation: string] | [translation: string, strongsNumber: string];
|
|
14
|
+
/** A verse is an array of words */
|
|
15
|
+
type VerseData = ReadonlyArray<WordData>;
|
|
16
|
+
/** A chapter is an array of verses */
|
|
17
|
+
type ChapterData = ReadonlyArray<VerseData>;
|
|
18
|
+
/** A chapter is an array of chapters */
|
|
19
|
+
type BookData = ReadonlyArray<ChapterData>;
|
|
20
|
+
/**
|
|
21
|
+
* A book is metadata plus a record of books to arrays of chapterdata
|
|
22
|
+
*/
|
|
23
|
+
interface TranslationData {
|
|
13
24
|
readonly version: string;
|
|
14
25
|
readonly versionName: string;
|
|
15
26
|
readonly meta: {
|
|
@@ -22,24 +33,36 @@ export interface Book {
|
|
|
22
33
|
readonly license: string | null;
|
|
23
34
|
readonly copyright: string;
|
|
24
35
|
};
|
|
36
|
+
readonly books: Record<string, BookData>;
|
|
37
|
+
}
|
|
38
|
+
declare const BOOK_NAME: Readonly<{
|
|
39
|
+
ESV: "./data/ESV.json";
|
|
40
|
+
}>;
|
|
41
|
+
export type BookName = keyof typeof BOOK_NAME;
|
|
42
|
+
/**
|
|
43
|
+
* The standard interface to the text of a Translation
|
|
44
|
+
*/
|
|
45
|
+
export declare class Translation {
|
|
46
|
+
#private;
|
|
47
|
+
static create(bookName: BookName): Promise<Translation>;
|
|
48
|
+
constructor(translationData: TranslationData);
|
|
25
49
|
/**
|
|
26
|
-
*
|
|
27
|
-
* Chapters = ReadonlyArray<Verses>
|
|
28
|
-
* Verses = ReadonlyArray<Words>
|
|
29
|
-
* Words = [EnglishWords, StrongsNumber];
|
|
50
|
+
* Look up the Bible text for a given passage
|
|
30
51
|
*/
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
52
|
+
getPassageText(passage: Passage): ReadonlyArray<VerseText>;
|
|
53
|
+
/**
|
|
54
|
+
* Produce the output text needed for a search term
|
|
55
|
+
*/
|
|
56
|
+
search(terms: string): string;
|
|
36
57
|
}
|
|
37
58
|
/**
|
|
38
59
|
* Look up the Bible text for a given passage
|
|
60
|
+
* @deprecated Use `Translation.create(bookId).getPassageText(passage)`
|
|
39
61
|
*/
|
|
40
62
|
export declare function getPassageText(bookId: string, passage: Passage): ReadonlyArray<VerseText>;
|
|
41
63
|
/**
|
|
42
64
|
* Produce the output text needed for a search term
|
|
65
|
+
* @deprecated Use `Translation.create(bookId).search(terms)`
|
|
43
66
|
*/
|
|
44
67
|
export declare function search(bookId: string, terms: string): string;
|
|
45
68
|
export {};
|
package/dist/book/books.js
CHANGED
|
@@ -1,62 +1,8 @@
|
|
|
1
1
|
import { chaptersInBook, verseOrdinal, versesInChapter, } from '../passage/bible-info.js';
|
|
2
2
|
import { PassageTally } from '../passage/passage-tally.js';
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
})).default;
|
|
7
|
-
// It's not clear why we need to cast to unknown before Book, I suspect some
|
|
8
|
-
// data inconsistency
|
|
9
|
-
const esvBibleText = esv.books;
|
|
10
|
-
/**
|
|
11
|
-
* Look up the Bible text for a given passage
|
|
12
|
-
*/
|
|
13
|
-
export function getPassageText(bookId, passage) {
|
|
14
|
-
if (bookId !== 'ESV') {
|
|
15
|
-
throw new Error(`Unknown book: '${bookId}'.`);
|
|
16
|
-
}
|
|
17
|
-
const output = [];
|
|
18
|
-
for (const range of passage.verseRanges()) {
|
|
19
|
-
for (const verse of range.verses()) {
|
|
20
|
-
output.push({ verse, text: renderVerseText(lookupWords(verse)) });
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
return output;
|
|
24
|
-
}
|
|
25
|
-
function lookupWords(verse) {
|
|
26
|
-
const bookName = indexLookup[verse.book];
|
|
27
|
-
return esvBibleText[bookName][verse.chapter - 1][verse.verse - 1];
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Join the per-word entries for a single verse into a display string,
|
|
31
|
-
* keeping attaching punctuation (.,;!?:) flush with the preceding word.
|
|
32
|
-
*/
|
|
33
|
-
function renderVerseText(words) {
|
|
34
|
-
let text = '';
|
|
35
|
-
for (const word of words) {
|
|
36
|
-
const head = word[0];
|
|
37
|
-
if (text.length === 0 || isAttachingPunctuation(head)) {
|
|
38
|
-
text += head;
|
|
39
|
-
}
|
|
40
|
-
else {
|
|
41
|
-
text += ` ${head}`;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return text;
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* True for punctuation that should attach to the previous word with no
|
|
48
|
-
* intervening space (sentence/clause punctuation).
|
|
49
|
-
*/
|
|
50
|
-
function isAttachingPunctuation(word) {
|
|
51
|
-
return (word.startsWith('.') ||
|
|
52
|
-
word.startsWith(',') ||
|
|
53
|
-
word.startsWith(';') ||
|
|
54
|
-
word.startsWith('!') ||
|
|
55
|
-
word.startsWith('?') ||
|
|
56
|
-
word.startsWith(':'));
|
|
57
|
-
}
|
|
58
|
-
const indexLookup = [
|
|
59
|
-
'',
|
|
3
|
+
/** A lookup table for book names used in the TranslationData.books record */
|
|
4
|
+
const BOOK_NAME_LOOKUP = [
|
|
5
|
+
'#ERROR#',
|
|
60
6
|
'Genesis',
|
|
61
7
|
'Exodus',
|
|
62
8
|
'Leviticus',
|
|
@@ -124,73 +70,161 @@ const indexLookup = [
|
|
|
124
70
|
'Jude',
|
|
125
71
|
'Revelation of John',
|
|
126
72
|
];
|
|
73
|
+
const BOOK_NAME = Object.freeze({
|
|
74
|
+
ESV: './data/ESV.json',
|
|
75
|
+
});
|
|
127
76
|
/**
|
|
128
|
-
*
|
|
77
|
+
* The standard interface to the text of a Translation
|
|
129
78
|
*/
|
|
130
|
-
|
|
131
|
-
|
|
79
|
+
export class Translation {
|
|
80
|
+
#translationData;
|
|
81
|
+
static async create(bookName) {
|
|
82
|
+
const translationData = (await import(BOOK_NAME[bookName], {
|
|
83
|
+
with: { type: 'json' },
|
|
84
|
+
}));
|
|
85
|
+
return new Translation(translationData.default);
|
|
86
|
+
}
|
|
87
|
+
constructor(translationData) {
|
|
88
|
+
this.#translationData = translationData;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Look up the Bible text for a given passage
|
|
92
|
+
*/
|
|
93
|
+
getPassageText(passage) {
|
|
94
|
+
const output = [];
|
|
95
|
+
for (const verse of passage.verses()) {
|
|
96
|
+
output.push({ verse, text: renderVerseText(this.#lookupWords(verse)) });
|
|
97
|
+
}
|
|
98
|
+
return output;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Produce the output text needed for a search term
|
|
102
|
+
*/
|
|
103
|
+
search(terms) {
|
|
104
|
+
const searchWords = terms
|
|
105
|
+
.split(' ')
|
|
106
|
+
.filter(word => word.trim().length > 0)
|
|
107
|
+
.map(word => {
|
|
108
|
+
const pattern = `\\b(${escapeRegExp(word)})\\b`;
|
|
109
|
+
return {
|
|
110
|
+
// The `g` flag mutates `lastIndex` across `.test()` calls and would
|
|
111
|
+
// make matches on later words start past the beginning of the string.
|
|
112
|
+
test: new RegExp(pattern, 'i'),
|
|
113
|
+
highlight: new RegExp(pattern, 'gi'),
|
|
114
|
+
};
|
|
115
|
+
});
|
|
116
|
+
if (searchWords.length === 0) {
|
|
117
|
+
return '\n\n';
|
|
118
|
+
}
|
|
119
|
+
const tally = new PassageTally();
|
|
120
|
+
const booksData = this.#translationData.books;
|
|
121
|
+
for (let book = 1; book < BOOK_NAME_LOOKUP.length; book++) {
|
|
122
|
+
const bookName = BOOK_NAME_LOOKUP[book];
|
|
123
|
+
const bookData = booksData[bookName];
|
|
124
|
+
const maxChapter = chaptersInBook(book);
|
|
125
|
+
for (let chapter = 1; chapter <= maxChapter; chapter++) {
|
|
126
|
+
const chapterData = bookData[chapter - 1];
|
|
127
|
+
const maxVerse = versesInChapter(book, chapter);
|
|
128
|
+
for (let verse = 1; verse <= maxVerse; verse++) {
|
|
129
|
+
const ordinal = verseOrdinal(book, chapter, verse);
|
|
130
|
+
const words = chapterData[verse - 1];
|
|
131
|
+
for (const searchWord of searchWords) {
|
|
132
|
+
wordLoop: for (const word of words) {
|
|
133
|
+
if (searchWord.test.test(word[0])) {
|
|
134
|
+
tally.incrementByOrdinal(ordinal, 1);
|
|
135
|
+
// Verses with multiple matches for a search term should not
|
|
136
|
+
// get extra weighting
|
|
137
|
+
break wordLoop;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return (
|
|
145
|
+
// eslint-disable-next-line prefer-template
|
|
146
|
+
'\n' +
|
|
147
|
+
tally
|
|
148
|
+
.results({ minScore: searchWords.length })
|
|
149
|
+
.map(verse => {
|
|
150
|
+
let text = renderVerseText(this.#lookupWords(verse));
|
|
151
|
+
for (const searchWord of searchWords) {
|
|
152
|
+
text = text.replace(searchWord.highlight, x => {
|
|
153
|
+
return `**${x}**`;
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
return `[${verse.toString()} → ${text}]`;
|
|
157
|
+
})
|
|
158
|
+
.join('\n') +
|
|
159
|
+
'\n');
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Convert a verse reference to stored verse data.
|
|
163
|
+
*/
|
|
164
|
+
#lookupWords(verse) {
|
|
165
|
+
const bookName = BOOK_NAME_LOOKUP[verse.book];
|
|
166
|
+
const booksData = this.#translationData.books;
|
|
167
|
+
return booksData[bookName][verse.chapter - 1][verse.verse - 1];
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
// https://github.com/jestjs/jest/issues/15000#issuecomment-2470602098
|
|
171
|
+
const esvTranslationData = (await import(/* webpackChunkName: "mobile/esv" */ './data/ESV.json', {
|
|
172
|
+
with: { type: 'json' },
|
|
173
|
+
})).default;
|
|
174
|
+
const esvTranslation = new Translation(esvTranslationData);
|
|
175
|
+
/**
|
|
176
|
+
* Look up the Bible text for a given passage
|
|
177
|
+
* @deprecated Use `Translation.create(bookId).getPassageText(passage)`
|
|
178
|
+
*/
|
|
179
|
+
export function getPassageText(bookId, passage) {
|
|
180
|
+
if (bookId !== 'ESV') {
|
|
181
|
+
throw new Error(`Unknown book: '${bookId}'.`);
|
|
182
|
+
}
|
|
183
|
+
return esvTranslation.getPassageText(passage);
|
|
132
184
|
}
|
|
133
185
|
/**
|
|
134
186
|
* Produce the output text needed for a search term
|
|
187
|
+
* @deprecated Use `Translation.create(bookId).search(terms)`
|
|
135
188
|
*/
|
|
136
189
|
export function search(bookId, terms) {
|
|
137
190
|
if (bookId !== 'ESV') {
|
|
138
191
|
throw new Error(`Unknown book: '${bookId}'.`);
|
|
139
192
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
const tally = new PassageTally();
|
|
156
|
-
for (let book = 1; book < indexLookup.length; book++) {
|
|
157
|
-
const bookName = indexLookup[book];
|
|
158
|
-
const bookData = esvBibleText[bookName];
|
|
159
|
-
const maxChapter = chaptersInBook(book);
|
|
160
|
-
for (let chapter = 1; chapter <= maxChapter; chapter++) {
|
|
161
|
-
const chapterData = bookData[chapter - 1];
|
|
162
|
-
const maxVerse = versesInChapter(book, chapter);
|
|
163
|
-
for (let verse = 1; verse <= maxVerse; verse++) {
|
|
164
|
-
const ordinal = verseOrdinal(book, chapter, verse);
|
|
165
|
-
const words = chapterData[verse - 1];
|
|
166
|
-
for (const searchWord of searchWords) {
|
|
167
|
-
wordLoop: for (const word of words) {
|
|
168
|
-
if (searchWord.test.test(word[0])) {
|
|
169
|
-
tally.incrementByOrdinal(ordinal, 1);
|
|
170
|
-
// Verses with multiple matches for a search term should not
|
|
171
|
-
// get extra weighting
|
|
172
|
-
break wordLoop;
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
}
|
|
193
|
+
return esvTranslation.search(terms);
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Join the per-word entries for a single verse into a display string,
|
|
197
|
+
* keeping attaching punctuation (.,;!?:) flush with the preceding word.
|
|
198
|
+
*/
|
|
199
|
+
function renderVerseText(words) {
|
|
200
|
+
let text = '';
|
|
201
|
+
for (const word of words) {
|
|
202
|
+
const head = word[0];
|
|
203
|
+
if (text.length === 0 || isAttachingPunctuation(head)) {
|
|
204
|
+
text += head;
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
text += ` ${head}`;
|
|
177
208
|
}
|
|
178
209
|
}
|
|
179
|
-
return
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
210
|
+
return text;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* True for punctuation that should attach to the previous word with no
|
|
214
|
+
* intervening space (sentence/clause punctuation).
|
|
215
|
+
*/
|
|
216
|
+
function isAttachingPunctuation(word) {
|
|
217
|
+
return (word.startsWith('.') ||
|
|
218
|
+
word.startsWith(',') ||
|
|
219
|
+
word.startsWith(';') ||
|
|
220
|
+
word.startsWith('!') ||
|
|
221
|
+
word.startsWith('?') ||
|
|
222
|
+
word.startsWith(':'));
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Escape a string so it can be safely embedded in a regular expression.
|
|
226
|
+
*/
|
|
227
|
+
function escapeRegExp(value) {
|
|
228
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
195
229
|
}
|
|
196
230
|
//# sourceMappingURL=books.js.map
|
package/dist/book/books.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"books.js","sourceRoot":"","sources":["../../src/book/books.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,YAAY,EACZ,eAAe,GAChB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"books.js","sourceRoot":"","sources":["../../src/book/books.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,6 @@ export type { Accuracy, VerseParseResult } from './passage/verse.js';
|
|
|
3
3
|
export { VerseRange } from './passage/verse-range.js';
|
|
4
4
|
export { Passage } from './passage/passage.js';
|
|
5
5
|
export { PassageTally } from './passage/passage-tally.js';
|
|
6
|
-
export { getPassageText, search } from './book/books.js';
|
|
7
|
-
export type {
|
|
6
|
+
export { getPassageText, search, Translation } from './book/books.js';
|
|
7
|
+
export type { BookName, VerseText } from './book/books.js';
|
|
8
8
|
export { findBookNumber, getShortName, getLongName, chaptersInBook, versesInChapter, versesInBible, chaptersInBible, booksInBible, verseOrdinal, decodeOrdinal, bookNames, shortBookNames, } from './passage/bible-info.js';
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,6 @@ export { Verse, ACCURACY } from './passage/verse.js';
|
|
|
2
2
|
export { VerseRange } from './passage/verse-range.js';
|
|
3
3
|
export { Passage } from './passage/passage.js';
|
|
4
4
|
export { PassageTally } from './passage/passage-tally.js';
|
|
5
|
-
export { getPassageText, search } from './book/books.js';
|
|
5
|
+
export { getPassageText, search, Translation } from './book/books.js';
|
|
6
6
|
export { findBookNumber, getShortName, getLongName, chaptersInBook, versesInChapter, versesInBible, chaptersInBible, booksInBible, verseOrdinal, decodeOrdinal, bookNames, shortBookNames, } from './passage/bible-info.js';
|
|
7
7
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAGtE,OAAO,EACL,cAAc,EACd,YAAY,EACZ,WAAW,EACX,cAAc,EACd,eAAe,EACf,aAAa,EACb,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,SAAS,EACT,cAAc,GACf,MAAM,yBAAyB,CAAC"}
|
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
export type BookLookupResult = {
|
|
2
|
+
readonly type: 'found';
|
|
3
|
+
readonly book: number;
|
|
4
|
+
} | {
|
|
5
|
+
readonly type: 'unknown';
|
|
6
|
+
} | {
|
|
7
|
+
readonly type: 'ambiguous';
|
|
8
|
+
readonly books: string;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Build the normalized book alias lookup table.
|
|
12
|
+
*
|
|
13
|
+
* Throws if the same alias is assigned to two different books, or if an alias
|
|
14
|
+
* is also listed in `ambiguousAliases` (the ambiguous branch in
|
|
15
|
+
* `_lookupBookNumber` would otherwise silently shadow the concrete entry).
|
|
16
|
+
*/
|
|
17
|
+
export declare function _buildBookLookup(aliasesByBook: ReadonlyArray<readonly [number, string]>, ambiguousAliases: ReadonlyMap<string, string>): ReadonlyMap<string, number>;
|
|
1
18
|
/**
|
|
2
19
|
* Find the (1-based) book number for a given string.
|
|
3
20
|
* e.g.:
|
|
@@ -6,6 +23,10 @@
|
|
|
6
23
|
* - findBookNumber('g') === undefined
|
|
7
24
|
*/
|
|
8
25
|
export declare function findBookNumber(name: string): number | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* Look up a normalized book name and report ambiguous matches separately.
|
|
28
|
+
*/
|
|
29
|
+
export declare function _lookupBookNumber(name: string): BookLookupResult;
|
|
9
30
|
/**
|
|
10
31
|
* What is the canonical short name for a book?
|
|
11
32
|
*/
|