mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-23 20:00:15 +01:00
🖋️ feat: Add option to render User Messages as Markdown (#4170)
This commit is contained in:
parent
42b7373ddc
commit
be44caaab1
10 changed files with 94 additions and 21 deletions
|
|
@ -1,15 +1,18 @@
|
|||
import { Fragment, Suspense, useMemo } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import type { TMessage, TResPlugin } from 'librechat-data-provider';
|
||||
import type { TMessageContentProps, TDisplayProps } from '~/common';
|
||||
import Plugin from '~/components/Messages/Content/Plugin';
|
||||
import Error from '~/components/Messages/Content/Error';
|
||||
import { DelayedRender } from '~/components/ui';
|
||||
import { useChatContext } from '~/Providers';
|
||||
import MarkdownLite from './MarkdownLite';
|
||||
import EditMessage from './EditMessage';
|
||||
import { useLocalize } from '~/hooks';
|
||||
import Container from './Container';
|
||||
import Markdown from './Markdown';
|
||||
import { cn } from '~/utils';
|
||||
import store from '~/store';
|
||||
|
||||
export const ErrorMessage = ({
|
||||
text,
|
||||
|
|
@ -64,9 +67,9 @@ export const ErrorMessage = ({
|
|||
);
|
||||
};
|
||||
|
||||
// Display Message Component
|
||||
const DisplayMessage = ({ text, isCreatedByUser, message, showCursor }: TDisplayProps) => {
|
||||
const { isSubmitting, latestMessage } = useChatContext();
|
||||
const enableUserMsgMarkdown = useRecoilValue(store.enableUserMsgMarkdown);
|
||||
const showCursorState = useMemo(
|
||||
() => showCursor === true && isSubmitting,
|
||||
[showCursor, isSubmitting],
|
||||
|
|
@ -75,6 +78,18 @@ const DisplayMessage = ({ text, isCreatedByUser, message, showCursor }: TDisplay
|
|||
() => message.messageId === latestMessage?.messageId,
|
||||
[message.messageId, latestMessage?.messageId],
|
||||
);
|
||||
|
||||
let content: React.ReactElement;
|
||||
if (!isCreatedByUser) {
|
||||
content = (
|
||||
<Markdown content={text} showCursor={showCursorState} isLatestMessage={isLatestMessage} />
|
||||
);
|
||||
} else if (enableUserMsgMarkdown) {
|
||||
content = <MarkdownLite content={text} />;
|
||||
} else {
|
||||
content = <>{text}</>;
|
||||
}
|
||||
|
||||
return (
|
||||
<Container message={message}>
|
||||
<div
|
||||
|
|
@ -85,11 +100,7 @@ const DisplayMessage = ({ text, isCreatedByUser, message, showCursor }: TDisplay
|
|||
isCreatedByUser ? 'whitespace-pre-wrap dark:text-gray-20' : 'dark:text-gray-100',
|
||||
)}
|
||||
>
|
||||
{!isCreatedByUser ? (
|
||||
<Markdown content={text} showCursor={showCursorState} isLatestMessage={isLatestMessage} />
|
||||
) : (
|
||||
<>{text}</>
|
||||
)}
|
||||
{content}
|
||||
</div>
|
||||
</Container>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
import { memo, useMemo } from 'react';
|
||||
import { useChatContext } from '~/Providers';
|
||||
import { memo, useMemo, ReactElement } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import MarkdownLite from '~/components/Chat/Messages/Content/MarkdownLite';
|
||||
import Markdown from '~/components/Chat/Messages/Content/Markdown';
|
||||
import { useChatContext } from '~/Providers';
|
||||
import { cn } from '~/utils';
|
||||
import store from '~/store';
|
||||
|
||||
type TextPartProps = {
|
||||
text: string;
|
||||
|
|
@ -10,14 +13,32 @@ type TextPartProps = {
|
|||
showCursor: boolean;
|
||||
};
|
||||
|
||||
type ContentType =
|
||||
| ReactElement<React.ComponentProps<typeof Markdown>>
|
||||
| ReactElement<React.ComponentProps<typeof MarkdownLite>>
|
||||
| ReactElement;
|
||||
|
||||
const TextPart = memo(({ text, isCreatedByUser, messageId, showCursor }: TextPartProps) => {
|
||||
const { isSubmitting, latestMessage } = useChatContext();
|
||||
const enableUserMsgMarkdown = useRecoilValue(store.enableUserMsgMarkdown);
|
||||
const showCursorState = useMemo(() => showCursor && isSubmitting, [showCursor, isSubmitting]);
|
||||
const isLatestMessage = useMemo(
|
||||
() => messageId === latestMessage?.messageId,
|
||||
[messageId, latestMessage?.messageId],
|
||||
);
|
||||
|
||||
const content: ContentType = useMemo(() => {
|
||||
if (!isCreatedByUser) {
|
||||
return (
|
||||
<Markdown content={text} showCursor={showCursorState} isLatestMessage={isLatestMessage} />
|
||||
);
|
||||
} else if (enableUserMsgMarkdown) {
|
||||
return <MarkdownLite content={text} />;
|
||||
} else {
|
||||
return <>{text}</>;
|
||||
}
|
||||
}, [isCreatedByUser, enableUserMsgMarkdown, text, showCursorState, isLatestMessage]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
|
|
@ -27,11 +48,7 @@ const TextPart = memo(({ text, isCreatedByUser, messageId, showCursor }: TextPar
|
|||
isCreatedByUser ? 'whitespace-pre-wrap dark:text-gray-20' : 'dark:text-gray-70',
|
||||
)}
|
||||
>
|
||||
{!isCreatedByUser ? (
|
||||
<Markdown content={text} showCursor={showCursorState} isLatestMessage={isLatestMessage} />
|
||||
) : (
|
||||
<>{text}</>
|
||||
)}
|
||||
{content}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -22,12 +22,13 @@ const SearchContent = ({ message }: { message: TMessage }) => {
|
|||
key={`display-${messageId}-${idx}`}
|
||||
showCursor={false}
|
||||
isSubmitting={false}
|
||||
isCreatedByUser={message.isCreatedByUser}
|
||||
messageId={message.messageId}
|
||||
part={part}
|
||||
message={message}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
{message.unfinished && (
|
||||
{message.unfinished === true && (
|
||||
<Suspense>
|
||||
<DelayedRender delay={250}>
|
||||
<UnfinishedMessage message={message} key={`unfinished-${messageId}`} />
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue