-
{item.title || 'Untitled'}
+
+ {!item.trashedAt && itemHref(item) ? (
+
+ {item.title || 'Untitled'}
+
+ ) : (
+ item.title || 'Untitled'
+ )}
+
{item.kind} · {detail(item)}
diff --git a/app/frontend/src/pages/spaces/SpaceLayout.tsx b/app/frontend/src/pages/spaces/SpaceLayout.tsx
index 60d3518..5a83754 100644
--- a/app/frontend/src/pages/spaces/SpaceLayout.tsx
+++ b/app/frontend/src/pages/spaces/SpaceLayout.tsx
@@ -27,6 +27,7 @@ export function SpaceLayout() {
const base = `/spaces/${space.id}`;
const tabs = [
[base, 'Items'],
+ [`${base}/notes`, 'Notes'],
[`${base}/tasks`, 'Tasks'],
[`${base}/recurring`, 'Recurring'],
[`${base}/tags`, 'Tags'],
diff --git a/app/frontend/src/pages/spaces/SpaceNotes.tsx b/app/frontend/src/pages/spaces/SpaceNotes.tsx
new file mode 100644
index 0000000..119a62f
--- /dev/null
+++ b/app/frontend/src/pages/spaces/SpaceNotes.tsx
@@ -0,0 +1,64 @@
+import { Link, useNavigate } from 'react-router';
+import { EmptyState, Icon, ListSkeleton } from '@project-graphite/ui';
+import { useAuth } from '../../auth';
+import { LoadError } from '../../components/LoadError';
+import { flattenTree, noteTitle, type Note } from '../../notes';
+import { useAction } from '../../useAction';
+import { useResource } from '../../useResource';
+import { useSpace } from './SpaceLayout';
+
+export function SpaceNotes() {
+ const auth = useAuth();
+ const space = useSpace();
+ const navigate = useNavigate();
+ const notes = useResource
(`/spaces/${space.id}/notes`, true);
+ const creating = useAction();
+ const editable = space.role !== 'viewer';
+
+ if (notes.error) return ;
+ if (!notes.data) return ;
+ const branches = flattenTree(notes.data);
+
+ return (
+
+ {editable && (
+
+ )}
+ {branches.length === 0 ? (
+
+ ) : (
+
+ {branches.map(({ note, depth }) => (
+ -
+
+
+ {note.icon ?? '·'}
+
+ {noteTitle(note)}
+ {note.pinnedAt && Pinned}
+
+
+ ))}
+
+ )}
+
+ );
+}
diff --git a/app/frontend/src/spaces.tsx b/app/frontend/src/spaces.tsx
index 213cced..e95026c 100644
--- a/app/frontend/src/spaces.tsx
+++ b/app/frontend/src/spaces.tsx
@@ -53,6 +53,15 @@ export async function addJoinedSpace(
spaces.mutate((current) => [...current.filter((shown) => shown.id !== space.id), space]);
}
+export function itemHref(item: { id: string; kind: string; spaceId: string }) {
+ if (item.kind === 'note') return `/notes/${item.id}`;
+ if (item.kind === 'event') return `/events/${item.id}`;
+ if (item.kind === 'task') return `/spaces/${item.spaceId}/tasks`;
+ if (item.kind === 'list') return `/spaces/${item.spaceId}/tasks?list=${item.id}`;
+ if (item.kind === 'subscription') return `/spaces/${item.spaceId}/recurring`;
+ return null;
+}
+
export function SpaceDot({ color }: { color: TagColor }) {
return ;
}
diff --git a/app/frontend/src/styles/global.css b/app/frontend/src/styles/global.css
index de29881..a983eae 100644
--- a/app/frontend/src/styles/global.css
+++ b/app/frontend/src/styles/global.css
@@ -1,3 +1,162 @@
@import 'tailwindcss';
@import '@project-graphite/ui/theme.css';
@source '../../../node_modules/@project-graphite/ui/dist';
+
+.note-title {
+ width: 100%;
+ border: 0;
+ background: transparent;
+ padding: 0;
+ color: var(--color-ink);
+ font-size: clamp(1.75rem, 4vw, 2.25rem);
+ font-weight: 640;
+ letter-spacing: -0.03em;
+ line-height: 1.15;
+}
+
+.note-title:focus {
+ outline: none;
+}
+
+.note-title::placeholder {
+ color: var(--color-faint);
+}
+
+.note-toolbar {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.25rem;
+}
+
+.note-tool {
+ min-width: 2rem;
+ border: 1px solid transparent;
+ border-radius: var(--radius-field);
+ padding: 0.3rem 0.5rem;
+ color: var(--color-muted);
+ font-size: 0.85rem;
+ font-weight: 600;
+}
+
+.note-tool:hover,
+.note-tool[aria-pressed='true'] {
+ border-color: var(--color-line);
+ background: var(--color-line-soft);
+ color: var(--color-ink);
+}
+
+.note-content {
+ min-height: 45vh;
+ color: var(--color-ink);
+ line-height: 1.7;
+ outline: none;
+}
+
+.note-content > * + * {
+ margin-top: 0.75em;
+}
+
+.note-content h1 {
+ font-size: 1.6rem;
+ font-weight: 640;
+ letter-spacing: -0.02em;
+}
+
+.note-content h2 {
+ font-size: 1.25rem;
+ font-weight: 620;
+}
+
+.note-content ul,
+.note-content ol {
+ padding-left: 1.4rem;
+}
+
+.note-content ul {
+ list-style: disc;
+}
+
+.note-content ol {
+ list-style: decimal;
+}
+
+.note-content ul[data-type='taskList'] {
+ list-style: none;
+ padding-left: 0.25rem;
+}
+
+.note-content ul[data-type='taskList'] li {
+ display: flex;
+ gap: 0.6rem;
+}
+
+.note-content ul[data-type='taskList'] li > label {
+ margin-top: 0.15rem;
+}
+
+.note-content ul[data-type='taskList'] li[data-checked='true'] > div {
+ color: var(--color-faint);
+ text-decoration: line-through;
+}
+
+.note-content blockquote {
+ border-left: 3px solid var(--color-line);
+ padding-left: 1rem;
+ color: var(--color-muted);
+}
+
+.note-content pre {
+ overflow-x: auto;
+ border-radius: var(--radius-field);
+ background: var(--color-surface);
+ padding: 0.75rem 1rem;
+ font-family: var(--font-mono);
+ font-size: 0.85rem;
+}
+
+.note-content code {
+ font-family: var(--font-mono);
+ font-size: 0.9em;
+}
+
+.note-content a {
+ color: var(--color-ink);
+ text-decoration: underline;
+}
+
+.note-content hr {
+ border: 0;
+ border-top: 1px solid var(--color-line);
+}
+
+.note-content p.is-editor-empty:first-child::before {
+ float: left;
+ height: 0;
+ color: var(--color-faint);
+ content: attr(data-placeholder);
+ pointer-events: none;
+}
+
+.collaboration-carets__caret {
+ position: relative;
+ margin-right: -1px;
+ margin-left: -1px;
+ border-right: 1px solid;
+ border-left: 1px solid;
+ pointer-events: none;
+ word-break: normal;
+}
+
+.collaboration-carets__label {
+ position: absolute;
+ top: -1.4em;
+ left: -1px;
+ border-radius: 3px 3px 3px 0;
+ padding: 0.1rem 0.3rem;
+ color: #0c0c0e;
+ font-size: 0.7rem;
+ font-weight: 600;
+ line-height: normal;
+ white-space: nowrap;
+ user-select: none;
+}
diff --git a/app/frontend/test/notes.spec.tsx b/app/frontend/test/notes.spec.tsx
new file mode 100644
index 0000000..a868bb0
--- /dev/null
+++ b/app/frontend/test/notes.spec.tsx
@@ -0,0 +1,148 @@
+import { act } from 'react';
+import { createRoot, type Root } from 'react-dom/client';
+import { MemoryRouter } from 'react-router';
+import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
+import { App } from '../src/App';
+import { AuthProvider } from '../src/auth';
+import { flattenTree, type Note } from '../src/notes';
+
+vi.mock('../src/components/NoteEditor', () => ({
+ default: ({ editable, noteId }: { editable: boolean; noteId: string }) => ,
+}));
+
+(globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true;
+
+const json = (body: unknown, status = 200) =>
+ new Response(JSON.stringify(body), { status, headers: { 'Content-Type': 'application/json' } });
+
+const user = { id: 'me', email: 'amr@example.com', handle: 'amr', displayName: 'Amr', role: 'member', timeZone: 'Etc/UTC' };
+const home = { id: 'home', name: 'Home', color: 'green', kind: 'shared', role: 'editor', createdAt: '2026-10-01T00:00:00Z' };
+const note = (id: string, title: string, parentId: string | null = null, position = 1): Note => ({
+ id,
+ spaceId: 'home',
+ title,
+ parentId,
+ position,
+ icon: null,
+ pinnedAt: null,
+ createdAt: '2026-10-05T10:00:00Z',
+ updatedAt: '2026-10-05T10:00:00Z',
+});
+const pages = [note('trips', 'Trips'), note('lisbon', 'Lisbon', 'trips'), note('food', 'Food', 'lisbon'), note('recipes', '', null, 2)];
+
+describe('Notes', () => {
+ let container: HTMLDivElement;
+ let root: Root;
+
+ beforeEach(() => {
+ container = document.createElement('div');
+ document.body.append(container);
+ root = createRoot(container);
+ });
+
+ afterEach(() => {
+ act(() => root.unmount());
+ container.remove();
+ vi.unstubAllGlobals();
+ });
+
+ function serve(route: (path: string, init?: RequestInit) => Response | undefined) {
+ const fetchMock = vi.fn((input: string, init?: RequestInit) => {
+ const path = input.replace('/api/v1', '');
+ if (path === '/auth/refresh') return Promise.resolve(json({ accessToken: 'token', user }));
+ if (path === '/spaces') return Promise.resolve(json([home]));
+ if (path === '/me/inbox/summary') return Promise.resolve(json({ unread: 0 }));
+ if (path === '/spaces/home/notes' && !init?.method) return Promise.resolve(json(pages));
+ return Promise.resolve(route(path, init) ?? new Response(null, { status: 404 }));
+ });
+ vi.stubGlobal('fetch', fetchMock);
+ return fetchMock;
+ }
+
+ async function render(path: string) {
+ await act(async () =>
+ root.render(
+
+
+
+
+ ,
+ ),
+ );
+ }
+
+ it('orders pages as a tree, keeping orphans at the top level', () => {
+ expect(flattenTree([...pages, note('orphan', 'Orphan', 'gone')]).map(({ note: page, depth }) => `${depth}:${page.title}`)).toEqual([
+ '0:Trips',
+ '1:Lisbon',
+ '2:Food',
+ '0:',
+ '0:Orphan',
+ ]);
+ });
+
+ it('lists the pages of a space and opens a new one', async () => {
+ const fetchMock = serve((path, init) => {
+ if (path === '/spaces/home/notes' && init?.method === 'POST') return json(note('new', ''), 201);
+ if (path === '/notes/new') return json({ ...note('new', ''), editable: true, path: [] });
+ return undefined;
+ });
+ await render('/spaces/home/notes');
+
+ const links = [...container.querySelectorAll('main a[href^="/notes/"]')];
+ expect(links.map((link) => link.textContent)).toEqual(['·Trips', '·Lisbon', '·Food', '·Untitled']);
+ expect((links[2] as HTMLElement).style.paddingLeft).toBe('3.5rem');
+
+ await act(async () => [...container.querySelectorAll('button')].find((button) => button.textContent === 'New page')!.click());
+ expect(fetchMock).toHaveBeenCalledWith('/api/v1/spaces/home/notes', expect.objectContaining({ method: 'POST' }));
+ expect(container.querySelector('[data-testid="editor"]')?.getAttribute('data-note')).toBe('new');
+ });
+
+ it('shows the path, renames on blur and adds a page inside', async () => {
+ const fetchMock = serve((path, init) => {
+ if (path === '/notes/food' && init?.method === 'PATCH') {
+ expect(JSON.parse(String(init.body))).toEqual({ title: 'Food and drink' });
+ return json(note('food', 'Food and drink', 'lisbon'));
+ }
+ if (path === '/notes/food') {
+ return json({ ...note('food', 'Food', 'lisbon'), editable: true, path: [{ id: 'trips', title: 'Trips' }, { id: 'lisbon', title: 'Lisbon' }] });
+ }
+ if (path === '/spaces/home/notes' && init?.method === 'POST') {
+ expect(JSON.parse(String(init.body))).toEqual({ parentId: 'food' });
+ return json(note('pastel', '', 'food'), 201);
+ }
+ if (path === '/notes/pastel') return json({ ...note('pastel', '', 'food'), editable: true, path: [] });
+ return undefined;
+ });
+ await render('/notes/food');
+
+ expect([...container.querySelectorAll('nav[aria-label="Breadcrumb"] a')].map((link) => link.textContent)).toEqual(['Home', 'Trips', 'Lisbon']);
+ const title = container.querySelector('input[aria-label="Page title"]')!;
+ expect(title.value).toBe('Food');
+ title.value = 'Food and drink';
+ await act(async () => {
+ title.dispatchEvent(new FocusEvent('focusout', { bubbles: true }));
+ });
+ expect(fetchMock).toHaveBeenCalledWith('/api/v1/notes/food', expect.objectContaining({ method: 'PATCH' }));
+
+ await act(async () => [...container.querySelectorAll('button')].find((button) => button.textContent?.includes('Add a page inside'))!.click());
+ expect(container.querySelector('[data-testid="editor"]')?.getAttribute('data-note')).toBe('pastel');
+ });
+
+ it('opens a viewer’s page read-only and explains a missing page', async () => {
+ serve((path) => {
+ if (path === '/notes/trips') return json({ ...note('trips', 'Trips'), editable: false, path: [] });
+ if (path === '/notes/gone') return json({ message: 'Item not found' }, 404);
+ return undefined;
+ });
+ await render('/notes/trips');
+ expect(container.querySelector('input[aria-label="Page title"]')!.readOnly).toBe(true);
+ expect(container.querySelector('[data-testid="editor"]')?.getAttribute('data-editable')).toBe('false');
+ expect(container.textContent).not.toContain('Add a page inside');
+
+ act(() => root.unmount());
+ root = createRoot(container);
+ await render('/notes/gone');
+ expect(container.textContent).toContain('Page not found');
+ });
+});
diff --git a/app/frontend/test/search.spec.tsx b/app/frontend/test/search.spec.tsx
index 52ce671..f2117d9 100644
--- a/app/frontend/test/search.spec.tsx
+++ b/app/frontend/test/search.spec.tsx
@@ -72,6 +72,6 @@ describe('Search palette', () => {
expect(fetchMock).toHaveBeenCalledWith('/api/v1/search?q=fla', expect.anything());
const options = [...container.querySelectorAll('[role="option"]')].map((option) => option.textContent);
expect(options).toEqual(['Flat rotanote · Flat', 'Flat billsFlat', 'Flat']);
- expect(container.querySelector('[role="option"]')?.getAttribute('href')).toBe('/spaces/flat');
+ expect(container.querySelector('[role="option"]')?.getAttribute('href')).toBe('/notes/rota');
});
});
diff --git a/app/frontend/vite.config.ts b/app/frontend/vite.config.ts
index 897cf3f..5e7fb97 100644
--- a/app/frontend/vite.config.ts
+++ b/app/frontend/vite.config.ts
@@ -29,7 +29,7 @@ export default defineConfig({
plugins: [react(), tailwindcss(), serviceWorker()],
server: {
proxy: {
- '/api': process.env.VITE_API_ORIGIN ?? 'http://localhost:3000',
+ '/api': { target: process.env.VITE_API_ORIGIN ?? 'http://localhost:3000', ws: true },
},
},
});
diff --git a/app/package-lock.json b/app/package-lock.json
index 918ae22..21bb1f6 100644
--- a/app/package-lock.json
+++ b/app/package-lock.json
@@ -19,8 +19,18 @@
"name": "strata-frontend",
"version": "0.1.0",
"dependencies": {
+ "@hocuspocus/provider": "4.7.0",
"@project-graphite/ui": "https://github.com/project-graphite/graphite-ui/releases/download/v0.3.0/project-graphite-ui-0.3.0.tgz",
- "uqr": "0.1.3"
+ "@tiptap/core": "3.31.4",
+ "@tiptap/extension-collaboration": "3.31.4",
+ "@tiptap/extension-collaboration-caret": "3.31.4",
+ "@tiptap/extension-list": "3.31.4",
+ "@tiptap/extensions": "3.31.4",
+ "@tiptap/pm": "3.31.4",
+ "@tiptap/react": "3.31.4",
+ "@tiptap/starter-kit": "3.31.4",
+ "uqr": "0.1.3",
+ "yjs": "13.6.33"
},
"devDependencies": {
"@tailwindcss/vite": "4.3.3",
@@ -183,6 +193,34 @@
"@electric-sql/pglite": "0.4.3"
}
},
+ "node_modules/@floating-ui/core": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.8.0.tgz",
+ "integrity": "sha512-0CIZ5itps/8x7BG8dEIhs53BvCUH2PCoogtakwRTut+Arm58sJooJ0AuZhLw2HJYIR5cMLNPBSS728sPho2khQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@floating-ui/utils": "^0.2.12"
+ }
+ },
+ "node_modules/@floating-ui/dom": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.8.0.tgz",
+ "integrity": "sha512-yXSrzeHZBTZadLOlfyhCkJHNeLJnHRnRInwdZ40L7ZiaAtrBwoYlsDrX3v5zB1Utk7CLfzcOVnVVWoXEky7Ceg==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@floating-ui/core": "^1.8.0",
+ "@floating-ui/utils": "^0.2.12"
+ }
+ },
+ "node_modules/@floating-ui/utils": {
+ "version": "0.2.12",
+ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.12.tgz",
+ "integrity": "sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==",
+ "license": "MIT",
+ "optional": true
+ },
"node_modules/@hocuspocus/common": {
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/@hocuspocus/common/-/common-4.7.0.tgz",
@@ -196,7 +234,6 @@
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/@hocuspocus/provider/-/provider-4.7.0.tgz",
"integrity": "sha512-BOAqoj6g4EZQ9pTwIiR7bNl1QkMAnrr8EY69jMcdhSLFtTrsKaE8hsDIEncPFnGq+khWRFCAPEJSM7F9HC7fvQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@hocuspocus/common": "^4.7.0",
@@ -626,7 +663,6 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@lifeomic/attempt/-/attempt-3.1.0.tgz",
"integrity": "sha512-QZqem4QuAnAyzfz+Gj5/+SLxqwCAw2qmt7732ZXodr6VDWGeYLG6w1i/vYLa55JQM9wRuBKLmXmiZ2P0LtE5rw==",
- "dev": true,
"license": "MIT"
},
"node_modules/@lukeed/csprng": {
@@ -2319,6 +2355,488 @@
"vite": "^5.2.0 || ^6 || ^7 || ^8"
}
},
+ "node_modules/@tiptap/core": {
+ "version": "3.31.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-3.31.4.tgz",
+ "integrity": "sha512-cIVUQYBycighzsk6GbmCef8ZiEDVxoT5EuAe4xg2q9dNkDqCXVqI4YGr9aavCQEiAS4uHiRwqvcsPqJHipFDfg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/pm": "3.31.4"
+ }
+ },
+ "node_modules/@tiptap/extension-blockquote": {
+ "version": "3.31.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-blockquote/-/extension-blockquote-3.31.4.tgz",
+ "integrity": "sha512-FHnbvCIW0eDKgUUFjmvEB0ax9YUBW7/Unm+38qpuQROvU872yRqhnDtycKT9IKk46jNdjM4A4fAGUbge10CrAA==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.31.4",
+ "@tiptap/pm": "3.31.4"
+ }
+ },
+ "node_modules/@tiptap/extension-bold": {
+ "version": "3.31.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-bold/-/extension-bold-3.31.4.tgz",
+ "integrity": "sha512-QX1xoXvO0gz6uVsoLegumqQ4MJXL7lcUDQZ4J7la7LBqiIh4efrCmp2EXbhpr37M/YQL7w8q3g7H/VovSh7xIg==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.31.4"
+ }
+ },
+ "node_modules/@tiptap/extension-bubble-menu": {
+ "version": "3.31.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-bubble-menu/-/extension-bubble-menu-3.31.4.tgz",
+ "integrity": "sha512-Ml/yswuys+3QkOMajfXyAGlUKCxEbT3dMyF8vHwQ5mDk9MDm+dqp10It5CrDBkUT/KkVTa6AJI3kb0TXZJZiAA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@floating-ui/dom": "^1.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.31.4",
+ "@tiptap/pm": "3.31.4"
+ }
+ },
+ "node_modules/@tiptap/extension-bullet-list": {
+ "version": "3.31.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-bullet-list/-/extension-bullet-list-3.31.4.tgz",
+ "integrity": "sha512-gHn1RDR4olCnmKpH+G9x+f8R+iKPNVdLlvbFkIpR/stjabZi7fB4Rr5GiHWsulbtxAjdQrNjnVeNdGM4rBxApw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/extension-list": "3.31.4"
+ }
+ },
+ "node_modules/@tiptap/extension-code": {
+ "version": "3.31.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-code/-/extension-code-3.31.4.tgz",
+ "integrity": "sha512-pzi8GNDs5J1DEoO1HNYiJ5WZpgOZzlc/2VIa77mMpEuD4hZxuK0BQzlF/O6Ps/O5P1lGJT4xS0Yowpzb9mD9RA==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.31.4"
+ }
+ },
+ "node_modules/@tiptap/extension-code-block": {
+ "version": "3.31.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-code-block/-/extension-code-block-3.31.4.tgz",
+ "integrity": "sha512-su/B/cfQ1HpiHl6JfJ6wa+RVEptiYsV4dCntE8XQNj2dUcII4y6w6PQbbswOoDrU79uXHsAvpy44215rghG4LA==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.31.4",
+ "@tiptap/pm": "3.31.4"
+ }
+ },
+ "node_modules/@tiptap/extension-collaboration": {
+ "version": "3.31.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-collaboration/-/extension-collaboration-3.31.4.tgz",
+ "integrity": "sha512-vIGuBU2oV1jIr0zGPdWc1qFo4NrzObktC06s8Z0zYCb59hm3lfnYzw0w4R2i/BYjjoKRgpiDVYweGAQHuLT7Vw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.31.4",
+ "@tiptap/pm": "3.31.4",
+ "@tiptap/y-tiptap": "^3.0.7",
+ "yjs": "^13"
+ }
+ },
+ "node_modules/@tiptap/extension-collaboration-caret": {
+ "version": "3.31.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-collaboration-caret/-/extension-collaboration-caret-3.31.4.tgz",
+ "integrity": "sha512-1dHvh2VDxRcNehsfPGpahP9RmFcoJIecoSuhOUjDfCP0QPxuGql14mYbflYYm1arj7Z6SZLNt/2tL5Zh0fpyqQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.31.4",
+ "@tiptap/pm": "3.31.4",
+ "@tiptap/y-tiptap": "^3.0.7"
+ }
+ },
+ "node_modules/@tiptap/extension-document": {
+ "version": "3.31.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-3.31.4.tgz",
+ "integrity": "sha512-vT20u62RWR+BLIyNJ54e24MPUY4zm8VF7tcgJnxQXi7BgVJWcNMtMWWDIkPJ4JNXwfoIznKh3jzYsaYmbCJgQQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.31.4"
+ }
+ },
+ "node_modules/@tiptap/extension-dropcursor": {
+ "version": "3.31.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-dropcursor/-/extension-dropcursor-3.31.4.tgz",
+ "integrity": "sha512-5TbCPCC4RL+QT1NYHjXCYDBHBtVqYOFvFEnk3v98lvXCM2PNL13ofXUfJPuykAVy1OdTAx4DlZOQAD9WKy/IdQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/extensions": "3.31.4"
+ }
+ },
+ "node_modules/@tiptap/extension-floating-menu": {
+ "version": "3.31.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-floating-menu/-/extension-floating-menu-3.31.4.tgz",
+ "integrity": "sha512-pKzulkDmolpVt7IP9FSPsC5pKbXQ5pyeqkaAYr8cyOVW+KUObpPRIzAuXvEso8PCjWgwJ1f2qyishOEMw8MbfQ==",
+ "license": "MIT",
+ "optional": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@floating-ui/dom": "^1.0.0",
+ "@tiptap/core": "3.31.4",
+ "@tiptap/pm": "3.31.4"
+ }
+ },
+ "node_modules/@tiptap/extension-gapcursor": {
+ "version": "3.31.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-gapcursor/-/extension-gapcursor-3.31.4.tgz",
+ "integrity": "sha512-hBogUAepQH6IQUhaePhPWzQ1Oeu+yqlJVMKO06Eue5m36uRy1PZZAQ780pCGT0SC4R5MH2td1N8EUQ7bupQdDA==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/extensions": "3.31.4"
+ }
+ },
+ "node_modules/@tiptap/extension-hard-break": {
+ "version": "3.31.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-hard-break/-/extension-hard-break-3.31.4.tgz",
+ "integrity": "sha512-oLNajLyUvRMg1qtzFgKGduygTlpaHFB9PU+M+pUWdA4sa1bRnxS2Y++Ao4lHYopJ7nxatLndrYoCIHkotqkPDQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.31.4"
+ }
+ },
+ "node_modules/@tiptap/extension-heading": {
+ "version": "3.31.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-heading/-/extension-heading-3.31.4.tgz",
+ "integrity": "sha512-KqlSeLathpdxCc3kVHBCA/RkHvb+V7u5vgiSEu1Cv3L70r7F19COMGODav/k1AGYBgEXKL6lM9cy8cloE5/28g==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.31.4"
+ }
+ },
+ "node_modules/@tiptap/extension-horizontal-rule": {
+ "version": "3.31.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-3.31.4.tgz",
+ "integrity": "sha512-ws0Kh8kfHL7ESILSXj0HJAXs8G10ewlW1sedXKm8dm0op9L8il+xl8bEJVoqG/jMf77900Fc2CaQldcCGRpF1g==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.31.4",
+ "@tiptap/pm": "3.31.4"
+ }
+ },
+ "node_modules/@tiptap/extension-italic": {
+ "version": "3.31.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-italic/-/extension-italic-3.31.4.tgz",
+ "integrity": "sha512-pftTQBPYZocNDAj/u6OyDIp7YxmN0+N895cQPogJQ6qMHdLiRhzgawiEewJkniyN1w8k3Wx/Etp8pTKrxaOOBQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.31.4"
+ }
+ },
+ "node_modules/@tiptap/extension-link": {
+ "version": "3.31.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-link/-/extension-link-3.31.4.tgz",
+ "integrity": "sha512-LLxW3qfeL9gvDdMPVdxYFYZ0zZSjsoIDhOqjJ5U2UfaK3U2iwkKTBgV2qT+FWf3uUHmBRjBZ08q3dRPmWBAD5g==",
+ "license": "MIT",
+ "dependencies": {
+ "linkifyjs": "^4.3.3"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.31.4",
+ "@tiptap/pm": "3.31.4"
+ }
+ },
+ "node_modules/@tiptap/extension-list": {
+ "version": "3.31.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-list/-/extension-list-3.31.4.tgz",
+ "integrity": "sha512-Wd4YRYxOdf+TtF33/QsRo1RK1CecVxjYGjUBIKNGHAywfh8tghgV4YOUCiV1iJqYt2IBs+RWlIqTmdIPzBrd4A==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.31.4",
+ "@tiptap/pm": "3.31.4"
+ }
+ },
+ "node_modules/@tiptap/extension-list-item": {
+ "version": "3.31.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-list-item/-/extension-list-item-3.31.4.tgz",
+ "integrity": "sha512-ao8XAPvhOrtGFILs+fKtOM91omDSpUC8X19m44gbaq5xJDVpIMZ0rP+NAVUS72G7LskhcHa0bu/Pm022bUVjVw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/extension-list": "3.31.4"
+ }
+ },
+ "node_modules/@tiptap/extension-list-keymap": {
+ "version": "3.31.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-list-keymap/-/extension-list-keymap-3.31.4.tgz",
+ "integrity": "sha512-etdkl/YnYfwtALDxecJ+4WYgJAez1fn1vzzZqJklZBpgqiZtny3NxpvWS7/JhsltNG84Wo/oovpfJgVmzhddrw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/extension-list": "3.31.4"
+ }
+ },
+ "node_modules/@tiptap/extension-ordered-list": {
+ "version": "3.31.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-ordered-list/-/extension-ordered-list-3.31.4.tgz",
+ "integrity": "sha512-UNWyF+Dhm08znszIMnT8Y2kJ1lvtiCvUGs1aG7m9cPHxDa7VycWnOqdtXWkc+6xRLNiC0zgWCFWgLLHduV8pRQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/extension-list": "3.31.4"
+ }
+ },
+ "node_modules/@tiptap/extension-paragraph": {
+ "version": "3.31.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-paragraph/-/extension-paragraph-3.31.4.tgz",
+ "integrity": "sha512-WZlBgw+XVKXerRlmEsoQ7x1PwSU+dh3X+b70+ViZsLebdfsmmYBIaNDrvIGwG9UQr5eLnddJnZplMSTI2YKs+g==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.31.4"
+ }
+ },
+ "node_modules/@tiptap/extension-strike": {
+ "version": "3.31.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-strike/-/extension-strike-3.31.4.tgz",
+ "integrity": "sha512-4MBr63TJIMqxCjE+gAPdlY1IdELgvbAP516K3Ntn/BkcpEbEoPMEYVz+XTxULyHQEuARDO6jsXPPxRXpA74jaw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.31.4"
+ }
+ },
+ "node_modules/@tiptap/extension-text": {
+ "version": "3.31.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-3.31.4.tgz",
+ "integrity": "sha512-WL2ZRpFksgQcXJN05/UQH09YCH9LlhdLrSEcviASvEH/aAfsKiJlDrouN8PET+YAWK/F5xFc5/Q1z0xj+I23jw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.31.4"
+ }
+ },
+ "node_modules/@tiptap/extension-underline": {
+ "version": "3.31.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extension-underline/-/extension-underline-3.31.4.tgz",
+ "integrity": "sha512-0iFGPIqmqGkCrOFh1OPo7Dzv5s86dVN3bZaugsz0jK04otkb8bn04ZDKP2/6Wq+lcK0M9DfJ0QqfW5hC2nBZxQ==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.31.4"
+ }
+ },
+ "node_modules/@tiptap/extensions": {
+ "version": "3.31.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/extensions/-/extensions-3.31.4.tgz",
+ "integrity": "sha512-nIupIne/sHpV2Kw1M4MOmr4+G454KI8BXM5+LWKOU2EpzfALZWVSy7koF9lVRna4Zp5Gv8hfg5Z8kvmrYQvhkw==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.31.4",
+ "@tiptap/pm": "3.31.4"
+ }
+ },
+ "node_modules/@tiptap/pm": {
+ "version": "3.31.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-3.31.4.tgz",
+ "integrity": "sha512-x7dwth79cQp4QGae66/RJqMDJQv0+n7b7dD7cyFQBWqzPFLJxN/4paHY4qbWedZjNLhRyIOAD9a5q4AYM1zmPA==",
+ "license": "MIT",
+ "dependencies": {
+ "prosemirror-changeset": "^2.4.1",
+ "prosemirror-commands": "^1.7.1",
+ "prosemirror-dropcursor": "^1.8.2",
+ "prosemirror-gapcursor": "^1.4.1",
+ "prosemirror-history": "^1.5.0",
+ "prosemirror-inputrules": "^1.5.1",
+ "prosemirror-keymap": "^1.2.3",
+ "prosemirror-model": "^1.25.11",
+ "prosemirror-schema-list": "^1.5.1",
+ "prosemirror-state": "^1.4.4",
+ "prosemirror-tables": "^1.8.5",
+ "prosemirror-transform": "^1.12.0",
+ "prosemirror-view": "^1.42.3"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ }
+ },
+ "node_modules/@tiptap/react": {
+ "version": "3.31.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/react/-/react-3.31.4.tgz",
+ "integrity": "sha512-mBvvXgdPhMinT1NPfwHvFK1dFdMXHVWMSeNn0IPj7/zV0XBmOnASkEOwoIvl8NluKYEtpZBE1yA+6pN2enLa5g==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/use-sync-external-store": "^0.0.6",
+ "fast-equals": "^5.3.3",
+ "use-sync-external-store": "^1.4.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ },
+ "optionalDependencies": {
+ "@tiptap/extension-bubble-menu": "3.31.4",
+ "@tiptap/extension-floating-menu": "3.31.4"
+ },
+ "peerDependencies": {
+ "@tiptap/core": "3.31.4",
+ "@tiptap/pm": "3.31.4",
+ "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
+ "@types/react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react": "^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/@tiptap/starter-kit": {
+ "version": "3.31.4",
+ "resolved": "https://registry.npmjs.org/@tiptap/starter-kit/-/starter-kit-3.31.4.tgz",
+ "integrity": "sha512-u7HIJ9vK6kFe4S4J2CIcDLrhRZzoTMSyU0XxjQ6lUNF7pWW3rMi//pvi8RcsZmxGjyb8CpXAqYgNl7f9WyaUeA==",
+ "license": "MIT",
+ "dependencies": {
+ "@tiptap/core": "3.31.4",
+ "@tiptap/extension-blockquote": "3.31.4",
+ "@tiptap/extension-bold": "3.31.4",
+ "@tiptap/extension-bullet-list": "3.31.4",
+ "@tiptap/extension-code": "3.31.4",
+ "@tiptap/extension-code-block": "3.31.4",
+ "@tiptap/extension-document": "3.31.4",
+ "@tiptap/extension-dropcursor": "3.31.4",
+ "@tiptap/extension-gapcursor": "3.31.4",
+ "@tiptap/extension-hard-break": "3.31.4",
+ "@tiptap/extension-heading": "3.31.4",
+ "@tiptap/extension-horizontal-rule": "3.31.4",
+ "@tiptap/extension-italic": "3.31.4",
+ "@tiptap/extension-link": "3.31.4",
+ "@tiptap/extension-list": "3.31.4",
+ "@tiptap/extension-list-item": "3.31.4",
+ "@tiptap/extension-list-keymap": "3.31.4",
+ "@tiptap/extension-ordered-list": "3.31.4",
+ "@tiptap/extension-paragraph": "3.31.4",
+ "@tiptap/extension-strike": "3.31.4",
+ "@tiptap/extension-text": "3.31.4",
+ "@tiptap/extension-underline": "3.31.4",
+ "@tiptap/extensions": "3.31.4",
+ "@tiptap/pm": "3.31.4"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/ueberdosis"
+ }
+ },
+ "node_modules/@tiptap/y-tiptap": {
+ "version": "3.0.9",
+ "resolved": "https://registry.npmjs.org/@tiptap/y-tiptap/-/y-tiptap-3.0.9.tgz",
+ "integrity": "sha512-7/El8NQ8R5V5MkdrOUdfj9IgZacpt0H071xNimX7B0AnYiWiKefQnMKd41neQYzo2MOXbWdN3iZ+7Z7BruzOSA==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "lib0": "^0.2.100"
+ },
+ "engines": {
+ "node": ">=16.0.0",
+ "npm": ">=8.0.0"
+ },
+ "peerDependencies": {
+ "prosemirror-model": "^1.7.1",
+ "prosemirror-state": "^1.2.3",
+ "prosemirror-view": "^1.9.10",
+ "y-protocols": "^1.0.1",
+ "yjs": "^13.5.38"
+ }
+ },
"node_modules/@tokenizer/inflate": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/@tokenizer/inflate/-/inflate-0.4.1.tgz",
@@ -2615,7 +3133,6 @@
"version": "19.3.0",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.3.0.tgz",
"integrity": "sha512-ZI7bU42mZXXKHn/qNLEw2IrbiINU7X5+vfgdixBHkCNpYWXjKgfQ/P+uyGb5CjOLB9UcnTeg3rylQtV2hym44Q==",
- "devOptional": true,
"license": "MIT",
"peerDependencies": {
"@types/react": "^19.3.0"
@@ -2642,6 +3159,12 @@
"@types/node": "*"
}
},
+ "node_modules/@types/use-sync-external-store": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz",
+ "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==",
+ "license": "MIT"
+ },
"node_modules/@types/validator": {
"version": "13.15.10",
"resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.15.10.tgz",
@@ -3996,6 +4519,15 @@
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"license": "MIT"
},
+ "node_modules/fast-equals": {
+ "version": "5.4.3",
+ "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.4.3.tgz",
+ "integrity": "sha512-8unmvA0qrfpFWBYUate9BTGtQdKHWBYt+KdAIkag7Vvxe7wz8Q2nJg7fLMC0bJqe0bjP31kca7Ckaawrs4Istg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
"node_modules/fast-querystring": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/fast-querystring/-/fast-querystring-1.1.2.tgz",
@@ -4870,6 +5402,12 @@
"url": "https://opencollective.com/parcel"
}
},
+ "node_modules/linkifyjs": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/linkifyjs/-/linkifyjs-4.3.3.tgz",
+ "integrity": "sha512-P8aEP5U/D1/IlTY2OeYsErdwh9bGuLE30NcXtKEjgdHcahveQoQwM2yZNsioQHsWFz0P7KKudisbrzCgR0sDHg==",
+ "license": "MIT"
+ },
"node_modules/load-esm": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/load-esm/-/load-esm-1.0.3.tgz",
@@ -5412,6 +5950,12 @@
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
}
},
+ "node_modules/orderedmap": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-2.1.1.tgz",
+ "integrity": "sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==",
+ "license": "MIT"
+ },
"node_modules/oxlint": {
"version": "1.85.0",
"resolved": "https://registry.npmjs.org/oxlint/-/oxlint-1.85.0.tgz",
@@ -5818,6 +6362,145 @@
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
"license": "ISC"
},
+ "node_modules/prosemirror-changeset": {
+ "version": "2.4.4",
+ "resolved": "https://registry.npmjs.org/prosemirror-changeset/-/prosemirror-changeset-2.4.4.tgz",
+ "integrity": "sha512-Gyuz9jYdrAeA9I7AholyOes9KUmv/lEwsC5O9s5xF5VB3EgTPsXMGUxz4+H1B+wKVPdZbvRcg1Cp3x8qX+8ofA==",
+ "license": "MIT",
+ "dependencies": {
+ "prosemirror-transform": "^1.0.0"
+ }
+ },
+ "node_modules/prosemirror-commands": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.7.2.tgz",
+ "integrity": "sha512-q6Q6szxqdu9Xd6EcdKsqXghu5nQdZTpB4Q9yd04WRc7/jt763e/rT60Owh0L1GYY+T46o5rD+9lEN36dZS43tw==",
+ "license": "MIT",
+ "dependencies": {
+ "prosemirror-model": "^1.0.0",
+ "prosemirror-state": "^1.0.0",
+ "prosemirror-transform": "^1.10.2"
+ }
+ },
+ "node_modules/prosemirror-dropcursor": {
+ "version": "1.8.4",
+ "resolved": "https://registry.npmjs.org/prosemirror-dropcursor/-/prosemirror-dropcursor-1.8.4.tgz",
+ "integrity": "sha512-VmKxhcA6a+h5oPSYmfF1ZNeQqPbyYaIxqZsKqeYCyTlPtrjUgNaHL3P8vVaO19oqAV0zuaM/axkowZHrB1P3Tg==",
+ "license": "MIT",
+ "dependencies": {
+ "prosemirror-state": "^1.0.0",
+ "prosemirror-transform": "^1.1.0",
+ "prosemirror-view": "^1.1.0"
+ }
+ },
+ "node_modules/prosemirror-gapcursor": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/prosemirror-gapcursor/-/prosemirror-gapcursor-1.4.1.tgz",
+ "integrity": "sha512-pMdYaEnjNMSwl11yjEGtgTmLkR08m/Vl+Jj443167p9eB3HVQKhYCc4gmHVDsLPODfZfjr/MmirsdyZziXbQKw==",
+ "license": "MIT",
+ "dependencies": {
+ "prosemirror-keymap": "^1.0.0",
+ "prosemirror-model": "^1.0.0",
+ "prosemirror-state": "^1.0.0",
+ "prosemirror-view": "^1.0.0"
+ }
+ },
+ "node_modules/prosemirror-history": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.5.1.tgz",
+ "integrity": "sha512-onlwnqKvgtFg6srZOmDOAhlAy1FIHQpOExORybX0S+DvJepE5tPALrB9iGet/2sqqqrelSnB10OoiOJqAvu2DA==",
+ "license": "MIT",
+ "dependencies": {
+ "prosemirror-state": "^1.2.2",
+ "prosemirror-transform": "^1.0.0",
+ "prosemirror-view": "^1.31.0",
+ "rope-sequence": "^1.3.0"
+ }
+ },
+ "node_modules/prosemirror-inputrules": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/prosemirror-inputrules/-/prosemirror-inputrules-1.5.1.tgz",
+ "integrity": "sha512-7wj4uMjKaXWAQ1CDgxNzNtR9AlsuwzHfdFH1ygEHA2KHF2DOEaXl1CJfNPAKCg9qNEh4rum975QLaCiQPyY6Fw==",
+ "license": "MIT",
+ "dependencies": {
+ "prosemirror-state": "^1.0.0",
+ "prosemirror-transform": "^1.0.0"
+ }
+ },
+ "node_modules/prosemirror-keymap": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/prosemirror-keymap/-/prosemirror-keymap-1.2.3.tgz",
+ "integrity": "sha512-4HucRlpiLd1IPQQXNqeo81BGtkY8Ai5smHhKW9jjPKRc2wQIxksg7Hl1tTI2IfT2B/LgX6bfYvXxEpJl7aKYKw==",
+ "license": "MIT",
+ "dependencies": {
+ "prosemirror-state": "^1.0.0",
+ "w3c-keyname": "^2.2.0"
+ }
+ },
+ "node_modules/prosemirror-model": {
+ "version": "1.25.12",
+ "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.25.12.tgz",
+ "integrity": "sha512-Ue2gTmXMa7EhpLNhC7J+h4+ykD8ha12K6rrZFFKKJHBForfIStw5gJ6Zrf1mqqAa9NmpmEB4wp9bKmA4eUVjWg==",
+ "license": "MIT",
+ "dependencies": {
+ "orderedmap": "^2.0.0"
+ }
+ },
+ "node_modules/prosemirror-schema-list": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.5.1.tgz",
+ "integrity": "sha512-927lFx/uwyQaGwJxLWCZRkjXG0p48KpMj6ueoYiu4JX05GGuGcgzAy62dfiV8eFZftgyBUvLx76RsMe20fJl+Q==",
+ "license": "MIT",
+ "dependencies": {
+ "prosemirror-model": "^1.0.0",
+ "prosemirror-state": "^1.0.0",
+ "prosemirror-transform": "^1.7.3"
+ }
+ },
+ "node_modules/prosemirror-state": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.4.4.tgz",
+ "integrity": "sha512-6jiYHH2CIGbCfnxdHbXZ12gySFY/fz/ulZE333G6bPqIZ4F+TXo9ifiR86nAHpWnfoNjOb3o5ESi7J8Uz1jXHw==",
+ "license": "MIT",
+ "dependencies": {
+ "prosemirror-model": "^1.0.0",
+ "prosemirror-transform": "^1.0.0",
+ "prosemirror-view": "^1.27.0"
+ }
+ },
+ "node_modules/prosemirror-tables": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/prosemirror-tables/-/prosemirror-tables-1.8.5.tgz",
+ "integrity": "sha512-V/0cDCsHKHe/tfWkeCmthNUcEp1IVO3p6vwN8XtwE9PZQLAZJigbw3QoraAdfJPir4NKJtNvOB8oYGKRl+t0Dw==",
+ "license": "MIT",
+ "dependencies": {
+ "prosemirror-keymap": "^1.2.3",
+ "prosemirror-model": "^1.25.4",
+ "prosemirror-state": "^1.4.4",
+ "prosemirror-transform": "^1.10.5",
+ "prosemirror-view": "^1.41.4"
+ }
+ },
+ "node_modules/prosemirror-transform": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.12.2.tgz",
+ "integrity": "sha512-PE/aY0HEY4zczvmqrilgkUK/WautF0chvMqkmM/iN5/aPHvwrCWaQZjS6CIZp+K84YrvPFqrL+YArrfJX8xX7g==",
+ "license": "MIT",
+ "dependencies": {
+ "prosemirror-model": "^1.21.0"
+ }
+ },
+ "node_modules/prosemirror-view": {
+ "version": "1.42.6",
+ "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.42.6.tgz",
+ "integrity": "sha512-3g25f6hKV2bBxo3puH3EcYWmmVNSH0iWmNsMVT7sugDSpA025jgpOLarcDWr39SdzPjYMaiYtRdNtXialPSjEQ==",
+ "license": "MIT",
+ "dependencies": {
+ "prosemirror-model": "^1.25.12",
+ "prosemirror-state": "^1.0.0",
+ "prosemirror-transform": "^1.1.0"
+ }
+ },
"node_modules/proxy-addr": {
"version": "2.0.8",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.8.tgz",
@@ -6077,6 +6760,12 @@
"@rolldown/binding-win32-x64-msvc": "1.2.12"
}
},
+ "node_modules/rope-sequence": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/rope-sequence/-/rope-sequence-1.3.4.tgz",
+ "integrity": "sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==",
+ "license": "MIT"
+ },
"node_modules/router": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz",
@@ -6698,6 +7387,15 @@
"integrity": "sha512-0rjE8iEJe4YmT9TOhwsZtqCMRLc5DXZUI2UEYUUg63ikBkqqE5EYWaI0etFe/5KUcmcYwLih2RND1kq+hrUJXA==",
"license": "MIT"
},
+ "node_modules/use-sync-external-store": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.7.0.tgz",
+ "integrity": "sha512-6L+EeigHMQhdaIPNIFUKwfWJSwWFQ8gJbJ2DLOs5sDIegTwR9fRxvnM3uciHKjIZhFz+KAv2emhWMRvDmMcY8A==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
"node_modules/utils-merge": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
@@ -7216,6 +7914,12 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/w3c-keyname": {
+ "version": "2.2.8",
+ "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz",
+ "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==",
+ "license": "MIT"
+ },
"node_modules/whatwg-mimetype": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz",