feat: integrate n+1 target highlighting

- Merge feature branch changes for n+1 target-only highlight flow

- Extend merged token model and token-merger to mark exactly-one unknown targets

- Thread n+1 candidate metadata through tokenizer and config systems

- Update subtitle renderer/state to route configured colors and new token class

- Resolve merge conflicts in core service tests, including subtitle and subsync behavior
This commit is contained in:
2026-02-15 02:36:48 -08:00
parent 88099e2ffa
commit 3a27c026b6
16 changed files with 494 additions and 66 deletions

View File

@@ -186,6 +186,63 @@ test("accepts valid ankiConnect n+1 match mode values", () => {
assert.equal(config.ankiConnect.nPlusOne.matchMode, "surface");
});
test("validates ankiConnect n+1 color values", () => {
const dir = makeTempDir();
fs.writeFileSync(
path.join(dir, "config.jsonc"),
`{
"ankiConnect": {
"nPlusOne": {
"nPlusOne": "not-a-color",
"knownWord": 123
}
}
}`,
"utf-8",
);
const service = new ConfigService(dir);
const config = service.getConfig();
const warnings = service.getWarnings();
assert.equal(
config.ankiConnect.nPlusOne.nPlusOne,
DEFAULT_CONFIG.ankiConnect.nPlusOne.nPlusOne,
);
assert.equal(
config.ankiConnect.nPlusOne.knownWord,
DEFAULT_CONFIG.ankiConnect.nPlusOne.knownWord,
);
assert.ok(
warnings.some((warning) => warning.path === "ankiConnect.nPlusOne.nPlusOne"),
);
assert.ok(
warnings.some((warning) => warning.path === "ankiConnect.nPlusOne.knownWord"),
);
});
test("accepts valid ankiConnect n+1 color values", () => {
const dir = makeTempDir();
fs.writeFileSync(
path.join(dir, "config.jsonc"),
`{
"ankiConnect": {
"nPlusOne": {
"nPlusOne": "#c6a0f6",
"knownWord": "#a6da95"
}
}
}`,
"utf-8",
);
const service = new ConfigService(dir);
const config = service.getConfig();
assert.equal(config.ankiConnect.nPlusOne.nPlusOne, "#c6a0f6");
assert.equal(config.ankiConnect.nPlusOne.knownWord, "#a6da95");
});
test("supports legacy ankiConnect.behavior N+1 settings as fallback", () => {
const dir = makeTempDir();
fs.writeFileSync(
@@ -268,5 +325,8 @@ test("template generator includes known keys", () => {
assert.match(output, /"ankiConnect":/);
assert.match(output, /"websocket":/);
assert.match(output, /"youtubeSubgen":/);
assert.match(output, /"nPlusOne"\s*:\s*\{/);
assert.match(output, /"nPlusOne": "#c6a0f6"/);
assert.match(output, /"knownWord": "#a6da95"/);
assert.match(output, /auto-generated from src\/config\/definitions.ts/);
});