feat(dictionary): add Hachidori backend support

- Add backend selection, setup gating, Anki integration, and external host support
- Add launcher flags, documentation, packaging, and focused tests
- Open on-demand overlay modals on the first attempt
This commit is contained in:
2026-09-22 00:21:19 -07:00
parent 1508863dbb
commit d9fdc7ef6d
446 changed files with 109060 additions and 244 deletions
+47
View File
@@ -0,0 +1,47 @@
#!/usr/bin/env node
// Lint the prepared Firefox extension with the pinned web-ext.
// scripts/package-store.py builds the release XPI from the same file list.
// SPDX-License-Identifier: GPL-3.0-or-later
import { readFile } from "node:fs/promises";
import { spawnSync } from "node:child_process";
import { dirname, resolve } from "node:path";
import { fileURLToPath, pathToFileURL } from "node:url";
import {
DEFAULT_FIREFOX_EXTENSION,
prepareFirefoxExtension,
} from "./prepare-firefox.mjs";
const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
const TOOLING = resolve(ROOT, "test/tooling");
async function webExtBin() {
const packagePath = resolve(TOOLING, "node_modules/web-ext/package.json");
const packageJson = JSON.parse(await readFile(packagePath, "utf8"));
const entry = typeof packageJson.bin === "string" ? packageJson.bin : packageJson.bin?.["web-ext"];
if (typeof entry !== "string") throw new Error("The pinned web-ext executable is unavailable. Run npm ci --prefix test/tooling.");
return resolve(dirname(packagePath), entry);
}
export async function lintFirefoxExtension(output = DEFAULT_FIREFOX_EXTENSION) {
const source = await prepareFirefoxExtension(output);
const result = spawnSync(process.execPath, [await webExtBin(), "lint", "--source-dir", source], {
cwd: ROOT,
encoding: "utf8",
stdio: "inherit",
});
if (result.error) throw result.error;
if (result.status !== 0) throw new Error(`web-ext lint exited with status ${result.status}`);
return source;
}
if (process.argv[1] && import.meta.url === pathToFileURL(resolve(process.argv[1])).href) {
try {
if (process.argv.length > 2) throw new Error("usage: node scripts/lint-firefox.mjs");
await lintFirefoxExtension();
} catch (error) {
console.error(error instanceof Error ? error.message : String(error));
process.exitCode = 1;
}
}