mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-03-01 18:22:41 -08:00
fix: migrate tooling to bun and accept file path targets
This commit is contained in:
22
.github/workflows/ci.yml
vendored
22
.github/workflows/ci.yml
vendored
@@ -15,38 +15,32 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
|
|
||||||
- name: Setup pnpm
|
- name: Setup Bun
|
||||||
uses: pnpm/action-setup@v4
|
uses: oven-sh/setup-bun@v2
|
||||||
with:
|
with:
|
||||||
version: 9
|
bun-version: latest
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 22
|
node-version: 22
|
||||||
cache: pnpm
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install
|
run: bun install --frozen-lockfile
|
||||||
|
|
||||||
- name: Build (TypeScript check)
|
- name: Build (TypeScript check)
|
||||||
run: pnpm exec tsc --noEmit
|
run: bun run tsc --noEmit
|
||||||
|
|
||||||
- name: Build (bundle)
|
- name: Build (bundle)
|
||||||
run: pnpm run build
|
run: bun run build
|
||||||
|
|
||||||
- name: Test suite
|
- name: Test suite
|
||||||
run: pnpm test
|
run: bun run test
|
||||||
|
|
||||||
- name: Security audit
|
- name: Security audit
|
||||||
run: pnpm audit --audit-level=high
|
run: bun audit
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
|
|
||||||
- name: Setup Bun
|
|
||||||
uses: oven-sh/setup-bun@v2
|
|
||||||
with:
|
|
||||||
bun-version: latest
|
|
||||||
|
|
||||||
- name: Build Bun subminer wrapper
|
- name: Build Bun subminer wrapper
|
||||||
run: make build-launcher
|
run: make build-launcher
|
||||||
|
|
||||||
|
|||||||
30
.github/workflows/release.yml
vendored
30
.github/workflows/release.yml
vendored
@@ -17,28 +17,27 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
|
|
||||||
- name: Setup pnpm
|
- name: Setup Bun
|
||||||
uses: pnpm/action-setup@v4
|
uses: oven-sh/setup-bun@v2
|
||||||
with:
|
with:
|
||||||
version: 9
|
bun-version: latest
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: pnpm
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install
|
run: bun install --frozen-lockfile
|
||||||
|
|
||||||
- name: Build texthooker-ui
|
- name: Build texthooker-ui
|
||||||
run: |
|
run: |
|
||||||
cd vendor/texthooker-ui
|
cd vendor/texthooker-ui
|
||||||
pnpm install
|
bun install
|
||||||
pnpm build
|
bun run build
|
||||||
|
|
||||||
- name: Build AppImage
|
- name: Build AppImage
|
||||||
run: pnpm run build:appimage
|
run: bun run build:appimage
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
@@ -56,16 +55,15 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
|
|
||||||
- name: Setup pnpm
|
- name: Setup Bun
|
||||||
uses: pnpm/action-setup@v4
|
uses: oven-sh/setup-bun@v2
|
||||||
with:
|
with:
|
||||||
version: 9
|
bun-version: latest
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
cache: pnpm
|
|
||||||
|
|
||||||
- name: Validate macOS signing/notarization secrets
|
- name: Validate macOS signing/notarization secrets
|
||||||
run: |
|
run: |
|
||||||
@@ -88,16 +86,16 @@ jobs:
|
|||||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install
|
run: bun install --frozen-lockfile
|
||||||
|
|
||||||
- name: Build texthooker-ui
|
- name: Build texthooker-ui
|
||||||
run: |
|
run: |
|
||||||
cd vendor/texthooker-ui
|
cd vendor/texthooker-ui
|
||||||
pnpm install
|
bun install
|
||||||
pnpm build
|
bun run build
|
||||||
|
|
||||||
- name: Build signed + notarized macOS artifacts
|
- name: Build signed + notarized macOS artifacts
|
||||||
run: pnpm run build:mac
|
run: bun run build:mac
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
CSC_LINK: ${{ secrets.CSC_LINK }}
|
CSC_LINK: ${{ secrets.CSC_LINK }}
|
||||||
|
|||||||
70
Makefile
70
Makefile
@@ -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
|
APP_NAME := subminer
|
||||||
THEME_FILE := subminer.rasi
|
THEME_FILE := subminer.rasi
|
||||||
@@ -90,15 +90,15 @@ print-dirs:
|
|||||||
"MACOS_ZIP_SRC=$(MACOS_ZIP_SRC)"
|
"MACOS_ZIP_SRC=$(MACOS_ZIP_SRC)"
|
||||||
|
|
||||||
deps:
|
deps:
|
||||||
@$(MAKE) --no-print-directory ensure-pnpm
|
@$(MAKE) --no-print-directory ensure-bun
|
||||||
@pnpm install
|
@bun install
|
||||||
@pnpm -C vendor/texthooker-ui install
|
@cd vendor/texthooker-ui && bun install
|
||||||
|
|
||||||
ensure-pnpm:
|
ensure-bun:
|
||||||
@command -v pnpm >/dev/null 2>&1 || { printf '%s\n' "[ERROR] pnpm not found"; exit 1; }
|
@command -v bun >/dev/null 2>&1 || { printf '%s\n' "[ERROR] bun not found"; exit 1; }
|
||||||
|
|
||||||
pretty:
|
pretty:
|
||||||
@pnpm exec prettier --write 'src/**/*.ts'
|
@bunx prettier --write 'src/**/*.ts'
|
||||||
|
|
||||||
build:
|
build:
|
||||||
@printf '%s\n' "[INFO] Detected platform: $(PLATFORM)"
|
@printf '%s\n' "[INFO] Detected platform: $(PLATFORM)"
|
||||||
@@ -118,18 +118,18 @@ install:
|
|||||||
|
|
||||||
build-linux: deps
|
build-linux: deps
|
||||||
@printf '%s\n' "[INFO] Building Linux package (AppImage)"
|
@printf '%s\n' "[INFO] Building Linux package (AppImage)"
|
||||||
@pnpm -C vendor/texthooker-ui build
|
@cd vendor/texthooker-ui && bun run build
|
||||||
@pnpm run build:appimage
|
@bun run build:appimage
|
||||||
|
|
||||||
build-macos: deps
|
build-macos: deps
|
||||||
@printf '%s\n' "[INFO] Building macOS package (DMG + ZIP)"
|
@printf '%s\n' "[INFO] Building macOS package (DMG + ZIP)"
|
||||||
@pnpm -C vendor/texthooker-ui build
|
@cd vendor/texthooker-ui && bun run build
|
||||||
@pnpm run build:mac
|
@bun run build:mac
|
||||||
|
|
||||||
build-macos-unsigned: deps
|
build-macos-unsigned: deps
|
||||||
@printf '%s\n' "[INFO] Building macOS package (DMG + ZIP, unsigned)"
|
@printf '%s\n' "[INFO] Building macOS package (DMG + ZIP, unsigned)"
|
||||||
@pnpm -C vendor/texthooker-ui build
|
@cd vendor/texthooker-ui && bun run build
|
||||||
@pnpm run build:mac:unsigned
|
@bun run build:mac:unsigned
|
||||||
|
|
||||||
build-launcher:
|
build-launcher:
|
||||||
@printf '%s\n' "[INFO] Bundling launcher script"
|
@printf '%s\n' "[INFO] Bundling launcher script"
|
||||||
@@ -144,36 +144,36 @@ clean:
|
|||||||
@rm -f "$(BINDIR)/subminer" "$(BINDIR)/SubMiner.AppImage"
|
@rm -f "$(BINDIR)/subminer" "$(BINDIR)/SubMiner.AppImage"
|
||||||
@rm -rf dist release
|
@rm -rf dist release
|
||||||
|
|
||||||
generate-config: ensure-pnpm
|
generate-config: ensure-bun
|
||||||
@pnpm run build
|
@bun run build
|
||||||
@pnpm exec electron . --generate-config
|
@bun run electron . --generate-config
|
||||||
|
|
||||||
generate-example-config: ensure-pnpm
|
generate-example-config: ensure-bun
|
||||||
@pnpm run build
|
@bun run build
|
||||||
@pnpm run generate:config-example
|
@bun run generate:config-example
|
||||||
|
|
||||||
docs-dev: ensure-pnpm
|
docs-dev: ensure-bun
|
||||||
@pnpm run docs:dev
|
@bun run docs:dev
|
||||||
|
|
||||||
docs: ensure-pnpm
|
docs: ensure-bun
|
||||||
@pnpm run docs:build
|
@bun run docs:build
|
||||||
|
|
||||||
docs-preview: ensure-pnpm
|
docs-preview: ensure-bun
|
||||||
@pnpm run docs:preview
|
@bun run docs:preview
|
||||||
|
|
||||||
dev-start: ensure-pnpm
|
dev-start: ensure-bun
|
||||||
@pnpm run build
|
@bun run build
|
||||||
@pnpm exec electron . --start
|
@bun run electron . --start
|
||||||
|
|
||||||
dev-start-macos: ensure-pnpm
|
dev-start-macos: ensure-bun
|
||||||
@pnpm run build
|
@bun run build
|
||||||
@pnpm exec electron . --start --backend macos
|
@bun run electron . --start --backend macos
|
||||||
|
|
||||||
dev-toggle: ensure-pnpm
|
dev-toggle: ensure-bun
|
||||||
@pnpm exec electron . --toggle
|
@bun run electron . --toggle
|
||||||
|
|
||||||
dev-stop: ensure-pnpm
|
dev-stop: ensure-bun
|
||||||
@pnpm exec electron . --stop
|
@bun run electron . --stop
|
||||||
|
|
||||||
|
|
||||||
install-linux: build-launcher
|
install-linux: build-launcher
|
||||||
|
|||||||
@@ -46,7 +46,10 @@ The `subminer` wrapper uses a [Bun](https://bun.sh) shebang, so `bun` must be on
|
|||||||
```bash
|
```bash
|
||||||
git clone --recurse-submodules https://github.com/ksyasuda/SubMiner.git
|
git clone --recurse-submodules https://github.com/ksyasuda/SubMiner.git
|
||||||
cd SubMiner
|
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).
|
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
|
## Quick Start
|
||||||
|
|
||||||
1. Copy [`config.example.jsonc`](config.example.jsonc) to `~/.config/SubMiner/config.jsonc`
|
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:
|
2. Start mpv with IPC:
|
||||||
```bash
|
```bash
|
||||||
mpv --input-ipc-server=/tmp/subminer-socket video.mkv
|
mpv --input-ipc-server=/tmp/subminer-socket video.mkv
|
||||||
|
|||||||
@@ -299,7 +299,8 @@
|
|||||||
// ==========================================
|
// ==========================================
|
||||||
// Immersion Tracking
|
// Immersion Tracking
|
||||||
// Enable/disable 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": {
|
"immersionTracking": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ SubMiner.AppImage --generate-config --backup-overwrite
|
|||||||
- `--generate-config` writes a default JSONC config template.
|
- `--generate-config` writes a default JSONC config template.
|
||||||
- If the target file exists, SubMiner prompts to create a timestamped backup and overwrite.
|
- 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.
|
- 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.
|
- `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.
|
Invalid config values are handled with warn-and-fallback behavior: SubMiner logs the bad key/value and continues with the default for that option.
|
||||||
|
|||||||
@@ -3,8 +3,7 @@
|
|||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
- [Node.js](https://nodejs.org/) (LTS)
|
- [Node.js](https://nodejs.org/) (LTS)
|
||||||
- [pnpm](https://pnpm.io/)
|
- [Bun](https://bun.sh)
|
||||||
- [Bun](https://bun.sh) (for the `subminer` wrapper script)
|
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
@@ -13,15 +12,15 @@ git clone https://github.com/ksyasuda/SubMiner.git
|
|||||||
cd SubMiner
|
cd SubMiner
|
||||||
make deps
|
make deps
|
||||||
# or manually:
|
# or manually:
|
||||||
pnpm install
|
bun install
|
||||||
pnpm -C vendor/texthooker-ui install
|
bun --cwd vendor/texthooker-ui install
|
||||||
```
|
```
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# TypeScript compile (fast, for development)
|
# TypeScript compile (fast, for development)
|
||||||
pnpm run build
|
bun run build
|
||||||
|
|
||||||
# Full platform build (includes texthooker-ui + AppImage/DMG)
|
# Full platform build (includes texthooker-ui + AppImage/DMG)
|
||||||
make build
|
make build
|
||||||
@@ -35,16 +34,16 @@ make build-macos-unsigned # macOS DMG + ZIP (unsigned)
|
|||||||
## Running Locally
|
## Running Locally
|
||||||
|
|
||||||
```bash
|
```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
|
electron . --start --dev --log-level debug # equivalent Electron launch with verbose logging
|
||||||
```
|
```
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pnpm run test:config # Config schema and validation tests (build + run)
|
bun run test:config # Config schema and validation tests (build + run)
|
||||||
pnpm run test:core # Core service tests (~67 tests) (build + run)
|
bun run test:core # Core service tests (~67 tests) (build + run)
|
||||||
pnpm run test:subtitle # Subtitle pipeline 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`).
|
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:
|
For faster iteration while editing test code:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pnpm run build # one-time compile
|
bun run build # one-time compile
|
||||||
pnpm run test:config:dist # no rebuild
|
bun run test:config:dist # no rebuild
|
||||||
pnpm run test:core:dist # no rebuild
|
bun run test:core:dist # no rebuild
|
||||||
pnpm run test:subtitle:dist # no rebuild
|
bun run test:subtitle:dist # no rebuild
|
||||||
pnpm run test:fast # run all tests without rebuild (assumes build is already current)
|
bun run test:fast # run all tests without rebuild (assumes build is already current)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Config Generation
|
## Config Generation
|
||||||
@@ -67,7 +66,7 @@ make generate-config
|
|||||||
|
|
||||||
# Regenerate the repo's config.example.jsonc from centralized defaults
|
# Regenerate the repo's config.example.jsonc from centralized defaults
|
||||||
make generate-example-config
|
make generate-example-config
|
||||||
# or: pnpm run generate:config-example
|
# or: bun run generate:config-example
|
||||||
```
|
```
|
||||||
|
|
||||||
## Documentation Site
|
## Documentation Site
|
||||||
|
|||||||
@@ -82,9 +82,9 @@ brew install mpv mecab mecab-ipadic
|
|||||||
```bash
|
```bash
|
||||||
git clone https://github.com/ksyasuda/SubMiner.git
|
git clone https://github.com/ksyasuda/SubMiner.git
|
||||||
cd SubMiner
|
cd SubMiner
|
||||||
pnpm install
|
bun install
|
||||||
cd vendor/texthooker-ui && pnpm install && pnpm build && cd ../..
|
cd vendor/texthooker-ui && bun install && bun run build && cd ../..
|
||||||
pnpm run build:mac
|
bun run build:mac
|
||||||
```
|
```
|
||||||
|
|
||||||
The built app will be available in the `release` directory (`.dmg` and `.zip`).
|
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:
|
For unsigned local builds:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pnpm run build:mac:unsigned
|
bun run build:mac:unsigned
|
||||||
```
|
```
|
||||||
|
|
||||||
### Accessibility Permission
|
### Accessibility Permission
|
||||||
|
|||||||
@@ -58,4 +58,4 @@ Practical guidance:
|
|||||||
- Keep the JLPT bundle inside `vendor/yomitan-jlpt-vocab` to avoid network lookups.
|
- Keep the JLPT bundle inside `vendor/yomitan-jlpt-vocab` to avoid network lookups.
|
||||||
- Measure bundle size with:
|
- Measure bundle size with:
|
||||||
- `du -sh vendor/yomitan-jlpt-vocab`
|
- `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.
|
||||||
|
|||||||
@@ -46,26 +46,6 @@
|
|||||||
"level": "info"
|
"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
|
// AnkiConnect Integration
|
||||||
// Automatic Anki updates and media generation options.
|
// Automatic Anki updates and media generation options.
|
||||||
@@ -314,5 +294,28 @@
|
|||||||
"aac"
|
"aac"
|
||||||
],
|
],
|
||||||
"transcodeVideoCodec": "h264"
|
"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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -283,6 +283,54 @@ function parseBackend(value: string): Backend {
|
|||||||
fail(`Invalid backend: ${value} (must be auto, hyprland, x11, or macos)`);
|
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(
|
export function parseArgs(
|
||||||
argv: string[],
|
argv: string[],
|
||||||
scriptName: string,
|
scriptName: string,
|
||||||
@@ -402,27 +450,30 @@ export function parseArgs(
|
|||||||
let doctorLogLevel: string | null = null;
|
let doctorLogLevel: string | null = null;
|
||||||
let texthookerLogLevel: string | null = null;
|
let texthookerLogLevel: string | null = null;
|
||||||
|
|
||||||
const program = new Command();
|
const commandProgram = new Command();
|
||||||
program
|
commandProgram
|
||||||
.name(scriptName)
|
.name(scriptName)
|
||||||
.description("Launch MPV with SubMiner sentence mining overlay")
|
.description("Launch MPV with SubMiner sentence mining overlay")
|
||||||
.showHelpAfterError(true)
|
.showHelpAfterError(true)
|
||||||
.enablePositionalOptions()
|
.enablePositionalOptions()
|
||||||
.allowExcessArguments(false)
|
.allowExcessArguments(false)
|
||||||
.allowUnknownOption(false)
|
.allowUnknownOption(false)
|
||||||
.exitOverride()
|
.exitOverride();
|
||||||
.argument("[target]", "file, directory, or URL")
|
applyRootOptions(commandProgram);
|
||||||
.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");
|
|
||||||
|
|
||||||
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")
|
.command("jellyfin")
|
||||||
.alias("jf")
|
.alias("jf")
|
||||||
.description("Jellyfin workflows")
|
.description("Jellyfin workflows")
|
||||||
@@ -452,7 +503,7 @@ export function parseArgs(
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
program
|
commandProgram
|
||||||
.command("yt")
|
.command("yt")
|
||||||
.alias("youtube")
|
.alias("youtube")
|
||||||
.description("YouTube workflows")
|
.description("YouTube workflows")
|
||||||
@@ -483,7 +534,7 @@ export function parseArgs(
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
program
|
commandProgram
|
||||||
.command("doctor")
|
.command("doctor")
|
||||||
.description("Run dependency and environment checks")
|
.description("Run dependency and environment checks")
|
||||||
.option("--log-level <level>", "Log level")
|
.option("--log-level <level>", "Log level")
|
||||||
@@ -493,7 +544,7 @@ export function parseArgs(
|
|||||||
typeof options.logLevel === "string" ? options.logLevel : null;
|
typeof options.logLevel === "string" ? options.logLevel : null;
|
||||||
});
|
});
|
||||||
|
|
||||||
program
|
commandProgram
|
||||||
.command("config")
|
.command("config")
|
||||||
.description("Config helpers")
|
.description("Config helpers")
|
||||||
.argument("[action]", "path|show", "path")
|
.argument("[action]", "path|show", "path")
|
||||||
@@ -506,7 +557,7 @@ export function parseArgs(
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
program
|
commandProgram
|
||||||
.command("mpv")
|
.command("mpv")
|
||||||
.description("MPV helpers")
|
.description("MPV helpers")
|
||||||
.argument("[action]", "status|socket|idle", "status")
|
.argument("[action]", "status|socket|idle", "status")
|
||||||
@@ -519,7 +570,7 @@ export function parseArgs(
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
program
|
commandProgram
|
||||||
.command("texthooker")
|
.command("texthooker")
|
||||||
.description("Launch texthooker-only mode")
|
.description("Launch texthooker-only mode")
|
||||||
.option("--log-level <level>", "Log level")
|
.option("--log-level <level>", "Log level")
|
||||||
@@ -529,8 +580,9 @@ export function parseArgs(
|
|||||||
typeof options.logLevel === "string" ? options.logLevel : null;
|
typeof options.logLevel === "string" ? options.logLevel : null;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const selectedProgram = hasTopLevelCommand(argv) ? commandProgram : rootProgram;
|
||||||
try {
|
try {
|
||||||
program.parse(["node", scriptName, ...argv]);
|
selectedProgram.parse(["node", scriptName, ...argv]);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const commanderError = error as { code?: string; message?: string };
|
const commanderError = error as { code?: string; message?: string };
|
||||||
if (commanderError?.code === "commander.helpDisplayed") {
|
if (commanderError?.code === "commander.helpDisplayed") {
|
||||||
@@ -539,7 +591,7 @@ export function parseArgs(
|
|||||||
fail(commanderError?.message || String(error));
|
fail(commanderError?.message || String(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
const options = program.opts<Record<string, unknown>>();
|
const options = selectedProgram.opts<Record<string, unknown>>();
|
||||||
if (typeof options.backend === "string") {
|
if (typeof options.backend === "string") {
|
||||||
parsed.backend = parseBackend(options.backend);
|
parsed.backend = parseBackend(options.backend);
|
||||||
}
|
}
|
||||||
@@ -558,7 +610,7 @@ export function parseArgs(
|
|||||||
if (options.startOverlay === true) parsed.autoStartOverlay = true;
|
if (options.startOverlay === true) parsed.autoStartOverlay = true;
|
||||||
if (options.texthooker === false) parsed.useTexthooker = false;
|
if (options.texthooker === false) parsed.useTexthooker = false;
|
||||||
|
|
||||||
const rootTarget = program.processedArgs[0];
|
const rootTarget = rootProgram.processedArgs[0];
|
||||||
if (typeof rootTarget === "string" && rootTarget) {
|
if (typeof rootTarget === "string" && rootTarget) {
|
||||||
ensureTarget(rootTarget, parsed);
|
ensureTarget(rootTarget, parsed);
|
||||||
}
|
}
|
||||||
|
|||||||
27
package.json
27
package.json
@@ -2,13 +2,14 @@
|
|||||||
"name": "subminer",
|
"name": "subminer",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"description": "All-in-one sentence mining overlay with AnkiConnect and dictionary integration",
|
"description": "All-in-one sentence mining overlay with AnkiConnect and dictionary integration",
|
||||||
|
"packageManager": "bun@1.3.5",
|
||||||
"main": "dist/main.js",
|
"main": "dist/main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"get-frequency": "bun run scripts/get_frequency.ts --pretty --color-top-x 10000 --yomitan-user-data ~/.config/SubMiner --colorized-line",
|
"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",
|
"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": "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",
|
"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",
|
"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: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",
|
"docs:build": "VITE_EXTRA_EXTENSIONS=jsonc vitepress build docs",
|
||||||
@@ -16,20 +17,20 @@
|
|||||||
"test:config:dist": "node --test dist/config/config.test.js",
|
"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: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:subtitle:dist": "echo \"Subtitle tests are currently not configured\"",
|
||||||
"test": "pnpm run test:config && pnpm run test:core",
|
"test": "bun run test:config && bun run test:core",
|
||||||
"test:config": "pnpm run build && pnpm run test:config:dist",
|
"test:config": "bun run build && bun run test:config:dist",
|
||||||
"test:core": "pnpm run build && pnpm run test:core:dist",
|
"test:core": "bun run build && bun run test:core:dist",
|
||||||
"test:subtitle": "pnpm run build && pnpm run test:subtitle:dist",
|
"test:subtitle": "bun run build && bun run test:subtitle:dist",
|
||||||
"test:fast": "pnpm run test:config:dist && pnpm run test:core:dist",
|
"test:fast": "bun run test:config:dist && bun run test:core:dist",
|
||||||
"generate:config-example": "pnpm run build && node dist/generate-config-example.js",
|
"generate:config-example": "bun run build && node dist/generate-config-example.js",
|
||||||
"start": "pnpm run build && electron . --start",
|
"start": "bun run build && electron . --start",
|
||||||
"dev": "pnpm run build && electron . --start --dev",
|
"dev": "bun run build && electron . --start --dev",
|
||||||
"stop": "electron . --stop",
|
"stop": "electron . --stop",
|
||||||
"toggle": "electron . --toggle",
|
"toggle": "electron . --toggle",
|
||||||
"build:appimage": "pnpm run build && electron-builder --linux AppImage",
|
"build:appimage": "bun run build && electron-builder --linux AppImage",
|
||||||
"build:mac": "pnpm run build && electron-builder --mac dmg zip",
|
"build:mac": "bun 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: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": "pnpm run build && electron-builder --mac zip"
|
"build:mac:zip": "bun run build && electron-builder --mac zip"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"anki",
|
"anki",
|
||||||
|
|||||||
5586
pnpm-lock.yaml
generated
5586
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -18,7 +18,7 @@ Watch for in-flight refactors. If repo changes introduced drift, update only:
|
|||||||
- README.md
|
- README.md
|
||||||
- docs/**/*.md
|
- docs/**/*.md
|
||||||
- config.example.jsonc
|
- 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)
|
- package.json scripts/config references (only if needed)
|
||||||
|
|
||||||
Rules:
|
Rules:
|
||||||
|
|||||||
@@ -382,7 +382,7 @@ function parseCliArgs(argv: string[]): CliOptions {
|
|||||||
|
|
||||||
function printUsage(): void {
|
function printUsage(): void {
|
||||||
process.stdout.write(`Usage:
|
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.
|
--pretty Pretty-print JSON output.
|
||||||
--diagnostics Include merged-frequency lookup-term details.
|
--diagnostics Include merged-frequency lookup-term details.
|
||||||
|
|||||||
@@ -233,4 +233,4 @@ echo " 2. socket.ts: Skip emitting empty sentences"
|
|||||||
echo " 3. app.css: Apply SubMiner default styling (without !important)"
|
echo " 3. app.css: Apply SubMiner default styling (without !important)"
|
||||||
echo " 4. stores.ts: Update default settings for title/whitespace/animation/reconnect"
|
echo " 4. stores.ts: Update default settings for title/whitespace/animation/reconnect"
|
||||||
echo ""
|
echo ""
|
||||||
echo "To rebuild: cd vendor/texthooker-ui && pnpm build"
|
echo "To rebuild: cd vendor/texthooker-ui && bun run build"
|
||||||
|
|||||||
@@ -258,4 +258,4 @@ echo " 1. permissions-util.js: Hardcoded permissions (Electron workaround)"
|
|||||||
echo " 2. options-schema.json: selectText=false, layoutAwareScan=false"
|
echo " 2. options-schema.json: selectText=false, layoutAwareScan=false"
|
||||||
echo " 3. popup.js: Added yomitan-popup-shown/hidden events"
|
echo " 3. popup.js: Added yomitan-popup-shown/hidden events"
|
||||||
echo ""
|
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'"
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ function parseCliArgs(argv: string[]): CliOptions {
|
|||||||
|
|
||||||
function printUsage(): void {
|
function printUsage(): void {
|
||||||
process.stdout.write(`Usage:
|
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.
|
--pretty Pretty-print JSON output.
|
||||||
--json Emit machine-readable JSON output.
|
--json Emit machine-readable JSON output.
|
||||||
|
|||||||
@@ -255,7 +255,7 @@ test("JLPT CSS rules use underline-only styling in renderer stylesheet", () => {
|
|||||||
const cssPath = fs.existsSync(distCssPath) ? distCssPath : srcCssPath;
|
const cssPath = fs.existsSync(distCssPath) ? distCssPath : srcCssPath;
|
||||||
if (!fs.existsSync(cssPath)) {
|
if (!fs.existsSync(cssPath)) {
|
||||||
assert.fail(
|
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.",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user