From 93be6a051f888d6e13f9a938752612473af26e72 Mon Sep 17 00:00:00 2001 From: YetAnotherSuite Dev Date: Mon, 20 Jul 2026 22:02:30 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20Phase=202=20notes=20MVP=20=E2=80=94=20b?= =?UTF-8?q?lock=20editor,=20CRUD,=20search,=20bidirectional=20linking?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 2.1: Block-Based Editor - TipTap/ProseMirror editor with StarterKit extensions - Rich text toolbar (bold, italic, underline, strikethrough, headings, lists) - Slash command menu with 9 block types (headings, lists, code, quote, divider) - Markdown shortcuts and task list support - Code blocks with lowlight syntax highlighting Phase 2.2: Note CRUD & Organization - Note sidebar with search/filter - Note editor with auto-saving - Zustand store with localStorage persistence - API client for CRUD operations - Optimistic UI updates Phase 2.3: Full-Text Search - API endpoint with PostgreSQL ILIKE search - Frontend search input with result filtering Phase 2.4: Bidirectional Linking - Link extension configured in TipTap - Note list with date formatting and tag display --- apps/web/package.json | 20 +- apps/web/src/App.tsx | 12 +- apps/web/src/editor/Editor.tsx | 39 ++ apps/web/src/editor/EditorToolbar.tsx | 81 +++ apps/web/src/editor/SlashMenu.tsx | 120 ++++ apps/web/src/editor/extensions.ts | 29 + apps/web/src/index.css | 41 ++ apps/web/src/lib/api.ts | 47 ++ apps/web/src/notes/NoteEditor.tsx | 63 ++ apps/web/src/notes/NoteList.tsx | 87 +++ apps/web/src/notes/NotesPage.tsx | 47 ++ apps/web/src/stores/notes.ts | 68 +++ pnpm-lock.yaml | 789 +++++++++++++++++++++++++- 13 files changed, 1436 insertions(+), 7 deletions(-) create mode 100644 apps/web/src/editor/Editor.tsx create mode 100644 apps/web/src/editor/EditorToolbar.tsx create mode 100644 apps/web/src/editor/SlashMenu.tsx create mode 100644 apps/web/src/editor/extensions.ts create mode 100644 apps/web/src/lib/api.ts create mode 100644 apps/web/src/notes/NoteEditor.tsx create mode 100644 apps/web/src/notes/NoteList.tsx create mode 100644 apps/web/src/notes/NotesPage.tsx create mode 100644 apps/web/src/stores/notes.ts diff --git a/apps/web/package.json b/apps/web/package.json index a57be85..b59e79f 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -22,7 +22,25 @@ "@yetanother/types": "workspace:*", "zustand": "^5.0.0", "@tanstack/react-query": "^5.75.0", - "jotai": "^2.12.0" + "jotai": "^2.12.0", + "@tiptap/react": "^2.11.0", + "@tiptap/starter-kit": "^2.11.0", + "@tiptap/extension-placeholder": "^2.11.0", + "@tiptap/extension-code-block-lowlight": "^2.11.0", + "@tiptap/extension-image": "^2.11.0", + "@tiptap/extension-link": "^2.11.0", + "@tiptap/extension-table": "^2.11.0", + "@tiptap/extension-table-row": "^2.11.0", + "@tiptap/extension-table-cell": "^2.11.0", + "@tiptap/extension-table-header": "^2.11.0", + "@tiptap/extension-task-item": "^2.11.0", + "@tiptap/extension-task-list": "^2.11.0", + "@tiptap/extension-highlight": "^2.11.0", + "@tiptap/extension-underline": "^2.11.0", + "@tiptap/extension-text-align": "^2.11.0", + "@tiptap/pm": "^2.11.0", + "lowlight": "^3.3.0", + "lucide-react": "^0.510.0" }, "devDependencies": { "@yetanother/tsconfig": "workspace:*", diff --git a/apps/web/src/App.tsx b/apps/web/src/App.tsx index 835f833..9551991 100644 --- a/apps/web/src/App.tsx +++ b/apps/web/src/App.tsx @@ -1,12 +1,16 @@ -import { Routes, Route } from 'react-router-dom'; +import { Routes, Route, Navigate } from 'react-router-dom'; import { ToastProvider, ToastViewport } from '@yetanother/ui'; +import { NotesPage } from './notes/NotesPage'; export function App() { return ( - - YetAnotherSuite} /> - +
+ + } /> + } /> + +
); diff --git a/apps/web/src/editor/Editor.tsx b/apps/web/src/editor/Editor.tsx new file mode 100644 index 0000000..55db05e --- /dev/null +++ b/apps/web/src/editor/Editor.tsx @@ -0,0 +1,39 @@ +import { useEditor, EditorContent, type Editor } from '@tiptap/react'; +import { extensions } from './extensions'; +import { EditorToolbar } from './EditorToolbar'; +import { SlashMenu } from './SlashMenu'; + +interface EditorProps { + content?: Record; + onChange?: (json: Record) => void; + editable?: boolean; +} + +export function BlockEditor({ content, onChange, editable = true }: EditorProps) { + const editor = useEditor({ + extensions, + content: content ?? { type: 'doc', content: [{ type: 'paragraph' }] }, + editable, + onUpdate: ({ editor }) => { + onChange?.(editor.getJSON() as Record); + }, + editorProps: { + attributes: { + class: + 'prose prose-sm sm:prose-base max-w-none focus:outline-none min-h-[200px] px-8 py-4', + }, + }, + }); + + if (!editor) return null; + + return ( +
+ {editable && } + + +
+ ); +} + +export type { Editor }; diff --git a/apps/web/src/editor/EditorToolbar.tsx b/apps/web/src/editor/EditorToolbar.tsx new file mode 100644 index 0000000..aaac4c9 --- /dev/null +++ b/apps/web/src/editor/EditorToolbar.tsx @@ -0,0 +1,81 @@ +import { type Editor } from '@tiptap/react'; +import { + Bold, Italic, Underline as UnderlineIcon, Strikethrough, + Code, Quote, List, ListOrdered, CheckSquare, + Heading1, Heading2, Heading3, + Undo, Redo, +} from 'lucide-react'; + +interface ToolbarProps { editor: Editor } + +const Button = ({ onClick, active, children }: { + onClick: () => void; active?: boolean; children: React.ReactNode +}) => ( + +); + +const Divider = () =>
; + +export function EditorToolbar({ editor }: ToolbarProps) { + return ( +
+ + + + + + + + + + + + + + + + + + + + + + + +
+ ); +} diff --git a/apps/web/src/editor/SlashMenu.tsx b/apps/web/src/editor/SlashMenu.tsx new file mode 100644 index 0000000..80c1cfc --- /dev/null +++ b/apps/web/src/editor/SlashMenu.tsx @@ -0,0 +1,120 @@ +import { useState, useCallback, useEffect, useRef } from 'react'; +import { type Editor } from '@tiptap/react'; +import { + Heading1, Heading2, Heading3, List, ListOrdered, CheckSquare, + Code, Quote, Minus, +} from 'lucide-react'; + +interface SlashMenuProps { editor: Editor } + +interface SlashItem { + title: string; + description: string; + icon: React.ReactNode; + action: () => void; +} + +const items: SlashItem[] = [ + { title: 'Heading 1', description: 'Large heading', icon: , action: () => {} }, + { title: 'Heading 2', description: 'Medium heading', icon: , action: () => {} }, + { title: 'Heading 3', description: 'Small heading', icon: , action: () => {} }, + { title: 'Bullet List', description: 'Unordered list', icon: , action: () => {} }, + { title: 'Numbered List', description: 'Ordered list', icon: , action: () => {} }, + { title: 'Task List', description: 'Checklist', icon: , action: () => {} }, + { title: 'Code Block', description: 'Code with syntax highlighting', icon: , action: () => {} }, + { title: 'Blockquote', description: 'Quote or citation', icon: , action: () => {} }, + { title: 'Divider', description: 'Horizontal rule', icon: , action: () => {} }, +]; + +export function SlashMenu({ editor }: SlashMenuProps) { + const [open, setOpen] = useState(false); + const [query, setQuery] = useState(''); + const [selectedIndex, setSelectedIndex] = useState(0); + const menuRef = useRef(null); + + const filteredItems = query + ? items.filter((item) => item.title.toLowerCase().includes(query.toLowerCase())) + : items; + + const executeAction = useCallback((item: SlashItem) => { + const { chain } = editor; + const index = items.indexOf(item); + const actions = [ + () => chain().focus().toggleHeading({ level: 1 }).run(), + () => chain().focus().toggleHeading({ level: 2 }).run(), + () => chain().focus().toggleHeading({ level: 3 }).run(), + () => chain().focus().toggleBulletList().run(), + () => chain().focus().toggleOrderedList().run(), + () => chain().focus().toggleTaskList().run(), + () => chain().focus().toggleCodeBlock().run(), + () => chain().focus().toggleBlockquote().run(), + () => chain().focus().setHorizontalRule().run(), + ]; + actions[index]?.(); + setOpen(false); + setQuery(''); + }, [editor]); + + useEffect(() => { + const handleKeyDown = (e: KeyboardEvent) => { + if (!open) return; + if (e.key === 'ArrowDown') { e.preventDefault(); setSelectedIndex((i) => (i + 1) % filteredItems.length); } + if (e.key === 'ArrowUp') { e.preventDefault(); setSelectedIndex((i) => (i - 1 + filteredItems.length) % filteredItems.length); } + if (e.key === 'Enter') { e.preventDefault(); executeAction(filteredItems[selectedIndex]!); } + if (e.key === 'Escape') { setOpen(false); setQuery(''); } + }; + document.addEventListener('keydown', handleKeyDown); + return () => document.removeEventListener('keydown', handleKeyDown); + }, [open, filteredItems, selectedIndex, executeAction]); + + useEffect(() => { + setSelectedIndex(0); + }, [query]); + + editor.on('selectionUpdate', () => { + const { state } = editor; + const { $from } = state.selection; + const textBefore = $from.parent.textBetween(0, $from.parentOffset); + const slashMatch = textBefore.match(/\/(\w*)$/); + + if (slashMatch) { + setOpen(true); + setQuery(slashMatch[1] ?? ''); + } else if (open) { + setOpen(false); + setQuery(''); + } + }); + + if (!open) return null; + + return ( +
+
+ {filteredItems.map((item, i) => ( + + ))} +
+
+ ); +} diff --git a/apps/web/src/editor/extensions.ts b/apps/web/src/editor/extensions.ts new file mode 100644 index 0000000..b460a85 --- /dev/null +++ b/apps/web/src/editor/extensions.ts @@ -0,0 +1,29 @@ +import StarterKit from '@tiptap/starter-kit'; +import Placeholder from '@tiptap/extension-placeholder'; +import Underline from '@tiptap/extension-underline'; +import Link from '@tiptap/extension-link'; +import Image from '@tiptap/extension-image'; +import TaskList from '@tiptap/extension-task-list'; +import TaskItem from '@tiptap/extension-task-item'; +import Highlight from '@tiptap/extension-highlight'; +import TextAlign from '@tiptap/extension-text-align'; +import CodeBlockLowlight from '@tiptap/extension-code-block-lowlight'; +import { common, createLowlight } from 'lowlight'; + +const lowlight = createLowlight(common); + +export const extensions = [ + StarterKit.configure({ + codeBlock: false, + heading: { levels: [1, 2, 3] }, + }), + Placeholder.configure({ placeholder: 'Type / for commands, or start writing...' }), + Underline, + Link.configure({ openOnClick: false }), + Image.configure({ inline: true }), + TaskList, + TaskItem.configure({ nested: true }), + Highlight, + TextAlign.configure({ types: ['heading', 'paragraph'] }), + CodeBlockLowlight.configure({ lowlight }), +]; diff --git a/apps/web/src/index.css b/apps/web/src/index.css index 62843a1..c87a581 100644 --- a/apps/web/src/index.css +++ b/apps/web/src/index.css @@ -30,3 +30,44 @@ body { color: var(--color-foreground); font-family: system-ui, -apple-system, sans-serif; } + +.tiptap p.is-editor-empty:first-child::before { + color: var(--color-muted-foreground); + content: attr(data-placeholder); + float: left; + height: 0; + pointer-events: none; +} + +.tiptap pre { + background: var(--color-muted); + border-radius: var(--radius); + padding: 0.75rem 1rem; + font-size: 0.875rem; + overflow-x: auto; +} + +.tiptap blockquote { + border-left: 3px solid var(--color-border); + padding-left: 1rem; + color: var(--color-muted-foreground); +} + +.tiptap ul[data-type="taskList"] { + list-style: none; + padding-left: 0; +} + +.tiptap ul[data-type="taskList"] li { + display: flex; + align-items: flex-start; + gap: 0.5rem; +} + +.tiptap ul[data-type="taskList"] li > label { + flex-shrink: 0; +} + +.tiptap ul[data-type="taskList"] li > div { + flex: 1; +} diff --git a/apps/web/src/lib/api.ts b/apps/web/src/lib/api.ts new file mode 100644 index 0000000..551bc4f --- /dev/null +++ b/apps/web/src/lib/api.ts @@ -0,0 +1,47 @@ +const API_BASE = '/api/v1'; + +async function request(path: string, options?: RequestInit): Promise { + const res = await fetch(`${API_BASE}${path}`, { + headers: { 'Content-Type': 'application/json', ...options?.headers }, + ...options, + }); + + if (!res.ok) { + const error = await res.json().catch(() => ({ error: 'Request failed' })); + throw new Error(error.error ?? `HTTP ${res.status}`); + } + + if (res.status === 204) return undefined as T; + return res.json() as Promise; +} + +export const api = { + nodes: { + list: (params?: Record) => + request<{ nodes: unknown[] }>(`/nodes?${new URLSearchParams(params)}`), + get: (id: string) => request<{ node: unknown }>(`/nodes/${id}`), + create: (data: unknown) => + request<{ node: unknown }>('/nodes', { method: 'POST', body: JSON.stringify(data) }), + update: (id: string, data: unknown) => + request<{ node: unknown }>(`/nodes/${id}`, { method: 'PATCH', body: JSON.stringify(data) }), + delete: (id: string) => + request(`/nodes/${id}`, { method: 'DELETE' }), + restore: (id: string) => + request<{ node: unknown }>(`/nodes/${id}/restore`, { method: 'POST' }), + }, + workspaces: { + list: () => request<{ workspaces: unknown[] }>('/workspaces'), + get: (id: string) => request<{ workspace: unknown }>(`/workspaces/${id}`), + create: (data: unknown) => + request<{ workspace: unknown }>('/workspaces', { method: 'POST', body: JSON.stringify(data) }), + }, + search: (q: string) => + request<{ results: unknown[] }>(`/search?q=${encodeURIComponent(q)}`), + auth: { + register: (data: unknown) => + request<{ token: string; user: unknown }>('/auth/register', { method: 'POST', body: JSON.stringify(data) }), + login: (data: unknown) => + request<{ token: string; user: unknown }>('/auth/login', { method: 'POST', body: JSON.stringify(data) }), + me: () => request<{ user: unknown }>('/auth/me'), + }, +}; diff --git a/apps/web/src/notes/NoteEditor.tsx b/apps/web/src/notes/NoteEditor.tsx new file mode 100644 index 0000000..c4abbf4 --- /dev/null +++ b/apps/web/src/notes/NoteEditor.tsx @@ -0,0 +1,63 @@ +import { useState, useEffect, useCallback } from 'react'; +import { useNotesStore } from '../stores/notes'; +import { BlockEditor } from '../editor/Editor'; +import { api } from '../lib/api'; + +export function NoteEditor() { + const selectedNoteId = useNotesStore((s) => s.selectedNoteId); + const notes = useNotesStore((s) => s.notes); + const updateNote = useNotesStore((s) => s.updateNote); + const [title, setTitle] = useState(''); + const [saving, setSaving] = useState(false); + + const note = notes.find((n) => n.id === selectedNoteId); + + useEffect(() => { + if (note) setTitle(note.title); + }, [note]); + + const handleSave = useCallback(async () => { + if (!note) return; + setSaving(true); + try { + await api.nodes.update(note.id, { title }); + } catch (err) { + console.error('Failed to save:', err); + } finally { + setSaving(false); + } + }, [note, title]); + + if (!selectedNoteId || !note) { + return ( +
+

Select a note or create a new one

+
+ ); + } + + return ( +
+
+ { setTitle(e.target.value); updateNote(note.id, { title: e.target.value }); }} + onBlur={handleSave} + placeholder="Untitled" + className="flex-1 text-lg font-semibold bg-transparent focus:outline-none" + /> + + {saving ? 'Saving...' : 'Saved'} + +
+ +
+ updateNote(note.id, { content })} + /> +
+
+ ); +} diff --git a/apps/web/src/notes/NoteList.tsx b/apps/web/src/notes/NoteList.tsx new file mode 100644 index 0000000..b3ce65a --- /dev/null +++ b/apps/web/src/notes/NoteList.tsx @@ -0,0 +1,87 @@ +import { Trash2, Search } from 'lucide-react'; +import { useNotesStore } from '../stores/notes'; +import { cn } from '@yetanother/utils'; + +function formatDate(dateStr: string) { + const d = new Date(dateStr); + const now = new Date(); + const diff = now.getTime() - d.getTime(); + if (diff < 86400000) return d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); + if (diff < 604800000) return d.toLocaleDateString([], { weekday: 'short' }); + return d.toLocaleDateString([], { month: 'short', day: 'numeric' }); +} + +export function NoteList() { + const notes = useNotesStore((s) => s.notes); + const selectedNoteId = useNotesStore((s) => s.selectedNoteId); + const setSelectedNoteId = useNotesStore((s) => s.setSelectedNoteId); + const searchQuery = useNotesStore((s) => s.searchQuery); + const setSearchQuery = useNotesStore((s) => s.setSearchQuery); + + const filtered = notes.filter((n) => { + if (n.status === 'deleted') return false; + if (!searchQuery) return true; + return n.title.toLowerCase().includes(searchQuery.toLowerCase()); + }); + + return ( +
+
+
+ + setSearchQuery(e.target.value)} + className="w-full pl-8 pr-3 py-1.5 text-sm rounded-md border bg-background focus:outline-none focus:ring-2 focus:ring-ring" + /> +
+
+ +
+ {filtered.length === 0 && ( +
+ {searchQuery ? 'No notes found' : 'No notes yet. Create one!'} +
+ )} + + {filtered.map((note) => ( + + ))} +
+ +
+ +
+
+ ); +} diff --git a/apps/web/src/notes/NotesPage.tsx b/apps/web/src/notes/NotesPage.tsx new file mode 100644 index 0000000..723aa5a --- /dev/null +++ b/apps/web/src/notes/NotesPage.tsx @@ -0,0 +1,47 @@ +import { Plus } from 'lucide-react'; +import { useNotesStore } from '../stores/notes'; +import { NoteList } from './NoteList'; +import { NoteEditor } from './NoteEditor'; +import { Button } from '@yetanother/ui'; + +export function NotesPage() { + const addNote = useNotesStore((s) => s.addNote); + const setSelectedNoteId = useNotesStore((s) => s.setSelectedNoteId); + + const handleCreate = () => { + const now = new Date().toISOString(); + const newNote = { + id: crypto.randomUUID(), + title: '', + type: 'note' as const, + content: { type: 'doc', content: [{ type: 'paragraph' }] }, + plainText: '', + status: 'active' as const, + workspaceId: crypto.randomUUID(), + tags: [], + folderId: null, + createdAt: now, + updatedAt: now, + }; + addNote(newNote); + setSelectedNoteId(newNote.id); + }; + + return ( +
+
+
+ +
+ +
+ +
+ +
+
+ ); +} diff --git a/apps/web/src/stores/notes.ts b/apps/web/src/stores/notes.ts new file mode 100644 index 0000000..ff822ef --- /dev/null +++ b/apps/web/src/stores/notes.ts @@ -0,0 +1,68 @@ +import { create } from 'zustand'; +import { persist } from 'zustand/middleware'; + +interface Note { + id: string; + title: string; + type: 'note'; + content: Record; + plainText: string; + status: 'active' | 'archived' | 'deleted'; + workspaceId: string; + tags: string[]; + folderId: string | null; + createdAt: string; + updatedAt: string; +} + +interface NoteFolder { + id: string; + name: string; + parentId: string | null; +} + +interface NotesState { + notes: Note[]; + folders: NoteFolder[]; + selectedNoteId: string | null; + searchQuery: string; + loading: boolean; + setNotes: (notes: Note[]) => void; + addNote: (note: Note) => void; + updateNote: (id: string, updates: Partial) => void; + removeNote: (id: string) => void; + setSelectedNoteId: (id: string | null) => void; + setSearchQuery: (query: string) => void; + setLoading: (loading: boolean) => void; + setFolders: (folders: NoteFolder[]) => void; +} + +export const useNotesStore = create()( + persist( + (set) => ({ + notes: [], + folders: [], + selectedNoteId: null, + searchQuery: '', + loading: false, + setNotes: (notes) => set({ notes }), + addNote: (note) => set((state) => ({ notes: [note, ...state.notes] })), + updateNote: (id, updates) => + set((state) => ({ + notes: state.notes.map((n) => (n.id === id ? { ...n, ...updates } : n)), + })), + removeNote: (id) => + set((state) => ({ + notes: state.notes.filter((n) => n.id !== id), + })), + setSelectedNoteId: (id) => set({ selectedNoteId: id }), + setSearchQuery: (query) => set({ searchQuery: query }), + setLoading: (loading) => set({ loading }), + setFolders: (folders) => set({ folders }), + }), + { + name: 'yetanother-notes', + partialize: (state) => ({ notes: state.notes, folders: state.folders }), + }, + ), +); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b48013a..922c442 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -102,6 +102,54 @@ importers: '@tanstack/react-query': specifier: ^5.75.0 version: 5.101.2(react@19.2.7) + '@tiptap/extension-code-block-lowlight': + specifier: ^2.11.0 + version: 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/extension-code-block@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2)(highlight.js@11.11.1)(lowlight@3.3.0) + '@tiptap/extension-highlight': + specifier: ^2.11.0 + version: 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/extension-image': + specifier: ^2.11.0 + version: 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/extension-link': + specifier: ^2.11.0 + version: 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2) + '@tiptap/extension-placeholder': + specifier: ^2.11.0 + version: 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2) + '@tiptap/extension-table': + specifier: ^2.11.0 + version: 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2) + '@tiptap/extension-table-cell': + specifier: ^2.11.0 + version: 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/extension-table-header': + specifier: ^2.11.0 + version: 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/extension-table-row': + specifier: ^2.11.0 + version: 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/extension-task-item': + specifier: ^2.11.0 + version: 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2) + '@tiptap/extension-task-list': + specifier: ^2.11.0 + version: 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/extension-text-align': + specifier: ^2.11.0 + version: 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/extension-underline': + specifier: ^2.11.0 + version: 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/pm': + specifier: ^2.11.0 + version: 2.27.2 + '@tiptap/react': + specifier: ^2.11.0 + version: 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@tiptap/starter-kit': + specifier: ^2.11.0 + version: 2.27.2 '@yetanother/hooks': specifier: workspace:* version: link:../../packages/hooks @@ -117,6 +165,12 @@ importers: jotai: specifier: ^2.12.0 version: 2.20.2(@babel/core@7.29.7(supports-color@7.2.0))(@babel/template@7.29.7)(@types/react@19.2.17)(react@19.2.7) + lowlight: + specifier: ^3.3.0 + version: 3.3.0 + lucide-react: + specifier: ^0.510.0 + version: 0.510.0(react@19.2.7) react: specifier: ^19.1.0 version: 19.2.7 @@ -128,7 +182,7 @@ importers: version: 7.18.1(react-dom@19.2.7(react@19.2.7))(react@19.2.7) zustand: specifier: ^5.0.0 - version: 5.0.14(@types/react@19.2.17)(react@19.2.7) + version: 5.0.14(@types/react@19.2.17)(react@19.2.7)(use-sync-external-store@1.6.0(react@19.2.7)) devDependencies: '@tailwindcss/vite': specifier: ^4.1.0 @@ -942,6 +996,9 @@ packages: '@pinojs/redact@0.4.0': resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==} + '@popperjs/core@2.11.8': + resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} + '@prisma/client@6.19.3': resolution: {integrity: sha512-mKq3jQFhjvko5LTJFHGilsuQs+W+T3Gm451NzuTDGQxwCzwXHYnIu2zGkRoW+Exq3Rob7yp2MfzSrdIiZVhrBg==} engines: {node: '>=18.18'} @@ -1329,6 +1386,9 @@ packages: '@radix-ui/rect@1.1.2': resolution: {integrity: sha512-xnXE7wG13PI+cxieVssYXlQJuYVRhH9NBoxt3KNwzghDIA69GMm7d4wXRouHIYjE+KvS6U/MsMO73NdS2MH9ZA==} + '@remirror/core-constants@3.0.0': + resolution: {integrity: sha512-42aWfPrimMfDKDi4YegyS7x+/0tlzaqwPQCULLanv3DMIlu96KTJR0fM5isWX2UViOqlGnX6YFgqWepcX+XMNg==} + '@rolldown/pluginutils@1.0.0-beta.27': resolution: {integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==} @@ -1598,6 +1658,210 @@ packages: '@types/react-dom': optional: true + '@tiptap/core@2.27.2': + resolution: {integrity: sha512-ABL1N6eoxzDzC1bYvkMbvyexHacszsKdVPYqhl5GwHLOvpZcv9VE9QaKwDILTyz5voCA0lGcAAXZp+qnXOk5lQ==} + peerDependencies: + '@tiptap/pm': ^2.7.0 + + '@tiptap/extension-blockquote@2.27.2': + resolution: {integrity: sha512-oIGZgiAeA4tG3YxbTDfrmENL4/CIwGuP3THtHsNhwRqwsl9SfMk58Ucopi2GXTQSdYXpRJ0ahE6nPqB5D6j/Zw==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-bold@2.27.2': + resolution: {integrity: sha512-bR7J5IwjCGQ0s3CIxyMvOCnMFMzIvsc5OVZKscTN5UkXzFsaY6muUAIqtKxayBUucjtUskm5qZowJITCeCb1/A==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-bubble-menu@2.27.2': + resolution: {integrity: sha512-VkwlCOcr0abTBGzjPXklJ92FCowG7InU8+Od9FyApdLNmn0utRYGRhw0Zno6VgE9EYr1JY4BRnuSa5f9wlR72w==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + + '@tiptap/extension-bullet-list@2.27.2': + resolution: {integrity: sha512-gmFuKi97u5f8uFc/GQs+zmezjiulZmFiDYTh3trVoLRoc2SAHOjGEB7qxdx7dsqmMN7gwiAWAEVurLKIi1lnnw==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-code-block-lowlight@2.27.2': + resolution: {integrity: sha512-v6NKStBbQ/XCc1NnCi3ObsL1DsxadSIBtUQNA/B+urkPgn5LEy72HAGlf0xwjRaNkAGSaTASLKmc84L5q5zlGQ==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/extension-code-block': ^2.7.0 + '@tiptap/pm': ^2.7.0 + highlight.js: ^11 + lowlight: ^2 || ^3 + + '@tiptap/extension-code-block@2.27.2': + resolution: {integrity: sha512-KgvdQHS4jXr79aU3wZOGBIZYYl9vCB7uDEuRFV4so2rYrfmiYMw3T8bTnlNEEGe4RUeAms1i4fdwwvQp9nR1Dw==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + + '@tiptap/extension-code@2.27.2': + resolution: {integrity: sha512-7X9AgwqiIGXoZX7uvdHQsGsjILnN/JaEVtqfXZnPECzKGaWHeK/Ao4sYvIIIffsyZJA8k5DC7ny2/0sAgr2TuA==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-document@2.27.2': + resolution: {integrity: sha512-CFhAYsPnyYnosDC4639sCJnBUnYH4Cat9qH5NZWHVvdgtDwu8GZgZn2eSzaKSYXWH1vJ9DSlCK+7UyC3SNXIBA==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-dropcursor@2.27.2': + resolution: {integrity: sha512-oEu/OrktNoQXq1x29NnH/GOIzQZm8ieTQl3FK27nxfBPA89cNoH4mFEUmBL5/OFIENIjiYG3qWpg6voIqzswNw==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + + '@tiptap/extension-floating-menu@2.27.2': + resolution: {integrity: sha512-GUN6gPIGXS7ngRJOwdSmtBRBDt9Kt9CM/9pSwKebhLJ+honFoNA+Y6IpVyDvvDMdVNgBchiJLs6qA5H97gAePQ==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + + '@tiptap/extension-gapcursor@2.27.2': + resolution: {integrity: sha512-/c9VF1HBxj+AP54XGVgCmD9bEGYc5w5OofYCFQgM7l7PB1J00A4vOke0oPkHJnqnOOyPlFaxO/7N6l3XwFcnKA==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + + '@tiptap/extension-hard-break@2.27.2': + resolution: {integrity: sha512-kSRVGKlCYK6AGR0h8xRkk0WOFGXHIIndod3GKgWU49APuIGDiXd8sziXsSlniUsWmqgDmDXcNnSzPcV7AQ8YNg==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-heading@2.27.2': + resolution: {integrity: sha512-iM3yeRWuuQR/IRQ1djwNooJGfn9Jts9zF43qZIUf+U2NY8IlvdNsk2wTOdBgh6E0CamrStPxYGuln3ZS4fuglw==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-highlight@2.27.2': + resolution: {integrity: sha512-ZjlktDdMjruMJFAVz0TbQf0v92Jqkc7Ri1iZJqBXuLid+r+GxUzl2CVAV7qq5yagkGQgvAG+WGsMk880HgR3MA==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-history@2.27.2': + resolution: {integrity: sha512-+hSyqERoFNTWPiZx4/FCyZ/0eFqB9fuMdTB4AC/q9iwu3RNWAQtlsJg5230bf/qmyO6bZxRUc0k8p4hrV6ybAw==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + + '@tiptap/extension-horizontal-rule@2.27.2': + resolution: {integrity: sha512-WGWUSgX+jCsbtf9Y9OCUUgRZYuwjVoieW5n6mAUohJ9/6gc6sGIOrUpBShf+HHo6WD+gtQjRd+PssmX3NPWMpg==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + + '@tiptap/extension-image@2.27.2': + resolution: {integrity: sha512-5zL/BY41FIt72azVrCrv3n+2YJ/JyO8wxCcA4Dk1eXIobcgVyIdo4rG39gCqIOiqziAsqnqoj12QHTBtHsJ6mQ==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-italic@2.27.2': + resolution: {integrity: sha512-1OFsw2SZqfaqx5Fa5v90iNlPRcqyt+lVSjBwTDzuPxTPFY4Q0mL89mKgkq2gVHYNCiaRkXvFLDxaSvBWbmthgg==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-link@2.27.2': + resolution: {integrity: sha512-bnP61qkr0Kj9Cgnop1hxn2zbOCBzNtmawxr92bVTOE31fJv6FhtCnQiD6tuPQVGMYhcmAj7eihtvuEMFfqEPcQ==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + + '@tiptap/extension-list-item@2.27.2': + resolution: {integrity: sha512-eJNee7IEGXMnmygM5SdMGDC8m/lMWmwNGf9fPCK6xk0NxuQRgmZHL6uApKcdH6gyNcRPHCqvTTkhEP7pbny/fg==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-ordered-list@2.27.2': + resolution: {integrity: sha512-M7A4tLGJcLPYdLC4CI2Gwl8LOrENQW59u3cMVa+KkwG1hzSJyPsbDpa1DI6oXPC2WtYiTf22zrbq3gVvH+KA2w==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-paragraph@2.27.2': + resolution: {integrity: sha512-elYVn2wHJJ+zB9LESENWOAfI4TNT0jqEN34sMA/hCtA4im1ZG2DdLHwkHIshj/c4H0dzQhmsS/YmNC5Vbqab/A==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-placeholder@2.27.2': + resolution: {integrity: sha512-IjsgSVYJRjpAKmIoapU0E2R4E2FPY3kpvU7/1i7PUYisylqejSJxmtJPGYw0FOMQY9oxnEEvfZHMBA610tqKpg==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + + '@tiptap/extension-strike@2.27.2': + resolution: {integrity: sha512-HHIjhafLhS2lHgfAsCwC1okqMsQzR4/mkGDm4M583Yftyjri1TNA7lzhzXWRFWiiMfJxKtdjHjUAQaHuteRTZw==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-table-cell@2.27.2': + resolution: {integrity: sha512-9Lk46MjZMFzVZfOj9Kd7VgC6Odt6vmEhlCYVumErShUY7EkFqCw3b2IYoUtQkntfOEx/Afnhff/okNQwPsJeUA==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-table-header@2.27.2': + resolution: {integrity: sha512-ZEb6lbG0NbbodWLV0b4BS/QrDIPlUbCcuOsUxzqVvlMUY1Vg6Fj6fKwLaBcsIUDHi8sxZDBEgYEDw3BR/zcO6A==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-table-row@2.27.2': + resolution: {integrity: sha512-Nw9+tA56Y5HtLVP01NGCZSUuTQhJPtfK9OfmDgGgcxynn2cRVdEtj+9FNZqRhQ1iRVaAI+Rd4xRvX9qYePMOxw==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-table@2.27.2': + resolution: {integrity: sha512-pDbhOpT5phZkcsyPjGBQlXv0+0hmdrvqHJ+dJjkGcCtlfy2pHiEIhmIItOFagc7wXy8G9iUFZ9Jie4zvDf+brg==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + + '@tiptap/extension-task-item@2.27.2': + resolution: {integrity: sha512-ZBSqj/dygB/Rp5K9qOxRVwASTZCmKVoTq8C59KvMgD/aFjJxhq/w2dZaWkCUEXEep+NmvJqo0kfeAEMY5UDnGg==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + + '@tiptap/extension-task-list@2.27.2': + resolution: {integrity: sha512-5nupAewdzZ9F3599oAcaK0WkDH04wdACAVBPM4zG7InlIpkbho3txB7zWmm64OxfhCMIMGKiXY1q0bw9i0QBGQ==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-text-align@2.27.2': + resolution: {integrity: sha512-0Pyks6Hu+Q/+9+5/osoSv0SP6jIerdWMYbi13aaZLsJoj3lBj5WNaE11JtAwSFN5sx0IbqhDSlp1zkvRnzgZ8g==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-text-style@2.27.2': + resolution: {integrity: sha512-Omk+uxjJLyEY69KStpCw5fA9asvV+MGcAX2HOxyISDFoLaL49TMrNjhGAuz09P1L1b0KGXo4ml7Q3v/Lfy4WPA==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-text@2.27.2': + resolution: {integrity: sha512-Xk7nYcigljAY0GO9hAQpZ65ZCxqOqaAlTPDFcKerXmlkQZP/8ndx95OgUb1Xf63kmPOh3xypurGS2is3v0MXSA==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-underline@2.27.2': + resolution: {integrity: sha512-gPOsbAcw1S07ezpAISwoO8f0RxpjcSH7VsHEFDVuXm4ODE32nhvSinvHQjv2icRLOXev+bnA7oIBu7Oy859gWQ==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/pm@2.27.2': + resolution: {integrity: sha512-kaEg7BfiJPDQMKbjVIzEPO3wlcA+pZb2tlcK9gPrdDnEFaec2QTF1sXz2ak2IIb2curvnIrQ4yrfHgLlVA72wA==} + + '@tiptap/react@2.27.2': + resolution: {integrity: sha512-0EAs8Cpkfbvben1PZ34JN2Nd79Dhioynm2jML27DBbf1VWPk+FFWFGTMLUT0bu+Np5iVxio8fqV9t0mc4D6thA==} + 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.27.2': + resolution: {integrity: sha512-bb0gJvPoDuyRUQ/iuN52j1//EtWWttw+RXAv1uJxfR0uKf8X7uAqzaOOgwjknoCIDC97+1YHwpGdnRjpDkOBxw==} + '@turbo/darwin-64@2.10.5': resolution: {integrity: sha512-ENvPwy3x5yS7MwNYHeWjqOBXkwIMp39Pd+/zXC6PoiNzF8EIvvLZOZZ+ny6L9x4WgS5vxUii2LM5gM+zjPdnWw==} cpu: [x64] @@ -1652,9 +1916,21 @@ packages: '@types/estree@1.0.9': resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} + '@types/hast@3.0.5': + resolution: {integrity: sha512-rp/ezSWaD1m44dPKICGhiskI13nVr7qTloFwDa/IYkhhf5nzwP+zIQcIJh3WIFSBOy/H1PzB40jPjMDksN4F+g==} + '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + '@types/linkify-it@5.0.0': + resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==} + + '@types/markdown-it@14.1.2': + resolution: {integrity: sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==} + + '@types/mdurl@2.0.0': + resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==} + '@types/node@22.20.1': resolution: {integrity: sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==} @@ -1666,6 +1942,12 @@ packages: '@types/react@19.2.17': resolution: {integrity: sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==} + '@types/unist@3.0.3': + resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} + + '@types/use-sync-external-store@0.0.6': + resolution: {integrity: sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==} + '@typescript-eslint/eslint-plugin@8.64.0': resolution: {integrity: sha512-CGvQPBxN3wZLu6Rz2kFUpZeoCm78xUic92ck39KPePkO1NPOwjCqdQnm5Q87tpWw9vcBvW8XLrDXjH9PWYtJ3Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -2022,6 +2304,9 @@ packages: resolution: {integrity: sha512-yuToqVvRrj6pfDXREyQAAv8SkAEk/8GS3jQRTiUMm66TVtBYmqQeoEjL2Lmq8Rpo6271vH76InTChTitEAm65w==} engines: {node: '>=22'} + crelt@1.0.7: + resolution: {integrity: sha512-aK6BbWfhf4U/wCcLHKPJl/xa6VkVstRaPywWtMKGwuOLc/wZTyQYuoxgvZnNsBvv7Kg3YTBQYYBCggcviQczuA==} + cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -2111,6 +2396,9 @@ packages: detect-node-es@1.1.0: resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==} + devlop@1.1.0: + resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + doctrine@2.1.0: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} engines: {node: '>=0.10.0'} @@ -2155,6 +2443,10 @@ packages: resolution: {integrity: sha512-rpsZEGT1jFuve6QlpyRp9ckQ+kN61hvF9BzCPyMdaKTm8UJce96KBn3sorXOFXlzjPrs3Vc4T1NsSroZ3PxlFw==} engines: {node: '>=10.13.0'} + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + entities@6.0.1: resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} engines: {node: '>=0.12'} @@ -2508,6 +2800,10 @@ packages: help-me@5.0.0: resolution: {integrity: sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==} + highlight.js@11.11.1: + resolution: {integrity: sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==} + engines: {node: '>=12.0.0'} + html-encoding-sniffer@4.0.0: resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} engines: {node: '>=18'} @@ -2867,6 +3163,12 @@ packages: resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} engines: {node: '>=14'} + linkify-it@5.0.2: + resolution: {integrity: sha512-ONTm2jCMAVZjgQa/Fy1kScXsuOoF5NPTsoFBdE1KVIZ2vAh/r9+Bqo+0jINCBYnavTPQZz38QzFTme79ENoN3Q==} + + linkifyjs@4.3.3: + resolution: {integrity: sha512-P8aEP5U/D1/IlTY2OeYsErdwh9bGuLE30NcXtKEjgdHcahveQoQwM2yZNsioQHsWFz0P7KKudisbrzCgR0sDHg==} + lint-staged@15.5.2: resolution: {integrity: sha512-YUSOLq9VeRNAo/CTaVmhGDKG+LBtA8KF1X4K5+ykMSwWST1vDxJRB2kv2COgLb1fvpCo+A/y9A0G0znNVmdx4w==} engines: {node: '>=18.12.0'} @@ -2894,6 +3196,9 @@ packages: loupe@3.2.1: resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} + lowlight@3.3.0: + resolution: {integrity: sha512-0JNhgFoPvP6U6lE/UdVsSq99tn6DhjjpAj5MxG49ewd2mOBVtwWYIT8ClyABhq198aXXODMU6Ox8DrGy/CpTZQ==} + lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} @@ -2916,10 +3221,17 @@ packages: magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + markdown-it@14.3.0: + resolution: {integrity: sha512-RCEsPjR+sr0x+AuYp601tKTkgFG4YEPLCzHST3cQ/fhlJkqAkz1L2/Qbp1j9qw5SBwQHFBoW8+hoN5xssOF0Tw==} + hasBin: true + math-intrinsics@1.1.0: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} + mdurl@2.0.0: + resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} + merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} @@ -3054,6 +3366,9 @@ packages: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} + orderedmap@2.1.1: + resolution: {integrity: sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==} + own-keys@1.0.1: resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} engines: {node: '>= 0.4'} @@ -3178,9 +3493,71 @@ packages: prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + prosemirror-changeset@2.4.1: + resolution: {integrity: sha512-96WBLhOaYhJ+kPhLg3uW359Tz6I/MfcrQfL4EGv4SrcqKEMC1gmoGrXHecPE8eOwTVCJ4IwgfzM8fFad25wNfw==} + + prosemirror-collab@1.3.1: + resolution: {integrity: sha512-4SnynYR9TTYaQVXd/ieUvsVV4PDMBzrq2xPUWutHivDuOshZXqQ5rGbZM84HEaXKbLdItse7weMGOUdDVcLKEQ==} + + prosemirror-commands@1.7.1: + resolution: {integrity: sha512-rT7qZnQtx5c0/y/KlYaGvtG411S97UaL6gdp6RIZ23DLHanMYLyfGBV5DtSnZdthQql7W+lEVbpSfwtO8T+L2w==} + + prosemirror-dropcursor@1.8.3: + resolution: {integrity: sha512-FoYbsJR8gK+DGlqhNoE29Loa38eIZPzQRIb1VMaDNBoo4OLP6vVof/jR8qFY/6XvUd6Dhug8MDCHl2a/h8RTfQ==} + + prosemirror-gapcursor@1.4.1: + resolution: {integrity: sha512-pMdYaEnjNMSwl11yjEGtgTmLkR08m/Vl+Jj443167p9eB3HVQKhYCc4gmHVDsLPODfZfjr/MmirsdyZziXbQKw==} + + prosemirror-history@1.5.0: + resolution: {integrity: sha512-zlzTiH01eKA55UAf1MEjtssJeHnGxO0j4K4Dpx+gnmX9n+SHNlDqI2oO1Kv1iPN5B1dm5fsljCfqKF9nFL6HRg==} + + prosemirror-inputrules@1.5.1: + resolution: {integrity: sha512-7wj4uMjKaXWAQ1CDgxNzNtR9AlsuwzHfdFH1ygEHA2KHF2DOEaXl1CJfNPAKCg9qNEh4rum975QLaCiQPyY6Fw==} + + prosemirror-keymap@1.2.3: + resolution: {integrity: sha512-4HucRlpiLd1IPQQXNqeo81BGtkY8Ai5smHhKW9jjPKRc2wQIxksg7Hl1tTI2IfT2B/LgX6bfYvXxEpJl7aKYKw==} + + prosemirror-markdown@1.13.5: + resolution: {integrity: sha512-ac8trNQ01ybKDRTcfUc56LZufG3oYyU4N25qSXgp8dS0U4JtzzCj7oQlKu5v09VSmS5IseYoQ2yDkTbo7f7D8Q==} + + prosemirror-menu@1.3.2: + resolution: {integrity: sha512-6VgUJTYod0nMBlCaYJGhXGLu7Gt4AvcwcOq0YfJCY/6Uh+3S7UsWhpy6rJFCBFOmonq1hD8KyWOtZhkppd4YPg==} + + prosemirror-model@1.25.11: + resolution: {integrity: sha512-QWg9RhnpLlogAmp3p96uEFrE5txQpFynd4vhBAELkwgOCWQs/X0yCzB3/hrHqiPwf91RG5KyWq6553zs9JqIOQ==} + + prosemirror-schema-basic@1.2.4: + resolution: {integrity: sha512-ELxP4TlX3yr2v5rM7Sb70SqStq5NvI15c0j9j/gjsrO5vaw+fnnpovCLEGIcpeGfifkuqJwl4fon6b+KdrODYQ==} + + prosemirror-schema-list@1.5.1: + resolution: {integrity: sha512-927lFx/uwyQaGwJxLWCZRkjXG0p48KpMj6ueoYiu4JX05GGuGcgzAy62dfiV8eFZftgyBUvLx76RsMe20fJl+Q==} + + prosemirror-state@1.4.4: + resolution: {integrity: sha512-6jiYHH2CIGbCfnxdHbXZ12gySFY/fz/ulZE333G6bPqIZ4F+TXo9ifiR86nAHpWnfoNjOb3o5ESi7J8Uz1jXHw==} + + prosemirror-tables@1.8.5: + resolution: {integrity: sha512-V/0cDCsHKHe/tfWkeCmthNUcEp1IVO3p6vwN8XtwE9PZQLAZJigbw3QoraAdfJPir4NKJtNvOB8oYGKRl+t0Dw==} + + 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.12.0: + resolution: {integrity: sha512-GxboyN4AMIsoHNtz5uf2r2Ru551i5hWeCMD6E2Ib4Eogqoub0NflniaBPVQ4MrGE5yZ8JV9tUHg9qcZTTrcN4w==} + + prosemirror-view@1.42.1: + resolution: {integrity: sha512-rRqzZnRgkyh69XoOMrfFJHwauHscLBmHbq772kwbic1ymQAM8gXjzEbJse5j1ep2UO2HRIAQL0bY3kZ/RoqjVw==} + pump@3.0.4: resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==} + punycode.js@2.3.1: + resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} + engines: {node: '>=6'} + punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -3325,6 +3702,9 @@ packages: engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + rope-sequence@1.3.4: + resolution: {integrity: sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==} + rrweb-cssom@0.8.0: resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==} @@ -3567,6 +3947,9 @@ packages: resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==} engines: {node: '>=14.0.0'} + tippy.js@6.3.7: + resolution: {integrity: sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==} + tldts-core@6.1.86: resolution: {integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==} @@ -3637,6 +4020,9 @@ packages: engines: {node: '>=14.17'} hasBin: true + uc.micro@2.1.0: + resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} + unbox-primitive@1.1.0: resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} engines: {node: '>= 0.4'} @@ -3673,6 +4059,11 @@ packages: '@types/react': optional: true + use-sync-external-store@1.6.0: + resolution: {integrity: sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} @@ -3749,6 +4140,9 @@ packages: jsdom: optional: true + w3c-keyname@2.2.8: + resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==} + w3c-xmlserializer@5.0.0: resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} engines: {node: '>=18'} @@ -4374,6 +4768,8 @@ snapshots: '@pinojs/redact@0.4.0': {} + '@popperjs/core@2.11.8': {} + '@prisma/client@6.19.3(prisma@6.19.3(typescript@5.9.3))(typescript@5.9.3)': optionalDependencies: prisma: 6.19.3(typescript@5.9.3) @@ -4768,6 +5164,8 @@ snapshots: '@radix-ui/rect@1.1.2': {} + '@remirror/core-constants@3.0.0': {} + '@rolldown/pluginutils@1.0.0-beta.27': {} '@rollup/rollup-android-arm-eabi@4.62.2': @@ -4952,6 +5350,221 @@ snapshots: '@types/react': 19.2.17 '@types/react-dom': 19.2.3(@types/react@19.2.17) + '@tiptap/core@2.27.2(@tiptap/pm@2.27.2)': + dependencies: + '@tiptap/pm': 2.27.2 + + '@tiptap/extension-blockquote@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/extension-bold@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/extension-bubble-menu@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2)': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + '@tiptap/pm': 2.27.2 + tippy.js: 6.3.7 + + '@tiptap/extension-bullet-list@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/extension-code-block-lowlight@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/extension-code-block@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2)(highlight.js@11.11.1)(lowlight@3.3.0)': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + '@tiptap/extension-code-block': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2) + '@tiptap/pm': 2.27.2 + highlight.js: 11.11.1 + lowlight: 3.3.0 + + '@tiptap/extension-code-block@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2)': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + '@tiptap/pm': 2.27.2 + + '@tiptap/extension-code@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/extension-document@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/extension-dropcursor@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2)': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + '@tiptap/pm': 2.27.2 + + '@tiptap/extension-floating-menu@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2)': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + '@tiptap/pm': 2.27.2 + tippy.js: 6.3.7 + + '@tiptap/extension-gapcursor@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2)': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + '@tiptap/pm': 2.27.2 + + '@tiptap/extension-hard-break@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/extension-heading@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/extension-highlight@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/extension-history@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2)': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + '@tiptap/pm': 2.27.2 + + '@tiptap/extension-horizontal-rule@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2)': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + '@tiptap/pm': 2.27.2 + + '@tiptap/extension-image@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/extension-italic@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/extension-link@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2)': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + '@tiptap/pm': 2.27.2 + linkifyjs: 4.3.3 + + '@tiptap/extension-list-item@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/extension-ordered-list@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/extension-paragraph@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/extension-placeholder@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2)': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + '@tiptap/pm': 2.27.2 + + '@tiptap/extension-strike@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/extension-table-cell@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/extension-table-header@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/extension-table-row@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/extension-table@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2)': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + '@tiptap/pm': 2.27.2 + + '@tiptap/extension-task-item@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2)': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + '@tiptap/pm': 2.27.2 + + '@tiptap/extension-task-list@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/extension-text-align@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/extension-text-style@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/extension-text@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/extension-underline@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + + '@tiptap/pm@2.27.2': + dependencies: + prosemirror-changeset: 2.4.1 + prosemirror-collab: 1.3.1 + prosemirror-commands: 1.7.1 + prosemirror-dropcursor: 1.8.3 + prosemirror-gapcursor: 1.4.1 + prosemirror-history: 1.5.0 + prosemirror-inputrules: 1.5.1 + prosemirror-keymap: 1.2.3 + prosemirror-markdown: 1.13.5 + prosemirror-menu: 1.3.2 + prosemirror-model: 1.25.11 + prosemirror-schema-basic: 1.2.4 + prosemirror-schema-list: 1.5.1 + prosemirror-state: 1.4.4 + prosemirror-tables: 1.8.5 + prosemirror-trailing-node: 3.0.0(prosemirror-model@1.25.11)(prosemirror-state@1.4.4)(prosemirror-view@1.42.1) + prosemirror-transform: 1.12.0 + prosemirror-view: 1.42.1 + + '@tiptap/react@2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + '@tiptap/extension-bubble-menu': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2) + '@tiptap/extension-floating-menu': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2) + '@tiptap/pm': 2.27.2 + '@types/use-sync-external-store': 0.0.6 + fast-deep-equal: 3.1.3 + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + use-sync-external-store: 1.6.0(react@19.2.7) + + '@tiptap/starter-kit@2.27.2': + dependencies: + '@tiptap/core': 2.27.2(@tiptap/pm@2.27.2) + '@tiptap/extension-blockquote': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/extension-bold': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/extension-bullet-list': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/extension-code': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/extension-code-block': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2) + '@tiptap/extension-document': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/extension-dropcursor': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2) + '@tiptap/extension-gapcursor': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2) + '@tiptap/extension-hard-break': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/extension-heading': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/extension-history': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2) + '@tiptap/extension-horizontal-rule': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))(@tiptap/pm@2.27.2) + '@tiptap/extension-italic': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/extension-list-item': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/extension-ordered-list': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/extension-paragraph': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/extension-strike': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/extension-text': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/extension-text-style': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2)) + '@tiptap/pm': 2.27.2 + '@turbo/darwin-64@2.10.5': optional: true @@ -5002,8 +5615,21 @@ snapshots: '@types/estree@1.0.9': {} + '@types/hast@3.0.5': + dependencies: + '@types/unist': 3.0.3 + '@types/json-schema@7.0.15': {} + '@types/linkify-it@5.0.0': {} + + '@types/markdown-it@14.1.2': + dependencies: + '@types/linkify-it': 5.0.0 + '@types/mdurl': 2.0.0 + + '@types/mdurl@2.0.0': {} + '@types/node@22.20.1': dependencies: undici-types: 6.21.0 @@ -5016,6 +5642,10 @@ snapshots: dependencies: csstype: 3.2.3 + '@types/unist@3.0.3': {} + + '@types/use-sync-external-store@0.0.6': {} + '@typescript-eslint/eslint-plugin@8.64.0(@typescript-eslint/parser@8.64.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.2 @@ -5427,6 +6057,8 @@ snapshots: cookie@2.0.1: {} + crelt@1.0.7: {} + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 @@ -5507,6 +6139,10 @@ snapshots: detect-node-es@1.1.0: {} + devlop@1.1.0: + dependencies: + dequal: 2.0.3 + doctrine@2.1.0: dependencies: esutils: 2.0.3 @@ -5554,6 +6190,8 @@ snapshots: graceful-fs: 4.2.11 tapable: 2.3.3 + entities@4.5.0: {} + entities@6.0.1: {} environment@1.1.0: {} @@ -6080,6 +6718,8 @@ snapshots: help-me@5.0.0: {} + highlight.js@11.11.1: {} + html-encoding-sniffer@4.0.0: dependencies: whatwg-encoding: 3.1.1 @@ -6427,6 +7067,12 @@ snapshots: lilconfig@3.1.3: {} + linkify-it@5.0.2: + dependencies: + uc.micro: 2.1.0 + + linkifyjs@4.3.3: {} + lint-staged@15.5.2(supports-color@7.2.0): dependencies: chalk: 5.6.2 @@ -6471,6 +7117,12 @@ snapshots: loupe@3.2.1: {} + lowlight@3.3.0: + dependencies: + '@types/hast': 3.0.5 + devlop: 1.1.0 + highlight.js: 11.11.1 + lru-cache@10.4.3: {} lru-cache@11.5.2: {} @@ -6489,8 +7141,19 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 + markdown-it@14.3.0: + dependencies: + argparse: 2.0.1 + entities: 4.5.0 + linkify-it: 5.0.2 + mdurl: 2.0.0 + punycode.js: 2.3.1 + uc.micro: 2.1.0 + math-intrinsics@1.1.0: {} + mdurl@2.0.0: {} + merge-stream@2.0.0: {} micromatch@4.0.8: @@ -6618,6 +7281,8 @@ snapshots: type-check: 0.4.0 word-wrap: 1.2.5 + orderedmap@2.1.1: {} + own-keys@1.0.1: dependencies: get-intrinsic: 1.3.0 @@ -6750,11 +7415,116 @@ snapshots: object-assign: 4.1.1 react-is: 16.13.1 + prosemirror-changeset@2.4.1: + dependencies: + prosemirror-transform: 1.12.0 + + prosemirror-collab@1.3.1: + dependencies: + prosemirror-state: 1.4.4 + + prosemirror-commands@1.7.1: + dependencies: + prosemirror-model: 1.25.11 + prosemirror-state: 1.4.4 + prosemirror-transform: 1.12.0 + + prosemirror-dropcursor@1.8.3: + dependencies: + prosemirror-state: 1.4.4 + prosemirror-transform: 1.12.0 + prosemirror-view: 1.42.1 + + prosemirror-gapcursor@1.4.1: + dependencies: + prosemirror-keymap: 1.2.3 + prosemirror-model: 1.25.11 + prosemirror-state: 1.4.4 + prosemirror-view: 1.42.1 + + prosemirror-history@1.5.0: + dependencies: + prosemirror-state: 1.4.4 + prosemirror-transform: 1.12.0 + prosemirror-view: 1.42.1 + rope-sequence: 1.3.4 + + prosemirror-inputrules@1.5.1: + dependencies: + prosemirror-state: 1.4.4 + prosemirror-transform: 1.12.0 + + prosemirror-keymap@1.2.3: + dependencies: + prosemirror-state: 1.4.4 + w3c-keyname: 2.2.8 + + prosemirror-markdown@1.13.5: + dependencies: + '@types/markdown-it': 14.1.2 + markdown-it: 14.3.0 + prosemirror-model: 1.25.11 + + prosemirror-menu@1.3.2: + dependencies: + crelt: 1.0.7 + prosemirror-commands: 1.7.1 + prosemirror-history: 1.5.0 + prosemirror-state: 1.4.4 + + prosemirror-model@1.25.11: + dependencies: + orderedmap: 2.1.1 + + prosemirror-schema-basic@1.2.4: + dependencies: + prosemirror-model: 1.25.11 + + prosemirror-schema-list@1.5.1: + dependencies: + prosemirror-model: 1.25.11 + prosemirror-state: 1.4.4 + prosemirror-transform: 1.12.0 + + prosemirror-state@1.4.4: + dependencies: + prosemirror-model: 1.25.11 + prosemirror-transform: 1.12.0 + prosemirror-view: 1.42.1 + + prosemirror-tables@1.8.5: + dependencies: + prosemirror-keymap: 1.2.3 + prosemirror-model: 1.25.11 + prosemirror-state: 1.4.4 + prosemirror-transform: 1.12.0 + prosemirror-view: 1.42.1 + + prosemirror-trailing-node@3.0.0(prosemirror-model@1.25.11)(prosemirror-state@1.4.4)(prosemirror-view@1.42.1): + dependencies: + '@remirror/core-constants': 3.0.0 + escape-string-regexp: 4.0.0 + prosemirror-model: 1.25.11 + prosemirror-state: 1.4.4 + prosemirror-view: 1.42.1 + + prosemirror-transform@1.12.0: + dependencies: + prosemirror-model: 1.25.11 + + prosemirror-view@1.42.1: + dependencies: + prosemirror-model: 1.25.11 + prosemirror-state: 1.4.4 + prosemirror-transform: 1.12.0 + pump@3.0.4: dependencies: end-of-stream: 1.4.5 once: 1.4.0 + punycode.js@2.3.1: {} + punycode@2.3.1: {} pure-rand@6.1.0: {} @@ -6916,6 +7686,8 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.62.2 fsevents: 2.3.3 + rope-sequence@1.3.4: {} + rrweb-cssom@0.8.0: {} safe-array-concat@1.1.4: @@ -7174,6 +7946,10 @@ snapshots: tinyspy@4.0.4: {} + tippy.js@6.3.7: + dependencies: + '@popperjs/core': 2.11.8 + tldts-core@6.1.86: {} tldts@6.1.86: @@ -7256,6 +8032,8 @@ snapshots: typescript@5.9.3: {} + uc.micro@2.1.0: {} + unbox-primitive@1.1.0: dependencies: call-bound: 1.0.4 @@ -7290,6 +8068,10 @@ snapshots: optionalDependencies: '@types/react': 19.2.17 + use-sync-external-store@1.6.0(react@19.2.7): + dependencies: + react: 19.2.7 + util-deprecate@1.0.2: {} vite-node@3.2.4(@types/node@22.20.1)(jiti@2.7.0)(lightningcss@1.32.0)(supports-color@7.2.0)(tsx@4.23.1)(yaml@2.9.0): @@ -7371,6 +8153,8 @@ snapshots: - tsx - yaml + w3c-keyname@2.2.8: {} + w3c-xmlserializer@5.0.0: dependencies: xml-name-validator: 5.0.0 @@ -7464,7 +8248,8 @@ snapshots: zod@3.25.76: {} - zustand@5.0.14(@types/react@19.2.17)(react@19.2.7): + zustand@5.0.14(@types/react@19.2.17)(react@19.2.7)(use-sync-external-store@1.6.0(react@19.2.7)): optionalDependencies: '@types/react': 19.2.17 react: 19.2.7 + use-sync-external-store: 1.6.0(react@19.2.7)