From ceeefeff1474604f2948315d832d87bae8e1727c Mon Sep 17 00:00:00 2001 From: geoffsee <> Date: Tue, 27 May 2025 14:39:00 -0400 Subject: [PATCH] `Remove unused components and assets from the project` Deleted unused components (Attachments, CustomMarkdownRenderer, EnableSearchButton, FlyoutSubMenu) and associated styles (katex.css) to streamline the codebase. This cleanup helps reduce technical debt and improve project maintainability. --- package.json | 8 - ...WelcomeHomeMessage.tsx => WelcomeHome.tsx} | 9 +- src/components/chat/Attachments.tsx | 40 - src/components/chat/Chat.tsx | 8 +- .../chat/CustomMarkdownRenderer.tsx | 22 - src/components/chat/EnableSearchButton.tsx | 49 - src/components/chat/FlyoutSubMenu.tsx | 135 -- src/components/chat/ModelSelectionMenu.tsx | 156 -- .../RenderWelcomeHomeCustomComponents.tsx | 574 -------- .../FlyoutSubMenu.tsx | 0 .../{flyoutmenu => input-menu}/InputMenu.tsx | 4 +- src/components/chat/{ => input}/ChatInput.tsx | 8 +- .../chat/{ => input}/ChatInputSendButton.tsx | 2 +- .../chat/{ => input}/ChatInputTextArea.tsx | 0 src/components/chat/katex.css | 1273 ----------------- .../chat/{ => lib}/SupportedModels.ts | 0 src/components/chat/{ => lib}/domPurify.ts | 0 .../{ => lib}/exportConversationAsMarkdown.ts | 2 +- .../{ => messages}/ChatMessageContent.tsx | 4 +- .../chat/{ => messages}/ChatMessages.tsx | 4 +- .../chat/{ => messages}/MessageBubble.tsx | 6 +- .../{ => messages}/MessageEditorComponent.tsx | 2 +- .../MessageMarkdown.tsx} | 9 +- .../chat/messages/MessageMarkdownRenderer.tsx | 14 + .../chat/{ => messages}/UserMessageTools.tsx | 0 src/components/chat/remarkImageGeneration.ts | 19 - src/components/legal/LegalDoc.tsx | 5 +- .../{chat => markdown}/ImageWithFallback.tsx | 0 src/components/markdown/MarkdownComponent.tsx | 576 ++++++++ .../react-markdown/WebComponents.tsx | 123 -- src/pages/index/+Page.tsx | 2 +- workers/site/sdk/chat-sdk.ts | 2 +- workers/site/services/ChatService.ts | 2 +- 33 files changed, 623 insertions(+), 2435 deletions(-) rename src/components/{WelcomeHomeMessage.tsx => WelcomeHome.tsx} (87%) delete mode 100644 src/components/chat/Attachments.tsx delete mode 100644 src/components/chat/CustomMarkdownRenderer.tsx delete mode 100644 src/components/chat/EnableSearchButton.tsx delete mode 100644 src/components/chat/FlyoutSubMenu.tsx delete mode 100644 src/components/chat/ModelSelectionMenu.tsx delete mode 100644 src/components/chat/RenderWelcomeHomeCustomComponents.tsx rename src/components/chat/{flyoutmenu => input-menu}/FlyoutSubMenu.tsx (100%) rename src/components/chat/{flyoutmenu => input-menu}/InputMenu.tsx (97%) rename src/components/chat/{ => input}/ChatInput.tsx (94%) rename src/components/chat/{ => input}/ChatInputSendButton.tsx (95%) rename src/components/chat/{ => input}/ChatInputTextArea.tsx (100%) delete mode 100644 src/components/chat/katex.css rename src/components/chat/{ => lib}/SupportedModels.ts (100%) rename src/components/chat/{ => lib}/domPurify.ts (100%) rename src/components/chat/{ => lib}/exportConversationAsMarkdown.ts (88%) rename src/components/chat/{ => messages}/ChatMessageContent.tsx (50%) rename src/components/chat/{ => messages}/ChatMessages.tsx (91%) rename src/components/chat/{ => messages}/MessageBubble.tsx (93%) rename src/components/chat/{ => messages}/MessageEditorComponent.tsx (96%) rename src/components/chat/{RenderCustomComponents.tsx => messages/MessageMarkdown.tsx} (97%) create mode 100644 src/components/chat/messages/MessageMarkdownRenderer.tsx rename src/components/chat/{ => messages}/UserMessageTools.tsx (100%) delete mode 100644 src/components/chat/remarkImageGeneration.ts rename src/components/{chat => markdown}/ImageWithFallback.tsx (100%) create mode 100644 src/components/markdown/MarkdownComponent.tsx delete mode 100644 src/components/react-markdown/WebComponents.tsx diff --git a/package.json b/package.json index de539b8..b3c5ea5 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,6 @@ "js-cookie": "^3.0.5", "katex": "^0.16.20", "lucide-react": "^0.436.0", - "manifold-workflow-engine": "^2.0.2", "marked": "^15.0.4", "marked-extended-latex": "^1.1.0", "marked-footnote": "^1.2.4", @@ -75,15 +74,8 @@ "react": "^18.3.1", "react-dom": "^18.3.1", "react-icons": "^5.4.0", - "react-markdown": "^9.0.1", "react-streaming": "^0.3.44", "react-textarea-autosize": "^8.5.5", - "rehype-katex": "^7.0.1", - "rehype-react": "^8.0.0", - "remark-gfm": "^4.0.0", - "remark-math": "^6.0.0", - "remark-parse": "^11.0.0", - "remark-rehype": "^11.1.1", "shiki": "^1.24.0", "terser": "^5.39.0", "typescript": "^5.7.2", diff --git a/src/components/WelcomeHomeMessage.tsx b/src/components/WelcomeHome.tsx similarity index 87% rename from src/components/WelcomeHomeMessage.tsx rename to src/components/WelcomeHome.tsx index a80e61f..4e9360e 100644 --- a/src/components/WelcomeHomeMessage.tsx +++ b/src/components/WelcomeHome.tsx @@ -4,9 +4,8 @@ import { welcome_home_text, welcome_home_tip, } from "../static-data/welcome_home_text"; -import CustomMarkdownRenderer, { - WelcomeHomeMarkdownRenderer, -} from "./chat/CustomMarkdownRenderer"; +import {renderMarkdown} from "./markdown/MarkdownComponent"; + function WelcomeHomeMessage({ visible }) { const containerVariants = { @@ -60,7 +59,7 @@ function WelcomeHomeMessage({ visible }) { > - + {renderMarkdown(welcome_home_text)} @@ -73,7 +72,7 @@ function WelcomeHomeMessage({ visible }) { color="text.secondary" mt={1} > - + {renderMarkdown(welcome_home_tip)} diff --git a/src/components/chat/Attachments.tsx b/src/components/chat/Attachments.tsx deleted file mode 100644 index 27da2f2..0000000 --- a/src/components/chat/Attachments.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import React from "react"; -import { IconButton, Tag, TagCloseButton, TagLabel } from "@chakra-ui/react"; -import { PaperclipIcon } from "lucide-react"; - -// Add a new component for UploadedItem -export const UploadedItem: React.FC<{ - url: string; - onRemove: () => void; - name: string; -}> = ({ url, onRemove, name }) => ( - - {name || url.split("/").pop()} - - -); - -export const AttachmentButton: React.FC<{ - onClick: () => void; - disabled: boolean; -}> = ({ onClick, disabled }) => ( - } - onClick={onClick} - _hover={{ - bg: "transparent", - svg: { - stroke: "accent.secondary", - transition: "stroke 0.3s ease-in-out", - }, - }} - variant="ghost" - size="sm" - isDisabled={disabled} - _focus={{ boxShadow: "none" }} - /> -); diff --git a/src/components/chat/Chat.tsx b/src/components/chat/Chat.tsx index 56de768..c50b34c 100644 --- a/src/components/chat/Chat.tsx +++ b/src/components/chat/Chat.tsx @@ -1,11 +1,11 @@ import React, { useEffect, useRef, useState } from "react"; import { observer } from "mobx-react-lite"; import { Box, Grid, GridItem } from "@chakra-ui/react"; -import ChatMessages from "./ChatMessages"; -import ChatInput from "./ChatInput"; +import ChatMessages from "./messages/ChatMessages"; +import ChatInput from "./input/ChatInput"; import chatStore from "../../stores/ClientChatStore"; import menuState from "../../stores/AppMenuStore"; -import WelcomeHomeMessage from "../WelcomeHomeMessage"; +import WelcomeHome from "../WelcomeHome"; const Chat = observer(({ height, width }) => { const scrollRef = useRef(); @@ -26,7 +26,7 @@ const Chat = observer(({ height, width }) => { gap={0} > = ({ - markdown, -}) => { - return
{renderCustomComponents(markdown)}
; -}; - -export const WelcomeHomeMarkdownRenderer: React.FC< - CustomMarkdownRendererProps -> = ({ markdown }) => { - return {renderWelcomeHomeMarkdown(markdown)}; -}; - -export default CustomMarkdownRenderer; diff --git a/src/components/chat/EnableSearchButton.tsx b/src/components/chat/EnableSearchButton.tsx deleted file mode 100644 index e798b25..0000000 --- a/src/components/chat/EnableSearchButton.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import React from "react"; -import { IconButton } from "@chakra-ui/react"; -import { Globe2Icon } from "lucide-react"; -import clientChatStore from "../../stores/ClientChatStore"; -import { observer } from "mobx-react-lite"; - -export const EnableSearchButton: React.FC<{ disabled: boolean }> = observer( - ({ disabled }) => { - const onClick = () => { - if (clientChatStore.tools.includes("web-search")) { - clientChatStore.setTools([]); - } else { - clientChatStore.setTools(["web-search"]); - } - }; - - const isActive = clientChatStore.tools.includes("web-search"); - - return ( - } - onClick={onClick} - isActive={isActive} - _active={{ - bg: "transparent", - svg: { - stroke: "brand.100", - transition: "stroke 0.3s ease-in-out", - }, - }} - _hover={{ - bg: "transparent", - svg: { - stroke: "accent.secondary", - transition: "stroke 0.3s ease-in-out", - }, - }} - variant="ghost" - size="sm" - isDisabled={disabled} - _focus={{ boxShadow: "none" }} - /> - ); - }, -); diff --git a/src/components/chat/FlyoutSubMenu.tsx b/src/components/chat/FlyoutSubMenu.tsx deleted file mode 100644 index 5926f83..0000000 --- a/src/components/chat/FlyoutSubMenu.tsx +++ /dev/null @@ -1,135 +0,0 @@ -import React, { useRef } from "react"; -import { observer } from "mobx-react-lite"; -import { - Box, - Divider, - HStack, - Menu, - MenuButton, - MenuItem, - MenuList, - Portal, - Text, - useDisclosure, - useOutsideClick, -} from "@chakra-ui/react"; -import { ChevronRight } from "lucide-react"; -import { useIsMobile } from "../contexts/MobileContext"; - -const FlyoutSubMenu: React.FC<{ - title: string; - flyoutMenuOptions: { name: string; value: string }[]; - onClose: () => void; - handleSelect: (item) => Promise; - isSelected?: (item) => boolean; - parentIsOpen: boolean; -}> = observer( - ({ - title, - flyoutMenuOptions, - onClose, - handleSelect, - isSelected, - parentIsOpen, - }) => { - const { isOpen, onOpen, onClose: onSubMenuClose } = useDisclosure(); - - const isMobile = useIsMobile(); - - const menuRef = new useRef(); - - useOutsideClick({ - ref: menuRef, - enabled: !isMobile, - handler: () => { - onSubMenuClose(); - }, - }); - - return ( - { - onSubMenuClose(); - }} - closeOnSelect={false} - > - - - {title} - - - - - - {flyoutMenuOptions.map((item, index) => ( - - { - handleSelect(item); - onSubMenuClose(); - onClose(); - }} - bg={ - isSelected(item) - ? "background.secondary" - : "background.tertiary" - } - _hover={{ bg: "rgba(0, 0, 0, 0.05)" }} - _focus={{ bg: "rgba(0, 0, 0, 0.1)" }} - > - {item.name} - - {index < flyoutMenuOptions.length - 1 && ( - - )} - - ))} - - - - ); - }, -); - -export default FlyoutSubMenu; diff --git a/src/components/chat/ModelSelectionMenu.tsx b/src/components/chat/ModelSelectionMenu.tsx deleted file mode 100644 index 5f685fc..0000000 --- a/src/components/chat/ModelSelectionMenu.tsx +++ /dev/null @@ -1,156 +0,0 @@ -import React, { useCallback } from "react"; -import { - Box, - Button, - Divider, - Flex, - IconButton, - Menu, - MenuButton, - MenuItem, - MenuList, - Text, - useDisclosure, -} from "@chakra-ui/react"; -import { observer } from "mobx-react-lite"; -import { ChevronDown, Copy, RefreshCcw, Settings } from "lucide-react"; -import ClientChatStore from "../../stores/ClientChatStore"; -import clientChatStore from "../../stores/ClientChatStore"; -import FlyoutSubMenu from "./FlyoutSubMenu"; -import { useIsMobile } from "../contexts/MobileContext"; -import { getModelFamily, SUPPORTED_MODELS } from "./SupportedModels"; -import { formatConversationMarkdown } from "./exportConversationAsMarkdown"; - -// Common styles for MenuButton and IconButton -export const MsM_commonButtonStyles = { - bg: "transparent", - color: "text.primary", - borderRadius: "full", - padding: 2, - border: "none", - _hover: { bg: "rgba(255, 255, 255, 0.2)" }, - _active: { bg: "rgba(255, 255, 255, 0.3)" }, - _focus: { boxShadow: "none" }, -}; - -const InputMenu: React.FC<{ isDisabled?: boolean }> = observer( - ({ isDisabled }) => { - const isMobile = useIsMobile(); - const { isOpen, onOpen, onClose } = useDisclosure(); - - const textModels = SUPPORTED_MODELS; - - const handleCopyConversation = useCallback(() => { - navigator.clipboard - .writeText(formatConversationMarkdown(ClientChatStore.messages)) - .then(() => { - window.alert( - "Conversation copied to clipboard. \n\nPaste it somewhere safe!", - ); - onClose(); - }) - .catch((err) => { - console.error("Could not copy text to clipboard: ", err); - window.alert("Failed to copy conversation. Please try again."); - }); - }, [onClose]); - - async function selectModelFn({ name, value }) { - if (getModelFamily(value)) { - ClientChatStore.setModel(value); - } - } - - function isSelectedModelFn({ name, value }) { - return ClientChatStore.model === value; - } - - return ( - - {isMobile ? ( - } - isDisabled={isDisabled} - aria-label="Settings" - _hover={{ bg: "rgba(255, 255, 255, 0.2)" }} - _focus={{ boxShadow: "none" }} - {...MsM_commonButtonStyles} - /> - ) : ( - } - isDisabled={isDisabled} - variant="ghost" - display="flex" - justifyContent="space-between" - alignItems="center" - minW="auto" - {...MsM_commonButtonStyles} - > - - {ClientChatStore.model} - - - )} - - - ({ name: m, value: m }))} - onClose={onClose} - parentIsOpen={isOpen} - handleSelect={selectModelFn} - isSelected={isSelectedModelFn} - /> - - {/*Export conversation button*/} - - - - Export - - - {/*New conversation button*/} - { - onClose(); - clientChatStore.reset(); - }} - _hover={{ bg: "rgba(0, 0, 0, 0.05)" }} - _focus={{ bg: "rgba(0, 0, 0, 0.1)" }} - > - - - New - - - - - ); - }, -); - -export default InputMenu; diff --git a/src/components/chat/RenderWelcomeHomeCustomComponents.tsx b/src/components/chat/RenderWelcomeHomeCustomComponents.tsx deleted file mode 100644 index 256faa1..0000000 --- a/src/components/chat/RenderWelcomeHomeCustomComponents.tsx +++ /dev/null @@ -1,574 +0,0 @@ -import React from "react"; - -import { - Box, - Code, - Divider, - Heading, - Link, - List, - ListItem, - OrderedList, - Table, - Tbody, - Td, - Text, - Th, - Thead, - Tr, - useColorModeValue, -} from "@chakra-ui/react"; -import { marked } from "marked"; -import CodeBlock from "../code/CodeBlock"; -import ImageWithFallback from "./ImageWithFallback"; -import markedKatex from "marked-katex-extension"; -import katex from "katex"; - -try { - if (localStorage) { - marked.use( - markedKatex({ - nonStandard: false, - displayMode: true, - throwOnError: false, - strict: true, - colorIsTextColor: true, - errorColor: "red", - }), - ); - } -} catch (_) {} - -const MemoizedCodeBlock = React.memo(CodeBlock); - -const getHeadingProps = (depth: number) => { - switch (depth) { - case 1: - return { as: "h1", size: "xl", mt: 4, mb: 2 }; - case 2: - return { as: "h2", size: "lg", mt: 3, mb: 2 }; - case 3: - return { as: "h3", size: "md", mt: 2, mb: 1 }; - case 4: - return { as: "h4", size: "sm", mt: 2, mb: 1 }; - case 5: - return { as: "h5", size: "sm", mt: 2, mb: 1 }; - case 6: - return { as: "h6", size: "xs", mt: 2, mb: 1 }; - default: - return { as: `h${depth}`, size: "md", mt: 2, mb: 1 }; - } -}; - -interface TableToken extends marked.Tokens.Table { - align: Array<"center" | "left" | "right" | null>; - header: (string | marked.Tokens.TableCell)[]; - rows: (string | marked.Tokens.TableCell)[][]; -} - -const CustomHeading: React.FC<{ text: string; depth: number }> = ({ - text, - depth, -}) => { - const headingProps = getHeadingProps(depth); - return ( - - {text} - - ); -}; - -const CustomParagraph: React.FC<{ children: React.ReactNode }> = ({ - children, -}) => { - return ( - - {children} - - ); -}; - -const CustomBlockquote: React.FC<{ children: React.ReactNode }> = ({ - children, -}) => { - return ( - - {children} - - ); -}; - -const CustomCodeBlock: React.FC<{ code: string; language?: string }> = ({ - code, - language, -}) => { - return ( - Promise.resolve()} - /> - ); -}; - -const CustomHr: React.FC = () => ; - -const CustomList: React.FC<{ - ordered?: boolean; - start?: number; - children: React.ReactNode; -}> = ({ ordered, start, children }) => { - const commonStyles = { - fontSize: "sm", - wordBreak: "break-word" as const, - maxWidth: "100%" as const, - stylePosition: "outside" as const, - mb: 2, - pl: 4, - }; - - return ordered ? ( - - {children} - - ) : ( - - {children} - - ); -}; - -const CustomListItem: React.FC<{ - children: React.ReactNode; -}> = ({ children }) => { - return {children}; -}; - -const CustomKatex: React.FC<{ math: string; displayMode: boolean }> = ({ - math, - displayMode, -}) => { - const renderedMath = katex.renderToString(math, { displayMode }); - - return ( - - ); -}; - -const CustomTable: React.FC<{ - header: React.ReactNode[]; - align: Array<"center" | "left" | "right" | null>; - rows: React.ReactNode[][]; -}> = ({ header, align, rows }) => { - return ( - - - - {header.map((cell, i) => ( - - ))} - - - - {rows.map((row, rIndex) => ( - - {row.map((cell, cIndex) => ( - - ))} - - ))} - -
- {cell} -
- {cell} -
- ); -}; - -const CustomHtmlBlock: React.FC<{ content: string }> = ({ content }) => { - return ; -}; - -const CustomText: React.FC<{ text: React.ReactNode }> = ({ text }) => { - return ( - - {text} - - ); -}; - -interface CustomStrongProps { - children: React.ReactNode; -} - -const CustomStrong: React.FC = ({ children }) => { - return {children}; -}; - -const CustomEm: React.FC<{ children: React.ReactNode }> = ({ children }) => { - return ( - - {children} - - ); -}; - -const CustomDel: React.FC<{ text: string }> = ({ text }) => { - return ( - - {text} - - ); -}; - -const CustomCodeSpan: React.FC<{ code: string }> = ({ code }) => { - const bg = useColorModeValue("gray.100", "gray.800"); - return ( - - {code} - - ); -}; - -const CustomMath: React.FC<{ math: string; displayMode?: boolean }> = ({ - math, - displayMode = false, -}) => { - return ( - - {math} - - ); -}; - -const CustomLink: React.FC<{ - href: string; - title?: string; - children: React.ReactNode; -}> = ({ href, title, children, ...props }) => { - return ( - - {children} - - ); -}; - -const CustomImage: React.FC<{ href: string; text: string; title?: string }> = ({ - href, - text, - title, -}) => { - return ( - - ); -}; - -function parseTokens(tokens: marked.Token[]): JSX.Element[] { - const output: JSX.Element[] = []; - let blockquoteContent: JSX.Element[] = []; - - tokens.forEach((token, i) => { - switch (token.type) { - case "heading": - output.push( - , - ); - break; - - case "paragraph": { - const parsedContent = token.tokens - ? parseTokens(token.tokens) - : token.text; - if (blockquoteContent.length > 0) { - blockquoteContent.push( - {parsedContent}, - ); - } else { - output.push( - {parsedContent}, - ); - } - break; - } - case "br": - output.push(
); - break; - case "escape": { - break; - } - case "blockquote_start": - blockquoteContent = []; - break; - - case "blockquote_end": - output.push( - - {parseTokens(blockquoteContent)} - , - ); - blockquoteContent = []; - break; - case "blockquote": { - output.push( - - {token.tokens ? parseTokens(token.tokens) : null} - , - ); - break; - } - case "math": - output.push( - , - ); - break; - - case "inlineMath": - output.push( - , - ); - break; - case "inlineKatex": - case "blockKatex": { - const katexToken = token as any; - output.push( - , - ); - break; - } - case "code": - output.push( - , - ); - break; - - case "hr": - output.push(); - break; - case "list": { - const { ordered, start, items } = token; - const listItems = items.map((listItem, idx) => { - const nestedContent = parseTokens(listItem.tokens); - return {nestedContent}; - }); - - output.push( - - {listItems} - , - ); - break; - } - case "table": { - const tableToken = token as TableToken; - - output.push( - - typeof cell === "string" ? cell : parseTokens(cell.tokens || []), - )} - align={tableToken.align} - rows={tableToken.rows.map((row) => - row.map((cell) => - typeof cell === "string" - ? cell - : parseTokens(cell.tokens || []), - ), - )} - />, - ); - break; - } - case "html": - output.push(); - break; - case "def": - case "space": - break; - case "strong": - output.push( - - {parseTokens(token.tokens || [])} - , - ); - break; - case "em": - output.push( - - {token.tokens ? parseTokens(token.tokens) : token.text} - , - ); - break; - - case "codespan": - output.push(); - break; - - case "link": - output.push( - - {token.tokens ? parseTokens(token.tokens) : token.text} - , - ); - break; - - case "image": - output.push( - , - ); - break; - - case "text": { - const parsedContent = token.tokens - ? parseTokens(token.tokens) - : token.text; - - if (blockquoteContent.length > 0) { - blockquoteContent.push( - {parsedContent}, - ); - } else { - output.push(); - } - break; - } - - default: - console.warn("Unhandled token type:", token.type, token); - } - }); - - return output; -} - -export function renderCustomComponents(markdown: string): JSX.Element[] { - marked.setOptions({ - breaks: true, - gfm: true, - silent: false, - async: true, - }); - - const tokens = marked.lexer(markdown); - return parseTokens(tokens); -} diff --git a/src/components/chat/flyoutmenu/FlyoutSubMenu.tsx b/src/components/chat/input-menu/FlyoutSubMenu.tsx similarity index 100% rename from src/components/chat/flyoutmenu/FlyoutSubMenu.tsx rename to src/components/chat/input-menu/FlyoutSubMenu.tsx diff --git a/src/components/chat/flyoutmenu/InputMenu.tsx b/src/components/chat/input-menu/InputMenu.tsx similarity index 97% rename from src/components/chat/flyoutmenu/InputMenu.tsx rename to src/components/chat/input-menu/InputMenu.tsx index bc110a8..dfcb4e1 100644 --- a/src/components/chat/flyoutmenu/InputMenu.tsx +++ b/src/components/chat/input-menu/InputMenu.tsx @@ -20,8 +20,8 @@ import clientChatStore from "../../../stores/ClientChatStore"; import FlyoutSubMenu from "./FlyoutSubMenu"; import { useIsMobile } from "../../contexts/MobileContext"; import { useIsMobile as useIsMobileUserAgent } from "../../../layout/_IsMobileHook"; -import { getModelFamily, SUPPORTED_MODELS } from "../SupportedModels"; -import { formatConversationMarkdown } from "../exportConversationAsMarkdown"; +import { getModelFamily, SUPPORTED_MODELS } from "../lib/SupportedModels"; +import { formatConversationMarkdown } from "../lib/exportConversationAsMarkdown"; export const MsM_commonButtonStyles = { bg: "transparent", diff --git a/src/components/chat/ChatInput.tsx b/src/components/chat/input/ChatInput.tsx similarity index 94% rename from src/components/chat/ChatInput.tsx rename to src/components/chat/input/ChatInput.tsx index cce9925..09ff6d6 100644 --- a/src/components/chat/ChatInput.tsx +++ b/src/components/chat/input/ChatInput.tsx @@ -7,12 +7,12 @@ import { useBreakpointValue, } from "@chakra-ui/react"; import { observer } from "mobx-react-lite"; -import chatStore from "../../stores/ClientChatStore"; -import InputMenu from "./flyoutmenu/InputMenu"; +import chatStore from "../../../stores/ClientChatStore"; +import InputMenu from "../input-menu/InputMenu"; import InputTextarea from "./ChatInputTextArea"; import SendButton from "./ChatInputSendButton"; -import { useMaxWidth } from "../../layout/useMaxWidth"; -import userOptionsStore from "../../stores/UserOptionsStore"; +import { useMaxWidth } from "../../../layout/useMaxWidth"; +import userOptionsStore from "../../../stores/UserOptionsStore"; const ChatInput = observer(() => { const inputRef = useRef(null); diff --git a/src/components/chat/ChatInputSendButton.tsx b/src/components/chat/input/ChatInputSendButton.tsx similarity index 95% rename from src/components/chat/ChatInputSendButton.tsx rename to src/components/chat/input/ChatInputSendButton.tsx index bea951b..8b9cbb3 100644 --- a/src/components/chat/ChatInputSendButton.tsx +++ b/src/components/chat/input/ChatInputSendButton.tsx @@ -1,6 +1,6 @@ import React from "react"; import { Button } from "@chakra-ui/react"; -import clientChatStore from "../../stores/ClientChatStore"; +import clientChatStore from "../../../stores/ClientChatStore"; import { CirclePause, Send } from "lucide-react"; import { motion } from "framer-motion"; diff --git a/src/components/chat/ChatInputTextArea.tsx b/src/components/chat/input/ChatInputTextArea.tsx similarity index 100% rename from src/components/chat/ChatInputTextArea.tsx rename to src/components/chat/input/ChatInputTextArea.tsx diff --git a/src/components/chat/katex.css b/src/components/chat/katex.css deleted file mode 100644 index b47e54e..0000000 --- a/src/components/chat/katex.css +++ /dev/null @@ -1,1273 +0,0 @@ -/* stylelint-disable font-family-no-missing-generic-family-keyword */ -@font-face { - font-family: "KaTeX_AMS"; - src: - url(static/fonts/KaTeX_AMS-Regular.woff2) format("woff2"), - url(static/fonts/KaTeX_AMS-Regular.woff) format("woff"), - url(static/fonts/KaTeX_AMS-Regular.ttf) format("truetype"); - font-weight: normal; - font-style: normal; -} -@font-face { - font-family: "KaTeX_Caligraphic"; - src: - url(static/fonts/KaTeX_Caligraphic-Bold.woff2) format("woff2"), - url(static/fonts/KaTeX_Caligraphic-Bold.woff) format("woff"), - url(static/fonts/KaTeX_Caligraphic-Bold.ttf) format("truetype"); - font-weight: bold; - font-style: normal; -} -@font-face { - font-family: "KaTeX_Caligraphic"; - src: - url(static/fonts/KaTeX_Caligraphic-Regular.woff2) format("woff2"), - url(static/fonts/KaTeX_Caligraphic-Regular.woff) format("woff"), - url(static/fonts/KaTeX_Caligraphic-Regular.ttf) format("truetype"); - font-weight: normal; - font-style: normal; -} -@font-face { - font-family: "KaTeX_Fraktur"; - src: - url(static/fonts/KaTeX_Fraktur-Bold.woff2) format("woff2"), - url(static/fonts/KaTeX_Fraktur-Bold.woff) format("woff"), - url(static/fonts/KaTeX_Fraktur-Bold.ttf) format("truetype"); - font-weight: bold; - font-style: normal; -} -@font-face { - font-family: "KaTeX_Fraktur"; - src: - url(static/fonts/KaTeX_Fraktur-Regular.woff2) format("woff2"), - url(static/fonts/KaTeX_Fraktur-Regular.woff) format("woff"), - url(static/fonts/KaTeX_Fraktur-Regular.ttf) format("truetype"); - font-weight: normal; - font-style: normal; -} -@font-face { - font-family: "KaTeX_Main"; - src: - url(static/fonts/KaTeX_Main-Bold.woff2) format("woff2"), - url(static/fonts/KaTeX_Main-Bold.woff) format("woff"), - url(static/fonts/KaTeX_Main-Bold.ttf) format("truetype"); - font-weight: bold; - font-style: normal; -} -@font-face { - font-family: "KaTeX_Main"; - src: - url(static/fonts/KaTeX_Main-BoldItalic.woff2) format("woff2"), - url(static/fonts/KaTeX_Main-BoldItalic.woff) format("woff"), - url(static/fonts/KaTeX_Main-BoldItalic.ttf) format("truetype"); - font-weight: bold; - font-style: italic; -} -@font-face { - font-family: "KaTeX_Main"; - src: - url(static/fonts/KaTeX_Main-Italic.woff2) format("woff2"), - url(static/fonts/KaTeX_Main-Italic.woff) format("woff"), - url(static/fonts/KaTeX_Main-Italic.ttf) format("truetype"); - font-weight: normal; - font-style: italic; -} -@font-face { - font-family: "KaTeX_Main"; - src: - url(static/fonts/KaTeX_Main-Regular.woff2) format("woff2"), - url(static/fonts/KaTeX_Main-Regular.woff) format("woff"), - url(static/fonts/KaTeX_Main-Regular.ttf) format("truetype"); - font-weight: normal; - font-style: normal; -} -@font-face { - font-family: "KaTeX_Math"; - src: - url(static/fonts/KaTeX_Math-BoldItalic.woff2) format("woff2"), - url(static/fonts/KaTeX_Math-BoldItalic.woff) format("woff"), - url(static/fonts/KaTeX_Math-BoldItalic.ttf) format("truetype"); - font-weight: bold; - font-style: italic; -} -@font-face { - font-family: "KaTeX_Math"; - src: - url(static/fonts/KaTeX_Math-Italic.woff2) format("woff2"), - url(static/fonts/KaTeX_Math-Italic.woff) format("woff"), - url(static/fonts/KaTeX_Math-Italic.ttf) format("truetype"); - font-weight: normal; - font-style: italic; -} -@font-face { - font-family: "KaTeX_SansSerif"; - src: - url(static/fonts/KaTeX_SansSerif-Bold.woff2) format("woff2"), - url(static/fonts/KaTeX_SansSerif-Bold.woff) format("woff"), - url(static/fonts/KaTeX_SansSerif-Bold.ttf) format("truetype"); - font-weight: bold; - font-style: normal; -} -@font-face { - font-family: "KaTeX_SansSerif"; - src: - url(static/fonts/KaTeX_SansSerif-Italic.woff2) format("woff2"), - url(static/fonts/KaTeX_SansSerif-Italic.woff) format("woff"), - url(static/fonts/KaTeX_SansSerif-Italic.ttf) format("truetype"); - font-weight: normal; - font-style: italic; -} -@font-face { - font-family: "KaTeX_SansSerif"; - src: - url(static/fonts/KaTeX_SansSerif-Regular.woff2) format("woff2"), - url(static/fonts/KaTeX_SansSerif-Regular.woff) format("woff"), - url(static/fonts/KaTeX_SansSerif-Regular.ttf) format("truetype"); - font-weight: normal; - font-style: normal; -} -@font-face { - font-family: "KaTeX_Script"; - src: - url(static/fonts/KaTeX_Script-Regular.woff2) format("woff2"), - url(static/fonts/KaTeX_Script-Regular.woff) format("woff"), - url(static/fonts/KaTeX_Script-Regular.ttf) format("truetype"); - font-weight: normal; - font-style: normal; -} -@font-face { - font-family: "KaTeX_Size1"; - src: - url(static/fonts/KaTeX_Size1-Regular.woff2) format("woff2"), - url(static/fonts/KaTeX_Size1-Regular.woff) format("woff"), - url(static/fonts/KaTeX_Size1-Regular.ttf) format("truetype"); - font-weight: normal; - font-style: normal; -} -@font-face { - font-family: "KaTeX_Size2"; - src: - url(static/fonts/KaTeX_Size2-Regular.woff2) format("woff2"), - url(static/fonts/KaTeX_Size2-Regular.woff) format("woff"), - url(static/fonts/KaTeX_Size2-Regular.ttf) format("truetype"); - font-weight: normal; - font-style: normal; -} -@font-face { - font-family: "KaTeX_Size3"; - src: - url(static/fonts/KaTeX_Size3-Regular.woff2) format("woff2"), - url(static/fonts/KaTeX_Size3-Regular.woff) format("woff"), - url(static/fonts/KaTeX_Size3-Regular.ttf) format("truetype"); - font-weight: normal; - font-style: normal; -} -@font-face { - font-family: "KaTeX_Size4"; - src: - url(static/fonts/KaTeX_Size4-Regular.woff2) format("woff2"), - url(static/fonts/KaTeX_Size4-Regular.woff) format("woff"), - url(static/fonts/KaTeX_Size4-Regular.ttf) format("truetype"); - font-weight: normal; - font-style: normal; -} -@font-face { - font-family: "KaTeX_Typewriter"; - src: - url(static/fonts/KaTeX_Typewriter-Regular.woff2) format("woff2"), - url(static/fonts/KaTeX_Typewriter-Regular.woff) format("woff"), - url(fonts/KaTeX_Typewriter-Regular.ttf) format("truetype"); - font-weight: normal; - font-style: normal; -} -.katex { - font: - normal 1.21em KaTeX_Main, - Times New Roman, - serif; - line-height: 1.2; - text-indent: 0; - text-rendering: auto; -} -.katex * { - -ms-high-contrast-adjust: none !important; -} -.katex * { - border-color: currentColor; -} -.katex .katex-version::after { - content: "0.16.11"; -} -.katex .katex-mathml { - /* Accessibility hack to only show to screen readers - Found at: http://a11yproject.com/posts/how-to-hide-content/ */ - position: absolute; - clip: rect(1px, 1px, 1px, 1px); - padding: 0; - border: 0; - height: 1px; - width: 1px; - overflow: hidden; -} -.katex .katex-html { - /* \newline is an empty block at top level, between .base elements */ -} -.katex .katex-html > .newline { - display: block; -} -.katex .base { - position: relative; - display: inline-block; - white-space: nowrap; - width: -webkit-min-content; - width: -moz-min-content; - width: min-content; -} -.katex .strut { - display: inline-block; -} -.katex .textbf { - font-weight: bold; -} -.katex .textit { - font-style: italic; -} -.katex .textrm { - font-family: KaTeX_Main; -} -.katex .textsf { - font-family: KaTeX_SansSerif; -} -.katex .texttt { - font-family: KaTeX_Typewriter; -} -.katex .mathnormal { - font-family: KaTeX_Math; - font-style: italic; -} -.katex .mathit { - font-family: KaTeX_Main; - font-style: italic; -} -.katex .mathrm { - font-style: normal; -} -.katex .mathbf { - font-family: KaTeX_Main; - font-weight: bold; -} -.katex .boldsymbol { - font-family: KaTeX_Math; - font-weight: bold; - font-style: italic; -} -.katex .amsrm { - font-family: KaTeX_AMS; -} -.katex .mathbb, -.katex .textbb { - font-family: KaTeX_AMS; -} -.katex .mathcal { - font-family: KaTeX_Caligraphic; -} -.katex .mathfrak, -.katex .textfrak { - font-family: KaTeX_Fraktur; -} -.katex .mathboldfrak, -.katex .textboldfrak { - font-family: KaTeX_Fraktur; - font-weight: bold; -} -.katex .mathtt { - font-family: KaTeX_Typewriter; -} -.katex .mathscr, -.katex .textscr { - font-family: KaTeX_Script; -} -.katex .mathsf, -.katex .textsf { - font-family: KaTeX_SansSerif; -} -.katex .mathboldsf, -.katex .textboldsf { - font-family: KaTeX_SansSerif; - font-weight: bold; -} -.katex .mathitsf, -.katex .textitsf { - font-family: KaTeX_SansSerif; - font-style: italic; -} -.katex .mainrm { - font-family: KaTeX_Main; - font-style: normal; -} -.katex .vlist-t { - display: inline-table; - table-layout: fixed; - border-collapse: collapse; -} -.katex .vlist-r { - display: table-row; -} -.katex .vlist { - display: table-cell; - vertical-align: bottom; - position: relative; -} -.katex .vlist > span { - display: block; - height: 0; - position: relative; -} -.katex .vlist > span > span { - display: inline-block; -} -.katex .vlist > span > .pstrut { - overflow: hidden; - width: 0; -} -.katex .vlist-t2 { - margin-right: -2px; -} -.katex .vlist-s { - display: table-cell; - vertical-align: bottom; - font-size: 1px; - width: 2px; - min-width: 2px; -} -.katex .vbox { - display: inline-flex; - flex-direction: column; - align-items: baseline; -} -.katex .hbox { - display: inline-flex; - flex-direction: row; - width: 100%; -} -.katex .thinbox { - display: inline-flex; - flex-direction: row; - width: 0; - max-width: 0; -} -.katex .msupsub { - text-align: left; -} -.katex .mfrac > span > span { - text-align: center; -} -.katex .mfrac .frac-line { - display: inline-block; - width: 100%; - border-bottom-style: solid; -} -.katex .mfrac .frac-line, -.katex .overline .overline-line, -.katex .underline .underline-line, -.katex .hline, -.katex .hdashline, -.katex .rule { - min-height: 1px; -} -.katex .mspace { - display: inline-block; -} -.katex .llap, -.katex .rlap, -.katex .clap { - width: 0; - position: relative; -} -.katex .llap > .inner, -.katex .rlap > .inner, -.katex .clap > .inner { - position: absolute; -} -.katex .llap > .fix, -.katex .rlap > .fix, -.katex .clap > .fix { - display: inline-block; -} -.katex .llap > .inner { - right: 0; -} -.katex .rlap > .inner, -.katex .clap > .inner { - left: 0; -} -.katex .clap > .inner > span { - margin-left: -50%; - margin-right: 50%; -} -.katex .rule { - display: inline-block; - border: solid 0; - position: relative; -} -.katex .overline .overline-line, -.katex .underline .underline-line, -.katex .hline { - display: inline-block; - width: 100%; - border-bottom-style: solid; -} -.katex .hdashline { - display: inline-block; - width: 100%; - border-bottom-style: dashed; -} -.katex .sqrt > .root { - /* These values are taken from the definition of `\r@@t`, - `\mkern 5mu` and `\mkern -10mu`. */ - margin-left: 0.2777777778em; - margin-right: -0.5555555556em; -} -.katex .sizing.reset-size1.size1, -.katex .fontsize-ensurer.reset-size1.size1 { - /* stylelint-disable-next-line */ - font-size: 1em; -} -.katex .sizing.reset-size1.size2, -.katex .fontsize-ensurer.reset-size1.size2 { - /* stylelint-disable-next-line */ - font-size: 1.2em; -} -.katex .sizing.reset-size1.size3, -.katex .fontsize-ensurer.reset-size1.size3 { - /* stylelint-disable-next-line */ - font-size: 1.4em; -} -.katex .sizing.reset-size1.size4, -.katex .fontsize-ensurer.reset-size1.size4 { - /* stylelint-disable-next-line */ - font-size: 1.6em; -} -.katex .sizing.reset-size1.size5, -.katex .fontsize-ensurer.reset-size1.size5 { - /* stylelint-disable-next-line */ - font-size: 1.8em; -} -.katex .sizing.reset-size1.size6, -.katex .fontsize-ensurer.reset-size1.size6 { - /* stylelint-disable-next-line */ - font-size: 2em; -} -.katex .sizing.reset-size1.size7, -.katex .fontsize-ensurer.reset-size1.size7 { - /* stylelint-disable-next-line */ - font-size: 2.4em; -} -.katex .sizing.reset-size1.size8, -.katex .fontsize-ensurer.reset-size1.size8 { - /* stylelint-disable-next-line */ - font-size: 2.88em; -} -.katex .sizing.reset-size1.size9, -.katex .fontsize-ensurer.reset-size1.size9 { - /* stylelint-disable-next-line */ - font-size: 3.456em; -} -.katex .sizing.reset-size1.size10, -.katex .fontsize-ensurer.reset-size1.size10 { - /* stylelint-disable-next-line */ - font-size: 4.148em; -} -.katex .sizing.reset-size1.size11, -.katex .fontsize-ensurer.reset-size1.size11 { - /* stylelint-disable-next-line */ - font-size: 4.976em; -} -.katex .sizing.reset-size2.size1, -.katex .fontsize-ensurer.reset-size2.size1 { - /* stylelint-disable-next-line */ - font-size: 0.8333333333em; -} -.katex .sizing.reset-size2.size2, -.katex .fontsize-ensurer.reset-size2.size2 { - /* stylelint-disable-next-line */ - font-size: 1em; -} -.katex .sizing.reset-size2.size3, -.katex .fontsize-ensurer.reset-size2.size3 { - /* stylelint-disable-next-line */ - font-size: 1.1666666667em; -} -.katex .sizing.reset-size2.size4, -.katex .fontsize-ensurer.reset-size2.size4 { - /* stylelint-disable-next-line */ - font-size: 1.3333333333em; -} -.katex .sizing.reset-size2.size5, -.katex .fontsize-ensurer.reset-size2.size5 { - /* stylelint-disable-next-line */ - font-size: 1.5em; -} -.katex .sizing.reset-size2.size6, -.katex .fontsize-ensurer.reset-size2.size6 { - /* stylelint-disable-next-line */ - font-size: 1.6666666667em; -} -.katex .sizing.reset-size2.size7, -.katex .fontsize-ensurer.reset-size2.size7 { - /* stylelint-disable-next-line */ - font-size: 2em; -} -.katex .sizing.reset-size2.size8, -.katex .fontsize-ensurer.reset-size2.size8 { - /* stylelint-disable-next-line */ - font-size: 2.4em; -} -.katex .sizing.reset-size2.size9, -.katex .fontsize-ensurer.reset-size2.size9 { - /* stylelint-disable-next-line */ - font-size: 2.88em; -} -.katex .sizing.reset-size2.size10, -.katex .fontsize-ensurer.reset-size2.size10 { - /* stylelint-disable-next-line */ - font-size: 3.4566666667em; -} -.katex .sizing.reset-size2.size11, -.katex .fontsize-ensurer.reset-size2.size11 { - /* stylelint-disable-next-line */ - font-size: 4.1466666667em; -} -.katex .sizing.reset-size3.size1, -.katex .fontsize-ensurer.reset-size3.size1 { - /* stylelint-disable-next-line */ - font-size: 0.7142857143em; -} -.katex .sizing.reset-size3.size2, -.katex .fontsize-ensurer.reset-size3.size2 { - /* stylelint-disable-next-line */ - font-size: 0.8571428571em; -} -.katex .sizing.reset-size3.size3, -.katex .fontsize-ensurer.reset-size3.size3 { - /* stylelint-disable-next-line */ - font-size: 1em; -} -.katex .sizing.reset-size3.size4, -.katex .fontsize-ensurer.reset-size3.size4 { - /* stylelint-disable-next-line */ - font-size: 1.1428571429em; -} -.katex .sizing.reset-size3.size5, -.katex .fontsize-ensurer.reset-size3.size5 { - /* stylelint-disable-next-line */ - font-size: 1.2857142857em; -} -.katex .sizing.reset-size3.size6, -.katex .fontsize-ensurer.reset-size3.size6 { - /* stylelint-disable-next-line */ - font-size: 1.4285714286em; -} -.katex .sizing.reset-size3.size7, -.katex .fontsize-ensurer.reset-size3.size7 { - /* stylelint-disable-next-line */ - font-size: 1.7142857143em; -} -.katex .sizing.reset-size3.size8, -.katex .fontsize-ensurer.reset-size3.size8 { - /* stylelint-disable-next-line */ - font-size: 2.0571428571em; -} -.katex .sizing.reset-size3.size9, -.katex .fontsize-ensurer.reset-size3.size9 { - /* stylelint-disable-next-line */ - font-size: 2.4685714286em; -} -.katex .sizing.reset-size3.size10, -.katex .fontsize-ensurer.reset-size3.size10 { - /* stylelint-disable-next-line */ - font-size: 2.9628571429em; -} -.katex .sizing.reset-size3.size11, -.katex .fontsize-ensurer.reset-size3.size11 { - /* stylelint-disable-next-line */ - font-size: 3.5542857143em; -} -.katex .sizing.reset-size4.size1, -.katex .fontsize-ensurer.reset-size4.size1 { - /* stylelint-disable-next-line */ - font-size: 0.625em; -} -.katex .sizing.reset-size4.size2, -.katex .fontsize-ensurer.reset-size4.size2 { - /* stylelint-disable-next-line */ - font-size: 0.75em; -} -.katex .sizing.reset-size4.size3, -.katex .fontsize-ensurer.reset-size4.size3 { - /* stylelint-disable-next-line */ - font-size: 0.875em; -} -.katex .sizing.reset-size4.size4, -.katex .fontsize-ensurer.reset-size4.size4 { - /* stylelint-disable-next-line */ - font-size: 1em; -} -.katex .sizing.reset-size4.size5, -.katex .fontsize-ensurer.reset-size4.size5 { - /* stylelint-disable-next-line */ - font-size: 1.125em; -} -.katex .sizing.reset-size4.size6, -.katex .fontsize-ensurer.reset-size4.size6 { - /* stylelint-disable-next-line */ - font-size: 1.25em; -} -.katex .sizing.reset-size4.size7, -.katex .fontsize-ensurer.reset-size4.size7 { - /* stylelint-disable-next-line */ - font-size: 1.5em; -} -.katex .sizing.reset-size4.size8, -.katex .fontsize-ensurer.reset-size4.size8 { - /* stylelint-disable-next-line */ - font-size: 1.8em; -} -.katex .sizing.reset-size4.size9, -.katex .fontsize-ensurer.reset-size4.size9 { - /* stylelint-disable-next-line */ - font-size: 2.16em; -} -.katex .sizing.reset-size4.size10, -.katex .fontsize-ensurer.reset-size4.size10 { - /* stylelint-disable-next-line */ - font-size: 2.5925em; -} -.katex .sizing.reset-size4.size11, -.katex .fontsize-ensurer.reset-size4.size11 { - /* stylelint-disable-next-line */ - font-size: 3.11em; -} -.katex .sizing.reset-size5.size1, -.katex .fontsize-ensurer.reset-size5.size1 { - /* stylelint-disable-next-line */ - font-size: 0.5555555556em; -} -.katex .sizing.reset-size5.size2, -.katex .fontsize-ensurer.reset-size5.size2 { - /* stylelint-disable-next-line */ - font-size: 0.6666666667em; -} -.katex .sizing.reset-size5.size3, -.katex .fontsize-ensurer.reset-size5.size3 { - /* stylelint-disable-next-line */ - font-size: 0.7777777778em; -} -.katex .sizing.reset-size5.size4, -.katex .fontsize-ensurer.reset-size5.size4 { - /* stylelint-disable-next-line */ - font-size: 0.8888888889em; -} -.katex .sizing.reset-size5.size5, -.katex .fontsize-ensurer.reset-size5.size5 { - /* stylelint-disable-next-line */ - font-size: 1em; -} -.katex .sizing.reset-size5.size6, -.katex .fontsize-ensurer.reset-size5.size6 { - /* stylelint-disable-next-line */ - font-size: 1.1111111111em; -} -.katex .sizing.reset-size5.size7, -.katex .fontsize-ensurer.reset-size5.size7 { - /* stylelint-disable-next-line */ - font-size: 1.3333333333em; -} -.katex .sizing.reset-size5.size8, -.katex .fontsize-ensurer.reset-size5.size8 { - /* stylelint-disable-next-line */ - font-size: 1.6em; -} -.katex .sizing.reset-size5.size9, -.katex .fontsize-ensurer.reset-size5.size9 { - /* stylelint-disable-next-line */ - font-size: 1.92em; -} -.katex .sizing.reset-size5.size10, -.katex .fontsize-ensurer.reset-size5.size10 { - /* stylelint-disable-next-line */ - font-size: 2.3044444444em; -} -.katex .sizing.reset-size5.size11, -.katex .fontsize-ensurer.reset-size5.size11 { - /* stylelint-disable-next-line */ - font-size: 2.7644444444em; -} -.katex .sizing.reset-size6.size1, -.katex .fontsize-ensurer.reset-size6.size1 { - /* stylelint-disable-next-line */ - font-size: 0.5em; -} -.katex .sizing.reset-size6.size2, -.katex .fontsize-ensurer.reset-size6.size2 { - /* stylelint-disable-next-line */ - font-size: 0.6em; -} -.katex .sizing.reset-size6.size3, -.katex .fontsize-ensurer.reset-size6.size3 { - /* stylelint-disable-next-line */ - font-size: 0.7em; -} -.katex .sizing.reset-size6.size4, -.katex .fontsize-ensurer.reset-size6.size4 { - /* stylelint-disable-next-line */ - font-size: 0.8em; -} -.katex .sizing.reset-size6.size5, -.katex .fontsize-ensurer.reset-size6.size5 { - /* stylelint-disable-next-line */ - font-size: 0.9em; -} -.katex .sizing.reset-size6.size6, -.katex .fontsize-ensurer.reset-size6.size6 { - /* stylelint-disable-next-line */ - font-size: 1em; -} -.katex .sizing.reset-size6.size7, -.katex .fontsize-ensurer.reset-size6.size7 { - /* stylelint-disable-next-line */ - font-size: 1.2em; -} -.katex .sizing.reset-size6.size8, -.katex .fontsize-ensurer.reset-size6.size8 { - /* stylelint-disable-next-line */ - font-size: 1.44em; -} -.katex .sizing.reset-size6.size9, -.katex .fontsize-ensurer.reset-size6.size9 { - /* stylelint-disable-next-line */ - font-size: 1.728em; -} -.katex .sizing.reset-size6.size10, -.katex .fontsize-ensurer.reset-size6.size10 { - /* stylelint-disable-next-line */ - font-size: 2.074em; -} -.katex .sizing.reset-size6.size11, -.katex .fontsize-ensurer.reset-size6.size11 { - /* stylelint-disable-next-line */ - font-size: 2.488em; -} -.katex .sizing.reset-size7.size1, -.katex .fontsize-ensurer.reset-size7.size1 { - /* stylelint-disable-next-line */ - font-size: 0.4166666667em; -} -.katex .sizing.reset-size7.size2, -.katex .fontsize-ensurer.reset-size7.size2 { - /* stylelint-disable-next-line */ - font-size: 0.5em; -} -.katex .sizing.reset-size7.size3, -.katex .fontsize-ensurer.reset-size7.size3 { - /* stylelint-disable-next-line */ - font-size: 0.5833333333em; -} -.katex .sizing.reset-size7.size4, -.katex .fontsize-ensurer.reset-size7.size4 { - /* stylelint-disable-next-line */ - font-size: 0.6666666667em; -} -.katex .sizing.reset-size7.size5, -.katex .fontsize-ensurer.reset-size7.size5 { - /* stylelint-disable-next-line */ - font-size: 0.75em; -} -.katex .sizing.reset-size7.size6, -.katex .fontsize-ensurer.reset-size7.size6 { - /* stylelint-disable-next-line */ - font-size: 0.8333333333em; -} -.katex .sizing.reset-size7.size7, -.katex .fontsize-ensurer.reset-size7.size7 { - /* stylelint-disable-next-line */ - font-size: 1em; -} -.katex .sizing.reset-size7.size8, -.katex .fontsize-ensurer.reset-size7.size8 { - /* stylelint-disable-next-line */ - font-size: 1.2em; -} -.katex .sizing.reset-size7.size9, -.katex .fontsize-ensurer.reset-size7.size9 { - /* stylelint-disable-next-line */ - font-size: 1.44em; -} -.katex .sizing.reset-size7.size10, -.katex .fontsize-ensurer.reset-size7.size10 { - /* stylelint-disable-next-line */ - font-size: 1.7283333333em; -} -.katex .sizing.reset-size7.size11, -.katex .fontsize-ensurer.reset-size7.size11 { - /* stylelint-disable-next-line */ - font-size: 2.0733333333em; -} -.katex .sizing.reset-size8.size1, -.katex .fontsize-ensurer.reset-size8.size1 { - /* stylelint-disable-next-line */ - font-size: 0.3472222222em; -} -.katex .sizing.reset-size8.size2, -.katex .fontsize-ensurer.reset-size8.size2 { - /* stylelint-disable-next-line */ - font-size: 0.4166666667em; -} -.katex .sizing.reset-size8.size3, -.katex .fontsize-ensurer.reset-size8.size3 { - /* stylelint-disable-next-line */ - font-size: 0.4861111111em; -} -.katex .sizing.reset-size8.size4, -.katex .fontsize-ensurer.reset-size8.size4 { - /* stylelint-disable-next-line */ - font-size: 0.5555555556em; -} -.katex .sizing.reset-size8.size5, -.katex .fontsize-ensurer.reset-size8.size5 { - /* stylelint-disable-next-line */ - font-size: 0.625em; -} -.katex .sizing.reset-size8.size6, -.katex .fontsize-ensurer.reset-size8.size6 { - /* stylelint-disable-next-line */ - font-size: 0.6944444444em; -} -.katex .sizing.reset-size8.size7, -.katex .fontsize-ensurer.reset-size8.size7 { - /* stylelint-disable-next-line */ - font-size: 0.8333333333em; -} -.katex .sizing.reset-size8.size8, -.katex .fontsize-ensurer.reset-size8.size8 { - /* stylelint-disable-next-line */ - font-size: 1em; -} -.katex .sizing.reset-size8.size9, -.katex .fontsize-ensurer.reset-size8.size9 { - /* stylelint-disable-next-line */ - font-size: 1.2em; -} -.katex .sizing.reset-size8.size10, -.katex .fontsize-ensurer.reset-size8.size10 { - /* stylelint-disable-next-line */ - font-size: 1.4402777778em; -} -.katex .sizing.reset-size8.size11, -.katex .fontsize-ensurer.reset-size8.size11 { - /* stylelint-disable-next-line */ - font-size: 1.7277777778em; -} -.katex .sizing.reset-size9.size1, -.katex .fontsize-ensurer.reset-size9.size1 { - /* stylelint-disable-next-line */ - font-size: 0.2893518519em; -} -.katex .sizing.reset-size9.size2, -.katex .fontsize-ensurer.reset-size9.size2 { - /* stylelint-disable-next-line */ - font-size: 0.3472222222em; -} -.katex .sizing.reset-size9.size3, -.katex .fontsize-ensurer.reset-size9.size3 { - /* stylelint-disable-next-line */ - font-size: 0.4050925926em; -} -.katex .sizing.reset-size9.size4, -.katex .fontsize-ensurer.reset-size9.size4 { - /* stylelint-disable-next-line */ - font-size: 0.462962963em; -} -.katex .sizing.reset-size9.size5, -.katex .fontsize-ensurer.reset-size9.size5 { - /* stylelint-disable-next-line */ - font-size: 0.5208333333em; -} -.katex .sizing.reset-size9.size6, -.katex .fontsize-ensurer.reset-size9.size6 { - /* stylelint-disable-next-line */ - font-size: 0.5787037037em; -} -.katex .sizing.reset-size9.size7, -.katex .fontsize-ensurer.reset-size9.size7 { - /* stylelint-disable-next-line */ - font-size: 0.6944444444em; -} -.katex .sizing.reset-size9.size8, -.katex .fontsize-ensurer.reset-size9.size8 { - /* stylelint-disable-next-line */ - font-size: 0.8333333333em; -} -.katex .sizing.reset-size9.size9, -.katex .fontsize-ensurer.reset-size9.size9 { - /* stylelint-disable-next-line */ - font-size: 1em; -} -.katex .sizing.reset-size9.size10, -.katex .fontsize-ensurer.reset-size9.size10 { - /* stylelint-disable-next-line */ - font-size: 1.2002314815em; -} -.katex .sizing.reset-size9.size11, -.katex .fontsize-ensurer.reset-size9.size11 { - /* stylelint-disable-next-line */ - font-size: 1.4398148148em; -} -.katex .sizing.reset-size10.size1, -.katex .fontsize-ensurer.reset-size10.size1 { - /* stylelint-disable-next-line */ - font-size: 0.2410800386em; -} -.katex .sizing.reset-size10.size2, -.katex .fontsize-ensurer.reset-size10.size2 { - /* stylelint-disable-next-line */ - font-size: 0.2892960463em; -} -.katex .sizing.reset-size10.size3, -.katex .fontsize-ensurer.reset-size10.size3 { - /* stylelint-disable-next-line */ - font-size: 0.337512054em; -} -.katex .sizing.reset-size10.size4, -.katex .fontsize-ensurer.reset-size10.size4 { - /* stylelint-disable-next-line */ - font-size: 0.3857280617em; -} -.katex .sizing.reset-size10.size5, -.katex .fontsize-ensurer.reset-size10.size5 { - /* stylelint-disable-next-line */ - font-size: 0.4339440694em; -} -.katex .sizing.reset-size10.size6, -.katex .fontsize-ensurer.reset-size10.size6 { - /* stylelint-disable-next-line */ - font-size: 0.4821600771em; -} -.katex .sizing.reset-size10.size7, -.katex .fontsize-ensurer.reset-size10.size7 { - /* stylelint-disable-next-line */ - font-size: 0.5785920926em; -} -.katex .sizing.reset-size10.size8, -.katex .fontsize-ensurer.reset-size10.size8 { - /* stylelint-disable-next-line */ - font-size: 0.6943105111em; -} -.katex .sizing.reset-size10.size9, -.katex .fontsize-ensurer.reset-size10.size9 { - /* stylelint-disable-next-line */ - font-size: 0.8331726133em; -} -.katex .sizing.reset-size10.size10, -.katex .fontsize-ensurer.reset-size10.size10 { - /* stylelint-disable-next-line */ - font-size: 1em; -} -.katex .sizing.reset-size10.size11, -.katex .fontsize-ensurer.reset-size10.size11 { - /* stylelint-disable-next-line */ - font-size: 1.1996142719em; -} -.katex .sizing.reset-size11.size1, -.katex .fontsize-ensurer.reset-size11.size1 { - /* stylelint-disable-next-line */ - font-size: 0.2009646302em; -} -.katex .sizing.reset-size11.size2, -.katex .fontsize-ensurer.reset-size11.size2 { - /* stylelint-disable-next-line */ - font-size: 0.2411575563em; -} -.katex .sizing.reset-size11.size3, -.katex .fontsize-ensurer.reset-size11.size3 { - /* stylelint-disable-next-line */ - font-size: 0.2813504823em; -} -.katex .sizing.reset-size11.size4, -.katex .fontsize-ensurer.reset-size11.size4 { - /* stylelint-disable-next-line */ - font-size: 0.3215434084em; -} -.katex .sizing.reset-size11.size5, -.katex .fontsize-ensurer.reset-size11.size5 { - /* stylelint-disable-next-line */ - font-size: 0.3617363344em; -} -.katex .sizing.reset-size11.size6, -.katex .fontsize-ensurer.reset-size11.size6 { - /* stylelint-disable-next-line */ - font-size: 0.4019292605em; -} -.katex .sizing.reset-size11.size7, -.katex .fontsize-ensurer.reset-size11.size7 { - /* stylelint-disable-next-line */ - font-size: 0.4823151125em; -} -.katex .sizing.reset-size11.size8, -.katex .fontsize-ensurer.reset-size11.size8 { - /* stylelint-disable-next-line */ - font-size: 0.578778135em; -} -.katex .sizing.reset-size11.size9, -.katex .fontsize-ensurer.reset-size11.size9 { - /* stylelint-disable-next-line */ - font-size: 0.6945337621em; -} -.katex .sizing.reset-size11.size10, -.katex .fontsize-ensurer.reset-size11.size10 { - /* stylelint-disable-next-line */ - font-size: 0.8336012862em; -} -.katex .sizing.reset-size11.size11, -.katex .fontsize-ensurer.reset-size11.size11 { - /* stylelint-disable-next-line */ - font-size: 1em; -} -.katex .delimsizing.size1 { - font-family: KaTeX_Size1; -} -.katex .delimsizing.size2 { - font-family: KaTeX_Size2; -} -.katex .delimsizing.size3 { - font-family: KaTeX_Size3; -} -.katex .delimsizing.size4 { - font-family: KaTeX_Size4; -} -.katex .delimsizing.mult .delim-size1 > span { - font-family: KaTeX_Size1; -} -.katex .delimsizing.mult .delim-size4 > span { - font-family: KaTeX_Size4; -} -.katex .nulldelimiter { - display: inline-block; - width: 0.12em; -} -.katex .delimcenter { - position: relative; -} -.katex .op-symbol { - position: relative; -} -.katex .op-symbol.small-op { - font-family: KaTeX_Size1; -} -.katex .op-symbol.large-op { - font-family: KaTeX_Size2; -} -.katex .op-limits > .vlist-t { - text-align: center; -} -.katex .accent > .vlist-t { - text-align: center; -} -.katex .accent .accent-body { - position: relative; -} -.katex .accent .accent-body:not(.accent-full) { - width: 0; -} -.katex .overlay { - display: block; -} -.katex .mtable .vertical-separator { - display: inline-block; - min-width: 1px; -} -.katex .mtable .arraycolsep { - display: inline-block; -} -.katex .mtable .col-align-c > .vlist-t { - text-align: center; -} -.katex .mtable .col-align-l > .vlist-t { - text-align: left; -} -.katex .mtable .col-align-r > .vlist-t { - text-align: right; -} -.katex .svg-align { - text-align: left; -} -.katex svg { - display: block; - position: absolute; - width: 100%; - height: inherit; - fill: currentColor; - stroke: currentColor; - fill-rule: nonzero; - fill-opacity: 1; - stroke-width: 1; - stroke-linecap: butt; - stroke-linejoin: miter; - stroke-miterlimit: 4; - stroke-dasharray: none; - stroke-dashoffset: 0; - stroke-opacity: 1; -} -.katex svg path { - stroke: none; -} -.katex img { - border-style: none; - min-width: 0; - min-height: 0; - max-width: none; - max-height: none; -} -.katex .stretchy { - width: 100%; - display: block; - position: relative; - overflow: hidden; -} -.katex .stretchy::before, -.katex .stretchy::after { - content: ""; -} -.katex .hide-tail { - width: 100%; - position: relative; - overflow: hidden; -} -.katex .halfarrow-left { - position: absolute; - left: 0; - width: 50.2%; - overflow: hidden; -} -.katex .halfarrow-right { - position: absolute; - right: 0; - width: 50.2%; - overflow: hidden; -} -.katex .brace-left { - position: absolute; - left: 0; - width: 25.1%; - overflow: hidden; -} -.katex .brace-center { - position: absolute; - left: 25%; - width: 50%; - overflow: hidden; -} -.katex .brace-right { - position: absolute; - right: 0; - width: 25.1%; - overflow: hidden; -} -.katex .x-arrow-pad { - padding: 0 0.5em; -} -.katex .cd-arrow-pad { - padding: 0 0.55556em 0 0.27778em; -} -.katex .x-arrow, -.katex .mover, -.katex .munder { - text-align: center; -} -.katex .boxpad { - padding: 0 0.3em; -} -.katex .fbox, -.katex .fcolorbox { - box-sizing: border-box; - border: 0.04em solid; -} -.katex .cancel-pad { - padding: 0 0.2em; -} -.katex .cancel-lap { - margin-left: -0.2em; - margin-right: -0.2em; -} -.katex .sout { - border-bottom-style: solid; - border-bottom-width: 0.08em; -} -.katex .angl { - box-sizing: border-box; - border-top: 0.049em solid; - border-right: 0.049em solid; - margin-right: 0.03889em; -} -.katex .anglpad { - padding: 0 0.03889em; -} -.katex .eqn-num::before { - counter-increment: katexEqnNo; - content: "(" counter(katexEqnNo) ")"; -} -.katex .mml-eqn-num::before { - counter-increment: mmlEqnNo; - content: "(" counter(mmlEqnNo) ")"; -} -.katex .mtr-glue { - width: 50%; -} -.katex .cd-vert-arrow { - display: inline-block; - position: relative; -} -.katex .cd-label-left { - display: inline-block; - position: absolute; - right: calc(50% + 0.3em); - text-align: left; -} -.katex .cd-label-right { - display: inline-block; - position: absolute; - left: calc(50% + 0.3em); - text-align: right; -} - -.katex-display { - display: block; - margin: 1em 0; - text-align: center; -} -.katex-display > .katex { - display: block; - text-align: center; - white-space: nowrap; -} -.katex-display > .katex > .katex-html { - display: block; - position: relative; -} -.katex-display > .katex > .katex-html > .tag { - position: absolute; - right: 0; -} - -.katex-display.leqno > .katex > .katex-html > .tag { - left: 0; - right: auto; -} - -.katex-display.fleqn > .katex { - text-align: left; - padding-left: 2em; -} - -body { - counter-reset: katexEqnNo mmlEqnNo; -} diff --git a/src/components/chat/SupportedModels.ts b/src/components/chat/lib/SupportedModels.ts similarity index 100% rename from src/components/chat/SupportedModels.ts rename to src/components/chat/lib/SupportedModels.ts diff --git a/src/components/chat/domPurify.ts b/src/components/chat/lib/domPurify.ts similarity index 100% rename from src/components/chat/domPurify.ts rename to src/components/chat/lib/domPurify.ts diff --git a/src/components/chat/exportConversationAsMarkdown.ts b/src/components/chat/lib/exportConversationAsMarkdown.ts similarity index 88% rename from src/components/chat/exportConversationAsMarkdown.ts rename to src/components/chat/lib/exportConversationAsMarkdown.ts index 26c4827..c897e82 100644 --- a/src/components/chat/exportConversationAsMarkdown.ts +++ b/src/components/chat/lib/exportConversationAsMarkdown.ts @@ -1,5 +1,5 @@ // Function to generate a Markdown representation of the current conversation -import { type IMessage } from "../../stores/ClientChatStore"; +import { type IMessage } from "../../../stores/ClientChatStore"; import { Instance } from "mobx-state-tree"; export function formatConversationMarkdown( diff --git a/src/components/chat/ChatMessageContent.tsx b/src/components/chat/messages/ChatMessageContent.tsx similarity index 50% rename from src/components/chat/ChatMessageContent.tsx rename to src/components/chat/messages/ChatMessageContent.tsx index 768e56f..2531636 100644 --- a/src/components/chat/ChatMessageContent.tsx +++ b/src/components/chat/messages/ChatMessageContent.tsx @@ -1,9 +1,9 @@ import React from "react"; -import CustomMarkdownRenderer from "./CustomMarkdownRenderer"; +import MessageMarkdownRenderer from "./MessageMarkdownRenderer"; const ChatMessageContent = ({ content }) => { - return ; + return ; }; export default React.memo(ChatMessageContent); diff --git a/src/components/chat/ChatMessages.tsx b/src/components/chat/messages/ChatMessages.tsx similarity index 91% rename from src/components/chat/ChatMessages.tsx rename to src/components/chat/messages/ChatMessages.tsx index 0614b3c..1f166ae 100644 --- a/src/components/chat/ChatMessages.tsx +++ b/src/components/chat/messages/ChatMessages.tsx @@ -2,8 +2,8 @@ import React from "react"; import {Box, Grid, GridItem} from "@chakra-ui/react"; import MessageBubble from "./MessageBubble"; import {observer} from "mobx-react-lite"; -import chatStore from "../../stores/ClientChatStore"; -import {useIsMobile} from "../contexts/MobileContext"; +import chatStore from "../../../stores/ClientChatStore"; +import {useIsMobile} from "../../contexts/MobileContext"; interface ChatMessagesProps { scrollRef: React.RefObject; diff --git a/src/components/chat/MessageBubble.tsx b/src/components/chat/messages/MessageBubble.tsx similarity index 93% rename from src/components/chat/MessageBubble.tsx rename to src/components/chat/messages/MessageBubble.tsx index dd8938d..6501bff 100644 --- a/src/components/chat/MessageBubble.tsx +++ b/src/components/chat/messages/MessageBubble.tsx @@ -3,11 +3,10 @@ import { motion } from "framer-motion"; import { Box, Flex, Text } from "@chakra-ui/react"; import MessageRenderer from "./ChatMessageContent"; import { observer } from "mobx-react-lite"; -import { IntermediateStepsComponent } from "./IntermediateStepsComponent"; import MessageEditor from "./MessageEditorComponent"; import UserMessageTools from "./UserMessageTools"; -import clientChatStore from "../../stores/ClientChatStore"; -import UserOptionsStore from "../../stores/UserOptionsStore"; +import clientChatStore from "../../../stores/ClientChatStore"; +import UserOptionsStore from "../../../stores/UserOptionsStore"; const MotionBox = motion(Box); @@ -128,7 +127,6 @@ const MessageBubble = observer(({ msg, scrollRef }) => { }, }} > -
diff --git a/src/components/chat/ImageWithFallback.tsx b/src/components/markdown/ImageWithFallback.tsx similarity index 100% rename from src/components/chat/ImageWithFallback.tsx rename to src/components/markdown/ImageWithFallback.tsx diff --git a/src/components/markdown/MarkdownComponent.tsx b/src/components/markdown/MarkdownComponent.tsx new file mode 100644 index 0000000..51aab63 --- /dev/null +++ b/src/components/markdown/MarkdownComponent.tsx @@ -0,0 +1,576 @@ +import React from "react"; + +import { + Box, + Code, + Divider, + Heading, + Link, + List, + ListItem, + OrderedList, + Table, + Tbody, + Td, + Text, + Th, + Thead, + Tr, + useColorModeValue, +} from "@chakra-ui/react"; +import {marked} from "marked"; + +import markedKatex from "marked-katex-extension"; +import katex from "katex"; +import CodeBlock from "../code/CodeBlock"; +import ImageWithFallback from "./ImageWithFallback"; + +try { + if (localStorage) { + marked.use( + markedKatex({ + nonStandard: false, + displayMode: true, + throwOnError: false, + strict: true, + colorIsTextColor: true, + errorColor: "red", + }), + ); + } +} catch (_) { +} + +const MemoizedCodeBlock = React.memo(CodeBlock); + +const getHeadingProps = (depth: number) => { + switch (depth) { + case 1: + return {as: "h1", size: "xl", mt: 4, mb: 2}; + case 2: + return {as: "h2", size: "lg", mt: 3, mb: 2}; + case 3: + return {as: "h3", size: "md", mt: 2, mb: 1}; + case 4: + return {as: "h4", size: "sm", mt: 2, mb: 1}; + case 5: + return {as: "h5", size: "sm", mt: 2, mb: 1}; + case 6: + return {as: "h6", size: "xs", mt: 2, mb: 1}; + default: + return {as: `h${depth}`, size: "md", mt: 2, mb: 1}; + } +}; + +interface TableToken extends marked.Tokens.Table { + align: Array<"center" | "left" | "right" | null>; + header: (string | marked.Tokens.TableCell)[]; + rows: (string | marked.Tokens.TableCell)[][]; +} + +const CustomHeading: React.FC<{ text: string; depth: number }> = ({ + text, + depth, + }) => { + const headingProps = getHeadingProps(depth); + return ( + + {text} + + ); +}; + +const CustomParagraph: React.FC<{ children: React.ReactNode }> = ({ + children, + }) => { + return ( + + {children} + + ); +}; + +const CustomBlockquote: React.FC<{ children: React.ReactNode }> = ({ + children, + }) => { + return ( + + {children} + + ); +}; + +const CustomCodeBlock: React.FC<{ code: string; language?: string }> = ({ + code, + language, + }) => { + return ( + Promise.resolve()} + /> + ); +}; + +const CustomHr: React.FC = () => ; + +const CustomList: React.FC<{ + ordered?: boolean; + start?: number; + children: React.ReactNode; +}> = ({ordered, start, children}) => { + const commonStyles = { + fontSize: "sm", + wordBreak: "break-word" as const, + maxWidth: "100%" as const, + stylePosition: "outside" as const, + mb: 2, + pl: 4, + }; + + return ordered ? ( + + {children} + + ) : ( + + {children} + + ); +}; + +const CustomListItem: React.FC<{ + children: React.ReactNode; +}> = ({children}) => { + return {children}; +}; + +const CustomKatex: React.FC<{ math: string; displayMode: boolean }> = ({ + math, + displayMode, + }) => { + const renderedMath = katex.renderToString(math, {displayMode}); + + return ( + + ); +}; + +const CustomTable: React.FC<{ + header: React.ReactNode[]; + align: Array<"center" | "left" | "right" | null>; + rows: React.ReactNode[][]; +}> = ({header, align, rows}) => { + return ( + + + + {header.map((cell, i) => ( + + ))} + + + + {rows.map((row, rIndex) => ( + + {row.map((cell, cIndex) => ( + + ))} + + ))} + +
+ {cell} +
+ {cell} +
+ ); +}; + +const CustomHtmlBlock: React.FC<{ content: string }> = ({content}) => { + return ; +}; + +const CustomText: React.FC<{ text: React.ReactNode }> = ({text}) => { + return ( + + {text} + + ); +}; + +interface CustomStrongProps { + children: React.ReactNode; +} + +const CustomStrong: React.FC = ({children}) => { + return {children}; +}; + +const CustomEm: React.FC<{ children: React.ReactNode }> = ({children}) => { + return ( + + {children} + + ); +}; + +const CustomDel: React.FC<{ text: string }> = ({text}) => { + return ( + + {text} + + ); +}; + +const CustomCodeSpan: React.FC<{ code: string }> = ({code}) => { + const bg = useColorModeValue("gray.100", "gray.800"); + return ( + + {code} + + ); +}; + +const CustomMath: React.FC<{ math: string; displayMode?: boolean }> = ({ + math, + displayMode = false, + }) => { + return ( + + {math} + + ); +}; + +const CustomLink: React.FC<{ + href: string; + title?: string; + children: React.ReactNode; +}> = ({href, title, children, ...props}) => { + return ( + + {children} + + ); +}; + +const CustomImage: React.FC<{ href: string; text: string; title?: string }> = ({ + href, + text, + title, + }) => { + return ( + + ); +}; + +function parseTokens(tokens: marked.Token[]): JSX.Element[] { + const output: JSX.Element[] = []; + let blockquoteContent: JSX.Element[] = []; + + tokens.forEach((token, i) => { + switch (token.type) { + case "heading": + output.push( + , + ); + break; + + case "paragraph": { + const parsedContent = token.tokens + ? parseTokens(token.tokens) + : token.text; + if (blockquoteContent.length > 0) { + blockquoteContent.push( + {parsedContent}, + ); + } else { + output.push( + {parsedContent}, + ); + } + break; + } + case "br": + output.push(
); + break; + case "escape": { + break; + } + case "blockquote_start": + blockquoteContent = []; + break; + + case "blockquote_end": + output.push( + + {parseTokens(blockquoteContent)} + , + ); + blockquoteContent = []; + break; + case "blockquote": { + output.push( + + {token.tokens ? parseTokens(token.tokens) : null} + , + ); + break; + } + case "math": + output.push( + , + ); + break; + + case "inlineMath": + output.push( + , + ); + break; + case "inlineKatex": + case "blockKatex": { + const katexToken = token as any; + output.push( + , + ); + break; + } + case "code": + output.push( + , + ); + break; + + case "hr": + output.push(); + break; + case "list": { + const {ordered, start, items} = token; + const listItems = items.map((listItem, idx) => { + const nestedContent = parseTokens(listItem.tokens); + return {nestedContent}; + }); + + output.push( + + {listItems} + , + ); + break; + } + case "table": { + const tableToken = token as TableToken; + + output.push( + + typeof cell === "string" ? cell : parseTokens(cell.tokens || []), + )} + align={tableToken.align} + rows={tableToken.rows.map((row) => + row.map((cell) => + typeof cell === "string" + ? cell + : parseTokens(cell.tokens || []), + ), + )} + />, + ); + break; + } + case "html": + output.push(); + break; + case "def": + case "space": + break; + case "strong": + output.push( + + {parseTokens(token.tokens || [])} + , + ); + break; + case "em": + output.push( + + {token.tokens ? parseTokens(token.tokens) : token.text} + , + ); + break; + + case "codespan": + output.push(); + break; + + case "link": + output.push( + + {token.tokens ? parseTokens(token.tokens) : token.text} + , + ); + break; + + case "image": + output.push( + , + ); + break; + + case "text": { + const parsedContent = token.tokens + ? parseTokens(token.tokens) + : token.text; + + if (blockquoteContent.length > 0) { + blockquoteContent.push( + {parsedContent}, + ); + } else { + output.push(); + } + break; + } + + default: + console.warn("Unhandled token type:", token.type, token); + } + }); + + return output; +} + +export function renderMarkdown(markdown: string): JSX.Element[] { + marked.setOptions({ + breaks: true, + gfm: true, + silent: false, + async: true, + }); + + const tokens = marked.lexer(markdown); + return parseTokens(tokens); +} diff --git a/src/components/react-markdown/WebComponents.tsx b/src/components/react-markdown/WebComponents.tsx deleted file mode 100644 index 5c0c89a..0000000 --- a/src/components/react-markdown/WebComponents.tsx +++ /dev/null @@ -1,123 +0,0 @@ -import React from "react"; -import { - Box, - Divider, - Heading, - Link, - List, - ListItem, - OrderedList, - Text, - UnorderedList, -} from "@chakra-ui/react"; -import ImageWithFallback from "../chat/ImageWithFallback"; -import { MdCheckCircle } from "react-icons/md"; - -export const webComponents = { - p: ({ children }) => ( - - {children} - - ), - strong: ({ children }) => {children}, - h1: ({ children }) => ( - - {children} - - ), - h2: ({ children }) => ( - - {children} - - ), - h3: ({ children }) => ( - - {children} - - ), - h4: ({ children }) => ( - - {children} - - ), - ul: ({ children }) => ( - - {children} - - ), - - ol: ({ children }) => ( - - {children} - - ), - li: ({ children, ...rest }) => { - const filteredChildren = React.Children.toArray(children) - .filter((child) => !(typeof child === "string" && child.trim() === "\n")) - .map((child, index, array) => { - // if (typeof child === 'string' && index === array.length - 1 && /\n/.test(child)) { - // return '\n'; - // } - return child; - }); - - return {filteredChildren}; - }, - pre: ({ children }) => ( - - {children} - - ), - - blockquote: ({ children }) => ( - - {children} - - ), - hr: () => , - a: ({ href, children }) => ( - - {children} - - ), - img: ({ alt, src }) => , - icon_list: ({ children }) => ( - - {React.Children.map(children, (child) => ( - - - {child} - - ))} - - ), -}; diff --git a/src/pages/index/+Page.tsx b/src/pages/index/+Page.tsx index 05e0e48..d862374 100644 --- a/src/pages/index/+Page.tsx +++ b/src/pages/index/+Page.tsx @@ -2,7 +2,7 @@ import React, { useEffect } from "react"; import { Stack } from "@chakra-ui/react"; import Chat from "../../components/chat/Chat"; import clientChatStore from "../../stores/ClientChatStore"; -import { getModelFamily } from "../../components/chat/SupportedModels"; +import { getModelFamily } from "../../components/chat/lib/SupportedModels"; // renders "/" export default function IndexPage() { diff --git a/workers/site/sdk/chat-sdk.ts b/workers/site/sdk/chat-sdk.ts index f1c2a7a..0b55993 100644 --- a/workers/site/sdk/chat-sdk.ts +++ b/workers/site/sdk/chat-sdk.ts @@ -2,7 +2,7 @@ import {OpenAI} from "openai"; import Message from "../models/Message"; import {AssistantSdk} from "./assistant-sdk"; import {IMessage} from "../../../src/stores/ClientChatStore"; -import {getModelFamily} from "../../../src/components/chat/SupportedModels"; +import {getModelFamily} from "../../../src/components/chat/lib/SupportedModels"; export class ChatSdk { static async preprocess({ diff --git a/workers/site/services/ChatService.ts b/workers/site/services/ChatService.ts index 6183e0f..b11e99e 100644 --- a/workers/site/services/ChatService.ts +++ b/workers/site/services/ChatService.ts @@ -3,7 +3,7 @@ import OpenAI from 'openai'; import ChatSdk from '../sdk/chat-sdk'; import Message from "../models/Message"; import O1Message from "../models/O1Message"; -import {getModelFamily, ModelFamily} from "../../../src/components/chat/SupportedModels"; +import {getModelFamily, ModelFamily} from "../../../src/components/chat/lib/SupportedModels"; import {OpenAiChatSdk} from "../sdk/models/openai"; import {GroqChatSdk} from "../sdk/models/groq"; import {ClaudeChatSdk} from "../sdk/models/claude";