diff --git a/docs-site/anilist-integration.md b/docs-site/anilist-integration.md index 89452397..444f60d2 100644 --- a/docs-site/anilist-integration.md +++ b/docs-site/anilist-integration.md @@ -4,7 +4,7 @@ SubMiner can sync your watch progress to [AniList](https://anilist.co) automatic AniList data also powers two additional features: [cover art](#cover-art) for the stats dashboard and the [Character Dictionary](/character-dictionary) for in-overlay name lookup. -[AniList](https://anilist.co) is a free website for tracking which anime you have watched. An **access token** is a private key SubMiner stores so it can update your list on your behalf — you approve it once during setup, and you never paste a password into SubMiner. +[AniList](https://anilist.co) is a free website for tracking which anime you have watched. An **access token** is a private key SubMiner stores so it can update your list on your behalf - you approve it once during setup, and you never paste a password into SubMiner. ## Setup diff --git a/docs-site/anki-integration.md b/docs-site/anki-integration.md index 8d43ad88..49f16ba3 100644 --- a/docs-site/anki-integration.md +++ b/docs-site/anki-integration.md @@ -6,7 +6,7 @@ This project is built primarily for [Kiku](https://kiku.youyoumu.my.id/) and [La ::: tip New to these terms? - **Anki** is the flashcard app where your study cards live. - **AnkiConnect** is a free add-on that lets other programs (like SubMiner) talk to Anki over a local connection. SubMiner needs it installed to add or edit cards. -- A **note type** (also called a "model") is the template that defines what a card looks like — for example the Kiku or Lapis templates many Japanese learners use. +- A **note type** (also called a "model") is the template that defines what a card looks like - for example the Kiku or Lapis templates many Japanese learners use. - A **field** is one labeled slot in that template, such as `Sentence`, `Expression`, or `Picture`. SubMiner fills these fields when it mines a card. ::: @@ -22,9 +22,9 @@ AnkiConnect listens on `http://127.0.0.1:8765` by default. If you changed the po When you add a word via Yomitan, SubMiner detects the new card and fills in the sentence, audio, image, and translation fields automatically. Two detection methods are available: -**Proxy mode** (default) — SubMiner runs a local *proxy*: a small middleman server that sits between Yomitan and Anki. Yomitan sends new cards to SubMiner, SubMiner enriches them, then passes them along to Anki. This makes enrichment instant. +**Proxy mode** (default) - SubMiner runs a local *proxy*: a small middleman server that sits between Yomitan and Anki. Yomitan sends new cards to SubMiner, SubMiner enriches them, then passes them along to Anki. This makes enrichment instant. -**Polling mode** (fallback, when the proxy is disabled) — SubMiner asks AnkiConnect every few seconds whether any new cards were added, then enriches them. Simpler setup, but with a short delay (~3 seconds). +**Polling mode** (fallback, when the proxy is disabled) - SubMiner asks AnkiConnect every few seconds whether any new cards were added, then enriches them. Simpler setup, but with a short delay (~3 seconds). Use proxy mode if you want immediate enrichment. Use polling mode if your Yomitan instance is external (browser-based) or you prefer minimal configuration. diff --git a/docs-site/architecture.md b/docs-site/architecture.md index b4671cd4..b9d5b4f4 100644 --- a/docs-site/architecture.md +++ b/docs-site/architecture.md @@ -34,7 +34,7 @@ plugin/ src/ ai/ # AI translation provider utilities (client, config) main-entry.ts # Background-mode bootstrap wrapper before loading main.js - main.ts # Entry point — delegates to runtime composers/domain modules + main.ts # Entry point - delegates to runtime composers/domain modules preload.ts # Electron preload bridge types.ts # Shared type definitions main/ # Main-process composition/runtime adapters @@ -226,17 +226,17 @@ Most runtime code follows a dependency-injection pattern: The composition root (`src/main.ts`) delegates to focused modules in `src/main/` and `src/main/runtime/composers/`: -- `startup.ts` — argv/env processing and bootstrap flow -- `app-lifecycle.ts` — Electron lifecycle event registration -- `startup-lifecycle.ts` — app-ready initialization sequence -- `state.ts` — centralized application runtime state container -- `ipc-runtime.ts` — IPC channel registration and handler wiring -- `cli-runtime.ts` — CLI command parsing and dispatch -- `overlay-runtime.ts` — overlay window selection and modal state management -- `subsync-runtime.ts` — subsync command orchestration -- `runtime/composers/anilist-tracking-composer.ts` — AniList media tracking/probe/retry wiring -- `runtime/composers/jellyfin-runtime-composer.ts` — Jellyfin config/client/playback/command/setup composition wiring -- `runtime/composers/mpv-runtime-composer.ts` — MPV event/factory/tokenizer/warmup wiring +- `startup.ts` - argv/env processing and bootstrap flow +- `app-lifecycle.ts` - Electron lifecycle event registration +- `startup-lifecycle.ts` - app-ready initialization sequence +- `state.ts` - centralized application runtime state container +- `ipc-runtime.ts` - IPC channel registration and handler wiring +- `cli-runtime.ts` - CLI command parsing and dispatch +- `overlay-runtime.ts` - overlay window selection and modal state management +- `subsync-runtime.ts` - subsync command orchestration +- `runtime/composers/anilist-tracking-composer.ts` - AniList media tracking/probe/retry wiring +- `runtime/composers/jellyfin-runtime-composer.ts` - Jellyfin config/client/playback/command/setup composition wiring +- `runtime/composers/mpv-runtime-composer.ts` - MPV event/factory/tokenizer/warmup wiring Composer modules share contract conventions via `src/main/runtime/composers/contracts.ts`: @@ -271,9 +271,9 @@ For domains migrated to reducer-style transitions (for example AniList token/que ## Playback Startup Flow -Before the app boots, something has to launch mpv, inject the plugin, and bring the overlay up. SubMiner-managed launches own this step — the `subminer` launcher, the app's own playback, and the packaged Windows shortcut all follow the same path. The launcher reads `config.jsonc`, spawns mpv with the IPC socket and the bundled plugin, and passes runtime settings as `--script-opts`. The plugin never reads a config file: the shipped `subminer.conf` is intentionally empty so command-line opts always win. +Before the app boots, something has to launch mpv, inject the plugin, and bring the overlay up. SubMiner-managed launches own this step - the `subminer` launcher, the app's own playback, and the packaged Windows shortcut all follow the same path. The launcher reads `config.jsonc`, spawns mpv with the IPC socket and the bundled plugin, and passes runtime settings as `--script-opts`. The plugin never reads a config file: the shipped `subminer.conf` is intentionally empty so command-line opts always win. -Once mpv is up, exactly one of two triggers brings up the overlay. On a first launch the plugin's `file-loaded` hook self-starts the app once the socket is ready (because the launcher injected `auto_start=yes`). When the app is already running — or for explicit `--start-overlay` and YouTube flows — the launcher instead attaches over the control socket and suppresses the plugin's auto-start, so the two never fire together. Both converge on the same app bring-up, which then runs the Program Lifecycle below. +Once mpv is up, exactly one of two triggers brings up the overlay. On a first launch the plugin's `file-loaded` hook self-starts the app once the socket is ready (because the launcher injected `auto_start=yes`). When the app is already running - or for explicit `--start-overlay` and YouTube flows - the launcher instead attaches over the control socket and suppresses the plugin's auto-start, so the two never fire together. Both converge on the same app bring-up, which then runs the Program Lifecycle below. ```mermaid flowchart TB diff --git a/docs-site/changelog.md b/docs-site/changelog.md index 7da31518..a92d2b10 100644 --- a/docs-site/changelog.md +++ b/docs-site/changelog.md @@ -6,7 +6,7 @@ - **Linux Overlay Stacking**: Fixed the overlay intermittently dropping behind mpv on KDE Plasma and other non-Hyprland/Sway Wayland sessions; restored subtitle hover, pause-on-hover, and Yomitan lookups on X11/XWayland; the overlay now correctly layers above/below mpv based on fullscreen state, yields to foreground windows (Settings, Yomitan, AniList, etc.), and avoids startup flashes and fullscreen transition glitches. - **Linux Overlay (Hyprland Lua)**: Fixed overlay placement on Hyprland 0.55+ when using a Lua-based config. -- **Manual Overlay Startup**: Fixed manual visible-overlay startup from mpv — now correctly attaches to playback, keeps the window bounds synced with mpv, and primes current subtitles before showing. +- **Manual Overlay Startup**: Fixed manual visible-overlay startup from mpv - now correctly attaches to playback, keeps the window bounds synced with mpv, and primes current subtitles before showing. - **Playlist Transitions**: Reused the warm overlay when mpv advances to the next playlist item, avoiding a redundant tokenization pause and preserving visible subtitles across tracks. - **macOS Overlay**: Fixed the visible subtitle overlay staying click-through after pause-until-ready releases playback; restored mpv focus after closing modal windows so subtitles and keybinds resume without clicking the player. - **Mouse Keybindings**: Fixed keybinding capture and runtime handling for mouse buttons, including side buttons like `MBTN_BACK` and `MBTN_FORWARD`. @@ -25,7 +25,7 @@ - Subsync now always opens the manual subtitle picker regardless of any previously set default mode - **N+1 Highlighting:** - N+1 highlighting now has its own dedicated `ankiConnect.nPlusOne.enabled` option, separate from known-word highlighting - - It is no longer enabled automatically when known-word highlighting is on — enable it explicitly to keep N+1 annotations + - It is no longer enabled automatically when known-word highlighting is on - enable it explicitly to keep N+1 annotations **Added** @@ -177,7 +177,7 @@ **Added** -- **Character Dictionary:** Added AniList-based character dictionary selection for resolving title mismatches — open it in-app with the new `Ctrl+Alt+A` shortcut or from the CLI with `subminer dictionary --candidates` / `--select`. Series-scoped overrides replace stale entries in the merged dictionary. +- **Character Dictionary:** Added AniList-based character dictionary selection for resolving title mismatches - open it in-app with the new `Ctrl+Alt+A` shortcut or from the CLI with `subminer dictionary --candidates` / `--select`. Series-scoped overrides replace stale entries in the merged dictionary. - **Primary Subtitle Bar:** Added a `V` shortcut and mpv plugin binding to toggle the primary subtitle bar without affecting mpv's native subtitle visibility. - **Texthooker:** Added `subminer texthooker -o` and a tray menu item to open the local texthooker page in the default browser. @@ -231,7 +231,7 @@ **Internal** - Replaced the changelog renderer with an AI polish pass that merges related fragments and writes user-facing release notes. `CHANGELOG.md` keeps internal items in a collapsed `
` block; GitHub release notes omit them entirely. -- Release CI no longer auto-builds pending `changes/*.md` fragments on tag. Tagging now fails fast if fragments remain — run `bun run changelog:build` (requires the `claude` CLI) and commit before tagging. +- Release CI no longer auto-builds pending `changes/*.md` fragments on tag. Tagging now fails fast if fragments remain - run `bun run changelog:build` (requires the `claude` CLI) and commit before tagging.
@@ -255,8 +255,8 @@ - Stats: Episode detail hides card events whose Anki notes have been deleted, instead of showing phantom mining activity. - Stats: Trend and watch-time charts share a unified theme with horizontal gridlines and larger ticks for legibility. - Stats: Overview, Library, Trends, Sessions, and Vocabulary now use generic "title" wording so YouTube videos and anime live comfortably side by side in the dashboard. -- Stats: Session timeline no longer plots seek-forward/seek-backward markers — they were too noisy on sessions with lots of rewinds. -- Stats: Replaced the "Library — Per Day" section on the Stats → Trends page with a "Library — Summary" section. The new section shows a top-10 watch-time leaderboard chart and a sortable per-title table (watch time, videos, sessions, cards, words, lookups, lookups/100w, date range), all scoped to the current date range selector. +- Stats: Session timeline no longer plots seek-forward/seek-backward markers - they were too noisy on sessions with lots of rewinds. +- Stats: Replaced the "Library - Per Day" section on the Stats → Trends page with a "Library - Summary" section. The new section shows a top-10 watch-time leaderboard chart and a sortable per-title table (watch time, videos, sessions, cards, words, lookups, lookups/100w, date range), all scoped to the current date range selector. **Fixed** diff --git a/docs-site/character-dictionary.md b/docs-site/character-dictionary.md index 0a5890d7..8dc20574 100644 --- a/docs-site/character-dictionary.md +++ b/docs-site/character-dictionary.md @@ -1,6 +1,6 @@ # Character Dictionary -SubMiner can build a Yomitan-compatible character dictionary from [AniList](https://anilist.co) metadata so that character names in subtitles are recognized, highlighted, and enrichable with context — portraits, roles, voice actors, and biographical detail — without leaving the overlay. (AniList is an online anime/manga database; SubMiner pulls each show's character list from it.) +SubMiner can build a Yomitan-compatible character dictionary from [AniList](https://anilist.co) metadata so that character names in subtitles are recognized, highlighted, and enrichable with context - portraits, roles, voice actors, and biographical detail - without leaving the overlay. (AniList is an online anime/manga database; SubMiner pulls each show's character list from it.) This is helpful because proper names rarely appear in normal dictionaries, so character names would otherwise be flagged as "unknown" words and clutter your mining. Recognizing them keeps your N+1 highlighting focused on real vocabulary. @@ -10,25 +10,25 @@ The dictionary is generated per-media, merged across your recently-watched title The feature has three stages: **snapshot**, **merge**, and **match**. -1. **Snapshot** — When you start watching a new title, SubMiner queries the AniList GraphQL API for the media's character list. Each character's names, reading, role, description, birthday, voice actors, and portrait are fetched and saved as a local JSON snapshot in `character-dictionaries/snapshots/anilist-{mediaId}.json`. Images are downloaded and base64-encoded into the snapshot. +1. **Snapshot** - When you start watching a new title, SubMiner queries the AniList GraphQL API for the media's character list. Each character's names, reading, role, description, birthday, voice actors, and portrait are fetched and saved as a local JSON snapshot in `character-dictionaries/snapshots/anilist-{mediaId}.json`. Images are downloaded and base64-encoded into the snapshot. -2. **Merge** — SubMiner maintains a most-recently-used list of media IDs (default: 3). Snapshots from those titles are merged into a single Yomitan ZIP — `character-dictionaries/merged.zip` — which is always named "SubMiner Character Dictionary" so Yomitan treats it as a single stable dictionary across rebuilds. +2. **Merge** - SubMiner maintains a most-recently-used list of media IDs (default: 3). Snapshots from those titles are merged into a single Yomitan ZIP - `character-dictionaries/merged.zip` - which is always named "SubMiner Character Dictionary" so Yomitan treats it as a single stable dictionary across rebuilds. -3. **Match** — During subtitle rendering, Yomitan scans subtitle text against all loaded dictionaries including the character dictionary. SubMiner only accepts character entries for the current AniList media when that media ID is known, then flags matching tokens with `isNameMatch` and highlights them in the overlay with a distinct color. +3. **Match** - During subtitle rendering, Yomitan scans subtitle text against all loaded dictionaries including the character dictionary. SubMiner only accepts character entries for the current AniList media when that media ID is known, then flags matching tokens with `isNameMatch` and highlights them in the overlay with a distinct color. ## Enabling the Feature Character dictionary sync is disabled by default. To turn it on: 1. Enable **Name Match** in Settings → Subtitle Style, or set `subtitleStyle.nameMatchEnabled: true` in your config. -2. Start watching — SubMiner queries AniList's public GraphQL API (no authentication required) and imports the merged dictionary into Yomitan automatically. +2. Start watching - SubMiner queries AniList's public GraphQL API (no authentication required) and imports the merged dictionary into Yomitan automatically. 3. Optionally enable **Name Match Images** (Settings → Subtitle Style) to show inline circular character portraits next to matched names in subtitles. ```jsonc { "subtitleStyle": { "nameMatchEnabled": true, - "nameMatchImagesEnabled": true, // optional — inline portraits + "nameMatchImagesEnabled": true, // optional - inline portraits }, } ``` @@ -38,7 +38,7 @@ The first sync for a media title takes a few seconds while character data and po ::: ::: info -AniList character data is fetched via public GraphQL queries — no account or access token is needed. AniList authentication is only required for the separate [watch-progress sync](/anilist-integration) feature. +AniList character data is fetched via public GraphQL queries - no account or access token is needed. AniList authentication is only required for the separate [watch-progress sync](/anilist-integration) feature. ::: ::: warning @@ -60,7 +60,7 @@ A single character produces many searchable terms so that names are recognized r - ア・リ・ス → アリス (combined), plus individual segments -**Honorific suffixes** — each base name is expanded with 15 common suffixes: +**Honorific suffixes** - each base name is expanded with 15 common suffixes: | Honorific | Reading | | --------- | ---------- | @@ -80,16 +80,16 @@ A single character produces many searchable terms so that names are recognized r | 社長 | しゃちょう | | 部長 | ぶちょう | -**Romanized names** — names stored in romaji on AniList are converted to kana aliases so they can match against Japanese subtitle text. +**Romanized names** - names stored in romaji on AniList are converted to kana aliases so they can match against Japanese subtitle text. -This means a character like "太郎" generates entries for 太郎, 太郎さん, 太郎先生, 太郎君, 太郎ちゃん, and so on — all with correct readings. +This means a character like "太郎" generates entries for 太郎, 太郎さん, 太郎先生, 太郎君, 太郎ちゃん, and so on - all with correct readings. ## Name Matching Name matching runs inside Yomitan's scanning pipeline during subtitle tokenization. 1. Yomitan receives subtitle text and scans for dictionary matches. -2. Entries from "SubMiner Character Dictionary" are checked with exact primary-source matching — the token must match the entry's `originalText` with `isPrimary: true` and `matchType: 'exact'`. +2. Entries from "SubMiner Character Dictionary" are checked with exact primary-source matching - the token must match the entry's `originalText` with `isPrimary: true` and `matchType: 'exact'`. 3. When the current AniList media ID is known, entries whose embedded media ID belongs to a different title are ignored for name matching and inline portraits. 4. Matched tokens are flagged `isNameMatch: true` and forwarded to the renderer. 5. If `subtitleStyle.nameMatchEnabled` is enabled, the renderer applies the name-match highlight color (default: `#f5bde6`). @@ -111,7 +111,7 @@ Name matches are visually distinct from [N+1 targeting, frequency highlighting, When `subtitleStyle.nameMatchImagesEnabled` is enabled, SubMiner injects a small circular portrait image directly into the subtitle line next to each matched character name. -Portraits are sourced from the local snapshot — they are embedded at snapshot-generation time and served from the cached ZIP, so no network request happens during playback. Images are downloaded from AniList CDN once per character and stored in `character-dictionaries/img/`. +Portraits are sourced from the local snapshot - they are embedded at snapshot-generation time and served from the cached ZIP, so no network request happens during playback. Images are downloaded from AniList CDN once per character and stored in `character-dictionaries/img/`. If a snapshot was generated before portrait data was available (e.g. during an earlier version or offline sync), SubMiner detects the missing image data on the next media match and automatically refreshes the snapshot so portraits are included in the next merged dictionary build. @@ -123,20 +123,20 @@ If a snapshot was generated before portrait data was available (e.g. during an e The portrait size is controlled by the surrounding subtitle font size and renders as a circle clipped from the character's AniList cover image. ::: tip -Inline portraits help you quickly associate names with faces while building vocabulary — especially useful for shows with large casts where you're still learning who's who. +Inline portraits help you quickly associate names with faces while building vocabulary - especially useful for shows with large casts where you're still learning who's who. ::: ## Dictionary Entries Each character entry in the Yomitan dictionary includes structured content: -- **Name** — the matched Japanese name form -- **Known names** — generated non-honorific Japanese aliases for that character, excluding raw romanized/English aliases from lookup results -- **Role badge** — color-coded by role: main (score 100), supporting (90), side (80), background (70) -- **Portrait** — character image from AniList, embedded in the ZIP -- **Description** — biography text from AniList (collapsible) -- **Character information** — age, birthday, gender, blood type (collapsible) -- **Voiced by** — voice actor name and portrait (collapsible) +- **Name** - the matched Japanese name form +- **Known names** - generated non-honorific Japanese aliases for that character, excluding raw romanized/English aliases from lookup results +- **Role badge** - color-coded by role: main (score 100), supporting (90), side (80), background (70) +- **Portrait** - character image from AniList, embedded in the ZIP +- **Description** - biography text from AniList (collapsible) +- **Character information** - age, birthday, gender, blood type (collapsible) +- **Voiced by** - voice actor name and portrait (collapsible) The three collapsible sections can be configured to start open or closed: @@ -160,12 +160,12 @@ When `subtitleStyle.nameMatchEnabled` is `true`, SubMiner runs an auto-sync rout **Phases:** -1. **checking** — Is there already a cached snapshot for this media ID? -2. **generating** — No cache hit: fetch characters from AniList GraphQL, download portraits (250ms throttle between image requests), save snapshot JSON. -3. **syncing** — Add the media ID to the most-recently-used list. Evict old entries beyond `maxLoaded`. -4. **building** — Merge active snapshots into a single Yomitan ZIP. A SHA-1 revision hash is computed from the media set — if it matches the previously imported revision, the import is skipped. -5. **importing** — Push the ZIP into Yomitan. Waits for Yomitan mutation readiness (7-second timeout per operation). -6. **ready** — Dictionary is live. Character names will match on the next subtitle line. +1. **checking** - Is there already a cached snapshot for this media ID? +2. **generating** - No cache hit: fetch characters from AniList GraphQL, download portraits (250ms throttle between image requests), save snapshot JSON. +3. **syncing** - Add the media ID to the most-recently-used list. Evict old entries beyond `maxLoaded`. +4. **building** - Merge active snapshots into a single Yomitan ZIP. A SHA-1 revision hash is computed from the media set - if it matches the previously imported revision, the import is skipped. +5. **importing** - Push the ZIP into Yomitan. Waits for Yomitan mutation readiness (7-second timeout per operation). +6. **ready** - Dictionary is live. Character names will match on the next subtitle line. **State tracking** is persisted in `character-dictionaries/auto-sync-state.json`. AniList media matches are cached separately in `character-dictionaries/anilist-resolution-cache.json` so snapshot hits do not need another AniList search. @@ -274,9 +274,9 @@ merged.zip ## Reference Implementation -SubMiner's character dictionary builder is inspired by the [Japanese Character Name Dictionary](https://github.com/bee-san/Japanese_Character_Name_Dictionary) project — a standalone Rust web service that generates Yomitan character dictionaries from AniList and VNDB data. +SubMiner's character dictionary builder is inspired by the [Japanese Character Name Dictionary](https://github.com/bee-san/Japanese_Character_Name_Dictionary) project - a standalone Rust web service that generates Yomitan character dictionaries from AniList and VNDB data. -The reference implementation covers similar ground — name variant generation, honorific expansion, structured Yomitan content, portrait embedding — and additionally supports VNDB as a data source for visual novel characters. Key differences: +The reference implementation covers similar ground - name variant generation, honorific expansion, structured Yomitan content, portrait embedding - and additionally supports VNDB as a data source for visual novel characters. Key differences: | | SubMiner | Reference Implementation | | ---------------------- | -------------------------------------------- | ------------------------------------- | @@ -291,7 +291,7 @@ If you work with visual novels or want a standalone dictionary generator indepen ## Troubleshooting -- **Names not highlighting:** Confirm `subtitleStyle.nameMatchEnabled` is `true`. Check that the current media has an AniList entry — SubMiner needs a media ID to fetch characters. +- **Names not highlighting:** Confirm `subtitleStyle.nameMatchEnabled` is `true`. Check that the current media has an AniList entry - SubMiner needs a media ID to fetch characters. - **Inline portraits missing:** Confirm `subtitleStyle.nameMatchImagesEnabled` is `true`. On the next character dictionary sync, SubMiner refreshes current-version snapshots that do not contain usable cached character portrait data. Portraits still require AniList to return an image and the image download to succeed. - **Sync seems stuck:** The auto-sync debounces for 800ms after media changes and throttles image downloads at 250ms per image. Large casts (50+ characters) take longer. Check the status bar for the current sync phase. - **Wrong characters showing:** Open the in-app character dictionary manager (`Ctrl/Cmd+D`) to remove/reorder loaded titles, then use **Override** to correct the active AniList match. You can also run `--dictionary-candidates`, then save the correct media with `--dictionary-select --dictionary-anilist-id `. SubMiner ignores character entries from other loaded titles for subtitle name matching and inline portraits once the current media ID is known. @@ -300,6 +300,6 @@ If you work with visual novels or want a standalone dictionary generator indepen ## Related -- [Subtitle Annotations](/subtitle-annotations) — how name matches interact with N+1, frequency, and JLPT layers -- [AniList Integration](/anilist-integration) — watch-progress sync and AniList authentication (separate from character dictionary) -- [Configuration Reference](/configuration) — full config options +- [Subtitle Annotations](/subtitle-annotations) - how name matches interact with N+1, frequency, and JLPT layers +- [AniList Integration](/anilist-integration) - watch-progress sync and AniList authentication (separate from character dictionary) +- [Configuration Reference](/configuration) - full config options diff --git a/docs-site/configuration.md b/docs-site/configuration.md index 330ef3fb..558bb253 100644 --- a/docs-site/configuration.md +++ b/docs-site/configuration.md @@ -8,7 +8,7 @@ outline: [2, 3] import { withBase } from 'vitepress'; -SubMiner is configured through a single file (`config.jsonc`). Most settings are also editable from the in-app **Settings** window — you rarely need to edit the file by hand. This page is the full reference: it explains the Settings window, where the config file lives, and documents every option grouped by topic. New to SubMiner? The Quick Start below plus the [Settings window](#settings) cover everything most users need. +SubMiner is configured through a single file (`config.jsonc`). Most settings are also editable from the in-app **Settings** window - you rarely need to edit the file by hand. This page is the full reference: it explains the Settings window, where the config file lives, and documents every option grouped by topic. New to SubMiner? The Quick Start below plus the [Settings window](#settings) cover everything most users need. ## Quick Start @@ -39,7 +39,7 @@ Then customize as needed using the sections below. ## Settings -SubMiner includes a dedicated **Settings** window accessible from the tray menu, the app `--settings` flag, or launcher commands such as `subminer --settings` and `subminer settings`. It is the primary way to configure SubMiner — all changes are written directly to `config.jsonc`, so manual file editing is not required for most users. +SubMiner includes a dedicated **Settings** window accessible from the tray menu, the app `--settings` flag, or launcher commands such as `subminer --settings` and `subminer settings`. It is the primary way to configure SubMiner - all changes are written directly to `config.jsonc`, so manual file editing is not required for most users. The Settings window groups options by workflow instead of mirroring the raw config-file shape: @@ -223,7 +223,7 @@ Control whether the overlay automatically becomes visible when it connects to mp | -------------------- | --------------- | ----------------------------------------------------- | | `auto_start_overlay` | `true`, `false` | Auto-show overlay on mpv connection (default: `true`) | -When you launch through the SubMiner app or the `subminer` wrapper, the launcher reads these settings from this config and injects them into the mpv plugin at runtime — there is no separate plugin config file to edit. `auto_start_overlay` controls whether the visible overlay shows on auto-start. Two related keys in the `mpv` block tune startup behavior: `mpv.autoStartSubMiner` starts the overlay automatically when a file loads, and `mpv.pauseUntilOverlayReady` pauses mpv on visible auto-start until SubMiner signals overlay/tokenization readiness. +When you launch through the SubMiner app or the `subminer` wrapper, the launcher reads these settings from this config and injects them into the mpv plugin at runtime - there is no separate plugin config file to edit. `auto_start_overlay` controls whether the visible overlay shows on auto-start. Two related keys in the `mpv` block tune startup behavior: `mpv.autoStartSubMiner` starts the overlay automatically when a file loads, and `mpv.pauseUntilOverlayReady` pauses mpv on visible auto-start until SubMiner signals overlay/tokenization readiness. On Windows, packaged plugin installs also rewrite the plugin socket path to `\\.\pipe\subminer-socket`. @@ -526,9 +526,9 @@ The secondary-subtitle language list also acts as the fallback secondary-languag **Display modes:** -- **hidden** — Secondary subtitles not shown -- **visible** — Always visible at top of overlay -- **hover** — Only visible when hovering over the subtitle area (default) +- **hidden** - Secondary subtitles not shown +- **visible** - Always visible at top of overlay +- **hover** - Only visible when hovering over the subtitle area (default) **See `config.example.jsonc`** for additional secondary subtitle configuration options. @@ -1101,8 +1101,8 @@ Set `openBrowser` to `false` to only print the URL without opening a browser. Sync the active subtitle track from the overlay picker using `alass` or `ffsubsync`. Both are **optional external tools** that must be installed separately and available on your `PATH` (or configured via the path options below). -- [`alass`](https://github.com/kaegi/alass) — fast, audio-independent sync using a secondary subtitle as reference -- [`ffsubsync`](https://github.com/smacke/ffsubsync) — audio-based sync using the video file as reference +- [`alass`](https://github.com/kaegi/alass) - fast, audio-independent sync using a secondary subtitle as reference +- [`ffsubsync`](https://github.com/smacke/ffsubsync) - audio-based sync using the video file as reference ```json { @@ -1473,9 +1473,9 @@ If `mpv.profile` is configured and the launcher also receives `--profile`, SubMi Launch mode behavior: -- **`normal`** — mpv opens at its default window size with no extra flags. -- **`maximized`** — mpv starts maximized via `--window-maximized=yes`, keeping taskbar access. -- **`fullscreen`** — mpv starts in true fullscreen via `--fullscreen`. +- **`normal`** - mpv opens at its default window size with no extra flags. +- **`maximized`** - mpv starts maximized via `--window-maximized=yes`, keeping taskbar access. +- **`fullscreen`** - mpv starts in true fullscreen via `--fullscreen`. ### YouTube Playback Settings diff --git a/docs-site/demos.md b/docs-site/demos.md index 86dec154..cc4b5900 100644 --- a/docs-site/demos.md +++ b/docs-site/demos.md @@ -25,7 +25,7 @@ Mine vocabulary cards from Yomitan or directly from subtitle lines. SubMiner aut ## Subtitle Download & Sync -Search and download subtitles from Jimaku, then retime them with alass or ffsubsync — all from within SubMiner. +Search and download subtitles from Jimaku, then retime them with alass or ffsubsync - all from within SubMiner.