diff --git a/packages/app-expo/assets/reader/reader.html b/packages/app-expo/assets/reader/reader.html index 178d0f69..a385dd53 100644 --- a/packages/app-expo/assets/reader/reader.html +++ b/packages/app-expo/assets/reader/reader.html @@ -3369,6 +3369,9 @@ 'rp', 'sup', '.readany-translation', + '.foliate-note-tooltip', + '#foliate-note-shared-tooltip', + '[data-readany-tts-skip]', '[role="doc-noteref"]', '[role="doc-footnote"]', '[epub\\:type~="noteref"]', diff --git a/packages/app-expo/assets/reader/reader.template.html b/packages/app-expo/assets/reader/reader.template.html index 6ad30183..dc0cccf5 100644 --- a/packages/app-expo/assets/reader/reader.template.html +++ b/packages/app-expo/assets/reader/reader.template.html @@ -3369,6 +3369,9 @@ 'rp', 'sup', '.readany-translation', + '.foliate-note-tooltip', + '#foliate-note-shared-tooltip', + '[data-readany-tts-skip]', '[role="doc-noteref"]', '[role="doc-footnote"]', '[epub\\:type~="noteref"]', diff --git a/packages/app/src/components/reader/FoliateViewer.tsx b/packages/app/src/components/reader/FoliateViewer.tsx index 1179c838..48b2ac70 100644 --- a/packages/app/src/components/reader/FoliateViewer.tsx +++ b/packages/app/src/components/reader/FoliateViewer.tsx @@ -3417,6 +3417,7 @@ function ensureNoteTooltipSystem(doc: Document) { const tooltip = doc.createElement("div"); tooltip.className = "foliate-note-tooltip"; tooltip.id = "foliate-note-shared-tooltip"; + tooltip.setAttribute("data-readany-tts-skip", "true"); const content = doc.createElement("div"); content.className = "note-content"; tooltip.appendChild(content); diff --git a/packages/core/src/tts/text-utils.test.ts b/packages/core/src/tts/text-utils.test.ts index 8ef1a490..ae7f3941 100644 --- a/packages/core/src/tts/text-utils.test.ts +++ b/packages/core/src/tts/text-utils.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from "vitest"; -import { cleanText, isTTSFootnoteMarker } from "./text-utils"; +import { cleanText, isTTSFootnoteMarker, shouldSkipTTSNode } from "./text-utils"; describe("TTS text utils", () => { it("removes numeric footnote markers from narration text", () => { @@ -20,4 +20,15 @@ describe("TTS text utils", () => { expect(isTTSFootnoteMarker("(四)")).toBe(true); expect(isTTSFootnoteMarker("正文[十二]")).toBe(false); }); + + it("skips ReadAny note tooltip text", () => { + const tooltipChild = { + closest: (selector: string) => + selector.includes(".foliate-note-tooltip") && selector.includes("[data-readany-tts-skip]") + ? {} + : null, + } as unknown as Element; + + expect(shouldSkipTTSNode(tooltipChild)).toBe(true); + }); }); diff --git a/packages/core/src/tts/text-utils.ts b/packages/core/src/tts/text-utils.ts index bee5804d..91ba5221 100644 --- a/packages/core/src/tts/text-utils.ts +++ b/packages/core/src/tts/text-utils.ts @@ -15,6 +15,9 @@ const TTS_SKIPPED_ELEMENT_SELECTOR = [ "rp", "sup", ".readany-translation", + ".foliate-note-tooltip", + "#foliate-note-shared-tooltip", + "[data-readany-tts-skip]", '[role="doc-noteref"]', '[role="doc-footnote"]', '[epub\\:type~="noteref"]', @@ -25,8 +28,8 @@ const TTS_SKIPPED_ELEMENT_SELECTOR = [ 'a[href^="#footnote"]', 'a[href*="footnote"]', 'a[href*="note"]', - 'a.noteref', - 'a.footnote', + "a.noteref", + "a.footnote", ".noteref", ".footnote", ".footnote-ref", @@ -48,10 +51,7 @@ export function shouldSkipTTSNode(element: Element | null | undefined): boolean /** Clean text for TTS: remove footnote references and extra whitespace. */ export function cleanText(text: string): string { - return text - .replace(FOOTNOTE_MARKER_PATTERN, "") - .replace(/\s+/g, " ") - .trim(); + return text.replace(FOOTNOTE_MARKER_PATTERN, "").replace(/\s+/g, " ").trim(); } /** Count characters (CJK = 2 units, others = 1) */