fix: resolve TipTap v3 collaboration crash
Browse files- Replace @tiptap /extension-collaboration-cursor v2 with custom
CollaborationCursorV3 using yCursorPlugin from @tiptap /y-tiptap
(same ySyncPluginKey as Collaboration v3)
- Simplify CollaborationUndo to read UndoManager from Collaboration v3's
yUndoPlugin instead of creating its own
- Fix BubbleMenu import: @tiptap /react/menus (v3 API change)
- Install @floating-ui/dom, remove y-prosemirror and .npmrc
- Fix backend Image import to named export
Made-with: Cursor
- backend/src/publisher/extensions.ts +2 -1
- frontend/.npmrc +0 -1
- frontend/package-lock.json +39 -52
- frontend/package.json +1 -3
- frontend/src/editor/BubbleToolbar.tsx +2 -2
- frontend/src/editor/Editor.tsx +3 -5
- frontend/src/editor/extensions/collaboration-cursor-v3.ts +80 -0
- frontend/src/editor/extensions/collaboration-undo.ts +12 -61
backend/src/publisher/extensions.ts
CHANGED
|
@@ -11,7 +11,7 @@ import { Node, mergeAttributes, type Extensions } from "@tiptap/core";
|
|
| 11 |
import StarterKit from "@tiptap/starter-kit";
|
| 12 |
import CodeBlockLowlight from "@tiptap/extension-code-block-lowlight";
|
| 13 |
import Mathematics from "@tiptap/extension-mathematics";
|
| 14 |
-
import Image from "@tiptap/extension-image";
|
| 15 |
import { Table } from "@tiptap/extension-table";
|
| 16 |
import { TableRow } from "@tiptap/extension-table-row";
|
| 17 |
import { TableCell } from "@tiptap/extension-table-cell";
|
|
@@ -305,6 +305,7 @@ export function getServerExtensions(): Extensions {
|
|
| 305 |
return [
|
| 306 |
StarterKit.configure({
|
| 307 |
codeBlock: false,
|
|
|
|
| 308 |
link: { openOnClick: false },
|
| 309 |
} as any),
|
| 310 |
CodeBlockLowlight.configure({ lowlight }),
|
|
|
|
| 11 |
import StarterKit from "@tiptap/starter-kit";
|
| 12 |
import CodeBlockLowlight from "@tiptap/extension-code-block-lowlight";
|
| 13 |
import Mathematics from "@tiptap/extension-mathematics";
|
| 14 |
+
import { Image } from "@tiptap/extension-image";
|
| 15 |
import { Table } from "@tiptap/extension-table";
|
| 16 |
import { TableRow } from "@tiptap/extension-table-row";
|
| 17 |
import { TableCell } from "@tiptap/extension-table-cell";
|
|
|
|
| 305 |
return [
|
| 306 |
StarterKit.configure({
|
| 307 |
codeBlock: false,
|
| 308 |
+
undoRedo: false,
|
| 309 |
link: { openOnClick: false },
|
| 310 |
} as any),
|
| 311 |
CodeBlockLowlight.configure({ lowlight }),
|
frontend/.npmrc
DELETED
|
@@ -1 +0,0 @@
|
|
| 1 |
-
legacy-peer-deps=true
|
|
|
|
|
|
frontend/package-lock.json
CHANGED
|
@@ -11,13 +11,12 @@
|
|
| 11 |
"@ai-sdk/react": "^3.0.160",
|
| 12 |
"@emotion/react": "^11.14.0",
|
| 13 |
"@emotion/styled": "^11.14.1",
|
|
|
|
| 14 |
"@mui/icons-material": "^9.0.0",
|
| 15 |
"@mui/material": "^9.0.0",
|
| 16 |
"@tiptap/core": "^3.22.3",
|
| 17 |
-
"@tiptap/extension-bubble-menu": "^3.22.3",
|
| 18 |
"@tiptap/extension-code-block-lowlight": "^3.22.3",
|
| 19 |
"@tiptap/extension-collaboration": "^3.22.3",
|
| 20 |
-
"@tiptap/extension-collaboration-cursor": "^2.26.2",
|
| 21 |
"@tiptap/extension-image": "^3.22.3",
|
| 22 |
"@tiptap/extension-link": "^3.22.3",
|
| 23 |
"@tiptap/extension-mathematics": "^3.22.3",
|
|
@@ -39,7 +38,6 @@
|
|
| 39 |
"react": "^18.3.0",
|
| 40 |
"react-dom": "^18.3.0",
|
| 41 |
"tippy.js": "^6.3.7",
|
| 42 |
-
"y-prosemirror": "^1.2.0",
|
| 43 |
"y-websocket": "^2.0.0",
|
| 44 |
"yjs": "^13.6.0",
|
| 45 |
"zod": "^4.3.6"
|
|
@@ -145,6 +143,7 @@
|
|
| 145 |
"integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
|
| 146 |
"dev": true,
|
| 147 |
"license": "MIT",
|
|
|
|
| 148 |
"dependencies": {
|
| 149 |
"@babel/code-frame": "^7.29.0",
|
| 150 |
"@babel/generator": "^7.29.0",
|
|
@@ -461,6 +460,7 @@
|
|
| 461 |
"resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz",
|
| 462 |
"integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==",
|
| 463 |
"license": "MIT",
|
|
|
|
| 464 |
"dependencies": {
|
| 465 |
"@babel/runtime": "^7.18.3",
|
| 466 |
"@emotion/babel-plugin": "^11.13.5",
|
|
@@ -504,6 +504,7 @@
|
|
| 504 |
"resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.1.tgz",
|
| 505 |
"integrity": "sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==",
|
| 506 |
"license": "MIT",
|
|
|
|
| 507 |
"dependencies": {
|
| 508 |
"@babel/runtime": "^7.18.3",
|
| 509 |
"@emotion/babel-plugin": "^11.13.5",
|
|
@@ -1005,6 +1006,7 @@
|
|
| 1005 |
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz",
|
| 1006 |
"integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==",
|
| 1007 |
"license": "MIT",
|
|
|
|
| 1008 |
"dependencies": {
|
| 1009 |
"@floating-ui/core": "^1.7.5",
|
| 1010 |
"@floating-ui/utils": "^0.2.11"
|
|
@@ -1103,6 +1105,7 @@
|
|
| 1103 |
"resolved": "https://registry.npmjs.org/@mui/material/-/material-9.0.0.tgz",
|
| 1104 |
"integrity": "sha512-+VP/oQCDhDR87NQQgXnNBG8dwy6GNuQLnenS1pZvkbn2dKFSxRSRMybTpH9xUxXP+316mlYDy5CSbYtusnCWtw==",
|
| 1105 |
"license": "MIT",
|
|
|
|
| 1106 |
"dependencies": {
|
| 1107 |
"@babel/runtime": "^7.29.2",
|
| 1108 |
"@mui/core-downloads-tracker": "^9.0.0",
|
|
@@ -1688,6 +1691,7 @@
|
|
| 1688 |
"resolved": "https://registry.npmjs.org/@tiptap/core/-/core-3.22.3.tgz",
|
| 1689 |
"integrity": "sha512-Dv9MKK5BDWCF0N2l6/Pxv3JNCce2kwuWf2cKMBc2bEetx0Pn6o7zlFmSxMvYK4UtG1Tw9Yg/ZHi6QOFWK0Zm9Q==",
|
| 1690 |
"license": "MIT",
|
|
|
|
| 1691 |
"funding": {
|
| 1692 |
"type": "github",
|
| 1693 |
"url": "https://github.com/sponsors/ueberdosis"
|
|
@@ -1727,6 +1731,7 @@
|
|
| 1727 |
"resolved": "https://registry.npmjs.org/@tiptap/extension-bubble-menu/-/extension-bubble-menu-3.22.3.tgz",
|
| 1728 |
"integrity": "sha512-Y6zQjh0ypDg32HWgICEvmPSKjGLr39k3aDxxt/H0uQEZSfw4smT0hxUyyyjVjx68C6t6MTnwdfz0hPI5lL68vQ==",
|
| 1729 |
"license": "MIT",
|
|
|
|
| 1730 |
"dependencies": {
|
| 1731 |
"@floating-ui/dom": "^1.0.0"
|
| 1732 |
},
|
|
@@ -1770,6 +1775,7 @@
|
|
| 1770 |
"resolved": "https://registry.npmjs.org/@tiptap/extension-code-block/-/extension-code-block-3.22.3.tgz",
|
| 1771 |
"integrity": "sha512-RiQtEjDAPrHpdo6sw6b7fOw/PijqgFIsozKKkGcSeBgWHQuFg7q9OxJTj+l0e60rVwSu/5gmKEEobzM9bX+t2Q==",
|
| 1772 |
"license": "MIT",
|
|
|
|
| 1773 |
"funding": {
|
| 1774 |
"type": "github",
|
| 1775 |
"url": "https://github.com/sponsors/ueberdosis"
|
|
@@ -1812,20 +1818,6 @@
|
|
| 1812 |
"yjs": "^13"
|
| 1813 |
}
|
| 1814 |
},
|
| 1815 |
-
"node_modules/@tiptap/extension-collaboration-cursor": {
|
| 1816 |
-
"version": "2.26.2",
|
| 1817 |
-
"resolved": "https://registry.npmjs.org/@tiptap/extension-collaboration-cursor/-/extension-collaboration-cursor-2.26.2.tgz",
|
| 1818 |
-
"integrity": "sha512-FdRb27mZ5Kr18hN6cbfBj1e9F0DOoHB1Gv3IYeic+g4h1C9BjDVMN0+JRBQc+4lamNA8TsHO0oKWRwaPe4sSlA==",
|
| 1819 |
-
"license": "MIT",
|
| 1820 |
-
"funding": {
|
| 1821 |
-
"type": "github",
|
| 1822 |
-
"url": "https://github.com/sponsors/ueberdosis"
|
| 1823 |
-
},
|
| 1824 |
-
"peerDependencies": {
|
| 1825 |
-
"@tiptap/core": "^2.7.0",
|
| 1826 |
-
"y-prosemirror": "^1.2.11"
|
| 1827 |
-
}
|
| 1828 |
-
},
|
| 1829 |
"node_modules/@tiptap/extension-document": {
|
| 1830 |
"version": "3.22.3",
|
| 1831 |
"resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-3.22.3.tgz",
|
|
@@ -1969,6 +1961,7 @@
|
|
| 1969 |
"resolved": "https://registry.npmjs.org/@tiptap/extension-list/-/extension-list-3.22.3.tgz",
|
| 1970 |
"integrity": "sha512-rqvv/dtqwbX+8KnPv0eMYp6PnBcuhPMol5cv1GlS8Nq/Cxt68EWGUHBuTFesw+hdnRQLmKwzoO1DlRn7PhxYRQ==",
|
| 1971 |
"license": "MIT",
|
|
|
|
| 1972 |
"funding": {
|
| 1973 |
"type": "github",
|
| 1974 |
"url": "https://github.com/sponsors/ueberdosis"
|
|
@@ -2076,6 +2069,7 @@
|
|
| 2076 |
"resolved": "https://registry.npmjs.org/@tiptap/extension-table/-/extension-table-3.22.3.tgz",
|
| 2077 |
"integrity": "sha512-inbQSusJad7H0T++L1APg/anfL5d15cNGp2YG3vwo6TQr71nn2c9pepvmz3xuAIt8eygZDRba+4GT/COP1f9QA==",
|
| 2078 |
"license": "MIT",
|
|
|
|
| 2079 |
"funding": {
|
| 2080 |
"type": "github",
|
| 2081 |
"url": "https://github.com/sponsors/ueberdosis"
|
|
@@ -2155,6 +2149,7 @@
|
|
| 2155 |
"resolved": "https://registry.npmjs.org/@tiptap/extensions/-/extensions-3.22.3.tgz",
|
| 2156 |
"integrity": "sha512-s5eiMq0m5N6N+W7dU6rd60KgZyyCD7FvtPNNswISfPr12EQwJBfbjWwTqd0UKNzA4fNrhQEERXnzORkykttPeA==",
|
| 2157 |
"license": "MIT",
|
|
|
|
| 2158 |
"funding": {
|
| 2159 |
"type": "github",
|
| 2160 |
"url": "https://github.com/sponsors/ueberdosis"
|
|
@@ -2169,6 +2164,7 @@
|
|
| 2169 |
"resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-3.22.3.tgz",
|
| 2170 |
"integrity": "sha512-NjfWjZuvrqmpICT+GZWNIjtOdhPyqFKDMtQy7tsQ5rErM9L2ZQdy/+T/BKSO1JdTeBhdg9OP+0yfsqoYp2aT6A==",
|
| 2171 |
"license": "MIT",
|
|
|
|
| 2172 |
"dependencies": {
|
| 2173 |
"prosemirror-changeset": "^2.3.0",
|
| 2174 |
"prosemirror-collab": "^1.3.1",
|
|
@@ -2276,6 +2272,7 @@
|
|
| 2276 |
"resolved": "https://registry.npmjs.org/@tiptap/y-tiptap/-/y-tiptap-3.0.3.tgz",
|
| 2277 |
"integrity": "sha512-8UvuV4lTisCE9cMTc/X8kRyTn9edUO7Kball0I6wb17VwZSjNDfh/YKtP4O5vcPawEzFHQIvZGq/k1h37kAf0w==",
|
| 2278 |
"license": "MIT",
|
|
|
|
| 2279 |
"dependencies": {
|
| 2280 |
"lib0": "^0.2.100"
|
| 2281 |
},
|
|
@@ -2396,8 +2393,8 @@
|
|
| 2396 |
"version": "18.3.28",
|
| 2397 |
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.28.tgz",
|
| 2398 |
"integrity": "sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==",
|
| 2399 |
-
"dev": true,
|
| 2400 |
"license": "MIT",
|
|
|
|
| 2401 |
"dependencies": {
|
| 2402 |
"@types/prop-types": "*",
|
| 2403 |
"csstype": "^3.2.2"
|
|
@@ -2407,8 +2404,8 @@
|
|
| 2407 |
"version": "18.3.7",
|
| 2408 |
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz",
|
| 2409 |
"integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==",
|
| 2410 |
-
"dev": true,
|
| 2411 |
"license": "MIT",
|
|
|
|
| 2412 |
"peerDependencies": {
|
| 2413 |
"@types/react": "^18.0.0"
|
| 2414 |
}
|
|
@@ -2582,6 +2579,7 @@
|
|
| 2582 |
}
|
| 2583 |
],
|
| 2584 |
"license": "MIT",
|
|
|
|
| 2585 |
"dependencies": {
|
| 2586 |
"baseline-browser-mapping": "^2.10.12",
|
| 2587 |
"caniuse-lite": "^1.0.30001782",
|
|
@@ -2691,6 +2689,15 @@
|
|
| 2691 |
"node": ">=10"
|
| 2692 |
}
|
| 2693 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2694 |
"node_modules/crelt": {
|
| 2695 |
"version": "1.0.6",
|
| 2696 |
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz",
|
|
@@ -2991,6 +2998,7 @@
|
|
| 2991 |
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.11.1.tgz",
|
| 2992 |
"integrity": "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==",
|
| 2993 |
"license": "BSD-3-Clause",
|
|
|
|
| 2994 |
"engines": {
|
| 2995 |
"node": ">=12.0.0"
|
| 2996 |
}
|
|
@@ -3144,6 +3152,7 @@
|
|
| 3144 |
"https://github.com/sponsors/katex"
|
| 3145 |
],
|
| 3146 |
"license": "MIT",
|
|
|
|
| 3147 |
"dependencies": {
|
| 3148 |
"commander": "^8.3.0"
|
| 3149 |
},
|
|
@@ -3366,6 +3375,7 @@
|
|
| 3366 |
"resolved": "https://registry.npmjs.org/lowlight/-/lowlight-3.3.0.tgz",
|
| 3367 |
"integrity": "sha512-0JNhgFoPvP6U6lE/UdVsSq99tn6DhjjpAj5MxG49ewd2mOBVtwWYIT8ClyABhq198aXXODMU6Ox8DrGy/CpTZQ==",
|
| 3368 |
"license": "MIT",
|
|
|
|
| 3369 |
"dependencies": {
|
| 3370 |
"@types/hast": "^3.0.0",
|
| 3371 |
"devlop": "^1.0.0",
|
|
@@ -3539,6 +3549,7 @@
|
|
| 3539 |
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
|
| 3540 |
"dev": true,
|
| 3541 |
"license": "MIT",
|
|
|
|
| 3542 |
"engines": {
|
| 3543 |
"node": ">=12"
|
| 3544 |
},
|
|
@@ -3704,6 +3715,7 @@
|
|
| 3704 |
"resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.25.4.tgz",
|
| 3705 |
"integrity": "sha512-PIM7E43PBxKce8OQeezAs9j4TP+5yDpZVbuurd1h5phUxEKIu+G2a+EUZzIC5nS1mJktDJWzbqS23n1tsAf5QA==",
|
| 3706 |
"license": "MIT",
|
|
|
|
| 3707 |
"dependencies": {
|
| 3708 |
"orderedmap": "^2.0.0"
|
| 3709 |
}
|
|
@@ -3733,6 +3745,7 @@
|
|
| 3733 |
"resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.4.4.tgz",
|
| 3734 |
"integrity": "sha512-6jiYHH2CIGbCfnxdHbXZ12gySFY/fz/ulZE333G6bPqIZ4F+TXo9ifiR86nAHpWnfoNjOb3o5ESi7J8Uz1jXHw==",
|
| 3735 |
"license": "MIT",
|
|
|
|
| 3736 |
"dependencies": {
|
| 3737 |
"prosemirror-model": "^1.0.0",
|
| 3738 |
"prosemirror-transform": "^1.0.0",
|
|
@@ -3781,6 +3794,7 @@
|
|
| 3781 |
"resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.41.8.tgz",
|
| 3782 |
"integrity": "sha512-TnKDdohEatgyZNGCDWIdccOHXhYloJwbwU+phw/a23KBvJIR9lWQWW7WHHK3vBdOLDNuF7TaX98GObUZOWkOnA==",
|
| 3783 |
"license": "MIT",
|
|
|
|
| 3784 |
"dependencies": {
|
| 3785 |
"prosemirror-model": "^1.20.0",
|
| 3786 |
"prosemirror-state": "^1.0.0",
|
|
@@ -3808,6 +3822,7 @@
|
|
| 3808 |
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
|
| 3809 |
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
|
| 3810 |
"license": "MIT",
|
|
|
|
| 3811 |
"dependencies": {
|
| 3812 |
"loose-envify": "^1.1.0"
|
| 3813 |
},
|
|
@@ -3820,6 +3835,7 @@
|
|
| 3820 |
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
|
| 3821 |
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
|
| 3822 |
"license": "MIT",
|
|
|
|
| 3823 |
"dependencies": {
|
| 3824 |
"loose-envify": "^1.1.0",
|
| 3825 |
"scheduler": "^0.23.2"
|
|
@@ -4153,6 +4169,7 @@
|
|
| 4153 |
"integrity": "sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ==",
|
| 4154 |
"dev": true,
|
| 4155 |
"license": "MIT",
|
|
|
|
| 4156 |
"dependencies": {
|
| 4157 |
"esbuild": "^0.25.0",
|
| 4158 |
"fdir": "^6.4.4",
|
|
@@ -4266,35 +4283,12 @@
|
|
| 4266 |
"yjs": "^13.0.0"
|
| 4267 |
}
|
| 4268 |
},
|
| 4269 |
-
"node_modules/y-prosemirror": {
|
| 4270 |
-
"version": "1.3.7",
|
| 4271 |
-
"resolved": "https://registry.npmjs.org/y-prosemirror/-/y-prosemirror-1.3.7.tgz",
|
| 4272 |
-
"integrity": "sha512-NpM99WSdD4Fx4if5xOMDpPtU3oAmTSjlzh5U4353ABbRHl1HtAFUx6HlebLZfyFxXN9jzKMDkVbcRjqOZVkYQg==",
|
| 4273 |
-
"license": "MIT",
|
| 4274 |
-
"dependencies": {
|
| 4275 |
-
"lib0": "^0.2.109"
|
| 4276 |
-
},
|
| 4277 |
-
"engines": {
|
| 4278 |
-
"node": ">=16.0.0",
|
| 4279 |
-
"npm": ">=8.0.0"
|
| 4280 |
-
},
|
| 4281 |
-
"funding": {
|
| 4282 |
-
"type": "GitHub Sponsors ❤",
|
| 4283 |
-
"url": "https://github.com/sponsors/dmonad"
|
| 4284 |
-
},
|
| 4285 |
-
"peerDependencies": {
|
| 4286 |
-
"prosemirror-model": "^1.7.1",
|
| 4287 |
-
"prosemirror-state": "^1.2.3",
|
| 4288 |
-
"prosemirror-view": "^1.9.10",
|
| 4289 |
-
"y-protocols": "^1.0.1",
|
| 4290 |
-
"yjs": "^13.5.38"
|
| 4291 |
-
}
|
| 4292 |
-
},
|
| 4293 |
"node_modules/y-protocols": {
|
| 4294 |
"version": "1.0.7",
|
| 4295 |
"resolved": "https://registry.npmjs.org/y-protocols/-/y-protocols-1.0.7.tgz",
|
| 4296 |
"integrity": "sha512-YSVsLoXxO67J6eE/nV4AtFtT3QEotZf5sK5BHxFBXso7VDUT3Tx07IfA6hsu5Q5OmBdMkQVmFZ9QOA7fikWvnw==",
|
| 4297 |
"license": "MIT",
|
|
|
|
| 4298 |
"dependencies": {
|
| 4299 |
"lib0": "^0.2.85"
|
| 4300 |
},
|
|
@@ -4347,20 +4341,12 @@
|
|
| 4347 |
"dev": true,
|
| 4348 |
"license": "ISC"
|
| 4349 |
},
|
| 4350 |
-
"node_modules/yaml": {
|
| 4351 |
-
"version": "1.10.3",
|
| 4352 |
-
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.3.tgz",
|
| 4353 |
-
"integrity": "sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==",
|
| 4354 |
-
"license": "ISC",
|
| 4355 |
-
"engines": {
|
| 4356 |
-
"node": ">= 6"
|
| 4357 |
-
}
|
| 4358 |
-
},
|
| 4359 |
"node_modules/yjs": {
|
| 4360 |
"version": "13.6.30",
|
| 4361 |
"resolved": "https://registry.npmjs.org/yjs/-/yjs-13.6.30.tgz",
|
| 4362 |
"integrity": "sha512-vv/9h42eCMC81ZHDFswuu/MKzkl/vyq1BhaNGfHyOonwlG4CJbQF4oiBBJPvfdeCt/PlVDWh7Nov9D34YY09uQ==",
|
| 4363 |
"license": "MIT",
|
|
|
|
| 4364 |
"dependencies": {
|
| 4365 |
"lib0": "^0.2.99"
|
| 4366 |
},
|
|
@@ -4378,6 +4364,7 @@
|
|
| 4378 |
"resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz",
|
| 4379 |
"integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==",
|
| 4380 |
"license": "MIT",
|
|
|
|
| 4381 |
"funding": {
|
| 4382 |
"url": "https://github.com/sponsors/colinhacks"
|
| 4383 |
}
|
|
|
|
| 11 |
"@ai-sdk/react": "^3.0.160",
|
| 12 |
"@emotion/react": "^11.14.0",
|
| 13 |
"@emotion/styled": "^11.14.1",
|
| 14 |
+
"@floating-ui/dom": "^1.7.6",
|
| 15 |
"@mui/icons-material": "^9.0.0",
|
| 16 |
"@mui/material": "^9.0.0",
|
| 17 |
"@tiptap/core": "^3.22.3",
|
|
|
|
| 18 |
"@tiptap/extension-code-block-lowlight": "^3.22.3",
|
| 19 |
"@tiptap/extension-collaboration": "^3.22.3",
|
|
|
|
| 20 |
"@tiptap/extension-image": "^3.22.3",
|
| 21 |
"@tiptap/extension-link": "^3.22.3",
|
| 22 |
"@tiptap/extension-mathematics": "^3.22.3",
|
|
|
|
| 38 |
"react": "^18.3.0",
|
| 39 |
"react-dom": "^18.3.0",
|
| 40 |
"tippy.js": "^6.3.7",
|
|
|
|
| 41 |
"y-websocket": "^2.0.0",
|
| 42 |
"yjs": "^13.6.0",
|
| 43 |
"zod": "^4.3.6"
|
|
|
|
| 143 |
"integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
|
| 144 |
"dev": true,
|
| 145 |
"license": "MIT",
|
| 146 |
+
"peer": true,
|
| 147 |
"dependencies": {
|
| 148 |
"@babel/code-frame": "^7.29.0",
|
| 149 |
"@babel/generator": "^7.29.0",
|
|
|
|
| 460 |
"resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz",
|
| 461 |
"integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==",
|
| 462 |
"license": "MIT",
|
| 463 |
+
"peer": true,
|
| 464 |
"dependencies": {
|
| 465 |
"@babel/runtime": "^7.18.3",
|
| 466 |
"@emotion/babel-plugin": "^11.13.5",
|
|
|
|
| 504 |
"resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.1.tgz",
|
| 505 |
"integrity": "sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==",
|
| 506 |
"license": "MIT",
|
| 507 |
+
"peer": true,
|
| 508 |
"dependencies": {
|
| 509 |
"@babel/runtime": "^7.18.3",
|
| 510 |
"@emotion/babel-plugin": "^11.13.5",
|
|
|
|
| 1006 |
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz",
|
| 1007 |
"integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==",
|
| 1008 |
"license": "MIT",
|
| 1009 |
+
"peer": true,
|
| 1010 |
"dependencies": {
|
| 1011 |
"@floating-ui/core": "^1.7.5",
|
| 1012 |
"@floating-ui/utils": "^0.2.11"
|
|
|
|
| 1105 |
"resolved": "https://registry.npmjs.org/@mui/material/-/material-9.0.0.tgz",
|
| 1106 |
"integrity": "sha512-+VP/oQCDhDR87NQQgXnNBG8dwy6GNuQLnenS1pZvkbn2dKFSxRSRMybTpH9xUxXP+316mlYDy5CSbYtusnCWtw==",
|
| 1107 |
"license": "MIT",
|
| 1108 |
+
"peer": true,
|
| 1109 |
"dependencies": {
|
| 1110 |
"@babel/runtime": "^7.29.2",
|
| 1111 |
"@mui/core-downloads-tracker": "^9.0.0",
|
|
|
|
| 1691 |
"resolved": "https://registry.npmjs.org/@tiptap/core/-/core-3.22.3.tgz",
|
| 1692 |
"integrity": "sha512-Dv9MKK5BDWCF0N2l6/Pxv3JNCce2kwuWf2cKMBc2bEetx0Pn6o7zlFmSxMvYK4UtG1Tw9Yg/ZHi6QOFWK0Zm9Q==",
|
| 1693 |
"license": "MIT",
|
| 1694 |
+
"peer": true,
|
| 1695 |
"funding": {
|
| 1696 |
"type": "github",
|
| 1697 |
"url": "https://github.com/sponsors/ueberdosis"
|
|
|
|
| 1731 |
"resolved": "https://registry.npmjs.org/@tiptap/extension-bubble-menu/-/extension-bubble-menu-3.22.3.tgz",
|
| 1732 |
"integrity": "sha512-Y6zQjh0ypDg32HWgICEvmPSKjGLr39k3aDxxt/H0uQEZSfw4smT0hxUyyyjVjx68C6t6MTnwdfz0hPI5lL68vQ==",
|
| 1733 |
"license": "MIT",
|
| 1734 |
+
"optional": true,
|
| 1735 |
"dependencies": {
|
| 1736 |
"@floating-ui/dom": "^1.0.0"
|
| 1737 |
},
|
|
|
|
| 1775 |
"resolved": "https://registry.npmjs.org/@tiptap/extension-code-block/-/extension-code-block-3.22.3.tgz",
|
| 1776 |
"integrity": "sha512-RiQtEjDAPrHpdo6sw6b7fOw/PijqgFIsozKKkGcSeBgWHQuFg7q9OxJTj+l0e60rVwSu/5gmKEEobzM9bX+t2Q==",
|
| 1777 |
"license": "MIT",
|
| 1778 |
+
"peer": true,
|
| 1779 |
"funding": {
|
| 1780 |
"type": "github",
|
| 1781 |
"url": "https://github.com/sponsors/ueberdosis"
|
|
|
|
| 1818 |
"yjs": "^13"
|
| 1819 |
}
|
| 1820 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1821 |
"node_modules/@tiptap/extension-document": {
|
| 1822 |
"version": "3.22.3",
|
| 1823 |
"resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-3.22.3.tgz",
|
|
|
|
| 1961 |
"resolved": "https://registry.npmjs.org/@tiptap/extension-list/-/extension-list-3.22.3.tgz",
|
| 1962 |
"integrity": "sha512-rqvv/dtqwbX+8KnPv0eMYp6PnBcuhPMol5cv1GlS8Nq/Cxt68EWGUHBuTFesw+hdnRQLmKwzoO1DlRn7PhxYRQ==",
|
| 1963 |
"license": "MIT",
|
| 1964 |
+
"peer": true,
|
| 1965 |
"funding": {
|
| 1966 |
"type": "github",
|
| 1967 |
"url": "https://github.com/sponsors/ueberdosis"
|
|
|
|
| 2069 |
"resolved": "https://registry.npmjs.org/@tiptap/extension-table/-/extension-table-3.22.3.tgz",
|
| 2070 |
"integrity": "sha512-inbQSusJad7H0T++L1APg/anfL5d15cNGp2YG3vwo6TQr71nn2c9pepvmz3xuAIt8eygZDRba+4GT/COP1f9QA==",
|
| 2071 |
"license": "MIT",
|
| 2072 |
+
"peer": true,
|
| 2073 |
"funding": {
|
| 2074 |
"type": "github",
|
| 2075 |
"url": "https://github.com/sponsors/ueberdosis"
|
|
|
|
| 2149 |
"resolved": "https://registry.npmjs.org/@tiptap/extensions/-/extensions-3.22.3.tgz",
|
| 2150 |
"integrity": "sha512-s5eiMq0m5N6N+W7dU6rd60KgZyyCD7FvtPNNswISfPr12EQwJBfbjWwTqd0UKNzA4fNrhQEERXnzORkykttPeA==",
|
| 2151 |
"license": "MIT",
|
| 2152 |
+
"peer": true,
|
| 2153 |
"funding": {
|
| 2154 |
"type": "github",
|
| 2155 |
"url": "https://github.com/sponsors/ueberdosis"
|
|
|
|
| 2164 |
"resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-3.22.3.tgz",
|
| 2165 |
"integrity": "sha512-NjfWjZuvrqmpICT+GZWNIjtOdhPyqFKDMtQy7tsQ5rErM9L2ZQdy/+T/BKSO1JdTeBhdg9OP+0yfsqoYp2aT6A==",
|
| 2166 |
"license": "MIT",
|
| 2167 |
+
"peer": true,
|
| 2168 |
"dependencies": {
|
| 2169 |
"prosemirror-changeset": "^2.3.0",
|
| 2170 |
"prosemirror-collab": "^1.3.1",
|
|
|
|
| 2272 |
"resolved": "https://registry.npmjs.org/@tiptap/y-tiptap/-/y-tiptap-3.0.3.tgz",
|
| 2273 |
"integrity": "sha512-8UvuV4lTisCE9cMTc/X8kRyTn9edUO7Kball0I6wb17VwZSjNDfh/YKtP4O5vcPawEzFHQIvZGq/k1h37kAf0w==",
|
| 2274 |
"license": "MIT",
|
| 2275 |
+
"peer": true,
|
| 2276 |
"dependencies": {
|
| 2277 |
"lib0": "^0.2.100"
|
| 2278 |
},
|
|
|
|
| 2393 |
"version": "18.3.28",
|
| 2394 |
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.28.tgz",
|
| 2395 |
"integrity": "sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==",
|
|
|
|
| 2396 |
"license": "MIT",
|
| 2397 |
+
"peer": true,
|
| 2398 |
"dependencies": {
|
| 2399 |
"@types/prop-types": "*",
|
| 2400 |
"csstype": "^3.2.2"
|
|
|
|
| 2404 |
"version": "18.3.7",
|
| 2405 |
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz",
|
| 2406 |
"integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==",
|
|
|
|
| 2407 |
"license": "MIT",
|
| 2408 |
+
"peer": true,
|
| 2409 |
"peerDependencies": {
|
| 2410 |
"@types/react": "^18.0.0"
|
| 2411 |
}
|
|
|
|
| 2579 |
}
|
| 2580 |
],
|
| 2581 |
"license": "MIT",
|
| 2582 |
+
"peer": true,
|
| 2583 |
"dependencies": {
|
| 2584 |
"baseline-browser-mapping": "^2.10.12",
|
| 2585 |
"caniuse-lite": "^1.0.30001782",
|
|
|
|
| 2689 |
"node": ">=10"
|
| 2690 |
}
|
| 2691 |
},
|
| 2692 |
+
"node_modules/cosmiconfig/node_modules/yaml": {
|
| 2693 |
+
"version": "1.10.3",
|
| 2694 |
+
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.3.tgz",
|
| 2695 |
+
"integrity": "sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==",
|
| 2696 |
+
"license": "ISC",
|
| 2697 |
+
"engines": {
|
| 2698 |
+
"node": ">= 6"
|
| 2699 |
+
}
|
| 2700 |
+
},
|
| 2701 |
"node_modules/crelt": {
|
| 2702 |
"version": "1.0.6",
|
| 2703 |
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz",
|
|
|
|
| 2998 |
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.11.1.tgz",
|
| 2999 |
"integrity": "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==",
|
| 3000 |
"license": "BSD-3-Clause",
|
| 3001 |
+
"peer": true,
|
| 3002 |
"engines": {
|
| 3003 |
"node": ">=12.0.0"
|
| 3004 |
}
|
|
|
|
| 3152 |
"https://github.com/sponsors/katex"
|
| 3153 |
],
|
| 3154 |
"license": "MIT",
|
| 3155 |
+
"peer": true,
|
| 3156 |
"dependencies": {
|
| 3157 |
"commander": "^8.3.0"
|
| 3158 |
},
|
|
|
|
| 3375 |
"resolved": "https://registry.npmjs.org/lowlight/-/lowlight-3.3.0.tgz",
|
| 3376 |
"integrity": "sha512-0JNhgFoPvP6U6lE/UdVsSq99tn6DhjjpAj5MxG49ewd2mOBVtwWYIT8ClyABhq198aXXODMU6Ox8DrGy/CpTZQ==",
|
| 3377 |
"license": "MIT",
|
| 3378 |
+
"peer": true,
|
| 3379 |
"dependencies": {
|
| 3380 |
"@types/hast": "^3.0.0",
|
| 3381 |
"devlop": "^1.0.0",
|
|
|
|
| 3549 |
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
|
| 3550 |
"dev": true,
|
| 3551 |
"license": "MIT",
|
| 3552 |
+
"peer": true,
|
| 3553 |
"engines": {
|
| 3554 |
"node": ">=12"
|
| 3555 |
},
|
|
|
|
| 3715 |
"resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.25.4.tgz",
|
| 3716 |
"integrity": "sha512-PIM7E43PBxKce8OQeezAs9j4TP+5yDpZVbuurd1h5phUxEKIu+G2a+EUZzIC5nS1mJktDJWzbqS23n1tsAf5QA==",
|
| 3717 |
"license": "MIT",
|
| 3718 |
+
"peer": true,
|
| 3719 |
"dependencies": {
|
| 3720 |
"orderedmap": "^2.0.0"
|
| 3721 |
}
|
|
|
|
| 3745 |
"resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.4.4.tgz",
|
| 3746 |
"integrity": "sha512-6jiYHH2CIGbCfnxdHbXZ12gySFY/fz/ulZE333G6bPqIZ4F+TXo9ifiR86nAHpWnfoNjOb3o5ESi7J8Uz1jXHw==",
|
| 3747 |
"license": "MIT",
|
| 3748 |
+
"peer": true,
|
| 3749 |
"dependencies": {
|
| 3750 |
"prosemirror-model": "^1.0.0",
|
| 3751 |
"prosemirror-transform": "^1.0.0",
|
|
|
|
| 3794 |
"resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.41.8.tgz",
|
| 3795 |
"integrity": "sha512-TnKDdohEatgyZNGCDWIdccOHXhYloJwbwU+phw/a23KBvJIR9lWQWW7WHHK3vBdOLDNuF7TaX98GObUZOWkOnA==",
|
| 3796 |
"license": "MIT",
|
| 3797 |
+
"peer": true,
|
| 3798 |
"dependencies": {
|
| 3799 |
"prosemirror-model": "^1.20.0",
|
| 3800 |
"prosemirror-state": "^1.0.0",
|
|
|
|
| 3822 |
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
|
| 3823 |
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
|
| 3824 |
"license": "MIT",
|
| 3825 |
+
"peer": true,
|
| 3826 |
"dependencies": {
|
| 3827 |
"loose-envify": "^1.1.0"
|
| 3828 |
},
|
|
|
|
| 3835 |
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
|
| 3836 |
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
|
| 3837 |
"license": "MIT",
|
| 3838 |
+
"peer": true,
|
| 3839 |
"dependencies": {
|
| 3840 |
"loose-envify": "^1.1.0",
|
| 3841 |
"scheduler": "^0.23.2"
|
|
|
|
| 4169 |
"integrity": "sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ==",
|
| 4170 |
"dev": true,
|
| 4171 |
"license": "MIT",
|
| 4172 |
+
"peer": true,
|
| 4173 |
"dependencies": {
|
| 4174 |
"esbuild": "^0.25.0",
|
| 4175 |
"fdir": "^6.4.4",
|
|
|
|
| 4283 |
"yjs": "^13.0.0"
|
| 4284 |
}
|
| 4285 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4286 |
"node_modules/y-protocols": {
|
| 4287 |
"version": "1.0.7",
|
| 4288 |
"resolved": "https://registry.npmjs.org/y-protocols/-/y-protocols-1.0.7.tgz",
|
| 4289 |
"integrity": "sha512-YSVsLoXxO67J6eE/nV4AtFtT3QEotZf5sK5BHxFBXso7VDUT3Tx07IfA6hsu5Q5OmBdMkQVmFZ9QOA7fikWvnw==",
|
| 4290 |
"license": "MIT",
|
| 4291 |
+
"peer": true,
|
| 4292 |
"dependencies": {
|
| 4293 |
"lib0": "^0.2.85"
|
| 4294 |
},
|
|
|
|
| 4341 |
"dev": true,
|
| 4342 |
"license": "ISC"
|
| 4343 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4344 |
"node_modules/yjs": {
|
| 4345 |
"version": "13.6.30",
|
| 4346 |
"resolved": "https://registry.npmjs.org/yjs/-/yjs-13.6.30.tgz",
|
| 4347 |
"integrity": "sha512-vv/9h42eCMC81ZHDFswuu/MKzkl/vyq1BhaNGfHyOonwlG4CJbQF4oiBBJPvfdeCt/PlVDWh7Nov9D34YY09uQ==",
|
| 4348 |
"license": "MIT",
|
| 4349 |
+
"peer": true,
|
| 4350 |
"dependencies": {
|
| 4351 |
"lib0": "^0.2.99"
|
| 4352 |
},
|
|
|
|
| 4364 |
"resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz",
|
| 4365 |
"integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==",
|
| 4366 |
"license": "MIT",
|
| 4367 |
+
"peer": true,
|
| 4368 |
"funding": {
|
| 4369 |
"url": "https://github.com/sponsors/colinhacks"
|
| 4370 |
}
|
frontend/package.json
CHANGED
|
@@ -12,13 +12,12 @@
|
|
| 12 |
"@ai-sdk/react": "^3.0.160",
|
| 13 |
"@emotion/react": "^11.14.0",
|
| 14 |
"@emotion/styled": "^11.14.1",
|
|
|
|
| 15 |
"@mui/icons-material": "^9.0.0",
|
| 16 |
"@mui/material": "^9.0.0",
|
| 17 |
"@tiptap/core": "^3.22.3",
|
| 18 |
-
"@tiptap/extension-bubble-menu": "^3.22.3",
|
| 19 |
"@tiptap/extension-code-block-lowlight": "^3.22.3",
|
| 20 |
"@tiptap/extension-collaboration": "^3.22.3",
|
| 21 |
-
"@tiptap/extension-collaboration-cursor": "^2.26.2",
|
| 22 |
"@tiptap/extension-image": "^3.22.3",
|
| 23 |
"@tiptap/extension-link": "^3.22.3",
|
| 24 |
"@tiptap/extension-mathematics": "^3.22.3",
|
|
@@ -40,7 +39,6 @@
|
|
| 40 |
"react": "^18.3.0",
|
| 41 |
"react-dom": "^18.3.0",
|
| 42 |
"tippy.js": "^6.3.7",
|
| 43 |
-
"y-prosemirror": "^1.2.0",
|
| 44 |
"y-websocket": "^2.0.0",
|
| 45 |
"yjs": "^13.6.0",
|
| 46 |
"zod": "^4.3.6"
|
|
|
|
| 12 |
"@ai-sdk/react": "^3.0.160",
|
| 13 |
"@emotion/react": "^11.14.0",
|
| 14 |
"@emotion/styled": "^11.14.1",
|
| 15 |
+
"@floating-ui/dom": "^1.7.6",
|
| 16 |
"@mui/icons-material": "^9.0.0",
|
| 17 |
"@mui/material": "^9.0.0",
|
| 18 |
"@tiptap/core": "^3.22.3",
|
|
|
|
| 19 |
"@tiptap/extension-code-block-lowlight": "^3.22.3",
|
| 20 |
"@tiptap/extension-collaboration": "^3.22.3",
|
|
|
|
| 21 |
"@tiptap/extension-image": "^3.22.3",
|
| 22 |
"@tiptap/extension-link": "^3.22.3",
|
| 23 |
"@tiptap/extension-mathematics": "^3.22.3",
|
|
|
|
| 39 |
"react": "^18.3.0",
|
| 40 |
"react-dom": "^18.3.0",
|
| 41 |
"tippy.js": "^6.3.7",
|
|
|
|
| 42 |
"y-websocket": "^2.0.0",
|
| 43 |
"yjs": "^13.6.0",
|
| 44 |
"zod": "^4.3.6"
|
frontend/src/editor/BubbleToolbar.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
import { BubbleMenu } from "@tiptap/
|
| 2 |
import type { Editor } from "@tiptap/core";
|
| 3 |
import { Box, IconButton, Divider, Tooltip } from "@mui/material";
|
| 4 |
import FormatBoldIcon from "@mui/icons-material/FormatBold";
|
|
@@ -59,7 +59,7 @@ export function BubbleToolbar({ editor, onAddComment }: BubbleToolbarProps) {
|
|
| 59 |
return (
|
| 60 |
<BubbleMenu
|
| 61 |
editor={editor}
|
| 62 |
-
|
| 63 |
>
|
| 64 |
<Box
|
| 65 |
sx={{
|
|
|
|
| 1 |
+
import { BubbleMenu } from "@tiptap/react/menus";
|
| 2 |
import type { Editor } from "@tiptap/core";
|
| 3 |
import { Box, IconButton, Divider, Tooltip } from "@mui/material";
|
| 4 |
import FormatBoldIcon from "@mui/icons-material/FormatBold";
|
|
|
|
| 59 |
return (
|
| 60 |
<BubbleMenu
|
| 61 |
editor={editor}
|
| 62 |
+
options={{ placement: "top", offset: 6 }}
|
| 63 |
>
|
| 64 |
<Box
|
| 65 |
sx={{
|
frontend/src/editor/Editor.tsx
CHANGED
|
@@ -2,7 +2,7 @@ import { useEditor, EditorContent } from "@tiptap/react";
|
|
| 2 |
import { Editor as TiptapEditor } from "@tiptap/core";
|
| 3 |
import StarterKit from "@tiptap/starter-kit";
|
| 4 |
import Collaboration from "@tiptap/extension-collaboration";
|
| 5 |
-
import
|
| 6 |
import Placeholder from "@tiptap/extension-placeholder";
|
| 7 |
import CodeBlockLowlight from "@tiptap/extension-code-block-lowlight";
|
| 8 |
// Link is included in StarterKit v3, configured via StarterKit options
|
|
@@ -66,7 +66,6 @@ export function Editor({
|
|
| 66 |
onAddComment,
|
| 67 |
}: EditorProps) {
|
| 68 |
const ydoc = useMemo(() => new Y.Doc(), []);
|
| 69 |
-
const fragment = useMemo(() => ydoc.getXmlFragment("default"), [ydoc]);
|
| 70 |
const undoManagerCallbackRef = useRef(onUndoManagerReady);
|
| 71 |
undoManagerCallbackRef.current = onUndoManagerReady;
|
| 72 |
|
|
@@ -163,7 +162,7 @@ export function Editor({
|
|
| 163 |
Collaboration.configure({
|
| 164 |
document: ydoc,
|
| 165 |
}),
|
| 166 |
-
|
| 167 |
provider,
|
| 168 |
user,
|
| 169 |
}),
|
|
@@ -189,13 +188,12 @@ export function Editor({
|
|
| 189 |
...COMPONENTS.filter((d) => d.kind === "wrapper").map(createWrapperExtension),
|
| 190 |
...COMPONENTS.filter((d) => d.kind === "atomic").map(createAtomicExtension),
|
| 191 |
CollaborationUndo.configure({
|
| 192 |
-
fragment,
|
| 193 |
onUndoManagerReady: (um) => undoManagerCallbackRef.current?.(um),
|
| 194 |
}),
|
| 195 |
Comment,
|
| 196 |
],
|
| 197 |
},
|
| 198 |
-
[ydoc, provider
|
| 199 |
);
|
| 200 |
|
| 201 |
const seededRef = useRef(false);
|
|
|
|
| 2 |
import { Editor as TiptapEditor } from "@tiptap/core";
|
| 3 |
import StarterKit from "@tiptap/starter-kit";
|
| 4 |
import Collaboration from "@tiptap/extension-collaboration";
|
| 5 |
+
import { CollaborationCursorV3 } from "./extensions/collaboration-cursor-v3";
|
| 6 |
import Placeholder from "@tiptap/extension-placeholder";
|
| 7 |
import CodeBlockLowlight from "@tiptap/extension-code-block-lowlight";
|
| 8 |
// Link is included in StarterKit v3, configured via StarterKit options
|
|
|
|
| 66 |
onAddComment,
|
| 67 |
}: EditorProps) {
|
| 68 |
const ydoc = useMemo(() => new Y.Doc(), []);
|
|
|
|
| 69 |
const undoManagerCallbackRef = useRef(onUndoManagerReady);
|
| 70 |
undoManagerCallbackRef.current = onUndoManagerReady;
|
| 71 |
|
|
|
|
| 162 |
Collaboration.configure({
|
| 163 |
document: ydoc,
|
| 164 |
}),
|
| 165 |
+
CollaborationCursorV3.configure({
|
| 166 |
provider,
|
| 167 |
user,
|
| 168 |
}),
|
|
|
|
| 188 |
...COMPONENTS.filter((d) => d.kind === "wrapper").map(createWrapperExtension),
|
| 189 |
...COMPONENTS.filter((d) => d.kind === "atomic").map(createAtomicExtension),
|
| 190 |
CollaborationUndo.configure({
|
|
|
|
| 191 |
onUndoManagerReady: (um) => undoManagerCallbackRef.current?.(um),
|
| 192 |
}),
|
| 193 |
Comment,
|
| 194 |
],
|
| 195 |
},
|
| 196 |
+
[ydoc, provider],
|
| 197 |
);
|
| 198 |
|
| 199 |
const seededRef = useRef(false);
|
frontend/src/editor/extensions/collaboration-cursor-v3.ts
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { Extension } from "@tiptap/core";
|
| 2 |
+
import { yCursorPlugin, defaultCursorBuilder, defaultSelectionBuilder } from "@tiptap/y-tiptap";
|
| 3 |
+
|
| 4 |
+
export interface CollaborationCursorOptions {
|
| 5 |
+
provider: any;
|
| 6 |
+
user: { name: string; color: string };
|
| 7 |
+
render?: (user: { name: string; color: string }) => HTMLElement;
|
| 8 |
+
selectionRender?: typeof defaultSelectionBuilder;
|
| 9 |
+
}
|
| 10 |
+
|
| 11 |
+
const awarenessStatesToArray = (states: Map<number, any>) => {
|
| 12 |
+
return Array.from(states.entries()).map(([key, value]) => ({
|
| 13 |
+
clientId: key,
|
| 14 |
+
...value.user,
|
| 15 |
+
}));
|
| 16 |
+
};
|
| 17 |
+
|
| 18 |
+
export const CollaborationCursorV3 = Extension.create<CollaborationCursorOptions>({
|
| 19 |
+
name: "collaborationCursor",
|
| 20 |
+
priority: 999,
|
| 21 |
+
|
| 22 |
+
addOptions() {
|
| 23 |
+
return {
|
| 24 |
+
provider: null,
|
| 25 |
+
user: { name: "Anonymous", color: "#aaaaaa" },
|
| 26 |
+
render: (user: { name: string; color: string }) => {
|
| 27 |
+
const cursor = document.createElement("span");
|
| 28 |
+
cursor.classList.add("collaboration-cursor__caret");
|
| 29 |
+
cursor.setAttribute("style", `border-color: ${user.color}`);
|
| 30 |
+
const label = document.createElement("div");
|
| 31 |
+
label.classList.add("collaboration-cursor__label");
|
| 32 |
+
label.setAttribute("style", `background-color: ${user.color}`);
|
| 33 |
+
label.insertBefore(document.createTextNode(user.name), null);
|
| 34 |
+
cursor.insertBefore(label, null);
|
| 35 |
+
return cursor;
|
| 36 |
+
},
|
| 37 |
+
selectionRender: defaultSelectionBuilder,
|
| 38 |
+
};
|
| 39 |
+
},
|
| 40 |
+
|
| 41 |
+
addStorage() {
|
| 42 |
+
return { users: [] as any[] };
|
| 43 |
+
},
|
| 44 |
+
|
| 45 |
+
onCreate() {
|
| 46 |
+
if (!this.options.provider) {
|
| 47 |
+
throw new Error('The "provider" option is required for CollaborationCursorV3');
|
| 48 |
+
}
|
| 49 |
+
},
|
| 50 |
+
|
| 51 |
+
addCommands() {
|
| 52 |
+
return {
|
| 53 |
+
updateUser:
|
| 54 |
+
(attributes: Record<string, any>) =>
|
| 55 |
+
() => {
|
| 56 |
+
this.options.user = attributes as any;
|
| 57 |
+
this.options.provider.awareness.setLocalStateField("user", this.options.user);
|
| 58 |
+
return true;
|
| 59 |
+
},
|
| 60 |
+
};
|
| 61 |
+
},
|
| 62 |
+
|
| 63 |
+
addProseMirrorPlugins() {
|
| 64 |
+
this.options.provider.awareness.setLocalStateField("user", this.options.user);
|
| 65 |
+
this.storage.users = awarenessStatesToArray(this.options.provider.awareness.states);
|
| 66 |
+
this.options.provider.awareness.on("update", () => {
|
| 67 |
+
this.storage.users = awarenessStatesToArray(this.options.provider.awareness.states);
|
| 68 |
+
});
|
| 69 |
+
|
| 70 |
+
return [
|
| 71 |
+
yCursorPlugin(
|
| 72 |
+
this.options.provider.awareness,
|
| 73 |
+
{
|
| 74 |
+
cursorBuilder: this.options.render ?? defaultCursorBuilder,
|
| 75 |
+
selectionBuilder: this.options.selectionRender ?? defaultSelectionBuilder,
|
| 76 |
+
},
|
| 77 |
+
),
|
| 78 |
+
];
|
| 79 |
+
},
|
| 80 |
+
});
|
frontend/src/editor/extensions/collaboration-undo.ts
CHANGED
|
@@ -1,35 +1,22 @@
|
|
| 1 |
import { Extension } from "@tiptap/core";
|
| 2 |
import { UndoManager } from "yjs";
|
| 3 |
-
import
|
| 4 |
-
|
| 5 |
-
declare module "@tiptap/core" {
|
| 6 |
-
interface Commands<ReturnType> {
|
| 7 |
-
collaborationUndo: {
|
| 8 |
-
undo: () => ReturnType;
|
| 9 |
-
redo: () => ReturnType;
|
| 10 |
-
};
|
| 11 |
-
}
|
| 12 |
-
}
|
| 13 |
|
| 14 |
export interface CollaborationUndoOptions {
|
| 15 |
-
fragment: XmlFragment;
|
| 16 |
onUndoManagerReady?: (manager: UndoManager) => void;
|
| 17 |
}
|
| 18 |
|
| 19 |
/**
|
| 20 |
-
*
|
| 21 |
-
*
|
| 22 |
-
*
|
| 23 |
-
*
|
| 24 |
-
* before and after a batch of changes - everything between two
|
| 25 |
-
* stopCapturing() calls is merged into a single undo step.
|
| 26 |
*/
|
| 27 |
export const CollaborationUndo = Extension.create<CollaborationUndoOptions>({
|
| 28 |
-
name: "
|
| 29 |
|
| 30 |
addOptions() {
|
| 31 |
return {
|
| 32 |
-
fragment: null as unknown as XmlFragment,
|
| 33 |
onUndoManagerReady: undefined,
|
| 34 |
};
|
| 35 |
},
|
|
@@ -41,47 +28,11 @@ export const CollaborationUndo = Extension.create<CollaborationUndoOptions>({
|
|
| 41 |
},
|
| 42 |
|
| 43 |
onCreate() {
|
| 44 |
-
const
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
onDestroy() {
|
| 52 |
-
this.storage.undoManager?.destroy();
|
| 53 |
-
},
|
| 54 |
-
|
| 55 |
-
addCommands() {
|
| 56 |
-
return {
|
| 57 |
-
undo:
|
| 58 |
-
() =>
|
| 59 |
-
() => {
|
| 60 |
-
const um = this.storage.undoManager;
|
| 61 |
-
if (um && um.undoStack.length > 0) {
|
| 62 |
-
um.undo();
|
| 63 |
-
return true;
|
| 64 |
-
}
|
| 65 |
-
return false;
|
| 66 |
-
},
|
| 67 |
-
redo:
|
| 68 |
-
() =>
|
| 69 |
-
() => {
|
| 70 |
-
const um = this.storage.undoManager;
|
| 71 |
-
if (um && um.redoStack.length > 0) {
|
| 72 |
-
um.redo();
|
| 73 |
-
return true;
|
| 74 |
-
}
|
| 75 |
-
return false;
|
| 76 |
-
},
|
| 77 |
-
};
|
| 78 |
-
},
|
| 79 |
-
|
| 80 |
-
addKeyboardShortcuts() {
|
| 81 |
-
return {
|
| 82 |
-
"Mod-z": () => this.editor.commands.undo(),
|
| 83 |
-
"Mod-Shift-z": () => this.editor.commands.redo(),
|
| 84 |
-
"Mod-y": () => this.editor.commands.redo(),
|
| 85 |
-
};
|
| 86 |
},
|
| 87 |
});
|
|
|
|
| 1 |
import { Extension } from "@tiptap/core";
|
| 2 |
import { UndoManager } from "yjs";
|
| 3 |
+
import { yUndoPluginKey } from "@tiptap/y-tiptap";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
|
| 5 |
export interface CollaborationUndoOptions {
|
|
|
|
| 6 |
onUndoManagerReady?: (manager: UndoManager) => void;
|
| 7 |
}
|
| 8 |
|
| 9 |
/**
|
| 10 |
+
* Thin extension that exposes the UndoManager created by @tiptap/extension-collaboration v3.
|
| 11 |
+
* The actual undo/redo commands and shortcuts are handled by the Collaboration extension itself.
|
| 12 |
+
* This extension only reads the UndoManager from the yUndoPlugin state and
|
| 13 |
+
* exposes it via onUndoManagerReady for external consumers (e.g. agent chat batching).
|
|
|
|
|
|
|
| 14 |
*/
|
| 15 |
export const CollaborationUndo = Extension.create<CollaborationUndoOptions>({
|
| 16 |
+
name: "collaborationUndoBridge",
|
| 17 |
|
| 18 |
addOptions() {
|
| 19 |
return {
|
|
|
|
| 20 |
onUndoManagerReady: undefined,
|
| 21 |
};
|
| 22 |
},
|
|
|
|
| 28 |
},
|
| 29 |
|
| 30 |
onCreate() {
|
| 31 |
+
const state = this.editor.state;
|
| 32 |
+
const undoState = yUndoPluginKey.getState(state);
|
| 33 |
+
if (undoState?.undoManager) {
|
| 34 |
+
this.storage.undoManager = undoState.undoManager;
|
| 35 |
+
this.options.onUndoManagerReady?.(undoState.undoManager);
|
| 36 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
},
|
| 38 |
});
|