fix: migrate tooling to bun and accept file path targets

This commit is contained in:
2026-02-17 20:39:06 -08:00
parent a531527e1f
commit 846b075206
20 changed files with 1620 additions and 5735 deletions

View File

@@ -15,38 +15,32 @@ jobs:
with:
submodules: true
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
version: 9
bun-version: latest
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- name: Install dependencies
run: pnpm install
run: bun install --frozen-lockfile
- name: Build (TypeScript check)
run: pnpm exec tsc --noEmit
run: bun run tsc --noEmit
- name: Build (bundle)
run: pnpm run build
run: bun run build
- name: Test suite
run: pnpm test
run: bun run test
- name: Security audit
run: pnpm audit --audit-level=high
run: bun audit
continue-on-error: true
- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Build Bun subminer wrapper
run: make build-launcher

View File

@@ -17,28 +17,27 @@ jobs:
with:
submodules: true
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
version: 9
bun-version: latest
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- name: Install dependencies
run: pnpm install
run: bun install --frozen-lockfile
- name: Build texthooker-ui
run: |
cd vendor/texthooker-ui
pnpm install
pnpm build
bun install
bun run build
- name: Build AppImage
run: pnpm run build:appimage
run: bun run build:appimage
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -56,16 +55,15 @@ jobs:
with:
submodules: true
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
version: 9
bun-version: latest
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- name: Validate macOS signing/notarization secrets
run: |
@@ -88,16 +86,16 @@ jobs:
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
- name: Install dependencies
run: pnpm install
run: bun install --frozen-lockfile
- name: Build texthooker-ui
run: |
cd vendor/texthooker-ui
pnpm install
pnpm build
bun install
bun run build
- name: Build signed + notarized macOS artifacts
run: pnpm run build:mac
run: bun run build:mac
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CSC_LINK: ${{ secrets.CSC_LINK }}

View File

@@ -1,4 +1,4 @@
.PHONY: help deps build build-launcher install build-linux build-macos build-macos-unsigned clean install-linux install-macos install-plugin uninstall uninstall-linux uninstall-macos print-dirs pretty ensure-pnpm generate-config generate-example-config docs-dev docs docs-preview dev-start dev-start-macos dev-toggle dev-stop
.PHONY: help deps build build-launcher install build-linux build-macos build-macos-unsigned clean install-linux install-macos install-plugin uninstall uninstall-linux uninstall-macos print-dirs pretty ensure-bun generate-config generate-example-config docs-dev docs docs-preview dev-start dev-start-macos dev-toggle dev-stop
APP_NAME := subminer
THEME_FILE := subminer.rasi
@@ -90,15 +90,15 @@ print-dirs:
"MACOS_ZIP_SRC=$(MACOS_ZIP_SRC)"
deps:
@$(MAKE) --no-print-directory ensure-pnpm
@pnpm install
@pnpm -C vendor/texthooker-ui install
@$(MAKE) --no-print-directory ensure-bun
@bun install
@cd vendor/texthooker-ui && bun install
ensure-pnpm:
@command -v pnpm >/dev/null 2>&1 || { printf '%s\n' "[ERROR] pnpm not found"; exit 1; }
ensure-bun:
@command -v bun >/dev/null 2>&1 || { printf '%s\n' "[ERROR] bun not found"; exit 1; }
pretty:
@pnpm exec prettier --write 'src/**/*.ts'
@bunx prettier --write 'src/**/*.ts'
build:
@printf '%s\n' "[INFO] Detected platform: $(PLATFORM)"
@@ -118,18 +118,18 @@ install:
build-linux: deps
@printf '%s\n' "[INFO] Building Linux package (AppImage)"
@pnpm -C vendor/texthooker-ui build
@pnpm run build:appimage
@cd vendor/texthooker-ui && bun run build
@bun run build:appimage
build-macos: deps
@printf '%s\n' "[INFO] Building macOS package (DMG + ZIP)"
@pnpm -C vendor/texthooker-ui build
@pnpm run build:mac
@cd vendor/texthooker-ui && bun run build
@bun run build:mac
build-macos-unsigned: deps
@printf '%s\n' "[INFO] Building macOS package (DMG + ZIP, unsigned)"
@pnpm -C vendor/texthooker-ui build
@pnpm run build:mac:unsigned
@cd vendor/texthooker-ui && bun run build
@bun run build:mac:unsigned
build-launcher:
@printf '%s\n' "[INFO] Bundling launcher script"
@@ -144,36 +144,36 @@ clean:
@rm -f "$(BINDIR)/subminer" "$(BINDIR)/SubMiner.AppImage"
@rm -rf dist release
generate-config: ensure-pnpm
@pnpm run build
@pnpm exec electron . --generate-config
generate-config: ensure-bun
@bun run build
@bun run electron . --generate-config
generate-example-config: ensure-pnpm
@pnpm run build
@pnpm run generate:config-example
generate-example-config: ensure-bun
@bun run build
@bun run generate:config-example
docs-dev: ensure-pnpm
@pnpm run docs:dev
docs-dev: ensure-bun
@bun run docs:dev
docs: ensure-pnpm
@pnpm run docs:build
docs: ensure-bun
@bun run docs:build
docs-preview: ensure-pnpm
@pnpm run docs:preview
docs-preview: ensure-bun
@bun run docs:preview
dev-start: ensure-pnpm
@pnpm run build
@pnpm exec electron . --start
dev-start: ensure-bun
@bun run build
@bun run electron . --start
dev-start-macos: ensure-pnpm
@pnpm run build
@pnpm exec electron . --start --backend macos
dev-start-macos: ensure-bun
@bun run build
@bun run electron . --start --backend macos
dev-toggle: ensure-pnpm
@pnpm exec electron . --toggle
dev-toggle: ensure-bun
@bun run electron . --toggle
dev-stop: ensure-pnpm
@pnpm exec electron . --stop
dev-stop: ensure-bun
@bun run electron . --stop
install-linux: build-launcher

