feat(anki): add configurable word card type for Kiku/Lapis

- Add `ankiConnect.lapisKiku.wordCardKind` setting to choose the card-type flag SubMiner marks on mined word cards: word-and-sentence (default), click, sentence, audio, or none
- Support IsClickCard, which SubMiner previously never set
- Clear other card-type flags whenever one is set, so a note can't claim two card types at once
- Extract card-kind flag resolution into new card-kinds.ts module
- Hot-reload the new setting alongside existing Kiku/Lapis config
- Update docs-site and config.example.jsonc
This commit is contained in:
2026-07-30 00:45:38 -07:00
parent 1995200e76
commit d37a3eb299
31 changed files with 752 additions and 218 deletions
+37
View File
@@ -2738,6 +2738,43 @@ test('ignores deprecated isLapis sentence-card field overrides', () => {
);
});
test('accepts a Kiku/Lapis word card kind and warns on an unknown one', () => {
const dir = makeTempDir();
fs.writeFileSync(
path.join(dir, 'config.jsonc'),
`{
"ankiConnect": {
"isKiku": { "enabled": true },
"lapisKiku": { "wordCardKind": "click" }
}
}`,
'utf-8',
);
const service = new ConfigService(dir);
assert.equal(service.getConfig().ankiConnect.lapisKiku.wordCardKind, 'click');
assert.equal(service.getWarnings().length, 0);
const invalidDir = makeTempDir();
fs.writeFileSync(
path.join(invalidDir, 'config.jsonc'),
`{
"ankiConnect": {
"lapisKiku": { "wordCardKind": "isClickCard" }
}
}`,
'utf-8',
);
const invalidService = new ConfigService(invalidDir);
assert.equal(invalidService.getConfig().ankiConnect.lapisKiku.wordCardKind, 'word-and-sentence');
assert.ok(
invalidService
.getWarnings()
.some((warning) => warning.path === 'ankiConnect.lapisKiku.wordCardKind'),
);
});
test('accepts valid ankiConnect knownWords deck object', () => {
const dir = makeTempDir();
fs.writeFileSync(