diff --git a/ee/tabby-ui/components/chat/popover-mention-list.tsx b/ee/tabby-ui/components/chat/popover-mention-list.tsx
new file mode 100644
index 000000000000..efe5a702160d
--- /dev/null
+++ b/ee/tabby-ui/components/chat/popover-mention-list.tsx
@@ -0,0 +1,130 @@
+import React, { useEffect, useRef } from 'react'
+
+import { MentionNodeAttrs, SourceItem } from './prompt-form-editor/types'
+
+interface PopoverMentionListProps {
+ items: SourceItem[]
+ selectedIndex: number
+ onUpdateSelectedIndex: (index: number) => void
+ handleItemSelection: (
+ item: SourceItem,
+ command?: (props: MentionNodeAttrs) => void
+ ) => void
+}
+
+// Maximum number of items visible in the list
+const MAX_VISIBLE_ITEMS = 4
+// Height of each item in pixels
+const ITEM_HEIGHT = 42
+
+export const PopoverMentionList: React.FC
= ({
+ items,
+ selectedIndex,
+ onUpdateSelectedIndex,
+ handleItemSelection
+}) => {
+ const selectedItemRef = useRef(null)
+ const containerRef = useRef(null)
+
+ // Dynamically calculate container height based on number of items
+ const containerHeight =
+ Math.min(items.length, MAX_VISIBLE_ITEMS) * ITEM_HEIGHT
+
+ // Scroll into view for the currently selected item
+ useEffect(() => {
+ const container = containerRef.current
+ const selectedItem = selectedItemRef.current
+ if (container && selectedItem) {
+ const containerTop = container.scrollTop
+ const containerBottom = containerTop + container.clientHeight
+ const itemTop = selectedItem.offsetTop
+ const itemBottom = itemTop + selectedItem.offsetHeight
+
+ if (itemTop < containerTop) {
+ container.scrollTop = itemTop
+ } else if (itemBottom > containerBottom) {
+ container.scrollTop = itemBottom - container.clientHeight
+ }
+ }
+ }, [selectedIndex])
+
+ // Render list content
+ const renderContent = () => {
+ if (!items.length) {
+ return (
+
+ No files found
+
+ )
+ }
+
+ return (
+
+ {items.map((item, index) => {
+ const filepath = item.filepath
+ const isSelected = index === selectedIndex
+
+ return (
+
+ )
+ })}
+
+ )
+ }
+
+ return <>{renderContent()}>
+}
diff --git a/ee/tabby-ui/components/chat/prompt-form-editor/mention-component.tsx b/ee/tabby-ui/components/chat/prompt-form-editor/mention-component.tsx
new file mode 100644
index 000000000000..e79cc4e6a698
--- /dev/null
+++ b/ee/tabby-ui/components/chat/prompt-form-editor/mention-component.tsx
@@ -0,0 +1,37 @@
+/* eslint-disable no-console */
+// mention-component.tsx
+import React from 'react'
+import { NodeViewWrapper } from '@tiptap/react'
+
+import { cn } from '@/lib/utils'
+
+export const PromptFormMentionComponent = ({ node }: { node: any }) => {
+ console.log('mention comp:' + JSON.stringify(node.attrs))
+ return (
+
+
+ {node.attrs.category === 'file' ? (
+
+ ) : (
+ @
+ )}
+ {node.attrs.name}
+
+
+ )
+}
diff --git a/ee/tabby-ui/components/chat/prompt-form-editor/mention-extension.ts b/ee/tabby-ui/components/chat/prompt-form-editor/mention-extension.ts
new file mode 100644
index 000000000000..714fe0053961
--- /dev/null
+++ b/ee/tabby-ui/components/chat/prompt-form-editor/mention-extension.ts
@@ -0,0 +1,43 @@
+import Mention from '@tiptap/extension-mention'
+import { ReactNodeViewRenderer } from '@tiptap/react'
+
+import { PromptFormMentionComponent } from './mention-component'
+
+export const MENTION_EXTENSION_NAME = 'mention'
+
+export const PromptFormMentionExtension = Mention.extend({
+ addNodeView() {
+ return ReactNodeViewRenderer(PromptFormMentionComponent)
+ },
+ renderText({ node }) {
+ return `[[atSource:${JSON.stringify(node.attrs.atInfo)}]]`
+ },
+ addAttributes() {
+ return {
+ name: {
+ default: null,
+ parseHTML: element => element.getAttribute('data-name'),
+ renderHTML: attributes => ({
+ 'data-name': attributes.name
+ })
+ },
+ category: {
+ default: 'file',
+ parseHTML: element => element.getAttribute('data-category'),
+ renderHTML: attributes => ({
+ 'data-category': attributes.category
+ })
+ },
+ atInfo: {
+ default: null,
+ parseHTML: element => {
+ const atInfo = element.getAttribute('data-at-info')
+ return atInfo ? JSON.parse(atInfo) : null
+ },
+ renderHTML: attributes => ({
+ 'data-at-info': JSON.stringify(attributes.atInfo)
+ })
+ }
+ }
+ }
+})
diff --git a/ee/tabby-ui/components/chat/prompt-form-editor/types.ts b/ee/tabby-ui/components/chat/prompt-form-editor/types.ts
new file mode 100644
index 000000000000..5fc94f1bfc61
--- /dev/null
+++ b/ee/tabby-ui/components/chat/prompt-form-editor/types.ts
@@ -0,0 +1,88 @@
+/* eslint-disable no-console */
+import { AtInfo } from 'tabby-chat-panel/index'
+
+/**
+ * Types of mention categories, such as files, symbols, or categories.
+ * 'categories' serves as a root-level menu before selecting 'files' or 'symbols'.
+ */
+export type MentionCategory = 'files' | 'symbols' | 'categories'
+
+/**
+ * The first level pop menu.
+ */
+export const CATEGORIES_MENU: SourceItem[] = [
+ {
+ name: 'Files',
+ category: 'categories',
+ filepath: ''
+ },
+ {
+ name: 'Symbols',
+ category: 'categories',
+ filepath: ''
+ }
+]
+
+/**
+ * Represents an item that can be mentioned, such as a file or symbol.
+ */
+export interface SourceItem {
+ /**
+ * Original 'AtInfo' object, It could be optional if we are in root level
+ */
+ atInfo?: AtInfo
+
+ /**
+ * Name derived from 'atInfo.name'.
+ * Typically a filename or symbol name that will be shown in the mention list.
+ */
+ name: string
+
+ /**
+ * Filepath or a descriptive path to be shown in the UI.
+ */
+ filepath: string
+
+ /**
+ * The mention category, e.g. 'files', 'symbols', or 'categories'.
+ */
+ category: MentionCategory
+}
+
+/**
+ * Alias of SourceItem, used for option lists.
+ */
+export type OptionItem = SourceItem
+
+/**
+ * Manages the current view of the mention menu.
+ * For example, 'categories' or directly 'files'/'symbols'.
+ */
+export interface MenuState {
+ view: MentionCategory
+}
+
+/**
+ * Attributes for a mention node used by the Tiptap editor.
+ * 'id' is required by Tiptap. 'atInfo' holds optional extra data.
+ */
+export interface MentionNodeAttrs {
+ id: string
+ name: string
+ category: MentionCategory
+ atInfo: AtInfo // TODO: Consider removing if not needed in final implementation
+}
+
+/**
+ * Represents the suggestion popover state:
+ * - items: the current list of potential mentions
+ * - command: the Tiptap command function to insert the mention
+ * - clientRect: a function returning the current bounding box for positioning
+ * - selectedIndex: the index of the currently highlighted item
+ */
+export interface SuggestionState {
+ items: SourceItem[]
+ command: (props: MentionNodeAttrs) => void
+ clientRect: () => DOMRect | null
+ selectedIndex: number
+}
diff --git a/ee/tabby-ui/components/chat/prompt-form-editor/utils.ts b/ee/tabby-ui/components/chat/prompt-form-editor/utils.ts
new file mode 100644
index 000000000000..645bb1b02498
--- /dev/null
+++ b/ee/tabby-ui/components/chat/prompt-form-editor/utils.ts
@@ -0,0 +1,85 @@
+import { AtInfo, FileAtInfo } from 'tabby-chat-panel/index'
+
+import { MentionNodeAttrs, SourceItem } from './types'
+
+/**
+ * A regex to detect patterns like [[atSource: {...}]]
+ * The JSON inside can be parsed to reconstruct AtInfo data.
+ */
+export const AT_SOURCE_REGEX = /\[\[atSource:(.*?)\]\]/g
+
+/**
+ * Type guard to check if the given AtInfo is a FileAtInfo.
+ */
+export function isFileAtInfo(atInfo: AtInfo): atInfo is FileAtInfo {
+ return atInfo.atKind === 'file'
+}
+
+/**
+ * Convert an AtInfo object into a SourceItem for display and mention.
+ * @param info An AtInfo object from tabby-chat-panel
+ * @returns A SourceItem containing category, name, filepath, and the raw atInfo
+ */
+export function atInfoToSourceItem(info: AtInfo): SourceItem {
+ if (isFileAtInfo(info)) {
+ return {
+ category: 'files' as const,
+ atInfo: info,
+ name: info.name,
+ filepath:
+ 'uri' in info.filepath ? info.filepath.uri : info.filepath.filepath
+ }
+ } else {
+ return {
+ category: 'symbols' as const,
+ atInfo: info,
+ name: info.name,
+ filepath:
+ 'uri' in info.location.filepath
+ ? info.location.filepath.uri
+ : info.location.filepath.filepath
+ }
+ }
+}
+
+/**
+ * Convert a SourceItem into a MentionNodeAttrs object to be used by Tiptap.
+ * Useful for inserting a mention node into the editor.
+ * @param item The SourceItem to convert
+ * @returns The mention node attributes needed by Tiptap
+ */
+export function sourceItemToMentionNodeAttrs(
+ item: SourceItem
+): MentionNodeAttrs {
+ return {
+ id: `${item.name}-${item.filepath}`,
+ name: item.name,
+ category: item.category,
+ atInfo: item.atInfo!
+ }
+}
+
+/**
+ * Extracts AtInfo objects from text that match the AT_SOURCE_REGEX pattern.
+ * Replaces the matched patterns with @ in the original text.
+ * @param text The text to parse
+ * @returns An object with updated text (after replacement) and a list of extracted AtInfo
+ */
+export function extractAtSourceFromString(text: string) {
+ const atInfos: AtInfo[] = []
+ let match
+
+ while ((match = AT_SOURCE_REGEX.exec(text))) {
+ const sourceData = match[1]
+ try {
+ const parsedAtInfo = JSON.parse(sourceData)
+ atInfos.push(parsedAtInfo)
+ text = text.replace(match[0], `@${parsedAtInfo.name}`)
+ } catch {
+ // If JSON parsing fails, skip this match
+ continue
+ }
+ }
+
+ return { text, atInfos }
+}
diff --git a/ee/tabby-ui/components/chat/prompt-form.css b/ee/tabby-ui/components/chat/prompt-form.css
new file mode 100644
index 000000000000..3c979015534d
--- /dev/null
+++ b/ee/tabby-ui/components/chat/prompt-form.css
@@ -0,0 +1,22 @@
+.source-mention {
+ @apply inline-flex items-baseline space-x-1;
+}
+
+.tiptap .mention {
+ @apply bg-muted text-muted-foreground px-1.5 py-0.5 rounded;
+}
+
+.tiptap p.is-editor-empty:first-child::before {
+ @apply text-muted-foreground float-left;
+ content: attr(data-placeholder);
+ float: left;
+ height: 0;
+ pointer-events: none;
+}
+.ProseMirror {
+ outline: none !important;
+}
+
+.ProseMirror-focused {
+ outline: none !important;
+}
diff --git a/ee/tabby-ui/components/chat/prompt-form.tsx b/ee/tabby-ui/components/chat/prompt-form.tsx
index 98fcd56d54ec..7ca09b3fc77e 100644
--- a/ee/tabby-ui/components/chat/prompt-form.tsx
+++ b/ee/tabby-ui/components/chat/prompt-form.tsx
@@ -1,348 +1,457 @@
-import * as React from 'react'
-import { UseChatHelpers } from 'ai/react'
-import { debounce, has } from 'lodash-es'
-import useSWR from 'swr'
+import React, {
+ ForwardedRef,
+ useCallback,
+ useEffect,
+ useImperativeHandle,
+ useRef,
+ useState
+} from 'react'
+import { Editor, Extension } from '@tiptap/core'
+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 { Popover, PopoverAnchor, PopoverContent } from '@/components/ui/popover'
+import { IconArrowElbow, IconEdit } from '@/components/ui/icons'
import {
Tooltip,
TooltipContent,
TooltipTrigger
} from '@/components/ui/tooltip'
+
+import { Popover, PopoverContent } from '../ui/popover'
+import { ChatContext } from './chat'
+import { PopoverMentionList } from './popover-mention-list'
+import {
+ CATEGORIES_MENU,
+ MentionNodeAttrs,
+ MenuState,
+ SourceItem,
+ SuggestionState
+} from './prompt-form-editor/types'
+
+import './prompt-form.css'
+
+import { cn } from '@/lib/utils'
+
+import { PromptFormMentionExtension } from './prompt-form-editor/mention-extension'
import {
- SearchableSelect,
- SearchableSelectAnchor,
- SearchableSelectContent,
- SearchableSelectOption,
- SearchableSelectTextarea
-} from '@/components/searchable-select'
-
-export interface PromptProps
- extends Pick {
+ atInfoToSourceItem,
+ sourceItemToMentionNodeAttrs
+} from './prompt-form-editor/utils'
+
+export interface PromptProps {
onSubmit: (value: string) => Promise
isLoading: boolean
- chatInputRef: React.RefObject
isInitializing?: boolean
}
export interface PromptFormRef {
focus: () => void
+ setInput: (value: string) => void
+ input: string
}
function PromptFormRenderer(
- {
- onSubmit,
- input,
- setInput,
- isLoading,
- chatInputRef,
- isInitializing
- }: PromptProps,
- ref: React.ForwardedRef
+ { onSubmit, isLoading, isInitializing }: 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
- >({})
-
- const { data: completionData } = useSWR(
- queryCompletionUrl,
- fetcher,
- {
- revalidateOnFocus: false,
- dedupingInterval: 0,
- errorRetryCount: 0
- }
+ const { formRef } = useEnterSubmit()
+
+ const { provideFileAtInfo } = React.useContext(ChatContext)
+
+ const popoverRef = useRef(null)
+ const selectedItemRef = useRef(null)
+
+ const [suggestionState, setSuggestionState] =
+ useState(null)
+
+ const suggestionRef = useRef | null>(null)
+
+ const [menuState, setMenuState] = useState({ view: 'categories' })
+ const menuStateRef = useRef({ view: 'categories' })
+
+ useEffect(() => {
+ menuStateRef.current = menuState
+ }, [menuState])
+
+ const updateSelectedIndex = useCallback((index: number) => {
+ setSuggestionState(prev =>
+ prev ? { ...prev, selectedIndex: index } : null
+ )
+ }, [])
+
+ /**
+ * Scroll the suggestion container so that the selected item is visible.
+ */
+ const scrollToSelected = useCallback(
+ (containerEl: HTMLElement | null, selectedEl: HTMLElement | null) => {
+ if (!containerEl || !selectedEl) return
+ const containerRect = containerEl.getBoundingClientRect()
+ const selectedRect = selectedEl.getBoundingClientRect()
+
+ if (selectedRect.bottom > containerRect.bottom) {
+ containerEl.scrollTop += selectedRect.bottom - containerRect.bottom
+ } else if (selectedRect.top < containerRect.top) {
+ containerEl.scrollTop -= containerRect.top - selectedRect.top
+ }
+ },
+ []
)
- React.useEffect(() => {
- const suggestions = completionData?.hits ?? []
- setOptions(suggestions)
- setSuggestionOpen(!!suggestions?.length)
- }, [completionData?.hits])
-
- React.useImperativeHandle(ref, () => ({
- focus: () => chatInputRef.current?.focus()
- }))
-
- React.useEffect(() => {
- if (
- input &&
- chatInputRef.current &&
- chatInputRef.current !== document.activeElement
- ) {
- chatInputRef.current.focus()
+ // Whenever the selected index changes, ensure it's scrolled into view
+ useEffect(() => {
+ if (suggestionState?.selectedIndex !== undefined) {
+ scrollToSelected(popoverRef.current, selectedItemRef.current)
}
- }, [input, chatInputRef])
-
- React.useLayoutEffect(() => {
- if (nextInputSelectionRange.current?.length) {
- chatInputRef.current?.setSelectionRange?.(
- nextInputSelectionRange.current[0],
- nextInputSelectionRange.current[1]
- )
- nextInputSelectionRange.current = undefined
+ }, [suggestionState?.selectedIndex, scrollToSelected])
+
+ /**
+ * Custom Tiptap extension to handle special keyboard shortcuts.
+ */
+ const CustomKeyboardShortcuts = Extension.create({
+ addKeyboardShortcuts() {
+ return {
+ 'Shift-Enter': () =>
+ this.editor.commands.first(({ commands }) => [
+ () => commands.newlineInCode(),
+ () => commands.createParagraphNear(),
+ () => commands.liftEmptyBlock(),
+ () => commands.splitBlock()
+ ]),
+ Enter: ({ editor }) => {
+ // If there's an active suggestion or if we are not in the main menu, do not submit
+ if (
+ suggestionRef.current ||
+ menuStateRef.current.view !== 'categories'
+ ) {
+ return false
+ }
+ handleSubmit(undefined, editor.getText())
+ editor.commands.setContent('')
+ return true
+ }
+ }
}
- }, [chatInputRef])
-
- 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)
+ })
+
+ /**
+ * Handle item selection when '@' mention is triggered.
+ */
+ const handleItemSelection = useCallback(
+ (item: SourceItem, command?: (props: MentionNodeAttrs) => void) => {
+ // If user is in the main menu (categories) and picks something like "files"
+ if (menuStateRef.current.view === 'categories') {
+ switch (item.name.toLowerCase()) {
+ case 'files': {
+ const state: MenuState = { view: 'files' }
+ setMenuState(state)
+ menuStateRef.current = state
+
+ // If a function is provided to fetch file info, get them and update suggestions
+ if (provideFileAtInfo) {
+ provideFileAtInfo().then(files => {
+ if (!files) return
+ const items = files.map(atInfoToSourceItem)
+ setSuggestionState(prev =>
+ prev
+ ? {
+ ...prev,
+ items,
+ selectedIndex: 0
+ }
+ : null
+ )
+ suggestionRef.current = {
+ items,
+ selectedIndex: 0,
+ command: command || suggestionRef.current?.command!
+ }
+ })
+ }
+ break
+ }
+ case 'symbols':
+ // TODO: Implement symbol selection if needed
+ break
+ default:
+ break
+ }
} else {
- setOptions([])
- setSuggestionOpen(false)
+ const attrs = sourceItemToMentionNodeAttrs(item)
+ if (command) {
+ command(attrs)
+ } else if (suggestionRef.current?.command) {
+ suggestionRef.current.command(attrs)
+ }
}
- }, 200)
- }, [])
+ },
+ [provideFileAtInfo]
+ )
+
+ /**
+ * Handle up/down/enter keys in the suggestion popover.
+ */
+ const handleKeyDown = useCallback(
+ (event: KeyboardEvent) => {
+ const currentSuggestion = suggestionRef.current
+ if (!currentSuggestion || !currentSuggestion.items?.length) return false
+
+ switch (event.key) {
+ case 'ArrowUp':
+ case 'ArrowDown': {
+ event.preventDefault()
+ const direction = event.key === 'ArrowUp' ? -1 : 1
- const handleCompletionSelect = (item: ISearchHit) => {
- const selectionEnd = prevInputSelectionEnd.current ?? 0
- const queryNameMatches = getSearchCompletionQueryName(input, selectionEnd)
- if (queryNameMatches) {
- setSelectedCompletionsMap({
- ...selectedCompletionsMap,
- [`@${item.doc?.name}`]: item
+ setSuggestionState(prev => {
+ if (!prev) return null
+ const length = currentSuggestion.items.length
+ const newIndex = (prev.selectedIndex + direction + length) % length
+ return { ...prev, selectedIndex: newIndex }
+ })
+
+ suggestionRef.current = {
+ ...currentSuggestion,
+ selectedIndex:
+ (currentSuggestion.selectedIndex +
+ direction +
+ currentSuggestion.items.length) %
+ currentSuggestion.items.length
+ }
+ return true
+ }
+ case 'Enter': {
+ event.preventDefault()
+ const selectedItem =
+ currentSuggestion.items[currentSuggestion.selectedIndex]
+ if (selectedItem) {
+ handleItemSelection(selectedItem, currentSuggestion.command)
+ }
+ return true
+ }
+ default:
+ return false
+ }
+ },
+ [handleItemSelection]
+ )
+
+ /**
+ * Initialize the Tiptap editor with the specified extensions and placeholder.
+ */
+ const editor = useEditor({
+ extensions: [
+ Document,
+ Paragraph,
+ Text,
+ CustomKeyboardShortcuts,
+ Placeholder.configure({
+ showOnlyWhenEditable: true,
+ placeholder: 'Ask anything...'
+ }),
+ PromptFormMentionExtension.configure({
+ HTMLAttributes: {
+ class: 'mention'
+ },
+ suggestion: {
+ char: '@',
+ allowSpaces: true,
+ items: async ({ query }): Promise => {
+ if (!provideFileAtInfo) return []
+
+ if (menuStateRef.current.view === 'categories') {
+ return CATEGORIES_MENU
+ }
+
+ try {
+ const files = await provideFileAtInfo({ query })
+ return files?.map(atInfoToSourceItem) || []
+ } catch (error) {
+ // TODO: handle or log error if needed
+ return []
+ }
+ },
+ render: () => ({
+ onStart: props => {
+ const newState: SuggestionState = {
+ items: props.items as SourceItem[],
+ command: props.command,
+ clientRect: props.clientRect!,
+ selectedIndex: 0
+ }
+ suggestionRef.current = {
+ items: props.items as SourceItem[],
+ command: props.command,
+ selectedIndex: 0
+ }
+ setSuggestionState(newState)
+
+ // Ensure the editor keeps focus after mention starts
+ requestAnimationFrame(() => {
+ editor?.commands.focus()
+ })
+ },
+ onUpdate: props => {
+ const newState: SuggestionState = {
+ items: props.items as SourceItem[],
+ command: props.command,
+ clientRect: props.clientRect!,
+ selectedIndex: 0
+ }
+ suggestionRef.current = {
+ items: props.items as SourceItem[],
+ command: props.command,
+ selectedIndex: 0
+ }
+ setSuggestionState(newState)
+
+ requestAnimationFrame(() => {
+ editor?.commands.focus()
+ })
+ },
+ onKeyDown: ({ event }) => {
+ if (['ArrowUp', 'ArrowDown', 'Enter'].includes(event.key)) {
+ return handleKeyDown(event)
+ }
+ return false
+ },
+ onExit: () => {
+ const initialMenuState: MenuState = { view: 'categories' }
+ setMenuState(initialMenuState)
+ menuStateRef.current = initialMenuState
+ suggestionRef.current = null
+ setSuggestionState(null)
+ }
+ })
+ }
})
- 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)
- }
+ ],
+ content: ''
+ })
- const handlePromptSubmit: React.FormEventHandler<
- HTMLFormElement
- > = async e => {
- e.preventDefault()
- if (!input?.trim() || isLoading || isInitializing) {
- return
- }
+ const input = editor?.getText() || ''
+
+ useImperativeHandle(
+ ref,
+ () => ({
+ focus: () => {
+ editor?.commands.focus('end')
+ },
+ setInput: (str: string) => {
+ editor?.commands.setContent(str)
+ },
+ input
+ }),
+ [editor, input]
+ )
+
+ /**
+ * Submit handler for the form. Called on Enter or via button click.
+ */
+ const handleSubmit = async (e?: React.FormEvent, text?: string) => {
+ e?.preventDefault()
+ if (isLoading) return
- 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`
- )
- })
-
- setInput('')
- await onSubmit(finalInput)
+ const finalText = text ?? input
+ if (!finalText?.trim()) return
+
+ await onSubmit(finalText)
+ editor?.commands.setContent('')
}
- 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
- }
- onKeyDown(e)
+ /**
+ * Calculate the vertical offset for the Popover, depending on the active menu view.
+ */
+ const topOffset = (() => {
+ if (!suggestionState) return 0
+ const { view } = menuStateRef.current
+ if (view === 'categories') {
+ return 70
+ } else if (view === 'files' && suggestionState.items.length > 0) {
+ // Each item is ~42px tall, display max 4 items
+ return Math.min(suggestionState.items.length * 42, 4 * 42)
}
- }
+ return 70
+ })()
return (
-
+ <>
+
+
+ {/* Suggestion popover, triggered if mentionState is not null */}
+ {suggestionState && (
+
+ e.preventDefault()}
+ onPointerDownOutside={e => e.preventDefault()}
+ onFocusOutside={e => e.preventDefault()}
+ >
+
+ handleItemSelection(item, suggestionRef.current?.command)
+ }
+ />
+
+
+ )}
+ >
)
}
+/**
+ * Export PromptForm with a forwarded ref to access internal methods.
+ */
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.
- */
-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 54a06d0b907a..062f2d8df0ac 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -360,10 +360,10 @@ importers:
version: 5.2.0
esbuild-plugin-copy:
specifier: ^2.1.1
- version: 2.1.1(esbuild@0.20.2)
+ version: 2.1.1(esbuild@0.19.12)
esbuild-plugin-polyfill-node:
specifier: ^0.3.0
- version: 0.3.0(esbuild@0.20.2)
+ version: 0.3.0(esbuild@0.19.12)
eslint:
specifier: ^8.55.0
version: 8.57.0
@@ -511,27 +511,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)
@@ -3351,8 +3360,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==}
@@ -3790,67 +3799,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/suggestion@2.6.6':
- resolution: {integrity: sha512-jogG0QgGit9UtTznVnhQfNImZfQM89NR0is20yRQzC0HmD8B8f3jmGrotG63Why2oKbeoe3CpM5/5eDE/paqCA==}
+ '@tiptap/extension-hard-break@2.10.4':
+ resolution: {integrity: sha512-nW9wubW1A/CO2Ssn9wNMP08tR9Oarg9VUGzJ5qNuz38DDNyntE1SyDS+XStkeMq5nKqJ3YKhukyAJH/PiRq4Mg==}
peerDependencies:
- '@tiptap/core': ^2.6.6
- '@tiptap/pm': ^2.6.6
+ '@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.10.4':
+ resolution: {integrity: sha512-7Bzcn1REA7OmVRxiMF2kVK9EhosXotdLAGaEvSbn4zQtHCJG0tREuYvPy53LGzVuPkBDR6Pf6sp1QbGvSne/8g==}
+ peerDependencies:
+ '@tiptap/core': ^2.7.0
+ '@tiptap/pm': ^2.7.0
'@tootallnate/once@1.1.2':
resolution: {integrity: sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==}
@@ -3992,15 +4089,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==}
@@ -8842,8 +8948,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==}
@@ -8860,14 +8966,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==}
@@ -8878,21 +8984,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==}
@@ -13857,7 +13963,7 @@ snapshots:
- encoding
- supports-color
- '@remirror/core-constants@2.0.2': {}
+ '@remirror/core-constants@3.0.0': {}
'@repeaterjs/repeater@3.0.5': {}
@@ -14218,81 +14324,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.10.4(@tiptap/pm@2.10.4)
+
+ '@tiptap/extension-document@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-dropcursor@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-floating-menu@2.6.6(@tiptap/core@2.6.6(@tiptap/pm@2.6.6))(@tiptap/pm@2.6.6)':
+ '@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.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
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.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-hard-break@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-placeholder@2.6.6(@tiptap/core@2.6.6(@tiptap/pm@2.6.6))(@tiptap/pm@2.6.6)':
+ '@tiptap/extension-heading@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-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/core': 2.10.4(@tiptap/pm@2.10.4)
+ '@tiptap/pm': 2.10.4
- '@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.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))':
+ dependencies:
+ '@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))':
+ dependencies:
+ '@tiptap/core': 2.10.4(@tiptap/pm@2.10.4)
+
+ '@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': {}
@@ -14420,16 +14620,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': {}
@@ -16760,11 +16969,11 @@ snapshots:
is-date-object: 1.0.5
is-symbol: 1.0.4
- esbuild-plugin-copy@2.1.1(esbuild@0.20.2):
+ esbuild-plugin-copy@2.1.1(esbuild@0.19.12):
dependencies:
chalk: 4.1.2
chokidar: 3.6.0
- esbuild: 0.20.2
+ esbuild: 0.19.12
fs-extra: 10.1.0
globby: 11.1.0
@@ -16774,12 +16983,6 @@ snapshots:
esbuild: 0.19.12
import-meta-resolve: 3.1.1
- esbuild-plugin-polyfill-node@0.3.0(esbuild@0.20.2):
- dependencies:
- '@jspm/core': 2.0.1
- esbuild: 0.20.2
- import-meta-resolve: 3.1.1
-
esbuild@0.19.11:
optionalDependencies:
'@esbuild/aix-ppc64': 0.19.11
@@ -20497,105 +20700,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: {}