View File

@@ -46,7 +46,10 @@ The `subminer` wrapper uses a [Bun](https://bun.sh) shebang, so `bun` must be on
```bash
git clone --recurse-submodules https://github.com/ksyasuda/SubMiner.git
cd SubMiner
make build && make install
bun install
cd vendor/texthooker-ui && bun install && cd ../..
make build
make install
```
For macOS builds and platform details, see the [installation docs](docs/installation.md).
@@ -54,6 +57,7 @@ For macOS builds and platform details, see the [installation docs](docs/installa
## Quick Start
1. Copy [`config.example.jsonc`](config.example.jsonc) to `~/.config/SubMiner/config.jsonc`
- Regenerate anytime from source: `make generate-example-config` or `bun run generate:config-example`
2. Start mpv with IPC:
```bash
mpv --input-ipc-server=/tmp/subminer-socket video.mkv

1419
bun.lock Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -299,7 +299,8 @@
// ==========================================
// Immersion Tracking
// Enable/disable immersion tracking.
// Set dbPath to override the default app data path.
// Set dbPath to override the default sqlite database location.
// Policy tuning is available for queue, flush, and retention values.
// ==========================================
"immersionTracking": {
"enabled": true,

View File

@@ -37,7 +37,7 @@ SubMiner.AppImage --generate-config --backup-overwrite
- `--generate-config` writes a default JSONC config template.
- If the target file exists, SubMiner prompts to create a timestamped backup and overwrite.
- In non-interactive shells, use `--backup-overwrite` to explicitly back up and overwrite.
- `pnpm run generate:config-example` regenerates both repository `config.example.jsonc` and docs-served `/config.example.jsonc` from the same centralized defaults.
- `bun run generate:config-example` regenerates both repository `config.example.jsonc` and docs-served `/config.example.jsonc` from the same centralized defaults.
- `make generate-config` builds and runs the same default-config generator via local Electron.
Invalid config values are handled with warn-and-fallback behavior: SubMiner logs the bad key/value and continues with the default for that option.

View File

@@ -3,8 +3,7 @@
## Prerequisites
- [Node.js](https://nodejs.org/) (LTS)
- [pnpm](https://pnpm.io/)
- [Bun](https://bun.sh) (for the `subminer` wrapper script)
- [Bun](https://bun.sh)
## Setup
@@ -13,15 +12,15 @@ git clone https://github.com/ksyasuda/SubMiner.git
cd SubMiner
make deps
# or manually:
pnpm install
pnpm -C vendor/texthooker-ui install
bun install
bun --cwd vendor/texthooker-ui install
```
## Building
```bash
# TypeScript compile (fast, for development)
pnpm run build
bun run build
# Full platform build (includes texthooker-ui + AppImage/DMG)
make build
@@ -35,16 +34,16 @@ make build-macos-unsigned # macOS DMG + ZIP (unsigned)
## Running Locally
```bash
pnpm run dev # builds + launches with --start --dev
bun run dev # builds + launches with --start --dev
electron . --start --dev --log-level debug # equivalent Electron launch with verbose logging
```
## Testing
```bash
pnpm run test:config # Config schema and validation tests (build + run)
pnpm run test:core # Core service tests (~67 tests) (build + run)
pnpm run test:subtitle # Subtitle pipeline tests (build + run)
bun run test:config # Config schema and validation tests (build + run)
bun run test:core # Core service tests (~67 tests) (build + run)
bun run test:subtitle # Subtitle pipeline tests (build + run)
```
All legacy test commands build first, then run via Node's built-in test runner (`node --test`).
@@ -52,11 +51,11 @@ All legacy test commands build first, then run via Node's built-in test runner (
For faster iteration while editing test code:
```bash
pnpm run build # one-time compile
pnpm run test:config:dist # no rebuild
pnpm run test:core:dist # no rebuild
pnpm run test:subtitle:dist # no rebuild
pnpm run test:fast # run all tests without rebuild (assumes build is already current)
bun run build # one-time compile
bun run test:config:dist # no rebuild
bun run test:core:dist # no rebuild
bun run test:subtitle:dist # no rebuild
bun run test:fast # run all tests without rebuild (assumes build is already current)
```
## Config Generation
@@ -67,7 +66,7 @@ make generate-config
# Regenerate the repo's config.example.jsonc from centralized defaults
make generate-example-config
# or: pnpm run generate:config-example
# or: bun run generate:config-example
```
## Documentation Site

View File

@@ -82,9 +82,9 @@ brew install mpv mecab mecab-ipadic
```bash
git clone https://github.com/ksyasuda/SubMiner.git
cd SubMiner
pnpm install
cd vendor/texthooker-ui && pnpm install && pnpm build && cd ../..
pnpm run build:mac
bun install
cd vendor/texthooker-ui && bun install && bun run build && cd ../..
bun run build:mac
```
The built app will be available in the `release` directory (`.dmg` and `.zip`).
@@ -92,7 +92,7 @@ The built app will be available in the `release` directory (`.dmg` and `.zip`).
For unsigned local builds:
```bash
pnpm run build:mac:unsigned
bun run build:mac:unsigned
```
### Accessibility Permission

View File

@@ -58,4 +58,4 @@ Practical guidance:
- Keep the JLPT bundle inside `vendor/yomitan-jlpt-vocab` to avoid network lookups.
- Measure bundle size with:
- `du -sh vendor/yomitan-jlpt-vocab`
- If the JLPT source is updated, re-run `pnpm run build:appimage` / packaging and confirm startup logs do not report missing banks.
- If the JLPT source is updated, re-run `bun run build:appimage` / packaging and confirm startup logs do not report missing banks.

View File

@@ -46,26 +46,6 @@
"level": "info"
},
// Immersion Tracking
// Persist mined subtitle/session telemetry for analytics.
// ==========================================
"immersionTracking": {
"enabled": true,
"dbPath": "",
"batchSize": 25,
"flushIntervalMs": 500,
"queueCap": 1000,
"payloadCapBytes": 256,
"maintenanceIntervalMs": 86400000,
"retention": {
"eventsDays": 7,
"telemetryDays": 30,
"dailyRollupsDays": 365,
"monthlyRollupsDays": 1825,
"vacuumIntervalDays": 7
}
},
// ==========================================
// AnkiConnect Integration
// Automatic Anki updates and media generation options.
@@ -314,5 +294,28 @@
"aac"
],
"transcodeVideoCodec": "h264"
},
// ==========================================
// Immersion Tracking
// Enable/disable immersion tracking.
// Set dbPath to override the default sqlite database location.
// Policy tuning is available for queue, flush, and retention values.
// ==========================================
"immersionTracking": {
"enabled": true,
"dbPath": "",
"batchSize": 25,
"flushIntervalMs": 500,
"queueCap": 1000,
"payloadCapBytes": 256,
"maintenanceIntervalMs": 86400000,
"retention": {
"eventsDays": 7,
"telemetryDays": 30,
"dailyRollupsDays": 365,
"monthlyRollupsDays": 1825,
"vacuumIntervalDays": 7
}
}
}

