-
@@ -123,53 +84,6 @@ export default function KokoroReader({ pages }: { pages: any[] }) {
- {/*
*/}
-
- {results.map((result, i) => (
-
-
-
- #{results.length - i}
-
-
{result.text}
-
-
-
- ))}
);
}
diff --git a/components/MarkdownRenderer.tsx b/components/MarkdownRenderer.tsx
new file mode 100644
index 0000000..8b69114
--- /dev/null
+++ b/components/MarkdownRenderer.tsx
@@ -0,0 +1,106 @@
+"use client";
+import {
+ Popover,
+ PopoverTrigger,
+ PopoverContent,
+} from "@/components/ui/popover";
+import { useMemo } from "react";
+import ReactMarkdown, { Components } from "react-markdown";
+import rehypeRaw from "rehype-raw";
+import { useTTS } from "./TTSProvider";
+import rehypeHighlight from "@/lib/utils";
+
+// Utility to escape regex special characters:
+function escapeRegExp(text: string) {
+ return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
+}
+
+export default function MarkdownRenderer({
+ rawContent,
+}: {
+ rawContent: string;
+}) {
+ // Obtain TTS info from context.
+ // TTSProvider is already wrapping this component higher in the tree.
+ const { currentSentence, sentences } = useTTS();
+
+ // Determine the text to highlight.
+ const textToHighlight = useMemo(() => {
+ if (!sentences || sentences.length === 0) return "";
+ return sentences[currentSentence] || "";
+ }, [sentences, currentSentence]);
+
+ // Setup rehype plugins including our highlight plugin.
+ const rehypePlugins = useMemo(
+ () => [rehypeRaw, [rehypeHighlight, { textToHighlight }] as any],
+ [textToHighlight]
+ );
+
+ const components: Components = {
+ h1: ({ node, ...props }) => (
+