mirror of
https://github.com/bryanmanio/obsidian-lexophile.git
synced 2026-07-22 06:56:30 +00:00
The plugin used to call dictionaryapi.dev for every lookup, which was slow, rate-limited, and broke offline. It now ships a local SQLite file (~23MB, ~167K English entries from Wiktionary via the MattDodsonEnglish/english-dictionary project) and queries it locally via sql.js. Plumbing: - DictionaryStore loads the SQLite from <vault>/.obsidian/plugins/lexophile/dictionary.sqlite, downloads on demand from a configurable URL (default: a release asset on this repo), and exposes a synchronous lookup() that returns a WordEntry or null. - lookupWord is now an async wrapper around store.lookup that throws WordNotFoundError on null. DictionaryNotReadyError surfaces the pre-download state so modals can fail fast with a helpful message. - sql.js initialization moved to its own module (src/sqlite.ts) and reused by both the Kobo import and the new dictionary store. - AddWordModal / MassImportModal / KoboImportModal each take the store via constructor and guard against the not-ready state before starting work. - Settings tab gains a "Local dictionary" section with a status pill (Ready / Downloaded-not-loaded / Not downloaded), an entry count and size summary, a Download/Re-download button, and a configurable URL. - Removed the inter-request rate limit (was 350ms for API throttling) — local lookups are sub-millisecond, so a 0ms yield is enough to let the progress line repaint. Bundled dictionary data is hosted as a release asset on bryanmanio/obsidian-lexophile (tag: dictionary-v1). The plugin does not call dictionaryapi.dev at any point during normal use. The Chrome extension still uses the API for its own lookups — out of scope here. Build artifacts: - scripts/build-dictionary.py converts the upstream parquet (167,585 entries) to the compact SQLite schema we ship; documented for reproducibility. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
17 lines
768 B
TypeScript
17 lines
768 B
TypeScript
import initSqlJs, { type SqlJsStatic } from 'sql.js';
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
// @ts-ignore — esbuild's binary loader resolves this to a Uint8Array
|
|
import wasmBinary from 'sql.js/dist/sql-wasm.wasm';
|
|
|
|
let sqlJsPromise: Promise<SqlJsStatic> | null = null;
|
|
|
|
// Lazy-initialize sql.js so the WASM compile only happens when something
|
|
// actually needs the SQLite runtime (Kobo import, local dictionary lookup).
|
|
export function getSqlJs(): Promise<SqlJsStatic> {
|
|
if (!sqlJsPromise) {
|
|
// esbuild's binary loader hands us a Uint8Array; sql.js types want
|
|
// ArrayBuffer but accept either at runtime. Cast through unknown.
|
|
sqlJsPromise = initSqlJs({ wasmBinary: wasmBinary as unknown as ArrayBuffer });
|
|
}
|
|
return sqlJsPromise;
|
|
}
|