View File

@@ -283,6 +283,54 @@ function parseBackend(value: string): Backend {
fail(`Invalid backend: ${value} (must be auto, hyprland, x11, or macos)`);
}
function applyRootOptions(program: Command): void {
program
.option("-b, --backend <backend>", "Display backend")
.option("-d, --directory <dir>", "Directory to browse")
.option("-r, --recursive", "Search directories recursively")
.option("-p, --profile <profile>", "MPV profile")
.option("--start", "Explicitly start overlay")
.option("--log-level <level>", "Log level")
.option("-R, --rofi", "Use rofi picker")
.option("-S, --start-overlay", "Auto-start overlay")
.option("-T, --no-texthooker", "Disable texthooker-ui server");
}
function hasTopLevelCommand(argv: string[]): boolean {
const commandNames = new Set([
"jellyfin",
"jf",
"yt",
"youtube",
"doctor",
"config",
"mpv",
"texthooker",
"help",
]);
const optionsWithValue = new Set([
"-b",
"--backend",
"-d",
"--directory",
"-p",
"--profile",
"--log-level",
]);
for (let i = 0; i < argv.length; i += 1) {
const token = argv[i] || "";
if (token === "--") return false;
if (token.startsWith("-")) {
if (optionsWithValue.has(token)) {
i += 1;
}
continue;
}
return commandNames.has(token);
}
return false;
}
export function parseArgs(
argv: string[],
scriptName: string,
@@ -402,27 +450,30 @@ export function parseArgs(
let doctorLogLevel: string | null = null;
let texthookerLogLevel: string | null = null;
const program = new Command();
program
const commandProgram = new Command();
commandProgram
.name(scriptName)
.description("Launch MPV with SubMiner sentence mining overlay")
.showHelpAfterError(true)
.enablePositionalOptions()
.allowExcessArguments(false)
.allowUnknownOption(false)
.exitOverride()
.argument("[target]", "file, directory, or URL")
.option("-b, --backend <backend>", "Display backend")
.option("-d, --directory <dir>", "Directory to browse")
.option("-r, --recursive", "Search directories recursively")
.option("-p, --profile <profile>", "MPV profile")
.option("--start", "Explicitly start overlay")
.option("--log-level <level>", "Log level")
.option("-R, --rofi", "Use rofi picker")
.option("-S, --start-overlay", "Auto-start overlay")
.option("-T, --no-texthooker", "Disable texthooker-ui server");
.exitOverride();
applyRootOptions(commandProgram);
program
const rootProgram = new Command();
rootProgram
.name(scriptName)
.description("Launch MPV with SubMiner sentence mining overlay")
.usage("[options] [command] [target]")
.showHelpAfterError(true)
.allowExcessArguments(false)
.allowUnknownOption(false)
.exitOverride()
.argument("[target]", "file, directory, or URL");
applyRootOptions(rootProgram);
commandProgram
.command("jellyfin")
.alias("jf")
.description("Jellyfin workflows")
@@ -452,7 +503,7 @@ export function parseArgs(
};
});
program
commandProgram
.command("yt")
.alias("youtube")
.description("YouTube workflows")
@@ -483,7 +534,7 @@ export function parseArgs(
};
});
program
commandProgram
.command("doctor")
.description("Run dependency and environment checks")
.option("--log-level <level>", "Log level")
@@ -493,7 +544,7 @@ export function parseArgs(
typeof options.logLevel === "string" ? options.logLevel : null;
});
program
commandProgram
.command("config")
.description("Config helpers")
.argument("[action]", "path|show", "path")
@@ -506,7 +557,7 @@ export function parseArgs(
};
});
program
commandProgram
.command("mpv")
.description("MPV helpers")
.argument("[action]", "status|socket|idle", "status")
@@ -519,7 +570,7 @@ export function parseArgs(
};
});
program
commandProgram
.command("texthooker")
.description("Launch texthooker-only mode")
.option("--log-level <level>", "Log level")
@@ -529,8 +580,9 @@ export function parseArgs(
typeof options.logLevel === "string" ? options.logLevel : null;
});
const selectedProgram = hasTopLevelCommand(argv) ? commandProgram : rootProgram;
try {
program.parse(["node", scriptName, ...argv]);
selectedProgram.parse(["node", scriptName, ...argv]);
} catch (error) {
const commanderError = error as { code?: string; message?: string };
if (commanderError?.code === "commander.helpDisplayed") {
@@ -539,7 +591,7 @@ export function parseArgs(
fail(commanderError?.message || String(error));
}
const options = program.opts<Record<string, unknown>>();
const options = selectedProgram.opts<Record<string, unknown>>();
if (typeof options.backend === "string") {
parsed.backend = parseBackend(options.backend);
}
@@ -558,7 +610,7 @@ export function parseArgs(
if (options.startOverlay === true) parsed.autoStartOverlay = true;
if (options.texthooker === false) parsed.useTexthooker = false;
const rootTarget = program.processedArgs[0];
const rootTarget = rootProgram.processedArgs[0];
if (typeof rootTarget === "string" && rootTarget) {
ensureTarget(rootTarget, parsed);
}

View File

@@ -2,13 +2,14 @@
"name": "subminer",
"version": "0.1.0",
"description": "All-in-one sentence mining overlay with AnkiConnect and dictionary integration",
"packageManager": "bun@1.3.5",
"main": "dist/main.js",
"scripts": {
"get-frequency": "bun run scripts/get_frequency.ts --pretty --color-top-x 10000 --yomitan-user-data ~/.config/SubMiner --colorized-line",
"get-frequency:electron": "bun build scripts/get_frequency.ts --format=cjs --target=node --outfile dist/scripts/get_frequency.js --external electron && electron dist/scripts/get_frequency.js --pretty --color-top-x 10000 --yomitan-user-data ~/.config/SubMiner --colorized-line",
"test-yomitan-parser": "bun run scripts/test-yomitan-parser.ts",
"test-yomitan-parser:electron": "bun build scripts/test-yomitan-parser.ts --format=cjs --target=node --outfile dist/scripts/test-yomitan-parser.js --external electron && electron dist/scripts/test-yomitan-parser.js",
"build": "tsc && pnpm run build:renderer && cp src/renderer/index.html src/renderer/style.css dist/renderer/ && bash scripts/build-macos-helper.sh",
"build": "tsc && bun run build:renderer && cp src/renderer/index.html src/renderer/style.css dist/renderer/ && bash scripts/build-macos-helper.sh",
"build:renderer": "esbuild src/renderer/renderer.ts --bundle --platform=browser --format=esm --target=es2022 --outfile=dist/renderer/renderer.js --sourcemap",
"docs:dev": "VITE_EXTRA_EXTENSIONS=jsonc vitepress dev docs --host 0.0.0.0 --port 5173 --strictPort",
"docs:build": "VITE_EXTRA_EXTENSIONS=jsonc vitepress build docs",
@@ -16,20 +17,20 @@
"test:config:dist": "node --test dist/config/config.test.js",
"test:core:dist": "node --test dist/cli/args.test.js dist/cli/help.test.js dist/core/services/cli-command.test.js dist/core/services/ipc.test.js dist/core/services/field-grouping-overlay.test.js dist/core/services/numeric-shortcut-session.test.js dist/core/services/secondary-subtitle.test.js dist/core/services/mpv-render-metrics.test.js dist/core/services/overlay-content-measurement.test.js dist/core/services/mpv-control.test.js dist/core/services/mpv.test.js dist/core/services/runtime-options-ipc.test.js dist/core/services/runtime-config.test.js dist/core/services/tokenizer.test.js dist/core/services/subsync.test.js dist/core/services/overlay-bridge.test.js dist/core/services/overlay-manager.test.js dist/core/services/overlay-shortcut-handler.test.js dist/core/services/mining.test.js dist/core/services/anki-jimaku.test.js dist/core/services/jellyfin.test.js dist/core/services/jellyfin-remote.test.js dist/core/services/immersion-tracker-service.test.js dist/core/services/app-ready.test.js dist/core/services/startup-bootstrap.test.js dist/core/services/anilist/anilist-token-store.test.js dist/core/services/anilist/anilist-update-queue.test.js dist/subsync/utils.test.js dist/main/anilist-url-guard.test.js",
"test:subtitle:dist": "echo \"Subtitle tests are currently not configured\"",
"test": "pnpm run test:config && pnpm run test:core",
"test:config": "pnpm run build && pnpm run test:config:dist",
"test:core": "pnpm run build && pnpm run test:core:dist",
"test:subtitle": "pnpm run build && pnpm run test:subtitle:dist",
"test:fast": "pnpm run test:config:dist && pnpm run test:core:dist",
"generate:config-example": "pnpm run build && node dist/generate-config-example.js",
"start": "pnpm run build && electron . --start",
"dev": "pnpm run build && electron . --start --dev",
"test": "bun run test:config && bun run test:core",
"test:config": "bun run build && bun run test:config:dist",
"test:core": "bun run build && bun run test:core:dist",
"test:subtitle": "bun run build && bun run test:subtitle:dist",
"test:fast": "bun run test:config:dist && bun run test:core:dist",
"generate:config-example": "bun run build && node dist/generate-config-example.js",
"start": "bun run build && electron . --start",
"dev": "bun run build && electron . --start --dev",
"stop": "electron . --stop",
"toggle": "electron . --toggle",
"build:appimage": "pnpm run build && electron-builder --linux AppImage",
"build:mac": "pnpm run build && electron-builder --mac dmg zip",
"build:mac:unsigned": "pnpm run build && env -u APPLE_ID -u APPLE_APP_SPECIFIC_PASSWORD -u APPLE_TEAM_ID -u CSC_LINK -u CSC_KEY_PASSWORD CSC_IDENTITY_AUTO_DISCOVERY=false electron-builder --mac dmg zip",
"build:mac:zip": "pnpm run build && electron-builder --mac zip"
"build:appimage": "bun run build && electron-builder --linux AppImage",
"build:mac": "bun run build && electron-builder --mac dmg zip",
"build:mac:unsigned": "bun run build && env -u APPLE_ID -u APPLE_APP_SPECIFIC_PASSWORD -u APPLE_TEAM_ID -u CSC_LINK -u CSC_KEY_PASSWORD CSC_IDENTITY_AUTO_DISCOVERY=false electron-builder --mac dmg zip",
"build:mac:zip": "bun run build && electron-builder --mac zip"
},
"keywords": [
"anki",

5586
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -18,7 +18,7 @@ Watch for in-flight refactors. If repo changes introduced drift, update only:
- README.md
- docs/**/*.md
- config.example.jsonc
- docs/public/config.example.jsonc <-- generated automatically with make pnpm run generate:config-example
- docs/public/config.example.jsonc <-- generated automatically with make generate-example-config / bun run generate:config-example
- package.json scripts/config references (only if needed)
Rules:

View File

@@ -382,7 +382,7 @@ function parseCliArgs(argv: string[]): CliOptions {
function printUsage(): void {
process.stdout.write(`Usage:
pnpm run get-frequency [--pretty] [--diagnostics] [--dictionary <path>] [--mecab-command <path>] [--mecab-dictionary <path>] <text>
bun run get-frequency [--pretty] [--diagnostics] [--dictionary <path>] [--mecab-command <path>] [--mecab-dictionary <path>] <text>
--pretty Pretty-print JSON output.
--diagnostics Include merged-frequency lookup-term details.

View File

@@ -233,4 +233,4 @@ echo " 2. socket.ts: Skip emitting empty sentences"
echo " 3. app.css: Apply SubMiner default styling (without !important)"
echo " 4. stores.ts: Update default settings for title/whitespace/animation/reconnect"
echo ""
echo "To rebuild: cd vendor/texthooker-ui && pnpm build"
echo "To rebuild: cd vendor/texthooker-ui && bun run build"

View File

@@ -258,4 +258,4 @@ echo " 1. permissions-util.js: Hardcoded permissions (Electron workaround)"
echo " 2. options-schema.json: selectText=false, layoutAwareScan=false"
echo " 3. popup.js: Added yomitan-popup-shown/hidden events"
echo ""
echo "To verify: Run 'pnpm start --dev' and check for 'Yomitan extension loaded successfully'"
echo "To verify: Run 'bun run dev' and check for 'Yomitan extension loaded successfully'"

View File

@@ -213,7 +213,7 @@ function parseCliArgs(argv: string[]): CliOptions {
function printUsage(): void {
process.stdout.write(`Usage:
pnpm run test-yomitan-parser:electron -- [--pretty] [--json] [--yomitan-extension <path>] [--yomitan-user-data <path>] [--mecab-command <path>] [--mecab-dictionary <path>] <text>
bun run test-yomitan-parser:electron -- [--pretty] [--json] [--yomitan-extension <path>] [--yomitan-user-data <path>] [--mecab-command <path>] [--mecab-dictionary <path>] <text>
--pretty Pretty-print JSON output.
--json Emit machine-readable JSON output.

View File

@@ -255,7 +255,7 @@ test("JLPT CSS rules use underline-only styling in renderer stylesheet", () => {
const cssPath = fs.existsSync(distCssPath) ? distCssPath : srcCssPath;
if (!fs.existsSync(cssPath)) {
assert.fail(
"JLPT CSS file missing. Run `pnpm run build` first, or ensure src/renderer/style.css exists.",
"JLPT CSS file missing. Run `bun run build` first, or ensure src/renderer/style.css exists.",
);
}