diff --git a/bun.lockb b/bun.lockb index 0669364..546445c 100644 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/src/components/Common/Markdown.tsx b/src/components/Common/Markdown.tsx index 149716a..960b3bd 100644 --- a/src/components/Common/Markdown.tsx +++ b/src/components/Common/Markdown.tsx @@ -1,23 +1,41 @@ +import "katex/dist/katex.min.css" + import remarkGfm from "remark-gfm" import remarkMath from "remark-math" import ReactMarkdown from "react-markdown" +import rehypeKatex from "rehype-katex" import "property-information" import React from "react" import { CodeBlock } from "./CodeBlock" +export const preprocessLaTeX = (content: string) => { + // Replace block-level LaTeX delimiters \[ \] with $$ $$ -export default function Markdown({ + const blockProcessedContent = content.replace( + /\\\[(.*?)\\\]/gs, + (_, equation) => `$$${equation}$$` + ) + // Replace inline LaTeX delimiters \( \) with $ $ + const inlineProcessedContent = blockProcessedContent.replace( + /\\\((.*?)\\\)/gs, + (_, equation) => `$${equation}$` + ) + return inlineProcessedContent +} +function Markdown({ message, className = "prose break-words dark:prose-invert prose-p:leading-relaxed prose-pre:p-0 dark:prose-dark" }: { message: string className?: string }) { + message = preprocessLaTeX(message) return ( ) } + +export default React.memo(Markdown) diff --git a/src/hooks/useSmartScroll.tsx b/src/hooks/useSmartScroll.tsx index cad0ce4..d967c29 100644 --- a/src/hooks/useSmartScroll.tsx +++ b/src/hooks/useSmartScroll.tsx @@ -1,35 +1,42 @@ -import { useRef, useEffect, useState } from 'react'; +import { useRef, useEffect, useState } from "react" export const useSmartScroll = (messages: any[], streaming: boolean) => { - const containerRef = useRef(null); - const [isAtBottom, setIsAtBottom] = useState(true); + const containerRef = useRef(null) + const [isAtBottom, setIsAtBottom] = useState(true) useEffect(() => { - const container = containerRef.current; - if (!container) return; + const container = containerRef.current + if (!container) return const handleScroll = () => { - const { scrollTop, scrollHeight, clientHeight } = container; - setIsAtBottom(scrollHeight - scrollTop - clientHeight < 50); - }; + const { scrollTop, scrollHeight, clientHeight } = container + setIsAtBottom(scrollHeight - scrollTop - clientHeight < 50) + } - container.addEventListener('scroll', handleScroll); - return () => container.removeEventListener('scroll', handleScroll); - }, []); + container.addEventListener("scroll", handleScroll) + return () => container.removeEventListener("scroll", handleScroll) + }, []) useEffect(() => { + if (messages.length === 0) { + setIsAtBottom(true) + return + } + if (isAtBottom && containerRef.current) { const scrollOptions: ScrollIntoViewOptions = streaming - ? { behavior: 'smooth', block: 'end' } - : { behavior: 'auto', block: 'end' }; - containerRef.current.lastElementChild?.scrollIntoView(scrollOptions); + ? { behavior: "smooth", block: "end" } + : { behavior: "auto", block: "end" } + containerRef.current.lastElementChild?.scrollIntoView(scrollOptions) } - }, [messages, streaming, isAtBottom]); + }, [messages, streaming, isAtBottom]) const scrollToBottom = () => { - containerRef.current?.lastElementChild?.scrollIntoView({ behavior: 'smooth', block: 'end' }); - }; + containerRef.current?.lastElementChild?.scrollIntoView({ + behavior: "smooth", + block: "end" + }) + } - - return { containerRef, isAtBottom, scrollToBottom }; -}; + return { containerRef, isAtBottom, scrollToBottom } +} \ No newline at end of file diff --git a/wxt.config.ts b/wxt.config.ts index 3a88ec8..6ad0b4e 100644 --- a/wxt.config.ts +++ b/wxt.config.ts @@ -50,7 +50,7 @@ export default defineConfig({ outDir: "build", manifest: { - version: "1.2.2", + version: "1.2.3", name: process.env.TARGET === "firefox" ? "Page Assist - A Web UI for Local AI Models"