onSubtitleChange paused prefetching unconditionally, but the processing
controller returns early when the text matches what it already has. Nothing
is tokenized, so nothing is emitted, so the resume that rides on the emit
never fires and prefetching idles for the rest of the cue. The reachable
trigger is a repeat arriving after a cache invalidation, such as mining a card
while the same line is still on screen.
The controller now reports whether it scheduled processing and the caller
resumes when it did not, so every pause has a matching resume.
Also harden the character-name candidate prefilter: Yomitan collapses emphatic
sequences before matching, so a stretched spelling still resolves to its entry
(ミナァァト matches ミナト). The candidate match now skips small kana and
prolonged marks, which only widens the probe set and so cannot drop a name.
The greedy name pre-pass asked the Yomitan backend at every Japanese
position, because a character name can begin mid-token. With the character
dictionary enabled that roughly doubled the round trips per line (measured
10 -> 21 on a 23-char line).
SubMiner generates the character dictionary, so the cached snapshots already
list every form a character entry can be matched by (term and reading). Those
forms are installed into the scan runtime once per media and the pre-pass now
probes only positions where one of them starts, compared after kana
normalization so a katakana name still matches a hiragana reading form. The
overhead drops to zero (21 -> 10, the same as with the dictionary disabled).
Fail-safe: with no candidate list (no media id, no cached snapshot, failed
install) the pre-pass keeps its exhaustive behavior, so stale character data
costs speed rather than a missing name. Halfwidth katakana positions bypass
the filter since kana normalization does not fold them.
The candidate lookup is consulted per subtitle line, so it caches its snapshot
directory signature for 5s; dictionary writes still call invalidate().
- extract the injected scan runtime (helpers, install script, call-script
builder) into tokenizer/yomitan-scan-runtime-script.ts; the host module drops
from ~2700 to ~1900 lines
- append the kana run to the reading as well as the surface when an unparsed
run extends the previous token, so the reading keeps covering the surface and
the known-word reading fallback stays enabled (bumps scan runtime version)
- stop annotateMs before character-image resolution so the stage timing
measures the annotation stage only