mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-02-27 18:22:41 -08:00
fix(anki): fix Lapis sentence-card fields to defaults
Remove configurable isLapis sentence/audio field overrides so sentence cards always map to Sentence and SentenceAudio. Update types and docs to reflect the simplified config surface.
This commit is contained in:
@@ -0,0 +1,44 @@
|
|||||||
|
---
|
||||||
|
id: TASK-83
|
||||||
|
title: Simplify isLapis sentence card field config to fixed field names
|
||||||
|
status: Done
|
||||||
|
assignee:
|
||||||
|
- codex-main
|
||||||
|
created_date: '2026-02-19 08:38'
|
||||||
|
updated_date: '2026-02-19 08:40'
|
||||||
|
labels:
|
||||||
|
- config
|
||||||
|
- anki
|
||||||
|
- cleanup
|
||||||
|
dependencies: []
|
||||||
|
priority: medium
|
||||||
|
---
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
<!-- SECTION:DESCRIPTION:BEGIN -->
|
||||||
|
Remove `sentenceCardSentenceField` and `sentenceCardAudioField` from the `ankiConnect.isLapis` config surface so Lapis mode always uses fixed field names `Sentence` and `SentenceAudio`. Update types/defaults/docs/examples and adjust integration code to stop reading those keys.
|
||||||
|
<!-- SECTION:DESCRIPTION:END -->
|
||||||
|
|
||||||
|
## Acceptance Criteria
|
||||||
|
<!-- AC:BEGIN -->
|
||||||
|
- [x] #1 `isLapis` config no longer exposes `sentenceCardSentenceField` or `sentenceCardAudioField` in types/defaults/examples/docs
|
||||||
|
- [x] #2 Anki integration uses fixed sentence-card field names `Sentence` and `SentenceAudio` when Lapis/Kiku sentence-card flow runs
|
||||||
|
- [x] #3 Project build and relevant tests pass after removal
|
||||||
|
<!-- AC:END -->
|
||||||
|
|
||||||
|
## Implementation Notes
|
||||||
|
|
||||||
|
<!-- SECTION:NOTES:BEGIN -->
|
||||||
|
Removed `sentenceCardSentenceField` and `sentenceCardAudioField` from `isLapis` config types/defaults (`src/types.ts`, `src/config/definitions.ts`).
|
||||||
|
|
||||||
|
Updated Anki integration to always use fixed sentence-card field names `Sentence` and `SentenceAudio` in effective sentence-card config (`src/anki-integration.ts`).
|
||||||
|
|
||||||
|
Hardened config resolution for `ankiConnect.isLapis` to only read `enabled` and `sentenceCardModel`, and emit warnings when deprecated sentence/audio field override keys are provided (`src/config/service.ts`).
|
||||||
|
|
||||||
|
Updated examples/docs to remove the two keys and document fixed mapping (`config.example.jsonc`, `docs/public/config.example.jsonc`, `docs/configuration.md`, `docs/anki-integration.md`, `docs/mining-workflow.md`).
|
||||||
|
|
||||||
|
Added regression coverage `ignores deprecated isLapis sentence-card field overrides` in `src/config/config.test.ts`.
|
||||||
|
|
||||||
|
Verification: `bun run build && bun run test:config:dist` passed (33/33).
|
||||||
|
<!-- SECTION:NOTES:END -->
|
||||||
@@ -159,9 +159,7 @@ SubMiner can create standalone sentence cards (without a word/expression) using
|
|||||||
"ankiConnect": {
|
"ankiConnect": {
|
||||||
"isLapis": {
|
"isLapis": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"sentenceCardModel": "Japanese sentences",
|
"sentenceCardModel": "Japanese sentences"
|
||||||
"sentenceCardSentenceField": "Sentence",
|
|
||||||
"sentenceCardAudioField": "SentenceAudio"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -254,8 +252,6 @@ When you mine the same word multiple times, SubMiner can merge the cards instead
|
|||||||
"isLapis": {
|
"isLapis": {
|
||||||
"enabled": false,
|
"enabled": false,
|
||||||
"sentenceCardModel": "Japanese sentences",
|
"sentenceCardModel": "Japanese sentences",
|
||||||
"sentenceCardSentenceField": "Sentence",
|
|
||||||
"sentenceCardAudioField": "SentenceAudio",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -139,9 +139,7 @@ Enable automatic Anki card creation and updates with media generation:
|
|||||||
},
|
},
|
||||||
"isLapis": {
|
"isLapis": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"sentenceCardModel": "Japanese sentences",
|
"sentenceCardModel": "Japanese sentences"
|
||||||
"sentenceCardSentenceField": "Sentence",
|
|
||||||
"sentenceCardAudioField": "SentenceAudio"
|
|
||||||
},
|
},
|
||||||
"isKiku": {
|
"isKiku": {
|
||||||
"enabled": false,
|
"enabled": false,
|
||||||
@@ -204,7 +202,7 @@ This example is intentionally compact. The option table below documents availabl
|
|||||||
| `behavior.notificationType` | `"osd"`, `"system"`, `"both"`, `"none"` | Notification type on card update (default: `"osd"`) |
|
| `behavior.notificationType` | `"osd"`, `"system"`, `"both"`, `"none"` | Notification type on card update (default: `"osd"`) |
|
||||||
| `behavior.autoUpdateNewCards` | `true`, `false` | Automatically update cards on creation (default: `true`) |
|
| `behavior.autoUpdateNewCards` | `true`, `false` | Automatically update cards on creation (default: `true`) |
|
||||||
| `metadata.pattern` | string | Format pattern for metadata: `%f`=filename, `%F`=filename+ext, `%t`=time |
|
| `metadata.pattern` | string | Format pattern for metadata: `%f`=filename, `%F`=filename+ext, `%t`=time |
|
||||||
| `isLapis` | object | Lapis/shared sentence-card config: `{ enabled, sentenceCardModel, sentenceCardSentenceField, sentenceCardAudioField }` |
|
| `isLapis` | object | Lapis/shared sentence-card config: `{ enabled, sentenceCardModel }`. Sentence/audio field names are fixed to `Sentence` and `SentenceAudio`. |
|
||||||
| `isKiku` | object | Kiku-only config: `{ enabled, fieldGrouping, deleteDuplicateInAuto }` (shared sentence/audio/model settings are inherited from `isLapis`) |
|
| `isKiku` | object | Kiku-only config: `{ enabled, fieldGrouping, deleteDuplicateInAuto }` (shared sentence/audio/model settings are inherited from `isLapis`) |
|
||||||
|
|
||||||
**Kiku / Lapis Note Type Support:**
|
**Kiku / Lapis Note Type Support:**
|
||||||
@@ -231,6 +229,7 @@ Known-word cache policy:
|
|||||||
- The cache is automatically invalidated when the configured scope changes (for example, when deck changes).
|
- The cache is automatically invalidated when the configured scope changes (for example, when deck changes).
|
||||||
- Cache lookups are in-memory. By default, token headwords are matched against cached `Expression` / `Word` values; set `ankiConnect.nPlusOne.matchMode` to `"surface"` for raw subtitle text matching.
|
- Cache lookups are in-memory. By default, token headwords are matched against cached `Expression` / `Word` values; set `ankiConnect.nPlusOne.matchMode` to `"surface"` for raw subtitle text matching.
|
||||||
- `ankiConnect.behavior.nPlusOne*` legacy keys (`nPlusOneHighlightEnabled`, `nPlusOneRefreshMinutes`, `nPlusOneMatchMode`) are deprecated and only kept for backward compatibility.
|
- `ankiConnect.behavior.nPlusOne*` legacy keys (`nPlusOneHighlightEnabled`, `nPlusOneRefreshMinutes`, `nPlusOneMatchMode`) are deprecated and only kept for backward compatibility.
|
||||||
|
- Legacy top-level `ankiConnect` migration keys (for example `audioField`, `generateAudio`, `imageType`) are compatibility-only, validated before mapping, and ignored with a warning when invalid.
|
||||||
- If AnkiConnect is unreachable, the cache remains in its previous state and an on-screen/system status message is shown.
|
- If AnkiConnect is unreachable, the cache remains in its previous state and an on-screen/system status message is shown.
|
||||||
- Known-word sync activity is logged at `INFO`/`DEBUG` level with the `anki` logger scope and includes scope, notes returned, and word counts.
|
- Known-word sync activity is logged at `INFO`/`DEBUG` level with the `anki` logger scope and includes scope, notes returned, and word counts.
|
||||||
|
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ Create a standalone sentence card without going through Yomitan:
|
|||||||
- **Mine current sentence**: `Ctrl/Cmd+S` (configurable via `shortcuts.mineSentence`)
|
- **Mine current sentence**: `Ctrl/Cmd+S` (configurable via `shortcuts.mineSentence`)
|
||||||
- **Mine multiple lines**: `Ctrl/Cmd+Shift+S` followed by a digit 1–9 to select how many recent subtitle lines to combine.
|
- **Mine multiple lines**: `Ctrl/Cmd+Shift+S` followed by a digit 1–9 to select how many recent subtitle lines to combine.
|
||||||
|
|
||||||
The sentence card uses the note type configured in `isLapis.sentenceCardModel` with the sentence and audio fields mapped by `isLapis.sentenceCardSentenceField` and `isLapis.sentenceCardAudioField`.
|
The sentence card uses the note type configured in `isLapis.sentenceCardModel` and always maps sentence/audio to `Sentence` and `SentenceAudio`.
|
||||||
|
|
||||||
### 3. Mark as Audio Card
|
### 3. Mark as Audio Card
|
||||||
|
|
||||||
|
|||||||
@@ -334,15 +334,11 @@ export class AnkiIntegration {
|
|||||||
private getLapisConfig(): {
|
private getLapisConfig(): {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
sentenceCardModel?: string;
|
sentenceCardModel?: string;
|
||||||
sentenceCardSentenceField?: string;
|
|
||||||
sentenceCardAudioField?: string;
|
|
||||||
} {
|
} {
|
||||||
const lapis = this.config.isLapis;
|
const lapis = this.config.isLapis;
|
||||||
return {
|
return {
|
||||||
enabled: lapis?.enabled === true,
|
enabled: lapis?.enabled === true,
|
||||||
sentenceCardModel: lapis?.sentenceCardModel,
|
sentenceCardModel: lapis?.sentenceCardModel,
|
||||||
sentenceCardSentenceField: lapis?.sentenceCardSentenceField,
|
|
||||||
sentenceCardAudioField: lapis?.sentenceCardAudioField,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,8 +369,8 @@ export class AnkiIntegration {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
model: lapis.sentenceCardModel,
|
model: lapis.sentenceCardModel,
|
||||||
sentenceField: lapis.sentenceCardSentenceField || 'Sentence',
|
sentenceField: 'Sentence',
|
||||||
audioField: lapis.sentenceCardAudioField || 'SentenceAudio',
|
audioField: 'SentenceAudio',
|
||||||
lapisEnabled: lapis.enabled,
|
lapisEnabled: lapis.enabled,
|
||||||
kikuEnabled: kiku.enabled,
|
kikuEnabled: kiku.enabled,
|
||||||
kikuFieldGrouping: (kiku.fieldGrouping || 'disabled') as 'auto' | 'manual' | 'disabled',
|
kikuFieldGrouping: (kiku.fieldGrouping || 'disabled') as 'auto' | 'manual' | 'disabled',
|
||||||
|
|||||||
@@ -136,8 +136,6 @@ export const DEFAULT_CONFIG: ResolvedConfig = {
|
|||||||
isLapis: {
|
isLapis: {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
sentenceCardModel: 'Japanese sentences',
|
sentenceCardModel: 'Japanese sentences',
|
||||||
sentenceCardSentenceField: 'Sentence',
|
|
||||||
sentenceCardAudioField: 'SentenceAudio',
|
|
||||||
},
|
},
|
||||||
isKiku: {
|
isKiku: {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
|
|||||||
@@ -260,8 +260,6 @@ export interface AnkiConnectConfig {
|
|||||||
isLapis?: {
|
isLapis?: {
|
||||||
enabled?: boolean;
|
enabled?: boolean;
|
||||||
sentenceCardModel?: string;
|
sentenceCardModel?: string;
|
||||||
sentenceCardSentenceField?: string;
|
|
||||||
sentenceCardAudioField?: string;
|
|
||||||
};
|
};
|
||||||
isKiku?: {
|
isKiku?: {
|
||||||
enabled?: boolean;
|
enabled?: boolean;
|
||||||
@@ -480,8 +478,6 @@ export interface ResolvedConfig {
|
|||||||
isLapis: {
|
isLapis: {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
sentenceCardModel: string;
|
sentenceCardModel: string;
|
||||||
sentenceCardSentenceField: string;
|
|
||||||
sentenceCardAudioField: string;
|
|
||||||
};
|
};
|
||||||
isKiku: {
|
isKiku: {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
|
|||||||
Reference in New Issue
Block a user