Fix Greek word lookup: replace broken Bolls BDAG with OpenScriptures Strong's dictionary
The Bolls.life BDAG endpoint (/dictionary-definition/BDAG/) now returns empty arrays for all queries, and the search endpoint returns 404. Switched Greek lookups to the OpenScriptures Strong's Greek Dictionary served via jsDelivr CDN. The ~1.2 MB dictionary is fetched once on first lookup and cached in a useRef for the session, so subsequent lookups are instant. Hebrew lookups (Bolls BDBT) are unchanged and still working. Supports Strong's number lookup (G4102, 4102) and English word search (faith, apostle), returning lemma, transliteration, short definition, and an extended definition with derivation and KJV keyword list. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+2
-1
@@ -5,7 +5,8 @@
|
|||||||
"name": "study-app",
|
"name": "study-app",
|
||||||
"runtimeExecutable": "npm",
|
"runtimeExecutable": "npm",
|
||||||
"runtimeArgs": ["run", "dev"],
|
"runtimeArgs": ["run", "dev"],
|
||||||
"port": 5173
|
"port": 5173,
|
||||||
|
"autoPort": false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
+67
-24
@@ -892,36 +892,79 @@ const App = () => {
|
|||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchBollsDefinition = async (query) => {
|
// Module-level cache for the Greek Strong's dictionary (loaded once, ~1.2 MB)
|
||||||
const isGreek = isGreekStrongNumber(query);
|
const _greekDictRef = useRef(null);
|
||||||
const isHebrew = isHebrewStrongNumber(query);
|
const _greekDictLoadingRef = useRef(null);
|
||||||
|
|
||||||
if (isGreek || isHebrew) {
|
const loadGreekDict = async () => {
|
||||||
// The bolls.life API uses bare numbers in the URL (no G/H prefix).
|
if (_greekDictRef.current) return _greekDictRef.current;
|
||||||
// We filter returned results by topic prefix to get the right language.
|
if (_greekDictLoadingRef.current) return _greekDictLoadingRef.current;
|
||||||
const bare = query.trim().replace(/^[GgHh]/, '');
|
_greekDictLoadingRef.current = fetch(
|
||||||
const response = await fetch(`https://bolls.life/dictionary-definition/BDBT/${encodeURIComponent(bare)}/`);
|
'https://cdn.jsdelivr.net/gh/openscriptures/strongs@master/greek/strongs-greek-dictionary.js',
|
||||||
|
)
|
||||||
|
.then((res) => res.text())
|
||||||
|
.then((text) => {
|
||||||
|
const start = text.indexOf('{');
|
||||||
|
const end = text.lastIndexOf('}') + 1;
|
||||||
|
const dict = JSON.parse(text.slice(start, end));
|
||||||
|
_greekDictRef.current = dict;
|
||||||
|
_greekDictLoadingRef.current = null;
|
||||||
|
return dict;
|
||||||
|
});
|
||||||
|
return _greekDictLoadingRef.current;
|
||||||
|
};
|
||||||
|
|
||||||
|
const buildGreekDefinitionHtml = (key, entry) => {
|
||||||
|
let html = '';
|
||||||
|
if (entry.strongs_def) html += `<p>${entry.strongs_def.trim()}</p>`;
|
||||||
|
if (entry.derivation) html += `<p><em>Derivation:</em> ${entry.derivation}</p>`;
|
||||||
|
if (entry.kjv_def) html += `<p><em>KJV uses:</em> ${entry.kjv_def}</p>`;
|
||||||
|
return html;
|
||||||
|
};
|
||||||
|
|
||||||
|
const fetchBollsDefinition = async (query) => {
|
||||||
|
const encoded = encodeURIComponent(query.trim());
|
||||||
|
|
||||||
|
if (isHebrewStrongNumber(query)) {
|
||||||
|
const response = await fetch(`https://bolls.life/dictionary-definition/BDBT/${encoded}/`);
|
||||||
if (!response.ok) return null;
|
if (!response.ok) return null;
|
||||||
let defs;
|
let defs;
|
||||||
try { defs = await response.json(); } catch { return null; }
|
try { defs = await response.json(); } catch { return null; }
|
||||||
if (!Array.isArray(defs) || defs.length === 0) return null;
|
return Array.isArray(defs) && defs.length > 0 ? defs : null;
|
||||||
const prefix = isGreek ? 'G' : 'H';
|
|
||||||
const filtered = defs.filter((d) => String(d.topic ?? '').toUpperCase().startsWith(prefix));
|
|
||||||
return filtered.length > 0 ? filtered : defs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// English word — full-text search, filter to Greek entries only
|
// Greek — look up in the cached OpenScriptures Strong's dictionary.
|
||||||
const encoded = encodeURIComponent(query.trim());
|
const dict = await loadGreekDict();
|
||||||
try {
|
const key = isGreekStrongNumber(query) ? query.trim().toUpperCase() : null;
|
||||||
const searchResponse = await fetch(`https://bolls.life/search-dictionaries/BDBT/${encoded}/`);
|
|
||||||
if (searchResponse.ok) {
|
if (key) {
|
||||||
const results = await searchResponse.json();
|
const entry = dict[key];
|
||||||
const greekResults = Array.isArray(results)
|
if (!entry) return null;
|
||||||
? results.filter((r) => String(r.topic ?? '').startsWith('G'))
|
return [{
|
||||||
: [];
|
topic: key,
|
||||||
if (greekResults.length > 0) return [greekResults[0]];
|
lexeme: entry.lemma || '',
|
||||||
}
|
transliteration: entry.translit || '',
|
||||||
} catch { /* fall through */ }
|
short_definition: entry.kjv_def || '',
|
||||||
|
definition: buildGreekDefinitionHtml(key, entry),
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
// English word search — scan kjv_def and strongs_def for the query term.
|
||||||
|
const lowerQ = query.trim().toLowerCase();
|
||||||
|
const match = Object.entries(dict).find(([, entry]) =>
|
||||||
|
(entry.kjv_def || '').toLowerCase().split(/[,\s]+/).some((w) => w === lowerQ) ||
|
||||||
|
(entry.strongs_def || '').toLowerCase().includes(lowerQ),
|
||||||
|
);
|
||||||
|
if (match) {
|
||||||
|
const [matchKey, entry] = match;
|
||||||
|
return [{
|
||||||
|
topic: matchKey,
|
||||||
|
lexeme: entry.lemma || '',
|
||||||
|
transliteration: entry.translit || '',
|
||||||
|
short_definition: entry.kjv_def || '',
|
||||||
|
definition: buildGreekDefinitionHtml(matchKey, entry),
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user