diff --git a/ee/tabby-ui/app/chat/page.tsx b/ee/tabby-ui/app/chat/page.tsx index 87567bf4e983..b2355c8ed668 100644 --- a/ee/tabby-ui/app/chat/page.tsx +++ b/ee/tabby-ui/app/chat/page.tsx @@ -79,6 +79,9 @@ export default function ChatPage() { supportsReadWorkspaceGitRepoInfo, setSupportsReadWorkspaceGitRepoInfo ] = useState(false) + const [supportsListFileInWorkspace, setSupportProvideFileAtInfo] = + useState(false) + const [supportsReadFileContent, setSupportsReadFileContent] = useState(false) const executeCommand = (command: ChatCommand) => { if (chatRef.current) { @@ -244,6 +247,12 @@ export default function ChatPage() { server ?.hasCapability('readWorkspaceGitRepositories') .then(setSupportsReadWorkspaceGitRepoInfo) + server + ?.hasCapability('listFileInWorkspace') + .then(setSupportProvideFileAtInfo) + server + ?.hasCapability('readFileContent') + .then(setSupportsReadFileContent) } checkCapabilities().then(() => { @@ -427,6 +436,16 @@ export default function ChatPage() { : undefined } getActiveEditorSelection={getActiveEditorSelection} + listFileInWorkspace={ + isInEditor && supportsListFileInWorkspace + ? server?.listFileInWorkspace + : undefined + } + readFileContent={ + isInEditor && supportsReadFileContent + ? server?.readFileContent + : undefined + } /> ) diff --git a/ee/tabby-ui/components/chat/chat-panel.tsx b/ee/tabby-ui/components/chat/chat-panel.tsx index bdf497ac0bad..80c40d826f4e 100644 --- a/ee/tabby-ui/components/chat/chat-panel.tsx +++ b/ee/tabby-ui/components/chat/chat-panel.tsx @@ -32,11 +32,12 @@ import { IconTrash } from '@/components/ui/icons' import { ButtonScrollToBottom } from '@/components/button-scroll-to-bottom' -import { PromptForm, PromptFormRef } from '@/components/chat/prompt-form' +import { PromptForm } from '@/components/chat/prompt-form' import { FooterText } from '@/components/footer' import { Tooltip, TooltipContent, TooltipTrigger } from '../ui/tooltip' import { ChatContext } from './chat' +import { PromptFormRef } from './form-editor/types' import { RepoSelect } from './repo-select' export interface ChatPanelProps @@ -51,14 +52,14 @@ export interface ChatPanelProps export interface ChatPanelRef { focus: () => void + setInput: (input: string) => void + input: string } function ChatPanelRenderer( { stop, reload, - input, - setInput, className, onSubmit, chatMaxWidthClass, @@ -142,14 +143,17 @@ function ChatPanelRenderer( chatInputRef.current?.focus() }) } - React.useImperativeHandle( ref, () => { return { focus: () => { promptFormRef.current?.focus() - } + }, + setInput: str => { + promptFormRef.current?.setInput(str) + }, + input: promptFormRef.current?.input ?? '' } }, [] @@ -254,7 +258,7 @@ function ChatPanelRenderer( ease: 'easeInOut', duration: 0.1 }} - exit={{ opacity: 0, scale: 0.9, y: 5 }} + exit={{ opacity: 0, scale: 0.9, y: -5 }} > { updateEnableActiveSelection(!enableActiveSelection) }} @@ -299,7 +303,7 @@ function ChatPanelRenderer( ease: 'easeInOut', duration: 0.1 }} - exit={{ opacity: 0, scale: 0.9, y: 5 }} + exit={{ opacity: 0, scale: 0.9, y: -5 }} layout > @@ -324,11 +328,7 @@ function ChatPanelRenderer( diff --git a/ee/tabby-ui/components/chat/chat.tsx b/ee/tabby-ui/components/chat/chat.tsx index 210177f48ef8..0a28ce5374c5 100644 --- a/ee/tabby-ui/components/chat/chat.tsx +++ b/ee/tabby-ui/components/chat/chat.tsx @@ -5,7 +5,10 @@ import type { EditorContext, EditorFileContext, FileLocation, + FileRange, GitRepository, + ListFileItem, + ListFilesInWorkspaceParams, LookupSymbolHint, SymbolInfo } from 'tabby-chat-panel' @@ -48,6 +51,7 @@ import { import { ChatPanel, ChatPanelRef } from './chat-panel' import { ChatScrollAnchor } from './chat-scroll-anchor' import { EmptyScreen } from './empty-screen' +import { FILEITEM_REGEX } from './form-editor/utils' import { QuestionAnswerList } from './question-answer' type ChatContextValue = { @@ -80,6 +84,10 @@ type ChatContextValue = { setSelectedRepoId: React.Dispatch> repos: RepositorySourceListQuery['repositoryList'] | undefined fetchingRepos: boolean + listFileInWorkspace?: ( + params: ListFilesInWorkspaceParams + ) => Promise + readFileContent?: (info: FileRange) => Promise } export const ChatContext = React.createContext( @@ -121,6 +129,10 @@ interface ChatProps extends React.ComponentProps<'div'> { supportsOnApplyInEditorV2: boolean readWorkspaceGitRepositories?: () => Promise getActiveEditorSelection?: () => Promise + listFileInWorkspace?: ( + params: ListFilesInWorkspaceParams + ) => Promise + readFileContent?: (info: FileRange) => Promise } function ChatRenderer( @@ -144,7 +156,9 @@ function ChatRenderer( chatInputRef, supportsOnApplyInEditorV2, readWorkspaceGitRepositories, - getActiveEditorSelection + getActiveEditorSelection, + listFileInWorkspace, + readFileContent }: ChatProps, ref: React.ForwardedRef ) { @@ -153,7 +167,6 @@ function ChatRenderer( const [threadId, setThreadId] = React.useState() const isOnLoadExecuted = React.useRef(false) const [qaPairs, setQaPairs] = React.useState(initialMessages ?? []) - const [input, setInput] = React.useState('') const [relevantContext, setRelevantContext] = React.useState([]) const [activeSelection, setActiveSelection] = React.useState( null @@ -169,6 +182,12 @@ function ChatRenderer( const chatPanelRef = React.useRef(null) + // both set/get input from prompt form + const setInput = (str: string) => { + chatPanelRef.current?.setInput(str) + } + const input = chatPanelRef.current?.input ?? '' + const [{ data: repositoryListData, fetching: fetchingRepos }] = useQuery({ query: repositorySourceListQuery }) @@ -489,10 +508,28 @@ function ChatRenderer( } const handleSubmit = async (value: string) => { + const fileItems: any[] = [] + let newValue = value + + let match + while ((match = FILEITEM_REGEX.exec(value)) !== null) { + try { + const parsedItem = JSON.parse(match[1]) + fileItems.push(parsedItem) + + const replacement = `@${ + parsedItem.label.split('/').pop() || parsedItem.label || 'unknown' + }` + newValue = newValue.replace(match[0], replacement) + } catch (error) { + continue + } + } sendUserChat({ message: value, relevantContext: relevantContext }) + setRelevantContext([]) } @@ -620,7 +657,9 @@ function ChatRenderer( setSelectedRepoId, repos, fetchingRepos, - initialized + initialized, + listFileInWorkspace, + readFileContent }} >
diff --git a/ee/tabby-ui/components/chat/form-editor/types.ts b/ee/tabby-ui/components/chat/form-editor/types.ts new file mode 100644 index 000000000000..975aff24e472 --- /dev/null +++ b/ee/tabby-ui/components/chat/form-editor/types.ts @@ -0,0 +1,72 @@ +/** + * PromptProps defines the props for the PromptForm component. + */ +export interface PromptProps { + /** + * A callback function that handles form submission. + * It returns a Promise, so you can handle async actions. + */ + onSubmit: (value: string) => Promise + /** + * Indicates if the form (or chat) is in a loading/submitting state. + */ + isLoading: boolean +} + +/** + * PromptFormRef defines the methods exposed by the PromptForm via forwardRef. + */ +export interface PromptFormRef { + /** + * Focus the editor inside PromptForm. + */ + focus: () => void + /** + * Set the content of the editor programmatically. + */ + setInput: (value: string) => void + /** + * Get the current editor text content. + */ + input: string +} + +/** + * Represents a file item inside the workspace. + * (You can add more properties if needed) + */ +export interface FileItem { + label: string + id?: string + // ... any other fields that you might have +} + +/** + * Represents a file source item for mention suggestions. + */ +export interface SourceItem { + name: string + filepath: string + category: 'file' + fileItem: FileItem +} + +/** + * The attributes stored in a mention node. + */ +export interface MentionNodeAttrs { + id: string + name: string + category: 'file' + fileItem: FileItem +} + +/** + * Stores the current state of the mention feature while typing. + */ +export interface MentionState { + items: SourceItem[] + command: ((props: MentionNodeAttrs) => void) | null + query: string + selectedIndex: number +} diff --git a/ee/tabby-ui/components/chat/form-editor/utils.tsx b/ee/tabby-ui/components/chat/form-editor/utils.tsx new file mode 100644 index 000000000000..55ad9e5405a8 --- /dev/null +++ b/ee/tabby-ui/components/chat/form-editor/utils.tsx @@ -0,0 +1,195 @@ +import Mention from '@tiptap/extension-mention' +import { NodeViewWrapper, ReactNodeViewRenderer } from '@tiptap/react' + +import { cn } from '@/lib/utils' + +import type { FileItem, MentionNodeAttrs, SourceItem } from './types' + +// A regular expression to match fileItem placeholders in the text content. +// For example: [[fileItem:{"label":"some/file/path","id":"123"}]] +export const FILEITEM_REGEX = /\[\[fileItem:({.*?})\]\]/g + +/** + * Converts a FileItem to a SourceItem for the mention list. + */ +export function fileItemToSourceItem(info: FileItem): SourceItem { + return { + fileItem: info, + // The name is the filename (e.g., split by '/') + name: info.label.split('/').pop() || info.label, + // The filepath is the original label (which might be a path) + filepath: info.label, + category: 'file' + } +} + +/** + * A small file icon (SVG) for indicating file items. + */ +export const FileItemIcon = () => ( + + + + +) + +/** + * Shortens a file name or string, preserving only the last suffixLength characters. + */ +export function shortenLabel(label: string, suffixLength = 15): string { + if (label.length <= suffixLength) return label + return '...' + label.slice(label.length - suffixLength) +} + +/** + * A React component that renders a mention node inside the editor. + * It shows a small file icon and file name in a highlighted style. + */ +export const MentionComponent = ({ node }: { node: any }) => { + return ( + + + + {node.attrs.name} + + + ) +} + +/** + * A custom TipTap extension to handle file mentions (like @filename). + * When rendered as text, it produces a placeholder with file info. + */ +export const PromptFormMentionExtension = Mention.extend({ + // Use a React-based node view for the mention + addNodeView() { + return ReactNodeViewRenderer(MentionComponent) + }, + + // How the mention node is rendered as plain text (e.g. exporting final content) + renderText({ node }) { + const fileItem = node.attrs.fileItem as FileItem + return `[[fileItem:${JSON.stringify(fileItem)}]]` + }, + + // Define attributes stored in the mention node + addAttributes() { + return { + id: { + default: null, + parseHTML: element => element.getAttribute('data-id'), + renderHTML: attrs => { + if (!attrs.id) return {} + return { 'data-id': attrs.id } + } + }, + name: { + default: null, + parseHTML: element => element.getAttribute('data-name'), + renderHTML: attrs => { + if (!attrs.name) return {} + return { 'data-name': attrs.name } + } + }, + category: { + default: 'file', + parseHTML: element => element.getAttribute('data-category'), + renderHTML: attrs => { + if (!attrs.category) return {} + return { 'data-category': attrs.category } + } + }, + fileItem: { + default: null, + parseHTML: element => element.getAttribute('data-fileItem'), + renderHTML: attrs => { + if (!attrs.fileItem) return {} + return { 'data-fileItem': attrs.fileItem } + } + } + } + } +}) + +/** + * A React component rendering the mention dropdown list. + * Shown when the user types '@...' and possible file completions are fetched. + */ +export const MentionList = ({ + items, + command, + selectedIndex, + onHover +}: { + items: SourceItem[] + command: ((props: MentionNodeAttrs) => void) | null + selectedIndex: number + onHover: (index: number) => void +}) => { + /** + * Handle user selecting an item from the mention list. + */ + const handleSelect = (item: SourceItem) => { + if (!command) return + command({ + id: `${item.name}-${item.filepath}`, + name: item.name, + category: 'file', + fileItem: item.fileItem + }) + } + + return ( +
{ + // Prevent the popover from closing on clicks + e.preventDefault() + }} + > + {/* If no items found, show a simple message */} + {!items.length ? ( +
+ Cannot find any files. +
+ ) : ( +
+ {items.map((item, index) => ( + + ))} +
+ )} +
+ ) +} diff --git a/ee/tabby-ui/components/chat/prompt-form.tsx b/ee/tabby-ui/components/chat/prompt-form.tsx index 98fcd56d54ec..7844834e2a03 100644 --- a/ee/tabby-ui/components/chat/prompt-form.tsx +++ b/ee/tabby-ui/components/chat/prompt-form.tsx @@ -1,348 +1,347 @@ -import * as React from 'react' -import { UseChatHelpers } from 'ai/react' -import { debounce, has } from 'lodash-es' -import useSWR from 'swr' +import React, { + ForwardedRef, + useContext, + useImperativeHandle, + useRef, + useState +} from 'react' +import Document from '@tiptap/extension-document' +import Paragraph from '@tiptap/extension-paragraph' +import Placeholder from '@tiptap/extension-placeholder' +import Text from '@tiptap/extension-text' +import { EditorContent, useEditor } from '@tiptap/react' -import { useEnterSubmit } from '@/lib/hooks/use-enter-submit' -import fetcher from '@/lib/tabby/fetcher' -import type { ISearchHit, SearchReponse } from '@/lib/types' -import { cn } from '@/lib/utils' -import { Button, buttonVariants } from '@/components/ui/button' -import { - IconArrowElbow, - IconEdit, - IconSymbolFunction -} from '@/components/ui/icons' +import { Button } from '@/components/ui/button' +import { IconArrowElbow, IconEdit } from '@/components/ui/icons' import { Popover, PopoverAnchor, PopoverContent } from '@/components/ui/popover' -import { - Tooltip, - TooltipContent, - TooltipTrigger -} from '@/components/ui/tooltip' -import { - SearchableSelect, - SearchableSelectAnchor, - SearchableSelectContent, - SearchableSelectOption, - SearchableSelectTextarea -} from '@/components/searchable-select' - -export interface PromptProps - extends Pick { - onSubmit: (value: string) => Promise - isLoading: boolean - chatInputRef: React.RefObject - isInitializing?: boolean -} -export interface PromptFormRef { - focus: () => void -} +import { ChatContext } from './chat' +import { MentionState, PromptFormRef, PromptProps } from './form-editor/types' +import { + fileItemToSourceItem, + MentionList, + PromptFormMentionExtension +} from './form-editor/utils' +/** + * PromptFormRenderer is the internal component used by React.forwardRef + * It provides the main logic for the chat input with mention functionality. + */ function PromptFormRenderer( - { - onSubmit, - input, - setInput, - isLoading, - chatInputRef, - isInitializing - }: PromptProps, - ref: React.ForwardedRef + { onSubmit, isLoading }: PromptProps, + ref: ForwardedRef ) { - const { formRef, onKeyDown } = useEnterSubmit() - const [queryCompletionUrl, setQueryCompletionUrl] = React.useState< - string | null - >(null) - const [suggestionOpen, setSuggestionOpen] = React.useState(false) - // store the input selection for replacing inputValue - const prevInputSelectionEnd = React.useRef() - // for updating the input selection after replacing - const nextInputSelectionRange = React.useRef<[number, number]>() - const [options, setOptions] = React.useState([]) - const [selectedCompletionsMap, setSelectedCompletionsMap] = React.useState< - Record - >({}) + // A ref to track if the mention popover is open (for handling special key events) + const popoverOpenRef = useRef(false) + // State controlling the popover + const [popoverOpen, setPopoverOpen] = useState(false) + // The popover position is updated to follow the current mention trigger + const [anchorPos, setAnchorPos] = useState({ left: 0, top: 0 }) + // A ref to store the plain text from the editor + const inputRef = useRef('') - const { data: completionData } = useSWR( - queryCompletionUrl, - fetcher, + // Use forceUpdate to re-render manually when mention state changes + const [_, forceUpdate] = useState(0) + const triggerUpdate = () => { + forceUpdate(i => i + 1) + } + + // A mention state object to store mention items, command, query, etc. + const mentionStateRef = useRef({ + items: [], + command: null, + query: '', + selectedIndex: 0 + }) + + // If you need a DOM anchor for the popover, you can store it here + const anchorRef = useRef(null) + + // Access custom context (e.g., to fetch file suggestions) + const { listFileInWorkspace } = useContext(ChatContext) + + // Control the popover open/close state + const handlePopoverChange = (open: boolean) => { + popoverOpenRef.current = open + setPopoverOpen(open) + } + + // Set up the TipTap editor with mention extension + const editor = useEditor( { - revalidateOnFocus: false, - dedupingInterval: 0, - errorRetryCount: 0 - } - ) + extensions: [ + Document, + Paragraph, + Text, + Placeholder.configure({ + placeholder: 'typing...' + }), + PromptFormMentionExtension.configure({ + // Customize how mention suggestions are fetched and rendered + suggestion: { + char: '@', // Trigger character for mention + items: async ({ query }) => { + if (!listFileInWorkspace) return [] + const files = await listFileInWorkspace({ query }) + return files?.map(fileItemToSourceItem) || [] + }, + render: () => ({ + onStart: props => { + const { editor } = props + const { from } = props.range + // Calculate the popover position relative to the editor + const currentLine = editor.view.coordsAtPos(from) + const editorDom = editor.view.dom.getBoundingClientRect() - React.useEffect(() => { - const suggestions = completionData?.hits ?? [] - setOptions(suggestions) - setSuggestionOpen(!!suggestions?.length) - }, [completionData?.hits]) + setAnchorPos({ + left: currentLine.left - editorDom.left, + top: currentLine.top - editorDom.top - 10 + }) - React.useImperativeHandle(ref, () => ({ - focus: () => chatInputRef.current?.focus() - })) + // Update mention state + mentionStateRef.current.items = props.items || [] + mentionStateRef.current.command = props.command + ? (attrs: any) => { + props.command(attrs) + requestAnimationFrame(() => { + editor.commands.focus() + }) + } + : null + mentionStateRef.current.query = props.query || '' + mentionStateRef.current.selectedIndex = 0 - React.useEffect(() => { - if ( - input && - chatInputRef.current && - chatInputRef.current !== document.activeElement - ) { - chatInputRef.current.focus() - } - }, [input, chatInputRef]) + // Open popover and re-render + setPopoverOpen(true) + popoverOpenRef.current = true + triggerUpdate() + editor.commands.focus() + }, + onUpdate: props => { + const { editor } = props + const { from } = props.range + const currentLine = editor.view.coordsAtPos(from) + const editorDom = editor.view.dom.getBoundingClientRect() - React.useLayoutEffect(() => { - if (nextInputSelectionRange.current?.length) { - chatInputRef.current?.setSelectionRange?.( - nextInputSelectionRange.current[0], - nextInputSelectionRange.current[1] - ) - nextInputSelectionRange.current = undefined - } - }, [chatInputRef]) + setAnchorPos({ + left: currentLine.left - editorDom.left, + top: currentLine.top - editorDom.top - 10 + }) - const handleSearchCompletion = React.useMemo(() => { - return debounce((e: React.ChangeEvent) => { - const value = e.target?.value ?? '' - const end = e.target?.selectionEnd ?? 0 - const queryNameMatches = getSearchCompletionQueryName(value, end) - const queryName = queryNameMatches?.[1] - if (queryName) { - const query = encodeURIComponent(`name:${queryName} AND kind:function`) - const url = `/v1beta/search?q=${query}` - setQueryCompletionUrl(url) - } else { - setOptions([]) - setSuggestionOpen(false) - } - }, 200) - }, []) + // Update mention items, query, etc. + mentionStateRef.current.items = props.items || [] + mentionStateRef.current.command = props.command + ? (attrs: any) => { + props.command(attrs) + requestAnimationFrame(() => { + editor.commands.focus() + }) + } + : null + mentionStateRef.current.query = props.query || '' + mentionStateRef.current.selectedIndex = 0 - const handleCompletionSelect = (item: ISearchHit) => { - const selectionEnd = prevInputSelectionEnd.current ?? 0 - const queryNameMatches = getSearchCompletionQueryName(input, selectionEnd) - if (queryNameMatches) { - setSelectedCompletionsMap({ - ...selectedCompletionsMap, - [`@${item.doc?.name}`]: item - }) - const replaceString = `@${item?.doc?.name} ` - const prevInput = input - .substring(0, selectionEnd) - .replace(new RegExp(queryNameMatches[0]), '') - const nextSelectionEnd = prevInput.length + replaceString.length - nextInputSelectionRange.current = [nextSelectionEnd, nextSelectionEnd] - setInput(prevInput + replaceString + input.slice(selectionEnd)) - } - setOptions([]) - setSuggestionOpen(false) - } + triggerUpdate() + }, + onExit: () => { + setPopoverOpen(false) + popoverOpenRef.current = false + mentionStateRef.current.command = null + triggerUpdate() + }, + onKeyDown: ({ event }) => { + // Esc key -> close popover + if (event.key === 'Escape') { + setPopoverOpen(false) + triggerUpdate() + return true + } - const handlePromptSubmit: React.FormEventHandler< - HTMLFormElement - > = async e => { - e.preventDefault() - if (!input?.trim() || isLoading || isInitializing) { - return - } + // Down arrow -> move selection down + if (event.key === 'ArrowDown') { + event.preventDefault() + if (!mentionStateRef.current.items.length) return true + mentionStateRef.current.selectedIndex = + (mentionStateRef.current.selectedIndex + 1) % + mentionStateRef.current.items.length + triggerUpdate() + return true + } - let finalInput = input - Object.keys(selectedCompletionsMap).forEach(key => { - const completion = selectedCompletionsMap[key] - if (!completion?.doc) return - finalInput = finalInput.replaceAll( - key, - `\n${'```'}${completion.doc?.language ?? ''}\n${ - completion.doc.body ?? '' - }\n${'```'}\n` - ) - }) + // Up arrow -> move selection up + if (event.key === 'ArrowUp') { + event.preventDefault() + if (!mentionStateRef.current.items.length) return true + const prevIdx = mentionStateRef.current.selectedIndex - 1 + mentionStateRef.current.selectedIndex = + prevIdx < 0 + ? mentionStateRef.current.items.length - 1 + : prevIdx + triggerUpdate() + return true + } - setInput('') - await onSubmit(finalInput) - } + // Enter -> confirm selection + if (event.key === 'Enter') { + const { items, selectedIndex, command } = + mentionStateRef.current + const item = items[selectedIndex] + if (item && command) { + command({ + id: `${item.name}-${item.filepath}`, + name: item.name, + category: 'file', + fileItem: item.fileItem + }) + } + return true + } - const handleTextareaKeyDown = ( - e: React.KeyboardEvent, - isOpen: boolean - ) => { - if (e.key === 'Enter' && isOpen) { - e.preventDefault() - } else if ( - isOpen && - ['ArrowRight', 'ArrowLeft', 'Home', 'End'].includes(e.key) - ) { - setOptions([]) - setSuggestionOpen(false) - } else { - if (!isOpen) { - ;(e as any).preventDownshiftDefault = true + return false + } + }) + } + }) + ], + // On every editor update, store the raw text into inputRef + onUpdate: ({ editor }) => { + inputRef.current = editor.getText() + }, + // Additional editor props (e.g., handleKeyDown to submit on Enter) + editorProps: { + handleKeyDown(view, event) { + // If mention popover is open, let mention extension handle the keys + if (popoverOpenRef.current) { + return false + } + // Otherwise, handle Enter (without shift) as a submit + if (event.key === 'Enter' && !event.shiftKey) { + event.preventDefault() + const text = inputRef.current + // Clear the editor content + view.dispatch(view.state.tr.delete(0, view.state.doc.content.size)) + inputRef.current = '' + handleSubmit(undefined, text) + return true + } + } } - onKeyDown(e) - } + }, + [listFileInWorkspace] + ) + + // Current text from the editor (for checking if the submit button is disabled) + const input = editor?.getText() || '' + + /** + * Expose methods to the parent component via ref + */ + useImperativeHandle( + ref, + () => ({ + focus: () => editor?.commands.focus('end'), + setInput: value => editor?.commands.setContent(value), + input + }), + [editor, input] + ) + + /** + * A helper function to handle form submission + */ + const handleSubmit = async (e?: React.FormEvent, text?: string) => { + e?.preventDefault() + const content = text ?? editor?.getText() + if (isLoading || !content?.trim()) return + await onSubmit(content) + // Clear editor after successful submit + editor?.commands.setContent('') + inputRef.current = '' } + // This element is used as an anchor for the mention popover + const anchorElement = ( +
+ ) + return ( -
- { - if (isOpen && options?.length) { - setSuggestionOpen(isOpen) - } else { - setSuggestionOpen(false) - setOptions([]) - } - }} - > - {({ open, highlightedIndex }) => { - const highlightedOption = options?.[highlightedIndex] + +
+ {/* Editor & Submit row */} +
+ +
+ {/* TipTap editor content */} + +
+ {anchorElement} + {/* Submit Button */} + +
- return ( - <> - -
- - - - { - if (has(e, 'target.value')) { - prevInputSelectionEnd.current = e.target.selectionEnd - setInput(e.target.value) - // TODO: Temporarily disabling the current search function. Will be replaced with a different search functionality in the future. - // handleSearchCompletion(e) - } else { - prevInputSelectionEnd.current = undefined - } - }} - onKeyDown={e => handleTextareaKeyDown(e, open)} - /> -
- - - - - Send message - -
-
-
- e.preventDefault()} - className="w-[60vw] md:w-[430px]" - > - - -
- {open && - !!options?.length && - options.map((item, index) => ( - -
-
- -
- {item?.doc?.name}(...) -
-
-
- {item?.doc?.body} -
-
-
- ))} -
-
- e.preventDefault()} - onKeyDownCapture={e => e.preventDefault()} - className="rounded-none" - collisionPadding={{ bottom: 120 }} - > -
-
- {highlightedOption?.doc?.kind - ? `(${highlightedOption?.doc?.kind}) ` - : ''} - {highlightedOption?.doc?.name} -
-
- {highlightedOption?.doc?.body} -
-
-
-
-
- - ) - }} - + {/* Mention popover (dropdown) */} + + {anchorElement} + e.preventDefault()} + onCloseAutoFocus={e => e.preventDefault()} + onMouseDown={e => { + // Keep focus in the editor + e.preventDefault() + }} + > + { + mentionStateRef.current.selectedIndex = index + triggerUpdate() + }} + /> + + +
) } +/** + * Export the PromptForm as a forwardRef component + */ export const PromptForm = React.forwardRef( PromptFormRenderer ) /** - * Retrieves the name of the completion query from a given string@. - * @param {string} val - The input string to search for the completion query name. - * @param {number | undefined} selectionEnd - The index at which the selection ends in the input string. - * @return {string | undefined} - The name of the completion query if found, otherwise undefined. + * For convenience, also export it as default */ -export function getSearchCompletionQueryName( - val: string, - selectionEnd: number | undefined -): RegExpExecArray | null { - const queryString = val.substring(0, selectionEnd) - const matches = /@(\w+)$/.exec(queryString) - return matches -} - -function IconForCompletionKind({ - kind, - ...rest -}: { kind: string | undefined } & React.ComponentProps<'svg'>) { - switch (kind) { - case 'function': - return - default: - return - } -} +export default PromptForm diff --git a/ee/tabby-ui/package.json b/ee/tabby-ui/package.json index f44474941979..4f4b1792b67d 100644 --- a/ee/tabby-ui/package.json +++ b/ee/tabby-ui/package.json @@ -48,13 +48,16 @@ "@radix-ui/react-toggle": "^1.1.0", "@radix-ui/react-tooltip": "^1.0.7", "@sindresorhus/slugify": "^2.2.1", - "@tiptap/extension-document": "^2.6.6", - "@tiptap/extension-mention": "^2.6.6", - "@tiptap/extension-paragraph": "^2.6.6", - "@tiptap/extension-placeholder": "^2.6.6", - "@tiptap/extension-text": "^2.6.6", + "@tiptap/core": "^2.6.6", + "@tiptap/extension-document": "^2.10.4", + "@tiptap/extension-mention": "^2.10.4", + "@tiptap/extension-paragraph": "^2.10.4", + "@tiptap/extension-placeholder": "^2.10.4", + "@tiptap/extension-text": "^2.10.4", "@tiptap/pm": "^2.6.6", - "@tiptap/react": "^2.6.6", + "@tiptap/react": "^2.10.4", + "@tiptap/starter-kit": "^2.6.6", + "@tiptap/suggestion": "^2.10.4", "@uidotdev/usehooks": "^2.4.1", "@uiw/codemirror-extensions-langs": "^4.21.21", "@urql/core": "^4.2.3", @@ -168,4 +171,4 @@ "typescript": "^5.1.3", "vitest": "^1.5.2" } -} +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d470e02f30eb..23d83263fb20 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -517,27 +517,36 @@ importers: '@sindresorhus/slugify': specifier: ^2.2.1 version: 2.2.1 - '@tiptap/extension-document': + '@tiptap/core': specifier: ^2.6.6 - version: 2.6.6(@tiptap/core@2.6.6(@tiptap/pm@2.6.6)) + version: 2.10.4(@tiptap/pm@2.10.4) + '@tiptap/extension-document': + specifier: ^2.10.4 + version: 2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4)) '@tiptap/extension-mention': - specifier: ^2.6.6 - version: 2.6.6(@tiptap/core@2.6.6(@tiptap/pm@2.6.6))(@tiptap/pm@2.6.6)(@tiptap/suggestion@2.6.6(@tiptap/core@2.6.6(@tiptap/pm@2.6.6))(@tiptap/pm@2.6.6)) + specifier: ^2.10.4 + version: 2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))(@tiptap/pm@2.10.4)(@tiptap/suggestion@2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))(@tiptap/pm@2.10.4)) '@tiptap/extension-paragraph': - specifier: ^2.6.6 - version: 2.6.6(@tiptap/core@2.6.6(@tiptap/pm@2.6.6)) + specifier: ^2.10.4 + version: 2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4)) '@tiptap/extension-placeholder': - specifier: ^2.6.6 - version: 2.6.6(@tiptap/core@2.6.6(@tiptap/pm@2.6.6))(@tiptap/pm@2.6.6) + specifier: ^2.10.4 + version: 2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))(@tiptap/pm@2.10.4) '@tiptap/extension-text': - specifier: ^2.6.6 - version: 2.6.6(@tiptap/core@2.6.6(@tiptap/pm@2.6.6)) + specifier: ^2.10.4 + version: 2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4)) '@tiptap/pm': specifier: ^2.6.6 - version: 2.6.6 + version: 2.10.4 '@tiptap/react': + specifier: ^2.10.4 + version: 2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))(@tiptap/pm@2.10.4)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@tiptap/starter-kit': specifier: ^2.6.6 - version: 2.6.6(@tiptap/core@2.6.6(@tiptap/pm@2.6.6))(@tiptap/pm@2.6.6)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 2.10.4 + '@tiptap/suggestion': + specifier: ^2.10.4 + version: 2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))(@tiptap/pm@2.10.4) '@uidotdev/usehooks': specifier: ^2.4.1 version: 2.4.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0) @@ -3357,8 +3366,8 @@ packages: resolution: {integrity: sha512-kcbt7w23pcVYGLnJkh2LZpXF1OX5RDM4DLOtwPug2HvRE8ow/YfY8ZEM1YCFlA41D8rBPBVP918cYeIx4BVUbw==} engines: {node: '>=14.19.0', npm: '>=7.0.0'} - '@remirror/core-constants@2.0.2': - resolution: {integrity: sha512-dyHY+sMF0ihPus3O27ODd4+agdHMEmuRdyiZJ2CCWjPV5UFmn17ZbElvk6WOGVE4rdCJKZQCrPV2BcikOMLUGQ==} + '@remirror/core-constants@3.0.0': + resolution: {integrity: sha512-42aWfPrimMfDKDi4YegyS7x+/0tlzaqwPQCULLanv3DMIlu96KTJR0fM5isWX2UViOqlGnX6YFgqWepcX+XMNg==} '@repeaterjs/repeater@3.0.5': resolution: {integrity: sha512-l3YHBLAol6d/IKnB9LhpD0cEZWAoe3eFKUyTYWmFmCO2Q/WOckxLQAUyMZWwZV2M/m3+4vgRoaolFqaII82/TA==} @@ -3796,67 +3805,155 @@ packages: peerDependencies: tailwindcss: '>=3.0.0 || insiders' - '@tiptap/core@2.6.6': - resolution: {integrity: sha512-VO5qTsjt6rwworkuo0s5AqYMfDA0ZwiTiH6FHKFSu2G/6sS7HKcc/LjPq+5Legzps4QYdBDl3W28wGsGuS1GdQ==} + '@tiptap/core@2.10.4': + resolution: {integrity: sha512-fExFRTRgb6MSpg2VvR5qO2dPTQAZWuUoU4UsBCurIVcPWcyVv4FG1YzgMyoLDKy44rebFtwUGJbfU9NzX7Q/bA==} peerDependencies: - '@tiptap/pm': ^2.6.6 + '@tiptap/pm': ^2.7.0 - '@tiptap/extension-bubble-menu@2.6.6': - resolution: {integrity: sha512-IkfmlZq67aaegym5sBddBc/xXWCArxn5WJEl1oxKEayjQhybKSaqI7tk0lOx/x7fa5Ml1WlGpCFh+KKXbQTG0g==} + '@tiptap/extension-blockquote@2.10.4': + resolution: {integrity: sha512-4JSwAM3B92YWvGzu/Vd5rovPrCGwLSaSLD5rxcLyfxLSrTDQd3n7lp78pzVgGhunVECzaGF5A0ByWWpEyS0a3w==} peerDependencies: - '@tiptap/core': ^2.6.6 - '@tiptap/pm': ^2.6.6 + '@tiptap/core': ^2.7.0 - '@tiptap/extension-document@2.6.6': - resolution: {integrity: sha512-6qlH5VWzLHHRVeeciRC6C4ZHpMsAGPNG16EF53z0GeMSaaFD/zU3B239QlmqXmLsAl8bpf8Bn93N0t2ABUvScw==} + '@tiptap/extension-bold@2.10.4': + resolution: {integrity: sha512-SdO4oFQKaERCGfwOc1CLYQRtThENam2KWfWmvpsymknokt5qYzU57ft0SE1HQV9vVYEzZ9HrWIgv2xrgu0g9kg==} peerDependencies: - '@tiptap/core': ^2.6.6 + '@tiptap/core': ^2.7.0 - '@tiptap/extension-floating-menu@2.6.6': - resolution: {integrity: sha512-lPkESOfAUxgmXRiNqUU23WSyja5FUfSWjsW4hqe+BKNjsUt1OuFMEtYJtNc+MCGhhtPfFvM3Jg6g9jd6g5XsLQ==} + '@tiptap/extension-bubble-menu@2.10.4': + resolution: {integrity: sha512-GVtZwJaQyLBptMsmDtYl5GEobd1Uu7C9sc9Z+PdXwMuxmFfg+j07bCKCj5JJj/tjgXCSLVxWdTlDHxNrgzQHjw==} peerDependencies: - '@tiptap/core': ^2.6.6 - '@tiptap/pm': ^2.6.6 + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 - '@tiptap/extension-mention@2.6.6': - resolution: {integrity: sha512-fghNe4ZQRiZ7i3+sSrZx87zPZjaCwVtxn56/5UinoBUP/ZpCGwGtI+ErKhCBVyLW1fKyd0MmlihK/IGIeCBw1A==} + '@tiptap/extension-bullet-list@2.10.4': + resolution: {integrity: sha512-JVwDPgOBYRU2ivaadOh4IaQYXQEiSw6sB36KT/bwqJF2GnEvLiMwptdRMn9Uuh6xYR3imjIZtV6uZAoneZdd6g==} peerDependencies: - '@tiptap/core': ^2.6.6 - '@tiptap/pm': ^2.6.6 - '@tiptap/suggestion': ^2.6.6 + '@tiptap/core': ^2.7.0 - '@tiptap/extension-paragraph@2.6.6': - resolution: {integrity: sha512-fD/onCr16UQWx+/xEmuFC2MccZZ7J5u4YaENh8LMnAnBXf78iwU7CAcmuc9rfAEO3qiLoYGXgLKiHlh2ZfD4wA==} + '@tiptap/extension-code-block@2.10.4': + resolution: {integrity: sha512-qS4jnbJqghNMT2+B+GQ807ATgqkL9OQ//NlL+ZwVSe+DPDduNA9B6IB9SrWENDfOnzekpi7kcEcm+RenELARRQ==} peerDependencies: - '@tiptap/core': ^2.6.6 + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 - '@tiptap/extension-placeholder@2.6.6': - resolution: {integrity: sha512-J0ZMvF93NsRrt+R7IQ3GhxNq32vq+88g25oV/YFJiwvC48HMu1tQB6kG1I3LJpu5b8lN+LnfANNqDOEhiBfjaA==} + '@tiptap/extension-code@2.10.4': + resolution: {integrity: sha512-Vj/N0nbSQiV1o7X7pRySK9Fu72Dd266gm27TSlsts6IwJu5MklFvz7ezJUWoLjt2wmCV8/U/USmk/39ic9qjvg==} peerDependencies: - '@tiptap/core': ^2.6.6 - '@tiptap/pm': ^2.6.6 + '@tiptap/core': ^2.7.0 - '@tiptap/extension-text@2.6.6': - resolution: {integrity: sha512-e84uILnRzNzcwK1DVQNpXVmBG1Cq3BJipTOIDl1LHifOok7MBjhI/X+/NR0bd3N2t6gmDTWi63+4GuJ5EeDmsg==} + '@tiptap/extension-document@2.10.4': + resolution: {integrity: sha512-1Pqrl6Rr9bVEHJ3zO2dM7UUA0Qn/r70JQ9YLlestjW1sbMaMuY3Ifvu2uSyUE7SAGV3gvxwNVQCrv8f0VlVEaA==} peerDependencies: - '@tiptap/core': ^2.6.6 + '@tiptap/core': ^2.7.0 - '@tiptap/pm@2.6.6': - resolution: {integrity: sha512-56FGLPn3fwwUlIbLs+BO21bYfyqP9fKyZQbQyY0zWwA/AG2kOwoXaRn7FOVbjP6CylyWpFJnpRRmgn694QKHEg==} + '@tiptap/extension-dropcursor@2.10.4': + resolution: {integrity: sha512-0XEM/yNLaMc/sZlYOau7XpHyYiHT9LwXUe7kmze/L8eowIa/iLvmRbcnUd3rtlZ7x7wooE6UO9c7OtlREg4ZBw==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 - '@tiptap/react@2.6.6': - resolution: {integrity: sha512-AUmdb/J1O/vCO2b8LL68ctcZr9a3931BwX4fUUZ1kCrCA5lTj2xz0rjeAtpxEdzLnR+Z7q96vB7vf7bPYOUAew==} + '@tiptap/extension-floating-menu@2.10.4': + resolution: {integrity: sha512-K2MDiu6CwQ7+Jr6g1Lh3Tuxm1L6SefSHMpQO0UW3aRGwgEV5pjlrztnBFX4K9b7MNuQ4dJGCUK9u8Cv7Xss0qg==} peerDependencies: - '@tiptap/core': ^2.6.6 - '@tiptap/pm': ^2.6.6 - react: ^17.0.0 || ^18.0.0 - react-dom: ^17.0.0 || ^18.0.0 + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + + '@tiptap/extension-gapcursor@2.10.4': + resolution: {integrity: sha512-KbJfoaqTZePpkWAN+klpK5j0UVtELxN7H5B0J556/UCB/rnq+OsdEFHPks2Ss9TidqWzRUqcxUE50UZ7b8h7Ug==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + + '@tiptap/extension-hard-break@2.10.4': + resolution: {integrity: sha512-nW9wubW1A/CO2Ssn9wNMP08tR9Oarg9VUGzJ5qNuz38DDNyntE1SyDS+XStkeMq5nKqJ3YKhukyAJH/PiRq4Mg==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-heading@2.10.4': + resolution: {integrity: sha512-7D0h0MIvE97Gx3Qwuo2xnPDK07WfCnyh4tpOPBOus4e1g6sgxVkwDwhbkYWiwvIrf4BUVJflnke/DEDCVp6/Eg==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-history@2.10.4': + resolution: {integrity: sha512-fg6BNxbpMMtgKaiNI/GLcCzkxIQMwSYBhO9LA0CxLvmsWGU+My4r9W3DK6HwNoRJ9+6OleDPSLo1P73fbSTtEA==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + + '@tiptap/extension-horizontal-rule@2.10.4': + resolution: {integrity: sha512-s9ycm/BOGoW3L0Epnj541vdngHbFbMM488HoODd1CmVSw1C+wBWFgsukgqKjlyE3VGfZXuSb1ur9zinW0RiLJQ==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + + '@tiptap/extension-italic@2.10.4': + resolution: {integrity: sha512-8MIQ+wsbyxNCZDCFTVTOXrS2AvFyOhtlBNgVU2+6r6xnJV4AcfEA3qclysqrjOlL117ped/nzDeoB0AeX0CI+Q==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-list-item@2.10.4': + resolution: {integrity: sha512-8K3WUD5fPyw2poQKnJGGm7zlfeIbpld92+SRF4M9wkp95EzvgexTlodvxlrL3i8zKXcQQVyExWA8kCcGPFb9bA==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-mention@2.10.4': + resolution: {integrity: sha512-pVouKWxSVQSy4zn6HrljPIP1AG826gkm/w18Asi8QnZvR0AMqGLh9q7qd9Kc0j8NKoCzlzK8hECGlYPEaBldow==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + '@tiptap/suggestion': ^2.7.0 + + '@tiptap/extension-ordered-list@2.10.4': + resolution: {integrity: sha512-NaeEu+qFG2O0emc8WlwOM7DKNKOaqHWuNkuKrrmQzslgL+UQSEGlGMo6NEJ5sLLckPBDpIa0MuRm30407JE+cg==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-paragraph@2.10.4': + resolution: {integrity: sha512-SRNVhT8OXqjpZtcyuOtofbtOpXXFrQrjqqCc/yXebda//2SfUTOvB16Lss77vQOWi6xr7TF1mZuowJgSTkcczw==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-placeholder@2.10.4': + resolution: {integrity: sha512-leWG4xP7cvddR6alGZS7yojOh9941bxehgAeQDLlEisaJcNa2Od5Vbap2zipjc5sXMxZakQVChL27oH1wWhHkQ==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + + '@tiptap/extension-strike@2.10.4': + resolution: {integrity: sha512-OibipsomFpOJWTPVX/z4Z53HgwDA93lE/loHGa+ONJfML1dO6Zd6UTwzaVO1/g8WOwRgwkYu/6JnhxLKRlP8Lg==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-text-style@2.10.4': + resolution: {integrity: sha512-ibq7avkcwHyUSG53Hf+P31rrwsKVbbiqbWZM4kXC7M2X3iUwFrtvaa+SWzyWQfE1jl2cCrD1+rfSkj/alcOKGg==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-text@2.10.4': + resolution: {integrity: sha512-wPdVxCHrIS9S+8n08lgyyqRZPj9FBbyLlFt74/lV5yBC3LOorq1VKdjrTskmaj4jud7ImXoKDyBddAYTHdJ1xw==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/pm@2.10.4': + resolution: {integrity: sha512-pZ4NEkRtYoDLe0spARvXZ1N3hNv/5u6vfPdPtEbmNpoOSjSNqDC1kVM+qJY0iaCYpxbxcv7cxn3kBumcFLQpJQ==} + + '@tiptap/react@2.10.4': + resolution: {integrity: sha512-JTeqDB+xgjo46QC9ILRXe2TcSfxKVRwhZ3vDvYoemN7giRk5a/WsCF1VQIT1fax+tCl6kfv3U1f4Mkx0DkbPkA==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + react: ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^17.0.0 || ^18.0.0 || ^19.0.0 + + '@tiptap/starter-kit@2.10.4': + resolution: {integrity: sha512-tu/WCs9Mkr5Nt8c3/uC4VvAbQlVX0OY7ygcqdzHGUeG9zP3twdW7o5xM3kyDKR2++sbVzqu5Ll5qNU+1JZvPGQ==} - '@tiptap/suggestion@2.6.6': - resolution: {integrity: sha512-jogG0QgGit9UtTznVnhQfNImZfQM89NR0is20yRQzC0HmD8B8f3jmGrotG63Why2oKbeoe3CpM5/5eDE/paqCA==} + '@tiptap/suggestion@2.10.4': + resolution: {integrity: sha512-7Bzcn1REA7OmVRxiMF2kVK9EhosXotdLAGaEvSbn4zQtHCJG0tREuYvPy53LGzVuPkBDR6Pf6sp1QbGvSne/8g==} peerDependencies: - '@tiptap/core': ^2.6.6 - '@tiptap/pm': ^2.6.6 + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 '@tootallnate/once@1.1.2': resolution: {integrity: sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==} @@ -3998,15 +4095,24 @@ packages: '@types/katex@0.16.3': resolution: {integrity: sha512-CeVMX9EhVUW8MWnei05eIRks4D5Wscw/W9Byz1s3PA+yJvcdvq9SaDjiUKvRvEgjpdTyJMjQA43ae4KTwsvOPg==} + '@types/linkify-it@5.0.0': + resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==} + '@types/lodash-es@4.17.10': resolution: {integrity: sha512-YJP+w/2khSBwbUSFdGsSqmDvmnN3cCKoPOL7Zjle6s30ZtemkkqhjVfFqGwPN7ASil5VyjE2GtyU/yqYY6mC0A==} '@types/lodash@4.14.200': resolution: {integrity: sha512-YI/M/4HRImtNf3pJgbF+W6FrXovqj+T+/HpENLTooK9PnkacBsDpeP3IpHab40CClUfhNmdM2WTNP2sa2dni5Q==} + '@types/markdown-it@14.1.2': + resolution: {integrity: sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==} + '@types/mdast@3.0.13': resolution: {integrity: sha512-HjiGiWedR0DVFkeNljpa6Lv4/IZU1+30VY5d747K7lBudFc3R0Ibr6yJ9lN3BE28VnZyDfLF/VB1Ql1ZIbKrmg==} + '@types/mdurl@2.0.0': + resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==} + '@types/minimatch@5.1.2': resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} @@ -8848,8 +8954,8 @@ packages: prosemirror-collab@1.3.1: resolution: {integrity: sha512-4SnynYR9TTYaQVXd/ieUvsVV4PDMBzrq2xPUWutHivDuOshZXqQ5rGbZM84HEaXKbLdItse7weMGOUdDVcLKEQ==} - prosemirror-commands@1.6.0: - resolution: {integrity: sha512-xn1U/g36OqXn2tn5nGmvnnimAj/g1pUx2ypJJIe8WkVX83WyJVC5LTARaxZa2AtQRwntu9Jc5zXs9gL9svp/mg==} + prosemirror-commands@1.6.2: + resolution: {integrity: sha512-0nDHH++qcf/BuPLYvmqZTUUsPJUCPBUXt0J1ErTcDIS369CTp773itzLGIgIXG4LJXOlwYCr44+Mh4ii6MP1QA==} prosemirror-dropcursor@1.8.1: resolution: {integrity: sha512-M30WJdJZLyXHi3N8vxN6Zh5O8ZBbQCz0gURTfPmTIBNQ5pxrdU7A58QkNqfa98YEjSAL1HUyyU34f6Pm5xBSGw==} @@ -8866,14 +8972,14 @@ packages: prosemirror-keymap@1.2.2: resolution: {integrity: sha512-EAlXoksqC6Vbocqc0GtzCruZEzYgrn+iiGnNjsJsH4mrnIGex4qbLdWWNza3AW5W36ZRrlBID0eM6bdKH4OStQ==} - prosemirror-markdown@1.13.0: - resolution: {integrity: sha512-UziddX3ZYSYibgx8042hfGKmukq5Aljp2qoBiJRejD/8MH70siQNz5RB1TrdTPheqLMy4aCe4GYNF10/3lQS5g==} + prosemirror-markdown@1.13.1: + resolution: {integrity: sha512-Sl+oMfMtAjWtlcZoj/5L/Q39MpEnVZ840Xo330WJWUvgyhNmLBLN7MsHn07s53nG/KImevWHSE6fEj4q/GihHw==} prosemirror-menu@1.2.4: resolution: {integrity: sha512-S/bXlc0ODQup6aiBbWVsX/eM+xJgCTAfMq/nLqaO5ID/am4wS0tTCIkzwytmao7ypEtjj39i7YbJjAgO20mIqA==} - prosemirror-model@1.22.3: - resolution: {integrity: sha512-V4XCysitErI+i0rKFILGt/xClnFJaohe/wrrlT2NSZ+zk8ggQfDH4x2wNK7Gm0Hp4CIoWizvXFP7L9KMaCuI0Q==} + prosemirror-model@1.24.1: + resolution: {integrity: sha512-YM053N+vTThzlWJ/AtPtF1j0ebO36nvbmDy4U7qA2XQB8JVaQp1FmB9Jhrps8s+z+uxhhVTny4m20ptUvhk0Mg==} prosemirror-schema-basic@1.2.3: resolution: {integrity: sha512-h+H0OQwZVqMon1PNn0AG9cTfx513zgIG2DY00eJ00Yvgb3UD+GQ/VlWW5rcaxacpCGT1Yx8nuhwXk4+QbXUfJA==} @@ -8884,21 +8990,21 @@ packages: prosemirror-state@1.4.3: resolution: {integrity: sha512-goFKORVbvPuAQaXhpbemJFRKJ2aixr+AZMGiquiqKxaucC6hlpHNZHWgz5R7dS4roHiwq9vDctE//CZ++o0W1Q==} - prosemirror-tables@1.5.0: - resolution: {integrity: sha512-VMx4zlYWm7aBlZ5xtfJHpqa3Xgu3b7srV54fXYnXgsAcIGRqKSrhiK3f89omzzgaAgAtDOV4ImXnLKhVfheVNQ==} + prosemirror-tables@1.6.1: + resolution: {integrity: sha512-p8WRJNA96jaNQjhJolmbxTzd6M4huRE5xQ8OxjvMhQUP0Nzpo4zz6TztEiwk6aoqGBhz9lxRWR1yRZLlpQN98w==} - prosemirror-trailing-node@2.0.9: - resolution: {integrity: sha512-YvyIn3/UaLFlFKrlJB6cObvUhmwFNZVhy1Q8OpW/avoTbD/Y7H5EcjK4AZFKhmuS6/N6WkGgt7gWtBWDnmFvHg==} + prosemirror-trailing-node@3.0.0: + resolution: {integrity: sha512-xiun5/3q0w5eRnGYfNlW1uU9W6x5MoFKWwq/0TIRgt09lv7Hcser2QYV8t4muXbEr+Fwo0geYn79Xs4GKywrRQ==} peerDependencies: prosemirror-model: ^1.22.1 prosemirror-state: ^1.4.2 prosemirror-view: ^1.33.8 - prosemirror-transform@1.10.0: - resolution: {integrity: sha512-9UOgFSgN6Gj2ekQH5CTDJ8Rp/fnKR2IkYfGdzzp5zQMFsS4zDllLVx/+jGcX86YlACpG7UR5fwAXiWzxqWtBTg==} + prosemirror-transform@1.10.2: + resolution: {integrity: sha512-2iUq0wv2iRoJO/zj5mv8uDUriOHWzXRnOTVgCzSXnktS/2iQRa3UUQwVlkBlYZFtygw6Nh1+X4mGqoYBINn5KQ==} - prosemirror-view@1.34.1: - resolution: {integrity: sha512-KS2xmqrAM09h3SLu1S2pNO/ZoIP38qkTJ6KFd7+BeSfmX/ek0n5yOfGuiTZjFNTC8GOsEIUa1tHxt+2FMu3yWQ==} + prosemirror-view@1.37.1: + resolution: {integrity: sha512-MEAnjOdXU1InxEmhjgmEzQAikaS6lF3hD64MveTPpjOGNTl87iRLA1HupC/DEV6YuK7m4Q9DHFNTjwIVtqz5NA==} proto-list@1.2.4: resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} @@ -13863,7 +13969,7 @@ snapshots: - encoding - supports-color - '@remirror/core-constants@2.0.2': {} + '@remirror/core-constants@3.0.0': {} '@repeaterjs/repeater@3.0.5': {} @@ -14224,81 +14330,175 @@ snapshots: postcss-selector-parser: 6.0.10 tailwindcss: 3.3.3(ts-node@10.9.2(@types/node@17.0.45)(typescript@5.2.2)) - '@tiptap/core@2.6.6(@tiptap/pm@2.6.6)': + '@tiptap/core@2.10.4(@tiptap/pm@2.10.4)': dependencies: - '@tiptap/pm': 2.6.6 + '@tiptap/pm': 2.10.4 - '@tiptap/extension-bubble-menu@2.6.6(@tiptap/core@2.6.6(@tiptap/pm@2.6.6))(@tiptap/pm@2.6.6)': + '@tiptap/extension-blockquote@2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))': dependencies: - '@tiptap/core': 2.6.6(@tiptap/pm@2.6.6) - '@tiptap/pm': 2.6.6 + '@tiptap/core': 2.10.4(@tiptap/pm@2.10.4) + + '@tiptap/extension-bold@2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))': + dependencies: + '@tiptap/core': 2.10.4(@tiptap/pm@2.10.4) + + '@tiptap/extension-bubble-menu@2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))(@tiptap/pm@2.10.4)': + dependencies: + '@tiptap/core': 2.10.4(@tiptap/pm@2.10.4) + '@tiptap/pm': 2.10.4 tippy.js: 6.3.7 - '@tiptap/extension-document@2.6.6(@tiptap/core@2.6.6(@tiptap/pm@2.6.6))': + '@tiptap/extension-bullet-list@2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))': + dependencies: + '@tiptap/core': 2.10.4(@tiptap/pm@2.10.4) + + '@tiptap/extension-code-block@2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))(@tiptap/pm@2.10.4)': + dependencies: + '@tiptap/core': 2.10.4(@tiptap/pm@2.10.4) + '@tiptap/pm': 2.10.4 + + '@tiptap/extension-code@2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))': dependencies: - '@tiptap/core': 2.6.6(@tiptap/pm@2.6.6) + '@tiptap/core': 2.10.4(@tiptap/pm@2.10.4) - '@tiptap/extension-floating-menu@2.6.6(@tiptap/core@2.6.6(@tiptap/pm@2.6.6))(@tiptap/pm@2.6.6)': + '@tiptap/extension-document@2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))': dependencies: - '@tiptap/core': 2.6.6(@tiptap/pm@2.6.6) - '@tiptap/pm': 2.6.6 + '@tiptap/core': 2.10.4(@tiptap/pm@2.10.4) + + '@tiptap/extension-dropcursor@2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))(@tiptap/pm@2.10.4)': + dependencies: + '@tiptap/core': 2.10.4(@tiptap/pm@2.10.4) + '@tiptap/pm': 2.10.4 + + '@tiptap/extension-floating-menu@2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))(@tiptap/pm@2.10.4)': + dependencies: + '@tiptap/core': 2.10.4(@tiptap/pm@2.10.4) + '@tiptap/pm': 2.10.4 tippy.js: 6.3.7 - '@tiptap/extension-mention@2.6.6(@tiptap/core@2.6.6(@tiptap/pm@2.6.6))(@tiptap/pm@2.6.6)(@tiptap/suggestion@2.6.6(@tiptap/core@2.6.6(@tiptap/pm@2.6.6))(@tiptap/pm@2.6.6))': + '@tiptap/extension-gapcursor@2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))(@tiptap/pm@2.10.4)': + dependencies: + '@tiptap/core': 2.10.4(@tiptap/pm@2.10.4) + '@tiptap/pm': 2.10.4 + + '@tiptap/extension-hard-break@2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))': + dependencies: + '@tiptap/core': 2.10.4(@tiptap/pm@2.10.4) + + '@tiptap/extension-heading@2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))': + dependencies: + '@tiptap/core': 2.10.4(@tiptap/pm@2.10.4) + + '@tiptap/extension-history@2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))(@tiptap/pm@2.10.4)': dependencies: - '@tiptap/core': 2.6.6(@tiptap/pm@2.6.6) - '@tiptap/pm': 2.6.6 - '@tiptap/suggestion': 2.6.6(@tiptap/core@2.6.6(@tiptap/pm@2.6.6))(@tiptap/pm@2.6.6) + '@tiptap/core': 2.10.4(@tiptap/pm@2.10.4) + '@tiptap/pm': 2.10.4 - '@tiptap/extension-paragraph@2.6.6(@tiptap/core@2.6.6(@tiptap/pm@2.6.6))': + '@tiptap/extension-horizontal-rule@2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))(@tiptap/pm@2.10.4)': dependencies: - '@tiptap/core': 2.6.6(@tiptap/pm@2.6.6) + '@tiptap/core': 2.10.4(@tiptap/pm@2.10.4) + '@tiptap/pm': 2.10.4 - '@tiptap/extension-placeholder@2.6.6(@tiptap/core@2.6.6(@tiptap/pm@2.6.6))(@tiptap/pm@2.6.6)': + '@tiptap/extension-italic@2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))': dependencies: - '@tiptap/core': 2.6.6(@tiptap/pm@2.6.6) - '@tiptap/pm': 2.6.6 + '@tiptap/core': 2.10.4(@tiptap/pm@2.10.4) - '@tiptap/extension-text@2.6.6(@tiptap/core@2.6.6(@tiptap/pm@2.6.6))': + '@tiptap/extension-list-item@2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))': dependencies: - '@tiptap/core': 2.6.6(@tiptap/pm@2.6.6) + '@tiptap/core': 2.10.4(@tiptap/pm@2.10.4) - '@tiptap/pm@2.6.6': + '@tiptap/extension-mention@2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))(@tiptap/pm@2.10.4)(@tiptap/suggestion@2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))(@tiptap/pm@2.10.4))': + dependencies: + '@tiptap/core': 2.10.4(@tiptap/pm@2.10.4) + '@tiptap/pm': 2.10.4 + '@tiptap/suggestion': 2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))(@tiptap/pm@2.10.4) + + '@tiptap/extension-ordered-list@2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))': + dependencies: + '@tiptap/core': 2.10.4(@tiptap/pm@2.10.4) + + '@tiptap/extension-paragraph@2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))': + dependencies: + '@tiptap/core': 2.10.4(@tiptap/pm@2.10.4) + + '@tiptap/extension-placeholder@2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))(@tiptap/pm@2.10.4)': + dependencies: + '@tiptap/core': 2.10.4(@tiptap/pm@2.10.4) + '@tiptap/pm': 2.10.4 + + '@tiptap/extension-strike@2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))': + dependencies: + '@tiptap/core': 2.10.4(@tiptap/pm@2.10.4) + + '@tiptap/extension-text-style@2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))': + dependencies: + '@tiptap/core': 2.10.4(@tiptap/pm@2.10.4) + + '@tiptap/extension-text@2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))': + dependencies: + '@tiptap/core': 2.10.4(@tiptap/pm@2.10.4) + + '@tiptap/pm@2.10.4': dependencies: prosemirror-changeset: 2.2.1 prosemirror-collab: 1.3.1 - prosemirror-commands: 1.6.0 + prosemirror-commands: 1.6.2 prosemirror-dropcursor: 1.8.1 prosemirror-gapcursor: 1.3.2 prosemirror-history: 1.4.1 prosemirror-inputrules: 1.4.0 prosemirror-keymap: 1.2.2 - prosemirror-markdown: 1.13.0 + prosemirror-markdown: 1.13.1 prosemirror-menu: 1.2.4 - prosemirror-model: 1.22.3 + prosemirror-model: 1.24.1 prosemirror-schema-basic: 1.2.3 prosemirror-schema-list: 1.4.1 prosemirror-state: 1.4.3 - prosemirror-tables: 1.5.0 - prosemirror-trailing-node: 2.0.9(prosemirror-model@1.22.3)(prosemirror-state@1.4.3)(prosemirror-view@1.34.1) - prosemirror-transform: 1.10.0 - prosemirror-view: 1.34.1 + prosemirror-tables: 1.6.1 + prosemirror-trailing-node: 3.0.0(prosemirror-model@1.24.1)(prosemirror-state@1.4.3)(prosemirror-view@1.37.1) + prosemirror-transform: 1.10.2 + prosemirror-view: 1.37.1 - '@tiptap/react@2.6.6(@tiptap/core@2.6.6(@tiptap/pm@2.6.6))(@tiptap/pm@2.6.6)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + '@tiptap/react@2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))(@tiptap/pm@2.10.4)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': dependencies: - '@tiptap/core': 2.6.6(@tiptap/pm@2.6.6) - '@tiptap/extension-bubble-menu': 2.6.6(@tiptap/core@2.6.6(@tiptap/pm@2.6.6))(@tiptap/pm@2.6.6) - '@tiptap/extension-floating-menu': 2.6.6(@tiptap/core@2.6.6(@tiptap/pm@2.6.6))(@tiptap/pm@2.6.6) - '@tiptap/pm': 2.6.6 + '@tiptap/core': 2.10.4(@tiptap/pm@2.10.4) + '@tiptap/extension-bubble-menu': 2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))(@tiptap/pm@2.10.4) + '@tiptap/extension-floating-menu': 2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))(@tiptap/pm@2.10.4) + '@tiptap/pm': 2.10.4 '@types/use-sync-external-store': 0.0.6 + fast-deep-equal: 3.1.3 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) use-sync-external-store: 1.2.2(react@18.2.0) - '@tiptap/suggestion@2.6.6(@tiptap/core@2.6.6(@tiptap/pm@2.6.6))(@tiptap/pm@2.6.6)': - dependencies: - '@tiptap/core': 2.6.6(@tiptap/pm@2.6.6) - '@tiptap/pm': 2.6.6 + '@tiptap/starter-kit@2.10.4': + dependencies: + '@tiptap/core': 2.10.4(@tiptap/pm@2.10.4) + '@tiptap/extension-blockquote': 2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4)) + '@tiptap/extension-bold': 2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4)) + '@tiptap/extension-bullet-list': 2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4)) + '@tiptap/extension-code': 2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4)) + '@tiptap/extension-code-block': 2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))(@tiptap/pm@2.10.4) + '@tiptap/extension-document': 2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4)) + '@tiptap/extension-dropcursor': 2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))(@tiptap/pm@2.10.4) + '@tiptap/extension-gapcursor': 2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))(@tiptap/pm@2.10.4) + '@tiptap/extension-hard-break': 2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4)) + '@tiptap/extension-heading': 2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4)) + '@tiptap/extension-history': 2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))(@tiptap/pm@2.10.4) + '@tiptap/extension-horizontal-rule': 2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))(@tiptap/pm@2.10.4) + '@tiptap/extension-italic': 2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4)) + '@tiptap/extension-list-item': 2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4)) + '@tiptap/extension-ordered-list': 2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4)) + '@tiptap/extension-paragraph': 2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4)) + '@tiptap/extension-strike': 2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4)) + '@tiptap/extension-text': 2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4)) + '@tiptap/extension-text-style': 2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4)) + '@tiptap/pm': 2.10.4 + + '@tiptap/suggestion@2.10.4(@tiptap/core@2.10.4(@tiptap/pm@2.10.4))(@tiptap/pm@2.10.4)': + dependencies: + '@tiptap/core': 2.10.4(@tiptap/pm@2.10.4) + '@tiptap/pm': 2.10.4 '@tootallnate/once@1.1.2': {} @@ -14426,16 +14626,25 @@ snapshots: '@types/katex@0.16.3': {} + '@types/linkify-it@5.0.0': {} + '@types/lodash-es@4.17.10': dependencies: '@types/lodash': 4.14.200 '@types/lodash@4.14.200': {} + '@types/markdown-it@14.1.2': + dependencies: + '@types/linkify-it': 5.0.0 + '@types/mdurl': 2.0.0 + '@types/mdast@3.0.13': dependencies: '@types/unist': 2.0.8 + '@types/mdurl@2.0.0': {} + '@types/minimatch@5.1.2': {} '@types/mocha@10.0.6': {} @@ -20497,105 +20706,106 @@ snapshots: prosemirror-changeset@2.2.1: dependencies: - prosemirror-transform: 1.10.0 + prosemirror-transform: 1.10.2 prosemirror-collab@1.3.1: dependencies: prosemirror-state: 1.4.3 - prosemirror-commands@1.6.0: + prosemirror-commands@1.6.2: dependencies: - prosemirror-model: 1.22.3 + prosemirror-model: 1.24.1 prosemirror-state: 1.4.3 - prosemirror-transform: 1.10.0 + prosemirror-transform: 1.10.2 prosemirror-dropcursor@1.8.1: dependencies: prosemirror-state: 1.4.3 - prosemirror-transform: 1.10.0 - prosemirror-view: 1.34.1 + prosemirror-transform: 1.10.2 + prosemirror-view: 1.37.1 prosemirror-gapcursor@1.3.2: dependencies: prosemirror-keymap: 1.2.2 - prosemirror-model: 1.22.3 + prosemirror-model: 1.24.1 prosemirror-state: 1.4.3 - prosemirror-view: 1.34.1 + prosemirror-view: 1.37.1 prosemirror-history@1.4.1: dependencies: prosemirror-state: 1.4.3 - prosemirror-transform: 1.10.0 - prosemirror-view: 1.34.1 + prosemirror-transform: 1.10.2 + prosemirror-view: 1.37.1 rope-sequence: 1.3.4 prosemirror-inputrules@1.4.0: dependencies: prosemirror-state: 1.4.3 - prosemirror-transform: 1.10.0 + prosemirror-transform: 1.10.2 prosemirror-keymap@1.2.2: dependencies: prosemirror-state: 1.4.3 w3c-keyname: 2.2.8 - prosemirror-markdown@1.13.0: + prosemirror-markdown@1.13.1: dependencies: + '@types/markdown-it': 14.1.2 markdown-it: 14.1.0 - prosemirror-model: 1.22.3 + prosemirror-model: 1.24.1 prosemirror-menu@1.2.4: dependencies: crelt: 1.0.6 - prosemirror-commands: 1.6.0 + prosemirror-commands: 1.6.2 prosemirror-history: 1.4.1 prosemirror-state: 1.4.3 - prosemirror-model@1.22.3: + prosemirror-model@1.24.1: dependencies: orderedmap: 2.1.1 prosemirror-schema-basic@1.2.3: dependencies: - prosemirror-model: 1.22.3 + prosemirror-model: 1.24.1 prosemirror-schema-list@1.4.1: dependencies: - prosemirror-model: 1.22.3 + prosemirror-model: 1.24.1 prosemirror-state: 1.4.3 - prosemirror-transform: 1.10.0 + prosemirror-transform: 1.10.2 prosemirror-state@1.4.3: dependencies: - prosemirror-model: 1.22.3 - prosemirror-transform: 1.10.0 - prosemirror-view: 1.34.1 + prosemirror-model: 1.24.1 + prosemirror-transform: 1.10.2 + prosemirror-view: 1.37.1 - prosemirror-tables@1.5.0: + prosemirror-tables@1.6.1: dependencies: prosemirror-keymap: 1.2.2 - prosemirror-model: 1.22.3 + prosemirror-model: 1.24.1 prosemirror-state: 1.4.3 - prosemirror-transform: 1.10.0 - prosemirror-view: 1.34.1 + prosemirror-transform: 1.10.2 + prosemirror-view: 1.37.1 - prosemirror-trailing-node@2.0.9(prosemirror-model@1.22.3)(prosemirror-state@1.4.3)(prosemirror-view@1.34.1): + prosemirror-trailing-node@3.0.0(prosemirror-model@1.24.1)(prosemirror-state@1.4.3)(prosemirror-view@1.37.1): dependencies: - '@remirror/core-constants': 2.0.2 + '@remirror/core-constants': 3.0.0 escape-string-regexp: 4.0.0 - prosemirror-model: 1.22.3 + prosemirror-model: 1.24.1 prosemirror-state: 1.4.3 - prosemirror-view: 1.34.1 + prosemirror-view: 1.37.1 - prosemirror-transform@1.10.0: + prosemirror-transform@1.10.2: dependencies: - prosemirror-model: 1.22.3 + prosemirror-model: 1.24.1 - prosemirror-view@1.34.1: + prosemirror-view@1.37.1: dependencies: - prosemirror-model: 1.22.3 + prosemirror-model: 1.24.1 prosemirror-state: 1.4.3 - prosemirror-transform: 1.10.0 + prosemirror-transform: 1.10.2 proto-list@1.2.4: {}