Wire dynamic commentary and dictionary margin resources
This commit is contained in:
+138
-1
@@ -1,5 +1,5 @@
|
||||
import { invoke } from '@tauri-apps/api/core'
|
||||
import type { Footnote, LibraryState, StrongLink, Tag, Verse } from './types'
|
||||
import type { CommentaryEntry, DictionaryEntry, Footnote, LibraryState, StrongLink, Tag, Verse } from './types'
|
||||
|
||||
type TauriWindow = Window &
|
||||
typeof globalThis & {
|
||||
@@ -43,6 +43,36 @@ type ImportedStrongEntry = {
|
||||
kjv_definition?: string
|
||||
}
|
||||
|
||||
type ImportedCommentaryEntry = {
|
||||
id: string
|
||||
resource_id: string
|
||||
source: string
|
||||
book: string
|
||||
chapter: number
|
||||
verse_start: number
|
||||
verse_end: number
|
||||
reference: string
|
||||
title: string
|
||||
text: string
|
||||
}
|
||||
|
||||
type ImportedDictionaryEntry = {
|
||||
id: string
|
||||
resource_id: string
|
||||
term: string
|
||||
slug: string
|
||||
definitions: Array<{
|
||||
source: string
|
||||
source_name: string
|
||||
text: string
|
||||
}>
|
||||
scripture_refs: Array<{
|
||||
reference: string
|
||||
original: string
|
||||
}>
|
||||
sources: string[]
|
||||
}
|
||||
|
||||
type BrowserLexiconEntry = {
|
||||
lemma: string
|
||||
transliteration: string
|
||||
@@ -58,6 +88,8 @@ type BrowserStrongData = {
|
||||
let browserLibraryCache: Promise<Verse[]> | null = null
|
||||
let browserStrongDataCache: Promise<BrowserStrongData> | null = null
|
||||
let browserFootnotesCache: Promise<Map<string, Footnote[]>> | null = null
|
||||
let browserCommentaryCache: Promise<Map<string, CommentaryEntry[]>> | null = null
|
||||
let browserDictionaryCache: Promise<Map<string, DictionaryEntry>> | null = null
|
||||
const browserVerseSourceIds = new Map<number, string>()
|
||||
|
||||
const fallbackBrowserVerses: Verse[] = [
|
||||
@@ -291,6 +323,35 @@ export async function addTagToVerse(verseId: number, label: string, color: strin
|
||||
return verse
|
||||
}
|
||||
|
||||
export async function getCommentaryForVerse(verse: Verse): Promise<CommentaryEntry[]> {
|
||||
if (inTauri()) return []
|
||||
|
||||
const commentary = await loadBrowserCommentary()
|
||||
const chapterEntries = commentary.get(commentaryKey(verse.book, verse.chapter)) ?? []
|
||||
return chapterEntries.filter(
|
||||
(entry) => verse.verse >= entry.verseStart && verse.verse <= entry.verseEnd,
|
||||
)
|
||||
}
|
||||
|
||||
export async function getDictionaryEntriesForTerms(terms: string[]): Promise<DictionaryEntry[]> {
|
||||
if (inTauri()) return []
|
||||
|
||||
const dictionary = await loadBrowserDictionary()
|
||||
const seen = new Set<string>()
|
||||
const entries: DictionaryEntry[] = []
|
||||
|
||||
for (const term of terms) {
|
||||
const normalized = normalizeTerm(term)
|
||||
if (!normalized || seen.has(normalized)) continue
|
||||
const entry = dictionary.get(normalized)
|
||||
if (!entry) continue
|
||||
seen.add(normalized)
|
||||
entries.push(entry)
|
||||
}
|
||||
|
||||
return entries
|
||||
}
|
||||
|
||||
async function loadLibreBibleDevVerses(): Promise<Verse[]> {
|
||||
const importedVerses = await fetchJsonl<ImportedVerse>(
|
||||
`${libreBibleDevRoot}/kjv-eng-kjv2006/verses.jsonl`,
|
||||
@@ -313,6 +374,74 @@ async function loadLibreBibleDevVerses(): Promise<Verse[]> {
|
||||
})
|
||||
}
|
||||
|
||||
async function loadBrowserCommentary(): Promise<Map<string, CommentaryEntry[]>> {
|
||||
browserCommentaryCache ??= loadLibreBibleDevCommentary()
|
||||
|
||||
return browserCommentaryCache
|
||||
}
|
||||
|
||||
async function loadLibreBibleDevCommentary(): Promise<Map<string, CommentaryEntry[]>> {
|
||||
const importedEntries = await fetchJsonl<ImportedCommentaryEntry>(
|
||||
`${libreBibleDevRoot}/matthew-henry-concise-ccel/commentary.jsonl`,
|
||||
)
|
||||
const commentary = new Map<string, CommentaryEntry[]>()
|
||||
|
||||
for (const entry of importedEntries) {
|
||||
const mapped: CommentaryEntry = {
|
||||
id: entry.id,
|
||||
resourceId: entry.resource_id,
|
||||
source: entry.source,
|
||||
book: entry.book,
|
||||
chapter: entry.chapter,
|
||||
verseStart: entry.verse_start,
|
||||
verseEnd: entry.verse_end,
|
||||
reference: entry.reference,
|
||||
title: entry.title,
|
||||
text: entry.text,
|
||||
}
|
||||
const key = commentaryKey(mapped.book, mapped.chapter)
|
||||
const current = commentary.get(key) ?? []
|
||||
current.push(mapped)
|
||||
commentary.set(key, current)
|
||||
}
|
||||
|
||||
for (const entries of commentary.values()) {
|
||||
entries.sort((left, right) => left.verseStart - right.verseStart)
|
||||
}
|
||||
|
||||
return commentary
|
||||
}
|
||||
|
||||
async function loadBrowserDictionary(): Promise<Map<string, DictionaryEntry>> {
|
||||
browserDictionaryCache ??= loadLibreBibleDevDictionary()
|
||||
|
||||
return browserDictionaryCache
|
||||
}
|
||||
|
||||
async function loadLibreBibleDevDictionary(): Promise<Map<string, DictionaryEntry>> {
|
||||
const importedEntries = await fetchJsonl<ImportedDictionaryEntry>(
|
||||
`${libreBibleDevRoot}/easton-smith-dictionaries-neuu/entries.jsonl`,
|
||||
)
|
||||
return new Map(
|
||||
importedEntries.map((entry) => [
|
||||
normalizeTerm(entry.term),
|
||||
{
|
||||
id: entry.id,
|
||||
resourceId: entry.resource_id,
|
||||
term: entry.term,
|
||||
slug: entry.slug,
|
||||
definitions: entry.definitions.map((definition) => ({
|
||||
source: definition.source,
|
||||
sourceName: definition.source_name,
|
||||
text: definition.text,
|
||||
})),
|
||||
scriptureRefs: entry.scripture_refs,
|
||||
sources: entry.sources,
|
||||
},
|
||||
]),
|
||||
)
|
||||
}
|
||||
|
||||
async function loadBrowserFootnotes(): Promise<Map<string, Footnote[]>> {
|
||||
browserFootnotesCache ??= loadLibreBibleDevFootnotes()
|
||||
|
||||
@@ -402,6 +531,14 @@ function browserVerseKey(verse: Verse) {
|
||||
return browserVerseSourceIds.get(verse.id) ?? ''
|
||||
}
|
||||
|
||||
function commentaryKey(book: string, chapter: number) {
|
||||
return `${book}|${chapter}`
|
||||
}
|
||||
|
||||
function normalizeTerm(term: string) {
|
||||
return term.toLowerCase().replace(/[^a-z0-9\s'-]/g, '').trim()
|
||||
}
|
||||
|
||||
async function fetchJsonl<T>(url: string): Promise<T[]> {
|
||||
const response = await fetch(url)
|
||||
if (!response.ok) {
|
||||
|
||||
Reference in New Issue
Block a user