diff --git a/app/src/components/markdown.tsx b/app/src/components/markdown.tsx index 74ed7b0..b38b833 100644 --- a/app/src/components/markdown.tsx +++ b/app/src/components/markdown.tsx @@ -53,6 +53,7 @@ const ImagePreview = styled.div` export interface MarkdownProps { content: string; className?: string; + katex? : boolean; } export function Markdown(props: MarkdownProps) { @@ -68,11 +69,19 @@ export function Markdown(props: MarkdownProps) { return classes; }, [props.className]) - const elem = useMemo(() => ( - <div className={classes.join(' ')}> + const elem = useMemo(() => { + const remarkPlugins: any[] = [remarkGfm]; + const rehypePlugins: any[] = []; + + if (props.katex) { + remarkPlugins.push(remarkMath); + rehypePlugins.push(rehypeKatex); + } + + return <div className={classes.join(' ')}> <ReactMarkdown - remarkPlugins={[remarkGfm, remarkMath]} - rehypePlugins={[rehypeKatex]} + remarkPlugins={remarkPlugins} + rehypePlugins={rehypePlugins} components={{ ol({ start, children }) { return <ol start={start ?? 1} style={{ counterReset: `list-item ${(start || 1)}` }}> @@ -129,8 +138,8 @@ export function Markdown(props: MarkdownProps) { ) } }}>{props.content}</ReactMarkdown> - </div> - ), [props.content, classes, intl]); + </div>; + }, [props.content, props.katex, classes, intl]); return elem; } diff --git a/app/src/components/message.tsx b/app/src/components/message.tsx index 4650713..9567aac 100644 --- a/app/src/components/message.tsx +++ b/app/src/components/message.tsx @@ -1,6 +1,7 @@ import styled from '@emotion/styled'; import { Button, CopyButton, Loader, Textarea } from '@mantine/core'; +import { useOption } from '../core/options/use-option'; import { Message } from "../core/chat/types"; import { share } from '../core/utils'; import { TTSButton } from './tts-button'; @@ -210,6 +211,8 @@ export default function MessageComponent(props: { message: Message, last: boolea const [content, setContent] = useState(''); const intl = useIntl(); + const [katex] = useOption<boolean>('markdown', 'katex'); + const tab = useAppSelector(selectSettingsTab); const getRoleName = useCallback((role: string, share = false) => { @@ -288,7 +291,9 @@ export default function MessageComponent(props: { message: Message, last: boolea </Button> )} </div> - {!editing && <Markdown content={props.message.content} className={"content content-" + props.message.id} />} + {!editing && <Markdown content={props.message.content} + katex={katex} + className={"content content-" + props.message.id} />} {editing && (<Editor> <Textarea value={content} onChange={e => setContent(e.currentTarget.value)} diff --git a/app/src/global-options/index.tsx b/app/src/global-options/index.tsx index b75f250..d24567f 100644 --- a/app/src/global-options/index.tsx +++ b/app/src/global-options/index.tsx @@ -4,7 +4,7 @@ import { OptionGroup } from "../core/options/option-group"; import { openAIOptions } from "./openai"; import { parameterOptions } from "./parameters"; import { ttsServiceOptions } from "./tts-service"; -import { autoScrollOptions, inputOptions } from "./ui"; +import { autoScrollOptions, inputOptions, markdownOptions } from "./ui"; import { whisperOptions } from "./whisper"; export const globalOptions: OptionGroup[] = [ @@ -12,6 +12,7 @@ export const globalOptions: OptionGroup[] = [ autoScrollOptions, parameterOptions, inputOptions, + markdownOptions, whisperOptions, ttsServiceOptions, ]; diff --git a/app/src/global-options/ui.tsx b/app/src/global-options/ui.tsx index 016c975..4992e6d 100644 --- a/app/src/global-options/ui.tsx +++ b/app/src/global-options/ui.tsx @@ -47,4 +47,20 @@ export const inputOptions: OptionGroup = { }, }, ], +} + +export const markdownOptions: OptionGroup = { + id: 'markdown', + name: "Markdown", + options: [ + { + id: 'katex', + defaultValue: false, + displayOnSettingsScreen: "ui", + renderProps: { + type: "checkbox", + label: "Enable Katex math rendering (experimental)", + }, + }, + ], } \ No newline at end of file