diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index b913428..6b2109c 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -5,6 +5,12 @@ export default { title: 'SubMiner Docs', description: 'All-in-one sentence mining overlay for MPV with AnkiConnect and dictionary integration', base, + head: [ + ['link', { rel: 'icon', href: '/favicon.ico', sizes: 'any' }], + ['link', { rel: 'icon', type: 'image/png', href: '/favicon-32x32.png', sizes: '32x32' }], + ['link', { rel: 'icon', type: 'image/png', href: '/favicon-16x16.png', sizes: '16x16' }], + ['link', { rel: 'apple-touch-icon', href: '/apple-touch-icon.png', sizes: '180x180' }], + ], appearance: 'dark', cleanUrls: true, lastUpdated: true, diff --git a/docs/anki-integration.md b/docs/anki-integration.md index 850a5f1..797054c 100644 --- a/docs/anki-integration.md +++ b/docs/anki-integration.md @@ -172,7 +172,7 @@ To mine multiple subtitle lines as one sentence card, use `Ctrl/Cmd+Shift+S` fol ## Field Grouping (Kiku) -When you mine the same word multiple times, SubMiner can merge the cards instead of creating duplicates. This is designed for note types like [Kiku](https://github.com/donkuri/Kiku) that support grouped sentence/audio/image fields. +When you mine the same word multiple times, SubMiner can merge the cards instead of creating duplicates. This is designed for note types like [Kiku](https://github.com/youyoumu/kiku) that support grouped sentence/audio/image fields. ```jsonc "ankiConnect": { diff --git a/docs/architecture.md b/docs/architecture.md index fa3244f..cdb4b39 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -86,71 +86,51 @@ src/renderer/ ```mermaid flowchart TD - classDef root fill:#c6a0f6,stroke:#181926,color:#181926,stroke-width:2px; - classDef orchestration fill:#494d64,stroke:#b7bdf8,color:#cad3f5,stroke-width:2px; - classDef domain fill:#494d64,stroke:#8aadf4,color:#cad3f5,stroke-width:2px; - classDef boundary fill:#494d64,stroke:#a6da95,color:#cad3f5,stroke-width:2px; + classDef root fill:#c6a0f6,stroke:#24273a,color:#24273a,stroke-width:2px + classDef comp fill:#b7bdf8,stroke:#24273a,color:#24273a,stroke-width:1.5px + classDef svc fill:#8aadf4,stroke:#24273a,color:#24273a,stroke-width:1.5px + classDef ext fill:#a6da95,stroke:#24273a,color:#24273a,stroke-width:1.5px - subgraph Entry["Entrypoint"] - Main["src/main.ts\nentry point"] + Main["src/main.ts"]:::root + + subgraph Composition["Composition Modules"] + Startup["Startup & Lifecycle"]:::comp + IpcCli["IPC & CLI Wiring"]:::comp + Overlay["Overlay & Shortcuts"]:::comp + Subsync["Subsync"]:::comp end - class Main root; - subgraph MainModules["src/main/ Composition Modules"] - Startup["startup.ts\nbootstrap flow"] - AppLifecycle["app-lifecycle.ts\nlifecycle events"] - StartupLifecycle["startup-lifecycle.ts\napp-ready sequence"] - State["state.ts\nruntime state container"] - IpcRuntime["ipc-runtime.ts\nIPC handlers"] - CliRuntime["cli-runtime.ts\nCLI dispatch"] - OverlayRuntime["overlay-runtime.ts\nwindow/modal"] - SubsyncRuntime["subsync-runtime.ts\nsubsync orchestration"] + subgraph Services["Domain Services"] + OverlaySvc["Overlay Services"]:::svc + MpvSvc["MPV Stack"]:::svc + MiningSvc["Mining & Subtitles"]:::svc + ShortcutIpc["Shortcuts & IPC"]:::svc end - class Startup,AppLifecycle,StartupLifecycle,State,IpcRuntime,CliRuntime,OverlayRuntime,SubsyncRuntime orchestration; - subgraph RuntimeServices["Runtime Domain Services"] - OverlayMgr["overlay-manager-service"] - OverlayWindow["overlay-window-service"] - OverlayVisibility["overlay-visibility-service"] - Ipc["ipc-service\nipc-command-service"] - RuntimeOpts["runtime-options-ipc-service"] - Mpv["mpv-service\nmpv-control-service"] - MpvTransport["mpv-transport\nmpv-protocol"] - Subtitle["subtitle-ws-service\nsecondary-subtitle-service"] - Shortcuts["shortcut-service\noverlay-shortcut-service"] + subgraph External["External Boundaries"] + Config["Config & CLI"]:::ext + Trackers["Window Trackers"]:::ext + Integrations["Jimaku & Subsync"]:::ext end - class OverlayMgr,OverlayWindow,OverlayVisibility,Ipc,RuntimeOpts,Mpv,MpvTransport,Subtitle,Shortcuts domain; - subgraph Adapters["External Boundaries"] - Config["src/config/*"] - Cli["src/cli/*"] - Trackers["src/window-trackers/*"] - Integrations["src/jimaku/*\nsrc/subsync/*"] - end - class Config,Cli,Trackers,Integrations boundary; + Main --> Startup + Main --> IpcCli + Main --> Overlay + Main --> Subsync - Main -->|delegates to| Startup - Main -->|registers| AppLifecycle - AppLifecycle -->|triggers| StartupLifecycle - StartupLifecycle -->|initializes| State + Startup --> OverlaySvc + IpcCli --> ShortcutIpc + Overlay --> OverlaySvc + Overlay --> MpvSvc + Subsync --> Integrations - Main -->|builds deps| IpcRuntime - Main -->|builds deps| CliRuntime - Main -->|builds deps| OverlayRuntime - Main -->|builds deps| SubsyncRuntime + OverlaySvc --> Trackers + MpvSvc --> MiningSvc + ShortcutIpc --> Config - IpcRuntime -->|registers| Ipc - IpcRuntime -->|registers| RuntimeOpts - CliRuntime -->|registers| Cli - OverlayRuntime -->|manages| OverlayMgr - OverlayRuntime -->|manages| OverlayWindow - OverlayRuntime -->|manages| OverlayVisibility - - Main -->|loads| Config - - Ipc -->|updates| RuntimeOpts - Mpv -->|feeds| Subtitle - Shortcuts -->|drives| OverlayMgr + style Composition fill:#363a4f,stroke:#494d64,color:#cad3f5 + style Services fill:#363a4f,stroke:#494d64,color:#cad3f5 + style External fill:#363a4f,stroke:#494d64,color:#cad3f5 ``` ## Composition Pattern @@ -189,35 +169,28 @@ This keeps side effects explicit and makes behavior easy to unit-test with fakes ```mermaid flowchart TD - classDef phase fill:#494d64,stroke:#b7bdf8,color:#cad3f5,stroke-width:2px; - classDef decision fill:#494d64,stroke:#f5a97f,color:#cad3f5,stroke-width:2px; - classDef runtime fill:#494d64,stroke:#8aadf4,color:#cad3f5,stroke-width:2px; - classDef shutdown fill:#494d64,stroke:#a6da95,color:#cad3f5,stroke-width:2px; + classDef phase fill:#b7bdf8,stroke:#24273a,color:#24273a,stroke-width:1.5px + classDef decision fill:#f5a97f,stroke:#24273a,color:#24273a,stroke-width:1.5px + classDef runtime fill:#8aadf4,stroke:#24273a,color:#24273a,stroke-width:1.5px + classDef shutdown fill:#a6da95,stroke:#24273a,color:#24273a,stroke-width:1.5px - Args["CLI args / env"] --> Startup["src/main/startup.ts\nstartup-service"] - class Args,Startup phase; + Args["CLI args / env"]:::phase --> Startup["src/main/startup.ts"]:::phase - Startup --> Decision{"generate-config?"} - class Decision decision; + Startup --> Decision{"generate-config?"}:::decision - Decision -->|yes| WriteConfig["write config + exit"] - Decision -->|no| AppLifecycle["src/main/app-lifecycle.ts\napp-lifecycle-service"] - class WriteConfig,AppLifecycle phase; + Decision -->|yes| WriteConfig["Write config + exit"]:::phase + Decision -->|no| AppLifecycle["src/main/app-lifecycle.ts"]:::phase - AppLifecycle --> Ready["src/main/startup-lifecycle.ts\napp-ready flow\n(config + websocket policy + tracker/tokenizer init + state init)"] - class Ready phase; + AppLifecycle --> Ready["src/main/startup-lifecycle.ts\nConfig · WebSocket · Tracker · Tokenizer · State"]:::phase - Ready --> Runtime["src/main/* runtime modules:\nipc-runtime, cli-runtime, overlay-runtime, subsync-runtime"] - class Runtime runtime; + Ready --> Runtime["Runtime Modules\nipc · cli · overlay · subsync"]:::runtime - Runtime --> Overlay["overlay visibility + mining actions"] - Runtime --> Subtitle["subtitle + secondary-subtitle processing"] - Runtime --> Subsync["subsync / jimaku integration actions"] - class Overlay,Subtitle,Subsync runtime; + Runtime --> Overlay["Overlay & Mining"]:::runtime + Runtime --> Subtitle["Subtitle Processing"]:::runtime + Runtime --> SubsyncInt["Subsync & Jimaku"]:::runtime - Runtime --> WillQuit["Electron will-quit"] - WillQuit --> Cleanup["service-level teardown\n(unregister hooks, close resources)"] - class WillQuit,Cleanup shutdown; + Runtime --> WillQuit["Electron will-quit"]:::shutdown + WillQuit --> Cleanup["Service Teardown"]:::shutdown ``` ## Why This Design diff --git a/docs/configuration.md b/docs/configuration.md index 8aadecb..49bdfd6 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -2,6 +2,26 @@ Settings are stored in `$XDG_CONFIG_HOME/SubMiner/config.jsonc` (or `~/.config/SubMiner/config.jsonc` when `XDG_CONFIG_HOME` is unset). For backward compatibility, SubMiner also reads existing configs from lowercase `subminer` directories. +## Quick Start + +For most users, start with this minimal configuration: + +```json +{ + "ankiConnect": { + "enabled": true, + "deck": "YourDeckName", + "fields": { + "sentence": "Sentence", + "audio": "Audio", + "image": "Image" + } + } +} +``` + +Then customize as needed using the sections below. + ## Configuration File See [config.example.jsonc](/config.example.jsonc) for a comprehensive example configuration file with all available options, default values, and detailed comments. Only include the options you want to customize in your config file. @@ -196,12 +216,8 @@ To refresh roughly once per day, set: } ``` - +### Field Grouping Modes -Open demo in a new tab | Mode | Behavior | | ---------- | -------------------------------------------------------------------------------------------------------------------------- | | `auto` | Automatically merges the new card's content into the original; duplicate deletion is controlled by `deleteDuplicateInAuto` | @@ -210,15 +226,22 @@ To refresh roughly once per day, set: `deleteDuplicateInAuto` controls whether `auto` mode deletes the duplicate after merge (default: `true`). In `manual` mode, the popup asks each time whether to delete the duplicate. + + +Open demo in a new tab + **Image Quality Notes:** - `imageQuality` affects JPG and WebP only; PNG is lossless and ignores this setting - JPG quality is mapped to FFmpeg's scale (2-31, lower = better) - WebP quality uses FFmpeg's native 0-100 scale -**Manual Card Update:** +### Manual Card Update Shortcuts -When `behavior.autoUpdateNewCards` is set to `false`, new cards are detected but not automatically updated. Instead, you can manually update cards using keyboard shortcuts: +When `behavior.autoUpdateNewCards` is set to `false`, new cards are detected but not automatically updated. Use these keyboard shortcuts for manual control: | Shortcut | Action | | -------------- | ------------------------------------------------------------------------------------------------------------ | @@ -232,14 +255,14 @@ When `behavior.autoUpdateNewCards` is set to `false`, new cards are detected but | `Ctrl+Shift+A` | Mark the last added Anki card as an audio card (sets IsAudioCard, SentenceAudio, Sentence, Picture) | | `Ctrl+Shift+O` | Open runtime options palette (session-only live toggles) | -To copy multiple lines (current + previous): +**Multi-line copy workflow:** 1. Press `Ctrl+Shift+C` 2. Press a number key (`1-9`) within 3 seconds 3. The specified number of most recent subtitle lines are copied 4. Press `Ctrl+V` to update the last added card with the copied lines -These shortcuts are only active when the overlay window is visible. They are automatically disabled when the overlay is hidden to avoid interfering with normal system clipboard operations. +These shortcuts are only active when the overlay window is visible and automatically disabled when hidden. ### Auto-Start Overlay diff --git a/docs/index.md b/docs/index.md index c42279b..fdd47e0 100644 --- a/docs/index.md +++ b/docs/index.md @@ -23,22 +23,44 @@ hero: link: /configuration features: - - icon: "🎯" - title: Click-to-Lookup Overlay - details: Subtitles are tokenized into clickable words. Click any word to open a Yomitan dictionary popup — right on top of the video. - - icon: "📇" - title: Automatic Anki Cards - details: Add a word from Yomitan and SubMiner fills in the sentence, audio clip, screenshot, and translation automatically. - - icon: "🪟" + - icon: + src: /assets/mpv.svg + alt: mpv icon + title: Built for mpv + details: Connects directly to mpv over IPC — tracks subtitles in real time, observes playback properties, and renders a self-contained overlay with everything bundled in a single application. + - icon: + src: /assets/yomitan-icon.svg + alt: Yomitan logo + title: Yomitan Integration + details: Hover over any word in the subtitles to trigger Yomitan dictionary lookups — get instant definitions without leaving the video player. + - icon: + src: /assets/anki-card.svg + alt: Anki card icon + title: Anki Card Enrichment + details: Add a word from Yomitan and SubMiner automatically updates the card with the sentence, audio clip, screenshot, and translation — no extra steps needed. + - icon: + src: /assets/dual-layer.svg + alt: Dual layer icon title: Dual-Layer Subtitle System details: Visible overlay with styled, interactive subtitles — plus an invisible layer that aligns with mpv's own subtitle rendering for seamless click-through lookup. - - icon: "🎬" - title: YouTube & Subtitle Sync - details: Play YouTube videos with auto-generated subtitles. Sync external subtitle files with alass or ffsubsync. Search and download anime subtitles from Jimaku. - - icon: "🔠" - title: Smart Tokenization - details: Japanese text is segmented using Yomitan's internal parser with MeCab fallback, enabling accurate word boundary detection for dictionary lookups. - - icon: "⌨️" + - icon: + src: /assets/highlight.svg + alt: Highlight icon + title: N+1 Word Highlighting + details: Highlights words you already know from your Anki deck, making it easy to spot new vocabulary and identify true N+1 sentences during immersion. + - icon: + src: /assets/texthooker.svg + alt: Texthooker icon + title: Texthooker & WebSocket + details: Built-in texthooker page that receives subtitles over WebSocket — use it as a clipboard inserter for Yomitan or connect external tools for real-time subtitle streaming. + - icon: + src: /assets/subtitle-download.svg + alt: Subtitle download icon + title: Subtitle Download & Sync + details: Search and download Japanese subtitles from Jimaku, then sync them to the audio with alass or ffsubsync — all from within the player. + - icon: + src: /assets/keyboard.svg + alt: Keyboard icon title: Keyboard-Driven Workflow details: Mine sentences, copy subtitles, cycle display modes, and trigger field grouping — all from configurable keyboard shortcuts without touching the mouse. --- @@ -136,7 +158,7 @@ SubMiner sits as a transparent overlay on top of mpv. Subtitles appear as intera