From bc16879a10570693d327929f30c6838a85c1fe75 Mon Sep 17 00:00:00 2001 From: billchen Date: Mon, 26 Feb 2024 11:51:35 +0800 Subject: [PATCH 1/3] feat: add temporary conversation --- web/src/assets/svg/assistant.svg | 25 +++ web/src/pages/chat/chat-container/index.less | 5 +- web/src/pages/chat/chat-container/index.tsx | 18 +- web/src/pages/chat/hooks.ts | 213 +++++++++++++------ web/src/pages/chat/index.tsx | 18 +- web/src/pages/chat/model.ts | 9 +- web/src/pages/chat/utils.ts | 6 +- 7 files changed, 202 insertions(+), 92 deletions(-) create mode 100644 web/src/assets/svg/assistant.svg diff --git a/web/src/assets/svg/assistant.svg b/web/src/assets/svg/assistant.svg new file mode 100644 index 00000000000..43446a186a4 --- /dev/null +++ b/web/src/assets/svg/assistant.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/web/src/pages/chat/chat-container/index.less b/web/src/pages/chat/chat-container/index.less index ff6eec79c4a..7b9a2549355 100644 --- a/web/src/pages/chat/chat-container/index.less +++ b/web/src/pages/chat/chat-container/index.less @@ -1,11 +1,14 @@ .chatContainer { padding: 0 24px 24px; + .messageContainer { + overflow-y: auto; + } } .messageItem { .messageItemContent { display: inline-block; - width: 300px; + width: 400px; } } diff --git a/web/src/pages/chat/chat-container/index.tsx b/web/src/pages/chat/chat-container/index.tsx index b58b52f65c6..265509e6122 100644 --- a/web/src/pages/chat/chat-container/index.tsx +++ b/web/src/pages/chat/chat-container/index.tsx @@ -1,4 +1,4 @@ -import { Button, Flex, Input, Typography } from 'antd'; +import { Button, Flex, Input } from 'antd'; import { ChangeEventHandler, useState } from 'react'; import { Message } from '@/interfaces/database/chat'; @@ -9,8 +9,6 @@ import { MessageType } from '@/constants/chat'; import { IClientConversation } from '../interface'; import styles from './index.less'; -const { Paragraph } = Typography; - const MessageItem = ({ item }: { item: Message }) => { return (
{ })} > - - {item.content} - +
{item.content}
); @@ -44,10 +40,12 @@ const ChatContainer = () => { return ( - - {conversation?.message?.map((message) => ( - - ))} + +
+ {conversation?.message?.map((message) => ( + + ))} +
{ const dispatch = useDispatch(); @@ -137,16 +139,46 @@ export const useRemoveDialog = () => { return { onRemoveDialog }; }; +export const useGetChatSearchParams = () => { + const [currentQueryParameters] = useSearchParams(); + + return { + dialogId: currentQueryParameters.get(ChatSearchParams.DialogId) || '', + conversationId: + currentQueryParameters.get(ChatSearchParams.ConversationId) || '', + }; +}; + +export const useSetCurrentConversation = () => { + const dispatch = useDispatch(); + + const setCurrentConversation = useCallback( + (currentConversation: IClientConversation) => { + dispatch({ + type: 'chatModel/setCurrentConversation', + payload: currentConversation, + }); + }, + [dispatch], + ); + + return setCurrentConversation; +}; + export const useClickDialogCard = () => { const [currentQueryParameters, setSearchParams] = useSearchParams(); const newQueryParameters: URLSearchParams = useMemo(() => { - return new URLSearchParams(currentQueryParameters.toString()); - }, [currentQueryParameters]); + return new URLSearchParams(); + }, []); const handleClickDialog = useCallback( (dialogId: string) => { newQueryParameters.set(ChatSearchParams.DialogId, dialogId); + // newQueryParameters.set( + // ChatSearchParams.ConversationId, + // EmptyConversationId, + // ); setSearchParams(newQueryParameters); }, [newQueryParameters, setSearchParams], @@ -155,16 +187,6 @@ export const useClickDialogCard = () => { return { handleClickDialog }; }; -export const useGetChatSearchParams = () => { - const [currentQueryParameters] = useSearchParams(); - - return { - dialogId: currentQueryParameters.get(ChatSearchParams.DialogId) || '', - conversationId: - currentQueryParameters.get(ChatSearchParams.ConversationId) || '', - }; -}; - export const useSelectFirstDialogOnMount = () => { const dialogList = useFetchDialogList(); const { dialogId } = useGetChatSearchParams(); @@ -182,70 +204,42 @@ export const useSelectFirstDialogOnMount = () => { //#region conversation -export const useFetchConversationList = (dialogId?: string) => { - const dispatch = useDispatch(); - const conversationList: any[] = useSelector( - (state: any) => state.chatModel.conversationList, - ); - - const fetchConversationList = useCallback(() => { - if (dialogId) { - dispatch({ - type: 'chatModel/listConversation', - payload: { dialog_id: dialogId }, - }); - } - }, [dispatch, dialogId]); - - useEffect(() => { - fetchConversationList(); - }, [fetchConversationList]); - - return conversationList; -}; - -export const useClickConversationCard = () => { - const [currentQueryParameters, setSearchParams] = useSearchParams(); - const newQueryParameters: URLSearchParams = new URLSearchParams( - currentQueryParameters.toString(), - ); - - const handleClickConversation = (conversationId: string) => { - newQueryParameters.set(ChatSearchParams.ConversationId, conversationId); - setSearchParams(newQueryParameters); - }; - - return { handleClickConversation }; -}; - export const useCreateTemporaryConversation = () => { const dispatch = useDispatch(); const { dialogId } = useGetChatSearchParams(); const { handleClickConversation } = useClickConversationCard(); let chatModel = useSelector((state: any) => state.chatModel); - let currentConversation: Pick< + + const currentConversation: Pick< IClientConversation, 'id' | 'message' | 'name' | 'dialog_id' > = chatModel.currentConversation; - let conversationList: IClientConversation[] = chatModel.conversationList; - const createTemporaryConversation = (message: string) => { - const messages = [...(currentConversation?.message ?? [])]; + const conversationList: IClientConversation[] = chatModel.conversationList; + const currentDialog: IDialog = chatModel.currentDialog; + + const setCurrentConversation = useSetCurrentConversation(); + + const createTemporaryConversation = useCallback(() => { + const firstConversation = conversationList[0]; + const messages = [...(firstConversation?.message ?? [])]; if (messages.some((x) => x.id === EmptyConversationId)) { return; } - messages.unshift({ + messages.push({ id: EmptyConversationId, - content: message, + content: currentDialog?.prompt_config?.prologue ?? '', role: MessageType.Assistant, }); + let nextCurrentConversation = currentConversation; + // It’s the back-end data. if ('id' in currentConversation) { - currentConversation = { ...currentConversation, message: messages }; + nextCurrentConversation = { ...currentConversation, message: messages }; } else { // client data - currentConversation = { + nextCurrentConversation = { id: EmptyConversationId, name: 'New conversation', dialog_id: dialogId, @@ -255,23 +249,105 @@ export const useCreateTemporaryConversation = () => { const nextConversationList = [...conversationList]; - nextConversationList.push(currentConversation as IClientConversation); + nextConversationList.unshift( + nextCurrentConversation as IClientConversation, + ); - dispatch({ - type: 'chatModel/setCurrentConversation', - payload: currentConversation, - }); + setCurrentConversation(nextCurrentConversation as IClientConversation); dispatch({ type: 'chatModel/setConversationList', payload: nextConversationList, }); handleClickConversation(EmptyConversationId); - }; + }, [ + dispatch, + currentConversation, + dialogId, + setCurrentConversation, + handleClickConversation, + conversationList, + currentDialog, + ]); return { createTemporaryConversation }; }; +export const useFetchConversationList = () => { + const dispatch = useDispatch(); + const conversationList: any[] = useSelector( + (state: any) => state.chatModel.conversationList, + ); + const { dialogId } = useGetChatSearchParams(); + + const fetchConversationList = useCallback(async () => { + if (dialogId) { + dispatch({ + type: 'chatModel/listConversation', + payload: { dialog_id: dialogId }, + }); + } + }, [dispatch, dialogId]); + + useEffect(() => { + fetchConversationList(); + }, [fetchConversationList]); + + return conversationList; +}; + +export const useSelectConversationList = () => { + const [list, setList] = useState>([]); + let chatModel: ChatModelState = useSelector((state: any) => state.chatModel); + const { conversationList, currentDialog } = chatModel; + const { dialogId } = useGetChatSearchParams(); + const prologue = currentDialog?.prompt_config?.prologue ?? ''; + + const addTemporaryConversation = useCallback(() => { + setList(() => { + const nextList = [ + { + id: '', + name: 'New conversation', + dialog_id: dialogId, + message: [ + { + content: prologue, + role: MessageType.Assistant, + }, + ], + } as IConversation, + ...conversationList, + ]; + return nextList; + }); + }, [conversationList, dialogId, prologue]); + + useEffect(() => { + addTemporaryConversation(); + }, [addTemporaryConversation]); + + return { list, addTemporaryConversation }; +}; + +export const useClickConversationCard = () => { + const [currentQueryParameters, setSearchParams] = useSearchParams(); + const newQueryParameters: URLSearchParams = useMemo( + () => new URLSearchParams(currentQueryParameters.toString()), + [currentQueryParameters], + ); + + const handleClickConversation = useCallback( + (conversationId: string) => { + newQueryParameters.set(ChatSearchParams.ConversationId, conversationId); + setSearchParams(newQueryParameters); + }, + [newQueryParameters, setSearchParams], + ); + + return { handleClickConversation }; +}; + export const useSetConversation = () => { const dispatch = useDispatch(); const { dialogId } = useGetChatSearchParams(); @@ -302,17 +378,20 @@ export const useFetchConversation = () => { const conversation = useSelector( (state: any) => state.chatModel.currentConversation, ); + const setCurrentConversation = useSetCurrentConversation(); const fetchConversation = useCallback(() => { - if (conversationId !== EmptyConversationId && conversationId !== '') { - dispatch({ + if (isConversationIdNotExist(conversationId)) { + dispatch({ type: 'chatModel/getConversation', payload: { conversation_id: conversationId, }, }); + } else { + setCurrentConversation({} as IClientConversation); } - }, [dispatch, conversationId]); + }, [dispatch, conversationId, setCurrentConversation]); useEffect(() => { fetchConversation(); diff --git a/web/src/pages/chat/index.tsx b/web/src/pages/chat/index.tsx index 33b20e44c3b..4e3124f32ae 100644 --- a/web/src/pages/chat/index.tsx +++ b/web/src/pages/chat/index.tsx @@ -18,11 +18,11 @@ import ChatContainer from './chat-container'; import { useClickConversationCard, useClickDialogCard, - useCreateTemporaryConversation, useFetchConversationList, useFetchDialog, useGetChatSearchParams, useRemoveDialog, + useSelectConversationList, useSelectFirstDialogOnMount, useSetCurrentDialog, } from './hooks'; @@ -38,12 +38,10 @@ const Chat = () => { const { handleClickDialog } = useClickDialogCard(); const { handleClickConversation } = useClickConversationCard(); const { dialogId, conversationId } = useGetChatSearchParams(); - const list = useFetchConversationList(dialogId); - const { createTemporaryConversation } = useCreateTemporaryConversation(); + const { list: conversationList, addTemporaryConversation } = + useSelectConversationList(); - const selectedDialog = useFetchDialog(dialogId, true); - - const prologue = selectedDialog?.prompt_config?.prologue || ''; + useFetchDialog(dialogId, true); const handleAppCardEnter = (id: string) => () => { setActivated(id); @@ -69,8 +67,8 @@ const Chat = () => { }; const handleCreateTemporaryConversation = useCallback(() => { - createTemporaryConversation(prologue); - }, [createTemporaryConversation, prologue]); + addTemporaryConversation(); + }, [addTemporaryConversation]); const items: MenuProps['items'] = [ { @@ -112,6 +110,8 @@ const Chat = () => { return appItems; }; + useFetchConversationList(); + return ( @@ -171,7 +171,7 @@ const Chat = () => { - {list.map((x) => ( + {conversationList.map((x) => ( = { }; }, setCurrentConversation(state, { payload }) { - const messageList = payload?.message.map((x: Message | IMessage) => ({ - ...x, - id: 'id' in x ? x.id : uuid(), - })); + const messageList = + payload?.message?.map((x: Message | IMessage) => ({ + ...x, + id: 'id' in x ? x.id : uuid(), + })) ?? []; return { ...state, currentConversation: { ...payload, message: messageList }, diff --git a/web/src/pages/chat/utils.ts b/web/src/pages/chat/utils.ts index 997dc3755c2..cbec9e2c71a 100644 --- a/web/src/pages/chat/utils.ts +++ b/web/src/pages/chat/utils.ts @@ -1,4 +1,4 @@ -import { variableEnabledFieldMap } from './constants'; +import { EmptyConversationId, variableEnabledFieldMap } from './constants'; export const excludeUnEnabledVariables = (values: any) => { const unEnabledFields: Array = @@ -10,3 +10,7 @@ export const excludeUnEnabledVariables = (values: any) => { (key) => `llm_setting.${variableEnabledFieldMap[key]}`, ); }; + +export const isConversationIdNotExist = (conversationId: string) => { + return conversationId !== EmptyConversationId && conversationId !== ''; +}; From 2b728f442d10eead4985dd1870f8e733066facce Mon Sep 17 00:00:00 2001 From: billchen Date: Mon, 26 Feb 2024 15:03:53 +0800 Subject: [PATCH 2/3] feat: add avatar to MessageItem --- web/src/hooks/userSettingHook.ts | 22 +++++++++ web/src/interfaces/database/userSetting.ts | 21 ++++++++ web/src/layouts/components/header/index.tsx | 17 ++++--- web/src/layouts/components/user/index.tsx | 11 ++++- web/src/pages/chat/chat-container/index.less | 21 +++++++- web/src/pages/chat/chat-container/index.tsx | 50 +++++++++++++++++--- web/src/pages/chat/hooks.ts | 2 +- web/src/pages/setting/model.ts | 31 +++++++----- 8 files changed, 144 insertions(+), 31 deletions(-) create mode 100644 web/src/hooks/userSettingHook.ts create mode 100644 web/src/interfaces/database/userSetting.ts diff --git a/web/src/hooks/userSettingHook.ts b/web/src/hooks/userSettingHook.ts new file mode 100644 index 00000000000..743c790bfb1 --- /dev/null +++ b/web/src/hooks/userSettingHook.ts @@ -0,0 +1,22 @@ +import { IUserInfo } from '@/interfaces/database/userSetting'; +import { useCallback, useEffect } from 'react'; +import { useDispatch, useSelector } from 'umi'; + +export const useFetchUserInfo = () => { + const dispatch = useDispatch(); + const fetchUserInfo = useCallback(() => { + dispatch({ type: 'settingModel/getUserInfo' }); + }, [dispatch]); + + useEffect(() => { + fetchUserInfo(); + }, [fetchUserInfo]); +}; + +export const useSelectUserInfo = () => { + const userInfo: IUserInfo = useSelector( + (state: any) => state.settingModel.userInfo, + ); + + return userInfo; +}; diff --git a/web/src/interfaces/database/userSetting.ts b/web/src/interfaces/database/userSetting.ts new file mode 100644 index 00000000000..76a61fee4d6 --- /dev/null +++ b/web/src/interfaces/database/userSetting.ts @@ -0,0 +1,21 @@ +export interface IUserInfo { + access_token: string; + avatar?: any; + color_schema: string; + create_date: string; + create_time: number; + email: string; + id: string; + is_active: string; + is_anonymous: string; + is_authenticated: string; + is_superuser: boolean; + language: string; + last_login_time: string; + login_channel: string; + nickname: string; + password: string; + status: string; + update_date: string; + update_time: number; +} diff --git a/web/src/layouts/components/header/index.tsx b/web/src/layouts/components/header/index.tsx index 9d69a446478..7705cae780c 100644 --- a/web/src/layouts/components/header/index.tsx +++ b/web/src/layouts/components/header/index.tsx @@ -19,17 +19,20 @@ const RagHeader = () => { const navigate = useNavigate(); const { pathname } = useLocation(); - const tagsData = [ - { path: '/knowledge', name: 'Knowledge Base', icon: KnowledgeBaseIcon }, - { path: '/chat', name: 'Chat', icon: StarIon }, - { path: '/file', name: 'File Management', icon: FileIcon }, - ]; + const tagsData = useMemo( + () => [ + { path: '/knowledge', name: 'Knowledge Base', icon: KnowledgeBaseIcon }, + { path: '/chat', name: 'Chat', icon: StarIon }, + { path: '/file', name: 'File Management', icon: FileIcon }, + ], + [], + ); const currentPath = useMemo(() => { return ( tagsData.find((x) => pathname.startsWith(x.path))?.name || 'knowledge' ); - }, [pathname]); + }, [pathname, tagsData]); const handleChange = (path: string) => { navigate(path); @@ -48,7 +51,7 @@ const RagHeader = () => { > - + { const { t } = useTranslation(); + const userInfo = useSelectUserInfo(); const logout = () => { authorizationUtil.removeAll(); @@ -36,13 +38,18 @@ const App: React.FC = () => { ), }, ]; - }, []); + }, [t]); + + useFetchUserInfo(); return ( ); diff --git a/web/src/pages/chat/chat-container/index.less b/web/src/pages/chat/chat-container/index.less index 7b9a2549355..29a93582343 100644 --- a/web/src/pages/chat/chat-container/index.less +++ b/web/src/pages/chat/chat-container/index.less @@ -6,9 +6,26 @@ } .messageItem { - .messageItemContent { + padding: 24px 0; + .messageItemSection { display: inline-block; - width: 400px; + } + .messageItemSectionLeft { + width: 80%; + } + .messageItemSectionRight { + width: 20%; + } + .messageItemContent { + display: inline-flex; + gap: 20px; + } + .messageItemContentReverse { + flex-direction: row-reverse; + } + .messageText { + padding: 10px 14px; + background-color: rgba(249, 250, 251, 1); } } diff --git a/web/src/pages/chat/chat-container/index.tsx b/web/src/pages/chat/chat-container/index.tsx index 265509e6122..83cbd17aa53 100644 --- a/web/src/pages/chat/chat-container/index.tsx +++ b/web/src/pages/chat/chat-container/index.tsx @@ -1,15 +1,20 @@ -import { Button, Flex, Input } from 'antd'; +import { Avatar, Button, Flex, Input } from 'antd'; import { ChangeEventHandler, useState } from 'react'; import { Message } from '@/interfaces/database/chat'; import classNames from 'classnames'; import { useFetchConversation, useSendMessage } from '../hooks'; +import { ReactComponent as AssistantIcon } from '@/assets/svg/assistant.svg'; import { MessageType } from '@/constants/chat'; +import { useOneNamespaceEffectsLoading } from '@/hooks/storeHooks'; import { IClientConversation } from '../interface'; + +import { useSelectUserInfo } from '@/hooks/userSettingHook'; import styles from './index.less'; const MessageItem = ({ item }: { item: Message }) => { + const userInfo = useSelectUserInfo(); return (
{ [styles.messageItemRight]: item.role === MessageType.User, })} > - -
{item.content}
-
+
+
+ {item.role === MessageType.User ? ( + userInfo.avatar ?? ( + + ) + ) : ( + + )} + + + {item.role === MessageType.Assistant ? 'Resume Assistant' : 'You'} + +
{item.content}
+
+
+
); }; @@ -28,9 +62,13 @@ const ChatContainer = () => { const [value, setValue] = useState(''); const conversation: IClientConversation = useFetchConversation(); const { sendMessage } = useSendMessage(); + const loading = useOneNamespaceEffectsLoading('chatModel', [ + 'completeConversation', + 'getConversation', + ]); const handlePressEnter = () => { - console.info(value); + setValue(''); sendMessage(value); }; @@ -52,7 +90,7 @@ const ChatContainer = () => { placeholder="Message Resume Assistant..." value={value} suffix={ - } diff --git a/web/src/pages/chat/hooks.ts b/web/src/pages/chat/hooks.ts index dafc8d760c6..57ed30d1877 100644 --- a/web/src/pages/chat/hooks.ts +++ b/web/src/pages/chat/hooks.ts @@ -426,7 +426,7 @@ export const useSendMessage = () => { }; const handleSendMessage = async (message: string) => { - if (conversationId !== EmptyConversationId) { + if (conversationId !== '') { sendMessage(message); } else { const data = await setConversation(message); diff --git a/web/src/pages/setting/model.ts b/web/src/pages/setting/model.ts index 643ed5e717e..ce46dc86b3c 100644 --- a/web/src/pages/setting/model.ts +++ b/web/src/pages/setting/model.ts @@ -1,7 +1,7 @@ import { ITenantInfo } from '@/interfaces/database/knowledge'; import { IThirdOAIModelCollection as IThirdAiModelCollection } from '@/interfaces/database/llm'; +import { IUserInfo } from '@/interfaces/database/userSetting'; import userService from '@/services/userService'; -import authorizationUtil from '@/utils/authorizationUtil'; import { message } from 'antd'; import { Nullable } from 'typings'; import { DvaModel } from 'umi'; @@ -16,6 +16,7 @@ export interface SettingModelState { llmInfo: IThirdAiModelCollection; myLlm: any[]; factoriesList: any[]; + userInfo: IUserInfo; } const model: DvaModel = { @@ -30,6 +31,7 @@ const model: DvaModel = { llmInfo: {}, myLlm: [], factoriesList: [], + userInfo: {} as IUserInfo, }, reducers: { updateState(state, { payload }) { @@ -38,10 +40,11 @@ const model: DvaModel = { ...payload, }; }, - }, - subscriptions: { - setup({ dispatch, history }) { - history.listen((location) => {}); + setUserInfo(state, { payload }) { + return { + ...state, + userInfo: payload, + }; }, }, effects: { @@ -63,15 +66,17 @@ const model: DvaModel = { } }, *getUserInfo({ payload = {} }, { call, put }) { - const { data, response } = yield call(userService.user_info, payload); - const { retcode, data: res, retmsg } = data; - const userInfo = { - avatar: res.avatar, - name: res.nickname, - email: res.email, - }; - authorizationUtil.setUserInfo(userInfo); + const { data } = yield call(userService.user_info, payload); + const { retcode, data: res } = data; + + // const userInfo = { + // avatar: res.avatar, + // name: res.nickname, + // email: res.email, + // }; + // authorizationUtil.setUserInfo(userInfo); if (retcode === 0) { + yield put({ type: 'setUserInfo', payload: res }); // localStorage.setItem('userInfo',res.) } }, From f7d1da0ddaaac24e656181679f27f629a31aa9e1 Mon Sep 17 00:00:00 2001 From: billchen Date: Mon, 26 Feb 2024 18:33:48 +0800 Subject: [PATCH 3/3] feat: render message reference --- web/package-lock.json | 719 ++++++++++++++++++- web/package.json | 3 + web/src/interfaces/database/chat.ts | 28 +- web/src/pages/chat/chat-container/index.less | 9 +- web/src/pages/chat/chat-container/index.tsx | 77 +- 5 files changed, 812 insertions(+), 24 deletions(-) diff --git a/web/package-lock.json b/web/package-lock.json index 04902e1e325..f6ab7916fcb 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -21,8 +21,11 @@ "react-chat-elements": "^12.0.13", "react-i18next": "^14.0.0", "react-infinite-scroll-component": "^6.1.0", + "react-markdown": "^9.0.1", + "react-string-replace": "^1.1.1", "umi": "^4.0.90", "umi-request": "^1.4.0", + "unist-util-visit-parents": "^6.0.1", "uuid": "^9.0.1" }, "devDependencies": { @@ -2667,6 +2670,14 @@ "@babel/types": "^7.20.7" } }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmmirror.com/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "dependencies": { + "@types/ms": "*" + } + }, "node_modules/@types/eslint": { "version": "8.56.1", "resolved": "https://registry.npmmirror.com/@types/eslint/-/eslint-8.56.1.tgz", @@ -2690,8 +2701,15 @@ "node_modules/@types/estree": { "version": "1.0.5", "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "peer": true + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" + }, + "node_modules/@types/estree-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmmirror.com/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", + "dependencies": { + "@types/estree": "*" + } }, "node_modules/@types/glob": { "version": "7.2.0", @@ -2716,6 +2734,14 @@ "resolved": "https://registry.npmmirror.com/@types/hapi__joi/-/hapi__joi-17.1.9.tgz", "integrity": "sha512-oOMFT8vmCTFncsF1engrs04jatz8/Anwx3De9uxnOK4chgSEgWBvFtpSoJo8u3784JNO+ql5tzRR6phHoRnscQ==" }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmmirror.com/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "dependencies": { + "@types/unist": "*" + } + }, "node_modules/@types/history": { "version": "5.0.0", "resolved": "https://registry.npmmirror.com/@types/history/-/history-5.0.0.tgz", @@ -2787,6 +2813,14 @@ "integrity": "sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==", "dev": true }, + "node_modules/@types/mdast": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/@types/mdast/-/mdast-4.0.3.tgz", + "integrity": "sha512-LsjtqsyF+d2/yFOYaN22dHZI1Cpwkrj+g06G8+qtUKlhovPW89YhqSnfKtMbkgmEtYpH2gydRNULd6y8mciAFg==", + "dependencies": { + "@types/unist": "*" + } + }, "node_modules/@types/minimatch": { "version": "5.1.2", "resolved": "https://registry.npmmirror.com/@types/minimatch/-/minimatch-5.1.2.tgz", @@ -2799,6 +2833,11 @@ "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", "peer": true }, + "node_modules/@types/ms": { + "version": "0.7.34", + "resolved": "https://registry.npmmirror.com/@types/ms/-/ms-0.7.34.tgz", + "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" + }, "node_modules/@types/node": { "version": "20.10.6", "resolved": "https://registry.npmmirror.com/@types/node/-/node-20.10.6.tgz", @@ -2821,8 +2860,7 @@ "node_modules/@types/prop-types": { "version": "15.7.11", "resolved": "https://registry.npmmirror.com/@types/prop-types/-/prop-types-15.7.11.tgz", - "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==", - "dev": true + "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==" }, "node_modules/@types/q": { "version": "1.5.8", @@ -2834,7 +2872,6 @@ "version": "18.2.46", "resolved": "https://registry.npmmirror.com/@types/react/-/react-18.2.46.tgz", "integrity": "sha512-nNCvVBcZlvX4NU1nRRNV/mFl1nNRuTuslAJglQsq+8ldXe5Xv0Wd2f7WTE3jOxhLH2BFfiZGC6GCp+kHQbgG+w==", - "dev": true, "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -2912,8 +2949,7 @@ "node_modules/@types/scheduler": { "version": "0.16.8", "resolved": "https://registry.npmmirror.com/@types/scheduler/-/scheduler-0.16.8.tgz", - "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==", - "dev": true + "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==" }, "node_modules/@types/semver": { "version": "7.5.6", @@ -2926,6 +2962,11 @@ "integrity": "sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw==", "dev": true }, + "node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, "node_modules/@types/use-sync-external-store": { "version": "0.0.3", "resolved": "https://registry.npmmirror.com/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz", @@ -4364,8 +4405,7 @@ "node_modules/@ungap/structured-clone": { "version": "1.2.0", "resolved": "https://registry.npmmirror.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "peer": true + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" }, "node_modules/@vitejs/plugin-react": { "version": "4.0.0", @@ -5216,6 +5256,11 @@ "@babel/core": "^7.0.0" } }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==" + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz", @@ -5557,6 +5602,11 @@ "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001574.tgz", "integrity": "sha512-BtYEK4r/iHt/txm81KBudCUcTy7t+s9emrIaHqjYurQ10x71zJ5VQ9x1dYPcz/b+pKSp4y/v1xSI67A+LzpNyg==" }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==" + }, "node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz", @@ -5570,6 +5620,26 @@ "node": ">=4" } }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==" + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==" + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==" + }, + "node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==" + }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-3.5.3.tgz", @@ -5777,6 +5847,11 @@ "node": ">= 0.8" } }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==" + }, "node_modules/commander": { "version": "8.3.0", "resolved": "https://registry.npmmirror.com/commander/-/commander-8.3.0.tgz", @@ -6588,6 +6663,14 @@ "node": ">=0.10.0" } }, + "node_modules/decode-named-character-reference": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz", + "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==", + "dependencies": { + "character-entities": "^2.0.0" + } + }, "node_modules/decode-uri-component": { "version": "0.2.2", "resolved": "https://registry.npmmirror.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz", @@ -6772,6 +6855,14 @@ "node": ">=0.4.0" } }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "engines": { + "node": ">=6" + } + }, "node_modules/des.js": { "version": "1.1.0", "resolved": "https://registry.npmmirror.com/des.js/-/des.js-1.1.0.tgz", @@ -6845,6 +6936,14 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "dependencies": { + "dequal": "^2.0.0" + } + }, "node_modules/diffie-hellman": { "version": "5.0.3", "resolved": "https://registry.npmmirror.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz", @@ -7981,6 +8080,11 @@ "node": ">=4.0" } }, + "node_modules/estree-util-is-identifier-name": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==" + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmmirror.com/esutils/-/esutils-2.0.3.tgz", @@ -8129,6 +8233,11 @@ "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==", "dev": true }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmmirror.com/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, "node_modules/extend-shallow": { "version": "3.0.2", "resolved": "https://registry.npmmirror.com/extend-shallow/-/extend-shallow-3.0.2.tgz", @@ -9038,6 +9147,36 @@ "node": ">= 0.4" } }, + "node_modules/hast-util-to-jsx-runtime": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.0.tgz", + "integrity": "sha512-H/y0+IWPdsLLS738P8tDnrQ8Z+dj12zQQ6WC11TIM21C8WFVoIxcqWXf2H3hiTVZjF1AWqoimGwrTWecWrnmRQ==", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-object": "^1.0.0", + "unist-util-position": "^5.0.0", + "vfile-message": "^4.0.0" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "dependencies": { + "@types/hast": "^3.0.0" + } + }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmmirror.com/he/-/he-1.2.0.tgz", @@ -9203,6 +9342,11 @@ "node": ">=8" } }, + "node_modules/html-url-attributes": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/html-url-attributes/-/html-url-attributes-3.0.0.tgz", + "integrity": "sha512-/sXbVCWayk6GDVg3ctOX6nxaVj7So40FcFAnWlWGNAB1LpYKcV5Cd10APjPjW80O7zYW2MsjBV4zZ7IZO5fVow==" + }, "node_modules/html-webpack-plugin": { "version": "5.5.0", "resolved": "https://registry.npmmirror.com/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz", @@ -9400,6 +9544,11 @@ "resolved": "https://registry.npmmirror.com/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, + "node_modules/inline-style-parser": { + "version": "0.2.2", + "resolved": "https://registry.npmmirror.com/inline-style-parser/-/inline-style-parser-0.2.2.tgz", + "integrity": "sha512-EcKzdTHVe8wFVOGEYXiW9WmJXPjqi1T+234YpJr98RiFYKHV3cdy1+3mkTE+KHTHxFFLH51SfaGOoUdW+v7ViQ==" + }, "node_modules/insert-css": { "version": "2.0.0", "resolved": "https://registry.npmmirror.com/insert-css/-/insert-css-2.0.0.tgz", @@ -9471,6 +9620,20 @@ "node": ">= 0.10" } }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==" + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + } + }, "node_modules/is-arguments": { "version": "1.1.1", "resolved": "https://registry.npmmirror.com/is-arguments/-/is-arguments-1.1.1.tgz", @@ -9596,6 +9759,11 @@ "node": ">= 0.4" } }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==" + }, "node_modules/is-descriptor": { "version": "1.0.3", "resolved": "https://registry.npmmirror.com/is-descriptor/-/is-descriptor-1.0.3.tgz", @@ -9710,6 +9878,11 @@ "node": ">=0.10.0" } }, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==" + }, "node_modules/is-inside-container": { "version": "1.0.0", "resolved": "https://registry.npmmirror.com/is-inside-container/-/is-inside-container-1.0.0.tgz", @@ -10779,6 +10952,11 @@ "integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==", "dev": true }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==" + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmmirror.com/loose-envify/-/loose-envify-1.4.0.tgz", @@ -10882,6 +11060,119 @@ "safe-buffer": "^5.1.2" } }, + "node_modules/mdast-util-from-markdown": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.0.tgz", + "integrity": "sha512-n7MTOr/z+8NAX/wmhhDji8O3bRvPTV/U0oTCaZJkjhPSKTPhS3xufVhKGF8s1pJ7Ox4QgoIU7KHseh09S+9rTA==", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" + } + }, + "node_modules/mdast-util-mdx-expression": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.0.tgz", + "integrity": "sha512-fGCu8eWdKUKNu5mohVGkhBXCXGnOTLuFqOvGMvdikr+J1w7lDJgxThOKpwRWzzbyXAU2hhSwsmssOY4yTokluw==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + } + }, + "node_modules/mdast-util-mdx-jsx": { + "version": "3.1.0", + "resolved": "https://registry.npmmirror.com/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.1.0.tgz", + "integrity": "sha512-A8AJHlR7/wPQ3+Jre1+1rq040fX9A4Q1jG8JxmSNp/PLPHg80A6475wxTp3KzHpApFH6yWxFotHrJQA3dXP6/w==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-remove-position": "^5.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + } + }, + "node_modules/mdast-util-mdxjs-esm": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.1.0", + "resolved": "https://registry.npmmirror.com/mdast-util-to-hast/-/mdast-util-to-hast-13.1.0.tgz", + "integrity": "sha512-/e2l/6+OdGp/FB+ctrJ9Avz71AN/GRH3oi/3KAx/kMnoUsD6q0woXlDT8lLEeViVKE7oZxE7RXzvO3T8kF2/sA==", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + } + }, + "node_modules/mdast-util-to-markdown": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", + "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + } + }, + "node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "dependencies": { + "@types/mdast": "^4.0.0" + } + }, "node_modules/mdn-data": { "version": "2.0.14", "resolved": "https://registry.npmmirror.com/mdn-data/-/mdn-data-2.0.14.tgz", @@ -10934,6 +11225,217 @@ "node": ">= 8" } }, + "node_modules/micromark": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/micromark/-/micromark-4.0.0.tgz", + "integrity": "sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==", + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/micromark-core-commonmark/-/micromark-core-commonmark-2.0.0.tgz", + "integrity": "sha512-jThOz/pVmAYUtkroV3D5c1osFXAMv9e0ypGDOIZuCeAe91/sD6BoE2Sjzt30yuXtwOYUmySOhMas/PVyh02itA==", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/micromark-factory-destination/-/micromark-factory-destination-2.0.0.tgz", + "integrity": "sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/micromark-factory-label/-/micromark-factory-label-2.0.0.tgz", + "integrity": "sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/micromark-factory-title/-/micromark-factory-title-2.0.0.tgz", + "integrity": "sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.0.tgz", + "integrity": "sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/micromark-util-chunked/-/micromark-util-chunked-2.0.0.tgz", + "integrity": "sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/micromark-util-classify-character/-/micromark-util-classify-character-2.0.0.tgz", + "integrity": "sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.0.tgz", + "integrity": "sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==", + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.1.tgz", + "integrity": "sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/micromark-util-decode-string/-/micromark-util-decode-string-2.0.0.tgz", + "integrity": "sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz", + "integrity": "sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==" + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.0.tgz", + "integrity": "sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==" + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.0.tgz", + "integrity": "sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.0.tgz", + "integrity": "sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==", + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz", + "integrity": "sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-subtokenize": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.0.tgz", + "integrity": "sha512-vc93L1t+gpR3p8jxeVdaYlbV2jTYteDje19rNSS/H5dlhxUYll5Fy6vJ2cDwP8RnsXi818yGty1ayP55y3W6fg==", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==" + }, + "node_modules/micromark-util-types": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/micromark-util-types/-/micromark-util-types-2.0.0.tgz", + "integrity": "sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==" + }, "node_modules/micromatch": { "version": "4.0.5", "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.5.tgz", @@ -11787,6 +12289,26 @@ "safe-buffer": "^5.1.1" } }, + "node_modules/parse-entities": { + "version": "4.0.1", + "resolved": "https://registry.npmmirror.com/parse-entities/-/parse-entities-4.0.1.tgz", + "integrity": "sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + } + }, + "node_modules/parse-entities/node_modules/@types/unist": { + "version": "2.0.10", + "resolved": "https://registry.npmmirror.com/@types/unist/-/unist-2.0.10.tgz", + "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==" + }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmmirror.com/parse-json/-/parse-json-5.2.0.tgz", @@ -12717,6 +13239,11 @@ "resolved": "https://registry.npmmirror.com/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "node_modules/property-information": { + "version": "6.4.1", + "resolved": "https://registry.npmmirror.com/property-information/-/property-information-6.4.1.tgz", + "integrity": "sha512-OHYtXfu5aI2sS2LWFSN5rgJjrQ4pCy8i1jubJLe2QvMF8JJ++HXTUIVWFLfXJoaOfvYYjk2SN8J2wFUWIGXT4w==" + }, "node_modules/proxy-compare": { "version": "2.5.1", "resolved": "https://registry.npmmirror.com/proxy-compare/-/proxy-compare-2.5.1.tgz", @@ -13860,6 +14387,27 @@ "resolved": "https://registry.npmmirror.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" }, + "node_modules/react-markdown": { + "version": "9.0.1", + "resolved": "https://registry.npmmirror.com/react-markdown/-/react-markdown-9.0.1.tgz", + "integrity": "sha512-186Gw/vF1uRkydbsOIkcGXw7aHq0sZOCRFFjGrr7b9+nVZg4UfA4enXCaxm4fUzecU38sWfrNDitGhshuU7rdg==", + "dependencies": { + "@types/hast": "^3.0.0", + "devlop": "^1.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "html-url-attributes": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "unified": "^11.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "peerDependencies": { + "@types/react": ">=18", + "react": ">=18" + } + }, "node_modules/react-merge-refs": { "version": "1.1.0", "resolved": "https://registry.npmmirror.com/react-merge-refs/-/react-merge-refs-1.1.0.tgz", @@ -13982,6 +14530,14 @@ "prop-types": "^15.5.8" } }, + "node_modules/react-string-replace": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/react-string-replace/-/react-string-replace-1.1.1.tgz", + "integrity": "sha512-26TUbLzLfHQ5jO5N7y3Mx88eeKo0Ml0UjCQuX4BMfOd/JX+enQqlKpL1CZnmjeBRvQE8TR+ds9j1rqx9CxhKHQ==", + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/reactcss": { "version": "1.2.3", "resolved": "https://registry.npmmirror.com/reactcss/-/reactcss-1.2.3.tgz", @@ -14270,6 +14826,29 @@ "node": ">= 0.10" } }, + "node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmmirror.com/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" + } + }, + "node_modules/remark-rehype": { + "version": "11.1.0", + "resolved": "https://registry.npmmirror.com/remark-rehype/-/remark-rehype-11.1.0.tgz", + "integrity": "sha512-z3tJrAs2kIs1AqIIy6pzHmAHlF1hWQ+OdY4/hv+Wxe35EhyLKcajL33iUEn3ScxtFox9nUvRufR/Zre8Q08H/g==", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + } + }, "node_modules/remove-accents": { "version": "0.4.2", "resolved": "https://registry.npmmirror.com/remove-accents/-/remove-accents-0.4.2.tgz", @@ -15043,6 +15622,11 @@ "deprecated": "See https://github.com/lydell/source-map-url#deprecated", "dev": true }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==" + }, "node_modules/spdx-correct": { "version": "3.2.0", "resolved": "https://registry.npmmirror.com/spdx-correct/-/spdx-correct-3.2.0.tgz", @@ -15369,6 +15953,15 @@ "es-abstract": "^1.22.1" } }, + "node_modules/stringify-entities": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/stringify-entities/-/stringify-entities-4.0.3.tgz", + "integrity": "sha512-BP9nNHMhhfcMbiuQKCqMjhDP5yBCAxsPu4pHFFzJ6Alo9dZgY4VLDPutXqIjpRiMoKdp7Av85Gr73Q5uH9k7+g==", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -15415,6 +16008,14 @@ "integrity": "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==", "peer": true }, + "node_modules/style-to-object": { + "version": "1.0.5", + "resolved": "https://registry.npmmirror.com/style-to-object/-/style-to-object-1.0.5.tgz", + "integrity": "sha512-rDRwHtoDD3UMMrmZ6BzOW0naTjMsVZLIjsGleSKS/0Oz+cgCfAPRspaqJuE8rDzpKha/nEvnM0IF4seEAZUTKQ==", + "dependencies": { + "inline-style-parser": "0.2.2" + } + }, "node_modules/style-utils": { "version": "0.3.8", "resolved": "https://registry.npmmirror.com/style-utils/-/style-utils-0.3.8.tgz", @@ -15983,6 +16584,11 @@ "resolved": "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==" + }, "node_modules/trim-newlines": { "version": "3.0.1", "resolved": "https://registry.npmmirror.com/trim-newlines/-/trim-newlines-3.0.1.tgz", @@ -15992,6 +16598,11 @@ "node": ">=8" } }, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==" + }, "node_modules/tslib": { "version": "2.6.2", "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.6.2.tgz", @@ -16718,6 +17329,20 @@ "./packages/isomorphic-unfetch" ] }, + "node_modules/unified": { + "version": "11.0.4", + "resolved": "https://registry.npmmirror.com/unified/-/unified-11.0.4.tgz", + "integrity": "sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ==", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + } + }, "node_modules/union-value": { "version": "1.0.1", "resolved": "https://registry.npmmirror.com/union-value/-/union-value-1.0.1.tgz", @@ -16742,6 +17367,58 @@ "node": ">=0.10.0" } }, + "node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "dependencies": { + "@types/unist": "^3.0.0" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "dependencies": { + "@types/unist": "^3.0.0" + } + }, + "node_modules/unist-util-remove-position": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz", + "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-visit": "^5.0.0" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dependencies": { + "@types/unist": "^3.0.0" + } + }, + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + } + }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmmirror.com/universalify/-/universalify-2.0.1.tgz", @@ -16994,6 +17671,25 @@ "node": ">= 0.8" } }, + "node_modules/vfile": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/vfile/-/vfile-6.0.1.tgz", + "integrity": "sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + } + }, + "node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmmirror.com/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + } + }, "node_modules/vite": { "version": "4.3.1", "resolved": "https://registry.npmmirror.com/vite/-/vite-4.3.1.tgz", @@ -17370,6 +18066,11 @@ "engines": { "node": ">=10" } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmmirror.com/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==" } } } diff --git a/web/package.json b/web/package.json index 9fcffb194c7..43bbdb4374d 100644 --- a/web/package.json +++ b/web/package.json @@ -25,8 +25,11 @@ "react-chat-elements": "^12.0.13", "react-i18next": "^14.0.0", "react-infinite-scroll-component": "^6.1.0", + "react-markdown": "^9.0.1", + "react-string-replace": "^1.1.1", "umi": "^4.0.90", "umi-request": "^1.4.0", + "unist-util-visit-parents": "^6.0.1", "uuid": "^9.0.1" }, "devDependencies": { diff --git a/web/src/interfaces/database/chat.ts b/web/src/interfaces/database/chat.ts index f7c4a23cbf1..eb4ec51f370 100644 --- a/web/src/interfaces/database/chat.ts +++ b/web/src/interfaces/database/chat.ts @@ -54,7 +54,7 @@ export interface IConversation { dialog_id: string; id: string; message: Message[]; - reference: any[]; + reference: IReference[]; name: string; update_date: string; update_time: number; @@ -64,3 +64,29 @@ export interface Message { content: string; role: MessageType; } + +export interface IReference { + chunks: Chunk[]; + doc_aggs: Docagg[]; + total: number; +} + +interface Docagg { + count: number; + doc_id: string; + doc_name: string; +} + +interface Chunk { + chunk_id: string; + content_ltks: string; + content_with_weight: string; + doc_id: string; + docnm_kwd: string; + img_id: string; + important_kwd: any[]; + kb_id: string; + similarity: number; + term_similarity: number; + vector_similarity: number; +} diff --git a/web/src/pages/chat/chat-container/index.less b/web/src/pages/chat/chat-container/index.less index 29a93582343..c0ce04b554a 100644 --- a/web/src/pages/chat/chat-container/index.less +++ b/web/src/pages/chat/chat-container/index.less @@ -11,10 +11,10 @@ display: inline-block; } .messageItemSectionLeft { - width: 80%; + width: 70%; } .messageItemSectionRight { - width: 20%; + width: 30%; } .messageItemContent { display: inline-flex; @@ -24,9 +24,12 @@ flex-direction: row-reverse; } .messageText { - padding: 10px 14px; + padding: 0 14px; background-color: rgba(249, 250, 251, 1); } + .referenceIcon { + padding: 0 6px; + } } .messageItemLeft { diff --git a/web/src/pages/chat/chat-container/index.tsx b/web/src/pages/chat/chat-container/index.tsx index 83cbd17aa53..31d939ff506 100644 --- a/web/src/pages/chat/chat-container/index.tsx +++ b/web/src/pages/chat/chat-container/index.tsx @@ -1,20 +1,59 @@ -import { Avatar, Button, Flex, Input } from 'antd'; -import { ChangeEventHandler, useState } from 'react'; - -import { Message } from '@/interfaces/database/chat'; -import classNames from 'classnames'; -import { useFetchConversation, useSendMessage } from '../hooks'; - import { ReactComponent as AssistantIcon } from '@/assets/svg/assistant.svg'; import { MessageType } from '@/constants/chat'; import { useOneNamespaceEffectsLoading } from '@/hooks/storeHooks'; +import { useSelectUserInfo } from '@/hooks/userSettingHook'; +import { IReference, Message } from '@/interfaces/database/chat'; +import { Avatar, Button, Flex, Input, Popover } from 'antd'; +import classNames from 'classnames'; +import { ChangeEventHandler, useCallback, useMemo, useState } from 'react'; +import reactStringReplace from 'react-string-replace'; +import { useFetchConversation, useSendMessage } from '../hooks'; import { IClientConversation } from '../interface'; -import { useSelectUserInfo } from '@/hooks/userSettingHook'; +import { InfoCircleOutlined } from '@ant-design/icons'; +import Markdown from 'react-markdown'; +import { visitParents } from 'unist-util-visit-parents'; import styles from './index.less'; -const MessageItem = ({ item }: { item: Message }) => { +const rehypeWrapReference = () => { + return function wrapTextTransform(tree: any) { + visitParents(tree, 'text', (node, ancestors) => { + if (ancestors.at(-1).tagName !== 'custom-typography') { + node.type = 'element'; + node.tagName = 'custom-typography'; + node.properties = {}; + node.children = [{ type: 'text', value: node.value }]; + } + }); + }; +}; + +const MessageItem = ({ item }: { item: Message; references: IReference[] }) => { const userInfo = useSelectUserInfo(); + + const popoverContent = useMemo( + () => ( +
+

Content

+

Content

+
+ ), + [], + ); + + const renderReference = useCallback( + (text: string) => { + return reactStringReplace(text, /#{2}\d{1,}\${2}/g, (match, i) => { + return ( + + + + ); + }); + }, + [popoverContent], + ); + return (
{ {item.role === MessageType.Assistant ? 'Resume Assistant' : 'You'} -
{item.content}
+
+ + renderReference(children), + } as any + } + > + {item.content} + +
@@ -81,7 +132,11 @@ const ChatContainer = () => {
{conversation?.message?.map((message) => ( - + ))}