fix: CI changelog, annotation options threading, and Jellyfin quit

- Add `type: fixed` / `area:` frontmatter to `changes/319` to pass `changelog:lint`
- Thread `TokenizerAnnotationOptions` through `stripSubtitleAnnotationMetadata` so `sourceText` is honored
- Include `jellyfinPlay` in `shouldQuitOnDisconnectWhenOverlayRuntimeInitialized` predicate
- Make mouse test `elementFromPoint` stubs coordinate-sensitive
- Make Lua test `.tmp` mkdir portable on Windows
This commit is contained in:
2026-05-02 23:33:19 -07:00
parent a9625f8777
commit b926f97578
9 changed files with 106 additions and 37 deletions
+23 -22
View File
@@ -160,7 +160,7 @@ async function applyAnnotationStage(
options: TokenizerAnnotationOptions,
): Promise<MergedToken[]> {
if (!hasAnyAnnotationEnabled(options)) {
return stripSubtitleAnnotationMetadata(tokens);
return stripSubtitleAnnotationMetadata(tokens, options);
}
if (!annotationStageModulePromise) {
@@ -179,7 +179,10 @@ async function applyAnnotationStage(
);
}
async function stripSubtitleAnnotationMetadata(tokens: MergedToken[]): Promise<MergedToken[]> {
async function stripSubtitleAnnotationMetadata(
tokens: MergedToken[],
options: TokenizerAnnotationOptions,
): Promise<MergedToken[]> {
if (tokens.length === 0) {
return tokens;
}
@@ -189,7 +192,7 @@ async function stripSubtitleAnnotationMetadata(tokens: MergedToken[]): Promise<M
}
const annotationStage = await annotationStageModulePromise;
return tokens.map((token) => annotationStage.stripSubtitleAnnotationMetadata(token));
return tokens.map((token) => annotationStage.stripSubtitleAnnotationMetadata(token, options));
}
export function createTokenizerDepsRuntime(
@@ -683,25 +686,23 @@ async function parseWithYomitanInternalParser(
return null;
}
const normalizedSelectedTokens = normalizeSelectedYomitanTokens(
selectedTokens.map(
(token): MergedToken => {
const posMetadata = getYomitanWordClassPosMetadata(token.wordClasses);
return {
surface: token.surface,
reading: token.reading,
headword: token.headword,
startPos: token.startPos,
endPos: token.endPos,
partOfSpeech: posMetadata.partOfSpeech,
pos1: posMetadata.pos1,
isMerged: true,
isKnown: false,
isNPlusOneTarget: false,
isNameMatch: token.isNameMatch ?? false,
frequencyRank: token.frequencyRank,
};
},
),
selectedTokens.map((token): MergedToken => {
const posMetadata = getYomitanWordClassPosMetadata(token.wordClasses);
return {
surface: token.surface,
reading: token.reading,
headword: token.headword,
startPos: token.startPos,
endPos: token.endPos,
partOfSpeech: posMetadata.partOfSpeech,
pos1: posMetadata.pos1,
isMerged: true,
isKnown: false,
isNPlusOneTarget: false,
isNameMatch: token.isNameMatch ?? false,
frequencyRank: token.frequencyRank,
};
}),
);
if (deps.getYomitanGroupDebugEnabled?.() === true) {
@@ -507,8 +507,11 @@ export function shouldExcludeTokenFromSubtitleAnnotations(token: MergedToken): b
return sharedShouldExcludeTokenFromSubtitleAnnotations(token);
}
export function stripSubtitleAnnotationMetadata(token: MergedToken): MergedToken {
return sharedStripSubtitleAnnotationMetadata(token);
export function stripSubtitleAnnotationMetadata(
token: MergedToken,
options: AnnotationStageOptions = {},
): MergedToken {
return sharedStripSubtitleAnnotationMetadata(token, options);
}
function computeTokenKnownStatus(
@@ -310,8 +310,7 @@ function fillMissingPos1BySurfaceSequence(
let cursor = 0;
return tokens.map((token) => {
const hasCompletePosMetadata =
token.pos1?.trim() && token.pos2?.trim() && token.pos3?.trim();
const hasCompletePosMetadata = token.pos1?.trim() && token.pos2?.trim() && token.pos3?.trim();
if (hasCompletePosMetadata) {
return token;
}
+7 -3
View File
@@ -85,12 +85,16 @@ export function createBuildBindMpvMainEventHandlersMainDepsHandler(deps: {
hasInitialPlaybackQuitOnDisconnectArg: () =>
Boolean(
deps.appState.initialArgs?.managedPlayback ||
deps.appState.initialArgs?.jellyfinPlay ||
deps.appState.initialArgs?.youtubePlay,
deps.appState.initialArgs?.jellyfinPlay ||
deps.appState.initialArgs?.youtubePlay,
),
isOverlayRuntimeInitialized: () => deps.appState.overlayRuntimeInitialized,
shouldQuitOnDisconnectWhenOverlayRuntimeInitialized: () =>
Boolean(deps.appState.initialArgs?.managedPlayback || deps.appState.initialArgs?.youtubePlay),
Boolean(
deps.appState.initialArgs?.managedPlayback ||
deps.appState.initialArgs?.jellyfinPlay ||
deps.appState.initialArgs?.youtubePlay,
),
isQuitOnDisconnectArmed: () => deps.getQuitOnDisconnectArmed(),
scheduleQuitCheck: (callback: () => void) => deps.scheduleQuitCheck(callback),
isMpvConnected: () => Boolean(deps.appState.mpvClient?.connected),
+4 -2
View File
@@ -1347,7 +1347,8 @@ test('window resize allows primary hover pause from a real mouseenter over subti
configurable: true,
value: {
addEventListener: () => {},
elementFromPoint: () => ctx.dom.subtitleContainer,
elementFromPoint: (x: number, y: number) =>
x === 120 && y === 240 ? ctx.dom.subtitleContainer : null,
querySelectorAll: () => [],
body: {},
},
@@ -1496,7 +1497,8 @@ test('pointer tracking enables overlay interaction as soon as the cursor reaches
bucket.push(listener);
documentListeners.set(type, bucket);
},
elementFromPoint: () => ctx.dom.subtitleContainer,
elementFromPoint: (x: number, y: number) =>
x === 120 && y === 240 ? ctx.dom.subtitleContainer : null,
querySelectorAll: () => [],
body: {},
},
+1 -4
View File
@@ -1069,10 +1069,7 @@ test('subtitle annotation CSS underlines JLPT tokens without changing token colo
cssText,
`#subtitleRoot .word.word-jlpt-n${level}::selection`,
);
assert.ok(
jlptSelectionLockBlock.length > 0,
`word-jlpt-n${level} selection lock should exist`,
);
assert.ok(jlptSelectionLockBlock.length > 0, `word-jlpt-n${level} selection lock should exist`);
assert.match(
jlptSelectionLockBlock,
new RegExp(