From 889dc9c009bc0be552b4e35625e969caa108c410 Mon Sep 17 00:00:00 2001 From: sudacode Date: Thu, 28 May 2026 19:21:58 -0700 Subject: [PATCH] docs: reconcile docs-site with current config schema and defaults MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - sidebar: migrate flat props to css object (font-family, color, bg, custom vars) - frequencyDictionary.topX default: 1000 → 10000 - text-shadow default: updated to outline-style multi-shadow - anki: reset ai model/prompt, imageMaxWidth/Height, animatedMaxHeight to 0; isLapis defaults - troubleshooting: log default warn (not info), css["font-size"] usage - shortcuts: add W markWatchedKey; clarify keybindings vs built-in overlay actions - websocket: clarify all services off by default, fix enabled semantics - usage: --anilist → --anilist-setup - AGENTS.md: add Docs Upkeep trigger map, clarify CLAUDE.md symlink, expand PR notes --- AGENTS.md | 21 +++++++++- docs-site/configuration.md | 21 +++++----- docs-site/shortcuts.md | 3 +- docs-site/subtitle-annotations.md | 2 +- docs-site/subtitle-sidebar.md | 55 +++++++++++++++++---------- docs-site/troubleshooting.md | 10 +++-- docs-site/usage.md | 2 +- docs-site/websocket-texthooker-api.md | 8 ++-- 8 files changed, 78 insertions(+), 44 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 0a5fbdfd..c9212a52 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -13,6 +13,8 @@ Start here, then leave this file. `docs-site/` is user-facing. Do not treat it as the canonical internal source of truth. +`CLAUDE.md` is a symlink to this file — there is one project instruction file, not two. + ## Quick Start - Init workspace: `git submodule update --init --recursive` @@ -42,6 +44,20 @@ Start here, then leave this file. - Runtime-compat / dist-sensitive: `bun run test:runtime:compat` - Docs-only: `bun run docs:test`, then `bun run docs:build` +## Docs Upkeep + +- Docs ship with the change, not after. If a change alters behavior, defaults, flags, shortcuts, ports, or APIs, update the matching docs in the same PR. Touching code without reconciling its docs is an incomplete change. +- Source of truth for config defaults is the generated `config.example.jsonc`. Never write a default value into prose you didn't read from it — and don't restate the same default across multiple docs; cite/link to one place so there's a single thing to update. +- Trigger map (touch left → update right): + - `src/config/definitions/**` (schema/defaults/template) → `bun run generate:config-example`, then reconcile `docs-site/configuration.md` + any feature doc that cites that default + - shortcuts/keybindings (`shortcuts.*`, `keybindings`, `stats.*Key`, `subtitleSidebar.toggleKey`, controller bindings) → `docs-site/shortcuts.md` + - CLI flags/subcommands (`src/cli/args.ts`, `launcher/**`) → `docs-site/usage.md` + relevant integration doc + - feature behavior (anki / jellyfin / jimaku / anilist / youtube / immersion / stats / websocket / sidebar / character-dictionary / annotations) → matching `docs-site/.md` + - architecture / IPC / workflow / internal process → internal `docs/` (system of record) + - feature set / requirements / install flow → `README.md` +- Removing or renaming a config key: grep `docs-site/` and `docs/` for the old key and any value it documented; legacy/hidden keys (`LEGACY_HIDDEN_CONFIG_PATHS`) should not appear in user docs as current settings. +- Verify after doc edits: `bun run verify:config-example` (if config touched), `bun run docs:test`, `bun run docs:build`. + ## Sensitive Files - Launcher source of truth: `launcher/*.ts` @@ -52,7 +68,8 @@ Start here, then leave this file. ## Release / PR Notes -- User-visible PRs need one fragment in `changes/*.md` +- User-visible PRs need one fragment in `changes/*.md` — format and rules in [`changes/README.md`](./changes/README.md) (`type` + `area` keys required; apply the `skip-changelog` label to opt out) +- User-visible docs changes get a `type: docs` fragment - CI enforces `bun run changelog:lint` and `bun run changelog:pr-check` - PR review helpers: - `gh pr view --json number,title,url --jq '"PR #\\(.number): \\(.title)\\n\\(.url)"'` @@ -63,4 +80,4 @@ Start here, then leave this file. - Use Codex background for long jobs; tmux only when persistence/interaction is required - CI red: `gh run list/view`, rerun, fix, repeat until green - TypeScript: keep files small; follow existing patterns -- Swift: use workspace helper/daemon; validate `swift build` + tests +- Only Swift is the `scripts/get-mpv-window-macos.swift` helper (macOS mpv window detection); validate via `bun test scripts/get-mpv-window-macos.test.ts` diff --git a/docs-site/configuration.md b/docs-site/configuration.md index 57841149..118ebb61 100644 --- a/docs-site/configuration.md +++ b/docs-site/configuration.md @@ -339,7 +339,7 @@ See `config.example.jsonc` for detailed configuration options. "word-spacing": "0", "font-kerning": "normal", "text-rendering": "geometricPrecision", - "text-shadow": "0 2px 6px rgba(0,0,0,0.9), 0 0 12px rgba(0,0,0,0.55)", + "text-shadow": "-1px -1px 2px rgba(0,0,0,0.95), 1px -1px 2px rgba(0,0,0,0.95), -1px 1px 2px rgba(0,0,0,0.95), 1px 1px 2px rgba(0,0,0,0.95), 0 0 8px rgba(0,0,0,0.5)", "font-style": "normal", "backdrop-filter": "blur(6px)", "--subtitle-hover-token-color": "#f4dbd6", @@ -351,7 +351,7 @@ See `config.example.jsonc` for detailed configuration options. "color": "#cad3f5", "background-color": "transparent", "font-size": "24px", - "text-shadow": "0 2px 6px rgba(0,0,0,0.9), 0 0 12px rgba(0,0,0,0.55)" + "text-shadow": "-1px -1px 2px rgba(0,0,0,0.95), 1px -1px 2px rgba(0,0,0,0.95), -1px 1px 2px rgba(0,0,0,0.95), 1px 1px 2px rgba(0,0,0,0.95), 0 0 8px rgba(0,0,0,0.5)" } } } @@ -375,7 +375,7 @@ See `config.example.jsonc` for detailed configuration options. | `nPlusOneColor` | string | Hex color used for the single N+1 target subtitle highlight (default: `#c6a0f6`) | | `frequencyDictionary.enabled` | boolean | Enable frequency highlighting from dictionary lookups (`false` by default) | | `frequencyDictionary.sourcePath` | string | Path to a local frequency dictionary root. Leave empty or omit to use installed/default frequency-dictionary search paths. | -| `frequencyDictionary.topX` | number | Only color tokens whose frequency rank is `<= topX` (`1000` by default) | +| `frequencyDictionary.topX` | number | Only color tokens whose frequency rank is `<= topX` (`10000` by default) | | `frequencyDictionary.mode` | string | `"single"` or `"banded"` (`"single"` by default) | | `frequencyDictionary.matchMode` | string | `"headword"` or `"surface"` (`"headword"` by default) | | `frequencyDictionary.singleColor` | string | Color used for all highlighted tokens in single mode | @@ -897,8 +897,8 @@ Enable automatic Anki card creation and updates with media generation: }, "ai": { "enabled": false, - "model": "openai/gpt-4o-mini", - "systemPrompt": "Translate mined sentence text only." + "model": "", + "systemPrompt": "" }, "media": { "generateAudio": true, @@ -906,11 +906,11 @@ Enable automatic Anki card creation and updates with media generation: "imageType": "static", "imageFormat": "jpg", "imageQuality": 92, - "imageMaxWidth": 1280, - "imageMaxHeight": 720, + "imageMaxWidth": 0, + "imageMaxHeight": 0, "animatedFps": 10, "animatedMaxWidth": 640, - "animatedMaxHeight": 360, + "animatedMaxHeight": 0, "animatedCrf": 35, "audioPadding": 0, "fallbackDuration": 3, @@ -925,8 +925,8 @@ Enable automatic Anki card creation and updates with media generation: "pattern": "[SubMiner] %f (%t)" }, "isLapis": { - "enabled": true, - "sentenceCardModel": "Japanese sentences" + "enabled": false, + "sentenceCardModel": "Lapis" }, "isKiku": { "enabled": false, @@ -1133,7 +1133,6 @@ AniList integration is opt-in and disabled by default. Enable it to allow SubMin "enabled": true, "accessToken": "", "characterDictionary": { - "enabled": false, "maxLoaded": 3, "profileScope": "all", "collapsibleSections": { diff --git a/docs-site/shortcuts.md b/docs-site/shortcuts.md index 5952624f..0acc6883 100644 --- a/docs-site/shortcuts.md +++ b/docs-site/shortcuts.md @@ -67,7 +67,7 @@ These control playback and subtitle display. They require overlay window focus. | `Right-click + drag` | Reposition subtitles (on subtitle area) | | `Ctrl/Cmd+A` | Append clipboard video path to mpv playlist | -These keybindings can be overridden or disabled via the `keybindings` config array. The playlist browser opens a split overlay modal with sibling video files on the left and the live mpv playlist on the right. +The mpv-command rows above (`Space`, `F`, `J`, `Shift+J`, the seek/sub-seek/sub-delay keys, replay/play-next, and quit) are merged from the `keybindings` config array and can be remapped or disabled there. `V`, `Ctrl/Cmd+A`, and the mouse actions are built-in overlay behaviors and are not part of the `keybindings` array. The playlist browser opens a split overlay modal with sibling video files on the left and the live mpv playlist on the right. On macOS managed playback, SubMiner disables mpv's menu-bar shortcuts so configured SubMiner shortcuts like `Cmd+Shift+O` reach the mpv plugin instead of opening native mpv menu actions. @@ -86,6 +86,7 @@ Mouse-hover playback behavior is configured separately from shortcuts: `subtitle | `Ctrl+Alt+S` | Open subtitle sync (subsync) modal | `shortcuts.triggerSubsync` | | `\` | Toggle subtitle sidebar | `subtitleSidebar.toggleKey` | | `` ` `` | Toggle stats overlay | `stats.toggleKey` | +| `W` | Mark current video watched and advance to next in queue | `stats.markWatchedKey` | The stats toggle is handled inside the focused visible overlay window. It is configurable through the top-level `stats.toggleKey` setting and defaults to `Backquote`. diff --git a/docs-site/subtitle-annotations.md b/docs-site/subtitle-annotations.md index 396bda36..d819638e 100644 --- a/docs-site/subtitle-annotations.md +++ b/docs-site/subtitle-annotations.md @@ -74,7 +74,7 @@ SubMiner looks up each token's `frequencyRank` from `term_meta_bank_*.json` file | Option | Default | Description | | ------------------------------------------------ | ------------ | ---------------------------------------------------------------- | | `subtitleStyle.frequencyDictionary.enabled` | `false` | Enable frequency highlighting | -| `subtitleStyle.frequencyDictionary.topX` | `1000` | Max frequency rank to highlight | +| `subtitleStyle.frequencyDictionary.topX` | `10000` | Max frequency rank to highlight | | `subtitleStyle.frequencyDictionary.mode` | `"single"` | `"single"` or `"banded"` | | `subtitleStyle.frequencyDictionary.matchMode` | `"headword"` | `"headword"` or `"surface"` | | `subtitleStyle.frequencyDictionary.singleColor` | `#f5a97f` | Color for single mode | diff --git a/docs-site/subtitle-sidebar.md b/docs-site/subtitle-sidebar.md index d7b2458d..f25709c6 100644 --- a/docs-site/subtitle-sidebar.md +++ b/docs-site/subtitle-sidebar.md @@ -35,30 +35,45 @@ Enable and configure the sidebar under `subtitleSidebar` in your config file: "toggleKey": "Backslash", "pauseVideoOnHover": true, "autoScroll": true, - "fontFamily": "\"M PLUS 1\", \"Noto Sans CJK JP\", sans-serif", - "fontSize": 16 + "css": { + "font-family": "Hiragino Sans, M PLUS 1, Source Han Sans JP, Noto Sans CJK JP", + "color": "#cad3f5", + "background-color": "rgba(73, 77, 100, 0.9)", + "font-size": "16px", + "opacity": "0.95", + "--subtitle-sidebar-max-width": "420px", + "--subtitle-sidebar-timestamp-color": "#a5adcb", + "--subtitle-sidebar-active-line-color": "#f5bde6", + "--subtitle-sidebar-active-background-color": "rgba(138, 173, 244, 0.22)", + "--subtitle-sidebar-hover-background-color": "rgba(54, 58, 79, 0.84)" + } } } ``` -| Option | Type | Default | Description | -| --------------------------- | ------- | ------------ | -------------------------------------------------------------------------------------------------- | -| `enabled` | boolean | `true` | Enable subtitle sidebar support | -| `autoOpen` | boolean | `false` | Open the sidebar automatically on overlay startup | -| `layout` | string | `"overlay"` | `"overlay"` floats over mpv; `"embedded"` reserves right-side player space | -| `toggleKey` | string | `"Backslash"` | `KeyboardEvent.code` for the toggle shortcut | -| `pauseVideoOnHover` | boolean | `true` | Pause playback while hovering the cue list | -| `autoScroll` | boolean | `true` | Keep the active cue in view during playback | -| `maxWidth` | number | `420` | Maximum sidebar width in CSS pixels | -| `opacity` | number | `0.95` | Sidebar opacity between `0` and `1` | -| `backgroundColor` | string | `rgba(73, 77, 100, 0.9)` | Sidebar shell background color | -| `textColor` | string | `#cad3f5` | Default cue text color | -| `fontFamily` | string | `Hiragino Sans, M PLUS 1, Source Han Sans JP, Noto Sans CJK JP` | CSS `font-family` applied to cue text | -| `fontSize` | number | `16` | Base cue font size in CSS pixels | -| `timestampColor` | string | `#a5adcb` | Cue timestamp color | -| `activeLineColor` | string | `#f5bde6` | Active cue text color | -| `activeLineBackgroundColor` | string | `rgba(138, 173, 244, 0.22)` | Active cue background color | -| `hoverLineBackgroundColor` | string | `rgba(54, 58, 79, 0.84)` | Hovered cue background color | +Styling lives under the `css` object, using CSS property names and CSS custom properties (the same pattern as `subtitleStyle.css`). + +| Option | Type | Default | Description | +| ------------------- | ------- | ------------- | -------------------------------------------------------------------------- | +| `enabled` | boolean | `true` | Enable subtitle sidebar support | +| `autoOpen` | boolean | `false` | Open the sidebar automatically on overlay startup | +| `layout` | string | `"overlay"` | `"overlay"` floats over mpv; `"embedded"` reserves right-side player space | +| `toggleKey` | string | `"Backslash"` | `KeyboardEvent.code` for the toggle shortcut | +| `pauseVideoOnHover` | boolean | `true` | Pause playback while hovering the cue list | +| `autoScroll` | boolean | `true` | Keep the active cue in view during playback | + +| `css` property | Default | Description | +| ------------------------------------------- | --------------------------- | ---------------------------- | +| `font-family` | `Hiragino Sans, M PLUS 1, Source Han Sans JP, Noto Sans CJK JP` | Cue text font family | +| `color` | `#cad3f5` | Default cue text color | +| `background-color` | `rgba(73, 77, 100, 0.9)` | Sidebar shell background color | +| `font-size` | `16px` | Base cue font size | +| `opacity` | `0.95` | Sidebar opacity between `0` and `1` | +| `--subtitle-sidebar-max-width` | `420px` | Maximum sidebar width | +| `--subtitle-sidebar-timestamp-color` | `#a5adcb` | Cue timestamp color | +| `--subtitle-sidebar-active-line-color` | `#f5bde6` | Active cue text color | +| `--subtitle-sidebar-active-background-color`| `rgba(138, 173, 244, 0.22)` | Active cue background color | +| `--subtitle-sidebar-hover-background-color` | `rgba(54, 58, 79, 0.84)` | Hovered cue background color | ## Keyboard Shortcut diff --git a/docs-site/troubleshooting.md b/docs-site/troubleshooting.md index 10f06e6f..ec19a843 100644 --- a/docs-site/troubleshooting.md +++ b/docs-site/troubleshooting.md @@ -18,7 +18,7 @@ If the overlay never appears at all, see [Playback Startup Flow](./architecture# ## Logging and App Mode -- Default log output is `info`. +- Default log output is `warn`. - Use `--log-level` for more/less output. - Use `--dev`/`--debug` only to force app/dev mode (for example to get dev behavior from the overlay/app); they do not change log verbosity. - You can combine both, for example `SubMiner.AppImage --start --dev --log-level debug`, when you need maximum diagnostics. @@ -46,7 +46,7 @@ If the overlay never appears at all, see [Playback Startup Flow](./architecture# 2. Reduce rendering pressure: -- lower `subtitleStyle.fontSize` +- lower `subtitleStyle.css["font-size"]` - keep overlay complexity minimal during heavy CPU periods 3. Reduce media overhead: @@ -66,7 +66,9 @@ If the overlay never appears at all, see [Playback Startup Flow](./architecture# ```json { "subtitleStyle": { - "fontSize": 30, + "css": { + "font-size": "30px" + }, "enableJlpt": false, "frequencyDictionary": { "enabled": false @@ -95,7 +97,7 @@ If the overlay never appears at all, see [Playback Startup Flow](./architecture# - Confirm only one SubMiner instance is running. - Check whether bottlenecks are `ffmpeg`, `yt-dlp`, or sync tooling in system monitor. -- Use `info` logs by default; keep `debug` for targeted diagnosis. +- Keep the default `warn` level for normal use; raise to `info` or `debug` only for targeted diagnosis. - Reproduce once with `SubMiner.AppImage --start --log-level debug` and open DevTools (`y` then `d`) if freezes recur. **"Failed to parse MPV message"** diff --git a/docs-site/usage.md b/docs-site/usage.md index deab00ff..78d14586 100644 --- a/docs-site/usage.md +++ b/docs-site/usage.md @@ -116,7 +116,7 @@ subminer dictionary --candidates /path/to/file.mkv subminer dictionary --select 21355 /path/to/file.mkv subminer texthooker # Launch texthooker-only mode subminer texthooker -o # Launch texthooker and open it in your browser -subminer app --anilist # Pass args directly to SubMiner binary (example: AniList login flow) +subminer app --anilist-setup # Pass args directly to SubMiner binary (example: AniList login flow) # Direct packaged app control SubMiner.AppImage --background # Start in background (tray + IPC wait, minimal logs) diff --git a/docs-site/websocket-texthooker-api.md b/docs-site/websocket-texthooker-api.md index bae6b36b..18b8631d 100644 --- a/docs-site/websocket-texthooker-api.md +++ b/docs-site/websocket-texthooker-api.md @@ -24,7 +24,7 @@ This page documents those integration points and shows how to build custom consu ## Enable and Configure the Services -SubMiner's integration ports are configured in `config.jsonc`. +SubMiner's integration ports are configured in `config.jsonc`. All three services are **off by default** — the block below shows the values to set to turn them on. ```jsonc { @@ -45,9 +45,9 @@ SubMiner's integration ports are configured in `config.jsonc`. ### How startup behaves -- `websocket.enabled: "auto"` starts the basic subtitle websocket unless SubMiner detects the external `mpv_websocket` plugin. -- `annotationWebsocket` is independent from `websocket` and stays enabled unless you explicitly disable it. -- `texthooker.launchAtStartup` starts the local HTTP UI automatically. +- `websocket.enabled` defaults to `false`. Set it to `"auto"` to start the basic subtitle websocket unless SubMiner detects the external `mpv_websocket` plugin, or `true` to always start it. +- `annotationWebsocket.enabled` defaults to `false` and is independent from `websocket`. Set it to `true` to start the annotated stream. +- `texthooker.launchAtStartup` defaults to `false`. Set it to `true` to start the local HTTP UI automatically. - `texthooker.openBrowser` controls whether SubMiner opens the texthooker page in your browser when it starts. If you use the [mpv plugin](/mpv-plugin), it can also start a texthooker-only helper process. The launcher derives the plugin's texthooker setting from your SubMiner config (`texthooker.launchAtStartup`) and injects it at runtime — there is no plugin config file to edit.