= ({
- 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 (
-
- );
- },
-);
-
-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 (
-
- );
- },
-);
-
-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) => (
-
- {cell}
- |
- ))}
-
-
-
- {rows.map((row, rIndex) => (
-
- {row.map((cell, cIndex) => (
-
- {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 }) => {
},
}}
>
-
{isEditing ? (
) : isLoading ? (
diff --git a/src/components/chat/MessageEditorComponent.tsx b/src/components/chat/messages/MessageEditorComponent.tsx
similarity index 96%
rename from src/components/chat/MessageEditorComponent.tsx
rename to src/components/chat/messages/MessageEditorComponent.tsx
index 1b20953..46eedef 100644
--- a/src/components/chat/MessageEditorComponent.tsx
+++ b/src/components/chat/messages/MessageEditorComponent.tsx
@@ -2,7 +2,7 @@ import React, { KeyboardEvent, useState } from "react";
import { Box, Flex, IconButton, Textarea } from "@chakra-ui/react";
import { Check, X } from "lucide-react";
import { observer } from "mobx-react-lite";
-import store, { type IMessage } from "../../stores/ClientChatStore";
+import store, { type IMessage } from "../../../stores/ClientChatStore";
interface MessageEditorProps {
message: IMessage;
diff --git a/src/components/chat/RenderCustomComponents.tsx b/src/components/chat/messages/MessageMarkdown.tsx
similarity index 97%
rename from src/components/chat/RenderCustomComponents.tsx
rename to src/components/chat/messages/MessageMarkdown.tsx
index 5e21cf4..286c185 100644
--- a/src/components/chat/RenderCustomComponents.tsx
+++ b/src/components/chat/messages/MessageMarkdown.tsx
@@ -19,10 +19,11 @@ import {
useColorModeValue,
} from "@chakra-ui/react";
import { marked } from "marked";
-import CodeBlock from "../code/CodeBlock";
-import ImageWithFallback from "./ImageWithFallback";
+import CodeBlock from "../../code/CodeBlock";
+import ImageWithFallback from "../../markdown/ImageWithFallback";
import markedKatex from "marked-katex-extension";
import katex from "katex";
+import domPurify from "../lib/domPurify";
try {
if (localStorage) {
@@ -563,7 +564,7 @@ function parseTokens(tokens: marked.Token[]): JSX.Element[] {
return output;
}
-export function renderCustomComponents(markdown: string): JSX.Element[] {
+export function renderMessageMarkdown(markdown: string): JSX.Element[] {
marked.setOptions({
breaks: true,
gfm: true,
@@ -571,6 +572,6 @@ export function renderCustomComponents(markdown: string): JSX.Element[] {
async: true,
});
- const tokens = marked.lexer(markdown);
+ const tokens = marked.lexer(domPurify(markdown));
return parseTokens(tokens);
}
diff --git a/src/components/chat/messages/MessageMarkdownRenderer.tsx b/src/components/chat/messages/MessageMarkdownRenderer.tsx
new file mode 100644
index 0000000..a4307a4
--- /dev/null
+++ b/src/components/chat/messages/MessageMarkdownRenderer.tsx
@@ -0,0 +1,14 @@
+import React from "react";
+import {renderMessageMarkdown} from "./MessageMarkdown";
+
+interface CustomMarkdownRendererProps {
+ markdown: string;
+}
+
+const MessageMarkdownRenderer: React.FC = ({
+ markdown,
+}) => {
+ return {renderMessageMarkdown(markdown)}
;
+};
+
+export default MessageMarkdownRenderer;
diff --git a/src/components/chat/UserMessageTools.tsx b/src/components/chat/messages/UserMessageTools.tsx
similarity index 100%
rename from src/components/chat/UserMessageTools.tsx
rename to src/components/chat/messages/UserMessageTools.tsx
diff --git a/src/components/chat/remarkImageGeneration.ts b/src/components/chat/remarkImageGeneration.ts
deleted file mode 100644
index a0c9892..0000000
--- a/src/components/chat/remarkImageGeneration.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import { visit } from "unist-util-visit";
-
-export default function remarkImageGeneration() {
- return (tree) => {
- visit(tree, "code", (node, index, parent) => {
- if (node.lang === "generation") {
- try {
- const data = JSON.parse(node.value);
- parent.children[index] = {
- type: "generation",
- data: data,
- };
- } catch (error) {
- console.error("Invalid JSON in image-generation block:", error);
- }
- }
- });
- };
-}
diff --git a/src/components/legal/LegalDoc.tsx b/src/components/legal/LegalDoc.tsx
index 43f7099..8cb4061 100644
--- a/src/components/legal/LegalDoc.tsx
+++ b/src/components/legal/LegalDoc.tsx
@@ -1,7 +1,6 @@
import React from "react";
import { Box, VStack } from "@chakra-ui/react";
-import Markdown from "react-markdown";
-import { webComponents } from "../react-markdown/WebComponents";
+import {renderMarkdown} from "../markdown/MarkdownComponent";
function LegalDoc({ text }) {
return (
@@ -13,7 +12,7 @@ function LegalDoc({ text }) {
whiteSpace="pre-wrap"
spacing={4}
>
- {text}
+ {renderMarkdown(text)}
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) => (
+
+ {cell}
+ |
+ ))}
+
+
+
+ {rows.map((row, rIndex) => (
+
+ {row.map((cell, cIndex) => (
+
+ {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";